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.annotation.NonNull;
20 import android.annotation.Nullable;
21 import android.annotation.RequiresPermission;
22 import android.annotation.SystemApi;
23 import android.annotation.TestApi;
24 import android.app.ActivityThread;
25 import android.app.AppGlobals;
26 import android.os.Binder;
27 import android.os.Build;
28 import android.os.IBinder;
29 import android.os.Parcel;
30 import android.os.Parcelable;
31 import android.os.Process;
32 import android.os.UserHandle;
33 import android.permission.PermissionManager;
34 import android.util.ArraySet;
35 
36 import com.android.internal.annotations.Immutable;
37 
38 import java.util.Arrays;
39 import java.util.Collections;
40 import java.util.Objects;
41 import java.util.Set;
42 
43 /**
44  * This class represents a source to which access to permission protected data should be
45  * attributed. Attribution sources can be chained to represent cases where the protected
46  * data would flow through several applications. For example, app A may ask app B for
47  * contacts and in turn app B may ask app C for contacts. In this case, the attribution
48  * chain would be A -> B -> C and the data flow would be C -> B -> A. There are two
49  * main benefits of using the attribution source mechanism: avoid doing explicit permission
50  * checks on behalf of the calling app if you are accessing private data on their behalf
51  * to send back; avoid double data access blaming which happens as you check the calling
52  * app's permissions and when you access the data behind these permissions (for runtime
53  * permissions). Also if not explicitly blaming the caller the data access would be
54  * counted towards your app vs to the previous app where yours was just a proxy.
55  * <p>
56  * Every {@link Context} has an attribution source and you can get it via {@link
57  * Context#getAttributionSource()} representing itself, which is a chain of one. You
58  * can attribute work to another app, or more precisely to a chain of apps, through
59  * which the data you would be accessing would flow, via {@link Context#createContext(
60  * ContextParams)} plus specifying an attribution source for the next app to receive
61  * the protected data you are accessing via {@link AttributionSource.Builder#setNext(
62  * AttributionSource)}. Creating this attribution chain ensures that the datasource would
63  * check whether every app in the attribution chain has permission to access the data
64  * before releasing it. The datasource will also record appropriately that this data was
65  * accessed by the apps in the sequence if the data is behind a sensitive permission
66  * (e.g. dangerous). Again, this is useful if you are accessing the data on behalf of another
67  * app, for example a speech recognizer using the mic so it can provide recognition to
68  * a calling app.
69  * <p>
70  * You can create an attribution chain of you and any other app without any verification
71  * as this is something already available via the {@link android.app.AppOpsManager} APIs.
72  * This is supported to handle cases where you don't have access to the caller's attribution
73  * source and you can directly use the {@link AttributionSource.Builder} APIs. However,
74  * if the data flows through more than two apps (more than you access the data for the
75  * caller) you need to have a handle to the {@link AttributionSource} for the calling app's
76  * context in order to create an attribution context. This means you either need to have an
77  * API for the other app to send you its attribution source or use a platform API that pipes
78  * the callers attribution source.
79  * <p>
80  * You cannot forge an attribution chain without the participation of every app in the
81  * attribution chain (aside of the special case mentioned above). To create an attribution
82  * source that is trusted you need to create an attribution context that points to an
83  * attribution source that was explicitly created by the app that it refers to, recursively.
84  * <p>
85  * Since creating an attribution context leads to all permissions for apps in the attribution
86  * chain being checked, you need to expect getting a security exception when accessing
87  * permission protected APIs since some app in the chain may not have the permission.
88  */
89 @Immutable
90 public final class AttributionSource implements Parcelable {
91     private static final String DESCRIPTOR = "android.content.AttributionSource";
92 
93     private static final Binder sDefaultToken = new Binder(DESCRIPTOR);
94 
95     private final @NonNull AttributionSourceState mAttributionSourceState;
96 
97     private @Nullable AttributionSource mNextCached;
98     private @Nullable Set<String> mRenouncedPermissionsCached;
99 
100     /** @hide */
101     @TestApi
AttributionSource(int uid, @Nullable String packageName, @Nullable String attributionTag)102     public AttributionSource(int uid, @Nullable String packageName,
103             @Nullable String attributionTag) {
104         this(uid, Process.INVALID_PID, packageName, attributionTag, sDefaultToken);
105     }
106 
107     /** @hide */
AttributionSource(int uid, int pid, @Nullable String packageName, @Nullable String attributionTag)108     public AttributionSource(int uid, int pid, @Nullable String packageName,
109             @Nullable String attributionTag) {
110         this(uid, pid, packageName, attributionTag, sDefaultToken);
111     }
112 
113     /** @hide */
114     @TestApi
AttributionSource(int uid, @Nullable String packageName, @Nullable String attributionTag, @NonNull IBinder token)115     public AttributionSource(int uid, @Nullable String packageName,
116             @Nullable String attributionTag, @NonNull IBinder token) {
117         this(uid, Process.INVALID_PID, packageName, attributionTag, token,
118                 /*renouncedPermissions*/ null, /*next*/ null);
119     }
120 
121     /** @hide */
AttributionSource(int uid, int pid, @Nullable String packageName, @Nullable String attributionTag, @NonNull IBinder token)122     public AttributionSource(int uid, int pid, @Nullable String packageName,
123             @Nullable String attributionTag, @NonNull IBinder token) {
124         this(uid, pid, packageName, attributionTag, token, /*renouncedPermissions*/ null,
125                 /*next*/ null);
126     }
127 
128     /** @hide */
129     @TestApi
AttributionSource(int uid, @Nullable String packageName, @Nullable String attributionTag, @Nullable Set<String> renouncedPermissions, @Nullable AttributionSource next)130     public AttributionSource(int uid, @Nullable String packageName,
131             @Nullable String attributionTag, @Nullable Set<String> renouncedPermissions,
132             @Nullable AttributionSource next) {
133         this(uid, Process.INVALID_PID, packageName, attributionTag, sDefaultToken,
134                 (renouncedPermissions != null)
135                 ? renouncedPermissions.toArray(new String[0]) : null, /*next*/ next);
136     }
137 
138     /** @hide */
AttributionSource(@onNull AttributionSource current, @Nullable AttributionSource next)139     public AttributionSource(@NonNull AttributionSource current, @Nullable AttributionSource next) {
140         this(current.getUid(), current.getPid(), current.getPackageName(),
141                 current.getAttributionTag(), current.getToken(),
142                 current.mAttributionSourceState.renouncedPermissions, next);
143     }
144 
145     /** @hide */
AttributionSource(int uid, int pid, @Nullable String packageName, @Nullable String attributionTag, @Nullable String[] renouncedPermissions, @Nullable AttributionSource next)146     public AttributionSource(int uid, int pid, @Nullable String packageName,
147             @Nullable String attributionTag, @Nullable String[] renouncedPermissions,
148             @Nullable AttributionSource next) {
149         this(uid, pid, packageName, attributionTag, sDefaultToken, renouncedPermissions, next);
150     }
151 
152     /** @hide */
AttributionSource(int uid, int pid, @Nullable String packageName, @Nullable String attributionTag, @NonNull IBinder token, @Nullable String[] renouncedPermissions, @Nullable AttributionSource next)153     public AttributionSource(int uid, int pid, @Nullable String packageName,
154             @Nullable String attributionTag, @NonNull IBinder token,
155             @Nullable String[] renouncedPermissions,
156             @Nullable AttributionSource next) {
157         mAttributionSourceState = new AttributionSourceState();
158         mAttributionSourceState.uid = uid;
159         mAttributionSourceState.pid = pid;
160         mAttributionSourceState.token = token;
161         mAttributionSourceState.packageName = packageName;
162         mAttributionSourceState.attributionTag = attributionTag;
163         mAttributionSourceState.renouncedPermissions = renouncedPermissions;
164         mAttributionSourceState.next = (next != null) ? new AttributionSourceState[]
165                 {next.mAttributionSourceState} : new AttributionSourceState[0];
166     }
167 
AttributionSource(@onNull Parcel in)168     AttributionSource(@NonNull Parcel in) {
169         this(AttributionSourceState.CREATOR.createFromParcel(in));
170 
171         if (!Binder.isDirectlyHandlingTransaction()) {
172             throw new SecurityException("AttributionSource should be unparceled during a binder "
173                     + "transaction for proper verification.");
174         }
175 
176         // Since we just unpacked this object as part of it transiting a Binder
177         // call, this is the perfect time to enforce that its UID and PID can be trusted
178         enforceCallingUid();
179 
180         // If this object is being constructed as part of a oneway Binder call, getCallingPid will
181         // return 0 instead of the true PID. In that case, invalidate the PID by setting it to
182         // INVALID_PID (-1).
183         final int callingPid = Binder.getCallingPid();
184         if (callingPid == 0) {
185             mAttributionSourceState.pid = Process.INVALID_PID;
186         }
187 
188         enforceCallingPid();
189     }
190 
191     /** @hide */
AttributionSource(@onNull AttributionSourceState attributionSourceState)192     public AttributionSource(@NonNull AttributionSourceState attributionSourceState) {
193         mAttributionSourceState = attributionSourceState;
194     }
195 
196     /** @hide */
withNextAttributionSource(@ullable AttributionSource next)197     public AttributionSource withNextAttributionSource(@Nullable AttributionSource next) {
198         return new AttributionSource(getUid(), getPid(), getPackageName(), getAttributionTag(),
199                 getToken(), mAttributionSourceState.renouncedPermissions, next);
200     }
201 
202     /** @hide */
withPackageName(@ullable String packageName)203     public AttributionSource withPackageName(@Nullable String packageName) {
204         return new AttributionSource(getUid(), getPid(), packageName, getAttributionTag(),
205                getToken(), mAttributionSourceState.renouncedPermissions, getNext());
206     }
207 
208     /** @hide */
withToken(@onNull Binder token)209     public AttributionSource withToken(@NonNull Binder token) {
210         return new AttributionSource(getUid(), getPid(), getPackageName(), getAttributionTag(),
211                 token, mAttributionSourceState.renouncedPermissions, getNext());
212     }
213 
214     /** @hide */
withDefaultToken()215     public AttributionSource withDefaultToken() {
216         return withToken(sDefaultToken);
217     }
218 
219     /** @hide */
withPid(int pid)220     public AttributionSource withPid(int pid) {
221         return new AttributionSource(getUid(), pid, getPackageName(), getAttributionTag(),
222                 getToken(), mAttributionSourceState.renouncedPermissions, getNext());
223     }
224 
225     /** @hide */
asState()226     public @NonNull AttributionSourceState asState() {
227         return mAttributionSourceState;
228     }
229 
230     /** @hide */
asScopedParcelState()231     public @NonNull ScopedParcelState asScopedParcelState() {
232         return new ScopedParcelState(this);
233     }
234 
235     /**
236      * Returns a generic {@link AttributionSource} that represents the entire
237      * calling process.
238      *
239      * <p>Callers are <em>strongly</em> encouraged to use a more specific
240      * attribution source whenever possible, such as from
241      * {@link Context#getAttributionSource()}, since that enables developers to
242      * have more detailed and scoped control over attribution within
243      * sub-components of their app.
244      *
245      * @see Context#createAttributionContext(String)
246      * @see Context#getAttributionTag()
247      * @return a generic {@link AttributionSource} representing the entire
248      *         calling process
249      * @throws IllegalStateException when no accurate {@link AttributionSource}
250      *         can be determined
251      */
myAttributionSource()252     public static @NonNull AttributionSource myAttributionSource() {
253 
254         final AttributionSource globalSource = ActivityThread.currentAttributionSource();
255         if (globalSource != null) {
256             return globalSource;
257         }
258 
259         int uid = Process.myUid();
260         if (uid == Process.ROOT_UID) {
261             uid = Process.SYSTEM_UID;
262         }
263         try {
264             return new AttributionSource.Builder(uid)
265                 .setPid(Process.myPid())
266                 .setPackageName(AppGlobals.getPackageManager().getPackagesForUid(uid)[0])
267                 .build();
268         } catch (Exception ignored) {
269         }
270 
271         throw new IllegalStateException("Failed to resolve AttributionSource");
272     }
273 
274     /**
275      * This is a scoped object that exposes the content of an attribution source
276      * as a parcel. This is useful when passing one to native and avoid custom
277      * conversion logic from Java to native state that needs to be kept in sync
278      * as attribution source evolves. This way we use the same logic for passing
279      * to native as the ones for passing in an IPC - in both cases this is the
280      * same auto generated code.
281      *
282      * @hide
283      */
284     public static class ScopedParcelState implements AutoCloseable {
285         private final Parcel mParcel;
286 
getParcel()287         public @NonNull Parcel getParcel() {
288             return mParcel;
289         }
290 
ScopedParcelState(AttributionSource attributionSource)291         public ScopedParcelState(AttributionSource attributionSource) {
292             mParcel = Parcel.obtain();
293             attributionSource.writeToParcel(mParcel, 0);
294             mParcel.setDataPosition(0);
295         }
296 
close()297         public void close() {
298             mParcel.recycle();
299         }
300     }
301 
302     /**
303      * If you are handling an IPC and you don't trust the caller you need to validate
304      * whether the attribution source is one for the calling app to prevent the caller
305      * to pass you a source from another app without including themselves in the
306      * attribution chain.
307      *
308      * @throws SecurityException if the attribution source cannot be trusted to be from the caller.
309      */
enforceCallingUid()310     public void enforceCallingUid() {
311         if (!checkCallingUid()) {
312             throw new SecurityException("Calling uid: " + Binder.getCallingUid()
313                     + " doesn't match source uid: " + mAttributionSourceState.uid);
314         }
315         // No need to check package as app ops manager does it already.
316     }
317 
318     /**
319      * If you are handling an IPC and you don't trust the caller you need to validate
320      * whether the attribution source is one for the calling app to prevent the caller
321      * to pass you a source from another app without including themselves in the
322      * attribution chain.
323      *
324      * @return if the attribution source cannot be trusted to be from the caller.
325      */
checkCallingUid()326     public boolean checkCallingUid() {
327         final int callingUid = Binder.getCallingUid();
328         if (callingUid != Process.ROOT_UID
329                 && UserHandle.getAppId(callingUid) != Process.SYSTEM_UID
330                 && callingUid != mAttributionSourceState.uid) {
331             return false;
332         }
333         // No need to check package as app ops manager does it already.
334         return true;
335     }
336 
337     /**
338      * Validate that the pid being claimed for the calling app is not spoofed.
339      *
340      * Note that the PID may be unavailable, for example if we're in a oneway Binder call. In this
341      * case, calling enforceCallingPid is guaranteed to fail. The caller should anticipate this.
342      *
343      * @throws SecurityException if the attribution source cannot be trusted to be from the caller.
344      * @hide
345      */
346     @TestApi
enforceCallingPid()347     public void enforceCallingPid() {
348         if (!checkCallingPid()) {
349             if (Binder.getCallingPid() == 0) {
350                 throw new SecurityException("Calling pid unavailable due to oneway Binder call.");
351             } else {
352                 throw new SecurityException("Calling pid: " + Binder.getCallingPid()
353                         + " doesn't match source pid: " + mAttributionSourceState.pid);
354             }
355         }
356     }
357 
358     /**
359      * Validate that the pid being claimed for the calling app is not spoofed
360      *
361      * @return if the attribution source cannot be trusted to be from the caller.
362      */
checkCallingPid()363     private boolean checkCallingPid() {
364         final int callingPid = Binder.getCallingPid();
365         if (mAttributionSourceState.pid != Process.INVALID_PID
366                 && callingPid != mAttributionSourceState.pid) {
367             return false;
368         }
369         return true;
370     }
371 
372     @Override
toString()373     public String toString() {
374         if (Build.IS_DEBUGGABLE) {
375             return "AttributionSource { " +
376                     "uid = " + mAttributionSourceState.uid + ", " +
377                     "packageName = " + mAttributionSourceState.packageName + ", " +
378                     "attributionTag = " + mAttributionSourceState.attributionTag + ", " +
379                     "token = " + mAttributionSourceState.token + ", " +
380                     "next = " + (mAttributionSourceState.next != null
381                                     && mAttributionSourceState.next.length > 0
382                             ? mAttributionSourceState.next[0] : null) +
383                     " }";
384         }
385         return super.toString();
386     }
387 
388     /**
389      * @return The next UID that would receive the permission protected data.
390      *
391      * @hide
392      */
getNextUid()393     public int getNextUid() {
394         if (mAttributionSourceState.next != null
395                 && mAttributionSourceState.next.length > 0) {
396             return mAttributionSourceState.next[0].uid;
397         }
398         return Process.INVALID_UID;
399     }
400 
401     /**
402      * @return The next package that would receive the permission protected data.
403      *
404      * @hide
405      */
getNextPackageName()406     public @Nullable String getNextPackageName() {
407         if (mAttributionSourceState.next != null
408                 && mAttributionSourceState.next.length > 0) {
409             return mAttributionSourceState.next[0].packageName;
410         }
411         return null;
412     }
413 
414     /**
415      * @return The next package's attribution tag that would receive
416      * the permission protected data.
417      *
418      * @hide
419      */
getNextAttributionTag()420     public @Nullable String getNextAttributionTag() {
421         if (mAttributionSourceState.next != null
422                 && mAttributionSourceState.next.length > 0) {
423             return mAttributionSourceState.next[0].attributionTag;
424         }
425         return null;
426     }
427 
428     /**
429      * @return The next package's token that would receive
430      * the permission protected data.
431      *
432      * @hide
433      */
getNextToken()434     public @Nullable IBinder getNextToken() {
435         if (mAttributionSourceState.next != null
436                 && mAttributionSourceState.next.length > 0) {
437             return mAttributionSourceState.next[0].token;
438         }
439         return null;
440     }
441 
442     /**
443      * Checks whether this attribution source can be trusted. That is whether
444      * the app it refers to created it and provided to the attribution chain.
445      *
446      * @param context Context handle.
447      * @return Whether this is a trusted source.
448      */
isTrusted(@onNull Context context)449     public boolean isTrusted(@NonNull Context context) {
450         return mAttributionSourceState.token != null
451                 && context.getSystemService(PermissionManager.class)
452                         .isRegisteredAttributionSource(this);
453     }
454 
455     /**
456      * Permissions that should be considered revoked regardless if granted.
457      *
458      * @hide
459      */
460     @SystemApi
461     @RequiresPermission(android.Manifest.permission.RENOUNCE_PERMISSIONS)
462     @NonNull
getRenouncedPermissions()463     public Set<String> getRenouncedPermissions() {
464         if (mRenouncedPermissionsCached == null) {
465             if (mAttributionSourceState.renouncedPermissions != null) {
466                 mRenouncedPermissionsCached = new ArraySet<>(
467                         mAttributionSourceState.renouncedPermissions);
468             } else {
469                 mRenouncedPermissionsCached = Collections.emptySet();
470             }
471         }
472         return mRenouncedPermissionsCached;
473     }
474 
475     /**
476      * The UID that is accessing the permission protected data.
477      */
getUid()478     public int getUid() {
479         return mAttributionSourceState.uid;
480     }
481 
482     /**
483      * The PID that is accessing the permission protected data.
484      */
getPid()485     public int getPid() {
486         return mAttributionSourceState.pid;
487     }
488 
489     /**
490      * The package that is accessing the permission protected data.
491      */
getPackageName()492     public @Nullable String getPackageName() {
493         return mAttributionSourceState.packageName;
494     }
495 
496     /**
497      * The attribution tag of the app accessing the permission protected data.
498      */
getAttributionTag()499     public @Nullable String getAttributionTag() {
500         return mAttributionSourceState.attributionTag;
501     }
502 
503     /**
504      * Unique token for that source.
505      *
506      * @hide
507      */
getToken()508     public @NonNull IBinder getToken() {
509         return mAttributionSourceState.token;
510     }
511 
512     /**
513      * The next app to receive the permission protected data.
514      */
getNext()515     public @Nullable AttributionSource getNext() {
516         if (mNextCached == null && mAttributionSourceState.next != null
517                 && mAttributionSourceState.next.length > 0) {
518             mNextCached = new AttributionSource(mAttributionSourceState.next[0]);
519         }
520         return mNextCached;
521     }
522 
523     @Override
equals(@ullable Object o)524     public boolean equals(@Nullable Object o) {
525         if (this == o) return true;
526         if (o == null || getClass() != o.getClass()) return false;
527         AttributionSource that = (AttributionSource) o;
528         return equalsExceptToken(that) && Objects.equals(
529                 mAttributionSourceState.token, that.mAttributionSourceState.token);
530     }
531 
532     /**
533      * We store trusted attribution sources without their token (the token is the key to the map)
534      * to avoid having a strong reference to the token. This means, when checking the equality of a
535      * supplied AttributionSource in PermissionManagerService.isTrustedAttributionSource, we want to
536      * compare everything except the token.
537      *
538      * @hide
539      */
equalsExceptToken(@ullable AttributionSource o)540     public boolean equalsExceptToken(@Nullable AttributionSource o) {
541         if (o == null) return false;
542         return mAttributionSourceState.uid == o.mAttributionSourceState.uid
543                 && Objects.equals(mAttributionSourceState.packageName,
544                 o.mAttributionSourceState.packageName)
545                 && Objects.equals(mAttributionSourceState.attributionTag,
546                 o.mAttributionSourceState.attributionTag)
547                 && Arrays.equals(mAttributionSourceState.renouncedPermissions,
548                 o.mAttributionSourceState.renouncedPermissions)
549                 && Objects.equals(getNext(), o.getNext());
550     }
551 
552     @Override
hashCode()553     public int hashCode() {
554         return Objects.hash(mAttributionSourceState.uid, mAttributionSourceState.packageName,
555                 mAttributionSourceState.attributionTag, mAttributionSourceState.token,
556                 Arrays.hashCode(mAttributionSourceState.renouncedPermissions), getNext());
557     }
558 
559     @Override
writeToParcel(@onNull Parcel dest, int flags)560     public void writeToParcel(@NonNull Parcel dest, int flags) {
561         mAttributionSourceState.writeToParcel(dest, flags);
562     }
563 
564     @Override
describeContents()565     public int describeContents() { return 0; }
566 
567     public static final @NonNull Parcelable.Creator<AttributionSource> CREATOR
568             = new Parcelable.Creator<AttributionSource>() {
569         @Override
570         public AttributionSource[] newArray(int size) {
571             return new AttributionSource[size];
572         }
573 
574         @Override
575         public AttributionSource createFromParcel(@NonNull Parcel in) {
576             return new AttributionSource(in);
577         }
578     };
579 
580     /**
581      * A builder for {@link AttributionSource}
582      */
583     public static final class Builder {
584         private @NonNull final AttributionSourceState mAttributionSourceState =
585                 new AttributionSourceState();
586 
587         private long mBuilderFieldsSet = 0L;
588 
589         /**
590          * Creates a new Builder.
591          *
592          * @param uid
593          *   The UID that is accessing the permission protected data.
594          */
Builder(int uid)595         public Builder(int uid) {
596             mAttributionSourceState.uid = uid;
597         }
598 
Builder(@onNull AttributionSource current)599         public Builder(@NonNull AttributionSource current) {
600             if (current == null) {
601                 throw new IllegalArgumentException("current AttributionSource can not be null");
602             }
603             mAttributionSourceState.uid = current.getUid();
604             mAttributionSourceState.pid = current.getPid();
605             mAttributionSourceState.packageName = current.getPackageName();
606             mAttributionSourceState.attributionTag = current.getAttributionTag();
607             mAttributionSourceState.token = current.getToken();
608             mAttributionSourceState.renouncedPermissions =
609                 current.mAttributionSourceState.renouncedPermissions;
610         }
611 
612         /**
613          * The PID of the process that is accessing the permission protected data.
614          *
615          * If not called, pid will default to {@link Process@INVALID_PID} (-1). This indicates that
616          * the PID data is missing. Supplying a PID is not required, but recommended when
617          * accessible.
618          */
setPid(int value)619         public @NonNull Builder setPid(int value) {
620             checkNotUsed();
621             mBuilderFieldsSet |= 0x2;
622             mAttributionSourceState.pid = value;
623             return this;
624         }
625 
626         /**
627          * The package that is accessing the permission protected data.
628          */
setPackageName(@ullable String value)629         public @NonNull Builder setPackageName(@Nullable String value) {
630             checkNotUsed();
631             mBuilderFieldsSet |= 0x4;
632             mAttributionSourceState.packageName = value;
633             return this;
634         }
635 
636         /**
637          * The attribution tag of the app accessing the permission protected data.
638          */
setAttributionTag(@ullable String value)639         public @NonNull Builder setAttributionTag(@Nullable String value) {
640             checkNotUsed();
641             mBuilderFieldsSet |= 0x8;
642             mAttributionSourceState.attributionTag = value;
643             return this;
644         }
645 
646         /**
647          * Sets permissions which have been voluntarily "renounced" by the
648          * calling app.
649          * <p>
650          * Interactions performed through services obtained from the created
651          * Context will ideally be treated as if these "renounced" permissions
652          * have not actually been granted to the app, regardless of their actual
653          * grant status.
654          * <p>
655          * This is designed for use by separate logical components within an app
656          * which have no intention of interacting with data or services that are
657          * protected by the renounced permissions.
658          * <p>
659          * Note that only {@link PermissionInfo#PROTECTION_DANGEROUS}
660          * permissions are supported by this mechanism. Additionally, this
661          * mechanism only applies to calls made through services obtained via
662          * {@link Context#getSystemService}; it has no effect on static or raw
663          * Binder calls.
664          *
665          * @param renouncedPermissions The set of permissions to treat as
666          *            renounced, which is as if not granted.
667          * @return This builder.
668          * @hide
669          */
670         @SystemApi
671         @RequiresPermission(android.Manifest.permission.RENOUNCE_PERMISSIONS)
setRenouncedPermissions(@ullable Set<String> value)672         public @NonNull Builder setRenouncedPermissions(@Nullable Set<String> value) {
673             checkNotUsed();
674             mBuilderFieldsSet |= 0x10;
675             mAttributionSourceState.renouncedPermissions = (value != null)
676                     ? value.toArray(new String[0]) : null;
677             return this;
678         }
679 
680         /**
681          * The next app to receive the permission protected data.
682          */
setNext(@ullable AttributionSource value)683         public @NonNull Builder setNext(@Nullable AttributionSource value) {
684             checkNotUsed();
685             mBuilderFieldsSet |= 0x20;
686             mAttributionSourceState.next = (value != null) ? new AttributionSourceState[]
687                     {value.mAttributionSourceState} : mAttributionSourceState.next;
688             return this;
689         }
690 
691         /** Builds the instance. This builder should not be touched after calling this! */
build()692         public @NonNull AttributionSource build() {
693             checkNotUsed();
694             mBuilderFieldsSet |= 0x40; // Mark builder used
695 
696             if ((mBuilderFieldsSet & 0x2) == 0) {
697                 mAttributionSourceState.pid = Process.INVALID_PID;
698             }
699             if ((mBuilderFieldsSet & 0x4) == 0) {
700                 mAttributionSourceState.packageName = null;
701             }
702             if ((mBuilderFieldsSet & 0x8) == 0) {
703                 mAttributionSourceState.attributionTag = null;
704             }
705             if ((mBuilderFieldsSet & 0x10) == 0) {
706                 mAttributionSourceState.renouncedPermissions = null;
707             }
708             if ((mBuilderFieldsSet & 0x20) == 0) {
709                 mAttributionSourceState.next = null;
710             }
711 
712             mAttributionSourceState.token = sDefaultToken;
713 
714             if (mAttributionSourceState.next == null) {
715                 // The NDK aidl backend doesn't support null parcelable arrays.
716                 mAttributionSourceState.next = new AttributionSourceState[0];
717             }
718             return new AttributionSource(mAttributionSourceState);
719         }
720 
checkNotUsed()721         private void checkNotUsed() {
722             if ((mBuilderFieldsSet & 0x40) != 0) {
723                 throw new IllegalStateException(
724                         "This Builder should not be reused. Use a new Builder instance instead");
725             }
726         }
727     }
728 }
729