Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2529f65e authored by Narayan Kamath's avatar Narayan Kamath Committed by Gerrit Code Review
Browse files

Merge "Improvements to ActivityManagerService stack dumping"

parents 3a8ad81a 0f2c1c3f
Loading
Loading
Loading
Loading
+54 −34
Original line number Diff line number Diff line
@@ -5324,37 +5324,63 @@ public final class ActivityManagerService extends ActivityManagerNative
        return tracesFile;
    }
    public static class DumpStackFileObserver extends FileObserver {
        // Keep in sync with frameworks/native/cmds/dumpstate/utils.cpp
        private static final int TRACE_DUMP_TIMEOUT_MS = 10000; // 10 seconds
        static final int TRACE_DUMP_TIMEOUT_SECONDS = TRACE_DUMP_TIMEOUT_MS / 1000;
        private final String mTracesPath;
        private boolean mClosed;
        public DumpStackFileObserver(String tracesPath) {
            super(tracesPath, FileObserver.CLOSE_WRITE);
            mTracesPath = tracesPath;
        }
        @Override
        public synchronized void onEvent(int event, String path) {
            mClosed = true;
            notify();
        }
        public void dumpWithTimeout(int pid) {
            Process.sendSignal(pid, Process.SIGNAL_QUIT);
            synchronized (this) {
                try {
                    wait(TRACE_DUMP_TIMEOUT_MS); // Wait for traces file to be closed.
                } catch (InterruptedException e) {
                    Slog.wtf(TAG, e);
                }
            }
            if (!mClosed) {
                Slog.w(TAG, "Didn't see close of " + mTracesPath + " for pid " + pid +
                       ". Attempting native stack collection.");
                Debug.dumpNativeBacktraceToFileTimeout(pid, mTracesPath, TRACE_DUMP_TIMEOUT_SECONDS);
            }
            mClosed = false;
        }
    }
    private static void dumpStackTraces(String tracesPath, ArrayList<Integer> firstPids,
            ProcessCpuTracker processCpuTracker, SparseArray<Boolean> lastPids, String[] nativeProcs) {
        // Use a FileObserver to detect when traces finish writing.
        // The order of traces is considered important to maintain for legibility.
        FileObserver observer = new FileObserver(tracesPath, FileObserver.CLOSE_WRITE) {
            @Override
            public synchronized void onEvent(int event, String path) { notify(); }
        };
        DumpStackFileObserver observer = new DumpStackFileObserver(tracesPath);
        try {
            observer.startWatching();
            // First collect all of the stacks of the most important pids.
            if (firstPids != null) {
                try {
                int num = firstPids.size();
                for (int i = 0; i < num; i++) {
                        synchronized (observer) {
                    if (DEBUG_ANR) Slog.d(TAG, "Collecting stacks for pid "
                            + firstPids.get(i));
                    final long sime = SystemClock.elapsedRealtime();
                            Process.sendSignal(firstPids.get(i), Process.SIGNAL_QUIT);
                            observer.wait(1000);  // Wait for write-close, give up after 1 sec
                    observer.dumpWithTimeout(firstPids.get(i));
                    if (DEBUG_ANR) Slog.d(TAG, "Done with pid " + firstPids.get(i)
                            + " in " + (SystemClock.elapsedRealtime()-sime) + "ms");
                }
            }
                } catch (InterruptedException e) {
                    Slog.wtf(TAG, e);
                }
            }
            // Next collect the stacks of the native pids
            if (nativeProcs != null) {
@@ -5364,7 +5390,8 @@ public final class ActivityManagerService extends ActivityManagerNative
                        if (DEBUG_ANR) Slog.d(TAG, "Collecting stacks for native pid " + pid);
                        final long sime = SystemClock.elapsedRealtime();
                        Debug.dumpNativeBacktraceToFileTimeout(pid, tracesPath, 10);
                        Debug.dumpNativeBacktraceToFileTimeout(
                                pid, tracesPath, DumpStackFileObserver.TRACE_DUMP_TIMEOUT_SECONDS);
                        if (DEBUG_ANR) Slog.d(TAG, "Done with native pid " + pid
                                + " in " + (SystemClock.elapsedRealtime()-sime) + "ms");
                    }
@@ -5391,19 +5418,12 @@ public final class ActivityManagerService extends ActivityManagerNative
                    ProcessCpuTracker.Stats stats = processCpuTracker.getWorkingStats(i);
                    if (lastPids.indexOfKey(stats.pid) >= 0) {
                        numProcs++;
                        try {
                            synchronized (observer) {
                        if (DEBUG_ANR) Slog.d(TAG, "Collecting stacks for extra pid "
                                + stats.pid);
                        final long stime = SystemClock.elapsedRealtime();
                                Process.sendSignal(stats.pid, Process.SIGNAL_QUIT);
                                observer.wait(1000);  // Wait for write-close, give up after 1 sec
                        observer.dumpWithTimeout(stats.pid);
                        if (DEBUG_ANR) Slog.d(TAG, "Done with extra pid " + stats.pid
                                + " in " + (SystemClock.elapsedRealtime()-stime) + "ms");
                            }
                        } catch (InterruptedException e) {
                            Slog.wtf(TAG, e);
                        }
                    } else if (DEBUG_ANR) {
                        Slog.d(TAG, "Skipping next CPU consuming process, not a java proc: "
                                + stats.pid);