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