Merge "Support for a Context to "renounce" permissions." into sc-dev
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
private ContextParams() {
|
||||
/* hide ctor */
|
||||
/** {@hide} */
|
||||
public static final ContextParams EMPTY = new ContextParams.Builder().build();
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new instance. You need to either specify an attribution tag
|
||||
* or a receiver package or both.
|
||||
* 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.
|
||||
*
|
||||
* @return The new instance.
|
||||
*/
|
||||
@NonNull
|
||||
public ContextParams build() {
|
||||
return new ContextParams();
|
||||
return new ContextParams(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -171,6 +171,11 @@ public class ContextWrapper extends Context {
|
||||
return mBase.getAttributionTag();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable ContextParams getParams() {
|
||||
return mBase.getParams();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ApplicationInfo getApplicationInfo() {
|
||||
return mBase.getApplicationInfo();
|
||||
@@ -1044,6 +1049,12 @@ public class ContextWrapper extends Context {
|
||||
return mBase.createWindowContext(display, type, options);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NonNull
|
||||
public Context createContext(@NonNull ContextParams contextParams) {
|
||||
return mBase.createContext(contextParams);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull Context createAttributionContext(@Nullable String attributionTag) {
|
||||
return mBase.createAttributionContext(attributionTag);
|
||||
|
||||
@@ -5561,6 +5561,11 @@
|
||||
<permission android:name="android.permission.READ_PEOPLE_DATA"
|
||||
android:protectionLevel="signature|appPredictor|recents"/>
|
||||
|
||||
<!-- @hide @SystemApi Allows a logical component within an application to
|
||||
temporarily renounce a set of otherwise granted permissions. -->
|
||||
<permission android:name="android.permission.RENOUNCE_PERMISSIONS"
|
||||
android:protectionLevel="signature|privileged" />
|
||||
|
||||
<!-- Attribution for Geofencing service. -->
|
||||
<attribution android:tag="GeofencingService" android:label="@string/geofencing_service"/>
|
||||
<!-- Attribution for Country Detector. -->
|
||||
|
||||
Reference in New Issue
Block a user