1/* 2 * Copyright (C) 2013 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_TAG "Camera3-OutputStream" 18#define ATRACE_TAG ATRACE_TAG_CAMERA 19//#define LOG_NDEBUG 0 20 21#include <utils/Log.h> 22#include <utils/Trace.h> 23#include "Camera3OutputStream.h" 24 25#ifndef container_of 26#define container_of(ptr, type, member) \ 27 (type *)((char*)(ptr) - offsetof(type, member)) 28#endif 29 30namespace android { 31 32namespace camera3 { 33 34Camera3OutputStream::Camera3OutputStream(int id, 35 sp<Surface> consumer, 36 uint32_t width, uint32_t height, int format, 37 android_dataspace dataSpace, camera3_stream_rotation_t rotation, 38 nsecs_t timestampOffset, int setId) : 39 Camera3IOStreamBase(id, CAMERA3_STREAM_OUTPUT, width, height, 40 /*maxSize*/0, format, dataSpace, rotation, setId), 41 mConsumer(consumer), 42 mTransform(0), 43 mTraceFirstBuffer(true), 44 mUseBufferManager(false), 45 mTimestampOffset(timestampOffset) { 46 47 if (mConsumer == NULL) { 48 ALOGE("%s: Consumer is NULL!", __FUNCTION__); 49 mState = STATE_ERROR; 50 } 51 52 if (setId > CAMERA3_STREAM_SET_ID_INVALID) { 53 mBufferReleasedListener = new BufferReleasedListener(this); 54 } 55} 56 57Camera3OutputStream::Camera3OutputStream(int id, 58 sp<Surface> consumer, 59 uint32_t width, uint32_t height, size_t maxSize, int format, 60 android_dataspace dataSpace, camera3_stream_rotation_t rotation, 61 nsecs_t timestampOffset, int setId) : 62 Camera3IOStreamBase(id, CAMERA3_STREAM_OUTPUT, width, height, maxSize, 63 format, dataSpace, rotation, setId), 64 mConsumer(consumer), 65 mTransform(0), 66 mTraceFirstBuffer(true), 67 mUseMonoTimestamp(false), 68 mUseBufferManager(false), 69 mTimestampOffset(timestampOffset) { 70 71 if (format != HAL_PIXEL_FORMAT_BLOB && format != HAL_PIXEL_FORMAT_RAW_OPAQUE) { 72 ALOGE("%s: Bad format for size-only stream: %d", __FUNCTION__, 73 format); 74 mState = STATE_ERROR; 75 } 76 77 if (mConsumer == NULL) { 78 ALOGE("%s: Consumer is NULL!", __FUNCTION__); 79 mState = STATE_ERROR; 80 } 81 82 if (setId > CAMERA3_STREAM_SET_ID_INVALID) { 83 mBufferReleasedListener = new BufferReleasedListener(this); 84 } 85} 86 87Camera3OutputStream::Camera3OutputStream(int id, camera3_stream_type_t type, 88 uint32_t width, uint32_t height, 89 int format, 90 android_dataspace dataSpace, 91 camera3_stream_rotation_t rotation, 92 int setId) : 93 Camera3IOStreamBase(id, type, width, height, 94 /*maxSize*/0, 95 format, dataSpace, rotation, setId), 96 mTransform(0), 97 mTraceFirstBuffer(true), 98 mUseMonoTimestamp(false), 99 mUseBufferManager(false) { 100 101 if (setId > CAMERA3_STREAM_SET_ID_INVALID) { 102 mBufferReleasedListener = new BufferReleasedListener(this); 103 } 104 105 // Subclasses expected to initialize mConsumer themselves 106} 107 108 109Camera3OutputStream::~Camera3OutputStream() { 110 disconnectLocked(); 111} 112 113status_t Camera3OutputStream::getBufferLocked(camera3_stream_buffer *buffer) { 114 ATRACE_CALL(); 115 status_t res; 116 117 if ((res = getBufferPreconditionCheckLocked()) != OK) { 118 return res; 119 } 120 121 ANativeWindowBuffer* anb; 122 int fenceFd = -1; 123 bool gotBufferFromManager = false; 124 125 if (mUseBufferManager) { 126 sp<GraphicBuffer> gb; 127 res = mBufferManager->getBufferForStream(getId(), getStreamSetId(), &gb, &fenceFd); 128 if (res == OK) { 129 // Attach this buffer to the bufferQueue: the buffer will be in dequeue state after a 130 // successful return. 131 anb = gb.get(); 132 res = mConsumer->attachBuffer(anb); 133 if (res != OK) { 134 ALOGE("%s: Stream %d: Can't attach the output buffer to this surface: %s (%d)", 135 __FUNCTION__, mId, strerror(-res), res); 136 return res; 137 } 138 gotBufferFromManager = true; 139 ALOGV("Stream %d: Attached new buffer", getId()); 140 } else if (res == ALREADY_EXISTS) { 141 // Have sufficient free buffers already attached, can just 142 // dequeue from buffer queue 143 ALOGV("Stream %d: Reusing attached buffer", getId()); 144 gotBufferFromManager = false; 145 } else if (res != OK) { 146 ALOGE("%s: Stream %d: Can't get next output buffer from buffer manager: %s (%d)", 147 __FUNCTION__, mId, strerror(-res), res); 148 return res; 149 } 150 } 151 if (!gotBufferFromManager) { 152 /** 153 * Release the lock briefly to avoid deadlock for below scenario: 154 * Thread 1: StreamingProcessor::startStream -> Camera3Stream::isConfiguring(). 155 * This thread acquired StreamingProcessor lock and try to lock Camera3Stream lock. 156 * Thread 2: Camera3Stream::returnBuffer->StreamingProcessor::onFrameAvailable(). 157 * This thread acquired Camera3Stream lock and bufferQueue lock, and try to lock 158 * StreamingProcessor lock. 159 * Thread 3: Camera3Stream::getBuffer(). This thread acquired Camera3Stream lock 160 * and try to lock bufferQueue lock. 161 * Then there is circular locking dependency. 162 */ 163 sp<ANativeWindow> currentConsumer = mConsumer; 164 mLock.unlock(); 165 166 res = currentConsumer->dequeueBuffer(currentConsumer.get(), &anb, &fenceFd); 167 mLock.lock(); 168 if (res != OK) { 169 ALOGE("%s: Stream %d: Can't dequeue next output buffer: %s (%d)", 170 __FUNCTION__, mId, strerror(-res), res); 171 172 // Only transition to STATE_ABANDONED from STATE_CONFIGURED. (If it is STATE_PREPARING, 173 // let prepareNextBuffer handle the error.) 174 if (res == NO_INIT && mState == STATE_CONFIGURED) { 175 mState = STATE_ABANDONED; 176 } 177 178 return res; 179 } 180 } 181 182 /** 183 * FenceFD now owned by HAL except in case of error, 184 * in which case we reassign it to acquire_fence 185 */ 186 handoutBufferLocked(*buffer, &(anb->handle), /*acquireFence*/fenceFd, 187 /*releaseFence*/-1, CAMERA3_BUFFER_STATUS_OK, /*output*/true); 188 189 return OK; 190} 191 192status_t Camera3OutputStream::returnBufferLocked( 193 const camera3_stream_buffer &buffer, 194 nsecs_t timestamp) { 195 ATRACE_CALL(); 196 197 status_t res = returnAnyBufferLocked(buffer, timestamp, /*output*/true); 198 199 if (res != OK) { 200 return res; 201 } 202 203 mLastTimestamp = timestamp; 204 205 return OK; 206} 207 208status_t Camera3OutputStream::returnBufferCheckedLocked( 209 const camera3_stream_buffer &buffer, 210 nsecs_t timestamp, 211 bool output, 212 /*out*/ 213 sp<Fence> *releaseFenceOut) { 214 215 (void)output; 216 ALOG_ASSERT(output, "Expected output to be true"); 217 218 status_t res; 219 220 // Fence management - always honor release fence from HAL 221 sp<Fence> releaseFence = new Fence(buffer.release_fence); 222 int anwReleaseFence = releaseFence->dup(); 223 224 /** 225 * Release the lock briefly to avoid deadlock with 226 * StreamingProcessor::startStream -> Camera3Stream::isConfiguring (this 227 * thread will go into StreamingProcessor::onFrameAvailable) during 228 * queueBuffer 229 */ 230 sp<ANativeWindow> currentConsumer = mConsumer; 231 mLock.unlock(); 232 233 /** 234 * Return buffer back to ANativeWindow 235 */ 236 if (buffer.status == CAMERA3_BUFFER_STATUS_ERROR) { 237 // Cancel buffer 238 res = currentConsumer->cancelBuffer(currentConsumer.get(), 239 container_of(buffer.buffer, ANativeWindowBuffer, handle), 240 anwReleaseFence); 241 if (res != OK) { 242 ALOGE("%s: Stream %d: Error cancelling buffer to native window:" 243 " %s (%d)", __FUNCTION__, mId, strerror(-res), res); 244 } 245 246 if (mUseBufferManager) { 247 // Return this buffer back to buffer manager. 248 mBufferReleasedListener->onBufferReleased(); 249 } 250 } else { 251 if (mTraceFirstBuffer && (stream_type == CAMERA3_STREAM_OUTPUT)) { 252 { 253 char traceLog[48]; 254 snprintf(traceLog, sizeof(traceLog), "Stream %d: first full buffer\n", mId); 255 ATRACE_NAME(traceLog); 256 } 257 mTraceFirstBuffer = false; 258 } 259 260 /* Certain consumers (such as AudioSource or HardwareComposer) use 261 * MONOTONIC time, causing time misalignment if camera timestamp is 262 * in BOOTTIME. Do the conversion if necessary. */ 263 res = native_window_set_buffers_timestamp(mConsumer.get(), 264 mUseMonoTimestamp ? timestamp - mTimestampOffset : timestamp); 265 if (res != OK) { 266 ALOGE("%s: Stream %d: Error setting timestamp: %s (%d)", 267 __FUNCTION__, mId, strerror(-res), res); 268 return res; 269 } 270 271 res = currentConsumer->queueBuffer(currentConsumer.get(), 272 container_of(buffer.buffer, ANativeWindowBuffer, handle), 273 anwReleaseFence); 274 if (res != OK) { 275 ALOGE("%s: Stream %d: Error queueing buffer to native window: " 276 "%s (%d)", __FUNCTION__, mId, strerror(-res), res); 277 } 278 } 279 mLock.lock(); 280 281 // Once a valid buffer has been returned to the queue, can no longer 282 // dequeue all buffers for preallocation. 283 if (buffer.status != CAMERA3_BUFFER_STATUS_ERROR) { 284 mStreamUnpreparable = true; 285 } 286 287 if (res != OK) { 288 close(anwReleaseFence); 289 } 290 291 *releaseFenceOut = releaseFence; 292 293 return res; 294} 295 296void Camera3OutputStream::dump(int fd, const Vector<String16> &args) const { 297 (void) args; 298 String8 lines; 299 lines.appendFormat(" Stream[%d]: Output\n", mId); 300 lines.appendFormat(" Consumer name: %s\n", mConsumerName.string()); 301 write(fd, lines.string(), lines.size()); 302 303 Camera3IOStreamBase::dump(fd, args); 304} 305 306status_t Camera3OutputStream::setTransform(int transform) { 307 ATRACE_CALL(); 308 Mutex::Autolock l(mLock); 309 return setTransformLocked(transform); 310} 311 312status_t Camera3OutputStream::setTransformLocked(int transform) { 313 status_t res = OK; 314 if (mState == STATE_ERROR) { 315 ALOGE("%s: Stream in error state", __FUNCTION__); 316 return INVALID_OPERATION; 317 } 318 319 mTransform = transform; 320 if (mState == STATE_CONFIGURED) { 321 res = native_window_set_buffers_transform(mConsumer.get(), 322 transform); 323 if (res != OK) { 324 ALOGE("%s: Unable to configure stream transform to %x: %s (%d)", 325 __FUNCTION__, transform, strerror(-res), res); 326 } 327 } 328 return res; 329} 330 331status_t Camera3OutputStream::configureQueueLocked() { 332 status_t res; 333 334 mTraceFirstBuffer = true; 335 if ((res = Camera3IOStreamBase::configureQueueLocked()) != OK) { 336 return res; 337 } 338 339 ALOG_ASSERT(mConsumer != 0, "mConsumer should never be NULL"); 340 341 // Configure consumer-side ANativeWindow interface. The listener may be used 342 // to notify buffer manager (if it is used) of the returned buffers. 343 res = mConsumer->connect(NATIVE_WINDOW_API_CAMERA, /*listener*/mBufferReleasedListener); 344 if (res != OK) { 345 ALOGE("%s: Unable to connect to native window for stream %d", 346 __FUNCTION__, mId); 347 return res; 348 } 349 350 mConsumerName = mConsumer->getConsumerName(); 351 352 res = native_window_set_usage(mConsumer.get(), camera3_stream::usage); 353 if (res != OK) { 354 ALOGE("%s: Unable to configure usage %08x for stream %d", 355 __FUNCTION__, camera3_stream::usage, mId); 356 return res; 357 } 358 359 res = native_window_set_scaling_mode(mConsumer.get(), 360 NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW); 361 if (res != OK) { 362 ALOGE("%s: Unable to configure stream scaling: %s (%d)", 363 __FUNCTION__, strerror(-res), res); 364 return res; 365 } 366 367 if (mMaxSize == 0) { 368 // For buffers of known size 369 res = native_window_set_buffers_dimensions(mConsumer.get(), 370 camera3_stream::width, camera3_stream::height); 371 } else { 372 // For buffers with bounded size 373 res = native_window_set_buffers_dimensions(mConsumer.get(), 374 mMaxSize, 1); 375 } 376 if (res != OK) { 377 ALOGE("%s: Unable to configure stream buffer dimensions" 378 " %d x %d (maxSize %zu) for stream %d", 379 __FUNCTION__, camera3_stream::width, camera3_stream::height, 380 mMaxSize, mId); 381 return res; 382 } 383 res = native_window_set_buffers_format(mConsumer.get(), 384 camera3_stream::format); 385 if (res != OK) { 386 ALOGE("%s: Unable to configure stream buffer format %#x for stream %d", 387 __FUNCTION__, camera3_stream::format, mId); 388 return res; 389 } 390 391 res = native_window_set_buffers_data_space(mConsumer.get(), 392 camera3_stream::data_space); 393 if (res != OK) { 394 ALOGE("%s: Unable to configure stream dataspace %#x for stream %d", 395 __FUNCTION__, camera3_stream::data_space, mId); 396 return res; 397 } 398 399 int maxConsumerBuffers; 400 res = static_cast<ANativeWindow*>(mConsumer.get())->query( 401 mConsumer.get(), 402 NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &maxConsumerBuffers); 403 if (res != OK) { 404 ALOGE("%s: Unable to query consumer undequeued" 405 " buffer count for stream %d", __FUNCTION__, mId); 406 return res; 407 } 408 409 ALOGV("%s: Consumer wants %d buffers, HAL wants %d", __FUNCTION__, 410 maxConsumerBuffers, camera3_stream::max_buffers); 411 if (camera3_stream::max_buffers == 0) { 412 ALOGE("%s: Camera HAL requested max_buffer count: %d, requires at least 1", 413 __FUNCTION__, camera3_stream::max_buffers); 414 return INVALID_OPERATION; 415 } 416 417 mTotalBufferCount = maxConsumerBuffers + camera3_stream::max_buffers; 418 mHandoutTotalBufferCount = 0; 419 mFrameCount = 0; 420 mLastTimestamp = 0; 421 mUseMonoTimestamp = (isConsumedByHWComposer() | isVideoStream()); 422 423 res = native_window_set_buffer_count(mConsumer.get(), 424 mTotalBufferCount); 425 if (res != OK) { 426 ALOGE("%s: Unable to set buffer count for stream %d", 427 __FUNCTION__, mId); 428 return res; 429 } 430 431 res = native_window_set_buffers_transform(mConsumer.get(), 432 mTransform); 433 if (res != OK) { 434 ALOGE("%s: Unable to configure stream transform to %x: %s (%d)", 435 __FUNCTION__, mTransform, strerror(-res), res); 436 } 437 438 /** 439 * Camera3 Buffer manager is only supported by HAL3.3 onwards, as the older HALs requires 440 * buffers to be statically allocated for internal static buffer registration, while the 441 * buffers provided by buffer manager are really dynamically allocated. Camera3Device only 442 * sets the mBufferManager if device version is > HAL3.2, which guarantees that the buffer 443 * manager setup is skipped in below code. Note that HAL3.2 is also excluded here, as some 444 * HAL3.2 devices may not support the dynamic buffer registeration. 445 */ 446 if (mBufferManager != 0 && mSetId > CAMERA3_STREAM_SET_ID_INVALID) { 447 uint32_t consumerUsage = 0; 448 getEndpointUsage(&consumerUsage); 449 StreamInfo streamInfo( 450 getId(), getStreamSetId(), getWidth(), getHeight(), getFormat(), getDataSpace(), 451 camera3_stream::usage | consumerUsage, mTotalBufferCount, 452 /*isConfigured*/true); 453 wp<Camera3OutputStream> weakThis(this); 454 res = mBufferManager->registerStream(weakThis, 455 streamInfo); 456 if (res == OK) { 457 // Disable buffer allocation for this BufferQueue, buffer manager will take over 458 // the buffer allocation responsibility. 459 mConsumer->getIGraphicBufferProducer()->allowAllocation(false); 460 mUseBufferManager = true; 461 } else { 462 ALOGE("%s: Unable to register stream %d to camera3 buffer manager, " 463 "(error %d %s), fall back to BufferQueue for buffer management!", 464 __FUNCTION__, mId, res, strerror(-res)); 465 } 466 } 467 468 return OK; 469} 470 471status_t Camera3OutputStream::disconnectLocked() { 472 status_t res; 473 474 if ((res = Camera3IOStreamBase::disconnectLocked()) != OK) { 475 return res; 476 } 477 478 ALOGV("%s: disconnecting stream %d from native window", __FUNCTION__, getId()); 479 480 res = native_window_api_disconnect(mConsumer.get(), 481 NATIVE_WINDOW_API_CAMERA); 482 483 /** 484 * This is not an error. if client calling process dies, the window will 485 * also die and all calls to it will return DEAD_OBJECT, thus it's already 486 * "disconnected" 487 */ 488 if (res == DEAD_OBJECT) { 489 ALOGW("%s: While disconnecting stream %d from native window, the" 490 " native window died from under us", __FUNCTION__, mId); 491 } 492 else if (res != OK) { 493 ALOGE("%s: Unable to disconnect stream %d from native window " 494 "(error %d %s)", 495 __FUNCTION__, mId, res, strerror(-res)); 496 mState = STATE_ERROR; 497 return res; 498 } 499 500 // Since device is already idle, there is no getBuffer call to buffer manager, unregister the 501 // stream at this point should be safe. 502 if (mUseBufferManager) { 503 res = mBufferManager->unregisterStream(getId(), getStreamSetId()); 504 if (res != OK) { 505 ALOGE("%s: Unable to unregister stream %d from buffer manager " 506 "(error %d %s)", __FUNCTION__, mId, res, strerror(-res)); 507 mState = STATE_ERROR; 508 return res; 509 } 510 // Note that, to make prepare/teardown case work, we must not mBufferManager.clear(), as 511 // the stream is still in usable state after this call. 512 mUseBufferManager = false; 513 } 514 515 mState = (mState == STATE_IN_RECONFIG) ? STATE_IN_CONFIG 516 : STATE_CONSTRUCTED; 517 return OK; 518} 519 520status_t Camera3OutputStream::getEndpointUsage(uint32_t *usage) const { 521 522 status_t res; 523 int32_t u = 0; 524 res = static_cast<ANativeWindow*>(mConsumer.get())->query(mConsumer.get(), 525 NATIVE_WINDOW_CONSUMER_USAGE_BITS, &u); 526 527 // If an opaque output stream's endpoint is ImageReader, add 528 // GRALLOC_USAGE_HW_CAMERA_ZSL to the usage so HAL knows it will be used 529 // for the ZSL use case. 530 // Assume it's for ImageReader if the consumer usage doesn't have any of these bits set: 531 // 1. GRALLOC_USAGE_HW_TEXTURE 532 // 2. GRALLOC_USAGE_HW_RENDER 533 // 3. GRALLOC_USAGE_HW_COMPOSER 534 // 4. GRALLOC_USAGE_HW_VIDEO_ENCODER 535 if (camera3_stream::format == HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED && 536 (u & (GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_COMPOSER | 537 GRALLOC_USAGE_HW_VIDEO_ENCODER)) == 0) { 538 u |= GRALLOC_USAGE_HW_CAMERA_ZSL; 539 } 540 541 *usage = u; 542 return res; 543} 544 545bool Camera3OutputStream::isVideoStream() const { 546 uint32_t usage = 0; 547 status_t res = getEndpointUsage(&usage); 548 if (res != OK) { 549 ALOGE("%s: getting end point usage failed: %s (%d).", __FUNCTION__, strerror(-res), res); 550 return false; 551 } 552 553 return (usage & GRALLOC_USAGE_HW_VIDEO_ENCODER) != 0; 554} 555 556status_t Camera3OutputStream::setBufferManager(sp<Camera3BufferManager> bufferManager) { 557 Mutex::Autolock l(mLock); 558 if (mState != STATE_CONSTRUCTED) { 559 ALOGE("%s: this method can only be called when stream in in CONSTRUCTED state.", 560 __FUNCTION__); 561 return INVALID_OPERATION; 562 } 563 mBufferManager = bufferManager; 564 565 return OK; 566} 567 568void Camera3OutputStream::BufferReleasedListener::onBufferReleased() { 569 sp<Camera3OutputStream> stream = mParent.promote(); 570 if (stream == nullptr) { 571 ALOGV("%s: Parent camera3 output stream was destroyed", __FUNCTION__); 572 return; 573 } 574 575 Mutex::Autolock l(stream->mLock); 576 if (!(stream->mUseBufferManager)) { 577 return; 578 } 579 580 ALOGV("Stream %d: Buffer released", stream->getId()); 581 status_t res = stream->mBufferManager->onBufferReleased( 582 stream->getId(), stream->getStreamSetId()); 583 if (res != OK) { 584 ALOGE("%s: signaling buffer release to buffer manager failed: %s (%d).", __FUNCTION__, 585 strerror(-res), res); 586 stream->mState = STATE_ERROR; 587 } 588} 589 590status_t Camera3OutputStream::detachBuffer(sp<GraphicBuffer>* buffer, int* fenceFd) { 591 Mutex::Autolock l(mLock); 592 593 ALOGV("Stream %d: detachBuffer", getId()); 594 if (buffer == nullptr) { 595 return BAD_VALUE; 596 } 597 598 sp<Fence> fence; 599 status_t res = mConsumer->detachNextBuffer(buffer, &fence); 600 if (res == NO_MEMORY) { 601 // This may rarely happen, which indicates that the released buffer was freed by other 602 // call (e.g., attachBuffer, dequeueBuffer etc.) before reaching here. We should notify the 603 // buffer manager that this buffer has been freed. It's not fatal, but should be avoided, 604 // therefore log a warning. 605 *buffer = 0; 606 ALOGW("%s: the released buffer has already been freed by the buffer queue!", __FUNCTION__); 607 } else if (res != OK) { 608 // Treat other errors as abandonment 609 ALOGE("%s: detach next buffer failed: %s (%d).", __FUNCTION__, strerror(-res), res); 610 mState = STATE_ABANDONED; 611 return res; 612 } 613 614 if (fenceFd != nullptr) { 615 if (fence!= 0 && fence->isValid()) { 616 *fenceFd = fence->dup(); 617 } else { 618 *fenceFd = -1; 619 } 620 } 621 622 return OK; 623} 624 625bool Camera3OutputStream::isConsumedByHWComposer() const { 626 uint32_t usage = 0; 627 status_t res = getEndpointUsage(&usage); 628 if (res != OK) { 629 ALOGE("%s: getting end point usage failed: %s (%d).", __FUNCTION__, strerror(-res), res); 630 return false; 631 } 632 633 return (usage & GRALLOC_USAGE_HW_COMPOSER) != 0; 634} 635 636}; // namespace camera3 637 638}; // namespace android 639