• 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.net.Uri;
22 import android.util.Pair;
23 
24 import androidx.annotation.Nullable;
25 
26 import com.android.adservices.service.measurement.noising.SourceNoiseHandler;
27 import com.android.adservices.service.measurement.reporting.EventReportWindowCalcDelegate;
28 import com.android.adservices.service.measurement.util.UnsignedLong;
29 
30 import com.google.common.collect.ImmutableMultiset;
31 
32 import java.lang.annotation.Retention;
33 import java.lang.annotation.RetentionPolicy;
34 import java.util.ArrayList;
35 import java.util.List;
36 import java.util.Objects;
37 import java.util.UUID;
38 
39 /**
40  * POJO for EventReport.
41  */
42 public class EventReport {
43 
44     private String mId;
45     private UnsignedLong mSourceEventId;
46     private long mReportTime;
47     private long mTriggerTime;
48     private long mTriggerPriority;
49     private List<Uri> mAttributionDestinations;
50     private String mEnrollmentId;
51     private UnsignedLong mTriggerData;
52     private UnsignedLong mTriggerDedupKey;
53     private double mRandomizedTriggerRate;
54     private @Status int mStatus;
55     private @DebugReportStatus int mDebugReportStatus;
56     private Source.SourceType mSourceType;
57     @Nullable private UnsignedLong mSourceDebugKey;
58     @Nullable private UnsignedLong mTriggerDebugKey;
59     @NonNull private List<UnsignedLong> mTriggerDebugKeys;
60     private String mSourceId;
61     private String mTriggerId;
62     private Uri mRegistrationOrigin;
63     private long mTriggerValue;
64     private Pair<Long, Long> mTriggerSummaryBucket;
65 
66     @IntDef(value = {Status.PENDING, Status.DELIVERED, Status.MARKED_TO_DELETE})
67     @Retention(RetentionPolicy.SOURCE)
68     public @interface Status {
69         int PENDING = 0;
70         int DELIVERED = 1;
71         int MARKED_TO_DELETE = 2;
72     }
73 
74     @IntDef(
75             value = {
76                 DebugReportStatus.NONE,
77                 DebugReportStatus.PENDING,
78                 DebugReportStatus.DELIVERED,
79             })
80     @Retention(RetentionPolicy.SOURCE)
81     public @interface DebugReportStatus {
82         int NONE = 0;
83         int PENDING = 1;
84         int DELIVERED = 2;
85     }
86 
EventReport()87     private EventReport() {
88         mTriggerDedupKey = null;
89         mTriggerDebugKeys = new ArrayList<>();
90     }
91 
92     @Override
equals(Object obj)93     public boolean equals(Object obj) {
94         if (!(obj instanceof EventReport)) {
95             return false;
96         }
97         EventReport eventReport = (EventReport) obj;
98         return mStatus == eventReport.mStatus
99                 && mDebugReportStatus == eventReport.mDebugReportStatus
100                 && mReportTime == eventReport.mReportTime
101                 && Objects.equals(mAttributionDestinations, eventReport.mAttributionDestinations)
102                 && ImmutableMultiset.copyOf(mAttributionDestinations)
103                         .equals(ImmutableMultiset.copyOf(eventReport.mAttributionDestinations))
104                 && Objects.equals(mEnrollmentId, eventReport.mEnrollmentId)
105                 && mTriggerTime == eventReport.mTriggerTime
106                 && Objects.equals(mTriggerData, eventReport.mTriggerData)
107                 && Objects.equals(mSourceEventId, eventReport.mSourceEventId)
108                 && mTriggerPriority == eventReport.mTriggerPriority
109                 && Objects.equals(mTriggerDedupKey, eventReport.mTriggerDedupKey)
110                 && mSourceType == eventReport.mSourceType
111                 && mRandomizedTriggerRate == eventReport.mRandomizedTriggerRate
112                 && Objects.equals(mSourceDebugKey, eventReport.mSourceDebugKey)
113                 && Objects.equals(mTriggerDebugKey, eventReport.mTriggerDebugKey)
114                 && Objects.equals(mTriggerDebugKeys, eventReport.mTriggerDebugKeys)
115                 && Objects.equals(mSourceId, eventReport.mSourceId)
116                 && Objects.equals(mTriggerId, eventReport.mTriggerId)
117                 && Objects.equals(mRegistrationOrigin, eventReport.mRegistrationOrigin)
118                 && mTriggerValue == eventReport.mTriggerValue
119                 && Objects.equals(mTriggerSummaryBucket, eventReport.mTriggerSummaryBucket);
120     }
121 
122     @Override
hashCode()123     public int hashCode() {
124         return Objects.hash(
125                 mStatus,
126                 mDebugReportStatus,
127                 mReportTime,
128                 mAttributionDestinations,
129                 mEnrollmentId,
130                 mTriggerTime,
131                 mTriggerData,
132                 mSourceEventId,
133                 mTriggerPriority,
134                 mTriggerDedupKey,
135                 mSourceType,
136                 mRandomizedTriggerRate,
137                 mSourceDebugKey,
138                 mTriggerDebugKey,
139                 mTriggerDebugKeys,
140                 mSourceId,
141                 mTriggerId,
142                 mRegistrationOrigin,
143                 mTriggerValue,
144                 mTriggerSummaryBucket);
145     }
146 
147     /** Unique identifier for the report. */
getId()148     public String getId() {
149         return mId;
150     }
151 
152     /** Identifier of the associated {@link Source} event. */
getSourceEventId()153     public UnsignedLong getSourceEventId() {
154         return mSourceEventId;
155     }
156 
157     /**
158      * Scheduled time for the report to be sent.
159      */
getReportTime()160     public long getReportTime() {
161         return mReportTime;
162     }
163 
164     /**
165      * TriggerTime of the associated {@link Trigger}.
166      */
getTriggerTime()167     public long getTriggerTime() {
168         return mTriggerTime;
169     }
170 
171     /**
172      * Priority of the associated {@link Trigger}.
173      */
getTriggerPriority()174     public long getTriggerPriority() {
175         return mTriggerPriority;
176     }
177 
178     /**
179      * AttributionDestinations of the {@link Source} and {@link Trigger}.
180      */
getAttributionDestinations()181     public List<Uri> getAttributionDestinations() {
182         return mAttributionDestinations;
183     }
184 
185     /**
186      * Ad Tech enrollment ID.
187      */
getEnrollmentId()188     public String getEnrollmentId() {
189         return mEnrollmentId;
190     }
191 
192     /**
193      * Metadata for the report.
194      */
getTriggerData()195     public UnsignedLong getTriggerData() {
196         return mTriggerData;
197     }
198 
199     /**
200      * Deduplication key of the associated {@link Trigger}
201      */
getTriggerDedupKey()202     public UnsignedLong getTriggerDedupKey() {
203         return mTriggerDedupKey;
204     }
205 
206     /**
207      * Current {@link Status} of the report.
208      */
getStatus()209     public @Status int getStatus() {
210         return mStatus;
211     }
212 
213     /** Current {@link DebugReportStatus} of the report. */
getDebugReportStatus()214     public @DebugReportStatus int getDebugReportStatus() {
215         return mDebugReportStatus;
216     }
217 
218     /**
219      * SourceType of the event's source.
220      */
getSourceType()221     public Source.SourceType getSourceType() {
222         return mSourceType;
223     }
224 
225     /**
226      * Randomized trigger rate for noising
227      */
getRandomizedTriggerRate()228     public double getRandomizedTriggerRate() {
229         return mRandomizedTriggerRate;
230     }
231 
232     /** Source Debug Key */
233     @Nullable
getSourceDebugKey()234     public UnsignedLong getSourceDebugKey() {
235         return mSourceDebugKey;
236     }
237 
238     /** Trigger Debug Key */
239     @Nullable
getTriggerDebugKey()240     public UnsignedLong getTriggerDebugKey() {
241         return mTriggerDebugKey;
242     }
243 
244     /** Trigger Debug Keys */
245     @NonNull
getTriggerDebugKeys()246     public List<UnsignedLong> getTriggerDebugKeys() {
247         return mTriggerDebugKeys;
248     }
249 
250     /** Source ID */
getSourceId()251     public String getSourceId() {
252         return mSourceId;
253     }
254 
255     /** Trigger ID */
getTriggerId()256     public String getTriggerId() {
257         return mTriggerId;
258     }
259 
260     /** Trigger summary bucket */
getTriggerSummaryBucket()261     public Pair<Long, Long> getTriggerSummaryBucket() {
262         return mTriggerSummaryBucket;
263     }
264 
265     /** Returns registration origin used to register the source and trigger */
getRegistrationOrigin()266     public Uri getRegistrationOrigin() {
267         return mRegistrationOrigin;
268     }
269 
270     /** Trigger Value */
getTriggerValue()271     public long getTriggerValue() {
272         return mTriggerValue;
273     }
274 
275     /** Get Summary Bucket As String */
getStringEncodedTriggerSummaryBucket()276     public String getStringEncodedTriggerSummaryBucket() {
277         if (mTriggerSummaryBucket == null) {
278             return null;
279         } else {
280             return mTriggerSummaryBucket.first + "," + mTriggerSummaryBucket.second;
281         }
282     }
283 
284     /**
285      * Returns true if this EventReport is randomized.
286      * Randomized EventReports are not triggered by a specific event.
287      */
isRandomized()288     public boolean isRandomized() {
289         return mTriggerId == null;
290     }
291 
292     /** Builder for {@link EventReport} */
293     public static final class Builder {
294 
295         private final EventReport mBuilding;
296 
Builder()297         public Builder() {
298             mBuilding = new EventReport();
299         }
300 
301         /** See {@link EventReport#getId()} */
setId(String id)302         public Builder setId(String id) {
303             mBuilding.mId = id;
304             return this;
305         }
306 
307         /** See {@link EventReport#getSourceEventId()} */
setSourceEventId(UnsignedLong sourceEventId)308         public Builder setSourceEventId(UnsignedLong sourceEventId) {
309             mBuilding.mSourceEventId = sourceEventId;
310             return this;
311         }
312 
313         /** See {@link EventReport#getEnrollmentId()} */
setEnrollmentId(String enrollmentId)314         public Builder setEnrollmentId(String enrollmentId) {
315             mBuilding.mEnrollmentId = enrollmentId;
316             return this;
317         }
318 
319         /** See {@link EventReport#getAttributionDestinations()} */
setAttributionDestinations(List<Uri> attributionDestinations)320         public Builder setAttributionDestinations(List<Uri> attributionDestinations) {
321             mBuilding.mAttributionDestinations = attributionDestinations;
322             return this;
323         }
324 
325         /**
326          * See {@link EventReport#getTriggerTime()}
327          */
setTriggerTime(long triggerTime)328         public Builder setTriggerTime(long triggerTime) {
329             mBuilding.mTriggerTime = triggerTime;
330             return this;
331         }
332 
333         /**
334          * See {@link EventReport#getTriggerData()}
335          */
setTriggerData(UnsignedLong triggerData)336         public Builder setTriggerData(UnsignedLong triggerData) {
337             mBuilding.mTriggerData = triggerData;
338             return this;
339         }
340 
341         /**
342          * See {@link EventReport#getTriggerPriority()}
343          */
setTriggerPriority(long triggerPriority)344         public Builder setTriggerPriority(long triggerPriority) {
345             mBuilding.mTriggerPriority = triggerPriority;
346             return this;
347         }
348 
349         /**
350          * See {@link EventReport#getTriggerDedupKey()}
351          */
setTriggerDedupKey(UnsignedLong triggerDedupKey)352         public Builder setTriggerDedupKey(UnsignedLong triggerDedupKey) {
353             mBuilding.mTriggerDedupKey = triggerDedupKey;
354             return this;
355         }
356 
357         /**
358          * See {@link EventReport#getReportTime()}
359          */
setReportTime(long reportTime)360         public Builder setReportTime(long reportTime) {
361             mBuilding.mReportTime = reportTime;
362             return this;
363         }
364 
365         /**
366          * See {@link EventReport#getStatus()}
367          */
setStatus(@tatus int status)368         public Builder setStatus(@Status int status) {
369             mBuilding.mStatus = status;
370             return this;
371         }
372 
373         /** See {@link EventReport#getDebugReportStatus()}} */
setDebugReportStatus(@ebugReportStatus int debugReportStatus)374         public Builder setDebugReportStatus(@DebugReportStatus int debugReportStatus) {
375             mBuilding.mDebugReportStatus = debugReportStatus;
376             return this;
377         }
378 
379         /**
380          * See {@link EventReport#getSourceType()}
381          */
setSourceType(Source.SourceType sourceType)382         public Builder setSourceType(Source.SourceType sourceType) {
383             mBuilding.mSourceType = sourceType;
384             return this;
385         }
386 
387         /** See {@link EventReport#getRandomizedTriggerRate()}} */
setRandomizedTriggerRate(double randomizedTriggerRate)388         public Builder setRandomizedTriggerRate(double randomizedTriggerRate) {
389             mBuilding.mRandomizedTriggerRate = randomizedTriggerRate;
390             return this;
391         }
392 
393         /** See {@link EventReport#getSourceDebugKey()}} */
setSourceDebugKey(UnsignedLong sourceDebugKey)394         public Builder setSourceDebugKey(UnsignedLong sourceDebugKey) {
395             mBuilding.mSourceDebugKey = sourceDebugKey;
396             return this;
397         }
398 
399         /** See {@link EventReport#getTriggerDebugKey()}} */
setTriggerDebugKey(UnsignedLong triggerDebugKey)400         public Builder setTriggerDebugKey(UnsignedLong triggerDebugKey) {
401             mBuilding.mTriggerDebugKey = triggerDebugKey;
402             return this;
403         }
404 
405         /** See {@link EventReport#getTriggerDebugKeys()}} */
setTriggerDebugKeys(List<UnsignedLong> triggerDebugKeys)406         public Builder setTriggerDebugKeys(List<UnsignedLong> triggerDebugKeys) {
407             mBuilding.mTriggerDebugKeys = triggerDebugKeys;
408             return this;
409         }
410 
411         /** See {@link EventReport#getSourceId()} */
setSourceId(String sourceId)412         public Builder setSourceId(String sourceId) {
413             mBuilding.mSourceId = sourceId;
414             return this;
415         }
416 
417         /** See {@link EventReport#getTriggerId()} */
setTriggerId(String triggerId)418         public Builder setTriggerId(String triggerId) {
419             mBuilding.mTriggerId = triggerId;
420             return this;
421         }
422 
423         /**
424          * set the summary bucket from input DB text encode summary bucket
425          *
426          * @param summaryBucket the string encoded summary bucket
427          * @return builder
428          */
setTriggerSummaryBucket(@ullable String summaryBucket)429         public Builder setTriggerSummaryBucket(@Nullable String summaryBucket) {
430             if (summaryBucket == null || summaryBucket.isEmpty()) {
431                 mBuilding.mTriggerSummaryBucket = null;
432                 return this;
433             }
434             String[] numbers = summaryBucket.split(",");
435 
436             Long firstNumber = Long.parseLong(numbers[0].trim());
437             Long secondNumber = Long.parseLong(numbers[1].trim());
438             mBuilding.mTriggerSummaryBucket = new Pair<>(firstNumber, secondNumber);
439 
440             return this;
441         }
442 
443         /** See {@link EventReport#getTriggerSummaryBucket()} */
setTriggerSummaryBucket(@ullable Pair<Long, Long> summaryBucket)444         public Builder setTriggerSummaryBucket(@Nullable Pair<Long, Long> summaryBucket) {
445             mBuilding.mTriggerSummaryBucket = summaryBucket;
446             return this;
447         }
448 
449         /** See {@link EventReport#getTriggerId()} */
setTriggerValue(long triggerValue)450         public Builder setTriggerValue(long triggerValue) {
451             mBuilding.mTriggerValue = triggerValue;
452             return this;
453         }
454 
455         /** See {@link Source#getRegistrationOrigin()} ()} */
456         @NonNull
setRegistrationOrigin(Uri registrationOrigin)457         public Builder setRegistrationOrigin(Uri registrationOrigin) {
458             mBuilding.mRegistrationOrigin = registrationOrigin;
459             return this;
460         }
461 
462         // TODO (b/285607306): cleanup since this doesn't just do "populateFromSourceAndTrigger"
463         /** Populates fields using {@link Source}, {@link Trigger} and {@link EventTrigger}. */
populateFromSourceAndTrigger( @onNull Source source, @NonNull Trigger trigger, @NonNull UnsignedLong effectiveTriggerData, @NonNull EventTrigger eventTrigger, @NonNull Pair<UnsignedLong, UnsignedLong> debugKeyPair, @NonNull EventReportWindowCalcDelegate eventReportWindowCalcDelegate, @NonNull SourceNoiseHandler sourceNoiseHandler, List<Uri> eventReportDestinations)464         public Builder populateFromSourceAndTrigger(
465                 @NonNull Source source,
466                 @NonNull Trigger trigger,
467                 @NonNull UnsignedLong effectiveTriggerData,
468                 @NonNull EventTrigger eventTrigger,
469                 @NonNull Pair<UnsignedLong, UnsignedLong> debugKeyPair,
470                 @NonNull EventReportWindowCalcDelegate eventReportWindowCalcDelegate,
471                 @NonNull SourceNoiseHandler sourceNoiseHandler,
472                 List<Uri> eventReportDestinations) {
473             mBuilding.mId = UUID.randomUUID().toString();
474             mBuilding.mTriggerDedupKey = eventTrigger.getDedupKey();
475             mBuilding.mTriggerTime = trigger.getTriggerTime();
476             mBuilding.mSourceEventId = source.getEventId();
477             mBuilding.mEnrollmentId = source.getEnrollmentId();
478             mBuilding.mStatus = Status.PENDING;
479             mBuilding.mAttributionDestinations = eventReportDestinations;
480             mBuilding.mSourceType = source.getSourceType();
481             mBuilding.mSourceDebugKey = debugKeyPair.first;
482             mBuilding.mTriggerDebugKey = debugKeyPair.second;
483             mBuilding.mDebugReportStatus = DebugReportStatus.NONE;
484             if (mBuilding.mSourceDebugKey != null && mBuilding.mTriggerDebugKey != null) {
485                 mBuilding.mDebugReportStatus = DebugReportStatus.PENDING;
486             }
487             mBuilding.mSourceId = source.getId();
488             mBuilding.mTriggerId = trigger.getId();
489             mBuilding.mRegistrationOrigin = trigger.getRegistrationOrigin();
490             mBuilding.mTriggerPriority = eventTrigger.getTriggerPriority();
491             mBuilding.mTriggerData = effectiveTriggerData;
492             mBuilding.mReportTime =
493                     eventReportWindowCalcDelegate.getReportingTime(
494                             source, trigger.getTriggerTime(), trigger.getDestinationType());
495             mBuilding.mRandomizedTriggerRate =
496                     sourceNoiseHandler.getRandomizedTriggerRate(source);
497             return this;
498         }
499 
500         /** Provides event report builder for flexible event-level reports */
getForFlex( @onNull Source source, @NonNull Trigger trigger, @NonNull AttributedTrigger attributedTrigger, long reportTime, @NonNull Pair<Long, Long> triggerSummaryBucket, @Nullable UnsignedLong sourceDebugKey, @NonNull List<UnsignedLong> debugKeys, double flipProbability, List<Uri> eventReportDestinations)501         public Builder getForFlex(
502                 @NonNull Source source,
503                 @NonNull Trigger trigger,
504                 @NonNull AttributedTrigger attributedTrigger,
505                 long reportTime,
506                 @NonNull Pair<Long, Long> triggerSummaryBucket,
507                 @Nullable UnsignedLong sourceDebugKey,
508                 @NonNull List<UnsignedLong> debugKeys,
509                 double flipProbability,
510                 List<Uri> eventReportDestinations) {
511             mBuilding.mId = UUID.randomUUID().toString();
512             mBuilding.mTriggerTime = trigger.getTriggerTime();
513             mBuilding.mSourceEventId = source.getEventId();
514             mBuilding.mEnrollmentId = source.getEnrollmentId();
515             mBuilding.mStatus = Status.PENDING;
516             mBuilding.mAttributionDestinations = eventReportDestinations;
517             mBuilding.mSourceType = source.getSourceType();
518             mBuilding.mSourceDebugKey = sourceDebugKey;
519             mBuilding.mTriggerDebugKeys = debugKeys;
520             mBuilding.mDebugReportStatus = DebugReportStatus.NONE;
521             if (mBuilding.mSourceDebugKey != null && debugKeys.size() > 0) {
522                 mBuilding.mDebugReportStatus = DebugReportStatus.PENDING;
523             }
524             mBuilding.mSourceId = source.getId();
525             mBuilding.mTriggerId = trigger.getId();
526             mBuilding.mRegistrationOrigin = trigger.getRegistrationOrigin();
527             mBuilding.mRandomizedTriggerRate = flipProbability;
528             mBuilding.mTriggerData = attributedTrigger.getTriggerData();
529             mBuilding.mReportTime = reportTime;
530             mBuilding.mTriggerSummaryBucket = triggerSummaryBucket;
531             return this;
532         }
533 
534         /**
535          * Build the {@link EventReport}.
536          */
build()537         public EventReport build() {
538             return mBuilding;
539         }
540     }
541 }
542