Sumir Kataria | 15f793d | 2017-12-18 13:30:46 -0800 | [diff] [blame] | 1 | /* |
Rahul Ravikumar | 87d37e5 | 2018-01-04 18:18:29 -0800 | [diff] [blame] | 2 | * Copyright 2018 The Android Open Source Project |
Sumir Kataria | 15f793d | 2017-12-18 13:30:46 -0800 | [diff] [blame] | 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 | |
Sumir Kataria | 564e430 | 2018-02-14 11:22:30 -0800 | [diff] [blame] | 17 | package androidx.work.impl.utils; |
Sumir Kataria | 15f793d | 2017-12-18 13:30:46 -0800 | [diff] [blame] | 18 | |
Sumir Kataria | 564e430 | 2018-02-14 11:22:30 -0800 | [diff] [blame] | 19 | import static androidx.work.ExistingWorkPolicy.APPEND; |
| 20 | import static androidx.work.ExistingWorkPolicy.KEEP; |
| 21 | import static androidx.work.State.BLOCKED; |
Sumir Kataria | 84354e3 | 2018-03-07 15:30:16 -0800 | [diff] [blame] | 22 | import static androidx.work.State.CANCELLED; |
Sumir Kataria | 564e430 | 2018-02-14 11:22:30 -0800 | [diff] [blame] | 23 | import static androidx.work.State.ENQUEUED; |
Sumir Kataria | 84354e3 | 2018-03-07 15:30:16 -0800 | [diff] [blame] | 24 | import static androidx.work.State.FAILED; |
Sumir Kataria | 564e430 | 2018-02-14 11:22:30 -0800 | [diff] [blame] | 25 | import static androidx.work.State.RUNNING; |
| 26 | import static androidx.work.State.SUCCEEDED; |
Sumir Kataria | 31099f8 | 2018-03-16 16:17:36 -0700 | [diff] [blame] | 27 | import static androidx.work.impl.workers.ConstraintTrackingWorker.ARGUMENT_CLASS_NAME; |
Sumir Kataria | 15f793d | 2017-12-18 13:30:46 -0800 | [diff] [blame] | 28 | |
Sumir Kataria | 31099f8 | 2018-03-16 16:17:36 -0700 | [diff] [blame] | 29 | import android.os.Build; |
Sumir Kataria | 15f793d | 2017-12-18 13:30:46 -0800 | [diff] [blame] | 30 | import android.support.annotation.NonNull; |
| 31 | import android.support.annotation.RestrictTo; |
Rahul Ravikumar | c342d15 | 2018-01-05 12:10:04 -0800 | [diff] [blame] | 32 | import android.support.annotation.VisibleForTesting; |
Sumir Kataria | 4b59a5f | 2017-12-18 09:46:37 -0800 | [diff] [blame] | 33 | import android.text.TextUtils; |
Rahul Ravikumar | 697d6a4 | 2018-04-16 15:44:09 -0700 | [diff] [blame] | 34 | import android.util.Log; |
Sumir Kataria | 4b59a5f | 2017-12-18 09:46:37 -0800 | [diff] [blame] | 35 | |
Sumir Kataria | 31099f8 | 2018-03-16 16:17:36 -0700 | [diff] [blame] | 36 | import androidx.work.Constraints; |
Sumir Kataria | 64e6bd8 | 2018-03-28 17:14:22 -0700 | [diff] [blame] | 37 | import androidx.work.Data; |
Sumir Kataria | 564e430 | 2018-02-14 11:22:30 -0800 | [diff] [blame] | 38 | import androidx.work.ExistingWorkPolicy; |
Sumir Kataria | 84354e3 | 2018-03-07 15:30:16 -0800 | [diff] [blame] | 39 | import androidx.work.State; |
Rahul Ravikumar | 7031a0f | 2018-04-19 14:24:30 -0700 | [diff] [blame] | 40 | import androidx.work.WorkRequest; |
Rahul Ravikumar | 9f91ee8 | 2018-03-20 17:33:38 -0700 | [diff] [blame] | 41 | import androidx.work.impl.Schedulers; |
Sumir Kataria | 564e430 | 2018-02-14 11:22:30 -0800 | [diff] [blame] | 42 | import androidx.work.impl.WorkContinuationImpl; |
| 43 | import androidx.work.impl.WorkDatabase; |
| 44 | import androidx.work.impl.WorkManagerImpl; |
Sumir Kataria | 564e430 | 2018-02-14 11:22:30 -0800 | [diff] [blame] | 45 | import androidx.work.impl.model.Dependency; |
| 46 | import androidx.work.impl.model.DependencyDao; |
Sumir Kataria | 3665b82 | 2018-03-12 16:43:01 -0700 | [diff] [blame] | 47 | import androidx.work.impl.model.WorkName; |
Sumir Kataria | 564e430 | 2018-02-14 11:22:30 -0800 | [diff] [blame] | 48 | import androidx.work.impl.model.WorkSpec; |
| 49 | import androidx.work.impl.model.WorkSpecDao; |
| 50 | import androidx.work.impl.model.WorkTag; |
Sumir Kataria | 31099f8 | 2018-03-16 16:17:36 -0700 | [diff] [blame] | 51 | import androidx.work.impl.workers.ConstraintTrackingWorker; |
| 52 | |
| 53 | import java.util.ArrayList; |
Sumir Kataria | 31099f8 | 2018-03-16 16:17:36 -0700 | [diff] [blame] | 54 | import java.util.List; |
| 55 | import java.util.Set; |
Sumir Kataria | 564e430 | 2018-02-14 11:22:30 -0800 | [diff] [blame] | 56 | |
Sumir Kataria | 15f793d | 2017-12-18 13:30:46 -0800 | [diff] [blame] | 57 | /** |
Rahul Ravikumar | 87d37e5 | 2018-01-04 18:18:29 -0800 | [diff] [blame] | 58 | * Manages the enqueuing of a {@link WorkContinuationImpl}. |
Sumir Kataria | 15f793d | 2017-12-18 13:30:46 -0800 | [diff] [blame] | 59 | * |
| 60 | * @hide |
| 61 | */ |
| 62 | @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP) |
| 63 | public class EnqueueRunnable implements Runnable { |
| 64 | |
Sumir Kataria | 4b59a5f | 2017-12-18 09:46:37 -0800 | [diff] [blame] | 65 | private static final String TAG = "EnqueueRunnable"; |
| 66 | |
Rahul Ravikumar | 87d37e5 | 2018-01-04 18:18:29 -0800 | [diff] [blame] | 67 | private final WorkContinuationImpl mWorkContinuation; |
Sumir Kataria | 15f793d | 2017-12-18 13:30:46 -0800 | [diff] [blame] | 68 | |
Rahul Ravikumar | 87d37e5 | 2018-01-04 18:18:29 -0800 | [diff] [blame] | 69 | public EnqueueRunnable(@NonNull WorkContinuationImpl workContinuation) { |
| 70 | mWorkContinuation = workContinuation; |
| 71 | } |
| 72 | |
| 73 | @Override |
| 74 | public void run() { |
Rahul Ravikumar | 2ca6b2d | 2018-03-27 17:31:12 -0700 | [diff] [blame] | 75 | if (mWorkContinuation.hasCycles()) { |
| 76 | throw new IllegalStateException( |
| 77 | String.format("WorkContinuation has cycles (%s)", mWorkContinuation)); |
| 78 | } |
Rahul Ravikumar | 9f91ee8 | 2018-03-20 17:33:38 -0700 | [diff] [blame] | 79 | boolean needsScheduling = addToDatabase(); |
| 80 | if (needsScheduling) { |
| 81 | scheduleWorkInBackground(); |
| 82 | } |
Rahul Ravikumar | c342d15 | 2018-01-05 12:10:04 -0800 | [diff] [blame] | 83 | } |
| 84 | |
| 85 | /** |
| 86 | * Adds the {@link WorkSpec}'s to the datastore, parent first. |
| 87 | * Schedules work on the background scheduler, if transaction is successful. |
| 88 | */ |
| 89 | @VisibleForTesting |
Rahul Ravikumar | 9f91ee8 | 2018-03-20 17:33:38 -0700 | [diff] [blame] | 90 | public boolean addToDatabase() { |
Rahul Ravikumar | 87d37e5 | 2018-01-04 18:18:29 -0800 | [diff] [blame] | 91 | WorkManagerImpl workManagerImpl = mWorkContinuation.getWorkManagerImpl(); |
| 92 | WorkDatabase workDatabase = workManagerImpl.getWorkDatabase(); |
| 93 | workDatabase.beginTransaction(); |
| 94 | try { |
Rahul Ravikumar | 9f91ee8 | 2018-03-20 17:33:38 -0700 | [diff] [blame] | 95 | boolean needsScheduling = processContinuation(mWorkContinuation); |
Rahul Ravikumar | 87d37e5 | 2018-01-04 18:18:29 -0800 | [diff] [blame] | 96 | workDatabase.setTransactionSuccessful(); |
Rahul Ravikumar | 9f91ee8 | 2018-03-20 17:33:38 -0700 | [diff] [blame] | 97 | return needsScheduling; |
Rahul Ravikumar | 87d37e5 | 2018-01-04 18:18:29 -0800 | [diff] [blame] | 98 | } finally { |
| 99 | workDatabase.endTransaction(); |
| 100 | } |
| 101 | } |
| 102 | |
Rahul Ravikumar | c342d15 | 2018-01-05 12:10:04 -0800 | [diff] [blame] | 103 | /** |
| 104 | * Schedules work on the background scheduler. |
| 105 | */ |
| 106 | @VisibleForTesting |
| 107 | public void scheduleWorkInBackground() { |
Rahul Ravikumar | 9f91ee8 | 2018-03-20 17:33:38 -0700 | [diff] [blame] | 108 | WorkManagerImpl workManager = mWorkContinuation.getWorkManagerImpl(); |
| 109 | Schedulers.schedule(workManager.getWorkDatabase(), workManager.getSchedulers()); |
Rahul Ravikumar | c342d15 | 2018-01-05 12:10:04 -0800 | [diff] [blame] | 110 | } |
| 111 | |
Rahul Ravikumar | 9f91ee8 | 2018-03-20 17:33:38 -0700 | [diff] [blame] | 112 | private static boolean processContinuation(@NonNull WorkContinuationImpl workContinuation) { |
Rahul Ravikumar | 0c252a2 | 2018-04-06 16:07:11 -0700 | [diff] [blame] | 113 | boolean needsScheduling = false; |
Rahul Ravikumar | 59cbb57 | 2018-01-10 09:41:16 -0800 | [diff] [blame] | 114 | List<WorkContinuationImpl> parents = workContinuation.getParents(); |
| 115 | if (parents != null) { |
| 116 | for (WorkContinuationImpl parent : parents) { |
| 117 | // When chaining off a completed continuation we need to pay |
| 118 | // attention to parents that may have been marked as enqueued before. |
| 119 | if (!parent.isEnqueued()) { |
Rahul Ravikumar | 0c252a2 | 2018-04-06 16:07:11 -0700 | [diff] [blame] | 120 | needsScheduling |= processContinuation(parent); |
Rahul Ravikumar | 59cbb57 | 2018-01-10 09:41:16 -0800 | [diff] [blame] | 121 | } else { |
Rahul Ravikumar | 697d6a4 | 2018-04-16 15:44:09 -0700 | [diff] [blame] | 122 | Log.w(TAG, String.format("Already enqueued work ids (%s).", |
| 123 | TextUtils.join(", ", parent.getIds()))); |
Rahul Ravikumar | 59cbb57 | 2018-01-10 09:41:16 -0800 | [diff] [blame] | 124 | } |
Rahul Ravikumar | 87d37e5 | 2018-01-04 18:18:29 -0800 | [diff] [blame] | 125 | } |
Rahul Ravikumar | 87d37e5 | 2018-01-04 18:18:29 -0800 | [diff] [blame] | 126 | } |
Rahul Ravikumar | 0c252a2 | 2018-04-06 16:07:11 -0700 | [diff] [blame] | 127 | needsScheduling |= enqueueContinuation(workContinuation); |
| 128 | return needsScheduling; |
Rahul Ravikumar | 87d37e5 | 2018-01-04 18:18:29 -0800 | [diff] [blame] | 129 | } |
| 130 | |
Rahul Ravikumar | 9f91ee8 | 2018-03-20 17:33:38 -0700 | [diff] [blame] | 131 | private static boolean enqueueContinuation(@NonNull WorkContinuationImpl workContinuation) { |
Rahul Ravikumar | 2ca6b2d | 2018-03-27 17:31:12 -0700 | [diff] [blame] | 132 | Set<String> prerequisiteIds = WorkContinuationImpl.prerequisitesFor(workContinuation); |
Rahul Ravikumar | 87d37e5 | 2018-01-04 18:18:29 -0800 | [diff] [blame] | 133 | |
Rahul Ravikumar | 9f91ee8 | 2018-03-20 17:33:38 -0700 | [diff] [blame] | 134 | boolean needsScheduling = enqueueWorkWithPrerequisites( |
Rahul Ravikumar | 87d37e5 | 2018-01-04 18:18:29 -0800 | [diff] [blame] | 135 | workContinuation.getWorkManagerImpl(), |
| 136 | workContinuation.getWork(), |
Rahul Ravikumar | 59cbb57 | 2018-01-10 09:41:16 -0800 | [diff] [blame] | 137 | prerequisiteIds.toArray(new String[0]), |
Sumir Kataria | 3665b82 | 2018-03-12 16:43:01 -0700 | [diff] [blame] | 138 | workContinuation.getName(), |
Rahul Ravikumar | 9f91ee8 | 2018-03-20 17:33:38 -0700 | [diff] [blame] | 139 | workContinuation.getExistingWorkPolicy()); |
Rahul Ravikumar | 87d37e5 | 2018-01-04 18:18:29 -0800 | [diff] [blame] | 140 | |
| 141 | workContinuation.markEnqueued(); |
Rahul Ravikumar | 9f91ee8 | 2018-03-20 17:33:38 -0700 | [diff] [blame] | 142 | return needsScheduling; |
Rahul Ravikumar | 87d37e5 | 2018-01-04 18:18:29 -0800 | [diff] [blame] | 143 | } |
| 144 | |
| 145 | /** |
| 146 | * Enqueues the {@link WorkSpec}'s while keeping track of the prerequisites. |
Rahul Ravikumar | 9f91ee8 | 2018-03-20 17:33:38 -0700 | [diff] [blame] | 147 | * |
| 148 | * @return {@code true} If there is any scheduling to be done. |
Rahul Ravikumar | 87d37e5 | 2018-01-04 18:18:29 -0800 | [diff] [blame] | 149 | */ |
Rahul Ravikumar | 9f91ee8 | 2018-03-20 17:33:38 -0700 | [diff] [blame] | 150 | private static boolean enqueueWorkWithPrerequisites( |
Rahul Ravikumar | 87d37e5 | 2018-01-04 18:18:29 -0800 | [diff] [blame] | 151 | WorkManagerImpl workManagerImpl, |
Rahul Ravikumar | 7031a0f | 2018-04-19 14:24:30 -0700 | [diff] [blame] | 152 | @NonNull List<? extends WorkRequest> workList, |
Sumir Kataria | 4b59a5f | 2017-12-18 09:46:37 -0800 | [diff] [blame] | 153 | String[] prerequisiteIds, |
Sumir Kataria | 3665b82 | 2018-03-12 16:43:01 -0700 | [diff] [blame] | 154 | String name, |
Rahul Ravikumar | 9f91ee8 | 2018-03-20 17:33:38 -0700 | [diff] [blame] | 155 | ExistingWorkPolicy existingWorkPolicy) { |
Sumir Kataria | 15f793d | 2017-12-18 13:30:46 -0800 | [diff] [blame] | 156 | |
Rahul Ravikumar | 87d37e5 | 2018-01-04 18:18:29 -0800 | [diff] [blame] | 157 | long currentTimeMillis = System.currentTimeMillis(); |
| 158 | WorkDatabase workDatabase = workManagerImpl.getWorkDatabase(); |
| 159 | |
Rahul Ravikumar | 87d37e5 | 2018-01-04 18:18:29 -0800 | [diff] [blame] | 160 | boolean hasPrerequisite = (prerequisiteIds != null && prerequisiteIds.length > 0); |
| 161 | boolean hasCompletedAllPrerequisites = true; |
Sumir Kataria | 84354e3 | 2018-03-07 15:30:16 -0800 | [diff] [blame] | 162 | boolean hasFailedPrerequisites = false; |
| 163 | boolean hasCancelledPrerequisites = false; |
Rahul Ravikumar | 87d37e5 | 2018-01-04 18:18:29 -0800 | [diff] [blame] | 164 | |
| 165 | if (hasPrerequisite) { |
| 166 | // If there are prerequisites, make sure they actually exist before enqueuing |
| 167 | // anything. Prerequisites may not exist if we are using unique tags, because the |
| 168 | // chain of work could have been wiped out already. |
| 169 | for (String id : prerequisiteIds) { |
| 170 | WorkSpec prerequisiteWorkSpec = workDatabase.workSpecDao().getWorkSpec(id); |
| 171 | if (prerequisiteWorkSpec == null) { |
Rahul Ravikumar | 697d6a4 | 2018-04-16 15:44:09 -0700 | [diff] [blame] | 172 | Log.e(TAG, String.format("Prerequisite %s doesn't exist; not enqueuing", id)); |
Rahul Ravikumar | 9f91ee8 | 2018-03-20 17:33:38 -0700 | [diff] [blame] | 173 | return false; |
Rahul Ravikumar | 87d37e5 | 2018-01-04 18:18:29 -0800 | [diff] [blame] | 174 | } |
Sumir Kataria | 84354e3 | 2018-03-07 15:30:16 -0800 | [diff] [blame] | 175 | |
Sumir Kataria | b5728f4 | 2018-03-19 12:58:41 -0700 | [diff] [blame] | 176 | State prerequisiteState = prerequisiteWorkSpec.state; |
Sumir Kataria | 84354e3 | 2018-03-07 15:30:16 -0800 | [diff] [blame] | 177 | hasCompletedAllPrerequisites &= (prerequisiteState == SUCCEEDED); |
| 178 | if (prerequisiteState == FAILED) { |
| 179 | hasFailedPrerequisites = true; |
| 180 | } else if (prerequisiteState == CANCELLED) { |
| 181 | hasCancelledPrerequisites = true; |
| 182 | } |
Rahul Ravikumar | 87d37e5 | 2018-01-04 18:18:29 -0800 | [diff] [blame] | 183 | } |
| 184 | } |
| 185 | |
Sumir Kataria | 3665b82 | 2018-03-12 16:43:01 -0700 | [diff] [blame] | 186 | boolean isNamed = !TextUtils.isEmpty(name); |
Sumir Kataria | 5a04d6c | 2018-02-01 11:21:24 -0800 | [diff] [blame] | 187 | |
| 188 | // We only apply existing work policies for unique tag sequences that are the beginning of |
| 189 | // chains. |
Sumir Kataria | 3665b82 | 2018-03-12 16:43:01 -0700 | [diff] [blame] | 190 | boolean shouldApplyExistingWorkPolicy = isNamed && !hasPrerequisite; |
Sumir Kataria | 5a04d6c | 2018-02-01 11:21:24 -0800 | [diff] [blame] | 191 | if (shouldApplyExistingWorkPolicy) { |
| 192 | // Get everything with the unique tag. |
Sumir Kataria | 9cf4f3d | 2018-02-06 09:57:51 -0800 | [diff] [blame] | 193 | List<WorkSpec.IdAndState> existingWorkSpecIdAndStates = |
Sumir Kataria | 3665b82 | 2018-03-12 16:43:01 -0700 | [diff] [blame] | 194 | workDatabase.workSpecDao().getWorkSpecIdAndStatesForName(name); |
Sumir Kataria | 5a04d6c | 2018-02-01 11:21:24 -0800 | [diff] [blame] | 195 | |
Sumir Kataria | 9cf4f3d | 2018-02-06 09:57:51 -0800 | [diff] [blame] | 196 | if (!existingWorkSpecIdAndStates.isEmpty()) { |
Sumir Kataria | 5a04d6c | 2018-02-01 11:21:24 -0800 | [diff] [blame] | 197 | // If appending, these are the new prerequisites. |
Sumir Kataria | 8812a25 | 2018-02-02 12:40:07 -0800 | [diff] [blame] | 198 | if (existingWorkPolicy == APPEND) { |
Sumir Kataria | 5a04d6c | 2018-02-01 11:21:24 -0800 | [diff] [blame] | 199 | DependencyDao dependencyDao = workDatabase.dependencyDao(); |
| 200 | List<String> newPrerequisiteIds = new ArrayList<>(); |
Sumir Kataria | 9cf4f3d | 2018-02-06 09:57:51 -0800 | [diff] [blame] | 201 | for (WorkSpec.IdAndState idAndState : existingWorkSpecIdAndStates) { |
| 202 | if (!dependencyDao.hasDependents(idAndState.id)) { |
| 203 | hasCompletedAllPrerequisites &= (idAndState.state == SUCCEEDED); |
Sumir Kataria | 84354e3 | 2018-03-07 15:30:16 -0800 | [diff] [blame] | 204 | if (idAndState.state == FAILED) { |
| 205 | hasFailedPrerequisites = true; |
| 206 | } else if (idAndState.state == CANCELLED) { |
| 207 | hasCancelledPrerequisites = true; |
| 208 | } |
Sumir Kataria | 9cf4f3d | 2018-02-06 09:57:51 -0800 | [diff] [blame] | 209 | newPrerequisiteIds.add(idAndState.id); |
Sumir Kataria | b54385f | 2018-01-26 13:40:22 -0800 | [diff] [blame] | 210 | } |
| 211 | } |
Sumir Kataria | 5a04d6c | 2018-02-01 11:21:24 -0800 | [diff] [blame] | 212 | prerequisiteIds = newPrerequisiteIds.toArray(prerequisiteIds); |
| 213 | hasPrerequisite = (prerequisiteIds.length > 0); |
| 214 | } else { |
| 215 | // If we're keeping existing work, make sure to do so only if something is |
| 216 | // enqueued or running. |
Sumir Kataria | 8812a25 | 2018-02-02 12:40:07 -0800 | [diff] [blame] | 217 | if (existingWorkPolicy == KEEP) { |
Sumir Kataria | 9cf4f3d | 2018-02-06 09:57:51 -0800 | [diff] [blame] | 218 | for (WorkSpec.IdAndState idAndState : existingWorkSpecIdAndStates) { |
| 219 | if (idAndState.state == ENQUEUED || idAndState.state == RUNNING) { |
Rahul Ravikumar | 9f91ee8 | 2018-03-20 17:33:38 -0700 | [diff] [blame] | 220 | return false; |
Sumir Kataria | 5a04d6c | 2018-02-01 11:21:24 -0800 | [diff] [blame] | 221 | } |
| 222 | } |
| 223 | } |
Rahul Ravikumar | 87d37e5 | 2018-01-04 18:18:29 -0800 | [diff] [blame] | 224 | |
Sumir Kataria | 5a04d6c | 2018-02-01 11:21:24 -0800 | [diff] [blame] | 225 | // Cancel all of these workers. |
Sumir Kataria | 3665b82 | 2018-03-12 16:43:01 -0700 | [diff] [blame] | 226 | CancelWorkRunnable.forName(name, workManagerImpl).run(); |
Sumir Kataria | 5a04d6c | 2018-02-01 11:21:24 -0800 | [diff] [blame] | 227 | // And delete all the database records. |
| 228 | WorkSpecDao workSpecDao = workDatabase.workSpecDao(); |
Sumir Kataria | 9cf4f3d | 2018-02-06 09:57:51 -0800 | [diff] [blame] | 229 | for (WorkSpec.IdAndState idAndState : existingWorkSpecIdAndStates) { |
| 230 | workSpecDao.delete(idAndState.id); |
Sumir Kataria | 5a04d6c | 2018-02-01 11:21:24 -0800 | [diff] [blame] | 231 | } |
Sumir Kataria | b54385f | 2018-01-26 13:40:22 -0800 | [diff] [blame] | 232 | } |
Rahul Ravikumar | 87d37e5 | 2018-01-04 18:18:29 -0800 | [diff] [blame] | 233 | } |
| 234 | } |
| 235 | |
Rahul Ravikumar | 9f91ee8 | 2018-03-20 17:33:38 -0700 | [diff] [blame] | 236 | boolean needsScheduling = false; |
Rahul Ravikumar | 7031a0f | 2018-04-19 14:24:30 -0700 | [diff] [blame] | 237 | for (WorkRequest work : workList) { |
Rahul Ravikumar | 87d37e5 | 2018-01-04 18:18:29 -0800 | [diff] [blame] | 238 | WorkSpec workSpec = work.getWorkSpec(); |
| 239 | |
| 240 | if (hasPrerequisite && !hasCompletedAllPrerequisites) { |
Sumir Kataria | 84354e3 | 2018-03-07 15:30:16 -0800 | [diff] [blame] | 241 | if (hasFailedPrerequisites) { |
Sumir Kataria | b5728f4 | 2018-03-19 12:58:41 -0700 | [diff] [blame] | 242 | workSpec.state = FAILED; |
Sumir Kataria | 84354e3 | 2018-03-07 15:30:16 -0800 | [diff] [blame] | 243 | } else if (hasCancelledPrerequisites) { |
Sumir Kataria | b5728f4 | 2018-03-19 12:58:41 -0700 | [diff] [blame] | 244 | workSpec.state = CANCELLED; |
Sumir Kataria | 84354e3 | 2018-03-07 15:30:16 -0800 | [diff] [blame] | 245 | } else { |
Sumir Kataria | b5728f4 | 2018-03-19 12:58:41 -0700 | [diff] [blame] | 246 | workSpec.state = BLOCKED; |
Sumir Kataria | 84354e3 | 2018-03-07 15:30:16 -0800 | [diff] [blame] | 247 | } |
Rahul Ravikumar | 87d37e5 | 2018-01-04 18:18:29 -0800 | [diff] [blame] | 248 | } else { |
| 249 | // Set scheduled times only for work without prerequisites. Dependent work |
| 250 | // will set their scheduled times when they are unblocked. |
Sumir Kataria | b5728f4 | 2018-03-19 12:58:41 -0700 | [diff] [blame] | 251 | workSpec.periodStartTime = currentTimeMillis; |
Rahul Ravikumar | 87d37e5 | 2018-01-04 18:18:29 -0800 | [diff] [blame] | 252 | } |
| 253 | |
Sumir Kataria | 31099f8 | 2018-03-16 16:17:36 -0700 | [diff] [blame] | 254 | if (Build.VERSION.SDK_INT >= 23 && Build.VERSION.SDK_INT <= 25) { |
| 255 | tryDelegateConstrainedWorkSpec(workSpec); |
| 256 | } |
| 257 | |
Rahul Ravikumar | 9f91ee8 | 2018-03-20 17:33:38 -0700 | [diff] [blame] | 258 | // If we have one WorkSpec with an enqueued state, then we need to schedule. |
| 259 | if (workSpec.state == ENQUEUED) { |
| 260 | needsScheduling = true; |
| 261 | } |
| 262 | |
Rahul Ravikumar | 87d37e5 | 2018-01-04 18:18:29 -0800 | [diff] [blame] | 263 | workDatabase.workSpecDao().insertWorkSpec(workSpec); |
Sumir Kataria | 15f793d | 2017-12-18 13:30:46 -0800 | [diff] [blame] | 264 | |
Sumir Kataria | 4b59a5f | 2017-12-18 09:46:37 -0800 | [diff] [blame] | 265 | if (hasPrerequisite) { |
Rahul Ravikumar | 87d37e5 | 2018-01-04 18:18:29 -0800 | [diff] [blame] | 266 | for (String prerequisiteId : prerequisiteIds) { |
Sumir Kataria | fa284c9 | 2018-04-23 14:25:53 -0700 | [diff] [blame] | 267 | Dependency dep = new Dependency(work.getStringId(), prerequisiteId); |
Rahul Ravikumar | 87d37e5 | 2018-01-04 18:18:29 -0800 | [diff] [blame] | 268 | workDatabase.dependencyDao().insertDependency(dep); |
Sumir Kataria | 4b59a5f | 2017-12-18 09:46:37 -0800 | [diff] [blame] | 269 | } |
| 270 | } |
| 271 | |
Rahul Ravikumar | 87d37e5 | 2018-01-04 18:18:29 -0800 | [diff] [blame] | 272 | for (String tag : work.getTags()) { |
Sumir Kataria | fa284c9 | 2018-04-23 14:25:53 -0700 | [diff] [blame] | 273 | workDatabase.workTagDao().insert(new WorkTag(tag, work.getStringId())); |
Sumir Kataria | 4b59a5f | 2017-12-18 09:46:37 -0800 | [diff] [blame] | 274 | } |
| 275 | |
Sumir Kataria | 3665b82 | 2018-03-12 16:43:01 -0700 | [diff] [blame] | 276 | if (isNamed) { |
Sumir Kataria | fa284c9 | 2018-04-23 14:25:53 -0700 | [diff] [blame] | 277 | workDatabase.workNameDao().insert(new WorkName(name, work.getStringId())); |
Sumir Kataria | 15f793d | 2017-12-18 13:30:46 -0800 | [diff] [blame] | 278 | } |
Rahul Ravikumar | 87d37e5 | 2018-01-04 18:18:29 -0800 | [diff] [blame] | 279 | } |
Rahul Ravikumar | 9f91ee8 | 2018-03-20 17:33:38 -0700 | [diff] [blame] | 280 | return needsScheduling; |
Sumir Kataria | 31099f8 | 2018-03-16 16:17:36 -0700 | [diff] [blame] | 281 | } |
| 282 | |
| 283 | private static void tryDelegateConstrainedWorkSpec(WorkSpec workSpec) { |
| 284 | // requiresBatteryNotLow and requiresStorageNotLow require API 26 for JobScheduler. |
| 285 | // Delegate to ConstraintTrackingWorker between API 23-25. |
Sumir Kataria | b5728f4 | 2018-03-19 12:58:41 -0700 | [diff] [blame] | 286 | Constraints constraints = workSpec.constraints; |
Sumir Kataria | 31099f8 | 2018-03-16 16:17:36 -0700 | [diff] [blame] | 287 | if (constraints.requiresBatteryNotLow() || constraints.requiresStorageNotLow()) { |
Sumir Kataria | b5728f4 | 2018-03-19 12:58:41 -0700 | [diff] [blame] | 288 | String workerClassName = workSpec.workerClassName; |
Sumir Kataria | 64e6bd8 | 2018-03-28 17:14:22 -0700 | [diff] [blame] | 289 | Data.Builder builder = new Data.Builder(); |
Sumir Kataria | 31099f8 | 2018-03-16 16:17:36 -0700 | [diff] [blame] | 290 | // Copy all arguments |
Sumir Kataria | 64e6bd8 | 2018-03-28 17:14:22 -0700 | [diff] [blame] | 291 | builder.putAll(workSpec.input) |
Sumir Kataria | 31099f8 | 2018-03-16 16:17:36 -0700 | [diff] [blame] | 292 | .putString(ARGUMENT_CLASS_NAME, workerClassName); |
Sumir Kataria | b5728f4 | 2018-03-19 12:58:41 -0700 | [diff] [blame] | 293 | workSpec.workerClassName = ConstraintTrackingWorker.class.getName(); |
Sumir Kataria | 64e6bd8 | 2018-03-28 17:14:22 -0700 | [diff] [blame] | 294 | workSpec.input = builder.build(); |
Sumir Kataria | 15f793d | 2017-12-18 13:30:46 -0800 | [diff] [blame] | 295 | } |
| 296 | } |
| 297 | } |