Home | History | Annotate | Download | only in telephony
      1 /*
      2  * Copyright (C) 2013 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.internal.telephony;
     18 
     19 import android.Manifest.permission;
     20 import android.annotation.Nullable;
     21 import android.app.AppOpsManager;
     22 import android.app.role.RoleManager;
     23 import android.content.ComponentName;
     24 import android.content.Context;
     25 import android.content.Intent;
     26 import android.content.IntentFilter;
     27 import android.content.pm.ActivityInfo;
     28 import android.content.pm.ApplicationInfo;
     29 import android.content.pm.PackageInfo;
     30 import android.content.pm.PackageManager;
     31 import android.content.pm.PackageManager.NameNotFoundException;
     32 import android.content.pm.ResolveInfo;
     33 import android.content.pm.ServiceInfo;
     34 import android.net.Uri;
     35 import android.os.AsyncTask;
     36 import android.os.Binder;
     37 import android.os.Debug;
     38 import android.os.Process;
     39 import android.os.UserHandle;
     40 import android.provider.Telephony;
     41 import android.provider.Telephony.Sms.Intents;
     42 import android.telephony.Rlog;
     43 import android.telephony.SmsManager;
     44 import android.telephony.TelephonyManager;
     45 import android.util.Log;
     46 
     47 import com.android.internal.content.PackageMonitor;
     48 import com.android.internal.logging.MetricsLogger;
     49 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
     50 
     51 import java.util.Collection;
     52 import java.util.HashMap;
     53 import java.util.List;
     54 import java.util.concurrent.CompletableFuture;
     55 import java.util.concurrent.ExecutionException;
     56 import java.util.concurrent.TimeUnit;
     57 import java.util.concurrent.TimeoutException;
     58 import java.util.function.Consumer;
     59 
     60 /**
     61  * Class for managing the primary application that we will deliver SMS/MMS messages to
     62  *
     63  * {@hide}
     64  */
     65 public final class SmsApplication {
     66     static final String LOG_TAG = "SmsApplication";
     67     private static final String PHONE_PACKAGE_NAME = "com.android.phone";
     68     private static final String BLUETOOTH_PACKAGE_NAME = "com.android.bluetooth";
     69     private static final String MMS_SERVICE_PACKAGE_NAME = "com.android.mms.service";
     70     private static final String TELEPHONY_PROVIDER_PACKAGE_NAME = "com.android.providers.telephony";
     71 
     72     private static final String SCHEME_SMS = "sms";
     73     private static final String SCHEME_SMSTO = "smsto";
     74     private static final String SCHEME_MMS = "mms";
     75     private static final String SCHEME_MMSTO = "mmsto";
     76     private static final boolean DEBUG = false;
     77     private static final boolean DEBUG_MULTIUSER = false;
     78 
     79     private static final int[] DEFAULT_APP_EXCLUSIVE_APPOPS = {
     80             AppOpsManager.OP_READ_SMS,
     81             AppOpsManager.OP_WRITE_SMS,
     82             AppOpsManager.OP_RECEIVE_SMS,
     83             AppOpsManager.OP_RECEIVE_WAP_PUSH,
     84             AppOpsManager.OP_SEND_SMS,
     85             AppOpsManager.OP_READ_CELL_BROADCASTS
     86     };
     87 
     88     private static SmsPackageMonitor sSmsPackageMonitor = null;
     89 
     90     public static class SmsApplicationData {
     91         /**
     92          * Name of this SMS app for display.
     93          */
     94         private String mApplicationName;
     95 
     96         /**
     97          * Package name for this SMS app.
     98          */
     99         public String mPackageName;
    100 
    101         /**
    102          * The class name of the SMS_DELIVER_ACTION receiver in this app.
    103          */
    104         private String mSmsReceiverClass;
    105 
    106         /**
    107          * The class name of the WAP_PUSH_DELIVER_ACTION receiver in this app.
    108          */
    109         private String mMmsReceiverClass;
    110 
    111         /**
    112          * The class name of the ACTION_RESPOND_VIA_MESSAGE intent in this app.
    113          */
    114         private String mRespondViaMessageClass;
    115 
    116         /**
    117          * The class name of the ACTION_SENDTO intent in this app.
    118          */
    119         private String mSendToClass;
    120 
    121         /**
    122          * The class name of the ACTION_DEFAULT_SMS_PACKAGE_CHANGED receiver in this app.
    123          */
    124         private String mSmsAppChangedReceiverClass;
    125 
    126         /**
    127          * The class name of the ACTION_EXTERNAL_PROVIDER_CHANGE receiver in this app.
    128          */
    129         private String mProviderChangedReceiverClass;
    130 
    131         /**
    132          * The class name of the SIM_FULL_ACTION receiver in this app.
    133          */
    134         private String mSimFullReceiverClass;
    135 
    136         /**
    137          * The user-id for this application
    138          */
    139         private int mUid;
    140 
    141         /**
    142          * Returns true if this SmsApplicationData is complete (all intents handled).
    143          * @return
    144          */
    145         public boolean isComplete() {
    146             return (mSmsReceiverClass != null && mMmsReceiverClass != null
    147                     && mRespondViaMessageClass != null && mSendToClass != null);
    148         }
    149 
    150         public SmsApplicationData(String packageName, int uid) {
    151             mPackageName = packageName;
    152             mUid = uid;
    153         }
    154 
    155         public String getApplicationName(Context context) {
    156             if (mApplicationName == null) {
    157                 PackageManager pm = context.getPackageManager();
    158                 ApplicationInfo appInfo;
    159                 try {
    160                     appInfo = pm.getApplicationInfoAsUser(mPackageName, 0,
    161                             UserHandle.getUserId(mUid));
    162                 } catch (NameNotFoundException e) {
    163                     return null;
    164                 }
    165                 if (appInfo != null) {
    166                     CharSequence label  = pm.getApplicationLabel(appInfo);
    167                     mApplicationName = (label == null) ? null : label.toString();
    168                 }
    169             }
    170             return mApplicationName;
    171         }
    172 
    173         @Override
    174         public String toString() {
    175             return " mPackageName: " + mPackageName
    176                     + " mSmsReceiverClass: " + mSmsReceiverClass
    177                     + " mMmsReceiverClass: " + mMmsReceiverClass
    178                     + " mRespondViaMessageClass: " + mRespondViaMessageClass
    179                     + " mSendToClass: " + mSendToClass
    180                     + " mSmsAppChangedClass: " + mSmsAppChangedReceiverClass
    181                     + " mProviderChangedReceiverClass: " + mProviderChangedReceiverClass
    182                     + " mSimFullReceiverClass: " + mSimFullReceiverClass
    183                     + " mUid: " + mUid;
    184         }
    185     }
    186 
    187     /**
    188      * Returns the userId of the Context object, if called from a system app,
    189      * otherwise it returns the caller's userId
    190      * @param context The context object passed in by the caller.
    191      * @return
    192      */
    193     private static int getIncomingUserId(Context context) {
    194         int contextUserId = context.getUserId();
    195         final int callingUid = Binder.getCallingUid();
    196         if (DEBUG_MULTIUSER) {
    197             Log.i(LOG_TAG, "getIncomingUserHandle caller=" + callingUid + ", myuid="
    198                     + android.os.Process.myUid() + "\n\t" + Debug.getCallers(4));
    199         }
    200         if (UserHandle.getAppId(callingUid)
    201                 < android.os.Process.FIRST_APPLICATION_UID) {
    202             return contextUserId;
    203         } else {
    204             return UserHandle.getUserId(callingUid);
    205         }
    206     }
    207 
    208     /**
    209      * Returns the list of available SMS apps defined as apps that are registered for both the
    210      * SMS_RECEIVED_ACTION (SMS) and WAP_PUSH_RECEIVED_ACTION (MMS) broadcasts (and their broadcast
    211      * receivers are enabled)
    212      *
    213      * Requirements to be an SMS application:
    214      * Implement SMS_DELIVER_ACTION broadcast receiver.
    215      * Require BROADCAST_SMS permission.
    216      *
    217      * Implement WAP_PUSH_DELIVER_ACTION broadcast receiver.
    218      * Require BROADCAST_WAP_PUSH permission.
    219      *
    220      * Implement RESPOND_VIA_MESSAGE intent.
    221      * Support smsto Uri scheme.
    222      * Require SEND_RESPOND_VIA_MESSAGE permission.
    223      *
    224      * Implement ACTION_SENDTO intent.
    225      * Support smsto Uri scheme.
    226      */
    227     public static Collection<SmsApplicationData> getApplicationCollection(Context context) {
    228         return getApplicationCollectionAsUser(context, getIncomingUserId(context));
    229     }
    230 
    231     /**
    232      * Same as {@link #getApplicationCollection} but it takes a target user ID.
    233      */
    234     public static Collection<SmsApplicationData> getApplicationCollectionAsUser(Context context,
    235             int userId) {
    236         final long token = Binder.clearCallingIdentity();
    237         try {
    238             return getApplicationCollectionInternal(context, userId);
    239         } finally {
    240             Binder.restoreCallingIdentity(token);
    241         }
    242     }
    243 
    244     private static Collection<SmsApplicationData> getApplicationCollectionInternal(
    245             Context context, int userId) {
    246         PackageManager packageManager = context.getPackageManager();
    247 
    248         // Get the list of apps registered for SMS
    249         Intent intent = new Intent(Intents.SMS_DELIVER_ACTION);
    250         if (DEBUG) {
    251             intent.addFlags(Intent.FLAG_DEBUG_LOG_RESOLUTION);
    252         }
    253         List<ResolveInfo> smsReceivers = packageManager.queryBroadcastReceiversAsUser(intent,
    254                 PackageManager.MATCH_DIRECT_BOOT_AWARE | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
    255                 userId);
    256 
    257         HashMap<String, SmsApplicationData> receivers = new HashMap<String, SmsApplicationData>();
    258 
    259         // Add one entry to the map for every sms receiver (ignoring duplicate sms receivers)
    260         for (ResolveInfo resolveInfo : smsReceivers) {
    261             final ActivityInfo activityInfo = resolveInfo.activityInfo;
    262             if (activityInfo == null) {
    263                 continue;
    264             }
    265             if (!permission.BROADCAST_SMS.equals(activityInfo.permission)) {
    266                 continue;
    267             }
    268             final String packageName = activityInfo.packageName;
    269             if (!receivers.containsKey(packageName)) {
    270                 final SmsApplicationData smsApplicationData = new SmsApplicationData(packageName,
    271                         activityInfo.applicationInfo.uid);
    272                 smsApplicationData.mSmsReceiverClass = activityInfo.name;
    273                 receivers.put(packageName, smsApplicationData);
    274             }
    275         }
    276 
    277         // Update any existing entries with mms receiver class
    278         intent = new Intent(Intents.WAP_PUSH_DELIVER_ACTION);
    279         intent.setDataAndType(null, "application/vnd.wap.mms-message");
    280         List<ResolveInfo> mmsReceivers = packageManager.queryBroadcastReceiversAsUser(intent,
    281                 PackageManager.MATCH_DIRECT_BOOT_AWARE | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
    282                 userId);
    283         for (ResolveInfo resolveInfo : mmsReceivers) {
    284             final ActivityInfo activityInfo = resolveInfo.activityInfo;
    285             if (activityInfo == null) {
    286                 continue;
    287             }
    288             if (!permission.BROADCAST_WAP_PUSH.equals(activityInfo.permission)) {
    289                 continue;
    290             }
    291             final String packageName = activityInfo.packageName;
    292             final SmsApplicationData smsApplicationData = receivers.get(packageName);
    293             if (smsApplicationData != null) {
    294                 smsApplicationData.mMmsReceiverClass = activityInfo.name;
    295             }
    296         }
    297 
    298         // Update any existing entries with respond via message intent class.
    299         intent = new Intent(TelephonyManager.ACTION_RESPOND_VIA_MESSAGE,
    300                 Uri.fromParts(SCHEME_SMSTO, "", null));
    301         List<ResolveInfo> respondServices = packageManager.queryIntentServicesAsUser(intent,
    302                 PackageManager.MATCH_DIRECT_BOOT_AWARE | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
    303                 userId);
    304         for (ResolveInfo resolveInfo : respondServices) {
    305             final ServiceInfo serviceInfo = resolveInfo.serviceInfo;
    306             if (serviceInfo == null) {
    307                 continue;
    308             }
    309             if (!permission.SEND_RESPOND_VIA_MESSAGE.equals(serviceInfo.permission)) {
    310                 continue;
    311             }
    312             final String packageName = serviceInfo.packageName;
    313             final SmsApplicationData smsApplicationData = receivers.get(packageName);
    314             if (smsApplicationData != null) {
    315                 smsApplicationData.mRespondViaMessageClass = serviceInfo.name;
    316             }
    317         }
    318 
    319         // Update any existing entries with supports send to.
    320         intent = new Intent(Intent.ACTION_SENDTO,
    321                 Uri.fromParts(SCHEME_SMSTO, "", null));
    322         List<ResolveInfo> sendToActivities = packageManager.queryIntentActivitiesAsUser(intent,
    323                 PackageManager.MATCH_DIRECT_BOOT_AWARE | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
    324                 userId);
    325         for (ResolveInfo resolveInfo : sendToActivities) {
    326             final ActivityInfo activityInfo = resolveInfo.activityInfo;
    327             if (activityInfo == null) {
    328                 continue;
    329             }
    330             final String packageName = activityInfo.packageName;
    331             final SmsApplicationData smsApplicationData = receivers.get(packageName);
    332             if (smsApplicationData != null) {
    333                 smsApplicationData.mSendToClass = activityInfo.name;
    334             }
    335         }
    336 
    337         // Update any existing entries with the default sms changed handler.
    338         intent = new Intent(Telephony.Sms.Intents.ACTION_DEFAULT_SMS_PACKAGE_CHANGED);
    339         List<ResolveInfo> smsAppChangedReceivers =
    340                 packageManager.queryBroadcastReceiversAsUser(intent,
    341                         PackageManager.MATCH_DIRECT_BOOT_AWARE
    342                                 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE, userId);
    343         if (DEBUG_MULTIUSER) {
    344             Log.i(LOG_TAG, "getApplicationCollectionInternal smsAppChangedActivities=" +
    345                     smsAppChangedReceivers);
    346         }
    347         for (ResolveInfo resolveInfo : smsAppChangedReceivers) {
    348             final ActivityInfo activityInfo = resolveInfo.activityInfo;
    349             if (activityInfo == null) {
    350                 continue;
    351             }
    352             final String packageName = activityInfo.packageName;
    353             final SmsApplicationData smsApplicationData = receivers.get(packageName);
    354             if (DEBUG_MULTIUSER) {
    355                 Log.i(LOG_TAG, "getApplicationCollectionInternal packageName=" +
    356                         packageName + " smsApplicationData: " + smsApplicationData +
    357                         " activityInfo.name: " + activityInfo.name);
    358             }
    359             if (smsApplicationData != null) {
    360                 smsApplicationData.mSmsAppChangedReceiverClass = activityInfo.name;
    361             }
    362         }
    363 
    364         // Update any existing entries with the external provider changed handler.
    365         intent = new Intent(Telephony.Sms.Intents.ACTION_EXTERNAL_PROVIDER_CHANGE);
    366         List<ResolveInfo> providerChangedReceivers =
    367                 packageManager.queryBroadcastReceiversAsUser(intent,
    368                         PackageManager.MATCH_DIRECT_BOOT_AWARE
    369                                 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE, userId);
    370         if (DEBUG_MULTIUSER) {
    371             Log.i(LOG_TAG, "getApplicationCollectionInternal providerChangedActivities=" +
    372                     providerChangedReceivers);
    373         }
    374         for (ResolveInfo resolveInfo : providerChangedReceivers) {
    375             final ActivityInfo activityInfo = resolveInfo.activityInfo;
    376             if (activityInfo == null) {
    377                 continue;
    378             }
    379             final String packageName = activityInfo.packageName;
    380             final SmsApplicationData smsApplicationData = receivers.get(packageName);
    381             if (DEBUG_MULTIUSER) {
    382                 Log.i(LOG_TAG, "getApplicationCollectionInternal packageName=" +
    383                         packageName + " smsApplicationData: " + smsApplicationData +
    384                         " activityInfo.name: " + activityInfo.name);
    385             }
    386             if (smsApplicationData != null) {
    387                 smsApplicationData.mProviderChangedReceiverClass = activityInfo.name;
    388             }
    389         }
    390 
    391         // Update any existing entries with the sim full handler.
    392         intent = new Intent(Intents.SIM_FULL_ACTION);
    393         List<ResolveInfo> simFullReceivers =
    394                 packageManager.queryBroadcastReceiversAsUser(intent,
    395                         PackageManager.MATCH_DIRECT_BOOT_AWARE
    396                                 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE, userId);
    397         if (DEBUG_MULTIUSER) {
    398             Log.i(LOG_TAG, "getApplicationCollectionInternal simFullReceivers="
    399                     + simFullReceivers);
    400         }
    401         for (ResolveInfo resolveInfo : simFullReceivers) {
    402             final ActivityInfo activityInfo = resolveInfo.activityInfo;
    403             if (activityInfo == null) {
    404                 continue;
    405             }
    406             final String packageName = activityInfo.packageName;
    407             final SmsApplicationData smsApplicationData = receivers.get(packageName);
    408             if (DEBUG_MULTIUSER) {
    409                 Log.i(LOG_TAG, "getApplicationCollectionInternal packageName="
    410                         + packageName + " smsApplicationData: " + smsApplicationData
    411                         + " activityInfo.name: " + activityInfo.name);
    412             }
    413             if (smsApplicationData != null) {
    414                 smsApplicationData.mSimFullReceiverClass = activityInfo.name;
    415             }
    416         }
    417 
    418         // Remove any entries for which we did not find all required intents.
    419         for (ResolveInfo resolveInfo : smsReceivers) {
    420             final ActivityInfo activityInfo = resolveInfo.activityInfo;
    421             if (activityInfo == null) {
    422                 continue;
    423             }
    424             final String packageName = activityInfo.packageName;
    425             final SmsApplicationData smsApplicationData = receivers.get(packageName);
    426             if (smsApplicationData != null) {
    427                 if (!smsApplicationData.isComplete()) {
    428                     Log.w(LOG_TAG, "Package " + packageName
    429                             + " lacks required manifest declarations to be a default sms app: "
    430                             + smsApplicationData);
    431                     receivers.remove(packageName);
    432                 }
    433             }
    434         }
    435         return receivers.values();
    436     }
    437 
    438     /**
    439      * Checks to see if we have a valid installed SMS application for the specified package name
    440      * @return Data for the specified package name or null if there isn't one
    441      */
    442     public static SmsApplicationData getApplicationForPackage(
    443             Collection<SmsApplicationData> applications, String packageName) {
    444         if (packageName == null) {
    445             return null;
    446         }
    447         // Is there an entry in the application list for the specified package?
    448         for (SmsApplicationData application : applications) {
    449             if (application.mPackageName.contentEquals(packageName)) {
    450                 return application;
    451             }
    452         }
    453         return null;
    454     }
    455 
    456     /**
    457      * Get the application we will use for delivering SMS/MMS messages.
    458      *
    459      * We return the preferred sms application with the following order of preference:
    460      * (1) User selected SMS app (if selected, and if still valid)
    461      * (2) Android Messaging (if installed)
    462      * (3) The currently configured highest priority broadcast receiver
    463      * (4) Null
    464      */
    465     private static SmsApplicationData getApplication(Context context, boolean updateIfNeeded,
    466             int userId) {
    467         TelephonyManager tm = (TelephonyManager)
    468                 context.getSystemService(Context.TELEPHONY_SERVICE);
    469         RoleManager roleManager = (RoleManager) context.getSystemService(Context.ROLE_SERVICE);
    470         // (b/134400042) RoleManager might be null in unit tests running older mockito versions
    471         // that do not support mocking final classes.
    472         if (!tm.isSmsCapable() && (roleManager == null || !roleManager.isRoleAvailable(
    473                 RoleManager.ROLE_SMS))) {
    474             // No phone, no SMS
    475             return null;
    476         }
    477 
    478         Collection<SmsApplicationData> applications = getApplicationCollectionInternal(context,
    479                 userId);
    480         if (DEBUG_MULTIUSER) {
    481             Log.i(LOG_TAG, "getApplication userId=" + userId);
    482         }
    483         // Determine which application receives the broadcast
    484         String defaultApplication = getDefaultSmsPackage(context, userId);
    485         if (DEBUG_MULTIUSER) {
    486             Log.i(LOG_TAG, "getApplication defaultApp=" + defaultApplication);
    487         }
    488 
    489         SmsApplicationData applicationData = null;
    490         if (defaultApplication != null) {
    491             applicationData = getApplicationForPackage(applications, defaultApplication);
    492         }
    493         if (DEBUG_MULTIUSER) {
    494             Log.i(LOG_TAG, "getApplication appData=" + applicationData);
    495         }
    496 
    497         // If we found a package, make sure AppOps permissions are set up correctly
    498         if (applicationData != null) {
    499             // We can only call checkOp if we are privileged (updateIfNeeded) or if the app we
    500             // are checking is for our current uid. Doing this check from the unprivileged current
    501             // SMS app allows us to tell the current SMS app that it is not in a good state and
    502             // needs to ask to be the current SMS app again to work properly.
    503             if (updateIfNeeded || applicationData.mUid == android.os.Process.myUid()) {
    504                 // Verify that the SMS app has permissions
    505                 boolean appOpsFixed =
    506                         tryFixExclusiveSmsAppops(context, applicationData, updateIfNeeded);
    507                 if (!appOpsFixed) {
    508                     // We can not return a package if permissions are not set up correctly
    509                     applicationData = null;
    510                 }
    511             }
    512 
    513             // We can only verify the phone and BT app's permissions from a privileged caller
    514             if (applicationData != null && updateIfNeeded) {
    515                 // Ensure this component is still configured as the preferred activity. Usually the
    516                 // current SMS app will already be the preferred activity - but checking whether or
    517                 // not this is true is just as expensive as reconfiguring the preferred activity so
    518                 // we just reconfigure every time.
    519                 defaultSmsAppChanged(context);
    520             }
    521         }
    522         if (DEBUG_MULTIUSER) {
    523             Log.i(LOG_TAG, "getApplication returning appData=" + applicationData);
    524         }
    525         return applicationData;
    526     }
    527 
    528     private static String getDefaultSmsPackage(Context context, int userId) {
    529         return context.getSystemService(RoleManager.class).getDefaultSmsPackage(userId);
    530     }
    531 
    532     /**
    533      * Grants various permissions and appops on sms app change
    534      */
    535     private static void defaultSmsAppChanged(Context context) {
    536         PackageManager packageManager = context.getPackageManager();
    537         AppOpsManager appOps = context.getSystemService(AppOpsManager.class);
    538 
    539         // Assign permission to special system apps
    540         assignExclusiveSmsPermissionsToSystemApp(context, packageManager, appOps,
    541                 PHONE_PACKAGE_NAME);
    542         assignExclusiveSmsPermissionsToSystemApp(context, packageManager, appOps,
    543                 BLUETOOTH_PACKAGE_NAME);
    544         assignExclusiveSmsPermissionsToSystemApp(context, packageManager, appOps,
    545                 MMS_SERVICE_PACKAGE_NAME);
    546         assignExclusiveSmsPermissionsToSystemApp(context, packageManager, appOps,
    547                 TELEPHONY_PROVIDER_PACKAGE_NAME);
    548 
    549         // Give AppOps permission to UID 1001 which contains multiple
    550         // apps, all of them should be able to write to telephony provider.
    551         // This is to allow the proxy package permission check in telephony provider
    552         // to pass.
    553         for (int appop : DEFAULT_APP_EXCLUSIVE_APPOPS) {
    554             appOps.setUidMode(appop, Process.PHONE_UID, AppOpsManager.MODE_ALLOWED);
    555         }
    556     }
    557 
    558     private static boolean tryFixExclusiveSmsAppops(Context context,
    559             SmsApplicationData applicationData, boolean updateIfNeeded) {
    560         AppOpsManager appOps = context.getSystemService(AppOpsManager.class);
    561         for (int appOp : DEFAULT_APP_EXCLUSIVE_APPOPS) {
    562             int mode = appOps.checkOp(appOp, applicationData.mUid,
    563                     applicationData.mPackageName);
    564             if (mode != AppOpsManager.MODE_ALLOWED) {
    565                 Rlog.e(LOG_TAG, applicationData.mPackageName + " lost "
    566                         + AppOpsManager.modeToName(appOp) + ": "
    567                         + (updateIfNeeded ? " (fixing)" : " (no permission to fix)"));
    568                 if (updateIfNeeded) {
    569                     appOps.setUidMode(appOp, applicationData.mUid, AppOpsManager.MODE_ALLOWED);
    570                 } else {
    571                     return false;
    572                 }
    573             }
    574         }
    575         return true;
    576     }
    577 
    578     /**
    579      * Sets the specified package as the default SMS/MMS application. The caller of this method
    580      * needs to have permission to set AppOps and write to secure settings.
    581      */
    582     public static void setDefaultApplication(String packageName, Context context) {
    583         setDefaultApplicationAsUser(packageName, context, getIncomingUserId(context));
    584     }
    585 
    586     /**
    587      * Same as {@link #setDefaultApplication} but takes a target user id.
    588      */
    589     public static void setDefaultApplicationAsUser(String packageName, Context context,
    590             int userId) {
    591         TelephonyManager tm = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
    592         RoleManager roleManager = (RoleManager) context.getSystemService(Context.ROLE_SERVICE);
    593         // (b/134400042) RoleManager might be null in unit tests running older mockito versions
    594         // that do not support mocking final classes.
    595         if (!tm.isSmsCapable() && (roleManager == null || !roleManager.isRoleAvailable(
    596                 RoleManager.ROLE_SMS))) {
    597             // No phone, no SMS
    598             return;
    599         }
    600 
    601         final long token = Binder.clearCallingIdentity();
    602         try {
    603             setDefaultApplicationInternal(packageName, context, userId);
    604         } finally {
    605             Binder.restoreCallingIdentity(token);
    606         }
    607     }
    608 
    609     private static void setDefaultApplicationInternal(String packageName, Context context,
    610             int userId) {
    611         final UserHandle userHandle = UserHandle.of(userId);
    612 
    613         // Get old package name
    614         String oldPackageName = getDefaultSmsPackage(context, userId);
    615 
    616         if (DEBUG_MULTIUSER) {
    617             Log.i(LOG_TAG, "setDefaultApplicationInternal old=" + oldPackageName +
    618                     " new=" + packageName);
    619         }
    620 
    621         if (packageName != null && oldPackageName != null && packageName.equals(oldPackageName)) {
    622             // No change
    623             return;
    624         }
    625 
    626         // We only make the change if the new package is valid
    627         PackageManager packageManager = context.getPackageManager();
    628         Collection<SmsApplicationData> applications = getApplicationCollectionInternal(
    629                 context, userId);
    630         SmsApplicationData oldAppData = oldPackageName != null ?
    631                 getApplicationForPackage(applications, oldPackageName) : null;
    632         SmsApplicationData applicationData = getApplicationForPackage(applications, packageName);
    633         if (applicationData != null) {
    634             // Ignore relevant appops for the previously configured default SMS app.
    635             AppOpsManager appOps = (AppOpsManager)context.getSystemService(Context.APP_OPS_SERVICE);
    636             if (oldPackageName != null) {
    637                 try {
    638                     int uid = packageManager.getPackageInfoAsUser(
    639                             oldPackageName, 0, userId).applicationInfo.uid;
    640                     setExclusiveAppops(oldPackageName, appOps, uid, AppOpsManager.MODE_DEFAULT);
    641                 } catch (NameNotFoundException e) {
    642                     Rlog.w(LOG_TAG, "Old SMS package not found: " + oldPackageName);
    643                 }
    644             }
    645 
    646             // Update the setting.
    647             CompletableFuture<Void> future = new CompletableFuture<>();
    648             Consumer<Boolean> callback = successful -> {
    649                 if (successful) {
    650                     future.complete(null);
    651                 } else {
    652                     future.completeExceptionally(new RuntimeException());
    653                 }
    654             };
    655             context.getSystemService(RoleManager.class).addRoleHolderAsUser(
    656                     RoleManager.ROLE_SMS, applicationData.mPackageName, 0, UserHandle.of(userId),
    657                     AsyncTask.THREAD_POOL_EXECUTOR, callback);
    658             try {
    659                 future.get(5, TimeUnit.SECONDS);
    660             } catch (InterruptedException | ExecutionException | TimeoutException e) {
    661                 Log.e(LOG_TAG, "Exception while adding sms role holder " + applicationData, e);
    662                 return;
    663             }
    664 
    665             defaultSmsAppChanged(context);
    666         }
    667     }
    668 
    669     /**
    670      * Sends broadcasts on sms app change:
    671      * {@link Intent#ACTION_DEFAULT_SMS_PACKAGE_CHANGED}
    672      * {@link Intents.ACTION_DEFAULT_SMS_PACKAGE_CHANGED_INTERNAL}
    673      */
    674     public static void broadcastSmsAppChange(Context context,
    675             UserHandle userHandle, @Nullable String oldPackage, @Nullable String newPackage) {
    676         Collection<SmsApplicationData> apps = getApplicationCollection(context);
    677 
    678         broadcastSmsAppChange(context, userHandle,
    679                 getApplicationForPackage(apps, oldPackage),
    680                 getApplicationForPackage(apps, newPackage));
    681     }
    682 
    683     private static void broadcastSmsAppChange(Context context, UserHandle userHandle,
    684             @Nullable SmsApplicationData oldAppData,
    685             @Nullable SmsApplicationData applicationData) {
    686         if (DEBUG_MULTIUSER) {
    687             Log.i(LOG_TAG, "setDefaultApplicationInternal oldAppData=" + oldAppData);
    688         }
    689         if (oldAppData != null && oldAppData.mSmsAppChangedReceiverClass != null) {
    690             // Notify the old sms app that it's no longer the default
    691             final Intent oldAppIntent =
    692                     new Intent(Intents.ACTION_DEFAULT_SMS_PACKAGE_CHANGED);
    693             final ComponentName component = new ComponentName(oldAppData.mPackageName,
    694                     oldAppData.mSmsAppChangedReceiverClass);
    695             oldAppIntent.setComponent(component);
    696             oldAppIntent.putExtra(Intents.EXTRA_IS_DEFAULT_SMS_APP, false);
    697             if (DEBUG_MULTIUSER) {
    698                 Log.i(LOG_TAG, "setDefaultApplicationInternal old=" + oldAppData.mPackageName);
    699             }
    700             context.sendBroadcastAsUser(oldAppIntent, userHandle);
    701         }
    702         // Notify the new sms app that it's now the default (if the new sms app has a receiver
    703         // to handle the changed default sms intent).
    704         if (DEBUG_MULTIUSER) {
    705             Log.i(LOG_TAG, "setDefaultApplicationInternal new applicationData=" +
    706                     applicationData);
    707         }
    708         if (applicationData != null && applicationData.mSmsAppChangedReceiverClass != null) {
    709             final Intent intent =
    710                     new Intent(Intents.ACTION_DEFAULT_SMS_PACKAGE_CHANGED);
    711             final ComponentName component = new ComponentName(applicationData.mPackageName,
    712                     applicationData.mSmsAppChangedReceiverClass);
    713             intent.setComponent(component);
    714             intent.putExtra(Intents.EXTRA_IS_DEFAULT_SMS_APP, true);
    715             if (DEBUG_MULTIUSER) {
    716                 Log.i(LOG_TAG, "setDefaultApplicationInternal new=" + applicationData.mPackageName);
    717             }
    718             context.sendBroadcastAsUser(intent, userHandle);
    719         }
    720 
    721         // Send an implicit broadcast for the system server.
    722         // (or anyone with MONITOR_DEFAULT_SMS_PACKAGE, really.)
    723         final Intent intent =
    724                 new Intent(Intents.ACTION_DEFAULT_SMS_PACKAGE_CHANGED_INTERNAL);
    725         context.sendBroadcastAsUser(intent, userHandle,
    726                 permission.MONITOR_DEFAULT_SMS_PACKAGE);
    727 
    728         if (applicationData != null) {
    729             MetricsLogger.action(context, MetricsEvent.ACTION_DEFAULT_SMS_APP_CHANGED,
    730                     applicationData.mPackageName);
    731         }
    732     }
    733 
    734     /**
    735      * Assign WRITE_SMS AppOps permission to some special system apps.
    736      *
    737      * @param context The context
    738      * @param packageManager The package manager instance
    739      * @param appOps The AppOps manager instance
    740      * @param packageName The package name of the system app
    741      */
    742     private static void assignExclusiveSmsPermissionsToSystemApp(Context context,
    743             PackageManager packageManager, AppOpsManager appOps, String packageName) {
    744         // First check package signature matches the caller's package signature.
    745         // Since this class is only used internally by the system, this check makes sure
    746         // the package signature matches system signature.
    747         final int result = packageManager.checkSignatures(context.getPackageName(), packageName);
    748         if (result != PackageManager.SIGNATURE_MATCH) {
    749             Rlog.e(LOG_TAG, packageName + " does not have system signature");
    750             return;
    751         }
    752         try {
    753             PackageInfo info = packageManager.getPackageInfo(packageName, 0);
    754             int mode = appOps.checkOp(AppOpsManager.OP_WRITE_SMS, info.applicationInfo.uid,
    755                     packageName);
    756             if (mode != AppOpsManager.MODE_ALLOWED) {
    757                 Rlog.w(LOG_TAG, packageName + " does not have OP_WRITE_SMS:  (fixing)");
    758                 setExclusiveAppops(packageName, appOps, info.applicationInfo.uid,
    759                         AppOpsManager.MODE_ALLOWED);
    760             }
    761         } catch (NameNotFoundException e) {
    762             // No whitelisted system app on this device
    763             Rlog.e(LOG_TAG, "Package not found: " + packageName);
    764         }
    765 
    766     }
    767 
    768     private static void setExclusiveAppops(String pkg, AppOpsManager appOpsManager, int uid,
    769             int mode) {
    770         for (int appop : DEFAULT_APP_EXCLUSIVE_APPOPS) {
    771             appOpsManager.setUidMode(appop, uid, mode);
    772         }
    773     }
    774 
    775     /**
    776      * Tracks package changes and ensures that the default SMS app is always configured to be the
    777      * preferred activity for SENDTO sms/mms intents.
    778      */
    779     private static final class SmsPackageMonitor extends PackageMonitor {
    780         final Context mContext;
    781 
    782         public SmsPackageMonitor(Context context) {
    783             super();
    784             mContext = context;
    785         }
    786 
    787         @Override
    788         public void onPackageDisappeared(String packageName, int reason) {
    789             onPackageChanged();
    790         }
    791 
    792         @Override
    793         public void onPackageAppeared(String packageName, int reason) {
    794             onPackageChanged();
    795         }
    796 
    797         @Override
    798         public void onPackageModified(String packageName) {
    799             onPackageChanged();
    800         }
    801 
    802         private void onPackageChanged() {
    803             PackageManager packageManager = mContext.getPackageManager();
    804             Context userContext = mContext;
    805             final int userId = getSendingUserId();
    806             if (userId != UserHandle.USER_SYSTEM) {
    807                 try {
    808                     userContext = mContext.createPackageContextAsUser(mContext.getPackageName(), 0,
    809                             new UserHandle(userId));
    810                 } catch (NameNotFoundException nnfe) {
    811                     if (DEBUG_MULTIUSER) {
    812                         Log.w(LOG_TAG, "Unable to create package context for user " + userId);
    813                     }
    814                 }
    815             }
    816             // Ensure this component is still configured as the preferred activity
    817             ComponentName componentName = getDefaultSendToApplication(userContext, true);
    818             if (componentName != null) {
    819                 configurePreferredActivity(packageManager, componentName, userId);
    820             }
    821         }
    822     }
    823 
    824     public static void initSmsPackageMonitor(Context context) {
    825         sSmsPackageMonitor = new SmsPackageMonitor(context);
    826         sSmsPackageMonitor.register(context, context.getMainLooper(), UserHandle.ALL, false);
    827     }
    828 
    829     private static void configurePreferredActivity(PackageManager packageManager,
    830             ComponentName componentName, int userId) {
    831         // Add the four activity preferences we want to direct to this app.
    832         replacePreferredActivity(packageManager, componentName, userId, SCHEME_SMS);
    833         replacePreferredActivity(packageManager, componentName, userId, SCHEME_SMSTO);
    834         replacePreferredActivity(packageManager, componentName, userId, SCHEME_MMS);
    835         replacePreferredActivity(packageManager, componentName, userId, SCHEME_MMSTO);
    836     }
    837 
    838     /**
    839      * Updates the ACTION_SENDTO activity to the specified component for the specified scheme.
    840      */
    841     private static void replacePreferredActivity(PackageManager packageManager,
    842             ComponentName componentName, int userId, String scheme) {
    843         // Build the set of existing activities that handle this scheme
    844         Intent intent = new Intent(Intent.ACTION_SENDTO, Uri.fromParts(scheme, "", null));
    845         List<ResolveInfo> resolveInfoList = packageManager.queryIntentActivitiesAsUser(
    846                 intent, PackageManager.MATCH_DEFAULT_ONLY | PackageManager.GET_RESOLVED_FILTER,
    847                 userId);
    848 
    849         // Build the set of ComponentNames for these activities
    850         final int n = resolveInfoList.size();
    851         ComponentName[] set = new ComponentName[n];
    852         for (int i = 0; i < n; i++) {
    853             ResolveInfo info = resolveInfoList.get(i);
    854             set[i] = new ComponentName(info.activityInfo.packageName, info.activityInfo.name);
    855         }
    856 
    857         // Update the preferred SENDTO activity for the specified scheme
    858         IntentFilter intentFilter = new IntentFilter();
    859         intentFilter.addAction(Intent.ACTION_SENDTO);
    860         intentFilter.addCategory(Intent.CATEGORY_DEFAULT);
    861         intentFilter.addDataScheme(scheme);
    862         packageManager.replacePreferredActivityAsUser(intentFilter,
    863                 IntentFilter.MATCH_CATEGORY_SCHEME + IntentFilter.MATCH_ADJUSTMENT_NORMAL,
    864                 set, componentName, userId);
    865     }
    866 
    867     /**
    868      * Returns SmsApplicationData for this package if this package is capable of being set as the
    869      * default SMS application.
    870      */
    871     public static SmsApplicationData getSmsApplicationData(String packageName, Context context) {
    872         Collection<SmsApplicationData> applications = getApplicationCollection(context);
    873         return getApplicationForPackage(applications, packageName);
    874     }
    875 
    876     /**
    877      * Gets the default SMS application
    878      * @param context context from the calling app
    879      * @param updateIfNeeded update the default app if there is no valid default app configured.
    880      * @return component name of the app and class to deliver SMS messages to
    881      */
    882     public static ComponentName getDefaultSmsApplication(Context context, boolean updateIfNeeded) {
    883         return getDefaultSmsApplicationAsUser(context, updateIfNeeded, getIncomingUserId(context));
    884     }
    885 
    886     /**
    887      * Gets the default SMS application on a given user
    888      * @param context context from the calling app
    889      * @param updateIfNeeded update the default app if there is no valid default app configured.
    890      * @param userId target user ID.
    891      * @return component name of the app and class to deliver SMS messages to
    892      */
    893     public static ComponentName getDefaultSmsApplicationAsUser(Context context,
    894             boolean updateIfNeeded, int userId) {
    895         final long token = Binder.clearCallingIdentity();
    896         try {
    897             ComponentName component = null;
    898             SmsApplicationData smsApplicationData = getApplication(context, updateIfNeeded,
    899                     userId);
    900             if (smsApplicationData != null) {
    901                 component = new ComponentName(smsApplicationData.mPackageName,
    902                         smsApplicationData.mSmsReceiverClass);
    903             }
    904             return component;
    905         } finally {
    906             Binder.restoreCallingIdentity(token);
    907         }
    908     }
    909 
    910     /**
    911      * Gets the default MMS application
    912      * @param context context from the calling app
    913      * @param updateIfNeeded update the default app if there is no valid default app configured.
    914      * @return component name of the app and class to deliver MMS messages to
    915      */
    916     public static ComponentName getDefaultMmsApplication(Context context, boolean updateIfNeeded) {
    917         int userId = getIncomingUserId(context);
    918         final long token = Binder.clearCallingIdentity();
    919         try {
    920             ComponentName component = null;
    921             SmsApplicationData smsApplicationData = getApplication(context, updateIfNeeded,
    922                     userId);
    923             if (smsApplicationData != null) {
    924                 component = new ComponentName(smsApplicationData.mPackageName,
    925                         smsApplicationData.mMmsReceiverClass);
    926             }
    927             return component;
    928         } finally {
    929             Binder.restoreCallingIdentity(token);
    930         }
    931     }
    932 
    933     /**
    934      * Gets the default Respond Via Message application
    935      * @param context context from the calling app
    936      * @param updateIfNeeded update the default app if there is no valid default app configured.
    937      * @return component name of the app and class to direct Respond Via Message intent to
    938      */
    939     public static ComponentName getDefaultRespondViaMessageApplication(Context context,
    940             boolean updateIfNeeded) {
    941         int userId = getIncomingUserId(context);
    942         final long token = Binder.clearCallingIdentity();
    943         try {
    944             ComponentName component = null;
    945             SmsApplicationData smsApplicationData = getApplication(context, updateIfNeeded,
    946                     userId);
    947             if (smsApplicationData != null) {
    948                 component = new ComponentName(smsApplicationData.mPackageName,
    949                         smsApplicationData.mRespondViaMessageClass);
    950             }
    951             return component;
    952         } finally {
    953             Binder.restoreCallingIdentity(token);
    954         }
    955     }
    956 
    957     /**
    958      * Gets the default Send To (smsto) application.
    959      * <p>
    960      * Caller must pass in the correct user context if calling from a singleton service.
    961      * @param context context from the calling app
    962      * @param updateIfNeeded update the default app if there is no valid default app configured.
    963      * @return component name of the app and class to direct SEND_TO (smsto) intent to
    964      */
    965     public static ComponentName getDefaultSendToApplication(Context context,
    966             boolean updateIfNeeded) {
    967         int userId = getIncomingUserId(context);
    968         final long token = Binder.clearCallingIdentity();
    969         try {
    970             ComponentName component = null;
    971             SmsApplicationData smsApplicationData = getApplication(context, updateIfNeeded,
    972                     userId);
    973             if (smsApplicationData != null) {
    974                 component = new ComponentName(smsApplicationData.mPackageName,
    975                         smsApplicationData.mSendToClass);
    976             }
    977             return component;
    978         } finally {
    979             Binder.restoreCallingIdentity(token);
    980         }
    981     }
    982 
    983     /**
    984      * Gets the default application that handles external changes to the SmsProvider and
    985      * MmsProvider.
    986      * @param context context from the calling app
    987      * @param updateIfNeeded update the default app if there is no valid default app configured.
    988      * @return component name of the app and class to deliver change intents to
    989      */
    990     public static ComponentName getDefaultExternalTelephonyProviderChangedApplication(
    991             Context context, boolean updateIfNeeded) {
    992         int userId = getIncomingUserId(context);
    993         final long token = Binder.clearCallingIdentity();
    994         try {
    995             ComponentName component = null;
    996             SmsApplicationData smsApplicationData = getApplication(context, updateIfNeeded,
    997                     userId);
    998             if (smsApplicationData != null
    999                     && smsApplicationData.mProviderChangedReceiverClass != null) {
   1000                 component = new ComponentName(smsApplicationData.mPackageName,
   1001                         smsApplicationData.mProviderChangedReceiverClass);
   1002             }
   1003             return component;
   1004         } finally {
   1005             Binder.restoreCallingIdentity(token);
   1006         }
   1007     }
   1008 
   1009     /**
   1010      * Gets the default application that handles sim full event.
   1011      * @param context context from the calling app
   1012      * @param updateIfNeeded update the default app if there is no valid default app configured.
   1013      * @return component name of the app and class to deliver change intents to
   1014      */
   1015     public static ComponentName getDefaultSimFullApplication(
   1016             Context context, boolean updateIfNeeded) {
   1017         int userId = getIncomingUserId(context);
   1018         final long token = Binder.clearCallingIdentity();
   1019         try {
   1020             ComponentName component = null;
   1021             SmsApplicationData smsApplicationData = getApplication(context, updateIfNeeded,
   1022                     userId);
   1023             if (smsApplicationData != null
   1024                     && smsApplicationData.mSimFullReceiverClass != null) {
   1025                 component = new ComponentName(smsApplicationData.mPackageName,
   1026                         smsApplicationData.mSimFullReceiverClass);
   1027             }
   1028             return component;
   1029         } finally {
   1030             Binder.restoreCallingIdentity(token);
   1031         }
   1032     }
   1033 
   1034     /**
   1035      * Returns whether need to write the SMS message to SMS database for this package.
   1036      * <p>
   1037      * Caller must pass in the correct user context if calling from a singleton service.
   1038      */
   1039     public static boolean shouldWriteMessageForPackage(String packageName, Context context) {
   1040         if (SmsManager.getDefault().getAutoPersisting()) {
   1041             return true;
   1042         }
   1043         return !isDefaultSmsApplication(context, packageName);
   1044     }
   1045 
   1046     /**
   1047      * Check if a package is default sms app (or equivalent, like bluetooth)
   1048      *
   1049      * @param context context from the calling app
   1050      * @param packageName the name of the package to be checked
   1051      * @return true if the package is default sms app or bluetooth
   1052      */
   1053     public static boolean isDefaultSmsApplication(Context context, String packageName) {
   1054         if (packageName == null) {
   1055             return false;
   1056         }
   1057         final String defaultSmsPackage = getDefaultSmsApplicationPackageName(context);
   1058         if ((defaultSmsPackage != null && defaultSmsPackage.equals(packageName))
   1059                 || BLUETOOTH_PACKAGE_NAME.equals(packageName)) {
   1060             return true;
   1061         }
   1062         return false;
   1063     }
   1064 
   1065     private static String getDefaultSmsApplicationPackageName(Context context) {
   1066         final ComponentName component = getDefaultSmsApplication(context, false);
   1067         if (component != null) {
   1068             return component.getPackageName();
   1069         }
   1070         return null;
   1071     }
   1072 }
   1073