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
17fa954248b41b567dfa2ddd7bd063d3936a51758eDaniel Sandlerpackage com.android.deskclock;
185fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
195fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Projectimport android.app.AlarmManager;
20c7edd6ea840e25cb04d090b6c29dc96c04d2be40Patrick Scottimport android.app.NotificationManager;
215fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Projectimport android.app.PendingIntent;
225fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Projectimport android.content.ContentResolver;
235fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Projectimport android.content.ContentValues;
245fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Projectimport android.content.ContentUris;
255fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Projectimport android.content.Context;
265fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Projectimport android.content.Intent;
275fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Projectimport android.content.SharedPreferences;
285fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Projectimport android.database.Cursor;
295fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Projectimport android.net.Uri;
30d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scottimport android.os.Parcel;
315fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Projectimport android.provider.Settings;
325fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Projectimport android.text.format.DateFormat;
335fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
345fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Projectimport java.util.Calendar;
358304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrookimport java.util.HashSet;
368304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrookimport java.util.Set;
375fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
385fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project/**
395fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project * The Alarms provider supplies info about Alarm Clock settings
405fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project */
415fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Projectpublic class Alarms {
425fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
43d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott    // This action triggers the AlarmReceiver as well as the AlarmKlaxon. It
44d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott    // is a public action used in the manifest for receiving Alarm broadcasts
45d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott    // from the alarm manager.
46fa954248b41b567dfa2ddd7bd063d3936a51758eDaniel Sandler    public static final String ALARM_ALERT_ACTION = "com.android.deskclock.ALARM_ALERT";
475fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
48a3aba0c93c31e89045cca669418e85acfb4e22fbDavid Ingram    // A public action sent by AlarmKlaxon when the alarm has stopped sounding
49a3aba0c93c31e89045cca669418e85acfb4e22fbDavid Ingram    // for any reason (e.g. because it has been dismissed from AlarmAlertFullScreen,
50a3aba0c93c31e89045cca669418e85acfb4e22fbDavid Ingram    // or killed due to an incoming phone call, etc).
51a3aba0c93c31e89045cca669418e85acfb4e22fbDavid Ingram    public static final String ALARM_DONE_ACTION = "com.android.deskclock.ALARM_DONE";
52a3aba0c93c31e89045cca669418e85acfb4e22fbDavid Ingram
53a3aba0c93c31e89045cca669418e85acfb4e22fbDavid Ingram    // AlarmAlertFullScreen listens for this broadcast intent, so that other applications
54a3aba0c93c31e89045cca669418e85acfb4e22fbDavid Ingram    // can snooze the alarm (after ALARM_ALERT_ACTION and before ALARM_DONE_ACTION).
55a3aba0c93c31e89045cca669418e85acfb4e22fbDavid Ingram    public static final String ALARM_SNOOZE_ACTION = "com.android.deskclock.ALARM_SNOOZE";
56a3aba0c93c31e89045cca669418e85acfb4e22fbDavid Ingram
57a3aba0c93c31e89045cca669418e85acfb4e22fbDavid Ingram    // AlarmAlertFullScreen listens for this broadcast intent, so that other applications
58a3aba0c93c31e89045cca669418e85acfb4e22fbDavid Ingram    // can dismiss the alarm (after ALARM_ALERT_ACTION and before ALARM_DONE_ACTION).
59a3aba0c93c31e89045cca669418e85acfb4e22fbDavid Ingram    public static final String ALARM_DISMISS_ACTION = "com.android.deskclock.ALARM_DISMISS";
60a3aba0c93c31e89045cca669418e85acfb4e22fbDavid Ingram
61d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott    // This is a private action used by the AlarmKlaxon to update the UI to
62d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott    // show the alarm has been killed.
63d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott    public static final String ALARM_KILLED = "alarm_killed";
645fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
65d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott    // Extra in the ALARM_KILLED intent to indicate to the user how long the
66d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott    // alarm played before being killed.
67d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott    public static final String ALARM_KILLED_TIMEOUT = "alarm_killed_timeout";
685fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
69d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott    // This string is used to indicate a silent alarm in the db.
70d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott    public static final String ALARM_ALERT_SILENT = "silent";
715fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
72d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott    // This intent is sent from the notification when the user cancels the
73d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott    // snooze alert.
74d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott    public static final String CANCEL_SNOOZE = "cancel_snooze";
755fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
76d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott    // This string is used when passing an Alarm object through an intent.
77d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott    public static final String ALARM_INTENT_EXTRA = "intent.extra.alarm";
785fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
79d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott    // This extra is the raw Alarm object data. It is used in the
80d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott    // AlarmManagerService to avoid a ClassNotFoundException when filling in
81d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott    // the Intent extras.
82d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott    public static final String ALARM_RAW_DATA = "intent.extra.alarm_raw";
835fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
848304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook    private static final String PREF_SNOOZE_IDS = "snooze_ids";
858304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook    private static final String PREF_SNOOZE_TIME = "snooze_time";
865fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
87d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott    private final static String DM12 = "E h:mm aa";
88bababb66c17c665d374313da47e2f3734adec83aPatrick Scott    private final static String DM24 = "E kk:mm";
895fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
90d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott    private final static String M12 = "h:mm aa";
911ebd23eaa82ab560f5c7d8aeca8df7512df8424ePatrick Scott    // Shared with DigitalClock
921ebd23eaa82ab560f5c7d8aeca8df7512df8424ePatrick Scott    final static String M24 = "kk:mm";
935fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
948304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook    final static int INVALID_ALARM_ID = -1;
958304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook
965fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project    /**
976064d3f7aabcb073dc3f917e049bc04c67fb6b29Patrick Scott     * Creates a new Alarm and fills in the given alarm's id.
985fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project     */
99e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott    public static long addAlarm(Context context, Alarm alarm) {
100e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott        ContentValues values = createContentValues(alarm);
1016064d3f7aabcb073dc3f917e049bc04c67fb6b29Patrick Scott        Uri uri = context.getContentResolver().insert(
1026064d3f7aabcb073dc3f917e049bc04c67fb6b29Patrick Scott                Alarm.Columns.CONTENT_URI, values);
1036064d3f7aabcb073dc3f917e049bc04c67fb6b29Patrick Scott        alarm.id = (int) ContentUris.parseId(uri);
104e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott
105e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott        long timeInMillis = calculateAlarm(alarm);
106e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott        if (alarm.enabled) {
107e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott            clearSnoozeIfNeeded(context, timeInMillis);
108e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott        }
109e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott        setNextAlert(context);
110e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott        return timeInMillis;
1115fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project    }
1125fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
1135fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project    /**
1145fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project     * Removes an existing Alarm.  If this alarm is snoozing, disables
1155fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project     * snooze.  Sets next alert.
1165fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project     */
117bb13b216f986fc75dbd82d38f2bd6b2fbeb08abdPatrick Scott    public static void deleteAlarm(Context context, int alarmId) {
1188304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook        if (alarmId == INVALID_ALARM_ID) return;
1195fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
1205fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project        ContentResolver contentResolver = context.getContentResolver();
1215fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project        /* If alarm is snoozing, lose it */
122d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott        disableSnoozeAlert(context, alarmId);
1235fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
124d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott        Uri uri = ContentUris.withAppendedId(Alarm.Columns.CONTENT_URI, alarmId);
125d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott        contentResolver.delete(uri, "", null);
1265fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
1275fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project        setNextAlert(context);
1285fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project    }
1295fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
1305fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project    /**
1315fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project     * Queries all alarms
1325fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project     * @return cursor over all alarms
1335fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project     */
134d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott    public static Cursor getAlarmsCursor(ContentResolver contentResolver) {
1355fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project        return contentResolver.query(
136d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott                Alarm.Columns.CONTENT_URI, Alarm.Columns.ALARM_QUERY_COLUMNS,
137d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott                null, null, Alarm.Columns.DEFAULT_SORT_ORDER);
1385fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project    }
1395fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
140d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott    // Private method to get a more limited set of alarms from the database.
141d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott    private static Cursor getFilteredAlarmsCursor(
142d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott            ContentResolver contentResolver) {
143d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott        return contentResolver.query(Alarm.Columns.CONTENT_URI,
144d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott                Alarm.Columns.ALARM_QUERY_COLUMNS, Alarm.Columns.WHERE_ENABLED,
145d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott                null, null);
1465fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project    }
1475fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
148e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott    private static ContentValues createContentValues(Alarm alarm) {
149e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott        ContentValues values = new ContentValues(8);
150e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott        // Set the alarm_time value if this alarm does not repeat. This will be
151e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott        // used later to disable expire alarms.
152e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott        long time = 0;
153e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott        if (!alarm.daysOfWeek.isRepeatSet()) {
154e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott            time = calculateAlarm(alarm);
155e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott        }
156e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott
157e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott        values.put(Alarm.Columns.ENABLED, alarm.enabled ? 1 : 0);
158e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott        values.put(Alarm.Columns.HOUR, alarm.hour);
159e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott        values.put(Alarm.Columns.MINUTES, alarm.minutes);
160501a153616bd44880b587447788990d83f433a8fPatrick Scott        values.put(Alarm.Columns.ALARM_TIME, time);
161e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott        values.put(Alarm.Columns.DAYS_OF_WEEK, alarm.daysOfWeek.getCoded());
162e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott        values.put(Alarm.Columns.VIBRATE, alarm.vibrate);
163e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott        values.put(Alarm.Columns.MESSAGE, alarm.label);
164e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott
165e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott        // A null alert Uri indicates a silent alarm.
166e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott        values.put(Alarm.Columns.ALERT, alarm.alert == null ? ALARM_ALERT_SILENT
167e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott                : alarm.alert.toString());
168e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott
169e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott        return values;
170e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott    }
171e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott
172e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott    private static void clearSnoozeIfNeeded(Context context, long alarmTime) {
173e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott        // If this alarm fires before the next snooze, clear the snooze to
174e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott        // enable this alarm.
1758304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook        SharedPreferences prefs = context.getSharedPreferences(AlarmClock.PREFERENCES, 0);
1768304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook
1778304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook        // Get the list of snoozed alarms
1788304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook        final Set<String> snoozedIds = prefs.getStringSet(PREF_SNOOZE_IDS, new HashSet<String>());
1798304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook        for (String snoozedAlarm : snoozedIds) {
1808304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook            final long snoozeTime = prefs.getLong(getAlarmPrefSnoozeTimeKey(snoozedAlarm), 0);
1818304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook            if (alarmTime < snoozeTime) {
1828304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook                final int alarmId = Integer.parseInt(snoozedAlarm);
1838304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook                clearSnoozePreference(context, prefs, alarmId);
1848304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook            }
185e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott        }
186e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott    }
187e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott
1885fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project    /**
189d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott     * Return an Alarm object representing the alarm id in the database.
190d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott     * Returns null if no alarm exists.
1915fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project     */
192d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott    public static Alarm getAlarm(ContentResolver contentResolver, int alarmId) {
1935fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project        Cursor cursor = contentResolver.query(
194d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott                ContentUris.withAppendedId(Alarm.Columns.CONTENT_URI, alarmId),
195d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott                Alarm.Columns.ALARM_QUERY_COLUMNS,
196d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott                null, null, null);
197d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott        Alarm alarm = null;
198d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott        if (cursor != null) {
199d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott            if (cursor.moveToFirst()) {
200d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott                alarm = new Alarm(cursor);
201d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott            }
202d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott            cursor.close();
203d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott        }
204d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott        return alarm;
2055fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project    }
2065fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
2075fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
2085fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project    /**
2095fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project     * A convenience method to set an alarm in the Alarms
2105fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project     * content provider.
211c7edd6ea840e25cb04d090b6c29dc96c04d2be40Patrick Scott     * @return Time when the alarm will fire.
2125fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project     */
213e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott    public static long setAlarm(Context context, Alarm alarm) {
214e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott        ContentValues values = createContentValues(alarm);
2155fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project        ContentResolver resolver = context.getContentResolver();
216e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott        resolver.update(
217e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott                ContentUris.withAppendedId(Alarm.Columns.CONTENT_URI, alarm.id),
218e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott                values, null, null);
2195fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
220e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott        long timeInMillis = calculateAlarm(alarm);
221c7edd6ea840e25cb04d090b6c29dc96c04d2be40Patrick Scott
222e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott        if (alarm.enabled) {
223232725e8c1b1b85a44857cedcc842dcd2c956dc2Patrick Scott            // Disable the snooze if we just changed the snoozed alarm. This
224232725e8c1b1b85a44857cedcc842dcd2c956dc2Patrick Scott            // only does work if the snoozed alarm is the same as the given
225232725e8c1b1b85a44857cedcc842dcd2c956dc2Patrick Scott            // alarm.
226232725e8c1b1b85a44857cedcc842dcd2c956dc2Patrick Scott            // TODO: disableSnoozeAlert should have a better name.
227232725e8c1b1b85a44857cedcc842dcd2c956dc2Patrick Scott            disableSnoozeAlert(context, alarm.id);
228232725e8c1b1b85a44857cedcc842dcd2c956dc2Patrick Scott
229232725e8c1b1b85a44857cedcc842dcd2c956dc2Patrick Scott            // Disable the snooze if this alarm fires before the snoozed alarm.
230232725e8c1b1b85a44857cedcc842dcd2c956dc2Patrick Scott            // This works on every alarm since the user most likely intends to
231232725e8c1b1b85a44857cedcc842dcd2c956dc2Patrick Scott            // have the modified alarm fire next.
232e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott            clearSnoozeIfNeeded(context, timeInMillis);
233c7edd6ea840e25cb04d090b6c29dc96c04d2be40Patrick Scott        }
234c7edd6ea840e25cb04d090b6c29dc96c04d2be40Patrick Scott
2355fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project        setNextAlert(context);
236c7edd6ea840e25cb04d090b6c29dc96c04d2be40Patrick Scott
237c7edd6ea840e25cb04d090b6c29dc96c04d2be40Patrick Scott        return timeInMillis;
2385fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project    }
2395fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
2405fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project    /**
2415fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project     * A convenience method to enable or disable an alarm.
2425fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project     *
2435fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project     * @param id             corresponds to the _id column
2445fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project     * @param enabled        corresponds to the ENABLED column
2455fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project     */
2465fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
247d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott    public static void enableAlarm(
2485fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project            final Context context, final int id, boolean enabled) {
2495fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project        enableAlarmInternal(context, id, enabled);
2505fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project        setNextAlert(context);
2515fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project    }
2525fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
253d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott    private static void enableAlarmInternal(final Context context,
254d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott            final int id, boolean enabled) {
255d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott        enableAlarmInternal(context, getAlarm(context.getContentResolver(), id),
256d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott                enabled);
257d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott    }
2585fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
259d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott    private static void enableAlarmInternal(final Context context,
260d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott            final Alarm alarm, boolean enabled) {
26122924b6afee333e16fb62a19f1ac044c87c528b5Patrick Scott        if (alarm == null) {
26222924b6afee333e16fb62a19f1ac044c87c528b5Patrick Scott            return;
26322924b6afee333e16fb62a19f1ac044c87c528b5Patrick Scott        }
264d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott        ContentResolver resolver = context.getContentResolver();
2655fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
2665fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project        ContentValues values = new ContentValues(2);
267d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott        values.put(Alarm.Columns.ENABLED, enabled ? 1 : 0);
2685fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
269d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott        // If we are enabling the alarm, calculate alarm time since the time
270d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott        // value in Alarm may be old.
2715fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project        if (enabled) {
272d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott            long time = 0;
273d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott            if (!alarm.daysOfWeek.isRepeatSet()) {
274e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott                time = calculateAlarm(alarm);
2755fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project            }
276d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott            values.put(Alarm.Columns.ALARM_TIME, time);
27722924b6afee333e16fb62a19f1ac044c87c528b5Patrick Scott        } else {
27822924b6afee333e16fb62a19f1ac044c87c528b5Patrick Scott            // Clear the snooze if the id matches.
27922924b6afee333e16fb62a19f1ac044c87c528b5Patrick Scott            disableSnoozeAlert(context, alarm.id);
2805fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project        }
2815fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
282d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott        resolver.update(ContentUris.withAppendedId(
283d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott                Alarm.Columns.CONTENT_URI, alarm.id), values, null, null);
2845fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project    }
2855fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
2868304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook    private static Alarm calculateNextAlert(final Context context) {
287d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott        long minTime = Long.MAX_VALUE;
28898948f9ce1dabcc79350a847baf220635b0c087aPatrick Scott        long now = System.currentTimeMillis();
2898304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook        final SharedPreferences prefs = context.getSharedPreferences(AlarmClock.PREFERENCES, 0);
2908304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook
2918304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook        Set<Alarm> alarms = new HashSet<Alarm>();
2928304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook
2938304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook        // We need to to build the list of alarms from both the snoozed list and the scheduled
2948304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook        // list.  For a non-repeating alarm, when it goes of, it becomes disabled.  A snoozed
2958304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook        // non-repeating alarm is not in the active list in the database.
2968304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook
2978304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook        // first go through the snoozed alarms
2988304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook        final Set<String> snoozedIds = prefs.getStringSet(PREF_SNOOZE_IDS, new HashSet<String>());
2998304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook        for (String snoozedAlarm : snoozedIds) {
3008304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook            final int alarmId = Integer.parseInt(snoozedAlarm);
3018304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook            final Alarm a = getAlarm(context.getContentResolver(), alarmId);
3028304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook            alarms.add(a);
3038304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook        }
3048304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook
3058304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook        // Now add the scheduled alarms
3068304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook        final Cursor cursor = getFilteredAlarmsCursor(context.getContentResolver());
307d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott        if (cursor != null) {
30899ae7660f1e5e4645c889e78e26d44de20a7caf3Andy McFadden            try {
30999ae7660f1e5e4645c889e78e26d44de20a7caf3Andy McFadden                if (cursor.moveToFirst()) {
3108304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook                    do {
3118304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook                        final Alarm a = new Alarm(cursor);
3128304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook                        alarms.add(a);
3138304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook                    } while (cursor.moveToNext());
3148304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook                }
31599ae7660f1e5e4645c889e78e26d44de20a7caf3Andy McFadden            } finally {
31699ae7660f1e5e4645c889e78e26d44de20a7caf3Andy McFadden                cursor.close();
3175fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project            }
3185fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project        }
3198304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook
3208304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook        Alarm alarm = null;
3218304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook
3228304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook        for (Alarm a : alarms) {
3238304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook            // A time of 0 indicates this is a repeating alarm, so
3248304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook            // calculate the time to get the next alert.
3258304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook            if (a.time == 0) {
3268304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook                a.time = calculateAlarm(a);
3278304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook            }
3288304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook
3298304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook            // Update the alarm if it has been snoozed
3308304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook            updateAlarmTimeForSnooze(prefs, a);
3318304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook
3328304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook            if (a.time < now) {
3338304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook                Log.v("Disabling expired alarm set for " + Log.formatTime(a.time));
3348304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook                // Expired alarm, disable it and move along.
3358304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook                enableAlarmInternal(context, a, false);
3368304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook                continue;
3378304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook            }
3388304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook            if (a.time < minTime) {
3398304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook                minTime = a.time;
3408304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook                alarm = a;
3418304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook            }
3428304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook        }
3438304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook
344d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott        return alarm;
3455fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project    }
3465fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
3475fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project    /**
3485fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project     * Disables non-repeating alarms that have passed.  Called at
3495fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project     * boot.
3505fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project     */
3515fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project    public static void disableExpiredAlarms(final Context context) {
352d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott        Cursor cur = getFilteredAlarmsCursor(context.getContentResolver());
3535fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project        long now = System.currentTimeMillis();
3545fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
35599ae7660f1e5e4645c889e78e26d44de20a7caf3Andy McFadden        try {
35699ae7660f1e5e4645c889e78e26d44de20a7caf3Andy McFadden            if (cur.moveToFirst()) {
35799ae7660f1e5e4645c889e78e26d44de20a7caf3Andy McFadden                do {
35899ae7660f1e5e4645c889e78e26d44de20a7caf3Andy McFadden                    Alarm alarm = new Alarm(cur);
35999ae7660f1e5e4645c889e78e26d44de20a7caf3Andy McFadden                    // A time of 0 means this alarm repeats. If the time is
36099ae7660f1e5e4645c889e78e26d44de20a7caf3Andy McFadden                    // non-zero, check if the time is before now.
36199ae7660f1e5e4645c889e78e26d44de20a7caf3Andy McFadden                    if (alarm.time != 0 && alarm.time < now) {
36299ae7660f1e5e4645c889e78e26d44de20a7caf3Andy McFadden                        Log.v("Disabling expired alarm set for " +
36399ae7660f1e5e4645c889e78e26d44de20a7caf3Andy McFadden                              Log.formatTime(alarm.time));
36499ae7660f1e5e4645c889e78e26d44de20a7caf3Andy McFadden                        enableAlarmInternal(context, alarm, false);
36599ae7660f1e5e4645c889e78e26d44de20a7caf3Andy McFadden                    }
36699ae7660f1e5e4645c889e78e26d44de20a7caf3Andy McFadden                } while (cur.moveToNext());
36799ae7660f1e5e4645c889e78e26d44de20a7caf3Andy McFadden            }
36899ae7660f1e5e4645c889e78e26d44de20a7caf3Andy McFadden        } finally {
36999ae7660f1e5e4645c889e78e26d44de20a7caf3Andy McFadden            cur.close();
3705fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project        }
3715fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project    }
3725fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
3735fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project    /**
3745fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project     * Called at system startup, on time/timezone change, and whenever
3755fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project     * the user changes alarm settings.  Activates snooze if set,
3765fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project     * otherwise loads all alarms, activates next alert.
3775fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project     */
3785fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project    public static void setNextAlert(final Context context) {
3798304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook        final Alarm alarm = calculateNextAlert(context);
3808304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook        if (alarm != null) {
3818304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook            enableAlert(context, alarm, alarm.time);
3828304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook        } else {
3838304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook            disableAlert(context);
3845fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project        }
3855fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project    }
3865fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
3875fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project    /**
3885fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project     * Sets alert in AlarmManger and StatusBar.  This is what will
3895fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project     * actually launch the alert when the alarm triggers.
3905fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project     *
391d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott     * @param alarm Alarm.
3925fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project     * @param atTimeInMillis milliseconds since epoch
3935fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project     */
394d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott    private static void enableAlert(Context context, final Alarm alarm,
395d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott            final long atTimeInMillis) {
3965fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project        AlarmManager am = (AlarmManager)
3975fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project                context.getSystemService(Context.ALARM_SERVICE);
3985fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
399d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott        if (Log.LOGV) {
400d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott            Log.v("** setAlert id " + alarm.id + " atTime " + atTimeInMillis);
4015d6f5fa51fa7fd13784a73199161deabec5bc898Patrick Scott        }
402d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott
403d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott        Intent intent = new Intent(ALARM_ALERT_ACTION);
404d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott
405d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott        // XXX: This is a slight hack to avoid an exception in the remote
406d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott        // AlarmManagerService process. The AlarmManager adds extra data to
407d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott        // this Intent which causes it to inflate. Since the remote process
408d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott        // does not know about the Alarm class, it throws a
409d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott        // ClassNotFoundException.
410d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott        //
411d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott        // To avoid this, we marshall the data ourselves and then parcel a plain
412d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott        // byte[] array. The AlarmReceiver class knows to build the Alarm
413d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott        // object from the byte[] array.
414d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott        Parcel out = Parcel.obtain();
415d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott        alarm.writeToParcel(out, 0);
416d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott        out.setDataPosition(0);
417d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott        intent.putExtra(ALARM_RAW_DATA, out.marshall());
418d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott
4195fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project        PendingIntent sender = PendingIntent.getBroadcast(
4205fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project                context, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
4215fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
422d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott        am.set(AlarmManager.RTC_WAKEUP, atTimeInMillis, sender);
4235fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
4245fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project        setStatusBarIcon(context, true);
4255fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
4265fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project        Calendar c = Calendar.getInstance();
427e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott        c.setTimeInMillis(atTimeInMillis);
4285fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project        String timeString = formatDayAndTime(context, c);
4295fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project        saveNextAlarm(context, timeString);
4305fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project    }
4315fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
4325fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project    /**
4335fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project     * Disables alert in AlarmManger and StatusBar.
4345fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project     *
4355fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project     * @param id Alarm ID.
4365fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project     */
437d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott    static void disableAlert(Context context) {
4385fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project        AlarmManager am = (AlarmManager)
4395fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project                context.getSystemService(Context.ALARM_SERVICE);
4405fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project        PendingIntent sender = PendingIntent.getBroadcast(
441d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott                context, 0, new Intent(ALARM_ALERT_ACTION),
442d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott                PendingIntent.FLAG_CANCEL_CURRENT);
4435fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project        am.cancel(sender);
4445fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project        setStatusBarIcon(context, false);
4455fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project        saveNextAlarm(context, "");
4465fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project    }
4475fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
448d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott    static void saveSnoozeAlert(final Context context, final int id,
449d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott            final long time) {
4505fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project        SharedPreferences prefs = context.getSharedPreferences(
4515fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project                AlarmClock.PREFERENCES, 0);
4528304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook        if (id == INVALID_ALARM_ID) {
4538304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook            clearAllSnoozePreferences(context, prefs);
454d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott        } else {
4558304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook            final Set<String> snoozedIds =
4568304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook                    prefs.getStringSet(PREF_SNOOZE_IDS, new HashSet<String>());
4578304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook            snoozedIds.add(Integer.toString(id));
4588304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook            final SharedPreferences.Editor ed = prefs.edit();
4598304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook            ed.putStringSet(PREF_SNOOZE_IDS, snoozedIds);
4608304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook            ed.putLong(getAlarmPrefSnoozeTimeKey(id), time);
461c6098ef1fc69fe117343cc2e3db0d2b97b2daa6fBrad Fitzpatrick            ed.apply();
4625d6f5fa51fa7fd13784a73199161deabec5bc898Patrick Scott        }
463d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott        // Set the next alert after updating the snooze.
464d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott        setNextAlert(context);
4655fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project    }
4665fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
4678304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook    private static String getAlarmPrefSnoozeTimeKey(int id) {
4688304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook        return getAlarmPrefSnoozeTimeKey(Integer.toString(id));
4698304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook    }
4708304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook
4718304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook    private static String getAlarmPrefSnoozeTimeKey(String id) {
4728304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook        return PREF_SNOOZE_TIME + id;
4738304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook    }
4748304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook
4755fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project    /**
476d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott     * Disable the snooze alert if the given id matches the snooze id.
4775fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project     */
478d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott    static void disableSnoozeAlert(final Context context, final int id) {
4795fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project        SharedPreferences prefs = context.getSharedPreferences(
4805fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project                AlarmClock.PREFERENCES, 0);
4818304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook        if (hasAlarmBeenSnoozed(prefs, id)) {
482d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott            // This is the same id so clear the shared prefs.
4838304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook            clearSnoozePreference(context, prefs, id);
484d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott        }
4855fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project    }
4865fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
487e77fa5af5ac139f69ad504dbadd6f6aaab8c064dPatrick Scott    // Helper to remove the snooze preference. Do not use clear because that
488c7edd6ea840e25cb04d090b6c29dc96c04d2be40Patrick Scott    // will erase the clock preferences. Also clear the snooze notification in
489c7edd6ea840e25cb04d090b6c29dc96c04d2be40Patrick Scott    // the window shade.
490c7edd6ea840e25cb04d090b6c29dc96c04d2be40Patrick Scott    private static void clearSnoozePreference(final Context context,
4918304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook            final SharedPreferences prefs, final int id) {
4928304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook        final String alarmStr = Integer.toString(id);
4938304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook        final Set<String> snoozedIds =
4948304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook                prefs.getStringSet(PREF_SNOOZE_IDS, new HashSet<String>());
4958304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook        if (snoozedIds.contains(alarmStr)) {
496c7edd6ea840e25cb04d090b6c29dc96c04d2be40Patrick Scott            NotificationManager nm = (NotificationManager)
497c7edd6ea840e25cb04d090b6c29dc96c04d2be40Patrick Scott                    context.getSystemService(Context.NOTIFICATION_SERVICE);
4988304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook            nm.cancel(id);
499c7edd6ea840e25cb04d090b6c29dc96c04d2be40Patrick Scott        }
500c7edd6ea840e25cb04d090b6c29dc96c04d2be40Patrick Scott
501c7edd6ea840e25cb04d090b6c29dc96c04d2be40Patrick Scott        final SharedPreferences.Editor ed = prefs.edit();
5028304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook        snoozedIds.remove(alarmStr);
5038304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook        ed.putStringSet(PREF_SNOOZE_IDS, snoozedIds);
5048304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook        ed.remove(getAlarmPrefSnoozeTimeKey(alarmStr));
5058304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook        ed.apply();
5068304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook    }
5078304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook
5088304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook    private static void clearAllSnoozePreferences(final Context context,
5098304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook            final SharedPreferences prefs) {
5108304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook        NotificationManager nm = (NotificationManager)
5118304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook                context.getSystemService(Context.NOTIFICATION_SERVICE);
5128304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook        final Set<String> snoozedIds =
5138304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook                prefs.getStringSet(PREF_SNOOZE_IDS, new HashSet<String>());
5148304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook        final SharedPreferences.Editor ed = prefs.edit();
5158304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook        for (String snoozeId : snoozedIds) {
5168304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook            nm.cancel(Integer.parseInt(snoozeId));
5178304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook            ed.remove(getAlarmPrefSnoozeTimeKey(snoozeId));
5188304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook        }
5198304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook
5208304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook        ed.remove(PREF_SNOOZE_IDS);
521c6098ef1fc69fe117343cc2e3db0d2b97b2daa6fBrad Fitzpatrick        ed.apply();
5228304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook    }
5238304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook
5248304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook    private static boolean hasAlarmBeenSnoozed(final SharedPreferences prefs, final int alarmId) {
5258304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook        final Set<String> snoozedIds = prefs.getStringSet(PREF_SNOOZE_IDS, null);
5268304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook
5278304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook        // Return true if there a valid snoozed alarmId was saved
5288304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook        return snoozedIds != null && snoozedIds.contains(Integer.toString(alarmId));
5298304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook    }
530e77fa5af5ac139f69ad504dbadd6f6aaab8c064dPatrick Scott
5315fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project    /**
5328304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook     * Updates the specified Alarm with the additional snooze time.
5338304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook     * Returns a boolean indicating whether the alarm was updated.
5345fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project     */
5358304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook    private static boolean updateAlarmTimeForSnooze(
5368304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook            final SharedPreferences prefs, final Alarm alarm) {
5378304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook        if (!hasAlarmBeenSnoozed(prefs, alarm.id)) {
5388304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook            // No need to modify the alarm
539d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott            return false;
540d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott        }
541d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott
5428304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook        final long time = prefs.getLong(getAlarmPrefSnoozeTimeKey(alarm.id), -1);
543d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott        // The time in the database is either 0 (repeating) or a specific time
544d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott        // for a non-repeating alarm. Update this value so the AlarmReceiver
545d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott        // has the right time to compare.
546d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott        alarm.time = time;
547d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott
5485fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project        return true;
5495fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project    }
5505fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
5515fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project    /**
5525fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project     * Tells the StatusBar whether the alarm is enabled or disabled
5535fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project     */
5545fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project    private static void setStatusBarIcon(Context context, boolean enabled) {
555fe8dd39ee5e173f15337d09c36aa453a55364e98Patrick Scott        Intent alarmChanged = new Intent("android.intent.action.ALARM_CHANGED");
5565fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project        alarmChanged.putExtra("alarmSet", enabled);
5575fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project        context.sendBroadcast(alarmChanged);
5585fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project    }
5595fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
560e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott    private static long calculateAlarm(Alarm alarm) {
561e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott        return calculateAlarm(alarm.hour, alarm.minutes, alarm.daysOfWeek)
562e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott                .getTimeInMillis();
563e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott    }
564e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott
5655fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project    /**
5665fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project     * Given an alarm in hours and minutes, return a time suitable for
5675fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project     * setting in AlarmManager.
5685fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project     */
569e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott    static Calendar calculateAlarm(int hour, int minute,
570e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott            Alarm.DaysOfWeek daysOfWeek) {
5715fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
5725fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project        // start with now
5735fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project        Calendar c = Calendar.getInstance();
5745fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project        c.setTimeInMillis(System.currentTimeMillis());
5755fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
5765fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project        int nowHour = c.get(Calendar.HOUR_OF_DAY);
5775fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project        int nowMinute = c.get(Calendar.MINUTE);
5785fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
5795fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project        // if alarm is behind current time, advance one day
5805fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project        if (hour < nowHour  ||
5815fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project            hour == nowHour && minute <= nowMinute) {
5825fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project            c.add(Calendar.DAY_OF_YEAR, 1);
5835fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project        }
5845fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project        c.set(Calendar.HOUR_OF_DAY, hour);
5855fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project        c.set(Calendar.MINUTE, minute);
5865fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project        c.set(Calendar.SECOND, 0);
5875fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project        c.set(Calendar.MILLISECOND, 0);
5885fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
5895fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project        int addDays = daysOfWeek.getNextAlarm(c);
5905fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project        if (addDays > 0) c.add(Calendar.DAY_OF_WEEK, addDays);
5915fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project        return c;
5925fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project    }
5935fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
5945fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project    static String formatTime(final Context context, int hour, int minute,
595d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott                             Alarm.DaysOfWeek daysOfWeek) {
5965fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project        Calendar c = calculateAlarm(hour, minute, daysOfWeek);
5975fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project        return formatTime(context, c);
5985fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project    }
5995fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
6005fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project    /* used by AlarmAlert */
6015fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project    static String formatTime(final Context context, Calendar c) {
6025fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project        String format = get24HourMode(context) ? M24 : M12;
6035fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project        return (c == null) ? "" : (String)DateFormat.format(format, c);
6045fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project    }
6055fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
6065fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project    /**
6075fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project     * Shows day and time -- used for lock screen
6085fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project     */
6095fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project    private static String formatDayAndTime(final Context context, Calendar c) {
6105fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project        String format = get24HourMode(context) ? DM24 : DM12;
6115fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project        return (c == null) ? "" : (String)DateFormat.format(format, c);
6125fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project    }
6135fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
6145fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project    /**
6155fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project     * Save time of the next alarm, as a formatted string, into the system
6165fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project     * settings so those who care can make use of it.
6175fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project     */
6185fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project    static void saveNextAlarm(final Context context, String timeString) {
6195fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project        Settings.System.putString(context.getContentResolver(),
6205fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project                                  Settings.System.NEXT_ALARM_FORMATTED,
6215fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project                                  timeString);
6225fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project    }
6235fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
6245fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project    /**
6255fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project     * @return true if clock is set to 24-hour mode
6265fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project     */
6275fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project    static boolean get24HourMode(final Context context) {
6285fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project        return android.text.format.DateFormat.is24HourFormat(context);
6295fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project    }
6305fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project}
631