Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4dd6a516 authored by Shuzhen Wang's avatar Shuzhen Wang
Browse files

Camera: Add new camera metadata for settings override frame number

Add a frame number field in HAL capture result metadata to indicate
the frame number of newer request overriding this capture.

This is needed so that ZoomRatioMapper can look up the newer request's
zoom ratio.

Also add VTS test for transition between OFF and ZOOM.

Test: Camera VTS on cuttlefish
Bug: 239822823
Change-Id: I7439950cdb9f346bf36c4cc872fd7865eb9cf669
parent ea43fb74
Loading
Loading
Loading
Loading
+4 −3
Original line number Diff line number Diff line
@@ -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,
+6 −0
Original line number Diff line number Diff line
@@ -463,6 +463,12 @@ enum CameraMetadataTag {
     * be used to speed up certain controls.</p>
     */
    ANDROID_CONTROL_AVAILABLE_SETTINGS_OVERRIDES,
    /**
     * android.control.settingsOverridingFrameNumber [dynamic, int32, system]
     *
     * <p>The frame number of the newer request overriding this capture.</p>
     */
    ANDROID_CONTROL_SETTINGS_OVERRIDING_FRAME_NUMBER,
    /**
     * android.control.autoframing [dynamic, enum, public]
     *
+22 −0
Original line number Diff line number Diff line
@@ -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<std::string> cameraDeviceNames = getCameraDeviceNames(mProvider);
+186 −1
Original line number Diff line number Diff line
@@ -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);
}

@@ -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<ICameraProvider>& provider,
        const AvailableStream* previewThreshold, std::shared_ptr<ICameraDeviceSession>* 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<std::string> cameraDeviceNames = getCameraDeviceNames(mProvider);
    AvailableStream previewThreshold = {kMaxPreviewWidth, kMaxPreviewHeight,
                                        static_cast<int32_t>(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<ICameraDevice> device;
        openEmptyDeviceSession(name, mProvider, &mSession /*out*/, &meta /*out*/,
                               &device /*out*/);
        camera_metadata_t* staticMeta =
                clone_camera_metadata(reinterpret_cast<camera_metadata_t*>(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<HalStream> halStreams;
        std::shared_ptr<DeviceCb> 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<ResultMetadataQueue> resultQueue =
                std::make_shared<ResultMetadataQueue>(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<CaptureRequest> requests(frameCount);
        std::vector<buffer_handle_t> buffers(frameCount);
        std::vector<std::shared_ptr<InFlightRequest>> inflightReqs(frameCount);
        std::vector<CameraMetadata> requestSettings(frameCount);

        for (int32_t i = 0; i < frameCount; i++) {
            std::unique_lock<std::mutex> l(mLock);
            CaptureRequest& request = requests[i];
            std::vector<StreamBuffer>& 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<uint64_t>(halStreams[0].producerUsage),
                                              static_cast<uint64_t>(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<camera_metadata_t*>(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<uint8_t*>(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<InFlightRequest>(1, false, supportsPartialResults,
                                                                partialResultCount, resultQueue);
            mInflightMap[frameNumber + i] = inflightReqs[i];
        }

        int32_t numRequestProcessed = 0;
        std::vector<BufferCache> 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<std::mutex> 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());
    }
}
+6 −0
Original line number Diff line number Diff line
@@ -406,6 +406,12 @@ class CameraAidlTest : public ::testing::TestWithParam<std::string> {
            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 {