Merge "Add dumpsys appops option to dump discrete accesses" into sc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
f8504d250f
@@ -5276,8 +5276,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,
|
||||
@@ -5412,10 +5416,12 @@ 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) {
|
||||
for (int i=0; i<args.length; i++) {
|
||||
for (int i = 0; i < args.length; i++) {
|
||||
String arg = args[i];
|
||||
if ("-h".equals(arg)) {
|
||||
dumpHelp(pw);
|
||||
@@ -5473,7 +5479,22 @@ public class AppOpsService extends IAppOpsService.Stub {
|
||||
}
|
||||
} else if ("--watchers".equals(arg)) {
|
||||
dumpWatchers = true;
|
||||
} else if (arg.length() > 0 && arg.charAt(0) == '-'){
|
||||
} 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;
|
||||
} else {
|
||||
@@ -5483,6 +5504,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) {
|
||||
@@ -5492,8 +5515,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) {
|
||||
@@ -5961,6 +5982,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
|
||||
|
||||
@@ -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,
|
||||
@@ -535,6 +596,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++) {
|
||||
@@ -609,6 +688,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) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user