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