Merge "Always trigger prop change event for WAIT_FOR_VHAL." into tm-dev
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();