Camera VTS: Verify high speed video configurations

Verify high speed video configurations based on the tag definition.

Bug: 274392420
Test: Ran on cuttlefish
Change-Id: Ie64415cc8694d8f4da59a01f6051bc847ae30fa7
diff --git a/camera/provider/aidl/vts/VtsAidlHalCameraProvider_TargetTest.cpp b/camera/provider/aidl/vts/VtsAidlHalCameraProvider_TargetTest.cpp
index b764ad6..04ae63a 100644
--- a/camera/provider/aidl/vts/VtsAidlHalCameraProvider_TargetTest.cpp
+++ b/camera/provider/aidl/vts/VtsAidlHalCameraProvider_TargetTest.cpp
@@ -241,6 +241,7 @@
         verifyCameraCharacteristics(chars);
         verifyMonochromeCharacteristics(chars);
         verifyRecommendedConfigs(chars);
+        verifyHighSpeedRecordingCharacteristics(name, chars);
         verifyLogicalOrUltraHighResCameraMetadata(name, device, chars, cameraDeviceNames);
 
         ASSERT_TRUE(ret.isOk());
diff --git a/camera/provider/aidl/vts/camera_aidl_test.cpp b/camera/provider/aidl/vts/camera_aidl_test.cpp
index ef3ce4f..c8881b8 100644
--- a/camera/provider/aidl/vts/camera_aidl_test.cpp
+++ b/camera/provider/aidl/vts/camera_aidl_test.cpp
@@ -767,6 +767,90 @@
     ASSERT_TRUE(hasBokehStillCaptureMode || hasBokehContinuousMode || hasVendorMode);
 }
 
+void CameraAidlTest::verifyHighSpeedRecordingCharacteristics(const std::string& cameraName,
+                                                             const CameraMetadata& chars) {
+    const camera_metadata_t* metadata =
+            reinterpret_cast<const camera_metadata_t*>(chars.metadata.data());
+
+    // Check capabilities
+    bool hasHighSpeedRecordingCapability = false;
+    bool hasUltraHighResolutionCapability = false;
+    camera_metadata_ro_entry entry;
+    int rc =
+            find_camera_metadata_ro_entry(metadata, ANDROID_REQUEST_AVAILABLE_CAPABILITIES, &entry);
+    if ((0 == rc) && (entry.count > 0)) {
+        hasHighSpeedRecordingCapability =
+                std::find(entry.data.u8, entry.data.u8 + entry.count,
+                          ANDROID_REQUEST_AVAILABLE_CAPABILITIES_CONSTRAINED_HIGH_SPEED_VIDEO) !=
+                entry.data.u8 + entry.count;
+
+        hasUltraHighResolutionCapability =
+                std::find(entry.data.u8, entry.data.u8 + entry.count,
+                          ANDROID_REQUEST_AVAILABLE_CAPABILITIES_ULTRA_HIGH_RESOLUTION_SENSOR) !=
+                entry.data.u8 + entry.count;
+    }
+
+    // Check high speed video configurations
+    camera_metadata_ro_entry highSpeedEntry;
+    rc = find_camera_metadata_ro_entry(
+            metadata, ANDROID_CONTROL_AVAILABLE_HIGH_SPEED_VIDEO_CONFIGURATIONS, &highSpeedEntry);
+    bool hasHighSpeedEntry = (0 == rc && highSpeedEntry.count > 0);
+
+    camera_metadata_ro_entry highSpeedMaxResEntry;
+    rc = find_camera_metadata_ro_entry(
+            metadata, ANDROID_CONTROL_AVAILABLE_HIGH_SPEED_VIDEO_CONFIGURATIONS_MAXIMUM_RESOLUTION,
+            &highSpeedMaxResEntry);
+    bool hasHighSpeedMaxResEntry = (0 == rc && highSpeedMaxResEntry.count > 0);
+
+    // High speed recording configuration entry must be available based on capabilities
+    bool noHighSpeedRecording =
+            !hasHighSpeedRecordingCapability && !hasHighSpeedEntry && !hasHighSpeedMaxResEntry;
+    if (noHighSpeedRecording) {
+        return;
+    }
+    bool hasHighSpeedRecording = hasHighSpeedRecordingCapability && hasHighSpeedEntry &&
+                                 ((hasHighSpeedMaxResEntry && hasUltraHighResolutionCapability) ||
+                                  !hasHighSpeedMaxResEntry);
+    ASSERT_TRUE(hasHighSpeedRecording);
+
+    std::string version, cameraId;
+    ASSERT_TRUE(matchDeviceName(cameraName, mProviderType, &version, &cameraId));
+    bool needBatchSizeCheck = (version != CAMERA_DEVICE_API_VERSION_1);
+
+    // Check each entry item
+    ASSERT_TRUE(highSpeedEntry.count > 0 && highSpeedEntry.count % 5 == 0);
+    for (auto i = 4; i < highSpeedEntry.count; i += 5) {
+        int32_t fps_min = highSpeedEntry.data.i32[i - 2];
+        int32_t fps_max = highSpeedEntry.data.i32[i - 1];
+        int32_t batch_size_max = highSpeedEntry.data.i32[i];
+        int32_t allowedMaxBatchSize = fps_max / 30;
+
+        ASSERT_GE(fps_max, 120);
+        ASSERT_TRUE(fps_min % 30 == 0 && fps_max % 30 == 0);
+        if (needBatchSizeCheck) {
+            ASSERT_LE(batch_size_max, 32);
+            ASSERT_TRUE(allowedMaxBatchSize % batch_size_max == 0);
+        }
+    }
+
+    if (hasHighSpeedMaxResEntry) {
+        ASSERT_TRUE(highSpeedMaxResEntry.count > 0 && highSpeedMaxResEntry.count % 5 == 0);
+        for (auto i = 4; i < highSpeedMaxResEntry.count; i += 5) {
+            int32_t fps_min = highSpeedMaxResEntry.data.i32[i - 2];
+            int32_t fps_max = highSpeedMaxResEntry.data.i32[i - 1];
+            int32_t batch_size_max = highSpeedMaxResEntry.data.i32[i];
+            int32_t allowedMaxBatchSize = fps_max / 30;
+
+            ASSERT_GE(fps_max, 120);
+            ASSERT_TRUE(fps_min % 30 == 0 && fps_max % 30 == 0);
+            if (needBatchSizeCheck) {
+                ASSERT_LE(batch_size_max, 32);
+                ASSERT_TRUE(allowedMaxBatchSize % batch_size_max == 0);
+            }
+        }
+    }
+}
+
 Status CameraAidlTest::getAvailableOutputStreams(const camera_metadata_t* staticMeta,
                                                  std::vector<AvailableStream>& outputStreams,
                                                  const AvailableStream* threshold,
diff --git a/camera/provider/aidl/vts/camera_aidl_test.h b/camera/provider/aidl/vts/camera_aidl_test.h
index fdf312e..85ab443 100644
--- a/camera/provider/aidl/vts/camera_aidl_test.h
+++ b/camera/provider/aidl/vts/camera_aidl_test.h
@@ -222,6 +222,9 @@
 
     static void verifyExtendedSceneModeCharacteristics(const camera_metadata_t* metadata);
 
+    void verifyHighSpeedRecordingCharacteristics(const std::string& cameraName,
+                                                 const CameraMetadata& chars);
+
     static void verifyZoomCharacteristics(const camera_metadata_t* metadata);
 
     static void verifyRecommendedConfigs(const CameraMetadata& chars);
@@ -543,6 +546,8 @@
 namespace {
 // device@<major>.<minor>/<type>/id
 const char* kDeviceNameRE = "device@([0-9]+\\.[0-9]+)/\\s+/(.+)";
+const std::string CAMERA_DEVICE_API_VERSION_1 = "1.1";
+
 const int32_t kMaxVideoWidth = 4096;
 const int32_t kMaxVideoHeight = 2160;