Loading core/java/android/view/SurfaceControl.java +18 −31 Original line number Original line Diff line number Diff line Loading @@ -412,41 +412,28 @@ public final class SurfaceControl implements Parcelable { */ */ public static class JankData { public static class JankData { /** @hide */ /** @IntDef(flag = true, value = {JANK_NONE, * Needs to be kept in sync with android_view_SurfaceControl.cpp's DISPLAY_HAL, * JankDataListenerWrapper::onJankDataAvailable. JANK_SURFACEFLINGER_DEADLINE_MISSED, * @hide JANK_SURFACEFLINGER_GPU_DEADLINE_MISSED, */ JANK_APP_DEADLINE_MISSED, @IntDef(flag = true, value = { PREDICTION_ERROR, JANK_NONE, SURFACE_FLINGER_SCHEDULING}) JANK_COMPOSER, JANK_APPLICATION, JANK_OTHER, }) @Retention(RetentionPolicy.SOURCE) @Retention(RetentionPolicy.SOURCE) public @interface JankType {} public @interface JankType {} // Needs to be kept in sync with frameworks/native/libs/gui/include/gui/JankInfo.h // No Jank // No Jank public static final int JANK_NONE = 0x0; public static final int JANK_NONE = 0; // Jank caused by the composer missing a deadline // Jank not related to SurfaceFlinger or the App public static final int JANK_COMPOSER = 1 << 0; public static final int DISPLAY_HAL = 0x1; // Jank caused by the application missing the composer's deadline // SF took too long on the CPU public static final int JANK_APPLICATION = 1 << 1; public static final int JANK_SURFACEFLINGER_DEADLINE_MISSED = 0x2; // Jank due to other unknown reasons // SF took too long on the GPU public static final int JANK_OTHER = 1 << 2; public static final int JANK_SURFACEFLINGER_GPU_DEADLINE_MISSED = 0x4; // Either App or GPU took too long on the frame public static final int JANK_APP_DEADLINE_MISSED = 0x8; // Vsync predictions have drifted beyond the threshold from the actual HWVsync public static final int PREDICTION_ERROR = 0x10; // Latching a buffer early might cause an early present of the frame public static final int SURFACE_FLINGER_SCHEDULING = 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. public static final int BUFFER_STUFFING = 0x40; // Jank due to unknown reasons. public static final int UNKNOWN = 0x80; public JankData(long frameVsyncId, @JankType int jankType, long frameIntervalNs, public JankData(long frameVsyncId, @JankType int jankType, long frameIntervalNs, long scheduledAppFrameTimeNs, long actualAppFrameTimeNs) { long scheduledAppFrameTimeNs, long actualAppFrameTimeNs) { Loading core/java/com/android/internal/jank/FrameTracker.java +8 −28 Original line number Original line Diff line number Diff line Loading @@ -16,13 +16,9 @@ package com.android.internal.jank; package com.android.internal.jank; import static android.view.SurfaceControl.JankData.DISPLAY_HAL; import static android.view.SurfaceControl.JankData.JANK_APPLICATION; import static android.view.SurfaceControl.JankData.JANK_APP_DEADLINE_MISSED; import static android.view.SurfaceControl.JankData.JANK_COMPOSER; import static android.view.SurfaceControl.JankData.JANK_NONE; import static android.view.SurfaceControl.JankData.JANK_NONE; import static android.view.SurfaceControl.JankData.JANK_SURFACEFLINGER_DEADLINE_MISSED; import static android.view.SurfaceControl.JankData.JANK_SURFACEFLINGER_GPU_DEADLINE_MISSED; import static android.view.SurfaceControl.JankData.PREDICTION_ERROR; import static android.view.SurfaceControl.JankData.SURFACE_FLINGER_SCHEDULING; import static com.android.internal.jank.DisplayRefreshRate.UNKNOWN_REFRESH_RATE; import static com.android.internal.jank.DisplayRefreshRate.UNKNOWN_REFRESH_RATE; import static com.android.internal.jank.DisplayRefreshRate.VARIABLE_REFRESH_RATE; import static com.android.internal.jank.DisplayRefreshRate.VARIABLE_REFRESH_RATE; Loading Loading @@ -181,23 +177,11 @@ public class FrameTracker implements HardwareRendererObserver.OnFrameMetricsAvai case JANK_NONE: case JANK_NONE: str.append("JANK_NONE"); str.append("JANK_NONE"); break; break; case JANK_APP_DEADLINE_MISSED: case JANK_APPLICATION: str.append("JANK_APP_DEADLINE_MISSED"); str.append("JANK_APPLICATION"); break; break; case JANK_SURFACEFLINGER_DEADLINE_MISSED: case JANK_COMPOSER: str.append("JANK_SURFACEFLINGER_DEADLINE_MISSED"); str.append("JANK_COMPOSER"); break; case JANK_SURFACEFLINGER_GPU_DEADLINE_MISSED: str.append("JANK_SURFACEFLINGER_GPU_DEADLINE_MISSED"); break; case DISPLAY_HAL: str.append("DISPLAY_HAL"); break; case PREDICTION_ERROR: str.append("PREDICTION_ERROR"); break; case SURFACE_FLINGER_SCHEDULING: str.append("SURFACE_FLINGER_SCHEDULING"); break; break; default: default: str.append("UNKNOWN: ").append(jankType); str.append("UNKNOWN: ").append(jankType); Loading Loading @@ -628,16 +612,12 @@ public class FrameTracker implements HardwareRendererObserver.OnFrameMetricsAvai if (info.surfaceControlCallbackFired) { if (info.surfaceControlCallbackFired) { totalFramesCount++; totalFramesCount++; boolean missedFrame = false; boolean missedFrame = false; if ((info.jankType & JANK_APP_DEADLINE_MISSED) != 0) { if ((info.jankType & JANK_APPLICATION) != 0) { Log.w(TAG, "Missed App frame:" + info + ", CUJ=" + name); Log.w(TAG, "Missed App frame:" + info + ", CUJ=" + name); missedAppFramesCount++; missedAppFramesCount++; missedFrame = true; missedFrame = true; } } if ((info.jankType & DISPLAY_HAL) != 0 if ((info.jankType & JANK_COMPOSER) != 0) { || (info.jankType & JANK_SURFACEFLINGER_DEADLINE_MISSED) != 0 || (info.jankType & JANK_SURFACEFLINGER_GPU_DEADLINE_MISSED) != 0 || (info.jankType & SURFACE_FLINGER_SCHEDULING) != 0 || (info.jankType & PREDICTION_ERROR) != 0) { Log.w(TAG, "Missed SF frame:" + info + ", CUJ=" + name); Log.w(TAG, "Missed SF frame:" + info + ", CUJ=" + name); missedSfFramesCount++; missedSfFramesCount++; missedFrame = true; missedFrame = true; Loading core/jni/android_view_SurfaceControl.cpp +23 −1 Original line number Original line Diff line number Diff line Loading @@ -35,6 +35,7 @@ #include <android_runtime/android_view_SurfaceSession.h> #include <android_runtime/android_view_SurfaceSession.h> #include <cutils/ashmem.h> #include <cutils/ashmem.h> #include <gui/ISurfaceComposer.h> #include <gui/ISurfaceComposer.h> #include <gui/JankInfo.h> #include <gui/Surface.h> #include <gui/Surface.h> #include <gui/SurfaceComposerClient.h> #include <gui/SurfaceComposerClient.h> #include <jni.h> #include <jni.h> Loading Loading @@ -2161,9 +2162,30 @@ public: jobjectArray jJankDataArray = env->NewObjectArray(jankData.size(), jobjectArray jJankDataArray = env->NewObjectArray(jankData.size(), gJankDataClassInfo.clazz, nullptr); gJankDataClassInfo.clazz, nullptr); for (size_t i = 0; i < jankData.size(); i++) { for (size_t i = 0; i < jankData.size(); i++) { // The exposed constants in SurfaceControl are simplified, so we need to translate the // jank type we get from SF to what is exposed in Java. int sfJankType = jankData[i].jankType; int javaJankType = 0x0; // SurfaceControl.JankData.JANK_NONE if (sfJankType & (JankType::DisplayHAL | JankType::SurfaceFlingerCpuDeadlineMissed | JankType::SurfaceFlingerGpuDeadlineMissed | JankType::PredictionError | JankType::SurfaceFlingerScheduling)) { javaJankType |= 0x1; // SurfaceControl.JankData.JANK_COMPOSER } if (sfJankType & JankType::AppDeadlineMissed) { javaJankType |= 0x2; // SurfaceControl.JankData.JANK_APPLICATION } if (sfJankType & ~(JankType::DisplayHAL | JankType::SurfaceFlingerCpuDeadlineMissed | JankType::SurfaceFlingerGpuDeadlineMissed | JankType::AppDeadlineMissed | JankType::PredictionError | JankType::SurfaceFlingerScheduling | JankType::BufferStuffing | JankType::SurfaceFlingerStuffing)) { javaJankType |= 0x4; // SurfaceControl.JankData.JANK_OTHER } jobject jJankData = jobject jJankData = env->NewObject(gJankDataClassInfo.clazz, gJankDataClassInfo.ctor, env->NewObject(gJankDataClassInfo.clazz, gJankDataClassInfo.ctor, jankData[i].frameVsyncId, jankData[i].jankType, jankData[i].frameVsyncId, javaJankType, jankData[i].frameIntervalNs, jankData[i].scheduledAppFrameTimeNs, jankData[i].frameIntervalNs, jankData[i].scheduledAppFrameTimeNs, jankData[i].actualAppFrameTimeNs); jankData[i].actualAppFrameTimeNs); env->SetObjectArrayElement(jJankDataArray, i, jJankData); env->SetObjectArrayElement(jJankDataArray, i, jJankData); Loading core/tests/coretests/src/com/android/internal/jank/FrameTrackerTest.java +20 −20 Original line number Original line Diff line number Diff line Loading @@ -16,9 +16,9 @@ package com.android.internal.jank; package com.android.internal.jank; import static android.view.SurfaceControl.JankData.JANK_APP_DEADLINE_MISSED; import static android.view.SurfaceControl.JankData.JANK_APPLICATION; import static android.view.SurfaceControl.JankData.JANK_COMPOSER; import static android.view.SurfaceControl.JankData.JANK_NONE; import static android.view.SurfaceControl.JankData.JANK_NONE; import static android.view.SurfaceControl.JankData.JANK_SURFACEFLINGER_DEADLINE_MISSED; import static com.android.internal.jank.FrameTracker.SurfaceControlWrapper; import static com.android.internal.jank.FrameTracker.SurfaceControlWrapper; import static com.android.internal.jank.FrameTracker.ViewRootWrapper; import static com.android.internal.jank.FrameTracker.ViewRootWrapper; Loading Loading @@ -164,7 +164,7 @@ public class FrameTrackerTest { verify(mRenderer, only()).addObserver(any()); verify(mRenderer, only()).addObserver(any()); // send first frame with a long duration - should not be taken into account // send first frame with a long duration - should not be taken into account sendFirstWindowFrame(tracker, 100, JANK_APP_DEADLINE_MISSED, 100L); sendFirstWindowFrame(tracker, 100, JANK_APPLICATION, 100L); // send another frame with a short duration - should not be considered janky // send another frame with a short duration - should not be considered janky sendFrame(tracker, 5, JANK_NONE, 101L); sendFrame(tracker, 5, JANK_NONE, 101L); Loading @@ -173,7 +173,7 @@ public class FrameTrackerTest { when(mChoreographer.getVsyncId()).thenReturn(102L); when(mChoreographer.getVsyncId()).thenReturn(102L); tracker.end(FrameTracker.REASON_END_NORMAL); tracker.end(FrameTracker.REASON_END_NORMAL); sendFrame(tracker, 5, JANK_NONE, 102L); sendFrame(tracker, 5, JANK_NONE, 102L); sendFrame(tracker, 500, JANK_APP_DEADLINE_MISSED, 103L); sendFrame(tracker, 500, JANK_APPLICATION, 103L); verify(tracker).removeObservers(); verify(tracker).removeObservers(); verify(mTrackerListener, never()).triggerPerfetto(any()); verify(mTrackerListener, never()).triggerPerfetto(any()); Loading Loading @@ -202,7 +202,7 @@ public class FrameTrackerTest { sendFrame(tracker, 4, JANK_NONE, 100L); sendFrame(tracker, 4, JANK_NONE, 100L); // send another frame - should be considered janky // send another frame - should be considered janky sendFrame(tracker, 40, JANK_SURFACEFLINGER_DEADLINE_MISSED, 101L); sendFrame(tracker, 40, JANK_COMPOSER, 101L); // end the trace session // end the trace session when(mChoreographer.getVsyncId()).thenReturn(102L); when(mChoreographer.getVsyncId()).thenReturn(102L); Loading Loading @@ -236,7 +236,7 @@ public class FrameTrackerTest { verify(mRenderer, only()).addObserver(any()); verify(mRenderer, only()).addObserver(any()); // send first frame - janky // send first frame - janky sendFrame(tracker, 40, JANK_APP_DEADLINE_MISSED, 100L); sendFrame(tracker, 40, JANK_APPLICATION, 100L); // send another frame - not jank // send another frame - not jank sendFrame(tracker, 4, JANK_NONE, 101L); sendFrame(tracker, 4, JANK_NONE, 101L); Loading Loading @@ -275,7 +275,7 @@ public class FrameTrackerTest { sendFrame(tracker, 4, JANK_NONE, 100L); sendFrame(tracker, 4, JANK_NONE, 100L); // send another frame - should be considered janky // send another frame - should be considered janky sendFrame(tracker, 40, JANK_APP_DEADLINE_MISSED, 101L); sendFrame(tracker, 40, JANK_APPLICATION, 101L); // end the trace session // end the trace session when(mChoreographer.getVsyncId()).thenReturn(102L); when(mChoreographer.getVsyncId()).thenReturn(102L); Loading Loading @@ -317,7 +317,7 @@ public class FrameTrackerTest { // end the trace session, simulate one more valid callback came after the end call. // end the trace session, simulate one more valid callback came after the end call. when(mChoreographer.getVsyncId()).thenReturn(102L); when(mChoreographer.getVsyncId()).thenReturn(102L); tracker.end(FrameTracker.REASON_END_NORMAL); tracker.end(FrameTracker.REASON_END_NORMAL); sendFrame(tracker, 50, JANK_APP_DEADLINE_MISSED, 102L); sendFrame(tracker, 50, JANK_APPLICATION, 102L); // One more callback with VSYNC after the end() vsync id. // One more callback with VSYNC after the end() vsync id. sendFrame(tracker, 4, JANK_NONE, 103L); sendFrame(tracker, 4, JANK_NONE, 103L); Loading Loading @@ -365,7 +365,7 @@ public class FrameTrackerTest { sendSfFrame(tracker, 4, 102L, JANK_NONE); sendSfFrame(tracker, 4, 102L, JANK_NONE); // Send janky but complete callbck fo 103L // Send janky but complete callbck fo 103L sendFrame(tracker, 50, JANK_APP_DEADLINE_MISSED, 103L); sendFrame(tracker, 50, JANK_APPLICATION, 103L); verify(tracker).removeObservers(); verify(tracker).removeObservers(); verify(mTrackerListener, never()).triggerPerfetto(any()); verify(mTrackerListener, never()).triggerPerfetto(any()); Loading Loading @@ -397,7 +397,7 @@ public class FrameTrackerTest { sendFrame(tracker, 4, JANK_NONE, 101L); sendFrame(tracker, 4, JANK_NONE, 101L); // a janky frame // a janky frame sendFrame(tracker, 50, JANK_APP_DEADLINE_MISSED, 102L); sendFrame(tracker, 50, JANK_APPLICATION, 102L); tracker.cancel(FrameTracker.REASON_CANCEL_NORMAL); tracker.cancel(FrameTracker.REASON_CANCEL_NORMAL); verify(tracker).removeObservers(); verify(tracker).removeObservers(); Loading Loading @@ -481,7 +481,7 @@ public class FrameTrackerTest { // normal frame - not janky // normal frame - not janky sendFrame(tracker, JANK_NONE, 101L); sendFrame(tracker, JANK_NONE, 101L); // a janky frame // a janky frame sendFrame(tracker, JANK_APP_DEADLINE_MISSED, 102L); sendFrame(tracker, JANK_APPLICATION, 102L); when(mChoreographer.getVsyncId()).thenReturn(102L); when(mChoreographer.getVsyncId()).thenReturn(102L); tracker.end(FrameTracker.REASON_CANCEL_NORMAL); tracker.end(FrameTracker.REASON_CANCEL_NORMAL); Loading Loading @@ -514,7 +514,7 @@ public class FrameTrackerTest { verify(mSurfaceControlWrapper).addJankStatsListener(any(), any()); verify(mSurfaceControlWrapper).addJankStatsListener(any(), any()); // First frame - janky // First frame - janky sendFrame(tracker, JANK_APP_DEADLINE_MISSED, 100L); sendFrame(tracker, JANK_APPLICATION, 100L); // normal frame - not janky // normal frame - not janky sendFrame(tracker, JANK_NONE, 101L); sendFrame(tracker, JANK_NONE, 101L); // normal frame - not janky // normal frame - not janky Loading Loading @@ -561,7 +561,7 @@ public class FrameTrackerTest { tracker.end(FrameTracker.REASON_CANCEL_NORMAL); tracker.end(FrameTracker.REASON_CANCEL_NORMAL); // janky frame, should be ignored, trigger finish // janky frame, should be ignored, trigger finish sendFrame(tracker, JANK_APP_DEADLINE_MISSED, 103L); sendFrame(tracker, JANK_APPLICATION, 103L); verify(mJankStatsRegistration).removeAfter(anyLong()); verify(mJankStatsRegistration).removeAfter(anyLong()); verify(mTrackerListener, never()).triggerPerfetto(any()); verify(mTrackerListener, never()).triggerPerfetto(any()); Loading Loading @@ -623,16 +623,16 @@ public class FrameTrackerTest { tracker.begin(); tracker.begin(); mRunnableArgumentCaptor.getValue().run(); mRunnableArgumentCaptor.getValue().run(); verify(mSurfaceControlWrapper).addJankStatsListener(any(), any()); verify(mSurfaceControlWrapper).addJankStatsListener(any(), any()); sendFrame(tracker, JANK_SURFACEFLINGER_DEADLINE_MISSED, 100L); sendFrame(tracker, JANK_COMPOSER, 100L); sendFrame(tracker, JANK_SURFACEFLINGER_DEADLINE_MISSED, 101L); sendFrame(tracker, JANK_COMPOSER, 101L); sendFrame(tracker, JANK_APP_DEADLINE_MISSED, 102L); sendFrame(tracker, JANK_APPLICATION, 102L); sendFrame(tracker, JANK_NONE, 103L); sendFrame(tracker, JANK_NONE, 103L); sendFrame(tracker, JANK_APP_DEADLINE_MISSED, 104L); sendFrame(tracker, JANK_APPLICATION, 104L); sendFrame(tracker, JANK_APP_DEADLINE_MISSED, 105L); sendFrame(tracker, JANK_APPLICATION, 105L); when(mChoreographer.getVsyncId()).thenReturn(106L); when(mChoreographer.getVsyncId()).thenReturn(106L); tracker.end(FrameTracker.REASON_END_NORMAL); tracker.end(FrameTracker.REASON_END_NORMAL); sendFrame(tracker, JANK_SURFACEFLINGER_DEADLINE_MISSED, 106L); sendFrame(tracker, JANK_COMPOSER, 106L); sendFrame(tracker, JANK_SURFACEFLINGER_DEADLINE_MISSED, 107L); sendFrame(tracker, JANK_COMPOSER, 107L); verify(mJankStatsRegistration).removeAfter(anyLong()); verify(mJankStatsRegistration).removeAfter(anyLong()); verify(mTrackerListener).triggerPerfetto(any()); verify(mTrackerListener).triggerPerfetto(any()); verify(mStatsLog).write(eq(UI_INTERACTION_FRAME_INFO_REPORTED), verify(mStatsLog).write(eq(UI_INTERACTION_FRAME_INFO_REPORTED), Loading Loading
core/java/android/view/SurfaceControl.java +18 −31 Original line number Original line Diff line number Diff line Loading @@ -412,41 +412,28 @@ public final class SurfaceControl implements Parcelable { */ */ public static class JankData { public static class JankData { /** @hide */ /** @IntDef(flag = true, value = {JANK_NONE, * Needs to be kept in sync with android_view_SurfaceControl.cpp's DISPLAY_HAL, * JankDataListenerWrapper::onJankDataAvailable. JANK_SURFACEFLINGER_DEADLINE_MISSED, * @hide JANK_SURFACEFLINGER_GPU_DEADLINE_MISSED, */ JANK_APP_DEADLINE_MISSED, @IntDef(flag = true, value = { PREDICTION_ERROR, JANK_NONE, SURFACE_FLINGER_SCHEDULING}) JANK_COMPOSER, JANK_APPLICATION, JANK_OTHER, }) @Retention(RetentionPolicy.SOURCE) @Retention(RetentionPolicy.SOURCE) public @interface JankType {} public @interface JankType {} // Needs to be kept in sync with frameworks/native/libs/gui/include/gui/JankInfo.h // No Jank // No Jank public static final int JANK_NONE = 0x0; public static final int JANK_NONE = 0; // Jank caused by the composer missing a deadline // Jank not related to SurfaceFlinger or the App public static final int JANK_COMPOSER = 1 << 0; public static final int DISPLAY_HAL = 0x1; // Jank caused by the application missing the composer's deadline // SF took too long on the CPU public static final int JANK_APPLICATION = 1 << 1; public static final int JANK_SURFACEFLINGER_DEADLINE_MISSED = 0x2; // Jank due to other unknown reasons // SF took too long on the GPU public static final int JANK_OTHER = 1 << 2; public static final int JANK_SURFACEFLINGER_GPU_DEADLINE_MISSED = 0x4; // Either App or GPU took too long on the frame public static final int JANK_APP_DEADLINE_MISSED = 0x8; // Vsync predictions have drifted beyond the threshold from the actual HWVsync public static final int PREDICTION_ERROR = 0x10; // Latching a buffer early might cause an early present of the frame public static final int SURFACE_FLINGER_SCHEDULING = 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. public static final int BUFFER_STUFFING = 0x40; // Jank due to unknown reasons. public static final int UNKNOWN = 0x80; public JankData(long frameVsyncId, @JankType int jankType, long frameIntervalNs, public JankData(long frameVsyncId, @JankType int jankType, long frameIntervalNs, long scheduledAppFrameTimeNs, long actualAppFrameTimeNs) { long scheduledAppFrameTimeNs, long actualAppFrameTimeNs) { Loading
core/java/com/android/internal/jank/FrameTracker.java +8 −28 Original line number Original line Diff line number Diff line Loading @@ -16,13 +16,9 @@ package com.android.internal.jank; package com.android.internal.jank; import static android.view.SurfaceControl.JankData.DISPLAY_HAL; import static android.view.SurfaceControl.JankData.JANK_APPLICATION; import static android.view.SurfaceControl.JankData.JANK_APP_DEADLINE_MISSED; import static android.view.SurfaceControl.JankData.JANK_COMPOSER; import static android.view.SurfaceControl.JankData.JANK_NONE; import static android.view.SurfaceControl.JankData.JANK_NONE; import static android.view.SurfaceControl.JankData.JANK_SURFACEFLINGER_DEADLINE_MISSED; import static android.view.SurfaceControl.JankData.JANK_SURFACEFLINGER_GPU_DEADLINE_MISSED; import static android.view.SurfaceControl.JankData.PREDICTION_ERROR; import static android.view.SurfaceControl.JankData.SURFACE_FLINGER_SCHEDULING; import static com.android.internal.jank.DisplayRefreshRate.UNKNOWN_REFRESH_RATE; import static com.android.internal.jank.DisplayRefreshRate.UNKNOWN_REFRESH_RATE; import static com.android.internal.jank.DisplayRefreshRate.VARIABLE_REFRESH_RATE; import static com.android.internal.jank.DisplayRefreshRate.VARIABLE_REFRESH_RATE; Loading Loading @@ -181,23 +177,11 @@ public class FrameTracker implements HardwareRendererObserver.OnFrameMetricsAvai case JANK_NONE: case JANK_NONE: str.append("JANK_NONE"); str.append("JANK_NONE"); break; break; case JANK_APP_DEADLINE_MISSED: case JANK_APPLICATION: str.append("JANK_APP_DEADLINE_MISSED"); str.append("JANK_APPLICATION"); break; break; case JANK_SURFACEFLINGER_DEADLINE_MISSED: case JANK_COMPOSER: str.append("JANK_SURFACEFLINGER_DEADLINE_MISSED"); str.append("JANK_COMPOSER"); break; case JANK_SURFACEFLINGER_GPU_DEADLINE_MISSED: str.append("JANK_SURFACEFLINGER_GPU_DEADLINE_MISSED"); break; case DISPLAY_HAL: str.append("DISPLAY_HAL"); break; case PREDICTION_ERROR: str.append("PREDICTION_ERROR"); break; case SURFACE_FLINGER_SCHEDULING: str.append("SURFACE_FLINGER_SCHEDULING"); break; break; default: default: str.append("UNKNOWN: ").append(jankType); str.append("UNKNOWN: ").append(jankType); Loading Loading @@ -628,16 +612,12 @@ public class FrameTracker implements HardwareRendererObserver.OnFrameMetricsAvai if (info.surfaceControlCallbackFired) { if (info.surfaceControlCallbackFired) { totalFramesCount++; totalFramesCount++; boolean missedFrame = false; boolean missedFrame = false; if ((info.jankType & JANK_APP_DEADLINE_MISSED) != 0) { if ((info.jankType & JANK_APPLICATION) != 0) { Log.w(TAG, "Missed App frame:" + info + ", CUJ=" + name); Log.w(TAG, "Missed App frame:" + info + ", CUJ=" + name); missedAppFramesCount++; missedAppFramesCount++; missedFrame = true; missedFrame = true; } } if ((info.jankType & DISPLAY_HAL) != 0 if ((info.jankType & JANK_COMPOSER) != 0) { || (info.jankType & JANK_SURFACEFLINGER_DEADLINE_MISSED) != 0 || (info.jankType & JANK_SURFACEFLINGER_GPU_DEADLINE_MISSED) != 0 || (info.jankType & SURFACE_FLINGER_SCHEDULING) != 0 || (info.jankType & PREDICTION_ERROR) != 0) { Log.w(TAG, "Missed SF frame:" + info + ", CUJ=" + name); Log.w(TAG, "Missed SF frame:" + info + ", CUJ=" + name); missedSfFramesCount++; missedSfFramesCount++; missedFrame = true; missedFrame = true; Loading
core/jni/android_view_SurfaceControl.cpp +23 −1 Original line number Original line Diff line number Diff line Loading @@ -35,6 +35,7 @@ #include <android_runtime/android_view_SurfaceSession.h> #include <android_runtime/android_view_SurfaceSession.h> #include <cutils/ashmem.h> #include <cutils/ashmem.h> #include <gui/ISurfaceComposer.h> #include <gui/ISurfaceComposer.h> #include <gui/JankInfo.h> #include <gui/Surface.h> #include <gui/Surface.h> #include <gui/SurfaceComposerClient.h> #include <gui/SurfaceComposerClient.h> #include <jni.h> #include <jni.h> Loading Loading @@ -2161,9 +2162,30 @@ public: jobjectArray jJankDataArray = env->NewObjectArray(jankData.size(), jobjectArray jJankDataArray = env->NewObjectArray(jankData.size(), gJankDataClassInfo.clazz, nullptr); gJankDataClassInfo.clazz, nullptr); for (size_t i = 0; i < jankData.size(); i++) { for (size_t i = 0; i < jankData.size(); i++) { // The exposed constants in SurfaceControl are simplified, so we need to translate the // jank type we get from SF to what is exposed in Java. int sfJankType = jankData[i].jankType; int javaJankType = 0x0; // SurfaceControl.JankData.JANK_NONE if (sfJankType & (JankType::DisplayHAL | JankType::SurfaceFlingerCpuDeadlineMissed | JankType::SurfaceFlingerGpuDeadlineMissed | JankType::PredictionError | JankType::SurfaceFlingerScheduling)) { javaJankType |= 0x1; // SurfaceControl.JankData.JANK_COMPOSER } if (sfJankType & JankType::AppDeadlineMissed) { javaJankType |= 0x2; // SurfaceControl.JankData.JANK_APPLICATION } if (sfJankType & ~(JankType::DisplayHAL | JankType::SurfaceFlingerCpuDeadlineMissed | JankType::SurfaceFlingerGpuDeadlineMissed | JankType::AppDeadlineMissed | JankType::PredictionError | JankType::SurfaceFlingerScheduling | JankType::BufferStuffing | JankType::SurfaceFlingerStuffing)) { javaJankType |= 0x4; // SurfaceControl.JankData.JANK_OTHER } jobject jJankData = jobject jJankData = env->NewObject(gJankDataClassInfo.clazz, gJankDataClassInfo.ctor, env->NewObject(gJankDataClassInfo.clazz, gJankDataClassInfo.ctor, jankData[i].frameVsyncId, jankData[i].jankType, jankData[i].frameVsyncId, javaJankType, jankData[i].frameIntervalNs, jankData[i].scheduledAppFrameTimeNs, jankData[i].frameIntervalNs, jankData[i].scheduledAppFrameTimeNs, jankData[i].actualAppFrameTimeNs); jankData[i].actualAppFrameTimeNs); env->SetObjectArrayElement(jJankDataArray, i, jJankData); env->SetObjectArrayElement(jJankDataArray, i, jJankData); Loading
core/tests/coretests/src/com/android/internal/jank/FrameTrackerTest.java +20 −20 Original line number Original line Diff line number Diff line Loading @@ -16,9 +16,9 @@ package com.android.internal.jank; package com.android.internal.jank; import static android.view.SurfaceControl.JankData.JANK_APP_DEADLINE_MISSED; import static android.view.SurfaceControl.JankData.JANK_APPLICATION; import static android.view.SurfaceControl.JankData.JANK_COMPOSER; import static android.view.SurfaceControl.JankData.JANK_NONE; import static android.view.SurfaceControl.JankData.JANK_NONE; import static android.view.SurfaceControl.JankData.JANK_SURFACEFLINGER_DEADLINE_MISSED; import static com.android.internal.jank.FrameTracker.SurfaceControlWrapper; import static com.android.internal.jank.FrameTracker.SurfaceControlWrapper; import static com.android.internal.jank.FrameTracker.ViewRootWrapper; import static com.android.internal.jank.FrameTracker.ViewRootWrapper; Loading Loading @@ -164,7 +164,7 @@ public class FrameTrackerTest { verify(mRenderer, only()).addObserver(any()); verify(mRenderer, only()).addObserver(any()); // send first frame with a long duration - should not be taken into account // send first frame with a long duration - should not be taken into account sendFirstWindowFrame(tracker, 100, JANK_APP_DEADLINE_MISSED, 100L); sendFirstWindowFrame(tracker, 100, JANK_APPLICATION, 100L); // send another frame with a short duration - should not be considered janky // send another frame with a short duration - should not be considered janky sendFrame(tracker, 5, JANK_NONE, 101L); sendFrame(tracker, 5, JANK_NONE, 101L); Loading @@ -173,7 +173,7 @@ public class FrameTrackerTest { when(mChoreographer.getVsyncId()).thenReturn(102L); when(mChoreographer.getVsyncId()).thenReturn(102L); tracker.end(FrameTracker.REASON_END_NORMAL); tracker.end(FrameTracker.REASON_END_NORMAL); sendFrame(tracker, 5, JANK_NONE, 102L); sendFrame(tracker, 5, JANK_NONE, 102L); sendFrame(tracker, 500, JANK_APP_DEADLINE_MISSED, 103L); sendFrame(tracker, 500, JANK_APPLICATION, 103L); verify(tracker).removeObservers(); verify(tracker).removeObservers(); verify(mTrackerListener, never()).triggerPerfetto(any()); verify(mTrackerListener, never()).triggerPerfetto(any()); Loading Loading @@ -202,7 +202,7 @@ public class FrameTrackerTest { sendFrame(tracker, 4, JANK_NONE, 100L); sendFrame(tracker, 4, JANK_NONE, 100L); // send another frame - should be considered janky // send another frame - should be considered janky sendFrame(tracker, 40, JANK_SURFACEFLINGER_DEADLINE_MISSED, 101L); sendFrame(tracker, 40, JANK_COMPOSER, 101L); // end the trace session // end the trace session when(mChoreographer.getVsyncId()).thenReturn(102L); when(mChoreographer.getVsyncId()).thenReturn(102L); Loading Loading @@ -236,7 +236,7 @@ public class FrameTrackerTest { verify(mRenderer, only()).addObserver(any()); verify(mRenderer, only()).addObserver(any()); // send first frame - janky // send first frame - janky sendFrame(tracker, 40, JANK_APP_DEADLINE_MISSED, 100L); sendFrame(tracker, 40, JANK_APPLICATION, 100L); // send another frame - not jank // send another frame - not jank sendFrame(tracker, 4, JANK_NONE, 101L); sendFrame(tracker, 4, JANK_NONE, 101L); Loading Loading @@ -275,7 +275,7 @@ public class FrameTrackerTest { sendFrame(tracker, 4, JANK_NONE, 100L); sendFrame(tracker, 4, JANK_NONE, 100L); // send another frame - should be considered janky // send another frame - should be considered janky sendFrame(tracker, 40, JANK_APP_DEADLINE_MISSED, 101L); sendFrame(tracker, 40, JANK_APPLICATION, 101L); // end the trace session // end the trace session when(mChoreographer.getVsyncId()).thenReturn(102L); when(mChoreographer.getVsyncId()).thenReturn(102L); Loading Loading @@ -317,7 +317,7 @@ public class FrameTrackerTest { // end the trace session, simulate one more valid callback came after the end call. // end the trace session, simulate one more valid callback came after the end call. when(mChoreographer.getVsyncId()).thenReturn(102L); when(mChoreographer.getVsyncId()).thenReturn(102L); tracker.end(FrameTracker.REASON_END_NORMAL); tracker.end(FrameTracker.REASON_END_NORMAL); sendFrame(tracker, 50, JANK_APP_DEADLINE_MISSED, 102L); sendFrame(tracker, 50, JANK_APPLICATION, 102L); // One more callback with VSYNC after the end() vsync id. // One more callback with VSYNC after the end() vsync id. sendFrame(tracker, 4, JANK_NONE, 103L); sendFrame(tracker, 4, JANK_NONE, 103L); Loading Loading @@ -365,7 +365,7 @@ public class FrameTrackerTest { sendSfFrame(tracker, 4, 102L, JANK_NONE); sendSfFrame(tracker, 4, 102L, JANK_NONE); // Send janky but complete callbck fo 103L // Send janky but complete callbck fo 103L sendFrame(tracker, 50, JANK_APP_DEADLINE_MISSED, 103L); sendFrame(tracker, 50, JANK_APPLICATION, 103L); verify(tracker).removeObservers(); verify(tracker).removeObservers(); verify(mTrackerListener, never()).triggerPerfetto(any()); verify(mTrackerListener, never()).triggerPerfetto(any()); Loading Loading @@ -397,7 +397,7 @@ public class FrameTrackerTest { sendFrame(tracker, 4, JANK_NONE, 101L); sendFrame(tracker, 4, JANK_NONE, 101L); // a janky frame // a janky frame sendFrame(tracker, 50, JANK_APP_DEADLINE_MISSED, 102L); sendFrame(tracker, 50, JANK_APPLICATION, 102L); tracker.cancel(FrameTracker.REASON_CANCEL_NORMAL); tracker.cancel(FrameTracker.REASON_CANCEL_NORMAL); verify(tracker).removeObservers(); verify(tracker).removeObservers(); Loading Loading @@ -481,7 +481,7 @@ public class FrameTrackerTest { // normal frame - not janky // normal frame - not janky sendFrame(tracker, JANK_NONE, 101L); sendFrame(tracker, JANK_NONE, 101L); // a janky frame // a janky frame sendFrame(tracker, JANK_APP_DEADLINE_MISSED, 102L); sendFrame(tracker, JANK_APPLICATION, 102L); when(mChoreographer.getVsyncId()).thenReturn(102L); when(mChoreographer.getVsyncId()).thenReturn(102L); tracker.end(FrameTracker.REASON_CANCEL_NORMAL); tracker.end(FrameTracker.REASON_CANCEL_NORMAL); Loading Loading @@ -514,7 +514,7 @@ public class FrameTrackerTest { verify(mSurfaceControlWrapper).addJankStatsListener(any(), any()); verify(mSurfaceControlWrapper).addJankStatsListener(any(), any()); // First frame - janky // First frame - janky sendFrame(tracker, JANK_APP_DEADLINE_MISSED, 100L); sendFrame(tracker, JANK_APPLICATION, 100L); // normal frame - not janky // normal frame - not janky sendFrame(tracker, JANK_NONE, 101L); sendFrame(tracker, JANK_NONE, 101L); // normal frame - not janky // normal frame - not janky Loading Loading @@ -561,7 +561,7 @@ public class FrameTrackerTest { tracker.end(FrameTracker.REASON_CANCEL_NORMAL); tracker.end(FrameTracker.REASON_CANCEL_NORMAL); // janky frame, should be ignored, trigger finish // janky frame, should be ignored, trigger finish sendFrame(tracker, JANK_APP_DEADLINE_MISSED, 103L); sendFrame(tracker, JANK_APPLICATION, 103L); verify(mJankStatsRegistration).removeAfter(anyLong()); verify(mJankStatsRegistration).removeAfter(anyLong()); verify(mTrackerListener, never()).triggerPerfetto(any()); verify(mTrackerListener, never()).triggerPerfetto(any()); Loading Loading @@ -623,16 +623,16 @@ public class FrameTrackerTest { tracker.begin(); tracker.begin(); mRunnableArgumentCaptor.getValue().run(); mRunnableArgumentCaptor.getValue().run(); verify(mSurfaceControlWrapper).addJankStatsListener(any(), any()); verify(mSurfaceControlWrapper).addJankStatsListener(any(), any()); sendFrame(tracker, JANK_SURFACEFLINGER_DEADLINE_MISSED, 100L); sendFrame(tracker, JANK_COMPOSER, 100L); sendFrame(tracker, JANK_SURFACEFLINGER_DEADLINE_MISSED, 101L); sendFrame(tracker, JANK_COMPOSER, 101L); sendFrame(tracker, JANK_APP_DEADLINE_MISSED, 102L); sendFrame(tracker, JANK_APPLICATION, 102L); sendFrame(tracker, JANK_NONE, 103L); sendFrame(tracker, JANK_NONE, 103L); sendFrame(tracker, JANK_APP_DEADLINE_MISSED, 104L); sendFrame(tracker, JANK_APPLICATION, 104L); sendFrame(tracker, JANK_APP_DEADLINE_MISSED, 105L); sendFrame(tracker, JANK_APPLICATION, 105L); when(mChoreographer.getVsyncId()).thenReturn(106L); when(mChoreographer.getVsyncId()).thenReturn(106L); tracker.end(FrameTracker.REASON_END_NORMAL); tracker.end(FrameTracker.REASON_END_NORMAL); sendFrame(tracker, JANK_SURFACEFLINGER_DEADLINE_MISSED, 106L); sendFrame(tracker, JANK_COMPOSER, 106L); sendFrame(tracker, JANK_SURFACEFLINGER_DEADLINE_MISSED, 107L); sendFrame(tracker, JANK_COMPOSER, 107L); verify(mJankStatsRegistration).removeAfter(anyLong()); verify(mJankStatsRegistration).removeAfter(anyLong()); verify(mTrackerListener).triggerPerfetto(any()); verify(mTrackerListener).triggerPerfetto(any()); verify(mStatsLog).write(eq(UI_INTERACTION_FRAME_INFO_REPORTED), verify(mStatsLog).write(eq(UI_INTERACTION_FRAME_INFO_REPORTED), Loading