Merge "Add VTS coverage for RttConfig.secureConfig" into main
diff --git a/automotive/vehicle/aidl/impl/current/hardware/include/IVehicleHardware.h b/automotive/vehicle/aidl/impl/current/hardware/include/IVehicleHardware.h
index f46a1c8..9122955 100644
--- a/automotive/vehicle/aidl/impl/current/hardware/include/IVehicleHardware.h
+++ b/automotive/vehicle/aidl/impl/current/hardware/include/IVehicleHardware.h
@@ -303,6 +303,8 @@
//
// If the propertyId's supported values are static, then must do nothing.
//
+ // If some of the [propId, areaId]s are already subscribed, then 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
diff --git a/automotive/vehicle/aidl/impl/current/vhal/include/DefaultVehicleHal.h b/automotive/vehicle/aidl/impl/current/vhal/include/DefaultVehicleHal.h
index 8785bcd..02dbe9e 100644
--- a/automotive/vehicle/aidl/impl/current/vhal/include/DefaultVehicleHal.h
+++ b/automotive/vehicle/aidl/impl/current/vhal/include/DefaultVehicleHal.h
@@ -233,9 +233,9 @@
std::function<void(const std::unordered_map<int32_t, aidlvhal::VehiclePropConfig>&)>
callback) const EXCLUDES(mConfigLock);
- android::base::Result<const aidlvhal::VehicleAreaConfig*> getAreaConfigForPropIdAreaId(
+ android::base::Result<aidlvhal::VehicleAreaConfig> getAreaConfigForPropIdAreaId(
int32_t propId, int32_t areaId) const;
- android::base::Result<const aidlvhal::HasSupportedValueInfo*> getHasSupportedValueInfo(
+ android::base::Result<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(
diff --git a/automotive/vehicle/aidl/impl/current/vhal/include/SubscriptionManager.h b/automotive/vehicle/aidl/impl/current/vhal/include/SubscriptionManager.h
index cac1901..59c21aa 100644
--- a/automotive/vehicle/aidl/impl/current/vhal/include/SubscriptionManager.h
+++ b/automotive/vehicle/aidl/impl/current/vhal/include/SubscriptionManager.h
@@ -118,8 +118,19 @@
std::vector<aidl::android::hardware::automotive::vehicle::VehiclePropError>>
getSubscribedClientsForErrorEvents(const std::vector<SetValueErrorEvent>& errorEvents);
- // Returns the number of subscribed clients.
- size_t countClients();
+ // Subscribes to supported values change.
+ VhalResult<void> subscribeSupportedValueChange(const CallbackType& callback,
+ const std::vector<PropIdAreaId>& propIdAreaIds);
+
+ // Unsubscribes to supported values change.
+ VhalResult<void> unsubscribeSupportedValueChange(
+ ClientIdType client, const std::vector<PropIdAreaId>& propIdAreaIds);
+
+ // Returns the number of subscribed property change clients.
+ size_t countPropertyChangeClients();
+
+ // Returns the number of subscribed supported value change clients.
+ size_t countSupportedValueChangeClients();
// Checks whether the sample rate is valid.
static bool checkSampleRateHz(float sampleRateHz);
@@ -160,6 +171,11 @@
std::unordered_set<VehiclePropValue, VehiclePropValueHashPropIdAreaId,
VehiclePropValueEqualPropIdAreaId>>
mContSubValuesByCallback GUARDED_BY(mLock);
+ std::unordered_map<PropIdAreaId, std::unordered_map<ClientIdType, CallbackType>,
+ PropIdAreaIdHash>
+ mSupportedValueChangeClientsByPropIdAreaId GUARDED_BY(mLock);
+ std::unordered_map<ClientIdType, std::unordered_set<PropIdAreaId, PropIdAreaIdHash>>
+ mSupportedValueChangePropIdAreaIdsByClient GUARDED_BY(mLock);
VhalResult<void> addContinuousSubscriberLocked(const ClientIdType& clientId,
const PropIdAreaId& propIdAreaId,
@@ -180,6 +196,9 @@
VhalResult<void> unsubscribePropIdAreaIdLocked(SubscriptionManager::ClientIdType clientId,
const PropIdAreaId& propIdAreaId)
REQUIRES(mLock);
+ VhalResult<void> unsubscribeSupportedValueChangeLocked(
+ SubscriptionManager::ClientIdType clientId,
+ const std::vector<PropIdAreaId>& propIdAreaIds) REQUIRES(mLock);
// Checks whether the manager is empty. For testing purpose.
bool isEmpty();
diff --git a/automotive/vehicle/aidl/impl/current/vhal/src/DefaultVehicleHal.cpp b/automotive/vehicle/aidl/impl/current/vhal/src/DefaultVehicleHal.cpp
index 509d1c3..25af50e 100644
--- a/automotive/vehicle/aidl/impl/current/vhal/src/DefaultVehicleHal.cpp
+++ b/automotive/vehicle/aidl/impl/current/vhal/src/DefaultVehicleHal.cpp
@@ -82,9 +82,6 @@
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++) {
@@ -972,25 +969,25 @@
return ScopedAStatus::ok();
}
-Result<const VehicleAreaConfig*> DefaultVehicleHal::getAreaConfigForPropIdAreaId(
- int32_t propId, int32_t areaId) const {
+Result<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)
+ 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)
+ return Error() << "AreaId config not found for propertyId: " << propIdToString(propId)
<< ", areaId: " << areaId;
}
- return areaConfig;
+ return *areaConfig;
}
-Result<const HasSupportedValueInfo*> DefaultVehicleHal::getHasSupportedValueInfo(
- int32_t propId, int32_t areaId) const {
- Result<const VehicleAreaConfig*> propIdAreaIdConfigResult =
+Result<HasSupportedValueInfo> DefaultVehicleHal::getHasSupportedValueInfo(int32_t propId,
+ int32_t areaId) const {
+ Result<VehicleAreaConfig> propIdAreaIdConfigResult =
getAreaConfigForPropIdAreaId(propId, areaId);
if (!isGlobalProp(propId) && !propIdAreaIdConfigResult.ok()) {
// For global property, it is possible that no config exists.
@@ -998,11 +995,11 @@
}
if (propIdAreaIdConfigResult.has_value()) {
auto areaConfig = propIdAreaIdConfigResult.value();
- if (areaConfig->hasSupportedValueInfo.has_value()) {
- return &(areaConfig->hasSupportedValueInfo.value());
+ if (areaConfig.hasSupportedValueInfo.has_value()) {
+ return areaConfig.hasSupportedValueInfo.value();
}
}
- return Error() << "property: " << propIdtoString(propId) << ", areaId: " << areaId
+ return Error() << "property: " << propIdToString(propId) << ", areaId: " << areaId
<< " does not support this operation because hasSupportedValueInfo is null";
}
@@ -1026,7 +1023,7 @@
continue;
}
- const auto& hasSupportedValueInfo = *(hasSupportedValueInfoResult.value());
+ const auto& hasSupportedValueInfo = hasSupportedValueInfoResult.value();
if (hasSupportedValueInfo.hasSupportedValuesList) {
toHardwarePropIdAreaIds.push_back(PropIdAreaId{.propId = propId, .areaId = areaId});
toHardwareRequestCounters.push_back(requestCounter);
@@ -1087,7 +1084,7 @@
continue;
}
- const auto& hasSupportedValueInfo = *(hasSupportedValueInfoResult.value());
+ const auto& hasSupportedValueInfo = hasSupportedValueInfoResult.value();
if (hasSupportedValueInfo.hasMinSupportedValue ||
hasSupportedValueInfo.hasMaxSupportedValue) {
toHardwarePropIdAreaIds.push_back(PropIdAreaId{.propId = propId, .areaId = areaId});
@@ -1130,15 +1127,65 @@
}
ScopedAStatus DefaultVehicleHal::registerSupportedValueChangeCallback(
- const std::shared_ptr<IVehicleCallback>&, const std::vector<VhalPropIdAreaId>&) {
- // TODO(b/381020465): Add relevant implementation.
- return ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+ const std::shared_ptr<IVehicleCallback>& callback,
+ const std::vector<VhalPropIdAreaId>& vhalPropIdAreaIds) {
+ std::vector<PropIdAreaId> propIdAreaIdsToSubscribe;
+ for (size_t i = 0; i < vhalPropIdAreaIds.size(); i++) {
+ const auto& vhalPropIdAreaId = vhalPropIdAreaIds.at(i);
+ int32_t propId = vhalPropIdAreaId.propId;
+ int32_t areaId = vhalPropIdAreaId.areaId;
+ auto hasSupportedValueInfoResult = getHasSupportedValueInfo(propId, areaId);
+ if (!hasSupportedValueInfoResult.ok()) {
+ ALOGE("registerSupportedValueChangeCallback not supported: %s",
+ hasSupportedValueInfoResult.error().message().c_str());
+ return toScopedAStatus(hasSupportedValueInfoResult, StatusCode::INVALID_ARG);
+ }
+ const auto& hasSupportedValueInfo = hasSupportedValueInfoResult.value();
+ if (!hasSupportedValueInfo.hasMinSupportedValue &&
+ !hasSupportedValueInfo.hasMaxSupportedValue &&
+ !hasSupportedValueInfo.hasSupportedValuesList) {
+ ALOGW("registerSupportedValueChangeCallback: do nothing for property: %s, "
+ "areaId: %" PRId32
+ ", no min/max supported values or supported values list"
+ " specified",
+ propIdToString(propId).c_str(), areaId);
+ continue;
+ }
+ propIdAreaIdsToSubscribe.push_back(PropIdAreaId{.propId = propId, .areaId = areaId});
+ }
+ if (propIdAreaIdsToSubscribe.empty()) {
+ return ScopedAStatus::ok();
+ }
+ auto result =
+ mSubscriptionManager->subscribeSupportedValueChange(callback, propIdAreaIdsToSubscribe);
+ if (!result.ok()) {
+ ALOGW("registerSupportedValueChangeCallback: failed to subscribe supported value change"
+ " for %s, error: %s",
+ fmt::format("{}", propIdAreaIdsToSubscribe).c_str(),
+ result.error().message().c_str());
+ return toScopedAStatus(result);
+ }
+ return ScopedAStatus::ok();
}
ScopedAStatus DefaultVehicleHal::unregisterSupportedValueChangeCallback(
- const std::shared_ptr<IVehicleCallback>&, const std::vector<VhalPropIdAreaId>&) {
- // TODO(b/381020465): Add relevant implementation.
- return ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+ const std::shared_ptr<IVehicleCallback>& callback,
+ const std::vector<VhalPropIdAreaId>& vhalPropIdAreaIds) {
+ std::vector<PropIdAreaId> propIdAreaIds;
+ for (const auto& vhalPropIdAreaId : vhalPropIdAreaIds) {
+ propIdAreaIds.push_back(
+ PropIdAreaId{.propId = vhalPropIdAreaId.propId, .areaId = vhalPropIdAreaId.areaId});
+ }
+
+ auto result = mSubscriptionManager->unsubscribeSupportedValueChange(callback->asBinder().get(),
+ propIdAreaIds);
+ if (!result.ok()) {
+ ALOGW("unregisterSupportedValueChangeCallback: failed to unsubscribe supported value change"
+ " for %s, error: %s",
+ fmt::format("{}", propIdAreaIds).c_str(), result.error().message().c_str());
+ return toScopedAStatus(result);
+ }
+ return ScopedAStatus::ok();
}
IVehicleHardware* DefaultVehicleHal::getHardware() {
@@ -1256,12 +1303,14 @@
dprintf(fd, "Currently have %zu getValues clients\n", mGetValuesClients.size());
dprintf(fd, "Currently have %zu setValues clients\n", mSetValuesClients.size());
dprintf(fd, "Currently have %zu subscribe clients\n", countSubscribeClients());
+ dprintf(fd, "Currently have %zu supported values change subscribe clients\n",
+ mSubscriptionManager->countSupportedValueChangeClients());
}
return STATUS_OK;
}
size_t DefaultVehicleHal::countSubscribeClients() {
- return mSubscriptionManager->countClients();
+ return mSubscriptionManager->countPropertyChangeClients();
}
} // namespace vehicle
diff --git a/automotive/vehicle/aidl/impl/current/vhal/src/SubscriptionManager.cpp b/automotive/vehicle/aidl/impl/current/vhal/src/SubscriptionManager.cpp
index 2d09e02..f790033 100644
--- a/automotive/vehicle/aidl/impl/current/vhal/src/SubscriptionManager.cpp
+++ b/automotive/vehicle/aidl/impl/current/vhal/src/SubscriptionManager.cpp
@@ -17,6 +17,7 @@
#include "SubscriptionManager.h"
#include <VehicleUtils.h>
+#include <android-base/format.h>
#include <android-base/stringprintf.h>
#include <utils/Log.h>
#include <utils/SystemClock.h>
@@ -65,6 +66,8 @@
mClientsByPropIdAreaId.clear();
mSubscribedPropsByClient.clear();
+ mSupportedValueChangeClientsByPropIdAreaId.clear();
+ mSupportedValueChangePropIdAreaIdsByClient.clear();
}
bool SubscriptionManager::checkSampleRateHz(float sampleRateHz) {
@@ -166,8 +169,7 @@
/*enableVur*/ false));
status != StatusCode::OK) {
return StatusError(status)
- << StringPrintf("failed subscribe for prop: %s, areaId: %" PRId32,
- propIdToString(propId).c_str(), areaId);
+ << fmt::format("failed subscribe for propIdAreaId: {}", propIdAreaId);
}
return {};
}
@@ -379,16 +381,111 @@
if (mSubscribedPropsByClient.find(clientId) == mSubscribedPropsByClient.end()) {
ALOGW("No property was subscribed for this client, unsubscribe does nothing");
- return {};
+ } else {
+ auto& propIdAreaIds = mSubscribedPropsByClient[clientId];
+ for (auto const& propIdAreaId : propIdAreaIds) {
+ if (auto result = unsubscribePropIdAreaIdLocked(clientId, propIdAreaId); !result.ok()) {
+ return result;
+ }
+ }
+ mSubscribedPropsByClient.erase(clientId);
}
- auto& subscriptions = mSubscribedPropsByClient[clientId];
- for (auto const& propIdAreaId : subscriptions) {
- if (auto result = unsubscribePropIdAreaIdLocked(clientId, propIdAreaId); !result.ok()) {
+ if (mSupportedValueChangePropIdAreaIdsByClient.find(clientId) ==
+ mSupportedValueChangePropIdAreaIdsByClient.end()) {
+ ALOGW("No supported value change was subscribed for this client, unsubscribe does nothing");
+ } else {
+ const auto& propIdAreaIds = mSupportedValueChangePropIdAreaIdsByClient[clientId];
+ if (auto result = unsubscribeSupportedValueChangeLocked(
+ clientId,
+ std::vector<PropIdAreaId>(propIdAreaIds.begin(), propIdAreaIds.end()));
+ !result.ok()) {
return result;
}
}
- mSubscribedPropsByClient.erase(clientId);
+ return {};
+}
+
+VhalResult<void> SubscriptionManager::subscribeSupportedValueChange(
+ const std::shared_ptr<IVehicleCallback>& callback,
+ const std::vector<PropIdAreaId>& propIdAreaIds) {
+ // Need to make sure this whole operation is guarded by a lock so that our internal state is
+ // consistent with IVehicleHardware state.
+ std::scoped_lock<std::mutex> lockGuard(mLock);
+
+ ClientIdType clientId = callback->asBinder().get();
+
+ // It is possible that some of the [propId, areaId]s are already subscribed, IVehicleHardware
+ // will ignore them.
+ if (auto status = mVehicleHardware->subscribeSupportedValueChange(propIdAreaIds);
+ status != StatusCode::OK) {
+ return StatusError(status)
+ << fmt::format("failed to call subscribeSupportedValueChange for propIdAreaIds: {}",
+ propIdAreaIds);
+ }
+ for (const auto& propIdAreaId : propIdAreaIds) {
+ mSupportedValueChangeClientsByPropIdAreaId[propIdAreaId][clientId] = callback;
+ // mSupportedValueChangePropIdAreaIdsByClient[clientId] is a set so this will ignore
+ // duplicate [propId, areaId].
+ mSupportedValueChangePropIdAreaIdsByClient[clientId].insert(propIdAreaId);
+ }
+ return {};
+}
+
+VhalResult<void> SubscriptionManager::unsubscribeSupportedValueChange(
+ SubscriptionManager::ClientIdType clientId,
+ const std::vector<PropIdAreaId>& propIdAreaIds) {
+ // Need to make sure this whole operation is guarded by a lock so that our internal state is
+ // consistent with IVehicleHardware state.
+ std::scoped_lock<std::mutex> lockGuard(mLock);
+
+ return unsubscribeSupportedValueChangeLocked(clientId, propIdAreaIds);
+}
+
+VhalResult<void> SubscriptionManager::unsubscribeSupportedValueChangeLocked(
+ SubscriptionManager::ClientIdType clientId,
+ const std::vector<PropIdAreaId>& propIdAreaIds) {
+ std::vector<PropIdAreaId> propIdAreaIdsToUnsubscribe;
+
+ // Check which [propId, areaId] needs to be unsubscribed from the hardware.
+ for (const auto& propIdAreaId : propIdAreaIds) {
+ auto it = mSupportedValueChangeClientsByPropIdAreaId.find(propIdAreaId);
+ if (it != mSupportedValueChangeClientsByPropIdAreaId.end()) {
+ const auto& clients = it->second;
+ if (clients.size() == 1 && clients.find(clientId) != clients.end()) {
+ // This callback is the only client registered for [propId, areaId].
+ // Unregister it should unregister the [propId, areaId].
+ propIdAreaIdsToUnsubscribe.push_back(propIdAreaId);
+ }
+ }
+ }
+
+ // Send the unsubscribe request.
+ if (!propIdAreaIdsToUnsubscribe.empty()) {
+ if (auto status =
+ mVehicleHardware->unsubscribeSupportedValueChange(propIdAreaIdsToUnsubscribe);
+ status != StatusCode::OK) {
+ return StatusError(status) << fmt::format(
+ "failed to call unsubscribeSupportedValueChange for "
+ "propIdAreaIds: {}",
+ propIdAreaIdsToUnsubscribe);
+ }
+ }
+
+ // Remove internal book-keeping.
+ for (const auto& propIdAreaId : propIdAreaIds) {
+ if (mSupportedValueChangeClientsByPropIdAreaId.find(propIdAreaId) !=
+ mSupportedValueChangeClientsByPropIdAreaId.end()) {
+ mSupportedValueChangeClientsByPropIdAreaId[propIdAreaId].erase(clientId);
+ }
+ if (mSupportedValueChangeClientsByPropIdAreaId.empty()) {
+ mSupportedValueChangeClientsByPropIdAreaId.erase(propIdAreaId);
+ }
+ mSupportedValueChangePropIdAreaIdsByClient[clientId].erase(propIdAreaId);
+ if (mSupportedValueChangePropIdAreaIdsByClient[clientId].empty()) {
+ mSupportedValueChangePropIdAreaIdsByClient.erase(clientId);
+ }
+ }
return {};
}
@@ -486,14 +583,21 @@
bool SubscriptionManager::isEmpty() {
std::scoped_lock<std::mutex> lockGuard(mLock);
- return mSubscribedPropsByClient.empty() && mClientsByPropIdAreaId.empty();
+ return mSubscribedPropsByClient.empty() && mClientsByPropIdAreaId.empty() &&
+ mSupportedValueChangeClientsByPropIdAreaId.empty() &&
+ mSupportedValueChangePropIdAreaIdsByClient.empty();
}
-size_t SubscriptionManager::countClients() {
+size_t SubscriptionManager::countPropertyChangeClients() {
std::scoped_lock<std::mutex> lockGuard(mLock);
return mSubscribedPropsByClient.size();
}
+size_t SubscriptionManager::countSupportedValueChangeClients() {
+ std::scoped_lock<std::mutex> lockGuard(mLock);
+ return mSupportedValueChangePropIdAreaIdsByClient.size();
+}
+
} // namespace vehicle
} // namespace automotive
} // namespace hardware
diff --git a/automotive/vehicle/aidl/impl/current/vhal/test/DefaultVehicleHalTest.cpp b/automotive/vehicle/aidl/impl/current/vhal/test/DefaultVehicleHalTest.cpp
index 4df5ba3..0526f7d 100644
--- a/automotive/vehicle/aidl/impl/current/vhal/test/DefaultVehicleHalTest.cpp
+++ b/automotive/vehicle/aidl/impl/current/vhal/test/DefaultVehicleHalTest.cpp
@@ -2418,6 +2418,205 @@
ASSERT_EQ(result.status, StatusCode::INVALID_ARG);
}
+TEST_F(DefaultVehicleHalTest, testRegisterSupportedValueChangeCallback) {
+ auto testConfigs = std::vector<VehiclePropConfig>(
+ {VehiclePropConfig{
+ .prop = testInt32VecProp(1),
+ .areaConfigs =
+ {
+ {.areaId = 0,
+ .hasSupportedValueInfo =
+ HasSupportedValueInfo{
+ .hasMinSupportedValue = false,
+ .hasMaxSupportedValue = false,
+ .hasSupportedValuesList = false,
+ }},
+ },
+ },
+ VehiclePropConfig{
+ .prop = testInt32VecWindowProp(2),
+ .areaConfigs =
+ {
+ {.areaId = 2,
+ .hasSupportedValueInfo =
+ HasSupportedValueInfo{
+ .hasMinSupportedValue = true,
+ .hasMaxSupportedValue = false,
+ .hasSupportedValuesList = false,
+ }},
+ },
+ }});
+
+ auto hardware = std::make_unique<MockVehicleHardware>();
+ MockVehicleHardware* hardwarePtr = hardware.get();
+ hardware->setPropertyConfigs(testConfigs);
+
+ auto vhal = ndk::SharedRefBase::make<DefaultVehicleHal>(std::move(hardware));
+ std::shared_ptr<IVehicle> client = IVehicle::fromBinder(vhal->asBinder());
+
+ // This request is ignored because it does not have supported value info.
+ auto propIdAreaId1 = VhalPropIdAreaId{.propId = testInt32VecProp(1), .areaId = 0};
+ auto propIdAreaId2 = VhalPropIdAreaId{.propId = testInt32VecWindowProp(2), .areaId = 2};
+ auto status = client->registerSupportedValueChangeCallback(
+ getCallbackClient(), std::vector<VhalPropIdAreaId>{propIdAreaId1, propIdAreaId2});
+
+ ASSERT_TRUE(status.isOk()) << "Get non-okay status from registerSupportedValueChangeCallback"
+ << status.getMessage();
+ ASSERT_THAT(hardwarePtr->getSubscribedSupportedValueChangePropIdAreaIds(),
+ ElementsAre(PropIdAreaId{.propId = testInt32VecWindowProp(2), .areaId = 2}));
+}
+
+TEST_F(DefaultVehicleHalTest, testRegisterSupportedValueChangeCallback_invalidRequest) {
+ auto testConfigs = std::vector<VehiclePropConfig>({VehiclePropConfig{
+ .prop = testInt32VecProp(1),
+ .areaConfigs =
+ {
+ {.areaId = 0, .hasSupportedValueInfo = std::nullopt},
+ },
+ }});
+ 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());
+
+ auto propIdAreaId1 = VhalPropIdAreaId{.propId = testInt32VecProp(1), .areaId = 0};
+ auto status = client->registerSupportedValueChangeCallback(
+ getCallbackClient(), std::vector<VhalPropIdAreaId>{propIdAreaId1});
+
+ ASSERT_FALSE(status.isOk()) << "registerSupportedValueChangeCallback must return error if one "
+ "of the requested [propId, areaId]"
+ " does not have supportedValueInfo";
+}
+
+TEST_F(DefaultVehicleHalTest, testRegisterSupportedValueChangeCallback_errorStatusFromHardware) {
+ auto testConfigs = std::vector<VehiclePropConfig>({VehiclePropConfig{
+ .prop = testInt32VecWindowProp(2),
+ .areaConfigs =
+ {
+ {.areaId = 2,
+ .hasSupportedValueInfo =
+ HasSupportedValueInfo{
+ .hasMinSupportedValue = true,
+ .hasMaxSupportedValue = false,
+ .hasSupportedValuesList = false,
+ }},
+ },
+ }});
+
+ auto hardware = std::make_unique<MockVehicleHardware>();
+ hardware->setStatus("subscribeSupportedValueChange", StatusCode::INTERNAL_ERROR);
+ hardware->setPropertyConfigs(testConfigs);
+
+ auto vhal = ndk::SharedRefBase::make<DefaultVehicleHal>(std::move(hardware));
+ std::shared_ptr<IVehicle> client = IVehicle::fromBinder(vhal->asBinder());
+
+ auto propIdAreaId = VhalPropIdAreaId{.propId = testInt32VecWindowProp(2), .areaId = 2};
+ auto status = client->registerSupportedValueChangeCallback(
+ getCallbackClient(), std::vector<VhalPropIdAreaId>{propIdAreaId});
+
+ ASSERT_FALSE(status.isOk()) << "registerSupportedValueChangeCallback must return error if "
+ "VehicleHardware returns error";
+}
+
+TEST_F(DefaultVehicleHalTest, testUnregisterSupportedValueChangeCallback) {
+ auto testConfigs = std::vector<VehiclePropConfig>(
+ {VehiclePropConfig{
+ .prop = testInt32VecProp(1),
+ .areaConfigs =
+ {
+ {.areaId = 0,
+ .hasSupportedValueInfo =
+ HasSupportedValueInfo{
+ .hasMinSupportedValue = false,
+ .hasMaxSupportedValue = false,
+ .hasSupportedValuesList = true,
+ }},
+ },
+ },
+ VehiclePropConfig{
+ .prop = testInt32VecWindowProp(2),
+ .areaConfigs =
+ {
+ {.areaId = 2,
+ .hasSupportedValueInfo =
+ HasSupportedValueInfo{
+ .hasMinSupportedValue = true,
+ .hasMaxSupportedValue = false,
+ .hasSupportedValuesList = false,
+ }},
+ },
+ }});
+
+ auto hardware = std::make_unique<MockVehicleHardware>();
+ MockVehicleHardware* hardwarePtr = hardware.get();
+ hardware->setPropertyConfigs(testConfigs);
+
+ auto vhal = ndk::SharedRefBase::make<DefaultVehicleHal>(std::move(hardware));
+ std::shared_ptr<IVehicle> client = IVehicle::fromBinder(vhal->asBinder());
+
+ auto propIdAreaId1 = VhalPropIdAreaId{.propId = testInt32VecProp(1), .areaId = 0};
+ auto propIdAreaId2 = VhalPropIdAreaId{.propId = testInt32VecWindowProp(2), .areaId = 2};
+ auto status = client->registerSupportedValueChangeCallback(
+ getCallbackClient(), std::vector<VhalPropIdAreaId>{propIdAreaId1, propIdAreaId2});
+
+ ASSERT_TRUE(status.isOk()) << "Get non-okay status from registerSupportedValueChangeCallback"
+ << status.getMessage();
+
+ status = client->unregisterSupportedValueChangeCallback(
+ getCallbackClient(), std::vector<VhalPropIdAreaId>{propIdAreaId1, propIdAreaId2});
+
+ ASSERT_TRUE(status.isOk()) << "Get non-okay status from unregisterSupportedValueChangeCallback"
+ << status.getMessage();
+
+ ASSERT_TRUE(hardwarePtr->getSubscribedSupportedValueChangePropIdAreaIds().empty())
+ << "All registered [propId, areaId]s must be unregistered";
+}
+
+TEST_F(DefaultVehicleHalTest, testUnregisterSupportedValueChangeCallback_ignoreUnregistered) {
+ auto testConfigs = std::vector<VehiclePropConfig>(
+ {VehiclePropConfig{
+ .prop = testInt32VecProp(1),
+ .areaConfigs =
+ {
+ {.areaId = 0,
+ .hasSupportedValueInfo =
+ HasSupportedValueInfo{
+ .hasMinSupportedValue = false,
+ .hasMaxSupportedValue = false,
+ .hasSupportedValuesList = true,
+ }},
+ },
+ },
+ VehiclePropConfig{
+ .prop = testInt32VecWindowProp(2),
+ .areaConfigs =
+ {
+ {.areaId = 2,
+ .hasSupportedValueInfo =
+ HasSupportedValueInfo{
+ .hasMinSupportedValue = true,
+ .hasMaxSupportedValue = false,
+ .hasSupportedValuesList = false,
+ }},
+ },
+ }});
+
+ auto hardware = std::make_unique<MockVehicleHardware>();
+ MockVehicleHardware* hardwarePtr = hardware.get();
+ hardware->setPropertyConfigs(testConfigs);
+
+ auto vhal = ndk::SharedRefBase::make<DefaultVehicleHal>(std::move(hardware));
+ std::shared_ptr<IVehicle> client = IVehicle::fromBinder(vhal->asBinder());
+
+ auto propIdAreaId1 = VhalPropIdAreaId{.propId = testInt32VecProp(1), .areaId = 0};
+ auto propIdAreaId2 = VhalPropIdAreaId{.propId = testInt32VecWindowProp(2), .areaId = 2};
+ auto status = client->unregisterSupportedValueChangeCallback(
+ getCallbackClient(), std::vector<VhalPropIdAreaId>{propIdAreaId1, propIdAreaId2});
+
+ ASSERT_TRUE(status.isOk());
+}
+
} // 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 ae2b5a2..11f1835 100644
--- a/automotive/vehicle/aidl/impl/current/vhal/test/MockVehicleHardware.cpp
+++ b/automotive/vehicle/aidl/impl/current/vhal/test/MockVehicleHardware.cpp
@@ -310,6 +310,40 @@
return mEventBatchingWindow;
}
+StatusCode MockVehicleHardware::subscribeSupportedValueChange(
+ const std::vector<PropIdAreaId>& propIdAreaIds) {
+ std::scoped_lock<std::mutex> lockGuard(mLock);
+ if (auto it = mStatusByFunctions.find(__func__); it != mStatusByFunctions.end()) {
+ if (StatusCode status = it->second; status != StatusCode::OK) {
+ return status;
+ }
+ }
+ for (const auto& propIdAreaId : propIdAreaIds) {
+ mSubscribedSupportedValueChangePropIdAreaIds.insert(propIdAreaId);
+ }
+ return StatusCode::OK;
+}
+
+StatusCode MockVehicleHardware::unsubscribeSupportedValueChange(
+ const std::vector<PropIdAreaId>& propIdAreaIds) {
+ std::scoped_lock<std::mutex> lockGuard(mLock);
+ if (auto it = mStatusByFunctions.find(__func__); it != mStatusByFunctions.end()) {
+ if (StatusCode status = it->second; status != StatusCode::OK) {
+ return status;
+ }
+ }
+ for (const auto& propIdAreaId : propIdAreaIds) {
+ mSubscribedSupportedValueChangePropIdAreaIds.erase(propIdAreaId);
+ }
+ return StatusCode::OK;
+}
+
+std::unordered_set<PropIdAreaId, PropIdAreaIdHash>
+MockVehicleHardware::getSubscribedSupportedValueChangePropIdAreaIds() {
+ std::scoped_lock<std::mutex> lockGuard(mLock);
+ return mSubscribedSupportedValueChangePropIdAreaIds;
+}
+
template <class ResultType>
StatusCode MockVehicleHardware::returnResponse(
std::shared_ptr<const std::function<void(std::vector<ResultType>)>> callback,
diff --git a/automotive/vehicle/aidl/impl/current/vhal/test/MockVehicleHardware.h b/automotive/vehicle/aidl/impl/current/vhal/test/MockVehicleHardware.h
index d1e9771..e7359db 100644
--- a/automotive/vehicle/aidl/impl/current/vhal/test/MockVehicleHardware.h
+++ b/automotive/vehicle/aidl/impl/current/vhal/test/MockVehicleHardware.h
@@ -71,6 +71,10 @@
getSupportedValuesLists(const std::vector<PropIdAreaId>& propIdAreaIds) override;
std::vector<aidl::android::hardware::automotive::vehicle::MinMaxSupportedValueResult>
getMinMaxSupportedValues(const std::vector<PropIdAreaId>& propIdAreaIds) override;
+ aidl::android::hardware::automotive::vehicle::StatusCode subscribeSupportedValueChange(
+ const std::vector<PropIdAreaId>& propIdAreaIds) override;
+ aidl::android::hardware::automotive::vehicle::StatusCode unsubscribeSupportedValueChange(
+ const std::vector<PropIdAreaId>& propIdAreaIds) override;
// Test functions.
void setPropertyConfigs(
@@ -114,10 +118,13 @@
std::vector<aidl::android::hardware::automotive::vehicle::SubscribeOptions>
getSubscribeOptions();
void clearSubscribeOptions();
- // Whether getAllPropertyConfigs() has been called, which blocks all all property configs
+ // Whether getAllPropertyConfigs() has been called, which blocks on all property configs
// being ready.
bool getAllPropertyConfigsCalled();
+ std::unordered_set<PropIdAreaId, PropIdAreaIdHash>
+ getSubscribedSupportedValueChangePropIdAreaIds();
+
private:
mutable std::mutex mLock;
mutable std::condition_variable mCv;
@@ -174,6 +181,9 @@
std::shared_ptr<RecurrentTimer> mRecurrentTimer;
std::unordered_map<int32_t, std::unordered_map<int32_t, std::shared_ptr<std::function<void()>>>>
mRecurrentActions GUARDED_BY(mLock);
+
+ std::unordered_set<PropIdAreaId, PropIdAreaIdHash> mSubscribedSupportedValueChangePropIdAreaIds
+ GUARDED_BY(mLock);
};
} // namespace vehicle
diff --git a/boot/aidl/default/Android.bp b/boot/aidl/default/Android.bp
index c1d3c57..2fd2dad 100644
--- a/boot/aidl/default/Android.bp
+++ b/boot/aidl/default/Android.bp
@@ -57,7 +57,7 @@
name: "android.hardware.boot-service.default_recovery",
defaults: ["android.hardware.boot-service_common"],
init_rc: ["android.hardware.boot-service.default_recovery.rc"],
- vintf_fragments: ["android.hardware.boot-service.default.xml"],
+ vintf_fragment_modules: ["android.hardware.boot-service.default.xml.recovery"],
recovery: true,
shared_libs: [
@@ -77,11 +77,16 @@
installable: false,
}
-prebuilt_etc {
+vintf_fragment {
+ name: "android.hardware.boot-service.default.xml.recovery",
+ src: "android.hardware.boot-service.default.xml",
+ recovery: true,
+}
+
+vintf_fragment {
name: "android.hardware.boot-service.default.xml",
src: "android.hardware.boot-service.default.xml",
- sub_dir: "vintf",
- installable: false,
+ vendor: true,
}
apex {
@@ -98,6 +103,8 @@
],
prebuilts: [
"android.hardware.boot-service.default.rc",
+ ],
+ vintf_fragment_modules: [
"android.hardware.boot-service.default.xml",
],
}
diff --git a/contexthub/aidl/aidl_api/android.hardware.contexthub/current/android/hardware/contexthub/IContextHub.aidl b/contexthub/aidl/aidl_api/android.hardware.contexthub/current/android/hardware/contexthub/IContextHub.aidl
index 2646d15..2940745 100644
--- a/contexthub/aidl/aidl_api/android.hardware.contexthub/current/android/hardware/contexthub/IContextHub.aidl
+++ b/contexthub/aidl/aidl_api/android.hardware.contexthub/current/android/hardware/contexthub/IContextHub.aidl
@@ -51,14 +51,6 @@
void sendMessageDeliveryStatusToHub(in int contextHubId, in android.hardware.contexthub.MessageDeliveryStatus messageDeliveryStatus);
List<android.hardware.contexthub.HubInfo> getHubs();
List<android.hardware.contexthub.EndpointInfo> getEndpoints();
- void registerEndpoint(in android.hardware.contexthub.EndpointInfo endpoint);
- void unregisterEndpoint(in android.hardware.contexthub.EndpointInfo endpoint);
- void registerEndpointCallback(in android.hardware.contexthub.IEndpointCallback callback);
- int[2] requestSessionIdRange(int size);
- void openEndpointSession(int sessionId, in android.hardware.contexthub.EndpointId destination, in android.hardware.contexthub.EndpointId initiator, in @nullable String serviceDescriptor);
- void sendMessageToEndpoint(int sessionId, in android.hardware.contexthub.Message msg);
- void sendMessageDeliveryStatusToEndpoint(int sessionId, in android.hardware.contexthub.MessageDeliveryStatus msgStatus);
- void closeEndpointSession(int sessionId, in android.hardware.contexthub.Reason reason);
- void endpointSessionOpenComplete(int sessionId);
+ @PropagateAllowBlocking android.hardware.contexthub.IEndpointCommunication registerEndpointHub(in android.hardware.contexthub.IEndpointCallback callback, in android.hardware.contexthub.HubInfo hubInfo);
const int EX_CONTEXT_HUB_UNSPECIFIED = (-1) /* -1 */;
}
diff --git a/contexthub/aidl/aidl_api/android.hardware.contexthub/current/android/hardware/contexthub/IEndpointCommunication.aidl b/contexthub/aidl/aidl_api/android.hardware.contexthub/current/android/hardware/contexthub/IEndpointCommunication.aidl
new file mode 100644
index 0000000..8742415
--- /dev/null
+++ b/contexthub/aidl/aidl_api/android.hardware.contexthub/current/android/hardware/contexthub/IEndpointCommunication.aidl
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.contexthub;
+@VintfStability
+interface IEndpointCommunication {
+ void registerEndpoint(in android.hardware.contexthub.EndpointInfo endpoint);
+ void unregisterEndpoint(in android.hardware.contexthub.EndpointInfo endpoint);
+ int[2] requestSessionIdRange(int size);
+ void openEndpointSession(int sessionId, in android.hardware.contexthub.EndpointId destination, in android.hardware.contexthub.EndpointId initiator, in @nullable String serviceDescriptor);
+ void sendMessageToEndpoint(int sessionId, in android.hardware.contexthub.Message msg);
+ void sendMessageDeliveryStatusToEndpoint(int sessionId, in android.hardware.contexthub.MessageDeliveryStatus msgStatus);
+ void closeEndpointSession(int sessionId, in android.hardware.contexthub.Reason reason);
+ void endpointSessionOpenComplete(int sessionId);
+ void unregister();
+}
diff --git a/contexthub/aidl/android/hardware/contexthub/IContextHub.aidl b/contexthub/aidl/android/hardware/contexthub/IContextHub.aidl
index eb6d051..3fb452c 100644
--- a/contexthub/aidl/android/hardware/contexthub/IContextHub.aidl
+++ b/contexthub/aidl/android/hardware/contexthub/IContextHub.aidl
@@ -18,19 +18,16 @@
import android.hardware.contexthub.ContextHubInfo;
import android.hardware.contexthub.ContextHubMessage;
-import android.hardware.contexthub.EndpointId;
import android.hardware.contexthub.EndpointInfo;
import android.hardware.contexthub.HostEndpointInfo;
import android.hardware.contexthub.HubInfo;
import android.hardware.contexthub.IContextHubCallback;
import android.hardware.contexthub.IEndpointCallback;
-import android.hardware.contexthub.Message;
+import android.hardware.contexthub.IEndpointCommunication;
import android.hardware.contexthub.MessageDeliveryStatus;
import android.hardware.contexthub.NanSessionStateUpdate;
import android.hardware.contexthub.NanoappBinary;
import android.hardware.contexthub.NanoappInfo;
-import android.hardware.contexthub.Reason;
-import android.hardware.contexthub.Service;
import android.hardware.contexthub.Setting;
@VintfStability
@@ -271,125 +268,22 @@
List<EndpointInfo> getEndpoints();
/**
- * Publishes an endpoint from the calling side (e.g. Android). Endpoints must be registered
- * prior to starting a session.
+ * Registers a new hub for endpoint communication which will receive events for its endpoints
+ * over the given callback. Returns an interface for the hub to register endpoints, start
+ * sessions, and send messages.
+ *
+ * It is valid for the same callback to be registered for multiple hubs, as the
+ * IEndpointCallback events provide sufficient information to determine which hub the event is
+ * intended for:
+ * * session ids are allocated to a specific hub and are unique
+ * * endpoints are identified by hub and endpoint id
+ *
+ * @param callback Interface to send endpoint events targeting the caller
+ * @param hubInfo Details of the hub being registered
+ * @return Interface for the hub to interact with other endpoint hubs
+ *
+ * @throws EX_ILLEGAL_STATE if hubInfo.hubId has already been registered
*/
- void registerEndpoint(in EndpointInfo endpoint);
-
- /**
- * Teardown an endpoint from the calling side (e.g. Android). This endpoint must have already
- * been published via registerEndpoint().
- */
- void unregisterEndpoint(in EndpointInfo endpoint);
-
- /**
- * Attaches a callback interface to receive events targeted at endpoints registered by the
- * caller.
- */
- void registerEndpointCallback(in IEndpointCallback callback);
-
- /**
- * Request a range of session IDs for the caller to use when initiating sessions. This may be
- * called more than once, but typical usage is to request a large enough range to accommodate
- * the maximum expected number of concurrent sessions, but not overly large as to limit other
- * clients.
- *
- * @param size The number of sessionId reserved for host-initiated sessions. This number should
- * be less than or equal to 1024.
- *
- * @return An array with two elements representing the smallest and largest possible session id
- * available for host.
- *
- * @throws EX_ILLEGAL_ARGUMENT if the size is invalid.
- * @throws EX_SERVICE_SPECIFIC if the id range requested cannot be allocated.
- */
- int[2] requestSessionIdRange(int size);
-
- /**
- * Request to open a session for communication between an endpoint previously registered by the
- * caller and a target endpoint found in getEndpoints(), optionally scoped to a service
- * published by the target endpoint.
- *
- * Upon returning from this function, the session is in pending state, and the final result will
- * be given by an asynchronous call to onEndpointSessionOpenComplete() on success, or
- * onCloseEndpointSession() on failure.
- *
- * @param sessionId Caller-allocated session identifier, which must be unique across all active
- * sessions, and must fall in a range allocated via requestSessionIdRange().
- * @param destination The EndpointId representing the destination side of the session.
- * @param initiator The EndpointId representing the initiating side of the session, which
- * must've already been published through registerEndpoint().
- * @param serviceDescriptor Descriptor for the service specification for scoping this session
- * (nullable). Null indicates a fully custom marshalling scheme. The value should match
- * a published descriptor for both destination and initiator.
- *
- * @throws EX_ILLEGAL_ARGUMENT if any of the arguments are invalid, or the combination of the
- * arguments is invalid.
- * @throws EX_SERVICE_SPECIFIC on other errors
- * - EX_CONTEXT_HUB_UNSPECIFIED if the request failed for other reasons.
- */
- void openEndpointSession(int sessionId, in EndpointId destination, in EndpointId initiator,
- in @nullable String serviceDescriptor);
-
- /**
- * Send a message from one endpoint to another on the (currently open) session.
- *
- * @param sessionId The integer representing the communication session, previously set in
- * openEndpointSession() or onEndpointSessionOpenRequest().
- * @param msg The Message object representing a message to endpoint from the endpoint on host.
- *
- * @throws EX_ILLEGAL_ARGUMENT if any of the arguments are invalid, or the combination of the
- * arguments is invalid.
- * @throws EX_SERVICE_SPECIFIC on other errors
- * - EX_CONTEXT_HUB_UNSPECIFIED if the request failed for other reasons.
- */
- void sendMessageToEndpoint(int sessionId, in Message msg);
-
- /**
- * Sends a message delivery status to the endpoint in response to receiving a Message with flag
- * FLAG_REQUIRES_DELIVERY_STATUS. Each message with the flag should have a MessageDeliveryStatus
- * response. This method sends the message delivery status back to the remote endpoint for a
- * session.
- *
- * @param sessionId The integer representing the communication session, previously set in
- * openEndpointSession() or onEndpointSessionOpenRequest().
- * @param msgStatus The MessageDeliveryStatus object representing the delivery status for a
- * specific message (identified by the sequenceNumber) within the session.
- *
- * @throws EX_UNSUPPORTED_OPERATION if ContextHubInfo.supportsReliableMessages is false for
- * the hub involved in this session.
- */
- void sendMessageDeliveryStatusToEndpoint(int sessionId, in MessageDeliveryStatus msgStatus);
-
- /**
- * Closes a session previously opened by openEndpointSession() or requested via
- * onEndpointSessionOpenRequest(). Processing of session closure must be ordered/synchronized
- * with message delivery, such that if this session was open, any messages previously passed to
- * sendMessageToEndpoint() that are still in-flight must still be delivered before the session
- * is closed. Any in-flight messages to the endpoint that requested to close the session will
- * not be delivered.
- *
- * @param sessionId The integer representing the communication session, previously set in
- * openEndpointSession() or onEndpointSessionOpenRequest().
- * @param reason The reason for this close endpoint session request.
- *
- * @throws EX_ILLEGAL_ARGUMENT if any of the arguments are invalid, or the combination of the
- * arguments is invalid.
- * @throws EX_SERVICE_SPECIFIC on other errors
- * - EX_CONTEXT_HUB_UNSPECIFIED if the request failed for other reasons.
- */
- void closeEndpointSession(int sessionId, in Reason reason);
-
- /**
- * Notifies the HAL that the session requested by onEndpointSessionOpenRequest is ready to use.
- *
- * @param sessionId The integer representing the communication session, previously set in
- * onEndpointSessionOpenRequest(). This id is assigned by the HAL.
- *
- * @throws EX_ILLEGAL_ARGUMENT if any of the arguments are invalid, or the combination of the
- * arguments is invalid.
- * @throws EX_SERVICE_SPECIFIC on other errors
- * - EX_CONTEXT_HUB_UNSPECIFIED if the request failed for other reasons.
- */
- void endpointSessionOpenComplete(int sessionId);
+ @PropagateAllowBlocking
+ IEndpointCommunication registerEndpointHub(in IEndpointCallback callback, in HubInfo hubInfo);
}
diff --git a/contexthub/aidl/android/hardware/contexthub/IEndpointCommunication.aidl b/contexthub/aidl/android/hardware/contexthub/IEndpointCommunication.aidl
new file mode 100644
index 0000000..e5045ba
--- /dev/null
+++ b/contexthub/aidl/android/hardware/contexthub/IEndpointCommunication.aidl
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.contexthub;
+
+import android.hardware.contexthub.EndpointId;
+import android.hardware.contexthub.EndpointInfo;
+import android.hardware.contexthub.IEndpointCallback;
+import android.hardware.contexthub.Message;
+import android.hardware.contexthub.MessageDeliveryStatus;
+import android.hardware.contexthub.Reason;
+import android.hardware.contexthub.Service;
+
+@VintfStability
+interface IEndpointCommunication {
+ /**
+ * Publishes an endpoint from the calling side (e.g. Android). Endpoints must be registered
+ * prior to starting a session.
+ */
+ void registerEndpoint(in EndpointInfo endpoint);
+
+ /**
+ * Teardown an endpoint from the calling side (e.g. Android). This endpoint must have already
+ * been published via registerEndpoint().
+ */
+ void unregisterEndpoint(in EndpointInfo endpoint);
+
+ /**
+ * Request a range of session IDs for the caller to use when initiating sessions. This may be
+ * called more than once, but typical usage is to request a large enough range to accommodate
+ * the maximum expected number of concurrent sessions, but not overly large as to limit other
+ * clients.
+ *
+ * @param size The number of sessionId reserved for host-initiated sessions. This number should
+ * be less than or equal to 1024.
+ *
+ * @return An array with two elements representing the smallest and largest possible session id
+ * available for host.
+ *
+ * @throws EX_ILLEGAL_ARGUMENT if the size is invalid.
+ * @throws EX_SERVICE_SPECIFIC if the id range requested cannot be allocated.
+ */
+ int[2] requestSessionIdRange(int size);
+
+ /**
+ * Request to open a session for communication between an endpoint previously registered by the
+ * caller and a target endpoint found in getEndpoints(), optionally scoped to a service
+ * published by the target endpoint.
+ *
+ * Upon returning from this function, the session is in pending state, and the final result will
+ * be given by an asynchronous call to onEndpointSessionOpenComplete() on success, or
+ * onCloseEndpointSession() on failure.
+ *
+ * @param sessionId Caller-allocated session identifier, which must be unique across all active
+ * sessions, and must fall in a range allocated via requestSessionIdRange().
+ * @param destination The EndpointId representing the destination side of the session.
+ * @param initiator The EndpointId representing the initiating side of the session, which
+ * must've already been published through registerEndpoint().
+ * @param serviceDescriptor Descriptor for the service specification for scoping this session
+ * (nullable). Null indicates a fully custom marshalling scheme. The value should match
+ * a published descriptor for both destination and initiator.
+ *
+ * @throws EX_ILLEGAL_ARGUMENT if any of the arguments are invalid, or the combination of the
+ * arguments is invalid.
+ * @throws EX_SERVICE_SPECIFIC on other errors
+ * - EX_CONTEXT_HUB_UNSPECIFIED if the request failed for other reasons.
+ */
+ void openEndpointSession(int sessionId, in EndpointId destination, in EndpointId initiator,
+ in @nullable String serviceDescriptor);
+
+ /**
+ * Send a message from one endpoint to another on the (currently open) session.
+ *
+ * @param sessionId The integer representing the communication session, previously set in
+ * openEndpointSession() or onEndpointSessionOpenRequest().
+ * @param msg The Message object representing a message to endpoint from the endpoint on host.
+ *
+ * @throws EX_ILLEGAL_ARGUMENT if any of the arguments are invalid, or the combination of the
+ * arguments is invalid.
+ * @throws EX_SERVICE_SPECIFIC on other errors
+ * - EX_CONTEXT_HUB_UNSPECIFIED if the request failed for other reasons.
+ */
+ void sendMessageToEndpoint(int sessionId, in Message msg);
+
+ /**
+ * Sends a message delivery status to the endpoint in response to receiving a Message with flag
+ * FLAG_REQUIRES_DELIVERY_STATUS. Each message with the flag should have a MessageDeliveryStatus
+ * response. This method sends the message delivery status back to the remote endpoint for a
+ * session.
+ *
+ * @param sessionId The integer representing the communication session, previously set in
+ * openEndpointSession() or onEndpointSessionOpenRequest().
+ * @param msgStatus The MessageDeliveryStatus object representing the delivery status for a
+ * specific message (identified by the sequenceNumber) within the session.
+ *
+ * @throws EX_UNSUPPORTED_OPERATION if ContextHubInfo.supportsReliableMessages is false for
+ * the hub involved in this session.
+ */
+ void sendMessageDeliveryStatusToEndpoint(int sessionId, in MessageDeliveryStatus msgStatus);
+
+ /**
+ * Closes a session previously opened by openEndpointSession() or requested via
+ * onEndpointSessionOpenRequest(). Processing of session closure must be ordered/synchronized
+ * with message delivery, such that if this session was open, any messages previously passed to
+ * sendMessageToEndpoint() that are still in-flight must still be delivered before the session
+ * is closed. Any in-flight messages to the endpoint that requested to close the session will
+ * not be delivered.
+ *
+ * @param sessionId The integer representing the communication session, previously set in
+ * openEndpointSession() or onEndpointSessionOpenRequest().
+ * @param reason The reason for this close endpoint session request.
+ *
+ * @throws EX_ILLEGAL_ARGUMENT if any of the arguments are invalid, or the combination of the
+ * arguments is invalid.
+ * @throws EX_SERVICE_SPECIFIC on other errors
+ * - EX_CONTEXT_HUB_UNSPECIFIED if the request failed for other reasons.
+ */
+ void closeEndpointSession(int sessionId, in Reason reason);
+
+ /**
+ * Notifies the HAL that the session requested by onEndpointSessionOpenRequest is ready to use.
+ *
+ * @param sessionId The integer representing the communication session, previously set in
+ * onEndpointSessionOpenRequest(). This id is assigned by the HAL.
+ *
+ * @throws EX_ILLEGAL_ARGUMENT if any of the arguments are invalid, or the combination of the
+ * arguments is invalid.
+ * @throws EX_SERVICE_SPECIFIC on other errors
+ * - EX_CONTEXT_HUB_UNSPECIFIED if the request failed for other reasons.
+ */
+ void endpointSessionOpenComplete(int sessionId);
+
+ /**
+ * Unregisters this hub. Subsequent calls on this interface will fail.
+ *
+ * @throws EX_ILLEGAL_STATE if this interface was already unregistered.
+ */
+ void unregister();
+}
diff --git a/contexthub/aidl/default/ContextHub.cpp b/contexthub/aidl/default/ContextHub.cpp
index 19d9639..433617e 100644
--- a/contexthub/aidl/default/ContextHub.cpp
+++ b/contexthub/aidl/default/ContextHub.cpp
@@ -150,10 +150,11 @@
ScopedAStatus ContextHub::setTestMode(bool enable) {
if (enable) {
- std::unique_lock<std::mutex> lock(mEndpointMutex);
- mEndpoints.clear();
- mEndpointSessions.clear();
- mEndpointCallback = nullptr;
+ std::lock_guard lock(mHostHubsLock);
+ for (auto& [id, hub] : mIdToHostHub) {
+ hub->mActive = false;
+ }
+ mIdToHostHub.clear();
}
return ScopedAStatus::ok();
}
@@ -227,7 +228,23 @@
return ScopedAStatus::ok();
};
-ScopedAStatus ContextHub::registerEndpoint(const EndpointInfo& in_endpoint) {
+ScopedAStatus ContextHub::registerEndpointHub(
+ const std::shared_ptr<IEndpointCallback>& in_callback, const HubInfo& in_hubInfo,
+ std::shared_ptr<IEndpointCommunication>* _aidl_return) {
+ std::lock_guard lock(mHostHubsLock);
+ if (mIdToHostHub.count(in_hubInfo.hubId)) {
+ return ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+ }
+ auto hub = ndk::SharedRefBase::make<HubInterface>(*this, in_callback, in_hubInfo);
+ mIdToHostHub.insert({in_hubInfo.hubId, hub});
+ *_aidl_return = std::move(hub);
+ return ScopedAStatus::ok();
+}
+
+ScopedAStatus ContextHub::HubInterface::registerEndpoint(const EndpointInfo& in_endpoint) {
+ if (!mActive) {
+ return ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+ }
std::unique_lock<std::mutex> lock(mEndpointMutex);
for (const EndpointInfo& endpoint : mEndpoints) {
@@ -240,7 +257,10 @@
return ScopedAStatus::ok();
};
-ScopedAStatus ContextHub::unregisterEndpoint(const EndpointInfo& in_endpoint) {
+ScopedAStatus ContextHub::HubInterface::unregisterEndpoint(const EndpointInfo& in_endpoint) {
+ if (!mActive) {
+ return ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+ }
std::unique_lock<std::mutex> lock(mEndpointMutex);
for (auto it = mEndpoints.begin(); it != mEndpoints.end(); ++it) {
@@ -252,41 +272,47 @@
return ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
};
-ScopedAStatus ContextHub::registerEndpointCallback(
- const std::shared_ptr<IEndpointCallback>& in_callback) {
- std::unique_lock<std::mutex> lock(mEndpointMutex);
-
- mEndpointCallback = in_callback;
- return ScopedAStatus::ok();
-};
-
-ScopedAStatus ContextHub::requestSessionIdRange(int32_t in_size,
- std::array<int32_t, 2>* _aidl_return) {
+ScopedAStatus ContextHub::HubInterface::requestSessionIdRange(
+ int32_t in_size, std::array<int32_t, 2>* _aidl_return) {
+ if (!mActive) {
+ return ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+ }
constexpr int32_t kMaxSize = 1024;
if (in_size > kMaxSize || _aidl_return == nullptr) {
return ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
}
+ uint16_t base = 0;
{
- std::lock_guard<std::mutex> lock(mEndpointMutex);
- mMaxValidSessionId = in_size;
+ std::lock_guard lock(mHal.mHostHubsLock);
+ if (static_cast<int32_t>(USHRT_MAX) - mHal.mNextSessionIdBase + 1 < in_size) {
+ return ScopedAStatus::fromServiceSpecificError(EX_CONTEXT_HUB_UNSPECIFIED);
+ }
+ base = mHal.mNextSessionIdBase;
+ mHal.mNextSessionIdBase += in_size;
}
- (*_aidl_return)[0] = 0;
- (*_aidl_return)[1] = in_size;
+ {
+ std::lock_guard<std::mutex> lock(mEndpointMutex);
+ (*_aidl_return)[0] = mBaseSessionId = base;
+ (*_aidl_return)[1] = mMaxSessionId = base + (in_size - 1);
+ }
return ScopedAStatus::ok();
};
-ScopedAStatus ContextHub::openEndpointSession(
+ScopedAStatus ContextHub::HubInterface::openEndpointSession(
int32_t in_sessionId, const EndpointId& in_destination, const EndpointId& in_initiator,
const std::optional<std::string>& in_serviceDescriptor) {
+ if (!mActive) {
+ return ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+ }
// We are not calling onCloseEndpointSession on failure because the remote endpoints (our
// mock endpoints) always accept the session.
std::weak_ptr<IEndpointCallback> callback;
{
std::unique_lock<std::mutex> lock(mEndpointMutex);
- if (in_sessionId > mMaxValidSessionId) {
+ if (in_sessionId < mBaseSessionId || in_sessionId > mMaxSessionId) {
ALOGE("openEndpointSession: session ID %" PRId32 " is invalid", in_sessionId);
return ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
}
@@ -346,7 +372,11 @@
return ScopedAStatus::ok();
};
-ScopedAStatus ContextHub::sendMessageToEndpoint(int32_t in_sessionId, const Message& in_msg) {
+ScopedAStatus ContextHub::HubInterface::sendMessageToEndpoint(int32_t in_sessionId,
+ const Message& in_msg) {
+ if (!mActive) {
+ return ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+ }
std::weak_ptr<IEndpointCallback> callback;
{
std::unique_lock<std::mutex> lock(mEndpointMutex);
@@ -393,12 +423,19 @@
return ScopedAStatus::ok();
};
-ScopedAStatus ContextHub::sendMessageDeliveryStatusToEndpoint(
+ScopedAStatus ContextHub::HubInterface::sendMessageDeliveryStatusToEndpoint(
int32_t /* in_sessionId */, const MessageDeliveryStatus& /* in_msgStatus */) {
+ if (!mActive) {
+ return ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+ }
return ScopedAStatus::ok();
};
-ScopedAStatus ContextHub::closeEndpointSession(int32_t in_sessionId, Reason /* in_reason */) {
+ScopedAStatus ContextHub::HubInterface::closeEndpointSession(int32_t in_sessionId,
+ Reason /* in_reason */) {
+ if (!mActive) {
+ return ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+ }
std::unique_lock<std::mutex> lock(mEndpointMutex);
for (auto it = mEndpointSessions.begin(); it != mEndpointSessions.end(); ++it) {
@@ -411,8 +448,20 @@
return ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
};
-ScopedAStatus ContextHub::endpointSessionOpenComplete(int32_t /* in_sessionId */) {
+ScopedAStatus ContextHub::HubInterface::endpointSessionOpenComplete(int32_t /* in_sessionId */) {
+ if (!mActive) {
+ return ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+ }
return ScopedAStatus::ok();
};
+ScopedAStatus ContextHub::HubInterface::unregister() {
+ if (!mActive.exchange(false)) {
+ return ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+ }
+ std::lock_guard lock(mHal.mHostHubsLock);
+ mHal.mIdToHostHub.erase(kInfo.hubId);
+ return ScopedAStatus::ok();
+}
+
} // namespace aidl::android::hardware::contexthub
diff --git a/contexthub/aidl/default/include/contexthub-impl/ContextHub.h b/contexthub/aidl/default/include/contexthub-impl/ContextHub.h
index 6da8bf2..65e84bb 100644
--- a/contexthub/aidl/default/include/contexthub-impl/ContextHub.h
+++ b/contexthub/aidl/default/include/contexthub-impl/ContextHub.h
@@ -17,7 +17,9 @@
#pragma once
#include <aidl/android/hardware/contexthub/BnContextHub.h>
+#include <aidl/android/hardware/contexthub/BnEndpointCommunication.h>
+#include <atomic>
#include <mutex>
#include <unordered_set>
#include <vector>
@@ -56,54 +58,79 @@
::ndk::ScopedAStatus getHubs(std::vector<HubInfo>* _aidl_return) override;
::ndk::ScopedAStatus getEndpoints(std::vector<EndpointInfo>* _aidl_return) override;
- ::ndk::ScopedAStatus registerEndpoint(const EndpointInfo& in_endpoint) override;
- ::ndk::ScopedAStatus unregisterEndpoint(const EndpointInfo& in_endpoint) override;
- ::ndk::ScopedAStatus registerEndpointCallback(
- const std::shared_ptr<IEndpointCallback>& in_callback) override;
- ::ndk::ScopedAStatus requestSessionIdRange(int32_t in_size,
- std::array<int32_t, 2>* _aidl_return) override;
- ::ndk::ScopedAStatus openEndpointSession(
- int32_t in_sessionId, const EndpointId& in_destination, const EndpointId& in_initiator,
- const std::optional<std::string>& in_serviceDescriptor) override;
- ::ndk::ScopedAStatus sendMessageToEndpoint(int32_t in_sessionId,
- const Message& in_msg) override;
- ::ndk::ScopedAStatus sendMessageDeliveryStatusToEndpoint(
- int32_t in_sessionId, const MessageDeliveryStatus& in_msgStatus) override;
- ::ndk::ScopedAStatus closeEndpointSession(int32_t in_sessionId, Reason in_reason) override;
- ::ndk::ScopedAStatus endpointSessionOpenComplete(int32_t in_sessionId) override;
+ ::ndk::ScopedAStatus registerEndpointHub(
+ const std::shared_ptr<IEndpointCallback>& in_callback, const HubInfo& in_hubInfo,
+ std::shared_ptr<IEndpointCommunication>* _aidl_return) override;
private:
- struct EndpointSession {
- int32_t sessionId;
- EndpointId initiator;
- EndpointId peer;
- std::optional<std::string> serviceDescriptor;
+ class HubInterface : public BnEndpointCommunication {
+ public:
+ HubInterface(ContextHub& hal, const std::shared_ptr<IEndpointCallback>& in_callback,
+ const HubInfo& in_hubInfo)
+ : mHal(hal), mEndpointCallback(in_callback), kInfo(in_hubInfo) {}
+ ~HubInterface() = default;
+
+ ::ndk::ScopedAStatus registerEndpoint(const EndpointInfo& in_endpoint) override;
+ ::ndk::ScopedAStatus unregisterEndpoint(const EndpointInfo& in_endpoint) override;
+ ::ndk::ScopedAStatus requestSessionIdRange(int32_t in_size,
+ std::array<int32_t, 2>* _aidl_return) override;
+ ::ndk::ScopedAStatus openEndpointSession(
+ int32_t in_sessionId, const EndpointId& in_destination,
+ const EndpointId& in_initiator,
+ const std::optional<std::string>& in_serviceDescriptor) override;
+ ::ndk::ScopedAStatus sendMessageToEndpoint(int32_t in_sessionId,
+ const Message& in_msg) override;
+ ::ndk::ScopedAStatus sendMessageDeliveryStatusToEndpoint(
+ int32_t in_sessionId, const MessageDeliveryStatus& in_msgStatus) override;
+ ::ndk::ScopedAStatus closeEndpointSession(int32_t in_sessionId, Reason in_reason) override;
+ ::ndk::ScopedAStatus endpointSessionOpenComplete(int32_t in_sessionId) override;
+ ::ndk::ScopedAStatus unregister() override;
+
+ private:
+ friend class ContextHub;
+
+ struct EndpointSession {
+ int32_t sessionId;
+ EndpointId initiator;
+ EndpointId peer;
+ std::optional<std::string> serviceDescriptor;
+ };
+
+ //! Finds an endpoint in the range defined by the endpoints
+ //! @return whether the endpoint was found
+ template <typename Iter>
+ bool findEndpoint(const EndpointId& target, const Iter& begin, const Iter& end) {
+ for (auto iter = begin; iter != end; ++iter) {
+ if (iter->id.id == target.id && iter->id.hubId == target.hubId) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ //! Endpoint storage and information
+ ContextHub& mHal;
+ std::shared_ptr<IEndpointCallback> mEndpointCallback;
+ const HubInfo kInfo;
+
+ std::atomic<bool> mActive = true;
+
+ std::mutex mEndpointMutex;
+ std::vector<EndpointInfo> mEndpoints;
+ std::vector<EndpointSession> mEndpointSessions;
+ uint16_t mBaseSessionId;
+ uint16_t mMaxSessionId;
};
static constexpr uint32_t kMockHubId = 0;
- //! Finds an endpoint in the range defined by the endpoints
- //! @return whether the endpoint was found
- template <typename Iter>
- bool findEndpoint(const EndpointId& target, const Iter& begin, const Iter& end) {
- for (auto iter = begin; iter != end; ++iter) {
- if (iter->id.id == target.id && iter->id.hubId == target.hubId) {
- return true;
- }
- }
- return false;
- }
-
std::shared_ptr<IContextHubCallback> mCallback;
std::unordered_set<char16_t> mConnectedHostEndpoints;
- //! Endpoint storage and information
- std::mutex mEndpointMutex;
- std::vector<EndpointInfo> mEndpoints;
- std::vector<EndpointSession> mEndpointSessions;
- std::shared_ptr<IEndpointCallback> mEndpointCallback;
- int32_t mMaxValidSessionId = 0;
+ std::mutex mHostHubsLock;
+ std::unordered_map<int64_t, std::shared_ptr<HubInterface>> mIdToHostHub;
+ int32_t mNextSessionIdBase = 0;
};
} // namespace contexthub
diff --git a/contexthub/aidl/vts/VtsAidlHalContextHubTargetTest.cpp b/contexthub/aidl/vts/VtsAidlHalContextHubTargetTest.cpp
index aa611ce..d7859d9 100644
--- a/contexthub/aidl/vts/VtsAidlHalContextHubTargetTest.cpp
+++ b/contexthub/aidl/vts/VtsAidlHalContextHubTargetTest.cpp
@@ -24,6 +24,7 @@
#include <android/hardware/contexthub/IContextHub.h>
#include <android/hardware/contexthub/IContextHubCallback.h>
#include <android/hardware/contexthub/IEndpointCallback.h>
+#include <android/hardware/contexthub/IEndpointCommunication.h>
#include <binder/IServiceManager.h>
#include <binder/ProcessState.h>
#include <log/log.h>
@@ -46,6 +47,7 @@
using ::android::hardware::contexthub::HubInfo;
using ::android::hardware::contexthub::IContextHub;
using ::android::hardware::contexthub::IContextHubCallbackDefault;
+using ::android::hardware::contexthub::IEndpointCommunication;
using ::android::hardware::contexthub::Message;
using ::android::hardware::contexthub::MessageDeliveryStatus;
using ::android::hardware::contexthub::NanoappBinary;
@@ -62,34 +64,71 @@
// 6612b522-b717-41c8-b48d-c0b1cc64e142
constexpr std::array<uint8_t, 16> kUuid = {0x66, 0x12, 0xb5, 0x22, 0xb7, 0x17, 0x41, 0xc8,
0xb4, 0x8d, 0xc0, 0xb1, 0xcc, 0x64, 0xe1, 0x42};
+
const String16 kName{"VtsAidlHalContextHubTargetTest"};
const String16 kEchoServiceName{"android.hardware.contexthub.test.EchoService"};
+constexpr int64_t kDefaultHubId = 1;
+
+class TestEndpointCallback;
class ContextHubAidl : public testing::TestWithParam<std::tuple<std::string, int32_t>> {
public:
- virtual void SetUp() override {
- contextHub = android::waitForDeclaredService<IContextHub>(
+ void SetUp() override {
+ mContextHub = android::waitForDeclaredService<IContextHub>(
String16(std::get<0>(GetParam()).c_str()));
- ASSERT_NE(contextHub, nullptr);
-
- // Best effort enable test mode - this may not be supported on older HALS, so we
- // ignore the return value.
- contextHub->setTestMode(/* enable= */ true);
+ ASSERT_NE(mContextHub, nullptr);
+ mEndpointCb = sp<TestEndpointCallback>::make();
}
- virtual void TearDown() override { contextHub->setTestMode(/* enable= */ false); }
-
uint32_t getHubId() { return std::get<1>(GetParam()); }
+ Status registerHub(int64_t id, sp<IEndpointCommunication>* hubInterface) {
+ HubInfo info;
+ info.hubId = id;
+ return mContextHub->registerEndpointHub(mEndpointCb, info, hubInterface);
+ }
+
+ bool registerDefaultHub() {
+ Status status = registerHub(kDefaultHubId, &mHubInterface);
+ if (status.exceptionCode() == Status::EX_UNSUPPORTED_OPERATION ||
+ status.transactionError() == android::UNKNOWN_TRANSACTION) {
+ return false;
+ }
+ EXPECT_TRUE(status.isOk());
+ EXPECT_NE(mHubInterface, nullptr);
+ if (!mHubInterface) {
+ return false;
+ }
+ return true;
+ }
+
void testSettingChanged(Setting setting);
- sp<IContextHub> contextHub;
+ sp<IContextHub> mContextHub;
+ sp<TestEndpointCallback> mEndpointCb;
+ sp<IEndpointCommunication> mHubInterface;
+};
+
+class ContextHubAidlWithTestMode : public ContextHubAidl {
+ public:
+ void SetUp() override {
+ ContextHubAidl::SetUp();
+
+ // Best effort enable test mode - this may not be supported on older HALS, so we
+ // ignore the return value.
+ mContextHub->setTestMode(/* enable= */ true);
+ }
+
+ void TearDown() override {
+ mContextHub->setTestMode(/* enable= */ false);
+ ContextHubAidl::TearDown();
+ }
};
TEST_P(ContextHubAidl, TestGetHubs) {
std::vector<ContextHubInfo> hubs;
- ASSERT_TRUE(contextHub->getContextHubs(&hubs).isOk());
+ ASSERT_TRUE(mContextHub->getContextHubs(&hubs).isOk());
ALOGD("System reports %zu hubs", hubs.size());
@@ -111,7 +150,7 @@
}
TEST_P(ContextHubAidl, TestEnableTestMode) {
- Status status = contextHub->setTestMode(true);
+ Status status = mContextHub->setTestMode(true);
if (status.exceptionCode() == Status::EX_UNSUPPORTED_OPERATION ||
status.transactionError() == android::UNKNOWN_TRANSACTION) {
GTEST_SKIP() << "Not supported -> old API; or not implemented";
@@ -121,7 +160,7 @@
}
TEST_P(ContextHubAidl, TestDisableTestMode) {
- Status status = contextHub->setTestMode(false);
+ Status status = mContextHub->setTestMode(false);
if (status.exceptionCode() == Status::EX_UNSUPPORTED_OPERATION ||
status.transactionError() == android::UNKNOWN_TRANSACTION) {
GTEST_SKIP() << "Not supported -> old API; or not implemented";
@@ -170,7 +209,7 @@
TEST_P(ContextHubAidl, TestRegisterCallback) {
sp<EmptyContextHubCallback> cb = sp<EmptyContextHubCallback>::make();
- ASSERT_TRUE(contextHub->registerCallback(getHubId(), cb).isOk());
+ ASSERT_TRUE(mContextHub->registerCallback(getHubId(), cb).isOk());
}
// Helper callback that puts the async appInfo callback data into a promise
@@ -219,8 +258,8 @@
// Calls queryApps() and checks the returned metadata
TEST_P(ContextHubAidl, TestQueryApps) {
sp<QueryAppsCallback> cb = sp<QueryAppsCallback>::make();
- ASSERT_TRUE(contextHub->registerCallback(getHubId(), cb).isOk());
- ASSERT_TRUE(contextHub->queryNanoapps(getHubId()).isOk());
+ ASSERT_TRUE(mContextHub->registerCallback(getHubId(), cb).isOk());
+ ASSERT_TRUE(mContextHub->queryNanoapps(getHubId()).isOk());
std::vector<NanoappInfo> appInfoList;
ASSERT_TRUE(waitForCallback(cb->promise.get_future(), &appInfoList));
@@ -241,7 +280,7 @@
// Calls getPreloadedNanoappsIds() and verifies there are preloaded nanoapps
TEST_P(ContextHubAidl, TestGetPreloadedNanoappIds) {
std::vector<int64_t> preloadedNanoappIds;
- Status status = contextHub->getPreloadedNanoappIds(getHubId(), &preloadedNanoappIds);
+ Status status = mContextHub->getPreloadedNanoappIds(getHubId(), &preloadedNanoappIds);
if (status.exceptionCode() == Status::EX_UNSUPPORTED_OPERATION ||
status.transactionError() == android::UNKNOWN_TRANSACTION) {
GTEST_SKIP() << "Not supported -> old API; or not implemented";
@@ -304,7 +343,7 @@
public:
virtual void SetUp() override {
ContextHubAidl::SetUp();
- ASSERT_TRUE(contextHub->registerCallback(getHubId(), cb).isOk());
+ ASSERT_TRUE(mContextHub->registerCallback(getHubId(), cb).isOk());
}
sp<TransactionResultCallback> cb = sp<TransactionResultCallback>::make();
@@ -318,7 +357,7 @@
std::fill(message.messageBody.begin(), message.messageBody.end(), 0);
ALOGD("Sending message to non-existent nanoapp");
- ASSERT_TRUE(contextHub->sendMessageToHub(getHubId(), message).isOk());
+ ASSERT_TRUE(mContextHub->sendMessageToHub(getHubId(), message).isOk());
}
TEST_P(ContextHubTransactionTest, TestLoadEmptyNanoapp) {
@@ -332,7 +371,7 @@
emptyApp.targetChreApiMinorVersion = 0;
ALOGD("Loading empty nanoapp");
- bool success = contextHub->loadNanoapp(getHubId(), emptyApp, cb->expectedTransactionId).isOk();
+ bool success = mContextHub->loadNanoapp(getHubId(), emptyApp, cb->expectedTransactionId).isOk();
if (success) {
bool transactionSuccess;
ASSERT_TRUE(waitForCallback(cb->promise.get_future(), &transactionSuccess));
@@ -345,7 +384,7 @@
ALOGD("Unloading nonexistent nanoapp");
bool success =
- contextHub->unloadNanoapp(getHubId(), kNonExistentAppId, cb->expectedTransactionId)
+ mContextHub->unloadNanoapp(getHubId(), kNonExistentAppId, cb->expectedTransactionId)
.isOk();
if (success) {
bool transactionSuccess;
@@ -359,7 +398,7 @@
ALOGD("Enabling nonexistent nanoapp");
bool success =
- contextHub->enableNanoapp(getHubId(), kNonExistentAppId, cb->expectedTransactionId)
+ mContextHub->enableNanoapp(getHubId(), kNonExistentAppId, cb->expectedTransactionId)
.isOk();
if (success) {
bool transactionSuccess;
@@ -373,7 +412,7 @@
ALOGD("Disabling nonexistent nanoapp");
bool success =
- contextHub->disableNanoapp(getHubId(), kNonExistentAppId, cb->expectedTransactionId)
+ mContextHub->disableNanoapp(getHubId(), kNonExistentAppId, cb->expectedTransactionId)
.isOk();
if (success) {
bool transactionSuccess;
@@ -386,10 +425,10 @@
// In VTS, we only test that sending the values doesn't cause things to blow up - GTS tests
// verify the expected E2E behavior in CHRE
sp<EmptyContextHubCallback> cb = sp<EmptyContextHubCallback>::make();
- ASSERT_TRUE(contextHub->registerCallback(getHubId(), cb).isOk());
+ ASSERT_TRUE(mContextHub->registerCallback(getHubId(), cb).isOk());
- ASSERT_TRUE(contextHub->onSettingChanged(setting, true /* enabled */).isOk());
- ASSERT_TRUE(contextHub->onSettingChanged(setting, false /* enabled */).isOk());
+ ASSERT_TRUE(mContextHub->onSettingChanged(setting, true /* enabled */).isOk());
+ ASSERT_TRUE(mContextHub->onSettingChanged(setting, false /* enabled */).isOk());
}
TEST_P(ContextHubAidl, TestOnLocationSettingChanged) {
@@ -444,27 +483,27 @@
hostEndpointInfo.type = HostEndpointInfo::Type::NATIVE;
hostEndpointInfo.hostEndpointId = kHostEndpointId;
- ASSERT_TRUE(contextHub->onHostEndpointConnected(hostEndpointInfo).isOk());
- ASSERT_TRUE(contextHub->onHostEndpointDisconnected(kHostEndpointId).isOk());
+ ASSERT_TRUE(mContextHub->onHostEndpointConnected(hostEndpointInfo).isOk());
+ ASSERT_TRUE(mContextHub->onHostEndpointDisconnected(kHostEndpointId).isOk());
}
TEST_P(ContextHubTransactionTest, TestInvalidHostConnection) {
constexpr char16_t kHostEndpointId = 1;
- ASSERT_TRUE(contextHub->onHostEndpointDisconnected(kHostEndpointId).isOk());
+ ASSERT_TRUE(mContextHub->onHostEndpointDisconnected(kHostEndpointId).isOk());
}
TEST_P(ContextHubTransactionTest, TestNanSessionStateChange) {
NanSessionStateUpdate update;
update.state = true;
- Status status = contextHub->onNanSessionStateChanged(update);
+ Status status = mContextHub->onNanSessionStateChanged(update);
if (status.exceptionCode() == Status::EX_UNSUPPORTED_OPERATION ||
status.transactionError() == android::UNKNOWN_TRANSACTION) {
GTEST_SKIP() << "Not supported -> old API; or not implemented";
} else {
ASSERT_TRUE(status.isOk());
update.state = false;
- ASSERT_TRUE(contextHub->onNanSessionStateChanged(update).isOk());
+ ASSERT_TRUE(mContextHub->onNanSessionStateChanged(update).isOk());
}
}
@@ -473,7 +512,7 @@
messageDeliveryStatus.messageSequenceNumber = 123;
messageDeliveryStatus.errorCode = ErrorCode::OK;
- Status status = contextHub->sendMessageDeliveryStatusToHub(getHubId(), messageDeliveryStatus);
+ Status status = mContextHub->sendMessageDeliveryStatusToHub(getHubId(), messageDeliveryStatus);
if (status.exceptionCode() == Status::EX_UNSUPPORTED_OPERATION ||
status.transactionError() == android::UNKNOWN_TRANSACTION) {
GTEST_SKIP() << "Not supported -> old API; or not implemented";
@@ -546,7 +585,30 @@
bool mWasOnEndpointSessionOpenCompleteCalled = false;
};
-TEST_P(ContextHubAidl, RegisterEndpoint) {
+TEST_P(ContextHubAidlWithTestMode, RegisterHub) {
+ if (!registerDefaultHub()) {
+ GTEST_SKIP() << "Not supported -> old API; or not implemented";
+ }
+
+ sp<IEndpointCommunication> hub2;
+ Status status = registerHub(kDefaultHubId + 1, &hub2);
+ EXPECT_TRUE(status.isOk());
+
+ sp<IEndpointCommunication> hub3;
+ status = registerHub(kDefaultHubId + 1, &hub3);
+ ASSERT_FALSE(status.isOk());
+ EXPECT_EQ(status.exceptionCode(), Status::EX_ILLEGAL_STATE);
+
+ hub2->unregister();
+ status = registerHub(kDefaultHubId + 1, &hub3);
+ EXPECT_TRUE(status.isOk());
+}
+
+TEST_P(ContextHubAidlWithTestMode, RegisterEndpoint) {
+ if (!registerDefaultHub()) {
+ GTEST_SKIP() << "Not supported -> old API; or not implemented";
+ }
+
EndpointInfo endpointInfo;
endpointInfo.id.id = 1;
endpointInfo.id.hubId = 0xCAFECAFECAFECAFE;
@@ -554,7 +616,7 @@
endpointInfo.name = String16("Test host endpoint 1");
endpointInfo.version = 42;
- Status status = contextHub->registerEndpoint(endpointInfo);
+ Status status = mHubInterface->registerEndpoint(endpointInfo);
if (status.exceptionCode() == Status::EX_UNSUPPORTED_OPERATION ||
status.transactionError() == android::UNKNOWN_TRANSACTION) {
GTEST_SKIP() << "Not supported -> old API; or not implemented";
@@ -563,7 +625,11 @@
}
}
-TEST_P(ContextHubAidl, RegisterEndpointSameNameFailure) {
+TEST_P(ContextHubAidlWithTestMode, RegisterEndpointSameNameFailure) {
+ if (!registerDefaultHub()) {
+ GTEST_SKIP() << "Not supported -> old API; or not implemented";
+ }
+
EndpointInfo endpointInfo;
endpointInfo.id.id = 2;
endpointInfo.id.hubId = 0xCAFECAFECAFECAFE;
@@ -578,7 +644,7 @@
endpointInfo2.name = String16("Test host endpoint 2");
endpointInfo2.version = 42;
- Status status = contextHub->registerEndpoint(endpointInfo);
+ Status status = mHubInterface->registerEndpoint(endpointInfo);
if (status.exceptionCode() == Status::EX_UNSUPPORTED_OPERATION ||
status.transactionError() == android::UNKNOWN_TRANSACTION) {
GTEST_SKIP() << "Not supported -> old API; or not implemented";
@@ -586,10 +652,14 @@
EXPECT_TRUE(status.isOk());
}
- EXPECT_FALSE(contextHub->registerEndpoint(endpointInfo2).isOk());
+ EXPECT_FALSE(mHubInterface->registerEndpoint(endpointInfo2).isOk());
}
-TEST_P(ContextHubAidl, RegisterEndpointSameIdFailure) {
+TEST_P(ContextHubAidlWithTestMode, RegisterEndpointSameIdFailure) {
+ if (!registerDefaultHub()) {
+ GTEST_SKIP() << "Not supported -> old API; or not implemented";
+ }
+
EndpointInfo endpointInfo;
endpointInfo.id.id = 4;
endpointInfo.id.hubId = 0xCAFECAFECAFECAFE;
@@ -604,7 +674,7 @@
endpointInfo2.name = String16("Test host endpoint - same ID test");
endpointInfo2.version = 42;
- Status status = contextHub->registerEndpoint(endpointInfo);
+ Status status = mHubInterface->registerEndpoint(endpointInfo);
if (status.exceptionCode() == Status::EX_UNSUPPORTED_OPERATION ||
status.transactionError() == android::UNKNOWN_TRANSACTION) {
GTEST_SKIP() << "Not supported -> old API; or not implemented";
@@ -612,10 +682,14 @@
EXPECT_TRUE(status.isOk());
}
- EXPECT_FALSE(contextHub->registerEndpoint(endpointInfo2).isOk());
+ EXPECT_FALSE(mHubInterface->registerEndpoint(endpointInfo2).isOk());
}
-TEST_P(ContextHubAidl, UnregisterEndpoint) {
+TEST_P(ContextHubAidlWithTestMode, UnregisterEndpoint) {
+ if (!registerDefaultHub()) {
+ GTEST_SKIP() << "Not supported -> old API; or not implemented";
+ }
+
EndpointInfo endpointInfo;
endpointInfo.id.id = 6;
endpointInfo.id.hubId = 0xCAFECAFECAFECAFE;
@@ -623,7 +697,7 @@
endpointInfo.name = String16("Test host endpoint 6");
endpointInfo.version = 42;
- Status status = contextHub->registerEndpoint(endpointInfo);
+ Status status = mHubInterface->registerEndpoint(endpointInfo);
if (status.exceptionCode() == Status::EX_UNSUPPORTED_OPERATION ||
status.transactionError() == android::UNKNOWN_TRANSACTION) {
GTEST_SKIP() << "Not supported -> old API; or not implemented";
@@ -631,10 +705,14 @@
EXPECT_TRUE(status.isOk());
}
- EXPECT_TRUE(contextHub->unregisterEndpoint(endpointInfo).isOk());
+ EXPECT_TRUE(mHubInterface->unregisterEndpoint(endpointInfo).isOk());
}
-TEST_P(ContextHubAidl, UnregisterEndpointNonexistent) {
+TEST_P(ContextHubAidlWithTestMode, UnregisterEndpointNonexistent) {
+ if (!registerDefaultHub()) {
+ GTEST_SKIP() << "Not supported -> old API; or not implemented";
+ }
+
EndpointInfo endpointInfo;
endpointInfo.id.id = 100;
endpointInfo.id.hubId = 0xCAFECAFECAFECAFE;
@@ -642,7 +720,7 @@
endpointInfo.name = String16("Test host endpoint 100");
endpointInfo.version = 42;
- Status status = contextHub->unregisterEndpoint(endpointInfo);
+ Status status = mHubInterface->unregisterEndpoint(endpointInfo);
if (status.exceptionCode() == Status::EX_UNSUPPORTED_OPERATION ||
status.transactionError() == android::UNKNOWN_TRANSACTION) {
GTEST_SKIP() << "Not supported -> old API; or not implemented";
@@ -651,25 +729,9 @@
}
}
-TEST_P(ContextHubAidl, RegisterCallback) {
- auto cb = sp<TestEndpointCallback>::make();
- Status status = contextHub->registerEndpointCallback(cb);
- if (status.exceptionCode() == Status::EX_UNSUPPORTED_OPERATION ||
- status.transactionError() == android::UNKNOWN_TRANSACTION) {
+TEST_P(ContextHubAidlWithTestMode, OpenEndpointSessionInvalidRange) {
+ if (!registerDefaultHub()) {
GTEST_SKIP() << "Not supported -> old API; or not implemented";
- } else {
- EXPECT_TRUE(status.isOk());
- }
-}
-
-TEST_P(ContextHubAidl, OpenEndpointSessionInvalidRange) {
- auto cb = sp<TestEndpointCallback>::make();
- Status status = contextHub->registerEndpointCallback(cb);
- if (status.exceptionCode() == Status::EX_UNSUPPORTED_OPERATION ||
- status.transactionError() == android::UNKNOWN_TRANSACTION) {
- GTEST_SKIP() << "Not supported -> old API; or not implemented";
- } else {
- EXPECT_TRUE(status.isOk());
}
// Register the endpoint
@@ -679,11 +741,11 @@
initiatorEndpoint.type = EndpointInfo::EndpointType::NATIVE;
initiatorEndpoint.name = String16("Test host endpoint 7");
initiatorEndpoint.version = 42;
- EXPECT_TRUE(contextHub->registerEndpoint(initiatorEndpoint).isOk());
+ EXPECT_TRUE(mHubInterface->registerEndpoint(initiatorEndpoint).isOk());
// Find the destination, if it exists
std::vector<EndpointInfo> endpoints;
- EXPECT_TRUE(contextHub->getEndpoints(&endpoints).isOk());
+ EXPECT_TRUE(mContextHub->getEndpoints(&endpoints).isOk());
const EndpointInfo* destinationEndpoint = nullptr;
for (const EndpointInfo& endpoint : endpoints) {
for (const Service& service : endpoint.services) {
@@ -700,30 +762,24 @@
// Request the range
constexpr int32_t requestedRange = 100;
std::array<int32_t, 2> range;
- ASSERT_TRUE(contextHub->requestSessionIdRange(requestedRange, &range).isOk());
+ ASSERT_TRUE(mHubInterface->requestSessionIdRange(requestedRange, &range).isOk());
EXPECT_EQ(range.size(), 2);
EXPECT_GE(range[1] - range[0] + 1, requestedRange);
// Open the session
int32_t sessionId = range[1] + 10; // invalid
- EXPECT_FALSE(contextHub
+ EXPECT_FALSE(mHubInterface
->openEndpointSession(sessionId, destinationEndpoint->id,
initiatorEndpoint.id,
/* in_serviceDescriptor= */ kEchoServiceName)
.isOk());
}
-TEST_P(ContextHubAidl, OpenEndpointSessionAndSendMessageEchoesBack) {
- auto cb = sp<TestEndpointCallback>::make();
- Status status = contextHub->registerEndpointCallback(cb);
- if (status.exceptionCode() == Status::EX_UNSUPPORTED_OPERATION ||
- status.transactionError() == android::UNKNOWN_TRANSACTION) {
+TEST_P(ContextHubAidlWithTestMode, OpenEndpointSessionAndSendMessageEchoesBack) {
+ if (!registerDefaultHub()) {
GTEST_SKIP() << "Not supported -> old API; or not implemented";
- } else {
- EXPECT_TRUE(status.isOk());
}
-
- std::unique_lock<std::mutex> lock(cb->getMutex());
+ std::unique_lock<std::mutex> lock(mEndpointCb->getMutex());
// Register the endpoint
EndpointInfo initiatorEndpoint;
@@ -732,11 +788,11 @@
initiatorEndpoint.type = EndpointInfo::EndpointType::NATIVE;
initiatorEndpoint.name = String16("Test host endpoint 7");
initiatorEndpoint.version = 42;
- EXPECT_TRUE(contextHub->registerEndpoint(initiatorEndpoint).isOk());
+ EXPECT_TRUE(mHubInterface->registerEndpoint(initiatorEndpoint).isOk());
// Find the destination, if it exists
std::vector<EndpointInfo> endpoints;
- EXPECT_TRUE(contextHub->getEndpoints(&endpoints).isOk());
+ EXPECT_TRUE(mContextHub->getEndpoints(&endpoints).isOk());
const EndpointInfo* destinationEndpoint = nullptr;
for (const EndpointInfo& endpoint : endpoints) {
for (const Service& service : endpoint.services) {
@@ -753,32 +809,32 @@
// Request the range
constexpr int32_t requestedRange = 100;
std::array<int32_t, 2> range;
- ASSERT_TRUE(contextHub->requestSessionIdRange(requestedRange, &range).isOk());
+ ASSERT_TRUE(mHubInterface->requestSessionIdRange(requestedRange, &range).isOk());
EXPECT_EQ(range.size(), 2);
EXPECT_GE(range[1] - range[0] + 1, requestedRange);
// Open the session
- cb->resetWasOnEndpointSessionOpenCompleteCalled();
+ mEndpointCb->resetWasOnEndpointSessionOpenCompleteCalled();
int32_t sessionId = range[0];
- ASSERT_TRUE(contextHub
+ ASSERT_TRUE(mHubInterface
->openEndpointSession(sessionId, destinationEndpoint->id,
initiatorEndpoint.id,
/* in_serviceDescriptor= */ kEchoServiceName)
.isOk());
- cb->getCondVar().wait(lock);
- EXPECT_TRUE(cb->wasOnEndpointSessionOpenCompleteCalled());
+ mEndpointCb->getCondVar().wait(lock);
+ EXPECT_TRUE(mEndpointCb->wasOnEndpointSessionOpenCompleteCalled());
// Send the message
Message message;
message.flags = 0;
message.sequenceNumber = 0;
message.content.push_back(42);
- ASSERT_TRUE(contextHub->sendMessageToEndpoint(sessionId, message).isOk());
+ ASSERT_TRUE(mHubInterface->sendMessageToEndpoint(sessionId, message).isOk());
// Check for echo
- cb->getCondVar().wait(lock);
- EXPECT_FALSE(cb->getMessages().empty());
- EXPECT_EQ(cb->getMessages().back().content.back(), 42);
+ mEndpointCb->getCondVar().wait(lock);
+ EXPECT_FALSE(mEndpointCb->getMessages().empty());
+ EXPECT_EQ(mEndpointCb->getMessages().back().content.back(), 42);
}
std::string PrintGeneratedTest(const testing::TestParamInfo<ContextHubAidl::ParamType>& info) {
@@ -789,13 +845,17 @@
INSTANTIATE_TEST_SUITE_P(ContextHub, ContextHubAidl, testing::ValuesIn(generateContextHubMapping()),
PrintGeneratedTest);
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ContextHubAidlWithTestMode);
+INSTANTIATE_TEST_SUITE_P(ContextHub, ContextHubAidlWithTestMode,
+ testing::ValuesIn(generateContextHubMapping()), PrintGeneratedTest);
+
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ContextHubTransactionTest);
INSTANTIATE_TEST_SUITE_P(ContextHub, ContextHubTransactionTest,
testing::ValuesIn(generateContextHubMapping()), PrintGeneratedTest);
int main(int argc, char** argv) {
::testing::InitGoogleTest(&argc, argv);
- ProcessState::self()->setThreadPoolMaxThreadCount(1);
+ ProcessState::self()->setThreadPoolMaxThreadCount(2);
ProcessState::self()->startThreadPool();
return RUN_ALL_TESTS();
}
diff --git a/security/keymint/support/remote_prov_utils.cpp b/security/keymint/support/remote_prov_utils.cpp
index eaeec32..5afaf31 100644
--- a/security/keymint/support/remote_prov_utils.cpp
+++ b/security/keymint/support/remote_prov_utils.cpp
@@ -870,7 +870,7 @@
}
auto csr = hwtrust::Csr::validate(encodedCsr, *diceChainKind, false /*isFactory*/,
- false /*allowAnyMode*/, deviceSuffix(instanceName));
+ true /*allowAnyMode*/, deviceSuffix(instanceName));
if (!csr.ok()) {
return csr.error().message();
}
@@ -904,7 +904,7 @@
}
auto csr1 = hwtrust::Csr::validate(encodedCsr1, *diceChainKind, false /*isFactory*/,
- false /*allowAnyMode*/, deviceSuffix(instanceName1));
+ true /*allowAnyMode*/, deviceSuffix(instanceName1));
if (!csr1.ok()) {
return csr1.error().message();
}
@@ -921,7 +921,7 @@
}
auto csr2 = hwtrust::Csr::validate(encodedCsr2, *diceChainKind, false /*isFactory*/,
- false /*allowAnyMode*/, deviceSuffix(instanceName2));
+ true /*allowAnyMode*/, deviceSuffix(instanceName2));
if (!csr2.ok()) {
return csr2.error().message();
}
@@ -952,7 +952,7 @@
}
auto csr = hwtrust::Csr::validate(encodedCsr, *diceChainKind, false /*isFactory*/,
- false /*allowAnyMode*/, deviceSuffix(DEFAULT_INSTANCE_NAME));
+ true /*allowAnyMode*/, deviceSuffix(DEFAULT_INSTANCE_NAME));
if (!csr.ok()) {
return csr.error().message();
}
diff --git a/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see.hwcrypto/current/android/hardware/security/see/hwcrypto/IHwCryptoKey.aidl b/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see.hwcrypto/current/android/hardware/security/see/hwcrypto/IHwCryptoKey.aidl
index b31a06c..99eb761 100644
--- a/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see.hwcrypto/current/android/hardware/security/see/hwcrypto/IHwCryptoKey.aidl
+++ b/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see.hwcrypto/current/android/hardware/security/see/hwcrypto/IHwCryptoKey.aidl
@@ -64,7 +64,7 @@
int keySizeBytes;
}
union DerivedKeyPolicy {
- android.hardware.security.see.hwcrypto.IHwCryptoKey.ClearKeyPolicy clearKey;
+ android.hardware.security.see.hwcrypto.IHwCryptoKey.ClearKeyPolicy clearKeyPolicy;
byte[] opaqueKey;
}
parcelable DerivedKeyParameters {
diff --git a/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see.hwcrypto/current/android/hardware/security/see/hwcrypto/IHwCryptoOperations.aidl b/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see.hwcrypto/current/android/hardware/security/see/hwcrypto/IHwCryptoOperations.aidl
index 7c87dd3..3adb2f9 100644
--- a/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see.hwcrypto/current/android/hardware/security/see/hwcrypto/IHwCryptoOperations.aidl
+++ b/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see.hwcrypto/current/android/hardware/security/see/hwcrypto/IHwCryptoOperations.aidl
@@ -34,5 +34,5 @@
package android.hardware.security.see.hwcrypto;
@VintfStability
interface IHwCryptoOperations {
- android.hardware.security.see.hwcrypto.CryptoOperationResult[] processCommandList(inout android.hardware.security.see.hwcrypto.CryptoOperationSet[] operations, out android.hardware.security.see.hwcrypto.CryptoOperationErrorAdditionalInfo additionalErrorInfo);
+ android.hardware.security.see.hwcrypto.CryptoOperationResult[] processCommandList(inout android.hardware.security.see.hwcrypto.CryptoOperationSet[] operations);
}
diff --git a/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/IHwCryptoKey.aidl b/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/IHwCryptoKey.aidl
index 97a4c37..93d6cbc 100644
--- a/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/IHwCryptoKey.aidl
+++ b/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/IHwCryptoKey.aidl
@@ -107,10 +107,12 @@
* If used we will derive a clear key and pass it back as an array of bytes on
* <code>HwCryptoKeyMaterial::explicitKey</code>.
*/
- ClearKeyPolicy clearKey;
+ ClearKeyPolicy clearKeyPolicy;
/*
* Policy for the newly derived opaque key. Defines how the key can be used and its type.
+ * Its definition can be found in <code>KeyPolicy.cddl</code>, which is basically a CBOR
+ * serialization of the file <code>KeyPolicy.aidl</code>.
*/
byte[] opaqueKey;
}
@@ -154,11 +156,14 @@
* Key to be used to derive the new key using HKDF.
*
* @return:
- * A DiceCurrentBoundKeyResult containint the versioned key tied the current client version
+ * A DiceCurrentBoundKeyResult containing the versioned key tied the current client version
* on success.
*
* @throws:
- * ServiceSpecificException based on <code>HalErrorCode</code> if any error occurs.
+ * ServiceSpecificException based on <code>HalErrorCode</code> if any error occurs,
+ * in particular:
+ * - BAD_PARAMETER if an invalid DeviceKeyId is requested.
+ * - INVALID_KEY if an opaque key is provided that is not suitable for key derivation.
*/
DiceCurrentBoundKeyResult deriveCurrentDicePolicyBoundKey(
in DiceBoundDerivationKey derivationKey);
@@ -184,7 +189,11 @@
* success.
*
* @throws:
- * ServiceSpecificException based on <code>HalErrorCode</code> if any error occurs.
+ * ServiceSpecificException based on <code>HalErrorCode</code> if any error occurs,
+ * in particular:
+ * - BAD_PARAMETER if an invalid DeviceKeyId is requested or if dicePolicyForKeyVersion
+ * is not a valid encrypted DICE policy.
+ * - INVALID_KEY if an opaque key is provided that is not suitable for key derivation.
*/
DiceBoundKeyResult deriveDicePolicyBoundKey(
in DiceBoundDerivationKey derivationKey, in byte[] dicePolicyForKeyVersion);
@@ -197,10 +206,15 @@
* file for more information.
*
* @return:
- * A HwCryptoKeyMaterial containing the derived key on success.
+ * A <code>DerivedKey</code> containing the derived key on success.
*
* @throws:
- * ServiceSpecificException based on <code>HalErrorCode</code> if any error occurs.
+ * ServiceSpecificException based on <code>HalErrorCode</code> if any error occurs,
+ * in particular:
+ * - BAD_PARAMETER if an invalid key policy is provided or if the key policy conflicts
+ * with the requested key.
+ * - SERIALIZATION_ERROR if the provided key policy is not a valid CBOR key policy.
+ * - INVALID_KEY if an opaque key is provided that is not suitable for key derivation.
*/
DerivedKey deriveKey(in DerivedKeyParameters parameters);
@@ -233,7 +247,11 @@
* IOpaqueKey on success.
*
* @throws:
- * ServiceSpecificException based on <code>HalErrorCode</code> if any error occurs.
+ * ServiceSpecificException based on <code>HalErrorCode</code> if any error occurs,
+ * in particular:
+ * - BAD_PARAMETER if an invalid Key policy is provided or if the key policy conflicts
+ * with provided key material.
+ * - ALLOCATION_ERROR if the system runs out of memory while carring out the operation.
*/
IOpaqueKey importClearKey(in ExplicitKeyMaterial keyMaterial, in KeyPolicy newKeyPolicy);
@@ -248,7 +266,9 @@
* passing the receiver DICE policy to insure that only that receiver can import the key.
*
* @return:
- * byte[] on success, which is the caller encrypted DICE policy.
+ * byte[] on success, which is the caller encrypted DICE policy. The DICE policy follows
+ * the structure defined on DicePolicy.cddl, located under
+ * hardware/interfaces/security/authgraph/aidl/android/hardware/security/authgraph/
*/
byte[] getCurrentDicePolicy();
@@ -266,10 +286,14 @@
* DICE policy used to seal the exported key.
*
* @return:
- * An IOpaqueKey that can be directly be used on the local HWCrypto service on success.
+ * An IOpaqueKey that can be directly used on the local HWCrypto service on success.
*
* @throws:
- * ServiceSpecificException based on <code>HalErrorCode</code> if any error occurs.
+ * ServiceSpecificException based on <code>HalErrorCode</code> if any error occurs,
+ * in particular:
+ * - BAD_PARAMETER if an invalid encrypted sealing DICE policy is provided.
+ * - ALLOCATION_ERROR if the system runs out of memory while carring out the operation.
+ * - UNAUTHORIZED if the sealingDicePolicy do not match the caller.
*/
IOpaqueKey keyTokenImport(in OpaqueKeyToken requestedKey, in byte[] sealingDicePolicy);
@@ -287,8 +311,9 @@
* An IOpaqueKey corresponding to the requested key slot on success.
*
* @throws:
- * ServiceSpecificException <code>UNAUTHORIZED</code> if the caller cannot access the
- * requested key, another specific error based on <code>HalErrorCode</code> otherwise.
+ * ServiceSpecificException based on <code>HalErrorCode</code> if any error occurs,
+ * in particular:
+ * - UNAUTHORIZED if the caller cannot access the requested key.
*/
IOpaqueKey getKeyslotData(KeySlot slotId);
}
diff --git a/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/IHwCryptoOperations.aidl b/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/IHwCryptoOperations.aidl
index 9df6d67..dbe4d80 100644
--- a/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/IHwCryptoOperations.aidl
+++ b/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/IHwCryptoOperations.aidl
@@ -31,19 +31,21 @@
*
* @param operations:
* Parameter containing 1 or more set of commands to execute. Additionally, each set can
- * also contain a context on which the commands will be executed.
- *
- * @param additionalErrorInfo:
- * Structure containing additional info when errors are encountered. Only valid if the
- * function failed its execution.
+ * also contain a context on which the commands will be executed. The parameter has type
+ * inout because it can contain buffers used to write the output of the operation.
*
* @return:
* CryptoOperationResult[] on success, which can contain a context to continue executing
* each of the provided operations sets.
*
* @throws:
- * ServiceSpecificException based on <code>HalErrorCode</code> if any error occurs.
+ * ServiceSpecificException based on <code>HalErrorCode</code> if any error occurs,
+ * in particular:
+ * - INVALID_KEY if the provided key is not compatible with the operation requested.
+ * - BAD_STATE if the provided <code>CryptoOperationSet</code> contains operations that
+ * cannot be carried out in the current server state.
+ * - UNSUPPORTED if the requested operation is not supported by the server.
+ * - ALLOCATION_ERROR if the system runs out of memory while carring out the operation.
*/
- CryptoOperationResult[] processCommandList(inout CryptoOperationSet[] operations,
- out CryptoOperationErrorAdditionalInfo additionalErrorInfo);
+ CryptoOperationResult[] processCommandList(inout CryptoOperationSet[] operations);
}
diff --git a/tv/mediaquality/aidl/vts/functional/VtsHalMediaQualityTest.cpp b/tv/mediaquality/aidl/vts/functional/VtsHalMediaQualityTest.cpp
index f785cad..a01d4b0 100644
--- a/tv/mediaquality/aidl/vts/functional/VtsHalMediaQualityTest.cpp
+++ b/tv/mediaquality/aidl/vts/functional/VtsHalMediaQualityTest.cpp
@@ -35,6 +35,7 @@
#include <android/binder_manager.h>
#include <binder/IServiceManager.h>
#include <binder/ProcessState.h>
+#include <log/log.h>
#include <future>
using aidl::android::hardware::graphics::common::PixelFormat;
@@ -63,6 +64,407 @@
#define ASSERT_OK(ret) ASSERT_TRUE(ret.isOk())
#define EXPECT_OK(ret) EXPECT_TRUE(ret.isOk())
+void validateParameterRange0To100(int value) {
+ EXPECT_GE(value, 0);
+ EXPECT_LE(value, 100);
+}
+
+void validateParameterRange0To2047(int value) {
+ EXPECT_GE(value, 0);
+ EXPECT_LE(value, 2047);
+}
+
+void validateColorTemperature(int value) {
+ EXPECT_GE(value, -100);
+ EXPECT_LE(value, 100);
+}
+
+void validatePictureParameter(const PictureParameter& param) {
+ switch (param.getTag()) {
+ case PictureParameter::Tag::brightness: {
+ ALOGD("[validatePictureParameter] validate brightness value");
+ float value = param.get<PictureParameter::Tag::brightness>();
+ EXPECT_TRUE(value >= 0.0f && value <= 1.0f);
+ break;
+ }
+ case PictureParameter::Tag::contrast: {
+ ALOGD("[validatePictureParameter] validate contrast value");
+ int value = param.get<PictureParameter::Tag::contrast>();
+ validateParameterRange0To100(value);
+ break;
+ }
+ case PictureParameter::Tag::sharpness: {
+ ALOGD("[validatePictureParameter] validate sharpness value");
+ int value = param.get<PictureParameter::Tag::sharpness>();
+ validateParameterRange0To100(value);
+ break;
+ }
+ case PictureParameter::Tag::saturation: {
+ ALOGD("[validatePictureParameter] validate saturation value");
+ int value = param.get<PictureParameter::Tag::saturation>();
+ validateParameterRange0To100(value);
+ break;
+ }
+ case PictureParameter::Tag::hue: {
+ ALOGD("[validatePictureParameter] validate hue value");
+ int value = param.get<PictureParameter::Tag::hue>();
+ EXPECT_GE(value, -50);
+ EXPECT_LE(value, 50);
+ break;
+ }
+ case PictureParameter::Tag::colorTunerBrightness: {
+ ALOGD("[validatePictureParameter] validate colorTunerBrightness value");
+ int value = param.get<PictureParameter::Tag::colorTunerBrightness>();
+ validateParameterRange0To100(value);
+ break;
+ }
+ case PictureParameter::Tag::colorTunerSaturation: {
+ ALOGD("[validatePictureParameter] validate colorTunerSaturation value");
+ int value = param.get<PictureParameter::Tag::colorTunerSaturation>();
+ validateParameterRange0To100(value);
+ break;
+ }
+ case PictureParameter::Tag::colorTunerHue: {
+ ALOGD("[validatePictureParameter] validate colorTunerHue value");
+ int value = param.get<PictureParameter::Tag::colorTunerHue>();
+ EXPECT_GE(value, -50);
+ EXPECT_LE(value, 50);
+ break;
+ }
+ case PictureParameter::Tag::colorTunerRedOffset: {
+ ALOGD("[validatePictureParameter] validate colorTunerRedOffset value");
+ int value = param.get<PictureParameter::Tag::colorTunerRedOffset>();
+ validateParameterRange0To100(value);
+ break;
+ }
+ case PictureParameter::Tag::colorTunerGreenOffset: {
+ ALOGD("[validatePictureParameter] validate colorTunerGreenOffset value");
+ int value = param.get<PictureParameter::Tag::colorTunerGreenOffset>();
+ validateParameterRange0To100(value);
+ break;
+ }
+ case PictureParameter::Tag::colorTunerBlueOffset: {
+ ALOGD("[validatePictureParameter] validate colorTunerBlueOffset value");
+ int value = param.get<PictureParameter::Tag::colorTunerBlueOffset>();
+ validateParameterRange0To100(value);
+ break;
+ }
+ case PictureParameter::Tag::colorTunerRedGain: {
+ ALOGD("[validatePictureParameter] validate colorTunerRedGain value");
+ int value = param.get<PictureParameter::Tag::colorTunerRedGain>();
+ validateParameterRange0To100(value);
+ break;
+ }
+ case PictureParameter::Tag::colorTunerGreenGain: {
+ ALOGD("[validatePictureParameter] validate colorTunerGreenGain value");
+ int value = param.get<PictureParameter::Tag::colorTunerGreenGain>();
+ validateParameterRange0To100(value);
+ break;
+ }
+ case PictureParameter::Tag::colorTunerBlueGain: {
+ ALOGD("[validatePictureParameter] validate colorTunerBlueGain value");
+ int value = param.get<PictureParameter::Tag::colorTunerBlueGain>();
+ validateParameterRange0To100(value);
+ break;
+ }
+ case PictureParameter::Tag::panelInitMaxLuminceNits: {
+ ALOGD("[validatePictureParameter] validate panelInitMaxLuminceNits value");
+ int value = param.get<PictureParameter::Tag::panelInitMaxLuminceNits>();
+ EXPECT_GE(value, 0);
+ EXPECT_LE(value, 10000);
+ break;
+ }
+ case PictureParameter::Tag::colorTemperatureRedGain: {
+ ALOGD("[validatePictureParameter] validate colorTemperatureRedGain value");
+ int value = param.get<PictureParameter::Tag::colorTemperatureRedGain>();
+ validateColorTemperature(value);
+ break;
+ }
+ case PictureParameter::Tag::colorTemperatureGreenGain: {
+ ALOGD("[validatePictureParameter] validate colorTemperatureGreenGain value");
+ int value = param.get<PictureParameter::Tag::colorTemperatureGreenGain>();
+ validateColorTemperature(value);
+ break;
+ }
+ case PictureParameter::Tag::colorTemperatureBlueGain: {
+ ALOGD("[validatePictureParameter] validate colorTemperatureBlueGain value");
+ int value = param.get<PictureParameter::Tag::colorTemperatureBlueGain>();
+ validateColorTemperature(value);
+ break;
+ }
+ case PictureParameter::Tag::colorTemperatureRedOffset: {
+ ALOGD("[validatePictureParameter] validate ccolorTemperatureRedOffset value");
+ int value = param.get<PictureParameter::Tag::colorTemperatureRedOffset>();
+ validateColorTemperature(value);
+ break;
+ }
+ case PictureParameter::Tag::colorTemperatureGreenOffset: {
+ ALOGD("[validatePictureParameter] validate colorTemperatureGreenOffset value");
+ int value = param.get<PictureParameter::Tag::colorTemperatureGreenOffset>();
+ validateColorTemperature(value);
+ break;
+ }
+ case PictureParameter::Tag::colorTemperatureBlueOffset: {
+ ALOGD("[validatePictureParameter] validate colorTemperatureBlueOffset value");
+ int value = param.get<PictureParameter::Tag::colorTemperatureBlueOffset>();
+ validateColorTemperature(value);
+ break;
+ }
+ case PictureParameter::Tag::elevenPointRed: {
+ ALOGD("[validatePictureParameter] validate elevenPointRed value");
+ std::array<int, 11> elevenPointValues =
+ param.get<PictureParameter::Tag::elevenPointRed>();
+ for (int value : elevenPointValues) {
+ validateParameterRange0To100(value);
+ }
+ break;
+ }
+ case PictureParameter::Tag::elevenPointGreen: {
+ ALOGD("[validatePictureParameter] validate elevenPointGreen value");
+ std::array<int, 11> elevenPointValues =
+ param.get<PictureParameter::Tag::elevenPointGreen>();
+ for (int value : elevenPointValues) {
+ validateParameterRange0To100(value);
+ }
+ break;
+ }
+ case PictureParameter::Tag::elevenPointBlue: {
+ ALOGD("[validatePictureParameter] validate elevenPointBlue value");
+ std::array<int, 11> elevenPointValues =
+ param.get<PictureParameter::Tag::elevenPointBlue>();
+ for (int value : elevenPointValues) {
+ validateParameterRange0To100(value);
+ }
+ break;
+ }
+ case PictureParameter::Tag::osdRedGain: {
+ ALOGD("[validatePictureParameter] validate osdRedGain value");
+ int value = param.get<PictureParameter::Tag::osdRedGain>();
+ validateParameterRange0To2047(value);
+ break;
+ }
+ case PictureParameter::Tag::osdGreenGain: {
+ ALOGD("[validatePictureParameter] validate osdGreenGain value");
+ int value = param.get<PictureParameter::Tag::osdGreenGain>();
+ validateParameterRange0To2047(value);
+ break;
+ }
+ case PictureParameter::Tag::osdBlueGain: {
+ ALOGD("[validatePictureParameter] validate osdBlueGain value");
+ int value = param.get<PictureParameter::Tag::osdBlueGain>();
+ validateParameterRange0To2047(value);
+ break;
+ }
+ case PictureParameter::Tag::osdRedOffset: {
+ ALOGD("[validatePictureParameter] validate osdRedOffset value");
+ int value = param.get<PictureParameter::Tag::osdRedOffset>();
+ validateParameterRange0To2047(value);
+ break;
+ }
+ case PictureParameter::Tag::osdGreenOffset: {
+ ALOGD("[validatePictureParameter] validate osdGreenOffset value");
+ int value = param.get<PictureParameter::Tag::osdGreenOffset>();
+ validateParameterRange0To2047(value);
+ break;
+ }
+ case PictureParameter::Tag::osdBlueOffset: {
+ ALOGD("[validatePictureParameter] validate osdBlueOffset value");
+ int value = param.get<PictureParameter::Tag::osdBlueOffset>();
+ validateParameterRange0To2047(value);
+ break;
+ }
+ case PictureParameter::Tag::osdHue: {
+ ALOGD("[validatePictureParameter] validate osdHue value");
+ int value = param.get<PictureParameter::Tag::osdHue>();
+ validateParameterRange0To100(value);
+ break;
+ }
+ case PictureParameter::Tag::osdSaturation: {
+ ALOGD("[validatePictureParameter] validate osdSaturation value");
+ int value = param.get<PictureParameter::Tag::osdSaturation>();
+ EXPECT_GE(value, 0);
+ EXPECT_LE(value, 255);
+ break;
+ }
+ case PictureParameter::Tag::osdContrast: {
+ ALOGD("[validatePictureParameter] validate osdContrast value");
+ int value = param.get<PictureParameter::Tag::osdContrast>();
+ validateParameterRange0To2047(value);
+ break;
+ }
+ case PictureParameter::Tag::colorTunerHueRed: {
+ ALOGD("[validatePictureParameter] validate colorTunerHueRed value");
+ int value = param.get<PictureParameter::Tag::colorTunerHueRed>();
+ validateParameterRange0To100(value);
+ break;
+ }
+ case PictureParameter::Tag::colorTunerHueGreen: {
+ ALOGD("[validatePictureParameter] validate colorTunerHueGreen value");
+ int value = param.get<PictureParameter::Tag::colorTunerHueGreen>();
+ validateParameterRange0To100(value);
+ break;
+ }
+ case PictureParameter::Tag::colorTunerHueBlue: {
+ ALOGD("[validatePictureParameter] validate colorTunerHueBlue value");
+ int value = param.get<PictureParameter::Tag::colorTunerHueBlue>();
+ validateParameterRange0To100(value);
+ break;
+ }
+ case PictureParameter::Tag::colorTunerHueCyan: {
+ ALOGD("[validatePictureParameter] validate colorTunerHueCyan value");
+ int value = param.get<PictureParameter::Tag::colorTunerHueCyan>();
+ validateParameterRange0To100(value);
+ break;
+ }
+ case PictureParameter::Tag::colorTunerHueMagenta: {
+ ALOGD("[validatePictureParameter] validate colorTunerHueMagenta value");
+ int value = param.get<PictureParameter::Tag::colorTunerHueMagenta>();
+ validateParameterRange0To100(value);
+ break;
+ }
+ case PictureParameter::Tag::colorTunerHueYellow: {
+ ALOGD("[validatePictureParameter] validate colorTunerHueYellow value");
+ int value = param.get<PictureParameter::Tag::colorTunerHueYellow>();
+ validateParameterRange0To100(value);
+ break;
+ }
+ case PictureParameter::Tag::colorTunerHueFlesh: {
+ ALOGD("[validatePictureParameter] validate colorTunerHueFlesh value");
+ int value = param.get<PictureParameter::Tag::colorTunerHueFlesh>();
+ validateParameterRange0To100(value);
+ break;
+ }
+ case PictureParameter::Tag::colorTunerSaturationRed: {
+ ALOGD("[validatePictureParameter] validate colorTunerSaturationRed value");
+ int value = param.get<PictureParameter::Tag::colorTunerSaturationRed>();
+ validateParameterRange0To100(value);
+ break;
+ }
+ case PictureParameter::Tag::colorTunerSaturationGreen: {
+ ALOGD("[validatePictureParameter] validate colorTunerSaturationGreen value");
+ int value = param.get<PictureParameter::Tag::colorTunerSaturationGreen>();
+ validateParameterRange0To100(value);
+ break;
+ }
+ case PictureParameter::Tag::colorTunerSaturationBlue: {
+ ALOGD("[validatePictureParameter] validate colorTunerSaturationBlue value");
+ int value = param.get<PictureParameter::Tag::colorTunerSaturationBlue>();
+ validateParameterRange0To100(value);
+ break;
+ }
+ case PictureParameter::Tag::colorTunerSaturationCyan: {
+ ALOGD("[validatePictureParameter] validate colorTunerSaturationCyan value");
+ int value = param.get<PictureParameter::Tag::colorTunerSaturationCyan>();
+ validateParameterRange0To100(value);
+ break;
+ }
+ case PictureParameter::Tag::colorTunerSaturationMagenta: {
+ ALOGD("[validatePictureParameter] validate colorTunerSaturationMagenta value");
+ int value = param.get<PictureParameter::Tag::colorTunerSaturationMagenta>();
+ validateParameterRange0To100(value);
+ break;
+ }
+ case PictureParameter::Tag::colorTunerSaturationYellow: {
+ ALOGD("[validatePictureParameter] validate colorTunerSaturationYellow value");
+ int value = param.get<PictureParameter::Tag::colorTunerSaturationYellow>();
+ validateParameterRange0To100(value);
+ break;
+ }
+ case PictureParameter::Tag::colorTunerSaturationFlesh: {
+ ALOGD("[validatePictureParameter] validate colorTunerSaturationFlesh value");
+ int value = param.get<PictureParameter::Tag::colorTunerSaturationFlesh>();
+ validateParameterRange0To100(value);
+ break;
+ }
+ case PictureParameter::Tag::colorTunerLuminanceRed: {
+ ALOGD("[validatePictureParameter] validate colorTunerLuminanceRed value");
+ int value = param.get<PictureParameter::Tag::colorTunerLuminanceRed>();
+ validateParameterRange0To100(value);
+ break;
+ }
+ case PictureParameter::Tag::colorTunerLuminanceGreen: {
+ ALOGD("[validatePictureParameter] validate colorTunerLuminanceGreen value");
+ int value = param.get<PictureParameter::Tag::colorTunerLuminanceGreen>();
+ validateParameterRange0To100(value);
+ break;
+ }
+ case PictureParameter::Tag::colorTunerLuminanceBlue: {
+ ALOGD("[validatePictureParameter] validate colorTunerLuminanceBlue value");
+ int value = param.get<PictureParameter::Tag::colorTunerLuminanceBlue>();
+ validateParameterRange0To100(value);
+ break;
+ }
+ case PictureParameter::Tag::colorTunerLuminanceCyan: {
+ ALOGD("[validatePictureParameter] validate colorTunerLuminanceCyan value");
+ int value = param.get<PictureParameter::Tag::colorTunerLuminanceCyan>();
+ validateParameterRange0To100(value);
+ break;
+ }
+ case PictureParameter::Tag::colorTunerLuminanceMagenta: {
+ ALOGD("[validatePictureParameter] validate colorTunerLuminanceMagenta value");
+ int value = param.get<PictureParameter::Tag::colorTunerLuminanceMagenta>();
+ validateParameterRange0To100(value);
+ break;
+ }
+ case PictureParameter::Tag::colorTunerLuminanceYellow: {
+ ALOGD("[validatePictureParameter] validate colorTunerLuminanceYellow value");
+ int value = param.get<PictureParameter::Tag::colorTunerLuminanceYellow>();
+ validateParameterRange0To100(value);
+ break;
+ }
+ case PictureParameter::Tag::colorTunerLuminanceFlesh: {
+ ALOGD("[validatePictureParameter] validate colorTunerLuminanceFlesh value");
+ int value = param.get<PictureParameter::Tag::colorTunerLuminanceFlesh>();
+ validateParameterRange0To100(value);
+ break;
+ }
+ default:
+ ALOGD("Those parameters don't need to check.");
+ break;
+ }
+}
+
+void validateSoundParameter(const SoundParameter& param) {
+ switch (param.getTag()) {
+ case SoundParameter::Tag::balance: {
+ ALOGD("[validateSoundParameter] validate balance value");
+ int value = param.get<SoundParameter::Tag::balance>();
+ EXPECT_GE(value, -50);
+ EXPECT_LE(value, 50);
+ break;
+ }
+ case SoundParameter::Tag::bass: {
+ ALOGD("[validateSoundParameter] validate bass value");
+ int value = param.get<SoundParameter::Tag::bass>();
+ validateParameterRange0To100(value);
+ break;
+ }
+ case SoundParameter::Tag::treble: {
+ ALOGD("[validateSoundParameter] validate treble value");
+ int value = param.get<SoundParameter::Tag::treble>();
+ validateParameterRange0To100(value);
+ break;
+ }
+ case SoundParameter::Tag::speakersDelayMs: {
+ ALOGD("[validateSoundParameter] validate speakersDelayMs value");
+ int value = param.get<SoundParameter::Tag::speakersDelayMs>();
+ EXPECT_GE(value, 0);
+ EXPECT_LE(value, 250);
+ break;
+ }
+ case SoundParameter::Tag::digitalOutputDelayMs: {
+ ALOGD("[validateSoundParameter] validate digitalOutputDelayMs value");
+ int value = param.get<SoundParameter::Tag::digitalOutputDelayMs>();
+ EXPECT_GE(value, 0);
+ EXPECT_LE(value, 250);
+ break;
+ }
+ default:
+ ALOGD("Those parameters don't need to check.");
+ break;
+ }
+}
+
class MediaQualityCallback : public BnMediaQualityCallback {
public:
explicit MediaQualityCallback(
@@ -83,7 +485,11 @@
const std::function<void(const PictureProfile& pictureProfile)>&
on_hal_picture_profile_adjust)
: on_hal_picture_profile_adjust_(on_hal_picture_profile_adjust) {}
+
ScopedAStatus onPictureProfileAdjusted(const PictureProfile& pictureProfile) override {
+ for (const auto& param : pictureProfile.parameters.pictureParameters) {
+ validatePictureParameter(param);
+ }
on_hal_picture_profile_adjust_(pictureProfile);
return ScopedAStatus::ok();
}
@@ -111,7 +517,11 @@
const std::function<void(const SoundProfile& soundProfile)>&
on_hal_sound_profile_adjust)
: on_hal_sound_profile_adjust_(on_hal_sound_profile_adjust) {}
+
ScopedAStatus onSoundProfileAdjusted(const SoundProfile& soundProfile) override {
+ for (const auto& param : soundProfile.parameters.soundParameters) {
+ validateSoundParameter(param);
+ }
on_hal_sound_profile_adjust_(soundProfile);
return ScopedAStatus::ok();
}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ISupplicantStaIfaceCallback.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ISupplicantStaIfaceCallback.aidl
index 384ac9a..b0141df 100644
--- a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ISupplicantStaIfaceCallback.aidl
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ISupplicantStaIfaceCallback.aidl
@@ -84,8 +84,8 @@
oneway void onPmkSaCacheAdded(in android.hardware.wifi.supplicant.PmkSaCacheData pmkSaData);
oneway void onUsdPublishStarted(in int cmdId, in int publishId);
oneway void onUsdSubscribeStarted(in int cmdId, in int subscribeId);
- oneway void onUsdPublishConfigFailed(in int cmdId);
- oneway void onUsdSubscribeConfigFailed(in int cmdId);
+ oneway void onUsdPublishConfigFailed(in int cmdId, in android.hardware.wifi.supplicant.ISupplicantStaIfaceCallback.UsdConfigErrorCode errorCode);
+ oneway void onUsdSubscribeConfigFailed(in int cmdId, in android.hardware.wifi.supplicant.ISupplicantStaIfaceCallback.UsdConfigErrorCode errorCode);
oneway void onUsdPublishTerminated(in int publishId, in android.hardware.wifi.supplicant.UsdTerminateReasonCode reasonCode);
oneway void onUsdSubscribeTerminated(in int subscribeId, in android.hardware.wifi.supplicant.UsdTerminateReasonCode reasonCode);
oneway void onUsdPublishReplied(in android.hardware.wifi.supplicant.UsdServiceDiscoveryInfo info);
@@ -97,4 +97,10 @@
MULTI_LINK_RECONFIG_AP_REMOVAL = 1,
MULTI_LINK_DYNAMIC_RECONFIG = 2,
}
+ @Backing(type="int") @VintfStability
+ enum UsdConfigErrorCode {
+ FAILURE_UNKNOWN = 0,
+ FAILURE_TIMEOUT = 1,
+ FAILURE_NOT_AVAILABLE = 2,
+ }
}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicantStaIfaceCallback.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicantStaIfaceCallback.aidl
index 1ee873a..efbd066 100644
--- a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicantStaIfaceCallback.aidl
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicantStaIfaceCallback.aidl
@@ -439,12 +439,32 @@
void onUsdSubscribeStarted(in int cmdId, in int subscribeId);
/**
+ * Error codes returned by |onUsdPublishConfigFailed| and |onUsdSubscribeConfigFailed|.
+ */
+ @VintfStability
+ @Backing(type="int")
+ enum UsdConfigErrorCode {
+ /**
+ * Unknown failure.
+ */
+ FAILURE_UNKNOWN = 0,
+ /**
+ * The requested operation timed out.
+ */
+ FAILURE_TIMEOUT = 1,
+ /**
+ * The requested operation is currently not available.
+ */
+ FAILURE_NOT_AVAILABLE = 2,
+ }
+
+ /**
* Called in response to |ISupplicantStaIface.startUsdPublish| to indicate that the
* publish session could not be configured.
*
* @param cmdId Identifier for the original request.
*/
- void onUsdPublishConfigFailed(in int cmdId);
+ void onUsdPublishConfigFailed(in int cmdId, in UsdConfigErrorCode errorCode);
/**
* Called in response to |ISupplicantStaIface.startUsdSubscribe| to indicate that the
@@ -452,7 +472,7 @@
*
* @param cmdId Identifier for the original request.
*/
- void onUsdSubscribeConfigFailed(in int cmdId);
+ void onUsdSubscribeConfigFailed(in int cmdId, in UsdConfigErrorCode errorCode);
/**
* Called in response to |ISupplicantStaIface.cancelUsdPublish| to indicate that the session
diff --git a/wifi/supplicant/aidl/vts/functional/supplicant_sta_iface_aidl_test.cpp b/wifi/supplicant/aidl/vts/functional/supplicant_sta_iface_aidl_test.cpp
index da12a82..18b8ccb 100644
--- a/wifi/supplicant/aidl/vts/functional/supplicant_sta_iface_aidl_test.cpp
+++ b/wifi/supplicant/aidl/vts/functional/supplicant_sta_iface_aidl_test.cpp
@@ -254,10 +254,12 @@
int32_t /* subscribeId */) override {
return ndk::ScopedAStatus::ok();
}
- ::ndk::ScopedAStatus onUsdPublishConfigFailed(int32_t /* cmdId */) override {
+ ::ndk::ScopedAStatus onUsdPublishConfigFailed(int32_t /* cmdId */,
+ UsdConfigErrorCode /* errorCode */) override {
return ndk::ScopedAStatus::ok();
}
- ::ndk::ScopedAStatus onUsdSubscribeConfigFailed(int32_t /* cmdId */) override {
+ ::ndk::ScopedAStatus onUsdSubscribeConfigFailed(int32_t /* cmdId */,
+ UsdConfigErrorCode /* errorCode */) override {
return ndk::ScopedAStatus::ok();
}
::ndk::ScopedAStatus onUsdPublishTerminated(int32_t /* publishId */,