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;
         }