Send a protected intent ACTION_MMSSMS_DATABASE_LOST upon mmssms.db corruption or loss

This CL sends a protected broadcast intent for catching the mmssms.db
getting mysteriously lost. The intent is protected with
MODIFY_PHONE_STATE permission.

Bug: 115990430
Test: Simulated mmsmsm.db corruption and verified that the intent is
broadcasted and received by application with MODIFY_PHONE_STATE
permission

Merged-in: I1e9070d6a11406078876c9b71b163aec307e4050
Change-Id: I1e9070d6a11406078876c9b71b163aec307e4050
diff --git a/src/com/android/providers/telephony/MmsSmsDatabaseHelper.java b/src/com/android/providers/telephony/MmsSmsDatabaseHelper.java
index 2f19c14..b0265fa 100644
--- a/src/com/android/providers/telephony/MmsSmsDatabaseHelper.java
+++ b/src/com/android/providers/telephony/MmsSmsDatabaseHelper.java
@@ -16,6 +16,8 @@
 
 package com.android.providers.telephony;
 
+import static android.Manifest.permission.MODIFY_PHONE_STATE;
+
 import android.content.BroadcastReceiver;
 import android.content.ContentValues;
 import android.content.Context;
@@ -41,6 +43,7 @@
 import android.provider.Telephony.Sms;
 import android.provider.Telephony.Threads;
 import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyManager;
 import android.util.LocalLog;
 import android.util.Log;
 import android.util.Slog;
@@ -242,6 +245,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];
 
@@ -266,22 +270,24 @@
     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();
             Slog.wtf(TAG, logMsg);
             PhoneFactory.localLog(TAG, logMsg);
-            sendDbErrorIntents();
+            sendDbErrorIntents(mContext, true);
             mDefaultDatabaseErrorHandler.onCorruption(dbObj);
         }
     }
 
-    private static MmsSmsDatabaseErrorHandler sMmsSmsDatabaseErrorHandler
-            = new MmsSmsDatabaseErrorHandler();
-
-    private MmsSmsDatabaseHelper(Context context) {
-        super(context, DATABASE_NAME, null, DATABASE_VERSION, sMmsSmsDatabaseErrorHandler);
+    private MmsSmsDatabaseHelper(Context context, MmsSmsDatabaseErrorHandler dbErrHandler) {
+        super(context, DATABASE_NAME, null, DATABASE_VERSION, dbErrHandler);
         mContext = context;
         // Memory optimization - close idle connections after 30s of inactivity
         setIdleConnectionTimeout(IDLE_CONNECTION_TIMEOUT_MS);
@@ -292,9 +298,18 @@
         }
     }
 
-    private static void sendDbErrorIntents() {
-        // TODO: send intent to ConnectivityMonitor and also a public intent that tells apps
-        // that messaging db is gone
+    private static void sendDbErrorIntents(Context context, boolean isCorrupted) {
+        Intent intent = new Intent(TelephonyManager.ACTION_MMSSMS_DATABASE_LOST);
+        intent.addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
+        intent.putExtra(TelephonyManager.EXTRA_IS_CORRUPTED, isCorrupted);
+        context.sendBroadcast(intent, MODIFY_PHONE_STATE);
+    }
+
+    private static synchronized MmsSmsDatabaseErrorHandler getDbErrorHandler(Context context) {
+        if (sDbErrorHandler == null) {
+            sDbErrorHandler = new MmsSmsDatabaseErrorHandler(context);
+        }
+        return sDbErrorHandler;
     }
 
     /**
@@ -302,7 +317,9 @@
      */
     /* package */ static synchronized MmsSmsDatabaseHelper getInstanceForDe(Context context) {
         if (sDeInstance == null) {
-            sDeInstance = new MmsSmsDatabaseHelper(ProviderUtil.getDeviceEncryptedContext(context));
+            sDeInstance = new MmsSmsDatabaseHelper(
+                ProviderUtil.getDeviceEncryptedContext(context),
+                getDbErrorHandler(context));
         }
         return sDeInstance;
     }
@@ -315,7 +332,8 @@
         if (sCeInstance == null) {
             if (StorageManager.isFileEncryptedNativeOrEmulated()) {
                 sCeInstance = new MmsSmsDatabaseHelper(
-                    ProviderUtil.getCredentialEncryptedContext(context));
+                    ProviderUtil.getCredentialEncryptedContext(context),
+                    getDbErrorHandler(context));
             } else {
                 sCeInstance = getInstanceForDe(context);
             }
@@ -513,7 +531,7 @@
             String logMsg = "onCreate: was already called once earlier";
             Slog.wtf(TAG, logMsg);
             PhoneFactory.localLog(TAG, logMsg);
-            sendDbErrorIntents();
+            sendDbErrorIntents(mContext, false);
         } else {
             setInitialCreateDone();
         }