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

Commit ffae1cb4 authored by Dianne Hackborn's avatar Dianne Hackborn
Browse files

Add activity manager command to watch uid state changes.

Also fix a few issues in uid reporting: active was being
reported multiple times when a process started, and idle
could be reported before the idle delay actually happened.

Test: manual, will be adding cts using the new cmd

Change-Id: I051b54145f3cabf72e757b0dcb1f0ef2e979b34e
parent d8aad5ac
Loading
Loading
Loading
Loading
+4 −4
Original line number Diff line number Diff line
@@ -6715,7 +6715,6 @@ public class ActivityManagerService extends IActivityManager.Stub
            mActiveUids.put(proc.uid, uidRec);
            EventLogTags.writeAmUidRunning(uidRec.uid);
            noteUidProcessState(uidRec.uid, uidRec.curProcState);
            enqueueUidChangeLocked(uidRec, -1, UidRecord.CHANGE_ACTIVE);
        }
        proc.uidRecord = uidRec;
@@ -22807,8 +22806,9 @@ public class ActivityManagerService extends IActivityManager.Stub
        for (int i=mActiveUids.size()-1; i>=0; i--) {
            final UidRecord uidRec = mActiveUids.valueAt(i);
            int uidChange = UidRecord.CHANGE_PROCSTATE;
            if (uidRec.setProcState != uidRec.curProcState
                    || uidRec.setWhitelist != uidRec.curWhitelist) {
            if (uidRec.curProcState != ActivityManager.PROCESS_STATE_NONEXISTENT
                    && (uidRec.setProcState != uidRec.curProcState
                           || uidRec.setWhitelist != uidRec.curWhitelist)) {
                if (DEBUG_UID_OBSERVERS) Slog.i(TAG_UID_OBSERVERS,
                        "Changes in " + uidRec + ": proc state from " + uidRec.setProcState
                        + " to " + uidRec.curProcState + ", whitelist from " + uidRec.setWhitelist
@@ -22829,7 +22829,7 @@ public class ActivityManagerService extends IActivityManager.Stub
                                    mConstants.BACKGROUND_SETTLE_TIME);
                        }
                    }
                    if (!uidRec.setIdle) {
                    if (uidRec.idle && !uidRec.setIdle) {
                        uidChange = UidRecord.CHANGE_IDLE;
                    }
                } else {
+140 −0
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@ import android.app.IActivityContainer;
import android.app.IActivityController;
import android.app.IActivityManager;
import android.app.IStopUserCallback;
import android.app.IUidObserver;
import android.app.ProfilerInfo;
import android.app.WaitResult;
import android.app.usage.ConfigurationStats;
@@ -184,6 +185,8 @@ final class ActivityManagerShellCommand extends ShellCommand {
                    return runMakeIdle(pw);
                case "monitor":
                    return runMonitor(pw);
                case "watch-uids":
                    return runWatchUids(pw);
                case "hang":
                    return runHang(pw);
                case "restart":
@@ -1290,6 +1293,141 @@ final class ActivityManagerShellCommand extends ShellCommand {
        return 0;
    }

    static final class MyUidObserver extends IUidObserver.Stub {
        final IActivityManager mInterface;
        final PrintWriter mPw;
        final InputStream mInput;

        static final int STATE_NORMAL = 0;

        int mState;

        MyUidObserver(IActivityManager iam, PrintWriter pw, InputStream input) {
            mInterface = iam;
            mPw = pw;
            mInput = input;
        }

        @Override
        public void onUidStateChanged(int uid, int procState, long procStateSeq) throws RemoteException {
            synchronized (this) {
                mPw.print(uid);
                mPw.print(" procstate ");
                mPw.print(ProcessList.makeProcStateString(procState));
                mPw.print(" seq ");
                mPw.println(procStateSeq);
                mPw.flush();
            }
        }

        @Override
        public void onUidGone(int uid, boolean disabled) throws RemoteException {
            synchronized (this) {
                mPw.print(uid);
                mPw.print(" gone");
                if (disabled) {
                    mPw.print(" disabled");
                }
                mPw.println();
                mPw.flush();
            }
        }

        @Override
        public void onUidActive(int uid) throws RemoteException {
            synchronized (this) {
                mPw.print(uid);
                mPw.println(" active");
                mPw.flush();
            }
        }

        @Override
        public void onUidIdle(int uid, boolean disabled) throws RemoteException {
            synchronized (this) {
                mPw.print(uid);
                mPw.print(" idle");
                if (disabled) {
                    mPw.print(" disabled");
                }
                mPw.println();
                mPw.flush();
            }
        }

        @Override
        public void onUidCachedChanged(int uid, boolean cached) throws RemoteException {
            synchronized (this) {
                mPw.print(uid);
                mPw.println(cached ? " cached" : " uncached");
                mPw.flush();
            }
        }

        void printMessageForState() {
            switch (mState) {
                case STATE_NORMAL:
                    mPw.println("Watching uid states...  available commands:");
                    break;
            }
            mPw.println("(q)uit: finish watching");
        }

        void run() throws RemoteException {
            try {
                printMessageForState();
                mPw.flush();

                mInterface.registerUidObserver(this, ActivityManager.UID_OBSERVER_ACTIVE
                        | ActivityManager.UID_OBSERVER_GONE | ActivityManager.UID_OBSERVER_PROCSTATE
                        | ActivityManager.UID_OBSERVER_IDLE | ActivityManager.UID_OBSERVER_CACHED,
                        ActivityManager.PROCESS_STATE_UNKNOWN, null);
                mState = STATE_NORMAL;

                InputStreamReader converter = new InputStreamReader(mInput);
                BufferedReader in = new BufferedReader(converter);
                String line;

                while ((line = in.readLine()) != null) {
                    boolean addNewline = true;
                    if (line.length() <= 0) {
                        addNewline = false;
                    } else if ("q".equals(line) || "quit".equals(line)) {
                        break;
                    } else {
                        mPw.println("Invalid command: " + line);
                    }

                    synchronized (this) {
                        if (addNewline) {
                            mPw.println("");
                        }
                        printMessageForState();
                        mPw.flush();
                    }
                }

            } catch (IOException e) {
                e.printStackTrace(mPw);
                mPw.flush();
            } finally {
                mInterface.unregisterUidObserver(this);
            }
        }
    }

    int runWatchUids(PrintWriter pw) throws RemoteException {
        String opt;
        while ((opt=getNextOption()) != null) {
            getErrPrintWriter().println("Error: Unknown option: " + opt);
            return -1;
        }

        MyUidObserver controller = new MyUidObserver(mInterface, pw, getRawInputStream());
        controller.run();
        return 0;
    }

    int runHang(PrintWriter pw) throws RemoteException {
        String opt;
        boolean allowRestart = false;
@@ -2595,6 +2733,8 @@ final class ActivityManagerShellCommand extends ShellCommand {
            pw.println("  monitor [--gdb <port>]");
            pw.println("      Start monitoring for crashes or ANRs.");
            pw.println("      --gdb: start gdbserv on the given port at crash/ANR");
            pw.println("  watch-uids [--gdb <port>]");
            pw.println("      Start watching for and reporting uid state changes.");
            pw.println("  hang [--allow-restart]");
            pw.println("      Hang the system.");
            pw.println("      --allow-restart: allow watchdog to perform normal system restart");