blob: 907d1f727bd452d925b61b722c2e00f75315173f [file] [log] [blame]
Matthew Williams6e31c5c2014-04-11 15:49:16 -07001/*
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
Christopher Tate7060b042014-06-09 19:50:00 -070017package android.app.job;
Matthew Williams6e31c5c2014-04-11 15:49:16 -070018
Jeff Sharkeyd0fff2e2017-11-07 16:55:06 -070019import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
20import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
21import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING;
22import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VPN;
23import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED;
24import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
Jeff Sharkey1b6519b2016-04-28 15:33:18 -060025import static android.util.TimeUtils.formatDuration;
26
Jeff Sharkeycaa3f8d2017-10-25 16:12:00 -060027import android.annotation.BytesLong;
Jeff Sharkey30e06bb2017-04-24 11:18:03 -060028import android.annotation.IntDef;
Dianne Hackborn1a30bd92016-01-11 11:05:00 -080029import android.annotation.NonNull;
30import android.annotation.Nullable;
Jeff Sharkey30e06bb2017-04-24 11:18:03 -060031import android.annotation.RequiresPermission;
Mathew Inwood61e8ae62018-08-14 14:17:44 +010032import android.annotation.UnsupportedAppUsage;
Dianne Hackborna47223f2017-03-30 13:49:13 -070033import android.content.ClipData;
Christopher Tatefa380e92014-05-19 13:46:29 -070034import android.content.ComponentName;
Jeff Sharkeyd0fff2e2017-11-07 16:55:06 -070035import android.net.NetworkRequest;
36import android.net.NetworkSpecifier;
Dianne Hackborn1a30bd92016-01-11 11:05:00 -080037import android.net.Uri;
Dianne Hackborn7da13d72017-04-04 17:17:35 -070038import android.os.BaseBundle;
Mathew Inwood8c854f82018-09-14 12:35:36 +010039import android.os.Build;
Dianne Hackbornba604732016-02-10 17:05:10 -080040import android.os.Bundle;
Matthew Williams6e31c5c2014-04-11 15:49:16 -070041import android.os.Parcel;
42import android.os.Parcelable;
Matthew Williams3d86fd22014-05-16 18:02:17 -070043import android.os.PersistableBundle;
Shreyas Basargee96c3b72016-01-29 19:25:51 +000044import android.util.Log;
Matthew Williams6e31c5c2014-04-11 15:49:16 -070045
Jeff Sharkey30e06bb2017-04-24 11:18:03 -060046import java.lang.annotation.Retention;
47import java.lang.annotation.RetentionPolicy;
Dianne Hackborn1a30bd92016-01-11 11:05:00 -080048import java.util.ArrayList;
Paul Duffinc67663c2017-05-26 09:46:48 +010049import java.util.Arrays;
Dianne Hackborn121e1642016-06-21 20:39:02 -070050import java.util.Objects;
Dianne Hackborn1a30bd92016-01-11 11:05:00 -080051
Matthew Williams6e31c5c2014-04-11 15:49:16 -070052/**
Christopher Tate7060b042014-06-09 19:50:00 -070053 * Container of data passed to the {@link android.app.job.JobScheduler} fully encapsulating the
Matthew Williams6e31c5c2014-04-11 15:49:16 -070054 * parameters required to schedule work against the calling application. These are constructed
Christopher Tate7060b042014-06-09 19:50:00 -070055 * using the {@link JobInfo.Builder}.
Matthew Williams9ae3dbe2014-08-21 13:47:47 -070056 * You must specify at least one sort of constraint on the JobInfo object that you are creating.
57 * The goal here is to provide the scheduler with high-level semantics about the work you want to
58 * accomplish. Doing otherwise with throw an exception in your app.
Matthew Williams6e31c5c2014-04-11 15:49:16 -070059 */
Christopher Tate7060b042014-06-09 19:50:00 -070060public class JobInfo implements Parcelable {
Shreyas Basargee96c3b72016-01-29 19:25:51 +000061 private static String TAG = "JobInfo";
Jeff Sharkey30e06bb2017-04-24 11:18:03 -060062
63 /** @hide */
64 @IntDef(prefix = { "NETWORK_TYPE_" }, value = {
65 NETWORK_TYPE_NONE,
66 NETWORK_TYPE_ANY,
67 NETWORK_TYPE_UNMETERED,
68 NETWORK_TYPE_NOT_ROAMING,
Jeff Sharkeyd0fff2e2017-11-07 16:55:06 -070069 NETWORK_TYPE_CELLULAR,
Jeff Sharkey30e06bb2017-04-24 11:18:03 -060070 })
71 @Retention(RetentionPolicy.SOURCE)
72 public @interface NetworkType {}
73
Matthew Williamsd1c06752014-08-22 14:15:28 -070074 /** Default. */
75 public static final int NETWORK_TYPE_NONE = 0;
76 /** This job requires network connectivity. */
77 public static final int NETWORK_TYPE_ANY = 1;
78 /** This job requires network connectivity that is unmetered. */
79 public static final int NETWORK_TYPE_UNMETERED = 2;
Jeff Sharkeyf07c7b92016-04-22 09:50:16 -060080 /** This job requires network connectivity that is not roaming. */
81 public static final int NETWORK_TYPE_NOT_ROAMING = 3;
Jeff Sharkeyd0fff2e2017-11-07 16:55:06 -070082 /** This job requires network connectivity that is a cellular network. */
83 public static final int NETWORK_TYPE_CELLULAR = 4;
84
85 /**
86 * This job requires metered connectivity such as most cellular data
87 * networks.
88 *
89 * @deprecated Cellular networks may be unmetered, or Wi-Fi networks may be
90 * metered, so this isn't a good way of selecting a specific
91 * transport. Instead, use {@link #NETWORK_TYPE_CELLULAR} or
92 * {@link android.net.NetworkRequest.Builder#addTransportType(int)}
93 * if your job requires a specific network transport.
94 */
95 @Deprecated
96 public static final int NETWORK_TYPE_METERED = NETWORK_TYPE_CELLULAR;
Matthew Williams6e31c5c2014-04-11 15:49:16 -070097
Jeff Sharkeycaa3f8d2017-10-25 16:12:00 -060098 /** Sentinel value indicating that bytes are unknown. */
99 public static final int NETWORK_BYTES_UNKNOWN = -1;
100
Matthew Williams6e31c5c2014-04-11 15:49:16 -0700101 /**
Christopher Tate7060b042014-06-09 19:50:00 -0700102 * Amount of backoff a job has initially by default, in milliseconds.
Matthew Williams3d86fd22014-05-16 18:02:17 -0700103 */
Matthew Williamsd1c06752014-08-22 14:15:28 -0700104 public static final long DEFAULT_INITIAL_BACKOFF_MILLIS = 30000L; // 30 seconds.
105
106 /**
107 * Maximum backoff we allow for a job, in milliseconds.
108 */
109 public static final long MAX_BACKOFF_DELAY_MILLIS = 5 * 60 * 60 * 1000; // 5 hours.
110
Jeff Sharkey30e06bb2017-04-24 11:18:03 -0600111 /** @hide */
112 @IntDef(prefix = { "BACKOFF_POLICY_" }, value = {
113 BACKOFF_POLICY_LINEAR,
114 BACKOFF_POLICY_EXPONENTIAL,
115 })
116 @Retention(RetentionPolicy.SOURCE)
117 public @interface BackoffPolicy {}
118
Matthew Williamsd1c06752014-08-22 14:15:28 -0700119 /**
120 * Linearly back-off a failed job. See
121 * {@link android.app.job.JobInfo.Builder#setBackoffCriteria(long, int)}
122 * retry_time(current_time, num_failures) =
123 * current_time + initial_backoff_millis * num_failures, num_failures >= 1
124 */
125 public static final int BACKOFF_POLICY_LINEAR = 0;
126
127 /**
128 * Exponentially back-off a failed job. See
129 * {@link android.app.job.JobInfo.Builder#setBackoffCriteria(long, int)}
130 *
131 * retry_time(current_time, num_failures) =
132 * current_time + initial_backoff_millis * 2 ^ (num_failures - 1), num_failures >= 1
133 */
134 public static final int BACKOFF_POLICY_EXPONENTIAL = 1;
Matthew Williams3d86fd22014-05-16 18:02:17 -0700135
Shreyas Basarge89ee6182015-12-17 15:16:36 +0000136 /* Minimum interval for a periodic job, in milliseconds. */
Christopher Tate10be4e92016-03-15 16:56:21 -0700137 private static final long MIN_PERIOD_MILLIS = 15 * 60 * 1000L; // 15 minutes
138
Shreyas Basarge89ee6182015-12-17 15:16:36 +0000139 /* Minimum flex for a periodic job, in milliseconds. */
Christopher Tate10be4e92016-03-15 16:56:21 -0700140 private static final long MIN_FLEX_MILLIS = 5 * 60 * 1000L; // 5 minutes
141
Dianne Hackbornbfc23312017-05-11 11:53:24 -0700142 /**
143 * Minimum backoff interval for a job, in milliseconds
144 * @hide
145 */
146 public static final long MIN_BACKOFF_MILLIS = 10 * 1000L; // 10 seconds
Christopher Tateb2087f82017-03-29 17:42:39 -0700147
Christopher Tate10be4e92016-03-15 16:56:21 -0700148 /**
149 * Query the minimum interval allowed for periodic scheduled jobs. Attempting
150 * to declare a smaller period that this when scheduling a job will result in a
151 * job that is still periodic, but will run with this effective period.
152 *
153 * @return The minimum available interval for scheduling periodic jobs, in milliseconds.
154 */
Christopher Tatea9b4f3f2016-05-18 13:57:37 -0700155 public static final long getMinPeriodMillis() {
Christopher Tate10be4e92016-03-15 16:56:21 -0700156 return MIN_PERIOD_MILLIS;
157 }
158
159 /**
160 * Query the minimum flex time allowed for periodic scheduled jobs. Attempting
161 * to declare a shorter flex time than this when scheduling such a job will
162 * result in this amount as the effective flex time for the job.
163 *
164 * @return The minimum available flex time for scheduling periodic jobs, in milliseconds.
165 */
Christopher Tatea9b4f3f2016-05-18 13:57:37 -0700166 public static final long getMinFlexMillis() {
Christopher Tate10be4e92016-03-15 16:56:21 -0700167 return MIN_FLEX_MILLIS;
168 }
Shreyas Basarge89ee6182015-12-17 15:16:36 +0000169
Matthew Williams3d86fd22014-05-16 18:02:17 -0700170 /**
Christopher Tateb2087f82017-03-29 17:42:39 -0700171 * Query the minimum automatic-reschedule backoff interval permitted for jobs.
172 * @hide
173 */
174 public static final long getMinBackoffMillis() {
175 return MIN_BACKOFF_MILLIS;
176 }
177
178 /**
Matthew Williams3d86fd22014-05-16 18:02:17 -0700179 * Default type of backoff.
180 * @hide
181 */
Matthew Williamsd1c06752014-08-22 14:15:28 -0700182 public static final int DEFAULT_BACKOFF_POLICY = BACKOFF_POLICY_EXPONENTIAL;
Matthew Williams6e31c5c2014-04-11 15:49:16 -0700183
Dianne Hackborn1085ff62016-02-23 17:04:58 -0800184 /**
185 * Default of {@link #getPriority}.
186 * @hide
187 */
188 public static final int PRIORITY_DEFAULT = 0;
189
190 /**
191 * Value of {@link #getPriority} for expedited syncs.
192 * @hide
193 */
194 public static final int PRIORITY_SYNC_EXPEDITED = 10;
195
196 /**
197 * Value of {@link #getPriority} for first time initialization syncs.
198 * @hide
199 */
200 public static final int PRIORITY_SYNC_INITIALIZATION = 20;
201
202 /**
Makoto Onukiec8b14d2018-12-05 13:22:24 -0800203 * Value of {@link #getPriority} for a BFGS app (overrides the supplied
204 * JobInfo priority if it is smaller).
205 * @hide
206 */
207 public static final int PRIORITY_BOUND_FOREGROUND_SERVICE = 30;
208
209 /** @hide For backward compatibility. */
210 @UnsupportedAppUsage
211 public static final int PRIORITY_FOREGROUND_APP = PRIORITY_BOUND_FOREGROUND_SERVICE;
212
213 /**
214 * Value of {@link #getPriority} for a FG service app (overrides the supplied
Dianne Hackborn1085ff62016-02-23 17:04:58 -0800215 * JobInfo priority if it is smaller).
216 * @hide
217 */
Mathew Inwood61e8ae62018-08-14 14:17:44 +0100218 @UnsupportedAppUsage
Makoto Onukiec8b14d2018-12-05 13:22:24 -0800219 public static final int PRIORITY_FOREGROUND_SERVICE = 35;
Dianne Hackborn1085ff62016-02-23 17:04:58 -0800220
Dianne Hackborn970510b2016-02-24 16:56:42 -0800221 /**
222 * Value of {@link #getPriority} for the current top app (overrides the supplied
223 * JobInfo priority if it is smaller).
224 * @hide
225 */
226 public static final int PRIORITY_TOP_APP = 40;
227
Dianne Hackborn807de782016-04-07 17:54:41 -0700228 /**
229 * Adjustment of {@link #getPriority} if the app has often (50% or more of the time)
230 * been running jobs.
231 * @hide
232 */
233 public static final int PRIORITY_ADJ_OFTEN_RUNNING = -40;
234
235 /**
236 * Adjustment of {@link #getPriority} if the app has always (90% or more of the time)
237 * been running jobs.
238 * @hide
239 */
240 public static final int PRIORITY_ADJ_ALWAYS_RUNNING = -80;
241
Jeff Sharkey1b6519b2016-04-28 15:33:18 -0600242 /**
243 * Indicates that the implementation of this job will be using
244 * {@link JobService#startForeground(int, android.app.Notification)} to run
245 * in the foreground.
246 * <p>
247 * When set, the internal scheduling of this job will ignore any background
248 * network restrictions for the requesting app. Note that this flag alone
249 * doesn't actually place your {@link JobService} in the foreground; you
250 * still need to post the notification yourself.
Jeff Sharkey785f4942016-07-14 10:31:15 -0600251 * <p>
252 * To use this flag, the caller must hold the
253 * {@link android.Manifest.permission#CONNECTIVITY_INTERNAL} permission.
Jeff Sharkey1b6519b2016-04-28 15:33:18 -0600254 *
255 * @hide
256 */
Mathew Inwood61e8ae62018-08-14 14:17:44 +0100257 @UnsupportedAppUsage
Jeff Sharkey1b6519b2016-04-28 15:33:18 -0600258 public static final int FLAG_WILL_BE_FOREGROUND = 1 << 0;
259
Dianne Hackborna06ec6a2017-02-13 10:08:42 -0800260 /**
Suprabh Shukla106203b2017-11-02 21:23:44 -0700261 * Allows this job to run despite doze restrictions as long as the app is in the foreground
262 * or on the temporary whitelist
263 * @hide
264 */
265 public static final int FLAG_IMPORTANT_WHILE_FOREGROUND = 1 << 1;
266
267 /**
Dianne Hackborna06ec6a2017-02-13 10:08:42 -0800268 * @hide
269 */
Jeff Sharkey8474ca02018-03-26 19:10:02 -0600270 public static final int FLAG_PREFETCH = 1 << 2;
Jeff Sharkey9252b342018-01-19 07:58:35 +0900271
272 /**
Makoto Onuki959acb52018-01-26 14:10:03 -0800273 * This job needs to be exempted from the app standby throttling. Only the system (UID 1000)
274 * can set it. Jobs with a time constrant must not have it.
275 *
276 * @hide
277 */
278 public static final int FLAG_EXEMPT_FROM_APP_STANDBY = 1 << 3;
279
280 /**
Jeff Sharkey9252b342018-01-19 07:58:35 +0900281 * @hide
282 */
Dianne Hackborna06ec6a2017-02-13 10:08:42 -0800283 public static final int CONSTRAINT_FLAG_CHARGING = 1 << 0;
284
285 /**
286 * @hide
287 */
288 public static final int CONSTRAINT_FLAG_BATTERY_NOT_LOW = 1 << 1;
289
290 /**
291 * @hide
292 */
293 public static final int CONSTRAINT_FLAG_DEVICE_IDLE = 1 << 2;
294
Dianne Hackborn532ea262017-03-17 17:50:55 -0700295 /**
296 * @hide
297 */
298 public static final int CONSTRAINT_FLAG_STORAGE_NOT_LOW = 1 << 3;
299
Mathew Inwood61e8ae62018-08-14 14:17:44 +0100300 @UnsupportedAppUsage
Christopher Tate7060b042014-06-09 19:50:00 -0700301 private final int jobId;
Matthew Williams3d86fd22014-05-16 18:02:17 -0700302 private final PersistableBundle extras;
Dianne Hackbornba604732016-02-10 17:05:10 -0800303 private final Bundle transientExtras;
Dianne Hackborna47223f2017-03-30 13:49:13 -0700304 private final ClipData clipData;
305 private final int clipGrantFlags;
Mathew Inwood61e8ae62018-08-14 14:17:44 +0100306 @UnsupportedAppUsage
Matthew Williams6de79e22014-05-01 10:47:00 -0700307 private final ComponentName service;
Dianne Hackborna06ec6a2017-02-13 10:08:42 -0800308 private final int constraintFlags;
Dianne Hackborn1a30bd92016-01-11 11:05:00 -0800309 private final TriggerContentUri[] triggerContentUris;
Dianne Hackborn8db0fc12016-04-12 13:48:25 -0700310 private final long triggerContentUpdateDelay;
311 private final long triggerContentMaxDelay;
Matthew Williams9b9244b62014-05-14 11:06:04 -0700312 private final boolean hasEarlyConstraint;
313 private final boolean hasLateConstraint;
Jeff Sharkeyd0fff2e2017-11-07 16:55:06 -0700314 private final NetworkRequest networkRequest;
Jeff Sharkey8474ca02018-03-26 19:10:02 -0600315 private final long networkDownloadBytes;
316 private final long networkUploadBytes;
Matthew Williams6de79e22014-05-01 10:47:00 -0700317 private final long minLatencyMillis;
318 private final long maxExecutionDelayMillis;
319 private final boolean isPeriodic;
Matthew Williams900c67f2014-07-09 12:46:53 -0700320 private final boolean isPersisted;
Matthew Williams6de79e22014-05-01 10:47:00 -0700321 private final long intervalMillis;
Shreyas Basarge89ee6182015-12-17 15:16:36 +0000322 private final long flexMillis;
Matthew Williams6de79e22014-05-01 10:47:00 -0700323 private final long initialBackoffMillis;
324 private final int backoffPolicy;
Shreyas Basarge5db09082016-01-07 13:38:29 +0000325 private final int priority;
Mathew Inwood8c854f82018-09-14 12:35:36 +0100326 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
Jeff Sharkey1b6519b2016-04-28 15:33:18 -0600327 private final int flags;
Matthew Williams6de79e22014-05-01 10:47:00 -0700328
Matthew Williams6e31c5c2014-04-11 15:49:16 -0700329 /**
Dianne Hackborne9a988c2016-05-27 17:59:40 -0700330 * Unique job id associated with this application (uid). This is the same job ID
331 * you supplied in the {@link Builder} constructor.
Matthew Williams6e31c5c2014-04-11 15:49:16 -0700332 */
Matthew Williams9b9244b62014-05-14 11:06:04 -0700333 public int getId() {
Christopher Tate7060b042014-06-09 19:50:00 -0700334 return jobId;
Matthew Williams6e31c5c2014-04-11 15:49:16 -0700335 }
336
337 /**
Jeff Sharkey8474ca02018-03-26 19:10:02 -0600338 * @see JobInfo.Builder#setExtras(PersistableBundle)
Matthew Williams6e31c5c2014-04-11 15:49:16 -0700339 */
Dianne Hackbornf9bac162017-04-20 17:17:48 -0700340 public @NonNull PersistableBundle getExtras() {
Matthew Williams6e31c5c2014-04-11 15:49:16 -0700341 return extras;
342 }
343
344 /**
Jeff Sharkey8474ca02018-03-26 19:10:02 -0600345 * @see JobInfo.Builder#setTransientExtras(Bundle)
Dianne Hackbornba604732016-02-10 17:05:10 -0800346 */
Dianne Hackbornf9bac162017-04-20 17:17:48 -0700347 public @NonNull Bundle getTransientExtras() {
Dianne Hackbornba604732016-02-10 17:05:10 -0800348 return transientExtras;
349 }
350
351 /**
Jeff Sharkey8474ca02018-03-26 19:10:02 -0600352 * @see JobInfo.Builder#setClipData(ClipData, int)
Dianne Hackborna47223f2017-03-30 13:49:13 -0700353 */
Dianne Hackbornf9bac162017-04-20 17:17:48 -0700354 public @Nullable ClipData getClipData() {
Dianne Hackborna47223f2017-03-30 13:49:13 -0700355 return clipData;
356 }
357
358 /**
Jeff Sharkey8474ca02018-03-26 19:10:02 -0600359 * @see JobInfo.Builder#setClipData(ClipData, int)
Dianne Hackborna47223f2017-03-30 13:49:13 -0700360 */
361 public int getClipGrantFlags() {
362 return clipGrantFlags;
363 }
364
365 /**
Christopher Tate7060b042014-06-09 19:50:00 -0700366 * Name of the service endpoint that will be called back into by the JobScheduler.
Matthew Williams6e31c5c2014-04-11 15:49:16 -0700367 */
Dianne Hackbornf9bac162017-04-20 17:17:48 -0700368 public @NonNull ComponentName getService() {
Matthew Williams6de79e22014-05-01 10:47:00 -0700369 return service;
Matthew Williams6e31c5c2014-04-11 15:49:16 -0700370 }
371
Shreyas Basarge5db09082016-01-07 13:38:29 +0000372 /** @hide */
373 public int getPriority() {
374 return priority;
375 }
376
Jeff Sharkey1b6519b2016-04-28 15:33:18 -0600377 /** @hide */
378 public int getFlags() {
379 return flags;
380 }
381
Makoto Onuki959acb52018-01-26 14:10:03 -0800382 /** @hide */
383 public boolean isExemptedFromAppStandby() {
Makoto Onuki2b5811a2018-02-08 11:09:42 -0800384 return ((flags & FLAG_EXEMPT_FROM_APP_STANDBY) != 0) && !isPeriodic();
Makoto Onuki959acb52018-01-26 14:10:03 -0800385 }
386
Matthew Williams6e31c5c2014-04-11 15:49:16 -0700387 /**
Jeff Sharkey8474ca02018-03-26 19:10:02 -0600388 * @see JobInfo.Builder#setRequiresCharging(boolean)
Matthew Williams6e31c5c2014-04-11 15:49:16 -0700389 */
390 public boolean isRequireCharging() {
Dianne Hackborna06ec6a2017-02-13 10:08:42 -0800391 return (constraintFlags & CONSTRAINT_FLAG_CHARGING) != 0;
392 }
393
394 /**
Jeff Sharkey8474ca02018-03-26 19:10:02 -0600395 * @see JobInfo.Builder#setRequiresBatteryNotLow(boolean)
Dianne Hackborna06ec6a2017-02-13 10:08:42 -0800396 */
397 public boolean isRequireBatteryNotLow() {
398 return (constraintFlags & CONSTRAINT_FLAG_BATTERY_NOT_LOW) != 0;
Matthew Williams6e31c5c2014-04-11 15:49:16 -0700399 }
400
401 /**
Jeff Sharkey8474ca02018-03-26 19:10:02 -0600402 * @see JobInfo.Builder#setRequiresDeviceIdle(boolean)
Matthew Williams6e31c5c2014-04-11 15:49:16 -0700403 */
404 public boolean isRequireDeviceIdle() {
Dianne Hackborna06ec6a2017-02-13 10:08:42 -0800405 return (constraintFlags & CONSTRAINT_FLAG_DEVICE_IDLE) != 0;
406 }
407
408 /**
Jeff Sharkey8474ca02018-03-26 19:10:02 -0600409 * @see JobInfo.Builder#setRequiresStorageNotLow(boolean)
Dianne Hackborn532ea262017-03-17 17:50:55 -0700410 */
411 public boolean isRequireStorageNotLow() {
412 return (constraintFlags & CONSTRAINT_FLAG_STORAGE_NOT_LOW) != 0;
413 }
414
415 /**
Dianne Hackborna06ec6a2017-02-13 10:08:42 -0800416 * @hide
417 */
418 public int getConstraintFlags() {
419 return constraintFlags;
Matthew Williams6e31c5c2014-04-11 15:49:16 -0700420 }
421
422 /**
Dianne Hackborn1a30bd92016-01-11 11:05:00 -0800423 * Which content: URIs must change for the job to be scheduled. Returns null
424 * if there are none required.
Jeff Sharkey8474ca02018-03-26 19:10:02 -0600425 * @see JobInfo.Builder#addTriggerContentUri(TriggerContentUri)
Dianne Hackborn1a30bd92016-01-11 11:05:00 -0800426 */
Dianne Hackbornf9bac162017-04-20 17:17:48 -0700427 public @Nullable TriggerContentUri[] getTriggerContentUris() {
Dianne Hackborn1a30bd92016-01-11 11:05:00 -0800428 return triggerContentUris;
429 }
430
431 /**
Dianne Hackborn8db0fc12016-04-12 13:48:25 -0700432 * When triggering on content URI changes, this is the delay from when a change
433 * is detected until the job is scheduled.
Jeff Sharkey8474ca02018-03-26 19:10:02 -0600434 * @see JobInfo.Builder#setTriggerContentUpdateDelay(long)
Dianne Hackborn8db0fc12016-04-12 13:48:25 -0700435 */
436 public long getTriggerContentUpdateDelay() {
437 return triggerContentUpdateDelay;
438 }
439
440 /**
441 * When triggering on content URI changes, this is the maximum delay we will
442 * use before scheduling the job.
Jeff Sharkey8474ca02018-03-26 19:10:02 -0600443 * @see JobInfo.Builder#setTriggerContentMaxDelay(long)
Dianne Hackborn8db0fc12016-04-12 13:48:25 -0700444 */
445 public long getTriggerContentMaxDelay() {
446 return triggerContentMaxDelay;
447 }
448
449 /**
Jeff Sharkeyd0fff2e2017-11-07 16:55:06 -0700450 * Return the basic description of the kind of network this job requires.
451 *
452 * @deprecated This method attempts to map {@link #getRequiredNetwork()}
453 * into the set of simple constants, which results in a loss of
454 * fidelity. Callers should move to using
455 * {@link #getRequiredNetwork()} directly.
456 * @see Builder#setRequiredNetworkType(int)
Matthew Williams6e31c5c2014-04-11 15:49:16 -0700457 */
Jeff Sharkeyd0fff2e2017-11-07 16:55:06 -0700458 @Deprecated
Jeff Sharkey30e06bb2017-04-24 11:18:03 -0600459 public @NetworkType int getNetworkType() {
Jeff Sharkeyd0fff2e2017-11-07 16:55:06 -0700460 if (networkRequest == null) {
461 return NETWORK_TYPE_NONE;
462 } else if (networkRequest.networkCapabilities.hasCapability(NET_CAPABILITY_NOT_METERED)) {
463 return NETWORK_TYPE_UNMETERED;
464 } else if (networkRequest.networkCapabilities.hasCapability(NET_CAPABILITY_NOT_ROAMING)) {
465 return NETWORK_TYPE_NOT_ROAMING;
466 } else if (networkRequest.networkCapabilities.hasTransport(TRANSPORT_CELLULAR)) {
467 return NETWORK_TYPE_CELLULAR;
468 } else {
469 return NETWORK_TYPE_ANY;
470 }
471 }
472
473 /**
474 * Return the detailed description of the kind of network this job requires,
475 * or {@code null} if no specific kind of network is required.
476 *
477 * @see Builder#setRequiredNetwork(NetworkRequest)
478 */
479 public @Nullable NetworkRequest getRequiredNetwork() {
480 return networkRequest;
Matthew Williams6e31c5c2014-04-11 15:49:16 -0700481 }
482
483 /**
Jeff Sharkey8474ca02018-03-26 19:10:02 -0600484 * @deprecated replaced by {@link #getEstimatedNetworkDownloadBytes()} and
485 * {@link #getEstimatedNetworkUploadBytes()}.
486 * @removed
487 */
488 @Deprecated
489 public @BytesLong long getEstimatedNetworkBytes() {
490 if (networkDownloadBytes == NETWORK_BYTES_UNKNOWN
491 && networkUploadBytes == NETWORK_BYTES_UNKNOWN) {
492 return NETWORK_BYTES_UNKNOWN;
493 } else if (networkDownloadBytes == NETWORK_BYTES_UNKNOWN) {
494 return networkUploadBytes;
495 } else if (networkUploadBytes == NETWORK_BYTES_UNKNOWN) {
496 return networkDownloadBytes;
497 } else {
498 return networkDownloadBytes + networkUploadBytes;
499 }
500 }
501
502 /**
503 * Return the estimated size of download traffic that will be performed by
Jeff Sharkeycaa3f8d2017-10-25 16:12:00 -0600504 * this job, in bytes.
505 *
Jeff Sharkey8474ca02018-03-26 19:10:02 -0600506 * @return Estimated size of download traffic, or
Jeff Sharkeycaa3f8d2017-10-25 16:12:00 -0600507 * {@link #NETWORK_BYTES_UNKNOWN} when unknown.
Jeff Sharkey8474ca02018-03-26 19:10:02 -0600508 * @see Builder#setEstimatedNetworkBytes(long, long)
Jeff Sharkeycaa3f8d2017-10-25 16:12:00 -0600509 */
Jeff Sharkey8474ca02018-03-26 19:10:02 -0600510 public @BytesLong long getEstimatedNetworkDownloadBytes() {
511 return networkDownloadBytes;
512 }
513
514 /**
515 * Return the estimated size of upload traffic that will be performed by
516 * this job, in bytes.
517 *
518 * @return Estimated size of upload traffic, or
519 * {@link #NETWORK_BYTES_UNKNOWN} when unknown.
520 * @see Builder#setEstimatedNetworkBytes(long, long)
521 */
522 public @BytesLong long getEstimatedNetworkUploadBytes() {
523 return networkUploadBytes;
Jeff Sharkeycaa3f8d2017-10-25 16:12:00 -0600524 }
525
526 /**
Christopher Tate7060b042014-06-09 19:50:00 -0700527 * Set for a job that does not recur periodically, to specify a delay after which the job
528 * will be eligible for execution. This value is not set if the job recurs periodically.
Jeff Sharkey8474ca02018-03-26 19:10:02 -0600529 * @see JobInfo.Builder#setMinimumLatency(long)
Matthew Williams6e31c5c2014-04-11 15:49:16 -0700530 */
531 public long getMinLatencyMillis() {
532 return minLatencyMillis;
533 }
534
535 /**
Jeff Sharkey8474ca02018-03-26 19:10:02 -0600536 * @see JobInfo.Builder#setOverrideDeadline(long)
Matthew Williams6e31c5c2014-04-11 15:49:16 -0700537 */
538 public long getMaxExecutionDelayMillis() {
539 return maxExecutionDelayMillis;
540 }
541
542 /**
Christopher Tate7060b042014-06-09 19:50:00 -0700543 * Track whether this job will repeat with a given period.
Jeff Sharkey8474ca02018-03-26 19:10:02 -0600544 * @see JobInfo.Builder#setPeriodic(long)
545 * @see JobInfo.Builder#setPeriodic(long, long)
Matthew Williams6e31c5c2014-04-11 15:49:16 -0700546 */
547 public boolean isPeriodic() {
548 return isPeriodic;
549 }
550
551 /**
Jeff Sharkey8474ca02018-03-26 19:10:02 -0600552 * @see JobInfo.Builder#setPersisted(boolean)
Matthew Williams900c67f2014-07-09 12:46:53 -0700553 */
554 public boolean isPersisted() {
555 return isPersisted;
556 }
557
558 /**
Christopher Tate7060b042014-06-09 19:50:00 -0700559 * Set to the interval between occurrences of this job. This value is <b>not</b> set if the
560 * job does not recur periodically.
Jeff Sharkey8474ca02018-03-26 19:10:02 -0600561 * @see JobInfo.Builder#setPeriodic(long)
562 * @see JobInfo.Builder#setPeriodic(long, long)
Matthew Williams6e31c5c2014-04-11 15:49:16 -0700563 */
564 public long getIntervalMillis() {
Jeff Sharkeyd0fff2e2017-11-07 16:55:06 -0700565 return intervalMillis;
Shreyas Basarge89ee6182015-12-17 15:16:36 +0000566 }
567
568 /**
Shreyas Basarge9e6d5882016-04-12 10:59:07 +0100569 * Flex time for this job. Only valid if this is a periodic job. The job can
570 * execute at any time in a window of flex length at the end of the period.
Jeff Sharkey8474ca02018-03-26 19:10:02 -0600571 * @see JobInfo.Builder#setPeriodic(long)
572 * @see JobInfo.Builder#setPeriodic(long, long)
Shreyas Basarge89ee6182015-12-17 15:16:36 +0000573 */
574 public long getFlexMillis() {
Jeff Sharkeyd0fff2e2017-11-07 16:55:06 -0700575 return flexMillis;
Matthew Williams6e31c5c2014-04-11 15:49:16 -0700576 }
577
578 /**
Christopher Tate7060b042014-06-09 19:50:00 -0700579 * The amount of time the JobScheduler will wait before rescheduling a failed job. This value
580 * will be increased depending on the backoff policy specified at job creation time. Defaults
Dianne Hackbornbfc23312017-05-11 11:53:24 -0700581 * to 30 seconds, minimum is currently 10 seconds.
Jeff Sharkey8474ca02018-03-26 19:10:02 -0600582 * @see JobInfo.Builder#setBackoffCriteria(long, int)
Matthew Williams6e31c5c2014-04-11 15:49:16 -0700583 */
584 public long getInitialBackoffMillis() {
Jeff Sharkeyd0fff2e2017-11-07 16:55:06 -0700585 return initialBackoffMillis;
Matthew Williams6e31c5c2014-04-11 15:49:16 -0700586 }
587
588 /**
Jeff Sharkey30e06bb2017-04-24 11:18:03 -0600589 * Return the backoff policy of this job.
Jeff Sharkey8474ca02018-03-26 19:10:02 -0600590 * @see JobInfo.Builder#setBackoffCriteria(long, int)
Matthew Williams6e31c5c2014-04-11 15:49:16 -0700591 */
Jeff Sharkey30e06bb2017-04-24 11:18:03 -0600592 public @BackoffPolicy int getBackoffPolicy() {
Matthew Williams6e31c5c2014-04-11 15:49:16 -0700593 return backoffPolicy;
594 }
595
Matthew Williams9b9244b62014-05-14 11:06:04 -0700596 /**
Jeff Sharkey8474ca02018-03-26 19:10:02 -0600597 * @see JobInfo.Builder#setImportantWhileForeground(boolean)
598 */
599 public boolean isImportantWhileForeground() {
600 return (flags & FLAG_IMPORTANT_WHILE_FOREGROUND) != 0;
601 }
602
603 /**
604 * @see JobInfo.Builder#setPrefetch(boolean)
605 */
606 public boolean isPrefetch() {
607 return (flags & FLAG_PREFETCH) != 0;
608 }
609
610 /**
Matthew Williams9b9244b62014-05-14 11:06:04 -0700611 * User can specify an early constraint of 0L, which is valid, so we keep track of whether the
612 * function was called at all.
613 * @hide
614 */
615 public boolean hasEarlyConstraint() {
616 return hasEarlyConstraint;
617 }
618
619 /**
620 * User can specify a late constraint of 0L, which is valid, so we keep track of whether the
621 * function was called at all.
622 * @hide
623 */
624 public boolean hasLateConstraint() {
625 return hasLateConstraint;
626 }
627
Dianne Hackborn7da13d72017-04-04 17:17:35 -0700628 private static boolean kindofEqualsBundle(BaseBundle a, BaseBundle b) {
629 return (a == b) || (a != null && a.kindofEquals(b));
630 }
631
632 @Override
633 public boolean equals(Object o) {
634 if (!(o instanceof JobInfo)) {
635 return false;
636 }
637 JobInfo j = (JobInfo) o;
638 if (jobId != j.jobId) {
639 return false;
640 }
641 // XXX won't be correct if one is parcelled and the other not.
642 if (!kindofEqualsBundle(extras, j.extras)) {
643 return false;
644 }
645 // XXX won't be correct if one is parcelled and the other not.
646 if (!kindofEqualsBundle(transientExtras, j.transientExtras)) {
647 return false;
648 }
649 // XXX for now we consider two different clip data objects to be different,
650 // regardless of whether their contents are the same.
651 if (clipData != j.clipData) {
652 return false;
653 }
654 if (clipGrantFlags != j.clipGrantFlags) {
655 return false;
656 }
657 if (!Objects.equals(service, j.service)) {
658 return false;
659 }
660 if (constraintFlags != j.constraintFlags) {
661 return false;
662 }
Paul Duffinc67663c2017-05-26 09:46:48 +0100663 if (!Arrays.equals(triggerContentUris, j.triggerContentUris)) {
Dianne Hackborn7da13d72017-04-04 17:17:35 -0700664 return false;
665 }
666 if (triggerContentUpdateDelay != j.triggerContentUpdateDelay) {
667 return false;
668 }
669 if (triggerContentMaxDelay != j.triggerContentMaxDelay) {
670 return false;
671 }
672 if (hasEarlyConstraint != j.hasEarlyConstraint) {
673 return false;
674 }
675 if (hasLateConstraint != j.hasLateConstraint) {
676 return false;
677 }
Jeff Sharkeyd0fff2e2017-11-07 16:55:06 -0700678 if (!Objects.equals(networkRequest, j.networkRequest)) {
Dianne Hackborn7da13d72017-04-04 17:17:35 -0700679 return false;
680 }
Jeff Sharkey8474ca02018-03-26 19:10:02 -0600681 if (networkDownloadBytes != j.networkDownloadBytes) {
682 return false;
683 }
684 if (networkUploadBytes != j.networkUploadBytes) {
Jeff Sharkeycaa3f8d2017-10-25 16:12:00 -0600685 return false;
686 }
Dianne Hackborn7da13d72017-04-04 17:17:35 -0700687 if (minLatencyMillis != j.minLatencyMillis) {
688 return false;
689 }
690 if (maxExecutionDelayMillis != j.maxExecutionDelayMillis) {
691 return false;
692 }
693 if (isPeriodic != j.isPeriodic) {
694 return false;
695 }
696 if (isPersisted != j.isPersisted) {
697 return false;
698 }
699 if (intervalMillis != j.intervalMillis) {
700 return false;
701 }
702 if (flexMillis != j.flexMillis) {
703 return false;
704 }
705 if (initialBackoffMillis != j.initialBackoffMillis) {
706 return false;
707 }
708 if (backoffPolicy != j.backoffPolicy) {
709 return false;
710 }
711 if (priority != j.priority) {
712 return false;
713 }
714 if (flags != j.flags) {
715 return false;
716 }
717 return true;
718 }
719
720 @Override
721 public int hashCode() {
722 int hashCode = jobId;
723 if (extras != null) {
Paul Duffinc67663c2017-05-26 09:46:48 +0100724 hashCode = 31 * hashCode + extras.hashCode();
Dianne Hackborn7da13d72017-04-04 17:17:35 -0700725 }
726 if (transientExtras != null) {
Paul Duffinc67663c2017-05-26 09:46:48 +0100727 hashCode = 31 * hashCode + transientExtras.hashCode();
Dianne Hackborn7da13d72017-04-04 17:17:35 -0700728 }
729 if (clipData != null) {
Paul Duffinc67663c2017-05-26 09:46:48 +0100730 hashCode = 31 * hashCode + clipData.hashCode();
Dianne Hackborn7da13d72017-04-04 17:17:35 -0700731 }
732 hashCode = 31*hashCode + clipGrantFlags;
733 if (service != null) {
Paul Duffinc67663c2017-05-26 09:46:48 +0100734 hashCode = 31 * hashCode + service.hashCode();
Dianne Hackborn7da13d72017-04-04 17:17:35 -0700735 }
Paul Duffinc67663c2017-05-26 09:46:48 +0100736 hashCode = 31 * hashCode + constraintFlags;
Dianne Hackborn7da13d72017-04-04 17:17:35 -0700737 if (triggerContentUris != null) {
Paul Duffinc67663c2017-05-26 09:46:48 +0100738 hashCode = 31 * hashCode + Arrays.hashCode(triggerContentUris);
Dianne Hackborn7da13d72017-04-04 17:17:35 -0700739 }
Paul Duffinc67663c2017-05-26 09:46:48 +0100740 hashCode = 31 * hashCode + Long.hashCode(triggerContentUpdateDelay);
741 hashCode = 31 * hashCode + Long.hashCode(triggerContentMaxDelay);
742 hashCode = 31 * hashCode + Boolean.hashCode(hasEarlyConstraint);
743 hashCode = 31 * hashCode + Boolean.hashCode(hasLateConstraint);
Jeff Sharkeyd0fff2e2017-11-07 16:55:06 -0700744 if (networkRequest != null) {
745 hashCode = 31 * hashCode + networkRequest.hashCode();
746 }
Jeff Sharkey8474ca02018-03-26 19:10:02 -0600747 hashCode = 31 * hashCode + Long.hashCode(networkDownloadBytes);
748 hashCode = 31 * hashCode + Long.hashCode(networkUploadBytes);
Paul Duffinc67663c2017-05-26 09:46:48 +0100749 hashCode = 31 * hashCode + Long.hashCode(minLatencyMillis);
750 hashCode = 31 * hashCode + Long.hashCode(maxExecutionDelayMillis);
751 hashCode = 31 * hashCode + Boolean.hashCode(isPeriodic);
752 hashCode = 31 * hashCode + Boolean.hashCode(isPersisted);
753 hashCode = 31 * hashCode + Long.hashCode(intervalMillis);
754 hashCode = 31 * hashCode + Long.hashCode(flexMillis);
755 hashCode = 31 * hashCode + Long.hashCode(initialBackoffMillis);
756 hashCode = 31 * hashCode + backoffPolicy;
757 hashCode = 31 * hashCode + priority;
758 hashCode = 31 * hashCode + flags;
Dianne Hackborn7da13d72017-04-04 17:17:35 -0700759 return hashCode;
760 }
761
Christopher Tate7060b042014-06-09 19:50:00 -0700762 private JobInfo(Parcel in) {
763 jobId = in.readInt();
Matthew Williams3d86fd22014-05-16 18:02:17 -0700764 extras = in.readPersistableBundle();
Dianne Hackbornba604732016-02-10 17:05:10 -0800765 transientExtras = in.readBundle();
Dianne Hackborna47223f2017-03-30 13:49:13 -0700766 if (in.readInt() != 0) {
767 clipData = ClipData.CREATOR.createFromParcel(in);
768 clipGrantFlags = in.readInt();
769 } else {
770 clipData = null;
771 clipGrantFlags = 0;
772 }
Matthew Williamseffacfa2014-06-05 20:56:40 -0700773 service = in.readParcelable(null);
Dianne Hackborna06ec6a2017-02-13 10:08:42 -0800774 constraintFlags = in.readInt();
Dianne Hackborn1a30bd92016-01-11 11:05:00 -0800775 triggerContentUris = in.createTypedArray(TriggerContentUri.CREATOR);
Dianne Hackborn8db0fc12016-04-12 13:48:25 -0700776 triggerContentUpdateDelay = in.readLong();
777 triggerContentMaxDelay = in.readLong();
Jeff Sharkeyd0fff2e2017-11-07 16:55:06 -0700778 if (in.readInt() != 0) {
779 networkRequest = NetworkRequest.CREATOR.createFromParcel(in);
780 } else {
781 networkRequest = null;
782 }
Jeff Sharkey8474ca02018-03-26 19:10:02 -0600783 networkDownloadBytes = in.readLong();
784 networkUploadBytes = in.readLong();
Matthew Williams6e31c5c2014-04-11 15:49:16 -0700785 minLatencyMillis = in.readLong();
786 maxExecutionDelayMillis = in.readLong();
787 isPeriodic = in.readInt() == 1;
Matthew Williams900c67f2014-07-09 12:46:53 -0700788 isPersisted = in.readInt() == 1;
Matthew Williams6e31c5c2014-04-11 15:49:16 -0700789 intervalMillis = in.readLong();
Shreyas Basarge89ee6182015-12-17 15:16:36 +0000790 flexMillis = in.readLong();
Matthew Williams6e31c5c2014-04-11 15:49:16 -0700791 initialBackoffMillis = in.readLong();
792 backoffPolicy = in.readInt();
Matthew Williams9b9244b62014-05-14 11:06:04 -0700793 hasEarlyConstraint = in.readInt() == 1;
794 hasLateConstraint = in.readInt() == 1;
Shreyas Basarge5db09082016-01-07 13:38:29 +0000795 priority = in.readInt();
Jeff Sharkey1b6519b2016-04-28 15:33:18 -0600796 flags = in.readInt();
Matthew Williams6e31c5c2014-04-11 15:49:16 -0700797 }
798
Christopher Tate7060b042014-06-09 19:50:00 -0700799 private JobInfo(JobInfo.Builder b) {
800 jobId = b.mJobId;
Dianne Hackborn2510b372017-03-03 17:01:38 -0800801 extras = b.mExtras.deepCopy();
802 transientExtras = b.mTransientExtras.deepCopy();
Dianne Hackborna47223f2017-03-30 13:49:13 -0700803 clipData = b.mClipData;
804 clipGrantFlags = b.mClipGrantFlags;
Christopher Tate7060b042014-06-09 19:50:00 -0700805 service = b.mJobService;
Dianne Hackborna06ec6a2017-02-13 10:08:42 -0800806 constraintFlags = b.mConstraintFlags;
Dianne Hackborn1a30bd92016-01-11 11:05:00 -0800807 triggerContentUris = b.mTriggerContentUris != null
808 ? b.mTriggerContentUris.toArray(new TriggerContentUri[b.mTriggerContentUris.size()])
809 : null;
Dianne Hackborn8db0fc12016-04-12 13:48:25 -0700810 triggerContentUpdateDelay = b.mTriggerContentUpdateDelay;
811 triggerContentMaxDelay = b.mTriggerContentMaxDelay;
Jeff Sharkeyd0fff2e2017-11-07 16:55:06 -0700812 networkRequest = b.mNetworkRequest;
Jeff Sharkey8474ca02018-03-26 19:10:02 -0600813 networkDownloadBytes = b.mNetworkDownloadBytes;
814 networkUploadBytes = b.mNetworkUploadBytes;
Matthew Williams6e31c5c2014-04-11 15:49:16 -0700815 minLatencyMillis = b.mMinLatencyMillis;
816 maxExecutionDelayMillis = b.mMaxExecutionDelayMillis;
817 isPeriodic = b.mIsPeriodic;
Matthew Williams900c67f2014-07-09 12:46:53 -0700818 isPersisted = b.mIsPersisted;
Matthew Williams6e31c5c2014-04-11 15:49:16 -0700819 intervalMillis = b.mIntervalMillis;
Shreyas Basarge89ee6182015-12-17 15:16:36 +0000820 flexMillis = b.mFlexMillis;
Matthew Williams6e31c5c2014-04-11 15:49:16 -0700821 initialBackoffMillis = b.mInitialBackoffMillis;
822 backoffPolicy = b.mBackoffPolicy;
Matthew Williams9b9244b62014-05-14 11:06:04 -0700823 hasEarlyConstraint = b.mHasEarlyConstraint;
824 hasLateConstraint = b.mHasLateConstraint;
Shreyas Basarge5db09082016-01-07 13:38:29 +0000825 priority = b.mPriority;
Jeff Sharkey1b6519b2016-04-28 15:33:18 -0600826 flags = b.mFlags;
Matthew Williams6e31c5c2014-04-11 15:49:16 -0700827 }
828
829 @Override
830 public int describeContents() {
831 return 0;
832 }
833
834 @Override
835 public void writeToParcel(Parcel out, int flags) {
Christopher Tate7060b042014-06-09 19:50:00 -0700836 out.writeInt(jobId);
Matthew Williams3d86fd22014-05-16 18:02:17 -0700837 out.writePersistableBundle(extras);
Dianne Hackbornba604732016-02-10 17:05:10 -0800838 out.writeBundle(transientExtras);
Dianne Hackborna47223f2017-03-30 13:49:13 -0700839 if (clipData != null) {
840 out.writeInt(1);
841 clipData.writeToParcel(out, flags);
842 out.writeInt(clipGrantFlags);
843 } else {
844 out.writeInt(0);
845 }
Matthew Williamseffacfa2014-06-05 20:56:40 -0700846 out.writeParcelable(service, flags);
Dianne Hackborna06ec6a2017-02-13 10:08:42 -0800847 out.writeInt(constraintFlags);
Dianne Hackborn1a30bd92016-01-11 11:05:00 -0800848 out.writeTypedArray(triggerContentUris, flags);
Dianne Hackborn8db0fc12016-04-12 13:48:25 -0700849 out.writeLong(triggerContentUpdateDelay);
850 out.writeLong(triggerContentMaxDelay);
Jeff Sharkeyd0fff2e2017-11-07 16:55:06 -0700851 if (networkRequest != null) {
852 out.writeInt(1);
853 networkRequest.writeToParcel(out, flags);
854 } else {
855 out.writeInt(0);
856 }
Jeff Sharkey8474ca02018-03-26 19:10:02 -0600857 out.writeLong(networkDownloadBytes);
858 out.writeLong(networkUploadBytes);
Matthew Williams6e31c5c2014-04-11 15:49:16 -0700859 out.writeLong(minLatencyMillis);
860 out.writeLong(maxExecutionDelayMillis);
861 out.writeInt(isPeriodic ? 1 : 0);
Matthew Williams900c67f2014-07-09 12:46:53 -0700862 out.writeInt(isPersisted ? 1 : 0);
Matthew Williams6e31c5c2014-04-11 15:49:16 -0700863 out.writeLong(intervalMillis);
Shreyas Basarge89ee6182015-12-17 15:16:36 +0000864 out.writeLong(flexMillis);
Matthew Williams6e31c5c2014-04-11 15:49:16 -0700865 out.writeLong(initialBackoffMillis);
866 out.writeInt(backoffPolicy);
Matthew Williams9b9244b62014-05-14 11:06:04 -0700867 out.writeInt(hasEarlyConstraint ? 1 : 0);
868 out.writeInt(hasLateConstraint ? 1 : 0);
Shreyas Basarge5db09082016-01-07 13:38:29 +0000869 out.writeInt(priority);
Jeff Sharkey1b6519b2016-04-28 15:33:18 -0600870 out.writeInt(this.flags);
Matthew Williams6e31c5c2014-04-11 15:49:16 -0700871 }
872
Jeff Sharkey9e8f83d2019-02-28 12:06:45 -0700873 public static final @android.annotation.NonNull Creator<JobInfo> CREATOR = new Creator<JobInfo>() {
Matthew Williams6e31c5c2014-04-11 15:49:16 -0700874 @Override
Christopher Tate7060b042014-06-09 19:50:00 -0700875 public JobInfo createFromParcel(Parcel in) {
876 return new JobInfo(in);
Matthew Williams6e31c5c2014-04-11 15:49:16 -0700877 }
878
879 @Override
Christopher Tate7060b042014-06-09 19:50:00 -0700880 public JobInfo[] newArray(int size) {
881 return new JobInfo[size];
Matthew Williams6e31c5c2014-04-11 15:49:16 -0700882 }
883 };
884
Matthew Williamsee410da2014-07-25 11:30:40 -0700885 @Override
886 public String toString() {
887 return "(job:" + jobId + "/" + service.flattenToShortString() + ")";
888 }
889
Dianne Hackborn1a30bd92016-01-11 11:05:00 -0800890 /**
891 * Information about a content URI modification that a job would like to
892 * trigger on.
893 */
894 public static final class TriggerContentUri implements Parcelable {
895 private final Uri mUri;
896 private final int mFlags;
897
Jeff Sharkey30e06bb2017-04-24 11:18:03 -0600898 /** @hide */
899 @Retention(RetentionPolicy.SOURCE)
900 @IntDef(flag = true, prefix = { "FLAG_" }, value = {
901 FLAG_NOTIFY_FOR_DESCENDANTS,
902 })
903 public @interface Flags { }
904
Dianne Hackborn1a30bd92016-01-11 11:05:00 -0800905 /**
906 * Flag for trigger: also trigger if any descendants of the given URI change.
907 * Corresponds to the <var>notifyForDescendants</var> of
908 * {@link android.content.ContentResolver#registerContentObserver}.
909 */
910 public static final int FLAG_NOTIFY_FOR_DESCENDANTS = 1<<0;
911
912 /**
913 * Create a new trigger description.
914 * @param uri The URI to observe. Must be non-null.
Jeff Sharkey30e06bb2017-04-24 11:18:03 -0600915 * @param flags Flags for the observer.
Dianne Hackborn1a30bd92016-01-11 11:05:00 -0800916 */
Jeff Sharkey30e06bb2017-04-24 11:18:03 -0600917 public TriggerContentUri(@NonNull Uri uri, @Flags int flags) {
Dianne Hackborn1a30bd92016-01-11 11:05:00 -0800918 mUri = uri;
919 mFlags = flags;
920 }
921
922 /**
923 * Return the Uri this trigger was created for.
924 */
925 public Uri getUri() {
926 return mUri;
927 }
928
929 /**
930 * Return the flags supplied for the trigger.
931 */
Jeff Sharkey30e06bb2017-04-24 11:18:03 -0600932 public @Flags int getFlags() {
Dianne Hackborn1a30bd92016-01-11 11:05:00 -0800933 return mFlags;
934 }
935
Dianne Hackborn121e1642016-06-21 20:39:02 -0700936 @Override
937 public boolean equals(Object o) {
938 if (!(o instanceof TriggerContentUri)) {
939 return false;
940 }
941 TriggerContentUri t = (TriggerContentUri) o;
942 return Objects.equals(t.mUri, mUri) && t.mFlags == mFlags;
943 }
944
945 @Override
946 public int hashCode() {
947 return (mUri == null ? 0 : mUri.hashCode()) ^ mFlags;
948 }
949
Dianne Hackborn1a30bd92016-01-11 11:05:00 -0800950 private TriggerContentUri(Parcel in) {
951 mUri = Uri.CREATOR.createFromParcel(in);
952 mFlags = in.readInt();
953 }
954
955 @Override
956 public int describeContents() {
957 return 0;
958 }
959
960 @Override
961 public void writeToParcel(Parcel out, int flags) {
962 mUri.writeToParcel(out, flags);
963 out.writeInt(mFlags);
964 }
965
Jeff Sharkey9e8f83d2019-02-28 12:06:45 -0700966 public static final @android.annotation.NonNull Creator<TriggerContentUri> CREATOR = new Creator<TriggerContentUri>() {
Dianne Hackborn1a30bd92016-01-11 11:05:00 -0800967 @Override
968 public TriggerContentUri createFromParcel(Parcel in) {
969 return new TriggerContentUri(in);
970 }
971
972 @Override
973 public TriggerContentUri[] newArray(int size) {
974 return new TriggerContentUri[size];
975 }
976 };
977 }
978
Christopher Tate7060b042014-06-09 19:50:00 -0700979 /** Builder class for constructing {@link JobInfo} objects. */
Matthew Williams9b9244b62014-05-14 11:06:04 -0700980 public static final class Builder {
Dianne Hackborne9a988c2016-05-27 17:59:40 -0700981 private final int mJobId;
982 private final ComponentName mJobService;
Matthew Williams3d86fd22014-05-16 18:02:17 -0700983 private PersistableBundle mExtras = PersistableBundle.EMPTY;
Dianne Hackbornba604732016-02-10 17:05:10 -0800984 private Bundle mTransientExtras = Bundle.EMPTY;
Dianne Hackborna47223f2017-03-30 13:49:13 -0700985 private ClipData mClipData;
986 private int mClipGrantFlags;
Dianne Hackborn1085ff62016-02-23 17:04:58 -0800987 private int mPriority = PRIORITY_DEFAULT;
Jeff Sharkey1b6519b2016-04-28 15:33:18 -0600988 private int mFlags;
Matthew Williams6e31c5c2014-04-11 15:49:16 -0700989 // Requirements.
Dianne Hackborna06ec6a2017-02-13 10:08:42 -0800990 private int mConstraintFlags;
Jeff Sharkeyd0fff2e2017-11-07 16:55:06 -0700991 private NetworkRequest mNetworkRequest;
Jeff Sharkey8474ca02018-03-26 19:10:02 -0600992 private long mNetworkDownloadBytes = NETWORK_BYTES_UNKNOWN;
993 private long mNetworkUploadBytes = NETWORK_BYTES_UNKNOWN;
Dianne Hackborn1a30bd92016-01-11 11:05:00 -0800994 private ArrayList<TriggerContentUri> mTriggerContentUris;
Dianne Hackborn8db0fc12016-04-12 13:48:25 -0700995 private long mTriggerContentUpdateDelay = -1;
996 private long mTriggerContentMaxDelay = -1;
Matthew Williams900c67f2014-07-09 12:46:53 -0700997 private boolean mIsPersisted;
Matthew Williams6e31c5c2014-04-11 15:49:16 -0700998 // One-off parameters.
999 private long mMinLatencyMillis;
1000 private long mMaxExecutionDelayMillis;
1001 // Periodic parameters.
1002 private boolean mIsPeriodic;
Matthew Williams9b9244b62014-05-14 11:06:04 -07001003 private boolean mHasEarlyConstraint;
1004 private boolean mHasLateConstraint;
Matthew Williams6e31c5c2014-04-11 15:49:16 -07001005 private long mIntervalMillis;
Shreyas Basarge89ee6182015-12-17 15:16:36 +00001006 private long mFlexMillis;
Matthew Williams6e31c5c2014-04-11 15:49:16 -07001007 // Back-off parameters.
Matthew Williams3d86fd22014-05-16 18:02:17 -07001008 private long mInitialBackoffMillis = DEFAULT_INITIAL_BACKOFF_MILLIS;
1009 private int mBackoffPolicy = DEFAULT_BACKOFF_POLICY;
Matthew Williams6e31c5c2014-04-11 15:49:16 -07001010 /** Easy way to track whether the client has tried to set a back-off policy. */
1011 private boolean mBackoffPolicySet = false;
1012
1013 /**
Dianne Hackborne9a988c2016-05-27 17:59:40 -07001014 * Initialize a new Builder to construct a {@link JobInfo}.
1015 *
Christopher Tate7060b042014-06-09 19:50:00 -07001016 * @param jobId Application-provided id for this job. Subsequent calls to cancel, or
Dianne Hackborne9a988c2016-05-27 17:59:40 -07001017 * jobs created with the same jobId, will update the pre-existing job with
1018 * the same id. This ID must be unique across all clients of the same uid
1019 * (not just the same package). You will want to make sure this is a stable
1020 * id across app updates, so probably not based on a resource ID.
Christopher Tate7060b042014-06-09 19:50:00 -07001021 * @param jobService The endpoint that you implement that will receive the callback from the
Dianne Hackborne9a988c2016-05-27 17:59:40 -07001022 * JobScheduler.
Matthew Williams6e31c5c2014-04-11 15:49:16 -07001023 */
Dianne Hackbornf9bac162017-04-20 17:17:48 -07001024 public Builder(int jobId, @NonNull ComponentName jobService) {
Christopher Tate7060b042014-06-09 19:50:00 -07001025 mJobService = jobService;
1026 mJobId = jobId;
Matthew Williams6e31c5c2014-04-11 15:49:16 -07001027 }
1028
Jeff Sharkey1b6519b2016-04-28 15:33:18 -06001029 /** @hide */
Mathew Inwood61e8ae62018-08-14 14:17:44 +01001030 @UnsupportedAppUsage
Shreyas Basarge5db09082016-01-07 13:38:29 +00001031 public Builder setPriority(int priority) {
1032 mPriority = priority;
1033 return this;
1034 }
1035
Jeff Sharkey1b6519b2016-04-28 15:33:18 -06001036 /** @hide */
Mathew Inwood61e8ae62018-08-14 14:17:44 +01001037 @UnsupportedAppUsage
Jeff Sharkey1b6519b2016-04-28 15:33:18 -06001038 public Builder setFlags(int flags) {
1039 mFlags = flags;
1040 return this;
1041 }
1042
Shreyas Basarge5db09082016-01-07 13:38:29 +00001043 /**
Matthew Williams6e31c5c2014-04-11 15:49:16 -07001044 * Set optional extras. This is persisted, so we only allow primitive types.
1045 * @param extras Bundle containing extras you want the scheduler to hold on to for you.
Jeff Sharkey8474ca02018-03-26 19:10:02 -06001046 * @see JobInfo#getExtras()
Matthew Williams6e31c5c2014-04-11 15:49:16 -07001047 */
Dianne Hackbornf9bac162017-04-20 17:17:48 -07001048 public Builder setExtras(@NonNull PersistableBundle extras) {
Matthew Williams6e31c5c2014-04-11 15:49:16 -07001049 mExtras = extras;
1050 return this;
1051 }
1052
1053 /**
Dianne Hackborn28d1b662017-04-21 14:17:23 -07001054 * Set optional transient extras.
1055 *
1056 * <p>Because setting this property is not compatible with persisted
1057 * jobs, doing so will throw an {@link java.lang.IllegalArgumentException} when
1058 * {@link android.app.job.JobInfo.Builder#build()} is called.</p>
1059 *
Dianne Hackbornba604732016-02-10 17:05:10 -08001060 * @param extras Bundle containing extras you want the scheduler to hold on to for you.
Jeff Sharkey8474ca02018-03-26 19:10:02 -06001061 * @see JobInfo#getTransientExtras()
Dianne Hackbornba604732016-02-10 17:05:10 -08001062 */
Dianne Hackbornf9bac162017-04-20 17:17:48 -07001063 public Builder setTransientExtras(@NonNull Bundle extras) {
Dianne Hackbornba604732016-02-10 17:05:10 -08001064 mTransientExtras = extras;
1065 return this;
1066 }
1067
1068 /**
Dianne Hackborna47223f2017-03-30 13:49:13 -07001069 * Set a {@link ClipData} associated with this Job.
1070 *
1071 * <p>The main purpose of providing a ClipData is to allow granting of
1072 * URI permissions for data associated with the clip. The exact kind
1073 * of permission grant to perform is specified through <var>grantFlags</var>.
1074 *
1075 * <p>If the ClipData contains items that are Intents, any
1076 * grant flags in those Intents will be ignored. Only flags provided as an argument
1077 * to this method are respected, and will be applied to all Uri or
1078 * Intent items in the clip (or sub-items of the clip).
1079 *
1080 * <p>Because setting this property is not compatible with persisted
1081 * jobs, doing so will throw an {@link java.lang.IllegalArgumentException} when
1082 * {@link android.app.job.JobInfo.Builder#build()} is called.</p>
1083 *
1084 * @param clip The new clip to set. May be null to clear the current clip.
1085 * @param grantFlags The desired permissions to grant for any URIs. This should be
1086 * a combination of {@link android.content.Intent#FLAG_GRANT_READ_URI_PERMISSION},
1087 * {@link android.content.Intent#FLAG_GRANT_WRITE_URI_PERMISSION}, and
1088 * {@link android.content.Intent#FLAG_GRANT_PREFIX_URI_PERMISSION}.
Jeff Sharkey8474ca02018-03-26 19:10:02 -06001089 * @see JobInfo#getClipData()
1090 * @see JobInfo#getClipGrantFlags()
Dianne Hackborna47223f2017-03-30 13:49:13 -07001091 */
Dianne Hackbornf9bac162017-04-20 17:17:48 -07001092 public Builder setClipData(@Nullable ClipData clip, int grantFlags) {
Dianne Hackborna47223f2017-03-30 13:49:13 -07001093 mClipData = clip;
1094 mClipGrantFlags = grantFlags;
1095 return this;
1096 }
1097
1098 /**
Jeff Sharkeyd0fff2e2017-11-07 16:55:06 -07001099 * Set basic description of the kind of network your job requires. If
1100 * you need more precise control over network capabilities, see
1101 * {@link #setRequiredNetwork(NetworkRequest)}.
1102 * <p>
1103 * If your job doesn't need a network connection, you don't need to call
1104 * this method, as the default value is {@link #NETWORK_TYPE_NONE}.
1105 * <p>
1106 * Calling this method defines network as a strict requirement for your
1107 * job. If the network requested is not available your job will never
1108 * run. See {@link #setOverrideDeadline(long)} to change this behavior.
1109 * Calling this method will override any requirements previously defined
1110 * by {@link #setRequiredNetwork(NetworkRequest)}; you typically only
1111 * want to call one of these methods.
Jeff Sharkey76a02412017-10-24 16:55:04 -06001112 * <p class="note">
Jeff Sharkeyd0fff2e2017-11-07 16:55:06 -07001113 * When your job executes in
Jeff Sharkey76a02412017-10-24 16:55:04 -06001114 * {@link JobService#onStartJob(JobParameters)}, be sure to use the
1115 * specific network returned by {@link JobParameters#getNetwork()},
1116 * otherwise you'll use the default network which may not meet this
1117 * constraint.
1118 *
Jeff Sharkeyd0fff2e2017-11-07 16:55:06 -07001119 * @see #setRequiredNetwork(NetworkRequest)
1120 * @see JobInfo#getNetworkType()
Jeff Sharkey76a02412017-10-24 16:55:04 -06001121 * @see JobParameters#getNetwork()
Matthew Williams6e31c5c2014-04-11 15:49:16 -07001122 */
Jeff Sharkey30e06bb2017-04-24 11:18:03 -06001123 public Builder setRequiredNetworkType(@NetworkType int networkType) {
Jeff Sharkeyd0fff2e2017-11-07 16:55:06 -07001124 if (networkType == NETWORK_TYPE_NONE) {
1125 return setRequiredNetwork(null);
1126 } else {
1127 final NetworkRequest.Builder builder = new NetworkRequest.Builder();
1128
1129 // All types require validated Internet
1130 builder.addCapability(NET_CAPABILITY_INTERNET);
1131 builder.addCapability(NET_CAPABILITY_VALIDATED);
1132 builder.removeCapability(NET_CAPABILITY_NOT_VPN);
1133
1134 if (networkType == NETWORK_TYPE_ANY) {
1135 // No other capabilities
1136 } else if (networkType == NETWORK_TYPE_UNMETERED) {
1137 builder.addCapability(NET_CAPABILITY_NOT_METERED);
1138 } else if (networkType == NETWORK_TYPE_NOT_ROAMING) {
1139 builder.addCapability(NET_CAPABILITY_NOT_ROAMING);
1140 } else if (networkType == NETWORK_TYPE_CELLULAR) {
1141 builder.addTransportType(TRANSPORT_CELLULAR);
1142 }
1143
1144 return setRequiredNetwork(builder.build());
1145 }
1146 }
1147
1148 /**
1149 * Set detailed description of the kind of network your job requires.
1150 * <p>
1151 * If your job doesn't need a network connection, you don't need to call
1152 * this method, as the default is {@code null}.
1153 * <p>
1154 * Calling this method defines network as a strict requirement for your
1155 * job. If the network requested is not available your job will never
1156 * run. See {@link #setOverrideDeadline(long)} to change this behavior.
1157 * Calling this method will override any requirements previously defined
1158 * by {@link #setRequiredNetworkType(int)}; you typically only want to
1159 * call one of these methods.
1160 * <p class="note">
1161 * When your job executes in
1162 * {@link JobService#onStartJob(JobParameters)}, be sure to use the
1163 * specific network returned by {@link JobParameters#getNetwork()},
1164 * otherwise you'll use the default network which may not meet this
1165 * constraint.
1166 *
1167 * @param networkRequest The detailed description of the kind of network
1168 * this job requires, or {@code null} if no specific kind of
1169 * network is required. Defining a {@link NetworkSpecifier}
1170 * is only supported for jobs that aren't persisted.
1171 * @see #setRequiredNetworkType(int)
1172 * @see JobInfo#getRequiredNetwork()
1173 * @see JobParameters#getNetwork()
1174 */
1175 public Builder setRequiredNetwork(@Nullable NetworkRequest networkRequest) {
1176 mNetworkRequest = networkRequest;
Matthew Williams6e31c5c2014-04-11 15:49:16 -07001177 return this;
1178 }
1179
Christopher Tate7060b042014-06-09 19:50:00 -07001180 /**
Jeff Sharkey8474ca02018-03-26 19:10:02 -06001181 * @deprecated replaced by
1182 * {@link #setEstimatedNetworkBytes(long, long)}.
1183 * @removed
1184 */
1185 @Deprecated
1186 public Builder setEstimatedNetworkBytes(@BytesLong long networkBytes) {
1187 return setEstimatedNetworkBytes(networkBytes, NETWORK_BYTES_UNKNOWN);
1188 }
1189
1190 /**
Jeff Sharkeycaa3f8d2017-10-25 16:12:00 -06001191 * Set the estimated size of network traffic that will be performed by
1192 * this job, in bytes.
1193 * <p>
1194 * Apps are encouraged to provide values that are as accurate as
1195 * possible, but when the exact size isn't available, an
1196 * order-of-magnitude estimate can be provided instead. Here are some
1197 * specific examples:
1198 * <ul>
1199 * <li>A job that is backing up a photo knows the exact size of that
1200 * photo, so it should provide that size as the estimate.
1201 * <li>A job that refreshes top news stories wouldn't know an exact
1202 * size, but if the size is expected to be consistently around 100KB, it
1203 * can provide that order-of-magnitude value as the estimate.
1204 * <li>A job that synchronizes email could end up using an extreme range
1205 * of data, from under 1KB when nothing has changed, to dozens of MB
1206 * when there are new emails with attachments. Jobs that cannot provide
Jeff Sharkey8474ca02018-03-26 19:10:02 -06001207 * reasonable estimates should use the sentinel value
1208 * {@link JobInfo#NETWORK_BYTES_UNKNOWN}.
Jeff Sharkeycaa3f8d2017-10-25 16:12:00 -06001209 * </ul>
1210 * Note that the system may choose to delay jobs with large network
1211 * usage estimates when the device has a poor network connection, in
1212 * order to save battery.
Jeff Sharkey8474ca02018-03-26 19:10:02 -06001213 * <p>
1214 * The values provided here only reflect the traffic that will be
1215 * performed by the base job; if you're using {@link JobWorkItem} then
1216 * you also need to define the network traffic used by each work item
1217 * when constructing them.
Jeff Sharkeycaa3f8d2017-10-25 16:12:00 -06001218 *
Jeff Sharkey8474ca02018-03-26 19:10:02 -06001219 * @param downloadBytes The estimated size of network traffic that will
1220 * be downloaded by this job, in bytes.
1221 * @param uploadBytes The estimated size of network traffic that will be
1222 * uploaded by this job, in bytes.
1223 * @see JobInfo#getEstimatedNetworkDownloadBytes()
1224 * @see JobInfo#getEstimatedNetworkUploadBytes()
1225 * @see JobWorkItem#JobWorkItem(android.content.Intent, long, long)
Jeff Sharkeycaa3f8d2017-10-25 16:12:00 -06001226 */
Jeff Sharkey8474ca02018-03-26 19:10:02 -06001227 public Builder setEstimatedNetworkBytes(@BytesLong long downloadBytes,
1228 @BytesLong long uploadBytes) {
1229 mNetworkDownloadBytes = downloadBytes;
1230 mNetworkUploadBytes = uploadBytes;
Jeff Sharkeycaa3f8d2017-10-25 16:12:00 -06001231 return this;
1232 }
1233
1234 /**
Christopher Tate78152512017-10-02 17:07:07 -07001235 * Specify that to run this job, the device must be charging (or be a
1236 * non-battery-powered device connected to permanent power, such as Android TV
1237 * devices). This defaults to {@code false}.
1238 *
1239 * <p class="note">For purposes of running jobs, a battery-powered device
1240 * "charging" is not quite the same as simply being connected to power. If the
1241 * device is so busy that the battery is draining despite a power connection, jobs
1242 * with this constraint will <em>not</em> run. This can happen during some
1243 * common use cases such as video chat, particularly if the device is plugged in
1244 * to USB rather than to wall power.
1245 *
1246 * @param requiresCharging Pass {@code true} to require that the device be
1247 * charging in order to run the job.
Jeff Sharkey8474ca02018-03-26 19:10:02 -06001248 * @see JobInfo#isRequireCharging()
Matthew Williams6e31c5c2014-04-11 15:49:16 -07001249 */
1250 public Builder setRequiresCharging(boolean requiresCharging) {
Dianne Hackborna06ec6a2017-02-13 10:08:42 -08001251 mConstraintFlags = (mConstraintFlags&~CONSTRAINT_FLAG_CHARGING)
1252 | (requiresCharging ? CONSTRAINT_FLAG_CHARGING : 0);
1253 return this;
1254 }
1255
1256 /**
1257 * Specify that to run this job, the device's battery level must not be low.
1258 * This defaults to false. If true, the job will only run when the battery level
1259 * is not low, which is generally the point where the user is given a "low battery"
1260 * warning.
1261 * @param batteryNotLow Whether or not the device's battery level must not be low.
Jeff Sharkey8474ca02018-03-26 19:10:02 -06001262 * @see JobInfo#isRequireBatteryNotLow()
Dianne Hackborna06ec6a2017-02-13 10:08:42 -08001263 */
1264 public Builder setRequiresBatteryNotLow(boolean batteryNotLow) {
1265 mConstraintFlags = (mConstraintFlags&~CONSTRAINT_FLAG_BATTERY_NOT_LOW)
1266 | (batteryNotLow ? CONSTRAINT_FLAG_BATTERY_NOT_LOW : 0);
Matthew Williams6e31c5c2014-04-11 15:49:16 -07001267 return this;
1268 }
1269
1270 /**
Christopher Tate78152512017-10-02 17:07:07 -07001271 * When set {@code true}, ensure that this job will not run if the device is in active use.
1272 * The default state is {@code false}: that is, the for the job to be runnable even when
1273 * someone is interacting with the device.
1274 *
1275 * <p>This state is a loose definition provided by the system. In general, it means that
1276 * the device is not currently being used interactively, and has not been in use for some
1277 * time. As such, it is a good time to perform resource heavy jobs. Bear in mind that
1278 * battery usage will still be attributed to your application, and surfaced to the user in
1279 * battery stats.</p>
1280 *
1281 * <p class="note">Despite the similar naming, this job constraint is <em>not</em>
1282 * related to the system's "device idle" or "doze" states. This constraint only
1283 * determines whether a job is allowed to run while the device is directly in use.
1284 *
1285 * @param requiresDeviceIdle Pass {@code true} to prevent the job from running
1286 * while the device is being used interactively.
Jeff Sharkey8474ca02018-03-26 19:10:02 -06001287 * @see JobInfo#isRequireDeviceIdle()
Matthew Williams6e31c5c2014-04-11 15:49:16 -07001288 */
1289 public Builder setRequiresDeviceIdle(boolean requiresDeviceIdle) {
Dianne Hackborna06ec6a2017-02-13 10:08:42 -08001290 mConstraintFlags = (mConstraintFlags&~CONSTRAINT_FLAG_DEVICE_IDLE)
1291 | (requiresDeviceIdle ? CONSTRAINT_FLAG_DEVICE_IDLE : 0);
Matthew Williams6e31c5c2014-04-11 15:49:16 -07001292 return this;
1293 }
1294
1295 /**
Dianne Hackborn532ea262017-03-17 17:50:55 -07001296 * Specify that to run this job, the device's available storage must not be low.
1297 * This defaults to false. If true, the job will only run when the device is not
1298 * in a low storage state, which is generally the point where the user is given a
1299 * "low storage" warning.
1300 * @param storageNotLow Whether or not the device's available storage must not be low.
Jeff Sharkey8474ca02018-03-26 19:10:02 -06001301 * @see JobInfo#isRequireStorageNotLow()
Dianne Hackborn532ea262017-03-17 17:50:55 -07001302 */
1303 public Builder setRequiresStorageNotLow(boolean storageNotLow) {
1304 mConstraintFlags = (mConstraintFlags&~CONSTRAINT_FLAG_STORAGE_NOT_LOW)
1305 | (storageNotLow ? CONSTRAINT_FLAG_STORAGE_NOT_LOW : 0);
1306 return this;
1307 }
1308
1309 /**
Dianne Hackborn1a30bd92016-01-11 11:05:00 -08001310 * Add a new content: URI that will be monitored with a
1311 * {@link android.database.ContentObserver}, and will cause the job to execute if changed.
1312 * If you have any trigger content URIs associated with a job, it will not execute until
1313 * there has been a change report for one or more of them.
Dianne Hackborn532ea262017-03-17 17:50:55 -07001314 *
Dianne Hackborn1a30bd92016-01-11 11:05:00 -08001315 * <p>Note that trigger URIs can not be used in combination with
1316 * {@link #setPeriodic(long)} or {@link #setPersisted(boolean)}. To continually monitor
1317 * for content changes, you need to schedule a new JobInfo observing the same URIs
Dianne Hackborn532ea262017-03-17 17:50:55 -07001318 * before you finish execution of the JobService handling the most recent changes.
1319 * Following this pattern will ensure you do not lost any content changes: while your
1320 * job is running, the system will continue monitoring for content changes, and propagate
1321 * any it sees over to the next job you schedule.</p>
1322 *
1323 * <p>Because setting this property is not compatible with periodic or
Dianne Hackborn46499a52016-03-09 17:57:48 -08001324 * persisted jobs, doing so will throw an {@link java.lang.IllegalArgumentException} when
1325 * {@link android.app.job.JobInfo.Builder#build()} is called.</p>
Dianne Hackbornc43a7f82016-06-01 10:48:43 -07001326 *
1327 * <p>The following example shows how this feature can be used to monitor for changes
1328 * in the photos on a device.</p>
1329 *
1330 * {@sample development/samples/ApiDemos/src/com/example/android/apis/content/PhotosContentJob.java
1331 * job}
1332 *
Dianne Hackborn1a30bd92016-01-11 11:05:00 -08001333 * @param uri The content: URI to monitor.
Jeff Sharkey8474ca02018-03-26 19:10:02 -06001334 * @see JobInfo#getTriggerContentUris()
Dianne Hackborn1a30bd92016-01-11 11:05:00 -08001335 */
1336 public Builder addTriggerContentUri(@NonNull TriggerContentUri uri) {
1337 if (mTriggerContentUris == null) {
1338 mTriggerContentUris = new ArrayList<>();
1339 }
1340 mTriggerContentUris.add(uri);
1341 return this;
1342 }
1343
1344 /**
Dianne Hackborn8db0fc12016-04-12 13:48:25 -07001345 * Set the delay (in milliseconds) from when a content change is detected until
1346 * the job is scheduled. If there are more changes during that time, the delay
1347 * will be reset to start at the time of the most recent change.
1348 * @param durationMs Delay after most recent content change, in milliseconds.
Jeff Sharkey8474ca02018-03-26 19:10:02 -06001349 * @see JobInfo#getTriggerContentUpdateDelay()
Dianne Hackborn8db0fc12016-04-12 13:48:25 -07001350 */
1351 public Builder setTriggerContentUpdateDelay(long durationMs) {
1352 mTriggerContentUpdateDelay = durationMs;
1353 return this;
1354 }
1355
1356 /**
1357 * Set the maximum total delay (in milliseconds) that is allowed from the first
1358 * time a content change is detected until the job is scheduled.
1359 * @param durationMs Delay after initial content change, in milliseconds.
Jeff Sharkey8474ca02018-03-26 19:10:02 -06001360 * @see JobInfo#getTriggerContentMaxDelay()
Dianne Hackborn8db0fc12016-04-12 13:48:25 -07001361 */
1362 public Builder setTriggerContentMaxDelay(long durationMs) {
1363 mTriggerContentMaxDelay = durationMs;
1364 return this;
1365 }
1366
1367 /**
Christopher Tate7060b042014-06-09 19:50:00 -07001368 * Specify that this job should recur with the provided interval, not more than once per
1369 * period. You have no control over when within this interval this job will be executed,
Matthew Williams6e31c5c2014-04-11 15:49:16 -07001370 * only the guarantee that it will be executed at most once within this interval.
Matthew Williams6e31c5c2014-04-11 15:49:16 -07001371 * Setting this function on the builder with {@link #setMinimumLatency(long)} or
1372 * {@link #setOverrideDeadline(long)} will result in an error.
Christopher Tate7060b042014-06-09 19:50:00 -07001373 * @param intervalMillis Millisecond interval for which this job will repeat.
Jeff Sharkey8474ca02018-03-26 19:10:02 -06001374 * @see JobInfo#getIntervalMillis()
1375 * @see JobInfo#getFlexMillis()
Matthew Williams6e31c5c2014-04-11 15:49:16 -07001376 */
1377 public Builder setPeriodic(long intervalMillis) {
Shreyas Basarge89ee6182015-12-17 15:16:36 +00001378 return setPeriodic(intervalMillis, intervalMillis);
1379 }
1380
1381 /**
1382 * Specify that this job should recur with the provided interval and flex. The job can
1383 * execute at any time in a window of flex length at the end of the period.
Shreyas Basargee96c3b72016-01-29 19:25:51 +00001384 * @param intervalMillis Millisecond interval for which this job will repeat. A minimum
Christopher Tatea9b4f3f2016-05-18 13:57:37 -07001385 * value of {@link #getMinPeriodMillis()} is enforced.
Shreyas Basarge89ee6182015-12-17 15:16:36 +00001386 * @param flexMillis Millisecond flex for this job. Flex is clamped to be at least
Christopher Tatea9b4f3f2016-05-18 13:57:37 -07001387 * {@link #getMinFlexMillis()} or 5 percent of the period, whichever is
Shreyas Basarge89ee6182015-12-17 15:16:36 +00001388 * higher.
Jeff Sharkey8474ca02018-03-26 19:10:02 -06001389 * @see JobInfo#getIntervalMillis()
1390 * @see JobInfo#getFlexMillis()
Shreyas Basarge89ee6182015-12-17 15:16:36 +00001391 */
1392 public Builder setPeriodic(long intervalMillis, long flexMillis) {
Jeff Sharkeyd0fff2e2017-11-07 16:55:06 -07001393 final long minPeriod = getMinPeriodMillis();
1394 if (intervalMillis < minPeriod) {
1395 Log.w(TAG, "Requested interval " + formatDuration(intervalMillis) + " for job "
1396 + mJobId + " is too small; raising to " + formatDuration(minPeriod));
1397 intervalMillis = minPeriod;
1398 }
1399
1400 final long percentClamp = 5 * intervalMillis / 100;
1401 final long minFlex = Math.max(percentClamp, getMinFlexMillis());
1402 if (flexMillis < minFlex) {
1403 Log.w(TAG, "Requested flex " + formatDuration(flexMillis) + " for job " + mJobId
1404 + " is too small; raising to " + formatDuration(minFlex));
1405 flexMillis = minFlex;
1406 }
1407
Matthew Williams6e31c5c2014-04-11 15:49:16 -07001408 mIsPeriodic = true;
1409 mIntervalMillis = intervalMillis;
Shreyas Basarge89ee6182015-12-17 15:16:36 +00001410 mFlexMillis = flexMillis;
Matthew Williams9b9244b62014-05-14 11:06:04 -07001411 mHasEarlyConstraint = mHasLateConstraint = true;
Matthew Williams6e31c5c2014-04-11 15:49:16 -07001412 return this;
1413 }
1414
1415 /**
Christopher Tate7060b042014-06-09 19:50:00 -07001416 * Specify that this job should be delayed by the provided amount of time.
1417 * Because it doesn't make sense setting this property on a periodic job, doing so will
Matthew Williams6e31c5c2014-04-11 15:49:16 -07001418 * throw an {@link java.lang.IllegalArgumentException} when
Christopher Tate7060b042014-06-09 19:50:00 -07001419 * {@link android.app.job.JobInfo.Builder#build()} is called.
1420 * @param minLatencyMillis Milliseconds before which this job will not be considered for
Matthew Williams6e31c5c2014-04-11 15:49:16 -07001421 * execution.
Jeff Sharkey8474ca02018-03-26 19:10:02 -06001422 * @see JobInfo#getMinLatencyMillis()
Matthew Williams6e31c5c2014-04-11 15:49:16 -07001423 */
1424 public Builder setMinimumLatency(long minLatencyMillis) {
1425 mMinLatencyMillis = minLatencyMillis;
Matthew Williams9b9244b62014-05-14 11:06:04 -07001426 mHasEarlyConstraint = true;
Matthew Williams6e31c5c2014-04-11 15:49:16 -07001427 return this;
1428 }
1429
1430 /**
Christopher Tate7060b042014-06-09 19:50:00 -07001431 * Set deadline which is the maximum scheduling latency. The job will be run by this
Matthew Williams6e31c5c2014-04-11 15:49:16 -07001432 * deadline even if other requirements are not met. Because it doesn't make sense setting
Christopher Tate7060b042014-06-09 19:50:00 -07001433 * this property on a periodic job, doing so will throw an
Matthew Williams6e31c5c2014-04-11 15:49:16 -07001434 * {@link java.lang.IllegalArgumentException} when
Christopher Tate7060b042014-06-09 19:50:00 -07001435 * {@link android.app.job.JobInfo.Builder#build()} is called.
Jeff Sharkey8474ca02018-03-26 19:10:02 -06001436 * @see JobInfo#getMaxExecutionDelayMillis()
Matthew Williams6e31c5c2014-04-11 15:49:16 -07001437 */
1438 public Builder setOverrideDeadline(long maxExecutionDelayMillis) {
1439 mMaxExecutionDelayMillis = maxExecutionDelayMillis;
Matthew Williams9b9244b62014-05-14 11:06:04 -07001440 mHasLateConstraint = true;
Matthew Williams6e31c5c2014-04-11 15:49:16 -07001441 return this;
1442 }
1443
1444 /**
1445 * Set up the back-off/retry policy.
Matthew Williamsd1c06752014-08-22 14:15:28 -07001446 * This defaults to some respectable values: {30 seconds, Exponential}. We cap back-off at
1447 * 5hrs.
Christopher Tate7060b042014-06-09 19:50:00 -07001448 * Note that trying to set a backoff criteria for a job with
Matthew Williams6e31c5c2014-04-11 15:49:16 -07001449 * {@link #setRequiresDeviceIdle(boolean)} will throw an exception when you call build().
Christopher Tate7060b042014-06-09 19:50:00 -07001450 * This is because back-off typically does not make sense for these types of jobs. See
1451 * {@link android.app.job.JobService#jobFinished(android.app.job.JobParameters, boolean)}
1452 * for more description of the return value for the case of a job executing while in idle
Matthew Williams6e31c5c2014-04-11 15:49:16 -07001453 * mode.
Christopher Tate7060b042014-06-09 19:50:00 -07001454 * @param initialBackoffMillis Millisecond time interval to wait initially when job has
Matthew Williams6e31c5c2014-04-11 15:49:16 -07001455 * failed.
Jeff Sharkey8474ca02018-03-26 19:10:02 -06001456 * @see JobInfo#getInitialBackoffMillis()
1457 * @see JobInfo#getBackoffPolicy()
Matthew Williams6e31c5c2014-04-11 15:49:16 -07001458 */
Jeff Sharkey30e06bb2017-04-24 11:18:03 -06001459 public Builder setBackoffCriteria(long initialBackoffMillis,
1460 @BackoffPolicy int backoffPolicy) {
Jeff Sharkeyd0fff2e2017-11-07 16:55:06 -07001461 final long minBackoff = getMinBackoffMillis();
1462 if (initialBackoffMillis < minBackoff) {
1463 Log.w(TAG, "Requested backoff " + formatDuration(initialBackoffMillis) + " for job "
1464 + mJobId + " is too small; raising to " + formatDuration(minBackoff));
1465 initialBackoffMillis = minBackoff;
1466 }
1467
Matthew Williams6e31c5c2014-04-11 15:49:16 -07001468 mBackoffPolicySet = true;
1469 mInitialBackoffMillis = initialBackoffMillis;
1470 mBackoffPolicy = backoffPolicy;
1471 return this;
1472 }
1473
1474 /**
Suprabh Shukla106203b2017-11-02 21:23:44 -07001475 * Setting this to true indicates that this job is important while the scheduling app
1476 * is in the foreground or on the temporary whitelist for background restrictions.
1477 * This means that the system will relax doze restrictions on this job during this time.
1478 *
1479 * Apps should use this flag only for short jobs that are essential for the app to function
1480 * properly in the foreground.
1481 *
1482 * Note that once the scheduling app is no longer whitelisted from background restrictions
1483 * and in the background, or the job failed due to unsatisfied constraints,
1484 * this job should be expected to behave like other jobs without this flag.
1485 *
1486 * @param importantWhileForeground whether to relax doze restrictions for this job when the
1487 * app is in the foreground. False by default.
Jeff Sharkey8474ca02018-03-26 19:10:02 -06001488 * @see JobInfo#isImportantWhileForeground()
Suprabh Shukla106203b2017-11-02 21:23:44 -07001489 */
1490 public Builder setImportantWhileForeground(boolean importantWhileForeground) {
1491 if (importantWhileForeground) {
1492 mFlags |= FLAG_IMPORTANT_WHILE_FOREGROUND;
1493 } else {
1494 mFlags &= (~FLAG_IMPORTANT_WHILE_FOREGROUND);
1495 }
1496 return this;
1497 }
1498
1499 /**
Jeff Sharkey8474ca02018-03-26 19:10:02 -06001500 * @removed
1501 * @deprecated replaced with {@link #setPrefetch(boolean)}
1502 */
1503 @Deprecated
1504 public Builder setIsPrefetch(boolean isPrefetch) {
1505 return setPrefetch(isPrefetch);
1506 }
1507
1508 /**
Jeff Sharkey9252b342018-01-19 07:58:35 +09001509 * Setting this to true indicates that this job is designed to prefetch
1510 * content that will make a material improvement to the experience of
1511 * the specific user of this device. For example, fetching top headlines
1512 * of interest to the current user.
1513 * <p>
1514 * The system may use this signal to relax the network constraints you
1515 * originally requested, such as allowing a
1516 * {@link JobInfo#NETWORK_TYPE_UNMETERED} job to run over a metered
1517 * network when there is a surplus of metered data available. The system
1518 * may also use this signal in combination with end user usage patterns
1519 * to ensure data is prefetched before the user launches your app.
Jeff Sharkey8474ca02018-03-26 19:10:02 -06001520 * @see JobInfo#isPrefetch()
Jeff Sharkey9252b342018-01-19 07:58:35 +09001521 */
Jeff Sharkey8474ca02018-03-26 19:10:02 -06001522 public Builder setPrefetch(boolean prefetch) {
1523 if (prefetch) {
1524 mFlags |= FLAG_PREFETCH;
Jeff Sharkey9252b342018-01-19 07:58:35 +09001525 } else {
Jeff Sharkey8474ca02018-03-26 19:10:02 -06001526 mFlags &= (~FLAG_PREFETCH);
Jeff Sharkey9252b342018-01-19 07:58:35 +09001527 }
1528 return this;
1529 }
1530
1531 /**
Jeff Sharkey30e06bb2017-04-24 11:18:03 -06001532 * Set whether or not to persist this job across device reboots.
1533 *
1534 * @param isPersisted True to indicate that the job will be written to
1535 * disk and loaded at boot.
Jeff Sharkey8474ca02018-03-26 19:10:02 -06001536 * @see JobInfo#isPersisted()
Matthew Williams900c67f2014-07-09 12:46:53 -07001537 */
Jeff Sharkey30e06bb2017-04-24 11:18:03 -06001538 @RequiresPermission(android.Manifest.permission.RECEIVE_BOOT_COMPLETED)
Matthew Williamsd1c06752014-08-22 14:15:28 -07001539 public Builder setPersisted(boolean isPersisted) {
Matthew Williams900c67f2014-07-09 12:46:53 -07001540 mIsPersisted = isPersisted;
1541 return this;
1542 }
1543
1544 /**
Christopher Tate7060b042014-06-09 19:50:00 -07001545 * @return The job object to hand to the JobScheduler. This object is immutable.
Matthew Williams6e31c5c2014-04-11 15:49:16 -07001546 */
Christopher Tate7060b042014-06-09 19:50:00 -07001547 public JobInfo build() {
Jeff Sharkeycaa3f8d2017-10-25 16:12:00 -06001548 // Check that network estimates require network type
Jeff Sharkey8474ca02018-03-26 19:10:02 -06001549 if ((mNetworkDownloadBytes > 0 || mNetworkUploadBytes > 0) && mNetworkRequest == null) {
Jeff Sharkeycaa3f8d2017-10-25 16:12:00 -06001550 throw new IllegalArgumentException(
1551 "Can't provide estimated network usage without requiring a network");
1552 }
Jeff Sharkeyd0fff2e2017-11-07 16:55:06 -07001553 // We can't serialize network specifiers
1554 if (mIsPersisted && mNetworkRequest != null
1555 && mNetworkRequest.networkCapabilities.getNetworkSpecifier() != null) {
1556 throw new IllegalArgumentException(
1557 "Network specifiers aren't supported for persistent jobs");
1558 }
Christopher Tate7060b042014-06-09 19:50:00 -07001559 // Check that a deadline was not set on a periodic job.
Dianne Hackborna47223f2017-03-30 13:49:13 -07001560 if (mIsPeriodic) {
1561 if (mMaxExecutionDelayMillis != 0L) {
1562 throw new IllegalArgumentException("Can't call setOverrideDeadline() on a " +
1563 "periodic job.");
1564 }
1565 if (mMinLatencyMillis != 0L) {
1566 throw new IllegalArgumentException("Can't call setMinimumLatency() on a " +
1567 "periodic job");
1568 }
1569 if (mTriggerContentUris != null) {
1570 throw new IllegalArgumentException("Can't call addTriggerContentUri() on a " +
1571 "periodic job");
1572 }
Matthew Williams6e31c5c2014-04-11 15:49:16 -07001573 }
Dianne Hackborna47223f2017-03-30 13:49:13 -07001574 if (mIsPersisted) {
1575 if (mTriggerContentUris != null) {
1576 throw new IllegalArgumentException("Can't call addTriggerContentUri() on a " +
1577 "persisted job");
1578 }
1579 if (!mTransientExtras.isEmpty()) {
1580 throw new IllegalArgumentException("Can't call setTransientExtras() on a " +
1581 "persisted job");
1582 }
1583 if (mClipData != null) {
1584 throw new IllegalArgumentException("Can't call setClipData() on a " +
1585 "persisted job");
1586 }
Dianne Hackbornba604732016-02-10 17:05:10 -08001587 }
Suprabh Shukla106203b2017-11-02 21:23:44 -07001588 if ((mFlags & FLAG_IMPORTANT_WHILE_FOREGROUND) != 0 && mHasEarlyConstraint) {
1589 throw new IllegalArgumentException("An important while foreground job cannot "
1590 + "have a time delay");
1591 }
Dianne Hackborna06ec6a2017-02-13 10:08:42 -08001592 if (mBackoffPolicySet && (mConstraintFlags & CONSTRAINT_FLAG_DEVICE_IDLE) != 0) {
Christopher Tate7060b042014-06-09 19:50:00 -07001593 throw new IllegalArgumentException("An idle mode job will not respect any" +
Matthew Williams6e31c5c2014-04-11 15:49:16 -07001594 " back-off policy, so calling setBackoffCriteria with" +
1595 " setRequiresDeviceIdle is an error.");
1596 }
Jeff Sharkeyd0fff2e2017-11-07 16:55:06 -07001597 return new JobInfo(this);
Matthew Williams6e31c5c2014-04-11 15:49:16 -07001598 }
1599 }
Makoto Onukiec8b14d2018-12-05 13:22:24 -08001600
1601 /**
1602 * Convert a priority integer into a human readable string for debugging.
1603 * @hide
1604 */
1605 public static String getPriorityString(int priority) {
1606 switch (priority) {
1607 case PRIORITY_DEFAULT:
1608 return PRIORITY_DEFAULT + " [DEFAULT]";
1609 case PRIORITY_SYNC_EXPEDITED:
1610 return PRIORITY_SYNC_EXPEDITED + " [SYNC_EXPEDITED]";
1611 case PRIORITY_SYNC_INITIALIZATION:
1612 return PRIORITY_SYNC_INITIALIZATION + " [SYNC_INITIALIZATION]";
1613 case PRIORITY_BOUND_FOREGROUND_SERVICE:
1614 return PRIORITY_BOUND_FOREGROUND_SERVICE + " [BFGS_APP]";
1615 case PRIORITY_FOREGROUND_SERVICE:
1616 return PRIORITY_FOREGROUND_SERVICE + " [FGS_APP]";
1617 case PRIORITY_TOP_APP:
1618 return PRIORITY_TOP_APP + " [TOP_APP]";
1619
1620 // PRIORITY_ADJ_* are adjustments and not used as real priorities.
1621 // No need to convert to strings.
1622 }
1623 return priority + " [UNKNOWN]";
1624 }
Matthew Williams6e31c5c2014-04-11 15:49:16 -07001625}