From f1285916c3ab259b216e5f3da3dba397c8e898b8 Mon Sep 17 00:00:00 2001 From: Wale Ogunwale Date: Fri, 9 Jun 2017 15:20:29 -0700 Subject: Added 'dumpsys activity lastanr' Allows for dumping the activity state during the last anr. This will also be included in collected bug reports. Bug: 38121026 Test: Cause an anr to occur and run 'adb shell dumpsys activity lastanr' Change-Id: I1e4200f9e5cc16bfab98e5af31fc599cdd54cd11 --- core/java/android/app/ActivityManagerInternal.java | 11 ++++ .../android/server/am/ActivityManagerService.java | 68 +++++++++++++++++++++- .../java/com/android/server/wm/InputMonitor.java | 3 + .../android/server/wm/WindowManagerService.java | 3 +- 4 files changed, 82 insertions(+), 3 deletions(-) diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java index e9ee13866b1a..d3b4b403e1ac 100644 --- a/core/java/android/app/ActivityManagerInternal.java +++ b/core/java/android/app/ActivityManagerInternal.java @@ -249,4 +249,15 @@ public abstract class ActivityManagerInternal { * {@param vr2dDisplayId}. */ public abstract void setVr2dDisplayId(int vr2dDisplayId); + + /** + * Saves the current activity manager state and includes the saved state in the next dump of + * activity manager. + */ + public abstract void saveANRState(String reason); + + /** + * Clears the previously saved activity manager ANR state. + */ + public abstract void clearSavedANRState(); } diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index a2a0634e4a03..30df978e45db 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -430,10 +430,12 @@ import java.io.StringWriter; import java.io.UnsupportedEncodingException; import java.lang.ref.WeakReference; import java.nio.charset.StandardCharsets; +import java.text.DateFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Comparator; +import java.util.Date; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; @@ -700,6 +702,12 @@ public class ActivityManagerService extends IActivityManager.Stub final AppErrors mAppErrors; + /** + * Dump of the activity state at the time of the last ANR. Cleared after + * {@link WindowManagerService#LAST_ANR_LIFETIME_DURATION_MSECS} + */ + String mLastANRState; + /** * Indicates the maximum time spent waiting for the network rules to get updated. */ @@ -14929,6 +14937,10 @@ public class ActivityManagerService extends IActivityManager.Stub synchronized (this) { dumpActivitiesLocked(fd, pw, args, opti, true, dumpClient, dumpPackage); } + } else if ("lastanr".equals(cmd)) { + synchronized (this) { + dumpLastANRLocked(pw); + } } else if ("recents".equals(cmd) || "r".equals(cmd)) { synchronized (this) { dumpRecentsLocked(fd, pw, args, opti, true, dumpPackage); @@ -15157,6 +15169,11 @@ public class ActivityManagerService extends IActivityManager.Stub if (dumpAll) { pw.println("-------------------------------------------------------------------------------"); } + dumpLastANRLocked(pw); + pw.println(); + if (dumpAll) { + pw.println("-------------------------------------------------------------------------------"); + } dumpActivitiesLocked(fd, pw, args, opti, dumpAll, dumpClient, dumpPackage); if (mAssociations.size() > 0) { pw.println(); @@ -15217,6 +15234,11 @@ public class ActivityManagerService extends IActivityManager.Stub if (dumpAll) { pw.println("-------------------------------------------------------------------------------"); } + dumpLastANRLocked(pw); + pw.println(); + if (dumpAll) { + pw.println("-------------------------------------------------------------------------------"); + } dumpActivitiesLocked(fd, pw, args, opti, dumpAll, dumpClient, dumpPackage); if (mAssociations.size() > 0) { pw.println(); @@ -15235,9 +15257,24 @@ public class ActivityManagerService extends IActivityManager.Stub Binder.restoreCallingIdentity(origId); } + private void dumpLastANRLocked(PrintWriter pw) { + if (mLastANRState == null) { + pw.println("ACTIVITY MANAGER ACTIVITIES (dumpsys activity lastanr)"); + pw.println(" "); + } else { + pw.println(mLastANRState); + } + } + void dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, String[] args, int opti, boolean dumpAll, boolean dumpClient, String dumpPackage) { - pw.println("ACTIVITY MANAGER ACTIVITIES (dumpsys activity activities)"); + dumpActivitiesLocked(fd, pw, args, opti, dumpAll, dumpClient, dumpPackage, + "ACTIVITY MANAGER ACTIVITIES (dumpsys activity activities)"); + } + + void dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, String[] args, + int opti, boolean dumpAll, boolean dumpClient, String dumpPackage, String header) { + pw.println(header); boolean printedAnything = mStackSupervisor.dumpActivitiesLocked(fd, pw, dumpAll, dumpClient, dumpPackage); @@ -23967,10 +24004,37 @@ public class ActivityManagerService extends IActivityManager.Stub mVr2dDisplayId = vr2dDisplayId; } } + + @Override + public void saveANRState(String reason) { + synchronized (ActivityManagerService.this) { + final StringWriter sw = new StringWriter(); + final PrintWriter pw = new FastPrintWriter(sw, false, 1024); + pw.println(" ANR time: " + DateFormat.getDateTimeInstance().format(new Date())); + if (reason != null) { + pw.println(" Reason: " + reason); + } + pw.println(); + dumpActivitiesLocked(null /* fd */, pw, null /* args */, 0 /* opti */, + true /* dumpAll */, false /* dumpClient */, null /* dumpPackage */, + "ACTIVITY MANAGER ACTIVITIES (dumpsys activity lastanr)"); + pw.println(); + pw.close(); + + mLastANRState = sw.toString(); + } + } + + @Override + public void clearSavedANRState() { + synchronized (ActivityManagerService.this) { + mLastANRState = null; + } + } } /** - * Called by app main thread to wait for the network policy rules to get udpated. + * Called by app main thread to wait for the network policy rules to get updated. * * @param procStateSeq The sequence number indicating the process state change that the main * thread is interested in. diff --git a/services/core/java/com/android/server/wm/InputMonitor.java b/services/core/java/com/android/server/wm/InputMonitor.java index 3caf89d750c8..5057f632461c 100644 --- a/services/core/java/com/android/server/wm/InputMonitor.java +++ b/services/core/java/com/android/server/wm/InputMonitor.java @@ -254,6 +254,9 @@ final class InputMonitor implements InputManagerService.WindowManagerCallbacks { mService.saveANRStateLocked(appWindowToken, windowState, reason); } + // All the calls below need to happen without the WM lock held since they call into AM. + mService.mAmInternal.saveANRState(reason); + if (appWindowToken != null && appWindowToken.appToken != null) { // Notify the activity manager about the timeout and let it decide whether // to abort dispatching or keep waiting. diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index 128109b68165..768b03a249b8 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -5116,6 +5116,7 @@ public class WindowManagerService extends IWindowManager.Stub synchronized (mWindowMap) { mLastANRState = null; } + mAmInternal.clearSavedANRState(); } break; case WALLPAPER_DRAW_PENDING_TIMEOUT: { @@ -6572,7 +6573,7 @@ public class WindowManagerService extends IWindowManager.Stub void saveANRStateLocked(AppWindowToken appWindowToken, WindowState windowState, String reason) { StringWriter sw = new StringWriter(); PrintWriter pw = new FastPrintWriter(sw, false, 1024); - pw.println(" ANR time: " + DateFormat.getInstance().format(new Date())); + pw.println(" ANR time: " + DateFormat.getDateTimeInstance().format(new Date())); if (appWindowToken != null) { pw.println(" Application at fault: " + appWindowToken.stringName); } -- cgit v1.2.3-59-g8ed1b