• 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 static com.android.car.internal.ExcludeFromCodeCoverageGeneratedReport.BOILERPLATE_CODE;
20 import static com.android.car.internal.util.DebugUtils.constantToString;
21 import static com.android.car.internal.util.DebugUtils.toAreaIdString;
22 
23 import android.annotation.FlaggedApi;
24 import android.annotation.IntDef;
25 import android.annotation.NonNull;
26 import android.annotation.Nullable;
27 import android.annotation.SystemApi;
28 import android.car.VehicleAreaType;
29 import android.car.VehicleAreaType.VehicleAreaTypeValue;
30 import android.car.VehiclePropertyIds;
31 import android.car.builtin.os.BuildHelper;
32 import android.car.feature.Flags;
33 import android.car.hardware.property.AreaIdConfig;
34 import android.car.hardware.property.CarPropertySimulationManager;
35 import android.os.Parcel;
36 import android.os.Parcelable;
37 import android.util.SparseArray;
38 
39 import com.android.car.internal.ExcludeFromCodeCoverageGeneratedReport;
40 
41 import java.lang.annotation.Retention;
42 import java.lang.annotation.RetentionPolicy;
43 import java.lang.reflect.Array;
44 import java.util.ArrayList;
45 import java.util.Collections;
46 import java.util.List;
47 
48 /**
49  * Represents general information about car property such as data type and min/max ranges for car
50  * areas (if applicable). This class supposed to be immutable, parcelable and could be passed over.
51  *
52  * @param <T> refer to {@link Parcel#writeValue(java.lang.Object)} to get a list of all supported
53  * types. The class should be visible to framework as default class loader is being used here.
54  *
55  */
56 public final class CarPropertyConfig<T> implements Parcelable {
57     private static final String TAG = CarPropertyConfig.class.getSimpleName();
58     private final int mAccess;
59     private final int mAreaType;
60     private final int mChangeMode;
61     private final ArrayList<Integer> mConfigArray;
62     private final String mConfigString;
63     private final float mMaxSampleRate;
64     private final float mMinSampleRate;
65     private final int mPropertyId;
66     private final List<AreaIdConfig<T>> mAreaIdConfigs;
67     private final SparseArray<AreaIdConfig<T>> mAreaIdToAreaIdConfig;
68     private final Class<T> mType;
69     private boolean mIsPropertyIdSimulationPropId;
70 
CarPropertyConfig(int access, int areaType, int changeMode, ArrayList<Integer> configArray, String configString, float maxSampleRate, float minSampleRate, int propertyId, List<AreaIdConfig<T>> areaIdConfigs, Class<T> type, boolean isPropertyIdSimulationPropId)71     private CarPropertyConfig(int access, int areaType, int changeMode,
72             ArrayList<Integer> configArray, String configString,
73             float maxSampleRate, float minSampleRate, int propertyId,
74             List<AreaIdConfig<T>> areaIdConfigs, Class<T> type,
75             boolean isPropertyIdSimulationPropId) {
76         mAccess = access;
77         mAreaType = areaType;
78         mChangeMode = changeMode;
79         mConfigArray = configArray;
80         mConfigString = configString;
81         mMaxSampleRate = maxSampleRate;
82         mMinSampleRate = minSampleRate;
83         mPropertyId = propertyId;
84         mAreaIdConfigs = areaIdConfigs;
85         mAreaIdToAreaIdConfig = generateAreaIdToAreaIdConfig(areaIdConfigs);
86         mType = type;
87         mIsPropertyIdSimulationPropId = isPropertyIdSimulationPropId;
88     }
89 
90     /** @hide */
91     @IntDef(prefix = {"VEHICLE_PROPERTY_ACCESS"}, value = {
92         VEHICLE_PROPERTY_ACCESS_NONE,
93         VEHICLE_PROPERTY_ACCESS_READ,
94         VEHICLE_PROPERTY_ACCESS_WRITE,
95         VEHICLE_PROPERTY_ACCESS_READ_WRITE
96     })
97     @Retention(RetentionPolicy.SOURCE)
98     public @interface VehiclePropertyAccessType {}
99 
100     /** Property Access Unknown */
101     public static final int VEHICLE_PROPERTY_ACCESS_NONE = 0;
102     /** The property is readable */
103     public static final int VEHICLE_PROPERTY_ACCESS_READ = 1;
104     /** The property is writable */
105     public static final int VEHICLE_PROPERTY_ACCESS_WRITE = 2;
106     /** The property is readable and writable */
107     public static final int VEHICLE_PROPERTY_ACCESS_READ_WRITE = 3;
108 
109     /** @hide */
110     @IntDef(prefix = {"VEHICLE_PROPERTY_CHANGE_MODE"}, value = {
111         VEHICLE_PROPERTY_CHANGE_MODE_STATIC,
112         VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
113         VEHICLE_PROPERTY_CHANGE_MODE_CONTINUOUS,
114     })
115     @Retention(RetentionPolicy.SOURCE)
116     public @interface VehiclePropertyChangeModeType {}
117 
118     /** Properties of this type must never be changed. */
119     public static final int VEHICLE_PROPERTY_CHANGE_MODE_STATIC = 0;
120     /** Properties of this type must report when there is a change. */
121     public static final int VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE = 1;
122     /** Properties of this type change continuously. */
123     public static final int VEHICLE_PROPERTY_CHANGE_MODE_CONTINUOUS = 2;
124 
125     /**
126      * Returns the access type of the car property.
127      * <p>The access type could be one of the following:
128      * <ul>
129      *   <li>{@link CarPropertyConfig#VEHICLE_PROPERTY_ACCESS_NONE}</li>
130      *   <li>{@link CarPropertyConfig#VEHICLE_PROPERTY_ACCESS_READ}</li>
131      *   <li>{@link CarPropertyConfig#VEHICLE_PROPERTY_ACCESS_WRITE}</li>
132      *   <li>{@link CarPropertyConfig#VEHICLE_PROPERTY_ACCESS_READ_WRITE}</li>
133      * </ul>
134      *
135      * @return the access type of the car property.
136      */
getAccess()137     public @VehiclePropertyAccessType int getAccess() {
138         return mAccess;
139     }
140 
141     /**
142      * Returns the area type of the car property.
143      * <p>The area type could be one of the following:
144      * <ul>
145      *   <li>{@link VehicleAreaType#VEHICLE_AREA_TYPE_GLOBAL}</li>
146      *   <li>{@link VehicleAreaType#VEHICLE_AREA_TYPE_WINDOW}</li>
147      *   <li>{@link VehicleAreaType#VEHICLE_AREA_TYPE_SEAT}</li>
148      *   <li>{@link VehicleAreaType#VEHICLE_AREA_TYPE_DOOR}</li>
149      *   <li>{@link VehicleAreaType#VEHICLE_AREA_TYPE_MIRROR}</li>
150      *   <li>{@link VehicleAreaType#VEHICLE_AREA_TYPE_WHEEL}</li>
151      *   <li>{@link VehicleAreaType#VEHICLE_AREA_TYPE_VENDOR}</li>
152      * </ul>
153      *
154      * @return the area type of the car property.
155      */
getAreaType()156     public @VehicleAreaTypeValue int getAreaType() {
157         return mAreaType;
158     }
159 
160     /**
161      * Returns the change mode of the car property.
162      *
163      * <p>The change mode could be one of the following:
164      * <ul>
165      *   <li>{@link CarPropertyConfig#VEHICLE_PROPERTY_CHANGE_MODE_STATIC }</li>
166      *   <li>{@link CarPropertyConfig#VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE}</li>
167      *   <li>{@link CarPropertyConfig#VEHICLE_PROPERTY_CHANGE_MODE_CONTINUOUS}</li>
168      * </ul>
169      *
170      * @return the change mode of properties.
171      */
getChangeMode()172     public @VehiclePropertyChangeModeType int getChangeMode() {
173         return mChangeMode;
174     }
175 
176     /**
177      * Returns the optional additional configuration parameters.
178      *
179      * @return Additional configuration parameters. For different properties, configArrays have
180      * different information.
181      */
182     @NonNull
getConfigArray()183     public List<Integer> getConfigArray() {
184         return Collections.unmodifiableList(mConfigArray);
185     }
186 
187     /**
188      * Returns the optional additional configuration information.
189      *
190      * @return Some properties may require additional information passed over this
191      * string. Most properties do not need to set this.
192      * @hide
193      */
getConfigString()194     public String getConfigString() {
195         return mConfigString;
196     }
197 
198     /**
199      * Returns the max sample rate in Hz.
200      *
201      * @return Max sample rate in Hz. Must be defined for {@link
202      * #VEHICLE_PROPERTY_CHANGE_MODE_CONTINUOUS} return 0 if change mode is not continuous.
203      */
getMaxSampleRate()204     public float getMaxSampleRate() {
205         return mMaxSampleRate;
206     }
207 
208     /**
209      * Returns the min sample rate in Hz.
210      *
211      * @return Min sample rate in Hz. Must be defined for {@link
212      * #VEHICLE_PROPERTY_CHANGE_MODE_CONTINUOUS} return 0 if change mode is not continuous.
213      */
getMinSampleRate()214     public float getMinSampleRate() {
215         return mMinSampleRate;
216     }
217 
218     /**
219      * Returns the property identifier.
220      *
221      * @return Property identifier, must be one of enums in
222      *   {@link android.car.VehiclePropertyIds}.
223      */
getPropertyId()224     public int getPropertyId() {
225         return mPropertyId;
226     }
227 
228     /**
229      * Returns the value type of the vehicle property.
230      * <p>The value type could be one of the following:
231      * <ul>
232      *   <li>Boolean</li>
233      *   <li>Float</li>
234      *   <li>Float[]</li>
235      *   <li>Integer</li>
236      *   <li>Integer[]</li>
237      *   <li>Long</li>
238      *   <li>Long[]</li>
239      *   <li>String</li>
240      *   <li>byte[]</li>
241      *   <li>Object[]</li>
242      * </ul>
243      *
244      * @return the value type of the vehicle property.
245      */
246     @NonNull
getPropertyType()247     public Class<T> getPropertyType() {
248         return mType;
249     }
250 
251     /**
252      * Returns a list of {@link AreaIdConfig} for this property.
253      *
254      * @return list of {@link AreaIdConfig} instances for this property.
255      */
256     @NonNull
getAreaIdConfigs()257     public List<AreaIdConfig<T>> getAreaIdConfigs() {
258         return Collections.unmodifiableList(mAreaIdConfigs);
259     }
260 
261     /**
262      * Returns the {@link AreaIdConfig} for the specified {@code areaId}.
263      *
264      * @return {@link AreaIdConfig} instance for passed {@code areaId}
265      * @throws IllegalArgumentException if {@code areaId} is not supported for property
266      */
267     @NonNull
getAreaIdConfig(int areaId)268     public AreaIdConfig<T> getAreaIdConfig(int areaId) {
269         if (!mAreaIdToAreaIdConfig.contains(areaId)) {
270             throw new IllegalArgumentException("Area ID: " + toAreaIdString(mPropertyId, areaId)
271                     + " is not supported for property ID: " + propertyIdToString());
272         }
273         return mAreaIdToAreaIdConfig.get(areaId);
274     }
275 
276     /**
277      * Returns whether this property is area type {@link VehicleAreaType#VEHICLE_AREA_TYPE_GLOBAL}.
278      *
279      * @return true if this property is area type {@link VehicleAreaType#VEHICLE_AREA_TYPE_GLOBAL}.
280      */
isGlobalProperty()281     public boolean isGlobalProperty() {
282         return mAreaType == VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL;
283     }
284 
285     /**
286      * Returns the number of areaIds for the property.
287      *
288      * @return the number of areaIds for the property.
289      * @hide
290      */
getAreaCount()291     public int getAreaCount() {
292         return mAreaIdConfigs.size();
293     }
294 
295     /**
296      * Returns a list of area IDs supported for the vehicle property.
297      *
298      * <p>An area represents a unique element of a {@link VehicleAreaType}. For instance, if the
299      * {@link VehicleAreaType} is {@link VehicleAreaType#VEHICLE_AREA_TYPE_SEAT}, then an example
300      * area is {@link android.car.VehicleAreaSeat#SEAT_ROW_1_LEFT}.
301      *
302      * <p>An area ID is a combination of one or more areas, and is created by bitwise "OR"ing the
303      * areas together. Areas from different {@link VehicleAreaType} values will not be mixed in a
304      * single area ID. For example, a {@link android.car.VehicleAreaWheel} area cannot be combined
305      * with a {@link android.car.VehicleAreaSeat} area in an area ID.
306      *
307      * <p>For properties that return {@link VehicleAreaType#VEHICLE_AREA_TYPE_GLOBAL} for {@link
308      * #getAreaType()}, they only support a single area ID of {@code 0}.
309      *
310      * <p>Rules for mapping a non {@link VehicleAreaType#VEHICLE_AREA_TYPE_GLOBAL} property to area
311      * IDs:
312      * <ul>
313      *  <li>A property is mapped to a set of area IDs that are impacted when the property value
314      *  changes.
315      *  <li>An area cannot be part of multiple area IDs, it will only be part of a single area ID.
316      *  <li>When the property value changes in one of the areas in an area ID, then it will
317      *  automatically change in all other areas in the area ID.
318      *  <li>The property value will be independently controllable in any two different area IDs.
319      * </ul>
320      *
321      * @return the array of supported area IDs.
322      */
323     @NonNull
getAreaIds()324     public int[] getAreaIds() {
325         int[] areaIds = new int[mAreaIdConfigs.size()];
326         for (int i = 0; i < areaIds.length; i++) {
327             areaIds[i] = mAreaIdConfigs.get(i).getAreaId();
328         }
329         return areaIds;
330     }
331 
332     /**
333      * Returns whether the propertyId is Simulation Property Id.
334      *
335      * <p>Simulation property is a property which is used by car service and vehicle hardware but
336      * is not defined in {@link android.car.VehiclePropertyIds}
337      *
338      * @return {@code true} when returned from
339      * {@link CarPropertySimulationManager#startRecordingVehicleProperties} {@code false} otherwise.
340      *
341      * @hide
342      */
343     @SystemApi
344     @FlaggedApi(Flags.FLAG_CAR_PROPERTY_SIMULATION)
isPropertyIdSimulationPropId()345     public boolean isPropertyIdSimulationPropId() {
346         if (!BuildHelper.isDebuggableBuild()) {
347             throw new IllegalStateException("Build is not eng or user-debug");
348         }
349         return mIsPropertyIdSimulationPropId;
350     }
351 
352     /**
353      * @return  the first areaId.
354      * Throws {@link java.lang.IllegalStateException} if supported area count not equals to one.
355      * @hide
356      */
getFirstAndOnlyAreaId()357     public int getFirstAndOnlyAreaId() {
358         if (mAreaIdConfigs.size() != 1) {
359             throw new IllegalStateException("Expected one and only area in this property. PropId: "
360                     + propertyIdToString());
361         }
362         return mAreaIdConfigs.get(0).getAreaId();
363     }
364 
propertyIdToString()365     private String propertyIdToString() {
366         if (Flags.carPropertySimulation()) {
367             if (isPropertyIdSimulationPropId()) {
368                 return "0x" + Integer.toHexString(mPropertyId);
369             }
370         }
371         return VehiclePropertyIds.toString(mPropertyId);
372     }
373 
374     /**
375      * Verify if the areaId passed as a parameter exists.
376      * @hide
377      */
hasArea(int areaId)378     public boolean hasArea(int areaId) {
379         return mAreaIdToAreaIdConfig.indexOfKey(areaId) >= 0;
380     }
381 
382     /**
383      * @deprecated - use {@link #getAreaIdConfigs()} or {@link #getAreaIdConfig(int)} instead.
384      *
385      * @param areaId the area ID
386      * @return min value in given areaId. Null if not have min value in given area
387      */
388     @Deprecated
389     @Nullable
getMinValue(int areaId)390     public T getMinValue(int areaId) {
391         AreaIdConfig<T> areaIdConfig = mAreaIdToAreaIdConfig.get(areaId);
392         return areaIdConfig == null ? null : areaIdConfig.getMinValue();
393     }
394 
395     /**
396      * @deprecated - use {@link #getAreaIdConfigs()} or {@link #getAreaIdConfig(int)} instead.
397      *
398      * @param areaId the area ID
399      * @return max value in given areaId. Null if not have max value in given area
400      */
401     @Deprecated
402     @Nullable
getMaxValue(int areaId)403     public T getMaxValue(int areaId) {
404         AreaIdConfig<T> areaIdConfig = mAreaIdToAreaIdConfig.get(areaId);
405         return areaIdConfig == null ? null : areaIdConfig.getMaxValue();
406     }
407 
408     /**
409      * @deprecated - use {@link #getAreaIdConfigs()} or {@link #getAreaIdConfig(int)} instead.
410      *
411      * @return Min value in areaId 0. Null if not have min value.
412      */
413     @Deprecated
414     @Nullable
getMinValue()415     public T getMinValue() {
416         AreaIdConfig<T> areaIdConfig = mAreaIdToAreaIdConfig.get(0);
417         return areaIdConfig == null ? null : areaIdConfig.getMinValue();
418     }
419 
420     /**
421      * @deprecated - use {@link #getAreaIdConfigs()} or {@link #getAreaIdConfig(int)} instead.
422      *
423      * @return Max value in areaId 0. Null if not have max value.
424      */
425     @Deprecated
426     @Nullable
getMaxValue()427     public T getMaxValue() {
428         AreaIdConfig<T> areaIdConfig = mAreaIdToAreaIdConfig.get(0);
429         return areaIdConfig == null ? null : areaIdConfig.getMaxValue();
430     }
431 
432     @Override
433     @ExcludeFromCodeCoverageGeneratedReport(reason = BOILERPLATE_CODE)
describeContents()434     public int describeContents() {
435         return 0;
436     }
437 
438     @Override
writeToParcel(Parcel dest, int flags)439     public void writeToParcel(Parcel dest, int flags) {
440         dest.writeInt(mAccess);
441         dest.writeInt(mAreaType);
442         dest.writeInt(mChangeMode);
443         dest.writeInt(mConfigArray.size());
444         for (int i = 0; i < mConfigArray.size(); i++) {
445             dest.writeInt(mConfigArray.get(i));
446         }
447         dest.writeString(mConfigString);
448         dest.writeFloat(mMaxSampleRate);
449         dest.writeFloat(mMinSampleRate);
450         dest.writeInt(mPropertyId);
451         dest.writeList(mAreaIdConfigs);
452         dest.writeString(mType.getName());
453     }
454 
455     @SuppressWarnings("unchecked")
CarPropertyConfig(Parcel in)456     private CarPropertyConfig(Parcel in) {
457         mAccess = in.readInt();
458         mAreaType = in.readInt();
459         mChangeMode = in.readInt();
460         int configArraySize = in.readInt();
461         mConfigArray = new ArrayList<Integer>(configArraySize);
462         for (int i = 0; i < configArraySize; i++) {
463             mConfigArray.add(in.readInt());
464         }
465         mConfigString = in.readString();
466         mMaxSampleRate = in.readFloat();
467         mMinSampleRate = in.readFloat();
468         mPropertyId = in.readInt();
469         mAreaIdConfigs = in.readArrayList(getClass().getClassLoader());
470         mAreaIdToAreaIdConfig = generateAreaIdToAreaIdConfig(mAreaIdConfigs);
471         String className = in.readString();
472         try {
473             mType = (Class<T>) Class.forName(className);
474         } catch (ClassNotFoundException e) {
475             throw new IllegalArgumentException("Class not found: " + className, e);
476         }
477     }
478 
479     public static final Creator<CarPropertyConfig> CREATOR = new Creator<CarPropertyConfig>() {
480         @Override
481         public CarPropertyConfig createFromParcel(Parcel in) {
482             return new CarPropertyConfig(in);
483         }
484 
485         @Override
486         public CarPropertyConfig[] newArray(int size) {
487             return new CarPropertyConfig[size];
488         }
489     };
490 
491     /** @hide */
492     @Override
toString()493     public String toString() {
494         String configString = "CarPropertyConfig{"
495                 + "mPropertyId=" + propertyIdToString()
496                 + ", mAccess=" + constantToString(CarPropertyConfig.class,
497                 "VEHICLE_PROPERTY_ACCESS_", mAccess)
498                 + ", mAreaType=" + constantToString(VehicleAreaType.class, "VEHICLE_AREA_TYPE_",
499                 mAreaType)
500                 + ", mChangeMode=" + constantToString(CarPropertyConfig.class,
501                 "VEHICLE_PROPERTY_CHANGE_MODE_", mChangeMode)
502                 + ", mConfigArray=" + mConfigArray
503                 + ", mConfigString=" + mConfigString
504                 + ", mMaxSampleRate(Hz)=" + mMaxSampleRate
505                 + ", mMinSampleRate(Hz)=" + mMinSampleRate
506                 + ", mAreaIdConfigs =" + mAreaIdConfigs.stream().map(
507                     areaIdConfig -> areaIdConfig.toString(mPropertyId)).toList()
508                 + ", mType=" + mType;
509         if (Flags.carPropertySimulation()) {
510             if (isPropertyIdSimulationPropId()) {
511                 return configString
512                         + ", mIsPropertyIdSimulationPropId=" + mIsPropertyIdSimulationPropId
513                         + '}';
514             }
515         }
516         return configString + '}';
517     }
518 
519     /**
520      * Represents min/max value of car property.
521      *
522      * @param <T> The property type
523      * @hide
524      * @deprecated This API is deprecated in favor of {@link
525      * android.car.hardware.property.AreaIdConfig} which allows properties to specify which enum
526      * values are supported. This API will be marked as {@code @removed} in the next major release
527      * and hard removed in the release after that.
528      */
529     @Deprecated
530     public static class AreaConfig<T> implements Parcelable {
531         @Nullable private final T mMinValue;
532         @Nullable private final T mMaxValue;
533 
534         @SuppressWarnings("unused")
AreaConfig(T minValue, T maxValue)535         private AreaConfig(T minValue, T maxValue) {
536             mMinValue = minValue;
537             mMaxValue = maxValue;
538         }
539 
540         public static final Parcelable.Creator<AreaConfig<Object>> CREATOR =
541                 getCreator(Object.class);
542 
getCreator(final Class<E> clazz)543         private static <E> Parcelable.Creator<AreaConfig<E>> getCreator(final Class<E> clazz) {
544             return new Creator<AreaConfig<E>>() {
545                 @Override
546                 public AreaConfig<E> createFromParcel(Parcel source) {
547                     return new AreaConfig<>(source);
548                 }
549 
550                 @Override @SuppressWarnings("unchecked")
551                 public AreaConfig<E>[] newArray(int size) {
552                     return (AreaConfig<E>[]) Array.newInstance(clazz, size);
553                 }
554             };
555         }
556 
557         @SuppressWarnings("unchecked")
AreaConfig(Parcel in)558         private AreaConfig(Parcel in) {
559             mMinValue = (T) in.readValue(getClass().getClassLoader());
560             mMaxValue = (T) in.readValue(getClass().getClassLoader());
561         }
562 
getMinValue()563         @Nullable public T getMinValue() {
564             return mMinValue;
565         }
566 
getMaxValue()567         @Nullable public T getMaxValue() {
568             return mMaxValue;
569         }
570 
571         @Override
describeContents()572         public int describeContents() {
573             return 0;
574         }
575 
576         @Override
writeToParcel(Parcel dest, int flags)577         public void writeToParcel(Parcel dest, int flags) {
578             dest.writeValue(mMinValue);
579             dest.writeValue(mMaxValue);
580         }
581 
582         @Override
toString()583         public String toString() {
584             return "CarAreaConfig{"
585                     + "mMinValue=" + mMinValue
586                     + ", mMaxValue=" + mMaxValue
587                     + '}';
588         }
589     }
590 
591     /**
592      * Prepare an instance of {@link CarPropertyConfig}
593      *
594      * @return Builder<T>
595      * @hide
596      * @deprecated marked as deprecated because clients should not have direct access to the
597      * CarPropertyConfig.Builder class
598      */
599     @Deprecated
600     @SystemApi
601     public static <T> Builder<T> newBuilder(Class<T> type, int propertyId, int areaType,
602                                             int areaCapacity) {
603         return new Builder<>(areaType, propertyId, type);
604     }
605 
606 
607     /**
608      * Prepare an instance of {@link CarPropertyConfig}
609      *
610      * @return Builder<T>
611      * @hide
612      */
613     public static <T> Builder<T> newBuilder(Class<T> type, int propertyId, int areaType) {
614         return new Builder<>(areaType, propertyId, type);
615     }
616 
617 
618     /**
619      * Builder for making new {@code CarPropertyConfig} objects.
620      *
621      * @param <T>
622      * @hide
623      * @deprecated marked as deprecated because clients should not have direct access to the
624      * CarPropertyConfig.Builder class
625      */
626     @Deprecated
627     @SystemApi
628     public static class Builder<T> {
629         private int mAccess = VEHICLE_PROPERTY_ACCESS_NONE;
630         private final int mAreaType;
631         private int mChangeMode;
632         private final ArrayList<Integer> mConfigArray = new ArrayList<>();
633         private String mConfigString;
634         private float mMaxSampleRate;
635         private float mMinSampleRate;
636         private final int mPropertyId;
637         private final List<AreaIdConfig<T>> mAreaIdConfigs = new ArrayList<>();
638         private final Class<T> mType;
639         private boolean mIsPropertyIdSimulationPropId;
640 
641         private Builder(int areaType, int propertyId, Class<T> type) {
642             mAreaType = areaType;
643             mPropertyId = propertyId;
644             mType = type;
645         }
646 
647         /**
648          * Add supported areas parameter to {@link CarPropertyConfig}
649          *
650          * <p>This function uses the access set in the builder to define the area ID's access level.
651          * Make sure to call {@link CarPropertyConfig.Builder#setAccess(int)} before calling this
652          * function.
653          *
654          * @return Builder<T>
655          * @removed - use {@link #addAreaIdConfig(AreaIdConfig)} instead.
656          */
657         @Deprecated
658         public Builder<T> addAreas(int[] areaIds) {
659             for (int areaId : areaIds) {
660                 AreaIdConfig.Builder<T> areaIdConfigBuilder = Flags.areaIdConfigAccess()
661                         ? new AreaIdConfig.Builder<T>(mAccess, areaId)
662                         : new AreaIdConfig.Builder<T>(areaId);
663                 mAreaIdConfigs.add(areaIdConfigBuilder.build());
664             }
665             return this;
666         }
667 
668         /**
669          * Add {@code areaId} to {@link CarPropertyConfig}
670          *
671          * <p>This function uses the access set in the builder to define the area's access level.
672          * Make sure to call {@link CarPropertyConfig.Builder#setAccess(int)} before calling this
673          * function.
674          *
675          * @return Builder<T>
676          * @removed - use {@link #addAreaIdConfig(AreaIdConfig)} instead.
677          */
678         @Deprecated
679         public Builder<T> addArea(int areaId) {
680             AreaIdConfig.Builder<T> areaIdConfigBuilder = Flags.areaIdConfigAccess()
681                     ? new AreaIdConfig.Builder<T>(mAccess, areaId)
682                     : new AreaIdConfig.Builder<T>(areaId);
683             mAreaIdConfigs.add(areaIdConfigBuilder.build());
684             return this;
685         }
686 
687         /**
688          * Add {@code areaConfig} to {@link CarPropertyConfig}
689          *
690          * <p>This function uses the access set in the builder to define the area's access level.
691          * Make sure to call {@link CarPropertyConfig.Builder#setAccess(int)} before calling this
692          * function.
693          *
694          * @return Builder<T>
695          * @removed - use {@link #addAreaIdConfig(AreaIdConfig)} instead.
696          */
697         @Deprecated
698         public Builder<T> addAreaConfig(int areaId, T min, T max) {
699             AreaIdConfig.Builder<T> areaIdConfigBuilder = Flags.areaIdConfigAccess()
700                     ? new AreaIdConfig.Builder<T>(mAccess, areaId)
701                     : new AreaIdConfig.Builder<T>(areaId);
702             mAreaIdConfigs.add(areaIdConfigBuilder.setMinValue(min).setMaxValue(max).build());
703             return this;
704         }
705 
706         /**
707          * Add {@link AreaIdConfig} to {@link CarPropertyConfig}.
708          *
709          * @return Builder<T>
710          */
711         @NonNull
712         public Builder<T> addAreaIdConfig(@NonNull AreaIdConfig<T> areaIdConfig) {
713             mAreaIdConfigs.add(areaIdConfig);
714             return this;
715         }
716 
717 
718         /**
719          * Set {@code access} parameter to {@link CarPropertyConfig}
720          *
721          * @return Builder<T>
722          */
723         public Builder<T> setAccess(int access) {
724             mAccess = access;
725             return this;
726         }
727 
728         /**
729          * Set {@code changeMode} parameter to {@link CarPropertyConfig}
730          *
731          * @return Builder<T>
732          */
733         public Builder<T> setChangeMode(int changeMode) {
734             mChangeMode = changeMode;
735             return this;
736         }
737 
738         /**
739          * Set {@code configArray} parameter to {@link CarPropertyConfig}
740          *
741          * @return Builder<T>
742          */
743         public Builder<T> setConfigArray(ArrayList<Integer> configArray) {
744             mConfigArray.clear();
745             mConfigArray.addAll(configArray);
746             return this;
747         }
748 
749         /**
750          * Set {@code configString} parameter to {@link CarPropertyConfig}
751          *
752          * @return Builder<T>
753          */
754         public Builder<T> setConfigString(String configString) {
755             mConfigString = configString;
756             return this;
757         }
758 
759         /**
760          * Set {@code maxSampleRate} parameter to {@link CarPropertyConfig}
761          *
762          * @return Builder<T>
763          */
764         public Builder<T> setMaxSampleRate(float maxSampleRate) {
765             mMaxSampleRate = maxSampleRate;
766             return this;
767         }
768 
769         /**
770          * Set {@code minSampleRate} parameter to {@link CarPropertyConfig}
771          *
772          * @return Builder<T>
773          */
774         public Builder<T> setMinSampleRate(float minSampleRate) {
775             mMinSampleRate = minSampleRate;
776             return this;
777         }
778 
779         /**
780          * Set whether property Id is Simulation.
781          *
782          * @return Builder
783          */
784         public Builder<T> setPropertyIdIsSimulationPropId(boolean isSimulationPropId) {
785             mIsPropertyIdSimulationPropId = isSimulationPropId;
786             return this;
787         }
788 
789         /**
790          * Builds a new {@link CarPropertyConfig}.
791          */
792         public CarPropertyConfig<T> build() {
793             return new CarPropertyConfig<>(mAccess, mAreaType, mChangeMode, mConfigArray,
794                                            mConfigString, mMaxSampleRate, mMinSampleRate,
795                                            mPropertyId, mAreaIdConfigs, mType,
796                                            mIsPropertyIdSimulationPropId);
797         }
798     }
799 
800     private static <U> SparseArray<AreaIdConfig<U>> generateAreaIdToAreaIdConfig(
801             List<AreaIdConfig<U>> areaIdConfigs) {
802         SparseArray<AreaIdConfig<U>> areaIdToAreaIdConfig = new SparseArray<>(areaIdConfigs.size());
803         for (int i = 0; i < areaIdConfigs.size(); i++) {
804             AreaIdConfig<U> areaIdConfig = areaIdConfigs.get(i);
805             areaIdToAreaIdConfig.put(areaIdConfig.getAreaId(), areaIdConfig);
806         }
807         return areaIdToAreaIdConfig;
808     }
809 }
810