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