Add StaticProperties and MetadataReader
MetadataReader provides a clean wrapper around getting
and translating certain metadata values in a nice form.
StaticProperties will be used by Camera as the source of
truth for metadata properties, extracted directly from a reader,
rather than calling down into the device again.
BUG: 31044638
TEST: unit tests pass
Change-Id: I712a80f87e629a7288c678637de0eae0225acf96
diff --git a/modules/camera/3_4/Android.mk b/modules/camera/3_4/Android.mk
index bf888be..12e8436 100644
--- a/modules/camera/3_4/Android.mk
+++ b/modules/camera/3_4/Android.mk
@@ -42,6 +42,8 @@
format_metadata_factory.cpp \
metadata/enum_converter.cpp \
metadata/metadata.cpp \
+ metadata/metadata_reader.cpp \
+ static_properties.cpp \
stream.cpp \
stream_format.cpp \
v4l2_camera.cpp \
@@ -57,6 +59,7 @@
metadata/ignored_control_delegate_test.cpp \
metadata/map_converter_test.cpp \
metadata/menu_control_options_test.cpp \
+ metadata/metadata_reader_test.cpp \
metadata/metadata_test.cpp \
metadata/no_effect_control_delegate_test.cpp \
metadata/partial_metadata_factory_test.cpp \
@@ -67,6 +70,7 @@
metadata/tagged_control_delegate_test.cpp \
metadata/tagged_control_options_test.cpp \
metadata/v4l2_control_delegate_test.cpp \
+ static_properties_test.cpp \
# V4L2 Camera HAL.
# ==============================================================================
diff --git a/modules/camera/3_4/metadata/metadata_reader.cpp b/modules/camera/3_4/metadata/metadata_reader.cpp
new file mode 100644
index 0000000..c570048
--- /dev/null
+++ b/modules/camera/3_4/metadata/metadata_reader.cpp
@@ -0,0 +1,86 @@
+/*
+ * 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 "metadata_reader.h"
+
+// #define LOG_NDEBUG 0
+#define LOG_TAG "MetadataReader"
+#include <cutils/log.h>
+#include <system/camera.h>
+
+#include "metadata_common.h"
+
+namespace default_camera_hal {
+
+MetadataReader::MetadataReader(
+ std::unique_ptr<const android::CameraMetadata> metadata)
+ : metadata_(std::move(metadata)) {}
+
+MetadataReader::~MetadataReader() {}
+
+int MetadataReader::Facing(int* facing) const {
+ uint8_t metadata_facing = 0;
+ int res = v4l2_camera_hal::SingleTagValue(
+ *metadata_, ANDROID_LENS_FACING, &metadata_facing);
+ if (res) {
+ ALOGE("%s: Failed to get facing from static metadata.", __func__);
+ return res;
+ }
+
+ switch (metadata_facing) {
+ case (ANDROID_LENS_FACING_FRONT):
+ *facing = CAMERA_FACING_FRONT;
+ break;
+ case (ANDROID_LENS_FACING_BACK):
+ *facing = CAMERA_FACING_BACK;
+ break;
+ case (ANDROID_LENS_FACING_EXTERNAL):
+ *facing = CAMERA_FACING_EXTERNAL;
+ break;
+ default:
+ ALOGE("%s: Invalid facing from static metadata: %d.",
+ __func__,
+ metadata_facing);
+ return -EINVAL;
+ }
+ return 0;
+}
+
+int MetadataReader::Orientation(int* orientation) const {
+ int32_t metadata_orientation = 0;
+ int res = v4l2_camera_hal::SingleTagValue(
+ *metadata_, ANDROID_SENSOR_ORIENTATION, &metadata_orientation);
+ if (res) {
+ ALOGE("%s: Failed to get orientation from static metadata.", __func__);
+ return res;
+ }
+
+ // Orientation must be 0, 90, 180, or 270.
+ if (metadata_orientation < 0 || metadata_orientation > 270 ||
+ metadata_orientation % 90 != 0) {
+ ALOGE(
+ "%s: Invalid orientation %d "
+ "(must be a 90-degree increment in [0, 360)).",
+ __func__,
+ metadata_orientation);
+ return -EINVAL;
+ }
+
+ *orientation = static_cast<int>(metadata_orientation);
+ return 0;
+}
+
+} // namespace default_camera_hal
diff --git a/modules/camera/3_4/metadata/metadata_reader.h b/modules/camera/3_4/metadata/metadata_reader.h
new file mode 100644
index 0000000..64bedd6
--- /dev/null
+++ b/modules/camera/3_4/metadata/metadata_reader.h
@@ -0,0 +1,63 @@
+/*
+ * 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 DEFAULT_CAMERA_HAL_METADATA_METADATA_READER_H_
+#define DEFAULT_CAMERA_HAL_METADATA_METADATA_READER_H_
+
+#include <memory>
+
+#include <camera/CameraMetadata.h>
+
+#include "../common.h"
+
+namespace default_camera_hal {
+
+// A MetadataReader reads and converts/validates various metadata entries.
+class MetadataReader {
+ public:
+ MetadataReader(std::unique_ptr<const android::CameraMetadata> metadata);
+ virtual ~MetadataReader();
+
+ // Get a pointer to the underlying metadata being read.
+ // The pointer is valid only as long as this object is alive.
+ // The "locking" here only causes non-const methods to fail,
+ // which is not a problem since the CameraMetadata being locked
+ // is already const. This could be a problem if the metadata was
+ // shared more widely, but |metadata_| is a unique_ptr,
+ // guaranteeing the safety of this. Destructing automatically "unlocks".
+ virtual const camera_metadata_t* raw_metadata() const {
+ return metadata_->getAndLock();
+ }
+
+ // All accessor methods must be given a valid pointer. They will return:
+ // 0: Success.
+ // -ENOENT: The necessary entry is missing.
+ // -EINVAL: The entry value is invalid.
+ // -ENODEV: Some other error occured.
+
+ // The |facing| returned will be one of the enum values from system/camera.h.
+ virtual int Facing(int* facing) const;
+ virtual int Orientation(int* orientation) const;
+
+ private:
+ std::unique_ptr<const android::CameraMetadata> metadata_;
+
+ DISALLOW_COPY_AND_ASSIGN(MetadataReader);
+};
+
+} // namespace default_camera_hal
+
+#endif // DEFAULT_CAMERA_HAL_METADATA_METADATA_READER_H_
diff --git a/modules/camera/3_4/metadata/metadata_reader_mock.h b/modules/camera/3_4/metadata/metadata_reader_mock.h
new file mode 100644
index 0000000..096cefe
--- /dev/null
+++ b/modules/camera/3_4/metadata/metadata_reader_mock.h
@@ -0,0 +1,38 @@
+/*
+ * 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 metadata readers.
+
+#ifndef DEFAULT_CAMERA_HAL_METADATA_METADATA_READER_MOCK_H_
+#define DEFAULT_CAMERA_HAL_METADATA_METADATA_READER_MOCK_H_
+
+#include <gmock/gmock.h>
+
+#include "metadata_reader.h"
+
+namespace default_camera_hal {
+
+class MetadataReaderMock : public MetadataReader {
+ public:
+ MetadataReaderMock() : MetadataReader(nullptr){};
+ MOCK_CONST_METHOD0(raw_metadata, const camera_metadata_t*());
+ MOCK_CONST_METHOD1(Facing, int(int*));
+ MOCK_CONST_METHOD1(Orientation, int(int*));
+};
+
+} // namespace default_camera_hal
+
+#endif // DEFAULT_CAMERA_HAL_METADATA_METADATA_READER_MOCK_H_
diff --git a/modules/camera/3_4/metadata/metadata_reader_test.cpp b/modules/camera/3_4/metadata/metadata_reader_test.cpp
new file mode 100644
index 0000000..cdbb3f9
--- /dev/null
+++ b/modules/camera/3_4/metadata/metadata_reader_test.cpp
@@ -0,0 +1,133 @@
+/*
+ * 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 "metadata_reader.h"
+
+#include <camera/CameraMetadata.h>
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+#include <system/camera.h>
+
+#include "metadata_common.h"
+
+using testing::AtMost;
+using testing::Expectation;
+using testing::Return;
+using testing::Test;
+
+namespace default_camera_hal {
+
+class MetadataReaderTest : public Test {
+ protected:
+ void SetUp() {
+ ResetMetadata();
+ // FillDUT should be called before using the device under test.
+ dut_.reset();
+ }
+
+ void ResetMetadata() {
+ metadata_ = std::make_unique<android::CameraMetadata>();
+ }
+
+ void FillDUT() {
+ dut_ = std::make_unique<MetadataReader>(std::move(metadata_));
+ ResetMetadata();
+ }
+
+ std::unique_ptr<MetadataReader> dut_;
+ std::unique_ptr<android::CameraMetadata> metadata_;
+
+ const int32_t facing_tag_ = ANDROID_LENS_FACING;
+ const int32_t orientation_tag_ = ANDROID_SENSOR_ORIENTATION;
+ const std::vector<int32_t> valid_orientations_ = {0, 90, 180, 270};
+};
+
+TEST_F(MetadataReaderTest, FacingTranslations) {
+ // Check that the enums are converting properly.
+ std::map<uint8_t, int> translations{
+ {ANDROID_LENS_FACING_FRONT, CAMERA_FACING_FRONT},
+ {ANDROID_LENS_FACING_BACK, CAMERA_FACING_BACK},
+ {ANDROID_LENS_FACING_EXTERNAL, CAMERA_FACING_EXTERNAL}};
+ for (const auto& translation : translations) {
+ ASSERT_EQ(v4l2_camera_hal::UpdateMetadata(
+ metadata_.get(), facing_tag_, translation.first),
+ 0);
+ FillDUT();
+
+ int expected = translation.second;
+ int actual = expected + 1;
+ EXPECT_EQ(dut_->Facing(&actual), 0);
+ EXPECT_EQ(actual, expected);
+ }
+}
+
+TEST_F(MetadataReaderTest, InvalidFacing) {
+ uint8_t invalid = 99;
+ ASSERT_EQ(
+ v4l2_camera_hal::UpdateMetadata(metadata_.get(), facing_tag_, invalid),
+ 0);
+ FillDUT();
+ int actual = 0;
+ EXPECT_EQ(dut_->Facing(&actual), -EINVAL);
+}
+
+TEST_F(MetadataReaderTest, EmptyFacing) {
+ FillDUT();
+ int actual = 0;
+ EXPECT_EQ(dut_->Facing(&actual), -ENOENT);
+}
+
+TEST_F(MetadataReaderTest, ValidOrientations) {
+ for (int32_t orientation : valid_orientations_) {
+ ASSERT_EQ(v4l2_camera_hal::UpdateMetadata(
+ metadata_.get(), orientation_tag_, orientation),
+ 0);
+ FillDUT();
+
+ int actual = orientation + 1;
+ EXPECT_EQ(dut_->Orientation(&actual), 0);
+ EXPECT_EQ(actual, orientation);
+ }
+}
+
+TEST_F(MetadataReaderTest, InvalidOrientations) {
+ // High.
+ for (int32_t orientation : valid_orientations_) {
+ ASSERT_EQ(v4l2_camera_hal::UpdateMetadata(
+ metadata_.get(), orientation_tag_, orientation + 1),
+ 0);
+ FillDUT();
+ int actual = 0;
+ EXPECT_EQ(dut_->Orientation(&actual), -EINVAL);
+ }
+ // Low.
+ for (int32_t orientation : valid_orientations_) {
+ ASSERT_EQ(v4l2_camera_hal::UpdateMetadata(
+ metadata_.get(), orientation_tag_, orientation - 1),
+ 0);
+ FillDUT();
+ int actual = 0;
+ EXPECT_EQ(dut_->Orientation(&actual), -EINVAL);
+ }
+}
+
+TEST_F(MetadataReaderTest, EmptyOrientation) {
+ FillDUT();
+ int actual = 0;
+ EXPECT_EQ(dut_->Orientation(&actual), -ENOENT);
+}
+
+} // namespace default_camera_hal
diff --git a/modules/camera/3_4/metadata/partial_metadata_factory.h b/modules/camera/3_4/metadata/partial_metadata_factory.h
index 27ea6e8..13f3d61 100644
--- a/modules/camera/3_4/metadata/partial_metadata_factory.h
+++ b/modules/camera/3_4/metadata/partial_metadata_factory.h
@@ -223,9 +223,6 @@
HAL_LOGE("Error converting value %d for control %d.", i, control_id);
return nullptr;
}
- if (control_id == V4L2_CID_COLORFX) {
- HAL_LOGE("Adding color effect %d (%d)", i, metadata_val);
- }
options.push_back(metadata_val);
}
// Check to make sure there's at least one option.
diff --git a/modules/camera/3_4/static_properties.cpp b/modules/camera/3_4/static_properties.cpp
new file mode 100644
index 0000000..a55e9e0
--- /dev/null
+++ b/modules/camera/3_4/static_properties.cpp
@@ -0,0 +1,49 @@
+/*
+ * 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 "static_properties.h"
+
+// #define LOG_NDEBUG 0
+#define LOG_TAG "StaticProperties"
+#include <cutils/log.h>
+#include <system/camera.h>
+
+#include "metadata/metadata_reader.h"
+
+namespace default_camera_hal {
+
+StaticProperties* StaticProperties::NewStaticProperties(
+ std::unique_ptr<const MetadataReader> metadata_reader) {
+ int facing = 0;
+ int orientation = 0;
+ // If reading any data returns an error, something is wrong.
+ if (metadata_reader->Facing(&facing) ||
+ metadata_reader->Orientation(&orientation)) {
+ return nullptr;
+ }
+
+ return new StaticProperties(std::move(metadata_reader), facing, orientation);
+}
+
+StaticProperties::StaticProperties(
+ std::unique_ptr<const MetadataReader> metadata_reader,
+ int facing,
+ int orientation)
+ : metadata_reader_(std::move(metadata_reader)),
+ facing_(facing),
+ orientation_(orientation) {}
+
+} // namespace default_camera_hal
diff --git a/modules/camera/3_4/static_properties.h b/modules/camera/3_4/static_properties.h
new file mode 100644
index 0000000..77d5c92
--- /dev/null
+++ b/modules/camera/3_4/static_properties.h
@@ -0,0 +1,61 @@
+/*
+ * 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 DEFAULT_CAMERA_HAL_STATIC_PROPERTIES_H_
+#define DEFAULT_CAMERA_HAL_STATIC_PROPERTIES_H_
+
+#include <memory>
+
+#include "common.h"
+#include "metadata/metadata_reader.h"
+
+namespace default_camera_hal {
+
+// StaticProperties provides a wrapper around useful static metadata entries.
+class StaticProperties {
+ public:
+ // Use this method to create StaticProperties objects.
+ // Functionally equivalent to "new StaticProperties",
+ // except that it may return nullptr in case of failure (missing entries).
+ static StaticProperties* NewStaticProperties(
+ std::unique_ptr<const MetadataReader> metadata_reader);
+ virtual ~StaticProperties(){};
+
+ int facing() const { return facing_; };
+ int orientation() const { return orientation_; };
+ // Carrying on the promise of the underlying reader,
+ // the returned pointer is valid only as long as this object is alive.
+ const camera_metadata_t* raw_metadata() const {
+ return metadata_reader_->raw_metadata();
+ };
+
+ private:
+ // Constructor private to allow failing on bad input.
+ // Use NewStaticProperties instead.
+ StaticProperties(std::unique_ptr<const MetadataReader> metadata_reader,
+ int facing,
+ int orientation);
+
+ const std::unique_ptr<const MetadataReader> metadata_reader_;
+ const int facing_;
+ const int orientation_;
+
+ DISALLOW_COPY_AND_ASSIGN(StaticProperties);
+};
+
+} // namespace default_camera_hal
+
+#endif // DEFAULT_CAMERA_HAL_STATIC_PROPERTIES_H_
diff --git a/modules/camera/3_4/static_properties_test.cpp b/modules/camera/3_4/static_properties_test.cpp
new file mode 100644
index 0000000..7c05ad3
--- /dev/null
+++ b/modules/camera/3_4/static_properties_test.cpp
@@ -0,0 +1,86 @@
+/*
+ * 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 "static_properties.h"
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+#include <system/camera.h>
+
+#include "metadata/metadata_reader_mock.h"
+
+using testing::AtMost;
+using testing::Expectation;
+using testing::Return;
+using testing::SetArgPointee;
+using testing::Test;
+using testing::_;
+
+namespace default_camera_hal {
+
+class StaticPropertiesTest : public Test {
+ protected:
+ void SetUp() {
+ // Ensure tests will probably fail if PrepareDUT isn't called.
+ dut_.reset();
+ mock_reader_ = std::make_unique<MetadataReaderMock>();
+ }
+
+ void PrepareDUT() {
+ dut_.reset(StaticProperties::NewStaticProperties(std::move(mock_reader_)));
+ }
+
+ void SetDefaultExpectations() {
+ EXPECT_CALL(*mock_reader_, Facing(_))
+ .Times(AtMost(1))
+ .WillOnce(DoAll(SetArgPointee<0>(test_facing_), Return(0)));
+ EXPECT_CALL(*mock_reader_, Orientation(_))
+ .Times(AtMost(1))
+ .WillOnce(DoAll(SetArgPointee<0>(test_orientation_), Return(0)));
+ }
+
+ std::unique_ptr<StaticProperties> dut_;
+ std::unique_ptr<MetadataReaderMock> mock_reader_;
+
+ const int test_facing_ = CAMERA_FACING_FRONT;
+ const int test_orientation_ = 90;
+};
+
+TEST_F(StaticPropertiesTest, FactorySuccess) {
+ SetDefaultExpectations();
+ PrepareDUT();
+ ASSERT_NE(dut_, nullptr);
+ EXPECT_EQ(dut_->facing(), test_facing_);
+ EXPECT_EQ(dut_->orientation(), test_orientation_);
+}
+
+TEST_F(StaticPropertiesTest, FactoryFailedFacing) {
+ SetDefaultExpectations();
+ // Override with a failure expectation.
+ EXPECT_CALL(*mock_reader_, Facing(_)).WillOnce(Return(99));
+ PrepareDUT();
+ EXPECT_EQ(dut_, nullptr);
+}
+
+TEST_F(StaticPropertiesTest, FactoryFailedOrientation) {
+ SetDefaultExpectations();
+ // Override with a failure expectation.
+ EXPECT_CALL(*mock_reader_, Orientation(_)).WillOnce(Return(99));
+ PrepareDUT();
+ EXPECT_EQ(dut_, nullptr);
+}
+
+} // namespace default_camera_hal