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(" Limit output to data associated with the given package name.");
|
||||||
pw.println(" --attributionTag [attributionTag]");
|
pw.println(" --attributionTag [attributionTag]");
|
||||||
pw.println(" Limit output to data associated with the given attribution tag.");
|
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(" --watchers");
|
||||||
pw.println(" Only output the watcher sections.");
|
pw.println(" Only output the watcher sections.");
|
||||||
|
pw.println(" --history");
|
||||||
|
pw.println(" Only output history.");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void dumpStatesLocked(@NonNull PrintWriter pw, @Nullable String filterAttributionTag,
|
private void dumpStatesLocked(@NonNull PrintWriter pw, @Nullable String filterAttributionTag,
|
||||||
@@ -5412,10 +5416,12 @@ public class AppOpsService extends IAppOpsService.Stub {
|
|||||||
boolean dumpWatchers = false;
|
boolean dumpWatchers = false;
|
||||||
// TODO ntmyren: Remove the dumpHistory and dumpFilter
|
// TODO ntmyren: Remove the dumpHistory and dumpFilter
|
||||||
boolean dumpHistory = false;
|
boolean dumpHistory = false;
|
||||||
|
boolean includeDiscreteOps = false;
|
||||||
|
int nDiscreteOps = 10;
|
||||||
@HistoricalOpsRequestFilter int dumpFilter = 0;
|
@HistoricalOpsRequestFilter int dumpFilter = 0;
|
||||||
|
|
||||||
if (args != null) {
|
if (args != null) {
|
||||||
for (int i=0; i<args.length; i++) {
|
for (int i = 0; i < args.length; i++) {
|
||||||
String arg = args[i];
|
String arg = args[i];
|
||||||
if ("-h".equals(arg)) {
|
if ("-h".equals(arg)) {
|
||||||
dumpHelp(pw);
|
dumpHelp(pw);
|
||||||
@@ -5473,7 +5479,22 @@ public class AppOpsService extends IAppOpsService.Stub {
|
|||||||
}
|
}
|
||||||
} else if ("--watchers".equals(arg)) {
|
} else if ("--watchers".equals(arg)) {
|
||||||
dumpWatchers = true;
|
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);
|
pw.println("Unknown option: " + arg);
|
||||||
return;
|
return;
|
||||||
} else {
|
} 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) {
|
synchronized (this) {
|
||||||
pw.println("Current AppOps Service state:");
|
pw.println("Current AppOps Service state:");
|
||||||
if (!dumpHistory && !dumpWatchers) {
|
if (!dumpHistory && !dumpWatchers) {
|
||||||
@@ -5492,8 +5515,6 @@ public class AppOpsService extends IAppOpsService.Stub {
|
|||||||
final long now = System.currentTimeMillis();
|
final long now = System.currentTimeMillis();
|
||||||
final long nowElapsed = SystemClock.elapsedRealtime();
|
final long nowElapsed = SystemClock.elapsedRealtime();
|
||||||
final long nowUptime = SystemClock.uptimeMillis();
|
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;
|
boolean needSep = false;
|
||||||
if (dumpFilter == 0 && dumpMode < 0 && mProfileOwners != null && !dumpWatchers
|
if (dumpFilter == 0 && dumpMode < 0 && mProfileOwners != null && !dumpWatchers
|
||||||
&& !dumpHistory) {
|
&& !dumpHistory) {
|
||||||
@@ -5961,6 +5982,11 @@ public class AppOpsService extends IAppOpsService.Stub {
|
|||||||
mHistoricalRegistry.dump(" ", pw, dumpUid, dumpPackage, dumpAttributionTag, dumpOp,
|
mHistoricalRegistry.dump(" ", pw, dumpUid, dumpPackage, dumpAttributionTag, dumpOp,
|
||||||
dumpFilter);
|
dumpFilter);
|
||||||
}
|
}
|
||||||
|
if (includeDiscreteOps) {
|
||||||
|
pw.println("Discrete accesses: ");
|
||||||
|
mHistoricalRegistry.dumpDiscreteData(pw, dumpUid, dumpPackage, dumpAttributionTag,
|
||||||
|
dumpFilter, dumpOp, sdf, date, " ", nDiscreteOps);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@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_CAMERA;
|
||||||
import static android.app.AppOpsManager.OP_COARSE_LOCATION;
|
import static android.app.AppOpsManager.OP_COARSE_LOCATION;
|
||||||
import static android.app.AppOpsManager.OP_FINE_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_SELF;
|
||||||
import static android.app.AppOpsManager.OP_FLAG_TRUSTED_PROXIED;
|
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.OP_RECORD_AUDIO;
|
||||||
|
import static android.app.AppOpsManager.flagsToString;
|
||||||
|
import static android.app.AppOpsManager.getUidStateName;
|
||||||
|
|
||||||
import static java.lang.Math.max;
|
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.ArrayUtils;
|
||||||
import com.android.internal.util.XmlUtils;
|
import com.android.internal.util.XmlUtils;
|
||||||
|
|
||||||
|
import libcore.util.EmptyArray;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.PrintWriter;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
import java.time.temporal.ChronoUnit;
|
import java.time.temporal.ChronoUnit;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.Date;
|
||||||
import java.util.List;
|
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) {
|
public static boolean isDiscreteOp(int op, int uid, @AppOpsManager.OpFlags int flags) {
|
||||||
if (!isDiscreteOp(op)) {
|
if (!isDiscreteOp(op)) {
|
||||||
return false;
|
return false;
|
||||||
@@ -306,6 +332,18 @@ final class DiscreteRegistry {
|
|||||||
stream.close();
|
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) {
|
private DiscreteUidOps getOrCreateDiscreteUidOps(int uid) {
|
||||||
DiscreteUidOps result = mUids.get(uid);
|
DiscreteUidOps result = mUids.get(uid);
|
||||||
if (result == null) {
|
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,
|
void deserialize(TypedXmlPullParser parser, long beginTimeMillis,
|
||||||
long endTimeMillis, @AppOpsManager.HistoricalOpsRequestFilter int filter,
|
long endTimeMillis, @AppOpsManager.HistoricalOpsRequestFilter int filter,
|
||||||
@Nullable String packageNameFilter,
|
@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,
|
void deserialize(TypedXmlPullParser parser, long beginTimeMillis, long endTimeMillis,
|
||||||
@AppOpsManager.HistoricalOpsRequestFilter int filter,
|
@AppOpsManager.HistoricalOpsRequestFilter int filter,
|
||||||
@Nullable String[] opNamesFilter, @Nullable String attributionTagFilter,
|
@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 {
|
void serialize(TypedXmlSerializer out) throws Exception {
|
||||||
int nAttributions = mAttributedOps.size();
|
int nAttributions = mAttributedOps.size();
|
||||||
for (int i = 0; i < nAttributions; i++) {
|
for (int i = 0; i < nAttributions; i++) {
|
||||||
@@ -609,6 +688,24 @@ final class DiscreteRegistry {
|
|||||||
mOpFlag = opFlag;
|
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 {
|
private void serialize(TypedXmlSerializer out) throws Exception {
|
||||||
out.attributeLong(null, ATTR_NOTE_TIME, mNoteTime);
|
out.attributeLong(null, ATTR_NOTE_TIME, mNoteTime);
|
||||||
if (mNoteDuration != -1) {
|
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() {
|
@HistoricalMode int getMode() {
|
||||||
synchronized (mInMemoryLock) {
|
synchronized (mInMemoryLock) {
|
||||||
return mMode;
|
return mMode;
|
||||||
|
|||||||
Reference in New Issue
Block a user