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

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

Implement getMinMaxSupportedValue.

This is similar to the implementation for getSupportedValuesLists.

Flag: EXEMPT HAL impl
Test: atest DefaultVehicleHalTest
Bug: 382563296
Change-Id: Ib5d8380f95425d873665296fadca57c367e11326
parent 5152fff0
Loading
Loading
Loading
Loading
+62 −4
Original line number Diff line number Diff line
@@ -51,6 +51,7 @@ using ::aidl::android::hardware::automotive::vehicle::GetValueResult;
using ::aidl::android::hardware::automotive::vehicle::GetValueResults;
using ::aidl::android::hardware::automotive::vehicle::HasSupportedValueInfo;
using ::aidl::android::hardware::automotive::vehicle::IVehicleCallback;
using ::aidl::android::hardware::automotive::vehicle::MinMaxSupportedValueResult;
using ::aidl::android::hardware::automotive::vehicle::MinMaxSupportedValueResults;
using ::aidl::android::hardware::automotive::vehicle::SetValueRequest;
using ::aidl::android::hardware::automotive::vehicle::SetValueRequests;
@@ -1065,10 +1066,67 @@ ScopedAStatus DefaultVehicleHal::getSupportedValuesLists(
    return ScopedAStatus::ok();
}

ScopedAStatus DefaultVehicleHal::getMinMaxSupportedValue(const std::vector<VhalPropIdAreaId>&,
                                                         MinMaxSupportedValueResults*) {
    // TODO(b/381020465): Add relevant implementation.
    return ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
ScopedAStatus DefaultVehicleHal::getMinMaxSupportedValue(
        const std::vector<VhalPropIdAreaId>& vhalPropIdAreaIds,
        MinMaxSupportedValueResults* minMaxSupportedValueResults) {
    std::vector<size_t> toHardwareRequestCounters;
    std::vector<PropIdAreaId> toHardwarePropIdAreaIds;
    std::vector<MinMaxSupportedValueResult> results;
    results.resize(vhalPropIdAreaIds.size());
    for (size_t requestCounter = 0; requestCounter < vhalPropIdAreaIds.size(); requestCounter++) {
        const auto& vhalPropIdAreaId = vhalPropIdAreaIds.at(requestCounter);
        int32_t propId = vhalPropIdAreaId.propId;
        int32_t areaId = vhalPropIdAreaId.areaId;
        auto hasSupportedValueInfoResult = getHasSupportedValueInfo(propId, areaId);
        if (!hasSupportedValueInfoResult.ok()) {
            ALOGE("getMinMaxSupportedValue: %s",
                  hasSupportedValueInfoResult.error().message().c_str());
            results[requestCounter] = MinMaxSupportedValueResult{.status = StatusCode::INVALID_ARG,
                                                                 .minSupportedValue = std::nullopt,
                                                                 .maxSupportedValue = std::nullopt};
            continue;
        }

        const auto& hasSupportedValueInfo = *(hasSupportedValueInfoResult.value());
        if (hasSupportedValueInfo.hasMinSupportedValue ||
            hasSupportedValueInfo.hasMaxSupportedValue) {
            toHardwarePropIdAreaIds.push_back(PropIdAreaId{.propId = propId, .areaId = areaId});
            toHardwareRequestCounters.push_back(requestCounter);
        } else {
            results[requestCounter] = MinMaxSupportedValueResult{.status = StatusCode::OK,
                                                                 .minSupportedValue = std::nullopt,
                                                                 .maxSupportedValue = std::nullopt};
            continue;
        }
    }
    if (toHardwarePropIdAreaIds.size() != 0) {
        std::vector<MinMaxSupportedValueResult> resultsFromHardware =
                mVehicleHardware->getMinMaxSupportedValues(toHardwarePropIdAreaIds);
        // It is guaranteed that toHardwarePropIdAreaIds, toHardwareRequestCounters,
        // resultsFromHardware have the same size.
        if (resultsFromHardware.size() != toHardwareRequestCounters.size()) {
            return ScopedAStatus::fromServiceSpecificErrorWithMessage(
                    toInt(StatusCode::INTERNAL_ERROR),
                    fmt::format(
                            "getMinMaxSupportedValue: Unexpected results size from IVehicleHardware"
                            ", got: {}, expect: {}",
                            resultsFromHardware.size(), toHardwareRequestCounters.size())
                            .c_str());
        }
        for (size_t i = 0; i < toHardwareRequestCounters.size(); i++) {
            results[toHardwareRequestCounters[i]] = resultsFromHardware[i];
        }
    }
    ScopedAStatus status =
            vectorToStableLargeParcelable(std::move(results), minMaxSupportedValueResults);
    if (!status.isOk()) {
        int statusCode = status.getServiceSpecificError();
        ALOGE("getMinMaxSupportedValue: failed to marshal result into large parcelable, error: "
              "%s, code: %d",
              status.getMessage(), statusCode);
        return status;
    }
    return ScopedAStatus::ok();
}

ScopedAStatus DefaultVehicleHal::registerSupportedValueChangeCallback(
+149 −1
Original line number Diff line number Diff line
@@ -55,6 +55,8 @@ using ::aidl::android::hardware::automotive::vehicle::GetValueResults;
using ::aidl::android::hardware::automotive::vehicle::HasSupportedValueInfo;
using ::aidl::android::hardware::automotive::vehicle::IVehicle;
using ::aidl::android::hardware::automotive::vehicle::IVehicleCallback;
using ::aidl::android::hardware::automotive::vehicle::MinMaxSupportedValueResult;
using ::aidl::android::hardware::automotive::vehicle::MinMaxSupportedValueResults;
using ::aidl::android::hardware::automotive::vehicle::RawPropValues;
using ::aidl::android::hardware::automotive::vehicle::SetValueRequest;
using ::aidl::android::hardware::automotive::vehicle::SetValueRequests;
@@ -2220,7 +2222,7 @@ TEST_F(DefaultVehicleHalTest, testGetSupportedValuesLists) {

    result = results.payloads[2];
    ASSERT_EQ(result.status, StatusCode::INVALID_ARG)
            << "PropId, areaId that set hasSupportedValueInfo to null must not be supported";
            << "Must return INVALID_ARG for global property without area config";
    ASSERT_FALSE(result.supportedValuesList.has_value());

    result = results.payloads[3];
@@ -2271,6 +2273,152 @@ TEST_F(DefaultVehicleHalTest, testGetSupportedValuesLists_propIdAreaIdNotFound)
    ASSERT_EQ(result.status, StatusCode::INVALID_ARG);
}

TEST_F(DefaultVehicleHalTest, testGetMinMaxSupportedValue) {
    auto testConfigs = std::vector<VehiclePropConfig>(
            {// This ia valid request, but no supported values are specified.
             VehiclePropConfig{
                     .prop = testInt32VecProp(1),
                     .areaConfigs =
                             {
                                     {.areaId = 0,
                                      .hasSupportedValueInfo =
                                              HasSupportedValueInfo{
                                                      .hasMinSupportedValue = false,
                                                      .hasMaxSupportedValue = false,
                                              }},
                             },
             },
             // This is an invalid request since hasSupportedValueInfo is null. This is not
             // supported.
             VehiclePropConfig{
                     .prop = testInt32VecWindowProp(2),
                     .areaConfigs =
                             {
                                     {
                                             .areaId = 2,
                                     },
                             },
             },
             // This is an invalid request for global property.
             VehiclePropConfig{
                     .prop = testInt32VecProp(3),
             },
             // This is a normal request.
             VehiclePropConfig{
                     .prop = testInt32VecWindowProp(4),
                     .areaConfigs =
                             {
                                     {.areaId = 4,
                                      .hasSupportedValueInfo =
                                              HasSupportedValueInfo{
                                                      .hasMinSupportedValue = true,
                                                      .hasMaxSupportedValue = false,
                                              }},
                             },
             }});

    auto hardware = std::make_unique<MockVehicleHardware>();
    MockVehicleHardware* hardwarePtr = hardware.get();
    hardware->setPropertyConfigs(testConfigs);

    MinMaxSupportedValueResult resultFromHardware = {
            .status = StatusCode::OK,
            .minSupportedValue = std::optional<RawPropValues>{RawPropValues{.int32Values = {1}}},
            .maxSupportedValue = std::nullopt,
    };
    auto response = std::vector<MinMaxSupportedValueResult>({resultFromHardware});
    hardware->setMinMaxSupportedValueResponse(response);

    auto vhal = ndk::SharedRefBase::make<DefaultVehicleHal>(std::move(hardware));
    std::shared_ptr<IVehicle> client = IVehicle::fromBinder(vhal->asBinder());

    MinMaxSupportedValueResults results;

    auto propIdAreaId1 = VhalPropIdAreaId{.propId = testInt32VecProp(1), .areaId = 0};
    auto propIdAreaId2 = VhalPropIdAreaId{.propId = testInt32VecWindowProp(2), .areaId = 2};
    auto propIdAreaId3 = VhalPropIdAreaId{.propId = testInt32VecWindowProp(3), .areaId = 0};
    auto propIdAreaId4 = VhalPropIdAreaId{.propId = testInt32VecWindowProp(4), .areaId = 4};
    auto status = vhal->getMinMaxSupportedValue(
            std::vector<VhalPropIdAreaId>{propIdAreaId1, propIdAreaId2, propIdAreaId3,
                                          propIdAreaId4},
            &results);

    ASSERT_TRUE(status.isOk()) << "Get non-okay status from getMinMaxSupportedValue"
                               << status.getMessage();
    ASSERT_THAT(hardwarePtr->getMinMaxSupportedValueRequest(),
                ElementsAre(PropIdAreaId{.propId = testInt32VecWindowProp(4), .areaId = 4}))
            << "Only valid request 4 should get to hardware";

    ASSERT_EQ(results.payloads.size(), 4u);
    MinMaxSupportedValueResult result = results.payloads[0];
    ASSERT_EQ(result.status, StatusCode::OK)
            << "Must return OK even if the min/max supported values are not specified";
    ASSERT_FALSE(result.minSupportedValue.has_value())
            << "Must return null min supported value if not specified";
    ASSERT_FALSE(result.maxSupportedValue.has_value())
            << "Must return null max supported value if not specified";

    result = results.payloads[1];
    ASSERT_EQ(result.status, StatusCode::INVALID_ARG)
            << "PropId, areaId that set hasSupportedValueInfo to null must not be supported";
    ASSERT_FALSE(result.minSupportedValue.has_value());
    ASSERT_FALSE(result.maxSupportedValue.has_value());

    result = results.payloads[2];
    ASSERT_EQ(result.status, StatusCode::INVALID_ARG)
            << "Must return INVALID_ARG for global property without area config";
    ASSERT_FALSE(result.minSupportedValue.has_value());
    ASSERT_FALSE(result.maxSupportedValue.has_value());

    result = results.payloads[3];
    ASSERT_EQ(result.status, StatusCode::OK);
    ASSERT_TRUE(result.minSupportedValue.has_value());
    ASSERT_EQ(result.minSupportedValue->int32Values.size(), 1u);
    ASSERT_EQ(result.minSupportedValue->int32Values[0], 1);
    ASSERT_FALSE(result.maxSupportedValue.has_value());
}

TEST_F(DefaultVehicleHalTest, testGetMinMaxSupportedValue_propIdAreaIdNotFound) {
    auto testConfigs = std::vector<VehiclePropConfig>({
            VehiclePropConfig{
                    .prop = testInt32VecWindowProp(1),
                    .areaConfigs =
                            {
                                    {.areaId = 1,
                                     .hasSupportedValueInfo =
                                             HasSupportedValueInfo{
                                                     .hasMinSupportedValue = true,
                                                     .hasMaxSupportedValue = true,
                                             }},
                            },
            },
    });

    auto hardware = std::make_unique<MockVehicleHardware>();
    hardware->setPropertyConfigs(testConfigs);

    auto vhal = ndk::SharedRefBase::make<DefaultVehicleHal>(std::move(hardware));
    std::shared_ptr<IVehicle> client = IVehicle::fromBinder(vhal->asBinder());

    MinMaxSupportedValueResults results;

    // propId not valid.
    auto propIdAreaId1 = VhalPropIdAreaId{.propId = testInt32VecWindowProp(2), .areaId = 1};
    // areaId not valid.
    auto propIdAreaId2 = VhalPropIdAreaId{.propId = testInt32VecWindowProp(1), .areaId = 2};

    auto status = vhal->getMinMaxSupportedValue(
            std::vector<VhalPropIdAreaId>{propIdAreaId1, propIdAreaId2}, &results);

    ASSERT_TRUE(status.isOk()) << "Get non-okay status from getMinMaxSupportedValue"
                               << status.getMessage();
    ASSERT_EQ(results.payloads.size(), 2u);
    MinMaxSupportedValueResult result = results.payloads[0];
    ASSERT_EQ(result.status, StatusCode::INVALID_ARG);
    result = results.payloads[1];
    ASSERT_EQ(result.status, StatusCode::INVALID_ARG);
}

}  // namespace vehicle
}  // namespace automotive
}  // namespace hardware
+19 −0
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@ namespace vehicle {

using ::aidl::android::hardware::automotive::vehicle::GetValueRequest;
using ::aidl::android::hardware::automotive::vehicle::GetValueResult;
using ::aidl::android::hardware::automotive::vehicle::MinMaxSupportedValueResult;
using ::aidl::android::hardware::automotive::vehicle::SetValueRequest;
using ::aidl::android::hardware::automotive::vehicle::SetValueResult;
using ::aidl::android::hardware::automotive::vehicle::StatusCode;
@@ -208,6 +209,13 @@ std::vector<SupportedValuesListResult> MockVehicleHardware::getSupportedValuesLi
    return mSupportedValuesListResponse;
}

std::vector<MinMaxSupportedValueResult> MockVehicleHardware::getMinMaxSupportedValues(
        const std::vector<PropIdAreaId>& propIdAreaIds) {
    std::scoped_lock<std::mutex> lockGuard(mLock);
    mMinMaxSupportedValueRequest = propIdAreaIds;
    return mMinMaxSupportedValueResponse;
}

void MockVehicleHardware::registerOnPropertyChangeEvent(
        std::unique_ptr<const PropertyChangeCallback> callback) {
    std::scoped_lock<std::mutex> lockGuard(mLock);
@@ -281,11 +289,22 @@ void MockVehicleHardware::setSupportedValuesListResponse(
    mSupportedValuesListResponse = response;
}

void MockVehicleHardware::setMinMaxSupportedValueResponse(
        const std::vector<MinMaxSupportedValueResult>& response) {
    std::scoped_lock<std::mutex> lockGuard(mLock);
    mMinMaxSupportedValueResponse = response;
}

std::vector<PropIdAreaId> MockVehicleHardware::getSupportedValuesListRequest() {
    std::scoped_lock<std::mutex> lockGuard(mLock);
    return mSupportedValuesListRequest;
}

std::vector<PropIdAreaId> MockVehicleHardware::getMinMaxSupportedValueRequest() {
    std::scoped_lock<std::mutex> lockGuard(mLock);
    return mMinMaxSupportedValueRequest;
}

std::chrono::nanoseconds MockVehicleHardware::getPropertyOnChangeEventBatchingWindow() {
    std::scoped_lock<std::mutex> lockGuard(mLock);
    return mEventBatchingWindow;
+10 −0
Original line number Diff line number Diff line
@@ -69,6 +69,8 @@ class MockVehicleHardware final : public IVehicleHardware {
    std::chrono::nanoseconds getPropertyOnChangeEventBatchingWindow() override;
    std::vector<aidl::android::hardware::automotive::vehicle::SupportedValuesListResult>
    getSupportedValuesLists(const std::vector<PropIdAreaId>& propIdAreaIds) override;
    std::vector<aidl::android::hardware::automotive::vehicle::MinMaxSupportedValueResult>
    getMinMaxSupportedValues(const std::vector<PropIdAreaId>& propIdAreaIds) override;

    // Test functions.
    void setPropertyConfigs(
@@ -84,6 +86,10 @@ class MockVehicleHardware final : public IVehicleHardware {
            const std::vector<
                    aidl::android::hardware::automotive::vehicle::SupportedValuesListResult>&
                    response);
    void setMinMaxSupportedValueResponse(
            const std::vector<
                    aidl::android::hardware::automotive::vehicle::MinMaxSupportedValueResult>&
                    response);
    void setGetValueResponder(
            std::function<aidl::android::hardware::automotive::vehicle::StatusCode(
                    std::shared_ptr<const GetValuesCallback>,
@@ -95,6 +101,7 @@ class MockVehicleHardware final : public IVehicleHardware {
    std::vector<aidl::android::hardware::automotive::vehicle::SetValueRequest>
    nextSetValueRequests();
    std::vector<PropIdAreaId> getSupportedValuesListRequest();
    std::vector<PropIdAreaId> getMinMaxSupportedValueRequest();
    void setStatus(const char* functionName,
                   aidl::android::hardware::automotive::vehicle::StatusCode status);
    void setSleepTime(int64_t timeInNano);
@@ -126,8 +133,11 @@ class MockVehicleHardware final : public IVehicleHardware {
    mutable std::list<std::vector<aidl::android::hardware::automotive::vehicle::SetValueResult>>
            mSetValueResponses GUARDED_BY(mLock);
    mutable std::vector<PropIdAreaId> mSupportedValuesListRequest GUARDED_BY(mLock);
    mutable std::vector<PropIdAreaId> mMinMaxSupportedValueRequest GUARDED_BY(mLock);
    mutable std::vector<aidl::android::hardware::automotive::vehicle::SupportedValuesListResult>
            mSupportedValuesListResponse GUARDED_BY(mLock);
    mutable std::vector<aidl::android::hardware::automotive::vehicle::MinMaxSupportedValueResult>
            mMinMaxSupportedValueResponse GUARDED_BY(mLock);
    std::unordered_map<const char*, aidl::android::hardware::automotive::vehicle::StatusCode>
            mStatusByFunctions GUARDED_BY(mLock);
    int64_t mSleepTime GUARDED_BY(mLock) = 0;