Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit dee44381 authored by Yu Shan's avatar Yu Shan Committed by Automerger Merge Worker
Browse files

Add EventMode to VehiclePropertyStore writeValue. am: 4be58ff1

parents b520b355 4be58ff1
Loading
Loading
Loading
Loading
+11 −12
Original line number Diff line number Diff line
@@ -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;
+30 −1
Original line number Diff line number Diff line
@@ -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.
+8 −2
Original line number Diff line number Diff line
@@ -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 {};
+61 −0
Original line number Diff line number Diff line
@@ -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