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