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