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 }