summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTetsui Ohkubo <tetsui@google.com>2015-10-12 23:59:31 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2015-10-12 23:59:31 +0000
commitff248ffa4d6ee63ab8c0e1f71b86a3d8ea3f4b25 (patch)
tree2245d3370d0d55242075070aae3b69221e1892e2
parent354ffd9aba4ebc8d57ec6e998944aaaff581d1e8 (diff)
parent32813990dcd93a84fa448acb160bf8f4a6897c1c (diff)
downloadloganalysis-ff248ffa4d6ee63ab8c0e1f71b86a3d8ea3f4b25.tar.gz
Merge "Add gfxinfo log collector to AUPT"
-rw-r--r--src/com/android/loganalysis/item/GfxInfoItem.java137
-rw-r--r--src/com/android/loganalysis/parser/GfxInfoParser.java92
-rw-r--r--tests/src/com/android/loganalysis/parser/GfxInfoParserTest.java350
3 files changed, 579 insertions, 0 deletions
diff --git a/src/com/android/loganalysis/item/GfxInfoItem.java b/src/com/android/loganalysis/item/GfxInfoItem.java
new file mode 100644
index 0000000..482cea3
--- /dev/null
+++ b/src/com/android/loganalysis/item/GfxInfoItem.java
@@ -0,0 +1,137 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+package com.android.loganalysis.item;
+
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+
+/**
+ * An {@link IItem} used to gfxinfo.
+ */
+public class GfxInfoItem implements IItem {
+ /** Constant for JSON output */
+ public static final String PROCESSES_KEY = "processes";
+ /** Constant for JSON output */
+ public static final String PID_KEY = "pid";
+ /** Constant for JSON output */
+ public static final String NAME_KEY = "name";
+ /** Constant for JSON output */
+ public static final String TOTAL_FRAMES_KEY = "total_frames";
+ /** Constant for JSON output */
+ public static final String JANKY_FRAMES_KEY = "janky_frames";
+
+ private Map<Integer, Row> mRows = new HashMap<Integer, Row>();
+
+ private static class Row {
+ public String name;
+ public long totalFrames;
+ public long jankyFrames;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public IItem merge(IItem other) throws ConflictingItemException {
+ throw new ConflictingItemException("GfxInfo items cannot be merged");
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean isConsistent(IItem other) {
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public JSONObject toJson() {
+ JSONObject object = new JSONObject();
+ JSONArray processes = new JSONArray();
+ for (int pid : getPids()) {
+ JSONObject proc = new JSONObject();
+ try {
+ proc.put(PID_KEY, pid);
+ proc.put(NAME_KEY, getName(pid));
+ proc.put(TOTAL_FRAMES_KEY, getTotalFrames(pid));
+ proc.put(JANKY_FRAMES_KEY, getJankyFrames(pid));
+ processes.put(proc);
+ } catch (JSONException e) {
+ // ignore
+ }
+ }
+
+ try {
+ object.put(PROCESSES_KEY, processes);
+ } catch (JSONException e) {
+ // ignore
+ }
+ return object;
+ }
+
+ /**
+ * Get a set of PIDs seen in the gfxinfo output.
+ */
+ public Set<Integer> getPids() {
+ return mRows.keySet();
+ }
+
+ /**
+ * Add a row from the gfxinfo output to the {@link GfxInfoItem}.
+ *
+ * @param pid The PID from the output
+ * @param name The process name
+ * @param totalFrames The number of total frames rendered by the process
+ * @param jankyFrames The number of janky frames rendered by the process
+ */
+ public void addRow(int pid, String name, long totalFrames, long jankyFrames) {
+ Row row = new Row();
+ row.name = name;
+ row.totalFrames = totalFrames;
+ row.jankyFrames = jankyFrames;
+ mRows.put(pid, row);
+ }
+
+ /**
+ * Get the process name for a given PID.
+ */
+ public String getName(int pid) {
+ return mRows.get(pid).name;
+ }
+
+ /**
+ * Get the number of total frames rendered by a given PID.
+ */
+ public long getTotalFrames(int pid) {
+ return mRows.get(pid).totalFrames;
+ }
+
+ /**
+ * Get the number of janky frames rendered by a given PID.
+ */
+ public long getJankyFrames(int pid) {
+ return mRows.get(pid).jankyFrames;
+ }
+}
diff --git a/src/com/android/loganalysis/parser/GfxInfoParser.java b/src/com/android/loganalysis/parser/GfxInfoParser.java
new file mode 100644
index 0000000..ef549d7
--- /dev/null
+++ b/src/com/android/loganalysis/parser/GfxInfoParser.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+package com.android.loganalysis.parser;
+
+import com.android.loganalysis.item.GfxInfoItem;
+
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * An {@link IParser} to handle the output of {@code gfxinfo}.
+ */
+public class GfxInfoParser implements IParser {
+
+ // Example: "** Graphics info for pid 853 [com.google.android.leanbacklauncher] **"
+ private static final Pattern PID_PREFIX = Pattern.compile(
+ "\\*\\* Graphics info for pid (\\d+) \\[(.+)\\] \\*\\*");
+
+ // Example: "Total frames rendered: 20391"
+ private static final Pattern TOTAL_FRAMES_PREFIX = Pattern.compile(
+ "Total frames rendered: (\\d+)");
+
+ // Example: "Janky frames: 785 (3.85%)"
+ private static final Pattern JANKY_FRAMES_PREFIX = Pattern.compile(
+ "Janky frames: (\\d+) \\(.+\\%\\)");
+
+ /**
+ * Parses the log of "dumpsys gfxinfo".
+ * Currently it only parses total frame number and total jank number per process.
+ * This method only works for M and later.
+ */
+ @Override
+ public GfxInfoItem parse(List<String> lines) {
+ GfxInfoItem item = new GfxInfoItem();
+
+ String name = null;
+ Integer pid = null;
+ Long totalFrames = null;
+ Long jankyFrames = null;
+
+ // gfxinfo also offers stats for specific views, but this parser
+ // only records per process data. See example in GfxInfoParserTest.java.
+
+ for (String line : lines) {
+ Matcher m = PID_PREFIX.matcher(line);
+ if (m.matches() && m.groupCount() == 2) {
+ // New process line, clear data.
+ pid = Integer.parseInt(m.group(1));
+ name = m.group(2);
+
+ totalFrames = null;
+ jankyFrames = null;
+ }
+
+ m = TOTAL_FRAMES_PREFIX.matcher(line);
+ if (totalFrames == null && m.matches()) {
+ totalFrames = Long.parseLong(m.group(1));
+ }
+
+ m = JANKY_FRAMES_PREFIX.matcher(line);
+ if (jankyFrames == null && m.matches()) {
+ jankyFrames = Long.parseLong(m.group(1));
+ }
+
+ if (name != null && pid != null && totalFrames != null && jankyFrames != null) {
+ // All the data for the process is recorded, add as a row.
+ item.addRow(pid, name, totalFrames, jankyFrames);
+
+ name = null;
+ pid = null;
+ totalFrames = null;
+ jankyFrames = null;
+ }
+ }
+
+ return item;
+ }
+}
diff --git a/tests/src/com/android/loganalysis/parser/GfxInfoParserTest.java b/tests/src/com/android/loganalysis/parser/GfxInfoParserTest.java
new file mode 100644
index 0000000..1ba7dce
--- /dev/null
+++ b/tests/src/com/android/loganalysis/parser/GfxInfoParserTest.java
@@ -0,0 +1,350 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+package com.android.loganalysis.parser;
+
+import com.android.loganalysis.item.GfxInfoItem;
+
+import junit.framework.TestCase;
+
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.util.Arrays;
+import java.util.List;
+
+public class GfxInfoParserTest extends TestCase {
+
+ /**
+ * Tests gfxinfo output from M with single process.
+ */
+ public void testSingleProcess() {
+ List<String> input = Arrays.asList(
+ "** Graphics info for pid 853 [com.google.android.leanbacklauncher] **",
+ "",
+ "Stats since: 13370233957ns",
+ "Total frames rendered: 20391",
+ "Janky frames: 785 (3.85%)",
+ "90th percentile: 9ms",
+ "95th percentile: 14ms",
+ "99th percentile: 32ms",
+ "Number Missed Vsync: 155",
+ "Number High input latency: 0",
+ "Number Slow UI thread: 469",
+ "Number Slow bitmap uploads: 65",
+ "Number Slow issue draw commands: 153",
+ "",
+ "Caches:",
+ "Current memory usage / total memory usage (bytes):",
+ " TextureCache 16055224 / 50331648",
+ " LayerCache 0 / 33554432 (numLayers = 0)",
+ " Layers total 0 (numLayers = 0)",
+ " RenderBufferCache 0 / 2097152",
+ " GradientCache 0 / 838860",
+ " PathCache 0 / 25165824",
+ " TessellationCache 1048296 / 1048576",
+ " TextDropShadowCache 0 / 4194304",
+ " PatchCache 0 / 131072",
+ " FontRenderer 0 A8 524288 / 524288",
+ " FontRenderer 0 RGBA 0 / 0",
+ " FontRenderer 0 total 524288 / 524288",
+ "Other:",
+ " FboCache 0 / 0",
+ "Total memory usage:",
+ " 17627808 bytes, 16.81 MB",
+ "",
+ "Profile data in ms:",
+ "",
+ "\tcom.google.android.leanbacklauncher/com.google.android.leanbacklauncher.MainActivity/android.view.ViewRootImpl@8dc465 (visibility=8)",
+ "Stats since: 13370233957ns",
+ "Total frames rendered: 20391",
+ "Janky frames: 785 (3.85%)",
+ "90th percentile: 9ms",
+ "95th percentile: 14ms",
+ "99th percentile: 32ms",
+ "Number Missed Vsync: 155",
+ "Number High input latency: 0",
+ "Number Slow UI thread: 469",
+ "Number Slow bitmap uploads: 65",
+ "Number Slow issue draw commands: 153",
+ "",
+ "View hierarchy:",
+ "",
+ " com.google.android.leanbacklauncher/com.google.android.leanbacklauncher.MainActivity/android.view.ViewRootImpl@8dc465",
+ " 220 views, 177.61 kB of display lists",
+ "",
+ "",
+ "Total ViewRootImpl: 1",
+ "Total Views: 220",
+ "Total DisplayList: 177.61 kB");
+
+ GfxInfoItem item = new GfxInfoParser().parse(input);
+
+ assertEquals(1, item.getPids().size());
+ assertEquals("com.google.android.leanbacklauncher", item.getName(853));
+ assertEquals(20391, item.getTotalFrames(853));
+ assertEquals(785, item.getJankyFrames(853));
+ }
+
+ /**
+ * Test gfxinfo output from M with multiple processes.
+ */
+ public void testMultipleProcesses() {
+ List<String> input = Arrays.asList(
+ "Applications Graphics Acceleration Info:",
+ "Uptime: 6127679 Realtime: 6127679",
+ "",
+ "** Graphics info for pid 844 [com.google.android.leanbacklauncher] **",
+ "",
+ "Stats since: 12167093145ns",
+ "Total frames rendered: 1690",
+ "Janky frames: 125 (7.40%)",
+ "90th percentile: 13ms",
+ "95th percentile: 19ms",
+ "99th percentile: 48ms",
+ "Number Missed Vsync: 17",
+ "Number High input latency: 0",
+ "Number Slow UI thread: 32",
+ "Number Slow bitmap uploads: 20",
+ "Number Slow issue draw commands: 67",
+ "",
+ "Caches:",
+ "Current memory usage / total memory usage (bytes):",
+ " TextureCache 16550096 / 50331648",
+ " LayerCache 0 / 33554432 (numLayers = 0)",
+ " Layers total 0 (numLayers = 0)",
+ " RenderBufferCache 0 / 2097152",
+ " GradientCache 0 / 838860",
+ " PathCache 0 / 25165824",
+ " TessellationCache 350424 / 1048576",
+ " TextDropShadowCache 0 / 4194304",
+ " PatchCache 0 / 131072",
+ " FontRenderer 0 A8 524288 / 524288",
+ " FontRenderer 0 RGBA 0 / 0",
+ " FontRenderer 0 total 524288 / 524288",
+ "Other:",
+ " FboCache 0 / 0",
+ "Total memory usage:",
+ " 17424808 bytes, 16.62 MB",
+ "",
+ "Profile data in ms:",
+ "",
+ "\tcom.google.android.leanbacklauncher/com.google.android.leanbacklauncher.MainActivity/android.view.ViewRootImpl@178d02b (visibility=0)",
+ "Stats since: 12167093145ns",
+ "Total frames rendered: 1690",
+ "Janky frames: 125 (7.40%)",
+ "90th percentile: 13ms",
+ "95th percentile: 19ms",
+ "99th percentile: 48ms",
+ "Number Missed Vsync: 17",
+ "Number High input latency: 0",
+ "Number Slow UI thread: 32",
+ "Number Slow bitmap uploads: 20",
+ "Number Slow issue draw commands: 67",
+ "",
+ "View hierarchy:",
+ "",
+ " com.google.android.leanbacklauncher/com.google.android.leanbacklauncher.MainActivity/android.view.ViewRootImpl@178d02b",
+ " 221 views, 207.24 kB of display lists",
+ "",
+ "",
+ "Total ViewRootImpl: 1",
+ "Total Views: 221",
+ "Total DisplayList: 207.24 kB",
+ "",
+ "",
+ "** Graphics info for pid 1881 [com.android.vending] **",
+ "",
+ "Stats since: 6092969986095ns",
+ "Total frames rendered: 693",
+ "Janky frames: 62 (8.95%)",
+ "90th percentile: 16ms",
+ "95th percentile: 26ms",
+ "99th percentile: 81ms",
+ "Number Missed Vsync: 17",
+ "Number High input latency: 0",
+ "Number Slow UI thread: 30",
+ "Number Slow bitmap uploads: 4",
+ "Number Slow issue draw commands: 13",
+ "",
+ "Caches:",
+ "Current memory usage / total memory usage (bytes):",
+ " TextureCache 7369504 / 50331648",
+ " LayerCache 0 / 33554432 (numLayers = 0)",
+ " Layers total 0 (numLayers = 0)",
+ " RenderBufferCache 0 / 2097152",
+ " GradientCache 0 / 838860",
+ " PathCache 0 / 25165824",
+ " TessellationCache 0 / 1048576",
+ " TextDropShadowCache 0 / 4194304",
+ " PatchCache 0 / 131072",
+ " FontRenderer 0 A8 524288 / 524288",
+ " FontRenderer 0 RGBA 0 / 0",
+ " FontRenderer 0 total 524288 / 524288",
+ "Other:",
+ " FboCache 0 / 0",
+ "Total memory usage:",
+ " 7893792 bytes, 7.53 MB",
+ "",
+ "Profile data in ms:",
+ "",
+ "\tcom.android.vending/com.google.android.finsky.activities.MainActivity/android.view.ViewRootImpl@5bd0cb2 (visibility=8)",
+ "Stats since: 6092969986095ns",
+ "Total frames rendered: 693",
+ "Janky frames: 62 (8.95%)",
+ "90th percentile: 16ms",
+ "95th percentile: 26ms",
+ "99th percentile: 81ms",
+ "Number Missed Vsync: 17",
+ "Number High input latency: 0",
+ "Number Slow UI thread: 30",
+ "Number Slow bitmap uploads: 4",
+ "Number Slow issue draw commands: 13",
+ "",
+ "View hierarchy:",
+ "",
+ " com.android.vending/com.google.android.finsky.activities.MainActivity/android.view.ViewRootImpl@5bd0cb2",
+ " 195 views, 157.71 kB of display lists",
+ "",
+ "",
+ "Total ViewRootImpl: 1",
+ "Total Views: 195",
+ "Total DisplayList: 157.71 kB",
+ "",
+ "",
+ "** Graphics info for pid 2931 [com.google.android.videos] **",
+ "",
+ "Stats since: 6039768250261ns",
+ "Total frames rendered: 107",
+ "Janky frames: 42 (39.25%)",
+ "90th percentile: 48ms",
+ "95th percentile: 65ms",
+ "99th percentile: 113ms",
+ "Number Missed Vsync: 9",
+ "Number High input latency: 0",
+ "Number Slow UI thread: 28",
+ "Number Slow bitmap uploads: 8",
+ "Number Slow issue draw commands: 20",
+ "",
+ "Caches:",
+ "Current memory usage / total memory usage (bytes):",
+ " TextureCache 7880000 / 50331648",
+ " LayerCache 0 / 33554432 (numLayers = 0)",
+ " Layers total 0 (numLayers = 0)",
+ " RenderBufferCache 0 / 2097152",
+ " GradientCache 0 / 838860",
+ " PathCache 0 / 25165824",
+ " TessellationCache 0 / 1048576",
+ " TextDropShadowCache 0 / 4194304",
+ " PatchCache 0 / 131072",
+ " FontRenderer 0 A8 524288 / 524288",
+ " FontRenderer 0 RGBA 0 / 0",
+ " FontRenderer 0 total 524288 / 524288",
+ "Other:",
+ " FboCache 0 / 0",
+ "Total memory usage:",
+ " 8404288 bytes, 8.01 MB",
+ "",
+ "Profile data in ms:",
+ "",
+ "\tcom.google.android.videos/com.google.android.videos.pano.activity.PanoHomeActivity/android.view.ViewRootImpl@3d96e69 (visibility=8)",
+ "Stats since: 6039768250261ns",
+ "Total frames rendered: 107",
+ "Janky frames: 42 (39.25%)",
+ "90th percentile: 48ms",
+ "95th percentile: 65ms",
+ "99th percentile: 113ms",
+ "Number Missed Vsync: 9",
+ "Number High input latency: 0",
+ "Number Slow UI thread: 28",
+ "Number Slow bitmap uploads: 8",
+ "Number Slow issue draw commands: 20",
+ "",
+ "View hierarchy:",
+ "",
+ " com.google.android.videos/com.google.android.videos.pano.activity.PanoHomeActivity/android.view.ViewRootImpl@3d96e69",
+ " 219 views, 173.57 kB of display lists",
+ "",
+ "",
+ "Total ViewRootImpl: 1",
+ "Total Views: 219",
+ "Total DisplayList: 173.57 kB");
+
+ GfxInfoItem item = new GfxInfoParser().parse(input);
+
+ assertEquals(3, item.getPids().size());
+ assertEquals("com.google.android.leanbacklauncher", item.getName(844));
+ assertEquals(1690, item.getTotalFrames(844));
+ assertEquals(125, item.getJankyFrames(844));
+ assertEquals("com.android.vending", item.getName(1881));
+ assertEquals(693, item.getTotalFrames(1881));
+ assertEquals(62, item.getJankyFrames(1881));
+ assertEquals("com.google.android.videos", item.getName(2931));
+ assertEquals(107, item.getTotalFrames(2931));
+ assertEquals(42, item.getJankyFrames(2931));
+ }
+
+ /**
+ * Test gfxinfo output from L with single process.
+ * In L, gfxinfo does not contain Jank number information.
+ * This method tests that GfxInfoParser silently ignores such outputs.
+ */
+ public void testSingleProcessInL() {
+ List<String> input = Arrays.asList(
+ "** Graphics info for pid 1924 [com.google.android.leanbacklauncher] **",
+ "",
+ "Caches:",
+ "Current memory usage / total memory usage (bytes):",
+ " TextureCache 19521592 / 50331648",
+ " LayerCache 14745600 / 50331648 (numLayers = 5)",
+ " Layer size 512x512; isTextureLayer()=0; texid=392 fbo=0; refs=1",
+ " Layer size 512x448; isTextureLayer()=0; texid=377 fbo=0; refs=1",
+ " Layer size 1920x832; isTextureLayer()=0; texid=360 fbo=0; refs=1",
+ " Layer size 1920x512; isTextureLayer()=0; texid=14 fbo=0; refs=1",
+ " Layer size 1920x320; isTextureLayer()=0; texid=393 fbo=0; refs=1",
+ " Layers total 14745600 (numLayers = 5)",
+ " RenderBufferCache 0 / 8388608",
+ " GradientCache 0 / 1048576",
+ " PathCache 3370264 / 33554432",
+ " TessellationCache 194928 / 1048576",
+ " TextDropShadowCache 0 / 6291456",
+ " PatchCache 0 / 131072",
+ " FontRenderer 0 A8 1048576 / 1048576",
+ " FontRenderer 0 RGBA 0 / 0",
+ " FontRenderer 0 total 1048576 / 1048576",
+ "Other:",
+ " FboCache 0 / 0",
+ "Total memory usage:",
+ " 38880960 bytes, 37.08 MB",
+ "",
+ "Profile data in ms:",
+ "",
+ "\tcom.google.android.leanbacklauncher/com.google.android.leanbacklauncher.MainActivity/android.view.ViewRootImpl@355a7923 (visibility=0)",
+ "View hierarchy:",
+ "",
+ " com.google.android.leanbacklauncher/com.google.android.leanbacklauncher.MainActivity/android.view.ViewRootImpl@355a7923",
+ " 142 views, 136.96 kB of display lists",
+ "",
+ "",
+ "Total ViewRootImpl: 1",
+ "Total Views: 142",
+ "Total DisplayList: 136.96 kB");
+
+ GfxInfoItem item = new GfxInfoParser().parse(input);
+
+ assertEquals(0, item.getPids().size());
+ }
+}