Monitor crashes of audio hal service via linkToDeath

Hwbinder 'linkToDeath' mechanism is used to track abrupt
disappearance of server hal objects due to hal server crash.

Upon hal server crash, notifications can be sent to binder
clients if needed, then the audioserver crashes itself as the
current audio HAL design does not provide an easy way to restore
all the transient objects (devices, streams, effects) in their
pre-crash state.

Bug: 34158778
Test: In binderized mode, kill audio hal server
Change-Id: If9265711edc445984601fcb5c29d2c173a370762
diff --git a/services/radio/Android.mk b/services/radio/Android.mk
index 74f1fe0..1b50dc3 100644
--- a/services/radio/Android.mk
+++ b/services/radio/Android.mk
@@ -46,6 +46,7 @@
     libhidlbase \
     libhidltransport \
     libbase \
+    libaudiohal \
     android.hardware.broadcastradio@1.0
 endif
 
diff --git a/services/radio/RadioHalHidl.cpp b/services/radio/RadioHalHidl.cpp
index 34a6db7..032d3fd 100644
--- a/services/radio/RadioHalHidl.cpp
+++ b/services/radio/RadioHalHidl.cpp
@@ -17,6 +17,7 @@
 #define LOG_TAG "RadioHalHidl"
 //#define LOG_NDEBUG 0
 
+#include <media/audiohal/hidl/HalDeathHandler.h>
 #include <utils/Log.h>
 #include <utils/misc.h>
 #include <system/radio_metadata.h>
@@ -333,11 +334,27 @@
 RadioHalHidl::Tuner::Tuner(sp<TunerCallbackInterface> callback, sp<RadioHalHidl> module)
     : TunerInterface(), mHalTuner(NULL), mCallback(callback), mParentModule(module)
 {
+    // Make sure the handler we are passing in only deals with const members,
+    // as it can be called on an arbitrary thread.
+    const auto& self = this;
+    HalDeathHandler::getInstance()->registerAtExitHandler(
+            this, [&self]() { self->sendHwFailureEvent(); });
 }
 
 
 RadioHalHidl::Tuner::~Tuner()
 {
+    HalDeathHandler::getInstance()->unregisterAtExitHandler(this);
+}
+
+void RadioHalHidl::Tuner::setHalTuner(sp<ITuner>& halTuner) {
+    if (mHalTuner != 0) {
+        mHalTuner->unlinkToDeath(HalDeathHandler::getInstance());
+    }
+    mHalTuner = halTuner;
+    if (mHalTuner != 0) {
+        mHalTuner->linkToDeath(HalDeathHandler::getInstance(), 0 /*cookie*/);
+    }
 }
 
 void RadioHalHidl::Tuner::handleHwFailure()
@@ -347,14 +364,19 @@
     if (parentModule != 0) {
         parentModule->clearService();
     }
+    sendHwFailureEvent();
+    mHalTuner.clear();
+}
+
+void RadioHalHidl::Tuner::sendHwFailureEvent() const
+{
     radio_hal_event_t event;
     memset(&event, 0, sizeof(radio_hal_event_t));
     event.type = RADIO_EVENT_HW_FAILURE;
     onCallback(&event);
-    mHalTuner.clear();
 }
 
-void RadioHalHidl::Tuner::onCallback(radio_hal_event_t *halEvent)
+void RadioHalHidl::Tuner::onCallback(radio_hal_event_t *halEvent) const
 {
     if (mCallback != 0) {
         mCallback->onEvent(halEvent);
diff --git a/services/radio/RadioHalHidl.h b/services/radio/RadioHalHidl.h
index b60a95e..38e181a 100644
--- a/services/radio/RadioHalHidl.h
+++ b/services/radio/RadioHalHidl.h
@@ -78,17 +78,18 @@
             virtual Return<void> newMetadata(uint32_t channel, uint32_t subChannel,
                                          const ::android::hardware::hidl_vec<MetaData>& metadata);
 
-            void setHalTuner(sp<ITuner>& halTuner) { mHalTuner = halTuner; }
+            void setHalTuner(sp<ITuner>& halTuner);
             sp<ITuner> getHalTuner() { return mHalTuner; }
 
         private:
             virtual          ~Tuner();
 
-                    void     onCallback(radio_hal_event_t *halEvent);
+                    void     onCallback(radio_hal_event_t *halEvent) const;
                     void     handleHwFailure();
+                    void     sendHwFailureEvent() const;
 
             sp<ITuner> mHalTuner;
-            sp<TunerCallbackInterface>  mCallback;
+            const sp<TunerCallbackInterface> mCallback;
             wp<RadioHalHidl> mParentModule;
         };