summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cmds/am/src/com/android/commands/am/Am.java12
-rw-r--r--core/java/android/app/IActivityController.aidl7
-rw-r--r--core/java/android/os/Binder.java33
-rw-r--r--services/java/com/android/server/Watchdog.java29
-rw-r--r--services/java/com/android/server/am/ActivityManagerService.java5
-rw-r--r--services/java/com/android/server/am/ActivityStack.java3
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;