Loading libs/gui/ITransactionCompletedListener.cpp +2 −4 Original line number Diff line number Diff line Loading @@ -99,15 +99,13 @@ JankData::JankData() : status_t JankData::writeToParcel(Parcel* output) const { SAFE_PARCEL(output->writeInt64, frameVsyncId); SAFE_PARCEL(output->writeInt32, static_cast<int32_t>(jankType)); SAFE_PARCEL(output->writeInt32, 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); SAFE_PARCEL(input->readInt32, &jankType); return NO_ERROR; } Loading libs/gui/include/gui/ITransactionCompletedListener.h +4 −5 Original line number Diff line number Diff line Loading @@ -69,15 +69,14 @@ public: status_t readFromParcel(const Parcel* input) override; JankData(); JankData(int64_t frameVsyncId, JankType jankType) : frameVsyncId(frameVsyncId), jankType(jankType) {} JankData(int64_t frameVsyncId, int32_t jankType) : frameVsyncId(frameVsyncId), jankType(jankType) {} // Identifier for the frame submitted with Transaction.setFrameTimelineVsyncId int64_t frameVsyncId; // The type of jank occurred JankType jankType; // Bitmask of janks that occurred int32_t jankType; }; class SurfaceStats : public Parcelable { Loading libs/gui/include/gui/JankInfo.h +17 −10 Original line number Diff line number Diff line Loading @@ -18,24 +18,31 @@ namespace android { // Jank information tracked by SurfaceFlinger for the purpose of funneling to telemetry. // Jank information tracked by SurfaceFlinger(SF) for perfetto tracing and telemetry. // TODO(b/175843808): Change JankType from enum to enum class enum JankType { // No Jank None = 0x0, // Jank not related to SurfaceFlinger or the App Display = 0x1, // Jank that occurs in the layers below SurfaceFlinger DisplayHAL = 0x1, // SF took too long on the CPU SurfaceFlingerDeadlineMissed = 0x2, SurfaceFlingerCpuDeadlineMissed = 0x2, // SF took too long on the GPU SurfaceFlingerGpuDeadlineMissed = 0x4, // Either App or GPU took too long on the frame AppDeadlineMissed = 0x8, // Predictions live for 120ms, if prediction is expired for a frame, there is definitely a // jank // associated with the App if this is for a SurfaceFrame, and SF for a DisplayFrame. PredictionExpired = 0x10, // Latching a buffer early might cause an early present of the frame SurfaceFlingerEarlyLatch = 0x20, // Vsync predictions have drifted beyond the threshold from the actual HWVsync PredictionError = 0x10, // Janks caused due to the time SF was scheduled to work on the frame // Example: SF woke up too early and latched a buffer resulting in an early present SurfaceFlingerScheduling = 0x20, // A buffer is said to be stuffed if it was expected to be presented on a vsync but was // presented later because the previous buffer was presented in its expected vsync. This // usually happens if there is an unexpectedly long frame causing the rest of the buffers // to enter a stuffed state. BufferStuffing = 0x40, // Jank due to unknown reasons. Unknown = 0x80, }; } // namespace android services/surfaceflinger/BufferQueueLayer.cpp +15 −12 Original line number Diff line number Diff line Loading @@ -274,8 +274,8 @@ status_t BufferQueueLayer::updateTexImage(bool& recomputeVisibleRegions, nsecs_t mConsumer->mergeSurfaceDamage(mQueueItems[0].item.mSurfaceDamage); mFlinger->mTimeStats->removeTimeRecord(layerId, mQueueItems[0].item.mFrameNumber); if (mQueueItems[0].surfaceFrame) { mFlinger->mFrameTimeline->addSurfaceFrame(std::move(mQueueItems[0].surfaceFrame), PresentState::Dropped); mQueueItems[0].surfaceFrame->setPresentState(PresentState::Dropped); mFlinger->mFrameTimeline->addSurfaceFrame(mQueueItems[0].surfaceFrame); } mQueueItems.erase(mQueueItems.begin()); mQueuedFrames--; Loading @@ -290,8 +290,8 @@ status_t BufferQueueLayer::updateTexImage(bool& recomputeVisibleRegions, nsecs_t Mutex::Autolock lock(mQueueItemLock); for (auto& [item, surfaceFrame] : mQueueItems) { if (surfaceFrame) { mFlinger->mFrameTimeline->addSurfaceFrame(std::move(surfaceFrame), PresentState::Dropped); surfaceFrame->setPresentState(PresentState::Dropped); mFlinger->mFrameTimeline->addSurfaceFrame(surfaceFrame); } } mQueueItems.clear(); Loading Loading @@ -321,8 +321,8 @@ status_t BufferQueueLayer::updateTexImage(bool& recomputeVisibleRegions, nsecs_t mConsumer->mergeSurfaceDamage(mQueueItems[0].item.mSurfaceDamage); mFlinger->mTimeStats->removeTimeRecord(layerId, mQueueItems[0].item.mFrameNumber); if (mQueueItems[0].surfaceFrame) { mFlinger->mFrameTimeline->addSurfaceFrame(std::move(mQueueItems[0].surfaceFrame), PresentState::Dropped); mQueueItems[0].surfaceFrame->setPresentState(PresentState::Dropped); mFlinger->mFrameTimeline->addSurfaceFrame(mQueueItems[0].surfaceFrame); } mQueueItems.erase(mQueueItems.begin()); mQueuedFrames--; Loading @@ -336,8 +336,9 @@ status_t BufferQueueLayer::updateTexImage(bool& recomputeVisibleRegions, nsecs_t if (mQueueItems[0].surfaceFrame) { mQueueItems[0].surfaceFrame->setAcquireFenceTime( mQueueItems[0].item.mFenceTime->getSignalTime()); mFlinger->mFrameTimeline->addSurfaceFrame(std::move(mQueueItems[0].surfaceFrame), PresentState::Presented); mQueueItems[0].surfaceFrame->setPresentState(PresentState::Presented, mLastLatchTime); mFlinger->mFrameTimeline->addSurfaceFrame(mQueueItems[0].surfaceFrame); mLastLatchTime = latchTime; } mQueueItems.erase(mQueueItems.begin()); } Loading Loading @@ -436,8 +437,9 @@ void BufferQueueLayer::onFrameAvailable(const BufferItem& item) { } auto surfaceFrame = mFlinger->mFrameTimeline->createSurfaceFrameForToken(mOwnerPid, mOwnerUid, mName, mName, mFrameTimelineVsyncId); mFlinger->mFrameTimeline->createSurfaceFrameForToken(mFrameTimelineVsyncId, mOwnerPid, mOwnerUid, mName, mName); surfaceFrame->setActualQueueTime(systemTime()); mQueueItems.push_back({item, surfaceFrame}); Loading Loading @@ -475,8 +477,9 @@ void BufferQueueLayer::onFrameReplaced(const BufferItem& item) { } auto surfaceFrame = mFlinger->mFrameTimeline->createSurfaceFrameForToken(mOwnerPid, mOwnerUid, mName, mName, mFrameTimelineVsyncId); mFlinger->mFrameTimeline->createSurfaceFrameForToken(mFrameTimelineVsyncId, mOwnerPid, mOwnerUid, mName, mName); surfaceFrame->setActualQueueTime(systemTime()); mQueueItems[mQueueItems.size() - 1].item = item; mQueueItems[mQueueItems.size() - 1].surfaceFrame = std::move(surfaceFrame); Loading services/surfaceflinger/BufferQueueLayer.h +5 −0 Original line number Diff line number Diff line Loading @@ -146,6 +146,11 @@ private: // a buffer to correlate the buffer with the vsync id. Can only be accessed // with the SF state lock held. std::optional<int64_t> mFrameTimelineVsyncId; // Keeps track of the time SF latched the last buffer from this layer. // Used in buffer stuffing analysis in FrameTimeline. // TODO(b/176106798): Find a way to do this for BLASTBufferQueue as well. nsecs_t mLastLatchTime = 0; }; } // namespace android Loading
libs/gui/ITransactionCompletedListener.cpp +2 −4 Original line number Diff line number Diff line Loading @@ -99,15 +99,13 @@ JankData::JankData() : status_t JankData::writeToParcel(Parcel* output) const { SAFE_PARCEL(output->writeInt64, frameVsyncId); SAFE_PARCEL(output->writeInt32, static_cast<int32_t>(jankType)); SAFE_PARCEL(output->writeInt32, 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); SAFE_PARCEL(input->readInt32, &jankType); return NO_ERROR; } Loading
libs/gui/include/gui/ITransactionCompletedListener.h +4 −5 Original line number Diff line number Diff line Loading @@ -69,15 +69,14 @@ public: status_t readFromParcel(const Parcel* input) override; JankData(); JankData(int64_t frameVsyncId, JankType jankType) : frameVsyncId(frameVsyncId), jankType(jankType) {} JankData(int64_t frameVsyncId, int32_t jankType) : frameVsyncId(frameVsyncId), jankType(jankType) {} // Identifier for the frame submitted with Transaction.setFrameTimelineVsyncId int64_t frameVsyncId; // The type of jank occurred JankType jankType; // Bitmask of janks that occurred int32_t jankType; }; class SurfaceStats : public Parcelable { Loading
libs/gui/include/gui/JankInfo.h +17 −10 Original line number Diff line number Diff line Loading @@ -18,24 +18,31 @@ namespace android { // Jank information tracked by SurfaceFlinger for the purpose of funneling to telemetry. // Jank information tracked by SurfaceFlinger(SF) for perfetto tracing and telemetry. // TODO(b/175843808): Change JankType from enum to enum class enum JankType { // No Jank None = 0x0, // Jank not related to SurfaceFlinger or the App Display = 0x1, // Jank that occurs in the layers below SurfaceFlinger DisplayHAL = 0x1, // SF took too long on the CPU SurfaceFlingerDeadlineMissed = 0x2, SurfaceFlingerCpuDeadlineMissed = 0x2, // SF took too long on the GPU SurfaceFlingerGpuDeadlineMissed = 0x4, // Either App or GPU took too long on the frame AppDeadlineMissed = 0x8, // Predictions live for 120ms, if prediction is expired for a frame, there is definitely a // jank // associated with the App if this is for a SurfaceFrame, and SF for a DisplayFrame. PredictionExpired = 0x10, // Latching a buffer early might cause an early present of the frame SurfaceFlingerEarlyLatch = 0x20, // Vsync predictions have drifted beyond the threshold from the actual HWVsync PredictionError = 0x10, // Janks caused due to the time SF was scheduled to work on the frame // Example: SF woke up too early and latched a buffer resulting in an early present SurfaceFlingerScheduling = 0x20, // A buffer is said to be stuffed if it was expected to be presented on a vsync but was // presented later because the previous buffer was presented in its expected vsync. This // usually happens if there is an unexpectedly long frame causing the rest of the buffers // to enter a stuffed state. BufferStuffing = 0x40, // Jank due to unknown reasons. Unknown = 0x80, }; } // namespace android
services/surfaceflinger/BufferQueueLayer.cpp +15 −12 Original line number Diff line number Diff line Loading @@ -274,8 +274,8 @@ status_t BufferQueueLayer::updateTexImage(bool& recomputeVisibleRegions, nsecs_t mConsumer->mergeSurfaceDamage(mQueueItems[0].item.mSurfaceDamage); mFlinger->mTimeStats->removeTimeRecord(layerId, mQueueItems[0].item.mFrameNumber); if (mQueueItems[0].surfaceFrame) { mFlinger->mFrameTimeline->addSurfaceFrame(std::move(mQueueItems[0].surfaceFrame), PresentState::Dropped); mQueueItems[0].surfaceFrame->setPresentState(PresentState::Dropped); mFlinger->mFrameTimeline->addSurfaceFrame(mQueueItems[0].surfaceFrame); } mQueueItems.erase(mQueueItems.begin()); mQueuedFrames--; Loading @@ -290,8 +290,8 @@ status_t BufferQueueLayer::updateTexImage(bool& recomputeVisibleRegions, nsecs_t Mutex::Autolock lock(mQueueItemLock); for (auto& [item, surfaceFrame] : mQueueItems) { if (surfaceFrame) { mFlinger->mFrameTimeline->addSurfaceFrame(std::move(surfaceFrame), PresentState::Dropped); surfaceFrame->setPresentState(PresentState::Dropped); mFlinger->mFrameTimeline->addSurfaceFrame(surfaceFrame); } } mQueueItems.clear(); Loading Loading @@ -321,8 +321,8 @@ status_t BufferQueueLayer::updateTexImage(bool& recomputeVisibleRegions, nsecs_t mConsumer->mergeSurfaceDamage(mQueueItems[0].item.mSurfaceDamage); mFlinger->mTimeStats->removeTimeRecord(layerId, mQueueItems[0].item.mFrameNumber); if (mQueueItems[0].surfaceFrame) { mFlinger->mFrameTimeline->addSurfaceFrame(std::move(mQueueItems[0].surfaceFrame), PresentState::Dropped); mQueueItems[0].surfaceFrame->setPresentState(PresentState::Dropped); mFlinger->mFrameTimeline->addSurfaceFrame(mQueueItems[0].surfaceFrame); } mQueueItems.erase(mQueueItems.begin()); mQueuedFrames--; Loading @@ -336,8 +336,9 @@ status_t BufferQueueLayer::updateTexImage(bool& recomputeVisibleRegions, nsecs_t if (mQueueItems[0].surfaceFrame) { mQueueItems[0].surfaceFrame->setAcquireFenceTime( mQueueItems[0].item.mFenceTime->getSignalTime()); mFlinger->mFrameTimeline->addSurfaceFrame(std::move(mQueueItems[0].surfaceFrame), PresentState::Presented); mQueueItems[0].surfaceFrame->setPresentState(PresentState::Presented, mLastLatchTime); mFlinger->mFrameTimeline->addSurfaceFrame(mQueueItems[0].surfaceFrame); mLastLatchTime = latchTime; } mQueueItems.erase(mQueueItems.begin()); } Loading Loading @@ -436,8 +437,9 @@ void BufferQueueLayer::onFrameAvailable(const BufferItem& item) { } auto surfaceFrame = mFlinger->mFrameTimeline->createSurfaceFrameForToken(mOwnerPid, mOwnerUid, mName, mName, mFrameTimelineVsyncId); mFlinger->mFrameTimeline->createSurfaceFrameForToken(mFrameTimelineVsyncId, mOwnerPid, mOwnerUid, mName, mName); surfaceFrame->setActualQueueTime(systemTime()); mQueueItems.push_back({item, surfaceFrame}); Loading Loading @@ -475,8 +477,9 @@ void BufferQueueLayer::onFrameReplaced(const BufferItem& item) { } auto surfaceFrame = mFlinger->mFrameTimeline->createSurfaceFrameForToken(mOwnerPid, mOwnerUid, mName, mName, mFrameTimelineVsyncId); mFlinger->mFrameTimeline->createSurfaceFrameForToken(mFrameTimelineVsyncId, mOwnerPid, mOwnerUid, mName, mName); surfaceFrame->setActualQueueTime(systemTime()); mQueueItems[mQueueItems.size() - 1].item = item; mQueueItems[mQueueItems.size() - 1].surfaceFrame = std::move(surfaceFrame); Loading
services/surfaceflinger/BufferQueueLayer.h +5 −0 Original line number Diff line number Diff line Loading @@ -146,6 +146,11 @@ private: // a buffer to correlate the buffer with the vsync id. Can only be accessed // with the SF state lock held. std::optional<int64_t> mFrameTimelineVsyncId; // Keeps track of the time SF latched the last buffer from this layer. // Used in buffer stuffing analysis in FrameTimeline. // TODO(b/176106798): Find a way to do this for BLASTBufferQueue as well. nsecs_t mLastLatchTime = 0; }; } // namespace android