1 /*
2  * Copyright (C) 2024 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 com.android.adservices.flags.Flags.FLAG_FLEDGE_GET_AD_SELECTION_DATA_SELLER_CONFIGURATION_ENABLED;
20 
21 import android.annotation.FlaggedApi;
22 import android.annotation.IntRange;
23 import android.annotation.NonNull;
24 import android.os.OutcomeReceiver;
25 import android.os.Parcel;
26 import android.os.Parcelable;
27 
28 import com.android.adservices.AdServicesParcelableUtil;
29 import com.android.internal.util.Preconditions;
30 
31 import java.util.ArrayList;
32 import java.util.HashSet;
33 import java.util.List;
34 import java.util.Objects;
35 import java.util.Set;
36 import java.util.concurrent.Executor;
37 
38 /**
39  * This object will be part of the {@link GetAdSelectionDataRequest} and will be constructed and
40  * used by the SDK to influence the size of the response of {@link
41  * AdSelectionManager#getAdSelectionData(GetAdSelectionDataRequest, Executor, OutcomeReceiver)}
42  */
43 @FlaggedApi(FLAG_FLEDGE_GET_AD_SELECTION_DATA_SELLER_CONFIGURATION_ENABLED)
44 public final class SellerConfiguration implements Parcelable {
45     private final int mMaximumPayloadSizeBytes;
46     private final Set<PerBuyerConfiguration> mPerBuyerConfigurations;
47 
SellerConfiguration(Parcel in)48     private SellerConfiguration(Parcel in) {
49         mMaximumPayloadSizeBytes = in.readInt();
50         List<PerBuyerConfiguration> perBuyerConfigurationList =
51                 AdServicesParcelableUtil.readNullableFromParcel(
52                         in,
53                         (sourceParcel -> in.createTypedArrayList(PerBuyerConfiguration.CREATOR)));
54         if (Objects.nonNull(perBuyerConfigurationList)) {
55             mPerBuyerConfigurations = new HashSet<>(perBuyerConfigurationList);
56         } else {
57             mPerBuyerConfigurations = new HashSet<>();
58         }
59     }
60 
61     @NonNull
62     public static final Creator<SellerConfiguration> CREATOR =
63             new Creator<>() {
64                 @Override
65                 public SellerConfiguration createFromParcel(@NonNull Parcel in) {
66                     Objects.requireNonNull(in);
67 
68                     return new SellerConfiguration(in);
69                 }
70 
71                 @Override
72                 public SellerConfiguration[] newArray(int size) {
73                     return new SellerConfiguration[size];
74                 }
75             };
76 
SellerConfiguration( int maximumPayloadSizeBytes, Set<PerBuyerConfiguration> perBuyerConfigurations)77     private SellerConfiguration(
78             int maximumPayloadSizeBytes, Set<PerBuyerConfiguration> perBuyerConfigurations) {
79 
80         mMaximumPayloadSizeBytes = maximumPayloadSizeBytes;
81         mPerBuyerConfigurations = perBuyerConfigurations;
82     }
83 
84     @Override
describeContents()85     public int describeContents() {
86         return 0;
87     }
88 
89     @Override
writeToParcel(@onNull Parcel dest, int flags)90     public void writeToParcel(@NonNull Parcel dest, int flags) {
91         Objects.requireNonNull(dest);
92 
93         dest.writeInt(mMaximumPayloadSizeBytes);
94         AdServicesParcelableUtil.writeNullableToParcel(
95                 dest,
96                 mPerBuyerConfigurations,
97                 (targetParcel, sourceSet) -> dest.writeTypedList(new ArrayList<>(sourceSet)));
98     }
99 
100     @Override
equals(Object o)101     public boolean equals(Object o) {
102         if (o instanceof SellerConfiguration) {
103             SellerConfiguration sellerConfiguration = (SellerConfiguration) o;
104             return Objects.equals(
105                             mMaximumPayloadSizeBytes, sellerConfiguration.mMaximumPayloadSizeBytes)
106                     && Objects.equals(
107                             mPerBuyerConfigurations, sellerConfiguration.mPerBuyerConfigurations);
108         }
109         return false;
110     }
111 
112     @Override
hashCode()113     public int hashCode() {
114         return Objects.hash(mMaximumPayloadSizeBytes, mPerBuyerConfigurations);
115     }
116 
117     /** Returns the maximum size of the payload in bytes that the service will return. */
118     @IntRange(from = 1, to = Integer.MAX_VALUE)
getMaximumPayloadSizeBytes()119     public int getMaximumPayloadSizeBytes() {
120         return mMaximumPayloadSizeBytes;
121     }
122 
123     /**
124      * Returns a set of per buyer configurations that the service will do a best effort to respect
125      * when constructing the response without exceeding {@link #getMaximumPayloadSizeBytes()}.
126      *
127      * <p>If this is empty, the service will fill up the response with buyer data until {@link
128      * #getMaximumPayloadSizeBytes()} is reached. Otherwise, only data from buyers from the per
129      * buyer configuration will be included. If the sum of {@link
130      * PerBuyerConfiguration#getTargetInputSizeBytes()} sizes is larger than {@link
131      * #getMaximumPayloadSizeBytes()}, the service will do a best effort attempt to proportionally
132      * include the buyer data based on the ratio between that specific buyer's target and the sum of
133      * {@link PerBuyerConfiguration#getTargetInputSizeBytes()}.
134      */
135     @NonNull
getPerBuyerConfigurations()136     public Set<PerBuyerConfiguration> getPerBuyerConfigurations() {
137         return mPerBuyerConfigurations;
138     }
139 
140     /** Builder for {@link SellerConfiguration} objects. */
141     public static final class Builder {
142         private int mMaximumPayloadSizeBytes;
143         @NonNull private Set<PerBuyerConfiguration> mPerBuyerConfigurations = new HashSet<>();
144 
145         /**
146          * Sets the target payload size in bytes. For more information see {@link
147          * #getMaximumPayloadSizeBytes()}
148          */
149         @NonNull
setMaximumPayloadSizeBytes( @ntRangefrom = 1, to = Integer.MAX_VALUE) int maximumPayloadSizeBytes)150         public Builder setMaximumPayloadSizeBytes(
151                 @IntRange(from = 1, to = Integer.MAX_VALUE) int maximumPayloadSizeBytes) {
152             mMaximumPayloadSizeBytes = maximumPayloadSizeBytes;
153 
154             Preconditions.checkArgument(
155                     maximumPayloadSizeBytes > 0,
156                     "Maximum payload of size %d must be greater than 0.",
157                     maximumPayloadSizeBytes);
158             return this;
159         }
160 
161         /**
162          * Sets the per buyer configurations. For more information see {@link
163          * #getPerBuyerConfigurations()}
164          */
165         @NonNull
setPerBuyerConfigurations( @onNull Set<PerBuyerConfiguration> perBuyerConfigurations)166         public Builder setPerBuyerConfigurations(
167                 @NonNull Set<PerBuyerConfiguration> perBuyerConfigurations) {
168             mPerBuyerConfigurations =
169                     Objects.requireNonNull(
170                             perBuyerConfigurations, "Per Buyer Configurations cannot be null.");
171             return this;
172         }
173 
174         /** Builds a {@link SellerConfiguration} instance. */
175         @NonNull
build()176         public SellerConfiguration build() {
177             if (mMaximumPayloadSizeBytes == 0) {
178                 throw new IllegalStateException("Maximum size must be set.");
179             }
180 
181             return new SellerConfiguration(mMaximumPayloadSizeBytes, mPerBuyerConfigurations);
182         }
183     }
184 }
185