summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorSara Ting <sarating@google.com>2012-05-25 10:26:49 -0700
committerSara Ting <sarating@google.com>2012-08-10 16:33:26 -0700
commit487d52c2789114e0ee3e7ce85694611b8d59dd70 (patch)
tree235b8a2bd32ef72f45ca1ae3013f3809d4fecf2e /src
parenta6ff5f0570e63e46a085bc82dc4256517e248f88 (diff)
downloadandroid_packages_apps_Calendar-487d52c2789114e0ee3e7ce85694611b8d59dd70.tar.gz
android_packages_apps_Calendar-487d52c2789114e0ee3e7ce85694611b8d59dd70.tar.bz2
android_packages_apps_Calendar-487d52c2789114e0ee3e7ce85694611b8d59dd70.zip
Notifications: made alarm scheduling testable, and a couple minor fixes.
- Added tests for scheduling next notification refresh time - Fixed priority of single expired event notifications (fixed from DEFAULT to MIN) - Fixed automatic demoting of allday events (refresh time wasn't correct) Bug:6282451 Change-Id: I160736827fc0b1017e2d001cb0fdb8f7d0502339
Diffstat (limited to 'src')
-rw-r--r--src/com/android/calendar/alerts/AlarmManagerInterface.java10
-rw-r--r--src/com/android/calendar/alerts/AlertActivity.java14
-rw-r--r--src/com/android/calendar/alerts/AlertReceiver.java22
-rw-r--r--src/com/android/calendar/alerts/AlertService.java67
-rw-r--r--src/com/android/calendar/alerts/AlertUtils.java27
5 files changed, 79 insertions, 61 deletions
diff --git a/src/com/android/calendar/alerts/AlarmManagerInterface.java b/src/com/android/calendar/alerts/AlarmManagerInterface.java
new file mode 100644
index 00000000..5ee83734
--- /dev/null
+++ b/src/com/android/calendar/alerts/AlarmManagerInterface.java
@@ -0,0 +1,10 @@
+package com.android.calendar.alerts;
+
+import android.app.PendingIntent;
+
+/**
+ * AlarmManager abstracted to an interface for testability.
+ */
+public interface AlarmManagerInterface {
+ public void set(int type, long triggerAtMillis, PendingIntent operation);
+}
diff --git a/src/com/android/calendar/alerts/AlertActivity.java b/src/com/android/calendar/alerts/AlertActivity.java
index d22408fd..12d7b10a 100644
--- a/src/com/android/calendar/alerts/AlertActivity.java
+++ b/src/com/android/calendar/alerts/AlertActivity.java
@@ -124,20 +124,6 @@ public class AlertActivity extends Activity implements OnClickListener {
}
@Override
- protected void onInsertComplete(int token, Object cookie, Uri uri) {
- if (uri != null) {
- Long alarmTime = (Long) cookie;
-
- if (alarmTime != 0) {
- // Set a new alarm to go off after the snooze delay.
- // TODO make provider schedule this automatically when
- // inserting an alarm
- AlertUtils.scheduleAlarm(AlertActivity.this, null, alarmTime);
- }
- }
- }
-
- @Override
protected void onUpdateComplete(int token, Object cookie, int result) {
// Ignore
}
diff --git a/src/com/android/calendar/alerts/AlertReceiver.java b/src/com/android/calendar/alerts/AlertReceiver.java
index 16c42b50..1991a4d1 100644
--- a/src/com/android/calendar/alerts/AlertReceiver.java
+++ b/src/com/android/calendar/alerts/AlertReceiver.java
@@ -219,16 +219,16 @@ public class AlertReceiver extends BroadcastReceiver {
public static NotificationWrapper makeBasicNotification(Context context, String title,
String summaryText, long startMillis, long endMillis, long eventId,
- int notificationId, boolean doPopup) {
+ int notificationId, boolean doPopup, int priority) {
Notification n = buildBasicNotification(new Notification.Builder(context),
context, title, summaryText, startMillis, endMillis, eventId, notificationId,
- doPopup, false, false);
+ doPopup, priority, false);
return new NotificationWrapper(n, notificationId, eventId, startMillis, endMillis, doPopup);
}
private static Notification buildBasicNotification(Notification.Builder notificationBuilder,
Context context, String title, String summaryText, long startMillis, long endMillis,
- long eventId, int notificationId, boolean doPopup, boolean highPriority,
+ long eventId, int notificationId, boolean doPopup, int priority,
boolean addActionButtons) {
Resources resources = context.getResources();
if (title == null || title.length() == 0) {
@@ -256,15 +256,11 @@ public class AlertReceiver extends BroadcastReceiver {
// Turn off timestamp.
notificationBuilder.setWhen(0);
-
+
if (Utils.isJellybeanOrLater()) {
- // Setting to a higher priority will encourage notification manager to expand the
- // notification.
- if (highPriority) {
- notificationBuilder.setPriority(Notification.PRIORITY_HIGH);
- } else {
- notificationBuilder.setPriority(Notification.PRIORITY_DEFAULT);
- }
+ // Should be one of the values in Notification (ie. Notification.PRIORITY_HIGH, etc).
+ // A higher priority will encourage notification manager to expand it.
+ notificationBuilder.setPriority(priority);
}
if (addActionButtons) {
@@ -313,11 +309,11 @@ public class AlertReceiver extends BroadcastReceiver {
*/
public static NotificationWrapper makeExpandingNotification(Context context, String title,
String summaryText, String description, long startMillis, long endMillis, long eventId,
- int notificationId, boolean doPopup, boolean highPriority) {
+ int notificationId, boolean doPopup, int priority) {
Notification.Builder basicBuilder = new Notification.Builder(context);
Notification notification = buildBasicNotification(basicBuilder, context, title,
summaryText, startMillis, endMillis, eventId, notificationId, doPopup,
- highPriority, true);
+ priority, true);
if (Utils.isJellybeanOrLater()) {
// Create a new-style expanded notification
Notification.BigTextStyle expandedBuilder = new Notification.BigTextStyle(
diff --git a/src/com/android/calendar/alerts/AlertService.java b/src/com/android/calendar/alerts/AlertService.java
index 8a4563e5..15986af6 100644
--- a/src/com/android/calendar/alerts/AlertService.java
+++ b/src/com/android/calendar/alerts/AlertService.java
@@ -16,7 +16,6 @@
package com.android.calendar.alerts;
-import android.app.AlarmManager;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.Service;
@@ -248,12 +247,13 @@ public class AlertService extends Service {
return false;
}
- return generateAlerts(context, nm, prefs, alertCursor, currentTime, MAX_NOTIFICATIONS);
+ return generateAlerts(context, nm, AlertUtils.createAlarmManager(context), prefs,
+ alertCursor, currentTime, MAX_NOTIFICATIONS);
}
public static boolean generateAlerts(Context context, NotificationMgr nm,
- SharedPreferences prefs, Cursor alertCursor, final long currentTime,
- final int maxNotifications) {
+ AlarmManagerInterface alarmMgr, SharedPreferences prefs, Cursor alertCursor,
+ final long currentTime, final int maxNotifications) {
if (DEBUG) {
Log.d(TAG, "alertCursor count:" + alertCursor.getCount());
}
@@ -326,7 +326,8 @@ public class AlertService extends Service {
info.allDay, info.location);
notification = AlertReceiver.makeBasicNotification(context, info.eventName,
summaryText, info.startMillis, info.endMillis, info.eventId,
- AlertUtils.EXPIRED_GROUP_NOTIFICATION_ID, false);
+ AlertUtils.EXPIRED_GROUP_NOTIFICATION_ID, false,
+ Notification.PRIORITY_MIN);
} else {
// Multiple expired events are listed in a digest.
notification = AlertReceiver.makeDigestNotification(context,
@@ -366,7 +367,7 @@ public class AlertService extends Service {
// Schedule the next silent refresh time so notifications will change
// buckets (eg. drop into expired digest, etc).
if (nextRefreshTime < Long.MAX_VALUE && nextRefreshTime > currentTime) {
- AlertUtils.scheduleNextNotificationRefresh(context, null, nextRefreshTime);
+ AlertUtils.scheduleNextNotificationRefresh(context, alarmMgr, nextRefreshTime);
if (DEBUG) {
long minutesBeforeRefresh = (nextRefreshTime - currentTime) / MINUTE_MS;
Time time = new Time();
@@ -455,18 +456,27 @@ public class AlertService extends Service {
}
private static long getNextRefreshTime(NotificationInfo info, long currentTime) {
- // We change an event's priority bucket at 15 minutes into the event (so recently started
- // concurrent events stay high priority)
+ long startAdjustedForAllDay = info.startMillis;
+ long endAdjustedForAllDay = info.endMillis;
+ if (info.allDay) {
+ Time t = new Time();
+ startAdjustedForAllDay = Utils.convertAlldayUtcToLocal(t, info.startMillis,
+ Time.getCurrentTimezone());
+ endAdjustedForAllDay = Utils.convertAlldayUtcToLocal(t, info.startMillis,
+ Time.getCurrentTimezone());
+ }
+
+ // We change an event's priority bucket at 15 minutes into the event or 1/4 event duration.
long nextRefreshTime = Long.MAX_VALUE;
- long gracePeriodCutoff = info.startMillis +
- getGracePeriodMs(info.startMillis, info.endMillis);
+ long gracePeriodCutoff = startAdjustedForAllDay +
+ getGracePeriodMs(startAdjustedForAllDay, endAdjustedForAllDay, info.allDay);
if (gracePeriodCutoff > currentTime) {
nextRefreshTime = Math.min(nextRefreshTime, gracePeriodCutoff);
}
// ... and at the end (so expiring ones drop into a digest).
- if (info.endMillis > currentTime && info.endMillis > gracePeriodCutoff) {
- nextRefreshTime = Math.min(nextRefreshTime, info.endMillis);
+ if (endAdjustedForAllDay > currentTime && endAdjustedForAllDay > gracePeriodCutoff) {
+ nextRefreshTime = Math.min(nextRefreshTime, endAdjustedForAllDay);
}
return nextRefreshTime;
}
@@ -578,16 +588,12 @@ public class AlertService extends Service {
// Adjust for all day events to ensure the right bucket. Don't use the 1/4 event
// duration grace period for these.
- long gracePeriodMs;
long beginTimeAdjustedForAllDay = beginTime;
String tz = null;
if (allDay) {
tz = TimeZone.getDefault().getID();
beginTimeAdjustedForAllDay = Utils.convertAlldayUtcToLocal(null, beginTime,
tz);
- gracePeriodMs = MIN_DEPRIORITIZE_GRACE_PERIOD_MS;
- } else {
- gracePeriodMs = getGracePeriodMs(beginTime, endTime);
}
// Handle multiple alerts for the same event ID.
@@ -636,7 +642,8 @@ public class AlertService extends Service {
// TODO: Prioritize by "primary" calendar
eventIds.put(eventId, newInfo);
- long highPriorityCutoff = currentTime - gracePeriodMs;
+ long highPriorityCutoff = currentTime -
+ getGracePeriodMs(beginTime, endTime, allDay);
if (beginTimeAdjustedForAllDay > highPriorityCutoff) {
// High priority = future events or events that just started
@@ -659,8 +666,14 @@ public class AlertService extends Service {
/**
* High priority cutoff should be 1/4 event duration or 15 min, whichever is longer.
*/
- private static long getGracePeriodMs(long beginTime, long endTime) {
- return Math.max(MIN_DEPRIORITIZE_GRACE_PERIOD_MS, ((endTime - beginTime) / 4));
+ private static long getGracePeriodMs(long beginTime, long endTime, boolean allDay) {
+ if (allDay) {
+ // We don't want all day events to be high priority for hours, so automatically
+ // demote these after 15 min.
+ return MIN_DEPRIORITIZE_GRACE_PERIOD_MS;
+ } else {
+ return Math.max(MIN_DEPRIORITIZE_GRACE_PERIOD_MS, ((endTime - beginTime) / 4));
+ }
}
private static String getDigestTitle(ArrayList<NotificationInfo> events) {
@@ -679,11 +692,15 @@ public class AlertService extends Service {
private static void postNotification(NotificationInfo info, String summaryText,
Context context, boolean highPriority, NotificationPrefs prefs,
NotificationMgr notificationMgr, int notificationId) {
+ int priorityVal = Notification.PRIORITY_DEFAULT;
+ if (highPriority) {
+ priorityVal = Notification.PRIORITY_HIGH;
+ }
+
String tickerText = getTickerText(info.eventName, info.location);
NotificationWrapper notification = AlertReceiver.makeExpandingNotification(context,
info.eventName, summaryText, info.description, info.startMillis,
- info.endMillis, info.eventId, notificationId, prefs.getDoPopup(),
- highPriority);
+ info.endMillis, info.eventId, notificationId, prefs.getDoPopup(), priorityVal);
boolean quietUpdate = true;
String ringtone = NotificationPrefs.EMPTY_RINGTONE;
@@ -851,10 +868,8 @@ public class AlertService extends Service {
private void doTimeChanged() {
ContentResolver cr = getContentResolver();
- Object service = getSystemService(Context.ALARM_SERVICE);
- AlarmManager manager = (AlarmManager) service;
// TODO Move this into Provider
- rescheduleMissedAlarms(cr, this, manager);
+ rescheduleMissedAlarms(cr, this, AlertUtils.createAlarmManager(this));
updateAlertNotification(this);
}
@@ -883,8 +898,8 @@ public class AlertService extends Service {
* @param context the Context
* @param manager the AlarmManager
*/
- public static final void rescheduleMissedAlarms(ContentResolver cr, Context context,
- AlarmManager manager) {
+ private static final void rescheduleMissedAlarms(ContentResolver cr, Context context,
+ AlarmManagerInterface manager) {
// Get all the alerts that have been scheduled but have not fired
// and should have fired by now and are not too old.
long now = System.currentTimeMillis();
diff --git a/src/com/android/calendar/alerts/AlertUtils.java b/src/com/android/calendar/alerts/AlertUtils.java
index 1777a2d4..cb5a33ca 100644
--- a/src/com/android/calendar/alerts/AlertUtils.java
+++ b/src/com/android/calendar/alerts/AlertUtils.java
@@ -53,6 +53,20 @@ public class AlertUtils {
public static final String EVENT_IDS_KEY = "eventids";
/**
+ * Creates an AlarmManagerInterface that wraps a real AlarmManager. The alarm code
+ * was abstracted to an interface to make it testable.
+ */
+ public static AlarmManagerInterface createAlarmManager(Context context) {
+ final AlarmManager mgr = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
+ return new AlarmManagerInterface() {
+ @Override
+ public void set(int type, long triggerAtMillis, PendingIntent operation) {
+ mgr.set(type, triggerAtMillis, operation);
+ }
+ };
+ }
+
+ /**
* Schedules an alarm intent with the system AlarmManager that will notify
* listeners when a reminder should be fired. The provider will keep
* scheduled reminders up to date but apps may use this to implement snooze
@@ -63,7 +77,8 @@ public class AlertUtils {
* @param manager The AlarmManager to use or null
* @param alarmTime The time to fire the intent in UTC millis since epoch
*/
- public static void scheduleAlarm(Context context, AlarmManager manager, long alarmTime) {
+ public static void scheduleAlarm(Context context, AlarmManagerInterface manager,
+ long alarmTime) {
scheduleAlarmHelper(context, manager, alarmTime, false);
}
@@ -71,17 +86,13 @@ public class AlertUtils {
* Schedules the next alarm to silently refresh the notifications. Note that if there
* is a pending silent refresh alarm, it will be replaced with this one.
*/
- static void scheduleNextNotificationRefresh(Context context, AlarmManager manager,
+ static void scheduleNextNotificationRefresh(Context context, AlarmManagerInterface manager,
long alarmTime) {
scheduleAlarmHelper(context, manager, alarmTime, true);
}
- private static void scheduleAlarmHelper(Context context, AlarmManager manager, long alarmTime,
- boolean quietUpdate) {
- if (manager == null) {
- manager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
- }
-
+ private static void scheduleAlarmHelper(Context context, AlarmManagerInterface manager,
+ long alarmTime, boolean quietUpdate) {
int alarmType = AlarmManager.RTC_WAKEUP;
Intent intent = new Intent(CalendarContract.ACTION_EVENT_REMINDER);
intent.setClass(context, AlertReceiver.class);