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