1 /* 2 * Copyright (C) 2014 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 android.app.job; 18 19 import android.annotation.IntDef; 20 import android.annotation.NonNull; 21 import android.annotation.Nullable; 22 import android.annotation.RequiresPermission; 23 import android.annotation.SystemApi; 24 import android.annotation.SystemService; 25 import android.content.ClipData; 26 import android.content.Context; 27 import android.os.Bundle; 28 import android.os.PersistableBundle; 29 30 import java.lang.annotation.Retention; 31 import java.lang.annotation.RetentionPolicy; 32 import java.util.List; 33 34 /** 35 * This is an API for scheduling various types of jobs against the framework that will be executed 36 * in your application's own process. 37 * <p> 38 * See {@link android.app.job.JobInfo} for more description of the types of jobs that can be run 39 * and how to construct them. You will construct these JobInfo objects and pass them to the 40 * JobScheduler with {@link #schedule(JobInfo)}. When the criteria declared are met, the 41 * system will execute this job on your application's {@link android.app.job.JobService}. 42 * You identify the service component that implements the logic for your job when you 43 * construct the JobInfo using 44 * {@link android.app.job.JobInfo.Builder#Builder(int,android.content.ComponentName)}. 45 * </p> 46 * <p> 47 * The framework will be intelligent about when it executes jobs, and attempt to batch 48 * and defer them as much as possible. Typically if you don't specify a deadline on a job, it 49 * can be run at any moment depending on the current state of the JobScheduler's internal queue. 50 * <p> 51 * While a job is running, the system holds a wakelock on behalf of your app. For this reason, 52 * you do not need to take any action to guarantee that the device stays awake for the 53 * duration of the job. 54 * </p> 55 * <p>You do not 56 * instantiate this class directly; instead, retrieve it through 57 * {@link android.content.Context#getSystemService 58 * Context.getSystemService(Context.JOB_SCHEDULER_SERVICE)}. 59 * 60 * <p> Prior to Android version {@link android.os.Build.VERSION_CODES#S}, jobs could only have 61 * a maximum of 100 jobs scheduled at a time. Starting with Android version 62 * {@link android.os.Build.VERSION_CODES#S}, that limit has been increased to 150. 63 * Expedited jobs also count towards the limit. 64 * 65 * <p> In Android version {@link android.os.Build.VERSION_CODES#LOLLIPOP}, jobs had a maximum 66 * execution time of one minute. Starting with Android version 67 * {@link android.os.Build.VERSION_CODES#M} and ending with Android version 68 * {@link android.os.Build.VERSION_CODES#R}, jobs had a maximum execution time of 10 minutes. 69 * Starting from Android version {@link android.os.Build.VERSION_CODES#S}, jobs will still be 70 * stopped after 10 minutes if the system is busy or needs the resources, but if not, jobs 71 * may continue running longer than 10 minutes. 72 * 73 * <p class="caution"><strong>Note:</strong> Beginning with API 30 74 * ({@link android.os.Build.VERSION_CODES#R}), JobScheduler will throttle runaway applications. 75 * Calling {@link #schedule(JobInfo)} and other such methods with very high frequency can have a 76 * high cost and so, to make sure the system doesn't get overwhelmed, JobScheduler will begin 77 * to throttle apps, regardless of target SDK version. 78 */ 79 @SystemService(Context.JOB_SCHEDULER_SERVICE) 80 public abstract class JobScheduler { 81 /** @hide */ 82 @IntDef(prefix = { "RESULT_" }, value = { 83 RESULT_FAILURE, 84 RESULT_SUCCESS, 85 }) 86 @Retention(RetentionPolicy.SOURCE) 87 public @interface Result {} 88 89 /** 90 * Returned from {@link #schedule(JobInfo)} if a job wasn't scheduled successfully. Scheduling 91 * can fail for a variety of reasons, including, but not limited to: 92 * <ul> 93 * <li>an invalid parameter was supplied (eg. the run-time for your job is too short, or the 94 * system can't resolve the requisite {@link JobService} in your package)</li> 95 * <li>the app has too many jobs scheduled</li> 96 * <li>the app has tried to schedule too many jobs in a short amount of time</li> 97 * </ul> 98 * Attempting to schedule the job again immediately after receiving this result will not 99 * guarantee a successful schedule. 100 */ 101 public static final int RESULT_FAILURE = 0; 102 /** 103 * Returned from {@link #schedule(JobInfo)} if this job has been successfully scheduled. 104 */ 105 public static final int RESULT_SUCCESS = 1; 106 107 /** 108 * Schedule a job to be executed. Will replace any currently scheduled job with the same 109 * ID with the new information in the {@link JobInfo}. If a job with the given ID is currently 110 * running, it will be stopped. 111 * 112 * <p class="caution"><strong>Note:</strong> Scheduling a job can have a high cost, even if it's 113 * rescheduling the same job and the job didn't execute, especially on platform versions before 114 * version {@link android.os.Build.VERSION_CODES#Q}. As such, the system may throttle calls to 115 * this API if calls are made too frequently in a short amount of time. 116 * 117 * <p>Note: The JobService component needs to be enabled in order to successfully schedule a 118 * job. 119 * 120 * @param job The job you wish scheduled. See 121 * {@link android.app.job.JobInfo.Builder JobInfo.Builder} for more detail on the sorts of jobs 122 * you can schedule. 123 * @return the result of the schedule request. 124 * @throws IllegalArgumentException if the specified {@link JobService} doesn't exist or is 125 * disabled. 126 */ schedule(@onNull JobInfo job)127 public abstract @Result int schedule(@NonNull JobInfo job); 128 129 /** 130 * Similar to {@link #schedule}, but allows you to enqueue work for a new <em>or existing</em> 131 * job. If a job with the same ID is already scheduled, it will be replaced with the 132 * new {@link JobInfo}, but any previously enqueued work will remain and be dispatched the 133 * next time it runs. If a job with the same ID is already running, the new work will be 134 * enqueued for it. 135 * 136 * <p>The work you enqueue is later retrieved through 137 * {@link JobParameters#dequeueWork() JobParameters.dequeueWork}. Be sure to see there 138 * about how to process work; the act of enqueueing work changes how you should handle the 139 * overall lifecycle of an executing job.</p> 140 * 141 * <p>It is strongly encouraged that you use the same {@link JobInfo} for all work you 142 * enqueue. This will allow the system to optimally schedule work along with any pending 143 * and/or currently running work. If the JobInfo changes from the last time the job was 144 * enqueued, the system will need to update the associated JobInfo, which can cause a disruption 145 * in execution. In particular, this can result in any currently running job that is processing 146 * previous work to be stopped and restarted with the new JobInfo.</p> 147 * 148 * <p>It is recommended that you avoid using 149 * {@link JobInfo.Builder#setExtras(PersistableBundle)} or 150 * {@link JobInfo.Builder#setTransientExtras(Bundle)} with a JobInfo you are using to 151 * enqueue work. The system will try to compare these extras with the previous JobInfo, 152 * but there are situations where it may get this wrong and count the JobInfo as changing. 153 * (That said, you should be relatively safe with a simple set of consistent data in these 154 * fields.) You should never use {@link JobInfo.Builder#setClipData(ClipData, int)} with 155 * work you are enqueue, since currently this will always be treated as a different JobInfo, 156 * even if the ClipData contents are exactly the same.</p> 157 * 158 * <p class="caution"><strong>Note:</strong> Scheduling a job can have a high cost, even if it's 159 * rescheduling the same job and the job didn't execute, especially on platform versions before 160 * version {@link android.os.Build.VERSION_CODES#Q}. As such, the system may throttle calls to 161 * this API if calls are made too frequently in a short amount of time. 162 * 163 * <p>Note: The JobService component needs to be enabled in order to successfully schedule a 164 * job. 165 * 166 * @param job The job you wish to enqueue work for. See 167 * {@link android.app.job.JobInfo.Builder JobInfo.Builder} for more detail on the sorts of jobs 168 * you can schedule. 169 * @param work New work to enqueue. This will be available later when the job starts running. 170 * @return the result of the enqueue request. 171 * @throws IllegalArgumentException if the specified {@link JobService} doesn't exist or is 172 * disabled. 173 */ enqueue(@onNull JobInfo job, @NonNull JobWorkItem work)174 public abstract @Result int enqueue(@NonNull JobInfo job, @NonNull JobWorkItem work); 175 176 /** 177 * 178 * @param job The job to be scheduled. 179 * @param packageName The package on behalf of which the job is to be scheduled. This will be 180 * used to track battery usage and appIdleState. 181 * @param userId User on behalf of whom this job is to be scheduled. 182 * @param tag Debugging tag for dumps associated with this job (instead of the service class) 183 * @hide 184 */ 185 @SuppressWarnings("HiddenAbstractMethod") 186 @SystemApi 187 @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) scheduleAsPackage(@onNull JobInfo job, @NonNull String packageName, int userId, String tag)188 public abstract @Result int scheduleAsPackage(@NonNull JobInfo job, @NonNull String packageName, 189 int userId, String tag); 190 191 /** 192 * Cancel the specified job. If the job is currently executing, it is stopped 193 * immediately and the return value from its {@link JobService#onStopJob(JobParameters)} 194 * method is ignored. 195 * 196 * @param jobId unique identifier for the job to be canceled, as supplied to 197 * {@link JobInfo.Builder#Builder(int, android.content.ComponentName) 198 * JobInfo.Builder(int, android.content.ComponentName)}. 199 */ cancel(int jobId)200 public abstract void cancel(int jobId); 201 202 /** 203 * Cancel <em>all</em> jobs that have been scheduled by the calling application. 204 */ cancelAll()205 public abstract void cancelAll(); 206 207 /** 208 * Retrieve all jobs that have been scheduled by the calling application. 209 * 210 * @return a list of all of the app's scheduled jobs. This includes jobs that are 211 * currently started as well as those that are still waiting to run. 212 */ getAllPendingJobs()213 public abstract @NonNull List<JobInfo> getAllPendingJobs(); 214 215 /** 216 * Look up the description of a scheduled job. 217 * 218 * @return The {@link JobInfo} description of the given scheduled job, or {@code null} 219 * if the supplied job ID does not correspond to any job. 220 */ getPendingJob(int jobId)221 public abstract @Nullable JobInfo getPendingJob(int jobId); 222 223 /** 224 * <b>For internal system callers only!</b> 225 * Returns a list of all currently-executing jobs. 226 * @hide 227 */ 228 @SuppressWarnings("HiddenAbstractMethod") getStartedJobs()229 public abstract List<JobInfo> getStartedJobs(); 230 231 /** 232 * <b>For internal system callers only!</b> 233 * Returns a snapshot of the state of all jobs known to the system. 234 * 235 * <p class="note">This is a slow operation, so it should be called sparingly. 236 * @hide 237 */ 238 @SuppressWarnings("HiddenAbstractMethod") getAllJobSnapshots()239 public abstract List<JobSnapshot> getAllJobSnapshots(); 240 }