• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2009 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.deskclock;
18 
19 import android.content.Context;
20 import android.database.Cursor;
21 import android.media.RingtoneManager;
22 import android.net.Uri;
23 import android.os.Parcel;
24 import android.os.Parcelable;
25 import android.provider.BaseColumns;
26 
27 import java.text.DateFormatSymbols;
28 import java.util.Calendar;
29 
30 public final class Alarm implements Parcelable {
31 
32     //////////////////////////////
33     // Parcelable apis
34     //////////////////////////////
35     public static final Parcelable.Creator<Alarm> CREATOR
36             = new Parcelable.Creator<Alarm>() {
37                 public Alarm createFromParcel(Parcel p) {
38                     return new Alarm(p);
39                 }
40 
41                 public Alarm[] newArray(int size) {
42                     return new Alarm[size];
43                 }
44             };
45 
describeContents()46     public int describeContents() {
47         return 0;
48     }
49 
writeToParcel(Parcel p, int flags)50     public void writeToParcel(Parcel p, int flags) {
51         p.writeInt(id);
52         p.writeInt(enabled ? 1 : 0);
53         p.writeInt(hour);
54         p.writeInt(minutes);
55         p.writeInt(daysOfWeek.getCoded());
56         p.writeLong(time);
57         p.writeInt(vibrate ? 1 : 0);
58         p.writeString(label);
59         p.writeParcelable(alert, flags);
60         p.writeInt(silent ? 1 : 0);
61     }
62     //////////////////////////////
63     // end Parcelable apis
64     //////////////////////////////
65 
66     //////////////////////////////
67     // Column definitions
68     //////////////////////////////
69     public static class Columns implements BaseColumns {
70         /**
71          * The content:// style URL for this table
72          */
73         public static final Uri CONTENT_URI =
74                 Uri.parse("content://com.android.deskclock/alarm");
75 
76         /**
77          * Hour in 24-hour localtime 0 - 23.
78          * <P>Type: INTEGER</P>
79          */
80         public static final String HOUR = "hour";
81 
82         /**
83          * Minutes in localtime 0 - 59
84          * <P>Type: INTEGER</P>
85          */
86         public static final String MINUTES = "minutes";
87 
88         /**
89          * Days of week coded as integer
90          * <P>Type: INTEGER</P>
91          */
92         public static final String DAYS_OF_WEEK = "daysofweek";
93 
94         /**
95          * Alarm time in UTC milliseconds from the epoch.
96          * <P>Type: INTEGER</P>
97          */
98         public static final String ALARM_TIME = "alarmtime";
99 
100         /**
101          * True if alarm is active
102          * <P>Type: BOOLEAN</P>
103          */
104         public static final String ENABLED = "enabled";
105 
106         /**
107          * True if alarm should vibrate
108          * <P>Type: BOOLEAN</P>
109          */
110         public static final String VIBRATE = "vibrate";
111 
112         /**
113          * Message to show when alarm triggers
114          * Note: not currently used
115          * <P>Type: STRING</P>
116          */
117         public static final String MESSAGE = "message";
118 
119         /**
120          * Audio alert to play when alarm triggers
121          * <P>Type: STRING</P>
122          */
123         public static final String ALERT = "alert";
124 
125         /**
126          * The default sort order for this table
127          */
128         public static final String DEFAULT_SORT_ORDER =
129                 HOUR + ", " + MINUTES + " ASC";
130 
131         // Used when filtering enabled alarms.
132         public static final String WHERE_ENABLED = ENABLED + "=1";
133 
134         static final String[] ALARM_QUERY_COLUMNS = {
135             _ID, HOUR, MINUTES, DAYS_OF_WEEK, ALARM_TIME,
136             ENABLED, VIBRATE, MESSAGE, ALERT };
137 
138         /**
139          * These save calls to cursor.getColumnIndexOrThrow()
140          * THEY MUST BE KEPT IN SYNC WITH ABOVE QUERY COLUMNS
141          */
142         public static final int ALARM_ID_INDEX = 0;
143         public static final int ALARM_HOUR_INDEX = 1;
144         public static final int ALARM_MINUTES_INDEX = 2;
145         public static final int ALARM_DAYS_OF_WEEK_INDEX = 3;
146         public static final int ALARM_TIME_INDEX = 4;
147         public static final int ALARM_ENABLED_INDEX = 5;
148         public static final int ALARM_VIBRATE_INDEX = 6;
149         public static final int ALARM_MESSAGE_INDEX = 7;
150         public static final int ALARM_ALERT_INDEX = 8;
151     }
152     //////////////////////////////
153     // End column definitions
154     //////////////////////////////
155 
156     // Public fields
157     public int        id;
158     public boolean    enabled;
159     public int        hour;
160     public int        minutes;
161     public DaysOfWeek daysOfWeek;
162     public long       time;
163     public boolean    vibrate;
164     public String     label;
165     public Uri        alert;
166     public boolean    silent;
167 
Alarm(Cursor c)168     public Alarm(Cursor c) {
169         id = c.getInt(Columns.ALARM_ID_INDEX);
170         enabled = c.getInt(Columns.ALARM_ENABLED_INDEX) == 1;
171         hour = c.getInt(Columns.ALARM_HOUR_INDEX);
172         minutes = c.getInt(Columns.ALARM_MINUTES_INDEX);
173         daysOfWeek = new DaysOfWeek(c.getInt(Columns.ALARM_DAYS_OF_WEEK_INDEX));
174         time = c.getLong(Columns.ALARM_TIME_INDEX);
175         vibrate = c.getInt(Columns.ALARM_VIBRATE_INDEX) == 1;
176         label = c.getString(Columns.ALARM_MESSAGE_INDEX);
177         String alertString = c.getString(Columns.ALARM_ALERT_INDEX);
178         if (Alarms.ALARM_ALERT_SILENT.equals(alertString)) {
179             if (Log.LOGV) {
180                 Log.v("Alarm is marked as silent");
181             }
182             silent = true;
183         } else {
184             if (alertString != null && alertString.length() != 0) {
185                 alert = Uri.parse(alertString);
186             }
187 
188             // If the database alert is null or it failed to parse, use the
189             // default alert.
190             if (alert == null) {
191                 alert = RingtoneManager.getDefaultUri(
192                         RingtoneManager.TYPE_ALARM);
193             }
194         }
195     }
196 
Alarm(Parcel p)197     public Alarm(Parcel p) {
198         id = p.readInt();
199         enabled = p.readInt() == 1;
200         hour = p.readInt();
201         minutes = p.readInt();
202         daysOfWeek = new DaysOfWeek(p.readInt());
203         time = p.readLong();
204         vibrate = p.readInt() == 1;
205         label = p.readString();
206         alert = (Uri) p.readParcelable(null);
207         silent = p.readInt() == 1;
208     }
209 
210     // Creates a default alarm at the current time.
Alarm()211     public Alarm() {
212         id = -1;
213         Calendar c = Calendar.getInstance();
214         c.setTimeInMillis(System.currentTimeMillis());
215         hour = c.get(Calendar.HOUR_OF_DAY);
216         minutes = c.get(Calendar.MINUTE);
217         vibrate = true;
218         daysOfWeek = new DaysOfWeek(0);
219         alert = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_ALARM);
220     }
221 
getLabelOrDefault(Context context)222     public String getLabelOrDefault(Context context) {
223         if (label == null || label.length() == 0) {
224             return context.getString(R.string.default_label);
225         }
226         return label;
227     }
228 
229     @Override
hashCode()230     public int hashCode() {
231         return id;
232     }
233 
234     @Override
equals(Object o)235     public boolean equals(Object o) {
236         if (!(o instanceof Alarm)) return false;
237         final Alarm other = (Alarm) o;
238         return id == other.id;
239     }
240 
241 
242     /*
243      * Days of week code as a single int.
244      * 0x00: no day
245      * 0x01: Monday
246      * 0x02: Tuesday
247      * 0x04: Wednesday
248      * 0x08: Thursday
249      * 0x10: Friday
250      * 0x20: Saturday
251      * 0x40: Sunday
252      */
253     static final class DaysOfWeek {
254 
255         private static int[] DAY_MAP = new int[] {
256             Calendar.MONDAY,
257             Calendar.TUESDAY,
258             Calendar.WEDNESDAY,
259             Calendar.THURSDAY,
260             Calendar.FRIDAY,
261             Calendar.SATURDAY,
262             Calendar.SUNDAY,
263         };
264 
265         // Bitmask of all repeating days
266         private int mDays;
267 
DaysOfWeek(int days)268         DaysOfWeek(int days) {
269             mDays = days;
270         }
271 
toString(Context context, boolean showNever)272         public String toString(Context context, boolean showNever) {
273             StringBuilder ret = new StringBuilder();
274 
275             // no days
276             if (mDays == 0) {
277                 return showNever ?
278                         context.getText(R.string.never).toString() : "";
279             }
280 
281             // every day
282             if (mDays == 0x7f) {
283                 return context.getText(R.string.every_day).toString();
284             }
285 
286             // count selected days
287             int dayCount = 0, days = mDays;
288             while (days > 0) {
289                 if ((days & 1) == 1) dayCount++;
290                 days >>= 1;
291             }
292 
293             // short or long form?
294             DateFormatSymbols dfs = new DateFormatSymbols();
295             String[] dayList = (dayCount > 1) ?
296                     dfs.getShortWeekdays() :
297                     dfs.getWeekdays();
298 
299             // selected days
300             for (int i = 0; i < 7; i++) {
301                 if ((mDays & (1 << i)) != 0) {
302                     ret.append(dayList[DAY_MAP[i]]);
303                     dayCount -= 1;
304                     if (dayCount > 0) ret.append(
305                             context.getText(R.string.day_concat));
306                 }
307             }
308             return ret.toString();
309         }
310 
isSet(int day)311         private boolean isSet(int day) {
312             return ((mDays & (1 << day)) > 0);
313         }
314 
set(int day, boolean set)315         public void set(int day, boolean set) {
316             if (set) {
317                 mDays |= (1 << day);
318             } else {
319                 mDays &= ~(1 << day);
320             }
321         }
322 
set(DaysOfWeek dow)323         public void set(DaysOfWeek dow) {
324             mDays = dow.mDays;
325         }
326 
getCoded()327         public int getCoded() {
328             return mDays;
329         }
330 
331         // Returns days of week encoded in an array of booleans.
getBooleanArray()332         public boolean[] getBooleanArray() {
333             boolean[] ret = new boolean[7];
334             for (int i = 0; i < 7; i++) {
335                 ret[i] = isSet(i);
336             }
337             return ret;
338         }
339 
isRepeatSet()340         public boolean isRepeatSet() {
341             return mDays != 0;
342         }
343 
344         /**
345          * returns number of days from today until next alarm
346          * @param c must be set to today
347          */
getNextAlarm(Calendar c)348         public int getNextAlarm(Calendar c) {
349             if (mDays == 0) {
350                 return -1;
351             }
352 
353             int today = (c.get(Calendar.DAY_OF_WEEK) + 5) % 7;
354 
355             int day = 0;
356             int dayCount = 0;
357             for (; dayCount < 7; dayCount++) {
358                 day = (today + dayCount) % 7;
359                 if (isSet(day)) {
360                     break;
361                 }
362             }
363             return dayCount;
364         }
365     }
366 }
367