#include <gtest/gtest.h>
#include <regex>
#include "system/camera_metadata.h"
+#include <hardware/gralloc.h>
+#include <unordered_map>
using ::android::hardware::Return;
using ::android::hardware::Void;
using ::android::hardware::hidl_string;
using ::android::hardware::hidl_vec;
using ::android::sp;
+using ::android::hardware::graphics::common::V1_0::PixelFormat;
using ::android::hardware::camera::common::V1_0::Status;
using ::android::hardware::camera::common::V1_0::CameraDeviceStatus;
using ::android::hardware::camera::common::V1_0::TorchMode;
using ::android::hardware::camera::device::V3_2::ICameraDeviceSession;
using ::android::hardware::camera::device::V3_2::NotifyMsg;
using ::android::hardware::camera::device::V3_2::RequestTemplate;
+using ::android::hardware::camera::device::V3_2::Stream;
+using ::android::hardware::camera::device::V3_2::StreamType;
+using ::android::hardware::camera::device::V3_2::StreamRotation;
+using ::android::hardware::camera::device::V3_2::StreamConfiguration;
+using ::android::hardware::camera::device::V3_2::StreamConfigurationMode;
+using ::android::hardware::camera::device::V3_2::CameraMetadata;
+using ::android::hardware::camera::device::V3_2::HalStreamConfiguration;
#define CAMERA_PASSTHROUGH_SERVICE_NAME "legacy/0"
+#define MAX_PREVIEW_WIDTH 1920
+#define MAX_PREVIEW_HEIGHT 1080
+#define MAX_VIDEO_WIDTH 4096
+#define MAX_VIDEO_HEIGHT 2160
+
+struct AvailableStream {
+ int32_t width;
+ int32_t height;
+ int32_t format;
+};
+
+struct AvailableZSLInputOutput {
+ int32_t inputFormat;
+ int32_t outputFormat;
+};
namespace {
// "device@<version>/legacy/<id>"
return Void();
}
};
+
+ static Status getAvailableOutputStreams(camera_metadata_t *staticMeta,
+ std::vector<AvailableStream> &outputStreams,
+ AvailableStream *threshold = nullptr);
+ static Status isConstrainedModeAvailable(camera_metadata_t *staticMeta);
+ static Status pickConstrainedModeSize(camera_metadata_t *staticMeta,
+ AvailableStream &hfrStream);
+ static Status isZSLModeAvailable(camera_metadata_t *staticMeta);
+ static Status getZSLInputOutputMap(camera_metadata_t *staticMeta,
+ std::vector<AvailableZSLInputOutput> &inputOutputMap);
+ static Status findLargestSize(
+ const std::vector<AvailableStream> &streamSizes,
+ int32_t format, AvailableStream &result);
};
hidl_vec<hidl_string> CameraHidlTest::getCameraDeviceNames() {
}
}
+// Verify that the device resource cost can be retrieved and the values are
+// sane.
TEST_F(CameraHidlTest, getResourceCost) {
CameraHidlEnvironment* env = CameraHidlEnvironment::Instance();
hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames();
}
}
+// Verify that the static camera characteristics can be retrieved
+// successfully.
TEST_F(CameraHidlTest, getCameraCharacteristics) {
CameraHidlEnvironment* env = CameraHidlEnvironment::Instance();
hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames();
}
}
+//In case it is supported verify that torch can be enabled.
TEST_F(CameraHidlTest, setTorchMode) {
CameraHidlEnvironment* env = CameraHidlEnvironment::Instance();
hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames();
}
}
+// Check dump functionality.
TEST_F(CameraHidlTest, dumpState) {
CameraHidlEnvironment* env = CameraHidlEnvironment::Instance();
hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames();
}
}
+// Check whether all common default request settings can be sucessfully
+// constructed.
TEST_F(CameraHidlTest, constructDefaultRequestSettings) {
CameraHidlEnvironment* env = CameraHidlEnvironment::Instance();
hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames();
}
}
-TEST_F(CameraHidlTest, configureStreams) {
+// Verify that all supported stream formats and sizes can be configured
+// successfully.
+TEST_F(CameraHidlTest, configureStreamsAvailableOutputs) {
+ CameraHidlEnvironment* env = CameraHidlEnvironment::Instance();
+ hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames();
+ std::vector<AvailableStream> outputStreams;
+
+ for (const auto& name : cameraDeviceNames) {
+ if (getCameraDeviceVersion(name) == CAMERA_DEVICE_API_VERSION_3_2) {
+ ::android::sp<::android::hardware::camera::device::V3_2::ICameraDevice> device3_2;
+ ALOGI("configureStreams: Testing camera device %s", name.c_str());
+ env->mProvider->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_2 = device;
+ });
+
+ sp<EmptyDeviceCb> cb = new EmptyDeviceCb;
+ sp<ICameraDeviceSession> session;
+ device3_2->open(
+ cb,
+ [&](auto status, const auto& newSession) {
+ ALOGI("device::open returns status:%d", (int)status);
+ ASSERT_EQ(Status::OK, status);
+ ASSERT_NE(newSession, nullptr);
+ session = newSession;
+ });
+
+ camera_metadata_t *staticMeta;
+ device3_2->getCameraCharacteristics([&] (Status s,
+ CameraMetadata metadata) {
+ ASSERT_EQ(Status::OK, s);
+ staticMeta =
+ reinterpret_cast<camera_metadata_t*>(metadata.data());
+ });
+ outputStreams.clear();
+ ASSERT_EQ(Status::OK, getAvailableOutputStreams(staticMeta,
+ outputStreams));
+ ASSERT_NE(0u, outputStreams.size());
+
+ int32_t streamId = 0;
+ for (auto &it : outputStreams) {
+ Stream stream = {streamId, StreamType::OUTPUT,
+ static_cast<uint32_t> (it.width),
+ static_cast<uint32_t> (it.height),
+ static_cast<PixelFormat> (it.format), 0, 0,
+ StreamRotation::ROTATION_0};
+ ::android::hardware::hidl_vec<Stream> streams = {stream};
+ StreamConfiguration config = {streams,
+ StreamConfigurationMode::NORMAL_MODE};
+ session->configureStreams(config, [streamId] (Status s,
+ HalStreamConfiguration halConfig) {
+ ASSERT_EQ(Status::OK, s);
+ ASSERT_EQ(1u, halConfig.streams.size());
+ ASSERT_EQ(halConfig.streams[0].id, streamId);
+ });
+ streamId++;
+ }
+
+ session->close();
+ }
+ }
+}
+
+// Check for correct handling of invalid/incorrect configuration parameters.
+TEST_F(CameraHidlTest, configureStreamsInvalidOutputs) {
+ CameraHidlEnvironment* env = CameraHidlEnvironment::Instance();
+ hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames();
+ std::vector<AvailableStream> outputStreams;
+
+ for (const auto& name : cameraDeviceNames) {
+ if (getCameraDeviceVersion(name) == CAMERA_DEVICE_API_VERSION_3_2) {
+ ::android::sp<::android::hardware::camera::device::V3_2::ICameraDevice> device3_2;
+ ALOGI("configureStreams: Testing camera device %s", name.c_str());
+ env->mProvider->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_2 = device;
+ });
+
+ sp<EmptyDeviceCb> cb = new EmptyDeviceCb;
+ sp<ICameraDeviceSession> session;
+ device3_2->open(
+ cb,
+ [&](auto status, const auto& newSession) {
+ ALOGI("device::open returns status:%d", (int)status);
+ ASSERT_EQ(Status::OK, status);
+ ASSERT_NE(newSession, nullptr);
+ session = newSession;
+ });
+
+ camera_metadata_t *staticMeta;
+ device3_2->getCameraCharacteristics([&] (Status s,
+ CameraMetadata metadata) {
+ ASSERT_EQ(Status::OK, s);
+ staticMeta =
+ reinterpret_cast<camera_metadata_t*>(metadata.data());
+ });
+ outputStreams.clear();
+ ASSERT_EQ(Status::OK, getAvailableOutputStreams(staticMeta,
+ outputStreams));
+ ASSERT_NE(0u, outputStreams.size());
+
+ int32_t streamId = 0;
+ Stream stream = {streamId++, StreamType::OUTPUT,
+ static_cast<uint32_t> (0),
+ static_cast<uint32_t> (0),
+ static_cast<PixelFormat> (outputStreams[0].format),
+ 0, 0, StreamRotation::ROTATION_0};
+ ::android::hardware::hidl_vec<Stream> streams = {stream};
+ StreamConfiguration config = {streams,
+ StreamConfigurationMode::NORMAL_MODE};
+ session->configureStreams(config, [] (Status s,
+ HalStreamConfiguration) {
+ ASSERT_EQ(Status::ILLEGAL_ARGUMENT, s);
+ });
+
+ stream = {streamId++, StreamType::OUTPUT,
+ static_cast<uint32_t> (UINT32_MAX),
+ static_cast<uint32_t> (UINT32_MAX),
+ static_cast<PixelFormat> (outputStreams[0].format),
+ 0, 0, StreamRotation::ROTATION_0};
+ streams[0] = stream;
+ config = {streams,
+ StreamConfigurationMode::NORMAL_MODE};
+ session->configureStreams(config, [] (Status s,
+ HalStreamConfiguration) {
+ ASSERT_EQ(Status::ILLEGAL_ARGUMENT, s);
+ });
+
+ for (auto &it : outputStreams) {
+ stream = {streamId++, StreamType::OUTPUT,
+ static_cast<uint32_t> (it.width),
+ static_cast<uint32_t> (it.height),
+ static_cast<PixelFormat> (UINT32_MAX),
+ 0, 0, StreamRotation::ROTATION_0};
+ streams[0] = stream;
+ config = {streams,
+ StreamConfigurationMode::NORMAL_MODE};
+ session->configureStreams(config, [] (Status s,
+ HalStreamConfiguration) {
+ ASSERT_EQ(Status::ILLEGAL_ARGUMENT, s);
+ });
+
+ stream = {streamId++, StreamType::OUTPUT,
+ static_cast<uint32_t> (it.width),
+ static_cast<uint32_t> (it.height),
+ static_cast<PixelFormat> (it.format),
+ 0, 0, static_cast<StreamRotation> (UINT32_MAX)};
+ streams[0] = stream;
+ config = {streams,
+ StreamConfigurationMode::NORMAL_MODE};
+ session->configureStreams(config, [] (Status s,
+ HalStreamConfiguration) {
+ ASSERT_EQ(Status::ILLEGAL_ARGUMENT, s);
+ });
+ }
+
+ session->close();
+ }
+ }
+}
+
+// Check whether all supported ZSL output stream combinations can be
+// configured successfully.
+TEST_F(CameraHidlTest, configureStreamsZSLInputOutputs) {
+ CameraHidlEnvironment* env = CameraHidlEnvironment::Instance();
+ hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames();
+ std::vector<AvailableStream> inputStreams;
+ std::vector<AvailableZSLInputOutput> inputOutputMap;
+
+ for (const auto& name : cameraDeviceNames) {
+ if (getCameraDeviceVersion(name) == CAMERA_DEVICE_API_VERSION_3_2) {
+ ::android::sp<::android::hardware::camera::device::V3_2::ICameraDevice> device3_2;
+ ALOGI("configureStreams: Testing camera device %s", name.c_str());
+ env->mProvider->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_2 = device;
+ });
+
+ sp<EmptyDeviceCb> cb = new EmptyDeviceCb;
+ sp<ICameraDeviceSession> session;
+ device3_2->open(
+ cb,
+ [&](auto status, const auto& newSession) {
+ ALOGI("device::open returns status:%d", (int)status);
+ ASSERT_EQ(Status::OK, status);
+ ASSERT_NE(newSession, nullptr);
+ session = newSession;
+ });
+
+ camera_metadata_t *staticMeta;
+ device3_2->getCameraCharacteristics([&] (Status s,
+ CameraMetadata metadata) {
+ ASSERT_EQ(Status::OK, s);
+ staticMeta =
+ reinterpret_cast<camera_metadata_t*>(metadata.data());
+ });
+ Status ret = isZSLModeAvailable(staticMeta);
+ if (Status::METHOD_NOT_SUPPORTED == ret) {
+ session->close();
+ continue;
+ }
+ ASSERT_EQ(Status::OK, ret);
+
+ inputStreams.clear();
+ ASSERT_EQ(Status::OK, getAvailableOutputStreams(staticMeta,
+ inputStreams));
+ ASSERT_NE(0u, inputStreams.size());
+
+ inputOutputMap.clear();
+ ASSERT_EQ(Status::OK, getZSLInputOutputMap(staticMeta,
+ inputOutputMap));
+ ASSERT_NE(0u, inputOutputMap.size());
+
+ int32_t streamId = 0;
+ for (auto &inputIter : inputOutputMap) {
+ AvailableStream input, output;
+ ASSERT_EQ(Status::OK,
+ findLargestSize(inputStreams, inputIter.inputFormat, input));
+ ASSERT_NE(0u, inputStreams.size());
+
+ AvailableStream outputThreshold = {INT32_MAX, INT32_MAX,
+ inputIter.outputFormat};
+ std::vector<AvailableStream> outputStreams;
+ ASSERT_EQ(Status::OK, getAvailableOutputStreams(staticMeta,
+ outputStreams, &outputThreshold));
+ for (auto &outputIter : outputStreams) {
+ Stream zslStream = {streamId++, StreamType::OUTPUT,
+ static_cast<uint32_t> (input.width),
+ static_cast<uint32_t> (input.height),
+ static_cast<PixelFormat> (input.format),
+ GRALLOC_USAGE_HW_CAMERA_ZSL, 0,
+ StreamRotation::ROTATION_0};
+ Stream inputStream = {streamId++, StreamType::INPUT,
+ static_cast<uint32_t> (input.width),
+ static_cast<uint32_t> (input.height),
+ static_cast<PixelFormat> (input.format), 0, 0,
+ StreamRotation::ROTATION_0};
+ Stream outputStream = {streamId++, StreamType::OUTPUT,
+ static_cast<uint32_t> (outputIter.width),
+ static_cast<uint32_t> (outputIter.height),
+ static_cast<PixelFormat> (outputIter.format), 0, 0,
+ StreamRotation::ROTATION_0};
+
+ ::android::hardware::hidl_vec<Stream> streams = {
+ inputStream, zslStream, outputStream};
+ StreamConfiguration config = {streams,
+ StreamConfigurationMode::NORMAL_MODE};
+ session->configureStreams(config, [streamId] (Status s,
+ HalStreamConfiguration halConfig) {
+ ASSERT_EQ(Status::OK, s);
+ ASSERT_EQ(3u, halConfig.streams.size());
+ });
+ }
+ }
+
+ session->close();
+ }
+ }
+}
+
+// Verify that all supported preview + still capture stream combinations
+// can be configured successfully.
+TEST_F(CameraHidlTest, configureStreamsPreviewStillOutputs) {
+ CameraHidlEnvironment* env = CameraHidlEnvironment::Instance();
+ hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames();
+ std::vector<AvailableStream> outputBlobStreams;
+ std::vector<AvailableStream> outputPreviewStreams;
+ AvailableStream previewThreshold = {MAX_PREVIEW_WIDTH, MAX_PREVIEW_HEIGHT,
+ static_cast<int32_t>(PixelFormat::IMPLEMENTATION_DEFINED)};
+ AvailableStream blobThreshold = {INT32_MAX, INT32_MAX,
+ static_cast<int32_t>(PixelFormat::BLOB)};
+
+ for (const auto& name : cameraDeviceNames) {
+ if (getCameraDeviceVersion(name) == CAMERA_DEVICE_API_VERSION_3_2) {
+ ::android::sp<::android::hardware::camera::device::V3_2::ICameraDevice> device3_2;
+ ALOGI("configureStreams: Testing camera device %s", name.c_str());
+ env->mProvider->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_2 = device;
+ });
+
+ sp<EmptyDeviceCb> cb = new EmptyDeviceCb;
+ sp<ICameraDeviceSession> session;
+ device3_2->open(
+ cb,
+ [&](auto status, const auto& newSession) {
+ ALOGI("device::open returns status:%d", (int)status);
+ ASSERT_EQ(Status::OK, status);
+ ASSERT_NE(newSession, nullptr);
+ session = newSession;
+ });
+
+ camera_metadata_t *staticMeta;
+ device3_2->getCameraCharacteristics([&] (Status s,
+ CameraMetadata metadata) {
+ ASSERT_EQ(Status::OK, s);
+ staticMeta =
+ reinterpret_cast<camera_metadata_t*>(metadata.data());
+ });
+ outputBlobStreams.clear();
+ ASSERT_EQ(Status::OK, getAvailableOutputStreams(staticMeta,
+ outputBlobStreams, &blobThreshold));
+ ASSERT_NE(0u, outputBlobStreams.size());
+
+ outputPreviewStreams.clear();
+ ASSERT_EQ(Status::OK, getAvailableOutputStreams(staticMeta,
+ outputPreviewStreams, &previewThreshold));
+ ASSERT_NE(0u, outputPreviewStreams.size());
+
+ int32_t streamId = 0;
+ for (auto &blobIter : outputBlobStreams) {
+ for (auto &previewIter : outputPreviewStreams) {
+ Stream previewStream = {streamId++, StreamType::OUTPUT,
+ static_cast<uint32_t> (previewIter.width),
+ static_cast<uint32_t> (previewIter.height),
+ static_cast<PixelFormat> (previewIter.format), 0, 0,
+ StreamRotation::ROTATION_0};
+ Stream blobStream = {streamId++, StreamType::OUTPUT,
+ static_cast<uint32_t> (blobIter.width),
+ static_cast<uint32_t> (blobIter.height),
+ static_cast<PixelFormat> (blobIter.format), 0, 0,
+ StreamRotation::ROTATION_0};
+ ::android::hardware::hidl_vec<Stream> streams = {
+ previewStream, blobStream};
+ StreamConfiguration config = {streams,
+ StreamConfigurationMode::NORMAL_MODE};
+ session->configureStreams(config, [streamId] (Status s,
+ HalStreamConfiguration halConfig) {
+ ASSERT_EQ(Status::OK, s);
+ ASSERT_EQ(2u, halConfig.streams.size());
+ });
+ }
+ }
+
+ session->close();
+ }
+ }
+}
+
+// In case constrained mode is supported, test whether it can be
+// configured. Additionally check for common invalid inputs when
+// using this mode.
+TEST_F(CameraHidlTest, configureStreamsConstrainedOutputs) {
+ CameraHidlEnvironment* env = CameraHidlEnvironment::Instance();
+ hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames();
+
+ for (const auto& name : cameraDeviceNames) {
+ if (getCameraDeviceVersion(name) == CAMERA_DEVICE_API_VERSION_3_2) {
+ ::android::sp<::android::hardware::camera::device::V3_2::ICameraDevice> device3_2;
+ ALOGI("configureStreams: Testing camera device %s", name.c_str());
+ env->mProvider->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_2 = device;
+ });
+
+ sp<EmptyDeviceCb> cb = new EmptyDeviceCb;
+ sp<ICameraDeviceSession> session;
+ device3_2->open(
+ cb,
+ [&](auto status, const auto& newSession) {
+ ALOGI("device::open returns status:%d", (int)status);
+ ASSERT_EQ(Status::OK, status);
+ ASSERT_NE(newSession, nullptr);
+ session = newSession;
+ });
+
+ camera_metadata_t *staticMeta;
+ device3_2->getCameraCharacteristics([&] (Status s,
+ CameraMetadata metadata) {
+ ASSERT_EQ(Status::OK, s);
+ staticMeta =
+ reinterpret_cast<camera_metadata_t*>(metadata.data());
+ });
+ Status rc = isConstrainedModeAvailable(staticMeta);
+ if (Status::METHOD_NOT_SUPPORTED == rc) {
+ session->close();
+ continue;
+ }
+ ASSERT_EQ(Status::OK, rc);
+
+ AvailableStream hfrStream;
+ rc = pickConstrainedModeSize(staticMeta, hfrStream);
+ ASSERT_EQ(Status::OK, rc);
+
+ int32_t streamId = 0;
+ Stream stream = {streamId, StreamType::OUTPUT,
+ static_cast<uint32_t> (hfrStream.width),
+ static_cast<uint32_t> (hfrStream.height),
+ static_cast<PixelFormat> (hfrStream.format), 0, 0,
+ StreamRotation::ROTATION_0};
+ ::android::hardware::hidl_vec<Stream> streams = {stream};
+ StreamConfiguration config = {streams,
+ StreamConfigurationMode::CONSTRAINED_HIGH_SPEED_MODE};
+ session->configureStreams(config, [streamId] (Status s,
+ HalStreamConfiguration halConfig) {
+ ASSERT_EQ(Status::OK, s);
+ ASSERT_EQ(1u, halConfig.streams.size());
+ ASSERT_EQ(halConfig.streams[0].id, streamId);
+ });
+
+ stream = {streamId++, StreamType::OUTPUT,
+ static_cast<uint32_t> (0),
+ static_cast<uint32_t> (0),
+ static_cast<PixelFormat> (hfrStream.format), 0, 0,
+ StreamRotation::ROTATION_0};
+ streams[0] = stream;
+ config = {streams,
+ StreamConfigurationMode::CONSTRAINED_HIGH_SPEED_MODE};
+ session->configureStreams(config, [streamId] (Status s,
+ HalStreamConfiguration) {
+ ASSERT_EQ(Status::ILLEGAL_ARGUMENT, s);
+ });
+
+ stream = {streamId++, StreamType::OUTPUT,
+ static_cast<uint32_t> (UINT32_MAX),
+ static_cast<uint32_t> (UINT32_MAX),
+ static_cast<PixelFormat> (hfrStream.format), 0, 0,
+ StreamRotation::ROTATION_0};
+ streams[0] = stream;
+ config = {streams,
+ StreamConfigurationMode::CONSTRAINED_HIGH_SPEED_MODE};
+ session->configureStreams(config, [streamId] (Status s,
+ HalStreamConfiguration) {
+ ASSERT_EQ(Status::ILLEGAL_ARGUMENT, s);
+ });
+
+ stream = {streamId++, StreamType::OUTPUT,
+ static_cast<uint32_t> (hfrStream.width),
+ static_cast<uint32_t> (hfrStream.height),
+ static_cast<PixelFormat> (UINT32_MAX), 0, 0,
+ StreamRotation::ROTATION_0};
+ streams[0] = stream;
+ config = {streams,
+ StreamConfigurationMode::CONSTRAINED_HIGH_SPEED_MODE};
+ session->configureStreams(config, [streamId] (Status s,
+ HalStreamConfiguration) {
+ ASSERT_EQ(Status::ILLEGAL_ARGUMENT, s);
+ });
+
+ session->close();
+ }
+ }
+}
+
+// Verify that all supported video + snapshot stream combinations can
+// be configured successfully.
+TEST_F(CameraHidlTest, configureStreamsVideoStillOutputs) {
CameraHidlEnvironment* env = CameraHidlEnvironment::Instance();
hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames();
+ std::vector<AvailableStream> outputBlobStreams;
+ std::vector<AvailableStream> outputVideoStreams;
+ AvailableStream videoThreshold = {MAX_VIDEO_WIDTH, MAX_VIDEO_HEIGHT,
+ static_cast<int32_t>(PixelFormat::IMPLEMENTATION_DEFINED)};
+ AvailableStream blobThreshold = {MAX_VIDEO_WIDTH, MAX_VIDEO_HEIGHT,
+ static_cast<int32_t>(PixelFormat::BLOB)};
for (const auto& name : cameraDeviceNames) {
if (getCameraDeviceVersion(name) == CAMERA_DEVICE_API_VERSION_3_2) {
session = newSession;
});
+ camera_metadata_t *staticMeta;
+ device3_2->getCameraCharacteristics([&] (Status s,
+ CameraMetadata metadata) {
+ ASSERT_EQ(Status::OK, s);
+ staticMeta =
+ reinterpret_cast<camera_metadata_t*>(metadata.data());
+ });
+ outputBlobStreams.clear();
+ ASSERT_EQ(Status::OK, getAvailableOutputStreams(staticMeta,
+ outputBlobStreams, &blobThreshold));
+ ASSERT_NE(0u, outputBlobStreams.size());
+
+ outputVideoStreams.clear();
+ ASSERT_EQ(Status::OK, getAvailableOutputStreams(staticMeta,
+ outputVideoStreams, &videoThreshold));
+ ASSERT_NE(0u, outputVideoStreams.size());
+
+ int32_t streamId = 0;
+ for (auto &blobIter : outputBlobStreams) {
+ for (auto &videoIter : outputVideoStreams) {
+ Stream videoStream = {streamId++, StreamType::OUTPUT,
+ static_cast<uint32_t> (videoIter.width),
+ static_cast<uint32_t> (videoIter.height),
+ static_cast<PixelFormat> (videoIter.format), 0, 0,
+ StreamRotation::ROTATION_0};
+ Stream blobStream = {streamId++, StreamType::OUTPUT,
+ static_cast<uint32_t> (blobIter.width),
+ static_cast<uint32_t> (blobIter.height),
+ static_cast<PixelFormat> (blobIter.format),
+ GRALLOC_USAGE_HW_VIDEO_ENCODER, 0,
+ StreamRotation::ROTATION_0};
+ ::android::hardware::hidl_vec<Stream> streams = {
+ videoStream, blobStream};
+ StreamConfiguration config = {streams,
+ StreamConfigurationMode::NORMAL_MODE};
+ session->configureStreams(config, [streamId] (Status s,
+ HalStreamConfiguration halConfig) {
+ ASSERT_EQ(Status::OK, s);
+ ASSERT_EQ(2u, halConfig.streams.size());
+ });
+ }
+ }
session->close();
}
}
}
+// Retrieve all valid output stream resolutions from the camera
+// static characteristics.
+Status CameraHidlTest::getAvailableOutputStreams(camera_metadata_t *staticMeta,
+ std::vector<AvailableStream> &outputStreams,
+ AvailableStream *threshold) {
+ if (nullptr == staticMeta) {
+ return Status::ILLEGAL_ARGUMENT;
+ }
+
+ camera_metadata_ro_entry entry;
+ int rc = find_camera_metadata_ro_entry(staticMeta,
+ ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS, &entry);
+ if ((0 != rc) || (0 != (entry.count % 4))) {
+ return Status::ILLEGAL_ARGUMENT;
+ }
+
+ for (size_t i = 0; i < entry.count; i+=4) {
+ if (ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT ==
+ entry.data.i32[i + 3]) {
+ if(nullptr == threshold) {
+ AvailableStream s = {entry.data.i32[i+1],
+ entry.data.i32[i+2], entry.data.i32[i]};
+ outputStreams.push_back(s);
+ } else {
+ if ((threshold->format == entry.data.i32[i]) &&
+ (threshold->width >= entry.data.i32[i+1]) &&
+ (threshold->height >= entry.data.i32[i+2])) {
+ AvailableStream s = {entry.data.i32[i+1],
+ entry.data.i32[i+2], threshold->format};
+ outputStreams.push_back(s);
+ }
+ }
+ }
+
+ }
+
+ return Status::OK;
+}
+
+// Check if constrained mode is supported by using the static
+// camera characteristics.
+Status CameraHidlTest::isConstrainedModeAvailable(camera_metadata_t *staticMeta) {
+ Status ret = Status::METHOD_NOT_SUPPORTED;
+ if (nullptr == staticMeta) {
+ return Status::ILLEGAL_ARGUMENT;
+ }
+
+ camera_metadata_ro_entry entry;
+ int rc = find_camera_metadata_ro_entry(staticMeta,
+ ANDROID_REQUEST_AVAILABLE_CAPABILITIES, &entry);
+ if (0 != rc) {
+ return Status::ILLEGAL_ARGUMENT;
+ }
+
+ for (size_t i = 0; i < entry.count; i++) {
+ if (ANDROID_REQUEST_AVAILABLE_CAPABILITIES_CONSTRAINED_HIGH_SPEED_VIDEO ==
+ entry.data.u8[i]) {
+ ret = Status::OK;
+ break;
+ }
+ }
+
+ return ret;
+}
+
+// Pick the largest supported HFR mode from the static camera
+// characteristics.
+Status CameraHidlTest::pickConstrainedModeSize(camera_metadata_t *staticMeta,
+ AvailableStream &hfrStream) {
+ if (nullptr == staticMeta) {
+ return Status::ILLEGAL_ARGUMENT;
+ }
+
+ camera_metadata_ro_entry entry;
+ int rc = find_camera_metadata_ro_entry(staticMeta,
+ ANDROID_CONTROL_AVAILABLE_HIGH_SPEED_VIDEO_CONFIGURATIONS, &entry);
+ if (0 != rc) {
+ return Status::METHOD_NOT_SUPPORTED;
+ } else if (0 != (entry.count % 5)) {
+ return Status::ILLEGAL_ARGUMENT;
+ }
+
+ hfrStream = {0, 0,
+ static_cast<uint32_t>(PixelFormat::IMPLEMENTATION_DEFINED)};
+ for (size_t i = 0; i < entry.count; i+=5) {
+ int32_t w = entry.data.i32[i];
+ int32_t h = entry.data.i32[i+1];
+ if ((hfrStream.width * hfrStream.height) < (w *h)) {
+ hfrStream.width = w;
+ hfrStream.height = h;
+ }
+ }
+
+ return Status::OK;
+}
+
+// Check whether ZSL is available using the static camera
+// characteristics.
+Status CameraHidlTest::isZSLModeAvailable(camera_metadata_t *staticMeta) {
+ Status ret = Status::METHOD_NOT_SUPPORTED;
+ if (nullptr == staticMeta) {
+ return Status::ILLEGAL_ARGUMENT;
+ }
+
+ camera_metadata_ro_entry entry;
+ int rc = find_camera_metadata_ro_entry(staticMeta,
+ ANDROID_REQUEST_AVAILABLE_CAPABILITIES, &entry);
+ if (0 != rc) {
+ return Status::ILLEGAL_ARGUMENT;
+ }
+
+ for (size_t i = 0; i < entry.count; i++) {
+ if ((ANDROID_REQUEST_AVAILABLE_CAPABILITIES_PRIVATE_REPROCESSING ==
+ entry.data.u8[i]) ||
+ (ANDROID_REQUEST_AVAILABLE_CAPABILITIES_YUV_REPROCESSING ==
+ entry.data.u8[i]) ){
+ ret = Status::OK;
+ break;
+ }
+ }
+
+ return ret;
+}
+
+// Retrieve the reprocess input-output format map from the static
+// camera characteristics.
+Status CameraHidlTest::getZSLInputOutputMap(camera_metadata_t *staticMeta,
+ std::vector<AvailableZSLInputOutput> &inputOutputMap) {
+ if (nullptr == staticMeta) {
+ return Status::ILLEGAL_ARGUMENT;
+ }
+
+ camera_metadata_ro_entry entry;
+ int rc = find_camera_metadata_ro_entry(staticMeta,
+ ANDROID_SCALER_AVAILABLE_INPUT_OUTPUT_FORMATS_MAP, &entry);
+ if ((0 != rc) || (0 >= entry.count)) {
+ return Status::ILLEGAL_ARGUMENT;
+ }
+
+ const int32_t* contents = &entry.data.i32[0];
+ for (size_t i = 0; i < entry.count; ) {
+ int32_t inputFormat = contents[i++];
+ int32_t length = contents[i++];
+ for (int32_t j = 0; j < length; j++) {
+ int32_t outputFormat = contents[i+j];
+ AvailableZSLInputOutput zslEntry = {inputFormat, outputFormat};
+ inputOutputMap.push_back(zslEntry);
+ }
+ i += length;
+ }
+
+ return Status::OK;
+}
+
+// Search for the largest stream size for a given format.
+Status CameraHidlTest::findLargestSize(
+ const std::vector<AvailableStream> &streamSizes, int32_t format,
+ AvailableStream &result) {
+ result = {0, 0, 0};
+ for (auto &iter : streamSizes) {
+ if (format == iter.format) {
+ if ((result.width * result.height) < (iter.width * iter.height)) {
+ result = iter;
+ }
+ }
+ }
+
+ return (result.format == format) ? Status::OK : Status::ILLEGAL_ARGUMENT;
+}
+
int main(int argc, char **argv) {
::testing::AddGlobalTestEnvironment(CameraHidlEnvironment::Instance());
::testing::InitGoogleTest(&argc, argv);