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

Commit 6595eabb authored by Jeff Sharkey's avatar Jeff Sharkey Committed by Android (Google) Code Review
Browse files

Merge "Support for a Context to "renounce" permissions." into sc-dev

parents fe232309 ba2974c8
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -10387,6 +10387,7 @@ package android.content {
    method public abstract android.content.pm.PackageManager getPackageManager();
    method public abstract String getPackageName();
    method public abstract String getPackageResourcePath();
    method @Nullable public android.content.ContextParams getParams();
    method public abstract android.content.res.Resources getResources();
    method public abstract android.content.SharedPreferences getSharedPreferences(String, int);
    method @NonNull public final String getString(@StringRes int);
+9 −0
Original line number Diff line number Diff line
@@ -228,6 +228,7 @@ package android {
    field public static final String REMOTE_DISPLAY_PROVIDER = "android.permission.REMOTE_DISPLAY_PROVIDER";
    field public static final String REMOVE_DRM_CERTIFICATES = "android.permission.REMOVE_DRM_CERTIFICATES";
    field public static final String REMOVE_TASKS = "android.permission.REMOVE_TASKS";
    field public static final String RENOUNCE_PERMISSIONS = "android.permission.RENOUNCE_PERMISSIONS";
    field public static final String REQUEST_NETWORK_SCORES = "android.permission.REQUEST_NETWORK_SCORES";
    field public static final String REQUEST_NOTIFICATION_ASSISTANT_SERVICE = "android.permission.REQUEST_NOTIFICATION_ASSISTANT_SERVICE";
    field public static final String RESET_PASSWORD = "android.permission.RESET_PASSWORD";
@@ -2184,6 +2185,14 @@ package android.content {
    field public static final String WIFI_SCANNING_SERVICE = "wifiscanner";
  }
  public final class ContextParams {
    method @Nullable @RequiresPermission(android.Manifest.permission.RENOUNCE_PERMISSIONS) public java.util.Set<java.lang.String> getRenouncedPermissions();
  }
  public static final class ContextParams.Builder {
    method @NonNull @RequiresPermission(android.Manifest.permission.RENOUNCE_PERMISSIONS) public android.content.ContextParams.Builder setRenouncedPermissions(@NonNull java.util.Set<java.lang.String>);
  }
  public class ContextWrapper extends android.content.Context {
    method public android.content.Context createCredentialProtectedStorageContext();
    method @Nullable public java.io.File getPreloadsFileCache();
+46 −27
Original line number Diff line number Diff line
@@ -24,7 +24,6 @@ import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.ContextParams;
import android.content.AutofillOptions;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
@@ -32,6 +31,7 @@ import android.content.ContentCaptureOptions;
import android.content.ContentProvider;
import android.content.ContentResolver;
import android.content.Context;
import android.content.ContextParams;
import android.content.ContextWrapper;
import android.content.IContentProvider;
import android.content.IIntentReceiver;
@@ -221,8 +221,7 @@ class ContextImpl extends Context {
    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
    private final String mOpPackageName;

    /** Attribution tag of this context */
    private final @Nullable String mAttributionTag;
    private final @NonNull ContextParams mParams;

    private final @NonNull ResourcesManager mResourcesManager;
    @UnsupportedAppUsage
@@ -470,7 +469,12 @@ class ContextImpl extends Context {
    /** @hide */
    @Override
    public @Nullable String getAttributionTag() {
        return mAttributionTag;
        return mParams.getAttributionTag();
    }

    @Override
    public @Nullable ContextParams getParams() {
        return mParams;
    }

    @Override
@@ -2047,6 +2051,11 @@ class ContextImpl extends Context {
        if (permission == null) {
            throw new IllegalArgumentException("permission is null");
        }
        if (mParams.isRenouncedPermission(permission)
                && pid == android.os.Process.myPid() && uid == android.os.Process.myUid()) {
            Log.v(TAG, "Treating renounced permission " + permission + " as denied");
            return PERMISSION_DENIED;
        }
        return PermissionManager.checkPermission(permission, pid, uid);
    }

@@ -2056,6 +2065,11 @@ class ContextImpl extends Context {
        if (permission == null) {
            throw new IllegalArgumentException("permission is null");
        }
        if (mParams.isRenouncedPermission(permission)
                && pid == android.os.Process.myPid() && uid == android.os.Process.myUid()) {
            Log.v(TAG, "Treating renounced permission " + permission + " as denied");
            return PERMISSION_DENIED;
        }

        try {
            return ActivityManager.getService().checkPermissionWithToken(
@@ -2093,6 +2107,10 @@ class ContextImpl extends Context {
        if (permission == null) {
            throw new IllegalArgumentException("permission is null");
        }
        if (mParams.isRenouncedPermission(permission)) {
            Log.v(TAG, "Treating renounced permission " + permission + " as denied");
            return PERMISSION_DENIED;
        }

        return checkPermission(permission, Process.myPid(), Process.myUid());
    }
@@ -2393,8 +2411,9 @@ class ContextImpl extends Context {
        LoadedApk pi = mMainThread.getPackageInfo(application, mResources.getCompatibilityInfo(),
                flags | CONTEXT_REGISTER_PACKAGE);
        if (pi != null) {
            ContextImpl c = new ContextImpl(this, mMainThread, pi, null, null, mToken,
                    new UserHandle(UserHandle.getUserId(application.uid)), flags, null, null);
            ContextImpl c = new ContextImpl(this, mMainThread, pi, ContextParams.EMPTY, null,
                    mToken, new UserHandle(UserHandle.getUserId(application.uid)),
                    flags, null, null);

            final int displayId = getDisplayId();
            final Integer overrideDisplayId = mForceDisplayOverrideInResources
@@ -2423,14 +2442,14 @@ class ContextImpl extends Context {
        if (packageName.equals("system") || packageName.equals("android")) {
            // The system resources are loaded in every application, so we can safely copy
            // the context without reloading Resources.
            return new ContextImpl(this, mMainThread, mPackageInfo, mAttributionTag, null,
            return new ContextImpl(this, mMainThread, mPackageInfo, mParams, null,
                    mToken, user, flags, null, null);
        }

        LoadedApk pi = mMainThread.getPackageInfo(packageName, mResources.getCompatibilityInfo(),
                flags | CONTEXT_REGISTER_PACKAGE, user.getIdentifier());
        if (pi != null) {
            ContextImpl c = new ContextImpl(this, mMainThread, pi, mAttributionTag, null,
            ContextImpl c = new ContextImpl(this, mMainThread, pi, mParams, null,
                    mToken, user, flags, null, null);

            final int displayId = getDisplayId();
@@ -2469,7 +2488,7 @@ class ContextImpl extends Context {
        final String[] paths = mPackageInfo.getSplitPaths(splitName);

        final ContextImpl context = new ContextImpl(this, mMainThread, mPackageInfo,
                mAttributionTag, splitName, mToken, mUser, mFlags, classLoader, null);
                mParams, splitName, mToken, mUser, mFlags, classLoader, null);

        context.setResources(ResourcesManager.getInstance().getResources(
                mToken,
@@ -2502,7 +2521,7 @@ class ContextImpl extends Context {
            overrideConfiguration = displayAdjustedConfig;
        }

        ContextImpl context = new ContextImpl(this, mMainThread, mPackageInfo, mAttributionTag,
        ContextImpl context = new ContextImpl(this, mMainThread, mPackageInfo, mParams,
                mSplitName, mToken, mUser, mFlags, mClassLoader, null);

        final int displayId = getDisplayId();
@@ -2520,7 +2539,7 @@ class ContextImpl extends Context {
            throw new IllegalArgumentException("display must not be null");
        }

        ContextImpl context = new ContextImpl(this, mMainThread, mPackageInfo, mAttributionTag,
        ContextImpl context = new ContextImpl(this, mMainThread, mPackageInfo, mParams,
                mSplitName, mToken, mUser, mFlags, mClassLoader, null);

        final int displayId = display.getDisplayId();
@@ -2578,7 +2597,7 @@ class ContextImpl extends Context {


    ContextImpl createBaseWindowContext(IBinder token, Display display) {
        ContextImpl context = new ContextImpl(this, mMainThread, mPackageInfo, mAttributionTag,
        ContextImpl context = new ContextImpl(this, mMainThread, mPackageInfo, mParams,
                mSplitName, token, mUser, mFlags, mClassLoader, null);
        // Window contexts receive configurations directly from the server and as such do not
        // need to override their display in ResourcesManager.
@@ -2609,21 +2628,21 @@ class ContextImpl extends Context {

    @NonNull
    @Override
    public Context createContext(@NonNull ContextParams contextParams) {
        return this;
    public Context createContext(@NonNull ContextParams params) {
        return new ContextImpl(this, mMainThread, mPackageInfo, params, mSplitName,
                mToken, mUser, mFlags, mClassLoader, null);
    }

    @Override
    public @NonNull Context createAttributionContext(@Nullable String attributionTag) {
        return new ContextImpl(this, mMainThread, mPackageInfo, attributionTag, mSplitName,
                mToken, mUser, mFlags, mClassLoader, null);
        return createContext(new ContextParams.Builder().setAttributionTag(attributionTag).build());
    }

    @Override
    public Context createDeviceProtectedStorageContext() {
        final int flags = (mFlags & ~Context.CONTEXT_CREDENTIAL_PROTECTED_STORAGE)
                | Context.CONTEXT_DEVICE_PROTECTED_STORAGE;
        return new ContextImpl(this, mMainThread, mPackageInfo, mAttributionTag, mSplitName,
        return new ContextImpl(this, mMainThread, mPackageInfo, mParams, mSplitName,
                mToken, mUser, flags, mClassLoader, null);
    }

@@ -2631,7 +2650,7 @@ class ContextImpl extends Context {
    public Context createCredentialProtectedStorageContext() {
        final int flags = (mFlags & ~Context.CONTEXT_DEVICE_PROTECTED_STORAGE)
                | Context.CONTEXT_CREDENTIAL_PROTECTED_STORAGE;
        return new ContextImpl(this, mMainThread, mPackageInfo, mAttributionTag, mSplitName,
        return new ContextImpl(this, mMainThread, mPackageInfo, mParams, mSplitName,
                mToken, mUser, flags, mClassLoader, null);
    }

@@ -2805,8 +2824,8 @@ class ContextImpl extends Context {
    @UnsupportedAppUsage
    static ContextImpl createSystemContext(ActivityThread mainThread) {
        LoadedApk packageInfo = new LoadedApk(mainThread);
        ContextImpl context = new ContextImpl(null, mainThread, packageInfo, null, null, null, null,
                0, null, null);
        ContextImpl context = new ContextImpl(null, mainThread, packageInfo,
                ContextParams.EMPTY, null, null, null, 0, null, null);
        context.setResources(packageInfo.getResources());
        context.mResources.updateConfiguration(context.mResourcesManager.getConfiguration(),
                context.mResourcesManager.getDisplayMetrics());
@@ -2823,8 +2842,8 @@ class ContextImpl extends Context {
     */
    static ContextImpl createSystemUiContext(ContextImpl systemContext, int displayId) {
        final LoadedApk packageInfo = systemContext.mPackageInfo;
        ContextImpl context = new ContextImpl(null, systemContext.mMainThread, packageInfo, null,
                null, null, null, 0, null, null);
        ContextImpl context = new ContextImpl(null, systemContext.mMainThread, packageInfo,
                ContextParams.EMPTY, null, null, null, 0, null, null);
        context.setResources(createResources(null, packageInfo, null, displayId, null,
                packageInfo.getCompatibilityInfo(), null));
        context.updateDisplay(displayId);
@@ -2848,8 +2867,8 @@ class ContextImpl extends Context {
    static ContextImpl createAppContext(ActivityThread mainThread, LoadedApk packageInfo,
            String opPackageName) {
        if (packageInfo == null) throw new IllegalArgumentException("packageInfo");
        ContextImpl context = new ContextImpl(null, mainThread, packageInfo, null, null, null, null,
                0, null, opPackageName);
        ContextImpl context = new ContextImpl(null, mainThread, packageInfo,
                ContextParams.EMPTY, null, null, null, 0, null, opPackageName);
        context.setResources(packageInfo.getResources());
        context.mContextType = isSystemOrSystemUI(context) ? CONTEXT_TYPE_SYSTEM_OR_SYSTEM_UI
                : CONTEXT_TYPE_NON_UI;
@@ -2878,7 +2897,7 @@ class ContextImpl extends Context {
            }
        }

        ContextImpl context = new ContextImpl(null, mainThread, packageInfo, null,
        ContextImpl context = new ContextImpl(null, mainThread, packageInfo, ContextParams.EMPTY,
                activityInfo.splitName, activityToken, null, 0, classLoader, null);
        context.mContextType = CONTEXT_TYPE_ACTIVITY;

@@ -2911,7 +2930,7 @@ class ContextImpl extends Context {
    }

    private ContextImpl(@Nullable ContextImpl container, @NonNull ActivityThread mainThread,
            @NonNull LoadedApk packageInfo, @Nullable String attributionTag,
            @NonNull LoadedApk packageInfo, @NonNull ContextParams params,
            @Nullable String splitName, @Nullable IBinder token, @Nullable UserHandle user,
            int flags, @Nullable ClassLoader classLoader, @Nullable String overrideOpPackageName) {
        mOuterContext = this;
@@ -2966,7 +2985,7 @@ class ContextImpl extends Context {
        }

        mOpPackageName = overrideOpPackageName != null ? overrideOpPackageName : opPackageName;
        mAttributionTag = attributionTag;
        mParams = Objects.requireNonNull(params);
        mContentResolver = new ApplicationContentResolver(this, mainThread);
    }

+8 −0
Original line number Diff line number Diff line
@@ -888,6 +888,14 @@ public abstract class Context {
        return getAttributionTag();
    }

    /**
     * Return the set of parameters which this Context was created with, if it
     * was created via {@link #createContext(ContextParams)}.
     */
    public @Nullable ContextParams getParams() {
        return null;
    }

    /** Return the full application info for this context's package. */
    public abstract ApplicationInfo getApplicationInfo();

+74 −8
Original line number Diff line number Diff line
@@ -18,6 +18,13 @@ package android.content;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SuppressLint;
import android.annotation.SystemApi;

import java.util.Collections;
import java.util.Objects;
import java.util.Set;

/**
 * This class represents rules around how a context being created via
@@ -48,9 +55,19 @@ import android.annotation.Nullable;
 * @see Context#createContext(ContextParams)
 */
public final class ContextParams {
    private final String mAttributionTag;
    private final String mReceiverPackage;
    private final String mReceiverAttributionTag;
    private final Set<String> mRenouncedPermissions;

    /** {@hide} */
    public static final ContextParams EMPTY = new ContextParams.Builder().build();

    private ContextParams() {
        /* hide ctor */
    private ContextParams(@NonNull ContextParams.Builder builder) {
        mAttributionTag = builder.mAttributionTag;
        mReceiverPackage = builder.mReceiverPackage;
        mReceiverAttributionTag = builder.mReceiverAttributionTag;
        mRenouncedPermissions = builder.mRenouncedPermissions;
    }

    /**
@@ -58,7 +75,7 @@ public final class ContextParams {
     */
    @Nullable
    public String getAttributionTag() {
        return null;
        return mAttributionTag;
    }

    /**
@@ -66,7 +83,7 @@ public final class ContextParams {
     */
    @Nullable
    public String getReceiverPackage() {
        return null;
        return mReceiverPackage;
    }

    /**
@@ -74,13 +91,33 @@ public final class ContextParams {
     */
    @Nullable
    public String getReceiverAttributionTag() {
        return null;
        return mReceiverAttributionTag;
    }

    /**
     * @return The set of permissions to treat as renounced.
     * @hide
     */
    @SystemApi
    @SuppressLint("NullableCollection")
    @RequiresPermission(android.Manifest.permission.RENOUNCE_PERMISSIONS)
    public @Nullable Set<String> getRenouncedPermissions() {
        return mRenouncedPermissions;
    }

    /** @hide */
    public boolean isRenouncedPermission(@NonNull String permission) {
        return mRenouncedPermissions != null && mRenouncedPermissions.contains(permission);
    }

    /**
     * Builder for creating a {@link ContextParams}.
     */
    public static final class Builder {
        private String mAttributionTag;
        private String mReceiverPackage;
        private String mReceiverAttributionTag;
        private Set<String> mRenouncedPermissions;

        /**
         * Sets an attribution tag against which to track permission accesses.
@@ -90,6 +127,7 @@ public final class ContextParams {
         */
        @NonNull
        public Builder setAttributionTag(@NonNull String attributionTag) {
            mAttributionTag = Objects.requireNonNull(attributionTag);
            return this;
        }

@@ -104,18 +142,46 @@ public final class ContextParams {
        @NonNull
        public Builder setReceiverPackage(@NonNull String packageName,
                @Nullable String attributionTag) {
            mReceiverPackage = Objects.requireNonNull(packageName);
            mReceiverAttributionTag = attributionTag;
            return this;
        }

        /**
         * Sets permissions which have been voluntarily "renounced" by the
         * calling app.
         * <p>
         * Interactions performed through the created Context will ideally be
         * treated as if these "renounced" permissions have not actually been
         * granted to the app, regardless of their actual grant status.
         * <p>
         * This is designed for use by separate logical components within an app
         * which have no intention of interacting with data or services that are
         * protected by the renounced permissions.
         * <p>
         * Note that only {@link PermissionInfo#PROTECTION_DANGEROUS}
         * permissions are supported by this mechanism.
         *
         * @param renouncedPermissions The set of permissions to treat as
         *            renounced.
         * @return This builder.
         * @hide
         */
        @SystemApi
        @RequiresPermission(android.Manifest.permission.RENOUNCE_PERMISSIONS)
        public @NonNull Builder setRenouncedPermissions(@NonNull Set<String> renouncedPermissions) {
            mRenouncedPermissions = Collections.unmodifiableSet(renouncedPermissions);
            return this;
        }

        /**
         * Creates a new instance. You need to either specify an attribution tag
         * or a receiver package or both.
         * Creates a new instance.
         *
         * @return The new instance.
         */
        @NonNull
        public ContextParams build() {
            return new ContextParams();
            return new ContextParams(this);
        }
    }
}
Loading