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 com.android.adservices.service.adselection;
18 
19 import android.adservices.common.AdTechIdentifier;
20 import android.adservices.common.FrequencyCapFilters;
21 
22 import androidx.annotation.NonNull;
23 import androidx.annotation.Nullable;
24 
25 import com.google.auto.value.AutoValue;
26 
27 import java.time.Instant;
28 import java.util.Objects;
29 
30 /**
31  * A value class representing a single histogram event.
32  *
33  * <p>Ad events are registered with FLEDGE in order to update internal event histograms which are
34  * used during ad selection to filter out ads with frequency cap filters.
35  */
36 @AutoValue
37 public abstract class HistogramEvent {
38     /**
39      * Returns the arbitrary int representing a grouping that a buyer adtech has assigned to an ad
40      * or histogram.
41      */
42     @NonNull
getAdCounterKey()43     public abstract int getAdCounterKey();
44 
45     /** Returns the histogram's buyer adtech's {@link AdTechIdentifier}. */
46     @NonNull
getBuyer()47     public abstract AdTechIdentifier getBuyer();
48 
49     /** Returns the owner package name of the custom audience the histogram is associated with. */
50     @Nullable
getCustomAudienceOwner()51     public abstract String getCustomAudienceOwner();
52 
53     /** Returns the name of the custom audience the histogram is associated with. */
54     @Nullable
getCustomAudienceName()55     public abstract String getCustomAudienceName();
56 
57     /** Returns the enumerated type of the ad event. */
58     @FrequencyCapFilters.AdEventType
getAdEventType()59     public abstract int getAdEventType();
60 
61     /** Returns the timestamp for the event. */
62     @NonNull
getTimestamp()63     public abstract Instant getTimestamp();
64 
65     /** Returns the package name of the source app the histogram is being updated from. */
66     @NonNull
getSourceApp()67     public abstract String getSourceApp();
68 
69     /** Returns an AutoValue builder for a {@link HistogramEvent} object. */
70     @NonNull
builder()71     public static Builder builder() {
72         return new AutoValue_HistogramEvent.Builder();
73     }
74 
75     /** Builder class for a {@link HistogramEvent} object. */
76     @AutoValue.Builder
77     public abstract static class Builder {
78         /**
79          * Sets the arbitrary int representing a grouping that a buyer adtech has assigned to an ad
80          * or histogram.
81          */
82         @NonNull
setAdCounterKey(int adCounterKey)83         public abstract Builder setAdCounterKey(int adCounterKey);
84 
85         /** Sets the histogram's buyer adtech's {@link AdTechIdentifier}. */
86         @NonNull
setBuyer(@onNull AdTechIdentifier buyer)87         public abstract Builder setBuyer(@NonNull AdTechIdentifier buyer);
88 
89         /** Sets the owner package name of the custom audience the histogram is associated with. */
90         @NonNull
setCustomAudienceOwner(@ullable String customAudienceOwner)91         public abstract Builder setCustomAudienceOwner(@Nullable String customAudienceOwner);
92 
93         /** Sets the name of the custom audience the histogram is associated with. */
94         @NonNull
setCustomAudienceName(@ullable String customAudienceName)95         public abstract Builder setCustomAudienceName(@Nullable String customAudienceName);
96 
97         /** Sets the enumerated type of the ad event. */
98         @NonNull
setAdEventType(@requencyCapFilters.AdEventType int adEventType)99         public abstract Builder setAdEventType(@FrequencyCapFilters.AdEventType int adEventType);
100 
101         /** Sets the timestamp for the event. */
102         @NonNull
setTimestamp(@onNull Instant timestamp)103         public abstract Builder setTimestamp(@NonNull Instant timestamp);
104 
105         /** Sets the package name of the source app the histogram is being updated from. */
106         @NonNull
setSourceApp(@onNull String sourceApp)107         public abstract Builder setSourceApp(@NonNull String sourceApp);
108 
109         /**
110          * Builds and returns the {@link HistogramEvent} object.
111          *
112          * <p>Note that AutoValue doesn't by itself do any validation, so splitting the builder with
113          * a manual verification is recommended.
114          *
115          * @throws IllegalStateException if any required field is unset when the object is built
116          */
117         @NonNull
autoValueBuild()118         abstract HistogramEvent autoValueBuild();
119 
120         /**
121          * Builds, validates, and returns the {@link HistogramEvent} object.
122          *
123          * @throws IllegalStateException if any required field is unset when the object is built
124          * @throws NullPointerException if any custom audience field is unset when the object is
125          *     built with a {@link FrequencyCapFilters#AD_EVENT_TYPE_WIN} event type
126          */
127         @NonNull
build()128         public HistogramEvent build() {
129             HistogramEvent event = autoValueBuild();
130 
131             // Win-typed events must be scoped to a custom audience
132             if (event.getAdEventType() == FrequencyCapFilters.AD_EVENT_TYPE_WIN) {
133                 Objects.requireNonNull(
134                         event.getCustomAudienceOwner(),
135                         "Custom audience owner must not be null for WIN events");
136                 Objects.requireNonNull(
137                         event.getCustomAudienceName(),
138                         "Custom audience name must not be null for WIN events");
139             }
140 
141             return event;
142         }
143     }
144 }
145