Camera: Add getSessionCharacteristics API

Test: Build
Bug: 303645857
Change-Id: I251f244f8e24bd4c874f54f7c8c7215a4c3a50b3
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
index 095d425..7443788 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
@@ -777,6 +777,60 @@
     return res;
 }
 
+binder::Status CameraDeviceClient::getSessionCharacteristics(
+        const SessionConfiguration& sessionConfiguration,
+        /*out*/
+        hardware::camera2::impl::CameraMetadataNative* sessionCharacteristics) {
+    ATRACE_CALL();
+    binder::Status res;
+    status_t ret = OK;
+    if (!(res = checkPidStatus(__FUNCTION__)).isOk()) return res;
+
+    Mutex::Autolock icl(mBinderSerializationLock);
+
+    if (!mDevice.get()) {
+        return STATUS_ERROR(CameraService::ERROR_DISCONNECTED, "Camera device no longer alive");
+    }
+
+    auto operatingMode = sessionConfiguration.getOperatingMode();
+    res = SessionConfigurationUtils::checkOperatingMode(operatingMode, mDevice->info(),
+            mCameraIdStr);
+    if (!res.isOk()) {
+        return res;
+    }
+
+    camera3::metadataGetter getMetadata = [this](const std::string &id,
+            bool /*overrideForPerfClass*/) {
+          return mDevice->infoPhysical(id);};
+    ret = mProviderManager->getSessionCharacteristics(mCameraIdStr.c_str(),
+            sessionConfiguration, mOverrideForPerfClass, getMetadata,
+            sessionCharacteristics);
+
+    switch (ret) {
+        case OK:
+            // Expected, do nothing.
+            break;
+        case INVALID_OPERATION: {
+                std::string msg = fmt::sprintf(
+                        "Camera %s: Session characteristics query not supported!",
+                        mCameraIdStr.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)", mCameraIdStr.c_str(),
+                        strerror(-ret), ret);
+                ALOGE("%s: %s", __FUNCTION__, msg.c_str());
+                res = STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
+                        msg.c_str());
+            }
+    }
+
+    return res;
+}
+
 binder::Status CameraDeviceClient::deleteStream(int streamId) {
     ATRACE_CALL();
     ALOGV("%s (streamId = 0x%x)", __FUNCTION__, streamId);
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.h b/services/camera/libcameraservice/api2/CameraDeviceClient.h
index b2c9626..c2f7f56 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.h
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.h
@@ -109,6 +109,11 @@
             /*out*/
             bool* streamStatus) override;
 
+    virtual binder::Status getSessionCharacteristics(
+            const SessionConfiguration& sessionConfiguration,
+            /*out*/
+            hardware::camera2::impl::CameraMetadataNative* sessionCharacteristics) override;
+
     // Returns -EBUSY if device is not idle or in error state
     virtual binder::Status deleteStream(int streamId) override;
 
diff --git a/services/camera/libcameraservice/common/CameraProviderManager.cpp b/services/camera/libcameraservice/common/CameraProviderManager.cpp
index fbb5e1b..1ba3de4 100644
--- a/services/camera/libcameraservice/common/CameraProviderManager.cpp
+++ b/services/camera/libcameraservice/common/CameraProviderManager.cpp
@@ -442,6 +442,23 @@
     return OK;
 }
 
+status_t CameraProviderManager::getSessionCharacteristics(const std::string& id,
+        const SessionConfiguration &configuration, bool overrideForPerfClass,
+        metadataGetter getMetadata,
+        CameraMetadata* sessionCharacteristics /*out*/) const {
+    if (!flags::feature_combination_query()) {
+        return INVALID_OPERATION;
+    }
+    std::lock_guard<std::mutex> lock(mInterfaceMutex);
+    auto deviceInfo = findDeviceInfoLocked(id);
+    if (deviceInfo == nullptr) {
+        return NAME_NOT_FOUND;
+    }
+
+    return deviceInfo->getSessionCharacteristics(configuration,
+            overrideForPerfClass, getMetadata, sessionCharacteristics);
+}
+
 status_t CameraProviderManager::getCameraIdIPCTransport(const std::string &id,
         IPCTransport *providerTransport) const {
     std::lock_guard<std::mutex> lock(mInterfaceMutex);
diff --git a/services/camera/libcameraservice/common/CameraProviderManager.h b/services/camera/libcameraservice/common/CameraProviderManager.h
index 6142a71..53a2102 100644
--- a/services/camera/libcameraservice/common/CameraProviderManager.h
+++ b/services/camera/libcameraservice/common/CameraProviderManager.h
@@ -317,6 +317,14 @@
             bool *status /*out*/) const;
 
     /**
+     * Get session characteristics for a particular session.
+     */
+     status_t getSessionCharacteristics(const std::string& id,
+            const SessionConfiguration &configuration,
+            bool overrideForPerfClass, camera3::metadataGetter getMetadata,
+            CameraMetadata* sessionCharacteristics /*out*/) const;
+
+    /**
      * Return the highest supported device interface version for this ID
      */
     status_t getHighestSupportedVersion(const std::string &id,
@@ -632,6 +640,15 @@
                     bool * /*status*/) {
                 return INVALID_OPERATION;
             }
+
+            virtual status_t getSessionCharacteristics(
+                    const SessionConfiguration &/*configuration*/,
+                    bool /*overrideForPerfClass*/,
+                    camera3::metadataGetter /*getMetadata*/,
+                    CameraMetadata* /*sessionCharacteristics*/) {
+                return INVALID_OPERATION;
+            }
+
             virtual status_t filterSmallJpegSizes() = 0;
             virtual void notifyDeviceStateChange(int64_t /*newState*/) {}
             virtual status_t createDefaultRequest(
diff --git a/services/camera/libcameraservice/common/aidl/AidlProviderInfo.cpp b/services/camera/libcameraservice/common/aidl/AidlProviderInfo.cpp
index a64c9d7..d773af3 100644
--- a/services/camera/libcameraservice/common/aidl/AidlProviderInfo.cpp
+++ b/services/camera/libcameraservice/common/aidl/AidlProviderInfo.cpp
@@ -900,6 +900,54 @@
     return res;
 }
 
+status_t AidlProviderInfo::AidlDeviceInfo3::getSessionCharacteristics(
+        const SessionConfiguration &configuration, bool overrideForPerfClass,
+        camera3::metadataGetter getMetadata, CameraMetadata *sessionCharacteristics) {
+    camera::device::StreamConfiguration streamConfiguration;
+    bool earlyExit = false;
+    auto res = SessionConfigurationUtils::convertToHALStreamCombination(configuration,
+            mId, mCameraCharacteristics, mCompositeJpegRDisabled, getMetadata,
+            mPhysicalIds, streamConfiguration, overrideForPerfClass, mProviderTagid,
+            /*checkSessionParams*/true, &earlyExit);
+
+    if (!res.isOk()) {
+        return UNKNOWN_ERROR;
+    }
+
+    if (earlyExit) {
+        return BAD_VALUE;
+    }
+
+    const std::shared_ptr<camera::device::ICameraDevice> interface =
+            startDeviceInterface();
+
+    if (interface == nullptr) {
+        return DEAD_OBJECT;
+    }
+
+    aidl::android::hardware::camera::device::CameraMetadata chars;
+    ::ndk::ScopedAStatus ret =
+        interface->getSessionCharacteristics(streamConfiguration, &chars);
+    std::vector<uint8_t> &metadata = chars.metadata;
+
+    camera_metadata_t *buffer = reinterpret_cast<camera_metadata_t*>(metadata.data());
+    size_t expectedSize = metadata.size();
+    int resV = validate_camera_metadata_structure(buffer, &expectedSize);
+    if (resV == OK || resV == CAMERA_METADATA_VALIDATION_SHIFTED) {
+        set_camera_metadata_vendor_id(buffer, mProviderTagid);
+        *sessionCharacteristics = buffer;
+    } else {
+        ALOGE("%s: Malformed camera metadata received from HAL", __FUNCTION__);
+        return BAD_VALUE;
+    }
+
+    if (!ret.isOk()) {
+        ALOGE("%s: Unexpected binder error: %s", __FUNCTION__, ret.getMessage());
+        return mapToStatusT(ret);
+    }
+    return OK;
+}
+
 status_t AidlProviderInfo::convertToAidlHALStreamCombinationAndCameraIdsLocked(
         const std::vector<CameraIdAndSessionConfiguration> &cameraIdsAndSessionConfigs,
         const std::set<std::string>& perfClassPrimaryCameraIds,
diff --git a/services/camera/libcameraservice/common/aidl/AidlProviderInfo.h b/services/camera/libcameraservice/common/aidl/AidlProviderInfo.h
index cc5101a..0bfa7d4 100644
--- a/services/camera/libcameraservice/common/aidl/AidlProviderInfo.h
+++ b/services/camera/libcameraservice/common/aidl/AidlProviderInfo.h
@@ -134,6 +134,11 @@
                     camera3::camera_request_template_t templateId,
                     camera_metadata_t** metadata) override;
 
+        virtual status_t getSessionCharacteristics(
+                const SessionConfiguration &/*configuration*/,
+                bool overrideForPerfClass, camera3::metadataGetter /*getMetadata*/,
+                CameraMetadata *sessionCharacteristics /*sessionCharacteristics*/);
+
         std::shared_ptr<aidl::android::hardware::camera::device::ICameraDevice>
                 startDeviceInterface();
     };
diff --git a/services/camera/libcameraservice/common/hidl/HidlProviderInfo.h b/services/camera/libcameraservice/common/hidl/HidlProviderInfo.h
index f53db7f..869bba0 100644
--- a/services/camera/libcameraservice/common/hidl/HidlProviderInfo.h
+++ b/services/camera/libcameraservice/common/hidl/HidlProviderInfo.h
@@ -107,6 +107,7 @@
                 const SessionConfiguration &/*configuration*/,
                 bool overrideForPerfClass, bool checkSessionParams,
                 bool *status/*status*/);
+
         sp<hardware::camera::device::V3_2::ICameraDevice> startDeviceInterface();
     };
 
diff --git a/services/camera/libcameraservice/tests/CameraProviderManagerTest.cpp b/services/camera/libcameraservice/tests/CameraProviderManagerTest.cpp
index 467707e..a53d26d 100644
--- a/services/camera/libcameraservice/tests/CameraProviderManagerTest.cpp
+++ b/services/camera/libcameraservice/tests/CameraProviderManagerTest.cpp
@@ -309,6 +309,12 @@
             bool*) override {
         return ndk::ScopedAStatus::ok();
     }
+
+    ::ndk::ScopedAStatus getSessionCharacteristics(
+        const ::aidl::android::hardware::camera::device::StreamConfiguration&,
+        ::aidl::android::hardware::camera::device::CameraMetadata*) override {
+        return ndk::ScopedAStatus::ok();
+    }
 };
 
 /**