diff options
-rw-r--r-- | cmds/am/src/com/android/commands/am/Am.java | 12 | ||||
-rw-r--r-- | core/java/android/app/IActivityController.aidl | 7 | ||||
-rw-r--r-- | core/java/android/os/Binder.java | 33 | ||||
-rw-r--r-- | services/java/com/android/server/Watchdog.java | 29 | ||||
-rw-r--r-- | services/java/com/android/server/am/ActivityManagerService.java | 6 |
5 files changed, 85 insertions, 2 deletions
diff --git a/cmds/am/src/com/android/commands/am/Am.java b/cmds/am/src/com/android/commands/am/Am.java index ccb9e1f..93658e1 100644 --- a/cmds/am/src/com/android/commands/am/Am.java +++ b/cmds/am/src/com/android/commands/am/Am.java @@ -1093,6 +1093,18 @@ public class Am extends BaseCommand { } } + @Override + public int systemNotResponding(String message) + throws RemoteException { + synchronized (this) { + System.out.println("** ERROR: PROCESS NOT RESPONDING"); + System.out.println("message: " + message); + System.out.println("#"); + System.out.println("Allowing system to die."); + return -1; + } + } + void killGdbLocked() { mGotGdbPrint = false; if (mGdbProcess != null) { diff --git a/core/java/android/app/IActivityController.aidl b/core/java/android/app/IActivityController.aidl index aca8305..952c900 100644 --- a/core/java/android/app/IActivityController.aidl +++ b/core/java/android/app/IActivityController.aidl @@ -58,4 +58,11 @@ interface IActivityController * immediately. */ int appNotResponding(String processName, int pid, String processStats); + + /** + * The system process watchdog has detected that the system seems to be + * hung. Return 1 to continue waiting, or -1 to let it continue with its + * normal kill. + */ + int systemNotResponding(String msg); } diff --git a/core/java/android/os/Binder.java b/core/java/android/os/Binder.java index e9e7551..7ffd30b 100644 --- a/core/java/android/os/Binder.java +++ b/core/java/android/os/Binder.java @@ -49,6 +49,11 @@ public class Binder implements IBinder { private static final boolean FIND_POTENTIAL_LEAKS = false; private static final String TAG = "Binder"; + /** + * Control whether dump() calls are allowed. + */ + private static String sDumpDisabled = null; + /* mObject is used by native code, do not remove or rename */ private int mObject; private IInterface mOwner; @@ -224,7 +229,23 @@ public class Binder implements IBinder { } return null; } - + + /** + * Control disabling of dump calls in this process. This is used by the system + * process watchdog to disable incoming dump calls while it has detecting the system + * is hung and is reporting that back to the activity controller. This is to + * prevent the controller from getting hung up on bug reports at this point. + * @hide + * + * @param msg The message to show instead of the dump; if null, dumps are + * re-enabled. + */ + public static void setDumpDisabled(String msg) { + synchronized (Binder.class) { + sDumpDisabled = msg; + } + } + /** * Default implementation is a stub that returns false. You will want * to override this to do the appropriate unmarshalling of transactions. @@ -269,7 +290,15 @@ public class Binder implements IBinder { FileOutputStream fout = new FileOutputStream(fd); PrintWriter pw = new PrintWriter(fout); try { - dump(fd, pw, args); + final String disabled; + synchronized (Binder.class) { + disabled = sDumpDisabled; + } + if (disabled == null) { + dump(fd, pw, args); + } else { + pw.println(sDumpDisabled); + } } finally { pw.flush(); } diff --git a/services/java/com/android/server/Watchdog.java b/services/java/com/android/server/Watchdog.java index 167e7af..e784cf2 100644 --- a/services/java/com/android/server/Watchdog.java +++ b/services/java/com/android/server/Watchdog.java @@ -16,6 +16,9 @@ package com.android.server; +import android.app.IActivityController; +import android.os.Binder; +import android.os.RemoteException; import com.android.server.am.ActivityManagerService; import com.android.server.power.PowerManagerService; @@ -91,6 +94,7 @@ public class Watchdog extends Thread { Monitor mCurrentMonitor; int mPhonePid; + IActivityController mController; final Calendar mCalendar = Calendar.getInstance(); int mMinScreenOff = MEMCHECK_DEFAULT_MIN_SCREEN_OFF; @@ -223,6 +227,12 @@ public class Watchdog extends Thread { } } + public void setActivityController(IActivityController controller) { + synchronized (this) { + mController = controller; + } + } + public void addMonitor(Monitor monitor) { synchronized (this) { if (isAlive()) { @@ -476,6 +486,25 @@ public class Watchdog extends Thread { dropboxThread.join(2000); // wait up to 2 seconds for it to return. } catch (InterruptedException ignored) {} + IActivityController controller; + synchronized (this) { + controller = mController; + } + if (controller != null) { + Slog.i(TAG, "Reporting stuck state to activity controller"); + try { + Binder.setDumpDisabled("Service dumps disabled due to hung system process."); + // 1 = keep waiting, -1 = kill system + int res = controller.systemNotResponding(name); + if (res >= 0) { + Slog.i(TAG, "Activity controller requested to coninue to wait"); + waitedHalf = false; + continue; + } + } catch (RemoteException e) { + } + } + // Only kill the process if the debugger is not attached. if (!Debug.isDebuggerConnected()) { Slog.w(TAG, "*** WATCHDOG KILLING SYSTEM PROCESS: " + name); diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java index 1d17da9..cbeed7b 100644 --- a/services/java/com/android/server/am/ActivityManagerService.java +++ b/services/java/com/android/server/am/ActivityManagerService.java @@ -2822,6 +2822,7 @@ public final class ActivityManagerService extends ActivityManagerNative resumeOK = mController.activityResuming(next.packageName); } catch (RemoteException e) { mController = null; + Watchdog.getInstance().setActivityController(null); } if (!resumeOK) { @@ -3334,6 +3335,7 @@ public final class ActivityManagerService extends ActivityManagerNative if (res < 0 && app.pid != MY_PID) Process.killProcess(app.pid); } catch (RemoteException e) { mController = null; + Watchdog.getInstance().setActivityController(null); } } @@ -3437,6 +3439,7 @@ public final class ActivityManagerService extends ActivityManagerNative } } catch (RemoteException e) { mController = null; + Watchdog.getInstance().setActivityController(null); } } @@ -7441,6 +7444,7 @@ public final class ActivityManagerService extends ActivityManagerNative "setActivityController()"); synchronized (this) { mController = controller; + Watchdog.getInstance().setActivityController(controller); } } @@ -8832,6 +8836,7 @@ public final class ActivityManagerService extends ActivityManagerNative } } catch (RemoteException e) { mController = null; + Watchdog.getInstance().setActivityController(null); } } @@ -12765,6 +12770,7 @@ public final class ActivityManagerService extends ActivityManagerNative resumeOK = mController.activityResuming(next.packageName); } catch (RemoteException e) { mController = null; + Watchdog.getInstance().setActivityController(null); } if (!resumeOK) { |