/* * Copyright (C) 2022 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.measurement; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.net.Uri; import android.os.Parcel; import android.os.Parcelable; import android.view.InputEvent; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.Objects; /** * Class to hold input to measurement registration calls. * @hide */ public final class RegistrationRequest implements Parcelable { /** @hide */ @Retention(RetentionPolicy.SOURCE) @IntDef({ INVALID, REGISTER_SOURCE, REGISTER_TRIGGER, }) public @interface RegistrationType {} /** Invalid registration type used as a default. */ public static final int INVALID = 0; /** * A request to register an Attribution Source event (NOTE: AdServices type not * android.context.AttributionSource). */ public static final int REGISTER_SOURCE = 1; /** A request to register a trigger event. */ public static final int REGISTER_TRIGGER = 2; @RegistrationType private final int mRegistrationType; private final Uri mRegistrationUri; private final InputEvent mInputEvent; private final String mAppPackageName; private final String mSdkPackageName; private final long mRequestTime; private final boolean mIsAdIdPermissionGranted; private final String mAdIdValue; private RegistrationRequest(@NonNull Builder builder) { mRegistrationType = builder.mRegistrationType; mRegistrationUri = builder.mRegistrationUri; mInputEvent = builder.mInputEvent; mAppPackageName = builder.mAppPackageName; mSdkPackageName = builder.mSdkPackageName; mRequestTime = builder.mRequestTime; mIsAdIdPermissionGranted = builder.mIsAdIdPermissionGranted; mAdIdValue = builder.mAdIdValue; } /** * Unpack an RegistrationRequest from a Parcel. */ private RegistrationRequest(Parcel in) { mRegistrationType = in.readInt(); mRegistrationUri = Uri.CREATOR.createFromParcel(in); mAppPackageName = in.readString(); mSdkPackageName = in.readString(); boolean hasInputEvent = in.readBoolean(); if (hasInputEvent) { mInputEvent = InputEvent.CREATOR.createFromParcel(in); } else { mInputEvent = null; } mRequestTime = in.readLong(); mIsAdIdPermissionGranted = in.readBoolean(); boolean hasAdIdValue = in.readBoolean(); if (hasAdIdValue) { mAdIdValue = in.readString(); } else { mAdIdValue = null; } } /** Creator for Parcelable (via reflection). */ @NonNull public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { @Override public RegistrationRequest createFromParcel(Parcel in) { return new RegistrationRequest(in); } @Override public RegistrationRequest[] newArray(int size) { return new RegistrationRequest[size]; } }; /** * For Parcelable, no special marshalled objects. */ public int describeContents() { return 0; } /** * For Parcelable, write out to a Parcel in particular order. */ public void writeToParcel(@NonNull Parcel out, int flags) { Objects.requireNonNull(out); out.writeInt(mRegistrationType); mRegistrationUri.writeToParcel(out, flags); out.writeString(mAppPackageName); out.writeString(mSdkPackageName); if (mInputEvent != null) { out.writeBoolean(true); mInputEvent.writeToParcel(out, flags); } else { out.writeBoolean(false); } out.writeLong(mRequestTime); out.writeBoolean(mIsAdIdPermissionGranted); if (mAdIdValue != null) { out.writeBoolean(true); out.writeString(mAdIdValue); } else { out.writeBoolean(false); } } /** Type of the registration. */ @RegistrationType public int getRegistrationType() { return mRegistrationType; } /** Source URI of the App / Publisher. */ @NonNull public Uri getRegistrationUri() { return mRegistrationUri; } /** InputEvent related to an ad event. */ @Nullable public InputEvent getInputEvent() { return mInputEvent; } /** Package name of the app used for the registration. */ @NonNull public String getAppPackageName() { return mAppPackageName; } /** Package name of the sdk used for the registration. */ @NonNull public String getSdkPackageName() { return mSdkPackageName; } /** Time the request was created, as millis since boot excluding time in deep sleep. */ @NonNull public long getRequestTime() { return mRequestTime; } /** Ad ID Permission */ @NonNull public boolean isAdIdPermissionGranted() { return mIsAdIdPermissionGranted; } /** Ad ID Value */ @Nullable public String getAdIdValue() { return mAdIdValue; } /** * A builder for {@link RegistrationRequest}. */ public static final class Builder { @RegistrationType private final int mRegistrationType; private final Uri mRegistrationUri; private final String mAppPackageName; private final String mSdkPackageName; private InputEvent mInputEvent; private long mRequestTime; private boolean mIsAdIdPermissionGranted; private String mAdIdValue; /** * Builder constructor for {@link RegistrationRequest}. * * @param type registration type, either source or trigger * @param registrationUri registration uri endpoint for registering a source/trigger * @param appPackageName app package name that is calling PP API * @param sdkPackageName sdk package name that is calling PP API * @throws IllegalArgumentException if the scheme for {@code registrationUri} is not HTTPS * or if {@code type} is not one of {@code REGISTER_SOURCE} or {@code REGISTER_TRIGGER} */ public Builder( @RegistrationType int type, @NonNull Uri registrationUri, @NonNull String appPackageName, @NonNull String sdkPackageName) { if (type != REGISTER_SOURCE && type != REGISTER_TRIGGER) { throw new IllegalArgumentException("Invalid registrationType"); } Objects.requireNonNull(registrationUri); if (registrationUri.getScheme() == null || !registrationUri.getScheme().equalsIgnoreCase("https")) { throw new IllegalArgumentException("registrationUri must have an HTTPS scheme"); } Objects.requireNonNull(appPackageName); Objects.requireNonNull(sdkPackageName); mRegistrationType = type; mRegistrationUri = registrationUri; mAppPackageName = appPackageName; mSdkPackageName = sdkPackageName; } /** See {@link RegistrationRequest#getInputEvent}. */ @NonNull public Builder setInputEvent(@Nullable InputEvent event) { mInputEvent = event; return this; } /** See {@link RegistrationRequest#getRequestTime}. */ @NonNull public Builder setRequestTime(long requestTime) { mRequestTime = requestTime; return this; } /** See {@link RegistrationRequest#isAdIdPermissionGranted()}. */ @NonNull public Builder setAdIdPermissionGranted(boolean adIdPermissionGranted) { mIsAdIdPermissionGranted = adIdPermissionGranted; return this; } /** See {@link RegistrationRequest#getAdIdValue()}. */ @NonNull public Builder setAdIdValue(@Nullable String adIdValue) { mAdIdValue = adIdValue; return this; } /** Build the RegistrationRequest. */ @NonNull public RegistrationRequest build() { // Ensure registrationType has been set, // throws IllegalArgumentException if mRegistrationType // isn't a valid choice. if (mRegistrationType != REGISTER_SOURCE && mRegistrationType != REGISTER_TRIGGER) { throw new IllegalArgumentException("Invalid registrationType"); } return new RegistrationRequest(this); } } }