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