Merge "Send protected intent ACTION_SMS_MMS_DB_LOST on mmssms.db corruption or lost mysteriously" into pi-dev
diff --git a/src/com/android/providers/telephony/MmsSmsDatabaseHelper.java b/src/com/android/providers/telephony/MmsSmsDatabaseHelper.java
index f4ae9cc..1dc2106 100644
--- a/src/com/android/providers/telephony/MmsSmsDatabaseHelper.java
+++ b/src/com/android/providers/telephony/MmsSmsDatabaseHelper.java
@@ -23,6 +23,8 @@
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.database.Cursor;
+import android.database.DatabaseErrorHandler;
+import android.database.DefaultDatabaseErrorHandler;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteException;
import android.database.sqlite.SQLiteOpenHelper;
@@ -239,6 +241,7 @@
private static MmsSmsDatabaseHelper sDeInstance = null;
private static MmsSmsDatabaseHelper sCeInstance = null;
+ private static MmsSmsDatabaseErrorHandler sDbErrorHandler = null;
private static final String[] BIND_ARGS_NONE = new String[0];
@@ -258,8 +261,31 @@
// cache for INITIAL_CREATE_DONE shared pref so access to it can be avoided when possible
private static AtomicBoolean sInitialCreateDone = new AtomicBoolean(false);
- private MmsSmsDatabaseHelper(Context context) {
- super(context, DATABASE_NAME, null, DATABASE_VERSION);
+ /**
+ * The primary purpose of this DatabaseErrorHandler is to broadcast an intent on corruption and
+ * print a Slog.wtf so database corruption can be caught earlier.
+ */
+ private static class MmsSmsDatabaseErrorHandler implements DatabaseErrorHandler {
+ private DefaultDatabaseErrorHandler mDefaultDatabaseErrorHandler
+ = new DefaultDatabaseErrorHandler();
+ private Context mContext;
+
+ MmsSmsDatabaseErrorHandler(Context context) {
+ mContext = context;
+ }
+
+ @Override
+ public void onCorruption(SQLiteDatabase dbObj) {
+ String logMsg = "Corruption reported by sqlite on database: " + dbObj.getPath();
+ localLogWtf(logMsg);
+ sendDbLostIntent(mContext, true);
+ // Let the default error handler take other actions
+ mDefaultDatabaseErrorHandler.onCorruption(dbObj);
+ }
+ }
+
+ private MmsSmsDatabaseHelper(Context context, MmsSmsDatabaseErrorHandler dbErrorHandler) {
+ super(context, DATABASE_NAME, null, DATABASE_VERSION, dbErrorHandler);
mContext = context;
// Memory optimization - close idle connections after 30s of inactivity
setIdleConnectionTimeout(IDLE_CONNECTION_TIMEOUT_MS);
@@ -270,12 +296,27 @@
}
}
+ private static synchronized MmsSmsDatabaseErrorHandler getDbErrorHandler(Context context) {
+ if (sDbErrorHandler == null) {
+ sDbErrorHandler = new MmsSmsDatabaseErrorHandler(context);
+ }
+ return sDbErrorHandler;
+ }
+
+ private static void sendDbLostIntent(Context context, boolean isCorrupted) {
+ // Broadcast ACTION_SMS_MMS_DB_LOST
+ Intent intent = new Intent(Sms.Intents.ACTION_SMS_MMS_DB_LOST);
+ intent.putExtra(Sms.Intents.EXTRA_IS_CORRUPTED, isCorrupted);
+ intent.addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
+ context.sendBroadcast(intent, android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE);
+ }
/**
* Returns a singleton helper for the combined MMS and SMS database in device encrypted storage.
*/
/* package */ static synchronized MmsSmsDatabaseHelper getInstanceForDe(Context context) {
if (sDeInstance == null) {
- sDeInstance = new MmsSmsDatabaseHelper(ProviderUtil.getDeviceEncryptedContext(context));
+ Context deContext = ProviderUtil.getDeviceEncryptedContext(context);
+ sDeInstance = new MmsSmsDatabaseHelper(deContext, getDbErrorHandler(deContext));
}
return sDeInstance;
}
@@ -287,8 +328,8 @@
/* package */ static synchronized MmsSmsDatabaseHelper getInstanceForCe(Context context) {
if (sCeInstance == null) {
if (StorageManager.isFileEncryptedNativeOrEmulated()) {
- sCeInstance = new MmsSmsDatabaseHelper(
- ProviderUtil.getCredentialEncryptedContext(context));
+ Context ceContext = ProviderUtil.getCredentialEncryptedContext(context);
+ sCeInstance = new MmsSmsDatabaseHelper(ceContext, getDbErrorHandler(ceContext));
} else {
sCeInstance = getInstanceForDe(context);
}
@@ -493,6 +534,7 @@
// disappeared mysteriously?
localLogWtf("onCreate: was already called once earlier");
intent.putExtra(Intents.EXTRA_IS_INITIAL_CREATE, false);
+ sendDbLostIntent(mContext, false);
} else {
setInitialCreateDone();
intent.putExtra(Intents.EXTRA_IS_INITIAL_CREATE, true);
@@ -509,12 +551,12 @@
createIndices(db);
}
- private void localLog(String logMsg) {
+ private static void localLog(String logMsg) {
Log.d(TAG, logMsg);
PhoneFactory.localLog(TAG, logMsg);
}
- private void localLogWtf(String logMsg) {
+ private static void localLogWtf(String logMsg) {
Slog.wtf(TAG, logMsg);
PhoneFactory.localLog(TAG, logMsg);
}