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

Commit 8885371b authored by Evan Severson's avatar Evan Severson
Browse files

Add event log for uid state tracker in dumpsys

This adds more debugging data for changes in uid state and results when
modes are evaluated against their uid states. The parameters increase
the total memory usage of AppOpsService by about 1% by adding about 9kb
of usage.

Test: Manual + check memory usage in heapdump
Bug: 241447638
Change-Id: I0cab94ba463b31aceab8f96cc1935d73d761a81c
parent b574e1c6
Loading
Loading
Loading
Loading
+10 −0
Original line number Original line Diff line number Diff line
@@ -5776,6 +5776,7 @@ public class AppOpsService extends IAppOpsService.Stub implements PersistenceSch
        boolean includeDiscreteOps = false;
        boolean includeDiscreteOps = false;
        int nDiscreteOps = 10;
        int nDiscreteOps = 10;
        @HistoricalOpsRequestFilter int dumpFilter = 0;
        @HistoricalOpsRequestFilter int dumpFilter = 0;
        boolean dumpAll = false;


        if (args != null) {
        if (args != null) {
            for (int i = 0; i < args.length; i++) {
            for (int i = 0; i < args.length; i++) {
@@ -5785,6 +5786,7 @@ public class AppOpsService extends IAppOpsService.Stub implements PersistenceSch
                    return;
                    return;
                } else if ("-a".equals(arg)) {
                } else if ("-a".equals(arg)) {
                    // dump all data
                    // dump all data
                    dumpAll = true;
                } else if ("--op".equals(arg)) {
                } else if ("--op".equals(arg)) {
                    i++;
                    i++;
                    if (i >= args.length) {
                    if (i >= args.length) {
@@ -6317,6 +6319,14 @@ public class AppOpsService extends IAppOpsService.Stub implements PersistenceSch
            mHistoricalRegistry.dumpDiscreteData(pw, dumpUid, dumpPackage, dumpAttributionTag,
            mHistoricalRegistry.dumpDiscreteData(pw, dumpUid, dumpPackage, dumpAttributionTag,
                    dumpFilter, dumpOp, sdf, date, "  ", nDiscreteOps);
                    dumpFilter, dumpOp, sdf, date, "  ", nDiscreteOps);
        }
        }

        if (dumpAll) {
            pw.println();
            pw.println("Uid State Changes Event Log:");
            if (mUidStateTracker != null) {
                mUidStateTracker.dumpEvents(pw);
            }
        }
    }
    }


    @Override
    @Override
+2 −0
Original line number Original line Diff line number Diff line
@@ -115,4 +115,6 @@ interface AppOpsUidStateTracker {
    }
    }


    void dumpUidState(PrintWriter pw, int uid, long nowElapsed);
    void dumpUidState(PrintWriter pw, int uid, long nowElapsed);

    void dumpEvents(PrintWriter pw);
}
}
+269 −1
Original line number Original line Diff line number Diff line
@@ -48,6 +48,7 @@ import com.android.internal.os.Clock;
import com.android.internal.util.function.pooled.PooledLambda;
import com.android.internal.util.function.pooled.PooledLambda;


import java.io.PrintWriter;
import java.io.PrintWriter;
import java.util.concurrent.CountDownLatch;


class AppOpsUidStateTrackerImpl implements AppOpsUidStateTracker {
class AppOpsUidStateTrackerImpl implements AppOpsUidStateTracker {


@@ -68,12 +69,16 @@ class AppOpsUidStateTrackerImpl implements AppOpsUidStateTracker {


    private ArrayMap<UidStateChangedCallback, Handler> mUidStateChangedCallbacks = new ArrayMap<>();
    private ArrayMap<UidStateChangedCallback, Handler> mUidStateChangedCallbacks = new ArrayMap<>();


    private final EventLog mEventLog;

    AppOpsUidStateTrackerImpl(ActivityManagerInternal activityManagerInternal,
    AppOpsUidStateTrackerImpl(ActivityManagerInternal activityManagerInternal,
            Handler handler, Clock clock, AppOpsService.Constants constants) {
            Handler handler, Clock clock, AppOpsService.Constants constants) {
        mActivityManagerInternal = activityManagerInternal;
        mActivityManagerInternal = activityManagerInternal;
        mHandler = handler;
        mHandler = handler;
        mClock = clock;
        mClock = clock;
        mConstants = constants;
        mConstants = constants;

        mEventLog = new EventLog(handler);
    }
    }


    @Override
    @Override
@@ -103,8 +108,10 @@ class AppOpsUidStateTrackerImpl implements AppOpsUidStateTracker {
        pendingTop = mActivityManagerInternal.isPendingTopUid(uid);
        pendingTop = mActivityManagerInternal.isPendingTopUid(uid);
        tempAllowlist = mActivityManagerInternal.isTempAllowlistedForFgsWhileInUse(uid);
        tempAllowlist = mActivityManagerInternal.isTempAllowlistedForFgsWhileInUse(uid);


        return evalMode(uidStateValue, code, mode, capability, visibleAppWidget, pendingTop,
        int result = evalMode(uidStateValue, code, mode, capability, visibleAppWidget, pendingTop,
                tempAllowlist);
                tempAllowlist);
        mEventLog.logEvalForegroundMode(uid, uidStateValue, capability, code, result);
        return result;
    }
    }


    private static int evalMode(int uidState, int code, int mode, int capability,
    private static int evalMode(int uidState, int code, int mode, int capability,
@@ -177,6 +184,7 @@ class AppOpsUidStateTrackerImpl implements AppOpsUidStateTracker {


    @Override
    @Override
    public void updateUidProcState(int uid, int procState, int capability) {
    public void updateUidProcState(int uid, int procState, int capability) {
        mEventLog.logUpdateUidProcState(uid, procState, capability);
        if (procState == PROCESS_STATE_NONEXISTENT) {
        if (procState == PROCESS_STATE_NONEXISTENT) {
            mUidStates.delete(uid);
            mUidStates.delete(uid);
            mPendingUidStates.delete(uid);
            mPendingUidStates.delete(uid);
@@ -271,6 +279,11 @@ class AppOpsUidStateTrackerImpl implements AppOpsUidStateTracker {
        }
        }
    }
    }


    @Override
    public void dumpEvents(PrintWriter pw) {
        mEventLog.dumpEvents(pw);
    }

    private void updateUidPendingStateIfNeeded(int uid) {
    private void updateUidPendingStateIfNeeded(int uid) {
        updateUidPendingStateIfNeededLocked(uid);
        updateUidPendingStateIfNeededLocked(uid);
    }
    }
@@ -303,6 +316,12 @@ class AppOpsUidStateTrackerImpl implements AppOpsUidStateTracker {
                    || capability != pendingCapability
                    || capability != pendingCapability
                    || visibleAppWidget != pendingVisibleAppWidget;
                    || visibleAppWidget != pendingVisibleAppWidget;


            if (foregroundChange) {
                // To save on memory usage, log only interesting changes.
                mEventLog.logCommitUidState(uid, pendingUidState, pendingCapability,
                        pendingVisibleAppWidget);
            }

            for (int i = 0; i < mUidStateChangedCallbacks.size(); i++) {
            for (int i = 0; i < mUidStateChangedCallbacks.size(); i++) {
                UidStateChangedCallback cb = mUidStateChangedCallbacks.keyAt(i);
                UidStateChangedCallback cb = mUidStateChangedCallbacks.keyAt(i);
                Handler h = mUidStateChangedCallbacks.valueAt(i);
                Handler h = mUidStateChangedCallbacks.valueAt(i);
@@ -329,4 +348,253 @@ class AppOpsUidStateTrackerImpl implements AppOpsUidStateTracker {
    private boolean getUidVisibleAppWidget(int uid) {
    private boolean getUidVisibleAppWidget(int uid) {
        return mVisibleAppWidget.get(uid, false);
        return mVisibleAppWidget.get(uid, false);
    }
    }

    private static class EventLog {

        // These seems a bit too verbose and not as useful, turning off for now.
        // DCE should be able to remove most associated code.
        // Memory usage: 16 * size bytes
        private static final int UPDATE_UID_PROC_STATE_LOG_MAX_SIZE = 0;
        // Memory usage: 20 * size bytes
        private static final int COMMIT_UID_STATE_LOG_MAX_SIZE = 200;
        // Memory usage: 24 * size bytes
        private static final int EVAL_FOREGROUND_MODE_MAX_SIZE = 200;

        private final Handler mHandler;

        private int[][] mUpdateUidProcStateLog = new int[UPDATE_UID_PROC_STATE_LOG_MAX_SIZE][3];
        private long[] mUpdateUidProcStateLogTimestamps =
                new long[UPDATE_UID_PROC_STATE_LOG_MAX_SIZE];
        private int mUpdateUidProcStateLogSize = 0;
        private int mUpdateUidProcStateLogHead = 0;

        private int[][] mCommitUidStateLog = new int[COMMIT_UID_STATE_LOG_MAX_SIZE][4];
        private long[] mCommitUidStateLogTimestamps = new long[COMMIT_UID_STATE_LOG_MAX_SIZE];
        private int mCommitUidStateLogSize = 0;
        private int mCommitUidStateLogHead = 0;

        private int[][] mEvalForegroundModeLog = new int[EVAL_FOREGROUND_MODE_MAX_SIZE][5];
        private long[] mEvalForegroundModeLogTimestamps = new long[EVAL_FOREGROUND_MODE_MAX_SIZE];
        private int mEvalForegroundModeLogSize = 0;
        private int mEvalForegroundModeLogHead = 0;

        EventLog(Handler handler) {
            mHandler = handler;
        }

        void logUpdateUidProcState(int uid, int procState, int capability) {
            if (UPDATE_UID_PROC_STATE_LOG_MAX_SIZE == 0) {
                return;
            }
            mHandler.sendMessage(PooledLambda.obtainMessage(EventLog::logUpdateUidProcStateAsync,
                    this, System.currentTimeMillis(), uid, procState, capability));
        }

        void logUpdateUidProcStateAsync(long timestamp, int uid, int procState, int capability) {
            int idx = (mUpdateUidProcStateLogHead + mUpdateUidProcStateLogSize)
                    % UPDATE_UID_PROC_STATE_LOG_MAX_SIZE;
            if (mUpdateUidProcStateLogSize == UPDATE_UID_PROC_STATE_LOG_MAX_SIZE) {
                mUpdateUidProcStateLogHead =
                        (mUpdateUidProcStateLogHead + 1) % UPDATE_UID_PROC_STATE_LOG_MAX_SIZE;
            } else {
                mUpdateUidProcStateLogSize++;
            }

            mUpdateUidProcStateLog[idx][0] = uid;
            mUpdateUidProcStateLog[idx][1] = procState;
            mUpdateUidProcStateLog[idx][2] = capability;
            mUpdateUidProcStateLogTimestamps[idx] = timestamp;
        }

        void logCommitUidState(int uid, int uidState, int capability, boolean visible) {
            if (COMMIT_UID_STATE_LOG_MAX_SIZE == 0) {
                return;
            }
            mHandler.sendMessage(PooledLambda.obtainMessage(EventLog::logCommitUidStateAsync,
                    this, System.currentTimeMillis(), uid, uidState, capability, visible));
        }

        void logCommitUidStateAsync(long timestamp, int uid, int uidState, int capability,
                boolean visible) {
            int idx = (mCommitUidStateLogHead + mCommitUidStateLogSize)
                    % COMMIT_UID_STATE_LOG_MAX_SIZE;
            if (mCommitUidStateLogSize == COMMIT_UID_STATE_LOG_MAX_SIZE) {
                mCommitUidStateLogHead =
                        (mCommitUidStateLogHead + 1) % COMMIT_UID_STATE_LOG_MAX_SIZE;
            } else {
                mCommitUidStateLogSize++;
            }

            mCommitUidStateLog[idx][0] = uid;
            mCommitUidStateLog[idx][1] = uidState;
            mCommitUidStateLog[idx][2] = capability;
            mCommitUidStateLog[idx][3] = visible ? 1 : 0;
            mCommitUidStateLogTimestamps[idx] = timestamp;
        }

        void logEvalForegroundMode(int uid, int uidState, int capability, int code, int result) {
            if (EVAL_FOREGROUND_MODE_MAX_SIZE == 0) {
                return;
            }
            mHandler.sendMessage(PooledLambda.obtainMessage(EventLog::logEvalForegroundModeAsync,
                    this, System.currentTimeMillis(), uid, uidState, capability, code, result));
        }

        void logEvalForegroundModeAsync(long timestamp, int uid, int uidState, int capability,
                int code, int result) {
            int idx = (mEvalForegroundModeLogHead + mEvalForegroundModeLogSize)
                    % EVAL_FOREGROUND_MODE_MAX_SIZE;
            if (mEvalForegroundModeLogSize == EVAL_FOREGROUND_MODE_MAX_SIZE) {
                mEvalForegroundModeLogHead =
                        (mEvalForegroundModeLogHead + 1) % EVAL_FOREGROUND_MODE_MAX_SIZE;
            } else {
                mEvalForegroundModeLogSize++;
            }

            mEvalForegroundModeLog[idx][0] = uid;
            mEvalForegroundModeLog[idx][1] = uidState;
            mEvalForegroundModeLog[idx][2] = capability;
            mEvalForegroundModeLog[idx][3] = code;
            mEvalForegroundModeLog[idx][4] = result;
            mEvalForegroundModeLogTimestamps[idx] = timestamp;
        }

        void dumpEvents(PrintWriter pw) {
            if (Thread.currentThread() != mHandler.getLooper().getThread()) {
                // All operations are done on the handler's thread
                CountDownLatch latch = new CountDownLatch(1);
                mHandler.post(() -> {
                    dumpEvents(pw);
                    latch.countDown();
                });

                try {
                    latch.await();
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                return;
            }

            int updateIdx = 0;
            int commitIdx = 0;
            int evalIdx = 0;

            while (updateIdx < mUpdateUidProcStateLogSize
                    || commitIdx < mCommitUidStateLogSize
                    || evalIdx < mEvalForegroundModeLogSize) {
                int updatePtr = 0;
                int commitPtr = 0;
                int evalPtr = 0;
                if (UPDATE_UID_PROC_STATE_LOG_MAX_SIZE != 0) {
                    updatePtr = (mUpdateUidProcStateLogHead + updateIdx)
                            % UPDATE_UID_PROC_STATE_LOG_MAX_SIZE;
                }
                if (COMMIT_UID_STATE_LOG_MAX_SIZE != 0) {
                    commitPtr = (mCommitUidStateLogHead + commitIdx)
                            % COMMIT_UID_STATE_LOG_MAX_SIZE;
                }
                if (EVAL_FOREGROUND_MODE_MAX_SIZE != 0) {
                    evalPtr = (mEvalForegroundModeLogHead + evalIdx)
                            % EVAL_FOREGROUND_MODE_MAX_SIZE;
                }

                long aTimestamp = updateIdx < mUpdateUidProcStateLogSize
                        ? mUpdateUidProcStateLogTimestamps[updatePtr] : Long.MAX_VALUE;
                long bTimestamp = commitIdx < mCommitUidStateLogSize
                        ? mCommitUidStateLogTimestamps[commitPtr] : Long.MAX_VALUE;
                long cTimestamp = evalIdx < mEvalForegroundModeLogSize
                        ? mEvalForegroundModeLogTimestamps[evalPtr] : Long.MAX_VALUE;

                if (aTimestamp <= bTimestamp && aTimestamp <= cTimestamp) {
                    dumpUpdateUidProcState(pw, updatePtr);
                    updateIdx++;
                } else if (bTimestamp <= cTimestamp) {
                    dumpCommitUidState(pw, commitPtr);
                    commitIdx++;
                } else {
                    dumpEvalForegroundMode(pw, evalPtr);
                    evalIdx++;
                }
            }
        }

        void dumpUpdateUidProcState(PrintWriter pw, int idx) {
            long timestamp = mUpdateUidProcStateLogTimestamps[idx];
            int uid = mUpdateUidProcStateLog[idx][0];
            int procState = mUpdateUidProcStateLog[idx][1];
            int capability = mUpdateUidProcStateLog[idx][2];

            TimeUtils.dumpTime(pw, timestamp);

            pw.print(" UPDATE_UID_PROC_STATE");

            pw.print(" uid=");
            pw.print(uid);

            pw.print(" procState=");
            pw.print(String.format("%-30s", ActivityManager.procStateToString(procState)));

            pw.print(" capability=");
            pw.print(ActivityManager.getCapabilitiesSummary(capability));

            pw.println();
        }

        void dumpCommitUidState(PrintWriter pw, int idx) {
            long timestamp = mCommitUidStateLogTimestamps[idx];
            int uid = mCommitUidStateLog[idx][0];
            int uidState = mCommitUidStateLog[idx][1];
            int capability = mCommitUidStateLog[idx][2];
            boolean visibleAppWidget = mCommitUidStateLog[idx][3] != 0;

            TimeUtils.dumpTime(pw, timestamp);

            pw.print(" COMMIT_UID_STATE     ");

            pw.print(" uid=");
            pw.print(uid);

            pw.print(" uidState=");
            pw.print(String.format("%-30s", AppOpsManager.uidStateToString(uidState)));

            pw.print(" capability=");
            pw.print(ActivityManager.getCapabilitiesSummary(capability));

            pw.print(" visibleAppWidget=");
            pw.print(visibleAppWidget);

            pw.println();
        }

        void dumpEvalForegroundMode(PrintWriter pw, int idx) {
            long timestamp = mEvalForegroundModeLogTimestamps[idx];
            int uid = mEvalForegroundModeLog[idx][0];
            int uidState = mEvalForegroundModeLog[idx][1];
            int capability = mEvalForegroundModeLog[idx][2];
            int code = mEvalForegroundModeLog[idx][3];
            int result = mEvalForegroundModeLog[idx][4];

            TimeUtils.dumpTime(pw, timestamp);

            pw.print(" EVAL_FOREGROUND_MODE ");

            pw.print(" uid=");
            pw.print(uid);

            pw.print(" uidState=");
            pw.print(String.format("%-30s", AppOpsManager.uidStateToString(uidState)));

            pw.print(" capability=");
            pw.print(ActivityManager.getCapabilitiesSummary(capability));

            pw.print(" code=");
            pw.print(String.format("%-20s", AppOpsManager.opToName(code)));

            pw.print(" result=");
            pw.print(AppOpsManager.modeToName(result));

            pw.println();
        }
    }
}
}