Dynamic default metadata based on templates
Instead of controls picking their own defaults,
a delegate taking a mapping of template : desired default
is taken instead. These defaults are honored if able.
BUG: b/31017806
TEST: unit tests pass, multiple CTS tests fixed, test app runs.
Change-Id: I8212580c9aee1d7fe223fa6b3ff17a6cfb97552f
diff --git a/modules/camera/3_4/Android.mk b/modules/camera/3_4/Android.mk
index 1211a08..8e3c85a 100644
--- a/modules/camera/3_4/Android.mk
+++ b/modules/camera/3_4/Android.mk
@@ -57,6 +57,7 @@
v4l2_test_files := \
format_metadata_factory_test.cpp \
metadata/control_test.cpp \
+ metadata/default_option_delegate_test.cpp \
metadata/enum_converter_test.cpp \
metadata/ignored_control_delegate_test.cpp \
metadata/map_converter_test.cpp \
diff --git a/modules/camera/3_4/format_metadata_factory.cpp b/modules/camera/3_4/format_metadata_factory.cpp
index 673477b..9ec15ed 100644
--- a/modules/camera/3_4/format_metadata_factory.cpp
+++ b/modules/camera/3_4/format_metadata_factory.cpp
@@ -186,6 +186,15 @@
fps_ranges.push_back({{min_fps, max_yuv_fps}});
fps_ranges.push_back({{max_yuv_fps, max_yuv_fps}});
+ std::array<int32_t, 2> video_fps_range;
+ int32_t video_fps = 30;
+ if (video_fps >= max_yuv_fps) {
+ video_fps_range = {{max_yuv_fps, max_yuv_fps}};
+ } else {
+ video_fps_range = {{video_fps, video_fps}};
+ fps_ranges.push_back(video_fps_range);
+ }
+
// Construct the metadata components.
insertion_point = std::make_unique<Property<ArrayVector<int32_t, 4>>>(
ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS,
@@ -201,7 +210,9 @@
insertion_point = NoEffectMenuControl<std::array<int32_t, 2>>(
ANDROID_CONTROL_AE_TARGET_FPS_RANGE,
ANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES,
- fps_ranges);
+ fps_ranges,
+ {{CAMERA3_TEMPLATE_VIDEO_RECORD, video_fps_range},
+ {OTHER_TEMPLATES, fps_ranges[0]}});
return 0;
}
diff --git a/modules/camera/3_4/format_metadata_factory_test.cpp b/modules/camera/3_4/format_metadata_factory_test.cpp
index a9603e8..d37b09f 100644
--- a/modules/camera/3_4/format_metadata_factory_test.cpp
+++ b/modules/camera/3_4/format_metadata_factory_test.cpp
@@ -64,7 +64,8 @@
// Device must support IMPLEMENTATION_DEFINED (as well as JPEG & YUV).
// Just duplicate the values from another format.
- uint32_t imp_defined_format = StreamFormat::HalToV4L2PixelFormat(HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED);
+ uint32_t imp_defined_format = StreamFormat::HalToV4L2PixelFormat(
+ HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED);
formats.insert(imp_defined_format);
sizes[imp_defined_format] = sizes[V4L2_PIX_FMT_YUV420];
durations[imp_defined_format] = durations[V4L2_PIX_FMT_YUV420];
@@ -119,7 +120,8 @@
}
TEST_F(FormatMetadataFactoryTest, GetFormatMetadataMissingJpeg) {
- uint32_t imp_defined_format = StreamFormat::HalToV4L2PixelFormat(HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED);
+ uint32_t imp_defined_format = StreamFormat::HalToV4L2PixelFormat(
+ HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED);
std::set<uint32_t> formats{V4L2_PIX_FMT_YUV420, imp_defined_format};
EXPECT_CALL(*mock_device_, GetFormats(_))
.WillOnce(DoAll(SetArgPointee<0>(formats), Return(0)));
@@ -127,11 +129,11 @@
ASSERT_EQ(AddFormatComponents(mock_device_,
std::inserter(components, components.end())),
-ENODEV);
-
}
TEST_F(FormatMetadataFactoryTest, GetFormatMetadataMissingYuv) {
- uint32_t imp_defined_format = StreamFormat::HalToV4L2PixelFormat(HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED);
+ uint32_t imp_defined_format = StreamFormat::HalToV4L2PixelFormat(
+ HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED);
std::set<uint32_t> formats{V4L2_PIX_FMT_JPEG, imp_defined_format};
EXPECT_CALL(*mock_device_, GetFormats(_))
.WillOnce(DoAll(SetArgPointee<0>(formats), Return(0)));
@@ -139,10 +141,10 @@
ASSERT_EQ(AddFormatComponents(mock_device_,
std::inserter(components, components.end())),
-ENODEV);
-
}
-TEST_F(FormatMetadataFactoryTest, GetFormatMetadataMissingImplementationDefined) {
+TEST_F(FormatMetadataFactoryTest,
+ GetFormatMetadataMissingImplementationDefined) {
std::set<uint32_t> formats{V4L2_PIX_FMT_JPEG, V4L2_PIX_FMT_YUV420};
EXPECT_CALL(*mock_device_, GetFormats(_))
.WillOnce(DoAll(SetArgPointee<0>(formats), Return(0)));
@@ -150,7 +152,6 @@
ASSERT_EQ(AddFormatComponents(mock_device_,
std::inserter(components, components.end())),
-ENODEV);
-
}
} // namespace v4l2_camera_hal
diff --git a/modules/camera/3_4/metadata/control.h b/modules/camera/3_4/metadata/control.h
index ed86d39..ad3f87b 100644
--- a/modules/camera/3_4/metadata/control.h
+++ b/modules/camera/3_4/metadata/control.h
@@ -69,7 +69,7 @@
template <typename T>
std::vector<int32_t> Control<T>::StaticTags() const {
std::vector<int32_t> result;
- if (options_) {
+ if (options_ && options_->tag() != DO_NOT_REPORT_OPTIONS) {
result.push_back(options_->tag());
}
return result;
@@ -88,7 +88,14 @@
template <typename T>
int Control<T>::PopulateStaticFields(android::CameraMetadata* metadata) const {
if (!options_) {
- HAL_LOGV("No options for control, nothing to populate.");
+ HAL_LOGV("No options for control %d, nothing to populate.",
+ delegate_->tag());
+ return 0;
+ } else if (options_->tag() == DO_NOT_REPORT_OPTIONS) {
+ HAL_LOGV(
+ "Options for control %d are not reported, "
+ "probably are set values defined and already known by the API.",
+ delegate_->tag());
return 0;
}
diff --git a/modules/camera/3_4/metadata/control_test.cpp b/modules/camera/3_4/metadata/control_test.cpp
index 572f25f..f76376c 100644
--- a/modules/camera/3_4/metadata/control_test.cpp
+++ b/modules/camera/3_4/metadata/control_test.cpp
@@ -44,7 +44,7 @@
control_.reset();
}
- virtual void PrepareControl(bool with_options = true) {
+ virtual void PrepareControl() {
// Use this method after all the EXPECT_CALLs to pass ownership of the mocks
// to the device.
std::unique_ptr<TaggedControlDelegate<uint8_t>> delegate =
@@ -52,8 +52,9 @@
delegate_tag_, std::move(mock_delegate_));
std::unique_ptr<TaggedControlOptions<uint8_t>> options =
std::make_unique<TaggedControlOptions<uint8_t>>(
- options_tag_, std::move(mock_options_));
- if (with_options) {
+ report_options_ ? options_tag_ : DO_NOT_REPORT_OPTIONS,
+ std::move(mock_options_));
+ if (use_options_) {
control_.reset(
new Control<uint8_t>(std::move(delegate), std::move(options)));
} else {
@@ -61,8 +62,8 @@
}
}
- virtual void ExpectTags(bool with_options = true) {
- if (with_options) {
+ virtual void ExpectTags() {
+ if (use_options_ && report_options_) {
ASSERT_EQ(control_->StaticTags().size(), 1);
EXPECT_EQ(control_->StaticTags()[0], options_tag_);
} else {
@@ -79,8 +80,14 @@
// Options should be available.
android::CameraMetadata metadata;
ASSERT_EQ(control_->PopulateStaticFields(&metadata), 0);
- EXPECT_EQ(metadata.entryCount(), 1);
- ExpectMetadataEq(metadata, options_tag_, options);
+ if (use_options_ && report_options_) {
+ EXPECT_EQ(metadata.entryCount(), 1);
+ ExpectMetadataEq(metadata, options_tag_, options);
+ } else {
+ EXPECT_EQ(metadata.entryCount(), 0);
+ // Shouldn't be expecting any options.
+ EXPECT_TRUE(options.empty());
+ }
}
virtual void ExpectValue(uint8_t value) {
@@ -93,6 +100,8 @@
std::unique_ptr<Control<uint8_t>> control_;
std::unique_ptr<ControlDelegateInterfaceMock<uint8_t>> mock_delegate_;
std::unique_ptr<ControlOptionsInterfaceMock<uint8_t>> mock_options_;
+ bool use_options_ = true;
+ bool report_options_ = true;
// Need tags that match the data type (uint8_t) being passed.
const int32_t delegate_tag_ = ANDROID_COLOR_CORRECTION_ABERRATION_MODE;
@@ -106,8 +115,15 @@
}
TEST_F(ControlTest, TagsNoOptions) {
- PrepareControl(false);
- ExpectTags(false);
+ use_options_ = false;
+ PrepareControl();
+ ExpectTags();
+}
+
+TEST_F(ControlTest, TagsUnreportedOptions) {
+ report_options_ = false;
+ PrepareControl();
+ ExpectTags();
}
TEST_F(ControlTest, PopulateStatic) {
@@ -119,11 +135,15 @@
}
TEST_F(ControlTest, PopulateStaticNoOptions) {
- PrepareControl(false);
- android::CameraMetadata metadata;
- ASSERT_EQ(control_->PopulateStaticFields(&metadata), 0);
- // Should not have added any entry.
- EXPECT_TRUE(metadata.isEmpty());
+ use_options_ = false;
+ PrepareControl();
+ ExpectOptions({});
+}
+
+TEST_F(ControlTest, PopulateStaticUnreportedOptions) {
+ report_options_ = false;
+ PrepareControl();
+ ExpectOptions({});
}
TEST_F(ControlTest, PopulateDynamic) {
@@ -136,10 +156,21 @@
TEST_F(ControlTest, PopulateDynamicNoOptions) {
// Lack of options shouldn't change anything for PopulateDynamic.
+ use_options_ = false;
uint8_t test_option = 99;
EXPECT_CALL(*mock_delegate_, GetValue(_))
.WillOnce(DoAll(SetArgPointee<0>(test_option), Return(0)));
- PrepareControl(false);
+ PrepareControl();
+ ExpectValue(test_option);
+}
+
+TEST_F(ControlTest, PopulateDynamicUnreportedOptions) {
+ // Lack of reported options shouldn't change anything for PopulateDynamic.
+ report_options_ = false;
+ uint8_t test_option = 99;
+ EXPECT_CALL(*mock_delegate_, GetValue(_))
+ .WillOnce(DoAll(SetArgPointee<0>(test_option), Return(0)));
+ PrepareControl();
ExpectValue(test_option);
}
@@ -179,12 +210,13 @@
}
TEST_F(ControlTest, PopulateTemplateOptionless) {
+ use_options_ = false;
int template_type = 3;
uint8_t value = 12;
// Should use delegate instead of options if no options.
EXPECT_CALL(*mock_delegate_, GetValue(_))
.WillOnce(DoAll(SetArgPointee<0>(value), Return(0)));
- PrepareControl(false);
+ PrepareControl();
android::CameraMetadata metadata;
EXPECT_EQ(control_->PopulateTemplateRequest(template_type, &metadata), 0);
@@ -192,11 +224,39 @@
}
TEST_F(ControlTest, PopulateTemplateOptionlessFail) {
+ use_options_ = false;
int template_type = 3;
int err = 10;
// Should use delegate instead of options if no options.
EXPECT_CALL(*mock_delegate_, GetValue(_)).WillOnce(Return(err));
- PrepareControl(false);
+ PrepareControl();
+
+ android::CameraMetadata metadata;
+ EXPECT_EQ(control_->PopulateTemplateRequest(template_type, &metadata), err);
+}
+
+TEST_F(ControlTest, PopulateTemplateUnreportedOptions) {
+ report_options_ = false;
+ int template_type = 3;
+ uint8_t default_value = 123;
+ // Unreported options should behave just like reported ones for templating.
+ EXPECT_CALL(*mock_options_, DefaultValueForTemplate(template_type, _))
+ .WillOnce(DoAll(SetArgPointee<1>(default_value), Return(0)));
+ PrepareControl();
+
+ android::CameraMetadata metadata;
+ EXPECT_EQ(control_->PopulateTemplateRequest(template_type, &metadata), 0);
+ ExpectMetadataEq(metadata, delegate_tag_, default_value);
+}
+
+TEST_F(ControlTest, PopulateTemplateUnreportedOptionsFail) {
+ report_options_ = false;
+ int template_type = 3;
+ int err = 10;
+ // Unreported options should behave just like reported ones for templating.
+ EXPECT_CALL(*mock_options_, DefaultValueForTemplate(template_type, _))
+ .WillOnce(Return(err));
+ PrepareControl();
android::CameraMetadata metadata;
EXPECT_EQ(control_->PopulateTemplateRequest(template_type, &metadata), err);
@@ -214,10 +274,23 @@
}
TEST_F(ControlTest, SupportsRequestNoOptions) {
+ use_options_ = false;
android::CameraMetadata metadata;
uint8_t test_option = 123;
ASSERT_EQ(UpdateMetadata(&metadata, delegate_tag_, test_option), 0);
- PrepareControl(false);
+ PrepareControl();
+
+ EXPECT_EQ(control_->SupportsRequestValues(metadata), true);
+}
+
+TEST_F(ControlTest, SupportsRequestUnreportedOptions) {
+ report_options_ = false;
+ android::CameraMetadata metadata;
+ uint8_t test_option = 123;
+ ASSERT_EQ(UpdateMetadata(&metadata, delegate_tag_, test_option), 0);
+
+ EXPECT_CALL(*mock_options_, IsSupported(test_option)).WillOnce(Return(true));
+ PrepareControl();
EXPECT_EQ(control_->SupportsRequestValues(metadata), true);
}
@@ -233,6 +306,19 @@
EXPECT_EQ(control_->SupportsRequestValues(metadata), false);
}
+TEST_F(ControlTest, SupportsRequestUnreportedOptionsFail) {
+ report_options_ = false;
+ android::CameraMetadata metadata;
+ uint8_t test_option = 123;
+ ASSERT_EQ(UpdateMetadata(&metadata, delegate_tag_, test_option), 0);
+
+ // Unreported options should still be checked against.
+ EXPECT_CALL(*mock_options_, IsSupported(test_option)).WillOnce(Return(false));
+ PrepareControl();
+
+ EXPECT_EQ(control_->SupportsRequestValues(metadata), false);
+}
+
TEST_F(ControlTest, SupportsRequestInvalidNumber) {
// Start with a request for multiple values.
android::CameraMetadata metadata;
@@ -243,11 +329,12 @@
}
TEST_F(ControlTest, SupportsRequestInvalidNumberNoOptions) {
+ use_options_ = false;
// Start with a request for multiple values.
android::CameraMetadata metadata;
std::vector<uint8_t> test_data = {1, 2, 3};
ASSERT_EQ(UpdateMetadata(&metadata, delegate_tag_, test_data), 0);
- PrepareControl(false);
+ PrepareControl();
// Not having any explicit options does not exempt a control
// from requiring the right number of values.
EXPECT_EQ(control_->SupportsRequestValues(metadata), false);
@@ -277,13 +364,33 @@
}
TEST_F(ControlTest, SetRequestNoOptions) {
+ use_options_ = false;
android::CameraMetadata metadata;
uint8_t test_option = 123;
ASSERT_EQ(UpdateMetadata(&metadata, delegate_tag_, test_option), 0);
// No options, no validation check.
EXPECT_CALL(*mock_delegate_, SetValue(test_option)).WillOnce(Return(0));
- PrepareControl(false);
+ PrepareControl();
+
+ // Make the request.
+ ASSERT_EQ(control_->SetRequestValues(metadata), 0);
+}
+
+TEST_F(ControlTest, SetRequestUnreportedOptions) {
+ report_options_ = false;
+ android::CameraMetadata metadata;
+ uint8_t test_option = 123;
+ ASSERT_EQ(UpdateMetadata(&metadata, delegate_tag_, test_option), 0);
+
+ // Unreported options still get a validation check.
+ Expectation validation_check =
+ EXPECT_CALL(*mock_options_, IsSupported(test_option))
+ .WillOnce(Return(true));
+ EXPECT_CALL(*mock_delegate_, SetValue(test_option))
+ .After(validation_check)
+ .WillOnce(Return(0));
+ PrepareControl();
// Make the request.
ASSERT_EQ(control_->SetRequestValues(metadata), 0);
@@ -328,12 +435,13 @@
}
TEST_F(ControlTest, SetRequestInvalidNumberNoOptions) {
+ use_options_ = false;
// Start with a request for multiple values.
android::CameraMetadata metadata;
std::vector<uint8_t> test_data = {1, 2, 3};
ASSERT_EQ(UpdateMetadata(&metadata, delegate_tag_, test_data), 0);
- PrepareControl(false);
+ PrepareControl();
// Not having explicit options does not change that an incorrect
// number of values is invalid.
EXPECT_EQ(control_->SetRequestValues(metadata), -EINVAL);
diff --git a/modules/camera/3_4/metadata/default_option_delegate.h b/modules/camera/3_4/metadata/default_option_delegate.h
new file mode 100644
index 0000000..f290318
--- /dev/null
+++ b/modules/camera/3_4/metadata/default_option_delegate.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef V4L2_CAMERA_HAL_METADATA_DEFAULT_OPTION_DELEGATE_H_
+#define V4L2_CAMERA_HAL_METADATA_DEFAULT_OPTION_DELEGATE_H_
+
+#include <errno.h>
+
+#include <map>
+
+#include <hardware/camera3.h>
+
+namespace v4l2_camera_hal {
+
+// A constant that can be used to identify an overall default.
+static constexpr int OTHER_TEMPLATES = CAMERA3_TEMPLATE_COUNT;
+
+// DefaultingOptionDelegate provides an interface to get default options from.
+template <typename T>
+class DefaultOptionDelegate {
+ public:
+ // |defaults| maps template types to default values
+ DefaultOptionDelegate(std::map<int, T> defaults)
+ : defaults_(std::move(defaults)){};
+ virtual ~DefaultOptionDelegate(){};
+
+ // Get a default value for a template type. Returns false if no default
+ // provided.
+ virtual bool DefaultValueForTemplate(int template_type, T* default_value) {
+ if (defaults_.count(template_type) > 0) {
+ // Best option is template-specific.
+ *default_value = defaults_[template_type];
+ return true;
+ } else if (defaults_.count(OTHER_TEMPLATES)) {
+ // Fall back to a general default.
+ *default_value = defaults_[OTHER_TEMPLATES];
+ return true;
+ }
+
+ return false;
+ };
+
+ private:
+ std::map<int, T> defaults_;
+};
+
+} // namespace v4l2_camera_hal
+
+#endif // V4L2_CAMERA_HAL_METADATA_DEFAULT_OPTION_DELEGATE_H_
diff --git a/modules/camera/3_4/metadata/default_option_delegate_mock.h b/modules/camera/3_4/metadata/default_option_delegate_mock.h
new file mode 100644
index 0000000..84ec740
--- /dev/null
+++ b/modules/camera/3_4/metadata/default_option_delegate_mock.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// Mock for default option delegates.
+
+#ifndef V4L2_CAMERA_HAL_METADATA_DEFAULT_OPTION_DELEGATE_MOCK_H_
+#define V4L2_CAMERA_HAL_METADATA_DEFAULT_OPTION_DELEGATE_MOCK_H_
+
+#include <gmock/gmock.h>
+
+#include "default_option_delegate.h"
+
+namespace v4l2_camera_hal {
+
+template <typename T>
+class DefaultOptionDelegateMock : public DefaultOptionDelegate<T> {
+ public:
+ DefaultOptionDelegateMock() : DefaultOptionDelegate<T>({}){};
+ MOCK_METHOD2_T(DefaultValueForTemplate, bool(int, T*));
+};
+
+} // namespace v4l2_camera_hal
+
+#endif // V4L2_CAMERA_HAL_METADATA_DEFAULT_OPTION_DELEGATE_MOCK_H_
diff --git a/modules/camera/3_4/metadata/default_option_delegate_test.cpp b/modules/camera/3_4/metadata/default_option_delegate_test.cpp
new file mode 100644
index 0000000..7b61dd4
--- /dev/null
+++ b/modules/camera/3_4/metadata/default_option_delegate_test.cpp
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "default_option_delegate.h"
+
+#include <memory>
+
+#include <gtest/gtest.h>
+#include <hardware/camera3.h>
+
+using testing::Test;
+
+namespace v4l2_camera_hal {
+
+class DefaultOptionDelegateTest : public Test {
+ protected:
+ virtual void SetUp() {
+ dut_.reset(new DefaultOptionDelegate<int>(defaults_));
+ }
+
+ std::unique_ptr<DefaultOptionDelegate<int>> dut_;
+ std::map<int, int> defaults_{{CAMERA3_TEMPLATE_STILL_CAPTURE, 10},
+ {OTHER_TEMPLATES, 20},
+ {CAMERA3_TEMPLATE_VIDEO_SNAPSHOT, 30}};
+};
+
+TEST_F(DefaultOptionDelegateTest, SpecificDefault) {
+ int actual = 0;
+ EXPECT_TRUE(
+ dut_->DefaultValueForTemplate(CAMERA3_TEMPLATE_STILL_CAPTURE, &actual));
+ EXPECT_EQ(actual, defaults_[CAMERA3_TEMPLATE_STILL_CAPTURE]);
+}
+
+TEST_F(DefaultOptionDelegateTest, GeneralDefault) {
+ int actual = 0;
+ // No ZSL default; should fall back to the OTHER_TEMPLATES default.
+ EXPECT_TRUE(dut_->DefaultValueForTemplate(CAMERA3_TEMPLATE_ZERO_SHUTTER_LAG,
+ &actual));
+ EXPECT_EQ(actual, defaults_[OTHER_TEMPLATES]);
+}
+
+TEST_F(DefaultOptionDelegateTest, NoDefaults) {
+ dut_.reset(new DefaultOptionDelegate<int>({}));
+ int actual = 0;
+ EXPECT_FALSE(dut_->DefaultValueForTemplate(CAMERA3_TEMPLATE_ZERO_SHUTTER_LAG,
+ &actual));
+}
+
+} // namespace v4l2_camera_hal
diff --git a/modules/camera/3_4/metadata/menu_control_options.h b/modules/camera/3_4/metadata/menu_control_options.h
index 95ed3b6..c972dc6 100644
--- a/modules/camera/3_4/metadata/menu_control_options.h
+++ b/modules/camera/3_4/metadata/menu_control_options.h
@@ -21,6 +21,7 @@
#include "../common.h"
#include "control_options_interface.h"
+#include "default_option_delegate.h"
namespace v4l2_camera_hal {
@@ -29,7 +30,12 @@
class MenuControlOptions : public ControlOptionsInterface<T> {
public:
// |options| must be non-empty.
- MenuControlOptions(std::vector<T> options) : options_(options) {}
+ MenuControlOptions(std::vector<T> options,
+ std::shared_ptr<DefaultOptionDelegate<T>> defaults)
+ : options_(options), defaults_(defaults){};
+ MenuControlOptions(std::vector<T> options, std::map<int, T> defaults)
+ : options_(options),
+ defaults_(std::make_shared<DefaultOptionDelegate<T>>(defaults)){};
virtual std::vector<T> MetadataRepresentation() override { return options_; };
virtual bool IsSupported(const T& option) override {
@@ -38,18 +44,26 @@
};
virtual int DefaultValueForTemplate(int template_type,
T* default_value) override {
- // TODO(b/31017806): More complex logic, depend on template_type.
// Default to the first option.
if (options_.empty()) {
HAL_LOGE("Can't get default value, options are empty.");
return -ENODEV;
}
+
+ // Try to get it from the defaults delegate.
+ if (defaults_->DefaultValueForTemplate(template_type, default_value) &&
+ IsSupported(*default_value)) {
+ return 0;
+ }
+
+ // Fall back to the first available.
*default_value = options_[0];
return 0;
- }
+ };
private:
std::vector<T> options_;
+ std::shared_ptr<DefaultOptionDelegate<T>> defaults_;
};
} // namespace v4l2_camera_hal
diff --git a/modules/camera/3_4/metadata/menu_control_options_test.cpp b/modules/camera/3_4/metadata/menu_control_options_test.cpp
index 24582f6..1a6ce6e 100644
--- a/modules/camera/3_4/metadata/menu_control_options_test.cpp
+++ b/modules/camera/3_4/metadata/menu_control_options_test.cpp
@@ -18,19 +18,29 @@
#include <memory>
+#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include <hardware/camera3.h>
+#include "default_option_delegate_mock.h"
+
+using testing::Return;
+using testing::SetArgPointee;
using testing::Test;
+using testing::_;
namespace v4l2_camera_hal {
class MenuControlOptionsTest : public Test {
protected:
- virtual void SetUp() { dut_.reset(new MenuControlOptions<int>(options_)); }
+ virtual void SetUp() {
+ mock_defaults_.reset(new DefaultOptionDelegateMock<int>());
+ dut_.reset(new MenuControlOptions<int>(options_, mock_defaults_));
+ }
std::unique_ptr<MenuControlOptions<int>> dut_;
const std::vector<int> options_{1, 10, 19, 30};
+ std::shared_ptr<DefaultOptionDelegateMock<int>> mock_defaults_;
};
TEST_F(MenuControlOptionsTest, MetadataRepresentation) {
@@ -47,19 +57,49 @@
EXPECT_FALSE(dut_->IsSupported(99));
}
-TEST_F(MenuControlOptionsTest, DefaultValue) {
- // All default values should be supported.
- // For some reason, the templates have values in the range [1, COUNT).
- for (int i = 1; i < CAMERA3_TEMPLATE_COUNT; ++i) {
- int value = -1;
- EXPECT_EQ(dut_->DefaultValueForTemplate(i, &value), 0);
- EXPECT_TRUE(dut_->IsSupported(value));
- }
+TEST_F(MenuControlOptionsTest, DelegateDefaultValue) {
+ int template_index = 3;
+ int expected = options_[2];
+ ASSERT_TRUE(dut_->IsSupported(expected));
+ EXPECT_CALL(*mock_defaults_, DefaultValueForTemplate(template_index, _))
+ .WillOnce(DoAll(SetArgPointee<1>(expected), Return(true)));
+ int actual = expected - 1;
+ EXPECT_EQ(dut_->DefaultValueForTemplate(template_index, &actual), 0);
+ EXPECT_EQ(actual, expected);
+}
+
+TEST_F(MenuControlOptionsTest, InvalidDelegateDefaultValue) {
+ // -1 is not a supported option.
+ int template_index = 3;
+ int default_val = -1;
+ ASSERT_FALSE(dut_->IsSupported(default_val));
+
+ EXPECT_CALL(*mock_defaults_, DefaultValueForTemplate(template_index, _))
+ .WillOnce(DoAll(SetArgPointee<1>(default_val), Return(true)));
+
+ int actual = default_val;
+ EXPECT_EQ(dut_->DefaultValueForTemplate(template_index, &actual), 0);
+ // Should just give any supported option instead.
+ EXPECT_TRUE(dut_->IsSupported(actual));
+}
+
+TEST_F(MenuControlOptionsTest, NoDelegateDefaultValue) {
+ int template_index = 3;
+ int actual = -1;
+ ASSERT_FALSE(dut_->IsSupported(actual));
+
+ // Have delegate error.
+ EXPECT_CALL(*mock_defaults_, DefaultValueForTemplate(template_index, _))
+ .WillOnce(Return(false));
+
+ // Should still give *some* supported value.
+ EXPECT_EQ(dut_->DefaultValueForTemplate(template_index, &actual), 0);
+ EXPECT_TRUE(dut_->IsSupported(actual));
}
TEST_F(MenuControlOptionsTest, NoDefaultValue) {
// Invalid options don't have a valid default.
- MenuControlOptions<int> bad_options({});
+ MenuControlOptions<int> bad_options({}, mock_defaults_);
for (int i = 1; i < CAMERA3_TEMPLATE_COUNT; ++i) {
int value = -1;
EXPECT_EQ(bad_options.DefaultValueForTemplate(i, &value), -ENODEV);
diff --git a/modules/camera/3_4/metadata/partial_metadata_factory.h b/modules/camera/3_4/metadata/partial_metadata_factory.h
index 13f3d61..6b6dbd8 100644
--- a/modules/camera/3_4/metadata/partial_metadata_factory.h
+++ b/modules/camera/3_4/metadata/partial_metadata_factory.h
@@ -45,26 +45,31 @@
int32_t delegate_tag, T default_value);
// NoEffectMenuControl: Some menu options, but they have no effect.
-// The default value will be the first element of |options|.
template <typename T>
static std::unique_ptr<Control<T>> NoEffectMenuControl(
- int32_t delegate_tag, int32_t options_tag, const std::vector<T>& options);
+ int32_t delegate_tag,
+ int32_t options_tag,
+ const std::vector<T>& options,
+ std::map<int, T> default_values = {});
// NoEffectSliderControl: A slider of options, but they have no effect.
-// The default value will be |min|.
template <typename T>
-static std::unique_ptr<Control<T>> NoEffectSliderControl(int32_t delegate_tag,
- int32_t options_tag,
- T min,
- T max);
+static std::unique_ptr<Control<T>> NoEffectSliderControl(
+ int32_t delegate_tag,
+ int32_t options_tag,
+ T min,
+ T max,
+ std::map<int, T> default_values = {});
// NoEffectControl: A control with no effect and only a single allowable
// value. Chooses an appropriate ControlOptionsInterface depending on type.
template <typename T>
-static std::unique_ptr<Control<T>> NoEffectControl(ControlType type,
- int32_t delegate_tag,
- int32_t options_tag,
- T value);
+static std::unique_ptr<Control<T>> NoEffectControl(
+ ControlType type,
+ int32_t delegate_tag,
+ int32_t options_tag,
+ T value,
+ std::map<int, T> default_values = {});
// V4L2Control: A control corresponding to a V4L2 control.
template <typename T>
@@ -74,10 +79,12 @@
int32_t options_tag,
std::shared_ptr<V4L2Wrapper> device,
int control_id,
- std::shared_ptr<ConverterInterface<T, int32_t>> converter);
+ std::shared_ptr<ConverterInterface<T, int32_t>> converter,
+ std::map<int, T> default_values = {});
// V4L2ControlOrDefault: Like V4L2Control, but if the V4L2Control fails to
-// initialize for some reason, this method will fall back to NoEffectControl.
+// initialize for some reason, this method will fall back to NoEffectControl
+// with an initial value defined by |fallback_default|.
template <typename T>
static std::unique_ptr<Control<T>> V4L2ControlOrDefault(
ControlType type,
@@ -86,7 +93,8 @@
std::shared_ptr<V4L2Wrapper> device,
int control_id,
std::shared_ptr<ConverterInterface<T, int32_t>> converter,
- const T& default_value);
+ T fallback_default,
+ std::map<int, T> default_values = {});
// -----------------------------------------------------------------------------
@@ -114,9 +122,11 @@
}
template <typename T>
-std::unique_ptr<Control<T>> NoEffectMenuControl(int32_t delegate_tag,
- int32_t options_tag,
- const std::vector<T>& options) {
+std::unique_ptr<Control<T>> NoEffectMenuControl(
+ int32_t delegate_tag,
+ int32_t options_tag,
+ const std::vector<T>& options,
+ std::map<int, T> default_values) {
HAL_LOG_ENTER();
if (options.empty()) {
@@ -129,35 +139,42 @@
delegate_tag,
std::make_unique<NoEffectControlDelegate<T>>(options[0])),
std::make_unique<TaggedControlOptions<T>>(
- options_tag, std::make_unique<MenuControlOptions<T>>(options)));
+ options_tag,
+ std::make_unique<MenuControlOptions<T>>(options, default_values)));
}
template <typename T>
-std::unique_ptr<Control<T>> NoEffectSliderControl(int32_t delegate_tag,
- int32_t options_tag,
- T min,
- T max) {
+std::unique_ptr<Control<T>> NoEffectSliderControl(
+ int32_t delegate_tag,
+ int32_t options_tag,
+ T min,
+ T max,
+ std::map<int, T> default_values) {
HAL_LOG_ENTER();
return std::make_unique<Control<T>>(
std::make_unique<TaggedControlDelegate<T>>(
delegate_tag, std::make_unique<NoEffectControlDelegate<T>>(min)),
std::make_unique<TaggedControlOptions<T>>(
- options_tag, std::make_unique<SliderControlOptions<T>>(min, max)));
+ options_tag,
+ std::make_unique<SliderControlOptions<T>>(min, max, default_values)));
}
template <typename T>
std::unique_ptr<Control<T>> NoEffectControl(ControlType type,
int32_t delegate_tag,
int32_t options_tag,
- T value) {
+ T value,
+ std::map<int, T> default_values) {
HAL_LOG_ENTER();
switch (type) {
case ControlType::kMenu:
- return NoEffectMenuControl<T>(delegate_tag, options_tag, {value});
+ return NoEffectMenuControl<T>(
+ delegate_tag, options_tag, {value}, default_values);
case ControlType::kSlider:
- return NoEffectSliderControl(delegate_tag, options_tag, value, value);
+ return NoEffectSliderControl(
+ delegate_tag, options_tag, value, value, default_values);
}
}
@@ -168,7 +185,8 @@
int32_t options_tag,
std::shared_ptr<V4L2Wrapper> device,
int control_id,
- std::shared_ptr<ConverterInterface<T, int32_t>> converter) {
+ std::shared_ptr<ConverterInterface<T, int32_t>> converter,
+ std::map<int, T> default_values) {
HAL_LOG_ENTER();
// Query the device.
@@ -230,7 +248,8 @@
HAL_LOGE("No valid options for control %d.", control_id);
return nullptr;
}
- result_options.reset(new MenuControlOptions<T>(options));
+
+ result_options.reset(new MenuControlOptions<T>(options, default_values));
// No converter changes necessary.
break;
case V4L2_CTRL_TYPE_INTEGER:
@@ -265,8 +284,8 @@
control_id);
return nullptr;
}
- result_options.reset(
- new SliderControlOptions<T>(metadata_min, metadata_max));
+ result_options.reset(new SliderControlOptions<T>(
+ metadata_min, metadata_max, default_values));
break;
default:
HAL_LOGE("Control %d (%s) is of unsupported type %d",
@@ -294,13 +313,20 @@
std::shared_ptr<V4L2Wrapper> device,
int control_id,
std::shared_ptr<ConverterInterface<T, int32_t>> converter,
- const T& default_value) {
+ T fallback_default,
+ std::map<int, T> default_values) {
HAL_LOG_ENTER();
- std::unique_ptr<Control<T>> result = V4L2Control(
- type, delegate_tag, options_tag, device, control_id, converter);
+ std::unique_ptr<Control<T>> result = V4L2Control(type,
+ delegate_tag,
+ options_tag,
+ device,
+ control_id,
+ converter,
+ default_values);
if (!result) {
- result = NoEffectControl(type, delegate_tag, options_tag, default_value);
+ result = NoEffectControl(
+ type, delegate_tag, options_tag, fallback_default, default_values);
}
return result;
}
diff --git a/modules/camera/3_4/metadata/slider_control_options.h b/modules/camera/3_4/metadata/slider_control_options.h
index 2815dad..88c1651 100644
--- a/modules/camera/3_4/metadata/slider_control_options.h
+++ b/modules/camera/3_4/metadata/slider_control_options.h
@@ -23,6 +23,7 @@
#include "../common.h"
#include "control_options_interface.h"
+#include "default_option_delegate.h"
namespace v4l2_camera_hal {
@@ -31,7 +32,14 @@
class SliderControlOptions : public ControlOptionsInterface<T> {
public:
// |min| must be <= |max|.
- SliderControlOptions(T min, T max) : min_(min), max_(max) {}
+ SliderControlOptions(const T& min,
+ const T& max,
+ std::shared_ptr<DefaultOptionDelegate<T>> defaults)
+ : min_(min), max_(max), defaults_(defaults){};
+ SliderControlOptions(const T& min, const T& max, std::map<int, T> defaults)
+ : min_(min),
+ max_(max),
+ defaults_(std::make_shared<DefaultOptionDelegate<T>>(defaults)){};
virtual std::vector<T> MetadataRepresentation() override {
return {min_, max_};
@@ -41,19 +49,30 @@
};
virtual int DefaultValueForTemplate(int template_type,
T* default_value) override {
- // TODO(b/31017806): More complex logic, depend on template_type.
if (min_ > max_) {
HAL_LOGE("No valid default slider option, min is greater than max.");
return -ENODEV;
}
- // Default to the min value.
+
+ if (defaults_->DefaultValueForTemplate(template_type, default_value)) {
+ // Get as close as we can to the desired value.
+ if (*default_value < min_) {
+ *default_value = min_;
+ } else if (*default_value > max_) {
+ *default_value = max_;
+ }
+ return 0;
+ }
+
+ // No default given, just fall back to the min of the range.
*default_value = min_;
return 0;
- }
+ };
private:
T min_;
T max_;
+ std::shared_ptr<DefaultOptionDelegate<T>> defaults_;
};
} // namespace v4l2_camera_hal
diff --git a/modules/camera/3_4/metadata/slider_control_options_test.cpp b/modules/camera/3_4/metadata/slider_control_options_test.cpp
index a241ad6..b7cef5a 100644
--- a/modules/camera/3_4/metadata/slider_control_options_test.cpp
+++ b/modules/camera/3_4/metadata/slider_control_options_test.cpp
@@ -18,20 +18,28 @@
#include <memory>
+#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include <hardware/camera3.h>
+#include "default_option_delegate_mock.h"
+
+using testing::Return;
+using testing::SetArgPointee;
using testing::Test;
+using testing::_;
namespace v4l2_camera_hal {
class SliderControlOptionsTest : public Test {
protected:
virtual void SetUp() {
- dut_.reset(new SliderControlOptions<int>(min_, max_));
+ mock_defaults_.reset(new DefaultOptionDelegateMock<int>());
+ dut_.reset(new SliderControlOptions<int>(min_, max_, mock_defaults_));
}
std::unique_ptr<SliderControlOptions<int>> dut_;
+ std::shared_ptr<DefaultOptionDelegateMock<int>> mock_defaults_;
const int min_ = 1;
const int max_ = 10;
};
@@ -52,19 +60,66 @@
EXPECT_FALSE(dut_->IsSupported(max_ + 1));
}
-TEST_F(SliderControlOptionsTest, DefaultValue) {
- // All default values should be supported.
- // For some reason, the templates have values in the range [1, COUNT).
- for (int i = 1; i < CAMERA3_TEMPLATE_COUNT; ++i) {
- int value = -1;
- EXPECT_EQ(dut_->DefaultValueForTemplate(i, &value), 0);
- EXPECT_TRUE(dut_->IsSupported(value));
- }
+TEST_F(SliderControlOptionsTest, DelegateDefaultValue) {
+ int template_index = 3;
+ int expected = max_ - 1;
+ ASSERT_TRUE(dut_->IsSupported(expected));
+ EXPECT_CALL(*mock_defaults_, DefaultValueForTemplate(template_index, _))
+ .WillOnce(DoAll(SetArgPointee<1>(expected), Return(true)));
+ int actual = expected - 1;
+ EXPECT_EQ(dut_->DefaultValueForTemplate(template_index, &actual), 0);
+ EXPECT_EQ(actual, expected);
+}
+
+TEST_F(SliderControlOptionsTest, LowDelegateDefaultValue) {
+ int template_index = 3;
+ // min - 1 is below the valid range.
+ int default_val = min_ - 1;
+ // Should get bumped up into range.
+ int expected = min_;
+ ASSERT_FALSE(dut_->IsSupported(default_val));
+ ASSERT_TRUE(dut_->IsSupported(expected));
+
+ EXPECT_CALL(*mock_defaults_, DefaultValueForTemplate(template_index, _))
+ .WillOnce(DoAll(SetArgPointee<1>(default_val), Return(true)));
+ int actual = default_val;
+ EXPECT_EQ(dut_->DefaultValueForTemplate(template_index, &actual), 0);
+ EXPECT_EQ(actual, expected);
+}
+
+TEST_F(SliderControlOptionsTest, HighDelegateDefaultValue) {
+ int template_index = 3;
+ // max + 1 is above the valid range.
+ int default_val = max_ + 1;
+ // Should get bumped down into range.
+ int expected = max_;
+ ASSERT_FALSE(dut_->IsSupported(default_val));
+ ASSERT_TRUE(dut_->IsSupported(expected));
+
+ EXPECT_CALL(*mock_defaults_, DefaultValueForTemplate(template_index, _))
+ .WillOnce(DoAll(SetArgPointee<1>(default_val), Return(true)));
+ int actual = default_val;
+ EXPECT_EQ(dut_->DefaultValueForTemplate(template_index, &actual), 0);
+ EXPECT_EQ(actual, expected);
+}
+
+TEST_F(SliderControlOptionsTest, NoDelegateDefaultValue) {
+ int template_index = 3;
+ int actual = min_ - 1;
+ ASSERT_FALSE(dut_->IsSupported(actual));
+
+ // Have delegate error.
+ EXPECT_CALL(*mock_defaults_, DefaultValueForTemplate(template_index, _))
+ .WillOnce(Return(false));
+
+ // Should still give *some* supported value.
+ EXPECT_EQ(dut_->DefaultValueForTemplate(template_index, &actual), 0);
+ EXPECT_TRUE(dut_->IsSupported(actual));
}
TEST_F(SliderControlOptionsTest, NoDefaultValue) {
// Invalid options don't have a valid default.
- SliderControlOptions<int> bad_options(10, 9); // min > max.
+ SliderControlOptions<int> bad_options(10, 9, mock_defaults_); // min > max.
for (int i = 1; i < CAMERA3_TEMPLATE_COUNT; ++i) {
int value = -1;
EXPECT_EQ(bad_options.DefaultValueForTemplate(i, &value), -ENODEV);
diff --git a/modules/camera/3_4/metadata/tagged_control_options.h b/modules/camera/3_4/metadata/tagged_control_options.h
index 9204fea..3d900ae 100644
--- a/modules/camera/3_4/metadata/tagged_control_options.h
+++ b/modules/camera/3_4/metadata/tagged_control_options.h
@@ -23,6 +23,13 @@
namespace v4l2_camera_hal {
+// A constant tag with a value not used as a real tag
+// (since all real tags are unsigned), to indicate options
+// that should not be reported.
+// Any class working with TaggedControlOptions should check
+// the tag against this value before using it.
+static int32_t DO_NOT_REPORT_OPTIONS = -1;
+
// A TaggedControlOptions wraps a ControlOptions and adds a tag.
template <typename T>
class TaggedControlOptions : public ControlOptionsInterface<T> {
diff --git a/modules/camera/3_4/v4l2_metadata_factory.cpp b/modules/camera/3_4/v4l2_metadata_factory.cpp
index b9c64be..dc43377 100644
--- a/modules/camera/3_4/v4l2_metadata_factory.cpp
+++ b/modules/camera/3_4/v4l2_metadata_factory.cpp
@@ -58,7 +58,10 @@
ANDROID_COLOR_CORRECTION_ABERRATION_MODE,
ANDROID_COLOR_CORRECTION_AVAILABLE_ABERRATION_MODES,
{ANDROID_COLOR_CORRECTION_ABERRATION_MODE_FAST,
- ANDROID_COLOR_CORRECTION_ABERRATION_MODE_HIGH_QUALITY}));
+ ANDROID_COLOR_CORRECTION_ABERRATION_MODE_HIGH_QUALITY},
+ {{CAMERA3_TEMPLATE_STILL_CAPTURE,
+ ANDROID_COLOR_CORRECTION_ABERRATION_MODE_HIGH_QUALITY},
+ {OTHER_TEMPLATES, ANDROID_COLOR_CORRECTION_ABERRATION_MODE_FAST}}));
// TODO(b/30510395): subcomponents of 3A.
// In general, default to ON/AUTO since they imply pretty much nothing,
@@ -76,11 +79,12 @@
V4L2_CID_AUTO_EXPOSURE_BIAS,
// No scaling necessary, AE_COMPENSATION_STEP handles this.
std::make_shared<ScalingConverter<int32_t, int32_t>>(1, 1),
- 0));
+ 0,
+ {{OTHER_TEMPLATES, 0}}));
components.insert(std::unique_ptr<PartialMetadataInterface>(
new Property<camera_metadata_rational_t>(
ANDROID_CONTROL_AE_COMPENSATION_STEP, kAeCompensationUnit)));
- // TODO(b/31021522): Autofocus subcomponent, AFTrigger.
+ // TODO(b/31021522): Autofocus subcomponent.
components.insert(
NoEffectMenuControl<uint8_t>(ANDROID_CONTROL_AF_MODE,
ANDROID_CONTROL_AF_AVAILABLE_MODES,
@@ -91,7 +95,23 @@
// the docs (system/media/camera/docs/docs.html).
components.insert(FixedState<uint8_t>(ANDROID_CONTROL_AF_STATE,
ANDROID_CONTROL_AF_STATE_INACTIVE));
- // TODO(b/31022735): AE & AF triggers.
+ // TODO(b/31022735): Correctly implement AE & AF triggers that
+ // actually do something. These no effect triggers are even worse than most
+ // of the useless controls in this class, since technically they should
+ // revert back to IDLE eventually after START/CANCEL, but for now they won't
+ // unless IDLE is requested.
+ components.insert(
+ NoEffectMenuControl<uint8_t>(ANDROID_CONTROL_AF_TRIGGER,
+ DO_NOT_REPORT_OPTIONS,
+ {ANDROID_CONTROL_AF_TRIGGER_IDLE,
+ ANDROID_CONTROL_AF_TRIGGER_START,
+ ANDROID_CONTROL_AF_TRIGGER_CANCEL}));
+ components.insert(NoEffectMenuControl<uint8_t>(
+ ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER,
+ DO_NOT_REPORT_OPTIONS,
+ {ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER_IDLE,
+ ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER_START,
+ ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER_CANCEL}));
components.insert(V4L2ControlOrDefault<uint8_t>(
ControlType::kMenu,
ANDROID_CONTROL_AE_MODE,
@@ -101,7 +121,9 @@
std::shared_ptr<ConverterInterface<uint8_t, int32_t>>(new EnumConverter(
{{V4L2_EXPOSURE_AUTO, ANDROID_CONTROL_AE_MODE_ON},
{V4L2_EXPOSURE_MANUAL, ANDROID_CONTROL_AE_MODE_OFF}})),
- ANDROID_CONTROL_AE_MODE_ON));
+ ANDROID_CONTROL_AE_MODE_ON,
+ {{CAMERA3_TEMPLATE_MANUAL, ANDROID_CONTROL_AE_MODE_OFF},
+ {OTHER_TEMPLATES, ANDROID_CONTROL_AE_MODE_ON}}));
components.insert(V4L2ControlOrDefault<uint8_t>(
ControlType::kMenu,
ANDROID_CONTROL_AE_ANTIBANDING_MODE,
@@ -117,7 +139,9 @@
ANDROID_CONTROL_AE_ANTIBANDING_MODE_60HZ},
{V4L2_CID_POWER_LINE_FREQUENCY_AUTO,
ANDROID_CONTROL_AE_ANTIBANDING_MODE_AUTO}})),
- ANDROID_CONTROL_AE_ANTIBANDING_MODE_AUTO));
+ ANDROID_CONTROL_AE_ANTIBANDING_MODE_AUTO,
+ {{CAMERA3_TEMPLATE_MANUAL, ANDROID_CONTROL_AE_ANTIBANDING_MODE_OFF},
+ {OTHER_TEMPLATES, ANDROID_CONTROL_AE_ANTIBANDING_MODE_AUTO}}));
std::unique_ptr<PartialMetadataInterface> exposure_time =
V4L2Control<int64_t>(ControlType::kSlider,
ANDROID_SENSOR_EXPOSURE_TIME,
@@ -171,7 +195,9 @@
{V4L2_WHITE_BALANCE_DAYLIGHT, ANDROID_CONTROL_AWB_MODE_DAYLIGHT},
{V4L2_WHITE_BALANCE_CLOUDY,
ANDROID_CONTROL_AWB_MODE_CLOUDY_DAYLIGHT},
- {V4L2_WHITE_BALANCE_SHADE, ANDROID_CONTROL_AWB_MODE_SHADE}}))));
+ {V4L2_WHITE_BALANCE_SHADE, ANDROID_CONTROL_AWB_MODE_SHADE}})),
+ {{CAMERA3_TEMPLATE_MANUAL, ANDROID_CONTROL_AWB_MODE_OFF},
+ {OTHER_TEMPLATES, ANDROID_CONTROL_AWB_MODE_AUTO}}));
if (awb) {
components.insert(std::move(awb));
} else {
@@ -185,7 +211,9 @@
std::shared_ptr<ConverterInterface<uint8_t, int32_t>>(
new EnumConverter({{0, ANDROID_CONTROL_AWB_MODE_OFF},
{1, ANDROID_CONTROL_AWB_MODE_AUTO}})),
- ANDROID_CONTROL_AWB_MODE_AUTO));
+ ANDROID_CONTROL_AWB_MODE_AUTO,
+ {{CAMERA3_TEMPLATE_MANUAL, ANDROID_CONTROL_AWB_MODE_OFF},
+ {OTHER_TEMPLATES, ANDROID_CONTROL_AWB_MODE_AUTO}}));
}
// TODO(b/31041577): Handle AWB state machine correctly.
components.insert(FixedState<uint8_t>(ANDROID_CONTROL_AWB_STATE,
@@ -249,19 +277,23 @@
// Not sure if V4L2 does or doesn't do this, but HAL documentation says
// all devices must support FAST, and FAST can be equivalent to OFF, so
- // either way it's fine to list.
- components.insert(
- NoEffectMenuControl<uint8_t>(ANDROID_EDGE_MODE,
- ANDROID_EDGE_AVAILABLE_EDGE_MODES,
- {ANDROID_EDGE_MODE_FAST}));
+ // either way it's fine to list. And if FAST is included, HIGH_QUALITY
+ // is supposed to be included as well.
+ components.insert(NoEffectMenuControl<uint8_t>(
+ ANDROID_EDGE_MODE,
+ ANDROID_EDGE_AVAILABLE_EDGE_MODES,
+ {ANDROID_EDGE_MODE_FAST, ANDROID_EDGE_MODE_HIGH_QUALITY},
+ {{CAMERA3_TEMPLATE_STILL_CAPTURE, ANDROID_EDGE_MODE_HIGH_QUALITY},
+ {OTHER_TEMPLATES, ANDROID_EDGE_MODE_FAST}}));
// TODO(b/31023454): subcomponents of flash.
- // Missing android.flash.mode control, since it uses a different enum.
components.insert(
std::unique_ptr<PartialMetadataInterface>(new Property<uint8_t>(
ANDROID_FLASH_INFO_AVAILABLE, ANDROID_FLASH_INFO_AVAILABLE_FALSE)));
components.insert(FixedState<uint8_t>(ANDROID_FLASH_STATE,
ANDROID_FLASH_STATE_UNAVAILABLE));
+ components.insert(NoEffectMenuControl<uint8_t>(
+ ANDROID_FLASH_MODE, DO_NOT_REPORT_OPTIONS, {ANDROID_FLASH_MODE_OFF}));
// TODO(30510395): subcomponents of hotpixel.
// No known V4L2 hot pixel correction. But it might be happening,
@@ -344,16 +376,39 @@
{ANDROID_LENS_OPTICAL_STABILIZATION_MODE_OFF}));
// TODO(b/31017806): This should definitely have a different default depending
// on template.
- components.insert(NoEffectOptionlessControl<uint8_t>(
+ components.insert(NoEffectMenuControl<uint8_t>(
ANDROID_CONTROL_CAPTURE_INTENT,
- ANDROID_CONTROL_CAPTURE_INTENT_STILL_CAPTURE));
+ DO_NOT_REPORT_OPTIONS,
+ {ANDROID_CONTROL_CAPTURE_INTENT_CUSTOM,
+ ANDROID_CONTROL_CAPTURE_INTENT_PREVIEW,
+ ANDROID_CONTROL_CAPTURE_INTENT_STILL_CAPTURE,
+ ANDROID_CONTROL_CAPTURE_INTENT_VIDEO_RECORD,
+ ANDROID_CONTROL_CAPTURE_INTENT_VIDEO_SNAPSHOT,
+ ANDROID_CONTROL_CAPTURE_INTENT_ZERO_SHUTTER_LAG,
+ ANDROID_CONTROL_CAPTURE_INTENT_MANUAL},
+ {{CAMERA3_TEMPLATE_PREVIEW, ANDROID_CONTROL_CAPTURE_INTENT_PREVIEW},
+ {CAMERA3_TEMPLATE_STILL_CAPTURE,
+ ANDROID_CONTROL_CAPTURE_INTENT_STILL_CAPTURE},
+ {CAMERA3_TEMPLATE_VIDEO_RECORD,
+ ANDROID_CONTROL_CAPTURE_INTENT_VIDEO_RECORD},
+ {CAMERA3_TEMPLATE_VIDEO_SNAPSHOT,
+ ANDROID_CONTROL_CAPTURE_INTENT_VIDEO_SNAPSHOT},
+ {CAMERA3_TEMPLATE_ZERO_SHUTTER_LAG,
+ ANDROID_CONTROL_CAPTURE_INTENT_ZERO_SHUTTER_LAG},
+ {CAMERA3_TEMPLATE_MANUAL, ANDROID_CONTROL_CAPTURE_INTENT_MANUAL},
+ {OTHER_TEMPLATES, ANDROID_CONTROL_CAPTURE_INTENT_CUSTOM}}));
// Unable to control noise reduction in V4L2 devices,
- // but FAST is allowed to be the same as OFF.
+ // but FAST is allowed to be the same as OFF,
+ // and HIGH_QUALITY can be the same as FAST.
components.insert(NoEffectMenuControl<uint8_t>(
ANDROID_NOISE_REDUCTION_MODE,
ANDROID_NOISE_REDUCTION_AVAILABLE_NOISE_REDUCTION_MODES,
- {ANDROID_NOISE_REDUCTION_MODE_FAST}));
+ {ANDROID_NOISE_REDUCTION_MODE_FAST,
+ ANDROID_NOISE_REDUCTION_MODE_HIGH_QUALITY},
+ {{CAMERA3_TEMPLATE_STILL_CAPTURE,
+ ANDROID_NOISE_REDUCTION_MODE_HIGH_QUALITY},
+ {OTHER_TEMPLATES, ANDROID_NOISE_REDUCTION_MODE_FAST}}));
// TODO(30510395): subcomponents of formats/streams.
// For now, no thumbnails available (only [0,0], the "no thumbnail" size).