camera: Destroy HDR+ client for thermal throttling

After receiving thermal throttling from EaselManagerClient, disable
HDR+ client when HAL receives a request and there is no pending HDR+
request.

Test: Camera CTS
Bug: 119872767
Change-Id: I1b14ad055c423a33b1c919b4548f641722439d2f
diff --git a/msm8998/QCamera2/HAL3/QCamera3HWI.cpp b/msm8998/QCamera2/HAL3/QCamera3HWI.cpp
index ed11ff6..5a7e3e0 100644
--- a/msm8998/QCamera2/HAL3/QCamera3HWI.cpp
+++ b/msm8998/QCamera2/HAL3/QCamera3HWI.cpp
@@ -672,13 +672,7 @@
     {
         std::unique_lock<std::mutex> l(gHdrPlusClientLock);
         finishHdrPlusClientOpeningLocked(l);
-        if (gHdrPlusClient != nullptr) {
-            // Disable HDR+ mode.
-            disableHdrPlusModeLocked();
-            // Disconnect Easel if it's connected.
-            gEaselManagerClient->closeHdrPlusClient(std::move(gHdrPlusClient));
-            gHdrPlusClient = nullptr;
-        }
+        closeHdrPlusClientLocked();
     }
 
     // unlink of dualcam during close camera
@@ -5300,6 +5294,18 @@
     bool isVidBufRequested = false;
     camera3_stream_buffer_t *pInputBuffer = NULL;
 
+    // If Easel is thermal throttled and there is no pending HDR+ request,
+    // close HDR+ client.
+    {
+        std::unique_lock<std::mutex> l(gHdrPlusClientLock);
+        if (gHdrPlusClient != nullptr && mEaselThermalThrottled) {
+            Mutex::Autolock lock(mHdrPlusPendingRequestsLock);
+            if (mHdrPlusPendingRequests.empty()) {
+                closeHdrPlusClientLocked();
+            }
+        }
+    }
+
     pthread_mutex_lock(&mMutex);
 
     // Validate current state
@@ -16144,6 +16150,25 @@
     handleEaselFatalErrorAsync();
 }
 
+void QCamera3HardwareInterface::closeHdrPlusClientLocked()
+{
+    if (gHdrPlusClient != nullptr) {
+        // Disable HDR+ mode.
+        disableHdrPlusModeLocked();
+        // Disconnect Easel if it's connected.
+        gEaselManagerClient->closeHdrPlusClient(std::move(gHdrPlusClient));
+        gHdrPlusClient = nullptr;
+        ALOGD("HDR+ client closed.");
+    }
+}
+
+void QCamera3HardwareInterface::onThermalThrottle() {
+    ALOGW("%s: Thermal throttling. Will close HDR+ client.", __FUNCTION__);
+    // HDR+ will be disabled when HAL receives the next request and there is no
+    // pending HDR+ request.
+    mEaselThermalThrottled = true;
+}
+
 void QCamera3HardwareInterface::onOpened(std::unique_ptr<HdrPlusClient> client)
 {
     int rc = NO_ERROR;
diff --git a/msm8998/QCamera2/HAL3/QCamera3HWI.h b/msm8998/QCamera2/HAL3/QCamera3HWI.h
index 03e9a12..1dddf3a 100644
--- a/msm8998/QCamera2/HAL3/QCamera3HWI.h
+++ b/msm8998/QCamera2/HAL3/QCamera3HWI.h
@@ -894,8 +894,12 @@
     // Handle Easel error.
     void handleEaselFatalError();
 
+    // Close HDR+ client. Must be protected by gHdrPlusClientLock.
+    void closeHdrPlusClientLocked();
+
     // Easel manager client callbacks.
     void onEaselFatalError(std::string errMsg);
+    void onThermalThrottle();
 
     // Clean up and wait for Easel error future.
     void cleanupEaselErrorFuture();
@@ -946,6 +950,9 @@
     std::mutex mEaselErrorFutureLock;
     std::future<void> mEaselErrorFuture;
 
+    // If HDR+ should be thermal throttled.
+    std::atomic<bool> mEaselThermalThrottled = false;
+
     // Thread to handle callbacks from HDR+ client. Protected by gHdrPlusClientLock.
     sp<QCamera3HdrPlusListenerThread> mQCamera3HdrPlusListenerThread;