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