Log view root, input and looper state in bug reports.
Bug: 10948648
Change-Id: I956cce2a0fb516c02f9bbbc021f6238bcb226891
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index e29f8ea..193724d 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -58,6 +58,7 @@
import android.util.AttributeSet;
import android.util.EventLog;
import android.util.Log;
+import android.util.PrintWriterPrinter;
import android.util.Slog;
import android.util.SparseArray;
import android.view.ActionMode;
@@ -4846,36 +4847,19 @@
writer.println(mChangingConfigurations);
writer.print(innerPrefix); writer.print("mCurrentConfig=");
writer.println(mCurrentConfig);
+
if (mLoaderManager != null) {
writer.print(prefix); writer.print("Loader Manager ");
writer.print(Integer.toHexString(System.identityHashCode(mLoaderManager)));
writer.println(":");
mLoaderManager.dump(prefix + " ", fd, writer, args);
}
- mFragments.dump(prefix, fd, writer, args);
- writer.print(prefix); writer.println("View Hierarchy:");
- dumpViewHierarchy(prefix + " ", writer, getWindow().getDecorView());
- }
- private void dumpViewHierarchy(String prefix, PrintWriter writer, View view) {
- writer.print(prefix);
- if (view == null) {
- writer.println("null");
- return;
- }
- writer.println(view.toString());
- if (!(view instanceof ViewGroup)) {
- return;
- }
- ViewGroup grp = (ViewGroup)view;
- final int N = grp.getChildCount();
- if (N <= 0) {
- return;
- }
- prefix = prefix + " ";
- for (int i=0; i<N; i++) {
- dumpViewHierarchy(prefix, writer, grp.getChildAt(i));
- }
+ mFragments.dump(prefix, fd, writer, args);
+
+ getWindow().getDecorView().getViewRootImpl().dump(prefix, fd, writer, args);
+
+ mHandler.getLooper().dump(new PrintWriterPrinter(writer), prefix);
}
/**
diff --git a/core/java/android/os/Looper.java b/core/java/android/os/Looper.java
index 78c859e..21e9f6b 100644
--- a/core/java/android/os/Looper.java
+++ b/core/java/android/os/Looper.java
@@ -59,7 +59,6 @@
final MessageQueue mQueue;
final Thread mThread;
- volatile boolean mRun;
private Printer mLogging;
@@ -187,7 +186,6 @@
private Looper(boolean quitAllowed) {
mQueue = new MessageQueue(quitAllowed);
- mRun = true;
mThread = Thread.currentThread();
}
@@ -300,27 +298,12 @@
}
public void dump(Printer pw, String prefix) {
- pw = PrefixPrinter.create(pw, prefix);
- pw.println(this.toString());
- pw.println("mRun=" + mRun);
- pw.println("mThread=" + mThread);
- pw.println("mQueue=" + ((mQueue != null) ? mQueue : "(null"));
- if (mQueue != null) {
- synchronized (mQueue) {
- long now = SystemClock.uptimeMillis();
- Message msg = mQueue.mMessages;
- int n = 0;
- while (msg != null) {
- pw.println(" Message " + n + ": " + msg.toString(now));
- n++;
- msg = msg.next;
- }
- pw.println("(Total messages: " + n + ")");
- }
- }
+ pw.println(prefix + toString());
+ mQueue.dump(pw, prefix + " ");
}
public String toString() {
- return "Looper{" + Integer.toHexString(System.identityHashCode(this)) + "}";
+ return "Looper (" + mThread.getName() + ", tid " + mThread.getId()
+ + ") {" + Integer.toHexString(System.identityHashCode(this)) + "}";
}
}
diff --git a/core/java/android/os/Message.java b/core/java/android/os/Message.java
index 0abc149..51203a48 100644
--- a/core/java/android/os/Message.java
+++ b/core/java/android/os/Message.java
@@ -428,36 +428,48 @@
public Message() {
}
+ @Override
public String toString() {
return toString(SystemClock.uptimeMillis());
}
String toString(long now) {
- StringBuilder b = new StringBuilder();
-
- b.append("{ what=");
- b.append(what);
+ StringBuilder b = new StringBuilder();
+ b.append("{ when=");
+ TimeUtils.formatDuration(when - now, b);
- b.append(" when=");
- TimeUtils.formatDuration(when-now, b);
+ if (target != null) {
+ if (callback != null) {
+ b.append(" callback=");
+ b.append(callback.getClass().getName());
+ } else {
+ b.append(" what=");
+ b.append(what);
+ }
- if (arg1 != 0) {
- b.append(" arg1=");
+ if (arg1 != 0) {
+ b.append(" arg1=");
+ b.append(arg1);
+ }
+
+ if (arg2 != 0) {
+ b.append(" arg2=");
+ b.append(arg2);
+ }
+
+ if (obj != null) {
+ b.append(" obj=");
+ b.append(obj);
+ }
+
+ b.append(" target=");
+ b.append(target.getClass().getName());
+ } else {
+ b.append(" barrier=");
b.append(arg1);
}
- if (arg2 != 0) {
- b.append(" arg2=");
- b.append(arg2);
- }
-
- if (obj != null) {
- b.append(" obj=");
- b.append(obj);
- }
-
b.append(" }");
-
return b.toString();
}
diff --git a/core/java/android/os/MessageQueue.java b/core/java/android/os/MessageQueue.java
index d1b8213..799de5c 100644
--- a/core/java/android/os/MessageQueue.java
+++ b/core/java/android/os/MessageQueue.java
@@ -18,6 +18,7 @@
import android.util.AndroidRuntimeException;
import android.util.Log;
+import android.util.Printer;
import java.util.ArrayList;
@@ -252,6 +253,7 @@
synchronized (this) {
final int token = mNextBarrierToken++;
final Message msg = Message.obtain();
+ msg.when = when;
msg.arg1 = token;
Message prev = null;
@@ -393,12 +395,16 @@
boolean isIdling() {
synchronized (this) {
- // If the loop is quitting then it must not be idling.
- // We can assume mPtr != 0 when mQuitting is false.
- return !mQuitting && nativeIsIdling(mPtr);
+ return isIdlingLocked();
}
}
+ private boolean isIdlingLocked() {
+ // If the loop is quitting then it must not be idling.
+ // We can assume mPtr != 0 when mQuitting is false.
+ return !mQuitting && nativeIsIdling(mPtr);
+ }
+
void removeMessages(Handler h, int what, Object object) {
if (h == null) {
return;
@@ -537,4 +543,17 @@
}
}
}
+
+ void dump(Printer pw, String prefix) {
+ synchronized (this) {
+ long now = SystemClock.uptimeMillis();
+ int n = 0;
+ for (Message msg = mMessages; msg != null; msg = msg.next) {
+ pw.println(prefix + "Message " + n + ": " + msg.toString(now));
+ n++;
+ }
+ pw.println(prefix + "(Total messages: " + n + ", idling=" + isIdlingLocked()
+ + ", quitting=" + mQuitting + ")");
+ }
+ }
}
diff --git a/core/java/android/view/Choreographer.java b/core/java/android/view/Choreographer.java
index f28e4b5..f1523ae 100644
--- a/core/java/android/view/Choreographer.java
+++ b/core/java/android/view/Choreographer.java
@@ -23,6 +23,9 @@
import android.os.SystemClock;
import android.os.SystemProperties;
import android.util.Log;
+import android.util.TimeUtils;
+
+import java.io.PrintWriter;
/**
* Coordinates the timing of animations, input and drawing.
@@ -256,6 +259,15 @@
return delayMillis <= frameDelay ? 0 : delayMillis - frameDelay;
}
+ void dump(String prefix, PrintWriter writer) {
+ String innerPrefix = prefix + " ";
+ writer.print(prefix); writer.println("Choreographer:");
+ writer.print(innerPrefix); writer.print("mFrameScheduled=");
+ writer.println(mFrameScheduled);
+ writer.print(innerPrefix); writer.print("mLastFrameTime=");
+ writer.println(TimeUtils.formatUptime(mLastFrameTimeNanos / 1000000));
+ }
+
/**
* Posts a callback to run on the next frame.
* <p>
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 9461068..ab93084 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -77,8 +77,10 @@
import com.android.internal.view.BaseSurfaceHolder;
import com.android.internal.view.RootViewSurfaceTaker;
+import java.io.FileDescriptor;
import java.io.IOException;
import java.io.OutputStream;
+import java.io.PrintWriter;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.HashSet;
@@ -3458,6 +3460,12 @@
finishInputEvent(q);
}
}
+
+ void dump(String prefix, PrintWriter writer) {
+ if (mNext != null) {
+ mNext.dump(prefix, writer);
+ }
+ }
}
/**
@@ -3595,6 +3603,16 @@
mQueueLength -= 1;
Trace.traceCounter(Trace.TRACE_TAG_INPUT, mTraceCounter, mQueueLength);
}
+
+ @Override
+ void dump(String prefix, PrintWriter writer) {
+ writer.print(prefix);
+ writer.print(getClass().getName());
+ writer.print(": mQueueLength=");
+ writer.println(mQueueLength);
+
+ super.dump(prefix, writer);
+ }
}
/**
@@ -5201,6 +5219,53 @@
mView.debug();
}
+ public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) {
+ String innerPrefix = prefix + " ";
+ writer.print(prefix); writer.println("ViewRoot:");
+ writer.print(innerPrefix); writer.print("mAdded="); writer.print(mAdded);
+ writer.print(" mRemoved="); writer.println(mRemoved);
+ writer.print(innerPrefix); writer.print("mConsumeBatchedInputScheduled=");
+ writer.println(mConsumeBatchedInputScheduled);
+ writer.print(innerPrefix); writer.print("mPendingInputEventCount=");
+ writer.println(mPendingInputEventCount);
+ writer.print(innerPrefix); writer.print("mProcessInputEventsScheduled=");
+ writer.println(mProcessInputEventsScheduled);
+ writer.print(innerPrefix); writer.print("mTraversalScheduled=");
+ writer.print(mTraversalScheduled);
+ if (mTraversalScheduled) {
+ writer.print(" (barrier="); writer.print(mTraversalBarrier); writer.println(")");
+ } else {
+ writer.println();
+ }
+ mFirstInputStage.dump(innerPrefix, writer);
+
+ mChoreographer.dump(prefix, writer);
+
+ writer.print(prefix); writer.println("View Hierarchy:");
+ dumpViewHierarchy(innerPrefix, writer, mView);
+ }
+
+ private void dumpViewHierarchy(String prefix, PrintWriter writer, View view) {
+ writer.print(prefix);
+ if (view == null) {
+ writer.println("null");
+ return;
+ }
+ writer.println(view.toString());
+ if (!(view instanceof ViewGroup)) {
+ return;
+ }
+ ViewGroup grp = (ViewGroup)view;
+ final int N = grp.getChildCount();
+ if (N <= 0) {
+ return;
+ }
+ prefix = prefix + " ";
+ for (int i=0; i<N; i++) {
+ dumpViewHierarchy(prefix, writer, grp.getChildAt(i));
+ }
+ }
+
public void dumpGfxInfo(int[] info) {
info[0] = info[1] = 0;
if (mView != null) {