Added CTS tests HVAC_TEMPERATURE_* properties

Test: atest CarPropertyManagerTest
Bug: 237610879
Change-Id: I9b6062539936f4b82309a3e567af664873edd716
diff --git a/tests/tests/car/src/android/car/cts/CarPropertyManagerTest.java b/tests/tests/car/src/android/car/cts/CarPropertyManagerTest.java
index 8bb9eba..8b6f668 100644
--- a/tests/tests/car/src/android/car/cts/CarPropertyManagerTest.java
+++ b/tests/tests/car/src/android/car/cts/CarPropertyManagerTest.java
@@ -1783,6 +1783,110 @@
         });
     }
 
+    @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() {
diff --git a/tests/tests/car/src/android/car/cts/utils/VehiclePropertyVerifier.java b/tests/tests/car/src/android/car/cts/utils/VehiclePropertyVerifier.java
index dfacec6..98dc099 100644
--- a/tests/tests/car/src/android/car/cts/utils/VehiclePropertyVerifier.java
+++ b/tests/tests/car/src/android/car/cts/utils/VehiclePropertyVerifier.java
@@ -49,6 +49,7 @@
 public class VehiclePropertyVerifier<T> {
     private final static String CAR_PROPERTY_VALUE_SOURCE_GETTER = "Getter";
     private final static String CAR_PROPERTY_VALUE_SOURCE_CALLBACK = "Callback";
+    private static final float FLOAT_INEQUALITY_THRESHOLD = 0.00001f;
     private static final ImmutableSet<Integer> WHEEL_AREAS = ImmutableSet.of(
             VehicleAreaWheel.WHEEL_LEFT_FRONT, VehicleAreaWheel.WHEEL_LEFT_REAR,
             VehicleAreaWheel.WHEEL_RIGHT_FRONT, VehicleAreaWheel.WHEEL_RIGHT_REAR);
@@ -88,7 +89,7 @@
     private final Optional<CarPropertyValueVerifier> mCarPropertyValueVerifier;
     private final Optional<AreaIdsVerifier> mAreaIdsVerifier;
     private final ImmutableSet<Integer> mPossibleConfigArrayValues;
-    private final ImmutableSet<Integer> mPossibleCarPropertyValues;
+    private final ImmutableSet<T> mPossibleCarPropertyValues;
     private final boolean mRequirePropertyValueToBeInConfigArray;
     private final boolean mVerifySetterWithConfigArrayValues;
     private final boolean mRequireMinMaxValues;
@@ -102,7 +103,7 @@
             Optional<CarPropertyValueVerifier> carPropertyValueVerifier,
             Optional<AreaIdsVerifier> areaIdsVerifier,
             ImmutableSet<Integer> possibleConfigArrayValues,
-            ImmutableSet<Integer> possibleCarPropertyValues,
+            ImmutableSet<T> possibleCarPropertyValues,
             boolean requirePropertyValueToBeInConfigArray,
             boolean verifySetterWithConfigArrayValues,
             boolean requireMinMaxValues,
@@ -229,6 +230,8 @@
             verifyBooleanPropertySetter(carPropertyConfig, carPropertyManager);
         } else if (Integer.class.equals(carPropertyConfig.getPropertyType())) {
             verifyIntegerPropertySetter(carPropertyConfig, carPropertyManager);
+        } else if (Float.class.equals(carPropertyConfig.getPropertyType())) {
+            verifyFloatPropertySetter(carPropertyConfig, carPropertyManager);
         }
     }
 
@@ -250,31 +253,21 @@
     private void verifyIntegerPropertySetter(CarPropertyConfig<?> carPropertyConfig,
             CarPropertyManager carPropertyManager) {
         if (mVerifySetterWithConfigArrayValues) {
-            verifySetterWithConfigArrayValues(carPropertyConfig, carPropertyManager);
+            verifySetterWithValues((CarPropertyConfig<T>) carPropertyConfig, carPropertyManager,
+                    (Collection<T>) carPropertyConfig.getConfigArray());
         } else if (!mPossibleCarPropertyValues.isEmpty()) {
-            verifySetterWithPossibleCarPropertyValues(carPropertyConfig, carPropertyManager);
+            verifySetterWithValues((CarPropertyConfig<T>) carPropertyConfig, carPropertyManager,
+                    mPossibleCarPropertyValues);
         } else {
             verifySetterWithMinMaxValues(carPropertyConfig, carPropertyManager);
         }
     }
 
-    private void verifySetterWithConfigArrayValues(CarPropertyConfig<?> carPropertyConfig,
-            CarPropertyManager carPropertyManager) {
-        verifySetterWithIntegerValues(carPropertyConfig, carPropertyManager,
-                carPropertyConfig.getConfigArray());
-    }
-
-    private void verifySetterWithPossibleCarPropertyValues(CarPropertyConfig<?> carPropertyConfig,
-            CarPropertyManager carPropertyManager) {
-        verifySetterWithIntegerValues(carPropertyConfig, carPropertyManager,
-                mPossibleCarPropertyValues);
-    }
-
-    private void verifySetterWithIntegerValues(CarPropertyConfig<?> carPropertyConfig,
-            CarPropertyManager carPropertyManager, Collection<Integer> valuesToSet) {
-        for (Integer valueToSet : valuesToSet) {
+    private void verifySetterWithValues(CarPropertyConfig<T> carPropertyConfig,
+            CarPropertyManager carPropertyManager, Collection<T> valuesToSet) {
+        for (T valueToSet : valuesToSet) {
             for (int areaId : carPropertyConfig.getAreaIds()) {
-                verifyIntegerSetProperty(carPropertyConfig, carPropertyManager, areaId, valueToSet);
+                verifySetProperty(carPropertyConfig, carPropertyManager, areaId, valueToSet);
             }
         }
     }
@@ -292,26 +285,29 @@
                     Collectors.toList());
 
             for (Integer valueToSet : valuesToSet) {
-                verifyIntegerSetProperty(carPropertyConfig, carPropertyManager, areaId, valueToSet);
+                verifySetProperty((CarPropertyConfig<Integer>) carPropertyConfig,
+                        carPropertyManager, areaId, valueToSet);
             }
         }
     }
 
-    private void verifyIntegerSetProperty(CarPropertyConfig<?> carPropertyConfig,
-            CarPropertyManager carPropertyManager, int areaId, Integer valueToSet) {
-        CarPropertyValue<Integer> currentCarPropertyValue = carPropertyManager.getProperty(
-                mPropertyId, areaId);
-        verifyCarPropertyValue(carPropertyConfig, currentCarPropertyValue, areaId,
-                CAR_PROPERTY_VALUE_SOURCE_GETTER);
-        if (currentCarPropertyValue.getValue().equals(valueToSet)) {
-            return;
+    private void verifyFloatPropertySetter(CarPropertyConfig<?> carPropertyConfig,
+            CarPropertyManager carPropertyManager) {
+        if (!mPossibleCarPropertyValues.isEmpty()) {
+            verifySetterWithValues((CarPropertyConfig<T>) carPropertyConfig, carPropertyManager,
+                    mPossibleCarPropertyValues);
         }
-        verifySetProperty((CarPropertyConfig<Integer>) carPropertyConfig, carPropertyManager,
-                areaId, valueToSet);
     }
 
     private <T> void verifySetProperty(CarPropertyConfig<T> carPropertyConfig,
             CarPropertyManager carPropertyManager, int areaId, T valueToSet) {
+        CarPropertyValue<T> currentCarPropertyValue = carPropertyManager.getProperty(
+                mPropertyId, areaId);
+        verifyCarPropertyValue(carPropertyConfig, currentCarPropertyValue, areaId,
+                CAR_PROPERTY_VALUE_SOURCE_GETTER);
+        if (valueEquals(valueToSet, currentCarPropertyValue.getValue())) {
+            return;
+        }
         SetterCallback setterCallback = new SetterCallback(mPropertyId, mPropertyName, areaId,
                 valueToSet);
         assertWithMessage("Failed to register setter callback for " + mPropertyName).that(
@@ -604,9 +600,23 @@
         }
 
         if (!mPossibleCarPropertyValues.isEmpty()) {
-            assertWithMessage(mPropertyName + " - areaId: " + areaId + " - source: " + source
-                    + " value must be listed in the Integer set")
-                    .that(carPropertyValue.getValue()).isIn(mPossibleCarPropertyValues);
+            if (Float.class.equals(mPropertyType)) {
+                boolean foundInPossibleValues = false;
+                for (Float possibleValue : (Collection<Float>) mPossibleCarPropertyValues) {
+                    if (floatEquals(possibleValue, (Float) carPropertyValue.getValue())) {
+                        foundInPossibleValues = true;
+                        break;
+                    }
+                }
+                assertWithMessage(
+                        mPropertyName + " - areaId: " + areaId + " - source: " + source + " value: "
+                                + carPropertyValue.getValue() + " must be listed in the Float set: "
+                                + mPossibleCarPropertyValues).that(foundInPossibleValues).isTrue();
+            } else {
+                assertWithMessage(mPropertyName + " - areaId: " + areaId + " - source: " + source
+                        + " value must be listed in the set").that(
+                        carPropertyValue.getValue()).isIn(mPossibleCarPropertyValues);
+            }
         }
 
         mCarPropertyValueVerifier.ifPresent(
@@ -705,7 +715,7 @@
         private Optional<CarPropertyValueVerifier> mCarPropertyValueVerifier = Optional.empty();
         private Optional<AreaIdsVerifier> mAreaIdsVerifier = Optional.empty();
         private ImmutableSet<Integer> mPossibleConfigArrayValues = ImmutableSet.of();
-        private ImmutableSet<Integer> mPossibleCarPropertyValues = ImmutableSet.of();
+        private ImmutableSet<T> mPossibleCarPropertyValues = ImmutableSet.of();
         private boolean mRequirePropertyValueToBeInConfigArray = false;
         private boolean mVerifySetterWithConfigArrayValues = false;
         private boolean mRequireMinMaxValues = false;
@@ -750,7 +760,7 @@
         }
 
         public Builder<T> setPossibleCarPropertyValues(
-                ImmutableSet<Integer> possibleCarPropertyValues) {
+                ImmutableSet<T> possibleCarPropertyValues) {
             mPossibleCarPropertyValues = possibleCarPropertyValues;
             return this;
         }
@@ -882,7 +892,7 @@
                     || carPropertyValue.getStatus() != CarPropertyValue.STATUS_AVAILABLE
                     || carPropertyValue.getTimestamp() <= mCreationTimeNanos
                     || carPropertyValue.getTimestamp() >= SystemClock.elapsedRealtimeNanos()
-                    || !carPropertyValue.getValue().equals(mExpectedSetValue)) {
+                    || !valueEquals(mExpectedSetValue, (T) carPropertyValue.getValue())) {
                 return;
             }
             mUpdatedCarPropertyValue = carPropertyValue;
@@ -893,4 +903,12 @@
         public void onErrorEvent(int propId, int zone) {
         }
     }
+
+    private static <V> boolean valueEquals(V v1, V v2) {
+        return (v1 instanceof Float && floatEquals((Float) v1, (Float) v2)) || v1.equals(v2);
+    }
+
+    private static boolean floatEquals(float f1, float f2) {
+        return Math.abs(f1 - f2) < FLOAT_INEQUALITY_THRESHOLD;
+    }
 }