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 static android.service.carrier.CarrierMessagingService.RECEIVE_OPTIONS_SKIP_NOTIFY_WHEN_CREDENTIAL_PROTECTED_STORAGE_UNAVAILABLE; 20 import static android.telephony.TelephonyManager.PHONE_TYPE_CDMA; 21 22 import android.app.Activity; 23 import android.app.ActivityManagerNative; 24 import android.app.AppOpsManager; 25 import android.app.BroadcastOptions; 26 import android.app.Notification; 27 import android.app.NotificationManager; 28 import android.app.PendingIntent; 29 import android.app.PendingIntent.CanceledException; 30 import android.content.BroadcastReceiver; 31 import android.content.ComponentName; 32 import android.content.ContentResolver; 33 import android.content.ContentUris; 34 import android.content.ContentValues; 35 import android.content.Context; 36 import android.content.Intent; 37 import android.content.pm.IPackageManager; 38 import android.content.pm.PackageManager; 39 import android.content.pm.ResolveInfo; 40 import android.content.pm.UserInfo; 41 import android.database.Cursor; 42 import android.database.SQLException; 43 import android.net.Uri; 44 import android.os.storage.StorageManager; 45 import android.os.AsyncResult; 46 import android.os.Binder; 47 import android.os.Build; 48 import android.os.Bundle; 49 import android.os.IDeviceIdleController; 50 import android.os.Message; 51 import android.os.PowerManager; 52 import android.os.RemoteException; 53 import android.os.ServiceManager; 54 import android.os.UserHandle; 55 import android.os.UserManager; 56 import android.provider.Telephony; 57 import android.provider.Telephony.Sms.Intents; 58 import android.service.carrier.CarrierMessagingService; 59 import android.service.carrier.ICarrierMessagingCallback; 60 import android.service.carrier.ICarrierMessagingService; 61 import android.service.carrier.MessagePdu; 62 import android.telephony.CarrierMessagingServiceManager; 63 import android.telephony.Rlog; 64 import android.telephony.SmsManager; 65 import android.telephony.SmsMessage; 66 import android.telephony.SubscriptionManager; 67 import android.telephony.TelephonyManager; 68 import android.text.TextUtils; 69 70 import com.android.internal.R; 71 import com.android.internal.annotations.VisibleForTesting; 72 import com.android.internal.telephony.uicc.UiccCard; 73 import com.android.internal.telephony.uicc.UiccController; 74 import com.android.internal.util.HexDump; 75 import com.android.internal.util.State; 76 import com.android.internal.util.StateMachine; 77 78 import java.io.ByteArrayOutputStream; 79 import java.util.ArrayList; 80 import java.util.Arrays; 81 import java.util.List; 82 83 /** 84 * This class broadcasts incoming SMS messages to interested apps after storing them in 85 * the SmsProvider "raw" table and ACKing them to the SMSC. After each message has been 86 * broadcast, its parts are removed from the raw table. If the device crashes after ACKing 87 * but before the broadcast completes, the pending messages will be rebroadcast on the next boot. 88 * 89 * <p>The state machine starts in {@link IdleState} state. When the {@link SMSDispatcher} receives a 90 * new SMS from the radio, it calls {@link #dispatchNormalMessage}, 91 * which sends a message to the state machine, causing the wakelock to be acquired in 92 * {@link #haltedProcessMessage}, which transitions to {@link DeliveringState} state, where the message 93 * is saved to the raw table, then acknowledged via the {@link SMSDispatcher} which called us. 94 * 95 * <p>After saving the SMS, if the message is complete (either single-part or the final segment 96 * of a multi-part SMS), we broadcast the completed PDUs as an ordered broadcast, then transition to 97 * {@link WaitingState} state to wait for the broadcast to complete. When the local 98 * {@link BroadcastReceiver} is called with the result, it sends {@link #EVENT_BROADCAST_COMPLETE} 99 * to the state machine, causing us to either broadcast the next pending message (if one has 100 * arrived while waiting for the broadcast to complete), or to transition back to the halted state 101 * after all messages are processed. Then the wakelock is released and we wait for the next SMS. 102 */ 103 public abstract class InboundSmsHandler extends StateMachine { 104 protected static final boolean DBG = true; 105 private static final boolean VDBG = false; // STOPSHIP if true, logs user data 106 107 /** Query projection for checking for duplicate message segments. */ 108 private static final String[] PDU_PROJECTION = { 109 "pdu" 110 }; 111 112 /** Query projection for combining concatenated message segments. */ 113 private static final String[] PDU_SEQUENCE_PORT_PROJECTION = { 114 "pdu", 115 "sequence", 116 "destination_port" 117 }; 118 119 public static final int PDU_COLUMN = 0; 120 public static final int SEQUENCE_COLUMN = 1; 121 public static final int DESTINATION_PORT_COLUMN = 2; 122 public static final int DATE_COLUMN = 3; 123 public static final int REFERENCE_NUMBER_COLUMN = 4; 124 public static final int COUNT_COLUMN = 5; 125 public static final int ADDRESS_COLUMN = 6; 126 public static final int ID_COLUMN = 7; 127 public static final int MESSAGE_BODY_COLUMN = 8; 128 129 public static final String SELECT_BY_ID = "_id=?"; 130 public static final String SELECT_BY_REFERENCE = "address=? AND reference_number=? AND " + 131 "count=? AND deleted=0"; 132 133 /** New SMS received as an AsyncResult. */ 134 public static final int EVENT_NEW_SMS = 1; 135 136 /** Message type containing a {@link InboundSmsTracker} ready to broadcast to listeners. */ 137 public static final int EVENT_BROADCAST_SMS = 2; 138 139 /** Message from resultReceiver notifying {@link WaitingState} of a completed broadcast. */ 140 private static final int EVENT_BROADCAST_COMPLETE = 3; 141 142 /** Sent on exit from {@link WaitingState} to return to idle after sending all broadcasts. */ 143 private static final int EVENT_RETURN_TO_IDLE = 4; 144 145 /** Release wakelock after a short timeout when returning to idle state. */ 146 private static final int EVENT_RELEASE_WAKELOCK = 5; 147 148 /** Sent by {@link SmsBroadcastUndelivered} after cleaning the raw table. */ 149 public static final int EVENT_START_ACCEPTING_SMS = 6; 150 151 /** Update phone object */ 152 private static final int EVENT_UPDATE_PHONE_OBJECT = 7; 153 154 /** New SMS received as an AsyncResult. */ 155 public static final int EVENT_INJECT_SMS = 8; 156 157 /** Wakelock release delay when returning to idle state. */ 158 private static final int WAKELOCK_TIMEOUT = 3000; 159 160 // The notitfication tag used when showing a notification. The combination of notification tag 161 // and notification id should be unique within the phone app. 162 private static final String NOTIFICATION_TAG = "InboundSmsHandler"; 163 private static final int NOTIFICATION_ID_NEW_MESSAGE = 1; 164 165 /** URI for raw table of SMS provider. */ 166 protected static final Uri sRawUri = Uri.withAppendedPath(Telephony.Sms.CONTENT_URI, "raw"); 167 protected static final Uri sRawUriPermanentDelete = 168 Uri.withAppendedPath(Telephony.Sms.CONTENT_URI, "raw/permanentDelete"); 169 170 protected final Context mContext; 171 private final ContentResolver mResolver; 172 173 /** Special handler for WAP push messages. */ 174 private final WapPushOverSms mWapPush; 175 176 /** Wake lock to ensure device stays awake while dispatching the SMS intents. */ 177 private final PowerManager.WakeLock mWakeLock; 178 179 /** DefaultState throws an exception or logs an error for unhandled message types. */ 180 private final DefaultState mDefaultState = new DefaultState(); 181 182 /** Startup state. Waiting for {@link SmsBroadcastUndelivered} to complete. */ 183 private final StartupState mStartupState = new StartupState(); 184 185 /** Idle state. Waiting for messages to process. */ 186 private final IdleState mIdleState = new IdleState(); 187 188 /** Delivering state. Saves the PDU in the raw table and acknowledges to SMSC. */ 189 private final DeliveringState mDeliveringState = new DeliveringState(); 190 191 /** Broadcasting state. Waits for current broadcast to complete before delivering next. */ 192 private final WaitingState mWaitingState = new WaitingState(); 193 194 /** Helper class to check whether storage is available for incoming messages. */ 195 protected SmsStorageMonitor mStorageMonitor; 196 197 private final boolean mSmsReceiveDisabled; 198 199 protected Phone mPhone; 200 201 protected CellBroadcastHandler mCellBroadcastHandler; 202 203 private UserManager mUserManager; 204 205 IDeviceIdleController mDeviceIdleController; 206 207 // Delete permanently from raw table 208 private final int DELETE_PERMANENTLY = 1; 209 // Only mark deleted, but keep in db for message de-duping 210 private final int MARK_DELETED = 2; 211 212 /** 213 * Create a new SMS broadcast helper. 214 * @param name the class name for logging 215 * @param context the context of the phone app 216 * @param storageMonitor the SmsStorageMonitor to check for storage availability 217 */ InboundSmsHandler(String name, Context context, SmsStorageMonitor storageMonitor, Phone phone, CellBroadcastHandler cellBroadcastHandler)218 protected InboundSmsHandler(String name, Context context, SmsStorageMonitor storageMonitor, 219 Phone phone, CellBroadcastHandler cellBroadcastHandler) { 220 super(name); 221 222 mContext = context; 223 mStorageMonitor = storageMonitor; 224 mPhone = phone; 225 mCellBroadcastHandler = cellBroadcastHandler; 226 mResolver = context.getContentResolver(); 227 mWapPush = new WapPushOverSms(context); 228 229 boolean smsCapable = mContext.getResources().getBoolean( 230 com.android.internal.R.bool.config_sms_capable); 231 mSmsReceiveDisabled = !TelephonyManager.from(mContext).getSmsReceiveCapableForPhone( 232 mPhone.getPhoneId(), smsCapable); 233 234 PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE); 235 mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, name); 236 mWakeLock.acquire(); // wake lock released after we enter idle state 237 mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE); 238 mDeviceIdleController = TelephonyComponentFactory.getInstance().getIDeviceIdleController(); 239 240 addState(mDefaultState); 241 addState(mStartupState, mDefaultState); 242 addState(mIdleState, mDefaultState); 243 addState(mDeliveringState, mDefaultState); 244 addState(mWaitingState, mDeliveringState); 245 246 setInitialState(mStartupState); 247 if (DBG) log("created InboundSmsHandler"); 248 } 249 250 /** 251 * Tell the state machine to quit after processing all messages. 252 */ dispose()253 public void dispose() { 254 quit(); 255 } 256 257 /** 258 * Update the phone object when it changes. 259 */ updatePhoneObject(Phone phone)260 public void updatePhoneObject(Phone phone) { 261 sendMessage(EVENT_UPDATE_PHONE_OBJECT, phone); 262 } 263 264 /** 265 * Dispose of the WAP push object and release the wakelock. 266 */ 267 @Override onQuitting()268 protected void onQuitting() { 269 mWapPush.dispose(); 270 271 while (mWakeLock.isHeld()) { 272 mWakeLock.release(); 273 } 274 } 275 276 // CAF_MSIM Is this used anywhere ? if not remove it getPhone()277 public Phone getPhone() { 278 return mPhone; 279 } 280 281 /** 282 * This parent state throws an exception (for debug builds) or prints an error for unhandled 283 * message types. 284 */ 285 private class DefaultState extends State { 286 @Override processMessage(Message msg)287 public boolean processMessage(Message msg) { 288 switch (msg.what) { 289 case EVENT_UPDATE_PHONE_OBJECT: { 290 onUpdatePhoneObject((Phone) msg.obj); 291 break; 292 } 293 default: { 294 String errorText = "processMessage: unhandled message type " + msg.what + 295 " currState=" + getCurrentState().getName(); 296 if (Build.IS_DEBUGGABLE) { 297 loge("---- Dumping InboundSmsHandler ----"); 298 loge("Total records=" + getLogRecCount()); 299 for (int i = Math.max(getLogRecSize() - 20, 0); i < getLogRecSize(); i++) { 300 loge("Rec[%d]: %s\n" + i + getLogRec(i).toString()); 301 } 302 loge("---- Dumped InboundSmsHandler ----"); 303 304 throw new RuntimeException(errorText); 305 } else { 306 loge(errorText); 307 } 308 break; 309 } 310 } 311 return HANDLED; 312 } 313 } 314 315 /** 316 * The Startup state waits for {@link SmsBroadcastUndelivered} to process the raw table and 317 * notify the state machine to broadcast any complete PDUs that might not have been broadcast. 318 */ 319 private class StartupState extends State { 320 @Override processMessage(Message msg)321 public boolean processMessage(Message msg) { 322 log("StartupState.processMessage:" + msg.what); 323 switch (msg.what) { 324 case EVENT_NEW_SMS: 325 case EVENT_INJECT_SMS: 326 case EVENT_BROADCAST_SMS: 327 deferMessage(msg); 328 return HANDLED; 329 330 case EVENT_START_ACCEPTING_SMS: 331 transitionTo(mIdleState); 332 return HANDLED; 333 334 case EVENT_BROADCAST_COMPLETE: 335 case EVENT_RETURN_TO_IDLE: 336 case EVENT_RELEASE_WAKELOCK: 337 default: 338 // let DefaultState handle these unexpected message types 339 return NOT_HANDLED; 340 } 341 } 342 } 343 344 /** 345 * In the idle state the wakelock is released until a new SM arrives, then we transition 346 * to Delivering mode to handle it, acquiring the wakelock on exit. 347 */ 348 private class IdleState extends State { 349 @Override enter()350 public void enter() { 351 if (DBG) log("entering Idle state"); 352 sendMessageDelayed(EVENT_RELEASE_WAKELOCK, WAKELOCK_TIMEOUT); 353 } 354 355 @Override exit()356 public void exit() { 357 mWakeLock.acquire(); 358 if (DBG) log("acquired wakelock, leaving Idle state"); 359 } 360 361 @Override processMessage(Message msg)362 public boolean processMessage(Message msg) { 363 log("IdleState.processMessage:" + msg.what); 364 if (DBG) log("Idle state processing message type " + msg.what); 365 switch (msg.what) { 366 case EVENT_NEW_SMS: 367 case EVENT_INJECT_SMS: 368 case EVENT_BROADCAST_SMS: 369 deferMessage(msg); 370 transitionTo(mDeliveringState); 371 return HANDLED; 372 373 case EVENT_RELEASE_WAKELOCK: 374 mWakeLock.release(); 375 if (DBG) { 376 if (mWakeLock.isHeld()) { 377 // this is okay as long as we call release() for every acquire() 378 log("mWakeLock is still held after release"); 379 } else { 380 log("mWakeLock released"); 381 } 382 } 383 return HANDLED; 384 385 case EVENT_RETURN_TO_IDLE: 386 // already in idle state; ignore 387 return HANDLED; 388 389 case EVENT_BROADCAST_COMPLETE: 390 case EVENT_START_ACCEPTING_SMS: 391 default: 392 // let DefaultState handle these unexpected message types 393 return NOT_HANDLED; 394 } 395 } 396 } 397 398 /** 399 * In the delivering state, the inbound SMS is processed and stored in the raw table. 400 * The message is acknowledged before we exit this state. If there is a message to broadcast, 401 * transition to {@link WaitingState} state to send the ordered broadcast and wait for the 402 * results. When all messages have been processed, the halting state will release the wakelock. 403 */ 404 private class DeliveringState extends State { 405 @Override enter()406 public void enter() { 407 if (DBG) log("entering Delivering state"); 408 } 409 410 @Override exit()411 public void exit() { 412 if (DBG) log("leaving Delivering state"); 413 } 414 415 @Override processMessage(Message msg)416 public boolean processMessage(Message msg) { 417 log("DeliveringState.processMessage:" + msg.what); 418 switch (msg.what) { 419 case EVENT_NEW_SMS: 420 // handle new SMS from RIL 421 handleNewSms((AsyncResult) msg.obj); 422 sendMessage(EVENT_RETURN_TO_IDLE); 423 return HANDLED; 424 425 case EVENT_INJECT_SMS: 426 // handle new injected SMS 427 handleInjectSms((AsyncResult) msg.obj); 428 sendMessage(EVENT_RETURN_TO_IDLE); 429 return HANDLED; 430 431 case EVENT_BROADCAST_SMS: 432 // if any broadcasts were sent, transition to waiting state 433 InboundSmsTracker inboundSmsTracker = (InboundSmsTracker) msg.obj; 434 if (processMessagePart(inboundSmsTracker)) { 435 transitionTo(mWaitingState); 436 } else { 437 // if event is sent from SmsBroadcastUndelivered.broadcastSms(), and 438 // processMessagePart() returns false, the state machine will be stuck in 439 // DeliveringState until next message is received. Send message to 440 // transition to idle to avoid that so that wakelock can be released 441 log("No broadcast sent on processing EVENT_BROADCAST_SMS in Delivering " + 442 "state. Return to Idle state"); 443 sendMessage(EVENT_RETURN_TO_IDLE); 444 } 445 return HANDLED; 446 447 case EVENT_RETURN_TO_IDLE: 448 // return to idle after processing all other messages 449 transitionTo(mIdleState); 450 return HANDLED; 451 452 case EVENT_RELEASE_WAKELOCK: 453 mWakeLock.release(); // decrement wakelock from previous entry to Idle 454 if (!mWakeLock.isHeld()) { 455 // wakelock should still be held until 3 seconds after we enter Idle 456 loge("mWakeLock released while delivering/broadcasting!"); 457 } 458 return HANDLED; 459 460 // we shouldn't get this message type in this state, log error and halt. 461 case EVENT_BROADCAST_COMPLETE: 462 case EVENT_START_ACCEPTING_SMS: 463 default: 464 // let DefaultState handle these unexpected message types 465 return NOT_HANDLED; 466 } 467 } 468 } 469 470 /** 471 * The waiting state delegates handling of new SMS to parent {@link DeliveringState}, but 472 * defers handling of the {@link #EVENT_BROADCAST_SMS} phase until after the current 473 * result receiver sends {@link #EVENT_BROADCAST_COMPLETE}. Before transitioning to 474 * {@link DeliveringState}, {@link #EVENT_RETURN_TO_IDLE} is sent to transition to 475 * {@link IdleState} after any deferred {@link #EVENT_BROADCAST_SMS} messages are handled. 476 */ 477 private class WaitingState extends State { 478 @Override processMessage(Message msg)479 public boolean processMessage(Message msg) { 480 log("WaitingState.processMessage:" + msg.what); 481 switch (msg.what) { 482 case EVENT_BROADCAST_SMS: 483 // defer until the current broadcast completes 484 deferMessage(msg); 485 return HANDLED; 486 487 case EVENT_BROADCAST_COMPLETE: 488 // return to idle after handling all deferred messages 489 sendMessage(EVENT_RETURN_TO_IDLE); 490 transitionTo(mDeliveringState); 491 return HANDLED; 492 493 case EVENT_RETURN_TO_IDLE: 494 // not ready to return to idle; ignore 495 return HANDLED; 496 497 default: 498 // parent state handles the other message types 499 return NOT_HANDLED; 500 } 501 } 502 } 503 handleNewSms(AsyncResult ar)504 private void handleNewSms(AsyncResult ar) { 505 if (ar.exception != null) { 506 loge("Exception processing incoming SMS: " + ar.exception); 507 return; 508 } 509 510 int result; 511 try { 512 SmsMessage sms = (SmsMessage) ar.result; 513 result = dispatchMessage(sms.mWrappedSmsMessage); 514 } catch (RuntimeException ex) { 515 loge("Exception dispatching message", ex); 516 result = Intents.RESULT_SMS_GENERIC_ERROR; 517 } 518 519 // RESULT_OK means that the SMS will be acknowledged by special handling, 520 // e.g. for SMS-PP data download. Any other result, we should ack here. 521 if (result != Activity.RESULT_OK) { 522 boolean handled = (result == Intents.RESULT_SMS_HANDLED); 523 notifyAndAcknowledgeLastIncomingSms(handled, result, null); 524 } 525 } 526 527 /** 528 * This method is called when a new SMS PDU is injected into application framework. 529 * @param ar is the AsyncResult that has the SMS PDU to be injected. 530 */ handleInjectSms(AsyncResult ar)531 private void handleInjectSms(AsyncResult ar) { 532 int result; 533 PendingIntent receivedIntent = null; 534 try { 535 receivedIntent = (PendingIntent) ar.userObj; 536 SmsMessage sms = (SmsMessage) ar.result; 537 if (sms == null) { 538 result = Intents.RESULT_SMS_GENERIC_ERROR; 539 } else { 540 result = dispatchMessage(sms.mWrappedSmsMessage); 541 } 542 } catch (RuntimeException ex) { 543 loge("Exception dispatching message", ex); 544 result = Intents.RESULT_SMS_GENERIC_ERROR; 545 } 546 547 if (receivedIntent != null) { 548 try { 549 receivedIntent.send(result); 550 } catch (CanceledException e) { } 551 } 552 } 553 554 /** 555 * Process an SMS message from the RIL, calling subclass methods to handle 3GPP and 556 * 3GPP2-specific message types. 557 * 558 * @param smsb the SmsMessageBase object from the RIL 559 * @return a result code from {@link android.provider.Telephony.Sms.Intents}, 560 * or {@link Activity#RESULT_OK} for delayed acknowledgment to SMSC 561 */ dispatchMessage(SmsMessageBase smsb)562 private int dispatchMessage(SmsMessageBase smsb) { 563 // If sms is null, there was a parsing error. 564 if (smsb == null) { 565 loge("dispatchSmsMessage: message is null"); 566 return Intents.RESULT_SMS_GENERIC_ERROR; 567 } 568 569 if (mSmsReceiveDisabled) { 570 // Device doesn't support receiving SMS, 571 log("Received short message on device which doesn't support " 572 + "receiving SMS. Ignored."); 573 return Intents.RESULT_SMS_HANDLED; 574 } 575 576 // onlyCore indicates if the device is in cryptkeeper 577 boolean onlyCore = false; 578 try { 579 onlyCore = IPackageManager.Stub.asInterface(ServiceManager.getService("package")). 580 isOnlyCoreApps(); 581 } catch (RemoteException e) { 582 } 583 if (onlyCore) { 584 // Device is unable to receive SMS in encrypted state 585 log("Received a short message in encrypted state. Rejecting."); 586 return Intents.RESULT_SMS_GENERIC_ERROR; 587 } 588 589 return dispatchMessageRadioSpecific(smsb); 590 } 591 592 /** 593 * Process voicemail notification, SMS-PP data download, CDMA CMAS, CDMA WAP push, and other 594 * 3GPP/3GPP2-specific messages. Regular SMS messages are handled by calling the shared 595 * {@link #dispatchNormalMessage} from this class. 596 * 597 * @param smsb the SmsMessageBase object from the RIL 598 * @return a result code from {@link android.provider.Telephony.Sms.Intents}, 599 * or {@link Activity#RESULT_OK} for delayed acknowledgment to SMSC 600 */ dispatchMessageRadioSpecific(SmsMessageBase smsb)601 protected abstract int dispatchMessageRadioSpecific(SmsMessageBase smsb); 602 603 /** 604 * Send an acknowledge message to the SMSC. 605 * @param success indicates that last message was successfully received. 606 * @param result result code indicating any error 607 * @param response callback message sent when operation completes. 608 */ acknowledgeLastIncomingSms(boolean success, int result, Message response)609 protected abstract void acknowledgeLastIncomingSms(boolean success, 610 int result, Message response); 611 612 /** 613 * Called when the phone changes the default method updates mPhone 614 * mStorageMonitor and mCellBroadcastHandler.updatePhoneObject. 615 * Override if different or other behavior is desired. 616 * 617 * @param phone 618 */ onUpdatePhoneObject(Phone phone)619 protected void onUpdatePhoneObject(Phone phone) { 620 mPhone = phone; 621 mStorageMonitor = mPhone.mSmsStorageMonitor; 622 log("onUpdatePhoneObject: phone=" + mPhone.getClass().getSimpleName()); 623 } 624 625 /** 626 * Notify interested apps if the framework has rejected an incoming SMS, 627 * and send an acknowledge message to the network. 628 * @param success indicates that last message was successfully received. 629 * @param result result code indicating any error 630 * @param response callback message sent when operation completes. 631 */ notifyAndAcknowledgeLastIncomingSms(boolean success, int result, Message response)632 private void notifyAndAcknowledgeLastIncomingSms(boolean success, 633 int result, Message response) { 634 if (!success) { 635 // broadcast SMS_REJECTED_ACTION intent 636 Intent intent = new Intent(Intents.SMS_REJECTED_ACTION); 637 intent.putExtra("result", result); 638 mContext.sendBroadcast(intent, android.Manifest.permission.RECEIVE_SMS); 639 } 640 acknowledgeLastIncomingSms(success, result, response); 641 } 642 643 /** 644 * Return true if this handler is for 3GPP2 messages; false for 3GPP format. 645 * @return true for the 3GPP2 handler; false for the 3GPP handler 646 */ is3gpp2()647 protected abstract boolean is3gpp2(); 648 649 /** 650 * Dispatch a normal incoming SMS. This is called from {@link #dispatchMessageRadioSpecific} 651 * if no format-specific handling was required. Saves the PDU to the SMS provider raw table, 652 * creates an {@link InboundSmsTracker}, then sends it to the state machine as an 653 * {@link #EVENT_BROADCAST_SMS}. Returns {@link Intents#RESULT_SMS_HANDLED} or an error value. 654 * 655 * @param sms the message to dispatch 656 * @return {@link Intents#RESULT_SMS_HANDLED} if the message was accepted, or an error status 657 */ dispatchNormalMessage(SmsMessageBase sms)658 protected int dispatchNormalMessage(SmsMessageBase sms) { 659 SmsHeader smsHeader = sms.getUserDataHeader(); 660 InboundSmsTracker tracker; 661 662 if ((smsHeader == null) || (smsHeader.concatRef == null)) { 663 // Message is not concatenated. 664 int destPort = -1; 665 if (smsHeader != null && smsHeader.portAddrs != null) { 666 // The message was sent to a port. 667 destPort = smsHeader.portAddrs.destPort; 668 if (DBG) log("destination port: " + destPort); 669 } 670 671 tracker = TelephonyComponentFactory.getInstance().makeInboundSmsTracker(sms.getPdu(), 672 sms.getTimestampMillis(), destPort, is3gpp2(), false, 673 sms.getDisplayOriginatingAddress(), sms.getMessageBody()); 674 } else { 675 // Create a tracker for this message segment. 676 SmsHeader.ConcatRef concatRef = smsHeader.concatRef; 677 SmsHeader.PortAddrs portAddrs = smsHeader.portAddrs; 678 int destPort = (portAddrs != null ? portAddrs.destPort : -1); 679 680 tracker = TelephonyComponentFactory.getInstance().makeInboundSmsTracker(sms.getPdu(), 681 sms.getTimestampMillis(), destPort, is3gpp2(), 682 sms.getDisplayOriginatingAddress(), concatRef.refNumber, concatRef.seqNumber, 683 concatRef.msgCount, false, sms.getMessageBody()); 684 } 685 686 if (VDBG) log("created tracker: " + tracker); 687 688 // de-duping is done only for text messages 689 // destPort = -1 indicates text messages, otherwise it's a data sms 690 return addTrackerToRawTableAndSendMessage(tracker, 691 tracker.getDestPort() == -1 /* de-dup if text message */); 692 } 693 694 /** 695 * Helper to add the tracker to the raw table and then send a message to broadcast it, if 696 * successful. Returns the SMS intent status to return to the SMSC. 697 * @param tracker the tracker to save to the raw table and then deliver 698 * @return {@link Intents#RESULT_SMS_HANDLED} or {@link Intents#RESULT_SMS_GENERIC_ERROR} 699 * or {@link Intents#RESULT_SMS_DUPLICATED} 700 */ addTrackerToRawTableAndSendMessage(InboundSmsTracker tracker, boolean deDup)701 protected int addTrackerToRawTableAndSendMessage(InboundSmsTracker tracker, boolean deDup) { 702 switch(addTrackerToRawTable(tracker, deDup)) { 703 case Intents.RESULT_SMS_HANDLED: 704 sendMessage(EVENT_BROADCAST_SMS, tracker); 705 return Intents.RESULT_SMS_HANDLED; 706 707 case Intents.RESULT_SMS_DUPLICATED: 708 return Intents.RESULT_SMS_HANDLED; 709 710 case Intents.RESULT_SMS_GENERIC_ERROR: 711 default: 712 return Intents.RESULT_SMS_GENERIC_ERROR; 713 } 714 } 715 716 /** 717 * Process the inbound SMS segment. If the message is complete, send it as an ordered 718 * broadcast to interested receivers and return true. If the message is a segment of an 719 * incomplete multi-part SMS, return false. 720 * @param tracker the tracker containing the message segment to process 721 * @return true if an ordered broadcast was sent; false if waiting for more message segments 722 */ processMessagePart(InboundSmsTracker tracker)723 private boolean processMessagePart(InboundSmsTracker tracker) { 724 int messageCount = tracker.getMessageCount(); 725 byte[][] pdus; 726 int destPort = tracker.getDestPort(); 727 728 if (messageCount == 1) { 729 // single-part message 730 pdus = new byte[][]{tracker.getPdu()}; 731 } else { 732 // multi-part message 733 Cursor cursor = null; 734 try { 735 // used by several query selection arguments 736 String address = tracker.getAddress(); 737 String refNumber = Integer.toString(tracker.getReferenceNumber()); 738 String count = Integer.toString(tracker.getMessageCount()); 739 740 // query for all segments and broadcast message if we have all the parts 741 String[] whereArgs = {address, refNumber, count}; 742 cursor = mResolver.query(sRawUri, PDU_SEQUENCE_PORT_PROJECTION, 743 SELECT_BY_REFERENCE, whereArgs, null); 744 745 int cursorCount = cursor.getCount(); 746 if (cursorCount < messageCount) { 747 // Wait for the other message parts to arrive. It's also possible for the last 748 // segment to arrive before processing the EVENT_BROADCAST_SMS for one of the 749 // earlier segments. In that case, the broadcast will be sent as soon as all 750 // segments are in the table, and any later EVENT_BROADCAST_SMS messages will 751 // get a row count of 0 and return. 752 return false; 753 } 754 755 // All the parts are in place, deal with them 756 pdus = new byte[messageCount][]; 757 while (cursor.moveToNext()) { 758 // subtract offset to convert sequence to 0-based array index 759 int index = cursor.getInt(SEQUENCE_COLUMN) - tracker.getIndexOffset(); 760 761 pdus[index] = HexDump.hexStringToByteArray(cursor.getString(PDU_COLUMN)); 762 763 // Read the destination port from the first segment (needed for CDMA WAP PDU). 764 // It's not a bad idea to prefer the port from the first segment in other cases. 765 if (index == 0 && !cursor.isNull(DESTINATION_PORT_COLUMN)) { 766 int port = cursor.getInt(DESTINATION_PORT_COLUMN); 767 // strip format flags and convert to real port number, or -1 768 port = InboundSmsTracker.getRealDestPort(port); 769 if (port != -1) { 770 destPort = port; 771 } 772 } 773 } 774 } catch (SQLException e) { 775 loge("Can't access multipart SMS database", e); 776 return false; 777 } finally { 778 if (cursor != null) { 779 cursor.close(); 780 } 781 } 782 } 783 784 // Do not process null pdu(s). Check for that and return false in that case. 785 List<byte[]> pduList = Arrays.asList(pdus); 786 if (pduList.size() == 0 || pduList.contains(null)) { 787 loge("processMessagePart: returning false due to " + 788 (pduList.size() == 0 ? "pduList.size() == 0" : "pduList.contains(null)")); 789 return false; 790 } 791 792 SmsBroadcastReceiver resultReceiver = new SmsBroadcastReceiver(tracker); 793 794 if (!mUserManager.isUserUnlocked()) { 795 return processMessagePartWithUserLocked(tracker, pdus, destPort, resultReceiver); 796 } 797 798 if (destPort == SmsHeader.PORT_WAP_PUSH) { 799 // Build up the data stream 800 ByteArrayOutputStream output = new ByteArrayOutputStream(); 801 for (byte[] pdu : pdus) { 802 // 3GPP needs to extract the User Data from the PDU; 3GPP2 has already done this 803 if (!tracker.is3gpp2()) { 804 SmsMessage msg = SmsMessage.createFromPdu(pdu, SmsConstants.FORMAT_3GPP); 805 if (msg != null) { 806 pdu = msg.getUserData(); 807 } else { 808 loge("processMessagePart: SmsMessage.createFromPdu returned null"); 809 return false; 810 } 811 } 812 output.write(pdu, 0, pdu.length); 813 } 814 int result = mWapPush.dispatchWapPdu(output.toByteArray(), resultReceiver, this); 815 if (DBG) log("dispatchWapPdu() returned " + result); 816 // result is Activity.RESULT_OK if an ordered broadcast was sent 817 if (result == Activity.RESULT_OK) { 818 return true; 819 } else { 820 deleteFromRawTable(tracker.getDeleteWhere(), tracker.getDeleteWhereArgs(), 821 MARK_DELETED); 822 return false; 823 } 824 } 825 826 if (BlockChecker.isBlocked(mContext, tracker.getAddress())) { 827 deleteFromRawTable(tracker.getDeleteWhere(), tracker.getDeleteWhereArgs(), 828 DELETE_PERMANENTLY); 829 return false; 830 } 831 832 boolean filterInvoked = filterSms( 833 pdus, destPort, tracker, resultReceiver, true /* userUnlocked */); 834 835 if (!filterInvoked) { 836 dispatchSmsDeliveryIntent(pdus, tracker.getFormat(), destPort, resultReceiver); 837 } 838 839 return true; 840 } 841 842 /** 843 * Processes the message part while the credential-encrypted storage is still locked. 844 * 845 * <p>If the message is a regular MMS, show a new message notification. If the message is a 846 * SMS, ask the carrier app to filter it and show the new message notification if the carrier 847 * app asks to keep the message. 848 * 849 * @return true if an ordered broadcast was sent to the carrier app; false otherwise. 850 */ processMessagePartWithUserLocked(InboundSmsTracker tracker, byte[][] pdus, int destPort, SmsBroadcastReceiver resultReceiver)851 private boolean processMessagePartWithUserLocked(InboundSmsTracker tracker, 852 byte[][] pdus, int destPort, SmsBroadcastReceiver resultReceiver) { 853 log("Credential-encrypted storage not available. Port: " + destPort); 854 if (destPort == SmsHeader.PORT_WAP_PUSH && mWapPush.isWapPushForMms(pdus[0], this)) { 855 showNewMessageNotification(); 856 return false; 857 } 858 if (destPort == -1) { 859 // This is a regular SMS - hand it to the carrier or system app for filtering. 860 boolean filterInvoked = filterSms( 861 pdus, destPort, tracker, resultReceiver, false /* userUnlocked */); 862 if (filterInvoked) { 863 // filter invoked, wait for it to return the result. 864 return true; 865 } else { 866 // filter not invoked, show the notification and do nothing further. 867 showNewMessageNotification(); 868 return false; 869 } 870 } 871 return false; 872 } 873 showNewMessageNotification()874 private void showNewMessageNotification() { 875 // Do not show the notification on non-FBE devices. 876 if (!StorageManager.isFileEncryptedNativeOrEmulated()) { 877 return; 878 } 879 log("Show new message notification."); 880 Intent intent = Intent.makeMainSelectorActivity( 881 Intent.ACTION_MAIN, Intent.CATEGORY_APP_MESSAGING); 882 Notification.Builder mBuilder = new Notification.Builder(mContext) 883 .setSmallIcon(com.android.internal.R.drawable.sym_action_chat) 884 .setAutoCancel(true) 885 .setVisibility(Notification.VISIBILITY_PUBLIC) 886 .setDefaults(Notification.DEFAULT_ALL) 887 .setContentTitle(mContext.getString(R.string.new_sms_notification_title)) 888 .setContentText(mContext.getString(R.string.new_sms_notification_content)) 889 .setContentIntent(PendingIntent.getActivity(mContext, 1, intent, 0)); 890 NotificationManager mNotificationManager = 891 (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE); 892 mNotificationManager.notify( 893 NOTIFICATION_TAG, NOTIFICATION_ID_NEW_MESSAGE, mBuilder.build()); 894 } 895 cancelNewMessageNotification(Context context)896 static void cancelNewMessageNotification(Context context) { 897 NotificationManager mNotificationManager = 898 (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); 899 mNotificationManager.cancel(InboundSmsHandler.NOTIFICATION_TAG, 900 InboundSmsHandler.NOTIFICATION_ID_NEW_MESSAGE); 901 } 902 903 /** 904 * Filters the SMS. 905 * 906 * <p>currently 3 filters exists: the carrier package, the system package, and the 907 * VisualVoicemailSmsFilter. 908 * 909 * <p>The filtering process is: 910 * 911 * <p>If the carrier package exists, the SMS will be filtered with it first. If the carrier 912 * package did not drop the SMS, then the VisualVoicemailSmsFilter will filter it in the 913 * callback. 914 * 915 * <p>If the carrier package does not exists, we will let the VisualVoicemailSmsFilter filter 916 * it. If the SMS passed the filter, then we will try to find the system package to do the 917 * filtering. 918 * 919 * @return true if a filter is invoked and the SMS processing flow is diverted, false otherwise. 920 */ filterSms(byte[][] pdus, int destPort, InboundSmsTracker tracker, SmsBroadcastReceiver resultReceiver, boolean userUnlocked)921 private boolean filterSms(byte[][] pdus, int destPort, 922 InboundSmsTracker tracker, SmsBroadcastReceiver resultReceiver, boolean userUnlocked) { 923 List<String> carrierPackages = null; 924 UiccCard card = UiccController.getInstance().getUiccCard(mPhone.getPhoneId()); 925 if (card != null) { 926 carrierPackages = card.getCarrierPackageNamesForIntent( 927 mContext.getPackageManager(), 928 new Intent(CarrierMessagingService.SERVICE_INTERFACE)); 929 } else { 930 loge("UiccCard not initialized."); 931 } 932 933 if (carrierPackages != null && carrierPackages.size() == 1) { 934 log("Found carrier package."); 935 CarrierSmsFilter smsFilter = new CarrierSmsFilter(pdus, destPort, 936 tracker.getFormat(), resultReceiver); 937 CarrierSmsFilterCallback smsFilterCallback = new CarrierSmsFilterCallback(smsFilter, 938 userUnlocked); 939 smsFilter.filterSms(carrierPackages.get(0), smsFilterCallback); 940 return true; 941 } 942 943 // It is possible that carrier app is not present as a CarrierPackage, but instead as a 944 // system app 945 List<String> systemPackages = 946 getSystemAppForIntent(new Intent(CarrierMessagingService.SERVICE_INTERFACE)); 947 948 if (systemPackages != null && systemPackages.size() == 1) { 949 log("Found system package."); 950 CarrierSmsFilter smsFilter = new CarrierSmsFilter(pdus, destPort, 951 tracker.getFormat(), resultReceiver); 952 CarrierSmsFilterCallback smsFilterCallback = new CarrierSmsFilterCallback(smsFilter, 953 userUnlocked); 954 smsFilter.filterSms(systemPackages.get(0), smsFilterCallback); 955 return true; 956 } 957 logv("Unable to find carrier package: " + carrierPackages 958 + ", nor systemPackages: " + systemPackages); 959 960 if (VisualVoicemailSmsFilter.filter( 961 mContext, pdus, tracker.getFormat(), destPort, mPhone.getSubId())) { 962 log("Visual voicemail SMS dropped"); 963 dropSms(resultReceiver); 964 return true; 965 } 966 967 return false; 968 } 969 getSystemAppForIntent(Intent intent)970 private List<String> getSystemAppForIntent(Intent intent) { 971 List<String> packages = new ArrayList<String>(); 972 PackageManager packageManager = mContext.getPackageManager(); 973 List<ResolveInfo> receivers = packageManager.queryIntentServices(intent, 0); 974 String carrierFilterSmsPerm = "android.permission.CARRIER_FILTER_SMS"; 975 976 for (ResolveInfo info : receivers) { 977 if (info.serviceInfo == null) { 978 loge("Can't get service information from " + info); 979 continue; 980 } 981 String packageName = info.serviceInfo.packageName; 982 if (packageManager.checkPermission(carrierFilterSmsPerm, packageName) == 983 packageManager.PERMISSION_GRANTED) { 984 packages.add(packageName); 985 if (DBG) log("getSystemAppForIntent: added package "+ packageName); 986 } 987 } 988 return packages; 989 } 990 991 /** 992 * Dispatch the intent with the specified permission, appOp, and result receiver, using 993 * this state machine's handler thread to run the result receiver. 994 * 995 * @param intent the intent to broadcast 996 * @param permission receivers are required to have this permission 997 * @param appOp app op that is being performed when dispatching to a receiver 998 * @param user user to deliver the intent to 999 */ dispatchIntent(Intent intent, String permission, int appOp, Bundle opts, BroadcastReceiver resultReceiver, UserHandle user)1000 public void dispatchIntent(Intent intent, String permission, int appOp, 1001 Bundle opts, BroadcastReceiver resultReceiver, UserHandle user) { 1002 intent.addFlags(Intent.FLAG_RECEIVER_NO_ABORT); 1003 final String action = intent.getAction(); 1004 if (Intents.SMS_DELIVER_ACTION.equals(action) 1005 || Intents.SMS_RECEIVED_ACTION.equals(action) 1006 || Intents.WAP_PUSH_DELIVER_ACTION.equals(action) 1007 || Intents.WAP_PUSH_RECEIVED_ACTION.equals(action)) { 1008 // Some intents need to be delivered with high priority: 1009 // SMS_DELIVER, SMS_RECEIVED, WAP_PUSH_DELIVER, WAP_PUSH_RECEIVED 1010 // In some situations, like after boot up or system under load, normal 1011 // intent delivery could take a long time. 1012 // This flag should only be set for intents for visible, timely operations 1013 // which is true for the intents above. 1014 intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND); 1015 } 1016 SubscriptionManager.putPhoneIdAndSubIdExtra(intent, mPhone.getPhoneId()); 1017 if (user.equals(UserHandle.ALL)) { 1018 // Get a list of currently started users. 1019 int[] users = null; 1020 try { 1021 users = ActivityManagerNative.getDefault().getRunningUserIds(); 1022 } catch (RemoteException re) { 1023 } 1024 if (users == null) { 1025 users = new int[] {user.getIdentifier()}; 1026 } 1027 // Deliver the broadcast only to those running users that are permitted 1028 // by user policy. 1029 for (int i = users.length - 1; i >= 0; i--) { 1030 UserHandle targetUser = new UserHandle(users[i]); 1031 if (users[i] != UserHandle.USER_SYSTEM) { 1032 // Is the user not allowed to use SMS? 1033 if (mUserManager.hasUserRestriction(UserManager.DISALLOW_SMS, targetUser)) { 1034 continue; 1035 } 1036 // Skip unknown users and managed profiles as well 1037 UserInfo info = mUserManager.getUserInfo(users[i]); 1038 if (info == null || info.isManagedProfile()) { 1039 continue; 1040 } 1041 } 1042 // Only pass in the resultReceiver when the USER_SYSTEM is processed. 1043 mContext.sendOrderedBroadcastAsUser(intent, targetUser, permission, appOp, opts, 1044 users[i] == UserHandle.USER_SYSTEM ? resultReceiver : null, 1045 getHandler(), Activity.RESULT_OK, null, null); 1046 } 1047 } else { 1048 mContext.sendOrderedBroadcastAsUser(intent, user, permission, appOp, opts, 1049 resultReceiver, getHandler(), Activity.RESULT_OK, null, null); 1050 } 1051 } 1052 1053 /** 1054 * Helper for {@link SmsBroadcastUndelivered} to delete an old message in the raw table. 1055 */ deleteFromRawTable(String deleteWhere, String[] deleteWhereArgs, int deleteType)1056 private void deleteFromRawTable(String deleteWhere, String[] deleteWhereArgs, 1057 int deleteType) { 1058 Uri uri = deleteType == DELETE_PERMANENTLY ? sRawUriPermanentDelete : sRawUri; 1059 int rows = mResolver.delete(uri, deleteWhere, deleteWhereArgs); 1060 if (rows == 0) { 1061 loge("No rows were deleted from raw table!"); 1062 } else if (DBG) { 1063 log("Deleted " + rows + " rows from raw table."); 1064 } 1065 } 1066 handleSmsWhitelisting(ComponentName target)1067 private Bundle handleSmsWhitelisting(ComponentName target) { 1068 String pkgName; 1069 String reason; 1070 if (target != null) { 1071 pkgName = target.getPackageName(); 1072 reason = "sms-app"; 1073 } else { 1074 pkgName = mContext.getPackageName(); 1075 reason = "sms-broadcast"; 1076 } 1077 try { 1078 long duration = mDeviceIdleController.addPowerSaveTempWhitelistAppForSms( 1079 pkgName, 0, reason); 1080 BroadcastOptions bopts = BroadcastOptions.makeBasic(); 1081 bopts.setTemporaryAppWhitelistDuration(duration); 1082 return bopts.toBundle(); 1083 } catch (RemoteException e) { 1084 } 1085 1086 return null; 1087 } 1088 1089 /** 1090 * Creates and dispatches the intent to the default SMS app or the appropriate port. 1091 * 1092 * @param pdus message pdus 1093 * @param format the message format, typically "3gpp" or "3gpp2" 1094 * @param destPort the destination port 1095 * @param resultReceiver the receiver handling the delivery result 1096 */ dispatchSmsDeliveryIntent(byte[][] pdus, String format, int destPort, BroadcastReceiver resultReceiver)1097 private void dispatchSmsDeliveryIntent(byte[][] pdus, String format, int destPort, 1098 BroadcastReceiver resultReceiver) { 1099 Intent intent = new Intent(); 1100 intent.putExtra("pdus", pdus); 1101 intent.putExtra("format", format); 1102 1103 if (destPort == -1) { 1104 intent.setAction(Intents.SMS_DELIVER_ACTION); 1105 // Direct the intent to only the default SMS app. If we can't find a default SMS app 1106 // then sent it to all broadcast receivers. 1107 // We are deliberately delivering to the primary user's default SMS App. 1108 ComponentName componentName = SmsApplication.getDefaultSmsApplication(mContext, true); 1109 if (componentName != null) { 1110 // Deliver SMS message only to this receiver. 1111 intent.setComponent(componentName); 1112 log("Delivering SMS to: " + componentName.getPackageName() + 1113 " " + componentName.getClassName()); 1114 } else { 1115 intent.setComponent(null); 1116 } 1117 1118 // TODO: Validate that this is the right place to store the SMS. 1119 if (SmsManager.getDefault().getAutoPersisting()) { 1120 final Uri uri = writeInboxMessage(intent); 1121 if (uri != null) { 1122 // Pass this to SMS apps so that they know where it is stored 1123 intent.putExtra("uri", uri.toString()); 1124 } 1125 } 1126 } else { 1127 intent.setAction(Intents.DATA_SMS_RECEIVED_ACTION); 1128 Uri uri = Uri.parse("sms://localhost:" + destPort); 1129 intent.setData(uri); 1130 intent.setComponent(null); 1131 } 1132 1133 Bundle options = handleSmsWhitelisting(intent.getComponent()); 1134 dispatchIntent(intent, android.Manifest.permission.RECEIVE_SMS, 1135 AppOpsManager.OP_RECEIVE_SMS, options, resultReceiver, UserHandle.SYSTEM); 1136 } 1137 1138 /** 1139 * Function to check if message should be dropped because same message has already been 1140 * received. In certain cases it checks for similar messages instead of exact same (cases where 1141 * keeping both messages in db can cause ambiguity) 1142 * @return true if duplicate exists, false otherwise 1143 */ duplicateExists(InboundSmsTracker tracker)1144 private boolean duplicateExists(InboundSmsTracker tracker) throws SQLException { 1145 String address = tracker.getAddress(); 1146 // convert to strings for query 1147 String refNumber = Integer.toString(tracker.getReferenceNumber()); 1148 String count = Integer.toString(tracker.getMessageCount()); 1149 // sequence numbers are 1-based except for CDMA WAP, which is 0-based 1150 int sequence = tracker.getSequenceNumber(); 1151 String seqNumber = Integer.toString(sequence); 1152 String date = Long.toString(tracker.getTimestamp()); 1153 String messageBody = tracker.getMessageBody(); 1154 String where; 1155 if (tracker.getMessageCount() == 1) { 1156 where = "address=? AND reference_number=? AND count=? AND sequence=? AND " + 1157 "date=? AND message_body=?"; 1158 } else { 1159 // for multi-part messages, deduping should also be done against undeleted 1160 // segments that can cause ambiguity when contacenating the segments, that is, 1161 // segments with same address, reference_number, count and sequence 1162 where = "address=? AND reference_number=? AND count=? AND sequence=? AND " + 1163 "((date=? AND message_body=?) OR deleted=0)"; 1164 } 1165 1166 Cursor cursor = null; 1167 try { 1168 // Check for duplicate message segments 1169 cursor = mResolver.query(sRawUri, PDU_PROJECTION, where, 1170 new String[]{address, refNumber, count, seqNumber, date, messageBody}, 1171 null); 1172 1173 // moveToNext() returns false if no duplicates were found 1174 if (cursor != null && cursor.moveToNext()) { 1175 loge("Discarding duplicate message segment, refNumber=" + refNumber 1176 + " seqNumber=" + seqNumber + " count=" + count); 1177 if (VDBG) { 1178 loge("address=" + address + " date=" + date + " messageBody=" + 1179 messageBody); 1180 } 1181 String oldPduString = cursor.getString(PDU_COLUMN); 1182 byte[] pdu = tracker.getPdu(); 1183 byte[] oldPdu = HexDump.hexStringToByteArray(oldPduString); 1184 if (!Arrays.equals(oldPdu, tracker.getPdu())) { 1185 loge("Warning: dup message segment PDU of length " + pdu.length 1186 + " is different from existing PDU of length " + oldPdu.length); 1187 } 1188 return true; // reject message 1189 } 1190 } finally { 1191 if (cursor != null) { 1192 cursor.close(); 1193 } 1194 } 1195 1196 return false; 1197 } 1198 1199 /** 1200 * Insert a message PDU into the raw table so we can acknowledge it immediately. 1201 * If the device crashes before the broadcast to listeners completes, it will be delivered 1202 * from the raw table on the next device boot. For single-part messages, the deleteWhere 1203 * and deleteWhereArgs fields of the tracker will be set to delete the correct row after 1204 * the ordered broadcast completes. 1205 * 1206 * @param tracker the tracker to add to the raw table 1207 * @return true on success; false on failure to write to database 1208 */ addTrackerToRawTable(InboundSmsTracker tracker, boolean deDup)1209 private int addTrackerToRawTable(InboundSmsTracker tracker, boolean deDup) { 1210 if (deDup) { 1211 try { 1212 if (duplicateExists(tracker)) { 1213 return Intents.RESULT_SMS_DUPLICATED; // reject message 1214 } 1215 } catch (SQLException e) { 1216 loge("Can't access SMS database", e); 1217 return Intents.RESULT_SMS_GENERIC_ERROR; // reject message 1218 } 1219 } else { 1220 logd("Skipped message de-duping logic"); 1221 } 1222 1223 String address = tracker.getAddress(); 1224 String refNumber = Integer.toString(tracker.getReferenceNumber()); 1225 String count = Integer.toString(tracker.getMessageCount()); 1226 ContentValues values = tracker.getContentValues(); 1227 1228 if (VDBG) log("adding content values to raw table: " + values.toString()); 1229 Uri newUri = mResolver.insert(sRawUri, values); 1230 if (DBG) log("URI of new row -> " + newUri); 1231 1232 try { 1233 long rowId = ContentUris.parseId(newUri); 1234 if (tracker.getMessageCount() == 1) { 1235 // set the delete selection args for single-part message 1236 tracker.setDeleteWhere(SELECT_BY_ID, new String[]{Long.toString(rowId)}); 1237 } else { 1238 // set the delete selection args for multi-part message 1239 String[] deleteWhereArgs = {address, refNumber, count}; 1240 tracker.setDeleteWhere(SELECT_BY_REFERENCE, deleteWhereArgs); 1241 } 1242 return Intents.RESULT_SMS_HANDLED; 1243 } catch (Exception e) { 1244 loge("error parsing URI for new row: " + newUri, e); 1245 return Intents.RESULT_SMS_GENERIC_ERROR; 1246 } 1247 } 1248 1249 /** 1250 * Returns whether the default message format for the current radio technology is 3GPP2. 1251 * @return true if the radio technology uses 3GPP2 format by default, false for 3GPP format 1252 */ isCurrentFormat3gpp2()1253 static boolean isCurrentFormat3gpp2() { 1254 int activePhone = TelephonyManager.getDefault().getCurrentPhoneType(); 1255 return (PHONE_TYPE_CDMA == activePhone); 1256 } 1257 1258 /** 1259 * Handler for an {@link InboundSmsTracker} broadcast. Deletes PDUs from the raw table and 1260 * logs the broadcast duration (as an error if the other receivers were especially slow). 1261 */ 1262 private final class SmsBroadcastReceiver extends BroadcastReceiver { 1263 private final String mDeleteWhere; 1264 private final String[] mDeleteWhereArgs; 1265 private long mBroadcastTimeNano; 1266 SmsBroadcastReceiver(InboundSmsTracker tracker)1267 SmsBroadcastReceiver(InboundSmsTracker tracker) { 1268 mDeleteWhere = tracker.getDeleteWhere(); 1269 mDeleteWhereArgs = tracker.getDeleteWhereArgs(); 1270 mBroadcastTimeNano = System.nanoTime(); 1271 } 1272 1273 @Override onReceive(Context context, Intent intent)1274 public void onReceive(Context context, Intent intent) { 1275 String action = intent.getAction(); 1276 if (action.equals(Intents.SMS_DELIVER_ACTION)) { 1277 // Now dispatch the notification only intent 1278 intent.setAction(Intents.SMS_RECEIVED_ACTION); 1279 intent.setComponent(null); 1280 // All running users will be notified of the received sms. 1281 Bundle options = handleSmsWhitelisting(null); 1282 dispatchIntent(intent, android.Manifest.permission.RECEIVE_SMS, 1283 AppOpsManager.OP_RECEIVE_SMS, options, this, UserHandle.ALL); 1284 } else if (action.equals(Intents.WAP_PUSH_DELIVER_ACTION)) { 1285 // Now dispatch the notification only intent 1286 intent.setAction(Intents.WAP_PUSH_RECEIVED_ACTION); 1287 intent.setComponent(null); 1288 // Only the primary user will receive notification of incoming mms. 1289 // That app will do the actual downloading of the mms. 1290 Bundle options = null; 1291 try { 1292 long duration = mDeviceIdleController.addPowerSaveTempWhitelistAppForMms( 1293 mContext.getPackageName(), 0, "mms-broadcast"); 1294 BroadcastOptions bopts = BroadcastOptions.makeBasic(); 1295 bopts.setTemporaryAppWhitelistDuration(duration); 1296 options = bopts.toBundle(); 1297 } catch (RemoteException e) { 1298 } 1299 1300 String mimeType = intent.getType(); 1301 dispatchIntent(intent, WapPushOverSms.getPermissionForType(mimeType), 1302 WapPushOverSms.getAppOpsPermissionForIntent(mimeType), options, this, 1303 UserHandle.SYSTEM); 1304 } else { 1305 // Now that the intents have been deleted we can clean up the PDU data. 1306 if (!Intents.DATA_SMS_RECEIVED_ACTION.equals(action) 1307 && !Intents.SMS_RECEIVED_ACTION.equals(action) 1308 && !Intents.DATA_SMS_RECEIVED_ACTION.equals(action) 1309 && !Intents.WAP_PUSH_RECEIVED_ACTION.equals(action)) { 1310 loge("unexpected BroadcastReceiver action: " + action); 1311 } 1312 1313 int rc = getResultCode(); 1314 if ((rc != Activity.RESULT_OK) && (rc != Intents.RESULT_SMS_HANDLED)) { 1315 loge("a broadcast receiver set the result code to " + rc 1316 + ", deleting from raw table anyway!"); 1317 } else if (DBG) { 1318 log("successful broadcast, deleting from raw table."); 1319 } 1320 1321 deleteFromRawTable(mDeleteWhere, mDeleteWhereArgs, MARK_DELETED); 1322 sendMessage(EVENT_BROADCAST_COMPLETE); 1323 1324 int durationMillis = (int) ((System.nanoTime() - mBroadcastTimeNano) / 1000000); 1325 if (durationMillis >= 5000) { 1326 loge("Slow ordered broadcast completion time: " + durationMillis + " ms"); 1327 } else if (DBG) { 1328 log("ordered broadcast completed in: " + durationMillis + " ms"); 1329 } 1330 } 1331 } 1332 } 1333 1334 /** 1335 * Asynchronously binds to the carrier messaging service, and filters out the message if 1336 * instructed to do so by the carrier messaging service. A new instance must be used for every 1337 * message. 1338 */ 1339 private final class CarrierSmsFilter extends CarrierMessagingServiceManager { 1340 private final byte[][] mPdus; 1341 private final int mDestPort; 1342 private final String mSmsFormat; 1343 private final SmsBroadcastReceiver mSmsBroadcastReceiver; 1344 // Instantiated in filterSms. 1345 private volatile CarrierSmsFilterCallback mSmsFilterCallback; 1346 CarrierSmsFilter(byte[][] pdus, int destPort, String smsFormat, SmsBroadcastReceiver smsBroadcastReceiver)1347 CarrierSmsFilter(byte[][] pdus, int destPort, String smsFormat, 1348 SmsBroadcastReceiver smsBroadcastReceiver) { 1349 mPdus = pdus; 1350 mDestPort = destPort; 1351 mSmsFormat = smsFormat; 1352 mSmsBroadcastReceiver = smsBroadcastReceiver; 1353 } 1354 1355 /** 1356 * Attempts to bind to a {@link ICarrierMessagingService}. Filtering is initiated 1357 * asynchronously once the service is ready using {@link #onServiceReady}. 1358 */ filterSms(String carrierPackageName, CarrierSmsFilterCallback smsFilterCallback)1359 void filterSms(String carrierPackageName, CarrierSmsFilterCallback smsFilterCallback) { 1360 mSmsFilterCallback = smsFilterCallback; 1361 if (!bindToCarrierMessagingService(mContext, carrierPackageName)) { 1362 loge("bindService() for carrier messaging service failed"); 1363 smsFilterCallback.onFilterComplete(CarrierMessagingService.RECEIVE_OPTIONS_DEFAULT); 1364 } else { 1365 logv("bindService() for carrier messaging service succeeded"); 1366 } 1367 } 1368 1369 /** 1370 * Invokes the {@code carrierMessagingService} to filter messages. The filtering result is 1371 * delivered to {@code smsFilterCallback}. 1372 */ 1373 @Override onServiceReady(ICarrierMessagingService carrierMessagingService)1374 protected void onServiceReady(ICarrierMessagingService carrierMessagingService) { 1375 try { 1376 carrierMessagingService.filterSms( 1377 new MessagePdu(Arrays.asList(mPdus)), mSmsFormat, mDestPort, 1378 mPhone.getSubId(), mSmsFilterCallback); 1379 } catch (RemoteException e) { 1380 loge("Exception filtering the SMS: " + e); 1381 mSmsFilterCallback.onFilterComplete( 1382 CarrierMessagingService.RECEIVE_OPTIONS_DEFAULT); 1383 } 1384 } 1385 } 1386 1387 /** 1388 * A callback used to notify the platform of the carrier messaging app filtering result. Once 1389 * the result is ready, the carrier messaging service connection is disposed. 1390 */ 1391 private final class CarrierSmsFilterCallback extends ICarrierMessagingCallback.Stub { 1392 private final CarrierSmsFilter mSmsFilter; 1393 private final boolean mUserUnlocked; 1394 CarrierSmsFilterCallback(CarrierSmsFilter smsFilter, boolean userUnlocked)1395 CarrierSmsFilterCallback(CarrierSmsFilter smsFilter, boolean userUnlocked) { 1396 mSmsFilter = smsFilter; 1397 mUserUnlocked = userUnlocked; 1398 } 1399 1400 /** 1401 * This method should be called only once. 1402 */ 1403 @Override onFilterComplete(int result)1404 public void onFilterComplete(int result) { 1405 mSmsFilter.disposeConnection(mContext); 1406 // Calling identity was the CarrierMessagingService in this callback, change it back to 1407 // ours. This is required for dropSms() and VisualVoicemailSmsFilter.filter(). 1408 long token = Binder.clearCallingIdentity(); 1409 try { 1410 logv("onFilterComplete: result is " + result); 1411 if ((result & CarrierMessagingService.RECEIVE_OPTIONS_DROP) == 0) { 1412 if (VisualVoicemailSmsFilter.filter(mContext, mSmsFilter.mPdus, 1413 mSmsFilter.mSmsFormat, mSmsFilter.mDestPort, mPhone.getSubId())) { 1414 log("Visual voicemail SMS dropped"); 1415 dropSms(mSmsFilter.mSmsBroadcastReceiver); 1416 return; 1417 } 1418 1419 if (mUserUnlocked) { 1420 dispatchSmsDeliveryIntent(mSmsFilter.mPdus, mSmsFilter.mSmsFormat, 1421 mSmsFilter.mDestPort, mSmsFilter.mSmsBroadcastReceiver); 1422 } else { 1423 // Don't do anything further, leave the message in the raw table if the 1424 // credential-encrypted storage is still locked and show the new message 1425 // notification if the message is visible to the user. 1426 if (!isSkipNotifyFlagSet(result)) { 1427 showNewMessageNotification(); 1428 } 1429 sendMessage(EVENT_BROADCAST_COMPLETE); 1430 } 1431 } else { 1432 // Drop this SMS. 1433 dropSms(mSmsFilter.mSmsBroadcastReceiver); 1434 } 1435 } finally { 1436 // return back to the CarrierMessagingService, restore the calling identity. 1437 Binder.restoreCallingIdentity(token); 1438 } 1439 } 1440 1441 @Override onSendSmsComplete(int result, int messageRef)1442 public void onSendSmsComplete(int result, int messageRef) { 1443 loge("Unexpected onSendSmsComplete call with result: " + result); 1444 } 1445 1446 @Override onSendMultipartSmsComplete(int result, int[] messageRefs)1447 public void onSendMultipartSmsComplete(int result, int[] messageRefs) { 1448 loge("Unexpected onSendMultipartSmsComplete call with result: " + result); 1449 } 1450 1451 @Override onSendMmsComplete(int result, byte[] sendConfPdu)1452 public void onSendMmsComplete(int result, byte[] sendConfPdu) { 1453 loge("Unexpected onSendMmsComplete call with result: " + result); 1454 } 1455 1456 @Override onDownloadMmsComplete(int result)1457 public void onDownloadMmsComplete(int result) { 1458 loge("Unexpected onDownloadMmsComplete call with result: " + result); 1459 } 1460 } 1461 dropSms(SmsBroadcastReceiver receiver)1462 private void dropSms(SmsBroadcastReceiver receiver) { 1463 // Needs phone package permissions. 1464 deleteFromRawTable(receiver.mDeleteWhere, receiver.mDeleteWhereArgs, MARK_DELETED); 1465 sendMessage(EVENT_BROADCAST_COMPLETE); 1466 } 1467 1468 /** Checks whether the flag to skip new message notification is set in the bitmask returned 1469 * from the carrier app. 1470 */ isSkipNotifyFlagSet(int callbackResult)1471 private boolean isSkipNotifyFlagSet(int callbackResult) { 1472 return (callbackResult 1473 & RECEIVE_OPTIONS_SKIP_NOTIFY_WHEN_CREDENTIAL_PROTECTED_STORAGE_UNAVAILABLE) > 0; 1474 } 1475 1476 /** 1477 * Log with debug level. 1478 * @param s the string to log 1479 */ 1480 @Override log(String s)1481 protected void log(String s) { 1482 Rlog.d(getName(), s); 1483 } 1484 1485 /** 1486 * Log with error level. 1487 * @param s the string to log 1488 */ 1489 @Override loge(String s)1490 protected void loge(String s) { 1491 Rlog.e(getName(), s); 1492 } 1493 1494 /** 1495 * Log with error level. 1496 * @param s the string to log 1497 * @param e is a Throwable which logs additional information. 1498 */ 1499 @Override loge(String s, Throwable e)1500 protected void loge(String s, Throwable e) { 1501 Rlog.e(getName(), s, e); 1502 } 1503 1504 /** 1505 * Store a received SMS into Telephony provider 1506 * 1507 * @param intent The intent containing the received SMS 1508 * @return The URI of written message 1509 */ writeInboxMessage(Intent intent)1510 private Uri writeInboxMessage(Intent intent) { 1511 final SmsMessage[] messages = Telephony.Sms.Intents.getMessagesFromIntent(intent); 1512 if (messages == null || messages.length < 1) { 1513 loge("Failed to parse SMS pdu"); 1514 return null; 1515 } 1516 // Sometimes, SmsMessage.mWrappedSmsMessage is null causing NPE when we access 1517 // the methods on it although the SmsMessage itself is not null. So do this check 1518 // before we do anything on the parsed SmsMessages. 1519 for (final SmsMessage sms : messages) { 1520 try { 1521 sms.getDisplayMessageBody(); 1522 } catch (NullPointerException e) { 1523 loge("NPE inside SmsMessage"); 1524 return null; 1525 } 1526 } 1527 final ContentValues values = parseSmsMessage(messages); 1528 final long identity = Binder.clearCallingIdentity(); 1529 try { 1530 return mContext.getContentResolver().insert(Telephony.Sms.Inbox.CONTENT_URI, values); 1531 } catch (Exception e) { 1532 loge("Failed to persist inbox message", e); 1533 } finally { 1534 Binder.restoreCallingIdentity(identity); 1535 } 1536 return null; 1537 } 1538 1539 /** 1540 * Convert SmsMessage[] into SMS database schema columns 1541 * 1542 * @param msgs The SmsMessage array of the received SMS 1543 * @return ContentValues representing the columns of parsed SMS 1544 */ parseSmsMessage(SmsMessage[] msgs)1545 private static ContentValues parseSmsMessage(SmsMessage[] msgs) { 1546 final SmsMessage sms = msgs[0]; 1547 final ContentValues values = new ContentValues(); 1548 values.put(Telephony.Sms.Inbox.ADDRESS, sms.getDisplayOriginatingAddress()); 1549 values.put(Telephony.Sms.Inbox.BODY, buildMessageBodyFromPdus(msgs)); 1550 values.put(Telephony.Sms.Inbox.DATE_SENT, sms.getTimestampMillis()); 1551 values.put(Telephony.Sms.Inbox.DATE, System.currentTimeMillis()); 1552 values.put(Telephony.Sms.Inbox.PROTOCOL, sms.getProtocolIdentifier()); 1553 values.put(Telephony.Sms.Inbox.SEEN, 0); 1554 values.put(Telephony.Sms.Inbox.READ, 0); 1555 final String subject = sms.getPseudoSubject(); 1556 if (!TextUtils.isEmpty(subject)) { 1557 values.put(Telephony.Sms.Inbox.SUBJECT, subject); 1558 } 1559 values.put(Telephony.Sms.Inbox.REPLY_PATH_PRESENT, sms.isReplyPathPresent() ? 1 : 0); 1560 values.put(Telephony.Sms.Inbox.SERVICE_CENTER, sms.getServiceCenterAddress()); 1561 return values; 1562 } 1563 1564 /** 1565 * Build up the SMS message body from the SmsMessage array of received SMS 1566 * 1567 * @param msgs The SmsMessage array of the received SMS 1568 * @return The text message body 1569 */ buildMessageBodyFromPdus(SmsMessage[] msgs)1570 private static String buildMessageBodyFromPdus(SmsMessage[] msgs) { 1571 if (msgs.length == 1) { 1572 // There is only one part, so grab the body directly. 1573 return replaceFormFeeds(msgs[0].getDisplayMessageBody()); 1574 } else { 1575 // Build up the body from the parts. 1576 StringBuilder body = new StringBuilder(); 1577 for (SmsMessage msg: msgs) { 1578 // getDisplayMessageBody() can NPE if mWrappedMessage inside is null. 1579 body.append(msg.getDisplayMessageBody()); 1580 } 1581 return replaceFormFeeds(body.toString()); 1582 } 1583 } 1584 1585 // Some providers send formfeeds in their messages. Convert those formfeeds to newlines. replaceFormFeeds(String s)1586 private static String replaceFormFeeds(String s) { 1587 return s == null ? "" : s.replace('\f', '\n'); 1588 } 1589 1590 @VisibleForTesting getWakeLock()1591 public PowerManager.WakeLock getWakeLock() { 1592 return mWakeLock; 1593 } 1594 1595 @VisibleForTesting getWakeLockTimeout()1596 public int getWakeLockTimeout() { 1597 return WAKELOCK_TIMEOUT; 1598 } 1599 } 1600