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