Add new ViewDebug APIs to profile the event queue.
Change-Id: I225bf288780b0244f459316e2765cfa29cd22c89
diff --git a/core/java/android/os/Looper.java b/core/java/android/os/Looper.java
index c0be664..720e802b 100644
--- a/core/java/android/os/Looper.java
+++ b/core/java/android/os/Looper.java
@@ -52,7 +52,6 @@
*/
public class Looper {
private static final String TAG = "Looper";
- private static final boolean LOG_V = Log.isLoggable(TAG, Log.VERBOSE);
// sThreadLocal.get() will return null unless you've called prepare().
private static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
@@ -70,7 +69,7 @@
* {@link #loop()} after calling this method, and end it by calling
* {@link #quit()}.
*/
- public static final void prepare() {
+ public static void prepare() {
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
@@ -83,7 +82,7 @@
* is created by the Android environment, so you should never need
* to call this function yourself. See also: {@link #prepare()}
*/
- public static final void prepareMainLooper() {
+ public static void prepareMainLooper() {
prepare();
setMainLooper(myLooper());
myLooper().mQueue.mQuitAllowed = false;
@@ -95,7 +94,7 @@
/** Returns the application's main looper, which lives in the main thread of the application.
*/
- public synchronized static final Looper getMainLooper() {
+ public synchronized static Looper getMainLooper() {
return mMainLooper;
}
@@ -103,7 +102,7 @@
* Run the message queue in this thread. Be sure to call
* {@link #quit()} to end the loop.
*/
- public static final void loop() {
+ public static void loop() {
Looper me = myLooper();
if (me == null) {
throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
@@ -122,20 +121,36 @@
// No target is a magic identifier for the quit message.
return;
}
- if (me.mLogging != null) me.mLogging.println(
- ">>>>> Dispatching to " + msg.target + " "
- + msg.callback + ": " + msg.what
- );
+
+ long wallStart = 0;
+ long threadStart = 0;
+
+ // This must be in a local variable, in case a UI event sets the logger
+ Printer logging = me.mLogging;
+ if (logging != null) {
+ logging.println(">>>>> Dispatching to " + msg.target + " " +
+ msg.callback + ": " + msg.what);
+ wallStart = System.currentTimeMillis();
+ threadStart = SystemClock.currentThreadTimeMillis();
+ }
+
msg.target.dispatchMessage(msg);
- if (me.mLogging != null) me.mLogging.println(
- "<<<<< Finished to " + msg.target + " "
- + msg.callback);
-
+
+ if (logging != null) {
+ long wallTime = System.currentTimeMillis() - wallStart;
+ long threadTime = SystemClock.currentThreadTimeMillis() - threadStart;
+
+ logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);
+ if (logging instanceof Profiler) {
+ ((Profiler) logging).profile(msg, wallStart, wallTime, threadTime);
+ }
+ }
+
// Make sure that during the course of dispatching the
// identity of the thread wasn't corrupted.
final long newIdent = Binder.clearCallingIdentity();
if (ident != newIdent) {
- Log.wtf("Looper", "Thread identity changed from 0x"
+ Log.wtf(TAG, "Thread identity changed from 0x"
+ Long.toHexString(ident) + " to 0x"
+ Long.toHexString(newIdent) + " while dispatching to "
+ msg.target.getClass().getName() + " "
@@ -151,7 +166,7 @@
* Return the Looper object associated with the current thread. Returns
* null if the calling thread is not associated with a Looper.
*/
- public static final Looper myLooper() {
+ public static Looper myLooper() {
return sThreadLocal.get();
}
@@ -173,7 +188,7 @@
* thread. This must be called from a thread running a Looper, or a
* NullPointerException will be thrown.
*/
- public static final MessageQueue myQueue() {
+ public static MessageQueue myQueue() {
return myLooper().mQueue;
}
@@ -225,23 +240,13 @@
}
public String toString() {
- return "Looper{"
- + Integer.toHexString(System.identityHashCode(this))
- + "}";
+ return "Looper{" + Integer.toHexString(System.identityHashCode(this)) + "}";
}
- static class HandlerException extends Exception {
-
- HandlerException(Message message, Throwable cause) {
- super(createMessage(cause), cause);
- }
-
- static String createMessage(Throwable cause) {
- String causeMsg = cause.getMessage();
- if (causeMsg == null) {
- causeMsg = cause.toString();
- }
- return causeMsg;
- }
+ /**
+ * @hide
+ */
+ public static interface Profiler {
+ void profile(Message message, long wallStart, long wallTime, long threadTime);
}
}