Loading libs/gui/include/gui/JankInfo.h 0 → 100644 +41 −0 Original line number Diff line number Diff line /* * Copyright 2020 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #pragma once namespace android { // Jank information tracked by SurfaceFlinger for the purpose of funneling to telemetry. enum JankType { // No Jank None = 0x0, // Jank not related to SurfaceFlinger or the App Display = 0x1, // SF took too long on the CPU SurfaceFlingerDeadlineMissed = 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, }; } // namespace android services/surfaceflinger/FrameTimeline/FrameTimeline.cpp +29 −29 Original line number Diff line number Diff line Loading @@ -94,19 +94,19 @@ std::string toString(PredictionState predictionState) { } } std::string toString(TimeStats::JankType jankType) { std::string toString(JankType jankType) { switch (jankType) { case TimeStats::JankType::None: case JankType::None: return "None"; case TimeStats::JankType::Display: case JankType::Display: return "Composer/Display - outside SF and App"; case TimeStats::JankType::SurfaceFlingerDeadlineMissed: case JankType::SurfaceFlingerDeadlineMissed: return "SurfaceFlinger Deadline Missed"; case TimeStats::JankType::AppDeadlineMissed: case JankType::AppDeadlineMissed: return "App Deadline Missed"; case TimeStats::JankType::PredictionExpired: case JankType::PredictionExpired: return "Prediction Expired"; case TimeStats::JankType::SurfaceFlingerEarlyLatch: case JankType::SurfaceFlingerEarlyLatch: return "SurfaceFlinger Early Latch"; default: return "Unclassified"; Loading Loading @@ -154,16 +154,16 @@ FrameTimelineEvent::PresentType presentTypeToProto(int32_t jankMetadata) { return FrameTimelineEvent::PRESENT_ON_TIME; } FrameTimelineEvent::JankType JankTypeToProto(TimeStats::JankType jankType) { FrameTimelineEvent::JankType JankTypeToProto(JankType jankType) { switch (jankType) { case TimeStats::None: case JankType::None: return FrameTimelineEvent::JANK_NONE; case TimeStats::Display: case JankType::Display: return FrameTimelineEvent::JANK_DISPLAY_HAL; case TimeStats::SurfaceFlingerDeadlineMissed: case JankType::SurfaceFlingerDeadlineMissed: return FrameTimelineEvent::JANK_SF_DEADLINE_MISSED; case TimeStats::AppDeadlineMissed: case TimeStats::PredictionExpired: case JankType::AppDeadlineMissed: case JankType::PredictionExpired: return FrameTimelineEvent::JANK_APP_DEADLINE_MISSED; default: return FrameTimelineEvent::JANK_UNKNOWN; Loading Loading @@ -217,7 +217,7 @@ SurfaceFrame::SurfaceFrame(int64_t token, pid_t ownerPid, uid_t ownerUid, std::s mPredictions(predictions), mActuals({0, 0, 0}), mActualQueueTime(0), mJankType(TimeStats::JankType::None), mJankType(JankType::None), mJankMetadata(0) {} void SurfaceFrame::setPresentState(PresentState state) { Loading Loading @@ -259,13 +259,13 @@ void SurfaceFrame::setActualPresentTime(nsecs_t presentTime) { mActuals.presentTime = presentTime; } void SurfaceFrame::setJankInfo(TimeStats::JankType jankType, int32_t jankMetadata) { void SurfaceFrame::setJankInfo(JankType jankType, int32_t jankMetadata) { std::lock_guard<std::mutex> lock(mMutex); mJankType = jankType; mJankMetadata = jankMetadata; } TimeStats::JankType SurfaceFrame::getJankType() const { JankType SurfaceFrame::getJankType() const { std::lock_guard<std::mutex> lock(mMutex); return mJankType; } Loading Loading @@ -300,7 +300,7 @@ void SurfaceFrame::dump(std::string& result, const std::string& indent, nsecs_t std::lock_guard<std::mutex> lock(mMutex); StringAppendF(&result, "%s", indent.c_str()); StringAppendF(&result, "Layer - %s", mDebugName.c_str()); if (mJankType != TimeStats::JankType::None) { if (mJankType != JankType::None) { // Easily identify a janky Surface Frame in the dump StringAppendF(&result, " [*] "); } Loading Loading @@ -454,7 +454,7 @@ void FrameTimeline::flushPendingPresentFences() { } } if (signalTime != Fence::SIGNAL_TIME_INVALID) { int32_t totalJankReasons = TimeStats::JankType::None; int32_t totalJankReasons = JankType::None; auto& displayFrame = pendingPresentFence.second; displayFrame->surfaceFlingerActuals.presentTime = signalTime; Loading @@ -475,14 +475,14 @@ void FrameTimeline::flushPendingPresentFences() { if ((displayFrame->jankMetadata & EarlyFinish) && (displayFrame->jankMetadata & EarlyPresent)) { displayFrame->jankType = TimeStats::JankType::SurfaceFlingerEarlyLatch; displayFrame->jankType = JankType::SurfaceFlingerEarlyLatch; } else if ((displayFrame->jankMetadata & LateFinish) && (displayFrame->jankMetadata & LatePresent)) { displayFrame->jankType = TimeStats::JankType::SurfaceFlingerDeadlineMissed; displayFrame->jankType = JankType::SurfaceFlingerDeadlineMissed; } else if (displayFrame->jankMetadata & EarlyPresent || displayFrame->jankMetadata & LatePresent) { // Cases where SF finished early but frame was presented late and vice versa displayFrame->jankType = TimeStats::JankType::Display; displayFrame->jankType = JankType::Display; } } Loading @@ -503,12 +503,12 @@ void FrameTimeline::flushPendingPresentFences() { const auto& predictionState = surfaceFrame->getPredictionState(); if (predictionState == PredictionState::Expired) { // Jank analysis cannot be done on apps that don't use predictions surfaceFrame->setJankInfo(TimeStats::JankType::PredictionExpired, 0); surfaceFrame->setJankInfo(JankType::PredictionExpired, 0); } else if (predictionState == PredictionState::Valid) { const auto& actuals = surfaceFrame->getActuals(); const auto& predictions = surfaceFrame->getPredictions(); int32_t jankMetadata = 0; TimeStats::JankType jankType = TimeStats::JankType::None; JankType jankType = JankType::None; if (std::abs(actuals.endTime - predictions.endTime) > kDeadlineThreshold) { jankMetadata |= actuals.endTime > predictions.endTime ? LateFinish : EarlyFinish; Loading @@ -520,13 +520,13 @@ void FrameTimeline::flushPendingPresentFences() { : EarlyPresent; } if (jankMetadata & EarlyPresent) { jankType = TimeStats::JankType::SurfaceFlingerEarlyLatch; jankType = JankType::SurfaceFlingerEarlyLatch; } else if (jankMetadata & LatePresent) { if (jankMetadata & EarlyFinish) { // TODO(b/169890654): Classify this properly jankType = TimeStats::JankType::Display; jankType = JankType::Display; } else { jankType = TimeStats::JankType::AppDeadlineMissed; jankType = JankType::AppDeadlineMissed; } } Loading Loading @@ -576,7 +576,7 @@ nsecs_t FrameTimeline::findBaseTime(const std::shared_ptr<DisplayFrame>& display void FrameTimeline::dumpDisplayFrame(std::string& result, const std::shared_ptr<DisplayFrame>& displayFrame, nsecs_t baseTime) { if (displayFrame->jankType != TimeStats::JankType::None) { if (displayFrame->jankType != JankType::None) { // Easily identify a janky Display Frame in the dump StringAppendF(&result, " [*] "); } Loading Loading @@ -610,11 +610,11 @@ void FrameTimeline::dumpJank(std::string& result) { nsecs_t baseTime = (mDisplayFrames.empty()) ? 0 : findBaseTime(mDisplayFrames[0]); for (size_t i = 0; i < mDisplayFrames.size(); i++) { const auto& displayFrame = mDisplayFrames[i]; if (displayFrame->jankType == TimeStats::JankType::None) { if (displayFrame->jankType == JankType::None) { // Check if any Surface Frame has been janky bool isJanky = false; for (const auto& surfaceFrame : displayFrame->surfaceFrames) { if (surfaceFrame->getJankType() != TimeStats::JankType::None) { if (surfaceFrame->getJankType() != JankType::None) { isJanky = true; break; } Loading services/surfaceflinger/FrameTimeline/FrameTimeline.h +5 −4 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ #include <../TimeStats/TimeStats.h> #include <gui/ISurfaceComposer.h> #include <gui/JankInfo.h> #include <perfetto/trace/android/frame_timeline_event.pbzero.h> #include <perfetto/tracing.h> #include <ui/FenceTime.h> Loading Loading @@ -208,7 +209,7 @@ public: PresentState getPresentState() const override; PredictionState getPredictionState() const override { return mPredictionState; }; pid_t getOwnerPid() const override { return mOwnerPid; }; TimeStats::JankType getJankType() const; JankType getJankType() const; int64_t getToken() const { return mToken; }; nsecs_t getBaseTime() const; uid_t getOwnerUid() const { return mOwnerUid; }; Loading @@ -219,7 +220,7 @@ public: void setAcquireFenceTime(nsecs_t acquireFenceTime) override; void setPresentState(PresentState state) override; void setActualPresentTime(nsecs_t presentTime); void setJankInfo(TimeStats::JankType jankType, int32_t jankMetadata); void setJankInfo(JankType jankType, int32_t jankMetadata); // All the timestamps are dumped relative to the baseTime void dump(std::string& result, const std::string& indent, nsecs_t baseTime); Loading @@ -241,7 +242,7 @@ private: TimelineItem mActuals GUARDED_BY(mMutex); nsecs_t mActualQueueTime GUARDED_BY(mMutex); mutable std::mutex mMutex; TimeStats::JankType mJankType GUARDED_BY(mMutex); // Enum for the type of jank JankType mJankType GUARDED_BY(mMutex); // Enum for the type of jank int32_t mJankMetadata GUARDED_BY(mMutex); // Additional details about the jank }; Loading Loading @@ -301,7 +302,7 @@ private: std::vector<std::unique_ptr<SurfaceFrame>> surfaceFrames; PredictionState predictionState = PredictionState::None; TimeStats::JankType jankType = TimeStats::JankType::None; // Enum for the type of jank JankType jankType = JankType::None; // Enum for the type of jank int32_t jankMetadata = 0x0; // Additional details about the jank }; Loading services/surfaceflinger/TimeStats/TimeStats.cpp +7 −7 Original line number Diff line number Diff line Loading @@ -681,21 +681,21 @@ static void updateJankPayload(T& t, int32_t reasons) { t.jankPayload.totalFrames++; static const constexpr int32_t kValidJankyReason = TimeStats::JankType::SurfaceFlingerDeadlineMissed | TimeStats::JankType::SurfaceFlingerGpuDeadlineMissed | TimeStats::JankType::AppDeadlineMissed | TimeStats::JankType::Display; JankType::SurfaceFlingerDeadlineMissed | JankType::SurfaceFlingerGpuDeadlineMissed | JankType::AppDeadlineMissed | JankType::Display; if (reasons & kValidJankyReason) { t.jankPayload.totalJankyFrames++; if ((reasons & TimeStats::JankType::SurfaceFlingerDeadlineMissed) != 0) { if ((reasons & JankType::SurfaceFlingerDeadlineMissed) != 0) { t.jankPayload.totalSFLongCpu++; } if ((reasons & TimeStats::JankType::SurfaceFlingerGpuDeadlineMissed) != 0) { if ((reasons & JankType::SurfaceFlingerGpuDeadlineMissed) != 0) { t.jankPayload.totalSFLongGpu++; } if ((reasons & TimeStats::JankType::Display) != 0) { if ((reasons & JankType::Display) != 0) { t.jankPayload.totalSFUnattributed++; } if ((reasons & TimeStats::JankType::AppDeadlineMissed) != 0) { if ((reasons & JankType::AppDeadlineMissed) != 0) { t.jankPayload.totalAppUnattributed++; } } Loading services/surfaceflinger/TimeStats/TimeStats.h +1 −20 Original line number Diff line number Diff line Loading @@ -31,6 +31,7 @@ #include <statslog.h> #include <timestatsproto/TimeStatsHelper.h> #include <timestatsproto/TimeStatsProtoHeader.h> #include <gui/JankInfo.h> #include <ui/FenceTime.h> #include <utils/String16.h> #include <utils/Vector.h> Loading Loading @@ -110,26 +111,6 @@ public: virtual void setPresentFence(int32_t layerId, uint64_t frameNumber, const std::shared_ptr<FenceTime>& presentFence) = 0; // Subset of jank metadata tracked by FrameTimeline for the purpose of funneling to telemetry. enum JankType { // No Jank None = 0x0, // Jank not related to SurfaceFlinger or the App Display = 0x1, // SF took too long on the CPU SurfaceFlingerDeadlineMissed = 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, }; // Increments janky frames, tracked globally. Because FrameTimeline is the infrastructure // responsible for computing jank in the system, this is expected to be called from // FrameTimeline, rather than directly from SurfaceFlinger or individual layers. If there are no Loading Loading
libs/gui/include/gui/JankInfo.h 0 → 100644 +41 −0 Original line number Diff line number Diff line /* * Copyright 2020 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #pragma once namespace android { // Jank information tracked by SurfaceFlinger for the purpose of funneling to telemetry. enum JankType { // No Jank None = 0x0, // Jank not related to SurfaceFlinger or the App Display = 0x1, // SF took too long on the CPU SurfaceFlingerDeadlineMissed = 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, }; } // namespace android
services/surfaceflinger/FrameTimeline/FrameTimeline.cpp +29 −29 Original line number Diff line number Diff line Loading @@ -94,19 +94,19 @@ std::string toString(PredictionState predictionState) { } } std::string toString(TimeStats::JankType jankType) { std::string toString(JankType jankType) { switch (jankType) { case TimeStats::JankType::None: case JankType::None: return "None"; case TimeStats::JankType::Display: case JankType::Display: return "Composer/Display - outside SF and App"; case TimeStats::JankType::SurfaceFlingerDeadlineMissed: case JankType::SurfaceFlingerDeadlineMissed: return "SurfaceFlinger Deadline Missed"; case TimeStats::JankType::AppDeadlineMissed: case JankType::AppDeadlineMissed: return "App Deadline Missed"; case TimeStats::JankType::PredictionExpired: case JankType::PredictionExpired: return "Prediction Expired"; case TimeStats::JankType::SurfaceFlingerEarlyLatch: case JankType::SurfaceFlingerEarlyLatch: return "SurfaceFlinger Early Latch"; default: return "Unclassified"; Loading Loading @@ -154,16 +154,16 @@ FrameTimelineEvent::PresentType presentTypeToProto(int32_t jankMetadata) { return FrameTimelineEvent::PRESENT_ON_TIME; } FrameTimelineEvent::JankType JankTypeToProto(TimeStats::JankType jankType) { FrameTimelineEvent::JankType JankTypeToProto(JankType jankType) { switch (jankType) { case TimeStats::None: case JankType::None: return FrameTimelineEvent::JANK_NONE; case TimeStats::Display: case JankType::Display: return FrameTimelineEvent::JANK_DISPLAY_HAL; case TimeStats::SurfaceFlingerDeadlineMissed: case JankType::SurfaceFlingerDeadlineMissed: return FrameTimelineEvent::JANK_SF_DEADLINE_MISSED; case TimeStats::AppDeadlineMissed: case TimeStats::PredictionExpired: case JankType::AppDeadlineMissed: case JankType::PredictionExpired: return FrameTimelineEvent::JANK_APP_DEADLINE_MISSED; default: return FrameTimelineEvent::JANK_UNKNOWN; Loading Loading @@ -217,7 +217,7 @@ SurfaceFrame::SurfaceFrame(int64_t token, pid_t ownerPid, uid_t ownerUid, std::s mPredictions(predictions), mActuals({0, 0, 0}), mActualQueueTime(0), mJankType(TimeStats::JankType::None), mJankType(JankType::None), mJankMetadata(0) {} void SurfaceFrame::setPresentState(PresentState state) { Loading Loading @@ -259,13 +259,13 @@ void SurfaceFrame::setActualPresentTime(nsecs_t presentTime) { mActuals.presentTime = presentTime; } void SurfaceFrame::setJankInfo(TimeStats::JankType jankType, int32_t jankMetadata) { void SurfaceFrame::setJankInfo(JankType jankType, int32_t jankMetadata) { std::lock_guard<std::mutex> lock(mMutex); mJankType = jankType; mJankMetadata = jankMetadata; } TimeStats::JankType SurfaceFrame::getJankType() const { JankType SurfaceFrame::getJankType() const { std::lock_guard<std::mutex> lock(mMutex); return mJankType; } Loading Loading @@ -300,7 +300,7 @@ void SurfaceFrame::dump(std::string& result, const std::string& indent, nsecs_t std::lock_guard<std::mutex> lock(mMutex); StringAppendF(&result, "%s", indent.c_str()); StringAppendF(&result, "Layer - %s", mDebugName.c_str()); if (mJankType != TimeStats::JankType::None) { if (mJankType != JankType::None) { // Easily identify a janky Surface Frame in the dump StringAppendF(&result, " [*] "); } Loading Loading @@ -454,7 +454,7 @@ void FrameTimeline::flushPendingPresentFences() { } } if (signalTime != Fence::SIGNAL_TIME_INVALID) { int32_t totalJankReasons = TimeStats::JankType::None; int32_t totalJankReasons = JankType::None; auto& displayFrame = pendingPresentFence.second; displayFrame->surfaceFlingerActuals.presentTime = signalTime; Loading @@ -475,14 +475,14 @@ void FrameTimeline::flushPendingPresentFences() { if ((displayFrame->jankMetadata & EarlyFinish) && (displayFrame->jankMetadata & EarlyPresent)) { displayFrame->jankType = TimeStats::JankType::SurfaceFlingerEarlyLatch; displayFrame->jankType = JankType::SurfaceFlingerEarlyLatch; } else if ((displayFrame->jankMetadata & LateFinish) && (displayFrame->jankMetadata & LatePresent)) { displayFrame->jankType = TimeStats::JankType::SurfaceFlingerDeadlineMissed; displayFrame->jankType = JankType::SurfaceFlingerDeadlineMissed; } else if (displayFrame->jankMetadata & EarlyPresent || displayFrame->jankMetadata & LatePresent) { // Cases where SF finished early but frame was presented late and vice versa displayFrame->jankType = TimeStats::JankType::Display; displayFrame->jankType = JankType::Display; } } Loading @@ -503,12 +503,12 @@ void FrameTimeline::flushPendingPresentFences() { const auto& predictionState = surfaceFrame->getPredictionState(); if (predictionState == PredictionState::Expired) { // Jank analysis cannot be done on apps that don't use predictions surfaceFrame->setJankInfo(TimeStats::JankType::PredictionExpired, 0); surfaceFrame->setJankInfo(JankType::PredictionExpired, 0); } else if (predictionState == PredictionState::Valid) { const auto& actuals = surfaceFrame->getActuals(); const auto& predictions = surfaceFrame->getPredictions(); int32_t jankMetadata = 0; TimeStats::JankType jankType = TimeStats::JankType::None; JankType jankType = JankType::None; if (std::abs(actuals.endTime - predictions.endTime) > kDeadlineThreshold) { jankMetadata |= actuals.endTime > predictions.endTime ? LateFinish : EarlyFinish; Loading @@ -520,13 +520,13 @@ void FrameTimeline::flushPendingPresentFences() { : EarlyPresent; } if (jankMetadata & EarlyPresent) { jankType = TimeStats::JankType::SurfaceFlingerEarlyLatch; jankType = JankType::SurfaceFlingerEarlyLatch; } else if (jankMetadata & LatePresent) { if (jankMetadata & EarlyFinish) { // TODO(b/169890654): Classify this properly jankType = TimeStats::JankType::Display; jankType = JankType::Display; } else { jankType = TimeStats::JankType::AppDeadlineMissed; jankType = JankType::AppDeadlineMissed; } } Loading Loading @@ -576,7 +576,7 @@ nsecs_t FrameTimeline::findBaseTime(const std::shared_ptr<DisplayFrame>& display void FrameTimeline::dumpDisplayFrame(std::string& result, const std::shared_ptr<DisplayFrame>& displayFrame, nsecs_t baseTime) { if (displayFrame->jankType != TimeStats::JankType::None) { if (displayFrame->jankType != JankType::None) { // Easily identify a janky Display Frame in the dump StringAppendF(&result, " [*] "); } Loading Loading @@ -610,11 +610,11 @@ void FrameTimeline::dumpJank(std::string& result) { nsecs_t baseTime = (mDisplayFrames.empty()) ? 0 : findBaseTime(mDisplayFrames[0]); for (size_t i = 0; i < mDisplayFrames.size(); i++) { const auto& displayFrame = mDisplayFrames[i]; if (displayFrame->jankType == TimeStats::JankType::None) { if (displayFrame->jankType == JankType::None) { // Check if any Surface Frame has been janky bool isJanky = false; for (const auto& surfaceFrame : displayFrame->surfaceFrames) { if (surfaceFrame->getJankType() != TimeStats::JankType::None) { if (surfaceFrame->getJankType() != JankType::None) { isJanky = true; break; } Loading
services/surfaceflinger/FrameTimeline/FrameTimeline.h +5 −4 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ #include <../TimeStats/TimeStats.h> #include <gui/ISurfaceComposer.h> #include <gui/JankInfo.h> #include <perfetto/trace/android/frame_timeline_event.pbzero.h> #include <perfetto/tracing.h> #include <ui/FenceTime.h> Loading Loading @@ -208,7 +209,7 @@ public: PresentState getPresentState() const override; PredictionState getPredictionState() const override { return mPredictionState; }; pid_t getOwnerPid() const override { return mOwnerPid; }; TimeStats::JankType getJankType() const; JankType getJankType() const; int64_t getToken() const { return mToken; }; nsecs_t getBaseTime() const; uid_t getOwnerUid() const { return mOwnerUid; }; Loading @@ -219,7 +220,7 @@ public: void setAcquireFenceTime(nsecs_t acquireFenceTime) override; void setPresentState(PresentState state) override; void setActualPresentTime(nsecs_t presentTime); void setJankInfo(TimeStats::JankType jankType, int32_t jankMetadata); void setJankInfo(JankType jankType, int32_t jankMetadata); // All the timestamps are dumped relative to the baseTime void dump(std::string& result, const std::string& indent, nsecs_t baseTime); Loading @@ -241,7 +242,7 @@ private: TimelineItem mActuals GUARDED_BY(mMutex); nsecs_t mActualQueueTime GUARDED_BY(mMutex); mutable std::mutex mMutex; TimeStats::JankType mJankType GUARDED_BY(mMutex); // Enum for the type of jank JankType mJankType GUARDED_BY(mMutex); // Enum for the type of jank int32_t mJankMetadata GUARDED_BY(mMutex); // Additional details about the jank }; Loading Loading @@ -301,7 +302,7 @@ private: std::vector<std::unique_ptr<SurfaceFrame>> surfaceFrames; PredictionState predictionState = PredictionState::None; TimeStats::JankType jankType = TimeStats::JankType::None; // Enum for the type of jank JankType jankType = JankType::None; // Enum for the type of jank int32_t jankMetadata = 0x0; // Additional details about the jank }; Loading
services/surfaceflinger/TimeStats/TimeStats.cpp +7 −7 Original line number Diff line number Diff line Loading @@ -681,21 +681,21 @@ static void updateJankPayload(T& t, int32_t reasons) { t.jankPayload.totalFrames++; static const constexpr int32_t kValidJankyReason = TimeStats::JankType::SurfaceFlingerDeadlineMissed | TimeStats::JankType::SurfaceFlingerGpuDeadlineMissed | TimeStats::JankType::AppDeadlineMissed | TimeStats::JankType::Display; JankType::SurfaceFlingerDeadlineMissed | JankType::SurfaceFlingerGpuDeadlineMissed | JankType::AppDeadlineMissed | JankType::Display; if (reasons & kValidJankyReason) { t.jankPayload.totalJankyFrames++; if ((reasons & TimeStats::JankType::SurfaceFlingerDeadlineMissed) != 0) { if ((reasons & JankType::SurfaceFlingerDeadlineMissed) != 0) { t.jankPayload.totalSFLongCpu++; } if ((reasons & TimeStats::JankType::SurfaceFlingerGpuDeadlineMissed) != 0) { if ((reasons & JankType::SurfaceFlingerGpuDeadlineMissed) != 0) { t.jankPayload.totalSFLongGpu++; } if ((reasons & TimeStats::JankType::Display) != 0) { if ((reasons & JankType::Display) != 0) { t.jankPayload.totalSFUnattributed++; } if ((reasons & TimeStats::JankType::AppDeadlineMissed) != 0) { if ((reasons & JankType::AppDeadlineMissed) != 0) { t.jankPayload.totalAppUnattributed++; } } Loading
services/surfaceflinger/TimeStats/TimeStats.h +1 −20 Original line number Diff line number Diff line Loading @@ -31,6 +31,7 @@ #include <statslog.h> #include <timestatsproto/TimeStatsHelper.h> #include <timestatsproto/TimeStatsProtoHeader.h> #include <gui/JankInfo.h> #include <ui/FenceTime.h> #include <utils/String16.h> #include <utils/Vector.h> Loading Loading @@ -110,26 +111,6 @@ public: virtual void setPresentFence(int32_t layerId, uint64_t frameNumber, const std::shared_ptr<FenceTime>& presentFence) = 0; // Subset of jank metadata tracked by FrameTimeline for the purpose of funneling to telemetry. enum JankType { // No Jank None = 0x0, // Jank not related to SurfaceFlinger or the App Display = 0x1, // SF took too long on the CPU SurfaceFlingerDeadlineMissed = 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, }; // Increments janky frames, tracked globally. Because FrameTimeline is the infrastructure // responsible for computing jank in the system, this is expected to be called from // FrameTimeline, rather than directly from SurfaceFlinger or individual layers. If there are no Loading