Alarms.java revision 98948f9ce1dabcc79350a847baf220635b0c087a
15fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project/*
25fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project * Copyright (C) 2007 The Android Open Source Project
35fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project *
45fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
55fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project * you may not use this file except in compliance with the License.
65fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project * You may obtain a copy of the License at
75fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project *
85fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
95fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project *
105fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
115fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
125fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
135fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project * See the License for the specific language governing permissions and
145fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project * limitations under the License.
155fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project */
165fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
175fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Projectpackage com.android.alarmclock;
185fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
195fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Projectimport android.app.AlarmManager;
205fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Projectimport android.app.PendingIntent;
215fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Projectimport android.content.ContentResolver;
225fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Projectimport android.content.ContentValues;
235fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Projectimport android.content.ContentUris;
245fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Projectimport android.content.Context;
255fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Projectimport android.content.Intent;
265fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Projectimport android.content.SharedPreferences;
275fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Projectimport android.database.Cursor;
285fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Projectimport android.net.Uri;
29d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scottimport android.os.Parcel;
305fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Projectimport android.provider.Settings;
315fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Projectimport android.text.format.DateFormat;
325fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
335fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Projectimport java.util.Calendar;
34eb142ac59aa8039c409b5fe4f50a130f16960d41Eric Fischerimport java.text.DateFormatSymbols;
355fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
365fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project/**
375fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project * The Alarms provider supplies info about Alarm Clock settings
385fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project */
395fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Projectpublic class Alarms {
405fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
41d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott    // This action triggers the AlarmReceiver as well as the AlarmKlaxon. It
42d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott    // is a public action used in the manifest for receiving Alarm broadcasts
43d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott    // from the alarm manager.
44d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott    public static final String ALARM_ALERT_ACTION = "com.android.alarmclock.ALARM_ALERT";
455fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
46d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott    // This is a private action used when the user clears all notifications.
47d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott    public static final String CLEAR_NOTIFICATION = "clear_notification";
485fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
49d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott    // This is a private action used by the AlarmKlaxon to update the UI to
50d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott    // show the alarm has been killed.
51d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott    public static final String ALARM_KILLED = "alarm_killed";
525fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
53d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott    // Extra in the ALARM_KILLED intent to indicate to the user how long the
54d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott    // alarm played before being killed.
55d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott    public static final String ALARM_KILLED_TIMEOUT = "alarm_killed_timeout";
565fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
57d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott    // This string is used to indicate a silent alarm in the db.
58d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott    public static final String ALARM_ALERT_SILENT = "silent";
595fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
60d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott    // This intent is sent from the notification when the user cancels the
61d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott    // snooze alert.
62d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott    public static final String CANCEL_SNOOZE = "cancel_snooze";
635fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
64d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott    // This string is used when passing an Alarm object through an intent.
65d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott    public static final String ALARM_INTENT_EXTRA = "intent.extra.alarm";
665fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
67d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott    // This extra is the raw Alarm object data. It is used in the
68d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott    // AlarmManagerService to avoid a ClassNotFoundException when filling in
69d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott    // the Intent extras.
70d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott    public static final String ALARM_RAW_DATA = "intent.extra.alarm_raw";
715fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
72d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott    // This string is used to identify the alarm id passed to SetAlarm from the
73d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott    // list of alarms.
74d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott    public static final String ALARM_ID = "alarm_id";
755fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
76d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott    final static String PREF_SNOOZE_ID = "snooze_id";
77d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott    final static String PREF_SNOOZE_TIME = "snooze_time";
785fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
79d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott    private final static String DM12 = "E h:mm aa";
80d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott    private final static String DM24 = "E k:mm";
815fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
82d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott    private final static String M12 = "h:mm aa";
831ebd23eaa82ab560f5c7d8aeca8df7512df8424ePatrick Scott    // Shared with DigitalClock
841ebd23eaa82ab560f5c7d8aeca8df7512df8424ePatrick Scott    final static String M24 = "kk:mm";
855fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
865fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project    /**
875fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project     * Creates a new Alarm.
885fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project     */
89d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott    public static Uri addAlarm(ContentResolver contentResolver) {
905fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project        ContentValues values = new ContentValues();
91d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott        values.put(Alarm.Columns.HOUR, 8);
92d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott        return contentResolver.insert(Alarm.Columns.CONTENT_URI, values);
935fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project    }
945fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
955fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project    /**
965fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project     * Removes an existing Alarm.  If this alarm is snoozing, disables
975fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project     * snooze.  Sets next alert.
985fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project     */
99d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott    public static void deleteAlarm(
1005fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project            Context context, int alarmId) {
1015fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
1025fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project        ContentResolver contentResolver = context.getContentResolver();
1035fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project        /* If alarm is snoozing, lose it */
104d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott        disableSnoozeAlert(context, alarmId);
1055fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
106d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott        Uri uri = ContentUris.withAppendedId(Alarm.Columns.CONTENT_URI, alarmId);
107d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott        contentResolver.delete(uri, "", null);
1085fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
1095fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project        setNextAlert(context);
1105fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project    }
1115fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
1125fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project    /**
1135fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project     * Queries all alarms
1145fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project     * @return cursor over all alarms
1155fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project     */
116d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott    public static Cursor getAlarmsCursor(ContentResolver contentResolver) {
1175fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project        return contentResolver.query(
118d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott                Alarm.Columns.CONTENT_URI, Alarm.Columns.ALARM_QUERY_COLUMNS,
119d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott                null, null, Alarm.Columns.DEFAULT_SORT_ORDER);
1205fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project    }
1215fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
122d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott    // Private method to get a more limited set of alarms from the database.
123d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott    private static Cursor getFilteredAlarmsCursor(
124d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott            ContentResolver contentResolver) {
125d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott        return contentResolver.query(Alarm.Columns.CONTENT_URI,
126d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott                Alarm.Columns.ALARM_QUERY_COLUMNS, Alarm.Columns.WHERE_ENABLED,
127d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott                null, null);
1285fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project    }
1295fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
1305fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project    /**
131d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott     * Return an Alarm object representing the alarm id in the database.
132d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott     * Returns null if no alarm exists.
1335fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project     */
134d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott    public static Alarm getAlarm(ContentResolver contentResolver, int alarmId) {
1355fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project        Cursor cursor = contentResolver.query(
136d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott                ContentUris.withAppendedId(Alarm.Columns.CONTENT_URI, alarmId),
137d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott                Alarm.Columns.ALARM_QUERY_COLUMNS,
138d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott                null, null, null);
139d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott        Alarm alarm = null;
140d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott        if (cursor != null) {
141d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott            if (cursor.moveToFirst()) {
142d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott                alarm = new Alarm(cursor);
143d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott            }
144d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott            cursor.close();
145d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott        }
146d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott        return alarm;
1475fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project    }
1485fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
1495fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
1505fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project    /**
1515fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project     * A convenience method to set an alarm in the Alarms
1525fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project     * content provider.
1535fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project     *
1545fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project     * @param id             corresponds to the _id column
1555fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project     * @param enabled        corresponds to the ENABLED column
1565fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project     * @param hour           corresponds to the HOUR column
1575fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project     * @param minutes        corresponds to the MINUTES column
1585fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project     * @param daysOfWeek     corresponds to the DAYS_OF_WEEK column
1595fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project     * @param time           corresponds to the ALARM_TIME column
1605fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project     * @param vibrate        corresponds to the VIBRATE column
1615fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project     * @param message        corresponds to the MESSAGE column
1625fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project     * @param alert          corresponds to the ALERT column
1635fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project     */
164d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott    public static void setAlarm(
1655fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project            Context context, int id, boolean enabled, int hour, int minutes,
166d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott            Alarm.DaysOfWeek daysOfWeek, boolean vibrate, String message,
1675fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project            String alert) {
1685fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
1695fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project        ContentValues values = new ContentValues(8);
1705fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project        ContentResolver resolver = context.getContentResolver();
171d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott        // Set the alarm_time value if this alarm does not repeat. This will be
172d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott        // used later to disable expired alarms.
173d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott        long time = 0;
174d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott        if (!daysOfWeek.isRepeatSet()) {
175d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott            time = calculateAlarm(hour, minutes, daysOfWeek).getTimeInMillis();
176d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott        }
1775fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
1785fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project        if (Log.LOGV) Log.v(
1795fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project                "**  setAlarm * idx " + id + " hour " + hour + " minutes " +
1805fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project                minutes + " enabled " + enabled + " time " + time);
1815fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
182d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott        values.put(Alarm.Columns.ENABLED, enabled ? 1 : 0);
183d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott        values.put(Alarm.Columns.HOUR, hour);
184d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott        values.put(Alarm.Columns.MINUTES, minutes);
185d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott        values.put(Alarm.Columns.ALARM_TIME, time);
186d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott        values.put(Alarm.Columns.DAYS_OF_WEEK, daysOfWeek.getCoded());
187d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott        values.put(Alarm.Columns.VIBRATE, vibrate);
188d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott        values.put(Alarm.Columns.MESSAGE, message);
189d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott        values.put(Alarm.Columns.ALERT, alert);
190d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott        resolver.update(ContentUris.withAppendedId(Alarm.Columns.CONTENT_URI, id),
1915fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project                        values, null, null);
1925fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
1935fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project        setNextAlert(context);
1945fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project    }
1955fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
1965fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project    /**
1975fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project     * A convenience method to enable or disable an alarm.
1985fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project     *
1995fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project     * @param id             corresponds to the _id column
2005fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project     * @param enabled        corresponds to the ENABLED column
2015fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project     */
2025fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
203d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott    public static void enableAlarm(
2045fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project            final Context context, final int id, boolean enabled) {
2055fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project        enableAlarmInternal(context, id, enabled);
2065fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project        setNextAlert(context);
2075fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project    }
2085fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
209d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott    private static void enableAlarmInternal(final Context context,
210d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott            final int id, boolean enabled) {
211d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott        enableAlarmInternal(context, getAlarm(context.getContentResolver(), id),
212d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott                enabled);
213d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott    }
2145fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
215d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott    private static void enableAlarmInternal(final Context context,
216d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott            final Alarm alarm, boolean enabled) {
217d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott        ContentResolver resolver = context.getContentResolver();
2185fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
2195fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project        ContentValues values = new ContentValues(2);
220d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott        values.put(Alarm.Columns.ENABLED, enabled ? 1 : 0);
2215fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
222d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott        // If we are enabling the alarm, calculate alarm time since the time
223d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott        // value in Alarm may be old.
2245fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project        if (enabled) {
225d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott            long time = 0;
226d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott            if (!alarm.daysOfWeek.isRepeatSet()) {
227d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott                time = calculateAlarm(alarm.hour, alarm.minutes,
228d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott                        alarm.daysOfWeek).getTimeInMillis();
2295fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project            }
230d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott            values.put(Alarm.Columns.ALARM_TIME, time);
2315fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project        }
2325fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
233d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott        resolver.update(ContentUris.withAppendedId(
234d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott                Alarm.Columns.CONTENT_URI, alarm.id), values, null, null);
2355fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project    }
2365fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
237d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott    public static Alarm calculateNextAlert(final Context context) {
238d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott        Alarm alarm = null;
239d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott        long minTime = Long.MAX_VALUE;
24098948f9ce1dabcc79350a847baf220635b0c087aPatrick Scott        long now = System.currentTimeMillis();
241d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott        Cursor cursor = getFilteredAlarmsCursor(context.getContentResolver());
242d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott        if (cursor != null) {
243d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott            if (cursor.moveToFirst()) {
244d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott                do {
245d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott                    Alarm a = new Alarm(cursor);
246d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott                    // A time of 0 indicates this is a repeating alarm, so
247d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott                    // calculate the time to get the next alert.
248d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott                    if (a.time == 0) {
249d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott                        a.time = calculateAlarm(a.hour, a.minutes, a.daysOfWeek)
250d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott                                .getTimeInMillis();
25198948f9ce1dabcc79350a847baf220635b0c087aPatrick Scott                    } else if (a.time < now) {
25298948f9ce1dabcc79350a847baf220635b0c087aPatrick Scott                        // Expired alarm, disable it and move along.
25398948f9ce1dabcc79350a847baf220635b0c087aPatrick Scott                        enableAlarmInternal(context, a, false);
25498948f9ce1dabcc79350a847baf220635b0c087aPatrick Scott                        continue;
255d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott                    }
256d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott                    if (a.time < minTime) {
257d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott                        minTime = a.time;
258d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott                        alarm = a;
259d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott                    }
260d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott                } while (cursor.moveToNext());
2615fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project            }
262d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott            cursor.close();
2635fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project        }
264d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott        return alarm;
2655fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project    }
2665fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
2675fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project    /**
2685fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project     * Disables non-repeating alarms that have passed.  Called at
2695fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project     * boot.
2705fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project     */
2715fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project    public static void disableExpiredAlarms(final Context context) {
272d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott        Cursor cur = getFilteredAlarmsCursor(context.getContentResolver());
2735fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project        long now = System.currentTimeMillis();
2745fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
2755fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project        if (cur.moveToFirst()) {
2765fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project            do {
277d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott                Alarm alarm = new Alarm(cur);
278d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott                // A time of 0 means this alarm repeats. If the time is
279d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott                // non-zero, check if the time is before now.
280d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott                if (alarm.time != 0 && alarm.time < now) {
281d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott                    if (Log.LOGV) {
282d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott                        Log.v("** DISABLE " + alarm.id + " now " + now +" set "
283d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott                                + alarm.time);
284d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott                    }
285d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott                    enableAlarmInternal(context, alarm, false);
2865fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project                }
2875fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project            } while (cur.moveToNext());
2885fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project        }
2895fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project        cur.close();
2905fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project    }
2915fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
2925fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project    /**
2935fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project     * Called at system startup, on time/timezone change, and whenever
2945fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project     * the user changes alarm settings.  Activates snooze if set,
2955fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project     * otherwise loads all alarms, activates next alert.
2965fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project     */
2975fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project    public static void setNextAlert(final Context context) {
298d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott        if (!enableSnoozeAlert(context)) {
299d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott            Alarm alarm = calculateNextAlert(context);
300d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott            if (alarm != null) {
301d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott                enableAlert(context, alarm, alarm.time);
3025fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project            } else {
303d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott                disableAlert(context);
3045fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project            }
3055fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project        }
3065fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project    }
3075fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
3085fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project    /**
3095fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project     * Sets alert in AlarmManger and StatusBar.  This is what will
3105fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project     * actually launch the alert when the alarm triggers.
3115fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project     *
312d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott     * @param alarm Alarm.
3135fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project     * @param atTimeInMillis milliseconds since epoch
3145fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project     */
315d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott    private static void enableAlert(Context context, final Alarm alarm,
316d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott            final long atTimeInMillis) {
3175fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project        AlarmManager am = (AlarmManager)
3185fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project                context.getSystemService(Context.ALARM_SERVICE);
3195fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
320d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott        if (Log.LOGV) {
321d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott            Log.v("** setAlert id " + alarm.id + " atTime " + atTimeInMillis);
3225d6f5fa51fa7fd13784a73199161deabec5bc898Patrick Scott        }
323d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott
324d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott        Intent intent = new Intent(ALARM_ALERT_ACTION);
325d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott
326d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott        // XXX: This is a slight hack to avoid an exception in the remote
327d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott        // AlarmManagerService process. The AlarmManager adds extra data to
328d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott        // this Intent which causes it to inflate. Since the remote process
329d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott        // does not know about the Alarm class, it throws a
330d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott        // ClassNotFoundException.
331d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott        //
332d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott        // To avoid this, we marshall the data ourselves and then parcel a plain
333d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott        // byte[] array. The AlarmReceiver class knows to build the Alarm
334d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott        // object from the byte[] array.
335d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott        Parcel out = Parcel.obtain();
336d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott        alarm.writeToParcel(out, 0);
337d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott        out.setDataPosition(0);
338d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott        intent.putExtra(ALARM_RAW_DATA, out.marshall());
339d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott
3405fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project        PendingIntent sender = PendingIntent.getBroadcast(
3415fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project                context, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
3425fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
343d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott        am.set(AlarmManager.RTC_WAKEUP, atTimeInMillis, sender);
3445fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
3455fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project        setStatusBarIcon(context, true);
3465fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
3475fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project        Calendar c = Calendar.getInstance();
3485fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project        c.setTime(new java.util.Date(atTimeInMillis));
3495fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project        String timeString = formatDayAndTime(context, c);
3505fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project        saveNextAlarm(context, timeString);
3515fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project    }
3525fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
3535fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project    /**
3545fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project     * Disables alert in AlarmManger and StatusBar.
3555fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project     *
3565fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project     * @param id Alarm ID.
3575fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project     */
358d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott    static void disableAlert(Context context) {
3595fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project        AlarmManager am = (AlarmManager)
3605fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project                context.getSystemService(Context.ALARM_SERVICE);
3615fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project        PendingIntent sender = PendingIntent.getBroadcast(
362d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott                context, 0, new Intent(ALARM_ALERT_ACTION),
363d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott                PendingIntent.FLAG_CANCEL_CURRENT);
3645fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project        am.cancel(sender);
3655fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project        setStatusBarIcon(context, false);
3665fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project        saveNextAlarm(context, "");
3675fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project    }
3685fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
369d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott    static void saveSnoozeAlert(final Context context, final int id,
370d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott            final long time) {
3715fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project        SharedPreferences prefs = context.getSharedPreferences(
3725fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project                AlarmClock.PREFERENCES, 0);
3735fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project        SharedPreferences.Editor ed = prefs.edit();
374d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott        if (id == -1) {
375e77fa5af5ac139f69ad504dbadd6f6aaab8c064dPatrick Scott            clearSnoozePreference(ed);
376d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott        } else {
377d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott            ed.putInt(PREF_SNOOZE_ID, id);
378d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott            ed.putLong(PREF_SNOOZE_TIME, time);
379e77fa5af5ac139f69ad504dbadd6f6aaab8c064dPatrick Scott            ed.commit();
3805d6f5fa51fa7fd13784a73199161deabec5bc898Patrick Scott        }
381d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott        // Set the next alert after updating the snooze.
382d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott        setNextAlert(context);
3835fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project    }
3845fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
3855fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project    /**
386d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott     * Disable the snooze alert if the given id matches the snooze id.
3875fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project     */
388d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott    static void disableSnoozeAlert(final Context context, final int id) {
3895fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project        SharedPreferences prefs = context.getSharedPreferences(
3905fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project                AlarmClock.PREFERENCES, 0);
391d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott        int snoozeId = prefs.getInt(PREF_SNOOZE_ID, -1);
392d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott        if (snoozeId == -1) {
393d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott            // No snooze set, do nothing.
394d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott            return;
395d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott        } else if (snoozeId == id) {
396d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott            // This is the same id so clear the shared prefs.
397e77fa5af5ac139f69ad504dbadd6f6aaab8c064dPatrick Scott            clearSnoozePreference(prefs.edit());
398d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott        }
3995fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project    }
4005fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
401e77fa5af5ac139f69ad504dbadd6f6aaab8c064dPatrick Scott    // Helper to remove the snooze preference. Do not use clear because that
402e77fa5af5ac139f69ad504dbadd6f6aaab8c064dPatrick Scott    // will erase the clock preferences.
403e77fa5af5ac139f69ad504dbadd6f6aaab8c064dPatrick Scott    private static void clearSnoozePreference(final SharedPreferences.Editor ed) {
404e77fa5af5ac139f69ad504dbadd6f6aaab8c064dPatrick Scott        ed.remove(PREF_SNOOZE_ID);
405e77fa5af5ac139f69ad504dbadd6f6aaab8c064dPatrick Scott        ed.remove(PREF_SNOOZE_TIME);
406e77fa5af5ac139f69ad504dbadd6f6aaab8c064dPatrick Scott        ed.commit();
407e77fa5af5ac139f69ad504dbadd6f6aaab8c064dPatrick Scott    };
408e77fa5af5ac139f69ad504dbadd6f6aaab8c064dPatrick Scott
4095fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project    /**
4105fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project     * If there is a snooze set, enable it in AlarmManager
4115fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project     * @return true if snooze is set
4125fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project     */
4135fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project    private static boolean enableSnoozeAlert(final Context context) {
4145fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project        SharedPreferences prefs = context.getSharedPreferences(
4155fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project                AlarmClock.PREFERENCES, 0);
4165fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
4175fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project        int id = prefs.getInt(PREF_SNOOZE_ID, -1);
418d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott        if (id == -1) {
419d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott            return false;
420d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott        }
421d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott        long time = prefs.getLong(PREF_SNOOZE_TIME, -1);
422d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott
423d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott        // Get the alarm from the db.
424d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott        final Alarm alarm = getAlarm(context.getContentResolver(), id);
425d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott        // The time in the database is either 0 (repeating) or a specific time
426d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott        // for a non-repeating alarm. Update this value so the AlarmReceiver
427d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott        // has the right time to compare.
428d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott        alarm.time = time;
429d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott
430d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott        enableAlert(context, alarm, time);
4315fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project        return true;
4325fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project    }
4335fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
4345fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project    /**
4355fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project     * Tells the StatusBar whether the alarm is enabled or disabled
4365fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project     */
4375fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project    private static void setStatusBarIcon(Context context, boolean enabled) {
4385fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project        Intent alarmChanged = new Intent(Intent.ACTION_ALARM_CHANGED);
4395fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project        alarmChanged.putExtra("alarmSet", enabled);
4405fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project        context.sendBroadcast(alarmChanged);
4415fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project    }
4425fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
4435fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project    /**
4445fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project     * Given an alarm in hours and minutes, return a time suitable for
4455fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project     * setting in AlarmManager.
4465fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project     * @param hour Always in 24 hour 0-23
4475fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project     * @param minute 0-59
4485fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project     * @param daysOfWeek 0-59
4495fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project     */
450d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott    static Calendar calculateAlarm(int hour, int minute, Alarm.DaysOfWeek daysOfWeek) {
4515fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
4525fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project        // start with now
4535fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project        Calendar c = Calendar.getInstance();
4545fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project        c.setTimeInMillis(System.currentTimeMillis());
4555fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
4565fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project        int nowHour = c.get(Calendar.HOUR_OF_DAY);
4575fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project        int nowMinute = c.get(Calendar.MINUTE);
4585fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
4595fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project        // if alarm is behind current time, advance one day
4605fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project        if (hour < nowHour  ||
4615fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project            hour == nowHour && minute <= nowMinute) {
4625fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project            c.add(Calendar.DAY_OF_YEAR, 1);
4635fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project        }
4645fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project        c.set(Calendar.HOUR_OF_DAY, hour);
4655fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project        c.set(Calendar.MINUTE, minute);
4665fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project        c.set(Calendar.SECOND, 0);
4675fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project        c.set(Calendar.MILLISECOND, 0);
4685fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
4695fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project        int addDays = daysOfWeek.getNextAlarm(c);
4705fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project        /* Log.v("** TIMES * " + c.getTimeInMillis() + " hour " + hour +
4715fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project           " minute " + minute + " dow " + c.get(Calendar.DAY_OF_WEEK) + " from now " +
4725fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project           addDays); */
4735fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project        if (addDays > 0) c.add(Calendar.DAY_OF_WEEK, addDays);
4745fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project        return c;
4755fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project    }
4765fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
4775fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project    static String formatTime(final Context context, int hour, int minute,
478d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott                             Alarm.DaysOfWeek daysOfWeek) {
4795fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project        Calendar c = calculateAlarm(hour, minute, daysOfWeek);
4805fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project        return formatTime(context, c);
4815fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project    }
4825fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
4835fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project    /* used by AlarmAlert */
4845fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project    static String formatTime(final Context context, Calendar c) {
4855fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project        String format = get24HourMode(context) ? M24 : M12;
4865fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project        return (c == null) ? "" : (String)DateFormat.format(format, c);
4875fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project    }
4885fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
4895fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project    /**
4905fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project     * Shows day and time -- used for lock screen
4915fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project     */
4925fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project    private static String formatDayAndTime(final Context context, Calendar c) {
4935fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project        String format = get24HourMode(context) ? DM24 : DM12;
4945fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project        return (c == null) ? "" : (String)DateFormat.format(format, c);
4955fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project    }
4965fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
4975fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project    /**
4985fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project     * Save time of the next alarm, as a formatted string, into the system
4995fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project     * settings so those who care can make use of it.
5005fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project     */
5015fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project    static void saveNextAlarm(final Context context, String timeString) {
5025fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project        Settings.System.putString(context.getContentResolver(),
5035fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project                                  Settings.System.NEXT_ALARM_FORMATTED,
5045fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project                                  timeString);
5055fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project    }
5065fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
5075fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project    /**
5085fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project     * @return true if clock is set to 24-hour mode
5095fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project     */
5105fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project    static boolean get24HourMode(final Context context) {
5115fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project        return android.text.format.DateFormat.is24HourFormat(context);
5125fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project    }
5135fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project}
514