Merge "Add UNKNOWN fan direction to HVAC_FAN_DIRECTION_AVAILABLE for emulator" into udc-dev
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 7b74092..84395a2 100644
--- a/automotive/vehicle/aidl/impl/fake_impl/hardware/include/FakeVehicleHardware.h
+++ b/automotive/vehicle/aidl/impl/fake_impl/hardware/include/FakeVehicleHardware.h
@@ -195,6 +195,8 @@
             const aidl::android::hardware::automotive::vehicle::VehiclePropValue& value);
     VehiclePropValuePool::RecyclableType createApPowerStateReq(
             aidl::android::hardware::automotive::vehicle::VehicleApPowerStateReq state);
+    VehiclePropValuePool::RecyclableType createAdasStateReq(int32_t propertyId, int32_t areaId,
+                                                            int32_t state);
     VhalResult<void> setUserHalProp(
             const aidl::android::hardware::automotive::vehicle::VehiclePropValue& value);
     ValueResultType getUserHalProp(
@@ -202,6 +204,7 @@
     ValueResultType getEchoReverseBytes(
             const aidl::android::hardware::automotive::vehicle::VehiclePropValue& value) const;
     bool isHvacPropAndHvacNotAvailable(int32_t propId, int32_t areaId) const;
+    VhalResult<void> isAdasPropertyAvailable(int32_t adasStatePropertyId) const;
 
     std::unordered_map<int32_t, ConfigDeclaration> loadConfigDeclarations();
 
@@ -244,6 +247,7 @@
 
     std::string genFakeDataCommand(const std::vector<std::string>& options);
     void sendHvacPropertiesCurrentValues(int32_t areaId);
+    void sendAdasPropertiesState(int32_t propertyId, int32_t state);
 
     static aidl::android::hardware::automotive::vehicle::VehiclePropValue createHwInputKeyProp(
             aidl::android::hardware::automotive::vehicle::VehicleHwKeyInputAction action,
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 096a6cd..577442e 100644
--- a/automotive/vehicle/aidl/impl/fake_impl/hardware/src/FakeVehicleHardware.cpp
+++ b/automotive/vehicle/aidl/impl/fake_impl/hardware/src/FakeVehicleHardware.cpp
@@ -52,6 +52,7 @@
 
 namespace {
 
+using ::aidl::android::hardware::automotive::vehicle::ErrorState;
 using ::aidl::android::hardware::automotive::vehicle::GetValueRequest;
 using ::aidl::android::hardware::automotive::vehicle::GetValueResult;
 using ::aidl::android::hardware::automotive::vehicle::RawPropValues;
@@ -107,6 +108,74 @@
         // Timestamp in int64.
         "-t"};
 
+// ADAS _ENABLED property to list of ADAS state properties using ErrorState enum.
+const std::unordered_map<int32_t, std::vector<int32_t>> mAdasEnabledPropToAdasPropWithErrorState = {
+        // AEB
+        {
+                toInt(VehicleProperty::AUTOMATIC_EMERGENCY_BRAKING_ENABLED),
+                {
+                        toInt(VehicleProperty::AUTOMATIC_EMERGENCY_BRAKING_STATE),
+                },
+        },
+        // FCW
+        {
+                toInt(VehicleProperty::FORWARD_COLLISION_WARNING_ENABLED),
+                {
+                        toInt(VehicleProperty::FORWARD_COLLISION_WARNING_STATE),
+                },
+        },
+        // BSW
+        {
+                toInt(VehicleProperty::BLIND_SPOT_WARNING_ENABLED),
+                {
+                        toInt(VehicleProperty::BLIND_SPOT_WARNING_STATE),
+                },
+        },
+        // LDW
+        {
+                toInt(VehicleProperty::LANE_DEPARTURE_WARNING_ENABLED),
+                {
+                        toInt(VehicleProperty::LANE_DEPARTURE_WARNING_STATE),
+                },
+        },
+        // LKA
+        {
+                toInt(VehicleProperty::LANE_KEEP_ASSIST_ENABLED),
+                {
+                        toInt(VehicleProperty::LANE_KEEP_ASSIST_STATE),
+                },
+        },
+        // LCA
+        {
+                toInt(VehicleProperty::LANE_CENTERING_ASSIST_ENABLED),
+                {
+                        toInt(VehicleProperty::LANE_CENTERING_ASSIST_STATE),
+                },
+        },
+        // ELKA
+        {
+                toInt(VehicleProperty::EMERGENCY_LANE_KEEP_ASSIST_ENABLED),
+                {
+                        toInt(VehicleProperty::EMERGENCY_LANE_KEEP_ASSIST_STATE),
+                },
+        },
+        // CC
+        {
+                toInt(VehicleProperty::CRUISE_CONTROL_ENABLED),
+                {
+                        toInt(VehicleProperty::CRUISE_CONTROL_TYPE),
+                        toInt(VehicleProperty::CRUISE_CONTROL_STATE),
+                },
+        },
+        // HOD
+        {
+                toInt(VehicleProperty::HANDS_ON_DETECTION_ENABLED),
+                {
+                        toInt(VehicleProperty::HANDS_ON_DETECTION_DRIVER_STATE),
+                        toInt(VehicleProperty::HANDS_ON_DETECTION_WARNING),
+                },
+        },
+};
 }  // namespace
 
 void FakeVehicleHardware::storePropInitialValue(const ConfigDeclaration& config) {
@@ -238,6 +307,18 @@
     return req;
 }
 
+VehiclePropValuePool::RecyclableType FakeVehicleHardware::createAdasStateReq(int32_t propertyId,
+                                                                             int32_t areaId,
+                                                                             int32_t state) {
+    auto req = mValuePool->obtain(VehiclePropertyType::INT32);
+    req->prop = propertyId;
+    req->areaId = areaId;
+    req->timestamp = elapsedRealtimeNano();
+    req->status = VehiclePropertyStatus::AVAILABLE;
+    req->value.int32Values[0] = state;
+    return req;
+}
+
 VhalResult<void> FakeVehicleHardware::setApPowerStateReport(const VehiclePropValue& value) {
     auto updatedValue = mValuePool->obtain(value);
     updatedValue->timestamp = elapsedRealtimeNano();
@@ -413,6 +494,41 @@
     return false;
 }
 
+VhalResult<void> FakeVehicleHardware::isAdasPropertyAvailable(int32_t adasStatePropertyId) const {
+    auto adasStateResult = mServerSidePropStore->readValue(adasStatePropertyId);
+    if (!adasStateResult.ok()) {
+        ALOGW("Failed to get ADAS ENABLED property 0x%x, error: %s", adasStatePropertyId,
+              getErrorMsg(adasStateResult).c_str());
+        return {};
+    }
+
+    if (adasStateResult.value()->value.int32Values.size() == 1 &&
+        adasStateResult.value()->value.int32Values[0] < 0) {
+        auto errorState = adasStateResult.value()->value.int32Values[0];
+        switch (errorState) {
+            case toInt(ErrorState::NOT_AVAILABLE_DISABLED):
+                return StatusError(StatusCode::NOT_AVAILABLE_DISABLED)
+                       << "ADAS feature is disabled.";
+            case toInt(ErrorState::NOT_AVAILABLE_SPEED_LOW):
+                return StatusError(StatusCode::NOT_AVAILABLE_SPEED_LOW)
+                       << "ADAS feature is disabled because the vehicle speed is too low.";
+            case toInt(ErrorState::NOT_AVAILABLE_SPEED_HIGH):
+                return StatusError(StatusCode::NOT_AVAILABLE_SPEED_HIGH)
+                       << "ADAS feature is disabled because the vehicle speed is too high.";
+            case toInt(ErrorState::NOT_AVAILABLE_POOR_VISIBILITY):
+                return StatusError(StatusCode::NOT_AVAILABLE_POOR_VISIBILITY)
+                       << "ADAS feature is disabled because the visibility is too poor.";
+            case toInt(ErrorState::NOT_AVAILABLE_SAFETY):
+                return StatusError(StatusCode::NOT_AVAILABLE_SAFETY)
+                       << "ADAS feature is disabled because of safety reasons.";
+            default:
+                return StatusError(StatusCode::NOT_AVAILABLE) << "ADAS feature is not available.";
+        }
+    }
+
+    return {};
+}
+
 VhalResult<void> FakeVehicleHardware::setUserHalProp(const VehiclePropValue& value) {
     auto result = mFakeUserHal->onSetProperty(value);
     if (!result.ok()) {
@@ -495,6 +611,19 @@
         case VENDOR_PROPERTY_ID:
             *isSpecialValue = true;
             return StatusError((StatusCode)VENDOR_ERROR_CODE);
+        case toInt(VehicleProperty::CRUISE_CONTROL_TARGET_SPEED):
+            [[fallthrough]];
+        case toInt(VehicleProperty::ADAPTIVE_CRUISE_CONTROL_TARGET_TIME_GAP):
+            [[fallthrough]];
+        case toInt(VehicleProperty::ADAPTIVE_CRUISE_CONTROL_LEAD_VEHICLE_MEASURED_DISTANCE): {
+            auto isAdasPropertyAvailableResult =
+                    isAdasPropertyAvailable(toInt(VehicleProperty::CRUISE_CONTROL_STATE));
+            if (!isAdasPropertyAvailableResult.ok()) {
+                *isSpecialValue = true;
+                return isAdasPropertyAvailableResult.error();
+            }
+            return nullptr;
+        }
         default:
             // Do nothing.
             break;
@@ -542,6 +671,25 @@
     }
 }
 
+void FakeVehicleHardware::sendAdasPropertiesState(int32_t propertyId, int32_t state) {
+    auto& adasDependentPropIds = mAdasEnabledPropToAdasPropWithErrorState.find(propertyId)->second;
+    for (auto dependentPropId : adasDependentPropIds) {
+        auto dependentPropConfigResult = mServerSidePropStore->getConfig(dependentPropId);
+        if (!dependentPropConfigResult.ok()) {
+            ALOGW("Failed to get config for ADAS property 0x%x, error: %s", dependentPropId,
+                  getErrorMsg(dependentPropConfigResult).c_str());
+            continue;
+        }
+        auto& dependentPropConfig = dependentPropConfigResult.value();
+        for (auto& areaConfig : dependentPropConfig->areaConfigs) {
+            auto propValue = createAdasStateReq(dependentPropId, areaConfig.areaId, state);
+            // This will trigger a property change event for the current ADAS property value.
+            mServerSidePropStore->writeValue(std::move(propValue), /*updateStatus=*/true,
+                                             VehiclePropertyStore::EventMode::ALWAYS);
+        }
+    }
+}
+
 VhalResult<void> FakeVehicleHardware::maybeSetSpecialValue(const VehiclePropValue& value,
                                                            bool* isSpecialValue) {
     *isSpecialValue = false;
@@ -565,6 +713,16 @@
         return StatusError(StatusCode::NOT_AVAILABLE_DISABLED) << "hvac not available";
     }
 
+    if (mAdasEnabledPropToAdasPropWithErrorState.count(propId) &&
+        value.value.int32Values.size() == 1) {
+        if (value.value.int32Values[0] == 1) {
+            // Set default state to 1 when ADAS feature is enabled.
+            sendAdasPropertiesState(propId, /* state = */ 1);
+        } else {
+            sendAdasPropertiesState(propId, toInt(ErrorState::NOT_AVAILABLE_DISABLED));
+        }
+    }
+
     switch (propId) {
         case toInt(VehicleProperty::AP_POWER_STATE_REPORT):
             *isSpecialValue = true;
@@ -583,6 +741,24 @@
         case toInt(VehicleProperty::HVAC_TEMPERATURE_VALUE_SUGGESTION):
             *isSpecialValue = true;
             return setHvacTemperatureValueSuggestion(value);
+        case toInt(VehicleProperty::LANE_CENTERING_ASSIST_COMMAND): {
+            auto isAdasPropertyAvailableResult =
+                    isAdasPropertyAvailable(toInt(VehicleProperty::LANE_CENTERING_ASSIST_STATE));
+            if (!isAdasPropertyAvailableResult.ok()) {
+                *isSpecialValue = true;
+            }
+            return isAdasPropertyAvailableResult;
+        }
+        case toInt(VehicleProperty::CRUISE_CONTROL_COMMAND):
+            [[fallthrough]];
+        case toInt(VehicleProperty::ADAPTIVE_CRUISE_CONTROL_TARGET_TIME_GAP): {
+            auto isAdasPropertyAvailableResult =
+                    isAdasPropertyAvailable(toInt(VehicleProperty::CRUISE_CONTROL_STATE));
+            if (!isAdasPropertyAvailableResult.ok()) {
+                *isSpecialValue = true;
+            }
+            return isAdasPropertyAvailableResult;
+        }
 
 #ifdef ENABLE_VEHICLE_HAL_TEST_PROPERTIES
         case toInt(VehicleProperty::CLUSTER_REPORT_STATE):
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 b399bdf..8d385dd 100644
--- a/automotive/vehicle/aidl/impl/fake_impl/hardware/test/FakeVehicleHardwareTest.cpp
+++ b/automotive/vehicle/aidl/impl/fake_impl/hardware/test/FakeVehicleHardwareTest.cpp
@@ -60,6 +60,7 @@
 namespace fake {
 namespace {
 
+using ::aidl::android::hardware::automotive::vehicle::ErrorState;
 using ::aidl::android::hardware::automotive::vehicle::GetValueRequest;
 using ::aidl::android::hardware::automotive::vehicle::GetValueResult;
 using ::aidl::android::hardware::automotive::vehicle::RawPropValues;
@@ -68,6 +69,7 @@
 using ::aidl::android::hardware::automotive::vehicle::StatusCode;
 using ::aidl::android::hardware::automotive::vehicle::VehicleApPowerStateReport;
 using ::aidl::android::hardware::automotive::vehicle::VehicleApPowerStateReq;
+using ::aidl::android::hardware::automotive::vehicle::VehicleAreaMirror;
 using ::aidl::android::hardware::automotive::vehicle::VehicleHwKeyInputAction;
 using ::aidl::android::hardware::automotive::vehicle::VehiclePropConfig;
 using ::aidl::android::hardware::automotive::vehicle::VehicleProperty;
@@ -1035,6 +1037,488 @@
                                     },
                             },
             },
+            SetSpecialValueTestCase{
+                    .name = "set_automatic_emergency_braking_enabled_false",
+                    .valuesToSet =
+                            {
+                                    VehiclePropValue{
+                                            .prop = toInt(
+                                                    VehicleProperty::
+                                                            AUTOMATIC_EMERGENCY_BRAKING_ENABLED),
+                                            .value.int32Values = {0},
+                                    },
+                            },
+                    .expectedValuesToGet =
+                            {
+                                    VehiclePropValue{
+                                            .prop = toInt(
+                                                    VehicleProperty::
+                                                            AUTOMATIC_EMERGENCY_BRAKING_ENABLED),
+                                            .value.int32Values = {0},
+                                    },
+                                    VehiclePropValue{
+                                            .prop = toInt(
+                                                    VehicleProperty::
+                                                            AUTOMATIC_EMERGENCY_BRAKING_STATE),
+                                            .value.int32Values = {toInt(
+                                                    ErrorState::NOT_AVAILABLE_DISABLED)},
+                                    },
+                            },
+            },
+            SetSpecialValueTestCase{
+                    .name = "set_automatic_emergency_braking_enabled_true",
+                    .valuesToSet =
+                            {
+                                    VehiclePropValue{
+                                            .prop = toInt(
+                                                    VehicleProperty::
+                                                            AUTOMATIC_EMERGENCY_BRAKING_ENABLED),
+                                            .value.int32Values = {1},
+                                    },
+                            },
+                    .expectedValuesToGet =
+                            {
+                                    VehiclePropValue{
+                                            .prop = toInt(
+                                                    VehicleProperty::
+                                                            AUTOMATIC_EMERGENCY_BRAKING_ENABLED),
+                                            .value.int32Values = {1},
+                                    },
+                                    VehiclePropValue{
+                                            .prop = toInt(
+                                                    VehicleProperty::
+                                                            AUTOMATIC_EMERGENCY_BRAKING_STATE),
+                                            .value.int32Values = {1},
+                                    },
+                            },
+            },
+            SetSpecialValueTestCase{
+                    .name = "set_forward_collision_warning_enabled_false",
+                    .valuesToSet =
+                            {
+                                    VehiclePropValue{
+                                            .prop = toInt(
+                                                    VehicleProperty::
+                                                            FORWARD_COLLISION_WARNING_ENABLED),
+                                            .value.int32Values = {0},
+                                    },
+                            },
+                    .expectedValuesToGet =
+                            {
+                                    VehiclePropValue{
+                                            .prop = toInt(
+                                                    VehicleProperty::
+                                                            FORWARD_COLLISION_WARNING_ENABLED),
+                                            .value.int32Values = {0},
+                                    },
+                                    VehiclePropValue{
+                                            .prop = toInt(VehicleProperty::
+                                                                  FORWARD_COLLISION_WARNING_STATE),
+                                            .value.int32Values = {toInt(
+                                                    ErrorState::NOT_AVAILABLE_DISABLED)},
+                                    },
+                            },
+            },
+            SetSpecialValueTestCase{
+                    .name = "set_forward_collision_warning_enabled_true",
+                    .valuesToSet =
+                            {
+                                    VehiclePropValue{
+                                            .prop = toInt(
+                                                    VehicleProperty::
+                                                            FORWARD_COLLISION_WARNING_ENABLED),
+                                            .value.int32Values = {1},
+                                    },
+                            },
+                    .expectedValuesToGet =
+                            {
+                                    VehiclePropValue{
+                                            .prop = toInt(
+                                                    VehicleProperty::
+                                                            FORWARD_COLLISION_WARNING_ENABLED),
+                                            .value.int32Values = {1},
+                                    },
+                                    VehiclePropValue{
+                                            .prop = toInt(VehicleProperty::
+                                                                  FORWARD_COLLISION_WARNING_STATE),
+                                            .value.int32Values = {1},
+                                    },
+                            },
+            },
+            SetSpecialValueTestCase{
+                    .name = "set_blind_spot_warning_enabled_false",
+                    .valuesToSet =
+                            {
+                                    VehiclePropValue{
+                                            .prop = toInt(
+                                                    VehicleProperty::BLIND_SPOT_WARNING_ENABLED),
+                                            .value.int32Values = {0},
+                                    },
+                            },
+                    .expectedValuesToGet =
+                            {
+                                    VehiclePropValue{
+                                            .prop = toInt(
+                                                    VehicleProperty::BLIND_SPOT_WARNING_ENABLED),
+                                            .value.int32Values = {0},
+                                    },
+                                    VehiclePropValue{
+                                            .prop = toInt(
+                                                    VehicleProperty::BLIND_SPOT_WARNING_STATE),
+                                            .areaId = toInt(VehicleAreaMirror::DRIVER_LEFT),
+                                            .value.int32Values = {toInt(
+                                                    ErrorState::NOT_AVAILABLE_DISABLED)},
+                                    },
+                                    VehiclePropValue{
+                                            .prop = toInt(
+                                                    VehicleProperty::BLIND_SPOT_WARNING_STATE),
+                                            .areaId = toInt(VehicleAreaMirror::DRIVER_RIGHT),
+                                            .value.int32Values = {toInt(
+                                                    ErrorState::NOT_AVAILABLE_DISABLED)},
+                                    },
+                            },
+            },
+            SetSpecialValueTestCase{
+                    .name = "set_blind_spot_warning_enabled_true",
+                    .valuesToSet =
+                            {
+                                    VehiclePropValue{
+                                            .prop = toInt(
+                                                    VehicleProperty::BLIND_SPOT_WARNING_ENABLED),
+                                            .value.int32Values = {1},
+                                    },
+                            },
+                    .expectedValuesToGet =
+                            {
+                                    VehiclePropValue{
+                                            .prop = toInt(
+                                                    VehicleProperty::BLIND_SPOT_WARNING_ENABLED),
+                                            .value.int32Values = {1},
+                                    },
+                                    VehiclePropValue{
+                                            .prop = toInt(
+                                                    VehicleProperty::BLIND_SPOT_WARNING_STATE),
+                                            .areaId = toInt(VehicleAreaMirror::DRIVER_LEFT),
+                                            .value.int32Values = {1},
+                                    },
+                                    VehiclePropValue{
+                                            .prop = toInt(
+                                                    VehicleProperty::BLIND_SPOT_WARNING_STATE),
+                                            .areaId = toInt(VehicleAreaMirror::DRIVER_RIGHT),
+                                            .value.int32Values = {1},
+                                    },
+                            },
+            },
+            SetSpecialValueTestCase{
+                    .name = "set_lane_departure_warning_enabled_false",
+                    .valuesToSet =
+                            {
+                                    VehiclePropValue{
+                                            .prop = toInt(VehicleProperty::
+                                                                  LANE_DEPARTURE_WARNING_ENABLED),
+                                            .value.int32Values = {0},
+                                    },
+                            },
+                    .expectedValuesToGet =
+                            {
+                                    VehiclePropValue{
+                                            .prop = toInt(VehicleProperty::
+                                                                  LANE_DEPARTURE_WARNING_ENABLED),
+                                            .value.int32Values = {0},
+                                    },
+                                    VehiclePropValue{
+                                            .prop = toInt(
+                                                    VehicleProperty::LANE_DEPARTURE_WARNING_STATE),
+                                            .value.int32Values = {toInt(
+                                                    ErrorState::NOT_AVAILABLE_DISABLED)},
+                                    },
+                            },
+            },
+            SetSpecialValueTestCase{
+                    .name = "set_lane_departure_warning_enabled_true",
+                    .valuesToSet =
+                            {
+                                    VehiclePropValue{
+                                            .prop = toInt(VehicleProperty::
+                                                                  LANE_DEPARTURE_WARNING_ENABLED),
+                                            .value.int32Values = {1},
+                                    },
+                            },
+                    .expectedValuesToGet =
+                            {
+                                    VehiclePropValue{
+                                            .prop = toInt(VehicleProperty::
+                                                                  LANE_DEPARTURE_WARNING_ENABLED),
+                                            .value.int32Values = {1},
+                                    },
+                                    VehiclePropValue{
+                                            .prop = toInt(
+                                                    VehicleProperty::LANE_DEPARTURE_WARNING_STATE),
+                                            .value.int32Values = {1},
+                                    },
+                            },
+            },
+            SetSpecialValueTestCase{
+                    .name = "set_lane_keep_assist_enabled_false",
+                    .valuesToSet =
+                            {
+                                    VehiclePropValue{
+                                            .prop = toInt(
+                                                    VehicleProperty::LANE_KEEP_ASSIST_ENABLED),
+                                            .value.int32Values = {0},
+                                    },
+                            },
+                    .expectedValuesToGet =
+                            {
+                                    VehiclePropValue{
+                                            .prop = toInt(
+                                                    VehicleProperty::LANE_KEEP_ASSIST_ENABLED),
+                                            .value.int32Values = {0},
+                                    },
+                                    VehiclePropValue{
+                                            .prop = toInt(VehicleProperty::LANE_KEEP_ASSIST_STATE),
+                                            .value.int32Values = {toInt(
+                                                    ErrorState::NOT_AVAILABLE_DISABLED)},
+                                    },
+                            },
+            },
+            SetSpecialValueTestCase{
+                    .name = "set_lane_keep_assist_enabled_true",
+                    .valuesToSet =
+                            {
+                                    VehiclePropValue{
+                                            .prop = toInt(
+                                                    VehicleProperty::LANE_KEEP_ASSIST_ENABLED),
+                                            .value.int32Values = {1},
+                                    },
+                            },
+                    .expectedValuesToGet =
+                            {
+                                    VehiclePropValue{
+                                            .prop = toInt(
+                                                    VehicleProperty::LANE_KEEP_ASSIST_ENABLED),
+                                            .value.int32Values = {1},
+                                    },
+                                    VehiclePropValue{
+                                            .prop = toInt(VehicleProperty::LANE_KEEP_ASSIST_STATE),
+                                            .value.int32Values = {1},
+                                    },
+                            },
+            },
+            SetSpecialValueTestCase{
+                    .name = "set_lane_centering_assist_enabled_false",
+                    .valuesToSet =
+                            {
+                                    VehiclePropValue{
+                                            .prop = toInt(
+                                                    VehicleProperty::LANE_CENTERING_ASSIST_ENABLED),
+                                            .value.int32Values = {0},
+                                    },
+                            },
+                    .expectedValuesToGet =
+                            {
+                                    VehiclePropValue{
+                                            .prop = toInt(
+                                                    VehicleProperty::LANE_CENTERING_ASSIST_ENABLED),
+                                            .value.int32Values = {0},
+                                    },
+                                    VehiclePropValue{
+                                            .prop = toInt(
+                                                    VehicleProperty::LANE_CENTERING_ASSIST_STATE),
+                                            .value.int32Values = {toInt(
+                                                    ErrorState::NOT_AVAILABLE_DISABLED)},
+                                    },
+                            },
+            },
+            SetSpecialValueTestCase{
+                    .name = "set_lane_centering_assist_enabled_true",
+                    .valuesToSet =
+                            {
+                                    VehiclePropValue{
+                                            .prop = toInt(
+                                                    VehicleProperty::LANE_CENTERING_ASSIST_ENABLED),
+                                            .value.int32Values = {1},
+                                    },
+                            },
+                    .expectedValuesToGet =
+                            {
+                                    VehiclePropValue{
+                                            .prop = toInt(
+                                                    VehicleProperty::LANE_CENTERING_ASSIST_ENABLED),
+                                            .value.int32Values = {1},
+                                    },
+                                    VehiclePropValue{
+                                            .prop = toInt(
+                                                    VehicleProperty::LANE_CENTERING_ASSIST_STATE),
+                                            .value.int32Values = {1},
+                                    },
+                            },
+            },
+            SetSpecialValueTestCase{
+                    .name = "set_emergency_lane_keep_assist_enabled_false",
+                    .valuesToSet =
+                            {
+                                    VehiclePropValue{
+                                            .prop = toInt(
+                                                    VehicleProperty::
+                                                            EMERGENCY_LANE_KEEP_ASSIST_ENABLED),
+                                            .value.int32Values = {0},
+                                    },
+                            },
+                    .expectedValuesToGet =
+                            {
+                                    VehiclePropValue{
+                                            .prop = toInt(
+                                                    VehicleProperty::
+                                                            EMERGENCY_LANE_KEEP_ASSIST_ENABLED),
+                                            .value.int32Values = {0},
+                                    },
+                                    VehiclePropValue{
+                                            .prop = toInt(VehicleProperty::
+                                                                  EMERGENCY_LANE_KEEP_ASSIST_STATE),
+                                            .value.int32Values = {toInt(
+                                                    ErrorState::NOT_AVAILABLE_DISABLED)},
+                                    },
+                            },
+            },
+            SetSpecialValueTestCase{
+                    .name = "set_emergency_lane_keep_assist_enabled_true",
+                    .valuesToSet =
+                            {
+                                    VehiclePropValue{
+                                            .prop = toInt(
+                                                    VehicleProperty::
+                                                            EMERGENCY_LANE_KEEP_ASSIST_ENABLED),
+                                            .value.int32Values = {1},
+                                    },
+                            },
+                    .expectedValuesToGet =
+                            {
+                                    VehiclePropValue{
+                                            .prop = toInt(
+                                                    VehicleProperty::
+                                                            EMERGENCY_LANE_KEEP_ASSIST_ENABLED),
+                                            .value.int32Values = {1},
+                                    },
+                                    VehiclePropValue{
+                                            .prop = toInt(VehicleProperty::
+                                                                  EMERGENCY_LANE_KEEP_ASSIST_STATE),
+                                            .value.int32Values = {1},
+                                    },
+                            },
+            },
+            SetSpecialValueTestCase{
+                    .name = "set_cruise_control_enabled_false",
+                    .valuesToSet =
+                            {
+                                    VehiclePropValue{
+                                            .prop = toInt(VehicleProperty::CRUISE_CONTROL_ENABLED),
+                                            .value.int32Values = {0},
+                                    },
+                            },
+                    .expectedValuesToGet =
+                            {
+                                    VehiclePropValue{
+                                            .prop = toInt(VehicleProperty::CRUISE_CONTROL_ENABLED),
+                                            .value.int32Values = {0},
+                                    },
+                                    VehiclePropValue{
+                                            .prop = toInt(VehicleProperty::CRUISE_CONTROL_TYPE),
+                                            .value.int32Values = {toInt(
+                                                    ErrorState::NOT_AVAILABLE_DISABLED)},
+                                    },
+                                    VehiclePropValue{
+                                            .prop = toInt(VehicleProperty::CRUISE_CONTROL_STATE),
+                                            .value.int32Values = {toInt(
+                                                    ErrorState::NOT_AVAILABLE_DISABLED)},
+                                    },
+                            },
+            },
+            SetSpecialValueTestCase{
+                    .name = "set_cruise_control_enabled_true",
+                    .valuesToSet =
+                            {
+                                    VehiclePropValue{
+                                            .prop = toInt(VehicleProperty::CRUISE_CONTROL_ENABLED),
+                                            .value.int32Values = {1},
+                                    },
+                            },
+                    .expectedValuesToGet =
+                            {
+                                    VehiclePropValue{
+                                            .prop = toInt(VehicleProperty::CRUISE_CONTROL_ENABLED),
+                                            .value.int32Values = {1},
+                                    },
+                                    VehiclePropValue{
+                                            .prop = toInt(VehicleProperty::CRUISE_CONTROL_TYPE),
+                                            .value.int32Values = {1},
+                                    },
+                                    VehiclePropValue{
+                                            .prop = toInt(VehicleProperty::CRUISE_CONTROL_STATE),
+                                            .value.int32Values = {1},
+                                    },
+                            },
+            },
+            SetSpecialValueTestCase{
+                    .name = "set_hands_on_detection_enabled_false",
+                    .valuesToSet =
+                            {
+                                    VehiclePropValue{
+                                            .prop = toInt(
+                                                    VehicleProperty::HANDS_ON_DETECTION_ENABLED),
+                                            .value.int32Values = {0},
+                                    },
+                            },
+                    .expectedValuesToGet =
+                            {
+                                    VehiclePropValue{
+                                            .prop = toInt(
+                                                    VehicleProperty::HANDS_ON_DETECTION_ENABLED),
+                                            .value.int32Values = {0},
+                                    },
+                                    VehiclePropValue{
+                                            .prop = toInt(VehicleProperty::
+                                                                  HANDS_ON_DETECTION_DRIVER_STATE),
+                                            .value.int32Values = {toInt(
+                                                    ErrorState::NOT_AVAILABLE_DISABLED)},
+                                    },
+                                    VehiclePropValue{
+                                            .prop = toInt(
+                                                    VehicleProperty::HANDS_ON_DETECTION_WARNING),
+                                            .value.int32Values = {toInt(
+                                                    ErrorState::NOT_AVAILABLE_DISABLED)},
+                                    },
+                            },
+            },
+            SetSpecialValueTestCase{
+                    .name = "set_hands_on_detection_enabled_true",
+                    .valuesToSet =
+                            {
+                                    VehiclePropValue{
+                                            .prop = toInt(
+                                                    VehicleProperty::HANDS_ON_DETECTION_ENABLED),
+                                            .value.int32Values = {1},
+                                    },
+                            },
+                    .expectedValuesToGet =
+                            {
+                                    VehiclePropValue{
+                                            .prop = toInt(
+                                                    VehicleProperty::HANDS_ON_DETECTION_ENABLED),
+                                            .value.int32Values = {1},
+                                    },
+                                    VehiclePropValue{
+                                            .prop = toInt(VehicleProperty::
+                                                                  HANDS_ON_DETECTION_DRIVER_STATE),
+                                            .value.int32Values = {1},
+                                    },
+                                    VehiclePropValue{
+                                            .prop = toInt(
+                                                    VehicleProperty::HANDS_ON_DETECTION_WARNING),
+                                            .value.int32Values = {1},
+                                    },
+                            },
+            },
     };
 }
 
@@ -1052,7 +1536,7 @@
     std::vector<VehiclePropValue> gotValues;
 
     for (const auto& value : tc.expectedValuesToGet) {
-        auto result = getValue(VehiclePropValue{.prop = value.prop});
+        auto result = getValue(VehiclePropValue{.prop = value.prop, .areaId = value.areaId});
 
         ASSERT_TRUE(result.ok()) << "failed to get property " << value.prop
                                  << " status:" << getStatus(result);
@@ -1263,6 +1747,157 @@
     }
 }
 
+TEST_F(FakeVehicleHardwareTest, testGetAdasPropNotAvailable) {
+    std::unordered_map<int32_t, std::vector<int32_t>> adasEnabledPropToDependentProps = {
+            {
+                    toInt(VehicleProperty::CRUISE_CONTROL_ENABLED),
+                    {
+                            toInt(VehicleProperty::CRUISE_CONTROL_TARGET_SPEED),
+                            toInt(VehicleProperty::ADAPTIVE_CRUISE_CONTROL_TARGET_TIME_GAP),
+                            toInt(VehicleProperty::
+                                          ADAPTIVE_CRUISE_CONTROL_LEAD_VEHICLE_MEASURED_DISTANCE),
+                    },
+            },
+    };
+    for (auto& enabledToDependents : adasEnabledPropToDependentProps) {
+        int32_t adasEnabledPropertyId = enabledToDependents.first;
+        StatusCode status =
+                setValue(VehiclePropValue{.prop = adasEnabledPropertyId, .value.int32Values = {0}});
+        EXPECT_EQ(status, StatusCode::OK);
+
+        auto& dependentProps = enabledToDependents.second;
+        for (auto dependentProp : dependentProps) {
+            auto getValueResult = getValue(VehiclePropValue{.prop = dependentProp});
+            EXPECT_FALSE(getValueResult.ok());
+            EXPECT_EQ(getValueResult.error(), StatusCode::NOT_AVAILABLE_DISABLED);
+        }
+    }
+}
+
+TEST_F(FakeVehicleHardwareTest, testSetAdasPropNotAvailable) {
+    std::unordered_map<int32_t, std::vector<int32_t>> adasEnabledPropToDependentProps = {
+            {
+                    toInt(VehicleProperty::LANE_CENTERING_ASSIST_ENABLED),
+                    {
+                            toInt(VehicleProperty::LANE_CENTERING_ASSIST_COMMAND),
+                    },
+            },
+            {
+                    toInt(VehicleProperty::CRUISE_CONTROL_ENABLED),
+                    {
+                            toInt(VehicleProperty::CRUISE_CONTROL_COMMAND),
+                            toInt(VehicleProperty::ADAPTIVE_CRUISE_CONTROL_TARGET_TIME_GAP),
+                    },
+            },
+    };
+    for (auto& enabledToDependents : adasEnabledPropToDependentProps) {
+        int32_t adasEnabledPropertyId = enabledToDependents.first;
+        StatusCode status =
+                setValue(VehiclePropValue{.prop = adasEnabledPropertyId, .value.int32Values = {0}});
+        EXPECT_EQ(status, StatusCode::OK);
+
+        auto& dependentProps = enabledToDependents.second;
+        for (auto dependentProp : dependentProps) {
+            StatusCode status = setValue(VehiclePropValue{.prop = dependentProp});
+            EXPECT_EQ(status, StatusCode::NOT_AVAILABLE_DISABLED);
+        }
+    }
+}
+
+TEST_F(FakeVehicleHardwareTest, testSendAdasPropertiesState) {
+    std::unordered_map<int32_t, std::vector<int32_t>> adasEnabledPropToAdasPropWithErrorState = {
+            // AEB
+            {
+                    toInt(VehicleProperty::AUTOMATIC_EMERGENCY_BRAKING_ENABLED),
+                    {
+                            toInt(VehicleProperty::AUTOMATIC_EMERGENCY_BRAKING_STATE),
+                    },
+            },
+            // FCW
+            {
+                    toInt(VehicleProperty::FORWARD_COLLISION_WARNING_ENABLED),
+                    {
+                            toInt(VehicleProperty::FORWARD_COLLISION_WARNING_STATE),
+                    },
+            },
+            // BSW
+            {
+                    toInt(VehicleProperty::BLIND_SPOT_WARNING_ENABLED),
+                    {
+                            toInt(VehicleProperty::BLIND_SPOT_WARNING_STATE),
+                    },
+            },
+            // LDW
+            {
+                    toInt(VehicleProperty::LANE_DEPARTURE_WARNING_ENABLED),
+                    {
+                            toInt(VehicleProperty::LANE_DEPARTURE_WARNING_STATE),
+                    },
+            },
+            // LKA
+            {
+                    toInt(VehicleProperty::LANE_KEEP_ASSIST_ENABLED),
+                    {
+                            toInt(VehicleProperty::LANE_KEEP_ASSIST_STATE),
+                    },
+            },
+            // LCA
+            {
+                    toInt(VehicleProperty::LANE_CENTERING_ASSIST_ENABLED),
+                    {
+                            toInt(VehicleProperty::LANE_CENTERING_ASSIST_STATE),
+                    },
+            },
+            // ELKA
+            {
+                    toInt(VehicleProperty::EMERGENCY_LANE_KEEP_ASSIST_ENABLED),
+                    {
+                            toInt(VehicleProperty::EMERGENCY_LANE_KEEP_ASSIST_STATE),
+                    },
+            },
+            // CC
+            {
+                    toInt(VehicleProperty::CRUISE_CONTROL_ENABLED),
+                    {
+                            toInt(VehicleProperty::CRUISE_CONTROL_TYPE),
+                            toInt(VehicleProperty::CRUISE_CONTROL_STATE),
+                    },
+            },
+            // HOD
+            {
+                    toInt(VehicleProperty::HANDS_ON_DETECTION_ENABLED),
+                    {
+                            toInt(VehicleProperty::HANDS_ON_DETECTION_DRIVER_STATE),
+                            toInt(VehicleProperty::HANDS_ON_DETECTION_WARNING),
+                    },
+            },
+    };
+    for (auto& enabledToErrorStateProps : adasEnabledPropToAdasPropWithErrorState) {
+        int32_t adasEnabledPropertyId = enabledToErrorStateProps.first;
+        StatusCode status =
+                setValue(VehiclePropValue{.prop = adasEnabledPropertyId, .value.int32Values = {0}});
+        EXPECT_EQ(status, StatusCode::OK);
+
+        clearChangedProperties();
+        status =
+                setValue(VehiclePropValue{.prop = adasEnabledPropertyId, .value.int32Values = {1}});
+        EXPECT_EQ(status, StatusCode::OK);
+
+        // If we enable the ADAS feature, we expect to receive one property event for every ADAS
+        // state property plus one event for enabling the feature.
+        std::unordered_set<int32_t> expectedChangedPropIds(enabledToErrorStateProps.second.begin(),
+                                                           enabledToErrorStateProps.second.end());
+        expectedChangedPropIds.insert(adasEnabledPropertyId);
+
+        std::unordered_set<int32_t> changedPropIds;
+        auto events = getChangedProperties();
+        for (const auto& event : events) {
+            changedPropIds.insert(event.prop);
+        }
+        EXPECT_EQ(changedPropIds, expectedChangedPropIds);
+    }
+}
+
 TEST_F(FakeVehicleHardwareTest, testGetUserPropertySetOnly) {
     for (VehicleProperty prop : std::vector<VehicleProperty>({
                  VehicleProperty::INITIAL_USER_INFO,
diff --git a/graphics/composer/aidl/include/android/hardware/graphics/composer3/ComposerClientWriter.h b/graphics/composer/aidl/include/android/hardware/graphics/composer3/ComposerClientWriter.h
index 4a5ac69..2e902e5 100644
--- a/graphics/composer/aidl/include/android/hardware/graphics/composer3/ComposerClientWriter.h
+++ b/graphics/composer/aidl/include/android/hardware/graphics/composer3/ComposerClientWriter.h
@@ -70,12 +70,6 @@
     ComposerClientWriter(const ComposerClientWriter&) = delete;
     ComposerClientWriter& operator=(const ComposerClientWriter&) = delete;
 
-    void reset() {
-        mDisplayCommand.reset();
-        mLayerCommand.reset();
-        mCommands.clear();
-    }
-
     void setColorTransform(int64_t display, const float* matrix) {
         std::vector<float> matVec;
         matVec.reserve(16);
@@ -235,10 +229,12 @@
         getLayerCommand(display, layer).blockingRegion.emplace(blocking.begin(), blocking.end());
     }
 
-    const std::vector<DisplayCommand>& getPendingCommands() {
+    std::vector<DisplayCommand> takePendingCommands() {
         flushLayerCommand();
         flushDisplayCommand();
-        return mCommands;
+        std::vector<DisplayCommand> moved = std::move(mCommands);
+        mCommands.clear();
+        return moved;
     }
 
   private:
@@ -289,6 +285,12 @@
         }
         return *mLayerCommand;
     }
+
+    void reset() {
+        mDisplayCommand.reset();
+        mLayerCommand.reset();
+        mCommands.clear();
+    }
 };
 
 }  // namespace aidl::android::hardware::graphics::composer3
diff --git a/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_ReadbackTest.cpp b/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_ReadbackTest.cpp
index 6fa3392..b047220 100644
--- a/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_ReadbackTest.cpp
+++ b/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_ReadbackTest.cpp
@@ -207,9 +207,8 @@
     }
 
     void execute() {
-        const auto& commands = mWriter->getPendingCommands();
+        auto commands = mWriter->takePendingCommands();
         if (commands.empty()) {
-            mWriter->reset();
             return;
         }
 
@@ -217,7 +216,6 @@
         ASSERT_TRUE(status.isOk()) << "executeCommands failed " << status.getDescription();
 
         mReader.parse(std::move(results));
-        mWriter->reset();
     }
 
     bool getHasReadbackBuffer() {
diff --git a/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_TargetTest.cpp b/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_TargetTest.cpp
index 3ea5bf5..ed4f28c 100644
--- a/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_TargetTest.cpp
+++ b/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_TargetTest.cpp
@@ -1171,15 +1171,13 @@
     void execute() {
         std::vector<CommandResultPayload> payloads;
         for (auto& [_, writer] : mWriters) {
-            const auto& commands = writer.getPendingCommands();
+            auto commands = writer.takePendingCommands();
             if (commands.empty()) {
-                writer.reset();
                 continue;
             }
 
             auto [status, results] = mComposerClient->executeCommands(commands);
             ASSERT_TRUE(status.isOk()) << "executeCommands failed " << status.getDescription();
-            writer.reset();
 
             payloads.reserve(payloads.size() + results.size());
             payloads.insert(payloads.end(), std::make_move_iterator(results.begin()),
diff --git a/input/classifier/1.0/vts/functional/Android.bp b/input/classifier/1.0/vts/functional/Android.bp
index 5ff1457..22346ed 100644
--- a/input/classifier/1.0/vts/functional/Android.bp
+++ b/input/classifier/1.0/vts/functional/Android.bp
@@ -25,6 +25,7 @@
 
 cc_test {
     name: "VtsHalInputClassifierV1_0TargetTest",
+    cpp_std: "c++20",
     defaults: ["VtsHalTargetTestDefaults"],
     srcs: [
         ":inputconstants_aidl",
diff --git a/tv/cec/1.0/vts/functional/VtsHalTvCecV1_0TargetTest.cpp b/tv/cec/1.0/vts/functional/VtsHalTvCecV1_0TargetTest.cpp
index 7b42689..75c44b7 100644
--- a/tv/cec/1.0/vts/functional/VtsHalTvCecV1_0TargetTest.cpp
+++ b/tv/cec/1.0/vts/functional/VtsHalTvCecV1_0TargetTest.cpp
@@ -127,7 +127,15 @@
 
 TEST_P(HdmiCecTest, SendMessage) {
     CecMessage message;
-    message.initiator = CecLogicalAddress::PLAYBACK_1;
+    if (hasDeviceType(CecDeviceType::TV))
+    {
+        hdmiCec->clearLogicalAddress();
+        Return<Result> result = hdmiCec->addLogicalAddress(CecLogicalAddress::TV);
+        EXPECT_EQ(result, Result::SUCCESS);
+        message.initiator = CecLogicalAddress::TV;
+    }
+    else
+        message.initiator = CecLogicalAddress::PLAYBACK_1;
     message.destination = CecLogicalAddress::BROADCAST;
     message.body.resize(1);
     message.body[0] = 131;
diff --git a/wifi/aidl/default/aidl_callback_util.h b/wifi/aidl/default/aidl_callback_util.h
index 41d70a5..f8ba53b 100644
--- a/wifi/aidl/default/aidl_callback_util.h
+++ b/wifi/aidl/default/aidl_callback_util.h
@@ -19,11 +19,13 @@
 
 #include <android-base/logging.h>
 
+#include <mutex>
 #include <set>
 #include <unordered_map>
 
 namespace {
 std::unordered_map<void* /* callback */, void* /* handler */> callback_handler_map_;
+std::mutex callback_handler_lock_;
 }
 
 namespace aidl {
@@ -43,6 +45,7 @@
     ~AidlCallbackHandler() { invalidate(); }
 
     bool addCallback(const std::shared_ptr<CallbackType>& cb) {
+        std::unique_lock<std::mutex> lk(callback_handler_lock_);
         void* cbPtr = reinterpret_cast<void*>(cb->asBinder().get());
         const auto& cbPosition = findCbInSet(cbPtr);
         if (cbPosition != cb_set_.end()) {
@@ -58,12 +61,18 @@
 
         callback_handler_map_[cbPtr] = reinterpret_cast<void*>(this);
         cb_set_.insert(cb);
+        // unique_lock unlocked here
         return true;
     }
 
-    const std::set<std::shared_ptr<CallbackType>>& getCallbacks() { return cb_set_; }
+    const std::set<std::shared_ptr<CallbackType>>& getCallbacks() {
+        std::unique_lock<std::mutex> lk(callback_handler_lock_);
+        // unique_lock unlocked here
+        return cb_set_;
+    }
 
     void invalidate() {
+        std::unique_lock<std::mutex> lk(callback_handler_lock_);
         for (auto cb : cb_set_) {
             void* cookie = reinterpret_cast<void*>(cb->asBinder().get());
             if (AIBinder_unlinkToDeath(cb->asBinder().get(), death_handler_, cookie) != STATUS_OK) {
@@ -74,12 +83,14 @@
             }
         }
         cb_set_.clear();
+        // unique_lock unlocked here
     }
 
     // Entry point for the death handling logic. AIBinder_DeathRecipient
     // can only call a static function, so use the cookie to find the
     // proper handler and route the request there.
     static void onCallbackDeath(void* cookie) {
+        std::unique_lock<std::mutex> lk(callback_handler_lock_);
         auto cbQuery = callback_handler_map_.find(cookie);
         if (cbQuery == callback_handler_map_.end()) {
             LOG(ERROR) << "Invalid death cookie received";
@@ -92,6 +103,7 @@
             return;
         }
         cbHandler->handleCallbackDeath(cbQuery->first);
+        // unique_lock unlocked here
     }
 
   private: