summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMakoto Onuki <omakoto@google.com>2018-05-09 13:56:58 -0700
committerMakoto Onuki <omakoto@google.com>2018-05-15 00:01:54 +0000
commit92afb2f26633de583662cdb22b04423c6affb2dd (patch)
tree17d1933d7da79026fe455dd827ad5c428b4f4cf3
parent484cf8543ca37c370544ed98be8b9236c878be89 (diff)
downloadCalendarProvider-pie-qpr3-s1-release.tar.gz
Otherwise if the provider crashes when it receives a "check next event" before it sets a next alarm, we'd be in trouble. Change-Id: Ic0193fadfc07b065ef47b7a5aceb2b3d36c04b6b Fixes: 79418474 Test: Verified behavior with "setprop debug.calendar.check_interval 5000"
-rw-r--r--src/com/android/providers/calendar/CalendarAlarmManager.java54
-rw-r--r--src/com/android/providers/calendar/CalendarReceiver.java56
-rw-r--r--src/com/android/providers/calendar/CalendarSanityChecker.java24
3 files changed, 54 insertions, 80 deletions
diff --git a/src/com/android/providers/calendar/CalendarAlarmManager.java b/src/com/android/providers/calendar/CalendarAlarmManager.java
index 9e0bb5f..7019797 100644
--- a/src/com/android/providers/calendar/CalendarAlarmManager.java
+++ b/src/com/android/providers/calendar/CalendarAlarmManager.java
@@ -140,10 +140,16 @@ public class CalendarAlarmManager {
static Intent getCheckNextAlarmIntent(Context context, boolean removeAlarms) {
Intent intent = new Intent(CalendarAlarmManager.ACTION_CHECK_NEXT_ALARM);
intent.setClass(context, CalendarProviderBroadcastReceiver.class);
- intent.putExtra(KEY_REMOVE_ALARMS, removeAlarms);
+ if (removeAlarms) {
+ intent.putExtra(KEY_REMOVE_ALARMS, true);
+ }
return intent;
}
+ public static Intent getCheckNextAlarmIntentForBroadcast(Context context) {
+ return getCheckNextAlarmIntent(context, false);
+ }
+
/**
* Called by CalendarProvider to check the next alarm. A small delay is added before the real
* checking happens in order to batch the requests.
@@ -179,37 +185,11 @@ public class CalendarAlarmManager {
}
}
- /**
- * Similar to {@link #checkNextAlarm}, but schedule the checking at specific {@code
- * triggerTime}. In general, we do not need an alarm for scheduling. Instead we set the next
- * alarm check immediately when a reminder is shown. The only use case for this
- * is to schedule the next alarm check when there is no reminder within 1 day.
- *
- * @param triggerTimeMillis Time to run the next alarm check, in milliseconds.
- */
- void scheduleNextAlarmCheck(long triggerTimeMillis) {
- Intent intent = getCheckNextAlarmIntent(mContext, false /* removeAlarms*/);
- PendingIntent pending = PendingIntent.getBroadcast(
- mContext, 0, intent, PendingIntent.FLAG_NO_CREATE);
- if (pending != null) {
- // Cancel any previous alarms that do the same thing.
- cancel(pending);
- }
- pending = PendingIntent.getBroadcast(
- mContext, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
-
- if (Log.isLoggable(CalendarProvider2.TAG, Log.DEBUG)) {
- Time time = new Time();
- time.set(triggerTimeMillis);
- String timeStr = time.format(" %a, %b %d, %Y %I:%M%P");
- Log.d(CalendarProvider2.TAG,
- "scheduleNextAlarmCheck at: " + triggerTimeMillis + timeStr);
- }
- setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, triggerTimeMillis, pending);
- }
-
- void scheduleNextAlarmCheckRightNow() {
- scheduleNextAlarmCheck(System.currentTimeMillis());
+ static void checkNextAlarmCheckRightNow(Context context) {
+ // We should probably call scheduleNextAlarmLocked() directly but we don't want
+ // to mix java synchronization and DB transactions that might cause deadlocks, so we
+ // just send a broadcast to serialize all the calls.
+ context.sendBroadcast(getCheckNextAlarmIntentForBroadcast(context));
}
void rescheduleMissedAlarms() {
@@ -474,14 +454,8 @@ public class CalendarAlarmManager {
}
// No event alarm is scheduled, check again in 24 hours - 15
- // minutes. Scheduling the check 15 minutes earlier than 24
- // hours to prevent the scheduler alarm from using up the
- // alarms quota for reminders during dozing. If a new event is
- // inserted before the next alarm check, then this method will
- // be run again when the new event is inserted.
- if (!alarmScheduled) {
- scheduleNextAlarmCheck(currentMillis + NEXT_ALARM_CHECK_TIME_MS);
- }
+ // minutes.
+ // We have a repeated alarm to check the next even every N hours, so nothing to do here.
}
/**
diff --git a/src/com/android/providers/calendar/CalendarReceiver.java b/src/com/android/providers/calendar/CalendarReceiver.java
index d1d8a5a..55b75e0 100644
--- a/src/com/android/providers/calendar/CalendarReceiver.java
+++ b/src/com/android/providers/calendar/CalendarReceiver.java
@@ -16,15 +16,17 @@
package com.android.providers.calendar;
+import android.app.AlarmManager;
+import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.os.PowerManager;
+import android.os.SystemProperties;
import android.util.Log;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
/**
* This IntentReceiver executes when the boot completes and ensures that
@@ -34,13 +36,26 @@ import java.util.concurrent.Executors;
* yet.
*/
public class CalendarReceiver extends BroadcastReceiver {
- private static final String TAG = "CalendarReceiver";
+ private static final String TAG = CalendarProvider2.TAG;
+
+ private static final long NEXT_EVENT_CHECK_INTERVAL =
+ SystemProperties.getLong("debug.calendar.check_interval", TimeUnit.HOURS.toMillis(6));
+ private static final int NEXT_EVENT_CHECK_PENDING_CODE = 100;
- private final ExecutorService executor = Executors.newCachedThreadPool();
private PowerManager.WakeLock mWakeLock;
@Override
public void onReceive(Context context, Intent intent) {
+ final String action = intent.getAction();
+
+ if (!Intent.ACTION_BOOT_COMPLETED.equals(action)) {
+ Log.w(TAG, "Unexpected broadcast: " + action);
+ return;
+ }
+ if (Log.isLoggable(TAG, Log.DEBUG)) {
+ Log.d(TAG, "BOOT_COMPLETED");
+ }
+
if (mWakeLock == null) {
PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "CalendarReceiver_Provider");
@@ -48,19 +63,15 @@ public class CalendarReceiver extends BroadcastReceiver {
}
mWakeLock.acquire();
- final String action = intent.getAction();
final ContentResolver cr = context.getContentResolver();
final PendingResult result = goAsync();
- executor.submit(new Runnable() {
- @Override
- public void run() {
- if (Intent.ACTION_BOOT_COMPLETED.equals(action)) {
- removeScheduledAlarms(cr);
- }
- result.finish();
- mWakeLock.release();
- }
- });
+
+ new Thread(() -> {
+ setCalendarCheckAlarm(context);
+ removeScheduledAlarms(cr);
+ result.finish();
+ mWakeLock.release();
+ }).start();
}
/*
@@ -75,10 +86,19 @@ public class CalendarReceiver extends BroadcastReceiver {
* worry about serializing the use of the service.
*/
private void removeScheduledAlarms(ContentResolver resolver) {
- if (Log.isLoggable(TAG, Log.DEBUG)) {
- Log.d(TAG, "Removing scheduled alarms");
- }
resolver.update(CalendarAlarmManager.SCHEDULE_ALARM_REMOVE_URI, null /* values */,
null /* where */, null /* selectionArgs */);
}
+
+ private static void setCalendarCheckAlarm(Context context) {
+ final PendingIntent checkIntent = PendingIntent.getBroadcast(context,
+ NEXT_EVENT_CHECK_PENDING_CODE,
+ CalendarAlarmManager.getCheckNextAlarmIntentForBroadcast(context),
+ PendingIntent.FLAG_UPDATE_CURRENT);
+
+ final AlarmManager am = context.getSystemService(AlarmManager.class);
+
+ am.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,
+ NEXT_EVENT_CHECK_INTERVAL, NEXT_EVENT_CHECK_INTERVAL, checkIntent);
+ }
}
diff --git a/src/com/android/providers/calendar/CalendarSanityChecker.java b/src/com/android/providers/calendar/CalendarSanityChecker.java
index f6f9b21..19cb5b1 100644
--- a/src/com/android/providers/calendar/CalendarSanityChecker.java
+++ b/src/com/android/providers/calendar/CalendarSanityChecker.java
@@ -73,26 +73,9 @@ public class CalendarSanityChecker {
@VisibleForTesting
final SharedPreferences mPrefs;
- @Nullable // only null when initialization failed.
- private final CalendarProvider2 mCalendarProvider2;
-
protected CalendarSanityChecker(Context context) {
mContext = context;
mPrefs = mContext.getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE);
- mCalendarProvider2 = getProvider(mContext);
- }
-
- protected static CalendarProvider2 getProvider(Context context) {
- final IContentProvider iprovider =
- context.getContentResolver().acquireProvider(CalendarContract.AUTHORITY);
- final ContentProvider cprovider = ContentProvider.coerceToLocalContentProvider(iprovider);
-
- if (!(cprovider instanceof CalendarProvider2)) {
- Slog.wtf(TAG, "CalendarProvider2 not found in CalendarSanityChecker.");
- return null;
- }
-
- return (CalendarProvider2) cprovider;
}
@VisibleForTesting
@@ -141,7 +124,7 @@ public class CalendarSanityChecker {
/**
* Call this at public entry points. This will check if the last check time was recent enough,
- * and otherwise it'll call {@link CalendarAlarmManager#scheduleNextAlarmCheckRightNow()}.
+ * and otherwise it'll call {@link CalendarAlarmManager#checkNextAlarmCheckRightNow}.
*/
public final boolean checkLastCheckTime() {
final long lastBootCount;
@@ -202,10 +185,7 @@ public class CalendarSanityChecker {
.apply();
// Note mCalendarProvider2 really shouldn't be null.
- if (mCalendarProvider2 != null) {
- mCalendarProvider2.getOrCreateCalendarAlarmManager()
- .scheduleNextAlarmCheckRightNow();
- }
+ CalendarAlarmManager.checkNextAlarmCheckRightNow(mContext);
}
return false;
}