Add disable/enable camera service watchdog feature

- Allows the camera service watchdog to be enabled and disabled
- Usage: adb shell cmd media.camera set-cameraservice-watchdog [0/1]

Test: Manual
Bug: 62296107
Change-Id: I528ca819cc2be03006c77e869adf8f5fa99128d6
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index c576162..0118a12 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -1883,6 +1883,9 @@
             }
         }
 
+        // Enable/disable camera service watchdog
+        client->setCameraServiceWatchdog(mCameraServiceWatchdogEnabled);
+
         // Set rotate-and-crop override behavior
         if (mOverrideRotateAndCropMode != ANDROID_SCALER_ROTATE_AND_CROP_AUTO) {
             client->setRotateAndCropOverride(mOverrideRotateAndCropMode);
@@ -4802,6 +4805,8 @@
         return handleSetCameraMute(args);
     } else if (args.size() >= 2 && args[0] == String16("watch")) {
         return handleWatchCommand(args, in, out);
+    } else if (args.size() >= 2 && args[0] == String16("set-watchdog")) {
+        return handleSetCameraServiceWatchdog(args);
     } else if (args.size() == 1 && args[0] == String16("help")) {
         printHelp(out);
         return OK;
@@ -4895,6 +4900,28 @@
     return OK;
 }
 
+status_t CameraService::handleSetCameraServiceWatchdog(const Vector<String16>& args) {
+    int enableWatchdog = atoi(String8(args[1]));
+
+    if (enableWatchdog < 0 || enableWatchdog > 1) return BAD_VALUE;
+
+    Mutex::Autolock lock(mServiceLock);
+
+    mCameraServiceWatchdogEnabled = enableWatchdog;
+
+    const auto clients = mActiveClientManager.getAll();
+    for (auto& current : clients) {
+        if (current != nullptr) {
+            const auto basicClient = current->getValue();
+            if (basicClient.get() != nullptr) {
+                basicClient->setCameraServiceWatchdog(enableWatchdog);
+            }
+        }
+    }
+
+    return OK;
+}
+
 status_t CameraService::handleGetRotateAndCrop(int out) {
     Mutex::Autolock lock(mServiceLock);
 
diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h
index 6346f50..e0190e2 100644
--- a/services/camera/libcameraservice/CameraService.h
+++ b/services/camera/libcameraservice/CameraService.h
@@ -338,6 +338,9 @@
         // Set/reset camera mute
         virtual status_t setCameraMute(bool enabled) = 0;
 
+        // Set Camera service watchdog
+        virtual status_t setCameraServiceWatchdog(bool enabled) = 0;
+
         // The injection camera session to replace the internal camera
         // session.
         virtual status_t injectCamera(const String8& injectedCamId,
@@ -1190,6 +1193,9 @@
     // Handle 'watch' command as passed through 'cmd'
     status_t handleWatchCommand(const Vector<String16> &args, int inFd, int outFd);
 
+    // Set the camera service watchdog
+    status_t handleSetCameraServiceWatchdog(const Vector<String16>& args);
+
     // Enable tag monitoring of the given tags in provided clients
     status_t startWatchingTags(const Vector<String16> &args, int outFd);
 
@@ -1275,6 +1281,9 @@
     // Current camera mute mode
     bool mOverrideCameraMuteMode = false;
 
+    // Camera Service watchdog flag
+    bool mCameraServiceWatchdogEnabled = true;
+
     /**
      * A listener class that implements the IBinder::DeathRecipient interface
      * for use to call back the error state injected by the external camera, and
diff --git a/services/camera/libcameraservice/CameraServiceWatchdog.cpp b/services/camera/libcameraservice/CameraServiceWatchdog.cpp
index fcd6ebe..950da6a 100644
--- a/services/camera/libcameraservice/CameraServiceWatchdog.cpp
+++ b/services/camera/libcameraservice/CameraServiceWatchdog.cpp
@@ -64,6 +64,17 @@
     }
 }
 
+void CameraServiceWatchdog::setEnabled(bool enable)
+{
+    AutoMutex _l(mEnabledLock);
+
+    if (enable) {
+        mEnabled = true;
+    } else {
+        mEnabled = false;
+    }
+}
+
 void CameraServiceWatchdog::stop(uint32_t tid)
 {
     AutoMutex _l(mWatchdogLock);
diff --git a/services/camera/libcameraservice/CameraServiceWatchdog.h b/services/camera/libcameraservice/CameraServiceWatchdog.h
index f4955e2..f7c90a9 100644
--- a/services/camera/libcameraservice/CameraServiceWatchdog.h
+++ b/services/camera/libcameraservice/CameraServiceWatchdog.h
@@ -21,10 +21,12 @@
  * expected duration has exceeded.
  * Notes on multi-threaded behaviors:
  *    - The threadloop is blocked/paused when there are no calls being
- *   monitored.
+ *   monitored (when the TID cycle to counter map is empty).
  *   - The start and stop functions handle simultaneous call monitoring
  *   and single call monitoring differently. See function documentation for
  *   more details.
+ * To disable/enable:
+ *   - adb shell cmd media.camera set-cameraservice-watchdog [0/1]
  */
 
 #include <chrono>
@@ -49,15 +51,19 @@
 
 public:
     explicit CameraServiceWatchdog() : mPause(true), mMaxCycles(kMaxCycles),
-            mCycleLengthMs(kCycleLengthMs) {};
+            mCycleLengthMs(kCycleLengthMs), mEnabled(true) {};
 
-    explicit CameraServiceWatchdog (size_t maxCycles, uint32_t cycleLengthMs) :
-            mPause(true), mMaxCycles(maxCycles), mCycleLengthMs(cycleLengthMs) {};
+    explicit CameraServiceWatchdog (size_t maxCycles, uint32_t cycleLengthMs, bool enabled) :
+            mPause(true), mMaxCycles(maxCycles), mCycleLengthMs(cycleLengthMs), mEnabled(enabled)
+                    {};
 
     virtual ~CameraServiceWatchdog() {};
 
     virtual void requestExit();
 
+    /** Enables/disables the watchdog */
+    void setEnabled(bool enable);
+
     /** Used to wrap monitored calls in start and stop functions using custom timer values */
     template<typename T>
     auto watchThread(T func, uint32_t tid, uint32_t cycles, uint32_t cycleLength) {
@@ -66,8 +72,13 @@
         if (cycles != mMaxCycles || cycleLength != mCycleLengthMs) {
             // Create another instance of the watchdog to prevent disruption
             // of timer for current monitored calls
+
+            // Lock for mEnabled
+            mEnabledLock.lock();
             sp<CameraServiceWatchdog> tempWatchdog =
-                    new CameraServiceWatchdog(cycles, cycleLength);
+                    new CameraServiceWatchdog(cycles, cycleLength, mEnabled);
+            mEnabledLock.unlock();
+
             tempWatchdog->run("CameraServiceWatchdog");
             res = tempWatchdog->watchThread(func, tid);
             tempWatchdog->requestExit();
@@ -84,11 +95,17 @@
     /** Used to wrap monitored calls in start and stop functions using class timer values */
     template<typename T>
     auto watchThread(T func, uint32_t tid) {
+        AutoMutex _l(mEnabledLock);
+
         auto res = NULL;
 
-        start(tid);
-        res = func();
-        stop(tid);
+        if (mEnabled) {
+            start(tid);
+            res = func();
+            stop(tid);
+        } else {
+            res = func();
+        }
 
         return res;
     }
@@ -109,11 +126,13 @@
 
     virtual bool    threadLoop();
 
-    Mutex           mWatchdogLock;        // Lock for condition variable
-    Condition       mWatchdogCondition;   // Condition variable for stop/start
-    bool            mPause;               // True if thread is currently paused
-    uint32_t        mMaxCycles;           // Max cycles
-    uint32_t        mCycleLengthMs;       // Length of time elapsed per cycle
+    Mutex           mWatchdogLock;      // Lock for condition variable
+    Mutex           mEnabledLock;       // Lock for enabled status
+    Condition       mWatchdogCondition; // Condition variable for stop/start
+    bool            mPause;             // True if tid map is empty
+    uint32_t        mMaxCycles;         // Max cycles
+    uint32_t        mCycleLengthMs;     // Length of time elapsed per cycle
+    bool            mEnabled;           // True if watchdog is enabled
 
     std::unordered_map<uint32_t, uint32_t> tidToCycleCounterMap; // Thread Id to cycle counter map
 };
diff --git a/services/camera/libcameraservice/api1/Camera2Client.cpp b/services/camera/libcameraservice/api1/Camera2Client.cpp
index 5fcd43e..f8589c7 100644
--- a/services/camera/libcameraservice/api1/Camera2Client.cpp
+++ b/services/camera/libcameraservice/api1/Camera2Client.cpp
@@ -2294,6 +2294,10 @@
     return INVALID_OPERATION;
 }
 
+status_t Camera2Client::setCameraServiceWatchdog(bool enabled) {
+    return mDevice->setCameraServiceWatchdog(enabled);
+}
+
 status_t Camera2Client::setRotateAndCropOverride(uint8_t rotateAndCrop) {
     if (rotateAndCrop > ANDROID_SCALER_ROTATE_AND_CROP_AUTO) return BAD_VALUE;
 
diff --git a/services/camera/libcameraservice/api1/Camera2Client.h b/services/camera/libcameraservice/api1/Camera2Client.h
index 64ab8ff..0e72553 100644
--- a/services/camera/libcameraservice/api1/Camera2Client.h
+++ b/services/camera/libcameraservice/api1/Camera2Client.h
@@ -90,6 +90,8 @@
     virtual bool            supportsCameraMute();
     virtual status_t        setCameraMute(bool enabled);
 
+    virtual status_t        setCameraServiceWatchdog(bool enabled);
+
     /**
      * Interface used by CameraService
      */
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
index 701206a..3b7f33b 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
@@ -1718,6 +1718,10 @@
     return binder::Status::ok();
 }
 
+status_t CameraDeviceClient::setCameraServiceWatchdog(bool enabled) {
+    return mDevice->setCameraServiceWatchdog(enabled);
+}
+
 status_t CameraDeviceClient::setRotateAndCropOverride(uint8_t rotateAndCrop) {
     if (rotateAndCrop > ANDROID_SCALER_ROTATE_AND_CROP_AUTO) return BAD_VALUE;
 
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.h b/services/camera/libcameraservice/api2/CameraDeviceClient.h
index 9d1deb1..df1aa32 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.h
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.h
@@ -206,6 +206,8 @@
     virtual status_t      stopWatchingTags(int out);
     virtual status_t      dumpWatchedEventsToVector(std::vector<std::string> &out);
 
+    virtual status_t      setCameraServiceWatchdog(bool enabled);
+
     /**
      * Device listener interface
      */
diff --git a/services/camera/libcameraservice/api2/CameraOfflineSessionClient.cpp b/services/camera/libcameraservice/api2/CameraOfflineSessionClient.cpp
index 9303fd2..beb655b 100644
--- a/services/camera/libcameraservice/api2/CameraOfflineSessionClient.cpp
+++ b/services/camera/libcameraservice/api2/CameraOfflineSessionClient.cpp
@@ -66,6 +66,10 @@
     return OK;
 }
 
+status_t CameraOfflineSessionClient::setCameraServiceWatchdog(bool) {
+    return OK;
+}
+
 status_t CameraOfflineSessionClient::setRotateAndCropOverride(uint8_t /*rotateAndCrop*/) {
     // Since we're not submitting more capture requests, changes to rotateAndCrop override
     // make no difference.
diff --git a/services/camera/libcameraservice/api2/CameraOfflineSessionClient.h b/services/camera/libcameraservice/api2/CameraOfflineSessionClient.h
index f2c42d8..9ea1093 100644
--- a/services/camera/libcameraservice/api2/CameraOfflineSessionClient.h
+++ b/services/camera/libcameraservice/api2/CameraOfflineSessionClient.h
@@ -84,6 +84,8 @@
     bool supportsCameraMute() override;
     status_t setCameraMute(bool enabled) override;
 
+    status_t setCameraServiceWatchdog(bool enabled) override;
+
     // permissions management
     status_t startCameraOps() override;
     status_t finishCameraOps() override;
diff --git a/services/camera/libcameraservice/common/CameraDeviceBase.h b/services/camera/libcameraservice/common/CameraDeviceBase.h
index 05edd6a..ca3b019 100644
--- a/services/camera/libcameraservice/common/CameraDeviceBase.h
+++ b/services/camera/libcameraservice/common/CameraDeviceBase.h
@@ -443,6 +443,11 @@
     virtual status_t setCameraMute(bool enabled) = 0;
 
     /**
+     * Enable/disable camera service watchdog
+     */
+    virtual status_t setCameraServiceWatchdog(bool enabled) = 0;
+
+    /**
      * Get the status tracker of the camera device
      */
     virtual wp<camera3::StatusTracker> getStatusTracker() = 0;
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index f5c6d6f..07055ec 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -115,10 +115,6 @@
 
 status_t Camera3Device::initializeCommonLocked() {
 
-    /** Start watchdog thread */
-    mCameraServiceWatchdog = new CameraServiceWatchdog();
-    mCameraServiceWatchdog->run("CameraServiceWatchdog");
-
     /** Start up status tracker thread */
     mStatusTracker = new StatusTracker(this);
     status_t res = mStatusTracker->run(String8::format("C3Dev-%s-Status", mId.string()).string());
@@ -232,6 +228,10 @@
     // Hidl/AidlCamera3DeviceInjectionMethods
     mInjectionMethods = createCamera3DeviceInjectionMethods(this);
 
+    /** Start watchdog thread */
+    mCameraServiceWatchdog = new CameraServiceWatchdog();
+    mCameraServiceWatchdog->run("CameraServiceWatchdog");
+
     return OK;
 }
 
@@ -4083,6 +4083,17 @@
     }
 }
 
+status_t Camera3Device::setCameraServiceWatchdog(bool enabled) {
+    Mutex::Autolock il(mInterfaceLock);
+    Mutex::Autolock l(mLock);
+
+    if (mCameraServiceWatchdog != NULL) {
+        mCameraServiceWatchdog->setEnabled(enabled);
+    }
+
+    return OK;
+}
+
 void Camera3Device::RequestThread::cleanUpFailedRequests(bool sendRequestError) {
     if (mNextRequests.empty()) {
         return;
diff --git a/services/camera/libcameraservice/device3/Camera3Device.h b/services/camera/libcameraservice/device3/Camera3Device.h
index 0fd0a2d..b58f54e 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.h
+++ b/services/camera/libcameraservice/device3/Camera3Device.h
@@ -279,6 +279,11 @@
      */
     status_t setCameraMute(bool enabled);
 
+    /**
+     * Enables/disables camera service watchdog
+     */
+    status_t setCameraServiceWatchdog(bool enabled);
+
     // Get the status trackeer for the camera device
     wp<camera3::StatusTracker> getStatusTracker() { return mStatusTracker; }