From c1982fe71b2161ac0f820388336dfb92cd7c43ed Mon Sep 17 00:00:00 2001 From: Jayant Chowdhary Date: Wed, 24 Mar 2021 10:24:32 -0700 Subject: [PATCH] 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: Jayant Chowdhary --- .../VtsHalCameraProviderV2_4TargetTest.cpp | 407 +++++++++++++++++- 1 file changed, 394 insertions(+), 13 deletions(-) diff --git a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp index b2fd402ed8..ed3b1faa53 100644 --- a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp +++ b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp @@ -125,6 +125,7 @@ using ::android::hardware::camera::device::V3_4::PhysicalCameraMetadata; using ::android::hardware::camera::metadata::V3_4:: CameraMetadataEnumAndroidSensorInfoColorFilterArrangement; 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::ICameraProviderCallback; using ::android::hardware::camera::provider::V2_6::CameraIdAndStreamCombination; @@ -767,6 +768,8 @@ public: 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, StreamConfigurationMode configMode, ::android::hardware::camera::device::V3_2::StreamConfiguration *config3_2, @@ -785,6 +788,16 @@ public: sp *outCb /*out*/, uint32_t *jpegBufferSize /*out*/, bool *useHalBufManager /*out*/); + void configureStreams3_7(const std::string& name, int32_t deviceVersion, + sp provider, PixelFormat format, + sp* 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* outCb /*out*/, uint32_t streamConfigCounter, + bool maxResolution); + void configurePreviewStreams3_4(const std::string &name, int32_t deviceVersion, sp provider, const AvailableStream *previewThreshold, @@ -846,6 +859,10 @@ public: hidl_vec streamIds, sp cb, uint32_t streamConfigCounter = 0); + void verifyBuffersReturned(sp session, + hidl_vec streamIds, sp cb, + uint32_t streamConfigCounter = 0); + void verifySessionReconfigurationQuery(sp session3_5, camera_metadata* oldSessionParams, camera_metadata* newSessionParams); @@ -853,12 +870,15 @@ public: static bool isDepthOnly(const camera_metadata_t* staticMeta); - static Status getAvailableOutputStreams(const camera_metadata_t *staticMeta, - std::vector &outputStreams, - const AvailableStream *threshold = nullptr); + static bool isUltraHighResolution(const camera_metadata_t* staticMeta); + + static Status getAvailableOutputStreams(const camera_metadata_t* staticMeta, + std::vector& outputStreams, + const AvailableStream* threshold = nullptr, + bool maxResolution = false); 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, std::vector* outputStreams); @@ -4841,6 +4861,184 @@ TEST_P(CameraHidlTest, processMultiCaptureRequestPreview) { } } +// Generate and verify an ultra high resolution capture request +TEST_P(CameraHidlTest, processUltraHighResolutionRequest) { + hidl_vec cameraDeviceNames = getCameraDeviceNames(mProvider); + uint64_t bufferId = 1; + uint32_t frameNumber = 1; + ::android::hardware::hidl_vec 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 ret; + sp 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(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(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(const_cast(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 session3_7; + sp cb; + std::list 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 resultQueue; + auto resultQueueRet = session3_7->getCaptureResultMetadataQueue( + [&resultQueue](const auto& descriptor) { + 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. + } + }); + ASSERT_TRUE(resultQueueRet.isOk()); + + std::vector graphicBuffers; + graphicBuffers.reserve(halStreamConfig.streams.size()); + ::android::hardware::hidl_vec outputBuffers; + outputBuffers.resize(halStreamConfig.streams.size()); + InFlightRequest inflightReq = {static_cast(halStreamConfig.streams.size()), + false, + supportsPartialResults, + partialResultCount, + std::unordered_set(), + 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 l(mLock); + mInflightMap.clear(); + mInflightMap.add(frameNumber, &inflightReq); + } + + Status stat = Status::INTERNAL_ERROR; + uint32_t numRequestProcessed = 0; + hidl_vec cachesToRemove; + Return 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 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 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 TEST_P(CameraHidlTest, processCaptureRequestBurstISO) { hidl_vec cameraDeviceNames = getCameraDeviceNames(mProvider); @@ -5537,21 +5735,26 @@ TEST_P(CameraHidlTest, providerDeviceStateNotification) { // Retrieve all valid output stream resolutions from the camera // static characteristics. -Status CameraHidlTest::getAvailableOutputStreams(const camera_metadata_t *staticMeta, - std::vector &outputStreams, - const AvailableStream *threshold) { +Status CameraHidlTest::getAvailableOutputStreams(const camera_metadata_t* staticMeta, + std::vector& outputStreams, + const AvailableStream* threshold, + bool maxResolution) { AvailableStream depthPreviewThreshold = {kMaxPreviewWidth, kMaxPreviewHeight, static_cast(PixelFormat::Y16)}; if (nullptr == staticMeta) { 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 depthEntry; - int foundScalar = find_camera_metadata_ro_entry(staticMeta, - ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS, &scalarEntry); - int foundDepth = find_camera_metadata_ro_entry(staticMeta, - ANDROID_DEPTH_AVAILABLE_DEPTH_STREAM_CONFIGURATIONS, &depthEntry); + int foundScalar = find_camera_metadata_ro_entry(staticMeta, scalerTag, &scalarEntry); + int foundDepth = find_camera_metadata_ro_entry(staticMeta, depthTag, &depthEntry); if ((0 != foundScalar || (0 != (scalarEntry.count % 4))) && (0 != foundDepth || (0 != (depthEntry.count % 4)))) { return Status::ILLEGAL_ARGUMENT; @@ -5619,9 +5822,12 @@ Status CameraHidlTest::getMandatoryConcurrentStreams(const camera_metadata_t* st } Status CameraHidlTest::getMaxOutputSizeForFormat(const camera_metadata_t* staticMeta, - PixelFormat format, Size* size) { + PixelFormat format, Size* size, + bool maxResolution) { std::vector outputStreams; - if (size == nullptr || getAvailableOutputStreams(staticMeta, outputStreams) != Status::OK) { + if (size == nullptr || + getAvailableOutputStreams(staticMeta, outputStreams, + /*threshold*/ nullptr, maxResolution) != Status::OK) { return Status::ILLEGAL_ARGUMENT; } Size maxSize; @@ -6065,6 +6271,148 @@ void CameraHidlTest::createStreamConfiguration( *config3_2 = {streams3_2, configMode}; } +// Configure streams +void CameraHidlTest::configureStreams3_7( + const std::string& name, int32_t deviceVersion, sp provider, + PixelFormat format, sp* 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* 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 outputStreams; + ::android::sp device3_x; + ALOGI("configureStreams: Testing camera device %s", name.c_str()); + Return 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(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 cb = new DeviceCb(this, deviceVersion, staticMeta); + sp 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 session3_3; + sp session3_4; + sp session3_5; + sp 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 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(maxSize.width); + streams3_7[0].v3_4.v3_2.height = static_cast(maxSize.height); + streams3_7[0].v3_4.v3_2.format = static_cast(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 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 streams(1); + hidl_vec 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. void CameraHidlTest::configurePreviewStreams3_4(const std::string &name, int32_t deviceVersion, sp provider, @@ -6362,6 +6710,21 @@ void CameraHidlTest::configureOfflineStillStream(const std::string &name, 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) { camera_metadata_ro_entry scalarEntry; camera_metadata_ro_entry depthEntry; @@ -6590,6 +6953,17 @@ 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*/) { ASSERT_NE(nullptr, device3_5); @@ -7303,6 +7677,13 @@ void CameraHidlTest::verifyBuffersReturned( cb->waitForBuffersReturned(); } +void CameraHidlTest::verifyBuffersReturned(sp session3_7, + hidl_vec streamIds, sp cb, + uint32_t streamConfigCounter) { + session3_7->signalStreamFlush(streamIds, /*streamConfigCounter*/ streamConfigCounter); + cb->waitForBuffersReturned(); +} + void CameraHidlTest::verifyLogicalCameraResult(const camera_metadata_t* staticMetadata, const ::android::hardware::camera::common::V1_0::helper::CameraMetadata& resultMetadata) { std::unordered_set physicalIds;