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