Search in sources :

Example 11 with IActivityController

use of android.app.IActivityController in project android_frameworks_base by crdroidandroid.

the class Watchdog method run.

@Override
public void run() {
    boolean waitedHalf = false;
    while (true) {
        final ArrayList<HandlerChecker> blockedCheckers;
        final String subject;
        final boolean allowRestart;
        int debuggerWasConnected = 0;
        synchronized (this) {
            long timeout = CHECK_INTERVAL;
            // this wait-and-check interval
            for (int i = 0; i < mHandlerCheckers.size(); i++) {
                HandlerChecker hc = mHandlerCheckers.get(i);
                hc.scheduleCheckLocked();
            }
            if (debuggerWasConnected > 0) {
                debuggerWasConnected--;
            }
            // 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
            // positive on when to kill things.
            long start = SystemClock.uptimeMillis();
            while (timeout > 0) {
                if (Debug.isDebuggerConnected()) {
                    debuggerWasConnected = 2;
                }
                try {
                    wait(timeout);
                } catch (InterruptedException e) {
                    Log.wtf(TAG, e);
                }
                if (Debug.isDebuggerConnected()) {
                    debuggerWasConnected = 2;
                }
                timeout = CHECK_INTERVAL - (SystemClock.uptimeMillis() - start);
            }
            final int waitState = evaluateCheckerCompletionLocked();
            if (waitState == COMPLETED) {
                // The monitors have returned; reset
                waitedHalf = false;
                continue;
            } else if (waitState == WAITING) {
                // still waiting but within their configured intervals; back off and recheck
                continue;
            } else if (waitState == WAITED_HALF) {
                if (!waitedHalf) {
                    // We've waited half the deadlock-detection interval.  Pull a stack
                    // trace and wait another half.
                    ArrayList<Integer> pids = new ArrayList<Integer>();
                    pids.add(Process.myPid());
                    ActivityManagerService.dumpStackTraces(true, pids, null, null, NATIVE_STACKS_OF_INTEREST);
                    waitedHalf = true;
                }
                continue;
            }
            // something is overdue!
            blockedCheckers = getBlockedCheckersLocked();
            subject = describeCheckersLocked(blockedCheckers);
            allowRestart = mAllowRestart;
        }
        // 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.
        EventLog.writeEvent(EventLogTags.WATCHDOG, subject);
        ArrayList<Integer> pids = new ArrayList<Integer>();
        pids.add(Process.myPid());
        if (mPhonePid > 0)
            pids.add(mPhonePid);
        // 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.
        final File stack = ActivityManagerService.dumpStackTraces(!waitedHalf, pids, null, null, NATIVE_STACKS_OF_INTEREST);
        // 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.
        SystemClock.sleep(2000);
        // Pull our own kernel thread stacks as well if we're configured for that
        if (RECORD_KERNEL_THREADS) {
            dumpKernelStackTraces();
        }
        String tracesPath = SystemProperties.get("dalvik.vm.stack-trace-file", null);
        String traceFileNameAmendment = "_SystemServer_WDT" + mTraceDateFormat.format(new Date());
        if (tracesPath != null && tracesPath.length() != 0) {
            File traceRenameFile = new File(tracesPath);
            String newTracesPath;
            int lpos = tracesPath.lastIndexOf(".");
            if (-1 != lpos)
                newTracesPath = tracesPath.substring(0, lpos) + traceFileNameAmendment + tracesPath.substring(lpos);
            else
                newTracesPath = tracesPath + traceFileNameAmendment;
            traceRenameFile.renameTo(new File(newTracesPath));
            tracesPath = newTracesPath;
        }
        final File newFd = new File(tracesPath);
        // Try to add the error to the dropbox, but assuming that the ActivityManager
        // itself may be deadlocked.  (which has happened, causing this statement to
        // deadlock and the watchdog as a whole to be ineffective)
        Thread dropboxThread = new Thread("watchdogWriteToDropbox") {

            public void run() {
                mActivity.addErrorToDropBox("watchdog", null, "system_server", null, null, subject, null, newFd, null);
            }
        };
        dropboxThread.start();
        try {
            // wait up to 2 seconds for it to return.
            dropboxThread.join(2000);
        } catch (InterruptedException ignored) {
        }
        // At times, when user space watchdog traces don't give an indication on
        // which component held a lock, because of which other threads are blocked,
        // (thereby causing Watchdog), crash the device to analyze RAM dumps
        boolean crashOnWatchdog = SystemProperties.getBoolean("persist.sys.crashOnWatchdog", false);
        if (crashOnWatchdog) {
            // Trigger the kernel to dump all blocked threads, and backtraces
            // on all CPUs to the kernel log
            Slog.e(TAG, "Triggering SysRq for system_server watchdog");
            doSysRq('w');
            doSysRq('l');
            // wait until the above blocked threads be dumped into kernel log
            SystemClock.sleep(3000);
            // now try to crash the target
            doSysRq('c');
        }
        IActivityController controller;
        synchronized (this) {
            controller = mController;
        }
        if (controller != null) {
            Slog.i(TAG, "Reporting stuck state to activity controller");
            Binder.setDumpDisabled("Service dumps disabled due to hung system process.");
            // 1 = keep waiting, -1 = kill system
            int res = getSystemNotRespondingAction(controller, subject);
            if (res >= 0) {
                Slog.i(TAG, "Activity controller requested to coninue to wait");
                waitedHalf = false;
                continue;
            }
        }
        // Only kill the process if the debugger is not attached.
        if (Debug.isDebuggerConnected()) {
            debuggerWasConnected = 2;
        }
        if (debuggerWasConnected >= 2) {
            Slog.w(TAG, "Debugger connected: Watchdog is *not* killing the system process");
        } else if (debuggerWasConnected > 0) {
            Slog.w(TAG, "Debugger was connected: Watchdog is *not* killing the system process");
        } else if (!allowRestart) {
            Slog.w(TAG, "Restart not allowed: Watchdog is *not* killing the system process");
        } else {
            Slog.w(TAG, "*** WATCHDOG KILLING SYSTEM PROCESS: " + subject);
            for (int i = 0; i < blockedCheckers.size(); i++) {
                Slog.w(TAG, blockedCheckers.get(i).getName() + " stack trace:");
                StackTraceElement[] stackTrace = blockedCheckers.get(i).getThread().getStackTrace();
                for (StackTraceElement element : stackTrace) {
                    Slog.w(TAG, "    at " + element);
                }
            }
            Slog.w(TAG, "*** GOODBYE!");
            Process.killProcess(Process.myPid());
            System.exit(10);
        }
        waitedHalf = false;
    }
}
Also used : ArrayList(java.util.ArrayList) Date(java.util.Date) IActivityController(android.app.IActivityController) File(java.io.File)

Aggregations

IActivityController (android.app.IActivityController)11 RemoteException (android.os.RemoteException)8 File (java.io.File)6 ArrayList (java.util.ArrayList)6 ComponentName (android.content.ComponentName)5 ActivityInfo (android.content.pm.ActivityInfo)5 Point (android.graphics.Point)5 Date (java.util.Date)3 FileWriter (java.io.FileWriter)1 IOException (java.io.IOException)1