blob: 73414c5f9c2fad5caf4967de40a9b9981cb65b29 [file] [log] [blame]
/*
* 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 +
'}';
}
}
}