WorkTimer.java revision accafea75309628ec2456574bcaff8c97411187b
1accafea75309628ec2456574bcaff8c97411187bJan Clarin/*
2accafea75309628ec2456574bcaff8c97411187bJan Clarin * Copyright 2018 The Android Open Source Project
3accafea75309628ec2456574bcaff8c97411187bJan Clarin *
4accafea75309628ec2456574bcaff8c97411187bJan Clarin * Licensed under the Apache License, Version 2.0 (the "License");
5accafea75309628ec2456574bcaff8c97411187bJan Clarin * you may not use this file except in compliance with the License.
6accafea75309628ec2456574bcaff8c97411187bJan Clarin * You may obtain a copy of the License at
7accafea75309628ec2456574bcaff8c97411187bJan Clarin *
8accafea75309628ec2456574bcaff8c97411187bJan Clarin *      http://www.apache.org/licenses/LICENSE-2.0
9accafea75309628ec2456574bcaff8c97411187bJan Clarin *
10accafea75309628ec2456574bcaff8c97411187bJan Clarin * Unless required by applicable law or agreed to in writing, software
11accafea75309628ec2456574bcaff8c97411187bJan Clarin * distributed under the License is distributed on an "AS IS" BASIS,
12accafea75309628ec2456574bcaff8c97411187bJan Clarin * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13accafea75309628ec2456574bcaff8c97411187bJan Clarin * See the License for the specific language governing permissions and
14accafea75309628ec2456574bcaff8c97411187bJan Clarin * limitations under the License.
15accafea75309628ec2456574bcaff8c97411187bJan Clarin */
16accafea75309628ec2456574bcaff8c97411187bJan Clarin
17accafea75309628ec2456574bcaff8c97411187bJan Clarinpackage android.arch.background.workmanager.impl.background.systemalarm;
18accafea75309628ec2456574bcaff8c97411187bJan Clarin
19accafea75309628ec2456574bcaff8c97411187bJan Clarinimport android.arch.background.workmanager.BaseWork;
20accafea75309628ec2456574bcaff8c97411187bJan Clarinimport android.arch.background.workmanager.impl.logger.Logger;
21accafea75309628ec2456574bcaff8c97411187bJan Clarinimport android.support.annotation.NonNull;
22accafea75309628ec2456574bcaff8c97411187bJan Clarinimport android.support.annotation.RestrictTo;
23accafea75309628ec2456574bcaff8c97411187bJan Clarin
24accafea75309628ec2456574bcaff8c97411187bJan Clarinimport java.util.Map;
25accafea75309628ec2456574bcaff8c97411187bJan Clarinimport java.util.concurrent.ConcurrentHashMap;
26accafea75309628ec2456574bcaff8c97411187bJan Clarinimport java.util.concurrent.Executors;
27accafea75309628ec2456574bcaff8c97411187bJan Clarinimport java.util.concurrent.Future;
28accafea75309628ec2456574bcaff8c97411187bJan Clarinimport java.util.concurrent.ScheduledExecutorService;
29accafea75309628ec2456574bcaff8c97411187bJan Clarinimport java.util.concurrent.TimeUnit;
30accafea75309628ec2456574bcaff8c97411187bJan Clarin
31accafea75309628ec2456574bcaff8c97411187bJan Clarin/**
32accafea75309628ec2456574bcaff8c97411187bJan Clarin * Manages timers to enforce a time limit for processing {@link BaseWork}. Notifies a
33accafea75309628ec2456574bcaff8c97411187bJan Clarin * {@link TimeLimitExceededListener} when the time limit is exceeded.
34accafea75309628ec2456574bcaff8c97411187bJan Clarin *
35accafea75309628ec2456574bcaff8c97411187bJan Clarin * @hide
36accafea75309628ec2456574bcaff8c97411187bJan Clarin */
37accafea75309628ec2456574bcaff8c97411187bJan Clarin@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
38accafea75309628ec2456574bcaff8c97411187bJan Clarinpublic class WorkTimer {
39accafea75309628ec2456574bcaff8c97411187bJan Clarin    private static final String TAG = "WorkTimer";
40accafea75309628ec2456574bcaff8c97411187bJan Clarin
41accafea75309628ec2456574bcaff8c97411187bJan Clarin    private final Map<String, Future<?>> mWorkIdTimerMap = new ConcurrentHashMap<>();
42accafea75309628ec2456574bcaff8c97411187bJan Clarin    private final ScheduledExecutorService mScheduledExecutorService =
43accafea75309628ec2456574bcaff8c97411187bJan Clarin            Executors.newSingleThreadScheduledExecutor();
44accafea75309628ec2456574bcaff8c97411187bJan Clarin
45accafea75309628ec2456574bcaff8c97411187bJan Clarin    private TimeLimitExceededListener mListener;
46accafea75309628ec2456574bcaff8c97411187bJan Clarin
47accafea75309628ec2456574bcaff8c97411187bJan Clarin    /** Must be public for mocking */
48accafea75309628ec2456574bcaff8c97411187bJan Clarin    public void setOnTimeLimitExceededListener(@NonNull TimeLimitExceededListener listener) {
49accafea75309628ec2456574bcaff8c97411187bJan Clarin        mListener = listener;
50accafea75309628ec2456574bcaff8c97411187bJan Clarin    }
51accafea75309628ec2456574bcaff8c97411187bJan Clarin
52accafea75309628ec2456574bcaff8c97411187bJan Clarin    /** Must be public for mocking */
53accafea75309628ec2456574bcaff8c97411187bJan Clarin    public void startTimer(@NonNull final String workSpecId, long processingTimeMillis) {
54accafea75309628ec2456574bcaff8c97411187bJan Clarin        stopTimer(workSpecId); // Clear any existing timers for the workSpecId.
55accafea75309628ec2456574bcaff8c97411187bJan Clarin
56accafea75309628ec2456574bcaff8c97411187bJan Clarin        mWorkIdTimerMap.put(workSpecId, mScheduledExecutorService.schedule(new Runnable() {
57accafea75309628ec2456574bcaff8c97411187bJan Clarin            @Override
58accafea75309628ec2456574bcaff8c97411187bJan Clarin            public void run() {
59accafea75309628ec2456574bcaff8c97411187bJan Clarin                Future<?> timer = mWorkIdTimerMap.remove(workSpecId);
60accafea75309628ec2456574bcaff8c97411187bJan Clarin                if (timer != null && mListener != null) {
61accafea75309628ec2456574bcaff8c97411187bJan Clarin                    mListener.onTimeLimitExceeded(workSpecId);
62accafea75309628ec2456574bcaff8c97411187bJan Clarin                    Logger.debug(TAG, "Time limit exceeded for Work %s", workSpecId);
63accafea75309628ec2456574bcaff8c97411187bJan Clarin                }
64accafea75309628ec2456574bcaff8c97411187bJan Clarin            }
65accafea75309628ec2456574bcaff8c97411187bJan Clarin        }, processingTimeMillis, TimeUnit.MILLISECONDS));
66accafea75309628ec2456574bcaff8c97411187bJan Clarin
67accafea75309628ec2456574bcaff8c97411187bJan Clarin        Logger.debug(TAG, "Started timer for Work %s", workSpecId);
68accafea75309628ec2456574bcaff8c97411187bJan Clarin    }
69accafea75309628ec2456574bcaff8c97411187bJan Clarin
70accafea75309628ec2456574bcaff8c97411187bJan Clarin    /** Must be public for mocking */
71accafea75309628ec2456574bcaff8c97411187bJan Clarin    public void stopTimer(@NonNull final String workSpecId) {
72accafea75309628ec2456574bcaff8c97411187bJan Clarin        Future<?> timer = mWorkIdTimerMap.remove(workSpecId);
73accafea75309628ec2456574bcaff8c97411187bJan Clarin        if (timer != null) {
74accafea75309628ec2456574bcaff8c97411187bJan Clarin            timer.cancel(false);
75accafea75309628ec2456574bcaff8c97411187bJan Clarin            Logger.debug(TAG, "Stopped timer for Work %s", workSpecId);
76accafea75309628ec2456574bcaff8c97411187bJan Clarin        }
77accafea75309628ec2456574bcaff8c97411187bJan Clarin    }
78accafea75309628ec2456574bcaff8c97411187bJan Clarin
79accafea75309628ec2456574bcaff8c97411187bJan Clarin    interface TimeLimitExceededListener {
80accafea75309628ec2456574bcaff8c97411187bJan Clarin        void onTimeLimitExceeded(@NonNull String workSpecId);
81accafea75309628ec2456574bcaff8c97411187bJan Clarin    }
82accafea75309628ec2456574bcaff8c97411187bJan Clarin}
83