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