AppOpsManagerpublic class AppOpsManager extends Object API for interacting with "application operation" tracking.
This API is not generally intended for third party application developers; most
features are only available to system applications. Obtain an instance of it through
{@link Context#getSystemService(String) Context.getSystemService} with
{@link Context#APP_OPS_SERVICE Context.APP_OPS_SERVICE}. |
Fields Summary |
---|
final android.content.Context | mContext App ops allows callers to:
- Note when operations are happening, and find out if they are allowed for the current
caller.
- Disallow specific apps from doing specific operations.
- Collect all of the current information about operations that have been executed or
are not being allowed.
- Monitor for changes in whether an operation is allowed.
Each operation is identified by a single integer; these integers are a fixed set of
operations, enumerated by the OP_* constants.
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 com.android.internal.app.IAppOpsService | mService | final android.util.ArrayMap | mModeWatchers | static android.os.IBinder | sToken | public static final int | MODE_ALLOWEDResult from {@link #checkOp}, {@link #noteOp}, {@link #startOp}: the given caller is
allowed to perform the given operation. | public static final int | MODE_IGNOREDResult from {@link #checkOp}, {@link #noteOp}, {@link #startOp}: the given caller is
not allowed to perform the given operation, and this attempt should
silently fail (it should not cause the app to crash). | public static final int | MODE_ERROREDResult from {@link #checkOpNoThrow}, {@link #noteOpNoThrow}, {@link #startOpNoThrow}: the
given caller is not allowed to perform the given operation, and this attempt should
cause it to have a fatal error, typically a {@link SecurityException}. | public static final int | MODE_DEFAULTResult from {@link #checkOp}, {@link #noteOp}, {@link #startOp}: the given caller should
use its default security check. This mode is not normally used; it should only be used
with appop permissions, and callers must explicitly check for it and deal with it. | public static final int | OP_NONE | public static final int | OP_COARSE_LOCATION | public static final int | OP_FINE_LOCATION | public static final int | OP_GPS | public static final int | OP_VIBRATE | public static final int | OP_READ_CONTACTS | public static final int | OP_WRITE_CONTACTS | public static final int | OP_READ_CALL_LOG | public static final int | OP_WRITE_CALL_LOG | public static final int | OP_READ_CALENDAR | public static final int | OP_WRITE_CALENDAR | public static final int | OP_WIFI_SCAN | public static final int | OP_POST_NOTIFICATION | public static final int | OP_NEIGHBORING_CELLS | public static final int | OP_CALL_PHONE | public static final int | OP_READ_SMS | public static final int | OP_WRITE_SMS | public static final int | OP_RECEIVE_SMS | public static final int | OP_RECEIVE_EMERGECY_SMS | public static final int | OP_RECEIVE_MMS | public static final int | OP_RECEIVE_WAP_PUSH | public static final int | OP_SEND_SMS | public static final int | OP_READ_ICC_SMS | public static final int | OP_WRITE_ICC_SMS | public static final int | OP_WRITE_SETTINGS | public static final int | OP_SYSTEM_ALERT_WINDOW | public static final int | OP_ACCESS_NOTIFICATIONS | public static final int | OP_CAMERA | public static final int | OP_RECORD_AUDIO | public static final int | OP_PLAY_AUDIO | public static final int | OP_READ_CLIPBOARD | public static final int | OP_WRITE_CLIPBOARD | public static final int | OP_TAKE_MEDIA_BUTTONS | public static final int | OP_TAKE_AUDIO_FOCUS | public static final int | OP_AUDIO_MASTER_VOLUME | public static final int | OP_AUDIO_VOICE_VOLUME | public static final int | OP_AUDIO_RING_VOLUME | public static final int | OP_AUDIO_MEDIA_VOLUME | public static final int | OP_AUDIO_ALARM_VOLUME | public static final int | OP_AUDIO_NOTIFICATION_VOLUME | public static final int | OP_AUDIO_BLUETOOTH_VOLUME | public static final int | OP_WAKE_LOCK | public static final int | OP_MONITOR_LOCATION | public static final int | OP_MONITOR_HIGH_POWER_LOCATION | public static final int | OP_GET_USAGE_STATS | public static final int | OP_MUTE_MICROPHONE | public static final int | OP_TOAST_WINDOW | public static final int | OP_PROJECT_MEDIA | public static final int | OP_ACTIVATE_VPN | public static final int | _NUM_OP | public static final String | OPSTR_COARSE_LOCATIONAccess to coarse location information. | public static final String | OPSTR_FINE_LOCATIONAccess to fine location information. | public static final String | OPSTR_MONITOR_LOCATIONContinually monitoring location data. | public static final String | OPSTR_MONITOR_HIGH_POWER_LOCATIONContinually monitoring location data with a relatively high power request. | public static final String | OPSTR_GET_USAGE_STATSAccess to {@link android.app.usage.UsageStatsManager}. | public static final String | OPSTR_ACTIVATE_VPNActivate a VPN connection without user intervention. @hide | private static int[] | sOpToSwitchThis maps each operation to the operation that serves as the
switch to determine whether it is allowed. Generally this is
a 1:1 mapping, but for some things (like location) that have
multiple low-level operations being tracked that should be
presented to the user as one switch then this can be used to
make them all controlled by the same single operation. | private static String[] | sOpToStringThis maps each operation to the public string constant for it.
If it doesn't have a public string constant, it maps to null. | private static String[] | sOpNamesThis provides a simple name for each operation to be used
in debug output. | private static String[] | sOpPermsThis optionally maps a permission to an operation. If there
is no permission associated with an operation, it is null. | private static String[] | sOpRestrictionsSpecifies whether an Op should be restricted by a user restriction.
Each Op should be filled with a restriction string from UserManager or
null to specify it is not affected by any user restriction. | private static boolean[] | sOpAllowSystemRestrictionBypassThis specifies whether each option should allow the system
(and system ui) to bypass the user restriction when active. | private static int[] | sOpDefaultModeThis specifies the default mode for each operation. | private static boolean[] | sOpDisableResetThis specifies whether each option is allowed to be reset
when resetting all app preferences. Disable reset for
app ops that are under strong control of some part of the
system (such as OP_WRITE_SMS, which should be allowed only
for whichever app is selected as the current SMS app). | private static HashMap | sOpStrToOp |
Methods Summary |
---|
private java.lang.String | buildSecurityExceptionMsg(int op, int uid, java.lang.String packageName)
return packageName + " from uid " + uid + " not allowed to perform " + sOpNames[op];
| public int | checkAudioOp(int op, int stream, int uid, java.lang.String packageName)Like {@link #checkOp} but at a stream-level for audio operations.
try {
final int mode = mService.checkAudioOperation(op, stream, uid, packageName);
if (mode == MODE_ERRORED) {
throw new SecurityException(buildSecurityExceptionMsg(op, uid, packageName));
}
return mode;
} catch (RemoteException e) {
}
return MODE_IGNORED;
| public int | checkAudioOpNoThrow(int op, int stream, int uid, java.lang.String packageName)Like {@link #checkAudioOp} but instead of throwing a {@link SecurityException} it
returns {@link #MODE_ERRORED}.
try {
return mService.checkAudioOperation(op, stream, uid, packageName);
} catch (RemoteException e) {
}
return MODE_IGNORED;
| public int | checkOp(java.lang.String op, int uid, java.lang.String packageName)Do a quick check for whether an application might be able to perform an operation.
This is not a security check; you must use {@link #noteOp(String, int, String)}
or {@link #startOp(String, int, String)} for your actual security checks, which also
ensure that the given uid and package name are consistent. This function can just be
used for a quick check to see if an operation has been disabled for the application,
as an early reject of some work. This does not modify the time stamp or other data
about the operation.
return checkOp(strOpToOp(op), uid, packageName);
| public int | checkOp(int op, int uid, java.lang.String packageName)Do a quick check for whether an application might be able to perform an operation.
This is not a security check; you must use {@link #noteOp(int, int, String)}
or {@link #startOp(int, int, String)} for your actual security checks, which also
ensure that the given uid and package name are consistent. This function can just be
used for a quick check to see if an operation has been disabled for the application,
as an early reject of some work. This does not modify the time stamp or other data
about the operation.
try {
int mode = mService.checkOperation(op, uid, packageName);
if (mode == MODE_ERRORED) {
throw new SecurityException(buildSecurityExceptionMsg(op, uid, packageName));
}
return mode;
} catch (RemoteException e) {
}
return MODE_IGNORED;
| public int | checkOpNoThrow(java.lang.String op, int uid, java.lang.String packageName)Like {@link #checkOp} but instead of throwing a {@link SecurityException} it
returns {@link #MODE_ERRORED}.
return checkOpNoThrow(strOpToOp(op), uid, packageName);
| public int | checkOpNoThrow(int op, int uid, java.lang.String packageName)Like {@link #checkOp} but instead of throwing a {@link SecurityException} it
returns {@link #MODE_ERRORED}.
try {
return mService.checkOperation(op, uid, packageName);
} catch (RemoteException e) {
}
return MODE_IGNORED;
| public void | checkPackage(int uid, java.lang.String packageName)Do a quick check to validate if a package name belongs to a UID.
try {
if (mService.checkPackage(uid, packageName) != MODE_ALLOWED) {
throw new SecurityException(
"Package " + packageName + " does not belong to " + uid);
}
} catch (RemoteException e) {
throw new SecurityException("Unable to verify package ownership", e);
}
| public void | finishOp(java.lang.String op, int uid, java.lang.String packageName)Report that an application is no longer performing an operation that had previously
been started with {@link #startOp(String, int, String)}. There is no validation of input
or result; the parameters supplied here must be the exact same ones previously passed
in when starting the operation.
finishOp(strOpToOp(op), uid, packageName);
| public void | finishOp(int op, int uid, java.lang.String packageName)Report that an application is no longer performing an operation that had previously
been started with {@link #startOp(int, int, String)}. There is no validation of input
or result; the parameters supplied here must be the exact same ones previously passed
in when starting the operation.
try {
mService.finishOperation(getToken(mService), op, uid, packageName);
} catch (RemoteException e) {
}
| public void | finishOp(int op)
finishOp(op, Process.myUid(), mContext.getOpPackageName());
| public java.util.List | getOpsForPackage(int uid, java.lang.String packageName, int[] ops)Retrieve current operation state for one application.
try {
return mService.getOpsForPackage(uid, packageName, ops);
} catch (RemoteException e) {
}
return null;
| public java.util.List | getPackagesForOps(int[] ops)Retrieve current operation state for all applications.
try {
return mService.getPackagesForOps(ops);
} catch (RemoteException e) {
}
return null;
| public static android.os.IBinder | getToken(com.android.internal.app.IAppOpsService service)
synchronized (AppOpsManager.class) {
if (sToken != null) {
return sToken;
}
try {
sToken = service.getToken(new Binder());
} catch (RemoteException e) {
// System is dead, whatevs.
}
return sToken;
}
| public int | noteOp(java.lang.String op, int uid, java.lang.String packageName)Make note of an application performing an operation. Note that you must pass
in both the uid and name of the application to be checked; this function will verify
that these two match, and if not, return {@link #MODE_IGNORED}. If this call
succeeds, the last execution time of the operation for this app will be updated to
the current time.
return noteOp(strOpToOp(op), uid, packageName);
| public int | noteOp(int op, int uid, java.lang.String packageName)Make note of an application performing an operation. Note that you must pass
in both the uid and name of the application to be checked; this function will verify
that these two match, and if not, return {@link #MODE_IGNORED}. If this call
succeeds, the last execution time of the operation for this app will be updated to
the current time.
try {
int mode = mService.noteOperation(op, uid, packageName);
if (mode == MODE_ERRORED) {
throw new SecurityException(buildSecurityExceptionMsg(op, uid, packageName));
}
return mode;
} catch (RemoteException e) {
}
return MODE_IGNORED;
| public int | noteOp(int op)
return noteOp(op, Process.myUid(), mContext.getOpPackageName());
| public int | noteOpNoThrow(java.lang.String op, int uid, java.lang.String packageName)Like {@link #noteOp} but instead of throwing a {@link SecurityException} it
returns {@link #MODE_ERRORED}.
return noteOpNoThrow(strOpToOp(op), uid, packageName);
| public int | noteOpNoThrow(int op, int uid, java.lang.String packageName)Like {@link #noteOp} but instead of throwing a {@link SecurityException} it
returns {@link #MODE_ERRORED}.
try {
return mService.noteOperation(op, uid, packageName);
} catch (RemoteException e) {
}
return MODE_IGNORED;
| public static boolean | opAllowSystemBypassRestriction(int op)Retrieve whether the op allows the system (and system ui) to
bypass the user restriction.
return sOpAllowSystemRestrictionBypass[op];
| public static boolean | opAllowsReset(int op)Retrieve whether the op allows itself to be reset.
return !sOpDisableReset[op];
| public static int | opToDefaultMode(int op)Retrieve the default mode for the operation.
return sOpDefaultMode[op];
| public static java.lang.String | opToName(int op)Retrieve a non-localized name for the operation, for debugging output.
if (op == OP_NONE) return "NONE";
return op < sOpNames.length ? sOpNames[op] : ("Unknown(" + op + ")");
| public static java.lang.String | opToPermission(int op)Retrieve the permission associated with an operation, or null if there is not one.
return sOpPerms[op];
| public static java.lang.String | opToRestriction(int op)Retrieve the user restriction associated with an operation, or null if there is not one.
return sOpRestrictions[op];
| public static int | opToSwitch(int op)Retrieve the op switch that controls the given operation.
if (sOpToSwitch.length != _NUM_OP) {
throw new IllegalStateException("sOpToSwitch length " + sOpToSwitch.length
+ " should be " + _NUM_OP);
}
if (sOpToString.length != _NUM_OP) {
throw new IllegalStateException("sOpToString length " + sOpToString.length
+ " should be " + _NUM_OP);
}
if (sOpNames.length != _NUM_OP) {
throw new IllegalStateException("sOpNames length " + sOpNames.length
+ " should be " + _NUM_OP);
}
if (sOpPerms.length != _NUM_OP) {
throw new IllegalStateException("sOpPerms length " + sOpPerms.length
+ " should be " + _NUM_OP);
}
if (sOpDefaultMode.length != _NUM_OP) {
throw new IllegalStateException("sOpDefaultMode length " + sOpDefaultMode.length
+ " should be " + _NUM_OP);
}
if (sOpDisableReset.length != _NUM_OP) {
throw new IllegalStateException("sOpDisableReset length " + sOpDisableReset.length
+ " should be " + _NUM_OP);
}
if (sOpRestrictions.length != _NUM_OP) {
throw new IllegalStateException("sOpRestrictions length " + sOpRestrictions.length
+ " should be " + _NUM_OP);
}
if (sOpAllowSystemRestrictionBypass.length != _NUM_OP) {
throw new IllegalStateException("sOpAllowSYstemRestrictionsBypass length "
+ sOpRestrictions.length + " should be " + _NUM_OP);
}
for (int i=0; i<_NUM_OP; i++) {
if (sOpToString[i] != null) {
sOpStrToOp.put(sOpToString[i], i);
}
}
return sOpToSwitch[op];
| public void | resetAllModes()
try {
mService.resetAllModes(UserHandle.myUserId(), null);
} catch (RemoteException e) {
}
| public void | setMode(int code, int uid, java.lang.String packageName, int mode)
try {
mService.setMode(code, uid, packageName, mode);
} catch (RemoteException e) {
}
| public void | setRestriction(int code, int usage, int mode, java.lang.String[] exceptionPackages)Set a non-persisted restriction on an audio operation at a stream-level.
Restrictions are temporary additional constraints imposed on top of the persisted rules
defined by {@link #setMode}.
try {
final int uid = Binder.getCallingUid();
mService.setAudioRestriction(code, usage, uid, mode, exceptionPackages);
} catch (RemoteException e) {
}
| public int | startOp(java.lang.String op, int uid, java.lang.String packageName)Report that an application has started executing a long-running operation. Note that you
must pass in both the uid and name of the application to be checked; this function will
verify that these two match, and if not, return {@link #MODE_IGNORED}. If this call
succeeds, the last execution time of the operation for this app will be updated to
the current time and the operation will be marked as "running". In this case you must
later call {@link #finishOp(String, int, String)} to report when the application is no
longer performing the operation.
return startOp(strOpToOp(op), uid, packageName);
| public int | startOp(int op, int uid, java.lang.String packageName)Report that an application has started executing a long-running operation. Note that you
must pass in both the uid and name of the application to be checked; this function will
verify that these two match, and if not, return {@link #MODE_IGNORED}. If this call
succeeds, the last execution time of the operation for this app will be updated to
the current time and the operation will be marked as "running". In this case you must
later call {@link #finishOp(int, int, String)} to report when the application is no
longer performing the operation.
try {
int mode = mService.startOperation(getToken(mService), op, uid, packageName);
if (mode == MODE_ERRORED) {
throw new SecurityException(buildSecurityExceptionMsg(op, uid, packageName));
}
return mode;
} catch (RemoteException e) {
}
return MODE_IGNORED;
| public int | startOp(int op)
return startOp(op, Process.myUid(), mContext.getOpPackageName());
| public int | startOpNoThrow(java.lang.String op, int uid, java.lang.String packageName)Like {@link #startOp} but instead of throwing a {@link SecurityException} it
returns {@link #MODE_ERRORED}.
return startOpNoThrow(strOpToOp(op), uid, packageName);
| public int | startOpNoThrow(int op, int uid, java.lang.String packageName)Like {@link #startOp} but instead of throwing a {@link SecurityException} it
returns {@link #MODE_ERRORED}.
try {
return mService.startOperation(getToken(mService), op, uid, packageName);
} catch (RemoteException e) {
}
return MODE_IGNORED;
| public void | startWatchingMode(java.lang.String op, java.lang.String packageName, android.app.AppOpsManager$OnOpChangedListener callback)Monitor for changes to the operating mode for the given op in the given app package.
startWatchingMode(strOpToOp(op), packageName, callback);
| public void | startWatchingMode(int op, java.lang.String packageName, android.app.AppOpsManager$OnOpChangedListener callback)Monitor for changes to the operating mode for the given op in the given app package.
synchronized (mModeWatchers) {
IAppOpsCallback cb = mModeWatchers.get(callback);
if (cb == null) {
cb = new IAppOpsCallback.Stub() {
public void opChanged(int op, String packageName) {
if (callback instanceof OnOpChangedInternalListener) {
((OnOpChangedInternalListener)callback).onOpChanged(op, packageName);
}
if (sOpToString[op] != null) {
callback.onOpChanged(sOpToString[op], packageName);
}
}
};
mModeWatchers.put(callback, cb);
}
try {
mService.startWatchingMode(op, packageName, cb);
} catch (RemoteException e) {
}
}
| public void | stopWatchingMode(android.app.AppOpsManager$OnOpChangedListener callback)Stop monitoring that was previously started with {@link #startWatchingMode}. All
monitoring associated with this callback will be removed.
synchronized (mModeWatchers) {
IAppOpsCallback cb = mModeWatchers.get(callback);
if (cb != null) {
try {
mService.stopWatchingMode(cb);
} catch (RemoteException e) {
}
}
}
| public static int | strDebugOpToOp(java.lang.String op)
for (int i=0; i<sOpNames.length; i++) {
if (sOpNames[i].equals(op)) {
return i;
}
}
throw new IllegalArgumentException("Unknown operation string: " + op);
| public static int | strOpToOp(java.lang.String op){@hide}
Integer val = sOpStrToOp.get(op);
if (val == null) {
throw new IllegalArgumentException("Unknown operation string: " + op);
}
return val;
|
|