• 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 <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