diff options
author | 2024-12-18 20:59:20 -0800 | |
---|---|---|
committer | 2024-12-18 20:59:20 -0800 | |
commit | c9117adb099ef5cda9064e9c58efc0c04ed705db (patch) | |
tree | 4e2c8db76e1db931b55acd52f78fc6f998fe1ae9 | |
parent | 042f578681e6b75c2c390f5848fb9395cb507b67 (diff) | |
parent | eb7603da9940548aae9b27be237962f303a6f55b (diff) |
Merge "Revert "Revert "Batch noteOperation binder calls in the client t..."" into main
9 files changed, 325 insertions, 67 deletions
diff --git a/core/java/android/app/AppOpsManager.aidl b/core/java/android/app/AppOpsManager.aidl index b4dee2e937cb..56ed290baf2e 100644 --- a/core/java/android/app/AppOpsManager.aidl +++ b/core/java/android/app/AppOpsManager.aidl @@ -19,6 +19,7 @@ package android.app; parcelable AppOpsManager.PackageOps; parcelable AppOpsManager.NoteOpEventProxyInfo; parcelable AppOpsManager.NoteOpEvent; +parcelable AppOpsManager.NotedOp; parcelable AppOpsManager.OpFeatureEntry; parcelable AppOpsManager.OpEntry; diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java index 19138126698c..53b4b54e9f93 100644 --- a/core/java/android/app/AppOpsManager.java +++ b/core/java/android/app/AppOpsManager.java @@ -262,6 +262,23 @@ public class AppOpsManager { private static final Object sLock = new Object(); + // A map that records noted times for each op. + private static ArrayMap<NotedOp, Integer> sPendingNotedOps = new ArrayMap<>(); + private static HandlerThread sHandlerThread; + private static final int NOTE_OP_BATCHING_DELAY_MILLIS = 1000; + + private boolean isNoteOpBatchingSupported() { + // If noteOp is called from system server no IPC is made, hence we don't need batching. + if (Process.myUid() == Process.SYSTEM_UID) { + return false; + } + return Flags.noteOpBatchingEnabled(); + } + + private static final Object sBatchedNoteOpLock = new Object(); + @GuardedBy("sBatchedNoteOpLock") + private static boolean sIsBatchedNoteOpCallScheduled = false; + /** Current {@link OnOpNotedCallback}. Change via {@link #setOnOpNotedCallback} */ @GuardedBy("sLock") private static @Nullable OnOpNotedCallback sOnOpNotedCallback; @@ -7466,6 +7483,141 @@ public class AppOpsManager { } /** + * A NotedOp is an app op grouped in noteOp API and sent to the system server in a batch + * + * @hide + */ + public static final class NotedOp implements Parcelable { + private final @IntRange(from = 0, to = _NUM_OP - 1) int mOp; + private final @IntRange(from = 0) int mUid; + private final @Nullable String mPackageName; + private final @Nullable String mAttributionTag; + private final int mVirtualDeviceId; + private final @Nullable String mMessage; + private final boolean mShouldCollectAsyncNotedOp; + private final boolean mShouldCollectMessage; + + public NotedOp(int op, int uid, @Nullable String packageName, + @Nullable String attributionTag, int virtualDeviceId, @Nullable String message, + boolean shouldCollectAsyncNotedOp, boolean shouldCollectMessage) { + mOp = op; + mUid = uid; + mPackageName = packageName; + mAttributionTag = attributionTag; + mVirtualDeviceId = virtualDeviceId; + mMessage = message; + mShouldCollectAsyncNotedOp = shouldCollectAsyncNotedOp; + mShouldCollectMessage = shouldCollectMessage; + } + + NotedOp(Parcel source) { + mOp = source.readInt(); + mUid = source.readInt(); + mPackageName = source.readString(); + mAttributionTag = source.readString(); + mVirtualDeviceId = source.readInt(); + mMessage = source.readString(); + mShouldCollectAsyncNotedOp = source.readBoolean(); + mShouldCollectMessage = source.readBoolean(); + } + + public int getOp() { + return mOp; + } + + public int getUid() { + return mUid; + } + + public @Nullable String getPackageName() { + return mPackageName; + } + + public @Nullable String getAttributionTag() { + return mAttributionTag; + } + + public int getVirtualDeviceId() { + return mVirtualDeviceId; + } + + public @Nullable String getMessage() { + return mMessage; + } + + public boolean getShouldCollectAsyncNotedOp() { + return mShouldCollectAsyncNotedOp; + } + + public boolean getShouldCollectMessage() { + return mShouldCollectMessage; + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(@NonNull Parcel dest, int flags) { + dest.writeInt(mOp); + dest.writeInt(mUid); + dest.writeString(mPackageName); + dest.writeString(mAttributionTag); + dest.writeInt(mVirtualDeviceId); + dest.writeString(mMessage); + dest.writeBoolean(mShouldCollectAsyncNotedOp); + dest.writeBoolean(mShouldCollectMessage); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + NotedOp that = (NotedOp) o; + return mOp == that.mOp + && mUid == that.mUid + && Objects.equals(mPackageName, that.mPackageName) + && Objects.equals(mAttributionTag, that.mAttributionTag) + && mVirtualDeviceId == that.mVirtualDeviceId + && Objects.equals(mMessage, that.mMessage) + && Objects.equals(mShouldCollectAsyncNotedOp, that.mShouldCollectAsyncNotedOp) + && Objects.equals(mShouldCollectMessage, that.mShouldCollectMessage); + } + + @Override + public int hashCode() { + return Objects.hash(mOp, mUid, mPackageName, mAttributionTag, mVirtualDeviceId, + mMessage, mShouldCollectAsyncNotedOp, mShouldCollectMessage); + } + + @Override + public String toString() { + return "NotedOp{" + + "mOp=" + mOp + + ", mUid=" + mUid + + ", mPackageName=" + mPackageName + + ", mAttributionTag=" + mAttributionTag + + ", mVirtualDeviceId=" + mVirtualDeviceId + + ", mMessage=" + mMessage + + ", mShouldCollectAsyncNotedOp=" + mShouldCollectAsyncNotedOp + + ", mShouldCollectMessage=" + mShouldCollectMessage + + "}"; + } + + public static final @NonNull Creator<NotedOp> CREATOR = + new Creator<>() { + @Override public NotedOp createFromParcel(Parcel source) { + return new NotedOp(source); + } + + @Override public NotedOp[] newArray(int size) { + return new NotedOp[size]; + } + }; + } + + /** * Computes the sum of the counts for the given flags in between the begin and * end UID states. * @@ -9301,6 +9453,65 @@ public class AppOpsManager { message); } + /** + * Create a new NotedOp object to represent the note operation. If the note operation is + * a duplicate in the buffer, put it in a batch for an async binder call to the system server. + * + * @return whether this note operation is a duplicate in the buffer. If it's the + * first, the noteOp is not batched, the caller should manually call noteOperation. + */ + private boolean batchDuplicateNoteOps(int op, int uid, @Nullable String packageName, + @Nullable String attributionTag, int virtualDeviceId, @Nullable String message, + boolean collectAsync, boolean shouldCollectMessage) { + synchronized (sBatchedNoteOpLock) { + NotedOp notedOp = new NotedOp(op, uid, packageName, attributionTag, + virtualDeviceId, message, collectAsync, shouldCollectMessage); + + // Batch same noteOp calls and send them with their counters to the system + // service asynchronously. The time window for batching is specified in + // NOTE_OP_BATCHING_DELAY_MILLIS. Always allow the first noteOp call to go + // through binder API. Accumulate subsequent same noteOp calls during the + // time window in sPendingNotedOps. + boolean isDuplicated = sPendingNotedOps.containsKey(notedOp); + if (!isDuplicated) { + sPendingNotedOps.put(notedOp, 0); + } else { + sPendingNotedOps.merge(notedOp, 1, Integer::sum); + } + + if (!sIsBatchedNoteOpCallScheduled) { + if (sHandlerThread == null) { + sHandlerThread = new HandlerThread("AppOpsManagerNoteOpBatching"); + sHandlerThread.start(); + } + + sHandlerThread.getThreadHandler().postDelayed(() -> { + ArrayMap<NotedOp, Integer> pendingNotedOpsCopy; + synchronized(sBatchedNoteOpLock) { + sIsBatchedNoteOpCallScheduled = false; + pendingNotedOpsCopy = sPendingNotedOps; + sPendingNotedOps = new ArrayMap<>(); + } + for (int i = pendingNotedOpsCopy.size() - 1; i >= 0; i--) { + if (pendingNotedOpsCopy.valueAt(i) == 0) { + pendingNotedOpsCopy.removeAt(i); + } + } + if (!pendingNotedOpsCopy.isEmpty()) { + try { + mService.noteOperationsInBatch(pendingNotedOpsCopy); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + }, NOTE_OP_BATCHING_DELAY_MILLIS); + + sIsBatchedNoteOpCallScheduled = true; + } + return isDuplicated; + } + } + private int noteOpNoThrow(int op, int uid, @Nullable String packageName, @Nullable String attributionTag, int virtualDeviceId, @Nullable String message) { try { @@ -9315,15 +9526,34 @@ public class AppOpsManager { } } - SyncNotedAppOp syncOp; - if (virtualDeviceId == Context.DEVICE_ID_DEFAULT) { - syncOp = mService.noteOperation(op, uid, packageName, attributionTag, - collectionMode == COLLECT_ASYNC, message, shouldCollectMessage); - } else { - syncOp = mService.noteOperationForDevice(op, uid, packageName, attributionTag, - virtualDeviceId, collectionMode == COLLECT_ASYNC, message, - shouldCollectMessage); + SyncNotedAppOp syncOp = null; + boolean isNoteOpDuplicated = false; + if (isNoteOpBatchingSupported()) { + int mode = sAppOpModeCache.query( + new AppOpModeQuery(op, uid, packageName, virtualDeviceId, attributionTag, + "noteOpNoThrow")); + // For FOREGROUND mode, we still need to make a binder call to the system service + // to translate it to ALLOWED or IGNORED. So no batching is needed. + if (mode != MODE_FOREGROUND) { + isNoteOpDuplicated = batchDuplicateNoteOps(op, uid, packageName, attributionTag, + virtualDeviceId, message, + collectionMode == COLLECT_ASYNC, shouldCollectMessage); + + syncOp = new SyncNotedAppOp(mode, op, attributionTag, packageName); + } + } + + if (!isNoteOpDuplicated) { + if (virtualDeviceId == Context.DEVICE_ID_DEFAULT) { + syncOp = mService.noteOperation(op, uid, packageName, attributionTag, + collectionMode == COLLECT_ASYNC, message, shouldCollectMessage); + } else { + syncOp = mService.noteOperationForDevice(op, uid, packageName, attributionTag, + virtualDeviceId, collectionMode == COLLECT_ASYNC, message, + shouldCollectMessage); + } } + if (syncOp.getOpMode() == MODE_ALLOWED) { if (collectionMode == COLLECT_SELF) { collectNotedOpForSelf(syncOp); diff --git a/core/java/android/app/AppOpsManagerInternal.java b/core/java/android/app/AppOpsManagerInternal.java index b21defbcc0e3..8b7ea0f8b46a 100644 --- a/core/java/android/app/AppOpsManagerInternal.java +++ b/core/java/android/app/AppOpsManagerInternal.java @@ -29,7 +29,7 @@ import com.android.internal.app.IAppOpsCallback; import com.android.internal.util.function.DodecFunction; import com.android.internal.util.function.HexConsumer; import com.android.internal.util.function.HexFunction; -import com.android.internal.util.function.OctFunction; +import com.android.internal.util.function.NonaFunction; import com.android.internal.util.function.QuadFunction; import com.android.internal.util.function.UndecFunction; @@ -86,9 +86,9 @@ public abstract class AppOpsManagerInternal { */ SyncNotedAppOp noteOperation(int code, int uid, @Nullable String packageName, @Nullable String featureId, int virtualDeviceId, boolean shouldCollectAsyncNotedOp, - @Nullable String message, boolean shouldCollectMessage, - @NonNull OctFunction<Integer, Integer, String, String, Integer, Boolean, String, - Boolean, SyncNotedAppOp> superImpl); + @Nullable String message, boolean shouldCollectMessage, int notedCount, + @NonNull NonaFunction<Integer, Integer, String, String, Integer, Boolean, String, + Boolean, Integer, SyncNotedAppOp> superImpl); /** * Allows overriding note proxy operation behavior. diff --git a/core/java/com/android/internal/app/IAppOpsService.aidl b/core/java/com/android/internal/app/IAppOpsService.aidl index 2cfc680a3fe8..f01aa80fab4f 100644 --- a/core/java/com/android/internal/app/IAppOpsService.aidl +++ b/core/java/com/android/internal/app/IAppOpsService.aidl @@ -163,4 +163,5 @@ interface IAppOpsService { void finishOperationForDevice(IBinder clientId, int code, int uid, String packageName, @nullable String attributionTag, int virtualDeviceId); List<AppOpsManager.PackageOps> getPackagesForOpsForDevice(in int[] ops, String persistentDeviceId); + oneway void noteOperationsInBatch(in Map batchedNoteOps); } diff --git a/services/core/java/com/android/server/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java index 06c586f5e9c2..295e0443371d 100644 --- a/services/core/java/com/android/server/appop/AppOpsService.java +++ b/services/core/java/com/android/server/appop/AppOpsService.java @@ -3191,7 +3191,7 @@ public class AppOpsService extends IAppOpsService.Stub { resolveProxyPackageName, proxyAttributionTag, proxyVirtualDeviceId, Process.INVALID_UID, null, null, Context.DEVICE_ID_DEFAULT, proxyFlags, !isProxyTrusted, - "proxy " + message, shouldCollectMessage); + "proxy " + message, shouldCollectMessage, 1); if (proxyReturn.getOpMode() != AppOpsManager.MODE_ALLOWED) { return new SyncNotedAppOp(proxyReturn.getOpMode(), code, proxiedAttributionTag, proxiedPackageName); @@ -3210,7 +3210,20 @@ public class AppOpsService extends IAppOpsService.Stub { return noteOperationUnchecked(code, proxiedUid, resolveProxiedPackageName, proxiedAttributionTag, proxiedVirtualDeviceId, proxyUid, resolveProxyPackageName, proxyAttributionTag, proxyVirtualDeviceId, proxiedFlags, shouldCollectAsyncNotedOp, - message, shouldCollectMessage); + message, shouldCollectMessage, 1); + } + + @Override + public void noteOperationsInBatch(Map batchedNoteOps) { + for (var entry : ((Map<AppOpsManager.NotedOp, Integer>) batchedNoteOps).entrySet()) { + AppOpsManager.NotedOp notedOp = entry.getKey(); + int notedCount = entry.getValue(); + mCheckOpsDelegateDispatcher.noteOperation( + notedOp.getOp(), notedOp.getUid(), notedOp.getPackageName(), + notedOp.getAttributionTag(), notedOp.getVirtualDeviceId(), + notedOp.getShouldCollectAsyncNotedOp(), notedOp.getMessage(), + notedOp.getShouldCollectMessage(), notedCount); + } } @Override @@ -3228,7 +3241,7 @@ public class AppOpsService extends IAppOpsService.Stub { } return mCheckOpsDelegateDispatcher.noteOperation(code, uid, packageName, attributionTag, Context.DEVICE_ID_DEFAULT, shouldCollectAsyncNotedOp, message, - shouldCollectMessage); + shouldCollectMessage, 1); } @Override @@ -3237,13 +3250,12 @@ public class AppOpsService extends IAppOpsService.Stub { String message, boolean shouldCollectMessage) { return mCheckOpsDelegateDispatcher.noteOperation(code, uid, packageName, attributionTag, virtualDeviceId, shouldCollectAsyncNotedOp, message, - shouldCollectMessage); + shouldCollectMessage, 1); } private SyncNotedAppOp noteOperationImpl(int code, int uid, @Nullable String packageName, - @Nullable String attributionTag, int virtualDeviceId, - boolean shouldCollectAsyncNotedOp, @Nullable String message, - boolean shouldCollectMessage) { + @Nullable String attributionTag, int virtualDeviceId, boolean shouldCollectAsyncNotedOp, + @Nullable String message, boolean shouldCollectMessage, int notedCount) { String resolvedPackageName; if (!shouldUseNewCheckOp()) { verifyIncomingUid(uid); @@ -3278,14 +3290,14 @@ public class AppOpsService extends IAppOpsService.Stub { return noteOperationUnchecked(code, uid, resolvedPackageName, attributionTag, virtualDeviceId, Process.INVALID_UID, null, null, Context.DEVICE_ID_DEFAULT, AppOpsManager.OP_FLAG_SELF, shouldCollectAsyncNotedOp, - message, shouldCollectMessage); + message, shouldCollectMessage, notedCount); } private SyncNotedAppOp noteOperationUnchecked(int code, int uid, @NonNull String packageName, @Nullable String attributionTag, int virtualDeviceId, int proxyUid, String proxyPackageName, @Nullable String proxyAttributionTag, int proxyVirtualDeviceId, @OpFlags int flags, boolean shouldCollectAsyncNotedOp, @Nullable String message, - boolean shouldCollectMessage) { + boolean shouldCollectMessage, int notedCount) { PackageVerificationResult pvr; try { pvr = verifyAndGetBypass(uid, packageName, attributionTag, proxyPackageName); @@ -3388,11 +3400,11 @@ public class AppOpsService extends IAppOpsService.Stub { virtualDeviceId, flags, AppOpsManager.MODE_ALLOWED); attributedOp.accessed(proxyUid, proxyPackageName, proxyAttributionTag, - getPersistentId(proxyVirtualDeviceId), uidState.getState(), flags); + getPersistentId(proxyVirtualDeviceId), uidState.getState(), flags, notedCount); if (shouldCollectAsyncNotedOp) { collectAsyncNotedOp(uid, packageName, code, attributionTag, flags, message, - shouldCollectMessage); + shouldCollectMessage, notedCount); } return new SyncNotedAppOp(AppOpsManager.MODE_ALLOWED, code, attributionTag, @@ -3551,7 +3563,7 @@ public class AppOpsService extends IAppOpsService.Stub { */ private void collectAsyncNotedOp(int uid, @NonNull String packageName, int opCode, @Nullable String attributionTag, @OpFlags int flags, @NonNull String message, - boolean shouldCollectMessage) { + boolean shouldCollectMessage, int notedCount) { Objects.requireNonNull(message); int callingUid = Binder.getCallingUid(); @@ -3559,42 +3571,51 @@ public class AppOpsService extends IAppOpsService.Stub { final long token = Binder.clearCallingIdentity(); try { synchronized (this) { - Pair<String, Integer> key = getAsyncNotedOpsKey(packageName, uid); - - RemoteCallbackList<IAppOpsAsyncNotedCallback> callbacks = mAsyncOpWatchers.get(key); - AsyncNotedAppOp asyncNotedOp = new AsyncNotedAppOp(opCode, callingUid, - attributionTag, message, System.currentTimeMillis()); - final boolean[] wasNoteForwarded = {false}; - if ((flags & (OP_FLAG_SELF | OP_FLAG_TRUSTED_PROXIED)) != 0 && shouldCollectMessage) { reportRuntimeAppOpAccessMessageAsyncLocked(uid, packageName, opCode, attributionTag, message); } - if (callbacks != null) { + Pair<String, Integer> key = getAsyncNotedOpsKey(packageName, uid); + RemoteCallbackList<IAppOpsAsyncNotedCallback> callbacks = mAsyncOpWatchers.get(key); + if (callbacks == null) { + return; + } + + final boolean[] wasNoteForwarded = {false}; + if (Flags.rateLimitBatchedNoteOpAsyncCallbacksEnabled()) { + notedCount = 1; + } + + for (int i = 0; i < notedCount; i++) { + AsyncNotedAppOp asyncNotedOp = new AsyncNotedAppOp(opCode, callingUid, + attributionTag, message, System.currentTimeMillis()); + wasNoteForwarded[0] = false; callbacks.broadcast((cb) -> { try { cb.opNoted(asyncNotedOp); wasNoteForwarded[0] = true; } catch (RemoteException e) { Slog.e(TAG, - "Could not forward noteOp of " + opCode + " to " + packageName + "Could not forward noteOp of " + opCode + " to " + + packageName + "/" + uid + "(" + attributionTag + ")", e); } }); - } - if (!wasNoteForwarded[0]) { - ArrayList<AsyncNotedAppOp> unforwardedOps = mUnforwardedAsyncNotedOps.get(key); - if (unforwardedOps == null) { - unforwardedOps = new ArrayList<>(1); - mUnforwardedAsyncNotedOps.put(key, unforwardedOps); - } + if (!wasNoteForwarded[0]) { + ArrayList<AsyncNotedAppOp> unforwardedOps = mUnforwardedAsyncNotedOps.get( + key); + if (unforwardedOps == null) { + unforwardedOps = new ArrayList<>(1); + mUnforwardedAsyncNotedOps.put(key, unforwardedOps); + } - unforwardedOps.add(asyncNotedOp); - if (unforwardedOps.size() > MAX_UNFORWARDED_OPS) { - unforwardedOps.remove(0); + unforwardedOps.add(asyncNotedOp); + if (unforwardedOps.size() > MAX_UNFORWARDED_OPS) { + unforwardedOps.remove(0); + } } } } @@ -4026,7 +4047,7 @@ public class AppOpsService extends IAppOpsService.Stub { if (shouldCollectAsyncNotedOp && !isRestricted) { collectAsyncNotedOp(uid, packageName, code, attributionTag, AppOpsManager.OP_FLAG_SELF, - message, shouldCollectMessage); + message, shouldCollectMessage, 1); } return new SyncNotedAppOp(isRestricted ? MODE_IGNORED : MODE_ALLOWED, code, attributionTag, @@ -7574,34 +7595,36 @@ public class AppOpsService extends IAppOpsService.Stub { public SyncNotedAppOp noteOperation(int code, int uid, String packageName, String attributionTag, int virtualDeviceId, boolean shouldCollectAsyncNotedOp, - String message, boolean shouldCollectMessage) { + String message, boolean shouldCollectMessage, int notedCount) { if (mPolicy != null) { if (mCheckOpsDelegate != null) { return mPolicy.noteOperation(code, uid, packageName, attributionTag, virtualDeviceId, shouldCollectAsyncNotedOp, message, - shouldCollectMessage, this::noteDelegateOperationImpl + shouldCollectMessage, notedCount, this::noteDelegateOperationImpl ); } else { return mPolicy.noteOperation(code, uid, packageName, attributionTag, virtualDeviceId, shouldCollectAsyncNotedOp, message, - shouldCollectMessage, AppOpsService.this::noteOperationImpl + shouldCollectMessage, notedCount, AppOpsService.this::noteOperationImpl ); } } else if (mCheckOpsDelegate != null) { return noteDelegateOperationImpl(code, uid, packageName, attributionTag, - virtualDeviceId, shouldCollectAsyncNotedOp, message, shouldCollectMessage); + virtualDeviceId, shouldCollectAsyncNotedOp, message, shouldCollectMessage, + notedCount); } return noteOperationImpl(code, uid, packageName, attributionTag, - virtualDeviceId, shouldCollectAsyncNotedOp, message, shouldCollectMessage); + virtualDeviceId, shouldCollectAsyncNotedOp, message, shouldCollectMessage, + notedCount); } private SyncNotedAppOp noteDelegateOperationImpl(int code, int uid, @Nullable String packageName, @Nullable String featureId, int virtualDeviceId, boolean shouldCollectAsyncNotedOp, @Nullable String message, - boolean shouldCollectMessage) { + boolean shouldCollectMessage, int notedCount) { return mCheckOpsDelegate.noteOperation(code, uid, packageName, featureId, virtualDeviceId, shouldCollectAsyncNotedOp, message, shouldCollectMessage, - AppOpsService.this::noteOperationImpl + notedCount, AppOpsService.this::noteOperationImpl ); } diff --git a/services/core/java/com/android/server/appop/AttributedOp.java b/services/core/java/com/android/server/appop/AttributedOp.java index 314664b0a79d..4d114b4ad4ac 100644 --- a/services/core/java/com/android/server/appop/AttributedOp.java +++ b/services/core/java/com/android/server/appop/AttributedOp.java @@ -100,10 +100,12 @@ final class AttributedOp { * @param proxyDeviceId The device Id of the proxy * @param uidState UID state of the app noteOp/startOp was called for * @param flags OpFlags of the call + * @param accessCount The number of times the op is accessed */ public void accessed(int proxyUid, @Nullable String proxyPackageName, @Nullable String proxyAttributionTag, @Nullable String proxyDeviceId, - @AppOpsManager.UidState int uidState, @AppOpsManager.OpFlags int flags) { + @AppOpsManager.UidState int uidState, @AppOpsManager.OpFlags int flags, + int accessCount) { long accessTime = System.currentTimeMillis(); accessed(accessTime, -1, proxyUid, proxyPackageName, proxyAttributionTag, proxyDeviceId, uidState, flags); @@ -111,7 +113,7 @@ final class AttributedOp { mAppOpsService.mHistoricalRegistry.incrementOpAccessedCount(parent.op, parent.uid, parent.packageName, persistentDeviceId, tag, uidState, flags, accessTime, AppOpsManager.ATTRIBUTION_FLAGS_NONE, AppOpsManager.ATTRIBUTION_CHAIN_ID_NONE, - DiscreteRegistry.ACCESS_TYPE_NOTE_OP); + DiscreteRegistry.ACCESS_TYPE_NOTE_OP, accessCount); } /** @@ -255,7 +257,7 @@ final class AttributedOp { if (isStarted) { mAppOpsService.mHistoricalRegistry.incrementOpAccessedCount(parent.op, parent.uid, parent.packageName, persistentDeviceId, tag, uidState, flags, startTime, - attributionFlags, attributionChainId, DiscreteRegistry.ACCESS_TYPE_START_OP); + attributionFlags, attributionChainId, DiscreteRegistry.ACCESS_TYPE_START_OP, 1); } } @@ -451,7 +453,7 @@ final class AttributedOp { mAppOpsService.mHistoricalRegistry.incrementOpAccessedCount(parent.op, parent.uid, parent.packageName, persistentDeviceId, tag, event.getUidState(), event.getFlags(), startTime, event.getAttributionFlags(), - event.getAttributionChainId(), DiscreteRegistry.ACCESS_TYPE_RESUME_OP); + event.getAttributionChainId(), DiscreteRegistry.ACCESS_TYPE_RESUME_OP, 1); if (shouldSendActive) { mAppOpsService.scheduleOpActiveChangedIfNeededLocked(parent.op, parent.uid, parent.packageName, tag, event.getVirtualDeviceId(), true, diff --git a/services/core/java/com/android/server/appop/HistoricalRegistry.java b/services/core/java/com/android/server/appop/HistoricalRegistry.java index 6b0253864e2b..5e67f26ba1f6 100644 --- a/services/core/java/com/android/server/appop/HistoricalRegistry.java +++ b/services/core/java/com/android/server/appop/HistoricalRegistry.java @@ -475,7 +475,7 @@ final class HistoricalRegistry { @NonNull String deviceId, @Nullable String attributionTag, @UidState int uidState, @OpFlags int flags, long accessTime, @AppOpsManager.AttributionFlags int attributionFlags, int attributionChainId, - @DiscreteRegistry.AccessType int accessType) { + @DiscreteRegistry.AccessType int accessType, int accessCount) { synchronized (mInMemoryLock) { if (mMode == AppOpsManager.HISTORICAL_MODE_ENABLED_ACTIVE) { if (!isPersistenceInitializedMLocked()) { @@ -484,7 +484,7 @@ final class HistoricalRegistry { } getUpdatedPendingHistoricalOpsMLocked( System.currentTimeMillis()).increaseAccessCount(op, uid, packageName, - attributionTag, uidState, flags, 1); + attributionTag, uidState, flags, accessCount); mDiscreteRegistry.recordDiscreteAccess(uid, packageName, deviceId, op, attributionTag, flags, uidState, accessTime, -1, attributionFlags, diff --git a/services/core/java/com/android/server/pm/permission/AccessCheckDelegate.java b/services/core/java/com/android/server/pm/permission/AccessCheckDelegate.java index e9cb279439a6..e989d6875d15 100644 --- a/services/core/java/com/android/server/pm/permission/AccessCheckDelegate.java +++ b/services/core/java/com/android/server/pm/permission/AccessCheckDelegate.java @@ -40,7 +40,7 @@ import com.android.internal.util.ArrayUtils; import com.android.internal.util.function.DodecFunction; import com.android.internal.util.function.HexConsumer; import com.android.internal.util.function.HexFunction; -import com.android.internal.util.function.OctFunction; +import com.android.internal.util.function.NonaFunction; import com.android.internal.util.function.QuadFunction; import com.android.internal.util.function.TriFunction; import com.android.internal.util.function.UndecFunction; @@ -351,22 +351,22 @@ public interface AccessCheckDelegate extends CheckPermissionDelegate, CheckOpsDe @Override public SyncNotedAppOp noteOperation(int code, int uid, @Nullable String packageName, @Nullable String featureId, int virtualDeviceId, boolean shouldCollectAsyncNotedOp, - @Nullable String message, boolean shouldCollectMessage, - @NonNull OctFunction<Integer, Integer, String, String, Integer, Boolean, String, - Boolean, SyncNotedAppOp> superImpl) { + @Nullable String message, boolean shouldCollectMessage, int notedCount, + @NonNull NonaFunction<Integer, Integer, String, String, Integer, Boolean, String, + Boolean, Integer, SyncNotedAppOp> superImpl) { if (uid == mDelegateAndOwnerUid && isDelegateOp(code)) { final int shellUid = UserHandle.getUid(UserHandle.getUserId(uid), Process.SHELL_UID); final long identity = Binder.clearCallingIdentity(); try { return superImpl.apply(code, shellUid, SHELL_PKG, featureId, virtualDeviceId, - shouldCollectAsyncNotedOp, message, shouldCollectMessage); + shouldCollectAsyncNotedOp, message, shouldCollectMessage, notedCount); } finally { Binder.restoreCallingIdentity(identity); } } return superImpl.apply(code, uid, packageName, featureId, virtualDeviceId, - shouldCollectAsyncNotedOp, message, shouldCollectMessage); + shouldCollectAsyncNotedOp, message, shouldCollectMessage, notedCount); } @Override diff --git a/services/core/java/com/android/server/policy/AppOpsPolicy.java b/services/core/java/com/android/server/policy/AppOpsPolicy.java index 3f9144f0d980..dea52fd7cd99 100644 --- a/services/core/java/com/android/server/policy/AppOpsPolicy.java +++ b/services/core/java/com/android/server/policy/AppOpsPolicy.java @@ -53,7 +53,7 @@ import com.android.internal.annotations.GuardedBy; import com.android.internal.util.function.DodecFunction; import com.android.internal.util.function.HexConsumer; import com.android.internal.util.function.HexFunction; -import com.android.internal.util.function.OctFunction; +import com.android.internal.util.function.NonaFunction; import com.android.internal.util.function.QuadFunction; import com.android.internal.util.function.UndecFunction; import com.android.server.LocalServices; @@ -248,11 +248,12 @@ public final class AppOpsPolicy implements AppOpsManagerInternal.CheckOpsDelegat public SyncNotedAppOp noteOperation(int code, int uid, @Nullable String packageName, @Nullable String attributionTag, int virtualDeviceId, boolean shouldCollectAsyncNotedOp, @Nullable String message, - boolean shouldCollectMessage, @NonNull OctFunction<Integer, Integer, String, String, - Integer, Boolean, String, Boolean, SyncNotedAppOp> superImpl) { + boolean shouldCollectMessage, int notedCount, + @NonNull NonaFunction<Integer, Integer, String, String, + Integer, Boolean, String, Boolean, Integer, SyncNotedAppOp> superImpl) { return superImpl.apply(resolveDatasourceOp(code, uid, packageName, attributionTag), resolveUid(code, uid), packageName, attributionTag, virtualDeviceId, - shouldCollectAsyncNotedOp, message, shouldCollectMessage); + shouldCollectAsyncNotedOp, message, shouldCollectMessage, notedCount); } @Override |