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