1 /* 2 * Copyright (C) 2021 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.content; 18 19 import static android.permission.flags.Flags.FLAG_SHOULD_REGISTER_ATTRIBUTION_SOURCE; 20 21 import android.Manifest; 22 import android.annotation.FlaggedApi; 23 import android.annotation.NonNull; 24 import android.annotation.Nullable; 25 import android.annotation.RequiresPermission; 26 import android.annotation.SystemApi; 27 import android.app.ActivityThread; 28 import android.content.pm.PackageManager; 29 30 import java.util.Collections; 31 import java.util.Objects; 32 import java.util.Set; 33 34 /** 35 * This class represents rules around how a context being created via 36 * {@link Context#createContext} should behave. 37 * 38 * <p>One of the dimensions to customize is how permissions should behave. 39 * For example, you can specify how permission accesses from a context should 40 * be attributed in the platform's permission tracking system. 41 * 42 * <p>The two main types of attribution are: against an attribution tag which 43 * is an arbitrary string your app specifies for the purposes of tracking permission 44 * accesses from a given portion of your app; against another package and optionally 45 * its attribution tag if you are accessing the data on behalf of another app and 46 * you will be passing that data to this app, recursively. Both attributions are 47 * not mutually exclusive. 48 * 49 * @see Context#createContext(ContextParams) 50 * @see AttributionSource 51 */ 52 public final class ContextParams { 53 private final @Nullable String mAttributionTag; 54 private final @Nullable AttributionSource mNext; 55 private final @NonNull Set<String> mRenouncedPermissions; 56 private final boolean mShouldRegisterAttributionSource; 57 58 /** {@hide} */ 59 public static final ContextParams EMPTY = new ContextParams.Builder().build(); 60 ContextParams(@ullable String attributionTag, @Nullable AttributionSource next, @Nullable Set<String> renouncedPermissions, boolean shouldRegister)61 private ContextParams(@Nullable String attributionTag, 62 @Nullable AttributionSource next, 63 @Nullable Set<String> renouncedPermissions, 64 boolean shouldRegister) { 65 mAttributionTag = attributionTag; 66 mNext = next; 67 mRenouncedPermissions = (renouncedPermissions != null) 68 ? renouncedPermissions : Collections.emptySet(); 69 mShouldRegisterAttributionSource = shouldRegister; 70 } 71 72 /** 73 * @return The attribution tag. 74 */ 75 @Nullable getAttributionTag()76 public String getAttributionTag() { 77 return mAttributionTag; 78 } 79 80 /** 81 * @return The set of permissions to treat as renounced. 82 * @hide 83 */ 84 @SystemApi 85 @RequiresPermission(android.Manifest.permission.RENOUNCE_PERMISSIONS) getRenouncedPermissions()86 public @NonNull Set<String> getRenouncedPermissions() { 87 return mRenouncedPermissions; 88 } 89 90 /** @hide */ isRenouncedPermission(@onNull String permission)91 public boolean isRenouncedPermission(@NonNull String permission) { 92 return mRenouncedPermissions.contains(permission); 93 } 94 95 /** 96 * @return The receiving attribution source. 97 */ 98 @Nullable getNextAttributionSource()99 public AttributionSource getNextAttributionSource() { 100 return mNext; 101 } 102 103 /** 104 * @return Whether the attribution source associated with the Context being created should be 105 * registered. 106 */ 107 @NonNull 108 @FlaggedApi(FLAG_SHOULD_REGISTER_ATTRIBUTION_SOURCE) shouldRegisterAttributionSource()109 public boolean shouldRegisterAttributionSource() { 110 return mShouldRegisterAttributionSource; 111 } 112 113 /** 114 * Builder for creating a {@link ContextParams}. 115 */ 116 public static final class Builder { 117 private @Nullable String mAttributionTag; 118 private @NonNull Set<String> mRenouncedPermissions = Collections.emptySet(); 119 private @Nullable AttributionSource mNext; 120 private boolean mShouldRegisterAttributionSource; 121 122 /** 123 * Create a new builder. 124 * <p> 125 * This is valuable when you are interested in having explicit control 126 * over every sub-parameter, and don't want to inherit any values from 127 * an existing Context. 128 * <p> 129 * Developers should strongly consider using 130 * {@link #Builder(ContextParams)} instead of this constructor, since 131 * that will will automatically inherit any new sub-parameters added in 132 * future platform releases. 133 */ Builder()134 public Builder() { 135 } 136 137 /** 138 * Create a new builder that inherits all sub-parameters by default. 139 * <p> 140 * This is valuable when you are only interested in overriding specific 141 * sub-parameters, and want to preserve all other parameters. Setting a 142 * specific sub-parameter on the returned builder will override any 143 * inherited value. 144 */ Builder(@onNull ContextParams params)145 public Builder(@NonNull ContextParams params) { 146 Objects.requireNonNull(params); 147 mAttributionTag = params.mAttributionTag; 148 mRenouncedPermissions = params.mRenouncedPermissions; 149 mNext = params.mNext; 150 } 151 152 /** 153 * Sets an attribution tag against which to track permission accesses. 154 * 155 * @param attributionTag The attribution tag. 156 * @return This builder. 157 */ 158 @NonNull setAttributionTag(@ullable String attributionTag)159 public Builder setAttributionTag(@Nullable String attributionTag) { 160 mAttributionTag = attributionTag; 161 return this; 162 } 163 164 /** 165 * Sets the attribution source for the app on whose behalf you are doing the work. 166 * 167 * @param next The permission identity of the receiving app. 168 * @return This builder. 169 * 170 * @see AttributionSource 171 */ 172 @NonNull setNextAttributionSource(@ullable AttributionSource next)173 public Builder setNextAttributionSource(@Nullable AttributionSource next) { 174 mNext = next; 175 return this; 176 } 177 178 /** 179 * Sets whether the attribution source associated with the context created from these params 180 * should be registered. 181 * 182 * @param shouldRegister Whether the attribution source associated with the Context being 183 * created should be registered. 184 */ 185 @NonNull 186 @FlaggedApi(FLAG_SHOULD_REGISTER_ATTRIBUTION_SOURCE) setShouldRegisterAttributionSource(boolean shouldRegister)187 public Builder setShouldRegisterAttributionSource(boolean shouldRegister) { 188 mShouldRegisterAttributionSource = shouldRegister; 189 return this; 190 } 191 192 /** 193 * Sets permissions which have been voluntarily "renounced" by the 194 * calling app. 195 * <p> 196 * Interactions performed through services obtained from the created 197 * Context will ideally be treated as if these "renounced" permissions 198 * have not actually been granted to the app, regardless of their actual 199 * grant status. 200 * <p> 201 * This is designed for use by separate logical components within an app 202 * which have no intention of interacting with data or services that are 203 * protected by the renounced permissions. 204 * <p> 205 * Note that only {@link PermissionInfo#PROTECTION_DANGEROUS} 206 * permissions are supported by this mechanism. Additionally, this 207 * mechanism only applies to calls made through services obtained via 208 * {@link Context#getSystemService}; it has no effect on static or raw 209 * Binder calls. 210 * 211 * @param renouncedPermissions The set of permissions to treat as 212 * renounced, which is as if not granted. 213 * @return This builder. 214 * @hide 215 */ 216 @SystemApi 217 @RequiresPermission(android.Manifest.permission.RENOUNCE_PERMISSIONS) setRenouncedPermissions( @ullable Set<String> renouncedPermissions)218 public @NonNull Builder setRenouncedPermissions( 219 @Nullable Set<String> renouncedPermissions) { 220 // This is not a security check but a fail fast - the OS enforces the permission too 221 if (renouncedPermissions != null && !renouncedPermissions.isEmpty() 222 && ActivityThread.currentApplication().checkSelfPermission(Manifest.permission 223 .RENOUNCE_PERMISSIONS) != PackageManager.PERMISSION_GRANTED) { 224 throw new SecurityException("Renouncing permissions requires: " 225 + Manifest.permission.RENOUNCE_PERMISSIONS); 226 } 227 mRenouncedPermissions = renouncedPermissions; 228 return this; 229 } 230 231 /** 232 * Creates a new instance. 233 * 234 * @return The new instance. 235 */ 236 @NonNull build()237 public ContextParams build() { 238 return new ContextParams(mAttributionTag, mNext, 239 mRenouncedPermissions, mShouldRegisterAttributionSource); 240 } 241 } 242 } 243