Also dump system process threads halfway through the watchdog interval

This gives us a snapshot of what the system process was doing after 30 seconds
of apparent inactivity as well as after 1 minute, to help distinguishing actual
deadlocks from too-slow progress, livelock, etc.

Change-Id: I19758861d1b25f298e88788e8f1c7ec7bf828823
diff --git a/services/java/com/android/server/Watchdog.java b/services/java/com/android/server/Watchdog.java
index be1d1c4..5eaadbc 100644
--- a/services/java/com/android/server/Watchdog.java
+++ b/services/java/com/android/server/Watchdog.java
@@ -54,7 +54,8 @@
     static final int MONITOR = 2718;
     static final int GLOBAL_PSS = 2719;
 
-    static final int TIME_TO_WAIT = DB ? 15*1000 : 60*1000;
+    static final int TIME_TO_RESTART = DB ? 15*1000 : 60*1000;
+    static final int TIME_TO_WAIT = TIME_TO_RESTART / 2;
 
     static final int MEMCHECK_DEFAULT_INTERVAL = DB ? 30 : 30*60; // 30 minutes
     static final int MEMCHECK_DEFAULT_LOG_REALTIME_INTERVAL = DB ? 60 : 2*60*60;      // 2 hours
@@ -792,6 +793,7 @@
 
     @Override
     public void run() {
+        boolean waitedHalf = false;
         while (true) {
             mCompleted = false;
             mHandler.sendEmptyMessage(MONITOR);
@@ -801,7 +803,7 @@
 
                 // NOTE: We use uptimeMillis() here because we do not want to increment the time we
                 // wait while asleep. If the device is asleep then the thing that we are waiting
-                // to timeout on is asleep as well and won't have a chance to run. Causing a false
+                // 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();
                 while (timeout > 0 && !mForceKillSystem) {
@@ -815,6 +817,17 @@
 
                 if (mCompleted && !mForceKillSystem) {
                     // The monitors have returned.
+                    waitedHalf = false;
+                    continue;
+                }
+
+                if (!waitedHalf) {
+                    // We've waited half the deadlock-detection interval.  Pull a stack
+                    // trace and wait another half.
+                    ArrayList pids = new ArrayList();
+                    pids.add(Process.myPid());
+                    File stack = ActivityManagerService.dumpStackTraces(true, pids);
+                    waitedHalf = true;
                     continue;
                 }
             }
@@ -829,7 +842,9 @@
             ArrayList pids = new ArrayList();
             pids.add(Process.myPid());
             if (mPhonePid > 0) pids.add(mPhonePid);
-            File stack = ActivityManagerService.dumpStackTraces(pids);
+            // Pass !waitedHalf so that just in case we somehow wind up here without having
+            // dumped the halfway stacks, we properly re-initialize the trace file.
+            File stack = ActivityManagerService.dumpStackTraces(!waitedHalf, pids);
 
             // Give some extra time to make sure the stack traces get written.
             // The system's been hanging for a minute, another second or two won't hurt much.
@@ -845,6 +860,8 @@
             } else {
                 Slog.w(TAG, "Debugger connected: Watchdog is *not* killing the system process");
             }
+
+            waitedHalf = false;
         }
     }
 }