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

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/13787676

MUST ONLY BE SUBMITTED BY AUTOMERGER

Change-Id: Ia3308acb68c0bf1013d7963fb0547ef675b18d0d
This commit is contained in:
Stanislav Zholnin
2021-03-10 08:41:15 +00:00
committed by Automerger Merge Worker
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(" --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

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

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() {
synchronized (mInMemoryLock) {
return mMode;