cameraserver: Avoiding deadlocks while calling getSystemCameraKind()

The following scenario can occur:

 T1 serving Client A's disconnect() call:
   T2 : serving Client B's connect() call
     T2 : CameraProviderManager::openSession() locks mInterfaceMutex and waits on open() HAL
          interface call
       T1: updateStatus() locks mStatusListenerMutex
         T1: CameraProviderManager::isPublicallyHiddenSecureCamera() / getSystemCameraKind() waits
             on mInterfaceMutex
           T2: while waiting on open(), gets a torchModeStatus() callback from the camera HAL
              T2: onStatusChanged()
                T2: broadcastTorchModeStatus() which waits on mStatusListenerMutex

As a result there's a possible circular hold and wait between T1 and T2.

We cache the system camera kind in CameraState. That doesn't completely
avoid having to hold mInterfaceLock while calling getSystemCameraKind in
CameraService (cache updates), instead it reduces it. We instead need to
hold mCameraStates lock which has a smaller scope.

Bug: 141756275

Test: CTS
Test: GCA (sanity)

Change-Id: I4a697c1eaccc3603007be4a595febea981fbeb64
Signed-off-by: Jayant Chowdhary <jchowdhary@google.com>
diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h
index 058d57e..8765fbf 100644
--- a/services/camera/libcameraservice/CameraService.h
+++ b/services/camera/libcameraservice/CameraService.h
@@ -490,7 +490,8 @@
          * Make a new CameraState and set the ID, cost, and conflicting devices using the values
          * returned in the HAL's camera_info struct for each device.
          */
-        CameraState(const String8& id, int cost, const std::set<String8>& conflicting);
+        CameraState(const String8& id, int cost, const std::set<String8>& conflicting,
+                SystemCameraKind deviceKind);
         virtual ~CameraState();
 
         /**
@@ -542,6 +543,11 @@
          */
         String8 getId() const;
 
+        /**
+         * Return the kind (SystemCameraKind) of this camera device.
+         */
+        SystemCameraKind getSystemCameraKind() const;
+
     private:
         const String8 mId;
         StatusInternal mStatus; // protected by mStatusLock
@@ -549,6 +555,7 @@
         std::set<String8> mConflicting;
         mutable Mutex mStatusLock;
         CameraParameters mShimParams;
+        const SystemCameraKind mSystemCameraKind;
     }; // class CameraState
 
     // Observer for UID lifecycle enforcing that UIDs in idle
@@ -660,12 +667,14 @@
     // Should a device status update be skipped for a particular camera device ? (this can happen
     // under various conditions. For example if a camera device is advertised as
     // system only or hidden secure camera, amongst possible others.
-    bool shouldSkipStatusUpdates(const String8& cameraId, bool isVendorListener, int clientPid,
-            int clientUid) const;
+    static bool shouldSkipStatusUpdates(SystemCameraKind systemCameraKind, bool isVendorListener,
+            int clientPid, int clientUid);
 
-    inline SystemCameraKind getSystemCameraKind(const String8& cameraId) const {
-        return mCameraProviderManager->getSystemCameraKind(cameraId.c_str());
-    }
+    // Gets the kind of camera device (i.e public, hidden secure or system only)
+    // getSystemCameraKind() needs mInterfaceMutex which might lead to deadlocks
+    // if held along with mStatusListenerLock (depending on lock ordering, b/141756275), it is
+    // recommended that we don't call this function with mStatusListenerLock held.
+    status_t getSystemCameraKind(const String8& cameraId, SystemCameraKind *kind) const;
 
     // Update the set of API1Compatible camera devices without including system
     // cameras and secure cameras. This is used for hiding system only cameras