Fix GfxMonitorImpl to match latest `dumpsys GfxInfo` output.
Change-Id: Iad0a1ac8ed5c9a6a52e1cdc45e44563f779a9c05
diff --git a/src/main/java/android/support/test/jank/internal/GfxMonitorImpl.java b/src/main/java/android/support/test/jank/internal/GfxMonitorImpl.java
index bc1abd5..15077ee 100644
--- a/src/main/java/android/support/test/jank/internal/GfxMonitorImpl.java
+++ b/src/main/java/android/support/test/jank/internal/GfxMonitorImpl.java
@@ -26,6 +26,8 @@
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
+import java.util.EnumMap;
+import java.util.Map;
import java.util.List;
import java.util.regex.Pattern;
import java.util.regex.Matcher;
@@ -41,46 +43,62 @@
class GfxMonitorImpl implements JankMonitor {
// Patterns used for parsing dumpsys gfxinfo output
- private static final Pattern TOTAL_FRAMES_PATTERN =
- Pattern.compile("\\s*Total frames rendered: (\\d+)");
- private static final Pattern JANKY_FRAMES_PATTERN =
- Pattern.compile("\\s*Janky frames: (\\d+) \\(.*\\)");
- private static final Pattern MISSED_VSYNC_PATTERN =
- Pattern.compile("\\s*Number Missed Vsync: (\\d+)");
- private static final Pattern INPUT_LATENCY_PATTERN =
- Pattern.compile("\\s*Number High input latency: (\\d+)");
- private static final Pattern SLOW_UI_PATTERN =
- Pattern.compile("\\s*Number Slow UI thread: (\\d+)");
- private static final Pattern SLOW_BITMAP_PATTERN =
- Pattern.compile("\\s*Number Slow bitmap uploads: (\\d+)");
- private static final Pattern SLOW_DRAW_PATTERN =
- Pattern.compile("\\s*Number Slow draw: (\\d+)");
- private static final Pattern FRAME_TIME_90TH_PERCENTILE_PATTERN =
- Pattern.compile("\\s*90th percentile: (\\d+)ms");
- private static final Pattern FRAME_TIME_95TH_PERCENTILE_PATTERN =
- Pattern.compile("\\s*95th percentile: (\\d+)ms");
- private static final Pattern FRAME_TIME_99TH_PERCENTILE_PATTERN =
- Pattern.compile("\\s*99th percentile: (\\d+)ms");
+ public enum JankStat {
+ TOTAL_FRAMES(Pattern.compile("\\s*Total frames rendered: (\\d+)"), 1),
+ NUM_JANKY(Pattern.compile("\\s*Janky frames: (\\d+) \\(.*\\)"), 1),
+ FRAME_TIME_90TH(Pattern.compile("\\s*90th percentile: (\\d+)ms"), 1),
+ FRAME_TIME_95TH(Pattern.compile("\\s*95th percentile: (\\d+)ms"), 1),
+ FRAME_TIME_99TH(Pattern.compile("\\s*99th percentile: (\\d+)ms"), 1),
+ NUM_MISSED_VSYNC(Pattern.compile("\\s*Number Missed Vsync: (\\d+)"), 1),
+ NUM_HIGH_INPUT_LATENCY(Pattern.compile("\\s*Number High input latency: (\\d+)"), 1),
+ NUM_SLOW_UI_THREAD(Pattern.compile("\\s*Number Slow UI thread: (\\d+)"), 1),
+ NUM_SLOW_BITMAP_UPLOADS(Pattern.compile("\\s*Number Slow bitmap uploads: (\\d+)"), 1),
+ NUM_SLOW_DRAW(Pattern.compile("\\s*Number Slow draw: (\\d+)"), 1);
+
+ private boolean mSuccessfulParse = false;
+ private Pattern mParsePattern;
+ private int mGroupIndex;
+
+ JankStat(Pattern pattern, int groupIndex) {
+ mParsePattern = pattern;
+ mGroupIndex = groupIndex;
+ }
+
+ String parse(String line) {
+ String ret = null;
+ Matcher matcher = mParsePattern.matcher(line);
+ if (matcher.matches()) {
+ ret = matcher.group(mGroupIndex);
+ mSuccessfulParse = true;
+ }
+ return ret;
+ }
+
+ boolean wasParsedSuccessfully() {
+ return mSuccessfulParse;
+ }
+
+ void reset() {
+ mSuccessfulParse = false;
+ }
+ }
+
+ // Metrics accumulated for each iteration
+ private Map<JankStat, List<Integer>> mAccumulatedStats =
+ new EnumMap<JankStat, List<Integer>>(JankStat.class);
// Used to invoke dumpsys gfxinfo
private UiAutomation mUiAutomation;
private String mProcess;
- // Metrics accumulated for each iteration
- private List<Integer> jankyFrames = new ArrayList<Integer>();
- private List<Integer> missedVsync = new ArrayList<Integer>();
- private List<Integer> highInputLatency = new ArrayList<Integer>();
- private List<Integer> slowUiThread = new ArrayList<Integer>();
- private List<Integer> slowBitmapUploads = new ArrayList<Integer>();
- private List<Integer> slowDraw = new ArrayList<Integer>();
- private List<Integer> frameTime90thPercentile = new ArrayList<Integer>();
- private List<Integer> frameTime95thPercentile = new ArrayList<Integer>();
- private List<Integer> frameTime99thPercentile = new ArrayList<Integer>();
-
public GfxMonitorImpl(UiAutomation automation, String process) {
mUiAutomation = automation;
mProcess = process;
+
+ for (JankStat stat : JankStat.values()) {
+ mAccumulatedStats.put(stat, new ArrayList<Integer>());
+ }
}
@Override
@@ -96,6 +114,7 @@
}
}
+
@Override
public int stopIteration() throws IOException {
ParcelFileDescriptor stdout = mUiAutomation.executeShellCommand(
@@ -103,138 +122,91 @@
BufferedReader stream = new BufferedReader(new InputStreamReader(
new ParcelFileDescriptor.AutoCloseInputStream(stdout)));
- // Wait until we enter the frame stats section
+ // The frame stats section has the following output:
+ // Total frames rendered: ###
+ // Janky frames: ### (##.##%)
+ // 90th percentile: ##ms
+ // 95th percentile: ##ms
+ // 99th percentile: ##ms
+ // Number Missed Vsync: #
+ // Number High input latency: #
+ // Number Slow UI thread: #
+ // Number Slow bitmap uploads: #
+ // Number Slow draw: #
+
String line;
while ((line = stream.readLine()) != null) {
- if (line.startsWith("Frame stats:")) {
- break;
+
+ // Attempt to parse the line as a frame stat value
+ for (JankStat stat : JankStat.values()) {
+ String part;
+ if ((part = stat.parse(line)) != null) {
+ // Parse was successful. Add the numeric value to the accumulated list of values
+ // for that stat.
+ mAccumulatedStats.get(stat).add(Integer.parseInt(part));
+ break;
+ }
}
}
- Assert.assertTrue("Failed to locate frame stats in gfxinfo output",
- line != null && line.startsWith("Frame stats:"));
- // The frame stats section has the following output:
- // Frame stats:
- // Total frames rendered: ###
- // Janky frames: ### (##.##%)
- // 90th percentile: ##ms
- // 95th percentile: ##ms
- // 99th percentile: ##ms
- // Number Missed Vsync: #
- // Number High input latency: #
- // Number Slow UI thread: #
- // Number Slow bitmap uploads: #
- // Number Slow draw: #
-
- // Get Total Frames
- String part;
- if ((part = getMatchGroup(stream.readLine(), TOTAL_FRAMES_PATTERN, 1)) == null) {
- Assert.fail("Failed to parse total frames");
+ // Make sure we found all the stats
+ for (JankStat stat : JankStat.values()) {
+ if (!stat.wasParsedSuccessfully()) {
+ Assert.fail(String.format("Failed to parse %s", stat.name()));
+ }
+ stat.reset();
}
- int totalFrames = Integer.parseInt(part);
- // Get Num Janky
- if ((part = getMatchGroup(stream.readLine(), JANKY_FRAMES_PATTERN, 1)) == null) {
- Assert.fail("Failed to parse janky frames");
- }
- jankyFrames.add(Integer.parseInt(part));
+ List<Integer> totalFrames = mAccumulatedStats.get(JankStat.TOTAL_FRAMES);
+ return totalFrames.get(totalFrames.size()-1);
+ }
- // Get 90th percentile
- if ((part = getMatchGroup(stream.readLine(), FRAME_TIME_90TH_PERCENTILE_PATTERN, 1)) == null) {
- Assert.fail("Failed to parse 90th percentile");
- }
- frameTime90thPercentile.add(Integer.parseInt(part));
+ private void putAvgMax(Bundle metrics, String averageKey, String maxKey,
+ List<Integer> values) {
- // Get 95th percentile
- if ((part = getMatchGroup(stream.readLine(), FRAME_TIME_95TH_PERCENTILE_PATTERN, 1)) == null) {
- Assert.fail("Failed to parse 95th percentile");
- }
- frameTime95thPercentile.add(Integer.parseInt(part));
-
- // Get 99th percentile
- if ((part = getMatchGroup(stream.readLine(), FRAME_TIME_99TH_PERCENTILE_PATTERN, 1)) == null) {
- Assert.fail("Failed to parse 99th percentile");
- }
- frameTime99thPercentile.add(Integer.parseInt(part));
-
- // Get Missed Vsync
- if ((part = getMatchGroup(stream.readLine(), MISSED_VSYNC_PATTERN, 1)) == null) {
- Assert.fail("Failed to parse number missed vsync");
- }
- missedVsync.add(Integer.parseInt(part));
-
- // Get High input latency
- if ((part = getMatchGroup(stream.readLine(), INPUT_LATENCY_PATTERN, 1)) == null) {
- Assert.fail("Failed to parse number high input latency");
- }
- highInputLatency.add(Integer.parseInt(part));
-
- // Get Slow UI thread
- if ((part = getMatchGroup(stream.readLine(), SLOW_UI_PATTERN, 1)) == null) {
- Assert.fail("Failed to parse number slow ui thread");
- }
- slowUiThread.add(Integer.parseInt(part));
-
- // Get Slow bitmap uploads
- if ((part = getMatchGroup(stream.readLine(), SLOW_BITMAP_PATTERN, 1)) == null) {
- Assert.fail("Failed to parse number slow bitmap uploads");
- }
- slowBitmapUploads.add(Integer.parseInt(part));
-
- // Get Slow draw
- if ((part = getMatchGroup(stream.readLine(), SLOW_DRAW_PATTERN, 1)) == null) {
- Assert.fail("Failed to parse number slow draw");
- }
- slowDraw.add(Integer.parseInt(part));
-
- return totalFrames;
+ metrics.putDouble(averageKey, MetricsHelper.computeAverageInt(values));
+ metrics.putInt(maxKey, Collections.max(values));
}
public Bundle getMetrics() {
Bundle metrics = new Bundle();
// Store average and max jank
- metrics.putDouble(GfxMonitor.KEY_AVG_NUM_JANKY,
- MetricsHelper.computeAverageInt(jankyFrames));
- metrics.putInt(GfxMonitor.KEY_MAX_NUM_JANKY, Collections.max(jankyFrames));
+ putAvgMax(metrics, GfxMonitor.KEY_AVG_NUM_JANKY, GfxMonitor.KEY_MAX_NUM_JANKY,
+ mAccumulatedStats.get(JankStat.NUM_JANKY));
// Store average and max percentile frame times
- metrics.putDouble(GfxMonitor.KEY_AVG_FRAME_TIME_90TH_PERCENTILE,
- MetricsHelper.computeAverageInt(frameTime90thPercentile));
- metrics.putInt(GfxMonitor.KEY_MAX_FRAME_TIME_90TH_PERCENTILE,
- Collections.max(frameTime90thPercentile));
- metrics.putDouble(GfxMonitor.KEY_AVG_FRAME_TIME_95TH_PERCENTILE,
- MetricsHelper.computeAverageInt(frameTime95thPercentile));
- metrics.putInt(GfxMonitor.KEY_MAX_FRAME_TIME_95TH_PERCENTILE,
- Collections.max(frameTime95thPercentile));
- metrics.putDouble(GfxMonitor.KEY_AVG_FRAME_TIME_99TH_PERCENTILE,
- MetricsHelper.computeAverageInt(frameTime99thPercentile));
- metrics.putInt(GfxMonitor.KEY_MAX_FRAME_TIME_99TH_PERCENTILE,
- Collections.max(frameTime99thPercentile));
+ putAvgMax(metrics, GfxMonitor.KEY_AVG_FRAME_TIME_90TH_PERCENTILE,
+ GfxMonitor.KEY_MAX_FRAME_TIME_90TH_PERCENTILE,
+ mAccumulatedStats.get(JankStat.FRAME_TIME_90TH));
+ putAvgMax(metrics, GfxMonitor.KEY_AVG_FRAME_TIME_95TH_PERCENTILE,
+ GfxMonitor.KEY_MAX_FRAME_TIME_95TH_PERCENTILE,
+ mAccumulatedStats.get(JankStat.FRAME_TIME_95TH));
+ putAvgMax(metrics, GfxMonitor.KEY_AVG_FRAME_TIME_99TH_PERCENTILE,
+ GfxMonitor.KEY_MAX_FRAME_TIME_99TH_PERCENTILE,
+ mAccumulatedStats.get(JankStat.FRAME_TIME_99TH));
// Store average and max missed vsync
- metrics.putDouble(GfxMonitor.KEY_AVG_MISSED_VSYNC,
- MetricsHelper.computeAverageInt(missedVsync));
- metrics.putInt(GfxMonitor.KEY_MAX_MISSED_VSYNC, Collections.max(missedVsync));
+ putAvgMax(metrics, GfxMonitor.KEY_AVG_MISSED_VSYNC, GfxMonitor.KEY_MAX_MISSED_VSYNC,
+ mAccumulatedStats.get(JankStat.NUM_MISSED_VSYNC));
// Store average and max high input latency
- metrics.putDouble(GfxMonitor.KEY_AVG_HIGH_INPUT_LATENCY,
- MetricsHelper.computeAverageInt(highInputLatency));
- metrics.putInt(GfxMonitor.KEY_MAX_HIGH_INPUT_LATENCY, Collections.max(highInputLatency));
+ putAvgMax(metrics, GfxMonitor.KEY_AVG_HIGH_INPUT_LATENCY,
+ GfxMonitor.KEY_MAX_HIGH_INPUT_LATENCY,
+ mAccumulatedStats.get(JankStat.NUM_HIGH_INPUT_LATENCY));
// Store average and max slow ui thread
- metrics.putDouble(GfxMonitor.KEY_AVG_SLOW_UI_THREAD,
- MetricsHelper.computeAverageInt(slowUiThread));
- metrics.putInt(GfxMonitor.KEY_MAX_SLOW_UI_THREAD, Collections.max(slowUiThread));
+ putAvgMax(metrics, GfxMonitor.KEY_AVG_SLOW_UI_THREAD, GfxMonitor.KEY_MAX_SLOW_UI_THREAD,
+ mAccumulatedStats.get(JankStat.NUM_SLOW_UI_THREAD));
// Store average and max slow bitmap uploads
- metrics.putDouble(GfxMonitor.KEY_AVG_SLOW_BITMAP_UPLOADS,
- MetricsHelper.computeAverageInt(slowUiThread));
- metrics.putInt(GfxMonitor.KEY_MAX_SLOW_BITMAP_UPLOADS, Collections.max(slowUiThread));
+ putAvgMax(metrics, GfxMonitor.KEY_AVG_SLOW_BITMAP_UPLOADS,
+ GfxMonitor.KEY_MAX_SLOW_BITMAP_UPLOADS,
+ mAccumulatedStats.get(JankStat.NUM_SLOW_BITMAP_UPLOADS));
// Store average and max slow draw
- metrics.putDouble(GfxMonitor.KEY_AVG_SLOW_DRAW, MetricsHelper.computeAverageInt(slowDraw));
- metrics.putInt(GfxMonitor.KEY_MAX_SLOW_DRAW, Collections.max(slowDraw));
+ putAvgMax(metrics, GfxMonitor.KEY_AVG_SLOW_DRAW, GfxMonitor.KEY_MAX_SLOW_DRAW,
+ mAccumulatedStats.get(JankStat.NUM_SLOW_DRAW));
return metrics;
}