thermalservice: add HIDL ThermalCallback implementation

The IThermalCallback implementation in thermalserviced enables vendor
thermal management code to send thermal events to ThermalService.

Test: manual: marlin with modified thermal-engine.conf
Bug: 30982366
Change-Id: Ic566bc51aebcd03163f8909f846ee4f7025ed472
diff --git a/services/thermalservice/thermalserviced.cpp b/services/thermalservice/thermalserviced.cpp
index 281851d..b9315b8 100644
--- a/services/thermalservice/thermalserviced.cpp
+++ b/services/thermalservice/thermalserviced.cpp
@@ -19,21 +19,103 @@
 
 #include "thermalserviced.h"
 #include "ThermalService.h"
+#include "libthermalcallback/ThermalCallback.h"
 
+#include <android/hardware/thermal/1.1/IThermal.h>
 #include <binder/IPCThreadState.h>
 #include <binder/IServiceManager.h>
+#include <hidl/HidlTransportSupport.h>
 
 using namespace android;
+using ::android::hardware::thermal::V1_1::IThermal;
+using ::android::hardware::thermal::V1_0::Temperature;
+using ::android::hardware::thermal::V1_1::IThermalCallback;
+using ::android::hardware::thermal::V1_1::implementation::ThermalCallback;
+using ::android::hardware::configureRpcThreadpool;
+using ::android::hardware::hidl_death_recipient;
+using ::android::hidl::base::V1_0::IBase;
+using ::android::os::ThermalService;
+
+template<typename T>
+using Return = hardware::Return<T>;
+
+namespace {
+
+// Our thermalserviced main object
+ThermalServiceDaemon* gThermalServiceDaemon;
+
+// Thermal HAL client
+sp<IThermal> gThermalHal = nullptr;
+
+// Binder death notifier informing of Thermal HAL death.
+struct ThermalServiceDeathRecipient : hidl_death_recipient {
+    virtual void serviceDied(
+        uint64_t cookie __unused, const wp<IBase>& who __unused) {
+        gThermalHal = nullptr;
+        ALOGE("IThermal HAL died");
+        gThermalServiceDaemon->getThermalHal();
+    }
+};
+
+sp<ThermalServiceDeathRecipient> gThermalHalDied = nullptr;
+
+}  // anonymous namespace
 
 void ThermalServiceDaemon::thermalServiceStartup() {
     // Binder IThermalService startup
     mThermalService = new android::os::ThermalService;
     mThermalService->publish(mThermalService);
+    // Register IThermalService object with IThermalCallback
+    if (mThermalCallback != nullptr)
+        mThermalCallback->registerThermalService(mThermalService);
     IPCThreadState::self()->joinThreadPool();
 }
 
+// Lookup Thermal HAL, register death notifier, register our
+// ThermalCallback with the Thermal HAL.
+void ThermalServiceDaemon::getThermalHal() {
+    gThermalHal = IThermal::getService();
+    if (gThermalHal == nullptr) {
+        ALOGW("Unable to get Thermal HAL V1.1, vendor thermal event notification not available");
+        return;
+    }
+
+    // Binder death notifier for Thermal HAL
+    if (gThermalHalDied == nullptr)
+        gThermalHalDied = new ThermalServiceDeathRecipient();
+
+    if (gThermalHalDied != nullptr)
+        gThermalHal->linkToDeath(gThermalHalDied, 0x451F /* cookie */);
+
+    if (mThermalCallback != nullptr) {
+        Return<void> ret = gThermalHal->registerThermalCallback(
+            mThermalCallback);
+        if (!ret.isOk())
+            ALOGE("registerThermalCallback failed, status: %s",
+                  ret.description().c_str());
+    }
+}
+
+void ThermalServiceDaemon::thermalCallbackStartup() {
+    status_t err;
+
+    // HIDL IThermalCallback startup
+    // Need at least 2 threads in thread pool since we wait for dead HAL
+    // to come back on the binder death notification thread and we need
+    // another thread for the incoming service now available call.
+    configureRpcThreadpool(2, false /* callerWillJoin */);
+    mThermalCallback = new ThermalCallback();
+    err = mThermalCallback->registerAsService();
+    ALOGE_IF(err != OK, "Cannot register %s: %d",
+        IThermalCallback::descriptor, err);
+
+    // Lookup Thermal HAL and register our ThermalCallback.
+    getThermalHal();
+}
 
 int main(int /*argc*/, char** /*argv*/) {
-    ThermalServiceDaemon* daemon = new ThermalServiceDaemon();
-    daemon->thermalServiceStartup();
+    gThermalServiceDaemon = new ThermalServiceDaemon();
+    gThermalServiceDaemon->thermalCallbackStartup();
+    gThermalServiceDaemon->thermalServiceStartup();
+    /* NOTREACHED */
 }