149 lines
6.6 KiB
Java
149 lines
6.6 KiB
Java
![]() |
/*
|
||
|
* 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.ondevicepersonalization;
|
||
|
|
||
|
import static android.adservices.ondevicepersonalization.OnDevicePersonalizationPermissions.NOTIFY_MEASUREMENT_EVENT;
|
||
|
|
||
|
import android.adservices.ondevicepersonalization.aidl.IOnDevicePersonalizationManagingService;
|
||
|
import android.adservices.ondevicepersonalization.aidl.IRegisterMeasurementEventCallback;
|
||
|
import android.annotation.CallbackExecutor;
|
||
|
import android.annotation.FlaggedApi;
|
||
|
import android.annotation.NonNull;
|
||
|
import android.annotation.RequiresPermission;
|
||
|
import android.annotation.SystemApi;
|
||
|
import android.content.Context;
|
||
|
import android.os.Binder;
|
||
|
import android.os.Bundle;
|
||
|
import android.os.OutcomeReceiver;
|
||
|
import android.os.SystemClock;
|
||
|
|
||
|
import com.android.adservices.ondevicepersonalization.flags.Flags;
|
||
|
import com.android.federatedcompute.internal.util.AbstractServiceBinder;
|
||
|
import com.android.internal.annotations.VisibleForTesting;
|
||
|
import com.android.ondevicepersonalization.internal.util.LoggerFactory;
|
||
|
|
||
|
import java.util.List;
|
||
|
import java.util.Objects;
|
||
|
import java.util.concurrent.Executor;
|
||
|
|
||
|
/**
|
||
|
* Provides APIs for the platform to signal events that are to be handled by the ODP service.
|
||
|
* @hide
|
||
|
*/
|
||
|
@SystemApi
|
||
|
@FlaggedApi(Flags.FLAG_ON_DEVICE_PERSONALIZATION_APIS_ENABLED)
|
||
|
public class OnDevicePersonalizationSystemEventManager {
|
||
|
/** @hide */
|
||
|
public static final String ON_DEVICE_PERSONALIZATION_SYSTEM_EVENT_SERVICE =
|
||
|
"on_device_personalization_system_event_service";
|
||
|
private static final String INTENT_FILTER_ACTION =
|
||
|
"android.OnDevicePersonalizationService";
|
||
|
private static final String ODP_MANAGING_SERVICE_PACKAGE_SUFFIX =
|
||
|
"com.android.ondevicepersonalization.services";
|
||
|
private static final String ALT_ODP_MANAGING_SERVICE_PACKAGE_SUFFIX =
|
||
|
"com.google.android.ondevicepersonalization.services";
|
||
|
private static final LoggerFactory.Logger sLogger = LoggerFactory.getLogger();
|
||
|
|
||
|
// TODO(b/301732670): Define a new service for this manager and bind to it.
|
||
|
private final AbstractServiceBinder<IOnDevicePersonalizationManagingService> mServiceBinder;
|
||
|
private final Context mContext;
|
||
|
|
||
|
/** @hide */
|
||
|
public OnDevicePersonalizationSystemEventManager(Context context) {
|
||
|
this(
|
||
|
context,
|
||
|
AbstractServiceBinder.getServiceBinderByIntent(
|
||
|
context,
|
||
|
INTENT_FILTER_ACTION,
|
||
|
List.of(
|
||
|
ODP_MANAGING_SERVICE_PACKAGE_SUFFIX,
|
||
|
ALT_ODP_MANAGING_SERVICE_PACKAGE_SUFFIX),
|
||
|
0,
|
||
|
IOnDevicePersonalizationManagingService.Stub::asInterface));
|
||
|
}
|
||
|
|
||
|
/** @hide */
|
||
|
@VisibleForTesting
|
||
|
public OnDevicePersonalizationSystemEventManager(
|
||
|
Context context,
|
||
|
AbstractServiceBinder<IOnDevicePersonalizationManagingService> serviceBinder) {
|
||
|
mContext = context;
|
||
|
mServiceBinder = serviceBinder;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Receives a web trigger event from the Measurement API. This is intended to be called by the
|
||
|
* <a href="https://developer.android.com/design-for-safety/privacy-sandbox/guides/attribution">
|
||
|
* Measurement Service</a> when a browser registers an attribution event using the
|
||
|
* <a href="https://github.com/WICG/attribution-reporting-api">Attribution and Reporting API</a>
|
||
|
* with a payload that should be processed by an {@link IsolatedService}.
|
||
|
*
|
||
|
* @param measurementWebTriggerEvent the web trigger payload to be processed.
|
||
|
* @param executor the {@link Executor} on which to invoke the callback.
|
||
|
* @param receiver This either returns a {@code null} on success, or an exception on failure.
|
||
|
*/
|
||
|
@RequiresPermission(NOTIFY_MEASUREMENT_EVENT)
|
||
|
public void notifyMeasurementEvent(
|
||
|
@NonNull MeasurementWebTriggerEventParams measurementWebTriggerEvent,
|
||
|
@NonNull @CallbackExecutor Executor executor,
|
||
|
@NonNull OutcomeReceiver<Void, Exception> receiver) {
|
||
|
Objects.requireNonNull(measurementWebTriggerEvent);
|
||
|
Objects.requireNonNull(executor);
|
||
|
Objects.requireNonNull(receiver);
|
||
|
long startTimeMillis = SystemClock.elapsedRealtime();
|
||
|
|
||
|
try {
|
||
|
final IOnDevicePersonalizationManagingService service =
|
||
|
mServiceBinder.getService(executor);
|
||
|
Bundle bundle = new Bundle();
|
||
|
bundle.putParcelable(Constants.EXTRA_MEASUREMENT_WEB_TRIGGER_PARAMS,
|
||
|
new MeasurementWebTriggerEventParamsParcel(measurementWebTriggerEvent));
|
||
|
// TODO(b/301732670): Update method name in service.
|
||
|
service.registerMeasurementEvent(
|
||
|
Constants.MEASUREMENT_EVENT_TYPE_WEB_TRIGGER,
|
||
|
bundle,
|
||
|
new CallerMetadata.Builder().setStartTimeMillis(startTimeMillis).build(),
|
||
|
new IRegisterMeasurementEventCallback.Stub() {
|
||
|
@Override
|
||
|
public void onSuccess() {
|
||
|
final long token = Binder.clearCallingIdentity();
|
||
|
try {
|
||
|
executor.execute(() -> receiver.onResult(null));
|
||
|
} finally {
|
||
|
Binder.restoreCallingIdentity(token);
|
||
|
}
|
||
|
}
|
||
|
@Override
|
||
|
public void onError(int errorCode) {
|
||
|
final long token = Binder.clearCallingIdentity();
|
||
|
try {
|
||
|
executor.execute(() -> receiver.onError(
|
||
|
new IllegalStateException("Error: " + errorCode)));
|
||
|
} finally {
|
||
|
Binder.restoreCallingIdentity(token);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
);
|
||
|
} catch (IllegalArgumentException | NullPointerException e) {
|
||
|
throw e;
|
||
|
} catch (Exception e) {
|
||
|
receiver.onError(e);
|
||
|
}
|
||
|
}
|
||
|
}
|