Add (un)linkToDeath to IBase.

With corresponding callback interfaces. hidl_death_recipient
is a transport-independent interface, used directly by clients
and servers. hidl_binder_death_recipient wraps a hidl_death_recipient
object and implements the Binder-specific death recipient. It
holds a weak reference to the callback interface, as well as the
interface it was called on (so we can include that in the callback).

Bug: 31632518
Test: mma, hidl_test
Change-Id: I0430efff24c2bfd3993438c6ed3fe007d9f9e3ef
diff --git a/base/include/hidl/HidlSupport.h b/base/include/hidl/HidlSupport.h
index 844ef40..1a4fd3c 100644
--- a/base/include/hidl/HidlSupport.h
+++ b/base/include/hidl/HidlSupport.h
@@ -38,7 +38,8 @@
 
 namespace android {
 
-// this file is included by all hidl interface, so we must forward declare the IMemory type.
+// this file is included by all hidl interface, so we must forward declare the
+// IMemory and IBase types.
 namespace hidl {
 namespace memory {
 namespace V1_0 {
@@ -47,8 +48,23 @@
 }; // namespace manager
 }; // namespace hidl
 
+namespace hidl {
+namespace base {
+namespace V1_0 {
+    struct IBase;
+}; // namespace V1_0
+}; // namespace base
+}; // namespace hidl
+
 namespace hardware {
 
+// hidl_death_recipient is a callback interfaced that can be used with
+// linkToDeath() / unlinkToDeath()
+struct hidl_death_recipient : public virtual RefBase {
+    virtual void serviceDied(uint64_t cookie,
+            const ::android::wp<::android::hidl::base::V1_0::IBase>& who) = 0;
+};
+
 // hidl_handle wraps a pointer to a native_handle_t in a hidl_pointer,
 // so that it can safely be transferred between 32-bit and 64-bit processes.
 struct hidl_handle {
diff --git a/transport/base/1.0/IBase.hal b/transport/base/1.0/IBase.hal
index 379213a..d696249 100644
--- a/transport/base/1.0/IBase.hal
+++ b/transport/base/1.0/IBase.hal
@@ -54,4 +54,21 @@
      * tags).
      */
     oneway notifySyspropsChanged();
+
+    /*
+     * Registers a death recipient, to be called when the process hosting this
+     * interface dies.
+     *
+     * @param recipient a hidl_death_recipient callback object
+     * @param cookie a cookie that must be returned with the callback
+     * @return success whether the death recipient was registered successfully.
+     */
+    linkToDeath(death_recipient recipient, uint64_t cookie) generates (bool success);
+
+    /*
+     * Unregisters a previously registered death recipient.
+     * @param recipient a previously registered hidl_death_recipient callback
+     * @return success whether the death recipient was unregistered successfully.
+     */
+    unlinkToDeath(death_recipient recipient) generates (bool success);
 };
diff --git a/transport/include/hidl/HidlBinderSupport.h b/transport/include/hidl/HidlBinderSupport.h
index 38ff6c9..13b67fd 100644
--- a/transport/include/hidl/HidlBinderSupport.h
+++ b/transport/include/hidl/HidlBinderSupport.h
@@ -17,6 +17,7 @@
 #ifndef ANDROID_HIDL_BINDER_SUPPORT_H
 #define ANDROID_HIDL_BINDER_SUPPORT_H
 
+#include <android/hidl/base/1.0/IBase.h>
 #include <hidl/HidlSupport.h>
 #include <hidl/HidlTransportUtils.h>
 #include <hidl/MQDescriptor.h>
@@ -30,6 +31,29 @@
 namespace android {
 namespace hardware {
 
+// hidl_binder_death_recipient wraps a transport-independent
+// hidl_death_recipient, and implements the binder-specific
+// DeathRecipient interface.
+struct hidl_binder_death_recipient : IBinder::DeathRecipient {
+    hidl_binder_death_recipient(const sp<hidl_death_recipient> &recipient,
+            uint64_t cookie, const sp<::android::hidl::base::V1_0::IBase> &base) :
+        mRecipient(recipient), mCookie(cookie), mBase(base) {
+    }
+    virtual void binderDied(const wp<IBinder>& /*who*/) {
+        sp<hidl_death_recipient> recipient = mRecipient.promote();
+        if (recipient != nullptr) {
+            recipient->serviceDied(mCookie, mBase);
+        }
+    }
+    wp<hidl_death_recipient> getRecipient() {
+        return mRecipient;
+    }
+private:
+    wp<hidl_death_recipient> mRecipient;
+    uint64_t mCookie;
+    wp<::android::hidl::base::V1_0::IBase> mBase;
+};
+
 // ---------------------- hidl_memory
 
 status_t readEmbeddedFromParcel(hidl_memory *memory,