ICameraService: Add methods to query concurrent streaming camera support.

- getConcurrentStreamingCameraIds() :
        returns a list of combinations of camera ids that may stream
        concurrently.

- isConcurrentSessionConfigurationSupported() :
        queries whether camera devices can support the
        corresponding given session configurations concurrently.

Bug: 77960042

Test: GCA (sanity)
Test: CTS

Change-Id: Iba237118ccf145695a500a2c406713e416e66011
Signed-off-by: Jayant Chowdhary <jchowdhary@google.com>
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
index 8ed3ab6..ff9d274 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
@@ -492,7 +492,7 @@
         return STATUS_ERROR(CameraService::ERROR_DISCONNECTED, "Camera device no longer alive");
     }
 
-    res = checkOperatingModeLocked(operatingMode);
+    res = checkOperatingMode(operatingMode, mDevice->info(), mCameraIdStr);
     if (!res.isOk()) {
         return res;
     }
@@ -550,8 +550,8 @@
     return res;
 }
 
-binder::Status CameraDeviceClient::checkSurfaceTypeLocked(size_t numBufferProducers,
-        bool deferredConsumer, int surfaceType) const {
+binder::Status CameraDeviceClient::checkSurfaceType(size_t numBufferProducers,
+        bool deferredConsumer, int surfaceType)  {
     if (numBufferProducers > MAX_SURFACES_PER_STREAM) {
         ALOGE("%s: GraphicBufferProducer count %zu for stream exceeds limit of %d",
                 __FUNCTION__, numBufferProducers, MAX_SURFACES_PER_STREAM);
@@ -572,28 +572,27 @@
     return binder::Status::ok();
 }
 
-binder::Status CameraDeviceClient::checkPhysicalCameraIdLocked(String8 physicalCameraId) {
-    if (physicalCameraId.size() > 0) {
-        std::vector<std::string> physicalCameraIds;
-        bool logicalCamera =
-            mProviderManager->isLogicalCamera(mCameraIdStr.string(), &physicalCameraIds);
-        if (!logicalCamera ||
-                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());
-            return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
-        }
+binder::Status CameraDeviceClient::checkPhysicalCameraId(
+        const std::vector<std::string> &physicalCameraIds, const String8 &physicalCameraId,
+        const String8 &logicalCameraId) {
+    if (physicalCameraId.size() == 0) {
+        return binder::Status::ok();
     }
-
+    if (std::find(physicalCameraIds.begin(), physicalCameraIds.end(),
+        physicalCameraId.string()) == physicalCameraIds.end()) {
+        String8 msg = String8::format("Camera %s: Camera doesn't support physicalCameraId %s.",
+                logicalCameraId.string(), physicalCameraId.string());
+        ALOGE("%s: %s", __FUNCTION__, msg.string());
+        return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
+    }
     return binder::Status::ok();
 }
 
-binder::Status CameraDeviceClient::checkOperatingModeLocked(int operatingMode) const {
+binder::Status CameraDeviceClient::checkOperatingMode(int operatingMode,
+        const CameraMetadata &staticInfo, const String8 &cameraId) {
     if (operatingMode < 0) {
         String8 msg = String8::format(
-            "Camera %s: Invalid operating mode %d requested", mCameraIdStr.string(), operatingMode);
+            "Camera %s: Invalid operating mode %d requested", cameraId.string(), operatingMode);
         ALOGE("%s: %s", __FUNCTION__, msg.string());
         return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
                 msg.string());
@@ -601,8 +600,7 @@
 
     bool isConstrainedHighSpeed = (operatingMode == ICameraDeviceUser::CONSTRAINED_HIGH_SPEED_MODE);
     if (isConstrainedHighSpeed) {
-        CameraMetadata staticInfo = mDevice->info();
-        camera_metadata_entry_t entry = staticInfo.find(ANDROID_REQUEST_AVAILABLE_CAPABILITIES);
+        camera_metadata_ro_entry_t entry = staticInfo.find(ANDROID_REQUEST_AVAILABLE_CAPABILITIES);
         bool isConstrainedHighSpeedSupported = false;
         for(size_t i = 0; i < entry.count; ++i) {
             uint8_t capability = entry.data.u8[i];
@@ -614,7 +612,7 @@
         if (!isConstrainedHighSpeedSupported) {
             String8 msg = String8::format(
                 "Camera %s: Try to create a constrained high speed configuration on a device"
-                " that doesn't support it.", mCameraIdStr.string());
+                " that doesn't support it.", cameraId.string());
             ALOGE("%s: %s", __FUNCTION__, msg.string());
             return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
                     msg.string());
@@ -645,39 +643,31 @@
     stream->bufferSize = 0;
 }
 
-binder::Status CameraDeviceClient::isSessionConfigurationSupported(
-        const SessionConfiguration& sessionConfiguration, bool *status /*out*/) {
-    ATRACE_CALL();
-
-    binder::Status res;
-    if (!(res = checkPidStatus(__FUNCTION__)).isOk()) return res;
-
-    Mutex::Autolock icl(mBinderSerializationLock);
-
-    if (!mDevice.get()) {
-        return STATUS_ERROR(CameraService::ERROR_DISCONNECTED, "Camera device no longer alive");
-    }
-
+binder::Status
+CameraDeviceClient::convertToHALStreamCombination(const SessionConfiguration& sessionConfiguration,
+        const String8 &logicalCameraId, const CameraMetadata &deviceInfo,
+        metadataGetter getMetadata, const std::vector<std::string> &physicalCameraIds,
+        hardware::camera::device::V3_4::StreamConfiguration &streamConfiguration,
+        bool *unsupported) {
     auto operatingMode = sessionConfiguration.getOperatingMode();
-    res = checkOperatingModeLocked(operatingMode);
+    binder::Status res = checkOperatingMode(operatingMode, deviceInfo, logicalCameraId);
     if (!res.isOk()) {
         return res;
     }
 
-    if (status == nullptr) {
-        String8 msg = String8::format( "Camera %s: Invalid status!", mCameraIdStr.string());
+    if (unsupported == nullptr) {
+        String8 msg("unsupported nullptr");
         ALOGE("%s: %s", __FUNCTION__, msg.string());
         return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
     }
-
-    hardware::camera::device::V3_4::StreamConfiguration streamConfiguration;
+    *unsupported = false;
     auto ret = Camera3Device::mapToStreamConfigurationMode(
             static_cast<camera3_stream_configuration_mode_t> (operatingMode),
             /*out*/ &streamConfiguration.operationMode);
     if (ret != OK) {
         String8 msg = String8::format(
-            "Camera %s: Failed mapping operating mode %d requested: %s (%d)", mCameraIdStr.string(),
-            operatingMode, strerror(-ret), ret);
+            "Camera %s: Failed mapping operating mode %d requested: %s (%d)",
+            logicalCameraId.string(), operatingMode, strerror(-ret), ret);
         ALOGE("%s: %s", __FUNCTION__, msg.string());
         return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
                 msg.string());
@@ -711,12 +701,12 @@
         bool isStreamInfoValid = false;
         OutputStreamInfo streamInfo;
 
-        res = checkSurfaceTypeLocked(numBufferProducers, deferredConsumer, it.getSurfaceType());
+        res = checkSurfaceType(numBufferProducers, deferredConsumer, it.getSurfaceType());
         if (!res.isOk()) {
             return res;
         }
-
-        res = checkPhysicalCameraIdLocked(physicalCameraId);
+        res = checkPhysicalCameraId(physicalCameraIds, physicalCameraId,
+                logicalCameraId);
         if (!res.isOk()) {
             return res;
         }
@@ -742,8 +732,10 @@
 
         for (auto& bufferProducer : bufferProducers) {
             sp<Surface> surface;
+            const CameraMetadata &physicalDeviceInfo = getMetadata(physicalCameraId);
             res = createSurfaceFromGbp(streamInfo, isStreamInfoValid, surface, bufferProducer,
-                    physicalCameraId);
+                    logicalCameraId,
+                    physicalCameraId.size() > 0 ? physicalDeviceInfo : deviceInfo );
 
             if (!res.isOk())
                 return res;
@@ -759,15 +751,15 @@
                     std::vector<OutputStreamInfo> compositeStreams;
                     if (isDepthCompositeStream) {
                         ret = camera3::DepthCompositeStream::getCompositeStreamInfo(streamInfo,
-                                mDevice->info(), &compositeStreams);
+                                deviceInfo, &compositeStreams);
                     } else {
                         ret = camera3::HeicCompositeStream::getCompositeStreamInfo(streamInfo,
-                            mDevice->info(), &compositeStreams);
+                            deviceInfo, &compositeStreams);
                     }
                     if (ret != OK) {
                         String8 msg = String8::format(
                                 "Camera %s: Failed adding composite streams: %s (%d)",
-                                mCameraIdStr.string(), strerror(-ret), ret);
+                                logicalCameraId.string(), strerror(-ret), ret);
                         ALOGE("%s: %s", __FUNCTION__, msg.string());
                         return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
                     }
@@ -775,7 +767,7 @@
                     if (compositeStreams.size() == 0) {
                         // No internal streams means composite stream not
                         // supported.
-                        *status = false;
+                        *unsupported = true;
                         return binder::Status::ok();
                     } else if (compositeStreams.size() > 1) {
                         streamCount += compositeStreams.size() - 1;
@@ -796,6 +788,49 @@
             }
         }
     }
+    return binder::Status::ok();
+}
+
+binder::Status CameraDeviceClient::isSessionConfigurationSupported(
+        const SessionConfiguration& sessionConfiguration, bool *status /*out*/) {
+    ATRACE_CALL();
+
+    binder::Status res;
+    status_t ret = OK;
+    if (!(res = checkPidStatus(__FUNCTION__)).isOk()) return res;
+
+    Mutex::Autolock icl(mBinderSerializationLock);
+
+    if (!mDevice.get()) {
+        return STATUS_ERROR(CameraService::ERROR_DISCONNECTED, "Camera device no longer alive");
+    }
+
+    auto operatingMode = sessionConfiguration.getOperatingMode();
+    res = checkOperatingMode(operatingMode, mDevice->info(), mCameraIdStr);
+    if (!res.isOk()) {
+        return res;
+    }
+
+    if (status == nullptr) {
+        String8 msg = String8::format( "Camera %s: Invalid status!", mCameraIdStr.string());
+        ALOGE("%s: %s", __FUNCTION__, msg.string());
+        return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
+    }
+    hardware::camera::device::V3_4::StreamConfiguration streamConfiguration;
+    bool earlyExit = false;
+    metadataGetter getMetadata = [this](const String8 &id) {return mDevice->info(id);};
+    std::vector<std::string> physicalCameraIds;
+    mProviderManager->isLogicalCamera(mCameraIdStr.string(), &physicalCameraIds);
+    res = convertToHALStreamCombination(sessionConfiguration, mCameraIdStr,
+            mDevice->info(), getMetadata, physicalCameraIds, streamConfiguration, &earlyExit);
+    if (!res.isOk()) {
+        return res;
+    }
+
+    if (earlyExit) {
+        *status = false;
+        return binder::Status::ok();
+    }
 
     *status = false;
     ret = mProviderManager->isSessionConfigurationSupported(mCameraIdStr.string(),
@@ -935,7 +970,7 @@
     String8 physicalCameraId = String8(outputConfiguration.getPhysicalCameraId());
     bool deferredConsumerOnly = deferredConsumer && numBufferProducers == 0;
 
-    res = checkSurfaceTypeLocked(numBufferProducers, deferredConsumer,
+    res = checkSurfaceType(numBufferProducers, deferredConsumer,
             outputConfiguration.getSurfaceType());
     if (!res.isOk()) {
         return res;
@@ -944,8 +979,9 @@
     if (!mDevice.get()) {
         return STATUS_ERROR(CameraService::ERROR_DISCONNECTED, "Camera device no longer alive");
     }
-
-    res = checkPhysicalCameraIdLocked(physicalCameraId);
+    std::vector<std::string> physicalCameraIds;
+    mProviderManager->isLogicalCamera(mCameraIdStr.string(), &physicalCameraIds);
+    res = checkPhysicalCameraId(physicalCameraIds, physicalCameraId, mCameraIdStr);
     if (!res.isOk()) {
         return res;
     }
@@ -974,7 +1010,7 @@
 
         sp<Surface> surface;
         res = createSurfaceFromGbp(streamInfo, isStreamInfoValid, surface, bufferProducer,
-                physicalCameraId);
+                mCameraIdStr, mDevice->info(physicalCameraId));
 
         if (!res.isOk())
             return res;
@@ -1278,7 +1314,7 @@
         OutputStreamInfo outInfo;
         sp<Surface> surface;
         res = createSurfaceFromGbp(outInfo, /*isStreamInfoValid*/ false, surface,
-                newOutputsMap.valueAt(i), physicalCameraId);
+                newOutputsMap.valueAt(i), mCameraIdStr, mDevice->info(physicalCameraId));
         if (!res.isOk())
             return res;
 
@@ -1358,11 +1394,11 @@
 binder::Status CameraDeviceClient::createSurfaceFromGbp(
         OutputStreamInfo& streamInfo, bool isStreamInfoValid,
         sp<Surface>& surface, const sp<IGraphicBufferProducer>& gbp,
-        const String8& physicalId) {
+        const String8 &cameraId, const CameraMetadata &physicalCameraMetadata) {
 
     // bufferProducer must be non-null
     if (gbp == nullptr) {
-        String8 msg = String8::format("Camera %s: Surface is NULL", mCameraIdStr.string());
+        String8 msg = String8::format("Camera %s: Surface is NULL", cameraId.string());
         ALOGW("%s: %s", __FUNCTION__, msg.string());
         return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
     }
@@ -1374,13 +1410,13 @@
     status_t err;
     if ((err = gbp->getConsumerUsage(&consumerUsage)) != OK) {
         String8 msg = String8::format("Camera %s: Failed to query Surface consumer usage: %s (%d)",
-                mCameraIdStr.string(), strerror(-err), err);
+                cameraId.string(), strerror(-err), err);
         ALOGE("%s: %s", __FUNCTION__, msg.string());
         return STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION, msg.string());
     }
     if (consumerUsage & GraphicBuffer::USAGE_HW_TEXTURE) {
         ALOGW("%s: Camera %s with consumer usage flag: %" PRIu64 ": Forcing asynchronous mode for stream",
-                __FUNCTION__, mCameraIdStr.string(), consumerUsage);
+                __FUNCTION__, cameraId.string(), consumerUsage);
         useAsync = true;
     }
 
@@ -1399,26 +1435,26 @@
     android_dataspace dataSpace;
     if ((err = anw->query(anw, NATIVE_WINDOW_WIDTH, &width)) != OK) {
         String8 msg = String8::format("Camera %s: Failed to query Surface width: %s (%d)",
-                 mCameraIdStr.string(), strerror(-err), err);
+                 cameraId.string(), strerror(-err), err);
         ALOGE("%s: %s", __FUNCTION__, msg.string());
         return STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION, msg.string());
     }
     if ((err = anw->query(anw, NATIVE_WINDOW_HEIGHT, &height)) != OK) {
         String8 msg = String8::format("Camera %s: Failed to query Surface height: %s (%d)",
-                mCameraIdStr.string(), strerror(-err), err);
+                cameraId.string(), strerror(-err), err);
         ALOGE("%s: %s", __FUNCTION__, msg.string());
         return STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION, msg.string());
     }
     if ((err = anw->query(anw, NATIVE_WINDOW_FORMAT, &format)) != OK) {
         String8 msg = String8::format("Camera %s: Failed to query Surface format: %s (%d)",
-                mCameraIdStr.string(), strerror(-err), err);
+                cameraId.string(), strerror(-err), err);
         ALOGE("%s: %s", __FUNCTION__, msg.string());
         return STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION, msg.string());
     }
     if ((err = anw->query(anw, NATIVE_WINDOW_DEFAULT_DATASPACE,
             reinterpret_cast<int*>(&dataSpace))) != OK) {
         String8 msg = String8::format("Camera %s: Failed to query Surface dataspace: %s (%d)",
-                mCameraIdStr.string(), strerror(-err), err);
+                cameraId.string(), strerror(-err), err);
         ALOGE("%s: %s", __FUNCTION__, msg.string());
         return STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION, msg.string());
     }
@@ -1429,16 +1465,16 @@
             ((consumerUsage & GRALLOC_USAGE_HW_MASK) &&
              ((consumerUsage & GRALLOC_USAGE_SW_READ_MASK) == 0))) {
         ALOGW("%s: Camera %s: Overriding format %#x to IMPLEMENTATION_DEFINED",
-                __FUNCTION__, mCameraIdStr.string(), format);
+                __FUNCTION__, cameraId.string(), format);
         format = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
     }
     // Round dimensions to the nearest dimensions available for this format
     if (flexibleConsumer && isPublicFormat(format) &&
             !CameraDeviceClient::roundBufferDimensionNearest(width, height,
-            format, dataSpace, mDevice->info(physicalId), /*out*/&width, /*out*/&height)) {
+            format, dataSpace, physicalCameraMetadata, /*out*/&width, /*out*/&height)) {
         String8 msg = String8::format("Camera %s: No supported stream configurations with "
                 "format %#x defined, failed to create output stream",
-                mCameraIdStr.string(), format);
+                cameraId.string(), format);
         ALOGE("%s: %s", __FUNCTION__, msg.string());
         return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
     }
@@ -1453,26 +1489,26 @@
     }
     if (width != streamInfo.width) {
         String8 msg = String8::format("Camera %s:Surface width doesn't match: %d vs %d",
-                mCameraIdStr.string(), width, streamInfo.width);
+                cameraId.string(), width, streamInfo.width);
         ALOGE("%s: %s", __FUNCTION__, msg.string());
         return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
     }
     if (height != streamInfo.height) {
         String8 msg = String8::format("Camera %s:Surface height doesn't match: %d vs %d",
-                 mCameraIdStr.string(), height, streamInfo.height);
+                 cameraId.string(), height, streamInfo.height);
         ALOGE("%s: %s", __FUNCTION__, msg.string());
         return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
     }
     if (format != streamInfo.format) {
         String8 msg = String8::format("Camera %s:Surface format doesn't match: %d vs %d",
-                 mCameraIdStr.string(), format, streamInfo.format);
+                 cameraId.string(), format, streamInfo.format);
         ALOGE("%s: %s", __FUNCTION__, msg.string());
         return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
     }
     if (format != HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED) {
         if (dataSpace != streamInfo.dataSpace) {
             String8 msg = String8::format("Camera %s:Surface dataSpace doesn't match: %d vs %d",
-                    mCameraIdStr.string(), dataSpace, streamInfo.dataSpace);
+                    cameraId.string(), dataSpace, streamInfo.dataSpace);
             ALOGE("%s: %s", __FUNCTION__, msg.string());
             return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
         }
@@ -1481,7 +1517,7 @@
         if (consumerUsage != streamInfo.consumerUsage) {
             String8 msg = String8::format(
                     "Camera %s:Surface usage flag doesn't match %" PRIu64 " vs %" PRIu64 "",
-                    mCameraIdStr.string(), consumerUsage, streamInfo.consumerUsage);
+                    cameraId.string(), consumerUsage, streamInfo.consumerUsage);
             ALOGE("%s: %s", __FUNCTION__, msg.string());
             return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
         }
@@ -1861,7 +1897,7 @@
 
         sp<Surface> surface;
         res = createSurfaceFromGbp(mStreamInfoMap[streamId], true /*isStreamInfoValid*/,
-                surface, bufferProducer, physicalId);
+                surface, bufferProducer, mCameraIdStr, mDevice->info(physicalId));
 
         if (!res.isOk())
             return res;