Only provide templates for supported capabilities
Plugs in the StaticProperties class for ease of accessing the
static metadata.
Expands StaticProperties to handle checking template support.
Test: Unit tests pass, test app runs, fixes 2 failing CTS tests on rpi3
BUG: b/32951283
Change-Id: I3077a3507751c3072b88f7d91902bdaa5b53c30e
diff --git a/modules/camera/3_4/camera.cpp b/modules/camera/3_4/camera.cpp
index dc9c825..5a89e3e 100644
--- a/modules/camera/3_4/camera.cpp
+++ b/modules/camera/3_4/camera.cpp
@@ -97,60 +97,50 @@
int Camera::getInfo(struct camera_info *info)
{
- android::Mutex::Autolock al(mStaticInfoLock);
-
info->device_version = mDevice.common.version;
initDeviceInfo(info);
- if (mStaticInfo == NULL) {
- std::unique_ptr<android::CameraMetadata> static_info =
- std::make_unique<android::CameraMetadata>();
- if (initStaticInfo(static_info.get())) {
- return -ENODEV;
+ if (!mStaticInfo) {
+ int res = loadStaticInfo();
+ if (res) {
+ return res;
}
- mStaticInfo = std::move(static_info);
}
- // The "locking" here only causes non-const methods to fail,
- // which is not a problem since the CameraMetadata being locked
- // is already const. Destructing automatically "unlocks".
- info->static_camera_characteristics = mStaticInfo->getAndLock();
-
- // Get facing & orientation from the static info.
- uint8_t facing = 0;
- int res = v4l2_camera_hal::SingleTagValue(
- *mStaticInfo, ANDROID_LENS_FACING, &facing);
- if (res) {
- ALOGE("%s:%d: Failed to get facing from static metadata.",
- __func__, mId);
- return res;
- }
- switch (facing) {
- case (ANDROID_LENS_FACING_FRONT):
- info->facing = CAMERA_FACING_FRONT;
- break;
- case (ANDROID_LENS_FACING_BACK):
- info->facing = CAMERA_FACING_BACK;
- break;
- case (ANDROID_LENS_FACING_EXTERNAL):
- info->facing = CAMERA_FACING_EXTERNAL;
- break;
- default:
- ALOGE("%s:%d: Invalid facing from metadata: %d.",
- __func__, mId, facing);
- return -ENODEV;
- }
- int32_t orientation = 0;
- res = v4l2_camera_hal::SingleTagValue(
- *mStaticInfo, ANDROID_SENSOR_ORIENTATION, &orientation);
- if (res) {
- ALOGE("%s:%d: Failed to get orientation from static metadata.",
- __func__, mId);
- return res;
- }
- info->orientation = static_cast<int>(orientation);
+ info->static_camera_characteristics = mStaticInfo->raw_metadata();
+ info->facing = mStaticInfo->facing();
+ info->orientation = mStaticInfo->orientation();
return 0;
}
+int Camera::loadStaticInfo() {
+ // Using a lock here ensures |mStaticInfo| will only ever be set once,
+ // even in concurrent situations.
+ android::Mutex::Autolock al(mStaticInfoLock);
+
+ if (mStaticInfo) {
+ return 0;
+ }
+
+ std::unique_ptr<android::CameraMetadata> static_metadata =
+ std::make_unique<android::CameraMetadata>();
+ int res = initStaticInfo(static_metadata.get());
+ if (res) {
+ ALOGE("%s:%d: Failed to get static info from device.",
+ __func__, mId);
+ return res;
+ }
+
+ mStaticInfo.reset(StaticProperties::NewStaticProperties(
+ std::move(static_metadata)));
+ if (!mStaticInfo) {
+ ALOGE("%s:%d: Failed to initialize static properties from device metadata.",
+ __func__, mId);
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
int Camera::close()
{
ALOGI("%s:%d: Closing camera device", __func__, mId);
@@ -373,6 +363,14 @@
}
if (!mTemplates[type]) {
+ // Check if the device has the necessary features
+ // for the requested template. If not, don't bother.
+ if (!mStaticInfo->TemplateSupported(type)) {
+ ALOGW("%s:%d: Camera does not support template type %d",
+ __func__, mId, type);
+ return NULL;
+ }
+
// Initialize this template if it hasn't been initialized yet.
std::unique_ptr<android::CameraMetadata> new_template =
std::make_unique<android::CameraMetadata>();
diff --git a/modules/camera/3_4/camera.h b/modules/camera/3_4/camera.h
index e1f7639..2685fd1 100644
--- a/modules/camera/3_4/camera.h
+++ b/modules/camera/3_4/camera.h
@@ -27,6 +27,7 @@
#include "capture_request.h"
#include "metadata/metadata.h"
#include "request_tracker.h"
+#include "static_properties.h"
#include "stream.h"
namespace default_camera_hal {
@@ -97,6 +98,8 @@
private:
// Camera device handle returned to framework for use
camera3_device_t mDevice;
+ // Get static info from the device and store it in mStaticInfo.
+ int loadStaticInfo();
// Reuse a stream already created by this device
Stream *reuseStream(camera3_stream_t *astream);
// Destroy all streams in a stream array, and the array itself
@@ -121,7 +124,7 @@
// Identifier used by framework to distinguish cameras
const int mId;
// CameraMetadata containing static characteristics
- std::unique_ptr<const android::CameraMetadata> mStaticInfo;
+ std::unique_ptr<StaticProperties> mStaticInfo;
// Flag indicating if settings have been set since
// the last configure_streams() call.
bool mSettingsSet;
diff --git a/modules/camera/3_4/metadata/metadata_reader.cpp b/modules/camera/3_4/metadata/metadata_reader.cpp
index 53c9535..fe2ff85 100644
--- a/modules/camera/3_4/metadata/metadata_reader.cpp
+++ b/modules/camera/3_4/metadata/metadata_reader.cpp
@@ -114,6 +114,21 @@
return 0;
}
+int MetadataReader::RequestCapabilities(std::set<uint8_t>* capabilities) const {
+ std::vector<uint8_t> raw_capabilities;
+ int res = v4l2_camera_hal::VectorTagValue(
+ *metadata_, ANDROID_REQUEST_AVAILABLE_CAPABILITIES, &raw_capabilities);
+ if (res) {
+ ALOGE("%s: Failed to get request capabilities from static metadata.",
+ __func__);
+ return res;
+ }
+
+ // Move from vector to set.
+ capabilities->insert(raw_capabilities.begin(), raw_capabilities.end());
+ return 0;
+}
+
int MetadataReader::StreamConfigurations(
std::vector<StreamConfiguration>* configs) const {
std::vector<RawStreamConfiguration> raw_stream_configs;
diff --git a/modules/camera/3_4/metadata/metadata_reader.h b/modules/camera/3_4/metadata/metadata_reader.h
index 828e992..996bf8b 100644
--- a/modules/camera/3_4/metadata/metadata_reader.h
+++ b/modules/camera/3_4/metadata/metadata_reader.h
@@ -19,6 +19,8 @@
#include <map>
#include <memory>
+#include <set>
+#include <vector>
#include <camera/CameraMetadata.h>
@@ -57,6 +59,7 @@
virtual int MaxOutputStreams(int32_t* max_raw_output_streams,
int32_t* max_non_stalling_output_streams,
int32_t* max_stalling_output_streams) const;
+ virtual int RequestCapabilities(std::set<uint8_t>* capabilites) const;
virtual int StreamConfigurations(
std::vector<StreamConfiguration>* configs) const;
virtual int StreamStallDurations(
diff --git a/modules/camera/3_4/metadata/metadata_reader_mock.h b/modules/camera/3_4/metadata/metadata_reader_mock.h
index fcd0704..19895a7 100644
--- a/modules/camera/3_4/metadata/metadata_reader_mock.h
+++ b/modules/camera/3_4/metadata/metadata_reader_mock.h
@@ -33,6 +33,7 @@
MOCK_CONST_METHOD1(Orientation, int(int*));
MOCK_CONST_METHOD1(MaxInputStreams, int(int32_t*));
MOCK_CONST_METHOD3(MaxOutputStreams, int(int32_t*, int32_t*, int32_t*));
+ MOCK_CONST_METHOD1(RequestCapabilities, int(std::set<uint8_t>*));
MOCK_CONST_METHOD1(StreamConfigurations,
int(std::vector<StreamConfiguration>*));
MOCK_CONST_METHOD1(StreamStallDurations,
diff --git a/modules/camera/3_4/metadata/metadata_reader_test.cpp b/modules/camera/3_4/metadata/metadata_reader_test.cpp
index eadf51c..5b9cc63 100644
--- a/modules/camera/3_4/metadata/metadata_reader_test.cpp
+++ b/modules/camera/3_4/metadata/metadata_reader_test.cpp
@@ -363,8 +363,6 @@
}
TEST_F(MetadataReaderTest, EmptyReprocessFormats) {
- // 3 indicates that there are 3 output formats for input format 1,
- // which is not ok since there are only 2 here.
FillDUT();
ReprocessFormatMap actual;
ASSERT_EQ(dut_->ReprocessFormats(&actual), -ENOENT);
diff --git a/modules/camera/3_4/static_properties.cpp b/modules/camera/3_4/static_properties.cpp
index 0584290..b075e6e 100644
--- a/modules/camera/3_4/static_properties.cpp
+++ b/modules/camera/3_4/static_properties.cpp
@@ -19,14 +19,15 @@
// #define LOG_NDEBUG 0
#define LOG_TAG "StaticProperties"
#include <cutils/log.h>
+#include <hardware/camera3.h>
#include <system/camera.h>
#include "metadata/metadata_reader.h"
namespace default_camera_hal {
-// Build and capabilities from configs + stall durations.
-static bool ConstructCapabilities(
+// Build stream capabilities from configs + stall durations.
+static bool ConstructStreamCapabilities(
const std::vector<StreamConfiguration>& configs,
const std::vector<StreamStallDuration>& stalls,
StaticProperties::CapabilitiesMap* capabilities) {
@@ -59,7 +60,7 @@
// Check that each output config has a valid corresponding stall duration
// (extra durations not matching any output config are ignored).
-static bool ValidateCapabilities(
+static bool ValidateStreamCapabilities(
StaticProperties::CapabilitiesMap capabilities) {
for (const auto& spec_capabilities : capabilities) {
// Only non-negative stall durations are valid. This should only happen
@@ -146,9 +147,10 @@
int32_t max_raw_output_streams = 0;
int32_t max_non_stalling_output_streams = 0;
int32_t max_stalling_output_streams = 0;
+ std::set<uint8_t> request_capabilities;
std::vector<StreamConfiguration> configs;
std::vector<StreamStallDuration> stalls;
- CapabilitiesMap capabilities;
+ CapabilitiesMap stream_capabilities;
ReprocessFormatMap reprocess_map;
// If reading any data returns an error, something is wrong.
@@ -158,18 +160,19 @@
metadata_reader->MaxOutputStreams(&max_raw_output_streams,
&max_non_stalling_output_streams,
&max_stalling_output_streams) ||
+ metadata_reader->RequestCapabilities(&request_capabilities) ||
metadata_reader->StreamConfigurations(&configs) ||
metadata_reader->StreamStallDurations(&stalls) ||
- !ConstructCapabilities(configs, stalls, &capabilities) ||
+ !ConstructStreamCapabilities(configs, stalls, &stream_capabilities) ||
// MetadataReader validates configs and stall seperately,
// but not that they match.
- !ValidateCapabilities(capabilities) ||
+ !ValidateStreamCapabilities(stream_capabilities) ||
// Reprocessing metadata only necessary if input streams are allowed.
(max_input_streams > 0 &&
(metadata_reader->ReprocessFormats(&reprocess_map) ||
// MetadataReader validates configs and the reprocess map seperately,
// but not that they match.
- !ValidateReprocessFormats(capabilities, reprocess_map)))) {
+ !ValidateReprocessFormats(stream_capabilities, reprocess_map)))) {
return nullptr;
}
@@ -180,7 +183,8 @@
max_raw_output_streams,
max_non_stalling_output_streams,
max_stalling_output_streams,
- std::move(capabilities),
+ std::move(request_capabilities),
+ std::move(stream_capabilities),
std::move(reprocess_map));
}
@@ -192,6 +196,7 @@
int32_t max_raw_output_streams,
int32_t max_non_stalling_output_streams,
int32_t max_stalling_output_streams,
+ std::set<uint8_t> request_capabilities,
CapabilitiesMap stream_capabilities,
ReprocessFormatMap supported_reprocess_outputs)
: metadata_reader_(std::move(metadata_reader)),
@@ -201,9 +206,33 @@
max_raw_output_streams_(max_raw_output_streams),
max_non_stalling_output_streams_(max_non_stalling_output_streams),
max_stalling_output_streams_(max_stalling_output_streams),
+ request_capabilities_(std::move(request_capabilities)),
stream_capabilities_(std::move(stream_capabilities)),
supported_reprocess_outputs_(std::move(supported_reprocess_outputs)) {}
+bool StaticProperties::TemplateSupported(int type) {
+ uint8_t required_capability = 0;
+ switch (type) {
+ case CAMERA3_TEMPLATE_PREVIEW:
+ // Preview is always supported.
+ return true;
+ case CAMERA3_TEMPLATE_MANUAL:
+ required_capability =
+ ANDROID_REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR;
+ break;
+ case CAMERA3_TEMPLATE_ZERO_SHUTTER_LAG:
+ required_capability =
+ ANDROID_REQUEST_AVAILABLE_CAPABILITIES_PRIVATE_REPROCESSING;
+ break;
+ default:
+ required_capability =
+ ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE;
+ return true;
+ }
+
+ return request_capabilities_.count(required_capability) > 0;
+}
+
// Helper functions for checking stream properties when verifying support.
static bool IsInputType(int stream_type) {
return stream_type == CAMERA3_STREAM_INPUT ||
diff --git a/modules/camera/3_4/static_properties.h b/modules/camera/3_4/static_properties.h
index a687a80..25c8205 100644
--- a/modules/camera/3_4/static_properties.h
+++ b/modules/camera/3_4/static_properties.h
@@ -51,6 +51,11 @@
// except that it may return nullptr in case of failure (missing entries).
static StaticProperties* NewStaticProperties(
std::unique_ptr<const MetadataReader> metadata_reader);
+ static StaticProperties* NewStaticProperties(
+ std::unique_ptr<android::CameraMetadata> metadata) {
+ return NewStaticProperties(
+ std::make_unique<MetadataReader>(std::move(metadata)));
+ }
virtual ~StaticProperties(){};
// Simple accessors.
@@ -62,6 +67,8 @@
return metadata_reader_->raw_metadata();
};
+ // Check if a given template type is supported.
+ bool TemplateSupported(int type);
// Validators (check that values are consistent with the capabilities
// this object represents/base requirements of the camera HAL).
bool StreamConfigurationSupported(
@@ -81,6 +88,7 @@
int32_t max_raw_output_streams,
int32_t max_non_stalling_output_streams,
int32_t max_stalling_output_streams,
+ std::set<uint8_t> request_capabilities,
CapabilitiesMap stream_capabilities,
ReprocessFormatMap supported_reprocess_outputs);
@@ -101,6 +109,7 @@
const int32_t max_raw_output_streams_;
const int32_t max_non_stalling_output_streams_;
const int32_t max_stalling_output_streams_;
+ const std::set<uint8_t> request_capabilities_;
const CapabilitiesMap stream_capabilities_;
const ReprocessFormatMap supported_reprocess_outputs_;
diff --git a/modules/camera/3_4/static_properties_test.cpp b/modules/camera/3_4/static_properties_test.cpp
index 4e41ada..e78e343 100644
--- a/modules/camera/3_4/static_properties_test.cpp
+++ b/modules/camera/3_4/static_properties_test.cpp
@@ -66,6 +66,10 @@
SetArgPointee<1>(test_max_non_stalling_outputs_),
SetArgPointee<2>(test_max_stalling_outputs_),
Return(0)));
+ EXPECT_CALL(*mock_reader_, RequestCapabilities(_))
+ .Times(AtMost(1))
+ .WillOnce(
+ DoAll(SetArgPointee<0>(test_request_capabilities_), Return(0)));
EXPECT_CALL(*mock_reader_, StreamConfigurations(_))
.Times(AtMost(1))
.WillOnce(DoAll(SetArgPointee<0>(test_configs_), Return(0)));
@@ -125,6 +129,10 @@
const int32_t test_max_raw_outputs_ = 1;
const int32_t test_max_non_stalling_outputs_ = 2;
const int32_t test_max_stalling_outputs_ = 3;
+ const std::set<uint8_t> test_request_capabilities_ = {
+ ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE,
+ ANDROID_REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR,
+ ANDROID_REQUEST_AVAILABLE_CAPABILITIES_PRIVATE_REPROCESSING};
// Some formats for various purposes (in various combinations,
// these types should be capable of testing all failure conditions).
@@ -227,6 +235,14 @@
EXPECT_EQ(dut_, nullptr);
}
+TEST_F(StaticPropertiesTest, FactoryFailedRequestCapabilities) {
+ SetDefaultExpectations();
+ // Override with a failure expectation.
+ EXPECT_CALL(*mock_reader_, RequestCapabilities(_)).WillOnce(Return(99));
+ PrepareDUT();
+ EXPECT_EQ(dut_, nullptr);
+}
+
TEST_F(StaticPropertiesTest, FactoryFailedStreamConfigs) {
SetDefaultExpectations();
// Override with a failure expectation.
@@ -355,6 +371,13 @@
EXPECT_EQ(dut_, nullptr);
}
+TEST_F(StaticPropertiesTest, TemplatesValid) {
+ PrepareDefaultDUT();
+ for (int i = 1; i < CAMERA3_TEMPLATE_COUNT; ++i) {
+ EXPECT_TRUE(dut_->TemplateSupported(i));
+ }
+}
+
TEST_F(StaticPropertiesTest, ConfigureSingleOutput) {
std::vector<camera3_stream_t> streams;
streams.push_back(MakeStream(output_multisize_non_stalling_));