Ensure that a default SMS app is configured at boot
David Braun [Thu, 19 Sep 2013 19:14:09 +0000 (12:14 -0700)]
Make sure that two things are true on boot so that SMS/MMS will work
properly:
1) We have selected a default SMS/MMS app that will have write permission
to the SMS database
2) The Phone app always has permission to the database because it needs
to write to the raw tables when delivering MMS messages.

Note: If you change the default app explicitly the problems sending SMS
and MMS messages in Messaging will still happen. Preventing this requires
a larger change to prevent Mms from trying to send when it is not the
default app.

Bug: 10819150 Messaging App crashes while sending MMS
Bug: 10837862 Unable to send messages in Messaging app
Change-Id: Ie920e308b9b4067f0bbe1b6b2184c22aaf663065

src/java/com/android/internal/telephony/PhoneFactory.java

index 463f7d3..bd30dbb 100644 (file)
 
 package com.android.internal.telephony;
 
+import android.app.AppOpsManager;
+import android.content.ComponentName;
 import android.content.Context;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
 import android.net.LocalServerSocket;
 import android.os.Looper;
 import android.provider.Settings;
 import android.telephony.TelephonyManager;
 import android.telephony.Rlog;
+
 import com.android.internal.telephony.cdma.CDMAPhone;
 import com.android.internal.telephony.cdma.CDMALTEPhone;
 import com.android.internal.telephony.cdma.CdmaSubscriptionSourceManager;
@@ -37,6 +43,7 @@ public class PhoneFactory {
     static final String LOG_TAG = "PhoneFactory";
     static final int SOCKET_OPEN_RETRY_MILLIS = 2 * 1000;
     static final int SOCKET_OPEN_MAX_RETRY = 3;
+    private static final String PHONE_PACKAGE_NAME = "com.android.phone";
 
     //***** Class Variables
 
@@ -135,6 +142,29 @@ public class PhoneFactory {
                     }
                 }
 
+                // Ensure that we have a default SMS app. Requesting the app with
+                // updateIfNeeded set to true is enough to configure a default SMS app.
+                ComponentName componentName =
+                        SmsApplication.getDefaultSmsApplication(context, true /* updateIfNeeded */);
+                String packageName = "NONE";
+                if (componentName != null) {
+                    packageName = componentName.getPackageName();
+                }
+                Rlog.i(LOG_TAG, "defaultSmsApplication: " + packageName);
+
+                // Phone needs to always have this permission to write to the sms database
+                PackageManager packageManager = context.getPackageManager();
+                AppOpsManager appOps = (AppOpsManager)context.getSystemService(
+                        Context.APP_OPS_SERVICE);
+                try {
+                    PackageInfo info = packageManager.getPackageInfo(PHONE_PACKAGE_NAME, 0);
+                    appOps.setMode(AppOpsManager.OP_WRITE_SMS, info.applicationInfo.uid,
+                            PHONE_PACKAGE_NAME, AppOpsManager.MODE_ALLOWED);
+                } catch (NameNotFoundException e) {
+                    // No phone app on this device (unexpected, even for non-phone devices)
+                    Rlog.e(LOG_TAG, "Unable to find phone package");
+                }
+
                 sMadeDefaults = true;
             }
         }