From 9f89b053799b5d99223253d27fd590252fbe8c6c Mon Sep 17 00:00:00 2001 From: Shuzhen Wang Date: Thu, 4 Mar 2021 11:59:23 -0800 Subject: [PATCH] Camera: Add a new tag for multi-resolution stream support - The new tag is used to remove the ambiguity when a physical camera is backing more than one logical cameras. - Add missing VTS tests for multi-resolution stream. Test: Camera CTS, VTS Bug: 156254356 Bug: 184663916 Change-Id: I8adc152bbf57e8ec5e058834c1c6f461aca1bcbd --- camera/metadata/3.6/types.hal | 14 + .../VtsHalCameraProviderV2_4TargetTest.cpp | 634 ++++++++++++++---- 2 files changed, 521 insertions(+), 127 deletions(-) diff --git a/camera/metadata/3.6/types.hal b/camera/metadata/3.6/types.hal index 709cfb3ec5..97cac7c3e8 100644 --- a/camera/metadata/3.6/types.hal +++ b/camera/metadata/3.6/types.hal @@ -131,6 +131,12 @@ enum CameraMetadataTag : @3.5::CameraMetadataTag { */ ANDROID_SCALER_AVAILABLE_INPUT_OUTPUT_FORMATS_MAP_MAXIMUM_RESOLUTION, + /** android.scaler.multiResolutionStreamSupported [static, enum, ndk_public] + * + *

Whether the camera device supports multi-resolution input or output streams

+ */ + ANDROID_SCALER_MULTI_RESOLUTION_STREAM_SUPPORTED, + ANDROID_SCALER_END_3_6, /** android.sensor.opaqueRawSizeMaximumResolution [static, int32[], system] @@ -334,6 +340,14 @@ enum CameraMetadataEnumAndroidScalerAvailableStreamConfigurationsMaximumResoluti ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_MAXIMUM_RESOLUTION_INPUT, }; +/** android.scaler.multiResolutionStreamSupported enumeration values + * @see ANDROID_SCALER_MULTI_RESOLUTION_STREAM_SUPPORTED + */ +enum CameraMetadataEnumAndroidScalerMultiResolutionStreamSupported : uint32_t { + ANDROID_SCALER_MULTI_RESOLUTION_STREAM_SUPPORTED_FALSE, + ANDROID_SCALER_MULTI_RESOLUTION_STREAM_SUPPORTED_TRUE, +}; + /** android.sensor.pixelMode enumeration values * @see ANDROID_SENSOR_PIXEL_MODE */ diff --git a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp index ed3b1faa53..7bb300ed2e 100644 --- a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp +++ b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp @@ -578,7 +578,7 @@ public: uint32_t id; ASSERT_TRUE(parseProviderName(service_name, &mProviderType, &id)); - castProvider(mProvider, &mProvider2_5, &mProvider2_6); + castProvider(mProvider, &mProvider2_5, &mProvider2_6, &mProvider2_7); notifyDeviceState(provider::V2_5::DeviceState::NORMAL); } virtual void TearDown() override {} @@ -759,22 +759,24 @@ public: ::android::sp *device = nullptr/*out*/); void castProvider(const sp& provider, sp* provider2_5 /*out*/, - sp* provider2_6 /*out*/); + sp* provider2_6 /*out*/, + sp* provider2_7 /*out*/); void castSession(const sp &session, int32_t deviceVersion, sp *session3_3 /*out*/, sp *session3_4 /*out*/, sp *session3_5 /*out*/, sp *session3_6 /*out*/, sp *session3_7 /*out*/); - void castDevice(const sp &device, int32_t deviceVersion, - sp *device3_5/*out*/); - void castDevice3_7(const sp& device, int32_t deviceVersion, - sp* device3_7 /*out*/); - void createStreamConfiguration(const ::android::hardware::hidl_vec& streams3_2, + void castDevice(const sp& device, int32_t deviceVersion, + sp* device3_5 /*out*/, + sp* device3_7 /*out*/); + void createStreamConfiguration( + const ::android::hardware::hidl_vec& streams3_2, StreamConfigurationMode configMode, - ::android::hardware::camera::device::V3_2::StreamConfiguration *config3_2, - ::android::hardware::camera::device::V3_4::StreamConfiguration *config3_4, - ::android::hardware::camera::device::V3_5::StreamConfiguration *config3_5, + ::android::hardware::camera::device::V3_2::StreamConfiguration* config3_2, + ::android::hardware::camera::device::V3_4::StreamConfiguration* config3_4, + ::android::hardware::camera::device::V3_5::StreamConfiguration* config3_5, + ::android::hardware::camera::device::V3_7::StreamConfiguration* config3_7, uint32_t jpegBufferSize = 0); void configureOfflineStillStream(const std::string &name, int32_t deviceVersion, @@ -834,7 +836,8 @@ public: uint32_t* partialResultCount /*out*/, bool* useHalBufManager /*out*/, sp* cb /*out*/, uint32_t streamConfigCounter = 0); - void verifyLogicalCameraMetadata(const std::string& cameraName, + void verifyLogicalOrUltraHighResCameraMetadata( + const std::string& cameraName, const ::android::sp<::android::hardware::camera::device::V3_2::ICameraDevice>& device, const CameraMetadata& chars, int deviceVersion, const hidl_vec& deviceNames); @@ -845,8 +848,11 @@ public: void verifyMonochromeCharacteristics(const CameraMetadata& chars, int deviceVersion); void verifyMonochromeCameraResult( const ::android::hardware::camera::common::V1_0::helper::CameraMetadata& metadata); - void verifyStreamCombination(sp cameraDevice3_5, - const ::android::hardware::camera::device::V3_4::StreamConfiguration &config3_4, + void verifyStreamCombination( + sp cameraDevice3_7, + const ::android::hardware::camera::device::V3_7::StreamConfiguration& config3_7, + sp cameraDevice3_5, + const ::android::hardware::camera::device::V3_4::StreamConfiguration& config3_4, bool expectedStatus, bool expectStreamCombQuery); void verifyLogicalCameraResult(const camera_metadata_t* staticMetadata, const ::android::hardware::camera::common::V1_0::helper::CameraMetadata& resultMetadata); @@ -915,6 +921,11 @@ public: static Status isMonochromeCamera(const camera_metadata_t *staticMeta); static Status getSystemCameraKind(const camera_metadata_t* staticMeta, SystemCameraKind* systemCameraKind); + static void getMultiResolutionStreamConfigurations( + camera_metadata_ro_entry* multiResStreamConfigs, + camera_metadata_ro_entry* streamConfigs, + camera_metadata_ro_entry* maxResolutionStreamConfigs, + const camera_metadata_t* staticMetadata); static V3_2::DataspaceFlags getDataspace(PixelFormat format); @@ -1047,6 +1058,7 @@ protected: sp mProvider; sp<::android::hardware::camera::provider::V2_5::ICameraProvider> mProvider2_5; sp<::android::hardware::camera::provider::V2_6::ICameraProvider> mProvider2_6; + sp<::android::hardware::camera::provider::V2_7::ICameraProvider> mProvider2_7; // Camera provider type. std::string mProviderType; @@ -2805,8 +2817,8 @@ TEST_P(CameraHidlTest, getCameraCharacteristics) { verifyCameraCharacteristics(status, chars); verifyMonochromeCharacteristics(chars, deviceVersion); verifyRecommendedConfigs(chars); - verifyLogicalCameraMetadata(name, device3_x, chars, deviceVersion, - cameraDeviceNames); + verifyLogicalOrUltraHighResCameraMetadata(name, device3_x, chars, deviceVersion, + cameraDeviceNames); }); ASSERT_TRUE(ret.isOk()); @@ -3264,11 +3276,12 @@ TEST_P(CameraHidlTest, configureStreamsAvailableOutputs) { sp session3_7; sp cameraDevice; sp cameraDevice3_5; + sp cameraDevice3_7; openEmptyDeviceSession(name, mProvider, &session /*out*/, &staticMeta /*out*/, &cameraDevice /*out*/); castSession(session, deviceVersion, &session3_3, &session3_4, &session3_5, &session3_6, &session3_7); - castDevice(cameraDevice, deviceVersion, &cameraDevice3_5); + castDevice(cameraDevice, deviceVersion, &cameraDevice3_5, &cameraDevice3_7); outputStreams.clear(); ASSERT_EQ(Status::OK, getAvailableOutputStreams(staticMeta, outputStreams)); @@ -3292,15 +3305,29 @@ TEST_P(CameraHidlTest, configureStreamsAvailableOutputs) { dataspaceFlag, StreamRotation::ROTATION_0}; ::android::hardware::hidl_vec streams3_2 = {stream3_2}; + ::android::hardware::camera::device::V3_7::StreamConfiguration config3_7; ::android::hardware::camera::device::V3_5::StreamConfiguration config3_5; ::android::hardware::camera::device::V3_4::StreamConfiguration config3_4; ::android::hardware::camera::device::V3_2::StreamConfiguration config3_2; - createStreamConfiguration(streams3_2, StreamConfigurationMode::NORMAL_MODE, - &config3_2, &config3_4, &config3_5, jpegBufferSize); + createStreamConfiguration(streams3_2, StreamConfigurationMode::NORMAL_MODE, &config3_2, + &config3_4, &config3_5, &config3_7, jpegBufferSize); + if (session3_5 != nullptr) { bool expectStreamCombQuery = (isLogicalMultiCamera(staticMeta) == Status::OK); - verifyStreamCombination(cameraDevice3_5, config3_4, - /*expectedStatus*/ true, expectStreamCombQuery); + verifyStreamCombination(cameraDevice3_7, config3_7, cameraDevice3_5, config3_4, + /*expectedStatus*/ true, expectStreamCombQuery); + } + + if (session3_7 != nullptr) { + config3_7.streamConfigCounter = streamConfigCounter++; + ret = session3_7->configureStreams_3_7( + config3_7, + [streamId](Status s, device::V3_6::HalStreamConfiguration halConfig) { + ASSERT_EQ(Status::OK, s); + ASSERT_EQ(1u, halConfig.streams.size()); + ASSERT_EQ(halConfig.streams[0].v3_4.v3_3.v3_2.id, streamId); + }); + } else if (session3_5 != nullptr) { config3_5.streamConfigCounter = streamConfigCounter++; ret = session3_5->configureStreams_3_5(config3_5, [streamId](Status s, device::V3_4::HalStreamConfiguration halConfig) { @@ -3352,6 +3379,8 @@ TEST_P(CameraHidlTest, configureConcurrentStreamsAvailableOutputs) { sp session3_7; sp cameraDevice; sp cameraDevice3_5; + sp cameraDevice3_7; + ::android::hardware::camera::device::V3_7::StreamConfiguration config3_7; ::android::hardware::camera::device::V3_5::StreamConfiguration config3_5; ::android::hardware::camera::device::V3_4::StreamConfiguration config3_4; ::android::hardware::camera::device::V3_2::StreamConfiguration config3_2; @@ -3388,7 +3417,7 @@ TEST_P(CameraHidlTest, configureConcurrentStreamsAvailableOutputs) { &cti.staticMeta /*out*/, &cti.cameraDevice /*out*/); castSession(cti.session, deviceVersion, &cti.session3_3, &cti.session3_4, &cti.session3_5, &cti.session3_6, &cti.session3_7); - castDevice(cti.cameraDevice, deviceVersion, &cti.cameraDevice3_5); + castDevice(cti.cameraDevice, deviceVersion, &cti.cameraDevice3_5, &cti.cameraDevice3_7); outputStreams.clear(); ASSERT_EQ(Status::OK, getMandatoryConcurrentStreams(cti.staticMeta, &outputStreams)); @@ -3420,7 +3449,7 @@ TEST_P(CameraHidlTest, configureConcurrentStreamsAvailableOutputs) { // Add the created stream configs to cameraIdsAndStreamCombinations createStreamConfiguration(streams3_2, StreamConfigurationMode::NORMAL_MODE, &cti.config3_2, &cti.config3_4, &cti.config3_5, - jpegBufferSize); + &cti.config3_7, jpegBufferSize); cti.config3_5.streamConfigCounter = outputStreams.size(); CameraIdAndStreamCombination cameraIdAndStreamCombination; @@ -3443,8 +3472,19 @@ TEST_P(CameraHidlTest, configureConcurrentStreamsAvailableOutputs) { for (const auto& cti : cameraTestInfos) { if (cti.session3_5 != nullptr) { bool expectStreamCombQuery = (isLogicalMultiCamera(cti.staticMeta) == Status::OK); - verifyStreamCombination(cti.cameraDevice3_5, cti.config3_4, + verifyStreamCombination(cti.cameraDevice3_7, cti.config3_7, cti.cameraDevice3_5, + cti.config3_4, /*expectedStatus*/ true, expectStreamCombQuery); + } + + if (cti.session3_7 != nullptr) { + ret = cti.session3_7->configureStreams_3_7( + cti.config3_7, + [&cti](Status s, device::V3_6::HalStreamConfiguration halConfig) { + ASSERT_EQ(Status::OK, s); + ASSERT_EQ(cti.config3_7.streams.size(), halConfig.streams.size()); + }); + } else if (cti.session3_5 != nullptr) { ret = cti.session3_5->configureStreams_3_5( cti.config3_5, [&cti](Status s, device::V3_4::HalStreamConfiguration halConfig) { @@ -3508,11 +3548,12 @@ TEST_P(CameraHidlTest, configureStreamsInvalidOutputs) { sp session3_7; sp cameraDevice; sp cameraDevice3_5; + sp cameraDevice3_7; openEmptyDeviceSession(name, mProvider, &session /*out*/, &staticMeta /*out*/, &cameraDevice /*out*/); castSession(session, deviceVersion, &session3_3, &session3_4, &session3_5, &session3_6, &session3_7); - castDevice(cameraDevice, deviceVersion, &cameraDevice3_5); + castDevice(cameraDevice, deviceVersion, &cameraDevice3_5, &cameraDevice3_7); outputStreams.clear(); ASSERT_EQ(Status::OK, getAvailableOutputStreams(staticMeta, outputStreams)); @@ -3533,14 +3574,26 @@ TEST_P(CameraHidlTest, configureStreamsInvalidOutputs) { StreamRotation::ROTATION_0}; uint32_t streamConfigCounter = 0; ::android::hardware::hidl_vec streams = {stream3_2}; + ::android::hardware::camera::device::V3_7::StreamConfiguration config3_7; ::android::hardware::camera::device::V3_5::StreamConfiguration config3_5; ::android::hardware::camera::device::V3_4::StreamConfiguration config3_4; ::android::hardware::camera::device::V3_2::StreamConfiguration config3_2; - createStreamConfiguration(streams, StreamConfigurationMode::NORMAL_MODE, - &config3_2, &config3_4, &config3_5, jpegBufferSize); + createStreamConfiguration(streams, StreamConfigurationMode::NORMAL_MODE, &config3_2, + &config3_4, &config3_5, &config3_7, jpegBufferSize); + if (session3_5 != nullptr) { - verifyStreamCombination(cameraDevice3_5, config3_4, /*expectedStatus*/ false, - /*expectStreamCombQuery*/false); + verifyStreamCombination(cameraDevice3_7, config3_7, cameraDevice3_5, config3_4, + /*expectedStatus*/ false, /*expectStreamCombQuery*/ false); + } + + if (session3_7 != nullptr) { + config3_7.streamConfigCounter = streamConfigCounter++; + ret = session3_7->configureStreams_3_7( + config3_7, [](Status s, device::V3_6::HalStreamConfiguration) { + ASSERT_TRUE((Status::ILLEGAL_ARGUMENT == s) || + (Status::INTERNAL_ERROR == s)); + }); + } else if (session3_5 != nullptr) { config3_5.streamConfigCounter = streamConfigCounter++; ret = session3_5->configureStreams_3_5(config3_5, [](Status s, device::V3_4::HalStreamConfiguration) { @@ -3553,7 +3606,7 @@ TEST_P(CameraHidlTest, configureStreamsInvalidOutputs) { ASSERT_TRUE((Status::ILLEGAL_ARGUMENT == s) || (Status::INTERNAL_ERROR == s)); }); - } else if(session3_3 != nullptr) { + } else if (session3_3 != nullptr) { ret = session3_3->configureStreams_3_3(config3_2, [](Status s, device::V3_3::HalStreamConfiguration) { ASSERT_TRUE((Status::ILLEGAL_ARGUMENT == s) || @@ -3577,8 +3630,8 @@ TEST_P(CameraHidlTest, configureStreamsInvalidOutputs) { 0, StreamRotation::ROTATION_0}; streams[0] = stream3_2; - createStreamConfiguration(streams, StreamConfigurationMode::NORMAL_MODE, - &config3_2, &config3_4, &config3_5, jpegBufferSize); + createStreamConfiguration(streams, StreamConfigurationMode::NORMAL_MODE, &config3_2, + &config3_4, &config3_5, &config3_7, jpegBufferSize); if (session3_5 != nullptr) { config3_5.streamConfigCounter = streamConfigCounter++; ret = session3_5->configureStreams_3_5(config3_5, [](Status s, @@ -3613,8 +3666,8 @@ TEST_P(CameraHidlTest, configureStreamsInvalidOutputs) { 0, StreamRotation::ROTATION_0}; streams[0] = stream3_2; - createStreamConfiguration(streams, StreamConfigurationMode::NORMAL_MODE, - &config3_2, &config3_4, &config3_5, jpegBufferSize); + createStreamConfiguration(streams, StreamConfigurationMode::NORMAL_MODE, &config3_2, + &config3_4, &config3_5, &config3_7, jpegBufferSize); if (session3_5 != nullptr) { config3_5.streamConfigCounter = streamConfigCounter++; ret = session3_5->configureStreams_3_5(config3_5, @@ -3648,8 +3701,8 @@ TEST_P(CameraHidlTest, configureStreamsInvalidOutputs) { 0, static_cast(UINT32_MAX)}; streams[0] = stream3_2; - createStreamConfiguration(streams, StreamConfigurationMode::NORMAL_MODE, - &config3_2, &config3_4, &config3_5, jpegBufferSize); + createStreamConfiguration(streams, StreamConfigurationMode::NORMAL_MODE, &config3_2, + &config3_4, &config3_5, &config3_7, jpegBufferSize); if (session3_5 != nullptr) { config3_5.streamConfigCounter = streamConfigCounter++; ret = session3_5->configureStreams_3_5(config3_5, @@ -3708,11 +3761,12 @@ TEST_P(CameraHidlTest, configureStreamsZSLInputOutputs) { sp session3_7; sp cameraDevice; sp cameraDevice3_5; + sp cameraDevice3_7; openEmptyDeviceSession(name, mProvider, &session /*out*/, &staticMeta /*out*/, &cameraDevice /*out*/); castSession(session, deviceVersion, &session3_3, &session3_4, &session3_5, &session3_6, &session3_7); - castDevice(cameraDevice, deviceVersion, &cameraDevice3_5); + castDevice(cameraDevice, deviceVersion, &cameraDevice3_5, &cameraDevice3_7); Status rc = isZSLModeAvailable(staticMeta); if (Status::METHOD_NOT_SUPPORTED == rc) { @@ -3797,14 +3851,27 @@ TEST_P(CameraHidlTest, configureStreamsZSLInputOutputs) { ::android::hardware::hidl_vec streams = {inputStream, zslStream, outputStream}; + ::android::hardware::camera::device::V3_7::StreamConfiguration config3_7; ::android::hardware::camera::device::V3_5::StreamConfiguration config3_5; ::android::hardware::camera::device::V3_4::StreamConfiguration config3_4; ::android::hardware::camera::device::V3_2::StreamConfiguration config3_2; - createStreamConfiguration(streams, StreamConfigurationMode::NORMAL_MODE, - &config3_2, &config3_4, &config3_5, jpegBufferSize); + createStreamConfiguration(streams, StreamConfigurationMode::NORMAL_MODE, &config3_2, + &config3_4, &config3_5, &config3_7, jpegBufferSize); if (session3_5 != nullptr) { - verifyStreamCombination(cameraDevice3_5, config3_4, - /*expectedStatus*/ true, /*expectStreamCombQuery*/ false); + verifyStreamCombination(cameraDevice3_7, config3_7, cameraDevice3_5, config3_4, + /*expectedStatus*/ true, + /*expectStreamCombQuery*/ false); + } + + if (session3_7 != nullptr) { + config3_7.streamConfigCounter = streamConfigCounter++; + ret = session3_7->configureStreams_3_7( + config3_7, + [](Status s, device::V3_6::HalStreamConfiguration halConfig) { + ASSERT_EQ(Status::OK, s); + ASSERT_EQ(3u, halConfig.streams.size()); + }); + } else if (session3_5 != nullptr) { config3_5.streamConfigCounter = streamConfigCounter++; ret = session3_5->configureStreams_3_5(config3_5, [](Status s, device::V3_4::HalStreamConfiguration halConfig) { @@ -3927,6 +3994,7 @@ TEST_P(CameraHidlTest, configureStreamsWithSessionParameters) { ::android::hardware::hidl_vec streams = {previewStream}; ::android::hardware::camera::device::V3_4::StreamConfiguration config; ::android::hardware::camera::device::V3_5::StreamConfiguration config3_5; + ::android::hardware::camera::device::V3_7::StreamConfiguration config3_7; config.streams = streams; config.operationMode = StreamConfigurationMode::NORMAL_MODE; modifiedSessionParams = sessionParams; @@ -3935,6 +4003,13 @@ TEST_P(CameraHidlTest, configureStreamsWithSessionParameters) { get_camera_metadata_size(sessionParamsBuffer)); config3_5.v3_4 = config; config3_5.streamConfigCounter = 0; + config3_7.streams = {{previewStream, -1, {ANDROID_SENSOR_PIXEL_MODE_DEFAULT}}}; + config3_7.operationMode = config.operationMode; + config3_7.sessionParams.setToExternal(reinterpret_cast(sessionParamsBuffer), + get_camera_metadata_size(sessionParamsBuffer)); + config3_7.streamConfigCounter = 0; + config3_7.multiResolutionInputImage = false; + if (session3_5 != nullptr) { bool newSessionParamsAvailable = false; for (const auto& it : availableSessionKeys) { @@ -3950,7 +4025,15 @@ TEST_P(CameraHidlTest, configureStreamsWithSessionParameters) { modifiedSessionParamsBuffer); modifiedSessionParams.acquire(modifiedSessionParamsBuffer); } + } + if (session3_7 != nullptr) { + ret = session3_7->configureStreams_3_7( + config3_7, [](Status s, device::V3_6::HalStreamConfiguration halConfig) { + ASSERT_EQ(Status::OK, s); + ASSERT_EQ(1u, halConfig.streams.size()); + }); + } else if (session3_5 != nullptr) { ret = session3_5->configureStreams_3_5(config3_5, [](Status s, device::V3_4::HalStreamConfiguration halConfig) { ASSERT_EQ(Status::OK, s); @@ -4003,11 +4086,12 @@ TEST_P(CameraHidlTest, configureStreamsPreviewStillOutputs) { sp session3_7; sp cameraDevice; sp cameraDevice3_5; + sp cameraDevice3_7; openEmptyDeviceSession(name, mProvider, &session /*out*/, &staticMeta /*out*/, &cameraDevice /*out*/); castSession(session, deviceVersion, &session3_3, &session3_4, &session3_5, &session3_6, &session3_7); - castDevice(cameraDevice, deviceVersion, &cameraDevice3_5); + castDevice(cameraDevice, deviceVersion, &cameraDevice3_5, &cameraDevice3_7); // Check if camera support depth only if (isDepthOnly(staticMeta)) { @@ -4054,14 +4138,27 @@ TEST_P(CameraHidlTest, configureStreamsPreviewStillOutputs) { StreamRotation::ROTATION_0}; ::android::hardware::hidl_vec streams = {previewStream, blobStream}; + ::android::hardware::camera::device::V3_7::StreamConfiguration config3_7; ::android::hardware::camera::device::V3_5::StreamConfiguration config3_5; ::android::hardware::camera::device::V3_4::StreamConfiguration config3_4; ::android::hardware::camera::device::V3_2::StreamConfiguration config3_2; - createStreamConfiguration(streams, StreamConfigurationMode::NORMAL_MODE, - &config3_2, &config3_4, &config3_5, jpegBufferSize); + createStreamConfiguration(streams, StreamConfigurationMode::NORMAL_MODE, &config3_2, + &config3_4, &config3_5, &config3_7, jpegBufferSize); if (session3_5 != nullptr) { - verifyStreamCombination(cameraDevice3_5, config3_4, - /*expectedStatus*/ true, /*expectStreamCombQuery*/ false); + verifyStreamCombination(cameraDevice3_7, config3_7, cameraDevice3_5, config3_4, + /*expectedStatus*/ true, + /*expectStreamCombQuery*/ false); + } + + if (session3_7 != nullptr) { + config3_7.streamConfigCounter = streamConfigCounter++; + ret = session3_7->configureStreams_3_7( + config3_7, + [](Status s, device::V3_6::HalStreamConfiguration halConfig) { + ASSERT_EQ(Status::OK, s); + ASSERT_EQ(2u, halConfig.streams.size()); + }); + } else if (session3_5 != nullptr) { config3_5.streamConfigCounter = streamConfigCounter++; ret = session3_5->configureStreams_3_5(config3_5, [](Status s, device::V3_4::HalStreamConfiguration halConfig) { @@ -4123,11 +4220,12 @@ TEST_P(CameraHidlTest, configureStreamsConstrainedOutputs) { sp session3_7; sp cameraDevice; sp cameraDevice3_5; + sp cameraDevice3_7; openEmptyDeviceSession(name, mProvider, &session /*out*/, &staticMeta /*out*/, &cameraDevice /*out*/); castSession(session, deviceVersion, &session3_3, &session3_4, &session3_5, &session3_6, &session3_7); - castDevice(cameraDevice, deviceVersion, &cameraDevice3_5); + castDevice(cameraDevice, deviceVersion, &cameraDevice3_5, &cameraDevice3_7); Status rc = isConstrainedModeAvailable(staticMeta); if (Status::METHOD_NOT_SUPPORTED == rc) { @@ -4152,14 +4250,27 @@ TEST_P(CameraHidlTest, configureStreamsConstrainedOutputs) { 0, StreamRotation::ROTATION_0}; ::android::hardware::hidl_vec streams = {stream}; + ::android::hardware::camera::device::V3_7::StreamConfiguration config3_7; ::android::hardware::camera::device::V3_5::StreamConfiguration config3_5; ::android::hardware::camera::device::V3_4::StreamConfiguration config3_4; ::android::hardware::camera::device::V3_2::StreamConfiguration config3_2; createStreamConfiguration(streams, StreamConfigurationMode::CONSTRAINED_HIGH_SPEED_MODE, - &config3_2, &config3_4, &config3_5); + &config3_2, &config3_4, &config3_5, &config3_7); if (session3_5 != nullptr) { - verifyStreamCombination(cameraDevice3_5, config3_4, - /*expectedStatus*/ true, /*expectStreamCombQuery*/ false); + verifyStreamCombination(cameraDevice3_7, config3_7, cameraDevice3_5, config3_4, + /*expectedStatus*/ true, /*expectStreamCombQuery*/ false); + } + + if (session3_7 != nullptr) { + config3_7.streamConfigCounter = streamConfigCounter++; + ret = session3_7->configureStreams_3_7( + config3_7, + [streamId](Status s, device::V3_6::HalStreamConfiguration halConfig) { + ASSERT_EQ(Status::OK, s); + ASSERT_EQ(1u, halConfig.streams.size()); + ASSERT_EQ(halConfig.streams[0].v3_4.v3_3.v3_2.id, streamId); + }); + } else if (session3_5 != nullptr) { config3_5.streamConfigCounter = streamConfigCounter++; ret = session3_5->configureStreams_3_5(config3_5, [streamId](Status s, device::V3_4::HalStreamConfiguration halConfig) { @@ -4201,8 +4312,15 @@ TEST_P(CameraHidlTest, configureStreamsConstrainedOutputs) { StreamRotation::ROTATION_0}; streams[0] = stream; createStreamConfiguration(streams, StreamConfigurationMode::CONSTRAINED_HIGH_SPEED_MODE, - &config3_2, &config3_4, &config3_5); - if (session3_5 != nullptr) { + &config3_2, &config3_4, &config3_5, &config3_7); + if (session3_7 != nullptr) { + config3_7.streamConfigCounter = streamConfigCounter++; + ret = session3_7->configureStreams_3_7( + config3_7, [](Status s, device::V3_6::HalStreamConfiguration) { + ASSERT_TRUE((Status::ILLEGAL_ARGUMENT == s) || + (Status::INTERNAL_ERROR == s)); + }); + } else if (session3_5 != nullptr) { config3_5.streamConfigCounter = streamConfigCounter++; ret = session3_5->configureStreams_3_5(config3_5, [](Status s, device::V3_4::HalStreamConfiguration) { @@ -4240,8 +4358,14 @@ TEST_P(CameraHidlTest, configureStreamsConstrainedOutputs) { StreamRotation::ROTATION_0}; streams[0] = stream; createStreamConfiguration(streams, StreamConfigurationMode::CONSTRAINED_HIGH_SPEED_MODE, - &config3_2, &config3_4, &config3_5); - if (session3_5 != nullptr) { + &config3_2, &config3_4, &config3_5, &config3_7); + if (session3_7 != nullptr) { + config3_7.streamConfigCounter = streamConfigCounter++; + ret = session3_7->configureStreams_3_7( + config3_7, [](Status s, device::V3_6::HalStreamConfiguration) { + ASSERT_EQ(Status::ILLEGAL_ARGUMENT, s); + }); + } else if (session3_5 != nullptr) { config3_5.streamConfigCounter = streamConfigCounter++; ret = session3_5->configureStreams_3_5(config3_5, [](Status s, device::V3_4::HalStreamConfiguration) { @@ -4275,8 +4399,14 @@ TEST_P(CameraHidlTest, configureStreamsConstrainedOutputs) { StreamRotation::ROTATION_0}; streams[0] = stream; createStreamConfiguration(streams, StreamConfigurationMode::CONSTRAINED_HIGH_SPEED_MODE, - &config3_2, &config3_4, &config3_5); - if (session3_5 != nullptr) { + &config3_2, &config3_4, &config3_5, &config3_7); + if (session3_7 != nullptr) { + config3_7.streamConfigCounter = streamConfigCounter++; + ret = session3_7->configureStreams_3_7( + config3_7, [](Status s, device::V3_6::HalStreamConfiguration) { + ASSERT_EQ(Status::ILLEGAL_ARGUMENT, s); + }); + } else if (session3_5 != nullptr) { config3_5.streamConfigCounter = streamConfigCounter++; ret = session3_5->configureStreams_3_5(config3_5, [](Status s, device::V3_4::HalStreamConfiguration) { @@ -4337,11 +4467,12 @@ TEST_P(CameraHidlTest, configureStreamsVideoStillOutputs) { sp session3_7; sp cameraDevice; sp cameraDevice3_5; + sp cameraDevice3_7; openEmptyDeviceSession(name, mProvider, &session /*out*/, &staticMeta /*out*/, &cameraDevice /*out*/); castSession(session, deviceVersion, &session3_3, &session3_4, &session3_5, &session3_6, &session3_7); - castDevice(cameraDevice, deviceVersion, &cameraDevice3_5); + castDevice(cameraDevice, deviceVersion, &cameraDevice3_5, &cameraDevice3_7); // Check if camera support depth only if (isDepthOnly(staticMeta)) { @@ -4388,14 +4519,27 @@ TEST_P(CameraHidlTest, configureStreamsVideoStillOutputs) { static_cast(Dataspace::V0_JFIF), StreamRotation::ROTATION_0}; ::android::hardware::hidl_vec streams = {videoStream, blobStream}; + ::android::hardware::camera::device::V3_7::StreamConfiguration config3_7; ::android::hardware::camera::device::V3_5::StreamConfiguration config3_5; ::android::hardware::camera::device::V3_4::StreamConfiguration config3_4; ::android::hardware::camera::device::V3_2::StreamConfiguration config3_2; - createStreamConfiguration(streams, StreamConfigurationMode::NORMAL_MODE, - &config3_2, &config3_4, &config3_5, jpegBufferSize); + createStreamConfiguration(streams, StreamConfigurationMode::NORMAL_MODE, &config3_2, + &config3_4, &config3_5, &config3_7, jpegBufferSize); if (session3_5 != nullptr) { - verifyStreamCombination(cameraDevice3_5, config3_4, - /*expectedStatus*/ true, /*expectStreamCombQuery*/ false); + verifyStreamCombination(cameraDevice3_7, config3_7, cameraDevice3_5, config3_4, + /*expectedStatus*/ true, + /*expectStreamCombQuery*/ false); + } + + if (session3_7 != nullptr) { + config3_7.streamConfigCounter = streamConfigCounter++; + ret = session3_7->configureStreams_3_7( + config3_7, + [](Status s, device::V3_6::HalStreamConfiguration halConfig) { + ASSERT_EQ(Status::OK, s); + ASSERT_EQ(2u, halConfig.streams.size()); + }); + } else if (session3_5 != nullptr) { config3_5.streamConfigCounter = streamConfigCounter++; ret = session3_5->configureStreams_3_5(config3_5, [](Status s, device::V3_4::HalStreamConfiguration halConfig) { @@ -6142,6 +6286,28 @@ Status CameraHidlTest::getSystemCameraKind(const camera_metadata_t* staticMeta, return ret; } +void CameraHidlTest::getMultiResolutionStreamConfigurations( + camera_metadata_ro_entry* multiResStreamConfigs, camera_metadata_ro_entry* streamConfigs, + camera_metadata_ro_entry* maxResolutionStreamConfigs, + const camera_metadata_t* staticMetadata) { + ASSERT_NE(multiResStreamConfigs, nullptr); + ASSERT_NE(streamConfigs, nullptr); + ASSERT_NE(maxResolutionStreamConfigs, nullptr); + ASSERT_NE(staticMetadata, nullptr); + + int retcode = find_camera_metadata_ro_entry( + staticMetadata, ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS, streamConfigs); + ASSERT_TRUE(0 == retcode); + retcode = find_camera_metadata_ro_entry( + staticMetadata, ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_MAXIMUM_RESOLUTION, + maxResolutionStreamConfigs); + ASSERT_TRUE(-ENOENT == retcode || 0 == retcode); + retcode = find_camera_metadata_ro_entry( + staticMetadata, ANDROID_SCALER_PHYSICAL_CAMERA_MULTI_RESOLUTION_STREAM_CONFIGURATIONS, + multiResStreamConfigs); + ASSERT_TRUE(-ENOENT == retcode || 0 == retcode); +} + // Select an appropriate dataspace given a specific pixel format. V3_2::DataspaceFlags CameraHidlTest::getDataspace(PixelFormat format) { switch (format) { @@ -6245,15 +6411,18 @@ Status CameraHidlTest::isAutoFocusModeAvailable( void CameraHidlTest::createStreamConfiguration( const ::android::hardware::hidl_vec& streams3_2, StreamConfigurationMode configMode, - ::android::hardware::camera::device::V3_2::StreamConfiguration *config3_2 /*out*/, - ::android::hardware::camera::device::V3_4::StreamConfiguration *config3_4 /*out*/, - ::android::hardware::camera::device::V3_5::StreamConfiguration *config3_5 /*out*/, + ::android::hardware::camera::device::V3_2::StreamConfiguration* config3_2 /*out*/, + ::android::hardware::camera::device::V3_4::StreamConfiguration* config3_4 /*out*/, + ::android::hardware::camera::device::V3_5::StreamConfiguration* config3_5 /*out*/, + ::android::hardware::camera::device::V3_7::StreamConfiguration* config3_7 /*out*/, uint32_t jpegBufferSize) { ASSERT_NE(nullptr, config3_2); ASSERT_NE(nullptr, config3_4); ASSERT_NE(nullptr, config3_5); + ASSERT_NE(nullptr, config3_7); ::android::hardware::hidl_vec streams3_4(streams3_2.size()); + ::android::hardware::hidl_vec streams3_7(streams3_2.size()); size_t idx = 0; for (auto& stream3_2 : streams3_2) { V3_4::Stream stream; @@ -6263,9 +6432,12 @@ void CameraHidlTest::createStreamConfiguration( stream3_2.dataSpace == static_cast(Dataspace::V0_JFIF)) { stream.bufferSize = jpegBufferSize; } - streams3_4[idx++] = stream; + streams3_4[idx] = stream; + streams3_7[idx] = {stream, /*groupId*/ -1, {ANDROID_SENSOR_PIXEL_MODE_DEFAULT}}; + idx++; } // Caller is responsible to fill in non-zero config3_5->streamConfigCounter after this returns + *config3_7 = {streams3_7, configMode, {}, 0, false}; *config3_5 = {{streams3_4, configMode, {}}, 0}; *config3_4 = config3_5->v3_4; *config3_2 = {streams3_2, configMode}; @@ -6379,8 +6551,9 @@ void CameraHidlTest::configureStreams3_7( ASSERT_TRUE(ret.isOk()); ASSERT_TRUE(deviceVersion >= CAMERA_DEVICE_API_VERSION_3_7); + sp cameraDevice3_5 = nullptr; sp cameraDevice3_7 = nullptr; - castDevice3_7(device3_x, deviceVersion, &cameraDevice3_7); + castDevice(device3_x, deviceVersion, &cameraDevice3_5, &cameraDevice3_7); ASSERT_NE(cameraDevice3_7, nullptr); bool supported = false; ret = cameraDevice3_7->isStreamCombinationSupported_3_7( @@ -6532,7 +6705,8 @@ void CameraHidlTest::configurePreviewStreams3_4(const std::string &name, int32_t ASSERT_TRUE(!allowUnsupport || deviceVersion >= CAMERA_DEVICE_API_VERSION_3_5); if (allowUnsupport) { sp cameraDevice3_5; - castDevice(device3_x, deviceVersion, &cameraDevice3_5); + sp cameraDevice3_7; + castDevice(device3_x, deviceVersion, &cameraDevice3_5, &cameraDevice3_7); bool supported = false; ret = cameraDevice3_5->isStreamCombinationSupported(config3_4, @@ -6891,9 +7065,32 @@ void CameraHidlTest::configureSingleStream( ::android::hardware::camera::device::V3_2::StreamConfiguration config3_2; ::android::hardware::camera::device::V3_4::StreamConfiguration config3_4; ::android::hardware::camera::device::V3_5::StreamConfiguration config3_5; - createStreamConfiguration(streams3_2, StreamConfigurationMode::NORMAL_MODE, - &config3_2, &config3_4, &config3_5, jpegBufferSize); - if (session3_5 != nullptr) { + ::android::hardware::camera::device::V3_7::StreamConfiguration config3_7; + createStreamConfiguration(streams3_2, StreamConfigurationMode::NORMAL_MODE, &config3_2, + &config3_4, &config3_5, &config3_7, jpegBufferSize); + if (session3_7 != nullptr) { + ret = session3_7->constructDefaultRequestSettings( + reqTemplate, [&config3_7](auto status, const auto& req) { + ASSERT_EQ(Status::OK, status); + config3_7.sessionParams = req; + }); + ASSERT_TRUE(ret.isOk()); + config3_7.streamConfigCounter = streamConfigCounter; + ret = session3_7->configureStreams_3_7( + config3_7, [&](Status s, device::V3_6::HalStreamConfiguration halConfig) { + ASSERT_EQ(Status::OK, s); + ASSERT_EQ(1u, halConfig.streams.size()); + halStreamConfig->streams.resize(1); + halStreamConfig->streams[0] = halConfig.streams[0].v3_4.v3_3.v3_2; + if (*useHalBufManager) { + hidl_vec streams(1); + hidl_vec halStreams(1); + streams[0] = config3_4.streams[0]; + halStreams[0] = halConfig.streams[0].v3_4.v3_3.v3_2; + cb->setCurrentStreamConfig(streams, halStreams); + } + }); + } else if (session3_5 != nullptr) { ret = session3_5->constructDefaultRequestSettings(reqTemplate, [&config3_5](auto status, const auto& req) { ASSERT_EQ(Status::OK, status); @@ -6953,31 +7150,30 @@ void CameraHidlTest::configureSingleStream( ASSERT_TRUE(ret.isOk()); } -void CameraHidlTest::castDevice3_7(const sp& device, - int32_t deviceVersion, - sp* device3_7 /*out*/) { - ASSERT_NE(nullptr, device3_7); - if (deviceVersion >= CAMERA_DEVICE_API_VERSION_3_7) { - auto castResult = device::V3_7::ICameraDevice::castFrom(device); - ASSERT_TRUE(castResult.isOk()); - *device3_7 = castResult; - } -} - -void CameraHidlTest::castDevice(const sp &device, - int32_t deviceVersion, sp *device3_5/*out*/) { +void CameraHidlTest::castDevice(const sp& device, + int32_t deviceVersion, + sp* device3_5 /*out*/, + sp* device3_7 /*out*/) { ASSERT_NE(nullptr, device3_5); if (deviceVersion == CAMERA_DEVICE_API_VERSION_3_5) { auto castResult = device::V3_5::ICameraDevice::castFrom(device); ASSERT_TRUE(castResult.isOk()); *device3_5 = castResult; } + + ASSERT_NE(nullptr, device3_7); + if (deviceVersion == CAMERA_DEVICE_API_VERSION_3_7) { + auto castResult = device::V3_7::ICameraDevice::castFrom(device); + ASSERT_TRUE(castResult.isOk()); + *device3_7 = castResult; + } } //Cast camera provider to corresponding version if available void CameraHidlTest::castProvider(const sp& provider, sp* provider2_5 /*out*/, - sp* provider2_6 /*out*/) { + sp* provider2_6 /*out*/, + sp* provider2_7 /*out*/) { ASSERT_NE(nullptr, provider2_5); auto castResult2_5 = provider::V2_5::ICameraProvider::castFrom(provider); if (castResult2_5.isOk()) { @@ -6989,6 +7185,12 @@ void CameraHidlTest::castProvider(const sp& provider, if (castResult2_6.isOk()) { *provider2_6 = castResult2_6; } + + ASSERT_NE(nullptr, provider2_7); + auto castResult2_7 = provider::V2_7::ICameraProvider::castFrom(provider); + if (castResult2_7.isOk()) { + *provider2_7 = castResult2_7; + } } //Cast camera device session to corresponding version @@ -7041,9 +7243,24 @@ void CameraHidlTest::castSession(const sp &session, int32_ } } -void CameraHidlTest::verifyStreamCombination(sp cameraDevice3_5, - const ::android::hardware::camera::device::V3_4::StreamConfiguration &config3_4, +void CameraHidlTest::verifyStreamCombination( + sp cameraDevice3_7, + const ::android::hardware::camera::device::V3_7::StreamConfiguration& config3_7, + sp cameraDevice3_5, + const ::android::hardware::camera::device::V3_4::StreamConfiguration& config3_4, bool expectedStatus, bool expectMethodSupported) { + if (cameraDevice3_7.get() != nullptr) { + auto ret = cameraDevice3_7->isStreamCombinationSupported_3_7( + config3_7, [expectedStatus, expectMethodSupported](Status s, bool combStatus) { + ASSERT_TRUE((Status::OK == s) || + (!expectMethodSupported && Status::METHOD_NOT_SUPPORTED == s)); + if (Status::OK == s) { + ASSERT_TRUE(combStatus == expectedStatus); + } + }); + ASSERT_TRUE(ret.isOk()); + } + if (cameraDevice3_5.get() != nullptr) { auto ret = cameraDevice3_5->isStreamCombinationSupported(config3_4, [expectedStatus, expectMethodSupported] (Status s, bool combStatus) { @@ -7057,11 +7274,11 @@ void CameraHidlTest::verifyStreamCombination(sp cam } } -// Verify logical camera static metadata -void CameraHidlTest::verifyLogicalCameraMetadata(const std::string& cameraName, +// Verify logical or ultra high resolution camera static metadata +void CameraHidlTest::verifyLogicalOrUltraHighResCameraMetadata( + const std::string& cameraName, const ::android::sp<::android::hardware::camera::device::V3_2::ICameraDevice>& device, - const CameraMetadata &chars, int deviceVersion, - const hidl_vec& deviceNames) { + const CameraMetadata& chars, int deviceVersion, const hidl_vec& deviceNames) { const camera_metadata_t* metadata = (camera_metadata_t*)chars.data(); ASSERT_NE(nullptr, metadata); SystemCameraKind systemCameraKind = SystemCameraKind::PUBLIC; @@ -7069,7 +7286,9 @@ void CameraHidlTest::verifyLogicalCameraMetadata(const std::string& cameraName, ASSERT_EQ(rc, Status::OK); rc = isLogicalMultiCamera(metadata); ASSERT_TRUE(Status::OK == rc || Status::METHOD_NOT_SUPPORTED == rc); - if (Status::METHOD_NOT_SUPPORTED == rc) { + bool isMultiCamera = (Status::OK == rc); + bool isUltraHighResCamera = isUltraHighResolution(metadata); + if (!isMultiCamera && !isUltraHighResCamera) { return; } @@ -7077,13 +7296,36 @@ void CameraHidlTest::verifyLogicalCameraMetadata(const std::string& cameraName, int retcode = find_camera_metadata_ro_entry(metadata, ANDROID_CONTROL_ZOOM_RATIO_RANGE, &entry); bool hasZoomRatioRange = (0 == retcode && entry.count == 2); + retcode = find_camera_metadata_ro_entry( + metadata, ANDROID_INFO_SUPPORTED_BUFFER_MANAGEMENT_VERSION, &entry); + bool hasHalBufferManager = + (0 == retcode && 1 == entry.count && + entry.data.i32[0] == ANDROID_INFO_SUPPORTED_BUFFER_MANAGEMENT_VERSION_HIDL_DEVICE_3_5); + retcode = find_camera_metadata_ro_entry( + metadata, ANDROID_SCALER_MULTI_RESOLUTION_STREAM_SUPPORTED, &entry); + bool multiResolutionStreamSupported = + (0 == retcode && 1 == entry.count && + entry.data.u8[0] == ANDROID_SCALER_MULTI_RESOLUTION_STREAM_SUPPORTED_TRUE); + if (multiResolutionStreamSupported) { + ASSERT_TRUE(hasHalBufferManager); + } std::string version, cameraId; ASSERT_TRUE(::matchDeviceName(cameraName, mProviderType, &version, &cameraId)); std::unordered_set physicalIds; - ASSERT_TRUE(Status::OK == getPhysicalCameraIds(metadata, &physicalIds)); + rc = getPhysicalCameraIds(metadata, &physicalIds); + ASSERT_TRUE(isUltraHighResCamera || Status::OK == rc); for (auto physicalId : physicalIds) { ASSERT_NE(physicalId, cameraId); + } + if (physicalIds.size() == 0) { + ASSERT_TRUE(isUltraHighResCamera && !isMultiCamera); + physicalIds.insert(cameraId); + } + // Map from image format to number of multi-resolution sizes for that format + std::unordered_map multiResOutputFormatCounterMap; + std::unordered_map multiResInputFormatCounterMap; + for (auto physicalId : physicalIds) { bool isPublicId = false; std::string fullPublicId; SystemCameraKind physSystemCameraKind = SystemCameraKind::PUBLIC; @@ -7096,6 +7338,11 @@ void CameraHidlTest::verifyLogicalCameraMetadata(const std::string& cameraName, break; } } + + camera_metadata_ro_entry physicalMultiResStreamConfigs; + camera_metadata_ro_entry physicalStreamConfigs; + camera_metadata_ro_entry physicalMaxResolutionStreamConfigs; + bool isUltraHighRes = false; if (isPublicId) { ::android::sp<::android::hardware::camera::device::V3_2::ICameraDevice> subDevice; Return ret; @@ -7107,62 +7354,195 @@ void CameraHidlTest::verifyLogicalCameraMetadata(const std::string& cameraName, }); ASSERT_TRUE(ret.isOk()); - ret = subDevice->getCameraCharacteristics( - [&](auto status, const auto& chars) { + ret = subDevice->getCameraCharacteristics([&](auto status, const auto& chars) { ASSERT_EQ(Status::OK, status); - const camera_metadata_t* staticMeta = + const camera_metadata_t* staticMetadata = reinterpret_cast(chars.data()); - rc = getSystemCameraKind(staticMeta, &physSystemCameraKind); + rc = getSystemCameraKind(staticMetadata, &physSystemCameraKind); ASSERT_EQ(rc, Status::OK); // Make sure that the system camera kind of a non-hidden // physical cameras is the same as the logical camera associated // with it. ASSERT_EQ(physSystemCameraKind, systemCameraKind); - retcode = find_camera_metadata_ro_entry(staticMeta, + retcode = find_camera_metadata_ro_entry(staticMetadata, ANDROID_CONTROL_ZOOM_RATIO_RANGE, &entry); bool subCameraHasZoomRatioRange = (0 == retcode && entry.count == 2); ASSERT_EQ(hasZoomRatioRange, subCameraHasZoomRatioRange); + + getMultiResolutionStreamConfigurations( + &physicalMultiResStreamConfigs, &physicalStreamConfigs, + &physicalMaxResolutionStreamConfigs, staticMetadata); + isUltraHighRes = isUltraHighResolution(staticMetadata); }); ASSERT_TRUE(ret.isOk()); - continue; + } else { + ASSERT_TRUE(deviceVersion >= CAMERA_DEVICE_API_VERSION_3_5); + auto castResult = device::V3_5::ICameraDevice::castFrom(device); + ASSERT_TRUE(castResult.isOk()); + ::android::sp<::android::hardware::camera::device::V3_5::ICameraDevice> device3_5 = + castResult; + ASSERT_NE(device3_5, nullptr); + + // Check camera characteristics for hidden camera id + Return ret = device3_5->getPhysicalCameraCharacteristics( + physicalId, [&](auto status, const auto& chars) { + verifyCameraCharacteristics(status, chars); + verifyMonochromeCharacteristics(chars, deviceVersion); + + auto staticMetadata = (const camera_metadata_t*)chars.data(); + retcode = find_camera_metadata_ro_entry( + staticMetadata, ANDROID_CONTROL_ZOOM_RATIO_RANGE, &entry); + bool subCameraHasZoomRatioRange = (0 == retcode && entry.count == 2); + ASSERT_EQ(hasZoomRatioRange, subCameraHasZoomRatioRange); + + getMultiResolutionStreamConfigurations( + &physicalMultiResStreamConfigs, &physicalStreamConfigs, + &physicalMaxResolutionStreamConfigs, staticMetadata); + isUltraHighRes = isUltraHighResolution(staticMetadata); + }); + ASSERT_TRUE(ret.isOk()); + + // Check calling getCameraDeviceInterface_V3_x() on hidden camera id returns + // ILLEGAL_ARGUMENT. + std::stringstream s; + s << "device@" << version << "/" << mProviderType << "/" << physicalId; + hidl_string fullPhysicalId(s.str()); + ret = mProvider->getCameraDeviceInterface_V3_x( + fullPhysicalId, [&](auto status, const auto& device3_x) { + ASSERT_EQ(Status::ILLEGAL_ARGUMENT, status); + ASSERT_EQ(device3_x, nullptr); + }); + ASSERT_TRUE(ret.isOk()); } - ASSERT_TRUE(deviceVersion >= CAMERA_DEVICE_API_VERSION_3_5); - auto castResult = device::V3_5::ICameraDevice::castFrom(device); - ASSERT_TRUE(castResult.isOk()); - ::android::sp<::android::hardware::camera::device::V3_5::ICameraDevice> device3_5 = - castResult; - ASSERT_NE(device3_5, nullptr); + if (physicalMultiResStreamConfigs.count > 0) { + ASSERT_GE(deviceVersion, CAMERA_DEVICE_API_VERSION_3_7); + ASSERT_EQ(physicalMultiResStreamConfigs.count % 4, 0); - // Check camera characteristics for hidden camera id - Return ret = device3_5->getPhysicalCameraCharacteristics( - physicalId, [&](auto status, const auto& chars) { - verifyCameraCharacteristics(status, chars); - verifyMonochromeCharacteristics(chars, deviceVersion); - retcode = - find_camera_metadata_ro_entry((const camera_metadata_t*)chars.data(), - ANDROID_CONTROL_ZOOM_RATIO_RANGE, &entry); - bool subCameraHasZoomRatioRange = (0 == retcode && entry.count == 2); - ASSERT_EQ(hasZoomRatioRange, subCameraHasZoomRatioRange); - }); - ASSERT_TRUE(ret.isOk()); + // Each supported size must be max size for that format, + for (size_t i = 0; i < physicalMultiResStreamConfigs.count / 4; i++) { + int32_t multiResFormat = physicalMultiResStreamConfigs.data.i32[i * 4]; + int32_t multiResWidth = physicalMultiResStreamConfigs.data.i32[i * 4 + 1]; + int32_t multiResHeight = physicalMultiResStreamConfigs.data.i32[i * 4 + 2]; + int32_t multiResInput = physicalMultiResStreamConfigs.data.i32[i * 4 + 3]; - // Check calling getCameraDeviceInterface_V3_x() on hidden camera id returns - // ILLEGAL_ARGUMENT. - std::stringstream s; - s << "device@" << version << "/" << mProviderType << "/" << physicalId; - hidl_string fullPhysicalId(s.str()); - ret = mProvider->getCameraDeviceInterface_V3_x(fullPhysicalId, - [&](auto status, const auto& device3_x) { - ASSERT_EQ(Status::ILLEGAL_ARGUMENT, status); - ASSERT_EQ(device3_x, nullptr); - }); - ASSERT_TRUE(ret.isOk()); + // Check if the resolution is the max resolution in stream + // configuration map + bool supported = false; + bool isMaxSize = true; + for (size_t j = 0; j < physicalStreamConfigs.count / 4; j++) { + int32_t format = physicalStreamConfigs.data.i32[j * 4]; + int32_t width = physicalStreamConfigs.data.i32[j * 4 + 1]; + int32_t height = physicalStreamConfigs.data.i32[j * 4 + 2]; + int32_t input = physicalStreamConfigs.data.i32[j * 4 + 3]; + if (format == multiResFormat && input == multiResInput) { + if (width == multiResWidth && height == multiResHeight) { + supported = true; + } else if (width * height > multiResWidth * multiResHeight) { + isMaxSize = false; + } + } + } + // Check if the resolution is the max resolution in max + // resolution stream configuration map + bool supportedUltraHighRes = false; + bool isUltraHighResMaxSize = true; + for (size_t j = 0; j < physicalMaxResolutionStreamConfigs.count / 4; j++) { + int32_t format = physicalMaxResolutionStreamConfigs.data.i32[j * 4]; + int32_t width = physicalMaxResolutionStreamConfigs.data.i32[j * 4 + 1]; + int32_t height = physicalMaxResolutionStreamConfigs.data.i32[j * 4 + 2]; + int32_t input = physicalMaxResolutionStreamConfigs.data.i32[j * 4 + 3]; + if (format == multiResFormat && input == multiResInput) { + if (width == multiResWidth && height == multiResHeight) { + supportedUltraHighRes = true; + } else if (width * height > multiResWidth * multiResHeight) { + isUltraHighResMaxSize = false; + } + } + } + + if (isUltraHighRes) { + // For ultra high resolution camera, the configuration must + // be the maximum size in stream configuration map, or max + // resolution stream configuration map + ASSERT_TRUE((supported && isMaxSize) || + (supportedUltraHighRes && isUltraHighResMaxSize)); + } else { + // The configuration must be the maximum size in stream + // configuration map + ASSERT_TRUE(supported && isMaxSize); + ASSERT_FALSE(supportedUltraHighRes); + } + + // Increment the counter for the configuration's format. + auto& formatCounterMap = multiResInput ? multiResInputFormatCounterMap + : multiResOutputFormatCounterMap; + if (formatCounterMap.count(multiResFormat) == 0) { + formatCounterMap[multiResFormat] = 1; + } else { + formatCounterMap[multiResFormat]++; + } + } + + // There must be no duplicates + for (size_t i = 0; i < physicalMultiResStreamConfigs.count / 4 - 1; i++) { + for (size_t j = i + 1; j < physicalMultiResStreamConfigs.count / 4; j++) { + // Input/output doesn't match + if (physicalMultiResStreamConfigs.data.i32[i * 4 + 3] != + physicalMultiResStreamConfigs.data.i32[j * 4 + 3]) { + continue; + } + // Format doesn't match + if (physicalMultiResStreamConfigs.data.i32[i * 4] != + physicalMultiResStreamConfigs.data.i32[j * 4]) { + continue; + } + // Width doesn't match + if (physicalMultiResStreamConfigs.data.i32[i * 4 + 1] != + physicalMultiResStreamConfigs.data.i32[j * 4 + 1]) { + continue; + } + // Height doesn't match + if (physicalMultiResStreamConfigs.data.i32[i * 4 + 2] != + physicalMultiResStreamConfigs.data.i32[j * 4 + 2]) { + continue; + } + // input/output, format, width, and height all match + ADD_FAILURE(); + } + } + } + } + + // If a multi-resolution stream is supported, there must be at least one + // format with more than one resolutions + if (multiResolutionStreamSupported) { + size_t numMultiResFormats = 0; + for (const auto& [format, sizeCount] : multiResOutputFormatCounterMap) { + if (sizeCount >= 2) { + numMultiResFormats++; + } + } + for (const auto& [format, sizeCount] : multiResInputFormatCounterMap) { + if (sizeCount >= 2) { + numMultiResFormats++; + + // If multi-resolution reprocessing is supported, the logical + // camera or ultra-high resolution sensor camera must support + // the corresponding reprocessing capability. + if (format == static_cast(PixelFormat::IMPLEMENTATION_DEFINED)) { + ASSERT_EQ(isZSLModeAvailable(metadata, PRIV_REPROCESS), Status::OK); + } else if (format == static_cast(PixelFormat::YCBCR_420_888)) { + ASSERT_EQ(isZSLModeAvailable(metadata, YUV_REPROCESS), Status::OK); + } + } + } + ASSERT_GT(numMultiResFormats, 0); } // Make sure ANDROID_LOGICAL_MULTI_CAMERA_ACTIVE_PHYSICAL_ID is available in // result keys. - if (deviceVersion >= CAMERA_DEVICE_API_VERSION_3_5) { + if (isMultiCamera && deviceVersion >= CAMERA_DEVICE_API_VERSION_3_5) { retcode = find_camera_metadata_ro_entry(metadata, ANDROID_REQUEST_AVAILABLE_RESULT_KEYS, &entry); if ((0 == retcode) && (entry.count > 0)) {