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