Capture window manager's last ANR state in bug report.

Currently just grabbing the window state but we could grab
other things as part of the last ANR report.

Bug: 6680398
Change-Id: I23aa70907b1bdcb21c8acc556fde196ca790ef6a
This commit is contained in:
Jeff Brown
2012-06-17 14:17:52 -07:00
parent 22aa512026
commit d7a04de167
4 changed files with 73 additions and 23 deletions

View File

@@ -26,7 +26,6 @@ import android.os.LocalPowerManager;
import android.os.Looper; import android.os.Looper;
import android.view.animation.Animation; import android.view.animation.Animation;
import java.io.FileDescriptor;
import java.io.PrintWriter; import java.io.PrintWriter;
/** /**
@@ -1122,10 +1121,9 @@ public interface WindowManagerPolicy {
* Print the WindowManagerPolicy's state into the given stream. * Print the WindowManagerPolicy's state into the given stream.
* *
* @param prefix Text to print at the front of each line. * @param prefix Text to print at the front of each line.
* @param fd The raw file descriptor that the dump is being sent to.
* @param writer The PrintWriter to which you should dump your state. This will be * @param writer The PrintWriter to which you should dump your state. This will be
* closed for you after you return. * closed for you after you return.
* @param args additional arguments to the dump request. * @param args additional arguments to the dump request.
*/ */
public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args); public void dump(String prefix, PrintWriter writer, String[] args);
} }

View File

@@ -143,7 +143,6 @@ import android.view.animation.Animation;
import android.view.animation.AnimationUtils; import android.view.animation.AnimationUtils;
import java.io.File; import java.io.File;
import java.io.FileDescriptor;
import java.io.FileReader; import java.io.FileReader;
import java.io.IOException; import java.io.IOException;
import java.io.PrintWriter; import java.io.PrintWriter;
@@ -4371,7 +4370,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
mLastInputMethodTargetWindow = target; mLastInputMethodTargetWindow = target;
} }
public void dump(String prefix, FileDescriptor fd, PrintWriter pw, String[] args) { public void dump(String prefix, PrintWriter pw, String[] args) {
pw.print(prefix); pw.print("mSafeMode="); pw.print(mSafeMode); pw.print(prefix); pw.print("mSafeMode="); pw.print(mSafeMode);
pw.print(" mSystemReady="); pw.print(mSystemReady); pw.print(" mSystemReady="); pw.print(mSystemReady);
pw.print(" mSystemBooted="); pw.println(mSystemBooted); pw.print(" mSystemBooted="); pw.println(mSystemBooted);

View File

@@ -94,6 +94,7 @@ final class InputMonitor implements InputManagerService.Callbacks {
Slog.i(WindowManagerService.TAG, "Input event dispatching timed out sending to " Slog.i(WindowManagerService.TAG, "Input event dispatching timed out sending to "
+ windowState.mAttrs.getTitle()); + windowState.mAttrs.getTitle());
appWindowToken = windowState.mAppToken; appWindowToken = windowState.mAppToken;
mService.saveANRStateLocked(appWindowToken, windowState);
} }
} }
} }
@@ -104,6 +105,7 @@ final class InputMonitor implements InputManagerService.Callbacks {
Slog.i(WindowManagerService.TAG, Slog.i(WindowManagerService.TAG,
"Input event dispatching timed out sending to application " "Input event dispatching timed out sending to application "
+ appWindowToken.stringName); + appWindowToken.stringName);
mService.saveANRStateLocked(appWindowToken, null);
} }
} }

View File

@@ -143,7 +143,9 @@ import java.io.OutputStreamWriter;
import java.io.PrintWriter; import java.io.PrintWriter;
import java.io.StringWriter; import java.io.StringWriter;
import java.net.Socket; import java.net.Socket;
import java.text.DateFormat;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.Iterator; import java.util.Iterator;
@@ -458,6 +460,8 @@ public class WindowManagerService extends IWindowManager.Stub
boolean mForceDisplayEnabled = false; boolean mForceDisplayEnabled = false;
boolean mShowingBootMessages = false; boolean mShowingBootMessages = false;
String mLastANRState;
// This protects the following display size properties, so that // This protects the following display size properties, so that
// getDisplaySize() doesn't need to acquire the global lock. This is // getDisplaySize() doesn't need to acquire the global lock. This is
// needed because the window manager sometimes needs to use ActivityThread // needed because the window manager sometimes needs to use ActivityThread
@@ -9429,12 +9433,12 @@ public class WindowManagerService extends IWindowManager.Stub
mPolicy.lockNow(); mPolicy.lockNow();
} }
void dumpPolicyLocked(FileDescriptor fd, PrintWriter pw, String[] args, boolean dumpAll) { void dumpPolicyLocked(PrintWriter pw, String[] args, boolean dumpAll) {
pw.println("WINDOW MANAGER POLICY STATE (dumpsys window policy)"); pw.println("WINDOW MANAGER POLICY STATE (dumpsys window policy)");
mPolicy.dump(" ", fd, pw, args); mPolicy.dump(" ", pw, args);
} }
void dumpTokensLocked(FileDescriptor fd, PrintWriter pw, boolean dumpAll) { void dumpTokensLocked(PrintWriter pw, boolean dumpAll) {
pw.println("WINDOW MANAGER TOKENS (dumpsys window tokens)"); pw.println("WINDOW MANAGER TOKENS (dumpsys window tokens)");
if (mTokenMap.size() > 0) { if (mTokenMap.size() > 0) {
pw.println(" All tokens:"); pw.println(" All tokens:");
@@ -9542,7 +9546,7 @@ public class WindowManagerService extends IWindowManager.Stub
} }
} }
void dumpSessionsLocked(FileDescriptor fd, PrintWriter pw, boolean dumpAll) { void dumpSessionsLocked(PrintWriter pw, boolean dumpAll) {
pw.println("WINDOW MANAGER SESSIONS (dumpsys window sessions)"); pw.println("WINDOW MANAGER SESSIONS (dumpsys window sessions)");
if (mSessions.size() > 0) { if (mSessions.size() > 0) {
Iterator<Session> it = mSessions.iterator(); Iterator<Session> it = mSessions.iterator();
@@ -9554,9 +9558,14 @@ public class WindowManagerService extends IWindowManager.Stub
} }
} }
void dumpWindowsLocked(FileDescriptor fd, PrintWriter pw, boolean dumpAll, void dumpWindowsLocked(PrintWriter pw, boolean dumpAll,
ArrayList<WindowState> windows) { ArrayList<WindowState> windows) {
pw.println("WINDOW MANAGER WINDOWS (dumpsys window windows)"); pw.println("WINDOW MANAGER WINDOWS (dumpsys window windows)");
dumpWindowsNoHeaderLocked(pw, dumpAll, windows);
}
void dumpWindowsNoHeaderLocked(PrintWriter pw, boolean dumpAll,
ArrayList<WindowState> windows) {
for (int i=mWindows.size()-1; i>=0; i--) { for (int i=mWindows.size()-1; i>=0; i--) {
WindowState w = mWindows.get(i); WindowState w = mWindows.get(i);
if (windows == null || windows.contains(w)) { if (windows == null || windows.contains(w)) {
@@ -9793,7 +9802,7 @@ public class WindowManagerService extends IWindowManager.Stub
} }
} }
boolean dumpWindows(FileDescriptor fd, PrintWriter pw, String name, String[] args, boolean dumpWindows(PrintWriter pw, String name, String[] args,
int opti, boolean dumpAll) { int opti, boolean dumpAll) {
ArrayList<WindowState> windows = new ArrayList<WindowState>(); ArrayList<WindowState> windows = new ArrayList<WindowState>();
if ("visible".equals(name)) { if ("visible".equals(name)) {
@@ -9832,11 +9841,42 @@ public class WindowManagerService extends IWindowManager.Stub
} }
synchronized(mWindowMap) { synchronized(mWindowMap) {
dumpWindowsLocked(fd, pw, dumpAll, windows); dumpWindowsLocked(pw, dumpAll, windows);
} }
return true; return true;
} }
void dumpLastANRLocked(PrintWriter pw) {
pw.println("WINDOW MANAGER LAST ANR (dumpsys window lastanr)");
if (mLastANRState == null) {
pw.println(" <no ANR has occurred since boot>");
} else {
pw.println(mLastANRState);
}
}
/**
* Saves information about the state of the window manager at
* the time an ANR occurred before anything else in the system changes
* in response.
*
* @param appWindowToken The application that ANR'd, never null.
* @param windowState The window that ANR'd, may be null.
*/
public void saveANRStateLocked(AppWindowToken appWindowToken, WindowState windowState) {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
pw.println(" ANR time: " + DateFormat.getInstance().format(new Date()));
pw.println(" Application at fault: " + appWindowToken.stringName);
if (windowState != null) {
pw.println(" Window at fault: " + windowState.mAttrs.getTitle());
}
pw.println();
dumpWindowsNoHeaderLocked(pw, true, null);
pw.close();
mLastANRState = sw.toString();
}
@Override @Override
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
if (mContext.checkCallingOrSelfPermission("android.permission.DUMP") if (mContext.checkCallingOrSelfPermission("android.permission.DUMP")
@@ -9862,6 +9902,7 @@ public class WindowManagerService extends IWindowManager.Stub
pw.println("Window manager dump options:"); pw.println("Window manager dump options:");
pw.println(" [-a] [-h] [cmd] ..."); pw.println(" [-a] [-h] [cmd] ...");
pw.println(" cmd may be one of:"); pw.println(" cmd may be one of:");
pw.println(" l[astanr]: last ANR information");
pw.println(" p[policy]: policy state"); pw.println(" p[policy]: policy state");
pw.println(" s[essions]: active sessions"); pw.println(" s[essions]: active sessions");
pw.println(" t[okens]: token list"); pw.println(" t[okens]: token list");
@@ -9882,34 +9923,39 @@ public class WindowManagerService extends IWindowManager.Stub
if (opti < args.length) { if (opti < args.length) {
String cmd = args[opti]; String cmd = args[opti];
opti++; opti++;
if ("policy".equals(cmd) || "p".equals(cmd)) { if ("lastanr".equals(cmd) || "l".equals(cmd)) {
synchronized(mWindowMap) { synchronized(mWindowMap) {
dumpPolicyLocked(fd, pw, args, true); dumpLastANRLocked(pw);
}
return;
} else if ("policy".equals(cmd) || "p".equals(cmd)) {
synchronized(mWindowMap) {
dumpPolicyLocked(pw, args, true);
} }
return; return;
} else if ("sessions".equals(cmd) || "s".equals(cmd)) { } else if ("sessions".equals(cmd) || "s".equals(cmd)) {
synchronized(mWindowMap) { synchronized(mWindowMap) {
dumpSessionsLocked(fd, pw, true); dumpSessionsLocked(pw, true);
} }
return; return;
} else if ("tokens".equals(cmd) || "t".equals(cmd)) { } else if ("tokens".equals(cmd) || "t".equals(cmd)) {
synchronized(mWindowMap) { synchronized(mWindowMap) {
dumpTokensLocked(fd, pw, true); dumpTokensLocked(pw, true);
} }
return; return;
} else if ("windows".equals(cmd) || "w".equals(cmd)) { } else if ("windows".equals(cmd) || "w".equals(cmd)) {
synchronized(mWindowMap) { synchronized(mWindowMap) {
dumpWindowsLocked(fd, pw, true, null); dumpWindowsLocked(pw, true, null);
} }
return; return;
} else if ("all".equals(cmd) || "a".equals(cmd)) { } else if ("all".equals(cmd) || "a".equals(cmd)) {
synchronized(mWindowMap) { synchronized(mWindowMap) {
dumpWindowsLocked(fd, pw, true, null); dumpWindowsLocked(pw, true, null);
} }
return; return;
} else { } else {
// Dumping a single name? // Dumping a single name?
if (!dumpWindows(fd, pw, cmd, args, opti, dumpAll)) { if (!dumpWindows(pw, cmd, args, opti, dumpAll)) {
pw.println("Bad window command, or no windows match: " + cmd); pw.println("Bad window command, or no windows match: " + cmd);
pw.println("Use -h for help."); pw.println("Use -h for help.");
} }
@@ -9921,22 +9967,27 @@ public class WindowManagerService extends IWindowManager.Stub
if (dumpAll) { if (dumpAll) {
pw.println("-------------------------------------------------------------------------------"); pw.println("-------------------------------------------------------------------------------");
} }
dumpPolicyLocked(fd, pw, args, dumpAll); dumpPolicyLocked(pw, args, dumpAll);
pw.println(); pw.println();
if (dumpAll) { if (dumpAll) {
pw.println("-------------------------------------------------------------------------------"); pw.println("-------------------------------------------------------------------------------");
} }
dumpSessionsLocked(fd, pw, dumpAll); dumpSessionsLocked(pw, dumpAll);
pw.println(); pw.println();
if (dumpAll) { if (dumpAll) {
pw.println("-------------------------------------------------------------------------------"); pw.println("-------------------------------------------------------------------------------");
} }
dumpTokensLocked(fd, pw, dumpAll); dumpTokensLocked(pw, dumpAll);
pw.println(); pw.println();
if (dumpAll) { if (dumpAll) {
pw.println("-------------------------------------------------------------------------------"); pw.println("-------------------------------------------------------------------------------");
} }
dumpWindowsLocked(fd, pw, dumpAll, null); dumpWindowsLocked(pw, dumpAll, null);
pw.println();
if (dumpAll) {
pw.println("-------------------------------------------------------------------------------");
}
dumpLastANRLocked(pw);
} }
} }