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