am 1f64c188: (-s ours) am 07a7d5ce: am ba79889d: (-s ours) Disallow empty eventTimezone values. Do not merge
* commit '1f64c188804bc4c15e4a97ed1792dc22ea1b111b':
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 1621f8e..3d424e4 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -50,6 +50,9 @@
<!-- This is used to keep the provider alive long enough to send update
intent broadcasts. -->
<service android:name=".EmptyService" />
+ <!-- This is used to keep the provider alive long enough to clean up scheduled
+ alarms after boot. -->
+ <service android:name=".CalendarReceiver$RemoveScheduledAlarmsEmptyService" />
<activity android:name="CalendarContentProviderTests" android:label="Calendar Content Provider"
android:exported="false">
diff --git a/src/com/android/providers/calendar/CalendarAlarmManager.java b/src/com/android/providers/calendar/CalendarAlarmManager.java
index 3f4b53c..d917020 100644
--- a/src/com/android/providers/calendar/CalendarAlarmManager.java
+++ b/src/com/android/providers/calendar/CalendarAlarmManager.java
@@ -112,12 +112,6 @@
@VisibleForTesting
protected AtomicBoolean mNextAlarmCheckScheduled;
/**
- * Used for tracking if current alarms should be removed when recalculating
- * new ones.
- */
- @VisibleForTesting
- protected AtomicBoolean mNeedRemoveAlarms;
- /**
* Used for synchronization
*/
@VisibleForTesting
@@ -139,14 +133,10 @@
mContext = context;
mAlarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
mNextAlarmCheckScheduled = new AtomicBoolean(false);
- mNeedRemoveAlarms = new AtomicBoolean(false);
mAlarmLock = new Object();
}
void scheduleNextAlarm(boolean removeAlarms) {
- // We aggregate first the "remove alarm flag". Whenever it is to true,
- // it will be sticky
- mNeedRemoveAlarms.set(mNeedRemoveAlarms.get() || removeAlarms);
if (!mNextAlarmCheckScheduled.getAndSet(true)) {
if (Log.isLoggable(CalendarProvider2.TAG, Log.DEBUG)) {
Log.d(CalendarProvider2.TAG, "Scheduling check of next Alarm");
diff --git a/src/com/android/providers/calendar/CalendarDatabaseHelper.java b/src/com/android/providers/calendar/CalendarDatabaseHelper.java
index d609bdf..4fed7da 100644
--- a/src/com/android/providers/calendar/CalendarDatabaseHelper.java
+++ b/src/com/android/providers/calendar/CalendarDatabaseHelper.java
@@ -16,6 +16,9 @@
package com.android.providers.calendar;
+import com.android.common.content.SyncStateContentProviderHelper;
+import com.google.common.annotations.VisibleForTesting;
+
import android.accounts.Account;
import android.content.ContentResolver;
import android.content.ContentValues;
@@ -36,8 +39,6 @@
import android.text.TextUtils;
import android.text.format.Time;
import android.util.Log;
-import com.android.common.content.SyncStateContentProviderHelper;
-import com.google.common.annotations.VisibleForTesting;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
@@ -2957,7 +2958,6 @@
}
if (url != null) {
extras.putString("feed", url);
- extras.putBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, true);
}
ContentResolver.requestSync(account, CalendarContract.Calendars.CONTENT_URI.getAuthority(),
extras);
diff --git a/src/com/android/providers/calendar/CalendarReceiver.java b/src/com/android/providers/calendar/CalendarReceiver.java
index 2cd834a..48760dd 100644
--- a/src/com/android/providers/calendar/CalendarReceiver.java
+++ b/src/com/android/providers/calendar/CalendarReceiver.java
@@ -16,10 +16,13 @@
package com.android.providers.calendar;
+import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
+import android.os.IBinder;
+import android.util.Log;
/**
* This IntentReceiver executes when the boot completes and ensures that
@@ -29,6 +32,7 @@
* yet.
*/
public class CalendarReceiver extends BroadcastReceiver {
+ private static final String TAG = "CalendarReceiver";
static final String SCHEDULE = "com.android.providers.calendar.SCHEDULE_ALARM";
@@ -40,14 +44,62 @@
cr.update(CalendarAlarmManager.SCHEDULE_ALARM_URI, null /* values */, null /* where */,
null /* selectionArgs */);
} else if (action.equals(Intent.ACTION_BOOT_COMPLETED)) {
- // Remove alarms from the CalendarAlerts table that have been marked
- // as "scheduled" but not fired yet. We do this because the
- // AlarmManagerService loses all information about alarms when the
- // power turns off but we store the information in a database table
- // that persists across reboots. See the documentation for
- // scheduleNextAlarmLocked() for more information.
- cr.update(CalendarAlarmManager.SCHEDULE_ALARM_REMOVE_URI, null /* values */,
+ removeScheduledAlarms(context, cr);
+ }
+ }
+
+ /*
+ * Remove alarms from the CalendarAlerts table that have been marked
+ * as "scheduled" but not fired yet. We do this because the
+ * AlarmManagerService loses all information about alarms when the
+ * power turns off but we store the information in a database table
+ * that persists across reboots. See the documentation for
+ * scheduleNextAlarmLocked() for more information.
+ *
+ * Running this on the main thread has caused ANRs, so we run it on a background
+ * thread and start an "empty service" to encourage the system to keep us alive.
+ *
+ * We don't expect this to be called more than once. If it were, we would have to
+ * worry about serializing the use of the service.
+ */
+ private void removeScheduledAlarms(Context context, ContentResolver resolver) {
+ context.startService(new Intent(context, RemoveScheduledAlarmsEmptyService.class));
+
+ RemoveScheduledAlarmsThread thread = new RemoveScheduledAlarmsThread(context, resolver);
+ thread.start();
+ }
+
+ /**
+ * Background thread that handles cleanup of scheduled alarms.
+ */
+ private static class RemoveScheduledAlarmsThread extends Thread {
+ private Context mContext;
+ private ContentResolver mResolver;
+
+ RemoveScheduledAlarmsThread(Context context, ContentResolver resolver) {
+ mContext = context;
+ mResolver = resolver;
+ }
+
+ @Override
+ public void run() {
+ if (Log.isLoggable(TAG, Log.DEBUG)) {
+ Log.d(TAG, "Removing scheduled alarms");
+ }
+ mResolver.update(CalendarAlarmManager.SCHEDULE_ALARM_REMOVE_URI, null /* values */,
null /* where */, null /* selectionArgs */);
+ mContext.stopService(new Intent(mContext, RemoveScheduledAlarmsEmptyService.class));
+ }
+ }
+
+ /**
+ * Background {@link Service} that is used to keep our process alive long enough
+ * for background threads to finish. Used for cleanup of scheduled alarms.
+ */
+ public static class RemoveScheduledAlarmsEmptyService extends Service {
+ @Override
+ public IBinder onBind(Intent intent) {
+ return null;
}
}
}
diff --git a/tests/src/com/android/providers/calendar/CalendarProvider2ForTesting.java b/tests/src/com/android/providers/calendar/CalendarProvider2ForTesting.java
index 9c52207..9aa02bf 100644
--- a/tests/src/com/android/providers/calendar/CalendarProvider2ForTesting.java
+++ b/tests/src/com/android/providers/calendar/CalendarProvider2ForTesting.java
@@ -49,7 +49,6 @@
protected void initializeWithContext(Context context) {
mContext = context;
mNextAlarmCheckScheduled = new AtomicBoolean(false);
- mNeedRemoveAlarms = new AtomicBoolean(false);
mAlarmLock = new Object();
}