Loading core/api/test-current.txt +11 −2 Original line number Diff line number Diff line Loading @@ -201,6 +201,11 @@ package android.app { 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 public static int strOpToOp(@NonNull String); field public static final int ATTRIBUTION_CHAIN_ID_NONE = -1; // 0xffffffff field public static final int ATTRIBUTION_FLAGS_NONE = 0; // 0x0 field public static final int ATTRIBUTION_FLAG_ACCESSOR = 1; // 0x1 field public static final int ATTRIBUTION_FLAG_INTERMEDIARY = 2; // 0x2 field public static final int ATTRIBUTION_FLAG_RECEIVER = 4; // 0x4 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_PASSIVE = 2; // 0x2 Loading Loading @@ -230,6 +235,10 @@ package android.app { method public void offsetBeginAndEndTime(long); } public static interface AppOpsManager.OnOpActiveChangedListener { method public default void onOpActiveChanged(@NonNull String, int, @NonNull String, @Nullable String, boolean, int, int); } public class BroadcastOptions { ctor public BroadcastOptions(@NonNull android.os.Bundle); method public int getMaxManifestReceiverApiLevel(); Loading Loading @@ -669,7 +678,7 @@ package android.content { public final class AttributionSource implements android.os.Parcelable { ctor public AttributionSource(int, @Nullable String, @Nullable String); ctor public AttributionSource(int, @Nullable String, @Nullable String, @Nullable android.content.AttributionSource); ctor public AttributionSource(int, @Nullable String, @Nullable String, @NonNull android.os.IBinder); ctor public AttributionSource(int, @Nullable String, @Nullable String, @Nullable java.util.Set<java.lang.String>, @Nullable android.content.AttributionSource); } Loading Loading @@ -2041,7 +2050,7 @@ package android.permission { public final class PermissionManager { method @NonNull @RequiresPermission(android.Manifest.permission.GET_APP_OPS_STATS) public java.util.List<android.permission.PermGroupUsage> getIndicatorAppOpUsageData(); method @NonNull @RequiresPermission(android.Manifest.permission.GET_APP_OPS_STATS) public java.util.List<android.permission.PermGroupUsage> getIndicatorAppOpUsageData(boolean); method @NonNull public android.content.AttributionSource registerAttributionSource(@NonNull android.content.AttributionSource); method public void registerAttributionSource(@NonNull android.content.AttributionSource); } } Loading core/java/android/app/AppOpsManager.java +156 −21 Original line number Diff line number Diff line Loading @@ -708,6 +708,62 @@ public class AppOpsManager { } } /** * Attribution chain flag: specifies that this is the accessor. When * an app A accesses the data that is then passed to app B that is then * passed to C, we call app A accessor, app B intermediary, and app C * receiver. If A accesses the data for itself, then it is the accessor * and the receiver. * @hide */ @TestApi public static final int ATTRIBUTION_FLAG_ACCESSOR = 0x1; /** * Attribution chain flag: specifies that this is the intermediary. When * an app A accesses the data that is then passed to app B that is then * passed to C, we call app A accessor, app B intermediary, and app C * receiver. If A accesses the data for itself, then it is the accessor * and the receiver. * @hide */ @TestApi public static final int ATTRIBUTION_FLAG_INTERMEDIARY = 0x2; /** * Attribution chain flag: specifies that this is the receiver. When * an app A accesses the data that is then passed to app B that is then * passed to C, we call app A accessor, app B intermediary, and app C * receiver. If A accesses the data for itself, then it is the accessor * and the receiver. * @hide */ @TestApi public static final int ATTRIBUTION_FLAG_RECEIVER = 0x4; /** * No attribution flags. * @hide */ @TestApi public static final int ATTRIBUTION_FLAGS_NONE = 0x0; /** * No attribution chain id. * @hide */ @TestApi public static final int ATTRIBUTION_CHAIN_ID_NONE = -1; /** @hide */ @Retention(RetentionPolicy.SOURCE) @IntDef(flag = true, prefix = { "FLAG_" }, value = { ATTRIBUTION_FLAG_ACCESSOR, ATTRIBUTION_FLAG_INTERMEDIARY, ATTRIBUTION_FLAG_RECEIVER }) public @interface AttributionFlags {} // These constants are redefined here to work around a metalava limitation/bug where // @IntDef is not able to see @hide symbols when they are hidden via package hiding: // frameworks/base/core/java/com/android/internal/package.html Loading Loading @@ -7063,6 +7119,25 @@ public class AppOpsManager { */ void onOpActiveChanged(@NonNull String op, int uid, @NonNull String packageName, boolean active); /** * Called when the active state of an app-op changes. * * @param op The operation that changed. * @param uid The UID performing the operation. * @param packageName The package performing the operation. * @param attributionTag The operation's attribution tag. * @param active Whether the operation became active or inactive. * @param attributionFlags the attribution flags for this operation. * @param attributionChainId the unique id of the attribution chain this op is a part of. * @hide */ @TestApi default void onOpActiveChanged(@NonNull String op, int uid, @NonNull String packageName, @Nullable String attributionTag, boolean active, @AttributionFlags int attributionFlags, int attributionChainId) { onOpActiveChanged(op, uid, packageName, active); } } /** Loading Loading @@ -7684,14 +7759,17 @@ public class AppOpsManager { } cb = new IAppOpsActiveCallback.Stub() { @Override public void opActiveChanged(int op, int uid, String packageName, boolean active) { public void opActiveChanged(int op, int uid, String packageName, String attributionTag, boolean active, @AttributionFlags int attributionFlags, int attributionChainId) { executor.execute(() -> { if (callback instanceof OnOpActiveChangedInternalListener) { ((OnOpActiveChangedInternalListener) callback).onOpActiveChanged(op, uid, packageName, active); } if (sOpToString[op] != null) { callback.onOpActiveChanged(sOpToString[op], uid, packageName, active); callback.onOpActiveChanged(sOpToString[op], uid, packageName, attributionTag, active, attributionFlags, attributionChainId); } }); } Loading Loading @@ -8169,8 +8247,9 @@ public class AppOpsManager { public int noteProxyOp(int op, @Nullable String proxiedPackageName, int proxiedUid, @Nullable String proxiedAttributionTag, @Nullable String message) { return noteProxyOp(op, new AttributionSource(mContext.getAttributionSource(), new AttributionSource(proxiedUid, proxiedPackageName, proxiedAttributionTag)), message, /*skipProxyOperation*/ false); new AttributionSource(proxiedUid, proxiedPackageName, proxiedAttributionTag, mContext.getAttributionSource().getToken())), message, /*skipProxyOperation*/ false); } /** Loading Loading @@ -8255,8 +8334,8 @@ public class AppOpsManager { int proxiedUid, @Nullable String proxiedAttributionTag, @Nullable String message) { return noteProxyOpNoThrow(strOpToOp(op), new AttributionSource( mContext.getAttributionSource(), new AttributionSource(proxiedUid, proxiedPackageName, proxiedAttributionTag)), message, /*skipProxyOperation*/ false); proxiedPackageName, proxiedAttributionTag, mContext.getAttributionSource() .getToken())), message,/*skipProxyOperation*/ false); } /** Loading Loading @@ -8592,6 +8671,29 @@ public class AppOpsManager { */ public int startOpNoThrow(int op, int uid, @NonNull String packageName, boolean startIfModeDefault, @Nullable String attributionTag, @Nullable String message) { return startOpNoThrow(mContext.getAttributionSource().getToken(), op, uid, packageName, startIfModeDefault, attributionTag, message); } /** * @see #startOpNoThrow(String, int, String, String, String) * * @hide */ public int startOpNoThrow(@NonNull IBinder token, int op, int uid, @NonNull String packageName, boolean startIfModeDefault, @Nullable String attributionTag, @Nullable String message) { return startOpNoThrow(token, op, uid, packageName, startIfModeDefault, attributionTag, message, ATTRIBUTION_FLAGS_NONE, ATTRIBUTION_CHAIN_ID_NONE); } /** * @see #startOpNoThrow(String, int, String, String, String) * * @hide */ public int startOpNoThrow(@NonNull IBinder token, int op, int uid, @NonNull String packageName, boolean startIfModeDefault, @Nullable String attributionTag, @Nullable String message, @AttributionFlags int attributionFlags, int attributionChainId) { try { collectNoteOpCallsForValidation(op); int collectionMode = getNotedOpCollectionMode(uid, packageName, op); Loading @@ -8604,9 +8706,9 @@ public class AppOpsManager { } } SyncNotedAppOp syncOp = mService.startOperation(getClientId(), op, uid, packageName, SyncNotedAppOp syncOp = mService.startOperation(token, op, uid, packageName, attributionTag, startIfModeDefault, collectionMode == COLLECT_ASYNC, message, shouldCollectMessage); shouldCollectMessage, attributionFlags, attributionChainId); if (syncOp.getOpMode() == MODE_ALLOWED) { if (collectionMode == COLLECT_SELF) { Loading Loading @@ -8643,8 +8745,9 @@ public class AppOpsManager { public int startProxyOp(@NonNull String op, int proxiedUid, @NonNull String proxiedPackageName, @Nullable String proxiedAttributionTag, @Nullable String message) { return startProxyOp(op, new AttributionSource(mContext.getAttributionSource(), new AttributionSource(proxiedUid, proxiedPackageName, proxiedAttributionTag)), message, /*skipProxyOperation*/ false); new AttributionSource(proxiedUid, proxiedPackageName, proxiedAttributionTag, mContext.getAttributionSource().getToken())), message, /*skipProxyOperation*/ false); } /** Loading Loading @@ -8690,7 +8793,8 @@ public class AppOpsManager { @Nullable String message) { return startProxyOpNoThrow(AppOpsManager.strOpToOp(op), new AttributionSource( mContext.getAttributionSource(), new AttributionSource(proxiedUid, proxiedPackageName, proxiedAttributionTag)), message, proxiedPackageName, proxiedAttributionTag, mContext.getAttributionSource().getToken())), message, /*skipProxyOperation*/ false); } Loading @@ -8705,6 +8809,23 @@ public class AppOpsManager { */ public int startProxyOpNoThrow(int op, @NonNull AttributionSource attributionSource, @Nullable String message, boolean skipProxyOperation) { return startProxyOpNoThrow(op, attributionSource, message, skipProxyOperation, ATTRIBUTION_FLAGS_NONE, ATTRIBUTION_FLAGS_NONE, ATTRIBUTION_CHAIN_ID_NONE); } /** * Like {@link #startProxyOp(String, AttributionSource, String)} but instead * of throwing a {@link SecurityException} it returns {@link #MODE_ERRORED} and * the checks is for the attribution chain specified by the {@link AttributionSource}. * * @see #startProxyOp(String, AttributionSource, String) * * @hide */ public int startProxyOpNoThrow(int op, @NonNull AttributionSource attributionSource, @Nullable String message, boolean skipProxyOperation, @AttributionFlags int proxyAttributionFlags, @AttributionFlags int proxiedAttributionFlags, int attributionChainId) { try { collectNoteOpCallsForValidation(op); int collectionMode = getNotedOpCollectionMode( Loading @@ -8719,9 +8840,10 @@ public class AppOpsManager { } } SyncNotedAppOp syncOp = mService.startProxyOperation(getClientId(), op, SyncNotedAppOp syncOp = mService.startProxyOperation(op, attributionSource, false, collectionMode == COLLECT_ASYNC, message, shouldCollectMessage, skipProxyOperation); shouldCollectMessage, skipProxyOperation, proxyAttributionFlags, proxiedAttributionFlags, attributionChainId); if (syncOp.getOpMode() == MODE_ALLOWED) { if (collectionMode == COLLECT_SELF) { Loading Loading @@ -8785,8 +8907,18 @@ public class AppOpsManager { */ public void finishOp(int op, int uid, @NonNull String packageName, @Nullable String attributionTag) { finishOp(mContext.getAttributionSource().getToken(), op, uid, packageName, attributionTag); } /** * @see #finishOp(String, int, String, String) * * @hide */ public void finishOp(IBinder token, int op, int uid, @NonNull String packageName, @Nullable String attributionTag) { try { mService.finishOperation(getClientId(), op, uid, packageName, attributionTag); mService.finishOperation(token, op, uid, packageName, attributionTag); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } Loading @@ -8807,23 +8939,26 @@ public class AppOpsManager { public void finishProxyOp(@NonNull String op, int proxiedUid, @NonNull String proxiedPackageName, @Nullable String proxiedAttributionTag) { finishProxyOp(op, new AttributionSource(mContext.getAttributionSource(), new AttributionSource(proxiedUid, proxiedPackageName, proxiedAttributionTag))); new AttributionSource(proxiedUid, proxiedPackageName, proxiedAttributionTag, mContext.getAttributionSource().getToken())), /*skipProxyOperation*/ false); } /** * Report that an application is no longer performing an operation that had previously * been started with {@link #startProxyOp(String, AttributionSource, 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. * been started with {@link #startProxyOp(String, AttributionSource, String, boolean)}. 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 attributionSource The permission identity for which to finish * @param skipProxyOperation Whether to skip the proxy finish. * * @hide */ public void finishProxyOp(@NonNull String op, @NonNull AttributionSource attributionSource) { public void finishProxyOp(@NonNull String op, @NonNull AttributionSource attributionSource, boolean skipProxyOperation) { try { mService.finishProxyOperation(getClientId(), strOpToOp(op), attributionSource); mService.finishProxyOperation(strOpToOp(op), attributionSource, skipProxyOperation); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } Loading core/java/android/app/AppOpsManagerInternal.java +23 −17 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ package android.app; import android.app.AppOpsManager.AttributionFlags; import android.annotation.NonNull; import android.annotation.Nullable; import android.content.AttributionSource; Loading @@ -24,13 +25,13 @@ import android.util.SparseArray; import android.util.SparseIntArray; import com.android.internal.app.IAppOpsCallback; import com.android.internal.util.function.DecFunction; import com.android.internal.util.function.HeptFunction; import com.android.internal.util.function.HexFunction; import com.android.internal.util.function.NonaFunction; import com.android.internal.util.function.OctFunction; import com.android.internal.util.function.QuadFunction; import com.android.internal.util.function.QuintFunction; import com.android.internal.util.function.TriFunction; import com.android.internal.util.function.UndecFunction; /** * App ops service local interface. Loading @@ -52,8 +53,8 @@ public abstract class AppOpsManagerInternal { * @return The app op check result. */ int checkOperation(int code, int uid, String packageName, @Nullable String attributionTag, boolean raw, QuintFunction<Integer, Integer, String, String, Boolean, Integer> superImpl); boolean raw, QuintFunction<Integer, Integer, String, String, Boolean, Integer> superImpl); /** * Allows overriding check audio operation behavior. Loading Loading @@ -116,20 +117,22 @@ public abstract class AppOpsManagerInternal { * @param shouldCollectAsyncNotedOp If an {@link AsyncNotedAppOp} should be collected * @param message The message in the async noted op * @param shouldCollectMessage whether to collect messages * @param attributionFlags the attribution flags for this operation. * @param attributionChainId the unique id of the attribution chain this op is a part of. * @param superImpl The super implementation. * @return The app op note result. */ SyncNotedAppOp startOperation(IBinder token, int code, int uid, @Nullable String packageName, @Nullable String attributionTag, boolean startIfModeDefault, boolean shouldCollectAsyncNotedOp, @Nullable String message, boolean shouldCollectMessage, @NonNull NonaFunction< IBinder, Integer, Integer, String, String, Boolean, Boolean, String, Boolean, SyncNotedAppOp> superImpl); @Nullable String message, boolean shouldCollectMessage, @AttributionFlags int attributionFlags, int attributionChainId, @NonNull UndecFunction<IBinder, Integer, Integer, String, String, Boolean, Boolean, String, Boolean, Integer, Integer, SyncNotedAppOp> superImpl); /** * Allows overriding start proxy operation behavior. * * @param token The client state. * @param code The op code to start. * @param attributionSource The permission identity of the caller. * @param startIfModeDefault Whether to start the op of the mode is default. Loading @@ -137,26 +140,29 @@ public abstract class AppOpsManagerInternal { * @param message The message in the async noted op * @param shouldCollectMessage whether to collect messages * @param skipProxyOperation Whether to skip the proxy portion of the operation * @param proxyAttributionFlags The attribution flags for the proxy. * @param proxiedAttributionFlags The attribution flags for the proxied. * @oaram attributionChainId The id of the attribution chain this operation is a part of. * @param superImpl The super implementation. * @return The app op note result. */ SyncNotedAppOp startProxyOperation(IBinder token, int code, @NonNull AttributionSource attributionSource, boolean startIfModeDefault, boolean shouldCollectAsyncNotedOp, String message, boolean shouldCollectMessage, boolean skipProxyOperation, @NonNull OctFunction<IBinder, Integer, AttributionSource, Boolean, Boolean, String, Boolean, Boolean, SyncNotedAppOp startProxyOperation(int code, @NonNull AttributionSource attributionSource, boolean startIfModeDefault, boolean shouldCollectAsyncNotedOp, String message, boolean shouldCollectMessage, boolean skipProxyOperation, @AttributionFlags int proxyAttributionFlags, @AttributionFlags int proxiedAttributionFlags, int attributionChainId, @NonNull DecFunction<Integer, AttributionSource, Boolean, Boolean, String, Boolean, Boolean, Integer, Integer, Integer, SyncNotedAppOp> superImpl); /** * Allows overriding finish proxy op. * * @param clientId Client state token. * @param code The op code to finish. * @param attributionSource The permission identity of the caller. */ void finishProxyOperation(IBinder clientId, int code, @NonNull AttributionSource attributionSource, @NonNull TriFunction<IBinder, Integer, AttributionSource, Void> superImpl); void finishProxyOperation(int code, @NonNull AttributionSource attributionSource, boolean skipProxyOperation, @NonNull TriFunction<Integer, AttributionSource, Boolean, Void> superImpl); } /** Loading core/java/android/app/ContextImpl.java +1 −7 Original line number Diff line number Diff line Loading @@ -3157,13 +3157,7 @@ class ContextImpl extends Context { // If we want to access protected data on behalf of another app we need to // tell the OS that we opt in to participate in the attribution chain. if (nextAttributionSource != null) { // If an app happened to stub the internal OS for testing the registration method // can return null. In this case we keep the current untrusted attribution source. final AttributionSource registeredAttributionSource = getSystemService( PermissionManager.class).registerAttributionSource(attributionSource); if (registeredAttributionSource != null) { return registeredAttributionSource; } getSystemService(PermissionManager.class).registerAttributionSource(attributionSource); } return attributionSource; } Loading core/java/android/app/SystemServiceRegistry.java +9 −0 Original line number Diff line number Diff line Loading @@ -186,6 +186,7 @@ import android.os.incremental.IIncrementalService; import android.os.incremental.IncrementalManager; import android.os.storage.StorageManager; import android.permission.LegacyPermissionManager; import android.permission.PermissionCheckerManager; import android.permission.PermissionControllerManager; import android.permission.PermissionManager; import android.print.IPrintManager; Loading Loading @@ -1334,6 +1335,14 @@ public final class SystemServiceRegistry { ctx.getMainThreadHandler()); }}); registerService(Context.PERMISSION_CHECKER_SERVICE, PermissionCheckerManager.class, new CachedServiceFetcher<PermissionCheckerManager>() { @Override public PermissionCheckerManager createService(ContextImpl ctx) throws ServiceNotFoundException { return new PermissionCheckerManager(ctx.getOuterContext()); }}); registerService(Context.DYNAMIC_SYSTEM_SERVICE, DynamicSystemManager.class, new CachedServiceFetcher<DynamicSystemManager>() { @Override Loading Loading
core/api/test-current.txt +11 −2 Original line number Diff line number Diff line Loading @@ -201,6 +201,11 @@ package android.app { 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 public static int strOpToOp(@NonNull String); field public static final int ATTRIBUTION_CHAIN_ID_NONE = -1; // 0xffffffff field public static final int ATTRIBUTION_FLAGS_NONE = 0; // 0x0 field public static final int ATTRIBUTION_FLAG_ACCESSOR = 1; // 0x1 field public static final int ATTRIBUTION_FLAG_INTERMEDIARY = 2; // 0x2 field public static final int ATTRIBUTION_FLAG_RECEIVER = 4; // 0x4 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_PASSIVE = 2; // 0x2 Loading Loading @@ -230,6 +235,10 @@ package android.app { method public void offsetBeginAndEndTime(long); } public static interface AppOpsManager.OnOpActiveChangedListener { method public default void onOpActiveChanged(@NonNull String, int, @NonNull String, @Nullable String, boolean, int, int); } public class BroadcastOptions { ctor public BroadcastOptions(@NonNull android.os.Bundle); method public int getMaxManifestReceiverApiLevel(); Loading Loading @@ -669,7 +678,7 @@ package android.content { public final class AttributionSource implements android.os.Parcelable { ctor public AttributionSource(int, @Nullable String, @Nullable String); ctor public AttributionSource(int, @Nullable String, @Nullable String, @Nullable android.content.AttributionSource); ctor public AttributionSource(int, @Nullable String, @Nullable String, @NonNull android.os.IBinder); ctor public AttributionSource(int, @Nullable String, @Nullable String, @Nullable java.util.Set<java.lang.String>, @Nullable android.content.AttributionSource); } Loading Loading @@ -2041,7 +2050,7 @@ package android.permission { public final class PermissionManager { method @NonNull @RequiresPermission(android.Manifest.permission.GET_APP_OPS_STATS) public java.util.List<android.permission.PermGroupUsage> getIndicatorAppOpUsageData(); method @NonNull @RequiresPermission(android.Manifest.permission.GET_APP_OPS_STATS) public java.util.List<android.permission.PermGroupUsage> getIndicatorAppOpUsageData(boolean); method @NonNull public android.content.AttributionSource registerAttributionSource(@NonNull android.content.AttributionSource); method public void registerAttributionSource(@NonNull android.content.AttributionSource); } } Loading
core/java/android/app/AppOpsManager.java +156 −21 Original line number Diff line number Diff line Loading @@ -708,6 +708,62 @@ public class AppOpsManager { } } /** * Attribution chain flag: specifies that this is the accessor. When * an app A accesses the data that is then passed to app B that is then * passed to C, we call app A accessor, app B intermediary, and app C * receiver. If A accesses the data for itself, then it is the accessor * and the receiver. * @hide */ @TestApi public static final int ATTRIBUTION_FLAG_ACCESSOR = 0x1; /** * Attribution chain flag: specifies that this is the intermediary. When * an app A accesses the data that is then passed to app B that is then * passed to C, we call app A accessor, app B intermediary, and app C * receiver. If A accesses the data for itself, then it is the accessor * and the receiver. * @hide */ @TestApi public static final int ATTRIBUTION_FLAG_INTERMEDIARY = 0x2; /** * Attribution chain flag: specifies that this is the receiver. When * an app A accesses the data that is then passed to app B that is then * passed to C, we call app A accessor, app B intermediary, and app C * receiver. If A accesses the data for itself, then it is the accessor * and the receiver. * @hide */ @TestApi public static final int ATTRIBUTION_FLAG_RECEIVER = 0x4; /** * No attribution flags. * @hide */ @TestApi public static final int ATTRIBUTION_FLAGS_NONE = 0x0; /** * No attribution chain id. * @hide */ @TestApi public static final int ATTRIBUTION_CHAIN_ID_NONE = -1; /** @hide */ @Retention(RetentionPolicy.SOURCE) @IntDef(flag = true, prefix = { "FLAG_" }, value = { ATTRIBUTION_FLAG_ACCESSOR, ATTRIBUTION_FLAG_INTERMEDIARY, ATTRIBUTION_FLAG_RECEIVER }) public @interface AttributionFlags {} // These constants are redefined here to work around a metalava limitation/bug where // @IntDef is not able to see @hide symbols when they are hidden via package hiding: // frameworks/base/core/java/com/android/internal/package.html Loading Loading @@ -7063,6 +7119,25 @@ public class AppOpsManager { */ void onOpActiveChanged(@NonNull String op, int uid, @NonNull String packageName, boolean active); /** * Called when the active state of an app-op changes. * * @param op The operation that changed. * @param uid The UID performing the operation. * @param packageName The package performing the operation. * @param attributionTag The operation's attribution tag. * @param active Whether the operation became active or inactive. * @param attributionFlags the attribution flags for this operation. * @param attributionChainId the unique id of the attribution chain this op is a part of. * @hide */ @TestApi default void onOpActiveChanged(@NonNull String op, int uid, @NonNull String packageName, @Nullable String attributionTag, boolean active, @AttributionFlags int attributionFlags, int attributionChainId) { onOpActiveChanged(op, uid, packageName, active); } } /** Loading Loading @@ -7684,14 +7759,17 @@ public class AppOpsManager { } cb = new IAppOpsActiveCallback.Stub() { @Override public void opActiveChanged(int op, int uid, String packageName, boolean active) { public void opActiveChanged(int op, int uid, String packageName, String attributionTag, boolean active, @AttributionFlags int attributionFlags, int attributionChainId) { executor.execute(() -> { if (callback instanceof OnOpActiveChangedInternalListener) { ((OnOpActiveChangedInternalListener) callback).onOpActiveChanged(op, uid, packageName, active); } if (sOpToString[op] != null) { callback.onOpActiveChanged(sOpToString[op], uid, packageName, active); callback.onOpActiveChanged(sOpToString[op], uid, packageName, attributionTag, active, attributionFlags, attributionChainId); } }); } Loading Loading @@ -8169,8 +8247,9 @@ public class AppOpsManager { public int noteProxyOp(int op, @Nullable String proxiedPackageName, int proxiedUid, @Nullable String proxiedAttributionTag, @Nullable String message) { return noteProxyOp(op, new AttributionSource(mContext.getAttributionSource(), new AttributionSource(proxiedUid, proxiedPackageName, proxiedAttributionTag)), message, /*skipProxyOperation*/ false); new AttributionSource(proxiedUid, proxiedPackageName, proxiedAttributionTag, mContext.getAttributionSource().getToken())), message, /*skipProxyOperation*/ false); } /** Loading Loading @@ -8255,8 +8334,8 @@ public class AppOpsManager { int proxiedUid, @Nullable String proxiedAttributionTag, @Nullable String message) { return noteProxyOpNoThrow(strOpToOp(op), new AttributionSource( mContext.getAttributionSource(), new AttributionSource(proxiedUid, proxiedPackageName, proxiedAttributionTag)), message, /*skipProxyOperation*/ false); proxiedPackageName, proxiedAttributionTag, mContext.getAttributionSource() .getToken())), message,/*skipProxyOperation*/ false); } /** Loading Loading @@ -8592,6 +8671,29 @@ public class AppOpsManager { */ public int startOpNoThrow(int op, int uid, @NonNull String packageName, boolean startIfModeDefault, @Nullable String attributionTag, @Nullable String message) { return startOpNoThrow(mContext.getAttributionSource().getToken(), op, uid, packageName, startIfModeDefault, attributionTag, message); } /** * @see #startOpNoThrow(String, int, String, String, String) * * @hide */ public int startOpNoThrow(@NonNull IBinder token, int op, int uid, @NonNull String packageName, boolean startIfModeDefault, @Nullable String attributionTag, @Nullable String message) { return startOpNoThrow(token, op, uid, packageName, startIfModeDefault, attributionTag, message, ATTRIBUTION_FLAGS_NONE, ATTRIBUTION_CHAIN_ID_NONE); } /** * @see #startOpNoThrow(String, int, String, String, String) * * @hide */ public int startOpNoThrow(@NonNull IBinder token, int op, int uid, @NonNull String packageName, boolean startIfModeDefault, @Nullable String attributionTag, @Nullable String message, @AttributionFlags int attributionFlags, int attributionChainId) { try { collectNoteOpCallsForValidation(op); int collectionMode = getNotedOpCollectionMode(uid, packageName, op); Loading @@ -8604,9 +8706,9 @@ public class AppOpsManager { } } SyncNotedAppOp syncOp = mService.startOperation(getClientId(), op, uid, packageName, SyncNotedAppOp syncOp = mService.startOperation(token, op, uid, packageName, attributionTag, startIfModeDefault, collectionMode == COLLECT_ASYNC, message, shouldCollectMessage); shouldCollectMessage, attributionFlags, attributionChainId); if (syncOp.getOpMode() == MODE_ALLOWED) { if (collectionMode == COLLECT_SELF) { Loading Loading @@ -8643,8 +8745,9 @@ public class AppOpsManager { public int startProxyOp(@NonNull String op, int proxiedUid, @NonNull String proxiedPackageName, @Nullable String proxiedAttributionTag, @Nullable String message) { return startProxyOp(op, new AttributionSource(mContext.getAttributionSource(), new AttributionSource(proxiedUid, proxiedPackageName, proxiedAttributionTag)), message, /*skipProxyOperation*/ false); new AttributionSource(proxiedUid, proxiedPackageName, proxiedAttributionTag, mContext.getAttributionSource().getToken())), message, /*skipProxyOperation*/ false); } /** Loading Loading @@ -8690,7 +8793,8 @@ public class AppOpsManager { @Nullable String message) { return startProxyOpNoThrow(AppOpsManager.strOpToOp(op), new AttributionSource( mContext.getAttributionSource(), new AttributionSource(proxiedUid, proxiedPackageName, proxiedAttributionTag)), message, proxiedPackageName, proxiedAttributionTag, mContext.getAttributionSource().getToken())), message, /*skipProxyOperation*/ false); } Loading @@ -8705,6 +8809,23 @@ public class AppOpsManager { */ public int startProxyOpNoThrow(int op, @NonNull AttributionSource attributionSource, @Nullable String message, boolean skipProxyOperation) { return startProxyOpNoThrow(op, attributionSource, message, skipProxyOperation, ATTRIBUTION_FLAGS_NONE, ATTRIBUTION_FLAGS_NONE, ATTRIBUTION_CHAIN_ID_NONE); } /** * Like {@link #startProxyOp(String, AttributionSource, String)} but instead * of throwing a {@link SecurityException} it returns {@link #MODE_ERRORED} and * the checks is for the attribution chain specified by the {@link AttributionSource}. * * @see #startProxyOp(String, AttributionSource, String) * * @hide */ public int startProxyOpNoThrow(int op, @NonNull AttributionSource attributionSource, @Nullable String message, boolean skipProxyOperation, @AttributionFlags int proxyAttributionFlags, @AttributionFlags int proxiedAttributionFlags, int attributionChainId) { try { collectNoteOpCallsForValidation(op); int collectionMode = getNotedOpCollectionMode( Loading @@ -8719,9 +8840,10 @@ public class AppOpsManager { } } SyncNotedAppOp syncOp = mService.startProxyOperation(getClientId(), op, SyncNotedAppOp syncOp = mService.startProxyOperation(op, attributionSource, false, collectionMode == COLLECT_ASYNC, message, shouldCollectMessage, skipProxyOperation); shouldCollectMessage, skipProxyOperation, proxyAttributionFlags, proxiedAttributionFlags, attributionChainId); if (syncOp.getOpMode() == MODE_ALLOWED) { if (collectionMode == COLLECT_SELF) { Loading Loading @@ -8785,8 +8907,18 @@ public class AppOpsManager { */ public void finishOp(int op, int uid, @NonNull String packageName, @Nullable String attributionTag) { finishOp(mContext.getAttributionSource().getToken(), op, uid, packageName, attributionTag); } /** * @see #finishOp(String, int, String, String) * * @hide */ public void finishOp(IBinder token, int op, int uid, @NonNull String packageName, @Nullable String attributionTag) { try { mService.finishOperation(getClientId(), op, uid, packageName, attributionTag); mService.finishOperation(token, op, uid, packageName, attributionTag); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } Loading @@ -8807,23 +8939,26 @@ public class AppOpsManager { public void finishProxyOp(@NonNull String op, int proxiedUid, @NonNull String proxiedPackageName, @Nullable String proxiedAttributionTag) { finishProxyOp(op, new AttributionSource(mContext.getAttributionSource(), new AttributionSource(proxiedUid, proxiedPackageName, proxiedAttributionTag))); new AttributionSource(proxiedUid, proxiedPackageName, proxiedAttributionTag, mContext.getAttributionSource().getToken())), /*skipProxyOperation*/ false); } /** * Report that an application is no longer performing an operation that had previously * been started with {@link #startProxyOp(String, AttributionSource, 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. * been started with {@link #startProxyOp(String, AttributionSource, String, boolean)}. 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 attributionSource The permission identity for which to finish * @param skipProxyOperation Whether to skip the proxy finish. * * @hide */ public void finishProxyOp(@NonNull String op, @NonNull AttributionSource attributionSource) { public void finishProxyOp(@NonNull String op, @NonNull AttributionSource attributionSource, boolean skipProxyOperation) { try { mService.finishProxyOperation(getClientId(), strOpToOp(op), attributionSource); mService.finishProxyOperation(strOpToOp(op), attributionSource, skipProxyOperation); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } Loading
core/java/android/app/AppOpsManagerInternal.java +23 −17 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ package android.app; import android.app.AppOpsManager.AttributionFlags; import android.annotation.NonNull; import android.annotation.Nullable; import android.content.AttributionSource; Loading @@ -24,13 +25,13 @@ import android.util.SparseArray; import android.util.SparseIntArray; import com.android.internal.app.IAppOpsCallback; import com.android.internal.util.function.DecFunction; import com.android.internal.util.function.HeptFunction; import com.android.internal.util.function.HexFunction; import com.android.internal.util.function.NonaFunction; import com.android.internal.util.function.OctFunction; import com.android.internal.util.function.QuadFunction; import com.android.internal.util.function.QuintFunction; import com.android.internal.util.function.TriFunction; import com.android.internal.util.function.UndecFunction; /** * App ops service local interface. Loading @@ -52,8 +53,8 @@ public abstract class AppOpsManagerInternal { * @return The app op check result. */ int checkOperation(int code, int uid, String packageName, @Nullable String attributionTag, boolean raw, QuintFunction<Integer, Integer, String, String, Boolean, Integer> superImpl); boolean raw, QuintFunction<Integer, Integer, String, String, Boolean, Integer> superImpl); /** * Allows overriding check audio operation behavior. Loading Loading @@ -116,20 +117,22 @@ public abstract class AppOpsManagerInternal { * @param shouldCollectAsyncNotedOp If an {@link AsyncNotedAppOp} should be collected * @param message The message in the async noted op * @param shouldCollectMessage whether to collect messages * @param attributionFlags the attribution flags for this operation. * @param attributionChainId the unique id of the attribution chain this op is a part of. * @param superImpl The super implementation. * @return The app op note result. */ SyncNotedAppOp startOperation(IBinder token, int code, int uid, @Nullable String packageName, @Nullable String attributionTag, boolean startIfModeDefault, boolean shouldCollectAsyncNotedOp, @Nullable String message, boolean shouldCollectMessage, @NonNull NonaFunction< IBinder, Integer, Integer, String, String, Boolean, Boolean, String, Boolean, SyncNotedAppOp> superImpl); @Nullable String message, boolean shouldCollectMessage, @AttributionFlags int attributionFlags, int attributionChainId, @NonNull UndecFunction<IBinder, Integer, Integer, String, String, Boolean, Boolean, String, Boolean, Integer, Integer, SyncNotedAppOp> superImpl); /** * Allows overriding start proxy operation behavior. * * @param token The client state. * @param code The op code to start. * @param attributionSource The permission identity of the caller. * @param startIfModeDefault Whether to start the op of the mode is default. Loading @@ -137,26 +140,29 @@ public abstract class AppOpsManagerInternal { * @param message The message in the async noted op * @param shouldCollectMessage whether to collect messages * @param skipProxyOperation Whether to skip the proxy portion of the operation * @param proxyAttributionFlags The attribution flags for the proxy. * @param proxiedAttributionFlags The attribution flags for the proxied. * @oaram attributionChainId The id of the attribution chain this operation is a part of. * @param superImpl The super implementation. * @return The app op note result. */ SyncNotedAppOp startProxyOperation(IBinder token, int code, @NonNull AttributionSource attributionSource, boolean startIfModeDefault, boolean shouldCollectAsyncNotedOp, String message, boolean shouldCollectMessage, boolean skipProxyOperation, @NonNull OctFunction<IBinder, Integer, AttributionSource, Boolean, Boolean, String, Boolean, Boolean, SyncNotedAppOp startProxyOperation(int code, @NonNull AttributionSource attributionSource, boolean startIfModeDefault, boolean shouldCollectAsyncNotedOp, String message, boolean shouldCollectMessage, boolean skipProxyOperation, @AttributionFlags int proxyAttributionFlags, @AttributionFlags int proxiedAttributionFlags, int attributionChainId, @NonNull DecFunction<Integer, AttributionSource, Boolean, Boolean, String, Boolean, Boolean, Integer, Integer, Integer, SyncNotedAppOp> superImpl); /** * Allows overriding finish proxy op. * * @param clientId Client state token. * @param code The op code to finish. * @param attributionSource The permission identity of the caller. */ void finishProxyOperation(IBinder clientId, int code, @NonNull AttributionSource attributionSource, @NonNull TriFunction<IBinder, Integer, AttributionSource, Void> superImpl); void finishProxyOperation(int code, @NonNull AttributionSource attributionSource, boolean skipProxyOperation, @NonNull TriFunction<Integer, AttributionSource, Boolean, Void> superImpl); } /** Loading
core/java/android/app/ContextImpl.java +1 −7 Original line number Diff line number Diff line Loading @@ -3157,13 +3157,7 @@ class ContextImpl extends Context { // If we want to access protected data on behalf of another app we need to // tell the OS that we opt in to participate in the attribution chain. if (nextAttributionSource != null) { // If an app happened to stub the internal OS for testing the registration method // can return null. In this case we keep the current untrusted attribution source. final AttributionSource registeredAttributionSource = getSystemService( PermissionManager.class).registerAttributionSource(attributionSource); if (registeredAttributionSource != null) { return registeredAttributionSource; } getSystemService(PermissionManager.class).registerAttributionSource(attributionSource); } return attributionSource; } Loading
core/java/android/app/SystemServiceRegistry.java +9 −0 Original line number Diff line number Diff line Loading @@ -186,6 +186,7 @@ import android.os.incremental.IIncrementalService; import android.os.incremental.IncrementalManager; import android.os.storage.StorageManager; import android.permission.LegacyPermissionManager; import android.permission.PermissionCheckerManager; import android.permission.PermissionControllerManager; import android.permission.PermissionManager; import android.print.IPrintManager; Loading Loading @@ -1334,6 +1335,14 @@ public final class SystemServiceRegistry { ctx.getMainThreadHandler()); }}); registerService(Context.PERMISSION_CHECKER_SERVICE, PermissionCheckerManager.class, new CachedServiceFetcher<PermissionCheckerManager>() { @Override public PermissionCheckerManager createService(ContextImpl ctx) throws ServiceNotFoundException { return new PermissionCheckerManager(ctx.getOuterContext()); }}); registerService(Context.DYNAMIC_SYSTEM_SERVICE, DynamicSystemManager.class, new CachedServiceFetcher<DynamicSystemManager>() { @Override Loading