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