Loading libs/gui/BLASTBufferQueue.cpp +84 −4 Original line number Diff line number Diff line Loading @@ -31,6 +31,68 @@ using namespace std::chrono_literals; namespace android { void BLASTBufferItemConsumer::onDisconnect() { Mutex::Autolock lock(mFrameEventHistoryMutex); mPreviouslyConnected = mCurrentlyConnected; mCurrentlyConnected = false; if (mPreviouslyConnected) { mDisconnectEvents.push(mCurrentFrameNumber); } mFrameEventHistory.onDisconnect(); } void BLASTBufferItemConsumer::addAndGetFrameTimestamps(const NewFrameEventsEntry* newTimestamps, FrameEventHistoryDelta* outDelta) { Mutex::Autolock lock(mFrameEventHistoryMutex); if (newTimestamps) { // BufferQueueProducer only adds a new timestamp on // queueBuffer mCurrentFrameNumber = newTimestamps->frameNumber; mFrameEventHistory.addQueue(*newTimestamps); } if (outDelta) { // frame event histories will be processed // only after the producer connects and requests // deltas for the first time. Forward this intent // to SF-side to turn event processing back on mPreviouslyConnected = mCurrentlyConnected; mCurrentlyConnected = true; mFrameEventHistory.getAndResetDelta(outDelta); } } void BLASTBufferItemConsumer::updateFrameTimestamps(uint64_t frameNumber, nsecs_t refreshStartTime, const sp<Fence>& glDoneFence, const sp<Fence>& presentFence, const sp<Fence>& prevReleaseFence, CompositorTiming compositorTiming, nsecs_t latchTime, nsecs_t dequeueReadyTime) { Mutex::Autolock lock(mFrameEventHistoryMutex); // if the producer is not connected, don't bother updating, // the next producer that connects won't access this frame event if (!mCurrentlyConnected) return; std::shared_ptr<FenceTime> glDoneFenceTime = std::make_shared<FenceTime>(glDoneFence); std::shared_ptr<FenceTime> presentFenceTime = std::make_shared<FenceTime>(presentFence); std::shared_ptr<FenceTime> releaseFenceTime = std::make_shared<FenceTime>(prevReleaseFence); mFrameEventHistory.addLatch(frameNumber, latchTime); mFrameEventHistory.addRelease(frameNumber, dequeueReadyTime, std::move(releaseFenceTime)); mFrameEventHistory.addPreComposition(frameNumber, refreshStartTime); mFrameEventHistory.addPostComposition(frameNumber, glDoneFenceTime, presentFenceTime, compositorTiming); } void BLASTBufferItemConsumer::getConnectionEvents(uint64_t frameNumber, bool* needsDisconnect) { bool disconnect = false; Mutex::Autolock lock(mFrameEventHistoryMutex); while (!mDisconnectEvents.empty() && mDisconnectEvents.front() <= frameNumber) { disconnect = true; mDisconnectEvents.pop(); } if (needsDisconnect != nullptr) *needsDisconnect = disconnect; } BLASTBufferQueue::BLASTBufferQueue(const sp<SurfaceControl>& surface, int width, int height) : mSurfaceControl(surface), mWidth(width), Loading @@ -39,7 +101,7 @@ BLASTBufferQueue::BLASTBufferQueue(const sp<SurfaceControl>& surface, int width, BufferQueue::createBufferQueue(&mProducer, &mConsumer); mConsumer->setMaxAcquiredBufferCount(MAX_ACQUIRED_BUFFERS); mBufferItemConsumer = new BufferItemConsumer(mConsumer, AHARDWAREBUFFER_USAGE_GPU_FRAMEBUFFER, 1, true); new BLASTBufferItemConsumer(mConsumer, AHARDWAREBUFFER_USAGE_GPU_FRAMEBUFFER, 1, true); static int32_t id = 0; auto name = std::string("BLAST Consumer") + std::to_string(id); id++; Loading Loading @@ -79,11 +141,21 @@ void BLASTBufferQueue::transactionCallback(nsecs_t /*latchTime*/, const sp<Fence std::unique_lock _lock{mMutex}; ATRACE_CALL(); if (mPendingReleaseItem.item.mGraphicBuffer != nullptr) { if (stats.size() > 0) { mPendingReleaseItem.releaseFence = stats[0].previousReleaseFence; if (!stats.empty()) { mTransformHint = stats[0].transformHint; mBufferItemConsumer->setTransformHint(mTransformHint); mBufferItemConsumer->updateFrameTimestamps(stats[0].frameEventStats.frameNumber, stats[0].frameEventStats.refreshStartTime, stats[0].frameEventStats.gpuCompositionDoneFence, stats[0].presentFence, stats[0].previousReleaseFence, stats[0].frameEventStats.compositorTiming, stats[0].latchTime, stats[0].frameEventStats.dequeueReadyTime); } if (mPendingReleaseItem.item.mGraphicBuffer != nullptr) { if (!stats.empty()) { mPendingReleaseItem.releaseFence = stats[0].previousReleaseFence; } else { ALOGE("Warning: no SurfaceControlStats returned in BLASTBufferQueue callback"); mPendingReleaseItem.releaseFence = nullptr; Loading Loading @@ -144,6 +216,14 @@ void BLASTBufferQueue::processNextBufferLocked() { mNumAcquired++; mSubmitted.push(bufferItem); bool needsDisconnect = false; mBufferItemConsumer->getConnectionEvents(bufferItem.mFrameNumber, &needsDisconnect); // if producer disconnected before, notify SurfaceFlinger if (needsDisconnect) { t->notifyProducerDisconnect(mSurfaceControl); } // Ensure BLASTBufferQueue stays alive until we receive the transaction complete callback. incStrong((void*)transactionCallbackThunk); Loading libs/gui/ITransactionCompletedListener.cpp +70 −0 Original line number Diff line number Diff line Loading @@ -30,6 +30,66 @@ enum class Tag : uint32_t { } // Anonymous namespace status_t FrameEventHistoryStats::writeToParcel(Parcel* output) const { status_t err = output->writeUint64(frameNumber); if (err != NO_ERROR) return err; if (gpuCompositionDoneFence) { err = output->writeBool(true); if (err != NO_ERROR) return err; err = output->write(*gpuCompositionDoneFence); } else { err = output->writeBool(false); } if (err != NO_ERROR) return err; err = output->writeInt64(compositorTiming.deadline); if (err != NO_ERROR) return err; err = output->writeInt64(compositorTiming.interval); if (err != NO_ERROR) return err; err = output->writeInt64(compositorTiming.presentLatency); if (err != NO_ERROR) return err; err = output->writeInt64(refreshStartTime); if (err != NO_ERROR) return err; err = output->writeInt64(dequeueReadyTime); return err; } status_t FrameEventHistoryStats::readFromParcel(const Parcel* input) { status_t err = input->readUint64(&frameNumber); if (err != NO_ERROR) return err; bool hasFence = false; err = input->readBool(&hasFence); if (err != NO_ERROR) return err; if (hasFence) { gpuCompositionDoneFence = new Fence(); err = input->read(*gpuCompositionDoneFence); if (err != NO_ERROR) return err; } err = input->readInt64(&(compositorTiming.deadline)); if (err != NO_ERROR) return err; err = input->readInt64(&(compositorTiming.interval)); if (err != NO_ERROR) return err; err = input->readInt64(&(compositorTiming.presentLatency)); if (err != NO_ERROR) return err; err = input->readInt64(&refreshStartTime); if (err != NO_ERROR) return err; err = input->readInt64(&dequeueReadyTime); return err; } status_t SurfaceStats::writeToParcel(Parcel* output) const { status_t err = output->writeStrongBinder(surfaceControl); if (err != NO_ERROR) { Loading @@ -49,6 +109,11 @@ status_t SurfaceStats::writeToParcel(Parcel* output) const { err = output->writeBool(false); } err = output->writeUint32(transformHint); if (err != NO_ERROR) { return err; } err = output->writeParcelable(eventStats); return err; } Loading @@ -74,6 +139,11 @@ status_t SurfaceStats::readFromParcel(const Parcel* input) { } } err = input->readUint32(&transformHint); if (err != NO_ERROR) { return err; } err = input->readParcelable(&eventStats); return err; } Loading libs/gui/SurfaceComposerClient.cpp +16 −2 Original line number Diff line number Diff line Loading @@ -222,8 +222,10 @@ void TransactionCompletedListener::onTransactionCompleted(ListenerStats listener surfaceControlStats .emplace_back(callbacksMap[callbackId] .surfaceControls[surfaceStats.surfaceControl], surfaceStats.acquireTime, surfaceStats.previousReleaseFence, surfaceStats.transformHint); transactionStats.latchTime, surfaceStats.acquireTime, transactionStats.presentFence, surfaceStats.previousReleaseFence, surfaceStats.transformHint, surfaceStats.eventStats); if (callbacksMap[callbackId].surfaceControls[surfaceStats.surfaceControl]) { callbacksMap[callbackId] .surfaceControls[surfaceStats.surfaceControl] Loading Loading @@ -1235,6 +1237,18 @@ SurfaceComposerClient::Transaction::addTransactionCompletedCallback( return *this; } SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::notifyProducerDisconnect( const sp<SurfaceControl>& sc) { layer_state_t* s = getLayerState(sc); if (!s) { mStatus = BAD_INDEX; return *this; } s->what |= layer_state_t::eProducerDisconnect; return *this; } SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::detachChildren( const sp<SurfaceControl>& sc) { layer_state_t* s = getLayerState(sc); Loading libs/gui/include/gui/BLASTBufferQueue.h +30 −1 Original line number Diff line number Diff line Loading @@ -33,6 +33,35 @@ namespace android { class BufferItemConsumer; class BLASTBufferItemConsumer : public BufferItemConsumer { public: BLASTBufferItemConsumer(const sp<IGraphicBufferConsumer>& consumer, uint64_t consumerUsage, int bufferCount, bool controlledByApp) : BufferItemConsumer(consumer, consumerUsage, bufferCount, controlledByApp), mCurrentlyConnected(false), mPreviouslyConnected(false) {} void onDisconnect() override; void addAndGetFrameTimestamps(const NewFrameEventsEntry* newTimestamps, FrameEventHistoryDelta* outDelta) override REQUIRES(mFrameEventHistoryMutex); void updateFrameTimestamps(uint64_t frameNumber, nsecs_t refreshStartTime, const sp<Fence>& gpuCompositionDoneFence, const sp<Fence>& presentFence, const sp<Fence>& prevReleaseFence, CompositorTiming compositorTiming, nsecs_t latchTime, nsecs_t dequeueReadyTime) REQUIRES(mFrameEventHistoryMutex); void getConnectionEvents(uint64_t frameNumber, bool* needsDisconnect); private: uint64_t mCurrentFrameNumber = 0; Mutex mFrameEventHistoryMutex; ConsumerFrameEventHistory mFrameEventHistory GUARDED_BY(mFrameEventHistoryMutex); std::queue<uint64_t> mDisconnectEvents GUARDED_BY(mFrameEventHistoryMutex); bool mCurrentlyConnected GUARDED_BY(mFrameEventHistoryMutex); bool mPreviouslyConnected GUARDED_BY(mFrameEventHistoryMutex); }; class BLASTBufferQueue : public ConsumerBase::FrameAvailableListener, public BufferItemConsumer::BufferFreedListener { Loading Loading @@ -89,7 +118,7 @@ private: sp<IGraphicBufferConsumer> mConsumer; sp<IGraphicBufferProducer> mProducer; sp<BufferItemConsumer> mBufferItemConsumer; sp<BLASTBufferItemConsumer> mBufferItemConsumer; SurfaceComposerClient::Transaction* mNextTransaction GUARDED_BY(mMutex); }; Loading libs/gui/include/gui/FrameTimestamps.h +0 −1 Original line number Diff line number Diff line Loading @@ -174,7 +174,6 @@ struct NewFrameEventsEntry { std::shared_ptr<FenceTime> acquireFence{FenceTime::NO_FENCE}; }; // Used by the consumer to keep track of which fields it already sent to // the producer. class FrameEventDirtyFields { Loading Loading
libs/gui/BLASTBufferQueue.cpp +84 −4 Original line number Diff line number Diff line Loading @@ -31,6 +31,68 @@ using namespace std::chrono_literals; namespace android { void BLASTBufferItemConsumer::onDisconnect() { Mutex::Autolock lock(mFrameEventHistoryMutex); mPreviouslyConnected = mCurrentlyConnected; mCurrentlyConnected = false; if (mPreviouslyConnected) { mDisconnectEvents.push(mCurrentFrameNumber); } mFrameEventHistory.onDisconnect(); } void BLASTBufferItemConsumer::addAndGetFrameTimestamps(const NewFrameEventsEntry* newTimestamps, FrameEventHistoryDelta* outDelta) { Mutex::Autolock lock(mFrameEventHistoryMutex); if (newTimestamps) { // BufferQueueProducer only adds a new timestamp on // queueBuffer mCurrentFrameNumber = newTimestamps->frameNumber; mFrameEventHistory.addQueue(*newTimestamps); } if (outDelta) { // frame event histories will be processed // only after the producer connects and requests // deltas for the first time. Forward this intent // to SF-side to turn event processing back on mPreviouslyConnected = mCurrentlyConnected; mCurrentlyConnected = true; mFrameEventHistory.getAndResetDelta(outDelta); } } void BLASTBufferItemConsumer::updateFrameTimestamps(uint64_t frameNumber, nsecs_t refreshStartTime, const sp<Fence>& glDoneFence, const sp<Fence>& presentFence, const sp<Fence>& prevReleaseFence, CompositorTiming compositorTiming, nsecs_t latchTime, nsecs_t dequeueReadyTime) { Mutex::Autolock lock(mFrameEventHistoryMutex); // if the producer is not connected, don't bother updating, // the next producer that connects won't access this frame event if (!mCurrentlyConnected) return; std::shared_ptr<FenceTime> glDoneFenceTime = std::make_shared<FenceTime>(glDoneFence); std::shared_ptr<FenceTime> presentFenceTime = std::make_shared<FenceTime>(presentFence); std::shared_ptr<FenceTime> releaseFenceTime = std::make_shared<FenceTime>(prevReleaseFence); mFrameEventHistory.addLatch(frameNumber, latchTime); mFrameEventHistory.addRelease(frameNumber, dequeueReadyTime, std::move(releaseFenceTime)); mFrameEventHistory.addPreComposition(frameNumber, refreshStartTime); mFrameEventHistory.addPostComposition(frameNumber, glDoneFenceTime, presentFenceTime, compositorTiming); } void BLASTBufferItemConsumer::getConnectionEvents(uint64_t frameNumber, bool* needsDisconnect) { bool disconnect = false; Mutex::Autolock lock(mFrameEventHistoryMutex); while (!mDisconnectEvents.empty() && mDisconnectEvents.front() <= frameNumber) { disconnect = true; mDisconnectEvents.pop(); } if (needsDisconnect != nullptr) *needsDisconnect = disconnect; } BLASTBufferQueue::BLASTBufferQueue(const sp<SurfaceControl>& surface, int width, int height) : mSurfaceControl(surface), mWidth(width), Loading @@ -39,7 +101,7 @@ BLASTBufferQueue::BLASTBufferQueue(const sp<SurfaceControl>& surface, int width, BufferQueue::createBufferQueue(&mProducer, &mConsumer); mConsumer->setMaxAcquiredBufferCount(MAX_ACQUIRED_BUFFERS); mBufferItemConsumer = new BufferItemConsumer(mConsumer, AHARDWAREBUFFER_USAGE_GPU_FRAMEBUFFER, 1, true); new BLASTBufferItemConsumer(mConsumer, AHARDWAREBUFFER_USAGE_GPU_FRAMEBUFFER, 1, true); static int32_t id = 0; auto name = std::string("BLAST Consumer") + std::to_string(id); id++; Loading Loading @@ -79,11 +141,21 @@ void BLASTBufferQueue::transactionCallback(nsecs_t /*latchTime*/, const sp<Fence std::unique_lock _lock{mMutex}; ATRACE_CALL(); if (mPendingReleaseItem.item.mGraphicBuffer != nullptr) { if (stats.size() > 0) { mPendingReleaseItem.releaseFence = stats[0].previousReleaseFence; if (!stats.empty()) { mTransformHint = stats[0].transformHint; mBufferItemConsumer->setTransformHint(mTransformHint); mBufferItemConsumer->updateFrameTimestamps(stats[0].frameEventStats.frameNumber, stats[0].frameEventStats.refreshStartTime, stats[0].frameEventStats.gpuCompositionDoneFence, stats[0].presentFence, stats[0].previousReleaseFence, stats[0].frameEventStats.compositorTiming, stats[0].latchTime, stats[0].frameEventStats.dequeueReadyTime); } if (mPendingReleaseItem.item.mGraphicBuffer != nullptr) { if (!stats.empty()) { mPendingReleaseItem.releaseFence = stats[0].previousReleaseFence; } else { ALOGE("Warning: no SurfaceControlStats returned in BLASTBufferQueue callback"); mPendingReleaseItem.releaseFence = nullptr; Loading Loading @@ -144,6 +216,14 @@ void BLASTBufferQueue::processNextBufferLocked() { mNumAcquired++; mSubmitted.push(bufferItem); bool needsDisconnect = false; mBufferItemConsumer->getConnectionEvents(bufferItem.mFrameNumber, &needsDisconnect); // if producer disconnected before, notify SurfaceFlinger if (needsDisconnect) { t->notifyProducerDisconnect(mSurfaceControl); } // Ensure BLASTBufferQueue stays alive until we receive the transaction complete callback. incStrong((void*)transactionCallbackThunk); Loading
libs/gui/ITransactionCompletedListener.cpp +70 −0 Original line number Diff line number Diff line Loading @@ -30,6 +30,66 @@ enum class Tag : uint32_t { } // Anonymous namespace status_t FrameEventHistoryStats::writeToParcel(Parcel* output) const { status_t err = output->writeUint64(frameNumber); if (err != NO_ERROR) return err; if (gpuCompositionDoneFence) { err = output->writeBool(true); if (err != NO_ERROR) return err; err = output->write(*gpuCompositionDoneFence); } else { err = output->writeBool(false); } if (err != NO_ERROR) return err; err = output->writeInt64(compositorTiming.deadline); if (err != NO_ERROR) return err; err = output->writeInt64(compositorTiming.interval); if (err != NO_ERROR) return err; err = output->writeInt64(compositorTiming.presentLatency); if (err != NO_ERROR) return err; err = output->writeInt64(refreshStartTime); if (err != NO_ERROR) return err; err = output->writeInt64(dequeueReadyTime); return err; } status_t FrameEventHistoryStats::readFromParcel(const Parcel* input) { status_t err = input->readUint64(&frameNumber); if (err != NO_ERROR) return err; bool hasFence = false; err = input->readBool(&hasFence); if (err != NO_ERROR) return err; if (hasFence) { gpuCompositionDoneFence = new Fence(); err = input->read(*gpuCompositionDoneFence); if (err != NO_ERROR) return err; } err = input->readInt64(&(compositorTiming.deadline)); if (err != NO_ERROR) return err; err = input->readInt64(&(compositorTiming.interval)); if (err != NO_ERROR) return err; err = input->readInt64(&(compositorTiming.presentLatency)); if (err != NO_ERROR) return err; err = input->readInt64(&refreshStartTime); if (err != NO_ERROR) return err; err = input->readInt64(&dequeueReadyTime); return err; } status_t SurfaceStats::writeToParcel(Parcel* output) const { status_t err = output->writeStrongBinder(surfaceControl); if (err != NO_ERROR) { Loading @@ -49,6 +109,11 @@ status_t SurfaceStats::writeToParcel(Parcel* output) const { err = output->writeBool(false); } err = output->writeUint32(transformHint); if (err != NO_ERROR) { return err; } err = output->writeParcelable(eventStats); return err; } Loading @@ -74,6 +139,11 @@ status_t SurfaceStats::readFromParcel(const Parcel* input) { } } err = input->readUint32(&transformHint); if (err != NO_ERROR) { return err; } err = input->readParcelable(&eventStats); return err; } Loading
libs/gui/SurfaceComposerClient.cpp +16 −2 Original line number Diff line number Diff line Loading @@ -222,8 +222,10 @@ void TransactionCompletedListener::onTransactionCompleted(ListenerStats listener surfaceControlStats .emplace_back(callbacksMap[callbackId] .surfaceControls[surfaceStats.surfaceControl], surfaceStats.acquireTime, surfaceStats.previousReleaseFence, surfaceStats.transformHint); transactionStats.latchTime, surfaceStats.acquireTime, transactionStats.presentFence, surfaceStats.previousReleaseFence, surfaceStats.transformHint, surfaceStats.eventStats); if (callbacksMap[callbackId].surfaceControls[surfaceStats.surfaceControl]) { callbacksMap[callbackId] .surfaceControls[surfaceStats.surfaceControl] Loading Loading @@ -1235,6 +1237,18 @@ SurfaceComposerClient::Transaction::addTransactionCompletedCallback( return *this; } SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::notifyProducerDisconnect( const sp<SurfaceControl>& sc) { layer_state_t* s = getLayerState(sc); if (!s) { mStatus = BAD_INDEX; return *this; } s->what |= layer_state_t::eProducerDisconnect; return *this; } SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::detachChildren( const sp<SurfaceControl>& sc) { layer_state_t* s = getLayerState(sc); Loading
libs/gui/include/gui/BLASTBufferQueue.h +30 −1 Original line number Diff line number Diff line Loading @@ -33,6 +33,35 @@ namespace android { class BufferItemConsumer; class BLASTBufferItemConsumer : public BufferItemConsumer { public: BLASTBufferItemConsumer(const sp<IGraphicBufferConsumer>& consumer, uint64_t consumerUsage, int bufferCount, bool controlledByApp) : BufferItemConsumer(consumer, consumerUsage, bufferCount, controlledByApp), mCurrentlyConnected(false), mPreviouslyConnected(false) {} void onDisconnect() override; void addAndGetFrameTimestamps(const NewFrameEventsEntry* newTimestamps, FrameEventHistoryDelta* outDelta) override REQUIRES(mFrameEventHistoryMutex); void updateFrameTimestamps(uint64_t frameNumber, nsecs_t refreshStartTime, const sp<Fence>& gpuCompositionDoneFence, const sp<Fence>& presentFence, const sp<Fence>& prevReleaseFence, CompositorTiming compositorTiming, nsecs_t latchTime, nsecs_t dequeueReadyTime) REQUIRES(mFrameEventHistoryMutex); void getConnectionEvents(uint64_t frameNumber, bool* needsDisconnect); private: uint64_t mCurrentFrameNumber = 0; Mutex mFrameEventHistoryMutex; ConsumerFrameEventHistory mFrameEventHistory GUARDED_BY(mFrameEventHistoryMutex); std::queue<uint64_t> mDisconnectEvents GUARDED_BY(mFrameEventHistoryMutex); bool mCurrentlyConnected GUARDED_BY(mFrameEventHistoryMutex); bool mPreviouslyConnected GUARDED_BY(mFrameEventHistoryMutex); }; class BLASTBufferQueue : public ConsumerBase::FrameAvailableListener, public BufferItemConsumer::BufferFreedListener { Loading Loading @@ -89,7 +118,7 @@ private: sp<IGraphicBufferConsumer> mConsumer; sp<IGraphicBufferProducer> mProducer; sp<BufferItemConsumer> mBufferItemConsumer; sp<BLASTBufferItemConsumer> mBufferItemConsumer; SurfaceComposerClient::Transaction* mNextTransaction GUARDED_BY(mMutex); }; Loading
libs/gui/include/gui/FrameTimestamps.h +0 −1 Original line number Diff line number Diff line Loading @@ -174,7 +174,6 @@ struct NewFrameEventsEntry { std::shared_ptr<FenceTime> acquireFence{FenceTime::NO_FENCE}; }; // Used by the consumer to keep track of which fields it already sent to // the producer. class FrameEventDirtyFields { Loading