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