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_NDEBUG 0
18 #define LOG_TAG "GCH_ResultDispatcher"
19 #define ATRACE_TAG ATRACE_TAG_CAMERA
20 #include <log/log.h>
21 #include <utils/Trace.h>
22 
23 #include <inttypes.h>
24 
25 #include "result_dispatcher.h"
26 
27 namespace android {
28 namespace google_camera_hal {
29 
Create(uint32_t partial_result_count,ProcessCaptureResultFunc process_capture_result,NotifyFunc notify)30 std::unique_ptr<ResultDispatcher> ResultDispatcher::Create(
31     uint32_t partial_result_count,
32     ProcessCaptureResultFunc process_capture_result, NotifyFunc notify) {
33   ATRACE_CALL();
34   auto dispatcher = std::unique_ptr<ResultDispatcher>(new ResultDispatcher(
35       partial_result_count, process_capture_result, notify));
36   if (dispatcher == nullptr) {
37     ALOGE("%s: Creating ResultDispatcher failed.", __FUNCTION__);
38     return nullptr;
39   }
40 
41   return dispatcher;
42 }
43 
ResultDispatcher(uint32_t partial_result_count,ProcessCaptureResultFunc process_capture_result,NotifyFunc notify)44 ResultDispatcher::ResultDispatcher(
45     uint32_t partial_result_count,
46     ProcessCaptureResultFunc process_capture_result, NotifyFunc notify)
47     : kPartialResultCount(partial_result_count),
48       process_capture_result_(process_capture_result),
49       notify_(notify) {
50   ATRACE_CALL();
51   notify_callback_thread_ =
52       std::thread([this] { this->NotifyCallbackThreadLoop(); });
53 }
54 
~ResultDispatcher()55 ResultDispatcher::~ResultDispatcher() {
56   ATRACE_CALL();
57   {
58     std::unique_lock<std::mutex> lock(notify_callback_lock);
59     notify_callback_thread_exiting = true;
60   }
61 
62   notify_callback_condition_.notify_one();
63   notify_callback_thread_.join();
64 }
65 
RemovePendingRequest(uint32_t frame_number)66 void ResultDispatcher::RemovePendingRequest(uint32_t frame_number) {
67   ATRACE_CALL();
68   std::lock_guard<std::mutex> lock(result_lock_);
69   RemovePendingRequestLocked(frame_number);
70 }
71 
AddPendingRequest(const CaptureRequest & pending_request)72 status_t ResultDispatcher::AddPendingRequest(
73     const CaptureRequest& pending_request) {
74   ATRACE_CALL();
75   std::lock_guard<std::mutex> lock(result_lock_);
76 
77   status_t res = AddPendingRequestLocked(pending_request);
78   if (res != OK) {
79     ALOGE("%s: Adding a pending request failed: %s(%d).", __FUNCTION__,
80           strerror(-res), res);
81     RemovePendingRequestLocked(pending_request.frame_number);
82     return res;
83   }
84 
85   return OK;
86 }
87 
AddPendingRequestLocked(const CaptureRequest & pending_request)88 status_t ResultDispatcher::AddPendingRequestLocked(
89     const CaptureRequest& pending_request) {
90   ATRACE_CALL();
91   uint32_t frame_number = pending_request.frame_number;
92 
93   status_t res = AddPendingShutterLocked(frame_number);
94   if (res != OK) {
95     ALOGE("%s: Adding pending shutter for frame %u failed: %s(%d)",
96           __FUNCTION__, frame_number, strerror(-res), res);
97     return res;
98   }
99 
100   res = AddPendingFinalResultMetadataLocked(frame_number);
101   if (res != OK) {
102     ALOGE("%s: Adding pending result metadata for frame %u failed: %s(%d)",
103           __FUNCTION__, frame_number, strerror(-res), res);
104     return res;
105   }
106 
107   for (auto& buffer : pending_request.input_buffers) {
108     res = AddPendingBufferLocked(frame_number, buffer, /*is_input=*/true);
109     if (res != OK) {
110       ALOGE("%s: Adding pending input buffer for frame %u failed: %s(%d)",
111             __FUNCTION__, frame_number, strerror(-res), res);
112       return res;
113     }
114   }
115 
116   for (auto& buffer : pending_request.output_buffers) {
117     res = AddPendingBufferLocked(frame_number, buffer, /*is_input=*/false);
118     if (res != OK) {
119       ALOGE("%s: Adding pending output buffer for frame %u failed: %s(%d)",
120             __FUNCTION__, frame_number, strerror(-res), res);
121       return res;
122     }
123   }
124 
125   return OK;
126 }
127 
AddPendingShutterLocked(uint32_t frame_number)128 status_t ResultDispatcher::AddPendingShutterLocked(uint32_t frame_number) {
129   ATRACE_CALL();
130   if (pending_shutters_.find(frame_number) != pending_shutters_.end()) {
131     ALOGE("%s: Pending shutter for frame %u already exists.", __FUNCTION__,
132           frame_number);
133     return ALREADY_EXISTS;
134   }
135 
136   pending_shutters_[frame_number] = PendingShutter();
137   return OK;
138 }
139 
AddPendingFinalResultMetadataLocked(uint32_t frame_number)140 status_t ResultDispatcher::AddPendingFinalResultMetadataLocked(
141     uint32_t frame_number) {
142   ATRACE_CALL();
143   if (pending_final_metadata_.find(frame_number) !=
144       pending_final_metadata_.end()) {
145     ALOGE("%s: Pending final result metadata for frame %u already exists.",
146           __FUNCTION__, frame_number);
147     return ALREADY_EXISTS;
148   }
149 
150   pending_final_metadata_[frame_number] = PendingFinalResultMetadata();
151   return OK;
152 }
153 
AddPendingBufferLocked(uint32_t frame_number,const StreamBuffer & buffer,bool is_input)154 status_t ResultDispatcher::AddPendingBufferLocked(uint32_t frame_number,
155                                                   const StreamBuffer& buffer,
156                                                   bool is_input) {
157   ATRACE_CALL();
158   uint32_t stream_id = buffer.stream_id;
159   if (stream_pending_buffers_map_.find(stream_id) ==
160       stream_pending_buffers_map_.end()) {
161     stream_pending_buffers_map_[stream_id] = std::map<uint32_t, PendingBuffer>();
162   }
163 
164   if (stream_pending_buffers_map_[stream_id].find(frame_number) !=
165       stream_pending_buffers_map_[stream_id].end()) {
166     ALOGE("%s: Pending buffer of stream %u for frame %u already exists.",
167           __FUNCTION__, stream_id, frame_number);
168     return ALREADY_EXISTS;
169   }
170 
171   PendingBuffer pending_buffer = {.is_input = is_input};
172   stream_pending_buffers_map_[stream_id][frame_number] = pending_buffer;
173   return OK;
174 }
175 
RemovePendingRequestLocked(uint32_t frame_number)176 void ResultDispatcher::RemovePendingRequestLocked(uint32_t frame_number) {
177   ATRACE_CALL();
178   pending_shutters_.erase(frame_number);
179   pending_final_metadata_.erase(frame_number);
180 
181   for (auto& pending_buffers : stream_pending_buffers_map_) {
182     pending_buffers.second.erase(frame_number);
183   }
184 }
185 
AddResult(std::unique_ptr<CaptureResult> result)186 status_t ResultDispatcher::AddResult(std::unique_ptr<CaptureResult> result) {
187   ATRACE_CALL();
188   status_t res;
189   bool failed = false;
190   uint32_t frame_number = result->frame_number;
191 
192   if (result->result_metadata != nullptr) {
193     res = AddResultMetadata(frame_number, std::move(result->result_metadata),
194                             std::move(result->physical_metadata),
195                             result->partial_result);
196     if (res != OK) {
197       ALOGE("%s: Adding result metadata failed: %s (%d)", __FUNCTION__,
198             strerror(-res), res);
199       failed = true;
200     }
201   }
202 
203   for (auto& buffer : result->output_buffers) {
204     res = AddBuffer(frame_number, buffer);
205     if (res != OK) {
206       ALOGE("%s: Adding an output buffer failed: %s (%d)", __FUNCTION__,
207             strerror(-res), res);
208       failed = true;
209     }
210   }
211 
212   for (auto& buffer : result->input_buffers) {
213     res = AddBuffer(frame_number, buffer);
214     if (res != OK) {
215       ALOGE("%s: Adding an input buffer failed: %s (%d)", __FUNCTION__,
216             strerror(-res), res);
217       failed = true;
218     }
219   }
220 
221   notify_callback_condition_.notify_one();
222   return failed ? UNKNOWN_ERROR : OK;
223 }
224 
AddShutter(uint32_t frame_number,int64_t timestamp_ns)225 status_t ResultDispatcher::AddShutter(uint32_t frame_number,
226                                       int64_t timestamp_ns) {
227   ATRACE_CALL();
228   std::lock_guard<std::mutex> lock(result_lock_);
229 
230   auto shutter_it = pending_shutters_.find(frame_number);
231   if (shutter_it == pending_shutters_.end()) {
232     ALOGE("%s: Cannot find the pending shutter for frame %u", __FUNCTION__,
233           frame_number);
234     return NAME_NOT_FOUND;
235   }
236 
237   if (shutter_it->second.ready) {
238     ALOGE("%s: Already received shutter (%" PRId64
239           ") for frame %u. New "
240           "timestamp %" PRId64,
241           __FUNCTION__, shutter_it->second.timestamp_ns, frame_number,
242           timestamp_ns);
243     return ALREADY_EXISTS;
244   }
245 
246   shutter_it->second.timestamp_ns = timestamp_ns;
247   shutter_it->second.ready = true;
248 
249   notify_callback_condition_.notify_one();
250   return OK;
251 }
252 
AddError(const ErrorMessage & error)253 status_t ResultDispatcher::AddError(const ErrorMessage& error) {
254   ATRACE_CALL();
255   std::lock_guard<std::mutex> lock(result_lock_);
256   uint32_t frame_number = error.frame_number;
257   // No need to deliver the shutter message on an error
258   pending_shutters_.erase(frame_number);
259   // No need to deliver the result metadata on a result metadata error
260   if (error.error_code == ErrorCode::kErrorResult) {
261     pending_final_metadata_.erase(frame_number);
262   }
263 
264   NotifyMessage message = {.type = MessageType::kError, .message.error = error};
265   ALOGD("%s: Notify error %u for frame %u stream %d", __FUNCTION__,
266         error.error_code, frame_number, error.error_stream_id);
267   notify_(message);
268 
269   return OK;
270 }
271 
NotifyResultMetadata(uint32_t frame_number,std::unique_ptr<HalCameraMetadata> metadata,std::vector<PhysicalCameraMetadata> physical_metadata,uint32_t partial_result)272 void ResultDispatcher::NotifyResultMetadata(
273     uint32_t frame_number, std::unique_ptr<HalCameraMetadata> metadata,
274     std::vector<PhysicalCameraMetadata> physical_metadata,
275     uint32_t partial_result) {
276   ATRACE_CALL();
277   auto result = std::make_unique<CaptureResult>(CaptureResult({}));
278   result->frame_number = frame_number;
279   result->result_metadata = std::move(metadata);
280   result->physical_metadata = std::move(physical_metadata);
281   result->partial_result = partial_result;
282 
283   process_capture_result_(std::move(result));
284 }
285 
AddFinalResultMetadata(uint32_t frame_number,std::unique_ptr<HalCameraMetadata> final_metadata,std::vector<PhysicalCameraMetadata> physical_metadata)286 status_t ResultDispatcher::AddFinalResultMetadata(
287     uint32_t frame_number, std::unique_ptr<HalCameraMetadata> final_metadata,
288     std::vector<PhysicalCameraMetadata> physical_metadata) {
289   ATRACE_CALL();
290   std::lock_guard<std::mutex> lock(result_lock_);
291 
292   auto metadata_it = pending_final_metadata_.find(frame_number);
293   if (metadata_it == pending_final_metadata_.end()) {
294     ALOGE("%s: Cannot find the pending result metadata for frame %u",
295           __FUNCTION__, frame_number);
296     return NAME_NOT_FOUND;
297   }
298 
299   if (metadata_it->second.ready) {
300     ALOGE("%s: Already received final result metadata for frame %u.",
301           __FUNCTION__, frame_number);
302     return ALREADY_EXISTS;
303   }
304 
305   metadata_it->second.metadata = std::move(final_metadata);
306   metadata_it->second.physical_metadata = std::move(physical_metadata);
307   metadata_it->second.ready = true;
308   return OK;
309 }
310 
AddResultMetadata(uint32_t frame_number,std::unique_ptr<HalCameraMetadata> metadata,std::vector<PhysicalCameraMetadata> physical_metadata,uint32_t partial_result)311 status_t ResultDispatcher::AddResultMetadata(
312     uint32_t frame_number, std::unique_ptr<HalCameraMetadata> metadata,
313     std::vector<PhysicalCameraMetadata> physical_metadata,
314     uint32_t partial_result) {
315   ATRACE_CALL();
316   if (metadata == nullptr) {
317     ALOGE("%s: metadata is nullptr.", __FUNCTION__);
318     return BAD_VALUE;
319   }
320 
321   if (partial_result > kPartialResultCount) {
322     ALOGE("%s: partial_result %u cannot be larger than partial result count %u",
323           __FUNCTION__, partial_result, kPartialResultCount);
324     return BAD_VALUE;
325   }
326 
327   if (partial_result < kPartialResultCount) {
328     // Send out partial results immediately.
329     NotifyResultMetadata(frame_number, std::move(metadata),
330                          std::move(physical_metadata), partial_result);
331     return OK;
332   }
333 
334   return AddFinalResultMetadata(frame_number, std::move(metadata),
335                                 std::move(physical_metadata));
336 }
337 
AddBuffer(uint32_t frame_number,StreamBuffer buffer)338 status_t ResultDispatcher::AddBuffer(uint32_t frame_number,
339                                      StreamBuffer buffer) {
340   ATRACE_CALL();
341   std::lock_guard<std::mutex> lock(result_lock_);
342 
343   uint32_t stream_id = buffer.stream_id;
344   auto pending_buffers_it = stream_pending_buffers_map_.find(stream_id);
345   if (pending_buffers_it == stream_pending_buffers_map_.end()) {
346     ALOGE("%s: Cannot find the pending buffer for stream %u", __FUNCTION__,
347           stream_id);
348     return NAME_NOT_FOUND;
349   }
350 
351   auto pending_buffer_it = pending_buffers_it->second.find(frame_number);
352   if (pending_buffer_it == pending_buffers_it->second.end()) {
353     ALOGE("%s: Cannot find the pending buffer for stream %u for frame %u",
354           __FUNCTION__, stream_id, frame_number);
355     return NAME_NOT_FOUND;
356   }
357 
358   if (pending_buffer_it->second.ready) {
359     ALOGE("%s: Already received a buffer for stream %u for frame %u",
360           __FUNCTION__, stream_id, frame_number);
361     return ALREADY_EXISTS;
362   }
363 
364   pending_buffer_it->second.buffer = std::move(buffer);
365   pending_buffer_it->second.ready = true;
366 
367   return OK;
368 }
369 
NotifyCallbackThreadLoop()370 void ResultDispatcher::NotifyCallbackThreadLoop() {
371   while (1) {
372     NotifyShutters();
373     NotifyFinalResultMetadata();
374     NotifyBuffers();
375 
376     std::unique_lock<std::mutex> lock(notify_callback_lock);
377     if (notify_callback_thread_exiting) {
378       ALOGV("%s: NotifyCallbackThreadLoop exits.", __FUNCTION__);
379       return;
380     }
381 
382     if (notify_callback_condition_.wait_for(
383             lock, std::chrono::milliseconds(kCallbackThreadTimeoutMs)) ==
384         std::cv_status::timeout) {
385       PrintTimeoutMessages();
386     }
387   }
388 }
389 
PrintTimeoutMessages()390 void ResultDispatcher::PrintTimeoutMessages() {
391   std::lock_guard<std::mutex> lock(result_lock_);
392   for (auto& [frame_number, shutter] : pending_shutters_) {
393     ALOGW("%s: pending shutter for frame %u ready %d", __FUNCTION__,
394           frame_number, shutter.ready);
395   }
396 
397   for (auto& [frame_number, final_metadata] : pending_final_metadata_) {
398     ALOGW("%s: pending final result metadaata for frame %u ready %d",
399           __FUNCTION__, frame_number, final_metadata.ready);
400   }
401 
402   for (auto& [stream_id, pending_buffers] : stream_pending_buffers_map_) {
403     for (auto& [frame_number, pending_buffer] : pending_buffers) {
404       ALOGW("%s: pending buffer of stream %d for frame %u ready %d",
405             __FUNCTION__, stream_id, frame_number, pending_buffer.ready);
406     }
407   }
408 }
409 
GetReadyShutterMessage(NotifyMessage * message)410 status_t ResultDispatcher::GetReadyShutterMessage(NotifyMessage* message) {
411   ATRACE_CALL();
412   if (message == nullptr) {
413     ALOGE("%s: message is nullptr", __FUNCTION__);
414     return BAD_VALUE;
415   }
416 
417   std::lock_guard<std::mutex> lock(result_lock_);
418 
419   auto shutter_it = pending_shutters_.begin();
420   if (shutter_it == pending_shutters_.end() || !shutter_it->second.ready) {
421     // The first pending shutter is not ready.
422     return NAME_NOT_FOUND;
423   }
424 
425   message->type = MessageType::kShutter;
426   message->message.shutter.frame_number = shutter_it->first;
427   message->message.shutter.timestamp_ns = shutter_it->second.timestamp_ns;
428   pending_shutters_.erase(shutter_it);
429 
430   return OK;
431 }
432 
NotifyShutters()433 void ResultDispatcher::NotifyShutters() {
434   ATRACE_CALL();
435   NotifyMessage message = {};
436 
437   while (GetReadyShutterMessage(&message) == OK) {
438     ALOGV("%s: Notify shutter for frame %u timestamp %" PRIu64, __FUNCTION__,
439           message.message.shutter.frame_number,
440           message.message.shutter.timestamp_ns);
441     notify_(message);
442   }
443 }
444 
GetReadyFinalMetadata(uint32_t * frame_number,std::unique_ptr<HalCameraMetadata> * final_metadata,std::vector<PhysicalCameraMetadata> * physical_metadata)445 status_t ResultDispatcher::GetReadyFinalMetadata(
446     uint32_t* frame_number, std::unique_ptr<HalCameraMetadata>* final_metadata,
447     std::vector<PhysicalCameraMetadata>* physical_metadata) {
448   ATRACE_CALL();
449   if (final_metadata == nullptr || frame_number == nullptr) {
450     ALOGE("%s: final_metadata (%p) or frame_number (%p) is nullptr",
451           __FUNCTION__, final_metadata, frame_number);
452     return BAD_VALUE;
453   }
454 
455   std::lock_guard<std::mutex> lock(result_lock_);
456 
457   auto final_metadata_it = pending_final_metadata_.begin();
458   if (final_metadata_it == pending_final_metadata_.end() ||
459       !final_metadata_it->second.ready) {
460     // The first pending final metadata is not ready.
461     return NAME_NOT_FOUND;
462   }
463 
464   *frame_number = final_metadata_it->first;
465   *final_metadata = std::move(final_metadata_it->second.metadata);
466   *physical_metadata = std::move(final_metadata_it->second.physical_metadata);
467   pending_final_metadata_.erase(final_metadata_it);
468 
469   return OK;
470 }
471 
NotifyFinalResultMetadata()472 void ResultDispatcher::NotifyFinalResultMetadata() {
473   ATRACE_CALL();
474   uint32_t frame_number;
475   std::unique_ptr<HalCameraMetadata> final_metadata;
476   std::vector<PhysicalCameraMetadata> physical_metadata;
477 
478   while (GetReadyFinalMetadata(&frame_number, &final_metadata,
479                                &physical_metadata) == OK) {
480     ALOGV("%s: Notify final metadata for frame %u", __FUNCTION__, frame_number);
481     NotifyResultMetadata(frame_number, std::move(final_metadata),
482                          std::move(physical_metadata), kPartialResultCount);
483   }
484 }
485 
GetReadyBufferResult(std::unique_ptr<CaptureResult> * result)486 status_t ResultDispatcher::GetReadyBufferResult(
487     std::unique_ptr<CaptureResult>* result) {
488   ATRACE_CALL();
489   std::lock_guard<std::mutex> lock(result_lock_);
490   if (result == nullptr) {
491     ALOGE("%s: result is nullptr.", __FUNCTION__);
492     return BAD_VALUE;
493   }
494 
495   *result = nullptr;
496 
497   for (auto& pending_buffers : stream_pending_buffers_map_) {
498     auto buffer_it = pending_buffers.second.begin();
499     while (buffer_it != pending_buffers.second.end()) {
500       if (!buffer_it->second.ready) {
501         // No more buffer ready.
502         break;
503       }
504 
505       auto buffer_result = std::make_unique<CaptureResult>(CaptureResult({}));
506 
507       buffer_result->frame_number = buffer_it->first;
508       if (buffer_it->second.is_input) {
509         buffer_result->input_buffers.push_back(buffer_it->second.buffer);
510       } else {
511         buffer_result->output_buffers.push_back(buffer_it->second.buffer);
512       }
513 
514       pending_buffers.second.erase(buffer_it);
515       *result = std::move(buffer_result);
516       return OK;
517     }
518   }
519 
520   return NAME_NOT_FOUND;
521 }
522 
NotifyBuffers()523 void ResultDispatcher::NotifyBuffers() {
524   ATRACE_CALL();
525   std::unique_ptr<CaptureResult> result;
526 
527   while (GetReadyBufferResult(&result) == OK) {
528     if (result == nullptr) {
529       ALOGE("%s: result is nullptr", __FUNCTION__);
530       return;
531     }
532     process_capture_result_(std::move(result));
533   }
534 }
535 
536 }  // namespace google_camera_hal
537 }  // namespace android