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