Add a PRE_BOOT_COMPLETED receiver.
It runs the first time after an OTA and either creates
the database or runs the upgrade path on it. This may
take a significatn amount of time so it's done before
the boot animation completes.
Bug: 2713849
Change-Id: Ie7ac396bd82577cd421daa102ad05c0abf55b6f0
diff --git a/Android.mk b/Android.mk
index 3dea6da..af7aa95 100644
--- a/Android.mk
+++ b/Android.mk
@@ -21,6 +21,8 @@
LOCAL_STATIC_JAVA_LIBRARIES := guava
LOCAL_SRC_FILES := $(call all-java-files-under,src)
+LOCAL_SRC_FILES += \
+ src/com/android/providers/calendar/EventLogTags.logtags
LOCAL_PACKAGE_NAME := CalendarProvider
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 361ae6d..d9926c2 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -85,6 +85,15 @@
</intent-filter>
</receiver>
+ <!-- Handles database upgrades after OTAs, then disables itself -->
+ <receiver android:name="CalendarUpgradeReceiver">
+ <!-- This broadcast is sent after the core system has finished
+ booting, before the home app is launched or BOOT_COMPLETED
+ is sent. -->
+ <intent-filter>
+ <action android:name="android.intent.action.PRE_BOOT_COMPLETED"/>
+ </intent-filter>
+ </receiver>
</application>
</manifest>
diff --git a/src/com/android/providers/calendar/CalendarDatabaseHelper.java b/src/com/android/providers/calendar/CalendarDatabaseHelper.java
index 9ba72f7..b38831b 100644
--- a/src/com/android/providers/calendar/CalendarDatabaseHelper.java
+++ b/src/com/android/providers/calendar/CalendarDatabaseHelper.java
@@ -58,7 +58,7 @@
// Note: if you update the version number, you must also update the code
// in upgradeDatabase() to modify the database (gracefully, if possible).
- private static final int DATABASE_VERSION = 69;
+ static final int DATABASE_VERSION = 69;
private static final int PRE_FROYO_SYNC_STATE_VERSION = 3;
diff --git a/src/com/android/providers/calendar/CalendarUpgradeReceiver.java b/src/com/android/providers/calendar/CalendarUpgradeReceiver.java
new file mode 100644
index 0000000..30ac58c
--- /dev/null
+++ b/src/com/android/providers/calendar/CalendarUpgradeReceiver.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.providers.calendar;
+
+import android.content.BroadcastReceiver;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.content.pm.PackageManager;
+import android.util.EventLog;
+import android.util.Log;
+
+/**
+ * This will be launched during system boot, after the core system has
+ * been brought up but before any non-persistent processes have been
+ * started. It is launched in a special state, with no content provider
+ * or custom application class associated with the process running.
+ *
+ * It's job is to prime the calendar database. Either create it
+ * if it doesn't exist, or open it and force any necessary upgrades.
+ * All of this heavy lifting happens before the boot animation ends.
+ */
+public class CalendarUpgradeReceiver extends BroadcastReceiver {
+ static final String TAG = "CalendarUpgradeReceiver";
+ static final String PREF_DB_VERSION = "db_version";
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ // We are now running with the system up, but no apps started,
+ // so can do whatever cleanup after an upgrade that we want.
+
+ try {
+ long startTime = System.currentTimeMillis();
+
+ // Lookup the last known database version
+ SharedPreferences prefs = context.getSharedPreferences(TAG, Context.MODE_PRIVATE);
+ int prefVersion = prefs.getInt(PREF_DB_VERSION, 0);
+
+ // If the version is old go ahead and attempt to create or upgrade the database.
+ if (prefVersion != CalendarDatabaseHelper.DATABASE_VERSION) {
+ // Store the current version so this receiver isn't run again until the database
+ // version number changes. This is intentionally done even before the upgrade path
+ // is attempted to be conservative. If the upgrade fails for some reason and we
+ // crash and burn we don't want to get into a loop doing so.
+ prefs.edit().putInt(PREF_DB_VERSION, CalendarDatabaseHelper.DATABASE_VERSION).commit();
+
+ // Ask for a reference to the database to force the helper to either
+ // create the database or open it up, performing any necessary upgrades
+ // in the process.
+ Log.i(TAG, "Creating or opening calendar database");
+ CalendarDatabaseHelper helper = CalendarDatabaseHelper.getInstance(context);
+ helper.getWritableDatabase();
+ helper.close();
+
+ // Log the total time taken for the receiver to perform the operation
+ EventLogTags.writeCalendarUpgradeReceiver(System.currentTimeMillis() - startTime);
+ }
+ } catch (Throwable t) {
+ // Something has gone terribly wrong. Disable this receiver for good so we can't
+ // possibly end up in a reboot loop.
+ Log.wtf(TAG, "Error during upgrade attempt. Disabling receiver.", t);
+ context.getPackageManager().setComponentEnabledSetting(
+ new ComponentName(context, getClass()),
+ PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
+ PackageManager.DONT_KILL_APP);
+ }
+ }
+}
diff --git a/src/com/android/providers/calendar/EventLogTags.logtags b/src/com/android/providers/calendar/EventLogTags.logtags
new file mode 100644
index 0000000..621b3c7
--- /dev/null
+++ b/src/com/android/providers/calendar/EventLogTags.logtags
@@ -0,0 +1,5 @@
+# See system/core/logcat/event.logtags for a description of the format of this file.
+
+option java_package com.android.providers.calendar;
+
+4000 calendar_upgrade_receiver (time|2|3)