Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9fc42f9a authored by Paul Sliwowski's avatar Paul Sliwowski
Browse files

Make alarm times be in local time, regardless of time zone.

Bug: 5974730
Change-Id: I454dda60f40352d202c270d518b1830ee081ad39
parent ce9b1067
Loading
Loading
Loading
Loading
+12 −7
Original line number Diff line number Diff line
@@ -30,7 +30,6 @@ import java.util.HashMap;
import java.util.HashSet;

public final class Alarm implements Parcelable {

    //////////////////////////////
    // Parcelable apis
    //////////////////////////////
@@ -55,12 +54,14 @@ public final class Alarm implements Parcelable {
        p.writeInt(hour);
        p.writeInt(minutes);
        p.writeInt(daysOfWeek.getCoded());
        p.writeLong(time);
        // We don't need the alarmTime field anymore, but write 0 to be backwards compatible
        p.writeLong(0);
        p.writeInt(vibrate ? 1 : 0);
        p.writeString(label);
        p.writeParcelable(alert, flags);
        p.writeInt(silent ? 1 : 0);
    }

    //////////////////////////////
    // end Parcelable apis
    //////////////////////////////
@@ -97,6 +98,7 @@ public final class Alarm implements Parcelable {
         * Alarm time in UTC milliseconds from the epoch.
         * <P>Type: INTEGER</P>
         */
        @Deprecated // Calculate this from the other fields
        public static final String ALARM_TIME = "alarmtime";

        /**
@@ -145,7 +147,7 @@ public final class Alarm implements Parcelable {
        public static final int ALARM_HOUR_INDEX = 1;
        public static final int ALARM_MINUTES_INDEX = 2;
        public static final int ALARM_DAYS_OF_WEEK_INDEX = 3;
        public static final int ALARM_TIME_INDEX = 4;
        @Deprecated public static final int ALARM_TIME_INDEX = 4;
        public static final int ALARM_ENABLED_INDEX = 5;
        public static final int ALARM_VIBRATE_INDEX = 6;
        public static final int ALARM_MESSAGE_INDEX = 7;
@@ -161,7 +163,6 @@ public final class Alarm implements Parcelable {
    public int        hour;
    public int        minutes;
    public DaysOfWeek daysOfWeek;
    public long       time;
    public boolean    vibrate;
    public String     label;
    public Uri        alert;
@@ -176,7 +177,6 @@ public final class Alarm implements Parcelable {
                ", hour=" + hour +
                ", minutes=" + minutes +
                ", daysOfWeek=" + daysOfWeek +
                ", time=" + time +
                ", vibrate=" + vibrate +
                ", label='" + label + '\'' +
                ", silent=" + silent +
@@ -189,7 +189,6 @@ public final class Alarm implements Parcelable {
        hour = c.getInt(Columns.ALARM_HOUR_INDEX);
        minutes = c.getInt(Columns.ALARM_MINUTES_INDEX);
        daysOfWeek = new DaysOfWeek(c.getInt(Columns.ALARM_DAYS_OF_WEEK_INDEX));
        time = c.getLong(Columns.ALARM_TIME_INDEX);
        vibrate = c.getInt(Columns.ALARM_VIBRATE_INDEX) == 1;
        label = c.getString(Columns.ALARM_MESSAGE_INDEX);
        String alertString = c.getString(Columns.ALARM_ALERT_INDEX);
@@ -218,7 +217,8 @@ public final class Alarm implements Parcelable {
        hour = p.readInt();
        minutes = p.readInt();
        daysOfWeek = new DaysOfWeek(p.readInt());
        time = p.readLong();
        // Don't need the alarmTime field anymore, but do a readLong to be backwards compatible
        p.readLong();
        vibrate = p.readInt() == 1;
        label = p.readString();
        alert = (Uri) p.readParcelable(null);
@@ -236,6 +236,11 @@ public final class Alarm implements Parcelable {
        alert = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_ALARM);
    }

    public long calculateAlarmTime() {
        // Would it be safe to cache this value in memory?
        return Alarms.calculateAlarm(hour, minutes, daysOfWeek).getTimeInMillis();
    }

    public String getLabelOrDefault(Context context) {
        if (label == null || label.length() == 0) {
            return context.getString(R.string.default_label);
+7 −6
Original line number Diff line number Diff line
@@ -116,10 +116,11 @@ public class AlarmReceiver extends BroadcastReceiver {
        // Intentionally verbose: always log the alarm time to provide useful
        // information in bug reports.
        long now = System.currentTimeMillis();
        Log.v("Received alarm set for id=" + alarm.id + " " + Log.formatTime(alarm.time));
        long alarmTime = alarm.calculateAlarmTime();
        Log.v("Received alarm set for id=" + alarm.id + " " + Log.formatTime(alarmTime));

        // Always verbose to track down time change problems.
        if (now > alarm.time + STALE_WINDOW) {
        if (now > alarmTime + STALE_WINDOW) {
            Log.v("Ignoring stale alarm");
            return;
        }
@@ -167,15 +168,15 @@ public class AlarmReceiver extends BroadcastReceiver {
                alarm.id, dismissIntent, 0);

        final Calendar cal = Calendar.getInstance();
        cal.setTimeInMillis(alarm.time);
        String alarmTime = Alarms.formatTime(context, cal);
        cal.setTimeInMillis(alarmTime);
        String alarmTimeLabel = Alarms.formatTime(context, cal);

        // Use the alarm's label or the default label main text of the notification.
        String label = alarm.getLabelOrDefault(context);

        Notification n = new Notification.Builder(context)
        .setContentTitle(label)
        .setContentText(alarmTime)
        .setContentText(alarmTimeLabel)
        .setSmallIcon(R.drawable.stat_notify_alarm)
        .setOngoing(true)
        .setAutoCancel(false)
@@ -231,7 +232,7 @@ public class AlarmReceiver extends BroadcastReceiver {
        // silenced.
        String label = alarm.getLabelOrDefault(context);
        Notification n = new Notification(R.drawable.stat_notify_alarm,
                label, alarm.time);
                label, alarm.calculateAlarmTime());
        n.setLatestEventInfo(context, label,
                context.getString(R.string.alarm_alert_alert_silenced, timeout),
                intent);
+25 −64
Original line number Diff line number Diff line
@@ -116,7 +116,7 @@ public class Alarms {
                Alarm.Columns.CONTENT_URI, values);
        alarm.id = (int) ContentUris.parseId(uri);

        long timeInMillis = calculateAlarm(alarm);
        long timeInMillis = alarm.calculateAlarmTime();
        if (alarm.enabled) {
            clearSnoozeIfNeeded(context, timeInMillis);
        }
@@ -167,13 +167,6 @@ public class Alarms {

    private static ContentValues createContentValues(Alarm alarm) {
        ContentValues values = new ContentValues(8);
        // Set the alarm_time value if this alarm does not repeat. This will be
        // used later to disable expire alarms.
        long time = 0;
        if (!alarm.daysOfWeek.isRepeatSet()) {
            time = calculateAlarm(alarm);
        }

        // -1 means generate new id.
        if (alarm.id != -1) {
            values.put(Alarm.Columns._ID, alarm.id);
@@ -182,7 +175,8 @@ public class Alarms {
        values.put(Alarm.Columns.ENABLED, alarm.enabled ? 1 : 0);
        values.put(Alarm.Columns.HOUR, alarm.hour);
        values.put(Alarm.Columns.MINUTES, alarm.minutes);
        values.put(Alarm.Columns.ALARM_TIME, time);
        // We don't need this field anymore
        values.put(Alarm.Columns.ALARM_TIME, 0);
        values.put(Alarm.Columns.DAYS_OF_WEEK, alarm.daysOfWeek.getCoded());
        values.put(Alarm.Columns.VIBRATE, alarm.vibrate);
        values.put(Alarm.Columns.MESSAGE, alarm.label);
@@ -246,8 +240,7 @@ public class Alarms {
            return rowsUpdated;
        }

        long timeInMillis = calculateAlarm(alarm);

        long timeInMillis = alarm.calculateAlarmTime();
        if (alarm.enabled) {
            // Disable the snooze if we just changed the snoozed alarm. This
            // only does work if the snoozed alarm is the same as the given
@@ -295,15 +288,7 @@ public class Alarms {
        ContentValues values = new ContentValues(2);
        values.put(Alarm.Columns.ENABLED, enabled ? 1 : 0);

        // If we are enabling the alarm, calculate alarm time since the time
        // value in Alarm may be old.
        if (enabled) {
            long time = 0;
            if (!alarm.daysOfWeek.isRepeatSet()) {
                time = calculateAlarm(alarm);
            }
            values.put(Alarm.Columns.ALARM_TIME, time);
        } else {
        if (!enabled) {
            // Clear the snooze if the id matches.
            disableSnoozeAlert(context, alarm.id);
        }
@@ -349,23 +334,19 @@ public class Alarms {
        Alarm alarm = null;

        for (Alarm a : alarms) {
            // A time of 0 indicates this is a repeating alarm, so
            // calculate the time to get the next alert.
            if (a.time == 0) {
                a.time = calculateAlarm(a);
            }

            // Update the alarm if it has been snoozed
            updateAlarmTimeForSnooze(prefs, a);
            long alarmTime = hasAlarmBeenSnoozed(prefs, a.id) ?
                    prefs.getLong(getAlarmPrefSnoozeTimeKey(alarm.id), -1) :
                    a.calculateAlarmTime();

            if (a.time < now) {
                Log.v("Disabling expired alarm set for " + Log.formatTime(a.time));
            if (alarmTime < now) {
                Log.v("Disabling expired alarm set for " + Log.formatTime(alarmTime));
                // Expired alarm, disable it and move along.
                enableAlarmInternal(context, a, false);
                continue;
            }
            if (a.time < minTime) {
                minTime = a.time;
            if (alarmTime < minTime) {
                minTime = alarmTime;
                alarm = a;
            }
        }
@@ -385,11 +366,14 @@ public class Alarms {
            if (cur.moveToFirst()) {
                do {
                    Alarm alarm = new Alarm(cur);
                    // A time of 0 means this alarm repeats. If the time is
                    // non-zero, check if the time is before now.
                    if (alarm.time != 0 && alarm.time < now) {
                        Log.v("Disabling expired alarm set for " +
                              Log.formatTime(alarm.time));
                    // Ignore repeatable alarms
                    if (alarm.daysOfWeek.isRepeatSet()) {
                        continue;
                    }

                    long alarmTime = alarm.calculateAlarmTime();
                    if (alarmTime < now) {
                        Log.v("Disabling expired alarm set for " + Log.formatTime(alarmTime));
                        enableAlarmInternal(context, alarm, false);
                    }
                } while (cur.moveToNext());
@@ -407,7 +391,7 @@ public class Alarms {
    public static void setNextAlert(final Context context) {
        final Alarm alarm = calculateNextAlert(context);
        if (alarm != null) {
            enableAlert(context, alarm, alarm.time);
            enableAlert(context, alarm, alarm.calculateAlarmTime());
        } else {
            disableAlert(context);
        }
@@ -479,6 +463,8 @@ public class Alarms {
        saveNextAlarm(context, "");
    }

    // Snoozes are affected by timezone changes, but this shouldn't be a problem
    // for real use-cases.
    static void saveSnoozeAlert(final Context context, final int id,
            final long time) {
        SharedPreferences prefs = context.getSharedPreferences(PREFERENCES, 0);
@@ -560,26 +546,6 @@ public class Alarms {
        return snoozedIds != null && snoozedIds.contains(Integer.toString(alarmId));
    }

    /**
     * Updates the specified Alarm with the additional snooze time.
     * Returns a boolean indicating whether the alarm was updated.
     */
    private static boolean updateAlarmTimeForSnooze(
            final SharedPreferences prefs, final Alarm alarm) {
        if (!hasAlarmBeenSnoozed(prefs, alarm.id)) {
            // No need to modify the alarm
            return false;
        }

        final long time = prefs.getLong(getAlarmPrefSnoozeTimeKey(alarm.id), -1);
        // The time in the database is either 0 (repeating) or a specific time
        // for a non-repeating alarm. Update this value so the AlarmReceiver
        // has the right time to compare.
        alarm.time = time;

        return true;
    }

    /**
     * Tells the StatusBar whether the alarm is enabled or disabled
     */
@@ -589,11 +555,6 @@ public class Alarms {
        context.sendBroadcast(alarmChanged);
    }

    private static long calculateAlarm(Alarm alarm) {
        return calculateAlarm(alarm.hour, alarm.minutes, alarm.daysOfWeek)
                .getTimeInMillis();
    }

    /**
     * Given an alarm in hours and minutes, return a time suitable for
     * setting in AlarmManager.
@@ -609,8 +570,8 @@ public class Alarms {
        int nowMinute = c.get(Calendar.MINUTE);

        // if alarm is behind current time, advance one day
        if (hour < nowHour  ||
            hour == nowHour && minute <= nowMinute) {
        if (daysOfWeek.isRepeatSet() &&
                (hour < nowHour  || (hour == nowHour && minute <= nowMinute))) {
            c.add(Calendar.DAY_OF_YEAR, 1);
        }
        c.set(Calendar.HOUR_OF_DAY, hour);