am 6ab3ea5f: am 147ef944: am 60d1e1a0: Merge "Watchdog: Improvement of debuggability"

* commit '6ab3ea5f48abfd777d5bd18d92acc3bc766f78ce':
  Watchdog: Improvement of debuggability
diff --git a/services/java/com/android/server/Watchdog.java b/services/java/com/android/server/Watchdog.java
index 9edfad6..2c5038e 100644
--- a/services/java/com/android/server/Watchdog.java
+++ b/services/java/com/android/server/Watchdog.java
@@ -26,6 +26,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.os.Build;
 import android.os.Debug;
 import android.os.Handler;
 import android.os.Message;
@@ -39,6 +40,8 @@
 import android.util.Slog;
 
 import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Calendar;
 
@@ -429,11 +432,10 @@
             }
 
             // If we got here, that means that the system is most likely hung.
-            // First collect stack traces from all threads of the system process.
-            // Then kill this process so that the system will restart.
 
             final String name = (mCurrentMonitor != null) ?
                     mCurrentMonitor.getClass().getName() : "null";
+            Slog.w(TAG, "WATCHDOG PROBLEM IN SYSTEM SERVER: " + name);
             EventLog.writeEvent(EventLogTags.WATCHDOG, name);
 
             ArrayList<Integer> pids = new ArrayList<Integer>();
@@ -468,11 +470,15 @@
                 dropboxThread.join(2000);  // wait up to 2 seconds for it to return.
             } catch (InterruptedException ignored) {}
 
-            // Only kill the process if the debugger is not attached.
+            // Only kill/crash the process if the debugger is not attached.
             if (!Debug.isDebuggerConnected()) {
                 Slog.w(TAG, "*** WATCHDOG KILLING SYSTEM PROCESS: " + name);
-                Process.killProcess(Process.myPid());
-                System.exit(10);
+                if (!Build.TYPE.equals("user")) {
+                    forceCrashDump();
+                } else {
+                    Process.killProcess(Process.myPid());
+                    System.exit(10);
+                }
             } else {
                 Slog.w(TAG, "Debugger connected: Watchdog is *not* killing the system process");
             }
@@ -481,6 +487,50 @@
         }
     }
 
+    private void forceCrashDump() {
+        /* Sync file system to flash the data which is written just before the
+         * crash.
+         */
+        java.lang.Process p = null;
+        try {
+            p = Runtime.getRuntime().exec("sync");
+            if (p != null) {
+                // It is not necessary to check the exit code, here.
+                // 'sync' command always succeeds, and this function returns 0.
+                p.waitFor();
+            } else {
+                Slog.e(TAG, "Failed to execute 'sync' command. (no process handle)");
+            }
+        } catch (Exception e) {
+            // This code is an emergency path to crash MUT. The system already
+            // caused fatal error, and then calls this function to create a
+            // crash dump. This function must run the code below to force a
+            // crash, even if the sync command failed.
+            // Therefore, ignore all exceptions, here.
+            Slog.e(TAG, "Failed to execute 'sync' command prior to forcing crash: " + e);
+        } finally {
+            if (p != null) {
+                p.destroy();
+            }
+        }
+
+        FileWriter out = null;
+        try {
+            out = new FileWriter("/proc/sysrq-trigger");
+            out.write("c");
+        } catch (IOException e) {
+            Slog.e(TAG, "Failed to write to sysrq-trigger while triggering crash: " + e);
+        } finally {
+            if (out != null) {
+                try {
+                    out.close();
+                } catch (IOException e) {
+                    Slog.e(TAG, "Failed to close sysrq-trigger while triggering crash: " + e);
+                }
+            }
+        }
+    }
+
     private File dumpKernelStackTraces() {
         String tracesPath = SystemProperties.get("dalvik.vm.stack-trace-file", null);
         if (tracesPath == null || tracesPath.length() == 0) {