| /* |
| * Copyright (C) 2019 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package android.car.cts; |
| |
| import static com.google.common.truth.Truth.assertThat; |
| import static com.google.common.truth.Truth.assertWithMessage; |
| |
| import static org.testng.Assert.assertThrows; |
| |
| import android.app.UiAutomation; |
| import android.car.Car; |
| import android.car.EvConnectorType; |
| import android.car.FuelType; |
| import android.car.PortLocationType; |
| import android.car.VehicleAreaSeat; |
| import android.car.VehicleAreaType; |
| import android.car.VehicleAreaWheel; |
| import android.car.VehicleGear; |
| import android.car.VehicleIgnitionState; |
| import android.car.VehiclePropertyIds; |
| import android.car.VehicleUnit; |
| import android.car.cts.utils.VehiclePropertyVerifier; |
| import android.car.hardware.CarPropertyConfig; |
| import android.car.hardware.CarPropertyValue; |
| import android.car.hardware.property.CarPropertyManager; |
| import android.car.hardware.property.CarPropertyManager.CarPropertyEventCallback; |
| import android.car.hardware.property.VehicleElectronicTollCollectionCardStatus; |
| import android.car.hardware.property.VehicleElectronicTollCollectionCardType; |
| import android.platform.test.annotations.AppModeFull; |
| import android.platform.test.annotations.RequiresDevice; |
| import android.test.suitebuilder.annotation.SmallTest; |
| import android.util.ArraySet; |
| import android.util.SparseArray; |
| |
| import androidx.annotation.GuardedBy; |
| import androidx.test.platform.app.InstrumentationRegistry; |
| import androidx.test.runner.AndroidJUnit4; |
| |
| import com.android.compatibility.common.util.ApiTest; |
| import com.android.compatibility.common.util.CddTest; |
| |
| import com.google.common.collect.ImmutableSet; |
| import com.google.common.collect.Sets; |
| |
| import org.junit.Assert; |
| import org.junit.Assume; |
| import org.junit.Before; |
| import org.junit.Test; |
| import org.junit.runner.RunWith; |
| |
| import java.util.Arrays; |
| import java.util.List; |
| import java.util.concurrent.CountDownLatch; |
| import java.util.concurrent.TimeUnit; |
| import java.util.stream.Collectors; |
| |
| @SmallTest |
| @RequiresDevice |
| @RunWith(AndroidJUnit4.class) |
| @AppModeFull(reason = "Instant apps cannot get car related permissions.") |
| public class CarPropertyManagerTest extends CarApiTestBase { |
| |
| private static final long WAIT_CALLBACK = 1500L; |
| private static final int NO_EVENTS = 0; |
| private static final int ONCHANGE_RATE_EVENT_COUNTER = 1; |
| private static final int UI_RATE_EVENT_COUNTER = 5; |
| private static final int FAST_OR_FASTEST_EVENT_COUNTER = 10; |
| private static final ImmutableSet<Integer> PORT_LOCATION_TYPES = |
| ImmutableSet.<Integer>builder().add(PortLocationType.UNKNOWN, |
| PortLocationType.FRONT_LEFT, PortLocationType.FRONT_RIGHT, |
| PortLocationType.REAR_RIGHT, PortLocationType.REAR_LEFT, |
| PortLocationType.FRONT, PortLocationType.REAR).build(); |
| private static final ImmutableSet<Integer> VEHICLE_GEARS = |
| ImmutableSet.<Integer>builder().add(VehicleGear.GEAR_UNKNOWN, |
| VehicleGear.GEAR_NEUTRAL, VehicleGear.GEAR_REVERSE, |
| VehicleGear.GEAR_PARK, VehicleGear.GEAR_DRIVE, |
| VehicleGear.GEAR_FIRST, VehicleGear.GEAR_SECOND, |
| VehicleGear.GEAR_THIRD, VehicleGear.GEAR_FOURTH, |
| VehicleGear.GEAR_FIFTH, VehicleGear.GEAR_SIXTH, |
| VehicleGear.GEAR_SEVENTH, VehicleGear.GEAR_EIGHTH, |
| VehicleGear.GEAR_NINTH).build(); |
| private static final ImmutableSet<Integer> DISTANCE_DISPLAY_UNITS = |
| ImmutableSet.<Integer>builder().add(VehicleUnit.MILLIMETER, VehicleUnit.METER, |
| VehicleUnit.KILOMETER, VehicleUnit.MILE).build(); |
| private static final ImmutableSet<Integer> VOLUME_DISPLAY_UNITS = |
| ImmutableSet.<Integer>builder().add(VehicleUnit.MILLILITER, VehicleUnit.LITER, |
| VehicleUnit.US_GALLON, VehicleUnit.IMPERIAL_GALLON).build(); |
| private static final ImmutableSet<Integer> PRESSURE_DISPLAY_UNITS = |
| ImmutableSet.<Integer>builder().add(VehicleUnit.KILOPASCAL, VehicleUnit.PSI, |
| VehicleUnit.BAR).build(); |
| private static final ImmutableSet<Integer> BATTERY_DISPLAY_UNITS = |
| ImmutableSet.<Integer>builder().add(VehicleUnit.WATT_HOUR, VehicleUnit.AMPERE_HOURS, |
| VehicleUnit.KILOWATT_HOUR).build(); |
| private static final ImmutableSet<Integer> SPEED_DISPLAY_UNITS = |
| ImmutableSet.<Integer>builder().add(VehicleUnit.METER_PER_SEC, |
| VehicleUnit.MILES_PER_HOUR, VehicleUnit.KILOMETERS_PER_HOUR).build(); |
| private static final ImmutableSet<Integer> TURN_SIGNAL_STATES = |
| ImmutableSet.<Integer>builder().add(/*TurnSignalState.NONE=*/0, |
| /*TurnSignalState.RIGHT=*/1, /*TurnSignalState.LEFT=*/2).build(); |
| private static final ImmutableSet<Integer> VEHICLE_LIGHT_STATES = |
| ImmutableSet.<Integer>builder().add(/*VehicleLightState.OFF=*/0, |
| /*VehicleLightState.ON=*/1, /*VehicleLightState.DAYTIME_RUNNING=*/2).build(); |
| private static final ImmutableSet<Integer> VEHICLE_LIGHT_SWITCHES = |
| ImmutableSet.<Integer>builder().add(/*VehicleLightSwitch.OFF=*/0, |
| /*VehicleLightSwitch.ON=*/1, /*VehicleLightSwitch.DAYTIME_RUNNING=*/2, |
| /*VehicleLightSwitch.AUTOMATIC=*/256).build(); |
| private static final ImmutableSet<Integer> HVAC_TEMPERATURE_DISPLAY_UNITS = |
| ImmutableSet.<Integer>builder().add(VehicleUnit.CELSIUS, |
| VehicleUnit.FAHRENHEIT).build(); |
| private static final ImmutableSet<Integer> SINGLE_HVAC_FAN_DIRECTIONS = ImmutableSet.of( |
| /*VehicleHvacFanDirection.FACE=*/0x1, /*VehicleHvacFanDirection.FLOOR=*/0x2, |
| /*VehicleHvacFanDirection.DEFROST=*/0x4); |
| private static final ImmutableSet<Integer> ALL_POSSIBLE_HVAC_FAN_DIRECTIONS = |
| generateAllPossibleHvacFanDirections(); |
| |
| /** contains property Ids for the properties required by CDD */ |
| private final ArraySet<Integer> mPropertyIds = new ArraySet<>(); |
| private CarPropertyManager mCarPropertyManager; |
| |
| private static ImmutableSet<Integer> generateAllPossibleHvacFanDirections() { |
| ImmutableSet.Builder<Integer> allPossibleFanDirectionsBuilder = ImmutableSet.builder(); |
| for (int i = 1; i <= SINGLE_HVAC_FAN_DIRECTIONS.size(); i++) { |
| allPossibleFanDirectionsBuilder.addAll(Sets.combinations(SINGLE_HVAC_FAN_DIRECTIONS, |
| i).stream().map(hvacFanDirectionCombo -> { |
| Integer possibleHvacFanDirection = 0; |
| for (Integer hvacFanDirection : hvacFanDirectionCombo) { |
| possibleHvacFanDirection |= hvacFanDirection; |
| } |
| return possibleHvacFanDirection; |
| }).collect(Collectors.toList())); |
| } |
| return allPossibleFanDirectionsBuilder.build(); |
| } |
| |
| private static void verifyWheelTickConfigArray(int supportedWheels, int wheelToVerify, |
| int configArrayIndex, int wheelTicksToUm) { |
| if ((supportedWheels & wheelToVerify) != 0) { |
| assertWithMessage( |
| "WHEEL_TICK configArray[" + configArrayIndex |
| + "] must specify the ticks to micrometers for " + wheelToString( |
| wheelToVerify)) |
| .that(wheelTicksToUm) |
| .isGreaterThan(0); |
| } else { |
| assertWithMessage( |
| "WHEEL_TICK configArray[" + configArrayIndex + "] should be zero since " |
| + wheelToString(wheelToVerify) |
| + "is not supported") |
| .that(wheelTicksToUm) |
| .isEqualTo(0); |
| } |
| } |
| |
| private static void verifyWheelTickValue(int supportedWheels, int wheelToVerify, |
| int valueIndex, Long ticks) { |
| if ((supportedWheels & wheelToVerify) == 0) { |
| assertWithMessage( |
| "WHEEL_TICK value[" + valueIndex + "] should be zero since " |
| + wheelToString(wheelToVerify) |
| + "is not supported") |
| .that(ticks) |
| .isEqualTo(0); |
| } |
| } |
| |
| private static String wheelToString(int wheel) { |
| switch (wheel) { |
| case VehicleAreaWheel.WHEEL_LEFT_FRONT: |
| return "WHEEL_LEFT_FRONT"; |
| case VehicleAreaWheel.WHEEL_RIGHT_FRONT: |
| return "WHEEL_RIGHT_FRONT"; |
| case VehicleAreaWheel.WHEEL_RIGHT_REAR: |
| return "WHEEL_RIGHT_REAR"; |
| case VehicleAreaWheel.WHEEL_LEFT_REAR: |
| return "WHEEL_LEFT_REAR"; |
| default: |
| return Integer.toString(wheel); |
| } |
| } |
| |
| private static void adoptSystemLevelPermission(String permission, Runnable verifierRunnable) { |
| UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation(); |
| uiAutomation.adoptShellPermissionIdentity(permission); |
| try { |
| verifierRunnable.run(); |
| } finally { |
| uiAutomation.dropShellPermissionIdentity(); |
| } |
| } |
| |
| @Before |
| public void setUp() throws Exception { |
| super.setUp(); |
| mCarPropertyManager = (CarPropertyManager) getCar().getCarManager(Car.PROPERTY_SERVICE); |
| mPropertyIds.add(VehiclePropertyIds.PERF_VEHICLE_SPEED); |
| mPropertyIds.add(VehiclePropertyIds.GEAR_SELECTION); |
| mPropertyIds.add(VehiclePropertyIds.NIGHT_MODE); |
| mPropertyIds.add(VehiclePropertyIds.PARKING_BRAKE_ON); |
| } |
| |
| /** |
| * Test for {@link CarPropertyManager#getPropertyList()} |
| */ |
| @Test |
| public void testGetPropertyList() { |
| List<CarPropertyConfig> allConfigs = mCarPropertyManager.getPropertyList(); |
| assertThat(allConfigs).isNotNull(); |
| } |
| |
| /** |
| * Test for {@link CarPropertyManager#getPropertyList(ArraySet)} |
| */ |
| @Test |
| public void testGetPropertyListWithArraySet() { |
| List<CarPropertyConfig> requiredConfigs = mCarPropertyManager.getPropertyList(mPropertyIds); |
| // Vehicles need to implement all of those properties |
| assertThat(requiredConfigs.size()).isEqualTo(mPropertyIds.size()); |
| } |
| |
| /** |
| * Test for {@link CarPropertyManager#getCarPropertyConfig(int)} |
| */ |
| @Test |
| public void testGetPropertyConfig() { |
| List<CarPropertyConfig> allConfigs = mCarPropertyManager.getPropertyList(); |
| for (CarPropertyConfig cfg : allConfigs) { |
| assertThat(mCarPropertyManager.getCarPropertyConfig(cfg.getPropertyId())).isNotNull(); |
| } |
| } |
| |
| /** |
| * Test for {@link CarPropertyManager#getAreaId(int, int)} |
| */ |
| @Test |
| public void testGetAreaId() { |
| // For global properties, getAreaId should always return 0. |
| List<CarPropertyConfig> allConfigs = mCarPropertyManager.getPropertyList(); |
| for (CarPropertyConfig cfg : allConfigs) { |
| if (cfg.isGlobalProperty()) { |
| assertThat(mCarPropertyManager.getAreaId(cfg.getPropertyId(), |
| VehicleAreaSeat.SEAT_ROW_1_LEFT)) |
| .isEqualTo(VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL); |
| } else { |
| int[] areaIds = cfg.getAreaIds(); |
| // Because areaId in propConfig must not be overlapped with each other. |
| // The result should be itself. |
| for (int areaIdInConfig : areaIds) { |
| int areaIdByCarPropertyManager = |
| mCarPropertyManager.getAreaId(cfg.getPropertyId(), areaIdInConfig); |
| assertThat(areaIdByCarPropertyManager).isEqualTo(areaIdInConfig); |
| } |
| } |
| } |
| } |
| |
| @Test |
| public void testInvalidMustNotBeImplemented() { |
| assertThat(mCarPropertyManager.getCarPropertyConfig(VehiclePropertyIds.INVALID)).isNull(); |
| } |
| |
| @CddTest(requirement = "2.5.1") |
| @Test |
| public void testMustSupportGearSelection() { |
| VehiclePropertyVerifier.newBuilder(VehiclePropertyIds.GEAR_SELECTION, |
| CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ, |
| VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL, |
| CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE, |
| Integer.class).requireProperty().setPossibleConfigArrayValues( |
| VEHICLE_GEARS).requirePropertyValueTobeInConfigArray().build().verify( |
| mCarPropertyManager); |
| } |
| |
| @CddTest(requirement = "2.5.1") |
| @Test |
| public void testMustSupportNightMode() { |
| VehiclePropertyVerifier.newBuilder(VehiclePropertyIds.NIGHT_MODE, |
| CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ, |
| VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL, |
| CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE, |
| Boolean.class).requireProperty().build().verify(mCarPropertyManager); |
| } |
| |
| @CddTest(requirement = "2.5.1") |
| @Test |
| public void testMustSupportPerfVehicleSpeed() { |
| VehiclePropertyVerifier.newBuilder(VehiclePropertyIds.PERF_VEHICLE_SPEED, |
| CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ, |
| VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL, |
| CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_CONTINUOUS, |
| Float.class).requireProperty().build().verify(mCarPropertyManager); |
| } |
| |
| @Test |
| public void testPerfVehicleSpeedDisplayIfSupported() { |
| VehiclePropertyVerifier.newBuilder(VehiclePropertyIds.PERF_VEHICLE_SPEED_DISPLAY, |
| CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ, |
| VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL, |
| CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_CONTINUOUS, |
| Float.class).build().verify(mCarPropertyManager); |
| } |
| |
| @CddTest(requirement = "2.5.1") |
| @Test |
| public void testMustSupportParkingBrakeOn() { |
| VehiclePropertyVerifier.newBuilder(VehiclePropertyIds.PARKING_BRAKE_ON, |
| CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ, |
| VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL, |
| CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE, |
| Boolean.class).requireProperty().build().verify(mCarPropertyManager); |
| } |
| |
| @Test |
| public void testWheelTickIfSupported() { |
| VehiclePropertyVerifier.newBuilder(VehiclePropertyIds.WHEEL_TICK, |
| CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ, |
| VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL, |
| CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_CONTINUOUS, |
| Long[].class).setConfigArrayVerifier( |
| configArray -> { |
| assertWithMessage("WHEEL_TICK config array must be size 5") |
| .that(configArray.size()) |
| .isEqualTo(5); |
| |
| int supportedWheels = configArray.get(0); |
| assertWithMessage( |
| "WHEEL_TICK config array first element specifies which wheels are" |
| + " supported") |
| .that(supportedWheels).isGreaterThan( |
| VehicleAreaWheel.WHEEL_UNKNOWN); |
| assertWithMessage( |
| "WHEEL_TICK config array first element specifies which wheels are" |
| + " supported") |
| .that(supportedWheels) |
| .isAtMost(VehicleAreaWheel.WHEEL_LEFT_FRONT |
| | VehicleAreaWheel.WHEEL_RIGHT_FRONT | |
| VehicleAreaWheel.WHEEL_LEFT_REAR |
| | VehicleAreaWheel.WHEEL_RIGHT_REAR); |
| |
| verifyWheelTickConfigArray(supportedWheels, |
| VehicleAreaWheel.WHEEL_LEFT_FRONT, 1, configArray.get(1)); |
| verifyWheelTickConfigArray(supportedWheels, |
| VehicleAreaWheel.WHEEL_RIGHT_FRONT, 2, configArray.get(2)); |
| verifyWheelTickConfigArray(supportedWheels, |
| VehicleAreaWheel.WHEEL_RIGHT_REAR, 3, configArray.get(3)); |
| verifyWheelTickConfigArray(supportedWheels, |
| VehicleAreaWheel.WHEEL_LEFT_REAR, 4, configArray.get(4)); |
| }).setCarPropertyValueVerifier( |
| (carPropertyConfig, carPropertyValue) -> { |
| List<Integer> wheelTickConfigArray = carPropertyConfig.getConfigArray(); |
| int supportedWheels = wheelTickConfigArray.get(0); |
| |
| Long[] wheelTicks = (Long[]) carPropertyValue.getValue(); |
| assertWithMessage("WHEEL_TICK Long[] value must be size 5").that( |
| wheelTicks.length).isEqualTo(5); |
| |
| verifyWheelTickValue(supportedWheels, VehicleAreaWheel.WHEEL_LEFT_FRONT, 1, |
| wheelTicks[1]); |
| verifyWheelTickValue(supportedWheels, VehicleAreaWheel.WHEEL_RIGHT_FRONT, 2, |
| wheelTicks[2]); |
| verifyWheelTickValue(supportedWheels, VehicleAreaWheel.WHEEL_RIGHT_REAR, 3, |
| wheelTicks[3]); |
| verifyWheelTickValue(supportedWheels, VehicleAreaWheel.WHEEL_LEFT_REAR, 4, |
| wheelTicks[4]); |
| }).build().verify(mCarPropertyManager); |
| |
| } |
| |
| @Test |
| public void testInfoMakeIfSupported() { |
| VehiclePropertyVerifier.newBuilder(VehiclePropertyIds.INFO_MAKE, |
| CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ, |
| VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL, |
| CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_STATIC, |
| String.class).build().verify(mCarPropertyManager); |
| } |
| |
| @Test |
| public void testInfoModelIfSupported() { |
| VehiclePropertyVerifier.newBuilder(VehiclePropertyIds.INFO_MODEL, |
| CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ, |
| VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL, |
| CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_STATIC, |
| String.class).build().verify(mCarPropertyManager); |
| } |
| |
| @Test |
| public void testInfoModelYearIfSupported() { |
| VehiclePropertyVerifier.newBuilder(VehiclePropertyIds.INFO_MODEL_YEAR, |
| CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ, |
| VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL, |
| CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_STATIC, |
| Integer.class).build().verify(mCarPropertyManager); |
| } |
| |
| @Test |
| public void testInfoFuelCapacityIfSupported() { |
| VehiclePropertyVerifier.newBuilder(VehiclePropertyIds.INFO_FUEL_CAPACITY, |
| CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ, |
| VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL, |
| CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_STATIC, |
| Float.class).setCarPropertyValueVerifier( |
| (carPropertyConfig, carPropertyValue) -> assertWithMessage( |
| "INFO_FUEL_CAPACITY Float value must be greater than or equal 0").that( |
| (Float) carPropertyValue.getValue()).isAtLeast(0)).build().verify( |
| mCarPropertyManager); |
| } |
| |
| @Test |
| public void testInfoFuelTypeIfSupported() { |
| VehiclePropertyVerifier.newBuilder(VehiclePropertyIds.INFO_FUEL_TYPE, |
| CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ, |
| VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL, |
| CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_STATIC, |
| Integer[].class).setCarPropertyValueVerifier( |
| (carPropertyConfig, carPropertyValue) -> { |
| Integer[] fuelTypes = (Integer[]) carPropertyValue.getValue(); |
| assertWithMessage("INFO_FUEL_TYPE must specify at least 1 fuel type").that( |
| fuelTypes.length).isGreaterThan(0); |
| for (Integer fuelType : fuelTypes) { |
| assertWithMessage( |
| "INFO_FUEL_TYPE must be a defined fuel type: " + fuelType).that( |
| fuelType).isIn( |
| ImmutableSet.builder().add(FuelType.UNKNOWN, FuelType.UNLEADED, |
| FuelType.LEADED, FuelType.DIESEL_1, FuelType.DIESEL_2, |
| FuelType.BIODIESEL, FuelType.E85, FuelType.LPG, |
| FuelType.CNG, FuelType.LNG, FuelType.ELECTRIC, |
| FuelType.HYDROGEN, FuelType.OTHER).build()); |
| } |
| }).build().verify(mCarPropertyManager); |
| } |
| |
| @Test |
| public void testInfoEvBatteryCapacityIfSupported() { |
| VehiclePropertyVerifier.newBuilder(VehiclePropertyIds.INFO_EV_BATTERY_CAPACITY, |
| CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ, |
| VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL, |
| CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_STATIC, |
| Float.class).setCarPropertyValueVerifier( |
| (carPropertyConfig, carPropertyValue) -> assertWithMessage( |
| "INFO_EV_BATTERY_CAPACITY Float value must be greater than or equal to 0") |
| .that((Float) carPropertyValue.getValue()).isAtLeast(0)).build().verify( |
| mCarPropertyManager); |
| } |
| |
| @Test |
| public void testInfoEvConnectorTypeIfSupported() { |
| VehiclePropertyVerifier.newBuilder(VehiclePropertyIds.INFO_EV_CONNECTOR_TYPE, |
| CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ, |
| VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL, |
| CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_STATIC, |
| Integer[].class).setCarPropertyValueVerifier( |
| (carPropertyConfig, carPropertyValue) -> { |
| Integer[] evConnectorTypes = (Integer[]) carPropertyValue.getValue(); |
| assertWithMessage( |
| "INFO_EV_CONNECTOR_TYPE must specify at least 1 connection type").that( |
| evConnectorTypes.length).isGreaterThan(0); |
| for (Integer evConnectorType : evConnectorTypes) { |
| assertWithMessage( |
| "INFO_EV_CONNECTOR_TYPE must be a defined connection type: " |
| + evConnectorType).that( |
| evConnectorType).isIn( |
| ImmutableSet.builder().add(EvConnectorType.UNKNOWN, |
| EvConnectorType.J1772, EvConnectorType.MENNEKES, |
| EvConnectorType.CHADEMO, EvConnectorType.COMBO_1, |
| EvConnectorType.COMBO_2, EvConnectorType.TESLA_ROADSTER, |
| EvConnectorType.TESLA_HPWC, |
| EvConnectorType.TESLA_SUPERCHARGER, EvConnectorType.GBT, |
| EvConnectorType.GBT_DC, EvConnectorType.SCAME, |
| EvConnectorType.OTHER).build()); |
| } |
| }).build().verify(mCarPropertyManager); |
| } |
| |
| @Test |
| public void testInfoFuelDoorLocationIfSupported() { |
| VehiclePropertyVerifier.newBuilder(VehiclePropertyIds.INFO_FUEL_DOOR_LOCATION, |
| CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ, |
| VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL, |
| CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_STATIC, |
| Integer.class).setPossibleCarPropertyValues(PORT_LOCATION_TYPES).build() |
| .verify(mCarPropertyManager); |
| } |
| |
| @Test |
| public void testInfoEvPortLocationIfSupported() { |
| VehiclePropertyVerifier.newBuilder(VehiclePropertyIds.INFO_EV_PORT_LOCATION, |
| CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ, |
| VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL, |
| CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_STATIC, |
| Integer.class).setPossibleCarPropertyValues(PORT_LOCATION_TYPES).build() |
| .verify(mCarPropertyManager); |
| } |
| |
| @Test |
| public void testInfoMultiEvPortLocationsIfSupported() { |
| VehiclePropertyVerifier.newBuilder(VehiclePropertyIds.INFO_MULTI_EV_PORT_LOCATIONS, |
| CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ, |
| VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL, |
| CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_STATIC, |
| Integer[].class).setCarPropertyValueVerifier( |
| (carPropertyConfig, carPropertyValue) -> { |
| Integer[] evPortLocations = (Integer[]) carPropertyValue.getValue(); |
| assertWithMessage( |
| "INFO_MULTI_EV_PORT_LOCATIONS must specify at least 1 port location") |
| .that(evPortLocations.length).isGreaterThan(0); |
| for (Integer evPortLocation : evPortLocations) { |
| assertWithMessage( |
| "INFO_MULTI_EV_PORT_LOCATIONS must be a defined port location: " |
| + evPortLocation).that( |
| evPortLocation).isIn(PORT_LOCATION_TYPES); |
| } |
| }).build().verify(mCarPropertyManager); |
| } |
| |
| @Test |
| public void testInfoDriverSeatIfSupported() { |
| VehiclePropertyVerifier.newBuilder(VehiclePropertyIds.INFO_DRIVER_SEAT, |
| CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ, |
| VehicleAreaType.VEHICLE_AREA_TYPE_SEAT, |
| CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_STATIC, |
| Integer.class).setPossibleCarPropertyValues(ImmutableSet.of( |
| VehicleAreaSeat.SEAT_UNKNOWN, |
| VehicleAreaSeat.SEAT_ROW_1_LEFT, |
| VehicleAreaSeat.SEAT_ROW_1_CENTER, |
| VehicleAreaSeat.SEAT_ROW_1_RIGHT)) |
| .setAreaIdsVerifier(areaIds -> assertWithMessage( |
| "Even though INFO_DRIVER_SEAT is VEHICLE_AREA_TYPE_SEAT, it is meant to be " |
| + "VEHICLE_AREA_TYPE_GLOBAL, so its AreaIds must contain a single 0").that( |
| areaIds).isEqualTo(new int[]{VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL})) |
| .build().verify(mCarPropertyManager); |
| } |
| |
| @Test |
| public void testInfoExteriorDimensionsIfSupported() { |
| VehiclePropertyVerifier.newBuilder(VehiclePropertyIds.INFO_EXTERIOR_DIMENSIONS, |
| CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ, |
| VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL, |
| CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_STATIC, |
| Integer[].class).setCarPropertyValueVerifier( |
| (carPropertyConfig, carPropertyValue) -> { |
| Integer[] exteriorDimensions = (Integer[]) carPropertyValue.getValue(); |
| assertWithMessage( |
| "INFO_EXTERIOR_DIMENSIONS must specify all 8 dimension measurements") |
| .that(exteriorDimensions.length).isEqualTo(8); |
| for (Integer exteriorDimension : exteriorDimensions) { |
| assertWithMessage( |
| "INFO_EXTERIOR_DIMENSIONS measurement must be greater than 0").that( |
| exteriorDimension).isGreaterThan(0); |
| } |
| }).build().verify(mCarPropertyManager); |
| } |
| |
| @Test |
| public void testElectronicTollCollectionCardTypeIfSupported() { |
| VehiclePropertyVerifier.newBuilder( |
| VehiclePropertyIds.ELECTRONIC_TOLL_COLLECTION_CARD_TYPE, |
| CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ, |
| VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL, |
| CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE, |
| Integer.class).setPossibleCarPropertyValues(ImmutableSet.of( |
| VehicleElectronicTollCollectionCardType.UNKNOWN, |
| VehicleElectronicTollCollectionCardType.JP_ELECTRONIC_TOLL_COLLECTION_CARD, |
| VehicleElectronicTollCollectionCardType.JP_ELECTRONIC_TOLL_COLLECTION_CARD_V2) |
| ).build().verify(mCarPropertyManager); |
| } |
| |
| @Test |
| public void testElectronicTollCollectionCardStatusIfSupported() { |
| VehiclePropertyVerifier.newBuilder( |
| VehiclePropertyIds.ELECTRONIC_TOLL_COLLECTION_CARD_STATUS, |
| CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ, |
| VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL, |
| CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE, |
| Integer.class).setPossibleCarPropertyValues(ImmutableSet.of( |
| VehicleElectronicTollCollectionCardStatus.UNKNOWN, |
| VehicleElectronicTollCollectionCardStatus |
| .ELECTRONIC_TOLL_COLLECTION_CARD_VALID, |
| VehicleElectronicTollCollectionCardStatus |
| .ELECTRONIC_TOLL_COLLECTION_CARD_INVALID, |
| VehicleElectronicTollCollectionCardStatus |
| .ELECTRONIC_TOLL_COLLECTION_CARD_NOT_INSERTED) |
| ).build().verify(mCarPropertyManager); |
| } |
| |
| @Test |
| public void testEnvOutsideTemperatureIfSupported() { |
| VehiclePropertyVerifier.newBuilder(VehiclePropertyIds.ENV_OUTSIDE_TEMPERATURE, |
| CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ, |
| VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL, |
| CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_CONTINUOUS, |
| Float.class).build().verify(mCarPropertyManager); |
| } |
| |
| @Test |
| public void testCurrentGearIfSupported() { |
| VehiclePropertyVerifier.newBuilder(VehiclePropertyIds.CURRENT_GEAR, |
| CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ, |
| VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL, |
| CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE, |
| Integer.class).setPossibleConfigArrayValues( |
| VEHICLE_GEARS).requirePropertyValueTobeInConfigArray().build().verify( |
| mCarPropertyManager); |
| } |
| |
| @Test |
| public void testParkingBrakeAutoApplyIfSupported() { |
| VehiclePropertyVerifier.newBuilder(VehiclePropertyIds.PARKING_BRAKE_AUTO_APPLY, |
| CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ, |
| VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL, |
| CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE, |
| Boolean.class).build().verify(mCarPropertyManager); |
| } |
| |
| @Test |
| public void testIgnitionStateIfSupported() { |
| VehiclePropertyVerifier.newBuilder(VehiclePropertyIds.IGNITION_STATE, |
| CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ, |
| VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL, |
| CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE, |
| Integer.class).setPossibleCarPropertyValues(ImmutableSet.of( |
| VehicleIgnitionState.UNDEFINED, VehicleIgnitionState.LOCK, |
| VehicleIgnitionState.OFF, VehicleIgnitionState.ACC, VehicleIgnitionState.ON, |
| VehicleIgnitionState.START)).build().verify(mCarPropertyManager); |
| } |
| |
| @Test |
| public void testAbsActiveIfSupported() { |
| adoptSystemLevelPermission(/* Car.PERMISSION_CAR_DYNAMICS_STATE = */ |
| "android.car.permission.CAR_DYNAMICS_STATE", () -> { |
| VehiclePropertyVerifier.newBuilder(VehiclePropertyIds.ABS_ACTIVE, |
| CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ, |
| VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL, |
| CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE, |
| Boolean.class).build().verify(mCarPropertyManager); |
| }); |
| } |
| |
| @Test |
| public void testTractionControlActiveIfSupported() { |
| adoptSystemLevelPermission(/* Car.PERMISSION_CAR_DYNAMICS_STATE = */ |
| "android.car.permission.CAR_DYNAMICS_STATE", () -> { |
| VehiclePropertyVerifier.newBuilder(VehiclePropertyIds.TRACTION_CONTROL_ACTIVE, |
| CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ, |
| VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL, |
| CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE, |
| Boolean.class).build().verify(mCarPropertyManager); |
| }); |
| } |
| |
| @Test |
| public void testDoorPosIfSupported() { |
| adoptSystemLevelPermission(/* Car.PERMISSION_CONTROL_CAR_DOORS = */ |
| "android.car.permission.CONTROL_CAR_DOORS", () -> { |
| VehiclePropertyVerifier.newBuilder(VehiclePropertyIds.DOOR_POS, |
| CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE, |
| VehicleAreaType.VEHICLE_AREA_TYPE_DOOR, |
| CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE, |
| Integer.class).requireMinMaxValues().requireMinValuesToBeZero().build() |
| .verify(mCarPropertyManager); |
| }); |
| } |
| |
| @Test |
| public void testDoorMoveIfSupported() { |
| adoptSystemLevelPermission(/* Car.PERMISSION_CONTROL_CAR_DOORS = */ |
| "android.car.permission.CONTROL_CAR_DOORS", () -> { |
| VehiclePropertyVerifier.newBuilder(VehiclePropertyIds.DOOR_MOVE, |
| CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE, |
| VehicleAreaType.VEHICLE_AREA_TYPE_DOOR, |
| CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE, |
| Integer.class).requireMinMaxValues() |
| .requireZeroToBeContainedInMinMaxRanges().build().verify( |
| mCarPropertyManager); |
| }); |
| } |
| |
| @Test |
| public void testDoorLockIfSupported() { |
| adoptSystemLevelPermission(/* Car.PERMISSION_CONTROL_CAR_DOORS = */ |
| "android.car.permission.CONTROL_CAR_DOORS", () -> { |
| VehiclePropertyVerifier.newBuilder(VehiclePropertyIds.DOOR_LOCK, |
| CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE, |
| VehicleAreaType.VEHICLE_AREA_TYPE_DOOR, |
| CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE, |
| Boolean.class).build().verify(mCarPropertyManager); |
| }); |
| } |
| |
| @Test |
| public void testDistanceDisplayUnitsIfSupported() { |
| adoptSystemLevelPermission(/*Car.PERMISSION_VENDOR_EXTENSION=*/ |
| "android.car.permission.CAR_VENDOR_EXTENSION", () -> { |
| VehiclePropertyVerifier.newBuilder(VehiclePropertyIds.DISTANCE_DISPLAY_UNITS, |
| CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE, |
| VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL, |
| CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE, |
| Integer.class).setPossibleConfigArrayValues( |
| DISTANCE_DISPLAY_UNITS).requirePropertyValueTobeInConfigArray() |
| .verifySetterWithConfigArrayValues().build().verify( |
| mCarPropertyManager); |
| }); |
| } |
| |
| @Test |
| public void testFuelVolumeDisplayUnitsIfSupported() { |
| adoptSystemLevelPermission(/*Car.PERMISSION_VENDOR_EXTENSION=*/ |
| "android.car.permission.CAR_VENDOR_EXTENSION", () -> { |
| VehiclePropertyVerifier.newBuilder(VehiclePropertyIds.FUEL_VOLUME_DISPLAY_UNITS, |
| CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE, |
| VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL, |
| CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE, |
| Integer.class).setPossibleConfigArrayValues( |
| VOLUME_DISPLAY_UNITS).requirePropertyValueTobeInConfigArray() |
| .verifySetterWithConfigArrayValues().build().verify( |
| mCarPropertyManager); |
| |
| }); |
| } |
| |
| @Test |
| public void testTirePressureIfSupported() { |
| adoptSystemLevelPermission(/*Car.PERMISSION_TIRES=*/ |
| "android.car.permission.CAR_TIRES", () -> { |
| VehiclePropertyVerifier.newBuilder(VehiclePropertyIds.TIRE_PRESSURE, |
| CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ, |
| VehicleAreaType.VEHICLE_AREA_TYPE_WHEEL, |
| CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_CONTINUOUS, |
| Float.class).requireMinMaxValues().setCarPropertyValueVerifier( |
| (carPropertyConfig, carPropertyValue) -> assertWithMessage( |
| "TIRE_PRESSURE Float value" |
| + " at Area ID equals to " |
| + carPropertyValue.getAreaId() |
| + " must be greater than or equal 0").that( |
| (Float) carPropertyValue.getValue()).isAtLeast( |
| 0)).build().verify( |
| mCarPropertyManager); |
| }); |
| } |
| |
| @Test |
| public void testCriticallyLowTirePressureIfSupported() { |
| adoptSystemLevelPermission(/*Car.PERMISSION_TIRES=*/ |
| "android.car.permission.CAR_TIRES", () -> { |
| VehiclePropertyVerifier.newBuilder( |
| VehiclePropertyIds.CRITICALLY_LOW_TIRE_PRESSURE, |
| CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ, |
| VehicleAreaType.VEHICLE_AREA_TYPE_WHEEL, |
| CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_STATIC, |
| Float.class).setCarPropertyValueVerifier( |
| (carPropertyConfig, carPropertyValue) -> { |
| int areaId = carPropertyValue.getAreaId(); |
| |
| assertWithMessage( |
| "CRITICALLY_LOW_TIRE_PRESSURE Float value" |
| + "at Area ID equals to" + areaId |
| + " must be greater than or equal 0") |
| .that((Float) carPropertyValue.getValue()).isAtLeast(0); |
| |
| CarPropertyConfig<?> tirePressureConfig = |
| mCarPropertyManager.getCarPropertyConfig( |
| VehiclePropertyIds.TIRE_PRESSURE); |
| |
| if (tirePressureConfig == null |
| || tirePressureConfig.getMinValue(areaId) == null) { |
| return; |
| } |
| |
| assertWithMessage( |
| "CRITICALLY_LOW_TIRE_PRESSURE Float value" |
| + "at Area ID equals to" + areaId |
| + " must not exceed" |
| + " minFloatValue in TIRE_PRESSURE") |
| .that((Float) carPropertyValue.getValue()).isAtMost( |
| (Float) tirePressureConfig |
| .getMinValue(areaId)); |
| }).build().verify(mCarPropertyManager); |
| }); |
| } |
| |
| @Test |
| public void testTirePressureDisplayUnitsIfSupported() { |
| adoptSystemLevelPermission(/*Car.PERMISSION_VENDOR_EXTENSION=*/ |
| "android.car.permission.CAR_VENDOR_EXTENSION", () -> { |
| VehiclePropertyVerifier.newBuilder( |
| VehiclePropertyIds.TIRE_PRESSURE_DISPLAY_UNITS, |
| CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE, |
| VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL, |
| CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE, |
| Integer.class).setPossibleConfigArrayValues( |
| PRESSURE_DISPLAY_UNITS).requirePropertyValueTobeInConfigArray() |
| .verifySetterWithConfigArrayValues().build().verify( |
| mCarPropertyManager); |
| |
| }); |
| } |
| |
| @Test |
| public void testEvBatteryDisplayUnitsIfSupported() { |
| adoptSystemLevelPermission(/*Car.PERMISSION_VENDOR_EXTENSION=*/ |
| "android.car.permission.CAR_VENDOR_EXTENSION", () -> { |
| VehiclePropertyVerifier.newBuilder(VehiclePropertyIds.EV_BATTERY_DISPLAY_UNITS, |
| CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE, |
| VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL, |
| CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE, |
| Integer.class).setPossibleConfigArrayValues( |
| BATTERY_DISPLAY_UNITS).requirePropertyValueTobeInConfigArray() |
| .verifySetterWithConfigArrayValues().build().verify( |
| mCarPropertyManager); |
| |
| }); |
| } |
| |
| @Test |
| public void testVehicleSpeedDisplayUnitsIfSupported() { |
| adoptSystemLevelPermission(/*Car.PERMISSION_VENDOR_EXTENSION=*/ |
| "android.car.permission.CAR_VENDOR_EXTENSION", () -> { |
| VehiclePropertyVerifier.newBuilder( |
| VehiclePropertyIds.VEHICLE_SPEED_DISPLAY_UNITS, |
| CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE, |
| VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL, |
| CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE, |
| Integer.class).setPossibleConfigArrayValues( |
| SPEED_DISPLAY_UNITS).requirePropertyValueTobeInConfigArray() |
| .verifySetterWithConfigArrayValues().build().verify( |
| mCarPropertyManager); |
| }); |
| } |
| |
| @Test |
| public void testFuelConsumptionUnitsDistanceOverTimeIfSupported() { |
| adoptSystemLevelPermission(Car.PERMISSION_VENDOR_EXTENSION, () -> { |
| VehiclePropertyVerifier.newBuilder( |
| VehiclePropertyIds.FUEL_CONSUMPTION_UNITS_DISTANCE_OVER_VOLUME, |
| CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE, |
| VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL, |
| CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE, |
| Boolean.class).build().verify(mCarPropertyManager); |
| }); |
| } |
| |
| @Test |
| public void testFuelLevelIfSupported() { |
| VehiclePropertyVerifier.newBuilder( |
| VehiclePropertyIds.FUEL_LEVEL, |
| CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ, |
| VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL, |
| CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_CONTINUOUS, |
| Float.class).setCarPropertyValueVerifier( |
| (carPropertyConfig, carPropertyValue) -> { |
| assertWithMessage( |
| "FUEL_LEVEL Float value must be greater than or equal 0").that( |
| (Float) carPropertyValue.getValue()).isAtLeast(0); |
| |
| if (mCarPropertyManager.getCarPropertyConfig( |
| VehiclePropertyIds.INFO_FUEL_CAPACITY) == null) { |
| return; |
| } |
| |
| CarPropertyValue<?> infoFuelCapacityValue = mCarPropertyManager.getProperty( |
| VehiclePropertyIds.INFO_FUEL_CAPACITY, |
| VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL); |
| |
| assertWithMessage( |
| "FUEL_LEVEL Float value must not exceed INFO_FUEL_CAPACITY Float " |
| + "value").that( |
| (Float) carPropertyValue.getValue()).isAtMost( |
| (Float) infoFuelCapacityValue.getValue()); |
| }).build().verify(mCarPropertyManager); |
| } |
| |
| @Test |
| public void testEvBatteryLevelIfSupported() { |
| VehiclePropertyVerifier.newBuilder( |
| VehiclePropertyIds.EV_BATTERY_LEVEL, |
| CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ, |
| VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL, |
| CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_CONTINUOUS, |
| Float.class).setCarPropertyValueVerifier( |
| (carPropertyConfig, carPropertyValue) -> { |
| assertWithMessage( |
| "EV_BATTERY_LEVEL Float value must be greater than or equal 0").that( |
| (Float) carPropertyValue.getValue()).isAtLeast(0); |
| |
| if (mCarPropertyManager.getCarPropertyConfig( |
| VehiclePropertyIds.INFO_EV_BATTERY_CAPACITY) == null) { |
| return; |
| } |
| |
| CarPropertyValue<?> infoEvBatteryCapacityValue = |
| mCarPropertyManager.getProperty( |
| VehiclePropertyIds.INFO_EV_BATTERY_CAPACITY, |
| VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL); |
| |
| assertWithMessage( |
| "EV_BATTERY_LEVEL Float value must not exceed " |
| + "INFO_EV_BATTERY_CAPACITY Float " |
| + "value").that( |
| (Float) carPropertyValue.getValue()).isAtMost( |
| (Float) infoEvBatteryCapacityValue.getValue()); |
| }).build().verify(mCarPropertyManager); |
| } |
| |
| @Test |
| public void testEvBatteryInstantaneousChargeRateIfSupported() { |
| VehiclePropertyVerifier.newBuilder( |
| VehiclePropertyIds.EV_BATTERY_INSTANTANEOUS_CHARGE_RATE, |
| CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ, |
| VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL, |
| CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_CONTINUOUS, |
| Float.class).build().verify(mCarPropertyManager); |
| } |
| |
| @Test |
| public void testRangeRemainingIfSupported() { |
| VehiclePropertyVerifier.newBuilder( |
| VehiclePropertyIds.RANGE_REMAINING, |
| CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE, |
| VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL, |
| CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_CONTINUOUS, |
| Float.class).setCarPropertyValueVerifier( |
| (carPropertyConfig, carPropertyValue) -> { |
| assertWithMessage( |
| "RANGE_REMAINING Float value must be greater than or equal 0").that( |
| (Float) carPropertyValue.getValue()).isAtLeast(0); |
| }).build().verify(mCarPropertyManager); |
| } |
| |
| @Test |
| public void testFuelLevelLowIfSupported() { |
| VehiclePropertyVerifier.newBuilder( |
| VehiclePropertyIds.FUEL_LEVEL_LOW, |
| CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ, |
| VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL, |
| CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE, |
| Boolean.class).build().verify(mCarPropertyManager); |
| } |
| |
| @Test |
| public void testFuelDoorOpenIfSupported() { |
| adoptSystemLevelPermission(Car.PERMISSION_CONTROL_ENERGY_PORTS, () -> { |
| VehiclePropertyVerifier.newBuilder(VehiclePropertyIds.FUEL_DOOR_OPEN, |
| CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE, |
| VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL, |
| CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE, |
| Boolean.class).build().verify(mCarPropertyManager); |
| }); |
| } |
| |
| @Test |
| public void testEvChargePortOpenIfSupported() { |
| adoptSystemLevelPermission(Car.PERMISSION_CONTROL_ENERGY_PORTS, () -> { |
| VehiclePropertyVerifier.newBuilder(VehiclePropertyIds.EV_CHARGE_PORT_OPEN, |
| CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE, |
| VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL, |
| CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE, |
| Boolean.class).build().verify(mCarPropertyManager); |
| }); |
| } |
| |
| @Test |
| public void testEvChargePortConnectedIfSupported() { |
| VehiclePropertyVerifier.newBuilder( |
| VehiclePropertyIds.EV_CHARGE_PORT_CONNECTED, |
| CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ, |
| VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL, |
| CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE, |
| Boolean.class).build().verify(mCarPropertyManager); |
| } |
| |
| @Test |
| public void testEvChargeCurrentDrawLimitIfSupported() { |
| VehiclePropertyVerifier.newBuilder(VehiclePropertyIds.EV_CHARGE_CURRENT_DRAW_LIMIT, |
| CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE, |
| VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL, |
| CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE, |
| Float.class).setConfigArrayVerifier(configArray -> { |
| assertWithMessage("EV_CHARGE_CURRENT_DRAW_LIMIT config array must be size 1").that( |
| configArray.size()).isEqualTo(1); |
| |
| int maxCurrentDrawThresholdAmps = configArray.get(0); |
| assertWithMessage("EV_CHARGE_CURRENT_DRAW_LIMIT config array first element specifies " |
| + "max current draw allowed by vehicle in amperes.").that( |
| maxCurrentDrawThresholdAmps).isGreaterThan(0); |
| }).setCarPropertyValueVerifier((carPropertyConfig, carPropertyValue) -> { |
| List<Integer> evChargeCurrentDrawLimitConfigArray = carPropertyConfig.getConfigArray(); |
| int maxCurrentDrawThresholdAmps = evChargeCurrentDrawLimitConfigArray.get(0); |
| |
| Float evChargeCurrentDrawLimit = (Float) carPropertyValue.getValue(); |
| assertWithMessage("EV_CHARGE_CURRENT_DRAW_LIMIT value must be greater than 0").that( |
| evChargeCurrentDrawLimit).isGreaterThan(0); |
| assertWithMessage("EV_CHARGE_CURRENT_DRAW_LIMIT value must be less than or equal to max" |
| + " current draw by the vehicle").that(evChargeCurrentDrawLimit).isAtMost( |
| maxCurrentDrawThresholdAmps); |
| }).build().verify(mCarPropertyManager); |
| } |
| |
| @Test |
| public void testEvChargePercentLimitIfSupported() { |
| VehiclePropertyVerifier.newBuilder(VehiclePropertyIds.EV_CHARGE_PERCENT_LIMIT, |
| CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE, |
| VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL, |
| CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE, |
| Float.class).setConfigArrayVerifier(configArray -> { |
| for (int i = 0; i < configArray.size(); i++) { |
| assertWithMessage("EV_CHARGE_PERCENT_LIMIT configArray[" + i |
| + "] valid charge percent limit must be greater than 0").that( |
| configArray.get(i)).isGreaterThan(0); |
| assertWithMessage("EV_CHARGE_PERCENT_LIMIT configArray[" + i |
| + "] valid charge percent limit must be at most 100").that( |
| configArray.get(i)).isAtMost(100); |
| } |
| }).setCarPropertyValueVerifier((carPropertyConfig, carPropertyValue) -> { |
| List<Integer> evChargePercentLimitConfigArray = carPropertyConfig.getConfigArray(); |
| Float evChargePercentLimit = (Float) carPropertyValue.getValue(); |
| |
| if (evChargePercentLimitConfigArray.isEmpty()) { |
| assertWithMessage("EV_CHARGE_PERCENT_LIMIT value must be greater than 0").that( |
| evChargePercentLimit).isGreaterThan(0); |
| assertWithMessage("EV_CHARGE_PERCENT_LIMIT value must be at most 100").that( |
| evChargePercentLimit).isAtMost(100); |
| } else { |
| assertWithMessage( |
| "EV_CHARGE_PERCENT_LIMIT value must be in the configArray valid charge " |
| + "percent limit list").that(evChargePercentLimit.intValue()).isIn( |
| evChargePercentLimitConfigArray); |
| } |
| }).build().verify(mCarPropertyManager); |
| } |
| |
| @Test |
| public void testEvChargeStateIfSupported() { |
| VehiclePropertyVerifier.newBuilder(VehiclePropertyIds.EV_CHARGE_STATE, |
| CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ, |
| VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL, |
| CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE, |
| Integer.class).setCarPropertyValueVerifier( |
| (carPropertyConfig, carPropertyValue) -> { |
| Integer evChargeState = (Integer) carPropertyValue.getValue(); |
| assertWithMessage("EV_CHARGE_STATE must be a defined charge state: " |
| + evChargeState).that(evChargeState).isIn( |
| ImmutableSet.of(/*EvChargeState.UNKNOWN=*/0, |
| /*EvChargeState.CHARGING=*/1, /*EvChargeState.FULLY_CHARGED=*/2, |
| /*EvChargeState.NOT_CHARGING=*/3, /*EvChargeState.ERROR=*/4)); |
| }).build().verify(mCarPropertyManager); |
| } |
| |
| @Test |
| public void testEvChargeSwitchIfSupported() { |
| adoptSystemLevelPermission(Car.PERMISSION_CONTROL_CAR_ENERGY, () -> { |
| VehiclePropertyVerifier.newBuilder(VehiclePropertyIds.EV_CHARGE_SWITCH, |
| CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE, |
| VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL, |
| CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE, |
| Boolean.class).build().verify(mCarPropertyManager); |
| }); |
| } |
| |
| @Test |
| public void testEvChargeTimeRemainingIfSupported() { |
| VehiclePropertyVerifier.newBuilder(VehiclePropertyIds.EV_CHARGE_TIME_REMAINING, |
| CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ, |
| VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL, |
| CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_CONTINUOUS, |
| Integer.class).setCarPropertyValueVerifier( |
| (carPropertyConfig, carPropertyValue) -> { |
| assertWithMessage( |
| "FUEL_LEVEL Integer value must be greater than or equal 0").that( |
| (Integer) carPropertyValue.getValue()).isAtLeast(0); |
| |
| }).build().verify(mCarPropertyManager); |
| } |
| |
| @Test |
| public void testEvRegenerativeBrakingStateIfSupported() { |
| VehiclePropertyVerifier.newBuilder(VehiclePropertyIds.EV_REGENERATIVE_BRAKING_STATE, |
| CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ, |
| VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL, |
| CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE, |
| Integer.class).setCarPropertyValueVerifier( |
| (carPropertyConfig, carPropertyValue) -> { |
| Integer evRegenerativeBrakingState = (Integer) carPropertyValue.getValue(); |
| assertWithMessage("EV_REGENERATIVE_BRAKING_STATE must be a defined state: " |
| + evRegenerativeBrakingState).that(evRegenerativeBrakingState).isIn( |
| ImmutableSet.of(/*EvRegenerativeBrakingState.UNKNOWN=*/0, |
| /*EvRegenerativeBrakingState.DISABLED=*/1, |
| /*EvRegenerativeBrakingState.PARTIALLY_ENABLED=*/2, |
| /*EvRegenerativeBrakingState.FULLY_ENABLED=*/3)); |
| }).build().verify(mCarPropertyManager); |
| } |
| |
| @Test |
| public void testPerfSteeringAngleIfSupported() { |
| adoptSystemLevelPermission(Car.PERMISSION_READ_STEERING_STATE, () -> { |
| VehiclePropertyVerifier.newBuilder(VehiclePropertyIds.PERF_STEERING_ANGLE, |
| CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ, |
| VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL, |
| CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_CONTINUOUS, |
| Float.class).build().verify(mCarPropertyManager); |
| }); |
| } |
| |
| @Test |
| public void testPerfRearSteeringAngleIfSupported() { |
| adoptSystemLevelPermission(Car.PERMISSION_READ_STEERING_STATE, () -> { |
| VehiclePropertyVerifier.newBuilder(VehiclePropertyIds.PERF_REAR_STEERING_ANGLE, |
| CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ, |
| VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL, |
| CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_CONTINUOUS, |
| Float.class).build().verify(mCarPropertyManager); |
| }); |
| } |
| |
| @Test |
| public void testEngineCoolantTempIfSupported() { |
| adoptSystemLevelPermission(/*Car.PERMISSION_CAR_ENGINE_DETAILED=*/ |
| "android.car.permission.CAR_ENGINE_DETAILED", () -> { |
| VehiclePropertyVerifier.newBuilder(VehiclePropertyIds.ENGINE_COOLANT_TEMP, |
| CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ, |
| VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL, |
| CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_CONTINUOUS, |
| Float.class).build().verify(mCarPropertyManager); |
| }); |
| } |
| |
| @Test |
| public void testEngineOilLevelIfSupported() { |
| adoptSystemLevelPermission(/*Car.PERMISSION_CAR_ENGINE_DETAILED=*/ |
| "android.car.permission.CAR_ENGINE_DETAILED", () -> { |
| VehiclePropertyVerifier.newBuilder(VehiclePropertyIds.ENGINE_OIL_LEVEL, |
| CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ, |
| VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL, |
| CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE, |
| Integer.class).setCarPropertyValueVerifier( |
| (carPropertyConfig, carPropertyValue) -> assertWithMessage( |
| "ENGINE_OIL_LEVEL Integer value must be greater than or equal" |
| + " 0").that( |
| (Integer) carPropertyValue.getValue()).isAtLeast( |
| 0)).build().verify( |
| mCarPropertyManager); |
| }); |
| } |
| |
| @Test |
| public void testEngineOilTempIfSupported() { |
| adoptSystemLevelPermission(/*Car.PERMISSION_CAR_ENGINE_DETAILED=*/ |
| "android.car.permission.CAR_ENGINE_DETAILED", () -> { |
| VehiclePropertyVerifier.newBuilder(VehiclePropertyIds.ENGINE_OIL_TEMP, |
| CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ, |
| VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL, |
| CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_CONTINUOUS, |
| Float.class).build().verify(mCarPropertyManager); |
| }); |
| } |
| |
| @Test |
| public void testEngineRpmIfSupported() { |
| adoptSystemLevelPermission(/*Car.PERMISSION_CAR_ENGINE_DETAILED=*/ |
| "android.car.permission.CAR_ENGINE_DETAILED", () -> { |
| VehiclePropertyVerifier.newBuilder(VehiclePropertyIds.ENGINE_RPM, |
| CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ, |
| VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL, |
| CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_CONTINUOUS, |
| Float.class).setCarPropertyValueVerifier( |
| (carPropertyConfig, carPropertyValue) -> assertWithMessage( |
| "ENGINE_RPM Float value must be greater than or equal 0").that( |
| (Float) carPropertyValue.getValue()).isAtLeast( |
| 0)).build().verify( |
| mCarPropertyManager); |
| }); |
| } |
| |
| @Test |
| public void testPerfOdometerIfSupported() { |
| adoptSystemLevelPermission(/*Car.PERMISSION_MILEAGE=*/"android.car.permission.CAR_MILEAGE", |
| () -> { |
| VehiclePropertyVerifier.newBuilder(VehiclePropertyIds.PERF_ODOMETER, |
| CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ, |
| VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL, |
| CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_CONTINUOUS, |
| Float.class).setCarPropertyValueVerifier( |
| (carPropertyConfig, carPropertyValue) -> assertWithMessage( |
| "PERF_ODOMETER Float value must be greater than or equal 0") |
| .that((Float) carPropertyValue.getValue()).isAtLeast(0)) |
| .build().verify(mCarPropertyManager); |
| }); |
| } |
| |
| @Test |
| public void testTurnSignalStateIfSupported() { |
| adoptSystemLevelPermission(/*Car.PERMISSION_EXTERIOR_LIGHTS=*/ |
| "android.car.permission.CAR_EXTERIOR_LIGHTS", () -> { |
| VehiclePropertyVerifier.newBuilder(VehiclePropertyIds.TURN_SIGNAL_STATE, |
| CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ, |
| VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL, |
| CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE, |
| Integer.class).setPossibleCarPropertyValues(TURN_SIGNAL_STATES).build() |
| .verify(mCarPropertyManager); |
| }); |
| } |
| |
| @Test |
| public void testHeadlightsStateIfSupported() { |
| adoptSystemLevelPermission(/*Car.PERMISSION_EXTERIOR_LIGHTS=*/ |
| "android.car.permission.CAR_EXTERIOR_LIGHTS", () -> { |
| VehiclePropertyVerifier.newBuilder(VehiclePropertyIds.HEADLIGHTS_STATE, |
| CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ, |
| VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL, |
| CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE, |
| Integer.class).setPossibleCarPropertyValues(VEHICLE_LIGHT_STATES) |
| .build().verify(mCarPropertyManager); |
| }); |
| } |
| |
| @Test |
| public void testHighBeamLightsStateIfSupported() { |
| adoptSystemLevelPermission(/*Car.PERMISSION_EXTERIOR_LIGHTS=*/ |
| "android.car.permission.CAR_EXTERIOR_LIGHTS", () -> { |
| VehiclePropertyVerifier.newBuilder(VehiclePropertyIds.HIGH_BEAM_LIGHTS_STATE, |
| CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ, |
| VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL, |
| CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE, |
| Integer.class).setPossibleCarPropertyValues(VEHICLE_LIGHT_STATES) |
| .build().verify(mCarPropertyManager); |
| }); |
| } |
| |
| @Test |
| public void testFogLightsStateIfSupported() { |
| adoptSystemLevelPermission(/*Car.PERMISSION_EXTERIOR_LIGHTS=*/ |
| "android.car.permission.CAR_EXTERIOR_LIGHTS", () -> { |
| VehiclePropertyVerifier.newBuilder(VehiclePropertyIds.FOG_LIGHTS_STATE, |
| CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ, |
| VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL, |
| CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE, |
| Integer.class).setPossibleCarPropertyValues(VEHICLE_LIGHT_STATES) |
| .setCarPropertyValueVerifier( |
| (carPropertyConfig, carPropertyValue) -> { |
| assertWithMessage( |
| "FRONT_FOG_LIGHTS_STATE must not be implemented" |
| + "when FOG_LIGHTS_STATE is implemented") |
| .that(mCarPropertyManager.getCarPropertyConfig( |
| VehiclePropertyIds.FRONT_FOG_LIGHTS_STATE)) |
| .isNull(); |
| |
| assertWithMessage( |
| "REAR_FOG_LIGHTS_STATE must not be implemented" |
| + "when FOG_LIGHTS_STATE is implemented") |
| .that(mCarPropertyManager.getCarPropertyConfig( |
| VehiclePropertyIds.REAR_FOG_LIGHTS_STATE)) |
| .isNull(); |
| }).build().verify(mCarPropertyManager); |
| }); |
| } |
| |
| @Test |
| public void testHazardLightsStateIfSupported() { |
| adoptSystemLevelPermission(/*Car.PERMISSION_EXTERIOR_LIGHTS=*/ |
| "android.car.permission.CAR_EXTERIOR_LIGHTS", () -> { |
| VehiclePropertyVerifier.newBuilder(VehiclePropertyIds.HAZARD_LIGHTS_STATE, |
| CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ, |
| VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL, |
| CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE, |
| Integer.class).setPossibleCarPropertyValues(VEHICLE_LIGHT_STATES) |
| .build().verify(mCarPropertyManager); |
| }); |
| } |
| |
| @Test |
| public void testFrontFogLightsStateIfSupported() { |
| adoptSystemLevelPermission(/*Car.PERMISSION_EXTERIOR_LIGHTS=*/ |
| "android.car.permission.CAR_EXTERIOR_LIGHTS", () -> { |
| VehiclePropertyVerifier.newBuilder(VehiclePropertyIds.FRONT_FOG_LIGHTS_STATE, |
| CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ, |
| VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL, |
| CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE, |
| Integer.class).setPossibleCarPropertyValues(VEHICLE_LIGHT_STATES) |
| .setCarPropertyValueVerifier( |
| (carPropertyConfig, carPropertyValue) -> { |
| assertWithMessage( |
| "FOG_LIGHTS_STATE must not be implemented" |
| + "when FRONT_FOG_LIGHTS_STATE is implemented") |
| .that(mCarPropertyManager.getCarPropertyConfig( |
| VehiclePropertyIds.FOG_LIGHTS_STATE)) |
| .isNull(); |
| }).build().verify(mCarPropertyManager); |
| }); |
| } |
| |
| @Test |
| public void testRearFogLightsStateIfSupported() { |
| adoptSystemLevelPermission(/*Car.PERMISSION_EXTERIOR_LIGHTS=*/ |
| "android.car.permission.CAR_EXTERIOR_LIGHTS", () -> { |
| VehiclePropertyVerifier.newBuilder(VehiclePropertyIds.REAR_FOG_LIGHTS_STATE, |
| CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ, |
| VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL, |
| CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE, |
| Integer.class).setPossibleCarPropertyValues(VEHICLE_LIGHT_STATES) |
| .setCarPropertyValueVerifier( |
| (carPropertyConfig, carPropertyValue) -> { |
| assertWithMessage( |
| "FOG_LIGHTS_STATE must not be implemented" |
| + "when REAR_FOG_LIGHTS_STATE is implemented") |
| .that(mCarPropertyManager.getCarPropertyConfig( |
| VehiclePropertyIds.FOG_LIGHTS_STATE)) |
| .isNull(); |
| }).build().verify(mCarPropertyManager); |
| }); |
| } |
| |
| @Test |
| public void testVehicleCurbWeightIfSupported() { |
| adoptSystemLevelPermission(Car.PERMISSION_PRIVILEGED_CAR_INFO, () -> { |
| VehiclePropertyVerifier.newBuilder(VehiclePropertyIds.VEHICLE_CURB_WEIGHT, |
| CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ, |
| VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL, |
| CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_STATIC, |
| Integer.class).setConfigArrayVerifier(configArray -> { |
| assertWithMessage( |
| "VEHICLE_CURB_WEIGHT configArray must contain the gross weight in " |
| + "kilograms").that(configArray).hasSize(1); |
| assertWithMessage( |
| "VEHICLE_CURB_WEIGHT configArray[0] must contain the gross weight in " |
| + "kilograms and be greater than zero").that( |
| configArray.get(0)).isGreaterThan(0); |
| }).setCarPropertyValueVerifier((carPropertyConfig, carPropertyValue) -> { |
| Integer curbWeightKg = (Integer) carPropertyValue.getValue(); |
| Integer grossWeightKg = carPropertyConfig.getConfigArray().get(0); |
| |
| assertWithMessage("VEHICLE_CURB_WEIGHT must be greater than zero").that( |
| curbWeightKg).isGreaterThan(0); |
| assertWithMessage("VEHICLE_CURB_WEIGHT must be less than the gross weight").that( |
| curbWeightKg).isLessThan(grossWeightKg); |
| }).build().verify(mCarPropertyManager); |
| }); |
| } |
| |
| @Test |
| public void testHeadlightsSwitchIfSupported() { |
| adoptSystemLevelPermission(Car.PERMISSION_CONTROL_EXTERIOR_LIGHTS, () -> { |
| VehiclePropertyVerifier.newBuilder(VehiclePropertyIds.HEADLIGHTS_SWITCH, |
| CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE, |
| VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL, |
| CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE, |
| Integer.class).setPossibleCarPropertyValues(VEHICLE_LIGHT_SWITCHES) |
| .build().verify(mCarPropertyManager); |
| }); |
| } |
| |
| @Test |
| public void testTrailerPresentIfSupported() { |
| adoptSystemLevelPermission(Car.PERMISSION_PRIVILEGED_CAR_INFO, () -> { |
| VehiclePropertyVerifier.newBuilder(VehiclePropertyIds.TRAILER_PRESENT, |
| CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ, |
| VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL, |
| CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE, |
| Integer.class).setPossibleCarPropertyValues( |
| ImmutableSet.of(/*TrailerState.UNKNOWN=*/ |
| 0, /*TrailerState.NOT_PRESENT*/ |
| 1, /*TrailerState.PRESENT=*/2, /*TrailerState.ERROR=*/ |
| 3)).build().verify(mCarPropertyManager); |
| }); |
| } |
| |
| @Test |
| public void testHighBeamLightsSwitchIfSupported() { |
| adoptSystemLevelPermission(Car.PERMISSION_CONTROL_EXTERIOR_LIGHTS, () -> { |
| VehiclePropertyVerifier.newBuilder(VehiclePropertyIds.HIGH_BEAM_LIGHTS_SWITCH, |
| CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE, |
| VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL, |
| CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE, |
| Integer.class).setPossibleCarPropertyValues(VEHICLE_LIGHT_SWITCHES) |
| .build().verify(mCarPropertyManager); |
| }); |
| } |
| |
| @Test |
| public void testFogLightsSwitchIfSupported() { |
| adoptSystemLevelPermission(Car.PERMISSION_CONTROL_EXTERIOR_LIGHTS, () -> { |
| VehiclePropertyVerifier.newBuilder(VehiclePropertyIds.FOG_LIGHTS_SWITCH, |
| CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE, |
| VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL, |
| CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE, |
| Integer.class).setPossibleCarPropertyValues(VEHICLE_LIGHT_SWITCHES) |
| .setCarPropertyValueVerifier((carPropertyConfig, carPropertyValue) -> { |
| assertWithMessage("FRONT_FOG_LIGHTS_SWITCH must not be implemented" |
| + "when FOG_LIGHTS_SWITCH is implemented") |
| .that(mCarPropertyManager.getCarPropertyConfig( |
| VehiclePropertyIds.FRONT_FOG_LIGHTS_SWITCH)).isNull(); |
| |
| assertWithMessage("REAR_FOG_LIGHTS_SWITCH must not be implemented" |
| + "when FOG_LIGHTS_SWITCH is implemented") |
| .that(mCarPropertyManager.getCarPropertyConfig( |
| VehiclePropertyIds.REAR_FOG_LIGHTS_SWITCH)).isNull(); |
| }).build().verify(mCarPropertyManager); |
| }); |
| } |
| |
| @Test |
| public void testHazardLightsSwitchIfSupported() { |
| adoptSystemLevelPermission(Car.PERMISSION_CONTROL_EXTERIOR_LIGHTS, () -> { |
| VehiclePropertyVerifier.newBuilder(VehiclePropertyIds.HAZARD_LIGHTS_SWITCH, |
| CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE, |
| VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL, |
| CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE, |
| Integer.class).setPossibleCarPropertyValues(VEHICLE_LIGHT_SWITCHES) |
| .build().verify(mCarPropertyManager); |
| }); |
| } |
| |
| @Test |
| public void testFrontFogLightsSwitchIfSupported() { |
| adoptSystemLevelPermission(Car.PERMISSION_CONTROL_EXTERIOR_LIGHTS, () -> { |
| VehiclePropertyVerifier.newBuilder(VehiclePropertyIds.FRONT_FOG_LIGHTS_SWITCH, |
| CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE, |
| VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL, |
| CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE, |
| Integer.class).setPossibleCarPropertyValues(VEHICLE_LIGHT_SWITCHES) |
| .setCarPropertyValueVerifier((carPropertyConfig, carPropertyValue) -> { |
| assertWithMessage("FOG_LIGHTS_SWITCH must not be implemented" |
| + "when FRONT_FOG_LIGHTS_SWITCH is implemented") |
| .that(mCarPropertyManager.getCarPropertyConfig( |
| VehiclePropertyIds.FOG_LIGHTS_SWITCH)).isNull(); |
| }).build().verify(mCarPropertyManager); |
| }); |
| } |
| |
| @Test |
| public void testRearFogLightsSwitchIfSupported() { |
| adoptSystemLevelPermission(Car.PERMISSION_CONTROL_EXTERIOR_LIGHTS, () -> { |
| VehiclePropertyVerifier.newBuilder(VehiclePropertyIds.REAR_FOG_LIGHTS_SWITCH, |
| CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE, |
| VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL, |
| CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE, |
| Integer.class).setPossibleCarPropertyValues(VEHICLE_LIGHT_SWITCHES) |
| .setCarPropertyValueVerifier((carPropertyConfig, carPropertyValue) -> { |
| assertWithMessage("FOG_LIGHTS_SWITCH must not be implemented" |
| + "when REAR_FOG_LIGHTS_SWITCH is implemented") |
| .that(mCarPropertyManager.getCarPropertyConfig( |
| VehiclePropertyIds.FOG_LIGHTS_SWITCH)).isNull(); |
| }).build().verify(mCarPropertyManager); |
| }); |
| } |
| |
| @Test |
| public void testSeatBeltBuckledIfSupported() { |
| adoptSystemLevelPermission(Car.PERMISSION_CONTROL_CAR_SEATS, () -> { |
| VehiclePropertyVerifier.newBuilder(VehiclePropertyIds.SEAT_BELT_BUCKLED, |
| CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE, |
| VehicleAreaType.VEHICLE_AREA_TYPE_SEAT, |
| CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE, |
| Boolean.class).build().verify(mCarPropertyManager); |
| }); |
| } |
| |
| @Test |
| public void testSeatBeltHeightPosIfSupported() { |
| adoptSystemLevelPermission(Car.PERMISSION_CONTROL_CAR_SEATS, () -> { |
| VehiclePropertyVerifier.newBuilder(VehiclePropertyIds.SEAT_BELT_HEIGHT_POS, |
| CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE, |
| VehicleAreaType.VEHICLE_AREA_TYPE_SEAT, |
| CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE, |
| Integer.class).requireMinMaxValues().build() |
| .verify(mCarPropertyManager); |
| }); |
| } |
| |
| @Test |
| public void testSeatBeltHeightMoveIfSupported() { |
| adoptSystemLevelPermission(Car.PERMISSION_CONTROL_CAR_SEATS, () -> { |
| VehiclePropertyVerifier.newBuilder(VehiclePropertyIds.SEAT_BELT_HEIGHT_MOVE, |
| CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE, |
| VehicleAreaType.VEHICLE_AREA_TYPE_SEAT, |
| CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE, |
| Integer.class).requireMinMaxValues() |
| .requireZeroToBeContainedInMinMaxRanges().build().verify(mCarPropertyManager); |
| }); |
| } |
| |
| @Test |
| public void testSeatForeAftPosIfSupported() { |
| adoptSystemLevelPermission(Car.PERMISSION_CONTROL_CAR_SEATS, () -> { |
| VehiclePropertyVerifier.newBuilder(VehiclePropertyIds.SEAT_FORE_AFT_POS, |
| CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE, |
| VehicleAreaType.VEHICLE_AREA_TYPE_SEAT, |
| CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE, |
| Integer.class).requireMinMaxValues().build() |
| .verify(mCarPropertyManager); |
| }); |
| } |
| |
| @Test |
| public void testSeatForeAftMoveIfSupported() { |
| adoptSystemLevelPermission(Car.PERMISSION_CONTROL_CAR_SEATS, () -> { |
| VehiclePropertyVerifier.newBuilder(VehiclePropertyIds.SEAT_FORE_AFT_MOVE, |
| CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE, |
| VehicleAreaType.VEHICLE_AREA_TYPE_SEAT, |
| CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE, |
| Integer.class).requireMinMaxValues() |
| .requireZeroToBeContainedInMinMaxRanges().build().verify(mCarPropertyManager); |
| }); |
| } |
| |
| @Test |
| public void testSeatBackrestAngle1PosIfSupported() { |
| adoptSystemLevelPermission(Car.PERMISSION_CONTROL_CAR_SEATS, () -> { |
| VehiclePropertyVerifier.newBuilder(VehiclePropertyIds.SEAT_BACKREST_ANGLE_1_POS, |
| CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE, |
| VehicleAreaType.VEHICLE_AREA_TYPE_SEAT, |
| CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE, |
| Integer.class).requireMinMaxValues().build() |
| .verify(mCarPropertyManager); |
| }); |
| } |
| |
| @Test |
| public void testSeatBackrestAngle1MoveIfSupported() { |
| adoptSystemLevelPermission(Car.PERMISSION_CONTROL_CAR_SEATS, () -> { |
| VehiclePropertyVerifier.newBuilder(VehiclePropertyIds.SEAT_BACKREST_ANGLE_1_MOVE, |
| CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE, |
| VehicleAreaType.VEHICLE_AREA_TYPE_SEAT, |
| CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE, |
| Integer.class).requireMinMaxValues() |
| .requireZeroToBeContainedInMinMaxRanges().build().verify(mCarPropertyManager); |
| }); |
| } |
| |
| @Test |
| public void testSeatBackrestAngle2PosIfSupported() { |
| adoptSystemLevelPermission(Car.PERMISSION_CONTROL_CAR_SEATS, () -> { |
| VehiclePropertyVerifier.newBuilder(VehiclePropertyIds.SEAT_BACKREST_ANGLE_2_POS, |
| CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE, |
| VehicleAreaType.VEHICLE_AREA_TYPE_SEAT, |
| CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE, |
| Integer.class).requireMinMaxValues().build() |
| .verify(mCarPropertyManager); |
| }); |
| } |
| |
| @Test |
| public void testSeatBackrestAngle2MoveIfSupported() { |
| adoptSystemLevelPermission(Car.PERMISSION_CONTROL_CAR_SEATS, () -> { |
| VehiclePropertyVerifier.newBuilder(VehiclePropertyIds.SEAT_BACKREST_ANGLE_2_MOVE, |
| CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE, |
| VehicleAreaType.VEHICLE_AREA_TYPE_SEAT, |
| CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE, |
| Integer.class).requireMinMaxValues() |
| .requireZeroToBeContainedInMinMaxRanges().build().verify(mCarPropertyManager); |
| }); |
| } |
| |
| @Test |
| public void testHvacDefrosterIfSupported() { |
| adoptSystemLevelPermission(Car.PERMISSION_CONTROL_CAR_CLIMATE, () -> { |
| VehiclePropertyVerifier.newBuilder(VehiclePropertyIds.HVAC_DEFROSTER, |
| CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE, |
| VehicleAreaType.VEHICLE_AREA_TYPE_WINDOW, |
| CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE, |
| Boolean.class).build().verify(mCarPropertyManager); |
| }); |
| } |
| |
| @Test |
| public void testHvacElectricDefrosterOnIfSupported() { |
| adoptSystemLevelPermission(Car.PERMISSION_CONTROL_CAR_CLIMATE, () -> { |
| VehiclePropertyVerifier.newBuilder(VehiclePropertyIds.HVAC_ELECTRIC_DEFROSTER_ON, |
| CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE, |
| VehicleAreaType.VEHICLE_AREA_TYPE_WINDOW, |
| CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE, |
| Boolean.class).build().verify(mCarPropertyManager); |
| }); |
| } |
| |
| @Test |
| public void testHvacSideMirrorHeatIfSupported() { |
| adoptSystemLevelPermission(Car.PERMISSION_CONTROL_CAR_CLIMATE, () -> { |
| VehiclePropertyVerifier.newBuilder(VehiclePropertyIds.HVAC_SIDE_MIRROR_HEAT, |
| CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE, |
| VehicleAreaType.VEHICLE_AREA_TYPE_MIRROR, |
| CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE, |
| Integer.class).requireMinMaxValues().requireMinValuesToBeZero().build().verify( |
| mCarPropertyManager); |
| }); |
| } |
| |
| @Test |
| public void testHvacSteeringWheelHeatIfSupported() { |
| adoptSystemLevelPermission(Car.PERMISSION_CONTROL_CAR_CLIMATE, () -> { |
| VehiclePropertyVerifier.newBuilder(VehiclePropertyIds.HVAC_STEERING_WHEEL_HEAT, |
| CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE, |
| VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL, |
| CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE, |
| Integer.class).requireMinMaxValues().requireZeroToBeContainedInMinMaxRanges() |
| .build().verify(mCarPropertyManager); |
| }); |
| } |
| |
| @Test |
| public void testHvacTemperatureDisplayUnitsIfSupported() { |
| adoptSystemLevelPermission(Car.PERMISSION_CONTROL_CAR_CLIMATE, () -> { |
| VehiclePropertyVerifier.newBuilder(VehiclePropertyIds.HVAC_TEMPERATURE_DISPLAY_UNITS, |
| CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE, |
| VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL, |
| CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE, |
| Integer.class).setPossibleConfigArrayValues( |
| HVAC_TEMPERATURE_DISPLAY_UNITS).requirePropertyValueTobeInConfigArray() |
| .verifySetterWithConfigArrayValues().build().verify(mCarPropertyManager); |
| }); |
| } |
| |
| @Test |
| public void testHvacTemperatureValueSuggestionIfSupported() { |
| adoptSystemLevelPermission(Car.PERMISSION_CONTROL_CAR_CLIMATE, () -> { |
| VehiclePropertyVerifier.newBuilder(VehiclePropertyIds.HVAC_TEMPERATURE_VALUE_SUGGESTION, |
| CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE, |
| VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL, |
| CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE, |
| Float[].class).build().verify(mCarPropertyManager); |
| }); |
| } |
| |
| @Test |
| @ApiTest(apis = {"android.car.hardware.property.CarPropertyManager#getCarPropertyConfig", |
| "android.car.hardware.property.CarPropertyManager#getProperty", |
| "android.car.hardware.property.CarPropertyManager#setProperty", |
| "android.car.hardware.property.CarPropertyManager#registerCallback", |
| "android.car.hardware.property.CarPropertyManager#unregisterCallback"}) |
| public void testHvacPowerOnIfSupported() { |
| adoptSystemLevelPermission(Car.PERMISSION_CONTROL_CAR_CLIMATE, () -> { |
| VehiclePropertyVerifier.newBuilder(VehiclePropertyIds.HVAC_POWER_ON, |
| CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE, |
| VehicleAreaType.VEHICLE_AREA_TYPE_SEAT, |
| CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE, |
| Boolean.class).setConfigArrayVerifier(configArray -> { |
| CarPropertyConfig<?> hvacPowerOnCarPropertyConfig = |
| mCarPropertyManager.getCarPropertyConfig(VehiclePropertyIds.HVAC_POWER_ON); |
| for (int powerDependentProperty : configArray) { |
| CarPropertyConfig<?> powerDependentCarPropertyConfig = |
| mCarPropertyManager.getCarPropertyConfig(powerDependentProperty); |
| if (powerDependentCarPropertyConfig == null) { |
| continue; |
| } |
| assertWithMessage( |
| "HVAC_POWER_ON configArray must only contain VehicleAreaSeat type " |
| + "properties: " + VehiclePropertyIds.toString( |
| powerDependentProperty)).that( |
| powerDependentCarPropertyConfig.getAreaType()).isEqualTo( |
| VehicleAreaType.VEHICLE_AREA_TYPE_SEAT); |
| assertWithMessage( |
| "HVAC_POWER_ON's area IDs must match the area IDs of power dependent " |
| + "property: " + VehiclePropertyIds.toString( |
| powerDependentProperty)).that(Arrays.stream( |
| powerDependentCarPropertyConfig.getAreaIds()).boxed().collect( |
| Collectors.toList())).containsExactlyElementsIn(Arrays.stream( |
| hvacPowerOnCarPropertyConfig.getAreaIds()).boxed().collect( |
| Collectors.toList())); |
| } |
| }).build().verify(mCarPropertyManager); |
| }); |
| } |
| |
| @Test |
| @ApiTest(apis = {"android.car.hardware.property.CarPropertyManager#getCarPropertyConfig", |
| "android.car.hardware.property.CarPropertyManager#getProperty", |
| "android.car.hardware.property.CarPropertyManager#setProperty", |
| "android.car.hardware.property.CarPropertyManager#registerCallback", |
| "android.car.hardware.property.CarPropertyManager#unregisterCallback"}) |
| public void testHvacFanSpeedIfSupported() { |
| adoptSystemLevelPermission(Car.PERMISSION_CONTROL_CAR_CLIMATE, () -> { |
| VehiclePropertyVerifier.newBuilder(VehiclePropertyIds.HVAC_FAN_SPEED, |
| CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE, |
| VehicleAreaType.VEHICLE_AREA_TYPE_SEAT, |
| CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE, |
| Integer.class).requireMinMaxValues().setPossiblyDependentOnHvacPowerOn().build() |
| .verify(mCarPropertyManager); |
| }); |
| } |
| |
| @Test |
| @ApiTest(apis = {"android.car.hardware.property.CarPropertyManager#getCarPropertyConfig", |
| "android.car.hardware.property.CarPropertyManager#getProperty", |
| "android.car.hardware.property.CarPropertyManager#setProperty", |
| "android.car.hardware.property.CarPropertyManager#registerCallback", |
| "android.car.hardware.property.CarPropertyManager#unregisterCallback"}) |
| public void testHvacFanDirectionAvailableIfSupported() { |
| adoptSystemLevelPermission(Car.PERMISSION_CONTROL_CAR_CLIMATE, () -> { |
| VehiclePropertyVerifier.newBuilder(VehiclePropertyIds.HVAC_FAN_DIRECTION_AVAILABLE, |
| CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ, |
| VehicleAreaType.VEHICLE_AREA_TYPE_SEAT, |
| CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_STATIC, |
| Integer[].class).setPossiblyDependentOnHvacPowerOn().setAreaIdsVerifier( |
| areaIds -> { |
| CarPropertyConfig<?> hvacFanDirectionCarPropertyConfig = |
| mCarPropertyManager.getCarPropertyConfig( |
| VehiclePropertyIds.HVAC_FAN_DIRECTION); |
| assertWithMessage("HVAC_FAN_DIRECTION must be implemented if " |
| + "HVAC_FAN_DIRECTION_AVAILABLE is implemented").that( |
| hvacFanDirectionCarPropertyConfig).isNotNull(); |
| |
| assertWithMessage( |
| "HVAC_FAN_DIRECTION_AVAILABLE area IDs must match the area IDs of " |
| + "HVAC_FAN_DIRECTION").that(Arrays.stream( |
| areaIds).boxed().collect( |
| Collectors.toList())).containsExactlyElementsIn(Arrays.stream( |
| hvacFanDirectionCarPropertyConfig.getAreaIds()).boxed().collect( |
| Collectors.toList())); |
| |
| }).setCarPropertyValueVerifier((carPropertyConfig, carPropertyValue) -> { |
| Integer[] fanDirectionValues = (Integer[]) carPropertyValue.getValue(); |
| assertWithMessage( |
| "HVAC_FAN_DIRECTION_AVAILABLE area ID: " + carPropertyValue.getAreaId() |
| + " must have at least 1 direction defined").that( |
| fanDirectionValues.length).isAtLeast(1); |
| assertWithMessage( |
| "HVAC_FAN_DIRECTION_AVAILABLE area ID: " + carPropertyValue.getAreaId() |
| + " values all must all be unique: " + Arrays.toString( |
| fanDirectionValues)).that(fanDirectionValues.length).isEqualTo( |
| ImmutableSet.copyOf(fanDirectionValues).size()); |
| for (Integer fanDirection : fanDirectionValues) { |
| assertWithMessage("HVAC_FAN_DIRECTION_AVAILABLE's area ID: " |
| + carPropertyValue.getAreaId() |
| + " must be a valid combination of fan directions").that( |
| fanDirection).isIn(ALL_POSSIBLE_HVAC_FAN_DIRECTIONS); |
| } |
| }).build().verify(mCarPropertyManager); |
| }); |
| } |
| |
| @Test |
| @ApiTest(apis = {"android.car.hardware.property.CarPropertyManager#getCarPropertyConfig", |
| "android.car.hardware.property.CarPropertyManager#getProperty", |
| "android.car.hardware.property.CarPropertyManager#setProperty", |
| "android.car.hardware.property.CarPropertyManager#registerCallback", |
| "android.car.hardware.property.CarPropertyManager#unregisterCallback"}) |
| public void testHvacFanDirectionIfSupported() { |
| adoptSystemLevelPermission(Car.PERMISSION_CONTROL_CAR_CLIMATE, () -> { |
| VehiclePropertyVerifier.newBuilder(VehiclePropertyIds.HVAC_FAN_DIRECTION, |
| CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE, |
| VehicleAreaType.VEHICLE_AREA_TYPE_SEAT, |
| CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE, |
| Integer.class).setPossiblyDependentOnHvacPowerOn().setAreaIdsVerifier( |
| areaIds -> { |
| CarPropertyConfig<?> hvacFanDirectionAvailableCarPropertyConfig = |
| mCarPropertyManager.getCarPropertyConfig( |
| VehiclePropertyIds.HVAC_FAN_DIRECTION_AVAILABLE); |
| assertWithMessage("HVAC_FAN_DIRECTION_AVAILABLE must be implemented if " |
| + "HVAC_FAN_DIRECTION is implemented").that( |
| hvacFanDirectionAvailableCarPropertyConfig).isNotNull(); |
| |
| assertWithMessage("HVAC_FAN_DIRECTION area IDs must match the area IDs of " |
| + "HVAC_FAN_DIRECTION_AVAILABLE").that(Arrays.stream( |
| areaIds).boxed().collect( |
| Collectors.toList())).containsExactlyElementsIn(Arrays.stream( |
| hvacFanDirectionAvailableCarPropertyConfig.getAreaIds()).boxed() |
| .collect(Collectors.toList())); |
| |
| }).setCarPropertyValueVerifier((carPropertyConfig, carPropertyValue) -> { |
| CarPropertyValue<Integer[]> hvacFanDirectionAvailableCarPropertyValue = |
| mCarPropertyManager.getProperty( |
| VehiclePropertyIds.HVAC_FAN_DIRECTION_AVAILABLE, |
| carPropertyValue.getAreaId()); |
| assertWithMessage("HVAC_FAN_DIRECTION_AVAILABLE value must be available").that( |
| hvacFanDirectionAvailableCarPropertyValue).isNotNull(); |
| |
| assertWithMessage("HVAC_FAN_DIRECTION area ID " + carPropertyValue.getAreaId() |
| + " value must be in list for HVAC_FAN_DIRECTION_AVAILABLE").that( |
| carPropertyValue.getValue()).isIn( |
| Arrays.asList(hvacFanDirectionAvailableCarPropertyValue.getValue())); |
| }).build().verify(mCarPropertyManager); |
| }); |
| } |
| |
| @Test |
| @ApiTest(apis = {"android.car.hardware.property.CarPropertyManager#getCarPropertyConfig", |
| "android.car.hardware.property.CarPropertyManager#getProperty", |
| "android.car.hardware.property.CarPropertyManager#setProperty", |
| "android.car.hardware.property.CarPropertyManager#registerCallback", |
| "android.car.hardware.property.CarPropertyManager#unregisterCallback"}) |
| public void testHvacTemperatureCurrentIfSupported() { |
| adoptSystemLevelPermission(Car.PERMISSION_CONTROL_CAR_CLIMATE, () -> { |
| VehiclePropertyVerifier.newBuilder(VehiclePropertyIds.HVAC_TEMPERATURE_CURRENT, |
| CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ, |
| VehicleAreaType.VEHICLE_AREA_TYPE_SEAT, |
| CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE, |
| Float.class).setPossiblyDependentOnHvacPowerOn().build().verify( |
| mCarPropertyManager); |
| }); |
| } |
| |
| @Test |
| @ApiTest(apis = {"android.car.hardware.property.CarPropertyManager#getCarPropertyConfig", |
| "android.car.hardware.property.CarPropertyManager#getProperty", |
| "android.car.hardware.property.CarPropertyManager#setProperty", |
| "android.car.hardware.property.CarPropertyManager#registerCallback", |
| "android.car.hardware.property.CarPropertyManager#unregisterCallback"}) |
| public void testHvacTemperatureSetIfSupported() { |
| adoptSystemLevelPermission(Car.PERMISSION_CONTROL_CAR_CLIMATE, () -> { |
| VehiclePropertyVerifier.Builder<Float> hvacTempSetVerifierBuilder = |
| VehiclePropertyVerifier.newBuilder(VehiclePropertyIds.HVAC_TEMPERATURE_SET, |
| CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE, |
| VehicleAreaType.VEHICLE_AREA_TYPE_SEAT, |
| CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE, |
| Float.class).setPossiblyDependentOnHvacPowerOn().setConfigArrayVerifier( |
| configArray -> { |
| assertWithMessage( |
| "HVAC_TEMPERATURE_SET config array must be size 6").that( |
| configArray.size()).isEqualTo(6); |
| |
| assertWithMessage( |
| "HVAC_TEMPERATURE_SET lower bound must be less than the " |
| + "upper bound for " |
| + "the supported temperatures in Celsius").that( |
| configArray.get(0)).isLessThan(configArray.get(1)); |
| assertWithMessage( |
| "HVAC_TEMPERATURE_SET increment in Celsius must be " |
| + "greater than 0").that( |
| configArray.get(2)).isGreaterThan(0); |
| assertWithMessage( |
| "HVAC_TEMPERATURE_SET increment in Celsius must be less " |
| + "than the " |
| + "difference between the upper and lower bound " |
| + "supported " |
| + "temperatures").that( |
| configArray.get(2)).isLessThan( |
| configArray.get(1) - configArray.get(0)); |
| assertWithMessage( |
| "HVAC_TEMPERATURE_SET increment in Celsius must evenly " |
| + "space the gap " |
| + "between upper and lower bound").that( |
| (configArray.get(1) - configArray.get(0)) % configArray.get( |
| 2)).isEqualTo(0); |
| |
| assertWithMessage( |
| "HVAC_TEMPERATURE_SET lower bound must be less than the " |
| + "upper bound for " |
| + "the supported temperatures in Fahrenheit").that( |
| configArray.get(3)).isLessThan(configArray.get(4)); |
| assertWithMessage( |
| "HVAC_TEMPERATURE_SET increment in Fahrenheit must be " |
| + "greater than 0").that( |
| configArray.get(5)).isGreaterThan(0); |
| assertWithMessage( |
| "HVAC_TEMPERATURE_SET increment in Fahrenheit must be " |
| + "less than the " |
| + "difference between the upper and lower bound " |
| + "supported " |
| + "temperatures").that( |
| configArray.get(5)).isLessThan( |
| configArray.get(4) - configArray.get(3)); |
| assertWithMessage( |
| "HVAC_TEMPERATURE_SET increment in Fahrenheit must evenly" |
| + " space the gap " |
| + "between upper and lower bound").that( |
| (configArray.get(4) - configArray.get(3)) % configArray.get( |
| 5)).isEqualTo(0); |
| |
| }); |
| |
| CarPropertyConfig<?> hvacTempSetConfig = mCarPropertyManager.getCarPropertyConfig( |
| VehiclePropertyIds.HVAC_TEMPERATURE_SET); |
| if (hvacTempSetConfig != null) { |
| ImmutableSet.Builder<Float> possibleHvacTempSetValuesBuilder = |
| ImmutableSet.builder(); |
| for (int possibleHvacTempSetValue = hvacTempSetConfig.getConfigArray().get(0); |
| possibleHvacTempSetValue <= hvacTempSetConfig.getConfigArray().get(1); |
| possibleHvacTempSetValue += hvacTempSetConfig.getConfigArray().get(2)) { |
| possibleHvacTempSetValuesBuilder.add((float) possibleHvacTempSetValue / 10.0f); |
| } |
| hvacTempSetVerifierBuilder.setPossibleCarPropertyValues( |
| possibleHvacTempSetValuesBuilder.build()); |
| } |
| |
| hvacTempSetVerifierBuilder.build().verify(mCarPropertyManager); |
| }); |
| } |
| |
| @SuppressWarnings("unchecked") |
| @Test |
| public void testGetProperty() { |
| List<CarPropertyConfig> configs = mCarPropertyManager.getPropertyList(mPropertyIds); |
| for (CarPropertyConfig cfg : configs) { |
| if (cfg.getAccess() == CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ) { |
| int[] areaIds = getAreaIdsHelper(cfg); |
| int propId = cfg.getPropertyId(); |
| // no guarantee if we can get values, just call and check if it throws exception. |
| if (cfg.getPropertyType() == Boolean.class) { |
| for (int areaId : areaIds) { |
| mCarPropertyManager.getBooleanProperty(propId, areaId); |
| } |
| } else if (cfg.getPropertyType() == Integer.class) { |
| for (int areaId : areaIds) { |
| mCarPropertyManager.getIntProperty(propId, areaId); |
| } |
| } else if (cfg.getPropertyType() == Float.class) { |
| for (int areaId : areaIds) { |
| mCarPropertyManager.getFloatProperty(propId, areaId); |
| } |
| } else if (cfg.getPropertyType() == Integer[].class) { |
| for (int areId : areaIds) { |
| mCarPropertyManager.getIntArrayProperty(propId, areId); |
| } |
| } else { |
| for (int areaId : areaIds) { |
| mCarPropertyManager.getProperty( |
| cfg.getPropertyType(), propId, areaId); |
| } |
| } |
| } |
| } |
| } |
| |
| @Test |
| public void testGetIntArrayProperty() { |
| List<CarPropertyConfig> allConfigs = mCarPropertyManager.getPropertyList(); |
| for (CarPropertyConfig cfg : allConfigs) { |
| if (cfg.getAccess() == CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_NONE |
| || cfg.getAccess() == CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_WRITE |
| || cfg.getPropertyType() != Integer[].class) { |
| // skip the test if the property is not readable or not an int array type property. |
| continue; |
| } |
| switch (cfg.getPropertyId()) { |
| case VehiclePropertyIds.INFO_FUEL_TYPE: |
| int[] fuelTypes = mCarPropertyManager.getIntArrayProperty(cfg.getPropertyId(), |
| VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL); |
| verifyEnumsRange(EXPECTED_FUEL_TYPES, fuelTypes); |
| break; |
| case VehiclePropertyIds.INFO_MULTI_EV_PORT_LOCATIONS: |
| int[] evPortLocations = mCarPropertyManager.getIntArrayProperty( |
| cfg.getPropertyId(), VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL); |
| verifyEnumsRange(EXPECTED_PORT_LOCATIONS, evPortLocations); |
| break; |
| default: |
| int[] areaIds = getAreaIdsHelper(cfg); |
| for (int areaId : areaIds) { |
| mCarPropertyManager.getIntArrayProperty(cfg.getPropertyId(), areaId); |
| } |
| } |
| } |
| } |
| |
| private void verifyEnumsRange(List<Integer> expectedResults, int[] results) { |
| assertThat(results).isNotNull(); |
| // If the property is not implemented in cars, getIntArrayProperty returns an empty array. |
| if (results.length == 0) { |
| return; |
| } |
| for (int result : results) { |
| assertThat(result).isIn(expectedResults); |
| } |
| } |
| |
| @Test |
| public void testIsPropertyAvailable() { |
| List<CarPropertyConfig> configs = mCarPropertyManager.getPropertyList(mPropertyIds); |
| |
| for (CarPropertyConfig cfg : configs) { |
| int[] areaIds = getAreaIdsHelper(cfg); |
| for (int areaId : areaIds) { |
| assertThat(mCarPropertyManager.isPropertyAvailable(cfg.getPropertyId(), areaId)) |
| .isTrue(); |
| } |
| } |
| } |
| |
| @Test |
| public void testSetProperty() { |
| List<CarPropertyConfig> configs = mCarPropertyManager.getPropertyList(); |
| for (CarPropertyConfig cfg : configs) { |
| if (cfg.getAccess() == CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE |
| && cfg.getPropertyType() == Boolean.class) { |
| // In R, there is no property which is writable for third-party apps. |
| for (int areaId : getAreaIdsHelper(cfg)) { |
| assertThrows(SecurityException.class, |
| () -> mCarPropertyManager.setBooleanProperty( |
| cfg.getPropertyId(), areaId, true)); |
| } |
| } |
| } |
| } |
| |
| @Test |
| public void testRegisterCallback() throws Exception { |
| //Test on registering a invalid property |
| int invalidPropertyId = -1; |
| boolean isRegistered = mCarPropertyManager.registerCallback( |
| new CarPropertyEventCounter(), invalidPropertyId, 0); |
| assertThat(isRegistered).isFalse(); |
| |
| // Test for continuous properties |
| int vehicleSpeed = VehiclePropertyIds.PERF_VEHICLE_SPEED; |
| CarPropertyConfig<?> carPropertyConfig = mCarPropertyManager.getCarPropertyConfig( |
| VehiclePropertyIds.PERF_VEHICLE_SPEED); |
| float secondsToMillis = 1_000; |
| long bufferMillis = 1_000; // 1 second |
| // timeoutMillis is set to the maximum expected time needed to receive the required |
| // number of PERF_VEHICLE_SPEED events for test. If the test does not receive the |
| // required number of events before the timeout expires, it fails. |
| long timeoutMillis = |
| ((long) ((1.0f / carPropertyConfig.getMinSampleRate()) * secondsToMillis |
| * UI_RATE_EVENT_COUNTER)) + bufferMillis; |
| CarPropertyEventCounter speedListenerUI = new CarPropertyEventCounter(timeoutMillis); |
| CarPropertyEventCounter speedListenerFast = new CarPropertyEventCounter(); |
| |
| assertThat(speedListenerUI.receivedEvent(vehicleSpeed)).isEqualTo(NO_EVENTS); |
| assertThat(speedListenerUI.receivedError(vehicleSpeed)).isEqualTo(NO_EVENTS); |
| assertThat(speedListenerUI.receivedErrorWithErrorCode(vehicleSpeed)).isEqualTo(NO_EVENTS); |
| assertThat(speedListenerFast.receivedEvent(vehicleSpeed)).isEqualTo(NO_EVENTS); |
| assertThat(speedListenerFast.receivedError(vehicleSpeed)).isEqualTo(NO_EVENTS); |
| assertThat(speedListenerFast.receivedErrorWithErrorCode(vehicleSpeed)).isEqualTo(NO_EVENTS); |
| |
| speedListenerUI.resetCountDownLatch(UI_RATE_EVENT_COUNTER); |
| mCarPropertyManager.registerCallback(speedListenerUI, vehicleSpeed, |
| CarPropertyManager.SENSOR_RATE_UI); |
| mCarPropertyManager.registerCallback(speedListenerFast, vehicleSpeed, |
| CarPropertyManager.SENSOR_RATE_FASTEST); |
| speedListenerUI.assertOnChangeEventCalled(); |
| mCarPropertyManager.unregisterCallback(speedListenerUI); |
| mCarPropertyManager.unregisterCallback(speedListenerFast); |
| |
| assertThat(speedListenerUI.receivedEvent(vehicleSpeed)).isGreaterThan(NO_EVENTS); |
| assertThat(speedListenerFast.receivedEvent(vehicleSpeed)).isAtLeast( |
| speedListenerUI.receivedEvent(vehicleSpeed)); |
| // The test did not change property values, it should not get error with error codes. |
| assertThat(speedListenerUI.receivedErrorWithErrorCode(vehicleSpeed)).isEqualTo(NO_EVENTS); |
| assertThat(speedListenerFast.receivedErrorWithErrorCode(vehicleSpeed)).isEqualTo(NO_EVENTS); |
| |
| // Test for on_change properties |
| int nightMode = VehiclePropertyIds.NIGHT_MODE; |
| CarPropertyEventCounter nightModeListener = new CarPropertyEventCounter(); |
| nightModeListener.resetCountDownLatch(ONCHANGE_RATE_EVENT_COUNTER); |
| mCarPropertyManager.registerCallback(nightModeListener, nightMode, 0); |
| nightModeListener.assertOnChangeEventCalled(); |
| assertThat(nightModeListener.receivedEvent(nightMode)).isEqualTo(1); |
| mCarPropertyManager.unregisterCallback(nightModeListener); |
| } |
| |
| @Test |
| public void testUnregisterCallback() throws Exception { |
| |
| int vehicleSpeed = VehiclePropertyIds.PERF_VEHICLE_SPEED; |
| CarPropertyEventCounter speedListenerNormal = new CarPropertyEventCounter(); |
| CarPropertyEventCounter speedListenerUI = new CarPropertyEventCounter(); |
| |
| mCarPropertyManager.registerCallback(speedListenerNormal, vehicleSpeed, |
| CarPropertyManager.SENSOR_RATE_NORMAL); |
| |
| // test on unregistering a callback that was never registered |
| try { |
| mCarPropertyManager.unregisterCallback(speedListenerUI); |
| } catch (Exception e) { |
| Assert.fail(); |
| } |
| |
| mCarPropertyManager.registerCallback(speedListenerUI, vehicleSpeed, |
| CarPropertyManager.SENSOR_RATE_UI); |
| speedListenerUI.resetCountDownLatch(UI_RATE_EVENT_COUNTER); |
| speedListenerUI.assertOnChangeEventCalled(); |
| mCarPropertyManager.unregisterCallback(speedListenerNormal, vehicleSpeed); |
| |
| int currentEventNormal = speedListenerNormal.receivedEvent(vehicleSpeed); |
| int currentEventUI = speedListenerUI.receivedEvent(vehicleSpeed); |
| speedListenerNormal.assertOnChangeEventNotCalled(); |
| |
| assertThat(speedListenerNormal.receivedEvent(vehicleSpeed)).isEqualTo(currentEventNormal); |
| assertThat(speedListenerUI.receivedEvent(vehicleSpeed)).isNotEqualTo(currentEventUI); |
| |
| mCarPropertyManager.unregisterCallback(speedListenerUI); |
| speedListenerUI.assertOnChangeEventNotCalled(); |
| |
| currentEventUI = speedListenerUI.receivedEvent(vehicleSpeed); |
| assertThat(speedListenerUI.receivedEvent(vehicleSpeed)).isEqualTo(currentEventUI); |
| } |
| |
| @Test |
| public void testUnregisterWithPropertyId() throws Exception { |
| // Ignores the test if wheel_tick property does not exist in the car. |
| Assume.assumeTrue("WheelTick is not available, skip unregisterCallback test", |
| mCarPropertyManager.isPropertyAvailable( |
| VehiclePropertyIds.WHEEL_TICK, VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL)); |
| |
| CarPropertyConfig wheelTickConfig = mCarPropertyManager.getCarPropertyConfig( |
| VehiclePropertyIds.WHEEL_TICK); |
| CarPropertyConfig speedConfig = mCarPropertyManager.getCarPropertyConfig( |
| VehiclePropertyIds.PERF_VEHICLE_SPEED); |
| float maxSampleRateHz = |
| Math.max(wheelTickConfig.getMaxSampleRate(), speedConfig.getMaxSampleRate()); |
| int eventCounter = getCounterBySampleRate(maxSampleRateHz); |
| |
| // Ignores the test if sampleRates for properties are too low. |
| Assume.assumeTrue("The SampleRates for properties are too low, " |
| + "skip testUnregisterWithPropertyId test", eventCounter != 0); |
| CarPropertyEventCounter speedAndWheelTicksListener = new CarPropertyEventCounter(); |
| |
| // CarService will register them to the maxSampleRate in CarPropertyConfig |
| mCarPropertyManager.registerCallback(speedAndWheelTicksListener, |
| VehiclePropertyIds.PERF_VEHICLE_SPEED, CarPropertyManager.SENSOR_RATE_FASTEST); |
| mCarPropertyManager.registerCallback(speedAndWheelTicksListener, |
| VehiclePropertyIds.WHEEL_TICK, CarPropertyManager.SENSOR_RATE_FASTEST); |
| speedAndWheelTicksListener.resetCountDownLatch(eventCounter); |
| speedAndWheelTicksListener.assertOnChangeEventCalled(); |
| |
| // Tests unregister the individual property |
| mCarPropertyManager.unregisterCallback(speedAndWheelTicksListener, |
| VehiclePropertyIds.PERF_VEHICLE_SPEED); |
| |
| // Updates counter after unregistering the PERF_VEHICLE_SPEED |
| int wheelTickEventCounter = getCounterBySampleRate(wheelTickConfig.getMaxSampleRate()); |
| speedAndWheelTicksListener.resetCountDownLatch(wheelTickEventCounter); |
| speedAndWheelTicksListener.assertOnChangeEventCalled(); |
| int speedEventCountAfterFirstCountDown = speedAndWheelTicksListener.receivedEvent( |
| VehiclePropertyIds.PERF_VEHICLE_SPEED); |
| int wheelTickEventCountAfterFirstCountDown = speedAndWheelTicksListener.receivedEvent( |
| VehiclePropertyIds.WHEEL_TICK); |
| |
| speedAndWheelTicksListener.resetCountDownLatch(wheelTickEventCounter); |
| speedAndWheelTicksListener.assertOnChangeEventCalled(); |
| int speedEventCountAfterSecondCountDown = speedAndWheelTicksListener.receivedEvent( |
| VehiclePropertyIds.PERF_VEHICLE_SPEED); |
| int wheelTickEventCountAfterSecondCountDown = speedAndWheelTicksListener.receivedEvent( |
| VehiclePropertyIds.WHEEL_TICK); |
| |
| assertThat(speedEventCountAfterFirstCountDown).isEqualTo( |
| speedEventCountAfterSecondCountDown); |
| assertThat(wheelTickEventCountAfterSecondCountDown) |
| .isGreaterThan(wheelTickEventCountAfterFirstCountDown); |
| } |
| |
| private int getCounterBySampleRate(float maxSampleRateHz) { |
| if (Float.compare(maxSampleRateHz, (float) FAST_OR_FASTEST_EVENT_COUNTER) > 0) { |
| return FAST_OR_FASTEST_EVENT_COUNTER; |
| } else if (Float.compare(maxSampleRateHz, (float) UI_RATE_EVENT_COUNTER) > 0) { |
| return UI_RATE_EVENT_COUNTER; |
| } else if (Float.compare(maxSampleRateHz, (float) ONCHANGE_RATE_EVENT_COUNTER) > 0) { |
| return ONCHANGE_RATE_EVENT_COUNTER; |
| } else { |
| return 0; |
| } |
| } |
| |
| // Returns {0} if the property is global property, otherwise query areaId for CarPropertyConfig |
| private int[] getAreaIdsHelper(CarPropertyConfig config) { |
| if (config.isGlobalProperty()) { |
| return new int[]{0}; |
| } else { |
| return config.getAreaIds(); |
| } |
| } |
| |
| private static class CarPropertyEventCounter implements CarPropertyEventCallback { |
| private final Object mLock = new Object(); |
| @GuardedBy("mLock") |
| private final SparseArray<Integer> mEventCounter = new SparseArray<>(); |
| @GuardedBy("mLock") |
| private final SparseArray<Integer> mErrorCounter = new SparseArray<>(); |
| @GuardedBy("mLock") |
| private final SparseArray<Integer> mErrorWithErrorCodeCounter = new SparseArray<>(); |
| private int mCounter = FAST_OR_FASTEST_EVENT_COUNTER; |
| private CountDownLatch mCountDownLatch = new CountDownLatch(mCounter); |
| private final long mTimeoutMillis; |
| |
| CarPropertyEventCounter(long timeoutMillis) { |
| mTimeoutMillis = timeoutMillis; |
| } |
| |
| CarPropertyEventCounter() { |
| this(WAIT_CALLBACK); |
| } |
| |
| public int receivedEvent(int propId) { |
| int val; |
| synchronized (mLock) { |
| val = mEventCounter.get(propId, 0); |
| } |
| return val; |
| } |
| |
| public int receivedError(int propId) { |
| int val; |
| synchronized (mLock) { |
| val = mErrorCounter.get(propId, 0); |
| } |
| return val; |
| } |
| |
| public int receivedErrorWithErrorCode(int propId) { |
| int val; |
| synchronized (mLock) { |
| val = mErrorWithErrorCodeCounter.get(propId, 0); |
| } |
| return val; |
| } |
| |
| @Override |
| public void onChangeEvent(CarPropertyValue value) { |
| synchronized (mLock) { |
| int val = mEventCounter.get(value.getPropertyId(), 0) + 1; |
| mEventCounter.put(value.getPropertyId(), val); |
| } |
| mCountDownLatch.countDown(); |
| } |
| |
| @Override |
| public void onErrorEvent(int propId, int zone) { |
| synchronized (mLock) { |
| int val = mErrorCounter.get(propId, 0) + 1; |
| mErrorCounter.put(propId, val); |
| } |
| } |
| |
| @Override |
| public void onErrorEvent(int propId, int areaId, int errorCode) { |
| synchronized (mLock) { |
| int val = mErrorWithErrorCodeCounter.get(propId, 0) + 1; |
| mErrorWithErrorCodeCounter.put(propId, val); |
| } |
| } |
| |
| public void resetCountDownLatch(int counter) { |
| mCountDownLatch = new CountDownLatch(counter); |
| mCounter = counter; |
| } |
| |
| public void assertOnChangeEventCalled() throws InterruptedException { |
| if (!mCountDownLatch.await(mTimeoutMillis, TimeUnit.MILLISECONDS)) { |
| throw new IllegalStateException( |
| "Callback is not called " + mCounter + "times in " + mTimeoutMillis |
| + " ms. It was only called " + (mCounter |
| - mCountDownLatch.getCount()) + " times."); |
| } |
| } |
| |
| public void assertOnChangeEventNotCalled() throws InterruptedException { |
| // Once get an event, fail the test. |
| mCountDownLatch = new CountDownLatch(1); |
| if (mCountDownLatch.await(mTimeoutMillis, TimeUnit.MILLISECONDS)) { |
| throw new IllegalStateException("Callback is called in " + mTimeoutMillis + " ms."); |
| } |
| } |
| |
| } |
| } |