diff options
author | Makoto Onuki <omakoto@google.com> | 2018-05-09 13:56:58 -0700 |
---|---|---|
committer | Makoto Onuki <omakoto@google.com> | 2018-05-15 00:01:54 +0000 |
commit | 92afb2f26633de583662cdb22b04423c6affb2dd (patch) | |
tree | 17d1933d7da79026fe455dd827ad5c428b4f4cf3 | |
parent | 484cf8543ca37c370544ed98be8b9236c878be89 (diff) | |
download | CalendarProvider-pie-qpr3-s1-release.tar.gz |
Use repeated alarm to check new eventsandroid-9.0.0_r47android-9.0.0_r46android-9.0.0_r45android-9.0.0_r44android-9.0.0_r43android-9.0.0_r42android-9.0.0_r41android-9.0.0_r40android-9.0.0_r39android-9.0.0_r38android-9.0.0_r37android-9.0.0_r36android-9.0.0_r35android-9.0.0_r34android-9.0.0_r33android-9.0.0_r32android-9.0.0_r31android-9.0.0_r30android-9.0.0_r22android-9.0.0_r21android-9.0.0_r20android-9.0.0_r19android-9.0.0_r16android-9.0.0_r12android-9.0.0_r11pie-qpr3-s1-releasepie-qpr3-releasepie-qpr3-b-releasepie-qpr2-releasepie-qpr1-s3-releasepie-qpr1-s2-releasepie-qpr1-s1-releasepie-qpr1-releasepie-dr1-releasepie-dr1-devpie-devpie-b4s4-releasepie-b4s4-dev
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"
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; } |