1 /* 2 * Copyright (C) 2024 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.adservices.service.customaudience; 18 19 import static com.android.adservices.service.Flags.FLEDGE_BACKGROUND_FETCH_JOB_FLEX_MS; 20 import static com.android.adservices.service.Flags.FLEDGE_BACKGROUND_FETCH_JOB_PERIOD_MS; 21 import static com.android.adservices.service.consent.AdServicesApiType.FLEDGE; 22 import static com.android.adservices.shared.proto.JobPolicy.BatteryType.BATTERY_TYPE_REQUIRE_NOT_LOW; 23 import static com.android.adservices.shared.spe.JobServiceConstants.JOB_ENABLED_STATUS_DISABLED_FOR_KILL_SWITCH_ON; 24 import static com.android.adservices.shared.spe.JobServiceConstants.JOB_ENABLED_STATUS_DISABLED_FOR_USER_CONSENT_REVOKED; 25 import static com.android.adservices.shared.spe.JobServiceConstants.JOB_ENABLED_STATUS_ENABLED; 26 import static com.android.adservices.shared.spe.framework.ExecutionResult.SUCCESS; 27 import static com.android.adservices.spe.AdServicesJobInfo.FLEDGE_BACKGROUND_FETCH_JOB; 28 29 import android.annotation.RequiresApi; 30 import android.content.Context; 31 import android.os.Build; 32 33 import com.android.adservices.LoggerFactory; 34 import com.android.adservices.concurrency.AdServicesExecutors; 35 import com.android.adservices.service.Flags; 36 import com.android.adservices.service.FlagsFactory; 37 import com.android.adservices.service.consent.ConsentManager; 38 import com.android.adservices.shared.proto.JobPolicy; 39 import com.android.adservices.shared.spe.framework.ExecutionResult; 40 import com.android.adservices.shared.spe.framework.ExecutionRuntimeParameters; 41 import com.android.adservices.shared.spe.framework.JobWorker; 42 import com.android.adservices.shared.spe.scheduling.BackoffPolicy; 43 import com.android.adservices.shared.spe.scheduling.JobSpec; 44 import com.android.adservices.spe.AdServicesJobScheduler; 45 import com.android.adservices.spe.AdServicesJobServiceFactory; 46 import com.android.internal.annotations.VisibleForTesting; 47 48 import com.google.common.util.concurrent.ListenableFuture; 49 50 /** 51 * Background fetch for FLEDGE Custom Audience API, executing periodic garbage collection and custom 52 * audience updates. 53 */ 54 @RequiresApi(Build.VERSION_CODES.S) 55 public class BackgroundFetchJob implements JobWorker { 56 private static final LoggerFactory.Logger sLogger = LoggerFactory.getFledgeLogger(); 57 58 @Override getExecutionFuture( Context context, ExecutionRuntimeParameters executionRuntimeParameters)59 public ListenableFuture<ExecutionResult> getExecutionFuture( 60 Context context, ExecutionRuntimeParameters executionRuntimeParameters) { 61 return BackgroundFetchWorker.getInstance(context) 62 .runBackgroundFetch() 63 .transform(voidResult -> SUCCESS, AdServicesExecutors.getBackgroundExecutor()); 64 } 65 66 @Override getJobEnablementStatus()67 public int getJobEnablementStatus() { 68 Flags flags = FlagsFactory.getFlags(); 69 70 if (!flags.getFledgeBackgroundFetchEnabled()) { 71 sLogger.d("FLEDGE background fetch is disabled; skipping and cancelling job"); 72 return JOB_ENABLED_STATUS_DISABLED_FOR_KILL_SWITCH_ON; 73 } 74 75 if (flags.getFledgeCustomAudienceServiceKillSwitch()) { 76 sLogger.d("FLEDGE Custom Audience API is disabled ; skipping and cancelling job"); 77 return JOB_ENABLED_STATUS_DISABLED_FOR_KILL_SWITCH_ON; 78 } 79 80 // Skip the execution and cancel the job if user consent is revoked. 81 // Use the per-API consent with GA UX. 82 if (!ConsentManager.getInstance().getConsent(FLEDGE).isGiven()) { 83 sLogger.d("User Consent is revoked ; skipping and cancelling job"); 84 return JOB_ENABLED_STATUS_DISABLED_FOR_USER_CONSENT_REVOKED; 85 } 86 return JOB_ENABLED_STATUS_ENABLED; 87 } 88 89 /** 90 * Attempts to schedule the FLEDGE Background Fetch as a singleton periodic job if it is not 91 * already scheduled. 92 * 93 * <p>The background fetch primarily updates custom audiences' ads and bidding data. It also 94 * prunes the custom audience database of any expired data. 95 */ schedule(Flags flags)96 public static void schedule(Flags flags) { 97 // If SPE is not enabled, force to schedule the job with the old JobService. 98 if (!flags.getSpeOnBackgroundFetchJobEnabled()) { 99 sLogger.d("SPE is not enabled. Schedule the job with BackgroundFetchJobService."); 100 int resultCode = 101 BackgroundFetchJobService.scheduleIfNeeded(flags, /* forceSchedule= */ false); 102 103 AdServicesJobServiceFactory.getInstance() 104 .getJobSchedulingLogger() 105 .recordOnSchedulingLegacy(FLEDGE_BACKGROUND_FETCH_JOB.getJobId(), resultCode); 106 return; 107 } 108 109 AdServicesJobScheduler.getInstance().schedule(createDefaultJobSpec()); 110 } 111 112 @VisibleForTesting createDefaultJobSpec()113 static JobSpec createDefaultJobSpec() { 114 JobPolicy jobPolicy = 115 JobPolicy.newBuilder() 116 .setJobId(FLEDGE_BACKGROUND_FETCH_JOB.getJobId()) 117 .setBatteryType(BATTERY_TYPE_REQUIRE_NOT_LOW) 118 .setRequireDeviceIdle(true) 119 .setPeriodicJobParams( 120 JobPolicy.PeriodicJobParams.newBuilder() 121 .setPeriodicIntervalMs( 122 FLEDGE_BACKGROUND_FETCH_JOB_PERIOD_MS) 123 .setFlexInternalMs(FLEDGE_BACKGROUND_FETCH_JOB_FLEX_MS) 124 .build()) 125 .setNetworkType(JobPolicy.NetworkType.NETWORK_TYPE_UNMETERED) 126 .setIsPersisted(true) 127 .build(); 128 129 BackoffPolicy backoffPolicy = 130 new BackoffPolicy.Builder().setShouldRetryOnExecutionStop(true).build(); 131 132 return new JobSpec.Builder(jobPolicy).setBackoffPolicy(backoffPolicy).build(); 133 } 134 } 135