From 154b0883f920d75161f1100ed054718392e166c6 Mon Sep 17 00:00:00 2001 From: Brian Duddie Date: Thu, 1 Jun 2017 18:51:22 -0700 Subject: [PATCH] contexthub: Handle service death Register for notification of service death for callbacks registered with the context hub HAL. Upon this notification, unregister the callback to avoid crashing if an event occurs prior to the service coming back up. Bug: 36202367 Test: adb shell stop, confirm death notification received via log; vts-tradefed run commandAndExit vts --module VtsHalContexthubV1_0Target Change-Id: I3c25229806cb9f2a116007939c752841edbf0985 --- contexthub/1.0/default/Contexthub.cpp | 41 +++++++++++++++++++++++++-- contexthub/1.0/default/Contexthub.h | 19 +++++++++++-- 2 files changed, 55 insertions(+), 5 deletions(-) diff --git a/contexthub/1.0/default/Contexthub.cpp b/contexthub/1.0/default/Contexthub.cpp index 4a6b3f278b..bf459005b4 100644 --- a/contexthub/1.0/default/Contexthub.cpp +++ b/contexthub/1.0/default/Contexthub.cpp @@ -38,6 +38,7 @@ static constexpr uint64_t ALL_APPS = UINT64_C(0xFFFFFFFFFFFFFFFF); Contexthub::Contexthub() : mInitCheck(NO_INIT), mContextHubModule(nullptr), + mDeathRecipient(new DeathRecipient(this)), mIsTransactionPending(false) { const hw_module_t *module; @@ -96,7 +97,7 @@ Return Contexthub::getHubs(getHubs_cb _hidl_cb) { c.stoppedPowerDrawMw = hubArray[i].stopped_power_draw_mw; c.sleepPowerDrawMw = hubArray[i].sleep_power_draw_mw; - info.callBack = nullptr; + info.callback = nullptr; info.osAppName = hubArray[i].os_app_name; mCachedHubInfo[hubArray[i].hub_id] = info; @@ -110,6 +111,16 @@ Return Contexthub::getHubs(getHubs_cb _hidl_cb) { return Void(); } +Contexthub::DeathRecipient::DeathRecipient(sp contexthub) + : mContexthub(contexthub) {} + +void Contexthub::DeathRecipient::serviceDied( + uint64_t cookie, + const wp<::android::hidl::base::V1_0::IBase>& /*who*/) { + uint32_t hubId = static_cast(cookie); + mContexthub->handleServiceDeath(hubId); +} + bool Contexthub::isValidHubId(uint32_t hubId) { if (!mCachedHubInfo.count(hubId)) { ALOGW("Hub information not found for hubId %" PRIu32, hubId); @@ -123,7 +134,7 @@ sp Contexthub::getCallBackForHubId(uint32_t hubId) { if (!isValidHubId(hubId)) { return nullptr; } else { - return mCachedHubInfo[hubId].callBack; + return mCachedHubInfo[hubId].callback; } } @@ -193,8 +204,22 @@ Return Contexthub::registerCallback(uint32_t hubId, contextHubCb, this) == 0) { // Initialized && valid hub && subscription successful + if (mCachedHubInfo[hubId].callback != nullptr) { + ALOGD("Modifying callback for hubId %" PRIu32, hubId); + mCachedHubInfo[hubId].callback->unlinkToDeath(mDeathRecipient); + } + + mCachedHubInfo[hubId].callback = cb; + if (cb != nullptr) { + Return linkResult = cb->linkToDeath(mDeathRecipient, hubId); + bool linkSuccess = linkResult.isOk() ? + static_cast(linkResult) : false; + if (!linkSuccess) { + ALOGW("Couldn't link death recipient for hubId %" PRIu32, + hubId); + } + } retVal = Result::OK; - mCachedHubInfo[hubId].callBack = cb; } else { // Initalized && valid hubId - but subscription unsuccessful // This is likely an internal error in the HAL implementation, but we @@ -309,6 +334,16 @@ int Contexthub::handleOsMessage(sp cb, return retVal; } +void Contexthub::handleServiceDeath(uint32_t hubId) { + ALOGI("Callback/service died for hubId %" PRIu32, hubId); + int ret = mContextHubModule->subscribe_messages(hubId, nullptr, nullptr); + if (ret != 0) { + ALOGW("Failed to unregister callback from hubId %" PRIu32 ": %d", + hubId, ret); + } + mCachedHubInfo[hubId].callback.clear(); +} + int Contexthub::contextHubCb(uint32_t hubId, const struct hub_message_t *rxMsg, void *cookie) { diff --git a/contexthub/1.0/default/Contexthub.h b/contexthub/1.0/default/Contexthub.h index 236e0798f2..db23ec2e63 100644 --- a/contexthub/1.0/default/Contexthub.h +++ b/contexthub/1.0/default/Contexthub.h @@ -65,14 +65,26 @@ private: struct CachedHubInformation{ struct hub_app_name_t osAppName; - sp callBack; + sp callback; + }; + + class DeathRecipient : public hidl_death_recipient { + public: + DeathRecipient(const sp contexthub); + + void serviceDied( + uint64_t cookie, + const wp<::android::hidl::base::V1_0::IBase>& who) override; + + private: + sp mContexthub; }; status_t mInitCheck; const struct context_hub_module_t *mContextHubModule; std::unordered_map mCachedHubInfo; - sp mCb; + sp mDeathRecipient; bool mIsTransactionPending; uint32_t mTransactionId; @@ -85,6 +97,9 @@ private: const uint8_t *msg, int msgLen); + // Handle the case where the callback registered for the given hub ID dies + void handleServiceDeath(uint32_t hubId); + static int contextHubCb(uint32_t hubId, const struct hub_message_t *rxMsg, void *cookie);