diff options
author | 2020-01-29 08:44:02 -0800 | |
---|---|---|
committer | 2020-02-05 15:21:11 -0800 | |
commit | 871d635736f502e67e6b41a162d4c77826cf6523 (patch) | |
tree | 3fafeaf37ac3f73dcbf95f8526817db5bbd16ec2 | |
parent | b1f1a5d40c363d57ef0579087bd8bbd4c7a4b0cb (diff) |
Plumb FrameEventHistory to client
Bug: 141939081
Test: build, boot, libgui_test, SurfaceFlinger_test
Change-Id: I7294c5357bc28cf0336eef583264c5d0544ec7d4
-rw-r--r-- | libs/gui/BLASTBufferQueue.cpp | 88 | ||||
-rw-r--r-- | libs/gui/ITransactionCompletedListener.cpp | 70 | ||||
-rw-r--r-- | libs/gui/SurfaceComposerClient.cpp | 18 | ||||
-rw-r--r-- | libs/gui/include/gui/BLASTBufferQueue.h | 31 | ||||
-rw-r--r-- | libs/gui/include/gui/FrameTimestamps.h | 1 | ||||
-rw-r--r-- | libs/gui/include/gui/ITransactionCompletedListener.h | 28 | ||||
-rw-r--r-- | libs/gui/include/gui/LayerState.h | 1 | ||||
-rw-r--r-- | libs/gui/include/gui/SurfaceComposerClient.h | 18 | ||||
-rw-r--r-- | libs/gui/tests/BLASTBufferQueue_test.cpp | 76 | ||||
-rw-r--r-- | services/surfaceflinger/BufferStateLayer.cpp | 28 | ||||
-rw-r--r-- | services/surfaceflinger/BufferStateLayer.h | 6 | ||||
-rw-r--r-- | services/surfaceflinger/Layer.h | 6 | ||||
-rw-r--r-- | services/surfaceflinger/SurfaceFlinger.cpp | 7 | ||||
-rw-r--r-- | services/surfaceflinger/TransactionCompletedThread.cpp | 6 | ||||
-rw-r--r-- | services/surfaceflinger/TransactionCompletedThread.h | 5 | ||||
-rw-r--r-- | services/surfaceflinger/tests/utils/CallbackUtils.h | 6 |
16 files changed, 371 insertions, 24 deletions
diff --git a/libs/gui/BLASTBufferQueue.cpp b/libs/gui/BLASTBufferQueue.cpp index 4e62da79ea..e2f5d31d00 100644 --- a/libs/gui/BLASTBufferQueue.cpp +++ b/libs/gui/BLASTBufferQueue.cpp @@ -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), @@ -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++; @@ -79,11 +141,21 @@ void BLASTBufferQueue::transactionCallback(nsecs_t /*latchTime*/, const sp<Fence std::unique_lock _lock{mMutex}; ATRACE_CALL(); + 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.size() > 0) { + if (!stats.empty()) { mPendingReleaseItem.releaseFence = stats[0].previousReleaseFence; - mTransformHint = stats[0].transformHint; - mBufferItemConsumer->setTransformHint(mTransformHint); } else { ALOGE("Warning: no SurfaceControlStats returned in BLASTBufferQueue callback"); mPendingReleaseItem.releaseFence = nullptr; @@ -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); diff --git a/libs/gui/ITransactionCompletedListener.cpp b/libs/gui/ITransactionCompletedListener.cpp index e5e25aa50f..69f7894d07 100644 --- a/libs/gui/ITransactionCompletedListener.cpp +++ b/libs/gui/ITransactionCompletedListener.cpp @@ -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) { @@ -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; } @@ -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; } diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 43bccf6c04..7017b7c8f3 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -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] @@ -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); diff --git a/libs/gui/include/gui/BLASTBufferQueue.h b/libs/gui/include/gui/BLASTBufferQueue.h index be429feade..d72eb5a632 100644 --- a/libs/gui/include/gui/BLASTBufferQueue.h +++ b/libs/gui/include/gui/BLASTBufferQueue.h @@ -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 { @@ -89,7 +118,7 @@ private: sp<IGraphicBufferConsumer> mConsumer; sp<IGraphicBufferProducer> mProducer; - sp<BufferItemConsumer> mBufferItemConsumer; + sp<BLASTBufferItemConsumer> mBufferItemConsumer; SurfaceComposerClient::Transaction* mNextTransaction GUARDED_BY(mMutex); }; diff --git a/libs/gui/include/gui/FrameTimestamps.h b/libs/gui/include/gui/FrameTimestamps.h index 816dd2b176..4af86594fc 100644 --- a/libs/gui/include/gui/FrameTimestamps.h +++ b/libs/gui/include/gui/FrameTimestamps.h @@ -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 { diff --git a/libs/gui/include/gui/ITransactionCompletedListener.h b/libs/gui/include/gui/ITransactionCompletedListener.h index 9c15225ac8..c58634b8a2 100644 --- a/libs/gui/include/gui/ITransactionCompletedListener.h +++ b/libs/gui/include/gui/ITransactionCompletedListener.h @@ -21,6 +21,7 @@ #include <binder/Parcelable.h> #include <binder/SafeInterface.h> +#include <gui/FrameTimestamps.h> #include <ui/Fence.h> #include <utils/Timers.h> @@ -35,6 +36,27 @@ class ListenerCallbacks; using CallbackId = int64_t; +class FrameEventHistoryStats : public Parcelable { +public: + status_t writeToParcel(Parcel* output) const override; + status_t readFromParcel(const Parcel* input) override; + + FrameEventHistoryStats() = default; + FrameEventHistoryStats(uint64_t fn, const sp<Fence>& gpuCompFence, CompositorTiming compTiming, + nsecs_t refreshTime, nsecs_t dequeueReadyTime) + : frameNumber(fn), + gpuCompositionDoneFence(gpuCompFence), + compositorTiming(compTiming), + refreshStartTime(refreshTime), + dequeueReadyTime(dequeueReadyTime) {} + + uint64_t frameNumber; + sp<Fence> gpuCompositionDoneFence; + CompositorTiming compositorTiming; + nsecs_t refreshStartTime; + nsecs_t dequeueReadyTime; +}; + class SurfaceStats : public Parcelable { public: status_t writeToParcel(Parcel* output) const override; @@ -42,16 +64,18 @@ public: SurfaceStats() = default; SurfaceStats(const sp<IBinder>& sc, nsecs_t time, const sp<Fence>& prevReleaseFence, - uint32_t hint) + uint32_t hint, FrameEventHistoryStats frameEventStats) : surfaceControl(sc), acquireTime(time), previousReleaseFence(prevReleaseFence), - transformHint(hint) {} + transformHint(hint), + eventStats(frameEventStats) {} sp<IBinder> surfaceControl; nsecs_t acquireTime = -1; sp<Fence> previousReleaseFence; uint32_t transformHint = 0; + FrameEventHistoryStats eventStats; }; class TransactionStats : public Parcelable { diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h index c256a09c40..2d53b48475 100644 --- a/libs/gui/include/gui/LayerState.h +++ b/libs/gui/include/gui/LayerState.h @@ -102,6 +102,7 @@ struct layer_state_t { eFrameRateSelectionPriority = 0x20'00000000, eFrameRateChanged = 0x40'00000000, eBackgroundBlurRadiusChanged = 0x80'00000000, + eProducerDisconnect = 0x100'00000000, }; layer_state_t() diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index 6eec2b7a91..d0bb6a39ec 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -52,17 +52,24 @@ class IRegionSamplingListener; class Region; struct SurfaceControlStats { - SurfaceControlStats(const sp<SurfaceControl>& sc, nsecs_t time, - const sp<Fence>& prevReleaseFence, uint32_t hint) + SurfaceControlStats(const sp<SurfaceControl>& sc, nsecs_t latchTime, nsecs_t acquireTime, + const sp<Fence>& presentFence, const sp<Fence>& prevReleaseFence, + uint32_t hint, FrameEventHistoryStats eventStats) : surfaceControl(sc), - acquireTime(time), + latchTime(latchTime), + acquireTime(acquireTime), + presentFence(presentFence), previousReleaseFence(prevReleaseFence), - transformHint(hint) {} + transformHint(hint), + frameEventStats(eventStats) {} sp<SurfaceControl> surfaceControl; + nsecs_t latchTime = -1; nsecs_t acquireTime = -1; + sp<Fence> presentFence; sp<Fence> previousReleaseFence; uint32_t transformHint = 0; + FrameEventHistoryStats frameEventStats; }; using TransactionCompletedCallbackTakesContext = @@ -484,6 +491,9 @@ public: Transaction& addTransactionCompletedCallback( TransactionCompletedCallbackTakesContext callback, void* callbackContext); + // ONLY FOR BLAST ADAPTER + Transaction& notifyProducerDisconnect(const sp<SurfaceControl>& sc); + // Detaches all child surfaces (and their children recursively) // from their SurfaceControl. // The child SurfaceControls will not throw exceptions or return errors, diff --git a/libs/gui/tests/BLASTBufferQueue_test.cpp b/libs/gui/tests/BLASTBufferQueue_test.cpp index a273914caf..b40eb14093 100644 --- a/libs/gui/tests/BLASTBufferQueue_test.cpp +++ b/libs/gui/tests/BLASTBufferQueue_test.cpp @@ -21,6 +21,7 @@ #include <android/hardware/graphics/common/1.2/types.h> #include <gui/BufferQueueCore.h> #include <gui/BufferQueueProducer.h> +#include <gui/FrameTimestamps.h> #include <gui/IGraphicBufferProducer.h> #include <gui/IProducerListener.h> #include <gui/SurfaceComposerClient.h> @@ -647,4 +648,79 @@ TEST_F(BLASTBufferQueueTransformTest, setTransform_ROT_180) { TEST_F(BLASTBufferQueueTransformTest, setTransform_ROT_270) { test(ui::Transform::ROT_270); } + +class BLASTFrameEventHistoryTest : public BLASTBufferQueueTest { +public: + void setUpAndQueueBuffer(const sp<IGraphicBufferProducer>& igbProducer, + nsecs_t* requestedPresentTime, nsecs_t* postedTime, + IGraphicBufferProducer::QueueBufferOutput* qbOutput, + bool getFrameTimestamps) { + int slot; + sp<Fence> fence; + sp<GraphicBuffer> buf; + auto ret = igbProducer->dequeueBuffer(&slot, &fence, mDisplayWidth, mDisplayHeight, + PIXEL_FORMAT_RGBA_8888, GRALLOC_USAGE_SW_WRITE_OFTEN, + nullptr, nullptr); + ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, ret); + ASSERT_EQ(OK, igbProducer->requestBuffer(slot, &buf)); + + nsecs_t requestedTime = systemTime(); + if (requestedPresentTime) *requestedPresentTime = requestedTime; + IGraphicBufferProducer::QueueBufferInput input(requestedTime, false, HAL_DATASPACE_UNKNOWN, + Rect(mDisplayWidth, mDisplayHeight), + NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, + Fence::NO_FENCE, /*sticky*/ 0, + getFrameTimestamps); + if (postedTime) *postedTime = systemTime(); + igbProducer->queueBuffer(slot, input, qbOutput); + } +}; + +TEST_F(BLASTFrameEventHistoryTest, FrameEventHistory_Basic) { + BLASTBufferQueueHelper adapter(mSurfaceControl, mDisplayWidth, mDisplayHeight); + sp<IGraphicBufferProducer> igbProducer; + ProducerFrameEventHistory history; + setUpProducer(adapter, igbProducer); + + IGraphicBufferProducer::QueueBufferOutput qbOutput; + nsecs_t requestedPresentTimeA = 0; + nsecs_t postedTimeA = 0; + setUpAndQueueBuffer(igbProducer, &requestedPresentTimeA, &postedTimeA, &qbOutput, true); + history.applyDelta(qbOutput.frameTimestamps); + + FrameEvents* events = nullptr; + events = history.getFrame(1); + ASSERT_NE(nullptr, events); + ASSERT_EQ(1, events->frameNumber); + ASSERT_EQ(requestedPresentTimeA, events->requestedPresentTime); + ASSERT_GE(events->postedTime, postedTimeA); + + adapter.waitForCallbacks(); + + // queue another buffer so we query for frame event deltas + nsecs_t requestedPresentTimeB = 0; + nsecs_t postedTimeB = 0; + setUpAndQueueBuffer(igbProducer, &requestedPresentTimeB, &postedTimeB, &qbOutput, true); + history.applyDelta(qbOutput.frameTimestamps); + events = history.getFrame(1); + ASSERT_NE(nullptr, events); + + // frame number, requestedPresentTime, and postTime should not have changed + ASSERT_EQ(1, events->frameNumber); + ASSERT_EQ(requestedPresentTimeA, events->requestedPresentTime); + ASSERT_GE(events->postedTime, postedTimeA); + + ASSERT_GE(events->latchTime, postedTimeA); + ASSERT_GE(events->dequeueReadyTime, events->latchTime); + ASSERT_NE(nullptr, events->gpuCompositionDoneFence); + ASSERT_NE(nullptr, events->displayPresentFence); + ASSERT_NE(nullptr, events->releaseFence); + + // we should also have gotten the initial values for the next frame + events = history.getFrame(2); + ASSERT_NE(nullptr, events); + ASSERT_EQ(2, events->frameNumber); + ASSERT_EQ(requestedPresentTimeB, events->requestedPresentTime); + ASSERT_GE(events->postedTime, postedTimeB); +} } // namespace android diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp index 29688dac63..f8769c0614 100644 --- a/services/surfaceflinger/BufferStateLayer.cpp +++ b/services/surfaceflinger/BufferStateLayer.cpp @@ -115,6 +115,7 @@ void BufferStateLayer::setTransformHint(uint32_t orientation) const { void BufferStateLayer::releasePendingBuffer(nsecs_t dequeueReadyTime) { for (const auto& handle : mDrawingState.callbackHandles) { handle->transformHint = mTransformHint; + handle->dequeueReadyTime = dequeueReadyTime; } mFlinger->getTransactionCompletedThread().finalizePendingCallbackHandles( @@ -133,6 +134,14 @@ void BufferStateLayer::releasePendingBuffer(nsecs_t dequeueReadyTime) { } } +void BufferStateLayer::finalizeFrameEventHistory(const std::shared_ptr<FenceTime>& glDoneFence, + const CompositorTiming& compositorTiming) { + for (const auto& handle : mDrawingState.callbackHandles) { + handle->gpuCompositionDoneFence = glDoneFence; + handle->compositorTiming = compositorTiming; + } +} + bool BufferStateLayer::shouldPresentNow(nsecs_t /*expectedPresentTime*/) const { if (getSidebandStreamChanged() || getAutoRefresh()) { return true; @@ -244,14 +253,15 @@ bool BufferStateLayer::setFrame(const Rect& frame) { return true; } -bool BufferStateLayer::updateFrameEventHistory(const sp<Fence>& acquireFence, nsecs_t postedTime, - nsecs_t desiredPresentTime) { +bool BufferStateLayer::addFrameEvent(const sp<Fence>& acquireFence, nsecs_t postedTime, + nsecs_t desiredPresentTime) { Mutex::Autolock lock(mFrameEventHistoryMutex); mAcquireTimeline.updateSignalTimes(); std::shared_ptr<FenceTime> acquireFenceTime = std::make_shared<FenceTime>((acquireFence ? acquireFence : Fence::NO_FENCE)); NewFrameEventsEntry newTimestamps = {mCurrentState.frameNumber, postedTime, desiredPresentTime, acquireFenceTime}; + mFrameEventHistory.setProducerWantsEvents(); mFrameEventHistory.addQueue(newTimestamps); return true; } @@ -276,12 +286,12 @@ bool BufferStateLayer::setBuffer(const sp<GraphicBuffer>& buffer, const sp<Fence mFlinger->mFrameTracer->traceNewLayer(layerId, getName().c_str()); mFlinger->mFrameTracer->traceTimestamp(layerId, buffer->getId(), mCurrentState.frameNumber, postTime, FrameTracer::FrameEvent::POST); + desiredPresentTime = desiredPresentTime <= 0 ? 0 : desiredPresentTime; mCurrentState.desiredPresentTime = desiredPresentTime; - mFlinger->mScheduler->recordLayerHistory(this, - desiredPresentTime <= 0 ? 0 : desiredPresentTime); + mFlinger->mScheduler->recordLayerHistory(this, desiredPresentTime); - updateFrameEventHistory(acquireFence, postTime, desiredPresentTime); + addFrameEvent(acquireFence, postTime, desiredPresentTime); return true; } @@ -446,6 +456,13 @@ bool BufferStateLayer::framePresentTimeIsCurrent(nsecs_t expectedPresentTime) co return mCurrentState.desiredPresentTime <= expectedPresentTime; } +bool BufferStateLayer::onPreComposition(nsecs_t refreshStartTime) { + for (const auto& handle : mDrawingState.callbackHandles) { + handle->refreshStartTime = refreshStartTime; + } + return BufferLayer::onPreComposition(refreshStartTime); +} + uint64_t BufferStateLayer::getFrameNumber(nsecs_t /*expectedPresentTime*/) const { return mDrawingState.frameNumber; } @@ -529,6 +546,7 @@ status_t BufferStateLayer::updateTexImage(bool& /*recomputeVisibleRegions*/, nse for (auto& handle : mDrawingState.callbackHandles) { handle->latchTime = latchTime; + handle->frameNumber = mDrawingState.frameNumber; } if (!SyncFeatures::getInstance().useNativeFenceSync()) { diff --git a/services/surfaceflinger/BufferStateLayer.h b/services/surfaceflinger/BufferStateLayer.h index 57ff8bc00d..8e22215b4a 100644 --- a/services/surfaceflinger/BufferStateLayer.h +++ b/services/surfaceflinger/BufferStateLayer.h @@ -45,6 +45,9 @@ public: void setTransformHint(uint32_t orientation) const override; void releasePendingBuffer(nsecs_t dequeueReadyTime) override; + void finalizeFrameEventHistory(const std::shared_ptr<FenceTime>& glDoneFence, + const CompositorTiming& compositorTiming) override; + bool shouldPresentNow(nsecs_t expectedPresentTime) const override; uint32_t doTransactionResize(uint32_t flags, Layer::State* /*stateToCommit*/) override { @@ -78,6 +81,8 @@ public: bool setSidebandStream(const sp<NativeHandle>& sidebandStream) override; bool setTransactionCompletedListeners(const std::vector<sp<CallbackHandle>>& handles) override; void forceSendCallbacks() override; + bool addFrameEvent(const sp<Fence>& acquireFence, nsecs_t postedTime, + nsecs_t requestedPresentTime) override; // Override to ignore legacy layer state properties that are not used by BufferStateLayer bool setSize(uint32_t /*w*/, uint32_t /*h*/) override { return false; } @@ -104,6 +109,7 @@ public: // ----------------------------------------------------------------------- bool fenceHasSignaled() const override; bool framePresentTimeIsCurrent(nsecs_t expectedPresentTime) const override; + bool onPreComposition(nsecs_t refreshStartTime) override; protected: void gatherBufferInfo() override; diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 810e0af47f..de4a08070c 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -372,6 +372,10 @@ public: return false; }; virtual void forceSendCallbacks() {} + virtual bool addFrameEvent(const sp<Fence>& /*acquireFence*/, nsecs_t /*postedTime*/, + nsecs_t /*requestedPresentTime*/) { + return false; + } virtual bool setBackgroundColor(const half3& color, float alpha, ui::Dataspace dataspace); virtual bool setColorSpaceAgnostic(const bool agnostic); bool setShadowRadius(float shadowRadius); @@ -596,6 +600,8 @@ public: // If a buffer was replaced this frame, release the former buffer virtual void releasePendingBuffer(nsecs_t /*dequeueReadyTime*/) { } + virtual void finalizeFrameEventHistory(const std::shared_ptr<FenceTime>& /*glDoneFence*/, + const CompositorTiming& /*compositorTiming*/) {} /* * doTransaction - process the transaction. This is a good place to figure * out which attributes of the surface have changed. diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 33d85cb420..c125b2c75b 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -2037,12 +2037,10 @@ void SurfaceFlinger::postComposition() ATRACE_CALL(); ALOGV("postComposition"); - // Release any buffers which were replaced this frame nsecs_t dequeueReadyTime = systemTime(); for (auto& layer : mLayersWithQueuedFrames) { layer->releasePendingBuffer(dequeueReadyTime); } - // |mStateLock| not needed as we are on the main thread const auto displayDevice = getDefaultDisplayDeviceLocked(); @@ -3349,6 +3347,11 @@ uint32_t SurfaceFlinger::setClientStateLocked( layer->pushPendingState(); } + // Only set by BLAST adapter layers + if (what & layer_state_t::eProducerDisconnect) { + layer->onDisconnect(); + } + if (what & layer_state_t::ePositionChanged) { if (layer->setPosition(s.x, s.y)) { flags |= eTraversalNeeded; diff --git a/services/surfaceflinger/TransactionCompletedThread.cpp b/services/surfaceflinger/TransactionCompletedThread.cpp index daa67ae043..0cdff8f380 100644 --- a/services/surfaceflinger/TransactionCompletedThread.cpp +++ b/services/surfaceflinger/TransactionCompletedThread.cpp @@ -237,9 +237,13 @@ status_t TransactionCompletedThread::addCallbackHandle(const sp<CallbackHandle>& // destroyed the client side is dead and there won't be anyone to send the callback to. sp<IBinder> surfaceControl = handle->surfaceControl.promote(); if (surfaceControl) { + FrameEventHistoryStats eventStats(handle->frameNumber, + handle->gpuCompositionDoneFence->getSnapshot().fence, + handle->compositorTiming, handle->refreshStartTime, + handle->dequeueReadyTime); transactionStats->surfaceStats.emplace_back(surfaceControl, handle->acquireTime, handle->previousReleaseFence, - handle->transformHint); + handle->transformHint, eventStats); } return NO_ERROR; } diff --git a/services/surfaceflinger/TransactionCompletedThread.h b/services/surfaceflinger/TransactionCompletedThread.h index 12ea8fe7d0..f50147a1e9 100644 --- a/services/surfaceflinger/TransactionCompletedThread.h +++ b/services/surfaceflinger/TransactionCompletedThread.h @@ -45,6 +45,11 @@ public: nsecs_t acquireTime = -1; nsecs_t latchTime = -1; uint32_t transformHint = 0; + std::shared_ptr<FenceTime> gpuCompositionDoneFence{FenceTime::NO_FENCE}; + CompositorTiming compositorTiming; + nsecs_t refreshStartTime = 0; + nsecs_t dequeueReadyTime = 0; + uint64_t frameNumber = 0; }; class TransactionCompletedThread { diff --git a/services/surfaceflinger/tests/utils/CallbackUtils.h b/services/surfaceflinger/tests/utils/CallbackUtils.h index 4e2b7c3543..1318debbba 100644 --- a/services/surfaceflinger/tests/utils/CallbackUtils.h +++ b/services/surfaceflinger/tests/utils/CallbackUtils.h @@ -121,8 +121,10 @@ private: void verifySurfaceControlStats(const SurfaceControlStats& surfaceControlStats, nsecs_t latchTime) const { - const auto& [surfaceControl, acquireTime, previousReleaseFence, transformHint] = - surfaceControlStats; + const auto& + [surfaceControl, latch, acquireTime, presentFence, previousReleaseFence, + transformHint, + frameEvents] = surfaceControlStats; ASSERT_EQ(acquireTime > 0, mBufferResult == ExpectedResult::Buffer::ACQUIRED) << "bad acquire time"; |