Merge "contexthub: Handle service death" into oc-dev
diff --git a/contexthub/1.0/default/Contexthub.cpp b/contexthub/1.0/default/Contexthub.cpp
index 4a6b3f2..bf45900 100644
--- a/contexthub/1.0/default/Contexthub.cpp
+++ b/contexthub/1.0/default/Contexthub.cpp
@@ -38,6 +38,7 @@
 Contexthub::Contexthub()
         : mInitCheck(NO_INIT),
           mContextHubModule(nullptr),
+          mDeathRecipient(new DeathRecipient(this)),
           mIsTransactionPending(false) {
     const hw_module_t *module;
 
@@ -96,7 +97,7 @@
             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 Void();
 }
 
+Contexthub::DeathRecipient::DeathRecipient(sp<Contexthub> contexthub)
+        : mContexthub(contexthub) {}
+
+void Contexthub::DeathRecipient::serviceDied(
+        uint64_t cookie,
+        const wp<::android::hidl::base::V1_0::IBase>& /*who*/) {
+    uint32_t hubId = static_cast<uint32_t>(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 @@
     if (!isValidHubId(hubId)) {
         return nullptr;
     } else {
-        return mCachedHubInfo[hubId].callBack;
+        return mCachedHubInfo[hubId].callback;
     }
 }
 
@@ -193,8 +204,22 @@
                                                      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<bool> linkResult = cb->linkToDeath(mDeathRecipient, hubId);
+            bool linkSuccess = linkResult.isOk() ?
+                static_cast<bool>(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 @@
       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 236e079..db23ec2 100644
--- a/contexthub/1.0/default/Contexthub.h
+++ b/contexthub/1.0/default/Contexthub.h
@@ -65,14 +65,26 @@
 
     struct CachedHubInformation{
         struct hub_app_name_t osAppName;
-        sp<IContexthubCallback> callBack;
+        sp<IContexthubCallback> callback;
+    };
+
+    class DeathRecipient : public hidl_death_recipient {
+    public:
+        DeathRecipient(const sp<Contexthub> contexthub);
+
+        void serviceDied(
+                uint64_t cookie,
+                const wp<::android::hidl::base::V1_0::IBase>& who) override;
+
+    private:
+        sp<Contexthub> mContexthub;
     };
 
     status_t mInitCheck;
     const struct context_hub_module_t *mContextHubModule;
     std::unordered_map<uint32_t, CachedHubInformation> mCachedHubInfo;
 
-    sp<IContexthubCallback> mCb;
+    sp<DeathRecipient> mDeathRecipient;
     bool mIsTransactionPending;
     uint32_t mTransactionId;
 
@@ -85,6 +97,9 @@
                         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);