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