Implement getMinMaxSupportedValue.
This is similar to the implementation for getSupportedValuesLists.
Flag: EXEMPT HAL impl
Test: atest DefaultVehicleHalTest
Bug: 382563296
Change-Id: Ib5d8380f95425d873665296fadca57c367e11326
diff --git a/automotive/vehicle/aidl/impl/current/vhal/src/DefaultVehicleHal.cpp b/automotive/vehicle/aidl/impl/current/vhal/src/DefaultVehicleHal.cpp
index 3edd651..509d1c3 100644
--- a/automotive/vehicle/aidl/impl/current/vhal/src/DefaultVehicleHal.cpp
+++ b/automotive/vehicle/aidl/impl/current/vhal/src/DefaultVehicleHal.cpp
@@ -51,6 +51,7 @@
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 @@
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(
diff --git a/automotive/vehicle/aidl/impl/current/vhal/test/DefaultVehicleHalTest.cpp b/automotive/vehicle/aidl/impl/current/vhal/test/DefaultVehicleHalTest.cpp
index 50bd8e0..992b0cc 100644
--- a/automotive/vehicle/aidl/impl/current/vhal/test/DefaultVehicleHalTest.cpp
+++ b/automotive/vehicle/aidl/impl/current/vhal/test/DefaultVehicleHalTest.cpp
@@ -55,6 +55,8 @@
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 @@
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 @@
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
diff --git a/automotive/vehicle/aidl/impl/current/vhal/test/MockVehicleHardware.cpp b/automotive/vehicle/aidl/impl/current/vhal/test/MockVehicleHardware.cpp
index ed5f47c..ae2b5a2 100644
--- a/automotive/vehicle/aidl/impl/current/vhal/test/MockVehicleHardware.cpp
+++ b/automotive/vehicle/aidl/impl/current/vhal/test/MockVehicleHardware.cpp
@@ -26,6 +26,7 @@
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 @@
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 @@
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;
diff --git a/automotive/vehicle/aidl/impl/current/vhal/test/MockVehicleHardware.h b/automotive/vehicle/aidl/impl/current/vhal/test/MockVehicleHardware.h
index 4b2ca7c..d1e9771 100644
--- a/automotive/vehicle/aidl/impl/current/vhal/test/MockVehicleHardware.h
+++ b/automotive/vehicle/aidl/impl/current/vhal/test/MockVehicleHardware.h
@@ -69,6 +69,8 @@
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 @@
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 @@
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 @@
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;