TimerService.java revision 6d603b7c62bb38d763a681a8bf20fadb1442e833
1/*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.deskclock.timer;
18
19import android.app.Service;
20import android.content.Context;
21import android.content.Intent;
22import android.os.IBinder;
23import android.support.annotation.StringRes;
24
25import com.android.deskclock.HandleDeskClockApiCalls;
26import com.android.deskclock.R;
27import com.android.deskclock.data.DataModel;
28import com.android.deskclock.data.Timer;
29import com.android.deskclock.events.Events;
30
31import static android.content.Intent.FLAG_RECEIVER_FOREGROUND;
32
33/**
34 * This service exists primarily to allow {@link android.app.AlarmManager} and timer notifications
35 * to alter the state of timers without disturbing the notification shade. If an activity were used
36 * instead (even one that is not displayed) the notification manager implicitly closes the
37 * notification shade which clashes with the use case of starting/pausing/resetting timers without
38 * interruption.
39 */
40public final class TimerService extends Service {
41
42    private static final String ACTION_PREFIX = "com.android.deskclock.action.";
43
44    private static final String ACTION_TIMER_EXPIRED = ACTION_PREFIX + "TIMER_EXPIRED";
45    private static final String ACTION_UPDATE_NOTIFICATION = ACTION_PREFIX + "UPDATE_NOTIFICATION";
46    private static final String ACTION_RESET_EXPIRED_TIMERS = ACTION_PREFIX +
47            "RESET_EXPIRED_TIMERS";
48    private static final String ACTION_RESET_UNEXPIRED_TIMERS = ACTION_PREFIX +
49            "RESET_UNEXPIRED_TIMERS";
50
51    public static Intent createTimerExpiredIntent(Context context, Timer timer) {
52        final int timerId = timer == null ? -1 : timer.getId();
53        return new Intent(context, TimerService.class)
54                .setAction(ACTION_TIMER_EXPIRED)
55                .addFlags(FLAG_RECEIVER_FOREGROUND)
56                .putExtra(HandleDeskClockApiCalls.EXTRA_TIMER_ID, timerId);
57    }
58
59    public static Intent createResetExpiredTimersIntent(Context context) {
60        return new Intent(context, TimerService.class)
61                .setAction(ACTION_RESET_EXPIRED_TIMERS)
62                .addFlags(FLAG_RECEIVER_FOREGROUND);
63    }
64
65    public static Intent createResetUnexpiredTimersIntent(Context context) {
66        return new Intent(context, TimerService.class)
67                .setAction(ACTION_RESET_UNEXPIRED_TIMERS)
68                .addFlags(FLAG_RECEIVER_FOREGROUND);
69    }
70
71    public static Intent createAddMinuteTimerIntent(Context context, int timerId) {
72        return new Intent(context, TimerService.class)
73                .setAction(HandleDeskClockApiCalls.ACTION_ADD_MINUTE_TIMER)
74                .putExtra(HandleDeskClockApiCalls.EXTRA_TIMER_ID, timerId)
75                .addFlags(FLAG_RECEIVER_FOREGROUND);
76    }
77
78    public static Intent createUpdateNotificationIntent(Context context) {
79        return new Intent(context, TimerService.class)
80                .setAction(ACTION_UPDATE_NOTIFICATION)
81                .addFlags(FLAG_RECEIVER_FOREGROUND);
82    }
83
84    @Override
85    public IBinder onBind(Intent intent) {
86        return null;
87    }
88
89    @Override
90    public int onStartCommand(Intent intent, int flags, int startId) {
91        final boolean fromNotification =
92                intent.getBooleanExtra(HandleDeskClockApiCalls.EXTRA_FROM_NOTIFICATION, false);
93
94        switch (intent.getAction()) {
95            case ACTION_UPDATE_NOTIFICATION: {
96                DataModel.getDataModel().updateTimerNotification();
97                return START_NOT_STICKY;
98            }
99            case ACTION_RESET_EXPIRED_TIMERS: {
100                final int eventLabelId = fromNotification ? R.string.label_notification : 0;
101                DataModel.getDataModel().resetExpiredTimers(eventLabelId);
102                if (fromNotification) {
103                    Events.sendTimerEvent(R.string.action_reset, R.string.label_notification);
104                }
105                return START_NOT_STICKY;
106            }
107            case ACTION_RESET_UNEXPIRED_TIMERS: {
108                final int eventLabelId = fromNotification ? R.string.label_notification : 0;
109                DataModel.getDataModel().resetUnexpiredTimers(eventLabelId);
110                if (fromNotification) {
111                    Events.sendTimerEvent(R.string.action_reset, R.string.label_notification);
112                }
113                return START_NOT_STICKY;
114            }
115        }
116
117        // Look up the timer in question.
118        final int timerId = intent.getIntExtra(HandleDeskClockApiCalls.EXTRA_TIMER_ID, -1);
119        final Timer timer = DataModel.getDataModel().getTimer(timerId);
120
121        // If the timer cannot be located, ignore the action.
122        if (timer == null) {
123            return START_NOT_STICKY;
124        }
125
126        // Perform the action on the timer.
127        switch (intent.getAction()) {
128            case HandleDeskClockApiCalls.ACTION_START_TIMER:
129                DataModel.getDataModel().startTimer(timer);
130                if (fromNotification) {
131                    Events.sendTimerEvent(R.string.action_start, R.string.label_notification);
132                }
133                break;
134            case HandleDeskClockApiCalls.ACTION_PAUSE_TIMER:
135                DataModel.getDataModel().pauseTimer(timer);
136                if (fromNotification) {
137                    Events.sendTimerEvent(R.string.action_pause, R.string.label_notification);
138                }
139                break;
140            case HandleDeskClockApiCalls.ACTION_ADD_MINUTE_TIMER:
141                DataModel.getDataModel().addTimerMinute(timer);
142                if (fromNotification) {
143                    Events.sendTimerEvent(R.string.action_add_minute, R.string.label_notification);
144                }
145                break;
146            case HandleDeskClockApiCalls.ACTION_RESET_TIMER:
147                @StringRes int eventLabelId = fromNotification ? R.string.label_notification : 0;
148                DataModel.getDataModel().resetOrDeleteTimer(timer, eventLabelId);
149                break;
150            case ACTION_TIMER_EXPIRED:
151                DataModel.getDataModel().expireTimer(timer);
152                Events.sendTimerEvent(R.string.action_fire, R.string.label_intent);
153                break;
154        }
155
156        return START_NOT_STICKY;
157    }
158}