/*
* 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 static android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_ATTRIBUTION;
import android.adservices.common.AdServicesOutcomeReceiver;
import android.adservices.common.OutcomeReceiverConverter;
import android.annotation.CallbackExecutor;
import android.annotation.FlaggedApi;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.app.sdksandbox.SandboxedSdkContext;
import android.content.Context;
import android.net.Uri;
import android.os.Build;
import android.os.OutcomeReceiver;
import android.view.InputEvent;
import androidx.annotation.RequiresApi;
import com.android.adservices.flags.Flags;
import com.android.internal.annotations.VisibleForTesting;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.Objects;
import java.util.concurrent.Executor;
/** MeasurementManager provides APIs to manage source and trigger registrations. */
public class MeasurementManager {
/** @hide */
public static final String MEASUREMENT_SERVICE = "measurement_service";
/**
* This state indicates that Measurement APIs are unavailable. Invoking them will result in an
* {@link UnsupportedOperationException}.
*/
public static final int MEASUREMENT_API_STATE_DISABLED = 0;
/**
* This state indicates that Measurement APIs are enabled.
*/
public static final int MEASUREMENT_API_STATE_ENABLED = 1;
/** @hide */
@Retention(RetentionPolicy.SOURCE)
@IntDef(
prefix = "MEASUREMENT_API_STATE_",
value = {
MEASUREMENT_API_STATE_DISABLED,
MEASUREMENT_API_STATE_ENABLED,
})
public @interface MeasurementApiState {}
private MeasurementCompatibleManager mImpl;
/**
* Factory method for creating an instance of MeasurementManager.
*
* @param context The {@link Context} to use
* @return A {@link MeasurementManager} instance
*/
@NonNull
public static MeasurementManager get(@NonNull Context context) {
// On T+, context.getSystemService() does more than just call constructor.
return (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU)
? context.getSystemService(MeasurementManager.class)
: new MeasurementManager(context);
}
/**
* Create MeasurementManager.
*
* @hide
*/
public MeasurementManager(Context context) {
// In case the MeasurementManager is initiated from inside a sdk_sandbox process the
// fields will be immediately rewritten by the initialize method below.
initialize(context);
}
/**
* Create MeasurementManager
*
* @param compatibleManager the underlying implementation that can be mocked for tests
* @hide
*/
@VisibleForTesting
public MeasurementManager(@NonNull MeasurementCompatibleManager compatibleManager) {
Objects.requireNonNull(compatibleManager);
mImpl = compatibleManager;
}
/**
* Initializes {@link MeasurementManager} with the given {@code context}.
*
*
This method is called by the {@link SandboxedSdkContext} to propagate the correct context.
* For more information check the javadoc on the {@link
* android.app.sdksandbox.SdkSandboxSystemServiceRegistry}.
*
* @hide
* @see android.app.sdksandbox.SdkSandboxSystemServiceRegistry
*/
public MeasurementManager initialize(@NonNull Context context) {
mImpl = MeasurementCompatibleManager.get(context);
return this;
}
/**
* Register an attribution source (click or view).
*
* @param attributionSource the platform issues a request to this URI in order to fetch metadata
* associated with the attribution source. The source metadata is stored on device, making
* it eligible to be matched to future triggers.
* @param inputEvent either an {@link InputEvent} object (for a click event) or null (for a view
* event).
* @param executor used by callback to dispatch results.
* @param callback intended to notify asynchronously the API result.
* @throws IllegalArgumentException if the scheme for {@code attributionSource} is not HTTPS
*/
@RequiresApi(Build.VERSION_CODES.S)
@RequiresPermission(ACCESS_ADSERVICES_ATTRIBUTION)
public void registerSource(
@NonNull Uri attributionSource,
@Nullable InputEvent inputEvent,
@Nullable @CallbackExecutor Executor executor,
@Nullable OutcomeReceiver