1dd3c04c8aa64eb9c8d3da1bbac6024e613d39143Rahul Ravikumar/*
2dd3c04c8aa64eb9c8d3da1bbac6024e613d39143Rahul Ravikumar * Copyright 2018 The Android Open Source Project
3dd3c04c8aa64eb9c8d3da1bbac6024e613d39143Rahul Ravikumar *
4dd3c04c8aa64eb9c8d3da1bbac6024e613d39143Rahul Ravikumar * Licensed under the Apache License, Version 2.0 (the "License");
5dd3c04c8aa64eb9c8d3da1bbac6024e613d39143Rahul Ravikumar * you may not use this file except in compliance with the License.
6dd3c04c8aa64eb9c8d3da1bbac6024e613d39143Rahul Ravikumar * You may obtain a copy of the License at
7dd3c04c8aa64eb9c8d3da1bbac6024e613d39143Rahul Ravikumar *
8dd3c04c8aa64eb9c8d3da1bbac6024e613d39143Rahul Ravikumar *      http://www.apache.org/licenses/LICENSE-2.0
9dd3c04c8aa64eb9c8d3da1bbac6024e613d39143Rahul Ravikumar *
10dd3c04c8aa64eb9c8d3da1bbac6024e613d39143Rahul Ravikumar * Unless required by applicable law or agreed to in writing, software
11dd3c04c8aa64eb9c8d3da1bbac6024e613d39143Rahul Ravikumar * distributed under the License is distributed on an "AS IS" BASIS,
12dd3c04c8aa64eb9c8d3da1bbac6024e613d39143Rahul Ravikumar * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13dd3c04c8aa64eb9c8d3da1bbac6024e613d39143Rahul Ravikumar * See the License for the specific language governing permissions and
14dd3c04c8aa64eb9c8d3da1bbac6024e613d39143Rahul Ravikumar * limitations under the License.
15dd3c04c8aa64eb9c8d3da1bbac6024e613d39143Rahul Ravikumar */
16dd3c04c8aa64eb9c8d3da1bbac6024e613d39143Rahul Ravikumar
17564e43098c323d1a90be53c190b8fdbdde973505Sumir Katariapackage androidx.work.impl.background.systemalarm;
18dd3c04c8aa64eb9c8d3da1bbac6024e613d39143Rahul Ravikumar
19dd3c04c8aa64eb9c8d3da1bbac6024e613d39143Rahul Ravikumarimport android.content.Context;
20dd3c04c8aa64eb9c8d3da1bbac6024e613d39143Rahul Ravikumarimport android.content.Intent;
21dd3c04c8aa64eb9c8d3da1bbac6024e613d39143Rahul Ravikumarimport android.os.PowerManager;
22dd3c04c8aa64eb9c8d3da1bbac6024e613d39143Rahul Ravikumarimport android.support.annotation.NonNull;
23dd3c04c8aa64eb9c8d3da1bbac6024e613d39143Rahul Ravikumarimport android.support.annotation.Nullable;
24dd3c04c8aa64eb9c8d3da1bbac6024e613d39143Rahul Ravikumarimport android.support.annotation.RestrictTo;
25e92262ff56fedd7753af56e777e38e07894210e6Rahul Ravikumarimport android.support.annotation.WorkerThread;
26697d6a4a3797bc71d0dd8685937a318e9934066bRahul Ravikumarimport android.util.Log;
27dd3c04c8aa64eb9c8d3da1bbac6024e613d39143Rahul Ravikumar
28564e43098c323d1a90be53c190b8fdbdde973505Sumir Katariaimport androidx.work.impl.ExecutionListener;
29564e43098c323d1a90be53c190b8fdbdde973505Sumir Katariaimport androidx.work.impl.constraints.WorkConstraintsCallback;
30564e43098c323d1a90be53c190b8fdbdde973505Sumir Katariaimport androidx.work.impl.constraints.WorkConstraintsTracker;
31564e43098c323d1a90be53c190b8fdbdde973505Sumir Katariaimport androidx.work.impl.model.WorkSpec;
32564e43098c323d1a90be53c190b8fdbdde973505Sumir Katariaimport androidx.work.impl.utils.WakeLocks;
33564e43098c323d1a90be53c190b8fdbdde973505Sumir Kataria
34b5728f4e1a4b3f4f1fabf033b1363ca6b1cffdefSumir Katariaimport java.util.Collections;
35b5728f4e1a4b3f4f1fabf033b1363ca6b1cffdefSumir Katariaimport java.util.List;
36b5728f4e1a4b3f4f1fabf033b1363ca6b1cffdefSumir Kataria
37dd3c04c8aa64eb9c8d3da1bbac6024e613d39143Rahul Ravikumar/**
38dd3c04c8aa64eb9c8d3da1bbac6024e613d39143Rahul Ravikumar * This is a command handler which attempts to run a work spec given its id.
39dd3c04c8aa64eb9c8d3da1bbac6024e613d39143Rahul Ravikumar * Also handles constraints gracefully.
40dd3c04c8aa64eb9c8d3da1bbac6024e613d39143Rahul Ravikumar *
41dd3c04c8aa64eb9c8d3da1bbac6024e613d39143Rahul Ravikumar * @hide
42dd3c04c8aa64eb9c8d3da1bbac6024e613d39143Rahul Ravikumar */
43dd3c04c8aa64eb9c8d3da1bbac6024e613d39143Rahul Ravikumar@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
44dd3c04c8aa64eb9c8d3da1bbac6024e613d39143Rahul Ravikumarpublic class DelayMetCommandHandler implements
45dd3c04c8aa64eb9c8d3da1bbac6024e613d39143Rahul Ravikumar        WorkConstraintsCallback,
46dd3c04c8aa64eb9c8d3da1bbac6024e613d39143Rahul Ravikumar        ExecutionListener,
47dd3c04c8aa64eb9c8d3da1bbac6024e613d39143Rahul Ravikumar        WorkTimer.TimeLimitExceededListener {
48dd3c04c8aa64eb9c8d3da1bbac6024e613d39143Rahul Ravikumar
49dd3c04c8aa64eb9c8d3da1bbac6024e613d39143Rahul Ravikumar    private static final String TAG = "DelayMetCommandHandler";
50dd3c04c8aa64eb9c8d3da1bbac6024e613d39143Rahul Ravikumar
51dd3c04c8aa64eb9c8d3da1bbac6024e613d39143Rahul Ravikumar    private final Context mContext;
52dd3c04c8aa64eb9c8d3da1bbac6024e613d39143Rahul Ravikumar    private final int mStartId;
53dd3c04c8aa64eb9c8d3da1bbac6024e613d39143Rahul Ravikumar    private final String mWorkSpecId;
54dd3c04c8aa64eb9c8d3da1bbac6024e613d39143Rahul Ravikumar    private final SystemAlarmDispatcher mDispatcher;
55dd3c04c8aa64eb9c8d3da1bbac6024e613d39143Rahul Ravikumar    private final WorkConstraintsTracker mWorkConstraintsTracker;
56dd3c04c8aa64eb9c8d3da1bbac6024e613d39143Rahul Ravikumar    private final Object mLock;
57e92262ff56fedd7753af56e777e38e07894210e6Rahul Ravikumar    private boolean mHasPendingStopWorkCommand;
58dd3c04c8aa64eb9c8d3da1bbac6024e613d39143Rahul Ravikumar
59e92262ff56fedd7753af56e777e38e07894210e6Rahul Ravikumar    @Nullable private PowerManager.WakeLock mWakeLock;
60e92262ff56fedd7753af56e777e38e07894210e6Rahul Ravikumar    private boolean mHasConstraints;
61dd3c04c8aa64eb9c8d3da1bbac6024e613d39143Rahul Ravikumar
62dd3c04c8aa64eb9c8d3da1bbac6024e613d39143Rahul Ravikumar    DelayMetCommandHandler(
63dd3c04c8aa64eb9c8d3da1bbac6024e613d39143Rahul Ravikumar            @NonNull Context context,
64dd3c04c8aa64eb9c8d3da1bbac6024e613d39143Rahul Ravikumar            int startId,
65dd3c04c8aa64eb9c8d3da1bbac6024e613d39143Rahul Ravikumar            @NonNull String workSpecId,
66dd3c04c8aa64eb9c8d3da1bbac6024e613d39143Rahul Ravikumar            @NonNull SystemAlarmDispatcher dispatcher) {
67dd3c04c8aa64eb9c8d3da1bbac6024e613d39143Rahul Ravikumar
68dd3c04c8aa64eb9c8d3da1bbac6024e613d39143Rahul Ravikumar        mContext = context;
69dd3c04c8aa64eb9c8d3da1bbac6024e613d39143Rahul Ravikumar        mStartId = startId;
70dd3c04c8aa64eb9c8d3da1bbac6024e613d39143Rahul Ravikumar        mDispatcher = dispatcher;
71dd3c04c8aa64eb9c8d3da1bbac6024e613d39143Rahul Ravikumar        mWorkSpecId = workSpecId;
72dd3c04c8aa64eb9c8d3da1bbac6024e613d39143Rahul Ravikumar        mWorkConstraintsTracker = new WorkConstraintsTracker(mContext, this);
73e92262ff56fedd7753af56e777e38e07894210e6Rahul Ravikumar        mHasConstraints = false;
74e92262ff56fedd7753af56e777e38e07894210e6Rahul Ravikumar        mHasPendingStopWorkCommand = false;
75dd3c04c8aa64eb9c8d3da1bbac6024e613d39143Rahul Ravikumar        mLock = new Object();
76dd3c04c8aa64eb9c8d3da1bbac6024e613d39143Rahul Ravikumar    }
77dd3c04c8aa64eb9c8d3da1bbac6024e613d39143Rahul Ravikumar
78dd3c04c8aa64eb9c8d3da1bbac6024e613d39143Rahul Ravikumar    @Override
79dd3c04c8aa64eb9c8d3da1bbac6024e613d39143Rahul Ravikumar    public void onAllConstraintsMet(@NonNull List<String> ignored) {
80697d6a4a3797bc71d0dd8685937a318e9934066bRahul Ravikumar        Log.d(TAG, String.format("onAllConstraintsMet for %s", mWorkSpecId));
81d70f977a2a312353a82ffefeeef67bb23941f78eRahul Ravikumar        // Constraints met, schedule execution
82d70f977a2a312353a82ffefeeef67bb23941f78eRahul Ravikumar
83d70f977a2a312353a82ffefeeef67bb23941f78eRahul Ravikumar        // Not using WorkManagerImpl#startWork() here because we need to know if the processor
84d70f977a2a312353a82ffefeeef67bb23941f78eRahul Ravikumar        // actually enqueued the work here.
85d70f977a2a312353a82ffefeeef67bb23941f78eRahul Ravikumar        // TODO(rahulrav@) Once WorkManagerImpl provides a callback for acknowledging if
86d70f977a2a312353a82ffefeeef67bb23941f78eRahul Ravikumar        // work was enqueued, call WorkManagerImpl#startWork().
879543a50886c5c217ae5616ec834b73274d0c1037Sumir Kataria        boolean isEnqueued = mDispatcher.getProcessor().startWork(mWorkSpecId);
88dd3c04c8aa64eb9c8d3da1bbac6024e613d39143Rahul Ravikumar
89dd3c04c8aa64eb9c8d3da1bbac6024e613d39143Rahul Ravikumar        if (isEnqueued) {
90dd3c04c8aa64eb9c8d3da1bbac6024e613d39143Rahul Ravikumar            // setup timers to enforce quotas on workers that have
91dd3c04c8aa64eb9c8d3da1bbac6024e613d39143Rahul Ravikumar            // been enqueued
92dd3c04c8aa64eb9c8d3da1bbac6024e613d39143Rahul Ravikumar            mDispatcher.getWorkTimer()
93dd3c04c8aa64eb9c8d3da1bbac6024e613d39143Rahul Ravikumar                    .startTimer(mWorkSpecId, CommandHandler.WORK_PROCESSING_TIME_IN_MS, this);
94dd3c04c8aa64eb9c8d3da1bbac6024e613d39143Rahul Ravikumar        } else {
95dd3c04c8aa64eb9c8d3da1bbac6024e613d39143Rahul Ravikumar            // if we did not actually enqueue the work, it was enqueued before
96dd3c04c8aa64eb9c8d3da1bbac6024e613d39143Rahul Ravikumar            // cleanUp and pretend this never happened.
97dd3c04c8aa64eb9c8d3da1bbac6024e613d39143Rahul Ravikumar            cleanUp();
98dd3c04c8aa64eb9c8d3da1bbac6024e613d39143Rahul Ravikumar        }
99dd3c04c8aa64eb9c8d3da1bbac6024e613d39143Rahul Ravikumar    }
100dd3c04c8aa64eb9c8d3da1bbac6024e613d39143Rahul Ravikumar
101dd3c04c8aa64eb9c8d3da1bbac6024e613d39143Rahul Ravikumar    @Override
102dd3c04c8aa64eb9c8d3da1bbac6024e613d39143Rahul Ravikumar    public void onExecuted(
103dd3c04c8aa64eb9c8d3da1bbac6024e613d39143Rahul Ravikumar            @NonNull String workSpecId,
104dd3c04c8aa64eb9c8d3da1bbac6024e613d39143Rahul Ravikumar            boolean isSuccessful,
105dd3c04c8aa64eb9c8d3da1bbac6024e613d39143Rahul Ravikumar            boolean needsReschedule) {
106dd3c04c8aa64eb9c8d3da1bbac6024e613d39143Rahul Ravikumar
107697d6a4a3797bc71d0dd8685937a318e9934066bRahul Ravikumar        Log.d(TAG, String.format(
108697d6a4a3797bc71d0dd8685937a318e9934066bRahul Ravikumar                "onExecuted %s, %s, %s", workSpecId, isSuccessful, needsReschedule));
109697d6a4a3797bc71d0dd8685937a318e9934066bRahul Ravikumar
110dd3c04c8aa64eb9c8d3da1bbac6024e613d39143Rahul Ravikumar        cleanUp();
111e92262ff56fedd7753af56e777e38e07894210e6Rahul Ravikumar
112e92262ff56fedd7753af56e777e38e07894210e6Rahul Ravikumar        if (mHasConstraints) {
113e92262ff56fedd7753af56e777e38e07894210e6Rahul Ravikumar            // The WorkSpec had constraints. Once the execution of the worker is complete,
114e92262ff56fedd7753af56e777e38e07894210e6Rahul Ravikumar            // we might need to disable constraint proxies which were previously enabled for
115e92262ff56fedd7753af56e777e38e07894210e6Rahul Ravikumar            // this WorkSpec. Hence, trigger a constraints changed command.
116e92262ff56fedd7753af56e777e38e07894210e6Rahul Ravikumar            Intent intent = CommandHandler.createConstraintsChangedIntent(mContext);
117e92262ff56fedd7753af56e777e38e07894210e6Rahul Ravikumar            mDispatcher.postOnMainThread(
118e92262ff56fedd7753af56e777e38e07894210e6Rahul Ravikumar                    new SystemAlarmDispatcher.AddRunnable(mDispatcher, intent, mStartId));
119e92262ff56fedd7753af56e777e38e07894210e6Rahul Ravikumar        }
120dd3c04c8aa64eb9c8d3da1bbac6024e613d39143Rahul Ravikumar    }
121dd3c04c8aa64eb9c8d3da1bbac6024e613d39143Rahul Ravikumar
122dd3c04c8aa64eb9c8d3da1bbac6024e613d39143Rahul Ravikumar    @Override
123dd3c04c8aa64eb9c8d3da1bbac6024e613d39143Rahul Ravikumar    public void onTimeLimitExceeded(@NonNull String workSpecId) {
124697d6a4a3797bc71d0dd8685937a318e9934066bRahul Ravikumar        Log.d(TAG, String.format("Exceeded time limits on execution for %s", workSpecId));
125e92262ff56fedd7753af56e777e38e07894210e6Rahul Ravikumar        stopWork();
126dd3c04c8aa64eb9c8d3da1bbac6024e613d39143Rahul Ravikumar    }
127dd3c04c8aa64eb9c8d3da1bbac6024e613d39143Rahul Ravikumar
128dd3c04c8aa64eb9c8d3da1bbac6024e613d39143Rahul Ravikumar    @Override
129dd3c04c8aa64eb9c8d3da1bbac6024e613d39143Rahul Ravikumar    public void onAllConstraintsNotMet(@NonNull List<String> ignored) {
130e92262ff56fedd7753af56e777e38e07894210e6Rahul Ravikumar        stopWork();
131dd3c04c8aa64eb9c8d3da1bbac6024e613d39143Rahul Ravikumar    }
132dd3c04c8aa64eb9c8d3da1bbac6024e613d39143Rahul Ravikumar
133e92262ff56fedd7753af56e777e38e07894210e6Rahul Ravikumar    @WorkerThread
134dd3c04c8aa64eb9c8d3da1bbac6024e613d39143Rahul Ravikumar    void handleProcessWork() {
135498888fde0080e29b854e4ba329644ccf5fc60c5Sumir Kataria        mWakeLock = WakeLocks.newWakeLock(
136498888fde0080e29b854e4ba329644ccf5fc60c5Sumir Kataria                mContext,
137498888fde0080e29b854e4ba329644ccf5fc60c5Sumir Kataria                String.format("%s (%s)", mWorkSpecId, mStartId));
138697d6a4a3797bc71d0dd8685937a318e9934066bRahul Ravikumar        Log.d(TAG, String.format("Acquiring wakelock %s for WorkSpec %s", mWakeLock, mWorkSpecId));
139dd3c04c8aa64eb9c8d3da1bbac6024e613d39143Rahul Ravikumar        mWakeLock.acquire();
140dd3c04c8aa64eb9c8d3da1bbac6024e613d39143Rahul Ravikumar
141dd3c04c8aa64eb9c8d3da1bbac6024e613d39143Rahul Ravikumar        WorkSpec workSpec = mDispatcher.getWorkManager()
142dd3c04c8aa64eb9c8d3da1bbac6024e613d39143Rahul Ravikumar                .getWorkDatabase()
143dd3c04c8aa64eb9c8d3da1bbac6024e613d39143Rahul Ravikumar                .workSpecDao()
144dd3c04c8aa64eb9c8d3da1bbac6024e613d39143Rahul Ravikumar                .getWorkSpec(mWorkSpecId);
145dd3c04c8aa64eb9c8d3da1bbac6024e613d39143Rahul Ravikumar
146e92262ff56fedd7753af56e777e38e07894210e6Rahul Ravikumar        // Keep track of whether the WorkSpec had constraints. This is useful for updating the
147e92262ff56fedd7753af56e777e38e07894210e6Rahul Ravikumar        // state of constraint proxies when onExecuted().
148e92262ff56fedd7753af56e777e38e07894210e6Rahul Ravikumar        mHasConstraints = workSpec.hasConstraints();
149e92262ff56fedd7753af56e777e38e07894210e6Rahul Ravikumar
150e92262ff56fedd7753af56e777e38e07894210e6Rahul Ravikumar        if (!mHasConstraints) {
151697d6a4a3797bc71d0dd8685937a318e9934066bRahul Ravikumar            Log.d(TAG, String.format("No constraints for %s", mWorkSpecId));
152dd3c04c8aa64eb9c8d3da1bbac6024e613d39143Rahul Ravikumar            onAllConstraintsMet(Collections.singletonList(mWorkSpecId));
153dd3c04c8aa64eb9c8d3da1bbac6024e613d39143Rahul Ravikumar        } else {
154e92262ff56fedd7753af56e777e38e07894210e6Rahul Ravikumar            // Allow tracker to report constraint changes
155dd3c04c8aa64eb9c8d3da1bbac6024e613d39143Rahul Ravikumar            mWorkConstraintsTracker.replace(Collections.singletonList(workSpec));
156dd3c04c8aa64eb9c8d3da1bbac6024e613d39143Rahul Ravikumar        }
157dd3c04c8aa64eb9c8d3da1bbac6024e613d39143Rahul Ravikumar    }
158dd3c04c8aa64eb9c8d3da1bbac6024e613d39143Rahul Ravikumar
159e92262ff56fedd7753af56e777e38e07894210e6Rahul Ravikumar    private void stopWork() {
160e92262ff56fedd7753af56e777e38e07894210e6Rahul Ravikumar        // No need to release the wake locks here. The stopWork command will eventually call
161e92262ff56fedd7753af56e777e38e07894210e6Rahul Ravikumar        // onExecuted() if there is a corresponding pending delay met command handler; which in
162e92262ff56fedd7753af56e777e38e07894210e6Rahul Ravikumar        // turn calls cleanUp().
163e92262ff56fedd7753af56e777e38e07894210e6Rahul Ravikumar
164e92262ff56fedd7753af56e777e38e07894210e6Rahul Ravikumar        // Needs to be synchronized, as the stopWork() request can potentially come from the
165e92262ff56fedd7753af56e777e38e07894210e6Rahul Ravikumar        // WorkTimer thread as well as the command executor service in SystemAlarmDispatcher.
166e92262ff56fedd7753af56e777e38e07894210e6Rahul Ravikumar        synchronized (mLock) {
167e92262ff56fedd7753af56e777e38e07894210e6Rahul Ravikumar            if (!mHasPendingStopWorkCommand) {
168697d6a4a3797bc71d0dd8685937a318e9934066bRahul Ravikumar                Log.d(TAG, String.format("Stopping work for workspec %s", mWorkSpecId));
169e92262ff56fedd7753af56e777e38e07894210e6Rahul Ravikumar                Intent stopWork = CommandHandler.createStopWorkIntent(mContext, mWorkSpecId);
170e92262ff56fedd7753af56e777e38e07894210e6Rahul Ravikumar                mDispatcher.postOnMainThread(
171e92262ff56fedd7753af56e777e38e07894210e6Rahul Ravikumar                        new SystemAlarmDispatcher.AddRunnable(mDispatcher, stopWork, mStartId));
172b035249dbe0cb224080705db57c7e05438bdbe87Rahul Ravikumar                // There are cases where the work may not have been enqueued at all, and therefore
173b035249dbe0cb224080705db57c7e05438bdbe87Rahul Ravikumar                // the processor is completely unaware of such a workSpecId in which case a
174b035249dbe0cb224080705db57c7e05438bdbe87Rahul Ravikumar                // reschedule should not happen. For e.g. DELAY_MET when constraints are not met,
175b035249dbe0cb224080705db57c7e05438bdbe87Rahul Ravikumar                // should not result in a reschedule.
176b035249dbe0cb224080705db57c7e05438bdbe87Rahul Ravikumar                if (mDispatcher.getProcessor().isEnqueued(mWorkSpecId)) {
177697d6a4a3797bc71d0dd8685937a318e9934066bRahul Ravikumar                    Log.d(TAG, String.format("WorkSpec %s needs to be rescheduled", mWorkSpecId));
178b035249dbe0cb224080705db57c7e05438bdbe87Rahul Ravikumar                    Intent reschedule = CommandHandler.createScheduleWorkIntent(mContext,
179b035249dbe0cb224080705db57c7e05438bdbe87Rahul Ravikumar                            mWorkSpecId);
180b035249dbe0cb224080705db57c7e05438bdbe87Rahul Ravikumar                    mDispatcher.postOnMainThread(
181b035249dbe0cb224080705db57c7e05438bdbe87Rahul Ravikumar                            new SystemAlarmDispatcher.AddRunnable(mDispatcher, reschedule,
182b035249dbe0cb224080705db57c7e05438bdbe87Rahul Ravikumar                                    mStartId));
183b035249dbe0cb224080705db57c7e05438bdbe87Rahul Ravikumar                } else {
184697d6a4a3797bc71d0dd8685937a318e9934066bRahul Ravikumar                    Log.d(TAG, String.format(
185697d6a4a3797bc71d0dd8685937a318e9934066bRahul Ravikumar                            "Processor does not have WorkSpec %s. No need to reschedule ",
186697d6a4a3797bc71d0dd8685937a318e9934066bRahul Ravikumar                            mWorkSpecId));
187b035249dbe0cb224080705db57c7e05438bdbe87Rahul Ravikumar                }
188e92262ff56fedd7753af56e777e38e07894210e6Rahul Ravikumar                mHasPendingStopWorkCommand = true;
189e92262ff56fedd7753af56e777e38e07894210e6Rahul Ravikumar            } else {
190697d6a4a3797bc71d0dd8685937a318e9934066bRahul Ravikumar                Log.d(TAG, String.format("Already stopped work for %s", mWorkSpecId));
191e92262ff56fedd7753af56e777e38e07894210e6Rahul Ravikumar            }
192e92262ff56fedd7753af56e777e38e07894210e6Rahul Ravikumar        }
193dd3c04c8aa64eb9c8d3da1bbac6024e613d39143Rahul Ravikumar    }
194dd3c04c8aa64eb9c8d3da1bbac6024e613d39143Rahul Ravikumar
195dd3c04c8aa64eb9c8d3da1bbac6024e613d39143Rahul Ravikumar    private void cleanUp() {
196dd3c04c8aa64eb9c8d3da1bbac6024e613d39143Rahul Ravikumar        // cleanUp() may occur from one of 2 threads.
1979543a50886c5c217ae5616ec834b73274d0c1037Sumir Kataria        // * In the call to bgProcessor.startWork() returns false,
198dd3c04c8aa64eb9c8d3da1bbac6024e613d39143Rahul Ravikumar        //   it probably means that the worker is already being processed
199dd3c04c8aa64eb9c8d3da1bbac6024e613d39143Rahul Ravikumar        //   so we just need to call cleanUp to release wakelocks on the command processor thread.
200dd3c04c8aa64eb9c8d3da1bbac6024e613d39143Rahul Ravikumar        // * It could also happen on the onExecutionCompleted() pass of the bgProcessor.
201dd3c04c8aa64eb9c8d3da1bbac6024e613d39143Rahul Ravikumar        // To avoid calling mWakeLock.release() twice, we are synchronizing here.
202dd3c04c8aa64eb9c8d3da1bbac6024e613d39143Rahul Ravikumar        synchronized (mLock) {
203dd3c04c8aa64eb9c8d3da1bbac6024e613d39143Rahul Ravikumar            // stop timers
204dd3c04c8aa64eb9c8d3da1bbac6024e613d39143Rahul Ravikumar            mDispatcher.getWorkTimer().stopTimer(mWorkSpecId);
205dd3c04c8aa64eb9c8d3da1bbac6024e613d39143Rahul Ravikumar
206dd3c04c8aa64eb9c8d3da1bbac6024e613d39143Rahul Ravikumar            // release wake locks
207dd3c04c8aa64eb9c8d3da1bbac6024e613d39143Rahul Ravikumar            if (mWakeLock != null && mWakeLock.isHeld()) {
208697d6a4a3797bc71d0dd8685937a318e9934066bRahul Ravikumar                Log.d(TAG, String.format(
209697d6a4a3797bc71d0dd8685937a318e9934066bRahul Ravikumar                        "Releasing wakelock %s for WorkSpec %s", mWakeLock, mWorkSpecId));
210dd3c04c8aa64eb9c8d3da1bbac6024e613d39143Rahul Ravikumar                mWakeLock.release();
211dd3c04c8aa64eb9c8d3da1bbac6024e613d39143Rahul Ravikumar            }
212dd3c04c8aa64eb9c8d3da1bbac6024e613d39143Rahul Ravikumar        }
213dd3c04c8aa64eb9c8d3da1bbac6024e613d39143Rahul Ravikumar    }
214dd3c04c8aa64eb9c8d3da1bbac6024e613d39143Rahul Ravikumar}
215