• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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