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