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