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_ZslBufferManager"
19 #define ATRACE_TAG ATRACE_TAG_CAMERA
20 #include <cutils/properties.h>
21 #include <log/log.h>
22 #include <utils/Trace.h>
23
24 #include <time.h>
25
26 #include "zsl_buffer_manager.h"
27
28 namespace android {
29 namespace google_camera_hal {
30
ZslBufferManager(IHalBufferAllocator * allocator)31 ZslBufferManager::ZslBufferManager(IHalBufferAllocator* allocator)
32 : kMemoryProfilingEnabled(
33 property_get_bool("persist.camera.hal.memoryprofile", false)),
34 buffer_allocator_(allocator) {
35 }
36
~ZslBufferManager()37 ZslBufferManager::~ZslBufferManager() {
38 ATRACE_CALL();
39 std::unique_lock<std::mutex> lock(zsl_buffers_lock_);
40 if (buffer_allocator_ != nullptr) {
41 buffer_allocator_->FreeBuffers(&buffers_);
42 }
43 }
44
AllocateBuffers(const HalBufferDescriptor & buffer_descriptor)45 status_t ZslBufferManager::AllocateBuffers(
46 const HalBufferDescriptor& buffer_descriptor) {
47 ATRACE_CALL();
48 std::unique_lock<std::mutex> lock(zsl_buffers_lock_);
49
50 if (allocated_) {
51 ALOGE("%s: Buffer is already allocated.", __FUNCTION__);
52 return ALREADY_EXISTS;
53 }
54
55 // Create a buffer allocator if the client doesn't specify one.
56 if (buffer_allocator_ == nullptr) {
57 // Create a buffer manager.
58 internal_buffer_allocator_ = GrallocBufferAllocator::Create();
59 if (internal_buffer_allocator_ == nullptr) {
60 ALOGE("%s: Creating a buffer manager failed.", __FUNCTION__);
61 return NO_MEMORY;
62 }
63
64 buffer_allocator_ = internal_buffer_allocator_.get();
65 }
66
67 uint32_t num_buffers = buffer_descriptor.immediate_num_buffers;
68 buffer_descriptor_ = buffer_descriptor;
69 status_t res = AllocateBuffersLocked(num_buffers);
70 if (res != OK) {
71 ALOGE("%s: Allocating %d buffers failed.", __FUNCTION__, num_buffers);
72 return res;
73 }
74
75 allocated_ = true;
76 return OK;
77 }
78
AllocateBuffersLocked(uint32_t buffer_number)79 status_t ZslBufferManager::AllocateBuffersLocked(uint32_t buffer_number) {
80 if (buffer_number + buffers_.size() > buffer_descriptor_.max_num_buffers) {
81 ALOGE("%s: allocate %d + exist %zu > max buffer number %d", __FUNCTION__,
82 buffer_number, buffers_.size(), buffer_descriptor_.max_num_buffers);
83 return NO_MEMORY;
84 }
85
86 HalBufferDescriptor buffer_descriptor = buffer_descriptor_;
87 buffer_descriptor.immediate_num_buffers = buffer_number;
88 std::vector<buffer_handle_t> buffers;
89 status_t res = buffer_allocator_->AllocateBuffers(buffer_descriptor, &buffers);
90 if (res != OK) {
91 ALOGE("%s: AllocateBuffers fail.", __FUNCTION__);
92 return res;
93 }
94
95 for (auto& buffer : buffers) {
96 if (buffer != kInvalidBufferHandle) {
97 buffers_.push_back(buffer);
98 empty_zsl_buffers_.push_back(buffer);
99 }
100 }
101
102 if (buffers.size() != buffer_number) {
103 ALOGE("%s: allocate buffer failed. request %u, get %zu", __FUNCTION__,
104 buffer_number, buffers.size());
105 return NO_MEMORY;
106 }
107
108 if (kMemoryProfilingEnabled) {
109 ALOGI(
110 "%s: Allocated %u buffers, res %ux%u, format %d, overall allocated "
111 "%zu buffers",
112 __FUNCTION__, buffer_number, buffer_descriptor_.width,
113 buffer_descriptor_.height, buffer_descriptor_.format, buffers_.size());
114 }
115
116 return OK;
117 }
118
GetEmptyBuffer()119 buffer_handle_t ZslBufferManager::GetEmptyBuffer() {
120 ATRACE_CALL();
121 std::unique_lock<std::mutex> lock(zsl_buffers_lock_);
122 if (!allocated_) {
123 ALOGE("%s: Buffers are not allocated.", __FUNCTION__);
124 return kInvalidBufferHandle;
125 }
126
127 buffer_handle_t buffer = GetEmptyBufferLocked();
128 if (buffer == kInvalidBufferHandle) {
129 // Try to allocate one more buffer if there is no empty buffer.
130 status_t res = AllocateBuffersLocked(/*buffer_number=*/1);
131 if (res != OK) {
132 ALOGE("%s: Allocating one more buffer failed: %s(%d)", __FUNCTION__,
133 strerror(-res), res);
134 return kInvalidBufferHandle;
135 }
136
137 buffer = GetEmptyBufferLocked();
138 }
139
140 return buffer;
141 }
142
GetEmptyBufferLocked()143 buffer_handle_t ZslBufferManager::GetEmptyBufferLocked() {
144 ATRACE_CALL();
145 buffer_handle_t buffer = kInvalidBufferHandle;
146
147 // Get an empty buffer from empty ZSL buffer queue.
148 // If empty ZSL buffer queue is empty,
149 // Get the oldest buffer from filled ZSL buffer queue.
150 // If filled ZSL buffer queue is empty,
151 // Get the oldest buffer from the partially filled ZSL buffer queue.
152 if (empty_zsl_buffers_.size() > 0) {
153 buffer = empty_zsl_buffers_[0];
154 empty_zsl_buffers_.pop_front();
155 } else if (filled_zsl_buffers_.size() > 0) {
156 auto buffer_iter = filled_zsl_buffers_.begin();
157 buffer = buffer_iter->second.buffer.buffer;
158 filled_zsl_buffers_.erase(buffer_iter);
159 } else if (partially_filled_zsl_buffers_.size() > 0) {
160 auto buffer_iter = partially_filled_zsl_buffers_.begin();
161 while (buffer_iter != partially_filled_zsl_buffers_.end()) {
162 if (buffer_iter->second.metadata != nullptr) {
163 if (buffer_iter->second.buffer.buffer != kInvalidBufferHandle) {
164 ALOGE("%s: Invalid: both are ready in partial zsl queue.",
165 __FUNCTION__);
166 // TODO: clean up resources in this invalid situation.
167 return kInvalidBufferHandle;
168 }
169 ALOGI(
170 "%s: Remove metadata-only buffer in partially filled zsl "
171 "buffer queue. Releasing the metadata resource.",
172 __FUNCTION__);
173 } else if (buffer_iter->second.buffer.buffer == kInvalidBufferHandle) {
174 ALOGE(
175 "%s: Invalid: both buffer and metadata are empty in partial "
176 "zsl queue.",
177 __FUNCTION__);
178 // TODO: clean up resources in this invalid situation.
179 return kInvalidBufferHandle;
180 } else {
181 ALOGI(
182 "%s: Get buffer-only empty buffer from partially filled zsl "
183 "buffer queue.",
184 __FUNCTION__);
185 buffer = buffer_iter->second.buffer.buffer;
186 }
187
188 // remove whatever visited
189 buffer_iter = partially_filled_zsl_buffers_.erase(buffer_iter);
190
191 if (buffer != kInvalidBufferHandle) {
192 break;
193 }
194 }
195
196 if (buffer_iter == partially_filled_zsl_buffers_.end()) {
197 ALOGE("%s: No empty buffer available.", __FUNCTION__);
198 }
199 } else {
200 ALOGW("%s: No empty buffer available.", __FUNCTION__);
201 }
202
203 return buffer;
204 }
205
FreeUnusedBuffersLocked()206 void ZslBufferManager::FreeUnusedBuffersLocked() {
207 ATRACE_CALL();
208 if (empty_zsl_buffers_.size() <= kMaxUnusedBuffers ||
209 buffers_.size() <= buffer_descriptor_.immediate_num_buffers) {
210 return;
211 }
212
213 std::vector<buffer_handle_t> unused_buffers;
214
215 // When there are at least kMaxUnusedBuffers unused buffers, try to reduce
216 // the number of buffers to buffer_descriptor_.immediate_num_buffers.
217 while (buffers_.size() > buffer_descriptor_.immediate_num_buffers &&
218 empty_zsl_buffers_.size() > 0) {
219 buffer_handle_t buffer = empty_zsl_buffers_.back();
220 unused_buffers.push_back(buffer);
221 empty_zsl_buffers_.pop_back();
222 buffers_.erase(std::find(buffers_.begin(), buffers_.end(), buffer));
223 }
224
225 if (kMemoryProfilingEnabled) {
226 ALOGI(
227 "%s: Freeing %zu buffers, res %ux%u, format %d, overall allocated "
228 "%zu buffers",
229 __FUNCTION__, unused_buffers.size(), buffer_descriptor_.width,
230 buffer_descriptor_.height, buffer_descriptor_.format, buffers_.size());
231 }
232
233 buffer_allocator_->FreeBuffers(&unused_buffers);
234 }
235
ReturnEmptyBuffer(buffer_handle_t buffer)236 status_t ZslBufferManager::ReturnEmptyBuffer(buffer_handle_t buffer) {
237 ATRACE_CALL();
238 if (buffer == kInvalidBufferHandle) {
239 ALOGE("%s: buffer is nullptr.", __FUNCTION__);
240 return BAD_VALUE;
241 }
242
243 std::unique_lock<std::mutex> lock(zsl_buffers_lock_);
244 // Check whether the returned buffer is freed or not
245 auto exist_buffer = std::find(buffers_.begin(), buffers_.end(), buffer);
246 if (exist_buffer == buffers_.end()) {
247 ALOGE("%s: Buffer %p is invalid", __FUNCTION__, buffer);
248 return BAD_VALUE;
249 }
250
251 auto empty_buffer = std::find(std::begin(empty_zsl_buffers_),
252 std::end(empty_zsl_buffers_), buffer);
253 if (empty_buffer != std::end(empty_zsl_buffers_)) {
254 ALOGE("%s: Buffer %p was already returned.", __FUNCTION__, buffer);
255 return ALREADY_EXISTS;
256 }
257
258 empty_zsl_buffers_.push_back(buffer);
259 FreeUnusedBuffersLocked();
260 return OK;
261 }
262
ReturnFilledBuffer(uint32_t frame_number,const StreamBuffer & buffer)263 status_t ZslBufferManager::ReturnFilledBuffer(uint32_t frame_number,
264 const StreamBuffer& buffer) {
265 ATRACE_CALL();
266 ZslBuffer zsl_buffer = {};
267 zsl_buffer.frame_number = frame_number;
268 zsl_buffer.buffer = buffer;
269
270 std::unique_lock<std::mutex> lock(zsl_buffers_lock_);
271 if (partially_filled_zsl_buffers_.empty() ||
272 partially_filled_zsl_buffers_.find(frame_number) ==
273 partially_filled_zsl_buffers_.end()) {
274 // not able to distinguish these two cases through the current status
275 // of the partial buffer
276 ALOGV(
277 "%s: no entry for frame[%u] in ZslBufferManager. Not created or "
278 "has been removed",
279 __FUNCTION__, frame_number);
280
281 zsl_buffer.metadata = nullptr;
282 partially_filled_zsl_buffers_[frame_number] = std::move(zsl_buffer);
283 } else if (partially_filled_zsl_buffers_[frame_number].buffer.buffer ==
284 kInvalidBufferHandle &&
285 partially_filled_zsl_buffers_[frame_number].metadata != nullptr) {
286 ALOGV(
287 "%s: both buffer and metadata for frame[%u] are ready. Move to "
288 "filled_zsl_buffers_.",
289 __FUNCTION__, frame_number);
290
291 zsl_buffer.metadata =
292 std::move(partially_filled_zsl_buffers_[frame_number].metadata);
293 filled_zsl_buffers_[frame_number] = std::move(zsl_buffer);
294 partially_filled_zsl_buffers_.erase(frame_number);
295 } else {
296 ALOGE(
297 "%s: the buffer for frame[%u] already returned or the metadata is "
298 "missing.",
299 __FUNCTION__, frame_number);
300 return INVALID_OPERATION;
301 }
302
303 return OK;
304 }
305
ReturnMetadata(uint32_t frame_number,const HalCameraMetadata * metadata)306 status_t ZslBufferManager::ReturnMetadata(uint32_t frame_number,
307 const HalCameraMetadata* metadata) {
308 ATRACE_CALL();
309 std::unique_lock<std::mutex> lock(zsl_buffers_lock_);
310
311 ZslBuffer zsl_buffer = {};
312 zsl_buffer.frame_number = frame_number;
313 zsl_buffer.metadata = HalCameraMetadata::Clone(metadata);
314 if (zsl_buffer.metadata == nullptr) {
315 ALOGE("%s: Failed to Clone camera metadata.", __FUNCTION__);
316 return NO_MEMORY;
317 }
318
319 if (partially_filled_zsl_buffers_.empty() ||
320 partially_filled_zsl_buffers_.find(frame_number) ==
321 partially_filled_zsl_buffers_.end()) {
322 // not able to distinguish these two cases through the current status of
323 // the partial buffer
324 ALOGV(
325 "%s: no entry for frame[%u] in ZslBufferManager. Not created or "
326 "has been removed",
327 __FUNCTION__, frame_number);
328
329 zsl_buffer.buffer = {};
330 partially_filled_zsl_buffers_[frame_number] = std::move(zsl_buffer);
331 } else if (partially_filled_zsl_buffers_[frame_number].metadata == nullptr &&
332 partially_filled_zsl_buffers_[frame_number].buffer.buffer !=
333 kInvalidBufferHandle) {
334 ALOGV(
335 "%s: both buffer and metadata for frame[%u] are ready. Move to "
336 "filled_zsl_buffers_.",
337 __FUNCTION__, frame_number);
338
339 zsl_buffer.buffer = partially_filled_zsl_buffers_[frame_number].buffer;
340 filled_zsl_buffers_[frame_number] = std::move(zsl_buffer);
341 partially_filled_zsl_buffers_.erase(frame_number);
342 } else {
343 ALOGE(
344 "%s: the metadata for frame[%u] already returned or the buffer is "
345 "missing.",
346 __FUNCTION__, frame_number);
347 return INVALID_OPERATION;
348 }
349
350 if (partially_filled_zsl_buffers_.size() > kMaxPartialZslBuffers) {
351 // Remove the oldest one if it exceeds the maximum number of partial ZSL
352 // buffers.
353 partially_filled_zsl_buffers_.erase(partially_filled_zsl_buffers_.begin());
354 }
355
356 return OK;
357 }
358
GetCurrentTimestampNs(int64_t * current_timestamp)359 status_t ZslBufferManager::GetCurrentTimestampNs(int64_t* current_timestamp) {
360 if (current_timestamp == nullptr) {
361 ALOGE("%s: current_timestamp is nullptr", __FUNCTION__);
362 return BAD_VALUE;
363 }
364
365 struct timespec ts;
366 if (clock_gettime(CLOCK_BOOTTIME, &ts)) {
367 ALOGE("%s: Getting boot time failed.", __FUNCTION__);
368 return UNKNOWN_ERROR;
369 }
370
371 static const int64_t kNsPerSec = 1000000000;
372 *current_timestamp = ts.tv_sec * kNsPerSec + ts.tv_nsec;
373 return OK;
374 }
375
GetMostRecentZslBuffers(std::vector<ZslBuffer> * zsl_buffers,uint32_t num_buffers,uint32_t min_buffers)376 void ZslBufferManager::GetMostRecentZslBuffers(
377 std::vector<ZslBuffer>* zsl_buffers, uint32_t num_buffers,
378 uint32_t min_buffers) {
379 ATRACE_CALL();
380 if (zsl_buffers == nullptr) {
381 return;
382 }
383
384 int64_t current_timestamp;
385 status_t res = GetCurrentTimestampNs(¤t_timestamp);
386 if (res != OK) {
387 ALOGE("%s: Getting current timestamp failed: %s(%d)", __FUNCTION__,
388 strerror(-res), res);
389 return;
390 }
391
392 std::unique_lock<std::mutex> lock(zsl_buffers_lock_);
393 if (filled_zsl_buffers_.size() < min_buffers) {
394 ALOGD("%s: Requested min_buffers = %u, ZslBufferManager only has %zu",
395 __FUNCTION__, min_buffers, filled_zsl_buffers_.size());
396 ALOGD("%s: Not enough ZSL buffers to get, returns empty zsl_buffers.",
397 __FUNCTION__);
398 return;
399 }
400
401 num_buffers =
402 std::min(static_cast<uint32_t>(filled_zsl_buffers_.size()), num_buffers);
403 auto zsl_buffer_iter = filled_zsl_buffers_.begin();
404
405 // Skip the older ones.
406 for (uint32_t i = 0; i < filled_zsl_buffers_.size() - num_buffers; i++) {
407 zsl_buffer_iter++;
408 }
409
410 // Fallback to realtime pipeline capture if there are any flash-fired frame
411 // in zsl buffers with AE_MODE_ON_AUTO_FLASH.
412 camera_metadata_ro_entry entry = {};
413 res = zsl_buffer_iter->second.metadata->Get(ANDROID_CONTROL_AE_MODE, &entry);
414 if (res == OK && entry.data.u8[0] == ANDROID_CONTROL_AE_MODE_ON_AUTO_FLASH) {
415 for (auto search_iter = filled_zsl_buffers_.begin();
416 search_iter != filled_zsl_buffers_.end(); search_iter++) {
417 res = search_iter->second.metadata->Get(ANDROID_FLASH_STATE, &entry);
418 if (res == OK && entry.count == 1) {
419 if (entry.data.u8[0] == ANDROID_FLASH_STATE_FIRED) {
420 ALOGD("%s: Returns empty zsl_buffers due to flash fired",
421 __FUNCTION__);
422 return;
423 }
424 }
425 }
426 }
427
428 for (uint32_t i = 0; i < num_buffers; i++) {
429 camera_metadata_ro_entry entry = {};
430 int64_t buffer_timestamp;
431 res =
432 zsl_buffer_iter->second.metadata->Get(ANDROID_SENSOR_TIMESTAMP, &entry);
433 if (res != OK || entry.count != 1) {
434 ALOGW("%s: Getting sensor timestamp failed: %s(%d)", __FUNCTION__,
435 strerror(-res), res);
436 return;
437 }
438
439 buffer_timestamp = entry.data.i64[0];
440 // Only include recent buffers.
441 if (current_timestamp - buffer_timestamp < kMaxBufferTimestampDiff) {
442 zsl_buffers->push_back(std::move(zsl_buffer_iter->second));
443 }
444
445 zsl_buffer_iter = filled_zsl_buffers_.erase(zsl_buffer_iter);
446 }
447 }
448
ReturnZslBuffer(ZslBuffer zsl_buffer)449 void ZslBufferManager::ReturnZslBuffer(ZslBuffer zsl_buffer) {
450 ATRACE_CALL();
451 std::unique_lock<std::mutex> lock(zsl_buffers_lock_);
452 filled_zsl_buffers_[zsl_buffer.frame_number] = std::move(zsl_buffer);
453 }
454
ReturnZslBuffers(std::vector<ZslBuffer> zsl_buffers)455 void ZslBufferManager::ReturnZslBuffers(std::vector<ZslBuffer> zsl_buffers) {
456 ATRACE_CALL();
457 for (auto& zsl_buffer : zsl_buffers) {
458 ReturnZslBuffer(std::move(zsl_buffer));
459 }
460 }
461
IsPendingBufferEmpty()462 bool ZslBufferManager::IsPendingBufferEmpty() {
463 std::lock_guard<std::mutex> lock(pending_zsl_buffers_mutex);
464 bool empty = (pending_zsl_buffers_.size() == 0);
465 if (!empty) {
466 ALOGW("%s: Pending buffer is not empty:%zu.", __FUNCTION__,
467 pending_zsl_buffers_.size());
468 return false;
469 }
470
471 return true;
472 }
473
AddPendingBuffers(const std::vector<ZslBuffer> & buffers)474 void ZslBufferManager::AddPendingBuffers(const std::vector<ZslBuffer>& buffers) {
475 ATRACE_CALL();
476 std::lock_guard<std::mutex> lock(pending_zsl_buffers_mutex);
477 for (auto& buffer : buffers) {
478 ZslBuffer zsl_buffer = {
479 .frame_number = buffer.frame_number,
480 .buffer = buffer.buffer,
481 .metadata = HalCameraMetadata::Clone(buffer.metadata.get()),
482 };
483
484 pending_zsl_buffers_.emplace(buffer.buffer.buffer, std::move(zsl_buffer));
485 }
486 }
487
CleanPendingBuffers(std::vector<ZslBuffer> * buffers)488 status_t ZslBufferManager::CleanPendingBuffers(std::vector<ZslBuffer>* buffers) {
489 ATRACE_CALL();
490 if (buffers == nullptr) {
491 ALOGE("%s: buffers is nullptr", __FUNCTION__);
492 return BAD_VALUE;
493 }
494
495 std::lock_guard<std::mutex> lock(pending_zsl_buffers_mutex);
496 if (pending_zsl_buffers_.empty()) {
497 ALOGE("%s: There is no empty buffer.", __FUNCTION__);
498 return BAD_VALUE;
499 }
500
501 for (auto zsl_buffer_iter = pending_zsl_buffers_.begin();
502 zsl_buffer_iter != pending_zsl_buffers_.end(); zsl_buffer_iter++) {
503 buffers->push_back(std::move(zsl_buffer_iter->second));
504 }
505
506 pending_zsl_buffers_.clear();
507 return OK;
508 }
509
510 } // namespace google_camera_hal
511 } // namespace android
512