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

Commit 9e9270ee authored by Narayan Kamath's avatar Narayan Kamath Committed by android-build-merger
Browse files

Merge "Improvements to ActivityManagerService stack dumping"

am: 2529f65e

Change-Id: Iabbf138719296a882aa98261fb2c4da8bbf027cc
parents a086824e 2529f65e
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);