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 | 5 | ||||
-rw-r--r-- | services/java/com/android/server/am/ActivityStack.java | 3 |
6 files changed, 87 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 95343f9..dca873e 100644 --- a/cmds/am/src/com/android/commands/am/Am.java +++ b/cmds/am/src/com/android/commands/am/Am.java @@ -1109,6 +1109,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 6a47243..92c35f8 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; @@ -89,6 +92,7 @@ public class Watchdog extends Thread { ActivityManagerService mActivity; int mPhonePid; + IActivityController mController; final Calendar mCalendar = Calendar.getInstance(); int mMinScreenOff = MEMCHECK_DEFAULT_MIN_SCREEN_OFF; @@ -260,6 +264,12 @@ public class Watchdog extends Thread { } } + public void setActivityController(IActivityController controller) { + synchronized (this) { + mController = controller; + } + } + public void addMonitor(Monitor monitor) { synchronized (this) { if (isAlive()) { @@ -549,6 +559,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 c34b4ec..14529bb 100644 --- a/services/java/com/android/server/am/ActivityManagerService.java +++ b/services/java/com/android/server/am/ActivityManagerService.java @@ -2920,6 +2920,7 @@ public final class ActivityManagerService extends ActivityManagerNative resumeOK = mController.activityResuming(next.packageName); } catch (RemoteException e) { mController = null; + Watchdog.getInstance().setActivityController(null); } if (!resumeOK) { @@ -3413,6 +3414,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); } } @@ -3516,6 +3518,7 @@ public final class ActivityManagerService extends ActivityManagerNative } } catch (RemoteException e) { mController = null; + Watchdog.getInstance().setActivityController(null); } } @@ -7569,6 +7572,7 @@ public final class ActivityManagerService extends ActivityManagerNative "setActivityController()"); synchronized (this) { mController = controller; + Watchdog.getInstance().setActivityController(controller); } } @@ -8932,6 +8936,7 @@ public final class ActivityManagerService extends ActivityManagerNative } } catch (RemoteException e) { mController = null; + Watchdog.getInstance().setActivityController(null); } } diff --git a/services/java/com/android/server/am/ActivityStack.java b/services/java/com/android/server/am/ActivityStack.java index 4787a1e..ba14b3b 100644 --- a/services/java/com/android/server/am/ActivityStack.java +++ b/services/java/com/android/server/am/ActivityStack.java @@ -20,6 +20,7 @@ import static com.android.server.am.ActivityStackSupervisor.HOME_STACK_ID; import com.android.internal.os.BatteryStatsImpl; import com.android.internal.util.Objects; +import com.android.server.Watchdog; import com.android.server.am.ActivityManagerService.ItemMatcher; import com.android.server.wm.AppTransition; import com.android.server.wm.TaskGroup; @@ -2498,6 +2499,7 @@ final class ActivityStack { resumeOK = controller.activityResuming(next.packageName); } catch (RemoteException e) { mService.mController = null; + Watchdog.getInstance().setActivityController(null); } if (!resumeOK) { @@ -3022,6 +3024,7 @@ final class ActivityStack { moveOK = mService.mController.activityResuming(next.packageName); } catch (RemoteException e) { mService.mController = null; + Watchdog.getInstance().setActivityController(null); } if (!moveOK) { return false; |