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 "ResultDispatcherTests"
18 #include <cutils/properties.h>
19 #include <gtest/gtest.h>
20 #include <log/log.h>
21
22 #include <string>
23 #include <unordered_map>
24 #include <unordered_set>
25
26 #include "result_dispatcher.h"
27
28 namespace android {
29 namespace google_camera_hal {
30
31 class ResultDispatcherTests : public ::testing::Test {
32 protected:
33 // TODO(b/143902331): Test partial results.
34 static constexpr uint32_t kPartialResult = 1;
35 static constexpr uint32_t kResultWaitTimeMs = 30;
36
37 // Defined a result metadata received from the result dispatcher.
38 struct ReceivedResultMetadata {
39 uint32_t frame_number = 0;
40 std::unique_ptr<HalCameraMetadata> result_metadata;
41 };
42
43 // Defined a buffer received from the result dispatcher.
44 struct ReceivedBuffer {
45 uint32_t frame_number = 0;
46 StreamBuffer buffer;
47 };
48
SetUp()49 void SetUp() override {
50 // Skip test if product is unsupported.
51 char product_name[PROPERTY_VALUE_MAX];
52 std::unordered_set<std::string> const supported_product_list{
53 "blueline", "crosshatch", "flame", "coral", "needlefish"};
54 property_get("ro.build.product", product_name, "");
55 bool product_support_test =
56 supported_product_list.find(std::string{product_name}) !=
57 supported_product_list.end();
58 if (!product_support_test) {
59 GTEST_SKIP();
60 }
61
62 StreamConfiguration stream_config;
63 result_dispatcher_ = ResultDispatcher::Create(
64 kPartialResult,
65 [this](std::unique_ptr<CaptureResult> result) {
66 ProcessCaptureResult(std::move(result));
67 },
68 /*process_batch_capture_result=*/nullptr,
69 [this](const NotifyMessage& message) { Notify(message); },
70 stream_config, "TestResultDispatcher");
71
72 ASSERT_NE(result_dispatcher_, nullptr)
73 << "Creating ResultDispatcher failed";
74 }
75
76 // Invoked when receiving a shutter from the result dispatcher.
Notify(const NotifyMessage & message)77 void Notify(const NotifyMessage& message) {
78 if (message.type != MessageType::kShutter) {
79 EXPECT_EQ(message.type, MessageType::kShutter)
80 << "Received a non-shutter message.";
81 return;
82 }
83
84 std::lock_guard<std::mutex> lock(callback_lock_);
85 received_shutters_.push_back({message.message.shutter.frame_number,
86 message.message.shutter.timestamp_ns});
87 callback_condition_.notify_one();
88 }
89
90 // Invoked when receiving a capture result from the result dispatcher.
ProcessCaptureResult(std::unique_ptr<CaptureResult> new_result)91 void ProcessCaptureResult(std::unique_ptr<CaptureResult> new_result) {
92 if (new_result == nullptr) {
93 EXPECT_NE(new_result, nullptr);
94 return;
95 }
96
97 uint32_t frame_number = new_result->frame_number;
98
99 std::lock_guard<std::mutex> lock(callback_lock_);
100 if (new_result->result_metadata != nullptr) {
101 ASSERT_EQ(new_result->partial_result, kPartialResult);
102
103 ReceivedResultMetadata metadata;
104 metadata.frame_number = frame_number;
105 metadata.result_metadata = std::move(new_result->result_metadata);
106 received_result_metadata_.push_back(std::move(metadata));
107 }
108
109 for (auto& buffer : new_result->output_buffers) {
110 ProcessReceivedBuffer(frame_number, buffer);
111 }
112
113 for (auto& buffer : new_result->input_buffers) {
114 ProcessReceivedBuffer(frame_number, buffer);
115 }
116 callback_condition_.notify_one();
117 }
118
119 // Add a bufffer to the received buffer queue.
ProcessReceivedBuffer(uint32_t frame_number,const StreamBuffer & buffer)120 void ProcessReceivedBuffer(uint32_t frame_number, const StreamBuffer& buffer) {
121 auto buffers_it = stream_received_buffers_map_.find(buffer.stream_id);
122 if (buffers_it == stream_received_buffers_map_.end()) {
123 stream_received_buffers_map_.emplace(buffer.stream_id,
124 std::vector<ReceivedBuffer>{});
125 buffers_it = stream_received_buffers_map_.find(buffer.stream_id);
126 ASSERT_NE(buffers_it, stream_received_buffers_map_.end());
127 }
128
129 buffers_it->second.push_back({frame_number, buffer});
130 }
131
132 // Protected by callback_lock_.
IsShutterReceivedLocked(uint32_t frame_number,uint64_t timestamp_ns)133 bool IsShutterReceivedLocked(uint32_t frame_number, uint64_t timestamp_ns) {
134 for (auto& shutter : received_shutters_) {
135 if (shutter.frame_number == frame_number &&
136 shutter.timestamp_ns == timestamp_ns) {
137 return true;
138 }
139 }
140
141 return false;
142 }
143
144 // Wait for a shutter from the result dispatcher.
WaitForShutter(uint32_t frame_number,uint64_t timestamp_ns)145 status_t WaitForShutter(uint32_t frame_number, uint64_t timestamp_ns) {
146 std::unique_lock<std::mutex> lock(callback_lock_);
147 bool received = callback_condition_.wait_for(
148 lock, std::chrono::milliseconds(kResultWaitTimeMs),
149 [&] { return IsShutterReceivedLocked(frame_number, timestamp_ns); });
150
151 return received ? OK : TIMED_OUT;
152 }
153
154 // Protected by callback_lock_.
IsResultMetadataReceivedLocked(uint32_t frame_number)155 bool IsResultMetadataReceivedLocked(uint32_t frame_number) {
156 for (auto& metadata : received_result_metadata_) {
157 if (metadata.frame_number == frame_number) {
158 return true;
159 }
160 }
161
162 return false;
163 }
164
WaitForResultMetadata(uint32_t frame_number)165 status_t WaitForResultMetadata(uint32_t frame_number) {
166 std::unique_lock<std::mutex> lock(callback_lock_);
167 bool received = callback_condition_.wait_for(
168 lock, std::chrono::milliseconds(kResultWaitTimeMs),
169 [&] { return IsResultMetadataReceivedLocked(frame_number); });
170
171 return received ? OK : TIMED_OUT;
172 }
173
174 // Protected by callback_lock_.
IsOutputBufferReceivedLocked(uint32_t frame_number,int32_t stream_id)175 bool IsOutputBufferReceivedLocked(uint32_t frame_number, int32_t stream_id) {
176 auto buffers_it = stream_received_buffers_map_.find(stream_id);
177 if (buffers_it == stream_received_buffers_map_.end()) {
178 return false;
179 }
180
181 for (auto& buffer : buffers_it->second) {
182 if (buffer.frame_number == frame_number) {
183 return true;
184 }
185 }
186
187 return false;
188 }
189
WaitForOuptutBuffer(uint32_t frame_number,int32_t stream_id)190 status_t WaitForOuptutBuffer(uint32_t frame_number, int32_t stream_id) {
191 std::unique_lock<std::mutex> lock(callback_lock_);
192 bool received = callback_condition_.wait_for(
193 lock, std::chrono::milliseconds(kResultWaitTimeMs),
194 [&] { return IsOutputBufferReceivedLocked(frame_number, stream_id); });
195
196 return received ? OK : TIMED_OUT;
197 }
198
199 // Verify received shutters are sorted by frame numbers.
VerifyShuttersOrder()200 void VerifyShuttersOrder() {
201 std::lock_guard<std::mutex> lock(callback_lock_);
202
203 auto shutter = received_shutters_.begin();
204 if (shutter == received_shutters_.end()) {
205 return;
206 }
207
208 while (1) {
209 auto next_shutter = shutter;
210 next_shutter++;
211 if (next_shutter == received_shutters_.end()) {
212 return;
213 }
214
215 EXPECT_LT(shutter->frame_number, next_shutter->frame_number);
216 shutter = next_shutter;
217 }
218 }
219
220 // Verify received result metadata are sorted by frame numbers.
VerifyResultMetadataOrder()221 void VerifyResultMetadataOrder() {
222 std::lock_guard<std::mutex> lock(callback_lock_);
223
224 auto metadata = received_result_metadata_.begin();
225 if (metadata == received_result_metadata_.end()) {
226 return;
227 }
228
229 while (1) {
230 auto next_metadata = metadata;
231 next_metadata++;
232 if (next_metadata == received_result_metadata_.end()) {
233 return;
234 }
235
236 EXPECT_LT(metadata->frame_number, next_metadata->frame_number);
237 metadata = next_metadata;
238 }
239 }
240
241 // Verify received buffers are sorted by frame numbers.
242 // Protected by callback_lock_.
VerifyBuffersOrderLocked(const std::vector<ReceivedBuffer> & buffers)243 void VerifyBuffersOrderLocked(const std::vector<ReceivedBuffer>& buffers) {
244 auto buffer = buffers.begin();
245 if (buffer == buffers.end()) {
246 return;
247 }
248
249 while (1) {
250 auto next_buffer = buffer;
251 next_buffer++;
252 if (next_buffer == buffers.end()) {
253 return;
254 }
255
256 EXPECT_LT(buffer->frame_number, next_buffer->frame_number);
257 buffer = next_buffer;
258 }
259 }
260
261 // Verify received buffers are sorted by frame numbers.
VerifyBuffersOrder()262 void VerifyBuffersOrder() {
263 std::lock_guard<std::mutex> lock(callback_lock_);
264
265 for (auto buffers : stream_received_buffers_map_) {
266 VerifyBuffersOrderLocked(buffers.second);
267 }
268 }
269
270 // Add pending request to dispatcher in the order of frame numbers, given
271 // unordered frame numbers and ordered output buffers.
AddPendingRequestsToDispatcher(const std::vector<uint32_t> & unordered_frame_numbers,const std::vector<std::vector<StreamBuffer>> & ordered_output_buffers={})272 void AddPendingRequestsToDispatcher(
273 const std::vector<uint32_t>& unordered_frame_numbers,
274 const std::vector<std::vector<StreamBuffer>>& ordered_output_buffers = {}) {
275 if (ordered_output_buffers.size() > 0) {
276 ASSERT_EQ(ordered_output_buffers.size(), unordered_frame_numbers.size());
277 }
278
279 std::vector<uint32_t> ordered_frame_numbers = unordered_frame_numbers;
280 std::sort(ordered_frame_numbers.begin(), ordered_frame_numbers.end());
281
282 // Add pending requests to result dispatcher.
283 for (size_t i = 0; i < ordered_frame_numbers.size(); i++) {
284 CaptureRequest request = {};
285 request.frame_number = ordered_frame_numbers[i];
286 if (ordered_output_buffers.size() > 0) {
287 request.output_buffers = ordered_output_buffers[i];
288 }
289
290 ASSERT_EQ(result_dispatcher_->AddPendingRequest(request), OK)
291 << "Failed to add a pending request for frame "
292 << request.frame_number;
293 }
294 }
295
296 std::unique_ptr<ResultDispatcher> result_dispatcher_;
297
298 std::mutex callback_lock_;
299 std::condition_variable callback_condition_;
300
301 // Protected by callback_lock_.
302 std::vector<ShutterMessage> received_shutters_;
303
304 // Protected by callback_lock_.
305 std::vector<ReceivedResultMetadata> received_result_metadata_;
306
307 // Maps from stream ID to received output buffers.
308 // Protected by callback_lock_.
309 std::unordered_map<int32_t, std::vector<ReceivedBuffer>>
310 stream_received_buffers_map_;
311 };
312
TEST_F(ResultDispatcherTests,ShutterOrder)313 TEST_F(ResultDispatcherTests, ShutterOrder) {
314 static constexpr uint64_t kFrameDurationNs = 100;
315 static constexpr uint64_t kFrameExposureTimeNs = 33;
316
317 std::vector<uint32_t> unordered_frame_numbers = {3, 1, 2, 5, 4, 6};
318 AddPendingRequestsToDispatcher(unordered_frame_numbers);
319
320 // Add unordered shutters to dispatcher.
321 for (auto frame_number : unordered_frame_numbers) {
322 EXPECT_EQ(result_dispatcher_->AddShutter(
323 frame_number,
324 frame_number * kFrameDurationNs - kFrameExposureTimeNs,
325 frame_number * kFrameDurationNs),
326 OK);
327 }
328
329 // Wait for all shutters to be notified.
330 for (auto& frame_number : unordered_frame_numbers) {
331 EXPECT_EQ(WaitForShutter(frame_number, frame_number * kFrameDurationNs), OK)
332 << "Waiting for shutter for frame " << frame_number << " timed out.";
333 }
334
335 // Verify the shutters are received in the order of frame numbers.
336 VerifyShuttersOrder();
337 }
338
TEST_F(ResultDispatcherTests,ResultMetadataOrder)339 TEST_F(ResultDispatcherTests, ResultMetadataOrder) {
340 std::vector<uint32_t> unordered_frame_numbers = {4, 2, 1, 3, 6, 5};
341 AddPendingRequestsToDispatcher(unordered_frame_numbers);
342
343 // Add unordered result metadata to dispatcher.
344 for (auto frame_number : unordered_frame_numbers) {
345 static constexpr uint32_t kNumEntries = 10;
346 static constexpr uint32_t kDataBytes = 256;
347
348 auto result = std::make_unique<CaptureResult>(CaptureResult({}));
349 result->frame_number = frame_number;
350 result->partial_result = kPartialResult;
351 result->result_metadata = HalCameraMetadata::Create(kNumEntries, kDataBytes);
352
353 EXPECT_EQ(result_dispatcher_->AddResult(std::move(result)), OK);
354 }
355
356 // Wait for all result metadata to be notified.
357 for (auto& frame_number : unordered_frame_numbers) {
358 EXPECT_EQ(WaitForResultMetadata(frame_number), OK)
359 << "Waiting for result metadata for frame " << frame_number
360 << " timed out.";
361 }
362
363 // Verify the result metadata are received in the order of frame numbers.
364 VerifyResultMetadataOrder();
365 }
366
TEST_F(ResultDispatcherTests,OutputBufferOrder)367 TEST_F(ResultDispatcherTests, OutputBufferOrder) {
368 static constexpr int32_t kStreamId = 5;
369
370 std::vector<uint32_t> unordered_frame_numbers = {3, 1, 4, 2, 5, 6};
371 std::vector<std::vector<StreamBuffer>> output_buffers;
372
373 for (uint32_t i = 0; i < unordered_frame_numbers.size(); i++) {
374 StreamBuffer buffer = {
375 .stream_id = kStreamId,
376 .buffer_id = i,
377 };
378
379 output_buffers.push_back({buffer});
380 }
381
382 AddPendingRequestsToDispatcher(unordered_frame_numbers, output_buffers);
383
384 // Add unordered output buffers to dispatcher.
385 for (uint32_t i = 0; i < unordered_frame_numbers.size(); i++) {
386 auto result = std::make_unique<CaptureResult>();
387 result->frame_number = unordered_frame_numbers[i];
388 result->partial_result = 0;
389 result->output_buffers = output_buffers[i];
390
391 EXPECT_EQ(result_dispatcher_->AddResult(std::move(result)), OK);
392 }
393
394 // Wait for all output buffers to be notified.
395 for (auto& frame_number : unordered_frame_numbers) {
396 EXPECT_EQ(WaitForOuptutBuffer(frame_number, kStreamId), OK)
397 << "Waiting for output buffers for frame " << frame_number
398 << " timed out.";
399 }
400
401 // Verify the buffers are received in the order of frame numbers.
402 VerifyBuffersOrder();
403 }
404
TEST_F(ResultDispatcherTests,ShutterOrderWithRemovePengingRequest)405 TEST_F(ResultDispatcherTests, ShutterOrderWithRemovePengingRequest) {
406 static constexpr uint64_t kFrameDurationNs = 100;
407 static constexpr uint64_t kFrameExposureTimeNs = 33;
408
409 std::vector<uint32_t> unordered_frame_numbers = {3, 1, 2, 5, 4, 6};
410 AddPendingRequestsToDispatcher(unordered_frame_numbers);
411
412 auto iter = unordered_frame_numbers.begin() + 2;
413 auto remove_frame_number = *iter;
414 // After erase iter, unordered_frame_numbers = {3, 1, 5, 4, 6};
415 unordered_frame_numbers.erase(iter);
416 for (auto frame_number : unordered_frame_numbers) {
417 EXPECT_EQ(result_dispatcher_->AddShutter(
418 frame_number,
419 frame_number * kFrameDurationNs - kFrameExposureTimeNs,
420 frame_number * kFrameDurationNs),
421 OK);
422 }
423
424 // Remove pending request for the frame number 2.
425 result_dispatcher_->RemovePendingRequest(remove_frame_number);
426
427 // Wait for all shutters to be notified.
428 for (auto& frame_number : unordered_frame_numbers) {
429 EXPECT_EQ(WaitForShutter(frame_number, frame_number * kFrameDurationNs), OK)
430 << "Waiting for shutter for frame " << frame_number << " timed out.";
431 }
432
433 // Verify the shutters are received in the order of frame numbers.
434 VerifyShuttersOrder();
435 }
436
437 // TODO(b/138960498): Test errors like adding repeated pending requests and
438 // repeated results.
439
440 } // namespace google_camera_hal
441 } // namespace android
442