144235b3ed93a4783f6bb1f3979779ee039289bfcRahul Ravikumar/* 244235b3ed93a4783f6bb1f3979779ee039289bfcRahul Ravikumar * Copyright 2018 The Android Open Source Project 344235b3ed93a4783f6bb1f3979779ee039289bfcRahul Ravikumar * 444235b3ed93a4783f6bb1f3979779ee039289bfcRahul Ravikumar * Licensed under the Apache License, Version 2.0 (the "License"); 544235b3ed93a4783f6bb1f3979779ee039289bfcRahul Ravikumar * you may not use this file except in compliance with the License. 644235b3ed93a4783f6bb1f3979779ee039289bfcRahul Ravikumar * You may obtain a copy of the License at 744235b3ed93a4783f6bb1f3979779ee039289bfcRahul Ravikumar * 844235b3ed93a4783f6bb1f3979779ee039289bfcRahul Ravikumar * http://www.apache.org/licenses/LICENSE-2.0 944235b3ed93a4783f6bb1f3979779ee039289bfcRahul Ravikumar * 1044235b3ed93a4783f6bb1f3979779ee039289bfcRahul Ravikumar * Unless required by applicable law or agreed to in writing, software 1144235b3ed93a4783f6bb1f3979779ee039289bfcRahul Ravikumar * distributed under the License is distributed on an "AS IS" BASIS, 1244235b3ed93a4783f6bb1f3979779ee039289bfcRahul Ravikumar * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1344235b3ed93a4783f6bb1f3979779ee039289bfcRahul Ravikumar * See the License for the specific language governing permissions and 1444235b3ed93a4783f6bb1f3979779ee039289bfcRahul Ravikumar * limitations under the License. 1544235b3ed93a4783f6bb1f3979779ee039289bfcRahul Ravikumar */ 1644235b3ed93a4783f6bb1f3979779ee039289bfcRahul Ravikumar 17564e43098c323d1a90be53c190b8fdbdde973505Sumir Katariapackage androidx.work.impl; 1844235b3ed93a4783f6bb1f3979779ee039289bfcRahul Ravikumar 1944235b3ed93a4783f6bb1f3979779ee039289bfcRahul Ravikumarimport android.arch.lifecycle.LiveData; 20d7470effc40d8e9f46e7e29d1ccbbf7e8ff706f8Sumir Katariaimport android.os.Looper; 2144235b3ed93a4783f6bb1f3979779ee039289bfcRahul Ravikumarimport android.support.annotation.NonNull; 2244235b3ed93a4783f6bb1f3979779ee039289bfcRahul Ravikumarimport android.support.annotation.Nullable; 2344235b3ed93a4783f6bb1f3979779ee039289bfcRahul Ravikumarimport android.support.annotation.RestrictTo; 24d7470effc40d8e9f46e7e29d1ccbbf7e8ff706f8Sumir Katariaimport android.support.annotation.WorkerThread; 2544235b3ed93a4783f6bb1f3979779ee039289bfcRahul Ravikumarimport android.text.TextUtils; 26697d6a4a3797bc71d0dd8685937a318e9934066bRahul Ravikumarimport android.util.Log; 2744235b3ed93a4783f6bb1f3979779ee039289bfcRahul Ravikumar 2887e8dc0458781cd41a5ee990be811790ac7f4e88Sumir Katariaimport androidx.work.ArrayCreatingInputMerger; 29564e43098c323d1a90be53c190b8fdbdde973505Sumir Katariaimport androidx.work.ExistingWorkPolicy; 307031a0fbe12b8159ab2dc6d9c50be5b3f38477faRahul Ravikumarimport androidx.work.OneTimeWorkRequest; 3162e0be94ea7e54ca9227564b14c1c6736ae770f7Sumir Katariaimport androidx.work.SynchronousWorkContinuation; 32564e43098c323d1a90be53c190b8fdbdde973505Sumir Katariaimport androidx.work.WorkContinuation; 338b3284fa4a62568df91f706b0b2334284794008fSumir Katariaimport androidx.work.WorkRequest; 34564e43098c323d1a90be53c190b8fdbdde973505Sumir Katariaimport androidx.work.WorkStatus; 35564e43098c323d1a90be53c190b8fdbdde973505Sumir Katariaimport androidx.work.impl.utils.EnqueueRunnable; 3655a030183e5b974f3ebf04ef5cd9ab83f3557dadSumir Katariaimport androidx.work.impl.workers.CombineContinuationsWorker; 37564e43098c323d1a90be53c190b8fdbdde973505Sumir Kataria 38707219fe57da2c3b270035c109ab865f01287ae9Rahul Ravikumarimport java.util.ArrayList; 39707219fe57da2c3b270035c109ab865f01287ae9Rahul Ravikumarimport java.util.Collections; 402ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumarimport java.util.HashSet; 41707219fe57da2c3b270035c109ab865f01287ae9Rahul Ravikumarimport java.util.List; 422ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumarimport java.util.Set; 43707219fe57da2c3b270035c109ab865f01287ae9Rahul Ravikumar 4444235b3ed93a4783f6bb1f3979779ee039289bfcRahul Ravikumar/** 4544235b3ed93a4783f6bb1f3979779ee039289bfcRahul Ravikumar * A concrete implementation of {@link WorkContinuation}. 4644235b3ed93a4783f6bb1f3979779ee039289bfcRahul Ravikumar * 4744235b3ed93a4783f6bb1f3979779ee039289bfcRahul Ravikumar * @hide 4844235b3ed93a4783f6bb1f3979779ee039289bfcRahul Ravikumar */ 4944235b3ed93a4783f6bb1f3979779ee039289bfcRahul Ravikumar@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP) 504484814aab16eec8d004c9e560ed5e25e0272d4dSumir Katariapublic class WorkContinuationImpl extends WorkContinuation 5162e0be94ea7e54ca9227564b14c1c6736ae770f7Sumir Kataria implements SynchronousWorkContinuation { 5244235b3ed93a4783f6bb1f3979779ee039289bfcRahul Ravikumar 5387d37e5587b277ba523d69df71e17a4039274cdaRahul Ravikumar private static final String TAG = "WorkContinuationImpl"; 5444235b3ed93a4783f6bb1f3979779ee039289bfcRahul Ravikumar 5587d37e5587b277ba523d69df71e17a4039274cdaRahul Ravikumar private final WorkManagerImpl mWorkManagerImpl; 563665b829af9706f7f85c53e4ef5a0825228f4d7aSumir Kataria private final String mName; 57b6430f2f232996be5971e9a57819aa2377daf920Sumir Kataria private final ExistingWorkPolicy mExistingWorkPolicy; 587031a0fbe12b8159ab2dc6d9c50be5b3f38477faRahul Ravikumar private final List<? extends WorkRequest> mWork; 5959cbb5756e54d32fb51e72fe1ed94934c93f7303Rahul Ravikumar private final List<String> mIds; 6087d37e5587b277ba523d69df71e17a4039274cdaRahul Ravikumar private final List<String> mAllIds; 6159cbb5756e54d32fb51e72fe1ed94934c93f7303Rahul Ravikumar private final List<WorkContinuationImpl> mParents; 6287d37e5587b277ba523d69df71e17a4039274cdaRahul Ravikumar private boolean mEnqueued; 6344235b3ed93a4783f6bb1f3979779ee039289bfcRahul Ravikumar 6487d37e5587b277ba523d69df71e17a4039274cdaRahul Ravikumar @NonNull 6587d37e5587b277ba523d69df71e17a4039274cdaRahul Ravikumar public WorkManagerImpl getWorkManagerImpl() { 6687d37e5587b277ba523d69df71e17a4039274cdaRahul Ravikumar return mWorkManagerImpl; 6787d37e5587b277ba523d69df71e17a4039274cdaRahul Ravikumar } 6887d37e5587b277ba523d69df71e17a4039274cdaRahul Ravikumar 6987d37e5587b277ba523d69df71e17a4039274cdaRahul Ravikumar @Nullable 703665b829af9706f7f85c53e4ef5a0825228f4d7aSumir Kataria public String getName() { 713665b829af9706f7f85c53e4ef5a0825228f4d7aSumir Kataria return mName; 7287d37e5587b277ba523d69df71e17a4039274cdaRahul Ravikumar } 7304f39f8ef8b7a77858763da5154a07ed423519bdSumir Kataria 74b6430f2f232996be5971e9a57819aa2377daf920Sumir Kataria public ExistingWorkPolicy getExistingWorkPolicy() { 7587d37e5587b277ba523d69df71e17a4039274cdaRahul Ravikumar return mExistingWorkPolicy; 7687d37e5587b277ba523d69df71e17a4039274cdaRahul Ravikumar } 7787d37e5587b277ba523d69df71e17a4039274cdaRahul Ravikumar 7887d37e5587b277ba523d69df71e17a4039274cdaRahul Ravikumar @NonNull 797031a0fbe12b8159ab2dc6d9c50be5b3f38477faRahul Ravikumar public List<? extends WorkRequest> getWork() { 8087d37e5587b277ba523d69df71e17a4039274cdaRahul Ravikumar return mWork; 8187d37e5587b277ba523d69df71e17a4039274cdaRahul Ravikumar } 8204f39f8ef8b7a77858763da5154a07ed423519bdSumir Kataria 8387d37e5587b277ba523d69df71e17a4039274cdaRahul Ravikumar @NonNull 8459cbb5756e54d32fb51e72fe1ed94934c93f7303Rahul Ravikumar public List<String> getIds() { 8587d37e5587b277ba523d69df71e17a4039274cdaRahul Ravikumar return mIds; 8687d37e5587b277ba523d69df71e17a4039274cdaRahul Ravikumar } 8744235b3ed93a4783f6bb1f3979779ee039289bfcRahul Ravikumar 8887d37e5587b277ba523d69df71e17a4039274cdaRahul Ravikumar public List<String> getAllIds() { 8987d37e5587b277ba523d69df71e17a4039274cdaRahul Ravikumar return mAllIds; 9087d37e5587b277ba523d69df71e17a4039274cdaRahul Ravikumar } 9144235b3ed93a4783f6bb1f3979779ee039289bfcRahul Ravikumar 9287d37e5587b277ba523d69df71e17a4039274cdaRahul Ravikumar public boolean isEnqueued() { 9387d37e5587b277ba523d69df71e17a4039274cdaRahul Ravikumar return mEnqueued; 9487d37e5587b277ba523d69df71e17a4039274cdaRahul Ravikumar } 9544235b3ed93a4783f6bb1f3979779ee039289bfcRahul Ravikumar 9687d37e5587b277ba523d69df71e17a4039274cdaRahul Ravikumar /** 9787d37e5587b277ba523d69df71e17a4039274cdaRahul Ravikumar * Marks the {@link WorkContinuationImpl} as enqueued. 9887d37e5587b277ba523d69df71e17a4039274cdaRahul Ravikumar */ 9987d37e5587b277ba523d69df71e17a4039274cdaRahul Ravikumar public void markEnqueued() { 10087d37e5587b277ba523d69df71e17a4039274cdaRahul Ravikumar mEnqueued = true; 10187d37e5587b277ba523d69df71e17a4039274cdaRahul Ravikumar } 10244235b3ed93a4783f6bb1f3979779ee039289bfcRahul Ravikumar 10359cbb5756e54d32fb51e72fe1ed94934c93f7303Rahul Ravikumar public List<WorkContinuationImpl> getParents() { 10459cbb5756e54d32fb51e72fe1ed94934c93f7303Rahul Ravikumar return mParents; 10587d37e5587b277ba523d69df71e17a4039274cdaRahul Ravikumar } 10644235b3ed93a4783f6bb1f3979779ee039289bfcRahul Ravikumar 10759cbb5756e54d32fb51e72fe1ed94934c93f7303Rahul Ravikumar WorkContinuationImpl( 10859cbb5756e54d32fb51e72fe1ed94934c93f7303Rahul Ravikumar @NonNull WorkManagerImpl workManagerImpl, 1097031a0fbe12b8159ab2dc6d9c50be5b3f38477faRahul Ravikumar @NonNull List<? extends WorkRequest> work) { 110d7c332544c4dc6e06b4a876fd10c25b0469e81bcSumir Kataria this( 111d7c332544c4dc6e06b4a876fd10c25b0469e81bcSumir Kataria workManagerImpl, 112d7c332544c4dc6e06b4a876fd10c25b0469e81bcSumir Kataria null, 113b6430f2f232996be5971e9a57819aa2377daf920Sumir Kataria ExistingWorkPolicy.KEEP, 114d7c332544c4dc6e06b4a876fd10c25b0469e81bcSumir Kataria work, 115d7c332544c4dc6e06b4a876fd10c25b0469e81bcSumir Kataria null); 11604f39f8ef8b7a77858763da5154a07ed423519bdSumir Kataria } 11704f39f8ef8b7a77858763da5154a07ed423519bdSumir Kataria 1181bffc919a167a732f24cf4216664374087628e15Sumir Kataria WorkContinuationImpl( 1191bffc919a167a732f24cf4216664374087628e15Sumir Kataria @NonNull WorkManagerImpl workManagerImpl, 1203665b829af9706f7f85c53e4ef5a0825228f4d7aSumir Kataria String name, 121b6430f2f232996be5971e9a57819aa2377daf920Sumir Kataria ExistingWorkPolicy existingWorkPolicy, 1227031a0fbe12b8159ab2dc6d9c50be5b3f38477faRahul Ravikumar @NonNull List<? extends WorkRequest> work) { 1233665b829af9706f7f85c53e4ef5a0825228f4d7aSumir Kataria this(workManagerImpl, name, existingWorkPolicy, work, null); 12444235b3ed93a4783f6bb1f3979779ee039289bfcRahul Ravikumar } 12544235b3ed93a4783f6bb1f3979779ee039289bfcRahul Ravikumar 12659cbb5756e54d32fb51e72fe1ed94934c93f7303Rahul Ravikumar WorkContinuationImpl(@NonNull WorkManagerImpl workManagerImpl, 1273665b829af9706f7f85c53e4ef5a0825228f4d7aSumir Kataria String name, 128b6430f2f232996be5971e9a57819aa2377daf920Sumir Kataria ExistingWorkPolicy existingWorkPolicy, 1297031a0fbe12b8159ab2dc6d9c50be5b3f38477faRahul Ravikumar @NonNull List<? extends WorkRequest> work, 13059cbb5756e54d32fb51e72fe1ed94934c93f7303Rahul Ravikumar @Nullable List<WorkContinuationImpl> parents) { 13144235b3ed93a4783f6bb1f3979779ee039289bfcRahul Ravikumar mWorkManagerImpl = workManagerImpl; 1323665b829af9706f7f85c53e4ef5a0825228f4d7aSumir Kataria mName = name; 13304f39f8ef8b7a77858763da5154a07ed423519bdSumir Kataria mExistingWorkPolicy = existingWorkPolicy; 13444235b3ed93a4783f6bb1f3979779ee039289bfcRahul Ravikumar mWork = work; 13559cbb5756e54d32fb51e72fe1ed94934c93f7303Rahul Ravikumar mParents = parents; 13651b5cd2bc8a7fb7979e2bcd731fc8fd0d195f860Sumir Kataria mIds = new ArrayList<>(mWork.size()); 13759cbb5756e54d32fb51e72fe1ed94934c93f7303Rahul Ravikumar mAllIds = new ArrayList<>(); 13859cbb5756e54d32fb51e72fe1ed94934c93f7303Rahul Ravikumar if (parents != null) { 13959cbb5756e54d32fb51e72fe1ed94934c93f7303Rahul Ravikumar for (WorkContinuationImpl parent : parents) { 14059cbb5756e54d32fb51e72fe1ed94934c93f7303Rahul Ravikumar mAllIds.addAll(parent.mAllIds); 14159cbb5756e54d32fb51e72fe1ed94934c93f7303Rahul Ravikumar } 14244235b3ed93a4783f6bb1f3979779ee039289bfcRahul Ravikumar } 14351b5cd2bc8a7fb7979e2bcd731fc8fd0d195f860Sumir Kataria for (int i = 0; i < work.size(); i++) { 144fa284c943bd003ff03f1934370d70bd4a5e034c3Sumir Kataria String id = work.get(i).getStringId(); 14551b5cd2bc8a7fb7979e2bcd731fc8fd0d195f860Sumir Kataria mIds.add(id); 14651b5cd2bc8a7fb7979e2bcd731fc8fd0d195f860Sumir Kataria mAllIds.add(id); 14744235b3ed93a4783f6bb1f3979779ee039289bfcRahul Ravikumar } 14844235b3ed93a4783f6bb1f3979779ee039289bfcRahul Ravikumar } 14944235b3ed93a4783f6bb1f3979779ee039289bfcRahul Ravikumar 15044235b3ed93a4783f6bb1f3979779ee039289bfcRahul Ravikumar @Override 1517031a0fbe12b8159ab2dc6d9c50be5b3f38477faRahul Ravikumar public WorkContinuation then(List<OneTimeWorkRequest> work) { 15244235b3ed93a4783f6bb1f3979779ee039289bfcRahul Ravikumar // TODO (rahulrav@) We need to decide if we want to allow chaining of continuations after 15344235b3ed93a4783f6bb1f3979779ee039289bfcRahul Ravikumar // an initial call to enqueue() 154b776ef68aac1def7eeda4a1f14b7364009302982Sumir Kataria return new WorkContinuationImpl(mWorkManagerImpl, 1553665b829af9706f7f85c53e4ef5a0825228f4d7aSumir Kataria mName, 156b6430f2f232996be5971e9a57819aa2377daf920Sumir Kataria ExistingWorkPolicy.KEEP, 15704f39f8ef8b7a77858763da5154a07ed423519bdSumir Kataria work, 15859cbb5756e54d32fb51e72fe1ed94934c93f7303Rahul Ravikumar Collections.singletonList(this)); 15944235b3ed93a4783f6bb1f3979779ee039289bfcRahul Ravikumar } 16044235b3ed93a4783f6bb1f3979779ee039289bfcRahul Ravikumar 16144235b3ed93a4783f6bb1f3979779ee039289bfcRahul Ravikumar @Override 1629cf4f3d3aa83bc64db574955805c67ac9ea84008Sumir Kataria public LiveData<List<WorkStatus>> getStatuses() { 16319ae799361a8911480519c1c2b2e0e042e3a6239Sumir Kataria return mWorkManagerImpl.getStatusesById(mAllIds); 16444235b3ed93a4783f6bb1f3979779ee039289bfcRahul Ravikumar } 16544235b3ed93a4783f6bb1f3979779ee039289bfcRahul Ravikumar 16644235b3ed93a4783f6bb1f3979779ee039289bfcRahul Ravikumar @Override 1675a4ced8020d8a3ee4b9100b97559db3d1fb5132bRahul Ravikumar public List<WorkStatus> getStatusesSync() { 1685a4ced8020d8a3ee4b9100b97559db3d1fb5132bRahul Ravikumar if (Looper.getMainLooper().getThread() == Thread.currentThread()) { 1695a4ced8020d8a3ee4b9100b97559db3d1fb5132bRahul Ravikumar throw new IllegalStateException("Cannot getStatusesSync on main thread!"); 1705a4ced8020d8a3ee4b9100b97559db3d1fb5132bRahul Ravikumar } 1715a4ced8020d8a3ee4b9100b97559db3d1fb5132bRahul Ravikumar return mWorkManagerImpl.getStatusesByIdSync(mAllIds); 1725a4ced8020d8a3ee4b9100b97559db3d1fb5132bRahul Ravikumar } 1735a4ced8020d8a3ee4b9100b97559db3d1fb5132bRahul Ravikumar 1745a4ced8020d8a3ee4b9100b97559db3d1fb5132bRahul Ravikumar @Override 17544235b3ed93a4783f6bb1f3979779ee039289bfcRahul Ravikumar public void enqueue() { 17644235b3ed93a4783f6bb1f3979779ee039289bfcRahul Ravikumar // Only enqueue if not already enqueued. 17744235b3ed93a4783f6bb1f3979779ee039289bfcRahul Ravikumar if (!mEnqueued) { 178f56b9ee9361d113ec89eb4a44a153938b987d734Jan Clarin // The runnable walks the hierarchy of the continuations 17987d37e5587b277ba523d69df71e17a4039274cdaRahul Ravikumar // and marks them enqueued using the markEnqueued() method, parent first. 18087d37e5587b277ba523d69df71e17a4039274cdaRahul Ravikumar mWorkManagerImpl.getTaskExecutor() 18187d37e5587b277ba523d69df71e17a4039274cdaRahul Ravikumar .executeOnBackgroundThread(new EnqueueRunnable(this)); 18244235b3ed93a4783f6bb1f3979779ee039289bfcRahul Ravikumar } else { 183697d6a4a3797bc71d0dd8685937a318e9934066bRahul Ravikumar Log.w(TAG, String.format("Already enqueued work ids (%s)", TextUtils.join(", ", mIds))); 18444235b3ed93a4783f6bb1f3979779ee039289bfcRahul Ravikumar } 18544235b3ed93a4783f6bb1f3979779ee039289bfcRahul Ravikumar } 18659cbb5756e54d32fb51e72fe1ed94934c93f7303Rahul Ravikumar 18759cbb5756e54d32fb51e72fe1ed94934c93f7303Rahul Ravikumar @Override 188d7470effc40d8e9f46e7e29d1ccbbf7e8ff706f8Sumir Kataria @WorkerThread 18962e0be94ea7e54ca9227564b14c1c6736ae770f7Sumir Kataria public void enqueueSync() { 190d7470effc40d8e9f46e7e29d1ccbbf7e8ff706f8Sumir Kataria if (Looper.getMainLooper().getThread() == Thread.currentThread()) { 19162e0be94ea7e54ca9227564b14c1c6736ae770f7Sumir Kataria throw new IllegalStateException("Cannot enqueueSync on main thread!"); 192d7470effc40d8e9f46e7e29d1ccbbf7e8ff706f8Sumir Kataria } 193d7470effc40d8e9f46e7e29d1ccbbf7e8ff706f8Sumir Kataria 194d7470effc40d8e9f46e7e29d1ccbbf7e8ff706f8Sumir Kataria if (!mEnqueued) { 195d7470effc40d8e9f46e7e29d1ccbbf7e8ff706f8Sumir Kataria // The runnable walks the hierarchy of the continuations 196d7470effc40d8e9f46e7e29d1ccbbf7e8ff706f8Sumir Kataria // and marks them enqueued using the markEnqueued() method, parent first. 197d7470effc40d8e9f46e7e29d1ccbbf7e8ff706f8Sumir Kataria new EnqueueRunnable(this).run(); 198d7470effc40d8e9f46e7e29d1ccbbf7e8ff706f8Sumir Kataria } else { 199697d6a4a3797bc71d0dd8685937a318e9934066bRahul Ravikumar Log.w(TAG, String.format("Already enqueued work ids (%s)", TextUtils.join(", ", mIds))); 200d7470effc40d8e9f46e7e29d1ccbbf7e8ff706f8Sumir Kataria } 201d7470effc40d8e9f46e7e29d1ccbbf7e8ff706f8Sumir Kataria } 202d7470effc40d8e9f46e7e29d1ccbbf7e8ff706f8Sumir Kataria 203d7470effc40d8e9f46e7e29d1ccbbf7e8ff706f8Sumir Kataria @Override 20462e0be94ea7e54ca9227564b14c1c6736ae770f7Sumir Kataria public SynchronousWorkContinuation synchronous() { 2054484814aab16eec8d004c9e560ed5e25e0272d4dSumir Kataria return this; 2064484814aab16eec8d004c9e560ed5e25e0272d4dSumir Kataria } 2074484814aab16eec8d004c9e560ed5e25e0272d4dSumir Kataria 2084484814aab16eec8d004c9e560ed5e25e0272d4dSumir Kataria @Override 20955a030183e5b974f3ebf04ef5cd9ab83f3557dadSumir Kataria protected WorkContinuation combineInternal( 2107031a0fbe12b8159ab2dc6d9c50be5b3f38477faRahul Ravikumar @Nullable OneTimeWorkRequest work, 21151b5cd2bc8a7fb7979e2bcd731fc8fd0d195f860Sumir Kataria @NonNull List<WorkContinuation> continuations) { 212930c8fb091c540642a0002e89eebb35c9eb88205Rahul Ravikumar 213930c8fb091c540642a0002e89eebb35c9eb88205Rahul Ravikumar if (work == null) { 21455a030183e5b974f3ebf04ef5cd9ab83f3557dadSumir Kataria work = new OneTimeWorkRequest.Builder(CombineContinuationsWorker.class) 21562a7e773945d980084dfc5d00c724de2e27dc22dSumir Kataria .setInputMerger(ArrayCreatingInputMerger.class) 21687e8dc0458781cd41a5ee990be811790ac7f4e88Sumir Kataria .build(); 217930c8fb091c540642a0002e89eebb35c9eb88205Rahul Ravikumar } 218930c8fb091c540642a0002e89eebb35c9eb88205Rahul Ravikumar 21951b5cd2bc8a7fb7979e2bcd731fc8fd0d195f860Sumir Kataria List<WorkContinuationImpl> parents = new ArrayList<>(continuations.size()); 22059cbb5756e54d32fb51e72fe1ed94934c93f7303Rahul Ravikumar for (WorkContinuation continuation : continuations) { 22159cbb5756e54d32fb51e72fe1ed94934c93f7303Rahul Ravikumar parents.add((WorkContinuationImpl) continuation); 22259cbb5756e54d32fb51e72fe1ed94934c93f7303Rahul Ravikumar } 22359cbb5756e54d32fb51e72fe1ed94934c93f7303Rahul Ravikumar 22459cbb5756e54d32fb51e72fe1ed94934c93f7303Rahul Ravikumar return new WorkContinuationImpl(mWorkManagerImpl, 22559cbb5756e54d32fb51e72fe1ed94934c93f7303Rahul Ravikumar null, 226b6430f2f232996be5971e9a57819aa2377daf920Sumir Kataria ExistingWorkPolicy.KEEP, 22751b5cd2bc8a7fb7979e2bcd731fc8fd0d195f860Sumir Kataria Collections.singletonList(work), 22859cbb5756e54d32fb51e72fe1ed94934c93f7303Rahul Ravikumar parents); 22959cbb5756e54d32fb51e72fe1ed94934c93f7303Rahul Ravikumar } 2302ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar 2312ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar /** 2322ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar * @return {@code true} If there are cycles in the {@link WorkContinuationImpl}. 2332ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar 2342ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar * @hide 2352ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar */ 2362ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP) 2372ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar public boolean hasCycles() { 2382ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar return hasCycles(this, new HashSet<String>()); 2392ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar } 2402ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar 2412ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar /** 2422ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar * @param continuation The {@link WorkContinuationImpl} instance. 2432ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar * @param visited The {@link Set} of {@link androidx.work.impl.model.WorkSpec} ids 2442ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar * marked as visited. 2452ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar * @return {@code true} if the {@link WorkContinuationImpl} has a cycle. 2462ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar * @hide 2472ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar */ 2482ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP) 2492ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar private static boolean hasCycles( 2502ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar @NonNull WorkContinuationImpl continuation, 2512ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar @NonNull Set<String> visited) { 2522ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar 2532ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar // mark the ids of this workContinuation as visited 2542ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar // before we check if the parents have cycles. 2552ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar visited.addAll(continuation.getIds()); 2562ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar 2572ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar Set<String> prerequisiteIds = prerequisitesFor(continuation); 2582ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar for (String id : visited) { 2592ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar if (prerequisiteIds.contains(id)) { 2602ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar // This prerequisite has already been visited before. 2612ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar // There is a cycle. 2622ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar return true; 2632ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar } 2642ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar } 2652ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar 2662ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar List<WorkContinuationImpl> parents = continuation.getParents(); 2672ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar if (parents != null && !parents.isEmpty()) { 2682ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar for (WorkContinuationImpl parent : parents) { 2692ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar // if any of the parent has a cycle, then bail out 2702ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar if (hasCycles(parent, visited)) { 2712ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar return true; 2722ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar } 2732ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar } 2742ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar } 2752ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar 2762ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar // Un-mark the ids of the workContinuation as visited for the next parent. 2772ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar // This is because we don't want to change the state of visited ids for subsequent parents 2782ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar // This is being done to avoid allocations. Ideally we would check for a 2792ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar // hasCycles(parent, new HashSet<>(visited)) instead. 2802ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar visited.removeAll(continuation.getIds()); 2812ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar return false; 2822ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar } 2832ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar 2842ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar /** 2852ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar * @return the {@link Set} of pre-requisites for a given {@link WorkContinuationImpl}. 2862ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar * 2872ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar * @hide 2882ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar */ 2892ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP) 2902ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar public static Set<String> prerequisitesFor(WorkContinuationImpl continuation) { 2912ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar Set<String> preRequisites = new HashSet<>(); 2922ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar List<WorkContinuationImpl> parents = continuation.getParents(); 2932ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar if (parents != null && !parents.isEmpty()) { 2942ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar for (WorkContinuationImpl parent : parents) { 2952ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar preRequisites.addAll(parent.getIds()); 2962ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar } 2972ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar } 2982ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar return preRequisites; 2992ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar } 30044235b3ed93a4783f6bb1f3979779ee039289bfcRahul Ravikumar} 301