270 lines
10 KiB
Java
270 lines
10 KiB
Java
![]() |
/*
|
||
|
* 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 android.annotation.IntDef;
|
||
|
import android.annotation.NonNull;
|
||
|
import android.annotation.Nullable;
|
||
|
import android.view.InputEvent;
|
||
|
|
||
|
import com.android.internal.util.Preconditions;
|
||
|
|
||
|
import java.lang.annotation.Retention;
|
||
|
import java.lang.annotation.RetentionPolicy;
|
||
|
import java.nio.charset.StandardCharsets;
|
||
|
import java.util.Locale;
|
||
|
import java.util.Objects;
|
||
|
|
||
|
/**
|
||
|
* Request object wrapping the required arguments needed to report an ad event.
|
||
|
*/
|
||
|
public class ReportEventRequest {
|
||
|
public static final int FLAG_REPORTING_DESTINATION_SELLER = 1 << 0;
|
||
|
public static final int FLAG_REPORTING_DESTINATION_BUYER = 1 << 1;
|
||
|
private static final int UNSET_REPORTING_DESTINATIONS = 0;
|
||
|
private static final String UNSET_REPORTING_DESTINATIONS_MESSAGE =
|
||
|
"Reporting destinations bitfield not set.";
|
||
|
private static final String INVALID_REPORTING_DESTINATIONS_MESSAGE =
|
||
|
"Invalid reporting destinations bitfield!";
|
||
|
|
||
|
/** @hide */
|
||
|
public static final long REPORT_EVENT_MAX_INTERACTION_DATA_SIZE_B = 64 * 1024; // 64 KB
|
||
|
|
||
|
private static final String EVENT_DATA_SIZE_MAX_EXCEEDED =
|
||
|
"Event data should not exceed " + REPORT_EVENT_MAX_INTERACTION_DATA_SIZE_B + " bytes";
|
||
|
|
||
|
private final long mAdSelectionId;
|
||
|
@NonNull private final String mEventKey;
|
||
|
@Nullable private final InputEvent mInputEvent;
|
||
|
@NonNull private final String mEventData;
|
||
|
@ReportingDestination private final int mReportingDestinations; // buyer, seller, or both
|
||
|
|
||
|
private ReportEventRequest(@NonNull Builder builder) {
|
||
|
Objects.requireNonNull(builder);
|
||
|
|
||
|
Preconditions.checkArgument(
|
||
|
builder.mAdSelectionId != UNSET_AD_SELECTION_ID, UNSET_AD_SELECTION_ID_MESSAGE);
|
||
|
Preconditions.checkArgument(
|
||
|
builder.mReportingDestinations != UNSET_REPORTING_DESTINATIONS,
|
||
|
UNSET_REPORTING_DESTINATIONS_MESSAGE);
|
||
|
Preconditions.checkArgument(
|
||
|
isValidDestination(builder.mReportingDestinations),
|
||
|
INVALID_REPORTING_DESTINATIONS_MESSAGE);
|
||
|
Preconditions.checkArgument(
|
||
|
builder.mEventData.getBytes(StandardCharsets.UTF_8).length
|
||
|
<= REPORT_EVENT_MAX_INTERACTION_DATA_SIZE_B,
|
||
|
EVENT_DATA_SIZE_MAX_EXCEEDED);
|
||
|
|
||
|
this.mAdSelectionId = builder.mAdSelectionId;
|
||
|
this.mEventKey = builder.mEventKey;
|
||
|
this.mInputEvent = builder.mInputEvent;
|
||
|
this.mEventData = builder.mEventData;
|
||
|
this.mReportingDestinations = builder.mReportingDestinations;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns the adSelectionId, the primary identifier of an ad selection process.
|
||
|
*/
|
||
|
public long getAdSelectionId() {
|
||
|
return mAdSelectionId;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns the event key, the type of ad event to be reported.
|
||
|
*
|
||
|
* <p>This field will be used to fetch the {@code reportingUri} associated with the {@code
|
||
|
* eventKey} registered in {@code registerAdBeacon} after ad selection.
|
||
|
*
|
||
|
* <p>This field should be an exact match to the {@code eventKey} registered in {@code
|
||
|
* registerAdBeacon}. Specific details about {@code registerAdBeacon} can be found at the
|
||
|
* documentation of {@link AdSelectionManager#reportImpression}
|
||
|
*
|
||
|
* <p>The event key (when inspecting its byte array with {@link String#getBytes()}) in {@code
|
||
|
* UTF-8} format should not exceed 40 bytes. Any key exceeding this limit will not be registered
|
||
|
* during the {@code registerAdBeacon} call.
|
||
|
*/
|
||
|
@NonNull
|
||
|
public String getKey() {
|
||
|
return mEventKey;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns the input event associated with the user interaction.
|
||
|
*
|
||
|
* <p>This field is either {@code null}, representing a <em>view</em> event, or has an {@link
|
||
|
* InputEvent} object, representing a <em>click</em> event.
|
||
|
*/
|
||
|
@Nullable
|
||
|
public InputEvent getInputEvent() {
|
||
|
return mInputEvent;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns the ad event data.
|
||
|
*
|
||
|
* <p>After ad selection, this data is generated by the caller. The caller can then call {@link
|
||
|
* AdSelectionManager#reportEvent}. This data will be attached in a POST request to the {@code
|
||
|
* reportingUri} registered in {@code registerAdBeacon}.
|
||
|
*
|
||
|
* <p>The size of {@link String#getBytes()} in {@code UTF-8} format should be below 64KB.
|
||
|
*/
|
||
|
@NonNull
|
||
|
public String getData() {
|
||
|
return mEventData;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns the bitfield of reporting destinations to report to (buyer, seller, or both).
|
||
|
*
|
||
|
* <p>To create this bitfield, place an {@code |} bitwise operator between each {@code
|
||
|
* reportingDestination} to be reported to. For example to only report to buyer, set the
|
||
|
* reportingDestinations field to {@link #FLAG_REPORTING_DESTINATION_BUYER} To only report to
|
||
|
* seller, set the reportingDestinations field to {@link #FLAG_REPORTING_DESTINATION_SELLER} To
|
||
|
* report to both buyers and sellers, set the reportingDestinations field to {@link
|
||
|
* #FLAG_REPORTING_DESTINATION_BUYER} | {@link #FLAG_REPORTING_DESTINATION_SELLER}
|
||
|
*/
|
||
|
@ReportingDestination
|
||
|
public int getReportingDestinations() {
|
||
|
return mReportingDestinations;
|
||
|
}
|
||
|
|
||
|
/** @hide */
|
||
|
@IntDef(
|
||
|
flag = true,
|
||
|
prefix = {"FLAG_REPORTING_DESTINATION"},
|
||
|
value = {FLAG_REPORTING_DESTINATION_SELLER, FLAG_REPORTING_DESTINATION_BUYER})
|
||
|
@Retention(RetentionPolicy.SOURCE)
|
||
|
public @interface ReportingDestination {}
|
||
|
|
||
|
private static boolean isValidDestination(@ReportingDestination int reportingDestinations) {
|
||
|
return 0 < reportingDestinations
|
||
|
&& reportingDestinations
|
||
|
<= (FLAG_REPORTING_DESTINATION_SELLER | FLAG_REPORTING_DESTINATION_BUYER);
|
||
|
}
|
||
|
|
||
|
/** Builder for {@link ReportEventRequest} objects. */
|
||
|
public static final class Builder {
|
||
|
|
||
|
private long mAdSelectionId;
|
||
|
@NonNull private String mEventKey;
|
||
|
@Nullable private InputEvent mInputEvent;
|
||
|
@NonNull private String mEventData;
|
||
|
@ReportingDestination private int mReportingDestinations; // buyer, seller, or both
|
||
|
|
||
|
public Builder(
|
||
|
long adSelectionId,
|
||
|
@NonNull String eventKey,
|
||
|
@NonNull String eventData,
|
||
|
@ReportingDestination int reportingDestinations) {
|
||
|
Objects.requireNonNull(eventKey);
|
||
|
Objects.requireNonNull(eventData);
|
||
|
|
||
|
Preconditions.checkArgument(
|
||
|
adSelectionId != UNSET_AD_SELECTION_ID, UNSET_AD_SELECTION_ID_MESSAGE);
|
||
|
Preconditions.checkArgument(
|
||
|
reportingDestinations != UNSET_REPORTING_DESTINATIONS,
|
||
|
UNSET_REPORTING_DESTINATIONS_MESSAGE);
|
||
|
Preconditions.checkArgument(
|
||
|
isValidDestination(reportingDestinations),
|
||
|
INVALID_REPORTING_DESTINATIONS_MESSAGE);
|
||
|
Preconditions.checkArgument(
|
||
|
eventData.getBytes(StandardCharsets.UTF_8).length
|
||
|
<= REPORT_EVENT_MAX_INTERACTION_DATA_SIZE_B,
|
||
|
EVENT_DATA_SIZE_MAX_EXCEEDED);
|
||
|
|
||
|
this.mAdSelectionId = adSelectionId;
|
||
|
this.mEventKey = eventKey;
|
||
|
this.mEventData = eventData;
|
||
|
this.mReportingDestinations = reportingDestinations;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Sets the ad selection ID with which the rendered ad's events are associated.
|
||
|
*
|
||
|
* <p>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 event key, the type of ad event to be reported.
|
||
|
*
|
||
|
* <p>See {@link #getKey()} for more information.
|
||
|
*/
|
||
|
@NonNull
|
||
|
public Builder setKey(@NonNull String eventKey) {
|
||
|
Objects.requireNonNull(eventKey);
|
||
|
|
||
|
mEventKey = eventKey;
|
||
|
return this;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Sets the input event associated with the user interaction.
|
||
|
*
|
||
|
* <p>See {@link #getInputEvent()} for more information.
|
||
|
*/
|
||
|
@NonNull
|
||
|
public Builder setInputEvent(@Nullable InputEvent inputEvent) {
|
||
|
mInputEvent = inputEvent;
|
||
|
return this;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Sets the ad event data.
|
||
|
*
|
||
|
* <p>See {@link #getData()} for more information.
|
||
|
*/
|
||
|
@NonNull
|
||
|
public Builder setData(@NonNull String eventData) {
|
||
|
Objects.requireNonNull(eventData);
|
||
|
|
||
|
mEventData = eventData;
|
||
|
return this;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Sets the bitfield of reporting destinations to report to (buyer, seller, or both).
|
||
|
*
|
||
|
* <p>See {@link #getReportingDestinations()} for more information.
|
||
|
*/
|
||
|
@NonNull
|
||
|
public Builder setReportingDestinations(@ReportingDestination int reportingDestinations) {
|
||
|
Preconditions.checkArgument(
|
||
|
isValidDestination(reportingDestinations),
|
||
|
INVALID_REPORTING_DESTINATIONS_MESSAGE);
|
||
|
|
||
|
mReportingDestinations = reportingDestinations;
|
||
|
return this;
|
||
|
}
|
||
|
|
||
|
/** Builds the {@link ReportEventRequest} object. */
|
||
|
@NonNull
|
||
|
public ReportEventRequest build() {
|
||
|
return new ReportEventRequest(this);
|
||
|
}
|
||
|
}
|
||
|
}
|