Add API support for permission access timeline.
Test: in development Bug: 176965672 Change-Id: Ib06452946fda2fcbd32ac6172ea4a43dabde7b67
This commit is contained in:
@@ -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.
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user