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.customaudience; 18 19 import static com.android.adservices.flags.Flags.FLAG_FLEDGE_SCHEDULE_CUSTOM_AUDIENCE_UPDATE_ENABLED; 20 21 import android.adservices.common.AdServicesOutcomeReceiver; 22 import android.annotation.FlaggedApi; 23 import android.annotation.NonNull; 24 import android.net.Uri; 25 26 import com.android.internal.util.Preconditions; 27 28 import java.time.Duration; 29 import java.util.List; 30 import java.util.Objects; 31 import java.util.concurrent.Executor; 32 33 /** 34 * The request object wrapping the required and optional parameters to schedule a deferred update 35 * for a buyer ad tech's custom audiences. 36 * 37 * <p>The on-device caller can specify information in a series of {@link PartialCustomAudience} 38 * objects that will be sent to the buyer ad tech's server after a designated minimum delay. 39 */ 40 @FlaggedApi(FLAG_FLEDGE_SCHEDULE_CUSTOM_AUDIENCE_UPDATE_ENABLED) 41 public final class ScheduleCustomAudienceUpdateRequest { 42 @NonNull private final Uri mUpdateUri; 43 @NonNull private final Duration mMinDelay; 44 @NonNull private final List<PartialCustomAudience> mPartialCustomAudienceList; 45 private final boolean mShouldReplacePendingUpdates; 46 ScheduleCustomAudienceUpdateRequest( @onNull ScheduleCustomAudienceUpdateRequest.Builder builder)47 private ScheduleCustomAudienceUpdateRequest( 48 @NonNull ScheduleCustomAudienceUpdateRequest.Builder builder) { 49 Objects.requireNonNull(builder); 50 51 this.mUpdateUri = builder.mUpdateUri; 52 this.mMinDelay = builder.mMinDelay; 53 this.mPartialCustomAudienceList = builder.mPartialCustomAudienceList; 54 this.mShouldReplacePendingUpdates = builder.mShouldReplacePendingUpdates; 55 } 56 57 /** 58 * Returns the {@link Uri} from which the update for the buyer's custom audiences will be 59 * fetched. 60 * 61 * <p>The {@link Uri} must use the same HTTPS site as the buyer ad tech's enrolled server. 62 */ 63 @NonNull getUpdateUri()64 public Uri getUpdateUri() { 65 return mUpdateUri; 66 } 67 68 /** 69 * Returns the minimum {@link Duration} that the update will be deferred before the service 70 * fetches updates for the buyer ad tech's custom audiences. 71 */ 72 @NonNull getMinDelay()73 public Duration getMinDelay() { 74 return mMinDelay; 75 } 76 77 /** 78 * Returns the list of {@link PartialCustomAudience} objects which are sent along with the 79 * request to download the updates for the buyer ad tech's custom audiences. 80 */ 81 @NonNull getPartialCustomAudienceList()82 public List<PartialCustomAudience> getPartialCustomAudienceList() { 83 return mPartialCustomAudienceList; 84 } 85 86 /** 87 * Returns {@code true} if any pending scheduled updates should be canceled and replaced with 88 * the update detailed in the current {@link ScheduleCustomAudienceUpdateRequest}. 89 * 90 * <p>If this method returns {@code false} and there are previously requested updates still 91 * pending for the same buyer in the same app, a call to {@link 92 * CustomAudienceManager#scheduleCustomAudienceUpdate(ScheduleCustomAudienceUpdateRequest, 93 * Executor, AdServicesOutcomeReceiver)} with this {@link ScheduleCustomAudienceUpdateRequest} 94 * will fail. 95 */ shouldReplacePendingUpdates()96 public boolean shouldReplacePendingUpdates() { 97 return mShouldReplacePendingUpdates; 98 } 99 100 /** Returns the hash of {@link ScheduleCustomAudienceUpdateRequest} object's data. */ 101 @Override hashCode()102 public int hashCode() { 103 return Objects.hash( 104 mUpdateUri, mMinDelay, mPartialCustomAudienceList, mShouldReplacePendingUpdates); 105 } 106 107 /** 108 * @return {@code true} only if two {@link ScheduleCustomAudienceUpdateRequest} objects contain 109 * the same information. 110 */ 111 @Override equals(Object o)112 public boolean equals(Object o) { 113 if (this == o) return true; 114 if (!(o instanceof ScheduleCustomAudienceUpdateRequest that)) return false; 115 return mShouldReplacePendingUpdates == that.mShouldReplacePendingUpdates 116 && mUpdateUri.equals(that.mUpdateUri) 117 && mMinDelay.equals(that.mMinDelay) 118 && mPartialCustomAudienceList.equals(that.mPartialCustomAudienceList); 119 } 120 121 /** 122 * @return a human-readable representation of {@link ScheduleCustomAudienceUpdateRequest}. 123 */ 124 @Override toString()125 public String toString() { 126 return "ScheduleCustomAudienceUpdateRequest{" 127 + "mUpdateUri=" 128 + mUpdateUri 129 + ", mMinDelay=" 130 + mMinDelay 131 + ", mPartialCustomAudienceList=" 132 + mPartialCustomAudienceList 133 + ", mShouldReplacePendingUpdates=" 134 + mShouldReplacePendingUpdates 135 + '}'; 136 } 137 138 /** Builder for {@link ScheduleCustomAudienceUpdateRequest} objects. */ 139 @FlaggedApi(FLAG_FLEDGE_SCHEDULE_CUSTOM_AUDIENCE_UPDATE_ENABLED) 140 public static final class Builder { 141 @NonNull private Uri mUpdateUri; 142 @NonNull private Duration mMinDelay; 143 @NonNull private List<PartialCustomAudience> mPartialCustomAudienceList; 144 private boolean mShouldReplacePendingUpdates; 145 146 /** 147 * Instantiates a builder for a {@link ScheduleCustomAudienceUpdateRequest} object. 148 * 149 * @param updateUri {@link Uri} of the buyer ad tech's server from which the updates for the 150 * buyer's custom audiences will be fetched 151 * @param minDelay Minimum {@link Duration} for which the update should be deferred 152 * @param partialCustomAudienceList {@link List} of {@link PartialCustomAudience} objects 153 * which will be sent to the buyer ad tech's server 154 */ Builder( @onNull Uri updateUri, @NonNull Duration minDelay, @NonNull List<PartialCustomAudience> partialCustomAudienceList)155 public Builder( 156 @NonNull Uri updateUri, 157 @NonNull Duration minDelay, 158 @NonNull List<PartialCustomAudience> partialCustomAudienceList) { 159 this.mUpdateUri = Objects.requireNonNull(updateUri, "Update URI must not be null"); 160 Objects.requireNonNull(minDelay, "Minimum delay must not be null"); 161 Preconditions.checkArgument( 162 !minDelay.isNegative(), "Minimum delay %d must not be negative", minDelay); 163 this.mMinDelay = minDelay; 164 this.mPartialCustomAudienceList = 165 Objects.requireNonNull( 166 partialCustomAudienceList, 167 "Partial custom audience list must not be null"); 168 } 169 170 /** 171 * Sets the {@link Uri} from which the update for the buyer's custom audiences will be 172 * fetched. 173 * 174 * <p>The {@link Uri} must use the same HTTPS site as the buyer ad tech's enrolled server. 175 * 176 * <p>See {@link #getUpdateUri()} for more details. 177 */ 178 @NonNull setUpdateUri(@onNull Uri updateUri)179 public Builder setUpdateUri(@NonNull Uri updateUri) { 180 this.mUpdateUri = Objects.requireNonNull(updateUri, "Update URI must not be null"); 181 return this; 182 } 183 184 /** 185 * Sets the minimum {@link Duration} that the update will be deferred before the service 186 * fetches updates for the buyer ad tech's custom audiences. 187 * 188 * <p>This delay must not be a negative {@link Duration}. 189 * 190 * <p>See {@link #getMinDelay()} for more details. 191 */ 192 @NonNull setMinDelay(@onNull Duration minDelay)193 public Builder setMinDelay(@NonNull Duration minDelay) { 194 Objects.requireNonNull(minDelay, "Minimum delay must not be null"); 195 Preconditions.checkArgument( 196 !minDelay.isNegative(), "Minimum delay %d must not be negative", minDelay); 197 this.mMinDelay = minDelay; 198 return this; 199 } 200 201 /** 202 * Sets the list of {@link PartialCustomAudience} objects that are sent to the buyer ad 203 * tech's server when making a request to download updates for the buyer's custom audiences. 204 * 205 * <p>See {@link #getPartialCustomAudienceList()} for more details. 206 */ 207 @NonNull setPartialCustomAudienceList( @onNull List<PartialCustomAudience> partialCustomAudienceList)208 public Builder setPartialCustomAudienceList( 209 @NonNull List<PartialCustomAudience> partialCustomAudienceList) { 210 this.mPartialCustomAudienceList = 211 Objects.requireNonNull( 212 partialCustomAudienceList, 213 "Partial custom audience list must not be null"); 214 return this; 215 } 216 217 /** 218 * Sets whether any pending scheduled updates should be deleted and replaced with this 219 * {@link ScheduleCustomAudienceUpdateRequest}. 220 * 221 * <p>By default, this setting is {@code false}. 222 * 223 * <p>See {@link #shouldReplacePendingUpdates()} for more details. 224 */ 225 @NonNull setShouldReplacePendingUpdates(boolean shouldReplacePendingUpdates)226 public Builder setShouldReplacePendingUpdates(boolean shouldReplacePendingUpdates) { 227 this.mShouldReplacePendingUpdates = shouldReplacePendingUpdates; 228 return this; 229 } 230 231 /** Builds an instance of {@link ScheduleCustomAudienceUpdateRequest}. */ 232 @NonNull build()233 public ScheduleCustomAudienceUpdateRequest build() { 234 return new ScheduleCustomAudienceUpdateRequest(this); 235 } 236 } 237 } 238