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