diff options
author | 2020-11-24 23:51:31 +0100 | |
---|---|---|
committer | 2020-12-10 16:17:14 +0100 | |
commit | 9c03b50a30c163ad4cee13455311812ef563db40 (patch) | |
tree | 380089958aada0c2e68d86a690b717c97547fe1e | |
parent | 5814ab8b847af326de5c46a1b5f2409ff404fc3a (diff) |
Add Shared timeline jank classification listener (1/2)
Adds the ability to register a listener that gets informed about
SF' jank classifications via the TransactionCompleted interface
Bug: 17475548
Test: FrameTimelineTest
Test: Register listener, ensure data flows back
Change-Id: Ie42c508da605c03569eadab6ab18b7315b35d247
18 files changed, 219 insertions, 97 deletions
diff --git a/libs/gui/ITransactionCompletedListener.cpp b/libs/gui/ITransactionCompletedListener.cpp index 69f7894d07..2dacae1cad 100644 --- a/libs/gui/ITransactionCompletedListener.cpp +++ b/libs/gui/ITransactionCompletedListener.cpp @@ -17,6 +17,8 @@ #define LOG_TAG "ITransactionCompletedListener" //#define LOG_NDEBUG 0 +#include <gui/LayerState.h> +#include <gui/ISurfaceComposer.h> #include <gui/ITransactionCompletedListener.h> namespace android { @@ -90,61 +92,63 @@ status_t FrameEventHistoryStats::readFromParcel(const Parcel* input) { return err; } +JankData::JankData() : + frameVsyncId(ISurfaceComposer::INVALID_VSYNC_ID), + jankType(JankType::None) { +} + +status_t JankData::writeToParcel(Parcel* output) const { + SAFE_PARCEL(output->writeInt64, frameVsyncId); + SAFE_PARCEL(output->writeInt32, static_cast<int32_t>(jankType)); + return NO_ERROR; +} + +status_t JankData::readFromParcel(const Parcel* input) { + SAFE_PARCEL(input->readInt64, &frameVsyncId); + int32_t jankTypeInt; + SAFE_PARCEL(input->readInt32, &jankTypeInt); + jankType = static_cast<JankType>(jankTypeInt); + return NO_ERROR; +} + status_t SurfaceStats::writeToParcel(Parcel* output) const { - status_t err = output->writeStrongBinder(surfaceControl); - if (err != NO_ERROR) { - return err; - } - err = output->writeInt64(acquireTime); - if (err != NO_ERROR) { - return err; - } + SAFE_PARCEL(output->writeStrongBinder, surfaceControl); + SAFE_PARCEL(output->writeInt64, acquireTime); if (previousReleaseFence) { - err = output->writeBool(true); - if (err != NO_ERROR) { - return err; - } - err = output->write(*previousReleaseFence); + SAFE_PARCEL(output->writeBool, true); + SAFE_PARCEL(output->write, *previousReleaseFence); } else { - err = output->writeBool(false); + SAFE_PARCEL(output->writeBool, false); } - err = output->writeUint32(transformHint); - if (err != NO_ERROR) { - return err; + SAFE_PARCEL(output->writeUint32, transformHint); + SAFE_PARCEL(output->writeParcelable, eventStats); + SAFE_PARCEL(output->writeInt32, static_cast<int32_t>(jankData.size())); + for (const auto& data : jankData) { + SAFE_PARCEL(output->writeParcelable, data); } - - err = output->writeParcelable(eventStats); - return err; + return NO_ERROR; } status_t SurfaceStats::readFromParcel(const Parcel* input) { - status_t err = input->readStrongBinder(&surfaceControl); - if (err != NO_ERROR) { - return err; - } - err = input->readInt64(&acquireTime); - if (err != NO_ERROR) { - return err; - } + SAFE_PARCEL(input->readStrongBinder, &surfaceControl); + SAFE_PARCEL(input->readInt64, &acquireTime); bool hasFence = false; - err = input->readBool(&hasFence); - if (err != NO_ERROR) { - return err; - } + SAFE_PARCEL(input->readBool, &hasFence); if (hasFence) { previousReleaseFence = new Fence(); - err = input->read(*previousReleaseFence); - if (err != NO_ERROR) { - return err; - } + SAFE_PARCEL(input->read, *previousReleaseFence); } - err = input->readUint32(&transformHint); - if (err != NO_ERROR) { - return err; + SAFE_PARCEL(input->readUint32, &transformHint); + SAFE_PARCEL(input->readParcelable, &eventStats); + + int32_t jankData_size = 0; + SAFE_PARCEL_READ_SIZE(input->readInt32, &jankData_size, input->dataSize()); + for (int i = 0; i < jankData_size; i++) { + JankData data; + SAFE_PARCEL(input->readParcelable, &data); + jankData.push_back(data); } - - err = input->readParcelable(&eventStats); - return err; + return NO_ERROR; } status_t TransactionStats::writeToParcel(Parcel* output) const { diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 47a08ab500..9ed7d1cc19 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -125,6 +125,9 @@ sp<SurfaceComposerClient> SurfaceComposerClient::getDefault() { return DefaultComposerClient::getComposerClient(); } +JankDataListener::~JankDataListener() { +} + // --------------------------------------------------------------------------- // TransactionCompletedListener does not use ANDROID_SINGLETON_STATIC_INSTANCE because it needs @@ -174,6 +177,23 @@ CallbackId TransactionCompletedListener::addCallbackFunction( return callbackId; } +void TransactionCompletedListener::addJankListener(const sp<JankDataListener>& listener, + sp<SurfaceControl> surfaceControl) { + std::lock_guard<std::mutex> lock(mMutex); + mJankListeners.insert({surfaceControl->getHandle(), listener}); +} + +void TransactionCompletedListener::removeJankListener(const sp<JankDataListener>& listener) { + std::lock_guard<std::mutex> lock(mMutex); + for (auto it = mJankListeners.begin(); it != mJankListeners.end();) { + if (it->second == listener) { + it = mJankListeners.erase(it); + } else { + it++; + } + } +} + void TransactionCompletedListener::addSurfaceControlToCallbacks( const sp<SurfaceControl>& surfaceControl, const std::unordered_set<CallbackId>& callbackIds) { @@ -189,6 +209,7 @@ void TransactionCompletedListener::addSurfaceControlToCallbacks( void TransactionCompletedListener::onTransactionCompleted(ListenerStats listenerStats) { std::unordered_map<CallbackId, CallbackTranslation> callbacksMap; + std::multimap<sp<IBinder>, sp<JankDataListener>> jankListenersMap; { std::lock_guard<std::mutex> lock(mMutex); @@ -204,6 +225,7 @@ void TransactionCompletedListener::onTransactionCompleted(ListenerStats listener * sp<SurfaceControl> that could possibly exist for the callbacks. */ callbacksMap = mCallbacks; + jankListenersMap = mJankListeners; for (const auto& transactionStats : listenerStats.transactionStats) { for (auto& callbackId : transactionStats.callbackIds) { mCallbacks.erase(callbackId); @@ -236,6 +258,13 @@ void TransactionCompletedListener::onTransactionCompleted(ListenerStats listener callbackFunction(transactionStats.latchTime, transactionStats.presentFence, surfaceControlStats); } + for (const auto& surfaceStats : transactionStats.surfaceStats) { + if (surfaceStats.jankData.empty()) continue; + for (auto it = jankListenersMap.find(surfaceStats.surfaceControl); + it != jankListenersMap.end(); it++) { + it->second->onJankDataAvailable(surfaceStats.jankData); + } + } } } diff --git a/libs/gui/include/gui/ITransactionCompletedListener.h b/libs/gui/include/gui/ITransactionCompletedListener.h index c58634b8a2..26b3840b5e 100644 --- a/libs/gui/include/gui/ITransactionCompletedListener.h +++ b/libs/gui/include/gui/ITransactionCompletedListener.h @@ -16,6 +16,8 @@ #pragma once +#include "JankInfo.h" + #include <binder/IInterface.h> #include <binder/Parcel.h> #include <binder/Parcelable.h> @@ -57,6 +59,27 @@ public: nsecs_t dequeueReadyTime; }; +/** + * Jank information representing SurfaceFlinger's jank classification about frames for a specific + * surface. + */ +class JankData : public Parcelable { +public: + status_t writeToParcel(Parcel* output) const override; + status_t readFromParcel(const Parcel* input) override; + + JankData(); + JankData(int64_t frameVsyncId, JankType jankType) + : frameVsyncId(frameVsyncId), + jankType(jankType) {} + + // Identifier for the frame submitted with Transaction.setFrameTimelineVsyncId + int64_t frameVsyncId; + + // The type of jank occurred + JankType jankType; +}; + class SurfaceStats : public Parcelable { public: status_t writeToParcel(Parcel* output) const override; @@ -64,18 +87,21 @@ public: SurfaceStats() = default; SurfaceStats(const sp<IBinder>& sc, nsecs_t time, const sp<Fence>& prevReleaseFence, - uint32_t hint, FrameEventHistoryStats frameEventStats) + uint32_t hint, FrameEventHistoryStats frameEventStats, + std::vector<JankData> jankData) : surfaceControl(sc), acquireTime(time), previousReleaseFence(prevReleaseFence), transformHint(hint), - eventStats(frameEventStats) {} + eventStats(frameEventStats), + jankData(std::move(jankData)) {} sp<IBinder> surfaceControl; nsecs_t acquireTime = -1; sp<Fence> previousReleaseFence; uint32_t transformHint = 0; FrameEventHistoryStats eventStats; + std::vector<JankData> jankData; }; class TransactionStats : public Parcelable { diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index 2eb97f27a1..f1845ee5ef 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -619,6 +619,12 @@ public: // --------------------------------------------------------------------------- +class JankDataListener : public VirtualLightRefBase { +public: + virtual ~JankDataListener() = 0; + virtual void onJankDataAvailable(const std::vector<JankData>& jankData) = 0; +}; + class TransactionCompletedListener : public BnTransactionCompletedListener { TransactionCompletedListener(); @@ -637,6 +643,7 @@ class TransactionCompletedListener : public BnTransactionCompletedListener { }; std::unordered_map<CallbackId, CallbackTranslation> mCallbacks GUARDED_BY(mMutex); + std::multimap<sp<IBinder>, sp<JankDataListener>> mJankListeners GUARDED_BY(mMutex); public: static sp<TransactionCompletedListener> getInstance(); @@ -652,6 +659,18 @@ public: void addSurfaceControlToCallbacks(const sp<SurfaceControl>& surfaceControl, const std::unordered_set<CallbackId>& callbackIds); + /* + * Adds a jank listener to be informed about SurfaceFlinger's jank classification for a specific + * surface. Jank classifications arrive as part of the transaction callbacks about previous + * frames submitted to this Surface. + */ + void addJankListener(const sp<JankDataListener>& listener, sp<SurfaceControl> surfaceControl); + + /** + * Removes a jank listener previously added to addJankCallback. + */ + void removeJankListener(const sp<JankDataListener>& listener); + // Overrides BnTransactionCompletedListener's onTransactionCompleted void onTransactionCompleted(ListenerStats stats) override; }; diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp index dc99986900..325ecfe8ae 100644 --- a/services/surfaceflinger/BufferQueueLayer.cpp +++ b/services/surfaceflinger/BufferQueueLayer.cpp @@ -440,7 +440,7 @@ void BufferQueueLayer::onFrameAvailable(const BufferItem& item) { mName, mFrameTimelineVsyncId); surfaceFrame->setActualQueueTime(systemTime()); - mQueueItems.push_back({item, std::move(surfaceFrame)}); + mQueueItems.push_back({item, surfaceFrame}); mQueuedFrames++; // Wake up any pending callbacks diff --git a/services/surfaceflinger/BufferQueueLayer.h b/services/surfaceflinger/BufferQueueLayer.h index b45900ef4c..5a6b9bcf6c 100644 --- a/services/surfaceflinger/BufferQueueLayer.h +++ b/services/surfaceflinger/BufferQueueLayer.h @@ -129,10 +129,10 @@ private: Condition mQueueItemCondition; struct BufferData { - BufferData(BufferItem item, std::unique_ptr<frametimeline::SurfaceFrame> surfaceFrame) - : item(item), surfaceFrame(std::move(surfaceFrame)) {} + BufferData(BufferItem item, std::shared_ptr<frametimeline::SurfaceFrame> surfaceFrame) + : item(item), surfaceFrame(surfaceFrame) {} BufferItem item; - std::unique_ptr<frametimeline::SurfaceFrame> surfaceFrame; + std::shared_ptr<frametimeline::SurfaceFrame> surfaceFrame; }; std::vector<BufferData> mQueueItems; std::atomic<uint64_t> mLastFrameNumberReceived{0}; diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp index 963e54105d..4efff75351 100644 --- a/services/surfaceflinger/BufferStateLayer.cpp +++ b/services/surfaceflinger/BufferStateLayer.cpp @@ -100,14 +100,30 @@ void BufferStateLayer::onLayerDisplayed(const sp<Fence>& releaseFence) { } } +void BufferStateLayer::onSurfaceFrameCreated( + const std::shared_ptr<frametimeline::SurfaceFrame>& surfaceFrame) { + mPendingJankClassifications.emplace_back(surfaceFrame); +} + void BufferStateLayer::releasePendingBuffer(nsecs_t dequeueReadyTime) { for (const auto& handle : mDrawingState.callbackHandles) { handle->transformHint = mTransformHint; handle->dequeueReadyTime = dequeueReadyTime; } + std::vector<JankData> jankData; + jankData.reserve(mPendingJankClassifications.size()); + while (!mPendingJankClassifications.empty() + && mPendingJankClassifications.front()->getJankType()) { + std::shared_ptr<frametimeline::SurfaceFrame> surfaceFrame = + mPendingJankClassifications.front(); + mPendingJankClassifications.pop_front(); + jankData.emplace_back( + JankData(surfaceFrame->getToken(), surfaceFrame->getJankType().value())); + } + mFlinger->getTransactionCompletedThread().finalizePendingCallbackHandles( - mDrawingState.callbackHandles); + mDrawingState.callbackHandles, jankData); mDrawingState.callbackHandles = {}; @@ -382,7 +398,7 @@ bool BufferStateLayer::setTransactionCompletedListeners( void BufferStateLayer::forceSendCallbacks() { mFlinger->getTransactionCompletedThread().finalizePendingCallbackHandles( - mCurrentState.callbackHandles); + mCurrentState.callbackHandles, std::vector<JankData>()); } bool BufferStateLayer::setTransparentRegionHint(const Region& transparent) { diff --git a/services/surfaceflinger/BufferStateLayer.h b/services/surfaceflinger/BufferStateLayer.h index 42be62a763..0f0b48a9d7 100644 --- a/services/surfaceflinger/BufferStateLayer.h +++ b/services/surfaceflinger/BufferStateLayer.h @@ -115,6 +115,7 @@ public: protected: void gatherBufferInfo() override; uint64_t getHeadFrameNumber(nsecs_t expectedPresentTime) const; + void onSurfaceFrameCreated(const std::shared_ptr<frametimeline::SurfaceFrame>& surfaceFrame); private: friend class SlotGenerationTest; @@ -158,6 +159,8 @@ private: bool mReleasePreviousBuffer = false; nsecs_t mCallbackHandleAcquireTime = -1; + std::deque<std::shared_ptr<android::frametimeline::SurfaceFrame>> mPendingJankClassifications; + // TODO(marissaw): support sticky transform for LEGACY camera mode class HwcSlotGenerator : public ClientCache::ErasedRecipient { diff --git a/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp b/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp index b45c213a6c..b09f07a2bb 100644 --- a/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp +++ b/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp @@ -265,8 +265,11 @@ void SurfaceFrame::setJankInfo(JankType jankType, int32_t jankMetadata) { mJankMetadata = jankMetadata; } -JankType SurfaceFrame::getJankType() const { +std::optional<JankType> SurfaceFrame::getJankType() const { std::lock_guard<std::mutex> lock(mMutex); + if (mActuals.presentTime == 0) { + return std::nullopt; + } return mJankType; } @@ -386,37 +389,36 @@ FrameTimeline::DisplayFrame::DisplayFrame() this->surfaceFrames.reserve(kNumSurfaceFramesInitial); } -std::unique_ptr<android::frametimeline::SurfaceFrame> FrameTimeline::createSurfaceFrameForToken( +std::shared_ptr<android::frametimeline::SurfaceFrame> FrameTimeline::createSurfaceFrameForToken( pid_t ownerPid, uid_t ownerUid, std::string layerName, std::string debugName, std::optional<int64_t> token) { ATRACE_CALL(); if (!token) { - return std::make_unique<impl::SurfaceFrame>(ISurfaceComposer::INVALID_VSYNC_ID, ownerPid, + return std::make_shared<impl::SurfaceFrame>(ISurfaceComposer::INVALID_VSYNC_ID,ownerPid, ownerUid, std::move(layerName), std::move(debugName), PredictionState::None, TimelineItem()); } std::optional<TimelineItem> predictions = mTokenManager.getPredictionsForToken(*token); if (predictions) { - return std::make_unique<impl::SurfaceFrame>(*token, ownerPid, ownerUid, + return std::make_shared<impl::SurfaceFrame>(*token, ownerPid, ownerUid, std::move(layerName), std::move(debugName), PredictionState::Valid, std::move(*predictions)); } - return std::make_unique<impl::SurfaceFrame>(*token, ownerPid, ownerUid, std::move(layerName), + return std::make_shared<impl::SurfaceFrame>(*token, ownerPid, ownerUid, std::move(layerName), std::move(debugName), PredictionState::Expired, TimelineItem()); } void FrameTimeline::addSurfaceFrame( - std::unique_ptr<android::frametimeline::SurfaceFrame> surfaceFrame, + std::shared_ptr<android::frametimeline::SurfaceFrame> surfaceFrame, SurfaceFrame::PresentState state) { ATRACE_CALL(); surfaceFrame->setPresentState(state); - std::unique_ptr<impl::SurfaceFrame> implSurfaceFrame( - static_cast<impl::SurfaceFrame*>(surfaceFrame.release())); std::lock_guard<std::mutex> lock(mMutex); - mCurrentDisplayFrame->surfaceFrames.push_back(std::move(implSurfaceFrame)); + mCurrentDisplayFrame->surfaceFrames.push_back( + std::static_pointer_cast<impl::SurfaceFrame>(surfaceFrame)); } void FrameTimeline::setSfWakeUp(int64_t token, nsecs_t wakeUpTime) { diff --git a/services/surfaceflinger/FrameTimeline/FrameTimeline.h b/services/surfaceflinger/FrameTimeline/FrameTimeline.h index fe83ebf1ea..084935b877 100644 --- a/services/surfaceflinger/FrameTimeline/FrameTimeline.h +++ b/services/surfaceflinger/FrameTimeline/FrameTimeline.h @@ -120,6 +120,12 @@ public: virtual void setActualStartTime(nsecs_t actualStartTime) = 0; virtual void setActualQueueTime(nsecs_t actualQueueTime) = 0; virtual void setAcquireFenceTime(nsecs_t acquireFenceTime) = 0; + + // Retrieves jank classification, if it's already been classified. + virtual std::optional<JankType> getJankType() const = 0; + + // Token identifying the frame. + virtual int64_t getToken() const = 0; }; /* @@ -138,13 +144,13 @@ public: // Create a new surface frame, set the predictions based on a token and return it to the caller. // Sets the PredictionState of SurfaceFrame. // Debug name is the human-readable debugging string for dumpsys. - virtual std::unique_ptr<SurfaceFrame> createSurfaceFrameForToken( + virtual std::shared_ptr<SurfaceFrame> createSurfaceFrameForToken( pid_t ownerPid, uid_t ownerUid, std::string layerName, std::string debugName, std::optional<int64_t> token) = 0; // Adds a new SurfaceFrame to the current DisplayFrame. Frames from multiple layers can be // composited into one display frame. - virtual void addSurfaceFrame(std::unique_ptr<SurfaceFrame> surfaceFrame, + virtual void addSurfaceFrame(std::shared_ptr<SurfaceFrame> surfaceFrame, SurfaceFrame::PresentState state) = 0; // The first function called by SF for the current DisplayFrame. Fetches SF predictions based on @@ -209,8 +215,8 @@ public: PresentState getPresentState() const override; PredictionState getPredictionState() const override { return mPredictionState; }; pid_t getOwnerPid() const override { return mOwnerPid; }; - JankType getJankType() const; - int64_t getToken() const { return mToken; }; + std::optional<JankType> getJankType() const override; + int64_t getToken() const override { return mToken; }; nsecs_t getBaseTime() const; uid_t getOwnerUid() const { return mOwnerUid; }; const std::string& getName() const { return mLayerName; }; @@ -258,10 +264,10 @@ public: ~FrameTimeline() = default; frametimeline::TokenManager* getTokenManager() override { return &mTokenManager; } - std::unique_ptr<frametimeline::SurfaceFrame> createSurfaceFrameForToken( + std::shared_ptr<frametimeline::SurfaceFrame> createSurfaceFrameForToken( pid_t ownerPid, uid_t ownerUid, std::string layerName, std::string debugName, std::optional<int64_t> token) override; - void addSurfaceFrame(std::unique_ptr<frametimeline::SurfaceFrame> surfaceFrame, + void addSurfaceFrame(std::shared_ptr<frametimeline::SurfaceFrame> surfaceFrame, SurfaceFrame::PresentState state) override; void setSfWakeUp(int64_t token, nsecs_t wakeupTime) override; void setSfPresent(nsecs_t sfPresentTime, @@ -299,7 +305,7 @@ private: TimelineItem surfaceFlingerActuals; // Collection of predictions and actual values sent over by Layers - std::vector<std::unique_ptr<SurfaceFrame>> surfaceFrames; + std::vector<std::shared_ptr<SurfaceFrame>> surfaceFrames; PredictionState predictionState = PredictionState::None; JankType jankType = JankType::None; // Enum for the type of jank diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index ab0d3df1f4..cfaa59de0b 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -901,17 +901,17 @@ bool Layer::applyPendingStates(State* stateToCommit) { ? std::nullopt : std::make_optional(stateToCommit->frameTimelineVsyncId); - auto surfaceFrame = + mSurfaceFrame = mFlinger->mFrameTimeline->createSurfaceFrameForToken(getOwnerPid(), getOwnerUid(), mName, mTransactionName, vsyncId); - surfaceFrame->setActualQueueTime(stateToCommit->postTime); + mSurfaceFrame->setActualQueueTime(stateToCommit->postTime); // For transactions we set the acquire fence time to the post time as we // don't have a buffer. For BufferStateLayer it is overridden in // BufferStateLayer::applyPendingStates - surfaceFrame->setAcquireFenceTime(stateToCommit->postTime); + mSurfaceFrame->setAcquireFenceTime(stateToCommit->postTime); - mSurfaceFrame = std::move(surfaceFrame); + onSurfaceFrameCreated(mSurfaceFrame); } mCurrentState.modified = false; @@ -1057,7 +1057,7 @@ uint32_t Layer::doTransaction(uint32_t flags) { void Layer::commitTransaction(const State& stateToCommit) { mDrawingState = stateToCommit; - mFlinger->mFrameTimeline->addSurfaceFrame(std::move(mSurfaceFrame), PresentState::Presented); + mFlinger->mFrameTimeline->addSurfaceFrame(mSurfaceFrame, PresentState::Presented); } uint32_t Layer::getTransactionFlags(uint32_t flags) { diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 75d68a16f2..b30793a360 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -942,6 +942,7 @@ protected: virtual void commitTransaction(const State& stateToCommit); virtual bool applyPendingStates(State* stateToCommit); virtual uint32_t doTransactionResize(uint32_t flags, Layer::State* stateToCommit); + virtual void onSurfaceFrameCreated(const std::shared_ptr<frametimeline::SurfaceFrame>&) {} // Returns mCurrentScaling mode (originating from the // Client) or mOverrideScalingMode mode (originating from @@ -1066,7 +1067,7 @@ protected: const InputWindowInfo::Type mWindowType; // Can only be accessed with the SF state lock held. - std::unique_ptr<frametimeline::SurfaceFrame> mSurfaceFrame; + std::shared_ptr<frametimeline::SurfaceFrame> mSurfaceFrame; // The owner of the layer. If created from a non system process, it will be the calling uid. // If created from a system process, the value can be passed in. diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 773b3ab54d..cb56ecc7fe 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -1986,12 +1986,14 @@ void SurfaceFlinger::onMessageRefresh() { mScheduler->onDisplayRefreshed(presentTime); - postFrame(); - postComposition(); - + // Set presentation information before calling postComposition, such that jank information from + // this' frame classification is already available when sending jank info to clients. mFrameTimeline->setSfPresent(systemTime(), std::make_shared<FenceTime>(mPreviousPresentFences[0])); + postFrame(); + postComposition(); + const bool prevFrameHadClientComposition = mHadClientComposition; mHadClientComposition = std::any_of(displays.cbegin(), displays.cend(), [](const auto& pair) { diff --git a/services/surfaceflinger/TransactionCompletedThread.cpp b/services/surfaceflinger/TransactionCompletedThread.cpp index ca244934e4..1797af4cf6 100644 --- a/services/surfaceflinger/TransactionCompletedThread.cpp +++ b/services/surfaceflinger/TransactionCompletedThread.cpp @@ -153,7 +153,7 @@ status_t TransactionCompletedThread::registerPendingCallbackHandle( } status_t TransactionCompletedThread::finalizePendingCallbackHandles( - const std::deque<sp<CallbackHandle>>& handles) { + const std::deque<sp<CallbackHandle>>& handles, const std::vector<JankData>& jankData) { if (handles.empty()) { return NO_ERROR; } @@ -186,7 +186,7 @@ status_t TransactionCompletedThread::finalizePendingCallbackHandles( ALOGW("cannot find listener in mPendingTransactions"); } - status_t err = addCallbackHandle(handle); + status_t err = addCallbackHandle(handle, jankData); if (err != NO_ERROR) { ALOGE("could not add callback handle"); return err; @@ -204,7 +204,7 @@ status_t TransactionCompletedThread::registerUnpresentedCallbackHandle( return BAD_VALUE; } - return addCallbackHandle(handle); + return addCallbackHandle(handle, std::vector<JankData>()); } status_t TransactionCompletedThread::findTransactionStats( @@ -225,7 +225,8 @@ status_t TransactionCompletedThread::findTransactionStats( return BAD_VALUE; } -status_t TransactionCompletedThread::addCallbackHandle(const sp<CallbackHandle>& handle) { +status_t TransactionCompletedThread::addCallbackHandle(const sp<CallbackHandle>& handle, + const std::vector<JankData>& jankData) { // If we can't find the transaction stats something has gone wrong. The client should call // startRegistration before trying to add a callback handle. TransactionStats* transactionStats; @@ -246,7 +247,7 @@ status_t TransactionCompletedThread::addCallbackHandle(const sp<CallbackHandle>& handle->dequeueReadyTime); transactionStats->surfaceStats.emplace_back(surfaceControl, handle->acquireTime, handle->previousReleaseFence, - handle->transformHint, eventStats); + handle->transformHint, eventStats, jankData); } return NO_ERROR; } diff --git a/services/surfaceflinger/TransactionCompletedThread.h b/services/surfaceflinger/TransactionCompletedThread.h index f50147a1e9..c4ba7e49ce 100644 --- a/services/surfaceflinger/TransactionCompletedThread.h +++ b/services/surfaceflinger/TransactionCompletedThread.h @@ -73,7 +73,8 @@ public: // presented. status_t registerPendingCallbackHandle(const sp<CallbackHandle>& handle); // Notifies the TransactionCompletedThread that a pending CallbackHandle has been presented. - status_t finalizePendingCallbackHandles(const std::deque<sp<CallbackHandle>>& handles); + status_t finalizePendingCallbackHandles(const std::deque<sp<CallbackHandle>>& handles, + const std::vector<JankData>& jankData); // Adds the Transaction CallbackHandle from a layer that does not need to be relatched and // presented this frame. @@ -93,7 +94,8 @@ private: const std::vector<CallbackId>& callbackIds, TransactionStats** outTransactionStats) REQUIRES(mMutex); - status_t addCallbackHandle(const sp<CallbackHandle>& handle) REQUIRES(mMutex); + status_t addCallbackHandle(const sp<CallbackHandle>& handle, + const std::vector<JankData>& jankData) REQUIRES(mMutex); class ThreadDeathRecipient : public IBinder::DeathRecipient { public: diff --git a/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp b/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp index 31a51268e6..538b10d274 100644 --- a/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp +++ b/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp @@ -69,6 +69,7 @@ using ::testing::SetArgPointee; using Transaction = SurfaceComposerClient::Transaction; using Attribute = V2_4::IComposerClient::Attribute; +using Display = V2_1::Display; /////////////////////////////////////////////// diff --git a/services/surfaceflinger/tests/unittests/FrameTimelineTest.cpp b/services/surfaceflinger/tests/unittests/FrameTimelineTest.cpp index 411e7809da..43b5afe9e2 100644 --- a/services/surfaceflinger/tests/unittests/FrameTimelineTest.cpp +++ b/services/surfaceflinger/tests/unittests/FrameTimelineTest.cpp @@ -205,7 +205,7 @@ TEST_F(FrameTimelineTest, presentFenceSignaled_droppedFramesNotUpdated) { // Set up the display frame mFrameTimeline->setSfWakeUp(token1, 20); - mFrameTimeline->addSurfaceFrame(std::move(surfaceFrame1), SurfaceFrame::PresentState::Dropped); + mFrameTimeline->addSurfaceFrame(surfaceFrame1, SurfaceFrame::PresentState::Dropped); mFrameTimeline->setSfPresent(25, presentFence1); presentFence1->signalForTest(30); @@ -229,11 +229,11 @@ TEST_F(FrameTimelineTest, presentFenceSignaled_presentedFramesUpdated) { sLayerNameOne, surfaceFrameToken1); auto surfaceFrame2 = mFrameTimeline->createSurfaceFrameForToken(sPidOne, sUidOne, sLayerNameTwo, - sLayerNameTwo, surfaceFrameToken1); + sLayerNameTwo, surfaceFrameToken2); mFrameTimeline->setSfWakeUp(sfToken1, 22); - mFrameTimeline->addSurfaceFrame(std::move(surfaceFrame1), + mFrameTimeline->addSurfaceFrame(surfaceFrame1, SurfaceFrame::PresentState::Presented); - mFrameTimeline->addSurfaceFrame(std::move(surfaceFrame2), + mFrameTimeline->addSurfaceFrame(surfaceFrame2, SurfaceFrame::PresentState::Presented); mFrameTimeline->setSfPresent(26, presentFence1); auto displayFrame = getDisplayFrame(0); @@ -246,13 +246,16 @@ TEST_F(FrameTimelineTest, presentFenceSignaled_presentedFramesUpdated) { EXPECT_EQ(presentedSurfaceFrame1.getActuals().presentTime, 0); EXPECT_EQ(presentedSurfaceFrame2.getActuals().presentTime, 0); + EXPECT_EQ(surfaceFrame1->getToken(), surfaceFrameToken1); + EXPECT_EQ(surfaceFrame2->getToken(), surfaceFrameToken2); + // Trigger a flush by finalizing the next DisplayFrame auto presentFence2 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE); auto surfaceFrame3 = mFrameTimeline->createSurfaceFrameForToken(sPidOne, sUidOne, sLayerNameOne, sLayerNameOne, surfaceFrameToken2); mFrameTimeline->setSfWakeUp(sfToken2, 52); - mFrameTimeline->addSurfaceFrame(std::move(surfaceFrame3), SurfaceFrame::PresentState::Dropped); + mFrameTimeline->addSurfaceFrame(surfaceFrame3, SurfaceFrame::PresentState::Dropped); mFrameTimeline->setSfPresent(56, presentFence2); displayFrame = getDisplayFrame(0); @@ -260,6 +263,8 @@ TEST_F(FrameTimelineTest, presentFenceSignaled_presentedFramesUpdated) { EXPECT_EQ(displayFrame->surfaceFlingerActuals.presentTime, 42); EXPECT_EQ(presentedSurfaceFrame1.getActuals().presentTime, 42); EXPECT_EQ(presentedSurfaceFrame2.getActuals().presentTime, 42); + EXPECT_NE(surfaceFrame1->getJankType(), std::nullopt); + EXPECT_NE(surfaceFrame2->getJankType(), std::nullopt); } TEST_F(FrameTimelineTest, displayFramesSlidingWindowMovesAfterLimit) { @@ -275,7 +280,7 @@ TEST_F(FrameTimelineTest, displayFramesSlidingWindowMovesAfterLimit) { mFrameTimeline->createSurfaceFrameForToken(sPidOne, sUidOne, sLayerNameOne, sLayerNameOne, surfaceFrameToken); mFrameTimeline->setSfWakeUp(sfToken, 22 + frameTimeFactor); - mFrameTimeline->addSurfaceFrame(std::move(surfaceFrame), + mFrameTimeline->addSurfaceFrame(surfaceFrame, SurfaceFrame::PresentState::Presented); mFrameTimeline->setSfPresent(27 + frameTimeFactor, presentFence); presentFence->signalForTest(32 + frameTimeFactor); @@ -297,7 +302,7 @@ TEST_F(FrameTimelineTest, displayFramesSlidingWindowMovesAfterLimit) { mFrameTimeline->createSurfaceFrameForToken(sPidOne, sUidOne, sLayerNameOne, sLayerNameOne, surfaceFrameToken); mFrameTimeline->setSfWakeUp(sfToken, 22 + frameTimeFactor); - mFrameTimeline->addSurfaceFrame(std::move(surfaceFrame), SurfaceFrame::PresentState::Presented); + mFrameTimeline->addSurfaceFrame(surfaceFrame, SurfaceFrame::PresentState::Presented); mFrameTimeline->setSfPresent(27 + frameTimeFactor, presentFence); presentFence->signalForTest(32 + frameTimeFactor); displayFrame0 = getDisplayFrame(0); @@ -337,7 +342,7 @@ TEST_F(FrameTimelineTest, setMaxDisplayFramesSetsSizeProperly) { sLayerNameOne, std::nullopt); int64_t sfToken = mTokenManager->generateTokenForPredictions({22, 26, 30}); mFrameTimeline->setSfWakeUp(sfToken, 22); - mFrameTimeline->addSurfaceFrame(std::move(surfaceFrame), + mFrameTimeline->addSurfaceFrame(surfaceFrame, SurfaceFrame::PresentState::Presented); mFrameTimeline->setSfPresent(27, presentFence); } @@ -353,7 +358,7 @@ TEST_F(FrameTimelineTest, setMaxDisplayFramesSetsSizeProperly) { sLayerNameOne, std::nullopt); int64_t sfToken = mTokenManager->generateTokenForPredictions({22, 26, 30}); mFrameTimeline->setSfWakeUp(sfToken, 22); - mFrameTimeline->addSurfaceFrame(std::move(surfaceFrame), + mFrameTimeline->addSurfaceFrame(surfaceFrame, SurfaceFrame::PresentState::Presented); mFrameTimeline->setSfPresent(27, presentFence); } @@ -369,7 +374,7 @@ TEST_F(FrameTimelineTest, setMaxDisplayFramesSetsSizeProperly) { sLayerNameOne, std::nullopt); int64_t sfToken = mTokenManager->generateTokenForPredictions({22, 26, 30}); mFrameTimeline->setSfWakeUp(sfToken, 22); - mFrameTimeline->addSurfaceFrame(std::move(surfaceFrame), + mFrameTimeline->addSurfaceFrame(surfaceFrame, SurfaceFrame::PresentState::Presented); mFrameTimeline->setSfPresent(27, presentFence); } @@ -396,10 +401,10 @@ TEST_F(FrameTimelineTest, presentFenceSignaled_reportsLongSfCpu) { sLayerNameOne, surfaceFrameToken1); mFrameTimeline->setSfWakeUp(sfToken1, std::chrono::duration_cast<std::chrono::nanoseconds>(52ms).count()); - mFrameTimeline->addSurfaceFrame(std::move(surfaceFrame1), + mFrameTimeline->addSurfaceFrame(surfaceFrame1, SurfaceFrame::PresentState::Presented); presentFence1->signalForTest( - std::chrono::duration_cast<std::chrono::nanoseconds>(90ms).count()); + std::chrono::duration_cast<std::chrono::nanoseconds>(70ms).count()); mFrameTimeline->setSfPresent(std::chrono::duration_cast<std::chrono::nanoseconds>(59ms).count(), presentFence1); @@ -423,12 +428,14 @@ TEST_F(FrameTimelineTest, presentFenceSignaled_reportsDisplayMiss) { sLayerNameOne, surfaceFrameToken1); mFrameTimeline->setSfWakeUp(sfToken1, std::chrono::duration_cast<std::chrono::nanoseconds>(52ms).count()); - mFrameTimeline->addSurfaceFrame(std::move(surfaceFrame1), + mFrameTimeline->addSurfaceFrame(surfaceFrame1, SurfaceFrame::PresentState::Presented); presentFence1->signalForTest( std::chrono::duration_cast<std::chrono::nanoseconds>(90ms).count()); mFrameTimeline->setSfPresent(std::chrono::duration_cast<std::chrono::nanoseconds>(59ms).count(), presentFence1); + EXPECT_NE(surfaceFrame1->getJankType(), std::nullopt); + EXPECT_TRUE((surfaceFrame1->getJankType().value() & JankType::Display) != 0); } TEST_F(FrameTimelineTest, presentFenceSignaled_reportsAppMiss) { @@ -453,12 +460,15 @@ TEST_F(FrameTimelineTest, presentFenceSignaled_reportsAppMiss) { mFrameTimeline->setSfWakeUp(sfToken1, std::chrono::duration_cast<std::chrono::nanoseconds>(52ms).count()); - mFrameTimeline->addSurfaceFrame(std::move(surfaceFrame1), + mFrameTimeline->addSurfaceFrame(surfaceFrame1, SurfaceFrame::PresentState::Presented); presentFence1->signalForTest( std::chrono::duration_cast<std::chrono::nanoseconds>(90ms).count()); mFrameTimeline->setSfPresent(std::chrono::duration_cast<std::chrono::nanoseconds>(56ms).count(), presentFence1); + + EXPECT_NE(surfaceFrame1->getJankType(), std::nullopt); + EXPECT_TRUE((surfaceFrame1->getJankType().value() & JankType::AppDeadlineMissed) != 0); } /* diff --git a/services/surfaceflinger/tests/unittests/mock/MockFrameTimeline.h b/services/surfaceflinger/tests/unittests/mock/MockFrameTimeline.h index 81c32fe08a..6b1253647b 100644 --- a/services/surfaceflinger/tests/unittests/mock/MockFrameTimeline.h +++ b/services/surfaceflinger/tests/unittests/mock/MockFrameTimeline.h @@ -31,7 +31,7 @@ public: MOCK_METHOD0(onBootFinished, void()); MOCK_METHOD2(addSurfaceFrame, - void(std::unique_ptr<frametimeline::SurfaceFrame>, + void(std::shared_ptr<frametimeline::SurfaceFrame>, frametimeline::SurfaceFrame::PresentState)); MOCK_METHOD2(setSfWakeUp, void(int64_t, nsecs_t)); MOCK_METHOD2(setSfPresent, void(nsecs_t, const std::shared_ptr<FenceTime>&)); |