1 /*
2 * Copyright (C) 2019 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #define LOG_TAG "ProcessBlockTest"
18 #include <log/log.h>
19
20 #include <gtest/gtest.h>
21 #include <memory>
22
23 #include "mock_device_session_hwl.h"
24 #include "mock_result_processor.h"
25 #include "multicam_realtime_process_block.h"
26 #include "realtime_process_block.h"
27 #include "test_utils.h"
28
29 using ::testing::_;
30
31 namespace android {
32 namespace google_camera_hal {
33
34 // Setup for testing a process block.
35 struct ProcessBlockTestSetup {
36 // Function to create a process block.
37 std::function<std::unique_ptr<ProcessBlock>()> process_block_create_func;
38 uint32_t camera_id; // Camera ID to test
39 std::vector<uint32_t> physical_camera_ids; // Physical camera IDs to test.
40 };
41
42 class ProcessBlockTest : public ::testing::Test {
43 protected:
SetUp()44 void SetUp() override {
45 // Initialize all process block test setups.
46 realtime_process_block_setup_ = {
47 .process_block_create_func =
48 [&]() { return RealtimeProcessBlock::Create(session_hwl_.get()); },
49 .camera_id = 3,
50 };
51
52 multi_camera_process_block_setup_ = {
53 .process_block_create_func =
54 [&]() {
55 return MultiCameraRtProcessBlock::Create(session_hwl_.get());
56 },
57 .camera_id = 3,
58 .physical_camera_ids = {1, 5},
59 };
60
61 process_block_test_setups_ = {
62 realtime_process_block_setup_,
63 multi_camera_process_block_setup_,
64 };
65 }
66
67 // Create a mock device session HWL and stream configuration based on
68 // the test setup.
InitializeProcessBlockTest(const ProcessBlockTestSetup & setup)69 void InitializeProcessBlockTest(const ProcessBlockTestSetup& setup) {
70 // Create a mock session HWL.
71 session_hwl_ = std::make_unique<MockDeviceSessionHwl>(
72 setup.camera_id, setup.physical_camera_ids);
73 ASSERT_NE(session_hwl_, nullptr);
74
75 session_hwl_->DelegateCallsToFakeSession();
76
77 // Create a stream configuration for testing.
78 if (setup.physical_camera_ids.empty()) {
79 test_utils::GetPreviewOnlyStreamConfiguration(&test_config_);
80 } else {
81 test_utils::GetPhysicalPreviewStreamConfiguration(
82 &test_config_, setup.physical_camera_ids);
83 }
84 }
85
86 std::unique_ptr<MockDeviceSessionHwl> session_hwl_;
87 std::vector<ProcessBlockTestSetup> process_block_test_setups_;
88 ProcessBlockTestSetup realtime_process_block_setup_;
89 ProcessBlockTestSetup multi_camera_process_block_setup_;
90 StreamConfiguration test_config_; // Configuration used in tests.
91 };
92
TEST_F(ProcessBlockTest,Create)93 TEST_F(ProcessBlockTest, Create) {
94 for (auto& setup : process_block_test_setups_) {
95 InitializeProcessBlockTest(setup);
96
97 auto block = setup.process_block_create_func();
98 ASSERT_NE(block, nullptr) << "Creating a process block failed";
99 }
100 }
101
TEST_F(ProcessBlockTest,StreamConfiguration)102 TEST_F(ProcessBlockTest, StreamConfiguration) {
103 for (auto& setup : process_block_test_setups_) {
104 InitializeProcessBlockTest(setup);
105
106 auto block = setup.process_block_create_func();
107 ASSERT_NE(block, nullptr) << "Creating a process block failed";
108
109 ASSERT_EQ(block->ConfigureStreams(test_config_, test_config_), OK);
110
111 // Configuring stream again should return ALREADY_EXISTS
112 ASSERT_EQ(block->ConfigureStreams(test_config_, test_config_),
113 ALREADY_EXISTS);
114 }
115 }
116
TEST_F(ProcessBlockTest,SetResultProcessor)117 TEST_F(ProcessBlockTest, SetResultProcessor) {
118 for (auto& setup : process_block_test_setups_) {
119 InitializeProcessBlockTest(setup);
120
121 auto block = setup.process_block_create_func();
122 ASSERT_NE(block, nullptr) << "Creating a process block failed";
123
124 ASSERT_EQ(block->SetResultProcessor(nullptr), BAD_VALUE)
125 << "Setting a nullptr result processor should return BAD_VALUE";
126
127 ASSERT_EQ(
128 block->SetResultProcessor(std::make_unique<MockResultProcessor>()), OK);
129
130 ASSERT_EQ(block->SetResultProcessor(std::make_unique<MockResultProcessor>()),
131 ALREADY_EXISTS)
132 << "Setting result processor again should return ALREADY_EXISTS";
133 }
134 }
135
TEST_F(ProcessBlockTest,GetConfiguredHalStreams)136 TEST_F(ProcessBlockTest, GetConfiguredHalStreams) {
137 for (auto& setup : process_block_test_setups_) {
138 InitializeProcessBlockTest(setup);
139
140 auto block = setup.process_block_create_func();
141 ASSERT_NE(block, nullptr) << "Creating a process block failed";
142
143 ASSERT_EQ(block->GetConfiguredHalStreams(nullptr), BAD_VALUE)
144 << "Passing nullptr should return BAD_VALUE";
145
146 std::vector<HalStream> hal_streams;
147 ASSERT_EQ(block->GetConfiguredHalStreams(&hal_streams), NO_INIT)
148 << "Should return NO_INIT without ConfigureStreams()";
149
150 ASSERT_EQ(block->ConfigureStreams(test_config_, test_config_), OK);
151 ASSERT_EQ(session_hwl_->BuildPipelines(), OK);
152 ASSERT_EQ(block->GetConfiguredHalStreams(&hal_streams), OK);
153 ASSERT_EQ(hal_streams.size(), test_config_.streams.size());
154 }
155 }
156
TEST_F(ProcessBlockTest,Flush)157 TEST_F(ProcessBlockTest, Flush) {
158 for (auto& setup : process_block_test_setups_) {
159 InitializeProcessBlockTest(setup);
160
161 auto block = setup.process_block_create_func();
162 ASSERT_NE(block, nullptr) << "Creating a process block failed";
163
164 ASSERT_EQ(block->Flush(), OK);
165 ASSERT_EQ(block->ConfigureStreams(test_config_, test_config_), OK);
166 ASSERT_EQ(block->Flush(), OK);
167 }
168 }
169
TEST_F(ProcessBlockTest,RealtimeProcessBlockRequest)170 TEST_F(ProcessBlockTest, RealtimeProcessBlockRequest) {
171 ProcessBlockTestSetup& setup = realtime_process_block_setup_;
172 InitializeProcessBlockTest(setup);
173
174 // Verify process block calls HWL session.
175 EXPECT_CALL(*session_hwl_, ConfigurePipeline(_, _, _, _, _)).Times(1);
176 EXPECT_CALL(*session_hwl_, GetConfiguredHalStream(_, _))
177 .Times(test_config_.streams.size());
178 EXPECT_CALL(*session_hwl_, SubmitRequests(_, _)).Times(1);
179
180 auto result_processor = std::make_unique<MockResultProcessor>();
181 ASSERT_NE(result_processor, nullptr) << "Cannot create a MockResultProcessor";
182
183 // Verify process block calls result processor
184 EXPECT_CALL(*result_processor, AddPendingRequests(_, _)).Times(1);
185 EXPECT_CALL(*result_processor, ProcessResult(_)).Times(1);
186 EXPECT_CALL(*result_processor, Notify(_)).Times(1);
187
188 auto block = setup.process_block_create_func();
189 ASSERT_NE(block, nullptr) << "Creating RealtimeProcessBlock failed";
190
191 ASSERT_EQ(block->ConfigureStreams(test_config_, test_config_), OK);
192
193 ASSERT_EQ(session_hwl_->BuildPipelines(), OK);
194
195 std::vector<HalStream> hal_streams;
196 ASSERT_EQ(block->GetConfiguredHalStreams(&hal_streams), OK);
197 EXPECT_EQ(hal_streams.size(), test_config_.streams.size());
198
199 ASSERT_EQ(block->SetResultProcessor(std::move(result_processor)), OK);
200
201 // Testing RealtimeProcessBlock with a dummy request.
202 std::vector<ProcessBlockRequest> block_requests(1);
203 ASSERT_EQ(block->ProcessRequests(block_requests, block_requests[0].request),
204 OK);
205 }
206
TEST_F(ProcessBlockTest,MultiCameraRtProcessBlockRequest)207 TEST_F(ProcessBlockTest, MultiCameraRtProcessBlockRequest) {
208 ProcessBlockTestSetup& setup = multi_camera_process_block_setup_;
209 InitializeProcessBlockTest(setup);
210
211 size_t num_pipelines = setup.physical_camera_ids.size();
212 size_t num_streams = test_config_.streams.size();
213
214 // Verify process block calls HWL session.
215 EXPECT_CALL(*session_hwl_, ConfigurePipeline(_, _, _, _, _))
216 .Times(num_pipelines);
217 EXPECT_CALL(*session_hwl_, GetConfiguredHalStream(_, _)).Times(num_streams);
218 EXPECT_CALL(*session_hwl_, SubmitRequests(_, _)).Times(1);
219
220 auto result_processor = std::make_unique<MockResultProcessor>();
221 ASSERT_NE(result_processor, nullptr) << "Cannot create a MockResultProcessor";
222
223 // Verify process block calls result processor
224 EXPECT_CALL(*result_processor, AddPendingRequests(_, _)).Times(1);
225 EXPECT_CALL(*result_processor, ProcessResult(_)).Times(num_pipelines);
226 EXPECT_CALL(*result_processor, Notify(_)).Times(num_pipelines);
227
228 auto block = setup.process_block_create_func();
229 ASSERT_NE(block, nullptr) << "Creating MultiCameraRtProcessBlock failed";
230
231 ASSERT_EQ(block->ConfigureStreams(test_config_, test_config_), OK);
232
233 ASSERT_EQ(session_hwl_->BuildPipelines(), OK);
234
235 std::vector<HalStream> hal_streams;
236 ASSERT_EQ(block->GetConfiguredHalStreams(&hal_streams), OK);
237 EXPECT_EQ(hal_streams.size(), test_config_.streams.size());
238
239 ASSERT_EQ(block->SetResultProcessor(std::move(result_processor)), OK);
240
241 // Testing RealtimeProcessBlock with dummy requests.
242 std::vector<ProcessBlockRequest> block_requests;
243 CaptureRequest remaining_session_requests;
244
245 for (auto& stream : test_config_.streams) {
246 StreamBuffer buffer;
247 buffer.stream_id = stream.id;
248
249 ProcessBlockRequest block_request;
250 block_request.request.output_buffers.push_back(buffer);
251
252 block_requests.push_back(std::move(block_request));
253 remaining_session_requests.output_buffers.push_back(buffer);
254 }
255
256 ASSERT_EQ(block->ProcessRequests(block_requests, remaining_session_requests),
257 OK);
258 }
259
260 } // namespace google_camera_hal
261 } // namespace android
262