summaryrefslogtreecommitdiffstats
path: root/core/java
diff options
context:
space:
mode:
authorRomain Guy <romainguy@google.com>2012-02-13 17:47:10 -0800
committerRomain Guy <romainguy@google.com>2012-02-13 17:47:10 -0800
commita676ad7e34c9afbaafaeca8c3fe96e95c518828e (patch)
tree4a48c68a0359e4c6776761b55fc5f2e51317a68d /core/java
parent75400e775e7f291720aa43fbe6bf2b4ab41265b1 (diff)
downloadframeworks_base-a676ad7e34c9afbaafaeca8c3fe96e95c518828e.zip
frameworks_base-a676ad7e34c9afbaafaeca8c3fe96e95c518828e.tar.gz
frameworks_base-a676ad7e34c9afbaafaeca8c3fe96e95c518828e.tar.bz2
New debugging tool in adb shell dumpsys gfxinfo
This tool lets you visualize the time it took, in ms, to: - Build display lists ("Draw" phase) - Process display lists ("Process" phase) - Swap GL buffers ("Execute" phase) To use this tool: - adb shell setprop hwui.profile true - adb shell dumpsys gfxinfo <process name> - Copy the profile data and paste it in a spreadsheet - Generate a graph (stacked graph) and enjoy Change-Id: I7840c0ea0f153550425aa798e3ada2f357688cf5
Diffstat (limited to 'core/java')
-rw-r--r--core/java/android/view/HardwareRenderer.java124
-rw-r--r--core/java/android/view/WindowManagerImpl.java14
2 files changed, 116 insertions, 22 deletions
diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java
index 9e8a228..1932c7f 100644
--- a/core/java/android/view/HardwareRenderer.java
+++ b/core/java/android/view/HardwareRenderer.java
@@ -39,6 +39,7 @@ import javax.microedition.khronos.egl.EGLSurface;
import javax.microedition.khronos.opengles.GL;
import java.io.File;
+import java.io.PrintWriter;
import static javax.microedition.khronos.egl.EGL10.*;
@@ -84,13 +85,27 @@ public abstract class HardwareRenderer {
static final String DISABLE_VSYNC_PROPERTY = "hwui.disable_vsync";
/**
+ * System property used to enable or disable hardware rendering profiling.
+ * The default value of this property is assumed to be false.
+ *
+ * When profiling is enabled, the adb shell dumpsys gfxinfo command will
+ * output extra information about the time taken to execute by the last
+ * frames.
+ *
+ * Possible values:
+ * "true", to enable profiling
+ * "false", to disable profiling
+ */
+ static final String PROFILE_PROPERTY = "hwui.profile";
+
+ /**
* System property used to debug EGL configuration choice.
*
* Possible values:
* "choice", print the chosen configuration only
* "all", print all possible configurations
*/
- static final String PRINT_CONFIG_PROPERTY = "hwui.print_config";
+ static final String PRINT_CONFIG_PROPERTY = "hwui.print_config";
/**
* Turn on to draw dirty regions every other frame.
@@ -112,6 +127,16 @@ public abstract class HardwareRenderer {
*/
public static boolean sSystemRendererDisabled = false;
+ /**
+ * Number of frames to profile.
+ */
+ private static final int PROFILE_MAX_FRAMES = 64;
+
+ /**
+ * Number of floats per profiled frame.
+ */
+ private static final int PROFILE_FRAME_DATA_COUNT = 3;
+
private boolean mEnabled;
private boolean mRequested = true;
@@ -226,6 +251,12 @@ public abstract class HardwareRenderer {
abstract HardwareCanvas getCanvas();
/**
+ * Outputs extra debugging information in the specified file descriptor.
+ * @param pw
+ */
+ abstract void dumpGfxInfo(PrintWriter pw);
+
+ /**
* Sets the directory to use as a persistent storage for hardware rendering
* resources.
*
@@ -439,6 +470,7 @@ public abstract class HardwareRenderer {
GL mGl;
HardwareCanvas mCanvas;
+
int mFrameCount;
Paint mDebugPaint;
@@ -456,6 +488,10 @@ public abstract class HardwareRenderer {
final boolean mVsyncDisabled;
+ final boolean mProfileEnabled;
+ final float[] mProfileData;
+ int mProfileCurrentFrame = -PROFILE_FRAME_DATA_COUNT;
+
final int mGlVersion;
final boolean mTranslucent;
@@ -472,6 +508,34 @@ public abstract class HardwareRenderer {
if (mVsyncDisabled) {
Log.d(LOG_TAG, "Disabling v-sync");
}
+
+ //noinspection PointlessBooleanExpression,ConstantConditions
+ if (!ViewDebug.DEBUG_LATENCY) {
+ final String profileProperty = SystemProperties.get(PROFILE_PROPERTY, "false");
+ mProfileEnabled = "true".equalsIgnoreCase(profileProperty);
+ if (mProfileEnabled) {
+ Log.d(LOG_TAG, "Profiling hardware renderer");
+ }
+ } else {
+ mProfileEnabled = true;
+ }
+
+ if (mProfileEnabled) {
+ mProfileData = new float[PROFILE_MAX_FRAMES * PROFILE_FRAME_DATA_COUNT];
+ } else {
+ mProfileData = null;
+ }
+ }
+
+ @Override
+ void dumpGfxInfo(PrintWriter pw) {
+ if (mProfileEnabled) {
+ pw.printf("\n\tDraw\tProcess\tExecute\n");
+ for (int i = 0; i < mProfileData.length; i += PROFILE_FRAME_DATA_COUNT) {
+ pw.printf("\t%3.2f\t%3.2f\t%3.2f\n", mProfileData[i], mProfileData[i + 1],
+ mProfileData[i + 2]);
+ }
+ }
}
/**
@@ -860,34 +924,49 @@ public abstract class HardwareRenderer {
(view.mPrivateFlags & View.INVALIDATED) == View.INVALIDATED;
view.mPrivateFlags &= ~View.INVALIDATED;
- final long getDisplayListStartTime;
- if (ViewDebug.DEBUG_LATENCY) {
+ long getDisplayListStartTime = 0;
+ if (mProfileEnabled) {
+ mProfileCurrentFrame += PROFILE_FRAME_DATA_COUNT;
+ if (mProfileCurrentFrame >= mProfileData.length) {
+ mProfileCurrentFrame = 0;
+ }
+
getDisplayListStartTime = System.nanoTime();
}
DisplayList displayList = view.getDisplayList();
- if (ViewDebug.DEBUG_LATENCY) {
+ if (mProfileEnabled) {
long now = System.nanoTime();
- Log.d(ViewDebug.DEBUG_LATENCY_TAG, "- getDisplayList() took "
- + ((now - getDisplayListStartTime) * 0.000001f) + "ms");
+ float total = (now - getDisplayListStartTime) * 0.000001f;
+ //noinspection PointlessArithmeticExpression
+ mProfileData[mProfileCurrentFrame] = total;
+
+ if (ViewDebug.DEBUG_LATENCY) {
+ Log.d(ViewDebug.DEBUG_LATENCY_TAG, "- getDisplayList() took " +
+ total + "ms");
+ }
}
if (displayList != null) {
- final long drawDisplayListStartTime;
- if (ViewDebug.DEBUG_LATENCY) {
+ long drawDisplayListStartTime = 0;
+ if (mProfileEnabled) {
drawDisplayListStartTime = System.nanoTime();
}
- boolean invalidateNeeded = canvas.drawDisplayList(
- displayList, view.getWidth(),
- view.getHeight(), mRedrawClip);
+ boolean invalidateNeeded = canvas.drawDisplayList(displayList,
+ view.getWidth(), view.getHeight(), mRedrawClip);
- if (ViewDebug.DEBUG_LATENCY) {
+ if (mProfileEnabled) {
long now = System.nanoTime();
- Log.d(ViewDebug.DEBUG_LATENCY_TAG, "- drawDisplayList() took "
- + ((now - drawDisplayListStartTime) * 0.000001f)
- + "ms, invalidateNeeded=" + invalidateNeeded + ".");
+ float total = (now - drawDisplayListStartTime) * 0.000001f;
+ mProfileData[mProfileCurrentFrame + 1] = total;
+
+ if (ViewDebug.DEBUG_LATENCY) {
+ Log.d(ViewDebug.DEBUG_LATENCY_TAG, "- drawDisplayList() took " +
+ total + "ms, invalidateNeeded=" +
+ invalidateNeeded + ".");
+ }
}
if (invalidateNeeded) {
@@ -922,17 +1001,22 @@ public abstract class HardwareRenderer {
attachInfo.mIgnoreDirtyState = false;
- final long eglSwapBuffersStartTime;
- if (ViewDebug.DEBUG_LATENCY) {
+ long eglSwapBuffersStartTime = 0;
+ if (mProfileEnabled) {
eglSwapBuffersStartTime = System.nanoTime();
}
sEgl.eglSwapBuffers(sEglDisplay, mEglSurface);
- if (ViewDebug.DEBUG_LATENCY) {
+ if (mProfileEnabled) {
long now = System.nanoTime();
- Log.d(ViewDebug.DEBUG_LATENCY_TAG, "- eglSwapBuffers() took "
- + ((now - eglSwapBuffersStartTime) * 0.000001f) + "ms");
+ float total = (now - eglSwapBuffersStartTime) * 0.000001f;
+ mProfileData[mProfileCurrentFrame + 2] = total;
+
+ if (ViewDebug.DEBUG_LATENCY) {
+ Log.d(ViewDebug.DEBUG_LATENCY_TAG, "- eglSwapBuffers() took " +
+ total + "ms");
+ }
}
checkEglErrors();
diff --git a/core/java/android/view/WindowManagerImpl.java b/core/java/android/view/WindowManagerImpl.java
index 6bdc4e8..6dbdedb 100644
--- a/core/java/android/view/WindowManagerImpl.java
+++ b/core/java/android/view/WindowManagerImpl.java
@@ -480,9 +480,19 @@ public class WindowManagerImpl implements WindowManager {
try {
synchronized (this) {
if (mViews != null) {
- pw.println("View hierarchy:");
-
final int count = mViews.length;
+
+ pw.println("Profile data in ms:");
+
+ for (int i = 0; i < count; i++) {
+ ViewRootImpl root = mRoots[i];
+ HardwareRenderer renderer = root.getView().mAttachInfo.mHardwareRenderer;
+ if (renderer != null) {
+ renderer.dumpGfxInfo(pw);
+ }
+ }
+
+ pw.println("\nView hierarchy:");
int viewsCount = 0;
int displayListsSize = 0;