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 7b740920d2..84395a22cf 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 @@ class FakeVehicleHardware : public IVehicleHardware { 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 setUserHalProp( const aidl::android::hardware::automotive::vehicle::VehiclePropValue& value); ValueResultType getUserHalProp( @@ -202,6 +204,7 @@ class FakeVehicleHardware : public IVehicleHardware { ValueResultType getEchoReverseBytes( const aidl::android::hardware::automotive::vehicle::VehiclePropValue& value) const; bool isHvacPropAndHvacNotAvailable(int32_t propId, int32_t areaId) const; + VhalResult isAdasPropertyAvailable(int32_t adasStatePropertyId) const; std::unordered_map loadConfigDeclarations(); @@ -244,6 +247,7 @@ class FakeVehicleHardware : public IVehicleHardware { std::string genFakeDataCommand(const std::vector& 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 096a6cda3f..577442e83f 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 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; @@ -107,6 +108,74 @@ const std::unordered_set SET_PROP_OPTIONS = { // Timestamp in int64. "-t"}; +// ADAS _ENABLED property to list of ADAS state properties using ErrorState enum. +const std::unordered_map> 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 @@ VehiclePropValuePool::RecyclableType FakeVehicleHardware::createApPowerStateReq( 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 FakeVehicleHardware::setApPowerStateReport(const VehiclePropValue& value) { auto updatedValue = mValuePool->obtain(value); updatedValue->timestamp = elapsedRealtimeNano(); @@ -413,6 +494,41 @@ bool FakeVehicleHardware::isHvacPropAndHvacNotAvailable(int32_t propId, int32_t return false; } +VhalResult 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 FakeVehicleHardware::setUserHalProp(const VehiclePropValue& value) { auto result = mFakeUserHal->onSetProperty(value); if (!result.ok()) { @@ -495,6 +611,19 @@ FakeVehicleHardware::ValueResultType FakeVehicleHardware::maybeGetSpecialValue( 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::sendHvacPropertiesCurrentValues(int32_t areaId) { } } +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 FakeVehicleHardware::maybeSetSpecialValue(const VehiclePropValue& value, bool* isSpecialValue) { *isSpecialValue = false; @@ -565,6 +713,16 @@ VhalResult FakeVehicleHardware::maybeSetSpecialValue(const VehiclePropValu 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 @@ VhalResult FakeVehicleHardware::maybeSetSpecialValue(const VehiclePropValu 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 b399bdfc65..8d385ddcfe 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 vehicle { 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::SetValueResult; 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 @@ std::vector setSpecialValueTestCases() { }, }, }, + 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 @@ TEST_P(FakeVehicleHardwareSpecialValuesTest, testSetSpecialProperties) { std::vector 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, testHvacPowerOnSendCurrentHvacPropValues) { } } +TEST_F(FakeVehicleHardwareTest, testGetAdasPropNotAvailable) { + std::unordered_map> 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> 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> 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 expectedChangedPropIds(enabledToErrorStateProps.second.begin(), + enabledToErrorStateProps.second.end()); + expectedChangedPropIds.insert(adasEnabledPropertyId); + + std::unordered_set 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::INITIAL_USER_INFO,