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.UpdateAdCounterHistogramRequest.UNSET_AD_EVENT_TYPE_MESSAGE; 20 import static android.adservices.common.FrequencyCapFilters.AD_EVENT_TYPE_INVALID; 21 22 import android.adservices.common.AdTechIdentifier; 23 import android.adservices.common.FrequencyCapFilters; 24 import android.annotation.NonNull; 25 import android.annotation.Nullable; 26 27 import com.android.internal.util.Preconditions; 28 29 import java.time.Instant; 30 import java.util.ArrayList; 31 import java.util.List; 32 import java.util.Objects; 33 34 /** 35 * Request object for setting ad counter histogram overrides. 36 * 37 * <p>Histogram overrides replace actual ad counter histograms used in ad selection. Overrides may 38 * only be set in debuggable apps on phones running a debuggable OS build with developer options 39 * enabled. Overrides are only available from the calling app. 40 * 41 * @hide 42 */ 43 // TODO(b/221876775): Unhide for frequency cap API review 44 public class SetAdCounterHistogramOverrideRequest { 45 /** @hide */ 46 public static final String NULL_AD_COUNTER_KEY_MESSAGE = "Ad counter key must not be null"; 47 48 /** @hide */ 49 public static final String NULL_HISTOGRAM_TIMESTAMPS_MESSAGE = 50 "List of histogram timestamps must not be null"; 51 52 /** @hide */ 53 public static final String NULL_BUYER_MESSAGE = "Buyer must not be null"; 54 55 /** @hide */ 56 public static final String NULL_CUSTOM_AUDIENCE_OWNER_MESSAGE = 57 "Custom audience owner must not be null"; 58 59 /** @hide */ 60 public static final String NULL_CUSTOM_AUDIENCE_NAME_MESSAGE = 61 "Custom audience name must not be null"; 62 63 @FrequencyCapFilters.AdEventType private final int mAdEventType; 64 @NonNull private final String mAdCounterKey; 65 @NonNull private final List<Instant> mHistogramTimestamps; 66 @NonNull private final AdTechIdentifier mBuyer; 67 @NonNull private final String mCustomAudienceOwner; 68 @NonNull private final String mCustomAudienceName; 69 SetAdCounterHistogramOverrideRequest(@onNull Builder builder)70 private SetAdCounterHistogramOverrideRequest(@NonNull Builder builder) { 71 Objects.requireNonNull(builder); 72 73 mAdEventType = builder.mAdEventType; 74 mAdCounterKey = builder.mAdCounterKey; 75 mHistogramTimestamps = builder.mHistogramTimestamps; 76 mBuyer = builder.mBuyer; 77 mCustomAudienceOwner = builder.mCustomAudienceOwner; 78 mCustomAudienceName = builder.mCustomAudienceName; 79 } 80 81 /** 82 * Gets the {@link FrequencyCapFilters.AdEventType} for the ad counter histogram override. 83 * 84 * <p>The ad event type is used with the ad counter key from {@link #getAdCounterKey()} and the 85 * buyer adtech from {@link #getBuyer()} to specify which histogram to use in ad selection 86 * filtering. The ad event type would normally be specified by an app/SDK after a 87 * FLEDGE-selected ad is rendered. 88 */ 89 @FrequencyCapFilters.AdEventType getAdEventType()90 public int getAdEventType() { 91 return mAdEventType; 92 } 93 94 /** 95 * Gets the ad counter key for the ad counter histogram override. 96 * 97 * <p>The ad counter key is used with the ad event type from {@link #getAdEventType()} and the 98 * buyer adtech from {@link #getBuyer()} to specify which histogram to use in ad selection 99 * filtering. The ad counter key would normally be specified by a custom audience ad to 100 * represent a grouping to filter on. 101 */ 102 @NonNull getAdCounterKey()103 public String getAdCounterKey() { 104 return mAdCounterKey; 105 } 106 107 /** 108 * Gets the list of {@link Instant} objects for the ad counter histogram override. 109 * 110 * <p>When set, this list of timestamps is used to populate the override histogram, which is 111 * used instead of actual histograms for ad selection filtering. 112 */ 113 @NonNull getHistogramTimestamps()114 public List<Instant> getHistogramTimestamps() { 115 return mHistogramTimestamps; 116 } 117 118 /** 119 * Gets the {@link AdTechIdentifier} for the buyer which owns the ad counter histogram. 120 * 121 * <p>During filtering in FLEDGE ad selection, ads can only use ad counter histogram data 122 * generated by the same buyer. For {@link FrequencyCapFilters#AD_EVENT_TYPE_WIN}, ad counter 123 * histogram data is further restricted to ads from the same custom audience, which is 124 * identified by the buyer, the custom audience's owner app package name from {@link 125 * #getCustomAudienceOwner()}, and the custom audience name from {@link 126 * #getCustomAudienceName()}. 127 */ 128 @NonNull getBuyer()129 public AdTechIdentifier getBuyer() { 130 return mBuyer; 131 } 132 133 /** 134 * Gets the package name for the app which generated the custom audience which is associated 135 * with the overridden ad counter histogram data. 136 * 137 * <p>For {@link FrequencyCapFilters#AD_EVENT_TYPE_WIN}, ad counter histogram data is restricted 138 * to ads from the same custom audience, which is identified by the buyer from {@link 139 * #getBuyer()}, the custom audience's owner app package name, and the custom audience name from 140 * {@link #getCustomAudienceName()}. 141 */ 142 @NonNull getCustomAudienceOwner()143 public String getCustomAudienceOwner() { 144 return mCustomAudienceOwner; 145 } 146 147 /** 148 * Gets the buyer-generated name for the custom audience which is associated with the overridden 149 * ad counter histogram data. 150 * 151 * <p>For {@link FrequencyCapFilters#AD_EVENT_TYPE_WIN}, ad counter histogram data is restricted 152 * to ads from the same custom audience, which is identified by the buyer from {@link 153 * #getBuyer()}, the custom audience's owner app package name from {@link 154 * #getCustomAudienceOwner()}, and the custom audience name. 155 */ 156 @NonNull getCustomAudienceName()157 public String getCustomAudienceName() { 158 return mCustomAudienceName; 159 } 160 161 @Override toString()162 public String toString() { 163 return "SetAdCounterHistogramOverrideRequest{" 164 + "mAdEventType=" 165 + mAdEventType 166 + ", mAdCounterKey='" 167 + mAdCounterKey 168 + "', mHistogramTimestamps=" 169 + mHistogramTimestamps 170 + ", mBuyer=" 171 + mBuyer 172 + ", mCustomAudienceOwner='" 173 + mCustomAudienceOwner 174 + "', mCustomAudienceName='" 175 + mCustomAudienceName 176 + "'}"; 177 } 178 179 /** Builder for {@link SetAdCounterHistogramOverrideRequest} objects. */ 180 public static final class Builder { 181 @FrequencyCapFilters.AdEventType private int mAdEventType = AD_EVENT_TYPE_INVALID; 182 @Nullable private String mAdCounterKey; 183 @NonNull private List<Instant> mHistogramTimestamps = new ArrayList<>(); 184 @Nullable private AdTechIdentifier mBuyer; 185 @Nullable private String mCustomAudienceOwner; 186 @Nullable private String mCustomAudienceName; 187 Builder()188 public Builder() {} 189 190 /** 191 * Sets the {@link FrequencyCapFilters.AdEventType} for the ad counter histogram override. 192 * 193 * <p>See {@link #getAdEventType()} for more information. 194 */ 195 @NonNull setAdEventType(@requencyCapFilters.AdEventType int adEventType)196 public Builder setAdEventType(@FrequencyCapFilters.AdEventType int adEventType) { 197 mAdEventType = adEventType; 198 return this; 199 } 200 201 /** 202 * Sets the ad counter key for the ad counter histogram override. 203 * 204 * <p>See {@link #getAdCounterKey()} for more information. 205 */ 206 @NonNull setAdCounterKey(@onNull String adCounterKey)207 public Builder setAdCounterKey(@NonNull String adCounterKey) { 208 Objects.requireNonNull(adCounterKey, NULL_AD_COUNTER_KEY_MESSAGE); 209 mAdCounterKey = adCounterKey; 210 return this; 211 } 212 213 /** 214 * Sets the list of {@link Instant} objects for the ad counter histogram override. 215 * 216 * <p>See {@link #getHistogramTimestamps()} for more information. 217 */ 218 @NonNull setHistogramTimestamps(@onNull List<Instant> histogramTimestamps)219 public Builder setHistogramTimestamps(@NonNull List<Instant> histogramTimestamps) { 220 Objects.requireNonNull(histogramTimestamps, NULL_HISTOGRAM_TIMESTAMPS_MESSAGE); 221 mHistogramTimestamps = histogramTimestamps; 222 return this; 223 } 224 225 /** 226 * Sets the {@link AdTechIdentifier} for the buyer which owns the ad counter histogram. 227 * 228 * <p>See {@link #getBuyer()} for more information. 229 */ 230 @NonNull setBuyer(@onNull AdTechIdentifier buyer)231 public Builder setBuyer(@NonNull AdTechIdentifier buyer) { 232 Objects.requireNonNull(buyer, NULL_BUYER_MESSAGE); 233 mBuyer = buyer; 234 return this; 235 } 236 237 /** 238 * Sets the package name for the app which generated the custom audience which is associated 239 * with the overridden ad counter histogram data. 240 * 241 * <p>See {@link #getCustomAudienceOwner()} for more information. 242 */ 243 @NonNull setCustomAudienceOwner(@onNull String customAudienceOwner)244 public Builder setCustomAudienceOwner(@NonNull String customAudienceOwner) { 245 Objects.requireNonNull(customAudienceOwner, NULL_CUSTOM_AUDIENCE_OWNER_MESSAGE); 246 mCustomAudienceOwner = customAudienceOwner; 247 return this; 248 } 249 250 /** 251 * Sets the buyer-generated name for the custom audience which is associated with the 252 * overridden ad counter histogram data. 253 * 254 * <p>See {@link #getCustomAudienceName()} for more information. 255 */ 256 @NonNull setCustomAudienceName(@onNull String customAudienceName)257 public Builder setCustomAudienceName(@NonNull String customAudienceName) { 258 Objects.requireNonNull(customAudienceName, NULL_CUSTOM_AUDIENCE_NAME_MESSAGE); 259 mCustomAudienceName = customAudienceName; 260 return this; 261 } 262 263 /** 264 * Builds the {@link SetAdCounterHistogramOverrideRequest} object. 265 * 266 * @throws NullPointerException if any parameters are not set 267 * @throws IllegalArgumentException if the ad event type is invalid 268 */ 269 @NonNull build()270 public SetAdCounterHistogramOverrideRequest build() 271 throws NullPointerException, IllegalArgumentException { 272 Preconditions.checkArgument( 273 mAdEventType != AD_EVENT_TYPE_INVALID, UNSET_AD_EVENT_TYPE_MESSAGE); 274 Objects.requireNonNull(mAdCounterKey, NULL_AD_COUNTER_KEY_MESSAGE); 275 Objects.requireNonNull(mBuyer, NULL_BUYER_MESSAGE); 276 Objects.requireNonNull(mCustomAudienceOwner, NULL_CUSTOM_AUDIENCE_OWNER_MESSAGE); 277 Objects.requireNonNull(mCustomAudienceName, NULL_CUSTOM_AUDIENCE_NAME_MESSAGE); 278 279 return new SetAdCounterHistogramOverrideRequest(this); 280 } 281 } 282 } 283