OSDN Git Service

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