Camera: Allow streaming requests with individual physical settings

Streaming capture requests which include individual physical
device settings should not be blocked.

Bug: 72524845
Test: Camera CTS

Change-Id: Idb3ad9d022d4e2b2ced2558d1746866dbd3842b4
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
index 8e112a1..4a72de0 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
@@ -28,6 +28,8 @@
 #include "common/CameraDeviceBase.h"
 #include "api2/CameraDeviceClient.h"
 
+#include <camera_metadata_hidden.h>
+
 // Convenience methods for constructing binder::Status objects for error returns
 
 #define STATUS_ERROR(errorCode, errorString) \
@@ -106,6 +108,15 @@
                                       /*listener*/this,
                                       /*sendPartials*/true);
 
+    auto deviceInfo = mDevice->info();
+    camera_metadata_entry_t physicalKeysEntry = deviceInfo.find(
+            ANDROID_REQUEST_AVAILABLE_PHYSICAL_CAMERA_REQUEST_KEYS);
+    if (physicalKeysEntry.count > 0) {
+        mSupportedPhysicalRequestKeys.insert(mSupportedPhysicalRequestKeys.begin(),
+                physicalKeysEntry.data.i32,
+                physicalKeysEntry.data.i32 + physicalKeysEntry.count);
+    }
+
     return OK;
 }
 
@@ -291,6 +302,13 @@
 
         CameraDeviceBase::PhysicalCameraSettingsList physicalSettingsList;
         for (const auto& it : request.mPhysicalCameraSettings) {
+            if (it.settings.isEmpty()) {
+                ALOGE("%s: Camera %s: Sent empty metadata packet. Rejecting request.",
+                        __FUNCTION__, mCameraIdStr.string());
+                return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
+                        "Request settings are empty");
+            }
+
             String8 physicalId(it.id.c_str());
             if (physicalId != mDevice->getId()) {
                 auto found = std::find(requestedPhysicalIds.begin(), requestedPhysicalIds.end(),
@@ -301,24 +319,27 @@
                     return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
                             "Invalid physical camera id");
                 }
+
+                if (!mSupportedPhysicalRequestKeys.empty()) {
+                    // Filter out any unsupported physical request keys.
+                    CameraMetadata filteredParams(mSupportedPhysicalRequestKeys.size());
+                    camera_metadata_t *meta = const_cast<camera_metadata_t *>(
+                            filteredParams.getAndLock());
+                    set_camera_metadata_vendor_id(meta, mDevice->getVendorTagId());
+                    filteredParams.unlock(meta);
+
+                    for (const auto& keyIt : mSupportedPhysicalRequestKeys) {
+                        camera_metadata_ro_entry entry = it.settings.find(keyIt);
+                        if (entry.count > 0) {
+                            filteredParams.update(entry);
+                        }
+                    }
+
+                    physicalSettingsList.push_back({it.id, filteredParams});
+                }
+            } else {
+                physicalSettingsList.push_back({it.id, it.settings});
             }
-
-            CameraMetadata metadata(it.settings);
-            if (metadata.isEmpty()) {
-                ALOGE("%s: Camera %s: Sent empty metadata packet. Rejecting request.",
-                        __FUNCTION__, mCameraIdStr.string());
-                return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
-                        "Request settings are empty");
-            }
-
-            physicalSettingsList.push_back({it.id, metadata});
-        }
-
-        if (streaming && (physicalSettingsList.size() > 1)) {
-            ALOGE("%s: Camera %s: Individual physical camera settings are not supported in "
-                    "streaming requests. Rejecting request.", __FUNCTION__, mCameraIdStr.string());
-            return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
-                    "Streaming request contains individual physical requests");
         }
 
         if (!enforceRequestPermissions(physicalSettingsList.begin()->metadata)) {
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.h b/services/camera/libcameraservice/api2/CameraDeviceClient.h
index 435c99d..f1cd00c 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.h
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.h
@@ -221,6 +221,8 @@
     static const int32_t FRAME_PROCESSOR_LISTENER_MIN_ID = 0;
     static const int32_t FRAME_PROCESSOR_LISTENER_MAX_ID = 0x7fffffffL;
 
+    std::vector<int32_t> mSupportedPhysicalRequestKeys;
+
     template<typename TProviderPtr>
     status_t      initializeImpl(TProviderPtr providerPtr);
 
diff --git a/services/camera/libcameraservice/common/CameraDeviceBase.h b/services/camera/libcameraservice/common/CameraDeviceBase.h
index 7956be5..ad83c3d 100644
--- a/services/camera/libcameraservice/common/CameraDeviceBase.h
+++ b/services/camera/libcameraservice/common/CameraDeviceBase.h
@@ -55,6 +55,11 @@
      */
     virtual const String8& getId() const = 0;
 
+    /**
+     * The device vendor tag ID
+     */
+    virtual metadata_vendor_id_t getVendorTagId() const = 0;
+
     virtual status_t initialize(sp<CameraProviderManager> manager) = 0;
     virtual status_t disconnect() = 0;
 
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index 324201b..7dba20d 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -3864,21 +3864,27 @@
         if (hidlSession_3_4 != nullptr) {
             captureRequests_3_4[i].physicalCameraSettings.resize(request->num_physcam_settings);
             for (size_t j = 0; j < request->num_physcam_settings; j++) {
-                size_t settingsSize = get_camera_metadata_size(request->physcam_settings[j]);
-                if (mRequestMetadataQueue != nullptr && mRequestMetadataQueue->write(
-                            reinterpret_cast<const uint8_t*>(request->physcam_settings[j]),
-                            settingsSize)) {
-                    captureRequests_3_4[i].physicalCameraSettings[j].settings.resize(0);
-                    captureRequests_3_4[i].physicalCameraSettings[j].fmqSettingsSize = settingsSize;
-                } else {
-                    if (mRequestMetadataQueue != nullptr) {
-                        ALOGW("%s: couldn't utilize fmq, fallback to hwbinder", __FUNCTION__);
+                if (request->physcam_settings != nullptr) {
+                    size_t settingsSize = get_camera_metadata_size(request->physcam_settings[j]);
+                    if (mRequestMetadataQueue != nullptr && mRequestMetadataQueue->write(
+                                reinterpret_cast<const uint8_t*>(request->physcam_settings[j]),
+                                settingsSize)) {
+                        captureRequests_3_4[i].physicalCameraSettings[j].settings.resize(0);
+                        captureRequests_3_4[i].physicalCameraSettings[j].fmqSettingsSize =
+                            settingsSize;
+                    } else {
+                        if (mRequestMetadataQueue != nullptr) {
+                            ALOGW("%s: couldn't utilize fmq, fallback to hwbinder", __FUNCTION__);
+                        }
+                        captureRequests_3_4[i].physicalCameraSettings[j].settings.setToExternal(
+                                reinterpret_cast<uint8_t*>(const_cast<camera_metadata_t*>(
+                                        request->physcam_settings[j])),
+                                get_camera_metadata_size(request->physcam_settings[j]));
+                        captureRequests_3_4[i].physicalCameraSettings[j].fmqSettingsSize = 0u;
                     }
-                    captureRequests_3_4[i].physicalCameraSettings[j].settings.setToExternal(
-                            reinterpret_cast<uint8_t*>(const_cast<camera_metadata_t*>(
-                                    request->physcam_settings[j])),
-                            get_camera_metadata_size(request->physcam_settings[j]));
+                } else {
                     captureRequests_3_4[i].physicalCameraSettings[j].fmqSettingsSize = 0u;
+                    captureRequests_3_4[i].physicalCameraSettings[j].settings.resize(0);
                 }
                 captureRequests_3_4[i].physicalCameraSettings[j].physicalCameraId =
                     request->physcam_id[j];
@@ -4716,7 +4722,8 @@
         mPrevTriggers = triggerCount;
 
         // If the request is the same as last, or we had triggers last time
-        if (mPrevRequest != captureRequest || triggersMixedIn) {
+        bool newRequest = mPrevRequest != captureRequest || triggersMixedIn;
+        if (newRequest) {
             /**
              * HAL workaround:
              * Insert a dummy trigger ID if a trigger is set but no trigger ID is
@@ -4761,14 +4768,20 @@
         if (captureRequest->mSettingsList.size() > 1) {
             halRequest->num_physcam_settings = captureRequest->mSettingsList.size() - 1;
             halRequest->physcam_id = new const char* [halRequest->num_physcam_settings];
-            halRequest->physcam_settings =
-                new const camera_metadata* [halRequest->num_physcam_settings];
+            if (newRequest) {
+                halRequest->physcam_settings =
+                    new const camera_metadata* [halRequest->num_physcam_settings];
+            } else {
+                halRequest->physcam_settings = nullptr;
+            }
             auto it = ++captureRequest->mSettingsList.begin();
             size_t i = 0;
             for (; it != captureRequest->mSettingsList.end(); it++, i++) {
                 halRequest->physcam_id[i] = it->cameraId.c_str();
-                it->metadata.sort();
-                halRequest->physcam_settings[i] = it->metadata.getAndLock();
+                if (newRequest) {
+                    it->metadata.sort();
+                    halRequest->physcam_settings[i] = it->metadata.getAndLock();
+                }
             }
         }
 
diff --git a/services/camera/libcameraservice/device3/Camera3Device.h b/services/camera/libcameraservice/device3/Camera3Device.h
index 12cb6b4..7faa6e5 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.h
+++ b/services/camera/libcameraservice/device3/Camera3Device.h
@@ -93,6 +93,8 @@
 
     const String8& getId() const override;
 
+    metadata_vendor_id_t getVendorTagId() const override { return mVendorTagId; }
+
     // Transitions to idle state on success.
     status_t initialize(sp<CameraProviderManager> manager) override;
     status_t disconnect() override;