cameraserver: re-cache concurrent camera id combinations on cameraDeviceStatusChange callbacks.

cameraserver should re-cache concurrent camera id combinations when it
receives cameraDeviceStatusChange callbacks from the camera provider in
case new concurrent camera id combinations have appeared / old ones have
gone away.

Bug: 148995918

Test: atest ConcurrentCameraTest.java

Change-Id: Ic433495d2dcf98d00cb247f434ad6c798ea17c54
Signed-off-by: Jayant Chowdhary <jchowdhary@google.com>
diff --git a/services/camera/libcameraservice/common/CameraProviderManager.cpp b/services/camera/libcameraservice/common/CameraProviderManager.cpp
index b20774a..2c97a38 100644
--- a/services/camera/libcameraservice/common/CameraProviderManager.cpp
+++ b/services/camera/libcameraservice/common/CameraProviderManager.cpp
@@ -1352,29 +1352,9 @@
 
     // Get list of concurrent streaming camera device combinations
     if (mMinorVersion >= 6) {
-        hardware::Return<void> ret = interface2_6->getConcurrentStreamingCameraIds([&status, this](
-                Status concurrentIdStatus, // TODO: Move all instances of hidl_string to 'using'
-                const hardware::hidl_vec<hardware::hidl_vec<hardware::hidl_string>>&
-                        cameraDeviceIdCombinations) {
-            status = concurrentIdStatus;
-            if (status == Status::OK) {
-                for (auto& combination : cameraDeviceIdCombinations) {
-                    std::unordered_set<std::string> deviceIds;
-                    for (auto &cameraDeviceId : combination) {
-                        deviceIds.insert(cameraDeviceId.c_str());
-                    }
-                    mConcurrentCameraIdCombinations.push_back(std::move(deviceIds));
-                }
-            } });
-        if (!ret.isOk()) {
-            ALOGE("%s: Transaction error in getting camera ID list from provider '%s': %s",
-                    __FUNCTION__, mProviderName.c_str(), linked.description().c_str());
-            return DEAD_OBJECT;
-        }
-        if (status != Status::OK) {
-            ALOGE("%s: Unable to query for camera devices from provider '%s'",
-                    __FUNCTION__, mProviderName.c_str());
-            return mapToStatusT(status);
+        res = getConcurrentStreamingCameraIdsInternalLocked(interface2_6);
+        if (res != OK) {
+            return res;
         }
     }
 
@@ -1626,6 +1606,75 @@
     return OK;
 }
 
+status_t CameraProviderManager::ProviderInfo::getConcurrentStreamingCameraIdsInternalLocked(
+        sp<provider::V2_6::ICameraProvider> &interface2_6) {
+    if (interface2_6 == nullptr) {
+        ALOGE("%s: null interface provided", __FUNCTION__);
+        return BAD_VALUE;
+    }
+    Status status = Status::OK;
+    hardware::Return<void> ret =
+            interface2_6->getConcurrentStreamingCameraIds([&status, this](
+            Status concurrentIdStatus, // TODO: Move all instances of hidl_string to 'using'
+            const hardware::hidl_vec<hardware::hidl_vec<hardware::hidl_string>>&
+                        cameraDeviceIdCombinations) {
+            status = concurrentIdStatus;
+            if (status == Status::OK) {
+                mConcurrentCameraIdCombinations.clear();
+                for (auto& combination : cameraDeviceIdCombinations) {
+                    std::unordered_set<std::string> deviceIds;
+                    for (auto &cameraDeviceId : combination) {
+                        deviceIds.insert(cameraDeviceId.c_str());
+                    }
+                    mConcurrentCameraIdCombinations.push_back(std::move(deviceIds));
+                }
+            } });
+    if (!ret.isOk()) {
+        ALOGE("%s: Transaction error in getting concurrent camera ID list from provider '%s'",
+                __FUNCTION__, mProviderName.c_str());
+            return DEAD_OBJECT;
+    }
+    if (status != Status::OK) {
+        ALOGE("%s: Unable to query for camera devices from provider '%s'",
+                    __FUNCTION__, mProviderName.c_str());
+        return mapToStatusT(status);
+    }
+    return OK;
+}
+
+status_t CameraProviderManager::ProviderInfo::reCacheConcurrentStreamingCameraIdsLocked() {
+    if (mMinorVersion < 6) {
+      // Unsupported operation, nothing to do here
+      return OK;
+    }
+    // Check if the provider is currently active - not going to start it up for this notification
+    auto interface = mSavedInterface != nullptr ? mSavedInterface : mActiveInterface.promote();
+    if (interface == nullptr) {
+        ALOGE("%s: camera provider interface for %s is not valid", __FUNCTION__,
+                mProviderName.c_str());
+        return INVALID_OPERATION;
+    }
+    auto castResult = provider::V2_6::ICameraProvider::castFrom(interface);
+
+    if (castResult.isOk()) {
+        sp<provider::V2_6::ICameraProvider> interface2_6 = castResult;
+        if (interface2_6 != nullptr) {
+            return getConcurrentStreamingCameraIdsInternalLocked(interface2_6);
+        } else {
+            // This should not happen since mMinorVersion >= 6
+            ALOGE("%s: mMinorVersion was >= 6, but interface2_6 was nullptr", __FUNCTION__);
+            return UNKNOWN_ERROR;
+        }
+    }
+    return OK;
+}
+
+std::vector<std::unordered_set<std::string>>
+CameraProviderManager::ProviderInfo::getConcurrentCameraIdCombinations() {
+    std::lock_guard<std::mutex> lock(mLock);
+    return mConcurrentCameraIdCombinations;
+}
+
 hardware::Return<void> CameraProviderManager::ProviderInfo::cameraDeviceStatusChange(
         const hardware::hidl_string& cameraDeviceName,
         CameraDeviceStatus newStatus) {
@@ -1659,6 +1708,10 @@
         }
         listener = mManager->getStatusListener();
         initialized = mInitialized;
+        if (reCacheConcurrentStreamingCameraIdsLocked() != OK) {
+            ALOGE("%s: CameraProvider %s could not re-cache concurrent streaming camera id list ",
+                      __FUNCTION__, mProviderName.c_str());
+        }
     }
     // Call without lock held to allow reentrancy into provider manager
     // Don't send the callback if providerInfo hasn't been initialized.
@@ -2747,7 +2800,7 @@
     std::vector<std::unordered_set<std::string>> deviceIdCombinations;
     std::lock_guard<std::mutex> lock(mInterfaceMutex);
     for (auto &provider : mProviders) {
-        for (auto &combinations : provider->mConcurrentCameraIdCombinations) {
+        for (auto &combinations : provider->getConcurrentCameraIdCombinations()) {
             deviceIdCombinations.push_back(combinations);
         }
     }
@@ -2831,7 +2884,7 @@
     // TODO: we should also do a findDeviceInfoLocked here ?
     for (auto &provider : mProviders) {
         if (checkIfSetContainsAll(cameraIdsAndSessionConfigs,
-                provider->mConcurrentCameraIdCombinations)) {
+                provider->getConcurrentCameraIdCombinations())) {
             // For each camera device in cameraIdsAndSessionConfigs collect
             // the streamConfigs and create the HAL
             // CameraIdAndStreamCombination, exit early if needed