1 /* 2 * Copyright (C) 2023 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 android.adservices.adselection; 18 19 import static android.adservices.adselection.AdSelectionOutcome.UNSET_AD_SELECTION_ID; 20 import static android.adservices.adselection.AdSelectionOutcome.UNSET_AD_SELECTION_ID_MESSAGE; 21 22 import android.annotation.NonNull; 23 import android.annotation.Nullable; 24 import android.os.Parcel; 25 import android.os.Parcelable; 26 import android.view.InputEvent; 27 28 import com.android.adservices.AdServicesParcelableUtil; 29 import com.android.internal.util.Preconditions; 30 31 import java.util.Objects; 32 33 /** 34 * Input object wrapping the required arguments needed to report an interaction. 35 * 36 * @hide 37 */ 38 public final class ReportInteractionInput implements Parcelable { 39 40 private static final int UNSET_REPORTING_DESTINATIONS = 0; 41 private static final String UNSET_REPORTING_DESTINATIONS_MESSAGE = 42 "Reporting Destinations bitfield not set."; 43 44 private final long mAdSelectionId; 45 @NonNull private final String mInteractionKey; 46 @NonNull private final String mInteractionData; 47 @NonNull private final String mCallerPackageName; 48 private final int mReportingDestinations; // buyer, seller, or both 49 @Nullable private final InputEvent mInputEvent; 50 @Nullable private final String mAdId; 51 @Nullable private final String mCallerSdkName; 52 53 @NonNull 54 public static final Creator<ReportInteractionInput> CREATOR = 55 new Creator<ReportInteractionInput>() { 56 @Override 57 public ReportInteractionInput createFromParcel(@NonNull Parcel in) { 58 Objects.requireNonNull(in); 59 60 return new ReportInteractionInput(in); 61 } 62 63 @Override 64 public ReportInteractionInput[] newArray(int size) { 65 return new ReportInteractionInput[size]; 66 } 67 }; 68 ReportInteractionInput( long adSelectionId, @NonNull String interactionKey, @NonNull String interactionData, @NonNull String callerPackageName, int reportingDestinations, @Nullable InputEvent inputEvent, @Nullable String adId, @Nullable String callerSdkName)69 private ReportInteractionInput( 70 long adSelectionId, 71 @NonNull String interactionKey, 72 @NonNull String interactionData, 73 @NonNull String callerPackageName, 74 int reportingDestinations, 75 @Nullable InputEvent inputEvent, 76 @Nullable String adId, 77 @Nullable String callerSdkName) { 78 Objects.requireNonNull(interactionKey); 79 Objects.requireNonNull(interactionData); 80 Objects.requireNonNull(callerPackageName); 81 82 this.mAdSelectionId = adSelectionId; 83 this.mInteractionKey = interactionKey; 84 this.mInteractionData = interactionData; 85 this.mCallerPackageName = callerPackageName; 86 this.mReportingDestinations = reportingDestinations; 87 this.mInputEvent = inputEvent; 88 this.mAdId = adId; 89 this.mCallerSdkName = callerSdkName; 90 } 91 ReportInteractionInput(@onNull Parcel in)92 private ReportInteractionInput(@NonNull Parcel in) { 93 this.mAdSelectionId = in.readLong(); 94 this.mInteractionKey = in.readString(); 95 this.mInteractionData = in.readString(); 96 this.mCallerPackageName = in.readString(); 97 this.mReportingDestinations = in.readInt(); 98 this.mInputEvent = 99 AdServicesParcelableUtil.readNullableFromParcel( 100 in, InputEvent.CREATOR::createFromParcel); 101 this.mAdId = 102 AdServicesParcelableUtil.readNullableFromParcel( 103 in, (sourceParcel -> in.readString())); 104 this.mCallerSdkName = 105 AdServicesParcelableUtil.readNullableFromParcel( 106 in, (sourceParcel -> in.readString())); 107 } 108 109 @Override describeContents()110 public int describeContents() { 111 return 0; 112 } 113 114 @Override writeToParcel(@onNull Parcel dest, int flags)115 public void writeToParcel(@NonNull Parcel dest, int flags) { 116 Objects.requireNonNull(dest); 117 dest.writeLong(mAdSelectionId); 118 dest.writeString(mInteractionKey); 119 dest.writeString(mInteractionData); 120 dest.writeString(mCallerPackageName); 121 dest.writeInt(mReportingDestinations); 122 AdServicesParcelableUtil.writeNullableToParcel( 123 dest, 124 mInputEvent, 125 (targetParcel, sourceInputEvent) -> 126 sourceInputEvent.writeToParcel(targetParcel, flags)); 127 AdServicesParcelableUtil.writeNullableToParcel(dest, mAdId, Parcel::writeString); 128 AdServicesParcelableUtil.writeNullableToParcel(dest, mCallerSdkName, Parcel::writeString); 129 } 130 131 /** Returns the adSelectionId, the primary identifier of an ad selection process. */ getAdSelectionId()132 public long getAdSelectionId() { 133 return mAdSelectionId; 134 } 135 136 /** 137 * Returns the interaction key, the type of interaction to be reported. 138 * 139 * <p>This will be used to fetch the {@code interactionReportingUri} associated with the {@code 140 * interactionKey} registered in {@code registerAdBeacon} after ad selection. 141 */ 142 @NonNull getInteractionKey()143 public String getInteractionKey() { 144 return mInteractionKey; 145 } 146 147 /** 148 * Returns the interaction data. 149 * 150 * <p>After ad selection, this data is generated by the caller, and will be attached in a POST 151 * request to the {@code interactionReportingUri} registered in {@code registerAdBeacon}. 152 */ 153 @NonNull getInteractionData()154 public String getInteractionData() { 155 return mInteractionData; 156 } 157 158 /** Returns the caller package name */ 159 @NonNull getCallerPackageName()160 public String getCallerPackageName() { 161 return mCallerPackageName; 162 } 163 164 /** Returns the bitfield of reporting destinations to report to (buyer, seller, or both) */ getReportingDestinations()165 public int getReportingDestinations() { 166 return mReportingDestinations; 167 } 168 169 /** 170 * Returns the input event associated with the user interaction. 171 * 172 * <p>This field is either {@code null}, representing a <em>view</em> event, or has an {@link 173 * InputEvent} object, representing a <em>click</em> event. 174 */ 175 @Nullable getInputEvent()176 public InputEvent getInputEvent() { 177 return mInputEvent; 178 } 179 180 /** 181 * Returns the {@code AdId} to enable event-level debug reporting. 182 * 183 * <p>This field is either set and non-{@code null}, representing a valid and enabled {@code 184 * AdId} or {@code null}, representing an invalid or disabled {@code AdId}. 185 */ 186 @Nullable getAdId()187 public String getAdId() { 188 return mAdId; 189 } 190 191 /** Returns the caller's sdk name. */ 192 @Nullable getCallerSdkName()193 public String getCallerSdkName() { 194 return mCallerSdkName; 195 } 196 197 /** 198 * Builder for {@link ReportInteractionInput} objects. 199 * 200 * @hide 201 */ 202 public static final class Builder { 203 private long mAdSelectionId = UNSET_AD_SELECTION_ID; 204 @Nullable private String mInteractionKey; 205 @Nullable private String mInteractionData; 206 @Nullable private String mCallerPackageName; 207 @Nullable private String mCallerSdkName; 208 private int mReportingDestinations = UNSET_REPORTING_DESTINATIONS; 209 @Nullable private InputEvent mInputEvent; 210 @Nullable private String mAdId; 211 Builder()212 public Builder() {} 213 214 /** Sets the adSelectionId. */ 215 @NonNull setAdSelectionId(long adSelectionId)216 public ReportInteractionInput.Builder setAdSelectionId(long adSelectionId) { 217 mAdSelectionId = adSelectionId; 218 return this; 219 } 220 221 /** Sets the interactionKey. */ 222 @NonNull setInteractionKey(@onNull String interactionKey)223 public ReportInteractionInput.Builder setInteractionKey(@NonNull String interactionKey) { 224 Objects.requireNonNull(interactionKey); 225 226 mInteractionKey = interactionKey; 227 return this; 228 } 229 230 /** Sets the interactionData. */ 231 @NonNull setInteractionData(@onNull String interactionData)232 public ReportInteractionInput.Builder setInteractionData(@NonNull String interactionData) { 233 Objects.requireNonNull(interactionData); 234 235 mInteractionData = interactionData; 236 return this; 237 } 238 239 /** Sets the caller's package name. */ 240 @NonNull setCallerPackageName( @onNull String callerPackageName)241 public ReportInteractionInput.Builder setCallerPackageName( 242 @NonNull String callerPackageName) { 243 Objects.requireNonNull(callerPackageName); 244 245 mCallerPackageName = callerPackageName; 246 return this; 247 } 248 249 /** Sets the bitfield of reporting destinations. */ 250 @NonNull setReportingDestinations(int reportingDestinations)251 public ReportInteractionInput.Builder setReportingDestinations(int reportingDestinations) { 252 Preconditions.checkArgument( 253 reportingDestinations != UNSET_REPORTING_DESTINATIONS, 254 UNSET_REPORTING_DESTINATIONS_MESSAGE); 255 256 mReportingDestinations = reportingDestinations; 257 return this; 258 } 259 260 /** Sets the input event associated with the user interaction. */ 261 @NonNull setInputEvent(@ullable InputEvent inputEvent)262 public ReportInteractionInput.Builder setInputEvent(@Nullable InputEvent inputEvent) { 263 mInputEvent = inputEvent; 264 return this; 265 } 266 267 /** Sets the {@code AdId}. */ 268 @NonNull setAdId(@ullable String adId)269 public ReportInteractionInput.Builder setAdId(@Nullable String adId) { 270 mAdId = adId; 271 return this; 272 } 273 274 /** Sets the caller's sdk name. */ 275 @NonNull setCallerSdkName(@ullable String callerSdkName)276 public ReportInteractionInput.Builder setCallerSdkName(@Nullable String callerSdkName) { 277 mCallerSdkName = callerSdkName; 278 return this; 279 } 280 281 /** Builds a {@link ReportInteractionInput} instance. */ 282 @NonNull build()283 public ReportInteractionInput build() { 284 Objects.requireNonNull(mInteractionKey); 285 Objects.requireNonNull(mInteractionData); 286 Objects.requireNonNull(mCallerPackageName); 287 288 Preconditions.checkArgument( 289 mAdSelectionId != UNSET_AD_SELECTION_ID, UNSET_AD_SELECTION_ID_MESSAGE); 290 Preconditions.checkArgument( 291 mReportingDestinations != UNSET_REPORTING_DESTINATIONS, 292 UNSET_REPORTING_DESTINATIONS_MESSAGE); 293 294 return new ReportInteractionInput( 295 mAdSelectionId, 296 mInteractionKey, 297 mInteractionData, 298 mCallerPackageName, 299 mReportingDestinations, 300 mInputEvent, 301 mAdId, 302 mCallerSdkName); 303 } 304 } 305 } 306