• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 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 
17 package com.android.car.hal;
18 
19 import android.car.hardware.CarPropertyValue;
20 import android.hardware.automotive.vehicle.VehiclePropertyType;
21 import android.util.Log;
22 
23 import java.util.ArrayList;
24 import java.util.Arrays;
25 import java.util.List;
26 
27 /**
28  * HalPropValue represents a vehicle property value.
29  *
30  * It could be used to convert between AIDL or HIDL VehiclePropValue used in vehicle HAL and
31  * {@link CarPropertyValue} used in CarPropertyManager.
32  */
33 public abstract class HalPropValue {
34     private static final String TAG = HalPropValue.class.getSimpleName();
35 
36     /**
37      * Gets the timestamp.
38      *
39      * @return The timestamp.
40      */
getTimestamp()41     public abstract long getTimestamp();
42 
43     /**
44      * Gets the area ID.
45      *
46      * @return The area ID.
47      */
getAreaId()48     public abstract int getAreaId();
49 
50     /**
51      * Gets the property ID.
52      *
53      * @return The property ID.
54      */
getPropId()55     public abstract int getPropId();
56 
57     /**
58      * Gets the property status.
59      *
60      * @return The property status.
61      */
getStatus()62     public abstract int getStatus();
63 
64     /**
65      * Get stored int32 values size.
66      *
67      * @return The size for the stored int32 values.
68      */
getInt32ValuesSize()69     public abstract int getInt32ValuesSize();
70 
71     /**
72      * Gets the int32 value at index.
73      *
74      * @param index The index.
75      * @return The int32 value at index.
76      */
getInt32Value(int index)77     public abstract int getInt32Value(int index);
78 
79     /**
80      * Dump all int32 values as a string. Used for debugging.
81      *
82      * @return A String representation of all int32 values.
83      */
dumpInt32Values()84     public abstract String dumpInt32Values();
85 
86     /**
87      * Get stored float values size.
88      *
89      * @return The size for the stored float values.
90      */
getFloatValuesSize()91     public abstract int getFloatValuesSize();
92 
93     /**
94      * Gets the float value at index.
95      *
96      * @param index The index.
97      * @return The float value at index.
98      */
getFloatValue(int index)99     public abstract float getFloatValue(int index);
100 
101     /**
102      * Dump all float values as a string. Used for debugging.
103      *
104      * @return A String representation of all float values.
105      */
dumpFloatValues()106     public abstract String dumpFloatValues();
107 
108     /**
109      * Get stored inn64 values size.
110      *
111      * @return The size for the stored inn64 values.
112      */
getInt64ValuesSize()113     public abstract int getInt64ValuesSize();
114 
115     /**
116      * Gets the int64 value at index.
117      *
118      * @param index The index.
119      * @return The int64 value at index.
120      */
getInt64Value(int index)121     public abstract long getInt64Value(int index);
122 
123     /**
124      * Dump all int64 values as a string. Used for debugging.
125      *
126      * @return A String representation of all int64 values.
127      */
dumpInt64Values()128     public abstract String dumpInt64Values();
129 
130     /**
131      * Get stored byte values size.
132      *
133      * @return The size for the stored byte values.
134      */
getByteValuesSize()135     public abstract int getByteValuesSize();
136 
137     /**
138      * Gets the byte value at index.
139      *
140      * @param index The index.
141      * @return The byte value at index.
142      */
getByteValue(int index)143     public abstract byte getByteValue(int index);
144 
145     /**
146      * Gets the byte values.
147      *
148      * @return The byte values.
149      */
getByteArray()150     public abstract byte[] getByteArray();
151 
152     /**
153      * Gets the string value.
154      *
155      * @return The stored string value.
156      */
getStringValue()157     public abstract String getStringValue();
158 
159     /**
160      * Converts to an AIDL/HIDL VehiclePropValue that could be used to sent to vehicle HAL.
161      *
162      * @return An AIDL or HIDL VehiclePropValue.
163      */
toVehiclePropValue()164     public abstract Object toVehiclePropValue();
165 
166     /**
167      * Turns this class to a {@link CarPropertyValue}.
168      *
169      * @param mgrPropId The property ID used in {@link android.car.VehiclePropertyIds}.
170      * @param config The config for the property.
171      * @return A CarPropertyValue that could be passed to upper layer.
172      */
toCarPropertyValue(int mgrPropId, HalPropConfig config)173     public CarPropertyValue toCarPropertyValue(int mgrPropId, HalPropConfig config) {
174         if (isMixedTypeProperty(getPropId())) {
175             int[] configArray = config.getConfigArray();
176             boolean containStringType = configArray[0] == 1;
177             boolean containBooleanType = configArray[1] == 1;
178             return toMixedCarPropertyValue(mgrPropId, containBooleanType, containStringType);
179         }
180         return toCarPropertyValue(mgrPropId);
181     }
182 
183     /**
184      * Check whether this property is equal to another property.
185      *
186      * @param argument The property to compare.
187      * @return true if equal, false if not.
188      */
189     @Override
equals(Object argument)190     public boolean equals(Object argument) {
191         if (!(argument instanceof HalPropValue)) {
192             return false;
193         }
194 
195         HalPropValue other = (HalPropValue) argument;
196 
197         if (other.getPropId() != getPropId()) {
198             Log.i(TAG, "Property ID mismatch, got " + other.getPropId() + " want "
199                     + getPropId());
200             return false;
201         }
202         if (other.getAreaId() != getAreaId()) {
203             Log.i(TAG, "Area ID mismatch, got " + other.getAreaId() + " want " + getAreaId());
204             return false;
205         }
206         if (other.getStatus() != getStatus()) {
207             Log.i(TAG, "Status mismatch, got " + other.getStatus() + " want " + getStatus());
208             return false;
209         }
210         if (other.getTimestamp() != getTimestamp()) {
211             Log.i(TAG, "Timestamp mismatch, got " + other.getTimestamp() + " want "
212                     + getTimestamp());
213             return false;
214         }
215         if (!equalInt32Values(other)) {
216             Log.i(TAG, "Int32Values mismatch, got " + other.dumpInt32Values() + " want "
217                     + dumpInt32Values());
218             return false;
219         }
220         if (!equalFloatValues(other)) {
221             Log.i(TAG, "FloatValues mismatch, got " + other.dumpFloatValues() + " want "
222                     + dumpFloatValues());
223             return false;
224         }
225         if (!equalInt64Values(other)) {
226             Log.i(TAG, "Int64Values mismatch, got " + other.dumpInt64Values() + " want "
227                     + dumpInt64Values());
228             return false;
229         }
230         if (!Arrays.equals(other.getByteArray(), getByteArray())) {
231             Log.i(TAG, "ByteValues mismatch, got " + Arrays.toString(other.getByteArray())
232                     + " want " + Arrays.toString(getByteArray()));
233             return false;
234         }
235         if (!other.getStringValue().equals(getStringValue())) {
236             Log.i(TAG, "StringValue mismatch, got " + other.getStringValue() + " want "
237                     + getStringValue());
238             return false;
239         }
240         return true;
241     }
242 
243     /**
244      * Get the hashCode for this value.
245      */
246     @Override
hashCode()247     public abstract int hashCode();
248 
isMixedTypeProperty(int prop)249     protected static boolean isMixedTypeProperty(int prop) {
250         return (prop & VehiclePropertyType.MASK) == VehiclePropertyType.MIXED;
251     }
252 
getFloatContainerArray()253     protected abstract Float[] getFloatContainerArray();
254 
getInt32ContainerArray()255     protected abstract Integer[] getInt32ContainerArray();
256 
getInt64ContainerArray()257     protected abstract Long[] getInt64ContainerArray();
258 
toCarPropertyValue(int propertyId)259     private CarPropertyValue<?> toCarPropertyValue(int propertyId) {
260         Class<?> clazz = CarPropertyUtils.getJavaClass(getPropId() & VehiclePropertyType.MASK);
261         int areaId = getAreaId();
262         int status = getStatus();
263         long timestamp = getTimestamp();
264 
265         // Handles each return value from {@link getJavaClass}.
266         if (Boolean.class == clazz) {
267             return new CarPropertyValue<>(
268                     propertyId, areaId, status, timestamp, getInt32Value(0) == 1);
269         } else if (Float.class == clazz) {
270             return new CarPropertyValue<>(propertyId, areaId, status, timestamp, getFloatValue(0));
271         } else if (Integer.class == clazz) {
272             return new CarPropertyValue<>(propertyId, areaId, status, timestamp, getInt32Value(0));
273         } else if (Long.class == clazz) {
274             return new CarPropertyValue<>(propertyId, areaId, status, timestamp, getInt64Value(0));
275         } else if (Float[].class == clazz) {
276             return new CarPropertyValue<>(
277                     propertyId, areaId, status, timestamp, getFloatContainerArray());
278         } else if (Integer[].class == clazz) {
279             return new CarPropertyValue<>(
280                     propertyId, areaId, status, timestamp, getInt32ContainerArray());
281         } else if (Long[].class == clazz) {
282             return new CarPropertyValue<>(
283                     propertyId, areaId, status, timestamp, getInt64ContainerArray());
284         } else if (String.class == clazz) {
285             return new CarPropertyValue<>(propertyId, areaId, status, timestamp, getStringValue());
286         } else if (byte[].class == clazz) {
287             return new CarPropertyValue<>(propertyId, areaId, status, timestamp, getByteArray());
288         } else {
289             throw new IllegalArgumentException("Unexpected type in: " + propertyId);
290         }
291     }
292 
toMixedCarPropertyValue( int propertyId, boolean containBoolean, boolean containString)293     private CarPropertyValue<?> toMixedCarPropertyValue(
294             int propertyId, boolean containBoolean, boolean containString) {
295         int areaId = getAreaId();
296         int status = getStatus();
297         long timestamp = getTimestamp();
298 
299         List<Object> valuesList = new ArrayList<>();
300         if (containString) {
301             valuesList.add(getStringValue());
302         }
303         if (containBoolean) {
304             boolean boolValue = getInt32Value(0) == 1;
305             valuesList.add(boolValue);
306             for (int i = 1; i < getInt32ValuesSize(); i++) {
307                 valuesList.add(getInt32Value(i));
308             }
309         } else {
310             for (int i = 0; i < getInt32ValuesSize(); i++) {
311                 valuesList.add(getInt32Value(i));
312             }
313         }
314         for (int i = 0; i < getInt64ValuesSize(); i++) {
315             valuesList.add(getInt64Value(i));
316         }
317         for (int i = 0; i < getFloatValuesSize(); i++) {
318             valuesList.add(getFloatValue(i));
319         }
320         for (int i = 0; i < getByteValuesSize(); i++) {
321             valuesList.add(getByteValue(i));
322         }
323         return new CarPropertyValue<>(propertyId, areaId, status, timestamp, valuesList.toArray());
324     }
325 
equalInt32Values(HalPropValue argument)326     private boolean equalInt32Values(HalPropValue argument) {
327         if (getInt32ValuesSize() != argument.getInt32ValuesSize()) {
328             return false;
329         }
330         for (int i = 0; i < getInt32ValuesSize(); i++) {
331             if (getInt32Value(i) != argument.getInt32Value(i)) {
332                 return false;
333             }
334         }
335         return true;
336     }
337 
equalFloatValues(HalPropValue argument)338     private boolean equalFloatValues(HalPropValue argument) {
339         if (getFloatValuesSize() != argument.getFloatValuesSize()) {
340             return false;
341         }
342         for (int i = 0; i < getFloatValuesSize(); i++) {
343             if (getFloatValue(i) != argument.getFloatValue(i)) {
344                 return false;
345             }
346         }
347         return true;
348     }
349 
equalInt64Values(HalPropValue argument)350     private boolean equalInt64Values(HalPropValue argument) {
351         if (getInt64ValuesSize() != argument.getInt64ValuesSize()) {
352             return false;
353         }
354         for (int i = 0; i < getInt64ValuesSize(); i++) {
355             if (getInt64Value(i) != argument.getInt64Value(i)) {
356                 return false;
357             }
358         }
359         return true;
360     }
361 }
362