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 
24 import com.android.adservices.service.Flags;
25 import com.android.adservices.service.common.WebAddresses;
26 import com.android.adservices.service.measurement.aggregation.AggregatableAttributionTrigger;
27 import com.android.adservices.service.measurement.aggregation.AggregateDeduplicationKey;
28 import com.android.adservices.service.measurement.aggregation.AggregateReport;
29 import com.android.adservices.service.measurement.aggregation.AggregateTriggerData;
30 import com.android.adservices.service.measurement.util.Filter;
31 import com.android.adservices.service.measurement.util.UnsignedLong;
32 import com.android.adservices.service.measurement.util.Validation;
33 
34 import org.json.JSONArray;
35 import org.json.JSONException;
36 import org.json.JSONObject;
37 
38 import java.lang.annotation.Retention;
39 import java.lang.annotation.RetentionPolicy;
40 import java.math.BigInteger;
41 import java.util.ArrayList;
42 import java.util.HashMap;
43 import java.util.HashSet;
44 import java.util.Iterator;
45 import java.util.List;
46 import java.util.Map;
47 import java.util.Objects;
48 import java.util.Optional;
49 import java.util.Set;
50 
51 /** POJO for Trigger. */
52 public class Trigger {
53 
54     private String mId;
55     private Uri mAttributionDestination;
56     @EventSurfaceType private int mDestinationType;
57     private String mEnrollmentId;
58     private long mTriggerTime;
59     private @NonNull String mEventTriggers;
60     @Status private int mStatus;
61     private Uri mRegistrant;
62     private String mAggregateTriggerData;
63     private String mAggregateValues;
64     private String mAggregateDeduplicationKeys;
65     private boolean mIsDebugReporting;
66     private Optional<AggregatableAttributionTrigger> mAggregatableAttributionTrigger;
67     private String mFilters;
68     private String mNotFilters;
69     @Nullable private UnsignedLong mDebugKey;
70     private boolean mAdIdPermission;
71     private boolean mArDebugPermission;
72     @Nullable private String mAttributionConfig;
73     @Nullable private String mAdtechKeyMapping;
74     @Nullable private String mDebugJoinKey;
75     @Nullable private String mPlatformAdId;
76     @Nullable private String mDebugAdId;
77     private Uri mRegistrationOrigin;
78     @Nullable private Uri mAggregationCoordinatorOrigin;
79     private SourceRegistrationTimeConfig mAggregatableSourceRegistrationTimeConfig;
80     @Nullable private String mTriggerContextId;
81     @Nullable private String mAttributionScopesString;
82 
83     @IntDef(value = {Status.PENDING, Status.IGNORED, Status.ATTRIBUTED, Status.MARKED_TO_DELETE})
84     @Retention(RetentionPolicy.SOURCE)
85     public @interface Status {
86         int PENDING = 0;
87         int IGNORED = 1;
88         int ATTRIBUTED = 2;
89         int MARKED_TO_DELETE = 3;
90     }
91 
92     public enum SourceRegistrationTimeConfig {
93         INCLUDE,
94         EXCLUDE
95     }
96 
Trigger()97     private Trigger() {
98         mStatus = Status.PENDING;
99         // Making this default explicit since it anyway occur on an uninitialised int field.
100         mDestinationType = EventSurfaceType.APP;
101         mIsDebugReporting = false;
102     }
103 
104     @Override
equals(Object obj)105     public boolean equals(Object obj) {
106         if (!(obj instanceof Trigger)) {
107             return false;
108         }
109         Trigger trigger = (Trigger) obj;
110         return Objects.equals(mId, trigger.getId())
111                 && Objects.equals(mAttributionDestination, trigger.mAttributionDestination)
112                 && mDestinationType == trigger.mDestinationType
113                 && Objects.equals(mEnrollmentId, trigger.mEnrollmentId)
114                 && mTriggerTime == trigger.mTriggerTime
115                 && Objects.equals(mDebugKey, trigger.mDebugKey)
116                 && Objects.equals(mEventTriggers, trigger.mEventTriggers)
117                 && mStatus == trigger.mStatus
118                 && mIsDebugReporting == trigger.mIsDebugReporting
119                 && mAdIdPermission == trigger.mAdIdPermission
120                 && mArDebugPermission == trigger.mArDebugPermission
121                 && mAggregatableSourceRegistrationTimeConfig
122                         == trigger.mAggregatableSourceRegistrationTimeConfig
123                 && Objects.equals(mRegistrant, trigger.mRegistrant)
124                 && Objects.equals(mAggregateTriggerData, trigger.mAggregateTriggerData)
125                 && Objects.equals(mAggregateValues, trigger.mAggregateValues)
126                 && Objects.equals(
127                         mAggregatableAttributionTrigger, trigger.mAggregatableAttributionTrigger)
128                 && Objects.equals(mFilters, trigger.mFilters)
129                 && Objects.equals(mNotFilters, trigger.mNotFilters)
130                 && Objects.equals(mAttributionConfig, trigger.mAttributionConfig)
131                 && Objects.equals(mAdtechKeyMapping, trigger.mAdtechKeyMapping)
132                 && Objects.equals(mAggregateDeduplicationKeys, trigger.mAggregateDeduplicationKeys)
133                 && Objects.equals(mDebugJoinKey, trigger.mDebugJoinKey)
134                 && Objects.equals(mPlatformAdId, trigger.mPlatformAdId)
135                 && Objects.equals(mDebugAdId, trigger.mDebugAdId)
136                 && Objects.equals(mRegistrationOrigin, trigger.mRegistrationOrigin)
137                 && Objects.equals(mTriggerContextId, trigger.mTriggerContextId)
138                 && Objects.equals(mAttributionScopesString, trigger.mAttributionScopesString);
139     }
140 
141     @Override
hashCode()142     public int hashCode() {
143         return Objects.hash(
144                 mId,
145                 mAttributionDestination,
146                 mDestinationType,
147                 mEnrollmentId,
148                 mTriggerTime,
149                 mEventTriggers,
150                 mStatus,
151                 mAggregateTriggerData,
152                 mAggregateValues,
153                 mAggregatableAttributionTrigger,
154                 mFilters,
155                 mNotFilters,
156                 mDebugKey,
157                 mAdIdPermission,
158                 mArDebugPermission,
159                 mAttributionConfig,
160                 mAdtechKeyMapping,
161                 mAggregateDeduplicationKeys,
162                 mDebugJoinKey,
163                 mPlatformAdId,
164                 mDebugAdId,
165                 mRegistrationOrigin,
166                 mAggregatableSourceRegistrationTimeConfig,
167                 mTriggerContextId,
168                 mAttributionScopesString);
169     }
170 
171     /** Unique identifier for the {@link Trigger}. */
getId()172     public String getId() {
173         return mId;
174     }
175 
176     /**
177      * Destination where {@link Trigger} occurred.
178      */
getAttributionDestination()179     public Uri getAttributionDestination() {
180         return mAttributionDestination;
181     }
182 
183     /** Destination type of the {@link Trigger}. */
184     @EventSurfaceType
getDestinationType()185     public int getDestinationType() {
186         return mDestinationType;
187     }
188 
189     /**
190      * AdTech enrollment ID.
191      */
getEnrollmentId()192     public String getEnrollmentId() {
193         return mEnrollmentId;
194     }
195 
196     /**
197      * Time when the event occurred.
198      */
getTriggerTime()199     public long getTriggerTime() {
200         return mTriggerTime;
201     }
202 
203     /**
204      * Event triggers containing priority, de-dup key, trigger data and event-level filters info.
205      */
getEventTriggers()206     public String getEventTriggers() {
207         return mEventTriggers;
208     }
209 
210     /** Current state of the {@link Trigger}. */
211     @Status
getStatus()212     public int getStatus() {
213         return mStatus;
214     }
215 
216     /**
217      * Set the status.
218      */
setStatus(@tatus int status)219     public void setStatus(@Status int status) {
220         mStatus = status;
221     }
222 
223     /**
224      * Registrant of this trigger, primarily an App.
225      */
getRegistrant()226     public Uri getRegistrant() {
227         return mRegistrant;
228     }
229 
230     /**
231      * Returns aggregate trigger data string used for aggregation. aggregate trigger data json is a
232      * JSONArray. example: [ // Each dict independently adds pieces to multiple source keys. { //
233      * Conversion type purchase = 2 at a 9 bit key_offset, i.e. 2 << 9. // A 9 bit key_offset is
234      * needed because there are 511 possible campaigns, which // will take up 9 bits in the
235      * resulting key. "key_piece": "0x400", // Apply this key piece to: "source_keys":
236      * ["campaignCounts"] }, { // Purchase category shirts = 21 at a 7 bit key_offset, i.e. 21 << 7.
237      * // A 7 bit key_offset is needed because there are ~100 regions for the geo key, // which will
238      * take up 7 bits of space in the resulting key. "key_piece": "0xA80", // Apply this key piece
239      * to: "source_keys": ["geoValue", "nonMatchingKeyIdsAreIgnored"] } ]
240      */
getAggregateTriggerData()241     public String getAggregateTriggerData() {
242         return mAggregateTriggerData;
243     }
244 
245     /**
246      * Returns aggregate value string used for aggregation. aggregate value json is a JSONObject.
247      * example:
248      * {
249      *   "campaignCounts": 32768,
250      *   "geoValue": 1664
251      * }
252      */
getAggregateValues()253     public String getAggregateValues() {
254         return mAggregateValues;
255     }
256 
257     /**
258      * Returns a list of aggregate deduplication keys. aggregate deduplication key is a JSONObject.
259      * example: { "deduplication_key": "32768", "filters": [ {type: [filter_1, filter_2]} ],
260      * "not_filters": [ {type: [not_filter_1, not_filter_2]} ] }
261      */
getAggregateDeduplicationKeys()262     public String getAggregateDeduplicationKeys() {
263         return mAggregateDeduplicationKeys;
264     }
265 
266     /**
267      * Returns the AggregatableAttributionTrigger object, which is constructed using the aggregate
268      * trigger data string and aggregate values string in Trigger.
269      */
getAggregatableAttributionTrigger(Flags flags)270     public Optional<AggregatableAttributionTrigger> getAggregatableAttributionTrigger(Flags flags)
271             throws JSONException {
272         if (mAggregatableAttributionTrigger != null) {
273             return mAggregatableAttributionTrigger;
274         }
275 
276         mAggregatableAttributionTrigger = parseAggregateTrigger(flags);
277         return mAggregatableAttributionTrigger;
278     }
279 
280     /**
281      * Returns top level filters. The value is in json format.
282      *
283      * <p>Will be used for deciding if the trigger can be attributed to the source. If the source
284      * fails the filtering against these filters then no reports(event/aggregate) are generated.
285      * example: { "key1" : ["value11", "value12"], "key2" : ["value21", "value22"] }
286      */
getFilters()287     public String getFilters() {
288         return mFilters;
289     }
290 
291     /** Is Ad Tech Opt-in to Debug Reporting {@link Trigger}. */
isDebugReporting()292     public boolean isDebugReporting() {
293         return mIsDebugReporting;
294     }
295 
296     /** Is Ad ID Permission Enabled. */
hasAdIdPermission()297     public boolean hasAdIdPermission() {
298         return mAdIdPermission;
299     }
300 
301     /** Is Ar Debug Permission Enabled. */
hasArDebugPermission()302     public boolean hasArDebugPermission() {
303         return mArDebugPermission;
304     }
305 
306     /**
307      * Returns top level not-filters. The value is in json format.
308      */
getNotFilters()309     public String getNotFilters() {
310         return mNotFilters;
311     }
312 
313     /** Debug key of {@link Trigger}. */
314     @Nullable
getDebugKey()315     public UnsignedLong getDebugKey() {
316         return mDebugKey;
317     }
318 
319     /**
320      * Returns field attribution config JSONArray as String. example: [{ "source_network":
321      * "AdTech1-Ads", "source_priority_range": { “start”: 100, “end”: 1000 }, "source_filters": {
322      * "campaign_type": ["install"], "source_type": ["navigation"], }, "priority": "99", "expiry":
323      * "604800", "filter_data":{ "campaign_type": ["install"], } }]
324      */
325     @Nullable
getAttributionConfig()326     public String getAttributionConfig() {
327         return mAttributionConfig;
328     }
329 
330     /**
331      * Returns adtech bit mapping JSONObject as String. example: "x_network_key_mapping": {
332      * "AdTechA-enrollment_id": "0x1", "AdTechB-enrollment_id": "0x2", }
333      */
334     @Nullable
getAdtechKeyMapping()335     public String getAdtechKeyMapping() {
336         return mAdtechKeyMapping;
337     }
338 
339     /**
340      * Returns join key that should be matched with source's join key at the time of generating
341      * reports.
342      */
343     @Nullable
getDebugJoinKey()344     public String getDebugJoinKey() {
345         return mDebugJoinKey;
346     }
347 
348     /**
349      * Returns actual platform AdID from getAdId() on app trigger registration, to be matched with a
350      * web source's {@link Trigger#getDebugAdId()} value at the time of generating reports.
351      */
352     @Nullable
getPlatformAdId()353     public String getPlatformAdId() {
354         return mPlatformAdId;
355     }
356 
357     /**
358      * Returns SHA256 hash of AdID from registration response on web registration concatenated with
359      * enrollment ID, to be matched with an app source's {@link Source#getPlatformAdId()} value at
360      * the time of generating reports.
361      */
362     @Nullable
getDebugAdId()363     public String getDebugAdId() {
364         return mDebugAdId;
365     }
366 
367     /** Returns registration origin used to register the source */
getRegistrationOrigin()368     public Uri getRegistrationOrigin() {
369         return mRegistrationOrigin;
370     }
371 
372     /** Returns coordinator origin for aggregatable reports */
373     @Nullable
getAggregationCoordinatorOrigin()374     public Uri getAggregationCoordinatorOrigin() {
375         return mAggregationCoordinatorOrigin;
376     }
377 
378     /**
379      * Return {@link SourceRegistrationTimeConfig#EXCLUDE} if the {@link AggregateReport} should not
380      * include the attributed {@link Source} registration time during attribution reporting. Returns
381      * {@link SourceRegistrationTimeConfig#INCLUDE} otherwise.
382      */
getAggregatableSourceRegistrationTimeConfig()383     public SourceRegistrationTimeConfig getAggregatableSourceRegistrationTimeConfig() {
384         return mAggregatableSourceRegistrationTimeConfig;
385     }
386 
387     /** Returns the context id */
388     @Nullable
getTriggerContextId()389     public String getTriggerContextId() {
390         return mTriggerContextId;
391     }
392 
393     /**
394      * Generates AggregatableAttributionTrigger from aggregate trigger data string and aggregate
395      * values string in Trigger.
396      */
parseAggregateTrigger(Flags flags)397     private Optional<AggregatableAttributionTrigger> parseAggregateTrigger(Flags flags)
398             throws JSONException, NumberFormatException {
399         if (this.mAggregateValues == null) {
400             return Optional.empty();
401         }
402         JSONArray triggerDataArray = this.mAggregateTriggerData == null
403                 ? new JSONArray()
404                 : new JSONArray(this.mAggregateTriggerData);
405         List<AggregateTriggerData> triggerDataList = new ArrayList<>();
406         Filter filter = new Filter(flags);
407         for (int i = 0; i < triggerDataArray.length(); i++) {
408             JSONObject triggerDatum = triggerDataArray.getJSONObject(i);
409             // Remove "0x" prefix.
410             String hexString = triggerDatum.getString("key_piece").substring(2);
411             BigInteger bigInteger = new BigInteger(hexString, 16);
412             JSONArray sourceKeys = triggerDatum.getJSONArray("source_keys");
413             Set<String> sourceKeySet = new HashSet<>();
414             for (int j = 0; j < sourceKeys.length(); j++) {
415                 sourceKeySet.add(sourceKeys.getString(j));
416             }
417             AggregateTriggerData.Builder builder =
418                     new AggregateTriggerData.Builder()
419                             .setKey(bigInteger)
420                             .setSourceKeys(sourceKeySet);
421             if (triggerDatum.has("filters") && !triggerDatum.isNull("filters")) {
422                 List<FilterMap> filterSet =
423                         filter.deserializeFilterSet(triggerDatum.getJSONArray("filters"));
424                 builder.setFilterSet(filterSet);
425             }
426             if (triggerDatum.has("not_filters")
427                     && !triggerDatum.isNull("not_filters")) {
428                 List<FilterMap> notFilterSet =
429                         filter.deserializeFilterSet(triggerDatum.getJSONArray("not_filters"));
430                 builder.setNotFilterSet(notFilterSet);
431             }
432             if (!triggerDatum.isNull("x_network_data")) {
433                 JSONObject xNetworkDataJson = triggerDatum.getJSONObject("x_network_data");
434                 XNetworkData xNetworkData = new XNetworkData.Builder(xNetworkDataJson).build();
435                 builder.setXNetworkData(xNetworkData);
436             }
437             triggerDataList.add(builder.build());
438         }
439         JSONObject values = new JSONObject(this.mAggregateValues);
440         Map<String, Integer> valueMap = new HashMap<>();
441         for (String key : values.keySet()) {
442             valueMap.put(key, values.getInt(key));
443         }
444         List<AggregateDeduplicationKey> dedupKeyList = new ArrayList<>();
445         if (getAggregateDeduplicationKeys() != null) {
446             JSONArray dedupKeyObjects = new JSONArray(this.getAggregateDeduplicationKeys());
447             for (int i = 0; i < dedupKeyObjects.length(); i++) {
448                 JSONObject dedupKeyObject = dedupKeyObjects.getJSONObject(i);
449                 AggregateDeduplicationKey.Builder builder = new AggregateDeduplicationKey.Builder();
450                 if (dedupKeyObject.has("deduplication_key")
451                         && !dedupKeyObject.isNull("deduplication_key")) {
452                     builder.setDeduplicationKey(
453                             new UnsignedLong(dedupKeyObject.getString("deduplication_key")));
454                 }
455                 if (dedupKeyObject.has("filters") && !dedupKeyObject.isNull("filters")) {
456                     List<FilterMap> filterSet =
457                             filter.deserializeFilterSet(dedupKeyObject.getJSONArray("filters"));
458                     builder.setFilterSet(filterSet);
459                 }
460                 if (dedupKeyObject.has("not_filters") && !dedupKeyObject.isNull("not_filters")) {
461                     List<FilterMap> notFilterSet =
462                             filter.deserializeFilterSet(dedupKeyObject.getJSONArray("not_filters"));
463                     builder.setNotFilterSet(notFilterSet);
464                 }
465                 dedupKeyList.add(builder.build());
466             }
467         }
468         return Optional.of(
469                 new AggregatableAttributionTrigger.Builder()
470                         .setTriggerData(triggerDataList)
471                         .setValues(valueMap)
472                         .setAggregateDeduplicationKeys(dedupKeyList)
473                         .build());
474     }
475 
476     /**
477      * Parses the json array under {@link #mEventTriggers} to form a list of {@link EventTrigger}s.
478      *
479      * @return list of {@link EventTrigger}s
480      * @throws JSONException if JSON parsing fails
481      */
parseEventTriggers(Flags flags)482     public List<EventTrigger> parseEventTriggers(Flags flags) throws JSONException {
483         JSONArray jsonArray = new JSONArray(this.mEventTriggers);
484         List<EventTrigger> eventTriggers = new ArrayList<>();
485         boolean readValue = flags.getMeasurementFlexibleEventReportingApiEnabled();
486         for (int i = 0; i < jsonArray.length(); i++) {
487             JSONObject eventTrigger = jsonArray.getJSONObject(i);
488 
489             EventTrigger.Builder eventTriggerBuilder =
490                     new EventTrigger.Builder(
491                             new UnsignedLong(
492                                     eventTrigger.getString(
493                                             EventTriggerContract.TRIGGER_DATA)));
494 
495             if (!eventTrigger.isNull(EventTriggerContract.PRIORITY)) {
496                 eventTriggerBuilder.setTriggerPriority(
497                         eventTrigger.getLong(EventTriggerContract.PRIORITY));
498             }
499 
500             if (readValue && !eventTrigger.isNull(EventTriggerContract.VALUE)) {
501                 eventTriggerBuilder.setTriggerValue(
502                         eventTrigger.getLong(EventTriggerContract.VALUE));
503             } else {
504                 eventTriggerBuilder.setTriggerValue(1L);
505             }
506 
507             if (!eventTrigger.isNull(EventTriggerContract.DEDUPLICATION_KEY)) {
508                 eventTriggerBuilder.setDedupKey(new UnsignedLong(
509                         eventTrigger.getString(EventTriggerContract.DEDUPLICATION_KEY)));
510             }
511 
512             if (!eventTrigger.isNull(EventTriggerContract.FILTERS)) {
513                 List<FilterMap> filterSet =
514                         new Filter(flags)
515                                 .deserializeFilterSet(
516                                         eventTrigger.getJSONArray(EventTriggerContract.FILTERS));
517                 eventTriggerBuilder.setFilterSet(filterSet);
518             }
519 
520             if (!eventTrigger.isNull(EventTriggerContract.NOT_FILTERS)) {
521                 List<FilterMap> notFilterSet =
522                         new Filter(flags)
523                                 .deserializeFilterSet(
524                                         eventTrigger.getJSONArray(
525                                                 EventTriggerContract.NOT_FILTERS));
526                 eventTriggerBuilder.setNotFilterSet(notFilterSet);
527             }
528             eventTriggers.add(eventTriggerBuilder.build());
529         }
530 
531         return eventTriggers;
532     }
533 
534     /**
535      * Parses the json object under {@link #mAdtechKeyMapping} to create a mapping of adtechs to
536      * their bits.
537      *
538      * @return mapping of String to BigInteger
539      * @throws JSONException if JSON parsing fails
540      * @throws NumberFormatException if BigInteger parsing fails
541      */
542     @Nullable
parseAdtechKeyMapping()543     public Map<String, BigInteger> parseAdtechKeyMapping()
544             throws JSONException, NumberFormatException {
545         if (mAdtechKeyMapping == null) {
546             return null;
547         }
548         Map<String, BigInteger> adtechBitMapping = new HashMap<>();
549         JSONObject jsonObject = new JSONObject(mAdtechKeyMapping);
550         Iterator<String> keys = jsonObject.keys();
551         while (keys.hasNext()) {
552             String key = keys.next();
553             // Remove "0x" prefix.
554             String hexString = jsonObject.getString(key).substring(2);
555             BigInteger bigInteger = new BigInteger(hexString, 16);
556             adtechBitMapping.put(key, bigInteger);
557         }
558         return adtechBitMapping;
559     }
560 
561     /**
562      * Returns a {@code Uri} with scheme and (1) public suffix + 1 in case of a web destination, or
563      * (2) the Android package name in case of an app destination. Returns null if extracting the
564      * public suffix + 1 fails.
565      */
566     @Nullable
getAttributionDestinationBaseUri()567     public Uri getAttributionDestinationBaseUri() {
568         if (mDestinationType == EventSurfaceType.APP) {
569             return mAttributionDestination;
570         } else {
571             Optional<Uri> uri = WebAddresses.topPrivateDomainAndScheme(mAttributionDestination);
572             return uri.orElse(null);
573         }
574     }
575 
576     /** Returns attribution scope string for the trigger. */
577     @Nullable
getAttributionScopesString()578     public String getAttributionScopesString() {
579         return mAttributionScopesString;
580     }
581 
582     /** Returns attribution scopes for the trigger. */
583     @Nullable
getAttributionScopes()584     public List<String> getAttributionScopes() throws JSONException {
585         if (mAttributionScopesString == null) {
586             return null;
587         }
588         JSONArray jsonArray = new JSONArray(mAttributionScopesString);
589         List<String> attributionScopes = new ArrayList<>();
590         for (int i = 0; i < jsonArray.length(); ++i) {
591             attributionScopes.add(jsonArray.getString(i));
592         }
593         return attributionScopes;
594     }
595 
596     /** Builder for {@link Trigger}. */
597     public static final class Builder {
598 
599         private final Trigger mBuilding;
600 
Builder()601         public Builder() {
602             mBuilding = new Trigger();
603         }
604 
605         /** See {@link Trigger#getId()}. */
606         @NonNull
setId(String id)607         public Builder setId(String id) {
608             mBuilding.mId = id;
609             return this;
610         }
611 
612         /** See {@link Trigger#getAttributionDestination()}. */
613         @NonNull
setAttributionDestination(Uri attributionDestination)614         public Builder setAttributionDestination(Uri attributionDestination) {
615             Validation.validateUri(attributionDestination);
616             mBuilding.mAttributionDestination = attributionDestination;
617             return this;
618         }
619 
620         /** See {@link Trigger#getDestinationType()}. */
621         @NonNull
setDestinationType(@ventSurfaceType int destinationType)622         public Builder setDestinationType(@EventSurfaceType int destinationType) {
623             mBuilding.mDestinationType = destinationType;
624             return this;
625         }
626 
627         /** See {@link Trigger#getEnrollmentId()}. */
628         @NonNull
setEnrollmentId(String enrollmentId)629         public Builder setEnrollmentId(String enrollmentId) {
630             mBuilding.mEnrollmentId = enrollmentId;
631             return this;
632         }
633 
634         /** See {@link Trigger#getStatus()}. */
635         @NonNull
setStatus(@tatus int status)636         public Builder setStatus(@Status int status) {
637             mBuilding.mStatus = status;
638             return this;
639         }
640 
641         /** See {@link Trigger#getTriggerTime()}. */
642         @NonNull
setTriggerTime(long triggerTime)643         public Builder setTriggerTime(long triggerTime) {
644             mBuilding.mTriggerTime = triggerTime;
645             return this;
646         }
647 
648         /** See {@link Trigger#getEventTriggers()}. */
649         @NonNull
setEventTriggers(@onNull String eventTriggers)650         public Builder setEventTriggers(@NonNull String eventTriggers) {
651             Validation.validateNonNull(eventTriggers);
652             mBuilding.mEventTriggers = eventTriggers;
653             return this;
654         }
655 
656         /** See {@link Trigger#getRegistrant()} */
657         @NonNull
setRegistrant(@onNull Uri registrant)658         public Builder setRegistrant(@NonNull Uri registrant) {
659             Validation.validateUri(registrant);
660             mBuilding.mRegistrant = registrant;
661             return this;
662         }
663 
664         /** See {@link Trigger#getAggregateTriggerData()}. */
665         @NonNull
setAggregateTriggerData(@ullable String aggregateTriggerData)666         public Builder setAggregateTriggerData(@Nullable String aggregateTriggerData) {
667             mBuilding.mAggregateTriggerData = aggregateTriggerData;
668             return this;
669         }
670 
671         /** See {@link Trigger#getAggregateValues()} */
672         @NonNull
setAggregateValues(@ullable String aggregateValues)673         public Builder setAggregateValues(@Nullable String aggregateValues) {
674             mBuilding.mAggregateValues = aggregateValues;
675             return this;
676         }
677 
678         /** See {@link Trigger#getAggregateDeduplicationKeys()} */
679         @NonNull
setAggregateDeduplicationKeys(@onNull String aggregateDeduplicationKeys)680         public Builder setAggregateDeduplicationKeys(@NonNull String aggregateDeduplicationKeys) {
681             mBuilding.mAggregateDeduplicationKeys = aggregateDeduplicationKeys;
682             return this;
683         }
684 
685         /** See {@link Trigger#getFilters()} */
686         @NonNull
setFilters(@ullable String filters)687         public Builder setFilters(@Nullable String filters) {
688             mBuilding.mFilters = filters;
689             return this;
690         }
691 
692         /** See {@link Trigger#isDebugReporting()} */
setIsDebugReporting(boolean isDebugReporting)693         public Builder setIsDebugReporting(boolean isDebugReporting) {
694             mBuilding.mIsDebugReporting = isDebugReporting;
695             return this;
696         }
697 
698         /** See {@link Trigger#hasAdIdPermission()} */
setAdIdPermission(boolean adIdPermission)699         public Builder setAdIdPermission(boolean adIdPermission) {
700             mBuilding.mAdIdPermission = adIdPermission;
701             return this;
702         }
703 
704         /** See {@link Trigger#hasArDebugPermission()} */
setArDebugPermission(boolean arDebugPermission)705         public Builder setArDebugPermission(boolean arDebugPermission) {
706             mBuilding.mArDebugPermission = arDebugPermission;
707             return this;
708         }
709 
710         /** See {@link Trigger#getNotFilters()} */
711         @NonNull
setNotFilters(@ullable String notFilters)712         public Builder setNotFilters(@Nullable String notFilters) {
713             mBuilding.mNotFilters = notFilters;
714             return this;
715         }
716 
717         /** See {@link Trigger#getDebugKey()} */
setDebugKey(@ullable UnsignedLong debugKey)718         public Builder setDebugKey(@Nullable UnsignedLong debugKey) {
719             mBuilding.mDebugKey = debugKey;
720             return this;
721         }
722 
723         /** See {@link Trigger#getAttributionConfig()} */
setAttributionConfig(@ullable String attributionConfig)724         public Builder setAttributionConfig(@Nullable String attributionConfig) {
725             mBuilding.mAttributionConfig = attributionConfig;
726             return this;
727         }
728 
729         /** See {@link Trigger#getAdtechKeyMapping()} */
setAdtechBitMapping(@ullable String adtechBitMapping)730         public Builder setAdtechBitMapping(@Nullable String adtechBitMapping) {
731             mBuilding.mAdtechKeyMapping = adtechBitMapping;
732             return this;
733         }
734 
735         /** See {@link Trigger#getAggregatableAttributionTrigger()} */
736         @NonNull
setAggregatableAttributionTrigger( @ullable AggregatableAttributionTrigger aggregatableAttributionTrigger)737         public Builder setAggregatableAttributionTrigger(
738                 @Nullable AggregatableAttributionTrigger aggregatableAttributionTrigger) {
739             mBuilding.mAggregatableAttributionTrigger =
740                     Optional.ofNullable(aggregatableAttributionTrigger);
741             return this;
742         }
743 
744         /** See {@link Trigger#getDebugJoinKey()} */
745         @NonNull
setDebugJoinKey(@ullable String debugJoinKey)746         public Builder setDebugJoinKey(@Nullable String debugJoinKey) {
747             mBuilding.mDebugJoinKey = debugJoinKey;
748             return this;
749         }
750 
751         /** See {@link Trigger#getPlatformAdId()} */
752         @NonNull
setPlatformAdId(@ullable String platformAdId)753         public Builder setPlatformAdId(@Nullable String platformAdId) {
754             mBuilding.mPlatformAdId = platformAdId;
755             return this;
756         }
757 
758         /** See {@link Trigger#getDebugAdId()} */
759         @NonNull
setDebugAdId(@ullable String debugAdId)760         public Builder setDebugAdId(@Nullable String debugAdId) {
761             mBuilding.mDebugAdId = debugAdId;
762             return this;
763         }
764 
765         /** See {@link Trigger#getRegistrationOrigin()} */
766         @NonNull
setRegistrationOrigin(Uri registrationOrigin)767         public Builder setRegistrationOrigin(Uri registrationOrigin) {
768             mBuilding.mRegistrationOrigin = registrationOrigin;
769             return this;
770         }
771 
772         /** See {@link Trigger#getAggregationCoordinatorOrigin()} */
setAggregationCoordinatorOrigin(Uri aggregationCoordinatorOrigin)773         public Builder setAggregationCoordinatorOrigin(Uri aggregationCoordinatorOrigin) {
774             mBuilding.mAggregationCoordinatorOrigin = aggregationCoordinatorOrigin;
775             return this;
776         }
777 
778         /** See {@link Trigger#getAggregatableSourceRegistrationTimeConfig()}. */
779         @NonNull
setAggregatableSourceRegistrationTimeConfig( SourceRegistrationTimeConfig config)780         public Builder setAggregatableSourceRegistrationTimeConfig(
781                 SourceRegistrationTimeConfig config) {
782             mBuilding.mAggregatableSourceRegistrationTimeConfig = config;
783             return this;
784         }
785         /** See {@link Trigger#getTriggerContextId()}. */
setTriggerContextId(@ullable String triggerContextId)786         public Builder setTriggerContextId(@Nullable String triggerContextId) {
787             mBuilding.mTriggerContextId = triggerContextId;
788             return this;
789         }
790 
791         /** See {@link Trigger#getAttributionScopesString()}. */
792         @NonNull
setAttributionScopesString(@ullable String attributionScopesString)793         public Builder setAttributionScopesString(@Nullable String attributionScopesString) {
794             mBuilding.mAttributionScopesString = attributionScopesString;
795             return this;
796         }
797 
798         /** Build the {@link Trigger}. */
799         @NonNull
build()800         public Trigger build() {
801             Validation.validateNonNull(
802                     mBuilding.mAttributionDestination,
803                     mBuilding.mEnrollmentId,
804                     mBuilding.mRegistrant,
805                     mBuilding.mRegistrationOrigin,
806                     mBuilding.mAggregatableSourceRegistrationTimeConfig);
807 
808             return mBuilding;
809         }
810     }
811 
812     /** Event trigger field keys. */
813     public interface EventTriggerContract {
814         String TRIGGER_DATA = "trigger_data";
815         String PRIORITY = "priority";
816         String VALUE = "value";
817         String DEDUPLICATION_KEY = "deduplication_key";
818         String FILTERS = "filters";
819         String NOT_FILTERS = "not_filters";
820     }
821 }
822