diff options
4 files changed, 37 insertions, 12 deletions
diff --git a/services/java/com/android/server/Watchdog.java b/services/java/com/android/server/Watchdog.java index 070b8e59d09d..ec573f947a50 100644 --- a/services/java/com/android/server/Watchdog.java +++ b/services/java/com/android/server/Watchdog.java @@ -120,6 +120,14 @@ public class Watchdog extends Thread { return mCompleted; } + public Thread getThread() { + return mHandler.getLooper().getThread(); + } + + public String getName() { + return mName; + } + public String describeBlockedStateLocked() { return mCurrentMonitor == null ? mName : mCurrentMonitor.getClass().getName(); } @@ -256,17 +264,25 @@ public class Watchdog extends Thread { return true; } - private String describeBlockedCheckersLocked() { - StringBuilder builder = new StringBuilder(128); + private ArrayList<HandlerChecker> getBlockedCheckersLocked() { + ArrayList<HandlerChecker> checkers = new ArrayList<HandlerChecker>(); for (int i=0; i<mHandlerCheckers.size(); i++) { HandlerChecker hc = mHandlerCheckers.get(i); if (!hc.isCompletedLocked()) { - if (builder.length() > 0) { - builder.append(", "); - } - builder.append(hc.describeBlockedStateLocked()); + checkers.add(hc); } } + return checkers; + } + + private String describeCheckersLocked(ArrayList<HandlerChecker> checkers) { + StringBuilder builder = new StringBuilder(128); + for (int i=0; i<checkers.size(); i++) { + if (builder.length() > 0) { + builder.append(", "); + } + builder.append(checkers.get(i).describeBlockedStateLocked()); + } return builder.toString(); } @@ -274,6 +290,7 @@ public class Watchdog extends Thread { public void run() { boolean waitedHalf = false; while (true) { + final ArrayList<HandlerChecker> blockedCheckers; final String name; final boolean allowRestart; synchronized (this) { @@ -318,7 +335,8 @@ public class Watchdog extends Thread { continue; } - name = describeBlockedCheckersLocked(); + blockedCheckers = getBlockedCheckersLocked(); + name = describeCheckersLocked(blockedCheckers); allowRestart = mAllowRestart; } @@ -395,12 +413,15 @@ public class Watchdog extends Thread { Slog.w(TAG, "Restart not allowed: Watchdog is *not* killing the system process"); } else { Slog.w(TAG, "*** WATCHDOG KILLING SYSTEM PROCESS: " + name); - Slog.w(TAG, "Main thread stack trace:"); - StackTraceElement[] stackTrace = Looper.getMainLooper().getThread().getStackTrace(); - for (StackTraceElement element: stackTrace) { - Slog.w(TAG, "\tat " + element); + for (int i=0; i<blockedCheckers.size(); i++) { + Slog.w(TAG, blockedCheckers.get(i).getName() + " stack trace:"); + StackTraceElement[] stackTrace + = blockedCheckers.get(i).getThread().getStackTrace(); + for (StackTraceElement element: stackTrace) { + Slog.w(TAG, " at " + element); + } } - Slog.w(TAG, "<End of main thread stack trace>"); + Slog.w(TAG, "*** GOODBYE!"); Process.killProcess(Process.myPid()); System.exit(10); } diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java index 42e2b3a9b7eb..9d9d06d1cde2 100644 --- a/services/java/com/android/server/am/ActivityManagerService.java +++ b/services/java/com/android/server/am/ActivityManagerService.java @@ -1576,6 +1576,7 @@ public final class ActivityManagerService extends ActivityManagerNative synchronized (this) { mService = m; mLooper = Looper.myLooper(); + Watchdog.getInstance().addThread(new Handler(mLooper), getName()); notifyAll(); } diff --git a/services/java/com/android/server/pm/PackageManagerService.java b/services/java/com/android/server/pm/PackageManagerService.java index 47282ba304da..8f512d33d9f4 100644 --- a/services/java/com/android/server/pm/PackageManagerService.java +++ b/services/java/com/android/server/pm/PackageManagerService.java @@ -41,6 +41,7 @@ import com.android.server.DeviceStorageMonitorService; import com.android.server.EventLogTags; import com.android.server.IntentResolver; +import com.android.server.Watchdog; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlSerializer; @@ -1093,6 +1094,7 @@ public class PackageManagerService extends IPackageManager.Stub { synchronized (mPackages) { mHandlerThread.start(); mHandler = new PackageHandler(mHandlerThread.getLooper()); + Watchdog.getInstance().addThread(mHandler, mHandlerThread.getName()); File dataDir = Environment.getDataDirectory(); mAppDataDir = new File(dataDir, "data"); diff --git a/services/java/com/android/server/power/PowerManagerService.java b/services/java/com/android/server/power/PowerManagerService.java index 198851c3dc1d..6c283faf7934 100644 --- a/services/java/com/android/server/power/PowerManagerService.java +++ b/services/java/com/android/server/power/PowerManagerService.java @@ -405,6 +405,7 @@ public final class PowerManagerService extends IPowerManager.Stub mHandler = new PowerManagerHandler(mHandlerThread.getLooper()); Watchdog.getInstance().addMonitor(this); + Watchdog.getInstance().addThread(mHandler, mHandlerThread.getName()); // Forcibly turn the screen on at boot so that it is in a known power state. // We do this in init() rather than in the constructor because setting the |