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

Commit c1982fe7 authored by Jayant Chowdhary's avatar Jayant Chowdhary
Browse files

camera VTS: Add VTS test for ultra high resolution sensors.



Bug: 152813564

Test: VtsHalCameraProviderV2_4TargetTest
      --gtest_filter=PerInstance/CameraHidlTest.processUltra* on
            cuttlefish

Change-Id: If314fedc5f57a01cb2a103b834356b0c3d51e976
Signed-off-by: default avatarJayant Chowdhary <jchowdhary@google.com>
parent 5a9c8020
Loading
Loading
Loading
Loading
+394 −13
Original line number Original line Diff line number Diff line
@@ -125,6 +125,7 @@ using ::android::hardware::camera::device::V3_4::PhysicalCameraMetadata;
using ::android::hardware::camera::metadata::V3_4::
using ::android::hardware::camera::metadata::V3_4::
        CameraMetadataEnumAndroidSensorInfoColorFilterArrangement;
        CameraMetadataEnumAndroidSensorInfoColorFilterArrangement;
using ::android::hardware::camera::metadata::V3_4::CameraMetadataTag;
using ::android::hardware::camera::metadata::V3_4::CameraMetadataTag;
using ::android::hardware::camera::metadata::V3_6::CameraMetadataEnumAndroidSensorPixelMode;
using ::android::hardware::camera::provider::V2_4::ICameraProvider;
using ::android::hardware::camera::provider::V2_4::ICameraProvider;
using ::android::hardware::camera::provider::V2_4::ICameraProviderCallback;
using ::android::hardware::camera::provider::V2_4::ICameraProviderCallback;
using ::android::hardware::camera::provider::V2_6::CameraIdAndStreamCombination;
using ::android::hardware::camera::provider::V2_6::CameraIdAndStreamCombination;
@@ -767,6 +768,8 @@ public:
            sp<device::V3_7::ICameraDeviceSession> *session3_7 /*out*/);
            sp<device::V3_7::ICameraDeviceSession> *session3_7 /*out*/);
    void castDevice(const sp<device::V3_2::ICameraDevice> &device, int32_t deviceVersion,
    void castDevice(const sp<device::V3_2::ICameraDevice> &device, int32_t deviceVersion,
            sp<device::V3_5::ICameraDevice> *device3_5/*out*/);
            sp<device::V3_5::ICameraDevice> *device3_5/*out*/);
    void castDevice3_7(const sp<device::V3_2::ICameraDevice>& device, int32_t deviceVersion,
                       sp<device::V3_7::ICameraDevice>* device3_7 /*out*/);
    void createStreamConfiguration(const ::android::hardware::hidl_vec<V3_2::Stream>& streams3_2,
    void createStreamConfiguration(const ::android::hardware::hidl_vec<V3_2::Stream>& streams3_2,
            StreamConfigurationMode configMode,
            StreamConfigurationMode configMode,
            ::android::hardware::camera::device::V3_2::StreamConfiguration *config3_2,
            ::android::hardware::camera::device::V3_2::StreamConfiguration *config3_2,
@@ -785,6 +788,16 @@ public:
            sp<DeviceCb> *outCb /*out*/,
            sp<DeviceCb> *outCb /*out*/,
            uint32_t *jpegBufferSize /*out*/,
            uint32_t *jpegBufferSize /*out*/,
            bool *useHalBufManager /*out*/);
            bool *useHalBufManager /*out*/);
    void configureStreams3_7(const std::string& name, int32_t deviceVersion,
                             sp<ICameraProvider> provider, PixelFormat format,
                             sp<device::V3_7::ICameraDeviceSession>* session3_7 /*out*/,
                             V3_2::Stream* previewStream /*out*/,
                             device::V3_6::HalStreamConfiguration* halStreamConfig /*out*/,
                             bool* supportsPartialResults /*out*/,
                             uint32_t* partialResultCount /*out*/, bool* useHalBufManager /*out*/,
                             sp<DeviceCb>* outCb /*out*/, uint32_t streamConfigCounter,
                             bool maxResolution);

    void configurePreviewStreams3_4(const std::string &name, int32_t deviceVersion,
    void configurePreviewStreams3_4(const std::string &name, int32_t deviceVersion,
            sp<ICameraProvider> provider,
            sp<ICameraProvider> provider,
            const AvailableStream *previewThreshold,
            const AvailableStream *previewThreshold,
@@ -846,6 +859,10 @@ public:
            hidl_vec<int32_t> streamIds, sp<DeviceCb> cb,
            hidl_vec<int32_t> streamIds, sp<DeviceCb> cb,
            uint32_t streamConfigCounter = 0);
            uint32_t streamConfigCounter = 0);


    void verifyBuffersReturned(sp<device::V3_7::ICameraDeviceSession> session,
                               hidl_vec<int32_t> streamIds, sp<DeviceCb> cb,
                               uint32_t streamConfigCounter = 0);

    void verifySessionReconfigurationQuery(sp<device::V3_5::ICameraDeviceSession> session3_5,
    void verifySessionReconfigurationQuery(sp<device::V3_5::ICameraDeviceSession> session3_5,
            camera_metadata* oldSessionParams, camera_metadata* newSessionParams);
            camera_metadata* oldSessionParams, camera_metadata* newSessionParams);


@@ -853,12 +870,15 @@ public:


    static bool isDepthOnly(const camera_metadata_t* staticMeta);
    static bool isDepthOnly(const camera_metadata_t* staticMeta);


    static bool isUltraHighResolution(const camera_metadata_t* staticMeta);

    static Status getAvailableOutputStreams(const camera_metadata_t* staticMeta,
    static Status getAvailableOutputStreams(const camera_metadata_t* staticMeta,
                                            std::vector<AvailableStream>& outputStreams,
                                            std::vector<AvailableStream>& outputStreams,
            const AvailableStream *threshold = nullptr);
                                            const AvailableStream* threshold = nullptr,
                                            bool maxResolution = false);


    static Status getMaxOutputSizeForFormat(const camera_metadata_t* staticMeta, PixelFormat format,
    static Status getMaxOutputSizeForFormat(const camera_metadata_t* staticMeta, PixelFormat format,
                                            Size* size);
                                            Size* size, bool maxResolution = false);


    static Status getMandatoryConcurrentStreams(const camera_metadata_t* staticMeta,
    static Status getMandatoryConcurrentStreams(const camera_metadata_t* staticMeta,
                                                std::vector<AvailableStream>* outputStreams);
                                                std::vector<AvailableStream>* outputStreams);
@@ -4841,6 +4861,184 @@ TEST_P(CameraHidlTest, processMultiCaptureRequestPreview) {
    }
    }
}
}


// Generate and verify an ultra high resolution capture request
TEST_P(CameraHidlTest, processUltraHighResolutionRequest) {
    hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(mProvider);
    uint64_t bufferId = 1;
    uint32_t frameNumber = 1;
    ::android::hardware::hidl_vec<uint8_t> settings;

    for (const auto& name : cameraDeviceNames) {
        int deviceVersion = getCameraDeviceVersion(name, mProviderType);
        if (deviceVersion < CAMERA_DEVICE_API_VERSION_3_7) {
            continue;
        }
        std::string version, deviceId;
        ASSERT_TRUE(::matchDeviceName(name, mProviderType, &version, &deviceId));
        camera_metadata_t* staticMeta;
        Return<void> ret;
        sp<ICameraDeviceSession> session;
        openEmptyDeviceSession(name, mProvider, &session, &staticMeta);
        if (!isUltraHighResolution(staticMeta)) {
            free_camera_metadata(staticMeta);
            ret = session->close();
            ASSERT_TRUE(ret.isOk());
            continue;
        }
        android::hardware::camera::common::V1_0::helper::CameraMetadata defaultSettings;
        ret = session->constructDefaultRequestSettings(
                RequestTemplate::STILL_CAPTURE,
                [&defaultSettings](auto status, const auto& req) mutable {
                    ASSERT_EQ(Status::OK, status);

                    const camera_metadata_t* metadata =
                            reinterpret_cast<const camera_metadata_t*>(req.data());
                    size_t expectedSize = req.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);
                    defaultSettings = metadata;
                });
        ASSERT_TRUE(ret.isOk());
        uint8_t sensorPixelMode =
                static_cast<uint8_t>(ANDROID_SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION);
        ASSERT_EQ(::android::OK,
                  defaultSettings.update(ANDROID_SENSOR_PIXEL_MODE, &sensorPixelMode, 1));

        const camera_metadata_t* settingsBuffer = defaultSettings.getAndLock();
        settings.setToExternal(
                reinterpret_cast<uint8_t*>(const_cast<camera_metadata_t*>(settingsBuffer)),
                get_camera_metadata_size(settingsBuffer));

        free_camera_metadata(staticMeta);
        ret = session->close();
        ASSERT_TRUE(ret.isOk());
        V3_6::HalStreamConfiguration halStreamConfig;
        bool supportsPartialResults = false;
        bool useHalBufManager = false;
        uint32_t partialResultCount = 0;
        V3_2::Stream previewStream;
        sp<device::V3_7::ICameraDeviceSession> session3_7;
        sp<DeviceCb> cb;
        std::list<PixelFormat> pixelFormats = {PixelFormat::YCBCR_420_888, PixelFormat::RAW16};
        for (PixelFormat format : pixelFormats) {
            configureStreams3_7(name, deviceVersion, mProvider, format, &session3_7, &previewStream,
                                &halStreamConfig, &supportsPartialResults, &partialResultCount,
                                &useHalBufManager, &cb, 0, /*maxResolution*/ true);
            ASSERT_NE(session3_7, nullptr);

            std::shared_ptr<ResultMetadataQueue> resultQueue;
            auto resultQueueRet = session3_7->getCaptureResultMetadataQueue(
                    [&resultQueue](const auto& descriptor) {
                        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.
                        }
                    });
            ASSERT_TRUE(resultQueueRet.isOk());

            std::vector<hidl_handle> graphicBuffers;
            graphicBuffers.reserve(halStreamConfig.streams.size());
            ::android::hardware::hidl_vec<StreamBuffer> outputBuffers;
            outputBuffers.resize(halStreamConfig.streams.size());
            InFlightRequest inflightReq = {static_cast<ssize_t>(halStreamConfig.streams.size()),
                                           false,
                                           supportsPartialResults,
                                           partialResultCount,
                                           std::unordered_set<std::string>(),
                                           resultQueue};

            size_t k = 0;
            for (const auto& halStream : halStreamConfig.streams) {
                hidl_handle buffer_handle;
                if (useHalBufManager) {
                    outputBuffers[k] = {halStream.v3_4.v3_3.v3_2.id,
                                        0,
                                        buffer_handle,
                                        BufferStatus::OK,
                                        nullptr,
                                        nullptr};
                } else {
                    allocateGraphicBuffer(
                            previewStream.width, previewStream.height,
                            android_convertGralloc1To0Usage(halStream.v3_4.v3_3.v3_2.producerUsage,
                                                            halStream.v3_4.v3_3.v3_2.consumerUsage),
                            halStream.v3_4.v3_3.v3_2.overrideFormat, &buffer_handle);
                    graphicBuffers.push_back(buffer_handle);
                    outputBuffers[k] = {halStream.v3_4.v3_3.v3_2.id,
                                        bufferId,
                                        buffer_handle,
                                        BufferStatus::OK,
                                        nullptr,
                                        nullptr};
                    bufferId++;
                }
                k++;
            }

            StreamBuffer emptyInputBuffer = {-1, 0, nullptr, BufferStatus::ERROR, nullptr, nullptr};
            V3_4::CaptureRequest request3_4;
            request3_4.v3_2.frameNumber = frameNumber;
            request3_4.v3_2.fmqSettingsSize = 0;
            request3_4.v3_2.settings = settings;
            request3_4.v3_2.inputBuffer = emptyInputBuffer;
            request3_4.v3_2.outputBuffers = outputBuffers;
            V3_7::CaptureRequest request3_7;
            request3_7.v3_4 = request3_4;
            request3_7.inputWidth = 0;
            request3_7.inputHeight = 0;

            {
                std::unique_lock<std::mutex> l(mLock);
                mInflightMap.clear();
                mInflightMap.add(frameNumber, &inflightReq);
            }

            Status stat = Status::INTERNAL_ERROR;
            uint32_t numRequestProcessed = 0;
            hidl_vec<BufferCache> cachesToRemove;
            Return<void> returnStatus = session3_7->processCaptureRequest_3_7(
                    {request3_7}, cachesToRemove,
                    [&stat, &numRequestProcessed](auto s, uint32_t n) {
                        stat = s;
                        numRequestProcessed = n;
                    });
            ASSERT_TRUE(returnStatus.isOk());
            ASSERT_EQ(Status::OK, stat);
            ASSERT_EQ(numRequestProcessed, 1u);

            {
                std::unique_lock<std::mutex> l(mLock);
                while (!inflightReq.errorCodeValid &&
                       ((0 < inflightReq.numBuffersLeft) || (!inflightReq.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(inflightReq.errorCodeValid);
                ASSERT_NE(inflightReq.resultOutputBuffers.size(), 0u);
            }
            if (useHalBufManager) {
                hidl_vec<int32_t> streamIds(halStreamConfig.streams.size());
                for (size_t i = 0; i < streamIds.size(); i++) {
                    streamIds[i] = halStreamConfig.streams[i].v3_4.v3_3.v3_2.id;
                }
                verifyBuffersReturned(session3_7, streamIds, cb);
            }

            ret = session3_7->close();
            ASSERT_TRUE(ret.isOk());
        }
    }
}

// Generate and verify a burst containing alternating sensor sensitivity values
// Generate and verify a burst containing alternating sensor sensitivity values
TEST_P(CameraHidlTest, processCaptureRequestBurstISO) {
TEST_P(CameraHidlTest, processCaptureRequestBurstISO) {
    hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(mProvider);
    hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(mProvider);
@@ -5539,19 +5737,24 @@ TEST_P(CameraHidlTest, providerDeviceStateNotification) {
// static characteristics.
// static characteristics.
Status CameraHidlTest::getAvailableOutputStreams(const camera_metadata_t* staticMeta,
Status CameraHidlTest::getAvailableOutputStreams(const camera_metadata_t* staticMeta,
                                                 std::vector<AvailableStream>& outputStreams,
                                                 std::vector<AvailableStream>& outputStreams,
        const AvailableStream *threshold) {
                                                 const AvailableStream* threshold,
                                                 bool maxResolution) {
    AvailableStream depthPreviewThreshold = {kMaxPreviewWidth, kMaxPreviewHeight,
    AvailableStream depthPreviewThreshold = {kMaxPreviewWidth, kMaxPreviewHeight,
                                             static_cast<int32_t>(PixelFormat::Y16)};
                                             static_cast<int32_t>(PixelFormat::Y16)};
    if (nullptr == staticMeta) {
    if (nullptr == staticMeta) {
        return Status::ILLEGAL_ARGUMENT;
        return Status::ILLEGAL_ARGUMENT;
    }
    }
    int scalerTag = maxResolution
                            ? ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_MAXIMUM_RESOLUTION
                            : ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS;
    int depthTag = maxResolution
                           ? ANDROID_DEPTH_AVAILABLE_DEPTH_STREAM_CONFIGURATIONS_MAXIMUM_RESOLUTION
                           : ANDROID_DEPTH_AVAILABLE_DEPTH_STREAM_CONFIGURATIONS;


    camera_metadata_ro_entry scalarEntry;
    camera_metadata_ro_entry scalarEntry;
    camera_metadata_ro_entry depthEntry;
    camera_metadata_ro_entry depthEntry;
    int foundScalar = find_camera_metadata_ro_entry(staticMeta,
    int foundScalar = find_camera_metadata_ro_entry(staticMeta, scalerTag, &scalarEntry);
            ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS, &scalarEntry);
    int foundDepth = find_camera_metadata_ro_entry(staticMeta, depthTag, &depthEntry);
    int foundDepth = find_camera_metadata_ro_entry(staticMeta,
            ANDROID_DEPTH_AVAILABLE_DEPTH_STREAM_CONFIGURATIONS, &depthEntry);
    if ((0 != foundScalar || (0 != (scalarEntry.count % 4))) &&
    if ((0 != foundScalar || (0 != (scalarEntry.count % 4))) &&
        (0 != foundDepth || (0 != (depthEntry.count % 4)))) {
        (0 != foundDepth || (0 != (depthEntry.count % 4)))) {
        return Status::ILLEGAL_ARGUMENT;
        return Status::ILLEGAL_ARGUMENT;
@@ -5619,9 +5822,12 @@ Status CameraHidlTest::getMandatoryConcurrentStreams(const camera_metadata_t* st
}
}


Status CameraHidlTest::getMaxOutputSizeForFormat(const camera_metadata_t* staticMeta,
Status CameraHidlTest::getMaxOutputSizeForFormat(const camera_metadata_t* staticMeta,
                                                 PixelFormat format, Size* size) {
                                                 PixelFormat format, Size* size,
                                                 bool maxResolution) {
    std::vector<AvailableStream> outputStreams;
    std::vector<AvailableStream> outputStreams;
    if (size == nullptr || getAvailableOutputStreams(staticMeta, outputStreams) != Status::OK) {
    if (size == nullptr ||
        getAvailableOutputStreams(staticMeta, outputStreams,
                                  /*threshold*/ nullptr, maxResolution) != Status::OK) {
        return Status::ILLEGAL_ARGUMENT;
        return Status::ILLEGAL_ARGUMENT;
    }
    }
    Size maxSize;
    Size maxSize;
@@ -6065,6 +6271,148 @@ void CameraHidlTest::createStreamConfiguration(
    *config3_2 = {streams3_2, configMode};
    *config3_2 = {streams3_2, configMode};
}
}


// Configure streams
void CameraHidlTest::configureStreams3_7(
        const std::string& name, int32_t deviceVersion, sp<ICameraProvider> provider,
        PixelFormat format, sp<device::V3_7::ICameraDeviceSession>* session3_7 /*out*/,
        V3_2::Stream* previewStream /*out*/,
        device::V3_6::HalStreamConfiguration* halStreamConfig /*out*/,
        bool* supportsPartialResults /*out*/, uint32_t* partialResultCount /*out*/,
        bool* useHalBufManager /*out*/, sp<DeviceCb>* outCb /*out*/, uint32_t streamConfigCounter,
        bool maxResolution) {
    ASSERT_NE(nullptr, session3_7);
    ASSERT_NE(nullptr, halStreamConfig);
    ASSERT_NE(nullptr, previewStream);
    ASSERT_NE(nullptr, supportsPartialResults);
    ASSERT_NE(nullptr, partialResultCount);
    ASSERT_NE(nullptr, useHalBufManager);
    ASSERT_NE(nullptr, outCb);

    std::vector<AvailableStream> outputStreams;
    ::android::sp<ICameraDevice> device3_x;
    ALOGI("configureStreams: Testing camera device %s", name.c_str());
    Return<void> ret;
    ret = provider->getCameraDeviceInterface_V3_x(name, [&](auto status, const auto& device) {
        ALOGI("getCameraDeviceInterface_V3_x returns status:%d", (int)status);
        ASSERT_EQ(Status::OK, status);
        ASSERT_NE(device, nullptr);
        device3_x = device;
    });
    ASSERT_TRUE(ret.isOk());

    camera_metadata_t* staticMeta;
    ret = device3_x->getCameraCharacteristics([&](Status s, CameraMetadata metadata) {
        ASSERT_EQ(Status::OK, s);
        staticMeta =
                clone_camera_metadata(reinterpret_cast<const camera_metadata_t*>(metadata.data()));
        ASSERT_NE(nullptr, staticMeta);
    });
    ASSERT_TRUE(ret.isOk());

    camera_metadata_ro_entry entry;
    auto status =
            find_camera_metadata_ro_entry(staticMeta, ANDROID_REQUEST_PARTIAL_RESULT_COUNT, &entry);
    if ((0 == status) && (entry.count > 0)) {
        *partialResultCount = entry.data.i32[0];
        *supportsPartialResults = (*partialResultCount > 1);
    }

    sp<DeviceCb> cb = new DeviceCb(this, deviceVersion, staticMeta);
    sp<ICameraDeviceSession> session;
    ret = device3_x->open(cb, [&session](auto status, const auto& newSession) {
        ALOGI("device::open returns status:%d", (int)status);
        ASSERT_EQ(Status::OK, status);
        ASSERT_NE(newSession, nullptr);
        session = newSession;
    });
    ASSERT_TRUE(ret.isOk());
    *outCb = cb;

    sp<device::V3_3::ICameraDeviceSession> session3_3;
    sp<device::V3_4::ICameraDeviceSession> session3_4;
    sp<device::V3_5::ICameraDeviceSession> session3_5;
    sp<device::V3_6::ICameraDeviceSession> session3_6;
    castSession(session, deviceVersion, &session3_3, &session3_4, &session3_5, &session3_6,
                session3_7);
    ASSERT_NE(nullptr, (*session3_7).get());

    *useHalBufManager = false;
    status = find_camera_metadata_ro_entry(
            staticMeta, ANDROID_INFO_SUPPORTED_BUFFER_MANAGEMENT_VERSION, &entry);
    if ((0 == status) && (entry.count == 1)) {
        *useHalBufManager = (entry.data.u8[0] ==
                             ANDROID_INFO_SUPPORTED_BUFFER_MANAGEMENT_VERSION_HIDL_DEVICE_3_5);
    }

    outputStreams.clear();
    Size maxSize;
    auto rc = getMaxOutputSizeForFormat(staticMeta, format, &maxSize, maxResolution);
    ASSERT_EQ(Status::OK, rc);
    free_camera_metadata(staticMeta);

    ::android::hardware::hidl_vec<V3_7::Stream> streams3_7(1);
    streams3_7[0].groupId = -1;
    streams3_7[0].sensorPixelModesUsed = {
            CameraMetadataEnumAndroidSensorPixelMode::ANDROID_SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION};
    streams3_7[0].v3_4.bufferSize = 0;
    streams3_7[0].v3_4.v3_2.id = 0;
    streams3_7[0].v3_4.v3_2.streamType = StreamType::OUTPUT;
    streams3_7[0].v3_4.v3_2.width = static_cast<uint32_t>(maxSize.width);
    streams3_7[0].v3_4.v3_2.height = static_cast<uint32_t>(maxSize.height);
    streams3_7[0].v3_4.v3_2.format = static_cast<PixelFormat>(format);
    streams3_7[0].v3_4.v3_2.usage = GRALLOC1_CONSUMER_USAGE_CPU_READ;
    streams3_7[0].v3_4.v3_2.dataSpace = 0;
    streams3_7[0].v3_4.v3_2.rotation = StreamRotation::ROTATION_0;

    ::android::hardware::camera::device::V3_7::StreamConfiguration config3_7;
    config3_7.streams = streams3_7;
    config3_7.operationMode = StreamConfigurationMode::NORMAL_MODE;
    config3_7.streamConfigCounter = streamConfigCounter;
    config3_7.multiResolutionInputImage = false;
    RequestTemplate reqTemplate = RequestTemplate::STILL_CAPTURE;
    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());

    ASSERT_TRUE(deviceVersion >= CAMERA_DEVICE_API_VERSION_3_7);
    sp<device::V3_7::ICameraDevice> cameraDevice3_7 = nullptr;
    castDevice3_7(device3_x, deviceVersion, &cameraDevice3_7);
    ASSERT_NE(cameraDevice3_7, nullptr);
    bool supported = false;
    ret = cameraDevice3_7->isStreamCombinationSupported_3_7(
            config3_7, [&supported](Status s, bool combStatus) {
                ASSERT_TRUE((Status::OK == s) || (Status::METHOD_NOT_SUPPORTED == s));
                if (Status::OK == s) {
                    supported = combStatus;
                }
            });
    ASSERT_TRUE(ret.isOk());
    ASSERT_EQ(supported, true);

    if (*session3_7 != nullptr) {
        ret = (*session3_7)
                      ->configureStreams_3_7(
                              config3_7,
                              [&](Status s, device::V3_6::HalStreamConfiguration halConfig) {
                                  ASSERT_EQ(Status::OK, s);
                                  *halStreamConfig = halConfig;
                                  if (*useHalBufManager) {
                                      hidl_vec<V3_4::Stream> streams(1);
                                      hidl_vec<V3_2::HalStream> halStreams(1);
                                      streams[0] = streams3_7[0].v3_4;
                                      halStreams[0] = halConfig.streams[0].v3_4.v3_3.v3_2;
                                      cb->setCurrentStreamConfig(streams, halStreams);
                                  }
                              });
    }
    *previewStream = streams3_7[0].v3_4.v3_2;
    ASSERT_TRUE(ret.isOk());
}

// Configure multiple preview streams using different physical ids.
// Configure multiple preview streams using different physical ids.
void CameraHidlTest::configurePreviewStreams3_4(const std::string &name, int32_t deviceVersion,
void CameraHidlTest::configurePreviewStreams3_4(const std::string &name, int32_t deviceVersion,
        sp<ICameraProvider> provider,
        sp<ICameraProvider> provider,
@@ -6362,6 +6710,21 @@ void CameraHidlTest::configureOfflineStillStream(const std::string &name,
    ASSERT_TRUE(ret.isOk());
    ASSERT_TRUE(ret.isOk());
}
}


bool CameraHidlTest::isUltraHighResolution(const camera_metadata_t* staticMeta) {
    camera_metadata_ro_entry scalarEntry;
    int rc = find_camera_metadata_ro_entry(staticMeta, ANDROID_REQUEST_AVAILABLE_CAPABILITIES,
                                           &scalarEntry);
    if (rc == 0) {
        for (uint32_t i = 0; i < scalarEntry.count; i++) {
            if (scalarEntry.data.u8[i] ==
                ANDROID_REQUEST_AVAILABLE_CAPABILITIES_ULTRA_HIGH_RESOLUTION_SENSOR) {
                return true;
            }
        }
    }
    return false;
}

bool CameraHidlTest::isDepthOnly(const camera_metadata_t* staticMeta) {
bool CameraHidlTest::isDepthOnly(const camera_metadata_t* staticMeta) {
    camera_metadata_ro_entry scalarEntry;
    camera_metadata_ro_entry scalarEntry;
    camera_metadata_ro_entry depthEntry;
    camera_metadata_ro_entry depthEntry;
@@ -6590,6 +6953,17 @@ void CameraHidlTest::configureSingleStream(
    ASSERT_TRUE(ret.isOk());
    ASSERT_TRUE(ret.isOk());
}
}


void CameraHidlTest::castDevice3_7(const sp<device::V3_2::ICameraDevice>& device,
                                   int32_t deviceVersion,
                                   sp<device::V3_7::ICameraDevice>* 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::V3_2::ICameraDevice> &device,
void CameraHidlTest::castDevice(const sp<device::V3_2::ICameraDevice> &device,
        int32_t deviceVersion, sp<device::V3_5::ICameraDevice> *device3_5/*out*/) {
        int32_t deviceVersion, sp<device::V3_5::ICameraDevice> *device3_5/*out*/) {
    ASSERT_NE(nullptr, device3_5);
    ASSERT_NE(nullptr, device3_5);
@@ -7303,6 +7677,13 @@ void CameraHidlTest::verifyBuffersReturned(
    cb->waitForBuffersReturned();
    cb->waitForBuffersReturned();
}
}


void CameraHidlTest::verifyBuffersReturned(sp<device::V3_7::ICameraDeviceSession> session3_7,
                                           hidl_vec<int32_t> streamIds, sp<DeviceCb> cb,
                                           uint32_t streamConfigCounter) {
    session3_7->signalStreamFlush(streamIds, /*streamConfigCounter*/ streamConfigCounter);
    cb->waitForBuffersReturned();
}

void CameraHidlTest::verifyLogicalCameraResult(const camera_metadata_t* staticMetadata,
void CameraHidlTest::verifyLogicalCameraResult(const camera_metadata_t* staticMetadata,
        const ::android::hardware::camera::common::V1_0::helper::CameraMetadata& resultMetadata) {
        const ::android::hardware::camera::common::V1_0::helper::CameraMetadata& resultMetadata) {
    std::unordered_set<std::string> physicalIds;
    std::unordered_set<std::string> physicalIds;