Merge "Add dumpsys appops option to dump discrete accesses" into sc-dev

This commit is contained in:
Stanislav Zholnin
2021-03-10 08:14:14 +00:00
committed by Android (Google) Code Review
3 changed files with 136 additions and 4 deletions

View File

@@ -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

View File

@@ -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) {

View File

@@ -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;