summaryrefslogtreecommitdiff
path: root/adservices/service-core/java/com/android/adservices/service/adselection/AdSelectionRunner.java
diff options
context:
space:
mode:
Diffstat (limited to 'adservices/service-core/java/com/android/adservices/service/adselection/AdSelectionRunner.java')
-rw-r--r--adservices/service-core/java/com/android/adservices/service/adselection/AdSelectionRunner.java359
1 files changed, 107 insertions, 252 deletions
diff --git a/adservices/service-core/java/com/android/adservices/service/adselection/AdSelectionRunner.java b/adservices/service-core/java/com/android/adservices/service/adselection/AdSelectionRunner.java
index 2f69f2f3d9..7851ef3986 100644
--- a/adservices/service-core/java/com/android/adservices/service/adselection/AdSelectionRunner.java
+++ b/adservices/service-core/java/com/android/adservices/service/adselection/AdSelectionRunner.java
@@ -23,18 +23,14 @@ import android.adservices.adselection.AdSelectionCallback;
import android.adservices.adselection.AdSelectionConfig;
import android.adservices.adselection.AdSelectionInput;
import android.adservices.adselection.AdSelectionResponse;
-import android.adservices.common.AdSelectionSignals;
import android.adservices.common.AdServicesStatusUtils;
import android.adservices.common.FledgeErrorResponse;
-import android.adservices.exceptions.AdServicesException;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.SuppressLint;
import android.content.Context;
import android.net.Uri;
import android.os.LimitExceededException;
import android.os.RemoteException;
-import android.util.Pair;
import com.android.adservices.LogUtil;
import com.android.adservices.data.adselection.AdSelectionEntryDao;
@@ -43,18 +39,18 @@ import com.android.adservices.data.adselection.DBBuyerDecisionLogic;
import com.android.adservices.data.customaudience.CustomAudienceDao;
import com.android.adservices.data.customaudience.DBCustomAudience;
import com.android.adservices.service.Flags;
-import com.android.adservices.service.common.AdServicesHttpsClient;
import com.android.adservices.service.common.AppImportanceFilter;
import com.android.adservices.service.common.AppImportanceFilter.WrongCallingApplicationStateException;
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.consent.ConsentManager;
-import com.android.adservices.service.devapi.DevContext;
+import com.android.adservices.service.js.JSSandboxIsNotAvailableException;
+import com.android.adservices.service.js.JSScriptEngine;
import com.android.adservices.service.stats.AdServicesLogger;
+import com.android.adservices.service.stats.ApiServiceLatencyCalculator;
import com.android.internal.annotations.VisibleForTesting;
-import com.google.common.base.Function;
import com.google.common.base.Preconditions;
import com.google.common.util.concurrent.AsyncFunction;
import com.google.common.util.concurrent.FluentFuture;
@@ -66,20 +62,13 @@ import com.google.common.util.concurrent.MoreExecutors;
import com.google.common.util.concurrent.UncheckedTimeoutException;
import java.time.Clock;
-import java.time.Instant;
import java.util.List;
import java.util.Objects;
-import java.util.Optional;
-import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
-import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
-import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Supplier;
-import java.util.stream.Collectors;
-
/**
* Orchestrator that runs the Ads Auction/Bidding and Scoring logic The class expects the caller to
@@ -88,7 +77,7 @@ import java.util.stream.Collectors;
*
* <p>Class takes in an executor on which it runs the AdSelection logic
*/
-public final class AdSelectionRunner {
+public abstract class AdSelectionRunner {
@VisibleForTesting static final String AD_SELECTION_ERROR_PATTERN = "%s: %s";
@@ -112,86 +101,90 @@ public final class AdSelectionRunner {
@VisibleForTesting
static final String AD_SELECTION_THROTTLED = "Ad selection exceeded allowed rate limit";
+ @VisibleForTesting
+ static final String JS_SANDBOX_IS_NOT_AVAILABLE =
+ String.format(
+ AD_SELECTION_ERROR_PATTERN,
+ ERROR_AD_SELECTION_FAILURE,
+ "JS Sandbox is not available");
+
public static final long DAY_IN_SECONDS = 60 * 60 * 24;
- @NonNull private final Context mContext;
- @NonNull private final CustomAudienceDao mCustomAudienceDao;
- @NonNull private final AdSelectionEntryDao mAdSelectionEntryDao;
- @NonNull private final AdServicesHttpsClient mAdServicesHttpsClient;
- @NonNull private final ListeningExecutorService mLightweightExecutorService;
- @NonNull private final ListeningExecutorService mBackgroundExecutorService;
- @NonNull private final AdsScoreGenerator mAdsScoreGenerator;
- @NonNull private final AdBidGenerator mAdBidGenerator;
- @NonNull private final AdSelectionIdGenerator mAdSelectionIdGenerator;
- @NonNull private final Clock mClock;
- @NonNull private final ConsentManager mConsentManager;
- @NonNull private final AdServicesLogger mAdServicesLogger;
- @NonNull private final Flags mFlags;
- @NonNull private final AppImportanceFilter mAppImportanceFilter;
- private final int mCallerUid;
- @NonNull private final Supplier<Throttler> mThrottlerSupplier;
- @NonNull private final FledgeAuthorizationFilter mFledgeAuthorizationFilter;
- @NonNull private final FledgeAllowListsFilter mFledgeAllowListsFilter;
+ @NonNull protected final Context mContext;
+ @NonNull protected final CustomAudienceDao mCustomAudienceDao;
+ @NonNull protected final AdSelectionEntryDao mAdSelectionEntryDao;
+ @NonNull protected final ListeningExecutorService mLightweightExecutorService;
+ @NonNull protected final ListeningExecutorService mBackgroundExecutorService;
+ @NonNull protected final ScheduledThreadPoolExecutor mScheduledExecutor;
+ @NonNull protected final AdSelectionIdGenerator mAdSelectionIdGenerator;
+ @NonNull protected final Clock mClock;
+ @NonNull protected final ConsentManager mConsentManager;
+ @NonNull protected final AdServicesLogger mAdServicesLogger;
+ @NonNull protected final Flags mFlags;
+ @NonNull protected final AppImportanceFilter mAppImportanceFilter;
+ @NonNull protected final Supplier<Throttler> mThrottlerSupplier;
+ @NonNull protected final FledgeAuthorizationFilter mFledgeAuthorizationFilter;
+ @NonNull protected final FledgeAllowListsFilter mFledgeAllowListsFilter;
+ @NonNull protected final ApiServiceLatencyCalculator mApiServiceLatencyCalculator;
+ protected final int mCallerUid;
+ /**
+ * @param context service context
+ * @param customAudienceDao DAO to access custom audience storage
+ * @param adSelectionEntryDao DAO to access ad selection storage
+ * @param lightweightExecutorService executor for running short tasks
+ * @param backgroundExecutorService executor for longer running tasks (ex. network calls)
+ * @param scheduledExecutor executor for tasks to be run with a delay or timed executions
+ * @param consentManager instance of {@link ConsentManager} for verifying user consent
+ * @param adServicesLogger logger for logging calls to PPAPI
+ * @param appImportanceFilter filter to assert calling app is running in the foreground
+ * @param flags for accessing feature flags
+ * @param throttlerSupplier supplier for throttling calls to PPAPI
+ * @param callerUid calling app UID
+ * @param fledgeAuthorizationFilter filter for authorizing the caller on certain behavior
+ * @param fledgeAllowListsFilter filter for verifying the caller can call PPAPI
+ */
public AdSelectionRunner(
@NonNull final Context context,
@NonNull final CustomAudienceDao customAudienceDao,
@NonNull final AdSelectionEntryDao adSelectionEntryDao,
- @NonNull final AdServicesHttpsClient adServicesHttpsClient,
@NonNull final ExecutorService lightweightExecutorService,
@NonNull final ExecutorService backgroundExecutorService,
+ @NonNull final ScheduledThreadPoolExecutor scheduledExecutor,
@NonNull final ConsentManager consentManager,
@NonNull final AdServicesLogger adServicesLogger,
- @NonNull final DevContext devContext,
@NonNull AppImportanceFilter appImportanceFilter,
@NonNull final Flags flags,
@NonNull final Supplier<Throttler> throttlerSupplier,
int callerUid,
@NonNull final FledgeAuthorizationFilter fledgeAuthorizationFilter,
- @NonNull final FledgeAllowListsFilter fledgeAllowListsFilter) {
+ @NonNull final FledgeAllowListsFilter fledgeAllowListsFilter,
+ @NonNull final ApiServiceLatencyCalculator apiServiceLatencyCalculator) {
Objects.requireNonNull(context);
Objects.requireNonNull(customAudienceDao);
Objects.requireNonNull(adSelectionEntryDao);
- Objects.requireNonNull(adServicesHttpsClient);
Objects.requireNonNull(lightweightExecutorService);
Objects.requireNonNull(backgroundExecutorService);
Objects.requireNonNull(consentManager);
Objects.requireNonNull(adServicesLogger);
- Objects.requireNonNull(devContext);
Objects.requireNonNull(appImportanceFilter);
Objects.requireNonNull(flags);
Objects.requireNonNull(throttlerSupplier);
Objects.requireNonNull(fledgeAuthorizationFilter);
Objects.requireNonNull(fledgeAllowListsFilter);
+ Preconditions.checkArgument(
+ JSScriptEngine.AvailabilityChecker.isJSSandboxAvailable(),
+ JS_SANDBOX_IS_NOT_AVAILABLE);
+ Objects.requireNonNull(apiServiceLatencyCalculator);
+
mContext = context;
mCustomAudienceDao = customAudienceDao;
mAdSelectionEntryDao = adSelectionEntryDao;
- mAdServicesHttpsClient = adServicesHttpsClient;
mLightweightExecutorService = MoreExecutors.listeningDecorator(lightweightExecutorService);
mBackgroundExecutorService = MoreExecutors.listeningDecorator(backgroundExecutorService);
+ mScheduledExecutor = scheduledExecutor;
mConsentManager = consentManager;
mAdServicesLogger = adServicesLogger;
- mAdsScoreGenerator =
- new AdsScoreGeneratorImpl(
- new AdSelectionScriptEngine(
- mContext,
- () -> flags.getEnforceIsolateMaxHeapSize(),
- () -> flags.getIsolateMaxHeapSizeBytes()),
- mLightweightExecutorService,
- mBackgroundExecutorService,
- mAdServicesHttpsClient,
- devContext,
- mAdSelectionEntryDao,
- flags);
- mAdBidGenerator =
- new AdBidGeneratorImpl(
- context,
- mAdServicesHttpsClient,
- mLightweightExecutorService,
- mBackgroundExecutorService,
- devContext,
- mCustomAudienceDao,
- flags);
mAdSelectionIdGenerator = new AdSelectionIdGenerator();
mClock = Clock.systemUTC();
mFlags = flags;
@@ -200,6 +193,7 @@ public final class AdSelectionRunner {
mCallerUid = callerUid;
mFledgeAuthorizationFilter = fledgeAuthorizationFilter;
mFledgeAllowListsFilter = fledgeAllowListsFilter;
+ mApiServiceLatencyCalculator = apiServiceLatencyCalculator;
}
@VisibleForTesting
@@ -207,12 +201,10 @@ public final class AdSelectionRunner {
@NonNull final Context context,
@NonNull final CustomAudienceDao customAudienceDao,
@NonNull final AdSelectionEntryDao adSelectionEntryDao,
- @NonNull final AdServicesHttpsClient adServicesHttpsClient,
@NonNull final ExecutorService lightweightExecutorService,
@NonNull final ExecutorService backgroundExecutorService,
+ @NonNull final ScheduledThreadPoolExecutor scheduledExecutor,
@NonNull final ConsentManager consentManager,
- @NonNull final AdsScoreGenerator adsScoreGenerator,
- @NonNull final AdBidGenerator adBidGenerator,
@NonNull final AdSelectionIdGenerator adSelectionIdGenerator,
@NonNull Clock clock,
@NonNull final AdServicesLogger adServicesLogger,
@@ -221,32 +213,30 @@ public final class AdSelectionRunner {
@NonNull final Supplier<Throttler> throttlerSupplier,
int callerUid,
@NonNull final FledgeAuthorizationFilter fledgeAuthorizationFilter,
- @NonNull final FledgeAllowListsFilter fledgeAllowListsFilter) {
+ @NonNull final FledgeAllowListsFilter fledgeAllowListsFilter,
+ @NonNull final ApiServiceLatencyCalculator apiServiceLatencyCalculator) {
Objects.requireNonNull(context);
Objects.requireNonNull(customAudienceDao);
Objects.requireNonNull(adSelectionEntryDao);
- Objects.requireNonNull(adServicesHttpsClient);
Objects.requireNonNull(lightweightExecutorService);
Objects.requireNonNull(backgroundExecutorService);
+ Objects.requireNonNull(scheduledExecutor);
Objects.requireNonNull(consentManager);
- Objects.requireNonNull(adsScoreGenerator);
- Objects.requireNonNull(adBidGenerator);
Objects.requireNonNull(adSelectionIdGenerator);
Objects.requireNonNull(clock);
Objects.requireNonNull(adServicesLogger);
Objects.requireNonNull(appImportanceFilter);
Objects.requireNonNull(flags);
Objects.requireNonNull(fledgeAuthorizationFilter);
+ Objects.requireNonNull(apiServiceLatencyCalculator);
mContext = context;
mCustomAudienceDao = customAudienceDao;
mAdSelectionEntryDao = adSelectionEntryDao;
- mAdServicesHttpsClient = adServicesHttpsClient;
mLightweightExecutorService = MoreExecutors.listeningDecorator(lightweightExecutorService);
mBackgroundExecutorService = MoreExecutors.listeningDecorator(backgroundExecutorService);
+ mScheduledExecutor = scheduledExecutor;
mConsentManager = consentManager;
- mAdsScoreGenerator = adsScoreGenerator;
- mAdBidGenerator = adBidGenerator;
mAdSelectionIdGenerator = adSelectionIdGenerator;
mClock = clock;
mAdServicesLogger = adServicesLogger;
@@ -256,6 +246,7 @@ public final class AdSelectionRunner {
mCallerUid = callerUid;
mFledgeAuthorizationFilter = fledgeAuthorizationFilter;
mFledgeAllowListsFilter = fledgeAllowListsFilter;
+ mApiServiceLatencyCalculator = apiServiceLatencyCalculator;
}
/**
@@ -293,8 +284,6 @@ public final class AdSelectionRunner {
@Override
public void onSuccess(DBAdSelection result) {
notifySuccessToCaller(result, callback);
- // TODO(242280808): Schedule a clear for stale data instead of this hack
- clearExpiredAdSelectionData();
}
@Override
@@ -306,12 +295,11 @@ public final class AdSelectionRunner {
} else {
notifyFailureToCaller(callback, t);
}
- // TODO(242280808): Schedule a clear for stale data instead of this hack
- clearExpiredAdSelectionData();
}
},
mLightweightExecutorService);
} catch (Throwable t) {
+ LogUtil.v("run ad selection fails fast with exception %s.", t.toString());
notifyFailureToCaller(callback, t);
}
}
@@ -330,11 +318,15 @@ public final class AdSelectionRunner {
LogUtil.e(e, "Encountered exception during notifying AdSelection callback");
resultCode = AdServicesStatusUtils.STATUS_UNKNOWN_ERROR;
} finally {
+ int overallLatencyMs = mApiServiceLatencyCalculator.getApiServiceOverallLatencyMs();
LogUtil.v(
- "Ad Selection with Id:%d completed, attempted notifying success",
- result.getAdSelectionId());
+ "Ad Selection with Id:%d completed with overall latency %d in ms, "
+ + "attempted notifying success",
+ result.getAdSelectionId(), overallLatencyMs);
+ // TODO(b//253522566): When including logging data from bidding & auction server side
+ // should be able to differentiate the data from the on-device telemetry.
mAdServicesLogger.logFledgeApiCallStats(
- AD_SERVICES_API_CALLED__API_NAME__SELECT_ADS, resultCode);
+ AD_SERVICES_API_CALLED__API_NAME__SELECT_ADS, resultCode, overallLatencyMs);
}
}
@@ -350,8 +342,15 @@ public final class AdSelectionRunner {
LogUtil.e(e, "Encountered exception during notifying AdSelection callback");
resultCode = AdServicesStatusUtils.STATUS_UNKNOWN_ERROR;
} finally {
+ int overallLatencyMs = mApiServiceLatencyCalculator.getApiServiceOverallLatencyMs();
+ LogUtil.v(
+ "Ad Selection with Id:%d completed with overall latency %d in ms, "
+ + "attempted notifying success for a silent failure",
+ mAdSelectionIdGenerator.generateId(), overallLatencyMs);
+ // TODO(b//253522566): When including logging data from bidding & auction server side
+ // should be able to differentiate the data from the on-device telemetry.
mAdServicesLogger.logFledgeApiCallStats(
- AD_SERVICES_API_CALLED__API_NAME__SELECT_ADS, resultCode);
+ AD_SERVICES_API_CALLED__API_NAME__SELECT_ADS, resultCode, overallLatencyMs);
}
}
@@ -372,6 +371,8 @@ public final class AdSelectionRunner {
resultCode = AdServicesStatusUtils.STATUS_INVALID_ARGUMENT;
} else if (t instanceof LimitExceededException) {
resultCode = AdServicesStatusUtils.STATUS_RATE_LIMIT_REACHED;
+ } else if (t instanceof JSSandboxIsNotAvailableException) {
+ resultCode = AdServicesStatusUtils.STATUS_JS_SANDBOX_UNAVAILABLE;
} else {
resultCode = AdServicesStatusUtils.STATUS_INTERNAL_ERROR;
}
@@ -391,8 +392,12 @@ public final class AdSelectionRunner {
LogUtil.e(e, "Encountered exception during notifying AdSelection callback");
resultCode = AdServicesStatusUtils.STATUS_UNKNOWN_ERROR;
} finally {
+ int overallLatencyMs = mApiServiceLatencyCalculator.getApiServiceOverallLatencyMs();
+ LogUtil.v("Ad Selection failed with overall latency %d in ms", overallLatencyMs);
+ // TODO(b//253522566): When including logging data from bidding & auction server side
+ // should be able to differentiate the data from the on-device telemetry.
mAdServicesLogger.logFledgeApiCallStats(
- AD_SERVICES_API_CALLED__API_NAME__SELECT_ADS, resultCode);
+ AD_SERVICES_API_CALLED__API_NAME__SELECT_ADS, resultCode, overallLatencyMs);
}
}
@@ -410,60 +415,34 @@ public final class AdSelectionRunner {
ListenableFuture<List<DBCustomAudience>> buyerCustomAudience =
getBuyersCustomAudience(adSelectionConfig);
+ ListenableFuture<AdSelectionOrchestrationResult> dbAdSelection =
+ orchestrateAdSelection(adSelectionConfig, callerPackageName, buyerCustomAudience);
- AsyncFunction<List<DBCustomAudience>, List<AdBiddingOutcome>> bidAds =
- buyerCAs -> {
- return runAdBidding(buyerCAs, adSelectionConfig);
- };
-
- ListenableFuture<List<AdBiddingOutcome>> biddingOutcome =
- Futures.transformAsync(buyerCustomAudience, bidAds, mLightweightExecutorService);
-
- AsyncFunction<List<AdBiddingOutcome>, List<AdScoringOutcome>> mapBidsToScores =
- bids -> {
- return runAdScoring(bids, adSelectionConfig);
- };
-
- ListenableFuture<List<AdScoringOutcome>> scoredAds =
- Futures.transformAsync(
- biddingOutcome, mapBidsToScores, mLightweightExecutorService);
-
- Function<List<AdScoringOutcome>, AdScoringOutcome> reduceScoresToWinner =
- scores -> {
- return getWinningOutcome(scores);
- };
-
- ListenableFuture<AdScoringOutcome> winningOutcome =
- Futures.transform(scoredAds, reduceScoresToWinner, mLightweightExecutorService);
-
- Function<AdScoringOutcome, Pair<DBAdSelection.Builder, String>> mapWinnerToDBResult =
- scoringWinner -> {
- return createAdSelectionResult(scoringWinner);
- };
-
- ListenableFuture<Pair<DBAdSelection.Builder, String>> dbAdSelectionBuilder =
- Futures.transform(winningOutcome, mapWinnerToDBResult, mLightweightExecutorService);
-
- AsyncFunction<Pair<DBAdSelection.Builder, String>, DBAdSelection> saveResultToPersistence =
+ AsyncFunction<AdSelectionOrchestrationResult, DBAdSelection> saveResultToPersistence =
adSelectionAndJs -> {
return persistAdSelection(
- adSelectionAndJs.first, adSelectionAndJs.second, callerPackageName);
+ adSelectionAndJs.mDbAdSelectionBuilder,
+ adSelectionAndJs.mBuyerDecisionLogicJs,
+ callerPackageName);
};
- return FluentFuture.from(dbAdSelectionBuilder)
+ return FluentFuture.from(dbAdSelection)
.transformAsync(saveResultToPersistence, mLightweightExecutorService)
.withTimeout(
mFlags.getAdSelectionOverallTimeoutMs(),
TimeUnit.MILLISECONDS,
- // TODO(b/237103033): Comply with thread usage policy for AdServices;
- // use a global scheduled executor
- new ScheduledThreadPoolExecutor(1))
+ mScheduledExecutor)
.catching(
TimeoutException.class,
this::handleTimeoutError,
mLightweightExecutorService);
}
+ abstract ListenableFuture<AdSelectionOrchestrationResult> orchestrateAdSelection(
+ @NonNull AdSelectionConfig adSelectionConfig,
+ @NonNull String callerPackageName,
+ @NonNull ListenableFuture<List<DBCustomAudience>> buyerCustomAudience);
+
@Nullable
private DBAdSelection handleTimeoutError(TimeoutException e) {
LogUtil.e(e, "Ad Selection exceeded time limit");
@@ -491,136 +470,6 @@ public final class AdSelectionRunner {
});
}
- private ListenableFuture<List<AdBiddingOutcome>> runAdBidding(
- @NonNull final List<DBCustomAudience> customAudiences,
- @NonNull final AdSelectionConfig adSelectionConfig)
- throws InterruptedException, ExecutionException {
- if (customAudiences.isEmpty()) {
- LogUtil.w("Cannot invoke bidding on empty list of CAs");
- return Futures.immediateFailedFuture(new Throwable("No CAs found for selection"));
- }
-
- // TODO(b/237004875) : Use common thread pool for parallel execution if possible
- ForkJoinPool customThreadPool = new ForkJoinPool(getParallelBiddingCount());
- final AtomicReference<List<ListenableFuture<AdBiddingOutcome>>> bidWinningAds =
- new AtomicReference<>();
-
- try {
- LogUtil.d("Triggering bidding for all %d custom audiences", customAudiences.size());
- customThreadPool
- .submit(
- () -> {
- LogUtil.v("Invoking bidding for #%d CAs", customAudiences.size());
- bidWinningAds.set(
- customAudiences.parallelStream()
- .map(
- customAudience -> {
- return runAdBiddingPerCA(
- customAudience,
- adSelectionConfig);
- })
- .collect(Collectors.toList()));
- })
- .get();
- } catch (InterruptedException e) {
- final String exceptionReason = "Bidding Interrupted Exception";
- LogUtil.e(e, exceptionReason);
- throw new InterruptedException(exceptionReason);
- } catch (ExecutionException e) {
- final String exceptionReason = "Bidding Execution Exception";
- LogUtil.e(e, exceptionReason);
- throw new ExecutionException(e.getCause());
- } finally {
- customThreadPool.shutdownNow();
- }
- return Futures.successfulAsList(bidWinningAds.get());
- }
-
- private int getParallelBiddingCount() {
- int parallelBiddingCountConfigValue = mFlags.getAdSelectionConcurrentBiddingCount();
- int numberOfAvailableProcessors = Runtime.getRuntime().availableProcessors();
- return Math.min(parallelBiddingCountConfigValue, numberOfAvailableProcessors);
- }
-
- private ListenableFuture<AdBiddingOutcome> runAdBiddingPerCA(
- @NonNull final DBCustomAudience customAudience,
- @NonNull final AdSelectionConfig adSelectionConfig) {
- LogUtil.v(String.format("Invoking bidding for CA: %s", customAudience.getName()));
-
- // TODO(b/233239475) : Validate Buyer signals in Ad Selection Config
- AdSelectionSignals buyerSignal =
- Optional.ofNullable(
- adSelectionConfig
- .getPerBuyerSignals()
- .get(customAudience.getBuyer()))
- .orElse(AdSelectionSignals.EMPTY);
- return mAdBidGenerator.runAdBiddingPerCA(
- customAudience,
- adSelectionConfig.getAdSelectionSignals(),
- buyerSignal,
- AdSelectionSignals.EMPTY,
- adSelectionConfig);
- // TODO(b/230569187): get the contextualSignal securely = "invoking app name"
- }
-
- @SuppressLint("DefaultLocale")
- private ListenableFuture<List<AdScoringOutcome>> runAdScoring(
- @NonNull final List<AdBiddingOutcome> adBiddingOutcomes,
- @NonNull final AdSelectionConfig adSelectionConfig)
- throws AdServicesException {
- LogUtil.v("Got %d bidding outcomes", adBiddingOutcomes.size());
- List<AdBiddingOutcome> validBiddingOutcomes =
- adBiddingOutcomes.stream().filter(Objects::nonNull).collect(Collectors.toList());
-
- if (validBiddingOutcomes.isEmpty()) {
- LogUtil.w("Received empty list of Bidding outcomes");
- throw new IllegalStateException(ERROR_NO_VALID_BIDS_FOR_SCORING);
- }
- return mAdsScoreGenerator.runAdScoring(validBiddingOutcomes, adSelectionConfig);
- }
-
- private AdScoringOutcome getWinningOutcome(
- @NonNull List<AdScoringOutcome> overallAdScoringOutcome) {
- LogUtil.v("Scoring completed, generating winning outcome");
- return overallAdScoringOutcome.stream()
- .filter(a -> a.getAdWithScore().getScore() > 0)
- .max(
- (a, b) ->
- Double.compare(
- a.getAdWithScore().getScore(),
- b.getAdWithScore().getScore()))
- .orElseThrow(() -> new IllegalStateException(ERROR_NO_WINNING_AD_FOUND));
- }
-
- /**
- * This method populates an Ad Selection result ready to be persisted in DB, with all the fields
- * except adSelectionId and creation time, which should be created as close as possible to
- * persistence logic
- *
- * @param scoringWinner Winning Ad for overall Ad Selection
- * @return A {@link Pair} with a Builder for {@link DBAdSelection} populated with necessary data
- * and a string containing the JS with the decision logic from this buyer.
- */
- @VisibleForTesting
- Pair<DBAdSelection.Builder, String> createAdSelectionResult(
- @NonNull AdScoringOutcome scoringWinner) {
- DBAdSelection.Builder dbAdSelectionBuilder = new DBAdSelection.Builder();
- LogUtil.v("Creating Ad Selection result from scoring winner");
- dbAdSelectionBuilder
- .setWinningAdBid(scoringWinner.getAdWithScore().getAdWithBid().getBid())
- .setCustomAudienceSignals(
- scoringWinner.getCustomAudienceBiddingInfo().getCustomAudienceSignals())
- .setWinningAdRenderUri(
- scoringWinner.getAdWithScore().getAdWithBid().getAdData().getRenderUri())
- .setBiddingLogicUri(
- scoringWinner.getCustomAudienceBiddingInfo().getBiddingLogicUri())
- .setContextualSignals("{}");
- // TODO(b/230569187): get the contextualSignal securely = "invoking app name"
- return Pair.create(
- dbAdSelectionBuilder,
- scoringWinner.getCustomAudienceBiddingInfo().getBuyerDecisionLogicJs());
- }
-
private ListenableFuture<DBAdSelection> persistAdSelection(
@NonNull DBAdSelection.Builder dbAdSelectionBuilder,
@NonNull String buyerDecisionLogicJS,
@@ -654,7 +503,7 @@ public final class AdSelectionRunner {
* user consent
*/
private Void assertCallerHasUserConsent() throws ConsentManager.RevokedConsentException {
- if (!mConsentManager.getConsent(mContext.getPackageManager()).isGiven()) {
+ if (!mConsentManager.getConsent().isGiven()) {
throw new ConsentManager.RevokedConsentException();
}
return null;
@@ -793,8 +642,14 @@ public final class AdSelectionRunner {
return null;
}
- private void clearExpiredAdSelectionData() {
- Instant expirationTime = mClock.instant().minusSeconds(DAY_IN_SECONDS);
- mAdSelectionEntryDao.removeExpiredAdSelection(expirationTime);
+ static class AdSelectionOrchestrationResult {
+ DBAdSelection.Builder mDbAdSelectionBuilder;
+ String mBuyerDecisionLogicJs;
+
+ AdSelectionOrchestrationResult(
+ DBAdSelection.Builder dbAdSelectionBuilder, String buyerDecisionLogicJs) {
+ this.mDbAdSelectionBuilder = dbAdSelectionBuilder;
+ this.mBuyerDecisionLogicJs = buyerDecisionLogicJs;
+ }
}
}