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.Debug; 29 import com.android.adservices.service.measurement.util.UnsignedLong; 30 31 import com.google.common.collect.ImmutableMultiset; 32 33 import java.lang.annotation.Retention; 34 import java.lang.annotation.RetentionPolicy; 35 import java.util.List; 36 import java.util.Objects; 37 38 /** 39 * POJO for EventReport. 40 */ 41 public class EventReport { 42 43 private String mId; 44 private UnsignedLong mSourceEventId; 45 private long mReportTime; 46 private long mTriggerTime; 47 private long mTriggerPriority; 48 private List<Uri> mAttributionDestinations; 49 private String mEnrollmentId; 50 private UnsignedLong mTriggerData; 51 private UnsignedLong mTriggerDedupKey; 52 private double mRandomizedTriggerRate; 53 private @Status int mStatus; 54 private @DebugReportStatus int mDebugReportStatus; 55 private Source.SourceType mSourceType; 56 @Nullable private UnsignedLong mSourceDebugKey; 57 @Nullable private UnsignedLong mTriggerDebugKey; 58 private String mSourceId; 59 private String mTriggerId; 60 private Uri mRegistrationOrigin; 61 62 @IntDef(value = {Status.PENDING, Status.DELIVERED, Status.MARKED_TO_DELETE}) 63 @Retention(RetentionPolicy.SOURCE) 64 public @interface Status { 65 int PENDING = 0; 66 int DELIVERED = 1; 67 int MARKED_TO_DELETE = 2; 68 } 69 70 @IntDef( 71 value = { 72 DebugReportStatus.NONE, 73 DebugReportStatus.PENDING, 74 DebugReportStatus.DELIVERED, 75 }) 76 @Retention(RetentionPolicy.SOURCE) 77 public @interface DebugReportStatus { 78 int NONE = 0; 79 int PENDING = 1; 80 int DELIVERED = 2; 81 } 82 EventReport()83 private EventReport() { 84 mTriggerDedupKey = null; 85 } 86 87 @Override equals(Object obj)88 public boolean equals(Object obj) { 89 if (!(obj instanceof EventReport)) { 90 return false; 91 } 92 EventReport eventReport = (EventReport) obj; 93 return mStatus == eventReport.mStatus 94 && mDebugReportStatus == eventReport.mDebugReportStatus 95 && mReportTime == eventReport.mReportTime 96 && Objects.equals(mAttributionDestinations, eventReport.mAttributionDestinations) 97 && ImmutableMultiset.copyOf(mAttributionDestinations) 98 .equals(ImmutableMultiset.copyOf(eventReport.mAttributionDestinations)) 99 && Objects.equals(mEnrollmentId, eventReport.mEnrollmentId) 100 && mTriggerTime == eventReport.mTriggerTime 101 && Objects.equals(mTriggerData, eventReport.mTriggerData) 102 && Objects.equals(mSourceEventId, eventReport.mSourceEventId) 103 && mTriggerPriority == eventReport.mTriggerPriority 104 && Objects.equals(mTriggerDedupKey, eventReport.mTriggerDedupKey) 105 && mSourceType == eventReport.mSourceType 106 && mRandomizedTriggerRate == eventReport.mRandomizedTriggerRate 107 && Objects.equals(mSourceDebugKey, eventReport.mSourceDebugKey) 108 && Objects.equals(mTriggerDebugKey, eventReport.mTriggerDebugKey) 109 && Objects.equals(mSourceId, eventReport.mSourceId) 110 && Objects.equals(mTriggerId, eventReport.mTriggerId) 111 && Objects.equals(mRegistrationOrigin, eventReport.mRegistrationOrigin); 112 } 113 114 @Override hashCode()115 public int hashCode() { 116 return Objects.hash( 117 mStatus, 118 mDebugReportStatus, 119 mReportTime, 120 mAttributionDestinations, 121 mEnrollmentId, 122 mTriggerTime, 123 mTriggerData, 124 mSourceEventId, 125 mTriggerPriority, 126 mTriggerDedupKey, 127 mSourceType, 128 mRandomizedTriggerRate, 129 mSourceDebugKey, 130 mTriggerDebugKey, 131 mSourceId, 132 mTriggerId, 133 mRegistrationOrigin); 134 } 135 136 /** Unique identifier for the report. */ getId()137 public String getId() { 138 return mId; 139 } 140 141 /** Identifier of the associated {@link Source} event. */ getSourceEventId()142 public UnsignedLong getSourceEventId() { 143 return mSourceEventId; 144 } 145 146 /** 147 * Scheduled time for the report to be sent. 148 */ getReportTime()149 public long getReportTime() { 150 return mReportTime; 151 } 152 153 /** 154 * TriggerTime of the associated {@link Trigger}. 155 */ getTriggerTime()156 public long getTriggerTime() { 157 return mTriggerTime; 158 } 159 160 /** 161 * Priority of the associated {@link Trigger}. 162 */ getTriggerPriority()163 public long getTriggerPriority() { 164 return mTriggerPriority; 165 } 166 167 /** 168 * AttributionDestinations of the {@link Source} and {@link Trigger}. 169 */ getAttributionDestinations()170 public List<Uri> getAttributionDestinations() { 171 return mAttributionDestinations; 172 } 173 174 /** 175 * Ad Tech enrollment ID. 176 */ getEnrollmentId()177 public String getEnrollmentId() { 178 return mEnrollmentId; 179 } 180 181 /** 182 * Metadata for the report. 183 */ getTriggerData()184 public UnsignedLong getTriggerData() { 185 return mTriggerData; 186 } 187 188 /** 189 * Deduplication key of the associated {@link Trigger} 190 */ getTriggerDedupKey()191 public UnsignedLong getTriggerDedupKey() { 192 return mTriggerDedupKey; 193 } 194 195 /** 196 * Current {@link Status} of the report. 197 */ getStatus()198 public @Status int getStatus() { 199 return mStatus; 200 } 201 202 /** Current {@link DebugReportStatus} of the report. */ getDebugReportStatus()203 public @DebugReportStatus int getDebugReportStatus() { 204 return mDebugReportStatus; 205 } 206 207 /** 208 * SourceType of the event's source. 209 */ getSourceType()210 public Source.SourceType getSourceType() { 211 return mSourceType; 212 } 213 214 /** 215 * Randomized trigger rate for noising 216 */ getRandomizedTriggerRate()217 public double getRandomizedTriggerRate() { 218 return mRandomizedTriggerRate; 219 } 220 221 /** Source Debug Key */ 222 @Nullable getSourceDebugKey()223 public UnsignedLong getSourceDebugKey() { 224 return mSourceDebugKey; 225 } 226 227 /** Trigger Debug Key */ 228 @Nullable getTriggerDebugKey()229 public UnsignedLong getTriggerDebugKey() { 230 return mTriggerDebugKey; 231 } 232 233 /** Source ID */ getSourceId()234 public String getSourceId() { 235 return mSourceId; 236 } 237 238 /** Trigger ID */ getTriggerId()239 public String getTriggerId() { 240 return mTriggerId; 241 } 242 243 /** Returns registration origin used to register the source and trigger */ getRegistrationOrigin()244 public Uri getRegistrationOrigin() { 245 return mRegistrationOrigin; 246 } 247 248 /** Builder for {@link EventReport} */ 249 public static final class Builder { 250 251 private final EventReport mBuilding; 252 Builder()253 public Builder() { 254 mBuilding = new EventReport(); 255 } 256 257 /** 258 * See {@link EventReport#getId()} 259 */ setId(String id)260 public Builder setId(String id) { 261 mBuilding.mId = id; 262 return this; 263 } 264 265 /** See {@link EventReport#getSourceEventId()} */ setSourceEventId(UnsignedLong sourceEventId)266 public Builder setSourceEventId(UnsignedLong sourceEventId) { 267 mBuilding.mSourceEventId = sourceEventId; 268 return this; 269 } 270 271 /** See {@link EventReport#getEnrollmentId()} */ setEnrollmentId(String enrollmentId)272 public Builder setEnrollmentId(String enrollmentId) { 273 mBuilding.mEnrollmentId = enrollmentId; 274 return this; 275 } 276 277 /** 278 * See {@link EventReport#getAttributionDestination()} 279 */ setAttributionDestinations(List<Uri> attributionDestinations)280 public Builder setAttributionDestinations(List<Uri> attributionDestinations) { 281 mBuilding.mAttributionDestinations = attributionDestinations; 282 return this; 283 } 284 285 /** 286 * See {@link EventReport#getTriggerTime()} 287 */ setTriggerTime(long triggerTime)288 public Builder setTriggerTime(long triggerTime) { 289 mBuilding.mTriggerTime = triggerTime; 290 return this; 291 } 292 293 /** 294 * See {@link EventReport#getTriggerData()} 295 */ setTriggerData(UnsignedLong triggerData)296 public Builder setTriggerData(UnsignedLong triggerData) { 297 mBuilding.mTriggerData = triggerData; 298 return this; 299 } 300 301 /** 302 * See {@link EventReport#getTriggerPriority()} 303 */ setTriggerPriority(long triggerPriority)304 public Builder setTriggerPriority(long triggerPriority) { 305 mBuilding.mTriggerPriority = triggerPriority; 306 return this; 307 } 308 309 /** 310 * See {@link EventReport#getTriggerDedupKey()} 311 */ setTriggerDedupKey(UnsignedLong triggerDedupKey)312 public Builder setTriggerDedupKey(UnsignedLong triggerDedupKey) { 313 mBuilding.mTriggerDedupKey = triggerDedupKey; 314 return this; 315 } 316 317 /** 318 * See {@link EventReport#getReportTime()} 319 */ setReportTime(long reportTime)320 public Builder setReportTime(long reportTime) { 321 mBuilding.mReportTime = reportTime; 322 return this; 323 } 324 325 /** 326 * See {@link EventReport#getStatus()} 327 */ setStatus(@tatus int status)328 public Builder setStatus(@Status int status) { 329 mBuilding.mStatus = status; 330 return this; 331 } 332 333 /** See {@link EventReport#getDebugReportStatus()}} */ setDebugReportStatus(@ebugReportStatus int debugReportStatus)334 public Builder setDebugReportStatus(@DebugReportStatus int debugReportStatus) { 335 mBuilding.mDebugReportStatus = debugReportStatus; 336 return this; 337 } 338 339 /** 340 * See {@link EventReport#getSourceType()} 341 */ setSourceType(Source.SourceType sourceType)342 public Builder setSourceType(Source.SourceType sourceType) { 343 mBuilding.mSourceType = sourceType; 344 return this; 345 } 346 347 /** See {@link EventReport#getRandomizedTriggerRate()}} */ setRandomizedTriggerRate(double randomizedTriggerRate)348 public Builder setRandomizedTriggerRate(double randomizedTriggerRate) { 349 mBuilding.mRandomizedTriggerRate = randomizedTriggerRate; 350 return this; 351 } 352 353 /** See {@link EventReport#getSourceDebugKey()}} */ setSourceDebugKey(UnsignedLong sourceDebugKey)354 public Builder setSourceDebugKey(UnsignedLong sourceDebugKey) { 355 mBuilding.mSourceDebugKey = sourceDebugKey; 356 return this; 357 } 358 359 /** See {@link EventReport#getTriggerDebugKey()}} */ setTriggerDebugKey(UnsignedLong triggerDebugKey)360 public Builder setTriggerDebugKey(UnsignedLong triggerDebugKey) { 361 mBuilding.mTriggerDebugKey = triggerDebugKey; 362 return this; 363 } 364 365 /** See {@link EventReport#getSourceId()} */ setSourceId(String sourceId)366 public Builder setSourceId(String sourceId) { 367 mBuilding.mSourceId = sourceId; 368 return this; 369 } 370 371 /** See {@link EventReport#getTriggerId()} */ setTriggerId(String triggerId)372 public Builder setTriggerId(String triggerId) { 373 mBuilding.mTriggerId = triggerId; 374 return this; 375 } 376 377 /** See {@link Source#getRegistrationOrigin()} ()} */ 378 @NonNull setRegistrationOrigin(Uri registrationOrigin)379 public Builder setRegistrationOrigin(Uri registrationOrigin) { 380 mBuilding.mRegistrationOrigin = registrationOrigin; 381 return this; 382 } 383 384 // TODO (b/285607306): cleanup since this doesn't just do "populateFromSourceAndTrigger" 385 /** Populates fields using {@link Source}, {@link Trigger} and {@link EventTrigger}. */ populateFromSourceAndTrigger( @onNull Source source, @NonNull Trigger trigger, @NonNull EventTrigger eventTrigger, @Nullable Pair<UnsignedLong, UnsignedLong> debugKeyPair, @NonNull EventReportWindowCalcDelegate eventReportWindowCalcDelegate, @NonNull SourceNoiseHandler sourceNoiseHandler, List<Uri> eventReportDestinations)386 public Builder populateFromSourceAndTrigger( 387 @NonNull Source source, 388 @NonNull Trigger trigger, 389 @NonNull EventTrigger eventTrigger, 390 @Nullable Pair<UnsignedLong, UnsignedLong> debugKeyPair, 391 @NonNull EventReportWindowCalcDelegate eventReportWindowCalcDelegate, 392 @NonNull SourceNoiseHandler sourceNoiseHandler, 393 List<Uri> eventReportDestinations) { 394 mBuilding.mTriggerPriority = eventTrigger.getTriggerPriority(); 395 mBuilding.mTriggerDedupKey = eventTrigger.getDedupKey(); 396 // truncate trigger data to 3-bit or 1-bit based on {@link Source.SourceType} 397 mBuilding.mTriggerData = getTruncatedTriggerData(source, eventTrigger); 398 mBuilding.mTriggerTime = trigger.getTriggerTime(); 399 mBuilding.mSourceEventId = source.getEventId(); 400 mBuilding.mEnrollmentId = source.getEnrollmentId(); 401 mBuilding.mStatus = Status.PENDING; 402 mBuilding.mAttributionDestinations = eventReportDestinations; 403 mBuilding.mReportTime = 404 eventReportWindowCalcDelegate.getReportingTime( 405 source, trigger.getTriggerTime(), trigger.getDestinationType()); 406 mBuilding.mSourceType = source.getSourceType(); 407 mBuilding.mRandomizedTriggerRate = 408 sourceNoiseHandler.getRandomAttributionProbability(source); 409 mBuilding.mSourceDebugKey = debugKeyPair.first; 410 mBuilding.mTriggerDebugKey = debugKeyPair.second; 411 mBuilding.mDebugReportStatus = DebugReportStatus.NONE; 412 if (Debug.isAttributionDebugReportPermitted(source, trigger, 413 mBuilding.mSourceDebugKey, mBuilding.mTriggerDebugKey)) { 414 mBuilding.mDebugReportStatus = DebugReportStatus.PENDING; 415 } 416 mBuilding.mSourceId = source.getId(); 417 mBuilding.mTriggerId = trigger.getId(); 418 mBuilding.mRegistrationOrigin = trigger.getRegistrationOrigin(); 419 return this; 420 } 421 getTruncatedTriggerData(Source source, EventTrigger eventTrigger)422 private UnsignedLong getTruncatedTriggerData(Source source, EventTrigger eventTrigger) { 423 UnsignedLong triggerData = eventTrigger.getTriggerData(); 424 return triggerData.mod(source.getTriggerDataCardinality()); 425 } 426 427 /** 428 * Build the {@link EventReport}. 429 */ build()430 public EventReport build() { 431 return mBuilding; 432 } 433 } 434 } 435