JobInfo.java revision ee410da42b6b8352213f03f7725fd041f703b035
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 @Override 270 public String toString() { 271 return "(job:" + jobId + "/" + service.flattenToShortString() + ")"; 272 } 273 274 /** Builder class for constructing {@link JobInfo} objects. */ 275 public static final class Builder { 276 private int mJobId; 277 private PersistableBundle mExtras = PersistableBundle.EMPTY; 278 private ComponentName mJobService; 279 // Requirements. 280 private boolean mRequiresCharging; 281 private boolean mRequiresDeviceIdle; 282 private int mNetworkCapabilities; 283 private boolean mIsPersisted; 284 // One-off parameters. 285 private long mMinLatencyMillis; 286 private long mMaxExecutionDelayMillis; 287 // Periodic parameters. 288 private boolean mIsPeriodic; 289 private boolean mHasEarlyConstraint; 290 private boolean mHasLateConstraint; 291 private long mIntervalMillis; 292 // Back-off parameters. 293 private long mInitialBackoffMillis = DEFAULT_INITIAL_BACKOFF_MILLIS; 294 private int mBackoffPolicy = DEFAULT_BACKOFF_POLICY; 295 /** Easy way to track whether the client has tried to set a back-off policy. */ 296 private boolean mBackoffPolicySet = false; 297 298 /** 299 * @param jobId Application-provided id for this job. Subsequent calls to cancel, or 300 * jobs created with the same jobId, will update the pre-existing job with 301 * the same id. 302 * @param jobService The endpoint that you implement that will receive the callback from the 303 * JobScheduler. 304 */ 305 public Builder(int jobId, ComponentName jobService) { 306 mJobService = jobService; 307 mJobId = jobId; 308 } 309 310 /** 311 * Set optional extras. This is persisted, so we only allow primitive types. 312 * @param extras Bundle containing extras you want the scheduler to hold on to for you. 313 */ 314 public Builder setExtras(PersistableBundle extras) { 315 mExtras = extras; 316 return this; 317 } 318 319 /** 320 * Set some description of the kind of network capabilities you would like to have. This 321 * will be a parameter defined in {@link android.app.job.JobInfo.NetworkType}. 322 * Not calling this function means the network is not necessary. 323 * Bear in mind that calling this function defines network as a strict requirement for your 324 * job if the network requested is not available your job will never run. See 325 * {@link #setOverrideDeadline(long)} to change this behaviour. 326 */ 327 public Builder setRequiredNetworkCapabilities(int networkCapabilities) { 328 mNetworkCapabilities = networkCapabilities; 329 return this; 330 } 331 332 /** 333 * Specify that to run this job, the device needs to be plugged in. This defaults to 334 * false. 335 * @param requiresCharging Whether or not the device is plugged in. 336 */ 337 public Builder setRequiresCharging(boolean requiresCharging) { 338 mRequiresCharging = requiresCharging; 339 return this; 340 } 341 342 /** 343 * Specify that to run, the job needs the device to be in idle mode. This defaults to 344 * false. 345 * <p>Idle mode is a loose definition provided by the system, which means that the device 346 * is not in use, and has not been in use for some time. As such, it is a good time to 347 * perform resource heavy jobs. Bear in mind that battery usage will still be attributed 348 * to your application, and surfaced to the user in battery stats.</p> 349 * @param requiresDeviceIdle Whether or not the device need be within an idle maintenance 350 * window. 351 */ 352 public Builder setRequiresDeviceIdle(boolean requiresDeviceIdle) { 353 mRequiresDeviceIdle = requiresDeviceIdle; 354 return this; 355 } 356 357 /** 358 * Specify that this job should recur with the provided interval, not more than once per 359 * period. You have no control over when within this interval this job will be executed, 360 * only the guarantee that it will be executed at most once within this interval. 361 * Setting this function on the builder with {@link #setMinimumLatency(long)} or 362 * {@link #setOverrideDeadline(long)} will result in an error. 363 * @param intervalMillis Millisecond interval for which this job will repeat. 364 */ 365 public Builder setPeriodic(long intervalMillis) { 366 mIsPeriodic = true; 367 mIntervalMillis = intervalMillis; 368 mHasEarlyConstraint = mHasLateConstraint = true; 369 return this; 370 } 371 372 /** 373 * Specify that this job should be delayed by the provided amount of time. 374 * Because it doesn't make sense setting this property on a periodic job, doing so will 375 * throw an {@link java.lang.IllegalArgumentException} when 376 * {@link android.app.job.JobInfo.Builder#build()} is called. 377 * @param minLatencyMillis Milliseconds before which this job will not be considered for 378 * execution. 379 */ 380 public Builder setMinimumLatency(long minLatencyMillis) { 381 mMinLatencyMillis = minLatencyMillis; 382 mHasEarlyConstraint = true; 383 return this; 384 } 385 386 /** 387 * Set deadline which is the maximum scheduling latency. The job will be run by this 388 * deadline even if other requirements are not met. Because it doesn't make sense setting 389 * this property on a periodic job, doing so will throw an 390 * {@link java.lang.IllegalArgumentException} when 391 * {@link android.app.job.JobInfo.Builder#build()} is called. 392 */ 393 public Builder setOverrideDeadline(long maxExecutionDelayMillis) { 394 mMaxExecutionDelayMillis = maxExecutionDelayMillis; 395 mHasLateConstraint = true; 396 return this; 397 } 398 399 /** 400 * Set up the back-off/retry policy. 401 * This defaults to some respectable values: {5 seconds, Exponential}. We cap back-off at 402 * 1hr. 403 * Note that trying to set a backoff criteria for a job with 404 * {@link #setRequiresDeviceIdle(boolean)} will throw an exception when you call build(). 405 * This is because back-off typically does not make sense for these types of jobs. See 406 * {@link android.app.job.JobService#jobFinished(android.app.job.JobParameters, boolean)} 407 * for more description of the return value for the case of a job executing while in idle 408 * mode. 409 * @param initialBackoffMillis Millisecond time interval to wait initially when job has 410 * failed. 411 * @param backoffPolicy is one of {@link BackoffPolicy} 412 */ 413 public Builder setBackoffCriteria(long initialBackoffMillis, int backoffPolicy) { 414 mBackoffPolicySet = true; 415 mInitialBackoffMillis = initialBackoffMillis; 416 mBackoffPolicy = backoffPolicy; 417 return this; 418 } 419 420 /** 421 * Set whether or not to persist this job across device reboots. This will only have an 422 * effect if your application holds the permission 423 * {@link android.Manifest.permission#RECEIVE_BOOT_COMPLETED}. Otherwise an exception will 424 * be thrown. 425 * @param isPersisted True to indicate that the job will be written to disk and loaded at 426 * boot. 427 */ 428 public Builder setIsPersisted(boolean isPersisted) { 429 mIsPersisted = isPersisted; 430 return this; 431 } 432 433 /** 434 * @return The job object to hand to the JobScheduler. This object is immutable. 435 */ 436 public JobInfo build() { 437 mExtras = new PersistableBundle(mExtras); // Make our own copy. 438 // Check that a deadline was not set on a periodic job. 439 if (mIsPeriodic && (mMaxExecutionDelayMillis != 0L)) { 440 throw new IllegalArgumentException("Can't call setOverrideDeadline() on a " + 441 "periodic job."); 442 } 443 if (mIsPeriodic && (mMinLatencyMillis != 0L)) { 444 throw new IllegalArgumentException("Can't call setMinimumLatency() on a " + 445 "periodic job"); 446 } 447 if (mBackoffPolicySet && mRequiresDeviceIdle) { 448 throw new IllegalArgumentException("An idle mode job will not respect any" + 449 " back-off policy, so calling setBackoffCriteria with" + 450 " setRequiresDeviceIdle is an error."); 451 } 452 return new JobInfo(this); 453 } 454 } 455 456} 457