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 <jchowdhary@google.com>
This commit is contained in:
Jayant Chowdhary
2021-03-24 10:24:32 -07:00
parent 5a9c80205e
commit c1982fe71b

View File

@@ -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<device::V3_7::ICameraDeviceSession> *session3_7 /*out*/);
void castDevice(const sp<device::V3_2::ICameraDevice> &device, int32_t deviceVersion,
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,
StreamConfigurationMode configMode,
::android::hardware::camera::device::V3_2::StreamConfiguration *config3_2,
@@ -785,6 +788,16 @@ public:
sp<DeviceCb> *outCb /*out*/,
uint32_t *jpegBufferSize /*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,
sp<ICameraProvider> provider,
const AvailableStream *previewThreshold,
@@ -846,6 +859,10 @@ public:
hidl_vec<int32_t> streamIds, sp<DeviceCb> cb,
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,
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<AvailableStream> &outputStreams,
const AvailableStream *threshold = nullptr);
static bool isUltraHighResolution(const camera_metadata_t* staticMeta);
static Status getAvailableOutputStreams(const camera_metadata_t* staticMeta,
std::vector<AvailableStream>& 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<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
TEST_P(CameraHidlTest, processCaptureRequestBurstISO) {
hidl_vec<hidl_string> 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<AvailableStream> &outputStreams,
const AvailableStream *threshold) {
Status CameraHidlTest::getAvailableOutputStreams(const camera_metadata_t* staticMeta,
std::vector<AvailableStream>& outputStreams,
const AvailableStream* threshold,
bool maxResolution) {
AvailableStream depthPreviewThreshold = {kMaxPreviewWidth, kMaxPreviewHeight,
static_cast<int32_t>(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<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;
}
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<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.
void CameraHidlTest::configurePreviewStreams3_4(const std::string &name, int32_t deviceVersion,
sp<ICameraProvider> 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::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,
int32_t deviceVersion, sp<device::V3_5::ICameraDevice> *device3_5/*out*/) {
ASSERT_NE(nullptr, device3_5);
@@ -7303,6 +7677,13 @@ void CameraHidlTest::verifyBuffersReturned(
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,
const ::android::hardware::camera::common::V1_0::helper::CameraMetadata& resultMetadata) {
std::unordered_set<std::string> physicalIds;