1 /* 2 * Copyright (C) 2006 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 static android.Manifest.permission.SEND_SMS_NO_CONFIRMATION; 20 import static android.telephony.SmsManager.RESULT_ERROR_GENERIC_FAILURE; 21 import static android.telephony.SmsManager.RESULT_ERROR_LIMIT_EXCEEDED; 22 import static android.telephony.SmsManager.RESULT_ERROR_NONE; 23 import static android.telephony.SmsManager.RESULT_ERROR_NO_SERVICE; 24 import static android.telephony.SmsManager.RESULT_ERROR_NULL_PDU; 25 import static android.telephony.SmsManager.RESULT_ERROR_RADIO_OFF; 26 import static android.telephony.SmsManager.RESULT_ERROR_SHORT_CODE_NEVER_ALLOWED; 27 import static android.telephony.SmsManager.RESULT_ERROR_SHORT_CODE_NOT_ALLOWED; 28 29 import static com.android.internal.telephony.IccSmsInterfaceManager.SMS_MESSAGE_PERIOD_NOT_SPECIFIED; 30 import static com.android.internal.telephony.IccSmsInterfaceManager.SMS_MESSAGE_PRIORITY_NOT_SPECIFIED; 31 import static com.android.internal.telephony.SmsResponse.NO_ERROR_CODE; 32 33 import android.annotation.UserIdInt; 34 import android.app.Activity; 35 import android.app.AlertDialog; 36 import android.app.PendingIntent; 37 import android.app.PendingIntent.CanceledException; 38 import android.compat.annotation.UnsupportedAppUsage; 39 import android.content.ContentResolver; 40 import android.content.ContentValues; 41 import android.content.Context; 42 import android.content.DialogInterface; 43 import android.content.Intent; 44 import android.content.pm.ApplicationInfo; 45 import android.content.pm.PackageInfo; 46 import android.content.pm.PackageManager; 47 import android.content.res.Resources; 48 import android.database.ContentObserver; 49 import android.net.Uri; 50 import android.os.AsyncResult; 51 import android.os.Binder; 52 import android.os.Handler; 53 import android.os.Message; 54 import android.os.PersistableBundle; 55 import android.os.Process; 56 import android.os.UserHandle; 57 import android.provider.Settings; 58 import android.provider.Telephony; 59 import android.provider.Telephony.Sms; 60 import android.service.carrier.CarrierMessagingService; 61 import android.service.carrier.CarrierMessagingServiceWrapper; 62 import android.service.carrier.CarrierMessagingServiceWrapper.CarrierMessagingCallbackWrapper; 63 import android.telephony.CarrierConfigManager; 64 import android.telephony.PhoneNumberUtils; 65 import android.telephony.ServiceState; 66 import android.telephony.SmsManager; 67 import android.telephony.TelephonyManager; 68 import android.text.Html; 69 import android.text.Spanned; 70 import android.text.TextUtils; 71 import android.util.EventLog; 72 import android.view.LayoutInflater; 73 import android.view.View; 74 import android.view.ViewGroup; 75 import android.view.WindowManager; 76 import android.widget.Button; 77 import android.widget.CheckBox; 78 import android.widget.CompoundButton; 79 import android.widget.TextView; 80 81 import com.android.internal.R; 82 import com.android.internal.annotations.VisibleForTesting; 83 import com.android.internal.telephony.GsmAlphabet.TextEncodingDetails; 84 import com.android.internal.telephony.cdma.sms.UserData; 85 import com.android.internal.telephony.uicc.UiccCard; 86 import com.android.internal.telephony.uicc.UiccController; 87 import com.android.telephony.Rlog; 88 89 import java.util.ArrayList; 90 import java.util.HashMap; 91 import java.util.List; 92 import java.util.Random; 93 import java.util.concurrent.atomic.AtomicBoolean; 94 import java.util.concurrent.atomic.AtomicInteger; 95 96 public abstract class SMSDispatcher extends Handler { 97 static final String TAG = "SMSDispatcher"; // accessed from inner class 98 static final boolean DBG = false; 99 private static final String SEND_NEXT_MSG_EXTRA = "SendNextMsg"; 100 private static final String MESSAGE_ID_EXTRA = "MessageId"; 101 protected static final String MAP_KEY_PDU = "pdu"; 102 protected static final String MAP_KEY_SMSC = "smsc"; 103 protected static final String MAP_KEY_DEST_ADDR = "destAddr"; 104 protected static final String MAP_KEY_SC_ADDR = "scAddr"; 105 protected static final String MAP_KEY_DEST_PORT = "destPort"; 106 protected static final String MAP_KEY_DATA = "data"; 107 protected static final String MAP_KEY_TEXT = "text"; 108 109 private static final int PREMIUM_RULE_USE_SIM = 1; 110 private static final int PREMIUM_RULE_USE_NETWORK = 2; 111 private static final int PREMIUM_RULE_USE_BOTH = 3; 112 private final AtomicInteger mPremiumSmsRule = new AtomicInteger(PREMIUM_RULE_USE_SIM); 113 private final SettingsObserver mSettingsObserver; 114 115 /** SMS send complete. */ 116 protected static final int EVENT_SEND_SMS_COMPLETE = 2; 117 118 /** Retry sending a previously failed SMS message */ 119 private static final int EVENT_SEND_RETRY = 3; 120 121 /** Confirmation required for sending a large number of messages. */ 122 private static final int EVENT_SEND_LIMIT_REACHED_CONFIRMATION = 4; 123 124 /** Send the user confirmed SMS */ 125 static final int EVENT_SEND_CONFIRMED_SMS = 5; // accessed from inner class 126 127 /** Don't send SMS (user did not confirm). */ 128 static final int EVENT_STOP_SENDING = 6; // accessed from inner class 129 130 /** Don't send SMS for this app (User had already denied eariler.) */ 131 static final int EVENT_SENDING_NOT_ALLOWED = 7; 132 133 /** Confirmation required for third-party apps sending to an SMS short code. */ 134 private static final int EVENT_CONFIRM_SEND_TO_POSSIBLE_PREMIUM_SHORT_CODE = 8; 135 136 /** Confirmation required for third-party apps sending to an SMS short code. */ 137 private static final int EVENT_CONFIRM_SEND_TO_PREMIUM_SHORT_CODE = 9; 138 139 /** Handle status report from {@code CdmaInboundSmsHandler}. */ 140 protected static final int EVENT_HANDLE_STATUS_REPORT = 10; 141 142 // other 143 protected static final int EVENT_NEW_ICC_SMS = 14; 144 protected static final int EVENT_ICC_CHANGED = 15; 145 protected static final int EVENT_GET_IMS_SERVICE = 16; 146 147 148 @UnsupportedAppUsage 149 protected Phone mPhone; 150 @UnsupportedAppUsage 151 protected final Context mContext; 152 @UnsupportedAppUsage 153 protected final ContentResolver mResolver; 154 @UnsupportedAppUsage 155 protected final CommandsInterface mCi; 156 @UnsupportedAppUsage 157 protected final TelephonyManager mTelephonyManager; 158 159 /** Maximum number of times to retry sending a failed SMS. */ 160 private static final int MAX_SEND_RETRIES = 3; 161 /** Delay before next send attempt on a failed SMS, in milliseconds. */ 162 private static final int SEND_RETRY_DELAY = 2000; 163 /** Message sending queue limit */ 164 private static final int MO_MSG_QUEUE_LIMIT = 5; 165 166 /** 167 * Message reference for a CONCATENATED_8_BIT_REFERENCE or 168 * CONCATENATED_16_BIT_REFERENCE message set. Should be 169 * incremented for each set of concatenated messages. 170 * Static field shared by all dispatcher objects. 171 */ 172 private static int sConcatenatedRef = new Random().nextInt(256); 173 174 protected SmsDispatchersController mSmsDispatchersController; 175 176 /** Number of outgoing SmsTrackers waiting for user confirmation. */ 177 private int mPendingTrackerCount; 178 179 /* Flags indicating whether the current device allows sms service */ 180 protected boolean mSmsCapable = true; 181 protected boolean mSmsSendDisabled; 182 183 @UnsupportedAppUsage getNextConcatenatedRef()184 protected static int getNextConcatenatedRef() { 185 sConcatenatedRef += 1; 186 return sConcatenatedRef; 187 } 188 189 /** 190 * Create a new SMS dispatcher. 191 * @param phone the Phone to use 192 */ SMSDispatcher(Phone phone, SmsDispatchersController smsDispatchersController)193 protected SMSDispatcher(Phone phone, SmsDispatchersController smsDispatchersController) { 194 mPhone = phone; 195 mSmsDispatchersController = smsDispatchersController; 196 mContext = phone.getContext(); 197 mResolver = mContext.getContentResolver(); 198 mCi = phone.mCi; 199 mTelephonyManager = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE); 200 mSettingsObserver = new SettingsObserver(this, mPremiumSmsRule, mContext); 201 mContext.getContentResolver().registerContentObserver(Settings.Global.getUriFor( 202 Settings.Global.SMS_SHORT_CODE_RULE), false, mSettingsObserver); 203 204 mSmsCapable = mContext.getResources().getBoolean( 205 com.android.internal.R.bool.config_sms_capable); 206 mSmsSendDisabled = !mTelephonyManager.getSmsSendCapableForPhone( 207 mPhone.getPhoneId(), mSmsCapable); 208 Rlog.d(TAG, "SMSDispatcher: ctor mSmsCapable=" + mSmsCapable + " format=" + getFormat() 209 + " mSmsSendDisabled=" + mSmsSendDisabled); 210 } 211 212 /** 213 * Observe the secure setting for updated premium sms determination rules 214 */ 215 private static class SettingsObserver extends ContentObserver { 216 private final AtomicInteger mPremiumSmsRule; 217 private final Context mContext; SettingsObserver(Handler handler, AtomicInteger premiumSmsRule, Context context)218 SettingsObserver(Handler handler, AtomicInteger premiumSmsRule, Context context) { 219 super(handler); 220 mPremiumSmsRule = premiumSmsRule; 221 mContext = context; 222 onChange(false); // load initial value; 223 } 224 225 @Override onChange(boolean selfChange)226 public void onChange(boolean selfChange) { 227 mPremiumSmsRule.set(Settings.Global.getInt(mContext.getContentResolver(), 228 Settings.Global.SMS_SHORT_CODE_RULE, PREMIUM_RULE_USE_SIM)); 229 } 230 } 231 232 /** Unregister for incoming SMS events. */ 233 @UnsupportedAppUsage dispose()234 public void dispose() { 235 mContext.getContentResolver().unregisterContentObserver(mSettingsObserver); 236 } 237 238 /** 239 * The format of the message PDU in the associated broadcast intent. 240 * This will be either "3gpp" for GSM/UMTS/LTE messages in 3GPP format 241 * or "3gpp2" for CDMA/LTE messages in 3GPP2 format. 242 * 243 * Note: All applications which handle incoming SMS messages by processing the 244 * SMS_RECEIVED_ACTION broadcast intent MUST pass the "format" extra from the intent 245 * into the new methods in {@link android.telephony.SmsMessage} which take an 246 * extra format parameter. This is required in order to correctly decode the PDU on 247 * devices which require support for both 3GPP and 3GPP2 formats at the same time, 248 * such as CDMA/LTE devices and GSM/CDMA world phones. 249 * 250 * @return the format of the message PDU 251 */ getFormat()252 protected abstract String getFormat(); 253 254 /** 255 * Pass the Message object to subclass to handle. Currently used to pass CDMA status reports 256 * from {@link com.android.internal.telephony.cdma.CdmaInboundSmsHandler}. 257 * @param o the SmsMessage containing the status report 258 */ handleStatusReport(Object o)259 protected void handleStatusReport(Object o) { 260 Rlog.d(TAG, "handleStatusReport() called with no subclass."); 261 } 262 263 /* TODO: Need to figure out how to keep track of status report routing in a 264 * persistent manner. If the phone process restarts (reboot or crash), 265 * we will lose this list and any status reports that come in after 266 * will be dropped. 267 */ 268 /** Sent messages awaiting a delivery status report. */ 269 @UnsupportedAppUsage 270 protected final ArrayList<SmsTracker> deliveryPendingList = new ArrayList<SmsTracker>(); 271 272 /** 273 * Handles events coming from the phone stack. Overridden from handler. 274 * 275 * @param msg the message to handle 276 */ 277 @Override handleMessage(Message msg)278 public void handleMessage(Message msg) { 279 switch (msg.what) { 280 case EVENT_SEND_SMS_COMPLETE: 281 // An outbound SMS has been successfully transferred, or failed. 282 handleSendComplete((AsyncResult) msg.obj); 283 break; 284 285 case EVENT_SEND_RETRY: 286 Rlog.d(TAG, "SMS retry.."); 287 sendRetrySms((SmsTracker) msg.obj); 288 break; 289 290 case EVENT_SEND_LIMIT_REACHED_CONFIRMATION: 291 handleReachSentLimit((SmsTracker[]) (msg.obj)); 292 break; 293 294 case EVENT_CONFIRM_SEND_TO_POSSIBLE_PREMIUM_SHORT_CODE: 295 handleConfirmShortCode(false, (SmsTracker[]) (msg.obj)); 296 break; 297 298 case EVENT_CONFIRM_SEND_TO_PREMIUM_SHORT_CODE: 299 handleConfirmShortCode(true, (SmsTracker[]) (msg.obj)); 300 break; 301 302 case EVENT_SEND_CONFIRMED_SMS: 303 { 304 SmsTracker[] trackers = (SmsTracker[]) msg.obj; 305 for (SmsTracker tracker : trackers) { 306 sendSms(tracker); 307 } 308 mPendingTrackerCount--; 309 break; 310 } 311 312 case EVENT_SENDING_NOT_ALLOWED: 313 { 314 SmsTracker[] trackers = (SmsTracker[]) msg.obj; 315 Rlog.d(TAG, "SMSDispatcher: EVENT_SENDING_NOT_ALLOWED - " 316 + "sending SHORT_CODE_NEVER_ALLOWED error code."); 317 handleSmsTrackersFailure( 318 trackers, RESULT_ERROR_SHORT_CODE_NEVER_ALLOWED, NO_ERROR_CODE); 319 break; 320 } 321 322 case EVENT_STOP_SENDING: 323 { 324 SmsTracker[] trackers = (SmsTracker[]) msg.obj; 325 int error; 326 if (msg.arg1 == ConfirmDialogListener.SHORT_CODE_MSG) { 327 if (msg.arg2 == ConfirmDialogListener.NEVER_ALLOW) { 328 error = RESULT_ERROR_SHORT_CODE_NEVER_ALLOWED; 329 Rlog.d(TAG, "SMSDispatcher: EVENT_STOP_SENDING - " 330 + "sending SHORT_CODE_NEVER_ALLOWED error code."); 331 } else { 332 error = RESULT_ERROR_SHORT_CODE_NOT_ALLOWED; 333 Rlog.d(TAG, "SMSDispatcher: EVENT_STOP_SENDING - " 334 + "sending SHORT_CODE_NOT_ALLOWED error code."); 335 } 336 } else if (msg.arg1 == ConfirmDialogListener.RATE_LIMIT) { 337 error = RESULT_ERROR_LIMIT_EXCEEDED; 338 Rlog.d(TAG, "SMSDispatcher: EVENT_STOP_SENDING - " 339 + "sending LIMIT_EXCEEDED error code."); 340 } else { 341 error = SmsManager.RESULT_UNEXPECTED_EVENT_STOP_SENDING; 342 Rlog.e(TAG, "SMSDispatcher: EVENT_STOP_SENDING - unexpected cases."); 343 } 344 345 handleSmsTrackersFailure(trackers, error, NO_ERROR_CODE); 346 mPendingTrackerCount--; 347 break; 348 } 349 350 case EVENT_HANDLE_STATUS_REPORT: 351 handleStatusReport(msg.obj); 352 break; 353 354 default: 355 Rlog.e(TAG, "handleMessage() ignoring message of unexpected type " + msg.what); 356 } 357 } 358 359 /** 360 * Use the carrier messaging service to send a data or text SMS. 361 */ 362 protected abstract class SmsSender extends CarrierMessagingServiceWrapper { 363 protected final SmsTracker mTracker; 364 // Initialized in sendSmsByCarrierApp 365 protected volatile SmsSenderCallback mSenderCallback; 366 SmsSender(SmsTracker tracker)367 protected SmsSender(SmsTracker tracker) { 368 mTracker = tracker; 369 } 370 sendSmsByCarrierApp(String carrierPackageName, SmsSenderCallback senderCallback)371 public void sendSmsByCarrierApp(String carrierPackageName, 372 SmsSenderCallback senderCallback) { 373 mSenderCallback = senderCallback; 374 if (!bindToCarrierMessagingService(mContext, carrierPackageName)) { 375 Rlog.e(TAG, "bindService() for carrier messaging service failed"); 376 mSenderCallback.onSendSmsComplete( 377 CarrierMessagingService.SEND_STATUS_RETRY_ON_CARRIER_NETWORK, 378 0 /* messageRef */); 379 } else { 380 Rlog.d(TAG, "bindService() for carrier messaging service succeeded"); 381 } 382 } 383 } 384 385 /** 386 * Use the carrier messaging service to send a text SMS. 387 */ 388 protected final class TextSmsSender extends SmsSender { TextSmsSender(SmsTracker tracker)389 public TextSmsSender(SmsTracker tracker) { 390 super(tracker); 391 } 392 393 @Override onServiceReady()394 public void onServiceReady() { 395 HashMap<String, Object> map = mTracker.getData(); 396 String text = (String) map.get(MAP_KEY_TEXT); 397 398 if (text != null) { 399 try { 400 sendTextSms( 401 text, 402 getSubId(), 403 mTracker.mDestAddress, 404 (mTracker.mDeliveryIntent != null) 405 ? CarrierMessagingService.SEND_FLAG_REQUEST_DELIVERY_STATUS 406 : 0, 407 mSenderCallback); 408 } catch (RuntimeException e) { 409 Rlog.e(TAG, "Exception sending the SMS: " + e); 410 mSenderCallback.onSendSmsComplete( 411 CarrierMessagingService.SEND_STATUS_RETRY_ON_CARRIER_NETWORK, 412 0 /* messageRef */); 413 } 414 } else { 415 mSenderCallback.onSendSmsComplete( 416 CarrierMessagingService.SEND_STATUS_RETRY_ON_CARRIER_NETWORK, 417 0 /* messageRef */); 418 } 419 } 420 } 421 422 /** 423 * Use the carrier messaging service to send a data SMS. 424 */ 425 protected final class DataSmsSender extends SmsSender { DataSmsSender(SmsTracker tracker)426 public DataSmsSender(SmsTracker tracker) { 427 super(tracker); 428 } 429 430 @Override onServiceReady()431 public void onServiceReady() { 432 HashMap<String, Object> map = mTracker.getData(); 433 byte[] data = (byte[]) map.get(MAP_KEY_DATA); 434 int destPort = (int) map.get(MAP_KEY_DEST_PORT); 435 436 if (data != null) { 437 try { 438 sendDataSms( 439 data, 440 getSubId(), 441 mTracker.mDestAddress, 442 destPort, 443 (mTracker.mDeliveryIntent != null) 444 ? CarrierMessagingService.SEND_FLAG_REQUEST_DELIVERY_STATUS 445 : 0, 446 mSenderCallback); 447 } catch (RuntimeException e) { 448 Rlog.e(TAG, "Exception sending the SMS: " + e 449 + " id: " + mTracker.mMessageId); 450 mSenderCallback.onSendSmsComplete( 451 CarrierMessagingService.SEND_STATUS_RETRY_ON_CARRIER_NETWORK, 452 0 /* messageRef */); 453 } 454 } else { 455 mSenderCallback.onSendSmsComplete( 456 CarrierMessagingService.SEND_STATUS_RETRY_ON_CARRIER_NETWORK, 457 0 /* messageRef */); 458 } 459 } 460 } 461 462 /** 463 * Callback for TextSmsSender and DataSmsSender from the carrier messaging service. 464 * Once the result is ready, the carrier messaging service connection is disposed. 465 */ 466 protected final class SmsSenderCallback extends 467 CarrierMessagingServiceWrapper.CarrierMessagingCallbackWrapper { 468 private final SmsSender mSmsSender; 469 SmsSenderCallback(SmsSender smsSender)470 public SmsSenderCallback(SmsSender smsSender) { 471 mSmsSender = smsSender; 472 } 473 474 /** 475 * This method should be called only once. 476 */ 477 @Override onSendSmsComplete(int result, int messageRef)478 public void onSendSmsComplete(int result, int messageRef) { 479 checkCallerIsPhoneOrCarrierApp(); 480 final long identity = Binder.clearCallingIdentity(); 481 try { 482 mSmsSender.disposeConnection(mContext); 483 processSendSmsResponse(mSmsSender.mTracker, result, messageRef); 484 } finally { 485 Binder.restoreCallingIdentity(identity); 486 } 487 } 488 489 @Override onSendMultipartSmsComplete(int result, int[] messageRefs)490 public void onSendMultipartSmsComplete(int result, int[] messageRefs) { 491 Rlog.e(TAG, "Unexpected onSendMultipartSmsComplete call with result: " + result); 492 } 493 494 @Override onFilterComplete(int result)495 public void onFilterComplete(int result) { 496 Rlog.e(TAG, "Unexpected onFilterComplete call with result: " + result); 497 } 498 499 @Override onSendMmsComplete(int result, byte[] sendConfPdu)500 public void onSendMmsComplete(int result, byte[] sendConfPdu) { 501 Rlog.e(TAG, "Unexpected onSendMmsComplete call with result: " + result); 502 } 503 504 @Override onDownloadMmsComplete(int result)505 public void onDownloadMmsComplete(int result) { 506 Rlog.e(TAG, "Unexpected onDownloadMmsComplete call with result: " + result); 507 } 508 } 509 510 @UnsupportedAppUsage processSendSmsResponse(SmsTracker tracker, int result, int messageRef)511 private void processSendSmsResponse(SmsTracker tracker, int result, int messageRef) { 512 if (tracker == null) { 513 Rlog.e(TAG, "processSendSmsResponse: null tracker"); 514 return; 515 } 516 517 SmsResponse smsResponse = new SmsResponse(messageRef, null /* ackPdu */, NO_ERROR_CODE); 518 519 switch (result) { 520 case CarrierMessagingService.SEND_STATUS_OK: 521 Rlog.d(TAG, "Sending SMS by IP succeeded." 522 + " id: " + tracker.mMessageId); 523 sendMessage(obtainMessage(EVENT_SEND_SMS_COMPLETE, 524 new AsyncResult(tracker, 525 smsResponse, 526 null /* exception*/))); 527 break; 528 case CarrierMessagingService.SEND_STATUS_ERROR: 529 Rlog.d(TAG, "Sending SMS by IP failed." 530 + " id: " + tracker.mMessageId); 531 sendMessage(obtainMessage(EVENT_SEND_SMS_COMPLETE, 532 new AsyncResult(tracker, smsResponse, 533 new CommandException(CommandException.Error.GENERIC_FAILURE)))); 534 break; 535 case CarrierMessagingService.SEND_STATUS_RETRY_ON_CARRIER_NETWORK: 536 Rlog.d(TAG, "Sending SMS by IP failed. Retry on carrier network." 537 + " id: " + tracker.mMessageId); 538 sendSubmitPdu(tracker); 539 break; 540 default: 541 Rlog.d(TAG, "Unknown result " + result + " Retry on carrier network." 542 + " id: " + tracker.mMessageId); 543 sendSubmitPdu(tracker); 544 } 545 } 546 547 /** 548 * Use the carrier messaging service to send a multipart text SMS. 549 */ 550 private final class MultipartSmsSender extends CarrierMessagingServiceWrapper { 551 private final List<String> mParts; 552 public final SmsTracker[] mTrackers; 553 // Initialized in sendSmsByCarrierApp 554 private volatile MultipartSmsSenderCallback mSenderCallback; 555 MultipartSmsSender(ArrayList<String> parts, SmsTracker[] trackers)556 MultipartSmsSender(ArrayList<String> parts, SmsTracker[] trackers) { 557 mParts = parts; 558 mTrackers = trackers; 559 } 560 561 @UnsupportedAppUsage sendSmsByCarrierApp(String carrierPackageName, MultipartSmsSenderCallback senderCallback)562 void sendSmsByCarrierApp(String carrierPackageName, 563 MultipartSmsSenderCallback senderCallback) { 564 mSenderCallback = senderCallback; 565 if (!bindToCarrierMessagingService(mContext, carrierPackageName)) { 566 Rlog.e(TAG, "bindService() for carrier messaging service failed"); 567 mSenderCallback.onSendMultipartSmsComplete( 568 CarrierMessagingService.SEND_STATUS_RETRY_ON_CARRIER_NETWORK, 569 null /* smsResponse */); 570 } else { 571 Rlog.d(TAG, "bindService() for carrier messaging service succeeded"); 572 } 573 } 574 575 @Override onServiceReady()576 public void onServiceReady() { 577 boolean statusReportRequested = false; 578 for (SmsTracker tracker : mTrackers) { 579 if (tracker.mDeliveryIntent != null) { 580 statusReportRequested = true; 581 break; 582 } 583 } 584 585 try { 586 sendMultipartTextSms( 587 mParts, 588 getSubId(), 589 mTrackers[0].mDestAddress, 590 statusReportRequested 591 ? CarrierMessagingService.SEND_FLAG_REQUEST_DELIVERY_STATUS 592 : 0, 593 mSenderCallback); 594 } catch (RuntimeException e) { 595 Rlog.e(TAG, "Exception sending the SMS: " + e); 596 mSenderCallback.onSendMultipartSmsComplete( 597 CarrierMessagingService.SEND_STATUS_RETRY_ON_CARRIER_NETWORK, 598 null /* smsResponse */); 599 } 600 } 601 } 602 603 /** 604 * Callback for MultipartSmsSender from the carrier messaging service. 605 * Once the result is ready, the carrier messaging service connection is disposed. 606 */ 607 private final class MultipartSmsSenderCallback extends CarrierMessagingCallbackWrapper { 608 private final MultipartSmsSender mSmsSender; 609 MultipartSmsSenderCallback(MultipartSmsSender smsSender)610 MultipartSmsSenderCallback(MultipartSmsSender smsSender) { 611 mSmsSender = smsSender; 612 } 613 614 @Override onSendSmsComplete(int result, int messageRef)615 public void onSendSmsComplete(int result, int messageRef) { 616 Rlog.e(TAG, "Unexpected onSendSmsComplete call with result: " + result); 617 } 618 619 /** 620 * This method should be called only once. 621 */ 622 @Override onSendMultipartSmsComplete(int result, int[] messageRefs)623 public void onSendMultipartSmsComplete(int result, int[] messageRefs) { 624 mSmsSender.disposeConnection(mContext); 625 626 if (mSmsSender.mTrackers == null) { 627 Rlog.e(TAG, "Unexpected onSendMultipartSmsComplete call with null trackers."); 628 return; 629 } 630 631 checkCallerIsPhoneOrCarrierApp(); 632 final long identity = Binder.clearCallingIdentity(); 633 try { 634 for (int i = 0; i < mSmsSender.mTrackers.length; i++) { 635 int messageRef = 0; 636 if (messageRefs != null && messageRefs.length > i) { 637 messageRef = messageRefs[i]; 638 } 639 processSendSmsResponse(mSmsSender.mTrackers[i], result, messageRef); 640 } 641 } finally { 642 Binder.restoreCallingIdentity(identity); 643 } 644 } 645 646 @Override onFilterComplete(int result)647 public void onFilterComplete(int result) { 648 Rlog.e(TAG, "Unexpected onFilterComplete call with result: " + result); 649 } 650 651 @Override onSendMmsComplete(int result, byte[] sendConfPdu)652 public void onSendMmsComplete(int result, byte[] sendConfPdu) { 653 Rlog.e(TAG, "Unexpected onSendMmsComplete call with result: " + result); 654 } 655 656 @Override onDownloadMmsComplete(int result)657 public void onDownloadMmsComplete(int result) { 658 Rlog.e(TAG, "Unexpected onDownloadMmsComplete call with result: " + result); 659 } 660 } 661 662 /** Send a single SMS PDU. */ 663 @UnsupportedAppUsage sendSubmitPdu(SmsTracker tracker)664 private void sendSubmitPdu(SmsTracker tracker) { 665 sendSubmitPdu(new SmsTracker[] {tracker}); 666 } 667 668 /** Send a multi-part SMS PDU. Usually just calls {@link sendRawPdu}. */ sendSubmitPdu(SmsTracker[] trackers)669 private void sendSubmitPdu(SmsTracker[] trackers) { 670 if (shouldBlockSmsForEcbm()) { 671 Rlog.d(TAG, "Block SMS in Emergency Callback mode"); 672 handleSmsTrackersFailure(trackers, SmsManager.RESULT_SMS_BLOCKED_DURING_EMERGENCY, 673 NO_ERROR_CODE); 674 } else { 675 sendRawPdu(trackers); 676 } 677 } 678 679 /** 680 * @return true if MO SMS should be blocked for Emergency Callback Mode. 681 */ shouldBlockSmsForEcbm()682 protected abstract boolean shouldBlockSmsForEcbm(); 683 684 /** 685 * Called when SMS send completes. Broadcasts a sentIntent on success. 686 * On failure, either sets up retries or broadcasts a sentIntent with 687 * the failure in the result code. 688 * 689 * @param ar AsyncResult passed into the message handler. ar.result should 690 * an SmsResponse instance if send was successful. ar.userObj 691 * should be an SmsTracker instance. 692 */ handleSendComplete(AsyncResult ar)693 protected void handleSendComplete(AsyncResult ar) { 694 SmsTracker tracker = (SmsTracker) ar.userObj; 695 PendingIntent sentIntent = tracker.mSentIntent; 696 697 if (ar.result != null) { 698 tracker.mMessageRef = ((SmsResponse)ar.result).mMessageRef; 699 } else { 700 Rlog.d(TAG, "SmsResponse was null"); 701 } 702 703 if (ar.exception == null) { 704 if (DBG) { 705 Rlog.d(TAG, "SMS send complete. Broadcasting intent: " + sentIntent 706 + " id: " + tracker.mMessageId); 707 } 708 709 if (tracker.mDeliveryIntent != null) { 710 // Expecting a status report. Add it to the list. 711 deliveryPendingList.add(tracker); 712 } 713 tracker.onSent(mContext); 714 mPhone.notifySmsSent(tracker.mDestAddress); 715 } else { 716 if (DBG) { 717 Rlog.d(TAG, "SMS send failed" 718 + " id: " + tracker.mMessageId); 719 } 720 721 int ss = mPhone.getServiceState().getState(); 722 723 if ( tracker.mImsRetry > 0 && ss != ServiceState.STATE_IN_SERVICE) { 724 // This is retry after failure over IMS but voice is not available. 725 // Set retry to max allowed, so no retry is sent and 726 // cause RESULT_ERROR_GENERIC_FAILURE to be returned to app. 727 tracker.mRetryCount = MAX_SEND_RETRIES; 728 729 Rlog.d(TAG, "handleSendComplete: Skipping retry: " 730 + " isIms()=" + isIms() 731 + " mRetryCount=" + tracker.mRetryCount 732 + " mImsRetry=" + tracker.mImsRetry 733 + " mMessageRef=" + tracker.mMessageRef 734 + " SS= " + mPhone.getServiceState().getState() 735 + " id=" + tracker.mMessageId); 736 } 737 738 // if sms over IMS is not supported on data and voice is not available... 739 if (!isIms() && ss != ServiceState.STATE_IN_SERVICE) { 740 tracker.onFailed(mContext, getNotInServiceError(ss), NO_ERROR_CODE); 741 } else if ((((CommandException)(ar.exception)).getCommandError() 742 == CommandException.Error.SMS_FAIL_RETRY) && 743 tracker.mRetryCount < MAX_SEND_RETRIES) { 744 // Retry after a delay if needed. 745 // TODO: According to TS 23.040, 9.2.3.6, we should resend 746 // with the same TP-MR as the failed message, and 747 // TP-RD set to 1. However, we don't have a means of 748 // knowing the MR for the failed message (EF_SMSstatus 749 // may or may not have the MR corresponding to this 750 // message, depending on the failure). Also, in some 751 // implementations this retry is handled by the baseband. 752 tracker.mRetryCount++; 753 Message retryMsg = obtainMessage(EVENT_SEND_RETRY, tracker); 754 sendMessageDelayed(retryMsg, SEND_RETRY_DELAY); 755 } else { 756 int errorCode = NO_ERROR_CODE; 757 if (ar.result != null) { 758 errorCode = ((SmsResponse)ar.result).mErrorCode; 759 } 760 int error = rilErrorToSmsManagerResult(((CommandException) (ar.exception)) 761 .getCommandError()); 762 tracker.onFailed(mContext, error, errorCode); 763 } 764 } 765 } 766 rilErrorToSmsManagerResult(CommandException.Error rilError)767 private static int rilErrorToSmsManagerResult(CommandException.Error rilError) { 768 switch (rilError) { 769 case RADIO_NOT_AVAILABLE: 770 return SmsManager.RESULT_RIL_RADIO_NOT_AVAILABLE; 771 case SMS_FAIL_RETRY: 772 return SmsManager.RESULT_RIL_SMS_SEND_FAIL_RETRY; 773 case NETWORK_REJECT: 774 return SmsManager.RESULT_RIL_NETWORK_REJECT; 775 case INVALID_STATE: 776 return SmsManager.RESULT_RIL_INVALID_STATE; 777 case INVALID_ARGUMENTS: 778 return SmsManager.RESULT_RIL_INVALID_ARGUMENTS; 779 case NO_MEMORY: 780 return SmsManager.RESULT_RIL_NO_MEMORY; 781 case REQUEST_RATE_LIMITED: 782 return SmsManager.RESULT_RIL_REQUEST_RATE_LIMITED; 783 case INVALID_SMS_FORMAT: 784 return SmsManager.RESULT_RIL_INVALID_SMS_FORMAT; 785 case SYSTEM_ERR: 786 return SmsManager.RESULT_RIL_SYSTEM_ERR; 787 case ENCODING_ERR: 788 return SmsManager.RESULT_RIL_ENCODING_ERR; 789 case MODEM_ERR: 790 return SmsManager.RESULT_RIL_MODEM_ERR; 791 case NETWORK_ERR: 792 return SmsManager.RESULT_RIL_NETWORK_ERR; 793 case INTERNAL_ERR: 794 return SmsManager.RESULT_RIL_INTERNAL_ERR; 795 case REQUEST_NOT_SUPPORTED: 796 return SmsManager.RESULT_RIL_REQUEST_NOT_SUPPORTED; 797 case INVALID_MODEM_STATE: 798 return SmsManager.RESULT_RIL_INVALID_MODEM_STATE; 799 case NETWORK_NOT_READY: 800 return SmsManager.RESULT_RIL_NETWORK_NOT_READY; 801 case OPERATION_NOT_ALLOWED: 802 return SmsManager.RESULT_RIL_OPERATION_NOT_ALLOWED; 803 case NO_RESOURCES: 804 return SmsManager.RESULT_RIL_NO_RESOURCES; 805 case REQUEST_CANCELLED: 806 return SmsManager.RESULT_RIL_CANCELLED; 807 case SIM_ABSENT: 808 return SmsManager.RESULT_RIL_SIM_ABSENT; 809 case FDN_CHECK_FAILURE: 810 return SmsManager.RESULT_ERROR_FDN_CHECK_FAILURE; 811 default: 812 return RESULT_ERROR_GENERIC_FAILURE; 813 } 814 } 815 816 /** 817 * Handles outbound message when the phone is not in service. 818 * 819 * @param ss Current service state. Valid values are: 820 * OUT_OF_SERVICE 821 * EMERGENCY_ONLY 822 * POWER_OFF 823 * @param sentIntent the PendingIntent to send the error to 824 */ handleNotInService(int ss, PendingIntent sentIntent)825 protected static void handleNotInService(int ss, PendingIntent sentIntent) { 826 if (sentIntent != null) { 827 try { 828 if (ss == ServiceState.STATE_POWER_OFF) { 829 sentIntent.send(RESULT_ERROR_RADIO_OFF); 830 } else { 831 sentIntent.send(RESULT_ERROR_NO_SERVICE); 832 } 833 } catch (CanceledException ex) { 834 Rlog.e(TAG, "Failed to send result"); 835 } 836 } 837 } 838 839 /** 840 * @param ss service state 841 * @return The result error based on input service state for not in service error 842 */ getNotInServiceError(int ss)843 protected static int getNotInServiceError(int ss) { 844 if (ss == ServiceState.STATE_POWER_OFF) { 845 return RESULT_ERROR_RADIO_OFF; 846 } 847 return RESULT_ERROR_NO_SERVICE; 848 } 849 850 /** 851 * Send a data based SMS to a specific application port. 852 * 853 * @param callingPackage the package name of the calling app 854 * @param destAddr the address to send the message to 855 * @param scAddr is the service center address or null to use 856 * the current default SMSC 857 * @param destPort the port to deliver the message to 858 * @param data the body of the message to send 859 * @param sentIntent if not NULL this <code>PendingIntent</code> is 860 * broadcast when the message is successfully sent, or failed. 861 * The result code will be <code>Activity.RESULT_OK<code> for success, 862 * or one of these errors:<br> 863 * <code>RESULT_ERROR_GENERIC_FAILURE</code><br> 864 * <code>RESULT_ERROR_RADIO_OFF</code><br> 865 * <code>RESULT_ERROR_NULL_PDU</code><br> 866 * <code>RESULT_ERROR_NO_SERVICE</code><br>. 867 * For <code>RESULT_ERROR_GENERIC_FAILURE</code> the sentIntent may include 868 * the extra "errorCode" containing a radio technology specific value, 869 * generally only useful for troubleshooting.<br> 870 * The per-application based SMS control checks sentIntent. If sentIntent 871 * is NULL the caller will be checked against all unknown applications, 872 * which cause smaller number of SMS to be sent in checking period. 873 * @param deliveryIntent if not NULL this <code>PendingIntent</code> is 874 * broadcast when the message is delivered to the recipient. The 875 * raw pdu of the status report is in the extended data ("pdu"). 876 */ 877 @UnsupportedAppUsage sendData(String callingPackage, String destAddr, String scAddr, int destPort, byte[] data, PendingIntent sentIntent, PendingIntent deliveryIntent, boolean isForVvm)878 protected void sendData(String callingPackage, String destAddr, String scAddr, int destPort, 879 byte[] data, PendingIntent sentIntent, PendingIntent deliveryIntent, boolean isForVvm) { 880 SmsMessageBase.SubmitPduBase pdu = getSubmitPdu( 881 scAddr, destAddr, destPort, data, (deliveryIntent != null)); 882 if (pdu != null) { 883 HashMap map = getSmsTrackerMap(destAddr, scAddr, destPort, data, pdu); 884 SmsTracker tracker = getSmsTracker(callingPackage, map, sentIntent, deliveryIntent, 885 getFormat(), null /*messageUri*/, false /*expectMore*/, 886 null /*fullMessageText*/, false /*isText*/, 887 true /*persistMessage*/, isForVvm, 0L /* messageId */); 888 889 if (!sendSmsByCarrierApp(true /* isDataSms */, tracker)) { 890 sendSubmitPdu(tracker); 891 } 892 } else { 893 Rlog.e(TAG, "SMSDispatcher.sendData(): getSubmitPdu() returned null"); 894 triggerSentIntentForFailure(sentIntent); 895 } 896 } 897 898 /** 899 * Send a text based SMS. 900 * @param destAddr the address to send the message to 901 * @param scAddr is the service center address or null to use 902 * the current default SMSC 903 * @param text the body of the message to send 904 * @param sentIntent if not NULL this <code>PendingIntent</code> is 905 * broadcast when the message is successfully sent, or failed. 906 * The result code will be <code>Activity.RESULT_OK<code> for success, 907 * or one of these errors:<br> 908 * <code>RESULT_ERROR_GENERIC_FAILURE</code><br> 909 * <code>RESULT_ERROR_RADIO_OFF</code><br> 910 * <code>RESULT_ERROR_NULL_PDU</code><br> 911 * <code>RESULT_ERROR_NO_SERVICE</code><br>. 912 * For <code>RESULT_ERROR_GENERIC_FAILURE</code> the sentIntent may include 913 * the extra "errorCode" containing a radio technology specific value, 914 * generally only useful for troubleshooting.<br> 915 * The per-application based SMS control checks sentIntent. If sentIntent 916 * is NULL the caller will be checked against all unknown applications, 917 * which cause smaller number of SMS to be sent in checking period. 918 * @param deliveryIntent if not NULL this <code>PendingIntent</code> is 919 * broadcast when the message is delivered to the recipient. The 920 * @param messageUri optional URI of the message if it is already stored in the system 921 * @param callingPkg the calling package name 922 * @param persistMessage whether to save the sent message into SMS DB for a 923 * non-default SMS app. 924 * 925 * @param priority Priority level of the message 926 * Refer specification See 3GPP2 C.S0015-B, v2.0, table 4.5.9-1 927 * --------------------------------- 928 * PRIORITY | Level of Priority 929 * --------------------------------- 930 * '00' | Normal 931 * '01' | Interactive 932 * '10' | Urgent 933 * '11' | Emergency 934 * ---------------------------------- 935 * Any Other values included Negative considered as Invalid Priority Indicator of the message. 936 * @param expectMore is a boolean to indicate the sending messages through same link or not. 937 * @param validityPeriod Validity Period of the message in mins. 938 * Refer specification 3GPP TS 23.040 V6.8.1 section 9.2.3.12.1. 939 * Validity Period(Minimum) -> 5 mins 940 * Validity Period(Maximum) -> 635040 mins(i.e.63 weeks). 941 * Any Other values included Negative considered as Invalid Validity Period of the message. 942 * @param messageId An id that uniquely identifies the message requested to be sent. 943 * Used for logging and diagnostics purposes. The id may be NULL. 944 */ sendText(String destAddr, String scAddr, String text, PendingIntent sentIntent, PendingIntent deliveryIntent, Uri messageUri, String callingPkg, boolean persistMessage, int priority, boolean expectMore, int validityPeriod, boolean isForVvm, long messageId)945 public void sendText(String destAddr, String scAddr, String text, 946 PendingIntent sentIntent, PendingIntent deliveryIntent, Uri messageUri, 947 String callingPkg, boolean persistMessage, int priority, 948 boolean expectMore, int validityPeriod, boolean isForVvm, 949 long messageId) { 950 Rlog.d(TAG, "sendText id: " + messageId); 951 SmsMessageBase.SubmitPduBase pdu = getSubmitPdu( 952 scAddr, destAddr, text, (deliveryIntent != null), null, priority, validityPeriod); 953 if (pdu != null) { 954 HashMap map = getSmsTrackerMap(destAddr, scAddr, text, pdu); 955 SmsTracker tracker = getSmsTracker(callingPkg, map, sentIntent, deliveryIntent, 956 getFormat(), messageUri, expectMore, text, true /*isText*/, 957 persistMessage, priority, validityPeriod, isForVvm, messageId); 958 959 if (!sendSmsByCarrierApp(false /* isDataSms */, tracker)) { 960 sendSubmitPdu(tracker); 961 } 962 } else { 963 Rlog.e(TAG, "SmsDispatcher.sendText(): getSubmitPdu() returned null" + " id: " 964 + messageId); 965 triggerSentIntentForFailure(sentIntent); 966 } 967 } 968 triggerSentIntentForFailure(PendingIntent sentIntent)969 private void triggerSentIntentForFailure(PendingIntent sentIntent) { 970 if (sentIntent != null) { 971 try { 972 sentIntent.send(RESULT_ERROR_GENERIC_FAILURE); 973 } catch (CanceledException ex) { 974 Rlog.e(TAG, "Intent has been canceled!"); 975 } 976 } 977 } 978 triggerSentIntentForFailure(List<PendingIntent> sentIntents)979 private void triggerSentIntentForFailure(List<PendingIntent> sentIntents) { 980 if (sentIntents == null) { 981 return; 982 } 983 984 for (PendingIntent sentIntent : sentIntents) { 985 triggerSentIntentForFailure(sentIntent); 986 } 987 } 988 sendSmsByCarrierApp(boolean isDataSms, SmsTracker tracker )989 private boolean sendSmsByCarrierApp(boolean isDataSms, SmsTracker tracker ) { 990 String carrierPackage = getCarrierAppPackageName(); 991 if (carrierPackage != null) { 992 Rlog.d(TAG, "Found carrier package."); 993 SmsSender smsSender; 994 if (isDataSms) { 995 smsSender = new DataSmsSender(tracker); 996 } else { 997 smsSender = new TextSmsSender(tracker); 998 } 999 smsSender.sendSmsByCarrierApp(carrierPackage, new SmsSenderCallback(smsSender)); 1000 return true; 1001 } 1002 1003 return false; 1004 } 1005 getSubmitPdu(String scAddr, String destAddr, String message, boolean statusReportRequested, SmsHeader smsHeader, int priority, int validityPeriod)1006 protected abstract SmsMessageBase.SubmitPduBase getSubmitPdu(String scAddr, String destAddr, 1007 String message, boolean statusReportRequested, SmsHeader smsHeader, 1008 int priority, int validityPeriod); 1009 getSubmitPdu(String scAddr, String destAddr, int destPort, byte[] message, boolean statusReportRequested)1010 protected abstract SmsMessageBase.SubmitPduBase getSubmitPdu(String scAddr, String destAddr, 1011 int destPort, byte[] message, boolean statusReportRequested); 1012 1013 /** 1014 * Calculate the number of septets needed to encode the message. This function should only be 1015 * called for individual segments of multipart message. 1016 * 1017 * @param messageBody the message to encode 1018 * @param use7bitOnly ignore (but still count) illegal characters if true 1019 * @return TextEncodingDetails 1020 */ 1021 @UnsupportedAppUsage calculateLength(CharSequence messageBody, boolean use7bitOnly)1022 protected abstract TextEncodingDetails calculateLength(CharSequence messageBody, 1023 boolean use7bitOnly); 1024 1025 /** 1026 * Send a multi-part text based SMS. 1027 * @param destAddr the address to send the message to 1028 * @param scAddr is the service center address or null to use 1029 * the current default SMSC 1030 * @param parts an <code>ArrayList</code> of strings that, in order, 1031 * comprise the original message 1032 * @param sentIntents if not null, an <code>ArrayList</code> of 1033 * <code>PendingIntent</code>s (one for each message part) that is 1034 * broadcast when the corresponding message part has been sent. 1035 * The result code will be <code>Activity.RESULT_OK<code> for success, 1036 * or one of these errors: 1037 * <code>RESULT_ERROR_GENERIC_FAILURE</code> 1038 * <code>RESULT_ERROR_RADIO_OFF</code> 1039 * <code>RESULT_ERROR_NULL_PDU</code> 1040 * <code>RESULT_ERROR_NO_SERVICE</code>. 1041 * The per-application based SMS control checks sentIntent. If sentIntent 1042 * is NULL the caller will be checked against all unknown applications, 1043 * which cause smaller number of SMS to be sent in checking period. 1044 * @param deliveryIntents if not null, an <code>ArrayList</code> of 1045 * <code>PendingIntent</code>s (one for each message part) that is 1046 * broadcast when the corresponding message part has been delivered 1047 * to the recipient. The raw pdu of the status report is in the 1048 * @param messageUri optional URI of the message if it is already stored in the system 1049 * @param callingPkg the calling package name 1050 * @param persistMessage whether to save the sent message into SMS DB for a 1051 * non-default SMS app. 1052 * @param priority Priority level of the message 1053 * Refer specification See 3GPP2 C.S0015-B, v2.0, table 4.5.9-1 1054 * --------------------------------- 1055 * PRIORITY | Level of Priority 1056 * --------------------------------- 1057 * '00' | Normal 1058 * '01' | Interactive 1059 * '10' | Urgent 1060 * '11' | Emergency 1061 * ---------------------------------- 1062 * Any Other values included Negative considered as Invalid Priority Indicator of the message. 1063 * @param expectMore is a boolean to indicate the sending messages through same link or not. 1064 * @param validityPeriod Validity Period of the message in mins. 1065 * Refer specification 3GPP TS 23.040 V6.8.1 section 9.2.3.12.1. 1066 * Validity Period(Minimum) -> 5 mins 1067 * Validity Period(Maximum) -> 635040 mins(i.e.63 weeks). 1068 * Any Other values included Negative considered as Invalid Validity Period of the message. 1069 */ 1070 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PROTECTED) sendMultipartText(String destAddr, String scAddr, ArrayList<String> parts, ArrayList<PendingIntent> sentIntents, ArrayList<PendingIntent> deliveryIntents, Uri messageUri, String callingPkg, boolean persistMessage, int priority, boolean expectMore, int validityPeriod, long messageId)1071 public void sendMultipartText(String destAddr, String scAddr, 1072 ArrayList<String> parts, ArrayList<PendingIntent> sentIntents, 1073 ArrayList<PendingIntent> deliveryIntents, Uri messageUri, String callingPkg, 1074 boolean persistMessage, int priority, boolean expectMore, int validityPeriod, 1075 long messageId) { 1076 final String fullMessageText = getMultipartMessageText(parts); 1077 int refNumber = getNextConcatenatedRef() & 0x00FF; 1078 int encoding = SmsConstants.ENCODING_UNKNOWN; 1079 int msgCount = parts.size(); 1080 if (msgCount < 1) { 1081 triggerSentIntentForFailure(sentIntents); 1082 return; 1083 } 1084 1085 TextEncodingDetails[] encodingForParts = new TextEncodingDetails[msgCount]; 1086 for (int i = 0; i < msgCount; i++) { 1087 TextEncodingDetails details = calculateLength(parts.get(i), false); 1088 if (encoding != details.codeUnitSize 1089 && (encoding == SmsConstants.ENCODING_UNKNOWN 1090 || encoding == SmsConstants.ENCODING_7BIT)) { 1091 encoding = details.codeUnitSize; 1092 } 1093 encodingForParts[i] = details; 1094 } 1095 1096 SmsTracker[] trackers = new SmsTracker[msgCount]; 1097 1098 // States to track at the message level (for all parts) 1099 final AtomicInteger unsentPartCount = new AtomicInteger(msgCount); 1100 final AtomicBoolean anyPartFailed = new AtomicBoolean(false); 1101 1102 for (int i = 0; i < msgCount; i++) { 1103 SmsHeader.ConcatRef concatRef = new SmsHeader.ConcatRef(); 1104 concatRef.refNumber = refNumber; 1105 concatRef.seqNumber = i + 1; // 1-based sequence 1106 concatRef.msgCount = msgCount; 1107 // TODO: We currently set this to true since our messaging app will never 1108 // send more than 255 parts (it converts the message to MMS well before that). 1109 // However, we should support 3rd party messaging apps that might need 16-bit 1110 // references 1111 // Note: It's not sufficient to just flip this bit to true; it will have 1112 // ripple effects (several calculations assume 8-bit ref). 1113 concatRef.isEightBits = true; 1114 SmsHeader smsHeader = new SmsHeader(); 1115 smsHeader.concatRef = concatRef; 1116 1117 // Set the national language tables for 3GPP 7-bit encoding, if enabled. 1118 if (encoding == SmsConstants.ENCODING_7BIT) { 1119 smsHeader.languageTable = encodingForParts[i].languageTable; 1120 smsHeader.languageShiftTable = encodingForParts[i].languageShiftTable; 1121 } 1122 1123 PendingIntent sentIntent = null; 1124 if (sentIntents != null && sentIntents.size() > i) { 1125 sentIntent = sentIntents.get(i); 1126 } 1127 1128 PendingIntent deliveryIntent = null; 1129 if (deliveryIntents != null && deliveryIntents.size() > i) { 1130 deliveryIntent = deliveryIntents.get(i); 1131 } 1132 1133 trackers[i] = 1134 getNewSubmitPduTracker(callingPkg, destAddr, scAddr, parts.get(i), smsHeader, 1135 encoding, sentIntent, deliveryIntent, (i == (msgCount - 1)), 1136 unsentPartCount, anyPartFailed, messageUri, 1137 fullMessageText, priority, expectMore, validityPeriod, messageId); 1138 if (trackers[i] == null) { 1139 triggerSentIntentForFailure(sentIntents); 1140 return; 1141 } 1142 trackers[i].mPersistMessage = persistMessage; 1143 } 1144 1145 String carrierPackage = getCarrierAppPackageName(); 1146 if (carrierPackage != null) { 1147 Rlog.d(TAG, "Found carrier package." 1148 + " id: " + getMultiTrackermessageId(trackers)); 1149 MultipartSmsSender smsSender = new MultipartSmsSender(parts, trackers); 1150 smsSender.sendSmsByCarrierApp(carrierPackage, 1151 new MultipartSmsSenderCallback(smsSender)); 1152 } else { 1153 Rlog.v(TAG, "No carrier package." 1154 + " id: " + getMultiTrackermessageId(trackers)); 1155 sendSubmitPdu(trackers); 1156 } 1157 } 1158 getMultiTrackermessageId(SmsTracker[] trackers)1159 private long getMultiTrackermessageId(SmsTracker[] trackers) { 1160 if (trackers.length == 0) { 1161 return 0L; 1162 } 1163 return trackers[0].mMessageId; 1164 } 1165 1166 /** 1167 * Create a new SubmitPdu and return the SMS tracker. 1168 */ getNewSubmitPduTracker(String callingPackage, String destinationAddress, String scAddress, String message, SmsHeader smsHeader, int encoding, PendingIntent sentIntent, PendingIntent deliveryIntent, boolean lastPart, AtomicInteger unsentPartCount, AtomicBoolean anyPartFailed, Uri messageUri, String fullMessageText, int priority, boolean expectMore, int validityPeriod, long messageId)1169 private SmsTracker getNewSubmitPduTracker(String callingPackage, String destinationAddress, 1170 String scAddress, String message, SmsHeader smsHeader, int encoding, 1171 PendingIntent sentIntent, PendingIntent deliveryIntent, boolean lastPart, 1172 AtomicInteger unsentPartCount, AtomicBoolean anyPartFailed, Uri messageUri, 1173 String fullMessageText, int priority, boolean expectMore, int validityPeriod, 1174 long messageId) { 1175 if (isCdmaMo()) { 1176 UserData uData = new UserData(); 1177 uData.payloadStr = message; 1178 uData.userDataHeader = smsHeader; 1179 if (encoding == SmsConstants.ENCODING_7BIT) { 1180 uData.msgEncoding = isAscii7bitSupportedForLongMessage() 1181 ? UserData.ENCODING_7BIT_ASCII : UserData.ENCODING_GSM_7BIT_ALPHABET; 1182 Rlog.d(TAG, "Message encoding for proper 7 bit: " + uData.msgEncoding); 1183 } else { // assume UTF-16 1184 uData.msgEncoding = UserData.ENCODING_UNICODE_16; 1185 } 1186 uData.msgEncodingSet = true; 1187 1188 /* By setting the statusReportRequested bit only for the 1189 * last message fragment, this will result in only one 1190 * callback to the sender when that last fragment delivery 1191 * has been acknowledged. */ 1192 //TODO FIX 1193 SmsMessageBase.SubmitPduBase submitPdu = 1194 com.android.internal.telephony.cdma.SmsMessage.getSubmitPdu(destinationAddress, 1195 uData, (deliveryIntent != null) && lastPart, priority); 1196 1197 if (submitPdu != null) { 1198 HashMap map = getSmsTrackerMap(destinationAddress, scAddress, 1199 message, submitPdu); 1200 return getSmsTracker(callingPackage, map, sentIntent, deliveryIntent, 1201 getFormat(), unsentPartCount, anyPartFailed, messageUri, smsHeader, 1202 (!lastPart || expectMore), fullMessageText, true /*isText*/, 1203 true /*persistMessage*/, priority, validityPeriod, false /* isForVvm */, 1204 messageId); 1205 } else { 1206 Rlog.e(TAG, "CdmaSMSDispatcher.getNewSubmitPduTracker(): getSubmitPdu() returned " 1207 + "null" + " id: " + messageId); 1208 return null; 1209 } 1210 } else { 1211 SmsMessageBase.SubmitPduBase pdu = 1212 com.android.internal.telephony.gsm.SmsMessage.getSubmitPdu(scAddress, 1213 destinationAddress, message, deliveryIntent != null, 1214 SmsHeader.toByteArray(smsHeader), encoding, smsHeader.languageTable, 1215 smsHeader.languageShiftTable, validityPeriod); 1216 if (pdu != null) { 1217 HashMap map = getSmsTrackerMap(destinationAddress, scAddress, 1218 message, pdu); 1219 return getSmsTracker(callingPackage, map, sentIntent, 1220 deliveryIntent, getFormat(), unsentPartCount, anyPartFailed, messageUri, 1221 smsHeader, (!lastPart || expectMore), fullMessageText, true /*isText*/, 1222 false /*persistMessage*/, priority, validityPeriod, false /* isForVvm */, 1223 messageId); 1224 } else { 1225 Rlog.e(TAG, "GsmSMSDispatcher.getNewSubmitPduTracker(): getSubmitPdu() returned " 1226 + "null" + " id: " + messageId); 1227 return null; 1228 } 1229 } 1230 } 1231 1232 /** 1233 * Send a single or a multi-part SMS 1234 * @param trackers each tracker will contain: 1235 * -smsc the SMSC to send the message through, or NULL for the 1236 * default SMSC 1237 * -pdu the raw PDU to send 1238 * -sentIntent if not NULL this <code>Intent</code> is 1239 * broadcast when the message is successfully sent, or failed. 1240 * The result code will be <code>Activity.RESULT_OK<code> for success, 1241 * or one of these errors: 1242 * <code>RESULT_ERROR_GENERIC_FAILURE</code> 1243 * <code>RESULT_ERROR_RADIO_OFF</code> 1244 * <code>RESULT_ERROR_NULL_PDU</code> 1245 * <code>RESULT_ERROR_NO_SERVICE</code>. 1246 * The per-application based SMS control checks sentIntent. If sentIntent 1247 * is NULL the caller will be checked against all unknown applications, 1248 * which cause smaller number of SMS to be sent in checking period. 1249 * -deliveryIntent if not NULL this <code>Intent</code> is 1250 * broadcast when the message is delivered to the recipient. The 1251 * raw pdu of the status report is in the extended data ("pdu"). 1252 * -param destAddr the destination phone number (for short code confirmation) 1253 */ 1254 @VisibleForTesting sendRawPdu(SmsTracker[] trackers)1255 public void sendRawPdu(SmsTracker[] trackers) { 1256 int error = RESULT_ERROR_NONE; 1257 PackageInfo appInfo = null; 1258 if (mSmsSendDisabled) { 1259 Rlog.e(TAG, "Device does not support sending sms."); 1260 error = RESULT_ERROR_NO_SERVICE; 1261 } else { 1262 for (SmsTracker tracker : trackers) { 1263 if (tracker.getData().get(MAP_KEY_PDU) == null) { 1264 Rlog.e(TAG, "Empty PDU"); 1265 error = RESULT_ERROR_NULL_PDU; 1266 break; 1267 } 1268 } 1269 1270 if (error == RESULT_ERROR_NONE) { 1271 UserHandle userHandle = UserHandle.of(trackers[0].mUserId); 1272 PackageManager pm = mContext.createContextAsUser(userHandle, 0).getPackageManager(); 1273 1274 try { 1275 // Get package info via packagemanager 1276 appInfo = 1277 pm.getPackageInfo( 1278 trackers[0].getAppPackageName(), 1279 PackageManager.GET_SIGNATURES); 1280 } catch (PackageManager.NameNotFoundException e) { 1281 Rlog.e(TAG, "Can't get calling app package info: refusing to send SMS" 1282 + " id: " + getMultiTrackermessageId(trackers)); 1283 error = RESULT_ERROR_GENERIC_FAILURE; 1284 } 1285 } 1286 } 1287 1288 if (error != RESULT_ERROR_NONE) { 1289 handleSmsTrackersFailure(trackers, error, NO_ERROR_CODE); 1290 return; 1291 } 1292 1293 // checkDestination() returns true if the destination is not a premium short code or the 1294 // sending app is approved to send to short codes. Otherwise, a message is sent to our 1295 // handler with the SmsTracker to request user confirmation before sending. 1296 if (checkDestination(trackers)) { 1297 // check for excessive outgoing SMS usage by this app 1298 if (!mSmsDispatchersController 1299 .getUsageMonitor() 1300 .check(appInfo.packageName, trackers.length)) { 1301 sendMessage(obtainMessage(EVENT_SEND_LIMIT_REACHED_CONFIRMATION, trackers)); 1302 return; 1303 } 1304 1305 for (SmsTracker tracker : trackers) { 1306 sendSms(tracker); 1307 } 1308 } 1309 1310 if (PhoneNumberUtils.isLocalEmergencyNumber(mContext, trackers[0].mDestAddress)) { 1311 new AsyncEmergencyContactNotifier(mContext).execute(); 1312 } 1313 } 1314 1315 /** 1316 * Check if destination is a potential premium short code and sender is not pre-approved to send 1317 * to short codes. 1318 * 1319 * @param trackers the trackers for a single or a multi-part SMS to send 1320 * @return true if the destination is approved; false if user confirmation event was sent 1321 */ checkDestination(SmsTracker[] trackers)1322 boolean checkDestination(SmsTracker[] trackers) { 1323 if (mContext.checkCallingOrSelfPermission(SEND_SMS_NO_CONFIRMATION) 1324 == PackageManager.PERMISSION_GRANTED || trackers[0].mIsForVvm) { 1325 return true; // app is pre-approved to send to short codes 1326 } else { 1327 int rule = mPremiumSmsRule.get(); 1328 int smsCategory = SmsManager.SMS_CATEGORY_NOT_SHORT_CODE; 1329 if (rule == PREMIUM_RULE_USE_SIM || rule == PREMIUM_RULE_USE_BOTH) { 1330 String simCountryIso = 1331 mTelephonyManager.getSimCountryIsoForPhone(mPhone.getPhoneId()); 1332 if (simCountryIso == null || simCountryIso.length() != 2) { 1333 Rlog.e(TAG, "Can't get SIM country Iso: trying network country Iso" 1334 + " id: " + getMultiTrackermessageId(trackers)); 1335 simCountryIso = 1336 mTelephonyManager.getNetworkCountryIso(mPhone.getPhoneId()); 1337 } 1338 1339 smsCategory = 1340 mSmsDispatchersController 1341 .getUsageMonitor() 1342 .checkDestination(trackers[0].mDestAddress, simCountryIso); 1343 } 1344 if (rule == PREMIUM_RULE_USE_NETWORK || rule == PREMIUM_RULE_USE_BOTH) { 1345 String networkCountryIso = 1346 mTelephonyManager.getNetworkCountryIso(mPhone.getPhoneId()); 1347 if (networkCountryIso == null || networkCountryIso.length() != 2) { 1348 Rlog.e(TAG, "Can't get Network country Iso: trying SIM country Iso" 1349 + " id: " + getMultiTrackermessageId(trackers)); 1350 networkCountryIso = 1351 mTelephonyManager.getSimCountryIsoForPhone(mPhone.getPhoneId()); 1352 } 1353 1354 smsCategory = 1355 SmsUsageMonitor.mergeShortCodeCategories( 1356 smsCategory, 1357 mSmsDispatchersController 1358 .getUsageMonitor() 1359 .checkDestination( 1360 trackers[0].mDestAddress, networkCountryIso)); 1361 } 1362 1363 if (smsCategory == SmsManager.SMS_CATEGORY_NOT_SHORT_CODE 1364 || smsCategory == SmsManager.SMS_CATEGORY_FREE_SHORT_CODE 1365 || smsCategory == SmsManager.SMS_CATEGORY_STANDARD_SHORT_CODE) { 1366 return true; // not a premium short code 1367 } 1368 1369 // Do not allow any premium sms during SuW 1370 if (Settings.Global.getInt(mResolver, Settings.Global.DEVICE_PROVISIONED, 0) == 0) { 1371 Rlog.e(TAG, "Can't send premium sms during Setup Wizard" 1372 + " id: " + getMultiTrackermessageId(trackers)); 1373 return false; 1374 } 1375 1376 // Wait for user confirmation unless the user has set permission to always allow/deny 1377 int premiumSmsPermission = 1378 mSmsDispatchersController 1379 .getUsageMonitor() 1380 .getPremiumSmsPermission(trackers[0].getAppPackageName()); 1381 if (premiumSmsPermission == SmsUsageMonitor.PREMIUM_SMS_PERMISSION_UNKNOWN) { 1382 // First time trying to send to premium SMS. 1383 premiumSmsPermission = SmsUsageMonitor.PREMIUM_SMS_PERMISSION_ASK_USER; 1384 } 1385 1386 switch (premiumSmsPermission) { 1387 case SmsUsageMonitor.PREMIUM_SMS_PERMISSION_ALWAYS_ALLOW: 1388 Rlog.d(TAG, "User approved this app to send to premium SMS" 1389 + " id: " + getMultiTrackermessageId(trackers)); 1390 return true; 1391 1392 case SmsUsageMonitor.PREMIUM_SMS_PERMISSION_NEVER_ALLOW: 1393 Rlog.w(TAG, "User denied this app from sending to premium SMS" 1394 + " id: " + getMultiTrackermessageId(trackers)); 1395 Message msg = obtainMessage(EVENT_SENDING_NOT_ALLOWED, trackers); 1396 sendMessage(msg); 1397 return false; // reject this message 1398 1399 case SmsUsageMonitor.PREMIUM_SMS_PERMISSION_ASK_USER: 1400 default: 1401 int event; 1402 if (smsCategory == SmsManager.SMS_CATEGORY_POSSIBLE_PREMIUM_SHORT_CODE) { 1403 event = EVENT_CONFIRM_SEND_TO_POSSIBLE_PREMIUM_SHORT_CODE; 1404 } else { 1405 event = EVENT_CONFIRM_SEND_TO_PREMIUM_SHORT_CODE; 1406 } 1407 sendMessage(obtainMessage(event, trackers)); 1408 return false; // wait for user confirmation 1409 } 1410 } 1411 } 1412 1413 /** 1414 * Deny sending a single or a multi-part SMS if the outgoing queue limit is reached. Used when 1415 * the message must be confirmed by the user due to excessive usage or potential premium SMS 1416 * detected. 1417 * 1418 * @param trackers the SmsTracker array for the message to send 1419 * @return true if the message was denied; false to continue with send confirmation 1420 */ denyIfQueueLimitReached(SmsTracker[] trackers)1421 private boolean denyIfQueueLimitReached(SmsTracker[] trackers) { 1422 // one SmsTracker array is treated as one message for checking queue limit. 1423 if (mPendingTrackerCount >= MO_MSG_QUEUE_LIMIT) { 1424 // Deny sending message when the queue limit is reached. 1425 Rlog.e(TAG, "Denied because queue limit reached" 1426 + " id: " + getMultiTrackermessageId(trackers)); 1427 handleSmsTrackersFailure(trackers, RESULT_ERROR_LIMIT_EXCEEDED, NO_ERROR_CODE); 1428 return true; 1429 } 1430 mPendingTrackerCount++; 1431 return false; 1432 } 1433 1434 /** 1435 * Returns the label for the specified app package name. 1436 * @param appPackage the package name of the app requesting to send an SMS 1437 * @return the label for the specified app, or the package name if getApplicationInfo() fails 1438 */ getAppLabel(String appPackage, @UserIdInt int userId)1439 private CharSequence getAppLabel(String appPackage, @UserIdInt int userId) { 1440 PackageManager pm = mContext.getPackageManager(); 1441 try { 1442 ApplicationInfo appInfo = pm.getApplicationInfoAsUser(appPackage, 0, 1443 UserHandle.getUserHandleForUid(userId)); 1444 return appInfo.loadSafeLabel(pm); 1445 } catch (PackageManager.NameNotFoundException e) { 1446 Rlog.e(TAG, "PackageManager Name Not Found for package " + appPackage); 1447 return appPackage; // fall back to package name if we can't get app label 1448 } 1449 } 1450 1451 /** 1452 * Post an alert when SMS needs confirmation due to excessive usage. 1453 * 1454 * @param trackers the SmsTracker array for the current message. 1455 */ handleReachSentLimit(SmsTracker[] trackers)1456 protected void handleReachSentLimit(SmsTracker[] trackers) { 1457 if (denyIfQueueLimitReached(trackers)) { 1458 return; // queue limit reached; error was returned to caller 1459 } 1460 1461 CharSequence appLabel = getAppLabel(trackers[0].getAppPackageName(), trackers[0].mUserId); 1462 Resources r = Resources.getSystem(); 1463 Spanned messageText = Html.fromHtml(r.getString(R.string.sms_control_message, appLabel)); 1464 1465 // Construct ConfirmDialogListenter for Rate Limit handling 1466 ConfirmDialogListener listener = 1467 new ConfirmDialogListener(trackers, null, ConfirmDialogListener.RATE_LIMIT); 1468 1469 AlertDialog d = new AlertDialog.Builder(mContext) 1470 .setTitle(R.string.sms_control_title) 1471 .setIcon(R.drawable.stat_sys_warning) 1472 .setMessage(messageText) 1473 .setPositiveButton(r.getString(R.string.sms_control_yes), listener) 1474 .setNegativeButton(r.getString(R.string.sms_control_no), listener) 1475 .setOnCancelListener(listener) 1476 .create(); 1477 1478 d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT); 1479 d.show(); 1480 } 1481 1482 /** 1483 * Post an alert for user confirmation when sending to a potential short code. 1484 * 1485 * @param isPremium true if the destination is known to be a premium short code 1486 * @param trackers the SmsTracker array for the current message. 1487 */ 1488 @UnsupportedAppUsage handleConfirmShortCode(boolean isPremium, SmsTracker[] trackers)1489 protected void handleConfirmShortCode(boolean isPremium, SmsTracker[] trackers) { 1490 if (denyIfQueueLimitReached(trackers)) { 1491 return; // queue limit reached; error was returned to caller 1492 } 1493 1494 int detailsId; 1495 if (isPremium) { 1496 detailsId = R.string.sms_premium_short_code_details; 1497 } else { 1498 detailsId = R.string.sms_short_code_details; 1499 } 1500 1501 CharSequence appLabel = getAppLabel(trackers[0].getAppPackageName(), trackers[0].mUserId); 1502 Resources r = Resources.getSystem(); 1503 Spanned messageText = 1504 Html.fromHtml( 1505 r.getString( 1506 R.string.sms_short_code_confirm_message, 1507 appLabel, 1508 trackers[0].mDestAddress)); 1509 1510 LayoutInflater inflater = (LayoutInflater) mContext.getSystemService( 1511 Context.LAYOUT_INFLATER_SERVICE); 1512 View layout = inflater.inflate(R.layout.sms_short_code_confirmation_dialog, null); 1513 1514 // Construct ConfirmDialogListenter for short code message sending 1515 ConfirmDialogListener listener = 1516 new ConfirmDialogListener( 1517 trackers, 1518 (TextView) 1519 layout.findViewById(R.id.sms_short_code_remember_undo_instruction), 1520 ConfirmDialogListener.SHORT_CODE_MSG); 1521 1522 TextView messageView = (TextView) layout.findViewById(R.id.sms_short_code_confirm_message); 1523 messageView.setText(messageText); 1524 1525 ViewGroup detailsLayout = (ViewGroup) layout.findViewById( 1526 R.id.sms_short_code_detail_layout); 1527 TextView detailsView = (TextView) detailsLayout.findViewById( 1528 R.id.sms_short_code_detail_message); 1529 detailsView.setText(detailsId); 1530 1531 CheckBox rememberChoice = (CheckBox) layout.findViewById( 1532 R.id.sms_short_code_remember_choice_checkbox); 1533 rememberChoice.setOnCheckedChangeListener(listener); 1534 1535 AlertDialog d = new AlertDialog.Builder(mContext) 1536 .setView(layout) 1537 .setPositiveButton(r.getString(R.string.sms_short_code_confirm_allow), listener) 1538 .setNegativeButton(r.getString(R.string.sms_short_code_confirm_deny), listener) 1539 .setOnCancelListener(listener) 1540 .create(); 1541 1542 d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT); 1543 d.show(); 1544 1545 listener.setPositiveButton(d.getButton(DialogInterface.BUTTON_POSITIVE)); 1546 listener.setNegativeButton(d.getButton(DialogInterface.BUTTON_NEGATIVE)); 1547 } 1548 1549 /** 1550 * Send the message along to the radio. 1551 * 1552 * @param tracker holds the SMS message to send 1553 */ 1554 @UnsupportedAppUsage sendSms(SmsTracker tracker)1555 protected abstract void sendSms(SmsTracker tracker); 1556 1557 /** 1558 * Retry the message along to the radio. 1559 * 1560 * @param tracker holds the SMS message to send 1561 */ sendRetrySms(SmsTracker tracker)1562 public void sendRetrySms(SmsTracker tracker) { 1563 // re-routing to SmsDispatchersController 1564 if (mSmsDispatchersController != null) { 1565 mSmsDispatchersController.sendRetrySms(tracker); 1566 } else { 1567 Rlog.e(TAG, mSmsDispatchersController + " is null. Retry failed" 1568 + " id: " + tracker.mMessageId); 1569 } 1570 } 1571 handleSmsTrackersFailure(SmsTracker[] trackers, int error, int errorCode)1572 private void handleSmsTrackersFailure(SmsTracker[] trackers, int error, int errorCode) { 1573 for (SmsTracker tracker : trackers) { 1574 tracker.onFailed(mContext, error, errorCode); 1575 } 1576 } 1577 1578 /** 1579 * Keeps track of an SMS that has been sent to the RIL, until it has 1580 * successfully been sent, or we're done trying. 1581 */ 1582 public static class SmsTracker { 1583 // fields need to be public for derived SmsDispatchers 1584 @UnsupportedAppUsage 1585 private final HashMap<String, Object> mData; 1586 public int mRetryCount; 1587 // IMS retry counter. Nonzero indicates initial message was sent over IMS channel in RIL and 1588 // counts how many retries have been made on the IMS channel. 1589 // Used in older implementations where the message is sent over IMS using the RIL. 1590 public int mImsRetry; 1591 // Tag indicating that this SMS is being handled by the ImsSmsDispatcher. This tracker 1592 // should not try to use SMS over IMS over the RIL interface in this case when falling back. 1593 public boolean mUsesImsServiceForIms; 1594 @UnsupportedAppUsage 1595 public int mMessageRef; 1596 public boolean mExpectMore; 1597 public int mValidityPeriod; 1598 public int mPriority; 1599 String mFormat; 1600 1601 @UnsupportedAppUsage 1602 public final PendingIntent mSentIntent; 1603 @UnsupportedAppUsage 1604 public final PendingIntent mDeliveryIntent; 1605 1606 @UnsupportedAppUsage 1607 public final PackageInfo mAppInfo; 1608 @UnsupportedAppUsage 1609 public final String mDestAddress; 1610 1611 public final SmsHeader mSmsHeader; 1612 1613 @UnsupportedAppUsage 1614 private long mTimestamp = System.currentTimeMillis(); 1615 @UnsupportedAppUsage 1616 public Uri mMessageUri; // Uri of persisted message if we wrote one 1617 1618 // Reference to states of a multipart message that this part belongs to 1619 private AtomicInteger mUnsentPartCount; 1620 private AtomicBoolean mAnyPartFailed; 1621 // The full message content of a single part message 1622 // or a multipart message that this part belongs to 1623 private String mFullMessageText; 1624 1625 private int mSubId; 1626 1627 // If this is a text message (instead of data message) 1628 private boolean mIsText; 1629 1630 @UnsupportedAppUsage 1631 private boolean mPersistMessage; 1632 1633 // User who sends the SMS. 1634 private final @UserIdInt int mUserId; 1635 1636 private final boolean mIsForVvm; 1637 1638 public final long mMessageId; 1639 SmsTracker(HashMap<String, Object> data, PendingIntent sentIntent, PendingIntent deliveryIntent, PackageInfo appInfo, String destAddr, String format, AtomicInteger unsentPartCount, AtomicBoolean anyPartFailed, Uri messageUri, SmsHeader smsHeader, boolean expectMore, String fullMessageText, int subId, boolean isText, boolean persistMessage, int userId, int priority, int validityPeriod, boolean isForVvm, long messageId)1640 private SmsTracker(HashMap<String, Object> data, PendingIntent sentIntent, 1641 PendingIntent deliveryIntent, PackageInfo appInfo, String destAddr, String format, 1642 AtomicInteger unsentPartCount, AtomicBoolean anyPartFailed, Uri messageUri, 1643 SmsHeader smsHeader, boolean expectMore, String fullMessageText, int subId, 1644 boolean isText, boolean persistMessage, int userId, int priority, 1645 int validityPeriod, boolean isForVvm, long messageId) { 1646 mData = data; 1647 mSentIntent = sentIntent; 1648 mDeliveryIntent = deliveryIntent; 1649 mRetryCount = 0; 1650 mAppInfo = appInfo; 1651 mDestAddress = destAddr; 1652 mFormat = format; 1653 mExpectMore = expectMore; 1654 mImsRetry = 0; 1655 mUsesImsServiceForIms = false; 1656 mMessageRef = 0; 1657 mUnsentPartCount = unsentPartCount; 1658 mAnyPartFailed = anyPartFailed; 1659 mMessageUri = messageUri; 1660 mSmsHeader = smsHeader; 1661 mFullMessageText = fullMessageText; 1662 mSubId = subId; 1663 mIsText = isText; 1664 mPersistMessage = persistMessage; 1665 mUserId = userId; 1666 mPriority = priority; 1667 mValidityPeriod = validityPeriod; 1668 mIsForVvm = isForVvm; 1669 mMessageId = messageId; 1670 } 1671 getData()1672 public HashMap<String, Object> getData() { 1673 return mData; 1674 } 1675 1676 /** 1677 * Get the App package name 1678 * @return App package name info 1679 */ getAppPackageName()1680 public String getAppPackageName() { 1681 return mAppInfo != null ? mAppInfo.packageName : null; 1682 } 1683 1684 /** 1685 * Update the status of this message if we persisted it 1686 */ 1687 @UnsupportedAppUsage updateSentMessageStatus(Context context, int status)1688 public void updateSentMessageStatus(Context context, int status) { 1689 if (mMessageUri != null) { 1690 // If we wrote this message in writeSentMessage, update it now 1691 ContentValues values = new ContentValues(1); 1692 values.put(Sms.STATUS, status); 1693 context.getContentResolver().update(mMessageUri, values, null, null); 1694 } 1695 } 1696 1697 /** 1698 * Set the final state of a message: FAILED or SENT 1699 * 1700 * @param context The Context 1701 * @param messageType The final message type 1702 * @param errorCode The error code 1703 */ updateMessageState(Context context, int messageType, int errorCode)1704 private void updateMessageState(Context context, int messageType, int errorCode) { 1705 if (mMessageUri == null) { 1706 return; 1707 } 1708 final ContentValues values = new ContentValues(2); 1709 values.put(Sms.TYPE, messageType); 1710 values.put(Sms.ERROR_CODE, errorCode); 1711 final long identity = Binder.clearCallingIdentity(); 1712 try { 1713 if (context.getContentResolver().update(mMessageUri, values, 1714 null/*where*/, null/*selectionArgs*/) != 1) { 1715 Rlog.e(TAG, "Failed to move message to " + messageType); 1716 } 1717 } finally { 1718 Binder.restoreCallingIdentity(identity); 1719 } 1720 } 1721 1722 /** 1723 * Persist a sent SMS if required: 1724 * 1. It is a text message 1725 * 2. SmsApplication tells us to persist: sent from apps that are not default-SMS app or 1726 * bluetooth 1727 * 1728 * @param context 1729 * @param messageType The folder to store (FAILED or SENT) 1730 * @param errorCode The current error code for this SMS or SMS part 1731 * @return The telephony provider URI if stored 1732 */ persistSentMessageIfRequired(Context context, int messageType, int errorCode)1733 private Uri persistSentMessageIfRequired(Context context, int messageType, int errorCode) { 1734 if (!mIsText || !mPersistMessage || 1735 !SmsApplication.shouldWriteMessageForPackage(mAppInfo.packageName, context)) { 1736 return null; 1737 } 1738 Rlog.d(TAG, "Persist SMS into " 1739 + (messageType == Sms.MESSAGE_TYPE_FAILED ? "FAILED" : "SENT")); 1740 final ContentValues values = new ContentValues(); 1741 values.put(Sms.SUBSCRIPTION_ID, mSubId); 1742 values.put(Sms.ADDRESS, mDestAddress); 1743 values.put(Sms.BODY, mFullMessageText); 1744 values.put(Sms.DATE, System.currentTimeMillis()); // milliseconds 1745 values.put(Sms.SEEN, 1); 1746 values.put(Sms.READ, 1); 1747 final String creator = mAppInfo != null ? mAppInfo.packageName : null; 1748 if (!TextUtils.isEmpty(creator)) { 1749 values.put(Sms.CREATOR, creator); 1750 } 1751 if (mDeliveryIntent != null) { 1752 values.put(Sms.STATUS, Telephony.Sms.STATUS_PENDING); 1753 } 1754 if (errorCode != NO_ERROR_CODE) { 1755 values.put(Sms.ERROR_CODE, errorCode); 1756 } 1757 final long identity = Binder.clearCallingIdentity(); 1758 final ContentResolver resolver = context.getContentResolver(); 1759 try { 1760 final Uri uri = resolver.insert(Telephony.Sms.Sent.CONTENT_URI, values); 1761 if (uri != null && messageType == Sms.MESSAGE_TYPE_FAILED) { 1762 // Since we can't persist a message directly into FAILED box, 1763 // we have to update the column after we persist it into SENT box. 1764 // The gap between the state change is tiny so I would not expect 1765 // it to cause any serious problem 1766 // TODO: we should add a "failed" URI for this in SmsProvider? 1767 final ContentValues updateValues = new ContentValues(1); 1768 updateValues.put(Sms.TYPE, Sms.MESSAGE_TYPE_FAILED); 1769 resolver.update(uri, updateValues, null/*where*/, null/*selectionArgs*/); 1770 } 1771 return uri; 1772 } catch (Exception e) { 1773 Rlog.e(TAG, "writeOutboxMessage: Failed to persist outbox message", e); 1774 return null; 1775 } finally { 1776 Binder.restoreCallingIdentity(identity); 1777 } 1778 } 1779 1780 /** 1781 * Persist or update an SMS depending on if we send a new message or a stored message 1782 * 1783 * @param context 1784 * @param messageType The message folder for this SMS, FAILED or SENT 1785 * @param errorCode The current error code for this SMS or SMS part 1786 */ persistOrUpdateMessage(Context context, int messageType, int errorCode)1787 private void persistOrUpdateMessage(Context context, int messageType, int errorCode) { 1788 if (mMessageUri != null) { 1789 updateMessageState(context, messageType, errorCode); 1790 } else { 1791 mMessageUri = persistSentMessageIfRequired(context, messageType, errorCode); 1792 } 1793 } 1794 1795 /** 1796 * Handle a failure of a single part message or a part of a multipart message 1797 * 1798 * @param context The Context 1799 * @param error The error to send back with 1800 * @param errorCode 1801 */ 1802 @UnsupportedAppUsage onFailed(Context context, int error, int errorCode)1803 public void onFailed(Context context, int error, int errorCode) { 1804 if (mAnyPartFailed != null) { 1805 mAnyPartFailed.set(true); 1806 } 1807 // is single part or last part of multipart message 1808 boolean isSinglePartOrLastPart = true; 1809 if (mUnsentPartCount != null) { 1810 isSinglePartOrLastPart = mUnsentPartCount.decrementAndGet() == 0; 1811 } 1812 if (isSinglePartOrLastPart) { 1813 persistOrUpdateMessage(context, Sms.MESSAGE_TYPE_FAILED, errorCode); 1814 } 1815 if (mSentIntent != null) { 1816 try { 1817 // Extra information to send with the sent intent 1818 Intent fillIn = new Intent(); 1819 if (mMessageUri != null) { 1820 // Pass this to SMS apps so that they know where it is stored 1821 fillIn.putExtra("uri", mMessageUri.toString()); 1822 } 1823 if (errorCode != NO_ERROR_CODE) { 1824 fillIn.putExtra("errorCode", errorCode); 1825 } 1826 if (mUnsentPartCount != null && isSinglePartOrLastPart) { 1827 // Is multipart and last part 1828 fillIn.putExtra(SEND_NEXT_MSG_EXTRA, true); 1829 } 1830 if (mMessageId != 0L) { 1831 // Send the id back to the caller so they can verify the message id 1832 // with the one they passed to SmsManager. 1833 fillIn.putExtra(MESSAGE_ID_EXTRA, mMessageId); 1834 } 1835 mSentIntent.send(context, error, fillIn); 1836 } catch (CanceledException ex) { 1837 Rlog.e(TAG, "Failed to send result" 1838 + " id: " + mMessageId); 1839 } 1840 } 1841 } 1842 1843 /** 1844 * Handle the sent of a single part message or a part of a multipart message 1845 * 1846 * @param context The Context 1847 */ 1848 @UnsupportedAppUsage onSent(Context context)1849 public void onSent(Context context) { 1850 // is single part or last part of multipart message 1851 boolean isSinglePartOrLastPart = true; 1852 if (mUnsentPartCount != null) { 1853 isSinglePartOrLastPart = mUnsentPartCount.decrementAndGet() == 0; 1854 } 1855 if (isSinglePartOrLastPart) { 1856 int messageType = Sms.MESSAGE_TYPE_SENT; 1857 if (mAnyPartFailed != null && mAnyPartFailed.get()) { 1858 messageType = Sms.MESSAGE_TYPE_FAILED; 1859 } 1860 persistOrUpdateMessage(context, messageType, NO_ERROR_CODE); 1861 } 1862 if (mSentIntent != null) { 1863 try { 1864 // Extra information to send with the sent intent 1865 Intent fillIn = new Intent(); 1866 if (mMessageUri != null) { 1867 // Pass this to SMS apps so that they know where it is stored 1868 fillIn.putExtra("uri", mMessageUri.toString()); 1869 } 1870 if (mUnsentPartCount != null && isSinglePartOrLastPart) { 1871 // Is multipart and last part 1872 fillIn.putExtra(SEND_NEXT_MSG_EXTRA, true); 1873 } 1874 mSentIntent.send(context, Activity.RESULT_OK, fillIn); 1875 } catch (CanceledException ex) { 1876 Rlog.e(TAG, "Failed to send result"); 1877 } 1878 } 1879 } 1880 } 1881 getSmsTracker(String callingPackage, HashMap<String, Object> data, PendingIntent sentIntent, PendingIntent deliveryIntent, String format, AtomicInteger unsentPartCount, AtomicBoolean anyPartFailed, Uri messageUri, SmsHeader smsHeader, boolean expectMore, String fullMessageText, boolean isText, boolean persistMessage, int priority, int validityPeriod, boolean isForVvm, long messageId)1882 protected SmsTracker getSmsTracker(String callingPackage, HashMap<String, Object> data, 1883 PendingIntent sentIntent, PendingIntent deliveryIntent, String format, 1884 AtomicInteger unsentPartCount, AtomicBoolean anyPartFailed, Uri messageUri, 1885 SmsHeader smsHeader, boolean expectMore, String fullMessageText, boolean isText, 1886 boolean persistMessage, int priority, int validityPeriod, boolean isForVvm, 1887 long messageId) { 1888 // Get package info via packagemanager 1889 UserHandle callingUser = UserHandle.getUserHandleForUid(Binder.getCallingUid()); 1890 final int userId = callingUser.getIdentifier(); 1891 PackageManager pm = mContext.createContextAsUser(callingUser, 0).getPackageManager(); 1892 PackageInfo appInfo = null; 1893 try { 1894 appInfo = pm.getPackageInfo(callingPackage, PackageManager.GET_SIGNATURES); 1895 } catch (PackageManager.NameNotFoundException e) { 1896 // error will be logged in sendRawPdu 1897 } 1898 // Strip non-digits from destination phone number before checking for short codes 1899 // and before displaying the number to the user if confirmation is required. 1900 String destAddr = PhoneNumberUtils.extractNetworkPortion((String) data.get("destAddr")); 1901 return new SmsTracker(data, sentIntent, deliveryIntent, appInfo, destAddr, format, 1902 unsentPartCount, anyPartFailed, messageUri, smsHeader, expectMore, 1903 fullMessageText, getSubId(), isText, persistMessage, userId, priority, 1904 validityPeriod, isForVvm, messageId); 1905 } 1906 getSmsTracker(String callingPackage, HashMap<String, Object> data, PendingIntent sentIntent, PendingIntent deliveryIntent, String format, Uri messageUri, boolean expectMore, String fullMessageText, boolean isText, boolean persistMessage, boolean isForVvm, long messageId)1907 protected SmsTracker getSmsTracker(String callingPackage, HashMap<String, Object> data, 1908 PendingIntent sentIntent, PendingIntent deliveryIntent, String format, Uri messageUri, 1909 boolean expectMore, String fullMessageText, boolean isText, boolean persistMessage, 1910 boolean isForVvm, long messageId) { 1911 return getSmsTracker(callingPackage, data, sentIntent, deliveryIntent, format, 1912 null/*unsentPartCount*/, null/*anyPartFailed*/, messageUri, null/*smsHeader*/, 1913 expectMore, fullMessageText, isText, persistMessage, 1914 SMS_MESSAGE_PRIORITY_NOT_SPECIFIED, SMS_MESSAGE_PERIOD_NOT_SPECIFIED, isForVvm, 1915 messageId); 1916 } 1917 getSmsTracker(String callingPackage, HashMap<String, Object> data, PendingIntent sentIntent, PendingIntent deliveryIntent, String format, Uri messageUri, boolean expectMore, String fullMessageText, boolean isText, boolean persistMessage, int priority, int validityPeriod, boolean isForVvm, long messageId)1918 protected SmsTracker getSmsTracker(String callingPackage, HashMap<String, Object> data, 1919 PendingIntent sentIntent, PendingIntent deliveryIntent, String format, Uri messageUri, 1920 boolean expectMore, String fullMessageText, boolean isText, boolean persistMessage, 1921 int priority, int validityPeriod, boolean isForVvm, long messageId) { 1922 return getSmsTracker(callingPackage, data, sentIntent, deliveryIntent, format, 1923 null/*unsentPartCount*/, null/*anyPartFailed*/, messageUri, null/*smsHeader*/, 1924 expectMore, fullMessageText, isText, persistMessage, priority, validityPeriod, 1925 isForVvm, messageId); 1926 } 1927 getSmsTrackerMap(String destAddr, String scAddr, String text, SmsMessageBase.SubmitPduBase pdu)1928 protected HashMap<String, Object> getSmsTrackerMap(String destAddr, String scAddr, 1929 String text, SmsMessageBase.SubmitPduBase pdu) { 1930 HashMap<String, Object> map = new HashMap<String, Object>(); 1931 map.put(MAP_KEY_DEST_ADDR, destAddr); 1932 map.put(MAP_KEY_SC_ADDR, scAddr); 1933 map.put(MAP_KEY_TEXT, text); 1934 map.put(MAP_KEY_SMSC, pdu.encodedScAddress); 1935 map.put(MAP_KEY_PDU, pdu.encodedMessage); 1936 return map; 1937 } 1938 getSmsTrackerMap(String destAddr, String scAddr, int destPort, byte[] data, SmsMessageBase.SubmitPduBase pdu)1939 protected HashMap<String, Object> getSmsTrackerMap(String destAddr, String scAddr, 1940 int destPort, byte[] data, SmsMessageBase.SubmitPduBase pdu) { 1941 HashMap<String, Object> map = new HashMap<String, Object>(); 1942 map.put(MAP_KEY_DEST_ADDR, destAddr); 1943 map.put(MAP_KEY_SC_ADDR, scAddr); 1944 map.put(MAP_KEY_DEST_PORT, destPort); 1945 map.put(MAP_KEY_DATA, data); 1946 map.put(MAP_KEY_SMSC, pdu.encodedScAddress); 1947 map.put(MAP_KEY_PDU, pdu.encodedMessage); 1948 return map; 1949 } 1950 1951 /** 1952 * Dialog listener for SMS confirmation dialog. 1953 */ 1954 private final class ConfirmDialogListener 1955 implements DialogInterface.OnClickListener, DialogInterface.OnCancelListener, 1956 CompoundButton.OnCheckedChangeListener { 1957 1958 private final SmsTracker[] mTrackers; 1959 @UnsupportedAppUsage 1960 private Button mPositiveButton; 1961 @UnsupportedAppUsage 1962 private Button mNegativeButton; 1963 private boolean mRememberChoice; // default is unchecked 1964 @UnsupportedAppUsage 1965 private final TextView mRememberUndoInstruction; 1966 private int mConfirmationType; // 0 - Short Code Msg Sending; 1 - Rate Limit Exceeded 1967 private static final int SHORT_CODE_MSG = 0; // Short Code Msg 1968 private static final int RATE_LIMIT = 1; // Rate Limit Exceeded 1969 private static final int NEVER_ALLOW = 1; // Never Allow 1970 ConfirmDialogListener(SmsTracker[] trackers, TextView textView, int confirmationType)1971 ConfirmDialogListener(SmsTracker[] trackers, TextView textView, int confirmationType) { 1972 mTrackers = trackers; 1973 mRememberUndoInstruction = textView; 1974 mConfirmationType = confirmationType; 1975 } 1976 setPositiveButton(Button button)1977 void setPositiveButton(Button button) { 1978 mPositiveButton = button; 1979 } 1980 setNegativeButton(Button button)1981 void setNegativeButton(Button button) { 1982 mNegativeButton = button; 1983 } 1984 1985 @Override onClick(DialogInterface dialog, int which)1986 public void onClick(DialogInterface dialog, int which) { 1987 // Always set the SMS permission so that Settings will show a permission setting 1988 // for the app (it won't be shown until after the app tries to send to a short code). 1989 int newSmsPermission = SmsUsageMonitor.PREMIUM_SMS_PERMISSION_ASK_USER; 1990 1991 if (which == DialogInterface.BUTTON_POSITIVE) { 1992 Rlog.d(TAG, "CONFIRM sending SMS"); 1993 // XXX this is lossy- apps can have more than one signature 1994 EventLog.writeEvent( 1995 EventLogTags.EXP_DET_SMS_SENT_BY_USER, 1996 mTrackers[0].mAppInfo.applicationInfo == null 1997 ? -1 1998 : mTrackers[0].mAppInfo.applicationInfo.uid); 1999 sendMessage(obtainMessage(EVENT_SEND_CONFIRMED_SMS, mTrackers)); 2000 if (mRememberChoice) { 2001 newSmsPermission = SmsUsageMonitor.PREMIUM_SMS_PERMISSION_ALWAYS_ALLOW; 2002 } 2003 } else if (which == DialogInterface.BUTTON_NEGATIVE) { 2004 Rlog.d(TAG, "DENY sending SMS"); 2005 // XXX this is lossy- apps can have more than one signature 2006 EventLog.writeEvent( 2007 EventLogTags.EXP_DET_SMS_DENIED_BY_USER, 2008 mTrackers[0].mAppInfo.applicationInfo == null 2009 ? -1 2010 : mTrackers[0].mAppInfo.applicationInfo.uid); 2011 Message msg = obtainMessage(EVENT_STOP_SENDING, mTrackers); 2012 msg.arg1 = mConfirmationType; 2013 if (mRememberChoice) { 2014 newSmsPermission = SmsUsageMonitor.PREMIUM_SMS_PERMISSION_NEVER_ALLOW; 2015 msg.arg2 = ConfirmDialogListener.NEVER_ALLOW; 2016 } 2017 sendMessage(msg); 2018 } 2019 mSmsDispatchersController.setPremiumSmsPermission( 2020 mTrackers[0].getAppPackageName(), newSmsPermission); 2021 } 2022 2023 @Override onCancel(DialogInterface dialog)2024 public void onCancel(DialogInterface dialog) { 2025 Rlog.d(TAG, "dialog dismissed: don't send SMS"); 2026 Message msg = obtainMessage(EVENT_STOP_SENDING, mTrackers); 2027 msg.arg1 = mConfirmationType; 2028 sendMessage(msg); 2029 } 2030 2031 @Override onCheckedChanged(CompoundButton buttonView, boolean isChecked)2032 public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { 2033 Rlog.d(TAG, "remember this choice: " + isChecked); 2034 mRememberChoice = isChecked; 2035 if (isChecked) { 2036 mPositiveButton.setText(R.string.sms_short_code_confirm_always_allow); 2037 mNegativeButton.setText(R.string.sms_short_code_confirm_never_allow); 2038 if (mRememberUndoInstruction != null) { 2039 mRememberUndoInstruction 2040 .setText(R.string.sms_short_code_remember_undo_instruction); 2041 mRememberUndoInstruction.setPadding(0,0,0,32); 2042 } 2043 } else { 2044 mPositiveButton.setText(R.string.sms_short_code_confirm_allow); 2045 mNegativeButton.setText(R.string.sms_short_code_confirm_deny); 2046 if (mRememberUndoInstruction != null) { 2047 mRememberUndoInstruction.setText(""); 2048 mRememberUndoInstruction.setPadding(0,0,0,0); 2049 } 2050 } 2051 } 2052 } 2053 isIms()2054 public boolean isIms() { 2055 if (mSmsDispatchersController != null) { 2056 return mSmsDispatchersController.isIms(); 2057 } else { 2058 Rlog.e(TAG, "mSmsDispatchersController is null"); 2059 return false; 2060 } 2061 } 2062 2063 @UnsupportedAppUsage getMultipartMessageText(ArrayList<String> parts)2064 private String getMultipartMessageText(ArrayList<String> parts) { 2065 final StringBuilder sb = new StringBuilder(); 2066 for (String part : parts) { 2067 if (part != null) { 2068 sb.append(part); 2069 } 2070 } 2071 return sb.toString(); 2072 } 2073 2074 @UnsupportedAppUsage getCarrierAppPackageName()2075 protected String getCarrierAppPackageName() { 2076 UiccCard card = UiccController.getInstance().getUiccCard(mPhone.getPhoneId()); 2077 if (card == null) { 2078 return null; 2079 } 2080 2081 List<String> carrierPackages = card.getCarrierPackageNamesForIntent( 2082 mContext.getPackageManager(), new Intent(CarrierMessagingService.SERVICE_INTERFACE)); 2083 if (carrierPackages != null && carrierPackages.size() == 1) { 2084 return carrierPackages.get(0); 2085 } 2086 // If there is no carrier package which implements CarrierMessagingService, then lookup if 2087 // for a carrierImsPackage that implements CarrierMessagingService. 2088 return CarrierSmsUtils.getCarrierImsPackageForIntent(mContext, mPhone, 2089 new Intent(CarrierMessagingService.SERVICE_INTERFACE)); 2090 } 2091 2092 @UnsupportedAppUsage getSubId()2093 protected int getSubId() { 2094 return SubscriptionController.getInstance().getSubIdUsingPhoneId(mPhone.getPhoneId()); 2095 } 2096 2097 @UnsupportedAppUsage checkCallerIsPhoneOrCarrierApp()2098 private void checkCallerIsPhoneOrCarrierApp() { 2099 int uid = Binder.getCallingUid(); 2100 int appId = UserHandle.getAppId(uid); 2101 if (appId == Process.PHONE_UID || uid == 0) { 2102 return; 2103 } 2104 try { 2105 PackageManager pm = mContext.getPackageManager(); 2106 ApplicationInfo ai = pm.getApplicationInfo(getCarrierAppPackageName(), 0); 2107 if (UserHandle.getAppId(ai.uid) != UserHandle.getAppId(Binder.getCallingUid())) { 2108 throw new SecurityException("Caller is not phone or carrier app!"); 2109 } 2110 } catch (PackageManager.NameNotFoundException re) { 2111 throw new SecurityException("Caller is not phone or carrier app!"); 2112 } 2113 } 2114 isCdmaMo()2115 protected boolean isCdmaMo() { 2116 return mSmsDispatchersController.isCdmaMo(); 2117 } 2118 isAscii7bitSupportedForLongMessage()2119 private boolean isAscii7bitSupportedForLongMessage() { 2120 //TODO: Do not rely on calling identity here, we should store UID & clear identity earlier. 2121 long token = Binder.clearCallingIdentity(); 2122 try { 2123 CarrierConfigManager configManager = (CarrierConfigManager) mContext.getSystemService( 2124 Context.CARRIER_CONFIG_SERVICE); 2125 PersistableBundle pb = null; 2126 pb = configManager.getConfigForSubId(mPhone.getSubId()); 2127 if (pb != null) { 2128 return pb.getBoolean(CarrierConfigManager 2129 .KEY_ASCII_7_BIT_SUPPORT_FOR_LONG_MESSAGE_BOOL); 2130 } 2131 return false; 2132 } finally { 2133 Binder.restoreCallingIdentity(token); 2134 } 2135 } 2136 } 2137