Loading src/java/com/android/internal/telephony/PhoneFactory.java +3 −0 Original line number Diff line number Diff line Loading @@ -147,6 +147,9 @@ public class PhoneFactory { } Rlog.i(LOG_TAG, "defaultSmsApplication: " + packageName); // Set up monitor to watch for changes to SMS packages SmsApplication.initSmsPackageMonitor(context); sMadeDefaults = true; } } Loading src/java/com/android/internal/telephony/SmsApplication.java +99 −3 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ import android.app.AppOpsManager; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.pm.ActivityInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; Loading @@ -33,6 +34,7 @@ import android.provider.Settings; import android.provider.Telephony.Sms.Intents; import android.telephony.Rlog; import android.telephony.TelephonyManager; import com.android.internal.content.PackageMonitor; import java.util.Collection; import java.util.HashMap; Loading @@ -48,6 +50,13 @@ public final class SmsApplication { private static final String PHONE_PACKAGE_NAME = "com.android.phone"; private static final String BLUETOOTH_PACKAGE_NAME = "com.android.bluetooth"; private static final String SCHEME_SMS = "sms"; private static final String SCHEME_SMSTO = "smsto"; private static final String SCHEME_MMS = "mms"; private static final String SCHEME_MMSTO = "mmsto"; private static SmsPackageMonitor sSmsPackageMonitor = null; public static class SmsApplicationData { /** * Name of this SMS app for display. Loading Loading @@ -168,7 +177,7 @@ public final class SmsApplication { // Update any existing entries with respond via message intent class. intent = new Intent(TelephonyManager.ACTION_RESPOND_VIA_MESSAGE, Uri.fromParts("smsto", "", null)); Uri.fromParts(SCHEME_SMSTO, "", null)); List<ResolveInfo> respondServices = packageManager.queryIntentServices(intent, 0); for (ResolveInfo resolveInfo : respondServices) { final ServiceInfo serviceInfo = resolveInfo.serviceInfo; Loading @@ -187,7 +196,7 @@ public final class SmsApplication { // Update any existing entries with supports send to. intent = new Intent(Intent.ACTION_SENDTO, Uri.fromParts("smsto", "", null)); Uri.fromParts(SCHEME_SMSTO, "", null)); List<ResolveInfo> sendToActivities = packageManager.queryIntentActivities(intent, 0); for (ResolveInfo resolveInfo : sendToActivities) { final ActivityInfo activityInfo = resolveInfo.activityInfo; Loading Loading @@ -311,8 +320,15 @@ public final class SmsApplication { // We can only verify the phone and BT app's permissions from a privileged caller if (updateIfNeeded) { // Verify that the phone and BT app has permissions // Ensure this component is still configured as the preferred activity. Usually the // current SMS app will already be the preferred activity - but checking whether or // not this is true is just as expensive as reconfiguring the preferred activity so // we just reconfigure every time. PackageManager packageManager = context.getPackageManager(); configurePreferredActivity(packageManager, new ComponentName( applicationData.mPackageName, applicationData.mSendToClass)); // Verify that the phone and BT app has permissions try { PackageInfo info = packageManager.getPackageInfo(PHONE_PACKAGE_NAME, 0); int mode = appOps.checkOp(AppOpsManager.OP_WRITE_SMS, info.applicationInfo.uid, Loading Loading @@ -388,6 +404,10 @@ public final class SmsApplication { Settings.Secure.putString(context.getContentResolver(), Settings.Secure.SMS_DEFAULT_APPLICATION, applicationData.mPackageName); // Configure this as the preferred activity for SENDTO sms/mms intents configurePreferredActivity(packageManager, new ComponentName( applicationData.mPackageName, applicationData.mSendToClass)); // Allow OP_WRITE_SMS for the newly configured default SMS app. appOps.setMode(AppOpsManager.OP_WRITE_SMS, applicationData.mUid, applicationData.mPackageName, AppOpsManager.MODE_ALLOWED); Loading @@ -414,6 +434,82 @@ public final class SmsApplication { } } /** * Tracks package changes and ensures that the default SMS app is always configured to be the * preferred activity for SENDTO sms/mms intents. */ private static final class SmsPackageMonitor extends PackageMonitor { final Context mContext; public SmsPackageMonitor(Context context) { super(); mContext = context; } @Override public void onPackageDisappeared(String packageName, int reason) { onPackageChanged(packageName); } @Override public void onPackageAppeared(String packageName, int reason) { onPackageChanged(packageName); } @Override public void onPackageModified(String packageName) { onPackageChanged(packageName); } private void onPackageChanged(String packageName) { PackageManager packageManager = mContext.getPackageManager(); // Ensure this component is still configured as the preferred activity ComponentName componentName = getDefaultSendToApplication(mContext, true); configurePreferredActivity(packageManager, componentName); } } public static void initSmsPackageMonitor(Context context) { sSmsPackageMonitor = new SmsPackageMonitor(context); sSmsPackageMonitor.register(context, context.getMainLooper(), false); } private static void configurePreferredActivity(PackageManager packageManager, ComponentName componentName) { // Add the four activity preferences we want to direct to this app. replacePreferredActivity(packageManager, componentName, SCHEME_SMS); replacePreferredActivity(packageManager, componentName, SCHEME_SMSTO); replacePreferredActivity(packageManager, componentName, SCHEME_MMS); replacePreferredActivity(packageManager, componentName, SCHEME_MMSTO);} /** * Updates the ACTION_SENDTO activity to the specified component for the specified scheme. */ private static void replacePreferredActivity(PackageManager packageManager, ComponentName componentName, String scheme) { // Build the set of existing activities that handle this scheme Intent intent = new Intent(Intent.ACTION_SENDTO, Uri.fromParts(scheme, "", null)); List<ResolveInfo> resolveInfoList = packageManager.queryIntentActivities( intent, PackageManager.MATCH_DEFAULT_ONLY | PackageManager.GET_RESOLVED_FILTER); // Build the set of ComponentNames for these activities final int n = resolveInfoList.size(); ComponentName[] set = new ComponentName[n]; for (int i = 0; i < n; i++) { ResolveInfo info = resolveInfoList.get(i); set[i] = new ComponentName(info.activityInfo.packageName, info.activityInfo.name); } // Update the preferred SENDTO activity for the specified scheme IntentFilter intentFilter = new IntentFilter(); intentFilter.addAction(Intent.ACTION_SENDTO); intentFilter.addCategory(Intent.CATEGORY_DEFAULT); intentFilter.addDataScheme(scheme); packageManager.replacePreferredActivity(intentFilter, IntentFilter.MATCH_CATEGORY_SCHEME + IntentFilter.MATCH_ADJUSTMENT_NORMAL, set, componentName); } /** * Returns SmsApplicationData for this package if this package is capable of being set as the * default SMS application. Loading Loading
src/java/com/android/internal/telephony/PhoneFactory.java +3 −0 Original line number Diff line number Diff line Loading @@ -147,6 +147,9 @@ public class PhoneFactory { } Rlog.i(LOG_TAG, "defaultSmsApplication: " + packageName); // Set up monitor to watch for changes to SMS packages SmsApplication.initSmsPackageMonitor(context); sMadeDefaults = true; } } Loading
src/java/com/android/internal/telephony/SmsApplication.java +99 −3 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ import android.app.AppOpsManager; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.pm.ActivityInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; Loading @@ -33,6 +34,7 @@ import android.provider.Settings; import android.provider.Telephony.Sms.Intents; import android.telephony.Rlog; import android.telephony.TelephonyManager; import com.android.internal.content.PackageMonitor; import java.util.Collection; import java.util.HashMap; Loading @@ -48,6 +50,13 @@ public final class SmsApplication { private static final String PHONE_PACKAGE_NAME = "com.android.phone"; private static final String BLUETOOTH_PACKAGE_NAME = "com.android.bluetooth"; private static final String SCHEME_SMS = "sms"; private static final String SCHEME_SMSTO = "smsto"; private static final String SCHEME_MMS = "mms"; private static final String SCHEME_MMSTO = "mmsto"; private static SmsPackageMonitor sSmsPackageMonitor = null; public static class SmsApplicationData { /** * Name of this SMS app for display. Loading Loading @@ -168,7 +177,7 @@ public final class SmsApplication { // Update any existing entries with respond via message intent class. intent = new Intent(TelephonyManager.ACTION_RESPOND_VIA_MESSAGE, Uri.fromParts("smsto", "", null)); Uri.fromParts(SCHEME_SMSTO, "", null)); List<ResolveInfo> respondServices = packageManager.queryIntentServices(intent, 0); for (ResolveInfo resolveInfo : respondServices) { final ServiceInfo serviceInfo = resolveInfo.serviceInfo; Loading @@ -187,7 +196,7 @@ public final class SmsApplication { // Update any existing entries with supports send to. intent = new Intent(Intent.ACTION_SENDTO, Uri.fromParts("smsto", "", null)); Uri.fromParts(SCHEME_SMSTO, "", null)); List<ResolveInfo> sendToActivities = packageManager.queryIntentActivities(intent, 0); for (ResolveInfo resolveInfo : sendToActivities) { final ActivityInfo activityInfo = resolveInfo.activityInfo; Loading Loading @@ -311,8 +320,15 @@ public final class SmsApplication { // We can only verify the phone and BT app's permissions from a privileged caller if (updateIfNeeded) { // Verify that the phone and BT app has permissions // Ensure this component is still configured as the preferred activity. Usually the // current SMS app will already be the preferred activity - but checking whether or // not this is true is just as expensive as reconfiguring the preferred activity so // we just reconfigure every time. PackageManager packageManager = context.getPackageManager(); configurePreferredActivity(packageManager, new ComponentName( applicationData.mPackageName, applicationData.mSendToClass)); // Verify that the phone and BT app has permissions try { PackageInfo info = packageManager.getPackageInfo(PHONE_PACKAGE_NAME, 0); int mode = appOps.checkOp(AppOpsManager.OP_WRITE_SMS, info.applicationInfo.uid, Loading Loading @@ -388,6 +404,10 @@ public final class SmsApplication { Settings.Secure.putString(context.getContentResolver(), Settings.Secure.SMS_DEFAULT_APPLICATION, applicationData.mPackageName); // Configure this as the preferred activity for SENDTO sms/mms intents configurePreferredActivity(packageManager, new ComponentName( applicationData.mPackageName, applicationData.mSendToClass)); // Allow OP_WRITE_SMS for the newly configured default SMS app. appOps.setMode(AppOpsManager.OP_WRITE_SMS, applicationData.mUid, applicationData.mPackageName, AppOpsManager.MODE_ALLOWED); Loading @@ -414,6 +434,82 @@ public final class SmsApplication { } } /** * Tracks package changes and ensures that the default SMS app is always configured to be the * preferred activity for SENDTO sms/mms intents. */ private static final class SmsPackageMonitor extends PackageMonitor { final Context mContext; public SmsPackageMonitor(Context context) { super(); mContext = context; } @Override public void onPackageDisappeared(String packageName, int reason) { onPackageChanged(packageName); } @Override public void onPackageAppeared(String packageName, int reason) { onPackageChanged(packageName); } @Override public void onPackageModified(String packageName) { onPackageChanged(packageName); } private void onPackageChanged(String packageName) { PackageManager packageManager = mContext.getPackageManager(); // Ensure this component is still configured as the preferred activity ComponentName componentName = getDefaultSendToApplication(mContext, true); configurePreferredActivity(packageManager, componentName); } } public static void initSmsPackageMonitor(Context context) { sSmsPackageMonitor = new SmsPackageMonitor(context); sSmsPackageMonitor.register(context, context.getMainLooper(), false); } private static void configurePreferredActivity(PackageManager packageManager, ComponentName componentName) { // Add the four activity preferences we want to direct to this app. replacePreferredActivity(packageManager, componentName, SCHEME_SMS); replacePreferredActivity(packageManager, componentName, SCHEME_SMSTO); replacePreferredActivity(packageManager, componentName, SCHEME_MMS); replacePreferredActivity(packageManager, componentName, SCHEME_MMSTO);} /** * Updates the ACTION_SENDTO activity to the specified component for the specified scheme. */ private static void replacePreferredActivity(PackageManager packageManager, ComponentName componentName, String scheme) { // Build the set of existing activities that handle this scheme Intent intent = new Intent(Intent.ACTION_SENDTO, Uri.fromParts(scheme, "", null)); List<ResolveInfo> resolveInfoList = packageManager.queryIntentActivities( intent, PackageManager.MATCH_DEFAULT_ONLY | PackageManager.GET_RESOLVED_FILTER); // Build the set of ComponentNames for these activities final int n = resolveInfoList.size(); ComponentName[] set = new ComponentName[n]; for (int i = 0; i < n; i++) { ResolveInfo info = resolveInfoList.get(i); set[i] = new ComponentName(info.activityInfo.packageName, info.activityInfo.name); } // Update the preferred SENDTO activity for the specified scheme IntentFilter intentFilter = new IntentFilter(); intentFilter.addAction(Intent.ACTION_SENDTO); intentFilter.addCategory(Intent.CATEGORY_DEFAULT); intentFilter.addDataScheme(scheme); packageManager.replacePreferredActivity(intentFilter, IntentFilter.MATCH_CATEGORY_SCHEME + IntentFilter.MATCH_ADJUSTMENT_NORMAL, set, componentName); } /** * Returns SmsApplicationData for this package if this package is capable of being set as the * default SMS application. Loading