Camera: Support querying session config with parameters

Existing isSessionConfigurationSupported doesn't consider session
parameters. However, many features are modeled as a session parameters.

Add a new API to query session configuration support considring session
parameters.

Test: Camera CTS
Bug: 309627704
Change-Id: If64d878cb0052c0f78db277ebe605d36197eb618
diff --git a/services/camera/libcameraservice/utils/SessionConfigurationUtils.cpp b/services/camera/libcameraservice/utils/SessionConfigurationUtils.cpp
index f7257e3..3be8e15 100644
--- a/services/camera/libcameraservice/utils/SessionConfigurationUtils.cpp
+++ b/services/camera/libcameraservice/utils/SessionConfigurationUtils.cpp
@@ -34,6 +34,7 @@
 using android::camera3::OutputStreamInfo;
 using android::camera3::OutputStreamInfo;
 using android::hardware::camera2::ICameraDeviceUser;
+using aidl::android::hardware::camera::device::RequestTemplate;
 
 namespace android {
 namespace camera3 {
@@ -682,7 +683,8 @@
         bool isCompositeJpegRDisabled,
         metadataGetter getMetadata, const std::vector<std::string> &physicalCameraIds,
         aidl::android::hardware::camera::device::StreamConfiguration &streamConfiguration,
-        bool overrideForPerfClass, bool *earlyExit) {
+        bool overrideForPerfClass, metadata_vendor_id_t vendorTagId,
+        bool checkSessionParams, bool *earlyExit) {
     using SensorPixelMode = aidl::android::hardware::camera::metadata::SensorPixelMode;
     auto operatingMode = sessionConfiguration.getOperatingMode();
     binder::Status res = checkOperatingMode(operatingMode, deviceInfo,
@@ -875,6 +877,21 @@
             }
         }
     }
+
+    if (checkSessionParams) {
+        const CameraMetadata &deviceInfo = getMetadata(logicalCameraId,
+                /*overrideForPerfClass*/false);
+        CameraMetadata filteredParams;
+
+        filterParameters(sessionConfiguration.getSessionParameters(), deviceInfo,
+                vendorTagId, filteredParams);
+
+        camera_metadata_t* metadata = const_cast<camera_metadata_t*>(filteredParams.getAndLock());
+        uint8_t *metadataP = reinterpret_cast<uint8_t*>(metadata);
+        streamConfiguration.sessionParams.metadata.assign(metadataP,
+                metadataP + get_camera_metadata_size(metadata));
+    }
+
     return binder::Status::ok();
 }
 
@@ -1049,6 +1066,92 @@
     return targetSdkVersion >= SDK_VERSION_S && isPerfClassPrimaryCamera;
 }
 
+binder::Status mapRequestTemplateFromClient(const std::string& cameraId, int templateId,
+        camera_request_template_t* tempId /*out*/) {
+    binder::Status ret = binder::Status::ok();
+
+    if (tempId == nullptr) {
+        ret = STATUS_ERROR_FMT(CameraService::ERROR_ILLEGAL_ARGUMENT,
+                "Camera %s: Invalid template argument", cameraId.c_str());
+        return ret;
+    }
+    switch(templateId) {
+        case ICameraDeviceUser::TEMPLATE_PREVIEW:
+            *tempId = camera_request_template_t::CAMERA_TEMPLATE_PREVIEW;
+            break;
+        case ICameraDeviceUser::TEMPLATE_RECORD:
+            *tempId = camera_request_template_t::CAMERA_TEMPLATE_VIDEO_RECORD;
+            break;
+        case ICameraDeviceUser::TEMPLATE_STILL_CAPTURE:
+            *tempId = camera_request_template_t::CAMERA_TEMPLATE_STILL_CAPTURE;
+            break;
+        case ICameraDeviceUser::TEMPLATE_VIDEO_SNAPSHOT:
+            *tempId = camera_request_template_t::CAMERA_TEMPLATE_VIDEO_SNAPSHOT;
+            break;
+        case ICameraDeviceUser::TEMPLATE_ZERO_SHUTTER_LAG:
+            *tempId = camera_request_template_t::CAMERA_TEMPLATE_ZERO_SHUTTER_LAG;
+            break;
+        case ICameraDeviceUser::TEMPLATE_MANUAL:
+            *tempId = camera_request_template_t::CAMERA_TEMPLATE_MANUAL;
+            break;
+        default:
+            ret = STATUS_ERROR_FMT(CameraService::ERROR_ILLEGAL_ARGUMENT,
+                    "Camera %s: Template ID %d is invalid or not supported",
+                    cameraId.c_str(), templateId);
+            return ret;
+    }
+
+    return ret;
+}
+
+status_t mapRequestTemplateToAidl(camera_request_template_t templateId,
+        RequestTemplate* id /*out*/) {
+    switch (templateId) {
+        case CAMERA_TEMPLATE_PREVIEW:
+            *id = RequestTemplate::PREVIEW;
+            break;
+        case CAMERA_TEMPLATE_STILL_CAPTURE:
+            *id = RequestTemplate::STILL_CAPTURE;
+            break;
+        case CAMERA_TEMPLATE_VIDEO_RECORD:
+            *id = RequestTemplate::VIDEO_RECORD;
+            break;
+        case CAMERA_TEMPLATE_VIDEO_SNAPSHOT:
+            *id = RequestTemplate::VIDEO_SNAPSHOT;
+            break;
+        case CAMERA_TEMPLATE_ZERO_SHUTTER_LAG:
+            *id = RequestTemplate::ZERO_SHUTTER_LAG;
+            break;
+        case CAMERA_TEMPLATE_MANUAL:
+            *id = RequestTemplate::MANUAL;
+            break;
+        default:
+            // Unknown template ID, or this HAL is too old to support it
+            return BAD_VALUE;
+    }
+    return OK;
+}
+
+void filterParameters(const CameraMetadata& src, const CameraMetadata& deviceInfo,
+        int vendorTagId, CameraMetadata& dst) {
+    const CameraMetadata params(src);
+    camera_metadata_ro_entry_t availableSessionKeys = deviceInfo.find(
+            ANDROID_REQUEST_AVAILABLE_SESSION_KEYS);
+    CameraMetadata filteredParams(availableSessionKeys.count);
+    camera_metadata_t *meta = const_cast<camera_metadata_t *>(
+            filteredParams.getAndLock());
+    set_camera_metadata_vendor_id(meta, vendorTagId);
+    filteredParams.unlock(meta);
+    for (size_t i = 0; i < availableSessionKeys.count; i++) {
+        camera_metadata_ro_entry entry = params.find(
+                availableSessionKeys.data.i32[i]);
+        if (entry.count > 0) {
+            filteredParams.update(entry);
+        }
+    }
+    dst = std::move(filteredParams);
+}
+
 } // namespace SessionConfigurationUtils
 } // namespace camera3
 } // namespace android
diff --git a/services/camera/libcameraservice/utils/SessionConfigurationUtils.h b/services/camera/libcameraservice/utils/SessionConfigurationUtils.h
index 79d80ea..29e3eca 100644
--- a/services/camera/libcameraservice/utils/SessionConfigurationUtils.h
+++ b/services/camera/libcameraservice/utils/SessionConfigurationUtils.h
@@ -48,6 +48,17 @@
 namespace android {
 namespace camera3 {
 
+typedef enum camera_request_template {
+    CAMERA_TEMPLATE_PREVIEW = 1,
+    CAMERA_TEMPLATE_STILL_CAPTURE = 2,
+    CAMERA_TEMPLATE_VIDEO_RECORD = 3,
+    CAMERA_TEMPLATE_VIDEO_SNAPSHOT = 4,
+    CAMERA_TEMPLATE_ZERO_SHUTTER_LAG = 5,
+    CAMERA_TEMPLATE_MANUAL = 6,
+    CAMERA_TEMPLATE_COUNT,
+    CAMERA_VENDOR_TEMPLATE_START = 0x40000000
+} camera_request_template_t;
+
 typedef std::function<CameraMetadata (const std::string &, bool overrideForPerfClass)>
         metadataGetter;
 
@@ -144,7 +155,8 @@
     bool isCompositeJpegRDisabled, metadataGetter getMetadata,
     const std::vector<std::string> &physicalCameraIds,
     aidl::android::hardware::camera::device::StreamConfiguration &streamConfiguration,
-    bool overrideForPerfClass, bool *earlyExit);
+    bool overrideForPerfClass, metadata_vendor_id_t vendorTagId,
+    bool checkSessionParams, bool *earlyExit);
 
 StreamConfigurationPair getStreamConfigurationPair(const CameraMetadata &metadata);
 
@@ -157,6 +169,16 @@
         const std::set<std::string>& perfClassPrimaryCameraIds, const std::string& cameraId,
         int32_t targetSdkVersion);
 
+// Utility method that maps AIDL request templates.
+binder::Status mapRequestTemplateFromClient(const std::string& cameraId, int templateId,
+        camera_request_template_t* tempId /*out*/);
+
+status_t mapRequestTemplateToAidl(camera_request_template_t templateId,
+        aidl::android::hardware::camera::device::RequestTemplate* tempId /*out*/);
+
+void filterParameters(const CameraMetadata& src, const CameraMetadata& deviceInfo,
+        int vendorTagId, CameraMetadata& dst);
+
 constexpr int32_t MAX_SURFACES_PER_STREAM = 4;
 
 constexpr int32_t ROUNDING_WIDTH_CAP = 1920;
diff --git a/services/camera/libcameraservice/utils/SessionConfigurationUtilsHidl.cpp b/services/camera/libcameraservice/utils/SessionConfigurationUtilsHidl.cpp
index cf93d3b..bf8ea84 100644
--- a/services/camera/libcameraservice/utils/SessionConfigurationUtilsHidl.cpp
+++ b/services/camera/libcameraservice/utils/SessionConfigurationUtilsHidl.cpp
@@ -108,11 +108,12 @@
         const std::string &logicalCameraId, const CameraMetadata &deviceInfo,
         metadataGetter getMetadata, const std::vector<std::string> &physicalCameraIds,
         hardware::camera::device::V3_7::StreamConfiguration &streamConfiguration,
-        bool overrideForPerfClass, bool *earlyExit) {
+        bool overrideForPerfClass, metadata_vendor_id_t vendorTagId, bool *earlyExit) {
     aidl::android::hardware::camera::device::StreamConfiguration aidlStreamConfiguration;
     auto ret = convertToHALStreamCombination(sessionConfiguration, logicalCameraId, deviceInfo,
             false /*isCompositeJpegRDisabled*/, getMetadata, physicalCameraIds,
-            aidlStreamConfiguration, overrideForPerfClass, earlyExit);
+            aidlStreamConfiguration, overrideForPerfClass, vendorTagId,
+            /*checkSessionParams*/false, earlyExit);
     if (!ret.isOk()) {
         return ret;
     }
diff --git a/services/camera/libcameraservice/utils/SessionConfigurationUtilsHidl.h b/services/camera/libcameraservice/utils/SessionConfigurationUtilsHidl.h
index eae2e30..bc37470 100644
--- a/services/camera/libcameraservice/utils/SessionConfigurationUtilsHidl.h
+++ b/services/camera/libcameraservice/utils/SessionConfigurationUtilsHidl.h
@@ -37,7 +37,8 @@
         const std::string &cameraId, const CameraMetadata &deviceInfo,
         metadataGetter getMetadata, const std::vector<std::string> &physicalCameraIds,
         hardware::camera::device::V3_7::StreamConfiguration &streamConfiguration,
-        bool overrideForPerfClass, bool *earlyExit);
+        bool overrideForPerfClass, metadata_vendor_id_t vendorTagId,
+        bool *earlyExit);
 
 // Utility function to convert a V3_7::StreamConfiguration to
 // V3_4::StreamConfiguration. Return false if the original V3_7 configuration cannot