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

Commit ad172b54 authored by Stanislav Zholnin's avatar Stanislav Zholnin
Browse files

Add dumpsys appops option to dump discrete accesses

Bug: 176965672
Test: adb shell dumpsys appops --include-discrete
Change-Id: I9f5db15ca775d0209d1c92b19bb08b6b17c89734
parent 1623f60d
Loading
Loading
Loading
Loading
+30 −4
Original line number Diff line number Diff line
@@ -5282,8 +5282,12 @@ public class AppOpsService extends IAppOpsService.Stub {
        pw.println("    Limit output to data associated with the given package name.");
        pw.println("  --attributionTag [attributionTag]");
        pw.println("    Limit output to data associated with the given attribution tag.");
        pw.println("  --include-discrete [n]");
        pw.println("    Include discrete ops limited to n per dimension. Use zero for no limit.");
        pw.println("  --watchers");
        pw.println("    Only output the watcher sections.");
        pw.println("  --history");
        pw.println("    Only output history.");
    }

    private void dumpStatesLocked(@NonNull PrintWriter pw, @Nullable String filterAttributionTag,
@@ -5418,6 +5422,8 @@ public class AppOpsService extends IAppOpsService.Stub {
        boolean dumpWatchers = false;
        // TODO ntmyren: Remove the dumpHistory and dumpFilter
        boolean dumpHistory = false;
        boolean includeDiscreteOps = false;
        int nDiscreteOps = 10;
        @HistoricalOpsRequestFilter int dumpFilter = 0;

        if (args != null) {
@@ -5479,6 +5485,21 @@ public class AppOpsService extends IAppOpsService.Stub {
                    }
                } else if ("--watchers".equals(arg)) {
                    dumpWatchers = true;
                } else if ("--include-discrete".equals(arg)) {
                    i++;
                    if (i >= args.length) {
                        pw.println("No argument for --include-discrete option");
                        return;
                    }
                    try {
                        nDiscreteOps = Integer.valueOf(args[i]);
                    } catch (NumberFormatException e) {
                        pw.println("Wrong parameter: " + args[i]);
                        return;
                    }
                    includeDiscreteOps = true;
                } else if ("--history".equals(arg)) {
                    dumpHistory = true;
                } else if (arg.length() > 0 && arg.charAt(0) == '-') {
                    pw.println("Unknown option: " + arg);
                    return;
@@ -5489,6 +5510,8 @@ public class AppOpsService extends IAppOpsService.Stub {
            }
        }

        final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
        final Date date = new Date();
        synchronized (this) {
            pw.println("Current AppOps Service state:");
            if (!dumpHistory && !dumpWatchers) {
@@ -5498,8 +5521,6 @@ public class AppOpsService extends IAppOpsService.Stub {
            final long now = System.currentTimeMillis();
            final long nowElapsed = SystemClock.elapsedRealtime();
            final long nowUptime = SystemClock.uptimeMillis();
            final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
            final Date date = new Date();
            boolean needSep = false;
            if (dumpFilter == 0 && dumpMode < 0 && mProfileOwners != null && !dumpWatchers
                    && !dumpHistory) {
@@ -5967,6 +5988,11 @@ public class AppOpsService extends IAppOpsService.Stub {
            mHistoricalRegistry.dump("  ", pw, dumpUid, dumpPackage, dumpAttributionTag, dumpOp,
                    dumpFilter);
        }
        if (includeDiscreteOps) {
            pw.println("Discrete accesses: ");
            mHistoricalRegistry.dumpDiscreteData(pw, dumpUid, dumpPackage, dumpAttributionTag,
                    dumpFilter, dumpOp, sdf, date, "  ", nDiscreteOps);
        }
    }

    @Override
+97 −0
Original line number Diff line number Diff line
@@ -23,9 +23,13 @@ import static android.app.AppOpsManager.FILTER_BY_UID;
import static android.app.AppOpsManager.OP_CAMERA;
import static android.app.AppOpsManager.OP_COARSE_LOCATION;
import static android.app.AppOpsManager.OP_FINE_LOCATION;
import static android.app.AppOpsManager.OP_FLAGS_ALL;
import static android.app.AppOpsManager.OP_FLAG_SELF;
import static android.app.AppOpsManager.OP_FLAG_TRUSTED_PROXIED;
import static android.app.AppOpsManager.OP_NONE;
import static android.app.AppOpsManager.OP_RECORD_AUDIO;
import static android.app.AppOpsManager.flagsToString;
import static android.app.AppOpsManager.getUidStateName;

import static java.lang.Math.max;

@@ -45,15 +49,20 @@ import com.android.internal.annotations.GuardedBy;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.XmlUtils;

import libcore.util.EmptyArray;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.time.Duration;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.List;

/**
@@ -237,6 +246,23 @@ final class DiscreteRegistry {
        }
    }

    void dump(@NonNull PrintWriter pw, int uidFilter, @Nullable String packageNameFilter,
            @Nullable String attributionTagFilter,
            @AppOpsManager.HistoricalOpsRequestFilter int filter, int dumpOp,
            @NonNull SimpleDateFormat sdf, @NonNull Date date, @NonNull String prefix,
            int nDiscreteOps) {
        DiscreteOps discreteOps = new DiscreteOps();
        synchronized (mOnDiskLock) {
            writeAndClearAccessHistory();
            String[] opNamesFilter = dumpOp == OP_NONE ? EmptyArray.STRING
                    : new String[]{AppOpsManager.opToPublicName(dumpOp)};
            readDiscreteOpsFromDisk(discreteOps, 0, Instant.now().toEpochMilli(), filter,
                    uidFilter, packageNameFilter, opNamesFilter, attributionTagFilter,
                    OP_FLAGS_ALL);
        }
        discreteOps.dump(pw, sdf, date, prefix, nDiscreteOps);
    }

    public static boolean isDiscreteOp(int op, int uid, @AppOpsManager.OpFlags int flags) {
        if (!isDiscreteOp(op)) {
            return false;
@@ -306,6 +332,18 @@ final class DiscreteRegistry {
            stream.close();
        }

        private void dump(@NonNull PrintWriter pw, @NonNull SimpleDateFormat sdf,
                @NonNull Date date, @NonNull String prefix, int nDiscreteOps) {
            int nUids = mUids.size();
            for (int i = 0; i < nUids; i++) {
                pw.print(prefix);
                pw.print("Uid: ");
                pw.print(mUids.keyAt(i));
                pw.println();
                mUids.valueAt(i).dump(pw, sdf, date, prefix + "  ", nDiscreteOps);
            }
        }

        private DiscreteUidOps getOrCreateDiscreteUidOps(int uid) {
            DiscreteUidOps result = mUids.get(uid);
            if (result == null) {
@@ -395,6 +433,18 @@ final class DiscreteRegistry {
            }
        }

        private void dump(@NonNull PrintWriter pw, @NonNull SimpleDateFormat sdf,
                @NonNull Date date, @NonNull String prefix, int nDiscreteOps) {
            int nPackages = mPackages.size();
            for (int i = 0; i < nPackages; i++) {
                pw.print(prefix);
                pw.print("Package: ");
                pw.print(mPackages.keyAt(i));
                pw.println();
                mPackages.valueAt(i).dump(pw, sdf, date, prefix + "  ", nDiscreteOps);
            }
        }

        void deserialize(TypedXmlPullParser parser, long beginTimeMillis,
                long endTimeMillis, @AppOpsManager.HistoricalOpsRequestFilter int filter,
                @Nullable String packageNameFilter,
@@ -458,6 +508,17 @@ final class DiscreteRegistry {
            }
        }

        private void dump(@NonNull PrintWriter pw, @NonNull SimpleDateFormat sdf,
                @NonNull Date date, @NonNull String prefix, int nDiscreteOps) {
            int nOps = mPackageOps.size();
            for (int i = 0; i < nOps; i++) {
                pw.print(prefix);
                pw.print(AppOpsManager.opToName(mPackageOps.keyAt(i)));
                pw.println();
                mPackageOps.valueAt(i).dump(pw, sdf, date, prefix + "  ", nDiscreteOps);
            }
        }

        void deserialize(TypedXmlPullParser parser, long beginTimeMillis, long endTimeMillis,
                @AppOpsManager.HistoricalOpsRequestFilter int filter,
                @Nullable String[] opNamesFilter, @Nullable String attributionTagFilter,
@@ -529,6 +590,24 @@ final class DiscreteRegistry {
            }
        }

        private void dump(@NonNull PrintWriter pw, @NonNull SimpleDateFormat sdf,
                @NonNull Date date, @NonNull String prefix, int nDiscreteOps) {
            int nAttributions = mAttributedOps.size();
            for (int i = 0; i < nAttributions; i++) {
                pw.print(prefix);
                pw.print("Attribution: ");
                pw.print(mAttributedOps.keyAt(i));
                pw.println();
                List<DiscreteOpEvent> ops = mAttributedOps.valueAt(i);
                int nOps = ops.size();
                int first = nDiscreteOps < 1 ? 0 : max(0, nOps - nDiscreteOps);
                for (int j = first; j < nOps; j++) {
                    ops.get(j).dump(pw, sdf, date, prefix + "  ");

                }
            }
        }

        void serialize(TypedXmlSerializer out) throws Exception {
            int nAttributions = mAttributedOps.size();
            for (int i = 0; i < nAttributions; i++) {
@@ -603,6 +682,24 @@ final class DiscreteRegistry {
            mOpFlag = opFlag;
        }

        private void dump(@NonNull PrintWriter pw, @NonNull SimpleDateFormat sdf,
                @NonNull Date date, @NonNull String prefix) {
            pw.print(prefix);
            pw.print("Access [");
            pw.print(getUidStateName(mUidState));
            pw.print("-");
            pw.print(flagsToString(mOpFlag));
            pw.print("] at ");
            date.setTime(mNoteTime);
            pw.print(sdf.format(date));
            if (mNoteDuration != -1) {
                pw.print(" for ");
                pw.print(mNoteDuration);
                pw.print(" milliseconds ");
            }
            pw.println();
        }

        private void serialize(TypedXmlSerializer out) throws Exception {
            out.attributeLong(null, ATTR_NOTE_TIME, mNoteTime);
            if (mNoteDuration != -1) {
+9 −0
Original line number Diff line number Diff line
@@ -349,6 +349,15 @@ final class HistoricalRegistry {
        }
    }

    void dumpDiscreteData(@NonNull PrintWriter pw, int uidFilter,
            @Nullable String packageNameFilter, @Nullable String attributionTagFilter,
            @HistoricalOpsRequestFilter int filter, int dumpOp,
            @NonNull SimpleDateFormat sdf, @NonNull Date date, @NonNull String prefix,
            int nDiscreteOps) {
        mDiscreteRegistry.dump(pw, uidFilter, packageNameFilter, attributionTagFilter, filter,
                dumpOp, sdf, date, prefix, nDiscreteOps);
    }

    @HistoricalMode int getMode() {
        synchronized (mInMemoryLock) {
            return mMode;