mirror of
https://github.com/Evolution-X/hardware_interfaces
synced 2026-02-02 06:22:53 +00:00
Add EventMode to VehiclePropertyStore writeValue.
Add an option to specify whether to trigger onpropertychange callback when VehiclePropertyStore.writeValue is called. Test: atest VehiclePropertyStoreTest Bug: 237318964 Change-Id: Iefd572c96f67dab2ecd5de56acf2e0d1c9b58939
This commit is contained in:
@@ -217,17 +217,16 @@ VhalResult<void> FakeVehicleHardware::setApPowerStateReport(const VehiclePropVal
|
||||
[[fallthrough]];
|
||||
case toInt(VehicleApPowerStateReport::WAIT_FOR_VHAL):
|
||||
// CPMS is in WAIT_FOR_VHAL state, simply move to ON and send back to HAL.
|
||||
// Must erase existing state because in the case when Car Service crashes, the power
|
||||
// state would already be ON when we receive WAIT_FOR_VHAL and thus new property change
|
||||
// event would be generated. However, Car Service always expect a property change event
|
||||
// even though there is not actual state change.
|
||||
mServerSidePropStore->removeValuesForProperty(
|
||||
toInt(VehicleProperty::AP_POWER_STATE_REQ));
|
||||
prop = createApPowerStateReq(VehicleApPowerStateReq::ON);
|
||||
|
||||
// ALWAYS update status for generated property value
|
||||
// ALWAYS update status for generated property value, and force a property update event
|
||||
// because in the case when Car Service crashes, the power state would already be ON
|
||||
// when we receive WAIT_FOR_VHAL and thus new property change event would be generated.
|
||||
// However, Car Service always expect a property change event even though there is no
|
||||
// actual state change.
|
||||
if (auto writeResult =
|
||||
mServerSidePropStore->writeValue(std::move(prop), /*updateStatus=*/true);
|
||||
mServerSidePropStore->writeValue(std::move(prop), /*updateStatus=*/true,
|
||||
VehiclePropertyStore::EventMode::ALWAYS);
|
||||
!writeResult.ok()) {
|
||||
return StatusError(getErrorCode(writeResult))
|
||||
<< "failed to write AP_POWER_STATE_REQ into property store, error: "
|
||||
@@ -894,10 +893,10 @@ StatusCode FakeVehicleHardware::updateSampleRate(int32_t propId, int32_t areaId,
|
||||
return;
|
||||
}
|
||||
result.value()->timestamp = elapsedRealtimeNano();
|
||||
// Must remove the value before writing, otherwise, we would generate no update event since
|
||||
// the value is the same.
|
||||
mServerSidePropStore->removeValue(*result.value());
|
||||
mServerSidePropStore->writeValue(std::move(result.value()));
|
||||
// For continuous properties, we must generate a new onPropertyChange event periodically
|
||||
// according to the sample rate.
|
||||
mServerSidePropStore->writeValue(std::move(result.value()), /*updateStatus=*/true,
|
||||
VehiclePropertyStore::EventMode::ALWAYS);
|
||||
});
|
||||
mRecurrentTimer->registerTimerCallback(interval, action);
|
||||
mRecurrentActions[propIdAreaId] = action;
|
||||
|
||||
@@ -46,6 +46,33 @@ class VehiclePropertyStore final {
|
||||
using ValueResultType = VhalResult<VehiclePropValuePool::RecyclableType>;
|
||||
using ValuesResultType = VhalResult<std::vector<VehiclePropValuePool::RecyclableType>>;
|
||||
|
||||
enum class EventMode : uint8_t {
|
||||
/**
|
||||
* Only invoke OnValueChangeCallback if the new property value (ignoring timestamp) is
|
||||
* different than the existing value.
|
||||
*
|
||||
* This should be used for regular cases.
|
||||
*/
|
||||
ON_VALUE_CHANGE,
|
||||
/**
|
||||
* Always invoke OnValueChangeCallback.
|
||||
*
|
||||
* This should be used for the special properties that are used for delivering event, e.g.
|
||||
* HW_KEY_INPUT.
|
||||
*/
|
||||
ALWAYS,
|
||||
/**
|
||||
* Never invoke OnValueChangeCallback.
|
||||
*
|
||||
* This should be used for continuous property subscription when the sample rate for the
|
||||
* subscription is smaller than the refresh rate for the property. E.g., the vehicle speed
|
||||
* is refreshed at 20hz, but we are only subscribing at 10hz. In this case, we want to
|
||||
* generate the property change event at 10hz, not 20hz, but we still want to refresh the
|
||||
* timestamp (via writeValue) at 20hz.
|
||||
*/
|
||||
NEVER,
|
||||
};
|
||||
|
||||
explicit VehiclePropertyStore(std::shared_ptr<VehiclePropValuePool> valuePool)
|
||||
: mValuePool(valuePool) {}
|
||||
|
||||
@@ -72,8 +99,10 @@ class VehiclePropertyStore final {
|
||||
// 'status' would be initialized to {@code VehiclePropertyStatus::AVAILABLE}, if this is to
|
||||
// override an existing value, the status for the existing value would be used for the
|
||||
// overridden value.
|
||||
// 'EventMode' controls whether the 'OnValueChangeCallback' will be called for this operation.
|
||||
VhalResult<void> writeValue(VehiclePropValuePool::RecyclableType propValue,
|
||||
bool updateStatus = false);
|
||||
bool updateStatus = false,
|
||||
EventMode mode = EventMode::ON_VALUE_CHANGE);
|
||||
|
||||
// Remove a given property value from the property store. The 'propValue' would be used to
|
||||
// generate the key for the value to remove.
|
||||
|
||||
@@ -106,7 +106,8 @@ void VehiclePropertyStore::registerProperty(const VehiclePropConfig& config,
|
||||
}
|
||||
|
||||
VhalResult<void> VehiclePropertyStore::writeValue(VehiclePropValuePool::RecyclableType propValue,
|
||||
bool updateStatus) {
|
||||
bool updateStatus,
|
||||
VehiclePropertyStore::EventMode eventMode) {
|
||||
std::scoped_lock<std::mutex> g(mLock);
|
||||
|
||||
int32_t propId = propValue->prop;
|
||||
@@ -145,7 +146,12 @@ VhalResult<void> VehiclePropertyStore::writeValue(VehiclePropValuePool::Recyclab
|
||||
}
|
||||
|
||||
record->values[recId] = std::move(propValue);
|
||||
if (valueUpdated && mOnValueChangeCallback != nullptr) {
|
||||
|
||||
if (eventMode == EventMode::NEVER) {
|
||||
return {};
|
||||
}
|
||||
|
||||
if ((eventMode == EventMode::ALWAYS || valueUpdated) && mOnValueChangeCallback != nullptr) {
|
||||
mOnValueChangeCallback(*(record->values[recId]));
|
||||
}
|
||||
return {};
|
||||
|
||||
@@ -448,6 +448,67 @@ TEST_F(VehiclePropertyStoreTest, testPropertyChangeCallbackNoUpdate) {
|
||||
ASSERT_EQ(updatedValue.prop, INVALID_PROP_ID);
|
||||
}
|
||||
|
||||
TEST_F(VehiclePropertyStoreTest, testPropertyChangeCallbackNoUpdateForTimestampChange) {
|
||||
VehiclePropValue updatedValue{
|
||||
.prop = INVALID_PROP_ID,
|
||||
};
|
||||
VehiclePropValue fuelCapacity = {
|
||||
.prop = toInt(VehicleProperty::INFO_FUEL_CAPACITY),
|
||||
.value = {.floatValues = {1.0}},
|
||||
};
|
||||
ASSERT_RESULT_OK(mStore->writeValue(mValuePool->obtain(fuelCapacity)));
|
||||
|
||||
mStore->setOnValueChangeCallback(
|
||||
[&updatedValue](const VehiclePropValue& value) { updatedValue = value; });
|
||||
|
||||
// Write the same value with different timestamp should succeed but should not trigger callback.
|
||||
fuelCapacity.timestamp = 1;
|
||||
ASSERT_RESULT_OK(mStore->writeValue(mValuePool->obtain(fuelCapacity)));
|
||||
|
||||
ASSERT_EQ(updatedValue.prop, INVALID_PROP_ID);
|
||||
}
|
||||
|
||||
TEST_F(VehiclePropertyStoreTest, testPropertyChangeCallbackForceUpdate) {
|
||||
VehiclePropValue updatedValue{
|
||||
.prop = INVALID_PROP_ID,
|
||||
};
|
||||
VehiclePropValue fuelCapacity = {
|
||||
.prop = toInt(VehicleProperty::INFO_FUEL_CAPACITY),
|
||||
.value = {.floatValues = {1.0}},
|
||||
};
|
||||
ASSERT_RESULT_OK(mStore->writeValue(mValuePool->obtain(fuelCapacity)));
|
||||
|
||||
mStore->setOnValueChangeCallback(
|
||||
[&updatedValue](const VehiclePropValue& value) { updatedValue = value; });
|
||||
|
||||
fuelCapacity.timestamp = 1;
|
||||
ASSERT_RESULT_OK(mStore->writeValue(mValuePool->obtain(fuelCapacity), /*updateStatus=*/false,
|
||||
VehiclePropertyStore::EventMode::ALWAYS));
|
||||
|
||||
ASSERT_EQ(updatedValue, fuelCapacity);
|
||||
}
|
||||
|
||||
TEST_F(VehiclePropertyStoreTest, testPropertyChangeCallbackForceNoUpdate) {
|
||||
VehiclePropValue updatedValue{
|
||||
.prop = INVALID_PROP_ID,
|
||||
};
|
||||
VehiclePropValue fuelCapacity = {
|
||||
.prop = toInt(VehicleProperty::INFO_FUEL_CAPACITY),
|
||||
.value = {.floatValues = {1.0}},
|
||||
};
|
||||
ASSERT_RESULT_OK(mStore->writeValue(mValuePool->obtain(fuelCapacity)));
|
||||
|
||||
mStore->setOnValueChangeCallback(
|
||||
[&updatedValue](const VehiclePropValue& value) { updatedValue = value; });
|
||||
fuelCapacity.value.floatValues[0] = 2.0;
|
||||
fuelCapacity.timestamp = 1;
|
||||
|
||||
ASSERT_RESULT_OK(mStore->writeValue(mValuePool->obtain(fuelCapacity), /*updateStatus=*/false,
|
||||
VehiclePropertyStore::EventMode::NEVER));
|
||||
|
||||
ASSERT_EQ(updatedValue.prop, INVALID_PROP_ID);
|
||||
}
|
||||
|
||||
} // namespace vehicle
|
||||
} // namespace automotive
|
||||
} // namespace hardware
|
||||
|
||||
Reference in New Issue
Block a user