Camera: Cache logical camera related info

Refactor code to cache logical camera related info, such that we don't
need to query the camera characteristics multiple times.

Test: Camera CTS
Bug: 79523700
Change-Id: I01733fc9165ec88aadc655491a025627fd622857
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
index 84428c2..b9e07f3 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
@@ -122,6 +122,7 @@
                 physicalKeysEntry.data.i32 + physicalKeysEntry.count);
     }
 
+    mProviderManager = providerPtr;
     return OK;
 }
 
@@ -626,12 +627,11 @@
 
     if (physicalCameraId.size() > 0) {
         std::vector<std::string> physicalCameraIds;
-        std::string physicalId(physicalCameraId.string());
         bool logicalCamera =
-                CameraProviderManager::isLogicalCamera(mDevice->info(), &physicalCameraIds);
+                mProviderManager->isLogicalCamera(mCameraIdStr.string(), &physicalCameraIds);
         if (!logicalCamera ||
-                std::find(physicalCameraIds.begin(), physicalCameraIds.end(), physicalId) ==
-                physicalCameraIds.end()) {
+                std::find(physicalCameraIds.begin(), physicalCameraIds.end(),
+                physicalCameraId.string()) == physicalCameraIds.end()) {
             String8 msg = String8::format("Camera %s: Camera doesn't support physicalCameraId %s.",
                     mCameraIdStr.string(), physicalCameraId.string());
             ALOGE("%s: %s", __FUNCTION__, msg.string());
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.h b/services/camera/libcameraservice/api2/CameraDeviceClient.h
index c30561d..09ce977 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.h
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.h
@@ -301,6 +301,7 @@
     std::unordered_map<int32_t, OutputStreamInfo> mStreamInfoMap;
 
     static const int32_t MAX_SURFACES_PER_STREAM = 2;
+    sp<CameraProviderManager> mProviderManager;
 };
 
 }; // namespace android
diff --git a/services/camera/libcameraservice/common/CameraProviderManager.cpp b/services/camera/libcameraservice/common/CameraProviderManager.cpp
index c4944a6..a94e886 100644
--- a/services/camera/libcameraservice/common/CameraProviderManager.cpp
+++ b/services/camera/libcameraservice/common/CameraProviderManager.cpp
@@ -396,35 +396,46 @@
     return ret;
 }
 
-bool CameraProviderManager::isLogicalCamera(const CameraMetadata& staticInfo,
-        std::vector<std::string>* physicalCameraIds) {
-    bool isLogicalCam = false;
-    camera_metadata_ro_entry_t entryCap;
+void CameraProviderManager::ProviderInfo::DeviceInfo3::queryPhysicalCameraIds() {
+    camera_metadata_entry_t entryCap;
 
-    entryCap = staticInfo.find(ANDROID_REQUEST_AVAILABLE_CAPABILITIES);
+    entryCap = mCameraCharacteristics.find(ANDROID_REQUEST_AVAILABLE_CAPABILITIES);
     for (size_t i = 0; i < entryCap.count; ++i) {
         uint8_t capability = entryCap.data.u8[i];
         if (capability == ANDROID_REQUEST_AVAILABLE_CAPABILITIES_LOGICAL_MULTI_CAMERA) {
-            isLogicalCam = true;
+            mIsLogicalCamera = true;
             break;
         }
     }
-    if (!isLogicalCam) {
-        return false;
+    if (!mIsLogicalCamera) {
+        return;
     }
 
-    camera_metadata_ro_entry_t entryIds = staticInfo.find(ANDROID_LOGICAL_MULTI_CAMERA_PHYSICAL_IDS);
+    camera_metadata_entry_t entryIds = mCameraCharacteristics.find(
+            ANDROID_LOGICAL_MULTI_CAMERA_PHYSICAL_IDS);
     const uint8_t* ids = entryIds.data.u8;
     size_t start = 0;
     for (size_t i = 0; i < entryIds.count; ++i) {
         if (ids[i] == '\0') {
             if (start != i) {
-                physicalCameraIds->push_back((const char*)ids+start);
+                mPhysicalIds.push_back((const char*)ids+start);
             }
             start = i+1;
         }
     }
-    return true;
+}
+
+bool CameraProviderManager::isLogicalCamera(const std::string& id,
+        std::vector<std::string>* physicalCameraIds) {
+    std::lock_guard<std::mutex> lock(mInterfaceMutex);
+
+    auto deviceInfo = findDeviceInfoLocked(id);
+    if (deviceInfo == nullptr) return false;
+
+    if (deviceInfo->mIsLogicalCamera && physicalCameraIds != nullptr) {
+        *physicalCameraIds = deviceInfo->mPhysicalIds;
+    }
+    return deviceInfo->mIsLogicalCamera;
 }
 
 bool CameraProviderManager::isHiddenPhysicalCamera(const std::string& cameraId) {
@@ -449,9 +460,9 @@
             }
 
             std::vector<std::string> physicalIds;
-            if (isLogicalCamera(info, &physicalIds)) {
-                if (std::find(physicalIds.begin(), physicalIds.end(), cameraId) !=
-                        physicalIds.end()) {
+            if (deviceInfo->mIsLogicalCamera) {
+                if (std::find(deviceInfo->mPhysicalIds.begin(), deviceInfo->mPhysicalIds.end(),
+                        cameraId) != deviceInfo->mPhysicalIds.end()) {
                     int deviceVersion = HARDWARE_DEVICE_API_VERSION(
                             deviceInfo->mVersion.get_major(), deviceInfo->mVersion.get_minor());
                     if (deviceVersion < CAMERA_DEVICE_API_VERSION_3_5) {
@@ -760,9 +771,8 @@
         }
 
         // Dump characteristics of non-standalone physical camera
-        std::vector<std::string> physicalIds;
-        if (isLogicalCamera(info2, &physicalIds)) {
-            for (auto& id : physicalIds) {
+        if (device->mIsLogicalCamera) {
+            for (auto& id : device->mPhysicalIds) {
                 // Skip if physical id is an independent camera
                 if (std::find(mProviderPublicCameraIds.begin(), mProviderPublicCameraIds.end(), id)
                         != mProviderPublicCameraIds.end()) {
@@ -1130,6 +1140,7 @@
         mHasFlashUnit = false;
     }
 
+    queryPhysicalCameraIds();
     // Get physical camera characteristics if applicable
     auto castResult = device::V3_5::ICameraDevice::castFrom(mInterface);
     if (!castResult.isOk()) {
@@ -1142,9 +1153,8 @@
         return;
     }
 
-    std::vector<std::string> physicalIds;
-    if (CameraProviderManager::isLogicalCamera(mCameraCharacteristics, &physicalIds)) {
-        for (auto& id : physicalIds) {
+    if (mIsLogicalCamera) {
+        for (auto& id : mPhysicalIds) {
             if (std::find(mPublicCameraIds.begin(), mPublicCameraIds.end(), id) !=
                     mPublicCameraIds.end()) {
                 continue;
@@ -1622,20 +1632,14 @@
     std::unordered_set<std::string> removedIds;
 
     for (auto& deviceId : deviceIds) {
-        CameraMetadata info;
-        status_t res = getCameraCharacteristicsLocked(deviceId, &info);
-        if (res != OK) {
-            ALOGE("%s: Failed to getCameraCharacteristics for id %s", __FUNCTION__,
-                    deviceId.c_str());
-            return;
-        }
+        auto deviceInfo = findDeviceInfoLocked(deviceId);
+        if (deviceInfo == nullptr) continue;
 
-        // idCombo contains the ids of a logical camera and its physical cameras
-        std::vector<std::string> idCombo;
-        bool logicalCamera = isLogicalCamera(info, &idCombo);
-        if (!logicalCamera) {
+        if (!deviceInfo->mIsLogicalCamera) {
             continue;
         }
+        // idCombo contains the ids of a logical camera and its physical cameras
+        std::vector<std::string> idCombo = deviceInfo->mPhysicalIds;
         idCombo.push_back(deviceId);
 
         for (auto& id : deviceIds) {
diff --git a/services/camera/libcameraservice/common/CameraProviderManager.h b/services/camera/libcameraservice/common/CameraProviderManager.h
index 61e21b4..9016747 100644
--- a/services/camera/libcameraservice/common/CameraProviderManager.h
+++ b/services/camera/libcameraservice/common/CameraProviderManager.h
@@ -231,11 +231,10 @@
             hardware::hidl_version maxVersion = hardware::hidl_version{1000,0}) const;
 
     /*
-     * Check if a camera with staticInfo is a logical camera. And if yes, return
+     * Check if a camera is a logical camera. And if yes, return
      * the physical camera ids.
      */
-    static bool isLogicalCamera(const CameraMetadata& staticInfo,
-            std::vector<std::string>* physicalCameraIds);
+    bool isLogicalCamera(const std::string& id, std::vector<std::string>* physicalCameraIds);
 
     bool isHiddenPhysicalCamera(const std::string& cameraId);
 private:
@@ -293,6 +292,8 @@
             const std::string mId;    // ID section of full name
             const hardware::hidl_version mVersion;
             const metadata_vendor_id_t mProviderTagid;
+            bool mIsLogicalCamera;
+            std::vector<std::string> mPhysicalIds;
 
             const hardware::camera::common::V1_0::CameraResourceCost mResourceCost;
 
@@ -319,7 +320,7 @@
                     const std::vector<std::string>& publicCameraIds,
                     const hardware::camera::common::V1_0::CameraResourceCost& resourceCost) :
                     mName(name), mId(id), mVersion(version), mProviderTagid(tagId),
-                    mResourceCost(resourceCost),
+                    mIsLogicalCamera(false), mResourceCost(resourceCost),
                     mStatus(hardware::camera::common::V1_0::CameraDeviceStatus::PRESENT),
                     mHasFlashUnit(false), mPublicCameraIds(publicCameraIds) {}
             virtual ~DeviceInfo();
@@ -383,6 +384,7 @@
         private:
             CameraMetadata mCameraCharacteristics;
             std::unordered_map<std::string, CameraMetadata> mPhysicalCameraCharacteristics;
+            void queryPhysicalCameraIds();
         };
 
     private:
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index 1bc5d33..664e7dc 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -127,7 +127,7 @@
     }
 
     std::vector<std::string> physicalCameraIds;
-    bool isLogical = CameraProviderManager::isLogicalCamera(mDeviceInfo, &physicalCameraIds);
+    bool isLogical = manager->isLogicalCamera(mId.string(), &physicalCameraIds);
     if (isLogical) {
         for (auto& physicalId : physicalCameraIds) {
             res = manager->getCameraCharacteristics(physicalId, &mPhysicalDeviceInfoMap[physicalId]);