diff --git a/camera/metadata/aidl/aidl_api/android.hardware.camera.metadata/current/android/hardware/camera/metadata/CameraMetadataTag.aidl b/camera/metadata/aidl/aidl_api/android.hardware.camera.metadata/current/android/hardware/camera/metadata/CameraMetadataTag.aidl index 617979d957..ecbfc9371f 100644 --- a/camera/metadata/aidl/aidl_api/android.hardware.camera.metadata/current/android/hardware/camera/metadata/CameraMetadataTag.aidl +++ b/camera/metadata/aidl/aidl_api/android.hardware.camera.metadata/current/android/hardware/camera/metadata/CameraMetadataTag.aidl @@ -94,9 +94,10 @@ enum CameraMetadataTag { ANDROID_CONTROL_AVAILABLE_HIGH_SPEED_VIDEO_CONFIGURATIONS_MAXIMUM_RESOLUTION = 65584, ANDROID_CONTROL_SETTINGS_OVERRIDE = 65588, ANDROID_CONTROL_AVAILABLE_SETTINGS_OVERRIDES = 65589, - ANDROID_CONTROL_AUTOFRAMING = 65590, - ANDROID_CONTROL_AUTOFRAMING_AVAILABLE = 65591, - ANDROID_CONTROL_AUTOFRAMING_STATE = 65592, + ANDROID_CONTROL_SETTINGS_OVERRIDING_FRAME_NUMBER = 65590, + ANDROID_CONTROL_AUTOFRAMING = 65591, + ANDROID_CONTROL_AUTOFRAMING_AVAILABLE = 65592, + ANDROID_CONTROL_AUTOFRAMING_STATE = 65593, ANDROID_DEMOSAIC_MODE = 131072, ANDROID_EDGE_MODE = 196608, ANDROID_EDGE_STRENGTH = 196609, diff --git a/camera/metadata/aidl/android/hardware/camera/metadata/CameraMetadataTag.aidl b/camera/metadata/aidl/android/hardware/camera/metadata/CameraMetadataTag.aidl index 85e56bce77..2e9bde95a3 100644 --- a/camera/metadata/aidl/android/hardware/camera/metadata/CameraMetadataTag.aidl +++ b/camera/metadata/aidl/android/hardware/camera/metadata/CameraMetadataTag.aidl @@ -463,6 +463,12 @@ enum CameraMetadataTag { * be used to speed up certain controls.

*/ ANDROID_CONTROL_AVAILABLE_SETTINGS_OVERRIDES, + /** + * android.control.settingsOverridingFrameNumber [dynamic, int32, system] + * + *

The frame number of the newer request overriding this capture.

+ */ + ANDROID_CONTROL_SETTINGS_OVERRIDING_FRAME_NUMBER, /** * android.control.autoframing [dynamic, enum, public] * diff --git a/camera/provider/aidl/vts/VtsAidlHalCameraProvider_TargetTest.cpp b/camera/provider/aidl/vts/VtsAidlHalCameraProvider_TargetTest.cpp index 017f6efa65..747ea336e2 100644 --- a/camera/provider/aidl/vts/VtsAidlHalCameraProvider_TargetTest.cpp +++ b/camera/provider/aidl/vts/VtsAidlHalCameraProvider_TargetTest.cpp @@ -2065,6 +2065,28 @@ TEST_P(CameraAidlTest, process10BitColorSpaceRequests) { } } +TEST_P(CameraAidlTest, processZoomSettingsOverrideRequests) { + const int32_t kFrameCount = 5; + const int32_t kTestCases = 2; + const bool kOverrideSequence[kTestCases][kFrameCount] = { + // ZOOM, ZOOM, ZOOM, ZOOM, ZOOM; + { true, true, true, true, true }, + // OFF, OFF, ZOOM, ZOOM, OFF; + { false, false, true, true, false } }; + const bool kExpectedOverrideResults[kTestCases][kFrameCount] = { + // All resuls should be overridden except the last one. The last result's + // zoom doesn't have speed-up. + { true, true, true, true, false }, + // Because we require at least 2 frames speed-up, request #1, #2 and #3 + // will be overridden. + { true, true, true, false, false } }; + + for (int i = 0; i < kTestCases; i++) { + processZoomSettingsOverrideRequests(kFrameCount, kOverrideSequence[i], + kExpectedOverrideResults[i]); + } +} + // Generate and verify a burst containing alternating sensor sensitivity values TEST_P(CameraAidlTest, processCaptureRequestBurstISO) { std::vector cameraDeviceNames = getCameraDeviceNames(mProvider); diff --git a/camera/provider/aidl/vts/camera_aidl_test.cpp b/camera/provider/aidl/vts/camera_aidl_test.cpp index ca316e5192..b9e30ab891 100644 --- a/camera/provider/aidl/vts/camera_aidl_test.cpp +++ b/camera/provider/aidl/vts/camera_aidl_test.cpp @@ -363,10 +363,15 @@ void CameraAidlTest::verifySettingsOverrideCharacteristics(const camera_metadata retcode = find_camera_metadata_ro_entry(metadata, ANDROID_REQUEST_AVAILABLE_RESULT_KEYS, &entry); bool hasSettingsOverrideResultKey = false; + bool hasOverridingFrameNumberKey = false; if ((0 == retcode) && (entry.count > 0)) { hasSettingsOverrideResultKey = std::find(entry.data.i32, entry.data.i32 + entry.count, ANDROID_CONTROL_SETTINGS_OVERRIDE) != entry.data.i32 + entry.count; + hasOverridingFrameNumberKey = + std::find(entry.data.i32, entry.data.i32 + entry.count, + ANDROID_CONTROL_SETTINGS_OVERRIDING_FRAME_NUMBER) + != entry.data.i32 + entry.count; } else { ADD_FAILURE() << "Get camera availableResultKeys failed!"; } @@ -385,6 +390,7 @@ void CameraAidlTest::verifySettingsOverrideCharacteristics(const camera_metadata ASSERT_EQ(supportSettingsOverride, hasSettingsOverrideRequestKey); ASSERT_EQ(supportSettingsOverride, hasSettingsOverrideResultKey); + ASSERT_EQ(supportSettingsOverride, hasOverridingFrameNumberKey); ASSERT_EQ(supportSettingsOverride, hasSettingsOverrideCharacteristicsKey); } @@ -1579,7 +1585,7 @@ void CameraAidlTest::verifyRequestTemplate(const camera_metadata_t* metadata, // Check settings override camera_metadata_ro_entry settingsOverrideEntry; int foundSettingsOverride = find_camera_metadata_ro_entry(metadata, - ANDROID_CONTROL_SETTINGS_OVERRIDE,&settingsOverrideEntry); + ANDROID_CONTROL_SETTINGS_OVERRIDE, &settingsOverrideEntry); if (foundSettingsOverride == 0) { ASSERT_EQ(settingsOverrideEntry.count, 1); ASSERT_EQ(settingsOverrideEntry.data.u8[0], ANDROID_CONTROL_SETTINGS_OVERRIDE_OFF); @@ -3019,6 +3025,30 @@ int32_t CameraAidlTest::halFormatToPublicFormat( } } +bool CameraAidlTest::supportZoomSettingsOverride(const camera_metadata_t* staticMeta) { + camera_metadata_ro_entry availableOverridesEntry; + int rc = find_camera_metadata_ro_entry(staticMeta, ANDROID_CONTROL_AVAILABLE_SETTINGS_OVERRIDES, + &availableOverridesEntry); + if (rc == 0) { + for (size_t i = 0; i < availableOverridesEntry.count; i++) { + if (availableOverridesEntry.data.i32[i] == ANDROID_CONTROL_SETTINGS_OVERRIDE_ZOOM) { + return true; + } + } + } + return false; +} + +bool CameraAidlTest::isPerFrameControl(const camera_metadata_t* staticMeta) { + camera_metadata_ro_entry syncLatencyEntry; + int rc = find_camera_metadata_ro_entry(staticMeta, ANDROID_SYNC_MAX_LATENCY, + &syncLatencyEntry); + if (rc == 0 && syncLatencyEntry.data.i32[0] == ANDROID_SYNC_MAX_LATENCY_PER_FRAME_CONTROL) { + return true; + } + return false; +} + void CameraAidlTest::configurePreviewStream( const std::string& name, const std::shared_ptr& provider, const AvailableStream* previewThreshold, std::shared_ptr* session, @@ -3385,3 +3415,158 @@ void CameraAidlTest::processColorSpaceRequest( ASSERT_TRUE(ret.isOk()); } } + +void CameraAidlTest::processZoomSettingsOverrideRequests( + int32_t frameCount, const bool *overrideSequence, const bool *expectedResults) { + std::vector cameraDeviceNames = getCameraDeviceNames(mProvider); + AvailableStream previewThreshold = {kMaxPreviewWidth, kMaxPreviewHeight, + static_cast(PixelFormat::IMPLEMENTATION_DEFINED)}; + int64_t bufferId = 1; + int32_t frameNumber = 1; + CameraMetadata settings; + ndk::ScopedAStatus ret; + for (const auto& name : cameraDeviceNames) { + CameraMetadata meta; + std::shared_ptr device; + openEmptyDeviceSession(name, mProvider, &mSession /*out*/, &meta /*out*/, + &device /*out*/); + camera_metadata_t* staticMeta = + clone_camera_metadata(reinterpret_cast(meta.metadata.data())); + + ret = mSession->close(); + mSession = nullptr; + ASSERT_TRUE(ret.isOk()); + + // Device does not support zoom settnigs override + if (!supportZoomSettingsOverride(staticMeta)) { + continue; + } + + if (!isPerFrameControl(staticMeta)) { + continue; + } + + bool supportsPartialResults = false; + bool useHalBufManager = false; + int32_t partialResultCount = 0; + Stream previewStream; + std::vector halStreams; + std::shared_ptr cb; + configurePreviewStream(name, mProvider, &previewThreshold, &mSession /*out*/, + &previewStream /*out*/, &halStreams /*out*/, + &supportsPartialResults /*out*/, &partialResultCount /*out*/, + &useHalBufManager /*out*/, &cb /*out*/); + ASSERT_NE(mSession, nullptr); + + ::aidl::android::hardware::common::fmq::MQDescriptor< + int8_t, aidl::android::hardware::common::fmq::SynchronizedReadWrite> + descriptor; + auto resultQueueRet = mSession->getCaptureResultMetadataQueue(&descriptor); + ASSERT_TRUE(resultQueueRet.isOk()); + + std::shared_ptr resultQueue = + std::make_shared(descriptor); + if (!resultQueue->isValid() || resultQueue->availableToWrite() <= 0) { + ALOGE("%s: HAL returns empty result metadata fmq, not use it", __func__); + resultQueue = nullptr; + // Don't use the queue onwards. + } + + ret = mSession->constructDefaultRequestSettings(RequestTemplate::PREVIEW, &settings); + ASSERT_TRUE(ret.isOk()); + + mInflightMap.clear(); + ::android::hardware::camera::common::V1_0::helper::CameraMetadata requestMeta; + std::vector requests(frameCount); + std::vector buffers(frameCount); + std::vector> inflightReqs(frameCount); + std::vector requestSettings(frameCount); + + for (int32_t i = 0; i < frameCount; i++) { + std::unique_lock l(mLock); + CaptureRequest& request = requests[i]; + std::vector& outputBuffers = request.outputBuffers; + outputBuffers.resize(1); + StreamBuffer& outputBuffer = outputBuffers[0]; + + if (useHalBufManager) { + outputBuffer = {halStreams[0].id, 0, + NativeHandle(), BufferStatus::OK, + NativeHandle(), NativeHandle()}; + } else { + allocateGraphicBuffer(previewStream.width, previewStream.height, + android_convertGralloc1To0Usage( + static_cast(halStreams[0].producerUsage), + static_cast(halStreams[0].consumerUsage)), + halStreams[0].overrideFormat, &buffers[i]); + outputBuffer = {halStreams[0].id, bufferId + i, ::android::makeToAidl(buffers[i]), + BufferStatus::OK, NativeHandle(), NativeHandle()}; + } + + // Set appropriate settings override tag + requestMeta.append(reinterpret_cast(settings.metadata.data())); + int32_t settingsOverride = overrideSequence[i] ? + ANDROID_CONTROL_SETTINGS_OVERRIDE_ZOOM : ANDROID_CONTROL_SETTINGS_OVERRIDE_OFF; + ASSERT_EQ(::android::OK, requestMeta.update(ANDROID_CONTROL_SETTINGS_OVERRIDE, + &settingsOverride, 1)); + camera_metadata_t* metaBuffer = requestMeta.release(); + uint8_t* rawMetaBuffer = reinterpret_cast(metaBuffer); + requestSettings[i].metadata = std::vector( + rawMetaBuffer, rawMetaBuffer + get_camera_metadata_size(metaBuffer)); + overrideRotateAndCrop(&(requestSettings[i])); + request.frameNumber = frameNumber + i; + request.fmqSettingsSize = 0; + request.settings = requestSettings[i]; + request.inputBuffer = { + -1, 0, NativeHandle(), BufferStatus::ERROR, NativeHandle(), NativeHandle()}; + + inflightReqs[i] = std::make_shared(1, false, supportsPartialResults, + partialResultCount, resultQueue); + mInflightMap[frameNumber + i] = inflightReqs[i]; + } + + int32_t numRequestProcessed = 0; + std::vector cachesToRemove; + + ndk::ScopedAStatus returnStatus = + mSession->processCaptureRequest(requests, cachesToRemove, &numRequestProcessed); + ASSERT_TRUE(returnStatus.isOk()); + ASSERT_EQ(numRequestProcessed, frameCount); + + for (size_t i = 0; i < frameCount; i++) { + std::unique_lock l(mLock); + while (!inflightReqs[i]->errorCodeValid && ((0 < inflightReqs[i]->numBuffersLeft) || + (!inflightReqs[i]->haveResultMetadata))) { + auto timeout = std::chrono::system_clock::now() + + std::chrono::seconds(kStreamBufferTimeoutSec); + ASSERT_NE(std::cv_status::timeout, mResultCondition.wait_until(l, timeout)); + } + + ASSERT_FALSE(inflightReqs[i]->errorCodeValid); + ASSERT_NE(inflightReqs[i]->resultOutputBuffers.size(), 0u); + ASSERT_EQ(previewStream.id, inflightReqs[i]->resultOutputBuffers[0].buffer.streamId); + ASSERT_FALSE(inflightReqs[i]->collectedResult.isEmpty()); + ASSERT_TRUE(inflightReqs[i]->collectedResult.exists(ANDROID_CONTROL_SETTINGS_OVERRIDE)); + camera_metadata_entry_t overrideResult = + inflightReqs[i]->collectedResult.find(ANDROID_CONTROL_SETTINGS_OVERRIDE); + ASSERT_EQ(overrideResult.data.i32[0] == ANDROID_CONTROL_SETTINGS_OVERRIDE_ZOOM, + expectedResults[i]); + ASSERT_TRUE(inflightReqs[i]->collectedResult.exists( + ANDROID_CONTROL_SETTINGS_OVERRIDING_FRAME_NUMBER)); + camera_metadata_entry_t frameNumberEntry = inflightReqs[i]->collectedResult.find( + ANDROID_CONTROL_SETTINGS_OVERRIDING_FRAME_NUMBER); + ALOGV("%s: i %zu, expcetedResults[i] %d, overrideResult is %d, frameNumber %d", + __FUNCTION__, i, expectedResults[i], overrideResult.data.i32[0], + frameNumberEntry.data.i32[0]); + if (expectedResults[i]) { + ASSERT_GT(frameNumberEntry.data.i32[0], inflightReqs[i]->frameNumber); + } else { + ASSERT_EQ(frameNumberEntry.data.i32[0], frameNumber + i); + } + } + + ret = mSession->close(); + mSession = nullptr; + ASSERT_TRUE(ret.isOk()); + } +} diff --git a/camera/provider/aidl/vts/camera_aidl_test.h b/camera/provider/aidl/vts/camera_aidl_test.h index ff3617f93c..b6e398b435 100644 --- a/camera/provider/aidl/vts/camera_aidl_test.h +++ b/camera/provider/aidl/vts/camera_aidl_test.h @@ -406,6 +406,12 @@ class CameraAidlTest : public ::testing::TestWithParam { aidl::android::hardware::camera::metadata:: RequestAvailableDynamicRangeProfilesMap dynamicRangeProfile); + void processZoomSettingsOverrideRequests( + int32_t frameCount, const bool *overrideSequence, const bool *expectedResults); + + bool supportZoomSettingsOverride(const camera_metadata_t* staticMeta); + bool isPerFrameControl(const camera_metadata_t* staticMeta); + protected: // In-flight queue for tracking completion of capture requests. struct InFlightRequest {