• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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