• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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  */
16 
17 package android.car.hardware;
18 
19 import android.annotation.IntDef;
20 import android.annotation.NonNull;
21 import android.annotation.Nullable;
22 import android.annotation.SystemApi;
23 import android.car.VehicleAreaType;
24 import android.car.VehicleAreaType.VehicleAreaTypeValue;
25 import android.car.VehiclePropertyType;
26 import android.os.Parcel;
27 import android.os.Parcelable;
28 import android.util.SparseArray;
29 
30 import java.lang.annotation.Retention;
31 import java.lang.annotation.RetentionPolicy;
32 import java.lang.reflect.Array;
33 import java.util.ArrayList;
34 import java.util.Collections;
35 import java.util.List;
36 
37 /**
38  * Represents general information about car property such as data type and min/max ranges for car
39  * areas (if applicable). This class supposed to be immutable, parcelable and could be passed over.
40  *
41  * @param <T> refer to Parcel#writeValue(Object) to get a list of all supported types. The class
42  * should be visible to framework as default class loader is being used here.
43  *
44  */
45 public final class CarPropertyConfig<T> implements Parcelable {
46     private final int mAccess;
47     private final int mAreaType;
48     private final int mChangeMode;
49     private final ArrayList<Integer> mConfigArray;
50     private final String mConfigString;
51     private final float mMaxSampleRate;
52     private final float mMinSampleRate;
53     private final int mPropertyId;
54     private final SparseArray<AreaConfig<T>> mSupportedAreas;
55     private final Class<T> mType;
56 
CarPropertyConfig(int access, int areaType, int changeMode, ArrayList<Integer> configArray, String configString, float maxSampleRate, float minSampleRate, int propertyId, SparseArray<AreaConfig<T>> supportedAreas, Class<T> type)57     private CarPropertyConfig(int access, int areaType, int changeMode,
58             ArrayList<Integer> configArray, String configString,
59             float maxSampleRate, float minSampleRate, int propertyId,
60             SparseArray<AreaConfig<T>> supportedAreas, Class<T> type) {
61         mAccess = access;
62         mAreaType = areaType;
63         mChangeMode = changeMode;
64         mConfigArray = configArray;
65         mConfigString = configString;
66         mMaxSampleRate = maxSampleRate;
67         mMinSampleRate = minSampleRate;
68         mPropertyId = propertyId;
69         mSupportedAreas = supportedAreas;
70         mType = type;
71     }
72 
73     /** @hide */
74     @IntDef(prefix = {"VEHICLE_PROPERTY_ACCESS"}, value = {
75         VEHICLE_PROPERTY_ACCESS_NONE,
76         VEHICLE_PROPERTY_ACCESS_READ,
77         VEHICLE_PROPERTY_ACCESS_WRITE,
78         VEHICLE_PROPERTY_ACCESS_READ_WRITE
79     })
80     @Retention(RetentionPolicy.SOURCE)
81     public @interface VehiclePropertyAccessType {}
82 
83     /** Property Access Unknown */
84     public static final int VEHICLE_PROPERTY_ACCESS_NONE = 0;
85     /** The property is readable */
86     public static final int VEHICLE_PROPERTY_ACCESS_READ = 1;
87     /** The property is writable */
88     public static final int VEHICLE_PROPERTY_ACCESS_WRITE = 2;
89     /** The property is readable and writable */
90     public static final int VEHICLE_PROPERTY_ACCESS_READ_WRITE = 3;
91 
92     /** @hide */
93     @IntDef(prefix = {"VEHICLE_PROPERTY_CHANGE_MODE"}, value = {
94         VEHICLE_PROPERTY_CHANGE_MODE_STATIC,
95         VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
96         VEHICLE_PROPERTY_CHANGE_MODE_CONTINUOUS,
97     })
98     @Retention(RetentionPolicy.SOURCE)
99     public @interface VehiclePropertyChangeModeType {}
100 
101     /** Properties of this type must never be changed. */
102     public static final int VEHICLE_PROPERTY_CHANGE_MODE_STATIC = 0;
103     /** Properties of this type must report when there is a change. */
104     public static final int VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE = 1;
105     /** Properties of this type change continuously. */
106     public static final int VEHICLE_PROPERTY_CHANGE_MODE_CONTINUOUS = 2;
107 
108     /**
109      * Return the access type of the car property.
110      * <p>The access type could be one of the following:
111      * <ul>
112      *   <li>{@link CarPropertyConfig#VEHICLE_PROPERTY_ACCESS_NONE}</li>
113      *   <li>{@link CarPropertyConfig#VEHICLE_PROPERTY_ACCESS_READ}</li>
114      *   <li>{@link CarPropertyConfig#VEHICLE_PROPERTY_ACCESS_WRITE}</li>
115      *   <li>{@link CarPropertyConfig#VEHICLE_PROPERTY_ACCESS_READ_WRITE}</li>
116      * </ul>
117      *
118      * @return the access type of the car property.
119      */
getAccess()120     public @VehiclePropertyAccessType int getAccess() {
121         return mAccess;
122     }
123 
124     /**
125      * Return the area type of the car property.
126      * <p>The area type could be one of the following:
127      * <ul>
128      *   <li>{@link VehicleAreaType#VEHICLE_AREA_TYPE_GLOBAL}</li>
129      *   <li>{@link VehicleAreaType#VEHICLE_AREA_TYPE_WINDOW}</li>
130      *   <li>{@link VehicleAreaType#VEHICLE_AREA_TYPE_SEAT}</li>
131      *   <li>{@link VehicleAreaType#VEHICLE_AREA_TYPE_DOOR}</li>
132      *   <li>{@link VehicleAreaType#VEHICLE_AREA_TYPE_MIRROR}</li>
133      *   <li>{@link VehicleAreaType#VEHICLE_AREA_TYPE_WHEEL}</li>
134      * </ul>
135      *
136      * @return the area type of the car property.
137      */
getAreaType()138     public @VehicleAreaTypeValue int getAreaType() {
139         return mAreaType;
140     }
141 
142     /**
143      * Return the change mode of the car property.
144      *
145      * <p>The change mode could be one of the following:
146      * <ul>
147      *   <li>{@link CarPropertyConfig#VEHICLE_PROPERTY_CHANGE_MODE_STATIC }</li>
148      *   <li>{@link CarPropertyConfig#VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE}</li>
149      *   <li>{@link CarPropertyConfig#VEHICLE_PROPERTY_CHANGE_MODE_CONTINUOUS}</li>
150      * </ul>
151      *
152      * @return the change mode of properties.
153      */
getChangeMode()154     public @VehiclePropertyChangeModeType int getChangeMode() {
155         return mChangeMode;
156     }
157 
158     /**
159      *
160      * @return Additional configuration parameters. For different properties, configArrays have
161      * different information.
162      */
163     @NonNull
getConfigArray()164     public List<Integer> getConfigArray() {
165         return Collections.unmodifiableList(mConfigArray);
166     }
167 
168     /**
169      *
170      * @return Some properties may require additional information passed over this
171      * string. Most properties do not need to set this.
172      * @hide
173      */
getConfigString()174     public String getConfigString() {
175         return mConfigString;
176     }
177 
178     /**
179      *
180      * @return Max sample rate in Hz. Must be defined for VehiclePropertyChangeMode::CONTINUOUS
181      * return 0 if change mode is not continuous.
182      */
getMaxSampleRate()183     public float getMaxSampleRate() {
184         return mMaxSampleRate;
185     }
186 
187     /**
188      *
189      * @return Min sample rate in Hz.Must be defined for VehiclePropertyChangeMode::CONTINUOUS
190      * return 0 if change mode is not continuous.
191      */
getMinSampleRate()192     public float getMinSampleRate() {
193         return mMinSampleRate;
194     }
195 
196     /**
197      * @return Property identifier
198      */
getPropertyId()199     public int getPropertyId() {
200         return mPropertyId;
201     }
202 
203     /**
204      * Returns the value type of the vehicle property.
205      * <p>The value type could be one of the following:
206      * <ul>
207      *   <li>Boolean</li>
208      *   <li>Float</li>
209      *   <li>Float[]</li>
210      *   <li>Integer</li>
211      *   <li>Integer[]</li>
212      *   <li>Long</li>
213      *   <li>Long[]</li>
214      *   <li>String</li>
215      *   <li>byte[]</li>
216      *   <li>Object[]</li>
217      * </ul>
218      *
219      * @return the value type of the vehicle property.
220      */
221     @NonNull
getPropertyType()222     public Class<T> getPropertyType() {
223         return mType;
224     }
225 
226     /**
227      *
228      * @return true if this property doesn't hold car area-specific configuration.
229      */
isGlobalProperty()230     public boolean isGlobalProperty() {
231         return mAreaType == VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL;
232     }
233 
234     /**
235      *
236      * @return the number of areaIds for properties.
237      * @hide
238      */
getAreaCount()239     public int getAreaCount() {
240         return mSupportedAreas.size();
241     }
242 
243     /**
244      *
245      * @return Array of areaIds. An AreaID is a combination of one or more areas,
246      * and is represented using a bitmask of Area enums. Different AreaTypes may
247      * not be mixed in a single AreaID. For instance, a window area cannot be
248      * combined with a seat area in an AreaID.
249      * Rules for mapping a zoned property to AreaIDs:
250      *  - A property must be mapped to an array of AreaIDs that are impacted when
251      *    the property value changes.
252      *  - Each element in the array must represent an AreaID, in which, the
253      *    property value can only be changed together in all the areas within
254      *    an AreaID and never independently. That is, when the property value
255      *    changes in one of the areas in an AreaID in the array, then it must
256      *    automatically change in all other areas in the AreaID.
257      *  - The property value must be independently controllable in any two
258      *    different AreaIDs in the array.
259      *  - An area must only appear once in the array of AreaIDs. That is, an
260      *    area must only be part of a single AreaID in the array.
261      */
262     @NonNull
getAreaIds()263     public int[] getAreaIds() {
264         int[] areaIds = new int[mSupportedAreas.size()];
265         for (int i = 0; i < areaIds.length; i++) {
266             areaIds[i] = mSupportedAreas.keyAt(i);
267         }
268         return areaIds;
269     }
270 
271     /**
272      * @return  the first areaId.
273      * Throws {@link IllegalStateException} if supported area count not equals to one.
274      * @hide
275      */
getFirstAndOnlyAreaId()276     public int getFirstAndOnlyAreaId() {
277         if (mSupportedAreas.size() != 1) {
278             throw new IllegalStateException("Expected one and only area in this property. Prop: 0x"
279                     + Integer.toHexString(mPropertyId));
280         }
281         return mSupportedAreas.keyAt(0);
282     }
283 
284     /**
285      *
286      * @param areaId
287      * @return true if areaId is existing.
288      * @hide
289      */
hasArea(int areaId)290     public boolean hasArea(int areaId) {
291         return mSupportedAreas.indexOfKey(areaId) >= 0;
292     }
293 
294     /**
295      *
296      * @param areaId
297      * @return Min value in given areaId. Null if not have min value in given area.
298      */
299     @Nullable
getMinValue(int areaId)300     public T getMinValue(int areaId) {
301         AreaConfig<T> area = mSupportedAreas.get(areaId);
302         return area == null ? null : area.getMinValue();
303     }
304 
305     /**
306      *
307      * @param areaId
308      * @return Max value in given areaId. Null if not have max value in given area.
309      */
310     @Nullable
getMaxValue(int areaId)311     public T getMaxValue(int areaId) {
312         AreaConfig<T> area = mSupportedAreas.get(areaId);
313         return area == null ? null : area.getMaxValue();
314     }
315 
316     /**
317      *
318      * @return Min value in areaId 0. Null if not have min value.
319      */
320     @Nullable
getMinValue()321     public T getMinValue() {
322         AreaConfig<T> area = mSupportedAreas.get(0);
323         return area == null ? null : area.getMinValue();
324     }
325 
326     /**
327      *
328      * @return Max value in areaId 0. Null if not have max value.
329      */
330     @Nullable
getMaxValue()331     public T getMaxValue() {
332         AreaConfig<T> area = mSupportedAreas.get(0);
333         return area == null ? null : area.getMaxValue();
334     }
335 
336     @Override
describeContents()337     public int describeContents() {
338         return 0;
339     }
340 
341 
342     @Override
writeToParcel(Parcel dest, int flags)343     public void writeToParcel(Parcel dest, int flags) {
344         dest.writeInt(mAccess);
345         dest.writeInt(mAreaType);
346         dest.writeInt(mChangeMode);
347         dest.writeInt(mConfigArray.size());
348         for (int i = 0; i < mConfigArray.size(); i++) {
349             dest.writeInt(mConfigArray.get(i));
350         }
351         dest.writeString(mConfigString);
352         dest.writeFloat(mMaxSampleRate);
353         dest.writeFloat(mMinSampleRate);
354         dest.writeInt(mPropertyId);
355         dest.writeInt(mSupportedAreas.size());
356         for (int i = 0; i < mSupportedAreas.size(); i++) {
357             dest.writeInt(mSupportedAreas.keyAt(i));
358             dest.writeParcelable(mSupportedAreas.valueAt(i), flags);
359         }
360         dest.writeString(mType.getName());
361     }
362 
363     @SuppressWarnings("unchecked")
CarPropertyConfig(Parcel in)364     private CarPropertyConfig(Parcel in) {
365         mAccess = in.readInt();
366         mAreaType = in.readInt();
367         mChangeMode = in.readInt();
368         int configArraySize = in.readInt();
369         mConfigArray = new ArrayList<Integer>(configArraySize);
370         for (int i = 0; i < configArraySize; i++) {
371             mConfigArray.add(in.readInt());
372         }
373         mConfigString = in.readString();
374         mMaxSampleRate = in.readFloat();
375         mMinSampleRate = in.readFloat();
376         mPropertyId = in.readInt();
377         int areaSize = in.readInt();
378         mSupportedAreas = new SparseArray<>(areaSize);
379         for (int i = 0; i < areaSize; i++) {
380             int areaId = in.readInt();
381             AreaConfig<T> area = in.readParcelable(getClass().getClassLoader());
382             mSupportedAreas.put(areaId, area);
383         }
384         String className = in.readString();
385         try {
386             mType = (Class<T>) Class.forName(className);
387         } catch (ClassNotFoundException e) {
388             throw new IllegalArgumentException("Class not found: " + className);
389         }
390     }
391 
392     public static final Creator<CarPropertyConfig> CREATOR = new Creator<CarPropertyConfig>() {
393         @Override
394         public CarPropertyConfig createFromParcel(Parcel in) {
395             return new CarPropertyConfig(in);
396         }
397 
398         @Override
399         public CarPropertyConfig[] newArray(int size) {
400             return new CarPropertyConfig[size];
401         }
402     };
403 
404     /** @hide */
405     @Override
toString()406     public String toString() {
407         return "CarPropertyConfig{"
408                 + "mPropertyId=" + mPropertyId
409                 + ", mAccess=" + mAccess
410                 + ", mAreaType=" + mAreaType
411                 + ", mChangeMode=" + mChangeMode
412                 + ", mConfigArray=" + mConfigArray
413                 + ", mConfigString=" + mConfigString
414                 + ", mMaxSampleRate=" + mMaxSampleRate
415                 + ", mMinSampleRate=" + mMinSampleRate
416                 + ", mSupportedAreas=" + mSupportedAreas
417                 + ", mType=" + mType
418                 + '}';
419     }
420 
421     /**
422      * Represents min/max value of car property.
423      * @param <T>
424      * @hide
425      */
426     public static class AreaConfig<T> implements Parcelable {
427         @Nullable private final T mMinValue;
428         @Nullable private final T mMaxValue;
429 
AreaConfig(T minValue, T maxValue)430         private AreaConfig(T minValue, T maxValue) {
431             mMinValue = minValue;
432             mMaxValue = maxValue;
433         }
434 
435         public static final Parcelable.Creator<AreaConfig<Object>> CREATOR =
436                 getCreator(Object.class);
437 
getCreator(final Class<E> clazz)438         private static <E> Parcelable.Creator<AreaConfig<E>> getCreator(final Class<E> clazz) {
439             return new Creator<AreaConfig<E>>() {
440                 @Override
441                 public AreaConfig<E> createFromParcel(Parcel source) {
442                     return new AreaConfig<>(source);
443                 }
444 
445                 @Override @SuppressWarnings("unchecked")
446                 public AreaConfig<E>[] newArray(int size) {
447                     return (AreaConfig<E>[]) Array.newInstance(clazz, size);
448                 }
449             };
450         }
451 
452         @SuppressWarnings("unchecked")
AreaConfig(Parcel in)453         private AreaConfig(Parcel in) {
454             mMinValue = (T) in.readValue(getClass().getClassLoader());
455             mMaxValue = (T) in.readValue(getClass().getClassLoader());
456         }
457 
getMinValue()458         @Nullable public T getMinValue() {
459             return mMinValue;
460         }
461 
getMaxValue()462         @Nullable public T getMaxValue() {
463             return mMaxValue;
464         }
465 
466         @Override
describeContents()467         public int describeContents() {
468             return 0;
469         }
470 
471         @Override
writeToParcel(Parcel dest, int flags)472         public void writeToParcel(Parcel dest, int flags) {
473             dest.writeValue(mMinValue);
474             dest.writeValue(mMaxValue);
475         }
476 
477         @Override
toString()478         public String toString() {
479             return "CarAreaConfig{"
480                     + "mMinValue=" + mMinValue
481                     + ", mMaxValue=" + mMaxValue
482                     + '}';
483         }
484     }
485 
486     /**
487      * Prepare an instance of CarPropertyConfig
488      *
489      * @return Builder<T>
490      * @hide
491      */
492     @SystemApi
493     public static <T> Builder<T> newBuilder(Class<T> type, int propertyId, int areaType,
494                                             int areaCapacity) {
495         return new Builder<>(areaCapacity, areaType, propertyId, type);
496     }
497 
498 
499     /**
500      * Prepare an instance of CarPropertyConfig
501      *
502      * @return Builder<T>
503      * @hide
504      */
505     public static <T> Builder<T> newBuilder(Class<T> type, int propertyId, int areaType) {
506         return new Builder<>(0, areaType, propertyId, type);
507     }
508 
509 
510     /**
511      * @param <T>
512      * @hide
513      * */
514     @SystemApi
515     public static class Builder<T> {
516         private int mAccess;
517         private final int mAreaType;
518         private int mChangeMode;
519         private final ArrayList<Integer> mConfigArray;
520         private String mConfigString;
521         private float mMaxSampleRate;
522         private float mMinSampleRate;
523         private final int mPropertyId;
524         private final SparseArray<AreaConfig<T>> mSupportedAreas;
525         private final Class<T> mType;
526 
527         private Builder(int areaCapacity, int areaType, int propertyId, Class<T> type) {
528             mAreaType = areaType;
529             mConfigArray = new ArrayList<>();
530             mPropertyId = propertyId;
531             if (areaCapacity != 0) {
532                 mSupportedAreas = new SparseArray<>(areaCapacity);
533             } else {
534                 mSupportedAreas = new SparseArray<>();
535             }
536             mType = type;
537         }
538 
539         /**
540          * Add supported areas parameter to CarPropertyConfig
541          *
542          * @return Builder<T>
543          */
544         public Builder<T> addAreas(int[] areaIds) {
545             for (int id : areaIds) {
546                 mSupportedAreas.put(id, null);
547             }
548             return this;
549         }
550 
551         /**
552          * Add area to CarPropertyConfig
553          *
554          * @return Builder<T>
555          */
556         public Builder<T> addArea(int areaId) {
557             return addAreaConfig(areaId, null, null);
558         }
559 
560         /**
561          * Add areaConfig to CarPropertyConfig
562          *
563          * @return Builder<T>
564          */
565         public Builder<T> addAreaConfig(int areaId, T min, T max) {
566             if (!isRangeAvailable(min, max)) {
567                 mSupportedAreas.put(areaId, null);
568             } else {
569                 mSupportedAreas.put(areaId, new AreaConfig<>(min, max));
570             }
571             return this;
572         }
573 
574         /**
575          * Set access parameter to CarPropertyConfig
576          *
577          * @return Builder<T>
578          */
579         public Builder<T> setAccess(int access) {
580             mAccess = access;
581             return this;
582         }
583 
584         /**
585          * Set changeMode parameter to CarPropertyConfig
586          *
587          * @return Builder<T>
588          */
589         public Builder<T> setChangeMode(int changeMode) {
590             mChangeMode = changeMode;
591             return this;
592         }
593 
594         /**
595          * Set configArray parameter to CarPropertyConfig
596          *
597          * @return Builder<T>
598          */
599         public Builder<T> setConfigArray(ArrayList<Integer> configArray) {
600             mConfigArray.clear();
601             mConfigArray.addAll(configArray);
602             return this;
603         }
604 
605         /**
606          * Set configString parameter to CarPropertyConfig
607          *
608          * @return Builder<T>
609          */
610         public Builder<T> setConfigString(String configString) {
611             mConfigString = configString;
612             return this;
613         }
614 
615         /**
616          * Set maxSampleRate parameter to CarPropertyConfig
617          *
618          * @return Builder<T>
619          */
620         public Builder<T> setMaxSampleRate(float maxSampleRate) {
621             mMaxSampleRate = maxSampleRate;
622             return this;
623         }
624 
625         /**
626          * Set minSampleRate parameter to CarPropertyConfig
627          *
628          * @return Builder<T>
629          */
630         public Builder<T> setMinSampleRate(float minSampleRate) {
631             mMinSampleRate = minSampleRate;
632             return this;
633         }
634 
635         /**
636          * Builds a new {@link CarPropertyConfig}.
637          */
638         public CarPropertyConfig<T> build() {
639             return new CarPropertyConfig<>(mAccess, mAreaType, mChangeMode, mConfigArray,
640                                            mConfigString, mMaxSampleRate, mMinSampleRate,
641                                            mPropertyId, mSupportedAreas, mType);
642         }
643 
644         private boolean isRangeAvailable(T min, T max) {
645             if (min == null || max == null) {
646                 return false;
647             }
648             int propertyType = mPropertyId & VehiclePropertyType.MASK;
649             switch (propertyType) {
650                 case VehiclePropertyType.INT32:
651                     return (Integer) min  != 0 || (Integer) max != 0;
652                 case VehiclePropertyType.INT64:
653                     return (Long) min != 0L || (Long) max != 0L;
654                 case VehiclePropertyType.FLOAT:
655                     return (Float) min != 0f || (Float) max != 0f;
656                 default:
657                     return false;
658             }
659         }
660     }
661 }
662