blob: e6fbc39b6dc693bafd60a1fd771c78ee7c967b86 [file] [log] [blame]
Christopher Tate7060b042014-06-09 19:50:00 -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
17package com.android.server.job.controllers;
18
Shreyas Basarge968ac752016-01-11 23:09:26 +000019import android.app.AppGlobals;
Christopher Tate7060b042014-06-09 19:50:00 -070020import android.app.job.JobInfo;
21import android.content.ComponentName;
Dianne Hackborn1a30bd92016-01-11 11:05:00 -080022import android.net.Uri;
Christopher Tate7060b042014-06-09 19:50:00 -070023import android.os.PersistableBundle;
Shreyas Basarge968ac752016-01-11 23:09:26 +000024import android.os.RemoteException;
Christopher Tate7060b042014-06-09 19:50:00 -070025import android.os.SystemClock;
26import android.os.UserHandle;
Matthew Williams9ae3dbe2014-08-21 13:47:47 -070027import android.text.format.DateUtils;
Dianne Hackborn1a30bd92016-01-11 11:05:00 -080028import android.util.ArraySet;
29import android.util.TimeUtils;
Christopher Tate7060b042014-06-09 19:50:00 -070030
31import java.io.PrintWriter;
32import java.util.concurrent.atomic.AtomicBoolean;
33
34/**
35 * Uniquely identifies a job internally.
36 * Created from the public {@link android.app.job.JobInfo} object when it lands on the scheduler.
37 * Contains current state of the requirements of the job, as well as a function to evaluate
38 * whether it's ready to run.
39 * This object is shared among the various controllers - hence why the different fields are atomic.
40 * This isn't strictly necessary because each controller is only interested in a specific field,
41 * and the receivers that are listening for global state change will all run on the main looper,
42 * but we don't enforce that so this is safer.
43 * @hide
44 */
Dianne Hackbornb0001f62016-02-16 10:30:33 -080045public final class JobStatus {
Christopher Tate7060b042014-06-09 19:50:00 -070046 public static final long NO_LATEST_RUNTIME = Long.MAX_VALUE;
47 public static final long NO_EARLIEST_RUNTIME = 0L;
48
Dianne Hackbornb0001f62016-02-16 10:30:33 -080049 static final int CONSTRAINT_CHARGING = 1<<0;
50 static final int CONSTRAINT_TIMING_DELAY = 1<<1;
51 static final int CONSTRAINT_DEADLINE = 1<<2;
52 static final int CONSTRAINT_IDLE = 1<<3;
53 static final int CONSTRAINT_UNMETERED = 1<<4;
54 static final int CONSTRAINT_CONNECTIVITY = 1<<5;
55 static final int CONSTRAINT_APP_NOT_IDLE = 1<<6;
56 static final int CONSTRAINT_CONTENT_TRIGGER = 1<<7;
57
Christopher Tate7060b042014-06-09 19:50:00 -070058 final JobInfo job;
Matthew Williams9ae3dbe2014-08-21 13:47:47 -070059 /** Uid of the package requesting this job. */
Shreyas Basarge8e64e2e2016-02-12 15:49:31 +000060 final int callingUid;
Dianne Hackborn1085ff62016-02-23 17:04:58 -080061 final String batteryName;
Christopher Tate7060b042014-06-09 19:50:00 -070062
Shreyas Basarge8e64e2e2016-02-12 15:49:31 +000063 final String sourcePackageName;
64 final int sourceUserId;
65 final int sourceUid;
Dianne Hackborn1085ff62016-02-23 17:04:58 -080066 final String sourceTag;
67
68 final String tag;
Shreyas Basarge968ac752016-01-11 23:09:26 +000069
Dianne Hackbornb0001f62016-02-16 10:30:33 -080070 /**
71 * Earliest point in the future at which this job will be eligible to run. A value of 0
72 * indicates there is no delay constraint. See {@link #hasTimingDelayConstraint()}.
73 */
74 private final long earliestRunTimeElapsedMillis;
75 /**
76 * Latest point in the future at which this job must be run. A value of {@link Long#MAX_VALUE}
77 * indicates there is no deadline constraint. See {@link #hasDeadlineConstraint()}.
78 */
79 private final long latestRunTimeElapsedMillis;
80
81 /** How many times this job has failed, used to compute back-off. */
82 private final int numFailures;
83
Christopher Tate7060b042014-06-09 19:50:00 -070084 // Constraints.
Dianne Hackbornb0001f62016-02-16 10:30:33 -080085 final int requiredConstraints;
86 int satisfiedConstraints = 0;
Dianne Hackborn1a30bd92016-01-11 11:05:00 -080087
88 // These are filled in by controllers when preparing for execution.
89 public ArraySet<Uri> changedUris;
90 public ArraySet<String> changedAuthorities;
91
Dianne Hackborn1085ff62016-02-23 17:04:58 -080092 public int lastEvaluatedPriority;
93
Dianne Hackborn1a30bd92016-01-11 11:05:00 -080094 /**
95 * For use only by ContentObserverController: state it is maintaining about content URIs
96 * being observed.
97 */
98 ContentObserverController.JobInstance contentObserverJobInstance;
Christopher Tate7060b042014-06-09 19:50:00 -070099
Christopher Tate7060b042014-06-09 19:50:00 -0700100 /** Provide a handle to the service that this job will be run on. */
101 public int getServiceToken() {
Shreyas Basarge8e64e2e2016-02-12 15:49:31 +0000102 return callingUid;
Christopher Tate7060b042014-06-09 19:50:00 -0700103 }
104
Dianne Hackbornb0001f62016-02-16 10:30:33 -0800105 private JobStatus(JobInfo job, int callingUid, String sourcePackageName,
Dianne Hackborn1085ff62016-02-23 17:04:58 -0800106 int sourceUserId, String tag, int numFailures, long earliestRunTimeElapsedMillis,
Dianne Hackbornb0001f62016-02-16 10:30:33 -0800107 long latestRunTimeElapsedMillis) {
Christopher Tate7060b042014-06-09 19:50:00 -0700108 this.job = job;
Shreyas Basarge8e64e2e2016-02-12 15:49:31 +0000109 this.callingUid = callingUid;
Shreyas Basarge8e64e2e2016-02-12 15:49:31 +0000110
111 int tempSourceUid = -1;
112 if (sourceUserId != -1 && sourcePackageName != null) {
113 try {
114 tempSourceUid = AppGlobals.getPackageManager().getPackageUid(sourcePackageName, 0,
115 sourceUserId);
116 } catch (RemoteException ex) {
117 // Can't happen, PackageManager runs in the same process.
118 }
119 }
120 if (tempSourceUid == -1) {
121 this.sourceUid = callingUid;
122 this.sourceUserId = UserHandle.getUserId(callingUid);
123 this.sourcePackageName = job.getService().getPackageName();
Dianne Hackborn1085ff62016-02-23 17:04:58 -0800124 this.sourceTag = null;
Shreyas Basarge8e64e2e2016-02-12 15:49:31 +0000125 } else {
126 this.sourceUid = tempSourceUid;
127 this.sourceUserId = sourceUserId;
128 this.sourcePackageName = sourcePackageName;
Dianne Hackborn1085ff62016-02-23 17:04:58 -0800129 this.sourceTag = tag;
Shreyas Basarge8e64e2e2016-02-12 15:49:31 +0000130 }
Dianne Hackbornb0001f62016-02-16 10:30:33 -0800131
Dianne Hackborn1085ff62016-02-23 17:04:58 -0800132 if (this.sourceTag != null) {
133 StringBuilder sb = new StringBuilder();
134 sb.append(job.getService().getPackageName());
135 sb.append('/');
136 sb.append(this.sourceTag);
137 this.batteryName = sb.toString();
138 } else {
139 this.batteryName = job.getService().flattenToShortString();
140 }
141 this.tag = "*job*/" + this.batteryName;
142
Dianne Hackbornb0001f62016-02-16 10:30:33 -0800143 this.earliestRunTimeElapsedMillis = earliestRunTimeElapsedMillis;
144 this.latestRunTimeElapsedMillis = latestRunTimeElapsedMillis;
145 this.numFailures = numFailures;
146
147 int requiredConstraints = 0;
148 if (job.getNetworkType() == JobInfo.NETWORK_TYPE_ANY) {
149 requiredConstraints |= CONSTRAINT_CONNECTIVITY;
150 }
151 if (job.getNetworkType() == JobInfo.NETWORK_TYPE_UNMETERED) {
152 requiredConstraints |= CONSTRAINT_UNMETERED;
153 }
154 if (job.isRequireCharging()) {
155 requiredConstraints |= CONSTRAINT_CHARGING;
156 }
157 if (earliestRunTimeElapsedMillis != NO_EARLIEST_RUNTIME) {
158 requiredConstraints |= CONSTRAINT_TIMING_DELAY;
159 }
160 if (latestRunTimeElapsedMillis != NO_LATEST_RUNTIME) {
161 requiredConstraints |= CONSTRAINT_DEADLINE;
162 }
163 if (job.isRequireDeviceIdle()) {
164 requiredConstraints |= CONSTRAINT_IDLE;
165 }
166 if (job.getTriggerContentUris() != null) {
167 requiredConstraints |= CONSTRAINT_CONTENT_TRIGGER;
168 }
169 this.requiredConstraints = requiredConstraints;
Christopher Tate7060b042014-06-09 19:50:00 -0700170 }
171
Matthew Williams0cc76542015-10-16 21:04:51 -0700172 /** Copy constructor. */
173 public JobStatus(JobStatus jobStatus) {
Dianne Hackbornb0001f62016-02-16 10:30:33 -0800174 this(jobStatus.getJob(), jobStatus.getUid(),
Dianne Hackborn33d31c52016-02-16 10:30:33 -0800175 jobStatus.getSourcePackageName(), jobStatus.getSourceUserId(),
Dianne Hackborn1085ff62016-02-23 17:04:58 -0800176 jobStatus.getSourceTag(), jobStatus.getNumFailures(),
177 jobStatus.getEarliestRunTime(), jobStatus.getLatestRunTimeElapsed());
Christopher Tate7060b042014-06-09 19:50:00 -0700178 }
179
180 /**
181 * Create a new JobStatus that was loaded from disk. We ignore the provided
182 * {@link android.app.job.JobInfo} time criteria because we can load a persisted periodic job
183 * from the {@link com.android.server.job.JobStore} and still want to respect its
184 * wallclock runtime rather than resetting it on every boot.
185 * We consider a freshly loaded job to no longer be in back-off.
186 */
Dianne Hackborn1085ff62016-02-23 17:04:58 -0800187 public JobStatus(JobInfo job, int callingUid, String sourcePackageName, int sourceUserId,
188 String sourceTag, long earliestRunTimeElapsedMillis, long latestRunTimeElapsedMillis) {
189 this(job, callingUid, sourcePackageName, sourceUserId, sourceTag, 0,
190 earliestRunTimeElapsedMillis, latestRunTimeElapsedMillis);
Christopher Tate7060b042014-06-09 19:50:00 -0700191 }
192
193 /** Create a new job to be rescheduled with the provided parameters. */
194 public JobStatus(JobStatus rescheduling, long newEarliestRuntimeElapsedMillis,
195 long newLatestRuntimeElapsedMillis, int backoffAttempt) {
Dianne Hackbornb0001f62016-02-16 10:30:33 -0800196 this(rescheduling.job, rescheduling.getUid(),
Dianne Hackborn1085ff62016-02-23 17:04:58 -0800197 rescheduling.getSourcePackageName(), rescheduling.getSourceUserId(),
198 rescheduling.getSourceTag(), backoffAttempt, newEarliestRuntimeElapsedMillis,
Dianne Hackbornb0001f62016-02-16 10:30:33 -0800199 newLatestRuntimeElapsedMillis);
200 }
Christopher Tate7060b042014-06-09 19:50:00 -0700201
Dianne Hackbornb0001f62016-02-16 10:30:33 -0800202 /**
203 * Create a newly scheduled job.
204 * @param callingUid Uid of the package that scheduled this job.
205 * @param sourcePackageName Package name on whose behalf this job is scheduled. Null indicates
206 * the calling package is the source.
207 * @param sourceUserId User id for whom this job is scheduled. -1 indicates this is same as the
208 */
209 public static JobStatus createFromJobInfo(JobInfo job, int callingUid, String sourcePackageName,
Dianne Hackborn1085ff62016-02-23 17:04:58 -0800210 int sourceUserId, String tag) {
Dianne Hackbornb0001f62016-02-16 10:30:33 -0800211 final long elapsedNow = SystemClock.elapsedRealtime();
212 final long earliestRunTimeElapsedMillis, latestRunTimeElapsedMillis;
213 if (job.isPeriodic()) {
214 latestRunTimeElapsedMillis = elapsedNow + job.getIntervalMillis();
215 earliestRunTimeElapsedMillis = latestRunTimeElapsedMillis - job.getFlexMillis();
216 } else {
217 earliestRunTimeElapsedMillis = job.hasEarlyConstraint() ?
218 elapsedNow + job.getMinLatencyMillis() : NO_EARLIEST_RUNTIME;
219 latestRunTimeElapsedMillis = job.hasLateConstraint() ?
220 elapsedNow + job.getMaxExecutionDelayMillis() : NO_LATEST_RUNTIME;
221 }
Dianne Hackborn1085ff62016-02-23 17:04:58 -0800222 return new JobStatus(job, callingUid, sourcePackageName, sourceUserId, tag, 0,
Dianne Hackbornb0001f62016-02-16 10:30:33 -0800223 earliestRunTimeElapsedMillis, latestRunTimeElapsedMillis);
Christopher Tate7060b042014-06-09 19:50:00 -0700224 }
225
226 public JobInfo getJob() {
227 return job;
228 }
229
230 public int getJobId() {
231 return job.getId();
232 }
233
234 public int getNumFailures() {
235 return numFailures;
236 }
237
238 public ComponentName getServiceComponent() {
239 return job.getService();
240 }
241
Shreyas Basarge968ac752016-01-11 23:09:26 +0000242 public String getSourcePackageName() {
Shreyas Basarge8e64e2e2016-02-12 15:49:31 +0000243 return sourcePackageName;
Shreyas Basarge968ac752016-01-11 23:09:26 +0000244 }
245
246 public int getSourceUid() {
247 return sourceUid;
248 }
249
250 public int getSourceUserId() {
Shreyas Basarge968ac752016-01-11 23:09:26 +0000251 return sourceUserId;
252 }
253
Christopher Tate7060b042014-06-09 19:50:00 -0700254 public int getUserId() {
Shreyas Basarge8e64e2e2016-02-12 15:49:31 +0000255 return UserHandle.getUserId(callingUid);
Christopher Tate7060b042014-06-09 19:50:00 -0700256 }
257
Dianne Hackborn1085ff62016-02-23 17:04:58 -0800258 public String getSourceTag() {
259 return sourceTag;
260 }
261
Christopher Tate7060b042014-06-09 19:50:00 -0700262 public int getUid() {
Shreyas Basarge8e64e2e2016-02-12 15:49:31 +0000263 return callingUid;
Christopher Tate7060b042014-06-09 19:50:00 -0700264 }
265
Dianne Hackborn1085ff62016-02-23 17:04:58 -0800266 public String getBatteryName() {
267 return batteryName;
Dianne Hackbornfdb19562014-07-11 16:03:36 -0700268 }
269
270 public String getTag() {
271 return tag;
272 }
273
Christopher Tate7060b042014-06-09 19:50:00 -0700274 public PersistableBundle getExtras() {
275 return job.getExtras();
276 }
Shreyas Basarge968ac752016-01-11 23:09:26 +0000277
Shreyas Basarge5db09082016-01-07 13:38:29 +0000278 public int getPriority() {
279 return job.getPriority();
280 }
Christopher Tate7060b042014-06-09 19:50:00 -0700281
282 public boolean hasConnectivityConstraint() {
Dianne Hackbornb0001f62016-02-16 10:30:33 -0800283 return (requiredConstraints&CONSTRAINT_CONNECTIVITY) != 0;
Christopher Tate7060b042014-06-09 19:50:00 -0700284 }
285
286 public boolean hasUnmeteredConstraint() {
Dianne Hackbornb0001f62016-02-16 10:30:33 -0800287 return (requiredConstraints&CONSTRAINT_UNMETERED) != 0;
Christopher Tate7060b042014-06-09 19:50:00 -0700288 }
289
290 public boolean hasChargingConstraint() {
Dianne Hackbornb0001f62016-02-16 10:30:33 -0800291 return (requiredConstraints&CONSTRAINT_CHARGING) != 0;
Christopher Tate7060b042014-06-09 19:50:00 -0700292 }
293
294 public boolean hasTimingDelayConstraint() {
Dianne Hackbornb0001f62016-02-16 10:30:33 -0800295 return (requiredConstraints&CONSTRAINT_TIMING_DELAY) != 0;
Christopher Tate7060b042014-06-09 19:50:00 -0700296 }
297
298 public boolean hasDeadlineConstraint() {
Dianne Hackbornb0001f62016-02-16 10:30:33 -0800299 return (requiredConstraints&CONSTRAINT_DEADLINE) != 0;
Christopher Tate7060b042014-06-09 19:50:00 -0700300 }
301
302 public boolean hasIdleConstraint() {
Dianne Hackbornb0001f62016-02-16 10:30:33 -0800303 return (requiredConstraints&CONSTRAINT_IDLE) != 0;
Christopher Tate7060b042014-06-09 19:50:00 -0700304 }
305
Dianne Hackborn1a30bd92016-01-11 11:05:00 -0800306 public boolean hasContentTriggerConstraint() {
Dianne Hackbornb0001f62016-02-16 10:30:33 -0800307 return (requiredConstraints&CONSTRAINT_CONTENT_TRIGGER) != 0;
Dianne Hackborn1a30bd92016-01-11 11:05:00 -0800308 }
309
Matthew Williams900c67f2014-07-09 12:46:53 -0700310 public boolean isPersisted() {
311 return job.isPersisted();
312 }
313
Christopher Tate7060b042014-06-09 19:50:00 -0700314 public long getEarliestRunTime() {
315 return earliestRunTimeElapsedMillis;
316 }
317
318 public long getLatestRunTimeElapsed() {
319 return latestRunTimeElapsedMillis;
320 }
321
Dianne Hackbornb0001f62016-02-16 10:30:33 -0800322 boolean setChargingConstraintSatisfied(boolean state) {
323 return setConstraintSatisfied(CONSTRAINT_CHARGING, state);
324 }
325
326 boolean setTimingDelayConstraintSatisfied(boolean state) {
327 return setConstraintSatisfied(CONSTRAINT_TIMING_DELAY, state);
328 }
329
330 boolean setDeadlineConstraintSatisfied(boolean state) {
331 return setConstraintSatisfied(CONSTRAINT_DEADLINE, state);
332 }
333
334 boolean setIdleConstraintSatisfied(boolean state) {
335 return setConstraintSatisfied(CONSTRAINT_IDLE, state);
336 }
337
338 boolean setUnmeteredConstraintSatisfied(boolean state) {
339 return setConstraintSatisfied(CONSTRAINT_UNMETERED, state);
340 }
341
342 boolean setConnectivityConstraintSatisfied(boolean state) {
343 return setConstraintSatisfied(CONSTRAINT_CONNECTIVITY, state);
344 }
345
346 boolean setAppNotIdleConstraintSatisfied(boolean state) {
347 return setConstraintSatisfied(CONSTRAINT_APP_NOT_IDLE, state);
348 }
349
350 boolean setContentTriggerConstraintSatisfied(boolean state) {
351 return setConstraintSatisfied(CONSTRAINT_CONTENT_TRIGGER, state);
352 }
353
354 boolean setConstraintSatisfied(int constraint, boolean state) {
355 boolean old = (satisfiedConstraints&constraint) != 0;
356 if (old == state) {
357 return false;
358 }
359 satisfiedConstraints = (satisfiedConstraints&~constraint) | (state ? constraint : 0);
360 return true;
361 }
362
Christopher Tate7060b042014-06-09 19:50:00 -0700363 /**
Matthew Williams03a4da62014-09-10 17:32:18 -0700364 * @return Whether or not this job is ready to run, based on its requirements. This is true if
365 * the constraints are satisfied <strong>or</strong> the deadline on the job has expired.
Christopher Tate7060b042014-06-09 19:50:00 -0700366 */
Dianne Hackborn33d31c52016-02-16 10:30:33 -0800367 public boolean isReady() {
Dianne Hackbornb0001f62016-02-16 10:30:33 -0800368 // Deadline constraint trumps other constraints (except for periodic jobs where deadline
369 // (is an implementation detail. A periodic job should only run if it's constraints are
370 // satisfied).
371 // AppNotIdle implicit constraint trumps all!
372 return (isConstraintsSatisfied()
373 || (!job.isPeriodic()
374 && hasDeadlineConstraint() && (satisfiedConstraints&CONSTRAINT_DEADLINE) != 0))
375 && (satisfiedConstraints&CONSTRAINT_APP_NOT_IDLE) != 0;
Matthew Williams03a4da62014-09-10 17:32:18 -0700376 }
377
Dianne Hackbornb0001f62016-02-16 10:30:33 -0800378 static final int CONSTRAINTS_OF_INTEREST =
379 CONSTRAINT_CHARGING | CONSTRAINT_TIMING_DELAY |
380 CONSTRAINT_CONNECTIVITY | CONSTRAINT_UNMETERED |
381 CONSTRAINT_IDLE | CONSTRAINT_CONTENT_TRIGGER;
382
Matthew Williams03a4da62014-09-10 17:32:18 -0700383 /**
384 * @return Whether the constraints set on this job are satisfied.
385 */
Dianne Hackborn33d31c52016-02-16 10:30:33 -0800386 public boolean isConstraintsSatisfied() {
Dianne Hackbornb0001f62016-02-16 10:30:33 -0800387 final int req = requiredConstraints & CONSTRAINTS_OF_INTEREST;
388 final int sat = satisfiedConstraints & CONSTRAINTS_OF_INTEREST;
389 return (sat & req) == req;
Christopher Tate7060b042014-06-09 19:50:00 -0700390 }
391
392 public boolean matches(int uid, int jobId) {
Shreyas Basarge8e64e2e2016-02-12 15:49:31 +0000393 return this.job.getId() == jobId && this.callingUid == uid;
Christopher Tate7060b042014-06-09 19:50:00 -0700394 }
395
396 @Override
397 public String toString() {
398 return String.valueOf(hashCode()).substring(0, 3) + ".."
Christopher Tate1b8b3aa2014-06-20 13:17:01 -0700399 + ":[" + job.getService()
400 + ",jId=" + job.getId()
Matthew Williams9ae3dbe2014-08-21 13:47:47 -0700401 + ",u" + getUserId()
402 + ",R=(" + formatRunTime(earliestRunTimeElapsedMillis, NO_EARLIEST_RUNTIME)
403 + "," + formatRunTime(latestRunTimeElapsedMillis, NO_LATEST_RUNTIME) + ")"
Matthew Williamsd1c06752014-08-22 14:15:28 -0700404 + ",N=" + job.getNetworkType() + ",C=" + job.isRequireCharging()
Dianne Hackborn1a30bd92016-01-11 11:05:00 -0800405 + ",I=" + job.isRequireDeviceIdle()
406 + ",U=" + (job.getTriggerContentUris() != null)
407 + ",F=" + numFailures + ",P=" + job.isPersisted()
Dianne Hackbornb0001f62016-02-16 10:30:33 -0800408 + ",ANI=" + ((satisfiedConstraints&CONSTRAINT_APP_NOT_IDLE) != 0)
Christopher Tate7060b042014-06-09 19:50:00 -0700409 + (isReady() ? "(READY)" : "")
410 + "]";
411 }
Matthew Williams9ae3dbe2014-08-21 13:47:47 -0700412
413 private String formatRunTime(long runtime, long defaultValue) {
414 if (runtime == defaultValue) {
415 return "none";
416 } else {
417 long elapsedNow = SystemClock.elapsedRealtime();
418 long nextRuntime = runtime - elapsedNow;
419 if (nextRuntime > 0) {
420 return DateUtils.formatElapsedTime(nextRuntime / 1000);
421 } else {
422 return "-" + DateUtils.formatElapsedTime(nextRuntime / -1000);
423 }
424 }
425 }
426
427 /**
428 * Convenience function to identify a job uniquely without pulling all the data that
429 * {@link #toString()} returns.
430 */
431 public String toShortString() {
Dianne Hackborn1a30bd92016-01-11 11:05:00 -0800432 StringBuilder sb = new StringBuilder();
433 sb.append(Integer.toHexString(System.identityHashCode(this)));
434 sb.append(" jId=");
435 sb.append(job.getId());
436 sb.append(" uid=");
Shreyas Basarge8e64e2e2016-02-12 15:49:31 +0000437 UserHandle.formatUid(sb, callingUid);
Dianne Hackborn1a30bd92016-01-11 11:05:00 -0800438 sb.append(' ');
439 sb.append(job.getService().flattenToShortString());
440 return sb.toString();
Matthew Williams9ae3dbe2014-08-21 13:47:47 -0700441 }
442
Dianne Hackbornb0001f62016-02-16 10:30:33 -0800443 void dumpConstraints(PrintWriter pw, int constraints) {
444 if ((constraints&CONSTRAINT_CHARGING) != 0) {
445 pw.print(" CHARGING");
446 }
447 if ((constraints&CONSTRAINT_TIMING_DELAY) != 0) {
448 pw.print(" TIMING_DELAY");
449 }
450 if ((constraints&CONSTRAINT_DEADLINE) != 0) {
451 pw.print(" DEADLINE");
452 }
453 if ((constraints&CONSTRAINT_IDLE) != 0) {
454 pw.print(" IDLE");
455 }
456 if ((constraints&CONSTRAINT_UNMETERED) != 0) {
457 pw.print(" UNMETERED");
458 }
459 if ((constraints&CONSTRAINT_CONNECTIVITY) != 0) {
460 pw.print(" CONNECTIVITY");
461 }
462 if ((constraints&CONSTRAINT_APP_NOT_IDLE) != 0) {
463 pw.print(" APP_NOT_IDLE");
464 }
465 if ((constraints&CONSTRAINT_CONTENT_TRIGGER) != 0) {
466 pw.print(" CONTENT_TRIGGER");
467 }
468 }
469
Christopher Tate7060b042014-06-09 19:50:00 -0700470 // Dumpsys infrastructure
471 public void dump(PrintWriter pw, String prefix) {
Shreyas Basarge8e64e2e2016-02-12 15:49:31 +0000472 pw.print(prefix); UserHandle.formatUid(pw, callingUid);
Dianne Hackborn1a30bd92016-01-11 11:05:00 -0800473 pw.print(" tag="); pw.println(tag);
Christopher Tatef973a7b2014-08-29 12:54:08 -0700474 pw.print(prefix);
Shreyas Basarged8bf6b92016-02-02 23:45:14 +0000475 pw.print("Source: uid="); UserHandle.formatUid(pw, getSourceUid());
476 pw.print(" user="); pw.print(getSourceUserId());
477 pw.print(" pkg="); pw.println(getSourcePackageName());
Dianne Hackborn1a30bd92016-01-11 11:05:00 -0800478 pw.print(prefix); pw.println("JobInfo:");
479 pw.print(prefix); pw.print(" Service: ");
480 pw.println(job.getService().flattenToShortString());
481 if (job.isPeriodic()) {
482 pw.print(prefix); pw.print(" PERIODIC: interval=");
483 TimeUtils.formatDuration(job.getIntervalMillis(), pw);
484 pw.print(" flex=");
485 TimeUtils.formatDuration(job.getFlexMillis(), pw);
486 pw.println();
487 }
488 if (job.isPersisted()) {
489 pw.print(prefix); pw.println(" PERSISTED");
490 }
491 if (job.getPriority() != 0) {
492 pw.print(prefix); pw.print(" Priority: ");
493 pw.println(job.getPriority());
494 }
495 pw.print(prefix); pw.print(" Requires: charging=");
496 pw.print(job.isRequireCharging());
497 pw.print(" deviceIdle=");
498 pw.println(job.isRequireDeviceIdle());
499 if (job.getTriggerContentUris() != null) {
500 pw.print(prefix); pw.println(" Trigger content URIs:");
501 for (int i=0; i<job.getTriggerContentUris().length; i++) {
502 JobInfo.TriggerContentUri trig = job.getTriggerContentUris()[i];
503 pw.print(prefix); pw.print(" ");
504 pw.print(Integer.toHexString(trig.getFlags()));
505 pw.print(' ' );
506 pw.println(trig.getUri());
507 }
508 }
509 if (job.getNetworkType() != JobInfo.NETWORK_TYPE_NONE) {
510 pw.print(prefix); pw.print(" Network type: ");
511 pw.println(job.getNetworkType());
512 }
513 if (job.getMinLatencyMillis() != 0) {
514 pw.print(prefix); pw.print(" Minimum latency: ");
515 TimeUtils.formatDuration(job.getMinLatencyMillis(), pw);
516 pw.println();
517 }
518 if (job.getMaxExecutionDelayMillis() != 0) {
519 pw.print(prefix); pw.print(" Max execution delay: ");
520 TimeUtils.formatDuration(job.getMaxExecutionDelayMillis(), pw);
521 pw.println();
522 }
523 pw.print(prefix); pw.print(" Backoff: policy=");
524 pw.print(job.getBackoffPolicy());
525 pw.print(" initial=");
526 TimeUtils.formatDuration(job.getInitialBackoffMillis(), pw);
527 pw.println();
528 if (job.hasEarlyConstraint()) {
529 pw.print(prefix); pw.println(" Has early constraint");
530 }
531 if (job.hasLateConstraint()) {
532 pw.print(prefix); pw.println(" Has late constraint");
533 }
Dianne Hackbornb0001f62016-02-16 10:30:33 -0800534 pw.print(prefix); pw.print("Required constraints:");
535 dumpConstraints(pw, requiredConstraints);
536 pw.println();
537 pw.print(prefix); pw.print("Satisfied constraints:");
538 dumpConstraints(pw, satisfiedConstraints);
539 pw.println();
Dianne Hackborn1a30bd92016-01-11 11:05:00 -0800540 if (changedAuthorities != null) {
541 pw.print(prefix); pw.println("Changed authorities:");
542 for (int i=0; i<changedAuthorities.size(); i++) {
543 pw.print(prefix); pw.print(" "); pw.println(changedAuthorities.valueAt(i));
544 }
545 if (changedUris != null) {
546 pw.print(prefix); pw.println("Changed URIs:");
547 for (int i=0; i<changedUris.size(); i++) {
548 pw.print(prefix); pw.print(" "); pw.println(changedUris.valueAt(i));
549 }
550 }
551 }
552 pw.print(prefix); pw.print("Earliest run time: ");
553 pw.println(formatRunTime(earliestRunTimeElapsedMillis, NO_EARLIEST_RUNTIME));
554 pw.print(prefix); pw.print("Latest run time: ");
555 pw.println(formatRunTime(latestRunTimeElapsedMillis, NO_LATEST_RUNTIME));
556 if (numFailures != 0) {
557 pw.print(prefix); pw.print("Num failures: "); pw.println(numFailures);
558 }
Christopher Tate7060b042014-06-09 19:50:00 -0700559 }
560}