xref: /aosp_15_r20/cts/tests/tests/car/src/android/car/cts/CarPropertyManagerTest.java (revision b7c941bb3fa97aba169d73cee0bed2de8ac964bf)
1 /*
2  * Copyright (C) 2019 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.cts;
18 
19 import static android.Manifest.permission.ACCESS_FINE_LOCATION;
20 import static android.car.VehicleAreaSeat.SEAT_ROW_1_LEFT;
21 import static android.car.VehicleAreaSeat.SEAT_ROW_1_RIGHT;
22 import static android.car.cts.utils.ShellPermissionUtils.runWithShellPermissionIdentity;
23 import static android.car.cts.utils.VehiclePropertyVerifiers.getHvacAcOnVerifierBuilder;
24 import static android.car.cts.utils.VehiclePropertyVerifiers.getHvacActualFanSpeedRpmVerifierBuilder;
25 import static android.car.cts.utils.VehiclePropertyVerifiers.getHvacAutoOnVerifierBuilder;
26 import static android.car.cts.utils.VehiclePropertyVerifiers.getHvacAutoRecircOnVerifierBuilder;
27 import static android.car.cts.utils.VehiclePropertyVerifiers.getHvacDefrosterVerifierBuilder;
28 import static android.car.cts.utils.VehiclePropertyVerifiers.getHvacDualOnVerifierBuilder;
29 import static android.car.cts.utils.VehiclePropertyVerifiers.getHvacFanDirectionAvailableVerifierBuilder;
30 import static android.car.cts.utils.VehiclePropertyVerifiers.getHvacFanDirectionVerifierBuilder;
31 import static android.car.cts.utils.VehiclePropertyVerifiers.getHvacFanSpeedVerifierBuilder;
32 import static android.car.cts.utils.VehiclePropertyVerifiers.getHvacMaxAcOnVerifierBuilder;
33 import static android.car.cts.utils.VehiclePropertyVerifiers.getHvacMaxDefrostOnVerifierBuilder;
34 import static android.car.cts.utils.VehiclePropertyVerifiers.getHvacPowerOnVerifierBuilder;
35 import static android.car.cts.utils.VehiclePropertyVerifiers.getHvacRecircOnVerifierBuilder;
36 import static android.car.cts.utils.VehiclePropertyVerifiers.getHvacSeatTemperatureVerifierBuilder;
37 import static android.car.cts.utils.VehiclePropertyVerifiers.getHvacSeatVentilationVerifierBuilder;
38 import static android.car.cts.utils.VehiclePropertyVerifiers.getHvacSideMirrorHeatVerifierBuilder;
39 import static android.car.cts.utils.VehiclePropertyVerifiers.getHvacSteeringWheelHeatVerifierBuilder;
40 import static android.car.cts.utils.VehiclePropertyVerifiers.getHvacTemperatureCurrentVerifierBuilder;
41 import static android.car.cts.utils.VehiclePropertyVerifiers.getHvacTemperatureDisplayUnitsVerifierBuilder;
42 import static android.car.cts.utils.VehiclePropertyVerifiers.getHvacTemperatureSetVerifierBuilder;
43 import static android.car.cts.utils.VehiclePropertyVerifiers.getHvacTemperatureValueSuggestionVerifierBuilder;
44 import static android.car.cts.utils.VehiclePropertyVerifiers.getLocationCharacterizationVerifierBuilder;
45 import static android.car.cts.utils.VehiclePropertyVerifiers.getPerfSteeringAngleVerifierBuilder;
46 import static android.car.hardware.property.CarPropertyManager.GetPropertyResult;
47 import static android.car.hardware.property.CarPropertyManager.SetPropertyResult;
48 
49 import static com.google.common.truth.Truth.assertThat;
50 import static com.google.common.truth.Truth.assertWithMessage;
51 
52 import static org.junit.Assert.assertThrows;
53 import static org.junit.Assume.assumeFalse;
54 import static org.junit.Assume.assumeTrue;
55 
56 import android.car.Car;
57 import android.car.FuelType;
58 import android.car.GsrComplianceType;
59 import android.car.PortLocationType;
60 import android.car.VehicleAreaSeat;
61 import android.car.VehicleAreaType;
62 import android.car.VehicleAreaWheel;
63 import android.car.VehicleGear;
64 import android.car.VehicleIgnitionState;
65 import android.car.VehiclePropertyIds;
66 import android.car.VehicleUnit;
67 import android.car.cts.property.CarSvcPropsParser;
68 import android.car.cts.utils.VehiclePropertyVerifier;
69 import android.car.cts.utils.VehiclePropertyVerifiers;
70 import android.car.feature.Flags;
71 import android.car.hardware.CarPropertyConfig;
72 import android.car.hardware.CarPropertyValue;
73 import android.car.hardware.property.AreaIdConfig;
74 import android.car.hardware.property.AutomaticEmergencyBrakingState;
75 import android.car.hardware.property.BlindSpotWarningState;
76 import android.car.hardware.property.CarPropertyManager;
77 import android.car.hardware.property.CarPropertyManager.CarPropertyEventCallback;
78 import android.car.hardware.property.CrossTrafficMonitoringWarningState;
79 import android.car.hardware.property.CruiseControlCommand;
80 import android.car.hardware.property.CruiseControlState;
81 import android.car.hardware.property.CruiseControlType;
82 import android.car.hardware.property.DriverDistractionState;
83 import android.car.hardware.property.DriverDistractionWarning;
84 import android.car.hardware.property.DriverDrowsinessAttentionState;
85 import android.car.hardware.property.DriverDrowsinessAttentionWarning;
86 import android.car.hardware.property.ElectronicStabilityControlState;
87 import android.car.hardware.property.EmergencyLaneKeepAssistState;
88 import android.car.hardware.property.ErrorState;
89 import android.car.hardware.property.EvChargeState;
90 import android.car.hardware.property.EvChargingConnectorType;
91 import android.car.hardware.property.EvRegenerativeBrakingState;
92 import android.car.hardware.property.EvStoppingMode;
93 import android.car.hardware.property.ForwardCollisionWarningState;
94 import android.car.hardware.property.HandsOnDetectionDriverState;
95 import android.car.hardware.property.HandsOnDetectionWarning;
96 import android.car.hardware.property.ImpactSensorLocation;
97 import android.car.hardware.property.LaneCenteringAssistCommand;
98 import android.car.hardware.property.LaneCenteringAssistState;
99 import android.car.hardware.property.LaneDepartureWarningState;
100 import android.car.hardware.property.LaneKeepAssistState;
101 import android.car.hardware.property.LowSpeedAutomaticEmergencyBrakingState;
102 import android.car.hardware.property.LowSpeedCollisionWarningState;
103 import android.car.hardware.property.PropertyNotAvailableException;
104 import android.car.hardware.property.Subscription;
105 import android.car.hardware.property.TrailerState;
106 import android.car.hardware.property.VehicleAirbagLocation;
107 import android.car.hardware.property.VehicleAutonomousState;
108 import android.car.hardware.property.VehicleElectronicTollCollectionCardStatus;
109 import android.car.hardware.property.VehicleElectronicTollCollectionCardType;
110 import android.car.hardware.property.VehicleLightState;
111 import android.car.hardware.property.VehicleLightSwitch;
112 import android.car.hardware.property.VehicleOilLevel;
113 import android.car.hardware.property.VehicleTurnSignal;
114 import android.car.hardware.property.VehicleVendorPermission;
115 import android.car.hardware.property.WindshieldWipersState;
116 import android.car.hardware.property.WindshieldWipersSwitch;
117 import android.os.Build;
118 import android.os.SystemClock;
119 import android.platform.test.annotations.AppModeFull;
120 import android.platform.test.annotations.RequiresDevice;
121 import android.platform.test.annotations.RequiresFlagsDisabled;
122 import android.platform.test.annotations.RequiresFlagsEnabled;
123 import android.util.ArraySet;
124 import android.util.Log;
125 import android.util.SparseArray;
126 
127 import androidx.annotation.GuardedBy;
128 import androidx.annotation.NonNull;
129 import androidx.annotation.Nullable;
130 import androidx.test.filters.LargeTest;
131 
132 import com.android.bedstead.nene.TestApis;
133 import com.android.bedstead.permissions.PermissionContext;
134 import com.android.compatibility.common.util.ApiTest;
135 import com.android.compatibility.common.util.CddTest;
136 
137 import com.google.common.collect.ImmutableList;
138 import com.google.common.collect.ImmutableSet;
139 import com.google.common.collect.Range;
140 import com.google.testing.junit.testparameterinjector.TestParameter;
141 import com.google.testing.junit.testparameterinjector.TestParameterInjector;
142 import com.google.testing.junit.testparameterinjector.TestParameterValuesProvider;
143 
144 import org.junit.Assert;
145 import org.junit.Before;
146 import org.junit.Test;
147 import org.junit.runner.RunWith;
148 
149 import java.lang.reflect.Field;
150 import java.lang.reflect.Modifier;
151 import java.time.Year;
152 import java.util.ArrayList;
153 import java.util.Arrays;
154 import java.util.Collection;
155 import java.util.List;
156 import java.util.Objects;
157 import java.util.Set;
158 import java.util.concurrent.CountDownLatch;
159 import java.util.concurrent.Executor;
160 import java.util.concurrent.Executors;
161 import java.util.concurrent.TimeUnit;
162 import java.util.concurrent.atomic.AtomicBoolean;
163 import java.util.stream.Collectors;
164 
165 @LargeTest
166 @RequiresDevice
167 @RunWith(TestParameterInjector.class)
168 @AppModeFull(reason = "Instant apps cannot get car related permissions.")
169 public final class CarPropertyManagerTest extends AbstractCarTestCase {
170 
171     private static final String TAG = CarPropertyManagerTest.class.getSimpleName();
172 
173     private static final int VEHICLE_PROPERTY_GROUP_MASK = 0xf0000000;
174     private static final int VEHICLE_PROPERTY_GROUP_SYSTEM = 0x10000000;
175     private static final int VEHICLE_PROPERTY_GROUP_VENDOR = 0x20000000;
176 
177     private static final long WAIT_CALLBACK = 1500L;
178     private static final int NO_EVENTS = 0;
179     private static final int ONCHANGE_RATE_EVENT_COUNTER = 1;
180     private static final int UI_RATE_EVENT_COUNTER = 5;
181     private static final int FAST_OR_FASTEST_EVENT_COUNTER = 10;
182     private static final int SECONDS_TO_MILLIS = 1_000;
183     private static final long ASYNC_WAIT_TIMEOUT_IN_SEC = 15;
184     private static final int REASONABLE_FUTURE_MODEL_YEAR_OFFSET = 5;
185     private static final int REASONABLE_PAST_MODEL_YEAR_OFFSET = -10;
186     private static final ImmutableSet<Integer> PORT_LOCATION_TYPES =
187             ImmutableSet.<Integer>builder()
188                     .add(
189                             PortLocationType.UNKNOWN,
190                             PortLocationType.FRONT_LEFT,
191                             PortLocationType.FRONT_RIGHT,
192                             PortLocationType.REAR_RIGHT,
193                             PortLocationType.REAR_LEFT,
194                             PortLocationType.FRONT,
195                             PortLocationType.REAR)
196                     .build();
197     private static final ImmutableSet<Integer> VEHICLE_GEARS =
198             ImmutableSet.<Integer>builder()
199                     .add(
200                             VehicleGear.GEAR_UNKNOWN,
201                             VehicleGear.GEAR_NEUTRAL,
202                             VehicleGear.GEAR_REVERSE,
203                             VehicleGear.GEAR_PARK,
204                             VehicleGear.GEAR_DRIVE,
205                             VehicleGear.GEAR_FIRST,
206                             VehicleGear.GEAR_SECOND,
207                             VehicleGear.GEAR_THIRD,
208                             VehicleGear.GEAR_FOURTH,
209                             VehicleGear.GEAR_FIFTH,
210                             VehicleGear.GEAR_SIXTH,
211                             VehicleGear.GEAR_SEVENTH,
212                             VehicleGear.GEAR_EIGHTH,
213                             VehicleGear.GEAR_NINTH)
214                     .build();
215     private static final ImmutableSet<Integer> TRAILER_STATES =
216             ImmutableSet.<Integer>builder()
217                     .add(
218                             TrailerState.STATE_UNKNOWN,
219                             TrailerState.STATE_NOT_PRESENT,
220                             TrailerState.STATE_PRESENT,
221                             TrailerState.STATE_ERROR)
222                     .build();
223     private static final ImmutableSet<Integer> DISTANCE_DISPLAY_UNITS =
224             ImmutableSet.<Integer>builder().add(VehicleUnit.MILLIMETER, VehicleUnit.METER,
225                     VehicleUnit.KILOMETER, VehicleUnit.MILE).build();
226     private static final ImmutableSet<Integer> VOLUME_DISPLAY_UNITS =
227             ImmutableSet.<Integer>builder().add(VehicleUnit.MILLILITER, VehicleUnit.LITER,
228                     VehicleUnit.US_GALLON, VehicleUnit.IMPERIAL_GALLON).build();
229     private static final ImmutableSet<Integer> PRESSURE_DISPLAY_UNITS =
230             ImmutableSet.<Integer>builder().add(VehicleUnit.KILOPASCAL, VehicleUnit.PSI,
231                     VehicleUnit.BAR).build();
232     private static final ImmutableSet<Integer> BATTERY_DISPLAY_UNITS =
233             ImmutableSet.<Integer>builder().add(VehicleUnit.WATT_HOUR, VehicleUnit.AMPERE_HOURS,
234                     VehicleUnit.KILOWATT_HOUR).build();
235     private static final ImmutableSet<Integer> SPEED_DISPLAY_UNITS =
236             ImmutableSet.<Integer>builder().add(VehicleUnit.METER_PER_SEC,
237                     VehicleUnit.MILES_PER_HOUR, VehicleUnit.KILOMETERS_PER_HOUR).build();
238     private static final ImmutableSet<Integer> TURN_SIGNAL_STATES =
239             ImmutableSet.<Integer>builder().add(VehicleTurnSignal.STATE_NONE,
240                     VehicleTurnSignal.STATE_RIGHT, VehicleTurnSignal.STATE_LEFT).build();
241     private static final ImmutableSet<Integer> VEHICLE_LIGHT_STATES =
242             ImmutableSet.<Integer>builder().add(VehicleLightState.STATE_OFF,
243                     VehicleLightState.STATE_ON, VehicleLightState.STATE_DAYTIME_RUNNING).build();
244     private static final ImmutableSet<Integer> VEHICLE_LIGHT_SWITCHES =
245             ImmutableSet.<Integer>builder().add(VehicleLightSwitch.STATE_OFF,
246                     VehicleLightSwitch.STATE_ON, VehicleLightSwitch.STATE_DAYTIME_RUNNING,
247                     VehicleLightSwitch.STATE_AUTOMATIC).build();
248     private static final ImmutableSet<Integer> VEHICLE_OIL_LEVELS =
249             ImmutableSet.<Integer>builder()
250                     .add(
251                             VehicleOilLevel.LEVEL_CRITICALLY_LOW,
252                             VehicleOilLevel.LEVEL_LOW,
253                             VehicleOilLevel.LEVEL_NORMAL,
254                             VehicleOilLevel.LEVEL_HIGH,
255                             VehicleOilLevel.LEVEL_ERROR)
256                     .build();
257     private static final ImmutableSet<Integer> WINDSHIELD_WIPERS_STATES =
258             ImmutableSet.<Integer>builder()
259                     .add(
260                             WindshieldWipersState.OTHER,
261                             WindshieldWipersState.OFF,
262                             WindshieldWipersState.ON,
263                             WindshieldWipersState.SERVICE)
264                     .build();
265     private static final ImmutableSet<Integer> WINDSHIELD_WIPERS_SWITCHES =
266             ImmutableSet.<Integer>builder()
267                     .add(
268                             WindshieldWipersSwitch.OTHER,
269                             WindshieldWipersSwitch.OFF,
270                             WindshieldWipersSwitch.MIST,
271                             WindshieldWipersSwitch.INTERMITTENT_LEVEL_1,
272                             WindshieldWipersSwitch.INTERMITTENT_LEVEL_2,
273                             WindshieldWipersSwitch.INTERMITTENT_LEVEL_3,
274                             WindshieldWipersSwitch.INTERMITTENT_LEVEL_4,
275                             WindshieldWipersSwitch.INTERMITTENT_LEVEL_5,
276                             WindshieldWipersSwitch.CONTINUOUS_LEVEL_1,
277                             WindshieldWipersSwitch.CONTINUOUS_LEVEL_2,
278                             WindshieldWipersSwitch.CONTINUOUS_LEVEL_3,
279                             WindshieldWipersSwitch.CONTINUOUS_LEVEL_4,
280                             WindshieldWipersSwitch.CONTINUOUS_LEVEL_5,
281                             WindshieldWipersSwitch.AUTO,
282                             WindshieldWipersSwitch.SERVICE)
283                     .build();
284     private static final ImmutableSet<Integer> EV_STOPPING_MODES =
285             ImmutableSet.<Integer>builder().add(EvStoppingMode.STATE_OTHER,
286                     EvStoppingMode.STATE_CREEP, EvStoppingMode.STATE_ROLL,
287                     EvStoppingMode.STATE_HOLD).build();
288 
289     private static final ImmutableSet<Integer> VEHICLE_AUTONOMOUS_STATES =
290             ImmutableSet.<Integer>builder()
291                     .add(
292                             VehicleAutonomousState.LEVEL_0,
293                             VehicleAutonomousState.LEVEL_1,
294                             VehicleAutonomousState.LEVEL_2,
295                             VehicleAutonomousState.LEVEL_3,
296                             VehicleAutonomousState.LEVEL_4,
297                             VehicleAutonomousState.LEVEL_5)
298                     .build();
299     private static final ImmutableSet<Integer> VEHICLE_AIRBAG_LOCATIONS =
300             ImmutableSet.<Integer>builder()
301                     .add(
302                             VehicleAirbagLocation.FRONT,
303                             VehicleAirbagLocation.KNEE,
304                             VehicleAirbagLocation.LEFT_SIDE,
305                             VehicleAirbagLocation.RIGHT_SIDE,
306                             VehicleAirbagLocation.CURTAIN)
307                     .build();
308     private static final ImmutableSet<Integer> IMPACT_SENSOR_LOCATIONS =
309             ImmutableSet.<Integer>builder()
310                     .add(
311                             ImpactSensorLocation.FRONT,
312                             ImpactSensorLocation.FRONT_LEFT_DOOR_SIDE,
313                             ImpactSensorLocation.FRONT_RIGHT_DOOR_SIDE,
314                             ImpactSensorLocation.REAR_LEFT_DOOR_SIDE,
315                             ImpactSensorLocation.REAR_RIGHT_DOOR_SIDE,
316                             ImpactSensorLocation.REAR)
317                     .build();
318     private static final ImmutableSet<Integer> EMERGENCY_LANE_KEEP_ASSIST_STATES =
319             ImmutableSet.<Integer>builder()
320                     .add(
321                             EmergencyLaneKeepAssistState.OTHER,
322                             EmergencyLaneKeepAssistState.ENABLED,
323                             EmergencyLaneKeepAssistState.WARNING_LEFT,
324                             EmergencyLaneKeepAssistState.WARNING_RIGHT,
325                             EmergencyLaneKeepAssistState.ACTIVATED_STEER_LEFT,
326                             EmergencyLaneKeepAssistState.ACTIVATED_STEER_RIGHT,
327                             EmergencyLaneKeepAssistState.USER_OVERRIDE)
328                     .build();
329     private static final ImmutableSet<Integer> CRUISE_CONTROL_TYPES =
330             ImmutableSet.<Integer>builder()
331                     .add(
332                             CruiseControlType.OTHER,
333                             CruiseControlType.STANDARD,
334                             CruiseControlType.ADAPTIVE,
335                             CruiseControlType.PREDICTIVE)
336                     .build();
337     private static final ImmutableSet<Integer> CRUISE_CONTROL_STATES =
338             ImmutableSet.<Integer>builder()
339                     .add(
340                             CruiseControlState.OTHER,
341                             CruiseControlState.ENABLED,
342                             CruiseControlState.ACTIVATED,
343                             CruiseControlState.USER_OVERRIDE,
344                             CruiseControlState.SUSPENDED,
345                             CruiseControlState.FORCED_DEACTIVATION_WARNING)
346                     .build();
347     private static final ImmutableSet<Integer> CRUISE_CONTROL_COMMANDS =
348             ImmutableSet.<Integer>builder()
349                     .add(
350                             CruiseControlCommand.ACTIVATE,
351                             CruiseControlCommand.SUSPEND,
352                             CruiseControlCommand.INCREASE_TARGET_SPEED,
353                             CruiseControlCommand.DECREASE_TARGET_SPEED,
354                             CruiseControlCommand.INCREASE_TARGET_TIME_GAP,
355                             CruiseControlCommand.DECREASE_TARGET_TIME_GAP)
356                     .build();
357     private static final ImmutableSet<Integer>
358             CRUISE_CONTROL_COMMANDS_UNAVAILABLE_STATES_ON_STANDARD_CRUISE_CONTROL =
359                     ImmutableSet.<Integer>builder()
360                             .add(
361                                     CruiseControlCommand.INCREASE_TARGET_TIME_GAP,
362                                     CruiseControlCommand.DECREASE_TARGET_TIME_GAP)
363                             .build();
364     private static final ImmutableSet<Integer> HANDS_ON_DETECTION_DRIVER_STATES =
365             ImmutableSet.<Integer>builder()
366                     .add(
367                             HandsOnDetectionDriverState.OTHER,
368                             HandsOnDetectionDriverState.HANDS_ON,
369                             HandsOnDetectionDriverState.HANDS_OFF)
370                     .build();
371     private static final ImmutableSet<Integer> HANDS_ON_DETECTION_WARNINGS =
372             ImmutableSet.<Integer>builder()
373                     .add(
374                             HandsOnDetectionWarning.OTHER,
375                             HandsOnDetectionWarning.NO_WARNING,
376                             HandsOnDetectionWarning.WARNING)
377                     .build();
378     private static final ImmutableSet<Integer> DRIVER_DROWSINESS_ATTENTION_STATES =
379             ImmutableSet.<Integer>builder()
380                     .add(
381                             DriverDrowsinessAttentionState.OTHER,
382                             DriverDrowsinessAttentionState.KSS_RATING_1_EXTREMELY_ALERT,
383                             DriverDrowsinessAttentionState.KSS_RATING_2_VERY_ALERT,
384                             DriverDrowsinessAttentionState.KSS_RATING_3_ALERT,
385                             DriverDrowsinessAttentionState.KSS_RATING_4_RATHER_ALERT,
386                             DriverDrowsinessAttentionState.KSS_RATING_5_NEITHER_ALERT_NOR_SLEEPY,
387                             DriverDrowsinessAttentionState.KSS_RATING_6_SOME_SLEEPINESS,
388                             DriverDrowsinessAttentionState.KSS_RATING_7_SLEEPY_NO_EFFORT,
389                             DriverDrowsinessAttentionState.KSS_RATING_8_SLEEPY_SOME_EFFORT,
390                             DriverDrowsinessAttentionState.KSS_RATING_9_VERY_SLEEPY)
391                      .build();
392     private static final ImmutableSet<Integer> DRIVER_DROWSINESS_ATTENTION_WARNINGS =
393             ImmutableSet.<Integer>builder()
394                     .add(
395                             DriverDrowsinessAttentionWarning.OTHER,
396                             DriverDrowsinessAttentionWarning.NO_WARNING,
397                             DriverDrowsinessAttentionWarning.WARNING)
398                     .build();
399     private static final ImmutableSet<Integer> DRIVER_DISTRACTION_STATES =
400             ImmutableSet.<Integer>builder()
401                     .add(
402                             DriverDistractionState.OTHER,
403                             DriverDistractionState.NOT_DISTRACTED,
404                             DriverDistractionState.DISTRACTED)
405                     .build();
406     private static final ImmutableSet<Integer> DRIVER_DISTRACTION_WARNINGS =
407             ImmutableSet.<Integer>builder()
408                     .add(
409                             DriverDistractionWarning.OTHER,
410                             DriverDistractionWarning.NO_WARNING,
411                             DriverDistractionWarning.WARNING)
412                     .build();
413 
414     private static final ImmutableSet<Integer> ERROR_STATES =
415             ImmutableSet.<Integer>builder()
416                     .add(
417                             ErrorState.OTHER_ERROR_STATE,
418                             ErrorState.NOT_AVAILABLE_DISABLED,
419                             ErrorState.NOT_AVAILABLE_SPEED_LOW,
420                             ErrorState.NOT_AVAILABLE_SPEED_HIGH,
421                             ErrorState.NOT_AVAILABLE_POOR_VISIBILITY,
422                             ErrorState.NOT_AVAILABLE_SAFETY)
423                     .build();
424     private static final ImmutableSet<Integer> AUTOMATIC_EMERGENCY_BRAKING_STATES =
425             ImmutableSet.<Integer>builder()
426                     .add(
427                             AutomaticEmergencyBrakingState.OTHER,
428                             AutomaticEmergencyBrakingState.ENABLED,
429                             AutomaticEmergencyBrakingState.ACTIVATED,
430                             AutomaticEmergencyBrakingState.USER_OVERRIDE)
431                     .build();
432     private static final ImmutableSet<Integer> FORWARD_COLLISION_WARNING_STATES =
433             ImmutableSet.<Integer>builder()
434                     .add(
435                             ForwardCollisionWarningState.OTHER,
436                             ForwardCollisionWarningState.NO_WARNING,
437                             ForwardCollisionWarningState.WARNING)
438                     .build();
439     private static final ImmutableSet<Integer> BLIND_SPOT_WARNING_STATES =
440             ImmutableSet.<Integer>builder()
441                     .add(
442                             BlindSpotWarningState.OTHER,
443                             BlindSpotWarningState.NO_WARNING,
444                             BlindSpotWarningState.WARNING)
445                     .build();
446     private static final ImmutableSet<Integer> LANE_DEPARTURE_WARNING_STATES =
447             ImmutableSet.<Integer>builder()
448                     .add(
449                             LaneDepartureWarningState.OTHER,
450                             LaneDepartureWarningState.NO_WARNING,
451                             LaneDepartureWarningState.WARNING_LEFT,
452                             LaneDepartureWarningState.WARNING_RIGHT)
453                     .build();
454     private static final ImmutableSet<Integer> LANE_KEEP_ASSIST_STATES =
455             ImmutableSet.<Integer>builder()
456                     .add(
457                             LaneKeepAssistState.OTHER,
458                             LaneKeepAssistState.ENABLED,
459                             LaneKeepAssistState.ACTIVATED_STEER_LEFT,
460                             LaneKeepAssistState.ACTIVATED_STEER_RIGHT,
461                             LaneKeepAssistState.USER_OVERRIDE)
462                     .build();
463     private static final ImmutableSet<Integer> LANE_CENTERING_ASSIST_STATES =
464             ImmutableSet.<Integer>builder()
465                     .add(
466                             LaneCenteringAssistState.OTHER,
467                             LaneCenteringAssistState.ENABLED,
468                             LaneCenteringAssistState.ACTIVATION_REQUESTED,
469                             LaneCenteringAssistState.ACTIVATED,
470                             LaneCenteringAssistState.USER_OVERRIDE,
471                             LaneCenteringAssistState.FORCED_DEACTIVATION_WARNING)
472                     .build();
473     private static final ImmutableSet<Integer> LANE_CENTERING_ASSIST_COMMANDS =
474             ImmutableSet.<Integer>builder()
475                     .add(
476                             LaneCenteringAssistCommand.ACTIVATE,
477                             LaneCenteringAssistCommand.DEACTIVATE)
478                     .build();
479     private static final ImmutableSet<Integer> LOW_SPEED_COLLISION_WARNING_STATES =
480             ImmutableSet.<Integer>builder()
481                     .add(
482                             LowSpeedCollisionWarningState.OTHER,
483                             LowSpeedCollisionWarningState.NO_WARNING,
484                             LowSpeedCollisionWarningState.WARNING)
485                     .build();
486     private static final ImmutableSet<Integer> ELECTRONIC_STABILITY_CONTROL_STATES =
487             ImmutableSet.<Integer>builder()
488                     .add(
489                             ElectronicStabilityControlState.OTHER,
490                             ElectronicStabilityControlState.ENABLED,
491                             ElectronicStabilityControlState.ACTIVATED)
492                     .build();
493     private static final ImmutableSet<Integer> CROSS_TRAFFIC_MONITORING_WARNING_STATES =
494             ImmutableSet.<Integer>builder()
495                     .add(
496                             CrossTrafficMonitoringWarningState.OTHER,
497                             CrossTrafficMonitoringWarningState.NO_WARNING,
498                             CrossTrafficMonitoringWarningState.WARNING_FRONT_LEFT,
499                             CrossTrafficMonitoringWarningState.WARNING_FRONT_RIGHT,
500                             CrossTrafficMonitoringWarningState.WARNING_FRONT_BOTH,
501                             CrossTrafficMonitoringWarningState.WARNING_REAR_LEFT,
502                             CrossTrafficMonitoringWarningState.WARNING_REAR_RIGHT,
503                             CrossTrafficMonitoringWarningState.WARNING_REAR_BOTH)
504                     .build();
505     private static final ImmutableSet<Integer> LOW_SPEED_AUTOMATIC_EMERGENCY_BRAKING_STATES =
506             ImmutableSet.<Integer>builder()
507                     .add(
508                             LowSpeedAutomaticEmergencyBrakingState.OTHER,
509                             LowSpeedAutomaticEmergencyBrakingState.ENABLED,
510                             LowSpeedAutomaticEmergencyBrakingState.ACTIVATED,
511                             LowSpeedAutomaticEmergencyBrakingState.USER_OVERRIDE)
512                     .build();
513     private static final ImmutableSet<Integer> VEHICLE_SEAT_OCCUPANCY_STATES = ImmutableSet.of(
514             /*VehicleSeatOccupancyState.UNKNOWN=*/0, /*VehicleSeatOccupancyState.VACANT=*/1,
515             /*VehicleSeatOccupancyState.OCCUPIED=*/2);
516     private static final ImmutableSet<Integer> CRUISE_CONTROL_TYPE_UNWRITABLE_STATES =
517             ImmutableSet.<Integer>builder()
518                     .addAll(ERROR_STATES)
519                     .add(
520                             CruiseControlType.OTHER)
521                     .build();
522     private static final ImmutableSet<Integer> EV_STOPPING_MODE_UNWRITABLE_STATES =
523             ImmutableSet.<Integer>builder()
524                     .add(
525                             EvStoppingMode.STATE_OTHER)
526                     .build();
527     private static final ImmutableSet<Integer> WINDSHIELD_WIPERS_SWITCH_UNWRITABLE_STATES =
528             ImmutableSet.<Integer>builder()
529                     .add(
530                             WindshieldWipersSwitch.OTHER)
531                     .build();
532 
533     private static final ImmutableSet<Integer> PROPERTIES_NOT_EXPOSED_THROUGH_CPM = ImmutableSet.of(
534             VehiclePropertyIds.INVALID,
535             VehiclePropertyIds.AP_POWER_STATE_REQ,
536             VehiclePropertyIds.AP_POWER_STATE_REPORT,
537             VehiclePropertyIds.AP_POWER_BOOTUP_REASON,
538             VehiclePropertyIds.DISPLAY_BRIGHTNESS,
539             VehiclePropertyIds.PER_DISPLAY_BRIGHTNESS,
540             VehiclePropertyIds.HW_KEY_INPUT,
541             VehiclePropertyIds.SEAT_HEADREST_HEIGHT_POS,
542             VehiclePropertyIds.VEHICLE_MAP_SERVICE,
543             VehiclePropertyIds.OBD2_LIVE_FRAME,
544             VehiclePropertyIds.OBD2_FREEZE_FRAME,
545             VehiclePropertyIds.OBD2_FREEZE_FRAME_INFO,
546             VehiclePropertyIds.OBD2_FREEZE_FRAME_CLEAR,
547             /*VehiclePropertyIds.CLUSTER_DISPLAY_STATE=*/289476405,
548             /*VehiclePropertyIds.CLUSTER_HEARTBEAT=*/299896651,
549             /*VehiclePropertyIds.CLUSTER_NAVIGATION_STATE=*/292556600,
550             /*VehiclePropertyIds.CLUSTER_REPORT_STATE=*/299896630,
551             /*VehiclePropertyIds.CLUSTER_REQUEST_DISPLAY=*/289410871,
552             /*VehiclePropertyIds.CLUSTER_SWITCH_UI=*/289410868,
553             /*VehiclePropertyIds.CREATE_USER=*/299896585,
554             /*VehiclePropertyIds.CURRENT_POWER_POLICY=*/286265123,
555             /*VehiclePropertyIds.INITIAL_USER_INFO=*/299896583,
556             /*VehiclePropertyIds.POWER_POLICY_GROUP_REQ=*/286265122,
557             /*VehiclePropertyIds.POWER_POLICY_REQ=*/286265121,
558             /*VehiclePropertyIds.REMOVE_USER=*/299896586,
559             /*VehiclePropertyIds.SWITCH_USER=*/299896584,
560             /*VehiclePropertyIds.USER_IDENTIFICATION_ASSOCIATION=*/299896587,
561             /*VehiclePropertyIds.VHAL_HEARTBEAT=*/290459443,
562             /*VehiclePropertyIds.WATCHDOG_ALIVE=*/290459441,
563             /*VehiclePropertyIds.WATCHDOG_TERMINATED_PROCESS=*/299896626
564     );
565 
566     private static final ImmutableList<Integer>
567             PERMISSION_READ_DRIVER_MONITORING_SETTINGS_PROPERTIES = ImmutableList.<Integer>builder()
568                     .add(
569                             VehiclePropertyIds.HANDS_ON_DETECTION_ENABLED,
570                             VehiclePropertyIds.DRIVER_DROWSINESS_ATTENTION_SYSTEM_ENABLED,
571                             VehiclePropertyIds.DRIVER_DROWSINESS_ATTENTION_WARNING_ENABLED,
572                             VehiclePropertyIds.DRIVER_DISTRACTION_SYSTEM_ENABLED,
573                             VehiclePropertyIds.DRIVER_DISTRACTION_WARNING_ENABLED)
574                     .build();
575     private static final ImmutableList<Integer>
576             PERMISSION_CONTROL_DRIVER_MONITORING_SETTINGS_PROPERTIES =
577             ImmutableList.<Integer>builder()
578                     .add(
579                             VehiclePropertyIds.HANDS_ON_DETECTION_ENABLED,
580                             VehiclePropertyIds.DRIVER_DROWSINESS_ATTENTION_SYSTEM_ENABLED,
581                             VehiclePropertyIds.DRIVER_DROWSINESS_ATTENTION_WARNING_ENABLED,
582                             VehiclePropertyIds.DRIVER_DISTRACTION_SYSTEM_ENABLED,
583                             VehiclePropertyIds.DRIVER_DISTRACTION_WARNING_ENABLED)
584                     .build();
585     private static final ImmutableList<Integer>
586             PERMISSION_READ_DRIVER_MONITORING_STATES_PROPERTIES = ImmutableList.<Integer>builder()
587                     .add(
588                             VehiclePropertyIds.HANDS_ON_DETECTION_DRIVER_STATE,
589                             VehiclePropertyIds.HANDS_ON_DETECTION_WARNING,
590                             VehiclePropertyIds.DRIVER_DROWSINESS_ATTENTION_STATE,
591                             VehiclePropertyIds.DRIVER_DROWSINESS_ATTENTION_WARNING,
592                             VehiclePropertyIds.DRIVER_DISTRACTION_STATE,
593                             VehiclePropertyIds.DRIVER_DISTRACTION_WARNING)
594                     .build();
595     private static final ImmutableList<Integer> PERMISSION_CAR_ENERGY_PROPERTIES =
596             ImmutableList.<Integer>builder()
597                     .add(
598                             VehiclePropertyIds.FUEL_LEVEL,
599                             VehiclePropertyIds.EV_BATTERY_LEVEL,
600                             VehiclePropertyIds.EV_CURRENT_BATTERY_CAPACITY,
601                             VehiclePropertyIds.EV_BATTERY_INSTANTANEOUS_CHARGE_RATE,
602                             VehiclePropertyIds.RANGE_REMAINING,
603                             VehiclePropertyIds.FUEL_LEVEL_LOW,
604                             VehiclePropertyIds.EV_CHARGE_CURRENT_DRAW_LIMIT,
605                             VehiclePropertyIds.EV_CHARGE_PERCENT_LIMIT,
606                             VehiclePropertyIds.EV_CHARGE_STATE,
607                             VehiclePropertyIds.EV_CHARGE_SWITCH,
608                             VehiclePropertyIds.EV_CHARGE_TIME_REMAINING,
609                             VehiclePropertyIds.EV_REGENERATIVE_BRAKING_STATE,
610                             VehiclePropertyIds.EV_BATTERY_AVERAGE_TEMPERATURE)
611                     .build();
612     private static final ImmutableList<Integer> PERMISSION_CAR_ENERGY_PORTS_PROPERTIES =
613             ImmutableList.<Integer>builder()
614                     .add(
615                             VehiclePropertyIds.FUEL_DOOR_OPEN,
616                             VehiclePropertyIds.EV_CHARGE_PORT_OPEN,
617                             VehiclePropertyIds.EV_CHARGE_PORT_CONNECTED)
618                     .build();
619     private static final ImmutableList<Integer> PERMISSION_CAR_EXTERIOR_ENVIRONMENT_PROPERTIES =
620             ImmutableList.<Integer>builder()
621                     .add(VehiclePropertyIds.NIGHT_MODE, VehiclePropertyIds.ENV_OUTSIDE_TEMPERATURE)
622                     .build();
623     private static final ImmutableList<Integer> PERMISSION_CAR_INFO_PROPERTIES =
624             ImmutableList.<Integer>builder()
625                     .add(
626                             VehiclePropertyIds.INFO_MAKE,
627                             VehiclePropertyIds.INFO_MODEL,
628                             VehiclePropertyIds.INFO_MODEL_YEAR,
629                             VehiclePropertyIds.INFO_FUEL_CAPACITY,
630                             VehiclePropertyIds.INFO_FUEL_TYPE,
631                             VehiclePropertyIds.INFO_EV_BATTERY_CAPACITY,
632                             VehiclePropertyIds.INFO_EV_CONNECTOR_TYPE,
633                             VehiclePropertyIds.INFO_FUEL_DOOR_LOCATION,
634                             VehiclePropertyIds.INFO_MULTI_EV_PORT_LOCATIONS,
635                             VehiclePropertyIds.INFO_EV_PORT_LOCATION,
636                             VehiclePropertyIds.INFO_DRIVER_SEAT,
637                             VehiclePropertyIds.INFO_EXTERIOR_DIMENSIONS,
638                             VehiclePropertyIds.ELECTRONIC_TOLL_COLLECTION_CARD_TYPE,
639                             VehiclePropertyIds.ELECTRONIC_TOLL_COLLECTION_CARD_STATUS,
640                             VehiclePropertyIds.GENERAL_SAFETY_REGULATION_COMPLIANCE)
641                     .build();
642     private static final ImmutableList<Integer> PERMISSION_CAR_POWERTRAIN_PROPERTIES =
643             ImmutableList.<Integer>builder()
644                     .add(
645                             VehiclePropertyIds.GEAR_SELECTION,
646                             VehiclePropertyIds.CURRENT_GEAR,
647                             VehiclePropertyIds.PARKING_BRAKE_ON,
648                             VehiclePropertyIds.PARKING_BRAKE_AUTO_APPLY,
649                             VehiclePropertyIds.IGNITION_STATE,
650                             VehiclePropertyIds.EV_BRAKE_REGENERATION_LEVEL,
651                             VehiclePropertyIds.EV_STOPPING_MODE)
652                     .build();
653     private static final ImmutableList<Integer> PERMISSION_CONTROL_CAR_POWERTRAIN_PROPERTIES =
654             ImmutableList.<Integer>builder()
655                     .add(
656                             VehiclePropertyIds.EV_BRAKE_REGENERATION_LEVEL,
657                             VehiclePropertyIds.EV_STOPPING_MODE)
658                     .build();
659     private static final ImmutableList<Integer> PERMISSION_CAR_SPEED_PROPERTIES =
660             ImmutableList.<Integer>builder()
661                     .add(
662                             VehiclePropertyIds.PERF_VEHICLE_SPEED,
663                             VehiclePropertyIds.PERF_VEHICLE_SPEED_DISPLAY,
664                             VehiclePropertyIds.WHEEL_TICK)
665                     .build();
666     private static final ImmutableList<Integer> PERMISSION_READ_CAR_DISPLAY_UNITS_PROPERTIES =
667             ImmutableList.<Integer>builder()
668                     .add(
669                             VehiclePropertyIds.DISTANCE_DISPLAY_UNITS,
670                             VehiclePropertyIds.FUEL_VOLUME_DISPLAY_UNITS,
671                             VehiclePropertyIds.TIRE_PRESSURE_DISPLAY_UNITS,
672                             VehiclePropertyIds.EV_BATTERY_DISPLAY_UNITS,
673                             VehiclePropertyIds.VEHICLE_SPEED_DISPLAY_UNITS,
674                             VehiclePropertyIds.FUEL_CONSUMPTION_UNITS_DISTANCE_OVER_VOLUME,
675                             VehiclePropertyIds.HVAC_TEMPERATURE_DISPLAY_UNITS)
676                     .build();
677     private static final ImmutableList<Integer> PERMISSION_CONTROL_CAR_STEERING_WHEEL_PROPERTIES =
678             ImmutableList.<Integer>builder()
679                     .add(
680                             VehiclePropertyIds.STEERING_WHEEL_DEPTH_POS,
681                             VehiclePropertyIds.STEERING_WHEEL_DEPTH_MOVE,
682                             VehiclePropertyIds.STEERING_WHEEL_HEIGHT_POS,
683                             VehiclePropertyIds.STEERING_WHEEL_HEIGHT_MOVE,
684                             VehiclePropertyIds.STEERING_WHEEL_THEFT_LOCK_ENABLED,
685                             VehiclePropertyIds.STEERING_WHEEL_LOCKED,
686                             VehiclePropertyIds.STEERING_WHEEL_EASY_ACCESS_ENABLED)
687                     .build();
688     private static final ImmutableList<Integer> PERMISSION_READ_CAR_AIRBAGS_PROPERTIES =
689             ImmutableList.<Integer>builder()
690                     .add(
691                             VehiclePropertyIds.SEAT_AIRBAGS_DEPLOYED)
692                     .build();
693     private static final ImmutableList<Integer> PERMISSION_CONTROL_CAR_AIRBAGS_PROPERTIES =
694             ImmutableList.<Integer>builder()
695                     .add(
696                             VehiclePropertyIds.SEAT_AIRBAG_ENABLED)
697                     .build();
698     private static final ImmutableList<Integer> PERMISSION_READ_IMPACT_SENSORS_PROPERTIES =
699             ImmutableList.<Integer>builder()
700                     .add(
701                             VehiclePropertyIds.IMPACT_DETECTED)
702                     .build();
703     private static final ImmutableList<Integer> PERMISSION_CONTROL_CAR_SEATS_PROPERTIES =
704             ImmutableList.<Integer>builder()
705                     .add(
706                             VehiclePropertyIds.SEAT_MEMORY_SELECT,
707                             VehiclePropertyIds.SEAT_MEMORY_SET,
708                             VehiclePropertyIds.SEAT_BELT_BUCKLED,
709                             VehiclePropertyIds.SEAT_BELT_HEIGHT_POS,
710                             VehiclePropertyIds.SEAT_BELT_HEIGHT_MOVE,
711                             VehiclePropertyIds.SEAT_FORE_AFT_POS,
712                             VehiclePropertyIds.SEAT_FORE_AFT_MOVE,
713                             VehiclePropertyIds.SEAT_BACKREST_ANGLE_1_POS,
714                             VehiclePropertyIds.SEAT_BACKREST_ANGLE_1_MOVE,
715                             VehiclePropertyIds.SEAT_BACKREST_ANGLE_2_POS,
716                             VehiclePropertyIds.SEAT_BACKREST_ANGLE_2_MOVE,
717                             VehiclePropertyIds.SEAT_HEIGHT_POS,
718                             VehiclePropertyIds.SEAT_HEIGHT_MOVE,
719                             VehiclePropertyIds.SEAT_DEPTH_POS,
720                             VehiclePropertyIds.SEAT_DEPTH_MOVE,
721                             VehiclePropertyIds.SEAT_TILT_POS,
722                             VehiclePropertyIds.SEAT_TILT_MOVE,
723                             VehiclePropertyIds.SEAT_LUMBAR_FORE_AFT_POS,
724                             VehiclePropertyIds.SEAT_LUMBAR_FORE_AFT_MOVE,
725                             VehiclePropertyIds.SEAT_LUMBAR_SIDE_SUPPORT_POS,
726                             VehiclePropertyIds.SEAT_LUMBAR_SIDE_SUPPORT_MOVE,
727                             VehiclePropertyIds.SEAT_HEADREST_HEIGHT_POS,
728                             VehiclePropertyIds.SEAT_HEADREST_HEIGHT_POS_V2,
729                             VehiclePropertyIds.SEAT_HEADREST_HEIGHT_MOVE,
730                             VehiclePropertyIds.SEAT_HEADREST_ANGLE_POS,
731                             VehiclePropertyIds.SEAT_HEADREST_ANGLE_MOVE,
732                             VehiclePropertyIds.SEAT_HEADREST_FORE_AFT_POS,
733                             VehiclePropertyIds.SEAT_HEADREST_FORE_AFT_MOVE,
734                             VehiclePropertyIds.SEAT_EASY_ACCESS_ENABLED,
735                             VehiclePropertyIds.SEAT_CUSHION_SIDE_SUPPORT_POS,
736                             VehiclePropertyIds.SEAT_CUSHION_SIDE_SUPPORT_MOVE,
737                             VehiclePropertyIds.SEAT_LUMBAR_VERTICAL_POS,
738                             VehiclePropertyIds.SEAT_LUMBAR_VERTICAL_MOVE,
739                             VehiclePropertyIds.SEAT_WALK_IN_POS,
740                             VehiclePropertyIds.SEAT_OCCUPANCY)
741                     .build();
742     private static final ImmutableList<Integer> PERMISSION_READ_CAR_SEAT_BELTS_PROPERTIES =
743             ImmutableList.<Integer>builder()
744                     .add(
745                             VehiclePropertyIds.SEAT_BELT_PRETENSIONER_DEPLOYED)
746                     .build();
747     private static final ImmutableList<Integer> PERMISSION_READ_VALET_MODE_PROPERTIES =
748             ImmutableList.<Integer>builder()
749                     .add(
750                             VehiclePropertyIds.VALET_MODE_ENABLED)
751                     .build();
752     private static final ImmutableList<Integer> PERMISSION_CONTROL_VALET_MODE_PROPERTIES =
753             ImmutableList.<Integer>builder()
754                     .add(
755                             VehiclePropertyIds.VALET_MODE_ENABLED)
756                     .build();
757     private static final ImmutableList<Integer> PERMISSION_READ_HEAD_UP_DISPLAY_STATUS_PROPERTIES =
758             ImmutableList.<Integer>builder()
759                     .add(
760                             VehiclePropertyIds.HEAD_UP_DISPLAY_ENABLED)
761                     .build();
762     private static final ImmutableList<Integer> PERMISSION_CONTROL_HEAD_UP_DISPLAY_PROPERTIES =
763             ImmutableList.<Integer>builder()
764                     .add(
765                             VehiclePropertyIds.HEAD_UP_DISPLAY_ENABLED)
766                     .build();
767     private static final ImmutableList<Integer> PERMISSION_IDENTIFICATION_PROPERTIES =
768             ImmutableList.<Integer>builder()
769                     .add(
770                             VehiclePropertyIds.INFO_VIN)
771                     .build();
772     private static final ImmutableList<Integer> PERMISSION_MILEAGE_PROPERTIES =
773             ImmutableList.<Integer>builder()
774                     .add(
775                             VehiclePropertyIds.PERF_ODOMETER)
776                     .build();
777     private static final ImmutableList<Integer> PERMISSION_MILEAGE_3P_PROPERTIES =
778             ImmutableList.<Integer>builder()
779                     .add(
780                             VehiclePropertyIds.INSTANTANEOUS_FUEL_ECONOMY,
781                             VehiclePropertyIds.INSTANTANEOUS_EV_EFFICIENCY)
782                     .build();
783     private static final ImmutableList<Integer> PERMISSION_READ_STEERING_STATE_PROPERTIES =
784             ImmutableList.<Integer>builder()
785                     .add(
786                             VehiclePropertyIds.PERF_STEERING_ANGLE,
787                             VehiclePropertyIds.PERF_REAR_STEERING_ANGLE)
788                     .build();
789     private static final ImmutableList<Integer> PERMISSION_READ_STEERING_STATE_3P_PROPERTIES =
790             ImmutableList.<Integer>builder().add(VehiclePropertyIds.PERF_STEERING_ANGLE).build();
791     private static final ImmutableList<Integer> PERMISSION_CAR_ENGINE_DETAILED_PROPERTIES =
792             ImmutableList.<Integer>builder()
793                     .add(
794                             VehiclePropertyIds.ENGINE_COOLANT_TEMP,
795                             VehiclePropertyIds.ENGINE_OIL_LEVEL,
796                             VehiclePropertyIds.ENGINE_OIL_TEMP,
797                             VehiclePropertyIds.ENGINE_RPM,
798                             VehiclePropertyIds.ENGINE_IDLE_AUTO_STOP_ENABLED)
799                     .build();
800     private static final ImmutableList<Integer> PERMISSION_CONTROL_ENERGY_PORTS_PROPERTIES =
801             ImmutableList.<Integer>builder()
802                     .add(
803                             VehiclePropertyIds.FUEL_DOOR_OPEN,
804                             VehiclePropertyIds.EV_CHARGE_PORT_OPEN)
805                     .build();
806     private static final ImmutableList<Integer> PERMISSION_ADJUST_RANGE_REMAINING_PROPERTIES =
807             ImmutableList.<Integer>builder()
808                     .add(
809                             VehiclePropertyIds.RANGE_REMAINING)
810                     .build();
811     private static final ImmutableList<Integer> PERMISSION_TIRES_PROPERTIES =
812             ImmutableList.<Integer>builder()
813                     .add(
814                             VehiclePropertyIds.TIRE_PRESSURE,
815                             VehiclePropertyIds.CRITICALLY_LOW_TIRE_PRESSURE)
816                     .build();
817     private static final ImmutableList<Integer> PERMISSION_EXTERIOR_LIGHTS_PROPERTIES =
818             ImmutableList.<Integer>builder()
819                     .add(
820                             VehiclePropertyIds.TURN_SIGNAL_STATE,
821                             VehiclePropertyIds.HEADLIGHTS_STATE,
822                             VehiclePropertyIds.HIGH_BEAM_LIGHTS_STATE,
823                             VehiclePropertyIds.FOG_LIGHTS_STATE,
824                             VehiclePropertyIds.HAZARD_LIGHTS_STATE,
825                             VehiclePropertyIds.FRONT_FOG_LIGHTS_STATE,
826                             VehiclePropertyIds.REAR_FOG_LIGHTS_STATE)
827                     .build();
828     private static final ImmutableList<Integer> PERMISSION_CAR_DYNAMICS_STATE_PROPERTIES =
829             ImmutableList.<Integer>builder()
830                     .add(
831                             VehiclePropertyIds.ABS_ACTIVE,
832                             VehiclePropertyIds.TRACTION_CONTROL_ACTIVE,
833                             VehiclePropertyIds.ELECTRONIC_STABILITY_CONTROL_ENABLED,
834                             VehiclePropertyIds.ELECTRONIC_STABILITY_CONTROL_STATE,
835                             VehiclePropertyIds.VEHICLE_PASSIVE_SUSPENSION_HEIGHT)
836                     .build();
837     private static final ImmutableList<Integer> PERMISSION_CONTROL_CAR_DYNAMICS_STATE_PROPERTIES =
838             ImmutableList.<Integer>builder()
839                     .add(
840                             VehiclePropertyIds.ELECTRONIC_STABILITY_CONTROL_ENABLED)
841                     .build();
842     private static final ImmutableList<Integer> PERMISSION_CONTROL_CAR_CLIMATE_PROPERTIES =
843             ImmutableList.<Integer>builder()
844                     .add(
845                             VehiclePropertyIds.HVAC_FAN_SPEED,
846                             VehiclePropertyIds.HVAC_FAN_DIRECTION,
847                             VehiclePropertyIds.HVAC_TEMPERATURE_CURRENT,
848                             VehiclePropertyIds.HVAC_TEMPERATURE_SET,
849                             VehiclePropertyIds.HVAC_TEMPERATURE_VALUE_SUGGESTION,
850                             VehiclePropertyIds.HVAC_DEFROSTER,
851                             VehiclePropertyIds.HVAC_AC_ON,
852                             VehiclePropertyIds.HVAC_MAX_AC_ON,
853                             VehiclePropertyIds.HVAC_MAX_DEFROST_ON,
854                             VehiclePropertyIds.HVAC_RECIRC_ON,
855                             VehiclePropertyIds.HVAC_DUAL_ON,
856                             VehiclePropertyIds.HVAC_AUTO_ON,
857                             VehiclePropertyIds.HVAC_SEAT_TEMPERATURE,
858                             VehiclePropertyIds.HVAC_SIDE_MIRROR_HEAT,
859                             VehiclePropertyIds.HVAC_STEERING_WHEEL_HEAT,
860                             VehiclePropertyIds.HVAC_TEMPERATURE_DISPLAY_UNITS,
861                             VehiclePropertyIds.HVAC_ACTUAL_FAN_SPEED_RPM,
862                             VehiclePropertyIds.HVAC_POWER_ON,
863                             VehiclePropertyIds.HVAC_FAN_DIRECTION_AVAILABLE,
864                             VehiclePropertyIds.HVAC_AUTO_RECIRC_ON,
865                             VehiclePropertyIds.HVAC_SEAT_VENTILATION,
866                             VehiclePropertyIds.HVAC_ELECTRIC_DEFROSTER_ON)
867                     .build();
868     private static final ImmutableList<Integer> PERMISSION_CONTROL_CAR_DOORS_PROPERTIES =
869             ImmutableList.<Integer>builder()
870                     .add(
871                             VehiclePropertyIds.DOOR_POS,
872                             VehiclePropertyIds.DOOR_MOVE,
873                             VehiclePropertyIds.DOOR_LOCK,
874                             VehiclePropertyIds.DOOR_CHILD_LOCK_ENABLED)
875                     .build();
876     private static final ImmutableList<Integer> PERMISSION_CONTROL_CAR_MIRRORS_PROPERTIES =
877             ImmutableList.<Integer>builder()
878                     .add(
879                             VehiclePropertyIds.MIRROR_Z_POS,
880                             VehiclePropertyIds.MIRROR_Z_MOVE,
881                             VehiclePropertyIds.MIRROR_Y_POS,
882                             VehiclePropertyIds.MIRROR_Y_MOVE,
883                             VehiclePropertyIds.MIRROR_LOCK,
884                             VehiclePropertyIds.MIRROR_FOLD,
885                             VehiclePropertyIds.MIRROR_AUTO_FOLD_ENABLED,
886                             VehiclePropertyIds.MIRROR_AUTO_TILT_ENABLED)
887                     .build();
888     private static final ImmutableList<Integer> PERMISSION_CONTROL_CAR_WINDOWS_PROPERTIES =
889             ImmutableList.<Integer>builder()
890                     .add(
891                             VehiclePropertyIds.WINDOW_POS,
892                             VehiclePropertyIds.WINDOW_MOVE,
893                             VehiclePropertyIds.WINDOW_LOCK)
894                     .build();
895     private static final ImmutableList<Integer> PERMISSION_READ_WINDSHIELD_WIPERS_PROPERTIES =
896             ImmutableList.<Integer>builder()
897                     .add(
898                             VehiclePropertyIds.WINDSHIELD_WIPERS_PERIOD,
899                             VehiclePropertyIds.WINDSHIELD_WIPERS_STATE,
900                             VehiclePropertyIds.WINDSHIELD_WIPERS_SWITCH)
901                     .build();
902     private static final ImmutableList<Integer> PERMISSION_CONTROL_WINDSHIELD_WIPERS_PROPERTIES =
903             ImmutableList.<Integer>builder()
904                     .add(
905                             VehiclePropertyIds.WINDSHIELD_WIPERS_SWITCH)
906                     .build();
907     private static final ImmutableList<Integer> PERMISSION_CONTROL_EXTERIOR_LIGHTS_PROPERTIES =
908             ImmutableList.<Integer>builder()
909                     .add(
910                             VehiclePropertyIds.HEADLIGHTS_SWITCH,
911                             VehiclePropertyIds.HIGH_BEAM_LIGHTS_SWITCH,
912                             VehiclePropertyIds.FOG_LIGHTS_SWITCH,
913                             VehiclePropertyIds.HAZARD_LIGHTS_SWITCH,
914                             VehiclePropertyIds.FRONT_FOG_LIGHTS_SWITCH,
915                             VehiclePropertyIds.REAR_FOG_LIGHTS_SWITCH)
916                     .build();
917     private static final ImmutableList<Integer> PERMISSION_READ_INTERIOR_LIGHTS_PROPERTIES =
918             ImmutableList.<Integer>builder()
919                     .add(
920                             VehiclePropertyIds.SEAT_FOOTWELL_LIGHTS_STATE,
921                             VehiclePropertyIds.CABIN_LIGHTS_STATE,
922                             VehiclePropertyIds.READING_LIGHTS_STATE,
923                             VehiclePropertyIds.STEERING_WHEEL_LIGHTS_STATE)
924                     .build();
925     private static final ImmutableList<Integer> PERMISSION_CONTROL_INTERIOR_LIGHTS_PROPERTIES =
926             ImmutableList.<Integer>builder()
927                     .add(
928                             VehiclePropertyIds.SEAT_FOOTWELL_LIGHTS_SWITCH,
929                             VehiclePropertyIds.CABIN_LIGHTS_SWITCH,
930                             VehiclePropertyIds.READING_LIGHTS_SWITCH,
931                             VehiclePropertyIds.STEERING_WHEEL_LIGHTS_SWITCH)
932                     .build();
933     private static final ImmutableList<Integer> PERMISSION_CAR_EPOCH_TIME_PROPERTIES =
934             ImmutableList.<Integer>builder()
935                     .add(
936                             VehiclePropertyIds.EPOCH_TIME)
937                     .build();
938     private static final ImmutableList<Integer> PERMISSION_CONTROL_CAR_ENERGY_PROPERTIES =
939             ImmutableList.<Integer>builder()
940                     .add(
941                             VehiclePropertyIds.EV_CHARGE_CURRENT_DRAW_LIMIT,
942                             VehiclePropertyIds.EV_CHARGE_PERCENT_LIMIT,
943                             VehiclePropertyIds.EV_CHARGE_SWITCH)
944                     .build();
945     private static final ImmutableList<Integer> PERMISSION_PRIVILEGED_CAR_INFO_PROPERTIES =
946             ImmutableList.<Integer>builder()
947                     .add(
948                             VehiclePropertyIds.VEHICLE_CURB_WEIGHT,
949                             VehiclePropertyIds.TRAILER_PRESENT)
950                     .build();
951     private static final ImmutableList<Integer>
952             PERMISSION_CONTROL_DISPLAY_UNITS_VENDOR_EXTENSION_PROPERTIES =
953             ImmutableList.<Integer>builder()
954                     .add(
955                             VehiclePropertyIds.DISTANCE_DISPLAY_UNITS,
956                             VehiclePropertyIds.FUEL_VOLUME_DISPLAY_UNITS,
957                             VehiclePropertyIds.TIRE_PRESSURE_DISPLAY_UNITS,
958                             VehiclePropertyIds.EV_BATTERY_DISPLAY_UNITS,
959                             VehiclePropertyIds.VEHICLE_SPEED_DISPLAY_UNITS,
960                             VehiclePropertyIds.FUEL_CONSUMPTION_UNITS_DISTANCE_OVER_VOLUME)
961                     .build();
962     private static final ImmutableList<Integer> PERMISSION_READ_ADAS_SETTINGS_PROPERTIES =
963             ImmutableList.<Integer>builder()
964                     .add(
965                             VehiclePropertyIds.AUTOMATIC_EMERGENCY_BRAKING_ENABLED,
966                             VehiclePropertyIds.FORWARD_COLLISION_WARNING_ENABLED,
967                             VehiclePropertyIds.BLIND_SPOT_WARNING_ENABLED,
968                             VehiclePropertyIds.LANE_DEPARTURE_WARNING_ENABLED,
969                             VehiclePropertyIds.LANE_KEEP_ASSIST_ENABLED,
970                             VehiclePropertyIds.LANE_CENTERING_ASSIST_ENABLED,
971                             VehiclePropertyIds.EMERGENCY_LANE_KEEP_ASSIST_ENABLED,
972                             VehiclePropertyIds.CRUISE_CONTROL_ENABLED,
973                             VehiclePropertyIds.LOW_SPEED_COLLISION_WARNING_ENABLED,
974                             VehiclePropertyIds.CROSS_TRAFFIC_MONITORING_ENABLED,
975                             VehiclePropertyIds.LOW_SPEED_AUTOMATIC_EMERGENCY_BRAKING_ENABLED)
976                     .build();
977     private static final ImmutableList<Integer> PERMISSION_CONTROL_ADAS_SETTINGS_PROPERTIES =
978             ImmutableList.<Integer>builder()
979                     .add(
980                             VehiclePropertyIds.AUTOMATIC_EMERGENCY_BRAKING_ENABLED,
981                             VehiclePropertyIds.FORWARD_COLLISION_WARNING_ENABLED,
982                             VehiclePropertyIds.BLIND_SPOT_WARNING_ENABLED,
983                             VehiclePropertyIds.LANE_DEPARTURE_WARNING_ENABLED,
984                             VehiclePropertyIds.LANE_KEEP_ASSIST_ENABLED,
985                             VehiclePropertyIds.LANE_CENTERING_ASSIST_ENABLED,
986                             VehiclePropertyIds.EMERGENCY_LANE_KEEP_ASSIST_ENABLED,
987                             VehiclePropertyIds.CRUISE_CONTROL_ENABLED,
988                             VehiclePropertyIds.LOW_SPEED_COLLISION_WARNING_ENABLED,
989                             VehiclePropertyIds.CROSS_TRAFFIC_MONITORING_ENABLED,
990                             VehiclePropertyIds.LOW_SPEED_AUTOMATIC_EMERGENCY_BRAKING_ENABLED)
991                     .build();
992     private static final ImmutableList<Integer> PERMISSION_READ_ADAS_STATES_PROPERTIES =
993             ImmutableList.<Integer>builder()
994                     .add(
995                             VehiclePropertyIds.AUTOMATIC_EMERGENCY_BRAKING_STATE,
996                             VehiclePropertyIds.FORWARD_COLLISION_WARNING_STATE,
997                             VehiclePropertyIds.BLIND_SPOT_WARNING_STATE,
998                             VehiclePropertyIds.LANE_DEPARTURE_WARNING_STATE,
999                             VehiclePropertyIds.LANE_KEEP_ASSIST_STATE,
1000                             VehiclePropertyIds.LANE_CENTERING_ASSIST_STATE,
1001                             VehiclePropertyIds.EMERGENCY_LANE_KEEP_ASSIST_STATE,
1002                             VehiclePropertyIds.CRUISE_CONTROL_TYPE,
1003                             VehiclePropertyIds.CRUISE_CONTROL_STATE,
1004                             VehiclePropertyIds.CRUISE_CONTROL_TARGET_SPEED,
1005                             VehiclePropertyIds.ADAPTIVE_CRUISE_CONTROL_TARGET_TIME_GAP,
1006                             VehiclePropertyIds
1007                                     .ADAPTIVE_CRUISE_CONTROL_LEAD_VEHICLE_MEASURED_DISTANCE,
1008                             VehiclePropertyIds.LOW_SPEED_COLLISION_WARNING_STATE,
1009                             VehiclePropertyIds.CROSS_TRAFFIC_MONITORING_WARNING_STATE,
1010                             VehiclePropertyIds.LOW_SPEED_AUTOMATIC_EMERGENCY_BRAKING_STATE)
1011                     .build();
1012     private static final ImmutableList<Integer> PERMISSION_CONTROL_ADAS_STATES_PROPERTIES =
1013             ImmutableList.<Integer>builder()
1014                     .add(
1015                             VehiclePropertyIds.LANE_CENTERING_ASSIST_COMMAND,
1016                             VehiclePropertyIds.CRUISE_CONTROL_TYPE,
1017                             VehiclePropertyIds.CRUISE_CONTROL_COMMAND,
1018                             VehiclePropertyIds.CRUISE_CONTROL_TARGET_SPEED,
1019                             VehiclePropertyIds.ADAPTIVE_CRUISE_CONTROL_TARGET_TIME_GAP)
1020                     .build();
1021     private static final ImmutableList<Integer> PERMISSION_CONTROL_GLOVE_BOX_PROPERTIES =
1022             ImmutableList.<Integer>builder()
1023                     .add(
1024                             VehiclePropertyIds.GLOVE_BOX_DOOR_POS,
1025                             VehiclePropertyIds.GLOVE_BOX_LOCKED)
1026                   .build();
1027     private static final ImmutableList<Integer>
1028             PERMISSION_ACCESS_FINE_LOCATION_PROPERTIES =
1029             ImmutableList.<Integer>builder()
1030                     .add(
1031                             VehiclePropertyIds.LOCATION_CHARACTERIZATION)
1032                     .build();
1033     private static final ImmutableList<Integer>
1034             PERMISSION_CAR_DRIVING_STATE_PROPERTIES =
1035             ImmutableList.<Integer>builder()
1036                     .add(
1037                             VehiclePropertyIds.VEHICLE_DRIVING_AUTOMATION_CURRENT_LEVEL,
1038                             VehiclePropertyIds.VEHICLE_DRIVING_AUTOMATION_TARGET_LEVEL)
1039                     .build();
1040     private static final ImmutableList<Integer>
1041             PERMISSION_READ_ULTRASONICS_SENSOR_DATA_PROPERTIES =
1042             ImmutableList.<Integer>builder()
1043                     .add(
1044                             VehiclePropertyIds.ULTRASONICS_SENSOR_POSITION,
1045                             VehiclePropertyIds.ULTRASONICS_SENSOR_ORIENTATION,
1046                             VehiclePropertyIds.ULTRASONICS_SENSOR_FIELD_OF_VIEW,
1047                             VehiclePropertyIds.ULTRASONICS_SENSOR_DETECTION_RANGE,
1048                             VehiclePropertyIds.ULTRASONICS_SENSOR_SUPPORTED_RANGES,
1049                             VehiclePropertyIds.ULTRASONICS_SENSOR_MEASURED_DISTANCE)
1050                     .build();
1051     private static final ImmutableList<Integer>
1052             PERMISSION_READ_EXTERIOR_LIGHTS_PROPERTIES =
1053             ImmutableList.<Integer>builder()
1054                     .add(
1055                             VehiclePropertyIds.TURN_SIGNAL_LIGHT_STATE,
1056                             VehiclePropertyIds.TURN_SIGNAL_SWITCH)
1057                     .build();
1058     private static final ImmutableList<Integer>
1059             PERMISSION_READ_CAR_HORN_PROPERTIES =
1060             ImmutableList.<Integer>builder()
1061                     .add(
1062                             VehiclePropertyIds.VEHICLE_HORN_ENGAGED)
1063                     .build();
1064     private static final ImmutableList<Integer>
1065             PERMISSION_CONTROL_CAR_HORN_PROPERTIES =
1066             ImmutableList.<Integer>builder()
1067                     .add(
1068                             VehiclePropertyIds.VEHICLE_HORN_ENGAGED)
1069                     .build();
1070     private static final ImmutableList<Integer>
1071             PERMISSION_READ_CAR_PEDALS_PROPERTIES =
1072             ImmutableList.<Integer>builder()
1073                     .add(
1074                             VehiclePropertyIds.ACCELERATOR_PEDAL_COMPRESSION_PERCENTAGE,
1075                             VehiclePropertyIds.BRAKE_PEDAL_COMPRESSION_PERCENTAGE)
1076                     .build();
1077     private static final ImmutableList<Integer>
1078             PERMISSION_READ_BRAKE_INFO_PROPERTIES =
1079             ImmutableList.<Integer>builder()
1080                     .add(
1081                             VehiclePropertyIds.BRAKE_PAD_WEAR_PERCENTAGE,
1082                             VehiclePropertyIds.BRAKE_FLUID_LEVEL_LOW)
1083                     .build();
1084     private static final ImmutableList<String> VENDOR_PROPERTY_PERMISSIONS =
1085             ImmutableList.<String>builder()
1086                     .add(
1087                             Car.PERMISSION_VENDOR_EXTENSION,
1088                             VehicleVendorPermission.PERMISSION_GET_CAR_VENDOR_CATEGORY_WINDOW,
1089                             VehicleVendorPermission.PERMISSION_SET_CAR_VENDOR_CATEGORY_WINDOW,
1090                             VehicleVendorPermission.PERMISSION_GET_CAR_VENDOR_CATEGORY_DOOR,
1091                             VehicleVendorPermission.PERMISSION_SET_CAR_VENDOR_CATEGORY_DOOR,
1092                             VehicleVendorPermission.PERMISSION_GET_CAR_VENDOR_CATEGORY_SEAT,
1093                             VehicleVendorPermission.PERMISSION_SET_CAR_VENDOR_CATEGORY_SEAT,
1094                             VehicleVendorPermission.PERMISSION_GET_CAR_VENDOR_CATEGORY_MIRROR,
1095                             VehicleVendorPermission.PERMISSION_SET_CAR_VENDOR_CATEGORY_MIRROR,
1096                             VehicleVendorPermission.PERMISSION_GET_CAR_VENDOR_CATEGORY_INFO,
1097                             VehicleVendorPermission.PERMISSION_SET_CAR_VENDOR_CATEGORY_INFO,
1098                             VehicleVendorPermission.PERMISSION_GET_CAR_VENDOR_CATEGORY_ENGINE,
1099                             VehicleVendorPermission.PERMISSION_SET_CAR_VENDOR_CATEGORY_ENGINE,
1100                             VehicleVendorPermission.PERMISSION_GET_CAR_VENDOR_CATEGORY_HVAC,
1101                             VehicleVendorPermission.PERMISSION_SET_CAR_VENDOR_CATEGORY_HVAC,
1102                             VehicleVendorPermission.PERMISSION_GET_CAR_VENDOR_CATEGORY_LIGHT,
1103                             VehicleVendorPermission.PERMISSION_SET_CAR_VENDOR_CATEGORY_LIGHT,
1104                             VehicleVendorPermission.PERMISSION_GET_CAR_VENDOR_CATEGORY_1,
1105                             VehicleVendorPermission.PERMISSION_SET_CAR_VENDOR_CATEGORY_1,
1106                             VehicleVendorPermission.PERMISSION_GET_CAR_VENDOR_CATEGORY_2,
1107                             VehicleVendorPermission.PERMISSION_SET_CAR_VENDOR_CATEGORY_2,
1108                             VehicleVendorPermission.PERMISSION_GET_CAR_VENDOR_CATEGORY_3,
1109                             VehicleVendorPermission.PERMISSION_SET_CAR_VENDOR_CATEGORY_3,
1110                             VehicleVendorPermission.PERMISSION_GET_CAR_VENDOR_CATEGORY_4,
1111                             VehicleVendorPermission.PERMISSION_SET_CAR_VENDOR_CATEGORY_4,
1112                             VehicleVendorPermission.PERMISSION_GET_CAR_VENDOR_CATEGORY_5,
1113                             VehicleVendorPermission.PERMISSION_SET_CAR_VENDOR_CATEGORY_5,
1114                             VehicleVendorPermission.PERMISSION_GET_CAR_VENDOR_CATEGORY_6,
1115                             VehicleVendorPermission.PERMISSION_SET_CAR_VENDOR_CATEGORY_6,
1116                             VehicleVendorPermission.PERMISSION_GET_CAR_VENDOR_CATEGORY_7,
1117                             VehicleVendorPermission.PERMISSION_SET_CAR_VENDOR_CATEGORY_7,
1118                             VehicleVendorPermission.PERMISSION_GET_CAR_VENDOR_CATEGORY_8,
1119                             VehicleVendorPermission.PERMISSION_SET_CAR_VENDOR_CATEGORY_8,
1120                             VehicleVendorPermission.PERMISSION_GET_CAR_VENDOR_CATEGORY_9,
1121                             VehicleVendorPermission.PERMISSION_SET_CAR_VENDOR_CATEGORY_9,
1122                             VehicleVendorPermission.PERMISSION_GET_CAR_VENDOR_CATEGORY_10,
1123                             VehicleVendorPermission.PERMISSION_SET_CAR_VENDOR_CATEGORY_10)
1124                     .build();
1125 
1126     /** contains property Ids for the properties required by CDD */
1127     private final ArraySet<Integer> mPropertyIds = new ArraySet<>();
1128     private CarPropertyManager mCarPropertyManager;
1129 
verifyWheelTickConfigArray(int supportedWheels, int wheelToVerify, int configArrayIndex, int wheelTicksToUm)1130     private static void verifyWheelTickConfigArray(int supportedWheels, int wheelToVerify,
1131             int configArrayIndex, int wheelTicksToUm) {
1132         if ((supportedWheels & wheelToVerify) != 0) {
1133             assertWithMessage(
1134                             "WHEEL_TICK configArray["
1135                                     + configArrayIndex
1136                                     + "] must specify the ticks to micrometers for "
1137                                     + wheelToString(wheelToVerify))
1138                     .that(wheelTicksToUm)
1139                     .isGreaterThan(0);
1140         } else {
1141             assertWithMessage(
1142                             "WHEEL_TICK configArray["
1143                                     + configArrayIndex
1144                                     + "] should be zero since "
1145                                     + wheelToString(wheelToVerify)
1146                                     + "is not supported")
1147                     .that(wheelTicksToUm)
1148                     .isEqualTo(0);
1149         }
1150     }
1151 
verifyWheelTickValue( int supportedWheels, int wheelToVerify, int valueIndex, Long ticks)1152     private static void verifyWheelTickValue(
1153             int supportedWheels, int wheelToVerify, int valueIndex, Long ticks) {
1154         if ((supportedWheels & wheelToVerify) == 0) {
1155             assertWithMessage(
1156                             "WHEEL_TICK value["
1157                                     + valueIndex
1158                                     + "] should be zero since "
1159                                     + wheelToString(wheelToVerify)
1160                                     + "is not supported")
1161                     .that(ticks)
1162                     .isEqualTo(0);
1163         }
1164     }
1165 
wheelToString(int wheel)1166     private static String wheelToString(int wheel) {
1167         switch (wheel) {
1168             case VehicleAreaWheel.WHEEL_LEFT_FRONT:
1169                 return "WHEEL_LEFT_FRONT";
1170             case VehicleAreaWheel.WHEEL_RIGHT_FRONT:
1171                 return "WHEEL_RIGHT_FRONT";
1172             case VehicleAreaWheel.WHEEL_RIGHT_REAR:
1173                 return "WHEEL_RIGHT_REAR";
1174             case VehicleAreaWheel.WHEEL_LEFT_REAR:
1175                 return "WHEEL_LEFT_REAR";
1176             default:
1177                 return Integer.toString(wheel);
1178         }
1179     }
1180 
verifyEnumValuesAreDistinct( ImmutableSet<Integer>.... possibleCarPropertyValues)1181     private static void verifyEnumValuesAreDistinct(
1182             ImmutableSet<Integer>... possibleCarPropertyValues) {
1183         ImmutableSet.Builder<Integer> combinedCarPropertyValues = ImmutableSet.<Integer>builder();
1184         int numCarPropertyValues = 0;
1185         for (ImmutableSet<Integer> values: possibleCarPropertyValues) {
1186             combinedCarPropertyValues.addAll(values);
1187             numCarPropertyValues += values.size();
1188         }
1189         int combinedCarPropertyValuesLength = combinedCarPropertyValues.build().size();
1190         assertWithMessage("The number of distinct enum values")
1191                 .that(combinedCarPropertyValuesLength)
1192                 .isEqualTo(numCarPropertyValues);
1193     }
1194 
verifyWindshieldWipersSwitchLevelsAreConsecutive( List<Integer> supportedEnumValues, ImmutableList<Integer> levels, int areaId)1195     private static void verifyWindshieldWipersSwitchLevelsAreConsecutive(
1196             List<Integer> supportedEnumValues, ImmutableList<Integer> levels, int areaId) {
1197         for (int i = 0; i < levels.size(); i++) {
1198             Integer level = levels.get(i);
1199             if (supportedEnumValues.contains(level)) {
1200                 for (int j = i + 1; j < levels.size(); j++) {
1201                     assertWithMessage(
1202                                     "For VehicleAreaWindow area ID " + areaId + ", "
1203                                         + WindshieldWipersSwitch.toString(levels.get(j))
1204                                         + " must be supported if "
1205                                         + WindshieldWipersSwitch.toString(level)
1206                                         + " is supported.")
1207                             .that(levels.get(j))
1208                             .isIn(supportedEnumValues);
1209                 }
1210                 break;
1211             }
1212         }
1213     }
1214 
generateTimeoutMillis(float minSampleRate, long bufferMillis)1215     private static long generateTimeoutMillis(float minSampleRate, long bufferMillis) {
1216         return ((long) ((1.0f / minSampleRate) * SECONDS_TO_MILLIS * UI_RATE_EVENT_COUNTER))
1217                 + bufferMillis;
1218     }
1219 
verifyExpectedPropertiesWhenPermissionsGranted( ImmutableList<Integer> expectedProperties, String... requiredPermissions)1220     private void verifyExpectedPropertiesWhenPermissionsGranted(
1221             ImmutableList<Integer> expectedProperties, String... requiredPermissions) {
1222         runWithShellPermissionIdentity(
1223                 () -> {
1224                     for (CarPropertyConfig<?> carPropertyConfig :
1225                             mCarPropertyManager.getPropertyList()) {
1226                         assertWithMessage(
1227                                 "%s found in CarPropertyManager#getPropertyList() but was not "
1228                                         + "expected to be exposed through %s",
1229                                 VehiclePropertyIds.toString(carPropertyConfig.getPropertyId()),
1230                                 Arrays.toString(requiredPermissions))
1231                                 .that(carPropertyConfig.getPropertyId())
1232                                 .isIn(expectedProperties);
1233                     }
1234                 },
1235                 requiredPermissions);
1236     }
1237 
verifyNoPropertiesExposedWhenCertainPermissionsGranted( String... requiredPermissions)1238     private void verifyNoPropertiesExposedWhenCertainPermissionsGranted(
1239             String... requiredPermissions) {
1240         runWithShellPermissionIdentity(
1241                 () -> {
1242                     assertWithMessage(
1243                             "CarPropertyManager#getPropertyList() excepted to be empty when %s "
1244                                     + "is/are granted but got %s",
1245                                     Arrays.toString(requiredPermissions),
1246                                     mCarPropertyManager.getPropertyList().toString())
1247                             .that(mCarPropertyManager.getPropertyList())
1248                             .isEmpty();
1249                 },
1250                 requiredPermissions);
1251     }
1252 
1253     @Before
setUp()1254     public void setUp() throws Exception {
1255         mCarPropertyManager = (CarPropertyManager) getCar().getCarManager(Car.PROPERTY_SERVICE);
1256         mPropertyIds.add(VehiclePropertyIds.PERF_VEHICLE_SPEED);
1257         mPropertyIds.add(VehiclePropertyIds.GEAR_SELECTION);
1258         mPropertyIds.add(VehiclePropertyIds.NIGHT_MODE);
1259         mPropertyIds.add(VehiclePropertyIds.PARKING_BRAKE_ON);
1260     }
1261 
1262     /**
1263      * Test for {@link CarPropertyManager#getPropertyList()}
1264      */
1265     @Test
testGetPropertyList()1266     public void testGetPropertyList() {
1267         List<CarPropertyConfig> allConfigs = mCarPropertyManager.getPropertyList();
1268         assertThat(allConfigs).isNotNull();
1269     }
1270 
1271     /**
1272      * Test for {@link CarPropertyManager#getPropertyList(ArraySet)}
1273      */
1274     @Test
testGetPropertyListWithArraySet()1275     public void testGetPropertyListWithArraySet() {
1276         runWithShellPermissionIdentity(
1277                 () -> {
1278                     List<CarPropertyConfig> requiredConfigs =
1279                             mCarPropertyManager.getPropertyList(mPropertyIds);
1280                     // Vehicles need to implement all of those properties
1281                     assertThat(requiredConfigs.size()).isEqualTo(mPropertyIds.size());
1282                 },
1283                 Car.PERMISSION_EXTERIOR_ENVIRONMENT,
1284                 Car.PERMISSION_POWERTRAIN,
1285                 Car.PERMISSION_SPEED);
1286     }
1287 
1288     /**
1289      * Test for {@link CarPropertyManager#getCarPropertyConfig(int)}
1290      */
1291     @Test
testGetPropertyConfig()1292     public void testGetPropertyConfig() {
1293         runWithShellPermissionIdentity(
1294                 () -> {
1295                     List<CarPropertyConfig> allConfigs = mCarPropertyManager.getPropertyList();
1296                     for (CarPropertyConfig cfg : allConfigs) {
1297                         assertThat(mCarPropertyManager.getCarPropertyConfig(cfg.getPropertyId()))
1298                                 .isNotNull();
1299                     }
1300                 });
1301     }
1302 
1303     /**
1304      * Test for {@link CarPropertyManager#getAreaId(int, int)}
1305      */
1306     @Test
testGetAreaId()1307     public void testGetAreaId() {
1308         runWithShellPermissionIdentity(
1309                 () -> {
1310                     // For global properties, getAreaId should always return 0.
1311                     List<CarPropertyConfig> allConfigs = mCarPropertyManager.getPropertyList();
1312                     for (CarPropertyConfig cfg : allConfigs) {
1313                         if (cfg.isGlobalProperty()) {
1314                             assertThat(
1315                                             mCarPropertyManager.getAreaId(
1316                                                     cfg.getPropertyId(),
1317                                                     SEAT_ROW_1_LEFT))
1318                                     .isEqualTo(VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL);
1319                         } else {
1320                             int[] areaIds = cfg.getAreaIds();
1321                             // Because areaId in propConfig must not be overlapped with each other.
1322                             // The result should be itself.
1323                             for (int areaIdInConfig : areaIds) {
1324                                 int areaIdByCarPropertyManager =
1325                                         mCarPropertyManager.getAreaId(
1326                                                 cfg.getPropertyId(), areaIdInConfig);
1327                                 assertThat(areaIdByCarPropertyManager).isEqualTo(areaIdInConfig);
1328                             }
1329                         }
1330                     }
1331                 });
1332     }
1333 
1334     @Test
testInvalidMustNotBeImplemented()1335     public void testInvalidMustNotBeImplemented() {
1336         runWithShellPermissionIdentity(
1337                 () -> {
1338                     assertThat(mCarPropertyManager.getCarPropertyConfig(VehiclePropertyIds.INVALID))
1339                             .isNull();
1340                 });
1341     }
1342 
1343     /**
1344      * If the feature flag: FLAG_ANDROID_VIC_VEHICLE_PROPERTIES is disabled, the VIC properties must
1345      * not be supported.
1346      */
1347     @RequiresFlagsDisabled(Flags.FLAG_ANDROID_VIC_VEHICLE_PROPERTIES)
1348     @Test
1349     @ApiTest(
1350             apis = {
1351                 "android.car.hardware.property.CarPropertyManager#getPropertyList",
1352                 "android.car.hardware.property.CarPropertyManager#getCarPropertyConfig",
1353             })
testVicPropertiesMustNotBeSupportedIfFlagDisabled()1354     public void testVicPropertiesMustNotBeSupportedIfFlagDisabled() {
1355         CarSvcPropsParser parser = new CarSvcPropsParser();
1356         List<Integer> vicSystemPropertyIds = parser.getSystemPropertyIdsForFlag(
1357                 "FLAG_ANDROID_VIC_VEHICLE_PROPERTIES");
1358 
1359         List<CarPropertyConfig> configs = new ArrayList<>();
1360         // Use shell permission identity to get as many property configs as possible.
1361         runWithShellPermissionIdentity(() -> {
1362             configs.addAll(mCarPropertyManager.getPropertyList());
1363         });
1364 
1365         for (int i = 0; i < configs.size(); i++) {
1366             int propertyId = configs.get(i).getPropertyId();
1367             if (!isSystemProperty(propertyId)) {
1368                 continue;
1369             }
1370 
1371             String propertyName = VehiclePropertyIds.toString(propertyId);
1372             expectWithMessage("Property: " + propertyName + " must not be supported if "
1373                     + "FLAG_ANDROID_VIC_VEHICLE_PROPERTIES is disabled").that(propertyId)
1374                     .isNotIn(vicSystemPropertyIds);
1375         }
1376 
1377         runWithShellPermissionIdentity(() -> {
1378             for (int propertyId : vicSystemPropertyIds) {
1379                 String propertyName = VehiclePropertyIds.toString(propertyId);
1380                 expectWithMessage("getCarPropertyConfig for: " + propertyName
1381                         + " when FLAG_ANDROID_VIC_VEHICLE_PROPERTIES is disabled must return null")
1382                         .that(mCarPropertyManager.getCarPropertyConfig(propertyId)).isNull();
1383             }
1384         });
1385     }
1386 
1387     /**
1388      * If the feature flag: FLAG_ANDROID_B_VEHICLE_PROPERTIES is disabled, the B properties must
1389      * not be supported.
1390      */
1391     @RequiresFlagsDisabled(Flags.FLAG_ANDROID_B_VEHICLE_PROPERTIES)
1392     @Test
1393     @ApiTest(
1394             apis = {
1395                     "android.car.hardware.property.CarPropertyManager#getPropertyList",
1396                     "android.car.hardware.property.CarPropertyManager#getCarPropertyConfig",
1397             })
testBPropertiesMustNotBeSupportedIfFlagDisabled()1398     public void testBPropertiesMustNotBeSupportedIfFlagDisabled() {
1399         CarSvcPropsParser parser = new CarSvcPropsParser();
1400         List<Integer> bSystemPropertyIds = parser.getSystemPropertyIdsForFlag(
1401                 "FLAG_ANDROID_B_VEHICLE_PROPERTIES");
1402 
1403         List<CarPropertyConfig> configs = new ArrayList<>();
1404         // Use shell permission identity to get as many property configs as possible.
1405         runWithShellPermissionIdentity(() -> {
1406             configs.addAll(mCarPropertyManager.getPropertyList());
1407         });
1408 
1409         for (int i = 0; i < configs.size(); i++) {
1410             int propertyId = configs.get(i).getPropertyId();
1411             if (!isSystemProperty(propertyId)) {
1412                 continue;
1413             }
1414 
1415             String propertyName = VehiclePropertyIds.toString(propertyId);
1416             expectWithMessage("Property: " + propertyName + " must not be supported if "
1417                     + "FLAG_ANDROID_B_VEHICLE_PROPERTIES is disabled").that(propertyId)
1418                     .isNotIn(bSystemPropertyIds);
1419         }
1420 
1421         runWithShellPermissionIdentity(() -> {
1422             for (int propertyId : bSystemPropertyIds) {
1423                 String propertyName = VehiclePropertyIds.toString(propertyId);
1424                 expectWithMessage("getCarPropertyConfig for: " + propertyName
1425                         + " when FLAG_ANDROID_B_VEHICLE_PROPERTIES is disabled must return null")
1426                         .that(mCarPropertyManager.getCarPropertyConfig(propertyId)).isNull();
1427             }
1428         });
1429     }
1430 
1431     /**
1432      * Test that all supported system property IDs are defined.
1433      */
1434     @Test
1435     @ApiTest(
1436             apis = {
1437                 "android.car.hardware.property.CarPropertyManager#getPropertyList",
1438             })
testAllSupportedSystemPropertyIdsAreDefined()1439     public void testAllSupportedSystemPropertyIdsAreDefined() {
1440         CarSvcPropsParser parser = new CarSvcPropsParser();
1441         List<Integer> allSystemPropertyIds = parser.getAllSystemPropertyIds();
1442 
1443         List<CarPropertyConfig> configs = new ArrayList<>();
1444         // Use shell permission identity to get as many property configs as possible.
1445         runWithShellPermissionIdentity(() -> {
1446             configs.addAll(mCarPropertyManager.getPropertyList());
1447         });
1448 
1449         for (int i = 0; i < configs.size(); i++) {
1450             int propertyId = configs.get(i).getPropertyId();
1451             if (!isSystemProperty(propertyId)) {
1452                 continue;
1453             }
1454 
1455             String propertyName = VehiclePropertyIds.toString(propertyId);
1456             expectWithMessage("Property: " + propertyName + " is not a defined system property")
1457                     .that(propertyId)
1458                     .isIn(allSystemPropertyIds);
1459         }
1460     }
1461 
1462     @Test
testAllPropertiesHaveVehiclePropertyVerifier()1463     public void testAllPropertiesHaveVehiclePropertyVerifier() {
1464         Set<Integer> verifierPropertyIds = new ArraySet<>();
1465         for (VehiclePropertyVerifier verifier : getAllVerifiers()) {
1466             expectWithMessage("Verifier for property: " + verifier.getPropertyName()
1467                             + " has been included twice!")
1468                     .that(verifierPropertyIds.add(verifier.getPropertyId())).isTrue();
1469         }
1470 
1471         for (Field field : VehiclePropertyIds.class.getDeclaredFields()) {
1472             boolean isIntConstant = field.getType() == int.class
1473                     && field.getModifiers() == (Modifier.STATIC | Modifier.FINAL | Modifier.PUBLIC);
1474             if (!isIntConstant) {
1475                 continue;
1476             }
1477 
1478             Integer propertyId = null;
1479             try {
1480                 propertyId = field.getInt(null);
1481             } catch (Exception e) {
1482                 assertWithMessage("Failed trying to find value for " + field.getName() + ", " + e)
1483                         .fail();
1484             }
1485             if (PROPERTIES_NOT_EXPOSED_THROUGH_CPM.contains(propertyId)) {
1486                 continue;
1487             }
1488             expectWithMessage("Property: " + VehiclePropertyIds.toString(propertyId) + " does not "
1489                             + "have a VehiclePropertyVerifier included in getAllVerifiers()")
1490                     .that(propertyId).isIn(verifierPropertyIds);
1491         }
1492     }
1493 
1494     static final class AllStepsProvider extends TestParameterValuesProvider {
provideValues(Context context)1495         @Override public List<?> provideValues(Context context) {
1496             return VehiclePropertyVerifier.getAllSteps();
1497         }
1498     }
1499 
1500     static final class AllVerifierBuildersProvider extends TestParameterValuesProvider {
provideValues(Context context)1501         @Override public List<?> provideValues(Context context) {
1502             var parameters = new ArrayList<Object>();
1503             var verifierInfo = getAllVerifierInfo();
1504             for (int i = 0; i < verifierInfo.length; i++) {
1505                 var info = verifierInfo[i];
1506                 String name = VehiclePropertyIds.toString(info.mBuilder.getPropertyId());
1507                 if (info.mBuilder.isRequired()) {
1508                     name = "MustSupport_" + name;
1509                 } else {
1510                     name = "Optional_" + name;
1511                 }
1512                 if (info.mAssumeStandardCC != null) {
1513                     if (info.mAssumeStandardCC) {
1514                         name += "_ assumeStandardCC";
1515                     } else {
1516                         name += "_assumeNonStandardCC";
1517                     }
1518                 }
1519                 parameters.add(value(info).withName(name));
1520             }
1521 
1522             return List.copyOf(parameters);
1523         }
1524     }
1525 
getAllVerifiers()1526     private List<VehiclePropertyVerifier<?>> getAllVerifiers() {
1527         var verifierInfo = getAllVerifierInfo();
1528         var verifiers = new ArrayList<VehiclePropertyVerifier<?>>();
1529         for (int i = 0; i < verifierInfo.length; i++) {
1530             if (verifierInfo[i].mAssumeStandardCC != null && !verifierInfo[i].mAssumeStandardCC) {
1531                 // For some ACC properties, we may have two properties, one for ACC, one for
1532                 // standard CC, here we just pick one.
1533                 // Note that if caller want to actually call the verify function, caller should
1534                 // check whether ACC is enabled first.
1535                 //  TODO(b/375505791): Use a generic verifier that works for all cases here.
1536                 continue;
1537             }
1538             verifiers.add(verifierInfo[i].mBuilder.setCarPropertyManager(mCarPropertyManager)
1539                     .build());
1540         }
1541         return verifiers;
1542     }
1543 
getAllSupportedVerifiers()1544     private List<VehiclePropertyVerifier<?>> getAllSupportedVerifiers() {
1545         Set<Integer> supportedPropertyIds = new ArraySet<>();
1546         try (PermissionContext p = TestApis.permissions().withPermission(
1547                 TestApis.permissions().adoptablePermissions().toArray(new String[0]))) {
1548             var configs = mCarPropertyManager.getPropertyList();
1549             for (int i = 0; i < configs.size(); i++) {
1550                 supportedPropertyIds.add(configs.get(i).getPropertyId());
1551             }
1552         }
1553 
1554         List<VehiclePropertyVerifier<?>> supportedVerifiers = new ArrayList<>();
1555         var allVerifiers = getAllVerifiers();
1556         for (int i = 0; i < allVerifiers.size(); i++) {
1557             if (!supportedPropertyIds.contains(allVerifiers.get(i).getPropertyId())) {
1558                 continue;
1559             }
1560             supportedVerifiers.add(allVerifiers.get(i));
1561         }
1562         return supportedVerifiers;
1563     }
1564 
1565     private static class VerifierInfo {
1566         final VehiclePropertyVerifier.Builder<?> mBuilder;
1567         @Nullable Boolean mAssumeStandardCC;
1568         @Nullable Class<?> mExceptedExceptionClass;
1569         @Nullable String mFlag;
1570 
VerifierInfo(VehiclePropertyVerifier.Builder<?> builder)1571         VerifierInfo(VehiclePropertyVerifier.Builder<?> builder) {
1572             mBuilder = builder;
1573         }
1574 
assumeStandardCC(boolean value)1575         public VerifierInfo assumeStandardCC(boolean value) {
1576             mAssumeStandardCC = value;
1577             return this;
1578         }
1579 
setExceptedExceptionClass(Class<?> exception)1580         public VerifierInfo setExceptedExceptionClass(Class<?> exception) {
1581             mExceptedExceptionClass = exception;
1582             return this;
1583         }
1584 
requireFlag(String flag)1585         public VerifierInfo requireFlag(String flag) {
1586             mFlag = flag;
1587             return this;
1588         }
1589     }
1590 
getAllVerifierInfo()1591     private static VerifierInfo[] getAllVerifierInfo() {
1592         return new VerifierInfo[] {
1593                 new VerifierInfo(getGearSelectionVerifierBuilder()),
1594                 new VerifierInfo(getNightModeVerifierBuilder()),
1595                 new VerifierInfo(getPerfVehicleSpeedVerifierBuilder()),
1596                 new VerifierInfo(getPerfVehicleSpeedDisplayVerifierBuilder()),
1597                 new VerifierInfo(getParkingBrakeOnVerifierBuilder()),
1598                 new VerifierInfo(getEmergencyLaneKeepAssistEnabledVerifierBuilder()),
1599                 new VerifierInfo(getEmergencyLaneKeepAssistStateVerifierBuilder()),
1600                 new VerifierInfo(getCruiseControlEnabledVerifierBuilder()),
1601                 new VerifierInfo(getCruiseControlTypeVerifierBuilder()),
1602                 new VerifierInfo(getCruiseControlStateVerifierBuilder()),
1603                 new VerifierInfo(getCruiseControlCommandVerifierBuilder_OnAdaptiveCruiseControl())
1604                         .assumeStandardCC(false),
1605                 new VerifierInfo(getCruiseControlCommandVerifierBuilder_OnStandardCruiseControl())
1606                         .assumeStandardCC(true),
1607                 new VerifierInfo(getCruiseControlTargetSpeedVerifierBuilder()),
1608                 new VerifierInfo(getAdaptiveCruiseControlTargetTimeGapVerifierBuilder())
1609                         .assumeStandardCC(false),
1610                 new VerifierInfo(getAdaptiveCruiseControlTargetTimeGapVerifierBuilder())
1611                         .assumeStandardCC(true)
1612                         .setExceptedExceptionClass(PropertyNotAvailableException.class),
1613                 new VerifierInfo(
1614                         getAdaptiveCruiseControlLeadVehicleMeasuredDistanceVerifierBuilder())
1615                         .assumeStandardCC(false),
1616                 new VerifierInfo(
1617                         getAdaptiveCruiseControlLeadVehicleMeasuredDistanceVerifierBuilder())
1618                         .assumeStandardCC(true)
1619                         .setExceptedExceptionClass(PropertyNotAvailableException.class),
1620                 new VerifierInfo(getHandsOnDetectionEnabledVerifierBuilder()),
1621                 new VerifierInfo(getHandsOnDetectionDriverStateVerifierBuilder()),
1622                 new VerifierInfo(getHandsOnDetectionWarningVerifierBuilder()),
1623                 new VerifierInfo(getDriverDrowsinessAttentionSystemEnabledVerifierBuilder())
1624                         .requireFlag(Flags.FLAG_ANDROID_VIC_VEHICLE_PROPERTIES),
1625                 new VerifierInfo(getDriverDrowsinessAttentionStateVerifierBuilder())
1626                         .requireFlag(Flags.FLAG_ANDROID_VIC_VEHICLE_PROPERTIES),
1627                 new VerifierInfo(getDriverDrowsinessAttentionWarningEnabledVerifierBuilder())
1628                         .requireFlag(Flags.FLAG_ANDROID_VIC_VEHICLE_PROPERTIES),
1629                 new VerifierInfo(getDriverDrowsinessAttentionWarningVerifierBuilder())
1630                         .requireFlag(Flags.FLAG_ANDROID_VIC_VEHICLE_PROPERTIES),
1631                 new VerifierInfo(getDriverDistractionSystemEnabledVerifierBuilder())
1632                         .requireFlag(Flags.FLAG_ANDROID_VIC_VEHICLE_PROPERTIES),
1633                 new VerifierInfo(getDriverDistractionStateVerifierBuilder())
1634                         .requireFlag(Flags.FLAG_ANDROID_VIC_VEHICLE_PROPERTIES),
1635                 new VerifierInfo(getDriverDistractionWarningEnabledVerifierBuilder())
1636                         .requireFlag(Flags.FLAG_ANDROID_VIC_VEHICLE_PROPERTIES),
1637                 new VerifierInfo(getDriverDistractionWarningVerifierBuilder())
1638                         .requireFlag(Flags.FLAG_ANDROID_VIC_VEHICLE_PROPERTIES),
1639                 new VerifierInfo(getWheelTickVerifierBuilder()),
1640                 new VerifierInfo(getInfoVinVerifierBuilder()),
1641                 new VerifierInfo(getInfoMakeVerifierBuilder()),
1642                 new VerifierInfo(getInfoModelVerifierBuilder()),
1643                 new VerifierInfo(getInfoModelYearVerifierBuilder()),
1644                 new VerifierInfo(getInfoFuelCapacityVerifierBuilder()),
1645                 new VerifierInfo(getInfoFuelTypeVerifierBuilder()),
1646                 new VerifierInfo(getInfoEvBatteryCapacityVerifierBuilder()),
1647                 new VerifierInfo(getInfoEvConnectorTypeVerifierBuilder()),
1648                 new VerifierInfo(getInfoFuelDoorLocationVerifierBuilder()),
1649                 new VerifierInfo(getInfoEvPortLocationVerifierBuilder()),
1650                 new VerifierInfo(getInfoMultiEvPortLocationsVerifierBuilder()),
1651                 new VerifierInfo(getInfoDriverSeatVerifierBuilder()),
1652                 new VerifierInfo(getInfoExteriorDimensionsVerifierBuilder()),
1653                 new VerifierInfo(getEpochTimeVerifierBuilder()),
1654                 new VerifierInfo(getLocationCharacterizationVerifierBuilder()),
1655                 new VerifierInfo(getUltrasonicsSensorPositionVerifierBuilder())
1656                         .requireFlag(Flags.FLAG_ANDROID_VIC_VEHICLE_PROPERTIES),
1657                 new VerifierInfo(getUltrasonicsSensorOrientationVerifierBuilder())
1658                         .requireFlag(Flags.FLAG_ANDROID_VIC_VEHICLE_PROPERTIES),
1659                 new VerifierInfo(getUltrasonicsSensorFieldOfViewVerifierBuilder())
1660                         .requireFlag(Flags.FLAG_ANDROID_VIC_VEHICLE_PROPERTIES),
1661                 new VerifierInfo(getUltrasonicsSensorDetectionRangeVerifierBuilder())
1662                         .requireFlag(Flags.FLAG_ANDROID_VIC_VEHICLE_PROPERTIES),
1663                 new VerifierInfo(getUltrasonicsSensorSupportedRangesVerifierBuilder())
1664                         .requireFlag(Flags.FLAG_ANDROID_VIC_VEHICLE_PROPERTIES),
1665                 new VerifierInfo(getUltrasonicsSensorMeasuredDistanceVerifierBuilder())
1666                         .requireFlag(Flags.FLAG_ANDROID_VIC_VEHICLE_PROPERTIES),
1667                 new VerifierInfo(getElectronicTollCollectionCardTypeVerifierBuilder()),
1668                 new VerifierInfo(getElectronicTollCollectionCardStatusVerifierBuilder()),
1669                 new VerifierInfo(getGeneralSafetyRegulationComplianceVerifierBuilder()),
1670                 new VerifierInfo(getEnvOutsideTemperatureVerifierBuilder()),
1671                 new VerifierInfo(getCurrentGearVerifierBuilder()),
1672                 new VerifierInfo(getParkingBrakeAutoApplyVerifierBuilder()),
1673                 new VerifierInfo(getIgnitionStateVerifierBuilder()),
1674                 new VerifierInfo(getEvBrakeRegenerationLevelVerifierBuilder()),
1675                 new VerifierInfo(getEvStoppingModeVerifierBuilder()),
1676                 new VerifierInfo(getAbsActiveVerifierBuilder()),
1677                 new VerifierInfo(getTractionControlActiveVerifierBuilder()),
1678                 new VerifierInfo(getDoorPosVerifierBuilder()),
1679                 new VerifierInfo(getDoorMoveVerifierBuilder()),
1680                 new VerifierInfo(getDoorLockVerifierBuilder()),
1681                 new VerifierInfo(getDoorChildLockEnabledVerifierBuilder()),
1682                 new VerifierInfo(getVehicleDrivingAutomationCurrentLevelVerifierBuilder())
1683                         .requireFlag(Flags.FLAG_ANDROID_VIC_VEHICLE_PROPERTIES),
1684                 new VerifierInfo(getMirrorZPosVerifierBuilder()),
1685                 new VerifierInfo(getMirrorZMoveVerifierBuilder()),
1686                 new VerifierInfo(getMirrorYPosVerifierBuilder()),
1687                 new VerifierInfo(getMirrorYMoveVerifierBuilder()),
1688                 new VerifierInfo(getMirrorLockVerifierBuilder()),
1689                 new VerifierInfo(getMirrorFoldVerifierBuilder()),
1690                 new VerifierInfo(getMirrorAutoFoldEnabledVerifierBuilder()),
1691                 new VerifierInfo(getMirrorAutoTiltEnabledVerifierBuilder()),
1692                 new VerifierInfo(getWindowPosVerifierBuilder()),
1693                 new VerifierInfo(getWindowMoveVerifierBuilder()),
1694                 new VerifierInfo(getWindowLockVerifierBuilder()),
1695                 new VerifierInfo(getWindshieldWipersPeriodVerifierBuilder()),
1696                 new VerifierInfo(getWindshieldWipersStateVerifierBuilder()),
1697                 new VerifierInfo(getWindshieldWipersSwitchVerifierBuilder()),
1698                 new VerifierInfo(getSteeringWheelDepthPosVerifierBuilder()),
1699                 new VerifierInfo(getSteeringWheelDepthMoveVerifierBuilder()),
1700                 new VerifierInfo(getSteeringWheelHeightPosVerifierBuilder()),
1701                 new VerifierInfo(getSteeringWheelHeightMoveVerifierBuilder()),
1702                 new VerifierInfo(getSteeringWheelTheftLockEnabledVerifierBuilder()),
1703                 new VerifierInfo(getSteeringWheelLockedVerifierBuilder()),
1704                 new VerifierInfo(getSteeringWheelEasyAccessEnabledVerifierBuilder()),
1705                 new VerifierInfo(getGloveBoxDoorPosVerifierBuilder()),
1706                 new VerifierInfo(getGloveBoxLockedVerifierBuilder()),
1707                 new VerifierInfo(getDistanceDisplayUnitsVerifierBuilder()),
1708                 new VerifierInfo(getFuelVolumeDisplayUnitsVerifierBuilder()),
1709                 new VerifierInfo(getTirePressureVerifierBuilder()),
1710                 new VerifierInfo(getCriticallyLowTirePressureVerifierBuilder()),
1711                 new VerifierInfo(getTirePressureDisplayUnitsVerifierBuilder()),
1712                 new VerifierInfo(getEvBatteryDisplayUnitsVerifierBuilder()),
1713                 new VerifierInfo(getVehicleSpeedDisplayUnitsVerifierBuilder()),
1714                 new VerifierInfo(getFuelConsumptionUnitsDistanceOverVolumeVerifierBuilder()),
1715                 new VerifierInfo(getFuelLevelVerifierBuilder()),
1716                 new VerifierInfo(getEvBatteryLevelVerifierBuilder()),
1717                 new VerifierInfo(getEvCurrentBatteryCapacityVerifierBuilder()),
1718                 new VerifierInfo(getEvBatteryInstantaneousChargeRateVerifierBuilder()),
1719                 new VerifierInfo(getRangeRemainingVerifierBuilder()),
1720                 new VerifierInfo(getEvBatteryAverageTemperatureVerifierBuilder())
1721                         .requireFlag(Flags.FLAG_ANDROID_VIC_VEHICLE_PROPERTIES),
1722                 new VerifierInfo(getFuelLevelLowVerifierBuilder()),
1723                 new VerifierInfo(getFuelDoorOpenVerifierBuilder()),
1724                 new VerifierInfo(getEvChargePortOpenVerifierBuilder()),
1725                 new VerifierInfo(getEvChargePortConnectedVerifierBuilder()),
1726                 new VerifierInfo(getEvChargeCurrentDrawLimitVerifierBuilder()),
1727                 new VerifierInfo(getEvChargePercentLimitVerifierBuilder()),
1728                 new VerifierInfo(getEvChargeStateVerifierBuilder()),
1729                 new VerifierInfo(getEvChargeSwitchVerifierBuilder()),
1730                 new VerifierInfo(getEvChargeTimeRemainingVerifierBuilder()),
1731                 new VerifierInfo(getEvRegenerativeBrakingStateVerifierBuilder()),
1732                 new VerifierInfo(getPerfSteeringAngleVerifierBuilder()),
1733                 new VerifierInfo(getPerfRearSteeringAngleVerifierBuilder()),
1734                 new VerifierInfo(getEngineCoolantTempVerifierBuilder()),
1735                 new VerifierInfo(getEngineOilLevelVerifierBuilder()),
1736                 new VerifierInfo(getEngineOilTempVerifierBuilder()),
1737                 new VerifierInfo(getEngineRpmVerifierBuilder()),
1738                 new VerifierInfo(getEngineIdleAutoStopEnabledVerifierBuilder()),
1739                 new VerifierInfo(getImpactDetectedVerifierBuilder())
1740                         .requireFlag(Flags.FLAG_ANDROID_VIC_VEHICLE_PROPERTIES),
1741                 new VerifierInfo(getPerfOdometerVerifierBuilder()),
1742                 new VerifierInfo(getTurnSignalStateVerifierBuilder()),
1743                 new VerifierInfo(getHeadlightsStateVerifierBuilder()),
1744                 new VerifierInfo(getHighBeamLightsStateVerifierBuilder()),
1745                 new VerifierInfo(getFogLightsStateVerifierBuilder()),
1746                 new VerifierInfo(getHazardLightsStateVerifierBuilder()),
1747                 new VerifierInfo(getFrontFogLightsStateVerifierBuilder()),
1748                 new VerifierInfo(getRearFogLightsStateVerifierBuilder()),
1749                 new VerifierInfo(getCabinLightsStateVerifierBuilder()),
1750                 new VerifierInfo(getReadingLightsStateVerifierBuilder()),
1751                 new VerifierInfo(getSteeringWheelLightsStateVerifierBuilder()),
1752                 new VerifierInfo(getVehicleCurbWeightVerifierBuilder()),
1753                 new VerifierInfo(getHeadlightsSwitchVerifierBuilder()),
1754                 new VerifierInfo(getTrailerPresentVerifierBuilder()),
1755                 new VerifierInfo(getHighBeamLightsSwitchVerifierBuilder()),
1756                 new VerifierInfo(getFogLightsSwitchVerifierBuilder()),
1757                 new VerifierInfo(getHazardLightsSwitchVerifierBuilder()),
1758                 new VerifierInfo(getFrontFogLightsSwitchVerifierBuilder()),
1759                 new VerifierInfo(getRearFogLightsSwitchVerifierBuilder()),
1760                 new VerifierInfo(getCabinLightsSwitchVerifierBuilder()),
1761                 new VerifierInfo(getReadingLightsSwitchVerifierBuilder()),
1762                 new VerifierInfo(getSteeringWheelLightsSwitchVerifierBuilder()),
1763                 new VerifierInfo(getSeatMemorySelectVerifierBuilder()),
1764                 new VerifierInfo(getSeatMemorySetVerifierBuilder()),
1765                 new VerifierInfo(getSeatBeltBuckledVerifierBuilder()),
1766                 new VerifierInfo(getSeatBeltHeightPosVerifierBuilder()),
1767                 new VerifierInfo(getSeatBeltHeightMoveVerifierBuilder()),
1768                 new VerifierInfo(getSeatForeAftPosVerifierBuilder()),
1769                 new VerifierInfo(getSeatForeAftMoveVerifierBuilder()),
1770                 new VerifierInfo(getSeatBackrestAngle1PosVerifierBuilder()),
1771                 new VerifierInfo(getSeatBackrestAngle1MoveVerifierBuilder()),
1772                 new VerifierInfo(getSeatBackrestAngle2PosVerifierBuilder()),
1773                 new VerifierInfo(getSeatBackrestAngle2MoveVerifierBuilder()),
1774                 new VerifierInfo(getSeatHeightPosVerifierBuilder()),
1775                 new VerifierInfo(getSeatHeightMoveVerifierBuilder()),
1776                 new VerifierInfo(getSeatDepthPosVerifierBuilder()),
1777                 new VerifierInfo(getSeatDepthMoveVerifierBuilder()),
1778                 new VerifierInfo(getSeatTiltPosVerifierBuilder()),
1779                 new VerifierInfo(getSeatTiltMoveVerifierBuilder()),
1780                 new VerifierInfo(getSeatLumbarForeAftPosVerifierBuilder()),
1781                 new VerifierInfo(getSeatLumbarForeAftMoveVerifierBuilder()),
1782                 new VerifierInfo(getSeatLumbarSideSupportPosVerifierBuilder()),
1783                 new VerifierInfo(getSeatLumbarSideSupportMoveVerifierBuilder()),
1784                 new VerifierInfo(getSeatHeadrestHeightPosV2VerifierBuilder()),
1785                 new VerifierInfo(getSeatHeadrestHeightMoveVerifierBuilder()),
1786                 new VerifierInfo(getSeatHeadrestAnglePosVerifierBuilder()),
1787                 new VerifierInfo(getSeatHeadrestAngleMoveVerifierBuilder()),
1788                 new VerifierInfo(getSeatHeadrestForeAftPosVerifierBuilder()),
1789                 new VerifierInfo(getSeatHeadrestForeAftMoveVerifierBuilder()),
1790                 new VerifierInfo(getSeatFootwellLightsStateVerifierBuilder()),
1791                 new VerifierInfo(getSeatFootwellLightsSwitchVerifierBuilder()),
1792                 new VerifierInfo(getSeatEasyAccessEnabledVerifierBuilder()),
1793                 new VerifierInfo(getSeatAirbagEnabledVerifierBuilder()),
1794                 new VerifierInfo(getSeatCushionSideSupportPosVerifierBuilder()),
1795                 new VerifierInfo(getSeatCushionSideSupportMoveVerifierBuilder()),
1796                 new VerifierInfo(getSeatLumberVerticalPosVerifierBuilder()),
1797                 new VerifierInfo(getSeatLumberVerticalMoveVerifierBuilder()),
1798                 new VerifierInfo(getSeatWalkInPosVerifierBuilder()),
1799                 new VerifierInfo(getSeatAirbagsDeployedVerifierBuilder())
1800                         .requireFlag(Flags.FLAG_ANDROID_VIC_VEHICLE_PROPERTIES),
1801                 new VerifierInfo(getSeatBeltPretensionerDeployedVerifierBuilder())
1802                         .requireFlag(Flags.FLAG_ANDROID_VIC_VEHICLE_PROPERTIES),
1803                 new VerifierInfo(getValetModeEnabledVerifierBuilder())
1804                         .requireFlag(Flags.FLAG_ANDROID_VIC_VEHICLE_PROPERTIES),
1805                 new VerifierInfo(getHeadUpDisplayEnabledVerifierBuilder())
1806                         .requireFlag(Flags.FLAG_ANDROID_VIC_VEHICLE_PROPERTIES),
1807                 new VerifierInfo(getSeatOccupancyVerifierBuilder()),
1808                 new VerifierInfo(getHvacDefrosterVerifierBuilder()),
1809                 new VerifierInfo(getHvacElectricDefrosterOnVerifierBuilder()),
1810                 new VerifierInfo(getHvacSideMirrorHeatVerifierBuilder()),
1811                 new VerifierInfo(getHvacSteeringWheelHeatVerifierBuilder()),
1812                 new VerifierInfo(getHvacTemperatureDisplayUnitsVerifierBuilder()),
1813                 new VerifierInfo(getHvacTemperatureValueSuggestionVerifierBuilder()),
1814                 new VerifierInfo(getHvacPowerOnVerifierBuilder()),
1815                 new VerifierInfo(getHvacFanSpeedVerifierBuilder()),
1816                 new VerifierInfo(getHvacFanDirectionAvailableVerifierBuilder()),
1817                 new VerifierInfo(getHvacFanDirectionVerifierBuilder()),
1818                 new VerifierInfo(getHvacTemperatureCurrentVerifierBuilder()),
1819                 new VerifierInfo(getHvacTemperatureSetVerifierBuilder()),
1820                 new VerifierInfo(getHvacAcOnVerifierBuilder()),
1821                 new VerifierInfo(getHvacMaxAcOnVerifierBuilder()),
1822                 new VerifierInfo(getHvacMaxDefrostOnVerifierBuilder()),
1823                 new VerifierInfo(getHvacRecircOnVerifierBuilder()),
1824                 new VerifierInfo(getHvacAutoOnVerifierBuilder()),
1825                 new VerifierInfo(getHvacSeatTemperatureVerifierBuilder()),
1826                 new VerifierInfo(getHvacActualFanSpeedRpmVerifierBuilder()),
1827                 new VerifierInfo(getHvacAutoRecircOnVerifierBuilder()),
1828                 new VerifierInfo(getHvacSeatVentilationVerifierBuilder()),
1829                 new VerifierInfo(getHvacDualOnVerifierBuilder()),
1830                 new VerifierInfo(getAutomaticEmergencyBrakingEnabledVerifierBuilder()),
1831                 new VerifierInfo(getAutomaticEmergencyBrakingStateVerifierBuilder()),
1832                 new VerifierInfo(getForwardCollisionWarningEnabledVerifierBuilder()),
1833                 new VerifierInfo(getForwardCollisionWarningStateVerifierBuilder()),
1834                 new VerifierInfo(getBlindSpotWarningEnabledVerifierBuilder()),
1835                 new VerifierInfo(getBlindSpotWarningStateVerifierBuilder()),
1836                 new VerifierInfo(getLaneDepartureWarningEnabledVerifierBuilder()),
1837                 new VerifierInfo(getLaneDepartureWarningStateVerifierBuilder()),
1838                 new VerifierInfo(getLaneKeepAssistEnabledVerifierBuilder()),
1839                 new VerifierInfo(getLaneKeepAssistStateVerifierBuilder()),
1840                 new VerifierInfo(getLaneCenteringAssistEnabledVerifierBuilder()),
1841                 new VerifierInfo(getLaneCenteringAssistCommandVerifierBuilder()),
1842                 new VerifierInfo(getLaneCenteringAssistStateVerifierBuilder()),
1843                 new VerifierInfo(getLowSpeedCollisionWarningEnabledVerifierBuilder())
1844                         .requireFlag(Flags.FLAG_ANDROID_VIC_VEHICLE_PROPERTIES),
1845                 new VerifierInfo(getLowSpeedCollisionWarningStateVerifierBuilder())
1846                         .requireFlag(Flags.FLAG_ANDROID_VIC_VEHICLE_PROPERTIES),
1847                 new VerifierInfo(getElectronicStabilityControlStateVerifierBuilder())
1848                         .requireFlag(Flags.FLAG_ANDROID_VIC_VEHICLE_PROPERTIES),
1849                 new VerifierInfo(getElectronicStabilityControlEnabledVerifierBuilder())
1850                         .requireFlag(Flags.FLAG_ANDROID_VIC_VEHICLE_PROPERTIES),
1851                 new VerifierInfo(getCrossTrafficMonitoringEnabledVerifierBuilder())
1852                         .requireFlag(Flags.FLAG_ANDROID_VIC_VEHICLE_PROPERTIES),
1853                 new VerifierInfo(getCrossTrafficMonitoringWarningStateVerifierBuilder())
1854                         .requireFlag(Flags.FLAG_ANDROID_VIC_VEHICLE_PROPERTIES),
1855                 new VerifierInfo(getLowSpeedAutomaticEmergencyBrakingEnabledVerifierBuilder())
1856                         .requireFlag(Flags.FLAG_ANDROID_VIC_VEHICLE_PROPERTIES),
1857                 new VerifierInfo(getLowSpeedAutomaticEmergencyBrakingStateVerifierBuilder())
1858                         .requireFlag(Flags.FLAG_ANDROID_VIC_VEHICLE_PROPERTIES),
1859                 new VerifierInfo(VehiclePropertyVerifiers.getInfoModelTrimVerifierBuilder())
1860                         .requireFlag(Flags.FLAG_ANDROID_B_VEHICLE_PROPERTIES),
1861                 new VerifierInfo(VehiclePropertyVerifiers.getInfoVehicleSizeClassVerifierBuilder())
1862                         .requireFlag(Flags.FLAG_ANDROID_B_VEHICLE_PROPERTIES),
1863                 new VerifierInfo(VehiclePropertyVerifiers.getTurnSignalLightStateVerifierBuilder())
1864                         .requireFlag(Flags.FLAG_ANDROID_B_VEHICLE_PROPERTIES),
1865                 new VerifierInfo(VehiclePropertyVerifiers.getTurnSignalSwitchVerifierBuilder())
1866                         .requireFlag(Flags.FLAG_ANDROID_B_VEHICLE_PROPERTIES),
1867                 new VerifierInfo(
1868                         VehiclePropertyVerifiers.getInstantaneousFuelEconomyVerifierBuilder())
1869                         .requireFlag(Flags.FLAG_ANDROID_B_VEHICLE_PROPERTIES),
1870                 new VerifierInfo(
1871                         VehiclePropertyVerifiers.getInstantaneousEvEfficiencyVerifierBuilder())
1872                         .requireFlag(Flags.FLAG_ANDROID_B_VEHICLE_PROPERTIES),
1873                 new VerifierInfo(VehiclePropertyVerifiers.getVehicleHornEngagedVerifierBuilder())
1874                         .requireFlag(Flags.FLAG_ANDROID_B_VEHICLE_PROPERTIES),
1875                 new VerifierInfo(VehiclePropertyVerifiers
1876                                 .getVehicleDrivingAutomationTargetLevelVerifierBuilder())
1877                         .requireFlag(Flags.FLAG_ANDROID_B_VEHICLE_PROPERTIES),
1878                 new VerifierInfo(VehiclePropertyVerifiers
1879                                 .getAcceleratorPedalCompressionPercentageVerifierBuilder())
1880                         .requireFlag(Flags.FLAG_ANDROID_B_VEHICLE_PROPERTIES),
1881                 new VerifierInfo(VehiclePropertyVerifiers
1882                                 .getBrakePedalCompressionPercentageVerifierBuilder())
1883                         .requireFlag(Flags.FLAG_ANDROID_B_VEHICLE_PROPERTIES),
1884                 new VerifierInfo(
1885                         VehiclePropertyVerifiers.getBrakePadWearPercentageVerifierBuilder())
1886                         .requireFlag(Flags.FLAG_ANDROID_B_VEHICLE_PROPERTIES),
1887                 new VerifierInfo(VehiclePropertyVerifiers.getBrakeFluidLevelLowVerifierBuilder())
1888                         .requireFlag(Flags.FLAG_ANDROID_B_VEHICLE_PROPERTIES),
1889                 new VerifierInfo(
1890                         VehiclePropertyVerifiers.getVehiclePassiveSuspensionHeightVerifierBuilder())
1891                         .requireFlag(Flags.FLAG_ANDROID_B_VEHICLE_PROPERTIES),
1892         };
1893     }
1894 
1895     @CddTest(requirements = {"2.5.1"})
1896     @Test
testIndividualProperty( @estParametervaluesProvider = AllVerifierBuildersProvider.class) VerifierInfo verifierInfo, @TestParameter(valuesProvider = AllStepsProvider.class) String step)1897     public void testIndividualProperty(
1898             @TestParameter(valuesProvider = AllVerifierBuildersProvider.class)
1899                     VerifierInfo verifierInfo,
1900             @TestParameter(valuesProvider = AllStepsProvider.class) String step) {
1901         // Check preconditions.
1902         var flag = verifierInfo.mFlag;
1903         if (flag != null) {
1904             switch (flag) {
1905                 case Flags.FLAG_ANDROID_VIC_VEHICLE_PROPERTIES:
1906                     assumeTrue(
1907                             "Flag: " + flag + " is disabled ", Flags.androidVicVehicleProperties());
1908                     break;
1909                 case Flags.FLAG_VEHICLE_PROPERTY_25Q2_3P_PERMISSIONS:
1910                     // Do nothing as property should be supported when this flag is enabled and when
1911                     // it is disabled.
1912                     break;
1913                 case Flags.FLAG_ANDROID_B_VEHICLE_PROPERTIES:
1914                     assumeTrue("Flag: " + flag + " is disabled ",
1915                             Flags.androidBVehicleProperties());
1916                     break;
1917                 default:
1918                     throw new IllegalStateException("Unknown flag: " + flag);
1919             }
1920         }
1921         if (verifierInfo.mAssumeStandardCC != null) {
1922             if (verifierInfo.mAssumeStandardCC) {
1923                 assumeTrue(
1924                         "Cruise control is not enabled or cannot be set/enabled or is not set to "
1925                         + "standard, skip testing standard CC behavior",
1926                         standardCruiseControlChecker(true));
1927             } else {
1928                 assumeTrue("Cruise control is not enabled or cannot be set/enabled or is set to "
1929                         + "standard, skip testing non-standard CC behavior",
1930                         standardCruiseControlChecker(false));
1931             }
1932         }
1933 
1934         // Run the verification.
1935         var verifier = verifierInfo.mBuilder.setCarPropertyManager(mCarPropertyManager).build();
1936         verifier.verify(step, verifierInfo.mExceptedExceptionClass);
1937     }
1938 
getGearSelectionVerifierBuilder()1939     private static VehiclePropertyVerifier.Builder<Integer> getGearSelectionVerifierBuilder() {
1940         return VehiclePropertyVerifier.newBuilder(
1941                         VehiclePropertyIds.GEAR_SELECTION,
1942                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ,
1943                         VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
1944                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
1945                         Integer.class)
1946                 .requireProperty()
1947                 .setAllPossibleEnumValues(VEHICLE_GEARS)
1948                 .setPossibleConfigArrayValues(VEHICLE_GEARS)
1949                 .requirePropertyValueTobeInConfigArray()
1950                 .addReadPermission(Car.PERMISSION_POWERTRAIN);
1951     }
1952 
getNightModeVerifierBuilder()1953     private static VehiclePropertyVerifier.Builder<Boolean> getNightModeVerifierBuilder() {
1954         return VehiclePropertyVerifier.newBuilder(
1955                         VehiclePropertyIds.NIGHT_MODE,
1956                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ,
1957                         VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
1958                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
1959                         Boolean.class)
1960                 .requireProperty()
1961                 .addReadPermission(Car.PERMISSION_EXTERIOR_ENVIRONMENT);
1962     }
1963 
getPerfVehicleSpeedVerifierBuilder()1964     private static VehiclePropertyVerifier.Builder<Float> getPerfVehicleSpeedVerifierBuilder() {
1965         return VehiclePropertyVerifier.newBuilder(
1966                         VehiclePropertyIds.PERF_VEHICLE_SPEED,
1967                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ,
1968                         VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
1969                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_CONTINUOUS,
1970                         Float.class)
1971                 .requireProperty()
1972                 .addReadPermission(Car.PERMISSION_SPEED);
1973     }
1974 
1975     private static VehiclePropertyVerifier.Builder<Float>
getPerfVehicleSpeedDisplayVerifierBuilder()1976             getPerfVehicleSpeedDisplayVerifierBuilder() {
1977         return VehiclePropertyVerifier.newBuilder(
1978                         VehiclePropertyIds.PERF_VEHICLE_SPEED_DISPLAY,
1979                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ,
1980                         VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
1981                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_CONTINUOUS,
1982                         Float.class)
1983                 .addReadPermission(Car.PERMISSION_SPEED);
1984     }
1985 
getParkingBrakeOnVerifierBuilder()1986     private static VehiclePropertyVerifier.Builder<Boolean> getParkingBrakeOnVerifierBuilder() {
1987         return VehiclePropertyVerifier.newBuilder(
1988                         VehiclePropertyIds.PARKING_BRAKE_ON,
1989                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ,
1990                         VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
1991                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
1992                         Boolean.class)
1993                 .requireProperty()
1994                 .addReadPermission(Car.PERMISSION_POWERTRAIN);
1995     }
1996 
1997     private static VehiclePropertyVerifier.Builder<Boolean>
getEmergencyLaneKeepAssistEnabledVerifierBuilder()1998             getEmergencyLaneKeepAssistEnabledVerifierBuilder() {
1999         return VehiclePropertyVerifier.newBuilder(
2000                         VehiclePropertyIds.EMERGENCY_LANE_KEEP_ASSIST_ENABLED,
2001                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE,
2002                         VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
2003                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
2004                         Boolean.class)
2005                 .addReadPermission(Car.PERMISSION_READ_ADAS_SETTINGS)
2006                 .addReadPermission(Car.PERMISSION_CONTROL_ADAS_SETTINGS)
2007                 .addWritePermission(Car.PERMISSION_CONTROL_ADAS_SETTINGS);
2008     }
2009 
2010     private static VehiclePropertyVerifier.Builder<Integer>
getEmergencyLaneKeepAssistStateVerifierBuilder()2011             getEmergencyLaneKeepAssistStateVerifierBuilder() {
2012         ImmutableSet<Integer> possibleEnumValues = ImmutableSet.<Integer>builder()
2013                 .addAll(EMERGENCY_LANE_KEEP_ASSIST_STATES)
2014                 .addAll(ERROR_STATES)
2015                 .build();
2016 
2017         return VehiclePropertyVerifier.newBuilder(
2018                         VehiclePropertyIds.EMERGENCY_LANE_KEEP_ASSIST_STATE,
2019                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ,
2020                         VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
2021                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
2022                         Integer.class)
2023                 .setAllPossibleEnumValues(possibleEnumValues)
2024                 .setDependentOnProperty(VehiclePropertyIds.EMERGENCY_LANE_KEEP_ASSIST_ENABLED,
2025                         ImmutableSet.of(Car.PERMISSION_READ_ADAS_SETTINGS,
2026                                 Car.PERMISSION_CONTROL_ADAS_SETTINGS))
2027                 .verifyErrorStates()
2028                 .addReadPermission(Car.PERMISSION_READ_ADAS_STATES);
2029     }
2030 
2031     @Test
testEmergencyLaneKeepAssistStateAndErrorStateDontIntersect()2032     public void testEmergencyLaneKeepAssistStateAndErrorStateDontIntersect() {
2033         verifyEnumValuesAreDistinct(EMERGENCY_LANE_KEEP_ASSIST_STATES, ERROR_STATES);
2034     }
2035 
2036     private static VehiclePropertyVerifier.Builder<Boolean>
getCruiseControlEnabledVerifierBuilder()2037             getCruiseControlEnabledVerifierBuilder() {
2038         return VehiclePropertyVerifier.newBuilder(
2039                         VehiclePropertyIds.CRUISE_CONTROL_ENABLED,
2040                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE,
2041                         VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
2042                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
2043                         Boolean.class)
2044                 .addReadPermission(Car.PERMISSION_READ_ADAS_SETTINGS)
2045                 .addReadPermission(Car.PERMISSION_CONTROL_ADAS_SETTINGS)
2046                 .addWritePermission(Car.PERMISSION_CONTROL_ADAS_SETTINGS);
2047     }
2048 
getCruiseControlTypeVerifierBuilder()2049     private static VehiclePropertyVerifier.Builder<Integer> getCruiseControlTypeVerifierBuilder() {
2050         ImmutableSet<Integer> possibleEnumValues = ImmutableSet.<Integer>builder()
2051                 .addAll(CRUISE_CONTROL_TYPES)
2052                 .addAll(ERROR_STATES)
2053                 .build();
2054 
2055         return VehiclePropertyVerifier.newBuilder(
2056                         VehiclePropertyIds.CRUISE_CONTROL_TYPE,
2057                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE,
2058                         VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
2059                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
2060                         Integer.class)
2061                 .setAllPossibleEnumValues(possibleEnumValues)
2062                 .setAllPossibleUnwritableValues(CRUISE_CONTROL_TYPE_UNWRITABLE_STATES)
2063                 .setDependentOnProperty(VehiclePropertyIds.CRUISE_CONTROL_ENABLED,
2064                         ImmutableSet.of(Car.PERMISSION_READ_ADAS_SETTINGS,
2065                                 Car.PERMISSION_CONTROL_ADAS_SETTINGS))
2066                 .verifyErrorStates()
2067                 .addReadPermission(Car.PERMISSION_READ_ADAS_STATES)
2068                 .addReadPermission(Car.PERMISSION_CONTROL_ADAS_STATES)
2069                 .addWritePermission(Car.PERMISSION_CONTROL_ADAS_STATES);
2070     }
2071 
2072     @Test
testCruiseControlTypeAndErrorStateDontIntersect()2073     public void testCruiseControlTypeAndErrorStateDontIntersect() {
2074         verifyEnumValuesAreDistinct(CRUISE_CONTROL_TYPES, ERROR_STATES);
2075     }
2076 
getCruiseControlStateVerifierBuilder()2077     private static VehiclePropertyVerifier.Builder<Integer> getCruiseControlStateVerifierBuilder() {
2078         ImmutableSet<Integer> possibleEnumValues = ImmutableSet.<Integer>builder()
2079                 .addAll(CRUISE_CONTROL_STATES)
2080                 .addAll(ERROR_STATES)
2081                 .build();
2082 
2083         return VehiclePropertyVerifier.newBuilder(
2084                         VehiclePropertyIds.CRUISE_CONTROL_STATE,
2085                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ,
2086                         VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
2087                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
2088                         Integer.class)
2089                 .setAllPossibleEnumValues(possibleEnumValues)
2090                 .setDependentOnProperty(VehiclePropertyIds.CRUISE_CONTROL_ENABLED,
2091                         ImmutableSet.of(Car.PERMISSION_READ_ADAS_SETTINGS,
2092                                 Car.PERMISSION_CONTROL_ADAS_SETTINGS))
2093                 .verifyErrorStates()
2094                 .addReadPermission(Car.PERMISSION_READ_ADAS_STATES);
2095     }
2096 
2097     @Test
testCruiseControlStateAndErrorStateDontIntersect()2098     public void testCruiseControlStateAndErrorStateDontIntersect() {
2099         verifyEnumValuesAreDistinct(CRUISE_CONTROL_STATES, ERROR_STATES);
2100     }
2101 
standardCruiseControlChecker(boolean requireStandard)2102     private boolean standardCruiseControlChecker(boolean requireStandard) {
2103         VehiclePropertyVerifier<Integer> verifier = getCruiseControlTypeVerifierBuilder()
2104                 .setCarPropertyManager(mCarPropertyManager).build();
2105         try {
2106             verifier.enableAdasFeatureIfAdasStateProperty();
2107             AtomicBoolean isMetStandardConditionCheck = new AtomicBoolean(false);
2108             runWithShellPermissionIdentity(
2109                     () -> {
2110                         try {
2111                             boolean ccEnabledValue = mCarPropertyManager
2112                                     .getBooleanProperty(VehiclePropertyIds.CRUISE_CONTROL_ENABLED,
2113                                             /* areaId */ 0);
2114                             if (!ccEnabledValue) {
2115                                 Log.w(TAG, "Expected CRUISE_CONTROL_ENABLED to be set to true but "
2116                                         + "got false instead.");
2117                                 return;
2118                             }
2119                         } catch (Exception e) {
2120                             Log.e(TAG, "Failed to assert that CRUISE_CONTROL_ENABLED is true. "
2121                                     + "Caught the following exception: " + e);
2122                             return;
2123                         }
2124                         try {
2125                             int ccTypeValue = mCarPropertyManager.getIntProperty(
2126                                     VehiclePropertyIds.CRUISE_CONTROL_TYPE, /* areaId */ 0);
2127                             boolean ccTypeCondition =
2128                                     ((ccTypeValue == CruiseControlType.STANDARD)
2129                                             == requireStandard);
2130                             if (!ccTypeCondition) {
2131                                 if (requireStandard) {
2132                                     Log.w(TAG, "Expected CRUISE_CONTROL_TYPE to be set to STANDARD "
2133                                             + "but got the following value instead: "
2134                                             + ccTypeValue);
2135                                 } else {
2136                                     Log.w(TAG, "Expected CRUISE_CONTROL_TYPE to be set to not "
2137                                             + "STANDARD but got the following value instead: "
2138                                             + ccTypeValue);
2139                                 }
2140                                 return;
2141                             }
2142                         } catch (Exception e) {
2143                             Log.e(TAG, "Failed to assert that CRUISE_CONTROL_TYPE value. Caught "
2144                                     + "the following exception: " + e);
2145                             return;
2146                         }
2147                         isMetStandardConditionCheck.set(true);
2148                     },
2149                     Car.PERMISSION_READ_ADAS_SETTINGS,
2150                     Car.PERMISSION_READ_ADAS_STATES
2151             );
2152             return isMetStandardConditionCheck.get();
2153         } finally {
2154             runWithShellPermissionIdentity(() -> {
2155                 verifier.restoreInitialValues();
2156             }, Car.PERMISSION_READ_ADAS_SETTINGS, Car.PERMISSION_CONTROL_ADAS_SETTINGS);
2157         }
2158     }
2159 
2160     private static VehiclePropertyVerifier.Builder<Integer>
getCruiseControlCommandVerifierBuilder_OnAdaptiveCruiseControl()2161             getCruiseControlCommandVerifierBuilder_OnAdaptiveCruiseControl() {
2162         return VehiclePropertyVerifier.newBuilder(
2163                         VehiclePropertyIds.CRUISE_CONTROL_COMMAND,
2164                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_WRITE,
2165                         VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
2166                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
2167                         Integer.class)
2168                 .setAllPossibleEnumValues(CRUISE_CONTROL_COMMANDS)
2169                 .setDependentOnProperty(VehiclePropertyIds.CRUISE_CONTROL_ENABLED,
2170                         ImmutableSet.of(Car.PERMISSION_READ_ADAS_SETTINGS,
2171                                 Car.PERMISSION_CONTROL_ADAS_SETTINGS))
2172                 .addWritePermission(Car.PERMISSION_CONTROL_ADAS_STATES);
2173     }
2174 
2175     private static VehiclePropertyVerifier.Builder<Integer>
getCruiseControlCommandVerifierBuilder_OnStandardCruiseControl()2176             getCruiseControlCommandVerifierBuilder_OnStandardCruiseControl() {
2177         return VehiclePropertyVerifier.newBuilder(
2178                         VehiclePropertyIds.CRUISE_CONTROL_COMMAND,
2179                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_WRITE,
2180                         VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
2181                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
2182                         Integer.class)
2183                 .setAllPossibleEnumValues(CRUISE_CONTROL_COMMANDS)
2184                 .setAllPossibleUnavailableValues(
2185                         CRUISE_CONTROL_COMMANDS_UNAVAILABLE_STATES_ON_STANDARD_CRUISE_CONTROL)
2186                 .setDependentOnProperty(VehiclePropertyIds.CRUISE_CONTROL_ENABLED,
2187                         ImmutableSet.of(Car.PERMISSION_READ_ADAS_SETTINGS,
2188                                 Car.PERMISSION_CONTROL_ADAS_SETTINGS))
2189                 .addWritePermission(Car.PERMISSION_CONTROL_ADAS_STATES);
2190     }
2191 
2192     private static VehiclePropertyVerifier.Builder<Float>
getCruiseControlTargetSpeedVerifierBuilder()2193             getCruiseControlTargetSpeedVerifierBuilder() {
2194         return VehiclePropertyVerifier.newBuilder(
2195                         VehiclePropertyIds.CRUISE_CONTROL_TARGET_SPEED,
2196                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ,
2197                         VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
2198                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
2199                         Float.class)
2200                 .requireMinMaxValues()
2201                 .setCarPropertyConfigVerifier(
2202                         (verifierContext, carPropertyConfig) -> {
2203                             List<? extends AreaIdConfig<?>> areaIdConfigs = carPropertyConfig
2204                                     .getAreaIdConfigs();
2205                             for (AreaIdConfig<?> areaIdConfig : areaIdConfigs) {
2206                                 assertWithMessage("Min/Max values must be non-negative")
2207                                         .that((Float) areaIdConfig.getMinValue())
2208                                         .isAtLeast(0F);
2209                             }
2210                         })
2211                 .setDependentOnProperty(VehiclePropertyIds.CRUISE_CONTROL_ENABLED,
2212                         ImmutableSet.of(Car.PERMISSION_READ_ADAS_SETTINGS,
2213                                 Car.PERMISSION_CONTROL_ADAS_SETTINGS))
2214                 .addReadPermission(Car.PERMISSION_READ_ADAS_STATES);
2215     }
2216 
2217     private static VehiclePropertyVerifier.Builder<Integer>
getAdaptiveCruiseControlTargetTimeGapVerifierBuilder()2218             getAdaptiveCruiseControlTargetTimeGapVerifierBuilder() {
2219         return VehiclePropertyVerifier.newBuilder(
2220                         VehiclePropertyIds.ADAPTIVE_CRUISE_CONTROL_TARGET_TIME_GAP,
2221                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE,
2222                         VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
2223                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
2224                         Integer.class)
2225                 .setCarPropertyConfigVerifier(
2226                         (verifierContext, carPropertyConfig) -> {
2227                             List<Integer> configArray = carPropertyConfig.getConfigArray();
2228 
2229                             for (Integer configArrayValue : configArray) {
2230                                 assertWithMessage("configArray values of "
2231                                         + "ADAPTIVE_CRUISE_CONTROL_TARGET_TIME_GAP must be "
2232                                         + "positive. Detected value " + configArrayValue
2233                                         + " in configArray " + configArray)
2234                                         .that(configArrayValue)
2235                                         .isGreaterThan(0);
2236                             }
2237 
2238                             for (int i = 0; i < configArray.size() - 1; i++) {
2239                                 assertWithMessage("configArray values of "
2240                                         + "ADAPTIVE_CRUISE_CONTROL_TARGET_TIME_GAP must be in "
2241                                         + "ascending order. Detected value "
2242                                         + configArray.get(i)
2243                                         + " is greater than or equal to "
2244                                         + configArray.get(i + 1)
2245                                         + " in configArray " + configArray)
2246                                         .that(configArray.get(i))
2247                                         .isLessThan(configArray.get(i + 1));
2248                             }
2249                         })
2250                 .verifySetterWithConfigArrayValues()
2251                 .setDependentOnProperty(VehiclePropertyIds.CRUISE_CONTROL_ENABLED,
2252                         ImmutableSet.of(Car.PERMISSION_READ_ADAS_SETTINGS,
2253                                 Car.PERMISSION_CONTROL_ADAS_SETTINGS))
2254                 .addReadPermission(Car.PERMISSION_READ_ADAS_STATES)
2255                 .addReadPermission(Car.PERMISSION_CONTROL_ADAS_STATES)
2256                 .addWritePermission(Car.PERMISSION_CONTROL_ADAS_STATES);
2257     }
2258 
2259     private static VehiclePropertyVerifier.Builder<Integer>
2260             getAdaptiveCruiseControlLeadVehicleMeasuredDistanceVerifierBuilder() {
2261         return VehiclePropertyVerifier.newBuilder(
2262                         VehiclePropertyIds.ADAPTIVE_CRUISE_CONTROL_LEAD_VEHICLE_MEASURED_DISTANCE,
2263                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ,
2264                         VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
2265                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_CONTINUOUS,
2266                         Integer.class)
2267                 .requireMinMaxValues()
2268                 .requireMinValuesToBeZero()
2269                 .setDependentOnProperty(VehiclePropertyIds.CRUISE_CONTROL_ENABLED,
2270                         ImmutableSet.of(Car.PERMISSION_READ_ADAS_SETTINGS,
2271                                 Car.PERMISSION_CONTROL_ADAS_SETTINGS))
2272                 .addReadPermission(Car.PERMISSION_READ_ADAS_STATES);
2273     }
2274 
2275     private static VehiclePropertyVerifier.Builder<Boolean>
2276             getHandsOnDetectionEnabledVerifierBuilder() {
2277         return VehiclePropertyVerifier.newBuilder(
2278                         VehiclePropertyIds.HANDS_ON_DETECTION_ENABLED,
2279                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE,
2280                         VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
2281                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
2282                         Boolean.class)
2283                 .addReadPermission(Car.PERMISSION_READ_DRIVER_MONITORING_SETTINGS)
2284                 .addReadPermission(Car.PERMISSION_CONTROL_DRIVER_MONITORING_SETTINGS)
2285                 .addWritePermission(Car.PERMISSION_CONTROL_DRIVER_MONITORING_SETTINGS);
2286     }
2287 
2288     private static VehiclePropertyVerifier.Builder<Integer>
2289             getHandsOnDetectionDriverStateVerifierBuilder() {
2290         ImmutableSet<Integer> possibleEnumValues = ImmutableSet.<Integer>builder()
2291                 .addAll(HANDS_ON_DETECTION_DRIVER_STATES)
2292                 .addAll(ERROR_STATES)
2293                 .build();
2294 
2295         return VehiclePropertyVerifier.newBuilder(
2296                         VehiclePropertyIds.HANDS_ON_DETECTION_DRIVER_STATE,
2297                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ,
2298                         VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
2299                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
2300                         Integer.class)
2301                 .setAllPossibleEnumValues(possibleEnumValues)
2302                 .setDependentOnProperty(VehiclePropertyIds.HANDS_ON_DETECTION_ENABLED,
2303                         ImmutableSet.of(Car.PERMISSION_READ_DRIVER_MONITORING_SETTINGS,
2304                                 Car.PERMISSION_CONTROL_DRIVER_MONITORING_SETTINGS))
2305                 .verifyErrorStates()
2306                 .addReadPermission(Car.PERMISSION_READ_DRIVER_MONITORING_STATES);
2307     }
2308 
2309     @Test
2310     public void testHandsOnDetectionDriverStateAndErrorStateDontIntersect() {
2311         verifyEnumValuesAreDistinct(HANDS_ON_DETECTION_DRIVER_STATES, ERROR_STATES);
2312     }
2313 
2314     private static VehiclePropertyVerifier.Builder<Integer>
2315             getHandsOnDetectionWarningVerifierBuilder() {
2316         ImmutableSet<Integer> possibleEnumValues = ImmutableSet.<Integer>builder()
2317                 .addAll(HANDS_ON_DETECTION_WARNINGS)
2318                 .addAll(ERROR_STATES)
2319                 .build();
2320 
2321         return VehiclePropertyVerifier.newBuilder(
2322                         VehiclePropertyIds.HANDS_ON_DETECTION_WARNING,
2323                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ,
2324                         VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
2325                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
2326                         Integer.class)
2327                 .setAllPossibleEnumValues(possibleEnumValues)
2328                 .setDependentOnProperty(VehiclePropertyIds.HANDS_ON_DETECTION_ENABLED,
2329                         ImmutableSet.of(Car.PERMISSION_READ_DRIVER_MONITORING_SETTINGS,
2330                                 Car.PERMISSION_CONTROL_DRIVER_MONITORING_SETTINGS))
2331                 .verifyErrorStates()
2332                 .addReadPermission(Car.PERMISSION_READ_DRIVER_MONITORING_STATES);
2333     }
2334 
2335     @Test
2336     public void testHandsOnDetectionWarningAndErrorStateDontIntersect() {
2337         verifyEnumValuesAreDistinct(HANDS_ON_DETECTION_WARNINGS, ERROR_STATES);
2338     }
2339 
2340     private static VehiclePropertyVerifier.Builder<Boolean>
2341             getDriverDrowsinessAttentionSystemEnabledVerifierBuilder() {
2342         return VehiclePropertyVerifier.newBuilder(
2343                         VehiclePropertyIds.DRIVER_DROWSINESS_ATTENTION_SYSTEM_ENABLED,
2344                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE,
2345                         VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
2346                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
2347                         Boolean.class)
2348                 .addReadPermission(Car.PERMISSION_READ_DRIVER_MONITORING_SETTINGS)
2349                 .addReadPermission(Car.PERMISSION_CONTROL_DRIVER_MONITORING_SETTINGS)
2350                 .addWritePermission(Car.PERMISSION_CONTROL_DRIVER_MONITORING_SETTINGS);
2351     }
2352 
2353     private static VehiclePropertyVerifier.Builder<Integer>
2354             getDriverDrowsinessAttentionStateVerifierBuilder() {
2355         ImmutableSet<Integer> possibleEnumValues = ImmutableSet.<Integer>builder()
2356                 .addAll(DRIVER_DROWSINESS_ATTENTION_STATES)
2357                 .addAll(ERROR_STATES)
2358                 .build();
2359 
2360         return VehiclePropertyVerifier.newBuilder(
2361                         VehiclePropertyIds.DRIVER_DROWSINESS_ATTENTION_STATE,
2362                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ,
2363                         VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
2364                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
2365                         Integer.class)
2366                 .setAllPossibleEnumValues(possibleEnumValues)
2367                 .setDependentOnProperty(
2368                         VehiclePropertyIds.DRIVER_DROWSINESS_ATTENTION_SYSTEM_ENABLED,
2369                         ImmutableSet.of(Car.PERMISSION_READ_DRIVER_MONITORING_SETTINGS,
2370                                 Car.PERMISSION_CONTROL_DRIVER_MONITORING_SETTINGS))
2371                 .verifyErrorStates()
2372                 .addReadPermission(Car.PERMISSION_READ_DRIVER_MONITORING_STATES);
2373     }
2374 
2375     @Test
2376     @RequiresFlagsEnabled(Flags.FLAG_ANDROID_VIC_VEHICLE_PROPERTIES)
2377     public void testDriverDrowsinessAttentionStateAndErrorStateDontIntersect() {
2378         verifyEnumValuesAreDistinct(HANDS_ON_DETECTION_DRIVER_STATES, ERROR_STATES);
2379     }
2380 
2381     private static VehiclePropertyVerifier.Builder<Boolean>
2382             getDriverDrowsinessAttentionWarningEnabledVerifierBuilder() {
2383         return VehiclePropertyVerifier.newBuilder(
2384                         VehiclePropertyIds.DRIVER_DROWSINESS_ATTENTION_WARNING_ENABLED,
2385                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE,
2386                         VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
2387                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
2388                         Boolean.class)
2389                 .addReadPermission(Car.PERMISSION_READ_DRIVER_MONITORING_SETTINGS)
2390                 .addReadPermission(Car.PERMISSION_CONTROL_DRIVER_MONITORING_SETTINGS)
2391                 .addWritePermission(Car.PERMISSION_CONTROL_DRIVER_MONITORING_SETTINGS);
2392     }
2393 
2394     private static VehiclePropertyVerifier.Builder<Integer>
2395             getDriverDrowsinessAttentionWarningVerifierBuilder() {
2396         ImmutableSet<Integer> possibleEnumValues = ImmutableSet.<Integer>builder()
2397                 .addAll(DRIVER_DROWSINESS_ATTENTION_WARNINGS)
2398                 .addAll(ERROR_STATES)
2399                 .build();
2400 
2401         return VehiclePropertyVerifier.newBuilder(
2402                         VehiclePropertyIds.DRIVER_DROWSINESS_ATTENTION_WARNING,
2403                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ,
2404                         VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
2405                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
2406                         Integer.class)
2407                 .setAllPossibleEnumValues(possibleEnumValues)
2408                 .setDependentOnProperty(
2409                         VehiclePropertyIds.DRIVER_DROWSINESS_ATTENTION_WARNING_ENABLED,
2410                         ImmutableSet.of(Car.PERMISSION_READ_DRIVER_MONITORING_SETTINGS,
2411                                 Car.PERMISSION_CONTROL_DRIVER_MONITORING_SETTINGS))
2412                 .verifyErrorStates()
2413                 .addReadPermission(Car.PERMISSION_READ_DRIVER_MONITORING_STATES);
2414     }
2415 
2416     @Test
2417     @RequiresFlagsEnabled(Flags.FLAG_ANDROID_VIC_VEHICLE_PROPERTIES)
2418     public void testDriverDrowsinessAttentionWarningAndErrorStateDontIntersect() {
2419         verifyEnumValuesAreDistinct(DRIVER_DROWSINESS_ATTENTION_WARNINGS, ERROR_STATES);
2420     }
2421 
2422     private static VehiclePropertyVerifier.Builder<Boolean>
2423             getDriverDistractionSystemEnabledVerifierBuilder() {
2424         return VehiclePropertyVerifier.newBuilder(
2425                         VehiclePropertyIds.DRIVER_DISTRACTION_SYSTEM_ENABLED,
2426                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE,
2427                         VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
2428                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
2429                         Boolean.class)
2430                 .addReadPermission(Car.PERMISSION_READ_DRIVER_MONITORING_SETTINGS)
2431                 .addReadPermission(Car.PERMISSION_CONTROL_DRIVER_MONITORING_SETTINGS)
2432                 .addWritePermission(Car.PERMISSION_CONTROL_DRIVER_MONITORING_SETTINGS);
2433     }
2434 
2435 
2436     private static VehiclePropertyVerifier.Builder<Integer>
2437             getDriverDistractionStateVerifierBuilder() {
2438         ImmutableSet<Integer> possibleEnumValues = ImmutableSet.<Integer>builder()
2439                 .addAll(DRIVER_DISTRACTION_STATES)
2440                 .addAll(ERROR_STATES)
2441                 .build();
2442 
2443         return VehiclePropertyVerifier.newBuilder(
2444                         VehiclePropertyIds.DRIVER_DISTRACTION_STATE,
2445                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ,
2446                         VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
2447                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
2448                         Integer.class)
2449                 .setAllPossibleEnumValues(possibleEnumValues)
2450                 .setDependentOnProperty(
2451                         VehiclePropertyIds.DRIVER_DISTRACTION_SYSTEM_ENABLED,
2452                         ImmutableSet.of(Car.PERMISSION_READ_DRIVER_MONITORING_SETTINGS,
2453                                 Car.PERMISSION_CONTROL_DRIVER_MONITORING_SETTINGS))
2454                 .verifyErrorStates()
2455                 .addReadPermission(Car.PERMISSION_READ_DRIVER_MONITORING_STATES);
2456     }
2457 
2458     @Test
2459     @RequiresFlagsEnabled(Flags.FLAG_ANDROID_VIC_VEHICLE_PROPERTIES)
2460     public void testDriverDistractionStateAndErrorStateDontIntersect() {
2461         verifyEnumValuesAreDistinct(DRIVER_DISTRACTION_STATES, ERROR_STATES);
2462     }
2463 
2464     private static VehiclePropertyVerifier.Builder<Boolean>
2465             getDriverDistractionWarningEnabledVerifierBuilder() {
2466         return VehiclePropertyVerifier.newBuilder(
2467                         VehiclePropertyIds.DRIVER_DISTRACTION_WARNING_ENABLED,
2468                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE,
2469                         VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
2470                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
2471                         Boolean.class)
2472                 .addReadPermission(Car.PERMISSION_READ_DRIVER_MONITORING_SETTINGS)
2473                 .addReadPermission(Car.PERMISSION_CONTROL_DRIVER_MONITORING_SETTINGS)
2474                 .addWritePermission(Car.PERMISSION_CONTROL_DRIVER_MONITORING_SETTINGS);
2475     }
2476 
2477     private static VehiclePropertyVerifier.Builder<Integer>
2478             getDriverDistractionWarningVerifierBuilder() {
2479         ImmutableSet<Integer> possibleEnumValues = ImmutableSet.<Integer>builder()
2480                 .addAll(DRIVER_DISTRACTION_WARNINGS)
2481                 .addAll(ERROR_STATES)
2482                 .build();
2483 
2484         return VehiclePropertyVerifier.newBuilder(
2485                         VehiclePropertyIds.DRIVER_DISTRACTION_WARNING,
2486                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ,
2487                         VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
2488                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
2489                         Integer.class)
2490                 .setAllPossibleEnumValues(possibleEnumValues)
2491                 .setDependentOnProperty(
2492                         VehiclePropertyIds.DRIVER_DISTRACTION_WARNING_ENABLED,
2493                         ImmutableSet.of(Car.PERMISSION_READ_DRIVER_MONITORING_SETTINGS,
2494                                 Car.PERMISSION_CONTROL_DRIVER_MONITORING_SETTINGS))
2495                 .verifyErrorStates()
2496                 .addReadPermission(Car.PERMISSION_READ_DRIVER_MONITORING_STATES);
2497     }
2498 
2499     @Test
2500     @RequiresFlagsEnabled(Flags.FLAG_ANDROID_VIC_VEHICLE_PROPERTIES)
2501     public void testDriverDistractionWarningAndErrorStateDontIntersect() {
2502         verifyEnumValuesAreDistinct(DRIVER_DISTRACTION_WARNINGS, ERROR_STATES);
2503     }
2504 
2505     public static VehiclePropertyVerifier.Builder<Long[]> getWheelTickVerifierBuilder() {
2506         return VehiclePropertyVerifier.newBuilder(
2507                         VehiclePropertyIds.WHEEL_TICK,
2508                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ,
2509                         VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
2510                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_CONTINUOUS,
2511                         Long[].class)
2512                 .setConfigArrayVerifier(
2513                         (verifierContext, configArray) -> {
2514                             assertWithMessage("WHEEL_TICK config array must be size 5")
2515                                     .that(configArray.size())
2516                                     .isEqualTo(5);
2517 
2518                             int supportedWheels = configArray.get(0);
2519                             assertWithMessage(
2520                                             "WHEEL_TICK config array first element specifies which"
2521                                                     + " wheels are supported")
2522                                     .that(supportedWheels)
2523                                     .isGreaterThan(VehicleAreaWheel.WHEEL_UNKNOWN);
2524                             assertWithMessage(
2525                                             "WHEEL_TICK config array first element specifies which"
2526                                                     + " wheels are supported")
2527                                     .that(supportedWheels)
2528                                     .isAtMost(
2529                                             VehicleAreaWheel.WHEEL_LEFT_FRONT
2530                                                     | VehicleAreaWheel.WHEEL_RIGHT_FRONT
2531                                                     | VehicleAreaWheel.WHEEL_LEFT_REAR
2532                                                     | VehicleAreaWheel.WHEEL_RIGHT_REAR);
2533 
2534                             verifyWheelTickConfigArray(
2535                                     supportedWheels,
2536                                     VehicleAreaWheel.WHEEL_LEFT_FRONT,
2537                                     1,
2538                                     configArray.get(1));
2539                             verifyWheelTickConfigArray(
2540                                     supportedWheels,
2541                                     VehicleAreaWheel.WHEEL_RIGHT_FRONT,
2542                                     2,
2543                                     configArray.get(2));
2544                             verifyWheelTickConfigArray(
2545                                     supportedWheels,
2546                                     VehicleAreaWheel.WHEEL_RIGHT_REAR,
2547                                     3,
2548                                     configArray.get(3));
2549                             verifyWheelTickConfigArray(
2550                                     supportedWheels,
2551                                     VehicleAreaWheel.WHEEL_LEFT_REAR,
2552                                     4,
2553                                     configArray.get(4));
2554                         })
2555                 .setCarPropertyValueVerifier(
2556                         (verifierContext, carPropertyConfig, propertyId, areaId, timestampNanos,
2557                                 wheelTicks) -> {
2558                             List<Integer> wheelTickConfigArray = carPropertyConfig.getConfigArray();
2559                             int supportedWheels = wheelTickConfigArray.get(0);
2560 
2561                             assertWithMessage("WHEEL_TICK Long[] value must be size 5")
2562                                     .that(wheelTicks.length)
2563                                     .isEqualTo(5);
2564 
2565                             verifyWheelTickValue(
2566                                     supportedWheels,
2567                                     VehicleAreaWheel.WHEEL_LEFT_FRONT,
2568                                     1,
2569                                     wheelTicks[1]);
2570                             verifyWheelTickValue(
2571                                     supportedWheels,
2572                                     VehicleAreaWheel.WHEEL_RIGHT_FRONT,
2573                                     2,
2574                                     wheelTicks[2]);
2575                             verifyWheelTickValue(
2576                                     supportedWheels,
2577                                     VehicleAreaWheel.WHEEL_RIGHT_REAR,
2578                                     3,
2579                                     wheelTicks[3]);
2580                             verifyWheelTickValue(
2581                                     supportedWheels,
2582                                     VehicleAreaWheel.WHEEL_LEFT_REAR,
2583                                     4,
2584                                     wheelTicks[4]);
2585                         })
2586                 .addReadPermission(Car.PERMISSION_SPEED);
2587     }
2588 
2589     private static VehiclePropertyVerifier.Builder<String> getInfoVinVerifierBuilder() {
2590         return VehiclePropertyVerifier.newBuilder(
2591                         VehiclePropertyIds.INFO_VIN,
2592                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ,
2593                         VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
2594                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_STATIC,
2595                         String.class)
2596                 .setCarPropertyValueVerifier(
2597                         (verifierContext, carPropertyConfig, propertyId, areaId, timestampNanos,
2598                                 vin) ->
2599                                 assertWithMessage("INFO_VIN must be 17 characters")
2600                                         .that(vin)
2601                                         .hasLength(17))
2602                 .addReadPermission(Car.PERMISSION_IDENTIFICATION);
2603     }
2604 
2605     private static VehiclePropertyVerifier.Builder<String> getInfoMakeVerifierBuilder() {
2606         return VehiclePropertyVerifier.newBuilder(
2607                         VehiclePropertyIds.INFO_MAKE,
2608                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ,
2609                         VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
2610                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_STATIC,
2611                         String.class)
2612                 .setCarPropertyValueVerifier(
2613                         (verifierContext, carPropertyConfig, propertyId, areaId, timestampNanos,
2614                                 make) ->
2615                                 assertWithMessage("INFO_MAKE must not be empty")
2616                                         .that(make)
2617                                         .isNotEmpty())
2618                 .addReadPermission(Car.PERMISSION_CAR_INFO);
2619     }
2620 
2621     private static VehiclePropertyVerifier.Builder<String> getInfoModelVerifierBuilder() {
2622         return VehiclePropertyVerifier.newBuilder(
2623                         VehiclePropertyIds.INFO_MODEL,
2624                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ,
2625                         VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
2626                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_STATIC,
2627                         String.class)
2628                 .setCarPropertyValueVerifier(
2629                         (verifierContext, carPropertyConfig, propertyId, areaId, timestampNanos,
2630                                 model) ->
2631                                 assertWithMessage("INFO_MODEL must not be empty")
2632                                         .that(model)
2633                                         .isNotEmpty())
2634                 .addReadPermission(Car.PERMISSION_CAR_INFO);
2635     }
2636 
2637     private static VehiclePropertyVerifier.Builder<Integer> getInfoModelYearVerifierBuilder() {
2638         return VehiclePropertyVerifier.newBuilder(
2639                         VehiclePropertyIds.INFO_MODEL_YEAR,
2640                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ,
2641                         VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
2642                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_STATIC,
2643                         Integer.class)
2644                 .setCarPropertyValueVerifier(
2645                         (verifierContext, carPropertyConfig, propertyId, areaId, timestampNanos,
2646                                 modelYear) -> {
2647                             int currentYear = Year.now().getValue();
2648                             assertWithMessage(
2649                                     "INFO_MODEL_YEAR Integer value must be greater"
2650                                             + " than or equal "
2651                                             + (currentYear + REASONABLE_PAST_MODEL_YEAR_OFFSET))
2652                                     .that(modelYear)
2653                                     .isAtLeast(currentYear + REASONABLE_PAST_MODEL_YEAR_OFFSET);
2654                             assertWithMessage(
2655                                     "INFO_MODEL_YEAR Integer value must be less"
2656                                             + " than or equal "
2657                                             + (currentYear + REASONABLE_FUTURE_MODEL_YEAR_OFFSET))
2658                                     .that(modelYear)
2659                                     .isAtMost(currentYear + REASONABLE_FUTURE_MODEL_YEAR_OFFSET);
2660                         })
2661                 .addReadPermission(Car.PERMISSION_CAR_INFO);
2662     }
2663 
2664     private static void assertFuelPropertyNotImplementedOnEv(
2665             CarPropertyManager mgr, int propertyId) {
2666         runWithShellPermissionIdentity(
2667                 () -> {
2668                     if (mgr.getCarPropertyConfig(
2669                             VehiclePropertyIds.INFO_FUEL_TYPE) == null) {
2670                         return;
2671                     }
2672                     CarPropertyValue<?> infoFuelTypeValue = mgr.getProperty(
2673                             VehiclePropertyIds.INFO_FUEL_TYPE, /* areaId */ 0);
2674                     if (infoFuelTypeValue.getStatus() != CarPropertyValue.STATUS_AVAILABLE) {
2675                         return;
2676                     }
2677                     Integer[] fuelTypes = (Integer[]) infoFuelTypeValue.getValue();
2678                     assertWithMessage("If fuelTypes only contains FuelType.ELECTRIC, "
2679                                     + VehiclePropertyIds.toString(propertyId)
2680                                     + " property must not be implemented")
2681                             .that(fuelTypes).isNotEqualTo(new Integer[]{FuelType.ELECTRIC});
2682                 },
2683                 Car.PERMISSION_CAR_INFO);
2684     }
2685 
2686     private static VehiclePropertyVerifier.Builder<Float> getInfoFuelCapacityVerifierBuilder() {
2687         return VehiclePropertyVerifier.newBuilder(
2688                         VehiclePropertyIds.INFO_FUEL_CAPACITY,
2689                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ,
2690                         VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
2691                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_STATIC,
2692                         Float.class)
2693                 .setCarPropertyConfigVerifier(
2694                         (verifierContext, config) -> {
2695                             assertFuelPropertyNotImplementedOnEv(
2696                                     verifierContext.getCarPropertyManager(),
2697                                     VehiclePropertyIds.INFO_FUEL_CAPACITY);
2698                         })
2699                 .setCarPropertyValueVerifier(
2700                         (verifierContext, carPropertyConfig, propertyId, areaId, timestampNanos,
2701                                 fuelCapacity) ->
2702                                 assertWithMessage(
2703                                                 "INFO_FUEL_CAPACITY Float value must be greater"
2704                                                         + " than or equal 0")
2705                                         .that(fuelCapacity)
2706                                         .isAtLeast(0))
2707                 .addReadPermission(Car.PERMISSION_CAR_INFO);
2708     }
2709 
2710     private static VehiclePropertyVerifier.Builder<Integer[]> getInfoFuelTypeVerifierBuilder() {
2711         return VehiclePropertyVerifier.newBuilder(
2712                         VehiclePropertyIds.INFO_FUEL_TYPE,
2713                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ,
2714                         VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
2715                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_STATIC,
2716                         Integer[].class)
2717                 .setCarPropertyValueVerifier(
2718                         (verifierContext, carPropertyConfig, propertyId, areaId, timestampNanos,
2719                                 fuelTypes) -> {
2720                             assertWithMessage("INFO_FUEL_TYPE must specify at least 1 fuel type")
2721                                     .that(fuelTypes.length)
2722                                     .isGreaterThan(0);
2723                             for (Integer fuelType : fuelTypes) {
2724                                 assertWithMessage(
2725                                                 "INFO_FUEL_TYPE must be a defined fuel type: "
2726                                                         + fuelType)
2727                                         .that(fuelType)
2728                                         .isIn(
2729                                                 ImmutableSet.builder()
2730                                                         .add(
2731                                                                 FuelType.UNKNOWN,
2732                                                                 FuelType.UNLEADED,
2733                                                                 FuelType.LEADED,
2734                                                                 FuelType.DIESEL_1,
2735                                                                 FuelType.DIESEL_2,
2736                                                                 FuelType.BIODIESEL,
2737                                                                 FuelType.E85,
2738                                                                 FuelType.LPG,
2739                                                                 FuelType.CNG,
2740                                                                 FuelType.LNG,
2741                                                                 FuelType.ELECTRIC,
2742                                                                 FuelType.HYDROGEN,
2743                                                                 FuelType.OTHER)
2744                                                         .build());
2745                             }
2746                         })
2747                 .addReadPermission(Car.PERMISSION_CAR_INFO);
2748     }
2749 
2750     private static VehiclePropertyVerifier.Builder<Float>
2751             getInfoEvBatteryCapacityVerifierBuilder() {
2752         return VehiclePropertyVerifier.newBuilder(
2753                         VehiclePropertyIds.INFO_EV_BATTERY_CAPACITY,
2754                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ,
2755                         VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
2756                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_STATIC,
2757                         Float.class)
2758                 .setCarPropertyValueVerifier(
2759                         (verifierContext, carPropertyConfig, propertyId, areaId, timestampNanos,
2760                                 evBatteryCapacity) ->
2761                                 assertWithMessage(
2762                                                 "INFO_EV_BATTERY_CAPACITY Float value must"
2763                                                         + " be greater than or equal to 0")
2764                                         .that(evBatteryCapacity)
2765                                         .isAtLeast(0))
2766                 .addReadPermission(Car.PERMISSION_CAR_INFO);
2767     }
2768 
2769     private static VehiclePropertyVerifier.Builder<Integer[]>
2770             getInfoEvConnectorTypeVerifierBuilder() {
2771         return VehiclePropertyVerifier.newBuilder(
2772                         VehiclePropertyIds.INFO_EV_CONNECTOR_TYPE,
2773                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ,
2774                         VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
2775                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_STATIC,
2776                         Integer[].class)
2777                 .setCarPropertyValueVerifier(
2778                         (verifierContext, carPropertyConfig, propertyId, areaId, timestampNanos,
2779                                 evConnectorTypes) -> {
2780                             assertWithMessage(
2781                                             "INFO_EV_CONNECTOR_TYPE must specify at least 1"
2782                                                     + " connection type")
2783                                     .that(evConnectorTypes.length)
2784                                     .isGreaterThan(0);
2785                             for (Integer evConnectorType : evConnectorTypes) {
2786                                 assertWithMessage(
2787                                                 "INFO_EV_CONNECTOR_TYPE must be a defined"
2788                                                         + " connection type: "
2789                                                         + evConnectorType)
2790                                         .that(evConnectorType)
2791                                         .isIn(
2792                                                 ImmutableSet.builder()
2793                                                         .add(
2794                                                                 EvChargingConnectorType.UNKNOWN,
2795                                                                 EvChargingConnectorType
2796                                                                         .IEC_TYPE_1_AC,
2797                                                                 EvChargingConnectorType
2798                                                                         .IEC_TYPE_2_AC,
2799                                                                 EvChargingConnectorType
2800                                                                         .IEC_TYPE_3_AC,
2801                                                                 EvChargingConnectorType
2802                                                                         .IEC_TYPE_4_DC,
2803                                                                 EvChargingConnectorType
2804                                                                         .IEC_TYPE_1_CCS_DC,
2805                                                                 EvChargingConnectorType
2806                                                                         .IEC_TYPE_2_CCS_DC,
2807                                                                 EvChargingConnectorType
2808                                                                         .TESLA_ROADSTER,
2809                                                                 EvChargingConnectorType.TESLA_HPWC,
2810                                                                 EvChargingConnectorType
2811                                                                         .TESLA_SUPERCHARGER,
2812                                                                 EvChargingConnectorType.GBT_AC,
2813                                                                 EvChargingConnectorType.GBT_DC,
2814                                                                 EvChargingConnectorType.OTHER)
2815                                                         .build());
2816                             }
2817                         })
2818                 .addReadPermission(Car.PERMISSION_CAR_INFO);
2819     }
2820 
2821     private static VehiclePropertyVerifier.Builder<Integer>
2822             getInfoFuelDoorLocationVerifierBuilder() {
2823         return VehiclePropertyVerifier.newBuilder(
2824                         VehiclePropertyIds.INFO_FUEL_DOOR_LOCATION,
2825                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ,
2826                         VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
2827                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_STATIC,
2828                         Integer.class)
2829                 .setCarPropertyConfigVerifier(
2830                         (verifierContext, config) -> {
2831                             assertFuelPropertyNotImplementedOnEv(
2832                                     verifierContext.getCarPropertyManager(),
2833                                     VehiclePropertyIds.INFO_FUEL_DOOR_LOCATION);
2834                         })
2835                 .setAllPossibleEnumValues(PORT_LOCATION_TYPES)
2836                 .addReadPermission(Car.PERMISSION_CAR_INFO);
2837     }
2838 
2839     private static VehiclePropertyVerifier.Builder<Integer> getInfoEvPortLocationVerifierBuilder() {
2840         return VehiclePropertyVerifier.newBuilder(
2841                         VehiclePropertyIds.INFO_EV_PORT_LOCATION,
2842                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ,
2843                         VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
2844                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_STATIC,
2845                         Integer.class)
2846                 .setAllPossibleEnumValues(PORT_LOCATION_TYPES)
2847                 .addReadPermission(Car.PERMISSION_CAR_INFO);
2848     }
2849 
2850     private static VehiclePropertyVerifier.Builder<Integer[]>
2851             getInfoMultiEvPortLocationsVerifierBuilder() {
2852         return VehiclePropertyVerifier.newBuilder(
2853                         VehiclePropertyIds.INFO_MULTI_EV_PORT_LOCATIONS,
2854                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ,
2855                         VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
2856                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_STATIC,
2857                         Integer[].class)
2858                 .setCarPropertyValueVerifier(
2859                         (verifierContext, carPropertyConfig, propertyId, areaId, timestampNanos,
2860                                 evPortLocations) -> {
2861                             assertWithMessage(
2862                                             "INFO_MULTI_EV_PORT_LOCATIONS must specify at least 1"
2863                                                     + " port location")
2864                                     .that(evPortLocations.length)
2865                                     .isGreaterThan(0);
2866                             for (Integer evPortLocation : evPortLocations) {
2867                                 assertWithMessage(
2868                                                 "INFO_MULTI_EV_PORT_LOCATIONS must be a defined"
2869                                                         + " port location: "
2870                                                         + evPortLocation)
2871                                         .that(evPortLocation)
2872                                         .isIn(PORT_LOCATION_TYPES);
2873                             }
2874                         })
2875                 .addReadPermission(Car.PERMISSION_CAR_INFO);
2876     }
2877 
2878     private static VehiclePropertyVerifier.Builder<Integer> getInfoDriverSeatVerifierBuilder() {
2879         return VehiclePropertyVerifier.newBuilder(
2880                         VehiclePropertyIds.INFO_DRIVER_SEAT,
2881                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ,
2882                         VehicleAreaType.VEHICLE_AREA_TYPE_SEAT,
2883                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_STATIC,
2884                         Integer.class)
2885                 .setAllPossibleEnumValues(
2886                         ImmutableSet.of(
2887                                 VehicleAreaSeat.SEAT_UNKNOWN,
2888                                 SEAT_ROW_1_LEFT,
2889                                 VehicleAreaSeat.SEAT_ROW_1_CENTER,
2890                                 VehicleAreaSeat.SEAT_ROW_1_RIGHT))
2891                 .setAreaIdsVerifier(
2892                         (verifierContext, areaIds) ->
2893                                 assertWithMessage("Even though INFO_DRIVER_SEAT is"
2894                                         + " VEHICLE_AREA_TYPE_SEAT, it is meant to be"
2895                                         + " VEHICLE_AREA_TYPE_GLOBAL, so its AreaIds"
2896                                         + " must contain a single 0")
2897                                         .that(areaIds)
2898                                         .isEqualTo(
2899                                                 new int[] {
2900                                                         VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL
2901                                                 }))
2902                 .addReadPermission(Car.PERMISSION_CAR_INFO);
2903     }
2904 
2905     private static VehiclePropertyVerifier.Builder<Integer[]>
2906             getInfoExteriorDimensionsVerifierBuilder() {
2907         return VehiclePropertyVerifier.newBuilder(
2908                         VehiclePropertyIds.INFO_EXTERIOR_DIMENSIONS,
2909                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ,
2910                         VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
2911                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_STATIC,
2912                         Integer[].class)
2913                 .setCarPropertyValueVerifier(
2914                         (verifierContext, carPropertyConfig, propertyId, areaId, timestampNanos,
2915                                 exteriorDimensions) -> {
2916                             assertWithMessage(
2917                                             "INFO_EXTERIOR_DIMENSIONS must specify all 8 dimension"
2918                                                     + " measurements")
2919                                     .that(exteriorDimensions.length)
2920                                     .isEqualTo(8);
2921                             for (Integer exteriorDimension : exteriorDimensions) {
2922                                 assertWithMessage(
2923                                                 "INFO_EXTERIOR_DIMENSIONS measurement must be"
2924                                                         + " greater than 0")
2925                                         .that(exteriorDimension)
2926                                         .isGreaterThan(0);
2927                             }
2928                         })
2929                 .addReadPermission(Car.PERMISSION_CAR_INFO);
2930     }
2931 
2932     private static VehiclePropertyVerifier.Builder<Long> getEpochTimeVerifierBuilder() {
2933         return VehiclePropertyVerifier.newBuilder(
2934                         VehiclePropertyIds.EPOCH_TIME,
2935                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_WRITE,
2936                         VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
2937                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
2938                         Long.class)
2939                 .addWritePermission(Car.PERMISSION_CAR_EPOCH_TIME);
2940     }
2941 
2942     private static VehiclePropertyVerifier.Builder<Integer[]>
2943             getUltrasonicsSensorPositionVerifierBuilder() {
2944         return VehiclePropertyVerifier.newBuilder(
2945                         VehiclePropertyIds.ULTRASONICS_SENSOR_POSITION,
2946                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ,
2947                         VehicleAreaType.VEHICLE_AREA_TYPE_VENDOR,
2948                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_STATIC,
2949                         Integer[].class)
2950                 .setCarPropertyValueVerifier(
2951                         (verifierContext, carPropertyConfig, propertyId, areaId, timestampNanos,
2952                                 positions) -> {
2953                             assertWithMessage("ULTRASONICS_SENSOR_POSITION must specify 3 values, "
2954                                             + "areaId: " + areaId)
2955                                     .that(positions.length)
2956                                     .isEqualTo(3);
2957                         })
2958                 .addReadPermission(Car.PERMISSION_READ_ULTRASONICS_SENSOR_DATA);
2959     }
2960 
2961     private static VehiclePropertyVerifier.Builder<Float[]>
2962             getUltrasonicsSensorOrientationVerifierBuilder() {
2963         return VehiclePropertyVerifier.newBuilder(
2964                         VehiclePropertyIds.ULTRASONICS_SENSOR_ORIENTATION,
2965                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ,
2966                         VehicleAreaType.VEHICLE_AREA_TYPE_VENDOR,
2967                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_STATIC,
2968                         Float[].class)
2969                 .setCarPropertyValueVerifier(
2970                         (verifierContext, carPropertyConfig, propertyId, areaId, timestampNanos,
2971                                 orientations) -> {
2972                             assertWithMessage("ULTRASONICS_SENSOR_ORIENTATION must specify 4 "
2973                                             + "values, areaId: " + areaId)
2974                                     .that(orientations.length)
2975                                     .isEqualTo(4);
2976                         })
2977                 .addReadPermission(Car.PERMISSION_READ_ULTRASONICS_SENSOR_DATA);
2978     }
2979 
2980     private static VehiclePropertyVerifier.Builder<Integer[]>
2981             getUltrasonicsSensorFieldOfViewVerifierBuilder() {
2982         return VehiclePropertyVerifier.newBuilder(
2983                         VehiclePropertyIds.ULTRASONICS_SENSOR_FIELD_OF_VIEW,
2984                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ,
2985                         VehicleAreaType.VEHICLE_AREA_TYPE_VENDOR,
2986                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_STATIC,
2987                         Integer[].class)
2988                 .setCarPropertyValueVerifier(
2989                         (verifierContext, carPropertyConfig, propertyId, areaId, timestampNanos,
2990                                 fieldOfViews) -> {
2991                             assertWithMessage("ULTRASONICS_SENSOR_FIELD_OF_VIEW must specify 2 "
2992                                             + "values, areaId: " + areaId)
2993                                     .that(fieldOfViews.length)
2994                                     .isEqualTo(2);
2995                             assertWithMessage("ULTRASONICS_SENSOR_FIELD_OF_VIEW horizontal fov "
2996                                             + "must be greater than zero, areaId: " + areaId)
2997                                     .that(fieldOfViews[0])
2998                                     .isGreaterThan(0);
2999                             assertWithMessage("ULTRASONICS_SENSOR_FIELD_OF_VIEW vertical fov "
3000                                             + "must be greater than zero, areaId: " + areaId)
3001                                     .that(fieldOfViews[1])
3002                                     .isGreaterThan(0);
3003                         })
3004                 .addReadPermission(Car.PERMISSION_READ_ULTRASONICS_SENSOR_DATA);
3005     }
3006 
3007     private static VehiclePropertyVerifier.Builder<Integer[]>
3008             getUltrasonicsSensorDetectionRangeVerifierBuilder() {
3009         return VehiclePropertyVerifier.newBuilder(
3010                         VehiclePropertyIds.ULTRASONICS_SENSOR_DETECTION_RANGE,
3011                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ,
3012                         VehicleAreaType.VEHICLE_AREA_TYPE_VENDOR,
3013                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_STATIC,
3014                         Integer[].class)
3015                 .setCarPropertyValueVerifier(
3016                         (verifierContext, carPropertyConfig, propertyId, areaId, timestampNanos,
3017                                 detectionRanges) -> {
3018                             assertWithMessage("ULTRASONICS_SENSOR_DETECTION_RANGE must "
3019                                             + "specify 2 values, areaId: " + areaId)
3020                                     .that(detectionRanges.length)
3021                                     .isEqualTo(2);
3022                             assertWithMessage("ULTRASONICS_SENSOR_DETECTION_RANGE min value must "
3023                                             + "be at least zero, areaId: " + areaId)
3024                                     .that(detectionRanges[0])
3025                                     .isAtLeast(0);
3026                             assertWithMessage("ULTRASONICS_SENSOR_DETECTION_RANGE max value must "
3027                                             + "be greater than min, areaId: " + areaId)
3028                                     .that(detectionRanges[1])
3029                                     .isGreaterThan(detectionRanges[0]);
3030                         })
3031                 .addReadPermission(Car.PERMISSION_READ_ULTRASONICS_SENSOR_DATA);
3032     }
3033 
3034     private static VehiclePropertyVerifier.Builder<Integer[]>
3035             getUltrasonicsSensorSupportedRangesVerifierBuilder() {
3036         return VehiclePropertyVerifier.newBuilder(
3037                         VehiclePropertyIds.ULTRASONICS_SENSOR_SUPPORTED_RANGES,
3038                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ,
3039                         VehicleAreaType.VEHICLE_AREA_TYPE_VENDOR,
3040                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_STATIC,
3041                         Integer[].class)
3042                 .setCarPropertyValueVerifier(
3043                         (verifierContext, carPropertyConfig, propertyId, areaId, timestampNanos,
3044                                 supportedRanges) -> {
3045                             assertWithMessage("ULTRASONICS_SENSOR_SUPPORTED_RANGES must "
3046                                     + "must have at least 1 range, areaId: " + areaId)
3047                                     .that(supportedRanges.length)
3048                                     .isAtLeast(2);
3049                             assertWithMessage("ULTRASONICS_SENSOR_SUPPORTED_RANGES must "
3050                                     + "specify an even number of values, areaId: " + areaId)
3051                                     .that(supportedRanges.length % 2)
3052                                     .isEqualTo(0);
3053                             assertWithMessage("ULTRASONICS_SENSOR_SUPPORTED_RANGES values "
3054                                     + "must be greater than zero, areaId: " + areaId)
3055                                     .that(supportedRanges[0])
3056                                     .isAtLeast(0);
3057                             for (int i = 1; i < supportedRanges.length; i++) {
3058                                 assertWithMessage("ULTRASONICS_SENSOR_SUPPORTED_RANGES values "
3059                                         + "must be in ascending order, areaId: " + areaId)
3060                                         .that(supportedRanges[i])
3061                                         .isGreaterThan(supportedRanges[i - 1]);
3062                             }
3063                             verifyUltrasonicsSupportedRangesWithinDetectionRange(
3064                                     verifierContext.getCarPropertyManager(), areaId,
3065                                     supportedRanges);
3066                         })
3067                 .addReadPermission(Car.PERMISSION_READ_ULTRASONICS_SENSOR_DATA);
3068     }
3069 
3070     private static void verifyUltrasonicsSupportedRangesWithinDetectionRange(
3071             CarPropertyManager carPropertyManager, int areaId, Integer[] supportedRanges) {
3072         if (carPropertyManager.getCarPropertyConfig(
3073                 VehiclePropertyIds.ULTRASONICS_SENSOR_DETECTION_RANGE) == null) {
3074             return;
3075         }
3076 
3077         Integer[] detectionRange = (Integer[]) carPropertyManager.getProperty(
3078                 VehiclePropertyIds.ULTRASONICS_SENSOR_DETECTION_RANGE, areaId).getValue();
3079 
3080         for (int i = 0; i < supportedRanges.length; i++) {
3081             assertWithMessage("ULTRASONICS_SENSOR_SUPPORTED_RANGES values must "
3082                             + "be within the ULTRASONICS_SENSOR_DETECTION_RANGE, areaId: " + areaId)
3083                     .that(supportedRanges[i])
3084                     .isIn(Range.closed(
3085                             detectionRange[0],
3086                             detectionRange[1]));
3087         }
3088     }
3089 
3090     private static VehiclePropertyVerifier.Builder<Integer[]>
3091             getUltrasonicsSensorMeasuredDistanceVerifierBuilder() {
3092         return VehiclePropertyVerifier.newBuilder(
3093                         VehiclePropertyIds.ULTRASONICS_SENSOR_MEASURED_DISTANCE,
3094                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ,
3095                         VehicleAreaType.VEHICLE_AREA_TYPE_VENDOR,
3096                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_CONTINUOUS,
3097                         Integer[].class)
3098                 .setCarPropertyValueVerifier(
3099                         (verifierContext, carPropertyConfig, propertyId, areaId, timestampNanos,
3100                                 distance) -> {
3101                             assertWithMessage("ULTRASONICS_SENSOR_MEASURED_DISTANCE must "
3102                                     + "have at most 2 values, areaId: " + areaId)
3103                                     .that(distance.length)
3104                                     .isAtMost(2);
3105                             if (distance.length == 2) {
3106                                 assertWithMessage("ULTRASONICS_SENSOR_MEASURED_DISTANCE distance "
3107                                     + "error must be greater than zero, areaId: " + areaId)
3108                                     .that(distance[1])
3109                                     .isAtLeast(0);
3110                             }
3111                             verifyUltrasonicsMeasuredDistanceInSupportedRanges(
3112                                     verifierContext.getCarPropertyManager(), areaId, distance);
3113                             verifyUltrasonicsMeasuredDistanceWithinDetectionRange(
3114                                     verifierContext.getCarPropertyManager(), areaId, distance);
3115                         })
3116             .addReadPermission(Car.PERMISSION_READ_ULTRASONICS_SENSOR_DATA);
3117     }
3118 
3119     private static void verifyUltrasonicsMeasuredDistanceInSupportedRanges(
3120             CarPropertyManager carPropertyManager, int areaId, Integer[] distance) {
3121         // Distance with length of 0 is valid. return because there are no values to verify.
3122         if (distance.length == 0) {
3123             return;
3124         }
3125 
3126         if (carPropertyManager.getCarPropertyConfig(
3127                 VehiclePropertyIds.ULTRASONICS_SENSOR_SUPPORTED_RANGES) == null) {
3128             return;
3129         }
3130 
3131         Integer[] supportedRanges = (Integer[]) carPropertyManager.getProperty(
3132                 VehiclePropertyIds.ULTRASONICS_SENSOR_SUPPORTED_RANGES, areaId).getValue();
3133         ImmutableSet.Builder<Integer> minimumSupportedRangeValues = ImmutableSet.builder();
3134         for (int i = 0; i < supportedRanges.length; i += 2) {
3135             minimumSupportedRangeValues.add(supportedRanges[i]);
3136         }
3137 
3138         assertWithMessage("ULTRASONICS_SENSOR_MEASURED_DISTANCE distance must be one of the "
3139                         + "minimum values in ULTRASONICS_SENSOR_SUPPORTED_RANGES, areaId: "
3140                         + areaId)
3141                 .that(distance[0])
3142                 .isIn(minimumSupportedRangeValues.build());
3143     }
3144 
3145     private static void verifyUltrasonicsMeasuredDistanceWithinDetectionRange(
3146             CarPropertyManager carPropertyManager, int areaId, Integer[] distance) {
3147         // Distance with length of 0 is valid. return because there are no values to verify.
3148         if (distance.length == 0) {
3149             return;
3150         }
3151 
3152         if (carPropertyManager.getCarPropertyConfig(
3153                 VehiclePropertyIds.ULTRASONICS_SENSOR_DETECTION_RANGE) == null) {
3154             return;
3155         }
3156 
3157         Integer[] detectionRange = (Integer[]) carPropertyManager.getProperty(
3158                 VehiclePropertyIds.ULTRASONICS_SENSOR_DETECTION_RANGE, areaId).getValue();
3159         assertWithMessage("ULTRASONICS_SENSOR_MEASURED_DISTANCE distance must "
3160                         + "be within the ULTRASONICS_SENSOR_DETECTION_RANGE, areaId: " + areaId)
3161                 .that(distance[0])
3162                 .isIn(Range.closed(
3163                         detectionRange[0],
3164                         detectionRange[1]));
3165     }
3166 
3167     private static VehiclePropertyVerifier.Builder<Integer>
3168             getElectronicTollCollectionCardTypeVerifierBuilder() {
3169         return VehiclePropertyVerifier.newBuilder(
3170                         VehiclePropertyIds.ELECTRONIC_TOLL_COLLECTION_CARD_TYPE,
3171                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ,
3172                         VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
3173                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
3174                         Integer.class)
3175                 .setAllPossibleEnumValues(
3176                         ImmutableSet.of(
3177                                 VehicleElectronicTollCollectionCardType.UNKNOWN,
3178                                 VehicleElectronicTollCollectionCardType
3179                                         .JP_ELECTRONIC_TOLL_COLLECTION_CARD,
3180                                 VehicleElectronicTollCollectionCardType
3181                                         .JP_ELECTRONIC_TOLL_COLLECTION_CARD_V2))
3182                 .addReadPermission(Car.PERMISSION_CAR_INFO);
3183     }
3184 
3185     private static VehiclePropertyVerifier.Builder<Integer>
3186             getElectronicTollCollectionCardStatusVerifierBuilder() {
3187         return VehiclePropertyVerifier.newBuilder(
3188                         VehiclePropertyIds.ELECTRONIC_TOLL_COLLECTION_CARD_STATUS,
3189                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ,
3190                         VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
3191                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
3192                         Integer.class)
3193                 .setAllPossibleEnumValues(
3194                         ImmutableSet.of(
3195                                 VehicleElectronicTollCollectionCardStatus.UNKNOWN,
3196                                 VehicleElectronicTollCollectionCardStatus
3197                                         .ELECTRONIC_TOLL_COLLECTION_CARD_VALID,
3198                                 VehicleElectronicTollCollectionCardStatus
3199                                         .ELECTRONIC_TOLL_COLLECTION_CARD_INVALID,
3200                                 VehicleElectronicTollCollectionCardStatus
3201                                         .ELECTRONIC_TOLL_COLLECTION_CARD_NOT_INSERTED))
3202                 .addReadPermission(Car.PERMISSION_CAR_INFO);
3203     }
3204 
3205     private static VehiclePropertyVerifier.Builder<Integer>
3206             getGeneralSafetyRegulationComplianceVerifierBuilder() {
3207         return VehiclePropertyVerifier.newBuilder(
3208                         VehiclePropertyIds.GENERAL_SAFETY_REGULATION_COMPLIANCE,
3209                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ,
3210                         VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
3211                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_STATIC,
3212                         Integer.class)
3213                 .setAllPossibleEnumValues(
3214                         ImmutableSet.of(
3215                                 GsrComplianceType.GSR_COMPLIANCE_TYPE_NOT_REQUIRED,
3216                                 GsrComplianceType.GSR_COMPLIANCE_TYPE_REQUIRED_V1))
3217                 .addReadPermission(Car.PERMISSION_CAR_INFO);
3218     }
3219 
3220     private static VehiclePropertyVerifier.Builder<Float>
3221             getEnvOutsideTemperatureVerifierBuilder() {
3222         return VehiclePropertyVerifier.newBuilder(
3223                         VehiclePropertyIds.ENV_OUTSIDE_TEMPERATURE,
3224                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ,
3225                         VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
3226                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_CONTINUOUS,
3227                         Float.class)
3228                 .addReadPermission(Car.PERMISSION_EXTERIOR_ENVIRONMENT);
3229     }
3230 
3231     private static VehiclePropertyVerifier.Builder<Integer> getCurrentGearVerifierBuilder() {
3232         return VehiclePropertyVerifier.newBuilder(
3233                         VehiclePropertyIds.CURRENT_GEAR,
3234                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ,
3235                         VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
3236                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
3237                         Integer.class)
3238                 .setAllPossibleEnumValues(VEHICLE_GEARS)
3239                 .setPossibleConfigArrayValues(VEHICLE_GEARS)
3240                 .requirePropertyValueTobeInConfigArray()
3241                 .addReadPermission(Car.PERMISSION_POWERTRAIN);
3242     }
3243 
3244     private static VehiclePropertyVerifier.Builder<Boolean>
3245             getParkingBrakeAutoApplyVerifierBuilder() {
3246         return VehiclePropertyVerifier.newBuilder(
3247                         VehiclePropertyIds.PARKING_BRAKE_AUTO_APPLY,
3248                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ,
3249                         VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
3250                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
3251                         Boolean.class)
3252                 .addReadPermission(Car.PERMISSION_POWERTRAIN);
3253     }
3254 
3255     private static VehiclePropertyVerifier.Builder<Integer> getIgnitionStateVerifierBuilder() {
3256         return VehiclePropertyVerifier.newBuilder(
3257                         VehiclePropertyIds.IGNITION_STATE,
3258                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ,
3259                         VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
3260                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
3261                         Integer.class)
3262                 .setAllPossibleEnumValues(
3263                         ImmutableSet.of(
3264                                 VehicleIgnitionState.UNDEFINED,
3265                                 VehicleIgnitionState.LOCK,
3266                                 VehicleIgnitionState.OFF,
3267                                 VehicleIgnitionState.ACC,
3268                                 VehicleIgnitionState.ON,
3269                                 VehicleIgnitionState.START))
3270                 .addReadPermission(Car.PERMISSION_POWERTRAIN);
3271     }
3272 
3273     private static VehiclePropertyVerifier.Builder<Integer>
3274             getEvBrakeRegenerationLevelVerifierBuilder() {
3275         return VehiclePropertyVerifier.newBuilder(
3276                         VehiclePropertyIds.EV_BRAKE_REGENERATION_LEVEL,
3277                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE,
3278                         VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
3279                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
3280                         Integer.class)
3281                 .requireMinMaxValues()
3282                 .requireMinValuesToBeZero()
3283                 .addReadPermission(Car.PERMISSION_POWERTRAIN)
3284                 .addReadPermission(Car.PERMISSION_CONTROL_POWERTRAIN)
3285                 .addWritePermission(Car.PERMISSION_CONTROL_POWERTRAIN);
3286     }
3287 
3288     private static VehiclePropertyVerifier.Builder<Integer> getEvStoppingModeVerifierBuilder() {
3289         return VehiclePropertyVerifier.newBuilder(
3290                         VehiclePropertyIds.EV_STOPPING_MODE,
3291                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE,
3292                         VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
3293                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
3294                         Integer.class)
3295                 .setAllPossibleEnumValues(EV_STOPPING_MODES)
3296                 .setAllPossibleUnwritableValues(EV_STOPPING_MODE_UNWRITABLE_STATES)
3297                 .addReadPermission(Car.PERMISSION_POWERTRAIN)
3298                 .addReadPermission(Car.PERMISSION_CONTROL_POWERTRAIN)
3299                 .addWritePermission(Car.PERMISSION_CONTROL_POWERTRAIN);
3300     }
3301 
3302     private static VehiclePropertyVerifier.Builder<Boolean> getAbsActiveVerifierBuilder() {
3303         return VehiclePropertyVerifier.newBuilder(
3304                         VehiclePropertyIds.ABS_ACTIVE,
3305                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ,
3306                         VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
3307                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
3308                         Boolean.class)
3309                 .addReadPermission(Car.PERMISSION_CAR_DYNAMICS_STATE);
3310     }
3311 
3312     private static VehiclePropertyVerifier.Builder<Boolean>
3313             getTractionControlActiveVerifierBuilder() {
3314         return VehiclePropertyVerifier.newBuilder(
3315                         VehiclePropertyIds.TRACTION_CONTROL_ACTIVE,
3316                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ,
3317                         VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
3318                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
3319                         Boolean.class)
3320                 .addReadPermission(Car.PERMISSION_CAR_DYNAMICS_STATE);
3321     }
3322 
3323     private static VehiclePropertyVerifier.Builder<Integer> getDoorPosVerifierBuilder() {
3324         return VehiclePropertyVerifier.newBuilder(
3325                         VehiclePropertyIds.DOOR_POS,
3326                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE,
3327                         VehicleAreaType.VEHICLE_AREA_TYPE_DOOR,
3328                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
3329                         Integer.class)
3330                 .requireMinMaxValues()
3331                 .requireMinValuesToBeZero()
3332                 .addReadPermission(Car.PERMISSION_CONTROL_CAR_DOORS)
3333                 .addWritePermission(Car.PERMISSION_CONTROL_CAR_DOORS);
3334     }
3335 
3336     private static VehiclePropertyVerifier.Builder<Integer> getDoorMoveVerifierBuilder() {
3337         return VehiclePropertyVerifier.newBuilder(
3338                         VehiclePropertyIds.DOOR_MOVE,
3339                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE,
3340                         VehicleAreaType.VEHICLE_AREA_TYPE_DOOR,
3341                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
3342                         Integer.class)
3343                 .requireMinMaxValues()
3344                 .requireZeroToBeContainedInMinMaxRanges()
3345                 .addReadPermission(Car.PERMISSION_CONTROL_CAR_DOORS)
3346                 .addWritePermission(Car.PERMISSION_CONTROL_CAR_DOORS);
3347     }
3348 
3349     private static VehiclePropertyVerifier.Builder<Boolean> getDoorLockVerifierBuilder() {
3350         return VehiclePropertyVerifier.newBuilder(
3351                         VehiclePropertyIds.DOOR_LOCK,
3352                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE,
3353                         VehicleAreaType.VEHICLE_AREA_TYPE_DOOR,
3354                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
3355                         Boolean.class)
3356                 .addReadPermission(Car.PERMISSION_CONTROL_CAR_DOORS)
3357                 .addWritePermission(Car.PERMISSION_CONTROL_CAR_DOORS);
3358     }
3359 
3360     private static VehiclePropertyVerifier.Builder<Boolean>
3361             getDoorChildLockEnabledVerifierBuilder() {
3362         return VehiclePropertyVerifier.newBuilder(
3363                         VehiclePropertyIds.DOOR_CHILD_LOCK_ENABLED,
3364                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE,
3365                         VehicleAreaType.VEHICLE_AREA_TYPE_DOOR,
3366                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
3367                         Boolean.class)
3368                 .addReadPermission(Car.PERMISSION_CONTROL_CAR_DOORS)
3369                 .addWritePermission(Car.PERMISSION_CONTROL_CAR_DOORS);
3370     }
3371 
3372     private static VehiclePropertyVerifier.Builder<Integer>
3373             getVehicleDrivingAutomationCurrentLevelVerifierBuilder() {
3374         return VehiclePropertyVerifier.newBuilder(
3375                 VehiclePropertyIds.VEHICLE_DRIVING_AUTOMATION_CURRENT_LEVEL,
3376                 CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ,
3377                 VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
3378                 CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
3379                 Integer.class)
3380             .setAllPossibleEnumValues(VEHICLE_AUTONOMOUS_STATES)
3381             .addReadPermission(Car.PERMISSION_CAR_DRIVING_STATE);
3382     }
3383 
3384     private static VehiclePropertyVerifier.Builder<Integer> getMirrorZPosVerifierBuilder() {
3385         return VehiclePropertyVerifier.newBuilder(
3386                         VehiclePropertyIds.MIRROR_Z_POS,
3387                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE,
3388                         VehicleAreaType.VEHICLE_AREA_TYPE_MIRROR,
3389                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
3390                         Integer.class)
3391                 .requireMinMaxValues()
3392                 .requireZeroToBeContainedInMinMaxRanges()
3393                 .addReadPermission(Car.PERMISSION_CONTROL_CAR_MIRRORS)
3394                 .addWritePermission(Car.PERMISSION_CONTROL_CAR_MIRRORS);
3395     }
3396 
3397     private static VehiclePropertyVerifier.Builder<Integer> getMirrorZMoveVerifierBuilder() {
3398         return VehiclePropertyVerifier.newBuilder(
3399                         VehiclePropertyIds.MIRROR_Z_MOVE,
3400                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE,
3401                         VehicleAreaType.VEHICLE_AREA_TYPE_MIRROR,
3402                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
3403                         Integer.class)
3404                 .requireMinMaxValues()
3405                 .requireZeroToBeContainedInMinMaxRanges()
3406                 .addReadPermission(Car.PERMISSION_CONTROL_CAR_MIRRORS)
3407                 .addWritePermission(Car.PERMISSION_CONTROL_CAR_MIRRORS);
3408     }
3409 
3410     private static VehiclePropertyVerifier.Builder<Integer> getMirrorYPosVerifierBuilder() {
3411         return VehiclePropertyVerifier.newBuilder(
3412                         VehiclePropertyIds.MIRROR_Y_POS,
3413                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE,
3414                         VehicleAreaType.VEHICLE_AREA_TYPE_MIRROR,
3415                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
3416                         Integer.class)
3417                 .requireMinMaxValues()
3418                 .requireZeroToBeContainedInMinMaxRanges()
3419                 .addReadPermission(Car.PERMISSION_CONTROL_CAR_MIRRORS)
3420                 .addWritePermission(Car.PERMISSION_CONTROL_CAR_MIRRORS);
3421     }
3422 
3423     private static VehiclePropertyVerifier.Builder<Integer> getMirrorYMoveVerifierBuilder() {
3424         return VehiclePropertyVerifier.newBuilder(
3425                         VehiclePropertyIds.MIRROR_Y_MOVE,
3426                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE,
3427                         VehicleAreaType.VEHICLE_AREA_TYPE_MIRROR,
3428                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
3429                         Integer.class)
3430                 .requireMinMaxValues()
3431                 .requireZeroToBeContainedInMinMaxRanges()
3432                 .addReadPermission(Car.PERMISSION_CONTROL_CAR_MIRRORS)
3433                 .addWritePermission(Car.PERMISSION_CONTROL_CAR_MIRRORS);
3434     }
3435 
3436     private static VehiclePropertyVerifier.Builder<Boolean> getMirrorLockVerifierBuilder() {
3437         return VehiclePropertyVerifier.newBuilder(
3438                         VehiclePropertyIds.MIRROR_LOCK,
3439                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE,
3440                         VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
3441                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
3442                         Boolean.class)
3443                 .addReadPermission(Car.PERMISSION_CONTROL_CAR_MIRRORS)
3444                 .addWritePermission(Car.PERMISSION_CONTROL_CAR_MIRRORS);
3445     }
3446 
3447     private static VehiclePropertyVerifier.Builder<Boolean> getMirrorFoldVerifierBuilder() {
3448         return VehiclePropertyVerifier.newBuilder(
3449                         VehiclePropertyIds.MIRROR_FOLD,
3450                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE,
3451                         VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
3452                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
3453                         Boolean.class)
3454                 .addReadPermission(Car.PERMISSION_CONTROL_CAR_MIRRORS)
3455                 .addWritePermission(Car.PERMISSION_CONTROL_CAR_MIRRORS);
3456     }
3457 
3458     private static VehiclePropertyVerifier.Builder<Boolean>
3459             getMirrorAutoFoldEnabledVerifierBuilder() {
3460         return VehiclePropertyVerifier.newBuilder(
3461                         VehiclePropertyIds.MIRROR_AUTO_FOLD_ENABLED,
3462                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE,
3463                         VehicleAreaType.VEHICLE_AREA_TYPE_MIRROR,
3464                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
3465                         Boolean.class)
3466                 .addReadPermission(Car.PERMISSION_CONTROL_CAR_MIRRORS)
3467                 .addWritePermission(Car.PERMISSION_CONTROL_CAR_MIRRORS);
3468     }
3469 
3470     private static VehiclePropertyVerifier.Builder<Boolean>
3471             getMirrorAutoTiltEnabledVerifierBuilder() {
3472         return VehiclePropertyVerifier.newBuilder(
3473                         VehiclePropertyIds.MIRROR_AUTO_TILT_ENABLED,
3474                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE,
3475                         VehicleAreaType.VEHICLE_AREA_TYPE_MIRROR,
3476                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
3477                         Boolean.class)
3478                 .addReadPermission(Car.PERMISSION_CONTROL_CAR_MIRRORS)
3479                 .addWritePermission(Car.PERMISSION_CONTROL_CAR_MIRRORS);
3480     }
3481 
3482     private static VehiclePropertyVerifier.Builder<Integer> getWindowPosVerifierBuilder() {
3483         return VehiclePropertyVerifier.newBuilder(
3484                         VehiclePropertyIds.WINDOW_POS,
3485                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE,
3486                         VehicleAreaType.VEHICLE_AREA_TYPE_WINDOW,
3487                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
3488                         Integer.class)
3489                 .requireMinMaxValues()
3490                 .requireZeroToBeContainedInMinMaxRanges()
3491                 .addReadPermission(Car.PERMISSION_CONTROL_CAR_WINDOWS)
3492                 .addWritePermission(Car.PERMISSION_CONTROL_CAR_WINDOWS);
3493     }
3494 
3495     private static VehiclePropertyVerifier.Builder<Integer> getWindowMoveVerifierBuilder() {
3496         return VehiclePropertyVerifier.newBuilder(
3497                         VehiclePropertyIds.WINDOW_MOVE,
3498                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE,
3499                         VehicleAreaType.VEHICLE_AREA_TYPE_WINDOW,
3500                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
3501                         Integer.class)
3502                 .requireMinMaxValues()
3503                 .requireZeroToBeContainedInMinMaxRanges()
3504                 .addReadPermission(Car.PERMISSION_CONTROL_CAR_WINDOWS)
3505                 .addWritePermission(Car.PERMISSION_CONTROL_CAR_WINDOWS);
3506     }
3507 
3508     private static VehiclePropertyVerifier.Builder<Boolean> getWindowLockVerifierBuilder() {
3509         return VehiclePropertyVerifier.newBuilder(
3510                         VehiclePropertyIds.WINDOW_LOCK,
3511                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE,
3512                         VehicleAreaType.VEHICLE_AREA_TYPE_WINDOW,
3513                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
3514                         Boolean.class)
3515                 .addReadPermission(Car.PERMISSION_CONTROL_CAR_WINDOWS)
3516                 .addWritePermission(Car.PERMISSION_CONTROL_CAR_WINDOWS);
3517     }
3518 
3519     private static VehiclePropertyVerifier.Builder<Integer>
3520             getWindshieldWipersPeriodVerifierBuilder() {
3521         return VehiclePropertyVerifier.newBuilder(
3522                         VehiclePropertyIds.WINDSHIELD_WIPERS_PERIOD,
3523                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ,
3524                         VehicleAreaType.VEHICLE_AREA_TYPE_WINDOW,
3525                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
3526                         Integer.class)
3527                 .requireMinMaxValues()
3528                 .requireMinValuesToBeZero()
3529                 .addReadPermission(Car.PERMISSION_READ_WINDSHIELD_WIPERS);
3530     }
3531 
3532     private static VehiclePropertyVerifier.Builder<Integer>
3533             getWindshieldWipersStateVerifierBuilder() {
3534         return VehiclePropertyVerifier.newBuilder(
3535                         VehiclePropertyIds.WINDSHIELD_WIPERS_STATE,
3536                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ,
3537                         VehicleAreaType.VEHICLE_AREA_TYPE_WINDOW,
3538                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
3539                         Integer.class)
3540                 .setAllPossibleEnumValues(WINDSHIELD_WIPERS_STATES)
3541                 .addReadPermission(Car.PERMISSION_READ_WINDSHIELD_WIPERS);
3542     }
3543 
3544     private static VehiclePropertyVerifier.Builder<Integer>
3545             getWindshieldWipersSwitchVerifierBuilder() {
3546         return VehiclePropertyVerifier.newBuilder(
3547                         VehiclePropertyIds.WINDSHIELD_WIPERS_SWITCH,
3548                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE,
3549                         VehicleAreaType.VEHICLE_AREA_TYPE_WINDOW,
3550                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
3551                         Integer.class)
3552                 .setAllPossibleEnumValues(WINDSHIELD_WIPERS_SWITCHES)
3553                 .setAllPossibleUnwritableValues(WINDSHIELD_WIPERS_SWITCH_UNWRITABLE_STATES)
3554                 .setCarPropertyConfigVerifier(
3555                         (verifierContext, carPropertyConfig) -> {
3556                             // Test to ensure that for both INTERMITTENT_LEVEL_* and
3557                             // CONTINUOUS_LEVEL_* the supportedEnumValues are consecutive.
3558                             // E.g. levels 1,2,3 is a valid config, but 1,3,4 is not valid because
3559                             // level 2 must be supported if level 3 or greater is supported.
3560                             ImmutableList<Integer> intermittentLevels =
3561                                     ImmutableList.<Integer>builder()
3562                                             .add(
3563                                                     WindshieldWipersSwitch.INTERMITTENT_LEVEL_5,
3564                                                     WindshieldWipersSwitch.INTERMITTENT_LEVEL_4,
3565                                                     WindshieldWipersSwitch.INTERMITTENT_LEVEL_3,
3566                                                     WindshieldWipersSwitch.INTERMITTENT_LEVEL_2,
3567                                                     WindshieldWipersSwitch.INTERMITTENT_LEVEL_1)
3568                                             .build();
3569 
3570                             ImmutableList<Integer> continuousLevels =
3571                                     ImmutableList.<Integer>builder()
3572                                             .add(
3573                                                     WindshieldWipersSwitch.CONTINUOUS_LEVEL_5,
3574                                                     WindshieldWipersSwitch.CONTINUOUS_LEVEL_4,
3575                                                     WindshieldWipersSwitch.CONTINUOUS_LEVEL_3,
3576                                                     WindshieldWipersSwitch.CONTINUOUS_LEVEL_2,
3577                                                     WindshieldWipersSwitch.CONTINUOUS_LEVEL_1)
3578                                             .build();
3579 
3580                             for (int areaId: carPropertyConfig.getAreaIds()) {
3581                                 AreaIdConfig<Integer> areaIdConfig =
3582                                         (AreaIdConfig<Integer>) carPropertyConfig
3583                                                 .getAreaIdConfig(areaId);
3584                                 List<Integer> supportedEnumValues =
3585                                         areaIdConfig.getSupportedEnumValues();
3586 
3587                                 verifyWindshieldWipersSwitchLevelsAreConsecutive(
3588                                         supportedEnumValues, intermittentLevels, areaId);
3589                                 verifyWindshieldWipersSwitchLevelsAreConsecutive(
3590                                         supportedEnumValues, continuousLevels, areaId);
3591                             }
3592                         })
3593                 .addReadPermission(Car.PERMISSION_READ_WINDSHIELD_WIPERS)
3594                 .addReadPermission(Car.PERMISSION_CONTROL_WINDSHIELD_WIPERS)
3595                 .addWritePermission(Car.PERMISSION_CONTROL_WINDSHIELD_WIPERS);
3596     }
3597 
3598     private static VehiclePropertyVerifier.Builder<Integer>
3599             getSteeringWheelDepthPosVerifierBuilder() {
3600         return VehiclePropertyVerifier.newBuilder(
3601                         VehiclePropertyIds.STEERING_WHEEL_DEPTH_POS,
3602                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE,
3603                         VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
3604                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
3605                         Integer.class)
3606                 .requireMinMaxValues()
3607                 .addReadPermission(Car.PERMISSION_CONTROL_STEERING_WHEEL)
3608                 .addWritePermission(Car.PERMISSION_CONTROL_STEERING_WHEEL);
3609     }
3610 
3611     private static VehiclePropertyVerifier.Builder<Integer>
3612             getSteeringWheelDepthMoveVerifierBuilder() {
3613         return VehiclePropertyVerifier.newBuilder(
3614                         VehiclePropertyIds.STEERING_WHEEL_DEPTH_MOVE,
3615                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE,
3616                         VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
3617                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
3618                         Integer.class)
3619                 .requireMinMaxValues()
3620                 .requireZeroToBeContainedInMinMaxRanges()
3621                 .addReadPermission(Car.PERMISSION_CONTROL_STEERING_WHEEL)
3622                 .addWritePermission(Car.PERMISSION_CONTROL_STEERING_WHEEL);
3623     }
3624 
3625     private static VehiclePropertyVerifier.Builder<Integer>
3626             getSteeringWheelHeightPosVerifierBuilder() {
3627         return VehiclePropertyVerifier.newBuilder(
3628                         VehiclePropertyIds.STEERING_WHEEL_HEIGHT_POS,
3629                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE,
3630                         VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
3631                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
3632                         Integer.class)
3633                 .requireMinMaxValues()
3634                 .addReadPermission(Car.PERMISSION_CONTROL_STEERING_WHEEL)
3635                 .addWritePermission(Car.PERMISSION_CONTROL_STEERING_WHEEL);
3636     }
3637 
3638     private static VehiclePropertyVerifier.Builder<Integer>
3639             getSteeringWheelHeightMoveVerifierBuilder() {
3640         return VehiclePropertyVerifier.newBuilder(
3641                         VehiclePropertyIds.STEERING_WHEEL_HEIGHT_MOVE,
3642                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE,
3643                         VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
3644                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
3645                         Integer.class)
3646                 .requireMinMaxValues()
3647                 .requireZeroToBeContainedInMinMaxRanges()
3648                 .addReadPermission(Car.PERMISSION_CONTROL_STEERING_WHEEL)
3649                 .addWritePermission(Car.PERMISSION_CONTROL_STEERING_WHEEL);
3650     }
3651 
3652     private static VehiclePropertyVerifier.Builder<Boolean>
3653             getSteeringWheelTheftLockEnabledVerifierBuilder() {
3654         return VehiclePropertyVerifier.newBuilder(
3655                         VehiclePropertyIds.STEERING_WHEEL_THEFT_LOCK_ENABLED,
3656                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE,
3657                         VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
3658                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
3659                         Boolean.class)
3660                 .addReadPermission(Car.PERMISSION_CONTROL_STEERING_WHEEL)
3661                 .addWritePermission(Car.PERMISSION_CONTROL_STEERING_WHEEL);
3662     }
3663 
3664     private static VehiclePropertyVerifier.Builder<Boolean>
3665             getSteeringWheelLockedVerifierBuilder() {
3666         return VehiclePropertyVerifier.newBuilder(
3667                         VehiclePropertyIds.STEERING_WHEEL_LOCKED,
3668                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE,
3669                         VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
3670                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
3671                         Boolean.class)
3672                 .addReadPermission(Car.PERMISSION_CONTROL_STEERING_WHEEL)
3673                 .addWritePermission(Car.PERMISSION_CONTROL_STEERING_WHEEL);
3674     }
3675 
3676     private static VehiclePropertyVerifier.Builder<Boolean>
3677             getSteeringWheelEasyAccessEnabledVerifierBuilder() {
3678         return VehiclePropertyVerifier.newBuilder(
3679                         VehiclePropertyIds.STEERING_WHEEL_EASY_ACCESS_ENABLED,
3680                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE,
3681                         VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
3682                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
3683                         Boolean.class)
3684                 .addReadPermission(Car.PERMISSION_CONTROL_STEERING_WHEEL)
3685                 .addWritePermission(Car.PERMISSION_CONTROL_STEERING_WHEEL);
3686     }
3687 
3688     private static VehiclePropertyVerifier.Builder<Integer> getGloveBoxDoorPosVerifierBuilder() {
3689         return VehiclePropertyVerifier.newBuilder(
3690                         VehiclePropertyIds.GLOVE_BOX_DOOR_POS,
3691                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE,
3692                         VehicleAreaType.VEHICLE_AREA_TYPE_SEAT,
3693                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
3694                         Integer.class)
3695                 .requireMinMaxValues()
3696                 .requireMinValuesToBeZero()
3697                 .addReadPermission(Car.PERMISSION_CONTROL_GLOVE_BOX)
3698                 .addWritePermission(Car.PERMISSION_CONTROL_GLOVE_BOX);
3699     }
3700 
3701     private static VehiclePropertyVerifier.Builder<Boolean> getGloveBoxLockedVerifierBuilder() {
3702         return VehiclePropertyVerifier.newBuilder(
3703                         VehiclePropertyIds.GLOVE_BOX_LOCKED,
3704                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE,
3705                         VehicleAreaType.VEHICLE_AREA_TYPE_SEAT,
3706                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
3707                         Boolean.class)
3708                 .addReadPermission(Car.PERMISSION_CONTROL_GLOVE_BOX)
3709                 .addWritePermission(Car.PERMISSION_CONTROL_GLOVE_BOX);
3710     }
3711 
3712     private static VehiclePropertyVerifier.Builder<Integer>
3713             getDistanceDisplayUnitsVerifierBuilder() {
3714         return VehiclePropertyVerifier.newBuilder(
3715                         VehiclePropertyIds.DISTANCE_DISPLAY_UNITS,
3716                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE,
3717                         VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
3718                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
3719                         Integer.class)
3720                 .setAllPossibleEnumValues(DISTANCE_DISPLAY_UNITS)
3721                 .setPossibleConfigArrayValues(DISTANCE_DISPLAY_UNITS)
3722                 .requirePropertyValueTobeInConfigArray()
3723                 .verifySetterWithConfigArrayValues()
3724                 .addReadPermission(Car.PERMISSION_READ_DISPLAY_UNITS)
3725                 .addWritePermission(ImmutableSet.of(Car.PERMISSION_CONTROL_DISPLAY_UNITS,
3726                         Car.PERMISSION_VENDOR_EXTENSION));
3727     }
3728 
3729     private static VehiclePropertyVerifier.Builder<Integer>
3730             getFuelVolumeDisplayUnitsVerifierBuilder() {
3731         return VehiclePropertyVerifier.newBuilder(
3732                         VehiclePropertyIds.FUEL_VOLUME_DISPLAY_UNITS,
3733                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE,
3734                         VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
3735                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
3736                         Integer.class)
3737                 .setAllPossibleEnumValues(VOLUME_DISPLAY_UNITS)
3738                 .setPossibleConfigArrayValues(VOLUME_DISPLAY_UNITS)
3739                 .requirePropertyValueTobeInConfigArray()
3740                 .verifySetterWithConfigArrayValues()
3741                 .addReadPermission(Car.PERMISSION_READ_DISPLAY_UNITS)
3742                 .addWritePermission(ImmutableSet.of(Car.PERMISSION_CONTROL_DISPLAY_UNITS,
3743                         Car.PERMISSION_VENDOR_EXTENSION));
3744     }
3745 
3746     private static VehiclePropertyVerifier.Builder<Float> getTirePressureVerifierBuilder() {
3747         return VehiclePropertyVerifier.newBuilder(
3748                         VehiclePropertyIds.TIRE_PRESSURE,
3749                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ,
3750                         VehicleAreaType.VEHICLE_AREA_TYPE_WHEEL,
3751                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_CONTINUOUS,
3752                         Float.class)
3753                 .requireMinMaxValues()
3754                 .setCarPropertyValueVerifier(
3755                         (verifierContext, carPropertyConfig, propertyId, areaId, timestampNanos,
3756                                 tirePressure) ->
3757                                 assertWithMessage(
3758                                                 "TIRE_PRESSURE Float value"
3759                                                         + " at Area ID equals to "
3760                                                         + areaId
3761                                                         + " must be greater than or equal 0")
3762                                         .that(tirePressure)
3763                                         .isAtLeast(0))
3764                 .addReadPermission(Car.PERMISSION_TIRES);
3765     }
3766 
3767     private static VehiclePropertyVerifier.Builder<Float>
3768             getCriticallyLowTirePressureVerifierBuilder() {
3769         return VehiclePropertyVerifier.newBuilder(
3770                         VehiclePropertyIds.CRITICALLY_LOW_TIRE_PRESSURE,
3771                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ,
3772                         VehicleAreaType.VEHICLE_AREA_TYPE_WHEEL,
3773                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_STATIC,
3774                         Float.class)
3775                 .setCarPropertyValueVerifier(
3776                         (verifierContext, carPropertyConfig, propertyId, areaId, timestampNanos,
3777                                 criticallyLowTirePressure) -> {
3778                             assertWithMessage(
3779                                             "CRITICALLY_LOW_TIRE_PRESSURE Float value"
3780                                                     + "at Area ID equals to"
3781                                                     + areaId
3782                                                     + " must be greater than or equal 0")
3783                                     .that(criticallyLowTirePressure)
3784                                     .isAtLeast(0);
3785 
3786                             CarPropertyConfig<?> tirePressureConfig =
3787                                     verifierContext.getCarPropertyManager().getCarPropertyConfig(
3788                                             VehiclePropertyIds.TIRE_PRESSURE);
3789 
3790                             if (tirePressureConfig == null
3791                                     || tirePressureConfig.getMinValue(areaId) == null) {
3792                                 return;
3793                             }
3794 
3795                             assertWithMessage(
3796                                             "CRITICALLY_LOW_TIRE_PRESSURE Float value"
3797                                                     + "at Area ID equals to"
3798                                                     + areaId
3799                                                     + " must not exceed"
3800                                                     + " minFloatValue in TIRE_PRESSURE")
3801                                     .that(criticallyLowTirePressure)
3802                                     .isAtMost((Float) tirePressureConfig.getMinValue(areaId));
3803                         })
3804                 .addReadPermission(Car.PERMISSION_TIRES);
3805     }
3806 
3807     private static VehiclePropertyVerifier.Builder<Integer>
3808             getTirePressureDisplayUnitsVerifierBuilder() {
3809         return VehiclePropertyVerifier.newBuilder(
3810                         VehiclePropertyIds.TIRE_PRESSURE_DISPLAY_UNITS,
3811                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE,
3812                         VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
3813                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
3814                         Integer.class)
3815                 .setAllPossibleEnumValues(PRESSURE_DISPLAY_UNITS)
3816                 .setPossibleConfigArrayValues(PRESSURE_DISPLAY_UNITS)
3817                 .requirePropertyValueTobeInConfigArray()
3818                 .verifySetterWithConfigArrayValues()
3819                 .addReadPermission(Car.PERMISSION_READ_DISPLAY_UNITS)
3820                 .addWritePermission(ImmutableSet.of(Car.PERMISSION_CONTROL_DISPLAY_UNITS,
3821                         Car.PERMISSION_VENDOR_EXTENSION));
3822     }
3823 
3824     private static VehiclePropertyVerifier.Builder<Integer>
3825             getEvBatteryDisplayUnitsVerifierBuilder() {
3826         return VehiclePropertyVerifier.newBuilder(
3827                         VehiclePropertyIds.EV_BATTERY_DISPLAY_UNITS,
3828                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE,
3829                         VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
3830                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
3831                         Integer.class)
3832                 .setAllPossibleEnumValues(BATTERY_DISPLAY_UNITS)
3833                 .setPossibleConfigArrayValues(BATTERY_DISPLAY_UNITS)
3834                 .requirePropertyValueTobeInConfigArray()
3835                 .verifySetterWithConfigArrayValues()
3836                 .addReadPermission(Car.PERMISSION_READ_DISPLAY_UNITS)
3837                 .addWritePermission(ImmutableSet.of(Car.PERMISSION_CONTROL_DISPLAY_UNITS,
3838                         Car.PERMISSION_VENDOR_EXTENSION));
3839     }
3840 
3841     private static VehiclePropertyVerifier.Builder<Integer>
3842             getVehicleSpeedDisplayUnitsVerifierBuilder() {
3843         return VehiclePropertyVerifier.newBuilder(
3844                         VehiclePropertyIds.VEHICLE_SPEED_DISPLAY_UNITS,
3845                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE,
3846                         VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
3847                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
3848                         Integer.class)
3849                 .setAllPossibleEnumValues(SPEED_DISPLAY_UNITS)
3850                 .setPossibleConfigArrayValues(SPEED_DISPLAY_UNITS)
3851                 .requirePropertyValueTobeInConfigArray()
3852                 .verifySetterWithConfigArrayValues()
3853                 .addReadPermission(Car.PERMISSION_READ_DISPLAY_UNITS)
3854                 .addWritePermission(ImmutableSet.of(Car.PERMISSION_CONTROL_DISPLAY_UNITS,
3855                         Car.PERMISSION_VENDOR_EXTENSION));
3856     }
3857 
3858     private static VehiclePropertyVerifier.Builder<Boolean>
3859             getFuelConsumptionUnitsDistanceOverVolumeVerifierBuilder() {
3860         return VehiclePropertyVerifier.newBuilder(
3861                         VehiclePropertyIds.FUEL_CONSUMPTION_UNITS_DISTANCE_OVER_VOLUME,
3862                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE,
3863                         VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
3864                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
3865                         Boolean.class)
3866                 .addReadPermission(Car.PERMISSION_READ_DISPLAY_UNITS)
3867                 .addWritePermission(ImmutableSet.of(Car.PERMISSION_CONTROL_DISPLAY_UNITS,
3868                         Car.PERMISSION_VENDOR_EXTENSION));
3869     }
3870 
3871     private static VehiclePropertyVerifier.Builder<Float> getFuelLevelVerifierBuilder() {
3872         return VehiclePropertyVerifier.newBuilder(
3873                         VehiclePropertyIds.FUEL_LEVEL,
3874                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ,
3875                         VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
3876                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_CONTINUOUS,
3877                         Float.class)
3878                 .setCarPropertyConfigVerifier(
3879                         (verifierContext, carPropertyConfig) -> {
3880                             assertFuelPropertyNotImplementedOnEv(
3881                                     verifierContext.getCarPropertyManager(),
3882                                     VehiclePropertyIds.FUEL_LEVEL);
3883                         })
3884                 .setCarPropertyValueVerifier(
3885                         (verifierContext, carPropertyConfig, propertyId, areaId, timestampNanos,
3886                                 fuelLevel) -> {
3887                             assertWithMessage(
3888                                             "FUEL_LEVEL Float value must be greater than or equal"
3889                                                 + " 0")
3890                                     .that(fuelLevel)
3891                                     .isAtLeast(0);
3892 
3893                             if (verifierContext.getCarPropertyManager().getCarPropertyConfig(
3894                                             VehiclePropertyIds.INFO_FUEL_CAPACITY)
3895                                     == null) {
3896                                 return;
3897                             }
3898 
3899                             CarPropertyValue<?> infoFuelCapacityValue =
3900                                     verifierContext.getCarPropertyManager().getProperty(
3901                                             VehiclePropertyIds.INFO_FUEL_CAPACITY,
3902                                             VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL);
3903 
3904                             assertWithMessage(
3905                                             "FUEL_LEVEL Float value must not exceed"
3906                                                 + " INFO_FUEL_CAPACITY Float value")
3907                                     .that(fuelLevel)
3908                                     .isAtMost((Float) infoFuelCapacityValue.getValue());
3909                         })
3910                 .addReadPermission(Car.PERMISSION_ENERGY);
3911     }
3912 
3913     private static VehiclePropertyVerifier.Builder<Float> getEvBatteryLevelVerifierBuilder() {
3914         return VehiclePropertyVerifier.newBuilder(
3915                         VehiclePropertyIds.EV_BATTERY_LEVEL,
3916                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ,
3917                         VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
3918                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_CONTINUOUS,
3919                         Float.class)
3920                 .setCarPropertyValueVerifier(
3921                         (verifierContext, carPropertyConfig, propertyId, areaId, timestampNanos,
3922                                 evBatteryLevel) -> {
3923                             assertWithMessage(
3924                                             "EV_BATTERY_LEVEL Float value must be greater than or"
3925                                                 + " equal 0")
3926                                     .that(evBatteryLevel)
3927                                     .isAtLeast(0);
3928 
3929                             if (verifierContext.getCarPropertyManager().getCarPropertyConfig(
3930                                             VehiclePropertyIds.INFO_EV_BATTERY_CAPACITY)
3931                                     == null) {
3932                                 return;
3933                             }
3934 
3935                             CarPropertyValue<?> infoEvBatteryCapacityValue =
3936                                     verifierContext.getCarPropertyManager().getProperty(
3937                                             VehiclePropertyIds.INFO_EV_BATTERY_CAPACITY,
3938                                             VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL);
3939 
3940                             assertWithMessage(
3941                                             "EV_BATTERY_LEVEL Float value must not exceed "
3942                                                     + "INFO_EV_BATTERY_CAPACITY Float "
3943                                                     + "value")
3944                                     .that(evBatteryLevel)
3945                                     .isAtMost((Float) infoEvBatteryCapacityValue.getValue());
3946                         })
3947                 .addReadPermission(Car.PERMISSION_ENERGY);
3948     }
3949 
3950     private static VehiclePropertyVerifier.Builder<Float>
3951             getEvCurrentBatteryCapacityVerifierBuilder() {
3952         return VehiclePropertyVerifier.newBuilder(
3953                         VehiclePropertyIds.EV_CURRENT_BATTERY_CAPACITY,
3954                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ,
3955                         VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
3956                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
3957                         Float.class)
3958                 .setCarPropertyValueVerifier(
3959                         (verifierContext, carPropertyConfig, propertyId, areaId, timestampNanos,
3960                                 evCurrentBatteryCapacity) -> {
3961                             assertWithMessage(
3962                                             "EV_CURRENT_BATTERY_CAPACITY Float value must be"
3963                                                     + "greater than or equal 0")
3964                                     .that(evCurrentBatteryCapacity)
3965                                     .isAtLeast(0);
3966 
3967                             if (verifierContext.getCarPropertyManager().getCarPropertyConfig(
3968                                             VehiclePropertyIds.INFO_EV_BATTERY_CAPACITY)
3969                                     == null) {
3970                                 return;
3971                             }
3972 
3973                             CarPropertyValue<?> infoEvBatteryCapacityValue =
3974                                     verifierContext.getCarPropertyManager().getProperty(
3975                                             VehiclePropertyIds.INFO_EV_BATTERY_CAPACITY,
3976                                             /*areaId=*/0);
3977 
3978                             assertWithMessage(
3979                                             "EV_CURRENT_BATTERY_CAPACITY Float value must not"
3980                                                     + "exceed INFO_EV_BATTERY_CAPACITY Float "
3981                                                     + "value")
3982                                     .that(evCurrentBatteryCapacity)
3983                                     .isAtMost((Float) infoEvBatteryCapacityValue.getValue());
3984                         })
3985                 .addReadPermission(Car.PERMISSION_ENERGY);
3986     }
3987 
3988     private static VehiclePropertyVerifier.Builder<Float>
3989             getEvBatteryInstantaneousChargeRateVerifierBuilder() {
3990         return VehiclePropertyVerifier.newBuilder(
3991                         VehiclePropertyIds.EV_BATTERY_INSTANTANEOUS_CHARGE_RATE,
3992                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ,
3993                         VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
3994                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_CONTINUOUS,
3995                         Float.class)
3996                 .addReadPermission(Car.PERMISSION_ENERGY);
3997     }
3998 
3999     private static VehiclePropertyVerifier.Builder<Float> getRangeRemainingVerifierBuilder() {
4000         return VehiclePropertyVerifier.newBuilder(
4001                         VehiclePropertyIds.RANGE_REMAINING,
4002                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE,
4003                         VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
4004                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_CONTINUOUS,
4005                         Float.class)
4006                 .setCarPropertyValueVerifier(
4007                         (verifierContext, carPropertyConfig, propertyId, areaId, timestampNanos,
4008                                 rangeRemaining) ->
4009                                 assertWithMessage(
4010                                         "RANGE_REMAINING Float value must be greater than"
4011                                                 + " or equal 0")
4012                                         .that(rangeRemaining)
4013                                         .isAtLeast(0))
4014                 .addReadPermission(Car.PERMISSION_ENERGY)
4015                 .addReadPermission(Car.PERMISSION_ADJUST_RANGE_REMAINING)
4016                 .addWritePermission(Car.PERMISSION_ADJUST_RANGE_REMAINING);
4017     }
4018 
4019     private static VehiclePropertyVerifier.Builder<Float>
4020             getEvBatteryAverageTemperatureVerifierBuilder() {
4021         return VehiclePropertyVerifier.newBuilder(
4022                         VehiclePropertyIds.EV_BATTERY_AVERAGE_TEMPERATURE,
4023                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ,
4024                         VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
4025                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_CONTINUOUS,
4026                         Float.class)
4027                 .addReadPermission(Car.PERMISSION_ENERGY);
4028     }
4029 
4030     private static VehiclePropertyVerifier.Builder<Boolean> getFuelLevelLowVerifierBuilder() {
4031         return VehiclePropertyVerifier.newBuilder(
4032                         VehiclePropertyIds.FUEL_LEVEL_LOW,
4033                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ,
4034                         VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
4035                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
4036                         Boolean.class)
4037                 .addReadPermission(Car.PERMISSION_ENERGY);
4038     }
4039 
4040     private static VehiclePropertyVerifier.Builder<Boolean> getFuelDoorOpenVerifierBuilder() {
4041         return VehiclePropertyVerifier.newBuilder(
4042                         VehiclePropertyIds.FUEL_DOOR_OPEN,
4043                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE,
4044                         VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
4045                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
4046                         Boolean.class)
4047                 .setCarPropertyConfigVerifier(
4048                         (verifierContext, config) -> {
4049                             assertFuelPropertyNotImplementedOnEv(
4050                                     verifierContext.getCarPropertyManager(),
4051                                     VehiclePropertyIds.FUEL_DOOR_OPEN);
4052                         })
4053                 .addReadPermission(Car.PERMISSION_ENERGY_PORTS)
4054                 .addReadPermission(Car.PERMISSION_CONTROL_ENERGY_PORTS)
4055                 .addWritePermission(Car.PERMISSION_CONTROL_ENERGY_PORTS);
4056     }
4057 
4058     private static VehiclePropertyVerifier.Builder<Boolean> getEvChargePortOpenVerifierBuilder() {
4059         return VehiclePropertyVerifier.newBuilder(
4060                         VehiclePropertyIds.EV_CHARGE_PORT_OPEN,
4061                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE,
4062                         VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
4063                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
4064                         Boolean.class)
4065                 .addReadPermission(Car.PERMISSION_ENERGY_PORTS)
4066                 .addReadPermission(Car.PERMISSION_CONTROL_ENERGY_PORTS)
4067                 .addWritePermission(Car.PERMISSION_CONTROL_ENERGY_PORTS);
4068     }
4069 
4070     private static VehiclePropertyVerifier.Builder<Boolean>
4071             getEvChargePortConnectedVerifierBuilder() {
4072         return VehiclePropertyVerifier.newBuilder(
4073                         VehiclePropertyIds.EV_CHARGE_PORT_CONNECTED,
4074                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ,
4075                         VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
4076                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
4077                         Boolean.class)
4078                 .addReadPermission(Car.PERMISSION_ENERGY_PORTS);
4079     }
4080 
4081     private static VehiclePropertyVerifier.Builder<Float>
4082             getEvChargeCurrentDrawLimitVerifierBuilder() {
4083         return VehiclePropertyVerifier.newBuilder(
4084                         VehiclePropertyIds.EV_CHARGE_CURRENT_DRAW_LIMIT,
4085                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE,
4086                         VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
4087                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
4088                         Float.class)
4089                 .setConfigArrayVerifier(
4090                         (verifierContext, configArray) -> {
4091                             assertWithMessage(
4092                                     "EV_CHARGE_CURRENT_DRAW_LIMIT config array must be size"
4093                                             + " 1")
4094                                     .that(configArray.size())
4095                                     .isEqualTo(1);
4096 
4097                             int maxCurrentDrawThresholdAmps = configArray.get(0);
4098                             assertWithMessage(
4099                                     "EV_CHARGE_CURRENT_DRAW_LIMIT config array first"
4100                                             + " element specifies max current draw allowed by"
4101                                             + " vehicle in amperes.")
4102                                     .that(maxCurrentDrawThresholdAmps)
4103                                     .isGreaterThan(0);
4104                         })
4105                 .setCarPropertyValueVerifier(
4106                         (verifierContext, carPropertyConfig, propertyId, areaId, timestampNanos,
4107                          evChargeCurrentDrawLimit) -> {
4108                             List<Integer> evChargeCurrentDrawLimitConfigArray =
4109                                     carPropertyConfig.getConfigArray();
4110                             int maxCurrentDrawThresholdAmps =
4111                                     evChargeCurrentDrawLimitConfigArray.get(0);
4112 
4113                             assertWithMessage(
4114                                     "EV_CHARGE_CURRENT_DRAW_LIMIT value must be greater"
4115                                             + " than 0")
4116                                     .that(evChargeCurrentDrawLimit)
4117                                     .isGreaterThan(0);
4118                             assertWithMessage(
4119                                     "EV_CHARGE_CURRENT_DRAW_LIMIT value must be less than"
4120                                             + " or equal to max current draw by the vehicle")
4121                                     .that(evChargeCurrentDrawLimit)
4122                                     .isAtMost(maxCurrentDrawThresholdAmps);
4123                         })
4124                 .addReadPermission(Car.PERMISSION_ENERGY)
4125                 .addReadPermission(Car.PERMISSION_CONTROL_CAR_ENERGY)
4126                 .addWritePermission(Car.PERMISSION_CONTROL_CAR_ENERGY);
4127     }
4128 
4129     private static VehiclePropertyVerifier.Builder<Float> getEvChargePercentLimitVerifierBuilder() {
4130         return VehiclePropertyVerifier.newBuilder(
4131                         VehiclePropertyIds.EV_CHARGE_PERCENT_LIMIT,
4132                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE,
4133                         VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
4134                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
4135                         Float.class)
4136                 .setConfigArrayVerifier(
4137                         (verifierContext, configArray) -> {
4138                             for (int i = 0; i < configArray.size(); i++) {
4139                                 assertWithMessage(
4140                                         "EV_CHARGE_PERCENT_LIMIT configArray["
4141                                                 + i
4142                                                 + "] valid charge percent limit must be"
4143                                                 + " greater than 0")
4144                                         .that(configArray.get(i))
4145                                         .isGreaterThan(0);
4146                                 assertWithMessage(
4147                                         "EV_CHARGE_PERCENT_LIMIT configArray["
4148                                                 + i
4149                                                 + "] valid charge percent limit must be at"
4150                                                 + " most 100")
4151                                         .that(configArray.get(i))
4152                                         .isAtMost(100);
4153                             }
4154                         })
4155                 .setCarPropertyValueVerifier(
4156                         (verifierContext, carPropertyConfig, propertyId, areaId, timestampNanos,
4157                          evChargePercentLimit) -> {
4158                             List<Integer> evChargePercentLimitConfigArray =
4159                                     carPropertyConfig.getConfigArray();
4160 
4161                             if (evChargePercentLimitConfigArray.isEmpty()) {
4162                                 assertWithMessage(
4163                                         "EV_CHARGE_PERCENT_LIMIT value must be greater than"
4164                                                 + " 0")
4165                                         .that(evChargePercentLimit)
4166                                         .isGreaterThan(0);
4167                                 assertWithMessage(
4168                                         "EV_CHARGE_PERCENT_LIMIT value must be at most 100")
4169                                         .that(evChargePercentLimit)
4170                                         .isAtMost(100);
4171                             } else {
4172                                 assertWithMessage(
4173                                         "EV_CHARGE_PERCENT_LIMIT value must be in the"
4174                                                 + " configArray valid charge percent limit"
4175                                                 + " list")
4176                                         .that(evChargePercentLimit.intValue())
4177                                         .isIn(evChargePercentLimitConfigArray);
4178                             }
4179                         })
4180                 .addReadPermission(Car.PERMISSION_ENERGY)
4181                 .addReadPermission(Car.PERMISSION_CONTROL_CAR_ENERGY)
4182                 .addWritePermission(Car.PERMISSION_CONTROL_CAR_ENERGY);
4183     }
4184 
4185     private static VehiclePropertyVerifier.Builder<Integer> getEvChargeStateVerifierBuilder() {
4186         return VehiclePropertyVerifier.newBuilder(
4187                         VehiclePropertyIds.EV_CHARGE_STATE,
4188                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ,
4189                         VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
4190                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
4191                         Integer.class)
4192                 .setAllPossibleEnumValues(
4193                         ImmutableSet.of(
4194                                 EvChargeState.STATE_UNKNOWN,
4195                                 EvChargeState.STATE_CHARGING,
4196                                 EvChargeState.STATE_FULLY_CHARGED,
4197                                 EvChargeState.STATE_NOT_CHARGING,
4198                                 EvChargeState.STATE_ERROR))
4199                 .addReadPermission(Car.PERMISSION_ENERGY);
4200     }
4201 
4202     private static VehiclePropertyVerifier.Builder<Boolean> getEvChargeSwitchVerifierBuilder() {
4203         return VehiclePropertyVerifier.newBuilder(
4204                         VehiclePropertyIds.EV_CHARGE_SWITCH,
4205                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE,
4206                         VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
4207                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
4208                         Boolean.class)
4209                 .addReadPermission(Car.PERMISSION_ENERGY)
4210                 .addReadPermission(Car.PERMISSION_CONTROL_CAR_ENERGY)
4211                 .addWritePermission(Car.PERMISSION_CONTROL_CAR_ENERGY);
4212     }
4213 
4214     private static VehiclePropertyVerifier.Builder<Integer>
4215             getEvChargeTimeRemainingVerifierBuilder() {
4216         return VehiclePropertyVerifier.newBuilder(
4217                         VehiclePropertyIds.EV_CHARGE_TIME_REMAINING,
4218                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ,
4219                         VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
4220                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_CONTINUOUS,
4221                         Integer.class)
4222                 .setCarPropertyValueVerifier(
4223                         (verifierContext, carPropertyConfig, propertyId, areaId, timestampNanos,
4224                          evChargeTimeRemaining) ->
4225                                 assertWithMessage(
4226                                         "EV_CHARGE_TIME_REMAINING Integer value"
4227                                                 + " must be greater than or equal 0")
4228                                         .that(evChargeTimeRemaining)
4229                                         .isAtLeast(0))
4230                 .addReadPermission(Car.PERMISSION_ENERGY);
4231     }
4232 
4233     private static VehiclePropertyVerifier.Builder<Integer>
4234             getEvRegenerativeBrakingStateVerifierBuilder() {
4235         return VehiclePropertyVerifier.newBuilder(
4236                         VehiclePropertyIds.EV_REGENERATIVE_BRAKING_STATE,
4237                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ,
4238                         VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
4239                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
4240                         Integer.class)
4241                 .setAllPossibleEnumValues(
4242                         ImmutableSet.of(
4243                                 EvRegenerativeBrakingState.STATE_UNKNOWN,
4244                                 EvRegenerativeBrakingState.STATE_DISABLED,
4245                                 EvRegenerativeBrakingState.STATE_PARTIALLY_ENABLED,
4246                                 EvRegenerativeBrakingState.STATE_FULLY_ENABLED))
4247                 .addReadPermission(Car.PERMISSION_ENERGY);
4248     }
4249 
4250     private static VehiclePropertyVerifier.Builder<Float>
4251             getPerfRearSteeringAngleVerifierBuilder() {
4252         return VehiclePropertyVerifier.newBuilder(
4253                         VehiclePropertyIds.PERF_REAR_STEERING_ANGLE,
4254                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ,
4255                         VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
4256                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_CONTINUOUS,
4257                         Float.class)
4258                 .addReadPermission(Car.PERMISSION_READ_STEERING_STATE);
4259     }
4260 
4261 
4262     private static VehiclePropertyVerifier.Builder<Float> getEngineCoolantTempVerifierBuilder() {
4263         return VehiclePropertyVerifier.newBuilder(
4264                         VehiclePropertyIds.ENGINE_COOLANT_TEMP,
4265                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ,
4266                         VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
4267                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_CONTINUOUS,
4268                         Float.class)
4269                 .addReadPermission(Car.PERMISSION_CAR_ENGINE_DETAILED);
4270     }
4271 
4272 
4273     private static VehiclePropertyVerifier.Builder<Integer> getEngineOilLevelVerifierBuilder() {
4274         return VehiclePropertyVerifier.newBuilder(
4275                         VehiclePropertyIds.ENGINE_OIL_LEVEL,
4276                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ,
4277                         VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
4278                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
4279                         Integer.class)
4280                 .setAllPossibleEnumValues(VEHICLE_OIL_LEVELS)
4281                 .addReadPermission(Car.PERMISSION_CAR_ENGINE_DETAILED);
4282     }
4283 
4284     private static VehiclePropertyVerifier.Builder<Float> getEngineOilTempVerifierBuilder() {
4285         return VehiclePropertyVerifier.newBuilder(
4286                         VehiclePropertyIds.ENGINE_OIL_TEMP,
4287                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ,
4288                         VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
4289                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_CONTINUOUS,
4290                         Float.class)
4291                 .addReadPermission(Car.PERMISSION_CAR_ENGINE_DETAILED);
4292     }
4293 
4294     private static VehiclePropertyVerifier.Builder<Float> getEngineRpmVerifierBuilder() {
4295         return VehiclePropertyVerifier.newBuilder(
4296                         VehiclePropertyIds.ENGINE_RPM,
4297                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ,
4298                         VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
4299                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_CONTINUOUS,
4300                         Float.class)
4301                 .setCarPropertyValueVerifier(
4302                         (verifierContext, carPropertyConfig, propertyId, areaId, timestampNanos,
4303                                 engineRpm) ->
4304                                 assertWithMessage(
4305                                         "ENGINE_RPM Float value must be greater than or"
4306                                                 + " equal 0")
4307                                         .that(engineRpm)
4308                                         .isAtLeast(0))
4309                 .addReadPermission(Car.PERMISSION_CAR_ENGINE_DETAILED);
4310     }
4311 
4312     private static VehiclePropertyVerifier.Builder<Boolean>
4313             getEngineIdleAutoStopEnabledVerifierBuilder() {
4314         return VehiclePropertyVerifier.newBuilder(
4315                         VehiclePropertyIds.ENGINE_IDLE_AUTO_STOP_ENABLED,
4316                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE,
4317                         VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
4318                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
4319                         Boolean.class)
4320                 .addReadPermission(Car.PERMISSION_CAR_ENGINE_DETAILED)
4321                 .addWritePermission(Car.PERMISSION_CAR_ENGINE_DETAILED);
4322     }
4323 
4324     private static VehiclePropertyVerifier.Builder<Integer> getImpactDetectedVerifierBuilder() {
4325         return VehiclePropertyVerifier.newBuilder(
4326                         VehiclePropertyIds.IMPACT_DETECTED,
4327                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ,
4328                         VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
4329                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
4330                         Integer.class)
4331                 .setAllPossibleEnumValues(IMPACT_SENSOR_LOCATIONS)
4332                 .setBitMapEnumEnabled(true)
4333                 .addReadPermission(Car.PERMISSION_READ_IMPACT_SENSORS);
4334     }
4335 
4336     private static VehiclePropertyVerifier.Builder<Float> getPerfOdometerVerifierBuilder() {
4337         return VehiclePropertyVerifier.newBuilder(
4338                         VehiclePropertyIds.PERF_ODOMETER,
4339                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ,
4340                         VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
4341                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_CONTINUOUS,
4342                         Float.class)
4343                 .setCarPropertyValueVerifier(
4344                         (verifierContext, carPropertyConfig, propertyId, areaId, timestampNanos,
4345                                 perfOdometer) ->
4346                                 assertWithMessage(
4347                                         "PERF_ODOMETER Float value must be greater than or"
4348                                                 + " equal 0")
4349                                         .that(perfOdometer)
4350                                         .isAtLeast(0))
4351                 .addReadPermission(Car.PERMISSION_MILEAGE);
4352     }
4353 
4354     private static VehiclePropertyVerifier.Builder<Integer> getTurnSignalStateVerifierBuilder() {
4355         return VehiclePropertyVerifier.newBuilder(
4356                         VehiclePropertyIds.TURN_SIGNAL_STATE,
4357                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ,
4358                         VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
4359                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
4360                         Integer.class)
4361                 .setAllPossibleEnumValues(TURN_SIGNAL_STATES)
4362                 .addReadPermission(Car.PERMISSION_EXTERIOR_LIGHTS);
4363     }
4364 
4365     private static VehiclePropertyVerifier.Builder<Integer> getHeadlightsStateVerifierBuilder() {
4366         return VehiclePropertyVerifier.newBuilder(
4367                         VehiclePropertyIds.HEADLIGHTS_STATE,
4368                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ,
4369                         VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
4370                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
4371                         Integer.class)
4372                 .setAllPossibleEnumValues(VEHICLE_LIGHT_STATES)
4373                 .addReadPermission(Car.PERMISSION_EXTERIOR_LIGHTS);
4374     }
4375 
4376     private static VehiclePropertyVerifier.Builder<Integer>
4377             getHighBeamLightsStateVerifierBuilder() {
4378         return VehiclePropertyVerifier.newBuilder(
4379                         VehiclePropertyIds.HIGH_BEAM_LIGHTS_STATE,
4380                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ,
4381                         VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
4382                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
4383                         Integer.class)
4384                 .setAllPossibleEnumValues(VEHICLE_LIGHT_STATES)
4385                 .addReadPermission(Car.PERMISSION_EXTERIOR_LIGHTS);
4386     }
4387 
4388     private static VehiclePropertyVerifier.Builder<Integer> getFogLightsStateVerifierBuilder() {
4389         return VehiclePropertyVerifier.newBuilder(
4390                         VehiclePropertyIds.FOG_LIGHTS_STATE,
4391                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ,
4392                         VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
4393                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
4394                         Integer.class)
4395                 .setAllPossibleEnumValues(VEHICLE_LIGHT_STATES)
4396                 .setCarPropertyValueVerifier(
4397                         (verifierContext, carPropertyConfig, propertyId, areaId, timestampNanos,
4398                                 fogLightsState) -> {
4399                             assertWithMessage(
4400                                             "FRONT_FOG_LIGHTS_STATE must not be implemented"
4401                                                     + "when FOG_LIGHTS_STATE is implemented")
4402                                     .that(verifierContext.getCarPropertyManager()
4403                                             .getCarPropertyConfig(
4404                                                     VehiclePropertyIds.FRONT_FOG_LIGHTS_STATE))
4405                                     .isNull();
4406 
4407                             assertWithMessage(
4408                                             "REAR_FOG_LIGHTS_STATE must not be implemented"
4409                                                     + "when FOG_LIGHTS_STATE is implemented")
4410                                     .that(verifierContext.getCarPropertyManager()
4411                                             .getCarPropertyConfig(
4412                                                     VehiclePropertyIds.REAR_FOG_LIGHTS_STATE))
4413                                     .isNull();
4414                         })
4415                 .addReadPermission(Car.PERMISSION_EXTERIOR_LIGHTS);
4416     }
4417 
4418     private static VehiclePropertyVerifier.Builder<Integer> getHazardLightsStateVerifierBuilder() {
4419         return VehiclePropertyVerifier.newBuilder(
4420                         VehiclePropertyIds.HAZARD_LIGHTS_STATE,
4421                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ,
4422                         VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
4423                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
4424                         Integer.class)
4425                 .setAllPossibleEnumValues(VEHICLE_LIGHT_STATES)
4426                 .addReadPermission(Car.PERMISSION_EXTERIOR_LIGHTS);
4427     }
4428 
4429     private static VehiclePropertyVerifier.Builder<Integer>
4430             getFrontFogLightsStateVerifierBuilder() {
4431         return VehiclePropertyVerifier.newBuilder(
4432                         VehiclePropertyIds.FRONT_FOG_LIGHTS_STATE,
4433                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ,
4434                         VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
4435                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
4436                         Integer.class)
4437                 .setAllPossibleEnumValues(VEHICLE_LIGHT_STATES)
4438                 .setCarPropertyValueVerifier(
4439                         (verifierContext, carPropertyConfig, propertyId, areaId, timestampNanos,
4440                                 frontFogLightsState) -> {
4441                             assertWithMessage(
4442                                             "FOG_LIGHTS_STATE must not be implemented"
4443                                                     + "when FRONT_FOG_LIGHTS_STATE is implemented")
4444                                     .that(verifierContext.getCarPropertyManager()
4445                                             .getCarPropertyConfig(
4446                                                     VehiclePropertyIds.FOG_LIGHTS_STATE))
4447                                     .isNull();
4448                         })
4449                 .addReadPermission(Car.PERMISSION_EXTERIOR_LIGHTS);
4450     }
4451 
4452     private static VehiclePropertyVerifier.Builder<Integer> getRearFogLightsStateVerifierBuilder() {
4453         return VehiclePropertyVerifier.newBuilder(
4454                         VehiclePropertyIds.REAR_FOG_LIGHTS_STATE,
4455                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ,
4456                         VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
4457                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
4458                         Integer.class)
4459                 .setAllPossibleEnumValues(VEHICLE_LIGHT_STATES)
4460                 .setCarPropertyValueVerifier(
4461                         (verifierContext, carPropertyConfig, propertyId, areaId, timestampNanos,
4462                                 rearFogLightsState) -> {
4463                             assertWithMessage(
4464                                             "FOG_LIGHTS_STATE must not be implemented"
4465                                                     + "when REAR_FOG_LIGHTS_STATE is implemented")
4466                                     .that(verifierContext.getCarPropertyManager()
4467                                             .getCarPropertyConfig(
4468                                                     VehiclePropertyIds.FOG_LIGHTS_STATE))
4469                                     .isNull();
4470                         })
4471                 .addReadPermission(Car.PERMISSION_EXTERIOR_LIGHTS);
4472     }
4473 
4474     private static VehiclePropertyVerifier.Builder<Integer> getCabinLightsStateVerifierBuilder() {
4475         return VehiclePropertyVerifier.newBuilder(
4476                         VehiclePropertyIds.CABIN_LIGHTS_STATE,
4477                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ,
4478                         VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
4479                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
4480                         Integer.class)
4481                 .setAllPossibleEnumValues(VEHICLE_LIGHT_STATES)
4482                 .addReadPermission(Car.PERMISSION_READ_INTERIOR_LIGHTS);
4483     }
4484 
4485     private static VehiclePropertyVerifier.Builder<Integer> getReadingLightsStateVerifierBuilder() {
4486         return VehiclePropertyVerifier.newBuilder(
4487                         VehiclePropertyIds.READING_LIGHTS_STATE,
4488                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ,
4489                         VehicleAreaType.VEHICLE_AREA_TYPE_SEAT,  // Note: Different area type
4490                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
4491                         Integer.class)
4492                 .setAllPossibleEnumValues(VEHICLE_LIGHT_STATES)
4493                 .addReadPermission(Car.PERMISSION_READ_INTERIOR_LIGHTS);
4494     }
4495 
4496     private static VehiclePropertyVerifier.Builder<Integer>
4497             getSteeringWheelLightsStateVerifierBuilder() {
4498         return VehiclePropertyVerifier.newBuilder(
4499                         VehiclePropertyIds.STEERING_WHEEL_LIGHTS_STATE,
4500                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ,
4501                         VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
4502                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
4503                         Integer.class)
4504                 .setAllPossibleEnumValues(VEHICLE_LIGHT_STATES)
4505                 .addReadPermission(Car.PERMISSION_READ_INTERIOR_LIGHTS);
4506     }
4507 
4508     private static VehiclePropertyVerifier.Builder<Integer> getVehicleCurbWeightVerifierBuilder() {
4509         return VehiclePropertyVerifier.newBuilder(
4510                         VehiclePropertyIds.VEHICLE_CURB_WEIGHT,
4511                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ,
4512                         VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
4513                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_STATIC,
4514                         Integer.class)
4515                 .setConfigArrayVerifier(
4516                         (verifierContext, configArray) -> {
4517                             assertWithMessage(
4518                                     "VEHICLE_CURB_WEIGHT configArray must contain the gross"
4519                                             + " weight in kilograms")
4520                                     .that(configArray)
4521                                     .hasSize(1);
4522                             assertWithMessage(
4523                                     "VEHICLE_CURB_WEIGHT configArray[0] must contain the"
4524                                             + " gross weight in kilograms and be greater than"
4525                                             + " zero")
4526                                     .that(configArray.get(0))
4527                                     .isGreaterThan(0);
4528                         })
4529                 .setCarPropertyValueVerifier(
4530                         (verifierContext, carPropertyConfig, propertyId, areaId, timestampNanos,
4531                                 curbWeightKg) -> {
4532                             Integer grossWeightKg = carPropertyConfig.getConfigArray().get(0);
4533 
4534                             assertWithMessage("VEHICLE_CURB_WEIGHT must be greater than zero")
4535                                     .that(curbWeightKg)
4536                                     .isGreaterThan(0);
4537                             assertWithMessage(
4538                                     "VEHICLE_CURB_WEIGHT must be less than the gross"
4539                                             + " weight")
4540                                     .that(curbWeightKg)
4541                                     .isLessThan(grossWeightKg);
4542                         })
4543                 .addReadPermission(Car.PERMISSION_PRIVILEGED_CAR_INFO);
4544     }
4545 
4546     private static VehiclePropertyVerifier.Builder<Integer> getHeadlightsSwitchVerifierBuilder() {
4547         return VehiclePropertyVerifier.newBuilder(
4548                         VehiclePropertyIds.HEADLIGHTS_SWITCH,
4549                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE,
4550                         VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
4551                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
4552                         Integer.class)
4553                 .setAllPossibleEnumValues(VEHICLE_LIGHT_SWITCHES)
4554                 .addReadPermission(Car.PERMISSION_CONTROL_EXTERIOR_LIGHTS)
4555                 .addWritePermission(Car.PERMISSION_CONTROL_EXTERIOR_LIGHTS);
4556     }
4557 
4558     private static VehiclePropertyVerifier.Builder<Integer> getTrailerPresentVerifierBuilder() {
4559         return VehiclePropertyVerifier.newBuilder(
4560                         VehiclePropertyIds.TRAILER_PRESENT,
4561                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ,
4562                         VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
4563                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
4564                         Integer.class)
4565                 .setAllPossibleEnumValues(TRAILER_STATES)
4566                 .addReadPermission(Car.PERMISSION_PRIVILEGED_CAR_INFO);
4567     }
4568 
4569     private static VehiclePropertyVerifier.Builder<Integer>
4570             getHighBeamLightsSwitchVerifierBuilder() {
4571         return VehiclePropertyVerifier.newBuilder(
4572                         VehiclePropertyIds.HIGH_BEAM_LIGHTS_SWITCH,
4573                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE,
4574                         VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
4575                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
4576                         Integer.class)
4577                 .setAllPossibleEnumValues(VEHICLE_LIGHT_SWITCHES)
4578                 .addReadPermission(Car.PERMISSION_CONTROL_EXTERIOR_LIGHTS)
4579                 .addWritePermission(Car.PERMISSION_CONTROL_EXTERIOR_LIGHTS);
4580     }
4581 
4582     private static VehiclePropertyVerifier.Builder<Integer> getFogLightsSwitchVerifierBuilder() {
4583         return VehiclePropertyVerifier.newBuilder(
4584                         VehiclePropertyIds.FOG_LIGHTS_SWITCH,
4585                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE,
4586                         VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
4587                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
4588                         Integer.class)
4589                 .setAllPossibleEnumValues(VEHICLE_LIGHT_SWITCHES)
4590                 .setCarPropertyValueVerifier(
4591                         (verifierContext, carPropertyConfig, propertyId, areaId, timestampNanos,
4592                                 fogLightsSwitch) -> {
4593                             assertWithMessage(
4594                                             "FRONT_FOG_LIGHTS_SWITCH must not be implemented"
4595                                                     + "when FOG_LIGHTS_SWITCH is implemented")
4596                                     .that(verifierContext.getCarPropertyManager()
4597                                             .getCarPropertyConfig(
4598                                                     VehiclePropertyIds.FRONT_FOG_LIGHTS_SWITCH))
4599                                     .isNull();
4600 
4601                             assertWithMessage(
4602                                             "REAR_FOG_LIGHTS_SWITCH must not be implemented"
4603                                                     + "when FOG_LIGHTS_SWITCH is implemented")
4604                                     .that(verifierContext.getCarPropertyManager()
4605                                             .getCarPropertyConfig(
4606                                                     VehiclePropertyIds.REAR_FOG_LIGHTS_SWITCH))
4607                                     .isNull();
4608                         })
4609                 .addReadPermission(Car.PERMISSION_CONTROL_EXTERIOR_LIGHTS)
4610                 .addWritePermission(Car.PERMISSION_CONTROL_EXTERIOR_LIGHTS);
4611     }
4612 
4613     private static VehiclePropertyVerifier.Builder<Integer> getHazardLightsSwitchVerifierBuilder() {
4614         return VehiclePropertyVerifier.newBuilder(
4615                         VehiclePropertyIds.HAZARD_LIGHTS_SWITCH,
4616                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE,
4617                         VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
4618                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
4619                         Integer.class)
4620                 .setAllPossibleEnumValues(VEHICLE_LIGHT_SWITCHES)
4621                 .addReadPermission(Car.PERMISSION_CONTROL_EXTERIOR_LIGHTS)
4622                 .addWritePermission(Car.PERMISSION_CONTROL_EXTERIOR_LIGHTS);
4623     }
4624 
4625     private static VehiclePropertyVerifier.Builder<Integer>
4626             getFrontFogLightsSwitchVerifierBuilder() {
4627         return VehiclePropertyVerifier.newBuilder(
4628                         VehiclePropertyIds.FRONT_FOG_LIGHTS_SWITCH,
4629                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE,
4630                         VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
4631                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
4632                         Integer.class)
4633                 .setAllPossibleEnumValues(VEHICLE_LIGHT_SWITCHES)
4634                 .setCarPropertyValueVerifier(
4635                         (verifierContext, carPropertyConfig, propertyId, areaId, timestampNanos,
4636                                 frontFogLightsSwitch) -> {
4637                             assertWithMessage(
4638                                             "FOG_LIGHTS_SWITCH must not be implemented"
4639                                                     + "when FRONT_FOG_LIGHTS_SWITCH is implemented")
4640                                     .that(verifierContext.getCarPropertyManager()
4641                                             .getCarPropertyConfig(
4642                                                     VehiclePropertyIds.FOG_LIGHTS_SWITCH))
4643                                     .isNull();
4644                         })
4645                 .addReadPermission(Car.PERMISSION_CONTROL_EXTERIOR_LIGHTS)
4646                 .addWritePermission(Car.PERMISSION_CONTROL_EXTERIOR_LIGHTS);
4647     }
4648 
4649     private static VehiclePropertyVerifier.Builder<Integer>
4650             getRearFogLightsSwitchVerifierBuilder() {
4651         return VehiclePropertyVerifier.newBuilder(
4652                         VehiclePropertyIds.REAR_FOG_LIGHTS_SWITCH,
4653                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE,
4654                         VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
4655                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
4656                         Integer.class)
4657                 .setAllPossibleEnumValues(VEHICLE_LIGHT_SWITCHES)
4658                 .setCarPropertyValueVerifier(
4659                         (verifierContext, carPropertyConfig, propertyId, areaId, timestampNanos,
4660                                 rearFogLightsSwitch) -> {
4661                             assertWithMessage(
4662                                             "FOG_LIGHTS_SWITCH must not be implemented"
4663                                                     + "when REAR_FOG_LIGHTS_SWITCH is implemented")
4664                                     .that(verifierContext.getCarPropertyManager()
4665                                             .getCarPropertyConfig(
4666                                                     VehiclePropertyIds.FOG_LIGHTS_SWITCH))
4667                                     .isNull();
4668                         })
4669                 .addReadPermission(Car.PERMISSION_CONTROL_EXTERIOR_LIGHTS)
4670                 .addWritePermission(Car.PERMISSION_CONTROL_EXTERIOR_LIGHTS);
4671     }
4672 
4673     private static VehiclePropertyVerifier.Builder<Integer> getCabinLightsSwitchVerifierBuilder() {
4674         return VehiclePropertyVerifier.newBuilder(
4675                         VehiclePropertyIds.CABIN_LIGHTS_SWITCH,
4676                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE,
4677                         VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
4678                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
4679                         Integer.class)
4680                 .setAllPossibleEnumValues(VEHICLE_LIGHT_SWITCHES)
4681                 .addReadPermission(Car.PERMISSION_CONTROL_INTERIOR_LIGHTS)
4682                 .addWritePermission(Car.PERMISSION_CONTROL_INTERIOR_LIGHTS);
4683     }
4684 
4685     private static VehiclePropertyVerifier.Builder<Integer>
4686             getReadingLightsSwitchVerifierBuilder() {
4687         return VehiclePropertyVerifier.newBuilder(
4688                         VehiclePropertyIds.READING_LIGHTS_SWITCH,
4689                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE,
4690                         VehicleAreaType.VEHICLE_AREA_TYPE_SEAT,
4691                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
4692                         Integer.class)
4693                 .setAllPossibleEnumValues(VEHICLE_LIGHT_SWITCHES)
4694                 .addReadPermission(Car.PERMISSION_CONTROL_INTERIOR_LIGHTS)
4695                 .addWritePermission(Car.PERMISSION_CONTROL_INTERIOR_LIGHTS);
4696     }
4697 
4698     private static VehiclePropertyVerifier.Builder<Integer>
4699             getSteeringWheelLightsSwitchVerifierBuilder() {
4700         return VehiclePropertyVerifier.newBuilder(
4701                         VehiclePropertyIds.STEERING_WHEEL_LIGHTS_SWITCH,
4702                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE,
4703                         VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
4704                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
4705                         Integer.class)
4706                 .setAllPossibleEnumValues(VEHICLE_LIGHT_SWITCHES)
4707                 .addReadPermission(Car.PERMISSION_CONTROL_INTERIOR_LIGHTS)
4708                 .addWritePermission(Car.PERMISSION_CONTROL_INTERIOR_LIGHTS);
4709     }
4710 
4711     private static VehiclePropertyVerifier.Builder<Integer> getSeatMemorySelectVerifierBuilder() {
4712         return VehiclePropertyVerifier.newBuilder(
4713                         VehiclePropertyIds.SEAT_MEMORY_SELECT,
4714                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_WRITE,
4715                         VehicleAreaType.VEHICLE_AREA_TYPE_SEAT,
4716                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
4717                         Integer.class)
4718                 .requireMinMaxValues()
4719                 .requireMinValuesToBeZero()
4720                 .setCarPropertyConfigVerifier(
4721                         (verifierContext, carPropertyConfig) -> {
4722                             int[] areaIds = carPropertyConfig.getAreaIds();
4723                             CarPropertyConfig<?> seatMemorySetCarPropertyConfig =
4724                                     verifierContext.getCarPropertyManager().getCarPropertyConfig(
4725                                             VehiclePropertyIds.SEAT_MEMORY_SET);
4726 
4727                             assertWithMessage(
4728                                             "SEAT_MEMORY_SET must be implemented if "
4729                                                     + "SEAT_MEMORY_SELECT is implemented")
4730                                     .that(seatMemorySetCarPropertyConfig)
4731                                     .isNotNull();
4732 
4733                             assertWithMessage(
4734                                             "SEAT_MEMORY_SELECT area IDs must match the area IDs of"
4735                                                 + " SEAT_MEMORY_SET")
4736                                     .that(
4737                                             Arrays.stream(areaIds)
4738                                                     .boxed()
4739                                                     .collect(Collectors.toList()))
4740                                     .containsExactlyElementsIn(
4741                                             Arrays.stream(
4742                                                             seatMemorySetCarPropertyConfig
4743                                                                     .getAreaIds())
4744                                                     .boxed()
4745                                                     .collect(Collectors.toList()));
4746 
4747                             for (int areaId : areaIds) {
4748                                 Integer seatMemorySetAreaIdMaxValue =
4749                                         (Integer)
4750                                                 seatMemorySetCarPropertyConfig.getMaxValue(areaId);
4751                                 assertWithMessage(
4752                                                 "SEAT_MEMORY_SET - area ID: "
4753                                                         + areaId
4754                                                         + " must have max value defined")
4755                                         .that(seatMemorySetAreaIdMaxValue)
4756                                         .isNotNull();
4757                                 assertWithMessage(
4758                                                 "SEAT_MEMORY_SELECT - area ID: "
4759                                                         + areaId
4760                                                         + "'s max value must be equal to"
4761                                                         + " SEAT_MEMORY_SET's max value under the"
4762                                                         + " same area ID")
4763                                         .that(seatMemorySetAreaIdMaxValue)
4764                                         .isEqualTo(carPropertyConfig.getMaxValue(areaId));
4765                             }
4766                         })
4767                 .addWritePermission(Car.PERMISSION_CONTROL_CAR_SEATS);
4768     }
4769 
4770     private static VehiclePropertyVerifier.Builder<Integer> getSeatMemorySetVerifierBuilder() {
4771         return VehiclePropertyVerifier.newBuilder(
4772                         VehiclePropertyIds.SEAT_MEMORY_SET,
4773                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_WRITE,
4774                         VehicleAreaType.VEHICLE_AREA_TYPE_SEAT,
4775                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
4776                         Integer.class)
4777                 .requireMinMaxValues()
4778                 .requireMinValuesToBeZero()
4779                 .setCarPropertyConfigVerifier(
4780                         (verifierContext, carPropertyConfig) -> {
4781                             int[] areaIds = carPropertyConfig.getAreaIds();
4782                             CarPropertyConfig<?> seatMemorySelectCarPropertyConfig =
4783                                     verifierContext.getCarPropertyManager().getCarPropertyConfig(
4784                                             VehiclePropertyIds.SEAT_MEMORY_SELECT);
4785 
4786                             assertWithMessage(
4787                                             "SEAT_MEMORY_SELECT must be implemented if "
4788                                                     + "SEAT_MEMORY_SET is implemented")
4789                                     .that(seatMemorySelectCarPropertyConfig)
4790                                     .isNotNull();
4791 
4792                             assertWithMessage(
4793                                             "SEAT_MEMORY_SET area IDs must match the area IDs of "
4794                                                     + "SEAT_MEMORY_SELECT")
4795                                     .that(
4796                                             Arrays.stream(areaIds)
4797                                                     .boxed()
4798                                                     .collect(Collectors.toList()))
4799                                     .containsExactlyElementsIn(
4800                                             Arrays.stream(
4801                                                             seatMemorySelectCarPropertyConfig
4802                                                                     .getAreaIds())
4803                                                     .boxed()
4804                                                     .collect(Collectors.toList()));
4805 
4806                             for (int areaId : areaIds) {
4807                                 Integer seatMemorySelectAreaIdMaxValue =
4808                                         (Integer)
4809                                                 seatMemorySelectCarPropertyConfig.getMaxValue(
4810                                                         areaId);
4811                                 assertWithMessage(
4812                                                 "SEAT_MEMORY_SELECT - area ID: "
4813                                                         + areaId
4814                                                         + " must have max value defined")
4815                                         .that(seatMemorySelectAreaIdMaxValue)
4816                                         .isNotNull();
4817                                 assertWithMessage(
4818                                                 "SEAT_MEMORY_SET - area ID: "
4819                                                         + areaId
4820                                                         + "'s max value must be equal to"
4821                                                         + " SEAT_MEMORY_SELECT's max value under"
4822                                                         + " the same area ID")
4823                                         .that(seatMemorySelectAreaIdMaxValue)
4824                                         .isEqualTo(carPropertyConfig.getMaxValue(areaId));
4825                             }
4826                         })
4827                 .addWritePermission(Car.PERMISSION_CONTROL_CAR_SEATS);
4828     }
4829 
4830     private static VehiclePropertyVerifier.Builder<Boolean> getSeatBeltBuckledVerifierBuilder() {
4831         return VehiclePropertyVerifier.newBuilder(
4832                         VehiclePropertyIds.SEAT_BELT_BUCKLED,
4833                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE,
4834                         VehicleAreaType.VEHICLE_AREA_TYPE_SEAT,
4835                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
4836                         Boolean.class)
4837                 .addReadPermission(Car.PERMISSION_CONTROL_CAR_SEATS)
4838                 .addWritePermission(Car.PERMISSION_CONTROL_CAR_SEATS);
4839     }
4840 
4841     private static VehiclePropertyVerifier.Builder<Integer> getSeatBeltHeightPosVerifierBuilder() {
4842         return VehiclePropertyVerifier.newBuilder(
4843                         VehiclePropertyIds.SEAT_BELT_HEIGHT_POS,
4844                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE,
4845                         VehicleAreaType.VEHICLE_AREA_TYPE_SEAT,
4846                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
4847                         Integer.class)
4848                 .requireMinMaxValues()
4849                 .addReadPermission(Car.PERMISSION_CONTROL_CAR_SEATS)
4850                 .addWritePermission(Car.PERMISSION_CONTROL_CAR_SEATS);
4851     }
4852 
4853     private static VehiclePropertyVerifier.Builder<Integer> getSeatBeltHeightMoveVerifierBuilder() {
4854         return VehiclePropertyVerifier.newBuilder(
4855                         VehiclePropertyIds.SEAT_BELT_HEIGHT_MOVE,
4856                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE,
4857                         VehicleAreaType.VEHICLE_AREA_TYPE_SEAT,
4858                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
4859                         Integer.class)
4860                 .requireMinMaxValues()
4861                 .requireZeroToBeContainedInMinMaxRanges()
4862                 .addReadPermission(Car.PERMISSION_CONTROL_CAR_SEATS)
4863                 .addWritePermission(Car.PERMISSION_CONTROL_CAR_SEATS);
4864     }
4865 
4866     private static VehiclePropertyVerifier.Builder<Integer> getSeatForeAftPosVerifierBuilder() {
4867         return VehiclePropertyVerifier.newBuilder(
4868                         VehiclePropertyIds.SEAT_FORE_AFT_POS,
4869                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE,
4870                         VehicleAreaType.VEHICLE_AREA_TYPE_SEAT,
4871                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
4872                         Integer.class)
4873                 .requireMinMaxValues()
4874                 .addReadPermission(Car.PERMISSION_CONTROL_CAR_SEATS)
4875                 .addWritePermission(Car.PERMISSION_CONTROL_CAR_SEATS);
4876     }
4877 
4878     private static VehiclePropertyVerifier.Builder<Integer>
4879             getSeatBackrestAngle1PosVerifierBuilder() {
4880         return VehiclePropertyVerifier.newBuilder(
4881                         VehiclePropertyIds.SEAT_BACKREST_ANGLE_1_POS,
4882                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE,
4883                         VehicleAreaType.VEHICLE_AREA_TYPE_SEAT,
4884                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
4885                         Integer.class)
4886                 .requireMinMaxValues()
4887                 .addReadPermission(Car.PERMISSION_CONTROL_CAR_SEATS)
4888                 .addWritePermission(Car.PERMISSION_CONTROL_CAR_SEATS);
4889     }
4890 
4891     private static VehiclePropertyVerifier.Builder<Integer> getSeatForeAftMoveVerifierBuilder() {
4892         return VehiclePropertyVerifier.newBuilder(
4893                         VehiclePropertyIds.SEAT_FORE_AFT_MOVE,
4894                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE,
4895                         VehicleAreaType.VEHICLE_AREA_TYPE_SEAT,
4896                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
4897                         Integer.class)
4898                 .requireMinMaxValues()
4899                 .requireZeroToBeContainedInMinMaxRanges()
4900                 .addReadPermission(Car.PERMISSION_CONTROL_CAR_SEATS)
4901                 .addWritePermission(Car.PERMISSION_CONTROL_CAR_SEATS);
4902     }
4903 
4904     private static VehiclePropertyVerifier.Builder<Integer>
4905             getSeatBackrestAngle1MoveVerifierBuilder() {
4906         return VehiclePropertyVerifier.newBuilder(
4907                         VehiclePropertyIds.SEAT_BACKREST_ANGLE_1_MOVE,
4908                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE,
4909                         VehicleAreaType.VEHICLE_AREA_TYPE_SEAT,
4910                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
4911                         Integer.class)
4912                 .requireMinMaxValues()
4913                 .requireZeroToBeContainedInMinMaxRanges()
4914                 .addReadPermission(Car.PERMISSION_CONTROL_CAR_SEATS)
4915                 .addWritePermission(Car.PERMISSION_CONTROL_CAR_SEATS);
4916     }
4917 
4918     private static VehiclePropertyVerifier.Builder<Integer>
4919             getSeatBackrestAngle2PosVerifierBuilder() {
4920         return VehiclePropertyVerifier.newBuilder(
4921                         VehiclePropertyIds.SEAT_BACKREST_ANGLE_2_POS,
4922                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE,
4923                         VehicleAreaType.VEHICLE_AREA_TYPE_SEAT,
4924                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
4925                         Integer.class)
4926                 .requireMinMaxValues()
4927                 .addReadPermission(Car.PERMISSION_CONTROL_CAR_SEATS)
4928                 .addWritePermission(Car.PERMISSION_CONTROL_CAR_SEATS);
4929     }
4930 
4931     private static VehiclePropertyVerifier.Builder<Integer>
4932             getSeatBackrestAngle2MoveVerifierBuilder() {
4933         return VehiclePropertyVerifier.newBuilder(
4934                         VehiclePropertyIds.SEAT_BACKREST_ANGLE_2_MOVE,
4935                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE,
4936                         VehicleAreaType.VEHICLE_AREA_TYPE_SEAT,
4937                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
4938                         Integer.class)
4939                 .requireMinMaxValues()
4940                 .requireZeroToBeContainedInMinMaxRanges()
4941                 .addReadPermission(Car.PERMISSION_CONTROL_CAR_SEATS)
4942                 .addWritePermission(Car.PERMISSION_CONTROL_CAR_SEATS);
4943     }
4944 
4945     private static VehiclePropertyVerifier.Builder<Integer> getSeatHeightPosVerifierBuilder() {
4946         return VehiclePropertyVerifier.newBuilder(
4947                         VehiclePropertyIds.SEAT_HEIGHT_POS,
4948                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE,
4949                         VehicleAreaType.VEHICLE_AREA_TYPE_SEAT,
4950                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
4951                         Integer.class)
4952                 .requireMinMaxValues()
4953                 .addReadPermission(Car.PERMISSION_CONTROL_CAR_SEATS)
4954                 .addWritePermission(Car.PERMISSION_CONTROL_CAR_SEATS);
4955     }
4956 
4957     private static VehiclePropertyVerifier.Builder<Integer> getSeatHeightMoveVerifierBuilder() {
4958         return VehiclePropertyVerifier.newBuilder(
4959                         VehiclePropertyIds.SEAT_HEIGHT_MOVE,
4960                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE,
4961                         VehicleAreaType.VEHICLE_AREA_TYPE_SEAT,
4962                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
4963                         Integer.class)
4964                 .requireMinMaxValues()
4965                 .requireZeroToBeContainedInMinMaxRanges()
4966                 .addReadPermission(Car.PERMISSION_CONTROL_CAR_SEATS)
4967                 .addWritePermission(Car.PERMISSION_CONTROL_CAR_SEATS);
4968     }
4969 
4970     private static VehiclePropertyVerifier.Builder<Integer> getSeatDepthPosVerifierBuilder() {
4971         return VehiclePropertyVerifier.newBuilder(
4972                         VehiclePropertyIds.SEAT_DEPTH_POS,
4973                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE,
4974                         VehicleAreaType.VEHICLE_AREA_TYPE_SEAT,
4975                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
4976                         Integer.class)
4977                 .requireMinMaxValues()
4978                 .addReadPermission(Car.PERMISSION_CONTROL_CAR_SEATS)
4979                 .addWritePermission(Car.PERMISSION_CONTROL_CAR_SEATS);
4980     }
4981 
4982     private static VehiclePropertyVerifier.Builder<Integer> getSeatDepthMoveVerifierBuilder() {
4983         return VehiclePropertyVerifier.newBuilder(
4984                         VehiclePropertyIds.SEAT_DEPTH_MOVE,
4985                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE,
4986                         VehicleAreaType.VEHICLE_AREA_TYPE_SEAT,
4987                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
4988                         Integer.class)
4989                 .requireMinMaxValues()
4990                 .requireZeroToBeContainedInMinMaxRanges()
4991                 .addReadPermission(Car.PERMISSION_CONTROL_CAR_SEATS)
4992                 .addWritePermission(Car.PERMISSION_CONTROL_CAR_SEATS);
4993     }
4994 
4995     private static VehiclePropertyVerifier.Builder<Integer> getSeatTiltPosVerifierBuilder() {
4996         return VehiclePropertyVerifier.newBuilder(
4997                         VehiclePropertyIds.SEAT_TILT_POS,
4998                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE,
4999                         VehicleAreaType.VEHICLE_AREA_TYPE_SEAT,
5000                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
5001                         Integer.class)
5002                 .requireMinMaxValues()
5003                 .addReadPermission(Car.PERMISSION_CONTROL_CAR_SEATS)
5004                 .addWritePermission(Car.PERMISSION_CONTROL_CAR_SEATS);
5005     }
5006 
5007     private static VehiclePropertyVerifier.Builder<Integer> getSeatTiltMoveVerifierBuilder() {
5008         return VehiclePropertyVerifier.newBuilder(
5009                         VehiclePropertyIds.SEAT_TILT_MOVE,
5010                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE,
5011                         VehicleAreaType.VEHICLE_AREA_TYPE_SEAT,
5012                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
5013                         Integer.class)
5014                 .requireMinMaxValues()
5015                 .requireZeroToBeContainedInMinMaxRanges()
5016                 .addReadPermission(Car.PERMISSION_CONTROL_CAR_SEATS)
5017                 .addWritePermission(Car.PERMISSION_CONTROL_CAR_SEATS);
5018     }
5019 
5020     private static VehiclePropertyVerifier.Builder<Integer>
5021             getSeatLumbarForeAftPosVerifierBuilder() {
5022         return VehiclePropertyVerifier.newBuilder(
5023                         VehiclePropertyIds.SEAT_LUMBAR_FORE_AFT_POS,
5024                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE,
5025                         VehicleAreaType.VEHICLE_AREA_TYPE_SEAT,
5026                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
5027                         Integer.class)
5028                 .requireMinMaxValues()
5029                 .addReadPermission(Car.PERMISSION_CONTROL_CAR_SEATS)
5030                 .addWritePermission(Car.PERMISSION_CONTROL_CAR_SEATS);
5031     }
5032 
5033     private static VehiclePropertyVerifier.Builder<Integer>
5034             getSeatLumbarForeAftMoveVerifierBuilder() {
5035         return VehiclePropertyVerifier.newBuilder(
5036                         VehiclePropertyIds.SEAT_LUMBAR_FORE_AFT_MOVE,
5037                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE,
5038                         VehicleAreaType.VEHICLE_AREA_TYPE_SEAT,
5039                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
5040                         Integer.class)
5041                 .requireMinMaxValues()
5042                 .requireZeroToBeContainedInMinMaxRanges()
5043                 .addReadPermission(Car.PERMISSION_CONTROL_CAR_SEATS)
5044                 .addWritePermission(Car.PERMISSION_CONTROL_CAR_SEATS);
5045     }
5046 
5047     private static VehiclePropertyVerifier.Builder<Integer>
5048             getSeatLumbarSideSupportPosVerifierBuilder() {
5049         return VehiclePropertyVerifier.newBuilder(
5050                         VehiclePropertyIds.SEAT_LUMBAR_SIDE_SUPPORT_POS,
5051                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE,
5052                         VehicleAreaType.VEHICLE_AREA_TYPE_SEAT,
5053                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
5054                         Integer.class)
5055                 .requireMinMaxValues()
5056                 .addReadPermission(Car.PERMISSION_CONTROL_CAR_SEATS)
5057                 .addWritePermission(Car.PERMISSION_CONTROL_CAR_SEATS);
5058     }
5059 
5060     private static VehiclePropertyVerifier.Builder<Integer>
5061             getSeatLumbarSideSupportMoveVerifierBuilder() {
5062         return VehiclePropertyVerifier.newBuilder(
5063                         VehiclePropertyIds.SEAT_LUMBAR_SIDE_SUPPORT_MOVE,
5064                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE,
5065                         VehicleAreaType.VEHICLE_AREA_TYPE_SEAT,
5066                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
5067                         Integer.class)
5068                 .requireMinMaxValues()
5069                 .requireZeroToBeContainedInMinMaxRanges()
5070                 .addReadPermission(Car.PERMISSION_CONTROL_CAR_SEATS)
5071                 .addWritePermission(Car.PERMISSION_CONTROL_CAR_SEATS);
5072     }
5073 
5074     @Test
5075     public void testSeatHeadrestHeightPosMustNotBeImplemented() {
5076         runWithShellPermissionIdentity(
5077                 () -> {
5078                     assertWithMessage(
5079                                 "SEAT_HEADREST_HEIGHT_POS has been deprecated and should not be"
5080                                 + " implemented. Use SEAT_HEADREST_HEIGHT_POS_V2 instead.")
5081                         .that(
5082                                 mCarPropertyManager.getCarPropertyConfig(
5083                                         VehiclePropertyIds.SEAT_HEADREST_HEIGHT_POS))
5084                         .isNull();
5085                 },
5086                 Car.PERMISSION_CONTROL_CAR_SEATS);
5087     }
5088 
5089     private static VehiclePropertyVerifier.Builder<Integer>
5090             getSeatHeadrestHeightPosV2VerifierBuilder() {
5091         return VehiclePropertyVerifier.newBuilder(
5092                         VehiclePropertyIds.SEAT_HEADREST_HEIGHT_POS_V2,
5093                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE,
5094                         VehicleAreaType.VEHICLE_AREA_TYPE_SEAT,
5095                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
5096                         Integer.class)
5097                 .requireMinMaxValues()
5098                 .addReadPermission(Car.PERMISSION_CONTROL_CAR_SEATS)
5099                 .addWritePermission(Car.PERMISSION_CONTROL_CAR_SEATS);
5100     }
5101 
5102     private static VehiclePropertyVerifier.Builder<Integer>
5103             getSeatHeadrestHeightMoveVerifierBuilder() {
5104         return VehiclePropertyVerifier.newBuilder(
5105                         VehiclePropertyIds.SEAT_HEADREST_HEIGHT_MOVE,
5106                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE,
5107                         VehicleAreaType.VEHICLE_AREA_TYPE_SEAT,
5108                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
5109                         Integer.class)
5110                 .requireMinMaxValues()
5111                 .requireZeroToBeContainedInMinMaxRanges()
5112                 .addReadPermission(Car.PERMISSION_CONTROL_CAR_SEATS)
5113                 .addWritePermission(Car.PERMISSION_CONTROL_CAR_SEATS);
5114     }
5115 
5116     private static VehiclePropertyVerifier.Builder<Integer>
5117             getSeatHeadrestAnglePosVerifierBuilder() {
5118         return VehiclePropertyVerifier.newBuilder(
5119                         VehiclePropertyIds.SEAT_HEADREST_ANGLE_POS,
5120                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE,
5121                         VehicleAreaType.VEHICLE_AREA_TYPE_SEAT,
5122                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
5123                         Integer.class)
5124                 .requireMinMaxValues()
5125                 .addReadPermission(Car.PERMISSION_CONTROL_CAR_SEATS)
5126                 .addWritePermission(Car.PERMISSION_CONTROL_CAR_SEATS);
5127     }
5128 
5129     private static VehiclePropertyVerifier.Builder<Integer>
5130             getSeatHeadrestAngleMoveVerifierBuilder() {
5131         return VehiclePropertyVerifier.newBuilder(
5132                         VehiclePropertyIds.SEAT_HEADREST_ANGLE_MOVE,
5133                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE,
5134                         VehicleAreaType.VEHICLE_AREA_TYPE_SEAT,
5135                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
5136                         Integer.class)
5137                 .requireMinMaxValues()
5138                 .requireZeroToBeContainedInMinMaxRanges()
5139                 .addReadPermission(Car.PERMISSION_CONTROL_CAR_SEATS)
5140                 .addWritePermission(Car.PERMISSION_CONTROL_CAR_SEATS);
5141     }
5142 
5143     private static VehiclePropertyVerifier.Builder<Integer>
5144             getSeatHeadrestForeAftPosVerifierBuilder() {
5145         return VehiclePropertyVerifier.newBuilder(
5146                         VehiclePropertyIds.SEAT_HEADREST_FORE_AFT_POS,
5147                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE,
5148                         VehicleAreaType.VEHICLE_AREA_TYPE_SEAT,
5149                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
5150                         Integer.class)
5151                 .requireMinMaxValues()
5152                 .addReadPermission(Car.PERMISSION_CONTROL_CAR_SEATS)
5153                 .addWritePermission(Car.PERMISSION_CONTROL_CAR_SEATS);
5154     }
5155 
5156     private static VehiclePropertyVerifier.Builder<Integer>
5157             getSeatHeadrestForeAftMoveVerifierBuilder() {
5158         return VehiclePropertyVerifier.newBuilder(
5159                         VehiclePropertyIds.SEAT_HEADREST_FORE_AFT_MOVE,
5160                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE,
5161                         VehicleAreaType.VEHICLE_AREA_TYPE_SEAT,
5162                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
5163                         Integer.class)
5164                 .requireMinMaxValues()
5165                 .requireZeroToBeContainedInMinMaxRanges()
5166                 .addReadPermission(Car.PERMISSION_CONTROL_CAR_SEATS)
5167                 .addWritePermission(Car.PERMISSION_CONTROL_CAR_SEATS);
5168     }
5169 
5170     private static VehiclePropertyVerifier.Builder<Integer>
5171             getSeatFootwellLightsStateVerifierBuilder() {
5172         return VehiclePropertyVerifier.newBuilder(
5173                         VehiclePropertyIds.SEAT_FOOTWELL_LIGHTS_STATE,
5174                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ,
5175                         VehicleAreaType.VEHICLE_AREA_TYPE_SEAT,
5176                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
5177                         Integer.class)
5178                 .setAllPossibleEnumValues(VEHICLE_LIGHT_STATES)
5179                 .addReadPermission(Car.PERMISSION_READ_INTERIOR_LIGHTS);
5180     }
5181 
5182     private static VehiclePropertyVerifier.Builder<Integer>
5183             getSeatFootwellLightsSwitchVerifierBuilder() {
5184         return VehiclePropertyVerifier.newBuilder(
5185                         VehiclePropertyIds.SEAT_FOOTWELL_LIGHTS_SWITCH,
5186                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE,
5187                         VehicleAreaType.VEHICLE_AREA_TYPE_SEAT,
5188                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
5189                         Integer.class)
5190                 .setAllPossibleEnumValues(VEHICLE_LIGHT_SWITCHES)
5191                 .addReadPermission(Car.PERMISSION_CONTROL_INTERIOR_LIGHTS)
5192                 .addWritePermission(Car.PERMISSION_CONTROL_INTERIOR_LIGHTS);
5193     }
5194 
5195     private static VehiclePropertyVerifier.Builder<Boolean>
5196             getSeatEasyAccessEnabledVerifierBuilder() {
5197         return VehiclePropertyVerifier.newBuilder(
5198                         VehiclePropertyIds.SEAT_EASY_ACCESS_ENABLED,
5199                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE,
5200                         VehicleAreaType.VEHICLE_AREA_TYPE_SEAT,
5201                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
5202                         Boolean.class)
5203                 .addReadPermission(Car.PERMISSION_CONTROL_CAR_SEATS)
5204                 .addWritePermission(Car.PERMISSION_CONTROL_CAR_SEATS);
5205     }
5206 
5207     private static VehiclePropertyVerifier.Builder<Boolean>
5208             getSeatAirbagEnabledVerifierBuilder() {
5209         return VehiclePropertyVerifier.newBuilder(
5210                         VehiclePropertyIds.SEAT_AIRBAG_ENABLED,
5211                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE,
5212                         VehicleAreaType.VEHICLE_AREA_TYPE_SEAT,
5213                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
5214                         Boolean.class)
5215                 .addReadPermission(Car.PERMISSION_CONTROL_CAR_AIRBAGS)
5216                 .addWritePermission(Car.PERMISSION_CONTROL_CAR_AIRBAGS);
5217     }
5218 
5219     private static VehiclePropertyVerifier.Builder<Integer>
5220             getSeatCushionSideSupportPosVerifierBuilder() {
5221         return VehiclePropertyVerifier.newBuilder(
5222                         VehiclePropertyIds.SEAT_CUSHION_SIDE_SUPPORT_POS,
5223                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE,
5224                         VehicleAreaType.VEHICLE_AREA_TYPE_SEAT,
5225                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
5226                         Integer.class)
5227                 .requireMinMaxValues()
5228                 .addReadPermission(Car.PERMISSION_CONTROL_CAR_SEATS)
5229                 .addWritePermission(Car.PERMISSION_CONTROL_CAR_SEATS);
5230     }
5231 
5232     private static VehiclePropertyVerifier.Builder<Integer>
5233             getSeatCushionSideSupportMoveVerifierBuilder() {
5234         return VehiclePropertyVerifier.newBuilder(
5235                         VehiclePropertyIds.SEAT_CUSHION_SIDE_SUPPORT_MOVE,
5236                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE,
5237                         VehicleAreaType.VEHICLE_AREA_TYPE_SEAT,
5238                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
5239                         Integer.class)
5240                 .requireMinMaxValues()
5241                 .requireZeroToBeContainedInMinMaxRanges()
5242                 .addReadPermission(Car.PERMISSION_CONTROL_CAR_SEATS)
5243                 .addWritePermission(Car.PERMISSION_CONTROL_CAR_SEATS);
5244     }
5245 
5246     private static VehiclePropertyVerifier.Builder<Integer>
5247             getSeatLumberVerticalPosVerifierBuilder() {
5248         return VehiclePropertyVerifier.newBuilder(
5249                         VehiclePropertyIds.SEAT_LUMBAR_VERTICAL_POS,
5250                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE,
5251                         VehicleAreaType.VEHICLE_AREA_TYPE_SEAT,
5252                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
5253                         Integer.class)
5254                 .requireMinMaxValues()
5255                 .addReadPermission(Car.PERMISSION_CONTROL_CAR_SEATS)
5256                 .addWritePermission(Car.PERMISSION_CONTROL_CAR_SEATS);
5257     }
5258 
5259     private static VehiclePropertyVerifier.Builder<Integer>
5260             getSeatLumberVerticalMoveVerifierBuilder() {
5261         return VehiclePropertyVerifier.newBuilder(
5262                         VehiclePropertyIds.SEAT_LUMBAR_VERTICAL_MOVE,
5263                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE,
5264                         VehicleAreaType.VEHICLE_AREA_TYPE_SEAT,
5265                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
5266                         Integer.class)
5267                 .requireMinMaxValues()
5268                 .requireZeroToBeContainedInMinMaxRanges()
5269                 .addReadPermission(Car.PERMISSION_CONTROL_CAR_SEATS)
5270                 .addWritePermission(Car.PERMISSION_CONTROL_CAR_SEATS);
5271     }
5272 
5273     private static VehiclePropertyVerifier.Builder<Integer> getSeatWalkInPosVerifierBuilder() {
5274         return VehiclePropertyVerifier.newBuilder(
5275                         VehiclePropertyIds.SEAT_WALK_IN_POS,
5276                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE,
5277                         VehicleAreaType.VEHICLE_AREA_TYPE_SEAT,
5278                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
5279                         Integer.class)
5280                 .requireMinMaxValues()
5281                 .requireMinValuesToBeZero()
5282                 .addReadPermission(Car.PERMISSION_CONTROL_CAR_SEATS)
5283                 .addWritePermission(Car.PERMISSION_CONTROL_CAR_SEATS);
5284     }
5285 
5286     private static VehiclePropertyVerifier.Builder<Integer>
5287             getSeatAirbagsDeployedVerifierBuilder() {
5288         return VehiclePropertyVerifier.newBuilder(
5289                         VehiclePropertyIds.SEAT_AIRBAGS_DEPLOYED,
5290                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ,
5291                         VehicleAreaType.VEHICLE_AREA_TYPE_SEAT,
5292                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
5293                         Integer.class)
5294                 .setAllPossibleEnumValues(VEHICLE_AIRBAG_LOCATIONS)
5295                 .setBitMapEnumEnabled(true)
5296                 .addReadPermission(Car.PERMISSION_READ_CAR_AIRBAGS);
5297     }
5298 
5299     private static VehiclePropertyVerifier.Builder<Boolean>
5300             getSeatBeltPretensionerDeployedVerifierBuilder() {
5301         return VehiclePropertyVerifier.newBuilder(
5302                         VehiclePropertyIds.SEAT_BELT_PRETENSIONER_DEPLOYED,
5303                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ,
5304                         VehicleAreaType.VEHICLE_AREA_TYPE_SEAT,
5305                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
5306                         Boolean.class)
5307                 .addReadPermission(Car.PERMISSION_READ_CAR_SEAT_BELTS);
5308     }
5309 
5310     private static VehiclePropertyVerifier.Builder<Boolean> getValetModeEnabledVerifierBuilder() {
5311         return VehiclePropertyVerifier.newBuilder(
5312                         VehiclePropertyIds.VALET_MODE_ENABLED,
5313                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE,
5314                         VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
5315                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
5316                         Boolean.class)
5317                 .addReadPermission(Car.PERMISSION_READ_VALET_MODE)
5318                 .addReadPermission(Car.PERMISSION_CONTROL_VALET_MODE)
5319                 .addWritePermission(Car.PERMISSION_CONTROL_VALET_MODE);
5320     }
5321 
5322     private static VehiclePropertyVerifier.Builder<Boolean>
5323             getHeadUpDisplayEnabledVerifierBuilder() {
5324         return VehiclePropertyVerifier.newBuilder(
5325                         VehiclePropertyIds.HEAD_UP_DISPLAY_ENABLED,
5326                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE,
5327                         VehicleAreaType.VEHICLE_AREA_TYPE_SEAT,
5328                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
5329                         Boolean.class)
5330                 .addReadPermission(Car.PERMISSION_READ_HEAD_UP_DISPLAY_STATUS)
5331                 .addReadPermission(Car.PERMISSION_CONTROL_HEAD_UP_DISPLAY)
5332                 .addWritePermission(Car.PERMISSION_CONTROL_HEAD_UP_DISPLAY);
5333     }
5334 
5335     private static VehiclePropertyVerifier.Builder<Integer> getSeatOccupancyVerifierBuilder() {
5336         return VehiclePropertyVerifier.newBuilder(
5337                         VehiclePropertyIds.SEAT_OCCUPANCY,
5338                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ,
5339                         VehicleAreaType.VEHICLE_AREA_TYPE_SEAT,
5340                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
5341                 Integer.class)
5342                 .setAllPossibleEnumValues(VEHICLE_SEAT_OCCUPANCY_STATES)
5343                 .addReadPermission(Car.PERMISSION_CONTROL_CAR_SEATS);
5344     }
5345 
5346 
5347     private static VehiclePropertyVerifier.Builder<Boolean>
5348             getHvacElectricDefrosterOnVerifierBuilder() {
5349         return VehiclePropertyVerifier.newBuilder(
5350                         VehiclePropertyIds.HVAC_ELECTRIC_DEFROSTER_ON,
5351                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE,
5352                         VehicleAreaType.VEHICLE_AREA_TYPE_WINDOW,
5353                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
5354                         Boolean.class)
5355                 .addReadPermission(Car.PERMISSION_CONTROL_CAR_CLIMATE)
5356                 .addWritePermission(Car.PERMISSION_CONTROL_CAR_CLIMATE);
5357     }
5358 
5359     private static VehiclePropertyVerifier.Builder<Boolean>
5360             getAutomaticEmergencyBrakingEnabledVerifierBuilder() {
5361         return VehiclePropertyVerifier.newBuilder(
5362                         VehiclePropertyIds.AUTOMATIC_EMERGENCY_BRAKING_ENABLED,
5363                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE,
5364                         VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
5365                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
5366                         Boolean.class)
5367                 .addReadPermission(Car.PERMISSION_READ_ADAS_SETTINGS)
5368                 .addReadPermission(Car.PERMISSION_CONTROL_ADAS_SETTINGS)
5369                 .addWritePermission(Car.PERMISSION_CONTROL_ADAS_SETTINGS);
5370     }
5371 
5372     private static VehiclePropertyVerifier.Builder<Integer>
5373             getAutomaticEmergencyBrakingStateVerifierBuilder() {
5374         ImmutableSet<Integer> combinedCarPropertyValues = ImmutableSet.<Integer>builder()
5375                 .addAll(AUTOMATIC_EMERGENCY_BRAKING_STATES)
5376                 .addAll(ERROR_STATES)
5377                 .build();
5378 
5379         return VehiclePropertyVerifier.newBuilder(
5380                         VehiclePropertyIds.AUTOMATIC_EMERGENCY_BRAKING_STATE,
5381                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ,
5382                         VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
5383                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
5384                         Integer.class)
5385                 .setAllPossibleEnumValues(combinedCarPropertyValues)
5386                 .setDependentOnProperty(VehiclePropertyIds.AUTOMATIC_EMERGENCY_BRAKING_ENABLED,
5387                         ImmutableSet.of(Car.PERMISSION_READ_ADAS_SETTINGS,
5388                                 Car.PERMISSION_CONTROL_ADAS_SETTINGS))
5389                 .verifyErrorStates()
5390                 .addReadPermission(Car.PERMISSION_READ_ADAS_STATES);
5391     }
5392 
5393     @Test
5394     public void testAutomaticEmergencyBrakingStateWithErrorState() {
5395         verifyEnumValuesAreDistinct(AUTOMATIC_EMERGENCY_BRAKING_STATES, ERROR_STATES);
5396     }
5397 
5398     private static VehiclePropertyVerifier.Builder<Boolean>
5399             getForwardCollisionWarningEnabledVerifierBuilder() {
5400         return VehiclePropertyVerifier.newBuilder(
5401                         VehiclePropertyIds.FORWARD_COLLISION_WARNING_ENABLED,
5402                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE,
5403                         VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
5404                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
5405                         Boolean.class)
5406                 .addReadPermission(Car.PERMISSION_READ_ADAS_SETTINGS)
5407                 .addReadPermission(Car.PERMISSION_CONTROL_ADAS_SETTINGS)
5408                 .addWritePermission(Car.PERMISSION_CONTROL_ADAS_SETTINGS);
5409     }
5410 
5411     private static VehiclePropertyVerifier.Builder<Integer>
5412             getForwardCollisionWarningStateVerifierBuilder() {
5413         ImmutableSet<Integer> combinedCarPropertyValues = ImmutableSet.<Integer>builder()
5414                 .addAll(FORWARD_COLLISION_WARNING_STATES)
5415                 .addAll(ERROR_STATES)
5416                 .build();
5417 
5418         return VehiclePropertyVerifier.newBuilder(
5419                         VehiclePropertyIds.FORWARD_COLLISION_WARNING_STATE,
5420                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ,
5421                         VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
5422                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
5423                         Integer.class)
5424                 .setAllPossibleEnumValues(combinedCarPropertyValues)
5425                 .setDependentOnProperty(VehiclePropertyIds.FORWARD_COLLISION_WARNING_ENABLED,
5426                         ImmutableSet.of(Car.PERMISSION_READ_ADAS_SETTINGS,
5427                                 Car.PERMISSION_CONTROL_ADAS_SETTINGS))
5428                 .verifyErrorStates()
5429                 .addReadPermission(Car.PERMISSION_READ_ADAS_STATES);
5430     }
5431 
5432     @Test
5433     public void testForwardCollisionWarningStateWithErrorState() {
5434         verifyEnumValuesAreDistinct(FORWARD_COLLISION_WARNING_STATES, ERROR_STATES);
5435     }
5436 
5437     private static VehiclePropertyVerifier.Builder<Boolean>
5438             getBlindSpotWarningEnabledVerifierBuilder() {
5439         return VehiclePropertyVerifier.newBuilder(
5440                         VehiclePropertyIds.BLIND_SPOT_WARNING_ENABLED,
5441                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE,
5442                         VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
5443                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
5444                         Boolean.class)
5445                 .addReadPermission(Car.PERMISSION_READ_ADAS_SETTINGS)
5446                 .addReadPermission(Car.PERMISSION_CONTROL_ADAS_SETTINGS)
5447                 .addWritePermission(Car.PERMISSION_CONTROL_ADAS_SETTINGS);
5448     }
5449 
5450     private static VehiclePropertyVerifier.Builder<Integer>
5451             getBlindSpotWarningStateVerifierBuilder() {
5452         ImmutableSet<Integer> combinedCarPropertyValues = ImmutableSet.<Integer>builder()
5453                 .addAll(BLIND_SPOT_WARNING_STATES)
5454                 .addAll(ERROR_STATES)
5455                 .build();
5456 
5457         return VehiclePropertyVerifier.newBuilder(
5458                         VehiclePropertyIds.BLIND_SPOT_WARNING_STATE,
5459                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ,
5460                         VehicleAreaType.VEHICLE_AREA_TYPE_MIRROR,
5461                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
5462                         Integer.class)
5463                 .setAllPossibleEnumValues(combinedCarPropertyValues)
5464                 .setDependentOnProperty(VehiclePropertyIds.BLIND_SPOT_WARNING_ENABLED,
5465                         ImmutableSet.of(Car.PERMISSION_READ_ADAS_SETTINGS,
5466                                 Car.PERMISSION_CONTROL_ADAS_SETTINGS))
5467                 .verifyErrorStates()
5468                 .addReadPermission(Car.PERMISSION_READ_ADAS_STATES);
5469     }
5470 
5471     @Test
5472     public void testBlindSpotWarningStateWithErrorState() {
5473         verifyEnumValuesAreDistinct(BLIND_SPOT_WARNING_STATES, ERROR_STATES);
5474     }
5475 
5476     private static VehiclePropertyVerifier.Builder<Boolean>
5477             getLaneDepartureWarningEnabledVerifierBuilder() {
5478         return VehiclePropertyVerifier.newBuilder(
5479                         VehiclePropertyIds.LANE_DEPARTURE_WARNING_ENABLED,
5480                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE,
5481                         VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
5482                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
5483                         Boolean.class)
5484                 .addReadPermission(Car.PERMISSION_READ_ADAS_SETTINGS)
5485                 .addReadPermission(Car.PERMISSION_CONTROL_ADAS_SETTINGS)
5486                 .addWritePermission(Car.PERMISSION_CONTROL_ADAS_SETTINGS);
5487     }
5488 
5489     private static VehiclePropertyVerifier.Builder<Integer>
5490             getLaneDepartureWarningStateVerifierBuilder() {
5491         ImmutableSet<Integer> combinedCarPropertyValues = ImmutableSet.<Integer>builder()
5492                 .addAll(LANE_DEPARTURE_WARNING_STATES)
5493                 .addAll(ERROR_STATES)
5494                 .build();
5495 
5496         return VehiclePropertyVerifier.newBuilder(
5497                         VehiclePropertyIds.LANE_DEPARTURE_WARNING_STATE,
5498                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ,
5499                         VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
5500                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
5501                         Integer.class)
5502                 .setAllPossibleEnumValues(combinedCarPropertyValues)
5503                 .setDependentOnProperty(VehiclePropertyIds.LANE_DEPARTURE_WARNING_ENABLED,
5504                         ImmutableSet.of(Car.PERMISSION_READ_ADAS_SETTINGS,
5505                                 Car.PERMISSION_CONTROL_ADAS_SETTINGS))
5506                 .verifyErrorStates()
5507                 .addReadPermission(Car.PERMISSION_READ_ADAS_STATES);
5508     }
5509 
5510     @Test
5511     public void testLaneDepartureWarningStateWithErrorState() {
5512         verifyEnumValuesAreDistinct(LANE_DEPARTURE_WARNING_STATES, ERROR_STATES);
5513     }
5514 
5515     private static VehiclePropertyVerifier.Builder<Boolean>
5516             getLaneKeepAssistEnabledVerifierBuilder() {
5517         return VehiclePropertyVerifier.newBuilder(
5518                         VehiclePropertyIds.LANE_KEEP_ASSIST_ENABLED,
5519                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE,
5520                         VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
5521                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
5522                         Boolean.class)
5523                 .addReadPermission(Car.PERMISSION_READ_ADAS_SETTINGS)
5524                 .addReadPermission(Car.PERMISSION_CONTROL_ADAS_SETTINGS)
5525                 .addWritePermission(Car.PERMISSION_CONTROL_ADAS_SETTINGS);
5526     }
5527 
5528     private static VehiclePropertyVerifier.Builder<Integer>
5529             getLaneKeepAssistStateVerifierBuilder() {
5530         ImmutableSet<Integer> combinedCarPropertyValues = ImmutableSet.<Integer>builder()
5531                 .addAll(LANE_KEEP_ASSIST_STATES)
5532                 .addAll(ERROR_STATES)
5533                 .build();
5534 
5535         return VehiclePropertyVerifier.newBuilder(
5536                         VehiclePropertyIds.LANE_KEEP_ASSIST_STATE,
5537                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ,
5538                         VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
5539                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
5540                         Integer.class)
5541                 .setAllPossibleEnumValues(combinedCarPropertyValues)
5542                 .setDependentOnProperty(VehiclePropertyIds.LANE_KEEP_ASSIST_ENABLED,
5543                         ImmutableSet.of(Car.PERMISSION_READ_ADAS_SETTINGS,
5544                                 Car.PERMISSION_CONTROL_ADAS_SETTINGS))
5545                 .verifyErrorStates()
5546                 .addReadPermission(Car.PERMISSION_READ_ADAS_STATES);
5547     }
5548 
5549     @Test
5550     public void testLaneKeepAssistStateWithErrorState() {
5551         verifyEnumValuesAreDistinct(LANE_KEEP_ASSIST_STATES, ERROR_STATES);
5552     }
5553 
5554     private static VehiclePropertyVerifier.Builder<Boolean>
5555             getLaneCenteringAssistEnabledVerifierBuilder() {
5556         return VehiclePropertyVerifier.newBuilder(
5557                         VehiclePropertyIds.LANE_CENTERING_ASSIST_ENABLED,
5558                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE,
5559                         VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
5560                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
5561                         Boolean.class)
5562                 .addReadPermission(Car.PERMISSION_READ_ADAS_SETTINGS)
5563                 .addReadPermission(Car.PERMISSION_CONTROL_ADAS_SETTINGS)
5564                 .addWritePermission(Car.PERMISSION_CONTROL_ADAS_SETTINGS);
5565     }
5566 
5567     private static VehiclePropertyVerifier.Builder<Integer>
5568             getLaneCenteringAssistCommandVerifierBuilder() {
5569         return VehiclePropertyVerifier.newBuilder(
5570                         VehiclePropertyIds.LANE_CENTERING_ASSIST_COMMAND,
5571                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_WRITE,
5572                         VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
5573                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
5574                         Integer.class)
5575                 .setAllPossibleEnumValues(LANE_CENTERING_ASSIST_COMMANDS)
5576                 .setDependentOnProperty(VehiclePropertyIds.LANE_CENTERING_ASSIST_ENABLED,
5577                         ImmutableSet.of(Car.PERMISSION_READ_ADAS_SETTINGS,
5578                                 Car.PERMISSION_CONTROL_ADAS_SETTINGS))
5579                 .addWritePermission(Car.PERMISSION_CONTROL_ADAS_STATES);
5580     }
5581 
5582     private static VehiclePropertyVerifier.Builder<Integer>
5583             getLaneCenteringAssistStateVerifierBuilder() {
5584         ImmutableSet<Integer> combinedCarPropertyValues = ImmutableSet.<Integer>builder()
5585                 .addAll(LANE_CENTERING_ASSIST_STATES)
5586                 .addAll(ERROR_STATES)
5587                 .build();
5588 
5589         return VehiclePropertyVerifier.newBuilder(
5590                         VehiclePropertyIds.LANE_CENTERING_ASSIST_STATE,
5591                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ,
5592                         VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
5593                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
5594                         Integer.class)
5595                 .setAllPossibleEnumValues(combinedCarPropertyValues)
5596                 .setDependentOnProperty(VehiclePropertyIds.LANE_CENTERING_ASSIST_ENABLED,
5597                         ImmutableSet.of(Car.PERMISSION_READ_ADAS_SETTINGS,
5598                                 Car.PERMISSION_CONTROL_ADAS_SETTINGS))
5599                 .verifyErrorStates()
5600                 .addReadPermission(Car.PERMISSION_READ_ADAS_STATES);
5601     }
5602 
5603     @Test
5604     public void testLaneCenteringAssistStateWithErrorState() {
5605         verifyEnumValuesAreDistinct(LANE_CENTERING_ASSIST_STATES, ERROR_STATES);
5606     }
5607 
5608     private static VehiclePropertyVerifier.Builder<Boolean>
5609             getLowSpeedCollisionWarningEnabledVerifierBuilder() {
5610         return VehiclePropertyVerifier.newBuilder(
5611                         VehiclePropertyIds.LOW_SPEED_COLLISION_WARNING_ENABLED,
5612                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE,
5613                         VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
5614                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
5615                         Boolean.class)
5616                 .addReadPermission(Car.PERMISSION_READ_ADAS_SETTINGS)
5617                 .addReadPermission(Car.PERMISSION_CONTROL_ADAS_SETTINGS)
5618                 .addWritePermission(Car.PERMISSION_CONTROL_ADAS_SETTINGS);
5619     }
5620 
5621     private static VehiclePropertyVerifier.Builder<Integer>
5622             getLowSpeedCollisionWarningStateVerifierBuilder() {
5623         ImmutableSet<Integer> combinedCarPropertyValues = ImmutableSet.<Integer>builder()
5624                 .addAll(LOW_SPEED_COLLISION_WARNING_STATES)
5625                 .add(
5626                         ErrorState.OTHER_ERROR_STATE,
5627                         ErrorState.NOT_AVAILABLE_DISABLED,
5628                         ErrorState.NOT_AVAILABLE_SPEED_HIGH,
5629                         ErrorState.NOT_AVAILABLE_POOR_VISIBILITY,
5630                         ErrorState.NOT_AVAILABLE_SAFETY)
5631                 .build();
5632 
5633         return VehiclePropertyVerifier.newBuilder(
5634                         VehiclePropertyIds.LOW_SPEED_COLLISION_WARNING_STATE,
5635                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ,
5636                         VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
5637                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
5638                         Integer.class)
5639                 .setAllPossibleEnumValues(combinedCarPropertyValues)
5640                 .setDependentOnProperty(VehiclePropertyIds.LOW_SPEED_COLLISION_WARNING_ENABLED,
5641                         ImmutableSet.of(Car.PERMISSION_READ_ADAS_SETTINGS,
5642                                 Car.PERMISSION_CONTROL_ADAS_SETTINGS))
5643                 .verifyErrorStates()
5644                 .addReadPermission(Car.PERMISSION_READ_ADAS_STATES);
5645     }
5646 
5647     @Test
5648     @RequiresFlagsEnabled(Flags.FLAG_ANDROID_VIC_VEHICLE_PROPERTIES)
5649     public void testLowSpeedCollisionWarningStateWithErrorState() {
5650         verifyEnumValuesAreDistinct(LOW_SPEED_COLLISION_WARNING_STATES, ERROR_STATES);
5651     }
5652 
5653     private static VehiclePropertyVerifier.Builder<Integer>
5654             getElectronicStabilityControlStateVerifierBuilder() {
5655         ImmutableSet<Integer> combinedCarPropertyValues = ImmutableSet.<Integer>builder()
5656                 .addAll(ELECTRONIC_STABILITY_CONTROL_STATES)
5657                 .addAll(ERROR_STATES)
5658                 .build();
5659 
5660         return VehiclePropertyVerifier.newBuilder(
5661                         VehiclePropertyIds.ELECTRONIC_STABILITY_CONTROL_STATE,
5662                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ,
5663                         VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
5664                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
5665                         Integer.class)
5666                 .setAllPossibleEnumValues(combinedCarPropertyValues)
5667                 .setDependentOnProperty(VehiclePropertyIds.ELECTRONIC_STABILITY_CONTROL_ENABLED,
5668                         ImmutableSet.of(Car.PERMISSION_CAR_DYNAMICS_STATE,
5669                                 Car.PERMISSION_CONTROL_CAR_DYNAMICS_STATE))
5670                 .verifyErrorStates()
5671                 .addReadPermission(Car.PERMISSION_CAR_DYNAMICS_STATE);
5672     }
5673 
5674     @Test
5675     @RequiresFlagsEnabled(Flags.FLAG_ANDROID_VIC_VEHICLE_PROPERTIES)
5676     public void testElectronicStabilityControlStateWithErrorState() {
5677         verifyEnumValuesAreDistinct(ELECTRONIC_STABILITY_CONTROL_STATES, ERROR_STATES);
5678     }
5679 
5680     private static VehiclePropertyVerifier.Builder<Boolean>
5681             getElectronicStabilityControlEnabledVerifierBuilder() {
5682         return VehiclePropertyVerifier.newBuilder(
5683                         VehiclePropertyIds.ELECTRONIC_STABILITY_CONTROL_ENABLED,
5684                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE,
5685                         VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
5686                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
5687                         Boolean.class)
5688                 .addReadPermission(Car.PERMISSION_CAR_DYNAMICS_STATE)
5689                 .addReadPermission(Car.PERMISSION_CONTROL_CAR_DYNAMICS_STATE)
5690                 .addWritePermission(Car.PERMISSION_CONTROL_CAR_DYNAMICS_STATE);
5691     }
5692 
5693     private static VehiclePropertyVerifier.Builder<Boolean>
5694             getCrossTrafficMonitoringEnabledVerifierBuilder() {
5695         return VehiclePropertyVerifier.newBuilder(
5696                         VehiclePropertyIds.CROSS_TRAFFIC_MONITORING_ENABLED,
5697                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE,
5698                         VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
5699                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
5700                         Boolean.class)
5701                 .addReadPermission(Car.PERMISSION_READ_ADAS_SETTINGS)
5702                 .addReadPermission(Car.PERMISSION_CONTROL_ADAS_SETTINGS)
5703                 .addWritePermission(Car.PERMISSION_CONTROL_ADAS_SETTINGS);
5704     }
5705 
5706     private static VehiclePropertyVerifier.Builder<Integer>
5707             getCrossTrafficMonitoringWarningStateVerifierBuilder() {
5708         ImmutableSet<Integer> combinedCarPropertyValues = ImmutableSet.<Integer>builder()
5709                 .addAll(CROSS_TRAFFIC_MONITORING_WARNING_STATES)
5710                 .addAll(ERROR_STATES)
5711                 .build();
5712 
5713         return VehiclePropertyVerifier.newBuilder(
5714                         VehiclePropertyIds.CROSS_TRAFFIC_MONITORING_WARNING_STATE,
5715                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ,
5716                         VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
5717                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
5718                         Integer.class)
5719                 .setAllPossibleEnumValues(combinedCarPropertyValues)
5720                 .setDependentOnProperty(VehiclePropertyIds.CROSS_TRAFFIC_MONITORING_ENABLED,
5721                         ImmutableSet.of(Car.PERMISSION_READ_ADAS_SETTINGS,
5722                                 Car.PERMISSION_CONTROL_ADAS_SETTINGS))
5723                 .verifyErrorStates()
5724                 .addReadPermission(Car.PERMISSION_READ_ADAS_STATES);
5725     }
5726 
5727     private static VehiclePropertyVerifier.Builder<Boolean>
5728             getLowSpeedAutomaticEmergencyBrakingEnabledVerifierBuilder() {
5729         return VehiclePropertyVerifier.newBuilder(
5730                         VehiclePropertyIds.LOW_SPEED_AUTOMATIC_EMERGENCY_BRAKING_ENABLED,
5731                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE,
5732                         VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
5733                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
5734                         Boolean.class)
5735                 .addReadPermission(Car.PERMISSION_READ_ADAS_SETTINGS)
5736                 .addReadPermission(Car.PERMISSION_CONTROL_ADAS_SETTINGS)
5737                 .addWritePermission(Car.PERMISSION_CONTROL_ADAS_SETTINGS);
5738     }
5739 
5740     private static VehiclePropertyVerifier.Builder<Integer>
5741             getLowSpeedAutomaticEmergencyBrakingStateVerifierBuilder() {
5742         ImmutableSet<Integer> combinedCarPropertyValues = ImmutableSet.<Integer>builder()
5743                 .addAll(LOW_SPEED_AUTOMATIC_EMERGENCY_BRAKING_STATES)
5744                 .addAll(ERROR_STATES)
5745                 .build();
5746 
5747         return VehiclePropertyVerifier.newBuilder(
5748                         VehiclePropertyIds.LOW_SPEED_AUTOMATIC_EMERGENCY_BRAKING_STATE,
5749                         CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ,
5750                         VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
5751                         CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
5752                         Integer.class)
5753                 .setAllPossibleEnumValues(combinedCarPropertyValues)
5754                 .setDependentOnProperty(
5755                         VehiclePropertyIds.LOW_SPEED_AUTOMATIC_EMERGENCY_BRAKING_ENABLED,
5756                         ImmutableSet.of(Car.PERMISSION_READ_ADAS_SETTINGS,
5757                                 Car.PERMISSION_CONTROL_ADAS_SETTINGS))
5758                 .verifyErrorStates()
5759                 .addReadPermission(Car.PERMISSION_READ_ADAS_STATES);
5760     }
5761 
5762     @Test
5763     @RequiresFlagsEnabled(Flags.FLAG_ANDROID_VIC_VEHICLE_PROPERTIES)
5764     public void testLowSpeedAutomaticEmergencyBrakingStateWithErrorState() {
5765         verifyEnumValuesAreDistinct(LOW_SPEED_AUTOMATIC_EMERGENCY_BRAKING_STATES, ERROR_STATES);
5766     }
5767 
5768     @SuppressWarnings("unchecked")
5769     @Test
5770     @ApiTest(apis = {"android.car.hardware.property.CarPropertyManager#getPropertyList",
5771             "android.car.hardware.property.CarPropertyManager#getBooleanProperty",
5772             "android.car.hardware.property.CarPropertyManager#getIntProperty",
5773             "android.car.hardware.property.CarPropertyManager#getFloatProperty",
5774             "android.car.hardware.property.CarPropertyManager#getIntArrayProperty",
5775             "android.car.hardware.property.CarPropertyManager#getProperty"})
5776     public void testGetAllSupportedReadablePropertiesSync() {
5777         runWithShellPermissionIdentity(
5778                 () -> {
5779                     List<CarPropertyConfig> configs =
5780                             mCarPropertyManager.getPropertyList(mPropertyIds);
5781                     for (CarPropertyConfig cfg : configs) {
5782                         int propId = cfg.getPropertyId();
5783                         List<AreaIdConfig<?>> areaIdConfigs = cfg.getAreaIdConfigs();
5784                         List<AreaIdConfig<?>> filteredAreaIdConfigs = new ArrayList<>();
5785                         if (Flags.areaIdConfigAccess()) {
5786                             for (AreaIdConfig<?> areaIdConfig : areaIdConfigs) {
5787                                 if (areaIdConfig.getAccess()
5788                                         == CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ
5789                                         || areaIdConfig.getAccess()
5790                                         == CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE) {
5791                                     filteredAreaIdConfigs.add(areaIdConfig);
5792                                 }
5793                             }
5794                         } else {
5795                             filteredAreaIdConfigs = areaIdConfigs;
5796                         }
5797                         // no guarantee if we can get values, just call and check if it throws
5798                         // exception.
5799                         for (AreaIdConfig<?> areaIdConfig : filteredAreaIdConfigs) {
5800                             mCarPropertyManager.getProperty(cfg.getPropertyType(), propId,
5801                                     areaIdConfig.getAreaId());
5802                         }
5803                     }
5804                 });
5805     }
5806 
5807     /**
5808      * Test for {@link CarPropertyManager#getPropertiesAsync}
5809      *
5810      * Generates GetPropertyRequest objects for supported readable properties and verifies if there
5811      * are no exceptions or request timeouts.
5812      */
5813     @Test
5814     @ApiTest(apis = {"android.car.hardware.property.CarPropertyManager#getPropertiesAsync"})
5815     public void testGetAllSupportedReadablePropertiesAsync() throws Exception {
5816         runWithShellPermissionIdentity(() -> {
5817             Executor executor = Executors.newFixedThreadPool(1);
5818             Set<Integer> pendingRequests = new ArraySet<>();
5819             List<CarPropertyManager.GetPropertyRequest> getPropertyRequests =
5820                     new ArrayList<>();
5821             Set<PropIdAreaId> requestPropIdAreaIds = new ArraySet<>();
5822 
5823             var verifiers = getAllSupportedVerifiers();
5824             for (int i = 0; i < verifiers.size(); i++) {
5825                 VehiclePropertyVerifier verifier = verifiers.get(i);
5826                 CarPropertyConfig cfg = verifier.getCarPropertyConfig();
5827                 if (!Flags.areaIdConfigAccess() && cfg.getAccess()
5828                         != CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ && cfg.getAccess()
5829                         != CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE) {
5830                     continue;
5831                 }
5832 
5833                 List<? extends AreaIdConfig<?>> areaIdConfigs = cfg.getAreaIdConfigs();
5834                 int propId = cfg.getPropertyId();
5835                 for (AreaIdConfig<?> areaIdConfig : areaIdConfigs) {
5836                     if (Flags.areaIdConfigAccess() && areaIdConfig.getAccess()
5837                             != CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ
5838                             && areaIdConfig.getAccess()
5839                             != CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE) {
5840                         continue;
5841                     }
5842 
5843                     int areaId = areaIdConfig.getAreaId();
5844                     CarPropertyManager.GetPropertyRequest gpr =
5845                             mCarPropertyManager.generateGetPropertyRequest(propId, areaId);
5846                     getPropertyRequests.add(gpr);
5847                     pendingRequests.add(gpr.getRequestId());
5848                     requestPropIdAreaIds.add(new PropIdAreaId(propId, areaId));
5849                 }
5850             }
5851 
5852             int expectedResultCount = pendingRequests.size();
5853 
5854             TestPropertyAsyncCallback testGetPropertyAsyncCallback =
5855                     new TestPropertyAsyncCallback(pendingRequests);
5856             mCarPropertyManager.getPropertiesAsync(
5857                     getPropertyRequests,
5858                     /* cancellationSignal= */ null,
5859                     executor,
5860                     testGetPropertyAsyncCallback);
5861             testGetPropertyAsyncCallback.waitAndFinish();
5862 
5863             assertThat(testGetPropertyAsyncCallback.getErrorList()).isEmpty();
5864             int resultCount = testGetPropertyAsyncCallback.getResultList().size();
5865             assertWithMessage("must receive at least " + expectedResultCount + " results, got "
5866                     + resultCount).that(resultCount).isEqualTo(expectedResultCount);
5867 
5868             for (PropIdAreaId receivedPropIdAreaId :
5869                     testGetPropertyAsyncCallback.getReceivedPropIdAreaIds()) {
5870                 assertWithMessage("received unexpected result for " + receivedPropIdAreaId)
5871                         .that(requestPropIdAreaIds).contains(receivedPropIdAreaId);
5872             }
5873         });
5874     }
5875 
5876     private static final class PropIdAreaId {
5877         private final int mPropId;
5878         private final int mAreaId;
5879 
5880         PropIdAreaId(int propId, int areaId) {
5881             mPropId = propId;
5882             mAreaId = areaId;
5883         }
5884 
5885         PropIdAreaId(PropIdAreaId other) {
5886             mPropId = other.mPropId;
5887             mAreaId = other.mAreaId;
5888         }
5889 
5890         @Override
5891         public int hashCode() {
5892             return Objects.hash(mAreaId, mPropId);
5893         }
5894 
5895         @Override
5896         public boolean equals(Object other) {
5897             if (this == other) {
5898                 return true;
5899             }
5900             if (other.getClass() != this.getClass()) {
5901                 return false;
5902             }
5903 
5904             PropIdAreaId o = (PropIdAreaId) other;
5905             return mPropId == o.mPropId && mAreaId == o.mAreaId;
5906         }
5907 
5908         @Override
5909         public String toString() {
5910             return "{propId: " + mPropId + ", areaId: " + mAreaId + "}";
5911         }
5912     }
5913 
5914     private static final class TestPropertyAsyncCallback implements
5915             CarPropertyManager.GetPropertyCallback,
5916             CarPropertyManager.SetPropertyCallback {
5917         private final CountDownLatch mCountDownLatch;
5918         private final Set<Integer> mPendingRequests;
5919         private final int mNumberOfRequests;
5920         private final Object mLock = new Object();
5921         @GuardedBy("mLock")
5922         private final List<String> mErrorList = new ArrayList<>();
5923         @GuardedBy("mLock")
5924         private final List<String> mResultList = new ArrayList<>();
5925         @GuardedBy("mLock")
5926         private final List<PropIdAreaId> mReceivedPropIdAreaIds = new ArrayList();
5927 
5928         TestPropertyAsyncCallback(Set<Integer> pendingRequests) {
5929             mNumberOfRequests = pendingRequests.size();
5930             mCountDownLatch = new CountDownLatch(mNumberOfRequests);
5931             mPendingRequests = pendingRequests;
5932         }
5933 
5934         private static String toMsg(int requestId, int propId, int areaId) {
5935             return "Request ID: " + requestId + " (propId: " + VehiclePropertyIds.toString(propId)
5936                     + ", areaId: " + areaId + ")";
5937         }
5938 
5939         private void onSuccess(boolean forGet, int requestId, int propId, int areaId,
5940                 @Nullable Object value, long updateTimestampNanos) {
5941             synchronized (mLock) {
5942                 if (!mPendingRequests.contains(requestId)) {
5943                     mErrorList.add(toMsg(requestId, propId, areaId) + " not present");
5944                     return;
5945                 } else {
5946                     mPendingRequests.remove(requestId);
5947                     mResultList.add(toMsg(requestId, propId, areaId)
5948                             + " complete with onSuccess()");
5949                 }
5950                 String requestInfo = toMsg(requestId, propId, areaId);
5951                 if (forGet) {
5952                     if (value == null) {
5953                         mErrorList.add("The property value for " + requestInfo + " must not be"
5954                                 + " null");
5955                     } else {
5956                         mReceivedPropIdAreaIds.add(new PropIdAreaId(propId, areaId));
5957                     }
5958                 } else {
5959                     if (updateTimestampNanos == 0) {
5960                         mErrorList.add("The updateTimestamp value for " + requestInfo + " must"
5961                                 + " not be 0");
5962                     }
5963                     mReceivedPropIdAreaIds.add(new PropIdAreaId(propId, areaId));
5964                 }
5965             }
5966             mCountDownLatch.countDown();
5967         }
5968 
5969         @Override
5970         public void onSuccess(@NonNull GetPropertyResult<?> gotPropertyResult) {
5971             onSuccess(true, gotPropertyResult.getRequestId(), gotPropertyResult.getPropertyId(),
5972                     gotPropertyResult.getAreaId(), gotPropertyResult.getValue(), 0L);
5973         }
5974 
5975         @Override
5976         public void onSuccess(@NonNull SetPropertyResult setPropertyResult) {
5977             onSuccess(false, setPropertyResult.getRequestId(), setPropertyResult.getPropertyId(),
5978                     setPropertyResult.getAreaId(), null,
5979                     setPropertyResult.getUpdateTimestampNanos());
5980         }
5981 
5982         @Override
5983         public void onFailure(@NonNull CarPropertyManager.PropertyAsyncError error) {
5984             int requestId = error.getRequestId();
5985             int propId = error.getPropertyId();
5986             int areaId = error.getAreaId();
5987             synchronized (mLock) {
5988                 if (!mPendingRequests.contains(requestId)) {
5989                     mErrorList.add(toMsg(requestId, propId, areaId) + " not present");
5990                     return;
5991                 } else {
5992                     mResultList.add(toMsg(requestId, propId, areaId)
5993                             + " complete with onFailure()");
5994                     mPendingRequests.remove(requestId);
5995                     mReceivedPropIdAreaIds.add(new PropIdAreaId(propId, areaId));
5996                 }
5997             }
5998             mCountDownLatch.countDown();
5999         }
6000 
6001         public void waitAndFinish() throws InterruptedException {
6002             boolean res = mCountDownLatch.await(ASYNC_WAIT_TIMEOUT_IN_SEC, TimeUnit.SECONDS);
6003             synchronized (mLock) {
6004                 if (!res) {
6005                     int gotRequestsCount = mNumberOfRequests - mPendingRequests.size();
6006                     mErrorList.add(
6007                             "Not enough responses received for getPropertiesAsync before timeout "
6008                                     + "(" + ASYNC_WAIT_TIMEOUT_IN_SEC + "s), expected "
6009                                     + mNumberOfRequests + " responses, got "
6010                                     + gotRequestsCount);
6011                 }
6012             }
6013         }
6014 
6015         public List<String> getErrorList() {
6016             List<String> errorList;
6017             synchronized (mLock) {
6018                 errorList = new ArrayList<>(mErrorList);
6019             }
6020             return errorList;
6021         }
6022 
6023         public List<String> getResultList() {
6024             List<String> resultList;
6025             synchronized (mLock) {
6026                 resultList = new ArrayList<>(mResultList);
6027             }
6028             return resultList;
6029         }
6030 
6031         public List<PropIdAreaId> getReceivedPropIdAreaIds() {
6032             List<PropIdAreaId> receivedPropIdAreaIds;
6033             synchronized (mLock) {
6034                 receivedPropIdAreaIds = new ArrayList<>(mReceivedPropIdAreaIds);
6035             }
6036             return receivedPropIdAreaIds;
6037         }
6038     }
6039 
6040     @Test
6041     public void testGetIntArrayProperty() {
6042         runWithShellPermissionIdentity(
6043                 () -> {
6044                     List<CarPropertyConfig> allConfigs = mCarPropertyManager.getPropertyList();
6045                     for (CarPropertyConfig cfg : allConfigs) {
6046                         if (cfg.getPropertyType() != Integer[].class
6047                                 || (!Flags.areaIdConfigAccess() && (cfg.getAccess()
6048                                 == CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_NONE || cfg.getAccess()
6049                                 == CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_WRITE))) {
6050                             // skip the test if the property is not readable or not an int array
6051                             // type property.
6052                             continue;
6053                         }
6054                         switch (cfg.getPropertyId()) {
6055                             case VehiclePropertyIds.INFO_FUEL_TYPE:
6056                                 int[] fuelTypes =
6057                                         mCarPropertyManager.getIntArrayProperty(
6058                                                 cfg.getPropertyId(),
6059                                                 VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL);
6060                                 verifyEnumsRange(EXPECTED_FUEL_TYPES, fuelTypes);
6061                                 break;
6062                             case VehiclePropertyIds.INFO_MULTI_EV_PORT_LOCATIONS:
6063                                 int[] evPortLocations =
6064                                         mCarPropertyManager.getIntArrayProperty(
6065                                                 cfg.getPropertyId(),
6066                                                 VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL);
6067                                 verifyEnumsRange(EXPECTED_PORT_LOCATIONS, evPortLocations);
6068                                 break;
6069                             default:
6070                                 List<? extends AreaIdConfig<?>> areaIdConfigs =
6071                                         cfg.getAreaIdConfigs();
6072                                 for (AreaIdConfig<?> areaIdConfig : areaIdConfigs) {
6073                                     if (Flags.areaIdConfigAccess() && (areaIdConfig.getAccess()
6074                                             == CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_NONE
6075                                             || areaIdConfig.getAccess()
6076                                             == CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_WRITE)) {
6077                                         // skip the test if the property is not readable
6078                                         continue;
6079                                     }
6080                                     mCarPropertyManager.getIntArrayProperty(
6081                                             cfg.getPropertyId(), areaIdConfig.getAreaId());
6082                                 }
6083                         }
6084                     }
6085                 });
6086     }
6087 
6088     private void verifyEnumsRange(List<Integer> expectedResults, int[] results) {
6089         assertThat(results).isNotNull();
6090         // If the property is not implemented in cars, getIntArrayProperty returns an empty array.
6091         if (results.length == 0) {
6092             return;
6093         }
6094         for (int result : results) {
6095             assertThat(result).isIn(expectedResults);
6096         }
6097     }
6098 
6099     @Test
6100     public void testIsPropertyAvailable() {
6101         runWithShellPermissionIdentity(
6102                 () -> {
6103                     List<CarPropertyConfig> configs =
6104                             mCarPropertyManager.getPropertyList(mPropertyIds);
6105 
6106                     for (CarPropertyConfig cfg : configs) {
6107                         int[] areaIds = getAreaIdsHelper(cfg);
6108                         for (int areaId : areaIds) {
6109                             assertThat(
6110                                             mCarPropertyManager.isPropertyAvailable(
6111                                                     cfg.getPropertyId(), areaId))
6112                                     .isTrue();
6113                         }
6114                     }
6115                 });
6116     }
6117 
6118     @Test
6119     @ApiTest(
6120             apis = {
6121                     "android.car.hardware.property.CarPropertyManager#subscribePropertyEvents"
6122             })
6123     @RequiresFlagsEnabled(Flags.FLAG_BATCHED_SUBSCRIPTIONS)
6124     public void testSubscribePropertyEventsWithInvalidProp() throws Exception {
6125         runWithShellPermissionIdentity(() -> {
6126             int invalidPropertyId = -1;
6127 
6128             assertThrows(IllegalArgumentException.class, () ->
6129                     mCarPropertyManager.subscribePropertyEvents(List.of(new Subscription
6130                             .Builder(invalidPropertyId)
6131                             .addAreaId(VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL).build()),
6132                     /* callbackExecutor= */ null, new CarPropertyEventCounter()));
6133         });
6134     }
6135 
6136     @Test
6137     @ApiTest(
6138             apis = {
6139                     "android.car.hardware.property.CarPropertyManager#subscribePropertyEvents",
6140                     "android.car.hardware.property.CarPropertyManager#unsubscribePropertyEvents"
6141             })
6142     @RequiresFlagsEnabled(Flags.FLAG_BATCHED_SUBSCRIPTIONS)
6143     public void testSubscribePropertyEventsWithDifferentExecutorForSamePropIdAreaId_notAllowed()
6144             throws Exception {
6145         runWithShellPermissionIdentity(() -> {
6146             // Ignores the test if wheel_tick property does not exist in the car.
6147             assumeTrue(
6148                     "WheelTick is not available, skip subscribePropertyEvent test",
6149                     mCarPropertyManager.isPropertyAvailable(
6150                             VehiclePropertyIds.WHEEL_TICK,
6151                             VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL));
6152 
6153             CarPropertyEventCallback callback = new CarPropertyEventCounter();
6154             assertThat(mCarPropertyManager.subscribePropertyEvents(List.of(new Subscription
6155                             .Builder(VehiclePropertyIds.PERF_VEHICLE_SPEED)
6156                             .addAreaId(VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL).build()),
6157                     Executors.newSingleThreadExecutor(), callback))
6158                     .isTrue();
6159 
6160             assertThrows(IllegalArgumentException.class, () ->
6161                     mCarPropertyManager.subscribePropertyEvents(List.of(new Subscription
6162                                     .Builder(VehiclePropertyIds.WHEEL_TICK)
6163                                     .addAreaId(VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL).build()),
6164                             Executors.newSingleThreadExecutor(), callback));
6165 
6166             mCarPropertyManager.unsubscribePropertyEvents(callback);
6167         });
6168     }
6169 
6170     @Test
6171     @ApiTest(
6172             apis = {
6173                     "android.car.hardware.property.CarPropertyManager#subscribePropertyEvents"
6174             }
6175     )
6176     @RequiresFlagsEnabled(Flags.FLAG_BATCHED_SUBSCRIPTIONS)
6177     public void testSubscribeOverlappingPropIdAreaIdInOneCall_notAllowed() throws Exception {
6178         runWithShellPermissionIdentity(() -> assertThrows(IllegalArgumentException.class, () ->
6179                 mCarPropertyManager.subscribePropertyEvents(
6180                 List.of(new Subscription.Builder(VehiclePropertyIds.HVAC_FAN_SPEED)
6181                                 .addAreaId(SEAT_ROW_1_LEFT).addAreaId(SEAT_ROW_1_RIGHT).build(),
6182                         new Subscription.Builder(VehiclePropertyIds.HVAC_FAN_SPEED)
6183                                 .addAreaId(SEAT_ROW_1_LEFT).build()),
6184                 null, new CarPropertyEventCounter())));
6185     }
6186 
6187     @Test
6188     @ApiTest(
6189             apis = {
6190                     "android.car.hardware.property.CarPropertyManager#subscribePropertyEvents"
6191             }
6192     )
6193     @RequiresFlagsEnabled(Flags.FLAG_BATCHED_SUBSCRIPTIONS)
6194     public void testSubscribePropertyEventsWithNoReadPermission_throwSecurityException()
6195             throws Exception {
6196         assertThrows(SecurityException.class, () ->
6197                 mCarPropertyManager.subscribePropertyEvents(
6198                 List.of(new Subscription.Builder(VehiclePropertyIds.PERF_VEHICLE_SPEED).build()),
6199                 null, new CarPropertyEventCounter()));
6200     }
6201 
6202     @Test
6203     @ApiTest(
6204             apis = {
6205                     "android.car.hardware.property.CarPropertyManager#subscribePropertyEvents",
6206                     "android.car.hardware.property.CarPropertyManager#unsubscribePropertyEvents",
6207                     "android.car.hardware.property.Subscription.Builder#Builder",
6208                     "android.car.hardware.property.Subscription.Builder#setUpdateRateUi",
6209                     "android.car.hardware.property.Subscription.Builder#addAreaId",
6210                     "android.car.hardware.property.Subscription.Builder#build",
6211                     "android.car.hardware.property.Subscription.Builder#"
6212                             + "setVariableUpdateRateEnabled"
6213             }
6214     )
6215     @RequiresFlagsEnabled({Flags.FLAG_BATCHED_SUBSCRIPTIONS, Flags.FLAG_VARIABLE_UPDATE_RATE})
6216     public void testSubscribePropertyEventsForContinuousPropertyWithBatchedRequest()
6217             throws Exception {
6218         runWithShellPermissionIdentity(
6219                 () -> {
6220                     int vehicleSpeed = VehiclePropertyIds.PERF_VEHICLE_SPEED;
6221                     int vehicleSpeedDisplay = VehiclePropertyIds.PERF_VEHICLE_SPEED_DISPLAY;
6222                     CarPropertyConfig<?> perfVehicleSpeedCarPropertyConfig =
6223                             mCarPropertyManager.getCarPropertyConfig(
6224                                     vehicleSpeed);
6225                     CarPropertyConfig<?> perfVehicleSpeedDisplayCarPropertyConfig =
6226                             mCarPropertyManager.getCarPropertyConfig(
6227                                     vehicleSpeedDisplay);
6228                     assumeTrue("The CarPropertyConfig of vehicle speed display does not exist",
6229                             perfVehicleSpeedDisplayCarPropertyConfig != null);
6230                     assumeTrue("The CarPropertyConfig of vehicle speed does not exist",
6231                             perfVehicleSpeedCarPropertyConfig != null);
6232                     long bufferMillis = 1_000; // 1 second
6233                     // timeoutMillis is set to the maximum expected time needed to receive the
6234                     // required number of PERF_VEHICLE_SPEED events for test. If the test does not
6235                     // receive the required number of events before the timeout expires, it fails.
6236                     long timeoutMillisPerfVehicleSpeed = generateTimeoutMillis(
6237                             perfVehicleSpeedCarPropertyConfig.getMinSampleRate(), bufferMillis);
6238                     long timeoutMillisPerfVehicleSpeedDisplay = generateTimeoutMillis(
6239                             perfVehicleSpeedDisplayCarPropertyConfig.getMinSampleRate(),
6240                             bufferMillis);
6241                     CarPropertyEventCounter speedListener =
6242                             new CarPropertyEventCounter(Math.max(timeoutMillisPerfVehicleSpeed,
6243                                     timeoutMillisPerfVehicleSpeedDisplay));
6244 
6245                     assertThat(speedListener.receivedEvent(vehicleSpeed)).isEqualTo(NO_EVENTS);
6246                     assertThat(speedListener.receivedError(vehicleSpeed)).isEqualTo(NO_EVENTS);
6247                     assertThat(speedListener.receivedErrorWithErrorCode(vehicleSpeed))
6248                             .isEqualTo(NO_EVENTS);
6249                     assertThat(speedListener.receivedEvent(vehicleSpeedDisplay))
6250                             .isEqualTo(NO_EVENTS);
6251                     assertThat(speedListener.receivedError(vehicleSpeedDisplay))
6252                             .isEqualTo(NO_EVENTS);
6253                     assertThat(speedListener.receivedErrorWithErrorCode(vehicleSpeedDisplay))
6254                             .isEqualTo(NO_EVENTS);
6255 
6256                     Subscription speedSubscription = new Subscription
6257                             .Builder(vehicleSpeed)
6258                             .setUpdateRateUi()
6259                             .addAreaId(VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL)
6260                             // We need to receive property update events based on update rate.
6261                             .setVariableUpdateRateEnabled(false)
6262                             .build();
6263                     Subscription speedDisplaySubscription = new Subscription
6264                             .Builder(vehicleSpeedDisplay)
6265                             .setUpdateRateUi()
6266                             .addAreaId(VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL)
6267                             // We need to receive property update events based on update rate.
6268                             .setVariableUpdateRateEnabled(false)
6269                             .build();
6270 
6271                     speedListener.resetCountDownLatch(UI_RATE_EVENT_COUNTER);
6272                     mCarPropertyManager.subscribePropertyEvents(
6273                             List.of(speedSubscription, speedDisplaySubscription),
6274                             /* callbackExecutor= */ null, speedListener);
6275                     speedListener.assertOnChangeEventCalled();
6276                     mCarPropertyManager.unsubscribePropertyEvents(speedListener);
6277 
6278                     assertThat(speedListener.receivedEvent(vehicleSpeed))
6279                             .isGreaterThan(NO_EVENTS);
6280                     assertThat(speedListener.receivedEvent(vehicleSpeedDisplay))
6281                             .isGreaterThan(NO_EVENTS);
6282                     // The test did not change property values, it should not get error with error
6283                     // codes.
6284                     assertThat(speedListener.receivedErrorWithErrorCode(vehicleSpeed))
6285                             .isEqualTo(NO_EVENTS);
6286                     assertThat(speedListener.receivedErrorWithErrorCode(vehicleSpeedDisplay))
6287                             .isEqualTo(NO_EVENTS);
6288                 });
6289     }
6290 
6291     private void subscribePropertyEventsForContinuousPropertyTestCase(boolean flagVUR)
6292             throws Exception {
6293         runWithShellPermissionIdentity(
6294                 () -> {
6295                     int vehicleSpeed = VehiclePropertyIds.PERF_VEHICLE_SPEED;
6296                     CarPropertyConfig<?> carPropertyConfig =
6297                             mCarPropertyManager.getCarPropertyConfig(
6298                                     VehiclePropertyIds.PERF_VEHICLE_SPEED);
6299                     assumeTrue("The CarPropertyConfig of vehicle speed does not exist",
6300                             carPropertyConfig != null);
6301                     long bufferMillis = 1_000; // 1 second
6302                     // timeoutMillis is set to the maximum expected time needed to receive the
6303                     // required number of PERF_VEHICLE_SPEED events for test. If the test does not
6304                     // receive the required number of events before the timeout expires, it fails.
6305                     long timeoutMillis = generateTimeoutMillis(carPropertyConfig.getMinSampleRate(),
6306                             bufferMillis);
6307                     CarPropertyEventCounter speedListenerUI =
6308                             new CarPropertyEventCounter(timeoutMillis);
6309                     CarPropertyEventCounter speedListenerFast = new CarPropertyEventCounter();
6310 
6311                     assertThat(speedListenerUI.receivedEvent(vehicleSpeed)).isEqualTo(NO_EVENTS);
6312                     assertThat(speedListenerUI.receivedError(vehicleSpeed)).isEqualTo(NO_EVENTS);
6313                     assertThat(speedListenerUI.receivedErrorWithErrorCode(vehicleSpeed))
6314                             .isEqualTo(NO_EVENTS);
6315                     assertThat(speedListenerFast.receivedEvent(vehicleSpeed)).isEqualTo(NO_EVENTS);
6316                     assertThat(speedListenerFast.receivedError(vehicleSpeed)).isEqualTo(NO_EVENTS);
6317                     assertThat(speedListenerFast.receivedErrorWithErrorCode(vehicleSpeed))
6318                             .isEqualTo(NO_EVENTS);
6319 
6320                     speedListenerUI.resetCountDownLatch(UI_RATE_EVENT_COUNTER);
6321                     Subscription.Builder uiRateSubscriptionBuilder = new Subscription
6322                             .Builder(VehiclePropertyIds.PERF_VEHICLE_SPEED)
6323                             .setUpdateRateUi()
6324                             .addAreaId(VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL);
6325                     Subscription.Builder fastestRateSubscriptionBuilder = new Subscription
6326                             .Builder(VehiclePropertyIds.PERF_VEHICLE_SPEED)
6327                             .setUpdateRateFastest().addAreaId(
6328                                     VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL);
6329                     if (flagVUR) {
6330                         // If VUR is enabled, we disable VUR because we need the property events
6331                         // to arrive according to update rate.
6332                         uiRateSubscriptionBuilder.setVariableUpdateRateEnabled(false);
6333                         fastestRateSubscriptionBuilder.setVariableUpdateRateEnabled(false);
6334                     }
6335                     Subscription uiRateSubscription = uiRateSubscriptionBuilder.build();
6336                     Subscription fastestRateSubscription = fastestRateSubscriptionBuilder.build();
6337                     mCarPropertyManager.subscribePropertyEvents(
6338                             List.of(uiRateSubscription),
6339                             /* callbackExecutor= */ null, speedListenerUI);
6340                     mCarPropertyManager.subscribePropertyEvents(
6341                             List.of(fastestRateSubscription),
6342                             /* callbackExecutor= */ null, speedListenerFast);
6343                     speedListenerUI.assertOnChangeEventCalled();
6344                     mCarPropertyManager.unsubscribePropertyEvents(speedListenerUI);
6345                     mCarPropertyManager.unsubscribePropertyEvents(speedListenerFast);
6346 
6347                     assertThat(speedListenerUI.receivedEvent(vehicleSpeed))
6348                             .isGreaterThan(NO_EVENTS);
6349                     assertThat(speedListenerFast.receivedEvent(vehicleSpeed))
6350                             .isAtLeast(speedListenerUI.receivedEvent(vehicleSpeed));
6351                     // The test did not change property values, it should not get error with error
6352                     // codes.
6353                     assertThat(speedListenerUI.receivedErrorWithErrorCode(vehicleSpeed))
6354                             .isEqualTo(NO_EVENTS);
6355                     assertThat(speedListenerFast.receivedErrorWithErrorCode(vehicleSpeed))
6356                             .isEqualTo(NO_EVENTS);
6357                 });
6358     }
6359 
6360 
6361     @Test
6362     @ApiTest(
6363             apis = {
6364                     "android.car.hardware.property.CarPropertyManager#subscribePropertyEvents",
6365                     "android.car.hardware.property.CarPropertyManager#unsubscribePropertyEvents",
6366                     "android.car.hardware.property.Subscription.Builder#Builder",
6367                     "android.car.hardware.property.Subscription.Builder#setUpdateRateUi",
6368                     "android.car.hardware.property.Subscription.Builder#setUpdateRateFastest",
6369                     "android.car.hardware.property.Subscription.Builder#addAreaId",
6370                     "android.car.hardware.property.Subscription.Builder#build"
6371             })
6372     @RequiresFlagsEnabled(Flags.FLAG_BATCHED_SUBSCRIPTIONS)
6373     @RequiresFlagsDisabled(Flags.FLAG_VARIABLE_UPDATE_RATE)
6374     public void testSubscribePropertyEventsForContinuousProperty() throws Exception {
6375         subscribePropertyEventsForContinuousPropertyTestCase(false);
6376     }
6377 
6378     @Test
6379     @ApiTest(
6380             apis = {
6381                     "android.car.hardware.property.CarPropertyManager#subscribePropertyEvents",
6382                     "android.car.hardware.property.CarPropertyManager#unsubscribePropertyEvents",
6383                     "android.car.hardware.property.Subscription.Builder#Builder",
6384                     "android.car.hardware.property.Subscription.Builder#setUpdateRateUi",
6385                     "android.car.hardware.property.Subscription.Builder#setUpdateRateFastest",
6386                     "android.car.hardware.property.Subscription.Builder#addAreaId",
6387                     "android.car.hardware.property.Subscription.Builder#build",
6388                     "android.car.hardware.property.Subscription.Builder#"
6389                             + "setVariableUpdateRateEnabled"
6390             })
6391     @RequiresFlagsEnabled({Flags.FLAG_BATCHED_SUBSCRIPTIONS, Flags.FLAG_VARIABLE_UPDATE_RATE})
6392     public void testSubscribePropertyEventsForContinuousProperty_disableVUR() throws Exception {
6393         subscribePropertyEventsForContinuousPropertyTestCase(true);
6394     }
6395 
6396     private static class DuplicatePropertyEventChecker extends CarPropertyEventCounter {
6397         private final Object mLock = new Object();
6398         @GuardedBy("mLock")
6399         private List<Object> mReceivedValues = new ArrayList<>();
6400         @GuardedBy("mLock")
6401         private CarPropertyValue mDuplicateValue;
6402 
6403         @Override
6404         public void onChangeEvent(CarPropertyValue value) {
6405             super.onChangeEvent(value);
6406             if (value.getStatus() != CarPropertyValue.STATUS_AVAILABLE) {
6407                 return;
6408             }
6409             synchronized (mLock) {
6410                 for (int i = 0; i < mReceivedValues.size(); i++) {
6411                     if (Objects.deepEquals(mReceivedValues.get(i), value.getValue())) {
6412                         mDuplicateValue = value;
6413                         break;
6414                     }
6415                 }
6416                 mReceivedValues.add(value.getValue());
6417             }
6418         }
6419 
6420         CarPropertyValue getDuplicateValue() {
6421             synchronized (mLock) {
6422                 return mDuplicateValue;
6423             }
6424         }
6425     }
6426 
6427     @Test
6428     @ApiTest(
6429             apis = {
6430                     "android.car.hardware.property.CarPropertyManager#subscribePropertyEvents",
6431                     "android.car.hardware.property.CarPropertyManager#unsubscribePropertyEvents",
6432                     "android.car.hardware.property.Subscription.Builder#Builder",
6433                     "android.car.hardware.property.Subscription.Builder#setUpdateRateFastest",
6434                     "android.car.hardware.property.Subscription.Builder#addAreaId",
6435                     "android.car.hardware.property.Subscription.Builder#build",
6436                     "android.car.hardware.property.Subscription.Builder#"
6437                             + "setVariableUpdateRateEnabled",
6438                     "android.car.hardware.property.CarPropertyConfig#getAreaIdConfig",
6439                     "android.car.hardware.property.AreaIdConfig#isVariableUpdateRateSupported"
6440             })
6441     @RequiresFlagsEnabled({Flags.FLAG_BATCHED_SUBSCRIPTIONS, Flags.FLAG_VARIABLE_UPDATE_RATE})
6442     public void testSubscribePropertyEventsForContinuousProperty_enableVUR() throws Exception {
6443         runWithShellPermissionIdentity(
6444                 () -> {
6445                     int vehicleSpeed = VehiclePropertyIds.PERF_VEHICLE_SPEED;
6446                     CarPropertyConfig<?> carPropertyConfig =
6447                             mCarPropertyManager.getCarPropertyConfig(
6448                                     VehiclePropertyIds.PERF_VEHICLE_SPEED);
6449                     assumeTrue("The CarPropertyConfig of vehicle speed does not exist",
6450                             carPropertyConfig != null);
6451 
6452                     // For global property, config for areaId: 0 must exist.
6453                     AreaIdConfig areaIdConfig = carPropertyConfig.getAreaIdConfig(0);
6454                     boolean vurSupported = areaIdConfig.isVariableUpdateRateSupported();
6455                     assumeTrue("Variable Update Rate is not supported for PERF_VEHICLE_SPEED",
6456                             vurSupported);
6457 
6458                     long bufferMillis = 1_000; // 1 second
6459                     long timeoutMillis = generateTimeoutMillis(carPropertyConfig.getMinSampleRate(),
6460                             bufferMillis);
6461                     DuplicatePropertyEventChecker vurEventCounter =
6462                             new DuplicatePropertyEventChecker();
6463                     CarPropertyEventCounter noVurEventCounter = new CarPropertyEventCounter(
6464                             timeoutMillis);
6465 
6466                     Subscription speedSubscription = new Subscription
6467                             .Builder(vehicleSpeed)
6468                             .setUpdateRateUi()
6469                             .addAreaId(VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL).build();
6470                     Subscription noVurSpeedSubscription = new Subscription
6471                             .Builder(vehicleSpeed)
6472                             .setUpdateRateUi()
6473                             .addAreaId(VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL)
6474                             .setVariableUpdateRateEnabled(false).build();
6475 
6476                     mCarPropertyManager.subscribePropertyEvents(
6477                             List.of(noVurSpeedSubscription), /* callbackExecutor= */ null,
6478                             noVurEventCounter);
6479                     mCarPropertyManager.subscribePropertyEvents(
6480                             List.of(speedSubscription), /* callbackExecutor= */ null,
6481                             vurEventCounter);
6482 
6483                     noVurEventCounter.resetCountDownLatch(UI_RATE_EVENT_COUNTER);
6484                     // Wait for no VUR subscription to receive some events.
6485                     noVurEventCounter.assertOnChangeEventCalled();
6486 
6487                     // Subscribe VUR last and unsubscribe VUR first so that it always gets less
6488                     // event even if the property is changing all the time.
6489                     mCarPropertyManager.unregisterCallback(vurEventCounter);
6490                     mCarPropertyManager.unregisterCallback(noVurEventCounter);
6491 
6492                     assertWithMessage("Subscription with Variable Update Rate enabled must not "
6493                             + "receive more events than subscription with VUR disabled").that(
6494                                     vurEventCounter.receivedEvent(vehicleSpeed)
6495                             ).isAtMost(noVurEventCounter.receivedEvent(vehicleSpeed));
6496                     assertWithMessage("Must not receive duplicate property update events when "
6497                             + "VUR is enabled").that(vurEventCounter.getDuplicateValue()).isNull();
6498                 });
6499     }
6500 
6501     @Test
6502     @ApiTest(
6503             apis = {
6504                     "android.car.hardware.property.CarPropertyManager#subscribePropertyEvents",
6505                     "android.car.hardware.property.CarPropertyManager#unsubscribePropertyEvents",
6506                     "android.car.hardware.property.Subscription.Builder#Builder",
6507                     "android.car.hardware.property.Subscription.Builder#setUpdateRateFastest",
6508                     "android.car.hardware.property.Subscription.Builder#addAreaId",
6509                     "android.car.hardware.property.Subscription.Builder#build",
6510                     "android.car.hardware.property.Subscription.Builder#"
6511                             + "setVariableUpdateRateEnabled",
6512                     "android.car.hardware.property.Subscription.Builder#"
6513                             + "setResolution",
6514                     "android.car.hardware.property.CarPropertyConfig#getAreaIdConfig",
6515                     "android.car.hardware.property.AreaIdConfig#isVariableUpdateRateSupported"
6516             })
6517     @RequiresFlagsEnabled({Flags.FLAG_BATCHED_SUBSCRIPTIONS, Flags.FLAG_VARIABLE_UPDATE_RATE,
6518             Flags.FLAG_SUBSCRIPTION_WITH_RESOLUTION})
6519     public void testSubscribePropertyEventsForContinuousProperty_withResolution() throws Exception {
6520         runWithShellPermissionIdentity(
6521                 () -> {
6522                     int propId = VehiclePropertyIds.ENV_OUTSIDE_TEMPERATURE;
6523                     CarPropertyConfig<?> carPropertyConfig =
6524                             mCarPropertyManager.getCarPropertyConfig(propId);
6525                     assumeTrue("The CarPropertyConfig of outside temperature does not exist",
6526                             carPropertyConfig != null);
6527 
6528                     long bufferMillis = 1_000; // 1 second
6529                     long timeoutMillis = generateTimeoutMillis(carPropertyConfig.getMinSampleRate(),
6530                             bufferMillis);
6531                     CarPropertyEventCounter eventCounter = new CarPropertyEventCounter(
6532                             timeoutMillis);
6533 
6534                     Subscription speedSubscription = new Subscription
6535                             .Builder(propId)
6536                             .setUpdateRateUi()
6537                             .addAreaId(VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL)
6538                             .setVariableUpdateRateEnabled(false)
6539                             .setResolution(10.0f)
6540                             .build();
6541 
6542                     mCarPropertyManager.subscribePropertyEvents(
6543                             List.of(speedSubscription), /* callbackExecutor= */ null,
6544                             eventCounter);
6545 
6546                     eventCounter.resetCountDownLatch(UI_RATE_EVENT_COUNTER);
6547                     // Wait for subscription to receive some events.
6548                     eventCounter.assertOnChangeEventCalled();
6549 
6550                     mCarPropertyManager.unregisterCallback(eventCounter);
6551 
6552                     for (CarPropertyValue<?> carPropertyValue :
6553                             eventCounter.getReceivedCarPropertyValues()) {
6554                         assertWithMessage("Incoming CarPropertyValue objects should have a value "
6555                                 + "rounded to 10")
6556                                 .that(((Float) carPropertyValue.getValue()).intValue() % 10 == 0)
6557                                 .isTrue();
6558                     }
6559                 });
6560     }
6561 
6562     @Test
6563     @ApiTest(
6564             apis = {
6565                     "android.car.hardware.property.CarPropertyManager#subscribePropertyEvents",
6566                     "android.car.hardware.property.CarPropertyManager#unsubscribePropertyEvents",
6567                     "android.car.hardware.property.Subscription.Builder#Builder",
6568                     "android.car.hardware.property.Subscription.Builder#addAreaId",
6569                     "android.car.hardware.property.Subscription.Builder#build"
6570             })
6571     @RequiresFlagsEnabled(Flags.FLAG_BATCHED_SUBSCRIPTIONS)
6572     public void testSubscribePropertyEventsForOnchangeProperty() throws Exception {
6573         runWithShellPermissionIdentity(
6574                 () -> {
6575                     // Test for on_change properties
6576                     int nightMode = VehiclePropertyIds.NIGHT_MODE;
6577                     CarPropertyConfig<?> carPropertyConfig =
6578                             mCarPropertyManager.getCarPropertyConfig(nightMode);
6579                     // Night mode is required in CDD.
6580                     assertWithMessage("Night mode property is not supported")
6581                             .that(carPropertyConfig).isNotNull();
6582 
6583                     CarPropertyEventCounter listener = new CarPropertyEventCounter();
6584                     listener.resetCountDownLatch(ONCHANGE_RATE_EVENT_COUNTER);
6585                     mCarPropertyManager.subscribePropertyEvents(
6586                             List.of(new Subscription.Builder(nightMode).addAreaId(0).build()),
6587                             /* callbackExecutor= */ null, listener);
6588 
6589                     listener.assertOnChangeEventCalled();
6590                     assertWithMessage("Must receive expected number of initial value events").that(
6591                             listener.receivedEvent(nightMode)).isEqualTo(1);
6592 
6593                     mCarPropertyManager.unsubscribePropertyEvents(listener);
6594                 });
6595     }
6596 
6597     @Test
6598     @ApiTest(
6599             apis = {
6600                     "android.car.hardware.property.CarPropertyManager#subscribePropertyEvents",
6601                     "android.car.hardware.property.CarPropertyManager#unsubscribePropertyEvents",
6602                     "android.car.hardware.property.Subscription.Builder#Builder",
6603                     "android.car.hardware.property.Subscription.Builder#addAreaId",
6604                     "android.car.hardware.property.Subscription.Builder#build"
6605             })
6606     @RequiresFlagsEnabled({Flags.FLAG_BATCHED_SUBSCRIPTIONS,
6607             Flags.FLAG_ALWAYS_SEND_INITIAL_VALUE_EVENT})
6608     public void testSubscribePropertyEventsForOnchangeProperty_alwaysReceiveInitEvent()
6609             throws Exception {
6610         assumeTrue("Skipped for target SDK version <= Android V",
6611                 mContext.getApplicationInfo().targetSdkVersion
6612                         > Build.VERSION_CODES.VANILLA_ICE_CREAM);
6613 
6614         runWithShellPermissionIdentity(
6615                 () -> {
6616                     // Test for on_change properties
6617                     int nightModePropId = VehiclePropertyIds.NIGHT_MODE;
6618                     CarPropertyConfig<?> carPropertyConfig =
6619                             mCarPropertyManager.getCarPropertyConfig(nightModePropId);
6620                     // Night mode is required in CDD.
6621                     assertWithMessage("Night mode property is not supported")
6622                             .that(carPropertyConfig).isNotNull();
6623 
6624                     CarPropertyEventCounter listener = new CarPropertyEventCounter();
6625 
6626                     // If we register the same listener multiple times, we still expect to
6627                     // receive the initial value event for every registration.
6628                     for (int i = 0; i < 5; i++) {
6629                         listener.resetCountDownLatch(ONCHANGE_RATE_EVENT_COUNTER);
6630                         listener.resetReceivedEvents();
6631 
6632                         mCarPropertyManager.subscribePropertyEvents(
6633                                 List.of(new Subscription.Builder(nightModePropId)
6634                                         .addAreaId(0).build()),
6635                                 /* callbackExecutor= */ null, listener);
6636 
6637                         listener.assertOnChangeEventCalled();
6638                         assertWithMessage("Must receive expected number of initial value events")
6639                                 .that(listener.receivedEvent(nightModePropId)).isEqualTo(1);
6640                     }
6641 
6642                     mCarPropertyManager.unsubscribePropertyEvents(listener);
6643                 });
6644     }
6645 
6646     @Test
6647     @ApiTest(
6648             apis = {
6649                     "android.car.hardware.property.CarPropertyManager#subscribePropertyEvents",
6650                     "android.car.hardware.property.CarPropertyManager#unregisterCallback"
6651             })
6652     @RequiresFlagsEnabled({Flags.FLAG_BATCHED_SUBSCRIPTIONS, Flags.FLAG_VARIABLE_UPDATE_RATE})
6653     public void testSubscribePropertyEvents_withPropertyIdCallback() throws Exception {
6654         runWithShellPermissionIdentity(
6655                 () -> {
6656                     // Test for on_change properties
6657                     int tirePressure = VehiclePropertyIds.TIRE_PRESSURE;
6658                     CarPropertyConfig<?> carPropertyConfig =
6659                             mCarPropertyManager.getCarPropertyConfig(tirePressure);
6660 
6661                     assumeFalse("Tire pressure property is not supported",
6662                             carPropertyConfig == null);
6663 
6664                     int areaIdCount = carPropertyConfig.getAreaIdConfigs().size();
6665 
6666                     assertWithMessage("No area IDs are defined for tire pressure").that(areaIdCount)
6667                             .isNotEqualTo(0);
6668 
6669                     // We should receive the current tire pressure value for all areaIds.
6670                     CarPropertyEventCounter listener = new CarPropertyEventCounter();
6671                     listener.resetCountDownLatch(areaIdCount);
6672                     mCarPropertyManager.subscribePropertyEvents(tirePressure, listener);
6673 
6674                     // VUR might be enabled if property supports it, we only guarantee to receive
6675                     // the initial property value events.
6676                     listener.assertOnChangeEventCalled();
6677                     assertWithMessage("Must receive expected number of initial value events").that(
6678                             listener.receivedEvent(tirePressure)).isAtLeast(areaIdCount);
6679 
6680                     mCarPropertyManager.unregisterCallback(listener);
6681                 }, Car.PERMISSION_TIRES);
6682     }
6683 
6684     @Test
6685     @ApiTest(
6686             apis = {
6687                     "android.car.hardware.property.CarPropertyManager#subscribePropertyEvents",
6688                     "android.car.hardware.property.CarPropertyManager#unregisterCallback"
6689             })
6690     @RequiresFlagsEnabled({Flags.FLAG_BATCHED_SUBSCRIPTIONS, Flags.FLAG_VARIABLE_UPDATE_RATE})
6691     public void testSubscribePropertyEvents_withPropertyIdAreaIdCallback() throws Exception {
6692         runWithShellPermissionIdentity(
6693                 () -> {
6694                     // Test for on_change properties
6695                     int tirePressure = VehiclePropertyIds.TIRE_PRESSURE;
6696                     CarPropertyConfig<Float> carPropertyConfig = (CarPropertyConfig<Float>)
6697                             mCarPropertyManager.getCarPropertyConfig(tirePressure);
6698 
6699                     assumeFalse("Tire pressure property is not supported",
6700                             carPropertyConfig == null);
6701 
6702                     List<AreaIdConfig<Float>> areaIdConfigs = carPropertyConfig.getAreaIdConfigs();
6703                     int areaIdCount = areaIdConfigs.size();
6704 
6705                     assertWithMessage("No area IDs are defined for tire pressure").that(areaIdCount)
6706                             .isNotEqualTo(0);
6707 
6708                     // We test the first areaId.
6709                     int areaId = areaIdConfigs.get(0).getAreaId();
6710 
6711                     // We should receive the current tire pressure value for all areaIds.
6712                     CarPropertyEventCounter listener = new CarPropertyEventCounter();
6713                     listener.resetCountDownLatch(1);
6714                     mCarPropertyManager.subscribePropertyEvents(tirePressure, areaId, listener);
6715 
6716                     // VUR might be enabled if property supports it, we only guarantee to receive
6717                     // the initial property value events.
6718                     listener.assertOnChangeEventCalled();
6719                     assertWithMessage("Must receive expected number of initial value events").that(
6720                             listener.receivedEvent(tirePressure)).isAtLeast(1);
6721 
6722                     mCarPropertyManager.unregisterCallback(listener);
6723                 }, Car.PERMISSION_TIRES);
6724     }
6725 
6726     @Test
6727     @ApiTest(
6728             apis = {
6729                     "android.car.hardware.property.CarPropertyManager#subscribePropertyEvents",
6730                     "android.car.hardware.property.CarPropertyManager#unregisterCallback"
6731             })
6732     @RequiresFlagsEnabled({Flags.FLAG_BATCHED_SUBSCRIPTIONS, Flags.FLAG_VARIABLE_UPDATE_RATE})
6733     public void testSubscribePropertyEvents_withPropertyIdUpdateRateHzCallback() throws Exception {
6734         runWithShellPermissionIdentity(
6735                 () -> {
6736                     // Test for on_change properties
6737                     int tirePressure = VehiclePropertyIds.TIRE_PRESSURE;
6738                     CarPropertyConfig<?> carPropertyConfig =
6739                             mCarPropertyManager.getCarPropertyConfig(tirePressure);
6740 
6741                     assumeFalse("Tire pressure property is not supported",
6742                             carPropertyConfig == null);
6743 
6744                     int areaIdCount = carPropertyConfig.getAreaIdConfigs().size();
6745 
6746                     assertWithMessage("No area IDs are defined for tire pressure").that(areaIdCount)
6747                             .isNotEqualTo(0);
6748 
6749                     // We should receive the current tire pressure value for all areaIds.
6750                     CarPropertyEventCounter listener = new CarPropertyEventCounter();
6751                     listener.resetCountDownLatch(areaIdCount);
6752                     mCarPropertyManager.subscribePropertyEvents(
6753                             tirePressure, /* updateRateHz= */ 10f, listener);
6754 
6755                     // VUR might be enabled if property supports it, we only guarantee to receive
6756                     // the initial property value events.
6757                     listener.assertOnChangeEventCalled();
6758                     assertWithMessage("Must receive expected number of initial value events").that(
6759                             listener.receivedEvent(tirePressure)).isAtLeast(areaIdCount);
6760 
6761                     mCarPropertyManager.unregisterCallback(listener);
6762                 }, Car.PERMISSION_TIRES);
6763     }
6764 
6765 
6766     @Test
6767     @ApiTest(
6768             apis = {
6769                     "android.car.hardware.property.CarPropertyManager#subscribePropertyEvents",
6770                     "android.car.hardware.property.CarPropertyManager#unregisterCallback"
6771             })
6772     @RequiresFlagsEnabled({Flags.FLAG_BATCHED_SUBSCRIPTIONS, Flags.FLAG_VARIABLE_UPDATE_RATE})
6773     public void testSubscribePropertyEvents_withPropertyIdAreaIdUpdateRateHzCallback()
6774             throws Exception {
6775         runWithShellPermissionIdentity(
6776                 () -> {
6777                     // Test for on_change properties
6778                     int tirePressure = VehiclePropertyIds.TIRE_PRESSURE;
6779                     CarPropertyConfig<Float> carPropertyConfig = (CarPropertyConfig<Float>)
6780                             mCarPropertyManager.getCarPropertyConfig(tirePressure);
6781 
6782                     assumeFalse("Tire pressure property is not supported",
6783                             carPropertyConfig == null);
6784 
6785                     List<AreaIdConfig<Float>> areaIdConfigs = carPropertyConfig.getAreaIdConfigs();
6786                     int areaIdCount = areaIdConfigs.size();
6787 
6788                     assertWithMessage("No area IDs are defined for tire pressure").that(areaIdCount)
6789                             .isNotEqualTo(0);
6790 
6791                     // We test the first areaId.
6792                     int areaId = areaIdConfigs.get(0).getAreaId();
6793                     CarPropertyEventCounter listener = new CarPropertyEventCounter();
6794                     listener.resetCountDownLatch(1);
6795                     mCarPropertyManager.subscribePropertyEvents(
6796                             tirePressure, areaId, UI_RATE_EVENT_COUNTER, listener);
6797 
6798                     // VUR might be enabled if property supports it, we only guarantee to receive
6799                     // the initial property value events.
6800                     listener.assertOnChangeEventCalled();
6801                     assertWithMessage("Must receive expected number of property events").that(
6802                             listener.receivedEvent(tirePressure)).isAtLeast(1);
6803 
6804                     mCarPropertyManager.unregisterCallback(listener);
6805                 }, Car.PERMISSION_TIRES);
6806     }
6807 
6808     @Test
6809     @ApiTest(
6810             apis = {
6811                 "android.car.hardware.property.CarPropertyManager#registerCallback"
6812             })
6813     public void testRegisterCallbackWithInvalidProp() throws Exception {
6814         runWithShellPermissionIdentity(() -> {
6815             int invalidPropertyId = -1;
6816 
6817             assertThat(mCarPropertyManager.registerCallback(
6818                     new CarPropertyEventCounter(), invalidPropertyId, /* updateRateHz= */ 0))
6819                     .isFalse();
6820         });
6821     }
6822 
6823     @Test
6824     @ApiTest(
6825             apis = {
6826                 "android.car.hardware.property.CarPropertyManager#getCarPropertyConfig",
6827                 "android.car.hardware.property.CarPropertyManager#registerCallback",
6828                 "android.car.hardware.property.CarPropertyManager#unregisterCallback"
6829             })
6830     public void testRegisterCallback() throws Exception {
6831         runWithShellPermissionIdentity(
6832                 () -> {
6833                     int vehicleSpeed = VehiclePropertyIds.PERF_VEHICLE_SPEED;
6834                     CarPropertyConfig<?> carPropertyConfig =
6835                             mCarPropertyManager.getCarPropertyConfig(
6836                                     VehiclePropertyIds.PERF_VEHICLE_SPEED);
6837                     long bufferMillis = 1_000; // 1 second
6838                     // timeoutMillis is set to the maximum expected time needed to receive the
6839                     // required number of PERF_VEHICLE_SPEED events for test. If the test does not
6840                     // receive the required number of events before the timeout expires, it fails.
6841                     long timeoutMillis = generateTimeoutMillis(carPropertyConfig.getMinSampleRate(),
6842                             bufferMillis);
6843                     CarPropertyEventCounter speedListenerUI =
6844                             new CarPropertyEventCounter(timeoutMillis);
6845                     CarPropertyEventCounter speedListenerFast = new CarPropertyEventCounter();
6846 
6847                     assertThat(speedListenerUI.receivedEvent(vehicleSpeed)).isEqualTo(NO_EVENTS);
6848                     assertThat(speedListenerUI.receivedError(vehicleSpeed)).isEqualTo(NO_EVENTS);
6849                     assertThat(speedListenerUI.receivedErrorWithErrorCode(vehicleSpeed))
6850                             .isEqualTo(NO_EVENTS);
6851                     assertThat(speedListenerFast.receivedEvent(vehicleSpeed)).isEqualTo(NO_EVENTS);
6852                     assertThat(speedListenerFast.receivedError(vehicleSpeed)).isEqualTo(NO_EVENTS);
6853                     assertThat(speedListenerFast.receivedErrorWithErrorCode(vehicleSpeed))
6854                             .isEqualTo(NO_EVENTS);
6855 
6856                     speedListenerUI.resetCountDownLatch(UI_RATE_EVENT_COUNTER);
6857                     mCarPropertyManager.registerCallback(
6858                             speedListenerUI, vehicleSpeed, CarPropertyManager.SENSOR_RATE_UI);
6859                     mCarPropertyManager.registerCallback(
6860                             speedListenerFast,
6861                             vehicleSpeed,
6862                             CarPropertyManager.SENSOR_RATE_FASTEST);
6863                     speedListenerUI.assertOnChangeEventCalled();
6864                     mCarPropertyManager.unregisterCallback(speedListenerUI);
6865                     mCarPropertyManager.unregisterCallback(speedListenerFast);
6866 
6867                     assertThat(speedListenerUI.receivedEvent(vehicleSpeed))
6868                             .isGreaterThan(NO_EVENTS);
6869                     assertThat(speedListenerFast.receivedEvent(vehicleSpeed))
6870                             .isAtLeast(speedListenerUI.receivedEvent(vehicleSpeed));
6871                     // The test did not change property values, it should not get error with error
6872                     // codes.
6873                     assertThat(speedListenerUI.receivedErrorWithErrorCode(vehicleSpeed))
6874                             .isEqualTo(NO_EVENTS);
6875                     assertThat(speedListenerFast.receivedErrorWithErrorCode(vehicleSpeed))
6876                             .isEqualTo(NO_EVENTS);
6877 
6878                     // Test for on_change properties
6879                     int nightMode = VehiclePropertyIds.NIGHT_MODE;
6880                     CarPropertyEventCounter nightModeListener = new CarPropertyEventCounter();
6881                     nightModeListener.resetCountDownLatch(ONCHANGE_RATE_EVENT_COUNTER);
6882                     mCarPropertyManager.registerCallback(nightModeListener, nightMode, 0);
6883                     nightModeListener.assertOnChangeEventCalled();
6884                     assertThat(nightModeListener.receivedEvent(nightMode)).isEqualTo(1);
6885                     mCarPropertyManager.unregisterCallback(nightModeListener);
6886                 });
6887     }
6888 
6889     @ApiTest(
6890             apis = {
6891                     "android.car.hardware.property.CarPropertyManager#subscribePropertyEvents",
6892                     "android.car.hardware.property.CarPropertyManager#unsubscribePropertyEvents"
6893             })
6894     @Test
6895     @RequiresFlagsEnabled({Flags.FLAG_BATCHED_SUBSCRIPTIONS, Flags.FLAG_VARIABLE_UPDATE_RATE})
6896     public void testUnsubscribePropertyEvents() throws Exception {
6897         runWithShellPermissionIdentity(
6898                 () -> {
6899                     int vehicleSpeed = VehiclePropertyIds.PERF_VEHICLE_SPEED;
6900                     CarPropertyEventCounter speedListenerNormal = new CarPropertyEventCounter();
6901                     CarPropertyEventCounter speedListenerUI = new CarPropertyEventCounter();
6902 
6903                     // Disable VUR so that we can receive multiple events.
6904                     Subscription normalRateSubscription = new Subscription.Builder(vehicleSpeed)
6905                             .setUpdateRateNormal().setVariableUpdateRateEnabled(false).build();
6906                     mCarPropertyManager.subscribePropertyEvents(List.of(normalRateSubscription),
6907                             /* callbackExecutor= */ null, speedListenerNormal);
6908 
6909                     // test on unregistering a callback that was never registered
6910                     mCarPropertyManager.unsubscribePropertyEvents(speedListenerUI);
6911 
6912                     // Disable VUR so that we can receive multiple events.
6913                     Subscription uiRateSubscription = new Subscription.Builder(vehicleSpeed)
6914                             .setUpdateRateUi().setVariableUpdateRateEnabled(false).build();
6915                     mCarPropertyManager.subscribePropertyEvents(List.of(uiRateSubscription),
6916                             /* callbackExecutor= */ null, speedListenerUI);
6917 
6918                     speedListenerUI.resetCountDownLatch(UI_RATE_EVENT_COUNTER);
6919                     speedListenerUI.assertOnChangeEventCalled();
6920                     mCarPropertyManager.unsubscribePropertyEvents(vehicleSpeed,
6921                             speedListenerNormal);
6922 
6923                     int currentEventUI = speedListenerUI.receivedEvent(vehicleSpeed);
6924                     // Because we copy the callback outside the lock, so even after
6925                     // unsubscribe, one callback that is already copied out still might be
6926                     // called. As a result, we verify that the callback is not called more than
6927                     // once.
6928                     speedListenerNormal.assertOnChangeEventNotCalledWithinMs(WAIT_CALLBACK);
6929 
6930                     assertThat(speedListenerUI.receivedEvent(vehicleSpeed))
6931                             .isNotEqualTo(currentEventUI);
6932 
6933                     mCarPropertyManager.unsubscribePropertyEvents(speedListenerUI);
6934                     speedListenerUI.assertOnChangeEventNotCalledWithinMs(WAIT_CALLBACK);
6935 
6936                     currentEventUI = speedListenerUI.receivedEvent(vehicleSpeed);
6937                     assertThat(speedListenerUI.receivedEvent(vehicleSpeed))
6938                             .isEqualTo(currentEventUI);
6939                 });
6940     }
6941 
6942     @ApiTest(
6943             apis = {
6944                     "android.car.hardware.property.CarPropertyManager#subscribePropertyEvents",
6945                     "android.car.hardware.property.CarPropertyManager#unsubscribePropertyEvents"
6946             })
6947     @Test
6948     @RequiresFlagsEnabled(Flags.FLAG_BATCHED_SUBSCRIPTIONS)
6949     public void testBatchedUnsubscribePropertyEvents() throws Exception {
6950         runWithShellPermissionIdentity(
6951                 () -> {
6952                     assumeTrue(
6953                             "WheelTick is not available, skip UnsubscribePropertyEvents test",
6954                             mCarPropertyManager.isPropertyAvailable(
6955                                     VehiclePropertyIds.WHEEL_TICK,
6956                                     VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL));
6957                     int vehicleSpeed = VehiclePropertyIds.PERF_VEHICLE_SPEED;
6958                     int vehicleSpeedDisplay = VehiclePropertyIds.PERF_VEHICLE_SPEED_DISPLAY;
6959                     int wheelTick = VehiclePropertyIds.WHEEL_TICK;
6960                     CarPropertyEventCounter listener = new CarPropertyEventCounter();
6961 
6962                     mCarPropertyManager.subscribePropertyEvents(List.of(
6963                             new Subscription.Builder(vehicleSpeed).setUpdateRateNormal()
6964                                     .addAreaId(VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL)
6965                                     .build(),
6966                             new Subscription.Builder(vehicleSpeedDisplay).setUpdateRateUi()
6967                                     .addAreaId(VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL)
6968                                     .build(),
6969                             new Subscription.Builder(wheelTick).setUpdateRateUi()
6970                                     .addAreaId(VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL)
6971                                     .build()),
6972                             /* callbackExecutor= */ null, listener);
6973                     mCarPropertyManager.unsubscribePropertyEvents(listener);
6974                     listener.assertOnChangeEventNotCalledWithinMs(WAIT_CALLBACK);
6975                 });
6976     }
6977 
6978     @Test
6979     public void testUnregisterCallback() throws Exception {
6980         runWithShellPermissionIdentity(
6981                 () -> {
6982                     int vehicleSpeed = VehiclePropertyIds.PERF_VEHICLE_SPEED;
6983                     CarPropertyEventCounter speedListenerNormal = new CarPropertyEventCounter();
6984                     CarPropertyEventCounter speedListenerUI = new CarPropertyEventCounter();
6985 
6986                     mCarPropertyManager.registerCallback(
6987                             speedListenerNormal,
6988                             vehicleSpeed,
6989                             CarPropertyManager.SENSOR_RATE_NORMAL);
6990 
6991                     // test on unregistering a callback that was never registered
6992                     try {
6993                         mCarPropertyManager.unregisterCallback(speedListenerUI);
6994                     } catch (Exception e) {
6995                         Assert.fail();
6996                     }
6997 
6998                     mCarPropertyManager.registerCallback(
6999                             speedListenerUI, vehicleSpeed, CarPropertyManager.SENSOR_RATE_UI);
7000                     speedListenerUI.resetCountDownLatch(UI_RATE_EVENT_COUNTER);
7001                     speedListenerUI.assertOnChangeEventCalled();
7002                     mCarPropertyManager.unregisterCallback(speedListenerNormal, vehicleSpeed);
7003 
7004                     int currentEventNormal = speedListenerNormal.receivedEvent(vehicleSpeed);
7005                     int currentEventUI = speedListenerUI.receivedEvent(vehicleSpeed);
7006                     // Because we copy the callback outside the lock, so even after
7007                     // unregisterCallback, one callback that is already copied out still might be
7008                     // called. As a result, we verify that the callback is not called more than
7009                     // once.
7010                     speedListenerNormal.assertOnChangeEventNotCalledWithinMs(WAIT_CALLBACK);
7011 
7012                     assertThat(speedListenerUI.receivedEvent(vehicleSpeed))
7013                             .isNotEqualTo(currentEventUI);
7014 
7015                     mCarPropertyManager.unregisterCallback(speedListenerUI);
7016                     speedListenerUI.assertOnChangeEventNotCalledWithinMs(WAIT_CALLBACK);
7017 
7018                     currentEventUI = speedListenerUI.receivedEvent(vehicleSpeed);
7019                     assertThat(speedListenerUI.receivedEvent(vehicleSpeed))
7020                             .isEqualTo(currentEventUI);
7021                 });
7022     }
7023 
7024     @Test
7025     public void testUnregisterWithPropertyId() throws Exception {
7026         runWithShellPermissionIdentity(
7027                 () -> {
7028                     // Ignores the test if wheel_tick property does not exist in the car.
7029                     assumeTrue(
7030                             "WheelTick is not available, skip unregisterCallback test",
7031                             mCarPropertyManager.isPropertyAvailable(
7032                                     VehiclePropertyIds.WHEEL_TICK,
7033                                     VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL));
7034 
7035                     CarPropertyConfig wheelTickConfig =
7036                             mCarPropertyManager.getCarPropertyConfig(VehiclePropertyIds.WHEEL_TICK);
7037                     CarPropertyConfig speedConfig =
7038                             mCarPropertyManager.getCarPropertyConfig(
7039                                     VehiclePropertyIds.PERF_VEHICLE_SPEED);
7040                     float maxSampleRateHz =
7041                             Math.max(
7042                                     wheelTickConfig.getMaxSampleRate(),
7043                                     speedConfig.getMaxSampleRate());
7044                     int eventCounter = getCounterBySampleRate(maxSampleRateHz);
7045 
7046                     // Ignores the test if sampleRates for properties are too low.
7047                     assumeTrue(
7048                             "The SampleRates for properties are too low, "
7049                                     + "skip testUnregisterWithPropertyId test",
7050                             eventCounter != 0);
7051                     CarPropertyEventCounter speedAndWheelTicksListener =
7052                             new CarPropertyEventCounter();
7053 
7054                     // CarService will register them to the maxSampleRate in CarPropertyConfig
7055                     mCarPropertyManager.registerCallback(
7056                             speedAndWheelTicksListener,
7057                             VehiclePropertyIds.PERF_VEHICLE_SPEED,
7058                             CarPropertyManager.SENSOR_RATE_FASTEST);
7059                     mCarPropertyManager.registerCallback(
7060                             speedAndWheelTicksListener,
7061                             VehiclePropertyIds.WHEEL_TICK,
7062                             CarPropertyManager.SENSOR_RATE_FASTEST);
7063                     speedAndWheelTicksListener.resetCountDownLatch(eventCounter);
7064                     speedAndWheelTicksListener.assertOnChangeEventCalled();
7065 
7066                     // Tests unregister the individual property
7067                     mCarPropertyManager.unregisterCallback(
7068                             speedAndWheelTicksListener, VehiclePropertyIds.PERF_VEHICLE_SPEED);
7069 
7070                     // Updates counter after unregistering the PERF_VEHICLE_SPEED
7071                     int wheelTickEventCounter =
7072                             getCounterBySampleRate(wheelTickConfig.getMaxSampleRate());
7073                     speedAndWheelTicksListener.resetCountDownLatch(wheelTickEventCounter);
7074                     speedAndWheelTicksListener.assertOnChangeEventCalled();
7075                     int speedEventCountAfterFirstCountDown =
7076                             speedAndWheelTicksListener.receivedEvent(
7077                                     VehiclePropertyIds.PERF_VEHICLE_SPEED);
7078                     int wheelTickEventCountAfterFirstCountDown =
7079                             speedAndWheelTicksListener.receivedEvent(VehiclePropertyIds.WHEEL_TICK);
7080 
7081                     speedAndWheelTicksListener.resetCountDownLatch(wheelTickEventCounter);
7082                     speedAndWheelTicksListener.assertOnChangeEventCalled();
7083                     int speedEventCountAfterSecondCountDown =
7084                             speedAndWheelTicksListener.receivedEvent(
7085                                     VehiclePropertyIds.PERF_VEHICLE_SPEED);
7086                     int wheelTickEventCountAfterSecondCountDown =
7087                             speedAndWheelTicksListener.receivedEvent(VehiclePropertyIds.WHEEL_TICK);
7088 
7089                     assertThat(speedEventCountAfterFirstCountDown)
7090                             .isEqualTo(speedEventCountAfterSecondCountDown);
7091                     assertThat(wheelTickEventCountAfterSecondCountDown)
7092                             .isGreaterThan(wheelTickEventCountAfterFirstCountDown);
7093                 });
7094     }
7095 
7096     @Test
7097     public void testNoPropertyPermissionsGranted() {
7098         assertWithMessage("CarPropertyManager.getPropertyList()")
7099                 .that(mCarPropertyManager.getPropertyList())
7100                 .isEmpty();
7101     }
7102 
7103     @Test
7104     public void testPermissionReadDriverMonitoringSettingsGranted() {
7105         verifyExpectedPropertiesWhenPermissionsGranted(
7106                 PERMISSION_READ_DRIVER_MONITORING_SETTINGS_PROPERTIES,
7107                 Car.PERMISSION_READ_DRIVER_MONITORING_SETTINGS);
7108     }
7109 
7110     @Test
7111     public void testPermissionControlDriverMonitoringSettingsGranted() {
7112         verifyExpectedPropertiesWhenPermissionsGranted(
7113                 PERMISSION_CONTROL_DRIVER_MONITORING_SETTINGS_PROPERTIES,
7114                 Car.PERMISSION_CONTROL_DRIVER_MONITORING_SETTINGS);
7115     }
7116 
7117     @Test
7118     public void testPermissionReadDriverMonitoringStatesGranted() {
7119         verifyExpectedPropertiesWhenPermissionsGranted(
7120                 PERMISSION_READ_DRIVER_MONITORING_STATES_PROPERTIES,
7121                 Car.PERMISSION_READ_DRIVER_MONITORING_STATES);
7122     }
7123 
7124     @Test
7125     public void testPermissionCarEnergyGranted() {
7126         verifyExpectedPropertiesWhenPermissionsGranted(
7127                 PERMISSION_CAR_ENERGY_PROPERTIES,
7128                 Car.PERMISSION_ENERGY);
7129     }
7130 
7131     @Test
7132     public void testPermissionCarEnergyPortsGranted() {
7133         verifyExpectedPropertiesWhenPermissionsGranted(
7134                 PERMISSION_CAR_ENERGY_PORTS_PROPERTIES,
7135                 Car.PERMISSION_ENERGY_PORTS);
7136     }
7137 
7138     @Test
7139     public void testPermissionCarExteriorEnvironmentGranted() {
7140         verifyExpectedPropertiesWhenPermissionsGranted(
7141                 PERMISSION_CAR_EXTERIOR_ENVIRONMENT_PROPERTIES,
7142                 Car.PERMISSION_EXTERIOR_ENVIRONMENT);
7143     }
7144 
7145     @Test
7146     public void testPermissionCarInfoGranted() {
7147         verifyExpectedPropertiesWhenPermissionsGranted(
7148                 Flags.androidBVehicleProperties() ?
7149                         ImmutableList.<Integer>builder().addAll(PERMISSION_CAR_INFO_PROPERTIES).add(
7150                                 VehiclePropertyIds.INFO_MODEL_TRIM).add(
7151                                 VehiclePropertyIds.INFO_VEHICLE_SIZE_CLASS).build()
7152                         : PERMISSION_CAR_INFO_PROPERTIES,
7153                 Car.PERMISSION_CAR_INFO);
7154     }
7155 
7156     @Test
7157     public void testPermissionCarPowertrainGranted() {
7158         verifyExpectedPropertiesWhenPermissionsGranted(
7159                 PERMISSION_CAR_POWERTRAIN_PROPERTIES,
7160                 Car.PERMISSION_POWERTRAIN);
7161     }
7162 
7163     @Test
7164     public void testPermissionControlCarPowertrainGranted() {
7165         verifyExpectedPropertiesWhenPermissionsGranted(
7166                 PERMISSION_CONTROL_CAR_POWERTRAIN_PROPERTIES,
7167                 Car.PERMISSION_CONTROL_POWERTRAIN);
7168     }
7169 
7170     @Test
7171     public void testPermissionCarSpeedGranted() {
7172         verifyExpectedPropertiesWhenPermissionsGranted(
7173                 PERMISSION_CAR_SPEED_PROPERTIES,
7174                 Car.PERMISSION_SPEED);
7175     }
7176 
7177     @Test
7178     public void testPermissionReadCarDisplayUnitsGranted() {
7179         verifyExpectedPropertiesWhenPermissionsGranted(
7180                 PERMISSION_READ_CAR_DISPLAY_UNITS_PROPERTIES,
7181                 Car.PERMISSION_READ_DISPLAY_UNITS);
7182     }
7183 
7184     @Test
7185     public void testPermissionControlSteeringWheelGranted() {
7186         verifyExpectedPropertiesWhenPermissionsGranted(
7187                 PERMISSION_CONTROL_CAR_STEERING_WHEEL_PROPERTIES,
7188                 Car.PERMISSION_CONTROL_STEERING_WHEEL);
7189     }
7190 
7191     @Test
7192     public void testPermissionControlGloveBoxGranted() {
7193         verifyExpectedPropertiesWhenPermissionsGranted(
7194                 PERMISSION_CONTROL_GLOVE_BOX_PROPERTIES,
7195                 Car.PERMISSION_CONTROL_GLOVE_BOX);
7196     }
7197 
7198     @Test
7199     @RequiresFlagsEnabled(Flags.FLAG_ANDROID_VIC_VEHICLE_PROPERTIES)
7200     public void testPermissionReadCarSeatBeltsGranted() {
7201         verifyExpectedPropertiesWhenPermissionsGranted(
7202                 PERMISSION_READ_CAR_SEAT_BELTS_PROPERTIES,
7203                 Car.PERMISSION_READ_CAR_SEAT_BELTS);
7204     }
7205 
7206     @Test
7207     @RequiresFlagsEnabled(Flags.FLAG_ANDROID_VIC_VEHICLE_PROPERTIES)
7208     public void testPermissionReadImpactSensorsGranted() {
7209         verifyExpectedPropertiesWhenPermissionsGranted(
7210                 PERMISSION_READ_IMPACT_SENSORS_PROPERTIES,
7211                 Car.PERMISSION_READ_IMPACT_SENSORS);
7212     }
7213 
7214     @Test
7215     @RequiresFlagsEnabled(Flags.FLAG_ANDROID_VIC_VEHICLE_PROPERTIES)
7216     public void testPermissionReadCarAirbagsGranted() {
7217         verifyExpectedPropertiesWhenPermissionsGranted(
7218                 PERMISSION_READ_CAR_AIRBAGS_PROPERTIES,
7219                 Car.PERMISSION_READ_CAR_AIRBAGS);
7220     }
7221 
7222     @Test
7223     public void testPermissionControlCarAirbagsGranted() {
7224         verifyExpectedPropertiesWhenPermissionsGranted(
7225                 PERMISSION_CONTROL_CAR_AIRBAGS_PROPERTIES,
7226                 Car.PERMISSION_CONTROL_CAR_AIRBAGS);
7227     }
7228 
7229     @Test
7230     public void testPermissionControlCarSeatsGranted() {
7231         verifyExpectedPropertiesWhenPermissionsGranted(
7232                 PERMISSION_CONTROL_CAR_SEATS_PROPERTIES,
7233                 Car.PERMISSION_CONTROL_CAR_SEATS);
7234     }
7235 
7236     @Test
7237     public void testPermissionIdentificationGranted() {
7238         verifyExpectedPropertiesWhenPermissionsGranted(
7239                 PERMISSION_IDENTIFICATION_PROPERTIES,
7240                 Car.PERMISSION_IDENTIFICATION);
7241     }
7242 
7243     @Test
7244     public void testPermissionMileageGranted() {
7245         verifyExpectedPropertiesWhenPermissionsGranted(
7246                 PERMISSION_MILEAGE_PROPERTIES,
7247                 Car.PERMISSION_MILEAGE);
7248     }
7249 
7250     @Test
7251     public void testPermissionMileage3pGranted() {
7252         verifyExpectedPropertiesWhenPermissionsGranted(
7253                 PERMISSION_MILEAGE_3P_PROPERTIES,
7254                 Car.PERMISSION_MILEAGE_3P);
7255     }
7256 
7257     @Test
7258     public void testPermissionReadSteeringStateGranted() {
7259         if (Flags.vehicleProperty25q23pPermissions()) {
7260             verifyExpectedPropertiesWhenPermissionsGranted(
7261                     PERMISSION_READ_STEERING_STATE_3P_PROPERTIES,
7262                     Car.PERMISSION_READ_STEERING_STATE_3P);
7263         }
7264         verifyExpectedPropertiesWhenPermissionsGranted(
7265                 PERMISSION_READ_STEERING_STATE_PROPERTIES, Car.PERMISSION_READ_STEERING_STATE);
7266     }
7267 
7268     @Test
7269     public void testPermissionCarEngineDetailedGranted() {
7270         verifyExpectedPropertiesWhenPermissionsGranted(
7271                 PERMISSION_CAR_ENGINE_DETAILED_PROPERTIES,
7272                 Car.PERMISSION_CAR_ENGINE_DETAILED);
7273     }
7274 
7275     @Test
7276     public void testPermissionControlEnergyPortsGranted() {
7277         verifyExpectedPropertiesWhenPermissionsGranted(
7278                 PERMISSION_CONTROL_ENERGY_PORTS_PROPERTIES,
7279                 Car.PERMISSION_CONTROL_ENERGY_PORTS);
7280     }
7281 
7282     @Test
7283     public void testPermissionAdjustRangeRemainingGranted() {
7284         verifyExpectedPropertiesWhenPermissionsGranted(
7285                 PERMISSION_ADJUST_RANGE_REMAINING_PROPERTIES,
7286                 Car.PERMISSION_ADJUST_RANGE_REMAINING);
7287     }
7288 
7289     @Test
7290     public void testPermissionTiresGranted() {
7291         verifyExpectedPropertiesWhenPermissionsGranted(
7292                 PERMISSION_TIRES_PROPERTIES,
7293                 Car.PERMISSION_TIRES);
7294     }
7295 
7296     @Test
7297     public void testPermissionExteriorLightsGranted() {
7298         verifyExpectedPropertiesWhenPermissionsGranted(
7299                 PERMISSION_EXTERIOR_LIGHTS_PROPERTIES,
7300                 Car.PERMISSION_EXTERIOR_LIGHTS);
7301     }
7302 
7303     @Test
7304     public void testPermissionCarDynamicsStateGranted() {
7305         verifyExpectedPropertiesWhenPermissionsGranted(
7306                 PERMISSION_CAR_DYNAMICS_STATE_PROPERTIES,
7307                 Car.PERMISSION_CAR_DYNAMICS_STATE);
7308     }
7309 
7310     @Test
7311     @RequiresFlagsEnabled(Flags.FLAG_ANDROID_VIC_VEHICLE_PROPERTIES)
7312     public void testPermissionControlCarDynamicsStateGranted() {
7313         verifyExpectedPropertiesWhenPermissionsGranted(
7314                 PERMISSION_CONTROL_CAR_DYNAMICS_STATE_PROPERTIES,
7315                 Car.PERMISSION_CONTROL_CAR_DYNAMICS_STATE);
7316     }
7317 
7318     @Test
7319     public void testPermissionControlCarClimateGranted() {
7320         verifyExpectedPropertiesWhenPermissionsGranted(
7321                 PERMISSION_CONTROL_CAR_CLIMATE_PROPERTIES,
7322                 Car.PERMISSION_CONTROL_CAR_CLIMATE);
7323     }
7324 
7325     @Test
7326     public void testPermissionControlCarDoorsGranted() {
7327         verifyExpectedPropertiesWhenPermissionsGranted(
7328                 PERMISSION_CONTROL_CAR_DOORS_PROPERTIES,
7329                 Car.PERMISSION_CONTROL_CAR_DOORS);
7330     }
7331 
7332     @Test
7333     public void testPermissionControlCarMirrorsGranted() {
7334         verifyExpectedPropertiesWhenPermissionsGranted(
7335                 PERMISSION_CONTROL_CAR_MIRRORS_PROPERTIES,
7336                 Car.PERMISSION_CONTROL_CAR_MIRRORS);
7337     }
7338 
7339     @Test
7340     public void testPermissionControlCarWindowsGranted() {
7341         verifyExpectedPropertiesWhenPermissionsGranted(
7342                 PERMISSION_CONTROL_CAR_WINDOWS_PROPERTIES,
7343                 Car.PERMISSION_CONTROL_CAR_WINDOWS);
7344     }
7345 
7346     @Test
7347     public void testPermissionReadWindshieldWipersGranted() {
7348         verifyExpectedPropertiesWhenPermissionsGranted(
7349                 PERMISSION_READ_WINDSHIELD_WIPERS_PROPERTIES,
7350                 Car.PERMISSION_READ_WINDSHIELD_WIPERS);
7351     }
7352 
7353     @Test
7354     public void testPermissionControlWindshieldWipersGranted() {
7355         verifyExpectedPropertiesWhenPermissionsGranted(
7356                 PERMISSION_CONTROL_WINDSHIELD_WIPERS_PROPERTIES,
7357                 Car.PERMISSION_CONTROL_WINDSHIELD_WIPERS);
7358     }
7359 
7360     @Test
7361     public void testPermissionControlExteriorLightsGranted() {
7362         verifyExpectedPropertiesWhenPermissionsGranted(
7363                 Flags.androidBVehicleProperties() ? ImmutableList.<Integer>builder().addAll(
7364                         PERMISSION_CONTROL_EXTERIOR_LIGHTS_PROPERTIES).add(
7365                         VehiclePropertyIds.TURN_SIGNAL_SWITCH).add(
7366                         VehiclePropertyIds.TURN_SIGNAL_LIGHT_STATE).build() :
7367                         PERMISSION_CONTROL_EXTERIOR_LIGHTS_PROPERTIES,
7368                 Car.PERMISSION_CONTROL_EXTERIOR_LIGHTS);
7369     }
7370 
7371     @Test
7372     public void testPermissionReadInteriorLightsGranted() {
7373         verifyExpectedPropertiesWhenPermissionsGranted(
7374                 PERMISSION_READ_INTERIOR_LIGHTS_PROPERTIES,
7375                 Car.PERMISSION_READ_INTERIOR_LIGHTS);
7376     }
7377 
7378     @Test
7379     public void testPermissionControlInteriorLightsGranted() {
7380         verifyExpectedPropertiesWhenPermissionsGranted(
7381                 PERMISSION_CONTROL_INTERIOR_LIGHTS_PROPERTIES,
7382                 Car.PERMISSION_CONTROL_INTERIOR_LIGHTS);
7383     }
7384 
7385     @Test
7386     public void testPermissionCarEpochTimeGranted() {
7387         verifyExpectedPropertiesWhenPermissionsGranted(
7388                 PERMISSION_CAR_EPOCH_TIME_PROPERTIES,
7389                 Car.PERMISSION_CAR_EPOCH_TIME);
7390     }
7391 
7392     @Test
7393     public void testPermissionControlCarEnergyGranted() {
7394         verifyExpectedPropertiesWhenPermissionsGranted(
7395                 PERMISSION_CONTROL_CAR_ENERGY_PROPERTIES,
7396                 Car.PERMISSION_CONTROL_CAR_ENERGY);
7397     }
7398 
7399     @Test
7400     public void testPermissionPrivilegedCarInfoGranted() {
7401         verifyExpectedPropertiesWhenPermissionsGranted(
7402                 PERMISSION_PRIVILEGED_CAR_INFO_PROPERTIES,
7403                 Car.PERMISSION_PRIVILEGED_CAR_INFO);
7404     }
7405 
7406     @Test
7407     @RequiresFlagsEnabled(Flags.FLAG_ANDROID_VIC_VEHICLE_PROPERTIES)
7408     public void testPermissionCarDrivingStateGranted() {
7409         verifyExpectedPropertiesWhenPermissionsGranted(
7410                 PERMISSION_CAR_DRIVING_STATE_PROPERTIES,
7411                 Car.PERMISSION_CAR_DRIVING_STATE);
7412     }
7413 
7414     @Test
7415     @RequiresFlagsEnabled(Flags.FLAG_ANDROID_VIC_VEHICLE_PROPERTIES)
7416     public void testPermissionReadValetModeGranted() {
7417         verifyExpectedPropertiesWhenPermissionsGranted(
7418                 PERMISSION_READ_VALET_MODE_PROPERTIES,
7419                 Car.PERMISSION_READ_VALET_MODE);
7420     }
7421 
7422     @Test
7423     @RequiresFlagsEnabled(Flags.FLAG_ANDROID_VIC_VEHICLE_PROPERTIES)
7424     public void testPermissionControlValetModeGranted() {
7425         verifyExpectedPropertiesWhenPermissionsGranted(
7426                 PERMISSION_CONTROL_VALET_MODE_PROPERTIES,
7427                 Car.PERMISSION_CONTROL_VALET_MODE);
7428     }
7429 
7430     @Test
7431     @RequiresFlagsEnabled(Flags.FLAG_ANDROID_VIC_VEHICLE_PROPERTIES)
7432     public void testPermissionReadHeadUpDisplayStatusGranted() {
7433         verifyExpectedPropertiesWhenPermissionsGranted(
7434                 PERMISSION_READ_HEAD_UP_DISPLAY_STATUS_PROPERTIES,
7435                 Car.PERMISSION_READ_HEAD_UP_DISPLAY_STATUS);
7436     }
7437 
7438     @Test
7439     @RequiresFlagsEnabled(Flags.FLAG_ANDROID_VIC_VEHICLE_PROPERTIES)
7440     public void testPermissionControlHeadUpDisplayGranted() {
7441         verifyExpectedPropertiesWhenPermissionsGranted(
7442                 PERMISSION_CONTROL_HEAD_UP_DISPLAY_PROPERTIES,
7443                 Car.PERMISSION_CONTROL_HEAD_UP_DISPLAY);
7444     }
7445 
7446     @Test
7447     public void testPermissionControlDisplayUnitsAndVendorExtensionGranted() {
7448         runWithShellPermissionIdentity(
7449                 () -> {
7450                     for (CarPropertyConfig<?> carPropertyConfig :
7451                             mCarPropertyManager.getPropertyList()) {
7452                         if ((carPropertyConfig.getPropertyId() & VEHICLE_PROPERTY_GROUP_MASK)
7453                                 == VEHICLE_PROPERTY_GROUP_VENDOR) {
7454                             continue;
7455                         }
7456                         assertWithMessage(
7457                                 "%s found in CarPropertyManager#getPropertyList() but was not "
7458                                         + "expected to be exposed by %s and %s",
7459                                 VehiclePropertyIds.toString(carPropertyConfig.getPropertyId()),
7460                                 Car.PERMISSION_CONTROL_DISPLAY_UNITS,
7461                                 Car.PERMISSION_VENDOR_EXTENSION)
7462                                 .that(carPropertyConfig.getPropertyId())
7463                                 .isIn(PERMISSION_CONTROL_DISPLAY_UNITS_VENDOR_EXTENSION_PROPERTIES);
7464                     }
7465                 },
7466                 Car.PERMISSION_CONTROL_DISPLAY_UNITS,
7467                 Car.PERMISSION_VENDOR_EXTENSION);
7468     }
7469 
7470     @Test
7471     public void testPermissionControlDisplayUnitsGranted() {
7472         runWithShellPermissionIdentity(
7473                 () -> {
7474                     assertWithMessage(
7475                             "There must be no exposed properties when only "
7476                                     + "PERMISSION_CONTROL_DISPLAY_UNITS is granted. Found: "
7477                                     + mCarPropertyManager.getPropertyList())
7478                             .that(mCarPropertyManager.getPropertyList())
7479                             .isEmpty();
7480                 },
7481                 Car.PERMISSION_CONTROL_DISPLAY_UNITS);
7482     }
7483 
7484     @Test
7485     public void testVendorPermissionsGranted() {
7486         for (String vendorPermission : VENDOR_PROPERTY_PERMISSIONS) {
7487             runWithShellPermissionIdentity(
7488                     () -> {
7489                         for (CarPropertyConfig<?> carPropertyConfig :
7490                                 mCarPropertyManager.getPropertyList()) {
7491                             assertWithMessage(
7492                                     "There must be no non-vendor properties exposed by vendor "
7493                                             + "permissions. Found: " + VehiclePropertyIds.toString(
7494                                             carPropertyConfig.getPropertyId()) + " exposed by: "
7495                                             + vendorPermission)
7496                                     .that(carPropertyConfig.getPropertyId()
7497                                             & VEHICLE_PROPERTY_GROUP_MASK)
7498                                     .isEqualTo(VEHICLE_PROPERTY_GROUP_VENDOR);
7499                         }
7500                     },
7501                     vendorPermission);
7502         }
7503     }
7504 
7505     @Test
7506     public void testPermissionReadAdasSettingsGranted() {
7507         verifyExpectedPropertiesWhenPermissionsGranted(
7508                 PERMISSION_READ_ADAS_SETTINGS_PROPERTIES,
7509                 Car.PERMISSION_READ_ADAS_SETTINGS);
7510     }
7511 
7512     @Test
7513     public void testPermissionControlAdasSettingsGranted() {
7514         verifyExpectedPropertiesWhenPermissionsGranted(
7515                 PERMISSION_CONTROL_ADAS_SETTINGS_PROPERTIES,
7516                 Car.PERMISSION_CONTROL_ADAS_SETTINGS);
7517     }
7518 
7519     @Test
7520     public void testPermissionReadAdasStatesGranted() {
7521         verifyExpectedPropertiesWhenPermissionsGranted(
7522                 PERMISSION_READ_ADAS_STATES_PROPERTIES,
7523                 Car.PERMISSION_READ_ADAS_STATES);
7524     }
7525 
7526     @Test
7527     public void testPermissionControlAdasStatesGranted() {
7528         verifyExpectedPropertiesWhenPermissionsGranted(
7529                 PERMISSION_CONTROL_ADAS_STATES_PROPERTIES,
7530                 Car.PERMISSION_CONTROL_ADAS_STATES);
7531     }
7532 
7533     @Test
7534     public void testPermissionAccessFineLocationGranted() {
7535         verifyExpectedPropertiesWhenPermissionsGranted(
7536                 PERMISSION_ACCESS_FINE_LOCATION_PROPERTIES,
7537                 ACCESS_FINE_LOCATION);
7538     }
7539 
7540     @Test
7541     @RequiresFlagsEnabled(Flags.FLAG_ANDROID_B_VEHICLE_PROPERTIES)
7542     public void testPermissionReadExteriorLightsGranted() {
7543         verifyExpectedPropertiesWhenPermissionsGranted(
7544                 PERMISSION_READ_EXTERIOR_LIGHTS_PROPERTIES,
7545                 Car.PERMISSION_READ_EXTERIOR_LIGHTS);
7546     }
7547 
7548     @Test
7549     @RequiresFlagsEnabled(Flags.FLAG_ANDROID_B_VEHICLE_PROPERTIES)
7550     public void testPermissionReadCarHornGranted() {
7551         verifyExpectedPropertiesWhenPermissionsGranted(
7552                 PERMISSION_READ_CAR_HORN_PROPERTIES,
7553                 Car.PERMISSION_READ_CAR_HORN);
7554     }
7555 
7556     @Test
7557     @RequiresFlagsEnabled(Flags.FLAG_ANDROID_B_VEHICLE_PROPERTIES)
7558     public void testPermissionControlCarHornGranted() {
7559         verifyExpectedPropertiesWhenPermissionsGranted(
7560                 PERMISSION_CONTROL_CAR_HORN_PROPERTIES,
7561                 Car.PERMISSION_CONTROL_CAR_HORN);
7562     }
7563 
7564     @Test
7565     @RequiresFlagsEnabled(Flags.FLAG_ANDROID_B_VEHICLE_PROPERTIES)
7566     public void testPermissionReadCarPedalsGranted() {
7567         verifyExpectedPropertiesWhenPermissionsGranted(
7568                 PERMISSION_READ_CAR_PEDALS_PROPERTIES,
7569                 Car.PERMISSION_READ_CAR_PEDALS);
7570     }
7571 
7572     @Test
7573     @RequiresFlagsEnabled(Flags.FLAG_ANDROID_B_VEHICLE_PROPERTIES)
7574     public void testPermissionReadBrakeInfoGranted() {
7575         verifyExpectedPropertiesWhenPermissionsGranted(
7576                 PERMISSION_READ_BRAKE_INFO_PROPERTIES,
7577                 Car.PERMISSION_READ_BRAKE_INFO);
7578     }
7579 
7580     @Test
7581     public void testPermissionCarPowerGranted() {
7582         verifyNoPropertiesExposedWhenCertainPermissionsGranted(
7583                 Car.PERMISSION_CAR_POWER);
7584     }
7585 
7586     @Test
7587     public void testPermissionVmsPublisherGranted() {
7588         verifyNoPropertiesExposedWhenCertainPermissionsGranted(
7589                 Car.PERMISSION_VMS_PUBLISHER);
7590     }
7591 
7592     @Test
7593     public void testPermissionVmsSubscriberGranted() {
7594         verifyNoPropertiesExposedWhenCertainPermissionsGranted(
7595                 Car.PERMISSION_VMS_SUBSCRIBER);
7596     }
7597 
7598     @Test
7599     public void testPermissionCarDiagnosticReadAllGranted() {
7600         verifyNoPropertiesExposedWhenCertainPermissionsGranted(
7601                 Car.PERMISSION_CAR_DIAGNOSTIC_READ_ALL);
7602     }
7603 
7604     @Test
7605     public void testPermissionCarDiagnosticClearGranted() {
7606         verifyNoPropertiesExposedWhenCertainPermissionsGranted(
7607                 Car.PERMISSION_CAR_DIAGNOSTIC_CLEAR);
7608     }
7609 
7610     private <T> @Nullable CarPropertyManager.SetPropertyRequest<T> addSetPropertyRequest(
7611             List<CarPropertyManager.SetPropertyRequest<?>> setPropertyRequests,
7612             int propId, int areaId, VehiclePropertyVerifier<?> verifier, Class<T> propertyType) {
7613         Collection<T> possibleValues = (Collection<T>) verifier.getPossibleValues(areaId);
7614         if (possibleValues == null || possibleValues.isEmpty()) {
7615             Log.w(TAG, "we can't find possible values to set for property: "
7616                     +  verifier.getPropertyName() + ", areaId: " + areaId
7617                     + ", ignore setting the property.");
7618             return null;
7619         }
7620         CarPropertyManager.SetPropertyRequest<T> spr =
7621                 mCarPropertyManager.generateSetPropertyRequest(propId, areaId,
7622                         possibleValues.iterator().next());
7623         setPropertyRequests.add(spr);
7624         return spr;
7625     }
7626 
7627     private void setAllSupportedReadWritePropertiesAsync(boolean waitForPropertyUpdate) {
7628         runWithShellPermissionIdentity(() -> {
7629             Executor executor = Executors.newFixedThreadPool(1);
7630             Set<Integer> pendingRequests = new ArraySet<>();
7631             List<CarPropertyManager.SetPropertyRequest<?>> setPropertyRequests =
7632                     new ArrayList<>();
7633             Set<PropIdAreaId> requestPropIdAreaIds = new ArraySet<>();
7634 
7635             var verifiers = getAllSupportedVerifiers();
7636             for (int i = 0; i < verifiers.size(); i++) {
7637                 var verifier = verifiers.get(i);
7638                 CarPropertyConfig cfg = verifier.getCarPropertyConfig();
7639                 if (!Flags.areaIdConfigAccess() && cfg.getAccess()
7640                         != CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE) {
7641                     continue;
7642                 }
7643 
7644                 List<? extends AreaIdConfig<?>> areaIdConfigs = cfg.getAreaIdConfigs();
7645                 int propId = cfg.getPropertyId();
7646                 for (AreaIdConfig<?> areaIdConfig : areaIdConfigs) {
7647                     if (Flags.areaIdConfigAccess() && areaIdConfig.getAccess()
7648                             != CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE) {
7649                         continue;
7650                     }
7651                     int areaId = areaIdConfig.getAreaId();
7652                     CarPropertyManager.SetPropertyRequest<?> spr;
7653                     spr = this.addSetPropertyRequest(setPropertyRequests, propId, areaId, verifier,
7654                             cfg.getPropertyType());
7655                     if (spr == null) {
7656                         continue;
7657                     }
7658                     spr.setWaitForPropertyUpdate(waitForPropertyUpdate);
7659                     pendingRequests.add(spr.getRequestId());
7660                     requestPropIdAreaIds.add(new PropIdAreaId(propId, areaId));
7661                 }
7662                 verifier.storeCurrentValues();
7663             }
7664 
7665             int expectedResultCount = pendingRequests.size();
7666 
7667             try {
7668                 TestPropertyAsyncCallback callback = new TestPropertyAsyncCallback(
7669                         pendingRequests);
7670                 mCarPropertyManager.setPropertiesAsync(setPropertyRequests,
7671                         ASYNC_WAIT_TIMEOUT_IN_SEC * 1000,
7672                         /* cancellationSignal= */ null, executor, callback);
7673 
7674                 callback.waitAndFinish();
7675 
7676                 assertThat(callback.getErrorList()).isEmpty();
7677                 int resultCount = callback.getResultList().size();
7678                 assertWithMessage("must receive at least " + expectedResultCount + " results, got "
7679                         + resultCount).that(resultCount).isEqualTo(expectedResultCount);
7680 
7681                 for (PropIdAreaId receivedPropIdAreaId : callback.getReceivedPropIdAreaIds()) {
7682                     assertWithMessage("received unexpected result for " + receivedPropIdAreaId)
7683                             .that(requestPropIdAreaIds).contains(receivedPropIdAreaId);
7684                 }
7685             } finally {
7686                 for (int i = 0; i < verifiers.size(); i++) {
7687                     verifiers.get(i).restoreInitialValues();
7688                 }
7689             }
7690         });
7691     }
7692 
7693     /**
7694      * Test for {@link CarPropertyManager#setPropertiesAsync}
7695      *
7696      * Generates SetPropertyRequest objects for supported writable properties and verifies if there
7697      * are no exceptions or request timeouts.
7698      */
7699     @Test
7700     @ApiTest(apis = {"android.car.hardware.property.CarPropertyManager#setPropertiesAsync",
7701             "android.car.hardware.property.CarPropertyManager#generateSetPropertyRequest",
7702             "android.car.hardware.property.CarPropertyManager.SetPropertyRequest#"
7703                         + "setWaitForPropertyUpdate",
7704             "android.car.hardware.property.CarPropertyManager.SetPropertyResult#getRequestId",
7705             "android.car.hardware.property.CarPropertyManager.SetPropertyResult#getPropertyId",
7706             "android.car.hardware.property.CarPropertyManager.SetPropertyResult#getAreaId",
7707             "android.car.hardware.property.CarPropertyManager.SetPropertyResult#"
7708                         + "getUpdateTimestampNanos"})
7709     public void testSetAllSupportedReadWritePropertiesAsync() throws Exception {
7710         setAllSupportedReadWritePropertiesAsync(true);
7711     }
7712 
7713     /**
7714      * Test for {@link CarPropertyManager#setPropertiesAsync}
7715      *
7716      * Similar to {@link #testSetAllSupportedReadWritePropertiesAsync} but don't wait for property
7717      * update before calling the success callback.
7718      */
7719     @Test
7720     @ApiTest(apis = {"android.car.hardware.property.CarPropertyManager#setPropertiesAsync",
7721             "android.car.hardware.property.CarPropertyManager#generateSetPropertyRequest",
7722             "android.car.hardware.property.CarPropertyManager.SetPropertyRequest#"
7723                         + "setWaitForPropertyUpdate",
7724             "android.car.hardware.property.CarPropertyManager.SetPropertyResult#getRequestId",
7725             "android.car.hardware.property.CarPropertyManager.SetPropertyResult#getPropertyId",
7726             "android.car.hardware.property.CarPropertyManager.SetPropertyResult#getAreaId",
7727             "android.car.hardware.property.CarPropertyManager.SetPropertyResult#"
7728                         + "getUpdateTimestampNanos"})
7729     public void testSetAllSupportedReadWritePropertiesAsyncNoWaitForUpdate() throws Exception {
7730         setAllSupportedReadWritePropertiesAsync(false);
7731     }
7732 
7733     @Test
7734     @ApiTest(apis = {"android.car.hardware.property.CarPropertyManager#generateSetPropertyRequest"})
7735     public void testGenerateSetPropertyRequest() throws Exception {
7736         assertThrows(NullPointerException.class, () -> {
7737             mCarPropertyManager.generateSetPropertyRequest(VehiclePropertyIds.FUEL_LEVEL,
7738                     /* areaId= */ 1, /* value= */ null);
7739         });
7740 
7741         CarPropertyManager.SetPropertyRequest request;
7742         request = mCarPropertyManager.generateSetPropertyRequest(VehiclePropertyIds.FUEL_LEVEL,
7743                 /* areaId= */ 1, /* value= */ Integer.valueOf(1));
7744 
7745         int requestId1 = request.getRequestId();
7746         assertThat(request.getPropertyId()).isEqualTo(VehiclePropertyIds.FUEL_LEVEL);
7747         assertThat(request.getAreaId()).isEqualTo(1);
7748         assertThat(request.getValue()).isEqualTo(1);
7749 
7750         request = mCarPropertyManager.generateSetPropertyRequest(VehiclePropertyIds.INFO_VIN,
7751                 /* areaId= */ 2, /* value= */ new String("1234"));
7752 
7753         int requestId2 = request.getRequestId();
7754         assertThat(request.getPropertyId()).isEqualTo(VehiclePropertyIds.INFO_VIN);
7755         assertThat(request.getAreaId()).isEqualTo(2);
7756         assertThat(request.getValue()).isEqualTo(new String("1234"));
7757         assertWithMessage("generateSetPropertyRequest must generate unique IDs").that(requestId1)
7758                 .isNotEqualTo(requestId2);
7759     }
7760 
7761     @Test
7762     @ApiTest(apis = {"android.car.hardware.property.CarPropertyManager#getProperty"})
7763     public void testGetProperty_multipleRequestsAtOnce_mustNotThrowException() throws Exception {
7764         runWithShellPermissionIdentity(
7765                 () -> {
7766                     // We only allow 16 sync operations at once at car service. The client will
7767                     // try to issue 32 requests at the same time, but 16 of them will be bounced
7768                     // back and will be retried later.
7769                     Executor executor = Executors.newFixedThreadPool(32);
7770                     CountDownLatch cd = new CountDownLatch(32);
7771                     for (int i = 0; i < 32; i++) {
7772                         executor.execute(() -> {
7773                             mCarPropertyManager.getProperty(
7774                                                 VehiclePropertyIds.PERF_VEHICLE_SPEED,
7775                                                 VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL);
7776                             cd.countDown();
7777                         });
7778                     }
7779                     cd.await(ASYNC_WAIT_TIMEOUT_IN_SEC, TimeUnit.SECONDS);
7780                 },
7781                 Car.PERMISSION_SPEED);
7782     }
7783 
7784     @Test
7785     @ApiTest(apis = {"android.car.hardware.property.CarPropertyManager#generateSetPropertyRequest",
7786             "android.car.hardware.property.CarPropertyManager.SetPropertyRequest#setUpdateRateHz",
7787             "android.car.hardware.property.CarPropertyManager.SetPropertyRequest#"
7788                     + "setWaitForPropertyUpdate",
7789             "android.car.hardware.property.CarPropertyManager.SetPropertyRequest#getPropertyId",
7790             "android.car.hardware.property.CarPropertyManager.SetPropertyRequest#getAreaId",
7791             "android.car.hardware.property.CarPropertyManager.SetPropertyRequest#getValue",
7792             "android.car.hardware.property.CarPropertyManager.SetPropertyRequest#getUpdateRateHz",
7793             "android.car.hardware.property.CarPropertyManager.SetPropertyRequest#"
7794                     + "isWaitForPropertyUpdate"})
7795     public void testSetPropertyRequestSettersGetters() throws Exception {
7796         int testPropId = 1;
7797         int testAreaId = 2;
7798         Float valueToSet = Float.valueOf(3.1f);
7799         float testUpdateRateHz = 4.1f;
7800         CarPropertyManager.SetPropertyRequest spr =
7801                 mCarPropertyManager.generateSetPropertyRequest(testPropId, testAreaId, valueToSet);
7802         spr.setUpdateRateHz(testUpdateRateHz);
7803 
7804         assertThat(spr.getPropertyId()).isEqualTo(testPropId);
7805         assertThat(spr.getAreaId()).isEqualTo(testAreaId);
7806         assertThat(spr.getValue()).isEqualTo(valueToSet);
7807         assertThat(spr.getUpdateRateHz()).isEqualTo(testUpdateRateHz);
7808         assertWithMessage("waitForPropertyUpdate is true by default").that(
7809                 spr.isWaitForPropertyUpdate()).isTrue();
7810 
7811         spr.setWaitForPropertyUpdate(false);
7812 
7813         assertThat(spr.isWaitForPropertyUpdate()).isFalse();
7814     }
7815 
7816     private int getCounterBySampleRate(float maxSampleRateHz) {
7817         if (Float.compare(maxSampleRateHz, (float) FAST_OR_FASTEST_EVENT_COUNTER) > 0) {
7818             return FAST_OR_FASTEST_EVENT_COUNTER;
7819         } else if (Float.compare(maxSampleRateHz, (float) UI_RATE_EVENT_COUNTER) > 0) {
7820             return UI_RATE_EVENT_COUNTER;
7821         } else if (Float.compare(maxSampleRateHz, (float) ONCHANGE_RATE_EVENT_COUNTER) > 0) {
7822             return ONCHANGE_RATE_EVENT_COUNTER;
7823         } else {
7824             return 0;
7825         }
7826     }
7827 
7828     // Returns {0} if the property is global property, otherwise query areaId for CarPropertyConfig
7829     private int[] getAreaIdsHelper(CarPropertyConfig config) {
7830         if (config.isGlobalProperty()) {
7831             return new int[]{0};
7832         } else {
7833             return config.getAreaIds();
7834         }
7835     }
7836 
7837     private static class CarPropertyEventCounter implements CarPropertyEventCallback {
7838         private final Object mLock = new Object();
7839         private final Set<CarPropertyValue<?>> mReceivedCarPropertyValues = new ArraySet<>();
7840         @GuardedBy("mLock")
7841         private final SparseArray<Integer> mEventCounter = new SparseArray<>();
7842         @GuardedBy("mLock")
7843         private final SparseArray<Integer> mErrorCounter = new SparseArray<>();
7844         @GuardedBy("mLock")
7845         private final SparseArray<Integer> mErrorWithErrorCodeCounter = new SparseArray<>();
7846         @GuardedBy("mLock")
7847         private int mCounter = FAST_OR_FASTEST_EVENT_COUNTER;
7848         @GuardedBy("mLock")
7849         private CountDownLatch mCountDownLatch = new CountDownLatch(mCounter);
7850         private final long mTimeoutMillis;
7851 
7852         CarPropertyEventCounter(long timeoutMillis) {
7853             mTimeoutMillis = timeoutMillis;
7854         }
7855 
7856         CarPropertyEventCounter() {
7857             this(WAIT_CALLBACK);
7858         }
7859 
7860         public Set<CarPropertyValue<?>> getReceivedCarPropertyValues() {
7861             return mReceivedCarPropertyValues;
7862         }
7863 
7864         public int receivedEvent(int propId) {
7865             int val;
7866             synchronized (mLock) {
7867                 val = mEventCounter.get(propId, 0);
7868             }
7869             return val;
7870         }
7871 
7872         public int receivedError(int propId) {
7873             int val;
7874             synchronized (mLock) {
7875                 val = mErrorCounter.get(propId, 0);
7876             }
7877             return val;
7878         }
7879 
7880         public int receivedErrorWithErrorCode(int propId) {
7881             int val;
7882             synchronized (mLock) {
7883                 val = mErrorWithErrorCodeCounter.get(propId, 0);
7884             }
7885             return val;
7886         }
7887 
7888         @Override
7889         public void onChangeEvent(CarPropertyValue value) {
7890             synchronized (mLock) {
7891                 mReceivedCarPropertyValues.add(value);
7892                 int val = mEventCounter.get(value.getPropertyId(), 0) + 1;
7893                 mEventCounter.put(value.getPropertyId(), val);
7894                 mCountDownLatch.countDown();
7895             }
7896         }
7897 
7898         @Override
7899         public void onErrorEvent(int propId, int zone) {
7900             synchronized (mLock) {
7901                 int val = mErrorCounter.get(propId, 0) + 1;
7902                 mErrorCounter.put(propId, val);
7903             }
7904         }
7905 
7906         @Override
7907         public void onErrorEvent(int propId, int areaId, int errorCode) {
7908             synchronized (mLock) {
7909                 int val = mErrorWithErrorCodeCounter.get(propId, 0) + 1;
7910                 mErrorWithErrorCodeCounter.put(propId, val);
7911             }
7912         }
7913 
7914         public void resetCountDownLatch(int counter) {
7915             synchronized (mLock) {
7916                 mCountDownLatch = new CountDownLatch(counter);
7917                 mCounter = counter;
7918             }
7919         }
7920 
7921         public void resetReceivedEvents() {
7922             synchronized (mLock) {
7923                 mEventCounter.clear();
7924                 mErrorCounter.clear();
7925                 mErrorWithErrorCodeCounter.clear();
7926             }
7927         }
7928 
7929         public void assertOnChangeEventCalled() throws InterruptedException {
7930             CountDownLatch countDownLatch;
7931             int counter;
7932             synchronized (mLock) {
7933                 countDownLatch = mCountDownLatch;
7934                 counter = mCounter;
7935             }
7936             if (!countDownLatch.await(mTimeoutMillis, TimeUnit.MILLISECONDS)) {
7937                 throw new IllegalStateException(
7938                         "Callback is not called "
7939                                 + counter
7940                                 + " times in "
7941                                 + mTimeoutMillis
7942                                 + " ms. It was only called "
7943                                 + (counter - countDownLatch.getCount())
7944                                 + " times.");
7945             }
7946         }
7947 
7948         public void assertOnChangeEventNotCalledWithinMs(long durationInMs)
7949                 throws InterruptedException {
7950             CountDownLatch countDownLatch;
7951             synchronized (mLock) {
7952                 mCountDownLatch = new CountDownLatch(1);
7953                 countDownLatch = mCountDownLatch;
7954             }
7955             long timeoutMillis = 2 * durationInMs;
7956             long startTimeMillis = SystemClock.uptimeMillis();
7957             while (true) {
7958                 if (countDownLatch.await(durationInMs, TimeUnit.MILLISECONDS)) {
7959                     if (SystemClock.uptimeMillis() - startTimeMillis > timeoutMillis) {
7960                         // If we are still receiving events when timeout happens, the test
7961                         // failed.
7962                         throw new IllegalStateException(
7963                                 "We are still receiving callback within "
7964                                         + durationInMs
7965                                         + " seconds after "
7966                                         + timeoutMillis
7967                                         + " ms.");
7968                     }
7969                     // Receive a event within the time period. This means there are still events
7970                     // being generated. Wait for another period and hope the events stop.
7971                     synchronized (mLock) {
7972                         mCountDownLatch = new CountDownLatch(1);
7973                         countDownLatch = mCountDownLatch;
7974                     }
7975                 } else {
7976                     break;
7977                 }
7978             }
7979         }
7980     }
7981 
7982     private static boolean isSystemProperty(int propertyId) {
7983         return (propertyId & VEHICLE_PROPERTY_GROUP_MASK) == VEHICLE_PROPERTY_GROUP_SYSTEM;
7984     }
7985 }
7986