Merge "Rename AppOpsCollector -> OnOpNotedCallback" into rvc-dev
diff --git a/api/current.txt b/api/current.txt
index 283d9b6..542a714 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -4368,7 +4368,7 @@
method @Deprecated public int noteProxyOpNoThrow(@NonNull String, @Nullable String, int);
method public int noteProxyOpNoThrow(@NonNull String, @Nullable String, int, @Nullable String, @Nullable String);
method @Nullable public static String permissionToOp(@NonNull String);
- method public void setNotedAppOpsCollector(@Nullable android.app.AppOpsManager.AppOpsCollector);
+ method public void setOnOpNotedCallback(@Nullable java.util.concurrent.Executor, @Nullable android.app.AppOpsManager.OnOpNotedCallback);
method @Deprecated public int startOp(@NonNull String, int, @NonNull String);
method public int startOp(@NonNull String, int, @Nullable String, @Nullable String, @Nullable String);
method @Deprecated public int startOpNoThrow(@NonNull String, int, @NonNull String);
@@ -4424,14 +4424,6 @@
field public static final int WATCH_FOREGROUND_CHANGES = 1; // 0x1
}
- public abstract static class AppOpsManager.AppOpsCollector {
- ctor public AppOpsManager.AppOpsCollector();
- method @NonNull public java.util.concurrent.Executor getAsyncNotedExecutor();
- method public abstract void onAsyncNoted(@NonNull android.app.AsyncNotedAppOp);
- method public abstract void onNoted(@NonNull android.app.SyncNotedAppOp);
- method public abstract void onSelfNoted(@NonNull android.app.SyncNotedAppOp);
- }
-
public static interface AppOpsManager.OnOpActiveChangedListener {
method public void onOpActiveChanged(@NonNull String, int, @NonNull String, boolean);
}
@@ -4440,6 +4432,13 @@
method public void onOpChanged(String, String);
}
+ public abstract static class AppOpsManager.OnOpNotedCallback {
+ ctor public AppOpsManager.OnOpNotedCallback();
+ method public abstract void onAsyncNoted(@NonNull android.app.AsyncNotedAppOp);
+ method public abstract void onNoted(@NonNull android.app.SyncNotedAppOp);
+ method public abstract void onSelfNoted(@NonNull android.app.SyncNotedAppOp);
+ }
+
public class Application extends android.content.ContextWrapper implements android.content.ComponentCallbacks2 {
ctor public Application();
method public static String getProcessName();
@@ -4591,7 +4590,7 @@
method @NonNull public String getMessage();
method @IntRange(from=0) public int getNotingUid();
method @NonNull public String getOp();
- method @IntRange(from=0) public long getTime();
+ method public long getTime();
method public void writeToParcel(@NonNull android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.app.AsyncNotedAppOp> CREATOR;
}
diff --git a/api/system-removed.txt b/api/system-removed.txt
index 07b8969..23e2499 100644
--- a/api/system-removed.txt
+++ b/api/system-removed.txt
@@ -11,6 +11,12 @@
public class AppOpsManager {
method @Deprecated @NonNull @RequiresPermission(android.Manifest.permission.GET_APP_OPS_STATS) public java.util.List<android.app.AppOpsManager.PackageOps> getOpsForPackage(int, @NonNull String, @Nullable int[]);
+ method @Deprecated public void setNotedAppOpsCollector(@Nullable android.app.AppOpsManager.AppOpsCollector);
+ }
+
+ @Deprecated public abstract static class AppOpsManager.AppOpsCollector extends android.app.AppOpsManager.OnOpNotedCallback {
+ ctor public AppOpsManager.AppOpsCollector();
+ method @NonNull public java.util.concurrent.Executor getAsyncNotedExecutor();
}
public class Notification implements android.os.Parcelable {
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index e2ecf85..eeb5d41 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -162,7 +162,7 @@
* might also make sense inside of a single app if the access is forwarded between two features of
* the app.
*
- * <p>An app can register an {@link AppOpsCollector} to get informed about what accesses the
+ * <p>An app can register an {@link OnOpNotedCallback} to get informed about what accesses the
* system is tracking for it. As each runtime permission has an associated app-op this API is
* particularly useful for an app that want to find unexpected private data accesses.
*/
@@ -206,16 +206,16 @@
private static final Object sLock = new Object();
- /** Current {@link AppOpsCollector}. Change via {@link #setNotedAppOpsCollector} */
+ /** Current {@link OnOpNotedCallback}. Change via {@link #setOnOpNotedCallback} */
@GuardedBy("sLock")
- private static @Nullable AppOpsCollector sNotedAppOpsCollector;
+ private static @Nullable OnOpNotedCallback sOnOpNotedCallback;
/**
* Additional collector that collect accesses and forwards a few of them them via
* {@link IAppOpsService#reportRuntimeAppOpAccessMessageAndGetConfig}.
*/
- private static AppOpsCollector sMessageCollector =
- new AppOpsCollector() {
+ private static OnOpNotedCallback sMessageCollector =
+ new OnOpNotedCallback() {
@Override
public void onNoted(@NonNull SyncNotedAppOp op) {
reportStackTraceIfNeeded(op);
@@ -7800,8 +7800,8 @@
*/
private void collectNotedOpForSelf(int op, @Nullable String featureId) {
synchronized (sLock) {
- if (sNotedAppOpsCollector != null) {
- sNotedAppOpsCollector.onSelfNoted(new SyncNotedAppOp(op, featureId));
+ if (sOnOpNotedCallback != null) {
+ sOnOpNotedCallback.onSelfNoted(new SyncNotedAppOp(op, featureId));
}
}
sMessageCollector.onSelfNoted(new SyncNotedAppOp(op, featureId));
@@ -7950,8 +7950,8 @@
synchronized (sLock) {
for (int code = notedAppOps.nextSetBit(0); code != -1;
code = notedAppOps.nextSetBit(code + 1)) {
- if (sNotedAppOpsCollector != null) {
- sNotedAppOpsCollector.onNoted(new SyncNotedAppOp(code, featureId));
+ if (sOnOpNotedCallback != null) {
+ sOnOpNotedCallback.onNoted(new SyncNotedAppOp(code, featureId));
}
}
}
@@ -7964,33 +7964,45 @@
}
/**
- * Register a new {@link AppOpsCollector}.
+ * Set a new {@link OnOpNotedCallback}.
*
- * <p>There can only ever be one collector per process. If there currently is a collector
- * registered, it will be unregistered.
+ * <p>There can only ever be one collector per process. If there currently is another callback
+ * set, this will fail.
*
- * <p><b>Only appops related to dangerous permissions are collected.</b>
+ * @param asyncExecutor executor to execute {@link OnOpNotedCallback#onAsyncNoted} on, {@code
+ * null} to unset
+ * @param callback listener to set, {@code null} to unset
*
- * @param collector The collector to set or {@code null} to unregister.
+ * @throws IllegalStateException If another callback is already registered
*/
- public void setNotedAppOpsCollector(@Nullable AppOpsCollector collector) {
+ public void setOnOpNotedCallback(@Nullable @CallbackExecutor Executor asyncExecutor,
+ @Nullable OnOpNotedCallback callback) {
+ Preconditions.checkState((callback == null) == (asyncExecutor == null));
+
synchronized (sLock) {
- if (sNotedAppOpsCollector != null) {
+ if (callback == null) {
+ Preconditions.checkState(sOnOpNotedCallback != null,
+ "No callback is currently registered");
+
try {
mService.stopWatchingAsyncNoted(mContext.getPackageName(),
- sNotedAppOpsCollector.mAsyncCb);
+ sOnOpNotedCallback.mAsyncCb);
} catch (RemoteException e) {
e.rethrowFromSystemServer();
}
- }
- sNotedAppOpsCollector = collector;
+ sOnOpNotedCallback = null;
+ } else {
+ Preconditions.checkState(sOnOpNotedCallback == null,
+ "Another callback is already registered");
- if (sNotedAppOpsCollector != null) {
+ callback.mAsyncExecutor = asyncExecutor;
+ sOnOpNotedCallback = callback;
+
List<AsyncNotedAppOp> missedAsyncOps = null;
try {
mService.startWatchingAsyncNoted(mContext.getPackageName(),
- sNotedAppOpsCollector.mAsyncCb);
+ sOnOpNotedCallback.mAsyncCb);
missedAsyncOps = mService.extractAsyncOps(mContext.getPackageName());
} catch (RemoteException e) {
e.rethrowFromSystemServer();
@@ -8000,10 +8012,9 @@
int numMissedAsyncOps = missedAsyncOps.size();
for (int i = 0; i < numMissedAsyncOps; i++) {
final AsyncNotedAppOp asyncNotedAppOp = missedAsyncOps.get(i);
- if (sNotedAppOpsCollector != null) {
- sNotedAppOpsCollector.getAsyncNotedExecutor().execute(
- () -> sNotedAppOpsCollector.onAsyncNoted(
- asyncNotedAppOp));
+ if (sOnOpNotedCallback != null) {
+ sOnOpNotedCallback.getAsyncNotedExecutor().execute(
+ () -> sOnOpNotedCallback.onAsyncNoted(asyncNotedAppOp));
}
}
}
@@ -8011,27 +8022,50 @@
}
}
+ // TODO moltmann: Remove
/**
- * @return {@code true} iff the process currently is currently collecting noted appops.
+ * Will be removed before R ships, leave it just to not break apps immediately.
*
- * @see #setNotedAppOpsCollector(AppOpsCollector)
+ * @removed
*
* @hide
*/
- public static boolean isCollectingNotedAppOps() {
- return sNotedAppOpsCollector != null;
+ @SystemApi
+ @Deprecated
+ public void setNotedAppOpsCollector(@Nullable AppOpsCollector collector) {
+ synchronized (sLock) {
+ if (collector != null) {
+ if (isListeningForOpNoted()) {
+ setOnOpNotedCallback(null, null);
+ }
+ setOnOpNotedCallback(new HandlerExecutor(Handler.getMain()), collector);
+ } else if (sOnOpNotedCallback != null) {
+ setOnOpNotedCallback(null, null);
+ }
+ }
}
/**
- * Callback an app can {@link #setNotedAppOpsCollector register} to monitor the app-ops the
- * system has tracked for it. I.e. each time any app calls {@link #noteOp} or {@link #startOp}
- * one of the callback methods of this object is called.
+ * @return {@code true} iff the process currently is currently collecting noted appops.
*
- * <p><b>There will be a callback for all app-ops related to runtime permissions, but not
+ * @see #setOnOpNotedCallback
+ *
+ * @hide
+ */
+ public static boolean isListeningForOpNoted() {
+ return sOnOpNotedCallback != null;
+ }
+
+ /**
+ * Callback an app can {@link #setOnOpNotedCallback set} to monitor the app-ops the
+ * system has tracked for it. I.e. each time any app calls {@link #noteOp} or {@link #startOp}
+ * one of a method of this object is called.
+ *
+ * <p><b>There will be a call for all app-ops related to runtime permissions, but not
* necessarily for all other app-ops.
*
* <pre>
- * setNotedAppOpsCollector(new AppOpsCollector() {
+ * setOnOpNotedCallback(getMainExecutor(), new OnOpNotedCallback() {
* ArraySet<Pair<String, String>> opsNotedForThisProcess = new ArraySet<>();
*
* private synchronized void addAccess(String op, String accessLocation) {
@@ -8056,24 +8090,36 @@
* });
* </pre>
*
- * @see #setNotedAppOpsCollector
+ * @see #setOnOpNotedCallback
*/
- public abstract static class AppOpsCollector {
+ public abstract static class OnOpNotedCallback {
+ private @NonNull Executor mAsyncExecutor;
+
/** Callback registered with the system. This will receive the async notes ops */
private final IAppOpsAsyncNotedCallback mAsyncCb = new IAppOpsAsyncNotedCallback.Stub() {
@Override
public void opNoted(AsyncNotedAppOp op) {
Objects.requireNonNull(op);
- getAsyncNotedExecutor().execute(() -> onAsyncNoted(op));
+ long token = Binder.clearCallingIdentity();
+ try {
+ getAsyncNotedExecutor().execute(() -> onAsyncNoted(op));
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
}
};
+ // TODO moltmann: Remove
/**
+ * Will be removed before R ships.
+ *
* @return The executor for the system to use when calling {@link #onAsyncNoted}.
+ *
+ * @hide
*/
- public @NonNull Executor getAsyncNotedExecutor() {
- return new HandlerExecutor(Handler.getMain());
+ protected @NonNull Executor getAsyncNotedExecutor() {
+ return mAsyncExecutor;
}
/**
@@ -8083,7 +8129,7 @@
* <p>Called on the calling thread before the API returns. This allows the app to e.g.
* collect stack traces to figure out where the access came from.
*
- * @param op The op noted
+ * @param op op noted
*/
public abstract void onNoted(@NonNull SyncNotedAppOp op);
@@ -8093,7 +8139,7 @@
* <p>This is very similar to {@link #onNoted} only that the tracking was not caused by the
* API provider in a separate process, but by one in the app's own process.
*
- * @param op The op noted
+ * @param op op noted
*/
public abstract void onSelfNoted(@NonNull SyncNotedAppOp op);
@@ -8105,14 +8151,30 @@
* guaranteed. Due to how async calls work in Android this might even be delivered slightly
* before the private data is delivered to the app.
*
- * <p>If the app is not running or no {@link AppOpsCollector} is registered a small amount
- * of noted app-ops are buffered and then delivered as soon as a collector is registered.
+ * <p>If the app is not running or no {@link OnOpNotedCallback} is registered a small amount
+ * of noted app-ops are buffered and then delivered as soon as a listener is registered.
*
- * @param asyncOp The op noted
+ * @param asyncOp op noted
*/
public abstract void onAsyncNoted(@NonNull AsyncNotedAppOp asyncOp);
}
+ // TODO moltmann: Remove
+ /**
+ * Will be removed before R ships, leave it just to not break apps immediately.
+ *
+ * @removed
+ *
+ * @hide
+ */
+ @SystemApi
+ @Deprecated
+ public abstract static class AppOpsCollector extends OnOpNotedCallback {
+ public @NonNull Executor getAsyncNotedExecutor() {
+ return new HandlerExecutor(Handler.getMain());
+ }
+ };
+
/**
* Generate a stack trace used for noted app-ops logging.
*
diff --git a/core/java/android/app/AsyncNotedAppOp.java b/core/java/android/app/AsyncNotedAppOp.java
index c2b2063..4d955db 100644
--- a/core/java/android/app/AsyncNotedAppOp.java
+++ b/core/java/android/app/AsyncNotedAppOp.java
@@ -16,6 +16,7 @@
package android.app;
+import android.annotation.CurrentTimeMillisLong;
import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -27,10 +28,11 @@
/**
* When an {@link AppOpsManager#noteOp(String, int, String, String, String) app-op is noted} and the
- * app the app-op is noted for has a {@link AppOpsManager.AppOpsCollector} registered the note-event
- * needs to be delivered to the collector. Usually this is done via an {@link SyncNotedAppOp}, but
- * in some cases this is not possible. In this case an {@link AsyncNotedAppOp} is send to the system
- * server and then forwarded to the {@link AppOpsManager.AppOpsCollector} in the app.
+ * app the app-op is noted for has a {@link AppOpsManager.OnOpNotedCallback} registered the
+ * note-event needs to be delivered to the callback. Usually this is done via an
+ * {@link SyncNotedAppOp}, but in some cases this is not possible. In this case an
+ * {@link AsyncNotedAppOp} is send to the system server and then forwarded to the
+ * {@link AppOpsManager.OnOpNotedCallback} in the app.
*/
@Immutable
@DataClass(genEqualsHashCode = true,
@@ -53,7 +55,7 @@
private final @NonNull String mMessage;
/** Milliseconds since epoch when the op was noted */
- private final @IntRange(from = 0) long mTime;
+ private final @CurrentTimeMillisLong long mTime;
/**
* @return Op that was noted.
@@ -70,7 +72,7 @@
- // Code below generated by codegen v1.0.14.
+ // Code below generated by codegen v1.0.15.
//
// DO NOT MODIFY!
// CHECKSTYLE:OFF Generated code
@@ -104,7 +106,7 @@
@IntRange(from = 0) int notingUid,
@Nullable String featureId,
@NonNull String message,
- @IntRange(from = 0) long time) {
+ @CurrentTimeMillisLong long time) {
this.mOpCode = opCode;
com.android.internal.util.AnnotationValidations.validate(
IntRange.class, null, mOpCode,
@@ -119,8 +121,7 @@
NonNull.class, null, mMessage);
this.mTime = time;
com.android.internal.util.AnnotationValidations.validate(
- IntRange.class, null, mTime,
- "from", 0);
+ CurrentTimeMillisLong.class, null, mTime);
onConstructed();
}
@@ -153,7 +154,7 @@
* Milliseconds since epoch when the op was noted
*/
@DataClass.Generated.Member
- public @IntRange(from = 0) long getTime() {
+ public @CurrentTimeMillisLong long getTime() {
return mTime;
}
@@ -240,8 +241,7 @@
NonNull.class, null, mMessage);
this.mTime = time;
com.android.internal.util.AnnotationValidations.validate(
- IntRange.class, null, mTime,
- "from", 0);
+ CurrentTimeMillisLong.class, null, mTime);
onConstructed();
}
@@ -261,10 +261,10 @@
};
@DataClass.Generated(
- time = 1583375913345L,
- codegenVersion = "1.0.14",
+ time = 1583866178330L,
+ codegenVersion = "1.0.15",
sourceFile = "frameworks/base/core/java/android/app/AsyncNotedAppOp.java",
- inputSignatures = "private final @android.annotation.IntRange(from=0L) int mOpCode\nprivate final @android.annotation.IntRange(from=0L) int mNotingUid\nprivate final @android.annotation.Nullable java.lang.String mFeatureId\nprivate final @android.annotation.NonNull java.lang.String mMessage\nprivate final @android.annotation.IntRange(from=0L) long mTime\npublic @android.annotation.NonNull java.lang.String getOp()\nprivate void onConstructed()\nclass AsyncNotedAppOp extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genEqualsHashCode=true, genAidl=true, genHiddenConstructor=true)")
+ inputSignatures = "private final @android.annotation.IntRange(from=0L) int mOpCode\nprivate final @android.annotation.IntRange(from=0L) int mNotingUid\nprivate final @android.annotation.Nullable java.lang.String mFeatureId\nprivate final @android.annotation.NonNull java.lang.String mMessage\nprivate final @android.annotation.CurrentTimeMillisLong long mTime\npublic @android.annotation.NonNull java.lang.String getOp()\nprivate void onConstructed()\nclass AsyncNotedAppOp extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genEqualsHashCode=true, genAidl=true, genHiddenConstructor=true)")
@Deprecated
private void __metadata() {}
diff --git a/core/java/android/app/SyncNotedAppOp.java b/core/java/android/app/SyncNotedAppOp.java
index aa11b95..13b90ca 100644
--- a/core/java/android/app/SyncNotedAppOp.java
+++ b/core/java/android/app/SyncNotedAppOp.java
@@ -28,9 +28,9 @@
* Description of an app-op that was noted for the current process.
*
* <p>This is either delivered after a
- * {@link AppOpsManager.AppOpsCollector#onNoted(SyncNotedAppOp) two way binder call} or
+ * {@link AppOpsManager.OnOpNotedCallback#onNoted(SyncNotedAppOp) two way binder call} or
* when the app
- * {@link AppOpsManager.AppOpsCollector#onSelfNoted(SyncNotedAppOp) notes an app-op for
+ * {@link AppOpsManager.OnOpNotedCallback#onSelfNoted(SyncNotedAppOp) notes an app-op for
* itself}.
*/
@Immutable
diff --git a/core/java/android/os/BinderProxy.java b/core/java/android/os/BinderProxy.java
index dd3f9fd..20e5f24 100644
--- a/core/java/android/os/BinderProxy.java
+++ b/core/java/android/os/BinderProxy.java
@@ -526,7 +526,7 @@
final AppOpsManager.PausedNotedAppOpsCollection prevCollection =
AppOpsManager.pauseNotedAppOpsCollection();
- if ((flags & FLAG_ONEWAY) == 0 && AppOpsManager.isCollectingNotedAppOps()) {
+ if ((flags & FLAG_ONEWAY) == 0 && AppOpsManager.isListeningForOpNoted()) {
flags |= FLAG_COLLECT_NOTED_APP_OPS;
}