getOpsForPackage(int uid, String packageName, int[] ops) {
try {
return mService.getOpsForPackage(uid, packageName, ops);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
* Sets given app op in the specified mode for app ops in the UID.
* This applies to all apps currently in the UID or installed in
* this UID in the future.
*
* @param code The app op.
* @param uid The UID for which to set the app.
* @param mode The app op mode to set.
* @hide
*/
@RequiresPermission(android.Manifest.permission.MANAGE_APP_OPS_MODES)
public void setUidMode(int code, int uid, int mode) {
try {
mService.setUidMode(code, uid, mode);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
* Sets given app op in the specified mode for app ops in the UID.
* This applies to all apps currently in the UID or installed in
* this UID in the future.
*
* @param appOp The app op.
* @param uid The UID for which to set the app.
* @param mode The app op mode to set.
* @hide
*/
@SystemApi
@RequiresPermission(android.Manifest.permission.MANAGE_APP_OPS_MODES)
public void setUidMode(String appOp, int uid, int mode) {
try {
mService.setUidMode(AppOpsManager.strOpToOp(appOp), uid, mode);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/** @hide */
public void setUserRestriction(int code, boolean restricted, IBinder token) {
setUserRestriction(code, restricted, token, /*exceptionPackages*/null);
}
/** @hide */
public void setUserRestriction(int code, boolean restricted, IBinder token,
String[] exceptionPackages) {
setUserRestrictionForUser(code, restricted, token, exceptionPackages, mContext.getUserId());
}
/** @hide */
public void setUserRestrictionForUser(int code, boolean restricted, IBinder token,
String[] exceptionPackages, int userId) {
try {
mService.setUserRestriction(code, restricted, token, userId, exceptionPackages);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/** @hide */
@TestApi
@RequiresPermission(android.Manifest.permission.MANAGE_APP_OPS_MODES)
public void setMode(int code, int uid, String packageName, int mode) {
try {
mService.setMode(code, uid, packageName, mode);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
* Change the operating mode for the given op in the given app package. You must pass
* in both the uid and name of the application whose mode is being modified; if these
* do not match, the modification will not be applied.
*
* @param op The operation to modify. One of the OPSTR_* constants.
* @param uid The user id of the application whose mode will be changed.
* @param packageName The name of the application package name whose mode will
* be changed.
* @hide
*/
@SystemApi
@RequiresPermission(android.Manifest.permission.MANAGE_APP_OPS_MODES)
public void setMode(String op, int uid, String packageName, int mode) {
try {
mService.setMode(strOpToOp(op), uid, packageName, mode);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
* 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}.
*
* @param code The operation to restrict.
* @param usage The {@link android.media.AudioAttributes} usage value.
* @param mode The restriction mode (MODE_IGNORED,MODE_ERRORED) or MODE_ALLOWED to unrestrict.
* @param exceptionPackages Optional list of packages to exclude from the restriction.
* @hide
*/
@RequiresPermission(android.Manifest.permission.MANAGE_APP_OPS_MODES)
public void setRestriction(int code, @AttributeUsage int usage, int mode,
String[] exceptionPackages) {
try {
final int uid = Binder.getCallingUid();
mService.setAudioRestriction(code, usage, uid, mode, exceptionPackages);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/** @hide */
@RequiresPermission(android.Manifest.permission.MANAGE_APP_OPS_MODES)
public void resetAllModes() {
try {
mService.resetAllModes(mContext.getUserId(), null);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
* Gets the app op name associated with a given permission.
* The app op name is one of the public constants defined
* in this class such as {@link #OPSTR_COARSE_LOCATION}.
* This API is intended to be used for mapping runtime
* permissions to the corresponding app op.
*
* @param permission The permission.
* @return The app op associated with the permission or null.
*/
public static String permissionToOp(String permission) {
final Integer opCode = sPermToOp.get(permission);
if (opCode == null) {
return null;
}
return sOpToString[opCode];
}
/**
* 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.
*/
public void startWatchingMode(String op, String packageName,
final OnOpChangedListener callback) {
startWatchingMode(strOpToOp(op), packageName, callback);
}
/**
* 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 flags Option flags: any combination of {@link #WATCH_FOREGROUND_CHANGES} or 0.
* @param callback Where to report changes.
* @hide
*/
public void startWatchingMode(String op, String packageName, int flags,
final OnOpChangedListener callback) {
startWatchingMode(strOpToOp(op), packageName, flags, callback);
}
/**
* Monitor for changes to the operating mode for the given op in the given app package.
*
* If you don't hold the {@link android.Manifest.permission#WATCH_APPOPS} permission
* you can 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
*/
@RequiresPermission(value=android.Manifest.permission.WATCH_APPOPS, conditional=true)
public void startWatchingMode(int op, String packageName, final OnOpChangedListener callback) {
startWatchingMode(op, packageName, 0, callback);
}
/**
* Monitor for changes to the operating mode for the given op in the given app package.
*
*
If you don't hold the {@link android.Manifest.permission#WATCH_APPOPS} permission
* you can 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 flags Option flags: any combination of {@link #WATCH_FOREGROUND_CHANGES} or 0.
* @param callback Where to report changes.
* @hide
*/
@RequiresPermission(value=android.Manifest.permission.WATCH_APPOPS, conditional=true)
public void startWatchingMode(int op, String packageName, int flags,
final OnOpChangedListener callback) {
synchronized (mModeWatchers) {
IAppOpsCallback cb = mModeWatchers.get(callback);
if (cb == null) {
cb = new IAppOpsCallback.Stub() {
public void opChanged(int op, int uid, 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.startWatchingModeWithFlags(op, packageName, flags, cb);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
}
/**
* Stop monitoring that was previously started with {@link #startWatchingMode}. All
* monitoring associated with this callback will be removed.
*/
public void stopWatchingMode(OnOpChangedListener callback) {
synchronized (mModeWatchers) {
IAppOpsCallback cb = mModeWatchers.get(callback);
if (cb != null) {
try {
mService.stopWatchingMode(cb);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
}
}
/**
* 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.
*
*
If you don't hold the {@link android.Manifest.permission#WATCH_APPOPS} permission
* you can watch changes only for your UID.
*
* @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
*/
@TestApi
// TODO: Uncomment below annotation once b/73559440 is fixed
// @RequiresPermission(value=Manifest.permission.WATCH_APPOPS, conditional=true)
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
*/
@TestApi
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];
}
/**
* {@hide}
*/
public static int strOpToOp(String op) {
Integer val = sOpStrToOp.get(op);
if (val == null) {
throw new IllegalArgumentException("Unknown operation string: " + op);
}
return val;
}
/**
* 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.
*
*
Important things this will not do (which you need to ultimate use
* {@link #noteOp(String, int, String)} or {@link #startOp(String, int, String)} to cover):
*
* - Verifying the uid and package are consistent, so callers can't spoof
* their identity.
* - Taking into account the current foreground/background state of the
* app; apps whose mode varies by this state will always be reported
* as {@link #MODE_ALLOWED}.
*
*
* @param op The operation to check. One of the OPSTR_* constants.
* @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.
* @return Returns {@link #MODE_ALLOWED} if the operation is allowed, or
* {@link #MODE_IGNORED} if it is not allowed and should be silently ignored (without
* causing the app to crash).
* @throws SecurityException If the app has been configured to crash on this op.
*/
public int checkOp(String op, int uid, String packageName) {
return checkOp(strOpToOp(op), uid, packageName);
}
/**
* Like {@link #checkOp} but instead of throwing a {@link SecurityException} it
* returns {@link #MODE_ERRORED}.
*/
public int checkOpNoThrow(String op, int uid, String packageName) {
return checkOpNoThrow(strOpToOp(op), uid, packageName);
}
/**
* Like {@link #checkOp} but returns the raw mode associated with the op.
* Does not throw a security exception, does not translate {@link #MODE_FOREGROUND}.
* @hide
*/
public int unsafeCheckOpRaw(String op, int uid, String packageName) {
try {
return mService.checkOperation(strOpToOp(op), uid, packageName);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
* 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.
* @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 packageName The name of the application attempting to perform the operation.
* @return Returns {@link #MODE_ALLOWED} if the operation is allowed, or
* {@link #MODE_IGNORED} if it is not allowed and should be silently ignored (without
* causing the app to crash).
* @throws SecurityException If the app has been configured to crash on this op.
*/
public int noteOp(String op, int uid, String packageName) {
return noteOp(strOpToOp(op), uid, packageName);
}
/**
* Like {@link #noteOp} but instead of throwing a {@link SecurityException} it
* returns {@link #MODE_ERRORED}.
*/
public int noteOpNoThrow(String op, int uid, String packageName) {
return noteOpNoThrow(strOpToOp(op), uid, packageName);
}
/**
* Make note of an application performing an operation on behalf of another
* application when handling an IPC. Note that you must pass the package name
* of the application that is being proxied while its UID will be inferred from
* the IPC state; this function will verify that the calling uid and proxied
* package name match, and if not, return {@link #MODE_IGNORED}. If this call
* succeeds, the last execution time of the operation for the proxied app and
* your app will be updated to the current time.
* @param op The operation to note. One of the OPSTR_* constants.
* @param proxiedPackageName The name of the application calling into the proxy application.
* @return Returns {@link #MODE_ALLOWED} if the operation is allowed, or
* {@link #MODE_IGNORED} if it is not allowed and should be silently ignored (without
* causing the app to crash).
* @throws SecurityException If the app has been configured to crash on this op.
*/
public int noteProxyOp(String op, String proxiedPackageName) {
return noteProxyOp(strOpToOp(op), proxiedPackageName);
}
/**
* Like {@link #noteProxyOp(String, String)} but instead
* of throwing a {@link SecurityException} it returns {@link #MODE_ERRORED}.
*/
public int noteProxyOpNoThrow(String op, String proxiedPackageName) {
return noteProxyOpNoThrow(strOpToOp(op), proxiedPackageName);
}
/**
* 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.
* @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 packageName The name of the application attempting to perform the operation.
* @return Returns {@link #MODE_ALLOWED} if the operation is allowed, or
* {@link #MODE_IGNORED} if it is not allowed and should be silently ignored (without
* causing the app to crash).
* @throws SecurityException If the app has been configured to crash on this op.
*/
public int startOp(String op, int uid, String packageName) {
return startOp(strOpToOp(op), uid, packageName);
}
/**
* Like {@link #startOp} but instead of throwing a {@link SecurityException} it
* returns {@link #MODE_ERRORED}.
*/
public int startOpNoThrow(String op, int uid, String packageName) {
return startOpNoThrow(strOpToOp(op), uid, 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.
*/
public void finishOp(String op, int uid, String packageName) {
finishOp(strOpToOp(op), uid, 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.
*
* Important things this will not do (which you need to ultimate use
* {@link #noteOp(int, int, String)} or {@link #startOp(int, int, String)} to cover):
*
* - Verifying the uid and package are consistent, so callers can't spoof
* their identity.
* - Taking into account the current foreground/background state of the
* app; apps whose mode varies by this state will always be reported
* as {@link #MODE_ALLOWED}.
*
*
* @param op The operation to check. One of the OP_* constants.
* @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.
* @return Returns {@link #MODE_ALLOWED} if the operation is allowed, or
* {@link #MODE_IGNORED} if it is not allowed and should be silently ignored (without
* causing the app to crash).
* @throws SecurityException If the app has been configured to crash on this op.
* @hide
*/
public int checkOp(int op, int uid, String packageName) {
try {
int mode = mService.checkOperation(op, uid, packageName);
if (mode == MODE_ERRORED) {
throw new SecurityException(buildSecurityExceptionMsg(op, uid, packageName));
}
return mode;
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
* Like {@link #checkOp} but instead of throwing a {@link SecurityException} it
* returns {@link #MODE_ERRORED}.
* @hide
*/
public int checkOpNoThrow(int op, int uid, String packageName) {
try {
int mode = mService.checkOperation(op, uid, packageName);
return mode == AppOpsManager.MODE_FOREGROUND ? AppOpsManager.MODE_ALLOWED : mode;
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
* Do a quick check to validate if a package name belongs to a UID.
*
* @throws SecurityException if the package name doesn't belong to the given
* UID, or if ownership cannot be verified.
*/
public void checkPackage(int uid, String packageName) {
try {
if (mService.checkPackage(uid, packageName) != MODE_ALLOWED) {
throw new SecurityException(
"Package " + packageName + " does not belong to " + uid);
}
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
* Like {@link #checkOp} but at a stream-level for audio operations.
* @hide
*/
public int checkAudioOp(int op, int stream, int uid, String packageName) {
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) {
throw e.rethrowFromSystemServer();
}
}
/**
* Like {@link #checkAudioOp} but instead of throwing a {@link SecurityException} it
* returns {@link #MODE_ERRORED}.
* @hide
*/
public int checkAudioOpNoThrow(int op, int stream, int uid, String packageName) {
try {
return mService.checkAudioOperation(op, stream, uid, packageName);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
* 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.
* @param op The operation to note. One of the OP_* constants.
* @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.
* @return Returns {@link #MODE_ALLOWED} if the operation is allowed, or
* {@link #MODE_IGNORED} if it is not allowed and should be silently ignored (without
* causing the app to crash).
* @throws SecurityException If the app has been configured to crash on this op.
* @hide
*/
public int noteOp(int op, int uid, String packageName) {
final int mode = noteOpNoThrow(op, uid, packageName);
if (mode == MODE_ERRORED) {
throw new SecurityException(buildSecurityExceptionMsg(op, uid, packageName));
}
return mode;
}
/**
* Make note of an application performing an operation on behalf of another
* application when handling an IPC. Note that you must pass the package name
* of the application that is being proxied while its UID will be inferred from
* the IPC state; this function will verify that the calling uid and proxied
* package name match, and if not, return {@link #MODE_IGNORED}. If this call
* succeeds, the last execution time of the operation for the proxied app and
* your app will be updated to the current time.
* @param op The operation to note. One of the OPSTR_* constants.
* @param proxiedPackageName The name of the application calling into the proxy application.
* @return Returns {@link #MODE_ALLOWED} if the operation is allowed, or
* {@link #MODE_IGNORED} if it is not allowed and should be silently ignored (without
* causing the app to crash).
* @throws SecurityException If the proxy or proxied app has been configured to
* crash on this op.
*
* @hide
*/
public int noteProxyOp(int op, String proxiedPackageName) {
int mode = noteProxyOpNoThrow(op, proxiedPackageName);
if (mode == MODE_ERRORED) {
throw new SecurityException("Proxy package " + mContext.getOpPackageName()
+ " from uid " + Process.myUid() + " or calling package "
+ proxiedPackageName + " from uid " + Binder.getCallingUid()
+ " not allowed to perform " + sOpNames[op]);
}
return mode;
}
/**
* Like {@link #noteProxyOp(int, String)} but instead
* of throwing a {@link SecurityException} it returns {@link #MODE_ERRORED}.
* @hide
*/
public int noteProxyOpNoThrow(int op, String proxiedPackageName) {
try {
return mService.noteProxyOperation(op, mContext.getOpPackageName(),
Binder.getCallingUid(), proxiedPackageName);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
* Like {@link #noteOp} but instead of throwing a {@link SecurityException} it
* returns {@link #MODE_ERRORED}.
* @hide
*/
public int noteOpNoThrow(int op, int uid, String packageName) {
try {
return mService.noteOperation(op, uid, packageName);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/** @hide */
public int noteOp(int op) {
return noteOp(op, Process.myUid(), mContext.getOpPackageName());
}
/** @hide */
public static IBinder getToken(IAppOpsService service) {
synchronized (AppOpsManager.class) {
if (sToken != null) {
return sToken;
}
try {
sToken = service.getToken(new Binder());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
return sToken;
}
}
/** @hide */
public int startOp(int op) {
return startOp(op, Process.myUid(), mContext.getOpPackageName());
}
/**
* 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.
*
* @param op The operation to start. One of the OP_* constants.
* @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.
* @return Returns {@link #MODE_ALLOWED} if the operation is allowed, or
* {@link #MODE_IGNORED} if it is not allowed and should be silently ignored (without
* causing the app to crash).
* @throws SecurityException If the app has been configured to crash on this op.
* @hide
*/
public int startOp(int op, int uid, String packageName) {
return startOp(op, uid, packageName, false);
}
/**
* Report that an application has started executing a long-running operation. Similar
* to {@link #startOp(String, int, String) except that if the mode is {@link #MODE_DEFAULT}
* the operation should succeed since the caller has performed its standard permission
* checks which passed and would perform the protected operation for this mode.
*
* @param op The operation to start. One of the OP_* constants.
* @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.
* @return Returns {@link #MODE_ALLOWED} if the operation is allowed, or
* {@link #MODE_IGNORED} if it is not allowed and should be silently ignored (without
* causing the app to crash).
* @param startIfModeDefault Whether to start if mode is {@link #MODE_DEFAULT}.
*
* @throws SecurityException If the app has been configured to crash on this op or
* the package is not in the passed in UID.
*
* @hide
*/
public int startOp(int op, int uid, String packageName, boolean startIfModeDefault) {
final int mode = startOpNoThrow(op, uid, packageName, startIfModeDefault);
if (mode == MODE_ERRORED) {
throw new SecurityException(buildSecurityExceptionMsg(op, uid, packageName));
}
return mode;
}
/**
* Like {@link #startOp} but instead of throwing a {@link SecurityException} it
* returns {@link #MODE_ERRORED}.
* @hide
*/
public int startOpNoThrow(int op, int uid, String packageName) {
return startOpNoThrow(op, uid, packageName, false);
}
/**
* Like {@link #startOp(int, int, String, boolean)} but instead of throwing a
* {@link SecurityException} it returns {@link #MODE_ERRORED}.
*
* @param op The operation to start. One of the OP_* constants.
* @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.
* @return Returns {@link #MODE_ALLOWED} if the operation is allowed, or
* {@link #MODE_IGNORED} if it is not allowed and should be silently ignored (without
* causing the app to crash).
* @param startIfModeDefault Whether to start if mode is {@link #MODE_DEFAULT}.
*
* @hide
*/
public int startOpNoThrow(int op, int uid, String packageName, boolean startIfModeDefault) {
try {
return mService.startOperation(getToken(mService), op, uid, packageName,
startIfModeDefault);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
* 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.
* @hide
*/
public void finishOp(int op, int uid, String packageName) {
try {
mService.finishOperation(getToken(mService), op, uid, packageName);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/** @hide */
public void finishOp(int op) {
finishOp(op, Process.myUid(), mContext.getOpPackageName());
}
/**
* Checks whether the given op for a UID and package is active.
*
* If you don't hold the {@link android.Manifest.permission#WATCH_APPOPS} permission
* you can query only for your UID.
*
* @see #startWatchingActive(int[], OnOpActiveChangedListener)
* @see #stopWatchingMode(OnOpChangedListener)
* @see #finishOp(int)
* @see #startOp(int)
*
* @hide */
@TestApi
// TODO: Uncomment below annotation once b/73559440 is fixed
// @RequiresPermission(value=Manifest.permission.WATCH_APPOPS, conditional=true)
public boolean isOperationActive(int code, int uid, String packageName) {
try {
return mService.isOperationActive(code, uid, packageName);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
* Returns all supported operation names.
* @hide
*/
@SystemApi
@TestApi
public static String[] getOpStrs() {
return Arrays.copyOf(sOpToString, sOpToString.length);
}
/**
* @hide
*/
public static long maxTime(long[] times, int start, int end) {
long time = 0;
for (int i = start; i < end; i++) {
if (times[i] > time) {
time = times[i];
}
}
return time;
}
}