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