1 /* 2 * Copyright (C) 2013 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.internal.telephony; 18 19 import android.app.Activity; 20 import android.app.ActivityManagerNative; 21 import android.app.AppOpsManager; 22 import android.app.PendingIntent; 23 import android.app.PendingIntent.CanceledException; 24 import android.content.BroadcastReceiver; 25 import android.content.ComponentName; 26 import android.content.ContentResolver; 27 import android.content.ContentUris; 28 import android.content.ContentValues; 29 import android.content.Context; 30 import android.content.Intent; 31 import android.content.pm.UserInfo; 32 import android.database.Cursor; 33 import android.database.SQLException; 34 import android.net.Uri; 35 import android.os.AsyncResult; 36 import android.os.Binder; 37 import android.os.Build; 38 import android.os.Bundle; 39 import android.os.Message; 40 import android.os.PowerManager; 41 import android.os.RemoteException; 42 import android.os.SystemProperties; 43 import android.os.UserHandle; 44 import android.os.UserManager; 45 import android.provider.Telephony; 46 import android.provider.Telephony.Sms.Intents; 47 import android.telephony.Rlog; 48 import android.telephony.SmsManager; 49 import android.telephony.SmsMessage; 50 import android.telephony.SubscriptionManager; 51 import android.telephony.TelephonyManager; 52 import android.text.TextUtils; 53 import android.util.Log; 54 55 import com.android.internal.telephony.uicc.UiccCard; 56 import com.android.internal.telephony.uicc.UiccController; 57 import com.android.internal.util.HexDump; 58 import com.android.internal.util.State; 59 import com.android.internal.util.StateMachine; 60 61 import java.io.ByteArrayOutputStream; 62 import java.util.Arrays; 63 import java.util.List; 64 65 import static android.telephony.TelephonyManager.PHONE_TYPE_CDMA; 66 67 /** 68 * This class broadcasts incoming SMS messages to interested apps after storing them in 69 * the SmsProvider "raw" table and ACKing them to the SMSC. After each message has been 70 * broadcast, its parts are removed from the raw table. If the device crashes after ACKing 71 * but before the broadcast completes, the pending messages will be rebroadcast on the next boot. 72 * 73 * <p>The state machine starts in {@link IdleState} state. When the {@link SMSDispatcher} receives a 74 * new SMS from the radio, it calls {@link #dispatchNormalMessage}, 75 * which sends a message to the state machine, causing the wakelock to be acquired in 76 * {@link #haltedProcessMessage}, which transitions to {@link DeliveringState} state, where the message 77 * is saved to the raw table, then acknowledged via the {@link SMSDispatcher} which called us. 78 * 79 * <p>After saving the SMS, if the message is complete (either single-part or the final segment 80 * of a multi-part SMS), we broadcast the completed PDUs as an ordered broadcast, then transition to 81 * {@link WaitingState} state to wait for the broadcast to complete. When the local 82 * {@link BroadcastReceiver} is called with the result, it sends {@link #EVENT_BROADCAST_COMPLETE} 83 * to the state machine, causing us to either broadcast the next pending message (if one has 84 * arrived while waiting for the broadcast to complete), or to transition back to the halted state 85 * after all messages are processed. Then the wakelock is released and we wait for the next SMS. 86 */ 87 public abstract class InboundSmsHandler extends StateMachine { 88 protected static final boolean DBG = true; 89 private static final boolean VDBG = false; // STOPSHIP if true, logs user data 90 91 /** Query projection for checking for duplicate message segments. */ 92 private static final String[] PDU_PROJECTION = { 93 "pdu" 94 }; 95 96 /** Query projection for combining concatenated message segments. */ 97 private static final String[] PDU_SEQUENCE_PORT_PROJECTION = { 98 "pdu", 99 "sequence", 100 "destination_port" 101 }; 102 103 static final int PDU_COLUMN = 0; 104 static final int SEQUENCE_COLUMN = 1; 105 static final int DESTINATION_PORT_COLUMN = 2; 106 static final int DATE_COLUMN = 3; 107 static final int REFERENCE_NUMBER_COLUMN = 4; 108 static final int COUNT_COLUMN = 5; 109 static final int ADDRESS_COLUMN = 6; 110 static final int ID_COLUMN = 7; 111 112 static final String SELECT_BY_ID = "_id=?"; 113 static final String SELECT_BY_REFERENCE = "address=? AND reference_number=? AND count=?"; 114 115 /** New SMS received as an AsyncResult. */ 116 public static final int EVENT_NEW_SMS = 1; 117 118 /** Message type containing a {@link InboundSmsTracker} ready to broadcast to listeners. */ 119 static final int EVENT_BROADCAST_SMS = 2; 120 121 /** Message from resultReceiver notifying {@link WaitingState} of a completed broadcast. */ 122 static final int EVENT_BROADCAST_COMPLETE = 3; 123 124 /** Sent on exit from {@link WaitingState} to return to idle after sending all broadcasts. */ 125 static final int EVENT_RETURN_TO_IDLE = 4; 126 127 /** Release wakelock after a short timeout when returning to idle state. */ 128 static final int EVENT_RELEASE_WAKELOCK = 5; 129 130 /** Sent by {@link SmsBroadcastUndelivered} after cleaning the raw table. */ 131 static final int EVENT_START_ACCEPTING_SMS = 6; 132 133 /** Update phone object */ 134 static final int EVENT_UPDATE_PHONE_OBJECT = 7; 135 136 /** New SMS received as an AsyncResult. */ 137 public static final int EVENT_INJECT_SMS = 8; 138 139 /** Wakelock release delay when returning to idle state. */ 140 private static final int WAKELOCK_TIMEOUT = 3000; 141 142 /** URI for raw table of SMS provider. */ 143 private static final Uri sRawUri = Uri.withAppendedPath(Telephony.Sms.CONTENT_URI, "raw"); 144 145 protected final Context mContext; 146 private final ContentResolver mResolver; 147 148 /** Special handler for WAP push messages. */ 149 private final WapPushOverSms mWapPush; 150 151 /** Wake lock to ensure device stays awake while dispatching the SMS intents. */ 152 final PowerManager.WakeLock mWakeLock; 153 154 /** DefaultState throws an exception or logs an error for unhandled message types. */ 155 final DefaultState mDefaultState = new DefaultState(); 156 157 /** Startup state. Waiting for {@link SmsBroadcastUndelivered} to complete. */ 158 final StartupState mStartupState = new StartupState(); 159 160 /** Idle state. Waiting for messages to process. */ 161 final IdleState mIdleState = new IdleState(); 162 163 /** Delivering state. Saves the PDU in the raw table and acknowledges to SMSC. */ 164 final DeliveringState mDeliveringState = new DeliveringState(); 165 166 /** Broadcasting state. Waits for current broadcast to complete before delivering next. */ 167 final WaitingState mWaitingState = new WaitingState(); 168 169 /** Helper class to check whether storage is available for incoming messages. */ 170 protected SmsStorageMonitor mStorageMonitor; 171 172 private final boolean mSmsReceiveDisabled; 173 174 protected PhoneBase mPhone; 175 176 protected CellBroadcastHandler mCellBroadcastHandler; 177 178 private UserManager mUserManager; 179 180 /** 181 * Create a new SMS broadcast helper. 182 * @param name the class name for logging 183 * @param context the context of the phone app 184 * @param storageMonitor the SmsStorageMonitor to check for storage availability 185 */ 186 protected InboundSmsHandler(String name, Context context, SmsStorageMonitor storageMonitor, 187 PhoneBase phone, CellBroadcastHandler cellBroadcastHandler) { 188 super(name); 189 190 mContext = context; 191 mStorageMonitor = storageMonitor; 192 mPhone = phone; 193 mCellBroadcastHandler = cellBroadcastHandler; 194 mResolver = context.getContentResolver(); 195 mWapPush = new WapPushOverSms(context); 196 197 boolean smsCapable = mContext.getResources().getBoolean( 198 com.android.internal.R.bool.config_sms_capable); 199 mSmsReceiveDisabled = !SystemProperties.getBoolean( 200 TelephonyProperties.PROPERTY_SMS_RECEIVE, smsCapable); 201 202 PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE); 203 mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, name); 204 mWakeLock.acquire(); // wake lock released after we enter idle state 205 mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE); 206 207 addState(mDefaultState); 208 addState(mStartupState, mDefaultState); 209 addState(mIdleState, mDefaultState); 210 addState(mDeliveringState, mDefaultState); 211 addState(mWaitingState, mDeliveringState); 212 213 setInitialState(mStartupState); 214 if (DBG) log("created InboundSmsHandler"); 215 } 216 217 /** 218 * Tell the state machine to quit after processing all messages. 219 */ 220 public void dispose() { 221 quit(); 222 } 223 224 /** 225 * Update the phone object when it changes. 226 */ 227 public void updatePhoneObject(PhoneBase phone) { 228 sendMessage(EVENT_UPDATE_PHONE_OBJECT, phone); 229 } 230 231 /** 232 * Dispose of the WAP push object and release the wakelock. 233 */ 234 @Override 235 protected void onQuitting() { 236 mWapPush.dispose(); 237 238 while (mWakeLock.isHeld()) { 239 mWakeLock.release(); 240 } 241 } 242 243 // CAF_MSIM Is this used anywhere ? if not remove it 244 public PhoneBase getPhone() { 245 return mPhone; 246 } 247 248 /** 249 * This parent state throws an exception (for debug builds) or prints an error for unhandled 250 * message types. 251 */ 252 class DefaultState extends State { 253 @Override 254 public boolean processMessage(Message msg) { 255 switch (msg.what) { 256 case EVENT_UPDATE_PHONE_OBJECT: { 257 onUpdatePhoneObject((PhoneBase) msg.obj); 258 break; 259 } 260 default: { 261 String errorText = "processMessage: unhandled message type " + msg.what + 262 " currState=" + getCurrentState().getName(); 263 if (Build.IS_DEBUGGABLE) { 264 loge("---- Dumping InboundSmsHandler ----"); 265 loge("Total records=" + getLogRecCount()); 266 for (int i = Math.max(getLogRecSize() - 20, 0); i < getLogRecSize(); i++) { 267 loge("Rec[%d]: %s\n" + i + getLogRec(i).toString()); 268 } 269 loge("---- Dumped InboundSmsHandler ----"); 270 271 throw new RuntimeException(errorText); 272 } else { 273 loge(errorText); 274 } 275 break; 276 } 277 } 278 return HANDLED; 279 } 280 } 281 282 /** 283 * The Startup state waits for {@link SmsBroadcastUndelivered} to process the raw table and 284 * notify the state machine to broadcast any complete PDUs that might not have been broadcast. 285 */ 286 class StartupState extends State { 287 @Override 288 public boolean processMessage(Message msg) { 289 log("StartupState.processMessage:" + msg.what); 290 switch (msg.what) { 291 case EVENT_NEW_SMS: 292 case EVENT_INJECT_SMS: 293 case EVENT_BROADCAST_SMS: 294 deferMessage(msg); 295 return HANDLED; 296 297 case EVENT_START_ACCEPTING_SMS: 298 transitionTo(mIdleState); 299 return HANDLED; 300 301 case EVENT_BROADCAST_COMPLETE: 302 case EVENT_RETURN_TO_IDLE: 303 case EVENT_RELEASE_WAKELOCK: 304 default: 305 // let DefaultState handle these unexpected message types 306 return NOT_HANDLED; 307 } 308 } 309 } 310 311 /** 312 * In the idle state the wakelock is released until a new SM arrives, then we transition 313 * to Delivering mode to handle it, acquiring the wakelock on exit. 314 */ 315 class IdleState extends State { 316 @Override 317 public void enter() { 318 if (DBG) log("entering Idle state"); 319 sendMessageDelayed(EVENT_RELEASE_WAKELOCK, WAKELOCK_TIMEOUT); 320 } 321 322 @Override 323 public void exit() { 324 mWakeLock.acquire(); 325 if (DBG) log("acquired wakelock, leaving Idle state"); 326 } 327 328 @Override 329 public boolean processMessage(Message msg) { 330 log("IdleState.processMessage:" + msg.what); 331 if (DBG) log("Idle state processing message type " + msg.what); 332 switch (msg.what) { 333 case EVENT_NEW_SMS: 334 case EVENT_INJECT_SMS: 335 case EVENT_BROADCAST_SMS: 336 deferMessage(msg); 337 transitionTo(mDeliveringState); 338 return HANDLED; 339 340 case EVENT_RELEASE_WAKELOCK: 341 mWakeLock.release(); 342 if (DBG) { 343 if (mWakeLock.isHeld()) { 344 // this is okay as long as we call release() for every acquire() 345 log("mWakeLock is still held after release"); 346 } else { 347 log("mWakeLock released"); 348 } 349 } 350 return HANDLED; 351 352 case EVENT_RETURN_TO_IDLE: 353 // already in idle state; ignore 354 return HANDLED; 355 356 case EVENT_BROADCAST_COMPLETE: 357 case EVENT_START_ACCEPTING_SMS: 358 default: 359 // let DefaultState handle these unexpected message types 360 return NOT_HANDLED; 361 } 362 } 363 } 364 365 /** 366 * In the delivering state, the inbound SMS is processed and stored in the raw table. 367 * The message is acknowledged before we exit this state. If there is a message to broadcast, 368 * transition to {@link WaitingState} state to send the ordered broadcast and wait for the 369 * results. When all messages have been processed, the halting state will release the wakelock. 370 */ 371 class DeliveringState extends State { 372 @Override 373 public void enter() { 374 if (DBG) log("entering Delivering state"); 375 } 376 377 @Override 378 public void exit() { 379 if (DBG) log("leaving Delivering state"); 380 } 381 382 @Override 383 public boolean processMessage(Message msg) { 384 log("DeliveringState.processMessage:" + msg.what); 385 switch (msg.what) { 386 case EVENT_NEW_SMS: 387 // handle new SMS from RIL 388 handleNewSms((AsyncResult) msg.obj); 389 sendMessage(EVENT_RETURN_TO_IDLE); 390 return HANDLED; 391 392 case EVENT_INJECT_SMS: 393 // handle new injected SMS 394 handleInjectSms((AsyncResult) msg.obj); 395 sendMessage(EVENT_RETURN_TO_IDLE); 396 return HANDLED; 397 398 case EVENT_BROADCAST_SMS: 399 // if any broadcasts were sent, transition to waiting state 400 if (processMessagePart((InboundSmsTracker) msg.obj)) { 401 transitionTo(mWaitingState); 402 } 403 return HANDLED; 404 405 case EVENT_RETURN_TO_IDLE: 406 // return to idle after processing all other messages 407 transitionTo(mIdleState); 408 return HANDLED; 409 410 case EVENT_RELEASE_WAKELOCK: 411 mWakeLock.release(); // decrement wakelock from previous entry to Idle 412 if (!mWakeLock.isHeld()) { 413 // wakelock should still be held until 3 seconds after we enter Idle 414 loge("mWakeLock released while delivering/broadcasting!"); 415 } 416 return HANDLED; 417 418 // we shouldn't get this message type in this state, log error and halt. 419 case EVENT_BROADCAST_COMPLETE: 420 case EVENT_START_ACCEPTING_SMS: 421 default: 422 // let DefaultState handle these unexpected message types 423 return NOT_HANDLED; 424 } 425 } 426 } 427 428 /** 429 * The waiting state delegates handling of new SMS to parent {@link DeliveringState}, but 430 * defers handling of the {@link #EVENT_BROADCAST_SMS} phase until after the current 431 * result receiver sends {@link #EVENT_BROADCAST_COMPLETE}. Before transitioning to 432 * {@link DeliveringState}, {@link #EVENT_RETURN_TO_IDLE} is sent to transition to 433 * {@link IdleState} after any deferred {@link #EVENT_BROADCAST_SMS} messages are handled. 434 */ 435 class WaitingState extends State { 436 @Override 437 public boolean processMessage(Message msg) { 438 log("WaitingState.processMessage:" + msg.what); 439 switch (msg.what) { 440 case EVENT_BROADCAST_SMS: 441 // defer until the current broadcast completes 442 deferMessage(msg); 443 return HANDLED; 444 445 case EVENT_BROADCAST_COMPLETE: 446 // return to idle after handling all deferred messages 447 sendMessage(EVENT_RETURN_TO_IDLE); 448 transitionTo(mDeliveringState); 449 return HANDLED; 450 451 case EVENT_RETURN_TO_IDLE: 452 // not ready to return to idle; ignore 453 return HANDLED; 454 455 default: 456 // parent state handles the other message types 457 return NOT_HANDLED; 458 } 459 } 460 } 461 462 void handleNewSms(AsyncResult ar) { 463 if (ar.exception != null) { 464 loge("Exception processing incoming SMS: " + ar.exception); 465 return; 466 } 467 468 int result; 469 try { 470 SmsMessage sms = (SmsMessage) ar.result; 471 result = dispatchMessage(sms.mWrappedSmsMessage); 472 } catch (RuntimeException ex) { 473 loge("Exception dispatching message", ex); 474 result = Intents.RESULT_SMS_GENERIC_ERROR; 475 } 476 477 // RESULT_OK means that the SMS will be acknowledged by special handling, 478 // e.g. for SMS-PP data download. Any other result, we should ack here. 479 if (result != Activity.RESULT_OK) { 480 boolean handled = (result == Intents.RESULT_SMS_HANDLED); 481 notifyAndAcknowledgeLastIncomingSms(handled, result, null); 482 } 483 } 484 485 /** 486 * This method is called when a new SMS PDU is injected into application framework. 487 * @param ar is the AsyncResult that has the SMS PDU to be injected. 488 */ 489 void handleInjectSms(AsyncResult ar) { 490 int result; 491 PendingIntent receivedIntent = null; 492 try { 493 receivedIntent = (PendingIntent) ar.userObj; 494 SmsMessage sms = (SmsMessage) ar.result; 495 if (sms == null) { 496 result = Intents.RESULT_SMS_GENERIC_ERROR; 497 } else { 498 result = dispatchMessage(sms.mWrappedSmsMessage); 499 } 500 } catch (RuntimeException ex) { 501 loge("Exception dispatching message", ex); 502 result = Intents.RESULT_SMS_GENERIC_ERROR; 503 } 504 505 if (receivedIntent != null) { 506 try { 507 receivedIntent.send(result); 508 } catch (CanceledException e) { } 509 } 510 } 511 512 /** 513 * Process an SMS message from the RIL, calling subclass methods to handle 3GPP and 514 * 3GPP2-specific message types. 515 * 516 * @param smsb the SmsMessageBase object from the RIL 517 * @return a result code from {@link android.provider.Telephony.Sms.Intents}, 518 * or {@link Activity#RESULT_OK} for delayed acknowledgment to SMSC 519 */ 520 public int dispatchMessage(SmsMessageBase smsb) { 521 // If sms is null, there was a parsing error. 522 if (smsb == null) { 523 loge("dispatchSmsMessage: message is null"); 524 return Intents.RESULT_SMS_GENERIC_ERROR; 525 } 526 527 if (mSmsReceiveDisabled) { 528 // Device doesn't support receiving SMS, 529 log("Received short message on device which doesn't support " 530 + "receiving SMS. Ignored."); 531 return Intents.RESULT_SMS_HANDLED; 532 } 533 534 return dispatchMessageRadioSpecific(smsb); 535 } 536 537 /** 538 * Process voicemail notification, SMS-PP data download, CDMA CMAS, CDMA WAP push, and other 539 * 3GPP/3GPP2-specific messages. Regular SMS messages are handled by calling the shared 540 * {@link #dispatchNormalMessage} from this class. 541 * 542 * @param smsb the SmsMessageBase object from the RIL 543 * @return a result code from {@link android.provider.Telephony.Sms.Intents}, 544 * or {@link Activity#RESULT_OK} for delayed acknowledgment to SMSC 545 */ 546 protected abstract int dispatchMessageRadioSpecific(SmsMessageBase smsb); 547 548 /** 549 * Send an acknowledge message to the SMSC. 550 * @param success indicates that last message was successfully received. 551 * @param result result code indicating any error 552 * @param response callback message sent when operation completes. 553 */ 554 protected abstract void acknowledgeLastIncomingSms(boolean success, 555 int result, Message response); 556 557 /** 558 * Called when the phone changes the default method updates mPhone 559 * mStorageMonitor and mCellBroadcastHandler.updatePhoneObject. 560 * Override if different or other behavior is desired. 561 * 562 * @param phone 563 */ 564 protected void onUpdatePhoneObject(PhoneBase phone) { 565 mPhone = phone; 566 mStorageMonitor = mPhone.mSmsStorageMonitor; 567 log("onUpdatePhoneObject: phone=" + mPhone.getClass().getSimpleName()); 568 } 569 570 /** 571 * Notify interested apps if the framework has rejected an incoming SMS, 572 * and send an acknowledge message to the network. 573 * @param success indicates that last message was successfully received. 574 * @param result result code indicating any error 575 * @param response callback message sent when operation completes. 576 */ 577 void notifyAndAcknowledgeLastIncomingSms(boolean success, 578 int result, Message response) { 579 if (!success) { 580 // broadcast SMS_REJECTED_ACTION intent 581 Intent intent = new Intent(Intents.SMS_REJECTED_ACTION); 582 intent.putExtra("result", result); 583 mContext.sendBroadcast(intent, android.Manifest.permission.RECEIVE_SMS); 584 } 585 acknowledgeLastIncomingSms(success, result, response); 586 } 587 588 /** 589 * Return true if this handler is for 3GPP2 messages; false for 3GPP format. 590 * @return true for the 3GPP2 handler; false for the 3GPP handler 591 */ 592 protected abstract boolean is3gpp2(); 593 594 /** 595 * Dispatch a normal incoming SMS. This is called from {@link #dispatchMessageRadioSpecific} 596 * if no format-specific handling was required. Saves the PDU to the SMS provider raw table, 597 * creates an {@link InboundSmsTracker}, then sends it to the state machine as an 598 * {@link #EVENT_BROADCAST_SMS}. Returns {@link Intents#RESULT_SMS_HANDLED} or an error value. 599 * 600 * @param sms the message to dispatch 601 * @return {@link Intents#RESULT_SMS_HANDLED} if the message was accepted, or an error status 602 */ 603 protected int dispatchNormalMessage(SmsMessageBase sms) { 604 SmsHeader smsHeader = sms.getUserDataHeader(); 605 InboundSmsTracker tracker; 606 607 if ((smsHeader == null) || (smsHeader.concatRef == null)) { 608 // Message is not concatenated. 609 int destPort = -1; 610 if (smsHeader != null && smsHeader.portAddrs != null) { 611 // The message was sent to a port. 612 destPort = smsHeader.portAddrs.destPort; 613 if (DBG) log("destination port: " + destPort); 614 } 615 616 tracker = new InboundSmsTracker(sms.getPdu(), sms.getTimestampMillis(), destPort, 617 is3gpp2(), false); 618 } else { 619 // Create a tracker for this message segment. 620 SmsHeader.ConcatRef concatRef = smsHeader.concatRef; 621 SmsHeader.PortAddrs portAddrs = smsHeader.portAddrs; 622 int destPort = (portAddrs != null ? portAddrs.destPort : -1); 623 624 tracker = new InboundSmsTracker(sms.getPdu(), sms.getTimestampMillis(), destPort, 625 is3gpp2(), sms.getOriginatingAddress(), concatRef.refNumber, 626 concatRef.seqNumber, concatRef.msgCount, false); 627 } 628 629 if (VDBG) log("created tracker: " + tracker); 630 return addTrackerToRawTableAndSendMessage(tracker); 631 } 632 633 /** 634 * Helper to add the tracker to the raw table and then send a message to broadcast it, if 635 * successful. Returns the SMS intent status to return to the SMSC. 636 * @param tracker the tracker to save to the raw table and then deliver 637 * @return {@link Intents#RESULT_SMS_HANDLED} or {@link Intents#RESULT_SMS_GENERIC_ERROR} 638 * or {@link Intents#RESULT_SMS_DUPLICATED} 639 */ 640 protected int addTrackerToRawTableAndSendMessage(InboundSmsTracker tracker) { 641 switch(addTrackerToRawTable(tracker)) { 642 case Intents.RESULT_SMS_HANDLED: 643 sendMessage(EVENT_BROADCAST_SMS, tracker); 644 return Intents.RESULT_SMS_HANDLED; 645 646 case Intents.RESULT_SMS_DUPLICATED: 647 return Intents.RESULT_SMS_HANDLED; 648 649 case Intents.RESULT_SMS_GENERIC_ERROR: 650 default: 651 return Intents.RESULT_SMS_GENERIC_ERROR; 652 } 653 } 654 655 /** 656 * Process the inbound SMS segment. If the message is complete, send it as an ordered 657 * broadcast to interested receivers and return true. If the message is a segment of an 658 * incomplete multi-part SMS, return false. 659 * @param tracker the tracker containing the message segment to process 660 * @return true if an ordered broadcast was sent; false if waiting for more message segments 661 */ 662 boolean processMessagePart(InboundSmsTracker tracker) { 663 int messageCount = tracker.getMessageCount(); 664 byte[][] pdus; 665 int destPort = tracker.getDestPort(); 666 667 if (messageCount == 1) { 668 // single-part message 669 pdus = new byte[][]{tracker.getPdu()}; 670 } else { 671 // multi-part message 672 Cursor cursor = null; 673 try { 674 // used by several query selection arguments 675 String address = tracker.getAddress(); 676 String refNumber = Integer.toString(tracker.getReferenceNumber()); 677 String count = Integer.toString(tracker.getMessageCount()); 678 679 // query for all segments and broadcast message if we have all the parts 680 String[] whereArgs = {address, refNumber, count}; 681 cursor = mResolver.query(sRawUri, PDU_SEQUENCE_PORT_PROJECTION, 682 SELECT_BY_REFERENCE, whereArgs, null); 683 684 int cursorCount = cursor.getCount(); 685 if (cursorCount < messageCount) { 686 // Wait for the other message parts to arrive. It's also possible for the last 687 // segment to arrive before processing the EVENT_BROADCAST_SMS for one of the 688 // earlier segments. In that case, the broadcast will be sent as soon as all 689 // segments are in the table, and any later EVENT_BROADCAST_SMS messages will 690 // get a row count of 0 and return. 691 return false; 692 } 693 694 // All the parts are in place, deal with them 695 pdus = new byte[messageCount][]; 696 while (cursor.moveToNext()) { 697 // subtract offset to convert sequence to 0-based array index 698 int index = cursor.getInt(SEQUENCE_COLUMN) - tracker.getIndexOffset(); 699 700 pdus[index] = HexDump.hexStringToByteArray(cursor.getString(PDU_COLUMN)); 701 702 // Read the destination port from the first segment (needed for CDMA WAP PDU). 703 // It's not a bad idea to prefer the port from the first segment in other cases. 704 if (index == 0 && !cursor.isNull(DESTINATION_PORT_COLUMN)) { 705 int port = cursor.getInt(DESTINATION_PORT_COLUMN); 706 // strip format flags and convert to real port number, or -1 707 port = InboundSmsTracker.getRealDestPort(port); 708 if (port != -1) { 709 destPort = port; 710 } 711 } 712 } 713 } catch (SQLException e) { 714 loge("Can't access multipart SMS database", e); 715 return false; 716 } finally { 717 if (cursor != null) { 718 cursor.close(); 719 } 720 } 721 } 722 723 BroadcastReceiver resultReceiver = new SmsBroadcastReceiver(tracker); 724 725 if (destPort == SmsHeader.PORT_WAP_PUSH) { 726 // Build up the data stream 727 ByteArrayOutputStream output = new ByteArrayOutputStream(); 728 for (byte[] pdu : pdus) { 729 // 3GPP needs to extract the User Data from the PDU; 3GPP2 has already done this 730 if (!tracker.is3gpp2()) { 731 SmsMessage msg = SmsMessage.createFromPdu(pdu, SmsConstants.FORMAT_3GPP); 732 pdu = msg.getUserData(); 733 } 734 output.write(pdu, 0, pdu.length); 735 } 736 int result = mWapPush.dispatchWapPdu(output.toByteArray(), resultReceiver, this); 737 if (DBG) log("dispatchWapPdu() returned " + result); 738 // result is Activity.RESULT_OK if an ordered broadcast was sent 739 return (result == Activity.RESULT_OK); 740 } 741 742 Intent intent = new Intent(Intents.SMS_FILTER_ACTION); 743 List<String> carrierPackages = null; 744 UiccCard card = UiccController.getInstance().getUiccCard(); 745 if (card != null) { 746 carrierPackages = card.getCarrierPackageNamesForIntent( 747 mContext.getPackageManager(), intent); 748 } 749 if (carrierPackages != null && carrierPackages.size() == 1) { 750 intent.setPackage(carrierPackages.get(0)); 751 intent.putExtra("destport", destPort); 752 } else { 753 setAndDirectIntent(intent, destPort); 754 } 755 756 intent.putExtra("pdus", pdus); 757 intent.putExtra("format", tracker.getFormat()); 758 dispatchIntent(intent, android.Manifest.permission.RECEIVE_SMS, 759 AppOpsManager.OP_RECEIVE_SMS, resultReceiver, UserHandle.OWNER); 760 return true; 761 } 762 763 /** 764 * Dispatch the intent with the specified permission, appOp, and result receiver, using 765 * this state machine's handler thread to run the result receiver. 766 * 767 * @param intent the intent to broadcast 768 * @param permission receivers are required to have this permission 769 * @param appOp app op that is being performed when dispatching to a receiver 770 * @param user user to deliver the intent to 771 */ 772 protected void dispatchIntent(Intent intent, String permission, int appOp, 773 BroadcastReceiver resultReceiver, UserHandle user) { 774 intent.addFlags(Intent.FLAG_RECEIVER_NO_ABORT); 775 SubscriptionManager.putPhoneIdAndSubIdExtra(intent, mPhone.getPhoneId()); 776 if (user.equals(UserHandle.ALL)) { 777 // Get a list of currently started users. 778 int[] users = null; 779 try { 780 users = ActivityManagerNative.getDefault().getRunningUserIds(); 781 } catch (RemoteException re) { 782 } 783 if (users == null) { 784 users = new int[] {user.getIdentifier()}; 785 } 786 // Deliver the broadcast only to those running users that are permitted 787 // by user policy. 788 for (int i = users.length - 1; i >= 0; i--) { 789 UserHandle targetUser = new UserHandle(users[i]); 790 if (users[i] != UserHandle.USER_OWNER) { 791 // Is the user not allowed to use SMS? 792 if (mUserManager.hasUserRestriction(UserManager.DISALLOW_SMS, targetUser)) { 793 continue; 794 } 795 // Skip unknown users and managed profiles as well 796 UserInfo info = mUserManager.getUserInfo(users[i]); 797 if (info == null || info.isManagedProfile()) { 798 continue; 799 } 800 } 801 // Only pass in the resultReceiver when the USER_OWNER is processed. 802 mContext.sendOrderedBroadcastAsUser(intent, targetUser, permission, appOp, 803 users[i] == UserHandle.USER_OWNER ? resultReceiver : null, 804 getHandler(), Activity.RESULT_OK, null, null); 805 } 806 } else { 807 mContext.sendOrderedBroadcastAsUser(intent, user, permission, appOp, 808 resultReceiver, 809 getHandler(), Activity.RESULT_OK, null, null); 810 } 811 } 812 813 /** 814 * Helper for {@link SmsBroadcastUndelivered} to delete an old message in the raw table. 815 */ 816 void deleteFromRawTable(String deleteWhere, String[] deleteWhereArgs) { 817 int rows = mResolver.delete(sRawUri, deleteWhere, deleteWhereArgs); 818 if (rows == 0) { 819 loge("No rows were deleted from raw table!"); 820 } else if (DBG) { 821 log("Deleted " + rows + " rows from raw table."); 822 } 823 } 824 825 /** 826 * Set the appropriate intent action and direct the intent to the default SMS app or the 827 * appropriate port. 828 * 829 * @param intent the intent to set and direct 830 * @param destPort the destination port 831 */ 832 void setAndDirectIntent(Intent intent, int destPort) { 833 if (destPort == -1) { 834 intent.setAction(Intents.SMS_DELIVER_ACTION); 835 836 // Direct the intent to only the default SMS app. If we can't find a default SMS app 837 // then sent it to all broadcast receivers. 838 // We are deliberately delivering to the primary user's default SMS App. 839 ComponentName componentName = SmsApplication.getDefaultSmsApplication(mContext, true); 840 if (componentName != null) { 841 // Deliver SMS message only to this receiver. 842 intent.setComponent(componentName); 843 log("Delivering SMS to: " + componentName.getPackageName() + 844 " " + componentName.getClassName()); 845 } else { 846 intent.setComponent(null); 847 } 848 } else { 849 intent.setAction(Intents.DATA_SMS_RECEIVED_ACTION); 850 Uri uri = Uri.parse("sms://localhost:" + destPort); 851 intent.setData(uri); 852 intent.setComponent(null); 853 } 854 } 855 856 /** 857 * Insert a message PDU into the raw table so we can acknowledge it immediately. 858 * If the device crashes before the broadcast to listeners completes, it will be delivered 859 * from the raw table on the next device boot. For single-part messages, the deleteWhere 860 * and deleteWhereArgs fields of the tracker will be set to delete the correct row after 861 * the ordered broadcast completes. 862 * 863 * @param tracker the tracker to add to the raw table 864 * @return true on success; false on failure to write to database 865 */ 866 private int addTrackerToRawTable(InboundSmsTracker tracker) { 867 if (tracker.getMessageCount() != 1) { 868 // check for duplicate message segments 869 Cursor cursor = null; 870 try { 871 // sequence numbers are 1-based except for CDMA WAP, which is 0-based 872 int sequence = tracker.getSequenceNumber(); 873 874 // convert to strings for query 875 String address = tracker.getAddress(); 876 String refNumber = Integer.toString(tracker.getReferenceNumber()); 877 String count = Integer.toString(tracker.getMessageCount()); 878 879 String seqNumber = Integer.toString(sequence); 880 881 // set the delete selection args for multi-part message 882 String[] deleteWhereArgs = {address, refNumber, count}; 883 tracker.setDeleteWhere(SELECT_BY_REFERENCE, deleteWhereArgs); 884 885 // Check for duplicate message segments 886 cursor = mResolver.query(sRawUri, PDU_PROJECTION, 887 "address=? AND reference_number=? AND count=? AND sequence=?", 888 new String[] {address, refNumber, count, seqNumber}, null); 889 890 // moveToNext() returns false if no duplicates were found 891 if (cursor.moveToNext()) { 892 loge("Discarding duplicate message segment, refNumber=" + refNumber 893 + " seqNumber=" + seqNumber); 894 String oldPduString = cursor.getString(PDU_COLUMN); 895 byte[] pdu = tracker.getPdu(); 896 byte[] oldPdu = HexDump.hexStringToByteArray(oldPduString); 897 if (!Arrays.equals(oldPdu, tracker.getPdu())) { 898 loge("Warning: dup message segment PDU of length " + pdu.length 899 + " is different from existing PDU of length " + oldPdu.length); 900 } 901 return Intents.RESULT_SMS_DUPLICATED; // reject message 902 } 903 cursor.close(); 904 } catch (SQLException e) { 905 loge("Can't access multipart SMS database", e); 906 return Intents.RESULT_SMS_GENERIC_ERROR; // reject message 907 } finally { 908 if (cursor != null) { 909 cursor.close(); 910 } 911 } 912 } 913 914 ContentValues values = tracker.getContentValues(); 915 916 if (VDBG) log("adding content values to raw table: " + values.toString()); 917 Uri newUri = mResolver.insert(sRawUri, values); 918 if (DBG) log("URI of new row -> " + newUri); 919 920 try { 921 long rowId = ContentUris.parseId(newUri); 922 if (tracker.getMessageCount() == 1) { 923 // set the delete selection args for single-part message 924 tracker.setDeleteWhere(SELECT_BY_ID, new String[]{Long.toString(rowId)}); 925 } 926 return Intents.RESULT_SMS_HANDLED; 927 } catch (Exception e) { 928 loge("error parsing URI for new row: " + newUri, e); 929 return Intents.RESULT_SMS_GENERIC_ERROR; 930 } 931 } 932 933 /** 934 * Returns whether the default message format for the current radio technology is 3GPP2. 935 * @return true if the radio technology uses 3GPP2 format by default, false for 3GPP format 936 */ 937 static boolean isCurrentFormat3gpp2() { 938 int activePhone = TelephonyManager.getDefault().getCurrentPhoneType(); 939 return (PHONE_TYPE_CDMA == activePhone); 940 } 941 942 /** 943 * Handler for an {@link InboundSmsTracker} broadcast. Deletes PDUs from the raw table and 944 * logs the broadcast duration (as an error if the other receivers were especially slow). 945 */ 946 private final class SmsBroadcastReceiver extends BroadcastReceiver { 947 private final String mDeleteWhere; 948 private final String[] mDeleteWhereArgs; 949 private long mBroadcastTimeNano; 950 951 SmsBroadcastReceiver(InboundSmsTracker tracker) { 952 mDeleteWhere = tracker.getDeleteWhere(); 953 mDeleteWhereArgs = tracker.getDeleteWhereArgs(); 954 mBroadcastTimeNano = System.nanoTime(); 955 } 956 957 @Override 958 public void onReceive(Context context, Intent intent) { 959 String action = intent.getAction(); 960 if (action.equals(Intents.SMS_FILTER_ACTION)) { 961 int rc = getResultCode(); 962 if (rc == Activity.RESULT_OK) { 963 // Overwrite pdus data if the SMS filter has set it. 964 Bundle resultExtras = getResultExtras(false); 965 if (resultExtras != null && resultExtras.containsKey("pdus")) { 966 intent.putExtra("pdus", (byte[][]) resultExtras.get("pdus")); 967 } 968 if (intent.hasExtra("destport")) { 969 int destPort = intent.getIntExtra("destport", -1); 970 intent.removeExtra("destport"); 971 setAndDirectIntent(intent, destPort); 972 if (SmsManager.getDefault().getAutoPersisting()) { 973 final Uri uri = writeInboxMessage(intent); 974 if (uri != null) { 975 // Pass this to SMS apps so that they know where it is stored 976 intent.putExtra("uri", uri.toString()); 977 } 978 } 979 dispatchIntent(intent, android.Manifest.permission.RECEIVE_SMS, 980 AppOpsManager.OP_RECEIVE_SMS, this, UserHandle.OWNER); 981 } else { 982 loge("destport doesn't exist in the extras for SMS filter action."); 983 } 984 } else { 985 // Drop this SMS. 986 log("SMS filtered by result code " + rc); 987 deleteFromRawTable(mDeleteWhere, mDeleteWhereArgs); 988 sendMessage(EVENT_BROADCAST_COMPLETE); 989 } 990 } else if (action.equals(Intents.SMS_DELIVER_ACTION)) { 991 // Now dispatch the notification only intent 992 intent.setAction(Intents.SMS_RECEIVED_ACTION); 993 intent.setComponent(null); 994 // All running users will be notified of the received sms. 995 dispatchIntent(intent, android.Manifest.permission.RECEIVE_SMS, 996 AppOpsManager.OP_RECEIVE_SMS, this, UserHandle.ALL); 997 } else if (action.equals(Intents.WAP_PUSH_DELIVER_ACTION)) { 998 // Now dispatch the notification only intent 999 intent.setAction(Intents.WAP_PUSH_RECEIVED_ACTION); 1000 intent.setComponent(null); 1001 // Only the primary user will receive notification of incoming mms. 1002 // That app will do the actual downloading of the mms. 1003 dispatchIntent(intent, android.Manifest.permission.RECEIVE_SMS, 1004 AppOpsManager.OP_RECEIVE_SMS, this, UserHandle.OWNER); 1005 } else { 1006 // Now that the intents have been deleted we can clean up the PDU data. 1007 if (!Intents.DATA_SMS_RECEIVED_ACTION.equals(action) 1008 && !Intents.SMS_RECEIVED_ACTION.equals(action) 1009 && !Intents.DATA_SMS_RECEIVED_ACTION.equals(action) 1010 && !Intents.WAP_PUSH_RECEIVED_ACTION.equals(action)) { 1011 loge("unexpected BroadcastReceiver action: " + action); 1012 } 1013 1014 int rc = getResultCode(); 1015 if ((rc != Activity.RESULT_OK) && (rc != Intents.RESULT_SMS_HANDLED)) { 1016 loge("a broadcast receiver set the result code to " + rc 1017 + ", deleting from raw table anyway!"); 1018 } else if (DBG) { 1019 log("successful broadcast, deleting from raw table."); 1020 } 1021 1022 deleteFromRawTable(mDeleteWhere, mDeleteWhereArgs); 1023 sendMessage(EVENT_BROADCAST_COMPLETE); 1024 1025 int durationMillis = (int) ((System.nanoTime() - mBroadcastTimeNano) / 1000000); 1026 if (durationMillis >= 5000) { 1027 loge("Slow ordered broadcast completion time: " + durationMillis + " ms"); 1028 } else if (DBG) { 1029 log("ordered broadcast completed in: " + durationMillis + " ms"); 1030 } 1031 } 1032 } 1033 } 1034 1035 /** 1036 * Log with debug level. 1037 * @param s the string to log 1038 */ 1039 @Override 1040 protected void log(String s) { 1041 Rlog.d(getName(), s); 1042 } 1043 1044 /** 1045 * Log with error level. 1046 * @param s the string to log 1047 */ 1048 @Override 1049 protected void loge(String s) { 1050 Rlog.e(getName(), s); 1051 } 1052 1053 /** 1054 * Log with error level. 1055 * @param s the string to log 1056 * @param e is a Throwable which logs additional information. 1057 */ 1058 @Override 1059 protected void loge(String s, Throwable e) { 1060 Rlog.e(getName(), s, e); 1061 } 1062 1063 /** 1064 * Store a received SMS into Telephony provider 1065 * 1066 * @param intent The intent containing the received SMS 1067 * @return The URI of written message 1068 */ 1069 private Uri writeInboxMessage(Intent intent) { 1070 final SmsMessage[] messages = Telephony.Sms.Intents.getMessagesFromIntent(intent); 1071 if (messages == null || messages.length < 1) { 1072 loge("Failed to parse SMS pdu"); 1073 return null; 1074 } 1075 // Sometimes, SmsMessage.mWrappedSmsMessage is null causing NPE when we access 1076 // the methods on it although the SmsMessage itself is not null. So do this check 1077 // before we do anything on the parsed SmsMessages. 1078 for (final SmsMessage sms : messages) { 1079 try { 1080 sms.getDisplayMessageBody(); 1081 } catch (NullPointerException e) { 1082 loge("NPE inside SmsMessage"); 1083 return null; 1084 } 1085 } 1086 final ContentValues values = parseSmsMessage(messages); 1087 final long identity = Binder.clearCallingIdentity(); 1088 try { 1089 return mContext.getContentResolver().insert(Telephony.Sms.Inbox.CONTENT_URI, values); 1090 } catch (Exception e) { 1091 loge("Failed to persist inbox message", e); 1092 } finally { 1093 Binder.restoreCallingIdentity(identity); 1094 } 1095 return null; 1096 } 1097 1098 /** 1099 * Convert SmsMessage[] into SMS database schema columns 1100 * 1101 * @param msgs The SmsMessage array of the received SMS 1102 * @return ContentValues representing the columns of parsed SMS 1103 */ 1104 private static ContentValues parseSmsMessage(SmsMessage[] msgs) { 1105 final SmsMessage sms = msgs[0]; 1106 final ContentValues values = new ContentValues(); 1107 values.put(Telephony.Sms.Inbox.ADDRESS, sms.getDisplayOriginatingAddress()); 1108 values.put(Telephony.Sms.Inbox.BODY, buildMessageBodyFromPdus(msgs)); 1109 values.put(Telephony.Sms.Inbox.DATE_SENT, sms.getTimestampMillis()); 1110 values.put(Telephony.Sms.Inbox.DATE, System.currentTimeMillis()); 1111 values.put(Telephony.Sms.Inbox.PROTOCOL, sms.getProtocolIdentifier()); 1112 values.put(Telephony.Sms.Inbox.SEEN, 0); 1113 values.put(Telephony.Sms.Inbox.READ, 0); 1114 final String subject = sms.getPseudoSubject(); 1115 if (!TextUtils.isEmpty(subject)) { 1116 values.put(Telephony.Sms.Inbox.SUBJECT, subject); 1117 } 1118 values.put(Telephony.Sms.Inbox.REPLY_PATH_PRESENT, sms.isReplyPathPresent() ? 1 : 0); 1119 values.put(Telephony.Sms.Inbox.SERVICE_CENTER, sms.getServiceCenterAddress()); 1120 return values; 1121 } 1122 1123 /** 1124 * Build up the SMS message body from the SmsMessage array of received SMS 1125 * 1126 * @param msgs The SmsMessage array of the received SMS 1127 * @return The text message body 1128 */ 1129 private static String buildMessageBodyFromPdus(SmsMessage[] msgs) { 1130 if (msgs.length == 1) { 1131 // There is only one part, so grab the body directly. 1132 return replaceFormFeeds(msgs[0].getDisplayMessageBody()); 1133 } else { 1134 // Build up the body from the parts. 1135 StringBuilder body = new StringBuilder(); 1136 for (SmsMessage msg: msgs) { 1137 // getDisplayMessageBody() can NPE if mWrappedMessage inside is null. 1138 body.append(msg.getDisplayMessageBody()); 1139 } 1140 return replaceFormFeeds(body.toString()); 1141 } 1142 } 1143 1144 // Some providers send formfeeds in their messages. Convert those formfeeds to newlines. 1145 private static String replaceFormFeeds(String s) { 1146 return s == null ? "" : s.replace('\f', '\n'); 1147 } 1148 } 1149