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