Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 51ed232c authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Improve AppOpsManager documentation"

parents 414b0663 a04b9ab4
Loading
Loading
Loading
Loading
+2 −2
Original line number Original line Diff line number Diff line
@@ -4351,7 +4351,7 @@ package android.app {
  public class AppOpsManager {
  public class AppOpsManager {
    method @Deprecated public int checkOp(@NonNull String, int, @NonNull String);
    method @Deprecated public int checkOp(@NonNull String, int, @NonNull String);
    method @Deprecated public int checkOpNoThrow(@NonNull String, int, @NonNull String);
    method @Deprecated public int checkOpNoThrow(@NonNull String, int, @NonNull String);
    method public void checkPackage(int, @NonNull String);
    method @Deprecated public void checkPackage(int, @NonNull String);
    method @Deprecated public void finishOp(@NonNull String, int, @NonNull String);
    method @Deprecated public void finishOp(@NonNull String, int, @NonNull String);
    method public void finishOp(@NonNull String, int, @NonNull String, @Nullable String);
    method public void finishOp(@NonNull String, int, @NonNull String, @Nullable String);
    method public boolean isOpActive(@NonNull String, int, @NonNull String);
    method public boolean isOpActive(@NonNull String, int, @NonNull String);
@@ -4364,7 +4364,7 @@ package android.app {
    method @Deprecated public int noteProxyOpNoThrow(@NonNull String, @NonNull String);
    method @Deprecated public int noteProxyOpNoThrow(@NonNull String, @NonNull String);
    method @Deprecated public int noteProxyOpNoThrow(@NonNull String, @Nullable String, int);
    method @Deprecated public int noteProxyOpNoThrow(@NonNull String, @Nullable String, int);
    method public int noteProxyOpNoThrow(@NonNull String, @Nullable String, int, @Nullable String, @Nullable String);
    method public int noteProxyOpNoThrow(@NonNull String, @Nullable String, int, @Nullable String, @Nullable String);
    method public static String permissionToOp(String);
    method @Nullable public static String permissionToOp(@NonNull String);
    method public void setNotedAppOpsCollector(@Nullable android.app.AppOpsManager.AppOpsCollector);
    method public void setNotedAppOpsCollector(@Nullable android.app.AppOpsManager.AppOpsCollector);
    method @Deprecated public int startOp(@NonNull String, int, @NonNull String);
    method @Deprecated public int startOp(@NonNull String, int, @NonNull String);
    method public int startOp(@NonNull String, int, @Nullable String, @Nullable String, @Nullable String);
    method public int startOp(@NonNull String, int, @Nullable String, @Nullable String, @Nullable String);
+2 −2
Original line number Original line Diff line number Diff line
@@ -371,8 +371,8 @@ package android.app {
    method @NonNull @RequiresPermission(android.Manifest.permission.GET_APP_OPS_STATS) public java.util.List<android.app.AppOpsManager.PackageOps> getPackagesForOps(@Nullable String[]);
    method @NonNull @RequiresPermission(android.Manifest.permission.GET_APP_OPS_STATS) public java.util.List<android.app.AppOpsManager.PackageOps> getPackagesForOps(@Nullable String[]);
    method public static int opToDefaultMode(@NonNull String);
    method public static int opToDefaultMode(@NonNull String);
    method @Nullable public static String opToPermission(@NonNull String);
    method @Nullable public static String opToPermission(@NonNull String);
    method @RequiresPermission("android.permission.MANAGE_APP_OPS_MODES") public void setMode(String, int, String, int);
    method @RequiresPermission("android.permission.MANAGE_APP_OPS_MODES") public void setMode(@NonNull String, int, @Nullable String, int);
    method @RequiresPermission("android.permission.MANAGE_APP_OPS_MODES") public void setUidMode(String, int, int);
    method @RequiresPermission("android.permission.MANAGE_APP_OPS_MODES") public void setUidMode(@NonNull String, int, int);
    field public static final String OPSTR_ACCEPT_HANDOVER = "android:accept_handover";
    field public static final String OPSTR_ACCEPT_HANDOVER = "android:accept_handover";
    field public static final String OPSTR_ACCESS_ACCESSIBILITY = "android:access_accessibility";
    field public static final String OPSTR_ACCESS_ACCESSIBILITY = "android:access_accessibility";
    field public static final String OPSTR_ACCESS_NOTIFICATIONS = "android:access_notifications";
    field public static final String OPSTR_ACCESS_NOTIFICATIONS = "android:access_notifications";
+2 −2
Original line number Original line Diff line number Diff line
@@ -180,8 +180,8 @@ package android.app {
    method @RequiresPermission("android.permission.MANAGE_APPOPS") public void resetHistoryParameters();
    method @RequiresPermission("android.permission.MANAGE_APPOPS") public void resetHistoryParameters();
    method @RequiresPermission("android.permission.MANAGE_APPOPS") public void setHistoryParameters(int, long, int);
    method @RequiresPermission("android.permission.MANAGE_APPOPS") public void setHistoryParameters(int, long, int);
    method @RequiresPermission("android.permission.MANAGE_APP_OPS_MODES") public void setMode(int, int, String, int);
    method @RequiresPermission("android.permission.MANAGE_APP_OPS_MODES") public void setMode(int, int, String, int);
    method @RequiresPermission("android.permission.MANAGE_APP_OPS_MODES") public void setMode(String, int, String, int);
    method @RequiresPermission("android.permission.MANAGE_APP_OPS_MODES") public void setMode(@NonNull String, int, @Nullable String, int);
    method @RequiresPermission("android.permission.MANAGE_APP_OPS_MODES") public void setUidMode(String, int, int);
    method @RequiresPermission("android.permission.MANAGE_APP_OPS_MODES") public void setUidMode(@NonNull String, int, int);
    method public static int strOpToOp(@NonNull String);
    method public static int strOpToOp(@NonNull String);
    field public static final int HISTORICAL_MODE_DISABLED = 0; // 0x0
    field public static final int HISTORICAL_MODE_DISABLED = 0; // 0x0
    field public static final int HISTORICAL_MODE_ENABLED_ACTIVE = 1; // 0x1
    field public static final int HISTORICAL_MODE_ENABLED_ACTIVE = 1; // 0x1
+107 −60
Original line number Original line Diff line number Diff line
@@ -97,15 +97,77 @@ import java.util.function.Consumer;
import java.util.function.Supplier;
import java.util.function.Supplier;


/**
/**
 * AppOps are mappings of [package/uid, op-name] -> [mode]. The list of existing appops is defined
 * App-ops are used for two purposes: Access control and tracking.
 * by the system and cannot be amended by apps. Only system apps can change appop-modes.
 *
 *
 * <p>App-ops cover a wide variety of functionality from helping with runtime permissions access
 * <p>Beside a mode the system tracks when an op was {@link #noteOp noted}. The tracked data can
 * control and tracking to battery consumption tracking.
 * only be read by system components.
 *
 *
 * <h2>Access control</h2>
 * <p>Installed apps can usually only listen to changes and events on their own ops. E.g.
 *
 * {@link AppOpsCollector} allows to get a callback each time an app called {@link #noteOp} or
 * <p>App-ops can either be controlled for each uid or for each package. Which one is used depends
 * {@link #startOp} for an op belonging to the app.
 * on the API provider maintaining this app-op. For any security or privacy related app-op the
 * provider needs to control the app-op for per uid as all security and privacy is based on uid in
 * Android.
 *
 * <p>To control access the app-op can be set to a mode to:
 * <dl>
 *     <dt>{@link #MODE_DEFAULT}
 *     <dd>Default behavior, might differ from app-op or app-op
 *     <dt>{@link #MODE_ALLOWED}
 *     <dd>Allow the access
 *     <dt>{@link #MODE_IGNORED}
 *     <dd>Don't allow the access, i.e. don't perform the requested action or return no or dummy
 *     data
 *     <dt>{@link #MODE_ERRORED}
 *     <dd>Throw a {@link SecurityException} on access. This can be suppressed by using a
 *     {@code ...noThrow} method to check the mode
 * </dl>
 *
 * <p>API providers need to check the mode returned by {@link #noteOp} if they are are allowing
 * access to operations gated by the app-op. {@link #unsafeCheckOp} should be used to check the
 * mode if no access is granted. E.g. this can be used for displaying app-op state in the UI or
 * when checking the state before later calling {@link #noteOp} anyway.
 *
 * <p>If an operation refers to a time span (e.g. a audio-recording session) the API provider
 * should use {@link #startOp} and {@link #finishOp} instead of {@link #noteOp}.
 *
 * <h3>Runtime permissions and app-ops</h3>
 *
 * <p>Each platform defined runtime permission (beside background modifiers) has an associated app
 * op which is used for tracking but also to allow for silent failures. I.e. if the runtime
 * permission is denied the caller gets a {@link SecurityException}, but if the permission is
 * granted and the app-op is {@link #MODE_IGNORED} then the callers gets dummy behavior, e.g.
 * location callbacks would not happen.
 *
 * <h3>App-op permissions</h3>
 *
 * <p>App-ops permissions are platform defined permissions that can be overridden. The security
 * check for app-op permissions should by {@link #MODE_DEFAULT default} check the permission grant
 * state. If the app-op state is set to {@link #MODE_ALLOWED} or {@link #MODE_IGNORED} the app-op
 * state should be checked instead of the permission grant state.
 *
 * <p>This functionality allows to grant access by default to apps fulfilling the requirements for
 * a certain permission level. Still the behavior can be overridden when needed.
 *
 * <h2>Tracking</h2>
 *
 * <p>App-ops track many important events, including all accesses to runtime permission protected
 * APIs. This is done by tracking when an app-op was {@link #noteOp noted} or
 * {@link #startOp started}. The tracked data can only be read by system components.
 *
 * <p><b>Only {@link #noteOp}/{@link #startOp} are tracked; {@link #unsafeCheckOp} is not tracked.
 * Hence it is important to eventually call {@link #noteOp} or {@link #startOp} when providing
 * access to protected operations or data.</b>
 *
 * <p>Some apps are forwarding access to other apps. E.g. an app might get the location from the
 * system's location provider and then send the location further to a 3rd app. In this case the
 * app passing on the data needs to call {@link #noteProxyOp} to signal the access proxying. This
 * 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
 * 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.
 */
 */
@SystemService(Context.APP_OPS_SERVICE)
@SystemService(Context.APP_OPS_SERVICE)
public class AppOpsManager {
public class AppOpsManager {
@@ -121,28 +183,6 @@ public class AppOpsManager {
    @EnabledAfter(targetSdkVersion = Build.VERSION_CODES.Q)
    @EnabledAfter(targetSdkVersion = Build.VERSION_CODES.Q)
    public static final long CALL_BACK_ON_CHANGED_LISTENER_WITH_SWITCHED_OP_CHANGE = 148180766L;
    public static final long CALL_BACK_ON_CHANGED_LISTENER_WITH_SWITCHED_OP_CHANGE = 148180766L;


    /**
     * <p>App ops allows callers to:</p>
     *
     * <ul>
     * <li> Note when operations are happening, and find out if they are allowed for the current
     * caller.</li>
     * <li> Disallow specific apps from doing specific operations.</li>
     * <li> Collect all of the current information about operations that have been executed or
     * are not being allowed.</li>
     * <li> Monitor for changes in whether an operation is allowed.</li>
     * </ul>
     *
     * <p>Each operation is identified by a single integer; these integers are a fixed set of
     * operations, enumerated by the OP_* constants.
     *
     * <p></p>When checking operations, the result is a "mode" integer indicating the current
     * setting for the operation under that caller: MODE_ALLOWED, MODE_IGNORED (don't execute
     * the operation but fake its behavior enough so that the caller doesn't crash),
     * MODE_ERRORED (throw a SecurityException back to the caller; the normal operation calls
     * will do this for you).
     */

    final Context mContext;
    final Context mContext;


    @UnsupportedAppUsage
    @UnsupportedAppUsage
@@ -1093,7 +1133,7 @@ public class AppOpsManager {
    /** Required to draw on top of other apps. */
    /** Required to draw on top of other apps. */
    public static final String OPSTR_SYSTEM_ALERT_WINDOW
    public static final String OPSTR_SYSTEM_ALERT_WINDOW
            = "android:system_alert_window";
            = "android:system_alert_window";
    /** Required to write/modify/update system settingss. */
    /** Required to write/modify/update system settings. */
    public static final String OPSTR_WRITE_SETTINGS
    public static final String OPSTR_WRITE_SETTINGS
            = "android:write_settings";
            = "android:write_settings";
    /** @hide Get device accounts. */
    /** @hide Get device accounts. */
@@ -6115,7 +6155,7 @@ public class AppOpsManager {
     */
     */
    public interface OnOpActiveChangedListener {
    public interface OnOpActiveChangedListener {
        /**
        /**
         * Called when the active state of an app op changes.
         * Called when the active state of an app-op changes.
         *
         *
         * @param op The operation that changed.
         * @param op The operation that changed.
         * @param packageName The package performing the operation.
         * @param packageName The package performing the operation.
@@ -6406,7 +6446,7 @@ public class AppOpsManager {
    @SystemApi
    @SystemApi
    @TestApi
    @TestApi
    @RequiresPermission(android.Manifest.permission.MANAGE_APP_OPS_MODES)
    @RequiresPermission(android.Manifest.permission.MANAGE_APP_OPS_MODES)
    public void setUidMode(String appOp, int uid, @Mode int mode) {
    public void setUidMode(@NonNull String appOp, int uid, @Mode int mode) {
        try {
        try {
            mService.setUidMode(AppOpsManager.strOpToOp(appOp), uid, mode);
            mService.setUidMode(AppOpsManager.strOpToOp(appOp), uid, mode);
        } catch (RemoteException e) {
        } catch (RemoteException e) {
@@ -6461,7 +6501,8 @@ public class AppOpsManager {
    @TestApi
    @TestApi
    @SystemApi
    @SystemApi
    @RequiresPermission(android.Manifest.permission.MANAGE_APP_OPS_MODES)
    @RequiresPermission(android.Manifest.permission.MANAGE_APP_OPS_MODES)
    public void setMode(String op, int uid, String packageName, @Mode int mode) {
    public void setMode(@NonNull String op, int uid, @Nullable String packageName,
            @Mode int mode) {
        try {
        try {
            mService.setMode(strOpToOp(op), uid, packageName, mode);
            mService.setMode(strOpToOp(op), uid, packageName, mode);
        } catch (RemoteException e) {
        } catch (RemoteException e) {
@@ -6504,16 +6545,17 @@ public class AppOpsManager {
    }
    }


    /**
    /**
     * Gets the app op name associated with a given permission.
     * Gets the app-op name associated with a given permission.
     * The app op name is one of the public constants defined
     *
     * <p>The app-op name is one of the public constants defined
     * in this class such as {@link #OPSTR_COARSE_LOCATION}.
     * in this class such as {@link #OPSTR_COARSE_LOCATION}.
     * This API is intended to be used for mapping runtime
     * This API is intended to be used for mapping runtime
     * permissions to the corresponding app op.
     * permissions to the corresponding app-op.
     *
     *
     * @param permission The permission.
     * @param permission The permission.
     * @return The app op associated with the permission or null.
     * @return The app-op associated with the permission or {@code null}.
     */
     */
    public static String permissionToOp(String permission) {
    public static @Nullable String permissionToOp(@NonNull String permission) {
        final Integer opCode = sPermToOp.get(permission);
        final Integer opCode = sPermToOp.get(permission);
        if (opCode == null) {
        if (opCode == null) {
            return null;
            return null;
@@ -6631,7 +6673,7 @@ public class AppOpsManager {
    }
    }


    /**
    /**
     * Start watching for changes to the active state of app ops. An app op may be
     * 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
     * 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
     * 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
     * watched ops for a registered callback you need to unregister and register it
@@ -6690,7 +6732,7 @@ public class AppOpsManager {
    }
    }


    /**
    /**
     * Stop watching for changes to the active state of an app op. An app op may be
     * 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
     * long running and it has a clear start and stop delimiters. Unregistering a
     * non-registered callback has no effect.
     * non-registered callback has no effect.
     *
     *
@@ -6921,7 +6963,8 @@ public class AppOpsManager {
     * @param op The operation to note.  One of the OPSTR_* constants.
     * @param op The operation to note.  One of the OPSTR_* constants.
     * @param uid The user id of the application attempting to perform the operation.
     * @param uid The user id of the application attempting to perform the operation.
     * @param packageName The name of the application attempting to perform the operation.
     * @param packageName The name of the application attempting to perform the operation.
     * @param featureId The feature in the app or {@code null} for default feature
     * @param featureId The {@link Context#createFeatureContext feature} in the package or {@code
     * null} for default feature
     * @param message A message describing the reason the op was noted
     * @param message A message describing the reason the op was noted
     *
     *
     * @return Returns {@link #MODE_ALLOWED} if the operation is allowed, or
     * @return Returns {@link #MODE_ALLOWED} if the operation is allowed, or
@@ -6996,6 +7039,8 @@ public class AppOpsManager {
     * @param op The operation to note.  One of the OPSTR_* constants.
     * @param op The operation to note.  One of the OPSTR_* constants.
     * @param uid The user id of the application attempting to perform the operation.
     * @param uid The user id of the application attempting to perform the operation.
     * @param packageName The name of the application attempting to perform the operation.
     * @param packageName The name of the application attempting to perform the operation.
     * @param featureId The {@link Context#createFeatureContext feature} in the package or {@code
     * null} for default feature
     * @param message A message describing the reason the op was noted
     * @param message A message describing the reason the op was noted
     *
     *
     * @return Returns {@link #MODE_ALLOWED} if the operation is allowed, or
     * @return Returns {@link #MODE_ALLOWED} if the operation is allowed, or
@@ -7003,8 +7048,8 @@ public class AppOpsManager {
     * causing the app to crash).
     * causing the app to crash).
     */
     */
    public int noteOpNoThrow(@NonNull String op, int uid, @NonNull String packageName,
    public int noteOpNoThrow(@NonNull String op, int uid, @NonNull String packageName,
            @Nullable String feature, @Nullable String message) {
            @Nullable String featureId, @Nullable String message) {
        return noteOpNoThrow(strOpToOp(op), uid, packageName, feature, message);
        return noteOpNoThrow(strOpToOp(op), uid, packageName, featureId, message);
    }
    }


    /**
    /**
@@ -7273,11 +7318,9 @@ public class AppOpsManager {
    }
    }


    /**
    /**
     * Do a quick check to validate if a package name belongs to a UID.
     * @deprecated Use {@link PackageManager#getPackageUid} instead
     *
     * @throws SecurityException if the package name doesn't belong to the given
     *             UID, or if ownership cannot be verified.
     */
     */
    @Deprecated
    public void checkPackage(int uid, @NonNull String packageName) {
    public void checkPackage(int uid, @NonNull String packageName) {
        try {
        try {
            if (mService.checkPackage(uid, packageName) != MODE_ALLOWED) {
            if (mService.checkPackage(uid, packageName) != MODE_ALLOWED) {
@@ -7396,7 +7439,8 @@ public class AppOpsManager {
     * @param op The operation to start.  One of the OPSTR_* constants.
     * @param op The operation to start.  One of the OPSTR_* constants.
     * @param uid The user id of the application attempting to perform the operation.
     * @param uid The user id of the application attempting to perform the operation.
     * @param packageName The name of the application attempting to perform the operation.
     * @param packageName The name of the application attempting to perform the operation.
     * @param featureId The feature in the app or {@code null} for default feature
     * @param featureId The {@link Context#createFeatureContext feature} in the package or {@code
     * null} for default feature
     * @param message Description why op was started
     * @param message Description why op was started
     *
     *
     * @return Returns {@link #MODE_ALLOWED} if the operation is allowed, or
     * @return Returns {@link #MODE_ALLOWED} if the operation is allowed, or
@@ -7587,7 +7631,8 @@ public class AppOpsManager {
    }
    }


    /**
    /**
     * Checks whether the given op for a package is active.
     * Checks whether the given op for a package is active, i.e. did someone call {@link #startOp}
     * without {@link #finishOp} yet.
     * <p>
     * <p>
     * If you don't hold the {@code android.Manifest.permission#WATCH_APPOPS}
     * If you don't hold the {@code android.Manifest.permission#WATCH_APPOPS}
     * permission you can query only for your UID.
     * permission you can query only for your UID.
@@ -7917,18 +7962,19 @@ public class AppOpsManager {
    }
    }


    /**
    /**
     * Callback an app can choose to {@link #setNotedAppOpsCollector register} to monitor it's noted
     * Callback an app can {@link #setNotedAppOpsCollector register} to monitor the app-ops the
     * appops. I.e. each time any app calls {@link #noteOp} or {@link #startOp} one of the callback
     * system has tracked for it. I.e. each time any app calls {@link #noteOp} or {@link #startOp}
     * methods of this object is called.
     * one of the callback methods of this object is called.
     *
     *
     * <p><b>Only appops related to dangerous permissions are collected.</b>
     * <p><b>There will be a callback for all app-ops related to runtime permissions, but not
     * necessarily for all other app-ops.
     *
     *
     * <pre>
     * <pre>
     * setNotedAppOpsCollector(new AppOpsCollector() {
     * setNotedAppOpsCollector(new AppOpsCollector() {
     *     ArraySet<Pair<String, String>> opsNotedForThisProcess = new ArraySet<>();
     *     ArraySet<Pair<String, String>> opsNotedForThisProcess = new ArraySet<>();
     *
     *
     *     private synchronized void addAccess(String op, String accessLocation) {
     *     private synchronized void addAccess(String op, String accessLocation) {
     *         // Ops are often noted when permission protected APIs were called.
     *         // Ops are often noted when runtime permission protected APIs were called.
     *         // In this case permissionToOp() allows to resolve the permission<->op
     *         // In this case permissionToOp() allows to resolve the permission<->op
     *         opsNotedForThisProcess.add(new Pair(accessType, accessLocation));
     *         opsNotedForThisProcess.add(new Pair(accessType, accessLocation));
     *     }
     *     }
@@ -7970,20 +8016,21 @@ public class AppOpsManager {
        }
        }


        /**
        /**
         * Called when an app-op was noted for this package inside of a two-way binder-call.
         * Called when an app-op was {@link #noteOp noted} for this package inside of a synchronous
         * API call, i.e. a API call that returned data or waited until the action was performed.
         *
         *
         * <p>Called on the calling thread just after executing the binder-call. This allows
         * <p>Called on the calling thread before the API returns. This allows the app to e.g.
         * the app to e.g. collect stack traces to figure out where the access came from.
         * collect stack traces to figure out where the access came from.
         *
         *
         * @param op The op noted
         * @param op The op noted
         */
         */
        public abstract void onNoted(@NonNull SyncNotedAppOp op);
        public abstract void onNoted(@NonNull SyncNotedAppOp op);


        /**
        /**
         * Called when this app noted an app-op for its own package.
         * Called when this app noted an app-op for its own package,
         *
         *
         * <p>Called on the thread the noted the op. This allows the app to e.g. collect stack
         * <p>This is very similar to {@link #onNoted} only that the tracking was not caused by the
         * traces to figure out where the access came from.
         * API provider in a separate process, but by one in the app's own process.
         *
         *
         * @param op The op noted
         * @param op The op noted
         */
         */