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

Commit c8e6c2e2 authored by Treehugger Robot's avatar Treehugger Robot Committed by Android (Google) Code Review
Browse files

Merge changes I52651729,Ice39f059,I5e29e971,I8d32d1eb into main

* changes:
  Support VUR in FakeVehicleHardware.
  Override subscribe/unsubscribe.
  Avoid holding lock while calling callback.
  Add subscribe/unsubscribe to IVehicleHardware.
parents 4e0fbcd8 605faf68
Loading
Loading
Loading
Loading
+26 −0
Original line number Diff line number Diff line
@@ -274,6 +274,16 @@ JsonValueParser::JsonValueParser() {
#endif  // ENABLE_VEHICLE_HAL_TEST_PROPERTIES
}

template <>
Result<bool> JsonValueParser::convertValueToType<bool>(const std::string& fieldName,
                                                       const Json::Value& value) {
    if (!value.isBool()) {
        return Error() << "The value: " << value << " for field: " << fieldName
                       << " is not in correct type, expect bool";
    }
    return value.asBool();
}

template <>
Result<int32_t> JsonValueParser::convertValueToType<int32_t>(const std::string& fieldName,
                                                             const Json::Value& value) {
@@ -531,6 +541,12 @@ void JsonConfigParser::parseAreas(const Json::Value& parentJsonNode, const std::
        tryParseJsonValueToVariable(jsonAreaConfig, "maxFloatValue", /*optional=*/true,
                                    &areaConfig.maxFloatValue, errors);

        // By default we support variable update rate for all properties except it is explicitly
        // disabled.
        areaConfig.supportVariableUpdateRate = true;
        tryParseJsonValueToVariable(jsonAreaConfig, "supportVariableUpdateRate", /*optional=*/true,
                                    &areaConfig.supportVariableUpdateRate, errors);

        std::vector<int64_t> supportedEnumValues;
        tryParseJsonArrayToVariable(jsonAreaConfig, "supportedEnumValues", /*optional=*/true,
                                    &supportedEnumValues, errors);
@@ -585,6 +601,16 @@ std::optional<ConfigDeclaration> JsonConfigParser::parseEachProperty(
    if (errors->size() != initialErrorCount) {
        return std::nullopt;
    }

    // If there is no area config, by default we allow variable update rate, so we have to add
    // a global area config.
    if (configDecl.config.areaConfigs.size() == 0) {
        VehicleAreaConfig areaConfig = {
                .areaId = 0,
                .supportVariableUpdateRate = true,
        };
        configDecl.config.areaConfigs.push_back(std::move(areaConfig));
    }
    return configDecl;
}

+13 −1
Original line number Diff line number Diff line
@@ -3579,7 +3579,13 @@
            "property": "VehicleProperty::WATCHDOG_TERMINATED_PROCESS"
        },
        {
            "property": "VehicleProperty::VHAL_HEARTBEAT"
            "property": "VehicleProperty::VHAL_HEARTBEAT",
            "areas": [
                {
                    "areaId": 0,
                    "supportVariableUpdateRate": false
                }
            ]
        },
        {
            "property": "VehicleProperty::CLUSTER_SWITCH_UI",
@@ -3641,6 +3647,12 @@
                0,
                16
            ],
            "areas": [
                {
                    "areaId": 0,
                    "supportVariableUpdateRate": false
                }
            ],
            "comment": "configArray specifies it consists of int64[2] and byte[16]."
        },
        {
+19 −4
Original line number Diff line number Diff line
@@ -91,9 +91,13 @@ class FakeVehicleHardware : public IVehicleHardware {
    void registerOnPropertySetErrorEvent(
            std::unique_ptr<const PropertySetErrorCallback> callback) override;

    // Update the sample rate for the [propId, areaId] pair.
    aidl::android::hardware::automotive::vehicle::StatusCode updateSampleRate(
            int32_t propId, int32_t areaId, float sampleRate) override;
    // Subscribe to a new [propId, areaId] or change the update rate.
    aidl::android::hardware::automotive::vehicle::StatusCode subscribe(
            aidl::android::hardware::automotive::vehicle::SubscribeOptions options) override;

    // Unsubscribe to a [propId, areaId].
    aidl::android::hardware::automotive::vehicle::StatusCode unsubscribe(int32_t propId,
                                                                         int32_t areaId) override;

  protected:
    // mValuePool is also used in mServerSidePropStore.
@@ -154,6 +158,7 @@ class FakeVehicleHardware : public IVehicleHardware {
            mRecurrentActions GUARDED_BY(mLock);
    std::unordered_map<PropIdAreaId, VehiclePropValuePool::RecyclableType, PropIdAreaIdHash>
            mSavedProps GUARDED_BY(mLock);
    std::unordered_set<PropIdAreaId, PropIdAreaIdHash> mSubOnChangePropIdAreaIds GUARDED_BY(mLock);
    // PendingRequestHandler is thread-safe.
    mutable PendingRequestHandler<GetValuesCallback,
                                  aidl::android::hardware::automotive::vehicle::GetValueRequest>
@@ -176,7 +181,8 @@ class FakeVehicleHardware : public IVehicleHardware {
    void storePropInitialValue(const ConfigDeclaration& config);
    // The callback that would be called when a vehicle property value change happens.
    void onValueChangeCallback(
            const aidl::android::hardware::automotive::vehicle::VehiclePropValue& value);
            const aidl::android::hardware::automotive::vehicle::VehiclePropValue& value)
            EXCLUDES(mLock);
    // Load the config files in format '*.json' from the directory and parse the config files
    // into a map from property ID to ConfigDeclarations.
    void loadPropConfigsFromDir(const std::string& dirPath,
@@ -262,6 +268,11 @@ class FakeVehicleHardware : public IVehicleHardware {
    void generateVendorConfigs(
            std::vector<aidl::android::hardware::automotive::vehicle::VehiclePropConfig>&) const;

    aidl::android::hardware::automotive::vehicle::StatusCode subscribePropIdAreaIdLocked(
            int32_t propId, int32_t areaId, float sampleRateHz, bool enableVariableUpdateRate,
            const aidl::android::hardware::automotive::vehicle::VehiclePropConfig&
                    vehiclePropConfig) REQUIRES(mLock);

    static aidl::android::hardware::automotive::vehicle::VehiclePropValue createHwInputKeyProp(
            aidl::android::hardware::automotive::vehicle::VehicleHwKeyInputAction action,
            int32_t keyCode, int32_t targetDisplay);
@@ -275,6 +286,10 @@ class FakeVehicleHardware : public IVehicleHardware {

    static std::string genFakeDataHelp();
    static std::string parseErrMsg(std::string fieldName, std::string value, std::string type);
    static bool isVariableUpdateRateSupported(
            const aidl::android::hardware::automotive::vehicle::VehiclePropConfig&
                    vehiclePropConfig,
            int32_t areaId);
};

}  // namespace fake
+114 −28
Original line number Diff line number Diff line
@@ -60,6 +60,8 @@ using ::aidl::android::hardware::automotive::vehicle::RawPropValues;
using ::aidl::android::hardware::automotive::vehicle::SetValueRequest;
using ::aidl::android::hardware::automotive::vehicle::SetValueResult;
using ::aidl::android::hardware::automotive::vehicle::StatusCode;
using ::aidl::android::hardware::automotive::vehicle::SubscribeOptions;
using ::aidl::android::hardware::automotive::vehicle::toString;
using ::aidl::android::hardware::automotive::vehicle::VehicleApPowerStateReport;
using ::aidl::android::hardware::automotive::vehicle::VehicleApPowerStateReq;
using ::aidl::android::hardware::automotive::vehicle::VehicleArea;
@@ -67,6 +69,7 @@ using ::aidl::android::hardware::automotive::vehicle::VehicleHwKeyInputAction;
using ::aidl::android::hardware::automotive::vehicle::VehiclePropConfig;
using ::aidl::android::hardware::automotive::vehicle::VehicleProperty;
using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyAccess;
using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyChangeMode;
using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyGroup;
using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyStatus;
using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType;
@@ -1926,26 +1929,78 @@ void FakeVehicleHardware::registerOnPropertySetErrorEvent(
    mOnPropertySetErrorCallback = std::move(callback);
}

StatusCode FakeVehicleHardware::updateSampleRate(int32_t propId, int32_t areaId, float sampleRate) {
    // DefaultVehicleHal makes sure that sampleRate must be within minSampleRate and maxSampleRate.
    // For fake implementation, we would write the same value with a new timestamp into propStore
    // at sample rate.
StatusCode FakeVehicleHardware::subscribe(SubscribeOptions options) {
    int32_t propId = options.propId;

    auto configResult = mServerSidePropStore->getConfig(propId);
    if (!configResult.ok()) {
        ALOGE("subscribe: property: %" PRId32 " is not supported", propId);
        return StatusCode::INVALID_ARG;
    }

    std::scoped_lock<std::mutex> lockGuard(mLock);
    for (int areaId : options.areaIds) {
        if (StatusCode status = subscribePropIdAreaIdLocked(propId, areaId, options.sampleRate,
                                                            options.enableVariableUpdateRate,
                                                            *configResult.value());
            status != StatusCode::OK) {
            return status;
        }
    }
    return StatusCode::OK;
}

bool FakeVehicleHardware::isVariableUpdateRateSupported(const VehiclePropConfig& vehiclePropConfig,
                                                        int32_t areaId) {
    for (size_t i = 0; i < vehiclePropConfig.areaConfigs.size(); i++) {
        const auto& areaConfig = vehiclePropConfig.areaConfigs[i];
        if (areaConfig.areaId != areaId) {
            continue;
        }
        if (areaConfig.supportVariableUpdateRate) {
            return true;
        }
        break;
    }
    return false;
}

StatusCode FakeVehicleHardware::subscribePropIdAreaIdLocked(
        int32_t propId, int32_t areaId, float sampleRateHz, bool enableVariableUpdateRate,
        const VehiclePropConfig& vehiclePropConfig) {
    PropIdAreaId propIdAreaId{
            .propId = propId,
            .areaId = areaId,
    };
    switch (vehiclePropConfig.changeMode) {
        case VehiclePropertyChangeMode::STATIC:
            ALOGW("subscribe to a static property, do nothing.");
            return StatusCode::OK;
        case VehiclePropertyChangeMode::ON_CHANGE:
            mSubOnChangePropIdAreaIds.insert(std::move(propIdAreaId));
            return StatusCode::OK;
        case VehiclePropertyChangeMode::CONTINUOUS:
            if (sampleRateHz == 0.f) {
                ALOGE("Must not use sample rate 0 for a continuous property");
                return StatusCode::INTERNAL_ERROR;
            }
            if (mRecurrentActions.find(propIdAreaId) != mRecurrentActions.end()) {
                mRecurrentTimer->unregisterTimerCallback(mRecurrentActions[propIdAreaId]);
            }
    if (sampleRate == 0) {
        return StatusCode::OK;
            int64_t intervalInNanos = static_cast<int64_t>(1'000'000'000. / sampleRateHz);

            // For continuous properties, we must generate a new onPropertyChange event
            // periodically according to the sample rate.
            auto eventMode = VehiclePropertyStore::EventMode::ALWAYS;
            if (isVariableUpdateRateSupported(vehiclePropConfig, areaId) &&
                enableVariableUpdateRate) {
                eventMode = VehiclePropertyStore::EventMode::ON_VALUE_CHANGE;
            }
    int64_t interval = static_cast<int64_t>(1'000'000'000. / sampleRate);
    auto action = std::make_shared<RecurrentTimer::Callback>([this, propId, areaId] {
        // Refresh the property value. In real implementation, this should poll the latest value
        // from vehicle bus. Here, we are just refreshing the existing value with a new timestamp.
            auto action = std::make_shared<RecurrentTimer::Callback>([this, propId, areaId,
                                                                      eventMode] {
                // Refresh the property value. In real implementation, this should poll the latest
                // value from vehicle bus. Here, we are just refreshing the existing value with a
                // new timestamp.
                auto result = getValue(VehiclePropValue{
                        .areaId = areaId,
                        .prop = propId,
@@ -1956,21 +2011,52 @@ StatusCode FakeVehicleHardware::updateSampleRate(int32_t propId, int32_t areaId,
                    return;
                }
                result.value()->timestamp = elapsedRealtimeNano();
        // 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);
                                                 eventMode);
            });
    mRecurrentTimer->registerTimerCallback(interval, action);
            mRecurrentTimer->registerTimerCallback(intervalInNanos, action);
            mRecurrentActions[propIdAreaId] = action;
            return StatusCode::OK;
    }
}

StatusCode FakeVehicleHardware::unsubscribe(int32_t propId, int32_t areaId) {
    std::scoped_lock<std::mutex> lockGuard(mLock);
    PropIdAreaId propIdAreaId{
            .propId = propId,
            .areaId = areaId,
    };
    if (mRecurrentActions.find(propIdAreaId) != mRecurrentActions.end()) {
        mRecurrentTimer->unregisterTimerCallback(mRecurrentActions[propIdAreaId]);
        mRecurrentActions.erase(propIdAreaId);
    }
    mSubOnChangePropIdAreaIds.erase(propIdAreaId);
    return StatusCode::OK;
}

void FakeVehicleHardware::onValueChangeCallback(const VehiclePropValue& value) {
    if (mOnPropertyChangeCallback == nullptr) {
        return;
    }

    PropIdAreaId propIdAreaId{
            .propId = value.prop,
            .areaId = value.areaId,
    };

    {
        std::scoped_lock<std::mutex> lockGuard(mLock);
        if (mRecurrentActions.find(propIdAreaId) == mRecurrentActions.end() &&
            mSubOnChangePropIdAreaIds.find(propIdAreaId) == mSubOnChangePropIdAreaIds.end()) {
            if (FAKE_VEHICLEHARDWARE_DEBUG) {
                ALOGD("The updated property value: %s is not subscribed, ignore",
                      value.toString().c_str());
            }
            return;
        }
    }

    std::vector<VehiclePropValue> updatedValues;
    updatedValues.push_back(value);
    (*mOnPropertyChangeCallback)(std::move(updatedValues));
+259 −114

File changed.

Preview size limit exceeded, changes collapsed.

Loading