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