Add API support for permission access timeline.

Test: in development
Bug: 176965672
Change-Id: Ib06452946fda2fcbd32ac6172ea4a43dabde7b67
This commit is contained in:
Stanislav Zholnin
2021-01-28 12:54:02 +00:00
parent 5d3166d403
commit 07e6855f8b
7 changed files with 1117 additions and 108 deletions

View File

@@ -16,6 +16,8 @@
package android.app;
import static java.lang.Long.max;
import android.Manifest;
import android.annotation.CallbackExecutor;
import android.annotation.IntDef;
@@ -3385,6 +3387,13 @@ public class AppOpsManager {
@DataClass.ParcelWith(LongSparseArrayParceling.class)
private final @Nullable LongSparseArray<NoteOpEvent> mRejectEvents;
private AttributedOpEntry(@NonNull AttributedOpEntry other) {
mOp = other.mOp;
mRunning = other.mRunning;
mAccessEvents = other.mAccessEvents == null ? null : other.mAccessEvents.clone();
mRejectEvents = other.mRejectEvents == null ? null : other.mRejectEvents.clone();
}
/**
* Returns all keys for which we have events.
*
@@ -3749,6 +3758,15 @@ public class AppOpsManager {
return lastEvent.getProxy();
}
@NonNull
String getOpName() {
return AppOpsManager.opToPublicName(mOp);
}
int getOp() {
return mOp;
}
private static class LongSparseArrayParceling implements
Parcelling<LongSparseArray<NoteOpEvent>> {
@Override
@@ -4570,6 +4588,50 @@ public class AppOpsManager {
void visitHistoricalOp(@NonNull HistoricalOp ops);
}
/**
* Flag for querying app op history: get only aggregate information and no
* discrete accesses.
*
* @see #getHistoricalOps(HistoricalOpsRequest, Executor, Consumer)
*
* @hide
*/
@TestApi
@SystemApi
public static final int HISTORY_FLAG_AGGREGATE = 1 << 0;
/**
* Flag for querying app op history: get only discrete information and no
* aggregate accesses.
*
* @see #getHistoricalOps(HistoricalOpsRequest, Executor, Consumer)
*
* @hide
*/
@TestApi
@SystemApi
public static final int HISTORY_FLAG_DISCRETE = 1 << 1;
/**
* Flag for querying app op history: get all types of historical accesses.
*
* @see #getHistoricalOps(HistoricalOpsRequest, Executor, Consumer)
*
* @hide
*/
@TestApi
@SystemApi
public static final int HISTORY_FLAGS_ALL = HISTORY_FLAG_AGGREGATE
| HISTORY_FLAG_DISCRETE;
/** @hide */
@Retention(RetentionPolicy.SOURCE)
@IntDef(flag = true, prefix = { "HISTORY_FLAG_" }, value = {
HISTORY_FLAG_AGGREGATE,
HISTORY_FLAG_DISCRETE
})
public @interface OpHistoryFlags {}
/**
* Specifies what parameters to filter historical appop requests for
*
@@ -4625,6 +4687,7 @@ public class AppOpsManager {
private final @Nullable String mPackageName;
private final @Nullable String mAttributionTag;
private final @Nullable List<String> mOpNames;
private final @OpHistoryFlags int mHistoryFlags;
private final @HistoricalOpsRequestFilter int mFilter;
private final long mBeginTimeMillis;
private final long mEndTimeMillis;
@@ -4632,12 +4695,13 @@ public class AppOpsManager {
private HistoricalOpsRequest(int uid, @Nullable String packageName,
@Nullable String attributionTag, @Nullable List<String> opNames,
@HistoricalOpsRequestFilter int filter, long beginTimeMillis,
long endTimeMillis, @OpFlags int flags) {
@OpHistoryFlags int historyFlags, @HistoricalOpsRequestFilter int filter,
long beginTimeMillis, long endTimeMillis, @OpFlags int flags) {
mUid = uid;
mPackageName = packageName;
mAttributionTag = attributionTag;
mOpNames = opNames;
mHistoryFlags = historyFlags;
mFilter = filter;
mBeginTimeMillis = beginTimeMillis;
mEndTimeMillis = endTimeMillis;
@@ -4655,6 +4719,7 @@ public class AppOpsManager {
private @Nullable String mPackageName;
private @Nullable String mAttributionTag;
private @Nullable List<String> mOpNames;
private @OpHistoryFlags int mHistoryFlags;
private @HistoricalOpsRequestFilter int mFilter;
private final long mBeginTimeMillis;
private final long mEndTimeMillis;
@@ -4676,6 +4741,7 @@ public class AppOpsManager {
"beginTimeMillis must be non negative and lesser than endTimeMillis");
mBeginTimeMillis = beginTimeMillis;
mEndTimeMillis = endTimeMillis;
mHistoryFlags = HISTORY_FLAG_AGGREGATE;
}
/**
@@ -4771,12 +4837,26 @@ public class AppOpsManager {
return this;
}
/**
* Specifies what type of historical information to query.
*
* @param flags Flags for the historical types to fetch which are any
* combination of {@link #HISTORY_FLAG_AGGREGATE}, {@link #HISTORY_FLAG_DISCRETE},
* {@link #HISTORY_FLAGS_ALL}. The default is {@link #HISTORY_FLAG_AGGREGATE}.
* @return This builder.
*/
public @NonNull Builder setHistoryFlags(@OpHistoryFlags int flags) {
Preconditions.checkFlagsArgument(flags, HISTORY_FLAGS_ALL);
mHistoryFlags = flags;
return this;
}
/**
* @return a new {@link HistoricalOpsRequest}.
*/
public @NonNull HistoricalOpsRequest build() {
return new HistoricalOpsRequest(mUid, mPackageName, mAttributionTag, mOpNames,
mFilter, mBeginTimeMillis, mEndTimeMillis, mFlags);
mHistoryFlags, mFilter, mBeginTimeMillis, mEndTimeMillis, mFlags);
}
}
}
@@ -4943,7 +5023,8 @@ public class AppOpsManager {
* @hide
*/
public void filter(int uid, @Nullable String packageName, @Nullable String attributionTag,
@Nullable String[] opNames, @HistoricalOpsRequestFilter int filter,
@Nullable String[] opNames, @OpHistoryFlags int historyFilter,
@HistoricalOpsRequestFilter int filter,
long beginTimeMillis, long endTimeMillis) {
final long durationMillis = getDurationMillis();
mBeginTimeMillis = Math.max(mBeginTimeMillis, beginTimeMillis);
@@ -4956,7 +5037,8 @@ public class AppOpsManager {
if ((filter & FILTER_BY_UID) != 0 && uid != uidOp.getUid()) {
mHistoricalUidOps.removeAt(i);
} else {
uidOp.filter(packageName, attributionTag, opNames, filter, scaleFactor);
uidOp.filter(packageName, attributionTag, opNames, filter, historyFilter,
scaleFactor, mBeginTimeMillis, mEndTimeMillis);
if (uidOp.getPackageCount() == 0) {
mHistoricalUidOps.removeAt(i);
}
@@ -5011,6 +5093,16 @@ public class AppOpsManager {
packageName, attributionTag, uidState, flags, increment);
}
/** @hide */
@TestApi
public void addDiscreteAccess(int opCode, int uid, @NonNull String packageName,
@Nullable String attributionTag, @UidState int uidState, @OpFlags int opFlag,
long discreteAccessTime, long discreteAccessDuration) {
getOrCreateHistoricalUidOps(uid).addDiscreteAccess(opCode, packageName, attributionTag,
uidState, opFlag, discreteAccessTime, discreteAccessDuration);
};
/** @hide */
@TestApi
public void offsetBeginAndEndTime(long offsetMillis) {
@@ -5288,7 +5380,8 @@ public class AppOpsManager {
private void filter(@Nullable String packageName, @Nullable String attributionTag,
@Nullable String[] opNames, @HistoricalOpsRequestFilter int filter,
double fractionToRemove) {
@OpHistoryFlags int historyFilter, double fractionToRemove, long beginTimeMillis,
long endTimeMillis) {
final int packageCount = getPackageCount();
for (int i = packageCount - 1; i >= 0; i--) {
final HistoricalPackageOps packageOps = getPackageOpsAt(i);
@@ -5296,7 +5389,8 @@ public class AppOpsManager {
packageOps.getPackageName())) {
mHistoricalPackageOps.removeAt(i);
} else {
packageOps.filter(attributionTag, opNames, filter, fractionToRemove);
packageOps.filter(attributionTag, opNames, filter, historyFilter,
fractionToRemove, beginTimeMillis, endTimeMillis);
if (packageOps.getAttributedOpsCount() == 0) {
mHistoricalPackageOps.removeAt(i);
}
@@ -5336,6 +5430,13 @@ public class AppOpsManager {
opCode, attributionTag, uidState, flags, increment);
}
private void addDiscreteAccess(int opCode, @NonNull String packageName,
@Nullable String attributionTag, @UidState int uidState,
@OpFlags int flag, long discreteAccessTime, long discreteAccessDuration) {
getOrCreateHistoricalPackageOps(packageName).addDiscreteAccess(opCode, attributionTag,
uidState, flag, discreteAccessTime, discreteAccessDuration);
};
/**
* @return The UID for which the data is related.
*/
@@ -5540,7 +5641,8 @@ public class AppOpsManager {
}
private void filter(@Nullable String attributionTag, @Nullable String[] opNames,
@HistoricalOpsRequestFilter int filter, double fractionToRemove) {
@HistoricalOpsRequestFilter int filter, @OpHistoryFlags int historyFilter,
double fractionToRemove, long beginTimeMillis, long endTimeMillis) {
final int attributionCount = getAttributedOpsCount();
for (int i = attributionCount - 1; i >= 0; i--) {
final AttributedHistoricalOps attributionOps = getAttributedOpsAt(i);
@@ -5548,7 +5650,8 @@ public class AppOpsManager {
attributionOps.getTag())) {
mAttributedHistoricalOps.removeAt(i);
} else {
attributionOps.filter(opNames, filter, fractionToRemove);
attributionOps.filter(opNames, filter, historyFilter, fractionToRemove,
beginTimeMillis, endTimeMillis);
if (attributionOps.getOpCount() == 0) {
mAttributedHistoricalOps.removeAt(i);
}
@@ -5593,6 +5696,13 @@ public class AppOpsManager {
opCode, uidState, flags, increment);
}
private void addDiscreteAccess(int opCode, @Nullable String attributionTag,
@UidState int uidState, @OpFlags int flag, long discreteAccessTime,
long discreteAccessDuration) {
getOrCreateAttributedHistoricalOps(attributionTag).addDiscreteAccess(opCode, uidState,
flag, discreteAccessTime, discreteAccessDuration);
}
/**
* Gets the package name which the data represents.
*
@@ -5870,7 +5980,8 @@ public class AppOpsManager {
}
private void filter(@Nullable String[] opNames, @HistoricalOpsRequestFilter int filter,
double scaleFactor) {
@OpHistoryFlags int historyFilter, double scaleFactor, long beginTimeMillis,
long endTimeMillis) {
final int opCount = getOpCount();
for (int i = opCount - 1; i >= 0; i--) {
final HistoricalOp op = mHistoricalOps.valueAt(i);
@@ -5878,7 +5989,7 @@ public class AppOpsManager {
op.getOpName())) {
mHistoricalOps.removeAt(i);
} else {
op.filter(scaleFactor);
op.filter(historyFilter, scaleFactor, beginTimeMillis, endTimeMillis);
}
}
}
@@ -5909,6 +6020,12 @@ public class AppOpsManager {
getOrCreateHistoricalOp(opCode).increaseAccessDuration(uidState, flags, increment);
}
private void addDiscreteAccess(int opCode, @UidState int uidState, @OpFlags int flag,
long discreteAccessTime, long discreteAccessDuration) {
getOrCreateHistoricalOp(opCode).addDiscreteAccess(uidState,flag, discreteAccessTime,
discreteAccessDuration);
}
/**
* Gets number historical app ops.
*
@@ -5970,8 +6087,6 @@ public class AppOpsManager {
return op;
}
// Code below generated by codegen v1.0.14.
//
// DO NOT MODIFY!
@@ -6121,6 +6236,9 @@ public class AppOpsManager {
private @Nullable LongSparseLongArray mRejectCount;
private @Nullable LongSparseLongArray mAccessDuration;
/** Discrete Ops for this Op */
private @Nullable List<AttributedOpEntry> mDiscreteAccesses;
/** @hide */
public HistoricalOp(int op) {
mOp = op;
@@ -6137,6 +6255,12 @@ public class AppOpsManager {
if (other.mAccessDuration != null) {
mAccessDuration = other.mAccessDuration.clone();
}
final int historicalOpCount = other.getDiscreteAccessCount();
for (int i = 0; i < historicalOpCount; i++) {
final AttributedOpEntry origOp = other.getDiscreteAccessAt(i);
final AttributedOpEntry cloneOp = new AttributedOpEntry(origOp);
getOrCreateDiscreteAccesses().add(cloneOp);
}
}
private HistoricalOp(@NonNull Parcel parcel) {
@@ -6144,22 +6268,45 @@ public class AppOpsManager {
mAccessCount = readLongSparseLongArrayFromParcel(parcel);
mRejectCount = readLongSparseLongArrayFromParcel(parcel);
mAccessDuration = readLongSparseLongArrayFromParcel(parcel);
mDiscreteAccesses = readDiscreteAccessArrayFromParcel(parcel);
}
private void filter(double scaleFactor) {
scale(mAccessCount, scaleFactor);
scale(mRejectCount, scaleFactor);
scale(mAccessDuration, scaleFactor);
private void filter(@OpHistoryFlags int historyFlag, double scaleFactor,
long beginTimeMillis, long endTimeMillis) {
if ((historyFlag & HISTORY_FLAG_AGGREGATE) == 0) {
mAccessCount = null;
mRejectCount = null;
mAccessDuration = null;
} else {
scale(mAccessCount, scaleFactor);
scale(mRejectCount, scaleFactor);
scale(mAccessDuration, scaleFactor);
}
if ((historyFlag & HISTORY_FLAG_DISCRETE) == 0) {
mDiscreteAccesses = null;
return;
}
final int discreteOpCount = getDiscreteAccessCount();
for (int i = discreteOpCount - 1; i >= 0; i--) {
final AttributedOpEntry op = mDiscreteAccesses.get(i);
long opBeginTime = op.getLastAccessTime(OP_FLAGS_ALL);
long opEndTime = opBeginTime + op.getLastDuration(OP_FLAGS_ALL);
opEndTime = max(opBeginTime, opEndTime);
if (opEndTime < beginTimeMillis || opBeginTime > endTimeMillis) {
mDiscreteAccesses.remove(i);
}
}
}
private boolean isEmpty() {
return !hasData(mAccessCount)
&& !hasData(mRejectCount)
&& !hasData(mAccessDuration);
&& !hasData(mAccessDuration)
&& (mDiscreteAccesses == null);
}
private boolean hasData(@NonNull LongSparseLongArray array) {
return (array != null && array.size() > 0);
return array != null && array.size() > 0;
}
private @Nullable HistoricalOp splice(double fractionToRemove) {
@@ -6191,6 +6338,32 @@ public class AppOpsManager {
merge(this::getOrCreateAccessCount, other.mAccessCount);
merge(this::getOrCreateRejectCount, other.mRejectCount);
merge(this::getOrCreateAccessDuration, other.mAccessDuration);
if (other.mDiscreteAccesses == null) {
return;
}
if (mDiscreteAccesses == null) {
mDiscreteAccesses = new ArrayList(other.mDiscreteAccesses);
return;
}
List<AttributedOpEntry> historicalDiscreteAccesses = new ArrayList<>();
final int otherHistoricalOpCount = other.getDiscreteAccessCount();
final int historicalOpCount = getDiscreteAccessCount();
int i = 0;
int j = 0;
while (i < otherHistoricalOpCount || j < historicalOpCount) {
if (i == otherHistoricalOpCount) {
historicalDiscreteAccesses.add(mDiscreteAccesses.get(j++));
} else if (j == historicalOpCount) {
historicalDiscreteAccesses.add(other.mDiscreteAccesses.get(i++));
} else if (mDiscreteAccesses.get(j).getLastAccessTime(OP_FLAGS_ALL)
< other.mDiscreteAccesses.get(i).getLastAccessTime(OP_FLAGS_ALL)) {
historicalDiscreteAccesses.add(mDiscreteAccesses.get(j++));
} else {
historicalDiscreteAccesses.add(other.mDiscreteAccesses.get(i++));
}
}
mDiscreteAccesses = historicalDiscreteAccesses;
}
private void increaseAccessCount(@UidState int uidState, @OpFlags int flags,
@@ -6218,6 +6391,23 @@ public class AppOpsManager {
}
}
private void addDiscreteAccess(@UidState int uidState, @OpFlags int flag,
long discreteAccessTime, long discreteAccessDuration) {
List<AttributedOpEntry> discreteAccesses = getOrCreateDiscreteAccesses();
LongSparseArray<NoteOpEvent> accessEvents = new LongSparseArray<>();
long key = makeKey(uidState, flag);
NoteOpEvent note = new NoteOpEvent(discreteAccessTime, discreteAccessDuration, null);
accessEvents.append(key, note);
AttributedOpEntry access = new AttributedOpEntry(mOp, false, accessEvents, null);
for (int i = discreteAccesses.size() - 1; i >= 0; i--) {
if (discreteAccesses.get(i).getLastAccessTime(OP_FLAGS_ALL) < discreteAccessTime) {
discreteAccesses.add(i + 1, access);
return;
}
}
discreteAccesses.add(0, access);
}
/**
* Gets the op name.
*
@@ -6232,6 +6422,33 @@ public class AppOpsManager {
return mOp;
}
/**
* Gets number of discrete historical app ops.
*
* @return The number historical app ops.
* @see #getOpAt(int)
*/
public @IntRange(from = 0) int getDiscreteAccessCount() {
if (mDiscreteAccesses == null) {
return 0;
}
return mDiscreteAccesses.size();
}
/**
* Gets the historical op at a given index.
*
* @param index The index to lookup.
* @return The op at the given index.
* @see #getOpCount()
*/
public @NonNull AttributedOpEntry getDiscreteAccessAt(@IntRange(from = 0) int index) {
if (mDiscreteAccesses == null) {
throw new IndexOutOfBoundsException();
}
return mDiscreteAccesses.get(index);
}
/**
* Gets the number times the op was accessed (performed) in the foreground.
*
@@ -6250,6 +6467,25 @@ public class AppOpsManager {
resolveFirstUnrestrictedUidState(mOp), flags);
}
/**
* Gets the discrete events the op was accessed (performed) in the foreground.
*
* @param flags The flags which are any combination of
* {@link #OP_FLAG_SELF}, {@link #OP_FLAG_TRUSTED_PROXY},
* {@link #OP_FLAG_UNTRUSTED_PROXY}, {@link #OP_FLAG_TRUSTED_PROXIED},
* {@link #OP_FLAG_UNTRUSTED_PROXIED}. You can use {@link #OP_FLAGS_ALL}
* for any flag.
* @return The list of discrete ops accessed in the foreground.
*
* @see #getBackgroundDiscreteAccesses(int)
* @see #getDiscreteAccesses(int, int, int)
*/
@NonNull
public List<AttributedOpEntry> getForegroundDiscreteAccesses(@OpFlags int flags) {
return listForFlagsInStates(mDiscreteAccesses, MAX_PRIORITY_UID_STATE,
resolveFirstUnrestrictedUidState(mOp), flags);
}
/**
* Gets the number times the op was accessed (performed) in the background.
*
@@ -6268,6 +6504,25 @@ public class AppOpsManager {
MIN_PRIORITY_UID_STATE, flags);
}
/**
* Gets the discrete events the op was accessed (performed) in the background.
*
* @param flags The flags which are any combination of
* {@link #OP_FLAG_SELF}, {@link #OP_FLAG_TRUSTED_PROXY},
* {@link #OP_FLAG_UNTRUSTED_PROXY}, {@link #OP_FLAG_TRUSTED_PROXIED},
* {@link #OP_FLAG_UNTRUSTED_PROXIED}. You can use {@link #OP_FLAGS_ALL}
* for any flag.
* @return The list of discrete ops accessed in the background.
*
* @see #getForegroundDiscreteAccesses(int)
* @see #getDiscreteAccesses(int, int, int)
*/
@NonNull
public List<AttributedOpEntry> getBackgroundDiscreteAccesses(@OpFlags int flags) {
return listForFlagsInStates(mDiscreteAccesses, resolveLastRestrictedUidState(mOp),
MIN_PRIORITY_UID_STATE, flags);
}
/**
* Gets the number times the op was accessed (performed) for a
* range of uid states.
@@ -6293,6 +6548,26 @@ public class AppOpsManager {
return sumForFlagsInStates(mAccessCount, fromUidState, toUidState, flags);
}
/**
* Gets the discrete events the op was accessed (performed) for a
* range of uid states.
*
* @param flags The flags which are any combination of
* {@link #OP_FLAG_SELF}, {@link #OP_FLAG_TRUSTED_PROXY},
* {@link #OP_FLAG_UNTRUSTED_PROXY}, {@link #OP_FLAG_TRUSTED_PROXIED},
* {@link #OP_FLAG_UNTRUSTED_PROXIED}. You can use {@link #OP_FLAGS_ALL}
* for any flag.
* @return The discrete the op was accessed in the background.
*
* @see #getBackgroundDiscreteAccesses(int)
* @see #getForegroundDiscreteAccesses(int)
*/
@NonNull
public List<AttributedOpEntry> getDiscreteAccesses(@UidState int fromUidState,
@UidState int toUidState, @OpFlags int flags) {
return listForFlagsInStates(mDiscreteAccesses, fromUidState, toUidState, flags);
}
/**
* Gets the number times the op was rejected in the foreground.
*
@@ -6427,6 +6702,7 @@ public class AppOpsManager {
writeLongSparseLongArrayToParcel(mAccessCount, parcel);
writeLongSparseLongArrayToParcel(mRejectCount, parcel);
writeLongSparseLongArrayToParcel(mAccessDuration, parcel);
writeDiscreteAccessArrayToParcel(mDiscreteAccesses, parcel);
}
@Override
@@ -6447,7 +6723,11 @@ public class AppOpsManager {
if (!equalsLongSparseLongArray(mRejectCount, other.mRejectCount)) {
return false;
}
return equalsLongSparseLongArray(mAccessDuration, other.mAccessDuration);
if (!equalsLongSparseLongArray(mAccessDuration, other.mAccessDuration)) {
return false;
}
return mDiscreteAccesses == null ? (other.mDiscreteAccesses == null ? true
: false) : mDiscreteAccesses.equals(other.mDiscreteAccesses);
}
@Override
@@ -6456,6 +6736,7 @@ public class AppOpsManager {
result = 31 * result + Objects.hashCode(mAccessCount);
result = 31 * result + Objects.hashCode(mRejectCount);
result = 31 * result + Objects.hashCode(mAccessDuration);
result = 31 * result + Objects.hashCode(mDiscreteAccesses);
return result;
}
@@ -6484,6 +6765,13 @@ public class AppOpsManager {
return mAccessDuration;
}
private @NonNull List<AttributedOpEntry> getOrCreateDiscreteAccesses() {
if (mDiscreteAccesses == null) {
mDiscreteAccesses = new ArrayList<>();
}
return mDiscreteAccesses;
}
/**
* Multiplies the entries in the array with the passed in scale factor and
* rounds the result at up 0.5 boundary.
@@ -6573,6 +6861,32 @@ public class AppOpsManager {
return sum;
}
/**
* Returns list of events filtered by UidState and UID flags.
*
* @param accesses The events list.
* @param beginUidState The beginning UID state (inclusive).
* @param endUidState The end UID state (inclusive).
* @param flags The UID flags.
* @return filtered list of events.
*/
private static List<AttributedOpEntry> listForFlagsInStates(List<AttributedOpEntry> accesses,
@UidState int beginUidState, @UidState int endUidState, @OpFlags int flags) {
List<AttributedOpEntry> result = new ArrayList<>();
if (accesses == null) {
return result;
}
int nAccesses = accesses.size();
for (int i = 0; i < nAccesses; i++) {
AttributedOpEntry entry = accesses.get(i);
if (entry.getLastAccessTime(beginUidState, endUidState, flags) == -1) {
continue;
}
result.add(entry);
}
return result;
}
/**
* Callback for notification of changes to operation state.
*/
@@ -6796,8 +7110,9 @@ public class AppOpsManager {
Objects.requireNonNull(callback, "callback cannot be null");
try {
mService.getHistoricalOps(request.mUid, request.mPackageName, request.mAttributionTag,
request.mOpNames, request.mFilter, request.mBeginTimeMillis,
request.mEndTimeMillis, request.mFlags, new RemoteCallback((result) -> {
request.mOpNames, request.mHistoryFlags, request.mFilter,
request.mBeginTimeMillis, request.mEndTimeMillis, request.mFlags,
new RemoteCallback((result) -> {
final HistoricalOps ops = result.getParcelable(KEY_HISTORICAL_OPS);
final long identity = Binder.clearCallingIdentity();
try {
@@ -6835,9 +7150,9 @@ public class AppOpsManager {
Objects.requireNonNull(callback, "callback cannot be null");
try {
mService.getHistoricalOpsFromDiskRaw(request.mUid, request.mPackageName,
request.mAttributionTag, request.mOpNames, request.mFilter,
request.mBeginTimeMillis, request.mEndTimeMillis, request.mFlags,
new RemoteCallback((result) -> {
request.mAttributionTag, request.mOpNames, request.mHistoryFlags,
request.mFilter, request.mBeginTimeMillis, request.mEndTimeMillis,
request.mFlags, new RemoteCallback((result) -> {
final HistoricalOps ops = result.getParcelable(KEY_HISTORICAL_OPS);
final long identity = Binder.clearCallingIdentity();
try {
@@ -9072,6 +9387,32 @@ public class AppOpsManager {
return array;
}
private static void writeDiscreteAccessArrayToParcel(
@Nullable List<AttributedOpEntry> array, @NonNull Parcel parcel) {
if (array != null) {
final int size = array.size();
parcel.writeInt(size);
for (int i = 0; i < size; i++) {
array.get(i).writeToParcel(parcel, 0);
}
} else {
parcel.writeInt(-1);
}
}
private static @Nullable List<AttributedOpEntry> readDiscreteAccessArrayFromParcel(
@NonNull Parcel parcel) {
final int size = parcel.readInt();
if (size < 0) {
return null;
}
final List<AttributedOpEntry> array = new ArrayList<>(size);
for (int i = 0; i < size; i++) {
array.add(new AttributedOpEntry(parcel));
}
return array;
}
/**
* Collects the keys from an array to the result creating the result if needed.
*