summaryrefslogtreecommitdiff
path: root/core/java/android/app/AppOpsManager.java
diff options
context:
space:
mode:
authorTreeHugger Robot <treehugger-gerrit@google.com>2018-02-20 18:46:57 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2018-02-20 18:46:57 +0000
commit414189fefe71beb998541cb2932b90f073ae8bcd (patch)
treeb4be11d6537f477ec1914eaba919cfba11c6289a /core/java/android/app/AppOpsManager.java
parent3feba764d6fe59056f3e38b3d7d2088890a29087 (diff)
parent2d20fb47f4a7162450f993728876c74762b93112 (diff)
Merge "APIs to watch active op changes"
Diffstat (limited to 'core/java/android/app/AppOpsManager.java')
-rw-r--r--core/java/android/app/AppOpsManager.java102
1 files changed, 100 insertions, 2 deletions
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index 1026550b9b6b..c5b3a4acd339 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -17,6 +17,7 @@
package android.app;
import android.Manifest;
+import android.annotation.NonNull;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.annotation.SystemService;
@@ -34,8 +35,10 @@ import android.os.UserHandle;
import android.os.UserManager;
import android.util.ArrayMap;
+import com.android.internal.app.IAppOpsActiveCallback;
import com.android.internal.app.IAppOpsCallback;
import com.android.internal.app.IAppOpsService;
+import com.android.internal.util.Preconditions;
import java.util.ArrayList;
import java.util.Arrays;
@@ -74,8 +77,9 @@ public class AppOpsManager {
final Context mContext;
final IAppOpsService mService;
- final ArrayMap<OnOpChangedListener, IAppOpsCallback> mModeWatchers
- = new ArrayMap<OnOpChangedListener, IAppOpsCallback>();
+ final ArrayMap<OnOpChangedListener, IAppOpsCallback> mModeWatchers = new ArrayMap<>();
+ final ArrayMap<OnOpActiveChangedListener, IAppOpsActiveCallback> mActiveWatchers =
+ new ArrayMap<>();
static IBinder sToken;
@@ -1532,6 +1536,23 @@ public class AppOpsManager {
}
/**
+ * Callback for notification of changes to operation active state.
+ *
+ * @hide
+ */
+ public interface OnOpActiveChangedListener {
+ /**
+ * Called when the active state of an app op changes.
+ *
+ * @param code The op code.
+ * @param uid The UID performing the operation.
+ * @param packageName The package performing the operation.
+ * @param active Whether the operation became active or inactive.
+ */
+ void onOpActiveChanged(int code, int uid, String packageName, boolean active);
+ }
+
+ /**
* Callback for notification of changes to operation state.
* This allows you to see the raw op codes instead of strings.
* @hide
@@ -1695,6 +1716,8 @@ public class AppOpsManager {
/**
* Monitor for changes to the operating mode for the given op in the given app package.
+ * You can watch op changes only for your UID.
+ *
* @param op The operation to monitor, one of OPSTR_*.
* @param packageName The name of the application to monitor.
* @param callback Where to report changes.
@@ -1706,11 +1729,17 @@ public class AppOpsManager {
/**
* Monitor for changes to the operating mode for the given op in the given app package.
+ *
+ * <p> If you don't hold the {@link android.Manifest.permission#WATCH_APPOPS} permission
+ * to watch changes only for your UID.
+ *
* @param op The operation to monitor, one of OP_*.
* @param packageName The name of the application to monitor.
* @param callback Where to report changes.
* @hide
*/
+ // TODO: Uncomment below annotation once b/73559440 is fixed
+ // @RequiresPermission(value=Manifest.permission.WATCH_APPOPS, conditional=true)
public void startWatchingMode(int op, String packageName, final OnOpChangedListener callback) {
synchronized (mModeWatchers) {
IAppOpsCallback cb = mModeWatchers.get(callback);
@@ -1752,6 +1781,74 @@ public class AppOpsManager {
}
}
+ /**
+ * Start watching for changes to the active state of app ops. An app op may be
+ * long running and it has a clear start and stop delimiters. If an op is being
+ * started or stopped by any package you will get a callback. To change the
+ * watched ops for a registered callback you need to unregister and register it
+ * again.
+ *
+ * @param ops The ops to watch.
+ * @param callback Where to report changes.
+ *
+ * @see #isOperationActive(int, int, String)
+ * @see #stopWatchingActive(OnOpActiveChangedListener)
+ * @see #startOp(int, int, String)
+ * @see #finishOp(int, int, String)
+ *
+ * @hide
+ */
+ @RequiresPermission(Manifest.permission.WATCH_APPOPS)
+ public void startWatchingActive(@NonNull int[] ops,
+ @NonNull OnOpActiveChangedListener callback) {
+ Preconditions.checkNotNull(ops, "ops cannot be null");
+ Preconditions.checkNotNull(callback, "callback cannot be null");
+ IAppOpsActiveCallback cb;
+ synchronized (mActiveWatchers) {
+ cb = mActiveWatchers.get(callback);
+ if (cb != null) {
+ return;
+ }
+ cb = new IAppOpsActiveCallback.Stub() {
+ @Override
+ public void opActiveChanged(int op, int uid, String packageName, boolean active) {
+ callback.onOpActiveChanged(op, uid, packageName, active);
+ }
+ };
+ mActiveWatchers.put(callback, cb);
+ }
+ try {
+ mService.startWatchingActive(ops, cb);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Stop watching for changes to the active state of an app op. An app op may be
+ * long running and it has a clear start and stop delimiters. Unregistering a
+ * non-registered callback has no effect.
+ *
+ * @see #isOperationActive#(int, int, String)
+ * @see #startWatchingActive(int[], OnOpActiveChangedListener)
+ * @see #startOp(int, int, String)
+ * @see #finishOp(int, int, String)
+ *
+ * @hide
+ */
+ public void stopWatchingActive(@NonNull OnOpActiveChangedListener callback) {
+ synchronized (mActiveWatchers) {
+ final IAppOpsActiveCallback cb = mActiveWatchers.get(callback);
+ if (cb != null) {
+ try {
+ mService.stopWatchingActive(cb);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+ }
+ }
+
private String buildSecurityExceptionMsg(int op, int uid, String packageName) {
return packageName + " from uid " + uid + " not allowed to perform " + sOpNames[op];
}
@@ -2145,6 +2242,7 @@ public class AppOpsManager {
}
/** @hide */
+ @RequiresPermission(Manifest.permission.WATCH_APPOPS)
public boolean isOperationActive(int code, int uid, String packageName) {
try {
return mService.isOperationActive(code, uid, packageName);