1 /*
2 * Copyright (C) 2018 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 "C2BqBuffer"
19 #include <android/hardware_buffer.h>
20 #include <utils/Log.h>
21
22 #include <ui/BufferQueueDefs.h>
23 #include <ui/GraphicBuffer.h>
24 #include <ui/Fence.h>
25
26 #include <types.h>
27
28 #include <hidl/HidlSupport.h>
29
30 #include <C2AllocatorGralloc.h>
31 #include <C2BqBufferPriv.h>
32 #include <C2BlockInternal.h>
33 #include <C2FenceFactory.h>
34 #include <C2SurfaceSyncObj.h>
35
36 #include <list>
37 #include <map>
38 #include <mutex>
39
40 using ::android::BufferQueueDefs::NUM_BUFFER_SLOTS;
41 using ::android::C2AllocatorGralloc;
42 using ::android::C2AndroidMemoryUsage;
43 using ::android::Fence;
44 using ::android::GraphicBuffer;
45 using ::android::sp;
46 using ::android::status_t;
47 using ::android::wp;
48 using ::android::hardware::hidl_handle;
49 using ::android::hardware::Return;
50
51 using HBuffer = ::android::hardware::graphics::common::V1_2::HardwareBuffer;
52 using HStatus = ::android::hardware::graphics::bufferqueue::V2_0::Status;
53 using ::android::hardware::graphics::bufferqueue::V2_0::utils::b2h;
54 using ::android::hardware::graphics::bufferqueue::V2_0::utils::h2b;
55 using ::android::hardware::graphics::bufferqueue::V2_0::utils::HFenceWrapper;
56
57 using HGraphicBufferProducer = ::android::hardware::graphics::bufferqueue::V2_0
58 ::IGraphicBufferProducer;
59
GetBufferQueueData(const std::shared_ptr<const _C2BlockPoolData> & data,uint32_t * generation,uint64_t * bqId,int32_t * bqSlot)60 bool _C2BlockFactory::GetBufferQueueData(
61 const std::shared_ptr<const _C2BlockPoolData>& data,
62 uint32_t* generation, uint64_t* bqId, int32_t* bqSlot) {
63 if (data && data->getType() == _C2BlockPoolData::TYPE_BUFFERQUEUE) {
64 const std::shared_ptr<const C2BufferQueueBlockPoolData> poolData =
65 std::static_pointer_cast<const C2BufferQueueBlockPoolData>(data);
66 poolData->getBufferQueueData(generation, bqId, bqSlot);
67 return true;
68 }
69 return false;
70 }
71
HoldBlockFromBufferQueue(const std::shared_ptr<_C2BlockPoolData> & data,const std::shared_ptr<int> & owner,const sp<HGraphicBufferProducer> & igbp,std::shared_ptr<C2SurfaceSyncMemory> syncMem)72 bool _C2BlockFactory::HoldBlockFromBufferQueue(
73 const std::shared_ptr<_C2BlockPoolData>& data,
74 const std::shared_ptr<int>& owner,
75 const sp<HGraphicBufferProducer>& igbp,
76 std::shared_ptr<C2SurfaceSyncMemory> syncMem) {
77 const std::shared_ptr<C2BufferQueueBlockPoolData> poolData =
78 std::static_pointer_cast<C2BufferQueueBlockPoolData>(data);
79 return poolData->holdBlockFromBufferQueue(owner, igbp, syncMem);
80 }
81
BeginTransferBlockToClient(const std::shared_ptr<_C2BlockPoolData> & data)82 bool _C2BlockFactory::BeginTransferBlockToClient(
83 const std::shared_ptr<_C2BlockPoolData>& data) {
84 const std::shared_ptr<C2BufferQueueBlockPoolData> poolData =
85 std::static_pointer_cast<C2BufferQueueBlockPoolData>(data);
86 return poolData->beginTransferBlockToClient();
87 }
88
EndTransferBlockToClient(const std::shared_ptr<_C2BlockPoolData> & data,bool transfer)89 bool _C2BlockFactory::EndTransferBlockToClient(
90 const std::shared_ptr<_C2BlockPoolData>& data,
91 bool transfer) {
92 const std::shared_ptr<C2BufferQueueBlockPoolData> poolData =
93 std::static_pointer_cast<C2BufferQueueBlockPoolData>(data);
94 return poolData->endTransferBlockToClient(transfer);
95 }
96
BeginAttachBlockToBufferQueue(const std::shared_ptr<_C2BlockPoolData> & data)97 bool _C2BlockFactory::BeginAttachBlockToBufferQueue(
98 const std::shared_ptr<_C2BlockPoolData>& data) {
99 const std::shared_ptr<C2BufferQueueBlockPoolData> poolData =
100 std::static_pointer_cast<C2BufferQueueBlockPoolData>(data);
101 return poolData->beginAttachBlockToBufferQueue();
102 }
103
104 // if display was tried during attach, buffer should be retired ASAP.
EndAttachBlockToBufferQueue(const std::shared_ptr<_C2BlockPoolData> & data,const std::shared_ptr<int> & owner,const sp<HGraphicBufferProducer> & igbp,std::shared_ptr<C2SurfaceSyncMemory> syncMem,uint32_t generation,uint64_t bqId,int32_t bqSlot)105 bool _C2BlockFactory::EndAttachBlockToBufferQueue(
106 const std::shared_ptr<_C2BlockPoolData>& data,
107 const std::shared_ptr<int>& owner,
108 const sp<HGraphicBufferProducer>& igbp,
109 std::shared_ptr<C2SurfaceSyncMemory> syncMem,
110 uint32_t generation,
111 uint64_t bqId,
112 int32_t bqSlot) {
113 const std::shared_ptr<C2BufferQueueBlockPoolData> poolData =
114 std::static_pointer_cast<C2BufferQueueBlockPoolData>(data);
115 return poolData->endAttachBlockToBufferQueue(owner, igbp, syncMem, generation, bqId, bqSlot);
116 }
117
DisplayBlockToBufferQueue(const std::shared_ptr<_C2BlockPoolData> & data)118 bool _C2BlockFactory::DisplayBlockToBufferQueue(
119 const std::shared_ptr<_C2BlockPoolData>& data) {
120 const std::shared_ptr<C2BufferQueueBlockPoolData> poolData =
121 std::static_pointer_cast<C2BufferQueueBlockPoolData>(data);
122 return poolData->displayBlockToBufferQueue();
123 }
124
CreateGraphicBlock(const C2Handle * handle)125 std::shared_ptr<C2GraphicBlock> _C2BlockFactory::CreateGraphicBlock(
126 const C2Handle *handle) {
127 // TODO: get proper allocator? and mutex?
128 static std::unique_ptr<C2AllocatorGralloc> sAllocator = std::make_unique<C2AllocatorGralloc>(0);
129
130 std::shared_ptr<C2GraphicAllocation> alloc;
131 if (C2AllocatorGralloc::CheckHandle(handle)) {
132 uint32_t width;
133 uint32_t height;
134 uint32_t format;
135 uint64_t usage;
136 uint32_t stride;
137 uint32_t generation;
138 uint64_t bqId;
139 uint32_t bqSlot;
140 android::_UnwrapNativeCodec2GrallocMetadata(
141 handle, &width, &height, &format, &usage, &stride, &generation, &bqId, &bqSlot);
142 c2_status_t err = sAllocator->priorGraphicAllocation(handle, &alloc);
143 if (err == C2_OK) {
144 std::shared_ptr<C2GraphicBlock> block;
145 if (bqId || bqSlot) {
146 // BQBBP
147 std::shared_ptr<C2BufferQueueBlockPoolData> poolData =
148 std::make_shared<C2BufferQueueBlockPoolData>(generation,
149 bqId,
150 (int32_t)bqSlot,
151 nullptr,
152 nullptr);
153 block = _C2BlockFactory::CreateGraphicBlock(alloc, poolData);
154 } else {
155 block = _C2BlockFactory::CreateGraphicBlock(alloc);
156 }
157 return block;
158 }
159 }
160 return nullptr;
161 }
162
163 namespace {
164
getTimestampNow()165 int64_t getTimestampNow() {
166 int64_t stamp;
167 struct timespec ts;
168 // TODO: CLOCK_MONOTONIC_COARSE?
169 clock_gettime(CLOCK_MONOTONIC, &ts);
170 stamp = ts.tv_nsec / 1000;
171 stamp += (ts.tv_sec * 1000000LL);
172 return stamp;
173 }
174
175 // Do not rely on AHardwareBuffer module for GraphicBuffer handling since AHardwareBuffer
176 // module is linked to framework which could have a different implementation of GraphicBuffer
177 // than mainline/vndk implementation.(See b/203347494.)
178 //
179 // b2h/h2b between HardwareBuffer and GraphicBuffer cannot be used. (b2h/h2b depend on
180 // AHardwareBuffer module for the conversion between HardwareBuffer and GraphicBuffer.)
181 // hgbp_ prefixed methods are added to be used instead of b2h/h2b.
182 //
183 // TODO: Remove dependency with existing AHwB module. Also clean up conversions.(conversions here
184 // and h2b/b2h coversions)
hgbp_AHBuffer_to_GraphicBuffer(const AHardwareBuffer * buffer)185 const GraphicBuffer* hgbp_AHBuffer_to_GraphicBuffer(const AHardwareBuffer* buffer) {
186 return GraphicBuffer::fromAHardwareBuffer(buffer);
187 }
188
hgbp_createFromHandle(const AHardwareBuffer_Desc * desc,const native_handle_t * handle,sp<GraphicBuffer> * outBuffer)189 int hgbp_createFromHandle(const AHardwareBuffer_Desc* desc,
190 const native_handle_t* handle,
191 sp<GraphicBuffer> *outBuffer) {
192
193 if (!desc || !handle || !outBuffer) return ::android::BAD_VALUE;
194 if (desc->rfu0 != 0 || desc->rfu1 != 0) return ::android::BAD_VALUE;
195 if (desc->format == AHARDWAREBUFFER_FORMAT_BLOB && desc->height != 1)
196 return ::android::BAD_VALUE;
197
198 const int format = uint32_t(desc->format);
199 const uint64_t usage = uint64_t(desc->usage);
200 sp<GraphicBuffer> gbuffer(new GraphicBuffer(handle,
201 GraphicBuffer::HandleWrapMethod::CLONE_HANDLE,
202 desc->width, desc->height,
203 format, desc->layers, usage, desc->stride));
204 status_t err = gbuffer->initCheck();
205 if (err != 0 || gbuffer->handle == 0) return err;
206
207 *outBuffer = gbuffer;
208
209 return ::android::NO_ERROR;
210 }
211
hgbp_describe(const AHardwareBuffer * buffer,AHardwareBuffer_Desc * outDesc)212 void hgbp_describe(const AHardwareBuffer* buffer,
213 AHardwareBuffer_Desc* outDesc) {
214 if (!buffer || !outDesc) return;
215
216 const GraphicBuffer* gbuffer = hgbp_AHBuffer_to_GraphicBuffer(buffer);
217
218 outDesc->width = gbuffer->getWidth();
219 outDesc->height = gbuffer->getHeight();
220 outDesc->layers = gbuffer->getLayerCount();
221 outDesc->format = uint32_t(gbuffer->getPixelFormat());
222 outDesc->usage = uint64_t(gbuffer->getUsage());
223 outDesc->stride = gbuffer->getStride();
224 outDesc->rfu0 = 0;
225 outDesc->rfu1 = 0;
226 }
227
228
hgbp_h2b(HBuffer const & from,sp<GraphicBuffer> * to)229 bool hgbp_h2b(HBuffer const& from, sp<GraphicBuffer>* to) {
230 AHardwareBuffer_Desc const* desc =
231 reinterpret_cast<AHardwareBuffer_Desc const*>(
232 from.description.data());
233 native_handle_t const* handle = from.nativeHandle;
234 if (hgbp_createFromHandle(desc, handle, to) != ::android::OK) {
235 return false;
236 }
237 return true;
238 }
239
hgbp_b2h(sp<GraphicBuffer> const & from,HBuffer * to,uint32_t * toGenerationNumber)240 bool hgbp_b2h(sp<GraphicBuffer> const& from, HBuffer* to,
241 uint32_t* toGenerationNumber) {
242 if (!from) {
243 return false;
244 }
245 AHardwareBuffer* hwBuffer = from->toAHardwareBuffer();
246 to->nativeHandle.setTo(
247 const_cast<native_handle_t*>(from->handle),
248 false);
249 hgbp_describe(
250 hwBuffer,
251 reinterpret_cast<AHardwareBuffer_Desc*>(to->description.data()));
252 if (toGenerationNumber) {
253 *toGenerationNumber = from->getGenerationNumber();
254 }
255 return true;
256 }
257
258 // End of hgbp methods for GraphicBuffer creation.
259
getGenerationNumberAndUsage(const sp<HGraphicBufferProducer> & producer,uint32_t * generation,uint64_t * usage)260 bool getGenerationNumberAndUsage(const sp<HGraphicBufferProducer> &producer,
261 uint32_t *generation, uint64_t *usage) {
262 status_t status{};
263 int slot{};
264 bool bufferNeedsReallocation{};
265 sp<Fence> fence = new Fence();
266
267 using Input = HGraphicBufferProducer::DequeueBufferInput;
268 using Output = HGraphicBufferProducer::DequeueBufferOutput;
269 Return<void> transResult = producer->dequeueBuffer(
270 Input{640, 480, HAL_PIXEL_FORMAT_YCBCR_420_888, 0},
271 [&status, &slot, &bufferNeedsReallocation, &fence]
272 (HStatus hStatus, int32_t hSlot, Output const& hOutput) {
273 slot = static_cast<int>(hSlot);
274 if (!h2b(hStatus, &status) || !h2b(hOutput.fence, &fence)) {
275 status = ::android::BAD_VALUE;
276 } else {
277 bufferNeedsReallocation =
278 hOutput.bufferNeedsReallocation;
279 }
280 });
281 if (!transResult.isOk() || status != android::OK) {
282 return false;
283 }
284 HFenceWrapper hFenceWrapper{};
285 if (!b2h(fence, &hFenceWrapper)) {
286 (void)producer->detachBuffer(static_cast<int32_t>(slot)).isOk();
287 ALOGE("Invalid fence received from dequeueBuffer.");
288 return false;
289 }
290 sp<GraphicBuffer> slotBuffer = new GraphicBuffer();
291 // N.B. This assumes requestBuffer# returns an existing allocation
292 // instead of a new allocation.
293 transResult = producer->requestBuffer(
294 slot,
295 [&status, &slotBuffer, &generation, &usage](
296 HStatus hStatus,
297 HBuffer const& hBuffer,
298 uint32_t generationNumber){
299 if (h2b(hStatus, &status) &&
300 hgbp_h2b(hBuffer, &slotBuffer) &&
301 slotBuffer) {
302 *generation = generationNumber;
303 *usage = slotBuffer->getUsage();
304 slotBuffer->setGenerationNumber(generationNumber);
305 } else {
306 status = android::BAD_VALUE;
307 }
308 });
309 if (!transResult.isOk()) {
310 return false;
311 } else if (status != android::NO_ERROR) {
312 (void)producer->detachBuffer(static_cast<int32_t>(slot)).isOk();
313 return false;
314 }
315 (void)producer->detachBuffer(static_cast<int32_t>(slot)).isOk();
316 return true;
317 }
318
319 };
320
321 class C2BufferQueueBlockPool::Impl
322 : public std::enable_shared_from_this<C2BufferQueueBlockPool::Impl> {
323 private:
dequeueBuffer(uint32_t width,uint32_t height,uint32_t format,C2AndroidMemoryUsage androidUsage,int * slot,bool * needsRealloc,sp<Fence> * fence)324 c2_status_t dequeueBuffer(
325 uint32_t width,
326 uint32_t height,
327 uint32_t format,
328 C2AndroidMemoryUsage androidUsage,
329 int *slot, bool *needsRealloc, sp<Fence> *fence) {
330 status_t status{};
331 using Input = HGraphicBufferProducer::DequeueBufferInput;
332 using Output = HGraphicBufferProducer::DequeueBufferOutput;
333 Return<void> transResult = mProducer->dequeueBuffer(
334 Input{
335 width,
336 height,
337 format,
338 androidUsage.asGrallocUsage()},
339 [&status, slot, needsRealloc,
340 fence](HStatus hStatus,
341 int32_t hSlot,
342 Output const& hOutput) {
343 *slot = static_cast<int>(hSlot);
344 if (!h2b(hStatus, &status) ||
345 !h2b(hOutput.fence, fence)) {
346 status = ::android::BAD_VALUE;
347 } else {
348 *needsRealloc =
349 hOutput.bufferNeedsReallocation;
350 }
351 });
352 if (!transResult.isOk() || status != android::OK) {
353 if (transResult.isOk()) {
354 ++mDqFailure;
355 if (status == android::INVALID_OPERATION ||
356 status == android::TIMED_OUT ||
357 status == android::WOULD_BLOCK) {
358 // Dequeue buffer is blocked temporarily. Retrying is
359 // required.
360 return C2_BLOCKING;
361 }
362 }
363 ALOGD("cannot dequeue buffer %d", status);
364 return C2_BAD_VALUE;
365 }
366 return C2_OK;
367 }
368
fetchFromIgbp_l(uint32_t width,uint32_t height,uint32_t format,C2MemoryUsage usage,std::shared_ptr<C2GraphicBlock> * block,C2Fence * c2Fence)369 c2_status_t fetchFromIgbp_l(
370 uint32_t width,
371 uint32_t height,
372 uint32_t format,
373 C2MemoryUsage usage,
374 std::shared_ptr<C2GraphicBlock> *block /* nonnull */,
375 C2Fence *c2Fence) {
376 // We have an IGBP now.
377 C2AndroidMemoryUsage androidUsage = usage;
378 status_t status{};
379 int slot{};
380 bool bufferNeedsReallocation{};
381 sp<Fence> fence = new Fence();
382 ALOGV("tries to dequeue buffer");
383
384 C2SyncVariables *syncVar = mSyncMem ? mSyncMem->mem(): nullptr;
385 { // Call dequeueBuffer().
386 c2_status_t c2Status;
387 if (syncVar) {
388 uint32_t waitId;
389 syncVar->lock();
390 if (!syncVar->isDequeueableLocked(&waitId)) {
391 syncVar->unlock();
392 if (c2Fence) {
393 *c2Fence = _C2FenceFactory::CreateSurfaceFence(mSyncMem, waitId);
394 }
395 return C2_BLOCKING;
396 }
397 if (syncVar->getSyncStatusLocked() != C2SyncVariables::STATUS_ACTIVE) {
398 waitId = syncVar->getWaitIdLocked();
399 syncVar->unlock();
400 if (c2Fence) {
401 *c2Fence = _C2FenceFactory::CreateSurfaceFence(mSyncMem, waitId);
402 }
403 return C2_BLOCKING;
404 }
405 syncVar->notifyDequeuedLocked();
406 syncVar->unlock();
407 c2Status = dequeueBuffer(width, height, format, androidUsage,
408 &slot, &bufferNeedsReallocation, &fence);
409 if (c2Status != C2_OK) {
410 syncVar->lock();
411 syncVar->notifyQueuedLocked();
412 syncVar->unlock();
413 }
414 } else {
415 c2Status = dequeueBuffer(width, height, format, usage,
416 &slot, &bufferNeedsReallocation, &fence);
417 }
418 if (c2Status != C2_OK) {
419 return c2Status;
420 }
421 mDqFailure = 0;
422 mLastDqTs = getTimestampNow();
423 }
424 HFenceWrapper hFenceWrapper{};
425 if (!b2h(fence, &hFenceWrapper)) {
426 ALOGE("Invalid fence received from dequeueBuffer.");
427 return C2_BAD_VALUE;
428 }
429 ALOGV("dequeued a buffer successfully");
430 bool dequeueable = false;
431 uint32_t waitId;
432 if (fence) {
433 static constexpr int kFenceWaitTimeMs = 10;
434
435 if (bufferNeedsReallocation) {
436 mBuffers[slot].clear();
437 }
438
439 status_t status = fence->wait(kFenceWaitTimeMs);
440 if (status == -ETIME) {
441 // fence is not signalled yet.
442 if (syncVar) {
443 (void)mProducer->cancelBuffer(slot, hFenceWrapper.getHandle()).isOk();
444 syncVar->lock();
445 dequeueable = syncVar->notifyQueuedLocked(&waitId);
446 syncVar->unlock();
447 if (c2Fence) {
448 *c2Fence = dequeueable ? C2Fence() :
449 _C2FenceFactory::CreateSurfaceFence(mSyncMem, waitId);
450 }
451 } else {
452 (void)mProducer->cancelBuffer(slot, hFenceWrapper.getHandle()).isOk();
453 }
454 return C2_BLOCKING;
455 }
456 if (status != android::NO_ERROR) {
457 ALOGD("buffer fence wait error %d", status);
458 if (syncVar) {
459 (void)mProducer->cancelBuffer(slot, hFenceWrapper.getHandle()).isOk();
460 syncVar->lock();
461 syncVar->notifyQueuedLocked();
462 syncVar->unlock();
463 if (c2Fence) {
464 *c2Fence = C2Fence();
465 }
466 } else {
467 (void)mProducer->cancelBuffer(slot, hFenceWrapper.getHandle()).isOk();
468 }
469 return C2_BAD_VALUE;
470 } else if (mRenderCallback) {
471 nsecs_t signalTime = fence->getSignalTime();
472 if (signalTime >= 0 && signalTime < INT64_MAX) {
473 mRenderCallback(mProducerId, slot, signalTime);
474 } else {
475 ALOGV("got fence signal time of %lld", (long long)signalTime);
476 }
477 }
478 }
479
480 sp<GraphicBuffer> &slotBuffer = mBuffers[slot];
481 uint32_t outGeneration;
482 if (bufferNeedsReallocation || !slotBuffer) {
483 if (!slotBuffer) {
484 slotBuffer = new GraphicBuffer();
485 }
486 // N.B. This assumes requestBuffer# returns an existing allocation
487 // instead of a new allocation.
488 Return<void> transResult = mProducer->requestBuffer(
489 slot,
490 [&status, &slotBuffer, &outGeneration](
491 HStatus hStatus,
492 HBuffer const& hBuffer,
493 uint32_t generationNumber){
494 if (h2b(hStatus, &status) &&
495 hgbp_h2b(hBuffer, &slotBuffer) &&
496 slotBuffer) {
497 slotBuffer->setGenerationNumber(generationNumber);
498 outGeneration = generationNumber;
499 } else {
500 status = android::BAD_VALUE;
501 }
502 });
503 if (!transResult.isOk()) {
504 slotBuffer.clear();
505 return C2_BAD_VALUE;
506 } else if (status != android::NO_ERROR) {
507 slotBuffer.clear();
508 if (syncVar) {
509 (void)mProducer->cancelBuffer(slot, hFenceWrapper.getHandle()).isOk();
510 syncVar->lock();
511 syncVar->notifyQueuedLocked();
512 syncVar->unlock();
513 if (c2Fence) {
514 *c2Fence = C2Fence();
515 }
516 } else {
517 (void)mProducer->cancelBuffer(slot, hFenceWrapper.getHandle()).isOk();
518 }
519 return C2_BAD_VALUE;
520 }
521 if (mGeneration == 0) {
522 // getting generation # lazily due to dequeue failure.
523 mGeneration = outGeneration;
524 }
525 }
526 if (slotBuffer) {
527 ALOGV("buffer wraps %llu %d", (unsigned long long)mProducerId, slot);
528 C2Handle *c2Handle = android::WrapNativeCodec2GrallocHandle(
529 slotBuffer->handle,
530 slotBuffer->width,
531 slotBuffer->height,
532 slotBuffer->format,
533 slotBuffer->usage,
534 slotBuffer->stride,
535 slotBuffer->getGenerationNumber(),
536 mProducerId, slot);
537 if (c2Handle) {
538 std::shared_ptr<C2GraphicAllocation> alloc;
539 c2_status_t err = mAllocator->priorGraphicAllocation(c2Handle, &alloc);
540 if (err != C2_OK) {
541 native_handle_close(c2Handle);
542 native_handle_delete(c2Handle);
543 return err;
544 }
545 std::shared_ptr<C2BufferQueueBlockPoolData> poolData =
546 std::make_shared<C2BufferQueueBlockPoolData>(
547 slotBuffer->getGenerationNumber(),
548 mProducerId, slot,
549 mIgbpValidityToken, mProducer, mSyncMem);
550 mPoolDatas[slot] = poolData;
551 *block = _C2BlockFactory::CreateGraphicBlock(alloc, poolData);
552 return C2_OK;
553 }
554 // Block was not created. call requestBuffer# again next time.
555 slotBuffer.clear();
556 if (syncVar) {
557 (void)mProducer->cancelBuffer(slot, hFenceWrapper.getHandle()).isOk();
558 syncVar->lock();
559 syncVar->notifyQueuedLocked();
560 syncVar->unlock();
561 if (c2Fence) {
562 *c2Fence = C2Fence();
563 }
564 } else {
565 (void)mProducer->cancelBuffer(slot, hFenceWrapper.getHandle()).isOk();
566 }
567 return C2_BAD_VALUE;
568 }
569 if (c2Fence) {
570 *c2Fence = C2Fence();
571 }
572 return C2_BAD_VALUE;
573 }
574
575 public:
Impl(const std::shared_ptr<C2Allocator> & allocator)576 Impl(const std::shared_ptr<C2Allocator> &allocator)
577 : mInit(C2_OK), mProducerId(0), mGeneration(0),
578 mConsumerUsage(0), mDqFailure(0), mLastDqTs(0),
579 mLastDqLogTs(0), mAllocator(allocator), mIgbpValidityToken(std::make_shared<int>(0)) {
580 }
581
~Impl()582 ~Impl() {
583 mIgbpValidityToken.reset();
584 for (int i = 0; i < NUM_BUFFER_SLOTS; ++i) {
585 mBuffers[i].clear();
586 }
587 }
588
fetchGraphicBlock(uint32_t width,uint32_t height,uint32_t format,C2MemoryUsage usage,std::shared_ptr<C2GraphicBlock> * block,C2Fence * fence)589 c2_status_t fetchGraphicBlock(
590 uint32_t width,
591 uint32_t height,
592 uint32_t format,
593 C2MemoryUsage usage,
594 std::shared_ptr<C2GraphicBlock> *block /* nonnull */,
595 C2Fence *fence) {
596 block->reset();
597 if (mInit != C2_OK) {
598 return mInit;
599 }
600
601 static int kMaxIgbpRetryDelayUs = 10000;
602
603 std::unique_lock<std::mutex> lock(mMutex);
604 if (mInvalidated) {
605 return C2_BAD_STATE;
606 }
607 if (mLastDqLogTs == 0) {
608 mLastDqLogTs = getTimestampNow();
609 } else {
610 int64_t now = getTimestampNow();
611 if (now >= mLastDqLogTs + 5000000) {
612 if (now >= mLastDqTs + 1000000 || mDqFailure > 5) {
613 ALOGW("last successful dequeue was %lld us ago, "
614 "%zu consecutive failures",
615 (long long)(now - mLastDqTs), mDqFailure);
616 }
617 mLastDqLogTs = now;
618 }
619 }
620 if (mProducerId == 0) {
621 std::shared_ptr<C2GraphicAllocation> alloc;
622 c2_status_t err = mAllocator->newGraphicAllocation(
623 width, height, format, usage, &alloc);
624 if (err != C2_OK) {
625 return err;
626 }
627 std::shared_ptr<C2BufferQueueBlockPoolData> poolData =
628 std::make_shared<C2BufferQueueBlockPoolData>(
629 0, (uint64_t)0, ~0, nullptr, nullptr, nullptr);
630 *block = _C2BlockFactory::CreateGraphicBlock(alloc, poolData);
631 ALOGV("allocated a buffer successfully");
632
633 return C2_OK;
634 }
635 c2_status_t status = fetchFromIgbp_l(width, height, format, usage, block, fence);
636 if (status == C2_BLOCKING) {
637 lock.unlock();
638 if (!fence) {
639 // in order not to drain cpu from component's spinning
640 ::usleep(kMaxIgbpRetryDelayUs);
641 }
642 }
643 return status;
644 }
645
setRenderCallback(const OnRenderCallback & renderCallback)646 void setRenderCallback(const OnRenderCallback &renderCallback) {
647 std::scoped_lock<std::mutex> lock(mMutex);
648 mRenderCallback = renderCallback;
649 }
650
651 /* This is for Old HAL request for compatibility */
configureProducer(const sp<HGraphicBufferProducer> & producer)652 void configureProducer(const sp<HGraphicBufferProducer> &producer) {
653 uint64_t producerId = 0;
654 uint32_t generation = 0;
655 uint64_t usage = 0;
656 bool bqInformation = false;
657 if (producer) {
658 Return<uint64_t> transResult = producer->getUniqueId();
659 if (!transResult.isOk()) {
660 ALOGD("configureProducer -- failed to connect to the producer");
661 return;
662 }
663 producerId = static_cast<uint64_t>(transResult);
664 bqInformation = getGenerationNumberAndUsage(producer, &generation, &usage);
665 if (!bqInformation) {
666 ALOGW("get generationNumber failed %llu",
667 (unsigned long long)producerId);
668 }
669 }
670 configureProducer(producer, nullptr, producerId, generation, usage, bqInformation);
671 }
672
configureProducer(const sp<HGraphicBufferProducer> & producer,native_handle_t * syncHandle,uint64_t producerId,uint32_t generation,uint64_t usage,bool bqInformation)673 void configureProducer(const sp<HGraphicBufferProducer> &producer,
674 native_handle_t *syncHandle,
675 uint64_t producerId,
676 uint32_t generation,
677 uint64_t usage,
678 bool bqInformation) {
679 std::shared_ptr<C2SurfaceSyncMemory> c2SyncMem;
680 if (syncHandle) {
681 if (!producer) {
682 native_handle_close(syncHandle);
683 native_handle_delete(syncHandle);
684 } else {
685 c2SyncMem = C2SurfaceSyncMemory::Import(syncHandle);
686 }
687 }
688 int migrated = 0;
689 std::shared_ptr<C2SurfaceSyncMemory> oldMem;
690 // poolDatas dtor should not be called during lock is held.
691 std::shared_ptr<C2BufferQueueBlockPoolData>
692 poolDatas[NUM_BUFFER_SLOTS];
693 {
694 sp<GraphicBuffer> buffers[NUM_BUFFER_SLOTS];
695 std::scoped_lock<std::mutex> lock(mMutex);
696 int32_t oldGeneration = mGeneration;
697 if (producer) {
698 mProducer = producer;
699 mProducerId = producerId;
700 mGeneration = bqInformation ? generation : 0;
701 } else {
702 mProducer = nullptr;
703 mProducerId = 0;
704 mGeneration = 0;
705 ALOGD("configuring null producer: igbp_information(%d)", bqInformation);
706 }
707 oldMem = mSyncMem; // preven destruction while locked.
708 mSyncMem = c2SyncMem;
709 C2SyncVariables *syncVar = mSyncMem ? mSyncMem->mem() : nullptr;
710 if (syncVar) {
711 syncVar->lock();
712 syncVar->setSyncStatusLocked(C2SyncVariables::STATUS_ACTIVE);
713 syncVar->unlock();
714 }
715 if (mProducer && bqInformation) { // migrate buffers
716 for (int i = 0; i < NUM_BUFFER_SLOTS; ++i) {
717 std::shared_ptr<C2BufferQueueBlockPoolData> data =
718 mPoolDatas[i].lock();
719 if (data) {
720 int slot = data->migrate(
721 mProducer, generation, usage,
722 producerId, mBuffers[i], oldGeneration, mSyncMem);
723 if (slot >= 0) {
724 buffers[slot] = mBuffers[i];
725 poolDatas[slot] = data;
726 ++migrated;
727 }
728 }
729 }
730 } else {
731 // old buffers should not be cancelled since the associated IGBP
732 // is no longer valid.
733 mIgbpValidityToken = std::make_shared<int>(0);
734 }
735 for (int i = 0; i < NUM_BUFFER_SLOTS; ++i) {
736 mBuffers[i] = buffers[i];
737 mPoolDatas[i] = poolDatas[i];
738 }
739 }
740 if (producer && bqInformation) {
741 ALOGD("local generation change %u , "
742 "bqId: %llu migrated buffers # %d",
743 generation, (unsigned long long)producerId, migrated);
744 }
745 mConsumerUsage = usage;
746 }
747
getConsumerUsage(uint64_t * consumeUsage)748 void getConsumerUsage(uint64_t *consumeUsage) {
749 *consumeUsage = mConsumerUsage;
750 }
751
invalidate()752 void invalidate() {
753 std::scoped_lock<std::mutex> lock(mMutex);
754 mInvalidated = true;
755 }
756
757 private:
758 friend struct C2BufferQueueBlockPoolData;
759
760 c2_status_t mInit;
761 uint64_t mProducerId;
762 uint32_t mGeneration;
763 uint64_t mConsumerUsage;
764 OnRenderCallback mRenderCallback;
765
766 size_t mDqFailure;
767 int64_t mLastDqTs;
768 int64_t mLastDqLogTs;
769
770 const std::shared_ptr<C2Allocator> mAllocator;
771
772 std::mutex mMutex;
773 sp<HGraphicBufferProducer> mProducer;
774 sp<HGraphicBufferProducer> mSavedProducer;
775
776 sp<GraphicBuffer> mBuffers[NUM_BUFFER_SLOTS];
777 std::weak_ptr<C2BufferQueueBlockPoolData> mPoolDatas[NUM_BUFFER_SLOTS];
778
779 std::shared_ptr<C2SurfaceSyncMemory> mSyncMem;
780
781 // IGBP invalidation notification token.
782 // The buffers(C2BufferQueueBlockPoolData) has the reference to the IGBP where
783 // they belong in order to call IGBP::cancelBuffer() when they are of no use.
784 //
785 // In certain cases, IGBP is no longer used by this class(actually MediaCodec)
786 // any more and the situation needs to be addressed quickly. In order to
787 // achieve those, std::shared_ptr<> is used as a token for quick IGBP invalidation
788 // notification from the buffers.
789 //
790 // The buffer side will have the reference of the token as std::weak_ptr<>.
791 // if the token has been expired, the buffers will not call IGBP::cancelBuffer()
792 // when they are no longer used.
793 std::shared_ptr<int> mIgbpValidityToken;
794 bool mInvalidated{false};
795 };
796
C2BufferQueueBlockPoolData(uint32_t generation,uint64_t bqId,int32_t bqSlot,const std::shared_ptr<int> & owner,const sp<HGraphicBufferProducer> & producer)797 C2BufferQueueBlockPoolData::C2BufferQueueBlockPoolData(
798 uint32_t generation, uint64_t bqId, int32_t bqSlot,
799 const std::shared_ptr<int>& owner,
800 const sp<HGraphicBufferProducer>& producer) :
801 mLocal(false), mHeld(producer && bqId != 0),
802 mGeneration(generation), mBqId(bqId), mBqSlot(bqSlot),
803 mCurrentGeneration(generation), mCurrentBqId(bqId),
804 mTransfer(false), mAttach(false), mDisplay(false),
805 mOwner(owner), mIgbp(producer) {
806 }
807
C2BufferQueueBlockPoolData(uint32_t generation,uint64_t bqId,int32_t bqSlot,const std::shared_ptr<int> & owner,const android::sp<HGraphicBufferProducer> & producer,std::shared_ptr<C2SurfaceSyncMemory> syncMem)808 C2BufferQueueBlockPoolData::C2BufferQueueBlockPoolData(
809 uint32_t generation, uint64_t bqId, int32_t bqSlot,
810 const std::shared_ptr<int>& owner,
811 const android::sp<HGraphicBufferProducer>& producer,
812 std::shared_ptr<C2SurfaceSyncMemory> syncMem) :
813 mLocal(true), mHeld(true),
814 mGeneration(generation), mBqId(bqId), mBqSlot(bqSlot),
815 mCurrentGeneration(generation), mCurrentBqId(bqId),
816 mTransfer(false), mAttach(false), mDisplay(false),
817 mOwner(owner), mIgbp(producer), mSyncMem(syncMem) {
818 }
819
~C2BufferQueueBlockPoolData()820 C2BufferQueueBlockPoolData::~C2BufferQueueBlockPoolData() {
821 if (!mHeld || mBqId == 0 || !mIgbp) {
822 return;
823 }
824
825 if (mLocal) {
826 if (mGeneration == mCurrentGeneration && mBqId == mCurrentBqId && !mOwner.expired()) {
827 C2SyncVariables *syncVar = mSyncMem ? mSyncMem->mem() : nullptr;
828 if (syncVar) {
829 mIgbp->cancelBuffer(mBqSlot, hidl_handle{}).isOk();
830 syncVar->lock();
831 syncVar->notifyQueuedLocked(nullptr,
832 syncVar->getSyncStatusLocked() == C2SyncVariables::STATUS_ACTIVE);
833 syncVar->unlock();
834 } else {
835 mIgbp->cancelBuffer(mBqSlot, hidl_handle{}).isOk();
836 }
837 }
838 } else if (!mOwner.expired()) {
839 C2SyncVariables *syncVar = mSyncMem ? mSyncMem->mem() : nullptr;
840 if (syncVar) {
841 mIgbp->cancelBuffer(mBqSlot, hidl_handle{}).isOk();
842 syncVar->lock();
843 syncVar->notifyQueuedLocked(nullptr,
844 syncVar->getSyncStatusLocked() != C2SyncVariables::STATUS_SWITCHING);
845 syncVar->unlock();
846 } else {
847 mIgbp->cancelBuffer(mBqSlot, hidl_handle{}).isOk();
848 }
849 }
850 }
851
getType() const852 C2BufferQueueBlockPoolData::type_t C2BufferQueueBlockPoolData::getType() const {
853 return TYPE_BUFFERQUEUE;
854 }
855
migrate(const sp<HGraphicBufferProducer> & producer,uint32_t toGeneration,uint64_t toUsage,uint64_t toBqId,sp<GraphicBuffer> & graphicBuffer,uint32_t oldGeneration,std::shared_ptr<C2SurfaceSyncMemory> syncMem)856 int C2BufferQueueBlockPoolData::migrate(
857 const sp<HGraphicBufferProducer>& producer,
858 uint32_t toGeneration, uint64_t toUsage, uint64_t toBqId,
859 sp<GraphicBuffer>& graphicBuffer, uint32_t oldGeneration,
860 std::shared_ptr<C2SurfaceSyncMemory> syncMem) {
861 std::scoped_lock<std::mutex> l(mLock);
862
863 mCurrentBqId = toBqId;
864 mCurrentGeneration = toGeneration;
865
866 if (!mHeld || mBqId == 0) {
867 ALOGV("buffer is not owned");
868 return -1;
869 }
870 if (!mLocal) {
871 ALOGV("pool is not local");
872 return -1;
873 }
874 if (mBqSlot < 0 || mBqSlot >= NUM_BUFFER_SLOTS) {
875 ALOGV("slot is not in effect");
876 return -1;
877 }
878 if (!graphicBuffer) {
879 ALOGV("buffer is null");
880 return -1;
881 }
882 if (toGeneration == mGeneration && mBqId == toBqId) {
883 ALOGV("cannot migrate to same bufferqueue");
884 return -1;
885 }
886 if (oldGeneration != mGeneration) {
887 ALOGV("cannot migrate stale buffer");
888 return -1;
889 }
890 if (mTransfer) {
891 // either transferred or detached.
892 ALOGV("buffer is in transfer");
893 return -1;
894 }
895
896 if (toUsage != graphicBuffer->getUsage()) {
897 sp<GraphicBuffer> newBuffer = new GraphicBuffer(
898 graphicBuffer->handle, GraphicBuffer::CLONE_HANDLE,
899 graphicBuffer->width, graphicBuffer->height, graphicBuffer->format,
900 graphicBuffer->layerCount, toUsage | graphicBuffer->getUsage(), graphicBuffer->stride);
901 if (newBuffer->initCheck() == android::NO_ERROR) {
902 graphicBuffer = std::move(newBuffer);
903 } else {
904 ALOGW("%s() failed to update usage, original usage=%" PRIx64 ", toUsage=%" PRIx64,
905 __func__, graphicBuffer->getUsage(), toUsage);
906 }
907 }
908 graphicBuffer->setGenerationNumber(toGeneration);
909
910 HBuffer hBuffer{};
911 uint32_t hGenerationNumber{};
912 if (!hgbp_b2h(graphicBuffer, &hBuffer, &hGenerationNumber)) {
913 ALOGD("I to O conversion failed");
914 return -1;
915 }
916
917 bool converted{};
918 status_t bStatus{};
919 int slot;
920 int *outSlot = &slot;
921 Return<void> transResult =
922 producer->attachBuffer(hBuffer, hGenerationNumber,
923 [&converted, &bStatus, outSlot](
924 HStatus hStatus, int32_t hSlot, bool releaseAll) {
925 converted = h2b(hStatus, &bStatus);
926 *outSlot = static_cast<int>(hSlot);
927 if (converted && releaseAll && bStatus == android::OK) {
928 bStatus = android::INVALID_OPERATION;
929 }
930 });
931 if (!transResult.isOk() || !converted || bStatus != android::OK) {
932 ALOGD("attach failed %d", static_cast<int>(bStatus));
933 return -1;
934 }
935 ALOGV("local migration from gen %u : %u slot %d : %d",
936 mGeneration, toGeneration, mBqSlot, slot);
937 mIgbp = producer;
938 mGeneration = toGeneration;
939 mBqId = toBqId;
940 mBqSlot = slot;
941 mSyncMem = syncMem;
942
943 C2SyncVariables *syncVar = syncMem ? syncMem->mem() : nullptr;
944 if (syncVar) {
945 syncVar->lock();
946 syncVar->notifyDequeuedLocked();
947 syncVar->unlock();
948 }
949 return slot;
950 }
951
getBufferQueueData(uint32_t * generation,uint64_t * bqId,int32_t * bqSlot) const952 void C2BufferQueueBlockPoolData::getBufferQueueData(
953 uint32_t* generation, uint64_t* bqId, int32_t* bqSlot) const {
954 if (generation) {
955 std::scoped_lock<std::mutex> lock(mLock);
956 *generation = mGeneration;
957 if (bqId) {
958 *bqId = mBqId;
959 }
960 if (bqSlot) {
961 *bqSlot = mBqSlot;
962 }
963 }
964 }
965
holdBlockFromBufferQueue(const std::shared_ptr<int> & owner,const sp<HGraphicBufferProducer> & igbp,std::shared_ptr<C2SurfaceSyncMemory> syncMem)966 bool C2BufferQueueBlockPoolData::holdBlockFromBufferQueue(
967 const std::shared_ptr<int>& owner,
968 const sp<HGraphicBufferProducer>& igbp,
969 std::shared_ptr<C2SurfaceSyncMemory> syncMem) {
970 std::scoped_lock<std::mutex> lock(mLock);
971 if (!mLocal) {
972 mOwner = owner;
973 mIgbp = igbp;
974 mSyncMem = syncMem;
975 }
976 if (mHeld) {
977 return false;
978 }
979 mHeld = true;
980 return true;
981 }
982
beginTransferBlockToClient()983 bool C2BufferQueueBlockPoolData::beginTransferBlockToClient() {
984 std::scoped_lock<std::mutex> lock(mLock);
985 mTransfer = true;
986 return true;
987 }
988
endTransferBlockToClient(bool transfer)989 bool C2BufferQueueBlockPoolData::endTransferBlockToClient(bool transfer) {
990 std::scoped_lock<std::mutex> lock(mLock);
991 mTransfer = false;
992 if (transfer) {
993 mHeld = false;
994 }
995 return true;
996 }
997
beginAttachBlockToBufferQueue()998 bool C2BufferQueueBlockPoolData::beginAttachBlockToBufferQueue() {
999 std::scoped_lock<std::mutex> lock(mLock);
1000 if (mLocal || mDisplay ||
1001 mAttach || !mHeld) {
1002 return false;
1003 }
1004 if (mBqId == 0) {
1005 return false;
1006 }
1007 mAttach = true;
1008 return true;
1009 }
1010
endAttachBlockToBufferQueue(const std::shared_ptr<int> & owner,const sp<HGraphicBufferProducer> & igbp,std::shared_ptr<C2SurfaceSyncMemory> syncMem,uint32_t generation,uint64_t bqId,int32_t bqSlot)1011 bool C2BufferQueueBlockPoolData::endAttachBlockToBufferQueue(
1012 const std::shared_ptr<int>& owner,
1013 const sp<HGraphicBufferProducer>& igbp,
1014 std::shared_ptr<C2SurfaceSyncMemory> syncMem,
1015 uint32_t generation,
1016 uint64_t bqId,
1017 int32_t bqSlot) {
1018 std::scoped_lock<std::mutex> lock(mLock);
1019 if (mLocal || !mAttach) {
1020 return false;
1021 }
1022 if (mDisplay) {
1023 mAttach = false;
1024 mHeld = false;
1025 return false;
1026 }
1027 mAttach = false;
1028 mHeld = true;
1029 mOwner = owner;
1030 mIgbp = igbp;
1031 mSyncMem = syncMem;
1032 mGeneration = generation;
1033 mBqId = bqId;
1034 mBqSlot = bqSlot;
1035 return true;
1036 }
1037
displayBlockToBufferQueue()1038 bool C2BufferQueueBlockPoolData::displayBlockToBufferQueue() {
1039 std::scoped_lock<std::mutex> lock(mLock);
1040 if (mLocal || mDisplay || !mHeld) {
1041 return false;
1042 }
1043 if (mBqId == 0) {
1044 return false;
1045 }
1046 mDisplay = true;
1047 if (mAttach) {
1048 return false;
1049 }
1050 mHeld = false;
1051 return true;
1052 }
1053
C2BufferQueueBlockPool(const std::shared_ptr<C2Allocator> & allocator,const local_id_t localId)1054 C2BufferQueueBlockPool::C2BufferQueueBlockPool(
1055 const std::shared_ptr<C2Allocator> &allocator, const local_id_t localId)
1056 : mAllocator(allocator), mLocalId(localId), mImpl(new Impl(allocator)) {}
1057
~C2BufferQueueBlockPool()1058 C2BufferQueueBlockPool::~C2BufferQueueBlockPool() {}
1059
fetchGraphicBlock(uint32_t width,uint32_t height,uint32_t format,C2MemoryUsage usage,std::shared_ptr<C2GraphicBlock> * block)1060 c2_status_t C2BufferQueueBlockPool::fetchGraphicBlock(
1061 uint32_t width,
1062 uint32_t height,
1063 uint32_t format,
1064 C2MemoryUsage usage,
1065 std::shared_ptr<C2GraphicBlock> *block /* nonnull */) {
1066 if (mImpl) {
1067 return mImpl->fetchGraphicBlock(width, height, format, usage, block, nullptr);
1068 }
1069 return C2_CORRUPTED;
1070 }
1071
fetchGraphicBlock(uint32_t width,uint32_t height,uint32_t format,C2MemoryUsage usage,std::shared_ptr<C2GraphicBlock> * block,C2Fence * fence)1072 c2_status_t C2BufferQueueBlockPool::fetchGraphicBlock(
1073 uint32_t width,
1074 uint32_t height,
1075 uint32_t format,
1076 C2MemoryUsage usage,
1077 std::shared_ptr<C2GraphicBlock> *block /* nonnull */,
1078 C2Fence *fence /* nonnull */) {
1079 if (mImpl) {
1080 return mImpl->fetchGraphicBlock(width, height, format, usage, block, fence);
1081 }
1082 return C2_CORRUPTED;
1083 }
1084
configureProducer(const sp<HGraphicBufferProducer> & producer)1085 void C2BufferQueueBlockPool::configureProducer(const sp<HGraphicBufferProducer> &producer) {
1086 if (mImpl) {
1087 mImpl->configureProducer(producer);
1088 }
1089 }
1090
configureProducer(const sp<HGraphicBufferProducer> & producer,native_handle_t * syncMemory,uint64_t bqId,uint32_t generationId,uint64_t consumerUsage)1091 void C2BufferQueueBlockPool::configureProducer(
1092 const sp<HGraphicBufferProducer> &producer,
1093 native_handle_t *syncMemory,
1094 uint64_t bqId,
1095 uint32_t generationId,
1096 uint64_t consumerUsage) {
1097 if (mImpl) {
1098 mImpl->configureProducer(
1099 producer, syncMemory, bqId, generationId, consumerUsage, true);
1100 }
1101 }
1102
setRenderCallback(const OnRenderCallback & renderCallback)1103 void C2BufferQueueBlockPool::setRenderCallback(const OnRenderCallback &renderCallback) {
1104 if (mImpl) {
1105 mImpl->setRenderCallback(renderCallback);
1106 }
1107 }
1108
getConsumerUsage(uint64_t * consumeUsage)1109 void C2BufferQueueBlockPool::getConsumerUsage(uint64_t *consumeUsage) {
1110 if (mImpl) {
1111 mImpl->getConsumerUsage(consumeUsage);
1112 }
1113 }
1114
invalidate()1115 void C2BufferQueueBlockPool::invalidate() {
1116 if (mImpl) {
1117 mImpl->invalidate();
1118 }
1119 }
1120
1121