1b8909f2c9c62261181e8270be8de44a69ac2b75fXyan Bhatnagar/*
2da315bf9331a3ead74483bd0d38fd331f4a96088Sumir Kataria * Copyright 2017 The Android Open Source Project
3b8909f2c9c62261181e8270be8de44a69ac2b75fXyan Bhatnagar *
4b8909f2c9c62261181e8270be8de44a69ac2b75fXyan Bhatnagar * Licensed under the Apache License, Version 2.0 (the "License");
5b8909f2c9c62261181e8270be8de44a69ac2b75fXyan Bhatnagar * you may not use this file except in compliance with the License.
6b8909f2c9c62261181e8270be8de44a69ac2b75fXyan Bhatnagar * You may obtain a copy of the License at
7b8909f2c9c62261181e8270be8de44a69ac2b75fXyan Bhatnagar *
8b8909f2c9c62261181e8270be8de44a69ac2b75fXyan Bhatnagar *      http://www.apache.org/licenses/LICENSE-2.0
9b8909f2c9c62261181e8270be8de44a69ac2b75fXyan Bhatnagar *
10b8909f2c9c62261181e8270be8de44a69ac2b75fXyan Bhatnagar * Unless required by applicable law or agreed to in writing, software
11b8909f2c9c62261181e8270be8de44a69ac2b75fXyan Bhatnagar * distributed under the License is distributed on an "AS IS" BASIS,
12b8909f2c9c62261181e8270be8de44a69ac2b75fXyan Bhatnagar * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13b8909f2c9c62261181e8270be8de44a69ac2b75fXyan Bhatnagar * See the License for the specific language governing permissions and
14b8909f2c9c62261181e8270be8de44a69ac2b75fXyan Bhatnagar * limitations under the License.
15b8909f2c9c62261181e8270be8de44a69ac2b75fXyan Bhatnagar */
16b8909f2c9c62261181e8270be8de44a69ac2b75fXyan Bhatnagar
17564e43098c323d1a90be53c190b8fdbdde973505Sumir Katariapackage androidx.work.impl;
18b8909f2c9c62261181e8270be8de44a69ac2b75fXyan Bhatnagar
195b84f5ce59c65703ce6d5cdb1133185cd93e1862Sumir Katariaimport static androidx.work.State.CANCELLED;
20564e43098c323d1a90be53c190b8fdbdde973505Sumir Katariaimport static androidx.work.State.ENQUEUED;
21564e43098c323d1a90be53c190b8fdbdde973505Sumir Katariaimport static androidx.work.State.FAILED;
22564e43098c323d1a90be53c190b8fdbdde973505Sumir Katariaimport static androidx.work.State.RUNNING;
23564e43098c323d1a90be53c190b8fdbdde973505Sumir Katariaimport static androidx.work.State.SUCCEEDED;
2463ccec5104c970c3d93dd67c7f829d6a8cf8abbdXyan Bhatnagar
25b8909f2c9c62261181e8270be8de44a69ac2b75fXyan Bhatnagarimport android.content.Context;
26b8909f2c9c62261181e8270be8de44a69ac2b75fXyan Bhatnagarimport android.support.annotation.NonNull;
27d64a1a65bd138cfeeb9ae6a595120b85e77a57f6Rahul Ravikumarimport android.support.annotation.Nullable;
282881509622c5dd8064f414075ce60060dbac688fSumir Katariaimport android.support.annotation.RestrictTo;
29d64a1a65bd138cfeeb9ae6a595120b85e77a57f6Rahul Ravikumarimport android.support.annotation.VisibleForTesting;
30f6d484674fd8f2c3a0bc6a8b5117769a3c9b3640Xyan Bhatnagarimport android.support.annotation.WorkerThread;
31b8909f2c9c62261181e8270be8de44a69ac2b75fXyan Bhatnagarimport android.util.Log;
32b8909f2c9c62261181e8270be8de44a69ac2b75fXyan Bhatnagar
33e326592ec414dfe4c002e2840d9fc4aef0ee8747Rahul Ravikumarimport androidx.work.Configuration;
3464e6bd86c786f1cb1b0c3dbc2b5307cca5c0d1f6Sumir Katariaimport androidx.work.Data;
35564e43098c323d1a90be53c190b8fdbdde973505Sumir Katariaimport androidx.work.InputMerger;
36564e43098c323d1a90be53c190b8fdbdde973505Sumir Katariaimport androidx.work.State;
37564e43098c323d1a90be53c190b8fdbdde973505Sumir Katariaimport androidx.work.Worker;
38564e43098c323d1a90be53c190b8fdbdde973505Sumir Katariaimport androidx.work.impl.model.DependencyDao;
39564e43098c323d1a90be53c190b8fdbdde973505Sumir Katariaimport androidx.work.impl.model.WorkSpec;
40564e43098c323d1a90be53c190b8fdbdde973505Sumir Katariaimport androidx.work.impl.model.WorkSpecDao;
417b5c560e4098585f73564951621060de708e441fSumir Katariaimport androidx.work.impl.model.WorkTagDao;
42564e43098c323d1a90be53c190b8fdbdde973505Sumir Katariaimport androidx.work.impl.utils.taskexecutor.WorkManagerTaskExecutor;
43564e43098c323d1a90be53c190b8fdbdde973505Sumir Kataria
44b5728f4e1a4b3f4f1fabf033b1363ca6b1cffdefSumir Katariaimport java.lang.reflect.Method;
45b5728f4e1a4b3f4f1fabf033b1363ca6b1cffdefSumir Katariaimport java.util.ArrayList;
46b5728f4e1a4b3f4f1fabf033b1363ca6b1cffdefSumir Katariaimport java.util.List;
47dd5f33cd6b98eba208ac7c69d3d6314d3115e2d2Sumir Katariaimport java.util.UUID;
48b5728f4e1a4b3f4f1fabf033b1363ca6b1cffdefSumir Kataria
49b8909f2c9c62261181e8270be8de44a69ac2b75fXyan Bhatnagar/**
50b8909f2c9c62261181e8270be8de44a69ac2b75fXyan Bhatnagar * A runnable that looks up the {@link WorkSpec} from the database for a given id, instantiates
51b8909f2c9c62261181e8270be8de44a69ac2b75fXyan Bhatnagar * its Worker, and then calls it.
522881509622c5dd8064f414075ce60060dbac688fSumir Kataria *
532881509622c5dd8064f414075ce60060dbac688fSumir Kataria * @hide
54b8909f2c9c62261181e8270be8de44a69ac2b75fXyan Bhatnagar */
552881509622c5dd8064f414075ce60060dbac688fSumir Kataria@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
56115eb6a640a0addca15460a2a994e21692a3ffefSumir Katariapublic class WorkerWrapper implements Runnable {
5763ccec5104c970c3d93dd67c7f829d6a8cf8abbdXyan Bhatnagar
58b8909f2c9c62261181e8270be8de44a69ac2b75fXyan Bhatnagar    private static final String TAG = "WorkerWrapper";
59b8909f2c9c62261181e8270be8de44a69ac2b75fXyan Bhatnagar    private Context mAppContext;
60b8909f2c9c62261181e8270be8de44a69ac2b75fXyan Bhatnagar    private String mWorkSpecId;
61dc31aa85682ec4cb14784d393b4b70ff4da5d43dXyan Bhatnagar    private ExecutionListener mListener;
62137c84c9c8212a44ee81c238a1a2271637ffa24bSumir Kataria    private List<Scheduler> mSchedulers;
637b5c560e4098585f73564951621060de708e441fSumir Kataria    private Extras.RuntimeExtras mRuntimeExtras;
64fdd887fead7d32e5e69e94d6b2ebe9770b2ec5bbXyan Bhatnagar    private WorkSpec mWorkSpec;
656ae802c24782090d816f3950869a446344206e55Sumir Kataria    Worker mWorker;
669e63790830c817be832dd4f7de2b483c2f555363Sumir Kataria
67e326592ec414dfe4c002e2840d9fc4aef0ee8747Rahul Ravikumar    private Configuration mConfiguration;
689e63790830c817be832dd4f7de2b483c2f555363Sumir Kataria    private WorkDatabase mWorkDatabase;
69fdd887fead7d32e5e69e94d6b2ebe9770b2ec5bbXyan Bhatnagar    private WorkSpecDao mWorkSpecDao;
70fdd887fead7d32e5e69e94d6b2ebe9770b2ec5bbXyan Bhatnagar    private DependencyDao mDependencyDao;
717b5c560e4098585f73564951621060de708e441fSumir Kataria    private WorkTagDao mWorkTagDao;
72969025c012f4a8bd7bccda7216d76fc4636590feXyan Bhatnagar
73b0a0d7b4910f8733c04bc9dd98ec05da7247bdceSumir Kataria    private volatile boolean mInterrupted;
74b0a0d7b4910f8733c04bc9dd98ec05da7247bdceSumir Kataria
75969025c012f4a8bd7bccda7216d76fc4636590feXyan Bhatnagar    private WorkerWrapper(Builder builder) {
76969025c012f4a8bd7bccda7216d76fc4636590feXyan Bhatnagar        mAppContext = builder.mAppContext;
77969025c012f4a8bd7bccda7216d76fc4636590feXyan Bhatnagar        mWorkSpecId = builder.mWorkSpecId;
78969025c012f4a8bd7bccda7216d76fc4636590feXyan Bhatnagar        mListener = builder.mListener;
79137c84c9c8212a44ee81c238a1a2271637ffa24bSumir Kataria        mSchedulers = builder.mSchedulers;
80681a8d809fe41189c9d590d33b986b98170e4963Sumir Kataria        mRuntimeExtras = builder.mRuntimeExtras;
81d64a1a65bd138cfeeb9ae6a595120b85e77a57f6Rahul Ravikumar        mWorker = builder.mWorker;
829e63790830c817be832dd4f7de2b483c2f555363Sumir Kataria
83e326592ec414dfe4c002e2840d9fc4aef0ee8747Rahul Ravikumar        mConfiguration = builder.mConfiguration;
849e63790830c817be832dd4f7de2b483c2f555363Sumir Kataria        mWorkDatabase = builder.mWorkDatabase;
85fdd887fead7d32e5e69e94d6b2ebe9770b2ec5bbXyan Bhatnagar        mWorkSpecDao = mWorkDatabase.workSpecDao();
86fdd887fead7d32e5e69e94d6b2ebe9770b2ec5bbXyan Bhatnagar        mDependencyDao = mWorkDatabase.dependencyDao();
877b5c560e4098585f73564951621060de708e441fSumir Kataria        mWorkTagDao = mWorkDatabase.workTagDao();
88b8909f2c9c62261181e8270be8de44a69ac2b75fXyan Bhatnagar    }
89b8909f2c9c62261181e8270be8de44a69ac2b75fXyan Bhatnagar
90f6d484674fd8f2c3a0bc6a8b5117769a3c9b3640Xyan Bhatnagar    @WorkerThread
91b8909f2c9c62261181e8270be8de44a69ac2b75fXyan Bhatnagar    @Override
92b8909f2c9c62261181e8270be8de44a69ac2b75fXyan Bhatnagar    public void run() {
93b0a0d7b4910f8733c04bc9dd98ec05da7247bdceSumir Kataria        if (tryCheckForInterruptionAndNotify()) {
94b0a0d7b4910f8733c04bc9dd98ec05da7247bdceSumir Kataria            return;
95b0a0d7b4910f8733c04bc9dd98ec05da7247bdceSumir Kataria        }
96b0a0d7b4910f8733c04bc9dd98ec05da7247bdceSumir Kataria
97fdd887fead7d32e5e69e94d6b2ebe9770b2ec5bbXyan Bhatnagar        mWorkSpec = mWorkSpecDao.getWorkSpec(mWorkSpecId);
98fdd887fead7d32e5e69e94d6b2ebe9770b2ec5bbXyan Bhatnagar        if (mWorkSpec == null) {
99697d6a4a3797bc71d0dd8685937a318e9934066bRahul Ravikumar            Log.e(TAG,  String.format("Didn't find WorkSpec for id %s", mWorkSpecId));
100fb351fb5fe9af0af6c37aa282ce3a3325d311425Rahul Ravikumar            notifyListener(false, false);
101b8909f2c9c62261181e8270be8de44a69ac2b75fXyan Bhatnagar            return;
102b8909f2c9c62261181e8270be8de44a69ac2b75fXyan Bhatnagar        }
103b8909f2c9c62261181e8270be8de44a69ac2b75fXyan Bhatnagar
104dcbf20db18e3e93a13e9fa75fa4b723255b87c54Sumir Kataria        // Do a quick check to make sure we don't need to bail out in case this work is already
105dcbf20db18e3e93a13e9fa75fa4b723255b87c54Sumir Kataria        // running, finished, or is blocked.
106b5728f4e1a4b3f4f1fabf033b1363ca6b1cffdefSumir Kataria        if (mWorkSpec.state != ENQUEUED) {
1073557457daf57a3248c72320243263a0387687085Xyan Bhatnagar            notifyIncorrectStatus();
1083557457daf57a3248c72320243263a0387687085Xyan Bhatnagar            return;
109b8909f2c9c62261181e8270be8de44a69ac2b75fXyan Bhatnagar        }
110b8909f2c9c62261181e8270be8de44a69ac2b75fXyan Bhatnagar
111dcbf20db18e3e93a13e9fa75fa4b723255b87c54Sumir Kataria        // Merge inputs.  This can be potentially expensive code, so this should not be done inside
112dcbf20db18e3e93a13e9fa75fa4b723255b87c54Sumir Kataria        // a database transaction.
11364e6bd86c786f1cb1b0c3dbc2b5307cca5c0d1f6Sumir Kataria        Data input;
11449cacea720fca909dfbcbd9c7642a05f3ddee400Sumir Kataria        if (mWorkSpec.isPeriodic()) {
11564e6bd86c786f1cb1b0c3dbc2b5307cca5c0d1f6Sumir Kataria            input = mWorkSpec.input;
11649cacea720fca909dfbcbd9c7642a05f3ddee400Sumir Kataria        } else {
117b5728f4e1a4b3f4f1fabf033b1363ca6b1cffdefSumir Kataria            InputMerger inputMerger = InputMerger.fromClassName(mWorkSpec.inputMergerClassName);
1183557457daf57a3248c72320243263a0387687085Xyan Bhatnagar            if (inputMerger == null) {
119697d6a4a3797bc71d0dd8685937a318e9934066bRahul Ravikumar                Log.e(TAG, String.format("Could not create Input Merger %s",
120697d6a4a3797bc71d0dd8685937a318e9934066bRahul Ravikumar                        mWorkSpec.inputMergerClassName));
1213557457daf57a3248c72320243263a0387687085Xyan Bhatnagar                setFailedAndNotify();
1223557457daf57a3248c72320243263a0387687085Xyan Bhatnagar                return;
1233557457daf57a3248c72320243263a0387687085Xyan Bhatnagar            }
12464e6bd86c786f1cb1b0c3dbc2b5307cca5c0d1f6Sumir Kataria            List<Data> inputs = new ArrayList<>();
12564e6bd86c786f1cb1b0c3dbc2b5307cca5c0d1f6Sumir Kataria            inputs.add(mWorkSpec.input);
12649cacea720fca909dfbcbd9c7642a05f3ddee400Sumir Kataria            inputs.addAll(mWorkSpecDao.getInputsFromPrerequisites(mWorkSpecId));
12764e6bd86c786f1cb1b0c3dbc2b5307cca5c0d1f6Sumir Kataria            input = inputMerger.merge(inputs);
12849cacea720fca909dfbcbd9c7642a05f3ddee400Sumir Kataria        }
129a48d7acf791f20ed5afc8bc8d8c66eebd9fbfd5bSumir Kataria
130b24ef38a0b526b524e3e6a7849f62f934a6ad58cSumir Kataria        Extras extras = new Extras(
131b24ef38a0b526b524e3e6a7849f62f934a6ad58cSumir Kataria                input,
132b24ef38a0b526b524e3e6a7849f62f934a6ad58cSumir Kataria                mWorkTagDao.getTagsForWorkSpecId(mWorkSpecId),
133b24ef38a0b526b524e3e6a7849f62f934a6ad58cSumir Kataria                mRuntimeExtras,
134b24ef38a0b526b524e3e6a7849f62f934a6ad58cSumir Kataria                mWorkSpec.runAttemptCount);
1357b5c560e4098585f73564951621060de708e441fSumir Kataria
136d64a1a65bd138cfeeb9ae6a595120b85e77a57f6Rahul Ravikumar        // Not always creating a worker here, as the WorkerWrapper.Builder can set a worker override
137d64a1a65bd138cfeeb9ae6a595120b85e77a57f6Rahul Ravikumar        // in test mode.
138d64a1a65bd138cfeeb9ae6a595120b85e77a57f6Rahul Ravikumar        if (mWorker == null) {
1397b5c560e4098585f73564951621060de708e441fSumir Kataria            mWorker = workerFromWorkSpec(mAppContext, mWorkSpec, extras);
140d64a1a65bd138cfeeb9ae6a595120b85e77a57f6Rahul Ravikumar        }
1413557457daf57a3248c72320243263a0387687085Xyan Bhatnagar
1421e9589d6482d2690e2eabb21f732377d268a5c05Sumir Kataria        if (mWorker == null) {
143697d6a4a3797bc71d0dd8685937a318e9934066bRahul Ravikumar            Log.e(TAG, String.format("Could for create Worker %s", mWorkSpec.workerClassName));
1443557457daf57a3248c72320243263a0387687085Xyan Bhatnagar            setFailedAndNotify();
145b8909f2c9c62261181e8270be8de44a69ac2b75fXyan Bhatnagar            return;
146b8909f2c9c62261181e8270be8de44a69ac2b75fXyan Bhatnagar        }
147b8909f2c9c62261181e8270be8de44a69ac2b75fXyan Bhatnagar
148dcbf20db18e3e93a13e9fa75fa4b723255b87c54Sumir Kataria        // Try to set the work to the running state.  Note that this may fail because another thread
149dcbf20db18e3e93a13e9fa75fa4b723255b87c54Sumir Kataria        // may have modified the DB since we checked last at the top of this function.
150dcbf20db18e3e93a13e9fa75fa4b723255b87c54Sumir Kataria        if (trySetRunning()) {
151b0a0d7b4910f8733c04bc9dd98ec05da7247bdceSumir Kataria            if (tryCheckForInterruptionAndNotify()) {
152b0a0d7b4910f8733c04bc9dd98ec05da7247bdceSumir Kataria                return;
153b0a0d7b4910f8733c04bc9dd98ec05da7247bdceSumir Kataria            }
154b0a0d7b4910f8733c04bc9dd98ec05da7247bdceSumir Kataria
15511a7c26af63674a21787696e509e9a43d0bd7acfSumir Kataria            Worker.Result result;
1563f0c0fbaf4be127488fc900d915d1c966813a4e6Sumir Kataria            try {
1573f0c0fbaf4be127488fc900d915d1c966813a4e6Sumir Kataria                result = mWorker.doWork();
1583f0c0fbaf4be127488fc900d915d1c966813a4e6Sumir Kataria            } catch (Exception | Error e) {
15911a7c26af63674a21787696e509e9a43d0bd7acfSumir Kataria                result = Worker.Result.FAILURE;
1603f0c0fbaf4be127488fc900d915d1c966813a4e6Sumir Kataria            }
161b0a0d7b4910f8733c04bc9dd98ec05da7247bdceSumir Kataria
162dcbf20db18e3e93a13e9fa75fa4b723255b87c54Sumir Kataria            try {
163b0a0d7b4910f8733c04bc9dd98ec05da7247bdceSumir Kataria                mWorkDatabase.beginTransaction();
164b0a0d7b4910f8733c04bc9dd98ec05da7247bdceSumir Kataria                if (!tryCheckForInterruptionAndNotify()) {
165b0a0d7b4910f8733c04bc9dd98ec05da7247bdceSumir Kataria                    State state = mWorkSpecDao.getState(mWorkSpecId);
166d874811ee5f3275e6022115a03aa6001dc1830a9Sumir Kataria                    if (state == null) {
1671b87cb6abe29d752f0594bf5afe96fcd8f4e9ae2Rahul Ravikumar                        // state can be null here with a REPLACE on beginUniqueWork().
1681b87cb6abe29d752f0594bf5afe96fcd8f4e9ae2Rahul Ravikumar                        // Treat it as a failure, and rescheduleAndNotify() will
1691b87cb6abe29d752f0594bf5afe96fcd8f4e9ae2Rahul Ravikumar                        // turn into a no-op. We still need to notify potential observers
1701b87cb6abe29d752f0594bf5afe96fcd8f4e9ae2Rahul Ravikumar                        // holding on to wake locks on our behalf.
171d874811ee5f3275e6022115a03aa6001dc1830a9Sumir Kataria                        notifyListener(false, false);
172d874811ee5f3275e6022115a03aa6001dc1830a9Sumir Kataria                    } else if (state == RUNNING) {
173d874811ee5f3275e6022115a03aa6001dc1830a9Sumir Kataria                        handleResult(result);
174d874811ee5f3275e6022115a03aa6001dc1830a9Sumir Kataria                    } else if (!state.isFinished()) {
175b0a0d7b4910f8733c04bc9dd98ec05da7247bdceSumir Kataria                        rescheduleAndNotify();
176b0a0d7b4910f8733c04bc9dd98ec05da7247bdceSumir Kataria                    }
177b0a0d7b4910f8733c04bc9dd98ec05da7247bdceSumir Kataria                    mWorkDatabase.setTransactionSuccessful();
178dcbf20db18e3e93a13e9fa75fa4b723255b87c54Sumir Kataria                }
179b0a0d7b4910f8733c04bc9dd98ec05da7247bdceSumir Kataria            } finally {
180b0a0d7b4910f8733c04bc9dd98ec05da7247bdceSumir Kataria                mWorkDatabase.endTransaction();
1812ace67d8c1383f7c33940d48817fd4d362105641Sumir Kataria            }
182dcbf20db18e3e93a13e9fa75fa4b723255b87c54Sumir Kataria        } else {
183dcbf20db18e3e93a13e9fa75fa4b723255b87c54Sumir Kataria            notifyIncorrectStatus();
1843557457daf57a3248c72320243263a0387687085Xyan Bhatnagar        }
1853557457daf57a3248c72320243263a0387687085Xyan Bhatnagar    }
1863557457daf57a3248c72320243263a0387687085Xyan Bhatnagar
187b0a0d7b4910f8733c04bc9dd98ec05da7247bdceSumir Kataria    /**
188b0a0d7b4910f8733c04bc9dd98ec05da7247bdceSumir Kataria     * @hide
189b0a0d7b4910f8733c04bc9dd98ec05da7247bdceSumir Kataria     */
190b0a0d7b4910f8733c04bc9dd98ec05da7247bdceSumir Kataria    @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
1915d373d376edddb57cd822dd06ed54f97ef949586Sumir Kataria    public void interrupt(boolean cancelled) {
192b0a0d7b4910f8733c04bc9dd98ec05da7247bdceSumir Kataria        mInterrupted = true;
193bf4f4f72fd27f110b95cc9867fb5dc695d2689b1Sumir Kataria        // Worker can be null if run() hasn't been called yet.
194bf4f4f72fd27f110b95cc9867fb5dc695d2689b1Sumir Kataria        if (mWorker != null) {
1955d373d376edddb57cd822dd06ed54f97ef949586Sumir Kataria            mWorker.stop(cancelled);
196bf4f4f72fd27f110b95cc9867fb5dc695d2689b1Sumir Kataria        }
197b0a0d7b4910f8733c04bc9dd98ec05da7247bdceSumir Kataria    }
198b0a0d7b4910f8733c04bc9dd98ec05da7247bdceSumir Kataria
1993557457daf57a3248c72320243263a0387687085Xyan Bhatnagar    private void notifyIncorrectStatus() {
200dcbf20db18e3e93a13e9fa75fa4b723255b87c54Sumir Kataria        State status = mWorkSpecDao.getState(mWorkSpecId);
2014ee69ffea5f5636674c7aa8a19366dd950c9b770Sumir Kataria        if (status == RUNNING) {
202697d6a4a3797bc71d0dd8685937a318e9934066bRahul Ravikumar            Log.d(TAG, String.format("Status for %s is RUNNING;"
203697d6a4a3797bc71d0dd8685937a318e9934066bRahul Ravikumar                    + "not doing any work and rescheduling for later execution", mWorkSpecId));
204fb351fb5fe9af0af6c37aa282ce3a3325d311425Rahul Ravikumar            notifyListener(false, true);
2053557457daf57a3248c72320243263a0387687085Xyan Bhatnagar        } else {
206697d6a4a3797bc71d0dd8685937a318e9934066bRahul Ravikumar            Log.e(TAG,
207697d6a4a3797bc71d0dd8685937a318e9934066bRahul Ravikumar                    String.format("Status for %s is %s; not doing any work", mWorkSpecId, status));
208fb351fb5fe9af0af6c37aa282ce3a3325d311425Rahul Ravikumar            notifyListener(false, false);
209d7b783ea8f3a1e7fe1318681573a59bdf341b9dbXyan Bhatnagar        }
210d7b783ea8f3a1e7fe1318681573a59bdf341b9dbXyan Bhatnagar    }
211d7b783ea8f3a1e7fe1318681573a59bdf341b9dbXyan Bhatnagar
212b0a0d7b4910f8733c04bc9dd98ec05da7247bdceSumir Kataria    private boolean tryCheckForInterruptionAndNotify() {
213b0a0d7b4910f8733c04bc9dd98ec05da7247bdceSumir Kataria        if (mInterrupted) {
214b0a0d7b4910f8733c04bc9dd98ec05da7247bdceSumir Kataria            Log.d(TAG, String.format("Work interrupted for %s", mWorkSpecId));
215b0a0d7b4910f8733c04bc9dd98ec05da7247bdceSumir Kataria            State currentState = mWorkSpecDao.getState(mWorkSpecId);
216d874811ee5f3275e6022115a03aa6001dc1830a9Sumir Kataria            if (currentState == null) {
217d874811ee5f3275e6022115a03aa6001dc1830a9Sumir Kataria                // This can happen because of a beginUniqueWork(..., REPLACE, ...).  Notify the
218d874811ee5f3275e6022115a03aa6001dc1830a9Sumir Kataria                // listeners so we can clean up any wake locks, etc.
219d874811ee5f3275e6022115a03aa6001dc1830a9Sumir Kataria                notifyListener(false, false);
220d874811ee5f3275e6022115a03aa6001dc1830a9Sumir Kataria            } else {
221d874811ee5f3275e6022115a03aa6001dc1830a9Sumir Kataria                notifyListener(currentState == SUCCEEDED, !currentState.isFinished());
222d874811ee5f3275e6022115a03aa6001dc1830a9Sumir Kataria            }
223b0a0d7b4910f8733c04bc9dd98ec05da7247bdceSumir Kataria            return true;
224d7b783ea8f3a1e7fe1318681573a59bdf341b9dbXyan Bhatnagar        }
225b0a0d7b4910f8733c04bc9dd98ec05da7247bdceSumir Kataria        return false;
226b8909f2c9c62261181e8270be8de44a69ac2b75fXyan Bhatnagar    }
227dc31aa85682ec4cb14784d393b4b70ff4da5d43dXyan Bhatnagar
228fb351fb5fe9af0af6c37aa282ce3a3325d311425Rahul Ravikumar    private void notifyListener(final boolean isSuccessful, final boolean needsReschedule) {
229969025c012f4a8bd7bccda7216d76fc4636590feXyan Bhatnagar        if (mListener == null) {
230969025c012f4a8bd7bccda7216d76fc4636590feXyan Bhatnagar            return;
231969025c012f4a8bd7bccda7216d76fc4636590feXyan Bhatnagar        }
232687da3388ece2fefd80c710c382dff908b615a3fXyan Bhatnagar        WorkManagerTaskExecutor.getInstance().postToMainThread(new Runnable() {
233dc31aa85682ec4cb14784d393b4b70ff4da5d43dXyan Bhatnagar            @Override
234dc31aa85682ec4cb14784d393b4b70ff4da5d43dXyan Bhatnagar            public void run() {
235fb351fb5fe9af0af6c37aa282ce3a3325d311425Rahul Ravikumar                mListener.onExecuted(mWorkSpecId, isSuccessful, needsReschedule);
236dc31aa85682ec4cb14784d393b4b70ff4da5d43dXyan Bhatnagar            }
237dc31aa85682ec4cb14784d393b4b70ff4da5d43dXyan Bhatnagar        });
238dc31aa85682ec4cb14784d393b4b70ff4da5d43dXyan Bhatnagar    }
2396463bebf1255dabbe9b5efd1c3be20e7dfd74551Xyan Bhatnagar
24011a7c26af63674a21787696e509e9a43d0bd7acfSumir Kataria    private void handleResult(Worker.Result result) {
241fdd887fead7d32e5e69e94d6b2ebe9770b2ec5bbXyan Bhatnagar        switch (result) {
242d7c332544c4dc6e06b4a876fd10c25b0469e81bcSumir Kataria            case SUCCESS: {
243697d6a4a3797bc71d0dd8685937a318e9934066bRahul Ravikumar                Log.d(TAG, String.format("Worker result SUCCESS for %s", mWorkSpecId));
244fdd887fead7d32e5e69e94d6b2ebe9770b2ec5bbXyan Bhatnagar                if (mWorkSpec.isPeriodic()) {
245fb351fb5fe9af0af6c37aa282ce3a3325d311425Rahul Ravikumar                    resetPeriodicAndNotify(true);
246fdd887fead7d32e5e69e94d6b2ebe9770b2ec5bbXyan Bhatnagar                } else {
2473557457daf57a3248c72320243263a0387687085Xyan Bhatnagar                    setSucceededAndNotify();
248fdd887fead7d32e5e69e94d6b2ebe9770b2ec5bbXyan Bhatnagar                }
249fdd887fead7d32e5e69e94d6b2ebe9770b2ec5bbXyan Bhatnagar                break;
250fdd887fead7d32e5e69e94d6b2ebe9770b2ec5bbXyan Bhatnagar            }
251fdd887fead7d32e5e69e94d6b2ebe9770b2ec5bbXyan Bhatnagar
252d7c332544c4dc6e06b4a876fd10c25b0469e81bcSumir Kataria            case RETRY: {
253697d6a4a3797bc71d0dd8685937a318e9934066bRahul Ravikumar                Log.d(TAG, String.format("Worker result RETRY for %s", mWorkSpecId));
254b0a0d7b4910f8733c04bc9dd98ec05da7247bdceSumir Kataria                rescheduleAndNotify();
255fdd887fead7d32e5e69e94d6b2ebe9770b2ec5bbXyan Bhatnagar                break;
256fdd887fead7d32e5e69e94d6b2ebe9770b2ec5bbXyan Bhatnagar            }
257fdd887fead7d32e5e69e94d6b2ebe9770b2ec5bbXyan Bhatnagar
258d7c332544c4dc6e06b4a876fd10c25b0469e81bcSumir Kataria            case FAILURE:
259fdd887fead7d32e5e69e94d6b2ebe9770b2ec5bbXyan Bhatnagar            default: {
260697d6a4a3797bc71d0dd8685937a318e9934066bRahul Ravikumar                Log.d(TAG, String.format("Worker result FAILURE for %s", mWorkSpecId));
261fdd887fead7d32e5e69e94d6b2ebe9770b2ec5bbXyan Bhatnagar                if (mWorkSpec.isPeriodic()) {
262fb351fb5fe9af0af6c37aa282ce3a3325d311425Rahul Ravikumar                    resetPeriodicAndNotify(false);
263fdd887fead7d32e5e69e94d6b2ebe9770b2ec5bbXyan Bhatnagar                } else {
2643557457daf57a3248c72320243263a0387687085Xyan Bhatnagar                    setFailedAndNotify();
265fdd887fead7d32e5e69e94d6b2ebe9770b2ec5bbXyan Bhatnagar                }
266fdd887fead7d32e5e69e94d6b2ebe9770b2ec5bbXyan Bhatnagar            }
267fdd887fead7d32e5e69e94d6b2ebe9770b2ec5bbXyan Bhatnagar        }
268fdd887fead7d32e5e69e94d6b2ebe9770b2ec5bbXyan Bhatnagar    }
269fdd887fead7d32e5e69e94d6b2ebe9770b2ec5bbXyan Bhatnagar
270dcbf20db18e3e93a13e9fa75fa4b723255b87c54Sumir Kataria    private boolean trySetRunning() {
271dcbf20db18e3e93a13e9fa75fa4b723255b87c54Sumir Kataria        boolean setToRunning = false;
2723557457daf57a3248c72320243263a0387687085Xyan Bhatnagar        mWorkDatabase.beginTransaction();
2733557457daf57a3248c72320243263a0387687085Xyan Bhatnagar        try {
274dcbf20db18e3e93a13e9fa75fa4b723255b87c54Sumir Kataria            State currentState = mWorkSpecDao.getState(mWorkSpecId);
275dcbf20db18e3e93a13e9fa75fa4b723255b87c54Sumir Kataria            if (currentState == ENQUEUED) {
276dcbf20db18e3e93a13e9fa75fa4b723255b87c54Sumir Kataria                mWorkSpecDao.setState(RUNNING, mWorkSpecId);
277dcbf20db18e3e93a13e9fa75fa4b723255b87c54Sumir Kataria                mWorkSpecDao.incrementWorkSpecRunAttemptCount(mWorkSpecId);
278dcbf20db18e3e93a13e9fa75fa4b723255b87c54Sumir Kataria                mWorkDatabase.setTransactionSuccessful();
279dcbf20db18e3e93a13e9fa75fa4b723255b87c54Sumir Kataria                setToRunning = true;
280dcbf20db18e3e93a13e9fa75fa4b723255b87c54Sumir Kataria            }
2813557457daf57a3248c72320243263a0387687085Xyan Bhatnagar        } finally {
2823557457daf57a3248c72320243263a0387687085Xyan Bhatnagar            mWorkDatabase.endTransaction();
2833557457daf57a3248c72320243263a0387687085Xyan Bhatnagar        }
284dcbf20db18e3e93a13e9fa75fa4b723255b87c54Sumir Kataria        return setToRunning;
2853557457daf57a3248c72320243263a0387687085Xyan Bhatnagar    }
2863557457daf57a3248c72320243263a0387687085Xyan Bhatnagar
2873557457daf57a3248c72320243263a0387687085Xyan Bhatnagar    private void setFailedAndNotify() {
28886666efc34520f0ac97e0fbde5229ba560caac46Sumir Kataria        mWorkDatabase.beginTransaction();
28986666efc34520f0ac97e0fbde5229ba560caac46Sumir Kataria        try {
290c1ba633e4668bbf02097a76261ebcee8f3b59e06Sumir Kataria            recursivelyFailWorkAndDependents(mWorkSpecId);
291c1ba633e4668bbf02097a76261ebcee8f3b59e06Sumir Kataria
292c1ba633e4668bbf02097a76261ebcee8f3b59e06Sumir Kataria            // Try to set the output for the failed work but check if the worker exists; this could
293c1ba633e4668bbf02097a76261ebcee8f3b59e06Sumir Kataria            // be a permanent error where we couldn't find or create the worker class.
29486666efc34520f0ac97e0fbde5229ba560caac46Sumir Kataria            if (mWorker != null) {
29564e6bd86c786f1cb1b0c3dbc2b5307cca5c0d1f6Sumir Kataria                // Update Data as necessary.
29664e6bd86c786f1cb1b0c3dbc2b5307cca5c0d1f6Sumir Kataria                Data output = mWorker.getOutputData();
297b9701e2752b53221501cfaeb247256f1ae12baecSumir Kataria                mWorkSpecDao.setOutput(mWorkSpecId, output);
29886666efc34520f0ac97e0fbde5229ba560caac46Sumir Kataria            }
299c1ba633e4668bbf02097a76261ebcee8f3b59e06Sumir Kataria
30086666efc34520f0ac97e0fbde5229ba560caac46Sumir Kataria            mWorkDatabase.setTransactionSuccessful();
30186666efc34520f0ac97e0fbde5229ba560caac46Sumir Kataria        } finally {
30286666efc34520f0ac97e0fbde5229ba560caac46Sumir Kataria            mWorkDatabase.endTransaction();
30386666efc34520f0ac97e0fbde5229ba560caac46Sumir Kataria            notifyListener(false, false);
30486666efc34520f0ac97e0fbde5229ba560caac46Sumir Kataria        }
3059f91ee8c71606f36a51177cd0b5c3005834be1ffRahul Ravikumar
306e326592ec414dfe4c002e2840d9fc4aef0ee8747Rahul Ravikumar        Schedulers.schedule(mConfiguration, mWorkDatabase, mSchedulers);
3073557457daf57a3248c72320243263a0387687085Xyan Bhatnagar    }
3083557457daf57a3248c72320243263a0387687085Xyan Bhatnagar
309c1ba633e4668bbf02097a76261ebcee8f3b59e06Sumir Kataria    private void recursivelyFailWorkAndDependents(String workSpecId) {
310c1ba633e4668bbf02097a76261ebcee8f3b59e06Sumir Kataria        List<String> dependentIds = mDependencyDao.getDependentWorkIds(workSpecId);
311c1ba633e4668bbf02097a76261ebcee8f3b59e06Sumir Kataria        for (String id : dependentIds) {
312c1ba633e4668bbf02097a76261ebcee8f3b59e06Sumir Kataria            recursivelyFailWorkAndDependents(id);
313c1ba633e4668bbf02097a76261ebcee8f3b59e06Sumir Kataria        }
314c1ba633e4668bbf02097a76261ebcee8f3b59e06Sumir Kataria
315c1ba633e4668bbf02097a76261ebcee8f3b59e06Sumir Kataria        // Don't fail already cancelled work.
3165b84f5ce59c65703ce6d5cdb1133185cd93e1862Sumir Kataria        if (mWorkSpecDao.getState(workSpecId) != CANCELLED) {
317c1ba633e4668bbf02097a76261ebcee8f3b59e06Sumir Kataria            mWorkSpecDao.setState(FAILED, workSpecId);
318c1ba633e4668bbf02097a76261ebcee8f3b59e06Sumir Kataria        }
319c1ba633e4668bbf02097a76261ebcee8f3b59e06Sumir Kataria    }
320c1ba633e4668bbf02097a76261ebcee8f3b59e06Sumir Kataria
321b0a0d7b4910f8733c04bc9dd98ec05da7247bdceSumir Kataria    private void rescheduleAndNotify() {
3221c78bb2b576a34e69875808aa675e1ca5d5068b4Xyan Bhatnagar        mWorkDatabase.beginTransaction();
3231c78bb2b576a34e69875808aa675e1ca5d5068b4Xyan Bhatnagar        try {
3249cf4f3d3aa83bc64db574955805c67ac9ea84008Sumir Kataria            mWorkSpecDao.setState(ENQUEUED, mWorkSpecId);
3251c78bb2b576a34e69875808aa675e1ca5d5068b4Xyan Bhatnagar            // TODO(xbhatnag): Period Start Time is confusing for non-periodic work. Rename.
3261c78bb2b576a34e69875808aa675e1ca5d5068b4Xyan Bhatnagar            mWorkSpecDao.setPeriodStartTime(mWorkSpecId, System.currentTimeMillis());
3271c78bb2b576a34e69875808aa675e1ca5d5068b4Xyan Bhatnagar            mWorkDatabase.setTransactionSuccessful();
3281c78bb2b576a34e69875808aa675e1ca5d5068b4Xyan Bhatnagar        } finally {
3291c78bb2b576a34e69875808aa675e1ca5d5068b4Xyan Bhatnagar            mWorkDatabase.endTransaction();
330b0a0d7b4910f8733c04bc9dd98ec05da7247bdceSumir Kataria            notifyListener(false, true);
3311c78bb2b576a34e69875808aa675e1ca5d5068b4Xyan Bhatnagar        }
3321c78bb2b576a34e69875808aa675e1ca5d5068b4Xyan Bhatnagar    }
3331c78bb2b576a34e69875808aa675e1ca5d5068b4Xyan Bhatnagar
334fb351fb5fe9af0af6c37aa282ce3a3325d311425Rahul Ravikumar    private void resetPeriodicAndNotify(boolean isSuccessful) {
335fdd887fead7d32e5e69e94d6b2ebe9770b2ec5bbXyan Bhatnagar        mWorkDatabase.beginTransaction();
336fdd887fead7d32e5e69e94d6b2ebe9770b2ec5bbXyan Bhatnagar        try {
337b5728f4e1a4b3f4f1fabf033b1363ca6b1cffdefSumir Kataria            long currentPeriodStartTime = mWorkSpec.periodStartTime;
338b5728f4e1a4b3f4f1fabf033b1363ca6b1cffdefSumir Kataria            long nextPeriodStartTime = currentPeriodStartTime + mWorkSpec.intervalDuration;
3390deb5e280d72959e89e7c4433e15c77f6523b693Jan Clarin            mWorkSpecDao.setPeriodStartTime(mWorkSpecId, nextPeriodStartTime);
3409cf4f3d3aa83bc64db574955805c67ac9ea84008Sumir Kataria            mWorkSpecDao.setState(ENQUEUED, mWorkSpecId);
341fdd887fead7d32e5e69e94d6b2ebe9770b2ec5bbXyan Bhatnagar            mWorkSpecDao.resetWorkSpecRunAttemptCount(mWorkSpecId);
342fdd887fead7d32e5e69e94d6b2ebe9770b2ec5bbXyan Bhatnagar            mWorkDatabase.setTransactionSuccessful();
343fdd887fead7d32e5e69e94d6b2ebe9770b2ec5bbXyan Bhatnagar        } finally {
344fdd887fead7d32e5e69e94d6b2ebe9770b2ec5bbXyan Bhatnagar            mWorkDatabase.endTransaction();
345fb351fb5fe9af0af6c37aa282ce3a3325d311425Rahul Ravikumar            notifyListener(isSuccessful, false);
346fdd887fead7d32e5e69e94d6b2ebe9770b2ec5bbXyan Bhatnagar        }
347fdd887fead7d32e5e69e94d6b2ebe9770b2ec5bbXyan Bhatnagar    }
3485643e2e608bf406eaf6a8bc990b9bad7a7deb97dSumir Kataria
3493557457daf57a3248c72320243263a0387687085Xyan Bhatnagar    private void setSucceededAndNotify() {
3506463bebf1255dabbe9b5efd1c3be20e7dfd74551Xyan Bhatnagar        mWorkDatabase.beginTransaction();
3516463bebf1255dabbe9b5efd1c3be20e7dfd74551Xyan Bhatnagar        try {
3529cf4f3d3aa83bc64db574955805c67ac9ea84008Sumir Kataria            mWorkSpecDao.setState(SUCCEEDED, mWorkSpecId);
3536ae802c24782090d816f3950869a446344206e55Sumir Kataria
35464e6bd86c786f1cb1b0c3dbc2b5307cca5c0d1f6Sumir Kataria            // Update Data as necessary.
35564e6bd86c786f1cb1b0c3dbc2b5307cca5c0d1f6Sumir Kataria            Data output = mWorker.getOutputData();
356b9701e2752b53221501cfaeb247256f1ae12baecSumir Kataria            mWorkSpecDao.setOutput(mWorkSpecId, output);
3576ae802c24782090d816f3950869a446344206e55Sumir Kataria
3583557457daf57a3248c72320243263a0387687085Xyan Bhatnagar            // Unblock Dependencies and set Period Start Time
3590deb5e280d72959e89e7c4433e15c77f6523b693Jan Clarin            long currentTimeMillis = System.currentTimeMillis();
3609244d377b9c9216a474b12d1a5f6aaa787941af4Sumir Kataria            List<String> dependentWorkIds = mDependencyDao.getDependentWorkIds(mWorkSpecId);
3619244d377b9c9216a474b12d1a5f6aaa787941af4Sumir Kataria            for (String dependentWorkId : dependentWorkIds) {
3629244d377b9c9216a474b12d1a5f6aaa787941af4Sumir Kataria                if (mDependencyDao.hasCompletedAllPrerequisites(dependentWorkId)) {
363697d6a4a3797bc71d0dd8685937a318e9934066bRahul Ravikumar                    Log.d(TAG, String.format("Setting status to enqueued for %s", dependentWorkId));
3649cf4f3d3aa83bc64db574955805c67ac9ea84008Sumir Kataria                    mWorkSpecDao.setState(ENQUEUED, dependentWorkId);
3650deb5e280d72959e89e7c4433e15c77f6523b693Jan Clarin                    mWorkSpecDao.setPeriodStartTime(dependentWorkId, currentTimeMillis);
3669244d377b9c9216a474b12d1a5f6aaa787941af4Sumir Kataria                }
3679244d377b9c9216a474b12d1a5f6aaa787941af4Sumir Kataria            }
3686ae802c24782090d816f3950869a446344206e55Sumir Kataria
3695611e083e6e2713f155fbdea091c1fa13c479b5cSumir Kataria            mWorkDatabase.setTransactionSuccessful();
3705611e083e6e2713f155fbdea091c1fa13c479b5cSumir Kataria        } finally {
3715611e083e6e2713f155fbdea091c1fa13c479b5cSumir Kataria            mWorkDatabase.endTransaction();
3725611e083e6e2713f155fbdea091c1fa13c479b5cSumir Kataria            notifyListener(true, false);
3735611e083e6e2713f155fbdea091c1fa13c479b5cSumir Kataria        }
3745611e083e6e2713f155fbdea091c1fa13c479b5cSumir Kataria
3759f91ee8c71606f36a51177cd0b5c3005834be1ffRahul Ravikumar        // This takes of scheduling the dependent workers as they have been marked ENQUEUED.
376e326592ec414dfe4c002e2840d9fc4aef0ee8747Rahul Ravikumar        Schedulers.schedule(mConfiguration, mWorkDatabase, mSchedulers);
3776463bebf1255dabbe9b5efd1c3be20e7dfd74551Xyan Bhatnagar    }
378969025c012f4a8bd7bccda7216d76fc4636590feXyan Bhatnagar
379da315bf9331a3ead74483bd0d38fd331f4a96088Sumir Kataria    static Worker workerFromWorkSpec(@NonNull Context context,
380da315bf9331a3ead74483bd0d38fd331f4a96088Sumir Kataria            @NonNull WorkSpec workSpec,
3817b5c560e4098585f73564951621060de708e441fSumir Kataria            @NonNull Extras extras) {
382b5728f4e1a4b3f4f1fabf033b1363ca6b1cffdefSumir Kataria        String workerClassName = workSpec.workerClassName;
383dd5f33cd6b98eba208ac7c69d3d6314d3115e2d2Sumir Kataria        UUID workSpecId = UUID.fromString(workSpec.id);
384681a8d809fe41189c9d590d33b986b98170e4963Sumir Kataria        return workerFromClassName(
385681a8d809fe41189c9d590d33b986b98170e4963Sumir Kataria                context,
386681a8d809fe41189c9d590d33b986b98170e4963Sumir Kataria                workerClassName,
387681a8d809fe41189c9d590d33b986b98170e4963Sumir Kataria                workSpecId,
3887b5c560e4098585f73564951621060de708e441fSumir Kataria                extras);
389d64a1a65bd138cfeeb9ae6a595120b85e77a57f6Rahul Ravikumar    }
390d64a1a65bd138cfeeb9ae6a595120b85e77a57f6Rahul Ravikumar
391d64a1a65bd138cfeeb9ae6a595120b85e77a57f6Rahul Ravikumar    /**
392d64a1a65bd138cfeeb9ae6a595120b85e77a57f6Rahul Ravikumar     * Creates a {@link Worker} reflectively & initializes the worker.
393d64a1a65bd138cfeeb9ae6a595120b85e77a57f6Rahul Ravikumar     *
394d64a1a65bd138cfeeb9ae6a595120b85e77a57f6Rahul Ravikumar     * @param context         The application {@link Context}
395d64a1a65bd138cfeeb9ae6a595120b85e77a57f6Rahul Ravikumar     * @param workerClassName The fully qualified class name for the {@link Worker}
396d64a1a65bd138cfeeb9ae6a595120b85e77a57f6Rahul Ravikumar     * @param workSpecId      The {@link WorkSpec} identifier
3977b5c560e4098585f73564951621060de708e441fSumir Kataria     * @param extras          The {@link Extras} for the worker
398d64a1a65bd138cfeeb9ae6a595120b85e77a57f6Rahul Ravikumar     * @return The instance of {@link Worker}
399d64a1a65bd138cfeeb9ae6a595120b85e77a57f6Rahul Ravikumar     *
400d64a1a65bd138cfeeb9ae6a595120b85e77a57f6Rahul Ravikumar     * @hide
401d64a1a65bd138cfeeb9ae6a595120b85e77a57f6Rahul Ravikumar     */
402d64a1a65bd138cfeeb9ae6a595120b85e77a57f6Rahul Ravikumar    @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
403d64a1a65bd138cfeeb9ae6a595120b85e77a57f6Rahul Ravikumar    @SuppressWarnings("ClassNewInstance")
404d64a1a65bd138cfeeb9ae6a595120b85e77a57f6Rahul Ravikumar    public static Worker workerFromClassName(
405d64a1a65bd138cfeeb9ae6a595120b85e77a57f6Rahul Ravikumar            @NonNull Context context,
406d64a1a65bd138cfeeb9ae6a595120b85e77a57f6Rahul Ravikumar            @NonNull String workerClassName,
407dd5f33cd6b98eba208ac7c69d3d6314d3115e2d2Sumir Kataria            @NonNull UUID workSpecId,
4087b5c560e4098585f73564951621060de708e441fSumir Kataria            @NonNull Extras extras) {
409d64a1a65bd138cfeeb9ae6a595120b85e77a57f6Rahul Ravikumar        Context appContext = context.getApplicationContext();
410da315bf9331a3ead74483bd0d38fd331f4a96088Sumir Kataria        try {
411da315bf9331a3ead74483bd0d38fd331f4a96088Sumir Kataria            Class<?> clazz = Class.forName(workerClassName);
412da315bf9331a3ead74483bd0d38fd331f4a96088Sumir Kataria            Worker worker = (Worker) clazz.newInstance();
413da315bf9331a3ead74483bd0d38fd331f4a96088Sumir Kataria            Method internalInitMethod = Worker.class.getDeclaredMethod(
414681a8d809fe41189c9d590d33b986b98170e4963Sumir Kataria                    "internalInit",
415681a8d809fe41189c9d590d33b986b98170e4963Sumir Kataria                    Context.class,
416dd5f33cd6b98eba208ac7c69d3d6314d3115e2d2Sumir Kataria                    UUID.class,
4177b5c560e4098585f73564951621060de708e441fSumir Kataria                    Extras.class);
418da315bf9331a3ead74483bd0d38fd331f4a96088Sumir Kataria            internalInitMethod.setAccessible(true);
419681a8d809fe41189c9d590d33b986b98170e4963Sumir Kataria            internalInitMethod.invoke(
420681a8d809fe41189c9d590d33b986b98170e4963Sumir Kataria                    worker,
421681a8d809fe41189c9d590d33b986b98170e4963Sumir Kataria                    appContext,
422681a8d809fe41189c9d590d33b986b98170e4963Sumir Kataria                    workSpecId,
4237b5c560e4098585f73564951621060de708e441fSumir Kataria                    extras);
424da315bf9331a3ead74483bd0d38fd331f4a96088Sumir Kataria            return worker;
425da315bf9331a3ead74483bd0d38fd331f4a96088Sumir Kataria        } catch (Exception e) {
426da315bf9331a3ead74483bd0d38fd331f4a96088Sumir Kataria            Log.e(TAG, "Trouble instantiating " + workerClassName, e);
427da315bf9331a3ead74483bd0d38fd331f4a96088Sumir Kataria        }
428da315bf9331a3ead74483bd0d38fd331f4a96088Sumir Kataria        return null;
429da315bf9331a3ead74483bd0d38fd331f4a96088Sumir Kataria    }
430da315bf9331a3ead74483bd0d38fd331f4a96088Sumir Kataria
431969025c012f4a8bd7bccda7216d76fc4636590feXyan Bhatnagar    /**
432969025c012f4a8bd7bccda7216d76fc4636590feXyan Bhatnagar     * Builder class for {@link WorkerWrapper}
433d64a1a65bd138cfeeb9ae6a595120b85e77a57f6Rahul Ravikumar     * @hide
434969025c012f4a8bd7bccda7216d76fc4636590feXyan Bhatnagar     */
435d64a1a65bd138cfeeb9ae6a595120b85e77a57f6Rahul Ravikumar    @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
436d64a1a65bd138cfeeb9ae6a595120b85e77a57f6Rahul Ravikumar    public static class Builder {
437969025c012f4a8bd7bccda7216d76fc4636590feXyan Bhatnagar        private Context mAppContext;
438d64a1a65bd138cfeeb9ae6a595120b85e77a57f6Rahul Ravikumar        @Nullable
439d64a1a65bd138cfeeb9ae6a595120b85e77a57f6Rahul Ravikumar        private Worker mWorker;
440e326592ec414dfe4c002e2840d9fc4aef0ee8747Rahul Ravikumar        private Configuration mConfiguration;
441969025c012f4a8bd7bccda7216d76fc4636590feXyan Bhatnagar        private WorkDatabase mWorkDatabase;
442969025c012f4a8bd7bccda7216d76fc4636590feXyan Bhatnagar        private String mWorkSpecId;
443969025c012f4a8bd7bccda7216d76fc4636590feXyan Bhatnagar        private ExecutionListener mListener;
444137c84c9c8212a44ee81c238a1a2271637ffa24bSumir Kataria        private List<Scheduler> mSchedulers;
4457b5c560e4098585f73564951621060de708e441fSumir Kataria        private Extras.RuntimeExtras mRuntimeExtras;
446969025c012f4a8bd7bccda7216d76fc4636590feXyan Bhatnagar
447d64a1a65bd138cfeeb9ae6a595120b85e77a57f6Rahul Ravikumar        public Builder(@NonNull Context context,
448e326592ec414dfe4c002e2840d9fc4aef0ee8747Rahul Ravikumar                @NonNull Configuration configuration,
449969025c012f4a8bd7bccda7216d76fc4636590feXyan Bhatnagar                @NonNull WorkDatabase database,
450969025c012f4a8bd7bccda7216d76fc4636590feXyan Bhatnagar                @NonNull String workSpecId) {
451969025c012f4a8bd7bccda7216d76fc4636590feXyan Bhatnagar            mAppContext = context.getApplicationContext();
452e326592ec414dfe4c002e2840d9fc4aef0ee8747Rahul Ravikumar            mConfiguration = configuration;
453969025c012f4a8bd7bccda7216d76fc4636590feXyan Bhatnagar            mWorkDatabase = database;
454969025c012f4a8bd7bccda7216d76fc4636590feXyan Bhatnagar            mWorkSpecId = workSpecId;
455969025c012f4a8bd7bccda7216d76fc4636590feXyan Bhatnagar        }
456969025c012f4a8bd7bccda7216d76fc4636590feXyan Bhatnagar
457d64a1a65bd138cfeeb9ae6a595120b85e77a57f6Rahul Ravikumar        /**
458d64a1a65bd138cfeeb9ae6a595120b85e77a57f6Rahul Ravikumar         * @param listener The {@link ExecutionListener} which gets notified on completion of the
459d64a1a65bd138cfeeb9ae6a595120b85e77a57f6Rahul Ravikumar         *                 {@link Worker} with the given {@code workSpecId}.
460d64a1a65bd138cfeeb9ae6a595120b85e77a57f6Rahul Ravikumar         * @return The instance of {@link Builder} for chaining.
461d64a1a65bd138cfeeb9ae6a595120b85e77a57f6Rahul Ravikumar         */
462d64a1a65bd138cfeeb9ae6a595120b85e77a57f6Rahul Ravikumar        public Builder withListener(ExecutionListener listener) {
463969025c012f4a8bd7bccda7216d76fc4636590feXyan Bhatnagar            mListener = listener;
464969025c012f4a8bd7bccda7216d76fc4636590feXyan Bhatnagar            return this;
465969025c012f4a8bd7bccda7216d76fc4636590feXyan Bhatnagar        }
466969025c012f4a8bd7bccda7216d76fc4636590feXyan Bhatnagar
467d64a1a65bd138cfeeb9ae6a595120b85e77a57f6Rahul Ravikumar        /**
468681a8d809fe41189c9d590d33b986b98170e4963Sumir Kataria         * @param schedulers The list of {@link Scheduler}s used for scheduling {@link Worker}s.
469d64a1a65bd138cfeeb9ae6a595120b85e77a57f6Rahul Ravikumar         * @return The instance of {@link Builder} for chaining.
470d64a1a65bd138cfeeb9ae6a595120b85e77a57f6Rahul Ravikumar         */
471d64a1a65bd138cfeeb9ae6a595120b85e77a57f6Rahul Ravikumar        public Builder withSchedulers(List<Scheduler> schedulers) {
472137c84c9c8212a44ee81c238a1a2271637ffa24bSumir Kataria            mSchedulers = schedulers;
473b7a9f83e8ec6365bfd9057e30bfa5f73270ed12dSumir Kataria            return this;
474b7a9f83e8ec6365bfd9057e30bfa5f73270ed12dSumir Kataria        }
475b7a9f83e8ec6365bfd9057e30bfa5f73270ed12dSumir Kataria
476d64a1a65bd138cfeeb9ae6a595120b85e77a57f6Rahul Ravikumar        /**
4777b5c560e4098585f73564951621060de708e441fSumir Kataria         * @param runtimeExtras The {@link Extras.RuntimeExtras} for the {@link Worker}.
478681a8d809fe41189c9d590d33b986b98170e4963Sumir Kataria         * @return The instance of {@link Builder} for chaining.
479681a8d809fe41189c9d590d33b986b98170e4963Sumir Kataria         */
4807b5c560e4098585f73564951621060de708e441fSumir Kataria        public Builder withRuntimeExtras(Extras.RuntimeExtras runtimeExtras) {
481681a8d809fe41189c9d590d33b986b98170e4963Sumir Kataria            mRuntimeExtras = runtimeExtras;
482681a8d809fe41189c9d590d33b986b98170e4963Sumir Kataria            return this;
483681a8d809fe41189c9d590d33b986b98170e4963Sumir Kataria        }
484681a8d809fe41189c9d590d33b986b98170e4963Sumir Kataria
485681a8d809fe41189c9d590d33b986b98170e4963Sumir Kataria        /**
486d64a1a65bd138cfeeb9ae6a595120b85e77a57f6Rahul Ravikumar         * @param worker The instance of {@link Worker} to be executed by {@link WorkerWrapper}.
487d64a1a65bd138cfeeb9ae6a595120b85e77a57f6Rahul Ravikumar         *               Useful in the context of testing.
488d64a1a65bd138cfeeb9ae6a595120b85e77a57f6Rahul Ravikumar         * @return The instance of {@link Builder} for chaining.
489d64a1a65bd138cfeeb9ae6a595120b85e77a57f6Rahul Ravikumar         */
490d64a1a65bd138cfeeb9ae6a595120b85e77a57f6Rahul Ravikumar        @VisibleForTesting
491d64a1a65bd138cfeeb9ae6a595120b85e77a57f6Rahul Ravikumar        public Builder withWorker(Worker worker) {
492d64a1a65bd138cfeeb9ae6a595120b85e77a57f6Rahul Ravikumar            mWorker = worker;
493d64a1a65bd138cfeeb9ae6a595120b85e77a57f6Rahul Ravikumar            return this;
494d64a1a65bd138cfeeb9ae6a595120b85e77a57f6Rahul Ravikumar        }
495d64a1a65bd138cfeeb9ae6a595120b85e77a57f6Rahul Ravikumar
496d64a1a65bd138cfeeb9ae6a595120b85e77a57f6Rahul Ravikumar        /**
497d64a1a65bd138cfeeb9ae6a595120b85e77a57f6Rahul Ravikumar         * @return The instance of {@link WorkerWrapper}.
498d64a1a65bd138cfeeb9ae6a595120b85e77a57f6Rahul Ravikumar         */
499d64a1a65bd138cfeeb9ae6a595120b85e77a57f6Rahul Ravikumar        public WorkerWrapper build() {
500969025c012f4a8bd7bccda7216d76fc4636590feXyan Bhatnagar            return new WorkerWrapper(this);
501969025c012f4a8bd7bccda7216d76fc4636590feXyan Bhatnagar        }
502969025c012f4a8bd7bccda7216d76fc4636590feXyan Bhatnagar    }
503b8909f2c9c62261181e8270be8de44a69ac2b75fXyan Bhatnagar}
504