OSDN Git Service

Fix the build.
[android-x86/packages-apps-DeskClock.git] / src / com / android / deskclock / AlarmReceiver.java
1 /*
2  * Copyright (C) 2007 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
17 package com.android.deskclock;
18
19 import android.app.KeyguardManager;
20 import android.app.Notification;
21 import android.app.NotificationManager;
22 import android.app.PendingIntent;
23 import android.content.ContentUris;
24 import android.content.Context;
25 import android.content.Intent;
26 import android.content.BroadcastReceiver;
27 import android.database.Cursor;
28 import android.os.Parcel;
29
30 import java.text.SimpleDateFormat;
31 import java.util.Date;
32
33 /**
34  * Glue class: connects AlarmAlert IntentReceiver to AlarmAlert
35  * activity.  Passes through Alarm ID.
36  */
37 public class AlarmReceiver extends BroadcastReceiver {
38
39     /** If the alarm is older than STALE_WINDOW seconds, ignore.  It
40         is probably the result of a time or timezone change */
41     private final static int STALE_WINDOW = 60 * 30;
42
43     @Override
44     public void onReceive(Context context, Intent intent) {
45         // Take care of the easy intents first.
46         if (Alarms.CLEAR_NOTIFICATION.equals(intent.getAction())) {
47             // If this is the "Clear All Notifications" intent, stop the alarm
48             // service and return.
49             context.stopService(new Intent(Alarms.ALARM_ALERT_ACTION));
50             return;
51         } else if (Alarms.ALARM_KILLED.equals(intent.getAction())) {
52             // The alarm has been killed, update the notification
53             updateNotification(context, (Alarm)
54                     intent.getParcelableExtra(Alarms.ALARM_INTENT_EXTRA),
55                     intent.getIntExtra(Alarms.ALARM_KILLED_TIMEOUT, -1));
56             return;
57         } else if (Alarms.CANCEL_SNOOZE.equals(intent.getAction())) {
58             Alarms.saveSnoozeAlert(context, -1, -1);
59             return;
60         }
61
62         Alarm alarm = null;
63         // Grab the alarm from the intent. Since the remote AlarmManagerService
64         // fills in the Intent to add some extra data, it must unparcel the
65         // Alarm object. It throws a ClassNotFoundException when unparcelling.
66         // To avoid this, do the marshalling ourselves.
67         final byte[] data = intent.getByteArrayExtra(Alarms.ALARM_RAW_DATA);
68         if (data != null) {
69             Parcel in = Parcel.obtain();
70             in.unmarshall(data, 0, data.length);
71             in.setDataPosition(0);
72             alarm = Alarm.CREATOR.createFromParcel(in);
73         }
74
75         if (alarm == null) {
76             Log.v("AlarmReceiver failed to parse the alarm from the intent");
77             return;
78         }
79
80         // Intentionally verbose: always log the alarm time to provide useful
81         // information in bug reports.
82         long now = System.currentTimeMillis();
83         SimpleDateFormat format =
84                 new SimpleDateFormat("HH:mm:ss.SSS aaa");
85         Log.v("AlarmReceiver.onReceive() id " + alarm.id + " setFor "
86                 + format.format(new Date(alarm.time)));
87
88         if (now > alarm.time + STALE_WINDOW * 1000) {
89             if (Log.LOGV) {
90                 Log.v("AlarmReceiver ignoring stale alarm");
91             }
92             return;
93         }
94
95         // Maintain a cpu wake lock until the AlarmAlert and AlarmKlaxon can
96         // pick it up.
97         AlarmAlertWakeLock.acquireCpuWakeLock(context);
98
99         /* Close dialogs and window shade */
100         Intent closeDialogs = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
101         context.sendBroadcast(closeDialogs);
102
103         // Decide which activity to start based on the state of the keyguard.
104         Class c = AlarmAlert.class;
105         KeyguardManager km = (KeyguardManager) context.getSystemService(
106                 Context.KEYGUARD_SERVICE);
107         if (km.inKeyguardRestrictedInputMode()) {
108             // Use the full screen activity for security.
109             c = AlarmAlertFullScreen.class;
110         }
111
112         /* launch UI, explicitly stating that this is not due to user action
113          * so that the current app's notification management is not disturbed */
114         Intent alarmAlert = new Intent(context, c);
115         alarmAlert.putExtra(Alarms.ALARM_INTENT_EXTRA, alarm);
116         alarmAlert.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
117                 | Intent.FLAG_ACTIVITY_NO_USER_ACTION);
118         context.startActivity(alarmAlert);
119
120         // Disable the snooze alert if this alarm is the snooze.
121         Alarms.disableSnoozeAlert(context, alarm.id);
122         // Disable this alarm if it does not repeat.
123         if (!alarm.daysOfWeek.isRepeatSet()) {
124             Alarms.enableAlarm(context, alarm.id, false);
125         } else {
126             // Enable the next alert if there is one. The above call to
127             // enableAlarm will call setNextAlert so avoid calling it twice.
128             Alarms.setNextAlert(context);
129         }
130
131         // Play the alarm alert and vibrate the device.
132         Intent playAlarm = new Intent(Alarms.ALARM_ALERT_ACTION);
133         playAlarm.putExtra(Alarms.ALARM_INTENT_EXTRA, alarm);
134         context.startService(playAlarm);
135
136         // Trigger a notification that, when clicked, will show the alarm alert
137         // dialog. No need to check for fullscreen since this will always be
138         // launched from a user action.
139         Intent notify = new Intent(context, AlarmAlert.class);
140         notify.putExtra(Alarms.ALARM_INTENT_EXTRA, alarm);
141         PendingIntent pendingNotify = PendingIntent.getActivity(context,
142                 alarm.id, notify, 0);
143
144         // Use the alarm's label or the default label as the ticker text and
145         // main text of the notification.
146         String label = alarm.getLabelOrDefault(context);
147         Notification n = new Notification(R.drawable.stat_notify_alarm,
148                 label, alarm.time);
149         n.setLatestEventInfo(context, label,
150                 context.getString(R.string.alarm_notify_text),
151                 pendingNotify);
152         n.flags |= Notification.FLAG_SHOW_LIGHTS;
153         n.ledARGB = 0xFF00FF00;
154         n.ledOnMS = 500;
155         n.ledOffMS = 500;
156
157         // Set the deleteIntent for when the user clicks "Clear All
158         // Notifications"
159         Intent clearAll = new Intent(context, AlarmReceiver.class);
160         clearAll.setAction(Alarms.CLEAR_NOTIFICATION);
161         n.deleteIntent = PendingIntent.getBroadcast(context, 0, clearAll, 0);
162
163         // Send the notification using the alarm id to easily identify the
164         // correct notification.
165         NotificationManager nm = getNotificationManager(context);
166         nm.notify(alarm.id, n);
167     }
168
169     private NotificationManager getNotificationManager(Context context) {
170         return (NotificationManager)
171                 context.getSystemService(Context.NOTIFICATION_SERVICE);
172     }
173
174     private void updateNotification(Context context, Alarm alarm, int timeout) {
175         NotificationManager nm = getNotificationManager(context);
176
177         // If the alarm is null, just cancel the notification.
178         if (alarm == null) {
179             if (Log.LOGV) {
180                 Log.v("Cannot update notification for killer callback");
181             }
182             return;
183         }
184
185         // Launch SetAlarm when clicked.
186         Intent viewAlarm = new Intent(context, SetAlarm.class);
187         viewAlarm.putExtra(Alarms.ALARM_ID, alarm.id);
188         PendingIntent intent =
189                 PendingIntent.getActivity(context, alarm.id, viewAlarm, 0);
190
191         // Update the notification to indicate that the alert has been
192         // silenced.
193         String label = alarm.getLabelOrDefault(context);
194         Notification n = new Notification(R.drawable.stat_notify_alarm,
195                 label, alarm.time);
196         n.setLatestEventInfo(context, label,
197                 context.getString(R.string.alarm_alert_alert_silenced, timeout),
198                 intent);
199         n.flags |= Notification.FLAG_AUTO_CANCEL;
200         nm.notify(alarm.id, n);
201     }
202 }