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_PendingRequestsTracker"
19 #define ATRACE_TAG ATRACE_TAG_CAMERA
20 #include "pending_requests_tracker.h"
21 
22 #include <log/log.h>
23 #include <utils/Trace.h>
24 
25 #include "libgooglecamerahal_flags.h"
26 
27 namespace android {
28 namespace google_camera_hal {
29 
Create(const std::vector<HalStream> & hal_configured_streams,const std::unordered_map<int32_t,int32_t> & grouped_stream_id_map,const std::set<int32_t> & hal_buffer_managed_stream_ids)30 std::unique_ptr<PendingRequestsTracker> PendingRequestsTracker::Create(
31     const std::vector<HalStream>& hal_configured_streams,
32     const std::unordered_map<int32_t, int32_t>& grouped_stream_id_map,
33     const std::set<int32_t>& hal_buffer_managed_stream_ids) {
34   auto tracker =
35       std::unique_ptr<PendingRequestsTracker>(new PendingRequestsTracker());
36   if (tracker == nullptr) {
37     ALOGE("%s: Failed to create PendingRequestsTracker", __FUNCTION__);
38     return nullptr;
39   }
40 
41   status_t res =
42       tracker->Initialize(hal_configured_streams, grouped_stream_id_map,
43                           hal_buffer_managed_stream_ids);
44   if (res != OK) {
45     ALOGE("%s: Initializing stream buffer tracker failed: %s(%d)", __FUNCTION__,
46           strerror(-res), res);
47     return nullptr;
48   }
49 
50   return tracker;
51 }
52 
Initialize(const std::vector<HalStream> & hal_configured_streams,const std::unordered_map<int32_t,int32_t> & grouped_stream_id_map,const std::set<int32_t> & hal_buffer_managed_stream_ids)53 status_t PendingRequestsTracker::Initialize(
54     const std::vector<HalStream>& hal_configured_streams,
55     const std::unordered_map<int32_t, int32_t>& grouped_stream_id_map,
56     const std::set<int32_t>& hal_buffer_managed_stream_ids) {
57   hal_buffer_managed_stream_ids_ = hal_buffer_managed_stream_ids;
58   grouped_stream_id_map_ = grouped_stream_id_map;
59   for (auto& hal_stream : hal_configured_streams) {
60     int hal_stream_id = OverrideStreamIdForGroup(hal_stream.id);
61     // For grouped hal streams, only use one stream to represent the whole group
62     if (hal_stream_id == hal_stream.id) {
63       auto [max_buffer_it, max_buffer_inserted] =
64           stream_max_buffers_.emplace(hal_stream_id, hal_stream.max_buffers);
65       if (!max_buffer_inserted) {
66         ALOGE("%s: There are duplicated stream id %d", __FUNCTION__,
67               hal_stream_id);
68         return BAD_VALUE;
69       }
70 
71       stream_pending_buffers_.emplace(hal_stream_id, /*pending_buffers=*/0);
72       stream_acquired_buffers_.emplace(hal_stream_id, /*pending_buffers=*/0);
73     }
74   }
75 
76   return OK;
77 }
78 
IsStreamConfigured(int32_t stream_id) const79 bool PendingRequestsTracker::IsStreamConfigured(int32_t stream_id) const {
80   return stream_max_buffers_.find(stream_id) != stream_max_buffers_.end();
81 }
82 
OverrideStreamIdForGroup(int32_t stream_id) const83 int32_t PendingRequestsTracker::OverrideStreamIdForGroup(int32_t stream_id) const {
84   if (grouped_stream_id_map_.count(stream_id) == 1) {
85     return grouped_stream_id_map_.at(stream_id);
86   } else {
87     return stream_id;
88   }
89 }
90 
TrackRequestBuffersLocked(const std::vector<StreamBuffer> & requested_buffers)91 void PendingRequestsTracker::TrackRequestBuffersLocked(
92     const std::vector<StreamBuffer>& requested_buffers) {
93   ATRACE_CALL();
94 
95   for (auto& buffer : requested_buffers) {
96     int32_t stream_id = OverrideStreamIdForGroup(buffer.stream_id);
97     if (!IsStreamConfigured(stream_id)) {
98       ALOGW("%s: stream %d was not configured.", __FUNCTION__, stream_id);
99       // Continue to track other buffers.
100       continue;
101     }
102     if (hal_buffer_managed_stream_ids_.find(stream_id) ==
103         hal_buffer_managed_stream_ids_.end()) {
104       // Pending requests tracker doesn't track stream ids which aren't HAL
105       // buffer managed
106       continue;
107     }
108 
109     stream_pending_buffers_[stream_id]++;
110   }
111 }
112 
TrackReturnedResultBuffers(const std::vector<StreamBuffer> & returned_buffers)113 status_t PendingRequestsTracker::TrackReturnedResultBuffers(
114     const std::vector<StreamBuffer>& returned_buffers) {
115   ATRACE_CALL();
116 
117   {
118     std::lock_guard<std::mutex> lock(pending_requests_mutex_);
119     for (auto& buffer : returned_buffers) {
120       int32_t stream_id = OverrideStreamIdForGroup(buffer.stream_id);
121       if (hal_buffer_managed_stream_ids_.find(stream_id) ==
122           hal_buffer_managed_stream_ids_.end()) {
123         // Pending requests tracker doesn't track stream ids which aren't HAL
124         // buffer managed
125         continue;
126       }
127       if (!IsStreamConfigured(stream_id)) {
128         ALOGW("%s: stream %d was not configured.", __FUNCTION__, stream_id);
129         // Continue to track other buffers.
130         continue;
131       }
132 
133       if (stream_pending_buffers_[stream_id] == 0) {
134         ALOGE("%s: stream %d should not have any pending quota buffers.",
135               __FUNCTION__, stream_id);
136         // Continue to track other buffers.
137         continue;
138       }
139 
140       stream_pending_buffers_[stream_id]--;
141       if (stream_pending_buffers_[stream_id] == 0) {
142         ALOGV("%s: stream %d all pending buffers have been returned.",
143               __FUNCTION__, stream_id);
144       }
145     }
146   }
147 
148   tracker_request_condition_.notify_one();
149   return OK;
150 }
151 
TrackReturnedAcquiredBuffers(const std::vector<StreamBuffer> & returned_buffers)152 status_t PendingRequestsTracker::TrackReturnedAcquiredBuffers(
153     const std::vector<StreamBuffer>& returned_buffers) {
154   ATRACE_CALL();
155 
156   {
157     std::lock_guard<std::mutex> lock(pending_acquisition_mutex_);
158     for (auto& buffer : returned_buffers) {
159       int32_t stream_id = OverrideStreamIdForGroup(buffer.stream_id);
160       if (!IsStreamConfigured(stream_id)) {
161         ALOGW("%s: stream %d was not configured.", __FUNCTION__, stream_id);
162         // Continue to track other buffers.
163         continue;
164       }
165       if (hal_buffer_managed_stream_ids_.find(stream_id) ==
166           hal_buffer_managed_stream_ids_.end()) {
167         // Pending requests tracker doesn't track stream ids which aren't HAL
168         // buffer managed
169         continue;
170       }
171       if (stream_acquired_buffers_[stream_id] == 0) {
172         if (buffer.status == BufferStatus::kOk) {
173           ALOGE("%s: stream %d should not have any pending acquired buffers.",
174                 __FUNCTION__, stream_id);
175         } else {
176           // This may indicate that HAL doesn't intend to process a certain
177           // buffer, so the buffer isn't sent to pipeline and it's not
178           // explicitly allocated and recorded in buffer cache manager.
179           // The buffer still needs to return to framework with an error status
180           // if HAL doesn't process it.
181           ALOGV(
182               "%s: stream %d isn't acquired but returned with buffer status %u",
183               __FUNCTION__, stream_id, buffer.status);
184         }
185         // Continue to track other buffers.
186         continue;
187       }
188 
189       stream_acquired_buffers_[stream_id]--;
190     }
191   }
192 
193   tracker_acquisition_condition_.notify_one();
194   return OK;
195 }
196 
OnBufferCacheFlushed()197 void PendingRequestsTracker::OnBufferCacheFlushed() {
198   std::unique_lock<std::mutex> lock(pending_requests_mutex_);
199   requested_stream_ids_.clear();
200 }
201 
DoStreamsHaveEnoughBuffersLocked(const std::vector<StreamBuffer> & buffers) const202 bool PendingRequestsTracker::DoStreamsHaveEnoughBuffersLocked(
203     const std::vector<StreamBuffer>& buffers) const {
204   for (auto& buffer : buffers) {
205     int32_t stream_id = OverrideStreamIdForGroup(buffer.stream_id);
206     if (!IsStreamConfigured(stream_id)) {
207       ALOGE("%s: stream %d was not configured.", __FUNCTION__, stream_id);
208       return false;
209     }
210     if (hal_buffer_managed_stream_ids_.find(stream_id) ==
211         hal_buffer_managed_stream_ids_.end()) {
212       // Pending requests tracker doesn't track stream ids which aren't HAL
213       // buffer managed
214       continue;
215     }
216 
217     if (stream_pending_buffers_.at(stream_id) >=
218         stream_max_buffers_.at(stream_id)) {
219       ALOGV("%s: stream %d is not ready. max_buffers=%u", __FUNCTION__,
220             stream_id, stream_max_buffers_.at(stream_id));
221       return false;
222     }
223   }
224 
225   return true;
226 }
227 
DoesStreamHaveEnoughBuffersToAcquireLocked(int32_t stream_id,uint32_t num_buffers) const228 bool PendingRequestsTracker::DoesStreamHaveEnoughBuffersToAcquireLocked(
229     int32_t stream_id, uint32_t num_buffers) const {
230   if (!IsStreamConfigured(stream_id)) {
231     ALOGE("%s: stream %d was not configured.", __FUNCTION__, stream_id);
232     return false;
233   }
234 
235   if (stream_acquired_buffers_.at(stream_id) + num_buffers >
236       stream_max_buffers_.at(stream_id)) {
237     ALOGV("%s: stream %d is not ready. max_buffers=%u", __FUNCTION__, stream_id,
238           stream_max_buffers_.at(stream_id));
239     return false;
240   }
241 
242   return true;
243 }
244 
UpdateRequestedStreamIdsLocked(const std::vector<StreamBuffer> & requested_buffers,std::vector<int32_t> * first_requested_stream_ids)245 status_t PendingRequestsTracker::UpdateRequestedStreamIdsLocked(
246     const std::vector<StreamBuffer>& requested_buffers,
247     std::vector<int32_t>* first_requested_stream_ids) {
248   if (first_requested_stream_ids == nullptr) {
249     ALOGE("%s: first_requested_stream_ids is nullptr", __FUNCTION__);
250     return BAD_VALUE;
251   }
252 
253   for (auto& buffer : requested_buffers) {
254     int32_t stream_id = OverrideStreamIdForGroup(buffer.stream_id);
255     if (hal_buffer_managed_stream_ids_.find(stream_id) ==
256         hal_buffer_managed_stream_ids_.end()) {
257       // Pending requests tracker doesn't track stream ids which aren't HAL
258       // buffer managed
259       continue;
260     }
261     auto stream_id_iter = requested_stream_ids_.find(stream_id);
262     if (stream_id_iter == requested_stream_ids_.end()) {
263       first_requested_stream_ids->push_back(stream_id);
264 
265       // Include all stream IDs in the same group in first_requested_stream_ids
266       for (auto& [id_in_group, group_stream_id] : grouped_stream_id_map_) {
267         if (group_stream_id == stream_id) {
268           first_requested_stream_ids->push_back(id_in_group);
269         }
270       }
271       requested_stream_ids_.emplace(stream_id);
272     }
273   }
274 
275   return OK;
276 }
277 
WaitAndTrackRequestBuffers(const CaptureRequest & request,std::vector<int32_t> * first_requested_stream_ids)278 status_t PendingRequestsTracker::WaitAndTrackRequestBuffers(
279     const CaptureRequest& request,
280     std::vector<int32_t>* first_requested_stream_ids) {
281   ATRACE_CALL();
282 
283   if (first_requested_stream_ids == nullptr) {
284     ALOGE("%s: first_requested_stream_ids is nullptr", __FUNCTION__);
285     return BAD_VALUE;
286   }
287 
288   std::unique_lock<std::mutex> lock(pending_requests_mutex_);
289   if (libgooglecamerahal::flags::disable_capture_request_timeout()) {
290     tracker_request_condition_.wait(lock, [this, &request] {
291       return DoStreamsHaveEnoughBuffersLocked(request.output_buffers);
292     });
293   } else {
294     constexpr uint32_t kTrackerTimeoutMs = 3000;
295     if (!tracker_request_condition_.wait_for(
296             lock, std::chrono::milliseconds(kTrackerTimeoutMs), [this, &request] {
297               return DoStreamsHaveEnoughBuffersLocked(request.output_buffers);
298             })) {
299       ALOGE("%s: Waiting for buffer ready timed out.", __FUNCTION__);
300       return TIMED_OUT;
301     }
302   }
303 
304   ALOGV("%s: all streams are ready", __FUNCTION__);
305 
306   TrackRequestBuffersLocked(request.output_buffers);
307 
308   first_requested_stream_ids->clear();
309   status_t res = UpdateRequestedStreamIdsLocked(request.output_buffers,
310                                                 first_requested_stream_ids);
311   if (res != OK) {
312     ALOGE("%s: Updating requested stream ID for output buffers failed: %s(%d)",
313           __FUNCTION__, strerror(-res), res);
314     return res;
315   }
316 
317   return OK;
318 }
319 
WaitAndTrackAcquiredBuffers(int32_t stream_id,uint32_t num_buffers)320 status_t PendingRequestsTracker::WaitAndTrackAcquiredBuffers(
321     int32_t stream_id, uint32_t num_buffers) {
322   ATRACE_CALL();
323 
324   int32_t overridden_stream_id = OverrideStreamIdForGroup(stream_id);
325   if (hal_buffer_managed_stream_ids_.find(stream_id) ==
326       hal_buffer_managed_stream_ids_.end()) {
327     // Pending requests tracker doesn't track stream ids which aren't HAL buffer
328     // managed
329     return OK;
330   }
331   if (!IsStreamConfigured(overridden_stream_id)) {
332     ALOGW("%s: stream %d was not configured.", __FUNCTION__,
333           overridden_stream_id);
334     // Continue to track other buffers.
335     return BAD_VALUE;
336   }
337 
338   std::unique_lock<std::mutex> lock(pending_acquisition_mutex_);
339   if (!tracker_acquisition_condition_.wait_for(
340           lock, std::chrono::milliseconds(kAcquireBufferTimeoutMs),
341           [this, overridden_stream_id, num_buffers] {
342             return DoesStreamHaveEnoughBuffersToAcquireLocked(
343                 overridden_stream_id, num_buffers);
344           })) {
345     ALOGW("%s: Waiting to acquire buffer timed out.", __FUNCTION__);
346     return TIMED_OUT;
347   }
348 
349   stream_acquired_buffers_[overridden_stream_id] += num_buffers;
350 
351   return OK;
352 }
353 
TrackBufferAcquisitionFailure(int32_t stream_id,uint32_t num_buffers)354 void PendingRequestsTracker::TrackBufferAcquisitionFailure(int32_t stream_id,
355                                                            uint32_t num_buffers) {
356   int32_t overridden_stream_id = OverrideStreamIdForGroup(stream_id);
357   if (!IsStreamConfigured(overridden_stream_id)) {
358     ALOGW("%s: stream %d was not configured.", __FUNCTION__,
359           overridden_stream_id);
360     // Continue to track other buffers.
361     return;
362   }
363   if (hal_buffer_managed_stream_ids_.find(stream_id) ==
364       hal_buffer_managed_stream_ids_.end()) {
365     // Pending requests tracker doesn't track stream ids which aren't HAL buffer
366     // managed
367     return;
368   }
369   std::unique_lock<std::mutex> lock(pending_acquisition_mutex_);
370   stream_acquired_buffers_[overridden_stream_id] -= num_buffers;
371 }
372 
DumpStatus()373 void PendingRequestsTracker::DumpStatus() {
374   std::string pending_requests_string = "{";
375   {
376     std::lock_guard<std::mutex> lock(pending_requests_mutex_);
377     for (auto& [stream_id, num_pending_buffers] : stream_pending_buffers_) {
378       pending_requests_string += "{" + std::to_string(stream_id) + ": " +
379                                  std::to_string(num_pending_buffers) + "},";
380     }
381   }
382   pending_requests_string += "}";
383 
384   std::string pending_acquisition_string = "{";
385   {
386     std::lock_guard<std::mutex> lock(pending_acquisition_mutex_);
387     for (auto& [stream_id, num_acquired_buffers] : stream_acquired_buffers_) {
388       pending_acquisition_string += "{" + std::to_string(stream_id) + ": " +
389                                     std::to_string(num_acquired_buffers) + "},";
390     }
391   }
392   pending_acquisition_string += "}";
393 
394   ALOGI(
395       "%s: Buffers (including placeholder) pending return from HWL: %s. "
396       "Buffers "
397       "proactively acquired from the framework: %s.",
398       __FUNCTION__, pending_requests_string.c_str(),
399       pending_acquisition_string.c_str());
400 }
401 
402 }  // namespace google_camera_hal
403 }  // namespace android
404