diff options
| author | Romain Guy <romainguy@google.com> | 2011-07-13 18:46:21 -0700 |
|---|---|---|
| committer | Romain Guy <romainguy@google.com> | 2011-07-15 11:25:11 -0700 |
| commit | f9284695e8c10dad4daf3d2c84f607483bcb56ca (patch) | |
| tree | bb4d52d7d3f6d9b73c8ba23d55036d3f4cd1ba31 /core/java/android/view/ViewDebug.java | |
| parent | fed878d98bc42db61cf04d759235b8406a7d14fd (diff) | |
Add new ViewDebug APIs to profile the event queue.
Change-Id: I225bf288780b0244f459316e2765cfa29cd22c89
Diffstat (limited to 'core/java/android/view/ViewDebug.java')
| -rw-r--r-- | core/java/android/view/ViewDebug.java | 168 |
1 files changed, 143 insertions, 25 deletions
diff --git a/core/java/android/view/ViewDebug.java b/core/java/android/view/ViewDebug.java index f014070d2b9d..f7f5a21399dd 100644 --- a/core/java/android/view/ViewDebug.java +++ b/core/java/android/view/ViewDebug.java @@ -16,41 +16,45 @@ package android.view; -import android.util.Log; -import android.util.DisplayMetrics; -import android.content.res.Resources; import android.content.Context; +import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Rect; -import android.os.Environment; import android.os.Debug; +import android.os.Environment; +import android.os.Looper; +import android.os.Message; import android.os.RemoteException; +import android.util.DisplayMetrics; +import android.util.Log; +import android.util.Printer; +import java.io.BufferedOutputStream; +import java.io.BufferedWriter; import java.io.ByteArrayOutputStream; +import java.io.DataOutputStream; import java.io.File; -import java.io.BufferedWriter; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; import java.io.FileWriter; import java.io.IOException; -import java.io.FileOutputStream; -import java.io.DataOutputStream; -import java.io.OutputStreamWriter; -import java.io.BufferedOutputStream; import java.io.OutputStream; -import java.util.List; -import java.util.LinkedList; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; -import java.lang.annotation.Target; +import java.io.OutputStreamWriter; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import java.lang.reflect.AccessibleObject; import java.lang.reflect.Field; -import java.lang.reflect.Method; import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.AccessibleObject; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; /** * Various debugging/tracing tools related to {@link View} and the view hierarchy. @@ -106,13 +110,6 @@ public class ViewDebug { public static final boolean DEBUG_PROFILE_LAYOUT = false; /** - * Profiles real fps (times between draws) and displays the result. - * - * @hide - */ - public static final boolean DEBUG_SHOW_FPS = false; - - /** * Enables detailed logging of drag/drop operations. * @hide */ @@ -396,6 +393,9 @@ public class ViewDebug { private static List<RecyclerTrace> sRecyclerTraces; private static String sRecyclerTracePrefix; + private static final ThreadLocal<LooperProfiler> sLooperProfilerStorage = + new ThreadLocal<LooperProfiler>(); + /** * Returns the number of instanciated Views. * @@ -419,6 +419,124 @@ public class ViewDebug { } /** + * Starts profiling the looper associated with the current thread. + * You must call {@link #stopLooperProfiling} to end profiling + * and obtain the traces. Both methods must be invoked on the + * same thread. + * + * @param traceFile The path where to write the looper traces + * + * @see #stopLooperProfiling() + */ + public static void startLooperProfiling(File traceFile) { + if (sLooperProfilerStorage.get() == null) { + LooperProfiler profiler = new LooperProfiler(traceFile); + sLooperProfilerStorage.set(profiler); + Looper.myLooper().setMessageLogging(profiler); + } + } + + /** + * Stops profiling the looper associated with the current thread. + * + * @see #startLooperProfiling(java.io.File) + */ + public static void stopLooperProfiling() { + LooperProfiler profiler = sLooperProfilerStorage.get(); + if (profiler != null) { + sLooperProfilerStorage.remove(); + Looper.myLooper().setMessageLogging(null); + profiler.save(); + } + } + + private static class LooperProfiler implements Looper.Profiler, Printer { + private static final int LOOPER_PROFILER_VERSION = 1; + + private static final String LOG_TAG = "LooperProfiler"; + + private final ArrayList<Entry> mTraces = new ArrayList<Entry>(512); + private final File mTraceFile; + + public LooperProfiler(File traceFile) { + mTraceFile = traceFile; + } + + @Override + public void println(String x) { + // Ignore messages + } + + @Override + public void profile(Message message, long wallStart, long wallTime, long threadTime) { + Entry entry = new Entry(); + entry.messageId = message.what; + entry.name = message.getTarget().getMessageName(message); + entry.wallStart = wallStart; + entry.wallTime = wallTime; + entry.threadTime = threadTime; + + mTraces.add(entry); + } + + void save() { + // Don't block the UI thread + new Thread(new Runnable() { + @Override + public void run() { + saveTraces(); + } + }, "LooperProfiler[" + mTraceFile + "]").start(); + } + + private void saveTraces() { + FileOutputStream fos; + try { + fos = new FileOutputStream(mTraceFile); + } catch (FileNotFoundException e) { + Log.e(LOG_TAG, "Could not open trace file: " + mTraceFile); + return; + } + + DataOutputStream out = new DataOutputStream(new BufferedOutputStream(fos)); + + try { + out.writeInt(LOOPER_PROFILER_VERSION); + out.writeInt(mTraces.size()); + for (Entry entry : mTraces) { + saveTrace(entry, out); + } + + Log.d(LOG_TAG, "Looper traces ready: " + mTraceFile); + } catch (IOException e) { + Log.e(LOG_TAG, "Could not write trace file: ", e); + } finally { + try { + out.close(); + } catch (IOException e) { + // Ignore + } + } + } + + private void saveTrace(Entry entry, DataOutputStream out) throws IOException { + out.writeInt(entry.messageId); + out.writeUTF(entry.name); + out.writeLong(entry.wallStart); + out.writeLong(entry.wallTime); + out.writeLong(entry.threadTime); + } + + static class Entry { + int messageId; + String name; + long wallStart; + long wallTime; + long threadTime; + } + } + + /** * Outputs a trace to the currently opened recycler traces. The trace records the type of * recycler action performed on the supplied view as well as a number of parameters. * |
