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