Merge changes I54613982,Ie01850ba,Ib5d8380f,I931fe18c into main
* changes:
Add toString and formatter for PropIdAreaId.
Do nothing when unsubscribe a not-subscribed property.
Implement getMinMaxSupportedValue.
Implement getSupportedValuesLists in DefaultVehicleHal.
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/IVehicle.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/IVehicle.aidl
index 220b1da..cdf9066 100644
--- a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/IVehicle.aidl
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/IVehicle.aidl
@@ -237,6 +237,8 @@
* {@link StatusCode#INVALID_ARG}. If a specified propId was not subscribed
* before, this method must ignore that propId.
*
+ * Unsubscribe a not-subscribed property ID must do nothing.
+ *
* If error is returned, some of the properties failed to unsubscribe.
* Caller is safe to try again, since unsubscribing an already unsubscribed
* property is okay.
@@ -267,6 +269,9 @@
/**
* Gets the supported values lists for [propId, areaId]s.
*
+ * This is only supported for [propId, areaId]s that have non-null
+ * {@code hasSupportedValueInfo} for their {@code VehicleAreaConfig}.
+ *
* For a specific [propId, areaId], if the hardware currently specifies
* a list of supported values for it, then it is returned through the
* {@code supportedValuesList} field inside
@@ -304,6 +309,9 @@
/**
* Gets the min/max supported values for [propId, areaId]s.
*
+ * This is only supported for [propId, areaId]s that have non-null
+ * {@code hasSupportedValueInfo} for their {@code VehicleAreaConfig}.
+ *
* For a specific [propId, areaId], if the hardware currently specifies
* min/max supported value for it, then it is returned through the
* {@code minSupportedValue} or {@code maxSupportedValue} field inside
@@ -342,6 +350,9 @@
/**
* Registers the supported value change callback.
*
+ * This is only supported for [propId, areaId]s that have non-null
+ * {@code hasSupportedValueInfo} for their {@code VehicleAreaConfig}.
+ *
* For the specified [propId, areaId]s,
* {@code callback.onSupportedValueChange} must be invoked if change
* happens.
@@ -360,6 +371,9 @@
/**
* Unregisters the supported value change callback.
*
+ * This is only supported for [propId, areaId]s that have non-null
+ * {@code hasSupportedValueInfo} for their {@code VehicleAreaConfig}.
+ *
* @param callback The callback to unregister.
* @param propIdAreaIds A list of [propId, areaId]s to unregister.
*/
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/MinMaxSupportedValueResult.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/MinMaxSupportedValueResult.aidl
index f85ad3a..a3508ee 100644
--- a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/MinMaxSupportedValueResult.aidl
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/MinMaxSupportedValueResult.aidl
@@ -43,6 +43,8 @@
*
* If the [propId, areaId] does not specify a max supported value, this
* is {@code null}.
+ *
+ * This must be ignored if status is not {@code StatusCode.OK}.
*/
@nullable RawPropValues maxSupportedValue;
}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/SupportedValuesListResult.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/SupportedValuesListResult.aidl
index 4524f4f..8800b0b 100644
--- a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/SupportedValuesListResult.aidl
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/SupportedValuesListResult.aidl
@@ -36,6 +36,8 @@
*
* If the [propId, areaId] does not specify a supported values list, this
* is {@code null}.
+ *
+ * This must be ignored if status is not {@code StatusCode.OK}.
*/
@nullable List<RawPropValues> supportedValuesList;
}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleAreaConfig.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleAreaConfig.aidl
index 62d7e21..c6b8cd1 100644
--- a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleAreaConfig.aidl
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleAreaConfig.aidl
@@ -230,10 +230,17 @@
boolean supportVariableUpdateRate;
/**
- * For VHAL implementation >= V4, this must not be {@code null}. This specifies whether
- * this property may have min/max supported value or supported values list.
+ * This specifies whether this property may have min/max supported value or supported values
+ * list for [propId, areaId] that supports new supported values APIs.
*
- * For VHAL implementation < V4, this is always {@code null} and is not accessed.
+ * If this is not {@code null}. The client may use {@code getMinMaxSupportedValue},
+ * {@code getSupportedValuesLists}, {@code subscribeSupportedValueChange},
+ * {@code unsubscribeSupportedValueChange}.
+ *
+ * If this is {@code null} for legacy properties, the APIs mentioned before are not supported.
+ * Client must fallback to use static supported value information in {@code VehicleAreaConfig}.
+ *
+ * For VHAL implementation < V4, this is always {@code null}.
*/
@nullable HasSupportedValueInfo hasSupportedValueInfo;
}
diff --git a/automotive/vehicle/aidl/impl/current/hardware/include/IVehicleHardware.h b/automotive/vehicle/aidl/impl/current/hardware/include/IVehicleHardware.h
index 0684655..f46a1c8 100644
--- a/automotive/vehicle/aidl/impl/current/hardware/include/IVehicleHardware.h
+++ b/automotive/vehicle/aidl/impl/current/hardware/include/IVehicleHardware.h
@@ -18,9 +18,11 @@
#define android_hardware_automotive_vehicle_aidl_impl_hardware_include_IVehicleHardware_H_
#include <VehicleHalTypes.h>
+#include <VehicleUtils.h>
#include <memory>
#include <optional>
+#include <unordered_set>
#include <vector>
namespace android {
@@ -59,10 +61,23 @@
using GetValuesCallback = std::function<void(std::vector<aidlvhal::GetValueResult>)>;
using PropertyChangeCallback = std::function<void(std::vector<aidlvhal::VehiclePropValue>)>;
using PropertySetErrorCallback = std::function<void(std::vector<SetValueErrorEvent>)>;
+ using SupportedValueChangeCallback = std::function<void(std::vector<PropIdAreaId>)>;
virtual ~IVehicleHardware() = default;
// Get all the property configs.
+ //
+ // Note that {@code VehicleAreaConfig.HasSupportedValueInfo} field is newly introduced in VHAL
+ // V4 to specify whether the [propertyId, areaId] has specified min/max supported value or
+ // supported values list.
+ //
+ // Since IVehicleHardware is designed to be backward compatible, this field can be set to null.
+ // If this field is set to null, VHAL client should fallback to use min/max supported value
+ // information in {@code VehicleAreaConfig} and {@code supportedEnumVaules} for enum properties.
+ //
+ // It is highly recommended to specify {@code VehicleAreaConfig.HasSupportedValueInfo} for new
+ // property implementations, even if the property does not specify supported values or the
+ // supported values are static.
virtual std::vector<aidlvhal::VehiclePropConfig> getAllPropertyConfigs() const = 0;
// Get the property configs for the specified propId. This is used for early-boot
@@ -240,6 +255,76 @@
[[maybe_unused]] float sampleRate) {
return aidlvhal::StatusCode::OK;
}
+
+ // Gets the min/max supported values for each of the specified [propId, areaId]s.
+ //
+ // The returned result may change dynamically.
+ //
+ // This is only called for [propId, areaId] that has
+ // {@code HasSupportedValueInfo.hasMinSupportedValue} or
+ // {@code HasSupportedValueInfo.hasMinSupportedValue} set to true.
+ //
+ // Client must implement (override) this function if at least one [propId, areaId]'s
+ // {@code HasSupportedValueInfo} is not null.
+ virtual std::vector<aidlvhal::MinMaxSupportedValueResult> getMinMaxSupportedValues(
+ [[maybe_unused]] const std::vector<PropIdAreaId>& propIdAreaIds) {
+ return {};
+ }
+
+ // Gets the supported values list for each of the specified [propId, areaId]s.
+ //
+ // The returned result may change dynamically.
+ //
+ // This is only called for [propId, areaId] that has
+ // {@code HasSupportedValueInfo.hasSupportedValuesList} set to true.
+ //
+ // Client must implement (override) this function if at least one [propId, areaId]'s
+ // {@code HasSupportedValueInfo} is not null.
+ virtual std::vector<aidlvhal::SupportedValuesListResult> getSupportedValuesLists(
+ [[maybe_unused]] const std::vector<PropIdAreaId>& propIdAreaIds) {
+ return {};
+ }
+
+ // Register a callback that would be called when the min/max supported value or supported
+ // values list change dynamically for propertyID returned from
+ // getPropertyIdsThatImplementGetSupportedValue
+ //
+ // This function must only be called once during initialization.
+ //
+ // Client must implement (override) this function if at least one [propId, areaId]'s
+ // {@code HasSupportedValueInfo} is not null.
+ virtual void registerSupportedValueChangeCallback(
+ [[maybe_unused]] std::unique_ptr<const SupportedValueChangeCallback> callback) {
+ // Do nothing.
+ }
+
+ // Subscribes to the min/max supported value or supported values list change for the specified
+ // [propId, areaId]s.
+ //
+ // If the propertyId's supported values are static, then must do nothing.
+ //
+ // This is only called for [propId, areaId] that has non-null {@code HasSupportedValueInfo}.
+ //
+ // Client must implement (override) this function if at least one [propId, areaId]'s
+ // {@code HasSupportedValueInfo} is not null.
+ virtual aidlvhal::StatusCode subscribeSupportedValueChange(
+ [[maybe_unused]] const std::vector<PropIdAreaId>& propIdAreaIds) {
+ return aidlvhal::StatusCode::OK;
+ }
+
+ // Unsubscrbies to the min/max supported value or supported values list change.
+ //
+ // Must do nothing if the [propId, areaId] was not previously subscribed to for supported
+ // values change.
+ //
+ // This is only called for [propId, areaId] that has non-null {@code HasSupportedValueInfo}.
+ //
+ // Client must implement (override) this function if at least one [propId, areaId]'s
+ // {@code HasSupportedValueInfo} is not null.
+ virtual aidlvhal::StatusCode unsubscribeSupportedValueChange(
+ [[maybe_unused]] const std::vector<PropIdAreaId>& propIdAreaIds) {
+ return aidlvhal::StatusCode::OK;
+ }
};
} // namespace vehicle
diff --git a/automotive/vehicle/aidl/impl/current/utils/common/include/VehicleHalTypes.h b/automotive/vehicle/aidl/impl/current/utils/common/include/VehicleHalTypes.h
index 4fa0a06..fcc006b 100644
--- a/automotive/vehicle/aidl/impl/current/utils/common/include/VehicleHalTypes.h
+++ b/automotive/vehicle/aidl/impl/current/utils/common/include/VehicleHalTypes.h
@@ -53,6 +53,8 @@
#include <aidl/android/hardware/automotive/vehicle/LocationCharacterization.h>
#include <aidl/android/hardware/automotive/vehicle/LowSpeedAutomaticEmergencyBrakingState.h>
#include <aidl/android/hardware/automotive/vehicle/LowSpeedCollisionWarningState.h>
+#include <aidl/android/hardware/automotive/vehicle/MinMaxSupportedValueResult.h>
+#include <aidl/android/hardware/automotive/vehicle/MinMaxSupportedValueResults.h>
#include <aidl/android/hardware/automotive/vehicle/Obd2CommonIgnitionMonitors.h>
#include <aidl/android/hardware/automotive/vehicle/Obd2FuelSystemStatus.h>
#include <aidl/android/hardware/automotive/vehicle/Obd2FuelType.h>
@@ -65,6 +67,8 @@
#include <aidl/android/hardware/automotive/vehicle/SetValueResults.h>
#include <aidl/android/hardware/automotive/vehicle/StatusCode.h>
#include <aidl/android/hardware/automotive/vehicle/SubscribeOptions.h>
+#include <aidl/android/hardware/automotive/vehicle/SupportedValuesListResult.h>
+#include <aidl/android/hardware/automotive/vehicle/SupportedValuesListResults.h>
#include <aidl/android/hardware/automotive/vehicle/VehicleAirbagLocation.h>
#include <aidl/android/hardware/automotive/vehicle/VehicleApPowerBootupReason.h>
#include <aidl/android/hardware/automotive/vehicle/VehicleApPowerStateReport.h>
diff --git a/automotive/vehicle/aidl/impl/current/utils/common/include/VehicleUtils.h b/automotive/vehicle/aidl/impl/current/utils/common/include/VehicleUtils.h
index 90a7c46..5b19100 100644
--- a/automotive/vehicle/aidl/impl/current/utils/common/include/VehicleUtils.h
+++ b/automotive/vehicle/aidl/impl/current/utils/common/include/VehicleUtils.h
@@ -310,6 +310,12 @@
return toScopedAStatus(result, getErrorCode(result), additionalErrorMsg);
}
+// This is for debug purpose only.
+inline std::string propIdToString(int32_t propId) {
+ return toString(
+ static_cast<aidl::android::hardware::automotive::vehicle::VehicleProperty>(propId));
+}
+
struct PropIdAreaId {
int32_t propId;
int32_t areaId;
@@ -317,6 +323,11 @@
inline bool operator==(const PropIdAreaId& other) const {
return areaId == other.areaId && propId == other.propId;
}
+
+ // This is for debug purpose only.
+ inline std::string toString() const {
+ return fmt::format("{{propId: {}, areaId: {}}}", propIdToString(propId), areaId);
+ }
};
struct PropIdAreaIdHash {
@@ -329,12 +340,6 @@
};
// This is for debug purpose only.
-inline std::string propIdToString(int32_t propId) {
- return toString(
- static_cast<aidl::android::hardware::automotive::vehicle::VehicleProperty>(propId));
-}
-
-// This is for debug purpose only.
android::base::Result<int32_t> stringToPropId(const std::string& propName);
// This is for debug purpose only. Converts an area's name to its enum definition.
@@ -362,4 +367,21 @@
} // namespace hardware
} // namespace android
+// Formatter must not be defined inside our namespace.
+template <>
+struct fmt::formatter<android::hardware::automotive::vehicle::PropIdAreaId> {
+ template <typename ParseContext>
+ constexpr auto parse(ParseContext& ctx) {
+ return ctx.begin();
+ }
+
+ template <typename FormatContext>
+ auto format(const android::hardware::automotive::vehicle::PropIdAreaId& p,
+ FormatContext& ctx) const {
+ return fmt::format_to(ctx.out(), "{{propId: {}, areaId: {}}}",
+ android::hardware::automotive::vehicle::propIdToString(p.propId),
+ p.areaId);
+ }
+};
+
#endif // android_hardware_automotive_vehicle_aidl_impl_utils_common_include_VehicleUtils_H_
diff --git a/automotive/vehicle/aidl/impl/current/utils/common/test/VehicleUtilsTest.cpp b/automotive/vehicle/aidl/impl/current/utils/common/test/VehicleUtilsTest.cpp
index 1048877..8278376 100644
--- a/automotive/vehicle/aidl/impl/current/utils/common/test/VehicleUtilsTest.cpp
+++ b/automotive/vehicle/aidl/impl/current/utils/common/test/VehicleUtilsTest.cpp
@@ -787,6 +787,29 @@
ASSERT_FALSE(result.ok());
}
+TEST(VehicleUtilsTest, testPropIdAreaIdToString) {
+ PropIdAreaId propIdAreaId = {
+ .propId = toInt(VehicleProperty::PERF_VEHICLE_SPEED),
+ .areaId = 0,
+ };
+
+ ASSERT_EQ(propIdAreaId.toString(), "{propId: PERF_VEHICLE_SPEED, areaId: 0}");
+}
+
+TEST(VehicleUtilsTest, testPropIdAreaIdFormatter) {
+ PropIdAreaId propIdAreaId1 = {
+ .propId = toInt(VehicleProperty::PERF_VEHICLE_SPEED),
+ .areaId = 0,
+ };
+ PropIdAreaId propIdAreaId2 = {
+ .propId = toInt(VehicleProperty::HVAC_FAN_SPEED),
+ .areaId = 1,
+ };
+
+ ASSERT_EQ(fmt::format("{}", std::vector<PropIdAreaId>{propIdAreaId1, propIdAreaId2}),
+ "[{propId: PERF_VEHICLE_SPEED, areaId: 0}, {propId: HVAC_FAN_SPEED, areaId: 1}]");
+}
+
class InvalidPropValueTest : public testing::TestWithParam<InvalidPropValueTestCase> {};
INSTANTIATE_TEST_SUITE_P(InvalidPropValueTests, InvalidPropValueTest,
diff --git a/automotive/vehicle/aidl/impl/current/vhal/include/DefaultVehicleHal.h b/automotive/vehicle/aidl/impl/current/vhal/include/DefaultVehicleHal.h
index 5d64e6f..8785bcd 100644
--- a/automotive/vehicle/aidl/impl/current/vhal/include/DefaultVehicleHal.h
+++ b/automotive/vehicle/aidl/impl/current/vhal/include/DefaultVehicleHal.h
@@ -233,6 +233,10 @@
std::function<void(const std::unordered_map<int32_t, aidlvhal::VehiclePropConfig>&)>
callback) const EXCLUDES(mConfigLock);
+ android::base::Result<const aidlvhal::VehicleAreaConfig*> getAreaConfigForPropIdAreaId(
+ int32_t propId, int32_t areaId) const;
+ android::base::Result<const aidlvhal::HasSupportedValueInfo*> getHasSupportedValueInfo(
+ int32_t propId, int32_t areaId) const;
// Puts the property change events into a queue so that they can handled in batch.
static void batchPropertyChangeEvent(
const std::weak_ptr<ConcurrentQueue<aidlvhal::VehiclePropValue>>& batchedEventQueue,
diff --git a/automotive/vehicle/aidl/impl/current/vhal/include/SubscriptionManager.h b/automotive/vehicle/aidl/impl/current/vhal/include/SubscriptionManager.h
index 2f16fca..cac1901 100644
--- a/automotive/vehicle/aidl/impl/current/vhal/include/SubscriptionManager.h
+++ b/automotive/vehicle/aidl/impl/current/vhal/include/SubscriptionManager.h
@@ -95,15 +95,14 @@
bool isContinuousProperty);
// Unsubscribes from the properties for the client.
- // Returns error if the client was not subscribed before, or one of the given property was not
- // subscribed, or one of the property failed to unsubscribe. Caller is safe to retry since
+ // Returns error if one of the property failed to unsubscribe. Caller is safe to retry since
// unsubscribing to an already unsubscribed property is okay (it would be ignored).
// Returns ok if all the requested properties for the client are unsubscribed.
VhalResult<void> unsubscribe(ClientIdType client, const std::vector<int32_t>& propIds);
// Unsubscribes from all the properties for the client.
- // Returns error if the client was not subscribed before or one of the subscribed properties
- // for the client failed to unsubscribe. Caller is safe to retry.
+ // Returns error one of the subscribed properties for the client failed to unsubscribe.
+ // Caller is safe to retry.
// Returns ok if all the properties for the client are unsubscribed.
VhalResult<void> unsubscribe(ClientIdType client);
diff --git a/automotive/vehicle/aidl/impl/current/vhal/src/DefaultVehicleHal.cpp b/automotive/vehicle/aidl/impl/current/vhal/src/DefaultVehicleHal.cpp
index 1e55a1a..509d1c3 100644
--- a/automotive/vehicle/aidl/impl/current/vhal/src/DefaultVehicleHal.cpp
+++ b/automotive/vehicle/aidl/impl/current/vhal/src/DefaultVehicleHal.cpp
@@ -49,7 +49,9 @@
using ::aidl::android::hardware::automotive::vehicle::GetValueRequests;
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;
@@ -57,6 +59,7 @@
using ::aidl::android::hardware::automotive::vehicle::SetValueResults;
using ::aidl::android::hardware::automotive::vehicle::StatusCode;
using ::aidl::android::hardware::automotive::vehicle::SubscribeOptions;
+using ::aidl::android::hardware::automotive::vehicle::SupportedValuesListResult;
using ::aidl::android::hardware::automotive::vehicle::SupportedValuesListResults;
using ::aidl::android::hardware::automotive::vehicle::VehicleAreaConfig;
using ::aidl::android::hardware::automotive::vehicle::VehiclePropConfig;
@@ -77,6 +80,11 @@
using ::ndk::ScopedAStatus;
using ::ndk::ScopedFileDescriptor;
+using VhalPropIdAreaId = ::aidl::android::hardware::automotive::vehicle::PropIdAreaId;
+
+#define propIdtoString(PROP_ID) \
+ aidl::android::hardware::automotive::vehicle::toString(static_cast<VehicleProperty>(PROP_ID))
+
std::string toString(const std::unordered_set<int64_t>& values) {
std::string str = "";
for (auto it = values.begin(); it != values.end(); it++) {
@@ -964,30 +972,171 @@
return ScopedAStatus::ok();
}
+Result<const VehicleAreaConfig*> DefaultVehicleHal::getAreaConfigForPropIdAreaId(
+ int32_t propId, int32_t areaId) const {
+ auto result = getConfig(propId);
+ if (!result.ok()) {
+ return Error() << "Failed to get property config for propertyId: " << propIdtoString(propId)
+ << ", error: " << result.error();
+ }
+ const VehiclePropConfig& config = result.value();
+ const VehicleAreaConfig* areaConfig = getAreaConfig(propId, areaId, config);
+ if (areaConfig == nullptr) {
+ return Error() << "AreaId config not found for propertyId: " << propIdtoString(propId)
+ << ", areaId: " << areaId;
+ }
+ return areaConfig;
+}
+
+Result<const HasSupportedValueInfo*> DefaultVehicleHal::getHasSupportedValueInfo(
+ int32_t propId, int32_t areaId) const {
+ Result<const VehicleAreaConfig*> propIdAreaIdConfigResult =
+ getAreaConfigForPropIdAreaId(propId, areaId);
+ if (!isGlobalProp(propId) && !propIdAreaIdConfigResult.ok()) {
+ // For global property, it is possible that no config exists.
+ return Error() << propIdAreaIdConfigResult.error();
+ }
+ if (propIdAreaIdConfigResult.has_value()) {
+ auto areaConfig = propIdAreaIdConfigResult.value();
+ if (areaConfig->hasSupportedValueInfo.has_value()) {
+ return &(areaConfig->hasSupportedValueInfo.value());
+ }
+ }
+ return Error() << "property: " << propIdtoString(propId) << ", areaId: " << areaId
+ << " does not support this operation because hasSupportedValueInfo is null";
+}
+
ScopedAStatus DefaultVehicleHal::getSupportedValuesLists(
- const std::vector<::aidl::android::hardware::automotive::vehicle::PropIdAreaId>&,
- SupportedValuesListResults*) {
- // TODO(b/381020465): Add relevant implementation.
- return ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+ const std::vector<VhalPropIdAreaId>& vhalPropIdAreaIds,
+ SupportedValuesListResults* supportedValuesListResults) {
+ std::vector<size_t> toHardwareRequestCounters;
+ std::vector<PropIdAreaId> toHardwarePropIdAreaIds;
+ std::vector<SupportedValuesListResult> 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("getSupportedValuesLists: %s",
+ hasSupportedValueInfoResult.error().message().c_str());
+ results[requestCounter] = SupportedValuesListResult{
+ .status = StatusCode::INVALID_ARG, .supportedValuesList = std::nullopt};
+ continue;
+ }
+
+ const auto& hasSupportedValueInfo = *(hasSupportedValueInfoResult.value());
+ if (hasSupportedValueInfo.hasSupportedValuesList) {
+ toHardwarePropIdAreaIds.push_back(PropIdAreaId{.propId = propId, .areaId = areaId});
+ toHardwareRequestCounters.push_back(requestCounter);
+ } else {
+ results[requestCounter] = SupportedValuesListResult{
+ .status = StatusCode::OK, .supportedValuesList = std::nullopt};
+ continue;
+ }
+ }
+ if (toHardwarePropIdAreaIds.size() != 0) {
+ std::vector<SupportedValuesListResult> resultsFromHardware =
+ mVehicleHardware->getSupportedValuesLists(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(
+ "getSupportedValuesLists: 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), supportedValuesListResults);
+ if (!status.isOk()) {
+ int statusCode = status.getServiceSpecificError();
+ ALOGE("getSupportedValuesLists: failed to marshal result into large parcelable, error: "
+ "%s, code: %d",
+ status.getMessage(), statusCode);
+ return status;
+ }
+ return ScopedAStatus::ok();
}
ScopedAStatus DefaultVehicleHal::getMinMaxSupportedValue(
- const std::vector<::aidl::android::hardware::automotive::vehicle::PropIdAreaId>&,
- MinMaxSupportedValueResults*) {
- // TODO(b/381020465): Add relevant implementation.
- return ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+ 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(
- const std::shared_ptr<IVehicleCallback>&,
- const std::vector<::aidl::android::hardware::automotive::vehicle::PropIdAreaId>&) {
+ const std::shared_ptr<IVehicleCallback>&, const std::vector<VhalPropIdAreaId>&) {
// TODO(b/381020465): Add relevant implementation.
return ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
}
ScopedAStatus DefaultVehicleHal::unregisterSupportedValueChangeCallback(
- const std::shared_ptr<IVehicleCallback>&,
- const std::vector<::aidl::android::hardware::automotive::vehicle::PropIdAreaId>&) {
+ const std::shared_ptr<IVehicleCallback>&, const std::vector<VhalPropIdAreaId>&) {
// TODO(b/381020465): Add relevant implementation.
return ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
}
diff --git a/automotive/vehicle/aidl/impl/current/vhal/src/SubscriptionManager.cpp b/automotive/vehicle/aidl/impl/current/vhal/src/SubscriptionManager.cpp
index 14ee707..2d09e02 100644
--- a/automotive/vehicle/aidl/impl/current/vhal/src/SubscriptionManager.cpp
+++ b/automotive/vehicle/aidl/impl/current/vhal/src/SubscriptionManager.cpp
@@ -345,8 +345,8 @@
std::scoped_lock<std::mutex> lockGuard(mLock);
if (mSubscribedPropsByClient.find(clientId) == mSubscribedPropsByClient.end()) {
- return StatusError(StatusCode::INVALID_ARG)
- << "No property was subscribed for the callback";
+ ALOGW("No property was subscribed for the callback, unsubscribe does nothing");
+ return {};
}
std::vector<PropIdAreaId> propIdAreaIdsToUnsubscribe;
@@ -378,7 +378,8 @@
std::scoped_lock<std::mutex> lockGuard(mLock);
if (mSubscribedPropsByClient.find(clientId) == mSubscribedPropsByClient.end()) {
- return StatusError(StatusCode::INVALID_ARG) << "No property was subscribed for this client";
+ ALOGW("No property was subscribed for this client, unsubscribe does nothing");
+ return {};
}
auto& subscriptions = mSubscribedPropsByClient[clientId];
diff --git a/automotive/vehicle/aidl/impl/current/vhal/test/DefaultVehicleHalTest.cpp b/automotive/vehicle/aidl/impl/current/vhal/test/DefaultVehicleHalTest.cpp
index ad34a4c..4df5ba3 100644
--- a/automotive/vehicle/aidl/impl/current/vhal/test/DefaultVehicleHalTest.cpp
+++ b/automotive/vehicle/aidl/impl/current/vhal/test/DefaultVehicleHalTest.cpp
@@ -21,6 +21,7 @@
#include <IVehicleHardware.h>
#include <LargeParcelableBase.h>
+#include <aidl/android/hardware/automotive/vehicle/HasSupportedValueInfo.h>
#include <aidl/android/hardware/automotive/vehicle/IVehicle.h>
#include <aidl/android/hardware/automotive/vehicle/IVehicleCallback.h>
@@ -51,14 +52,20 @@
using ::aidl::android::hardware::automotive::vehicle::GetValueRequests;
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::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;
using ::aidl::android::hardware::automotive::vehicle::SetValueResult;
using ::aidl::android::hardware::automotive::vehicle::SetValueResults;
using ::aidl::android::hardware::automotive::vehicle::StatusCode;
using ::aidl::android::hardware::automotive::vehicle::SubscribeOptions;
+using ::aidl::android::hardware::automotive::vehicle::SupportedValuesListResult;
+using ::aidl::android::hardware::automotive::vehicle::SupportedValuesListResults;
using ::aidl::android::hardware::automotive::vehicle::VehicleAreaConfig;
using ::aidl::android::hardware::automotive::vehicle::VehicleAreaWindow;
using ::aidl::android::hardware::automotive::vehicle::VehiclePropConfig;
@@ -85,6 +92,8 @@
using ::testing::UnorderedElementsAreArray;
using ::testing::WhenSortedBy;
+using VhalPropIdAreaId = ::aidl::android::hardware::automotive::vehicle::PropIdAreaId;
+
constexpr int32_t INVALID_PROP_ID = 0;
// VehiclePropertyGroup:VENDOR,VehicleArea:WINDOW,VehiclePropertyType:INT32
constexpr int32_t INT32_WINDOW_PROP = 10001 + 0x20000000 + 0x03000000 + 0x00400000;
@@ -112,6 +121,11 @@
return static_cast<int32_t>(i) + 0x20000000 + 0x01000000 + 0x00410000;
}
+int32_t testInt32VecWindowProp(size_t i) {
+ // VehiclePropertyGroup:VENDOR,VehicleArea:WINDOW,VehiclePropertyType:INT32_VEC
+ return static_cast<int32_t>(i) + 0x20000000 + 0x03000000 + 0x00410000;
+}
+
std::string toString(const std::vector<SubscribeOptions>& options) {
std::string optionsStr;
for (const auto& option : options) {
@@ -1828,12 +1842,11 @@
ASSERT_EQ(status.getServiceSpecificError(), toInt(StatusCode::ACCESS_DENIED));
}
-TEST_F(DefaultVehicleHalTest, testUnsubscribeFailure) {
+TEST_F(DefaultVehicleHalTest, testUnsubscribeNotSubscribedProperty) {
auto status = getClient()->unsubscribe(getCallbackClient(),
std::vector<int32_t>({GLOBAL_ON_CHANGE_PROP}));
- ASSERT_FALSE(status.isOk()) << "unsubscribe to a not-subscribed property must fail";
- ASSERT_EQ(status.getServiceSpecificError(), toInt(StatusCode::INVALID_ARG));
+ ASSERT_TRUE(status.isOk()) << "unsubscribe to a not-subscribed property must do nothing";
}
TEST_F(DefaultVehicleHalTest, testHeartbeatEvent) {
@@ -2121,6 +2134,290 @@
}
}
+TEST_F(DefaultVehicleHalTest, testGetSupportedValuesLists) {
+ auto testConfigs = std::vector<VehiclePropConfig>(
+ {// This ia valid request, but no supported values are specified.
+ VehiclePropConfig{
+ .prop = testInt32VecProp(1),
+ .areaConfigs =
+ {
+ {.areaId = 0,
+ .hasSupportedValueInfo =
+ HasSupportedValueInfo{
+ .hasSupportedValuesList = 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{
+ .hasSupportedValuesList = true,
+ }},
+ },
+ }});
+
+ auto hardware = std::make_unique<MockVehicleHardware>();
+ MockVehicleHardware* hardwarePtr = hardware.get();
+ hardware->setPropertyConfigs(testConfigs);
+
+ SupportedValuesListResult resultFromHardware = {
+ .status = StatusCode::OK,
+ .supportedValuesList =
+ std::vector<std::optional<RawPropValues>>{RawPropValues{.int32Values = {1}}}};
+ auto response = std::vector<SupportedValuesListResult>({resultFromHardware});
+ hardware->setSupportedValuesListResponse(response);
+
+ auto vhal = ndk::SharedRefBase::make<DefaultVehicleHal>(std::move(hardware));
+ std::shared_ptr<IVehicle> client = IVehicle::fromBinder(vhal->asBinder());
+
+ SupportedValuesListResults 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->getSupportedValuesLists(
+ std::vector<VhalPropIdAreaId>{propIdAreaId1, propIdAreaId2, propIdAreaId3,
+ propIdAreaId4},
+ &results);
+
+ ASSERT_TRUE(status.isOk()) << "Get non-okay status from getSupportedValuesLists"
+ << status.getMessage();
+ ASSERT_THAT(hardwarePtr->getSupportedValuesListRequest(),
+ ElementsAre(PropIdAreaId{.propId = testInt32VecWindowProp(4), .areaId = 4}))
+ << "Only valid request 4 should get to hardware";
+
+ ASSERT_EQ(results.payloads.size(), 4u);
+ SupportedValuesListResult result = results.payloads[0];
+ ASSERT_EQ(result.status, StatusCode::OK)
+ << "Must return OK even if the supported values list is not specified";
+ ASSERT_FALSE(result.supportedValuesList.has_value())
+ << "Must return an empty supported values list 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.supportedValuesList.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.supportedValuesList.has_value());
+
+ result = results.payloads[3];
+ ASSERT_EQ(result.status, StatusCode::OK);
+ ASSERT_TRUE(result.supportedValuesList.has_value());
+ ASSERT_EQ(result.supportedValuesList.value().size(), 1u);
+ ASSERT_EQ(result.supportedValuesList.value()[0]->int32Values.size(), 1u);
+ ASSERT_EQ((result.supportedValuesList.value())[0]->int32Values[0], 1);
+}
+
+TEST_F(DefaultVehicleHalTest, testGetSupportedValuesLists_propIdAreaIdNotFound) {
+ auto testConfigs = std::vector<VehiclePropConfig>({
+ VehiclePropConfig{
+ .prop = testInt32VecWindowProp(1),
+ .areaConfigs =
+ {
+ {.areaId = 1,
+ .hasSupportedValueInfo =
+ HasSupportedValueInfo{
+ .hasSupportedValuesList = 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());
+
+ SupportedValuesListResults 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->getSupportedValuesLists(
+ std::vector<VhalPropIdAreaId>{propIdAreaId1, propIdAreaId2}, &results);
+
+ ASSERT_TRUE(status.isOk()) << "Get non-okay status from getSupportedValuesLists"
+ << status.getMessage();
+ ASSERT_EQ(results.payloads.size(), 2u);
+ SupportedValuesListResult result = results.payloads[0];
+ ASSERT_EQ(result.status, StatusCode::INVALID_ARG);
+ result = results.payloads[1];
+ 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 e796ce5..ae2b5a2 100644
--- a/automotive/vehicle/aidl/impl/current/vhal/test/MockVehicleHardware.cpp
+++ b/automotive/vehicle/aidl/impl/current/vhal/test/MockVehicleHardware.cpp
@@ -26,10 +26,12 @@
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;
using ::aidl::android::hardware::automotive::vehicle::SubscribeOptions;
+using ::aidl::android::hardware::automotive::vehicle::SupportedValuesListResult;
using ::aidl::android::hardware::automotive::vehicle::VehiclePropConfig;
using ::aidl::android::hardware::automotive::vehicle::VehiclePropValue;
@@ -200,6 +202,20 @@
return propIdAreaIds;
}
+std::vector<SupportedValuesListResult> MockVehicleHardware::getSupportedValuesLists(
+ const std::vector<PropIdAreaId>& propIdAreaIds) {
+ std::scoped_lock<std::mutex> lockGuard(mLock);
+ mSupportedValuesListRequest = propIdAreaIds;
+ 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);
@@ -267,6 +283,28 @@
mEventBatchingWindow = window;
}
+void MockVehicleHardware::setSupportedValuesListResponse(
+ const std::vector<SupportedValuesListResult>& response) {
+ std::scoped_lock<std::mutex> lockGuard(mLock);
+ 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 06e01a8..d1e9771 100644
--- a/automotive/vehicle/aidl/impl/current/vhal/test/MockVehicleHardware.h
+++ b/automotive/vehicle/aidl/impl/current/vhal/test/MockVehicleHardware.h
@@ -67,6 +67,10 @@
aidl::android::hardware::automotive::vehicle::StatusCode unsubscribe(int32_t propId,
int32_t areaId) override;
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(
@@ -78,6 +82,14 @@
void addSetValueResponses(
const std::vector<aidl::android::hardware::automotive::vehicle::SetValueResult>&
responses);
+ void setSupportedValuesListResponse(
+ 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>,
@@ -88,6 +100,8 @@
nextGetValueRequests();
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);
@@ -118,6 +132,12 @@
mSetValueRequests GUARDED_BY(mLock);
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;
diff --git a/automotive/vehicle/aidl/impl/current/vhal/test/SubscriptionManagerTest.cpp b/automotive/vehicle/aidl/impl/current/vhal/test/SubscriptionManagerTest.cpp
index 5d58de5..2ac3a73 100644
--- a/automotive/vehicle/aidl/impl/current/vhal/test/SubscriptionManagerTest.cpp
+++ b/automotive/vehicle/aidl/impl/current/vhal/test/SubscriptionManagerTest.cpp
@@ -351,6 +351,10 @@
std::vector<int32_t>({0, 1, 2}));
ASSERT_TRUE(result.ok()) << "unsubscribe an unsubscribed property must do nothing";
+ result = getManager()->unsubscribe(getCallbackClient()->asBinder().get(),
+ std::vector<int32_t>({0, 1, 2}));
+ ASSERT_TRUE(result.ok()) << "retry an unsubscribe operation must not throw error";
+
std::vector<VehiclePropValue> updatedValues = {
{
.prop = 0,