/* * Copyright 2019 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ //#define LOG_NDEBUG 0 #define LOG_TAG "B2HGraphicBufferProducer@2.0" #include #include #include #include #include #include #include #include #include #include namespace android { namespace hardware { namespace graphics { namespace bufferqueue { namespace V2_0 { namespace utils { namespace /* unnamed */ { using BQueueBufferInput = ::android:: IGraphicBufferProducer::QueueBufferInput; using HQueueBufferInput = ::android::hardware::graphics::bufferqueue::V2_0:: IGraphicBufferProducer::QueueBufferInput; using BQueueBufferOutput = ::android:: IGraphicBufferProducer::QueueBufferOutput; using HQueueBufferOutput = ::android::hardware::graphics::bufferqueue::V2_0:: IGraphicBufferProducer::QueueBufferOutput; using ::android::hardware::graphics::bufferqueue::V2_0::utils::b2h; using ::android::hardware::graphics::bufferqueue::V2_0::utils::h2b; bool b2h(BQueueBufferOutput const& from, HQueueBufferOutput* to) { to->width = from.width; to->height = from.height; to->transformHint = static_cast(from.transformHint); to->numPendingBuffers = from.numPendingBuffers; to->nextFrameNumber = from.nextFrameNumber; to->bufferReplaced = from.bufferReplaced; return true; } } // unnamed namespace // B2HGraphicBufferProducer // ======================== B2HGraphicBufferProducer::B2HGraphicBufferProducer( sp const& base) : mBase{base} { } Return B2HGraphicBufferProducer::setMaxDequeuedBufferCount( int32_t maxDequeuedBuffers) { HStatus hStatus{}; bool converted = b2h( mBase->setMaxDequeuedBufferCount( static_cast(maxDequeuedBuffers)), &hStatus); return {converted ? hStatus : HStatus::UNKNOWN_ERROR}; } Return B2HGraphicBufferProducer::requestBuffer( int32_t slot, requestBuffer_cb _hidl_cb) { sp bBuffer; HStatus hStatus{}; HardwareBuffer hBuffer{}; uint32_t hGenerationNumber{}; bool converted = b2h(mBase->requestBuffer( static_cast(slot), &bBuffer), &hStatus) && b2h(bBuffer, &hBuffer, &hGenerationNumber); _hidl_cb(converted ? hStatus : HStatus::UNKNOWN_ERROR, hBuffer, hGenerationNumber); return {}; } Return B2HGraphicBufferProducer::setAsyncMode(bool async) { HStatus hStatus{}; bool converted = b2h(mBase->setAsyncMode(async), &hStatus); return {converted ? hStatus : HStatus::UNKNOWN_ERROR}; } Return B2HGraphicBufferProducer::dequeueBuffer( DequeueBufferInput const& input, dequeueBuffer_cb _hidl_cb) { int bSlot{}; sp bFence; HStatus hStatus{}; DequeueBufferOutput hOutput{}; HFenceWrapper hFenceWrapper; bool converted = b2h(mBase->dequeueBuffer( &bSlot, &bFence, input.width, input.height, static_cast(input.format), input.usage, &hOutput.bufferAge, nullptr /* outTimestamps */), &hStatus, &hOutput.bufferNeedsReallocation, &hOutput.releaseAllBuffers) && b2h(bFence, &hFenceWrapper); hOutput.fence = hFenceWrapper.getHandle(); _hidl_cb(converted ? hStatus : HStatus::UNKNOWN_ERROR, static_cast(bSlot), hOutput); return {}; } Return B2HGraphicBufferProducer::detachBuffer(int32_t slot) { HStatus hStatus{}; bool converted = b2h( mBase->detachBuffer(static_cast(slot)), &hStatus); return {converted ? hStatus : HStatus::UNKNOWN_ERROR}; } Return B2HGraphicBufferProducer::detachNextBuffer( detachNextBuffer_cb _hidl_cb) { sp bBuffer; sp bFence; HStatus hStatus{}; HardwareBuffer hBuffer{}; HFenceWrapper hFenceWrapper; bool converted = b2h(mBase->detachNextBuffer(&bBuffer, &bFence), &hStatus) && b2h(bBuffer, &hBuffer) && b2h(bFence, &hFenceWrapper); _hidl_cb(converted ? hStatus : HStatus::UNKNOWN_ERROR, hBuffer, hFenceWrapper.getHandle()); return {}; } Return B2HGraphicBufferProducer::attachBuffer( HardwareBuffer const& hBuffer, uint32_t generationNumber, attachBuffer_cb _hidl_cb) { sp bBuffer; if (!h2b(hBuffer, &bBuffer) || !bBuffer) { _hidl_cb(HStatus::UNKNOWN_ERROR, static_cast(SlotIndex::INVALID), false); return {}; } bBuffer->setGenerationNumber(generationNumber); int bSlot{}; HStatus hStatus{}; bool releaseAllBuffers{}; bool converted = b2h( mBase->attachBuffer(&bSlot, bBuffer), &hStatus, nullptr /* bufferNeedsReallocation */, &releaseAllBuffers); _hidl_cb(converted ? hStatus : HStatus::UNKNOWN_ERROR, static_cast(bSlot), releaseAllBuffers); return {}; } Return B2HGraphicBufferProducer::queueBuffer( int32_t slot, QueueBufferInput const& hInput, queueBuffer_cb _hidl_cb) { BQueueBufferInput bInput{ hInput.timestamp, hInput.isAutoTimestamp, static_cast(hInput.dataSpace), {}, /* crop */ 0 /* scalingMode = NATIVE_WINDOW_SCALING_MODE_FREEZE */, static_cast(hInput.transform), {}, /* fence */ static_cast(hInput.stickyTransform), false /* getFrameTimestamps */}; // Convert crop. if (!h2b(hInput.crop, &bInput.crop)) { _hidl_cb(HStatus::UNKNOWN_ERROR, QueueBufferOutput{}); return {}; } // Convert surfaceDamage. if (!h2b(hInput.surfaceDamage, &bInput.surfaceDamage)) { _hidl_cb(HStatus::UNKNOWN_ERROR, QueueBufferOutput{}); return {}; } // Convert fence. if (!h2b(hInput.fence, &bInput.fence)) { _hidl_cb(HStatus::UNKNOWN_ERROR, QueueBufferOutput{}); return {}; } BQueueBufferOutput bOutput{}; HStatus hStatus{}; QueueBufferOutput hOutput{}; bool converted = b2h( mBase->queueBuffer(static_cast(slot), bInput, &bOutput), &hStatus) && b2h(bOutput, &hOutput); _hidl_cb(converted ? hStatus : HStatus::UNKNOWN_ERROR, hOutput); return {}; } Return B2HGraphicBufferProducer::cancelBuffer( int32_t slot, hidl_handle const& fence) { sp bFence; if (!h2b(fence.getNativeHandle(), &bFence)) { return {HStatus::UNKNOWN_ERROR}; } HStatus hStatus{}; bool converted = b2h( mBase->cancelBuffer(static_cast(slot), bFence), &hStatus); return {converted ? hStatus : HStatus::UNKNOWN_ERROR}; } Return B2HGraphicBufferProducer::query(int32_t what, query_cb _hidl_cb) { int value{}; int result = mBase->query(static_cast(what), &value); _hidl_cb(static_cast(result), static_cast(value)); return {}; } struct Obituary : public hardware::hidl_death_recipient { wp producer; sp listener; HConnectionType apiType; Obituary(const wp& p, const sp& l, HConnectionType t) : producer(p), listener(l), apiType(t) {} void serviceDied(uint64_t /* cookie */, const wp<::android::hidl::base::V1_0::IBase>& /* who */) override { sp dr = producer.promote(); if (dr != nullptr) { (void)dr->disconnect(apiType); } } }; Return B2HGraphicBufferProducer::connect( sp const& hListener, HConnectionType hConnectionType, bool producerControlledByApp, connect_cb _hidl_cb) { sp bListener = new H2BProducerListener(hListener); int bConnectionType{}; if (!bListener || !h2b(hConnectionType, &bConnectionType)) { _hidl_cb(HStatus::UNKNOWN_ERROR, QueueBufferOutput{}); return {}; } BQueueBufferOutput bOutput{}; HStatus hStatus{}; QueueBufferOutput hOutput{}; bool converted = b2h(mBase->connect(bListener, bConnectionType, producerControlledByApp, &bOutput), &hStatus) && b2h(bOutput, &hOutput); #ifdef NO_BINDER if (converted && hListener != nullptr) { mObituary = new Obituary(this, hListener, hConnectionType); hListener->linkToDeath(mObituary, 0); } #endif // NO_BINDER _hidl_cb(converted ? hStatus : HStatus::UNKNOWN_ERROR, hOutput); return {}; } Return B2HGraphicBufferProducer::disconnect( HConnectionType hConnectionType) { int bConnectionType; if (!h2b(hConnectionType, &bConnectionType)) { return {HStatus::UNKNOWN_ERROR}; } HStatus hStatus{}; bool converted = b2h(mBase->disconnect(bConnectionType), &hStatus); #ifdef NO_BINDER if (mObituary != nullptr) { mObituary->listener->unlinkToDeath(mObituary); mObituary.clear(); } #endif // NO_BINDER return {converted ? hStatus : HStatus::UNKNOWN_ERROR}; } Return B2HGraphicBufferProducer::allocateBuffers( uint32_t width, uint32_t height, uint32_t format, uint64_t usage) { mBase->allocateBuffers( width, height, static_cast(format), usage); return {HStatus::OK}; } Return B2HGraphicBufferProducer::allowAllocation(bool allow) { HStatus hStatus{}; bool converted = b2h(mBase->allowAllocation(allow), &hStatus); return {converted ? hStatus : HStatus::UNKNOWN_ERROR}; } Return B2HGraphicBufferProducer::setGenerationNumber( uint32_t generationNumber) { HStatus hStatus{}; bool converted = b2h( mBase->setGenerationNumber(generationNumber), &hStatus); return {converted ? hStatus : HStatus::UNKNOWN_ERROR}; } Return B2HGraphicBufferProducer::setDequeueTimeout( int64_t timeoutNs) { HStatus hStatus{}; bool converted = b2h( mBase->setDequeueTimeout(static_cast(timeoutNs)), &hStatus); return {converted ? hStatus : HStatus::UNKNOWN_ERROR}; } Return B2HGraphicBufferProducer::getUniqueId() { uint64_t outId{}; HStatus hStatus{}; bool converted = b2h(mBase->getUniqueId(&outId), &hStatus); return {converted ? outId : 0}; } Return B2HGraphicBufferProducer::getConsumerName( getConsumerName_cb _hidl_cb) { _hidl_cb(hidl_string{mBase->getConsumerName().c_str()}); return {}; } } // namespace utils } // namespace V2_0 } // namespace bufferqueue } // namespace graphics } // namespace hardware } // namespace android