Add VTS test for getSessionCharacteristics

Test: atest VtsAidlHalCameraProvider_TargetTest
Bug: 314386872
Change-Id: I3f838fd041e6aca4b12fad512f57287a94149c6e
diff --git a/camera/provider/aidl/vts/VtsAidlHalCameraProvider_TargetTest.cpp b/camera/provider/aidl/vts/VtsAidlHalCameraProvider_TargetTest.cpp
index e335853..e24e078 100644
--- a/camera/provider/aidl/vts/VtsAidlHalCameraProvider_TargetTest.cpp
+++ b/camera/provider/aidl/vts/VtsAidlHalCameraProvider_TargetTest.cpp
@@ -283,6 +283,64 @@
     }
 }
 
+TEST_P(CameraAidlTest, getSessionCharacteristics) {
+    if (flags::feature_combination_query()) {
+        std::vector<std::string> cameraDeviceNames = getCameraDeviceNames(mProvider);
+
+        for (const auto& name : cameraDeviceNames) {
+            std::shared_ptr<ICameraDevice> device;
+            ALOGI("getSessionCharacteristics: Testing camera device %s", name.c_str());
+            ndk::ScopedAStatus ret = mProvider->getCameraDeviceInterface(name, &device);
+            ALOGI("getCameraDeviceInterface returns: %d:%d", ret.getExceptionCode(),
+                  ret.getServiceSpecificError());
+            ASSERT_TRUE(ret.isOk());
+            ASSERT_NE(device, nullptr);
+
+            CameraMetadata meta;
+            openEmptyDeviceSession(name, mProvider, &mSession /*out*/, &meta /*out*/,
+                                   &device /*out*/);
+
+            std::vector<AvailableStream> outputStreams;
+            camera_metadata_t* staticMeta =
+                    reinterpret_cast<camera_metadata_t*>(meta.metadata.data());
+            outputStreams.clear();
+            ASSERT_EQ(Status::OK, getAvailableOutputStreams(staticMeta, outputStreams));
+            ASSERT_NE(0u, outputStreams.size());
+
+            AvailableStream sampleStream = outputStreams[0];
+
+            int32_t streamId = 0;
+            Stream stream = {streamId,
+                             StreamType::OUTPUT,
+                             sampleStream.width,
+                             sampleStream.height,
+                             static_cast<PixelFormat>(sampleStream.format),
+                             static_cast<aidl::android::hardware::graphics::common::BufferUsage>(
+                                     GRALLOC1_CONSUMER_USAGE_VIDEO_ENCODER),
+                             Dataspace::UNKNOWN,
+                             StreamRotation::ROTATION_0,
+                             std::string(),
+                             /*bufferSize*/ 0,
+                             /*groupId*/ -1,
+                             {SensorPixelMode::ANDROID_SENSOR_PIXEL_MODE_DEFAULT},
+                             RequestAvailableDynamicRangeProfilesMap::
+                                     ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD};
+
+            std::vector<Stream> streams = {stream};
+            StreamConfiguration config;
+            createStreamConfiguration(streams, StreamConfigurationMode::NORMAL_MODE, &config);
+
+            CameraMetadata chars;
+            ret = device->getSessionCharacteristics(config, &chars);
+            ASSERT_TRUE(ret.isOk());
+            verifySessionCharacteristics(chars);
+        }
+    } else {
+        ALOGI("getSessionCharacteristics: Test skipped.\n");
+        GTEST_SKIP();
+    }
+}
+
 // Verify that the torch strength level can be set and retrieved successfully.
 TEST_P(CameraAidlTest, turnOnTorchWithStrengthLevel) {
     std::vector<std::string> cameraDeviceNames = getCameraDeviceNames(mProvider);
diff --git a/camera/provider/aidl/vts/camera_aidl_test.cpp b/camera/provider/aidl/vts/camera_aidl_test.cpp
index 8e72b3f..90444dd 100644
--- a/camera/provider/aidl/vts/camera_aidl_test.cpp
+++ b/camera/provider/aidl/vts/camera_aidl_test.cpp
@@ -1931,6 +1931,55 @@
     }
 }
 
+void CameraAidlTest::verifySessionCharacteristics(const CameraMetadata& chars) {
+    if (flags::feature_combination_query()) {
+        const camera_metadata_t* metadata =
+                reinterpret_cast<const camera_metadata_t*>(chars.metadata.data());
+
+        size_t expectedSize = chars.metadata.size();
+        int result = validate_camera_metadata_structure(metadata, &expectedSize);
+        ASSERT_TRUE((result == 0) || (result == CAMERA_METADATA_VALIDATION_SHIFTED));
+        size_t entryCount = get_camera_metadata_entry_count(metadata);
+        ASSERT_GT(entryCount, 0u);
+
+        camera_metadata_ro_entry entry;
+        int retcode = 0;
+        float maxDigitalZoom = 1.0;
+
+        retcode = find_camera_metadata_ro_entry(metadata, ANDROID_SCALER_AVAILABLE_MAX_DIGITAL_ZOOM,
+                                                &entry);
+        // ANDROID_SCALER_AVAILABLE_MAX_DIGITAL_ZOOM should always be present.
+        if ((0 == retcode) && (entry.count == 1)) {
+            maxDigitalZoom = entry.data.f[0];
+        } else {
+            ADD_FAILURE() << "Get camera scalerAvailableMaxDigitalZoom failed!";
+        }
+
+        retcode = find_camera_metadata_ro_entry(metadata, ANDROID_CONTROL_ZOOM_RATIO_RANGE, &entry);
+        bool hasZoomRatioRange = (0 == retcode && entry.count == 2);
+        if (!hasZoomRatioRange) {
+            return;
+        }
+        float minZoomRatio = entry.data.f[0];
+        float maxZoomRatio = entry.data.f[1];
+        constexpr float FLOATING_POINT_THRESHOLD = 0.00001f;
+        if (abs(maxDigitalZoom - maxZoomRatio) > FLOATING_POINT_THRESHOLD) {
+            ADD_FAILURE() << "Difference between maximum digital zoom " << maxDigitalZoom
+                          << " and maximum zoom ratio " << maxZoomRatio
+                          << " is greater than the threshold " << FLOATING_POINT_THRESHOLD << "!";
+        }
+        if (minZoomRatio > maxZoomRatio) {
+            ADD_FAILURE() << "Maximum zoom ratio is less than minimum zoom ratio!";
+        }
+        if (minZoomRatio > 1.0f) {
+            ADD_FAILURE() << "Minimum zoom ratio is more than 1.0!";
+        }
+        if (maxZoomRatio < 1.0f) {
+            ADD_FAILURE() << "Maximum zoom ratio is less than 1.0!";
+        }
+    }
+}
+
 std::vector<ConcurrentCameraIdCombination> CameraAidlTest::getConcurrentDeviceCombinations(
         std::shared_ptr<ICameraProvider>& provider) {
     std::vector<ConcurrentCameraIdCombination> combinations;
diff --git a/camera/provider/aidl/vts/camera_aidl_test.h b/camera/provider/aidl/vts/camera_aidl_test.h
index b51544f..b923345 100644
--- a/camera/provider/aidl/vts/camera_aidl_test.h
+++ b/camera/provider/aidl/vts/camera_aidl_test.h
@@ -281,6 +281,8 @@
     static void verifyStreamCombination(const std::shared_ptr<ICameraDevice>& device,
                                         const StreamConfiguration& config, bool expectedStatus);
 
+    static void verifySessionCharacteristics(const CameraMetadata& chars);
+
     static void verifyLogicalCameraResult(const camera_metadata_t* staticMetadata,
                                           const std::vector<uint8_t>& resultMetadata);