1 /* 2 * Copyright (C) 2008 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.server; 18 19 import android.app.IActivityController; 20 import android.content.BroadcastReceiver; 21 import android.content.Context; 22 import android.content.Intent; 23 import android.content.IntentFilter; 24 import android.hidl.manager.V1_0.IServiceManager; 25 import android.os.Binder; 26 import android.os.Debug; 27 import android.os.Handler; 28 import android.os.IPowerManager; 29 import android.os.Looper; 30 import android.os.Process; 31 import android.os.RemoteException; 32 import android.os.ServiceManager; 33 import android.os.SystemClock; 34 import android.util.EventLog; 35 import android.util.Log; 36 import android.util.Slog; 37 import android.util.StatsLog; 38 39 import com.android.internal.os.ZygoteConnectionConstants; 40 import com.android.server.am.ActivityManagerService; 41 import com.android.server.wm.SurfaceAnimationThread; 42 43 import java.io.File; 44 import java.io.FileWriter; 45 import java.io.IOException; 46 import java.util.ArrayList; 47 import java.util.Arrays; 48 import java.util.HashSet; 49 import java.util.List; 50 51 /** This class calls its monitor every minute. Killing this process if they don't return **/ 52 public class Watchdog extends Thread { 53 static final String TAG = "Watchdog"; 54 55 /** Debug flag. */ 56 public static final boolean DEBUG = false; 57 58 // Set this to true to use debug default values. 59 static final boolean DB = false; 60 61 // Note 1: Do not lower this value below thirty seconds without tightening the invoke-with 62 // timeout in com.android.internal.os.ZygoteConnection, or wrapped applications 63 // can trigger the watchdog. 64 // Note 2: The debug value is already below the wait time in ZygoteConnection. Wrapped 65 // applications may not work with a debug build. CTS will fail. 66 static final long DEFAULT_TIMEOUT = DB ? 10*1000 : 60*1000; 67 static final long CHECK_INTERVAL = DEFAULT_TIMEOUT / 2; 68 69 // These are temporally ordered: larger values as lateness increases 70 static final int COMPLETED = 0; 71 static final int WAITING = 1; 72 static final int WAITED_HALF = 2; 73 static final int OVERDUE = 3; 74 75 // Which native processes to dump into dropbox's stack traces 76 public static final String[] NATIVE_STACKS_OF_INTEREST = new String[] { 77 "/system/bin/audioserver", 78 "/system/bin/cameraserver", 79 "/system/bin/drmserver", 80 "/system/bin/mediadrmserver", 81 "/system/bin/mediaserver", 82 "/system/bin/netd", 83 "/system/bin/sdcard", 84 "/system/bin/surfaceflinger", 85 "/system/bin/vold", 86 "media.extractor", // system/bin/mediaextractor 87 "media.metrics", // system/bin/mediametrics 88 "media.codec", // vendor/bin/hw/android.hardware.media.omx@1.0-service 89 "media.swcodec", // /apex/com.android.media.swcodec/bin/mediaswcodec 90 "com.android.bluetooth", // Bluetooth service 91 "/system/bin/statsd", // Stats daemon 92 }; 93 94 public static final List<String> HAL_INTERFACES_OF_INTEREST = Arrays.asList( 95 "android.hardware.audio@2.0::IDevicesFactory", 96 "android.hardware.audio@4.0::IDevicesFactory", 97 "android.hardware.audio@5.0::IDevicesFactory", 98 "android.hardware.audio@6.0::IDevicesFactory", 99 "android.hardware.biometrics.face@1.0::IBiometricsFace", 100 "android.hardware.bluetooth@1.0::IBluetoothHci", 101 "android.hardware.camera.provider@2.4::ICameraProvider", 102 "android.hardware.graphics.allocator@2.0::IAllocator", 103 "android.hardware.graphics.composer@2.1::IComposer", 104 "android.hardware.health@2.0::IHealth", 105 "android.hardware.media.c2@1.0::IComponentStore", 106 "android.hardware.media.omx@1.0::IOmx", 107 "android.hardware.media.omx@1.0::IOmxStore", 108 "android.hardware.neuralnetworks@1.0::IDevice", 109 "android.hardware.power.stats@1.0::IPowerStats", 110 "android.hardware.sensors@1.0::ISensors", 111 "android.hardware.vr@1.0::IVr", 112 "android.system.suspend@1.0::ISystemSuspend" 113 ); 114 115 static Watchdog sWatchdog; 116 117 /* This handler will be used to post message back onto the main thread */ 118 final ArrayList<HandlerChecker> mHandlerCheckers = new ArrayList<>(); 119 final HandlerChecker mMonitorChecker; 120 ActivityManagerService mActivity; 121 122 int mPhonePid; 123 IActivityController mController; 124 boolean mAllowRestart = true; 125 126 /** 127 * Used for checking status of handle threads and scheduling monitor callbacks. 128 */ 129 public final class HandlerChecker implements Runnable { 130 private final Handler mHandler; 131 private final String mName; 132 private final long mWaitMax; 133 private final ArrayList<Monitor> mMonitors = new ArrayList<Monitor>(); 134 private final ArrayList<Monitor> mMonitorQueue = new ArrayList<Monitor>(); 135 private boolean mCompleted; 136 private Monitor mCurrentMonitor; 137 private long mStartTime; 138 private int mPauseCount; 139 HandlerChecker(Handler handler, String name, long waitMaxMillis)140 HandlerChecker(Handler handler, String name, long waitMaxMillis) { 141 mHandler = handler; 142 mName = name; 143 mWaitMax = waitMaxMillis; 144 mCompleted = true; 145 } 146 addMonitorLocked(Monitor monitor)147 void addMonitorLocked(Monitor monitor) { 148 // We don't want to update mMonitors when the Handler is in the middle of checking 149 // all monitors. We will update mMonitors on the next schedule if it is safe 150 mMonitorQueue.add(monitor); 151 } 152 scheduleCheckLocked()153 public void scheduleCheckLocked() { 154 if (mCompleted) { 155 // Safe to update monitors in queue, Handler is not in the middle of work 156 mMonitors.addAll(mMonitorQueue); 157 mMonitorQueue.clear(); 158 } 159 if ((mMonitors.size() == 0 && mHandler.getLooper().getQueue().isPolling()) 160 || (mPauseCount > 0)) { 161 // Don't schedule until after resume OR 162 // If the target looper has recently been polling, then 163 // there is no reason to enqueue our checker on it since that 164 // is as good as it not being deadlocked. This avoid having 165 // to do a context switch to check the thread. Note that we 166 // only do this if we have no monitors since those would need to 167 // be executed at this point. 168 mCompleted = true; 169 return; 170 } 171 if (!mCompleted) { 172 // we already have a check in flight, so no need 173 return; 174 } 175 176 mCompleted = false; 177 mCurrentMonitor = null; 178 mStartTime = SystemClock.uptimeMillis(); 179 mHandler.postAtFrontOfQueue(this); 180 } 181 isOverdueLocked()182 boolean isOverdueLocked() { 183 return (!mCompleted) && (SystemClock.uptimeMillis() > mStartTime + mWaitMax); 184 } 185 getCompletionStateLocked()186 public int getCompletionStateLocked() { 187 if (mCompleted) { 188 return COMPLETED; 189 } else { 190 long latency = SystemClock.uptimeMillis() - mStartTime; 191 if (latency < mWaitMax/2) { 192 return WAITING; 193 } else if (latency < mWaitMax) { 194 return WAITED_HALF; 195 } 196 } 197 return OVERDUE; 198 } 199 getThread()200 public Thread getThread() { 201 return mHandler.getLooper().getThread(); 202 } 203 getName()204 public String getName() { 205 return mName; 206 } 207 describeBlockedStateLocked()208 String describeBlockedStateLocked() { 209 if (mCurrentMonitor == null) { 210 return "Blocked in handler on " + mName + " (" + getThread().getName() + ")"; 211 } else { 212 return "Blocked in monitor " + mCurrentMonitor.getClass().getName() 213 + " on " + mName + " (" + getThread().getName() + ")"; 214 } 215 } 216 217 @Override run()218 public void run() { 219 // Once we get here, we ensure that mMonitors does not change even if we call 220 // #addMonitorLocked because we first add the new monitors to mMonitorQueue and 221 // move them to mMonitors on the next schedule when mCompleted is true, at which 222 // point we have completed execution of this method. 223 final int size = mMonitors.size(); 224 for (int i = 0 ; i < size ; i++) { 225 synchronized (Watchdog.this) { 226 mCurrentMonitor = mMonitors.get(i); 227 } 228 mCurrentMonitor.monitor(); 229 } 230 231 synchronized (Watchdog.this) { 232 mCompleted = true; 233 mCurrentMonitor = null; 234 } 235 } 236 237 /** Pause the HandlerChecker. */ pauseLocked(String reason)238 public void pauseLocked(String reason) { 239 mPauseCount++; 240 // Mark as completed, because there's a chance we called this after the watchog 241 // thread loop called Object#wait after 'WAITED_HALF'. In that case we want to ensure 242 // the next call to #getCompletionStateLocked for this checker returns 'COMPLETED' 243 mCompleted = true; 244 Slog.i(TAG, "Pausing HandlerChecker: " + mName + " for reason: " 245 + reason + ". Pause count: " + mPauseCount); 246 } 247 248 /** Resume the HandlerChecker from the last {@link #pauseLocked}. */ resumeLocked(String reason)249 public void resumeLocked(String reason) { 250 if (mPauseCount > 0) { 251 mPauseCount--; 252 Slog.i(TAG, "Resuming HandlerChecker: " + mName + " for reason: " 253 + reason + ". Pause count: " + mPauseCount); 254 } else { 255 Slog.wtf(TAG, "Already resumed HandlerChecker: " + mName); 256 } 257 } 258 } 259 260 final class RebootRequestReceiver extends BroadcastReceiver { 261 @Override onReceive(Context c, Intent intent)262 public void onReceive(Context c, Intent intent) { 263 if (intent.getIntExtra("nowait", 0) != 0) { 264 rebootSystem("Received ACTION_REBOOT broadcast"); 265 return; 266 } 267 Slog.w(TAG, "Unsupported ACTION_REBOOT broadcast: " + intent); 268 } 269 } 270 271 /** Monitor for checking the availability of binder threads. The monitor will block until 272 * there is a binder thread available to process in coming IPCs to make sure other processes 273 * can still communicate with the service. 274 */ 275 private static final class BinderThreadMonitor implements Watchdog.Monitor { 276 @Override monitor()277 public void monitor() { 278 Binder.blockUntilThreadAvailable(); 279 } 280 } 281 282 public interface Monitor { monitor()283 void monitor(); 284 } 285 getInstance()286 public static Watchdog getInstance() { 287 if (sWatchdog == null) { 288 sWatchdog = new Watchdog(); 289 } 290 291 return sWatchdog; 292 } 293 Watchdog()294 private Watchdog() { 295 super("watchdog"); 296 // Initialize handler checkers for each common thread we want to check. Note 297 // that we are not currently checking the background thread, since it can 298 // potentially hold longer running operations with no guarantees about the timeliness 299 // of operations there. 300 301 // The shared foreground thread is the main checker. It is where we 302 // will also dispatch monitor checks and do other work. 303 mMonitorChecker = new HandlerChecker(FgThread.getHandler(), 304 "foreground thread", DEFAULT_TIMEOUT); 305 mHandlerCheckers.add(mMonitorChecker); 306 // Add checker for main thread. We only do a quick check since there 307 // can be UI running on the thread. 308 mHandlerCheckers.add(new HandlerChecker(new Handler(Looper.getMainLooper()), 309 "main thread", DEFAULT_TIMEOUT)); 310 // Add checker for shared UI thread. 311 mHandlerCheckers.add(new HandlerChecker(UiThread.getHandler(), 312 "ui thread", DEFAULT_TIMEOUT)); 313 // And also check IO thread. 314 mHandlerCheckers.add(new HandlerChecker(IoThread.getHandler(), 315 "i/o thread", DEFAULT_TIMEOUT)); 316 // And the display thread. 317 mHandlerCheckers.add(new HandlerChecker(DisplayThread.getHandler(), 318 "display thread", DEFAULT_TIMEOUT)); 319 // And the animation thread. 320 mHandlerCheckers.add(new HandlerChecker(AnimationThread.getHandler(), 321 "animation thread", DEFAULT_TIMEOUT)); 322 // And the surface animation thread. 323 mHandlerCheckers.add(new HandlerChecker(SurfaceAnimationThread.getHandler(), 324 "surface animation thread", DEFAULT_TIMEOUT)); 325 326 // Initialize monitor for Binder threads. 327 addMonitor(new BinderThreadMonitor()); 328 329 // See the notes on DEFAULT_TIMEOUT. 330 assert DB || 331 DEFAULT_TIMEOUT > ZygoteConnectionConstants.WRAPPED_PID_TIMEOUT_MILLIS; 332 } 333 334 /** 335 * Registers a {@link BroadcastReceiver} to listen to reboot broadcasts and trigger reboot. 336 * Should be called during boot after the ActivityManagerService is up and registered 337 * as a system service so it can handle registration of a {@link BroadcastReceiver}. 338 */ init(Context context, ActivityManagerService activity)339 public void init(Context context, ActivityManagerService activity) { 340 mActivity = activity; 341 context.registerReceiver(new RebootRequestReceiver(), 342 new IntentFilter(Intent.ACTION_REBOOT), 343 android.Manifest.permission.REBOOT, null); 344 } 345 processStarted(String name, int pid)346 public void processStarted(String name, int pid) { 347 synchronized (this) { 348 if ("com.android.phone".equals(name)) { 349 mPhonePid = pid; 350 } 351 } 352 } 353 setActivityController(IActivityController controller)354 public void setActivityController(IActivityController controller) { 355 synchronized (this) { 356 mController = controller; 357 } 358 } 359 setAllowRestart(boolean allowRestart)360 public void setAllowRestart(boolean allowRestart) { 361 synchronized (this) { 362 mAllowRestart = allowRestart; 363 } 364 } 365 addMonitor(Monitor monitor)366 public void addMonitor(Monitor monitor) { 367 synchronized (this) { 368 mMonitorChecker.addMonitorLocked(monitor); 369 } 370 } 371 addThread(Handler thread)372 public void addThread(Handler thread) { 373 addThread(thread, DEFAULT_TIMEOUT); 374 } 375 addThread(Handler thread, long timeoutMillis)376 public void addThread(Handler thread, long timeoutMillis) { 377 synchronized (this) { 378 final String name = thread.getLooper().getThread().getName(); 379 mHandlerCheckers.add(new HandlerChecker(thread, name, timeoutMillis)); 380 } 381 } 382 383 /** 384 * Pauses Watchdog action for the currently running thread. Useful before executing long running 385 * operations that could falsely trigger the watchdog. Each call to this will require a matching 386 * call to {@link #resumeWatchingCurrentThread}. 387 * 388 * <p>If the current thread has not been added to the Watchdog, this call is a no-op. 389 * 390 * <p>If the Watchdog is already paused for the current thread, this call adds 391 * adds another pause and will require an additional {@link #resumeCurrentThread} to resume. 392 * 393 * <p>Note: Use with care, as any deadlocks on the current thread will be undetected until all 394 * pauses have been resumed. 395 */ pauseWatchingCurrentThread(String reason)396 public void pauseWatchingCurrentThread(String reason) { 397 synchronized (this) { 398 for (HandlerChecker hc : mHandlerCheckers) { 399 if (Thread.currentThread().equals(hc.getThread())) { 400 hc.pauseLocked(reason); 401 } 402 } 403 } 404 } 405 406 /** 407 * Resumes the last pause from {@link #pauseWatchingCurrentThread} for the currently running 408 * thread. 409 * 410 * <p>If the current thread has not been added to the Watchdog, this call is a no-op. 411 * 412 * <p>If the Watchdog action for the current thread is already resumed, this call logs a wtf. 413 * 414 * <p>If all pauses have been resumed, the Watchdog action is finally resumed, otherwise, 415 * the Watchdog action for the current thread remains paused until resume is called at least 416 * as many times as the calls to pause. 417 */ resumeWatchingCurrentThread(String reason)418 public void resumeWatchingCurrentThread(String reason) { 419 synchronized (this) { 420 for (HandlerChecker hc : mHandlerCheckers) { 421 if (Thread.currentThread().equals(hc.getThread())) { 422 hc.resumeLocked(reason); 423 } 424 } 425 } 426 } 427 428 /** 429 * Perform a full reboot of the system. 430 */ rebootSystem(String reason)431 void rebootSystem(String reason) { 432 Slog.i(TAG, "Rebooting system because: " + reason); 433 IPowerManager pms = (IPowerManager)ServiceManager.getService(Context.POWER_SERVICE); 434 try { 435 pms.reboot(false, reason, false); 436 } catch (RemoteException ex) { 437 } 438 } 439 evaluateCheckerCompletionLocked()440 private int evaluateCheckerCompletionLocked() { 441 int state = COMPLETED; 442 for (int i=0; i<mHandlerCheckers.size(); i++) { 443 HandlerChecker hc = mHandlerCheckers.get(i); 444 state = Math.max(state, hc.getCompletionStateLocked()); 445 } 446 return state; 447 } 448 getBlockedCheckersLocked()449 private ArrayList<HandlerChecker> getBlockedCheckersLocked() { 450 ArrayList<HandlerChecker> checkers = new ArrayList<HandlerChecker>(); 451 for (int i=0; i<mHandlerCheckers.size(); i++) { 452 HandlerChecker hc = mHandlerCheckers.get(i); 453 if (hc.isOverdueLocked()) { 454 checkers.add(hc); 455 } 456 } 457 return checkers; 458 } 459 describeCheckersLocked(List<HandlerChecker> checkers)460 private String describeCheckersLocked(List<HandlerChecker> checkers) { 461 StringBuilder builder = new StringBuilder(128); 462 for (int i=0; i<checkers.size(); i++) { 463 if (builder.length() > 0) { 464 builder.append(", "); 465 } 466 builder.append(checkers.get(i).describeBlockedStateLocked()); 467 } 468 return builder.toString(); 469 } 470 getInterestingHalPids()471 private static ArrayList<Integer> getInterestingHalPids() { 472 try { 473 IServiceManager serviceManager = IServiceManager.getService(); 474 ArrayList<IServiceManager.InstanceDebugInfo> dump = 475 serviceManager.debugDump(); 476 HashSet<Integer> pids = new HashSet<>(); 477 for (IServiceManager.InstanceDebugInfo info : dump) { 478 if (info.pid == IServiceManager.PidConstant.NO_PID) { 479 continue; 480 } 481 482 if (!HAL_INTERFACES_OF_INTEREST.contains(info.interfaceName)) { 483 continue; 484 } 485 486 pids.add(info.pid); 487 } 488 return new ArrayList<Integer>(pids); 489 } catch (RemoteException e) { 490 return new ArrayList<Integer>(); 491 } 492 } 493 getInterestingNativePids()494 static ArrayList<Integer> getInterestingNativePids() { 495 ArrayList<Integer> pids = getInterestingHalPids(); 496 497 int[] nativePids = Process.getPidsForCommands(NATIVE_STACKS_OF_INTEREST); 498 if (nativePids != null) { 499 pids.ensureCapacity(pids.size() + nativePids.length); 500 for (int i : nativePids) { 501 pids.add(i); 502 } 503 } 504 505 return pids; 506 } 507 508 @Override run()509 public void run() { 510 boolean waitedHalf = false; 511 while (true) { 512 final List<HandlerChecker> blockedCheckers; 513 final String subject; 514 final boolean allowRestart; 515 int debuggerWasConnected = 0; 516 synchronized (this) { 517 long timeout = CHECK_INTERVAL; 518 // Make sure we (re)spin the checkers that have become idle within 519 // this wait-and-check interval 520 for (int i=0; i<mHandlerCheckers.size(); i++) { 521 HandlerChecker hc = mHandlerCheckers.get(i); 522 hc.scheduleCheckLocked(); 523 } 524 525 if (debuggerWasConnected > 0) { 526 debuggerWasConnected--; 527 } 528 529 // NOTE: We use uptimeMillis() here because we do not want to increment the time we 530 // wait while asleep. If the device is asleep then the thing that we are waiting 531 // to timeout on is asleep as well and won't have a chance to run, causing a false 532 // positive on when to kill things. 533 long start = SystemClock.uptimeMillis(); 534 while (timeout > 0) { 535 if (Debug.isDebuggerConnected()) { 536 debuggerWasConnected = 2; 537 } 538 try { 539 wait(timeout); 540 // Note: mHandlerCheckers and mMonitorChecker may have changed after waiting 541 } catch (InterruptedException e) { 542 Log.wtf(TAG, e); 543 } 544 if (Debug.isDebuggerConnected()) { 545 debuggerWasConnected = 2; 546 } 547 timeout = CHECK_INTERVAL - (SystemClock.uptimeMillis() - start); 548 } 549 550 final int waitState = evaluateCheckerCompletionLocked(); 551 if (waitState == COMPLETED) { 552 // The monitors have returned; reset 553 waitedHalf = false; 554 continue; 555 } else if (waitState == WAITING) { 556 // still waiting but within their configured intervals; back off and recheck 557 continue; 558 } else if (waitState == WAITED_HALF) { 559 if (!waitedHalf) { 560 Slog.i(TAG, "WAITED_HALF"); 561 // We've waited half the deadlock-detection interval. Pull a stack 562 // trace and wait another half. 563 ArrayList<Integer> pids = new ArrayList<Integer>(); 564 pids.add(Process.myPid()); 565 ActivityManagerService.dumpStackTraces(pids, null, null, 566 getInterestingNativePids()); 567 waitedHalf = true; 568 } 569 continue; 570 } 571 572 // something is overdue! 573 blockedCheckers = getBlockedCheckersLocked(); 574 subject = describeCheckersLocked(blockedCheckers); 575 allowRestart = mAllowRestart; 576 } 577 578 // If we got here, that means that the system is most likely hung. 579 // First collect stack traces from all threads of the system process. 580 // Then kill this process so that the system will restart. 581 EventLog.writeEvent(EventLogTags.WATCHDOG, subject); 582 583 ArrayList<Integer> pids = new ArrayList<>(); 584 pids.add(Process.myPid()); 585 if (mPhonePid > 0) pids.add(mPhonePid); 586 587 final File stack = ActivityManagerService.dumpStackTraces( 588 pids, null, null, getInterestingNativePids()); 589 590 // Give some extra time to make sure the stack traces get written. 591 // The system's been hanging for a minute, another second or two won't hurt much. 592 SystemClock.sleep(5000); 593 594 // Trigger the kernel to dump all blocked threads, and backtraces on all CPUs to the kernel log 595 doSysRq('w'); 596 doSysRq('l'); 597 598 // Try to add the error to the dropbox, but assuming that the ActivityManager 599 // itself may be deadlocked. (which has happened, causing this statement to 600 // deadlock and the watchdog as a whole to be ineffective) 601 Thread dropboxThread = new Thread("watchdogWriteToDropbox") { 602 public void run() { 603 // If a watched thread hangs before init() is called, we don't have a 604 // valid mActivity. So we can't log the error to dropbox. 605 if (mActivity != null) { 606 mActivity.addErrorToDropBox( 607 "watchdog", null, "system_server", null, null, null, 608 subject, null, stack, null); 609 } 610 StatsLog.write(StatsLog.SYSTEM_SERVER_WATCHDOG_OCCURRED, subject); 611 } 612 }; 613 dropboxThread.start(); 614 try { 615 dropboxThread.join(2000); // wait up to 2 seconds for it to return. 616 } catch (InterruptedException ignored) {} 617 618 IActivityController controller; 619 synchronized (this) { 620 controller = mController; 621 } 622 if (controller != null) { 623 Slog.i(TAG, "Reporting stuck state to activity controller"); 624 try { 625 Binder.setDumpDisabled("Service dumps disabled due to hung system process."); 626 // 1 = keep waiting, -1 = kill system 627 int res = controller.systemNotResponding(subject); 628 if (res >= 0) { 629 Slog.i(TAG, "Activity controller requested to coninue to wait"); 630 waitedHalf = false; 631 continue; 632 } 633 } catch (RemoteException e) { 634 } 635 } 636 637 // Only kill the process if the debugger is not attached. 638 if (Debug.isDebuggerConnected()) { 639 debuggerWasConnected = 2; 640 } 641 if (debuggerWasConnected >= 2) { 642 Slog.w(TAG, "Debugger connected: Watchdog is *not* killing the system process"); 643 } else if (debuggerWasConnected > 0) { 644 Slog.w(TAG, "Debugger was connected: Watchdog is *not* killing the system process"); 645 } else if (!allowRestart) { 646 Slog.w(TAG, "Restart not allowed: Watchdog is *not* killing the system process"); 647 } else { 648 Slog.w(TAG, "*** WATCHDOG KILLING SYSTEM PROCESS: " + subject); 649 WatchdogDiagnostics.diagnoseCheckers(blockedCheckers); 650 Slog.w(TAG, "*** GOODBYE!"); 651 Process.killProcess(Process.myPid()); 652 System.exit(10); 653 } 654 655 waitedHalf = false; 656 } 657 } 658 doSysRq(char c)659 private void doSysRq(char c) { 660 try { 661 FileWriter sysrq_trigger = new FileWriter("/proc/sysrq-trigger"); 662 sysrq_trigger.write(c); 663 sysrq_trigger.close(); 664 } catch (IOException e) { 665 Slog.w(TAG, "Failed to write to /proc/sysrq-trigger", e); 666 } 667 } 668 } 669