Christopher Tate | 7060b04 | 2014-06-09 19:50:00 -0700 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (C) 2014 The Android Open Source Project |
| 3 | * |
| 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | * you may not use this file except in compliance with the License. |
| 6 | * You may obtain a copy of the License at |
| 7 | * |
| 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
| 9 | * |
| 10 | * Unless required by applicable law or agreed to in writing, software |
| 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
| 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 | * See the License for the specific language governing permissions and |
| 14 | * limitations under the License |
| 15 | */ |
| 16 | |
| 17 | package com.android.server.job.controllers; |
| 18 | |
Shreyas Basarge | 968ac75 | 2016-01-11 23:09:26 +0000 | [diff] [blame] | 19 | import android.app.AppGlobals; |
Dianne Hackborn | a47223f | 2017-03-30 13:49:13 -0700 | [diff] [blame] | 20 | import android.app.IActivityManager; |
Christopher Tate | 7060b04 | 2014-06-09 19:50:00 -0700 | [diff] [blame] | 21 | import android.app.job.JobInfo; |
Dianne Hackborn | 7da13d7 | 2017-04-04 17:17:35 -0700 | [diff] [blame] | 22 | import android.app.job.JobWorkItem; |
Dianne Hackborn | a47223f | 2017-03-30 13:49:13 -0700 | [diff] [blame] | 23 | import android.content.ClipData; |
Christopher Tate | 7060b04 | 2014-06-09 19:50:00 -0700 | [diff] [blame] | 24 | import android.content.ComponentName; |
Dianne Hackborn | 1a30bd9 | 2016-01-11 11:05:00 -0800 | [diff] [blame] | 25 | import android.net.Uri; |
Shreyas Basarge | 968ac75 | 2016-01-11 23:09:26 +0000 | [diff] [blame] | 26 | import android.os.RemoteException; |
Christopher Tate | 7060b04 | 2014-06-09 19:50:00 -0700 | [diff] [blame] | 27 | import android.os.SystemClock; |
| 28 | import android.os.UserHandle; |
Makoto Onuki | ab8a67f | 2017-06-20 12:20:34 -0700 | [diff] [blame] | 29 | import android.text.format.Time; |
Dianne Hackborn | 1a30bd9 | 2016-01-11 11:05:00 -0800 | [diff] [blame] | 30 | import android.util.ArraySet; |
Dianne Hackborn | a47223f | 2017-03-30 13:49:13 -0700 | [diff] [blame] | 31 | import android.util.Slog; |
Dianne Hackborn | 1a30bd9 | 2016-01-11 11:05:00 -0800 | [diff] [blame] | 32 | import android.util.TimeUtils; |
Christopher Tate | 7060b04 | 2014-06-09 19:50:00 -0700 | [diff] [blame] | 33 | |
Dianne Hackborn | 342e603 | 2017-04-13 18:04:31 -0700 | [diff] [blame] | 34 | import com.android.server.job.GrantedUriPermissions; |
| 35 | |
Christopher Tate | 7060b04 | 2014-06-09 19:50:00 -0700 | [diff] [blame] | 36 | import java.io.PrintWriter; |
Dianne Hackborn | 7da13d7 | 2017-04-04 17:17:35 -0700 | [diff] [blame] | 37 | import java.util.ArrayList; |
Dianne Hackborn | a47223f | 2017-03-30 13:49:13 -0700 | [diff] [blame] | 38 | import java.util.Arrays; |
Christopher Tate | 7060b04 | 2014-06-09 19:50:00 -0700 | [diff] [blame] | 39 | |
| 40 | /** |
| 41 | * Uniquely identifies a job internally. |
| 42 | * Created from the public {@link android.app.job.JobInfo} object when it lands on the scheduler. |
| 43 | * Contains current state of the requirements of the job, as well as a function to evaluate |
| 44 | * whether it's ready to run. |
| 45 | * This object is shared among the various controllers - hence why the different fields are atomic. |
| 46 | * This isn't strictly necessary because each controller is only interested in a specific field, |
| 47 | * and the receivers that are listening for global state change will all run on the main looper, |
| 48 | * but we don't enforce that so this is safer. |
| 49 | * @hide |
| 50 | */ |
Dianne Hackborn | b0001f6 | 2016-02-16 10:30:33 -0800 | [diff] [blame] | 51 | public final class JobStatus { |
Dianne Hackborn | a47223f | 2017-03-30 13:49:13 -0700 | [diff] [blame] | 52 | static final String TAG = "JobSchedulerService"; |
| 53 | |
Christopher Tate | 7060b04 | 2014-06-09 19:50:00 -0700 | [diff] [blame] | 54 | public static final long NO_LATEST_RUNTIME = Long.MAX_VALUE; |
| 55 | public static final long NO_EARLIEST_RUNTIME = 0L; |
| 56 | |
Dianne Hackborn | a06ec6a | 2017-02-13 10:08:42 -0800 | [diff] [blame] | 57 | static final int CONSTRAINT_CHARGING = JobInfo.CONSTRAINT_FLAG_CHARGING; |
| 58 | static final int CONSTRAINT_IDLE = JobInfo.CONSTRAINT_FLAG_DEVICE_IDLE; |
| 59 | static final int CONSTRAINT_BATTERY_NOT_LOW = JobInfo.CONSTRAINT_FLAG_BATTERY_NOT_LOW; |
Dianne Hackborn | 532ea26 | 2017-03-17 17:50:55 -0700 | [diff] [blame] | 60 | static final int CONSTRAINT_STORAGE_NOT_LOW = JobInfo.CONSTRAINT_FLAG_STORAGE_NOT_LOW; |
Dianne Hackborn | a06ec6a | 2017-02-13 10:08:42 -0800 | [diff] [blame] | 61 | static final int CONSTRAINT_TIMING_DELAY = 1<<31; |
| 62 | static final int CONSTRAINT_DEADLINE = 1<<30; |
| 63 | static final int CONSTRAINT_UNMETERED = 1<<29; |
| 64 | static final int CONSTRAINT_CONNECTIVITY = 1<<28; |
| 65 | static final int CONSTRAINT_APP_NOT_IDLE = 1<<27; |
| 66 | static final int CONSTRAINT_CONTENT_TRIGGER = 1<<26; |
| 67 | static final int CONSTRAINT_DEVICE_NOT_DOZING = 1<<25; |
| 68 | static final int CONSTRAINT_NOT_ROAMING = 1<<24; |
Christopher Tate | 60977f4 | 2017-04-13 13:48:46 -0700 | [diff] [blame] | 69 | static final int CONSTRAINT_METERED = 1<<23; |
| 70 | |
| 71 | static final int CONNECTIVITY_MASK = |
| 72 | CONSTRAINT_UNMETERED | CONSTRAINT_CONNECTIVITY | |
| 73 | CONSTRAINT_NOT_ROAMING | CONSTRAINT_METERED; |
Dianne Hackborn | b0001f6 | 2016-02-16 10:30:33 -0800 | [diff] [blame] | 74 | |
Christopher Tate | 5d34605 | 2016-03-08 12:56:08 -0800 | [diff] [blame] | 75 | // Soft override: ignore constraints like time that don't affect API availability |
| 76 | public static final int OVERRIDE_SOFT = 1; |
| 77 | // Full override: ignore all constraints including API-affecting like connectivity |
| 78 | public static final int OVERRIDE_FULL = 2; |
| 79 | |
Dianne Hackborn | 8db0fc1 | 2016-04-12 13:48:25 -0700 | [diff] [blame] | 80 | /** If not specified, trigger update delay is 10 seconds. */ |
| 81 | public static final long DEFAULT_TRIGGER_UPDATE_DELAY = 10*1000; |
| 82 | |
| 83 | /** The minimum possible update delay is 1/2 second. */ |
| 84 | public static final long MIN_TRIGGER_UPDATE_DELAY = 500; |
| 85 | |
| 86 | /** If not specified, trigger maxumum delay is 2 minutes. */ |
| 87 | public static final long DEFAULT_TRIGGER_MAX_DELAY = 2*60*1000; |
| 88 | |
| 89 | /** The minimum possible update delay is 1 second. */ |
| 90 | public static final long MIN_TRIGGER_MAX_DELAY = 1000; |
| 91 | |
Christopher Tate | 7060b04 | 2014-06-09 19:50:00 -0700 | [diff] [blame] | 92 | final JobInfo job; |
Matthew Williams | 9ae3dbe | 2014-08-21 13:47:47 -0700 | [diff] [blame] | 93 | /** Uid of the package requesting this job. */ |
Shreyas Basarge | 8e64e2e | 2016-02-12 15:49:31 +0000 | [diff] [blame] | 94 | final int callingUid; |
Dianne Hackborn | 1085ff6 | 2016-02-23 17:04:58 -0800 | [diff] [blame] | 95 | final String batteryName; |
Christopher Tate | 7060b04 | 2014-06-09 19:50:00 -0700 | [diff] [blame] | 96 | |
Shreyas Basarge | 8e64e2e | 2016-02-12 15:49:31 +0000 | [diff] [blame] | 97 | final String sourcePackageName; |
| 98 | final int sourceUserId; |
| 99 | final int sourceUid; |
Dianne Hackborn | 1085ff6 | 2016-02-23 17:04:58 -0800 | [diff] [blame] | 100 | final String sourceTag; |
| 101 | |
| 102 | final String tag; |
Shreyas Basarge | 968ac75 | 2016-01-11 23:09:26 +0000 | [diff] [blame] | 103 | |
Dianne Hackborn | 342e603 | 2017-04-13 18:04:31 -0700 | [diff] [blame] | 104 | private GrantedUriPermissions uriPerms; |
Dianne Hackborn | a47223f | 2017-03-30 13:49:13 -0700 | [diff] [blame] | 105 | private boolean prepared; |
| 106 | |
Christopher Tate | b164f01 | 2017-04-26 15:41:37 -0700 | [diff] [blame] | 107 | static final boolean DEBUG_PREPARE = true; |
| 108 | private Throwable unpreparedPoint = null; |
| 109 | |
Dianne Hackborn | b0001f6 | 2016-02-16 10:30:33 -0800 | [diff] [blame] | 110 | /** |
| 111 | * Earliest point in the future at which this job will be eligible to run. A value of 0 |
| 112 | * indicates there is no delay constraint. See {@link #hasTimingDelayConstraint()}. |
| 113 | */ |
| 114 | private final long earliestRunTimeElapsedMillis; |
| 115 | /** |
| 116 | * Latest point in the future at which this job must be run. A value of {@link Long#MAX_VALUE} |
| 117 | * indicates there is no deadline constraint. See {@link #hasDeadlineConstraint()}. |
| 118 | */ |
| 119 | private final long latestRunTimeElapsedMillis; |
| 120 | |
| 121 | /** How many times this job has failed, used to compute back-off. */ |
| 122 | private final int numFailures; |
| 123 | |
Christopher Tate | 7060b04 | 2014-06-09 19:50:00 -0700 | [diff] [blame] | 124 | // Constraints. |
Dianne Hackborn | b0001f6 | 2016-02-16 10:30:33 -0800 | [diff] [blame] | 125 | final int requiredConstraints; |
| 126 | int satisfiedConstraints = 0; |
Dianne Hackborn | 1a30bd9 | 2016-01-11 11:05:00 -0800 | [diff] [blame] | 127 | |
Dianne Hackborn | 7ab4025 | 2016-06-15 17:30:24 -0700 | [diff] [blame] | 128 | // Set to true if doze constraint was satisfied due to app being whitelisted. |
| 129 | public boolean dozeWhitelisted; |
| 130 | |
Dianne Hackborn | f9bac16 | 2017-04-20 17:17:48 -0700 | [diff] [blame] | 131 | /** |
| 132 | * Flag for {@link #trackingControllers}: the battery controller is currently tracking this job. |
| 133 | */ |
| 134 | public static final int TRACKING_BATTERY = 1<<0; |
| 135 | /** |
| 136 | * Flag for {@link #trackingControllers}: the network connectivity controller is currently |
| 137 | * tracking this job. |
| 138 | */ |
| 139 | public static final int TRACKING_CONNECTIVITY = 1<<1; |
| 140 | /** |
| 141 | * Flag for {@link #trackingControllers}: the content observer controller is currently |
| 142 | * tracking this job. |
| 143 | */ |
| 144 | public static final int TRACKING_CONTENT = 1<<2; |
| 145 | /** |
| 146 | * Flag for {@link #trackingControllers}: the idle controller is currently tracking this job. |
| 147 | */ |
| 148 | public static final int TRACKING_IDLE = 1<<3; |
| 149 | /** |
| 150 | * Flag for {@link #trackingControllers}: the storage controller is currently tracking this job. |
| 151 | */ |
| 152 | public static final int TRACKING_STORAGE = 1<<4; |
| 153 | /** |
| 154 | * Flag for {@link #trackingControllers}: the time controller is currently tracking this job. |
| 155 | */ |
| 156 | public static final int TRACKING_TIME = 1<<5; |
| 157 | |
| 158 | /** |
| 159 | * Bit mask of controllers that are currently tracking the job. |
| 160 | */ |
| 161 | private int trackingControllers; |
| 162 | |
Dianne Hackborn | 1a30bd9 | 2016-01-11 11:05:00 -0800 | [diff] [blame] | 163 | // These are filled in by controllers when preparing for execution. |
| 164 | public ArraySet<Uri> changedUris; |
| 165 | public ArraySet<String> changedAuthorities; |
| 166 | |
Dianne Hackborn | 1085ff6 | 2016-02-23 17:04:58 -0800 | [diff] [blame] | 167 | public int lastEvaluatedPriority; |
| 168 | |
Dianne Hackborn | 7da13d7 | 2017-04-04 17:17:35 -0700 | [diff] [blame] | 169 | // If non-null, this is work that has been enqueued for the job. |
| 170 | public ArrayList<JobWorkItem> pendingWork; |
| 171 | |
| 172 | // If non-null, this is work that is currently being executed. |
| 173 | public ArrayList<JobWorkItem> executingWork; |
| 174 | |
| 175 | public int nextPendingWorkId = 1; |
| 176 | |
Christopher Tate | 5d34605 | 2016-03-08 12:56:08 -0800 | [diff] [blame] | 177 | // Used by shell commands |
| 178 | public int overrideState = 0; |
| 179 | |
Dianne Hackborn | bfc2331 | 2017-05-11 11:53:24 -0700 | [diff] [blame] | 180 | // When this job was enqueued, for ordering. (in elapsedRealtimeMillis) |
| 181 | public long enqueueTime; |
| 182 | |
| 183 | // Metrics about queue latency. (in uptimeMillis) |
Christopher Tate | 7234fc6 | 2017-04-03 17:36:07 -0700 | [diff] [blame] | 184 | public long madePending; |
| 185 | public long madeActive; |
| 186 | |
Dianne Hackborn | 1a30bd9 | 2016-01-11 11:05:00 -0800 | [diff] [blame] | 187 | /** |
Makoto Onuki | ab8a67f | 2017-06-20 12:20:34 -0700 | [diff] [blame] | 188 | * Last time a job finished successfully for a periodic job, in the currentTimeMillis time, |
| 189 | * for dumpsys. |
| 190 | */ |
| 191 | private long mLastSuccessfulRunTime; |
| 192 | |
| 193 | /** |
| 194 | * Last time a job finished unsuccessfully, in the currentTimeMillis time, for dumpsys. |
| 195 | */ |
| 196 | private long mLastFailedRunTime; |
| 197 | |
| 198 | /** |
Dianne Hackborn | 1a30bd9 | 2016-01-11 11:05:00 -0800 | [diff] [blame] | 199 | * For use only by ContentObserverController: state it is maintaining about content URIs |
| 200 | * being observed. |
| 201 | */ |
| 202 | ContentObserverController.JobInstance contentObserverJobInstance; |
Christopher Tate | 7060b04 | 2014-06-09 19:50:00 -0700 | [diff] [blame] | 203 | |
Christopher Tate | 7060b04 | 2014-06-09 19:50:00 -0700 | [diff] [blame] | 204 | /** Provide a handle to the service that this job will be run on. */ |
| 205 | public int getServiceToken() { |
Shreyas Basarge | 8e64e2e | 2016-02-12 15:49:31 +0000 | [diff] [blame] | 206 | return callingUid; |
Christopher Tate | 7060b04 | 2014-06-09 19:50:00 -0700 | [diff] [blame] | 207 | } |
| 208 | |
Dianne Hackborn | b0001f6 | 2016-02-16 10:30:33 -0800 | [diff] [blame] | 209 | private JobStatus(JobInfo job, int callingUid, String sourcePackageName, |
Dianne Hackborn | 1085ff6 | 2016-02-23 17:04:58 -0800 | [diff] [blame] | 210 | int sourceUserId, String tag, int numFailures, long earliestRunTimeElapsedMillis, |
Makoto Onuki | ab8a67f | 2017-06-20 12:20:34 -0700 | [diff] [blame] | 211 | long latestRunTimeElapsedMillis, long lastSuccessfulRunTime, long lastFailedRunTime) { |
Christopher Tate | 7060b04 | 2014-06-09 19:50:00 -0700 | [diff] [blame] | 212 | this.job = job; |
Shreyas Basarge | 8e64e2e | 2016-02-12 15:49:31 +0000 | [diff] [blame] | 213 | this.callingUid = callingUid; |
Shreyas Basarge | 8e64e2e | 2016-02-12 15:49:31 +0000 | [diff] [blame] | 214 | |
| 215 | int tempSourceUid = -1; |
| 216 | if (sourceUserId != -1 && sourcePackageName != null) { |
| 217 | try { |
| 218 | tempSourceUid = AppGlobals.getPackageManager().getPackageUid(sourcePackageName, 0, |
| 219 | sourceUserId); |
| 220 | } catch (RemoteException ex) { |
| 221 | // Can't happen, PackageManager runs in the same process. |
| 222 | } |
| 223 | } |
| 224 | if (tempSourceUid == -1) { |
| 225 | this.sourceUid = callingUid; |
| 226 | this.sourceUserId = UserHandle.getUserId(callingUid); |
| 227 | this.sourcePackageName = job.getService().getPackageName(); |
Dianne Hackborn | 1085ff6 | 2016-02-23 17:04:58 -0800 | [diff] [blame] | 228 | this.sourceTag = null; |
Shreyas Basarge | 8e64e2e | 2016-02-12 15:49:31 +0000 | [diff] [blame] | 229 | } else { |
| 230 | this.sourceUid = tempSourceUid; |
| 231 | this.sourceUserId = sourceUserId; |
| 232 | this.sourcePackageName = sourcePackageName; |
Dianne Hackborn | 1085ff6 | 2016-02-23 17:04:58 -0800 | [diff] [blame] | 233 | this.sourceTag = tag; |
Shreyas Basarge | 8e64e2e | 2016-02-12 15:49:31 +0000 | [diff] [blame] | 234 | } |
Dianne Hackborn | b0001f6 | 2016-02-16 10:30:33 -0800 | [diff] [blame] | 235 | |
Shreyas Basarge | eda34e4 | 2016-04-26 00:14:02 +0100 | [diff] [blame] | 236 | this.batteryName = this.sourceTag != null |
| 237 | ? this.sourceTag + ":" + job.getService().getPackageName() |
| 238 | : job.getService().flattenToShortString(); |
Dianne Hackborn | 1085ff6 | 2016-02-23 17:04:58 -0800 | [diff] [blame] | 239 | this.tag = "*job*/" + this.batteryName; |
| 240 | |
Dianne Hackborn | b0001f6 | 2016-02-16 10:30:33 -0800 | [diff] [blame] | 241 | this.earliestRunTimeElapsedMillis = earliestRunTimeElapsedMillis; |
| 242 | this.latestRunTimeElapsedMillis = latestRunTimeElapsedMillis; |
| 243 | this.numFailures = numFailures; |
| 244 | |
Dianne Hackborn | a06ec6a | 2017-02-13 10:08:42 -0800 | [diff] [blame] | 245 | int requiredConstraints = job.getConstraintFlags(); |
Christopher Tate | 60977f4 | 2017-04-13 13:48:46 -0700 | [diff] [blame] | 246 | |
| 247 | switch (job.getNetworkType()) { |
| 248 | case JobInfo.NETWORK_TYPE_NONE: |
| 249 | // No constraint. |
| 250 | break; |
| 251 | case JobInfo.NETWORK_TYPE_ANY: |
| 252 | requiredConstraints |= CONSTRAINT_CONNECTIVITY; |
| 253 | break; |
| 254 | case JobInfo.NETWORK_TYPE_UNMETERED: |
| 255 | requiredConstraints |= CONSTRAINT_UNMETERED; |
| 256 | break; |
| 257 | case JobInfo.NETWORK_TYPE_NOT_ROAMING: |
| 258 | requiredConstraints |= CONSTRAINT_NOT_ROAMING; |
| 259 | break; |
| 260 | case JobInfo.NETWORK_TYPE_METERED: |
| 261 | requiredConstraints |= CONSTRAINT_METERED; |
| 262 | break; |
| 263 | default: |
| 264 | Slog.w(TAG, "Unrecognized networking constraint " + job.getNetworkType()); |
| 265 | break; |
Dianne Hackborn | b0001f6 | 2016-02-16 10:30:33 -0800 | [diff] [blame] | 266 | } |
Christopher Tate | 60977f4 | 2017-04-13 13:48:46 -0700 | [diff] [blame] | 267 | |
Dianne Hackborn | b0001f6 | 2016-02-16 10:30:33 -0800 | [diff] [blame] | 268 | if (earliestRunTimeElapsedMillis != NO_EARLIEST_RUNTIME) { |
| 269 | requiredConstraints |= CONSTRAINT_TIMING_DELAY; |
| 270 | } |
| 271 | if (latestRunTimeElapsedMillis != NO_LATEST_RUNTIME) { |
| 272 | requiredConstraints |= CONSTRAINT_DEADLINE; |
| 273 | } |
Dianne Hackborn | b0001f6 | 2016-02-16 10:30:33 -0800 | [diff] [blame] | 274 | if (job.getTriggerContentUris() != null) { |
| 275 | requiredConstraints |= CONSTRAINT_CONTENT_TRIGGER; |
| 276 | } |
| 277 | this.requiredConstraints = requiredConstraints; |
Makoto Onuki | ab8a67f | 2017-06-20 12:20:34 -0700 | [diff] [blame] | 278 | |
| 279 | mLastSuccessfulRunTime = lastSuccessfulRunTime; |
| 280 | mLastFailedRunTime = lastFailedRunTime; |
Christopher Tate | 7060b04 | 2014-06-09 19:50:00 -0700 | [diff] [blame] | 281 | } |
| 282 | |
Matthew Williams | 0cc7654 | 2015-10-16 21:04:51 -0700 | [diff] [blame] | 283 | /** Copy constructor. */ |
| 284 | public JobStatus(JobStatus jobStatus) { |
Dianne Hackborn | b0001f6 | 2016-02-16 10:30:33 -0800 | [diff] [blame] | 285 | this(jobStatus.getJob(), jobStatus.getUid(), |
Dianne Hackborn | d506b2b | 2016-02-16 10:30:33 -0800 | [diff] [blame] | 286 | jobStatus.getSourcePackageName(), jobStatus.getSourceUserId(), |
Dianne Hackborn | 1085ff6 | 2016-02-23 17:04:58 -0800 | [diff] [blame] | 287 | jobStatus.getSourceTag(), jobStatus.getNumFailures(), |
Makoto Onuki | ab8a67f | 2017-06-20 12:20:34 -0700 | [diff] [blame] | 288 | jobStatus.getEarliestRunTime(), jobStatus.getLatestRunTimeElapsed(), |
| 289 | jobStatus.getLastSuccessfulRunTime(), jobStatus.getLastFailedRunTime()); |
Christopher Tate | 7060b04 | 2014-06-09 19:50:00 -0700 | [diff] [blame] | 290 | } |
| 291 | |
| 292 | /** |
| 293 | * Create a new JobStatus that was loaded from disk. We ignore the provided |
| 294 | * {@link android.app.job.JobInfo} time criteria because we can load a persisted periodic job |
| 295 | * from the {@link com.android.server.job.JobStore} and still want to respect its |
| 296 | * wallclock runtime rather than resetting it on every boot. |
| 297 | * We consider a freshly loaded job to no longer be in back-off. |
| 298 | */ |
Dianne Hackborn | 1085ff6 | 2016-02-23 17:04:58 -0800 | [diff] [blame] | 299 | public JobStatus(JobInfo job, int callingUid, String sourcePackageName, int sourceUserId, |
Makoto Onuki | ab8a67f | 2017-06-20 12:20:34 -0700 | [diff] [blame] | 300 | String sourceTag, long earliestRunTimeElapsedMillis, long latestRunTimeElapsedMillis, |
| 301 | long lastSuccessfulRunTime, long lastFailedRunTime) { |
Dianne Hackborn | 1085ff6 | 2016-02-23 17:04:58 -0800 | [diff] [blame] | 302 | this(job, callingUid, sourcePackageName, sourceUserId, sourceTag, 0, |
Makoto Onuki | ab8a67f | 2017-06-20 12:20:34 -0700 | [diff] [blame] | 303 | earliestRunTimeElapsedMillis, latestRunTimeElapsedMillis, |
| 304 | lastSuccessfulRunTime, lastFailedRunTime); |
Christopher Tate | 7060b04 | 2014-06-09 19:50:00 -0700 | [diff] [blame] | 305 | } |
| 306 | |
| 307 | /** Create a new job to be rescheduled with the provided parameters. */ |
| 308 | public JobStatus(JobStatus rescheduling, long newEarliestRuntimeElapsedMillis, |
Makoto Onuki | ab8a67f | 2017-06-20 12:20:34 -0700 | [diff] [blame] | 309 | long newLatestRuntimeElapsedMillis, int backoffAttempt, |
| 310 | long lastSuccessfulRunTime, long lastFailedRunTime) { |
Dianne Hackborn | b0001f6 | 2016-02-16 10:30:33 -0800 | [diff] [blame] | 311 | this(rescheduling.job, rescheduling.getUid(), |
Dianne Hackborn | 1085ff6 | 2016-02-23 17:04:58 -0800 | [diff] [blame] | 312 | rescheduling.getSourcePackageName(), rescheduling.getSourceUserId(), |
| 313 | rescheduling.getSourceTag(), backoffAttempt, newEarliestRuntimeElapsedMillis, |
Makoto Onuki | ab8a67f | 2017-06-20 12:20:34 -0700 | [diff] [blame] | 314 | newLatestRuntimeElapsedMillis, |
| 315 | lastSuccessfulRunTime, lastFailedRunTime); |
Dianne Hackborn | b0001f6 | 2016-02-16 10:30:33 -0800 | [diff] [blame] | 316 | } |
Christopher Tate | 7060b04 | 2014-06-09 19:50:00 -0700 | [diff] [blame] | 317 | |
Dianne Hackborn | b0001f6 | 2016-02-16 10:30:33 -0800 | [diff] [blame] | 318 | /** |
| 319 | * Create a newly scheduled job. |
| 320 | * @param callingUid Uid of the package that scheduled this job. |
| 321 | * @param sourcePackageName Package name on whose behalf this job is scheduled. Null indicates |
| 322 | * the calling package is the source. |
| 323 | * @param sourceUserId User id for whom this job is scheduled. -1 indicates this is same as the |
| 324 | */ |
| 325 | public static JobStatus createFromJobInfo(JobInfo job, int callingUid, String sourcePackageName, |
Dianne Hackborn | 1085ff6 | 2016-02-23 17:04:58 -0800 | [diff] [blame] | 326 | int sourceUserId, String tag) { |
Dianne Hackborn | b0001f6 | 2016-02-16 10:30:33 -0800 | [diff] [blame] | 327 | final long elapsedNow = SystemClock.elapsedRealtime(); |
| 328 | final long earliestRunTimeElapsedMillis, latestRunTimeElapsedMillis; |
| 329 | if (job.isPeriodic()) { |
| 330 | latestRunTimeElapsedMillis = elapsedNow + job.getIntervalMillis(); |
| 331 | earliestRunTimeElapsedMillis = latestRunTimeElapsedMillis - job.getFlexMillis(); |
| 332 | } else { |
| 333 | earliestRunTimeElapsedMillis = job.hasEarlyConstraint() ? |
| 334 | elapsedNow + job.getMinLatencyMillis() : NO_EARLIEST_RUNTIME; |
| 335 | latestRunTimeElapsedMillis = job.hasLateConstraint() ? |
| 336 | elapsedNow + job.getMaxExecutionDelayMillis() : NO_LATEST_RUNTIME; |
| 337 | } |
Dianne Hackborn | 1085ff6 | 2016-02-23 17:04:58 -0800 | [diff] [blame] | 338 | return new JobStatus(job, callingUid, sourcePackageName, sourceUserId, tag, 0, |
Makoto Onuki | ab8a67f | 2017-06-20 12:20:34 -0700 | [diff] [blame] | 339 | earliestRunTimeElapsedMillis, latestRunTimeElapsedMillis, |
| 340 | 0 /* lastSuccessfulRunTime */, 0 /* lastFailedRunTime */); |
Christopher Tate | 7060b04 | 2014-06-09 19:50:00 -0700 | [diff] [blame] | 341 | } |
| 342 | |
Dianne Hackborn | 342e603 | 2017-04-13 18:04:31 -0700 | [diff] [blame] | 343 | public void enqueueWorkLocked(IActivityManager am, JobWorkItem work) { |
Dianne Hackborn | 7da13d7 | 2017-04-04 17:17:35 -0700 | [diff] [blame] | 344 | if (pendingWork == null) { |
| 345 | pendingWork = new ArrayList<>(); |
| 346 | } |
| 347 | work.setWorkId(nextPendingWorkId); |
| 348 | nextPendingWorkId++; |
Dianne Hackborn | 342e603 | 2017-04-13 18:04:31 -0700 | [diff] [blame] | 349 | if (work.getIntent() != null |
| 350 | && GrantedUriPermissions.checkGrantFlags(work.getIntent().getFlags())) { |
| 351 | work.setGrants(GrantedUriPermissions.createFromIntent(am, work.getIntent(), sourceUid, |
| 352 | sourcePackageName, sourceUserId, toShortString())); |
| 353 | } |
Dianne Hackborn | 7da13d7 | 2017-04-04 17:17:35 -0700 | [diff] [blame] | 354 | pendingWork.add(work); |
| 355 | } |
| 356 | |
| 357 | public JobWorkItem dequeueWorkLocked() { |
| 358 | if (pendingWork != null && pendingWork.size() > 0) { |
| 359 | JobWorkItem work = pendingWork.remove(0); |
| 360 | if (work != null) { |
| 361 | if (executingWork == null) { |
| 362 | executingWork = new ArrayList<>(); |
| 363 | } |
| 364 | executingWork.add(work); |
Dianne Hackborn | 28d1b66 | 2017-04-21 14:17:23 -0700 | [diff] [blame] | 365 | work.bumpDeliveryCount(); |
Dianne Hackborn | 7da13d7 | 2017-04-04 17:17:35 -0700 | [diff] [blame] | 366 | } |
| 367 | return work; |
| 368 | } |
| 369 | return null; |
| 370 | } |
| 371 | |
Dianne Hackborn | bfc2331 | 2017-05-11 11:53:24 -0700 | [diff] [blame] | 372 | public boolean hasWorkLocked() { |
| 373 | return (pendingWork != null && pendingWork.size() > 0) || hasExecutingWorkLocked(); |
| 374 | } |
| 375 | |
Dianne Hackborn | 7da13d7 | 2017-04-04 17:17:35 -0700 | [diff] [blame] | 376 | public boolean hasExecutingWorkLocked() { |
| 377 | return executingWork != null && executingWork.size() > 0; |
| 378 | } |
| 379 | |
Dianne Hackborn | 342e603 | 2017-04-13 18:04:31 -0700 | [diff] [blame] | 380 | private static void ungrantWorkItem(IActivityManager am, JobWorkItem work) { |
| 381 | if (work.getGrants() != null) { |
| 382 | ((GrantedUriPermissions)work.getGrants()).revoke(am); |
| 383 | } |
| 384 | } |
| 385 | |
| 386 | public boolean completeWorkLocked(IActivityManager am, int workId) { |
Dianne Hackborn | 7da13d7 | 2017-04-04 17:17:35 -0700 | [diff] [blame] | 387 | if (executingWork != null) { |
| 388 | final int N = executingWork.size(); |
| 389 | for (int i = 0; i < N; i++) { |
Dianne Hackborn | 342e603 | 2017-04-13 18:04:31 -0700 | [diff] [blame] | 390 | JobWorkItem work = executingWork.get(i); |
| 391 | if (work.getWorkId() == workId) { |
Dianne Hackborn | 7da13d7 | 2017-04-04 17:17:35 -0700 | [diff] [blame] | 392 | executingWork.remove(i); |
Dianne Hackborn | 342e603 | 2017-04-13 18:04:31 -0700 | [diff] [blame] | 393 | ungrantWorkItem(am, work); |
Dianne Hackborn | 7da13d7 | 2017-04-04 17:17:35 -0700 | [diff] [blame] | 394 | return true; |
| 395 | } |
| 396 | } |
| 397 | } |
| 398 | return false; |
| 399 | } |
| 400 | |
Dianne Hackborn | 342e603 | 2017-04-13 18:04:31 -0700 | [diff] [blame] | 401 | private static void ungrantWorkList(IActivityManager am, ArrayList<JobWorkItem> list) { |
| 402 | if (list != null) { |
| 403 | final int N = list.size(); |
| 404 | for (int i = 0; i < N; i++) { |
| 405 | ungrantWorkItem(am, list.get(i)); |
| 406 | } |
| 407 | } |
| 408 | } |
| 409 | |
| 410 | public void stopTrackingJobLocked(IActivityManager am, JobStatus incomingJob) { |
Dianne Hackborn | 7da13d7 | 2017-04-04 17:17:35 -0700 | [diff] [blame] | 411 | if (incomingJob != null) { |
Dianne Hackborn | 342e603 | 2017-04-13 18:04:31 -0700 | [diff] [blame] | 412 | // We are replacing with a new job -- transfer the work! We do any executing |
| 413 | // work first, since that was originally at the front of the pending work. |
| 414 | if (executingWork != null && executingWork.size() > 0) { |
| 415 | incomingJob.pendingWork = executingWork; |
| 416 | } |
| 417 | if (incomingJob.pendingWork == null) { |
| 418 | incomingJob.pendingWork = pendingWork; |
| 419 | } else if (pendingWork != null && pendingWork.size() > 0) { |
| 420 | incomingJob.pendingWork.addAll(pendingWork); |
| 421 | } |
Dianne Hackborn | 7da13d7 | 2017-04-04 17:17:35 -0700 | [diff] [blame] | 422 | pendingWork = null; |
Dianne Hackborn | 342e603 | 2017-04-13 18:04:31 -0700 | [diff] [blame] | 423 | executingWork = null; |
Dianne Hackborn | 7da13d7 | 2017-04-04 17:17:35 -0700 | [diff] [blame] | 424 | incomingJob.nextPendingWorkId = nextPendingWorkId; |
| 425 | } else { |
| 426 | // We are completely stopping the job... need to clean up work. |
Dianne Hackborn | 342e603 | 2017-04-13 18:04:31 -0700 | [diff] [blame] | 427 | ungrantWorkList(am, pendingWork); |
| 428 | pendingWork = null; |
| 429 | ungrantWorkList(am, executingWork); |
| 430 | executingWork = null; |
Dianne Hackborn | 7da13d7 | 2017-04-04 17:17:35 -0700 | [diff] [blame] | 431 | } |
| 432 | } |
| 433 | |
| 434 | public void prepareLocked(IActivityManager am) { |
Dianne Hackborn | a47223f | 2017-03-30 13:49:13 -0700 | [diff] [blame] | 435 | if (prepared) { |
| 436 | Slog.wtf(TAG, "Already prepared: " + this); |
| 437 | return; |
| 438 | } |
| 439 | prepared = true; |
Christopher Tate | b164f01 | 2017-04-26 15:41:37 -0700 | [diff] [blame] | 440 | if (DEBUG_PREPARE) { |
| 441 | unpreparedPoint = null; |
| 442 | } |
Dianne Hackborn | a47223f | 2017-03-30 13:49:13 -0700 | [diff] [blame] | 443 | final ClipData clip = job.getClipData(); |
| 444 | if (clip != null) { |
Dianne Hackborn | 342e603 | 2017-04-13 18:04:31 -0700 | [diff] [blame] | 445 | uriPerms = GrantedUriPermissions.createFromClip(am, clip, sourceUid, sourcePackageName, |
| 446 | sourceUserId, job.getClipGrantFlags(), toShortString()); |
Dianne Hackborn | a47223f | 2017-03-30 13:49:13 -0700 | [diff] [blame] | 447 | } |
| 448 | } |
| 449 | |
Dianne Hackborn | 7da13d7 | 2017-04-04 17:17:35 -0700 | [diff] [blame] | 450 | public void unprepareLocked(IActivityManager am) { |
Dianne Hackborn | a47223f | 2017-03-30 13:49:13 -0700 | [diff] [blame] | 451 | if (!prepared) { |
| 452 | Slog.wtf(TAG, "Hasn't been prepared: " + this); |
Christopher Tate | b164f01 | 2017-04-26 15:41:37 -0700 | [diff] [blame] | 453 | if (DEBUG_PREPARE && unpreparedPoint != null) { |
| 454 | Slog.e(TAG, "Was already unprepared at ", unpreparedPoint); |
| 455 | } |
Dianne Hackborn | a47223f | 2017-03-30 13:49:13 -0700 | [diff] [blame] | 456 | return; |
| 457 | } |
| 458 | prepared = false; |
Christopher Tate | b164f01 | 2017-04-26 15:41:37 -0700 | [diff] [blame] | 459 | if (DEBUG_PREPARE) { |
| 460 | unpreparedPoint = new Throwable().fillInStackTrace(); |
| 461 | } |
Dianne Hackborn | 342e603 | 2017-04-13 18:04:31 -0700 | [diff] [blame] | 462 | if (uriPerms != null) { |
| 463 | uriPerms.revoke(am); |
| 464 | uriPerms = null; |
Dianne Hackborn | a47223f | 2017-03-30 13:49:13 -0700 | [diff] [blame] | 465 | } |
| 466 | } |
| 467 | |
Dianne Hackborn | 7da13d7 | 2017-04-04 17:17:35 -0700 | [diff] [blame] | 468 | public boolean isPreparedLocked() { |
Dianne Hackborn | a47223f | 2017-03-30 13:49:13 -0700 | [diff] [blame] | 469 | return prepared; |
| 470 | } |
| 471 | |
Christopher Tate | 7060b04 | 2014-06-09 19:50:00 -0700 | [diff] [blame] | 472 | public JobInfo getJob() { |
| 473 | return job; |
| 474 | } |
| 475 | |
| 476 | public int getJobId() { |
| 477 | return job.getId(); |
| 478 | } |
| 479 | |
Dianne Hackborn | e9a988c | 2016-05-27 17:59:40 -0700 | [diff] [blame] | 480 | public void printUniqueId(PrintWriter pw) { |
| 481 | UserHandle.formatUid(pw, callingUid); |
| 482 | pw.print("/"); |
| 483 | pw.print(job.getId()); |
| 484 | } |
| 485 | |
Christopher Tate | 7060b04 | 2014-06-09 19:50:00 -0700 | [diff] [blame] | 486 | public int getNumFailures() { |
| 487 | return numFailures; |
| 488 | } |
| 489 | |
| 490 | public ComponentName getServiceComponent() { |
| 491 | return job.getService(); |
| 492 | } |
| 493 | |
Shreyas Basarge | 968ac75 | 2016-01-11 23:09:26 +0000 | [diff] [blame] | 494 | public String getSourcePackageName() { |
Shreyas Basarge | 8e64e2e | 2016-02-12 15:49:31 +0000 | [diff] [blame] | 495 | return sourcePackageName; |
Shreyas Basarge | 968ac75 | 2016-01-11 23:09:26 +0000 | [diff] [blame] | 496 | } |
| 497 | |
| 498 | public int getSourceUid() { |
| 499 | return sourceUid; |
| 500 | } |
| 501 | |
| 502 | public int getSourceUserId() { |
Shreyas Basarge | 968ac75 | 2016-01-11 23:09:26 +0000 | [diff] [blame] | 503 | return sourceUserId; |
| 504 | } |
| 505 | |
Christopher Tate | 7060b04 | 2014-06-09 19:50:00 -0700 | [diff] [blame] | 506 | public int getUserId() { |
Shreyas Basarge | 8e64e2e | 2016-02-12 15:49:31 +0000 | [diff] [blame] | 507 | return UserHandle.getUserId(callingUid); |
Christopher Tate | 7060b04 | 2014-06-09 19:50:00 -0700 | [diff] [blame] | 508 | } |
| 509 | |
Dianne Hackborn | 1085ff6 | 2016-02-23 17:04:58 -0800 | [diff] [blame] | 510 | public String getSourceTag() { |
| 511 | return sourceTag; |
| 512 | } |
| 513 | |
Christopher Tate | 7060b04 | 2014-06-09 19:50:00 -0700 | [diff] [blame] | 514 | public int getUid() { |
Shreyas Basarge | 8e64e2e | 2016-02-12 15:49:31 +0000 | [diff] [blame] | 515 | return callingUid; |
Christopher Tate | 7060b04 | 2014-06-09 19:50:00 -0700 | [diff] [blame] | 516 | } |
| 517 | |
Dianne Hackborn | 1085ff6 | 2016-02-23 17:04:58 -0800 | [diff] [blame] | 518 | public String getBatteryName() { |
| 519 | return batteryName; |
Dianne Hackborn | fdb1956 | 2014-07-11 16:03:36 -0700 | [diff] [blame] | 520 | } |
| 521 | |
| 522 | public String getTag() { |
| 523 | return tag; |
| 524 | } |
| 525 | |
Shreyas Basarge | 5db0908 | 2016-01-07 13:38:29 +0000 | [diff] [blame] | 526 | public int getPriority() { |
| 527 | return job.getPriority(); |
| 528 | } |
Christopher Tate | 7060b04 | 2014-06-09 19:50:00 -0700 | [diff] [blame] | 529 | |
Jeff Sharkey | 1b6519b | 2016-04-28 15:33:18 -0600 | [diff] [blame] | 530 | public int getFlags() { |
| 531 | return job.getFlags(); |
| 532 | } |
| 533 | |
Christopher Tate | 60977f4 | 2017-04-13 13:48:46 -0700 | [diff] [blame] | 534 | /** Does this job have any sort of networking constraint? */ |
Christopher Tate | 7060b04 | 2014-06-09 19:50:00 -0700 | [diff] [blame] | 535 | public boolean hasConnectivityConstraint() { |
Christopher Tate | 60977f4 | 2017-04-13 13:48:46 -0700 | [diff] [blame] | 536 | return (requiredConstraints&CONNECTIVITY_MASK) != 0; |
| 537 | } |
| 538 | |
| 539 | public boolean needsAnyConnectivity() { |
Dianne Hackborn | b0001f6 | 2016-02-16 10:30:33 -0800 | [diff] [blame] | 540 | return (requiredConstraints&CONSTRAINT_CONNECTIVITY) != 0; |
Christopher Tate | 7060b04 | 2014-06-09 19:50:00 -0700 | [diff] [blame] | 541 | } |
| 542 | |
Christopher Tate | 60977f4 | 2017-04-13 13:48:46 -0700 | [diff] [blame] | 543 | public boolean needsUnmeteredConnectivity() { |
Dianne Hackborn | b0001f6 | 2016-02-16 10:30:33 -0800 | [diff] [blame] | 544 | return (requiredConstraints&CONSTRAINT_UNMETERED) != 0; |
Christopher Tate | 7060b04 | 2014-06-09 19:50:00 -0700 | [diff] [blame] | 545 | } |
| 546 | |
Christopher Tate | 60977f4 | 2017-04-13 13:48:46 -0700 | [diff] [blame] | 547 | public boolean needsMeteredConnectivity() { |
| 548 | return (requiredConstraints&CONSTRAINT_METERED) != 0; |
| 549 | } |
| 550 | |
| 551 | public boolean needsNonRoamingConnectivity() { |
Jeff Sharkey | f07c7b9 | 2016-04-22 09:50:16 -0600 | [diff] [blame] | 552 | return (requiredConstraints&CONSTRAINT_NOT_ROAMING) != 0; |
| 553 | } |
| 554 | |
Christopher Tate | 7060b04 | 2014-06-09 19:50:00 -0700 | [diff] [blame] | 555 | public boolean hasChargingConstraint() { |
Dianne Hackborn | b0001f6 | 2016-02-16 10:30:33 -0800 | [diff] [blame] | 556 | return (requiredConstraints&CONSTRAINT_CHARGING) != 0; |
Christopher Tate | 7060b04 | 2014-06-09 19:50:00 -0700 | [diff] [blame] | 557 | } |
| 558 | |
Dianne Hackborn | a06ec6a | 2017-02-13 10:08:42 -0800 | [diff] [blame] | 559 | public boolean hasBatteryNotLowConstraint() { |
| 560 | return (requiredConstraints&CONSTRAINT_BATTERY_NOT_LOW) != 0; |
| 561 | } |
| 562 | |
| 563 | public boolean hasPowerConstraint() { |
| 564 | return (requiredConstraints&(CONSTRAINT_CHARGING|CONSTRAINT_BATTERY_NOT_LOW)) != 0; |
| 565 | } |
| 566 | |
Dianne Hackborn | 532ea26 | 2017-03-17 17:50:55 -0700 | [diff] [blame] | 567 | public boolean hasStorageNotLowConstraint() { |
| 568 | return (requiredConstraints&CONSTRAINT_STORAGE_NOT_LOW) != 0; |
| 569 | } |
| 570 | |
Christopher Tate | 7060b04 | 2014-06-09 19:50:00 -0700 | [diff] [blame] | 571 | public boolean hasTimingDelayConstraint() { |
Dianne Hackborn | b0001f6 | 2016-02-16 10:30:33 -0800 | [diff] [blame] | 572 | return (requiredConstraints&CONSTRAINT_TIMING_DELAY) != 0; |
Christopher Tate | 7060b04 | 2014-06-09 19:50:00 -0700 | [diff] [blame] | 573 | } |
| 574 | |
| 575 | public boolean hasDeadlineConstraint() { |
Dianne Hackborn | b0001f6 | 2016-02-16 10:30:33 -0800 | [diff] [blame] | 576 | return (requiredConstraints&CONSTRAINT_DEADLINE) != 0; |
Christopher Tate | 7060b04 | 2014-06-09 19:50:00 -0700 | [diff] [blame] | 577 | } |
| 578 | |
| 579 | public boolean hasIdleConstraint() { |
Dianne Hackborn | b0001f6 | 2016-02-16 10:30:33 -0800 | [diff] [blame] | 580 | return (requiredConstraints&CONSTRAINT_IDLE) != 0; |
Christopher Tate | 7060b04 | 2014-06-09 19:50:00 -0700 | [diff] [blame] | 581 | } |
| 582 | |
Dianne Hackborn | 1a30bd9 | 2016-01-11 11:05:00 -0800 | [diff] [blame] | 583 | public boolean hasContentTriggerConstraint() { |
Dianne Hackborn | b0001f6 | 2016-02-16 10:30:33 -0800 | [diff] [blame] | 584 | return (requiredConstraints&CONSTRAINT_CONTENT_TRIGGER) != 0; |
Dianne Hackborn | 1a30bd9 | 2016-01-11 11:05:00 -0800 | [diff] [blame] | 585 | } |
| 586 | |
Dianne Hackborn | 8db0fc1 | 2016-04-12 13:48:25 -0700 | [diff] [blame] | 587 | public long getTriggerContentUpdateDelay() { |
| 588 | long time = job.getTriggerContentUpdateDelay(); |
| 589 | if (time < 0) { |
| 590 | return DEFAULT_TRIGGER_UPDATE_DELAY; |
| 591 | } |
| 592 | return Math.max(time, MIN_TRIGGER_UPDATE_DELAY); |
| 593 | } |
| 594 | |
| 595 | public long getTriggerContentMaxDelay() { |
| 596 | long time = job.getTriggerContentMaxDelay(); |
| 597 | if (time < 0) { |
| 598 | return DEFAULT_TRIGGER_MAX_DELAY; |
| 599 | } |
| 600 | return Math.max(time, MIN_TRIGGER_MAX_DELAY); |
| 601 | } |
| 602 | |
Matthew Williams | 900c67f | 2014-07-09 12:46:53 -0700 | [diff] [blame] | 603 | public boolean isPersisted() { |
| 604 | return job.isPersisted(); |
| 605 | } |
| 606 | |
Christopher Tate | 7060b04 | 2014-06-09 19:50:00 -0700 | [diff] [blame] | 607 | public long getEarliestRunTime() { |
| 608 | return earliestRunTimeElapsedMillis; |
| 609 | } |
| 610 | |
| 611 | public long getLatestRunTimeElapsed() { |
| 612 | return latestRunTimeElapsedMillis; |
| 613 | } |
| 614 | |
Dianne Hackborn | b0001f6 | 2016-02-16 10:30:33 -0800 | [diff] [blame] | 615 | boolean setChargingConstraintSatisfied(boolean state) { |
| 616 | return setConstraintSatisfied(CONSTRAINT_CHARGING, state); |
| 617 | } |
| 618 | |
Dianne Hackborn | a06ec6a | 2017-02-13 10:08:42 -0800 | [diff] [blame] | 619 | boolean setBatteryNotLowConstraintSatisfied(boolean state) { |
| 620 | return setConstraintSatisfied(CONSTRAINT_BATTERY_NOT_LOW, state); |
| 621 | } |
| 622 | |
Dianne Hackborn | 532ea26 | 2017-03-17 17:50:55 -0700 | [diff] [blame] | 623 | boolean setStorageNotLowConstraintSatisfied(boolean state) { |
| 624 | return setConstraintSatisfied(CONSTRAINT_STORAGE_NOT_LOW, state); |
| 625 | } |
| 626 | |
Dianne Hackborn | b0001f6 | 2016-02-16 10:30:33 -0800 | [diff] [blame] | 627 | boolean setTimingDelayConstraintSatisfied(boolean state) { |
| 628 | return setConstraintSatisfied(CONSTRAINT_TIMING_DELAY, state); |
| 629 | } |
| 630 | |
| 631 | boolean setDeadlineConstraintSatisfied(boolean state) { |
| 632 | return setConstraintSatisfied(CONSTRAINT_DEADLINE, state); |
| 633 | } |
| 634 | |
| 635 | boolean setIdleConstraintSatisfied(boolean state) { |
| 636 | return setConstraintSatisfied(CONSTRAINT_IDLE, state); |
| 637 | } |
| 638 | |
Jeff Sharkey | f07c7b9 | 2016-04-22 09:50:16 -0600 | [diff] [blame] | 639 | boolean setConnectivityConstraintSatisfied(boolean state) { |
| 640 | return setConstraintSatisfied(CONSTRAINT_CONNECTIVITY, state); |
| 641 | } |
| 642 | |
Dianne Hackborn | b0001f6 | 2016-02-16 10:30:33 -0800 | [diff] [blame] | 643 | boolean setUnmeteredConstraintSatisfied(boolean state) { |
| 644 | return setConstraintSatisfied(CONSTRAINT_UNMETERED, state); |
| 645 | } |
| 646 | |
Christopher Tate | 60977f4 | 2017-04-13 13:48:46 -0700 | [diff] [blame] | 647 | boolean setMeteredConstraintSatisfied(boolean state) { |
| 648 | return setConstraintSatisfied(CONSTRAINT_METERED, state); |
| 649 | } |
| 650 | |
Jeff Sharkey | f07c7b9 | 2016-04-22 09:50:16 -0600 | [diff] [blame] | 651 | boolean setNotRoamingConstraintSatisfied(boolean state) { |
| 652 | return setConstraintSatisfied(CONSTRAINT_NOT_ROAMING, state); |
Dianne Hackborn | b0001f6 | 2016-02-16 10:30:33 -0800 | [diff] [blame] | 653 | } |
| 654 | |
| 655 | boolean setAppNotIdleConstraintSatisfied(boolean state) { |
| 656 | return setConstraintSatisfied(CONSTRAINT_APP_NOT_IDLE, state); |
| 657 | } |
| 658 | |
| 659 | boolean setContentTriggerConstraintSatisfied(boolean state) { |
| 660 | return setConstraintSatisfied(CONSTRAINT_CONTENT_TRIGGER, state); |
| 661 | } |
| 662 | |
Dianne Hackborn | 7ab4025 | 2016-06-15 17:30:24 -0700 | [diff] [blame] | 663 | boolean setDeviceNotDozingConstraintSatisfied(boolean state, boolean whitelisted) { |
| 664 | dozeWhitelisted = whitelisted; |
Amith Yamasani | cb926fc | 2016-03-14 17:15:20 -0700 | [diff] [blame] | 665 | return setConstraintSatisfied(CONSTRAINT_DEVICE_NOT_DOZING, state); |
| 666 | } |
| 667 | |
Dianne Hackborn | b0001f6 | 2016-02-16 10:30:33 -0800 | [diff] [blame] | 668 | boolean setConstraintSatisfied(int constraint, boolean state) { |
| 669 | boolean old = (satisfiedConstraints&constraint) != 0; |
| 670 | if (old == state) { |
| 671 | return false; |
| 672 | } |
| 673 | satisfiedConstraints = (satisfiedConstraints&~constraint) | (state ? constraint : 0); |
| 674 | return true; |
| 675 | } |
| 676 | |
Dianne Hackborn | e9a988c | 2016-05-27 17:59:40 -0700 | [diff] [blame] | 677 | boolean isConstraintSatisfied(int constraint) { |
| 678 | return (satisfiedConstraints&constraint) != 0; |
| 679 | } |
| 680 | |
Dianne Hackborn | f9bac16 | 2017-04-20 17:17:48 -0700 | [diff] [blame] | 681 | boolean clearTrackingController(int which) { |
| 682 | if ((trackingControllers&which) != 0) { |
| 683 | trackingControllers &= ~which; |
| 684 | return true; |
| 685 | } |
| 686 | return false; |
| 687 | } |
| 688 | |
| 689 | void setTrackingController(int which) { |
| 690 | trackingControllers |= which; |
| 691 | } |
| 692 | |
Makoto Onuki | ab8a67f | 2017-06-20 12:20:34 -0700 | [diff] [blame] | 693 | public long getLastSuccessfulRunTime() { |
| 694 | return mLastSuccessfulRunTime; |
| 695 | } |
| 696 | |
| 697 | public long getLastFailedRunTime() { |
| 698 | return mLastFailedRunTime; |
| 699 | } |
| 700 | |
Dianne Hackborn | ef3aa6e | 2016-04-29 18:18:08 -0700 | [diff] [blame] | 701 | public boolean shouldDump(int filterUid) { |
| 702 | return filterUid == -1 || UserHandle.getAppId(getUid()) == filterUid |
| 703 | || UserHandle.getAppId(getSourceUid()) == filterUid; |
| 704 | } |
| 705 | |
Christopher Tate | 7060b04 | 2014-06-09 19:50:00 -0700 | [diff] [blame] | 706 | /** |
Matthew Williams | 03a4da6 | 2014-09-10 17:32:18 -0700 | [diff] [blame] | 707 | * @return Whether or not this job is ready to run, based on its requirements. This is true if |
| 708 | * the constraints are satisfied <strong>or</strong> the deadline on the job has expired. |
Dianne Hackborn | 28d1b66 | 2017-04-21 14:17:23 -0700 | [diff] [blame] | 709 | * TODO: This function is called a *lot*. We should probably just have it check an |
| 710 | * already-computed boolean, which we updated whenever we see one of the states it depends |
| 711 | * on here change. |
Christopher Tate | 7060b04 | 2014-06-09 19:50:00 -0700 | [diff] [blame] | 712 | */ |
Dianne Hackborn | d506b2b | 2016-02-16 10:30:33 -0800 | [diff] [blame] | 713 | public boolean isReady() { |
Dianne Hackborn | b0001f6 | 2016-02-16 10:30:33 -0800 | [diff] [blame] | 714 | // Deadline constraint trumps other constraints (except for periodic jobs where deadline |
Christopher Tate | 5d34605 | 2016-03-08 12:56:08 -0800 | [diff] [blame] | 715 | // is an implementation detail. A periodic job should only run if its constraints are |
Dianne Hackborn | b0001f6 | 2016-02-16 10:30:33 -0800 | [diff] [blame] | 716 | // satisfied). |
Amith Yamasani | cb926fc | 2016-03-14 17:15:20 -0700 | [diff] [blame] | 717 | // AppNotIdle implicit constraint must be satisfied |
| 718 | // DeviceNotDozing implicit constraint must be satisfied |
Jeff Sharkey | 1b6519b | 2016-04-28 15:33:18 -0600 | [diff] [blame] | 719 | final boolean deadlineSatisfied = (!job.isPeriodic() && hasDeadlineConstraint() |
| 720 | && (satisfiedConstraints & CONSTRAINT_DEADLINE) != 0); |
| 721 | final boolean notIdle = (satisfiedConstraints & CONSTRAINT_APP_NOT_IDLE) != 0; |
| 722 | final boolean notDozing = (satisfiedConstraints & CONSTRAINT_DEVICE_NOT_DOZING) != 0 |
| 723 | || (job.getFlags() & JobInfo.FLAG_WILL_BE_FOREGROUND) != 0; |
| 724 | return (isConstraintsSatisfied() || deadlineSatisfied) && notIdle && notDozing; |
Matthew Williams | 03a4da6 | 2014-09-10 17:32:18 -0700 | [diff] [blame] | 725 | } |
| 726 | |
Dianne Hackborn | b0001f6 | 2016-02-16 10:30:33 -0800 | [diff] [blame] | 727 | static final int CONSTRAINTS_OF_INTEREST = |
Dianne Hackborn | 532ea26 | 2017-03-17 17:50:55 -0700 | [diff] [blame] | 728 | CONSTRAINT_CHARGING | CONSTRAINT_BATTERY_NOT_LOW | CONSTRAINT_STORAGE_NOT_LOW | |
| 729 | CONSTRAINT_TIMING_DELAY | |
Christopher Tate | 06f0852 | 2017-06-13 12:12:09 -0700 | [diff] [blame] | 730 | CONSTRAINT_CONNECTIVITY | CONSTRAINT_UNMETERED | |
| 731 | CONSTRAINT_NOT_ROAMING | CONSTRAINT_METERED | |
Dianne Hackborn | b0001f6 | 2016-02-16 10:30:33 -0800 | [diff] [blame] | 732 | CONSTRAINT_IDLE | CONSTRAINT_CONTENT_TRIGGER; |
| 733 | |
Christopher Tate | 5d34605 | 2016-03-08 12:56:08 -0800 | [diff] [blame] | 734 | // Soft override covers all non-"functional" constraints |
| 735 | static final int SOFT_OVERRIDE_CONSTRAINTS = |
Dianne Hackborn | 532ea26 | 2017-03-17 17:50:55 -0700 | [diff] [blame] | 736 | CONSTRAINT_CHARGING | CONSTRAINT_BATTERY_NOT_LOW | CONSTRAINT_STORAGE_NOT_LOW |
Dianne Hackborn | a06ec6a | 2017-02-13 10:08:42 -0800 | [diff] [blame] | 737 | | CONSTRAINT_TIMING_DELAY | CONSTRAINT_IDLE; |
Christopher Tate | 5d34605 | 2016-03-08 12:56:08 -0800 | [diff] [blame] | 738 | |
Matthew Williams | 03a4da6 | 2014-09-10 17:32:18 -0700 | [diff] [blame] | 739 | /** |
| 740 | * @return Whether the constraints set on this job are satisfied. |
| 741 | */ |
Dianne Hackborn | d506b2b | 2016-02-16 10:30:33 -0800 | [diff] [blame] | 742 | public boolean isConstraintsSatisfied() { |
Christopher Tate | 5d34605 | 2016-03-08 12:56:08 -0800 | [diff] [blame] | 743 | if (overrideState == OVERRIDE_FULL) { |
| 744 | // force override: the job is always runnable |
| 745 | return true; |
| 746 | } |
| 747 | |
Dianne Hackborn | b0001f6 | 2016-02-16 10:30:33 -0800 | [diff] [blame] | 748 | final int req = requiredConstraints & CONSTRAINTS_OF_INTEREST; |
Christopher Tate | 5d34605 | 2016-03-08 12:56:08 -0800 | [diff] [blame] | 749 | |
| 750 | int sat = satisfiedConstraints & CONSTRAINTS_OF_INTEREST; |
| 751 | if (overrideState == OVERRIDE_SOFT) { |
| 752 | // override: pretend all 'soft' requirements are satisfied |
| 753 | sat |= (requiredConstraints & SOFT_OVERRIDE_CONSTRAINTS); |
| 754 | } |
| 755 | |
Dianne Hackborn | b0001f6 | 2016-02-16 10:30:33 -0800 | [diff] [blame] | 756 | return (sat & req) == req; |
Christopher Tate | 7060b04 | 2014-06-09 19:50:00 -0700 | [diff] [blame] | 757 | } |
| 758 | |
| 759 | public boolean matches(int uid, int jobId) { |
Shreyas Basarge | 8e64e2e | 2016-02-12 15:49:31 +0000 | [diff] [blame] | 760 | return this.job.getId() == jobId && this.callingUid == uid; |
Christopher Tate | 7060b04 | 2014-06-09 19:50:00 -0700 | [diff] [blame] | 761 | } |
| 762 | |
| 763 | @Override |
| 764 | public String toString() { |
Dianne Hackborn | a47223f | 2017-03-30 13:49:13 -0700 | [diff] [blame] | 765 | StringBuilder sb = new StringBuilder(128); |
| 766 | sb.append("JobStatus{"); |
| 767 | sb.append(Integer.toHexString(System.identityHashCode(this))); |
| 768 | sb.append(" #"); |
| 769 | UserHandle.formatUid(sb, callingUid); |
| 770 | sb.append("/"); |
| 771 | sb.append(job.getId()); |
| 772 | sb.append(' '); |
| 773 | sb.append(batteryName); |
| 774 | sb.append(" u="); |
| 775 | sb.append(getUserId()); |
| 776 | sb.append(" s="); |
| 777 | sb.append(getSourceUid()); |
| 778 | if (earliestRunTimeElapsedMillis != NO_EARLIEST_RUNTIME |
| 779 | || latestRunTimeElapsedMillis != NO_LATEST_RUNTIME) { |
Dianne Hackborn | bfc2331 | 2017-05-11 11:53:24 -0700 | [diff] [blame] | 780 | long now = SystemClock.elapsedRealtime(); |
Dianne Hackborn | a47223f | 2017-03-30 13:49:13 -0700 | [diff] [blame] | 781 | sb.append(" TIME="); |
Dianne Hackborn | bfc2331 | 2017-05-11 11:53:24 -0700 | [diff] [blame] | 782 | formatRunTime(sb, earliestRunTimeElapsedMillis, NO_EARLIEST_RUNTIME, now); |
| 783 | sb.append(":"); |
| 784 | formatRunTime(sb, latestRunTimeElapsedMillis, NO_LATEST_RUNTIME, now); |
Dianne Hackborn | a47223f | 2017-03-30 13:49:13 -0700 | [diff] [blame] | 785 | } |
| 786 | if (job.getNetworkType() != JobInfo.NETWORK_TYPE_NONE) { |
| 787 | sb.append(" NET="); |
| 788 | sb.append(job.getNetworkType()); |
| 789 | } |
| 790 | if (job.isRequireCharging()) { |
| 791 | sb.append(" CHARGING"); |
| 792 | } |
| 793 | if (job.isRequireBatteryNotLow()) { |
| 794 | sb.append(" BATNOTLOW"); |
| 795 | } |
| 796 | if (job.isRequireStorageNotLow()) { |
| 797 | sb.append(" STORENOTLOW"); |
| 798 | } |
| 799 | if (job.isRequireDeviceIdle()) { |
| 800 | sb.append(" IDLE"); |
| 801 | } |
| 802 | if (job.isPersisted()) { |
| 803 | sb.append(" PERSISTED"); |
| 804 | } |
| 805 | if ((satisfiedConstraints&CONSTRAINT_APP_NOT_IDLE) == 0) { |
| 806 | sb.append(" WAIT:APP_NOT_IDLE"); |
| 807 | } |
| 808 | if ((satisfiedConstraints&CONSTRAINT_DEVICE_NOT_DOZING) == 0) { |
| 809 | sb.append(" WAIT:DEV_NOT_DOZING"); |
| 810 | } |
| 811 | if (job.getTriggerContentUris() != null) { |
| 812 | sb.append(" URIS="); |
| 813 | sb.append(Arrays.toString(job.getTriggerContentUris())); |
| 814 | } |
| 815 | if (numFailures != 0) { |
| 816 | sb.append(" failures="); |
| 817 | sb.append(numFailures); |
| 818 | } |
| 819 | if (isReady()) { |
| 820 | sb.append(" READY"); |
| 821 | } |
| 822 | sb.append("}"); |
| 823 | return sb.toString(); |
Christopher Tate | 7060b04 | 2014-06-09 19:50:00 -0700 | [diff] [blame] | 824 | } |
Matthew Williams | 9ae3dbe | 2014-08-21 13:47:47 -0700 | [diff] [blame] | 825 | |
Dianne Hackborn | bfc2331 | 2017-05-11 11:53:24 -0700 | [diff] [blame] | 826 | private void formatRunTime(PrintWriter pw, long runtime, long defaultValue, long now) { |
Matthew Williams | 9ae3dbe | 2014-08-21 13:47:47 -0700 | [diff] [blame] | 827 | if (runtime == defaultValue) { |
Dianne Hackborn | bfc2331 | 2017-05-11 11:53:24 -0700 | [diff] [blame] | 828 | pw.print("none"); |
Matthew Williams | 9ae3dbe | 2014-08-21 13:47:47 -0700 | [diff] [blame] | 829 | } else { |
Dianne Hackborn | bfc2331 | 2017-05-11 11:53:24 -0700 | [diff] [blame] | 830 | TimeUtils.formatDuration(runtime - now, pw); |
| 831 | } |
| 832 | } |
| 833 | |
| 834 | private void formatRunTime(StringBuilder sb, long runtime, long defaultValue, long now) { |
| 835 | if (runtime == defaultValue) { |
| 836 | sb.append("none"); |
| 837 | } else { |
| 838 | TimeUtils.formatDuration(runtime - now, sb); |
Matthew Williams | 9ae3dbe | 2014-08-21 13:47:47 -0700 | [diff] [blame] | 839 | } |
| 840 | } |
| 841 | |
| 842 | /** |
| 843 | * Convenience function to identify a job uniquely without pulling all the data that |
| 844 | * {@link #toString()} returns. |
| 845 | */ |
| 846 | public String toShortString() { |
Dianne Hackborn | 1a30bd9 | 2016-01-11 11:05:00 -0800 | [diff] [blame] | 847 | StringBuilder sb = new StringBuilder(); |
| 848 | sb.append(Integer.toHexString(System.identityHashCode(this))); |
Dianne Hackborn | e9a988c | 2016-05-27 17:59:40 -0700 | [diff] [blame] | 849 | sb.append(" #"); |
| 850 | UserHandle.formatUid(sb, callingUid); |
| 851 | sb.append("/"); |
Dianne Hackborn | 1a30bd9 | 2016-01-11 11:05:00 -0800 | [diff] [blame] | 852 | sb.append(job.getId()); |
Dianne Hackborn | 970510b | 2016-02-24 16:56:42 -0800 | [diff] [blame] | 853 | sb.append(' '); |
Dianne Hackborn | e9a988c | 2016-05-27 17:59:40 -0700 | [diff] [blame] | 854 | sb.append(batteryName); |
| 855 | return sb.toString(); |
| 856 | } |
| 857 | |
| 858 | /** |
| 859 | * Convenience function to identify a job uniquely without pulling all the data that |
| 860 | * {@link #toString()} returns. |
| 861 | */ |
| 862 | public String toShortStringExceptUniqueId() { |
| 863 | StringBuilder sb = new StringBuilder(); |
| 864 | sb.append(Integer.toHexString(System.identityHashCode(this))); |
Dianne Hackborn | 1a30bd9 | 2016-01-11 11:05:00 -0800 | [diff] [blame] | 865 | sb.append(' '); |
Dianne Hackborn | 970510b | 2016-02-24 16:56:42 -0800 | [diff] [blame] | 866 | sb.append(batteryName); |
Dianne Hackborn | 1a30bd9 | 2016-01-11 11:05:00 -0800 | [diff] [blame] | 867 | return sb.toString(); |
Matthew Williams | 9ae3dbe | 2014-08-21 13:47:47 -0700 | [diff] [blame] | 868 | } |
| 869 | |
Dianne Hackborn | b0001f6 | 2016-02-16 10:30:33 -0800 | [diff] [blame] | 870 | void dumpConstraints(PrintWriter pw, int constraints) { |
| 871 | if ((constraints&CONSTRAINT_CHARGING) != 0) { |
| 872 | pw.print(" CHARGING"); |
| 873 | } |
Dianne Hackborn | a06ec6a | 2017-02-13 10:08:42 -0800 | [diff] [blame] | 874 | if ((constraints& CONSTRAINT_BATTERY_NOT_LOW) != 0) { |
| 875 | pw.print(" BATTERY_NOT_LOW"); |
| 876 | } |
Dianne Hackborn | 532ea26 | 2017-03-17 17:50:55 -0700 | [diff] [blame] | 877 | if ((constraints& CONSTRAINT_STORAGE_NOT_LOW) != 0) { |
| 878 | pw.print(" STORAGE_NOT_LOW"); |
| 879 | } |
Dianne Hackborn | b0001f6 | 2016-02-16 10:30:33 -0800 | [diff] [blame] | 880 | if ((constraints&CONSTRAINT_TIMING_DELAY) != 0) { |
| 881 | pw.print(" TIMING_DELAY"); |
| 882 | } |
| 883 | if ((constraints&CONSTRAINT_DEADLINE) != 0) { |
| 884 | pw.print(" DEADLINE"); |
| 885 | } |
| 886 | if ((constraints&CONSTRAINT_IDLE) != 0) { |
| 887 | pw.print(" IDLE"); |
| 888 | } |
Jeff Sharkey | f07c7b9 | 2016-04-22 09:50:16 -0600 | [diff] [blame] | 889 | if ((constraints&CONSTRAINT_CONNECTIVITY) != 0) { |
| 890 | pw.print(" CONNECTIVITY"); |
| 891 | } |
Dianne Hackborn | b0001f6 | 2016-02-16 10:30:33 -0800 | [diff] [blame] | 892 | if ((constraints&CONSTRAINT_UNMETERED) != 0) { |
| 893 | pw.print(" UNMETERED"); |
| 894 | } |
Jeff Sharkey | f07c7b9 | 2016-04-22 09:50:16 -0600 | [diff] [blame] | 895 | if ((constraints&CONSTRAINT_NOT_ROAMING) != 0) { |
| 896 | pw.print(" NOT_ROAMING"); |
Dianne Hackborn | b0001f6 | 2016-02-16 10:30:33 -0800 | [diff] [blame] | 897 | } |
Christopher Tate | 06f0852 | 2017-06-13 12:12:09 -0700 | [diff] [blame] | 898 | if ((constraints&CONSTRAINT_METERED) != 0) { |
| 899 | pw.print(" METERED"); |
| 900 | } |
Dianne Hackborn | b0001f6 | 2016-02-16 10:30:33 -0800 | [diff] [blame] | 901 | if ((constraints&CONSTRAINT_APP_NOT_IDLE) != 0) { |
| 902 | pw.print(" APP_NOT_IDLE"); |
| 903 | } |
| 904 | if ((constraints&CONSTRAINT_CONTENT_TRIGGER) != 0) { |
| 905 | pw.print(" CONTENT_TRIGGER"); |
| 906 | } |
Amith Yamasani | cb926fc | 2016-03-14 17:15:20 -0700 | [diff] [blame] | 907 | if ((constraints&CONSTRAINT_DEVICE_NOT_DOZING) != 0) { |
| 908 | pw.print(" DEVICE_NOT_DOZING"); |
| 909 | } |
Dianne Hackborn | b0001f6 | 2016-02-16 10:30:33 -0800 | [diff] [blame] | 910 | } |
| 911 | |
Dianne Hackborn | 342e603 | 2017-04-13 18:04:31 -0700 | [diff] [blame] | 912 | private void dumpJobWorkItem(PrintWriter pw, String prefix, JobWorkItem work, int index) { |
| 913 | pw.print(prefix); pw.print(" #"); pw.print(index); pw.print(": #"); |
Dianne Hackborn | 28d1b66 | 2017-04-21 14:17:23 -0700 | [diff] [blame] | 914 | pw.print(work.getWorkId()); pw.print(" "); pw.print(work.getDeliveryCount()); |
| 915 | pw.print("x "); pw.println(work.getIntent()); |
Dianne Hackborn | 342e603 | 2017-04-13 18:04:31 -0700 | [diff] [blame] | 916 | if (work.getGrants() != null) { |
| 917 | pw.print(prefix); pw.println(" URI grants:"); |
| 918 | ((GrantedUriPermissions)work.getGrants()).dump(pw, prefix + " "); |
| 919 | } |
| 920 | } |
| 921 | |
Christopher Tate | 7060b04 | 2014-06-09 19:50:00 -0700 | [diff] [blame] | 922 | // Dumpsys infrastructure |
Dianne Hackborn | bfc2331 | 2017-05-11 11:53:24 -0700 | [diff] [blame] | 923 | public void dump(PrintWriter pw, String prefix, boolean full, long elapsedRealtimeMillis) { |
Shreyas Basarge | 8e64e2e | 2016-02-12 15:49:31 +0000 | [diff] [blame] | 924 | pw.print(prefix); UserHandle.formatUid(pw, callingUid); |
Dianne Hackborn | 1a30bd9 | 2016-01-11 11:05:00 -0800 | [diff] [blame] | 925 | pw.print(" tag="); pw.println(tag); |
Christopher Tate | f973a7b | 2014-08-29 12:54:08 -0700 | [diff] [blame] | 926 | pw.print(prefix); |
Shreyas Basarge | d8bf6b9 | 2016-02-02 23:45:14 +0000 | [diff] [blame] | 927 | pw.print("Source: uid="); UserHandle.formatUid(pw, getSourceUid()); |
| 928 | pw.print(" user="); pw.print(getSourceUserId()); |
| 929 | pw.print(" pkg="); pw.println(getSourcePackageName()); |
Dianne Hackborn | 970510b | 2016-02-24 16:56:42 -0800 | [diff] [blame] | 930 | if (full) { |
Dianne Hackborn | a47223f | 2017-03-30 13:49:13 -0700 | [diff] [blame] | 931 | pw.print(prefix); pw.println("JobInfo:"); |
| 932 | pw.print(prefix); pw.print(" Service: "); |
| 933 | pw.println(job.getService().flattenToShortString()); |
Dianne Hackborn | 970510b | 2016-02-24 16:56:42 -0800 | [diff] [blame] | 934 | if (job.isPeriodic()) { |
| 935 | pw.print(prefix); pw.print(" PERIODIC: interval="); |
| 936 | TimeUtils.formatDuration(job.getIntervalMillis(), pw); |
| 937 | pw.print(" flex="); TimeUtils.formatDuration(job.getFlexMillis(), pw); |
| 938 | pw.println(); |
Dianne Hackborn | 1a30bd9 | 2016-01-11 11:05:00 -0800 | [diff] [blame] | 939 | } |
Dianne Hackborn | 970510b | 2016-02-24 16:56:42 -0800 | [diff] [blame] | 940 | if (job.isPersisted()) { |
| 941 | pw.print(prefix); pw.println(" PERSISTED"); |
| 942 | } |
| 943 | if (job.getPriority() != 0) { |
| 944 | pw.print(prefix); pw.print(" Priority: "); pw.println(job.getPriority()); |
| 945 | } |
Jeff Sharkey | 1b6519b | 2016-04-28 15:33:18 -0600 | [diff] [blame] | 946 | if (job.getFlags() != 0) { |
| 947 | pw.print(prefix); pw.print(" Flags: "); |
| 948 | pw.println(Integer.toHexString(job.getFlags())); |
| 949 | } |
Dianne Hackborn | 970510b | 2016-02-24 16:56:42 -0800 | [diff] [blame] | 950 | pw.print(prefix); pw.print(" Requires: charging="); |
Dianne Hackborn | a06ec6a | 2017-02-13 10:08:42 -0800 | [diff] [blame] | 951 | pw.print(job.isRequireCharging()); pw.print(" batteryNotLow="); |
| 952 | pw.print(job.isRequireBatteryNotLow()); pw.print(" deviceIdle="); |
Dianne Hackborn | 970510b | 2016-02-24 16:56:42 -0800 | [diff] [blame] | 953 | pw.println(job.isRequireDeviceIdle()); |
| 954 | if (job.getTriggerContentUris() != null) { |
| 955 | pw.print(prefix); pw.println(" Trigger content URIs:"); |
| 956 | for (int i = 0; i < job.getTriggerContentUris().length; i++) { |
| 957 | JobInfo.TriggerContentUri trig = job.getTriggerContentUris()[i]; |
| 958 | pw.print(prefix); pw.print(" "); |
| 959 | pw.print(Integer.toHexString(trig.getFlags())); |
| 960 | pw.print(' '); pw.println(trig.getUri()); |
| 961 | } |
Dianne Hackborn | 8db0fc1 | 2016-04-12 13:48:25 -0700 | [diff] [blame] | 962 | if (job.getTriggerContentUpdateDelay() >= 0) { |
| 963 | pw.print(prefix); pw.print(" Trigger update delay: "); |
| 964 | TimeUtils.formatDuration(job.getTriggerContentUpdateDelay(), pw); |
| 965 | pw.println(); |
| 966 | } |
| 967 | if (job.getTriggerContentMaxDelay() >= 0) { |
| 968 | pw.print(prefix); pw.print(" Trigger max delay: "); |
| 969 | TimeUtils.formatDuration(job.getTriggerContentMaxDelay(), pw); |
| 970 | pw.println(); |
| 971 | } |
Dianne Hackborn | 970510b | 2016-02-24 16:56:42 -0800 | [diff] [blame] | 972 | } |
Dianne Hackborn | a47223f | 2017-03-30 13:49:13 -0700 | [diff] [blame] | 973 | if (job.getExtras() != null && !job.getExtras().maybeIsEmpty()) { |
| 974 | pw.print(prefix); pw.print(" Extras: "); |
| 975 | pw.println(job.getExtras().toShortString()); |
| 976 | } |
| 977 | if (job.getTransientExtras() != null && !job.getTransientExtras().maybeIsEmpty()) { |
| 978 | pw.print(prefix); pw.print(" Transient extras: "); |
| 979 | pw.println(job.getTransientExtras().toShortString()); |
| 980 | } |
| 981 | if (job.getClipData() != null) { |
| 982 | pw.print(prefix); pw.print(" Clip data: "); |
| 983 | StringBuilder b = new StringBuilder(128); |
| 984 | job.getClipData().toShortString(b); |
| 985 | pw.println(b); |
| 986 | } |
Dianne Hackborn | 342e603 | 2017-04-13 18:04:31 -0700 | [diff] [blame] | 987 | if (uriPerms != null) { |
| 988 | pw.print(prefix); pw.println(" Granted URI permissions:"); |
| 989 | uriPerms.dump(pw, prefix + " "); |
| 990 | } |
Dianne Hackborn | 970510b | 2016-02-24 16:56:42 -0800 | [diff] [blame] | 991 | if (job.getNetworkType() != JobInfo.NETWORK_TYPE_NONE) { |
| 992 | pw.print(prefix); pw.print(" Network type: "); pw.println(job.getNetworkType()); |
| 993 | } |
| 994 | if (job.getMinLatencyMillis() != 0) { |
| 995 | pw.print(prefix); pw.print(" Minimum latency: "); |
| 996 | TimeUtils.formatDuration(job.getMinLatencyMillis(), pw); |
| 997 | pw.println(); |
| 998 | } |
| 999 | if (job.getMaxExecutionDelayMillis() != 0) { |
| 1000 | pw.print(prefix); pw.print(" Max execution delay: "); |
| 1001 | TimeUtils.formatDuration(job.getMaxExecutionDelayMillis(), pw); |
| 1002 | pw.println(); |
| 1003 | } |
| 1004 | pw.print(prefix); pw.print(" Backoff: policy="); pw.print(job.getBackoffPolicy()); |
| 1005 | pw.print(" initial="); TimeUtils.formatDuration(job.getInitialBackoffMillis(), pw); |
Dianne Hackborn | 1a30bd9 | 2016-01-11 11:05:00 -0800 | [diff] [blame] | 1006 | pw.println(); |
Dianne Hackborn | 970510b | 2016-02-24 16:56:42 -0800 | [diff] [blame] | 1007 | if (job.hasEarlyConstraint()) { |
| 1008 | pw.print(prefix); pw.println(" Has early constraint"); |
| 1009 | } |
| 1010 | if (job.hasLateConstraint()) { |
| 1011 | pw.print(prefix); pw.println(" Has late constraint"); |
| 1012 | } |
Dianne Hackborn | 1a30bd9 | 2016-01-11 11:05:00 -0800 | [diff] [blame] | 1013 | } |
Dianne Hackborn | b0001f6 | 2016-02-16 10:30:33 -0800 | [diff] [blame] | 1014 | pw.print(prefix); pw.print("Required constraints:"); |
| 1015 | dumpConstraints(pw, requiredConstraints); |
| 1016 | pw.println(); |
Dianne Hackborn | 970510b | 2016-02-24 16:56:42 -0800 | [diff] [blame] | 1017 | if (full) { |
| 1018 | pw.print(prefix); pw.print("Satisfied constraints:"); |
| 1019 | dumpConstraints(pw, satisfiedConstraints); |
| 1020 | pw.println(); |
Jeff Sharkey | 1b6519b | 2016-04-28 15:33:18 -0600 | [diff] [blame] | 1021 | pw.print(prefix); pw.print("Unsatisfied constraints:"); |
| 1022 | dumpConstraints(pw, (requiredConstraints & ~satisfiedConstraints)); |
| 1023 | pw.println(); |
Dianne Hackborn | 7ab4025 | 2016-06-15 17:30:24 -0700 | [diff] [blame] | 1024 | if (dozeWhitelisted) { |
| 1025 | pw.print(prefix); pw.println("Doze whitelisted: true"); |
| 1026 | } |
Dianne Hackborn | 970510b | 2016-02-24 16:56:42 -0800 | [diff] [blame] | 1027 | } |
Dianne Hackborn | f9bac16 | 2017-04-20 17:17:48 -0700 | [diff] [blame] | 1028 | if (trackingControllers != 0) { |
| 1029 | pw.print(prefix); pw.print("Tracking:"); |
| 1030 | if ((trackingControllers&TRACKING_BATTERY) != 0) pw.print(" BATTERY"); |
| 1031 | if ((trackingControllers&TRACKING_CONNECTIVITY) != 0) pw.print(" CONNECTIVITY"); |
| 1032 | if ((trackingControllers&TRACKING_CONTENT) != 0) pw.print(" CONTENT"); |
| 1033 | if ((trackingControllers&TRACKING_IDLE) != 0) pw.print(" IDLE"); |
| 1034 | if ((trackingControllers&TRACKING_STORAGE) != 0) pw.print(" STORAGE"); |
| 1035 | if ((trackingControllers&TRACKING_TIME) != 0) pw.print(" TIME"); |
| 1036 | pw.println(); |
| 1037 | } |
Dianne Hackborn | 1a30bd9 | 2016-01-11 11:05:00 -0800 | [diff] [blame] | 1038 | if (changedAuthorities != null) { |
| 1039 | pw.print(prefix); pw.println("Changed authorities:"); |
| 1040 | for (int i=0; i<changedAuthorities.size(); i++) { |
| 1041 | pw.print(prefix); pw.print(" "); pw.println(changedAuthorities.valueAt(i)); |
| 1042 | } |
| 1043 | if (changedUris != null) { |
| 1044 | pw.print(prefix); pw.println("Changed URIs:"); |
| 1045 | for (int i=0; i<changedUris.size(); i++) { |
| 1046 | pw.print(prefix); pw.print(" "); pw.println(changedUris.valueAt(i)); |
| 1047 | } |
| 1048 | } |
| 1049 | } |
Dianne Hackborn | 7da13d7 | 2017-04-04 17:17:35 -0700 | [diff] [blame] | 1050 | if (pendingWork != null && pendingWork.size() > 0) { |
| 1051 | pw.print(prefix); pw.println("Pending work:"); |
| 1052 | for (int i = 0; i < pendingWork.size(); i++) { |
Dianne Hackborn | 342e603 | 2017-04-13 18:04:31 -0700 | [diff] [blame] | 1053 | dumpJobWorkItem(pw, prefix, pendingWork.get(i), i); |
Dianne Hackborn | 7da13d7 | 2017-04-04 17:17:35 -0700 | [diff] [blame] | 1054 | } |
| 1055 | } |
| 1056 | if (executingWork != null && executingWork.size() > 0) { |
| 1057 | pw.print(prefix); pw.println("Executing work:"); |
| 1058 | for (int i = 0; i < executingWork.size(); i++) { |
Dianne Hackborn | 342e603 | 2017-04-13 18:04:31 -0700 | [diff] [blame] | 1059 | dumpJobWorkItem(pw, prefix, executingWork.get(i), i); |
Dianne Hackborn | 7da13d7 | 2017-04-04 17:17:35 -0700 | [diff] [blame] | 1060 | } |
| 1061 | } |
Dianne Hackborn | bfc2331 | 2017-05-11 11:53:24 -0700 | [diff] [blame] | 1062 | pw.print(prefix); pw.print("Enqueue time: "); |
| 1063 | TimeUtils.formatDuration(enqueueTime, elapsedRealtimeMillis, pw); |
| 1064 | pw.println(); |
| 1065 | pw.print(prefix); pw.print("Run time: earliest="); |
| 1066 | formatRunTime(pw, earliestRunTimeElapsedMillis, NO_EARLIEST_RUNTIME, elapsedRealtimeMillis); |
| 1067 | pw.print(", latest="); |
| 1068 | formatRunTime(pw, latestRunTimeElapsedMillis, NO_LATEST_RUNTIME, elapsedRealtimeMillis); |
| 1069 | pw.println(); |
Dianne Hackborn | 1a30bd9 | 2016-01-11 11:05:00 -0800 | [diff] [blame] | 1070 | if (numFailures != 0) { |
| 1071 | pw.print(prefix); pw.print("Num failures: "); pw.println(numFailures); |
| 1072 | } |
Makoto Onuki | ab8a67f | 2017-06-20 12:20:34 -0700 | [diff] [blame] | 1073 | final Time t = new Time(); |
| 1074 | final String format = "%Y-%m-%d %H:%M:%S"; |
| 1075 | if (mLastSuccessfulRunTime != 0) { |
| 1076 | pw.print(prefix); pw.print("Last successful run: "); |
| 1077 | t.set(mLastSuccessfulRunTime); |
| 1078 | pw.println(t.format(format)); |
| 1079 | } |
| 1080 | if (mLastFailedRunTime != 0) { |
| 1081 | pw.print(prefix); pw.print("Last failed run: "); |
| 1082 | t.set(mLastFailedRunTime); |
| 1083 | pw.println(t.format(format)); |
| 1084 | } |
Christopher Tate | 7060b04 | 2014-06-09 19:50:00 -0700 | [diff] [blame] | 1085 | } |
| 1086 | } |