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