diff options
| -rw-r--r-- | AconfigFlags.bp | 15 | ||||
| -rw-r--r-- | core/java/android/view/SurfaceControl.java | 8 | ||||
| -rw-r--r-- | core/java/com/android/internal/jank/FrameTracker.java | 61 | ||||
| -rw-r--r-- | core/java/com/android/internal/jank/flags.aconfig | 10 | ||||
| -rw-r--r-- | core/jni/android_view_SurfaceControl.cpp | 10 | ||||
| -rw-r--r-- | core/tests/coretests/src/com/android/internal/jank/FrameTrackerTest.java | 10 |
6 files changed, 77 insertions, 37 deletions
diff --git a/AconfigFlags.bp b/AconfigFlags.bp index c76812111cec..6f8a189c42b8 100644 --- a/AconfigFlags.bp +++ b/AconfigFlags.bp @@ -100,6 +100,7 @@ aconfig_declarations_group { "framework-jobscheduler-job.flags-aconfig-java", "framework_graphics_flags_java_lib", "hwui_flags_java_lib", + "interaction_jank_monitor_flags_lib", "libcore_exported_aconfig_flags_lib", "libgui_flags_java_lib", "power_flags_lib", @@ -1578,3 +1579,17 @@ java_aconfig_library { aconfig_declarations: "dropbox_flags", defaults: ["framework-minus-apex-aconfig-java-defaults"], } + +// Zero Jank +aconfig_declarations { + name: "interaction_jank_monitor_flags", + package: "com.android.internal.jank", + container: "system", + srcs: ["core/java/com/android/internal/jank/flags.aconfig"], +} + +java_aconfig_library { + name: "interaction_jank_monitor_flags_lib", + aconfig_declarations: "interaction_jank_monitor_flags", + defaults: ["framework-minus-apex-aconfig-java-defaults"], +} diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java index 9e4b27d3fa55..2dda835436bc 100644 --- a/core/java/android/view/SurfaceControl.java +++ b/core/java/android/view/SurfaceControl.java @@ -445,16 +445,20 @@ public final class SurfaceControl implements Parcelable { // 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) { this.frameVsyncId = frameVsyncId; this.jankType = jankType; this.frameIntervalNs = frameIntervalNs; - + this.scheduledAppFrameTimeNs = scheduledAppFrameTimeNs; + this.actualAppFrameTimeNs = actualAppFrameTimeNs; } public final long frameVsyncId; public final @JankType int jankType; public final long frameIntervalNs; + public final long scheduledAppFrameTimeNs; + public final long actualAppFrameTimeNs; } /** diff --git a/core/java/com/android/internal/jank/FrameTracker.java b/core/java/com/android/internal/jank/FrameTracker.java index 53ef49bd3f65..d474c6db4f02 100644 --- a/core/java/com/android/internal/jank/FrameTracker.java +++ b/core/java/com/android/internal/jank/FrameTracker.java @@ -127,7 +127,7 @@ public class FrameTracker implements HardwareRendererObserver.OnFrameMetricsAvai private Runnable mWaitForFinishTimedOut; private static class JankInfo { - long frameVsyncId; + final long frameVsyncId; long totalDurationNanos; boolean isFirstFrame; boolean hwuiCallbackFired; @@ -135,29 +135,42 @@ public class FrameTracker implements HardwareRendererObserver.OnFrameMetricsAvai @JankType int jankType; @RefreshRate int refreshRate; - static JankInfo createFromHwuiCallback(long frameVsyncId, long totalDurationNanos, - boolean isFirstFrame) { - return new JankInfo(frameVsyncId, true, false, JANK_NONE, UNKNOWN_REFRESH_RATE, - totalDurationNanos, isFirstFrame); + static JankInfo createFromHwuiCallback( + long frameVsyncId, long totalDurationNanos, boolean isFirstFrame) { + return new JankInfo(frameVsyncId).update(totalDurationNanos, isFirstFrame); } - static JankInfo createFromSurfaceControlCallback(long frameVsyncId, - @JankType int jankType, @RefreshRate int refreshRate) { - return new JankInfo( - frameVsyncId, false, true, jankType, refreshRate, 0, false /* isFirstFrame */); + static JankInfo createFromSurfaceControlCallback(SurfaceControl.JankData jankStat) { + return new JankInfo(jankStat.frameVsyncId).update(jankStat); } - private JankInfo(long frameVsyncId, boolean hwuiCallbackFired, - boolean surfaceControlCallbackFired, @JankType int jankType, - @RefreshRate int refreshRate, - long totalDurationNanos, boolean isFirstFrame) { + private JankInfo(long frameVsyncId) { this.frameVsyncId = frameVsyncId; - this.hwuiCallbackFired = hwuiCallbackFired; - this.surfaceControlCallbackFired = surfaceControlCallbackFired; - this.jankType = jankType; - this.refreshRate = refreshRate; - this.totalDurationNanos = totalDurationNanos; + this.hwuiCallbackFired = false; + this.surfaceControlCallbackFired = false; + this.jankType = JANK_NONE; + this.refreshRate = UNKNOWN_REFRESH_RATE; + this.totalDurationNanos = 0; + this.isFirstFrame = false; + } + + private JankInfo update(SurfaceControl.JankData jankStat) { + this.surfaceControlCallbackFired = true; + this.jankType = jankStat.jankType; + this.refreshRate = DisplayRefreshRate.getRefreshRate(jankStat.frameIntervalNs); + if (Flags.useSfFrameDuration()) { + this.totalDurationNanos = jankStat.actualAppFrameTimeNs; + } + return this; + } + + private JankInfo update(long totalDurationNanos, boolean isFirstFrame) { + this.hwuiCallbackFired = true; + if (!Flags.useSfFrameDuration()) { + this.totalDurationNanos = totalDurationNanos; + } this.isFirstFrame = isFirstFrame; + return this; } @Override @@ -457,16 +470,12 @@ public class FrameTracker implements HardwareRendererObserver.OnFrameMetricsAvai if (!isInRange(jankStat.frameVsyncId)) { continue; } - int refreshRate = DisplayRefreshRate.getRefreshRate(jankStat.frameIntervalNs); JankInfo info = findJankInfo(jankStat.frameVsyncId); if (info != null) { - info.surfaceControlCallbackFired = true; - info.jankType = jankStat.jankType; - info.refreshRate = refreshRate; + info.update(jankStat); } else { mJankInfos.put((int) jankStat.frameVsyncId, - JankInfo.createFromSurfaceControlCallback( - jankStat.frameVsyncId, jankStat.jankType, refreshRate)); + JankInfo.createFromSurfaceControlCallback(jankStat)); } } processJankInfos(); @@ -513,9 +522,7 @@ public class FrameTracker implements HardwareRendererObserver.OnFrameMetricsAvai } JankInfo info = findJankInfo(frameVsyncId); if (info != null) { - info.hwuiCallbackFired = true; - info.totalDurationNanos = totalDurationNanos; - info.isFirstFrame = isFirstFrame; + info.update(totalDurationNanos, isFirstFrame); } else { mJankInfos.put((int) frameVsyncId, JankInfo.createFromHwuiCallback( frameVsyncId, totalDurationNanos, isFirstFrame)); diff --git a/core/java/com/android/internal/jank/flags.aconfig b/core/java/com/android/internal/jank/flags.aconfig new file mode 100644 index 000000000000..b6b8bc5ac44c --- /dev/null +++ b/core/java/com/android/internal/jank/flags.aconfig @@ -0,0 +1,10 @@ +package: "com.android.internal.jank" +container: "system" + +flag { + name: "use_sf_frame_duration" + namespace: "android_platform_window_surfaces" + description: "Whether to get the frame duration from SurfaceFlinger, or HWUI" + bug: "354763298" + is_fixed_read_only: true +} diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp index 0f531641903a..17c89f88b441 100644 --- a/core/jni/android_view_SurfaceControl.cpp +++ b/core/jni/android_view_SurfaceControl.cpp @@ -2089,9 +2089,11 @@ public: jobjectArray jJankDataArray = env->NewObjectArray(jankData.size(), gJankDataClassInfo.clazz, nullptr); for (size_t i = 0; i < jankData.size(); i++) { - jobject jJankData = env->NewObject(gJankDataClassInfo.clazz, gJankDataClassInfo.ctor, - jankData[i].frameVsyncId, jankData[i].jankType, - jankData[i].frameIntervalNs); + jobject jJankData = + env->NewObject(gJankDataClassInfo.clazz, gJankDataClassInfo.ctor, + jankData[i].frameVsyncId, jankData[i].jankType, + jankData[i].frameIntervalNs, jankData[i].scheduledAppFrameTimeNs, + jankData[i].actualAppFrameTimeNs); env->SetObjectArrayElement(jJankDataArray, i, jJankData); env->DeleteLocalRef(jJankData); } @@ -2727,7 +2729,7 @@ int register_android_view_SurfaceControl(JNIEnv* env) jclass jankDataClazz = FindClassOrDie(env, "android/view/SurfaceControl$JankData"); gJankDataClassInfo.clazz = MakeGlobalRefOrDie(env, jankDataClazz); - gJankDataClassInfo.ctor = GetMethodIDOrDie(env, gJankDataClassInfo.clazz, "<init>", "(JIJ)V"); + gJankDataClassInfo.ctor = GetMethodIDOrDie(env, gJankDataClassInfo.clazz, "<init>", "(JIJJJ)V"); jclass onJankDataListenerClazz = FindClassOrDie(env, "android/view/SurfaceControl$OnJankDataListener"); gJankDataListenerClassInfo.clazz = MakeGlobalRefOrDie(env, onJankDataListenerClazz); diff --git a/core/tests/coretests/src/com/android/internal/jank/FrameTrackerTest.java b/core/tests/coretests/src/com/android/internal/jank/FrameTrackerTest.java index 499caf5e12d3..c3a5b19c9442 100644 --- a/core/tests/coretests/src/com/android/internal/jank/FrameTrackerTest.java +++ b/core/tests/coretests/src/com/android/internal/jank/FrameTrackerTest.java @@ -359,7 +359,7 @@ public class FrameTrackerTest { tracker.end(FrameTracker.REASON_END_NORMAL); // Send incomplete callback for 102L - sendSfFrame(tracker, 102L, JANK_NONE); + sendSfFrame(tracker, 4, 102L, JANK_NONE); // Send janky but complete callbck fo 103L sendFrame(tracker, 50, JANK_APP_DEADLINE_MISSED, 103L); @@ -629,7 +629,7 @@ public class FrameTrackerTest { if (!tracker.mSurfaceOnly) { sendHwuiFrame(tracker, durationMillis, vsyncId, firstWindowFrame); } - sendSfFrame(tracker, vsyncId, jankType); + sendSfFrame(tracker, durationMillis, vsyncId, jankType); } private void sendHwuiFrame(FrameTracker tracker, long durationMillis, long vsyncId, @@ -645,11 +645,13 @@ public class FrameTrackerTest { captor.getValue().run(); } - private void sendSfFrame(FrameTracker tracker, long vsyncId, @JankType int jankType) { + private void sendSfFrame( + FrameTracker tracker, long durationMillis, long vsyncId, @JankType int jankType) { final ArgumentCaptor<Runnable> captor = ArgumentCaptor.forClass(Runnable.class); doNothing().when(tracker).postCallback(captor.capture()); mListenerCapture.getValue().onJankDataAvailable(new JankData[] { - new JankData(vsyncId, jankType, FRAME_TIME_60Hz) + new JankData(vsyncId, jankType, FRAME_TIME_60Hz, FRAME_TIME_60Hz, + TimeUnit.MILLISECONDS.toNanos(durationMillis)) }); captor.getValue().run(); } |