Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0f79c4da authored by Svetoslav Ganov's avatar Svetoslav Ganov Committed by Automerger Merge Worker
Browse files

Merge "Switch media fw permissions checks to AttributionSource" into sc-dev am: 1028eb2f

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/14664152

Change-Id: I7f3c14e427b1ef0cb0232c0f0194bfbaa23b7706
parents fb452645 1028eb2f
Loading
Loading
Loading
Loading
+11 −2
Original line number Diff line number Diff line
@@ -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
@@ -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();
@@ -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);
  }

@@ -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);
  }

}
+156 −21
Original line number Diff line number Diff line
@@ -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
@@ -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);
        }
    }

    /**
@@ -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);
                        }
                    });
                }
@@ -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);
    }

    /**
@@ -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);
    }

    /**
@@ -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);
@@ -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) {
@@ -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);
    }

    /**
@@ -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);
    }

@@ -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(
@@ -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) {
@@ -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();
        }
@@ -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();
        }
+23 −17
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package android.app;

import android.app.AppOpsManager.AttributionFlags;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.AttributionSource;
@@ -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.
@@ -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.
@@ -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.
@@ -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);
    }

    /**
+1 −7
Original line number Diff line number Diff line
@@ -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;
    }
+9 −0
Original line number Diff line number Diff line
@@ -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;
@@ -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