HalClient.java revision 0d07c76bbc788fba8c77d8e932330ab22ec6ba27
10d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev/*
20d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev * Copyright (C) 2016 The Android Open Source Project
30d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev *
40d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev * Licensed under the Apache License, Version 2.0 (the "License");
50d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev * you may not use this file except in compliance with the License.
60d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev * You may obtain a copy of the License at
70d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev *
80d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev *      http://www.apache.org/licenses/LICENSE-2.0
90d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev *
100d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev * Unless required by applicable law or agreed to in writing, software
110d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev * distributed under the License is distributed on an "AS IS" BASIS,
120d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
130d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev * See the License for the specific language governing permissions and
140d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev * limitations under the License.
150d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev */
160d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev
170d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsevpackage com.android.car.hal;
180d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev
190d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsevimport static android.os.SystemClock.elapsedRealtime;
200d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev
210d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsevimport android.hardware.vehicle.V2_0.IVehicle;
220d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsevimport android.hardware.vehicle.V2_0.IVehicle.getCallback;
230d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsevimport android.hardware.vehicle.V2_0.IVehicleCallback;
240d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsevimport android.hardware.vehicle.V2_0.StatusCode;
250d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsevimport android.hardware.vehicle.V2_0.SubscribeFlags;
260d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsevimport android.hardware.vehicle.V2_0.SubscribeOptions;
270d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsevimport android.hardware.vehicle.V2_0.VehiclePropConfig;
280d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsevimport android.hardware.vehicle.V2_0.VehiclePropValue;
290d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsevimport android.os.Handler;
300d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsevimport android.os.IHwBinder;
310d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsevimport android.os.Looper;
320d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsevimport android.os.Message;
330d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsevimport android.util.Log;
340d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev
350d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsevimport com.android.car.CarLog;
360d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev
370d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsevimport java.util.ArrayList;
380d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev
390d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev/**
400d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev * Vehicle HAL client. Interacts directly with Vehicle HAL interface {@link IVehicle}. Contains
410d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev * some logic for retriable properties, redirects Vehicle notifications into given looper thread.
420d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev */
430d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsevclass  HalClient {
440d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev    /**
450d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev     * If call to vehicle HAL returns StatusCode.TRY_AGAIN, than {@link HalClient} will retry to
460d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev     * invoke that method again for this amount of milliseconds.
470d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev     */
480d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev    private static final int WAIT_CAP_FOR_RETRIABLE_RESULT_MS = 2000;
490d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev
500d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev    private static final int SLEEP_BETWEEN_RETRIABLE_INVOKES_MS = 50;
510d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev
520d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev    private final IVehicle mVehicle;
530d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev
540d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev    private final IVehicleCallback mInternalCallback;
550d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev
560d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev    /**
570d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev     * Create HalClient object
580d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev     *
590d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev     * @param vehicle interface to the vehicle HAL
600d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev     * @param looper looper that will be used to propagate notifications from vehicle HAL
610d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev     * @param callback to propagate notifications from Vehicle HAL in the provided looper thread
620d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev     */
630d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev    HalClient(IVehicle vehicle, Looper looper, IVehicleCallback callback) {
640d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        mVehicle = vehicle;
650d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        Handler handler = new CallbackHandler(looper, callback);
660d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        mInternalCallback = new VehicleCallback(handler);
670d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev    }
680d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev
690d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev    ArrayList<VehiclePropConfig> getAllPropConfigs() {
700d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        return mVehicle.getAllPropConfigs();
710d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev    }
720d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev
730d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev    public void subscribe(int prop, float sampleRateHz) {
740d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        SubscribeOptions opt = new SubscribeOptions();
750d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        opt.propId = prop;
760d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        opt.sampleRate = sampleRateHz;
770d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        opt.flags = SubscribeFlags.HAL_EVENT;
780d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        ArrayList<SubscribeOptions> options = new ArrayList<>(1);
790d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        options.add(opt);
800d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        mVehicle.subscribe(mInternalCallback, options);
810d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev    }
820d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev
830d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev    public void unsubscribe(int prop) {
840d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        mVehicle.unsubscribe(mInternalCallback, prop);
850d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev    }
860d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev
870d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev    public void setValue(VehiclePropValue propValue) throws PropertyTimeoutException {
880d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        int status = invokeRetriable(() -> mVehicle.set(propValue),
890d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev                WAIT_CAP_FOR_RETRIABLE_RESULT_MS, SLEEP_BETWEEN_RETRIABLE_INVOKES_MS);
900d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev
910d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        if (StatusCode.INVALID_ARG == status) {
920d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev            throw new IllegalArgumentException(
930d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev                    String.format("Failed to set value for: 0x%x, areaId: 0x%x",
940d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev                            propValue.prop, propValue.areaId));
950d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        }
960d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev
970d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        if (StatusCode.TRY_AGAIN == status) {
980d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev            throw new PropertyTimeoutException(propValue.prop);
990d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        }
1000d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev
1010d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        if (StatusCode.OK != status) {
1020d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev            throw new IllegalStateException(
1030d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev                    String.format("Failed to set property: 0x%x, areaId: 0x%x, "
1040d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev                            + "code: %d", propValue.prop, propValue.areaId, status));
1050d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        }
1060d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev    }
1070d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev
1080d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev    VehiclePropValue getValue(VehiclePropValue requestedPropValue) throws PropertyTimeoutException {
1090d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        final ObjectWrapper<VehiclePropValue> valueWrapper = new ObjectWrapper<>();
1100d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        int status = invokeRetriable(() -> {
1110d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev            ValueResult res = internalGet(requestedPropValue);
1120d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev            valueWrapper.object = res.propValue;
1130d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev            return res.status;
1140d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        }, WAIT_CAP_FOR_RETRIABLE_RESULT_MS, SLEEP_BETWEEN_RETRIABLE_INVOKES_MS);
1150d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev
1160d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        int propId = requestedPropValue.prop;
1170d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        int areaId = requestedPropValue.areaId;
1180d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        if (StatusCode.INVALID_ARG == status) {
1190d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev            throw new IllegalArgumentException(
1200d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev                    String.format("Failed to get value for: 0x%x, areaId: 0x%x", propId, areaId));
1210d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        }
1220d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev
1230d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        if (StatusCode.TRY_AGAIN == status) {
1240d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev            throw new PropertyTimeoutException(propId);
1250d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        }
1260d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev
1270d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        if (StatusCode.OK != status || valueWrapper.object == null) {
1280d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev            throw new IllegalStateException(
1290d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev                    String.format("Failed to get property: 0x%x, areaId: 0x%x, "
1300d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev                            + "code: %d", propId, areaId, status));
1310d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        }
1320d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev
1330d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        return valueWrapper.object;
1340d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev    }
1350d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev
1360d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev    private ValueResult internalGet(VehiclePropValue requestedPropValue) {
1370d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        final ValueResult result = new ValueResult();
1380d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        mVehicle.get(requestedPropValue,
1390d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev                new getCallback() {
1400d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev                    @Override
1410d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev                    public void onValues(int status, VehiclePropValue propValue) {
1420d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev                        result.status = status;
1430d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev                        result.propValue = propValue;
1440d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev                    }
1450d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev                });
1460d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev
1470d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        return result;
1480d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev    }
1490d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev
1500d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev    interface RetriableCallback {
1510d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        /** Returns {@link StatusCode} */
1520d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        int action();
1530d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev    }
1540d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev
1550d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev    private static int invokeRetriable(RetriableCallback callback, long timeoutMs, long sleepMs) {
1560d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        int status = callback.action();
1570d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        long startTime = elapsedRealtime();
1580d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        while (StatusCode.TRY_AGAIN == status && (elapsedRealtime() - startTime) < timeoutMs) {
1590d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev            try {
1600d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev                Thread.sleep(sleepMs);
1610d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev            } catch (InterruptedException e) {
1620d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev                Log.e(CarLog.TAG_HAL, "Thread was interrupted while waiting for vehicle HAL.", e);
1630d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev                break;
1640d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev            }
1650d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev
1660d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev            status = callback.action();
1670d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        }
1680d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        return status;
1690d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev    }
1700d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev
1710d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev    private static class ObjectWrapper<T> {
1720d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        T object;
1730d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev    }
1740d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev
1750d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev    private static class ValueResult {
1760d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        int status;
1770d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        VehiclePropValue propValue;
1780d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev    }
1790d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev
1800d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev    private static class PropertySetError {
1810d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        final int errorCode;
1820d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        final int propId;
1830d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        final int areaId;
1840d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev
1850d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        PropertySetError(int errorCode, int propId, int areaId) {
1860d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev            this.errorCode = errorCode;
1870d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev            this.propId = propId;
1880d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev            this.areaId = areaId;
1890d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        }
1900d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev    }
1910d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev
1920d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev    private static class CallbackHandler extends Handler {
1930d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        private static final int MSG_ON_PROPERTY_SET = 1;
1940d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        private static final int MSG_ON_PROPERTY_EVENT = 2;
1950d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        private static final int MSG_ON_SET_ERROR = 3;
1960d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev
1970d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        private final IVehicleCallback mCallback;
1980d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev
1990d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        CallbackHandler(Looper looper, IVehicleCallback callback) {
2000d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev            super(looper);
2010d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev            mCallback = callback;
2020d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        }
2030d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev
2040d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        @Override
2050d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        public void handleMessage(Message msg) {
2060d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev            super.handleMessage(msg);
2070d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev
2080d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev            switch (msg.what) {
2090d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev                case MSG_ON_PROPERTY_EVENT:
2100d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev                    mCallback.onPropertyEvent((ArrayList<VehiclePropValue>) msg.obj);
2110d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev                    break;
2120d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev                case MSG_ON_PROPERTY_SET:
2130d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev                    mCallback.onPropertySet((VehiclePropValue) msg.obj);
2140d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev                    break;
2150d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev                case MSG_ON_SET_ERROR:
2160d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev                    PropertySetError obj = (PropertySetError) msg.obj;
2170d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev                    mCallback.onPropertySetError(obj.errorCode, obj.propId, obj.areaId);
2180d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev                    break;
2190d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev                default:
2200d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev                        Log.e(CarLog.TAG_HAL, "Unexpected message: " + msg.what);
2210d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev            }
2220d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        }
2230d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev    }
2240d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev
2250d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev    private static class VehicleCallback implements IVehicleCallback {
2260d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        private Handler mHandler;
2270d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev
2280d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        VehicleCallback(Handler handler) {
2290d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev            mHandler = handler;
2300d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        }
2310d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev
2320d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        @Override
2330d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        public IHwBinder asBinder() {
2340d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev            return null;
2350d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        }
2360d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev
2370d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        @Override
2380d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        public void onPropertyEvent(ArrayList<VehiclePropValue> propValues) {
2390d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev            mHandler.sendMessage(Message.obtain(
2400d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev                    mHandler, CallbackHandler.MSG_ON_PROPERTY_EVENT, propValues));
2410d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        }
2420d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev
2430d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        @Override
2440d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        public void onPropertySet(VehiclePropValue propValue) {
2450d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev            mHandler.sendMessage(Message.obtain(
2460d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev                    mHandler, CallbackHandler.MSG_ON_PROPERTY_SET, propValue));
2470d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        }
2480d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev
2490d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        @Override
2500d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        public void onPropertySetError(int errorCode, int propId, int areaId) {
2510d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev            mHandler.sendMessage(Message.obtain(
2520d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev                    mHandler, CallbackHandler.MSG_ON_SET_ERROR,
2530d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev                    new PropertySetError(errorCode, propId, areaId)));
2540d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        }
2550d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev
2560d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        @Override
2570d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        public ArrayList<String> interfaceChain() {
2580d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev            return null;
2590d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        }
2600d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev    }
2610d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev}
262