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