diff options
| author | Nate Myren <ntmyren@google.com> | 2020-10-01 13:20:47 -0700 |
|---|---|---|
| committer | Nate Myren <ntmyren@google.com> | 2020-10-07 14:44:58 -0700 |
| commit | eb75200bc45b63ff06eacf325b4c3c99c1c834ba (patch) | |
| tree | cd9c2f137232ecd0853ab676389b95825be8ae87 /core/java/android | |
| parent | fc97abcae258d0e9f25ea53d900677f0ac666dcb (diff) | |
Add start/finishProxyOp methods
Test: atest AppOpEventCollectionTest
Fixes: 170336396
Change-Id: I825c58d615fe23e6529d1f877e45a896438dbf15
Diffstat (limited to 'core/java/android')
| -rw-r--r-- | core/java/android/app/AppOpsManager.java | 107 |
1 files changed, 107 insertions, 0 deletions
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java index ef4f099f441d..7de6a383ef4c 100644 --- a/core/java/android/app/AppOpsManager.java +++ b/core/java/android/app/AppOpsManager.java @@ -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 @@ -8034,6 +8119,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. * <p> |
