| /* |
| * 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 com.android.adservices.service.adselection; |
| |
| import static android.adservices.common.AdServicesStatusUtils.STATUS_INTERNAL_ERROR; |
| import static android.adservices.common.AdServicesStatusUtils.STATUS_INVALID_ARGUMENT; |
| import static android.adservices.common.AdServicesStatusUtils.STATUS_SUCCESS; |
| |
| import static com.android.adservices.service.stats.AdServicesStatsLog.AD_SERVICES_API_CALLED__API_CLASS__FLEDGE; |
| import static com.android.adservices.service.stats.AdServicesStatsLog.AD_SERVICES_API_CALLED__API_NAME__API_NAME_UNKNOWN; |
| import static com.android.adservices.service.stats.AdServicesStatsLog.AD_SERVICES_API_CALLED__API_NAME__OVERRIDE_AD_SELECTION_CONFIG_REMOTE_INFO; |
| import static com.android.adservices.service.stats.AdServicesStatsLog.AD_SERVICES_API_CALLED__API_NAME__REMOVE_AD_SELECTION_CONFIG_REMOTE_INFO_OVERRIDE; |
| import static com.android.adservices.service.stats.AdServicesStatsLog.AD_SERVICES_API_CALLED__API_NAME__REPORT_IMPRESSION; |
| import static com.android.adservices.service.stats.AdServicesStatsLog.AD_SERVICES_API_CALLED__API_NAME__REPORT_INTERACTION; |
| import static com.android.adservices.service.stats.AdServicesStatsLog.AD_SERVICES_API_CALLED__API_NAME__RESET_ALL_AD_SELECTION_CONFIG_REMOTE_OVERRIDES; |
| import static com.android.adservices.service.stats.AdServicesStatsLog.AD_SERVICES_API_CALLED__API_NAME__UPDATE_AD_COUNTER_HISTOGRAM; |
| |
| import android.adservices.adselection.AdSelectionCallback; |
| import android.adservices.adselection.AdSelectionConfig; |
| import android.adservices.adselection.AdSelectionFromOutcomesConfig; |
| import android.adservices.adselection.AdSelectionFromOutcomesInput; |
| import android.adservices.adselection.AdSelectionInput; |
| import android.adservices.adselection.AdSelectionOverrideCallback; |
| import android.adservices.adselection.AdSelectionService; |
| import android.adservices.adselection.BuyersDecisionLogic; |
| import android.adservices.adselection.GetAdSelectionDataCallback; |
| import android.adservices.adselection.GetAdSelectionDataInput; |
| import android.adservices.adselection.PersistAdSelectionResultCallback; |
| import android.adservices.adselection.PersistAdSelectionResultInput; |
| import android.adservices.adselection.RemoveAdCounterHistogramOverrideInput; |
| import android.adservices.adselection.ReportImpressionCallback; |
| import android.adservices.adselection.ReportImpressionInput; |
| import android.adservices.adselection.ReportInteractionCallback; |
| import android.adservices.adselection.ReportInteractionInput; |
| import android.adservices.adselection.SetAdCounterHistogramOverrideInput; |
| import android.adservices.adselection.SetAppInstallAdvertisersCallback; |
| import android.adservices.adselection.SetAppInstallAdvertisersInput; |
| import android.adservices.adselection.UpdateAdCounterHistogramCallback; |
| import android.adservices.adselection.UpdateAdCounterHistogramInput; |
| import android.adservices.common.AdSelectionSignals; |
| import android.adservices.common.AdServicesStatusUtils; |
| import android.adservices.common.CallerMetadata; |
| import android.annotation.NonNull; |
| import android.content.Context; |
| import android.os.Binder; |
| import android.os.Build; |
| import android.os.RemoteException; |
| |
| import androidx.annotation.Nullable; |
| import androidx.annotation.RequiresApi; |
| |
| import com.android.adservices.LoggerFactory; |
| import com.android.adservices.concurrency.AdServicesExecutors; |
| import com.android.adservices.data.adselection.AdSelectionDatabase; |
| import com.android.adservices.data.adselection.AdSelectionDebugReportDao; |
| import com.android.adservices.data.adselection.AdSelectionDebugReportingDatabase; |
| import com.android.adservices.data.adselection.AdSelectionEntryDao; |
| import com.android.adservices.data.adselection.AdSelectionServerDatabase; |
| import com.android.adservices.data.adselection.AppInstallDao; |
| import com.android.adservices.data.adselection.EncryptionContextDao; |
| import com.android.adservices.data.adselection.EncryptionKeyDao; |
| import com.android.adservices.data.adselection.FrequencyCapDao; |
| import com.android.adservices.data.adselection.SharedStorageDatabase; |
| import com.android.adservices.data.customaudience.CustomAudienceDao; |
| import com.android.adservices.data.customaudience.CustomAudienceDatabase; |
| import com.android.adservices.data.signals.EncodedPayloadDao; |
| import com.android.adservices.data.signals.ProtectedSignalsDatabase; |
| import com.android.adservices.service.Flags; |
| import com.android.adservices.service.FlagsFactory; |
| import com.android.adservices.service.adid.AdIdWorker; |
| import com.android.adservices.service.adselection.encryption.AdSelectionEncryptionKeyManager; |
| import com.android.adservices.service.adselection.encryption.ObliviousHttpEncryptor; |
| import com.android.adservices.service.adselection.encryption.ObliviousHttpEncryptorImpl; |
| import com.android.adservices.service.common.AdRenderIdValidator; |
| import com.android.adservices.service.common.AdSelectionServiceFilter; |
| import com.android.adservices.service.common.AppImportanceFilter; |
| import com.android.adservices.service.common.BinderFlagReader; |
| import com.android.adservices.service.common.CallingAppUidSupplier; |
| import com.android.adservices.service.common.CallingAppUidSupplierBinderImpl; |
| import com.android.adservices.service.common.FledgeAllowListsFilter; |
| import com.android.adservices.service.common.FledgeAuthorizationFilter; |
| import com.android.adservices.service.common.Throttler; |
| import com.android.adservices.service.common.cache.CacheProviderFactory; |
| import com.android.adservices.service.common.httpclient.AdServicesHttpsClient; |
| import com.android.adservices.service.consent.ConsentManager; |
| import com.android.adservices.service.devapi.AdSelectionOverrider; |
| import com.android.adservices.service.devapi.DevContext; |
| import com.android.adservices.service.devapi.DevContextFilter; |
| import com.android.adservices.service.js.JSSandboxIsNotAvailableException; |
| import com.android.adservices.service.js.JSScriptEngine; |
| import com.android.adservices.service.measurement.MeasurementImpl; |
| import com.android.adservices.service.profiling.Tracing; |
| import com.android.adservices.service.stats.AdSelectionExecutionLogger; |
| import com.android.adservices.service.stats.AdServicesLogger; |
| import com.android.adservices.service.stats.AdServicesLoggerImpl; |
| import com.android.adservices.service.stats.AdServicesStatsLog; |
| import com.android.adservices.service.stats.Clock; |
| import com.android.internal.annotations.VisibleForTesting; |
| |
| import com.google.common.util.concurrent.FluentFuture; |
| import com.google.common.util.concurrent.FutureCallback; |
| import com.google.common.util.concurrent.ListenableFuture; |
| |
| import java.util.Objects; |
| import java.util.concurrent.ExecutorService; |
| import java.util.concurrent.ScheduledThreadPoolExecutor; |
| |
| /** |
| * Implementation of {@link AdSelectionService}. |
| * |
| * @hide |
| */ |
| // TODO(b/269798827): Enable for R. |
| @RequiresApi(Build.VERSION_CODES.S) |
| public class AdSelectionServiceImpl extends AdSelectionService.Stub { |
| @VisibleForTesting |
| static final String AUCTION_SERVER_API_IS_NOT_AVAILABLE = |
| "Auction Server API is not available!"; |
| |
| private static final LoggerFactory.Logger sLogger = LoggerFactory.getFledgeLogger(); |
| @NonNull private final AdSelectionEntryDao mAdSelectionEntryDao; |
| @NonNull private final AppInstallDao mAppInstallDao; |
| @NonNull private final CustomAudienceDao mCustomAudienceDao; |
| @NonNull private final EncodedPayloadDao mEncodedPayloadDao; |
| @NonNull private final FrequencyCapDao mFrequencyCapDao; |
| @NonNull private final EncryptionContextDao mEncryptionContextDao; |
| @NonNull private final EncryptionKeyDao mEncryptionKeyDao; |
| @NonNull private final AdServicesHttpsClient mAdServicesHttpsClient; |
| @NonNull private final ExecutorService mLightweightExecutor; |
| @NonNull private final ExecutorService mBackgroundExecutor; |
| @NonNull private final ScheduledThreadPoolExecutor mScheduledExecutor; |
| @NonNull private final Context mContext; |
| @NonNull private final DevContextFilter mDevContextFilter; |
| @NonNull private final AdServicesLogger mAdServicesLogger; |
| @NonNull private final Flags mFlags; |
| @NonNull private final CallingAppUidSupplier mCallingAppUidSupplier; |
| @NonNull private final FledgeAuthorizationFilter mFledgeAuthorizationFilter; |
| @NonNull private final AdSelectionServiceFilter mAdSelectionServiceFilter; |
| @NonNull private final AdFilteringFeatureFactory mAdFilteringFeatureFactory; |
| @NonNull private final ConsentManager mConsentManager; |
| @NonNull private final AdRenderIdValidator mAdRenderIdValidator; |
| @NonNull private final ObliviousHttpEncryptor mObliviousHttpEncryptor; |
| @NonNull private final AdSelectionDebugReportDao mAdSelectionDebugReportDao; |
| @NonNull private final AdIdFetcher mAdIdFetcher; |
| private final boolean mShouldUseUnifiedTables; |
| private static final String API_NOT_AUTHORIZED_MSG = |
| "This API is not enabled for the given app because either dev options are disabled or" |
| + " the app is not debuggable."; |
| |
| @VisibleForTesting |
| public AdSelectionServiceImpl( |
| @NonNull AdSelectionEntryDao adSelectionEntryDao, |
| @NonNull AppInstallDao appInstallDao, |
| @NonNull CustomAudienceDao customAudienceDao, |
| @NonNull EncodedPayloadDao encodedPayloadDao, |
| @NonNull FrequencyCapDao frequencyCapDao, |
| @NonNull EncryptionContextDao encryptionContextDao, |
| @NonNull EncryptionKeyDao encryptionKeyDao, |
| @NonNull AdServicesHttpsClient adServicesHttpsClient, |
| @NonNull DevContextFilter devContextFilter, |
| @NonNull ExecutorService lightweightExecutorService, |
| @NonNull ExecutorService backgroundExecutorService, |
| @NonNull ScheduledThreadPoolExecutor scheduledExecutor, |
| @NonNull Context context, |
| @NonNull AdServicesLogger adServicesLogger, |
| @NonNull Flags flags, |
| @NonNull CallingAppUidSupplier callingAppUidSupplier, |
| @NonNull FledgeAuthorizationFilter fledgeAuthorizationFilter, |
| @NonNull AdSelectionServiceFilter adSelectionServiceFilter, |
| @NonNull AdFilteringFeatureFactory adFilteringFeatureFactory, |
| @NonNull ConsentManager consentManager, |
| @NonNull ObliviousHttpEncryptor obliviousHttpEncryptor, |
| @NonNull AdSelectionDebugReportDao adSelectionDebugReportDao, |
| @NonNull AdIdFetcher adIdFetcher, |
| boolean shouldUseUnifiedTables) { |
| Objects.requireNonNull(context, "Context must be provided."); |
| Objects.requireNonNull(adSelectionEntryDao); |
| Objects.requireNonNull(appInstallDao); |
| Objects.requireNonNull(customAudienceDao); |
| Objects.requireNonNull(encodedPayloadDao); |
| Objects.requireNonNull(frequencyCapDao); |
| Objects.requireNonNull(encryptionContextDao); |
| Objects.requireNonNull(encryptionKeyDao); |
| Objects.requireNonNull(adServicesHttpsClient); |
| Objects.requireNonNull(devContextFilter); |
| Objects.requireNonNull(lightweightExecutorService); |
| Objects.requireNonNull(backgroundExecutorService); |
| Objects.requireNonNull(scheduledExecutor); |
| Objects.requireNonNull(adServicesLogger); |
| Objects.requireNonNull(flags); |
| Objects.requireNonNull(adFilteringFeatureFactory); |
| Objects.requireNonNull(consentManager); |
| Objects.requireNonNull(obliviousHttpEncryptor); |
| Objects.requireNonNull(adSelectionDebugReportDao); |
| Objects.requireNonNull(adIdFetcher); |
| |
| mAdSelectionEntryDao = adSelectionEntryDao; |
| mAppInstallDao = appInstallDao; |
| mCustomAudienceDao = customAudienceDao; |
| mEncodedPayloadDao = encodedPayloadDao; |
| mFrequencyCapDao = frequencyCapDao; |
| mEncryptionContextDao = encryptionContextDao; |
| mEncryptionKeyDao = encryptionKeyDao; |
| mAdServicesHttpsClient = adServicesHttpsClient; |
| mDevContextFilter = devContextFilter; |
| mLightweightExecutor = lightweightExecutorService; |
| mBackgroundExecutor = backgroundExecutorService; |
| mScheduledExecutor = scheduledExecutor; |
| mContext = context; |
| mAdServicesLogger = adServicesLogger; |
| mFlags = flags; |
| mCallingAppUidSupplier = callingAppUidSupplier; |
| mFledgeAuthorizationFilter = fledgeAuthorizationFilter; |
| mAdSelectionServiceFilter = adSelectionServiceFilter; |
| mAdFilteringFeatureFactory = adFilteringFeatureFactory; |
| mConsentManager = consentManager; |
| // No support for renderId on device |
| mAdRenderIdValidator = AdRenderIdValidator.AD_RENDER_ID_VALIDATOR_NO_OP; |
| mObliviousHttpEncryptor = obliviousHttpEncryptor; |
| mAdSelectionDebugReportDao = adSelectionDebugReportDao; |
| mAdIdFetcher = adIdFetcher; |
| mShouldUseUnifiedTables = shouldUseUnifiedTables; |
| } |
| |
| /** Creates a new instance of {@link AdSelectionServiceImpl}. */ |
| public static AdSelectionServiceImpl create(@NonNull Context context) { |
| return new AdSelectionServiceImpl(context); |
| } |
| |
| /** Creates an instance of {@link AdSelectionServiceImpl} to be used. */ |
| private AdSelectionServiceImpl(@NonNull Context context) { |
| this( |
| AdSelectionDatabase.getInstance(context).adSelectionEntryDao(), |
| SharedStorageDatabase.getInstance(context).appInstallDao(), |
| CustomAudienceDatabase.getInstance(context).customAudienceDao(), |
| ProtectedSignalsDatabase.getInstance(context).getEncodedPayloadDao(), |
| SharedStorageDatabase.getInstance(context).frequencyCapDao(), |
| AdSelectionServerDatabase.getInstance(context).encryptionContextDao(), |
| AdSelectionServerDatabase.getInstance(context).encryptionKeyDao(), |
| new AdServicesHttpsClient( |
| AdServicesExecutors.getBlockingExecutor(), |
| CacheProviderFactory.create(context, FlagsFactory.getFlags())), |
| DevContextFilter.create(context), |
| AdServicesExecutors.getLightWeightExecutor(), |
| AdServicesExecutors.getBackgroundExecutor(), |
| AdServicesExecutors.getScheduler(), |
| context, |
| AdServicesLoggerImpl.getInstance(), |
| FlagsFactory.getFlags(), |
| CallingAppUidSupplierBinderImpl.create(), |
| FledgeAuthorizationFilter.create(context, AdServicesLoggerImpl.getInstance()), |
| new AdSelectionServiceFilter( |
| context, |
| ConsentManager.getInstance(context), |
| FlagsFactory.getFlags(), |
| AppImportanceFilter.create( |
| context, |
| AD_SERVICES_API_CALLED__API_CLASS__FLEDGE, |
| () -> |
| FlagsFactory.getFlags() |
| .getForegroundStatuslLevelForValidation()), |
| FledgeAuthorizationFilter.create( |
| context, AdServicesLoggerImpl.getInstance()), |
| new FledgeAllowListsFilter( |
| FlagsFactory.getFlags(), AdServicesLoggerImpl.getInstance()), |
| Throttler.getInstance(FlagsFactory.getFlags())), |
| new AdFilteringFeatureFactory( |
| SharedStorageDatabase.getInstance(context).appInstallDao(), |
| SharedStorageDatabase.getInstance(context).frequencyCapDao(), |
| FlagsFactory.getFlags()), |
| ConsentManager.getInstance(context), |
| new ObliviousHttpEncryptorImpl( |
| new AdSelectionEncryptionKeyManager( |
| AdSelectionServerDatabase.getInstance(context).encryptionKeyDao(), |
| FlagsFactory.getFlags(), |
| new AdServicesHttpsClient( |
| AdServicesExecutors.getBlockingExecutor(), |
| CacheProviderFactory.create( |
| context, FlagsFactory.getFlags())), |
| AdServicesExecutors.getLightWeightExecutor()), |
| AdSelectionServerDatabase.getInstance(context).encryptionContextDao(), |
| AdServicesExecutors.getLightWeightExecutor()), |
| AdSelectionDebugReportingDatabase.getInstance(context) |
| .getAdSelectionDebugReportDao(), |
| new AdIdFetcher( |
| AdIdWorker.getInstance(), |
| AdServicesExecutors.getLightWeightExecutor(), |
| AdServicesExecutors.getScheduler()), |
| BinderFlagReader.readFlag( |
| () -> |
| FlagsFactory.getFlags() |
| .getFledgeOnDeviceAuctionShouldUseUnifiedTables())); |
| } |
| |
| @Override |
| public void getAdSelectionData( |
| GetAdSelectionDataInput inputParams, |
| CallerMetadata callerMetadata, |
| GetAdSelectionDataCallback callback) |
| throws RemoteException { |
| int traceCookie = Tracing.beginAsyncSection(Tracing.GET_AD_SELECTION_DATA); |
| int apiName = AdServicesStatsLog.AD_SERVICES_API_CALLED__API_NAME__API_NAME_UNKNOWN; |
| |
| if (BinderFlagReader.readFlag(mFlags::getFledgeAuctionServerKillSwitch)) { |
| throw new IllegalStateException(AUCTION_SERVER_API_IS_NOT_AVAILABLE); |
| } |
| |
| try { |
| Objects.requireNonNull(inputParams); |
| Objects.requireNonNull(inputParams.getSeller()); |
| Objects.requireNonNull(callback); |
| } catch (NullPointerException e) { |
| sLogger.v("The getAdSelectionData() arguments should not be null!"); |
| mAdServicesLogger.logFledgeApiCallStats( |
| apiName, AdServicesStatusUtils.STATUS_INVALID_ARGUMENT, 0); |
| // Rethrow because we want to fail fast |
| throw e; |
| } |
| |
| // Caller permissions must be checked in the binder thread, before anything else |
| mFledgeAuthorizationFilter.assertAppDeclaredCustomAudiencePermission( |
| mContext, inputParams.getCallerPackageName(), apiName); |
| |
| int callingUid = getCallingUid(apiName); |
| final DevContext devContext = mDevContextFilter.createDevContext(); |
| mLightweightExecutor.execute( |
| () -> { |
| runGetAdSelectionData(inputParams, callback, callingUid, devContext); |
| Tracing.endAsyncSection(Tracing.GET_AD_SELECTION_DATA, traceCookie); |
| }); |
| } |
| |
| @Override |
| public void persistAdSelectionResult( |
| PersistAdSelectionResultInput inputParams, |
| CallerMetadata callerMetadata, |
| PersistAdSelectionResultCallback callback) |
| throws RemoteException { |
| int traceCookie = Tracing.beginAsyncSection(Tracing.PERSIST_AD_SELECTION_RESULT); |
| int apiName = AdServicesStatsLog.AD_SERVICES_API_CALLED__API_NAME__API_NAME_UNKNOWN; |
| |
| if (BinderFlagReader.readFlag(mFlags::getFledgeAuctionServerKillSwitch)) { |
| throw new IllegalStateException(AUCTION_SERVER_API_IS_NOT_AVAILABLE); |
| } |
| |
| try { |
| Objects.requireNonNull(inputParams); |
| Objects.requireNonNull(inputParams.getSeller()); |
| Objects.requireNonNull(callback); |
| } catch (NullPointerException e) { |
| sLogger.v("The processAdSelectionResult() arguments should not be null!"); |
| mAdServicesLogger.logFledgeApiCallStats( |
| apiName, AdServicesStatusUtils.STATUS_INVALID_ARGUMENT, 0); |
| // Rethrow because we want to fail fast |
| throw e; |
| } |
| |
| // Caller permissions must be checked in the binder thread, before anything else |
| mFledgeAuthorizationFilter.assertAppDeclaredCustomAudiencePermission( |
| mContext, inputParams.getCallerPackageName(), apiName); |
| |
| int callingUid = getCallingUid(apiName); |
| final DevContext devContext = mDevContextFilter.createDevContext(); |
| final long overallTimeout = |
| BinderFlagReader.readFlag(mFlags::getFledgeAuctionServerOverallTimeoutMs); |
| final boolean forceSearchOnAbsentOwner = |
| BinderFlagReader.readFlag( |
| mFlags::getFledgeAuctionServerForceSearchWhenOwnerIsAbsentEnabled); |
| final boolean auctionServerEnabledForUpdateHistogram = |
| BinderFlagReader.readFlag(mFlags::getFledgeAuctionServerEnabledForUpdateHistogram); |
| |
| PersistAdSelectionResultRunner.ReportingRegistrationLimits limits = |
| PersistAdSelectionResultRunner.ReportingRegistrationLimits.builder() |
| .setMaxRegisteredAdBeaconsTotalCount( |
| BinderFlagReader.readFlag( |
| mFlags |
| ::getFledgeReportImpressionMaxRegisteredAdBeaconsTotalCount)) |
| .setMaxInteractionKeySize( |
| BinderFlagReader.readFlag( |
| mFlags |
| ::getFledgeReportImpressionRegisteredAdBeaconsMaxInteractionKeySizeB)) |
| .setMaxInteractionReportingUriSize( |
| BinderFlagReader.readFlag( |
| mFlags |
| ::getFledgeReportImpressionMaxInteractionReportingUriSizeB)) |
| .setMaxRegisteredAdBeaconsPerAdTechCount( |
| BinderFlagReader.readFlag( |
| mFlags |
| ::getFledgeReportImpressionMaxRegisteredAdBeaconsPerAdTechCount)) |
| .build(); |
| AuctionResultValidator auctionResultValidator = |
| new AuctionResultValidator( |
| mFledgeAuthorizationFilter, |
| BinderFlagReader.readFlag(mFlags::getDisableFledgeEnrollmentCheck)); |
| mLightweightExecutor.execute( |
| () -> { |
| PersistAdSelectionResultRunner runner = |
| new PersistAdSelectionResultRunner( |
| mObliviousHttpEncryptor, |
| mAdSelectionEntryDao, |
| mCustomAudienceDao, |
| mAdSelectionServiceFilter, |
| mBackgroundExecutor, |
| mLightweightExecutor, |
| mScheduledExecutor, |
| callingUid, |
| devContext, |
| overallTimeout, |
| forceSearchOnAbsentOwner, |
| limits, |
| mAdFilteringFeatureFactory.getAdCounterHistogramUpdater( |
| mAdSelectionEntryDao, |
| auctionServerEnabledForUpdateHistogram), |
| auctionResultValidator); |
| runner.run(inputParams, callback); |
| Tracing.endAsyncSection(Tracing.PERSIST_AD_SELECTION_RESULT, traceCookie); |
| }); |
| } |
| |
| // TODO(b/233116758): Validate all the fields inside the adSelectionConfig. |
| @Override |
| public void selectAds( |
| @NonNull AdSelectionInput inputParams, |
| @NonNull CallerMetadata callerMetadata, |
| @NonNull AdSelectionCallback callback) { |
| selectAds(inputParams, callerMetadata, callback, null); |
| } |
| |
| /** |
| * This method takes an extra callback which is triggered once all background tasks for ad |
| * selection are complete. Only required for testing. |
| */ |
| @VisibleForTesting |
| public void selectAds( |
| @NonNull AdSelectionInput inputParams, |
| @NonNull CallerMetadata callerMetadata, |
| @NonNull AdSelectionCallback partialCallback, |
| @Nullable AdSelectionCallback fullCallback) { |
| final AdSelectionExecutionLogger adSelectionExecutionLogger = |
| new AdSelectionExecutionLogger( |
| callerMetadata, Clock.SYSTEM_CLOCK, mContext, mAdServicesLogger); |
| int apiName = AdServicesStatsLog.AD_SERVICES_API_CALLED__API_NAME__SELECT_ADS; |
| |
| try { |
| Objects.requireNonNull(inputParams); |
| Objects.requireNonNull(partialCallback); |
| } catch (NullPointerException exception) { |
| int overallLatencyMs = adSelectionExecutionLogger.getRunAdSelectionOverallLatencyInMs(); |
| sLogger.v( |
| "The selectAds(AdSelectionConfig) arguments should not be null, failed with" |
| + " overall latency %d in ms.", |
| overallLatencyMs); |
| mAdServicesLogger.logFledgeApiCallStats( |
| apiName, STATUS_INVALID_ARGUMENT, overallLatencyMs); |
| // Rethrow because we want to fail fast |
| throw exception; |
| } |
| |
| // Caller permissions must be checked in the binder thread, before anything else |
| mFledgeAuthorizationFilter.assertAppDeclaredCustomAudiencePermission( |
| mContext, inputParams.getCallerPackageName(), apiName); |
| |
| int callingUid = getCallingUid(apiName); |
| |
| DevContext devContext = mDevContextFilter.createDevContext(); |
| final boolean auctionServerEnabledForUpdateHistogram = |
| BinderFlagReader.readFlag(mFlags::getFledgeAuctionServerEnabledForUpdateHistogram); |
| mLightweightExecutor.execute( |
| () -> |
| runAdSelection( |
| inputParams, |
| partialCallback, |
| fullCallback, |
| adSelectionExecutionLogger, |
| callingUid, |
| devContext, |
| auctionServerEnabledForUpdateHistogram)); |
| } |
| |
| private void runGetAdSelectionData( |
| GetAdSelectionDataInput inputParams, |
| GetAdSelectionDataCallback callback, |
| int callingUid, |
| DevContext devContext) { |
| ListenableFuture<AuctionServerDebugReporting> auctionServerDebugReportingFuture = |
| AuctionServerDebugReporting.createInstance( |
| mFlags, |
| mAdIdFetcher, |
| inputParams.getCallerPackageName(), |
| callingUid, |
| mLightweightExecutor); |
| |
| FluentFuture.from(auctionServerDebugReportingFuture) |
| .addCallback( |
| new FutureCallback<>() { |
| @Override |
| public void onSuccess( |
| AuctionServerDebugReporting auctionServerDebugReporting) { |
| sLogger.v( |
| "Auction Server Debug reporting enabled: %b", |
| auctionServerDebugReporting.isEnabled()); |
| GetAdSelectionDataRunner runner = |
| new GetAdSelectionDataRunner( |
| mObliviousHttpEncryptor, |
| mAdSelectionEntryDao, |
| mCustomAudienceDao, |
| mEncodedPayloadDao, |
| mAdSelectionServiceFilter, |
| mAdFilteringFeatureFactory.getAdFilterer(), |
| mBackgroundExecutor, |
| mLightweightExecutor, |
| AdServicesExecutors.getBlockingExecutor(), |
| mScheduledExecutor, |
| mFlags, |
| callingUid, |
| devContext, |
| auctionServerDebugReporting); |
| runner.run(inputParams, callback); |
| } |
| |
| @Override |
| public void onFailure(Throwable t) { |
| sLogger.e( |
| t, |
| "Failed to create Auction Server Debug Reporting instance," |
| + " debug reporting is disabled"); |
| GetAdSelectionDataRunner runner = |
| new GetAdSelectionDataRunner( |
| mObliviousHttpEncryptor, |
| mAdSelectionEntryDao, |
| mCustomAudienceDao, |
| mEncodedPayloadDao, |
| mAdSelectionServiceFilter, |
| mAdFilteringFeatureFactory.getAdFilterer(), |
| mBackgroundExecutor, |
| mLightweightExecutor, |
| AdServicesExecutors.getBlockingExecutor(), |
| mScheduledExecutor, |
| mFlags, |
| callingUid, |
| devContext, |
| AuctionServerDebugReporting |
| .createForDebugReportingDisabled()); |
| runner.run(inputParams, callback); |
| } |
| }, |
| mLightweightExecutor); |
| } |
| |
| private void runAdSelection( |
| AdSelectionInput inputParams, |
| AdSelectionCallback partialCallback, |
| @Nullable AdSelectionCallback fullCallback, |
| AdSelectionExecutionLogger adSelectionExecutionLogger, |
| int callingUid, |
| DevContext devContext, |
| boolean auctionServerEnabledForUpdateHistogram) { |
| |
| ListenableFuture<DebugReporting> debugReportingFuture = |
| DebugReporting.createInstance( |
| mContext, |
| mFlags, |
| mAdServicesHttpsClient, |
| devContext, |
| mAdSelectionDebugReportDao, |
| mLightweightExecutor, |
| mAdIdFetcher, |
| inputParams.getCallerPackageName(), |
| callingUid); |
| |
| FluentFuture.from(debugReportingFuture) |
| .addCallback( |
| new FutureCallback<>() { |
| @Override |
| public void onSuccess(DebugReporting debugReporting) { |
| sLogger.v( |
| "Debug reporting enabled: %b", debugReporting.isEnabled()); |
| runAdSelectionWithDebugReporting( |
| inputParams, |
| partialCallback, |
| fullCallback, |
| adSelectionExecutionLogger, |
| callingUid, |
| devContext, |
| auctionServerEnabledForUpdateHistogram, |
| debugReporting); |
| } |
| |
| @Override |
| public void onFailure(Throwable t) { |
| sLogger.e( |
| t, |
| "Failed to create Debug Reporting instance, debug reporting" |
| + " is disabled"); |
| runAdSelectionWithDebugReporting( |
| inputParams, |
| partialCallback, |
| fullCallback, |
| adSelectionExecutionLogger, |
| callingUid, |
| devContext, |
| auctionServerEnabledForUpdateHistogram, |
| new DebugReportingDisabled()); |
| } |
| }, |
| mLightweightExecutor); |
| } |
| |
| private void runAdSelectionWithDebugReporting( |
| AdSelectionInput inputParams, |
| AdSelectionCallback partialCallback, |
| @Nullable AdSelectionCallback fullCallback, |
| AdSelectionExecutionLogger adSelectionExecutionLogger, |
| int callingUid, |
| DevContext devContext, |
| boolean auctionServerEnabledForUpdateHistogram, |
| @NonNull DebugReporting debugReporting) { |
| |
| // TODO(b/249298855): Evolve off device ad selection logic. |
| if (mFlags.getAdSelectionOffDeviceEnabled()) { |
| runOffDeviceAdSelection( |
| devContext, |
| inputParams, |
| partialCallback, |
| adSelectionExecutionLogger, |
| mAdSelectionServiceFilter, |
| callingUid, |
| auctionServerEnabledForUpdateHistogram, |
| debugReporting, |
| fullCallback); |
| } else { |
| runOnDeviceAdSelection( |
| devContext, |
| inputParams, |
| partialCallback, |
| adSelectionExecutionLogger, |
| mAdSelectionServiceFilter, |
| callingUid, |
| auctionServerEnabledForUpdateHistogram, |
| debugReporting, |
| fullCallback); |
| } |
| } |
| |
| private void runOnDeviceAdSelection( |
| DevContext devContext, |
| @NonNull AdSelectionInput inputParams, |
| @NonNull AdSelectionCallback callback, |
| @NonNull AdSelectionExecutionLogger adSelectionExecutionLogger, |
| @NonNull AdSelectionServiceFilter adSelectionServiceFilter, |
| final int callerUid, |
| final boolean auctionServerEnabledForUpdateHistogram, |
| @NonNull DebugReporting debugReporting, |
| @Nullable AdSelectionCallback fullCallback) { |
| |
| OnDeviceAdSelectionRunner runner = |
| new OnDeviceAdSelectionRunner( |
| mContext, |
| mCustomAudienceDao, |
| mAdSelectionEntryDao, |
| mAdServicesHttpsClient, |
| mLightweightExecutor, |
| mBackgroundExecutor, |
| mScheduledExecutor, |
| mAdServicesLogger, |
| devContext, |
| mFlags, |
| adSelectionExecutionLogger, |
| adSelectionServiceFilter, |
| mAdFilteringFeatureFactory.getAdFilterer(), |
| mAdFilteringFeatureFactory.getAdCounterKeyCopier(), |
| mAdFilteringFeatureFactory.getAdCounterHistogramUpdater( |
| mAdSelectionEntryDao, auctionServerEnabledForUpdateHistogram), |
| mAdFilteringFeatureFactory.getFrequencyCapAdDataValidator(), |
| debugReporting, |
| callerUid, |
| mShouldUseUnifiedTables); |
| runner.runAdSelection(inputParams, callback, devContext, fullCallback); |
| } |
| |
| private void runOffDeviceAdSelection( |
| DevContext devContext, |
| @NonNull AdSelectionInput inputParams, |
| @NonNull AdSelectionCallback callback, |
| @NonNull AdSelectionExecutionLogger adSelectionExecutionLogger, |
| @NonNull AdSelectionServiceFilter adSelectionServiceFilter, |
| int callerUid, |
| boolean auctionServerEnabledForUpdateHistogram, |
| @NonNull DebugReporting debugReporting, |
| @Nullable AdSelectionCallback fullCallback) { |
| TrustedServerAdSelectionRunner runner = |
| new TrustedServerAdSelectionRunner( |
| mContext, |
| mCustomAudienceDao, |
| mAdSelectionEntryDao, |
| mAdServicesHttpsClient, |
| mLightweightExecutor, |
| mBackgroundExecutor, |
| mScheduledExecutor, |
| mAdServicesLogger, |
| devContext, |
| mFlags, |
| adSelectionExecutionLogger, |
| adSelectionServiceFilter, |
| mAdFilteringFeatureFactory.getAdFilterer(), |
| mAdFilteringFeatureFactory.getFrequencyCapAdDataValidator(), |
| mAdFilteringFeatureFactory.getAdCounterHistogramUpdater( |
| mAdSelectionEntryDao, auctionServerEnabledForUpdateHistogram), |
| mAdRenderIdValidator, |
| debugReporting, |
| callerUid); |
| runner.runAdSelection(inputParams, callback, devContext, fullCallback); |
| } |
| |
| /** |
| * Returns an ultimate winner ad of given list of previous winner ads. |
| * |
| * @param inputParams includes list of outcomes, signals and uri to download selection logic |
| * @param callerMetadata caller's metadata for stat logging |
| * @param callback delivers the results via OutcomeReceiver |
| */ |
| @Override |
| public void selectAdsFromOutcomes( |
| @NonNull AdSelectionFromOutcomesInput inputParams, |
| @NonNull CallerMetadata callerMetadata, |
| @NonNull AdSelectionCallback callback) |
| throws RemoteException { |
| int apiName = AdServicesStatsLog.AD_SERVICES_API_CALLED__API_NAME__SELECT_ADS_FROM_OUTCOMES; |
| |
| // TODO(257134800): Add telemetry |
| try { |
| Objects.requireNonNull(inputParams); |
| Objects.requireNonNull(callback); |
| } catch (NullPointerException e) { |
| sLogger.v( |
| "The selectAds(AdSelectionFromOutcomesConfig) arguments should not be null," |
| + " failed"); |
| mAdServicesLogger.logFledgeApiCallStats( |
| apiName, AdServicesStatusUtils.STATUS_INVALID_ARGUMENT, 0); |
| // Rethrow because we want to fail fast |
| throw e; |
| } |
| |
| // Caller permissions must be checked in the binder thread, before anything else |
| mFledgeAuthorizationFilter.assertAppDeclaredCustomAudiencePermission( |
| mContext, inputParams.getCallerPackageName(), apiName); |
| |
| int callingUid = getCallingUid(apiName); |
| |
| DevContext devContext = mDevContextFilter.createDevContext(); |
| mLightweightExecutor.execute( |
| () -> { |
| OutcomeSelectionRunner runner = |
| new OutcomeSelectionRunner( |
| mAdSelectionEntryDao, |
| mBackgroundExecutor, |
| mLightweightExecutor, |
| mScheduledExecutor, |
| mAdServicesHttpsClient, |
| mAdServicesLogger, |
| devContext, |
| mContext, |
| mFlags, |
| mAdSelectionServiceFilter, |
| mAdFilteringFeatureFactory.getAdCounterKeyCopier(), |
| callingUid); |
| runner.runOutcomeSelection(inputParams, callback); |
| }); |
| } |
| |
| @Override |
| public void reportImpression( |
| @NonNull ReportImpressionInput requestParams, |
| @NonNull ReportImpressionCallback callback) { |
| int apiName = AD_SERVICES_API_CALLED__API_NAME__REPORT_IMPRESSION; |
| |
| try { |
| Objects.requireNonNull(requestParams); |
| Objects.requireNonNull(callback); |
| } catch (NullPointerException exception) { |
| mAdServicesLogger.logFledgeApiCallStats(apiName, STATUS_INVALID_ARGUMENT, 0); |
| // Rethrow because we want to fail fast |
| throw exception; |
| } |
| |
| // Caller permissions must be checked in the binder thread, before anything else |
| mFledgeAuthorizationFilter.assertAppDeclaredCustomAudiencePermission( |
| mContext, requestParams.getCallerPackageName(), apiName); |
| |
| DevContext devContext = mDevContextFilter.createDevContext(); |
| |
| int callingUid = getCallingUid(apiName); |
| |
| // ImpressionReporter enables Auction Server flow reporting and sets the stage for Phase 2 |
| // in go/rb-rm-unified-flow-reporting whereas ImpressionReporterLegacy is the logic before |
| // Phase 1. FLEDGE_AUCTION_SERVER_REPORTING_ENABLED flag controls which logic is called. |
| if (BinderFlagReader.readFlag(mFlags::getFledgeAuctionServerEnabledForReportImpression)) { |
| ImpressionReporter reporter = |
| new ImpressionReporter( |
| mContext, |
| mLightweightExecutor, |
| mBackgroundExecutor, |
| mScheduledExecutor, |
| mAdSelectionEntryDao, |
| mCustomAudienceDao, |
| mAdServicesHttpsClient, |
| devContext, |
| mAdServicesLogger, |
| mFlags, |
| mAdSelectionServiceFilter, |
| mFledgeAuthorizationFilter, |
| mAdFilteringFeatureFactory.getFrequencyCapAdDataValidator(), |
| callingUid); |
| reporter.reportImpression(requestParams, callback); |
| } else { |
| ImpressionReporterLegacy reporter = |
| new ImpressionReporterLegacy( |
| mContext, |
| mLightweightExecutor, |
| mBackgroundExecutor, |
| mScheduledExecutor, |
| mAdSelectionEntryDao, |
| mCustomAudienceDao, |
| mAdServicesHttpsClient, |
| devContext, |
| mAdServicesLogger, |
| mFlags, |
| mAdSelectionServiceFilter, |
| mFledgeAuthorizationFilter, |
| mAdFilteringFeatureFactory.getFrequencyCapAdDataValidator(), |
| callingUid, |
| mShouldUseUnifiedTables); |
| reporter.reportImpression(requestParams, callback); |
| } |
| } |
| |
| @Override |
| public void reportInteraction( |
| @NonNull ReportInteractionInput inputParams, |
| @NonNull ReportInteractionCallback callback) { |
| int apiName = AD_SERVICES_API_CALLED__API_NAME__REPORT_INTERACTION; |
| |
| try { |
| Objects.requireNonNull(inputParams); |
| Objects.requireNonNull(callback); |
| } catch (NullPointerException exception) { |
| mAdServicesLogger.logFledgeApiCallStats(apiName, STATUS_INVALID_ARGUMENT, 0); |
| // Rethrow because we want to fail fast |
| throw exception; |
| } |
| |
| // Caller permissions must be checked in the binder thread, before anything else |
| mFledgeAuthorizationFilter.assertAppDeclaredCustomAudiencePermission( |
| mContext, inputParams.getCallerPackageName(), apiName); |
| |
| int callerUid = getCallingUid(apiName); |
| DevContext devContext = mDevContextFilter.createDevContext(); |
| |
| // Get an instance of measurement service |
| // Binder identity is cleared and eventually restored to allow reading values of device |
| // config flags. |
| MeasurementImpl measurementService; |
| final long token = Binder.clearCallingIdentity(); |
| try { |
| measurementService = MeasurementImpl.getInstance(mContext); |
| } finally { |
| Binder.restoreCallingIdentity(token); |
| } |
| |
| // Get an instance of the event reporter |
| EventReporter eventReporter = |
| new EventReporterFactory( |
| mAdSelectionEntryDao, |
| mAdServicesHttpsClient, |
| mLightweightExecutor, |
| mBackgroundExecutor, |
| mAdServicesLogger, |
| mFlags, |
| mAdSelectionServiceFilter, |
| callerUid, |
| mFledgeAuthorizationFilter, |
| devContext, |
| measurementService, |
| mConsentManager, |
| mContext) |
| .getEventReporter(); |
| |
| eventReporter.reportInteraction(inputParams, callback); |
| } |
| |
| @Override |
| public void setAppInstallAdvertisers( |
| @NonNull SetAppInstallAdvertisersInput request, |
| @NonNull SetAppInstallAdvertisersCallback callback) |
| throws RemoteException { |
| int apiName = |
| AdServicesStatsLog.AD_SERVICES_API_CALLED__API_NAME__SET_APP_INSTALL_ADVERTISERS; |
| |
| try { |
| Objects.requireNonNull(request); |
| Objects.requireNonNull(callback); |
| } catch (NullPointerException exception) { |
| mAdServicesLogger.logFledgeApiCallStats(apiName, STATUS_INVALID_ARGUMENT, 0); |
| // Rethrow because we want to fail fast |
| throw exception; |
| } |
| |
| // Caller permissions must be checked in the binder thread, before anything else |
| mFledgeAuthorizationFilter.assertAppDeclaredCustomAudiencePermission( |
| mContext, request.getCallerPackageName(), apiName); |
| |
| AppInstallAdvertisersSetter setter = |
| new AppInstallAdvertisersSetter( |
| mAppInstallDao, |
| mBackgroundExecutor, |
| mAdServicesLogger, |
| mFlags, |
| mAdSelectionServiceFilter, |
| mConsentManager, |
| getCallingUid(apiName), |
| mDevContextFilter.createDevContext()); |
| setter.setAppInstallAdvertisers(request, callback); |
| } |
| |
| @Override |
| public void updateAdCounterHistogram( |
| @NonNull UpdateAdCounterHistogramInput inputParams, |
| @NonNull UpdateAdCounterHistogramCallback callback) { |
| int apiName = AD_SERVICES_API_CALLED__API_NAME__UPDATE_AD_COUNTER_HISTOGRAM; |
| |
| try { |
| Objects.requireNonNull(inputParams); |
| Objects.requireNonNull(callback); |
| } catch (NullPointerException exception) { |
| mAdServicesLogger.logFledgeApiCallStats(apiName, STATUS_INVALID_ARGUMENT, 0); |
| // Rethrow because we want to fail fast |
| throw exception; |
| } |
| |
| // Caller permissions must be checked in the binder thread, before anything else |
| mFledgeAuthorizationFilter.assertAppDeclaredCustomAudiencePermission( |
| mContext, inputParams.getCallerPackageName(), apiName); |
| |
| final int callingUid = getCallingUid(apiName); |
| final int adCounterHistogramAbsoluteMaxTotalEventCount = |
| BinderFlagReader.readFlag( |
| mFlags::getFledgeAdCounterHistogramAbsoluteMaxTotalEventCount); |
| final int adCounterHistogramLowerMaxTotalEventCount = |
| BinderFlagReader.readFlag( |
| mFlags::getFledgeAdCounterHistogramLowerMaxTotalEventCount); |
| final int adCounterHistogramAbsoluteMaxPerBuyerEventCount = |
| BinderFlagReader.readFlag( |
| mFlags::getFledgeAdCounterHistogramAbsoluteMaxPerBuyerEventCount); |
| final int adCounterHistogramLowerMaxPerBuyerEventCount = |
| BinderFlagReader.readFlag( |
| mFlags::getFledgeAdCounterHistogramLowerMaxPerBuyerEventCount); |
| final boolean auctionServerEnabledForUpdateHistogram = |
| BinderFlagReader.readFlag(mFlags::getFledgeAuctionServerEnabledForUpdateHistogram); |
| |
| final UpdateAdCounterHistogramWorker worker = |
| new UpdateAdCounterHistogramWorker( |
| new AdCounterHistogramUpdaterImpl( |
| mAdSelectionEntryDao, |
| mFrequencyCapDao, |
| adCounterHistogramAbsoluteMaxTotalEventCount, |
| adCounterHistogramLowerMaxTotalEventCount, |
| adCounterHistogramAbsoluteMaxPerBuyerEventCount, |
| adCounterHistogramLowerMaxPerBuyerEventCount, |
| auctionServerEnabledForUpdateHistogram, |
| mShouldUseUnifiedTables), |
| mBackgroundExecutor, |
| // TODO(b/235841960): Use the same injected clock as AdSelectionRunner |
| // after aligning on Clock usage |
| java.time.Clock.systemUTC(), |
| mAdServicesLogger, |
| mFlags, |
| mAdSelectionServiceFilter, |
| mConsentManager, |
| callingUid, |
| mDevContextFilter.createDevContext()); |
| |
| worker.updateAdCounterHistogram(inputParams, callback); |
| } |
| |
| @Override |
| public void overrideAdSelectionConfigRemoteInfo( |
| @NonNull AdSelectionConfig adSelectionConfig, |
| @NonNull String decisionLogicJS, |
| @NonNull AdSelectionSignals trustedScoringSignals, |
| @NonNull BuyersDecisionLogic buyersDecisionLogic, |
| @NonNull AdSelectionOverrideCallback callback) { |
| int apiName = AD_SERVICES_API_CALLED__API_NAME__OVERRIDE_AD_SELECTION_CONFIG_REMOTE_INFO; |
| |
| try { |
| Objects.requireNonNull(adSelectionConfig); |
| Objects.requireNonNull(decisionLogicJS); |
| Objects.requireNonNull(buyersDecisionLogic); |
| Objects.requireNonNull(callback); |
| } catch (NullPointerException exception) { |
| mAdServicesLogger.logFledgeApiCallStats(apiName, STATUS_INVALID_ARGUMENT, 0); |
| // Rethrow because we want to fail fast |
| throw exception; |
| } |
| |
| DevContext devContext = mDevContextFilter.createDevContext(); |
| |
| if (!devContext.getDevOptionsEnabled()) { |
| mAdServicesLogger.logFledgeApiCallStats( |
| apiName, AdServicesStatusUtils.STATUS_INTERNAL_ERROR, 0); |
| throw new SecurityException(API_NOT_AUTHORIZED_MSG); |
| } |
| |
| // Caller permissions must be checked with a non-null callingAppPackageName |
| mFledgeAuthorizationFilter.assertAppDeclaredCustomAudiencePermission( |
| mContext, devContext.getCallingAppPackageName(), apiName); |
| |
| int callingUid = getCallingUid(apiName); |
| |
| AdSelectionOverrider overrider = |
| new AdSelectionOverrider( |
| devContext, |
| mAdSelectionEntryDao, |
| mLightweightExecutor, |
| mBackgroundExecutor, |
| mContext.getPackageManager(), |
| ConsentManager.getInstance(mContext), |
| mAdServicesLogger, |
| AppImportanceFilter.create( |
| mContext, |
| AD_SERVICES_API_CALLED__API_CLASS__FLEDGE, |
| () -> |
| FlagsFactory.getFlags() |
| .getForegroundStatuslLevelForValidation()), |
| mFlags, |
| callingUid); |
| |
| overrider.addOverride( |
| adSelectionConfig, |
| decisionLogicJS, |
| trustedScoringSignals, |
| buyersDecisionLogic, |
| callback); |
| } |
| |
| private int getCallingUid(int apiNameLoggingId) { |
| try { |
| return mCallingAppUidSupplier.getCallingAppUid(); |
| } catch (IllegalStateException illegalStateException) { |
| mAdServicesLogger.logFledgeApiCallStats( |
| apiNameLoggingId, AdServicesStatusUtils.STATUS_INTERNAL_ERROR, 0); |
| throw illegalStateException; |
| } |
| } |
| |
| @Override |
| public void removeAdSelectionConfigRemoteInfoOverride( |
| @NonNull AdSelectionConfig adSelectionConfig, |
| @NonNull AdSelectionOverrideCallback callback) { |
| // Auto-generated variable name is too long for lint check |
| int apiName = |
| AD_SERVICES_API_CALLED__API_NAME__REMOVE_AD_SELECTION_CONFIG_REMOTE_INFO_OVERRIDE; |
| |
| try { |
| Objects.requireNonNull(adSelectionConfig); |
| Objects.requireNonNull(callback); |
| } catch (NullPointerException exception) { |
| mAdServicesLogger.logFledgeApiCallStats(apiName, STATUS_INVALID_ARGUMENT, 0); |
| // Rethrow because we want to fail fast |
| throw exception; |
| } |
| |
| DevContext devContext = mDevContextFilter.createDevContext(); |
| |
| if (!devContext.getDevOptionsEnabled()) { |
| mAdServicesLogger.logFledgeApiCallStats( |
| apiName, AdServicesStatusUtils.STATUS_INTERNAL_ERROR, 0); |
| throw new SecurityException(API_NOT_AUTHORIZED_MSG); |
| } |
| |
| // Caller permissions must be checked with a non-null callingAppPackageName |
| mFledgeAuthorizationFilter.assertAppDeclaredCustomAudiencePermission( |
| mContext, devContext.getCallingAppPackageName(), apiName); |
| |
| int callingUid = getCallingUid(apiName); |
| |
| AdSelectionOverrider overrider = |
| new AdSelectionOverrider( |
| devContext, |
| mAdSelectionEntryDao, |
| mLightweightExecutor, |
| mBackgroundExecutor, |
| mContext.getPackageManager(), |
| ConsentManager.getInstance(mContext), |
| mAdServicesLogger, |
| AppImportanceFilter.create( |
| mContext, |
| AD_SERVICES_API_CALLED__API_CLASS__FLEDGE, |
| () -> |
| FlagsFactory.getFlags() |
| .getForegroundStatuslLevelForValidation()), |
| mFlags, |
| callingUid); |
| |
| overrider.removeOverride(adSelectionConfig, callback); |
| } |
| |
| @Override |
| public void resetAllAdSelectionConfigRemoteOverrides( |
| @NonNull AdSelectionOverrideCallback callback) { |
| // Auto-generated variable name is too long for lint check |
| int apiName = |
| AD_SERVICES_API_CALLED__API_NAME__RESET_ALL_AD_SELECTION_CONFIG_REMOTE_OVERRIDES; |
| |
| try { |
| Objects.requireNonNull(callback); |
| } catch (NullPointerException exception) { |
| mAdServicesLogger.logFledgeApiCallStats(apiName, STATUS_INVALID_ARGUMENT, 0); |
| // Rethrow because we want to fail fast |
| throw exception; |
| } |
| |
| DevContext devContext = mDevContextFilter.createDevContext(); |
| |
| if (!devContext.getDevOptionsEnabled()) { |
| mAdServicesLogger.logFledgeApiCallStats( |
| apiName, AdServicesStatusUtils.STATUS_INTERNAL_ERROR, 0); |
| throw new SecurityException(API_NOT_AUTHORIZED_MSG); |
| } |
| |
| // Caller permissions must be checked with a non-null callingAppPackageName |
| mFledgeAuthorizationFilter.assertAppDeclaredCustomAudiencePermission( |
| mContext, devContext.getCallingAppPackageName(), apiName); |
| |
| int callingUid = getCallingUid(apiName); |
| |
| AdSelectionOverrider overrider = |
| new AdSelectionOverrider( |
| devContext, |
| mAdSelectionEntryDao, |
| mLightweightExecutor, |
| mBackgroundExecutor, |
| mContext.getPackageManager(), |
| ConsentManager.getInstance(mContext), |
| mAdServicesLogger, |
| AppImportanceFilter.create( |
| mContext, |
| AD_SERVICES_API_CALLED__API_CLASS__FLEDGE, |
| () -> |
| FlagsFactory.getFlags() |
| .getForegroundStatuslLevelForValidation()), |
| mFlags, |
| callingUid); |
| |
| overrider.removeAllOverridesForAdSelectionConfig(callback); |
| } |
| |
| @Override |
| public void overrideAdSelectionFromOutcomesConfigRemoteInfo( |
| @NonNull AdSelectionFromOutcomesConfig config, |
| @NonNull String selectionLogicJs, |
| @NonNull AdSelectionSignals selectionSignals, |
| @NonNull AdSelectionOverrideCallback callback) { |
| int apiName = AD_SERVICES_API_CALLED__API_NAME__API_NAME_UNKNOWN; |
| |
| try { |
| Objects.requireNonNull(config); |
| Objects.requireNonNull(selectionLogicJs); |
| Objects.requireNonNull(selectionSignals); |
| Objects.requireNonNull(callback); |
| } catch (NullPointerException exception) { |
| mAdServicesLogger.logFledgeApiCallStats( |
| apiName, AdServicesStatusUtils.STATUS_INVALID_ARGUMENT, 0); |
| // Rethrow because we want to fail fast |
| throw exception; |
| } |
| |
| DevContext devContext = mDevContextFilter.createDevContext(); |
| |
| if (!devContext.getDevOptionsEnabled()) { |
| mAdServicesLogger.logFledgeApiCallStats( |
| apiName, AdServicesStatusUtils.STATUS_INTERNAL_ERROR, 0); |
| throw new SecurityException(API_NOT_AUTHORIZED_MSG); |
| } |
| |
| // Caller permissions must be checked with a non-null callingAppPackageName |
| mFledgeAuthorizationFilter.assertAppDeclaredCustomAudiencePermission( |
| mContext, devContext.getCallingAppPackageName(), apiName); |
| |
| int callingUid = getCallingUid(apiName); |
| |
| AdSelectionOverrider overrider = |
| new AdSelectionOverrider( |
| devContext, |
| mAdSelectionEntryDao, |
| mLightweightExecutor, |
| mBackgroundExecutor, |
| mContext.getPackageManager(), |
| ConsentManager.getInstance(mContext), |
| mAdServicesLogger, |
| AppImportanceFilter.create( |
| mContext, |
| AD_SERVICES_API_CALLED__API_CLASS__FLEDGE, |
| () -> |
| FlagsFactory.getFlags() |
| .getForegroundStatuslLevelForValidation()), |
| mFlags, |
| callingUid); |
| |
| overrider.addOverride(config, selectionLogicJs, selectionSignals, callback); |
| } |
| |
| @Override |
| public void removeAdSelectionFromOutcomesConfigRemoteInfoOverride( |
| @NonNull AdSelectionFromOutcomesConfig config, |
| @NonNull AdSelectionOverrideCallback callback) { |
| // Auto-generated variable name is too long for lint check |
| int apiName = AD_SERVICES_API_CALLED__API_NAME__API_NAME_UNKNOWN; |
| |
| try { |
| Objects.requireNonNull(config); |
| Objects.requireNonNull(callback); |
| } catch (NullPointerException exception) { |
| mAdServicesLogger.logFledgeApiCallStats(apiName, STATUS_INVALID_ARGUMENT, 0); |
| // Rethrow because we want to fail fast |
| throw exception; |
| } |
| |
| DevContext devContext = mDevContextFilter.createDevContext(); |
| |
| if (!devContext.getDevOptionsEnabled()) { |
| mAdServicesLogger.logFledgeApiCallStats( |
| apiName, AdServicesStatusUtils.STATUS_INTERNAL_ERROR, 0); |
| throw new SecurityException(API_NOT_AUTHORIZED_MSG); |
| } |
| |
| // Caller permissions must be checked with a non-null callingAppPackageName |
| mFledgeAuthorizationFilter.assertAppDeclaredCustomAudiencePermission( |
| mContext, devContext.getCallingAppPackageName(), apiName); |
| |
| int callingUid = getCallingUid(apiName); |
| |
| AdSelectionOverrider overrider = |
| new AdSelectionOverrider( |
| devContext, |
| mAdSelectionEntryDao, |
| mLightweightExecutor, |
| mBackgroundExecutor, |
| mContext.getPackageManager(), |
| ConsentManager.getInstance(mContext), |
| mAdServicesLogger, |
| AppImportanceFilter.create( |
| mContext, |
| AD_SERVICES_API_CALLED__API_CLASS__FLEDGE, |
| () -> |
| FlagsFactory.getFlags() |
| .getForegroundStatuslLevelForValidation()), |
| mFlags, |
| callingUid); |
| |
| overrider.removeOverride(config, callback); |
| } |
| |
| @Override |
| public void resetAllAdSelectionFromOutcomesConfigRemoteOverrides( |
| @NonNull AdSelectionOverrideCallback callback) { |
| // Auto-generated variable name is too long for lint check |
| int apiName = AD_SERVICES_API_CALLED__API_NAME__API_NAME_UNKNOWN; |
| |
| try { |
| Objects.requireNonNull(callback); |
| } catch (NullPointerException exception) { |
| mAdServicesLogger.logFledgeApiCallStats(apiName, STATUS_INVALID_ARGUMENT, 0); |
| // Rethrow because we want to fail fast |
| throw exception; |
| } |
| |
| DevContext devContext = mDevContextFilter.createDevContext(); |
| |
| if (!devContext.getDevOptionsEnabled()) { |
| mAdServicesLogger.logFledgeApiCallStats( |
| apiName, AdServicesStatusUtils.STATUS_INTERNAL_ERROR, 0); |
| throw new SecurityException(API_NOT_AUTHORIZED_MSG); |
| } |
| |
| // Caller permissions must be checked with a non-null callingAppPackageName |
| mFledgeAuthorizationFilter.assertAppDeclaredCustomAudiencePermission( |
| mContext, devContext.getCallingAppPackageName(), apiName); |
| |
| int callingUid = getCallingUid(apiName); |
| |
| AdSelectionOverrider overrider = |
| new AdSelectionOverrider( |
| devContext, |
| mAdSelectionEntryDao, |
| mLightweightExecutor, |
| mBackgroundExecutor, |
| mContext.getPackageManager(), |
| ConsentManager.getInstance(mContext), |
| mAdServicesLogger, |
| AppImportanceFilter.create( |
| mContext, |
| AD_SERVICES_API_CALLED__API_CLASS__FLEDGE, |
| () -> |
| FlagsFactory.getFlags() |
| .getForegroundStatuslLevelForValidation()), |
| mFlags, |
| callingUid); |
| |
| overrider.removeAllOverridesForAdSelectionFromOutcomes(callback); |
| } |
| |
| @Override |
| public void setAdCounterHistogramOverride( |
| @NonNull SetAdCounterHistogramOverrideInput inputParams, |
| @NonNull AdSelectionOverrideCallback callback) { |
| int apiName = AD_SERVICES_API_CALLED__API_NAME__API_NAME_UNKNOWN; |
| |
| try { |
| Objects.requireNonNull(inputParams); |
| Objects.requireNonNull(callback); |
| } catch (NullPointerException exception) { |
| mAdServicesLogger.logFledgeApiCallStats(apiName, STATUS_INVALID_ARGUMENT, 0); |
| // Rethrow because we want to fail fast |
| throw exception; |
| } |
| |
| DevContext devContext = mDevContextFilter.createDevContext(); |
| |
| if (!devContext.getDevOptionsEnabled()) { |
| mAdServicesLogger.logFledgeApiCallStats( |
| apiName, AdServicesStatusUtils.STATUS_INTERNAL_ERROR, 0); |
| throw new SecurityException(API_NOT_AUTHORIZED_MSG); |
| } |
| |
| // Caller permissions must be checked with a non-null callingAppPackageName |
| mFledgeAuthorizationFilter.assertAppDeclaredCustomAudiencePermission( |
| mContext, devContext.getCallingAppPackageName(), apiName); |
| |
| // TODO(b/265204820): Implement service |
| int status = STATUS_SUCCESS; |
| try { |
| callback.onSuccess(); |
| } catch (RemoteException exception) { |
| status = STATUS_INTERNAL_ERROR; |
| } finally { |
| mAdServicesLogger.logFledgeApiCallStats(apiName, status, 0); |
| } |
| } |
| |
| @Override |
| public void removeAdCounterHistogramOverride( |
| @NonNull RemoveAdCounterHistogramOverrideInput inputParams, |
| @NonNull AdSelectionOverrideCallback callback) { |
| int apiName = AD_SERVICES_API_CALLED__API_NAME__API_NAME_UNKNOWN; |
| |
| try { |
| Objects.requireNonNull(inputParams); |
| Objects.requireNonNull(callback); |
| } catch (NullPointerException exception) { |
| mAdServicesLogger.logFledgeApiCallStats(apiName, STATUS_INVALID_ARGUMENT, 0); |
| // Rethrow because we want to fail fast |
| throw exception; |
| } |
| |
| DevContext devContext = mDevContextFilter.createDevContext(); |
| |
| if (!devContext.getDevOptionsEnabled()) { |
| mAdServicesLogger.logFledgeApiCallStats( |
| apiName, AdServicesStatusUtils.STATUS_INTERNAL_ERROR, 0); |
| throw new SecurityException(API_NOT_AUTHORIZED_MSG); |
| } |
| |
| // Caller permissions must be checked with a non-null callingAppPackageName |
| mFledgeAuthorizationFilter.assertAppDeclaredCustomAudiencePermission( |
| mContext, devContext.getCallingAppPackageName(), apiName); |
| |
| // TODO(b/265204820): Implement service |
| int status = STATUS_SUCCESS; |
| try { |
| callback.onSuccess(); |
| } catch (RemoteException exception) { |
| status = STATUS_INTERNAL_ERROR; |
| } finally { |
| mAdServicesLogger.logFledgeApiCallStats(apiName, status, 0); |
| } |
| } |
| |
| @Override |
| public void resetAllAdCounterHistogramOverrides(@NonNull AdSelectionOverrideCallback callback) { |
| int apiName = AD_SERVICES_API_CALLED__API_NAME__API_NAME_UNKNOWN; |
| |
| try { |
| Objects.requireNonNull(callback); |
| } catch (NullPointerException exception) { |
| mAdServicesLogger.logFledgeApiCallStats(apiName, STATUS_INVALID_ARGUMENT, 0); |
| // Rethrow because we want to fail fast |
| throw exception; |
| } |
| |
| DevContext devContext = mDevContextFilter.createDevContext(); |
| |
| if (!devContext.getDevOptionsEnabled()) { |
| mAdServicesLogger.logFledgeApiCallStats( |
| apiName, AdServicesStatusUtils.STATUS_INTERNAL_ERROR, 0); |
| throw new SecurityException(API_NOT_AUTHORIZED_MSG); |
| } |
| |
| // Caller permissions must be checked with a non-null callingAppPackageName |
| mFledgeAuthorizationFilter.assertAppDeclaredCustomAudiencePermission( |
| mContext, devContext.getCallingAppPackageName(), apiName); |
| |
| // TODO(b/265204820): Implement service |
| int status = STATUS_SUCCESS; |
| try { |
| callback.onSuccess(); |
| } catch (RemoteException exception) { |
| status = STATUS_INTERNAL_ERROR; |
| } finally { |
| mAdServicesLogger.logFledgeApiCallStats(apiName, status, 0); |
| } |
| } |
| |
| /** Close down method to be invoked when the PPAPI process is shut down. */ |
| @SuppressWarnings("FutureReturnValueIgnored") |
| public void destroy() { |
| sLogger.i("Shutting down AdSelectionService"); |
| try { |
| JSScriptEngine jsScriptEngine = JSScriptEngine.getInstance(mContext, sLogger); |
| jsScriptEngine.shutdown(); |
| } catch (JSSandboxIsNotAvailableException exception) { |
| sLogger.i("Java script sandbox is not available, not shutting down JSScriptEngine."); |
| } |
| } |
| } |