Merge "Add start/finishProxyOp methods"

This commit is contained in:
Nate Myren
2020-10-08 21:38:22 +00:00
committed by Android (Google) Code Review
5 changed files with 346 additions and 50 deletions

View File

@@ -4376,6 +4376,7 @@ package android.app {
method @Deprecated public void checkPackage(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 finishProxyOp(@NonNull String, int, @NonNull String, @Nullable String);
method public boolean isOpActive(@NonNull String, int, @NonNull String);
method @Deprecated public int noteOp(@NonNull String, int, @NonNull String);
method public int noteOp(@NonNull String, int, @Nullable String, @Nullable String, @Nullable String);
@@ -4392,6 +4393,8 @@ package android.app {
method public int startOp(@NonNull String, int, @Nullable String, @Nullable String, @Nullable String);
method @Deprecated public int startOpNoThrow(@NonNull String, int, @NonNull String);
method public int startOpNoThrow(@NonNull String, int, @NonNull String, @NonNull String, @Nullable String);
method public int startProxyOp(@NonNull String, int, @NonNull String, @Nullable String, @Nullable String);
method public int startProxyOpNoThrow(@NonNull String, int, @NonNull String, @Nullable String, @Nullable String);
method public void startWatchingActive(@NonNull String[], @NonNull java.util.concurrent.Executor, @NonNull android.app.AppOpsManager.OnOpActiveChangedListener);
method public void startWatchingMode(@NonNull String, @Nullable String, @NonNull android.app.AppOpsManager.OnOpChangedListener);
method public void startWatchingMode(@NonNull String, @Nullable String, int, @NonNull android.app.AppOpsManager.OnOpChangedListener);

View File

@@ -7978,6 +7978,91 @@ public class AppOpsManager {
throw e.rethrowFromSystemServer();
}
}
/**
* Report that an application has started executing a long-running operation on behalf of
* another application when handling an IPC. This function will verify that the calling uid and
* proxied package name match, and if not, return {@link #MODE_IGNORED}.
*
* @param op The op to note
* @param proxiedUid The uid to note the op for {@code null}
* @param proxiedUid The package name the uid belongs to
* @param proxiedAttributionTag The proxied {@link Context#createAttributionContext
* attribution tag} or {@code null} for default attribution
* @param message A message describing the reason the op was noted
*
* @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.
*/
public int startProxyOp(@NonNull String op, int proxiedUid, @NonNull String proxiedPackageName,
@Nullable String proxiedAttributionTag, @Nullable String message) {
final int mode = startProxyOpNoThrow(op, proxiedUid, proxiedPackageName,
proxiedAttributionTag, message);
if (mode == MODE_ERRORED) {
throw new SecurityException("Proxy package " + mContext.getOpPackageName()
+ " from uid " + Process.myUid() + " or calling package " + proxiedPackageName
+ " from uid " + proxiedUid + " not allowed to perform "
+ sOpNames[strOpToOp(op)]);
}
return mode;
}
/**
*Like {@link #startProxyOp(String, int, String, String, String)} but instead
* of throwing a {@link SecurityException} it returns {@link #MODE_ERRORED}.
*
* @param op The op to note
* @param proxiedUid The uid to note the op for {@code null}
* @param proxiedUid The package name the uid belongs to
* @param proxiedAttributionTag The proxied {@link Context#createAttributionContext
* attribution tag} or {@code null} for default attribution
* @param message A message describing the reason the op was noted*
* <p>This API requires package with the {@code proxiedPackageName} to belong to
* {@code proxiedUid}.
*
* @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).
*/
public int startProxyOpNoThrow(@NonNull String op, int proxiedUid,
@NonNull String proxiedPackageName, @Nullable String proxiedAttributionTag,
@Nullable String message) {
try {
int opInt = strOpToOp(op);
collectNoteOpCallsForValidation(opInt);
int collectionMode = getNotedOpCollectionMode(proxiedUid, proxiedPackageName, opInt);
boolean shouldCollectMessage = Process.myUid() == Process.SYSTEM_UID;
if (collectionMode == COLLECT_ASYNC) {
if (message == null) {
// Set stack trace as default message
message = getFormattedStackTrace();
shouldCollectMessage = true;
}
}
int mode = mService.startProxyOperation(getClientId(), opInt, proxiedUid,
proxiedPackageName, proxiedAttributionTag, Process.myUid(),
mContext.getOpPackageName(), mContext.getAttributionTag(), false,
collectionMode == COLLECT_ASYNC, message, shouldCollectMessage);
if (mode == MODE_ALLOWED) {
if (collectionMode == COLLECT_SELF) {
collectNotedOpForSelf(opInt, proxiedAttributionTag);
} else if (collectionMode == COLLECT_SYNC
// Only collect app-ops when the proxy is trusted
&& mContext.checkPermission(Manifest.permission.UPDATE_APP_OPS_STATS, -1,
Process.myUid()) == PackageManager.PERMISSION_GRANTED) {
collectNotedOpSync(opInt, proxiedAttributionTag);
}
}
return mode;
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
* @deprecated Use {@link #finishOp(String, int, String, String)} instead
@@ -8033,6 +8118,28 @@ public class AppOpsManager {
}
}
/**
* Report that an application is no longer performing an operation that had previously
* been started with {@link #startProxyOp(String, int, String, String, 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.
* @param op The operation which was started
* @param proxiedUid The uid the op was started on behalf of
* @param proxiedPackageName The package the op was started on behalf of
* @param proxiedAttributionTag The proxied {@link Context#createAttributionContext
* attribution tag} or {@code null} for default attribution
*/
public void finishProxyOp(@NonNull String op, int proxiedUid,
@NonNull String proxiedPackageName, @Nullable String proxiedAttributionTag) {
try {
mService.finishProxyOperation(getClientId(), strOpToOp(op), proxiedUid,
proxiedPackageName, proxiedAttributionTag, Process.myUid(),
mContext.getOpPackageName(), mContext.getAttributionTag());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
* Checks whether the given op for a package is active, i.e. did someone call {@link #startOp}
* without {@link #finishOp} yet.

View File

@@ -56,6 +56,13 @@ interface IAppOpsService {
String proxiedAttributionTag, int proxyUid, String proxyPackageName,
String proxyAttributionTag, boolean shouldCollectAsyncNotedOp, String message,
boolean shouldCollectMessage);
int startProxyOperation(IBinder clientId, int code, int proxiedUid, String proxiedPackageName,
@nullable String proxiedAttributionTag, int proxyUid, String proxyPackageName,
@nullable String proxyAttributionTag, boolean startIfModeDefault,
boolean shouldCollectAsyncNotedOp, String message, boolean shouldCollectMessage);
void finishProxyOperation(IBinder clientId, int code, int proxiedUid, String proxiedPackageName,
@nullable String proxiedAttributionTag, int proxyUid, String proxyPackageName,
@nullable String proxyAttributionTag);
// Remaining methods are only used in Java.
int checkPackage(int uid, String packageName);

View File

@@ -4376,6 +4376,7 @@ package android.app {
method @Deprecated public void checkPackage(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 finishProxyOp(@NonNull String, int, @NonNull String, @Nullable String);
method public boolean isOpActive(@NonNull String, int, @NonNull String);
method @Deprecated public int noteOp(@NonNull String, int, @NonNull String);
method public int noteOp(@NonNull String, int, @Nullable String, @Nullable String, @Nullable String);
@@ -4392,6 +4393,8 @@ package android.app {
method public int startOp(@NonNull String, int, @Nullable String, @Nullable String, @Nullable String);
method @Deprecated public int startOpNoThrow(@NonNull String, int, @NonNull String);
method public int startOpNoThrow(@NonNull String, int, @NonNull String, @NonNull String, @Nullable String);
method public int startProxyOp(@NonNull String, int, @NonNull String, @Nullable String, @Nullable String);
method public int startProxyOpNoThrow(@NonNull String, int, @NonNull String, @Nullable String, @Nullable String);
method public void startWatchingActive(@NonNull String[], @NonNull java.util.concurrent.Executor, @NonNull android.app.AppOpsManager.OnOpActiveChangedListener);
method public void startWatchingMode(@NonNull String, @Nullable String, @NonNull android.app.AppOpsManager.OnOpChangedListener);
method public void startWatchingMode(@NonNull String, @Nullable String, int, @NonNull android.app.AppOpsManager.OnOpChangedListener);

View File

@@ -29,6 +29,7 @@ import static android.app.AppOpsManager.KEY_BG_STATE_SETTLE_TIME;
import static android.app.AppOpsManager.KEY_FG_SERVICE_STATE_SETTLE_TIME;
import static android.app.AppOpsManager.KEY_TOP_STATE_SETTLE_TIME;
import static android.app.AppOpsManager.MODE_ALLOWED;
import static android.app.AppOpsManager.MODE_DEFAULT;
import static android.app.AppOpsManager.MODE_FOREGROUND;
import static android.app.AppOpsManager.MODE_IGNORED;
import static android.app.AppOpsManager.NoteOpEvent;
@@ -132,6 +133,7 @@ import android.util.AtomicFile;
import android.util.KeyValueListParser;
import android.util.LongSparseArray;
import android.util.Pair;
import android.util.Pools;
import android.util.Pools.SimplePool;
import android.util.Slog;
import android.util.SparseArray;
@@ -408,14 +410,26 @@ public class AppOpsService extends IAppOpsService.Stub {
}
InProgressStartOpEvent acquire(long startTime, long elapsedTime, @NonNull IBinder clientId,
@NonNull Runnable onDeath, int uidState) throws RemoteException {
@NonNull Runnable onDeath, int proxyUid, @Nullable String proxyPackageName,
@Nullable String proxyAttributionTag, @AppOpsManager.UidState int uidState,
@OpFlags int flags) throws RemoteException {
InProgressStartOpEvent recycled = acquire();
OpEventProxyInfo proxyInfo = null;
if (proxyUid != Process.INVALID_UID) {
proxyInfo = mOpEventProxyInfoPool.acquire(proxyUid, proxyPackageName,
proxyAttributionTag);
}
if (recycled != null) {
recycled.reinit(startTime, elapsedTime, clientId, onDeath, uidState);
recycled.reinit(startTime, elapsedTime, clientId, onDeath, uidState, flags,
proxyInfo, mOpEventProxyInfoPool);
return recycled;
}
return new InProgressStartOpEvent(startTime, elapsedTime, clientId, onDeath, uidState);
return new InProgressStartOpEvent(startTime, elapsedTime, clientId, onDeath, uidState,
proxyInfo, flags);
}
}
@@ -670,6 +684,12 @@ public class AppOpsService extends IAppOpsService.Stub {
/** uidstate used when calling startOp */
private @AppOpsManager.UidState int mUidState;
/** Proxy information of the startOp event */
private @Nullable OpEventProxyInfo mProxy;
/** Proxy flag information */
private @OpFlags int mFlags;
/** How many times the op was started but not finished yet */
int numUnfinishedStarts;
@@ -681,17 +701,22 @@ public class AppOpsService extends IAppOpsService.Stub {
* @param clientId The client id of the caller of {@link #startOperation}
* @param onDeath The code to execute on client death
* @param uidState The uidstate of the app {@link #startOperation} was called for
* @param proxy The proxy information, if {@link #startProxyOperation} was called
* @param flags The trusted/nontrusted/self flags.
*
* @throws RemoteException If the client is dying
*/
private InProgressStartOpEvent(long startTime, long startElapsedTime,
@NonNull IBinder clientId, @NonNull Runnable onDeath, int uidState)
throws RemoteException {
@NonNull IBinder clientId, @NonNull Runnable onDeath,
@AppOpsManager.UidState int uidState, @Nullable OpEventProxyInfo proxy,
@OpFlags int flags) throws RemoteException {
mStartTime = startTime;
mStartElapsedTime = startElapsedTime;
mClientId = clientId;
mOnDeath = onDeath;
mUidState = uidState;
mProxy = proxy;
mFlags = flags;
clientId.linkToDeath(this, 0);
}
@@ -714,16 +739,27 @@ public class AppOpsService extends IAppOpsService.Stub {
* @param clientId The client id of the caller of {@link #startOperation}
* @param onDeath The code to execute on client death
* @param uidState The uidstate of the app {@link #startOperation} was called for
* @param flags The flags relating to the proxy
* @param proxy The proxy information, if {@link #startProxyOperation} was called
* @param proxyPool The pool to release previous {@link OpEventProxyInfo} to
*
* @throws RemoteException If the client is dying
*/
public void reinit(long startTime, long startElapsedTime, @NonNull IBinder clientId,
@NonNull Runnable onDeath, int uidState) throws RemoteException {
@NonNull Runnable onDeath, @AppOpsManager.UidState int uidState, @OpFlags int flags,
@Nullable OpEventProxyInfo proxy, @NonNull Pools.Pool<OpEventProxyInfo> proxyPool
) throws RemoteException {
mStartTime = startTime;
mStartElapsedTime = startElapsedTime;
mClientId = clientId;
mOnDeath = onDeath;
mUidState = uidState;
mFlags = flags;
if (mProxy != null) {
proxyPool.release(mProxy);
}
mProxy = proxy;
clientId.linkToDeath(this, 0);
}
@@ -744,9 +780,19 @@ public class AppOpsService extends IAppOpsService.Stub {
}
/** @return uidstate used when calling startOp */
public int getUidState() {
public @AppOpsManager.UidState int getUidState() {
return mUidState;
}
/** @return proxy info for the access */
public @Nullable OpEventProxyInfo getProxy() {
return mProxy;
}
/** @return flags used for the access */
public @OpFlags int getFlags() {
return mFlags;
}
}
private final class AttributedOp {
@@ -876,14 +922,22 @@ public class AppOpsService extends IAppOpsService.Stub {
* Update state when start was called
*
* @param clientId Id of the startOp caller
* @param proxyUid The UID of the proxy app
* @param proxyPackageName The package name of the proxy app
* @param proxyAttributionTag The attribution tag of the proxy app
* @param uidState UID state of the app startOp is called for
* @param flags The proxy flags
*/
public void started(@NonNull IBinder clientId, @AppOpsManager.UidState int uidState)
throws RemoteException {
started(clientId, uidState, true);
public void started(@NonNull IBinder clientId, int proxyUid,
@Nullable String proxyPackageName, @Nullable String proxyAttributionTag,
@AppOpsManager.UidState int uidState, @OpFlags int flags) throws RemoteException {
started(clientId, proxyUid, proxyPackageName, proxyAttributionTag, uidState, flags,
true);
}
private void started(@NonNull IBinder clientId, @AppOpsManager.UidState int uidState,
private void started(@NonNull IBinder clientId, int proxyUid,
@Nullable String proxyPackageName, @Nullable String proxyAttributionTag,
@AppOpsManager.UidState int uidState, @OpFlags int flags,
boolean triggerCallbackIfNeeded) throws RemoteException {
if (triggerCallbackIfNeeded && !parent.isRunning()) {
scheduleOpActiveChangedIfNeededLocked(parent.op, parent.uid,
@@ -899,7 +953,7 @@ public class AppOpsService extends IAppOpsService.Stub {
event = mInProgressStartOpEventPool.acquire(System.currentTimeMillis(),
SystemClock.elapsedRealtime(), clientId,
PooledLambda.obtainRunnable(AppOpsService::onClientDeath, this, clientId),
uidState);
proxyUid, proxyPackageName, proxyAttributionTag, uidState, flags);
mInProgressEvents.put(clientId, event);
} else {
if (uidState != event.mUidState) {
@@ -909,9 +963,8 @@ public class AppOpsService extends IAppOpsService.Stub {
event.numUnfinishedStarts++;
// startOp events don't support proxy, hence use flags==SELF
mHistoricalRegistry.incrementOpAccessedCount(parent.op, parent.uid, parent.packageName,
tag, uidState, OP_FLAG_SELF);
tag, uidState, flags);
}
/**
@@ -945,14 +998,17 @@ public class AppOpsService extends IAppOpsService.Stub {
mAccessEvents = new LongSparseArray<>(1);
}
// startOp events don't support proxy, hence use flags==SELF
OpEventProxyInfo proxyCopy = event.getProxy() != null
? new OpEventProxyInfo(event.getProxy()) : null;
NoteOpEvent finishedEvent = new NoteOpEvent(event.getStartTime(),
SystemClock.elapsedRealtime() - event.getStartElapsedTime(), null);
mAccessEvents.put(makeKey(event.getUidState(), OP_FLAG_SELF), finishedEvent);
SystemClock.elapsedRealtime() - event.getStartElapsedTime(), proxyCopy);
mAccessEvents.put(makeKey(event.getUidState(), event.getFlags()),
finishedEvent);
mHistoricalRegistry.increaseOpAccessDuration(parent.op, parent.uid,
parent.packageName, tag, event.getUidState(),
AppOpsManager.OP_FLAG_SELF, finishedEvent.getDuration());
event.getFlags(), finishedEvent.getDuration());
mInProgressStartOpEventPool.release(event);
@@ -1010,9 +1066,17 @@ public class AppOpsService extends IAppOpsService.Stub {
event.numUnfinishedStarts = 1;
finished(event.getClientId(), false);
OpEventProxyInfo proxy = event.getProxy();
// Call started() to add a new start event object and then add the
// previously removed unfinished start counts back
started(event.getClientId(), newState, false);
if (proxy != null) {
started(event.getClientId(), proxy.getUid(), proxy.getPackageName(),
proxy.getAttributionTag(), newState, event.getFlags(), false);
} else {
started(event.getClientId(), Process.INVALID_UID, null, null, newState,
OP_FLAG_SELF, false);
}
event.numUnfinishedStarts += numPreviousUnfinishedStarts - 1;
} catch (RemoteException e) {
if (DEBUG) Slog.e(TAG, "Cannot switch to new uidState " + newState);
@@ -1116,10 +1180,9 @@ public class AppOpsService extends IAppOpsService.Stub {
for (int i = 0; i < numInProgressEvents; i++) {
InProgressStartOpEvent event = mInProgressEvents.valueAt(i);
// startOp events don't support proxy
accessEvents.append(makeKey(event.getUidState(), OP_FLAG_SELF),
accessEvents.append(makeKey(event.getUidState(), event.getFlags()),
new NoteOpEvent(event.getStartTime(), now - event.getStartElapsedTime(),
null));
event.getProxy()));
}
}
@@ -2182,14 +2245,14 @@ public class AppOpsService extends IAppOpsService.Stub {
if (mode == defaultMode) {
return;
}
previousMode = AppOpsManager.MODE_DEFAULT;
previousMode = MODE_DEFAULT;
uidState = new UidState(uid);
uidState.opModes = new SparseIntArray();
uidState.opModes.put(code, mode);
mUidStates.put(uid, uidState);
scheduleWriteLocked();
} else if (uidState.opModes == null) {
previousMode = AppOpsManager.MODE_DEFAULT;
previousMode = MODE_DEFAULT;
if (mode != defaultMode) {
uidState.opModes = new SparseIntArray();
uidState.opModes.put(code, mode);
@@ -2430,7 +2493,7 @@ public class AppOpsService extends IAppOpsService.Stub {
return;
}
int previousMode = AppOpsManager.MODE_DEFAULT;
int previousMode = MODE_DEFAULT;
synchronized (this) {
UidState uidState = getUidStateLocked(uid, false);
Op op = getOpLocked(code, uid, packageName, null, bypass, true);
@@ -3409,7 +3472,75 @@ public class AppOpsService extends IAppOpsService.Stub {
return result;
}
}
return startOperationUnchecked(clientId, code, uid, packageName, attributionTag,
Process.INVALID_UID, null, null, OP_FLAG_SELF, startIfModeDefault,
shouldCollectAsyncNotedOp, message, shouldCollectMessage, false);
}
@Override
public int startProxyOperation(IBinder clientId, int code, int proxiedUid,
String proxiedPackageName, @Nullable String proxiedAttributionTag, int proxyUid,
String proxyPackageName, @Nullable String proxyAttributionTag,
boolean startIfModeDefault, boolean shouldCollectAsyncNotedOp, String message,
boolean shouldCollectMessage) {
verifyIncomingUid(proxyUid);
verifyIncomingOp(code);
verifyIncomingPackage(proxyPackageName, UserHandle.getUserId(proxyUid));
verifyIncomingPackage(proxiedPackageName, UserHandle.getUserId(proxiedUid));
String resolvedProxyPackageName = resolvePackageName(proxyUid, proxyPackageName);
if (resolvedProxyPackageName == null) {
return AppOpsManager.MODE_IGNORED;
}
final boolean isProxyTrusted = mContext.checkPermission(
Manifest.permission.UPDATE_APP_OPS_STATS, -1, proxyUid)
== PackageManager.PERMISSION_GRANTED;
final int proxyFlags = isProxyTrusted ? AppOpsManager.OP_FLAG_TRUSTED_PROXY
: AppOpsManager.OP_FLAG_UNTRUSTED_PROXY;
String resolvedProxiedPackageName = resolvePackageName(proxiedUid, proxiedPackageName);
if (resolvedProxiedPackageName == null) {
return AppOpsManager.MODE_IGNORED;
}
final int proxiedFlags = isProxyTrusted ? AppOpsManager.OP_FLAG_TRUSTED_PROXIED
: AppOpsManager.OP_FLAG_UNTRUSTED_PROXIED;
// Test if the proxied operation will succeed before starting the proxy operation
final int testProxiedMode = startOperationUnchecked(clientId, code, proxiedUid,
resolvedProxiedPackageName, proxiedAttributionTag, proxyUid,
resolvedProxyPackageName, proxyAttributionTag, proxiedFlags, startIfModeDefault,
shouldCollectAsyncNotedOp, message, shouldCollectMessage, true);
if (!shouldStartForMode(testProxiedMode, startIfModeDefault)) {
return testProxiedMode;
}
final int proxyMode = startOperationUnchecked(clientId, code, proxyUid,
resolvedProxyPackageName, proxyAttributionTag, Process.INVALID_UID, null, null,
proxyFlags, startIfModeDefault, !isProxyTrusted, "proxy " + message,
shouldCollectMessage, false);
if (!shouldStartForMode(proxyMode, startIfModeDefault)
|| Binder.getCallingUid() == proxiedUid) {
return proxyMode;
}
return startOperationUnchecked(clientId, code, proxiedUid, resolvedProxiedPackageName,
proxiedAttributionTag, proxyUid, resolvedProxyPackageName, proxyAttributionTag,
proxiedFlags, startIfModeDefault, shouldCollectAsyncNotedOp, message,
shouldCollectMessage, false);
}
private boolean shouldStartForMode(int mode, boolean startIfModeDefault) {
return (mode == MODE_ALLOWED || (mode == MODE_DEFAULT && startIfModeDefault));
}
private int startOperationUnchecked(IBinder clientId, int code, int uid,
@NonNull String packageName, @Nullable String attributionTag, int proxyUid,
String proxyPackageName, @Nullable String proxyAttributionTag, @OpFlags int flags,
boolean startIfModeDefault, boolean shouldCollectAsyncNotedOp, @Nullable String message,
boolean shouldCollectMessage, boolean dryRun) {
RestrictionBypass bypass;
try {
bypass = verifyAndGetBypass(uid, packageName, attributionTag);
@@ -3419,19 +3550,25 @@ public class AppOpsService extends IAppOpsService.Stub {
}
synchronized (this) {
final Ops ops = getOpsLocked(uid, resolvedPackageName, attributionTag, bypass,
true /* edit */);
final Ops ops = getOpsLocked(uid, packageName, attributionTag, bypass, true /* edit */);
if (ops == null) {
scheduleOpStartedIfNeededLocked(code, uid, packageName, AppOpsManager.MODE_IGNORED);
if (!dryRun) {
scheduleOpStartedIfNeededLocked(code, uid, packageName,
AppOpsManager.MODE_IGNORED);
}
if (DEBUG) Slog.d(TAG, "startOperation: no op for code " + code + " uid " + uid
+ " package " + resolvedPackageName);
+ " package " + packageName);
return AppOpsManager.MODE_ERRORED;
}
final Op op = getOpLocked(ops, code, uid, true);
if (isOpRestrictedLocked(uid, code, resolvedPackageName, bypass)) {
scheduleOpStartedIfNeededLocked(code, uid, packageName, AppOpsManager.MODE_IGNORED);
if (isOpRestrictedLocked(uid, code, packageName, bypass)) {
if (!dryRun) {
scheduleOpStartedIfNeededLocked(code, uid, packageName,
AppOpsManager.MODE_IGNORED);
}
return AppOpsManager.MODE_IGNORED;
}
final AttributedOp attributedOp = op.getOrCreateAttribution(op, attributionTag);
final int switchCode = AppOpsManager.opToSwitch(code);
final UidState uidState = ops.uidState;
@@ -3439,13 +3576,16 @@ public class AppOpsService extends IAppOpsService.Stub {
// non-default) it takes over, otherwise use the per package policy.
if (uidState.opModes != null && uidState.opModes.indexOfKey(switchCode) >= 0) {
final int uidMode = uidState.evalMode(code, uidState.opModes.get(switchCode));
if (uidMode != AppOpsManager.MODE_ALLOWED
&& (!startIfModeDefault || uidMode != AppOpsManager.MODE_DEFAULT)) {
if (DEBUG) Slog.d(TAG, "noteOperation: uid reject #" + uidMode + " for code "
+ switchCode + " (" + code + ") uid " + uid + " package "
+ resolvedPackageName);
attributedOp.rejected(uidState.state, AppOpsManager.OP_FLAG_SELF);
scheduleOpStartedIfNeededLocked(code, uid, packageName, uidMode);
if (!shouldStartForMode(uidMode, startIfModeDefault)) {
if (DEBUG) {
Slog.d(TAG, "startOperation: uid reject #" + uidMode + " for code "
+ switchCode + " (" + code + ") uid " + uid + " package "
+ packageName);
}
if (!dryRun) {
attributedOp.rejected(uidState.state, flags);
scheduleOpStartedIfNeededLocked(code, uid, packageName, uidMode);
}
return uidMode;
}
} else {
@@ -3453,26 +3593,31 @@ public class AppOpsService extends IAppOpsService.Stub {
: op;
final int mode = switchOp.evalMode();
if (mode != AppOpsManager.MODE_ALLOWED
&& (!startIfModeDefault || mode != AppOpsManager.MODE_DEFAULT)) {
&& (!startIfModeDefault || mode != MODE_DEFAULT)) {
if (DEBUG) Slog.d(TAG, "startOperation: reject #" + mode + " for code "
+ switchCode + " (" + code + ") uid " + uid + " package "
+ resolvedPackageName);
attributedOp.rejected(uidState.state, AppOpsManager.OP_FLAG_SELF);
scheduleOpStartedIfNeededLocked(code, uid, packageName, mode);
+ packageName);
if (!dryRun) {
attributedOp.rejected(uidState.state, flags);
scheduleOpStartedIfNeededLocked(code, uid, packageName, mode);
}
return mode;
}
}
if (DEBUG) Slog.d(TAG, "startOperation: allowing code " + code + " uid " + uid
+ " package " + resolvedPackageName);
scheduleOpStartedIfNeededLocked(code, uid, packageName, AppOpsManager.MODE_ALLOWED);
try {
attributedOp.started(clientId, uidState.state);
} catch (RemoteException e) {
throw new RuntimeException(e);
+ " package " + packageName);
if (!dryRun) {
scheduleOpStartedIfNeededLocked(code, uid, packageName, AppOpsManager.MODE_ALLOWED);
try {
attributedOp.started(clientId, proxyUid, proxyPackageName, proxyAttributionTag,
uidState.state, flags);
} catch (RemoteException e) {
throw new RuntimeException(e);
}
}
}
if (shouldCollectAsyncNotedOp) {
if (shouldCollectAsyncNotedOp && !dryRun) {
collectAsyncNotedOp(uid, packageName, code, attributionTag, AppOpsManager.OP_FLAG_SELF,
message, shouldCollectMessage);
}
@@ -3492,6 +3637,37 @@ public class AppOpsService extends IAppOpsService.Stub {
return;
}
finishOperationUnchecked(clientId, code, uid, resolvedPackageName, attributionTag);
}
@Override
public void finishProxyOperation(IBinder clientId, int code, int proxiedUid,
String proxiedPackageName, @Nullable String proxiedAttributionTag, int proxyUid,
@Nullable String proxyPackageName, @Nullable String proxyAttributionTag) {
verifyIncomingUid(proxyUid);
verifyIncomingOp(code);
verifyIncomingPackage(proxyPackageName, UserHandle.getUserId(proxyUid));
verifyIncomingPackage(proxiedPackageName, UserHandle.getUserId(proxiedUid));
String resolvedProxyPackageName = resolvePackageName(proxyUid, proxyPackageName);
if (resolvedProxyPackageName == null) {
return;
}
finishOperationUnchecked(clientId, code, proxyUid, resolvedProxyPackageName,
proxyAttributionTag);
String resolvedProxiedPackageName = resolvePackageName(proxiedUid, proxiedPackageName);
if (resolvedProxiedPackageName == null) {
return;
}
finishOperationUnchecked(clientId, code, proxiedUid, resolvedProxiedPackageName,
proxiedAttributionTag);
}
private void finishOperationUnchecked(IBinder clientId, int code, int uid, String packageName,
String attributionTag) {
RestrictionBypass bypass;
try {
bypass = verifyAndGetBypass(uid, packageName, attributionTag);
@@ -3501,7 +3677,7 @@ public class AppOpsService extends IAppOpsService.Stub {
}
synchronized (this) {
Op op = getOpLocked(code, uid, resolvedPackageName, attributionTag, bypass, true);
Op op = getOpLocked(code, uid, packageName, attributionTag, bypass, true);
if (op == null) {
Slog.e(TAG, "Operation not found: uid=" + uid + " pkg=" + packageName + "("
+ attributionTag + ") op=" + AppOpsManager.opToName(code));