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