Merge changes I3ac93815,I35dd253e,I274d4480 into main

* changes:
  Add additional HVAC_POWER_ON dependent properties
  Use HVAC_POWER_ON config array for determining power dependent props
  Send CarPropertyValue status when HVAC power state changes
diff --git a/automotive/vehicle/aidl/impl/default_config/config/DefaultProperties.json b/automotive/vehicle/aidl/impl/default_config/config/DefaultProperties.json
index 4a16bf7..6c8d59c 100644
--- a/automotive/vehicle/aidl/impl/default_config/config/DefaultProperties.json
+++ b/automotive/vehicle/aidl/impl/default_config/config/DefaultProperties.json
@@ -1899,8 +1899,16 @@
                 }
             ],
             "configArray": [
+                "VehicleProperty::HVAC_ACTUAL_FAN_SPEED_RPM",
+                "VehicleProperty::HVAC_AC_ON",
+                "VehicleProperty::HVAC_AUTO_ON",
+                "VehicleProperty::HVAC_AUTO_RECIRC_ON",
+                "VehicleProperty::HVAC_FAN_DIRECTION",
                 "VehicleProperty::HVAC_FAN_SPEED",
-                "VehicleProperty::HVAC_FAN_DIRECTION"
+                "VehicleProperty::HVAC_MAX_AC_ON",
+                "VehicleProperty::HVAC_RECIRC_ON",
+                "VehicleProperty::HVAC_TEMPERATURE_CURRENT",
+                "VehicleProperty::HVAC_TEMPERATURE_SET"
             ]
         },
         {
diff --git a/automotive/vehicle/aidl/impl/fake_impl/hardware/include/FakeVehicleHardware.h b/automotive/vehicle/aidl/impl/fake_impl/hardware/include/FakeVehicleHardware.h
index e8da43a..844bea5 100644
--- a/automotive/vehicle/aidl/impl/fake_impl/hardware/include/FakeVehicleHardware.h
+++ b/automotive/vehicle/aidl/impl/fake_impl/hardware/include/FakeVehicleHardware.h
@@ -36,6 +36,7 @@
 #include <memory>
 #include <mutex>
 #include <unordered_map>
+#include <unordered_set>
 #include <vector>
 
 namespace android {
@@ -161,6 +162,9 @@
                                   aidl::android::hardware::automotive::vehicle::SetValueRequest>
             mPendingSetValueRequests;
 
+    // Set of HVAC properties dependent on HVAC_POWER_ON
+    std::unordered_set<int32_t> hvacPowerDependentProps;
+
     const bool mForceOverride;
     bool mAddExtraTestVendorConfigs;
 
@@ -253,7 +257,7 @@
             const aidl::android::hardware::automotive::vehicle::SetValueRequest& request);
 
     std::string genFakeDataCommand(const std::vector<std::string>& options);
-    void sendHvacPropertiesCurrentValues(int32_t areaId);
+    void sendHvacPropertiesCurrentValues(int32_t areaId, int32_t hvacPowerOnVal);
     void sendAdasPropertiesState(int32_t propertyId, int32_t state);
     void generateVendorConfigs(
             std::vector<aidl::android::hardware::automotive::vehicle::VehiclePropConfig>&) const;
diff --git a/automotive/vehicle/aidl/impl/fake_impl/hardware/src/FakeVehicleHardware.cpp b/automotive/vehicle/aidl/impl/fake_impl/hardware/src/FakeVehicleHardware.cpp
index 13c48c6..ee24fbd 100644
--- a/automotive/vehicle/aidl/impl/fake_impl/hardware/src/FakeVehicleHardware.cpp
+++ b/automotive/vehicle/aidl/impl/fake_impl/hardware/src/FakeVehicleHardware.cpp
@@ -200,6 +200,11 @@
     bool globalProp = isGlobalProp(propId);
     size_t numAreas = globalProp ? 1 : vehiclePropConfig.areaConfigs.size();
 
+    if (propId == toInt(VehicleProperty::HVAC_POWER_ON)) {
+        const auto& configArray = vehiclePropConfig.configArray;
+        hvacPowerDependentProps.insert(configArray.begin(), configArray.end());
+    }
+
     for (size_t i = 0; i < numAreas; i++) {
         int32_t curArea = globalProp ? 0 : vehiclePropConfig.areaConfigs[i].areaId;
 
@@ -511,9 +516,7 @@
 }
 
 bool FakeVehicleHardware::isHvacPropAndHvacNotAvailable(int32_t propId, int32_t areaId) const {
-    std::unordered_set<int32_t> powerProps(std::begin(HVAC_POWER_PROPERTIES),
-                                           std::end(HVAC_POWER_PROPERTIES));
-    if (powerProps.count(propId)) {
+    if (hvacPowerDependentProps.count(propId)) {
         auto hvacPowerOnResults =
                 mServerSidePropStore->readValuesForProperty(toInt(VehicleProperty::HVAC_POWER_ON));
         if (!hvacPowerOnResults.ok()) {
@@ -731,9 +734,8 @@
     return std::move(gotValue);
 }
 
-void FakeVehicleHardware::sendHvacPropertiesCurrentValues(int32_t areaId) {
-    for (size_t i = 0; i < sizeof(HVAC_POWER_PROPERTIES) / sizeof(int32_t); i++) {
-        int powerPropId = HVAC_POWER_PROPERTIES[i];
+void FakeVehicleHardware::sendHvacPropertiesCurrentValues(int32_t areaId, int32_t hvacPowerOnVal) {
+    for (auto& powerPropId : hvacPowerDependentProps) {
         auto powerPropResults = mServerSidePropStore->readValuesForProperty(powerPropId);
         if (!powerPropResults.ok()) {
             ALOGW("failed to get power prop 0x%x, error: %s", powerPropId,
@@ -744,7 +746,8 @@
         for (size_t j = 0; j < powerPropValues.size(); j++) {
             auto powerPropValue = std::move(powerPropValues[j]);
             if ((powerPropValue->areaId & areaId) == powerPropValue->areaId) {
-                powerPropValue->status = VehiclePropertyStatus::AVAILABLE;
+                powerPropValue->status = hvacPowerOnVal ? VehiclePropertyStatus::AVAILABLE
+                                                        : VehiclePropertyStatus::UNAVAILABLE;
                 powerPropValue->timestamp = elapsedRealtimeNano();
                 // This will trigger a property change event for the current hvac property value.
                 mServerSidePropStore->writeValue(std::move(powerPropValue), /*updateStatus=*/true,
@@ -796,13 +799,6 @@
         return setUserHalProp(value);
     }
 
-    if (propId == toInt(VehicleProperty::HVAC_POWER_ON) && value.value.int32Values.size() == 1 &&
-        value.value.int32Values[0] == 1) {
-        // If we are turning HVAC power on, send current hvac property values through on change
-        // event.
-        sendHvacPropertiesCurrentValues(value.areaId);
-    }
-
     if (isHvacPropAndHvacNotAvailable(propId, value.areaId)) {
         *isSpecialValue = true;
         return StatusError(StatusCode::NOT_AVAILABLE_DISABLED) << "hvac not available";
@@ -841,6 +837,16 @@
         case toInt(TestVendorProperty::VENDOR_PROPERTY_FOR_ERROR_CODE_TESTING):
             *isSpecialValue = true;
             return StatusError((StatusCode)VENDOR_ERROR_CODE);
+        case toInt(VehicleProperty::HVAC_POWER_ON):
+            if (value.value.int32Values.size() != 1) {
+                *isSpecialValue = true;
+                return StatusError(StatusCode::INVALID_ARG)
+                       << "HVAC_POWER_ON requires only one int32 value";
+            }
+            // When changing HVAC power state, send current hvac property values
+            // through on change event.
+            sendHvacPropertiesCurrentValues(value.areaId, value.value.int32Values[0]);
+            return {};
         case toInt(VehicleProperty::HVAC_TEMPERATURE_VALUE_SUGGESTION):
             *isSpecialValue = true;
             return setHvacTemperatureValueSuggestion(value);
diff --git a/automotive/vehicle/aidl/impl/fake_impl/hardware/test/FakeVehicleHardwareTest.cpp b/automotive/vehicle/aidl/impl/fake_impl/hardware/test/FakeVehicleHardwareTest.cpp
index 6cc06bc..cf9beee 100644
--- a/automotive/vehicle/aidl/impl/fake_impl/hardware/test/FakeVehicleHardwareTest.cpp
+++ b/automotive/vehicle/aidl/impl/fake_impl/hardware/test/FakeVehicleHardwareTest.cpp
@@ -35,6 +35,7 @@
 #include <inttypes.h>
 #include <chrono>
 #include <condition_variable>
+#include <memory>
 #include <unordered_map>
 #include <unordered_set>
 #include <vector>
@@ -78,7 +79,9 @@
 using ::aidl::android::hardware::automotive::vehicle::VehicleHwKeyInputAction;
 using ::aidl::android::hardware::automotive::vehicle::VehiclePropConfig;
 using ::aidl::android::hardware::automotive::vehicle::VehicleProperty;
+using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyAccess;
 using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyStatus;
+using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType;
 using ::aidl::android::hardware::automotive::vehicle::VehiclePropValue;
 using ::aidl::android::hardware::automotive::vehicle::VehicleUnit;
 using ::android::base::expected;
@@ -109,6 +112,10 @@
         return mHardware->loadConfigDeclarations();
     }
 
+    std::unordered_set<int32_t> getHvacPowerDependentProps() {
+        return mHardware->hvacPowerDependentProps;
+    }
+
   private:
     FakeVehicleHardware* mHardware;
 };
@@ -390,6 +397,25 @@
         }
     } mPropValueCmp;
 
+    std::unique_ptr<VehiclePropConfig> getVehiclePropConfig(int32_t propertyId) {
+        auto configs = mHardware->getAllPropertyConfigs();
+        for (auto& config : configs) {
+            if (config.prop == propertyId) {
+                auto ptr = std::make_unique<VehiclePropConfig>();
+                ptr->prop = config.prop;
+                ptr->access = config.access;
+                ptr->changeMode = config.changeMode;
+                ptr->areaConfigs = config.areaConfigs;
+                ptr->configArray = config.configArray;
+                ptr->configString = config.configString;
+                ptr->minSampleRate = config.minSampleRate;
+                ptr->maxSampleRate = config.maxSampleRate;
+                return ptr;
+            }
+        }
+        return std::unique_ptr<VehiclePropConfig>(nullptr);
+    }
+
   private:
     std::unique_ptr<FakeVehicleHardware> mHardware;
     std::shared_ptr<IVehicleHardware::SetValuesCallback> mSetValuesCallback;
@@ -1687,23 +1713,35 @@
 }
 
 TEST_F(FakeVehicleHardwareTest, testGetHvacPropNotAvailable) {
-    int seatAreaIds[5] = {SEAT_1_LEFT, SEAT_1_RIGHT, SEAT_2_LEFT, SEAT_2_CENTER, SEAT_2_RIGHT};
-    for (int areaId : seatAreaIds) {
+    FakeVehicleHardwareTestHelper helper(getHardware());
+    auto hvacPowerOnConfig = std::move(getVehiclePropConfig(toInt(VehicleProperty::HVAC_POWER_ON)));
+    EXPECT_NE(hvacPowerOnConfig, nullptr);
+    for (auto& hvacPowerOnAreaConfig : hvacPowerOnConfig->areaConfigs) {
+        int hvacPowerAreaId = hvacPowerOnAreaConfig.areaId;
+        // Turn off HVAC_POWER_ON for only 1 area ID
         StatusCode status = setValue(VehiclePropValue{.prop = toInt(VehicleProperty::HVAC_POWER_ON),
-                                                      .areaId = areaId,
+                                                      .areaId = hvacPowerAreaId,
                                                       .value.int32Values = {0}});
+        EXPECT_EQ(status, StatusCode::OK);
 
-        ASSERT_EQ(status, StatusCode::OK);
-
-        for (size_t i = 0; i < sizeof(HVAC_POWER_PROPERTIES) / sizeof(int32_t); i++) {
-            int powerPropId = HVAC_POWER_PROPERTIES[i];
-            for (int powerDependentAreaId : seatAreaIds) {
+        for (auto& powerPropId : helper.getHvacPowerDependentProps()) {
+            auto powerPropConfig = std::move(getVehiclePropConfig(powerPropId));
+            EXPECT_NE(powerPropConfig, nullptr);
+            if (powerPropConfig->access == VehiclePropertyAccess::WRITE) {
+                continue;
+            }
+            // Try getting a value at each area ID supported by the power dependent property
+            for (auto& powerPropAreaConfig : powerPropConfig->areaConfigs) {
+                int powerDependentAreaId = powerPropAreaConfig.areaId;
                 auto getValueResult = getValue(VehiclePropValue{
                         .prop = powerPropId,
                         .areaId = powerDependentAreaId,
                 });
 
-                if (areaId == powerDependentAreaId) {
+                // If the current area ID is contained within the HVAC_POWER_ON area ID
+                // turned off, then getValue should fail and a StatusCode error should be
+                // returned. Otherwise, a value should be returned.
+                if ((hvacPowerAreaId & powerDependentAreaId) == powerDependentAreaId) {
                     EXPECT_FALSE(getValueResult.ok());
                     EXPECT_EQ(getValueResult.error(), StatusCode::NOT_AVAILABLE_DISABLED);
                 } else {
@@ -1716,28 +1754,45 @@
         // on this value from any power dependent property values other than those with the same
         // areaId.
         setValue(VehiclePropValue{.prop = toInt(VehicleProperty::HVAC_POWER_ON),
-                                  .areaId = areaId,
+                                  .areaId = hvacPowerAreaId,
                                   .value.int32Values = {1}});
     }
 }
 
 TEST_F(FakeVehicleHardwareTest, testSetHvacPropNotAvailable) {
-    int seatAreaIds[5] = {SEAT_1_LEFT, SEAT_1_RIGHT, SEAT_2_LEFT, SEAT_2_CENTER, SEAT_2_RIGHT};
-    for (int areaId : seatAreaIds) {
+    FakeVehicleHardwareTestHelper helper(getHardware());
+    auto hvacPowerOnConfig = std::move(getVehiclePropConfig(toInt(VehicleProperty::HVAC_POWER_ON)));
+    EXPECT_NE(hvacPowerOnConfig, nullptr);
+    for (auto& hvacPowerOnAreaConfig : hvacPowerOnConfig->areaConfigs) {
+        int hvacPowerAreaId = hvacPowerOnAreaConfig.areaId;
+        // Turn off HVAC_POWER_ON for only 1 area ID
         StatusCode status = setValue(VehiclePropValue{.prop = toInt(VehicleProperty::HVAC_POWER_ON),
-                                                      .areaId = areaId,
+                                                      .areaId = hvacPowerAreaId,
                                                       .value.int32Values = {0}});
+        EXPECT_EQ(status, StatusCode::OK);
 
-        ASSERT_EQ(status, StatusCode::OK);
+        for (auto& powerPropId : helper.getHvacPowerDependentProps()) {
+            auto powerPropConfig = std::move(getVehiclePropConfig(powerPropId));
+            EXPECT_NE(powerPropConfig, nullptr);
+            if (powerPropConfig->access == VehiclePropertyAccess::READ) {
+                continue;
+            }
+            auto propType = getPropType(powerPropId);
+            // Try setting a value at each area ID supported by the power dependent property
+            for (auto& powerPropAreaConfig : powerPropConfig->areaConfigs) {
+                int powerDependentAreaId = powerPropAreaConfig.areaId;
+                auto val = VehiclePropValue{.prop = powerPropId, .areaId = powerDependentAreaId};
+                if (propType == VehiclePropertyType::FLOAT) {
+                    val.value.floatValues.emplace_back(20);
+                } else {
+                    val.value.int32Values.emplace_back(1);
+                }
+                status = setValue(val);
 
-        for (size_t i = 0; i < sizeof(HVAC_POWER_PROPERTIES) / sizeof(int32_t); i++) {
-            int powerPropId = HVAC_POWER_PROPERTIES[i];
-            for (int powerDependentAreaId : seatAreaIds) {
-                StatusCode status = setValue(VehiclePropValue{.prop = powerPropId,
-                                                              .areaId = powerDependentAreaId,
-                                                              .value.int32Values = {1}});
-
-                if (areaId == powerDependentAreaId) {
+                // If the current area ID is contained within the HVAC_POWER_ON area ID
+                // turned off, then setValue should fail and a StatusCode error should be
+                // returned. Otherwise, an ok StatusCode should be returned.
+                if ((hvacPowerAreaId & powerDependentAreaId) == powerDependentAreaId) {
                     EXPECT_EQ(status, StatusCode::NOT_AVAILABLE_DISABLED);
                 } else {
                     EXPECT_EQ(status, StatusCode::OK);
@@ -1749,38 +1804,48 @@
         // on this value from any power dependent property values other than those with the same
         // areaId.
         setValue(VehiclePropValue{.prop = toInt(VehicleProperty::HVAC_POWER_ON),
-                                  .areaId = areaId,
+                                  .areaId = hvacPowerAreaId,
                                   .value.int32Values = {1}});
     }
 }
 
 TEST_F(FakeVehicleHardwareTest, testHvacPowerOnSendCurrentHvacPropValues) {
-    int seatAreaIds[5] = {SEAT_1_LEFT, SEAT_1_RIGHT, SEAT_2_LEFT, SEAT_2_CENTER, SEAT_2_RIGHT};
-    for (int areaId : seatAreaIds) {
+    FakeVehicleHardwareTestHelper helper(getHardware());
+    auto hvacPowerOnConfig = std::move(getVehiclePropConfig(toInt(VehicleProperty::HVAC_POWER_ON)));
+    EXPECT_NE(hvacPowerOnConfig, nullptr);
+    for (auto& hvacPowerOnAreaConfig : hvacPowerOnConfig->areaConfigs) {
+        int hvacPowerAreaId = hvacPowerOnAreaConfig.areaId;
         StatusCode status = setValue(VehiclePropValue{.prop = toInt(VehicleProperty::HVAC_POWER_ON),
-                                                      .areaId = areaId,
+                                                      .areaId = hvacPowerAreaId,
                                                       .value.int32Values = {0}});
-
-        ASSERT_EQ(status, StatusCode::OK);
-
-        clearChangedProperties();
-        setValue(VehiclePropValue{.prop = toInt(VehicleProperty::HVAC_POWER_ON),
-                                  .areaId = areaId,
-                                  .value.int32Values = {1}});
-
+        EXPECT_EQ(status, StatusCode::OK);
         auto events = getChangedProperties();
-        // If we turn HVAC power on, we expect to receive one property event for every HVAC prop
-        // areas plus one event for HVAC_POWER_ON.
-        std::vector<int32_t> changedPropIds;
-        for (size_t i = 0; i < sizeof(HVAC_POWER_PROPERTIES) / sizeof(int32_t); i++) {
-            changedPropIds.push_back(HVAC_POWER_PROPERTIES[i]);
-        }
-        changedPropIds.push_back(toInt(VehicleProperty::HVAC_POWER_ON));
-
         for (const auto& event : events) {
-            EXPECT_EQ(event.areaId, areaId);
-            EXPECT_THAT(event.prop, AnyOfArray(changedPropIds));
+            // Ignore HVAC_POWER_ON event
+            if (event.prop == toInt(VehicleProperty::HVAC_POWER_ON)) {
+                continue;
+            }
+            EXPECT_THAT(event.prop, AnyOfArray(helper.getHvacPowerDependentProps()));
+            EXPECT_EQ((hvacPowerAreaId & event.areaId), hvacPowerAreaId);
+            EXPECT_EQ(event.status, VehiclePropertyStatus::UNAVAILABLE);
         }
+        clearChangedProperties();
+
+        status = setValue(VehiclePropValue{.prop = toInt(VehicleProperty::HVAC_POWER_ON),
+                                           .areaId = hvacPowerAreaId,
+                                           .value.int32Values = {1}});
+        EXPECT_EQ(status, StatusCode::OK);
+        events = getChangedProperties();
+        for (const auto& event : events) {
+            // Ignore HVAC_POWER_ON event
+            if (event.prop == toInt(VehicleProperty::HVAC_POWER_ON)) {
+                continue;
+            }
+            EXPECT_THAT(event.prop, AnyOfArray(helper.getHvacPowerDependentProps()));
+            EXPECT_EQ((hvacPowerAreaId & event.areaId), hvacPowerAreaId);
+            EXPECT_EQ(event.status, VehiclePropertyStatus::AVAILABLE);
+        }
+        clearChangedProperties();
     }
 }
 
@@ -3016,13 +3081,8 @@
 
     // Config array values from HVAC_TEMPERATURE_SET in DefaultProperties.json
     auto configs = getHardware()->getAllPropertyConfigs();
-    VehiclePropConfig* hvacTemperatureSetConfig = nullptr;
-    for (auto& config : configs) {
-        if (config.prop == toInt(VehicleProperty::HVAC_TEMPERATURE_SET)) {
-            hvacTemperatureSetConfig = &config;
-            break;
-        }
-    }
+    auto hvacTemperatureSetConfig =
+            std::move(getVehiclePropConfig(toInt(VehicleProperty::HVAC_TEMPERATURE_SET)));
     EXPECT_NE(hvacTemperatureSetConfig, nullptr);
 
     auto& hvacTemperatureSetConfigArray = hvacTemperatureSetConfig->configArray;
diff --git a/automotive/vehicle/aidl/impl/utils/common/include/PropertyUtils.h b/automotive/vehicle/aidl/impl/utils/common/include/PropertyUtils.h
index e41ec30..78b61f7 100644
--- a/automotive/vehicle/aidl/impl/utils/common/include/PropertyUtils.h
+++ b/automotive/vehicle/aidl/impl/utils/common/include/PropertyUtils.h
@@ -98,11 +98,6 @@
 constexpr int HVAC_RIGHT = SEAT_1_RIGHT | SEAT_2_RIGHT;
 constexpr int HVAC_ALL = HVAC_LEFT | HVAC_RIGHT;
 
-const int32_t HVAC_POWER_PROPERTIES[] = {
-        toInt(propertyutils_impl::VehicleProperty::HVAC_FAN_SPEED),
-        toInt(propertyutils_impl::VehicleProperty::HVAC_FAN_DIRECTION),
-};
-
 }  // namespace vehicle
 }  // namespace automotive
 }  // namespace hardware