Help for the debugging help for issue #8734824.
Add a new "hang" am command that lets you hang the system
process. Useful for testing.
Change-Id: Ice0fc52b49d80e5189f016108b03f9fd549b58a7
diff --git a/services/java/com/android/server/Watchdog.java b/services/java/com/android/server/Watchdog.java
index e784cf2..3aec4ea 100644
--- a/services/java/com/android/server/Watchdog.java
+++ b/services/java/com/android/server/Watchdog.java
@@ -95,6 +95,7 @@
int mPhonePid;
IActivityController mController;
+ boolean mAllowRestart = true;
final Calendar mCalendar = Calendar.getInstance();
int mMinScreenOff = MEMCHECK_DEFAULT_MIN_SCREEN_OFF;
@@ -233,6 +234,12 @@
}
}
+ public void setAllowRestart(boolean allowRestart) {
+ synchronized (this) {
+ mAllowRestart = allowRestart;
+ }
+ }
+
public void addMonitor(Monitor monitor) {
synchronized (this) {
if (isAlive()) {
@@ -401,6 +408,7 @@
final String name;
+ final boolean allowRestart;
synchronized (this) {
long timeout = TIME_TO_WAIT;
@@ -437,6 +445,7 @@
name = (mCurrentMonitor != null) ?
mCurrentMonitor.getClass().getName() : "null";
+ allowRestart = mAllowRestart;
}
// If we got here, that means that the system is most likely hung.
@@ -506,12 +515,14 @@
}
// Only kill the process if the debugger is not attached.
- if (!Debug.isDebuggerConnected()) {
+ if (Debug.isDebuggerConnected()) {
+ Slog.w(TAG, "Debugger connected: Watchdog is *not* killing the system process");
+ } else if (!allowRestart) {
+ Slog.w(TAG, "Restart not allowed: Watchdog is *not* killing the system process");
+ } else {
Slog.w(TAG, "*** WATCHDOG KILLING SYSTEM PROCESS: " + name);
Process.killProcess(Process.myPid());
System.exit(10);
- } else {
- Slog.w(TAG, "Debugger connected: Watchdog is *not* killing the system process");
}
waitedHalf = false;
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index cbeed7b..0081dfc 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -7813,6 +7813,45 @@
return killed;
}
+ @Override
+ public void hang(final IBinder who, boolean allowRestart) {
+ if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
+ != PackageManager.PERMISSION_GRANTED) {
+ throw new SecurityException("Requires permission "
+ + android.Manifest.permission.SET_ACTIVITY_WATCHER);
+ }
+
+ final IBinder.DeathRecipient death = new DeathRecipient() {
+ @Override
+ public void binderDied() {
+ synchronized (this) {
+ notifyAll();
+ }
+ }
+ };
+
+ try {
+ who.linkToDeath(death, 0);
+ } catch (RemoteException e) {
+ Slog.w(TAG, "hang: given caller IBinder is already dead.");
+ return;
+ }
+
+ synchronized (this) {
+ Watchdog.getInstance().setAllowRestart(allowRestart);
+ Slog.i(TAG, "Hanging system process at request of pid " + Binder.getCallingPid());
+ synchronized (death) {
+ while (who.isBinderAlive()) {
+ try {
+ death.wait();
+ } catch (InterruptedException e) {
+ }
+ }
+ }
+ Watchdog.getInstance().setAllowRestart(true);
+ }
+ }
+
public final void startRunning(String pkg, String cls, String action,
String data) {
synchronized(this) {