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

Commit ef49e73f authored by Yu Shan's avatar Yu Shan
Browse files

Add set supported value debug command.

Add debug command to ref VHAL to allow setting min/max value and
supported values list for the test vendor property. The command
also triggers supported value change event so that we can test
the subscription logic.

Flag: EXEMPT HAL change
Test: atest FakeVehicleHardwareTest
Manual test using KS, verify we see the supported value change event.
Bug: 382563296

Change-Id: I7ec791b1ee8e6cade4e267b55e4b58e1d3a9e49c
parent 300630f7
Loading
Loading
Loading
Loading
+13 −0
Original line number Diff line number Diff line
@@ -100,6 +100,9 @@ class FakeVehicleHardware : public IVehicleHardware {
    void registerOnPropertySetErrorEvent(
            std::unique_ptr<const PropertySetErrorCallback> callback) override;

    void registerSupportedValueChangeCallback(
            std::unique_ptr<const SupportedValueChangeCallback> callback) 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;
@@ -177,6 +180,7 @@ class FakeVehicleHardware : public IVehicleHardware {
    // Only allowed to set once.
    std::unique_ptr<const PropertyChangeCallback> mOnPropertyChangeCallback;
    std::unique_ptr<const PropertySetErrorCallback> mOnPropertySetErrorCallback;
    std::unique_ptr<const SupportedValueChangeCallback> mOnSupportedValueChangeCallback;

    std::mutex mLock;
    std::unordered_map<PropIdAreaId, RefreshInfo, PropIdAreaIdHash> mRefreshInfoByPropIdAreaId
@@ -185,6 +189,10 @@ class FakeVehicleHardware : public IVehicleHardware {
    std::unordered_map<PropIdAreaId, VehiclePropValuePool::RecyclableType, PropIdAreaIdHash>
            mSavedProps GUARDED_BY(mLock);
    std::unordered_set<PropIdAreaId, PropIdAreaIdHash> mSubOnChangePropIdAreaIds GUARDED_BY(mLock);
    int32_t mMinSupportedValueForTestIntProp GUARDED_BY(mLock) = 0;
    int32_t mMaxSupportedValueForTestIntProp GUARDED_BY(mLock) = 10;
    std::vector<int32_t> mSupportedValuesListForTestIntProp GUARDED_BY(mLock) = {0, 2, 4, 6, 8, 10};

    // PendingRequestHandler is thread-safe.
    mutable PendingRequestHandler<GetValuesCallback,
                                  aidl::android::hardware::automotive::vehicle::GetValueRequest>
@@ -281,6 +289,8 @@ class FakeVehicleHardware : public IVehicleHardware {
    std::string dumpRestoreProperty(const std::vector<std::string>& options);
    std::string dumpInjectEvent(const std::vector<std::string>& options);
    std::string dumpSubscriptions();
    std::string dumpSetSupportedValues(const std::vector<std::string>& options);
    std::string dumpSetMinMaxValue(const std::vector<std::string>& options);

    std::vector<std::string> getOptionValues(const std::vector<std::string>& options,
                                             size_t* index);
@@ -310,6 +320,9 @@ class FakeVehicleHardware : public IVehicleHardware {
                               float sampleRateHz) REQUIRES(mLock);
    void unregisterRefreshLocked(PropIdAreaId propIdAreaId) REQUIRES(mLock);
    void refreshTimestampForInterval(int64_t intervalInNanos) EXCLUDES(mLock);
    void triggerSupportedValueChange(
            const aidl::android::hardware::automotive::vehicle::VehiclePropConfig& config)
            EXCLUDES(mLock);

    static aidl::android::hardware::automotive::vehicle::VehiclePropValue createHwInputKeyProp(
            aidl::android::hardware::automotive::vehicle::VehicleHwKeyInputAction action,
+109 −10
Original line number Diff line number Diff line
@@ -73,6 +73,7 @@ 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;
using ::aidl::android::hardware::automotive::vehicle::VehicleAreaConfig;
using ::aidl::android::hardware::automotive::vehicle::VehicleHwKeyInputAction;
using ::aidl::android::hardware::automotive::vehicle::VehiclePropConfig;
using ::aidl::android::hardware::automotive::vehicle::VehicleProperty;
@@ -1372,6 +1373,10 @@ DumpResult FakeVehicleHardware::dump(const std::vector<std::string>& options) {
        result.buffer = "successfully restored vendor configs";
    } else if (EqualsIgnoreCase(option, "--dumpSub")) {
        result.buffer = dumpSubscriptions();
    } else if (EqualsIgnoreCase(option, "--set-minmaxvalue")) {
        result.buffer = dumpSetMinMaxValue(options);
    } else if (EqualsIgnoreCase(option, "--set-supportedvalues")) {
        result.buffer = dumpSetSupportedValues(options);
    } else {
        result.buffer = StringPrintf("Invalid option: %s\n", option.c_str());
    }
@@ -1794,6 +1799,88 @@ std::string FakeVehicleHardware::dumpSubscriptions() {
    return result;
}

std::string FakeVehicleHardware::dumpSetMinMaxValue(const std::vector<std::string>& options) {
    if (auto result = checkArgumentsSize(options, /*minSize=*/3); !result.ok()) {
        return getErrorMsg(result);
    }
    int testPropId = toInt(TestVendorProperty::VENDOR_EXTENSION_INT_PROPERTY);
    auto configResult = mServerSidePropStore->getPropConfig(testPropId);
    if (!configResult.ok()) {
        return "Failed to set min/max supported value: VENDOR_EXTENSION_INT_PROPERTY not supported";
    }
    int32_t values[2];
    for (size_t i = 1; i < 3; i++) {
        auto int32Result = safelyParseInt<int32_t>(i, options[i]);
        if (!int32Result.ok()) {
            return StringPrintf(
                    "Failed to set min/max supported value: Value: \"%s\" is not a valid int: %s\n",
                    options[i].c_str(), getErrorMsg(int32Result).c_str());
        }
        values[i - 1] = int32Result.value();
    }
    int32_t minValue = values[0];
    int32_t maxValue = values[1];
    if (minValue > maxValue) {
        return StringPrintf("Failed to set min/max supported value: MinValue: %" PRId32
                            " must not > MaxValue: %" PRId32,
                            minValue, maxValue);
    }
    {
        std::scoped_lock<std::mutex> lockGuard(mLock);
        mMinSupportedValueForTestIntProp = minValue;
        mMaxSupportedValueForTestIntProp = maxValue;
    }
    triggerSupportedValueChange(configResult.value());
    return "Min/Max supported value for VENDOR_EXTENSION_INT_PROPERTY set";
}

std::string FakeVehicleHardware::dumpSetSupportedValues(const std::vector<std::string>& options) {
    if (auto result = checkArgumentsSize(options, /*minSize=*/2); !result.ok()) {
        return getErrorMsg(result);
    }
    int testPropId = toInt(TestVendorProperty::VENDOR_EXTENSION_INT_PROPERTY);
    auto configResult = mServerSidePropStore->getPropConfig(testPropId);
    if (!configResult.ok()) {
        return "Failed to set min/max supported value: VENDOR_EXTENSION_INT_PROPERTY not supported";
    }
    std::vector<int32_t> values;
    for (size_t i = 1; i < options.size(); i++) {
        auto int32Result = safelyParseInt<int32_t>(i, options[i]);
        if (!int32Result.ok()) {
            return StringPrintf(
                    "Failed to set supported values: Value: \"%s\" is not a valid int: %s\n",
                    options[i].c_str(), getErrorMsg(int32Result).c_str());
        }
        values.push_back(int32Result.value());
    }

    {
        std::scoped_lock<std::mutex> lockGuard(mLock);
        mSupportedValuesListForTestIntProp = values;
    }
    triggerSupportedValueChange(configResult.value());
    return "Supported values list for VENDOR_EXTENSION_INT_PROPERTY set";
}

// Triggers supported value change for all areaIds that specify hasSupportedValueInfo.
void FakeVehicleHardware::triggerSupportedValueChange(const VehiclePropConfig& config) {
    if (mOnSupportedValueChangeCallback == nullptr) {
        ALOGE("onSupportedValueChangeCallback is not registered, ignore event");
        return;
    }

    std::vector<PropIdAreaId> propIdAreaIds;
    for (const VehicleAreaConfig& areaConfig : config.areaConfigs) {
        if (areaConfig.hasSupportedValueInfo != std::nullopt) {
            propIdAreaIds.push_back({
                    .propId = config.prop,
                    .areaId = areaConfig.areaId,
            });
        }
    }
    (*mOnSupportedValueChangeCallback)(std::move(propIdAreaIds));
}

std::string FakeVehicleHardware::dumpHelp() {
    return "Usage: \n\n"
           "[no args]: dumps (id and value) all supported properties \n"
@@ -1805,6 +1892,10 @@ std::string FakeVehicleHardware::dumpHelp() {
           "The value arguments constructs a VehiclePropValue used in the getValue request. \n"
           "--set <PROP_ID> [ValueArguments]: sets the value of property PROP_ID, the value "
           "arguments constructs a VehiclePropValue used in the setValue request. \n"
           "--set-minmaxvalue <MIN_VALUE(int)> <MAX_VALUE(int)>: sets the min max supported value "
           "for VENDOR_EXTENSION_INT_PROPERTY\n"
           "--set-supportedvalues <VALUE_1(int)> [VALUE_2(int) ...]: sets the supported values list"
           "for VENDOR_EXTENSION_INT_PROPERTY\n"
           "--save-prop <PROP_ID> [-a AREA_ID]: saves the current value for PROP_ID, integration "
           "tests that modify prop value must call this before test and restore-prop after test. \n"
           "--restore-prop <PROP_ID> [-a AREA_ID]: restores a previously saved property value. \n"
@@ -2280,6 +2371,15 @@ void FakeVehicleHardware::registerOnPropertySetErrorEvent(
    mOnPropertySetErrorCallback = std::move(callback);
}

void FakeVehicleHardware::registerSupportedValueChangeCallback(
        std::unique_ptr<const SupportedValueChangeCallback> callback) {
    if (mOnSupportedValueChangeCallback != nullptr) {
        ALOGE("registerOnPropertyChangeEvent must only be called once");
        return;
    }
    mOnSupportedValueChangeCallback = std::move(callback);
}

StatusCode FakeVehicleHardware::subscribe(SubscribeOptions options) {
    int32_t propId = options.propId;

@@ -2303,6 +2403,7 @@ StatusCode FakeVehicleHardware::subscribe(SubscribeOptions options) {

std::vector<MinMaxSupportedValueResult> FakeVehicleHardware::getMinMaxSupportedValues(
        const std::vector<PropIdAreaId>& propIdAreaIds) {
    std::scoped_lock<std::mutex> lockGuard(mLock);
    std::vector<MinMaxSupportedValueResult> results;
    // We only support VENDOR_EXTENSION_INT_PROPERTY
    for (const auto& propIdAreaId : propIdAreaIds) {
@@ -2318,11 +2419,11 @@ std::vector<MinMaxSupportedValueResult> FakeVehicleHardware::getMinMaxSupportedV
                .status = StatusCode::OK,
                .minSupportedValue =
                        RawPropValues{
                                .int32Values = {0},
                                .int32Values = {mMinSupportedValueForTestIntProp},
                        },
                .maxSupportedValue =
                        RawPropValues{
                                .int32Values = {10},
                                .int32Values = {mMaxSupportedValueForTestIntProp},
                        },
        });
    }
@@ -2331,6 +2432,7 @@ std::vector<MinMaxSupportedValueResult> FakeVehicleHardware::getMinMaxSupportedV

std::vector<SupportedValuesListResult> FakeVehicleHardware::getSupportedValuesLists(
        const std::vector<PropIdAreaId>& propIdAreaIds) {
    std::scoped_lock<std::mutex> lockGuard(mLock);
    std::vector<SupportedValuesListResult> results;
    // We only support VENDOR_EXTENSION_INT_PROPERTY
    for (const auto& propIdAreaId : propIdAreaIds) {
@@ -2342,16 +2444,13 @@ std::vector<SupportedValuesListResult> FakeVehicleHardware::getSupportedValuesLi
            });
            continue;
        }
        std::vector<std::optional<RawPropValues>> supportedValuesList;
        for (int32_t value : mSupportedValuesListForTestIntProp) {
            supportedValuesList.push_back(RawPropValues{.int32Values = {value}});
        }
        results.push_back(SupportedValuesListResult{
                .status = StatusCode::OK,
                .supportedValuesList = std::vector<std::optional<RawPropValues>>({
                        RawPropValues{.int32Values = {0}},
                        RawPropValues{.int32Values = {2}},
                        RawPropValues{.int32Values = {4}},
                        RawPropValues{.int32Values = {6}},
                        RawPropValues{.int32Values = {8}},
                        RawPropValues{.int32Values = {10}},
                }),
                .supportedValuesList = supportedValuesList,
        });
    }
    return results;
+80 −0
Original line number Diff line number Diff line
@@ -2759,6 +2759,86 @@ TEST_F(FakeVehicleHardwareTest, testDumpFakeUserHal) {
                              "response\nNo SetUserIdentificationAssociation response\n"));
}

TEST_F(FakeVehicleHardwareTest, testDumpSetMinMaxValue) {
    std::vector<std::string> options = {"--set-minmaxvalue", "1", "100"};
    std::vector<PropIdAreaId> changedPropIdAreaIds;

    getHardware()->registerSupportedValueChangeCallback(
            std::make_unique<IVehicleHardware::SupportedValueChangeCallback>(
                    [&changedPropIdAreaIds](std::vector<PropIdAreaId> propIdAreaIds) {
                        changedPropIdAreaIds = propIdAreaIds;
                    }));

    DumpResult result = getHardware()->dump(options);
    ASSERT_FALSE(result.callerShouldDumpState);
    ASSERT_THAT(result.buffer, ContainsRegex("Min/Max supported value .* set"));

    ASSERT_EQ(changedPropIdAreaIds.size(), 1u);

    auto results = getHardware()->getMinMaxSupportedValues({PropIdAreaId{
            .propId = toInt(TestVendorProperty::VENDOR_EXTENSION_INT_PROPERTY), .areaId = 0}});

    ASSERT_EQ(results.size(), 1u);
    EXPECT_EQ(results[0].status, StatusCode::OK);
    EXPECT_EQ(results[0].minSupportedValue.value(), RawPropValues{.int32Values = {1}});
    EXPECT_EQ(results[0].maxSupportedValue.value(), RawPropValues{.int32Values = {100}});
}

TEST_F(FakeVehicleHardwareTest, testDumpSetMinMaxValue_invalidInt) {
    std::vector<std::string> options = {"--set-minmaxvalue", "abc", "100"};

    DumpResult result = getHardware()->dump(options);
    ASSERT_THAT(result.buffer, ContainsRegex("Failed"));

    options = {"--set-minmaxvalue", "1", "abc"};

    result = getHardware()->dump(options);
    ASSERT_THAT(result.buffer, ContainsRegex("Failed"));
}

TEST_F(FakeVehicleHardwareTest, testDumpSetMinMaxValue_minLargerThanMax) {
    std::vector<std::string> options = {"--set-minmaxvalue", "2", "1"};

    DumpResult result = getHardware()->dump(options);
    ASSERT_THAT(result.buffer, ContainsRegex("Failed"));
}

TEST_F(FakeVehicleHardwareTest, testDumpSetSupportedValues) {
    std::vector<std::string> options = {"--set-supportedvalues", "1", "2", "3"};
    std::vector<PropIdAreaId> changedPropIdAreaIds;

    getHardware()->registerSupportedValueChangeCallback(
            std::make_unique<IVehicleHardware::SupportedValueChangeCallback>(
                    [&changedPropIdAreaIds](std::vector<PropIdAreaId> propIdAreaIds) {
                        changedPropIdAreaIds = propIdAreaIds;
                    }));

    DumpResult result = getHardware()->dump(options);
    ASSERT_FALSE(result.callerShouldDumpState);
    ASSERT_THAT(result.buffer, ContainsRegex("Supported values list .* set"));

    ASSERT_EQ(changedPropIdAreaIds.size(), 1u);

    auto results = getHardware()->getSupportedValuesLists({PropIdAreaId{
            .propId = toInt(TestVendorProperty::VENDOR_EXTENSION_INT_PROPERTY), .areaId = 0}});

    ASSERT_EQ(results.size(), 1u);
    EXPECT_EQ(results[0].status, StatusCode::OK);
    EXPECT_NE(results[0].supportedValuesList, std::nullopt);
    EXPECT_EQ(results[0].supportedValuesList.value(), std::vector<std::optional<RawPropValues>>({
                                                              RawPropValues{.int32Values = {1}},
                                                              RawPropValues{.int32Values = {2}},
                                                              RawPropValues{.int32Values = {3}},
                                                      }));
}

TEST_F(FakeVehicleHardwareTest, testDumpSetSupportedValues_invalidInt) {
    std::vector<std::string> options = {"--set-supportedvalues", "1", "2", "ab", "3"};

    DumpResult result = getHardware()->dump(options);
    ASSERT_THAT(result.buffer, ContainsRegex("Failed"));
}

struct SetPropTestCase {
    std::string test_name;
    std::vector<std::string> options;