1 /* 2 * Copyright 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 #include <dvr/dvr_api.h> 18 #include <gui/BufferHubProducer.h> 19 #include <inttypes.h> 20 #include <log/log.h> 21 #include <system/window.h> 22 #include <ui/BufferHubBuffer.h> 23 24 namespace android { 25 26 using namespace dvr; 27 28 /* static */ 29 sp<BufferHubProducer> BufferHubProducer::Create(const std::shared_ptr<ProducerQueue>& queue) { 30 sp<BufferHubProducer> producer = new BufferHubProducer; 31 producer->queue_ = queue; 32 return producer; 33 } 34 35 /* static */ 36 sp<BufferHubProducer> BufferHubProducer::Create(ProducerQueueParcelable parcelable) { 37 if (!parcelable.IsValid()) { 38 ALOGE("BufferHubProducer::Create: Invalid producer parcelable."); 39 return nullptr; 40 } 41 42 sp<BufferHubProducer> producer = new BufferHubProducer; 43 producer->queue_ = ProducerQueue::Import(parcelable.TakeChannelHandle()); 44 return producer; 45 } 46 47 status_t BufferHubProducer::requestBuffer(int slot, sp<GraphicBuffer>* buf) { 48 ALOGV("requestBuffer: slot=%d", slot); 49 50 std::unique_lock<std::mutex> lock(mutex_); 51 52 if (connected_api_ == kNoConnectedApi) { 53 ALOGE("requestBuffer: BufferHubProducer has no connected producer"); 54 return NO_INIT; 55 } 56 57 if (slot < 0 || slot >= max_buffer_count_) { 58 ALOGE("requestBuffer: slot index %d out of range [0, %d)", slot, max_buffer_count_); 59 return BAD_VALUE; 60 } else if (!buffers_[slot].mBufferState.isDequeued()) { 61 ALOGE("requestBuffer: slot %d is not owned by the producer (state = %s)", slot, 62 buffers_[slot].mBufferState.string()); 63 return BAD_VALUE; 64 } else if (buffers_[slot].mGraphicBuffer != nullptr) { 65 ALOGE("requestBuffer: slot %d is not empty.", slot); 66 return BAD_VALUE; 67 } else if (buffers_[slot].mProducerBuffer == nullptr) { 68 ALOGE("requestBuffer: slot %d is not dequeued.", slot); 69 return BAD_VALUE; 70 } 71 72 const auto& producer_buffer = buffers_[slot].mProducerBuffer; 73 sp<GraphicBuffer> graphic_buffer = producer_buffer->buffer()->buffer(); 74 75 buffers_[slot].mGraphicBuffer = graphic_buffer; 76 buffers_[slot].mRequestBufferCalled = true; 77 78 *buf = graphic_buffer; 79 return NO_ERROR; 80 } 81 82 status_t BufferHubProducer::setMaxDequeuedBufferCount(int max_dequeued_buffers) { 83 ALOGV("setMaxDequeuedBufferCount: max_dequeued_buffers=%d", max_dequeued_buffers); 84 85 std::unique_lock<std::mutex> lock(mutex_); 86 87 if (max_dequeued_buffers <= 0 || 88 max_dequeued_buffers > 89 int(BufferHubQueue::kMaxQueueCapacity - kDefaultUndequeuedBuffers)) { 90 ALOGE("setMaxDequeuedBufferCount: %d out of range (0, %zu]", max_dequeued_buffers, 91 BufferHubQueue::kMaxQueueCapacity); 92 return BAD_VALUE; 93 } 94 95 // The new dequeued_buffers count should not be violated by the number 96 // of currently dequeued buffers. 97 int dequeued_count = 0; 98 for (const auto& buf : buffers_) { 99 if (buf.mBufferState.isDequeued()) { 100 dequeued_count++; 101 } 102 } 103 if (dequeued_count > max_dequeued_buffers) { 104 ALOGE("setMaxDequeuedBufferCount: the requested dequeued_buffers" 105 "count (%d) exceeds the current dequeued buffer count (%d)", 106 max_dequeued_buffers, dequeued_count); 107 return BAD_VALUE; 108 } 109 110 max_dequeued_buffer_count_ = max_dequeued_buffers; 111 return NO_ERROR; 112 } 113 114 status_t BufferHubProducer::setAsyncMode(bool async) { 115 if (async) { 116 // TODO(b/36724099) BufferHubQueue's consumer end always acquires the buffer 117 // automatically and behaves differently from IGraphicBufferConsumer. Thus, 118 // android::BufferQueue's async mode (a.k.a. allocating an additional buffer 119 // to prevent dequeueBuffer from being blocking) technically does not apply 120 // here. 121 // 122 // In Daydream, non-blocking producer side dequeue is guaranteed by careful 123 // buffer consumer implementations. In another word, BufferHubQueue based 124 // dequeueBuffer should never block whether setAsyncMode(true) is set or 125 // not. 126 // 127 // See: IGraphicBufferProducer::setAsyncMode and 128 // BufferQueueProducer::setAsyncMode for more about original implementation. 129 ALOGW("BufferHubProducer::setAsyncMode: BufferHubQueue should always be " 130 "asynchronous. This call makes no effact."); 131 return NO_ERROR; 132 } 133 return NO_ERROR; 134 } 135 136 status_t BufferHubProducer::dequeueBuffer(int* out_slot, sp<Fence>* out_fence, uint32_t width, 137 uint32_t height, PixelFormat format, uint64_t usage, 138 uint64_t* /*outBufferAge*/, 139 FrameEventHistoryDelta* /* out_timestamps */) { 140 ALOGV("dequeueBuffer: w=%u, h=%u, format=%d, usage=%" PRIu64, width, height, format, usage); 141 142 status_t ret; 143 std::unique_lock<std::mutex> lock(mutex_); 144 145 if (connected_api_ == kNoConnectedApi) { 146 ALOGE("dequeueBuffer: BufferQueue has no connected producer"); 147 return NO_INIT; 148 } 149 150 const uint32_t kLayerCount = 1; 151 if (int32_t(queue_->capacity()) < max_dequeued_buffer_count_ + kDefaultUndequeuedBuffers) { 152 // Lazy allocation. When the capacity of |queue_| has not reached 153 // |max_dequeued_buffer_count_|, allocate new buffer. 154 // TODO(jwcai) To save memory, the really reasonable thing to do is to go 155 // over existing slots and find first existing one to dequeue. 156 ret = AllocateBuffer(width, height, kLayerCount, format, usage); 157 if (ret < 0) return ret; 158 } 159 160 size_t slot = 0; 161 std::shared_ptr<ProducerBuffer> producer_buffer; 162 163 for (size_t retry = 0; retry < BufferHubQueue::kMaxQueueCapacity; retry++) { 164 LocalHandle fence; 165 auto buffer_status = queue_->Dequeue(dequeue_timeout_ms_, &slot, &fence); 166 if (!buffer_status) return NO_MEMORY; 167 168 producer_buffer = buffer_status.take(); 169 if (!producer_buffer) return NO_MEMORY; 170 171 if (width == producer_buffer->width() && height == producer_buffer->height() && 172 uint32_t(format) == producer_buffer->format()) { 173 // The producer queue returns a producer buffer matches the request. 174 break; 175 } 176 177 // Needs reallocation. 178 // TODO(jwcai) Consider use VLOG instead if we find this log is not useful. 179 ALOGI("dequeueBuffer: requested buffer (w=%u, h=%u, format=%u) is different " 180 "from the buffer returned at slot: %zu (w=%u, h=%u, format=%u). Need " 181 "re-allocattion.", 182 width, height, format, slot, producer_buffer->width(), producer_buffer->height(), 183 producer_buffer->format()); 184 // Mark the slot as reallocating, so that later we can set 185 // BUFFER_NEEDS_REALLOCATION when the buffer actually get dequeued. 186 buffers_[slot].mIsReallocating = true; 187 188 // Remove the old buffer once the allocation before allocating its 189 // replacement. 190 RemoveBuffer(slot); 191 192 // Allocate a new producer buffer with new buffer configs. Note that if 193 // there are already multiple buffers in the queue, the next one returned 194 // from |queue_->Dequeue| may not be the new buffer we just reallocated. 195 // Retry up to BufferHubQueue::kMaxQueueCapacity times. 196 ret = AllocateBuffer(width, height, kLayerCount, format, usage); 197 if (ret < 0) return ret; 198 } 199 200 // With the BufferHub backed solution. Buffer slot returned from 201 // |queue_->Dequeue| is guaranteed to avaiable for producer's use. 202 // It's either in free state (if the buffer has never been used before) or 203 // in queued state (if the buffer has been dequeued and queued back to 204 // BufferHubQueue). 205 LOG_ALWAYS_FATAL_IF((!buffers_[slot].mBufferState.isFree() && 206 !buffers_[slot].mBufferState.isQueued()), 207 "dequeueBuffer: slot %zu is not free or queued, actual state: %s.", slot, 208 buffers_[slot].mBufferState.string()); 209 210 buffers_[slot].mBufferState.freeQueued(); 211 buffers_[slot].mBufferState.dequeue(); 212 ALOGV("dequeueBuffer: slot=%zu", slot); 213 214 // TODO(jwcai) Handle fence properly. |BufferHub| has full fence support, we 215 // just need to exopose that through |BufferHubQueue| once we need fence. 216 *out_fence = Fence::NO_FENCE; 217 *out_slot = int(slot); 218 ret = NO_ERROR; 219 220 if (buffers_[slot].mIsReallocating) { 221 ret |= BUFFER_NEEDS_REALLOCATION; 222 buffers_[slot].mIsReallocating = false; 223 } 224 225 return ret; 226 } 227 228 status_t BufferHubProducer::detachBuffer(int slot) { 229 ALOGV("detachBuffer: slot=%d", slot); 230 std::unique_lock<std::mutex> lock(mutex_); 231 232 return DetachBufferLocked(static_cast<size_t>(slot)); 233 } 234 235 status_t BufferHubProducer::DetachBufferLocked(size_t slot) { 236 if (connected_api_ == kNoConnectedApi) { 237 ALOGE("detachBuffer: BufferHubProducer is not connected."); 238 return NO_INIT; 239 } 240 241 if (slot >= static_cast<size_t>(max_buffer_count_)) { 242 ALOGE("detachBuffer: slot index %zu out of range [0, %d)", slot, max_buffer_count_); 243 return BAD_VALUE; 244 } else if (!buffers_[slot].mBufferState.isDequeued()) { 245 ALOGE("detachBuffer: slot %zu is not owned by the producer (state = %s)", slot, 246 buffers_[slot].mBufferState.string()); 247 return BAD_VALUE; 248 } else if (!buffers_[slot].mRequestBufferCalled) { 249 ALOGE("detachBuffer: buffer in slot %zu has not been requested", slot); 250 return BAD_VALUE; 251 } 252 std::shared_ptr<ProducerBuffer> producer_buffer = queue_->GetBuffer(slot); 253 if (producer_buffer == nullptr || producer_buffer->buffer() == nullptr) { 254 ALOGE("detachBuffer: Invalid ProducerBuffer at slot %zu.", slot); 255 return BAD_VALUE; 256 } 257 sp<GraphicBuffer> graphic_buffer = producer_buffer->buffer()->buffer(); 258 if (graphic_buffer == nullptr) { 259 ALOGE("detachBuffer: Invalid GraphicBuffer at slot %zu.", slot); 260 return BAD_VALUE; 261 } 262 263 // Remove the ProducerBuffer from the ProducerQueue. 264 status_t error = RemoveBuffer(slot); 265 if (error != NO_ERROR) { 266 ALOGE("detachBuffer: Failed to remove buffer, slot=%zu, error=%d.", slot, error); 267 return error; 268 } 269 270 // Here we need to convert the existing ProducerBuffer into a DetachedBufferHandle and inject 271 // the handle into the GraphicBuffer object at the requested slot. 272 auto status_or_handle = producer_buffer->Detach(); 273 if (!status_or_handle.ok()) { 274 ALOGE("detachBuffer: Failed to detach from a ProducerBuffer at slot %zu, error=%d.", slot, 275 status_or_handle.error()); 276 return BAD_VALUE; 277 } 278 279 // TODO(b/70912269): Reimplement BufferHubProducer::DetachBufferLocked() once GraphicBuffer can 280 // be directly backed by BufferHub. 281 return INVALID_OPERATION; 282 } 283 284 status_t BufferHubProducer::detachNextBuffer(sp<GraphicBuffer>* out_buffer, sp<Fence>* out_fence) { 285 ALOGV("detachNextBuffer."); 286 287 if (out_buffer == nullptr || out_fence == nullptr) { 288 ALOGE("detachNextBuffer: Invalid parameter: out_buffer=%p, out_fence=%p", out_buffer, 289 out_fence); 290 return BAD_VALUE; 291 } 292 293 std::unique_lock<std::mutex> lock(mutex_); 294 295 if (connected_api_ == kNoConnectedApi) { 296 ALOGE("detachNextBuffer: BufferHubProducer is not connected."); 297 return NO_INIT; 298 } 299 300 // detachNextBuffer is equivalent to calling dequeueBuffer, requestBuffer, and detachBuffer in 301 // sequence, except for two things: 302 // 303 // 1) It is unnecessary to know the dimensions, format, or usage of the next buffer, i.e. the 304 // function just returns whatever ProducerBuffer is available from the ProducerQueue and no 305 // buffer allocation or re-allocation will happen. 306 // 2) It will not block, since if it cannot find an appropriate buffer to return, it will return 307 // an error instead. 308 size_t slot = 0; 309 LocalHandle fence; 310 311 // First, dequeue a ProducerBuffer from the ProducerQueue with no timeout. Report error 312 // immediately if ProducerQueue::Dequeue() fails. 313 auto status_or_buffer = queue_->Dequeue(/*timeout=*/0, &slot, &fence); 314 if (!status_or_buffer.ok()) { 315 ALOGE("detachNextBuffer: Failed to dequeue buffer, error=%d.", status_or_buffer.error()); 316 return NO_MEMORY; 317 } 318 319 std::shared_ptr<ProducerBuffer> producer_buffer = status_or_buffer.take(); 320 if (producer_buffer == nullptr) { 321 ALOGE("detachNextBuffer: Dequeued buffer is null."); 322 return NO_MEMORY; 323 } 324 325 // With the BufferHub backed solution, slot returned from |queue_->Dequeue| is guaranteed to 326 // be available for producer's use. It's either in free state (if the buffer has never been used 327 // before) or in queued state (if the buffer has been dequeued and queued back to 328 // BufferHubQueue). 329 if (!buffers_[slot].mBufferState.isFree() && !buffers_[slot].mBufferState.isQueued()) { 330 ALOGE("detachNextBuffer: slot %zu is not free or queued, actual state: %s.", slot, 331 buffers_[slot].mBufferState.string()); 332 return BAD_VALUE; 333 } 334 if (buffers_[slot].mProducerBuffer == nullptr) { 335 ALOGE("detachNextBuffer: ProducerBuffer at slot %zu is null.", slot); 336 return BAD_VALUE; 337 } 338 if (buffers_[slot].mProducerBuffer->id() != producer_buffer->id()) { 339 ALOGE("detachNextBuffer: ProducerBuffer at slot %zu has mismatched id, actual: " 340 "%d, expected: %d.", 341 slot, buffers_[slot].mProducerBuffer->id(), producer_buffer->id()); 342 return BAD_VALUE; 343 } 344 345 ALOGV("detachNextBuffer: slot=%zu", slot); 346 buffers_[slot].mBufferState.freeQueued(); 347 buffers_[slot].mBufferState.dequeue(); 348 349 // Second, request the buffer. 350 sp<GraphicBuffer> graphic_buffer = producer_buffer->buffer()->buffer(); 351 buffers_[slot].mGraphicBuffer = producer_buffer->buffer()->buffer(); 352 353 // Finally, detach the buffer and then return. 354 status_t error = DetachBufferLocked(slot); 355 if (error == NO_ERROR) { 356 *out_fence = new Fence(fence.Release()); 357 *out_buffer = graphic_buffer; 358 } 359 return error; 360 } 361 362 status_t BufferHubProducer::attachBuffer(int* out_slot, const sp<GraphicBuffer>& buffer) { 363 // In the BufferHub design, all buffers are allocated and owned by the BufferHub. Thus only 364 // GraphicBuffers that are originated from BufferHub can be attached to a BufferHubProducer. 365 ALOGV("queueBuffer: buffer=%p", buffer.get()); 366 367 if (out_slot == nullptr) { 368 ALOGE("attachBuffer: out_slot cannot be NULL."); 369 return BAD_VALUE; 370 } 371 if (buffer == nullptr) { 372 ALOGE("attachBuffer: invalid GraphicBuffer."); 373 return BAD_VALUE; 374 } 375 376 std::unique_lock<std::mutex> lock(mutex_); 377 378 if (connected_api_ == kNoConnectedApi) { 379 ALOGE("attachBuffer: BufferQueue has no connected producer"); 380 return NO_INIT; 381 } 382 383 // Before attaching the buffer, caller is supposed to call 384 // IGraphicBufferProducer::setGenerationNumber to inform the 385 // BufferHubProducer the next generation number. 386 if (buffer->getGenerationNumber() != generation_number_) { 387 ALOGE("attachBuffer: Mismatched generation number, buffer: %u, queue: %u.", 388 buffer->getGenerationNumber(), generation_number_); 389 return BAD_VALUE; 390 } 391 392 // TODO(b/70912269): Reimplement BufferHubProducer::DetachBufferLocked() once GraphicBuffer can 393 // be directly backed by BufferHub. 394 return INVALID_OPERATION; 395 } 396 397 status_t BufferHubProducer::queueBuffer(int slot, const QueueBufferInput& input, 398 QueueBufferOutput* output) { 399 ALOGV("queueBuffer: slot %d", slot); 400 401 if (output == nullptr) { 402 return BAD_VALUE; 403 } 404 405 int64_t timestamp; 406 bool is_auto_timestamp; 407 android_dataspace dataspace; 408 Rect crop(Rect::EMPTY_RECT); 409 int scaling_mode; 410 uint32_t transform; 411 sp<Fence> fence; 412 413 input.deflate(×tamp, &is_auto_timestamp, &dataspace, &crop, &scaling_mode, &transform, 414 &fence); 415 416 // Check input scaling mode is valid. 417 switch (scaling_mode) { 418 case NATIVE_WINDOW_SCALING_MODE_FREEZE: 419 case NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW: 420 case NATIVE_WINDOW_SCALING_MODE_SCALE_CROP: 421 case NATIVE_WINDOW_SCALING_MODE_NO_SCALE_CROP: 422 break; 423 default: 424 ALOGE("queueBuffer: unknown scaling mode %d", scaling_mode); 425 return BAD_VALUE; 426 } 427 428 // Check input fence is valid. 429 if (fence == nullptr) { 430 ALOGE("queueBuffer: fence is NULL"); 431 return BAD_VALUE; 432 } 433 434 std::unique_lock<std::mutex> lock(mutex_); 435 436 if (connected_api_ == kNoConnectedApi) { 437 ALOGE("queueBuffer: BufferQueue has no connected producer"); 438 return NO_INIT; 439 } 440 441 if (slot < 0 || slot >= max_buffer_count_) { 442 ALOGE("queueBuffer: slot index %d out of range [0, %d)", slot, max_buffer_count_); 443 return BAD_VALUE; 444 } else if (!buffers_[slot].mBufferState.isDequeued()) { 445 ALOGE("queueBuffer: slot %d is not owned by the producer (state = %s)", slot, 446 buffers_[slot].mBufferState.string()); 447 return BAD_VALUE; 448 } else if ((!buffers_[slot].mRequestBufferCalled || buffers_[slot].mGraphicBuffer == nullptr)) { 449 ALOGE("queueBuffer: slot %d is not requested (mRequestBufferCalled=%d, " 450 "mGraphicBuffer=%p)", 451 slot, buffers_[slot].mRequestBufferCalled, buffers_[slot].mGraphicBuffer.get()); 452 return BAD_VALUE; 453 } 454 455 // Post the producer buffer with timestamp in the metadata. 456 const auto& producer_buffer = buffers_[slot].mProducerBuffer; 457 458 // Check input crop is not out of boundary of current buffer. 459 Rect buffer_rect(producer_buffer->width(), producer_buffer->height()); 460 Rect cropped_rect(Rect::EMPTY_RECT); 461 crop.intersect(buffer_rect, &cropped_rect); 462 if (cropped_rect != crop) { 463 ALOGE("queueBuffer: slot %d has out-of-boundary crop.", slot); 464 return BAD_VALUE; 465 } 466 467 LocalHandle fence_fd(fence->isValid() ? fence->dup() : -1); 468 469 DvrNativeBufferMetadata meta_data; 470 meta_data.timestamp = timestamp; 471 meta_data.is_auto_timestamp = int32_t(is_auto_timestamp); 472 meta_data.dataspace = int32_t(dataspace); 473 meta_data.crop_left = crop.left; 474 meta_data.crop_top = crop.top; 475 meta_data.crop_right = crop.right; 476 meta_data.crop_bottom = crop.bottom; 477 meta_data.scaling_mode = int32_t(scaling_mode); 478 meta_data.transform = int32_t(transform); 479 480 producer_buffer->PostAsync(&meta_data, fence_fd); 481 buffers_[slot].mBufferState.queue(); 482 483 output->width = producer_buffer->width(); 484 output->height = producer_buffer->height(); 485 output->transformHint = 0; // default value, we don't use it yet. 486 487 // |numPendingBuffers| counts of the number of buffers that has been enqueued 488 // by the producer but not yet acquired by the consumer. Due to the nature 489 // of BufferHubQueue design, this is hard to trace from the producer's client 490 // side, but it's safe to assume it's zero. 491 output->numPendingBuffers = 0; 492 493 // Note that we are not setting nextFrameNumber here as it seems to be only 494 // used by surface flinger. See more at b/22802885, ag/791760. 495 output->nextFrameNumber = 0; 496 497 return NO_ERROR; 498 } 499 500 status_t BufferHubProducer::cancelBuffer(int slot, const sp<Fence>& fence) { 501 ALOGV(__FUNCTION__); 502 503 std::unique_lock<std::mutex> lock(mutex_); 504 505 if (connected_api_ == kNoConnectedApi) { 506 ALOGE("cancelBuffer: BufferQueue has no connected producer"); 507 return NO_INIT; 508 } 509 510 if (slot < 0 || slot >= max_buffer_count_) { 511 ALOGE("cancelBuffer: slot index %d out of range [0, %d)", slot, max_buffer_count_); 512 return BAD_VALUE; 513 } else if (!buffers_[slot].mBufferState.isDequeued()) { 514 ALOGE("cancelBuffer: slot %d is not owned by the producer (state = %s)", slot, 515 buffers_[slot].mBufferState.string()); 516 return BAD_VALUE; 517 } else if (fence == nullptr) { 518 ALOGE("cancelBuffer: fence is NULL"); 519 return BAD_VALUE; 520 } 521 522 auto producer_buffer = buffers_[slot].mProducerBuffer; 523 queue_->Enqueue(producer_buffer, size_t(slot), 0U); 524 buffers_[slot].mBufferState.cancel(); 525 buffers_[slot].mFence = fence; 526 ALOGV("cancelBuffer: slot %d", slot); 527 528 return NO_ERROR; 529 } 530 531 status_t BufferHubProducer::query(int what, int* out_value) { 532 ALOGV(__FUNCTION__); 533 534 std::unique_lock<std::mutex> lock(mutex_); 535 536 if (out_value == nullptr) { 537 ALOGE("query: out_value was NULL"); 538 return BAD_VALUE; 539 } 540 541 int value = 0; 542 switch (what) { 543 case NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS: 544 // TODO(b/36187402) This should be the maximum number of buffers that this 545 // producer queue's consumer can acquire. Set to be at least one. Need to 546 // find a way to set from the consumer side. 547 value = kDefaultUndequeuedBuffers; 548 break; 549 case NATIVE_WINDOW_BUFFER_AGE: 550 value = 0; 551 break; 552 case NATIVE_WINDOW_WIDTH: 553 value = int32_t(queue_->default_width()); 554 break; 555 case NATIVE_WINDOW_HEIGHT: 556 value = int32_t(queue_->default_height()); 557 break; 558 case NATIVE_WINDOW_FORMAT: 559 value = int32_t(queue_->default_format()); 560 break; 561 case NATIVE_WINDOW_CONSUMER_RUNNING_BEHIND: 562 // BufferHubQueue is always operating in async mode, thus semantically 563 // consumer can never be running behind. See BufferQueueCore.cpp core 564 // for more information about the original meaning of this flag. 565 value = 0; 566 break; 567 case NATIVE_WINDOW_CONSUMER_USAGE_BITS: 568 // TODO(jwcai) This is currently not implement as we don't need 569 // IGraphicBufferConsumer parity. 570 value = 0; 571 break; 572 case NATIVE_WINDOW_DEFAULT_DATASPACE: 573 // TODO(jwcai) Return the default value android::BufferQueue is using as 574 // there is no way dvr::ConsumerQueue can set it. 575 value = 0; // HAL_DATASPACE_UNKNOWN 576 break; 577 case NATIVE_WINDOW_STICKY_TRANSFORM: 578 // TODO(jwcai) Return the default value android::BufferQueue is using as 579 // there is no way dvr::ConsumerQueue can set it. 580 value = 0; 581 break; 582 case NATIVE_WINDOW_CONSUMER_IS_PROTECTED: 583 // In Daydream's implementation, the consumer end (i.e. VR Compostior) 584 // knows how to handle protected buffers. 585 value = 1; 586 break; 587 default: 588 return BAD_VALUE; 589 } 590 591 ALOGV("query: key=%d, v=%d", what, value); 592 *out_value = value; 593 return NO_ERROR; 594 } 595 596 status_t BufferHubProducer::connect(const sp<IProducerListener>& /* listener */, int api, 597 bool /* producer_controlled_by_app */, 598 QueueBufferOutput* output) { 599 // Consumer interaction are actually handled by buffer hub, and we need 600 // to maintain consumer operations here. We only need to perform basic input 601 // parameter checks here. 602 ALOGV(__FUNCTION__); 603 604 if (output == nullptr) { 605 return BAD_VALUE; 606 } 607 608 std::unique_lock<std::mutex> lock(mutex_); 609 610 if (connected_api_ != kNoConnectedApi) { 611 return BAD_VALUE; 612 } 613 614 if (!queue_->is_connected()) { 615 ALOGE("BufferHubProducer::connect: This BufferHubProducer is not " 616 "connected to bufferhud. Has it been taken out as a parcelable?"); 617 return BAD_VALUE; 618 } 619 620 switch (api) { 621 case NATIVE_WINDOW_API_EGL: 622 case NATIVE_WINDOW_API_CPU: 623 case NATIVE_WINDOW_API_MEDIA: 624 case NATIVE_WINDOW_API_CAMERA: 625 connected_api_ = api; 626 627 output->width = queue_->default_width(); 628 output->height = queue_->default_height(); 629 630 // default values, we don't use them yet. 631 output->transformHint = 0; 632 output->numPendingBuffers = 0; 633 output->nextFrameNumber = 0; 634 output->bufferReplaced = false; 635 636 break; 637 default: 638 ALOGE("BufferHubProducer::connect: unknow API %d", api); 639 return BAD_VALUE; 640 } 641 642 return NO_ERROR; 643 } 644 645 status_t BufferHubProducer::disconnect(int api, DisconnectMode /*mode*/) { 646 // Consumer interaction are actually handled by buffer hub, and we need 647 // to maintain consumer operations here. We only need to perform basic input 648 // parameter checks here. 649 ALOGV(__FUNCTION__); 650 651 std::unique_lock<std::mutex> lock(mutex_); 652 653 if (kNoConnectedApi == connected_api_) { 654 return NO_INIT; 655 } else if (api != connected_api_) { 656 return BAD_VALUE; 657 } 658 659 FreeAllBuffers(); 660 connected_api_ = kNoConnectedApi; 661 return NO_ERROR; 662 } 663 664 status_t BufferHubProducer::setSidebandStream(const sp<NativeHandle>& stream) { 665 if (stream != nullptr) { 666 // TODO(jwcai) Investigate how is is used, maybe use BufferHubBuffer's 667 // metadata. 668 ALOGE("SidebandStream is not currently supported."); 669 return INVALID_OPERATION; 670 } 671 return NO_ERROR; 672 } 673 674 void BufferHubProducer::allocateBuffers(uint32_t /* width */, uint32_t /* height */, 675 PixelFormat /* format */, uint64_t /* usage */) { 676 // TODO(jwcai) |allocateBuffers| aims to preallocate up to the maximum number 677 // of buffers permitted by the current BufferQueue configuration (aka 678 // |max_buffer_count_|). 679 ALOGE("BufferHubProducer::allocateBuffers not implemented."); 680 } 681 682 status_t BufferHubProducer::allowAllocation(bool /* allow */) { 683 ALOGE("BufferHubProducer::allowAllocation not implemented."); 684 return INVALID_OPERATION; 685 } 686 687 status_t BufferHubProducer::setGenerationNumber(uint32_t generation_number) { 688 ALOGV(__FUNCTION__); 689 690 std::unique_lock<std::mutex> lock(mutex_); 691 generation_number_ = generation_number; 692 return NO_ERROR; 693 } 694 695 String8 BufferHubProducer::getConsumerName() const { 696 // BufferHub based implementation could have one to many producer/consumer 697 // relationship, thus |getConsumerName| from the producer side does not 698 // make any sense. 699 ALOGE("BufferHubProducer::getConsumerName not supported."); 700 return String8("BufferHubQueue::DummyConsumer"); 701 } 702 703 status_t BufferHubProducer::setSharedBufferMode(bool shared_buffer_mode) { 704 if (shared_buffer_mode) { 705 ALOGE("BufferHubProducer::setSharedBufferMode(true) is not supported."); 706 // TODO(b/36373181) Front buffer mode for buffer hub queue as ANativeWindow. 707 return INVALID_OPERATION; 708 } 709 // Setting to default should just work as a no-op. 710 return NO_ERROR; 711 } 712 713 status_t BufferHubProducer::setAutoRefresh(bool auto_refresh) { 714 if (auto_refresh) { 715 ALOGE("BufferHubProducer::setAutoRefresh(true) is not supported."); 716 return INVALID_OPERATION; 717 } 718 // Setting to default should just work as a no-op. 719 return NO_ERROR; 720 } 721 722 status_t BufferHubProducer::setDequeueTimeout(nsecs_t timeout) { 723 ALOGV(__FUNCTION__); 724 725 std::unique_lock<std::mutex> lock(mutex_); 726 dequeue_timeout_ms_ = static_cast<int>(timeout / (1000 * 1000)); 727 return NO_ERROR; 728 } 729 730 status_t BufferHubProducer::getLastQueuedBuffer(sp<GraphicBuffer>* /* out_buffer */, 731 sp<Fence>* /* out_fence */, 732 float /*out_transform_matrix*/[16]) { 733 ALOGE("BufferHubProducer::getLastQueuedBuffer not implemented."); 734 return INVALID_OPERATION; 735 } 736 737 void BufferHubProducer::getFrameTimestamps(FrameEventHistoryDelta* /*outDelta*/) { 738 ALOGE("BufferHubProducer::getFrameTimestamps not implemented."); 739 } 740 741 status_t BufferHubProducer::getUniqueId(uint64_t* out_id) const { 742 ALOGV(__FUNCTION__); 743 744 *out_id = unique_id_; 745 return NO_ERROR; 746 } 747 748 status_t BufferHubProducer::getConsumerUsage(uint64_t* out_usage) const { 749 ALOGV(__FUNCTION__); 750 751 // same value as returned by querying NATIVE_WINDOW_CONSUMER_USAGE_BITS 752 *out_usage = 0; 753 return NO_ERROR; 754 } 755 756 status_t BufferHubProducer::TakeAsParcelable(ProducerQueueParcelable* out_parcelable) { 757 if (!out_parcelable || out_parcelable->IsValid()) return BAD_VALUE; 758 759 if (connected_api_ != kNoConnectedApi) { 760 ALOGE("BufferHubProducer::TakeAsParcelable: BufferHubProducer has " 761 "connected client. Must disconnect first."); 762 return BAD_VALUE; 763 } 764 765 if (!queue_->is_connected()) { 766 ALOGE("BufferHubProducer::TakeAsParcelable: This BufferHubProducer " 767 "is not connected to bufferhud. Has it been taken out as a " 768 "parcelable?"); 769 return BAD_VALUE; 770 } 771 772 auto status = queue_->TakeAsParcelable(); 773 if (!status) { 774 ALOGE("BufferHubProducer::TakeAsParcelable: Failed to take out " 775 "ProducuerQueueParcelable from the producer queue, error: %s.", 776 status.GetErrorMessage().c_str()); 777 return BAD_VALUE; 778 } 779 780 *out_parcelable = status.take(); 781 return NO_ERROR; 782 } 783 784 status_t BufferHubProducer::AllocateBuffer(uint32_t width, uint32_t height, uint32_t layer_count, 785 PixelFormat format, uint64_t usage) { 786 auto status = queue_->AllocateBuffer(width, height, layer_count, uint32_t(format), usage); 787 if (!status) { 788 ALOGE("BufferHubProducer::AllocateBuffer: Failed to allocate buffer: %s", 789 status.GetErrorMessage().c_str()); 790 return NO_MEMORY; 791 } 792 793 size_t slot = status.get(); 794 auto producer_buffer = queue_->GetBuffer(slot); 795 796 LOG_ALWAYS_FATAL_IF(producer_buffer == nullptr, 797 "Failed to get the producer buffer at slot: %zu", slot); 798 799 buffers_[slot].mProducerBuffer = producer_buffer; 800 801 return NO_ERROR; 802 } 803 804 status_t BufferHubProducer::RemoveBuffer(size_t slot) { 805 auto status = queue_->RemoveBuffer(slot); 806 if (!status) { 807 ALOGE("BufferHubProducer::RemoveBuffer: Failed to remove buffer at slot: %zu, error: %s.", 808 slot, status.GetErrorMessage().c_str()); 809 return INVALID_OPERATION; 810 } 811 812 // Reset in memory objects related the the buffer. 813 buffers_[slot].mProducerBuffer = nullptr; 814 buffers_[slot].mBufferState.detachProducer(); 815 buffers_[slot].mFence = Fence::NO_FENCE; 816 buffers_[slot].mGraphicBuffer = nullptr; 817 buffers_[slot].mRequestBufferCalled = false; 818 return NO_ERROR; 819 } 820 821 status_t BufferHubProducer::FreeAllBuffers() { 822 for (size_t slot = 0; slot < BufferHubQueue::kMaxQueueCapacity; slot++) { 823 // Reset in memory objects related the the buffer. 824 buffers_[slot].mProducerBuffer = nullptr; 825 buffers_[slot].mBufferState.reset(); 826 buffers_[slot].mFence = Fence::NO_FENCE; 827 buffers_[slot].mGraphicBuffer = nullptr; 828 buffers_[slot].mRequestBufferCalled = false; 829 } 830 831 auto status = queue_->FreeAllBuffers(); 832 if (!status) { 833 ALOGE("BufferHubProducer::FreeAllBuffers: Failed to free all buffers on " 834 "the queue: %s", 835 status.GetErrorMessage().c_str()); 836 } 837 838 if (queue_->capacity() != 0 || queue_->count() != 0) { 839 LOG_ALWAYS_FATAL("BufferHubProducer::FreeAllBuffers: Not all buffers are freed."); 840 } 841 842 return NO_ERROR; 843 } 844 845 status_t BufferHubProducer::exportToParcel(Parcel* parcel) { 846 status_t res = TakeAsParcelable(&pending_producer_parcelable_); 847 if (res != NO_ERROR) return res; 848 849 if (!pending_producer_parcelable_.IsValid()) { 850 ALOGE("BufferHubProducer::exportToParcel: Invalid parcelable object."); 851 return BAD_VALUE; 852 } 853 854 res = parcel->writeUint32(USE_BUFFER_HUB); 855 if (res != NO_ERROR) { 856 ALOGE("BufferHubProducer::exportToParcel: Cannot write magic, res=%d.", res); 857 return res; 858 } 859 860 return pending_producer_parcelable_.writeToParcel(parcel); 861 } 862 863 IBinder* BufferHubProducer::onAsBinder() { 864 ALOGE("BufferHubProducer::onAsBinder: BufferHubProducer should never be used as an Binder " 865 "object."); 866 return nullptr; 867 } 868 869 } // namespace android 870