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