/* * 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 "array_vector.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 int32_t max_inputs_tag_ = ANDROID_REQUEST_MAX_NUM_INPUT_STREAMS; const int32_t max_outputs_tag_ = ANDROID_REQUEST_MAX_NUM_OUTPUT_STREAMS; const int32_t configs_tag_ = ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS; const int32_t stalls_tag_ = ANDROID_SCALER_AVAILABLE_STALL_DURATIONS; const int32_t reprocess_formats_tag_ = ANDROID_SCALER_AVAILABLE_INPUT_OUTPUT_FORMATS_MAP; const std::vector<int32_t> valid_orientations_ = {0, 90, 180, 270}; // TODO(b/31384253): check for required configs/reprocess formats. }; 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); } TEST_F(MetadataReaderTest, MaxInputs) { int32_t expected = 12; ASSERT_EQ(v4l2_camera_hal::UpdateMetadata( metadata_.get(), max_inputs_tag_, expected), 0); FillDUT(); int32_t actual = expected + 1; ASSERT_EQ(dut_->MaxInputStreams(&actual), 0); EXPECT_EQ(actual, expected); } TEST_F(MetadataReaderTest, EmptyMaxInputs) { FillDUT(); // Max inputs is an optional key; if not present the default is 0. int32_t expected = 0; int32_t actual = expected + 1; ASSERT_EQ(dut_->MaxInputStreams(&actual), 0); EXPECT_EQ(actual, expected); } TEST_F(MetadataReaderTest, MaxOutputs) { std::array<int32_t, 3> expected = {{12, 34, 56}}; ASSERT_EQ(v4l2_camera_hal::UpdateMetadata( metadata_.get(), max_outputs_tag_, expected), 0); FillDUT(); std::array<int32_t, 3> actual; ASSERT_EQ(dut_->MaxOutputStreams(&actual[0], &actual[1], &actual[2]), 0); EXPECT_EQ(actual, expected); } TEST_F(MetadataReaderTest, InvalidMaxOutputs) { // Must be a 3-tuple to be valid. std::array<int32_t, 4> invalid = {{12, 34, 56, 78}}; ASSERT_EQ(v4l2_camera_hal::UpdateMetadata( metadata_.get(), max_outputs_tag_, invalid), 0); FillDUT(); int32_t actual; // Don't mind the aliasing since we don't care about the value. ASSERT_EQ(dut_->MaxOutputStreams(&actual, &actual, &actual), -EINVAL); } TEST_F(MetadataReaderTest, EmptyMaxOutputs) { FillDUT(); int32_t actual; // Don't mind the aliasing since we don't care about the value. ASSERT_EQ(dut_->MaxOutputStreams(&actual, &actual, &actual), -ENOENT); } TEST_F(MetadataReaderTest, StreamConfigurations) { v4l2_camera_hal::ArrayVector<int32_t, 4> configs; std::array<int32_t, 4> config1{ {1, 2, 3, ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT}}; std::array<int32_t, 4> config2{ {5, 6, 7, ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_INPUT}}; configs.push_back(config1); configs.push_back(config2); ASSERT_EQ( v4l2_camera_hal::UpdateMetadata(metadata_.get(), configs_tag_, configs), 0); FillDUT(); std::vector<StreamConfiguration> actual; ASSERT_EQ(dut_->StreamConfigurations(&actual), 0); ASSERT_EQ(actual.size(), configs.num_arrays()); EXPECT_EQ(actual[0].spec.format, config1[0]); EXPECT_EQ(actual[0].spec.width, config1[1]); EXPECT_EQ(actual[0].spec.height, config1[2]); EXPECT_EQ(actual[0].direction, config1[3]); EXPECT_EQ(actual[1].spec.format, config2[0]); EXPECT_EQ(actual[1].spec.width, config2[1]); EXPECT_EQ(actual[1].spec.height, config2[2]); EXPECT_EQ(actual[1].direction, config2[3]); } TEST_F(MetadataReaderTest, InvalidStreamConfigurationDirection) { // -1 is not a valid direction. std::array<int32_t, 4> config{{1, 2, 3, -1}}; ASSERT_EQ( v4l2_camera_hal::UpdateMetadata(metadata_.get(), configs_tag_, config), 0); FillDUT(); std::vector<StreamConfiguration> actual; ASSERT_EQ(dut_->StreamConfigurations(&actual), -EINVAL); } TEST_F(MetadataReaderTest, InvalidStreamConfigurationSize) { // Both size dimensions must be > 0. std::array<int32_t, 4> config{ {1, 2, 0, ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_INPUT}}; ASSERT_EQ( v4l2_camera_hal::UpdateMetadata(metadata_.get(), configs_tag_, config), 0); FillDUT(); std::vector<StreamConfiguration> actual; ASSERT_EQ(dut_->StreamConfigurations(&actual), -EINVAL); } TEST_F(MetadataReaderTest, InvalidStreamConfigurationNumElements) { // Should be a multiple of 4. std::array<int32_t, 5> config{ {1, 2, 3, ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_INPUT, 5}}; ASSERT_EQ( v4l2_camera_hal::UpdateMetadata(metadata_.get(), configs_tag_, config), 0); FillDUT(); std::vector<StreamConfiguration> actual; ASSERT_EQ(dut_->StreamConfigurations(&actual), -EINVAL); } // TODO(b/31384253): Test that failure occurs if // required configurations are not present. TEST_F(MetadataReaderTest, NoStreamConfigurations) { FillDUT(); std::vector<StreamConfiguration> actual; ASSERT_EQ(dut_->StreamConfigurations(&actual), -ENOENT); } TEST_F(MetadataReaderTest, StreamStallDurations) { v4l2_camera_hal::ArrayVector<int64_t, 4> stalls; std::array<int64_t, 4> stall1{{1, 2, 3, 4}}; std::array<int64_t, 4> stall2{{5, 6, 7, 8}}; stalls.push_back(stall1); stalls.push_back(stall2); ASSERT_EQ( v4l2_camera_hal::UpdateMetadata(metadata_.get(), stalls_tag_, stalls), 0); FillDUT(); std::vector<StreamStallDuration> actual; ASSERT_EQ(dut_->StreamStallDurations(&actual), 0); ASSERT_EQ(actual.size(), stalls.num_arrays()); EXPECT_EQ(actual[0].spec.format, stall1[0]); EXPECT_EQ(actual[0].spec.width, stall1[1]); EXPECT_EQ(actual[0].spec.height, stall1[2]); EXPECT_EQ(actual[0].duration, stall1[3]); EXPECT_EQ(actual[1].spec.format, stall2[0]); EXPECT_EQ(actual[1].spec.width, stall2[1]); EXPECT_EQ(actual[1].spec.height, stall2[2]); EXPECT_EQ(actual[1].duration, stall2[3]); } TEST_F(MetadataReaderTest, InvalidStreamStallDurationDuration) { // -1 is not a valid duration. std::array<int64_t, 4> stall{{1, 2, 3, -1}}; ASSERT_EQ( v4l2_camera_hal::UpdateMetadata(metadata_.get(), stalls_tag_, stall), 0); FillDUT(); std::vector<StreamStallDuration> actual; ASSERT_EQ(dut_->StreamStallDurations(&actual), -EINVAL); } TEST_F(MetadataReaderTest, InvalidStreamStallDurationSize) { // Both size dimensions must be > 0. std::array<int64_t, 4> stall{{1, 2, 0, 3}}; ASSERT_EQ( v4l2_camera_hal::UpdateMetadata(metadata_.get(), stalls_tag_, stall), 0); FillDUT(); std::vector<StreamStallDuration> actual; ASSERT_EQ(dut_->StreamStallDurations(&actual), -EINVAL); } TEST_F(MetadataReaderTest, InvalidStreamStallDurationNumElements) { // Should be a multiple of 4. std::array<int64_t, 5> stall{{1, 2, 3, 4, 5}}; ASSERT_EQ( v4l2_camera_hal::UpdateMetadata(metadata_.get(), stalls_tag_, stall), 0); FillDUT(); std::vector<StreamStallDuration> actual; ASSERT_EQ(dut_->StreamStallDurations(&actual), -EINVAL); } // TODO(b/31384253): Test that failure occurs if // YUV_420_888, RAW10, RAW12, RAW_OPAQUE, or IMPLEMENTATION_DEFINED // formats have stall durations > 0. TEST_F(MetadataReaderTest, NoStreamStallDurations) { FillDUT(); std::vector<StreamStallDuration> actual; ASSERT_EQ(dut_->StreamStallDurations(&actual), -ENOENT); } TEST_F(MetadataReaderTest, ReprocessFormats) { ReprocessFormatMap expected{{1, {4}}, {2, {5, 6}}, {3, {7, 8, 9}}}; std::vector<int32_t> raw; for (const auto& input_outputs : expected) { raw.push_back(input_outputs.first); raw.push_back(input_outputs.second.size()); raw.insert( raw.end(), input_outputs.second.begin(), input_outputs.second.end()); } ASSERT_EQ(v4l2_camera_hal::UpdateMetadata( metadata_.get(), reprocess_formats_tag_, raw), 0); FillDUT(); ReprocessFormatMap actual; ASSERT_EQ(dut_->ReprocessFormats(&actual), 0); EXPECT_EQ(actual, expected); } TEST_F(MetadataReaderTest, ReprocessFormatsNoOutputs) { // 0 indicates that there are 0 output formats for input format 1, // which is not ok. std::vector<int32_t> raw{1, 0}; ASSERT_EQ(v4l2_camera_hal::UpdateMetadata( metadata_.get(), reprocess_formats_tag_, raw), 0); FillDUT(); ReprocessFormatMap actual; ASSERT_EQ(dut_->ReprocessFormats(&actual), -EINVAL); } TEST_F(MetadataReaderTest, ReprocessFormatsPastEnd) { // 3 indicates that there are 3 output formats for input format 1, // which is not ok since there are only 2 here. std::vector<int32_t> raw{1, 3, 0, 0}; ASSERT_EQ(v4l2_camera_hal::UpdateMetadata( metadata_.get(), reprocess_formats_tag_, raw), 0); FillDUT(); ReprocessFormatMap actual; ASSERT_EQ(dut_->ReprocessFormats(&actual), -EINVAL); } TEST_F(MetadataReaderTest, EmptyReprocessFormats) { FillDUT(); ReprocessFormatMap actual; ASSERT_EQ(dut_->ReprocessFormats(&actual), -ENOENT); } } // namespace default_camera_hal