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