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