| /* |
| * Copyright (C) 2009 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package com.android.deskclock; |
| |
| import android.content.Context; |
| import android.database.Cursor; |
| import android.media.RingtoneManager; |
| import android.net.Uri; |
| import android.os.Parcel; |
| import android.os.Parcelable; |
| import android.provider.BaseColumns; |
| |
| import java.text.DateFormatSymbols; |
| import java.util.Calendar; |
| import java.util.HashMap; |
| import java.util.HashSet; |
| |
| public final class Alarm implements Parcelable { |
| |
| ////////////////////////////// |
| // Parcelable apis |
| ////////////////////////////// |
| public static final Parcelable.Creator<Alarm> CREATOR |
| = new Parcelable.Creator<Alarm>() { |
| public Alarm createFromParcel(Parcel p) { |
| return new Alarm(p); |
| } |
| |
| public Alarm[] newArray(int size) { |
| return new Alarm[size]; |
| } |
| }; |
| |
| public int describeContents() { |
| return 0; |
| } |
| |
| public void writeToParcel(Parcel p, int flags) { |
| p.writeInt(id); |
| p.writeInt(enabled ? 1 : 0); |
| p.writeInt(hour); |
| p.writeInt(minutes); |
| p.writeInt(daysOfWeek.getCoded()); |
| p.writeLong(time); |
| p.writeInt(vibrate ? 1 : 0); |
| p.writeString(label); |
| p.writeParcelable(alert, flags); |
| p.writeInt(silent ? 1 : 0); |
| } |
| ////////////////////////////// |
| // end Parcelable apis |
| ////////////////////////////// |
| |
| ////////////////////////////// |
| // Column definitions |
| ////////////////////////////// |
| public static class Columns implements BaseColumns { |
| /** |
| * The content:// style URL for this table |
| */ |
| public static final Uri CONTENT_URI = |
| Uri.parse("content://com.android.deskclock/alarm"); |
| |
| /** |
| * Hour in 24-hour localtime 0 - 23. |
| * <P>Type: INTEGER</P> |
| */ |
| public static final String HOUR = "hour"; |
| |
| /** |
| * Minutes in localtime 0 - 59 |
| * <P>Type: INTEGER</P> |
| */ |
| public static final String MINUTES = "minutes"; |
| |
| /** |
| * Days of week coded as integer |
| * <P>Type: INTEGER</P> |
| */ |
| public static final String DAYS_OF_WEEK = "daysofweek"; |
| |
| /** |
| * Alarm time in UTC milliseconds from the epoch. |
| * <P>Type: INTEGER</P> |
| */ |
| public static final String ALARM_TIME = "alarmtime"; |
| |
| /** |
| * True if alarm is active |
| * <P>Type: BOOLEAN</P> |
| */ |
| public static final String ENABLED = "enabled"; |
| |
| /** |
| * True if alarm should vibrate |
| * <P>Type: BOOLEAN</P> |
| */ |
| public static final String VIBRATE = "vibrate"; |
| |
| /** |
| * Message to show when alarm triggers |
| * Note: not currently used |
| * <P>Type: STRING</P> |
| */ |
| public static final String MESSAGE = "message"; |
| |
| /** |
| * Audio alert to play when alarm triggers |
| * <P>Type: STRING</P> |
| */ |
| public static final String ALERT = "alert"; |
| |
| /** |
| * The default sort order for this table |
| */ |
| public static final String DEFAULT_SORT_ORDER = |
| HOUR + ", " + MINUTES + " ASC" + ", " + _ID + " DESC"; |
| |
| // Used when filtering enabled alarms. |
| public static final String WHERE_ENABLED = ENABLED + "=1"; |
| |
| static final String[] ALARM_QUERY_COLUMNS = { |
| _ID, HOUR, MINUTES, DAYS_OF_WEEK, ALARM_TIME, |
| ENABLED, VIBRATE, MESSAGE, ALERT }; |
| |
| /** |
| * These save calls to cursor.getColumnIndexOrThrow() |
| * THEY MUST BE KEPT IN SYNC WITH ABOVE QUERY COLUMNS |
| */ |
| public static final int ALARM_ID_INDEX = 0; |
| 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; |
| public static final int ALARM_ENABLED_INDEX = 5; |
| public static final int ALARM_VIBRATE_INDEX = 6; |
| public static final int ALARM_MESSAGE_INDEX = 7; |
| public static final int ALARM_ALERT_INDEX = 8; |
| } |
| ////////////////////////////// |
| // End column definitions |
| ////////////////////////////// |
| |
| // Public fields |
| public int id; |
| public boolean enabled; |
| public int hour; |
| public int minutes; |
| public DaysOfWeek daysOfWeek; |
| public long time; |
| public boolean vibrate; |
| public String label; |
| public Uri alert; |
| public boolean silent; |
| |
| @Override |
| public String toString() { |
| return "Alarm{" + |
| "alert=" + alert + |
| ", id=" + id + |
| ", enabled=" + enabled + |
| ", hour=" + hour + |
| ", minutes=" + minutes + |
| ", daysOfWeek=" + daysOfWeek + |
| ", time=" + time + |
| ", vibrate=" + vibrate + |
| ", label='" + label + '\'' + |
| ", silent=" + silent + |
| '}'; |
| } |
| |
| public Alarm(Cursor c) { |
| id = c.getInt(Columns.ALARM_ID_INDEX); |
| enabled = c.getInt(Columns.ALARM_ENABLED_INDEX) == 1; |
| 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); |
| if (Alarms.ALARM_ALERT_SILENT.equals(alertString)) { |
| if (Log.LOGV) { |
| Log.v("Alarm is marked as silent"); |
| } |
| silent = true; |
| } else { |
| if (alertString != null && alertString.length() != 0) { |
| alert = Uri.parse(alertString); |
| } |
| |
| // If the database alert is null or it failed to parse, use the |
| // default alert. |
| if (alert == null) { |
| alert = RingtoneManager.getDefaultUri( |
| RingtoneManager.TYPE_ALARM); |
| } |
| } |
| } |
| |
| public Alarm(Parcel p) { |
| id = p.readInt(); |
| enabled = p.readInt() == 1; |
| hour = p.readInt(); |
| minutes = p.readInt(); |
| daysOfWeek = new DaysOfWeek(p.readInt()); |
| time = p.readLong(); |
| vibrate = p.readInt() == 1; |
| label = p.readString(); |
| alert = (Uri) p.readParcelable(null); |
| silent = p.readInt() == 1; |
| } |
| |
| // Creates a default alarm at the current time. |
| public Alarm() { |
| id = -1; |
| hour = 0; |
| minutes = 0; |
| vibrate = true; |
| daysOfWeek = new DaysOfWeek(0); |
| label = ""; |
| alert = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_ALARM); |
| } |
| |
| public String getLabelOrDefault(Context context) { |
| if (label == null || label.length() == 0) { |
| return context.getString(R.string.default_label); |
| } |
| return label; |
| } |
| |
| @Override |
| public int hashCode() { |
| return id; |
| } |
| |
| @Override |
| public boolean equals(Object o) { |
| if (!(o instanceof Alarm)) return false; |
| final Alarm other = (Alarm) o; |
| return id == other.id; |
| } |
| |
| |
| /* |
| * Days of week code as a single int. |
| * 0x00: no day |
| * 0x01: Monday |
| * 0x02: Tuesday |
| * 0x04: Wednesday |
| * 0x08: Thursday |
| * 0x10: Friday |
| * 0x20: Saturday |
| * 0x40: Sunday |
| */ |
| static final class DaysOfWeek { |
| |
| private static int[] DAY_MAP = new int[] { |
| Calendar.MONDAY, |
| Calendar.TUESDAY, |
| Calendar.WEDNESDAY, |
| Calendar.THURSDAY, |
| Calendar.FRIDAY, |
| Calendar.SATURDAY, |
| Calendar.SUNDAY, |
| }; |
| |
| |
| private static HashMap<Integer, Integer> DAY_TO_BIT_MASK = new HashMap<Integer, Integer>(); |
| static { |
| for (int i = 0; i < DAY_MAP.length; i++) { |
| DAY_TO_BIT_MASK.put(DAY_MAP[i], i); |
| } |
| } |
| |
| // Bitmask of all repeating days |
| private int mDays; |
| |
| DaysOfWeek(int days) { |
| mDays = days; |
| } |
| |
| public String toString(Context context, boolean showNever) { |
| return toString(context, showNever, false); |
| } |
| |
| public String toAccessibilityString(Context context) { |
| return toString(context, false, true); |
| } |
| |
| private String toString(Context context, boolean showNever, boolean forAccessibility) { |
| StringBuilder ret = new StringBuilder(); |
| |
| // no days |
| if (mDays == 0) { |
| return showNever ? |
| context.getText(R.string.never).toString() : ""; |
| } |
| |
| // every day |
| if (mDays == 0x7f) { |
| return context.getText(R.string.every_day).toString(); |
| } |
| |
| // count selected days |
| int dayCount = 0, days = mDays; |
| while (days > 0) { |
| if ((days & 1) == 1) dayCount++; |
| days >>= 1; |
| } |
| |
| // short or long form? |
| DateFormatSymbols dfs = new DateFormatSymbols(); |
| String[] dayList = (forAccessibility || dayCount <= 1) ? |
| dfs.getWeekdays() : |
| dfs.getShortWeekdays(); |
| |
| // selected days |
| for (int i = 0; i < 7; i++) { |
| if ((mDays & (1 << i)) != 0) { |
| ret.append(dayList[DAY_MAP[i]]); |
| dayCount -= 1; |
| if (dayCount > 0) ret.append( |
| context.getText(R.string.day_concat)); |
| } |
| } |
| return ret.toString(); |
| } |
| |
| private boolean isSet(int day) { |
| return ((mDays & (1 << day)) > 0); |
| } |
| |
| /** |
| * Sets the repeat day for the alarm. |
| * |
| * @param dayOfWeek One of: Calendar.SUNDAY, Calendar.MONDAY, Calendar.TUESDAY, etc. |
| * @param set Whether to set or unset. |
| */ |
| public void setDayOfWeek(int dayOfWeek, boolean set) { |
| final int bitIndex = DAY_TO_BIT_MASK.get(dayOfWeek); |
| set(bitIndex, set); |
| } |
| |
| public void set(int day, boolean set) { |
| if (set) { |
| mDays |= (1 << day); |
| } else { |
| mDays &= ~(1 << day); |
| } |
| } |
| |
| public void set(DaysOfWeek dow) { |
| mDays = dow.mDays; |
| } |
| |
| public int getCoded() { |
| return mDays; |
| } |
| |
| public HashSet<Integer> getSetDays() { |
| final HashSet<Integer> set = new HashSet<Integer>(); |
| for (int i = 0; i < 7; i++) { |
| if (isSet(i)) { |
| set.add(DAY_MAP[i]); |
| } |
| } |
| return set; |
| } |
| |
| // Returns days of week encoded in an array of booleans. |
| public boolean[] getBooleanArray() { |
| boolean[] ret = new boolean[7]; |
| for (int i = 0; i < 7; i++) { |
| ret[i] = isSet(i); |
| } |
| return ret; |
| } |
| |
| public boolean isRepeatSet() { |
| return mDays != 0; |
| } |
| |
| /** |
| * returns number of days from today until next alarm |
| * @param c must be set to today |
| */ |
| public int getNextAlarm(Calendar c) { |
| if (mDays == 0) { |
| return -1; |
| } |
| |
| int today = (c.get(Calendar.DAY_OF_WEEK) + 5) % 7; |
| |
| int day = 0; |
| int dayCount = 0; |
| for (; dayCount < 7; dayCount++) { |
| day = (today + dayCount) % 7; |
| if (isSet(day)) { |
| break; |
| } |
| } |
| return dayCount; |
| } |
| |
| @Override |
| public String toString() { |
| return "DaysOfWeek{" + |
| "mDays=" + mDays + |
| '}'; |
| } |
| } |
| } |