Merge "Improve watchdog diagnostics."
diff --git a/services/java/com/android/server/Watchdog.java b/services/java/com/android/server/Watchdog.java
index ee69715..f97f50a 100644
--- a/services/java/com/android/server/Watchdog.java
+++ b/services/java/com/android/server/Watchdog.java
@@ -34,8 +34,10 @@
 import android.provider.Settings;
 import android.util.Config;
 import android.util.EventLog;
+import android.util.Log;
 import android.util.Slog;
 
+import java.io.File;
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Calendar;
@@ -804,19 +806,14 @@
                 // to timeout on is asleep as well and won't have a chance to run. Causing a false
                 // positive on when to kill things.
                 long start = SystemClock.uptimeMillis();
-                do {
+                while (timeout > 0 && !mForceKillSystem) {
                     try {
-                        wait(timeout);
+                        wait(timeout);  // notifyAll() is called when mForceKillSystem is set
                     } catch (InterruptedException e) {
-                        if (SystemProperties.getBoolean("ro.secure", false)) {
-                            // If this is a secure build, just log the error.
-                            Slog.e("WatchDog", "Woof! Woof! Interrupter!");
-                        } else {
-                            throw new AssertionError("Someone interrupted the watchdog");
-                        }
+                        Log.wtf(TAG, e);
                     }
                     timeout = TIME_TO_WAIT - (SystemClock.uptimeMillis() - start);
-                } while (timeout > 0 && !mForceKillSystem);
+                }
 
                 if (mCompleted && !mForceKillSystem) {
                     // The monitors have returned.
@@ -825,22 +822,24 @@
             }
 
             // If we got here, that means that the system is most likely hung.
-            // First send a SIGQUIT so that we can see where it was hung. Then
-            // kill this process so that the system will restart.
+            // First collect stack traces from all threads of the system process.
+            // Then kill this process so that the system will restart.
+
             String name = (mCurrentMonitor != null) ? mCurrentMonitor.getClass().getName() : "null";
             EventLog.writeEvent(EventLogTags.WATCHDOG, name);
-            Process.sendSignal(Process.myPid(), Process.SIGNAL_QUIT);
 
-            // Wait a bit longer before killing so we can make sure that the stacks are captured.
-            try {
-                Thread.sleep(10*1000);
-            } catch (InterruptedException e) {
-            }
+            ArrayList pids = new ArrayList();
+            pids.add(Process.myPid());
+            File stack = ActivityManagerService.dumpStackTraces(pids);
+            mActivity.addErrorToDropBox("watchdog", null, null, null, name, null, stack, null);
 
             // Only kill the process if the debugger is not attached.
             if (!Debug.isDebuggerConnected()) {
-                Slog.i(TAG, "Watchdog is killing the system process");
+                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");
             }
         }
     }
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index a263b23..9018872 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -4662,7 +4662,7 @@
      * @param pids of dalvik VM processes to dump stack traces for
      * @return file containing stack traces, or null if no dump file is configured
      */
-    private static File dumpStackTraces(ArrayList<Integer> pids) {
+    public static File dumpStackTraces(ArrayList<Integer> pids) {
         String tracesPath = SystemProperties.get("dalvik.vm.stack-trace-file", null);
         if (tracesPath == null || tracesPath.length() == 0) {
             return null;
@@ -8958,10 +8958,13 @@
      * @param logFile to include in the report, null if none
      * @param crashInfo giving an application stack trace, null if absent
      */
-    private void addErrorToDropBox(String eventType,
+    public void addErrorToDropBox(String eventType,
             ProcessRecord process, HistoryRecord activity, HistoryRecord parent,
             String subject, String report, File logFile,
             ApplicationErrorReport.CrashInfo crashInfo) {
+        // NOTE -- this must never acquire the ActivityManagerService lock,
+        // otherwise the watchdog may be prevented from resetting the system.
+
         String dropboxTag;
         if (process == null || process.pid == MY_PID) {
             dropboxTag = "system_server_" + eventType;