Add support for test mode enable/disable
Bug: 247124878
Test: manual test
Change-Id: Ia888bd4e20fd77793f044f056cd48288b9485c5a
diff --git a/host/hal_generic/common/multi_client_context_hub_base.cc b/host/hal_generic/common/multi_client_context_hub_base.cc
index f486c67..cd74c60 100644
--- a/host/hal_generic/common/multi_client_context_hub_base.cc
+++ b/host/hal_generic/common/multi_client_context_hub_base.cc
@@ -36,6 +36,8 @@
// timeout for calling getContextHubs(), which is synchronous
constexpr auto kHubInfoQueryTimeout = std::chrono::seconds(5);
+// timeout for enable/disable test mode, which is synchronous
+constexpr std::chrono::duration ktestModeTimeOut = std::chrono::seconds(5);
enum class HalErrorCode : int32_t {
OPERATION_FAILED = -1,
@@ -380,9 +382,58 @@
return ndk::ScopedAStatus::ok();
}
-ScopedAStatus MultiClientContextHubBase::setTestMode(bool /*enable*/) {
- // To be implemented.
- return ScopedAStatus::ok();
+ScopedAStatus MultiClientContextHubBase::setTestMode(bool enable) {
+ return fromResult(enable ? enableTestMode() : disableTestMode());
+}
+
+bool MultiClientContextHubBase::enableTestMode() {
+ std::unique_lock<std::mutex> lock(mTestModeMutex);
+ if (mIsTestModeEnabled) {
+ return true;
+ }
+ mTestModeNanoapps.reset();
+ if (!queryNanoapps(kDefaultHubId).isOk()) {
+ LOGE("Failed to get a list of loaded nanoapps.");
+ mTestModeNanoapps.emplace();
+ return false;
+ }
+ mEnableTestModeCv.wait_for(lock, ktestModeTimeOut,
+ [&]() { return mTestModeNanoapps.has_value(); });
+ for (const auto &appId : *mTestModeNanoapps) {
+ if (!unloadNanoapp(kDefaultHubId, appId, mTestModeTransactionId).isOk()) {
+ LOGE("Failed to unload nanoapp 0x%" PRIx64 " to enable the test mode.",
+ appId);
+ return false;
+ }
+ mTestModeSyncUnloadResult.reset();
+ mEnableTestModeCv.wait_for(lock, ktestModeTimeOut, [&]() {
+ return mTestModeSyncUnloadResult.has_value();
+ });
+ if (!*mTestModeSyncUnloadResult) {
+ LOGE("Failed to unload nanoapp 0x%" PRIx64 " to enable the test mode.",
+ appId);
+ return false;
+ }
+ }
+ mIsTestModeEnabled = true;
+ return true;
+}
+
+bool MultiClientContextHubBase::disableTestMode() {
+ std::unique_lock<std::mutex> lock(mTestModeMutex);
+ if (!mIsTestModeEnabled) {
+ return true;
+ }
+ if (mTestModeNanoapps.has_value() && !mTestModeNanoapps->empty()) {
+ if (!mPreloadedNanoappLoader->loadPreloadedNanoapps(*mTestModeNanoapps)) {
+ LOGE("Failed to reload the nanoapps to disable the test mode.");
+ return false;
+ }
+ }
+ mTestModeNanoapps.emplace();
+ mTestModeTransactionId = static_cast<int32_t>(kDefaultTestModeTransactionId);
+ mIsTestModeEnabled = false;
+ return true;
}
void MultiClientContextHubBase::handleMessageFromChre(
@@ -498,6 +549,17 @@
appInfo.rpcServices = rpcServices;
appInfoList.push_back(appInfo);
}
+ {
+ std::unique_lock<std::mutex> lock(mTestModeMutex);
+ if (!mTestModeNanoapps.has_value()) {
+ mTestModeNanoapps.emplace();
+ for (const auto &appInfo : appInfoList) {
+ mTestModeNanoapps->insert(appInfo.nanoappId);
+ }
+ mEnableTestModeCv.notify_all();
+ }
+ }
+
callback->handleNanoappInfo(appInfoList);
}
@@ -552,6 +614,14 @@
const fbs::UnloadNanoappResponseT &response, HalClientId clientId) {
if (mHalClientManager->resetPendingUnloadTransaction(
clientId, response.transaction_id)) {
+ {
+ std::unique_lock<std::mutex> lock(mTestModeMutex);
+ if (response.transaction_id == mTestModeTransactionId) {
+ mTestModeSyncUnloadResult.emplace(response.success);
+ mEnableTestModeCv.notify_all();
+ return;
+ }
+ }
if (auto callback = mHalClientManager->getCallback(clientId);
callback != nullptr) {
callback->handleTransactionResult(response.transaction_id,
diff --git a/host/hal_generic/common/multi_client_context_hub_base.h b/host/hal_generic/common/multi_client_context_hub_base.h
index fa15996..c5ac533 100644
--- a/host/hal_generic/common/multi_client_context_hub_base.h
+++ b/host/hal_generic/common/multi_client_context_hub_base.h
@@ -43,8 +43,6 @@
*
* A subclass should initiate mConnection, mHalClientManager and
* mPreloadedNanoappLoader in its constructor.
- *
- * TODO(b/247124878): setTestMode is not implemented yet.
*/
class MultiClientContextHubBase
: public BnContextHub,
@@ -102,6 +100,9 @@
this->clientPid = pid;
}
};
+
+ static constexpr uint32_t kDefaultTestModeTransactionId = 0x80000000;
+
MultiClientContextHubBase() = default;
bool sendFragmentedLoadRequest(HalClientId clientId,
@@ -122,6 +123,9 @@
const ::chre::fbs::DebugDumpResponseT & /* response */);
void handleClientDeath(pid_t pid);
+ bool enableTestMode();
+ bool disableTestMode();
+
inline bool isSettingEnabled(Setting setting) {
return mSettingEnabled.find(setting) != mSettingEnabled.end() &&
mSettingEnabled[setting];
@@ -154,6 +158,16 @@
std::mutex mPreloadedNanoappIdsMutex;
std::optional<std::vector<uint64_t>> mPreloadedNanoappIds{};
+ // test mode settings
+ std::mutex mTestModeMutex;
+ std::condition_variable mEnableTestModeCv;
+ bool mIsTestModeEnabled = false;
+ std::optional<bool> mTestModeSyncUnloadResult = std::nullopt;
+ std::optional<std::unordered_set<uint64_t>> mTestModeNanoapps =
+ std::unordered_set<uint64_t>{};
+ int32_t mTestModeTransactionId =
+ static_cast<int32_t>(kDefaultTestModeTransactionId);
+
EventLogger mEventLogger;
};
} // namespace android::hardware::contexthub::common::implementation