1 /* 2 * Copyright (C) 2022 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 com.android.adservices.service.measurement; 18 19 import android.annotation.IntDef; 20 import android.annotation.NonNull; 21 import android.annotation.Nullable; 22 import android.net.Uri; 23 import android.util.Pair; 24 25 import com.android.adservices.LoggerFactory; 26 import com.android.adservices.service.Flags; 27 import com.android.adservices.service.FlagsFactory; 28 import com.android.adservices.service.measurement.aggregation.AggregatableAttributionSource; 29 import com.android.adservices.service.measurement.aggregation.AggregateDebugReporting; 30 import com.android.adservices.service.measurement.noising.Combinatorics; 31 import com.android.adservices.service.measurement.noising.SourceNoiseHandler; 32 import com.android.adservices.service.measurement.reporting.EventReportWindowCalcDelegate; 33 import com.android.adservices.service.measurement.util.UnsignedLong; 34 import com.android.adservices.service.measurement.util.Validation; 35 import com.android.internal.annotations.VisibleForTesting; 36 37 import com.google.common.collect.ImmutableMultiset; 38 39 import org.json.JSONArray; 40 import org.json.JSONException; 41 import org.json.JSONObject; 42 43 import java.lang.annotation.Retention; 44 import java.lang.annotation.RetentionPolicy; 45 import java.math.BigInteger; 46 import java.util.ArrayList; 47 import java.util.Collections; 48 import java.util.HashMap; 49 import java.util.Iterator; 50 import java.util.List; 51 import java.util.Map; 52 import java.util.Objects; 53 import java.util.Optional; 54 import java.util.Set; 55 import java.util.TreeMap; 56 import java.util.concurrent.TimeUnit; 57 58 /** 59 * POJO for Source. 60 */ 61 public class Source { 62 63 public static final long DEFAULT_MAX_EVENT_STATES = 3L; 64 65 private String mId; 66 private UnsignedLong mEventId; 67 private Uri mPublisher; 68 @EventSurfaceType private int mPublisherType; 69 private List<Uri> mAppDestinations; 70 private List<Uri> mWebDestinations; 71 private String mEnrollmentId; 72 private Uri mRegistrant; 73 private SourceType mSourceType; 74 private long mPriority; 75 @Status private int mStatus; 76 private long mEventTime; 77 private long mExpiryTime; 78 @Nullable private Long mEventReportWindow; 79 @Nullable private String mEventReportWindows; 80 private long mAggregatableReportWindow; 81 private long mReinstallReattributionWindow; 82 private List<UnsignedLong> mAggregateReportDedupKeys; 83 private List<UnsignedLong> mEventReportDedupKeys; 84 @AttributionMode private int mAttributionMode; 85 private long mInstallAttributionWindow; 86 private long mInstallCooldownWindow; 87 @Nullable private UnsignedLong mDebugKey; 88 private boolean mIsInstallAttributed; 89 private boolean mIsDebugReporting; 90 private String mFilterDataString; 91 @Nullable private String mSharedFilterDataKeys; 92 private FilterMap mFilterData; 93 private String mAggregateSource; 94 private int mAggregateContributions; 95 private Optional<AggregatableAttributionSource> mAggregatableAttributionSource; 96 private boolean mAdIdPermission; 97 private boolean mArDebugPermission; 98 @Nullable private String mRegistrationId; 99 @Nullable private String mSharedAggregationKeys; 100 @Nullable private Long mInstallTime; 101 @Nullable private String mParentId; 102 @Nullable private String mDebugJoinKey; 103 @Nullable private Set<UnsignedLong> mTriggerData; 104 @Nullable private List<AttributedTrigger> mAttributedTriggers; 105 @Nullable private TriggerSpecs mTriggerSpecs; 106 @Nullable private String mTriggerSpecsString; 107 @Nullable private Long mNumStates; 108 @Nullable private Double mFlipProbability; 109 @Nullable private Integer mMaxEventLevelReports; 110 @Nullable private String mEventAttributionStatusString; 111 @Nullable private String mPrivacyParametersString = null; 112 private TriggerDataMatching mTriggerDataMatching; 113 @Nullable private String mPlatformAdId; 114 @Nullable private String mDebugAdId; 115 private Uri mRegistrationOrigin; 116 private boolean mCoarseEventReportDestinations; 117 @Nullable private UnsignedLong mSharedDebugKey; 118 private List<Pair<Long, Long>> mParsedEventReportWindows; 119 private boolean mDropSourceIfInstalled; 120 @Nullable private List<String> mAttributionScopes; 121 @Nullable private Long mAttributionScopeLimit; 122 @Nullable private Long mMaxEventStates; 123 private long mDestinationLimitPriority; 124 @Nullable private DestinationLimitAlgorithm mDestinationLimitAlgorithm; 125 @Nullable private Double mEventLevelEpsilon; 126 @Nullable private String mAggregateDebugReportingString; 127 @Nullable private AggregateDebugReporting mAggregateDebugReporting; 128 private int mAggregateDebugReportContributions; 129 @Nullable private AggregatableNamedBudgets mAggregatableNamedBudgets; 130 131 /** 132 * Parses and returns the event_report_windows Returns null if parsing fails or if there is no 133 * windows provided by user. 134 */ 135 @Nullable parsedProcessedEventReportWindows()136 public List<Pair<Long, Long>> parsedProcessedEventReportWindows() { 137 if (mParsedEventReportWindows != null) { 138 return mParsedEventReportWindows; 139 } 140 141 if (mEventReportWindows == null) { 142 return null; 143 } 144 145 List<Pair<Long, Long>> rawWindows = parseEventReportWindows(mEventReportWindows); 146 if (rawWindows == null) { 147 return null; 148 } 149 // Append Event Time 150 mParsedEventReportWindows = new ArrayList<>(); 151 152 for (Pair<Long, Long> window : rawWindows) { 153 mParsedEventReportWindows.add( 154 new Pair<>(mEventTime + window.first, mEventTime + window.second)); 155 } 156 return mParsedEventReportWindows; 157 } 158 159 /** 160 * Returns parsed or default value of event report windows (can be used during {@code Source} 161 * construction since the method does not require a {@code Source} object). 162 * 163 * @param eventReportWindows string to be parsed 164 * @param sourceType Source's Type 165 * @param expiryDelta relative expiry value 166 * @param flags Flags 167 * @return parsed or default value 168 */ 169 @Nullable getOrDefaultEventReportWindowsForFlex( @ullable JSONObject eventReportWindows, @NonNull SourceType sourceType, long expiryDelta, @NonNull Flags flags)170 public static List<Pair<Long, Long>> getOrDefaultEventReportWindowsForFlex( 171 @Nullable JSONObject eventReportWindows, 172 @NonNull SourceType sourceType, 173 long expiryDelta, 174 @NonNull Flags flags) { 175 if (eventReportWindows == null) { 176 return getDefaultEventReportWindowsForFlex(expiryDelta, sourceType, flags); 177 } 178 return parseEventReportWindows(eventReportWindows); 179 } 180 181 /** Parses the provided eventReportWindows. Returns null if parsing fails */ 182 @Nullable parseEventReportWindows( @onNull String eventReportWindows)183 public static List<Pair<Long, Long>> parseEventReportWindows( 184 @NonNull String eventReportWindows) { 185 try { 186 JSONObject jsonObject = new JSONObject(eventReportWindows); 187 return parseEventReportWindows(jsonObject); 188 } catch (JSONException e) { 189 LoggerFactory.getMeasurementLogger() 190 .e(e, "Invalid JSON encountered: event_report_windows"); 191 return null; 192 } 193 } 194 195 /** Parses the provided eventReportWindows. Returns null if parsing fails */ 196 @Nullable parseEventReportWindows( @onNull JSONObject jsonObject)197 public static List<Pair<Long, Long>> parseEventReportWindows( 198 @NonNull JSONObject jsonObject) { 199 List<Pair<Long, Long>> result = new ArrayList<>(); 200 try { 201 long startTime = 0L; 202 if (!jsonObject.isNull("start_time")) { 203 startTime = jsonObject.getLong("start_time"); 204 } 205 JSONArray endTimesJSON = jsonObject.getJSONArray("end_times"); 206 207 for (int i = 0; i < endTimesJSON.length(); i++) { 208 long endTime = endTimesJSON.getLong(i); 209 Pair<Long, Long> window = Pair.create(startTime, endTime); 210 result.add(window); 211 startTime = endTime; 212 } 213 } catch (JSONException e) { 214 LoggerFactory.getMeasurementLogger() 215 .e(e, "Invalid JSON encountered: event_report_windows"); 216 return null; 217 } 218 return result; 219 } 220 getDefaultEventReportWindowsForFlex( long expiryDelta, SourceType sourceType, Flags flags)221 private static List<Pair<Long, Long>> getDefaultEventReportWindowsForFlex( 222 long expiryDelta, SourceType sourceType, Flags flags) { 223 List<Pair<Long, Long>> result = new ArrayList<>(); 224 // Obtain default early report windows without regard to install-related behaviour. 225 List<Long> defaultEarlyWindowEnds = 226 EventReportWindowCalcDelegate.getDefaultEarlyReportingWindowEnds(sourceType, false); 227 List<Long> earlyWindowEnds = 228 new EventReportWindowCalcDelegate(flags) 229 .getConfiguredOrDefaultEarlyReportingWindowEnds( 230 sourceType, defaultEarlyWindowEnds); 231 long windowStart = 0; 232 for (long earlyWindowEnd : earlyWindowEnds) { 233 if (earlyWindowEnd >= expiryDelta) { 234 break; 235 } 236 result.add(Pair.create(windowStart, earlyWindowEnd)); 237 windowStart = earlyWindowEnd; 238 } 239 result.add(Pair.create(windowStart, expiryDelta)); 240 return result; 241 } 242 243 /** 244 * Checks if the source has a valid number of report states and sets the value. mNumStates will 245 * not be set if invalid. 246 * 247 * @param flags flag values 248 */ validateAndSetNumReportStates(Flags flags)249 public boolean validateAndSetNumReportStates(Flags flags) { 250 if (mTriggerSpecs == null) { 251 long reportStateCountLimit = flags.getMeasurementMaxReportStatesPerSourceRegistration(); 252 EventReportWindowCalcDelegate eventReportWindowCalcDelegate = 253 new EventReportWindowCalcDelegate(flags); 254 int reportingWindowCountForNoising = 255 eventReportWindowCalcDelegate.getReportingWindowCountForNoising(this); 256 257 int numStars = eventReportWindowCalcDelegate.getMaxReportCount(this); 258 int numBars = getTriggerDataCardinality() 259 * reportingWindowCountForNoising 260 * getDestinationTypeMultiplier(flags); 261 262 long numStates = Combinatorics.getNumberOfStarsAndBarsSequences(numStars, numBars); 263 if (numStates > reportStateCountLimit) { 264 return false; 265 } 266 267 setNumStates(numStates); 268 269 return true; 270 } else { 271 return mTriggerSpecs.hasValidReportStateCount(this, flags); 272 } 273 } 274 275 /** 276 * Verifies whether the source contains valid attribution scope values. 277 * 278 * @param flags flag values 279 */ validateAttributionScopeValues(Flags flags)280 public AttributionScopeValidationResult validateAttributionScopeValues(Flags flags) { 281 if (!flags.getMeasurementEnableAttributionScope() || getAttributionScopeLimit() == null) { 282 return AttributionScopeValidationResult.VALID; 283 } 284 if (getMaxEventStates() == null) { 285 throw new IllegalStateException( 286 "maxEventStates should be set if attributionScopeLimit is set."); 287 } 288 Long numStates = 289 mTriggerSpecs == null 290 ? getNumStates(flags) 291 : mTriggerSpecs.getNumStates(this, flags); 292 if (numStates == null || numStates == 0L) { 293 throw new IllegalStateException( 294 "Num states should be validated before validating max event states"); 295 } 296 if (getSourceType() == SourceType.EVENT && numStates > getMaxEventStates()) { 297 return AttributionScopeValidationResult.INVALID_MAX_EVENT_STATES_LIMIT; 298 } 299 if (!hasValidAttributionScopeInformationGain(flags, numStates)) { 300 return AttributionScopeValidationResult.INVALID_INFORMATION_GAIN_LIMIT; 301 } 302 return AttributionScopeValidationResult.VALID; 303 } 304 305 /** 306 * Checks if the source has valid information gain 307 * 308 * @param flags flag values 309 */ hasValidInformationGain(@onNull Flags flags)310 public boolean hasValidInformationGain(@NonNull Flags flags) { 311 if (mTriggerSpecs != null) { 312 return isFlexEventApiValueValid(flags); 313 } 314 return isFlexLiteApiValueValid(flags); 315 } 316 317 /** 318 * @param flags flag values 319 * @return the information gain threshold for a single attribution source 320 */ getInformationGainThreshold(Flags flags)321 public float getInformationGainThreshold(Flags flags) { 322 if (getDestinationTypeMultiplier(flags) == 2) { 323 return mSourceType == SourceType.EVENT 324 ? flags.getMeasurementFlexApiMaxInformationGainDualDestinationEvent() 325 : flags.getMeasurementFlexApiMaxInformationGainDualDestinationNavigation(); 326 } 327 return mSourceType == SourceType.EVENT 328 ? flags.getMeasurementFlexApiMaxInformationGainEvent() 329 : flags.getMeasurementFlexApiMaxInformationGainNavigation(); 330 } 331 332 /** 333 * @param flags flag values 334 * @return the information gain threshold for attribution scopes. 335 */ getAttributionScopeInfoGainThreshold(Flags flags)336 public double getAttributionScopeInfoGainThreshold(Flags flags) { 337 if (getDestinationTypeMultiplier(flags) == 2) { 338 return mSourceType == SourceType.EVENT 339 ? flags.getMeasurementAttributionScopeMaxInfoGainDualDestinationEvent() 340 : flags.getMeasurementAttributionScopeMaxInfoGainDualDestinationNavigation(); 341 } 342 return mSourceType == SourceType.EVENT 343 ? flags.getMeasurementAttributionScopeMaxInfoGainEvent() 344 : flags.getMeasurementAttributionScopeMaxInfoGainNavigation(); 345 } 346 347 /** Retrieves the default epsilon or epsilon defined from Source. */ getConditionalEventLevelEpsilon(Flags flags)348 public double getConditionalEventLevelEpsilon(Flags flags) { 349 if (flags.getMeasurementEnableEventLevelEpsilonInSource() 350 && getEventLevelEpsilon() != null) { 351 return getEventLevelEpsilon(); 352 } 353 return flags.getMeasurementPrivacyEpsilon(); 354 } 355 isFlexLiteApiValueValid(Flags flags)356 private boolean isFlexLiteApiValueValid(Flags flags) { 357 return Combinatorics.getInformationGain(getNumStates(flags), getFlipProbability(flags)) 358 <= getInformationGainThreshold(flags); 359 } 360 hasValidAttributionScopeInformationGain(Flags flags, long numStates)361 private boolean hasValidAttributionScopeInformationGain(Flags flags, long numStates) { 362 if (!flags.getMeasurementEnableAttributionScope() || getAttributionScopeLimit() == null) { 363 return true; 364 } 365 return Combinatorics.getMaxInformationGainWithAttributionScope( 366 numStates, getAttributionScopeLimit(), getMaxEventStates()) 367 <= getAttributionScopeInfoGainThreshold(flags); 368 } 369 buildPrivacyParameters(Flags flags)370 private void buildPrivacyParameters(Flags flags) { 371 if (mTriggerSpecs != null) { 372 // Flex source has num states set during registration but not during attribution; also 373 // num states is only needed for information gain calculation, which is handled during 374 // registration. We set flip probability here for use in noising during registration and 375 // availability for debug reporting during attribution. 376 setFlipProbability(mTriggerSpecs.getFlipProbability(this, flags)); 377 return; 378 } 379 double epsilon = getConditionalEventLevelEpsilon(flags); 380 setFlipProbability(Combinatorics.getFlipProbability(getNumStates(flags), epsilon)); 381 } 382 383 /** Should source report coarse destinations */ shouldReportCoarseDestinations(Flags flags)384 public boolean shouldReportCoarseDestinations(Flags flags) { 385 return flags.getMeasurementEnableCoarseEventReportDestinations() 386 && hasCoarseEventReportDestinations(); 387 } 388 389 /** 390 * Returns the number of destination types to use in privacy computations. 391 */ getDestinationTypeMultiplier(Flags flags)392 public int getDestinationTypeMultiplier(Flags flags) { 393 return !shouldReportCoarseDestinations(flags) && hasAppDestinations() 394 && hasWebDestinations() 395 ? SourceNoiseHandler.DUAL_DESTINATION_IMPRESSION_NOISE_MULTIPLIER 396 : SourceNoiseHandler.SINGLE_DESTINATION_IMPRESSION_NOISE_MULTIPLIER; 397 } 398 399 /** Returns true is manual event reporting windows are set otherwise false; */ hasManualEventReportWindows()400 public boolean hasManualEventReportWindows() { 401 return getEventReportWindows() != null; 402 } 403 404 @IntDef(value = {Status.ACTIVE, Status.IGNORED, Status.MARKED_TO_DELETE}) 405 @Retention(RetentionPolicy.SOURCE) 406 public @interface Status { 407 int ACTIVE = 0; 408 int IGNORED = 1; 409 int MARKED_TO_DELETE = 2; 410 } 411 412 @IntDef(value = { 413 AttributionMode.UNASSIGNED, 414 AttributionMode.TRUTHFULLY, 415 AttributionMode.NEVER, 416 AttributionMode.FALSELY, 417 }) 418 @Retention(RetentionPolicy.SOURCE) 419 public @interface AttributionMode { 420 int UNASSIGNED = 0; 421 int TRUTHFULLY = 1; 422 int NEVER = 2; 423 int FALSELY = 3; 424 } 425 426 public enum DestinationLimitAlgorithm { 427 LIFO, 428 FIFO 429 } 430 431 /** The choice of the summary operator with the reporting window */ 432 public enum TriggerDataMatching { 433 MODULUS, 434 EXACT 435 } 436 437 /** The validation result attribution scope values. */ 438 public enum AttributionScopeValidationResult { 439 VALID(true), 440 INVALID_MAX_EVENT_STATES_LIMIT(false), 441 INVALID_INFORMATION_GAIN_LIMIT(false); 442 443 private final boolean mIsValid; 444 AttributionScopeValidationResult(boolean isValid)445 AttributionScopeValidationResult(boolean isValid) { 446 mIsValid = isValid; 447 } 448 isValid()449 public boolean isValid() { 450 return mIsValid; 451 } 452 } 453 454 public enum SourceType { 455 EVENT("event"), 456 NAVIGATION("navigation"); 457 458 private final String mValue; 459 SourceType(String value)460 SourceType(String value) { 461 mValue = value; 462 } 463 getValue()464 public String getValue() { 465 return mValue; 466 } 467 getIntValue()468 public int getIntValue() { 469 return this.equals(SourceType.NAVIGATION) ? 1 : 0; 470 } 471 } 472 Source()473 private Source() { 474 mEventReportDedupKeys = new ArrayList<>(); 475 mAggregateReportDedupKeys = new ArrayList<>(); 476 mStatus = Status.ACTIVE; 477 mSourceType = SourceType.EVENT; 478 // Making this default explicit since it anyway would occur on an uninitialised int field. 479 mPublisherType = EventSurfaceType.APP; 480 mAttributionMode = AttributionMode.UNASSIGNED; 481 mTriggerDataMatching = TriggerDataMatching.MODULUS; 482 mIsInstallAttributed = false; 483 mIsDebugReporting = false; 484 } 485 486 /** Class for storing fake report data. */ 487 public static class FakeReport { 488 private final UnsignedLong mTriggerData; 489 private final long mReportingTime; 490 private final long mTriggerTime; 491 private final List<Uri> mDestinations; 492 private final Pair<Long, Long> mTriggerSummaryBucket; 493 FakeReport( UnsignedLong triggerData, long reportingTime, long triggerTime, List<Uri> destinations, @Nullable Pair<Long, Long> triggerSummaryBucket)494 public FakeReport( 495 UnsignedLong triggerData, 496 long reportingTime, 497 long triggerTime, 498 List<Uri> destinations, 499 @Nullable Pair<Long, Long> triggerSummaryBucket) { 500 mTriggerData = triggerData; 501 mReportingTime = reportingTime; 502 mDestinations = destinations; 503 mTriggerTime = triggerTime; 504 mTriggerSummaryBucket = triggerSummaryBucket; 505 } 506 507 @Override equals(Object o)508 public boolean equals(Object o) { 509 if (this == o) return true; 510 if (!(o instanceof FakeReport)) return false; 511 FakeReport that = (FakeReport) o; 512 return Objects.equals(mTriggerData, that.mTriggerData) 513 && mReportingTime == that.mReportingTime 514 && mTriggerTime == that.mTriggerTime 515 && Objects.equals(mDestinations, that.mDestinations) 516 && Objects.equals(mTriggerSummaryBucket, that.mTriggerSummaryBucket); 517 } 518 519 @Override hashCode()520 public int hashCode() { 521 return Objects.hash( 522 mTriggerData, 523 mReportingTime, 524 mTriggerTime, 525 mDestinations, 526 mTriggerSummaryBucket); 527 } 528 getReportingTime()529 public long getReportingTime() { 530 return mReportingTime; 531 } 532 getTriggerTime()533 public long getTriggerTime() { 534 return mTriggerTime; 535 } 536 getTriggerData()537 public UnsignedLong getTriggerData() { 538 return mTriggerData; 539 } 540 getDestinations()541 public List<Uri> getDestinations() { 542 return mDestinations; 543 } 544 545 @Nullable getTriggerSummaryBucket()546 public Pair<Long, Long> getTriggerSummaryBucket() { 547 return mTriggerSummaryBucket; 548 } 549 } 550 551 /** 552 * Range of trigger metadata: [0, cardinality). 553 * 554 * @return Cardinality of {@link Trigger} metadata 555 */ getTriggerDataCardinality()556 public int getTriggerDataCardinality() { 557 if (getTriggerSpecs() != null) { 558 return getTriggerSpecs().getTriggerDataCardinality(); 559 } 560 if (getTriggerData() != null) { 561 return getTriggerData().size(); 562 } 563 return mSourceType == SourceType.EVENT 564 ? PrivacyParams.EVENT_TRIGGER_DATA_CARDINALITY 565 : PrivacyParams.getNavigationTriggerDataCardinality(); 566 } 567 568 /** 569 * @return the list of trigger data 570 */ 571 @Nullable getTriggerData()572 public Set<UnsignedLong> getTriggerData() { 573 return mTriggerData; 574 } 575 576 /** 577 * @return the list of attributed triggers 578 */ 579 @Nullable getAttributedTriggers()580 public List<AttributedTrigger> getAttributedTriggers() { 581 return mAttributedTriggers; 582 } 583 584 /** 585 * @return all the attributed trigger IDs 586 */ getAttributedTriggerIds()587 public List<String> getAttributedTriggerIds() { 588 List<String> result = new ArrayList<>(); 589 for (AttributedTrigger attributedTrigger : mAttributedTriggers) { 590 result.add(attributedTrigger.getTriggerId()); 591 } 592 return result; 593 } 594 595 /** 596 * @return the JSON encoded current trigger status 597 */ 598 @NonNull attributedTriggersToJson()599 public String attributedTriggersToJson() { 600 JSONArray jsonArray = new JSONArray(); 601 for (AttributedTrigger trigger : mAttributedTriggers) { 602 jsonArray.put(trigger.encodeToJson()); 603 } 604 return jsonArray.toString(); 605 } 606 607 /** 608 * @return the JSON encoded current trigger status 609 */ 610 @NonNull attributedTriggersToJsonFlexApi()611 public String attributedTriggersToJsonFlexApi() { 612 JSONArray jsonArray = new JSONArray(); 613 for (AttributedTrigger trigger : mAttributedTriggers) { 614 jsonArray.put(trigger.encodeToJsonFlexApi()); 615 } 616 return jsonArray.toString(); 617 } 618 619 /** 620 * @return the flex event trigger specification 621 */ 622 @Nullable getTriggerSpecs()623 public TriggerSpecs getTriggerSpecs() { 624 return mTriggerSpecs; 625 } 626 627 @Override equals(Object obj)628 public boolean equals(Object obj) { 629 if (!(obj instanceof Source)) { 630 return false; 631 } 632 Source source = (Source) obj; 633 return Objects.equals(mPublisher, source.mPublisher) 634 && mPublisherType == source.mPublisherType 635 && areEqualNullableDestinations(mAppDestinations, source.mAppDestinations) 636 && areEqualNullableDestinations(mWebDestinations, source.mWebDestinations) 637 && Objects.equals(mEnrollmentId, source.mEnrollmentId) 638 && mPriority == source.mPriority 639 && mStatus == source.mStatus 640 && mExpiryTime == source.mExpiryTime 641 && Objects.equals(mEventReportWindow, source.mEventReportWindow) 642 && Objects.equals(mEventReportWindows, source.mEventReportWindows) 643 && Objects.equals(mAggregatableReportWindow, source.mAggregatableReportWindow) 644 && mEventTime == source.mEventTime 645 && mReinstallReattributionWindow == source.mReinstallReattributionWindow 646 && mAdIdPermission == source.mAdIdPermission 647 && mArDebugPermission == source.mArDebugPermission 648 && Objects.equals(mEventId, source.mEventId) 649 && Objects.equals(mDebugKey, source.mDebugKey) 650 && mSourceType == source.mSourceType 651 && Objects.equals(mEventReportDedupKeys, source.mEventReportDedupKeys) 652 && Objects.equals(mAggregateReportDedupKeys, source.mAggregateReportDedupKeys) 653 && Objects.equals(mRegistrant, source.mRegistrant) 654 && mAttributionMode == source.mAttributionMode 655 && mIsDebugReporting == source.mIsDebugReporting 656 && Objects.equals(mFilterDataString, source.mFilterDataString) 657 && Objects.equals(mSharedFilterDataKeys, source.mSharedFilterDataKeys) 658 && Objects.equals(mAggregateSource, source.mAggregateSource) 659 && mAggregateContributions == source.mAggregateContributions 660 && Objects.equals( 661 mAggregatableAttributionSource, source.mAggregatableAttributionSource) 662 && Objects.equals(mRegistrationId, source.mRegistrationId) 663 && Objects.equals(mSharedAggregationKeys, source.mSharedAggregationKeys) 664 && Objects.equals(mParentId, source.mParentId) 665 && Objects.equals(mInstallTime, source.mInstallTime) 666 && Objects.equals(mDebugJoinKey, source.mDebugJoinKey) 667 && Objects.equals(mPlatformAdId, source.mPlatformAdId) 668 && Objects.equals(mDebugAdId, source.mDebugAdId) 669 && Objects.equals(mRegistrationOrigin, source.mRegistrationOrigin) 670 && mCoarseEventReportDestinations == source.mCoarseEventReportDestinations 671 && Objects.equals(mTriggerData, source.mTriggerData) 672 && Objects.equals(mAttributedTriggers, source.mAttributedTriggers) 673 && Objects.equals(mTriggerSpecs, source.mTriggerSpecs) 674 && Objects.equals(mTriggerSpecsString, source.mTriggerSpecsString) 675 && Objects.equals(mMaxEventLevelReports, source.mMaxEventLevelReports) 676 && Objects.equals( 677 mEventAttributionStatusString, source.mEventAttributionStatusString) 678 && Objects.equals(mPrivacyParametersString, source.mPrivacyParametersString) 679 && Objects.equals(mTriggerDataMatching, source.mTriggerDataMatching) 680 && Objects.equals(mSharedDebugKey, source.mSharedDebugKey) 681 && mDropSourceIfInstalled == source.mDropSourceIfInstalled 682 && Objects.equals(mAttributionScopes, source.mAttributionScopes) 683 && Objects.equals(mAttributionScopeLimit, source.mAttributionScopeLimit) 684 && Objects.equals(mMaxEventStates, source.mMaxEventStates) 685 && mDestinationLimitPriority == source.mDestinationLimitPriority 686 && Objects.equals(mDestinationLimitAlgorithm, source.mDestinationLimitAlgorithm) 687 && Objects.equals(mEventLevelEpsilon, source.mEventLevelEpsilon) 688 && Objects.equals( 689 mAggregateDebugReportingString, source.mAggregateDebugReportingString) 690 && mAggregateDebugReportContributions == source.mAggregateDebugReportContributions 691 && Objects.equals(mAggregatableNamedBudgets, source.mAggregatableNamedBudgets); 692 } 693 694 @Override hashCode()695 public int hashCode() { 696 return Objects.hash( 697 mId, 698 mPublisher, 699 mPublisherType, 700 mAppDestinations, 701 mWebDestinations, 702 mEnrollmentId, 703 mPriority, 704 mStatus, 705 mExpiryTime, 706 mEventReportWindow, 707 mEventReportWindows, 708 mAggregatableReportWindow, 709 mReinstallReattributionWindow, 710 mEventTime, 711 mEventId, 712 mSourceType, 713 mEventReportDedupKeys, 714 mAggregateReportDedupKeys, 715 mFilterDataString, 716 mSharedFilterDataKeys, 717 mAggregateSource, 718 mAggregateContributions, 719 mAggregatableAttributionSource, 720 mDebugKey, 721 mAdIdPermission, 722 mArDebugPermission, 723 mRegistrationId, 724 mSharedAggregationKeys, 725 mInstallTime, 726 mDebugJoinKey, 727 mPlatformAdId, 728 mDebugAdId, 729 mRegistrationOrigin, 730 mDebugJoinKey, 731 mTriggerData, 732 mAttributedTriggers, 733 mTriggerSpecs, 734 mTriggerSpecsString, 735 mTriggerDataMatching, 736 mMaxEventLevelReports, 737 mEventAttributionStatusString, 738 mPrivacyParametersString, 739 mCoarseEventReportDestinations, 740 mSharedDebugKey, 741 mDropSourceIfInstalled, 742 mAttributionScopes, 743 mAttributionScopeLimit, 744 mMaxEventStates, 745 mDestinationLimitPriority, 746 mDestinationLimitAlgorithm, 747 mEventLevelEpsilon, 748 mAggregateDebugReportingString, 749 mAggregateDebugReportContributions, 750 mAggregatableNamedBudgets); 751 } 752 setAttributionMode(@ttributionMode int attributionMode)753 public void setAttributionMode(@AttributionMode int attributionMode) { 754 mAttributionMode = attributionMode; 755 } 756 757 /** 758 * Retrieve the attribution destinations corresponding to their destination type. 759 * 760 * @return a list of Uris. 761 */ getAttributionDestinations(@ventSurfaceType int destinationType)762 public List<Uri> getAttributionDestinations(@EventSurfaceType int destinationType) { 763 return destinationType == EventSurfaceType.APP ? mAppDestinations : mWebDestinations; 764 } 765 766 /** 767 * Unique identifier for the {@link Source}. 768 */ getId()769 public String getId() { 770 return mId; 771 } 772 773 /** 774 * Identifier provided by the registrant. 775 */ getEventId()776 public UnsignedLong getEventId() { 777 return mEventId; 778 } 779 780 /** 781 * Priority of the {@link Source}. 782 */ getPriority()783 public long getPriority() { 784 return mPriority; 785 } 786 787 /** 788 * Ad Tech enrollment ID 789 */ getEnrollmentId()790 public String getEnrollmentId() { 791 return mEnrollmentId; 792 } 793 794 /** Uri which registered the {@link Source}. */ getPublisher()795 public Uri getPublisher() { 796 return mPublisher; 797 } 798 799 /** The publisher type (e.g., app or web) {@link Source}. */ 800 @EventSurfaceType getPublisherType()801 public int getPublisherType() { 802 return mPublisherType; 803 } 804 805 /** Uris for the {@link Trigger}'s app destinations. */ 806 @Nullable getAppDestinations()807 public List<Uri> getAppDestinations() { 808 return mAppDestinations; 809 } 810 811 /** Uris for the {@link Trigger}'s web destinations. */ 812 @Nullable getWebDestinations()813 public List<Uri> getWebDestinations() { 814 return mWebDestinations; 815 } 816 817 /** Returns combined list of web and app attribution destinations. */ getAllAttributionDestinations()818 public List<Pair<Integer, String>> getAllAttributionDestinations() { 819 List<Pair<Integer, String>> destinations = new ArrayList<>(); 820 if (hasAppDestinations()) { 821 for (Uri appDestination : getAppDestinations()) { 822 destinations.add(Pair.create(EventSurfaceType.APP, appDestination.toString())); 823 } 824 } 825 if (hasWebDestinations()) { 826 for (Uri webDestination : getWebDestinations()) { 827 destinations.add(Pair.create(EventSurfaceType.WEB, webDestination.toString())); 828 } 829 } 830 return destinations; 831 } 832 833 /** 834 * Type of {@link Source}. Values: Event, Navigation. 835 */ getSourceType()836 public SourceType getSourceType() { 837 return mSourceType; 838 } 839 840 /** Time when {@link Source} will expire. */ getExpiryTime()841 public long getExpiryTime() { 842 return mExpiryTime; 843 } 844 845 /** Returns Event report window */ getEventReportWindow()846 public Long getEventReportWindow() { 847 return mEventReportWindow; 848 } 849 850 /** Returns reinstall reattribution window */ getReinstallReattributionWindow()851 public long getReinstallReattributionWindow() { 852 return mReinstallReattributionWindow; 853 } 854 855 /** 856 * Time when {@link Source} event report window will expire. (Appends the Event Time to window) 857 */ getEffectiveEventReportWindow()858 public long getEffectiveEventReportWindow() { 859 if (mEventReportWindow == null) { 860 return getExpiryTime(); 861 } 862 // TODO(b/290098169): Cleanup after a few releases 863 // Handling cases where ReportWindow is already stored as mEventTime + mEventReportWindow 864 if (mEventReportWindow > mEventTime) { 865 return mEventReportWindow; 866 } else { 867 return mEventTime + mEventReportWindow; 868 } 869 } 870 871 /** JSON string for event report windows */ getEventReportWindows()872 public String getEventReportWindows() { 873 return mEventReportWindows; 874 } 875 876 /** Time when {@link Source} aggregate report window will expire. */ getAggregatableReportWindow()877 public long getAggregatableReportWindow() { 878 return mAggregatableReportWindow; 879 } 880 881 /** Debug key of {@link Source}. */ 882 @Nullable getDebugKey()883 public UnsignedLong getDebugKey() { 884 return mDebugKey; 885 } 886 887 /** 888 * Time the event occurred. 889 */ getEventTime()890 public long getEventTime() { 891 return mEventTime; 892 } 893 894 /** Is Ad ID Permission Enabled. */ hasAdIdPermission()895 public boolean hasAdIdPermission() { 896 return mAdIdPermission; 897 } 898 899 /** Is Ar Debug Permission Enabled. */ hasArDebugPermission()900 public boolean hasArDebugPermission() { 901 return mArDebugPermission; 902 } 903 904 /** List of dedup keys for the attributed {@link Trigger}. */ getEventReportDedupKeys()905 public List<UnsignedLong> getEventReportDedupKeys() { 906 return mEventReportDedupKeys; 907 } 908 909 /** List of dedup keys used for generating Aggregate Reports. */ getAggregateReportDedupKeys()910 public List<UnsignedLong> getAggregateReportDedupKeys() { 911 return mAggregateReportDedupKeys; 912 } 913 914 /** Current status of the {@link Source}. */ 915 @Status getStatus()916 public int getStatus() { 917 return mStatus; 918 } 919 920 /** 921 * Registrant of this source, primarily an App. 922 */ getRegistrant()923 public Uri getRegistrant() { 924 return mRegistrant; 925 } 926 927 /** Selected mode for attribution. Values: Truthfully, Never, Falsely. */ 928 @AttributionMode getAttributionMode()929 public int getAttributionMode() { 930 return mAttributionMode; 931 } 932 933 /** Specification for trigger matching behaviour. Values: Modulus, Exact. */ getTriggerDataMatching()934 public TriggerDataMatching getTriggerDataMatching() { 935 return mTriggerDataMatching; 936 } 937 938 /** 939 * Attribution window for install events. 940 */ getInstallAttributionWindow()941 public long getInstallAttributionWindow() { 942 return mInstallAttributionWindow; 943 } 944 945 /** 946 * Cooldown for attributing post-install {@link Trigger} events. 947 */ getInstallCooldownWindow()948 public long getInstallCooldownWindow() { 949 return mInstallCooldownWindow; 950 } 951 952 /** Check if install detection is enabled for the source. */ isInstallDetectionEnabled()953 public boolean isInstallDetectionEnabled() { 954 return getInstallCooldownWindow() > 0 && hasAppDestinations(); 955 } 956 957 /** 958 * Is an App-install attributed to the {@link Source}. 959 */ isInstallAttributed()960 public boolean isInstallAttributed() { 961 return mIsInstallAttributed; 962 } 963 964 /** Is Ad Tech Opt-in to Debug Reporting {@link Source}. */ isDebugReporting()965 public boolean isDebugReporting() { 966 return mIsDebugReporting; 967 } 968 969 /** 970 * Check whether the parameter of flexible event API is valid or not. Currently, only max 971 * information gain is check because of the computation is complicated. Other straightforward 972 * value errors will be show in the debug log using LogUtil 973 * 974 * @return whether the parameters of flexible are valid 975 */ 976 @VisibleForTesting isFlexEventApiValueValid(Flags flags)977 public boolean isFlexEventApiValueValid(Flags flags) { 978 return mTriggerSpecs.getInformationGain(this, flags) <= getInformationGainThreshold(flags); 979 } 980 981 /** 982 * Returns aggregate filter data string used for aggregation. aggregate filter data json is a 983 * JSONObject in Attribution-Reporting-Register-Source header. Example: 984 * Attribution-Reporting-Register-Source: { // some other fields. "filter_data" : { 985 * "conversion_subdomain": ["electronics.megastore"], "product": ["1234", "2345"], "ctid": 986 * ["id"], ...... } } 987 */ getFilterDataString()988 public String getFilterDataString() { 989 return mFilterDataString; 990 } 991 992 /** 993 * Returns the shared filter data keys of the source as a unique list of strings. Example: 994 * ["click_duration", "campaign_type"] 995 */ 996 @Nullable getSharedFilterDataKeys()997 public String getSharedFilterDataKeys() { 998 return mSharedFilterDataKeys; 999 } 1000 1001 /** Returns the epsilon value set by source. */ 1002 @Nullable getEventLevelEpsilon()1003 public Double getEventLevelEpsilon() { 1004 return mEventLevelEpsilon; 1005 } 1006 1007 /** 1008 * Returns aggregate source string used for aggregation. aggregate source json is a JSONArray. 1009 * Example: [{ // Generates a "0x159" key piece (low order bits of the key) named // 1010 * "campaignCounts" "id": "campaignCounts", "key_piece": "0x159", // User saw ad from campaign 1011 * 345 (out of 511) }, { // Generates a "0x5" key piece (low order bits of the key) named 1012 * "geoValue" "id": "geoValue", // Source-side geo region = 5 (US), out of a possible ~100 1013 * regions. "key_piece": "0x5", }] 1014 */ getAggregateSource()1015 public String getAggregateSource() { 1016 return mAggregateSource; 1017 } 1018 1019 /** 1020 * Returns the current sum of values the source contributed to aggregatable reports. 1021 */ getAggregateContributions()1022 public int getAggregateContributions() { 1023 return mAggregateContributions; 1024 } 1025 1026 /** 1027 * Returns the AggregatableAttributionSource object, which is constructed using the aggregate 1028 * source string and aggregate filter data string in Source. 1029 */ getAggregatableAttributionSource( @onNull Trigger trigger, Flags flags)1030 public Optional<AggregatableAttributionSource> getAggregatableAttributionSource( 1031 @NonNull Trigger trigger, Flags flags) throws JSONException { 1032 return flags.getMeasurementEnableLookbackWindowFilter() 1033 ? getAggregatableAttributionSourceV2(trigger) 1034 : getAggregatableAttributionSource(); 1035 } 1036 getAggregatableAttributionSource()1037 private Optional<AggregatableAttributionSource> getAggregatableAttributionSource() 1038 throws JSONException { 1039 if (mAggregatableAttributionSource == null) { 1040 if (mAggregateSource == null) { 1041 mAggregatableAttributionSource = Optional.empty(); 1042 return mAggregatableAttributionSource; 1043 } 1044 JSONObject jsonObject = new JSONObject(mAggregateSource); 1045 TreeMap<String, BigInteger> aggregateSourceMap = new TreeMap<>(); 1046 Iterator<String> keys = jsonObject.keys(); 1047 while (keys.hasNext()) { 1048 String key = keys.next(); 1049 // Remove "0x" prefix. 1050 String hexString = jsonObject.getString(key).substring(2); 1051 BigInteger bigInteger = new BigInteger(hexString, 16); 1052 aggregateSourceMap.put(key, bigInteger); 1053 } 1054 AggregatableAttributionSource aggregatableAttributionSource = 1055 new AggregatableAttributionSource.Builder() 1056 .setAggregatableSource(aggregateSourceMap) 1057 .setFilterMap(getFilterData()) 1058 .build(); 1059 mAggregatableAttributionSource = Optional.of(aggregatableAttributionSource); 1060 } 1061 1062 return mAggregatableAttributionSource; 1063 } 1064 getAggregatableAttributionSourceV2( @onNull Trigger trigger)1065 private Optional<AggregatableAttributionSource> getAggregatableAttributionSourceV2( 1066 @NonNull Trigger trigger) throws JSONException { 1067 if (mAggregateSource == null) { 1068 return Optional.empty(); 1069 } 1070 JSONObject jsonObject = new JSONObject(mAggregateSource); 1071 TreeMap<String, BigInteger> aggregateSourceMap = new TreeMap<>(); 1072 for (String key : jsonObject.keySet()) { 1073 // Remove "0x" prefix. 1074 String hexString = jsonObject.getString(key).substring(2); 1075 BigInteger bigInteger = new BigInteger(hexString, 16); 1076 aggregateSourceMap.put(key, bigInteger); 1077 } 1078 return Optional.of( 1079 new AggregatableAttributionSource.Builder() 1080 .setAggregatableSource(aggregateSourceMap) 1081 .setFilterMap(getFilterData(trigger)) 1082 .build()); 1083 } 1084 1085 /** Returns the registration id. */ 1086 @Nullable getRegistrationId()1087 public String getRegistrationId() { 1088 return mRegistrationId; 1089 } 1090 1091 /** 1092 * Returns the shared aggregation keys of the source as a unique list of strings. Example: 1093 * [“campaignCounts”] 1094 */ 1095 @Nullable getSharedAggregationKeys()1096 public String getSharedAggregationKeys() { 1097 return mSharedAggregationKeys; 1098 } 1099 1100 /** Returns the install time of the source which is the same value as event time. */ 1101 @Nullable getInstallTime()1102 public Long getInstallTime() { 1103 return mInstallTime; 1104 } 1105 1106 /** 1107 * Returns join key that should be matched with trigger's join key at the time of generating 1108 * reports. 1109 */ 1110 @Nullable getDebugJoinKey()1111 public String getDebugJoinKey() { 1112 return mDebugJoinKey; 1113 } 1114 1115 /** 1116 * Returns actual platform AdID from getAdId() on app source registration, to be matched with a 1117 * web trigger's {@link Trigger#getDebugAdId()} value at the time of generating reports. 1118 */ 1119 @Nullable getPlatformAdId()1120 public String getPlatformAdId() { 1121 return mPlatformAdId; 1122 } 1123 1124 /** 1125 * Returns SHA256 hash of AdID from registration response on web registration concatenated with 1126 * enrollment ID, to be matched with an app trigger's {@link Trigger#getPlatformAdId()} value at 1127 * the time of generating reports. 1128 */ 1129 @Nullable getDebugAdId()1130 public String getDebugAdId() { 1131 return mDebugAdId; 1132 } 1133 1134 /** 1135 * Indicates whether event report for this source should be generated with the destinations 1136 * where the conversion occurred or merge app and web destinations. Set to true of both app and 1137 * web destination should be merged into the array of event report. 1138 */ hasCoarseEventReportDestinations()1139 public boolean hasCoarseEventReportDestinations() { 1140 return mCoarseEventReportDestinations; 1141 } 1142 1143 /** Returns registration origin used to register the source */ getRegistrationOrigin()1144 public Uri getRegistrationOrigin() { 1145 return mRegistrationOrigin; 1146 } 1147 1148 /** Returns trigger specs */ getTriggerSpecsString()1149 public String getTriggerSpecsString() { 1150 return mTriggerSpecsString; 1151 } 1152 1153 /** 1154 * Returns the number of report states for the source (used only for computation and not 1155 * stored in the datastore) 1156 */ getNumStates(Flags flags)1157 private Long getNumStates(Flags flags) { 1158 if (mNumStates == null) { 1159 validateAndSetNumReportStates(flags); 1160 } 1161 return mNumStates; 1162 } 1163 1164 /** Returns flip probability (used only for computation and not stored in the datastore) */ getFlipProbability(Flags flags)1165 public Double getFlipProbability(Flags flags) { 1166 if (mFlipProbability == null) { 1167 buildPrivacyParameters(flags); 1168 } 1169 return mFlipProbability; 1170 } 1171 1172 /** Returns max bucket increments */ getMaxEventLevelReports()1173 public Integer getMaxEventLevelReports() { 1174 return mMaxEventLevelReports; 1175 } 1176 1177 /** 1178 * Returns the RBR provided or default value for max_event_level_reports 1179 * 1180 * @param sourceType Source's Type 1181 * @param maxEventLevelReports RBR parsed value for max_event_level_reports 1182 * @param flags Flag values 1183 */ 1184 @NonNull getOrDefaultMaxEventLevelReports( @onNull SourceType sourceType, @Nullable Integer maxEventLevelReports, @NonNull Flags flags)1185 public static Integer getOrDefaultMaxEventLevelReports( 1186 @NonNull SourceType sourceType, 1187 @Nullable Integer maxEventLevelReports, 1188 @NonNull Flags flags) { 1189 if (maxEventLevelReports == null) { 1190 return sourceType == Source.SourceType.NAVIGATION 1191 ? PrivacyParams.NAVIGATION_SOURCE_MAX_REPORTS 1192 : flags.getMeasurementVtcConfigurableMaxEventReportsCount(); 1193 } 1194 return maxEventLevelReports; 1195 } 1196 1197 /** Returns event attribution status of current source */ getEventAttributionStatus()1198 public String getEventAttributionStatus() { 1199 return mEventAttributionStatusString; 1200 } 1201 1202 /** Returns privacy parameters */ getPrivacyParameters()1203 public String getPrivacyParameters() { 1204 return mPrivacyParametersString; 1205 } 1206 1207 /** See {@link Source#getAppDestinations()} */ setAppDestinations(@ullable List<Uri> appDestinations)1208 public void setAppDestinations(@Nullable List<Uri> appDestinations) { 1209 mAppDestinations = appDestinations; 1210 } 1211 1212 /** See {@link Source#getWebDestinations()} */ setWebDestinations(@ullable List<Uri> webDestinations)1213 public void setWebDestinations(@Nullable List<Uri> webDestinations) { 1214 mWebDestinations = webDestinations; 1215 } 1216 1217 /** Set app install attribution to the {@link Source}. */ setInstallAttributed(boolean isInstallAttributed)1218 public void setInstallAttributed(boolean isInstallAttributed) { 1219 mIsInstallAttributed = isInstallAttributed; 1220 } 1221 1222 /** Set the number of report states for the {@link Source}. */ setNumStates(long numStates)1223 private void setNumStates(long numStates) { 1224 mNumStates = numStates; 1225 } 1226 1227 /** Set flip probability for the {@link Source}. */ setFlipProbability(double flipProbability)1228 private void setFlipProbability(double flipProbability) { 1229 mFlipProbability = flipProbability; 1230 } 1231 1232 /** 1233 * @return if it's a derived source, returns the ID of the source it was created from. If it is 1234 * null, it is an original source. 1235 */ 1236 @Nullable getParentId()1237 public String getParentId() { 1238 return mParentId; 1239 } 1240 1241 /** 1242 * Set the status. 1243 */ setStatus(@tatus int status)1244 public void setStatus(@Status int status) { 1245 mStatus = status; 1246 } 1247 1248 /** 1249 * Set the aggregate contributions value. 1250 */ setAggregateContributions(int aggregateContributions)1251 public void setAggregateContributions(int aggregateContributions) { 1252 mAggregateContributions = aggregateContributions; 1253 } 1254 1255 /** Set the aggregate debug contributions value. */ setAggregateDebugContributions(int aggregateDebugContributions)1256 public void setAggregateDebugContributions(int aggregateDebugContributions) { 1257 mAggregateDebugReportContributions = aggregateDebugContributions; 1258 } 1259 1260 /** 1261 * Generates AggregatableFilterData from aggregate filter string in Source, including entries 1262 * for source type and duration from source to trigger if lookback window filter is enabled. 1263 */ getFilterData(@onNull Trigger trigger, Flags flags)1264 public FilterMap getFilterData(@NonNull Trigger trigger, Flags flags) throws JSONException { 1265 return flags.getMeasurementEnableLookbackWindowFilter() 1266 ? getFilterData(trigger) 1267 : getFilterData(); 1268 } 1269 getFilterData()1270 private FilterMap getFilterData() throws JSONException { 1271 if (mFilterData != null) { 1272 return mFilterData; 1273 } 1274 1275 if (mFilterDataString == null || mFilterDataString.isEmpty()) { 1276 mFilterData = new FilterMap.Builder().build(); 1277 } else { 1278 mFilterData = 1279 new FilterMap.Builder() 1280 .buildFilterData(new JSONObject(mFilterDataString)) 1281 .build(); 1282 } 1283 mFilterData 1284 .getAttributionFilterMap() 1285 .put("source_type", Collections.singletonList(mSourceType.getValue())); 1286 return mFilterData; 1287 } 1288 getFilterData(@onNull Trigger trigger)1289 private FilterMap getFilterData(@NonNull Trigger trigger) throws JSONException { 1290 FilterMap.Builder builder = new FilterMap.Builder(); 1291 if (mFilterDataString != null && !mFilterDataString.isEmpty()) { 1292 builder.buildFilterDataV2(new JSONObject(mFilterDataString)); 1293 } 1294 builder.addStringListValue("source_type", Collections.singletonList(mSourceType.getValue())) 1295 .addLongValue( 1296 FilterMap.LOOKBACK_WINDOW, 1297 TimeUnit.MILLISECONDS.toSeconds(trigger.getTriggerTime() - mEventTime)); 1298 return builder.build(); 1299 } 1300 extractSharedFilterMapFromJson(Map<String, V> attributionFilterMap)1301 private <V> Map<String, V> extractSharedFilterMapFromJson(Map<String, V> attributionFilterMap) 1302 throws JSONException { 1303 Map<String, V> sharedAttributionFilterMap = new HashMap<>(); 1304 JSONArray sharedFilterDataKeysArray = new JSONArray(mSharedFilterDataKeys); 1305 for (int i = 0; i < sharedFilterDataKeysArray.length(); ++i) { 1306 String filterKey = sharedFilterDataKeysArray.getString(i); 1307 if (attributionFilterMap.containsKey(filterKey)) { 1308 sharedAttributionFilterMap.put(filterKey, attributionFilterMap.get(filterKey)); 1309 } 1310 } 1311 return sharedAttributionFilterMap; 1312 } 1313 1314 /** 1315 * Generates AggregatableFilterData from aggregate filter string in Source, including entries 1316 * for source type and duration from source to trigger if lookback window filter is enabled. 1317 */ getSharedFilterData(@onNull Trigger trigger, Flags flags)1318 public FilterMap getSharedFilterData(@NonNull Trigger trigger, Flags flags) 1319 throws JSONException { 1320 FilterMap filterMap = getFilterData(trigger, flags); 1321 if (mSharedFilterDataKeys == null) { 1322 return filterMap; 1323 } 1324 if (flags.getMeasurementEnableLookbackWindowFilter()) { 1325 return new FilterMap.Builder() 1326 .setAttributionFilterMapWithLongValue( 1327 extractSharedFilterMapFromJson( 1328 filterMap.getAttributionFilterMapWithLongValue())) 1329 .build(); 1330 } else { 1331 return new FilterMap.Builder() 1332 .setAttributionFilterMap( 1333 extractSharedFilterMapFromJson(filterMap.getAttributionFilterMap())) 1334 .build(); 1335 } 1336 } 1337 1338 @Nullable getSharedDebugKey()1339 public UnsignedLong getSharedDebugKey() { 1340 return mSharedDebugKey; 1341 } 1342 1343 /** Returns true if the source should be dropped when the app is already installed. */ shouldDropSourceIfInstalled()1344 public boolean shouldDropSourceIfInstalled() { 1345 return mDropSourceIfInstalled; 1346 } 1347 1348 /** Returns true if the source has app destination(s), false otherwise. */ hasAppDestinations()1349 public boolean hasAppDestinations() { 1350 return mAppDestinations != null && mAppDestinations.size() > 0; 1351 } 1352 1353 /** Returns true if the source has web destination(s), false otherwise. */ hasWebDestinations()1354 public boolean hasWebDestinations() { 1355 return mWebDestinations != null && mWebDestinations.size() > 0; 1356 } 1357 areEqualNullableDestinations( List<Uri> destinations, List<Uri> otherDestinations)1358 private static boolean areEqualNullableDestinations( 1359 List<Uri> destinations, List<Uri> otherDestinations) { 1360 if (destinations == null && otherDestinations == null) { 1361 return true; 1362 } else if (destinations == null || otherDestinations == null) { 1363 return false; 1364 } else { 1365 return ImmutableMultiset.copyOf(destinations) 1366 .equals(ImmutableMultiset.copyOf(otherDestinations)); 1367 } 1368 } 1369 1370 /** Parses the event attribution status string. */ 1371 @VisibleForTesting parseEventAttributionStatus()1372 public void parseEventAttributionStatus() throws JSONException { 1373 JSONArray eventAttributionStatus = new JSONArray(mEventAttributionStatusString); 1374 for (int i = 0; i < eventAttributionStatus.length(); i++) { 1375 JSONObject json = eventAttributionStatus.getJSONObject(i); 1376 mAttributedTriggers.add(new AttributedTrigger(json)); 1377 } 1378 } 1379 1380 /** Build the attributed triggers list from the raw string */ buildAttributedTriggers()1381 public void buildAttributedTriggers() throws JSONException { 1382 if (mAttributedTriggers == null) { 1383 mAttributedTriggers = new ArrayList<>(); 1384 if (mEventAttributionStatusString != null && !mEventAttributionStatusString.isEmpty()) { 1385 parseEventAttributionStatus(); 1386 } 1387 } 1388 } 1389 1390 /** Build the trigger specs from the raw string */ buildTriggerSpecs()1391 public void buildTriggerSpecs() throws JSONException { 1392 buildAttributedTriggers(); 1393 if (mTriggerSpecs == null) { 1394 mTriggerSpecs = 1395 new TriggerSpecs( 1396 mTriggerSpecsString, 1397 getOrDefaultMaxEventLevelReports( 1398 mSourceType, mMaxEventLevelReports, FlagsFactory.getFlags()), 1399 this, 1400 mPrivacyParametersString); 1401 } 1402 } 1403 1404 /** Returns the attribution scopes attached to the source. */ 1405 @Nullable getAttributionScopes()1406 public List<String> getAttributionScopes() { 1407 return mAttributionScopes; 1408 } 1409 1410 /** Sets the attribution scopes. */ setAttributionScopes(@ullable List<String> attributionScopes)1411 public void setAttributionScopes(@Nullable List<String> attributionScopes) { 1412 mAttributionScopes = attributionScopes; 1413 } 1414 1415 /** Sets the aggregatable named budgets. */ setAggregatableNamedBudgets( @ullable AggregatableNamedBudgets aggregatableNamedBudgets)1416 public void setAggregatableNamedBudgets( 1417 @Nullable AggregatableNamedBudgets aggregatableNamedBudgets) { 1418 mAggregatableNamedBudgets = aggregatableNamedBudgets; 1419 } 1420 1421 /** Returns the attribution scope limit for the source. It should be positive. */ 1422 @Nullable getAttributionScopeLimit()1423 public Long getAttributionScopeLimit() { 1424 return mAttributionScopeLimit; 1425 } 1426 1427 /** Returns max number of event states. It should be positive. */ 1428 @Nullable getMaxEventStates()1429 public Long getMaxEventStates() { 1430 return mMaxEventStates; 1431 } 1432 1433 /** 1434 * Priority of app and web destinations on this source. An incoming or existing source is 1435 * rejected, if the long-term destination limit is exceeded, based on this value - higher values 1436 * are retained. 1437 */ getDestinationLimitPriority()1438 public long getDestinationLimitPriority() { 1439 return mDestinationLimitPriority; 1440 } 1441 1442 /** 1443 * Algorithm to use for long term destination limiting. FIFO - remove the lowest priority 1444 * source, LIFO - reject the incoming source. It does not need to be persisted in the database 1445 * as we need it only at the time of registration. 1446 */ 1447 @Nullable getDestinationLimitAlgorithm()1448 public DestinationLimitAlgorithm getDestinationLimitAlgorithm() { 1449 return mDestinationLimitAlgorithm; 1450 } 1451 1452 /** Returns the aggregate debug reporting object as a string */ 1453 @Nullable getAggregateDebugReportingString()1454 public String getAggregateDebugReportingString() { 1455 return mAggregateDebugReportingString; 1456 } 1457 1458 /** Returns the aggregate debug reporting object as a string */ 1459 @Nullable getAggregateDebugReportingObject()1460 public AggregateDebugReporting getAggregateDebugReportingObject() throws JSONException { 1461 if (mAggregateDebugReportingString == null) { 1462 return null; 1463 } 1464 if (mAggregateDebugReporting == null) { 1465 mAggregateDebugReporting = 1466 new AggregateDebugReporting.Builder( 1467 new JSONObject(mAggregateDebugReportingString)) 1468 .build(); 1469 } 1470 return mAggregateDebugReporting; 1471 } 1472 1473 /** Returns the aggregate debug reporting contributions */ getAggregateDebugReportContributions()1474 public int getAggregateDebugReportContributions() { 1475 return mAggregateDebugReportContributions; 1476 } 1477 1478 /** 1479 * @return the aggregatable named budgets object 1480 */ 1481 @Nullable getAggregatableNamedBudgets()1482 public AggregatableNamedBudgets getAggregatableNamedBudgets() { 1483 return mAggregatableNamedBudgets; 1484 } 1485 1486 /** Builder for {@link Source}. */ 1487 public static final class Builder { 1488 private final Source mBuilding; 1489 Builder()1490 public Builder() { 1491 mBuilding = new Source(); 1492 } 1493 1494 /** 1495 * Copy builder. 1496 * 1497 * @param copyFrom copy from source 1498 * @return copied source 1499 */ from(Source copyFrom)1500 public static Builder from(Source copyFrom) { 1501 Builder builder = new Builder(); 1502 builder.setId(copyFrom.mId); 1503 builder.setRegistrationId(copyFrom.mRegistrationId); 1504 builder.setAggregateSource(copyFrom.mAggregateSource); 1505 builder.setExpiryTime(copyFrom.mExpiryTime); 1506 builder.setAppDestinations(copyFrom.mAppDestinations); 1507 builder.setWebDestinations(copyFrom.mWebDestinations); 1508 builder.setSharedAggregationKeys(copyFrom.mSharedAggregationKeys); 1509 builder.setEventId(copyFrom.mEventId); 1510 builder.setRegistrant(copyFrom.mRegistrant); 1511 builder.setEventTime(copyFrom.mEventTime); 1512 builder.setPublisher(copyFrom.mPublisher); 1513 builder.setPublisherType(copyFrom.mPublisherType); 1514 builder.setInstallCooldownWindow(copyFrom.mInstallCooldownWindow); 1515 builder.setInstallAttributed(copyFrom.mIsInstallAttributed); 1516 builder.setInstallAttributionWindow(copyFrom.mInstallAttributionWindow); 1517 builder.setReinstallReattributionWindow(copyFrom.mReinstallReattributionWindow); 1518 builder.setSourceType(copyFrom.mSourceType); 1519 builder.setAdIdPermission(copyFrom.mAdIdPermission); 1520 builder.setAggregateContributions(copyFrom.mAggregateContributions); 1521 builder.setArDebugPermission(copyFrom.mArDebugPermission); 1522 builder.setAttributionMode(copyFrom.mAttributionMode); 1523 builder.setDebugKey(copyFrom.mDebugKey); 1524 builder.setEventReportDedupKeys(copyFrom.mEventReportDedupKeys); 1525 builder.setAggregateReportDedupKeys(copyFrom.mAggregateReportDedupKeys); 1526 builder.setEventReportWindow(copyFrom.mEventReportWindow); 1527 builder.setEventReportWindows(copyFrom.mEventReportWindows); 1528 builder.setMaxEventLevelReports(copyFrom.mMaxEventLevelReports); 1529 builder.setAggregatableReportWindow(copyFrom.mAggregatableReportWindow); 1530 builder.setEnrollmentId(copyFrom.mEnrollmentId); 1531 builder.setFilterDataString(copyFrom.mFilterDataString); 1532 builder.setSharedFilterDataKeys(copyFrom.mSharedFilterDataKeys); 1533 builder.setInstallTime(copyFrom.mInstallTime); 1534 builder.setIsDebugReporting(copyFrom.mIsDebugReporting); 1535 builder.setPriority(copyFrom.mPriority); 1536 builder.setStatus(copyFrom.mStatus); 1537 builder.setDebugJoinKey(copyFrom.mDebugJoinKey); 1538 builder.setPlatformAdId(copyFrom.mPlatformAdId); 1539 builder.setDebugAdId(copyFrom.mDebugAdId); 1540 builder.setRegistrationOrigin(copyFrom.mRegistrationOrigin); 1541 builder.setAttributedTriggers(copyFrom.mAttributedTriggers); 1542 builder.setTriggerSpecs(copyFrom.mTriggerSpecs); 1543 builder.setTriggerDataMatching(copyFrom.mTriggerDataMatching); 1544 builder.setTriggerData(copyFrom.mTriggerData); 1545 builder.setCoarseEventReportDestinations(copyFrom.mCoarseEventReportDestinations); 1546 builder.setSharedDebugKey(copyFrom.mSharedDebugKey); 1547 builder.setDropSourceIfInstalled(copyFrom.mDropSourceIfInstalled); 1548 builder.setAttributionScopes(copyFrom.mAttributionScopes); 1549 builder.setAttributionScopeLimit(copyFrom.mAttributionScopeLimit); 1550 builder.setMaxEventStates(copyFrom.mMaxEventStates); 1551 builder.setDestinationLimitPriority(copyFrom.mDestinationLimitPriority); 1552 builder.setDestinationLimitAlgorithm(copyFrom.mDestinationLimitAlgorithm); 1553 builder.setEventLevelEpsilon(copyFrom.mEventLevelEpsilon); 1554 builder.setAggregateDebugReportingString(copyFrom.mAggregateDebugReportingString); 1555 builder.setAggregateDebugReportContributions( 1556 copyFrom.mAggregateDebugReportContributions); 1557 builder.setAggregatableNamedBudgets(copyFrom.mAggregatableNamedBudgets); 1558 return builder; 1559 } 1560 1561 /** See {@link Source#getId()}. */ 1562 @NonNull setId(@onNull String id)1563 public Builder setId(@NonNull String id) { 1564 mBuilding.mId = id; 1565 return this; 1566 } 1567 1568 /** See {@link Source#getEventId()}. */ 1569 @NonNull setEventId(UnsignedLong eventId)1570 public Builder setEventId(UnsignedLong eventId) { 1571 mBuilding.mEventId = eventId; 1572 return this; 1573 } 1574 1575 /** See {@link Source#getPublisher()}. */ 1576 @NonNull setPublisher(@onNull Uri publisher)1577 public Builder setPublisher(@NonNull Uri publisher) { 1578 Validation.validateUri(publisher); 1579 mBuilding.mPublisher = publisher; 1580 return this; 1581 } 1582 1583 /** See {@link Source#getPublisherType()}. */ 1584 @NonNull setPublisherType(@ventSurfaceType int publisherType)1585 public Builder setPublisherType(@EventSurfaceType int publisherType) { 1586 mBuilding.mPublisherType = publisherType; 1587 return this; 1588 } 1589 1590 /** See {@link Source#getAppDestinations()}. */ 1591 @NonNull setAppDestinations(@ullable List<Uri> appDestinations)1592 public Builder setAppDestinations(@Nullable List<Uri> appDestinations) { 1593 Optional.ofNullable(appDestinations).ifPresent(uris -> { 1594 Validation.validateNotEmpty(uris); 1595 if (uris.size() > 1) { 1596 throw new IllegalArgumentException("Received more than one app destination"); 1597 } 1598 Validation.validateUri(uris.toArray(new Uri[0])); 1599 }); 1600 mBuilding.mAppDestinations = appDestinations; 1601 return this; 1602 } 1603 1604 /** See {@link Source#getWebDestinations()}. */ 1605 @NonNull setWebDestinations(@ullable List<Uri> webDestinations)1606 public Builder setWebDestinations(@Nullable List<Uri> webDestinations) { 1607 Optional.ofNullable(webDestinations).ifPresent(uris -> { 1608 Validation.validateNotEmpty(uris); 1609 Validation.validateUri(uris.toArray(new Uri[0])); 1610 }); 1611 mBuilding.mWebDestinations = webDestinations; 1612 return this; 1613 } 1614 1615 /** See {@link Source#getEnrollmentId()}. */ 1616 @NonNull setEnrollmentId(@onNull String enrollmentId)1617 public Builder setEnrollmentId(@NonNull String enrollmentId) { 1618 mBuilding.mEnrollmentId = enrollmentId; 1619 return this; 1620 } 1621 1622 /** See {@link Source#hasAdIdPermission()} */ setAdIdPermission(boolean adIdPermission)1623 public Source.Builder setAdIdPermission(boolean adIdPermission) { 1624 mBuilding.mAdIdPermission = adIdPermission; 1625 return this; 1626 } 1627 1628 /** See {@link Source#hasArDebugPermission()} */ setArDebugPermission(boolean arDebugPermission)1629 public Source.Builder setArDebugPermission(boolean arDebugPermission) { 1630 mBuilding.mArDebugPermission = arDebugPermission; 1631 return this; 1632 } 1633 1634 /** See {@link Source#getEventId()}. */ 1635 @NonNull setEventTime(long eventTime)1636 public Builder setEventTime(long eventTime) { 1637 mBuilding.mEventTime = eventTime; 1638 return this; 1639 } 1640 1641 /** 1642 * See {@link Source#getExpiryTime()}. 1643 */ setExpiryTime(long expiryTime)1644 public Builder setExpiryTime(long expiryTime) { 1645 mBuilding.mExpiryTime = expiryTime; 1646 return this; 1647 } 1648 1649 /** See {@link Source#getEventReportWindow()}. */ setEventReportWindow(Long eventReportWindow)1650 public Builder setEventReportWindow(Long eventReportWindow) { 1651 mBuilding.mEventReportWindow = eventReportWindow; 1652 return this; 1653 } 1654 1655 /** See {@link Source#getEventReportWindows()} ()}. */ setEventReportWindows(String eventReportWindows)1656 public Builder setEventReportWindows(String eventReportWindows) { 1657 mBuilding.mEventReportWindows = eventReportWindows; 1658 return this; 1659 } 1660 1661 /** See {@link Source#getAggregatableReportWindow()}. */ setAggregatableReportWindow(Long aggregateReportWindow)1662 public Builder setAggregatableReportWindow(Long aggregateReportWindow) { 1663 mBuilding.mAggregatableReportWindow = aggregateReportWindow; 1664 return this; 1665 } 1666 1667 /** See {@link Source#getReinstallReattributionWindow()}. */ setReinstallReattributionWindow(Long reinstallReattributionWindow)1668 public Builder setReinstallReattributionWindow(Long reinstallReattributionWindow) { 1669 mBuilding.mReinstallReattributionWindow = reinstallReattributionWindow; 1670 return this; 1671 } 1672 1673 /** See {@link Source#getPriority()}. */ 1674 @NonNull setPriority(long priority)1675 public Builder setPriority(long priority) { 1676 mBuilding.mPriority = priority; 1677 return this; 1678 } 1679 1680 /** See {@link Source#getDebugKey()}. */ setDebugKey(@ullable UnsignedLong debugKey)1681 public Builder setDebugKey(@Nullable UnsignedLong debugKey) { 1682 mBuilding.mDebugKey = debugKey; 1683 return this; 1684 } 1685 1686 /** See {@link Source#isDebugReporting()}. */ setIsDebugReporting(boolean isDebugReporting)1687 public Builder setIsDebugReporting(boolean isDebugReporting) { 1688 mBuilding.mIsDebugReporting = isDebugReporting; 1689 return this; 1690 } 1691 1692 /** See {@link Source#getSourceType()}. */ 1693 @NonNull setSourceType(@onNull SourceType sourceType)1694 public Builder setSourceType(@NonNull SourceType sourceType) { 1695 Validation.validateNonNull(sourceType); 1696 mBuilding.mSourceType = sourceType; 1697 return this; 1698 } 1699 1700 /** See {@link Source#getEventReportDedupKeys()}. */ 1701 @NonNull setEventReportDedupKeys(@ullable List<UnsignedLong> mEventReportDedupKeys)1702 public Builder setEventReportDedupKeys(@Nullable List<UnsignedLong> mEventReportDedupKeys) { 1703 mBuilding.mEventReportDedupKeys = mEventReportDedupKeys; 1704 return this; 1705 } 1706 1707 /** See {@link Source#getAggregateReportDedupKeys()}. */ 1708 @NonNull setAggregateReportDedupKeys( @onNull List<UnsignedLong> mAggregateReportDedupKeys)1709 public Builder setAggregateReportDedupKeys( 1710 @NonNull List<UnsignedLong> mAggregateReportDedupKeys) { 1711 mBuilding.mAggregateReportDedupKeys = mAggregateReportDedupKeys; 1712 return this; 1713 } 1714 1715 /** See {@link Source#getStatus()}. */ 1716 @NonNull setStatus(@tatus int status)1717 public Builder setStatus(@Status int status) { 1718 mBuilding.mStatus = status; 1719 return this; 1720 } 1721 1722 /** See {@link Source#getRegistrant()} */ 1723 @NonNull setRegistrant(@onNull Uri registrant)1724 public Builder setRegistrant(@NonNull Uri registrant) { 1725 Validation.validateUri(registrant); 1726 mBuilding.mRegistrant = registrant; 1727 return this; 1728 } 1729 1730 /** See {@link Source#getAttributionMode()} */ 1731 @NonNull setAttributionMode(@ttributionMode int attributionMode)1732 public Builder setAttributionMode(@AttributionMode int attributionMode) { 1733 mBuilding.mAttributionMode = attributionMode; 1734 return this; 1735 } 1736 1737 /** See {@link Source#getTriggerDataMatching()} */ 1738 @NonNull setTriggerDataMatching(TriggerDataMatching triggerDataMatching)1739 public Builder setTriggerDataMatching(TriggerDataMatching triggerDataMatching) { 1740 mBuilding.mTriggerDataMatching = triggerDataMatching; 1741 return this; 1742 } 1743 1744 /** See {@link Source#getInstallAttributionWindow()} */ 1745 @NonNull setInstallAttributionWindow(long installAttributionWindow)1746 public Builder setInstallAttributionWindow(long installAttributionWindow) { 1747 mBuilding.mInstallAttributionWindow = installAttributionWindow; 1748 return this; 1749 } 1750 1751 /** See {@link Source#getInstallCooldownWindow()} */ 1752 @NonNull setInstallCooldownWindow(long installCooldownWindow)1753 public Builder setInstallCooldownWindow(long installCooldownWindow) { 1754 mBuilding.mInstallCooldownWindow = installCooldownWindow; 1755 return this; 1756 } 1757 1758 /** See {@link Source#isInstallAttributed()} */ 1759 @NonNull setInstallAttributed(boolean installAttributed)1760 public Builder setInstallAttributed(boolean installAttributed) { 1761 mBuilding.mIsInstallAttributed = installAttributed; 1762 return this; 1763 } 1764 1765 /** See {@link Source#getFilterDataString()}. */ setFilterDataString(@ullable String filterMap)1766 public Builder setFilterDataString(@Nullable String filterMap) { 1767 mBuilding.mFilterDataString = filterMap; 1768 return this; 1769 } 1770 1771 /** See {@link Source#getSharedFilterDataKeys()}. */ setSharedFilterDataKeys(@ullable String sharedFilterDataKeys)1772 public Builder setSharedFilterDataKeys(@Nullable String sharedFilterDataKeys) { 1773 mBuilding.mSharedFilterDataKeys = sharedFilterDataKeys; 1774 return this; 1775 } 1776 1777 /** See {@link Source#getEventLevelEpsilon()} ()}. */ setEventLevelEpsilon(@ullable Double eventLevelEpsilon)1778 public Builder setEventLevelEpsilon(@Nullable Double eventLevelEpsilon) { 1779 mBuilding.mEventLevelEpsilon = eventLevelEpsilon; 1780 return this; 1781 } 1782 1783 /** See {@link Source#getAggregateSource()} */ 1784 @NonNull setAggregateSource(@ullable String aggregateSource)1785 public Builder setAggregateSource(@Nullable String aggregateSource) { 1786 mBuilding.mAggregateSource = aggregateSource; 1787 return this; 1788 } 1789 1790 /** See {@link Source#getAggregateContributions()} */ 1791 @NonNull setAggregateContributions(int aggregateContributions)1792 public Builder setAggregateContributions(int aggregateContributions) { 1793 mBuilding.mAggregateContributions = aggregateContributions; 1794 return this; 1795 } 1796 1797 /** See {@link Source#getRegistrationId()} */ 1798 @NonNull setRegistrationId(@ullable String registrationId)1799 public Builder setRegistrationId(@Nullable String registrationId) { 1800 mBuilding.mRegistrationId = registrationId; 1801 return this; 1802 } 1803 1804 /** See {@link Source#getSharedAggregationKeys()} */ 1805 @NonNull setSharedAggregationKeys(@ullable String sharedAggregationKeys)1806 public Builder setSharedAggregationKeys(@Nullable String sharedAggregationKeys) { 1807 mBuilding.mSharedAggregationKeys = sharedAggregationKeys; 1808 return this; 1809 } 1810 1811 /** See {@link Source#getInstallTime()} */ 1812 @NonNull setInstallTime(@ullable Long installTime)1813 public Builder setInstallTime(@Nullable Long installTime) { 1814 mBuilding.mInstallTime = installTime; 1815 return this; 1816 } 1817 1818 /** See {@link Source#getParentId()} */ 1819 @NonNull setParentId(@ullable String parentId)1820 public Builder setParentId(@Nullable String parentId) { 1821 mBuilding.mParentId = parentId; 1822 return this; 1823 } 1824 1825 /** See {@link Source#getAggregatableAttributionSource()} */ 1826 @NonNull setAggregatableAttributionSource( @ullable AggregatableAttributionSource aggregatableAttributionSource)1827 public Builder setAggregatableAttributionSource( 1828 @Nullable AggregatableAttributionSource aggregatableAttributionSource) { 1829 mBuilding.mAggregatableAttributionSource = 1830 Optional.ofNullable(aggregatableAttributionSource); 1831 return this; 1832 } 1833 1834 /** See {@link Source#getDebugJoinKey()} */ 1835 @NonNull setDebugJoinKey(@ullable String debugJoinKey)1836 public Builder setDebugJoinKey(@Nullable String debugJoinKey) { 1837 mBuilding.mDebugJoinKey = debugJoinKey; 1838 return this; 1839 } 1840 1841 /** See {@link Source#getPlatformAdId()} */ 1842 @NonNull setPlatformAdId(@ullable String platformAdId)1843 public Builder setPlatformAdId(@Nullable String platformAdId) { 1844 mBuilding.mPlatformAdId = platformAdId; 1845 return this; 1846 } 1847 1848 /** See {@link Source#getDebugAdId()} */ 1849 @NonNull setDebugAdId(@ullable String debugAdId)1850 public Builder setDebugAdId(@Nullable String debugAdId) { 1851 mBuilding.mDebugAdId = debugAdId; 1852 return this; 1853 } 1854 1855 /** See {@link Source#getRegistrationOrigin()} ()} */ 1856 @NonNull setRegistrationOrigin(Uri registrationOrigin)1857 public Builder setRegistrationOrigin(Uri registrationOrigin) { 1858 mBuilding.mRegistrationOrigin = registrationOrigin; 1859 return this; 1860 } 1861 1862 /** See {@link Source#getTriggerData()} */ 1863 @NonNull setTriggerData(@onNull Set<UnsignedLong> triggerData)1864 public Builder setTriggerData(@NonNull Set<UnsignedLong> triggerData) { 1865 mBuilding.mTriggerData = triggerData; 1866 return this; 1867 } 1868 1869 /** See {@link Source#getAttributedTriggers()} */ 1870 @NonNull setAttributedTriggers(@onNull List<AttributedTrigger> attributedTriggers)1871 public Builder setAttributedTriggers(@NonNull List<AttributedTrigger> attributedTriggers) { 1872 mBuilding.mAttributedTriggers = attributedTriggers; 1873 return this; 1874 } 1875 1876 /** See {@link Source#getTriggerSpecs()} */ 1877 @NonNull setTriggerSpecs(@ullable TriggerSpecs triggerSpecs)1878 public Builder setTriggerSpecs(@Nullable TriggerSpecs triggerSpecs) { 1879 mBuilding.mTriggerSpecs = triggerSpecs; 1880 return this; 1881 } 1882 1883 /** See {@link Source#hasCoarseEventReportDestinations()} */ 1884 @NonNull setCoarseEventReportDestinations(boolean coarseEventReportDestinations)1885 public Builder setCoarseEventReportDestinations(boolean coarseEventReportDestinations) { 1886 mBuilding.mCoarseEventReportDestinations = coarseEventReportDestinations; 1887 return this; 1888 } 1889 1890 /** See {@link Source#getTriggerSpecsString()} */ 1891 @NonNull setTriggerSpecsString(@ullable String triggerSpecsString)1892 public Builder setTriggerSpecsString(@Nullable String triggerSpecsString) { 1893 mBuilding.mTriggerSpecsString = triggerSpecsString; 1894 return this; 1895 } 1896 1897 /** See {@link Source#getMaxEventLevelReports()} */ 1898 @NonNull setMaxEventLevelReports(@ullable Integer maxEventLevelReports)1899 public Builder setMaxEventLevelReports(@Nullable Integer maxEventLevelReports) { 1900 mBuilding.mMaxEventLevelReports = maxEventLevelReports; 1901 return this; 1902 } 1903 1904 /** See {@link Source#getEventAttributionStatus()} */ 1905 @NonNull setEventAttributionStatus(@ullable String eventAttributionStatus)1906 public Builder setEventAttributionStatus(@Nullable String eventAttributionStatus) { 1907 mBuilding.mEventAttributionStatusString = eventAttributionStatus; 1908 return this; 1909 } 1910 1911 /** See {@link Source#getPrivacyParameters()} */ 1912 @NonNull setPrivacyParameters(@ullable String privacyParameters)1913 public Builder setPrivacyParameters(@Nullable String privacyParameters) { 1914 mBuilding.mPrivacyParametersString = privacyParameters; 1915 return this; 1916 } 1917 1918 /** See {@link Source#getSharedDebugKey()}. */ 1919 @NonNull setSharedDebugKey(@ullable UnsignedLong sharedDebugKey)1920 public Builder setSharedDebugKey(@Nullable UnsignedLong sharedDebugKey) { 1921 mBuilding.mSharedDebugKey = sharedDebugKey; 1922 return this; 1923 } 1924 1925 /** See {@link Source#shouldDropSourceIfInstalled()}. */ 1926 @NonNull setDropSourceIfInstalled(boolean dropSourceIfInstalled)1927 public Builder setDropSourceIfInstalled(boolean dropSourceIfInstalled) { 1928 mBuilding.mDropSourceIfInstalled = dropSourceIfInstalled; 1929 return this; 1930 } 1931 1932 /** See {@link Source#getAttributionScopes()}. */ 1933 @NonNull setAttributionScopes(@ullable List<String> attributionScopes)1934 public Builder setAttributionScopes(@Nullable List<String> attributionScopes) { 1935 mBuilding.mAttributionScopes = attributionScopes; 1936 return this; 1937 } 1938 1939 /** See {@link Source#getAttributionScopeLimit()}. */ 1940 @NonNull setAttributionScopeLimit(@ullable Long attributionScopeLimit)1941 public Builder setAttributionScopeLimit(@Nullable Long attributionScopeLimit) { 1942 mBuilding.mAttributionScopeLimit = attributionScopeLimit; 1943 return this; 1944 } 1945 1946 /** See {@link Source#getMaxEventStates()}. */ 1947 @NonNull setMaxEventStates(@ullable Long maxEventStates)1948 public Builder setMaxEventStates(@Nullable Long maxEventStates) { 1949 mBuilding.mMaxEventStates = maxEventStates; 1950 return this; 1951 } 1952 1953 /** See {@link Source#getDestinationLimitPriority()}. */ 1954 @NonNull setDestinationLimitPriority(long destinationLimitPriority)1955 public Builder setDestinationLimitPriority(long destinationLimitPriority) { 1956 mBuilding.mDestinationLimitPriority = destinationLimitPriority; 1957 return this; 1958 } 1959 1960 /** See {@link Source#getDestinationLimitAlgorithm()}. */ 1961 @NonNull setDestinationLimitAlgorithm( @ullable DestinationLimitAlgorithm destinationLimitAlgorithm)1962 public Builder setDestinationLimitAlgorithm( 1963 @Nullable DestinationLimitAlgorithm destinationLimitAlgorithm) { 1964 mBuilding.mDestinationLimitAlgorithm = destinationLimitAlgorithm; 1965 return this; 1966 } 1967 1968 /** See {@link Source#getAggregateDebugReportingString()}. */ 1969 @NonNull setAggregateDebugReportingString( @ullable String aggregateDebugReportingString)1970 public Builder setAggregateDebugReportingString( 1971 @Nullable String aggregateDebugReportingString) { 1972 mBuilding.mAggregateDebugReportingString = aggregateDebugReportingString; 1973 return this; 1974 } 1975 1976 /** See {@link Source#getAggregateDebugReportContributions()}. */ 1977 @NonNull setAggregateDebugReportContributions( int aggregateDebugReportingContributions)1978 public Builder setAggregateDebugReportContributions( 1979 int aggregateDebugReportingContributions) { 1980 mBuilding.mAggregateDebugReportContributions = aggregateDebugReportingContributions; 1981 return this; 1982 } 1983 1984 /** See {@link Source#getAggregatableNamedBudgets()}. */ 1985 @NonNull setAggregatableNamedBudgets( @ullable AggregatableNamedBudgets aggregatableNamedBudgets)1986 public Builder setAggregatableNamedBudgets( 1987 @Nullable AggregatableNamedBudgets aggregatableNamedBudgets) { 1988 mBuilding.mAggregatableNamedBudgets = aggregatableNamedBudgets; 1989 return this; 1990 } 1991 1992 /** Build the {@link Source}. */ 1993 @NonNull build()1994 public Source build() { 1995 Validation.validateNonNull( 1996 mBuilding.mPublisher, 1997 mBuilding.mEnrollmentId, 1998 mBuilding.mRegistrant, 1999 mBuilding.mSourceType, 2000 mBuilding.mAggregateReportDedupKeys, 2001 mBuilding.mEventReportDedupKeys, 2002 mBuilding.mRegistrationOrigin); 2003 2004 return mBuilding; 2005 } 2006 } 2007 } 2008