1 /* 2 * Copyright 2019 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 //#define LOG_NDEBUG 0 18 #define LOG_TAG "H2BGraphicBufferProducer (at) 2.0" 19 20 #include <android-base/logging.h> 21 22 #include <android/hardware/graphics/common/1.2/types.h> 23 #include <gui/bufferqueue/2.0/B2HProducerListener.h> 24 #include <gui/bufferqueue/2.0/H2BGraphicBufferProducer.h> 25 #include <gui/bufferqueue/2.0/types.h> 26 #include <ui/GraphicBuffer.h> 27 #include <ui/Rect.h> 28 #include <ui/Region.h> 29 #include <vndk/hardware_buffer.h> 30 31 namespace android { 32 namespace hardware { 33 namespace graphics { 34 namespace bufferqueue { 35 namespace V2_0 { 36 namespace utils { 37 38 namespace /* unnamed */ { 39 40 using BQueueBufferInput = ::android:: 41 IGraphicBufferProducer::QueueBufferInput; 42 using HQueueBufferInput = ::android::hardware::graphics::bufferqueue::V2_0:: 43 IGraphicBufferProducer::QueueBufferInput; 44 using BQueueBufferOutput = ::android:: 45 IGraphicBufferProducer::QueueBufferOutput; 46 using HQueueBufferOutput = ::android::hardware::graphics::bufferqueue::V2_0:: 47 IGraphicBufferProducer::QueueBufferOutput; 48 49 using ::android::hardware::graphics::bufferqueue::V2_0::utils::b2h; 50 using ::android::hardware::graphics::bufferqueue::V2_0::utils::h2b; 51 52 bool b2h(BQueueBufferInput const& from, HQueueBufferInput* to, 53 HFenceWrapper* hFenceWrapper) { 54 to->timestamp = from.timestamp; 55 to->isAutoTimestamp = static_cast<bool>(from.isAutoTimestamp); 56 to->dataSpace = static_cast<int32_t>(from.dataSpace); 57 to->transform = static_cast<int32_t>(from.transform); 58 to->stickyTransform = static_cast<int32_t>(from.stickyTransform); 59 if (!b2h(from.crop, &to->crop) || 60 !b2h(from.surfaceDamage, &to->surfaceDamage) || 61 !b2h(from.fence, hFenceWrapper)) { 62 return false; 63 } 64 to->fence = hFenceWrapper->getHandle(); 65 return true; 66 } 67 68 bool h2b(HQueueBufferOutput const& from, BQueueBufferOutput* to) { 69 to->width = from.width; 70 to->height = from.height; 71 to->transformHint = static_cast<uint32_t>(from.transformHint); 72 to->numPendingBuffers = from.numPendingBuffers; 73 to->nextFrameNumber = from.nextFrameNumber; 74 to->bufferReplaced = from.bufferReplaced; 75 return true; 76 } 77 78 } // unnamed namespace 79 80 // H2BGraphicBufferProducer 81 // ======================== 82 83 status_t H2BGraphicBufferProducer::requestBuffer(int slot, 84 sp<GraphicBuffer>* bBuffer) { 85 bool converted{}; 86 status_t bStatus{}; 87 Return<void> transResult = mBase->requestBuffer(slot, 88 [&converted, &bStatus, bBuffer]( 89 HStatus hStatus, 90 HardwareBuffer const& hBuffer, 91 uint32_t generationNumber) { 92 converted = 93 h2b(hStatus, &bStatus) && 94 h2b(hBuffer, bBuffer); 95 if (*bBuffer) { 96 (*bBuffer)->setGenerationNumber(generationNumber); 97 } 98 }); 99 if (!transResult.isOk()) { 100 LOG(ERROR) << "requestBuffer: transaction failed."; 101 return FAILED_TRANSACTION; 102 } 103 if (!converted) { 104 LOG(ERROR) << "requestBuffer: corrupted transaction."; 105 return FAILED_TRANSACTION; 106 } 107 return bStatus; 108 } 109 110 status_t H2BGraphicBufferProducer::setMaxDequeuedBufferCount( 111 int maxDequeuedBuffers) { 112 status_t bStatus{}; 113 Return<HStatus> transResult = mBase->setMaxDequeuedBufferCount( 114 static_cast<int32_t>(maxDequeuedBuffers)); 115 if (!transResult.isOk()) { 116 LOG(ERROR) << "setMaxDequeuedBufferCount: transaction failed."; 117 return FAILED_TRANSACTION; 118 } 119 if (!h2b(static_cast<HStatus>(transResult), &bStatus)) { 120 LOG(ERROR) << "setMaxDequeuedBufferCount: corrupted transaction."; 121 return FAILED_TRANSACTION; 122 } 123 return bStatus; 124 } 125 126 status_t H2BGraphicBufferProducer::setAsyncMode(bool async) { 127 status_t bStatus{}; 128 Return<HStatus> transResult = mBase->setAsyncMode(async); 129 if (!transResult.isOk()) { 130 LOG(ERROR) << "setAsyncMode: transaction failed."; 131 return FAILED_TRANSACTION; 132 } 133 if (!h2b(static_cast<HStatus>(transResult), &bStatus)) { 134 LOG(ERROR) << "setAsyncMode: corrupted transaction."; 135 return FAILED_TRANSACTION; 136 } 137 return bStatus; 138 } 139 140 status_t H2BGraphicBufferProducer::dequeueBuffer( 141 int* slot, sp<BFence>* fence, 142 uint32_t w, uint32_t h, 143 PixelFormat format, uint64_t usage, 144 uint64_t* outBufferAge, FrameEventHistoryDelta* /* outTimestamps */) { 145 146 using HInput = HGraphicBufferProducer::DequeueBufferInput; 147 HInput input{w, h, static_cast<uint32_t>(format), usage}; 148 149 using HOutput = HGraphicBufferProducer::DequeueBufferOutput; 150 bool converted{}; 151 status_t bStatus{}; 152 Return<void> transResult = mBase->dequeueBuffer(input, 153 [&converted, &bStatus, slot, fence, outBufferAge] ( 154 HStatus hStatus, int32_t hSlot, HOutput const& hOutput) { 155 converted = h2b(hStatus, &bStatus); 156 if (!converted || bStatus != OK) { 157 return; 158 } 159 *slot = hSlot; 160 *outBufferAge = hOutput.bufferAge; 161 bStatus = 162 (hOutput.bufferNeedsReallocation ? 163 BUFFER_NEEDS_REALLOCATION : 0) | 164 (hOutput.releaseAllBuffers ? 165 RELEASE_ALL_BUFFERS : 0); 166 converted = h2b(hOutput.fence, fence); 167 }); 168 if (!transResult.isOk()) { 169 LOG(ERROR) << "dequeueBuffer: transaction failed."; 170 return FAILED_TRANSACTION; 171 } 172 if (!converted) { 173 LOG(ERROR) << "dequeueBuffer: corrupted transaction."; 174 return FAILED_TRANSACTION; 175 } 176 return bStatus; 177 } 178 179 status_t H2BGraphicBufferProducer::detachBuffer(int slot) { 180 status_t bStatus{}; 181 Return<HStatus> transResult = mBase->detachBuffer( 182 static_cast<int32_t>(slot)); 183 if (!transResult.isOk()) { 184 LOG(ERROR) << "detachBuffer: transaction failed."; 185 return FAILED_TRANSACTION; 186 } 187 if (!h2b(static_cast<HStatus>(transResult), &bStatus)) { 188 LOG(ERROR) << "detachBuffer: corrupted transaction."; 189 return FAILED_TRANSACTION; 190 } 191 return bStatus; 192 } 193 194 status_t H2BGraphicBufferProducer::detachNextBuffer( 195 sp<GraphicBuffer>* outBuffer, sp<BFence>* outFence) { 196 bool converted{}; 197 status_t bStatus{}; 198 Return<void> transResult = mBase->detachNextBuffer( 199 [&converted, &bStatus, outBuffer, outFence] ( 200 HStatus hStatus, 201 HardwareBuffer const& hBuffer, 202 hidl_handle const& hFence) { 203 converted = h2b(hStatus, &bStatus) && 204 h2b(hBuffer, outBuffer) && 205 h2b(hFence, outFence); 206 }); 207 if (!transResult.isOk()) { 208 LOG(ERROR) << "detachNextBuffer: transaction failed."; 209 return FAILED_TRANSACTION; 210 } 211 if (!converted) { 212 LOG(ERROR) << "detachNextBuffer: corrupted transaction."; 213 return FAILED_TRANSACTION; 214 } 215 return bStatus; 216 } 217 218 status_t H2BGraphicBufferProducer::attachBuffer( 219 int* outSlot, sp<GraphicBuffer> const& buffer) { 220 HardwareBuffer hBuffer{}; 221 uint32_t hGenerationNumber{}; 222 if (!b2h(buffer, &hBuffer, &hGenerationNumber)) { 223 LOG(ERROR) << "attachBuffer: invalid input buffer."; 224 return BAD_VALUE; 225 } 226 227 bool converted{}; 228 status_t bStatus{}; 229 Return<void> transResult = mBase->attachBuffer(hBuffer, hGenerationNumber, 230 [&converted, &bStatus, outSlot]( 231 HStatus hStatus, int32_t hSlot, bool releaseAllBuffers) { 232 converted = h2b(hStatus, &bStatus); 233 *outSlot = static_cast<int>(hSlot); 234 if (converted && releaseAllBuffers && bStatus == OK) { 235 bStatus = IGraphicBufferProducer::RELEASE_ALL_BUFFERS; 236 } 237 }); 238 if (!transResult.isOk()) { 239 LOG(ERROR) << "attachBuffer: transaction failed."; 240 return FAILED_TRANSACTION; 241 } 242 if (!converted) { 243 LOG(ERROR) << "attachBuffer: corrupted transaction."; 244 return FAILED_TRANSACTION; 245 } 246 return bStatus; 247 } 248 249 status_t H2BGraphicBufferProducer::queueBuffer( 250 int slot, 251 QueueBufferInput const& input, 252 QueueBufferOutput* output) { 253 HQueueBufferInput hInput{}; 254 HFenceWrapper hFenceWrapper; 255 if (!b2h(input, &hInput, &hFenceWrapper)) { 256 LOG(ERROR) << "queueBuffer: corrupted input."; 257 return UNKNOWN_ERROR; 258 } 259 260 bool converted{}; 261 status_t bStatus{}; 262 Return<void> transResult = mBase->queueBuffer( 263 static_cast<int32_t>(slot), 264 hInput, 265 [&converted, &bStatus, output]( 266 HStatus hStatus, 267 HQueueBufferOutput const& hOutput) { 268 converted = h2b(hStatus, &bStatus) && h2b(hOutput, output); 269 }); 270 271 if (!transResult.isOk()) { 272 LOG(ERROR) << "queueBuffer: transaction failed."; 273 return FAILED_TRANSACTION; 274 } 275 if (!converted) { 276 LOG(ERROR) << "queueBuffer: corrupted transaction."; 277 return FAILED_TRANSACTION; 278 } 279 return bStatus; 280 } 281 282 status_t H2BGraphicBufferProducer::cancelBuffer(int slot, sp<BFence> const& fence) { 283 HFenceWrapper hFenceWrapper; 284 if (!b2h(fence, &hFenceWrapper)) { 285 LOG(ERROR) << "cancelBuffer: corrupted input fence."; 286 return UNKNOWN_ERROR; 287 } 288 status_t bStatus{}; 289 Return<HStatus> transResult = mBase->cancelBuffer( 290 static_cast<int32_t>(slot), 291 hFenceWrapper.getHandle()); 292 if (!transResult.isOk()) { 293 LOG(ERROR) << "cancelBuffer: transaction failed."; 294 return FAILED_TRANSACTION; 295 } 296 if (!h2b(static_cast<HStatus>(transResult), &bStatus)) { 297 LOG(ERROR) << "cancelBuffer: corrupted transaction."; 298 return FAILED_TRANSACTION; 299 } 300 return bStatus; 301 } 302 303 int H2BGraphicBufferProducer::query(int what, int* value) { 304 int result{}; 305 Return<void> transResult = mBase->query( 306 static_cast<int32_t>(what), 307 [&result, value](int32_t r, int32_t v) { 308 result = static_cast<int>(r); 309 *value = static_cast<int>(v); 310 }); 311 if (!transResult.isOk()) { 312 LOG(ERROR) << "query: transaction failed."; 313 return FAILED_TRANSACTION; 314 } 315 return result; 316 } 317 318 status_t H2BGraphicBufferProducer::connect( 319 sp<IProducerListener> const& listener, int api, 320 bool producerControlledByApp, QueueBufferOutput* output) { 321 HConnectionType hConnectionType; 322 if (!b2h(api, &hConnectionType)) { 323 LOG(ERROR) << "connect: corrupted input connection type."; 324 return UNKNOWN_ERROR; 325 } 326 sp<HProducerListener> hListener = nullptr; 327 if (listener && listener->needsReleaseNotify()) { 328 hListener = new B2HProducerListener(listener); 329 if (!hListener) { 330 LOG(ERROR) << "connect: failed to wrap listener."; 331 return UNKNOWN_ERROR; 332 } 333 } 334 335 bool converted{}; 336 status_t bStatus{}; 337 Return<void> transResult = mBase->connect( 338 hListener, 339 hConnectionType, 340 producerControlledByApp, 341 [&converted, &bStatus, output]( 342 HStatus hStatus, 343 HQueueBufferOutput const& hOutput) { 344 converted = h2b(hStatus, &bStatus) && h2b(hOutput, output); 345 }); 346 if (!transResult.isOk()) { 347 LOG(ERROR) << "connect: transaction failed."; 348 return FAILED_TRANSACTION; 349 } 350 if (!converted) { 351 LOG(ERROR) << "connect: corrupted transaction."; 352 return FAILED_TRANSACTION; 353 } 354 return bStatus; 355 356 } 357 358 status_t H2BGraphicBufferProducer::disconnect(int api, DisconnectMode mode) { 359 HConnectionType hConnectionType; 360 if (mode == DisconnectMode::AllLocal) { 361 hConnectionType = HConnectionType::CURRENTLY_CONNECTED; 362 } else if (!b2h(api, &hConnectionType)) { 363 LOG(ERROR) << "connect: corrupted input connection type."; 364 return UNKNOWN_ERROR; 365 } 366 367 status_t bStatus{}; 368 Return<HStatus> transResult = mBase->disconnect(hConnectionType); 369 if (!transResult.isOk()) { 370 LOG(ERROR) << "disconnect: transaction failed."; 371 return FAILED_TRANSACTION; 372 } 373 if (!h2b(static_cast<HStatus>(transResult), &bStatus)) { 374 LOG(ERROR) << "disconnect: corrupted transaction."; 375 return FAILED_TRANSACTION; 376 } 377 return bStatus; 378 } 379 380 status_t H2BGraphicBufferProducer::setSidebandStream( 381 sp<NativeHandle> const& stream) { 382 if (stream) { 383 LOG(INFO) << "setSidebandStream: not supported."; 384 return INVALID_OPERATION; 385 } 386 return OK; 387 } 388 389 void H2BGraphicBufferProducer::allocateBuffers( 390 uint32_t width, uint32_t height, 391 PixelFormat format, uint64_t usage) { 392 status_t bStatus{}; 393 Return<HStatus> transResult = mBase->allocateBuffers( 394 width, height, static_cast<uint32_t>(format), usage); 395 if (!transResult.isOk()) { 396 LOG(ERROR) << "allocateBuffer: transaction failed."; 397 return; 398 } 399 if (!h2b(static_cast<HStatus>(transResult), &bStatus)) { 400 LOG(ERROR) << "allocateBuffer: corrupted transaction."; 401 return; 402 } 403 } 404 405 status_t H2BGraphicBufferProducer::allowAllocation(bool allow) { 406 status_t bStatus{}; 407 Return<HStatus> transResult = mBase->allowAllocation(allow); 408 if (!transResult.isOk()) { 409 LOG(ERROR) << "allowAllocation: transaction failed."; 410 return FAILED_TRANSACTION; 411 } 412 if (!h2b(static_cast<HStatus>(transResult), &bStatus)) { 413 LOG(ERROR) << "allowAllocation: corrupted transaction."; 414 return FAILED_TRANSACTION; 415 } 416 return bStatus; 417 } 418 419 status_t H2BGraphicBufferProducer::setGenerationNumber( 420 uint32_t generationNumber) { 421 status_t bStatus{}; 422 Return<HStatus> transResult = mBase->setGenerationNumber(generationNumber); 423 if (!transResult.isOk()) { 424 LOG(ERROR) << "setGenerationNumber: transaction failed."; 425 return FAILED_TRANSACTION; 426 } 427 if (!h2b(static_cast<HStatus>(transResult), &bStatus)) { 428 LOG(ERROR) << "setGenerationNumber: corrupted transaction."; 429 return FAILED_TRANSACTION; 430 } 431 return bStatus; 432 } 433 434 String8 H2BGraphicBufferProducer::getConsumerName() const { 435 String8 bName; 436 Return<void> transResult = mBase->getConsumerName( 437 [&bName](hidl_string const& name) { 438 bName = name.c_str(); 439 }); 440 return bName; 441 } 442 443 status_t H2BGraphicBufferProducer::setSharedBufferMode(bool sharedBufferMode) { 444 if (sharedBufferMode) { 445 LOG(INFO) << "setSharedBufferMode: not supported."; 446 return INVALID_OPERATION; 447 } 448 return OK; 449 } 450 451 status_t H2BGraphicBufferProducer::setAutoRefresh(bool autoRefresh) { 452 if (autoRefresh) { 453 LOG(INFO) << "setAutoRefresh: not supported."; 454 return INVALID_OPERATION; 455 } 456 return OK; 457 } 458 459 status_t H2BGraphicBufferProducer::setDequeueTimeout(nsecs_t timeout) { 460 status_t bStatus{}; 461 Return<HStatus> transResult = mBase->setDequeueTimeout( 462 static_cast<int64_t>(timeout)); 463 if (!transResult.isOk()) { 464 LOG(ERROR) << "setDequeueTimeout: transaction failed."; 465 return FAILED_TRANSACTION; 466 } 467 if (!h2b(static_cast<HStatus>(transResult), &bStatus)) { 468 LOG(ERROR) << "setDequeueTimeout: corrupted transaction."; 469 return FAILED_TRANSACTION; 470 } 471 return bStatus; 472 } 473 474 status_t H2BGraphicBufferProducer::getLastQueuedBuffer( 475 sp<GraphicBuffer>*, 476 sp<BFence>*, 477 float[16]) { 478 LOG(INFO) << "getLastQueuedBuffer: not supported."; 479 return INVALID_OPERATION; 480 } 481 482 void H2BGraphicBufferProducer::getFrameTimestamps(FrameEventHistoryDelta*) { 483 LOG(INFO) << "getFrameTimestamps: not supported."; 484 } 485 486 status_t H2BGraphicBufferProducer::getUniqueId(uint64_t* outId) const { 487 Return<uint64_t> transResult = mBase->getUniqueId(); 488 if (!transResult.isOk()) { 489 LOG(ERROR) << "getUniqueId: transaction failed."; 490 return FAILED_TRANSACTION; 491 } 492 *outId = static_cast<uint64_t>(transResult); 493 return OK; 494 } 495 496 status_t H2BGraphicBufferProducer::getConsumerUsage(uint64_t*) const { 497 LOG(INFO) << "getConsumerUsage: not supported."; 498 return INVALID_OPERATION; 499 } 500 501 } // namespace utils 502 } // namespace V2_0 503 } // namespace bufferqueue 504 } // namespace graphics 505 } // namespace hardware 506 } // namespace android 507