JobInfo.java revision 900c67fc51fc2672458dd1c9641250f2ecc01a31
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 17package android.app.job; 18 19import android.content.ComponentName; 20import android.os.Bundle; 21import android.os.Parcel; 22import android.os.Parcelable; 23import android.os.PersistableBundle; 24 25/** 26 * Container of data passed to the {@link android.app.job.JobScheduler} fully encapsulating the 27 * parameters required to schedule work against the calling application. These are constructed 28 * using the {@link JobInfo.Builder}. 29 */ 30public class JobInfo implements Parcelable { 31 public interface NetworkType { 32 /** Default. */ 33 public final int NONE = 0; 34 /** This job requires network connectivity. */ 35 public final int ANY = 1; 36 /** This job requires network connectivity that is unmetered. */ 37 public final int UNMETERED = 2; 38 } 39 40 /** 41 * Amount of backoff a job has initially by default, in milliseconds. 42 * @hide. 43 */ 44 public static final long DEFAULT_INITIAL_BACKOFF_MILLIS = 5000L; 45 46 /** 47 * Default type of backoff. 48 * @hide 49 */ 50 public static final int DEFAULT_BACKOFF_POLICY = BackoffPolicy.EXPONENTIAL; 51 /** 52 * Maximum backoff we allow for a job, in milliseconds. 53 * @hide 54 */ 55 public static final long MAX_BACKOFF_DELAY_MILLIS = 24 * 60 * 60 * 1000; // 24 hours. 56 57 /** 58 * Linear: retry_time(failure_time, t) = failure_time + initial_retry_delay * t, t >= 1 59 * Expon: retry_time(failure_time, t) = failure_time + initial_retry_delay ^ t, t >= 1 60 */ 61 public interface BackoffPolicy { 62 public final int LINEAR = 0; 63 public final int EXPONENTIAL = 1; 64 } 65 66 private final int jobId; 67 private final PersistableBundle extras; 68 private final ComponentName service; 69 private final boolean requireCharging; 70 private final boolean requireDeviceIdle; 71 private final boolean hasEarlyConstraint; 72 private final boolean hasLateConstraint; 73 private final int networkCapabilities; 74 private final long minLatencyMillis; 75 private final long maxExecutionDelayMillis; 76 private final boolean isPeriodic; 77 private final boolean isPersisted; 78 private final long intervalMillis; 79 private final long initialBackoffMillis; 80 private final int backoffPolicy; 81 82 /** 83 * Unique job id associated with this class. This is assigned to your job by the scheduler. 84 */ 85 public int getId() { 86 return jobId; 87 } 88 89 /** 90 * Bundle of extras which are returned to your application at execution time. 91 */ 92 public PersistableBundle getExtras() { 93 return extras; 94 } 95 96 /** 97 * Name of the service endpoint that will be called back into by the JobScheduler. 98 */ 99 public ComponentName getService() { 100 return service; 101 } 102 103 /** 104 * Whether this job needs the device to be plugged in. 105 */ 106 public boolean isRequireCharging() { 107 return requireCharging; 108 } 109 110 /** 111 * Whether this job needs the device to be in an Idle maintenance window. 112 */ 113 public boolean isRequireDeviceIdle() { 114 return requireDeviceIdle; 115 } 116 117 /** 118 * See {@link android.app.job.JobInfo.NetworkType} for a description of this value. 119 */ 120 public int getNetworkCapabilities() { 121 return networkCapabilities; 122 } 123 124 /** 125 * Set for a job that does not recur periodically, to specify a delay after which the job 126 * will be eligible for execution. This value is not set if the job recurs periodically. 127 */ 128 public long getMinLatencyMillis() { 129 return minLatencyMillis; 130 } 131 132 /** 133 * See {@link Builder#setOverrideDeadline(long)}. This value is not set if the job recurs 134 * periodically. 135 */ 136 public long getMaxExecutionDelayMillis() { 137 return maxExecutionDelayMillis; 138 } 139 140 /** 141 * Track whether this job will repeat with a given period. 142 */ 143 public boolean isPeriodic() { 144 return isPeriodic; 145 } 146 147 /** 148 * @return Whether or not this job should be persisted across device reboots. 149 */ 150 public boolean isPersisted() { 151 return isPersisted; 152 } 153 154 /** 155 * Set to the interval between occurrences of this job. This value is <b>not</b> set if the 156 * job does not recur periodically. 157 */ 158 public long getIntervalMillis() { 159 return intervalMillis; 160 } 161 162 /** 163 * The amount of time the JobScheduler will wait before rescheduling a failed job. This value 164 * will be increased depending on the backoff policy specified at job creation time. Defaults 165 * to 5 seconds. 166 */ 167 public long getInitialBackoffMillis() { 168 return initialBackoffMillis; 169 } 170 171 /** 172 * See {@link android.app.job.JobInfo.BackoffPolicy} for an explanation of the values this field 173 * can take. This defaults to exponential. 174 */ 175 public int getBackoffPolicy() { 176 return backoffPolicy; 177 } 178 179 /** 180 * User can specify an early constraint of 0L, which is valid, so we keep track of whether the 181 * function was called at all. 182 * @hide 183 */ 184 public boolean hasEarlyConstraint() { 185 return hasEarlyConstraint; 186 } 187 188 /** 189 * User can specify a late constraint of 0L, which is valid, so we keep track of whether the 190 * function was called at all. 191 * @hide 192 */ 193 public boolean hasLateConstraint() { 194 return hasLateConstraint; 195 } 196 197 private JobInfo(Parcel in) { 198 jobId = in.readInt(); 199 extras = in.readPersistableBundle(); 200 service = in.readParcelable(null); 201 requireCharging = in.readInt() == 1; 202 requireDeviceIdle = in.readInt() == 1; 203 networkCapabilities = in.readInt(); 204 minLatencyMillis = in.readLong(); 205 maxExecutionDelayMillis = in.readLong(); 206 isPeriodic = in.readInt() == 1; 207 isPersisted = in.readInt() == 1; 208 intervalMillis = in.readLong(); 209 initialBackoffMillis = in.readLong(); 210 backoffPolicy = in.readInt(); 211 hasEarlyConstraint = in.readInt() == 1; 212 hasLateConstraint = in.readInt() == 1; 213 } 214 215 private JobInfo(JobInfo.Builder b) { 216 jobId = b.mJobId; 217 extras = b.mExtras; 218 service = b.mJobService; 219 requireCharging = b.mRequiresCharging; 220 requireDeviceIdle = b.mRequiresDeviceIdle; 221 networkCapabilities = b.mNetworkCapabilities; 222 minLatencyMillis = b.mMinLatencyMillis; 223 maxExecutionDelayMillis = b.mMaxExecutionDelayMillis; 224 isPeriodic = b.mIsPeriodic; 225 isPersisted = b.mIsPersisted; 226 intervalMillis = b.mIntervalMillis; 227 initialBackoffMillis = b.mInitialBackoffMillis; 228 backoffPolicy = b.mBackoffPolicy; 229 hasEarlyConstraint = b.mHasEarlyConstraint; 230 hasLateConstraint = b.mHasLateConstraint; 231 } 232 233 @Override 234 public int describeContents() { 235 return 0; 236 } 237 238 @Override 239 public void writeToParcel(Parcel out, int flags) { 240 out.writeInt(jobId); 241 out.writePersistableBundle(extras); 242 out.writeParcelable(service, flags); 243 out.writeInt(requireCharging ? 1 : 0); 244 out.writeInt(requireDeviceIdle ? 1 : 0); 245 out.writeInt(networkCapabilities); 246 out.writeLong(minLatencyMillis); 247 out.writeLong(maxExecutionDelayMillis); 248 out.writeInt(isPeriodic ? 1 : 0); 249 out.writeInt(isPersisted ? 1 : 0); 250 out.writeLong(intervalMillis); 251 out.writeLong(initialBackoffMillis); 252 out.writeInt(backoffPolicy); 253 out.writeInt(hasEarlyConstraint ? 1 : 0); 254 out.writeInt(hasLateConstraint ? 1 : 0); 255 } 256 257 public static final Creator<JobInfo> CREATOR = new Creator<JobInfo>() { 258 @Override 259 public JobInfo createFromParcel(Parcel in) { 260 return new JobInfo(in); 261 } 262 263 @Override 264 public JobInfo[] newArray(int size) { 265 return new JobInfo[size]; 266 } 267 }; 268 269 /** Builder class for constructing {@link JobInfo} objects. */ 270 public static final class Builder { 271 private int mJobId; 272 private PersistableBundle mExtras = PersistableBundle.EMPTY; 273 private ComponentName mJobService; 274 // Requirements. 275 private boolean mRequiresCharging; 276 private boolean mRequiresDeviceIdle; 277 private int mNetworkCapabilities; 278 private boolean mIsPersisted; 279 // One-off parameters. 280 private long mMinLatencyMillis; 281 private long mMaxExecutionDelayMillis; 282 // Periodic parameters. 283 private boolean mIsPeriodic; 284 private boolean mHasEarlyConstraint; 285 private boolean mHasLateConstraint; 286 private long mIntervalMillis; 287 // Back-off parameters. 288 private long mInitialBackoffMillis = DEFAULT_INITIAL_BACKOFF_MILLIS; 289 private int mBackoffPolicy = DEFAULT_BACKOFF_POLICY; 290 /** Easy way to track whether the client has tried to set a back-off policy. */ 291 private boolean mBackoffPolicySet = false; 292 293 /** 294 * @param jobId Application-provided id for this job. Subsequent calls to cancel, or 295 * jobs created with the same jobId, will update the pre-existing job with 296 * the same id. 297 * @param jobService The endpoint that you implement that will receive the callback from the 298 * JobScheduler. 299 */ 300 public Builder(int jobId, ComponentName jobService) { 301 mJobService = jobService; 302 mJobId = jobId; 303 } 304 305 /** 306 * Set optional extras. This is persisted, so we only allow primitive types. 307 * @param extras Bundle containing extras you want the scheduler to hold on to for you. 308 */ 309 public Builder setExtras(PersistableBundle extras) { 310 mExtras = extras; 311 return this; 312 } 313 314 /** 315 * Set some description of the kind of network capabilities you would like to have. This 316 * will be a parameter defined in {@link android.app.job.JobInfo.NetworkType}. 317 * Not calling this function means the network is not necessary. 318 * Bear in mind that calling this function defines network as a strict requirement for your 319 * job if the network requested is not available your job will never run. See 320 * {@link #setOverrideDeadline(long)} to change this behaviour. 321 */ 322 public Builder setRequiredNetworkCapabilities(int networkCapabilities) { 323 mNetworkCapabilities = networkCapabilities; 324 return this; 325 } 326 327 /** 328 * Specify that to run this job, the device needs to be plugged in. This defaults to 329 * false. 330 * @param requiresCharging Whether or not the device is plugged in. 331 */ 332 public Builder setRequiresCharging(boolean requiresCharging) { 333 mRequiresCharging = requiresCharging; 334 return this; 335 } 336 337 /** 338 * Specify that to run, the job needs the device to be in idle mode. This defaults to 339 * false. 340 * <p>Idle mode is a loose definition provided by the system, which means that the device 341 * is not in use, and has not been in use for some time. As such, it is a good time to 342 * perform resource heavy jobs. Bear in mind that battery usage will still be attributed 343 * to your application, and surfaced to the user in battery stats.</p> 344 * @param requiresDeviceIdle Whether or not the device need be within an idle maintenance 345 * window. 346 */ 347 public Builder setRequiresDeviceIdle(boolean requiresDeviceIdle) { 348 mRequiresDeviceIdle = requiresDeviceIdle; 349 return this; 350 } 351 352 /** 353 * Specify that this job should recur with the provided interval, not more than once per 354 * period. You have no control over when within this interval this job will be executed, 355 * only the guarantee that it will be executed at most once within this interval. 356 * Setting this function on the builder with {@link #setMinimumLatency(long)} or 357 * {@link #setOverrideDeadline(long)} will result in an error. 358 * @param intervalMillis Millisecond interval for which this job will repeat. 359 */ 360 public Builder setPeriodic(long intervalMillis) { 361 mIsPeriodic = true; 362 mIntervalMillis = intervalMillis; 363 mHasEarlyConstraint = mHasLateConstraint = true; 364 return this; 365 } 366 367 /** 368 * Specify that this job should be delayed by the provided amount of time. 369 * Because it doesn't make sense setting this property on a periodic job, doing so will 370 * throw an {@link java.lang.IllegalArgumentException} when 371 * {@link android.app.job.JobInfo.Builder#build()} is called. 372 * @param minLatencyMillis Milliseconds before which this job will not be considered for 373 * execution. 374 */ 375 public Builder setMinimumLatency(long minLatencyMillis) { 376 mMinLatencyMillis = minLatencyMillis; 377 mHasEarlyConstraint = true; 378 return this; 379 } 380 381 /** 382 * Set deadline which is the maximum scheduling latency. The job will be run by this 383 * deadline even if other requirements are not met. Because it doesn't make sense setting 384 * this property on a periodic job, doing so will throw an 385 * {@link java.lang.IllegalArgumentException} when 386 * {@link android.app.job.JobInfo.Builder#build()} is called. 387 */ 388 public Builder setOverrideDeadline(long maxExecutionDelayMillis) { 389 mMaxExecutionDelayMillis = maxExecutionDelayMillis; 390 mHasLateConstraint = true; 391 return this; 392 } 393 394 /** 395 * Set up the back-off/retry policy. 396 * This defaults to some respectable values: {5 seconds, Exponential}. We cap back-off at 397 * 1hr. 398 * Note that trying to set a backoff criteria for a job with 399 * {@link #setRequiresDeviceIdle(boolean)} will throw an exception when you call build(). 400 * This is because back-off typically does not make sense for these types of jobs. See 401 * {@link android.app.job.JobService#jobFinished(android.app.job.JobParameters, boolean)} 402 * for more description of the return value for the case of a job executing while in idle 403 * mode. 404 * @param initialBackoffMillis Millisecond time interval to wait initially when job has 405 * failed. 406 * @param backoffPolicy is one of {@link BackoffPolicy} 407 */ 408 public Builder setBackoffCriteria(long initialBackoffMillis, int backoffPolicy) { 409 mBackoffPolicySet = true; 410 mInitialBackoffMillis = initialBackoffMillis; 411 mBackoffPolicy = backoffPolicy; 412 return this; 413 } 414 415 /** 416 * Set whether or not to persist this job across device reboots. This will only have an 417 * effect if your application holds the permission 418 * {@link android.Manifest.permission#RECEIVE_BOOT_COMPLETED}. Otherwise an exception will 419 * be thrown. 420 * @param isPersisted True to indicate that the job will be written to disk and loaded at 421 * boot. 422 */ 423 public Builder setIsPersisted(boolean isPersisted) { 424 mIsPersisted = isPersisted; 425 return this; 426 } 427 428 /** 429 * @return The job object to hand to the JobScheduler. This object is immutable. 430 */ 431 public JobInfo build() { 432 mExtras = new PersistableBundle(mExtras); // Make our own copy. 433 // Check that a deadline was not set on a periodic job. 434 if (mIsPeriodic && (mMaxExecutionDelayMillis != 0L)) { 435 throw new IllegalArgumentException("Can't call setOverrideDeadline() on a " + 436 "periodic job."); 437 } 438 if (mIsPeriodic && (mMinLatencyMillis != 0L)) { 439 throw new IllegalArgumentException("Can't call setMinimumLatency() on a " + 440 "periodic job"); 441 } 442 if (mBackoffPolicySet && mRequiresDeviceIdle) { 443 throw new IllegalArgumentException("An idle mode job will not respect any" + 444 " back-off policy, so calling setBackoffCriteria with" + 445 " setRequiresDeviceIdle is an error."); 446 } 447 return new JobInfo(this); 448 } 449 } 450 451} 452