summaryrefslogtreecommitdiffstats
path: root/src/com/android/calendar/alerts/AlertUtils.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/com/android/calendar/alerts/AlertUtils.java')
-rw-r--r--src/com/android/calendar/alerts/AlertUtils.java125
1 files changed, 125 insertions, 0 deletions
diff --git a/src/com/android/calendar/alerts/AlertUtils.java b/src/com/android/calendar/alerts/AlertUtils.java
index cb5a33ca..f68f5224 100644
--- a/src/com/android/calendar/alerts/AlertUtils.java
+++ b/src/com/android/calendar/alerts/AlertUtils.java
@@ -22,6 +22,7 @@ import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
+import android.content.SharedPreferences;
import android.net.Uri;
import android.provider.CalendarContract;
import android.provider.CalendarContract.CalendarAlerts;
@@ -29,15 +30,19 @@ import android.text.TextUtils;
import android.text.format.DateFormat;
import android.text.format.DateUtils;
import android.text.format.Time;
+import android.util.Log;
import com.android.calendar.EventInfoActivity;
import com.android.calendar.R;
import com.android.calendar.Utils;
import java.util.Locale;
+import java.util.Map;
import java.util.TimeZone;
public class AlertUtils {
+ private static final String TAG = "AlertUtils";
+ static final boolean DEBUG = true;
public static final long SNOOZE_DELAY = 5 * 60 * 1000L;
@@ -52,6 +57,28 @@ public class AlertUtils {
public static final String NOTIFICATION_ID_KEY = "notificationid";
public static final String EVENT_IDS_KEY = "eventids";
+ // A flag for using local storage to save alert state instead of the alerts DB table.
+ // This allows the unbundled app to run alongside other calendar apps without eating
+ // alerts from other apps.
+ static boolean BYPASS_DB = true;
+
+ // SharedPrefs table name for storing fired alerts. This prevents other installed
+ // Calendar apps from eating the alerts.
+ private static final String ALERTS_SHARED_PREFS_NAME = "calendar_alerts";
+
+ // Keyname prefix for the alerts data in SharedPrefs. The key will contain a combo
+ // of event ID, begin time, and alarm time. The value will be the fired time.
+ private static final String KEY_FIRED_ALERT_PREFIX = "preference_alert_";
+
+ // The last time the SharedPrefs was scanned and flushed of old alerts data.
+ private static final String KEY_LAST_FLUSH_TIME_MS = "preference_flushTimeMs";
+
+ // The # of days to save alert states in the shared prefs table, before flushing. This
+ // can be any value, since AlertService will also check for a recent alertTime before
+ // ringing the alert.
+ private static final int FLUSH_INTERVAL_DAYS = 1;
+ private static final int FLUSH_INTERVAL_MS = FLUSH_INTERVAL_DAYS * 24 * 60 * 60 * 1000;
+
/**
* Creates an AlarmManagerInterface that wraps a real AlarmManager. The alarm code
* was abstracted to an interface to make it testable.
@@ -195,4 +222,102 @@ public class AlertUtils {
return i;
}
+ public static SharedPreferences getFiredAlertsTable(Context context) {
+ return context.getSharedPreferences(ALERTS_SHARED_PREFS_NAME, Context.MODE_PRIVATE);
+ }
+
+ private static String getFiredAlertsKey(long eventId, long beginTime,
+ long alarmTime) {
+ StringBuilder sb = new StringBuilder(KEY_FIRED_ALERT_PREFIX);
+ sb.append(eventId);
+ sb.append("_");
+ sb.append(beginTime);
+ sb.append("_");
+ sb.append(alarmTime);
+ return sb.toString();
+ }
+
+ /**
+ * Returns whether the SharedPrefs storage indicates we have fired the alert before.
+ */
+ static boolean hasAlertFiredInSharedPrefs(Context context, long eventId, long beginTime,
+ long alarmTime) {
+ SharedPreferences prefs = getFiredAlertsTable(context);
+ return prefs.contains(getFiredAlertsKey(eventId, beginTime, alarmTime));
+ }
+
+ /**
+ * Store fired alert info in the SharedPrefs.
+ */
+ static void setAlertFiredInSharedPrefs(Context context, long eventId, long beginTime,
+ long alarmTime) {
+ // Store alarm time as the value too so we don't have to parse all the keys to flush
+ // old alarms out of the table later.
+ SharedPreferences prefs = getFiredAlertsTable(context);
+ SharedPreferences.Editor editor = prefs.edit();
+ editor.putLong(getFiredAlertsKey(eventId, beginTime, alarmTime), alarmTime);
+ editor.apply();
+ }
+
+ /**
+ * Scans and flushes the internal storage of old alerts. Looks up the previous flush
+ * time in SharedPrefs, and performs the flush if overdue. Otherwise, no-op.
+ */
+ static void flushOldAlertsFromInternalStorage(Context context) {
+ if (BYPASS_DB) {
+ SharedPreferences prefs = getFiredAlertsTable(context);
+
+ // Only flush if it hasn't been done in a while.
+ long nowTime = System.currentTimeMillis();
+ long lastFlushTimeMs = prefs.getLong(KEY_LAST_FLUSH_TIME_MS, 0);
+ if (nowTime - lastFlushTimeMs > FLUSH_INTERVAL_MS) {
+ if (DEBUG) {
+ Log.d(TAG, "Flushing old alerts from shared prefs table");
+ }
+
+ // Scan through all fired alert entries, removing old ones.
+ SharedPreferences.Editor editor = prefs.edit();
+ Time timeObj = new Time();
+ for (Map.Entry<String, ?> entry : prefs.getAll().entrySet()) {
+ String key = entry.getKey();
+ Object value = entry.getValue();
+ if (key.startsWith(KEY_FIRED_ALERT_PREFIX)) {
+ long alertTime;
+ if (value instanceof Long) {
+ alertTime = (Long) value;
+ } else {
+ // Should never occur.
+ Log.e(TAG,"SharedPrefs key " + key + " did not have Long value: " +
+ value);
+ continue;
+ }
+
+ if (nowTime - alertTime >= FLUSH_INTERVAL_MS) {
+ editor.remove(key);
+ if (DEBUG) {
+ int ageInDays = getIntervalInDays(alertTime, nowTime, timeObj);
+ Log.d(TAG, "SharedPrefs key " + key + ": removed (" + ageInDays +
+ " days old)");
+ }
+ } else {
+ if (DEBUG) {
+ int ageInDays = getIntervalInDays(alertTime, nowTime, timeObj);
+ Log.d(TAG, "SharedPrefs key " + key + ": keep (" + ageInDays +
+ " days old)");
+ }
+ }
+ }
+ }
+ editor.putLong(KEY_LAST_FLUSH_TIME_MS, nowTime);
+ editor.apply();
+ }
+ }
+ }
+
+ private static int getIntervalInDays(long startMillis, long endMillis, Time timeObj) {
+ timeObj.set(startMillis);
+ int startDay = Time.getJulianDay(startMillis, timeObj.gmtoff);
+ timeObj.set(endMillis);
+ return Time.getJulianDay(endMillis, timeObj.gmtoff) - startDay;
+ }
}