Always trigger prop change event for WAIT_FOR_VHAL.
CarService always expect VHAL to generate a property change event
when sending WAIT_FOR_VHAL even though there is not actual power
state change in VHAL.
VHAL power state might already be ON when receive WAIT_FOR_VHAL if
CarService client crashes and restarts. In this case, CarService
still expects an event to be generated.
VehiclePropStore would only generate event when there is an actual
property value change, so we must erase the value before setting
the value to ensure a change event.
Test: atest FakeVehicleHardwareTest
Bug: 219861737
Change-Id: I185b07e188f0b581253b5ab29faf859247ed9d38
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 097257e..a78d989 100644
--- a/automotive/vehicle/aidl/impl/fake_impl/hardware/src/FakeVehicleHardware.cpp
+++ b/automotive/vehicle/aidl/impl/fake_impl/hardware/src/FakeVehicleHardware.cpp
@@ -211,10 +211,16 @@
case toInt(VehicleApPowerStateReport::SHUTDOWN_CANCELLED):
[[fallthrough]];
case toInt(VehicleApPowerStateReport::WAIT_FOR_VHAL):
- // CPMS is in WAIT_FOR_VHAL state, simply move to ON
- // Send back to HAL
- // ALWAYS update status for generated property value
+ // 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
if (auto writeResult =
mServerSidePropStore->writeValue(std::move(prop), /*updateStatus=*/true);
!writeResult.ok()) {
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 3dae9fc..6259f96 100644
--- a/automotive/vehicle/aidl/impl/fake_impl/hardware/test/FakeVehicleHardwareTest.cpp
+++ b/automotive/vehicle/aidl/impl/fake_impl/hardware/test/FakeVehicleHardwareTest.cpp
@@ -924,6 +924,32 @@
return info.param.name;
});
+TEST_F(FakeVehicleHardwareTest, testSetWaitForVhalAfterCarServiceCrash) {
+ int32_t propId = toInt(VehicleProperty::AP_POWER_STATE_REPORT);
+ VehiclePropValue request = VehiclePropValue{
+ .prop = propId,
+ .value.int32Values = {toInt(VehicleApPowerStateReport::WAIT_FOR_VHAL)},
+ };
+ ASSERT_EQ(setValue(request), StatusCode::OK) << "failed to set property " << propId;
+
+ // Clear existing events.
+ clearChangedProperties();
+
+ // Simulate a Car Service crash, Car Service would restart and send the message again.
+ ASSERT_EQ(setValue(request), StatusCode::OK) << "failed to set property " << propId;
+
+ std::vector<VehiclePropValue> events = getChangedProperties();
+ // Even though the state is already ON, we should receive another ON event.
+ ASSERT_EQ(events.size(), 1u);
+ // Erase the timestamp for comparison.
+ events[0].timestamp = 0;
+ ASSERT_EQ(events[0], (VehiclePropValue{
+ .prop = toInt(VehicleProperty::AP_POWER_STATE_REQ),
+ .status = VehiclePropertyStatus::AVAILABLE,
+ .value.int32Values = {toInt(VehicleApPowerStateReq::ON), 0},
+ }));
+}
+
TEST_F(FakeVehicleHardwareTest, testGetObd2FreezeFrame) {
int64_t timestamp = elapsedRealtimeNano();