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.NonNull;
21 import android.annotation.Nullable;
22 import android.app.AppOpsManager;
23 import android.app.role.OnRoleHoldersChangedListener;
24 import android.app.role.RoleManager;
25 import android.compat.annotation.UnsupportedAppUsage;
26 import android.content.ComponentName;
27 import android.content.Context;
28 import android.content.Intent;
29 import android.content.IntentFilter;
30 import android.content.pm.ActivityInfo;
31 import android.content.pm.ApplicationInfo;
32 import android.content.pm.PackageInfo;
33 import android.content.pm.PackageManager;
34 import android.content.pm.PackageManager.NameNotFoundException;
35 import android.content.pm.ResolveInfo;
36 import android.content.pm.ServiceInfo;
37 import android.net.Uri;
38 import android.os.AsyncTask;
39 import android.os.Binder;
40 import android.os.Build;
41 import android.os.Process;
42 import android.os.UserHandle;
43 import android.os.UserManager;
44 import android.provider.Telephony;
45 import android.provider.Telephony.Sms.Intents;
46 import android.telephony.TelephonyManager;
47 import android.util.Log;
48 import android.util.SparseArray;
49 
50 import com.android.internal.annotations.VisibleForTesting;
51 
52 import java.util.Collection;
53 import java.util.HashMap;
54 import java.util.List;
55 import java.util.Objects;
56 import java.util.concurrent.CompletableFuture;
57 import java.util.concurrent.ExecutionException;
58 import java.util.concurrent.TimeUnit;
59 import java.util.concurrent.TimeoutException;
60 import java.util.function.Consumer;
61 import java.util.stream.Collectors;
62 
63 /**
64  * Class for managing the primary application that we will deliver SMS/MMS messages to
65  *
66  * {@hide}
67  */
68 public final class SmsApplication {
69     static final String LOG_TAG = "SmsApplication";
70     public static final String PHONE_PACKAGE_NAME = "com.android.phone";
71     public static final String MMS_SERVICE_PACKAGE_NAME = "com.android.mms.service";
72     public static final String TELEPHONY_PROVIDER_PACKAGE_NAME = "com.android.providers.telephony";
73 
74     private static final String SCHEME_SMS = "sms";
75     private static final String SCHEME_SMSTO = "smsto";
76     private static final String SCHEME_MMS = "mms";
77     private static final String SCHEME_MMSTO = "mmsto";
78     private static final boolean DEBUG = false;
79     private static final boolean DEBUG_MULTIUSER = false;
80 
81     private static final String[] DEFAULT_APP_EXCLUSIVE_APPOPS = {
82             AppOpsManager.OPSTR_READ_SMS,
83             AppOpsManager.OPSTR_WRITE_SMS,
84             AppOpsManager.OPSTR_RECEIVE_SMS,
85             AppOpsManager.OPSTR_RECEIVE_WAP_PUSH,
86             AppOpsManager.OPSTR_SEND_SMS,
87             AppOpsManager.OPSTR_READ_CELL_BROADCASTS
88     };
89 
90     private static SmsPackageMonitor sSmsPackageMonitor = null;
91 
92     private static SmsRoleListener sSmsRoleListener = null;
93 
94     public static class SmsApplicationData {
95         /**
96          * Name of this SMS app for display.
97          */
98         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
99         private String mApplicationName;
100 
101         /**
102          * Package name for this SMS app.
103          */
104         public String mPackageName;
105 
106         /**
107          * The class name of the SMS_DELIVER_ACTION receiver in this app.
108          */
109         private String mSmsReceiverClass;
110 
111         /**
112          * The class name of the WAP_PUSH_DELIVER_ACTION receiver in this app.
113          */
114         private String mMmsReceiverClass;
115 
116         /**
117          * The class name of the ACTION_RESPOND_VIA_MESSAGE intent in this app.
118          */
119         private String mRespondViaMessageClass;
120 
121         /**
122          * The class name of the ACTION_SENDTO intent in this app.
123          */
124         private String mSendToClass;
125 
126         /**
127          * The class name of the ACTION_DEFAULT_SMS_PACKAGE_CHANGED receiver in this app.
128          */
129         private String mSmsAppChangedReceiverClass;
130 
131         /**
132          * The class name of the ACTION_EXTERNAL_PROVIDER_CHANGE receiver in this app.
133          */
134         private String mProviderChangedReceiverClass;
135 
136         /**
137          * The class name of the SIM_FULL_ACTION receiver in this app.
138          */
139         private String mSimFullReceiverClass;
140 
141         /**
142          * The user-id for this application
143          */
144         private int mUid;
145 
146         /**
147          * Returns true if this SmsApplicationData is complete (all intents handled).
148          * @return
149          */
isComplete()150         public boolean isComplete() {
151             return (mSmsReceiverClass != null && mMmsReceiverClass != null
152                     && mRespondViaMessageClass != null && mSendToClass != null);
153         }
154 
SmsApplicationData(String packageName, int uid)155         public SmsApplicationData(String packageName, int uid) {
156             mPackageName = packageName;
157             mUid = uid;
158         }
159 
getApplicationName(Context context)160         public String getApplicationName(Context context) {
161             if (mApplicationName == null) {
162                 PackageManager pm = context.getPackageManager();
163                 ApplicationInfo appInfo;
164                 try {
165                     appInfo = pm.getApplicationInfoAsUser(mPackageName, 0,
166                             UserHandle.getUserHandleForUid(mUid));
167                 } catch (NameNotFoundException e) {
168                     return null;
169                 }
170                 if (appInfo != null) {
171                     CharSequence label  = pm.getApplicationLabel(appInfo);
172                     mApplicationName = (label == null) ? null : label.toString();
173                 }
174             }
175             return mApplicationName;
176         }
177 
178         @Override
toString()179         public String toString() {
180             return " mPackageName: " + mPackageName
181                     + " mSmsReceiverClass: " + mSmsReceiverClass
182                     + " mMmsReceiverClass: " + mMmsReceiverClass
183                     + " mRespondViaMessageClass: " + mRespondViaMessageClass
184                     + " mSendToClass: " + mSendToClass
185                     + " mSmsAppChangedClass: " + mSmsAppChangedReceiverClass
186                     + " mProviderChangedReceiverClass: " + mProviderChangedReceiverClass
187                     + " mSimFullReceiverClass: " + mSimFullReceiverClass
188                     + " mUid: " + mUid;
189         }
190     }
191 
192     /**
193      * Returns the userId of the current process, if called from a system app,
194      * otherwise it returns the caller's userId
195      * @return userId of the caller.
196      */
getIncomingUserId()197     private static int getIncomingUserId() {
198         int contextUserId = UserHandle.myUserId();
199         final int callingUid = Binder.getCallingUid();
200         if (DEBUG_MULTIUSER) {
201             Log.i(LOG_TAG, "getIncomingUserHandle caller=" + callingUid + ", myuid="
202                     + android.os.Process.myUid());
203         }
204         if (UserHandle.getAppId(callingUid)
205                 < android.os.Process.FIRST_APPLICATION_UID) {
206             return contextUserId;
207         } else {
208             return UserHandle.getUserHandleForUid(callingUid).getIdentifier();
209         }
210     }
211 
212     /**
213      * Returns the userHandle of the current process, if called from a system app,
214      * otherwise it returns the caller's userHandle
215      * @return userHandle of the caller.
216      */
getIncomingUserHandle()217     private static UserHandle getIncomingUserHandle() {
218         return UserHandle.of(getIncomingUserId());
219     }
220 
221     /**
222      * Returns the list of available SMS apps defined as apps that are registered for both the
223      * SMS_RECEIVED_ACTION (SMS) and WAP_PUSH_RECEIVED_ACTION (MMS) broadcasts (and their broadcast
224      * receivers are enabled)
225      *
226      * Requirements to be an SMS application:
227      * Implement SMS_DELIVER_ACTION broadcast receiver.
228      * Require BROADCAST_SMS permission.
229      *
230      * Implement WAP_PUSH_DELIVER_ACTION broadcast receiver.
231      * Require BROADCAST_WAP_PUSH permission.
232      *
233      * Implement RESPOND_VIA_MESSAGE intent.
234      * Support smsto Uri scheme.
235      * Require SEND_RESPOND_VIA_MESSAGE permission.
236      *
237      * Implement ACTION_SENDTO intent.
238      * Support smsto Uri scheme.
239      */
240     @UnsupportedAppUsage
getApplicationCollection(Context context)241     public static Collection<SmsApplicationData> getApplicationCollection(Context context) {
242         return getApplicationCollectionAsUser(context, getIncomingUserId());
243     }
244 
245     /**
246      * Same as {@link #getApplicationCollection} but it takes a target user ID.
247      */
getApplicationCollectionAsUser(Context context, int userId)248     public static Collection<SmsApplicationData> getApplicationCollectionAsUser(Context context,
249             int userId) {
250         final long token = Binder.clearCallingIdentity();
251         try {
252             return getApplicationCollectionInternal(context, userId);
253         } finally {
254             Binder.restoreCallingIdentity(token);
255         }
256     }
257 
getApplicationCollectionInternal( Context context, int userId)258     private static Collection<SmsApplicationData> getApplicationCollectionInternal(
259             Context context, int userId) {
260         PackageManager packageManager = context.getPackageManager();
261         UserHandle userHandle = UserHandle.of(userId);
262 
263         // Get the list of apps registered for SMS
264         Intent intent = new Intent(Intents.SMS_DELIVER_ACTION);
265         if (DEBUG) {
266             intent.addFlags(Intent.FLAG_DEBUG_LOG_RESOLUTION);
267         }
268         List<ResolveInfo> smsReceivers = packageManager.queryBroadcastReceiversAsUser(intent,
269                 PackageManager.MATCH_DIRECT_BOOT_AWARE | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
270                 userHandle);
271 
272         HashMap<String, SmsApplicationData> receivers = new HashMap<String, SmsApplicationData>();
273 
274         // Add one entry to the map for every sms receiver (ignoring duplicate sms receivers)
275         for (ResolveInfo resolveInfo : smsReceivers) {
276             final ActivityInfo activityInfo = resolveInfo.activityInfo;
277             if (activityInfo == null) {
278                 continue;
279             }
280             if (!permission.BROADCAST_SMS.equals(activityInfo.permission)) {
281                 continue;
282             }
283             final String packageName = activityInfo.packageName;
284             if (!receivers.containsKey(packageName)) {
285                 final SmsApplicationData smsApplicationData = new SmsApplicationData(packageName,
286                         activityInfo.applicationInfo.uid);
287                 smsApplicationData.mSmsReceiverClass = activityInfo.name;
288                 receivers.put(packageName, smsApplicationData);
289             }
290         }
291 
292         // Update any existing entries with mms receiver class
293         intent = new Intent(Intents.WAP_PUSH_DELIVER_ACTION);
294         intent.setDataAndType(null, "application/vnd.wap.mms-message");
295         List<ResolveInfo> mmsReceivers = packageManager.queryBroadcastReceiversAsUser(intent,
296                 PackageManager.MATCH_DIRECT_BOOT_AWARE | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
297                 userHandle);
298         for (ResolveInfo resolveInfo : mmsReceivers) {
299             final ActivityInfo activityInfo = resolveInfo.activityInfo;
300             if (activityInfo == null) {
301                 continue;
302             }
303             if (!permission.BROADCAST_WAP_PUSH.equals(activityInfo.permission)) {
304                 continue;
305             }
306             final String packageName = activityInfo.packageName;
307             final SmsApplicationData smsApplicationData = receivers.get(packageName);
308             if (smsApplicationData != null) {
309                 smsApplicationData.mMmsReceiverClass = activityInfo.name;
310             }
311         }
312 
313         // Update any existing entries with respond via message intent class.
314         intent = new Intent(TelephonyManager.ACTION_RESPOND_VIA_MESSAGE,
315                 Uri.fromParts(SCHEME_SMSTO, "", null));
316         List<ResolveInfo> respondServices = packageManager.queryIntentServicesAsUser(intent,
317                 PackageManager.MATCH_DIRECT_BOOT_AWARE | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
318                 UserHandle.of(userId));
319         for (ResolveInfo resolveInfo : respondServices) {
320             final ServiceInfo serviceInfo = resolveInfo.serviceInfo;
321             if (serviceInfo == null) {
322                 continue;
323             }
324             if (!permission.SEND_RESPOND_VIA_MESSAGE.equals(serviceInfo.permission)) {
325                 continue;
326             }
327             final String packageName = serviceInfo.packageName;
328             final SmsApplicationData smsApplicationData = receivers.get(packageName);
329             if (smsApplicationData != null) {
330                 smsApplicationData.mRespondViaMessageClass = serviceInfo.name;
331             }
332         }
333 
334         // Update any existing entries with supports send to.
335         intent = new Intent(Intent.ACTION_SENDTO,
336                 Uri.fromParts(SCHEME_SMSTO, "", null));
337         List<ResolveInfo> sendToActivities = packageManager.queryIntentActivitiesAsUser(intent,
338                 PackageManager.MATCH_DIRECT_BOOT_AWARE | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
339                 userHandle);
340         for (ResolveInfo resolveInfo : sendToActivities) {
341             final ActivityInfo activityInfo = resolveInfo.activityInfo;
342             if (activityInfo == null) {
343                 continue;
344             }
345             final String packageName = activityInfo.packageName;
346             final SmsApplicationData smsApplicationData = receivers.get(packageName);
347             if (smsApplicationData != null) {
348                 smsApplicationData.mSendToClass = activityInfo.name;
349             }
350         }
351 
352         // Update any existing entries with the default sms changed handler.
353         intent = new Intent(Telephony.Sms.Intents.ACTION_DEFAULT_SMS_PACKAGE_CHANGED);
354         List<ResolveInfo> smsAppChangedReceivers =
355                 packageManager.queryBroadcastReceiversAsUser(intent,
356                         PackageManager.MATCH_DIRECT_BOOT_AWARE
357                                 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE, userHandle);
358         if (DEBUG_MULTIUSER) {
359             Log.i(LOG_TAG, "getApplicationCollectionInternal smsAppChangedActivities=" +
360                     smsAppChangedReceivers);
361         }
362         for (ResolveInfo resolveInfo : smsAppChangedReceivers) {
363             final ActivityInfo activityInfo = resolveInfo.activityInfo;
364             if (activityInfo == null) {
365                 continue;
366             }
367             final String packageName = activityInfo.packageName;
368             final SmsApplicationData smsApplicationData = receivers.get(packageName);
369             if (DEBUG_MULTIUSER) {
370                 Log.i(LOG_TAG, "getApplicationCollectionInternal packageName=" +
371                         packageName + " smsApplicationData: " + smsApplicationData +
372                         " activityInfo.name: " + activityInfo.name);
373             }
374             if (smsApplicationData != null) {
375                 smsApplicationData.mSmsAppChangedReceiverClass = activityInfo.name;
376             }
377         }
378 
379         // Update any existing entries with the external provider changed handler.
380         intent = new Intent(Telephony.Sms.Intents.ACTION_EXTERNAL_PROVIDER_CHANGE);
381         List<ResolveInfo> providerChangedReceivers =
382                 packageManager.queryBroadcastReceiversAsUser(intent,
383                         PackageManager.MATCH_DIRECT_BOOT_AWARE
384                                 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE, userHandle);
385         if (DEBUG_MULTIUSER) {
386             Log.i(LOG_TAG, "getApplicationCollectionInternal providerChangedActivities=" +
387                     providerChangedReceivers);
388         }
389         for (ResolveInfo resolveInfo : providerChangedReceivers) {
390             final ActivityInfo activityInfo = resolveInfo.activityInfo;
391             if (activityInfo == null) {
392                 continue;
393             }
394             final String packageName = activityInfo.packageName;
395             final SmsApplicationData smsApplicationData = receivers.get(packageName);
396             if (DEBUG_MULTIUSER) {
397                 Log.i(LOG_TAG, "getApplicationCollectionInternal packageName=" +
398                         packageName + " smsApplicationData: " + smsApplicationData +
399                         " activityInfo.name: " + activityInfo.name);
400             }
401             if (smsApplicationData != null) {
402                 smsApplicationData.mProviderChangedReceiverClass = activityInfo.name;
403             }
404         }
405 
406         // Update any existing entries with the sim full handler.
407         intent = new Intent(Intents.SIM_FULL_ACTION);
408         List<ResolveInfo> simFullReceivers =
409                 packageManager.queryBroadcastReceiversAsUser(intent,
410                         PackageManager.MATCH_DIRECT_BOOT_AWARE
411                                 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE, userHandle);
412         if (DEBUG_MULTIUSER) {
413             Log.i(LOG_TAG, "getApplicationCollectionInternal simFullReceivers="
414                     + simFullReceivers);
415         }
416         for (ResolveInfo resolveInfo : simFullReceivers) {
417             final ActivityInfo activityInfo = resolveInfo.activityInfo;
418             if (activityInfo == null) {
419                 continue;
420             }
421             final String packageName = activityInfo.packageName;
422             final SmsApplicationData smsApplicationData = receivers.get(packageName);
423             if (DEBUG_MULTIUSER) {
424                 Log.i(LOG_TAG, "getApplicationCollectionInternal packageName="
425                         + packageName + " smsApplicationData: " + smsApplicationData
426                         + " activityInfo.name: " + activityInfo.name);
427             }
428             if (smsApplicationData != null) {
429                 smsApplicationData.mSimFullReceiverClass = activityInfo.name;
430             }
431         }
432 
433         // Remove any entries for which we did not find all required intents.
434         for (ResolveInfo resolveInfo : smsReceivers) {
435             final ActivityInfo activityInfo = resolveInfo.activityInfo;
436             if (activityInfo == null) {
437                 continue;
438             }
439             final String packageName = activityInfo.packageName;
440             final SmsApplicationData smsApplicationData = receivers.get(packageName);
441             if (smsApplicationData != null) {
442                 if (!smsApplicationData.isComplete()) {
443                     receivers.remove(packageName);
444                 }
445             }
446         }
447         return receivers.values();
448     }
449 
450     /**
451      * Checks to see if we have a valid installed SMS application for the specified package name
452      * @return Data for the specified package name or null if there isn't one
453      */
getApplicationForPackage( Collection<SmsApplicationData> applications, String packageName)454     public static SmsApplicationData getApplicationForPackage(
455             Collection<SmsApplicationData> applications, String packageName) {
456         if (packageName == null) {
457             return null;
458         }
459         // Is there an entry in the application list for the specified package?
460         for (SmsApplicationData application : applications) {
461             if (application.mPackageName.contentEquals(packageName)) {
462                 return application;
463             }
464         }
465         return null;
466     }
467 
468     /**
469      * Get the application we will use for delivering SMS/MMS messages.
470      *
471      * We return the preferred sms application with the following order of preference:
472      * (1) User selected SMS app (if selected, and if still valid)
473      * (2) Android Messaging (if installed)
474      * (3) The currently configured highest priority broadcast receiver
475      * (4) Null
476      */
getApplication(Context context, boolean updateIfNeeded, int userId)477     private static SmsApplicationData getApplication(Context context, boolean updateIfNeeded,
478             int userId) {
479         TelephonyManager tm = (TelephonyManager)
480                 context.getSystemService(Context.TELEPHONY_SERVICE);
481         RoleManager roleManager = (RoleManager) context.getSystemService(Context.ROLE_SERVICE);
482         // (b/134400042) RoleManager might be null in unit tests running older mockito versions
483         // that do not support mocking final classes.
484         if (!tm.isSmsCapable() && (roleManager == null || !roleManager.isRoleAvailable(
485                 RoleManager.ROLE_SMS))) {
486             // No phone, no SMS
487             return null;
488         }
489 
490         Collection<SmsApplicationData> applications = getApplicationCollectionInternal(context,
491                 userId);
492         if (DEBUG_MULTIUSER) {
493             Log.i(LOG_TAG, "getApplication userId=" + userId);
494         }
495         // Determine which application receives the broadcast
496         String defaultApplication = getDefaultSmsPackage(context, userId);
497         if (DEBUG_MULTIUSER) {
498             Log.i(LOG_TAG, "getApplication defaultApp=" + defaultApplication);
499         }
500 
501         SmsApplicationData applicationData = null;
502         if (defaultApplication != null) {
503             applicationData = getApplicationForPackage(applications, defaultApplication);
504         }
505         if (DEBUG_MULTIUSER) {
506             Log.i(LOG_TAG, "getApplication appData=" + applicationData);
507         }
508 
509         // If we found a package, make sure AppOps permissions are set up correctly
510         if (applicationData != null) {
511             // We can only call unsafeCheckOp if we are privileged (updateIfNeeded) or if the app we
512             // are checking is for our current uid. Doing this check from the unprivileged current
513             // SMS app allows us to tell the current SMS app that it is not in a good state and
514             // needs to ask to be the current SMS app again to work properly.
515             if (updateIfNeeded || applicationData.mUid == android.os.Process.myUid()) {
516                 // Verify that the SMS app has permissions
517                 boolean appOpsFixed =
518                         tryFixExclusiveSmsAppops(context, applicationData, updateIfNeeded);
519                 if (!appOpsFixed) {
520                     // We can not return a package if permissions are not set up correctly
521                     applicationData = null;
522                 }
523             }
524 
525             // We can only verify the phone and BT app's permissions from a privileged caller
526             if (applicationData != null && updateIfNeeded) {
527                 // Ensure this component is still configured as the preferred activity. Usually the
528                 // current SMS app will already be the preferred activity - but checking whether or
529                 // not this is true is just as expensive as reconfiguring the preferred activity so
530                 // we just reconfigure every time.
531                 defaultSmsAppChanged(context);
532             }
533         }
534         if (DEBUG_MULTIUSER) {
535             Log.i(LOG_TAG, "getApplication returning appData=" + applicationData);
536         }
537         return applicationData;
538     }
539 
getDefaultSmsPackage(Context context, int userId)540     private static String getDefaultSmsPackage(Context context, int userId) {
541         return context.getSystemService(RoleManager.class).getSmsRoleHolder(userId);
542     }
543 
544     /**
545      * Grants various permissions and appops on sms app change
546      */
defaultSmsAppChanged(Context context)547     private static void defaultSmsAppChanged(Context context) {
548         PackageManager packageManager = context.getPackageManager();
549         AppOpsManager appOps = context.getSystemService(AppOpsManager.class);
550 
551         final String bluetoothPackageName = context.getResources()
552                 .getString(com.android.internal.R.string.config_systemBluetoothStack);
553         // Assign permission to special system apps
554         assignExclusiveSmsPermissionsToSystemApp(context, packageManager, appOps,
555                 PHONE_PACKAGE_NAME, true);
556         assignExclusiveSmsPermissionsToSystemApp(context, packageManager, appOps,
557                 bluetoothPackageName, false);
558         assignExclusiveSmsPermissionsToSystemApp(context, packageManager, appOps,
559                 MMS_SERVICE_PACKAGE_NAME, true);
560         assignExclusiveSmsPermissionsToSystemApp(context, packageManager, appOps,
561                 TELEPHONY_PROVIDER_PACKAGE_NAME, true);
562         // CellbroadcastReceiver is a mainline module thus skip signature match.
563         assignExclusiveSmsPermissionsToSystemApp(context, packageManager, appOps,
564                 CellBroadcastUtils.getDefaultCellBroadcastReceiverPackageName(context), false);
565 
566         // Give AppOps permission to UID 1001 which contains multiple
567         // apps, all of them should be able to write to telephony provider.
568         // This is to allow the proxy package permission check in telephony provider
569         // to pass.
570         for (String opStr : DEFAULT_APP_EXCLUSIVE_APPOPS) {
571             appOps.setUidMode(opStr, Process.PHONE_UID, AppOpsManager.MODE_ALLOWED);
572         }
573     }
574 
tryFixExclusiveSmsAppops(Context context, SmsApplicationData applicationData, boolean updateIfNeeded)575     private static boolean tryFixExclusiveSmsAppops(Context context,
576             SmsApplicationData applicationData, boolean updateIfNeeded) {
577         AppOpsManager appOps = context.getSystemService(AppOpsManager.class);
578         for (String opStr : DEFAULT_APP_EXCLUSIVE_APPOPS) {
579             int mode = appOps.unsafeCheckOp(opStr, applicationData.mUid,
580                     applicationData.mPackageName);
581             if (mode != AppOpsManager.MODE_ALLOWED) {
582                 Log.e(LOG_TAG, applicationData.mPackageName + " lost "
583                         + opStr + ": "
584                         + (updateIfNeeded ? " (fixing)" : " (no permission to fix)"));
585                 if (updateIfNeeded) {
586                     appOps.setUidMode(opStr, applicationData.mUid, AppOpsManager.MODE_ALLOWED);
587                 } else {
588                     return false;
589                 }
590             }
591         }
592         return true;
593     }
594 
595     /**
596      * Sets the specified package as the default SMS/MMS application. The caller of this method
597      * needs to have permission to set AppOps and write to secure settings.
598      */
599     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
setDefaultApplication(String packageName, Context context)600     public static void setDefaultApplication(String packageName, Context context) {
601         setDefaultApplicationAsUser(packageName, context, getIncomingUserId());
602     }
603 
604     /**
605      * Same as {@link #setDefaultApplication} but takes a target user id.
606      */
setDefaultApplicationAsUser(String packageName, Context context, int userId)607     public static void setDefaultApplicationAsUser(String packageName, Context context,
608             int userId) {
609         TelephonyManager tm = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
610         RoleManager roleManager = (RoleManager) context.getSystemService(Context.ROLE_SERVICE);
611         // (b/134400042) RoleManager might be null in unit tests running older mockito versions
612         // that do not support mocking final classes.
613         if (!tm.isSmsCapable() && (roleManager == null || !roleManager.isRoleAvailable(
614                 RoleManager.ROLE_SMS))) {
615             // No phone, no SMS
616             return;
617         }
618 
619         final long token = Binder.clearCallingIdentity();
620         try {
621             setDefaultApplicationInternal(packageName, context, userId);
622         } finally {
623             Binder.restoreCallingIdentity(token);
624         }
625     }
626 
setDefaultApplicationInternal(String packageName, Context context, int userId)627     private static void setDefaultApplicationInternal(String packageName, Context context,
628             int userId) {
629         final UserHandle userHandle = UserHandle.of(userId);
630 
631         // Get old package name
632         String oldPackageName = getDefaultSmsPackage(context, userId);
633 
634         if (DEBUG_MULTIUSER) {
635             Log.i(LOG_TAG, "setDefaultApplicationInternal old=" + oldPackageName +
636                     " new=" + packageName);
637         }
638 
639         if (packageName != null && oldPackageName != null && packageName.equals(oldPackageName)) {
640             // No change
641             return;
642         }
643 
644         // We only make the change if the new package is valid
645         PackageManager packageManager =
646                 context.createContextAsUser(userHandle, 0).getPackageManager();
647         Collection<SmsApplicationData> applications = getApplicationCollectionInternal(
648                 context, userId);
649         SmsApplicationData oldAppData = oldPackageName != null ?
650                 getApplicationForPackage(applications, oldPackageName) : null;
651         SmsApplicationData applicationData = getApplicationForPackage(applications, packageName);
652         if (applicationData != null) {
653             // Ignore relevant appops for the previously configured default SMS app.
654             AppOpsManager appOps = (AppOpsManager)context.getSystemService(Context.APP_OPS_SERVICE);
655             if (oldPackageName != null) {
656                 try {
657                     int uid = packageManager.getPackageInfo(oldPackageName, 0).applicationInfo.uid;
658                     setExclusiveAppops(oldPackageName, appOps, uid, AppOpsManager.MODE_DEFAULT);
659                 } catch (NameNotFoundException e) {
660                     Log.w(LOG_TAG, "Old SMS package not found: " + oldPackageName);
661                 }
662             }
663 
664             // Update the setting.
665             CompletableFuture<Void> future = new CompletableFuture<>();
666             Consumer<Boolean> callback = successful -> {
667                 if (successful) {
668                     future.complete(null);
669                 } else {
670                     future.completeExceptionally(new RuntimeException());
671                 }
672             };
673             context.getSystemService(RoleManager.class).addRoleHolderAsUser(
674                     RoleManager.ROLE_SMS, applicationData.mPackageName, 0, UserHandle.of(userId),
675                     AsyncTask.THREAD_POOL_EXECUTOR, callback);
676             try {
677                 future.get(5, TimeUnit.SECONDS);
678             } catch (InterruptedException | ExecutionException | TimeoutException e) {
679                 Log.e(LOG_TAG, "Exception while adding sms role holder " + applicationData, e);
680                 return;
681             }
682 
683             defaultSmsAppChanged(context);
684         }
685     }
686 
687     /**
688      * Broadcast action:
689      * Same as {@link Intent#ACTION_DEFAULT_SMS_PACKAGE_CHANGED} but it's implicit (e.g. sent to
690      * all apps) and requires
691      * {@link #PERMISSION_MONITOR_DEFAULT_SMS_PACKAGE} to receive.
692      */
693     public static final String ACTION_DEFAULT_SMS_PACKAGE_CHANGED_INTERNAL =
694             "android.provider.action.DEFAULT_SMS_PACKAGE_CHANGED_INTERNAL";
695 
696     public static final String PERMISSION_MONITOR_DEFAULT_SMS_PACKAGE =
697             "android.permission.MONITOR_DEFAULT_SMS_PACKAGE";
698 
699     /**
700      * Sends broadcasts on sms app change:
701      * {@link Intent#ACTION_DEFAULT_SMS_PACKAGE_CHANGED}
702      * {@link #ACTION_DEFAULT_SMS_PACKAGE_CHANGED_INTERNAL}
703      */
broadcastSmsAppChange(Context context, UserHandle userHandle, @Nullable String oldPackage, @Nullable String newPackage)704     private static void broadcastSmsAppChange(Context context,
705             UserHandle userHandle, @Nullable String oldPackage, @Nullable String newPackage) {
706         Collection<SmsApplicationData> apps = getApplicationCollection(context);
707 
708         broadcastSmsAppChange(context, userHandle,
709                 getApplicationForPackage(apps, oldPackage),
710                 getApplicationForPackage(apps, newPackage));
711     }
712 
broadcastSmsAppChange(Context context, UserHandle userHandle, @Nullable SmsApplicationData oldAppData, @Nullable SmsApplicationData applicationData)713     private static void broadcastSmsAppChange(Context context, UserHandle userHandle,
714             @Nullable SmsApplicationData oldAppData,
715             @Nullable SmsApplicationData applicationData) {
716         if (DEBUG_MULTIUSER) {
717             Log.i(LOG_TAG, "setDefaultApplicationInternal oldAppData=" + oldAppData);
718         }
719         if (oldAppData != null && oldAppData.mSmsAppChangedReceiverClass != null) {
720             // Notify the old sms app that it's no longer the default
721             final Intent oldAppIntent =
722                     new Intent(Intents.ACTION_DEFAULT_SMS_PACKAGE_CHANGED);
723             final ComponentName component = new ComponentName(oldAppData.mPackageName,
724                     oldAppData.mSmsAppChangedReceiverClass);
725             oldAppIntent.setComponent(component);
726             oldAppIntent.putExtra(Intents.EXTRA_IS_DEFAULT_SMS_APP, false);
727             if (DEBUG_MULTIUSER) {
728                 Log.i(LOG_TAG, "setDefaultApplicationInternal old=" + oldAppData.mPackageName);
729             }
730             context.sendBroadcastAsUser(oldAppIntent, userHandle);
731         }
732         // Notify the new sms app that it's now the default (if the new sms app has a receiver
733         // to handle the changed default sms intent).
734         if (DEBUG_MULTIUSER) {
735             Log.i(LOG_TAG, "setDefaultApplicationInternal new applicationData=" +
736                     applicationData);
737         }
738         if (applicationData != null && applicationData.mSmsAppChangedReceiverClass != null) {
739             final Intent intent =
740                     new Intent(Intents.ACTION_DEFAULT_SMS_PACKAGE_CHANGED);
741             final ComponentName component = new ComponentName(applicationData.mPackageName,
742                     applicationData.mSmsAppChangedReceiverClass);
743             intent.setComponent(component);
744             intent.putExtra(Intents.EXTRA_IS_DEFAULT_SMS_APP, true);
745             if (DEBUG_MULTIUSER) {
746                 Log.i(LOG_TAG, "setDefaultApplicationInternal new=" + applicationData.mPackageName);
747             }
748             context.sendBroadcastAsUser(intent, userHandle);
749         }
750 
751         // Send an implicit broadcast for the system server.
752         // (or anyone with PERMISSION_MONITOR_DEFAULT_SMS_PACKAGE, really.)
753         final Intent intent =
754                 new Intent(ACTION_DEFAULT_SMS_PACKAGE_CHANGED_INTERNAL);
755         context.sendBroadcastAsUser(intent, userHandle,
756                 PERMISSION_MONITOR_DEFAULT_SMS_PACKAGE);
757     }
758 
759     /**
760      * Assign WRITE_SMS AppOps permission to some special system apps.
761      *
762      * @param context The context
763      * @param packageManager The package manager instance
764      * @param appOps The AppOps manager instance
765      * @param packageName The package name of the system app
766      * @param sigatureMatch whether to check signature match
767      */
assignExclusiveSmsPermissionsToSystemApp(Context context, PackageManager packageManager, AppOpsManager appOps, String packageName, boolean sigatureMatch)768     private static void assignExclusiveSmsPermissionsToSystemApp(Context context,
769             PackageManager packageManager, AppOpsManager appOps, String packageName,
770             boolean sigatureMatch) {
771         if (packageName == null) return;
772         // First check package signature matches the caller's package signature.
773         // Since this class is only used internally by the system, this check makes sure
774         // the package signature matches system signature.
775         if (sigatureMatch) {
776             final int result = packageManager.checkSignatures(context.getPackageName(),
777                     packageName);
778             if (result != PackageManager.SIGNATURE_MATCH) {
779                 Log.e(LOG_TAG, packageName + " does not have system signature");
780                 return;
781             }
782         }
783 
784         try {
785             PackageInfo info = packageManager.getPackageInfo(packageName, 0);
786             int mode = appOps.unsafeCheckOp(AppOpsManager.OPSTR_WRITE_SMS, info.applicationInfo.uid,
787                     packageName);
788             if (mode != AppOpsManager.MODE_ALLOWED) {
789                 Log.w(LOG_TAG, packageName + " does not have OP_WRITE_SMS:  (fixing)");
790                 setExclusiveAppops(packageName, appOps, info.applicationInfo.uid,
791                         AppOpsManager.MODE_ALLOWED);
792             }
793         } catch (NameNotFoundException e) {
794             // No allowlisted system app on this device
795             Log.e(LOG_TAG, "Package not found: " + packageName);
796         }
797 
798     }
799 
setExclusiveAppops(String pkg, AppOpsManager appOpsManager, int uid, int mode)800     private static void setExclusiveAppops(String pkg, AppOpsManager appOpsManager, int uid,
801             int mode) {
802         for (String opStr : DEFAULT_APP_EXCLUSIVE_APPOPS) {
803             appOpsManager.setUidMode(opStr, uid, mode);
804         }
805     }
806 
807     /**
808      * Tracks package changes and ensures that the default SMS app is always configured to be the
809      * preferred activity for SENDTO sms/mms intents.
810      */
811     private static final class SmsPackageMonitor extends PackageChangeReceiver {
812         final Context mContext;
813 
SmsPackageMonitor(Context context)814         public SmsPackageMonitor(Context context) {
815             super();
816             mContext = context;
817         }
818 
819         @Override
onPackageDisappeared()820         public void onPackageDisappeared() {
821             onPackageChanged();
822         }
823 
824         @Override
onPackageAppeared()825         public void onPackageAppeared() {
826             onPackageChanged();
827         }
828 
829         @Override
onPackageModified(String packageName)830         public void onPackageModified(String packageName) {
831             onPackageChanged();
832         }
833 
onPackageChanged()834         private void onPackageChanged() {
835             int userId;
836             try {
837                 userId = getSendingUser().getIdentifier();
838             } catch (NullPointerException e) {
839                 // This should never happen in prod -- unit tests will put the receiver into a
840                 // unusual state where the pending result is null, which produces a NPE when calling
841                 // getSendingUserId. Just pretend like it's the system user for testing.
842                 userId = UserHandle.SYSTEM.getIdentifier();
843             }
844             Context userContext = mContext;
845             if (userId != UserHandle.SYSTEM.getIdentifier()) {
846                 try {
847                     userContext = mContext.createPackageContextAsUser(mContext.getPackageName(), 0,
848                         UserHandle.of(userId));
849                 } catch (NameNotFoundException nnfe) {
850                     if (DEBUG_MULTIUSER) {
851                         Log.w(LOG_TAG, "Unable to create package context for user " + userId);
852                     }
853                 }
854             }
855             PackageManager packageManager = userContext.getPackageManager();
856             // Ensure this component is still configured as the preferred activity
857             ComponentName componentName = getDefaultSendToApplication(userContext, true);
858             if (componentName != null) {
859                 configurePreferredActivity(packageManager, componentName);
860             }
861         }
862     }
863 
864     /**
865      * Tracks SMS role changes and sends broadcasts for default SMS app change.
866      */
867     private static final class SmsRoleListener implements OnRoleHoldersChangedListener {
868         private final Context mContext;
869         private final RoleManager mRoleManager;
870         private final SparseArray<String> mSmsPackageNames = new SparseArray<>();
871 
SmsRoleListener(@onNull Context context)872         public SmsRoleListener(@NonNull Context context) {
873             mContext = context;
874             mRoleManager = context.getSystemService(RoleManager.class);
875             final List<UserHandle> users = context.getSystemService(UserManager.class)
876                     .getUserHandles(true);
877             final int usersSize = users.size();
878             for (int i = 0; i < usersSize; i++) {
879                 final UserHandle user = users.get(i);
880                 mSmsPackageNames.put(user.getIdentifier(), getSmsPackageName(user));
881             }
882             mRoleManager.addOnRoleHoldersChangedListenerAsUser(context.getMainExecutor(), this,
883                     UserHandle.ALL);
884         }
885 
886         @Override
onRoleHoldersChanged(@onNull String roleName, @NonNull UserHandle user)887         public void onRoleHoldersChanged(@NonNull String roleName, @NonNull UserHandle user) {
888             if (!Objects.equals(roleName, RoleManager.ROLE_SMS)) {
889                 return;
890             }
891             final int userId = user.getIdentifier();
892             final String newSmsPackageName = getSmsPackageName(user);
893             broadcastSmsAppChange(mContext, user, mSmsPackageNames.get(userId), newSmsPackageName);
894             mSmsPackageNames.put(userId, newSmsPackageName);
895         }
896 
897         @Nullable
getSmsPackageName(@onNull UserHandle user)898         private String getSmsPackageName(@NonNull UserHandle user) {
899             final List<String> roleHolders = mRoleManager.getRoleHoldersAsUser(
900                     RoleManager.ROLE_SMS, user);
901             return !roleHolders.isEmpty() ? roleHolders.get(0) : null;
902         }
903     }
904 
initSmsPackageMonitor(Context context)905     public static void initSmsPackageMonitor(Context context) {
906         sSmsPackageMonitor = new SmsPackageMonitor(context);
907         sSmsPackageMonitor.register(context, context.getMainLooper(), UserHandle.ALL);
908         sSmsRoleListener = new SmsRoleListener(context);
909     }
910 
911     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
configurePreferredActivity(PackageManager packageManager, ComponentName componentName)912     private static void configurePreferredActivity(PackageManager packageManager,
913             ComponentName componentName) {
914         // Add the four activity preferences we want to direct to this app.
915         replacePreferredActivity(packageManager, componentName, SCHEME_SMS);
916         replacePreferredActivity(packageManager, componentName, SCHEME_SMSTO);
917         replacePreferredActivity(packageManager, componentName, SCHEME_MMS);
918         replacePreferredActivity(packageManager, componentName, SCHEME_MMSTO);
919     }
920 
921     /**
922      * Updates the ACTION_SENDTO activity to the specified component for the specified scheme.
923      */
replacePreferredActivity(PackageManager packageManager, ComponentName componentName, String scheme)924     private static void replacePreferredActivity(PackageManager packageManager,
925             ComponentName componentName, String scheme) {
926         // Build the set of existing activities that handle this scheme
927         Intent intent = new Intent(Intent.ACTION_SENDTO, Uri.fromParts(scheme, "", null));
928         List<ResolveInfo> resolveInfoList = packageManager.queryIntentActivities(
929                 intent, PackageManager.MATCH_DEFAULT_ONLY | PackageManager.GET_RESOLVED_FILTER);
930 
931         List<ComponentName> components = resolveInfoList.stream().map(info ->
932                 new ComponentName(info.activityInfo.packageName, info.activityInfo.name))
933                 .collect(Collectors.toList());
934 
935         // Update the preferred SENDTO activity for the specified scheme
936         IntentFilter intentFilter = new IntentFilter();
937         intentFilter.addAction(Intent.ACTION_SENDTO);
938         intentFilter.addCategory(Intent.CATEGORY_DEFAULT);
939         intentFilter.addDataScheme(scheme);
940         packageManager.replacePreferredActivity(intentFilter,
941                 IntentFilter.MATCH_CATEGORY_SCHEME + IntentFilter.MATCH_ADJUSTMENT_NORMAL,
942                 components, componentName);
943     }
944 
945     /**
946      * Returns SmsApplicationData for this package if this package is capable of being set as the
947      * default SMS application.
948      */
949     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
getSmsApplicationData(String packageName, Context context)950     public static SmsApplicationData getSmsApplicationData(String packageName, Context context) {
951         Collection<SmsApplicationData> applications = getApplicationCollection(context);
952         return getApplicationForPackage(applications, packageName);
953     }
954 
955     /**
956      * Gets the default SMS application
957      * @param context context from the calling app
958      * @param updateIfNeeded update the default app if there is no valid default app configured.
959      * @return component name of the app and class to deliver SMS messages to
960      */
961     @UnsupportedAppUsage
getDefaultSmsApplication(Context context, boolean updateIfNeeded)962     public static ComponentName getDefaultSmsApplication(Context context, boolean updateIfNeeded) {
963         return getDefaultSmsApplicationAsUser(context, updateIfNeeded, getIncomingUserHandle());
964     }
965 
966     /**
967      * Gets the default SMS application on a given user
968      * @param context context from the calling app
969      * @param updateIfNeeded update the default app if there is no valid default app configured.
970      * @param userHandle target user handle
971      * if {@code null} is passed in then calling package uid is used to find out target user handle.
972      * @return component name of the app and class to deliver SMS messages to
973      */
getDefaultSmsApplicationAsUser(Context context, boolean updateIfNeeded, @Nullable UserHandle userHandle)974     public static ComponentName getDefaultSmsApplicationAsUser(Context context,
975             boolean updateIfNeeded, @Nullable UserHandle userHandle) {
976         if (userHandle == null) {
977             userHandle = getIncomingUserHandle();
978         }
979 
980         final long token = Binder.clearCallingIdentity();
981         try {
982             ComponentName component = null;
983             SmsApplicationData smsApplicationData = getApplication(context, updateIfNeeded,
984                     userHandle.getIdentifier());
985             if (smsApplicationData != null) {
986                 component = new ComponentName(smsApplicationData.mPackageName,
987                         smsApplicationData.mSmsReceiverClass);
988             }
989             return component;
990         } finally {
991             Binder.restoreCallingIdentity(token);
992         }
993     }
994 
995     /**
996      * Gets the default MMS application
997      * @param context context from the calling app
998      * @param updateIfNeeded update the default app if there is no valid default app configured.
999      * @return component name of the app and class to deliver MMS messages to
1000      */
1001     @UnsupportedAppUsage
getDefaultMmsApplication(Context context, boolean updateIfNeeded)1002     public static ComponentName getDefaultMmsApplication(Context context, boolean updateIfNeeded) {
1003         return getDefaultMmsApplicationAsUser(context, updateIfNeeded, getIncomingUserHandle());
1004     }
1005 
1006     /**
1007      * Gets the default MMS application on a given user
1008      * @param context context from the calling app
1009      * @param updateIfNeeded update the default app if there is no valid default app configured.
1010      * @param userHandle target user handle
1011      * if {@code null} is passed in then calling package uid is used to find out target user handle.
1012      * @return component name of the app and class to deliver MMS messages to.
1013      */
getDefaultMmsApplicationAsUser(Context context, boolean updateIfNeeded, @Nullable UserHandle userHandle)1014     public static ComponentName getDefaultMmsApplicationAsUser(Context context,
1015             boolean updateIfNeeded, @Nullable UserHandle userHandle) {
1016         if (userHandle == null) {
1017             userHandle = getIncomingUserHandle();
1018         }
1019 
1020         final long token = Binder.clearCallingIdentity();
1021         try {
1022             ComponentName component = null;
1023             SmsApplicationData smsApplicationData = getApplication(context, updateIfNeeded,
1024                     userHandle.getIdentifier());
1025             if (smsApplicationData != null) {
1026                 component = new ComponentName(smsApplicationData.mPackageName,
1027                         smsApplicationData.mMmsReceiverClass);
1028             }
1029             return component;
1030         } finally {
1031             Binder.restoreCallingIdentity(token);
1032         }
1033     }
1034 
1035     /**
1036      * Gets the default Respond Via Message application
1037      * @param context context from the calling app
1038      * @param updateIfNeeded update the default app if there is no valid default app configured.
1039      * @return component name of the app and class to direct Respond Via Message intent to
1040      */
1041     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
getDefaultRespondViaMessageApplication(Context context, boolean updateIfNeeded)1042     public static ComponentName getDefaultRespondViaMessageApplication(Context context,
1043             boolean updateIfNeeded) {
1044         return getDefaultRespondViaMessageApplicationAsUser(context, updateIfNeeded,
1045                 getIncomingUserHandle());
1046     }
1047 
1048     /**
1049      * Gets the default Respond Via Message application on a given user
1050      * @param context context from the calling app
1051      * @param updateIfNeeded update the default app if there is no valid default app configured
1052      * @param userHandle target user handle
1053      * if {@code null} is passed in then calling package uid is used to find out target user handle.
1054      * @return component name of the app and class to direct Respond Via Message intent to
1055      */
getDefaultRespondViaMessageApplicationAsUser(Context context, boolean updateIfNeeded, @Nullable UserHandle userHandle)1056     public static ComponentName getDefaultRespondViaMessageApplicationAsUser(Context context,
1057             boolean updateIfNeeded, @Nullable UserHandle userHandle) {
1058         if (userHandle == null) {
1059             userHandle = getIncomingUserHandle();
1060         }
1061 
1062         final long token = Binder.clearCallingIdentity();
1063         try {
1064             ComponentName component = null;
1065             SmsApplicationData smsApplicationData = getApplication(context, updateIfNeeded,
1066                     userHandle.getIdentifier());
1067             if (smsApplicationData != null) {
1068                 component = new ComponentName(smsApplicationData.mPackageName,
1069                         smsApplicationData.mRespondViaMessageClass);
1070             }
1071             return component;
1072         } finally {
1073             Binder.restoreCallingIdentity(token);
1074         }
1075     }
1076 
1077     /**
1078      * Gets the default Send To (smsto) application.
1079      * <p>
1080      * Caller must pass in the correct user context if calling from a singleton service.
1081      * @param context context from the calling app
1082      * @param updateIfNeeded update the default app if there is no valid default app configured.
1083      * @return component name of the app and class to direct SEND_TO (smsto) intent to
1084      */
getDefaultSendToApplication(Context context, boolean updateIfNeeded)1085     public static ComponentName getDefaultSendToApplication(Context context,
1086             boolean updateIfNeeded) {
1087         int userId = getIncomingUserId();
1088 
1089         final long token = Binder.clearCallingIdentity();
1090         try {
1091             ComponentName component = null;
1092             SmsApplicationData smsApplicationData = getApplication(context, updateIfNeeded,
1093                     userId);
1094             if (smsApplicationData != null) {
1095                 component = new ComponentName(smsApplicationData.mPackageName,
1096                         smsApplicationData.mSendToClass);
1097             }
1098             return component;
1099         } finally {
1100             Binder.restoreCallingIdentity(token);
1101         }
1102     }
1103 
1104     /**
1105      * Gets the default application that handles external changes to the SmsProvider and
1106      * MmsProvider.
1107      * @param context context from the calling app
1108      * @param updateIfNeeded update the default app if there is no valid default app configured.
1109      * @return component name of the app and class to deliver change intents to
1110      */
getDefaultExternalTelephonyProviderChangedApplication( Context context, boolean updateIfNeeded)1111     public static ComponentName getDefaultExternalTelephonyProviderChangedApplication(
1112             Context context, boolean updateIfNeeded) {
1113         return getDefaultExternalTelephonyProviderChangedApplicationAsUser(context, updateIfNeeded,
1114                 getIncomingUserHandle());
1115     }
1116 
1117     /**
1118      * Gets the default application that handles external changes to the SmsProvider and
1119      * MmsProvider on a given user.
1120      * @param context context from the calling app
1121      * @param updateIfNeeded update the default app if there is no valid default app configured
1122      * @param userHandle target user handle
1123      * if {@code null} is passed in then calling package uid is used to find out target user handle.
1124      * @return component name of the app and class to deliver change intents to.
1125      */
getDefaultExternalTelephonyProviderChangedApplicationAsUser( Context context, boolean updateIfNeeded, @Nullable UserHandle userHandle)1126     public static ComponentName getDefaultExternalTelephonyProviderChangedApplicationAsUser(
1127             Context context, boolean updateIfNeeded, @Nullable UserHandle userHandle) {
1128         if (userHandle == null) {
1129             userHandle = getIncomingUserHandle();
1130         }
1131 
1132         final long token = Binder.clearCallingIdentity();
1133         try {
1134             ComponentName component = null;
1135             SmsApplicationData smsApplicationData = getApplication(context, updateIfNeeded,
1136                     userHandle.getIdentifier());
1137             if (smsApplicationData != null
1138                     && smsApplicationData.mProviderChangedReceiverClass != null) {
1139                 component = new ComponentName(smsApplicationData.mPackageName,
1140                         smsApplicationData.mProviderChangedReceiverClass);
1141             }
1142             return component;
1143         } finally {
1144             Binder.restoreCallingIdentity(token);
1145         }
1146     }
1147 
1148     /**
1149      * Gets the default application that handles sim full event.
1150      * @param context context from the calling app
1151      * @param updateIfNeeded update the default app if there is no valid default app configured.
1152      * @return component name of the app and class to deliver change intents to
1153      */
getDefaultSimFullApplication( Context context, boolean updateIfNeeded)1154     public static ComponentName getDefaultSimFullApplication(
1155             Context context, boolean updateIfNeeded) {
1156         return getDefaultSimFullApplicationAsUser(context, updateIfNeeded, getIncomingUserHandle());
1157     }
1158 
1159     /**
1160      * Gets the default application that handles sim full event on a given user.
1161      * @param context context from the calling app
1162      * @param updateIfNeeded update the default app if there is no valid default app configured
1163      * @param userHandle target user handle
1164      * if {@code null} is passed in then calling package uid is used to find out target user handle.
1165      * @return component name of the app and class to deliver change intents to
1166      */
getDefaultSimFullApplicationAsUser(Context context, boolean updateIfNeeded, @Nullable UserHandle userHandle)1167     public static ComponentName getDefaultSimFullApplicationAsUser(Context context,
1168             boolean updateIfNeeded, @Nullable UserHandle userHandle) {
1169         if (userHandle == null) {
1170             userHandle = getIncomingUserHandle();
1171         }
1172 
1173         final long token = Binder.clearCallingIdentity();
1174         try {
1175             ComponentName component = null;
1176             SmsApplicationData smsApplicationData = getApplication(context, updateIfNeeded,
1177                     userHandle.getIdentifier());
1178             if (smsApplicationData != null
1179                     && smsApplicationData.mSimFullReceiverClass != null) {
1180                 component = new ComponentName(smsApplicationData.mPackageName,
1181                         smsApplicationData.mSimFullReceiverClass);
1182             }
1183             return component;
1184         } finally {
1185             Binder.restoreCallingIdentity(token);
1186         }
1187     }
1188 
1189     /**
1190      * Returns whether it is required to write the SMS message to SMS database for this package.
1191      *
1192      * @param packageName the name of the package to be checked
1193      * @param context context from the calling app
1194      * @return true if it is required to write SMS message to SMS database for this package.
1195      *
1196      * <p>
1197      * Caller must pass in the correct user context if calling from a singleton service.
1198      */
1199     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
shouldWriteMessageForPackage(String packageName, Context context)1200     public static boolean shouldWriteMessageForPackage(String packageName, Context context) {
1201         return !shouldWriteMessageForPackageAsUser(packageName, context, getIncomingUserHandle());
1202     }
1203 
1204     /**
1205      * Returns whether it is required to write the SMS message to SMS database for this package.
1206      *
1207      * @param packageName the name of the package to be checked
1208      * @param context context from the calling app
1209      * @param userHandle target user handle
1210      * if {@code null} is passed in then calling package uid is used to find out target user handle.
1211      * @return true if it is required to write SMS message to SMS database for this package.
1212      *
1213      * <p>
1214      * Caller must pass in the correct user context if calling from a singleton service.
1215      */
shouldWriteMessageForPackageAsUser(String packageName, Context context, @Nullable UserHandle userHandle)1216     public static boolean shouldWriteMessageForPackageAsUser(String packageName, Context context,
1217             @Nullable UserHandle userHandle) {
1218         return !isDefaultSmsApplicationAsUser(context, packageName, userHandle);
1219     }
1220 
1221     /**
1222      * Check if a package is default sms app (or equivalent, like bluetooth)
1223      *
1224      * @param context context from the calling app
1225      * @param packageName the name of the package to be checked
1226      * @return true if the package is default sms app or bluetooth
1227      */
1228     @UnsupportedAppUsage
isDefaultSmsApplication(Context context, String packageName)1229     public static boolean isDefaultSmsApplication(Context context, String packageName) {
1230         return isDefaultSmsApplicationAsUser(context, packageName, getIncomingUserHandle());
1231     }
1232 
1233     /**
1234      * Check if a package is default sms app (or equivalent, like bluetooth) on a given user.
1235      *
1236      * @param context context from the calling app
1237      * @param packageName the name of the package to be checked
1238      * @param userHandle target user handle
1239      * if {@code null} is passed in then calling package uid is used to find out target user handle.
1240      * @return true if the package is default sms app or bluetooth
1241      */
isDefaultSmsApplicationAsUser(Context context, String packageName, @Nullable UserHandle userHandle)1242     public static boolean isDefaultSmsApplicationAsUser(Context context, String packageName,
1243             @Nullable UserHandle userHandle) {
1244         if (packageName == null) {
1245             return false;
1246         }
1247 
1248         if (userHandle == null) {
1249             userHandle = getIncomingUserHandle();
1250         }
1251 
1252         ComponentName component = getDefaultSmsApplicationAsUser(context, false,
1253                 userHandle);
1254         if (component == null) {
1255             return false;
1256         }
1257 
1258         String defaultSmsPackage = component.getPackageName();
1259         if (defaultSmsPackage == null) {
1260             return false;
1261         }
1262 
1263         String bluetoothPackageName = context.getResources()
1264                 .getString(com.android.internal.R.string.config_systemBluetoothStack);
1265 
1266         if (defaultSmsPackage.equals(packageName) || bluetoothPackageName.equals(packageName)) {
1267             return true;
1268         }
1269         return false;
1270     }
1271 
1272     /**
1273      * Check if a package is default mms app (or equivalent, like bluetooth)
1274      *
1275      * @param context context from the calling app
1276      * @param packageName the name of the package to be checked
1277      * @return true if the package is default mms app or bluetooth
1278      */
1279     @UnsupportedAppUsage
isDefaultMmsApplication(Context context, String packageName)1280     public static boolean isDefaultMmsApplication(Context context, String packageName) {
1281         return isDefaultMmsApplicationAsUser(context, packageName, getIncomingUserHandle());
1282     }
1283 
1284     /**
1285      * Check if a package is default mms app (or equivalent, like bluetooth) on a given user.
1286      *
1287      * @param context context from the calling app
1288      * @param packageName the name of the package to be checked
1289      * @param userHandle target user handle
1290      * if {@code null} is passed in then calling package uid is used to find out target user handle.
1291      * @return true if the package is default mms app or bluetooth
1292      */
isDefaultMmsApplicationAsUser(Context context, String packageName, @Nullable UserHandle userHandle)1293     public static boolean isDefaultMmsApplicationAsUser(Context context, String packageName,
1294             @Nullable UserHandle userHandle) {
1295         if (packageName == null) {
1296             return false;
1297         }
1298 
1299         if (userHandle == null) {
1300             userHandle = getIncomingUserHandle();
1301         }
1302 
1303         ComponentName component = getDefaultMmsApplicationAsUser(context, false,
1304                 userHandle);
1305         if (component == null) {
1306             return false;
1307         }
1308 
1309         String defaultMmsPackage = component.getPackageName();
1310         if (defaultMmsPackage == null) {
1311             return false;
1312         }
1313 
1314         String bluetoothPackageName = context.getResources()
1315                 .getString(com.android.internal.R.string.config_systemBluetoothStack);
1316 
1317         if (defaultMmsPackage.equals(packageName)|| bluetoothPackageName.equals(packageName)) {
1318             return true;
1319         }
1320         return false;
1321     }
1322 }