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