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