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/camera/aidl/android/hardware/ICameraService.aidl b/camera/aidl/android/hardware/ICameraService.aidl
index 409a930..8078cea 100644
--- a/camera/aidl/android/hardware/ICameraService.aidl
+++ b/camera/aidl/android/hardware/ICameraService.aidl
@@ -22,6 +22,7 @@
 import android.hardware.camera2.ICameraDeviceCallbacks;
 import android.hardware.camera2.ICameraInjectionCallback;
 import android.hardware.camera2.ICameraInjectionSession;
+import android.hardware.camera2.params.SessionConfiguration;
 import android.hardware.camera2.params.VendorTagDescriptor;
 import android.hardware.camera2.params.VendorTagDescriptorCache;
 import android.hardware.camera2.utils.ConcurrentCameraIdCombination;
@@ -261,4 +262,18 @@
     const int DEVICE_STATE_FOLDED = 4;
     const int DEVICE_STATE_LAST_FRAMEWORK_BIT = 0x80000000; // 1 << 31;
 
+    // Create a CaptureRequest metadata based on template id
+    CameraMetadataNative createDefaultRequest(@utf8InCpp String cameraId, int templateId);
+
+    /**
+      * Check whether a particular session configuration with optional session parameters
+      * has camera device support.
+      *
+      * @param cameraId The camera id to query session configuration on
+      * @param sessionConfiguration Specific session configuration to be verified.
+      * @return true  - in case the stream combination is supported.
+      *         false - in case there is no device support.
+      */
+    boolean isSessionConfigurationWithParametersSupported(@utf8InCpp String cameraId,
+            in SessionConfiguration sessionConfiguration);
 }
diff --git a/camera/camera2/SessionConfiguration.cpp b/camera/camera2/SessionConfiguration.cpp
index 7cf6087..2f1f22d 100644
--- a/camera/camera2/SessionConfiguration.cpp
+++ b/camera/camera2/SessionConfiguration.cpp
@@ -22,10 +22,13 @@
 
 #include <camera/camera2/SessionConfiguration.h>
 #include <camera/camera2/OutputConfiguration.h>
+#include <com_android_internal_camera_flags.h>
 #include <binder/Parcel.h>
 
 namespace android {
 
+namespace flags = com::android::internal::camera::flags;
+
 status_t SessionConfiguration::readFromParcel(const android::Parcel* parcel) {
     status_t err = OK;
     int operatingMode = 0;
@@ -67,6 +70,22 @@
         return err;
     }
 
+    bool hasSessionParameters = false;
+    CameraMetadata settings;
+    if (flags::feature_combination_query()) {
+        if ((err = parcel->readBool(&hasSessionParameters)) != OK) {
+            ALOGE("%s: Failed to read hasSessionParameters flag from parcel", __FUNCTION__);
+            return err;
+        }
+
+        if (hasSessionParameters) {
+            if ((err = settings.readFromParcel(parcel)) != OK) {
+                ALOGE("%s: Failed to read metadata flag from parcel", __FUNCTION__);
+                return err;
+            }
+        }
+    }
+
     mOperatingMode = operatingMode;
     mInputWidth = inputWidth;
     mInputHeight = inputHeight;
@@ -75,7 +94,10 @@
     for (auto& stream : outputStreams) {
         mOutputStreams.push_back(stream);
     }
-
+    if (flags::feature_combination_query()) {
+        mHasSessionParameters = hasSessionParameters;
+        mSessionParameters = std::move(settings);
+    }
 
     return err;
 }
@@ -103,6 +125,16 @@
     err = parcel->writeParcelableVector(mOutputStreams);
     if (err != OK) return err;
 
+    if (flags::feature_combination_query()) {
+        err = parcel->writeBool(mHasSessionParameters);
+        if (err != OK) return err;
+
+        if (mHasSessionParameters) {
+            err = mSessionParameters.writeToParcel(parcel);
+            if (err != OK) return err;
+        }
+    }
+
     return OK;
 }
 
diff --git a/camera/camera_platform.aconfig b/camera/camera_platform.aconfig
index f8dfe34..f7deda1 100644
--- a/camera/camera_platform.aconfig
+++ b/camera/camera_platform.aconfig
@@ -13,6 +13,14 @@
      description: "Introduces a new concert mode camera extension type"
      bug: "297083874"
 }
+
+flag {
+     namespace: "camera_platform"
+     name: "feature_combination_query"
+     description: "Query feature combination support and session specific characteristics"
+     bug: "309627704"
+}
+
 flag {
      namespace: "camera_platform"
      name: "log_ultrawide_usage"
diff --git a/camera/include/camera/camera2/SessionConfiguration.h b/camera/include/camera/camera2/SessionConfiguration.h
index 29913f6..120bf9e 100644
--- a/camera/include/camera/camera2/SessionConfiguration.h
+++ b/camera/include/camera/camera2/SessionConfiguration.h
@@ -18,6 +18,7 @@
 #define ANDROID_HARDWARE_CAMERA2_SESSIONCONFIGURATION_H
 
 #include <binder/Parcelable.h>
+#include <camera/CameraMetadata.h>
 
 namespace android {
 
@@ -39,6 +40,8 @@
     int getInputFormat() const { return mInputFormat; }
     int getOperatingMode() const { return mOperatingMode; }
     bool inputIsMultiResolution() const { return mInputIsMultiResolution; }
+    bool hasSessionParameters() const { return mHasSessionParameters; }
+    const CameraMetadata& getSessionParameters() const { return mSessionParameters; }
 
     virtual status_t writeToParcel(android::Parcel* parcel) const override;
     virtual status_t readFromParcel(const android::Parcel* parcel) override;
@@ -111,6 +114,8 @@
     std::vector<OutputConfiguration> mOutputStreams;
     int                              mInputWidth, mInputHeight, mInputFormat, mOperatingMode;
     bool                             mInputIsMultiResolution = false;
+    bool                             mHasSessionParameters = false;
+    CameraMetadata                   mSessionParameters;
 };
 } // namespace params
 } // namespace camera2
diff --git a/services/camera/libcameraservice/Android.bp b/services/camera/libcameraservice/Android.bp
index f25bca3..4883a09 100644
--- a/services/camera/libcameraservice/Android.bp
+++ b/services/camera/libcameraservice/Android.bp
@@ -106,7 +106,7 @@
         "android.hardware.camera.provider@2.5",
         "android.hardware.camera.provider@2.6",
         "android.hardware.camera.provider@2.7",
-        "android.hardware.camera.provider-V2-ndk",
+        "android.hardware.camera.provider-V3-ndk",
         "libaidlcommonsupport",
         "libbinderthreadstateutils",
         "libcameraservice_device_independent",
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index 8add05e..feb9c75 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -84,6 +84,7 @@
 #include "utils/TagMonitor.h"
 #include "utils/CameraThreadState.h"
 #include "utils/CameraServiceProxyWrapper.h"
+#include "utils/SessionConfigurationUtils.h"
 
 namespace {
     const char* kPermissionServiceName = "permission";
@@ -95,8 +96,10 @@
 
 namespace android {
 
-using binder::Status;
 using namespace camera3;
+using namespace camera3::SessionConfigurationUtils;
+
+using binder::Status;
 using frameworks::cameraservice::service::V2_0::implementation::HidlCameraService;
 using frameworks::cameraservice::service::implementation::AidlCameraService;
 using hardware::ICamera;
@@ -861,6 +864,136 @@
     return Status::ok();
 }
 
+Status CameraService::createDefaultRequest(const std::string& unresolvedCameraId, int templateId,
+        /* out */
+        hardware::camera2::impl::CameraMetadataNative* request) {
+    ATRACE_CALL();
+
+    if (!flags::feature_combination_query()) {
+        return STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION,
+                "Camera subsystem doesn't support this method!");
+    }
+    if (!mInitialized) {
+        ALOGE("%s: Camera subsystem is not available", __FUNCTION__);
+        logServiceError("Camera subsystem is not available", ERROR_DISCONNECTED);
+        return STATUS_ERROR(ERROR_DISCONNECTED, "Camera subsystem is not available");
+    }
+
+    const std::string cameraId = resolveCameraId(unresolvedCameraId,
+            CameraThreadState::getCallingUid());
+
+    binder::Status res;
+    if (request == nullptr) {
+        res = STATUS_ERROR_FMT(CameraService::ERROR_INVALID_OPERATION,
+                "Camera %s: Error creating default request", cameraId.c_str());
+        return res;
+    }
+    camera_request_template_t tempId = camera_request_template_t::CAMERA_TEMPLATE_COUNT;
+    res = SessionConfigurationUtils::mapRequestTemplateFromClient(
+            cameraId, templateId, &tempId);
+    if (!res.isOk()) {
+        ALOGE("%s: Camera %s: failed to map request Template %d",
+                __FUNCTION__, cameraId.c_str(), templateId);
+        return res;
+    }
+
+    if (shouldRejectSystemCameraConnection(cameraId)) {
+        return STATUS_ERROR_FMT(ERROR_INVALID_OPERATION, "Unable to create default"
+                "request for system only device %s: ", cameraId.c_str());
+    }
+
+    // Check for camera permissions
+    if (!hasCameraPermissions()) {
+        return STATUS_ERROR(ERROR_PERMISSION_DENIED,
+                "android.permission.CAMERA needed to call"
+                "createDefaultRequest");
+    }
+
+    CameraMetadata metadata;
+    status_t err = mCameraProviderManager->createDefaultRequest(cameraId, tempId, &metadata);
+    if (err == OK) {
+        request->swap(metadata);
+    } else if (err == BAD_VALUE) {
+        res = STATUS_ERROR_FMT(CameraService::ERROR_ILLEGAL_ARGUMENT,
+                "Camera %s: Template ID %d is invalid or not supported: %s (%d)",
+                cameraId.c_str(), templateId, strerror(-err), err);
+    } else {
+        res = STATUS_ERROR_FMT(CameraService::ERROR_INVALID_OPERATION,
+                "Camera %s: Error creating default request for template %d: %s (%d)",
+                cameraId.c_str(), templateId, strerror(-err), err);
+    }
+    return res;
+}
+
+Status CameraService::isSessionConfigurationWithParametersSupported(
+        const std::string& unresolvedCameraId,
+        const SessionConfiguration& sessionConfiguration,
+        /*out*/
+        bool* supported) {
+    ATRACE_CALL();
+
+    if (!flags::feature_combination_query()) {
+        return STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION,
+                "Camera subsystem doesn't support this method!");
+    }
+    if (!mInitialized) {
+        ALOGE("%s: Camera HAL couldn't be initialized", __FUNCTION__);
+        logServiceError("Camera subsystem is not available", ERROR_DISCONNECTED);
+        return STATUS_ERROR(ERROR_DISCONNECTED, "Camera subsystem is not available");
+    }
+
+    const std::string cameraId = resolveCameraId(unresolvedCameraId,
+            CameraThreadState::getCallingUid());
+    if (supported == nullptr) {
+        std::string msg = fmt::sprintf("Camera %s: Invalid 'support' input!",
+                unresolvedCameraId.c_str());
+        ALOGE("%s: %s", __FUNCTION__, msg.c_str());
+        return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.c_str());
+    }
+
+    if (shouldRejectSystemCameraConnection(cameraId)) {
+        return STATUS_ERROR_FMT(ERROR_INVALID_OPERATION, "Unable to query "
+                "session configuration with parameters support for system only device %s: ",
+                cameraId.c_str());
+    }
+
+    // Check for camera permissions
+    if (!hasCameraPermissions()) {
+        return STATUS_ERROR(ERROR_PERMISSION_DENIED,
+                "android.permission.CAMERA needed to call"
+                "isSessionConfigurationWithParametersSupported");
+    }
+
+    *supported = false;
+    status_t ret = mCameraProviderManager->isSessionConfigurationSupported(cameraId.c_str(),
+            sessionConfiguration, /*mOverrideForPerfClass*/false, /*checkSessionParams*/true,
+            supported);
+    binder::Status res;
+    switch (ret) {
+        case OK:
+            // Expected, do nothing.
+            break;
+        case INVALID_OPERATION: {
+                std::string msg = fmt::sprintf(
+                        "Camera %s: Session configuration query not supported!",
+                        cameraId.c_str());
+                ALOGD("%s: %s", __FUNCTION__, msg.c_str());
+                res = STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION, msg.c_str());
+            }
+
+            break;
+        default: {
+                std::string msg = fmt::sprintf( "Camera %s: Error: %s (%d)", cameraId.c_str(),
+                        strerror(-ret), ret);
+                ALOGE("%s: %s", __FUNCTION__, msg.c_str());
+                res = STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
+                        msg.c_str());
+            }
+    }
+
+    return res;
+}
+
 Status CameraService::parseCameraIdRemapping(
         const hardware::CameraIdRemapping& cameraIdRemapping,
         /* out */ TCameraIdRemapping* cameraIdRemappingMap) {
@@ -3042,6 +3175,22 @@
     return Status::ok();
 }
 
+bool CameraService::hasCameraPermissions() const {
+    int callingPid = CameraThreadState::getCallingPid();
+    int callingUid = CameraThreadState::getCallingUid();
+    AttributionSourceState attributionSource{};
+    attributionSource.pid = callingPid;
+    attributionSource.uid = callingUid;
+    bool res = checkPermission(std::string(), sCameraPermission,
+            attributionSource, std::string(), AppOpsManager::OP_NONE);
+
+    bool hasPermission = ((callingPid == getpid()) || res);
+    if (!hasPermission) {
+        ALOGE("%s: pid %d doesn't have camera permissions", __FUNCTION__, callingPid);
+    }
+    return hasPermission;
+}
+
 Status CameraService::isConcurrentSessionConfigurationSupported(
         const std::vector<CameraIdAndSessionConfiguration>& cameraIdsAndSessionConfigurations,
         int targetSdkVersion, /*out*/bool* isSupported) {
@@ -3057,15 +3206,7 @@
     }
 
     // Check for camera permissions
-    int callingPid = CameraThreadState::getCallingPid();
-    int callingUid = CameraThreadState::getCallingUid();
-    AttributionSourceState attributionSource{};
-    attributionSource.pid = callingPid;
-    attributionSource.uid = callingUid;
-    bool checkPermissionForCamera = checkPermission(std::string(),
-                sCameraPermission, attributionSource, std::string(), AppOpsManager::OP_NONE);
-    if ((callingPid != getpid()) && !checkPermissionForCamera) {
-        ALOGE("%s: pid %d doesn't have camera permissions", __FUNCTION__, callingPid);
+    if (!hasCameraPermissions()) {
         return STATUS_ERROR(ERROR_PERMISSION_DENIED,
                 "android.permission.CAMERA needed to call"
                 "isConcurrentSessionConfigurationSupported");
diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h
index 6819136..cabac17 100644
--- a/services/camera/libcameraservice/CameraService.h
+++ b/services/camera/libcameraservice/CameraService.h
@@ -234,6 +234,16 @@
     virtual binder::Status remapCameraIds(const hardware::CameraIdRemapping&
         cameraIdRemapping);
 
+    virtual binder::Status createDefaultRequest(const std::string& cameraId, int templateId,
+            /*out*/
+            hardware::camera2::impl::CameraMetadataNative* request);
+
+    virtual binder::Status isSessionConfigurationWithParametersSupported(
+            const std::string& cameraId,
+            const SessionConfiguration& sessionConfiguration,
+            /*out*/
+            bool* supported);
+
     // Extra permissions checks
     virtual status_t    onTransact(uint32_t code, const Parcel& data,
                                    Parcel* reply, uint32_t flags);
@@ -662,6 +672,7 @@
     bool hasPermissionsForCameraHeadlessSystemUser(const std::string& cameraId, int callingPid,
             int callingUid) const;
 
+    bool hasCameraPermissions() const;
    /**
      * Typesafe version of device status, containing both the HAL-layer and the service interface-
      * layer values.
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
index 28f7054..095d425 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
@@ -742,13 +742,6 @@
         return STATUS_ERROR(CameraService::ERROR_DISCONNECTED, "Camera device no longer alive");
     }
 
-    auto operatingMode = sessionConfiguration.getOperatingMode();
-    res = SessionConfigurationUtils::checkOperatingMode(operatingMode, mDevice->info(),
-            mCameraIdStr);
-    if (!res.isOk()) {
-        return res;
-    }
-
     if (status == nullptr) {
         std::string msg = fmt::sprintf( "Camera %s: Invalid status!", mCameraIdStr.c_str());
         ALOGE("%s: %s", __FUNCTION__, msg.c_str());
@@ -756,11 +749,9 @@
     }
 
     *status = false;
-    camera3::metadataGetter getMetadata = [this](const std::string &id,
-            bool /*overrideForPerfClass*/) {
-          return mDevice->infoPhysical(id);};
     ret = mProviderManager->isSessionConfigurationSupported(mCameraIdStr.c_str(),
-            sessionConfiguration, mOverrideForPerfClass, getMetadata, status);
+            sessionConfiguration, mOverrideForPerfClass, /*checkSessionParams*/false,
+            status);
     switch (ret) {
         case OK:
             // Expected, do nothing.
@@ -1396,7 +1387,9 @@
 
     status_t err;
     camera_request_template_t tempId = camera_request_template_t::CAMERA_TEMPLATE_COUNT;
-    if (!(res = mapRequestTemplate(templateId, &tempId)).isOk()) return res;
+    res = SessionConfigurationUtils::mapRequestTemplateFromClient(
+            mCameraIdStr, templateId, &tempId);
+    if (!res.isOk()) return res;
 
     CameraMetadata metadata;
     if ( (err = mDevice->createDefaultRequest(tempId, &metadata) ) == OK &&
@@ -2245,44 +2238,6 @@
     return CameraUtils::getRotationTransform(staticInfo, mirrorMode, transform);
 }
 
-binder::Status CameraDeviceClient::mapRequestTemplate(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", mCameraIdStr.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",
-                    mCameraIdStr.c_str(), templateId);
-            return ret;
-    }
-
-    return ret;
-}
-
 const CameraMetadata &CameraDeviceClient::getStaticInfo(const std::string &cameraId) {
     if (mDevice->getId() == cameraId) {
         return mDevice->info();
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.h b/services/camera/libcameraservice/api2/CameraDeviceClient.h
index 5dea3aa..b2c9626 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.h
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.h
@@ -312,10 +312,6 @@
             /*out*/SurfaceMap* surfaceMap, /*out*/Vector<int32_t>* streamIds,
             /*out*/int32_t*  currentStreamId);
 
-    // Utility method that maps AIDL request templates.
-    binder::Status mapRequestTemplate(int templateId,
-            camera_request_template_t* tempId /*out*/);
-
     // IGraphicsBufferProducer binder -> Stream ID + Surface ID for output streams
     KeyedVector<sp<IBinder>, StreamSurfaceId> mStreamMap;
 
diff --git a/services/camera/libcameraservice/common/CameraDeviceBase.h b/services/camera/libcameraservice/common/CameraDeviceBase.h
index 01199af..983b2c1 100644
--- a/services/camera/libcameraservice/common/CameraDeviceBase.h
+++ b/services/camera/libcameraservice/common/CameraDeviceBase.h
@@ -35,6 +35,7 @@
 #include "binder/Status.h"
 #include "FrameProducer.h"
 #include "utils/IPCTransport.h"
+#include "utils/SessionConfigurationUtils.h"
 
 #include "CameraOfflineSessionBase.h"
 
@@ -42,17 +43,6 @@
 
 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 enum camera_stream_configuration_mode {
     CAMERA_STREAM_CONFIGURATION_NORMAL_MODE = 0,
     CAMERA_STREAM_CONFIGURATION_CONSTRAINED_HIGH_SPEED_MODE = 1,
diff --git a/services/camera/libcameraservice/common/CameraProviderManager.cpp b/services/camera/libcameraservice/common/CameraProviderManager.cpp
index adcb523..fbb5e1b 100644
--- a/services/camera/libcameraservice/common/CameraProviderManager.cpp
+++ b/services/camera/libcameraservice/common/CameraProviderManager.cpp
@@ -397,7 +397,7 @@
 
 status_t CameraProviderManager::isSessionConfigurationSupported(const std::string& id,
         const SessionConfiguration &configuration, bool overrideForPerfClass,
-        metadataGetter getMetadata, bool *status /*out*/) const {
+        bool checkSessionParams, bool *status /*out*/) const {
     std::lock_guard<std::mutex> lock(mInterfaceMutex);
     auto deviceInfo = findDeviceInfoLocked(id);
     if (deviceInfo == nullptr) {
@@ -405,7 +405,41 @@
     }
 
     return deviceInfo->isSessionConfigurationSupported(configuration,
-            overrideForPerfClass, getMetadata, status);
+            overrideForPerfClass, checkSessionParams, status);
+}
+
+status_t  CameraProviderManager::createDefaultRequest(const std::string& cameraId,
+        camera_request_template_t templateId,
+        CameraMetadata* metadata) const {
+    ATRACE_CALL();
+    if (templateId <= 0 || templateId >= CAMERA_TEMPLATE_COUNT) {
+        return BAD_VALUE;
+    }
+
+    std::lock_guard<std::mutex> lock(mInterfaceMutex);
+    auto deviceInfo = findDeviceInfoLocked(cameraId);
+    if (deviceInfo == nullptr) {
+        return NAME_NOT_FOUND;
+    }
+
+    camera_metadata_t *rawRequest;
+    status_t res = deviceInfo->createDefaultRequest(templateId,
+            &rawRequest);
+
+    if (res == BAD_VALUE) {
+        ALOGI("%s: template %d is not supported on this camera device",
+              __FUNCTION__, templateId);
+        return res;
+    } else if (res != OK) {
+        ALOGE("Unable to construct request template %d: %s (%d)",
+                templateId, strerror(-res), res);
+        return res;
+    }
+
+    set_camera_metadata_vendor_id(rawRequest, deviceInfo->mProviderTagid);
+    metadata->acquire(rawRequest);
+
+    return OK;
 }
 
 status_t CameraProviderManager::getCameraIdIPCTransport(const std::string &id,
@@ -1011,6 +1045,20 @@
     }
 }
 
+CameraMetadata CameraProviderManager::ProviderInfo::DeviceInfo3::deviceInfo(
+        const std::string &id) {
+    if (id.empty()) {
+        return mCameraCharacteristics;
+    } else {
+        if (mPhysicalCameraCharacteristics.find(id) != mPhysicalCameraCharacteristics.end()) {
+            return mPhysicalCameraCharacteristics.at(id);
+        } else {
+            ALOGE("%s: Invalid physical camera id %s", __FUNCTION__, id.c_str());
+            return mCameraCharacteristics;
+        }
+    }
+}
+
 SystemCameraKind CameraProviderManager::ProviderInfo::DeviceInfo3::getSystemCameraKind() {
     camera_metadata_entry_t entryCap;
     entryCap = mCameraCharacteristics.find(ANDROID_REQUEST_AVAILABLE_CAPABILITIES);
@@ -1757,6 +1805,26 @@
     return res;
 }
 
+status_t CameraProviderManager::ProviderInfo::DeviceInfo3::addSessionConfigQueryVersionTag() {
+    sp<ProviderInfo> parentProvider = mParentProvider.promote();
+    if (parentProvider == nullptr) {
+        return DEAD_OBJECT;
+    }
+
+    int versionCode = ANDROID_INFO_SESSION_CONFIGURATION_QUERY_VERSION_UPSIDE_DOWN_CAKE;
+    IPCTransport ipcTransport = parentProvider->getIPCTransport();
+    int deviceVersion = HARDWARE_DEVICE_API_VERSION(mVersion.get_major(), mVersion.get_minor());
+    if (ipcTransport == IPCTransport::AIDL
+            && deviceVersion >= CAMERA_DEVICE_API_VERSION_1_3) {
+        versionCode = ANDROID_INFO_SESSION_CONFIGURATION_QUERY_VERSION_VANILLA_ICE_CREAM;
+    }
+
+    auto& c = mCameraCharacteristics;
+    status_t res = c.update(ANDROID_INFO_SESSION_CONFIGURATION_QUERY_VERSION, &versionCode, 1);
+
+    return res;
+}
+
 status_t CameraProviderManager::ProviderInfo::DeviceInfo3::removeAvailableKeys(
         CameraMetadata& c, const std::vector<uint32_t>& keys, uint32_t keyTag) {
     status_t res = OK;
diff --git a/services/camera/libcameraservice/common/CameraProviderManager.h b/services/camera/libcameraservice/common/CameraProviderManager.h
index fd04854..6142a71 100644
--- a/services/camera/libcameraservice/common/CameraProviderManager.h
+++ b/services/camera/libcameraservice/common/CameraProviderManager.h
@@ -87,6 +87,7 @@
 
 #define CAMERA_DEVICE_API_VERSION_1_0 HARDWARE_DEVICE_API_VERSION(1, 0)
 #define CAMERA_DEVICE_API_VERSION_1_2 HARDWARE_DEVICE_API_VERSION(1, 2)
+#define CAMERA_DEVICE_API_VERSION_1_3 HARDWARE_DEVICE_API_VERSION(1, 3)
 #define CAMERA_DEVICE_API_VERSION_3_0 HARDWARE_DEVICE_API_VERSION(3, 0)
 #define CAMERA_DEVICE_API_VERSION_3_1 HARDWARE_DEVICE_API_VERSION(3, 1)
 #define CAMERA_DEVICE_API_VERSION_3_2 HARDWARE_DEVICE_API_VERSION(3, 2)
@@ -299,12 +300,20 @@
             int targetSdkVersion, bool *isSupported);
 
     std::vector<std::unordered_set<std::string>> getConcurrentCameraIds() const;
+
+    /**
+     * Create a default capture request metadata for a camera and a specific
+     * template.
+     */
+    status_t createDefaultRequest(const std::string& id,
+            camera3::camera_request_template_t templateId,
+            hardware::camera2::impl::CameraMetadataNative* request) const;
     /**
      * Check for device support of specific stream combination.
      */
     status_t isSessionConfigurationSupported(const std::string& id,
             const SessionConfiguration &configuration,
-            bool overrideForPerfClass, camera3::metadataGetter getMetadata,
+            bool overrideForPerfClass, bool checkSessionParams,
             bool *status /*out*/) const;
 
     /**
@@ -619,12 +628,17 @@
             virtual status_t isSessionConfigurationSupported(
                     const SessionConfiguration &/*configuration*/,
                     bool /*overrideForPerfClass*/,
-                    camera3::metadataGetter /*getMetadata*/,
+                    bool /*checkSessionParams*/,
                     bool * /*status*/) {
                 return INVALID_OPERATION;
             }
             virtual status_t filterSmallJpegSizes() = 0;
             virtual void notifyDeviceStateChange(int64_t /*newState*/) {}
+            virtual status_t createDefaultRequest(
+                    camera3::camera_request_template_t /*templateId*/,
+                    camera_metadata_t** /*metadata*/) {
+                return INVALID_OPERATION;
+            }
 
             DeviceInfo(const std::string& name, const metadata_vendor_id_t tagId,
                     const std::string &id, const hardware::hidl_version& version,
@@ -675,10 +689,6 @@
                     bool overrideToPortrait) override;
             virtual status_t getPhysicalCameraCharacteristics(const std::string& physicalCameraId,
                     CameraMetadata *characteristics) const override;
-            virtual status_t isSessionConfigurationSupported(
-                    const SessionConfiguration &configuration, bool /*overrideForPerfClass*/,
-                    camera3::metadataGetter /*getMetadata*/,
-                    bool *status /*out*/) = 0;
             virtual status_t filterSmallJpegSizes() override;
             virtual void notifyDeviceStateChange(
                         int64_t newState) override;
@@ -712,6 +722,7 @@
             status_t addAutoframingTags();
             status_t addPreCorrectionActiveArraySize();
             status_t addReadoutTimestampTag(bool readoutTimestampSupported = true);
+            status_t addSessionConfigQueryVersionTag();
 
             static void getSupportedSizes(const CameraMetadata& ch, uint32_t tag,
                     android_pixel_format_t format,
@@ -736,6 +747,8 @@
                     std::vector<int64_t>* stallDurations,
                     const camera_metadata_entry& halStreamConfigs,
                     const camera_metadata_entry& halStreamDurations);
+
+            CameraMetadata deviceInfo(const std::string &id);
         };
     protected:
         std::string mType;
@@ -887,8 +900,6 @@
             std::vector<std::string>& systemCameraDeviceIds) const;
 
     status_t usbDeviceDetached(const std::string &usbDeviceId);
-    ndk::ScopedAStatus onAidlRegistration(const std::string& in_name,
-            const ::ndk::SpAIBinder& in_binder);
 
     static bool isVirtualCameraHalEnabled();
 };
diff --git a/services/camera/libcameraservice/common/aidl/AidlProviderInfo.cpp b/services/camera/libcameraservice/common/aidl/AidlProviderInfo.cpp
index c2b8bf4..a64c9d7 100644
--- a/services/camera/libcameraservice/common/aidl/AidlProviderInfo.cpp
+++ b/services/camera/libcameraservice/common/aidl/AidlProviderInfo.cpp
@@ -386,7 +386,7 @@
 std::unique_ptr<CameraProviderManager::ProviderInfo::DeviceInfo>
     AidlProviderInfo::initializeDeviceInfo(
         const std::string &name, const metadata_vendor_id_t tagId,
-        const std::string &id, uint16_t minorVersion) {
+        const std::string &id, uint16_t /*minorVersion*/) {
     ::ndk::ScopedAStatus status;
 
     auto cameraInterface = startDeviceInterface(name);
@@ -411,9 +411,18 @@
         conflictName = id;
     }
 
+    int32_t interfaceVersion = 0;
+    status = cameraInterface->getInterfaceVersion(&interfaceVersion);
+    if (!status.isOk()) {
+        ALOGE("%s: Unable to obtain interface version for camera device %s: %s", __FUNCTION__,
+                id.c_str(), status.getMessage());
+        return nullptr;
+    }
+
     return std::unique_ptr<DeviceInfo3>(
-        new AidlDeviceInfo3(name, tagId, id, minorVersion, HalToFrameworkResourceCost(resourceCost),
-                this, mProviderPublicCameraIds, cameraInterface));
+        new AidlDeviceInfo3(name, tagId, id, static_cast<uint16_t>(interfaceVersion),
+                HalToFrameworkResourceCost(resourceCost), this,
+                mProviderPublicCameraIds, cameraInterface));
 }
 
 status_t AidlProviderInfo::reCacheConcurrentStreamingCameraIdsLocked() {
@@ -604,6 +613,14 @@
         mHasFlashUnit = false;
     }
 
+    if (flags::feature_combination_query()) {
+        res = addSessionConfigQueryVersionTag();
+        if (OK != res) {
+            ALOGE("%s: Unable to add sessionConfigurationQueryVersion tag: %s (%d)",
+                    __FUNCTION__, strerror(-res), res);
+        }
+    }
+
     camera_metadata_entry entry =
             mCameraCharacteristics.find(ANDROID_FLASH_INFO_STRENGTH_DEFAULT_LEVEL);
     if (entry.count == 1) {
@@ -766,13 +783,24 @@
 
 status_t AidlProviderInfo::AidlDeviceInfo3::isSessionConfigurationSupported(
         const SessionConfiguration &configuration, bool overrideForPerfClass,
-        camera3::metadataGetter getMetadata, bool *status) {
+        bool checkSessionParams, bool *status) {
+
+    auto operatingMode = configuration.getOperatingMode();
+
+    auto res = SessionConfigurationUtils::checkOperatingMode(operatingMode,
+            mCameraCharacteristics, mId);
+    if (!res.isOk()) {
+        return UNKNOWN_ERROR;
+    }
 
     camera::device::StreamConfiguration streamConfiguration;
     bool earlyExit = false;
+    camera3::metadataGetter getMetadata = [this](const std::string &id,
+            bool /*overrideForPerfClass*/) {return this->deviceInfo(id);};
     auto bRes = SessionConfigurationUtils::convertToHALStreamCombination(configuration,
             mId, mCameraCharacteristics, mCompositeJpegRDisabled, getMetadata,
-            mPhysicalIds, streamConfiguration, overrideForPerfClass, &earlyExit);
+            mPhysicalIds, streamConfiguration, overrideForPerfClass, mProviderTagid,
+            checkSessionParams, &earlyExit);
 
     if (!bRes.isOk()) {
         return UNKNOWN_ERROR;
@@ -790,8 +818,25 @@
         return DEAD_OBJECT;
     }
 
-    ::ndk::ScopedAStatus ret =
-        interface->isStreamCombinationSupported(streamConfiguration, status);
+    ::ndk::ScopedAStatus ret;
+    if (checkSessionParams) {
+        // Only interface version 1_3 or greater supports
+        // isStreamCombinationWIthSettingsSupported.
+        int deviceVersion = HARDWARE_DEVICE_API_VERSION(mVersion.get_major(), mVersion.get_minor());
+        if (deviceVersion < CAMERA_DEVICE_API_VERSION_1_3) {
+            ALOGI("%s: Camera device version (major %d, minor %d) doesn't support querying of "
+                    "session configuration!", __FUNCTION__, mVersion.get_major(),
+                    mVersion.get_minor());
+            return INVALID_OPERATION;
+        }
+        if (flags::feature_combination_query()) {
+            ret = interface->isStreamCombinationWithSettingsSupported(streamConfiguration, status);
+        } else {
+            return INVALID_OPERATION;
+        }
+    } else {
+        ret = interface->isStreamCombinationSupported(streamConfiguration, status);
+    }
     if (!ret.isOk()) {
         *status = false;
         ALOGE("%s: Unexpected binder error: %s", __FUNCTION__, ret.getMessage());
@@ -801,6 +846,60 @@
 
 }
 
+status_t AidlProviderInfo::AidlDeviceInfo3::createDefaultRequest(
+        camera3::camera_request_template_t templateId, camera_metadata_t** metadata) {
+    const std::shared_ptr<camera::device::ICameraDevice> interface =
+            startDeviceInterface();
+
+    if (interface == nullptr) {
+        return DEAD_OBJECT;
+    }
+
+    int deviceVersion = HARDWARE_DEVICE_API_VERSION(mVersion.get_major(), mVersion.get_minor());
+    if (deviceVersion < CAMERA_DEVICE_API_VERSION_1_3) {
+        ALOGI("%s: Camera device minor version 0x%x doesn't support creating "
+                " default request!", __FUNCTION__, mVersion.get_minor());
+        return INVALID_OPERATION;
+    }
+
+    aidl::android::hardware::camera::device::CameraMetadata request;
+
+    using aidl::android::hardware::camera::device::RequestTemplate;
+    RequestTemplate id;
+    status_t res = SessionConfigurationUtils::mapRequestTemplateToAidl(
+            templateId, &id);
+    if (res != OK) {
+        return res;
+    }
+
+    if (!flags::feature_combination_query()) {
+        return INVALID_OPERATION;
+    }
+
+    auto err = interface->constructDefaultRequestSettings(id, &request);
+    if (!err.isOk()) {
+        ALOGE("%s: Transaction error: %s", __FUNCTION__, err.getMessage());
+        return AidlProviderInfo::mapToStatusT(err);
+    }
+    const camera_metadata *r =
+            reinterpret_cast<const camera_metadata_t*>(request.metadata.data());
+    size_t expectedSize = request.metadata.size();
+    int ret = validate_camera_metadata_structure(r, &expectedSize);
+    if (ret == OK || ret == CAMERA_METADATA_VALIDATION_SHIFTED) {
+        *metadata = clone_camera_metadata(r);
+        if (*metadata == nullptr) {
+            ALOGE("%s: Unable to clone camera metadata received from HAL",
+                    __FUNCTION__);
+            res = UNKNOWN_ERROR;
+        }
+    } else {
+        ALOGE("%s: Malformed camera metadata received from HAL", __FUNCTION__);
+        res = UNKNOWN_ERROR;
+    }
+
+    return res;
+}
+
 status_t AidlProviderInfo::convertToAidlHALStreamCombinationAndCameraIdsLocked(
         const std::vector<CameraIdAndSessionConfiguration> &cameraIdsAndSessionConfigs,
         const std::set<std::string>& perfClassPrimaryCameraIds,
@@ -840,7 +939,8 @@
                     cameraId, deviceInfo,
                     mManager->isCompositeJpegRDisabledLocked(cameraId), getMetadata,
                     physicalCameraIds, streamConfiguration,
-                    overrideForPerfClass, &shouldExit);
+                    overrideForPerfClass, mProviderTagid,
+                    /*checkSessionParams*/false, &shouldExit);
         if (!bStatus.isOk()) {
             ALOGE("%s: convertToHALStreamCombination failed", __FUNCTION__);
             return INVALID_OPERATION;
diff --git a/services/camera/libcameraservice/common/aidl/AidlProviderInfo.h b/services/camera/libcameraservice/common/aidl/AidlProviderInfo.h
index 90bc627..cc5101a 100644
--- a/services/camera/libcameraservice/common/aidl/AidlProviderInfo.h
+++ b/services/camera/libcameraservice/common/aidl/AidlProviderInfo.h
@@ -107,8 +107,6 @@
 
     struct AidlDeviceInfo3 : public CameraProviderManager::ProviderInfo::DeviceInfo3 {
 
-        //TODO: fix init
-        const hardware::hidl_version mVersion = hardware::hidl_version{3, 2};
         std::shared_ptr<aidl::android::hardware::camera::device::ICameraDevice>
                 mSavedInterface = nullptr;
 
@@ -129,9 +127,13 @@
 
         virtual status_t isSessionConfigurationSupported(
                 const SessionConfiguration &/*configuration*/,
-                bool overrideForPerfClass, camera3::metadataGetter /*getMetadata*/,
+                bool overrideForPerfClass, bool checkSessionParams,
                 bool *status/*status*/);
 
+        virtual status_t createDefaultRequest(
+                    camera3::camera_request_template_t templateId,
+                    camera_metadata_t** metadata) override;
+
         std::shared_ptr<aidl::android::hardware::camera::device::ICameraDevice>
                 startDeviceInterface();
     };
diff --git a/services/camera/libcameraservice/common/hidl/HidlProviderInfo.cpp b/services/camera/libcameraservice/common/hidl/HidlProviderInfo.cpp
index e4bd503..d2643c1 100644
--- a/services/camera/libcameraservice/common/hidl/HidlProviderInfo.cpp
+++ b/services/camera/libcameraservice/common/hidl/HidlProviderInfo.cpp
@@ -853,13 +853,21 @@
 
 status_t HidlProviderInfo::HidlDeviceInfo3::isSessionConfigurationSupported(
         const SessionConfiguration &configuration, bool overrideForPerfClass,
-        metadataGetter getMetadata, bool *status) {
+        bool checkSessionParams, bool *status) {
+
+    if (checkSessionParams) {
+        // HIDL device doesn't support checking session parameters
+        return INVALID_OPERATION;
+    }
 
     hardware::camera::device::V3_7::StreamConfiguration configuration_3_7;
     bool earlyExit = false;
+    camera3::metadataGetter getMetadata = [this](const std::string &id,
+            bool /*overrideForPerfClass*/) {return this->deviceInfo(id);};
     auto bRes = SessionConfigurationUtils::convertToHALStreamCombination(configuration,
             mId, mCameraCharacteristics, getMetadata, mPhysicalIds,
-            configuration_3_7, overrideForPerfClass, &earlyExit);
+            configuration_3_7, overrideForPerfClass, mProviderTagid,
+            &earlyExit);
 
     if (!bRes.isOk()) {
         return UNKNOWN_ERROR;
@@ -961,7 +969,7 @@
                     cameraIdAndSessionConfig.mSessionConfiguration,
                     cameraId, deviceInfo, getMetadata,
                     physicalCameraIds, streamConfiguration,
-                    overrideForPerfClass, &shouldExit);
+                    overrideForPerfClass, mProviderTagid, &shouldExit);
         if (!bStatus.isOk()) {
             ALOGE("%s: convertToHALStreamCombination failed", __FUNCTION__);
             return INVALID_OPERATION;
diff --git a/services/camera/libcameraservice/common/hidl/HidlProviderInfo.h b/services/camera/libcameraservice/common/hidl/HidlProviderInfo.h
index fa6f4d4..f53db7f 100644
--- a/services/camera/libcameraservice/common/hidl/HidlProviderInfo.h
+++ b/services/camera/libcameraservice/common/hidl/HidlProviderInfo.h
@@ -105,7 +105,7 @@
 
         virtual status_t isSessionConfigurationSupported(
                 const SessionConfiguration &/*configuration*/,
-                bool overrideForPerfClass, camera3::metadataGetter getMetadata,
+                bool overrideForPerfClass, bool checkSessionParams,
                 bool *status/*status*/);
         sp<hardware::camera::device::V3_2::ICameraDevice> startDeviceInterface();
     };
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index 8006ee1..0a5b0c4 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -75,6 +75,7 @@
 #include <tuple>
 
 using namespace android::camera3;
+using namespace android::camera3::SessionConfigurationUtils;
 using namespace android::hardware::camera;
 
 namespace flags = com::android::internal::camera::flags;
@@ -1365,62 +1366,52 @@
     return filterParamsAndConfigureLocked(sessionParams, operatingMode);
 }
 
-status_t Camera3Device::filterParamsAndConfigureLocked(const CameraMetadata& sessionParams,
+status_t Camera3Device::filterParamsAndConfigureLocked(const CameraMetadata& params,
         int operatingMode) {
-    //Filter out any incoming session parameters
-    const CameraMetadata params(sessionParams);
+    CameraMetadata filteredParams;
+    SessionConfigurationUtils::filterParameters(params, mDeviceInfo, mVendorTagId, filteredParams);
+
     camera_metadata_entry_t availableSessionKeys = mDeviceInfo.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, mVendorTagId);
-    filteredParams.unlock(meta);
-    if (availableSessionKeys.count > 0) {
-        bool rotateAndCropSessionKey = false;
-        bool autoframingSessionKey = false;
-        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);
+
+    bool rotateAndCropSessionKey = false;
+    bool autoframingSessionKey = false;
+    for (size_t i = 0; i < availableSessionKeys.count; i++) {
+        if (ANDROID_SCALER_ROTATE_AND_CROP == availableSessionKeys.data.i32[i]) {
+            rotateAndCropSessionKey = true;
+        }
+        if (ANDROID_CONTROL_AUTOFRAMING == availableSessionKeys.data.i32[i]) {
+            autoframingSessionKey = true;
+        }
+    }
+
+    if (rotateAndCropSessionKey || autoframingSessionKey) {
+        sp<CaptureRequest> request = new CaptureRequest();
+        PhysicalCameraSettings settingsList;
+        settingsList.metadata = filteredParams;
+        request->mSettingsList.push_back(settingsList);
+
+        if (rotateAndCropSessionKey) {
+            auto rotateAndCropEntry = filteredParams.find(ANDROID_SCALER_ROTATE_AND_CROP);
+            if (rotateAndCropEntry.count > 0 &&
+                    rotateAndCropEntry.data.u8[0] == ANDROID_SCALER_ROTATE_AND_CROP_AUTO) {
+                request->mRotateAndCropAuto = true;
+            } else {
+                request->mRotateAndCropAuto = false;
             }
-            if (ANDROID_SCALER_ROTATE_AND_CROP == availableSessionKeys.data.i32[i]) {
-                rotateAndCropSessionKey = true;
-            }
-            if (ANDROID_CONTROL_AUTOFRAMING == availableSessionKeys.data.i32[i]) {
-                autoframingSessionKey = true;
+
+            overrideAutoRotateAndCrop(request, mOverrideToPortrait, mRotateAndCropOverride);
+        }
+
+        if (autoframingSessionKey) {
+            auto autoframingEntry = filteredParams.find(ANDROID_CONTROL_AUTOFRAMING);
+            if (autoframingEntry.count > 0 &&
+                    autoframingEntry.data.u8[0] == ANDROID_CONTROL_AUTOFRAMING_AUTO) {
+                overrideAutoframing(request, mAutoframingOverride);
             }
         }
 
-        if (rotateAndCropSessionKey || autoframingSessionKey) {
-            sp<CaptureRequest> request = new CaptureRequest();
-            PhysicalCameraSettings settingsList;
-            settingsList.metadata = filteredParams;
-            request->mSettingsList.push_back(settingsList);
-
-            if (rotateAndCropSessionKey) {
-                auto rotateAndCropEntry = filteredParams.find(ANDROID_SCALER_ROTATE_AND_CROP);
-                if (rotateAndCropEntry.count > 0 &&
-                        rotateAndCropEntry.data.u8[0] == ANDROID_SCALER_ROTATE_AND_CROP_AUTO) {
-                    request->mRotateAndCropAuto = true;
-                } else {
-                    request->mRotateAndCropAuto = false;
-                }
-
-                overrideAutoRotateAndCrop(request, mOverrideToPortrait, mRotateAndCropOverride);
-            }
-
-            if (autoframingSessionKey) {
-                auto autoframingEntry = filteredParams.find(ANDROID_CONTROL_AUTOFRAMING);
-                if (autoframingEntry.count > 0 &&
-                        autoframingEntry.data.u8[0] == ANDROID_CONTROL_AUTOFRAMING_AUTO) {
-                    overrideAutoframing(request, mAutoframingOverride);
-                }
-            }
-
-            filteredParams = request->mSettingsList.begin()->metadata;
-        }
+        filteredParams = request->mSettingsList.begin()->metadata;
     }
 
     return configureStreamsLocked(operatingMode, filteredParams);
diff --git a/services/camera/libcameraservice/device3/aidl/AidlCamera3Device.cpp b/services/camera/libcameraservice/device3/aidl/AidlCamera3Device.cpp
index c90fad2..97475f0 100644
--- a/services/camera/libcameraservice/device3/aidl/AidlCamera3Device.cpp
+++ b/services/camera/libcameraservice/device3/aidl/AidlCamera3Device.cpp
@@ -851,33 +851,15 @@
     ATRACE_NAME("CameraAidlHal::constructDefaultRequestSettings");
     using aidl::android::hardware::camera::device::RequestTemplate;
     if (!valid()) return INVALID_OPERATION;
-    status_t res = OK;
 
     RequestTemplate id;
-    aidl::android::hardware::camera::device::CameraMetadata request;
-    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;
+    status_t res = SessionConfigurationUtils::mapRequestTemplateToAidl(
+            templateId, &id);
+    if (res != OK) {
+        return res;
     }
+
+    aidl::android::hardware::camera::device::CameraMetadata request;
     auto err = mAidlSession->constructDefaultRequestSettings(id, &request);
 
     if (!err.isOk()) {
diff --git a/services/camera/libcameraservice/libcameraservice_fuzzer/Android.bp b/services/camera/libcameraservice/libcameraservice_fuzzer/Android.bp
index efc58b4..9dd657c 100644
--- a/services/camera/libcameraservice/libcameraservice_fuzzer/Android.bp
+++ b/services/camera/libcameraservice/libcameraservice_fuzzer/Android.bp
@@ -49,7 +49,7 @@
         "android.hardware.camera.provider@2.5",
         "android.hardware.camera.provider@2.6",
         "android.hardware.camera.provider@2.7",
-        "android.hardware.camera.provider-V2-ndk",
+        "android.hardware.camera.provider-V3-ndk",
         "android.hardware.camera.device@1.0",
         "android.hardware.camera.device@3.2",
         "android.hardware.camera.device@3.3",
diff --git a/services/camera/libcameraservice/tests/Android.bp b/services/camera/libcameraservice/tests/Android.bp
index e9ecc86..5072edd 100644
--- a/services/camera/libcameraservice/tests/Android.bp
+++ b/services/camera/libcameraservice/tests/Android.bp
@@ -62,7 +62,7 @@
         "android.hardware.camera.provider@2.5",
         "android.hardware.camera.provider@2.6",
         "android.hardware.camera.provider@2.7",
-        "android.hardware.camera.provider-V2-ndk",
+        "android.hardware.camera.provider-V3-ndk",
         "libcameraservice",
         "libgmock",
         "libflagtest",
diff --git a/services/camera/libcameraservice/tests/CameraProviderManagerTest.cpp b/services/camera/libcameraservice/tests/CameraProviderManagerTest.cpp
index afc8b94..467707e 100644
--- a/services/camera/libcameraservice/tests/CameraProviderManagerTest.cpp
+++ b/services/camera/libcameraservice/tests/CameraProviderManagerTest.cpp
@@ -299,6 +299,16 @@
     ::ndk::ScopedAStatus getTorchStrengthLevel(int32_t*) override {
         return ndk::ScopedAStatus::ok();
     }
+    ::ndk::ScopedAStatus constructDefaultRequestSettings(
+            ::aidl::android::hardware::camera::device::RequestTemplate,
+            ::aidl::android::hardware::camera::device::CameraMetadata*) override {
+        return ndk::ScopedAStatus::ok();
+    }
+    ::ndk::ScopedAStatus isStreamCombinationWithSettingsSupported(
+            const ::aidl::android::hardware::camera::device::StreamConfiguration&,
+            bool*) override {
+        return ndk::ScopedAStatus::ok();
+    }
 };
 
 /**
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
diff --git a/services/camera/virtualcamera/Android.bp b/services/camera/virtualcamera/Android.bp
index 870b9d5..c8fa84e 100644
--- a/services/camera/virtualcamera/Android.bp
+++ b/services/camera/virtualcamera/Android.bp
@@ -27,7 +27,7 @@
     static_libs: [
         "android.hardware.camera.common@1.0-helper",
         "android.hardware.camera.common-V1-ndk",
-        "android.hardware.camera.device-V3-ndk",
+        "android.hardware.camera.device-V2-ndk",
         "android.hardware.camera.metadata-V2-ndk",
         "android.hardware.camera.provider-V2-ndk",
         "libaidlcommonsupport",
diff --git a/services/camera/virtualcamera/VirtualCameraSession.h b/services/camera/virtualcamera/VirtualCameraSession.h
index 8bf66bc..50962e5 100644
--- a/services/camera/virtualcamera/VirtualCameraSession.h
+++ b/services/camera/virtualcamera/VirtualCameraSession.h
@@ -64,12 +64,6 @@
       std::vector<::aidl::android::hardware::camera::device::HalStream>*
           _aidl_return) override EXCLUDES(mLock);
 
-  ndk::ScopedAStatus configureStreamsV2(
-      const ::aidl::android::hardware::camera::device::StreamConfiguration&,
-      ::aidl::android::hardware::camera::device::ConfigureStreamsRet*) override {
-    return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
-  };
-
   ndk::ScopedAStatus constructDefaultRequestSettings(
       ::aidl::android::hardware::camera::device::RequestTemplate in_type,
       ::aidl::android::hardware::camera::device::CameraMetadata* _aidl_return)