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