Loading cmds/am/src/com/android/commands/am/Am.java +12 −0 Original line number Diff line number Diff line Loading @@ -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) { Loading core/java/android/app/IActivityController.aidl +7 −0 Original line number Diff line number Diff line Loading @@ -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); } core/java/android/os/Binder.java +31 −2 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -225,6 +230,22 @@ 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. Loading Loading @@ -269,7 +290,15 @@ public class Binder implements IBinder { FileOutputStream fout = new FileOutputStream(fd); PrintWriter pw = new PrintWriter(fout); try { final String disabled; synchronized (Binder.class) { disabled = sDumpDisabled; } if (disabled == null) { dump(fd, pw, args); } else { pw.println(sDumpDisabled); } } finally { pw.flush(); } Loading services/java/com/android/server/Watchdog.java +29 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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()) { Loading Loading @@ -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); Loading services/java/com/android/server/am/ActivityManagerService.java +6 −0 Original line number Diff line number Diff line Loading @@ -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) { Loading Loading @@ -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); } } Loading Loading @@ -3437,6 +3439,7 @@ public final class ActivityManagerService extends ActivityManagerNative } } catch (RemoteException e) { mController = null; Watchdog.getInstance().setActivityController(null); } } Loading Loading @@ -7441,6 +7444,7 @@ public final class ActivityManagerService extends ActivityManagerNative "setActivityController()"); synchronized (this) { mController = controller; Watchdog.getInstance().setActivityController(controller); } } Loading Loading @@ -8832,6 +8836,7 @@ public final class ActivityManagerService extends ActivityManagerNative } } catch (RemoteException e) { mController = null; Watchdog.getInstance().setActivityController(null); } } Loading Loading @@ -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) { Loading
cmds/am/src/com/android/commands/am/Am.java +12 −0 Original line number Diff line number Diff line Loading @@ -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) { Loading
core/java/android/app/IActivityController.aidl +7 −0 Original line number Diff line number Diff line Loading @@ -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); }
core/java/android/os/Binder.java +31 −2 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -225,6 +230,22 @@ 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. Loading Loading @@ -269,7 +290,15 @@ public class Binder implements IBinder { FileOutputStream fout = new FileOutputStream(fd); PrintWriter pw = new PrintWriter(fout); try { final String disabled; synchronized (Binder.class) { disabled = sDumpDisabled; } if (disabled == null) { dump(fd, pw, args); } else { pw.println(sDumpDisabled); } } finally { pw.flush(); } Loading
services/java/com/android/server/Watchdog.java +29 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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()) { Loading Loading @@ -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); Loading
services/java/com/android/server/am/ActivityManagerService.java +6 −0 Original line number Diff line number Diff line Loading @@ -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) { Loading Loading @@ -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); } } Loading Loading @@ -3437,6 +3439,7 @@ public final class ActivityManagerService extends ActivityManagerNative } } catch (RemoteException e) { mController = null; Watchdog.getInstance().setActivityController(null); } } Loading Loading @@ -7441,6 +7444,7 @@ public final class ActivityManagerService extends ActivityManagerNative "setActivityController()"); synchronized (this) { mController = controller; Watchdog.getInstance().setActivityController(controller); } } Loading Loading @@ -8832,6 +8836,7 @@ public final class ActivityManagerService extends ActivityManagerNative } } catch (RemoteException e) { mController = null; Watchdog.getInstance().setActivityController(null); } } Loading Loading @@ -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) {