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