summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--AconfigFlags.bp15
-rw-r--r--core/java/android/view/SurfaceControl.java8
-rw-r--r--core/java/com/android/internal/jank/FrameTracker.java61
-rw-r--r--core/java/com/android/internal/jank/flags.aconfig10
-rw-r--r--core/jni/android_view_SurfaceControl.cpp10
-rw-r--r--core/tests/coretests/src/com/android/internal/jank/FrameTrackerTest.java10
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();
}