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 import static android.adservices.common.FrequencyCapFilters.AD_EVENT_TYPE_WIN; 22 23 import android.adservices.common.AdTechIdentifier; 24 import android.adservices.common.FrequencyCapFilters; 25 import android.annotation.NonNull; 26 import android.os.OutcomeReceiver; 27 28 import com.android.internal.util.Preconditions; 29 30 import java.util.Objects; 31 import java.util.concurrent.Executor; 32 33 /** 34 * Request object wrapping the required arguments needed to update an ad counter histogram. 35 * 36 * <p>The ad counter histograms, which are historical logs of events which are associated with an ad 37 * counter key and an ad event type, are used to inform frequency cap filtering when using the 38 * Protected Audience APIs. 39 */ 40 public class UpdateAdCounterHistogramRequest { 41 /** @hide */ 42 public static final String UNSET_AD_EVENT_TYPE_MESSAGE = "Ad event type must be set"; 43 44 /** @hide */ 45 public static final String DISALLOW_AD_EVENT_TYPE_WIN_MESSAGE = 46 "Win event types cannot be manually updated"; 47 48 /** @hide */ 49 public static final String INVALID_AD_EVENT_TYPE_MESSAGE = 50 "Ad event type must be one of AD_EVENT_TYPE_IMPRESSION, AD_EVENT_TYPE_VIEW, or" 51 + " AD_EVENT_TYPE_CLICK"; 52 53 /** @hide */ 54 public static final String UNSET_CALLER_ADTECH_MESSAGE = "Caller ad tech must not be null"; 55 56 private final long mAdSelectionId; 57 @FrequencyCapFilters.AdEventType private final int mAdEventType; 58 @NonNull private final AdTechIdentifier mCallerAdTech; 59 UpdateAdCounterHistogramRequest(@onNull Builder builder)60 private UpdateAdCounterHistogramRequest(@NonNull Builder builder) { 61 Objects.requireNonNull(builder); 62 63 mAdSelectionId = builder.mAdSelectionId; 64 mAdEventType = builder.mAdEventType; 65 mCallerAdTech = builder.mCallerAdTech; 66 } 67 68 /** 69 * Gets the ad selection ID with which the rendered ad's events are associated. 70 * 71 * <p>For more information about the ad selection ID, see {@link AdSelectionOutcome}. 72 * 73 * <p>The ad must have been selected from Protected Audience ad selection in the last 24 hours, 74 * and the ad selection call must have been initiated from the same app as the current calling 75 * app. Event histograms for all ad counter keys associated with the ad specified by the ad 76 * selection ID will be updated for the ad event type from {@link #getAdEventType()}, to be used 77 * in Protected Audience frequency cap filtering. 78 */ getAdSelectionId()79 public long getAdSelectionId() { 80 return mAdSelectionId; 81 } 82 83 /** 84 * Gets the ad event type which, along with an ad's counter keys, identifies which histogram 85 * should be updated. 86 */ 87 @FrequencyCapFilters.AdEventType getAdEventType()88 public int getAdEventType() { 89 return mAdEventType; 90 } 91 92 /** 93 * Gets the caller adtech entity's {@link AdTechIdentifier}. 94 * 95 * <p>The adtech using this {@link UpdateAdCounterHistogramRequest} object must have enrolled 96 * with the Privacy Sandbox and be allowed to act on behalf of the calling app. The specified 97 * adtech is not required to be the same adtech as either the buyer which owns the rendered ad 98 * or the seller which initiated the ad selection associated with the ID returned by {@link 99 * #getAdSelectionId()}. 100 * 101 * <p>For more information about API requirements and exceptions, see {@link 102 * AdSelectionManager#updateAdCounterHistogram(UpdateAdCounterHistogramRequest, Executor, 103 * OutcomeReceiver)}. 104 */ 105 @NonNull getCallerAdTech()106 public AdTechIdentifier getCallerAdTech() { 107 return mCallerAdTech; 108 } 109 110 /** 111 * Checks whether the {@link UpdateAdCounterHistogramRequest} objects contain the same 112 * information. 113 */ 114 @Override equals(Object o)115 public boolean equals(Object o) { 116 if (this == o) return true; 117 if (!(o instanceof UpdateAdCounterHistogramRequest)) return false; 118 UpdateAdCounterHistogramRequest that = (UpdateAdCounterHistogramRequest) o; 119 return mAdSelectionId == that.mAdSelectionId 120 && mAdEventType == that.mAdEventType 121 && mCallerAdTech.equals(that.mCallerAdTech); 122 } 123 124 /** Returns the hash of the {@link UpdateAdCounterHistogramRequest} object's data. */ 125 @Override hashCode()126 public int hashCode() { 127 return Objects.hash(mAdSelectionId, mAdEventType, mCallerAdTech); 128 } 129 130 @Override toString()131 public String toString() { 132 return "UpdateAdCounterHistogramRequest{" 133 + "mAdSelectionId=" 134 + mAdSelectionId 135 + ", mAdEventType=" 136 + mAdEventType 137 + ", mCallerAdTech=" 138 + mCallerAdTech 139 + '}'; 140 } 141 142 /** Builder for {@link UpdateAdCounterHistogramRequest} objects. */ 143 public static final class Builder { 144 private long mAdSelectionId; 145 @FrequencyCapFilters.AdEventType private int mAdEventType; 146 @NonNull private AdTechIdentifier mCallerAdTech; 147 Builder( long adSelectionId, int adEventType, @NonNull AdTechIdentifier callerAdTech)148 public Builder( 149 long adSelectionId, int adEventType, @NonNull AdTechIdentifier callerAdTech) { 150 Preconditions.checkArgument( 151 adSelectionId != UNSET_AD_SELECTION_ID, UNSET_AD_SELECTION_ID_MESSAGE); 152 Preconditions.checkArgument( 153 adEventType != AD_EVENT_TYPE_WIN, DISALLOW_AD_EVENT_TYPE_WIN_MESSAGE); 154 Preconditions.checkArgument( 155 adEventType >= FrequencyCapFilters.AD_EVENT_TYPE_MIN 156 && adEventType <= FrequencyCapFilters.AD_EVENT_TYPE_MAX, 157 INVALID_AD_EVENT_TYPE_MESSAGE); 158 Objects.requireNonNull(callerAdTech, UNSET_CALLER_ADTECH_MESSAGE); 159 160 mAdSelectionId = adSelectionId; 161 mAdEventType = adEventType; 162 mCallerAdTech = callerAdTech; 163 } 164 165 /** 166 * Sets the ad selection ID with which the rendered ad's events are associated. 167 * 168 * <p>See {@link #getAdSelectionId()} for more information. 169 */ 170 @NonNull setAdSelectionId(long adSelectionId)171 public Builder setAdSelectionId(long adSelectionId) { 172 Preconditions.checkArgument( 173 adSelectionId != UNSET_AD_SELECTION_ID, UNSET_AD_SELECTION_ID_MESSAGE); 174 mAdSelectionId = adSelectionId; 175 return this; 176 } 177 178 /** 179 * Sets the ad event type which, along with an ad's counter keys, identifies which histogram 180 * should be updated. 181 * 182 * <p>See {@link #getAdEventType()} for more information. 183 */ 184 @NonNull setAdEventType(@requencyCapFilters.AdEventType int adEventType)185 public Builder setAdEventType(@FrequencyCapFilters.AdEventType int adEventType) { 186 Preconditions.checkArgument( 187 adEventType != AD_EVENT_TYPE_WIN, DISALLOW_AD_EVENT_TYPE_WIN_MESSAGE); 188 Preconditions.checkArgument( 189 adEventType >= FrequencyCapFilters.AD_EVENT_TYPE_MIN 190 && adEventType <= FrequencyCapFilters.AD_EVENT_TYPE_MAX, 191 INVALID_AD_EVENT_TYPE_MESSAGE); 192 mAdEventType = adEventType; 193 return this; 194 } 195 196 /** 197 * Sets the caller adtech entity's {@link AdTechIdentifier}. 198 * 199 * <p>See {@link #getCallerAdTech()} for more information. 200 */ 201 @NonNull setCallerAdTech(@onNull AdTechIdentifier callerAdTech)202 public Builder setCallerAdTech(@NonNull AdTechIdentifier callerAdTech) { 203 Objects.requireNonNull(callerAdTech, UNSET_CALLER_ADTECH_MESSAGE); 204 mCallerAdTech = callerAdTech; 205 return this; 206 } 207 208 /** Builds the {@link UpdateAdCounterHistogramRequest} object. */ 209 @NonNull build()210 public UpdateAdCounterHistogramRequest build() { 211 return new UpdateAdCounterHistogramRequest(this); 212 } 213 } 214 } 215