2626import android .content .Context ;
2727import android .content .Intent ;
2828import android .content .IntentFilter ;
29+ import android .os .Build ;
2930import android .os .Debug ;
3031import android .os .Handler ;
3132import android .os .Message ;
3940import android .util .Slog ;
4041
4142import java .io .File ;
43+ import java .io .FileWriter ;
44+ import java .io .IOException ;
4245import java .util .ArrayList ;
4346import java .util .Calendar ;
4447
@@ -429,11 +432,10 @@ public void run() {
429432 }
430433
431434 // If we got here, that means that the system is most likely hung.
432- // First collect stack traces from all threads of the system process.
433- // Then kill this process so that the system will restart.
434435
435436 final String name = (mCurrentMonitor != null ) ?
436437 mCurrentMonitor .getClass ().getName () : "null" ;
438+ Slog .w (TAG , "WATCHDOG PROBLEM IN SYSTEM SERVER: " + name );
437439 EventLog .writeEvent (EventLogTags .WATCHDOG , name );
438440
439441 ArrayList <Integer > pids = new ArrayList <Integer >();
@@ -468,11 +470,15 @@ public void run() {
468470 dropboxThread .join (2000 ); // wait up to 2 seconds for it to return.
469471 } catch (InterruptedException ignored ) {}
470472
471- // Only kill the process if the debugger is not attached.
473+ // Only kill/crash the process if the debugger is not attached.
472474 if (!Debug .isDebuggerConnected ()) {
473475 Slog .w (TAG , "*** WATCHDOG KILLING SYSTEM PROCESS: " + name );
474- Process .killProcess (Process .myPid ());
475- System .exit (10 );
476+ if (!Build .TYPE .equals ("user" )) {
477+ forceCrashDump ();
478+ } else {
479+ Process .killProcess (Process .myPid ());
480+ System .exit (10 );
481+ }
476482 } else {
477483 Slog .w (TAG , "Debugger connected: Watchdog is *not* killing the system process" );
478484 }
@@ -481,6 +487,50 @@ public void run() {
481487 }
482488 }
483489
490+ private void forceCrashDump () {
491+ /* Sync file system to flash the data which is written just before the
492+ * crash.
493+ */
494+ java .lang .Process p = null ;
495+ try {
496+ p = Runtime .getRuntime ().exec ("sync" );
497+ if (p != null ) {
498+ // It is not necessary to check the exit code, here.
499+ // 'sync' command always succeeds, and this function returns 0.
500+ p .waitFor ();
501+ } else {
502+ Slog .e (TAG , "Failed to execute 'sync' command. (no process handle)" );
503+ }
504+ } catch (Exception e ) {
505+ // This code is an emergency path to crash MUT. The system already
506+ // caused fatal error, and then calls this function to create a
507+ // crash dump. This function must run the code below to force a
508+ // crash, even if the sync command failed.
509+ // Therefore, ignore all exceptions, here.
510+ Slog .e (TAG , "Failed to execute 'sync' command prior to forcing crash: " + e );
511+ } finally {
512+ if (p != null ) {
513+ p .destroy ();
514+ }
515+ }
516+
517+ FileWriter out = null ;
518+ try {
519+ out = new FileWriter ("/proc/sysrq-trigger" );
520+ out .write ("c" );
521+ } catch (IOException e ) {
522+ Slog .e (TAG , "Failed to write to sysrq-trigger while triggering crash: " + e );
523+ } finally {
524+ if (out != null ) {
525+ try {
526+ out .close ();
527+ } catch (IOException e ) {
528+ Slog .e (TAG , "Failed to close sysrq-trigger while triggering crash: " + e );
529+ }
530+ }
531+ }
532+ }
533+
484534 private File dumpKernelStackTraces () {
485535 String tracesPath = SystemProperties .get ("dalvik.vm.stack-trace-file" , null );
486536 if (tracesPath == null || tracesPath .length () == 0 ) {
0 commit comments