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
21cfe93105f637c2822da113308f113ed418d0b319Pavel Maltsevimport android.hardware.automotive.vehicle.V2_0.IVehicle;
22cfe93105f637c2822da113308f113ed418d0b319Pavel Maltsevimport android.hardware.automotive.vehicle.V2_0.IVehicleCallback;
23cfe93105f637c2822da113308f113ed418d0b319Pavel Maltsevimport android.hardware.automotive.vehicle.V2_0.StatusCode;
24cfe93105f637c2822da113308f113ed418d0b319Pavel Maltsevimport android.hardware.automotive.vehicle.V2_0.SubscribeOptions;
25cfe93105f637c2822da113308f113ed418d0b319Pavel Maltsevimport android.hardware.automotive.vehicle.V2_0.VehiclePropConfig;
26cfe93105f637c2822da113308f113ed418d0b319Pavel Maltsevimport android.hardware.automotive.vehicle.V2_0.VehiclePropValue;
270d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsevimport android.os.Handler;
280d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsevimport android.os.Looper;
290d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsevimport android.os.Message;
30aef08383ef08533a411e328507b376f097143fd0Steven Morelandimport android.os.RemoteException;
310d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsevimport android.util.Log;
320d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev
330d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsevimport com.android.car.CarLog;
340d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev
350d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsevimport java.util.ArrayList;
3679d5e12ad8708c1f7f7f1a60aaeb349ac7ed0f7bPavel Maltsevimport java.util.Arrays;
370d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev
380d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev/**
390d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev * Vehicle HAL client. Interacts directly with Vehicle HAL interface {@link IVehicle}. Contains
400d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev * some logic for retriable properties, redirects Vehicle notifications into given looper thread.
410d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev */
420d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsevclass  HalClient {
430d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev    /**
440d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev     * If call to vehicle HAL returns StatusCode.TRY_AGAIN, than {@link HalClient} will retry to
450d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev     * invoke that method again for this amount of milliseconds.
460d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev     */
470d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev    private static final int WAIT_CAP_FOR_RETRIABLE_RESULT_MS = 2000;
480d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev
490d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev    private static final int SLEEP_BETWEEN_RETRIABLE_INVOKES_MS = 50;
500d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev
510d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev    private final IVehicle mVehicle;
520d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev
530d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev    private final IVehicleCallback mInternalCallback;
540d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev
550d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev    /**
560d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev     * Create HalClient object
570d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev     *
580d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev     * @param vehicle interface to the vehicle HAL
590d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev     * @param looper looper that will be used to propagate notifications from vehicle HAL
600d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev     * @param callback to propagate notifications from Vehicle HAL in the provided looper thread
610d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev     */
620d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev    HalClient(IVehicle vehicle, Looper looper, IVehicleCallback callback) {
630d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        mVehicle = vehicle;
640d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        Handler handler = new CallbackHandler(looper, callback);
650d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        mInternalCallback = new VehicleCallback(handler);
660d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev    }
670d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev
68aef08383ef08533a411e328507b376f097143fd0Steven Moreland    ArrayList<VehiclePropConfig> getAllPropConfigs() throws RemoteException {
690d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        return mVehicle.getAllPropConfigs();
700d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev    }
710d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev
7279d5e12ad8708c1f7f7f1a60aaeb349ac7ed0f7bPavel Maltsev    public void subscribe(SubscribeOptions... options) throws RemoteException {
7379d5e12ad8708c1f7f7f1a60aaeb349ac7ed0f7bPavel Maltsev        mVehicle.subscribe(mInternalCallback, new ArrayList<>(Arrays.asList(options)));
740d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev    }
750d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev
76aef08383ef08533a411e328507b376f097143fd0Steven Moreland    public void unsubscribe(int prop) throws RemoteException {
770d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        mVehicle.unsubscribe(mInternalCallback, prop);
780d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev    }
790d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev
80ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsev    public void setValue(VehiclePropValue propValue) throws PropertyTimeoutException {
81ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsev        int status = invokeRetriable(() -> {
82ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsev            try {
83ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsev                return mVehicle.set(propValue);
84ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsev            } catch (RemoteException e) {
85ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsev                Log.e(CarLog.TAG_HAL, "Failed to set value", e);
86ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsev                return StatusCode.TRY_AGAIN;
87ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsev            }
88ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsev        }, WAIT_CAP_FOR_RETRIABLE_RESULT_MS, SLEEP_BETWEEN_RETRIABLE_INVOKES_MS);
890d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev
900d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        if (StatusCode.INVALID_ARG == status) {
910d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev            throw new IllegalArgumentException(
920d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev                    String.format("Failed to set value for: 0x%x, areaId: 0x%x",
930d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev                            propValue.prop, propValue.areaId));
940d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        }
950d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev
960d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        if (StatusCode.TRY_AGAIN == status) {
970d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev            throw new PropertyTimeoutException(propValue.prop);
980d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        }
990d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev
1000d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        if (StatusCode.OK != status) {
1010d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev            throw new IllegalStateException(
1020d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev                    String.format("Failed to set property: 0x%x, areaId: 0x%x, "
1030d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev                            + "code: %d", propValue.prop, propValue.areaId, status));
1040d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        }
1050d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev    }
1060d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev
107ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsev    VehiclePropValue getValue(VehiclePropValue requestedPropValue) throws PropertyTimeoutException {
1080d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        final ObjectWrapper<VehiclePropValue> valueWrapper = new ObjectWrapper<>();
1090d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        int status = invokeRetriable(() -> {
1100d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev            ValueResult res = internalGet(requestedPropValue);
1110d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev            valueWrapper.object = res.propValue;
1120d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev            return res.status;
1130d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        }, WAIT_CAP_FOR_RETRIABLE_RESULT_MS, SLEEP_BETWEEN_RETRIABLE_INVOKES_MS);
1140d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev
1150d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        int propId = requestedPropValue.prop;
1160d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        int areaId = requestedPropValue.areaId;
1170d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        if (StatusCode.INVALID_ARG == status) {
1180d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev            throw new IllegalArgumentException(
1190d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev                    String.format("Failed to get value for: 0x%x, areaId: 0x%x", propId, areaId));
1200d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        }
1210d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev
1220d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        if (StatusCode.TRY_AGAIN == status) {
1230d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev            throw new PropertyTimeoutException(propId);
1240d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        }
1250d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev
1260d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        if (StatusCode.OK != status || valueWrapper.object == null) {
1270d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev            throw new IllegalStateException(
1280d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev                    String.format("Failed to get property: 0x%x, areaId: 0x%x, "
1290d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev                            + "code: %d", propId, areaId, status));
1300d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        }
1310d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev
1320d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        return valueWrapper.object;
1330d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev    }
1340d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev
135ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsev    private ValueResult internalGet(VehiclePropValue requestedPropValue) {
1360d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        final ValueResult result = new ValueResult();
137ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsev        try {
138ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsev            mVehicle.get(requestedPropValue,
139ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsev                    (status, propValue) -> {
1400d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev                        result.status = status;
1410d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev                        result.propValue = propValue;
142ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsev                    });
143ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsev        } catch (RemoteException e) {
144ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsev            Log.e(CarLog.TAG_HAL, "Failed to get value from vehicle HAL", e);
145ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsev            result.status = StatusCode.TRY_AGAIN;
146ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsev        }
1470d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev
1480d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        return result;
1490d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev    }
1500d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev
1510d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev    interface RetriableCallback {
1520d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        /** Returns {@link StatusCode} */
153ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsev        int action();
1540d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev    }
1550d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev
156ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsev    private static int invokeRetriable(RetriableCallback callback, long timeoutMs, long sleepMs) {
1570d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        int status = callback.action();
1580d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        long startTime = elapsedRealtime();
1590d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        while (StatusCode.TRY_AGAIN == status && (elapsedRealtime() - startTime) < timeoutMs) {
1600d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev            try {
1610d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev                Thread.sleep(sleepMs);
1620d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev            } catch (InterruptedException e) {
1630d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev                Log.e(CarLog.TAG_HAL, "Thread was interrupted while waiting for vehicle HAL.", e);
1640d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev                break;
1650d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev            }
1660d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev
1670d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev            status = callback.action();
1680d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        }
1690d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        return status;
1700d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev    }
1710d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev
1720d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev    private static class ObjectWrapper<T> {
1730d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        T object;
1740d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev    }
1750d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev
1760d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev    private static class ValueResult {
1770d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        int status;
1780d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        VehiclePropValue propValue;
1790d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev    }
1800d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev
1810d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev    private static class PropertySetError {
1820d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        final int errorCode;
1830d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        final int propId;
1840d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        final int areaId;
1850d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev
1860d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        PropertySetError(int errorCode, int propId, int areaId) {
1870d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev            this.errorCode = errorCode;
1880d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev            this.propId = propId;
1890d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev            this.areaId = areaId;
1900d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        }
1910d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev    }
1920d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev
1930d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev    private static class CallbackHandler extends Handler {
1940d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        private static final int MSG_ON_PROPERTY_SET = 1;
1950d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        private static final int MSG_ON_PROPERTY_EVENT = 2;
1960d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        private static final int MSG_ON_SET_ERROR = 3;
1970d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev
1980d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        private final IVehicleCallback mCallback;
1990d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev
2000d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        CallbackHandler(Looper looper, IVehicleCallback callback) {
2010d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev            super(looper);
2020d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev            mCallback = callback;
2030d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        }
2040d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev
2050d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        @Override
2060d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        public void handleMessage(Message msg) {
2070d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev            super.handleMessage(msg);
2080d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev
209aef08383ef08533a411e328507b376f097143fd0Steven Moreland            try {
210aef08383ef08533a411e328507b376f097143fd0Steven Moreland                switch (msg.what) {
211aef08383ef08533a411e328507b376f097143fd0Steven Moreland                    case MSG_ON_PROPERTY_EVENT:
212aef08383ef08533a411e328507b376f097143fd0Steven Moreland                        mCallback.onPropertyEvent((ArrayList<VehiclePropValue>) msg.obj);
213aef08383ef08533a411e328507b376f097143fd0Steven Moreland                        break;
214aef08383ef08533a411e328507b376f097143fd0Steven Moreland                    case MSG_ON_PROPERTY_SET:
215aef08383ef08533a411e328507b376f097143fd0Steven Moreland                        mCallback.onPropertySet((VehiclePropValue) msg.obj);
216aef08383ef08533a411e328507b376f097143fd0Steven Moreland                        break;
217aef08383ef08533a411e328507b376f097143fd0Steven Moreland                    case MSG_ON_SET_ERROR:
218aef08383ef08533a411e328507b376f097143fd0Steven Moreland                        PropertySetError obj = (PropertySetError) msg.obj;
219aef08383ef08533a411e328507b376f097143fd0Steven Moreland                        mCallback.onPropertySetError(obj.errorCode, obj.propId, obj.areaId);
220aef08383ef08533a411e328507b376f097143fd0Steven Moreland                        break;
221aef08383ef08533a411e328507b376f097143fd0Steven Moreland                    default:
2220d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev                        Log.e(CarLog.TAG_HAL, "Unexpected message: " + msg.what);
223aef08383ef08533a411e328507b376f097143fd0Steven Moreland                }
224aef08383ef08533a411e328507b376f097143fd0Steven Moreland            } catch (RemoteException e) {
225aef08383ef08533a411e328507b376f097143fd0Steven Moreland                Log.e(CarLog.TAG_HAL, "Message failed: " + msg.what);
2260d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev            }
2270d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        }
2280d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev    }
2290d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev
230ee412315d30eb1b8a0e8a4ea232f78ecc53b7486Martijn Coenen    private static class VehicleCallback extends IVehicleCallback.Stub {
2310d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        private Handler mHandler;
2320d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev
2330d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        VehicleCallback(Handler handler) {
2340d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev            mHandler = handler;
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}
257