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.shared.spe.framework; 18 19 import android.app.job.JobParameters; 20 import android.app.job.JobScheduler; 21 import android.app.job.JobService; 22 import android.content.Context; 23 24 import com.android.adservices.service.stats.AdServicesStatsLog; 25 import com.android.adservices.shared.spe.JobServiceConstants.JobEnablementStatus; 26 import com.android.adservices.shared.spe.scheduling.BackoffPolicy; 27 import com.android.adservices.shared.spe.scheduling.PolicyJobScheduler; 28 29 import com.google.common.util.concurrent.Futures; 30 import com.google.common.util.concurrent.ListenableFuture; 31 32 import java.util.concurrent.Future; 33 34 /** 35 * The interface used to implement a background job using the SPE (Scheduling Policy Engine) 36 * framework. For SPE, the execution part will be processed by {@link AbstractJobService} and the 37 * scheduling part will be processed by {@link PolicyJobScheduler}. 38 * 39 * <p>At the minimum effort, the job owner only needs to implement below methods, 40 * 41 * <ul> 42 * <li>{@link JobWorker#getExecutionFuture(Context, ExecutionRuntimeParameters)} 43 * <li>{@link JobWorker#getJobEnablementStatus()} 44 * </ul> 45 * 46 * Override below methods if needed, 47 * 48 * <ul> 49 * <li>{@link JobWorker#getExecutionStopFuture(Context, ExecutionRuntimeParameters)} 50 * </ul> 51 */ 52 public interface JobWorker { 53 /** 54 * Gets the Future for the job execution. It should be the specific task for a job to execute 55 * when JobScheduler invokes {@link JobService#onStartJob(JobParameters)}. For example, if the 56 * job is DbDeletionJob, this future should contain the database deletion logic. See {@link 57 * AbstractJobService} for more details. 58 * 59 * <p>Please chain multiple tasks using mature {@link Future} libraries like {@link 60 * com.google.common.util.concurrent.FluentFuture} to consolidate them into a single {@link 61 * Future} to return. 62 * 63 * @param context the context of the app of a module. 64 * @param executionRuntimeParameters the jobParameters passed in from {@link 65 * JobService#onStartJob(JobParameters)} and extract useful info into a {@link 66 * ExecutionRuntimeParameters}. 67 * @return a {@link ListenableFuture} that will be executed by {@link JobScheduler} in {@link 68 * JobService#onStartJob(JobParameters)}. For {@link ExecutionResult}, please use {@link 69 * ExecutionResult#SUCCESS}. Check {@link ExecutionResult} for more details if you configure 70 * the job that needs to compute the execution result dynamically. 71 */ getExecutionFuture( Context context, ExecutionRuntimeParameters executionRuntimeParameters)72 ListenableFuture<ExecutionResult> getExecutionFuture( 73 Context context, ExecutionRuntimeParameters executionRuntimeParameters); 74 75 /** 76 * Determines if the job execution is enabled. For example, the condition could be a combination 77 * of kill switches and feature flags. The execution will be disabled if the flags indicate so. 78 * 79 * <p><b>Note</b>: In production, it's suggested to always use one (or more) flag(s) to guard 80 * the job execution. For example, 81 * 82 * <p>{@code public int isEnabled() { if (!FlagsFactory.getInstance().getIsFooFeatureEnabled) { 83 * return JOB_ENABLED_STATUS_DISABLED_FOR_KILL_SWITCH_ON; } } } 84 * 85 * @return {@link JobEnablementStatus#JOB_ENABLED_STATUS_ENABLED} if the execution is enabled. 86 * Return other values in {@link JobEnablementStatus} if the execution needs to be disabled. 87 * Please add a skip reason to {@link AdServicesStatsLog} and {@link JobEnablementStatus} if 88 * needed. This will be used for logging in the server. 89 */ 90 @JobEnablementStatus getJobEnablementStatus()91 int getJobEnablementStatus(); 92 93 /** 94 * A default method to get the extra logic to be executed if it's stopped by {@link 95 * JobScheduler} due to reasons like device issues, constraint not met, etc. 96 * 97 * @param context the context of the app of a module. 98 * @param executionRuntimeParameters the jobParameters passed in from {@link 99 * JobService#onStartJob(JobParameters)} and extract useful info into a {@link 100 * ExecutionRuntimeParameters}. 101 * @return a {@link Future} that will be executed by {@link JobScheduler}. By default, it 102 * returns an immediate void future. 103 */ getExecutionStopFuture( Context context, ExecutionRuntimeParameters executionRuntimeParameters)104 default ListenableFuture<Void> getExecutionStopFuture( 105 Context context, ExecutionRuntimeParameters executionRuntimeParameters) { 106 return Futures.immediateVoidFuture(); 107 } 108 109 /** 110 * Determines if the job scheduling is enabled. 111 * 112 * <p>By default, it returns the same value as {@link #getJobEnablementStatus()}. Override this 113 * method when the condition of enablement in job execution and scheduling are different. 114 * 115 * @return {@link JobEnablementStatus#JOB_ENABLED_STATUS_ENABLED} if the scheduling is enabled. 116 * Return other values in {@link JobEnablementStatus} if the scheduling needs to be 117 * disabled. Please add a skip reason to {@link AdServicesStatsLog} and {@link 118 * JobEnablementStatus} if needed. 119 */ 120 @JobEnablementStatus getJobSchedulingEnablementStatus()121 default int getJobSchedulingEnablementStatus() { 122 return getJobEnablementStatus(); 123 } 124 125 /** 126 * A default method to get the backoff policy for failed executions. By default, the failed 127 * execution doesn't retry. 128 * 129 * @return a {@link BackoffPolicy}. 130 */ getBackoffPolicy()131 default BackoffPolicy getBackoffPolicy() { 132 return new BackoffPolicy.Builder().build(); 133 } 134 } 135