/* * Copyright (C) 2023 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.adservices.adselection; import static android.adservices.adselection.AdSelectionOutcome.UNSET_AD_SELECTION_ID; import static android.adservices.adselection.AdSelectionOutcome.UNSET_AD_SELECTION_ID_MESSAGE; import static android.adservices.adselection.UpdateAdCounterHistogramRequest.DISALLOW_AD_EVENT_TYPE_WIN_MESSAGE; import static android.adservices.adselection.UpdateAdCounterHistogramRequest.INVALID_AD_EVENT_TYPE_MESSAGE; import static android.adservices.adselection.UpdateAdCounterHistogramRequest.UNSET_CALLER_ADTECH_MESSAGE; import static android.adservices.common.FrequencyCapFilters.AD_EVENT_TYPE_WIN; import android.adservices.common.AdTechIdentifier; import android.adservices.common.FrequencyCapFilters; import android.annotation.NonNull; import android.os.Parcel; import android.os.Parcelable; import com.android.internal.util.Preconditions; import java.util.Objects; /** * Input object wrapping the required arguments needed to update an ad counter histogram. * *

The ad counter histograms, which are historical logs of events which are associated with an ad * counter key and an ad event type, are used to inform frequency cap filtering when using the * Protected Audience APIs. * * @hide */ public final class UpdateAdCounterHistogramInput implements Parcelable { private static final String UNSET_CALLER_PACKAGE_NAME_MESSAGE = "Caller package name must not be null"; private final long mAdSelectionId; @FrequencyCapFilters.AdEventType private final int mAdEventType; @NonNull private final AdTechIdentifier mCallerAdTech; @NonNull private final String mCallerPackageName; @NonNull public static final Creator CREATOR = new Creator() { @Override public UpdateAdCounterHistogramInput createFromParcel(@NonNull Parcel in) { Objects.requireNonNull(in); return new UpdateAdCounterHistogramInput(in); } @Override public UpdateAdCounterHistogramInput[] newArray(int size) { return new UpdateAdCounterHistogramInput[size]; } }; private UpdateAdCounterHistogramInput(@NonNull Builder builder) { Objects.requireNonNull(builder); mAdSelectionId = builder.mAdSelectionId; mAdEventType = builder.mAdEventType; mCallerAdTech = builder.mCallerAdTech; mCallerPackageName = builder.mCallerPackageName; } private UpdateAdCounterHistogramInput(@NonNull Parcel in) { Objects.requireNonNull(in); mAdSelectionId = in.readLong(); mAdEventType = in.readInt(); mCallerAdTech = AdTechIdentifier.CREATOR.createFromParcel(in); mCallerPackageName = in.readString(); } /** * Gets the ad selection ID with which the rendered ad's events are associated. * *

The ad must have been selected from Protected Audience ad selection in the last 24 hours, * and the ad selection call must have been initiated from the same app as the current calling * app. Event histograms for all ad counter keys associated with the ad specified by the ad * selection ID will be updated for the ad event type from {@link #getAdEventType()}, to be used * in Protected Audience frequency cap filtering. */ public long getAdSelectionId() { return mAdSelectionId; } /** * Gets the {@link android.adservices.common.FrequencyCapFilters.AdEventType} which, along with * an ad's counter keys, identifies which histogram should be updated. * *

See {@link android.adservices.common.FrequencyCapFilters.AdEventType} for more * information. */ @FrequencyCapFilters.AdEventType public int getAdEventType() { return mAdEventType; } /** * Gets the caller adtech entity's {@link AdTechIdentifier}. * *

The adtech using this {@link UpdateAdCounterHistogramInput} object must have enrolled with * the Privacy Sandbox and be allowed to act on behalf of the calling app. The specified adtech * is not required to be the same adtech as either the buyer which owns the rendered ad or the * seller which initiated the ad selection associated with the ID returned by {@link * #getAdSelectionId()}. */ @NonNull public AdTechIdentifier getCallerAdTech() { return mCallerAdTech; } /** * Gets the caller app's package name. * *

The package name must match the caller package name for the Protected Audience ad * selection represented by the ID returned by {@link #getAdSelectionId()}. */ @NonNull public String getCallerPackageName() { return mCallerPackageName; } @Override public void writeToParcel(Parcel dest, int flags) { dest.writeLong(mAdSelectionId); dest.writeInt(mAdEventType); mCallerAdTech.writeToParcel(dest, flags); dest.writeString(mCallerPackageName); } /** @hide */ @Override public int describeContents() { return 0; } /** * Checks whether the {@link UpdateAdCounterHistogramInput} objects contain the same * information. */ @Override public boolean equals(Object o) { if (this == o) return true; if (!(o instanceof UpdateAdCounterHistogramInput)) return false; UpdateAdCounterHistogramInput that = (UpdateAdCounterHistogramInput) o; return mAdSelectionId == that.mAdSelectionId && mAdEventType == that.mAdEventType && mCallerAdTech.equals(that.mCallerAdTech) && mCallerPackageName.equals(that.mCallerPackageName); } /** Returns the hash of the {@link UpdateAdCounterHistogramInput} object's data. */ @Override public int hashCode() { return Objects.hash(mAdSelectionId, mAdEventType, mCallerAdTech, mCallerPackageName); } @Override public String toString() { return "UpdateAdCounterHistogramInput{" + "mAdSelectionId=" + mAdSelectionId + ", mAdEventType=" + mAdEventType + ", mCallerAdTech=" + mCallerAdTech + ", mCallerPackageName='" + mCallerPackageName + '\'' + '}'; } /** Builder for {@link UpdateAdCounterHistogramInput} objects. */ public static final class Builder { private long mAdSelectionId; @FrequencyCapFilters.AdEventType private int mAdEventType; @NonNull private AdTechIdentifier mCallerAdTech; @NonNull private String mCallerPackageName; public Builder( long adSelectionId, int adEventType, @NonNull AdTechIdentifier callerAdTech, @NonNull String callerPackageName) { Preconditions.checkArgument( adSelectionId != UNSET_AD_SELECTION_ID, UNSET_AD_SELECTION_ID_MESSAGE); Preconditions.checkArgument( adEventType != AD_EVENT_TYPE_WIN, DISALLOW_AD_EVENT_TYPE_WIN_MESSAGE); Preconditions.checkArgument( adEventType >= FrequencyCapFilters.AD_EVENT_TYPE_MIN && adEventType <= FrequencyCapFilters.AD_EVENT_TYPE_MAX, INVALID_AD_EVENT_TYPE_MESSAGE); Objects.requireNonNull(callerAdTech, UNSET_CALLER_ADTECH_MESSAGE); Objects.requireNonNull(callerPackageName, UNSET_CALLER_PACKAGE_NAME_MESSAGE); mAdSelectionId = adSelectionId; mAdEventType = adEventType; mCallerAdTech = callerAdTech; mCallerPackageName = callerPackageName; } /** * Sets the ad selection ID with which the rendered ad's events are associated. * *

See {@link #getAdSelectionId()} for more information. */ @NonNull public Builder setAdSelectionId(long adSelectionId) { Preconditions.checkArgument( adSelectionId != UNSET_AD_SELECTION_ID, UNSET_AD_SELECTION_ID_MESSAGE); mAdSelectionId = adSelectionId; return this; } /** * Sets the {@link android.adservices.common.FrequencyCapFilters.AdEventType} which, along * with an ad's counter keys, identifies which histogram should be updated. * *

See {@link #getAdEventType()} for more information. */ @NonNull public Builder setAdEventType(@FrequencyCapFilters.AdEventType int adEventType) { Preconditions.checkArgument( adEventType != AD_EVENT_TYPE_WIN, DISALLOW_AD_EVENT_TYPE_WIN_MESSAGE); Preconditions.checkArgument( adEventType >= FrequencyCapFilters.AD_EVENT_TYPE_MIN && adEventType <= FrequencyCapFilters.AD_EVENT_TYPE_MAX, INVALID_AD_EVENT_TYPE_MESSAGE); mAdEventType = adEventType; return this; } /** * Sets the caller adtech entity's {@link AdTechIdentifier}. * *

See {@link #getCallerAdTech()} for more information. */ @NonNull public Builder setCallerAdTech(@NonNull AdTechIdentifier callerAdTech) { Objects.requireNonNull(callerAdTech, UNSET_CALLER_ADTECH_MESSAGE); mCallerAdTech = callerAdTech; return this; } /** * Sets the caller app's package name. * *

See {@link #getCallerPackageName()} for more information. */ @NonNull public Builder setCallerPackageName(@NonNull String callerPackageName) { Objects.requireNonNull(callerPackageName, UNSET_CALLER_PACKAGE_NAME_MESSAGE); mCallerPackageName = callerPackageName; return this; } /** Builds the {@link UpdateAdCounterHistogramInput} object. */ @NonNull public UpdateAdCounterHistogramInput build() { return new UpdateAdCounterHistogramInput(this); } } }