blob: 28dd4c60bf06ef575592831c5928657391271d3b [file] [log] [blame]
Steve Paik461ecc62016-06-08 15:28:32 -07001/*
2 * Copyright (C) 2016 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 */
16package com.android.car.hal;
17
18import static com.android.car.hal.CarPropertyUtils.toCarPropertyValue;
19import static com.android.car.hal.CarPropertyUtils.toVehiclePropValue;
20import static java.lang.Integer.toHexString;
21
Pavel Maltsev0d07c762016-11-03 16:40:15 -070022import android.annotation.Nullable;
Steve Paik461ecc62016-06-08 15:28:32 -070023import android.car.hardware.CarPropertyConfig;
24import android.car.hardware.CarPropertyValue;
25import android.car.hardware.property.CarPropertyEvent;
Pavel Maltsev0d07c762016-11-03 16:40:15 -070026import android.hardware.vehicle.V2_0.VehiclePropConfig;
27import android.hardware.vehicle.V2_0.VehiclePropValue;
Steve Paik461ecc62016-06-08 15:28:32 -070028import android.util.Log;
29import android.util.SparseIntArray;
30
31import com.android.car.CarLog;
Pavel Maltsev634e1ff2016-07-14 15:41:26 -070032import com.android.internal.annotations.GuardedBy;
Steve Paik461ecc62016-06-08 15:28:32 -070033
34import java.io.PrintWriter;
35import java.util.ArrayList;
Pavel Maltsev0d07c762016-11-03 16:40:15 -070036import java.util.Collection;
Steve Paik461ecc62016-06-08 15:28:32 -070037import java.util.LinkedList;
38import java.util.List;
39import java.util.concurrent.ConcurrentHashMap;
40
41/**
42 * Common interface for HAL services that send Vehicle Properties back and forth via ICarProperty.
43 * Services that communicate by passing vehicle properties back and forth via ICarProperty should
44 * extend this class.
45 */
46public abstract class PropertyHalServiceBase extends HalServiceBase {
47 private final boolean mDbg;
Steve Paik461ecc62016-06-08 15:28:32 -070048 private final ConcurrentHashMap<Integer, CarPropertyConfig<?>> mProps =
49 new ConcurrentHashMap<>();
50 private final String mTag;
51 private final VehicleHal mVehicleHal;
52
Pavel Maltsev634e1ff2016-07-14 15:41:26 -070053 @GuardedBy("mLock")
54 private PropertyHalListener mListener;
55 private final Object mLock = new Object();
56
57 protected final static int NOT_SUPPORTED_PROPERTY = -1;
58
Steve Paik461ecc62016-06-08 15:28:32 -070059 public interface PropertyHalListener {
60 void onPropertyChange(CarPropertyEvent event);
61 void onError(int zone, int property);
62 }
63
Pavel Maltsev634e1ff2016-07-14 15:41:26 -070064 protected PropertyHalServiceBase(VehicleHal vehicleHal, String tag, boolean dbg) {
Steve Paik461ecc62016-06-08 15:28:32 -070065 mVehicleHal = vehicleHal;
66 mTag = "PropertyHalServiceBase." + tag;
67 mDbg = dbg;
68
69 if (mDbg) {
70 Log.d(mTag, "started PropertyHalServiceBase!");
71 }
72 }
73
74 public void setListener(PropertyHalListener listener) {
Pavel Maltsev634e1ff2016-07-14 15:41:26 -070075 synchronized (mLock) {
Steve Paik461ecc62016-06-08 15:28:32 -070076 mListener = listener;
77 }
78 }
79
80 public List<CarPropertyConfig> getPropertyList() {
81 return new ArrayList<>(mProps.values());
82 }
83
Pavel Maltsev0d07c762016-11-03 16:40:15 -070084 /**
85 * Returns property or null if property is not ready yet.
86 */
87 @Nullable
Steve Paik461ecc62016-06-08 15:28:32 -070088 public CarPropertyValue getProperty(int mgrPropId, int areaId) {
89 int halPropId = managerToHalPropId(mgrPropId);
Pavel Maltsev634e1ff2016-07-14 15:41:26 -070090 if (halPropId == NOT_SUPPORTED_PROPERTY) {
91 throw new IllegalArgumentException("Invalid property Id : 0x" + toHexString(mgrPropId));
92 }
Steve Paik461ecc62016-06-08 15:28:32 -070093
94 VehiclePropValue value = null;
95 try {
Pavel Maltsev0d07c762016-11-03 16:40:15 -070096 value = mVehicleHal.get(halPropId, areaId);
97 } catch (PropertyTimeoutException e) {
Steve Paik461ecc62016-06-08 15:28:32 -070098 Log.e(CarLog.TAG_PROPERTY, "get, property not ready 0x" + toHexString(halPropId), e);
99 }
100
101 return value == null ? null : toCarPropertyValue(value, mgrPropId);
102 }
103
104 public void setProperty(CarPropertyValue prop) {
105 int halPropId = managerToHalPropId(prop.getPropertyId());
Pavel Maltsev634e1ff2016-07-14 15:41:26 -0700106 if (halPropId == NOT_SUPPORTED_PROPERTY) {
107 throw new IllegalArgumentException("Invalid property Id : 0x"
108 + toHexString(prop.getPropertyId()));
109 }
Steve Paik461ecc62016-06-08 15:28:32 -0700110 VehiclePropValue halProp = toVehiclePropValue(prop, halPropId);
111 try {
Pavel Maltsev0d07c762016-11-03 16:40:15 -0700112 mVehicleHal.set(halProp);
113 } catch (PropertyTimeoutException e) {
Steve Paik461ecc62016-06-08 15:28:32 -0700114 Log.e(CarLog.TAG_PROPERTY, "set, property not ready 0x" + toHexString(halPropId), e);
115 throw new RuntimeException(e);
116 }
117 }
118
119 @Override
120 public void init() {
121 if (mDbg) {
122 Log.d(mTag, "init()");
123 }
124 // Subscribe to each of the properties
125 for (Integer prop : mProps.keySet()) {
126 mVehicleHal.subscribeProperty(this, prop, 0);
127 }
128 }
129
130 @Override
131 public void release() {
132 if (mDbg) {
133 Log.d(mTag, "release()");
134 }
135
136 for (Integer prop : mProps.keySet()) {
137 mVehicleHal.unsubscribeProperty(this, prop);
138 }
139
140 // Clear the property list
141 mProps.clear();
142
Pavel Maltsev634e1ff2016-07-14 15:41:26 -0700143 synchronized (mLock) {
Steve Paik461ecc62016-06-08 15:28:32 -0700144 mListener = null;
145 }
146 }
147
148 @Override
Pavel Maltsev0d07c762016-11-03 16:40:15 -0700149 public Collection<VehiclePropConfig> takeSupportedProperties(
150 Collection<VehiclePropConfig> allProperties) {
Steve Paik461ecc62016-06-08 15:28:32 -0700151 List<VehiclePropConfig> taken = new LinkedList<>();
152
153 for (VehiclePropConfig p : allProperties) {
Pavel Maltsev0d07c762016-11-03 16:40:15 -0700154 int mgrPropId = halToManagerPropId(p.prop);
Steve Paik461ecc62016-06-08 15:28:32 -0700155
Pavel Maltsev634e1ff2016-07-14 15:41:26 -0700156 if (mgrPropId == NOT_SUPPORTED_PROPERTY) {
157 continue; // The property is not handled by this HAL.
Steve Paik461ecc62016-06-08 15:28:32 -0700158 }
Pavel Maltsev634e1ff2016-07-14 15:41:26 -0700159
Steve Paik461ecc62016-06-08 15:28:32 -0700160 CarPropertyConfig config = CarPropertyUtils.toCarPropertyConfig(p, mgrPropId);
161
162 taken.add(p);
Pavel Maltsev0d07c762016-11-03 16:40:15 -0700163 mProps.put(p.prop, config);
Steve Paik461ecc62016-06-08 15:28:32 -0700164
165 if (mDbg) {
Pavel Maltsev0d07c762016-11-03 16:40:15 -0700166 Log.d(mTag, "takeSupportedProperties: " + toHexString(p.prop));
Steve Paik461ecc62016-06-08 15:28:32 -0700167 }
168 }
169 return taken;
170 }
171
172 @Override
173 public void handleHalEvents(List<VehiclePropValue> values) {
174 PropertyHalListener listener;
175 synchronized (this) {
176 listener = mListener;
177 }
178 if (listener != null) {
179 for (VehiclePropValue v : values) {
Pavel Maltsev0d07c762016-11-03 16:40:15 -0700180 int prop = v.prop;
Pavel Maltsev634e1ff2016-07-14 15:41:26 -0700181 int mgrPropId = halToManagerPropId(prop);
Steve Paik461ecc62016-06-08 15:28:32 -0700182
Pavel Maltsev634e1ff2016-07-14 15:41:26 -0700183 if (mgrPropId == NOT_SUPPORTED_PROPERTY) {
184 Log.e(mTag, "Property is not supported: 0x" + toHexString(prop));
Steve Paik461ecc62016-06-08 15:28:32 -0700185 continue;
186 }
187
188 CarPropertyEvent event;
189 CarPropertyValue<?> propVal = toCarPropertyValue(v, mgrPropId);
190 event = new CarPropertyEvent(CarPropertyEvent.PROPERTY_EVENT_PROPERTY_CHANGE,
191 propVal);
192
193 listener.onPropertyChange(event);
194 if (mDbg) {
195 Log.d(mTag, "handleHalEvents event: " + event);
196 }
197 }
198 }
199 }
200
201 @Override
202 public void dump(PrintWriter writer) {
203 writer.println(mTag);
204 writer.println(" Properties available:");
205 for (CarPropertyConfig prop : mProps.values()) {
206 writer.println(" " + prop.toString());
207 }
208 }
209
210 /**
Pavel Maltsev634e1ff2016-07-14 15:41:26 -0700211 * Converts manager property ID to Vehicle HAL property ID.
212 * If property is not supported, it will return {@link #NOT_SUPPORTED_PROPERTY}.
Steve Paik461ecc62016-06-08 15:28:32 -0700213 */
214 abstract protected int managerToHalPropId(int managerPropId);
215
216 /**
Pavel Maltsev634e1ff2016-07-14 15:41:26 -0700217 * Converts Vehicle HAL property ID to manager property ID.
218 * If property is not supported, it will return {@link #NOT_SUPPORTED_PROPERTY}.
Steve Paik461ecc62016-06-08 15:28:32 -0700219 */
220 abstract protected int halToManagerPropId(int halPropId);
Pavel Maltsev634e1ff2016-07-14 15:41:26 -0700221
222 /**
223 * Helper class that maintains bi-directional mapping between manager's property
224 * Id (public or system API) and vehicle HAL property Id.
225 *
226 * <p>This class is supposed to be immutable. Use {@link #create(int[])} factory method to
227 * instantiate this class.
228 */
229 static class ManagerToHalPropIdMap {
230 private final SparseIntArray mMap;
231 private final SparseIntArray mInverseMap;
232
233 /**
234 * Creates {@link ManagerToHalPropIdMap} for provided [manager prop Id, hal prop Id] pairs.
235 *
236 * <p> The input array should have an odd number of elements.
237 */
238 static ManagerToHalPropIdMap create(int[] mgrToHalPropIds) {
239 int inputLength = mgrToHalPropIds.length;
240 if (inputLength % 2 != 0) {
241 throw new IllegalArgumentException("Odd number of key-value elements");
242 }
243
244 ManagerToHalPropIdMap biMap = new ManagerToHalPropIdMap(inputLength / 2);
245 for (int i = 0; i < mgrToHalPropIds.length; i += 2) {
246 biMap.put(mgrToHalPropIds[i], mgrToHalPropIds[i + 1]);
247 }
248 return biMap;
249 }
250
251 private ManagerToHalPropIdMap(int initialCapacity) {
252 mMap = new SparseIntArray(initialCapacity);
253 mInverseMap = new SparseIntArray(initialCapacity);
254 }
255
256 private void put(int managerPropId, int halPropId) {
257 mMap.put(managerPropId, halPropId);
258 mInverseMap.put(halPropId, managerPropId);
259 }
260
261 int getHalPropId(int managerPropId) {
262 return mMap.get(managerPropId, NOT_SUPPORTED_PROPERTY);
263 }
264
265 int getManagerPropId(int halPropId) {
266 return mInverseMap.get(halPropId, NOT_SUPPORTED_PROPERTY);
267 }
268 }
Steve Paik461ecc62016-06-08 15:28:32 -0700269}