Implement HVAC_TEMPERATURE_VALUE_SUGGESTION in emulator VHAL

This property behaves like a function call taking the value set and
outputting the expected temperature values.

Bug: 270448817
Test: atest FakeVehicleHardwareTest
Change-Id: Idf9840312a59b186850b2d6b2c2fb57fee545283
This commit is contained in:
Aaqib Ismail 2023-03-12 22:25:49 -07:00
parent 1027904931
commit 881bb30026
3 changed files with 453 additions and 0 deletions

View file

@ -178,6 +178,13 @@ class FakeVehicleHardware : public IVehicleHardware {
void eventFromVehicleBus(
const aidl::android::hardware::automotive::vehicle::VehiclePropValue& value);
int getHvacTempNumIncrements(int requestedTemp, int minTemp, int maxTemp, int increment);
void updateHvacTemperatureValueSuggestionInput(
const std::vector<int>& hvacTemperatureSetConfigArray,
std::vector<float>* hvacTemperatureValueSuggestionInput);
VhalResult<void> setHvacTemperatureValueSuggestion(
const aidl::android::hardware::automotive::vehicle::VehiclePropValue&
hvacTemperatureValueSuggestion);
VhalResult<void> maybeSetSpecialValue(
const aidl::android::hardware::automotive::vehicle::VehiclePropValue& value,
bool* isSpecialValue);

View file

@ -67,6 +67,7 @@ using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyGroup;
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::EqualsIgnoreCase;
using ::android::base::Error;
@ -298,6 +299,94 @@ VhalResult<void> FakeVehicleHardware::setApPowerStateReport(const VehiclePropVal
return {};
}
int FakeVehicleHardware::getHvacTempNumIncrements(int requestedTemp, int minTemp, int maxTemp,
int increment) {
requestedTemp = std::max(requestedTemp, minTemp);
requestedTemp = std::min(requestedTemp, maxTemp);
int numIncrements = (requestedTemp - minTemp) / increment;
return numIncrements;
}
void FakeVehicleHardware::updateHvacTemperatureValueSuggestionInput(
const std::vector<int>& hvacTemperatureSetConfigArray,
std::vector<float>* hvacTemperatureValueSuggestionInput) {
int minTempInCelsius = hvacTemperatureSetConfigArray[0];
int maxTempInCelsius = hvacTemperatureSetConfigArray[1];
int incrementInCelsius = hvacTemperatureSetConfigArray[2];
int minTempInFahrenheit = hvacTemperatureSetConfigArray[3];
int maxTempInFahrenheit = hvacTemperatureSetConfigArray[4];
int incrementInFahrenheit = hvacTemperatureSetConfigArray[5];
// The HVAC_TEMPERATURE_SET config array values are temperature values that have been multiplied
// by 10 and converted to integers. Therefore, requestedTemp must also be multiplied by 10 and
// converted to an integer in order for them to be the same units.
int requestedTemp = static_cast<int>((*hvacTemperatureValueSuggestionInput)[0] * 10.0f);
int numIncrements =
(*hvacTemperatureValueSuggestionInput)[1] == toInt(VehicleUnit::CELSIUS)
? getHvacTempNumIncrements(requestedTemp, minTempInCelsius, maxTempInCelsius,
incrementInCelsius)
: getHvacTempNumIncrements(requestedTemp, minTempInFahrenheit,
maxTempInFahrenheit, incrementInFahrenheit);
int suggestedTempInCelsius = minTempInCelsius + incrementInCelsius * numIncrements;
int suggestedTempInFahrenheit = minTempInFahrenheit + incrementInFahrenheit * numIncrements;
// HVAC_TEMPERATURE_VALUE_SUGGESTION specifies the temperature values to be in the original
// floating point form so we divide by 10 and convert to float.
(*hvacTemperatureValueSuggestionInput)[2] = static_cast<float>(suggestedTempInCelsius) / 10.0f;
(*hvacTemperatureValueSuggestionInput)[3] =
static_cast<float>(suggestedTempInFahrenheit) / 10.0f;
}
VhalResult<void> FakeVehicleHardware::setHvacTemperatureValueSuggestion(
const VehiclePropValue& hvacTemperatureValueSuggestion) {
auto hvacTemperatureSetConfigResult =
mServerSidePropStore->getConfig(toInt(VehicleProperty::HVAC_TEMPERATURE_SET));
if (!hvacTemperatureSetConfigResult.ok()) {
return StatusError(getErrorCode(hvacTemperatureSetConfigResult)) << StringPrintf(
"Failed to set HVAC_TEMPERATURE_VALUE_SUGGESTION because"
" HVAC_TEMPERATURE_SET could not be retrieved. Error: %s",
getErrorMsg(hvacTemperatureSetConfigResult).c_str());
}
const auto& originalInput = hvacTemperatureValueSuggestion.value.floatValues;
if (originalInput.size() != 4) {
return StatusError(StatusCode::INVALID_ARG) << StringPrintf(
"Failed to set HVAC_TEMPERATURE_VALUE_SUGGESTION because float"
" array value is not size 4.");
}
bool isTemperatureUnitSpecified = originalInput[1] == toInt(VehicleUnit::CELSIUS) ||
originalInput[1] == toInt(VehicleUnit::FAHRENHEIT);
if (!isTemperatureUnitSpecified) {
return StatusError(StatusCode::INVALID_ARG) << StringPrintf(
"Failed to set HVAC_TEMPERATURE_VALUE_SUGGESTION because float"
" value at index 1 is not any of %d or %d, which corresponds to"
" VehicleUnit#CELSIUS and VehicleUnit#FAHRENHEIT respectively.",
toInt(VehicleUnit::CELSIUS), toInt(VehicleUnit::FAHRENHEIT));
}
auto updatedValue = mValuePool->obtain(hvacTemperatureValueSuggestion);
const auto& hvacTemperatureSetConfigArray = hvacTemperatureSetConfigResult.value()->configArray;
auto& hvacTemperatureValueSuggestionInput = updatedValue->value.floatValues;
updateHvacTemperatureValueSuggestionInput(hvacTemperatureSetConfigArray,
&hvacTemperatureValueSuggestionInput);
updatedValue->timestamp = elapsedRealtimeNano();
auto writeResult = mServerSidePropStore->writeValue(std::move(updatedValue),
/* updateStatus = */ true,
VehiclePropertyStore::EventMode::ALWAYS);
if (!writeResult.ok()) {
return StatusError(getErrorCode(writeResult))
<< StringPrintf("failed to write value into property store, error: %s",
getErrorMsg(writeResult).c_str());
}
return {};
}
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));
@ -491,6 +580,9 @@ VhalResult<void> FakeVehicleHardware::maybeSetSpecialValue(const VehiclePropValu
case VENDOR_PROPERTY_ID:
*isSpecialValue = true;
return StatusError((StatusCode)VENDOR_ERROR_CODE);
case toInt(VehicleProperty::HVAC_TEMPERATURE_VALUE_SUGGESTION):
*isSpecialValue = true;
return setHvacTemperatureValueSuggestion(value);
#ifdef ENABLE_VEHICLE_HAL_TEST_PROPERTIES
case toInt(VehicleProperty::CLUSTER_REPORT_STATE):

View file

@ -57,6 +57,7 @@ using ::aidl::android::hardware::automotive::vehicle::VehiclePropConfig;
using ::aidl::android::hardware::automotive::vehicle::VehicleProperty;
using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyStatus;
using ::aidl::android::hardware::automotive::vehicle::VehiclePropValue;
using ::aidl::android::hardware::automotive::vehicle::VehicleUnit;
using ::android::base::expected;
using ::android::base::ScopedLockAssertion;
using ::android::base::StringPrintf;
@ -2242,6 +2243,359 @@ TEST_F(FakeVehicleHardwareTest, testUpdateSampleRate) {
}
}
TEST_F(FakeVehicleHardwareTest, testSetHvacTemperatureValueSuggestion) {
float CELSIUS = static_cast<float>(toInt(VehicleUnit::CELSIUS));
float FAHRENHEIT = static_cast<float>(toInt(VehicleUnit::FAHRENHEIT));
VehiclePropValue floatArraySizeFour = {
.prop = toInt(VehicleProperty::HVAC_TEMPERATURE_VALUE_SUGGESTION),
.areaId = HVAC_ALL,
.value.floatValues = {0, CELSIUS, 0, 0},
};
StatusCode status = setValue(floatArraySizeFour);
EXPECT_EQ(status, StatusCode::OK);
VehiclePropValue floatArraySizeZero = {
.prop = toInt(VehicleProperty::HVAC_TEMPERATURE_VALUE_SUGGESTION),
.areaId = HVAC_ALL,
};
status = setValue(floatArraySizeZero);
EXPECT_EQ(status, StatusCode::INVALID_ARG);
VehiclePropValue floatArraySizeFive = {
.prop = toInt(VehicleProperty::HVAC_TEMPERATURE_VALUE_SUGGESTION),
.areaId = HVAC_ALL,
.value.floatValues = {0, CELSIUS, 0, 0, 0},
};
status = setValue(floatArraySizeFive);
EXPECT_EQ(status, StatusCode::INVALID_ARG);
VehiclePropValue invalidUnit = {
.prop = toInt(VehicleProperty::HVAC_TEMPERATURE_VALUE_SUGGESTION),
.areaId = HVAC_ALL,
.value.floatValues = {0, 0, 0, 0},
};
status = setValue(floatArraySizeFive);
EXPECT_EQ(status, StatusCode::INVALID_ARG);
clearChangedProperties();
// 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;
}
}
EXPECT_NE(hvacTemperatureSetConfig, nullptr);
auto& hvacTemperatureSetConfigArray = hvacTemperatureSetConfig->configArray;
// The HVAC_TEMPERATURE_SET config array values are temperature values that have been multiplied
// by 10 and converted to integers. HVAC_TEMPERATURE_VALUE_SUGGESTION specifies the temperature
// values to be in the original floating point form so we divide by 10 and convert to float.
float minTempInCelsius = hvacTemperatureSetConfigArray[0] / 10.0f;
float maxTempInCelsius = hvacTemperatureSetConfigArray[1] / 10.0f;
float incrementInCelsius = hvacTemperatureSetConfigArray[2] / 10.0f;
float minTempInFahrenheit = hvacTemperatureSetConfigArray[3] / 10.0f;
float maxTempInFahrenheit = hvacTemperatureSetConfigArray[4] / 10.0f;
float incrementInFahrenheit = hvacTemperatureSetConfigArray[5] / 10.0f;
auto testCases = {
SetSpecialValueTestCase{
.name = "min_celsius_temperature",
.valuesToSet =
{
VehiclePropValue{
.prop = toInt(
VehicleProperty::
HVAC_TEMPERATURE_VALUE_SUGGESTION),
.areaId = HVAC_ALL,
.value.floatValues = {minTempInCelsius, CELSIUS, 0, 0},
},
},
.expectedValuesToGet =
{
VehiclePropValue{
.prop = toInt(
VehicleProperty::
HVAC_TEMPERATURE_VALUE_SUGGESTION),
.areaId = HVAC_ALL,
.value.floatValues = {minTempInCelsius, CELSIUS,
minTempInCelsius,
minTempInFahrenheit},
},
},
},
SetSpecialValueTestCase{
.name = "min_fahrenheit_temperature",
.valuesToSet =
{
VehiclePropValue{
.prop = toInt(
VehicleProperty::
HVAC_TEMPERATURE_VALUE_SUGGESTION),
.areaId = HVAC_ALL,
.value.floatValues = {minTempInFahrenheit, FAHRENHEIT,
0, 0},
},
},
.expectedValuesToGet =
{
VehiclePropValue{
.prop = toInt(
VehicleProperty::
HVAC_TEMPERATURE_VALUE_SUGGESTION),
.areaId = HVAC_ALL,
.value.floatValues = {minTempInFahrenheit, FAHRENHEIT,
minTempInCelsius,
minTempInFahrenheit},
},
},
},
SetSpecialValueTestCase{
.name = "max_celsius_temperature",
.valuesToSet =
{
VehiclePropValue{
.prop = toInt(
VehicleProperty::
HVAC_TEMPERATURE_VALUE_SUGGESTION),
.areaId = HVAC_ALL,
.value.floatValues = {maxTempInCelsius, CELSIUS, 0, 0},
},
},
.expectedValuesToGet =
{
VehiclePropValue{
.prop = toInt(
VehicleProperty::
HVAC_TEMPERATURE_VALUE_SUGGESTION),
.areaId = HVAC_ALL,
.value.floatValues = {maxTempInCelsius, CELSIUS,
maxTempInCelsius,
maxTempInFahrenheit},
},
},
},
SetSpecialValueTestCase{
.name = "max_fahrenheit_temperature",
.valuesToSet =
{
VehiclePropValue{
.prop = toInt(
VehicleProperty::
HVAC_TEMPERATURE_VALUE_SUGGESTION),
.areaId = HVAC_ALL,
.value.floatValues = {maxTempInFahrenheit, FAHRENHEIT,
0, 0},
},
},
.expectedValuesToGet =
{
VehiclePropValue{
.prop = toInt(
VehicleProperty::
HVAC_TEMPERATURE_VALUE_SUGGESTION),
.areaId = HVAC_ALL,
.value.floatValues = {maxTempInFahrenheit, FAHRENHEIT,
maxTempInCelsius,
maxTempInFahrenheit},
},
},
},
SetSpecialValueTestCase{
.name = "below_min_celsius_temperature",
.valuesToSet =
{
VehiclePropValue{
.prop = toInt(
VehicleProperty::
HVAC_TEMPERATURE_VALUE_SUGGESTION),
.areaId = HVAC_ALL,
.value.floatValues = {minTempInCelsius - 1, CELSIUS, 0,
0},
},
},
.expectedValuesToGet =
{
VehiclePropValue{
.prop = toInt(
VehicleProperty::
HVAC_TEMPERATURE_VALUE_SUGGESTION),
.areaId = HVAC_ALL,
.value.floatValues = {minTempInCelsius - 1, CELSIUS,
minTempInCelsius,
minTempInFahrenheit},
},
},
},
SetSpecialValueTestCase{
.name = "below_min_fahrenheit_temperature",
.valuesToSet =
{
VehiclePropValue{
.prop = toInt(
VehicleProperty::
HVAC_TEMPERATURE_VALUE_SUGGESTION),
.areaId = HVAC_ALL,
.value.floatValues = {minTempInFahrenheit - 1,
FAHRENHEIT, 0, 0},
},
},
.expectedValuesToGet =
{
VehiclePropValue{
.prop = toInt(
VehicleProperty::
HVAC_TEMPERATURE_VALUE_SUGGESTION),
.areaId = HVAC_ALL,
.value.floatValues = {minTempInFahrenheit - 1,
FAHRENHEIT, minTempInCelsius,
minTempInFahrenheit},
},
},
},
SetSpecialValueTestCase{
.name = "above_max_celsius_temperature",
.valuesToSet =
{
VehiclePropValue{
.prop = toInt(
VehicleProperty::
HVAC_TEMPERATURE_VALUE_SUGGESTION),
.areaId = HVAC_ALL,
.value.floatValues = {maxTempInCelsius + 1, CELSIUS, 0,
0},
},
},
.expectedValuesToGet =
{
VehiclePropValue{
.prop = toInt(
VehicleProperty::
HVAC_TEMPERATURE_VALUE_SUGGESTION),
.areaId = HVAC_ALL,
.value.floatValues = {maxTempInCelsius + 1, CELSIUS,
maxTempInCelsius,
maxTempInFahrenheit},
},
},
},
SetSpecialValueTestCase{
.name = "above_max_fahrenheit_temperature",
.valuesToSet =
{
VehiclePropValue{
.prop = toInt(
VehicleProperty::
HVAC_TEMPERATURE_VALUE_SUGGESTION),
.areaId = HVAC_ALL,
.value.floatValues = {maxTempInFahrenheit + 1,
FAHRENHEIT, 0, 0},
},
},
.expectedValuesToGet =
{
VehiclePropValue{
.prop = toInt(
VehicleProperty::
HVAC_TEMPERATURE_VALUE_SUGGESTION),
.areaId = HVAC_ALL,
.value.floatValues = {maxTempInFahrenheit + 1,
FAHRENHEIT, maxTempInCelsius,
maxTempInFahrenheit},
},
},
},
SetSpecialValueTestCase{
.name = "inbetween_value_celsius",
.valuesToSet =
{
VehiclePropValue{
.prop = toInt(
VehicleProperty::
HVAC_TEMPERATURE_VALUE_SUGGESTION),
.areaId = HVAC_ALL,
.value.floatValues = {minTempInCelsius +
incrementInCelsius * 2.5f,
CELSIUS, 0, 0},
},
},
.expectedValuesToGet =
{
VehiclePropValue{
.prop = toInt(
VehicleProperty::
HVAC_TEMPERATURE_VALUE_SUGGESTION),
.areaId = HVAC_ALL,
.value.floatValues =
{minTempInCelsius + incrementInCelsius * 2.5f,
CELSIUS,
minTempInCelsius + incrementInCelsius * 2,
minTempInFahrenheit +
incrementInFahrenheit * 2},
},
},
},
SetSpecialValueTestCase{
.name = "inbetween_value_fahrenheit",
.valuesToSet =
{
VehiclePropValue{
.prop = toInt(
VehicleProperty::
HVAC_TEMPERATURE_VALUE_SUGGESTION),
.areaId = HVAC_ALL,
.value.floatValues = {minTempInFahrenheit +
incrementInFahrenheit *
2.5f,
FAHRENHEIT, 0, 0},
},
},
.expectedValuesToGet =
{
VehiclePropValue{
.prop = toInt(
VehicleProperty::
HVAC_TEMPERATURE_VALUE_SUGGESTION),
.areaId = HVAC_ALL,
.value.floatValues =
{minTempInFahrenheit +
incrementInFahrenheit * 2.5f,
FAHRENHEIT,
minTempInCelsius + incrementInCelsius * 2,
minTempInFahrenheit +
incrementInFahrenheit * 2},
},
},
},
};
for (auto& tc : testCases) {
StatusCode status = setValue(tc.valuesToSet[0]);
EXPECT_EQ(status, StatusCode::OK);
auto events = getChangedProperties();
EXPECT_EQ(events.size(), static_cast<size_t>(1));
events[0].timestamp = 0;
EXPECT_EQ(events[0], (tc.expectedValuesToGet[0]))
<< "Failed Test: " << tc.name << "\n"
<< "Received - prop: " << events[0].prop << ", areaId: " << events[0].areaId
<< ", floatValues: {" << events[0].value.floatValues[0] << ", "
<< events[0].value.floatValues[1] << ", " << events[0].value.floatValues[2] << ", "
<< events[0].value.floatValues[3] << "}\n"
<< "Expected - prop: " << tc.expectedValuesToGet[0].prop
<< ", areaId: " << tc.expectedValuesToGet[0].areaId << ", floatValues: {"
<< tc.expectedValuesToGet[0].value.floatValues[0] << ", "
<< tc.expectedValuesToGet[0].value.floatValues[1] << ", "
<< tc.expectedValuesToGet[0].value.floatValues[2] << ", "
<< tc.expectedValuesToGet[0].value.floatValues[3] << "}\n";
clearChangedProperties();
}
}
} // namespace fake
} // namespace vehicle
} // namespace automotive