blob: 182583d2968194c452934bec43aa6452c25d0b76 [file] [log] [blame]
keunyoungcc449f72015-08-12 10:46:27 -07001/*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.car.hal;
18
Pavel Maltsev0d07c762016-11-03 16:40:15 -070019import static com.android.car.CarServiceUtils.toByteArray;
20import static com.android.car.CarServiceUtils.toFloatArray;
21import static com.android.car.CarServiceUtils.toIntArray;
22import static java.lang.Integer.toHexString;
23
24import android.annotation.CheckResult;
25import android.hardware.vehicle.V2_0.IVehicle;
26import android.hardware.vehicle.V2_0.IVehicleCallback;
27import android.hardware.vehicle.V2_0.VehicleAreaConfig;
28import android.hardware.vehicle.V2_0.VehiclePropConfig;
29import android.hardware.vehicle.V2_0.VehiclePropValue;
30import android.hardware.vehicle.V2_0.VehiclePropertyAccess;
31import android.hardware.vehicle.V2_0.VehiclePropertyChangeMode;
keunyoungcc449f72015-08-12 10:46:27 -070032import android.os.HandlerThread;
Keun-young Park97e46eb2016-04-09 15:02:38 -070033import android.os.SystemClock;
keunyoungfe30ba02015-09-17 17:56:35 -070034import android.util.ArraySet;
keunyoungcc449f72015-08-12 10:46:27 -070035import android.util.Log;
36import android.util.SparseArray;
37
38import com.android.car.CarLog;
Keun-young Parkfd3fbf72016-01-22 17:00:17 -080039import com.android.internal.annotations.VisibleForTesting;
keunyoungcc449f72015-08-12 10:46:27 -070040
41import java.io.PrintWriter;
Pavel Maltsev0d07c762016-11-03 16:40:15 -070042import java.lang.ref.WeakReference;
Steve Paik4d6088c2016-07-20 20:27:55 -070043import java.util.ArrayList;
Pavel Maltsev0d07c762016-11-03 16:40:15 -070044import java.util.Arrays;
keunyounga74b9ca2015-10-21 13:33:58 -070045import java.util.Collection;
keunyounge4c90c42015-11-16 18:42:52 -080046import java.util.HashMap;
Pavel Maltsev0d07c762016-11-03 16:40:15 -070047import java.util.HashSet;
keunyoungcc449f72015-08-12 10:46:27 -070048import java.util.List;
Pavel Maltsev0d07c762016-11-03 16:40:15 -070049import java.util.Set;
keunyoungcc449f72015-08-12 10:46:27 -070050
51/**
52 * Abstraction for vehicle HAL. This class handles interface with native HAL and do basic parsing
53 * of received data (type check). Then each event is sent to corresponding {@link HalServiceBase}
54 * implementation. It is responsibility of {@link HalServiceBase} to convert data to corresponding
55 * Car*Service for Car*Manager API.
56 */
Pavel Maltsev0d07c762016-11-03 16:40:15 -070057public class VehicleHal extends IVehicleCallback.Stub {
keunyoungcc449f72015-08-12 10:46:27 -070058
Vitalii Tomkiv1b1247b2016-09-30 11:27:19 -070059 private static final boolean DBG = false;
keunyoungcc449f72015-08-12 10:46:27 -070060
Pavel Maltsev0d07c762016-11-03 16:40:15 -070061 private static final int NO_AREA = -1;
keunyoungcc449f72015-08-12 10:46:27 -070062
keunyounge4c90c42015-11-16 18:42:52 -080063 private final HandlerThread mHandlerThread;
keunyoungcc449f72015-08-12 10:46:27 -070064 private final SensorHalService mSensorHal;
keunyounga3b28d82015-08-25 13:05:15 -070065 private final InfoHalService mInfoHal;
keunyoungd32f4e62015-09-21 11:33:06 -070066 private final AudioHalService mAudioHal;
Steve Paik43c04a72016-07-08 19:12:09 -070067 private final CabinHalService mCabinHal;
Sanket Agarwal3cf096a2015-10-13 14:46:31 -070068 private final RadioHalService mRadioHal;
keunyoung4b0212c2015-10-29 17:11:57 -070069 private final PowerHalService mPowerHal;
Steve Paik66481982015-10-27 15:22:38 -070070 private final HvacHalService mHvacHal;
Keun-young Parka28d7b22016-02-29 16:54:29 -080071 private final InputHalService mInputHal;
Pavel Maltsev634e1ff2016-07-14 15:41:26 -070072 private final VendorExtensionHalService mVendorExtensionHal;
Pavel Maltsev0d07c762016-11-03 16:40:15 -070073 private final HalClient mHalClient;
keunyoungcc449f72015-08-12 10:46:27 -070074
75 /** stores handler for each HAL property. Property events are sent to handler. */
Pavel Maltsev0d07c762016-11-03 16:40:15 -070076 private final SparseArray<HalServiceBase> mPropertyHandlers = new SparseArray<>();
keunyoungcc449f72015-08-12 10:46:27 -070077 /** This is for iterating all HalServices with fixed order. */
78 private final HalServiceBase[] mAllServices;
Pavel Maltsev0d07c762016-11-03 16:40:15 -070079 private final ArraySet<Integer> mSubscribedProperties = new ArraySet<>();
Steve Paik4d6088c2016-07-20 20:27:55 -070080 private final HashMap<Integer, VehiclePropConfig> mAllProperties = new HashMap<>();
Keun-young Park97e46eb2016-04-09 15:02:38 -070081 private final HashMap<Integer, VehiclePropertyEventInfo> mEventLog = new HashMap<>();
82
Pavel Maltsev0d07c762016-11-03 16:40:15 -070083 public VehicleHal(IVehicle vehicle) {
keunyounge4c90c42015-11-16 18:42:52 -080084 mHandlerThread = new HandlerThread("VEHICLE-HAL");
keunyoungcc449f72015-08-12 10:46:27 -070085 mHandlerThread.start();
keunyoungcc449f72015-08-12 10:46:27 -070086 // passing this should be safe as long as it is just kept and not used in constructor
keunyoung4b0212c2015-10-29 17:11:57 -070087 mPowerHal = new PowerHalService(this);
keunyoungcc449f72015-08-12 10:46:27 -070088 mSensorHal = new SensorHalService(this);
keunyounga3b28d82015-08-25 13:05:15 -070089 mInfoHal = new InfoHalService(this);
keunyoungd32f4e62015-09-21 11:33:06 -070090 mAudioHal = new AudioHalService(this);
Steve Paik43c04a72016-07-08 19:12:09 -070091 mCabinHal = new CabinHalService(this);
Sanket Agarwal3cf096a2015-10-13 14:46:31 -070092 mRadioHal = new RadioHalService(this);
Steve Paik66481982015-10-27 15:22:38 -070093 mHvacHal = new HvacHalService(this);
Pavel Maltsev0d07c762016-11-03 16:40:15 -070094 mInputHal = new InputHalService(this);
Pavel Maltsev634e1ff2016-07-14 15:41:26 -070095 mVendorExtensionHal = new VendorExtensionHalService(this);
keunyounga3b28d82015-08-25 13:05:15 -070096 mAllServices = new HalServiceBase[] {
keunyoung4b0212c2015-10-29 17:11:57 -070097 mPowerHal,
keunyoungd32f4e62015-09-21 11:33:06 -070098 mAudioHal,
Steve Paik43c04a72016-07-08 19:12:09 -070099 mCabinHal,
Steve Paik66481982015-10-27 15:22:38 -0700100 mHvacHal,
keunyounga3b28d82015-08-25 13:05:15 -0700101 mInfoHal,
Sanket Agarwal3cf096a2015-10-13 14:46:31 -0700102 mSensorHal,
Keun-young Parka28d7b22016-02-29 16:54:29 -0800103 mRadioHal,
Pavel Maltsev634e1ff2016-07-14 15:41:26 -0700104 mInputHal,
105 mVendorExtensionHal
Keun-young Parka28d7b22016-02-29 16:54:29 -0800106 };
Pavel Maltsev0d07c762016-11-03 16:40:15 -0700107
108 mHalClient = new HalClient(vehicle, mHandlerThread.getLooper(), this /*IVehicleCallback*/);
keunyoungcc449f72015-08-12 10:46:27 -0700109 }
110
Keun-young Parkfd3fbf72016-01-22 17:00:17 -0800111 /** Dummy version only for testing */
112 @VisibleForTesting
113 public VehicleHal(PowerHalService powerHal, SensorHalService sensorHal, InfoHalService infoHal,
Steve Paik43c04a72016-07-08 19:12:09 -0700114 AudioHalService audioHal, CabinHalService cabinHal, RadioHalService radioHal,
Pavel Maltsev0d07c762016-11-03 16:40:15 -0700115 HvacHalService hvacHal, HalClient halClient) {
Keun-young Parkfd3fbf72016-01-22 17:00:17 -0800116 mHandlerThread = null;
117 mPowerHal = powerHal;
118 mSensorHal = sensorHal;
119 mInfoHal = infoHal;
120 mAudioHal = audioHal;
Steve Paik43c04a72016-07-08 19:12:09 -0700121 mCabinHal = cabinHal;
Keun-young Parkfd3fbf72016-01-22 17:00:17 -0800122 mRadioHal = radioHal;
123 mHvacHal = hvacHal;
Keun-young Parka28d7b22016-02-29 16:54:29 -0800124 mInputHal = null;
Pavel Maltsev634e1ff2016-07-14 15:41:26 -0700125 mVendorExtensionHal = null;
Keun-young Parkfd3fbf72016-01-22 17:00:17 -0800126 mAllServices = null;
Pavel Maltsev0d07c762016-11-03 16:40:15 -0700127 mHalClient = halClient;
Keun-young Parkfd3fbf72016-01-22 17:00:17 -0800128 }
129
Keun-young Park021310d2016-04-25 21:09:39 -0700130 public void init() {
Pavel Maltsev0d07c762016-11-03 16:40:15 -0700131 Set<VehiclePropConfig> properties = new HashSet<>(mHalClient.getAllPropConfigs());
Steve Paik4d6088c2016-07-20 20:27:55 -0700132
133 synchronized (this) {
134 // Create map of all properties
Pavel Maltsev0d07c762016-11-03 16:40:15 -0700135 for (VehiclePropConfig p : properties) {
136 mAllProperties.put(p.prop, p);
Steve Paik4d6088c2016-07-20 20:27:55 -0700137 }
138 }
139
keunyoungcc449f72015-08-12 10:46:27 -0700140 for (HalServiceBase service: mAllServices) {
Pavel Maltsev0d07c762016-11-03 16:40:15 -0700141 Collection<VehiclePropConfig> taken = service.takeSupportedProperties(properties);
keunyounga3b28d82015-08-25 13:05:15 -0700142 if (taken == null) {
143 continue;
144 }
keunyoungcc449f72015-08-12 10:46:27 -0700145 if (DBG) {
146 Log.i(CarLog.TAG_HAL, "HalService " + service + " take properties " + taken.size());
147 }
keunyounge4c90c42015-11-16 18:42:52 -0800148 synchronized (this) {
149 for (VehiclePropConfig p: taken) {
Pavel Maltsev0d07c762016-11-03 16:40:15 -0700150 mPropertyHandlers.append(p.prop, service);
keunyounge4c90c42015-11-16 18:42:52 -0800151 }
keunyoungcc449f72015-08-12 10:46:27 -0700152 }
Pavel Maltsev0d07c762016-11-03 16:40:15 -0700153 properties.removeAll(taken);
keunyoungcc449f72015-08-12 10:46:27 -0700154 service.init();
155 }
156 }
157
Keun-young Park021310d2016-04-25 21:09:39 -0700158 public void release() {
keunyoungcc449f72015-08-12 10:46:27 -0700159 // release in reverse order from init
160 for (int i = mAllServices.length - 1; i >= 0; i--) {
161 mAllServices[i].release();
162 }
keunyounge4c90c42015-11-16 18:42:52 -0800163 synchronized (this) {
164 for (int p : mSubscribedProperties) {
Pavel Maltsev0d07c762016-11-03 16:40:15 -0700165 mHalClient.unsubscribe(p);
keunyounge4c90c42015-11-16 18:42:52 -0800166 }
167 mSubscribedProperties.clear();
Keun-young Park450faba2016-02-10 18:15:12 -0800168 mAllProperties.clear();
keunyoungfe30ba02015-09-17 17:56:35 -0700169 }
keunyoungfe30ba02015-09-17 17:56:35 -0700170 // keep the looper thread as should be kept for the whole life cycle.
keunyoungcc449f72015-08-12 10:46:27 -0700171 }
172
173 public SensorHalService getSensorHal() {
174 return mSensorHal;
175 }
176
keunyounga3b28d82015-08-25 13:05:15 -0700177 public InfoHalService getInfoHal() {
178 return mInfoHal;
179 }
180
keunyoungd32f4e62015-09-21 11:33:06 -0700181 public AudioHalService getAudioHal() {
182 return mAudioHal;
183 }
184
Steve Paik43c04a72016-07-08 19:12:09 -0700185 public CabinHalService getCabinHal() {
186 return mCabinHal;
187 }
188
Sanket Agarwal3cf096a2015-10-13 14:46:31 -0700189 public RadioHalService getRadioHal() {
190 return mRadioHal;
191 }
192
keunyoung4b0212c2015-10-29 17:11:57 -0700193 public PowerHalService getPowerHal() {
194 return mPowerHal;
195 }
196
Steve Paik66481982015-10-27 15:22:38 -0700197 public HvacHalService getHvacHal() {
198 return mHvacHal;
199 }
200
Keun-young Parka28d7b22016-02-29 16:54:29 -0800201 public InputHalService getInputHal() {
202 return mInputHal;
203 }
204
Pavel Maltsev634e1ff2016-07-14 15:41:26 -0700205 public VendorExtensionHalService getVendorExtensionHal() {
206 return mVendorExtensionHal;
207 }
208
keunyounge4c90c42015-11-16 18:42:52 -0800209 private void assertServiceOwnerLocked(HalServiceBase service, int property) {
keunyoungd32f4e62015-09-21 11:33:06 -0700210 if (service != mPropertyHandlers.get(property)) {
Pavel Maltsev0d07c762016-11-03 16:40:15 -0700211 throw new IllegalArgumentException("Property 0x" + toHexString(property)
Pavel Maltsev1bfbaef2016-07-25 14:23:51 -0700212 + " is not owned by service: " + service);
keunyoungfe30ba02015-09-17 17:56:35 -0700213 }
keunyoungcc449f72015-08-12 10:46:27 -0700214 }
215
keunyoungfe30ba02015-09-17 17:56:35 -0700216 /**
217 * Subscribe given property. Only Hal service owning the property can subscribe it.
keunyoungfe30ba02015-09-17 17:56:35 -0700218 */
keunyoungd32f4e62015-09-21 11:33:06 -0700219 public void subscribeProperty(HalServiceBase service, int property,
keunyoungfe30ba02015-09-17 17:56:35 -0700220 float samplingRateHz) throws IllegalArgumentException {
Pavel Maltsev0d07c762016-11-03 16:40:15 -0700221 if (DBG) {
222 Log.i(CarLog.TAG_HAL, "subscribeProperty, service:" + service
223 + ", property: 0x" + toHexString(property));
224 }
Steve Paik4d6088c2016-07-20 20:27:55 -0700225 VehiclePropConfig config;
keunyounge4c90c42015-11-16 18:42:52 -0800226 synchronized (this) {
Steve Paik4d6088c2016-07-20 20:27:55 -0700227 config = mAllProperties.get(property);
keunyounge4c90c42015-11-16 18:42:52 -0800228 }
Steve Paik4d6088c2016-07-20 20:27:55 -0700229
230 if (config == null) {
231 throw new IllegalArgumentException("subscribe error: config is null for property " +
232 property);
233 } else if (isPropertySubscribable(config)) {
234 synchronized (this) {
235 assertServiceOwnerLocked(service, property);
236 mSubscribedProperties.add(property);
237 }
Pavel Maltsev0d07c762016-11-03 16:40:15 -0700238 mHalClient.subscribe(property, samplingRateHz);
Steve Paik4d6088c2016-07-20 20:27:55 -0700239 } else {
240 Log.e(CarLog.TAG_HAL, "Cannot subscribe to property: " + property);
241 }
keunyounga3b28d82015-08-25 13:05:15 -0700242 }
243
keunyoungd32f4e62015-09-21 11:33:06 -0700244 public void unsubscribeProperty(HalServiceBase service, int property) {
Pavel Maltsev0d07c762016-11-03 16:40:15 -0700245 if (DBG) {
246 Log.i(CarLog.TAG_HAL, "unsubscribeProperty, service:" + service
247 + ", property: 0x" + toHexString(property));
248 }
Steve Paik4d6088c2016-07-20 20:27:55 -0700249 VehiclePropConfig config;
keunyounge4c90c42015-11-16 18:42:52 -0800250 synchronized (this) {
Steve Paik4d6088c2016-07-20 20:27:55 -0700251 config = mAllProperties.get(property);
keunyounge4c90c42015-11-16 18:42:52 -0800252 }
Steve Paik4d6088c2016-07-20 20:27:55 -0700253
254 if (config == null) {
255 Log.e(CarLog.TAG_HAL, "unsubscribeProperty: property " + property + " does not exist");
256 } else if (isPropertySubscribable(config)) {
257 synchronized (this) {
258 assertServiceOwnerLocked(service, property);
259 mSubscribedProperties.remove(property);
260 }
Pavel Maltsev0d07c762016-11-03 16:40:15 -0700261 mHalClient.unsubscribe(property);
Steve Paik4d6088c2016-07-20 20:27:55 -0700262 } else {
263 Log.e(CarLog.TAG_HAL, "Cannot unsubscribe property: " + property);
264 }
keunyounga3b28d82015-08-25 13:05:15 -0700265 }
266
Pavel Maltsev0d07c762016-11-03 16:40:15 -0700267 public boolean isPropertySupported(int propertyId) {
268 return mAllProperties.containsKey(propertyId);
keunyoungcc449f72015-08-12 10:46:27 -0700269 }
270
Pavel Maltsev0d07c762016-11-03 16:40:15 -0700271 public Collection<VehiclePropConfig> getAllPropConfigs() {
272 return mAllProperties.values();
273 }
274
275 public VehiclePropValue get(int propertyId) throws PropertyTimeoutException {
276 return get(propertyId, NO_AREA);
277 }
278
279 public VehiclePropValue get(int propertyId, int areaId) throws PropertyTimeoutException {
280 Log.i(CarLog.TAG_HAL, "get, property: 0x" + toHexString(propertyId)
281 + ", areaId: 0x" + toHexString(areaId));
282 VehiclePropValue propValue = new VehiclePropValue();
283 propValue.prop = propertyId;
284 propValue.areaId = areaId;
285 return mHalClient.getValue(propValue);
286 }
287
288 public <T> T get(Class clazz, int propertyId) throws PropertyTimeoutException {
289 return get(clazz, createPropValue(propertyId, NO_AREA));
290 }
291
292 public <T> T get(Class clazz, int propertyId, int areaId) throws PropertyTimeoutException {
293 return get(clazz, createPropValue(propertyId, areaId));
294 }
295
296 @SuppressWarnings("unchecked")
297 public <T> T get(Class clazz, VehiclePropValue requestedPropValue)
298 throws PropertyTimeoutException {
299 VehiclePropValue propValue = mHalClient.getValue(requestedPropValue);
300 if (clazz == Integer.class || clazz == int.class) {
301 return (T) propValue.value.int32Values.get(0);
302 } else if (clazz == Boolean.class || clazz == boolean.class) {
303 return (T) Boolean.valueOf(propValue.value.int32Values.get(0) == 1);
304 } else if (clazz == Float.class || clazz == float.class) {
305 return (T) propValue.value.floatValues.get(0);
306 } else if (clazz == Integer[].class) {
307 Integer[] intArray = new Integer[propValue.value.int32Values.size()];
308 return (T) propValue.value.int32Values.toArray(intArray);
309 } else if (clazz == Float[].class) {
310 Float[] floatArray = new Float[propValue.value.floatValues.size()];
311 return (T) propValue.value.floatValues.toArray(floatArray);
312 } else if (clazz == int[].class) {
313 return (T) toIntArray(propValue.value.int32Values);
314 } else if (clazz == float[].class) {
315 return (T) toFloatArray(propValue.value.floatValues);
316 } else if (clazz == byte[].class) {
317 return (T) toByteArray(propValue.value.bytes);
318 } else if (clazz == String.class) {
319 return (T) propValue.value.stringValue;
320 } else {
321 throw new IllegalArgumentException("Unexpected type: " + clazz);
322 }
323 }
324
325 public VehiclePropValue get(VehiclePropValue requestedPropValue)
326 throws PropertyTimeoutException {
327 return mHalClient.getValue(requestedPropValue);
328 }
329
330 void set(VehiclePropValue propValue) throws PropertyTimeoutException {
331 mHalClient.setValue(propValue);
332 }
333
334 @CheckResult
335 VehiclePropValueSetter set(int propId) {
336 return new VehiclePropValueSetter(mHalClient, propId, NO_AREA);
337 }
338
339 @CheckResult
340 VehiclePropValueSetter set(int propId, int areaId) {
341 return new VehiclePropValueSetter(mHalClient, propId, areaId);
342 }
343
344 static boolean isPropertySubscribable(VehiclePropConfig config) {
345 if ((config.access & VehiclePropertyAccess.READ) == 0 ||
346 (config.changeMode == VehiclePropertyChangeMode.STATIC)) {
keunyounga74b9ca2015-10-21 13:33:58 -0700347 return false;
348 }
349 return true;
350 }
351
Pavel Maltsev0d07c762016-11-03 16:40:15 -0700352 static void dumpProperties(PrintWriter writer, Collection<VehiclePropConfig> configs) {
keunyounga74b9ca2015-10-21 13:33:58 -0700353 for (VehiclePropConfig config : configs) {
Pavel Maltsev0d07c762016-11-03 16:40:15 -0700354 writer.println(String.format("property 0x%x", config.prop));
keunyounga74b9ca2015-10-21 13:33:58 -0700355 }
356 }
357
Pavel Maltsev0d07c762016-11-03 16:40:15 -0700358 private final ArraySet<HalServiceBase> mServicesToDispatch = new ArraySet<>();
keunyounge4c90c42015-11-16 18:42:52 -0800359
keunyoungfe30ba02015-09-17 17:56:35 -0700360 @Override
Pavel Maltsev0d07c762016-11-03 16:40:15 -0700361 public void onPropertyEvent(ArrayList<VehiclePropValue> propValues) {
keunyounge4c90c42015-11-16 18:42:52 -0800362 synchronized (this) {
Pavel Maltsev0d07c762016-11-03 16:40:15 -0700363 for (VehiclePropValue v : propValues) {
364 HalServiceBase service = mPropertyHandlers.get(v.prop);
keunyounge4c90c42015-11-16 18:42:52 -0800365 service.getDispatchList().add(v);
366 mServicesToDispatch.add(service);
Pavel Maltsev0d07c762016-11-03 16:40:15 -0700367 VehiclePropertyEventInfo info = mEventLog.get(v.prop);
Keun-young Park97e46eb2016-04-09 15:02:38 -0700368 if (info == null) {
369 info = new VehiclePropertyEventInfo(v);
Pavel Maltsev0d07c762016-11-03 16:40:15 -0700370 mEventLog.put(v.prop, info);
Keun-young Park97e46eb2016-04-09 15:02:38 -0700371 } else {
372 info.addNewEvent(v);
373 }
keunyounge4c90c42015-11-16 18:42:52 -0800374 }
keunyoungcc449f72015-08-12 10:46:27 -0700375 }
keunyoungfe30ba02015-09-17 17:56:35 -0700376 for (HalServiceBase s : mServicesToDispatch) {
377 s.handleHalEvents(s.getDispatchList());
378 s.getDispatchList().clear();
379 }
380 mServicesToDispatch.clear();
keunyoungcc449f72015-08-12 10:46:27 -0700381 }
382
Keun-young Park28dd4702015-11-19 18:06:04 -0800383 @Override
Pavel Maltsevb0324b42016-09-27 21:00:41 -0700384 public void onPropertySet(VehiclePropValue value) {
385 // No need to handle on-property-set events in HAL service yet.
386 }
387
388 @Override
Pavel Maltsev0d07c762016-11-03 16:40:15 -0700389 public void onPropertySetError(int errorCode, int propId, int areaId) {
390 Log.e(CarLog.TAG_HAL, String.format("onPropertySetError, errorCode: %d, prop: 0x%x, "
391 + "area: 0x%x", errorCode, propId, areaId));
Keun-young Parkf9215202016-10-10 12:34:08 -0700392 // TODO propagate per property error to HAL services and handle global error, bug:32068464
Keun-young Park28dd4702015-11-19 18:06:04 -0800393 }
394
keunyoungcc449f72015-08-12 10:46:27 -0700395 public void dump(PrintWriter writer) {
396 writer.println("**dump HAL services**");
397 for (HalServiceBase service: mAllServices) {
398 service.dump(writer);
399 }
Steve Paik4d6088c2016-07-20 20:27:55 -0700400
401 List<VehiclePropConfig> configList;
402 synchronized (this) {
403 configList = new ArrayList<>(mAllProperties.values());
404 }
405
Pavel Maltsev0d07c762016-11-03 16:40:15 -0700406
Keun-young Park450faba2016-02-10 18:15:12 -0800407 writer.println("**All properties**");
Steve Paik4d6088c2016-07-20 20:27:55 -0700408 for (VehiclePropConfig config : configList) {
Pavel Maltsev0d07c762016-11-03 16:40:15 -0700409 StringBuilder builder = new StringBuilder()
410 .append("Property:0x").append(toHexString(config.prop))
411 .append(",access:0x").append(toHexString(config.access))
412 .append(",changeMode:0x").append(toHexString(config.changeMode))
413 .append(",permission:0x").append(toHexString(config.permissionModel))
414 .append(",areas:0x").append(toHexString(config.supportedAreas))
415 .append(",config:0x").append(Arrays.toString(config.configArray.toArray()))
416 .append(",fs min:").append(config.minSampleRate)
417 .append(",fs max:").append(config.maxSampleRate);
418 for (VehicleAreaConfig area : config.areaConfigs) {
419 builder.append(",areaId :").append(toHexString(area.areaId))
420 .append(",f min:").append(area.minFloatValue)
421 .append(",f max:").append(area.maxFloatValue)
422 .append(",i min:").append(area.minInt32Value)
423 .append(",i max:").append(area.maxInt32Value)
424 .append(",i64 min:").append(area.minInt64Value)
425 .append(",i64 max:").append(area.maxInt64Value);
Keun-young Park450faba2016-02-10 18:15:12 -0800426 }
427 writer.println(builder.toString());
428 }
Keun-young Park97e46eb2016-04-09 15:02:38 -0700429 writer.println(String.format("**All Events, now ns:%d**",
430 SystemClock.elapsedRealtimeNanos()));
431 for (VehiclePropertyEventInfo info : mEventLog.values()) {
432 writer.println(String.format("event count:%d, lastEvent:%s",
433 info.eventCount, dumpVehiclePropValue(info.lastEvent)));
434 }
Pavel Maltsev437ab412016-08-15 15:41:06 -0700435
436 writer.println("**Property handlers**");
437 for (int i = 0; i < mPropertyHandlers.size(); i++) {
438 int propId = mPropertyHandlers.keyAt(i);
439 HalServiceBase service = mPropertyHandlers.valueAt(i);
440 writer.println(String.format("Prop: 0x%08X, service: %s", propId, service));
441 }
Keun-young Park97e46eb2016-04-09 15:02:38 -0700442 }
443
Keun-young Park97e46eb2016-04-09 15:02:38 -0700444 private static class VehiclePropertyEventInfo {
445 private int eventCount;
446 private VehiclePropValue lastEvent;
447
448 private VehiclePropertyEventInfo(VehiclePropValue event) {
449 eventCount = 1;
450 lastEvent = event;
451 }
452
453 private void addNewEvent(VehiclePropValue event) {
454 eventCount++;
455 lastEvent = event;
456 }
keunyoungcc449f72015-08-12 10:46:27 -0700457 }
Pavel Maltsev0d07c762016-11-03 16:40:15 -0700458
459 final class VehiclePropValueSetter {
460 final WeakReference<HalClient> mClient;
461 final VehiclePropValue mPropValue;
462
463 private VehiclePropValueSetter(HalClient client, int propId, int areaId) {
464 mClient = new WeakReference<>(client);
465 mPropValue = new VehiclePropValue();
466 mPropValue.prop = propId;
467 mPropValue.areaId = areaId;
468 }
469
470 void to(boolean value) throws PropertyTimeoutException {
471 to(value ? 1 : 0);
472 }
473
474 void to(int value) throws PropertyTimeoutException {
475 mPropValue.value.int32Values.add(value);
476 submit();
477 }
478
479 void to(int[] values) throws PropertyTimeoutException {
480 for (int value : values) {
481 mPropValue.value.int32Values.add(value);
482 }
483 submit();
484 }
485
486 void to(Collection<Integer> values) throws PropertyTimeoutException {
487 mPropValue.value.int32Values.addAll(values);
488 submit();
489 }
490
491 void submit() throws PropertyTimeoutException {
492 HalClient client = mClient.get();
493 if (client != null) {
494 Log.i(CarLog.TAG_HAL, "set, property: 0x" + toHexString(mPropValue.prop)
495 + ", areaId: 0x" + toHexString(mPropValue.areaId));
496 client.setValue(mPropValue);
497 }
498 }
499 }
500
501 private static String dumpVehiclePropValue(VehiclePropValue value) {
502 final int MAX_BYTE_SIZE = 20;
503
504 StringBuilder sb = new StringBuilder()
505 .append("Property:0x").append(toHexString(value.prop))
506 .append(",timestamp:").append(value.timestamp)
507 .append(",zone:0x").append(toHexString(value.areaId))
508 .append(",floatValues: ").append(Arrays.toString(value.value.floatValues.toArray()))
509 .append(",int32Values: ").append(Arrays.toString(value.value.int32Values.toArray()))
510 .append(",int64Values: ")
511 .append(Arrays.toString(value.value.int64Values.toArray()));
512
513 if (value.value.bytes.size() > MAX_BYTE_SIZE) {
514 Object[] bytes = Arrays.copyOf(value.value.bytes.toArray(), MAX_BYTE_SIZE);
515 sb.append(",bytes: ").append(Arrays.toString(bytes));
516 } else {
517 sb.append(",bytes: ").append(Arrays.toString(value.value.bytes.toArray()));
518 }
519 sb.append(",string: ").append(value.value.stringValue);
520
521 return sb.toString();
522 }
523
524 private static VehiclePropValue createPropValue(int propId, int areaId) {
525 VehiclePropValue propValue = new VehiclePropValue();
526 propValue.prop = propId;
527 propValue.areaId = areaId;
528 return propValue;
529 }
keunyoungcc449f72015-08-12 10:46:27 -0700530}