Add device-awareness for camera concurrency API's

- getConcurrentCameraIds
- isConcurrentSessionConfigurationSupported

Test: atest CtsCameraTestCases, CtsVirtualDevicesCameraTestCases
Bug: 291736219
Change-Id: I48fc1c7ea3357e3130557f0f5d1a1eff0658e3b1
diff --git a/camera/aidl/android/hardware/ICameraService.aidl b/camera/aidl/android/hardware/ICameraService.aidl
index 885749d..230de95 100644
--- a/camera/aidl/android/hardware/ICameraService.aidl
+++ b/camera/aidl/android/hardware/ICameraService.aidl
@@ -165,19 +165,24 @@
     ConcurrentCameraIdCombination[] getConcurrentCameraIds();
 
     /**
-      * Check whether a particular set of session configurations are concurrently supported by the
-      * corresponding camera ids.
-      *
-      * @param sessions the set of camera id and session configuration pairs to be queried.
-      * @param targetSdkVersion the target sdk level of the application calling this function.
-      * @return true  - the set of concurrent camera id and stream combinations is supported.
-      *         false - the set of concurrent camera id and stream combinations is not supported
-      *                 OR the method was called with a set of camera ids not returned by
-      *                 getConcurrentCameraIds().
-      */
+     * Check whether a particular set of session configurations are concurrently supported by the
+     * corresponding camera ids.
+     *
+     * @param sessions the set of camera id and session configuration pairs to be queried.
+     * @param targetSdkVersion the target sdk level of the application calling this function.
+     * @param deviceId The device id of the context associated with the caller.
+     * @param devicePolicy The camera policy of the device of the associated context (default
+     *                     policy for default device context). Only virtual cameras would be exposed
+     *                     only for custom policy and only real cameras would be exposed for default
+     *                     policy.
+     * @return true  - the set of concurrent camera id and stream combinations is supported.
+     *         false - the set of concurrent camera id and stream combinations is not supported
+     *                 OR the method was called with a set of camera ids not returned by
+     *                 getConcurrentCameraIds().
+     */
     boolean isConcurrentSessionConfigurationSupported(
             in CameraIdAndSessionConfiguration[] sessions,
-            int targetSdkVersion);
+            int targetSdkVersion, int deviceId, int devicePolicy);
 
     /**
      * Remap Camera Ids in the CameraService.
diff --git a/camera/camera2/ConcurrentCamera.cpp b/camera/camera2/ConcurrentCamera.cpp
index 67aa876..ac442ed 100644
--- a/camera/camera2/ConcurrentCamera.cpp
+++ b/camera/camera2/ConcurrentCamera.cpp
@@ -32,7 +32,8 @@
 ConcurrentCameraIdCombination::ConcurrentCameraIdCombination() = default;
 
 ConcurrentCameraIdCombination::ConcurrentCameraIdCombination(
-        std::vector<std::string> &&combination) : mConcurrentCameraIds(std::move(combination)) { }
+        std::vector<std::pair<std::string, int32_t>> &&combination)
+            : mConcurrentCameraIdDeviceIdPairs(std::move(combination)) { }
 
 ConcurrentCameraIdCombination::~ConcurrentCameraIdCombination() = default;
 
@@ -42,25 +43,29 @@
         return BAD_VALUE;
     }
     status_t err = OK;
-    mConcurrentCameraIds.clear();
-    int32_t cameraIdCount = 0;
-    if ((err = parcel->readInt32(&cameraIdCount)) != OK) {
-        ALOGE("%s: Failed to read the camera id count from parcel: %d", __FUNCTION__, err);
+    mConcurrentCameraIdDeviceIdPairs.clear();
+    int32_t cameraCount = 0;
+    if ((err = parcel->readInt32(&cameraCount)) != OK) {
+        ALOGE("%s: Failed to read the camera count from parcel: %d", __FUNCTION__, err);
         return err;
     }
-    for (int32_t i = 0; i < cameraIdCount; i++) {
-        String16 id;
-        if ((err = parcel->readString16(&id)) != OK) {
+    for (int32_t i = 0; i < cameraCount; i++) {
+        String16 cameraId;
+        if ((err = parcel->readString16(&cameraId)) != OK) {
             ALOGE("%s: Failed to read camera id!", __FUNCTION__);
             return err;
         }
-        mConcurrentCameraIds.push_back(toStdString(id));
+        int32_t deviceId;
+        if ((err = parcel->readInt32(&deviceId)) != OK) {
+            ALOGE("%s: Failed to read device id!", __FUNCTION__);
+            return err;
+        }
+        mConcurrentCameraIdDeviceIdPairs.push_back({toStdString(cameraId), deviceId});
     }
     return OK;
 }
 
 status_t ConcurrentCameraIdCombination::writeToParcel(android::Parcel* parcel) const {
-
     if (parcel == nullptr) {
         ALOGE("%s: Null parcel", __FUNCTION__);
         return BAD_VALUE;
@@ -68,16 +73,20 @@
 
     status_t err = OK;
 
-    if ((err = parcel->writeInt32(mConcurrentCameraIds.size())) != OK) {
+    if ((err = parcel->writeInt32(mConcurrentCameraIdDeviceIdPairs.size())) != OK) {
         ALOGE("%s: Failed to write the camera id count to parcel: %d", __FUNCTION__, err);
         return err;
     }
 
-    for (const auto &it : mConcurrentCameraIds) {
-        if ((err = parcel->writeString16(toString16(it))) != OK) {
+    for (const auto &it : mConcurrentCameraIdDeviceIdPairs) {
+        if ((err = parcel->writeString16(toString16(it.first))) != OK) {
             ALOGE("%s: Failed to write the camera id string to parcel: %d", __FUNCTION__, err);
             return err;
         }
+        if ((err = parcel->writeInt32(it.second)) != OK) {
+            ALOGE("%s: Failed to write the device id integer to parcel: %d", __FUNCTION__, err);
+            return err;
+        }
     }
     return OK;
 }
@@ -105,7 +114,6 @@
 }
 
 status_t CameraIdAndSessionConfiguration::writeToParcel(android::Parcel* parcel) const {
-
     if (parcel == nullptr) {
         ALOGE("%s: Null parcel", __FUNCTION__);
         return BAD_VALUE;
diff --git a/camera/include/camera/camera2/ConcurrentCamera.h b/camera/include/camera/camera2/ConcurrentCamera.h
index ac99fd5..2a65da8 100644
--- a/camera/include/camera/camera2/ConcurrentCamera.h
+++ b/camera/include/camera/camera2/ConcurrentCamera.h
@@ -28,9 +28,9 @@
 namespace utils {
 
 struct ConcurrentCameraIdCombination : public Parcelable {
-    std::vector<std::string> mConcurrentCameraIds;
+    std::vector<std::pair<std::string, int32_t>> mConcurrentCameraIdDeviceIdPairs;
     ConcurrentCameraIdCombination();
-    ConcurrentCameraIdCombination(std::vector<std::string> &&combination);
+    ConcurrentCameraIdCombination(std::vector<std::pair<std::string, int32_t>> &&combination);
     virtual ~ConcurrentCameraIdCombination();
 
     virtual status_t writeToParcel(android::Parcel *parcel) const override;
diff --git a/camera/tests/fuzzer/camera_c2ConcurrentCamera_fuzzer.cpp b/camera/tests/fuzzer/camera_c2ConcurrentCamera_fuzzer.cpp
index 12b5bc3..c00f2ba 100644
--- a/camera/tests/fuzzer/camera_c2ConcurrentCamera_fuzzer.cpp
+++ b/camera/tests/fuzzer/camera_c2ConcurrentCamera_fuzzer.cpp
@@ -15,6 +15,7 @@
  */
 
 #include <camera2/ConcurrentCamera.h>
+#include <CameraUtils.h>
 #include <fuzzer/FuzzedDataProvider.h>
 #include "camera2common.h"
 
@@ -33,7 +34,8 @@
         size_t concurrentCameraIdSize = fdp.ConsumeIntegralInRange<size_t>(kRangeMin, kRangeMax);
         for (size_t idx = 0; idx < concurrentCameraIdSize; ++idx) {
             string concurrentCameraId = fdp.ConsumeRandomLengthString();
-            camIdCombination.mConcurrentCameraIds.push_back(concurrentCameraId);
+            camIdCombination.mConcurrentCameraIdDeviceIdPairs.push_back(
+                    {concurrentCameraId, kDefaultDeviceId});
         }
     }
 
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index 9ec8e35..fbb485c 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -165,6 +165,8 @@
 const std::string CameraService::kOfflineDevice("offline-");
 const std::string CameraService::kWatchAllClientsFlag("all");
 
+constexpr int32_t kInvalidDeviceId = -1;
+
 // Set to keep track of logged service error events.
 static std::set<std::string> sServiceErrorEventSet;
 
@@ -3431,7 +3433,6 @@
     return Status::ok();
 }
 
-// TODO(b/291736219): This to be made device-aware.
 Status CameraService::getConcurrentCameraIds(
         std::vector<ConcurrentCameraIdCombination>* concurrentCameraIds) {
     ATRACE_CALL();
@@ -3451,7 +3452,8 @@
     std::vector<std::unordered_set<std::string>> concurrentCameraCombinations =
             mCameraProviderManager->getConcurrentCameraIds();
     for (auto &combination : concurrentCameraCombinations) {
-        std::vector<std::string> validCombination;
+        std::vector<std::pair<std::string, int32_t>> validCombination;
+        int32_t firstDeviceId = kInvalidDeviceId;
         for (auto &cameraId : combination) {
             // if the camera state is not present, skip
             auto state = getCameraState(cameraId);
@@ -3466,7 +3468,17 @@
             if (shouldRejectSystemCameraConnection(cameraId)) {
                 continue;
             }
-            validCombination.push_back(cameraId);
+            auto [cameraOwnerDeviceId, mappedCameraId] =
+                    mVirtualDeviceCameraIdMapper.getDeviceIdAndMappedCameraIdPair(cameraId);
+            if (firstDeviceId == kInvalidDeviceId) {
+                firstDeviceId = cameraOwnerDeviceId;
+            } else if (firstDeviceId != cameraOwnerDeviceId) {
+                // Found an invalid combination which contains cameras with different device id's,
+                // hence discard it.
+                validCombination.clear();
+                break;
+            }
+            validCombination.push_back({mappedCameraId, cameraOwnerDeviceId});
         }
         if (validCombination.size() != 0) {
             concurrentCameraIds->push_back(std::move(validCombination));
@@ -3477,7 +3489,8 @@
 
 Status CameraService::isConcurrentSessionConfigurationSupported(
         const std::vector<CameraIdAndSessionConfiguration>& cameraIdsAndSessionConfigurations,
-        int targetSdkVersion, /*out*/bool* isSupported) {
+        int targetSdkVersion, int32_t deviceId, int32_t devicePolicy,
+        /*out*/bool* isSupported) {
     if (!isSupported) {
         ALOGE("%s: isSupported is NULL", __FUNCTION__);
         return STATUS_ERROR(ERROR_ILLEGAL_ARGUMENT, "isSupported is NULL");
@@ -3489,12 +3502,26 @@
                 "Camera subsystem is not available");
     }
 
+    for (auto cameraIdAndSessionConfiguration : cameraIdsAndSessionConfigurations) {
+        std::optional<std::string> cameraIdOptional =
+                resolveCameraId(cameraIdAndSessionConfiguration.mCameraId, deviceId, devicePolicy,
+                                getCallingUid());
+        if (!cameraIdOptional.has_value()) {
+            std::string msg = fmt::sprintf("Camera %s: Invalid camera id for device id %d",
+                    cameraIdAndSessionConfiguration.mCameraId.c_str(), deviceId);
+            ALOGE("%s: %s", __FUNCTION__, msg.c_str());
+            return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.c_str());
+        }
+        cameraIdAndSessionConfiguration.mCameraId = cameraIdOptional.value();
+    }
+
     // Check for camera permissions
     int callingPid = getCallingPid();
     int callingUid = getCallingUid();
-    // TODO(b/291736219): Pass deviceId owning the camera if we make this method device-aware.
     bool hasCameraPermission = ((callingPid == getpid()) ||
-            hasPermissionsForCamera(callingPid, callingUid, kDefaultDeviceId));
+            hasPermissionsForCamera(callingPid, callingUid,
+                    devicePolicy == IVirtualDeviceManagerNative::DEVICE_POLICY_DEFAULT
+                        ? kDefaultDeviceId : deviceId));
     if (!hasCameraPermission) {
         return STATUS_ERROR(ERROR_PERMISSION_DENIED,
                 "android.permission.CAMERA needed to call"
diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h
index 8dbd591..61d8f3d 100644
--- a/services/camera/libcameraservice/CameraService.h
+++ b/services/camera/libcameraservice/CameraService.h
@@ -191,14 +191,14 @@
     virtual binder::Status    removeListener(
             const sp<hardware::ICameraServiceListener>& listener);
 
-    // TODO(b/291736219): This to be made device-aware.
     virtual binder::Status getConcurrentCameraIds(
         /*out*/
         std::vector<hardware::camera2::utils::ConcurrentCameraIdCombination>* concurrentCameraIds);
 
     virtual binder::Status isConcurrentSessionConfigurationSupported(
         const std::vector<hardware::camera2::utils::CameraIdAndSessionConfiguration>& sessions,
-        int targetSdkVersion, /*out*/bool* supported);
+        int targetSdkVersion, int32_t deviceId, int32_t devicePolicy,
+        /*out*/bool* supported);
 
     virtual binder::Status    getLegacyParameters(
             int32_t cameraId,