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 class="caution"><strong>Note:</strong> Beginning with API 30 61 * ({@link android.os.Build.VERSION_CODES#R}), JobScheduler will throttle runaway applications. 62 * Calling {@link #schedule(JobInfo)} and other such methods with very high frequency can have a 63 * high cost and so, to make sure the system doesn't get overwhelmed, JobScheduler will begin 64 * to throttle apps, regardless of target SDK version. 65 */ 66 @SystemService(Context.JOB_SCHEDULER_SERVICE) 67 public abstract class JobScheduler { 68 /** @hide */ 69 @IntDef(prefix = { "RESULT_" }, value = { 70 RESULT_FAILURE, 71 RESULT_SUCCESS, 72 }) 73 @Retention(RetentionPolicy.SOURCE) 74 public @interface Result {} 75 76 /** 77 * Returned from {@link #schedule(JobInfo)} if a job wasn't scheduled successfully. Scheduling 78 * can fail for a variety of reasons, including, but not limited to: 79 * <ul> 80 * <li>an invalid parameter was supplied (eg. the run-time for your job is too short, or the 81 * system can't resolve the requisite {@link JobService} in your package)</li> 82 * <li>the app has too many jobs scheduled</li> 83 * <li>the app has tried to schedule too many jobs in a short amount of time</li> 84 * </ul> 85 * Attempting to schedule the job again immediately after receiving this result will not 86 * guarantee a successful schedule. 87 */ 88 public static final int RESULT_FAILURE = 0; 89 /** 90 * Returned from {@link #schedule(JobInfo)} if this job has been successfully scheduled. 91 */ 92 public static final int RESULT_SUCCESS = 1; 93 94 /** 95 * Schedule a job to be executed. Will replace any currently scheduled job with the same 96 * ID with the new information in the {@link JobInfo}. If a job with the given ID is currently 97 * running, it will be stopped. 98 * 99 * <p class="caution"><strong>Note:</strong> Scheduling a job can have a high cost, even if it's 100 * rescheduling the same job and the job didn't execute, especially on platform versions before 101 * version {@link android.os.Build.VERSION_CODES#Q}. As such, the system may throttle calls to 102 * this API if calls are made too frequently in a short amount of time. 103 * 104 * @param job The job you wish scheduled. See 105 * {@link android.app.job.JobInfo.Builder JobInfo.Builder} for more detail on the sorts of jobs 106 * you can schedule. 107 * @return the result of the schedule request. 108 */ schedule(@onNull JobInfo job)109 public abstract @Result int schedule(@NonNull JobInfo job); 110 111 /** 112 * Similar to {@link #schedule}, but allows you to enqueue work for a new <em>or existing</em> 113 * job. If a job with the same ID is already scheduled, it will be replaced with the 114 * new {@link JobInfo}, but any previously enqueued work will remain and be dispatched the 115 * next time it runs. If a job with the same ID is already running, the new work will be 116 * enqueued for it. 117 * 118 * <p>The work you enqueue is later retrieved through 119 * {@link JobParameters#dequeueWork() JobParameters.dequeueWork}. Be sure to see there 120 * about how to process work; the act of enqueueing work changes how you should handle the 121 * overall lifecycle of an executing job.</p> 122 * 123 * <p>It is strongly encouraged that you use the same {@link JobInfo} for all work you 124 * enqueue. This will allow the system to optimally schedule work along with any pending 125 * and/or currently running work. If the JobInfo changes from the last time the job was 126 * enqueued, the system will need to update the associated JobInfo, which can cause a disruption 127 * in execution. In particular, this can result in any currently running job that is processing 128 * previous work to be stopped and restarted with the new JobInfo.</p> 129 * 130 * <p>It is recommended that you avoid using 131 * {@link JobInfo.Builder#setExtras(PersistableBundle)} or 132 * {@link JobInfo.Builder#setTransientExtras(Bundle)} with a JobInfo you are using to 133 * enqueue work. The system will try to compare these extras with the previous JobInfo, 134 * but there are situations where it may get this wrong and count the JobInfo as changing. 135 * (That said, you should be relatively safe with a simple set of consistent data in these 136 * fields.) You should never use {@link JobInfo.Builder#setClipData(ClipData, int)} with 137 * work you are enqueue, since currently this will always be treated as a different JobInfo, 138 * even if the ClipData contents are exactly the same.</p> 139 * 140 * @param job The job you wish to enqueue work for. See 141 * {@link android.app.job.JobInfo.Builder JobInfo.Builder} for more detail on the sorts of jobs 142 * you can schedule. 143 * @param work New work to enqueue. This will be available later when the job starts running. 144 * @return the result of the enqueue request. 145 */ enqueue(@onNull JobInfo job, @NonNull JobWorkItem work)146 public abstract @Result int enqueue(@NonNull JobInfo job, @NonNull JobWorkItem work); 147 148 /** 149 * 150 * @param job The job to be scheduled. 151 * @param packageName The package on behalf of which the job is to be scheduled. This will be 152 * used to track battery usage and appIdleState. 153 * @param userId User on behalf of whom this job is to be scheduled. 154 * @param tag Debugging tag for dumps associated with this job (instead of the service class) 155 * @hide 156 */ 157 @SystemApi 158 @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) scheduleAsPackage(@onNull JobInfo job, @NonNull String packageName, int userId, String tag)159 public abstract @Result int scheduleAsPackage(@NonNull JobInfo job, @NonNull String packageName, 160 int userId, String tag); 161 162 /** 163 * Cancel the specified job. If the job is currently executing, it is stopped 164 * immediately and the return value from its {@link JobService#onStopJob(JobParameters)} 165 * method is ignored. 166 * 167 * @param jobId unique identifier for the job to be canceled, as supplied to 168 * {@link JobInfo.Builder#Builder(int, android.content.ComponentName) 169 * JobInfo.Builder(int, android.content.ComponentName)}. 170 */ cancel(int jobId)171 public abstract void cancel(int jobId); 172 173 /** 174 * Cancel <em>all</em> jobs that have been scheduled by the calling application. 175 */ cancelAll()176 public abstract void cancelAll(); 177 178 /** 179 * Retrieve all jobs that have been scheduled by the calling application. 180 * 181 * @return a list of all of the app's scheduled jobs. This includes jobs that are 182 * currently started as well as those that are still waiting to run. 183 */ getAllPendingJobs()184 public abstract @NonNull List<JobInfo> getAllPendingJobs(); 185 186 /** 187 * Look up the description of a scheduled job. 188 * 189 * @return The {@link JobInfo} description of the given scheduled job, or {@code null} 190 * if the supplied job ID does not correspond to any job. 191 */ getPendingJob(int jobId)192 public abstract @Nullable JobInfo getPendingJob(int jobId); 193 194 /** 195 * <b>For internal system callers only!</b> 196 * Returns a list of all currently-executing jobs. 197 * @hide 198 */ getStartedJobs()199 public abstract List<JobInfo> getStartedJobs(); 200 201 /** 202 * <b>For internal system callers only!</b> 203 * Returns a snapshot of the state of all jobs known to the system. 204 * 205 * <p class="note">This is a slow operation, so it should be called sparingly. 206 * @hide 207 */ getAllJobSnapshots()208 public abstract List<JobSnapshot> getAllJobSnapshots(); 209 }