1 /* 2 * Copyright (C) 2013 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.internal.telephony; 18 19 import static android.os.PowerWhitelistManager.REASON_EVENT_MMS; 20 import static android.os.PowerWhitelistManager.REASON_EVENT_SMS; 21 import static android.os.PowerWhitelistManager.TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED; 22 import static android.provider.Telephony.Sms.Intents.RESULT_SMS_DATABASE_ERROR; 23 import static android.provider.Telephony.Sms.Intents.RESULT_SMS_DISPATCH_FAILURE; 24 import static android.provider.Telephony.Sms.Intents.RESULT_SMS_INVALID_URI; 25 import static android.provider.Telephony.Sms.Intents.RESULT_SMS_NULL_MESSAGE; 26 import static android.provider.Telephony.Sms.Intents.RESULT_SMS_NULL_PDU; 27 import static android.service.carrier.CarrierMessagingService.RECEIVE_OPTIONS_SKIP_NOTIFY_WHEN_CREDENTIAL_PROTECTED_STORAGE_UNAVAILABLE; 28 import static android.telephony.TelephonyManager.PHONE_TYPE_CDMA; 29 30 import android.annotation.IntDef; 31 import android.annotation.NonNull; 32 import android.annotation.Nullable; 33 import android.app.Activity; 34 import android.app.AppOpsManager; 35 import android.app.BroadcastOptions; 36 import android.app.Notification; 37 import android.app.NotificationManager; 38 import android.app.PendingIntent; 39 import android.compat.annotation.UnsupportedAppUsage; 40 import android.content.BroadcastReceiver; 41 import android.content.ComponentName; 42 import android.content.ContentResolver; 43 import android.content.ContentUris; 44 import android.content.ContentValues; 45 import android.content.Context; 46 import android.content.Intent; 47 import android.content.IntentFilter; 48 import android.content.pm.IPackageManager; 49 import android.content.pm.PackageManager; 50 import android.database.Cursor; 51 import android.database.SQLException; 52 import android.net.Uri; 53 import android.os.AsyncResult; 54 import android.os.Build; 55 import android.os.Bundle; 56 import android.os.Message; 57 import android.os.PowerManager; 58 import android.os.PowerWhitelistManager; 59 import android.os.RemoteException; 60 import android.os.ServiceManager; 61 import android.os.UserHandle; 62 import android.os.UserManager; 63 import android.os.storage.StorageManager; 64 import android.provider.Telephony; 65 import android.provider.Telephony.Sms.Intents; 66 import android.service.carrier.CarrierMessagingService; 67 import android.telephony.SmsMessage; 68 import android.telephony.SubscriptionManager; 69 import android.telephony.TelephonyManager; 70 import android.util.LocalLog; 71 import android.util.Pair; 72 73 import com.android.internal.R; 74 import com.android.internal.annotations.VisibleForTesting; 75 import com.android.internal.telephony.SmsConstants.MessageClass; 76 import com.android.internal.telephony.metrics.TelephonyMetrics; 77 import com.android.internal.telephony.util.NotificationChannelController; 78 import com.android.internal.telephony.util.TelephonyUtils; 79 import com.android.internal.util.HexDump; 80 import com.android.internal.util.IndentingPrintWriter; 81 import com.android.internal.util.State; 82 import com.android.internal.util.StateMachine; 83 import com.android.telephony.Rlog; 84 85 import java.io.ByteArrayOutputStream; 86 import java.io.FileDescriptor; 87 import java.io.PrintWriter; 88 import java.lang.annotation.Retention; 89 import java.lang.annotation.RetentionPolicy; 90 import java.util.ArrayList; 91 import java.util.Arrays; 92 import java.util.HashMap; 93 import java.util.List; 94 import java.util.ListIterator; 95 import java.util.Map; 96 97 /** 98 * This class broadcasts incoming SMS messages to interested apps after storing them in the 99 * SmsProvider "raw" table and ACKing them to the SMSC. After each message has been broadcast, its 100 * parts are removed from the raw table. If the device crashes after ACKing but before the broadcast 101 * completes, the pending messages will be rebroadcast on the next boot. 102 * 103 * <p>The state machine starts in {@link IdleState} state. When we receive a new SMS from the radio, 104 * the wakelock is acquired, then transition to {@link DeliveringState} state, where the message is 105 * saved to the raw table, then acknowledged to the modem which in turn acknowledges it to the SMSC. 106 * 107 * <p>After saving the SMS, if the message is complete (either single-part or the final segment of a 108 * multi-part SMS), we broadcast the completed PDUs as an ordered broadcast, then transition to 109 * {@link WaitingState} state to wait for the broadcast to complete. When the local 110 * {@link BroadcastReceiver} is called with the result, it sends {@link #EVENT_BROADCAST_COMPLETE} 111 * to the state machine, causing us to either broadcast the next pending message (if one has arrived 112 * while waiting for the broadcast to complete), or to transition back to the halted state after all 113 * messages are processed. Then the wakelock is released and we wait for the next SMS. 114 */ 115 public abstract class InboundSmsHandler extends StateMachine { 116 protected static final boolean DBG = true; 117 protected static final boolean VDBG = false; // STOPSHIP if true, logs user data 118 119 /** Query projection for checking for duplicate message segments. */ 120 private static final String[] PDU_DELETED_FLAG_PROJECTION = { 121 "pdu", 122 "deleted" 123 }; 124 125 /** Mapping from DB COLUMN to PDU_SEQUENCE_PORT PROJECTION index */ 126 private static final Map<Integer, Integer> PDU_DELETED_FLAG_PROJECTION_INDEX_MAPPING = 127 new HashMap<Integer, Integer>() {{ 128 put(PDU_COLUMN, 0); 129 put(DELETED_FLAG_COLUMN, 1); 130 }}; 131 132 /** Query projection for combining concatenated message segments. */ 133 private static final String[] PDU_SEQUENCE_PORT_PROJECTION = { 134 "pdu", 135 "sequence", 136 "destination_port", 137 "display_originating_addr", 138 "date" 139 }; 140 141 /** Mapping from DB COLUMN to PDU_SEQUENCE_PORT PROJECTION index */ 142 private static final Map<Integer, Integer> PDU_SEQUENCE_PORT_PROJECTION_INDEX_MAPPING = 143 new HashMap<Integer, Integer>() {{ 144 put(PDU_COLUMN, 0); 145 put(SEQUENCE_COLUMN, 1); 146 put(DESTINATION_PORT_COLUMN, 2); 147 put(DISPLAY_ADDRESS_COLUMN, 3); 148 put(DATE_COLUMN, 4); 149 }}; 150 151 public static final int PDU_COLUMN = 0; 152 public static final int SEQUENCE_COLUMN = 1; 153 public static final int DESTINATION_PORT_COLUMN = 2; 154 public static final int DATE_COLUMN = 3; 155 public static final int REFERENCE_NUMBER_COLUMN = 4; 156 public static final int COUNT_COLUMN = 5; 157 public static final int ADDRESS_COLUMN = 6; 158 public static final int ID_COLUMN = 7; 159 public static final int MESSAGE_BODY_COLUMN = 8; 160 public static final int DISPLAY_ADDRESS_COLUMN = 9; 161 public static final int DELETED_FLAG_COLUMN = 10; 162 public static final int SUBID_COLUMN = 11; 163 164 public static final String SELECT_BY_ID = "_id=?"; 165 166 /** New SMS received as an AsyncResult. */ 167 public static final int EVENT_NEW_SMS = 1; 168 169 /** Message type containing a {@link InboundSmsTracker} ready to broadcast to listeners. */ 170 public static final int EVENT_BROADCAST_SMS = 2; 171 172 /** Message from resultReceiver notifying {@link WaitingState} of a completed broadcast. */ 173 public static final int EVENT_BROADCAST_COMPLETE = 3; 174 175 /** Sent on exit from {@link WaitingState} to return to idle after sending all broadcasts. */ 176 private static final int EVENT_RETURN_TO_IDLE = 4; 177 178 /** Release wakelock after {@link #mWakeLockTimeout} when returning to idle state. */ 179 private static final int EVENT_RELEASE_WAKELOCK = 5; 180 181 /** Sent by {@link SmsBroadcastUndelivered} after cleaning the raw table. */ 182 public static final int EVENT_START_ACCEPTING_SMS = 6; 183 184 /** New SMS received as an AsyncResult. */ 185 public static final int EVENT_INJECT_SMS = 7; 186 187 /** Update the sms tracker */ 188 public static final int EVENT_UPDATE_TRACKER = 8; 189 190 /** BroadcastReceiver timed out waiting for an intent */ 191 public static final int EVENT_RECEIVER_TIMEOUT = 9; 192 193 /** Wakelock release delay when returning to idle state. */ 194 private static final int WAKELOCK_TIMEOUT = 3000; 195 196 /** Received SMS was not injected. */ 197 public static final int SOURCE_NOT_INJECTED = 0; 198 199 /** Received SMS was received over IMS and injected. */ 200 public static final int SOURCE_INJECTED_FROM_IMS = 1; 201 202 /** Received SMS was injected from source different than IMS. */ 203 public static final int SOURCE_INJECTED_FROM_UNKNOWN = 2; 204 205 @Retention(RetentionPolicy.SOURCE) 206 @IntDef(prefix = {"SOURCE_"}, 207 value = { 208 SOURCE_NOT_INJECTED, 209 SOURCE_INJECTED_FROM_IMS, 210 SOURCE_INJECTED_FROM_UNKNOWN 211 }) 212 public @interface SmsSource {} 213 214 // The notitfication tag used when showing a notification. The combination of notification tag 215 // and notification id should be unique within the phone app. 216 @VisibleForTesting 217 public static final String NOTIFICATION_TAG = "InboundSmsHandler"; 218 @VisibleForTesting 219 public static final int NOTIFICATION_ID_NEW_MESSAGE = 1; 220 221 /** URI for raw table of SMS provider. */ 222 protected static final Uri sRawUri = Uri.withAppendedPath(Telephony.Sms.CONTENT_URI, "raw"); 223 protected static final Uri sRawUriPermanentDelete = 224 Uri.withAppendedPath(Telephony.Sms.CONTENT_URI, "raw/permanentDelete"); 225 226 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) 227 protected final Context mContext; 228 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) 229 private final ContentResolver mResolver; 230 231 /** Special handler for WAP push messages. */ 232 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) 233 private final WapPushOverSms mWapPush; 234 235 /** Wake lock to ensure device stays awake while dispatching the SMS intents. */ 236 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) 237 private final PowerManager.WakeLock mWakeLock; 238 239 /** DefaultState throws an exception or logs an error for unhandled message types. */ 240 private final DefaultState mDefaultState = new DefaultState(); 241 242 /** Startup state. Waiting for {@link SmsBroadcastUndelivered} to complete. */ 243 private final StartupState mStartupState = new StartupState(); 244 245 /** Idle state. Waiting for messages to process. */ 246 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) 247 private final IdleState mIdleState = new IdleState(); 248 249 /** Delivering state. Saves the PDU in the raw table and acknowledges to SMSC. */ 250 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) 251 private final DeliveringState mDeliveringState = new DeliveringState(); 252 253 /** Broadcasting state. Waits for current broadcast to complete before delivering next. */ 254 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) 255 private final WaitingState mWaitingState = new WaitingState(); 256 257 /** Helper class to check whether storage is available for incoming messages. */ 258 protected SmsStorageMonitor mStorageMonitor; 259 260 private final boolean mSmsReceiveDisabled; 261 262 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) 263 protected Phone mPhone; 264 265 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) 266 private UserManager mUserManager; 267 268 protected TelephonyMetrics mMetrics = TelephonyMetrics.getInstance(); 269 270 private LocalLog mLocalLog = new LocalLog(64); 271 private LocalLog mCarrierServiceLocalLog = new LocalLog(10); 272 273 PowerWhitelistManager mPowerWhitelistManager; 274 275 protected CellBroadcastServiceManager mCellBroadcastServiceManager; 276 277 // Delete permanently from raw table 278 private final int DELETE_PERMANENTLY = 1; 279 // Only mark deleted, but keep in db for message de-duping 280 private final int MARK_DELETED = 2; 281 282 private static String ACTION_OPEN_SMS_APP = 283 "com.android.internal.telephony.OPEN_DEFAULT_SMS_APP"; 284 285 /** Timeout for releasing wakelock */ 286 private int mWakeLockTimeout; 287 288 private List<SmsFilter> mSmsFilters; 289 290 /** 291 * Create a new SMS broadcast helper. 292 * @param name the class name for logging 293 * @param context the context of the phone app 294 * @param storageMonitor the SmsStorageMonitor to check for storage availability 295 */ InboundSmsHandler(String name, Context context, SmsStorageMonitor storageMonitor, Phone phone)296 protected InboundSmsHandler(String name, Context context, SmsStorageMonitor storageMonitor, 297 Phone phone) { 298 super(name); 299 300 mContext = context; 301 mStorageMonitor = storageMonitor; 302 mPhone = phone; 303 mResolver = context.getContentResolver(); 304 mWapPush = new WapPushOverSms(context); 305 306 boolean smsCapable = mContext.getResources().getBoolean( 307 com.android.internal.R.bool.config_sms_capable); 308 mSmsReceiveDisabled = !TelephonyManager.from(mContext).getSmsReceiveCapableForPhone( 309 mPhone.getPhoneId(), smsCapable); 310 311 PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE); 312 mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, name); 313 mWakeLock.acquire(); // wake lock released after we enter idle state 314 mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE); 315 mPowerWhitelistManager = 316 (PowerWhitelistManager) mContext.getSystemService(Context.POWER_WHITELIST_MANAGER); 317 mCellBroadcastServiceManager = new CellBroadcastServiceManager(context, phone); 318 319 mSmsFilters = createDefaultSmsFilters(); 320 321 addState(mDefaultState); 322 addState(mStartupState, mDefaultState); 323 addState(mIdleState, mDefaultState); 324 addState(mDeliveringState, mDefaultState); 325 addState(mWaitingState, mDeliveringState); 326 327 setInitialState(mStartupState); 328 if (DBG) log("created InboundSmsHandler"); 329 } 330 331 /** 332 * Tell the state machine to quit after processing all messages. 333 */ dispose()334 public void dispose() { 335 quit(); 336 } 337 338 /** 339 * Dispose of the WAP push object and release the wakelock. 340 */ 341 @Override onQuitting()342 protected void onQuitting() { 343 mWapPush.dispose(); 344 mCellBroadcastServiceManager.disable(); 345 346 while (mWakeLock.isHeld()) { 347 mWakeLock.release(); 348 } 349 } 350 351 // CAF_MSIM Is this used anywhere ? if not remove it 352 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) getPhone()353 public Phone getPhone() { 354 return mPhone; 355 } 356 357 @Override getWhatToString(int what)358 protected String getWhatToString(int what) { 359 String whatString; 360 switch (what) { 361 case EVENT_NEW_SMS: 362 whatString = "EVENT_NEW_SMS"; 363 break; 364 case EVENT_BROADCAST_SMS: 365 whatString = "EVENT_BROADCAST_SMS"; 366 break; 367 case EVENT_BROADCAST_COMPLETE: 368 whatString = "EVENT_BROADCAST_COMPLETE"; 369 break; 370 case EVENT_RETURN_TO_IDLE: 371 whatString = "EVENT_RETURN_TO_IDLE"; 372 break; 373 case EVENT_RELEASE_WAKELOCK: 374 whatString = "EVENT_RELEASE_WAKELOCK"; 375 break; 376 case EVENT_START_ACCEPTING_SMS: 377 whatString = "EVENT_START_ACCEPTING_SMS"; 378 break; 379 case EVENT_INJECT_SMS: 380 whatString = "EVENT_INJECT_SMS"; 381 break; 382 case EVENT_UPDATE_TRACKER: 383 whatString = "EVENT_UPDATE_TRACKER"; 384 break; 385 case EVENT_RECEIVER_TIMEOUT: 386 whatString = "EVENT_RECEIVER_TIMEOUT"; 387 break; 388 default: 389 whatString = "UNKNOWN EVENT " + what; 390 } 391 return whatString; 392 } 393 394 /** 395 * This parent state throws an exception (for debug builds) or prints an error for unhandled 396 * message types. 397 */ 398 private class DefaultState extends State { 399 @Override processMessage(Message msg)400 public boolean processMessage(Message msg) { 401 switch (msg.what) { 402 default: { 403 String errorText = "processMessage: unhandled message type " 404 + getWhatToString(msg.what) + " currState=" 405 + getCurrentState().getName(); 406 if (TelephonyUtils.IS_DEBUGGABLE) { 407 loge("---- Dumping InboundSmsHandler ----"); 408 loge("Total records=" + getLogRecCount()); 409 for (int i = Math.max(getLogRecSize() - 20, 0); i < getLogRecSize(); i++) { 410 // getLogRec(i).toString() will call the overridden getWhatToString 411 // method which has more information 412 loge("Rec[%d]: %s\n" + i + getLogRec(i).toString()); 413 } 414 loge("---- Dumped InboundSmsHandler ----"); 415 416 throw new RuntimeException(errorText); 417 } else { 418 loge(errorText); 419 } 420 break; 421 } 422 } 423 return HANDLED; 424 } 425 } 426 427 /** 428 * The Startup state waits for {@link SmsBroadcastUndelivered} to process the raw table and 429 * notify the state machine to broadcast any complete PDUs that might not have been broadcast. 430 */ 431 private class StartupState extends State { 432 @Override enter()433 public void enter() { 434 if (DBG) log("StartupState.enter: entering StartupState"); 435 // Set wakelock timeout to 0 during startup, this will ensure that the wakelock is not 436 // held if there are no pending messages to be handled. 437 setWakeLockTimeout(0); 438 } 439 440 @Override processMessage(Message msg)441 public boolean processMessage(Message msg) { 442 log("StartupState.processMessage: processing " + getWhatToString(msg.what)); 443 switch (msg.what) { 444 case EVENT_NEW_SMS: 445 case EVENT_INJECT_SMS: 446 case EVENT_BROADCAST_SMS: 447 deferMessage(msg); 448 return HANDLED; 449 450 case EVENT_START_ACCEPTING_SMS: 451 transitionTo(mIdleState); 452 return HANDLED; 453 454 case EVENT_BROADCAST_COMPLETE: 455 case EVENT_RETURN_TO_IDLE: 456 case EVENT_RELEASE_WAKELOCK: 457 default: 458 // let DefaultState handle these unexpected message types 459 return NOT_HANDLED; 460 } 461 } 462 } 463 464 /** 465 * In the idle state the wakelock is released until a new SM arrives, then we transition 466 * to Delivering mode to handle it, acquiring the wakelock on exit. 467 */ 468 private class IdleState extends State { 469 @Override enter()470 public void enter() { 471 if (DBG) log("IdleState.enter: entering IdleState"); 472 sendMessageDelayed(EVENT_RELEASE_WAKELOCK, getWakeLockTimeout()); 473 } 474 475 @Override exit()476 public void exit() { 477 mWakeLock.acquire(); 478 if (DBG) log("IdleState.exit: acquired wakelock, leaving IdleState"); 479 } 480 481 @Override processMessage(Message msg)482 public boolean processMessage(Message msg) { 483 if (DBG) log("IdleState.processMessage: processing " + getWhatToString(msg.what)); 484 switch (msg.what) { 485 case EVENT_NEW_SMS: 486 case EVENT_INJECT_SMS: 487 case EVENT_BROADCAST_SMS: 488 deferMessage(msg); 489 transitionTo(mDeliveringState); 490 return HANDLED; 491 492 case EVENT_RELEASE_WAKELOCK: 493 mWakeLock.release(); 494 if (DBG) { 495 if (mWakeLock.isHeld()) { 496 // this is okay as long as we call release() for every acquire() 497 log("IdleState.processMessage: EVENT_RELEASE_WAKELOCK: mWakeLock is " 498 + "still held after release"); 499 } else { 500 log("IdleState.processMessage: EVENT_RELEASE_WAKELOCK: mWakeLock " 501 + "released"); 502 } 503 } 504 return HANDLED; 505 506 case EVENT_RETURN_TO_IDLE: 507 // already in idle state; ignore 508 return HANDLED; 509 510 case EVENT_BROADCAST_COMPLETE: 511 case EVENT_START_ACCEPTING_SMS: 512 default: 513 // let DefaultState handle these unexpected message types 514 return NOT_HANDLED; 515 } 516 } 517 } 518 519 /** 520 * In the delivering state, the inbound SMS is processed and stored in the raw table. 521 * The message is acknowledged before we exit this state. If there is a message to broadcast, 522 * transition to {@link WaitingState} state to send the ordered broadcast and wait for the 523 * results. When all messages have been processed, the halting state will release the wakelock. 524 */ 525 private class DeliveringState extends State { 526 @Override enter()527 public void enter() { 528 if (DBG) log("DeliveringState.enter: entering DeliveringState"); 529 } 530 531 @Override exit()532 public void exit() { 533 if (DBG) log("DeliveringState.exit: leaving DeliveringState"); 534 } 535 536 @Override processMessage(Message msg)537 public boolean processMessage(Message msg) { 538 if (DBG) log("DeliveringState.processMessage: processing " + getWhatToString(msg.what)); 539 switch (msg.what) { 540 case EVENT_NEW_SMS: 541 // handle new SMS from RIL 542 handleNewSms((AsyncResult) msg.obj); 543 sendMessage(EVENT_RETURN_TO_IDLE); 544 return HANDLED; 545 546 case EVENT_INJECT_SMS: 547 // handle new injected SMS 548 handleInjectSms((AsyncResult) msg.obj, msg.arg1 == 1 /* isOverIms */); 549 sendMessage(EVENT_RETURN_TO_IDLE); 550 return HANDLED; 551 552 case EVENT_BROADCAST_SMS: 553 // if any broadcasts were sent, transition to waiting state 554 InboundSmsTracker inboundSmsTracker = (InboundSmsTracker) msg.obj; 555 if (processMessagePart(inboundSmsTracker)) { 556 sendMessage(obtainMessage(EVENT_UPDATE_TRACKER, msg.obj)); 557 transitionTo(mWaitingState); 558 } else { 559 // if event is sent from SmsBroadcastUndelivered.broadcastSms(), and 560 // processMessagePart() returns false, the state machine will be stuck in 561 // DeliveringState until next message is received. Send message to 562 // transition to idle to avoid that so that wakelock can be released 563 log("DeliveringState.processMessage: EVENT_BROADCAST_SMS: No broadcast " 564 + "sent. Return to IdleState"); 565 sendMessage(EVENT_RETURN_TO_IDLE); 566 } 567 return HANDLED; 568 569 case EVENT_RETURN_TO_IDLE: 570 // return to idle after processing all other messages 571 transitionTo(mIdleState); 572 return HANDLED; 573 574 case EVENT_RELEASE_WAKELOCK: 575 mWakeLock.release(); // decrement wakelock from previous entry to Idle 576 if (!mWakeLock.isHeld()) { 577 // wakelock should still be held until 3 seconds after we enter Idle 578 loge("mWakeLock released while delivering/broadcasting!"); 579 } 580 return HANDLED; 581 582 case EVENT_UPDATE_TRACKER: 583 logd("process tracker message in DeliveringState " + msg.arg1); 584 return HANDLED; 585 586 // we shouldn't get this message type in this state, log error and halt. 587 case EVENT_BROADCAST_COMPLETE: 588 case EVENT_START_ACCEPTING_SMS: 589 default: 590 logeWithLocalLog("Unhandled msg in delivering state, msg.what = " 591 + getWhatToString(msg.what)); 592 // let DefaultState handle these unexpected message types 593 return NOT_HANDLED; 594 } 595 } 596 } 597 598 /** 599 * The waiting state delegates handling of new SMS to parent {@link DeliveringState}, but 600 * defers handling of the {@link #EVENT_BROADCAST_SMS} phase until after the current 601 * result receiver sends {@link #EVENT_BROADCAST_COMPLETE}. Before transitioning to 602 * {@link DeliveringState}, {@link #EVENT_RETURN_TO_IDLE} is sent to transition to 603 * {@link IdleState} after any deferred {@link #EVENT_BROADCAST_SMS} messages are handled. 604 */ 605 private class WaitingState extends State { 606 607 private InboundSmsTracker mLastDeliveredSmsTracker; 608 609 @Override enter()610 public void enter() { 611 if (DBG) log("WaitingState.enter: entering WaitingState"); 612 } 613 614 @Override exit()615 public void exit() { 616 if (DBG) log("WaitingState.exit: leaving WaitingState"); 617 // Before moving to idle state, set wakelock timeout to WAKE_LOCK_TIMEOUT milliseconds 618 // to give any receivers time to take their own wake locks 619 setWakeLockTimeout(WAKELOCK_TIMEOUT); 620 mPhone.getIccSmsInterfaceManager().mDispatchersController.sendEmptyMessage( 621 SmsDispatchersController.EVENT_SMS_HANDLER_EXITING_WAITING_STATE); 622 } 623 624 @Override processMessage(Message msg)625 public boolean processMessage(Message msg) { 626 if (DBG) log("WaitingState.processMessage: processing " + getWhatToString(msg.what)); 627 switch (msg.what) { 628 case EVENT_BROADCAST_SMS: 629 // defer until the current broadcast completes 630 if (mLastDeliveredSmsTracker != null) { 631 String str = "Defer sms broadcast due to undelivered sms, " 632 + " messageCount = " + mLastDeliveredSmsTracker.getMessageCount() 633 + " destPort = " + mLastDeliveredSmsTracker.getDestPort() 634 + " timestamp = " + mLastDeliveredSmsTracker.getTimestamp() 635 + " currentTimestamp = " + System.currentTimeMillis(); 636 logWithLocalLog(str, mLastDeliveredSmsTracker.getMessageId()); 637 } 638 deferMessage(msg); 639 return HANDLED; 640 641 case EVENT_RECEIVER_TIMEOUT: 642 logeWithLocalLog("WaitingState.processMessage: received " 643 + "EVENT_RECEIVER_TIMEOUT"); 644 if (mLastDeliveredSmsTracker != null) { 645 mLastDeliveredSmsTracker.getSmsBroadcastReceiver(InboundSmsHandler.this) 646 .fakeNextAction(); 647 } 648 return HANDLED; 649 650 case EVENT_BROADCAST_COMPLETE: 651 mLastDeliveredSmsTracker = null; 652 // return to idle after handling all deferred messages 653 sendMessage(EVENT_RETURN_TO_IDLE); 654 transitionTo(mDeliveringState); 655 return HANDLED; 656 657 case EVENT_RETURN_TO_IDLE: 658 // not ready to return to idle; ignore 659 return HANDLED; 660 661 case EVENT_UPDATE_TRACKER: 662 mLastDeliveredSmsTracker = (InboundSmsTracker) msg.obj; 663 return HANDLED; 664 665 default: 666 // parent state handles the other message types 667 return NOT_HANDLED; 668 } 669 } 670 } 671 672 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) handleNewSms(AsyncResult ar)673 private void handleNewSms(AsyncResult ar) { 674 if (ar.exception != null) { 675 loge("Exception processing incoming SMS: " + ar.exception); 676 return; 677 } 678 679 int result; 680 try { 681 SmsMessage sms = (SmsMessage) ar.result; 682 result = dispatchMessage(sms.mWrappedSmsMessage, SOURCE_NOT_INJECTED); 683 } catch (RuntimeException ex) { 684 loge("Exception dispatching message", ex); 685 result = RESULT_SMS_DISPATCH_FAILURE; 686 } 687 688 // RESULT_OK means that the SMS will be acknowledged by special handling, 689 // e.g. for SMS-PP data download. Any other result, we should ack here. 690 if (result != Activity.RESULT_OK) { 691 boolean handled = (result == Intents.RESULT_SMS_HANDLED); 692 notifyAndAcknowledgeLastIncomingSms(handled, result, null); 693 } 694 } 695 696 /** 697 * This method is called when a new SMS PDU is injected into application framework. 698 * @param ar is the AsyncResult that has the SMS PDU to be injected. 699 */ 700 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) handleInjectSms(AsyncResult ar, boolean isOverIms)701 private void handleInjectSms(AsyncResult ar, boolean isOverIms) { 702 int result; 703 SmsDispatchersController.SmsInjectionCallback callback = null; 704 try { 705 callback = (SmsDispatchersController.SmsInjectionCallback) ar.userObj; 706 SmsMessage sms = (SmsMessage) ar.result; 707 if (sms == null) { 708 loge("Null injected sms"); 709 result = RESULT_SMS_NULL_PDU; 710 } else { 711 @SmsSource int smsSource = 712 isOverIms ? SOURCE_INJECTED_FROM_IMS : SOURCE_INJECTED_FROM_UNKNOWN; 713 result = dispatchMessage(sms.mWrappedSmsMessage, smsSource); 714 } 715 } catch (RuntimeException ex) { 716 loge("Exception dispatching message", ex); 717 result = RESULT_SMS_DISPATCH_FAILURE; 718 } 719 720 if (callback != null) { 721 callback.onSmsInjectedResult(result); 722 } 723 } 724 725 /** 726 * Process an SMS message from the RIL, calling subclass methods to handle 3GPP and 727 * 3GPP2-specific message types. 728 * 729 * @param smsb the SmsMessageBase object from the RIL 730 * @param smsSource the source of the SMS message 731 * @return a result code from {@link android.provider.Telephony.Sms.Intents}, 732 * or {@link Activity#RESULT_OK} for delayed acknowledgment to SMSC 733 */ dispatchMessage(SmsMessageBase smsb, @SmsSource int smsSource)734 private int dispatchMessage(SmsMessageBase smsb, @SmsSource int smsSource) { 735 // If sms is null, there was a parsing error. 736 if (smsb == null) { 737 loge("dispatchSmsMessage: message is null"); 738 return RESULT_SMS_NULL_MESSAGE; 739 } 740 741 if (mSmsReceiveDisabled) { 742 // Device doesn't support receiving SMS, 743 log("Received short message on device which doesn't support " 744 + "receiving SMS. Ignored."); 745 return Intents.RESULT_SMS_HANDLED; 746 } 747 748 // onlyCore indicates if the device is in cryptkeeper 749 boolean onlyCore = false; 750 try { 751 onlyCore = IPackageManager.Stub.asInterface(ServiceManager.getService("package")) 752 .isOnlyCoreApps(); 753 } catch (RemoteException e) { 754 } 755 if (onlyCore) { 756 // Device is unable to receive SMS in encrypted state 757 log("Received a short message in encrypted state. Rejecting."); 758 return Intents.RESULT_SMS_RECEIVED_WHILE_ENCRYPTED; 759 } 760 761 int result = dispatchMessageRadioSpecific(smsb, smsSource); 762 763 // In case of error, add to metrics. This is not required in case of success, as the 764 // data will be tracked when the message is processed (processMessagePart). 765 if (result != Intents.RESULT_SMS_HANDLED && result != Activity.RESULT_OK) { 766 mMetrics.writeIncomingSmsError(mPhone.getPhoneId(), is3gpp2(), smsSource, result); 767 mPhone.getSmsStats().onIncomingSmsError(is3gpp2(), smsSource, result); 768 } 769 return result; 770 } 771 772 /** 773 * Process voicemail notification, SMS-PP data download, CDMA CMAS, CDMA WAP push, and other 774 * 3GPP/3GPP2-specific messages. Regular SMS messages are handled by calling the shared 775 * {@link #dispatchNormalMessage} from this class. 776 * 777 * @param smsb the SmsMessageBase object from the RIL 778 * @param smsSource the source of the SMS message 779 * @return a result code from {@link android.provider.Telephony.Sms.Intents}, 780 * or {@link Activity#RESULT_OK} for delayed acknowledgment to SMSC 781 */ dispatchMessageRadioSpecific(SmsMessageBase smsb, @SmsSource int smsSource)782 protected abstract int dispatchMessageRadioSpecific(SmsMessageBase smsb, 783 @SmsSource int smsSource); 784 785 /** 786 * Send an acknowledge message to the SMSC. 787 * @param success indicates that last message was successfully received. 788 * @param result result code indicating any error 789 * @param response callback message sent when operation completes. 790 */ 791 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) acknowledgeLastIncomingSms(boolean success, int result, Message response)792 protected abstract void acknowledgeLastIncomingSms(boolean success, 793 int result, Message response); 794 795 /** 796 * Notify interested apps if the framework has rejected an incoming SMS, 797 * and send an acknowledge message to the network. 798 * @param success indicates that last message was successfully received. 799 * @param result result code indicating any error 800 * @param response callback message sent when operation completes. 801 */ notifyAndAcknowledgeLastIncomingSms(boolean success, int result, Message response)802 private void notifyAndAcknowledgeLastIncomingSms(boolean success, 803 int result, Message response) { 804 if (!success) { 805 // broadcast SMS_REJECTED_ACTION intent 806 Intent intent = new Intent(Intents.SMS_REJECTED_ACTION); 807 intent.putExtra("result", result); 808 intent.putExtra("subId", mPhone.getSubId()); 809 mContext.sendBroadcast(intent, android.Manifest.permission.RECEIVE_SMS); 810 } 811 acknowledgeLastIncomingSms(success, result, response); 812 } 813 814 /** 815 * Return true if this handler is for 3GPP2 messages; false for 3GPP format. 816 * @return true for the 3GPP2 handler; false for the 3GPP handler 817 */ is3gpp2()818 protected abstract boolean is3gpp2(); 819 820 /** 821 * Dispatch a normal incoming SMS. This is called from {@link #dispatchMessageRadioSpecific} 822 * if no format-specific handling was required. Saves the PDU to the SMS provider raw table, 823 * creates an {@link InboundSmsTracker}, then sends it to the state machine as an 824 * {@link #EVENT_BROADCAST_SMS}. Returns {@link Intents#RESULT_SMS_HANDLED} or an error value. 825 * 826 * @param sms the message to dispatch 827 * @param smsSource the source of the SMS message 828 * @return {@link Intents#RESULT_SMS_HANDLED} if the message was accepted, or an error status 829 */ 830 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) dispatchNormalMessage(SmsMessageBase sms, @SmsSource int smsSource)831 protected int dispatchNormalMessage(SmsMessageBase sms, @SmsSource int smsSource) { 832 SmsHeader smsHeader = sms.getUserDataHeader(); 833 InboundSmsTracker tracker; 834 835 if ((smsHeader == null) || (smsHeader.concatRef == null)) { 836 // Message is not concatenated. 837 int destPort = -1; 838 if (smsHeader != null && smsHeader.portAddrs != null) { 839 // The message was sent to a port. 840 destPort = smsHeader.portAddrs.destPort; 841 if (DBG) log("destination port: " + destPort); 842 } 843 tracker = TelephonyComponentFactory.getInstance() 844 .inject(InboundSmsTracker.class.getName()) 845 .makeInboundSmsTracker(mContext, sms.getPdu(), 846 sms.getTimestampMillis(), destPort, is3gpp2(), false, 847 sms.getOriginatingAddress(), sms.getDisplayOriginatingAddress(), 848 sms.getMessageBody(), sms.getMessageClass() == MessageClass.CLASS_0, 849 mPhone.getSubId(), smsSource); 850 } else { 851 // Create a tracker for this message segment. 852 SmsHeader.ConcatRef concatRef = smsHeader.concatRef; 853 SmsHeader.PortAddrs portAddrs = smsHeader.portAddrs; 854 int destPort = (portAddrs != null ? portAddrs.destPort : -1); 855 tracker = TelephonyComponentFactory.getInstance() 856 .inject(InboundSmsTracker.class.getName()) 857 .makeInboundSmsTracker(mContext, sms.getPdu(), 858 sms.getTimestampMillis(), destPort, is3gpp2(), 859 sms.getOriginatingAddress(), sms.getDisplayOriginatingAddress(), 860 concatRef.refNumber, concatRef.seqNumber, concatRef.msgCount, false, 861 sms.getMessageBody(), sms.getMessageClass() == MessageClass.CLASS_0, 862 mPhone.getSubId(), smsSource); 863 } 864 865 if (VDBG) log("created tracker: " + tracker); 866 867 // de-duping is done only for text messages 868 // destPort = -1 indicates text messages, otherwise it's a data sms 869 return addTrackerToRawTableAndSendMessage(tracker, 870 tracker.getDestPort() == -1 /* de-dup if text message */); 871 } 872 873 /** 874 * Helper to add the tracker to the raw table and then send a message to broadcast it, if 875 * successful. Returns the SMS intent status to return to the SMSC. 876 * @param tracker the tracker to save to the raw table and then deliver 877 * @return {@link Intents#RESULT_SMS_HANDLED} or one of these errors:<br> 878 * <code>RESULT_SMS_UNSUPPORTED</code><br> 879 * <code>RESULT_SMS_DUPLICATED</code><br> 880 * <code>RESULT_SMS_DISPATCH_FAILURE</code><br> 881 * <code>RESULT_SMS_NULL_PDU</code><br> 882 * <code>RESULT_SMS_NULL_MESSAGE</code><br> 883 * <code>RESULT_SMS_RECEIVED_WHILE_ENCRYPTED</code><br> 884 * <code>RESULT_SMS_DATABASE_ERROR</code><br> 885 * <code>RESULT_SMS_INVALID_URI</code><br> 886 */ addTrackerToRawTableAndSendMessage(InboundSmsTracker tracker, boolean deDup)887 protected int addTrackerToRawTableAndSendMessage(InboundSmsTracker tracker, boolean deDup) { 888 int result = addTrackerToRawTable(tracker, deDup); 889 switch(result) { 890 case Intents.RESULT_SMS_HANDLED: 891 sendMessage(EVENT_BROADCAST_SMS, tracker); 892 return Intents.RESULT_SMS_HANDLED; 893 894 case Intents.RESULT_SMS_DUPLICATED: 895 return Intents.RESULT_SMS_HANDLED; 896 897 default: 898 return result; 899 } 900 } 901 902 /** 903 * Process the inbound SMS segment. If the message is complete, send it as an ordered 904 * broadcast to interested receivers and return true. If the message is a segment of an 905 * incomplete multi-part SMS, return false. 906 * @param tracker the tracker containing the message segment to process 907 * @return true if an ordered broadcast was sent; false if waiting for more message segments 908 */ 909 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) processMessagePart(InboundSmsTracker tracker)910 private boolean processMessagePart(InboundSmsTracker tracker) { 911 int messageCount = tracker.getMessageCount(); 912 byte[][] pdus; 913 long[] timestamps; 914 int destPort = tracker.getDestPort(); 915 boolean block = false; 916 String address = tracker.getAddress(); 917 918 // Do not process when the message count is invalid. 919 if (messageCount <= 0) { 920 loge("processMessagePart: returning false due to invalid message count " 921 + messageCount, tracker.getMessageId()); 922 return false; 923 } 924 925 if (messageCount == 1) { 926 // single-part message 927 pdus = new byte[][]{tracker.getPdu()}; 928 timestamps = new long[]{tracker.getTimestamp()}; 929 block = BlockChecker.isBlocked(mContext, tracker.getDisplayAddress(), null); 930 } else { 931 // multi-part message 932 Cursor cursor = null; 933 try { 934 // used by several query selection arguments 935 String refNumber = Integer.toString(tracker.getReferenceNumber()); 936 String count = Integer.toString(tracker.getMessageCount()); 937 938 // query for all segments and broadcast message if we have all the parts 939 String[] whereArgs = {address, refNumber, count}; 940 cursor = mResolver.query(sRawUri, PDU_SEQUENCE_PORT_PROJECTION, 941 tracker.getQueryForSegments(), whereArgs, null); 942 943 int cursorCount = cursor.getCount(); 944 if (cursorCount < messageCount) { 945 // Wait for the other message parts to arrive. It's also possible for the last 946 // segment to arrive before processing the EVENT_BROADCAST_SMS for one of the 947 // earlier segments. In that case, the broadcast will be sent as soon as all 948 // segments are in the table, and any later EVENT_BROADCAST_SMS messages will 949 // get a row count of 0 and return. 950 log("processMessagePart: returning false. Only " + cursorCount + " of " 951 + messageCount + " segments " + " have arrived. refNumber: " 952 + refNumber, tracker.getMessageId()); 953 return false; 954 } 955 956 // All the parts are in place, deal with them 957 pdus = new byte[messageCount][]; 958 timestamps = new long[messageCount]; 959 while (cursor.moveToNext()) { 960 // subtract offset to convert sequence to 0-based array index 961 int index = cursor.getInt(PDU_SEQUENCE_PORT_PROJECTION_INDEX_MAPPING 962 .get(SEQUENCE_COLUMN)) - tracker.getIndexOffset(); 963 964 // The invalid PDUs can be received and stored in the raw table. The range 965 // check ensures the process not crash even if the seqNumber in the 966 // UserDataHeader is invalid. 967 if (index >= pdus.length || index < 0) { 968 loge(String.format( 969 "processMessagePart: invalid seqNumber = %d, messageCount = %d", 970 index + tracker.getIndexOffset(), 971 messageCount), 972 tracker.getMessageId()); 973 continue; 974 } 975 976 pdus[index] = HexDump.hexStringToByteArray(cursor.getString( 977 PDU_SEQUENCE_PORT_PROJECTION_INDEX_MAPPING.get(PDU_COLUMN))); 978 979 // Read the destination port from the first segment (needed for CDMA WAP PDU). 980 // It's not a bad idea to prefer the port from the first segment in other cases. 981 if (index == 0 && !cursor.isNull(PDU_SEQUENCE_PORT_PROJECTION_INDEX_MAPPING 982 .get(DESTINATION_PORT_COLUMN))) { 983 int port = cursor.getInt(PDU_SEQUENCE_PORT_PROJECTION_INDEX_MAPPING 984 .get(DESTINATION_PORT_COLUMN)); 985 // strip format flags and convert to real port number, or -1 986 port = InboundSmsTracker.getRealDestPort(port); 987 if (port != -1) { 988 destPort = port; 989 } 990 } 991 992 timestamps[index] = cursor.getLong( 993 PDU_SEQUENCE_PORT_PROJECTION_INDEX_MAPPING.get(DATE_COLUMN)); 994 995 // check if display address should be blocked or not 996 if (!block) { 997 // Depending on the nature of the gateway, the display origination address 998 // is either derived from the content of the SMS TP-OA field, or the TP-OA 999 // field contains a generic gateway address and the from address is added 1000 // at the beginning in the message body. In that case only the first SMS 1001 // (part of Multi-SMS) comes with the display originating address which 1002 // could be used for block checking purpose. 1003 block = BlockChecker.isBlocked(mContext, 1004 cursor.getString(PDU_SEQUENCE_PORT_PROJECTION_INDEX_MAPPING 1005 .get(DISPLAY_ADDRESS_COLUMN)), null); 1006 } 1007 } 1008 log("processMessagePart: all " + messageCount + " segments " 1009 + " received. refNumber: " + refNumber, tracker.getMessageId()); 1010 } catch (SQLException e) { 1011 loge("processMessagePart: Can't access multipart SMS database, " 1012 + SmsController.formatCrossStackMessageId(tracker.getMessageId()), e); 1013 return false; 1014 } finally { 1015 if (cursor != null) { 1016 cursor.close(); 1017 } 1018 } 1019 } 1020 1021 final boolean isWapPush = (destPort == SmsHeader.PORT_WAP_PUSH); 1022 String format = tracker.getFormat(); 1023 1024 // Do not process null pdu(s). Check for that and return false in that case. 1025 List<byte[]> pduList = Arrays.asList(pdus); 1026 if (pduList.size() == 0 || pduList.contains(null)) { 1027 String errorMsg = "processMessagePart: returning false due to " 1028 + (pduList.size() == 0 ? "pduList.size() == 0" : "pduList.contains(null)"); 1029 logeWithLocalLog(errorMsg, tracker.getMessageId()); 1030 mPhone.getSmsStats().onIncomingSmsError( 1031 is3gpp2(), tracker.getSource(), RESULT_SMS_NULL_PDU); 1032 return false; 1033 } 1034 1035 ByteArrayOutputStream output = new ByteArrayOutputStream(); 1036 if (isWapPush) { 1037 for (byte[] pdu : pdus) { 1038 // 3GPP needs to extract the User Data from the PDU; 3GPP2 has already done this 1039 if (format == SmsConstants.FORMAT_3GPP) { 1040 SmsMessage msg = SmsMessage.createFromPdu(pdu, SmsConstants.FORMAT_3GPP); 1041 if (msg != null) { 1042 pdu = msg.getUserData(); 1043 } else { 1044 loge("processMessagePart: SmsMessage.createFromPdu returned null", 1045 tracker.getMessageId()); 1046 mMetrics.writeIncomingWapPush(mPhone.getPhoneId(), tracker.getSource(), 1047 SmsConstants.FORMAT_3GPP, timestamps, false, 1048 tracker.getMessageId()); 1049 mPhone.getSmsStats().onIncomingSmsWapPush(tracker.getSource(), 1050 messageCount, RESULT_SMS_NULL_MESSAGE, tracker.getMessageId()); 1051 return false; 1052 } 1053 } 1054 output.write(pdu, 0, pdu.length); 1055 } 1056 } 1057 1058 SmsBroadcastReceiver resultReceiver = tracker.getSmsBroadcastReceiver(this); 1059 1060 if (!mUserManager.isUserUnlocked()) { 1061 log("processMessagePart: !isUserUnlocked; calling processMessagePartWithUserLocked. " 1062 + "Port: " + destPort, tracker.getMessageId()); 1063 return processMessagePartWithUserLocked( 1064 tracker, 1065 (isWapPush ? new byte[][] {output.toByteArray()} : pdus), 1066 destPort, 1067 resultReceiver, 1068 block); 1069 } 1070 1071 if (isWapPush) { 1072 int result = mWapPush.dispatchWapPdu(output.toByteArray(), resultReceiver, 1073 this, address, tracker.getSubId(), tracker.getMessageId()); 1074 if (DBG) { 1075 log("processMessagePart: dispatchWapPdu() returned " + result, 1076 tracker.getMessageId()); 1077 } 1078 // Add result of WAP-PUSH into metrics. RESULT_SMS_HANDLED indicates that the WAP-PUSH 1079 // needs to be ignored, so treating it as a success case. 1080 boolean wapPushResult = 1081 result == Activity.RESULT_OK || result == Intents.RESULT_SMS_HANDLED; 1082 mMetrics.writeIncomingWapPush(mPhone.getPhoneId(), tracker.getSource(), 1083 format, timestamps, wapPushResult, tracker.getMessageId()); 1084 mPhone.getSmsStats().onIncomingSmsWapPush(tracker.getSource(), messageCount, 1085 result, tracker.getMessageId()); 1086 // result is Activity.RESULT_OK if an ordered broadcast was sent 1087 if (result == Activity.RESULT_OK) { 1088 return true; 1089 } else { 1090 deleteFromRawTable(tracker.getDeleteWhere(), tracker.getDeleteWhereArgs(), 1091 MARK_DELETED); 1092 loge("processMessagePart: returning false as the ordered broadcast for WAP push " 1093 + "was not sent", tracker.getMessageId()); 1094 return false; 1095 } 1096 } 1097 1098 // All parts of SMS are received. Update metrics for incoming SMS. 1099 // The metrics are generated before SMS filters are invoked. 1100 // For messages composed by multiple parts, the metrics are generated considering the 1101 // characteristics of the last one. 1102 mMetrics.writeIncomingSmsSession(mPhone.getPhoneId(), tracker.getSource(), 1103 format, timestamps, block, tracker.getMessageId()); 1104 mPhone.getSmsStats().onIncomingSmsSuccess(is3gpp2(), tracker.getSource(), 1105 messageCount, block, tracker.getMessageId()); 1106 1107 // Always invoke SMS filters, even if the number ends up being blocked, to prevent 1108 // surprising bugs due to blocking numbers that happen to be used for visual voicemail SMS 1109 // or other carrier system messages. 1110 boolean filterInvoked = filterSms( 1111 pdus, destPort, tracker, resultReceiver, true /* userUnlocked */, block); 1112 1113 if (!filterInvoked) { 1114 // Block now if the filter wasn't invoked. Otherwise, it will be the responsibility of 1115 // the filter to delete the SMS once processing completes. 1116 if (block) { 1117 deleteFromRawTable(tracker.getDeleteWhere(), tracker.getDeleteWhereArgs(), 1118 DELETE_PERMANENTLY); 1119 log("processMessagePart: returning false as the phone number is blocked", 1120 tracker.getMessageId()); 1121 return false; 1122 } 1123 1124 dispatchSmsDeliveryIntent(pdus, format, destPort, resultReceiver, 1125 tracker.isClass0(), tracker.getSubId(), tracker.getMessageId()); 1126 } 1127 1128 return true; 1129 } 1130 1131 /** 1132 * Processes the message part while the credential-encrypted storage is still locked. 1133 * 1134 * <p>If the message is a regular MMS, show a new message notification. If the message is a 1135 * SMS, ask the carrier app to filter it and show the new message notification if the carrier 1136 * app asks to keep the message. 1137 * 1138 * @return true if an ordered broadcast was sent to the carrier app; false otherwise. 1139 */ processMessagePartWithUserLocked(InboundSmsTracker tracker, byte[][] pdus, int destPort, SmsBroadcastReceiver resultReceiver, boolean block)1140 private boolean processMessagePartWithUserLocked(InboundSmsTracker tracker, 1141 byte[][] pdus, int destPort, SmsBroadcastReceiver resultReceiver, boolean block) { 1142 if (destPort == SmsHeader.PORT_WAP_PUSH && mWapPush.isWapPushForMms(pdus[0], this)) { 1143 showNewMessageNotification(); 1144 return false; 1145 } 1146 if (destPort == -1) { 1147 // This is a regular SMS - hand it to the carrier or system app for filtering. 1148 boolean filterInvoked = filterSms( 1149 pdus, destPort, tracker, resultReceiver, false /* userUnlocked */, 1150 block); 1151 if (filterInvoked) { 1152 // filter invoked, wait for it to return the result. 1153 return true; 1154 } else if (!block) { 1155 // filter not invoked and message not blocked, show the notification and do nothing 1156 // further. Even if the message is blocked, we keep it in the database so it can be 1157 // reprocessed by filters once credential-encrypted storage is available. 1158 showNewMessageNotification(); 1159 } 1160 } 1161 return false; 1162 } 1163 1164 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) showNewMessageNotification()1165 private void showNewMessageNotification() { 1166 // Do not show the notification on non-FBE devices. 1167 if (!StorageManager.isFileEncryptedNativeOrEmulated()) { 1168 return; 1169 } 1170 log("Show new message notification."); 1171 PendingIntent intent = PendingIntent.getBroadcast( 1172 mContext, 1173 0, 1174 new Intent(ACTION_OPEN_SMS_APP), 1175 PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_IMMUTABLE); 1176 Notification.Builder mBuilder = new Notification.Builder(mContext) 1177 .setSmallIcon(com.android.internal.R.drawable.sym_action_chat) 1178 .setAutoCancel(true) 1179 .setVisibility(Notification.VISIBILITY_PUBLIC) 1180 .setDefaults(Notification.DEFAULT_ALL) 1181 .setContentTitle(mContext.getString(R.string.new_sms_notification_title)) 1182 .setContentText(mContext.getString(R.string.new_sms_notification_content)) 1183 .setContentIntent(intent) 1184 .setChannelId(NotificationChannelController.CHANNEL_ID_SMS); 1185 NotificationManager mNotificationManager = 1186 (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE); 1187 mNotificationManager.notify( 1188 NOTIFICATION_TAG, NOTIFICATION_ID_NEW_MESSAGE, mBuilder.build()); 1189 } 1190 cancelNewMessageNotification(Context context)1191 static void cancelNewMessageNotification(Context context) { 1192 NotificationManager mNotificationManager = 1193 (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); 1194 mNotificationManager.cancel(InboundSmsHandler.NOTIFICATION_TAG, 1195 InboundSmsHandler.NOTIFICATION_ID_NEW_MESSAGE); 1196 } 1197 1198 /** 1199 * Creates the default filters used to filter SMS messages. 1200 * 1201 * <p>Currently 3 filters exist: the carrier package, the VisualVoicemailSmsFilter, and the 1202 * missed incoming call SMS filter. 1203 * 1204 * <p>Since the carrier filter is asynchronous, if a message passes through the carrier filter, 1205 * the remaining filters will be applied in the callback. 1206 */ createDefaultSmsFilters()1207 private List<SmsFilter> createDefaultSmsFilters() { 1208 List<SmsFilter> smsFilters = new ArrayList<>(3); 1209 smsFilters.add( 1210 (pdus, destPort, tracker, resultReceiver, userUnlocked, block, remainingFilters) 1211 -> { 1212 CarrierServicesSmsFilterCallback filterCallback = 1213 new CarrierServicesSmsFilterCallback( 1214 pdus, destPort, tracker, tracker.getFormat(), resultReceiver, 1215 userUnlocked, 1216 tracker.isClass0(), tracker.getSubId(), tracker.getMessageId(), 1217 block, remainingFilters); 1218 CarrierServicesSmsFilter carrierServicesFilter = new CarrierServicesSmsFilter( 1219 mContext, mPhone, pdus, destPort, tracker.getFormat(), 1220 filterCallback, getName() + "::CarrierServicesSmsFilter", 1221 mCarrierServiceLocalLog, tracker.getMessageId()); 1222 if (carrierServicesFilter.filter()) { 1223 log("SMS is being handled by carrier service", tracker.getMessageId()); 1224 return true; 1225 } else { 1226 return false; 1227 } 1228 }); 1229 smsFilters.add( 1230 (pdus, destPort, tracker, resultReceiver, userUnlocked, block, remainingFilters) 1231 -> { 1232 if (VisualVoicemailSmsFilter.filter( 1233 mContext, pdus, tracker.getFormat(), destPort, tracker.getSubId())) { 1234 logWithLocalLog("Visual voicemail SMS dropped", tracker.getMessageId()); 1235 dropFilteredSms(tracker, resultReceiver, block); 1236 return true; 1237 } 1238 return false; 1239 }); 1240 smsFilters.add( 1241 (pdus, destPort, tracker, resultReceiver, userUnlocked, block, remainingFilters) 1242 -> { 1243 MissedIncomingCallSmsFilter missedIncomingCallSmsFilter = 1244 new MissedIncomingCallSmsFilter(mPhone); 1245 if (missedIncomingCallSmsFilter.filter(pdus, tracker.getFormat())) { 1246 logWithLocalLog("Missed incoming call SMS received", 1247 tracker.getMessageId()); 1248 dropFilteredSms(tracker, resultReceiver, block); 1249 return true; 1250 } 1251 return false; 1252 }); 1253 return smsFilters; 1254 } 1255 dropFilteredSms( InboundSmsTracker tracker, SmsBroadcastReceiver resultReceiver, boolean block)1256 private void dropFilteredSms( 1257 InboundSmsTracker tracker, SmsBroadcastReceiver resultReceiver, boolean block) { 1258 if (block) { 1259 deleteFromRawTable( 1260 tracker.getDeleteWhere(), tracker.getDeleteWhereArgs(), 1261 DELETE_PERMANENTLY); 1262 sendMessage(EVENT_BROADCAST_COMPLETE); 1263 } else { 1264 dropSms(resultReceiver); 1265 } 1266 } 1267 1268 /** 1269 * Filters the SMS. 1270 * 1271 * <p>Each filter in {@link #mSmsFilters} is invoked sequentially. If any filter returns true, 1272 * this method returns true and subsequent filters are ignored. 1273 * 1274 * @return true if a filter is invoked and the SMS processing flow is diverted, false otherwise. 1275 */ filterSms(byte[][] pdus, int destPort, InboundSmsTracker tracker, SmsBroadcastReceiver resultReceiver, boolean userUnlocked, boolean block)1276 private boolean filterSms(byte[][] pdus, int destPort, 1277 InboundSmsTracker tracker, SmsBroadcastReceiver resultReceiver, boolean userUnlocked, 1278 boolean block) { 1279 return filterSms(pdus, destPort, tracker, resultReceiver, userUnlocked, block, mSmsFilters); 1280 } 1281 filterSms(byte[][] pdus, int destPort, InboundSmsTracker tracker, SmsBroadcastReceiver resultReceiver, boolean userUnlocked, boolean block, List<SmsFilter> filters)1282 private static boolean filterSms(byte[][] pdus, int destPort, 1283 InboundSmsTracker tracker, SmsBroadcastReceiver resultReceiver, boolean userUnlocked, 1284 boolean block, List<SmsFilter> filters) { 1285 ListIterator<SmsFilter> iterator = filters.listIterator(); 1286 while (iterator.hasNext()) { 1287 SmsFilter smsFilter = iterator.next(); 1288 if (smsFilter.filterSms(pdus, destPort, tracker, resultReceiver, userUnlocked, block, 1289 filters.subList(iterator.nextIndex(), filters.size()))) { 1290 return true; 1291 } 1292 } 1293 return false; 1294 } 1295 1296 /** 1297 * Dispatch the intent with the specified permission, appOp, and result receiver, using 1298 * this state machine's handler thread to run the result receiver. 1299 * 1300 * @param intent the intent to broadcast 1301 * @param permission receivers are required to have this permission 1302 * @param appOp app op that is being performed when dispatching to a receiver 1303 * @param user user to deliver the intent to 1304 */ 1305 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) dispatchIntent(Intent intent, String permission, String appOp, Bundle opts, SmsBroadcastReceiver resultReceiver, UserHandle user, int subId)1306 public void dispatchIntent(Intent intent, String permission, String appOp, 1307 Bundle opts, SmsBroadcastReceiver resultReceiver, UserHandle user, int subId) { 1308 intent.addFlags(Intent.FLAG_RECEIVER_NO_ABORT); 1309 final String action = intent.getAction(); 1310 if (Intents.SMS_DELIVER_ACTION.equals(action) 1311 || Intents.SMS_RECEIVED_ACTION.equals(action) 1312 || Intents.WAP_PUSH_DELIVER_ACTION.equals(action) 1313 || Intents.WAP_PUSH_RECEIVED_ACTION.equals(action)) { 1314 // Some intents need to be delivered with high priority: 1315 // SMS_DELIVER, SMS_RECEIVED, WAP_PUSH_DELIVER, WAP_PUSH_RECEIVED 1316 // In some situations, like after boot up or system under load, normal 1317 // intent delivery could take a long time. 1318 // This flag should only be set for intents for visible, timely operations 1319 // which is true for the intents above. 1320 intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND); 1321 } 1322 SubscriptionManager.putPhoneIdAndSubIdExtra(intent, mPhone.getPhoneId()); 1323 1324 // override the subId value in the intent with the values from tracker as they can be 1325 // different, specifically if the message is coming from SmsBroadcastUndelivered 1326 if (SubscriptionManager.isValidSubscriptionId(subId)) { 1327 SubscriptionManager.putSubscriptionIdExtra(intent, subId); 1328 } 1329 1330 if (user.equals(UserHandle.ALL)) { 1331 // Get a list of currently started users. 1332 int[] users = null; 1333 final List<UserHandle> userHandles = mUserManager.getUserHandles(false); 1334 final List<UserHandle> runningUserHandles = new ArrayList(); 1335 for (UserHandle handle : userHandles) { 1336 if (mUserManager.isUserRunning(handle)) { 1337 runningUserHandles.add(handle); 1338 } else { 1339 if (handle.equals(UserHandle.SYSTEM)) { 1340 logeWithLocalLog("dispatchIntent: SYSTEM user is not running", 1341 resultReceiver.mInboundSmsTracker.getMessageId()); 1342 } 1343 } 1344 } 1345 if (runningUserHandles.isEmpty()) { 1346 users = new int[] {user.getIdentifier()}; 1347 } else { 1348 users = new int[runningUserHandles.size()]; 1349 for (int i = 0; i < runningUserHandles.size(); i++) { 1350 users[i] = runningUserHandles.get(i).getIdentifier(); 1351 } 1352 } 1353 // Deliver the broadcast only to those running users that are permitted 1354 // by user policy. 1355 for (int i = users.length - 1; i >= 0; i--) { 1356 UserHandle targetUser = UserHandle.of(users[i]); 1357 if (users[i] != UserHandle.SYSTEM.getIdentifier()) { 1358 // Is the user not allowed to use SMS? 1359 if (hasUserRestriction(UserManager.DISALLOW_SMS, targetUser)) { 1360 continue; 1361 } 1362 // Skip unknown users and managed profiles as well 1363 if (mUserManager.isManagedProfile(users[i])) { 1364 continue; 1365 } 1366 } 1367 // Only pass in the resultReceiver when the user SYSTEM is processed. 1368 try { 1369 if (users[i] == UserHandle.SYSTEM.getIdentifier()) { 1370 resultReceiver.setWaitingForIntent(intent); 1371 } 1372 mContext.createPackageContextAsUser(mContext.getPackageName(), 0, targetUser) 1373 .sendOrderedBroadcast(intent, Activity.RESULT_OK, permission, appOp, 1374 users[i] == UserHandle.SYSTEM.getIdentifier() 1375 ? resultReceiver : null, getHandler(), 1376 null /* initialData */, null /* initialExtras */, opts); 1377 } catch (PackageManager.NameNotFoundException ignored) { 1378 } 1379 } 1380 } else { 1381 try { 1382 resultReceiver.setWaitingForIntent(intent); 1383 mContext.createPackageContextAsUser(mContext.getPackageName(), 0, user) 1384 .sendOrderedBroadcast(intent, Activity.RESULT_OK, permission, appOp, 1385 resultReceiver, getHandler(), null /* initialData */, 1386 null /* initialExtras */, opts); 1387 } catch (PackageManager.NameNotFoundException ignored) { 1388 } 1389 } 1390 } 1391 hasUserRestriction(String restrictionKey, UserHandle userHandle)1392 private boolean hasUserRestriction(String restrictionKey, UserHandle userHandle) { 1393 final List<UserManager.EnforcingUser> sources = mUserManager 1394 .getUserRestrictionSources(restrictionKey, userHandle); 1395 return (sources != null && !sources.isEmpty()); 1396 } 1397 1398 /** 1399 * Helper for {@link SmsBroadcastUndelivered} to delete an old message in the raw table. 1400 */ 1401 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) deleteFromRawTable(String deleteWhere, String[] deleteWhereArgs, int deleteType)1402 private void deleteFromRawTable(String deleteWhere, String[] deleteWhereArgs, 1403 int deleteType) { 1404 Uri uri = deleteType == DELETE_PERMANENTLY ? sRawUriPermanentDelete : sRawUri; 1405 int rows = mResolver.delete(uri, deleteWhere, deleteWhereArgs); 1406 if (rows == 0) { 1407 loge("No rows were deleted from raw table!"); 1408 } else if (DBG) { 1409 log("Deleted " + rows + " rows from raw table."); 1410 } 1411 } 1412 1413 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) handleSmsWhitelisting(ComponentName target, boolean bgActivityStartAllowed)1414 private Bundle handleSmsWhitelisting(ComponentName target, boolean bgActivityStartAllowed) { 1415 String pkgName; 1416 String reason; 1417 if (target != null) { 1418 pkgName = target.getPackageName(); 1419 reason = "sms-app"; 1420 } else { 1421 pkgName = mContext.getPackageName(); 1422 reason = "sms-broadcast"; 1423 } 1424 BroadcastOptions bopts = null; 1425 Bundle bundle = null; 1426 if (bgActivityStartAllowed) { 1427 bopts = BroadcastOptions.makeBasic(); 1428 bopts.setBackgroundActivityStartsAllowed(true); 1429 bundle = bopts.toBundle(); 1430 } 1431 long duration = mPowerWhitelistManager.whitelistAppTemporarilyForEvent( 1432 pkgName, PowerWhitelistManager.EVENT_SMS, REASON_EVENT_SMS, reason); 1433 if (bopts == null) bopts = BroadcastOptions.makeBasic(); 1434 bopts.setTemporaryAppAllowlist(duration, 1435 TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED, 1436 REASON_EVENT_SMS, 1437 ""); 1438 bundle = bopts.toBundle(); 1439 1440 return bundle; 1441 } 1442 1443 /** 1444 * Creates and dispatches the intent to the default SMS app, appropriate port or via the {@link 1445 * AppSmsManager}. 1446 * 1447 * @param pdus message pdus 1448 * @param format the message format, typically "3gpp" or "3gpp2" 1449 * @param destPort the destination port 1450 * @param resultReceiver the receiver handling the delivery result 1451 */ dispatchSmsDeliveryIntent(byte[][] pdus, String format, int destPort, SmsBroadcastReceiver resultReceiver, boolean isClass0, int subId, long messageId)1452 private void dispatchSmsDeliveryIntent(byte[][] pdus, String format, int destPort, 1453 SmsBroadcastReceiver resultReceiver, boolean isClass0, int subId, long messageId) { 1454 Intent intent = new Intent(); 1455 intent.putExtra("pdus", pdus); 1456 intent.putExtra("format", format); 1457 if (messageId != 0L) { 1458 intent.putExtra("messageId", messageId); 1459 } 1460 1461 if (destPort == -1) { 1462 intent.setAction(Intents.SMS_DELIVER_ACTION); 1463 // Direct the intent to only the default SMS app. If we can't find a default SMS app 1464 // then sent it to all broadcast receivers. 1465 // We are deliberately delivering to the primary user's default SMS App. 1466 ComponentName componentName = SmsApplication.getDefaultSmsApplication(mContext, true); 1467 if (componentName != null) { 1468 // Deliver SMS message only to this receiver. 1469 intent.setComponent(componentName); 1470 logWithLocalLog("Delivering SMS to: " + componentName.getPackageName() 1471 + " " + componentName.getClassName(), messageId); 1472 } else { 1473 intent.setComponent(null); 1474 } 1475 1476 // Handle app specific sms messages. 1477 AppSmsManager appManager = mPhone.getAppSmsManager(); 1478 if (appManager.handleSmsReceivedIntent(intent)) { 1479 // The AppSmsManager handled this intent, we're done. 1480 dropSms(resultReceiver); 1481 return; 1482 } 1483 } else { 1484 intent.setAction(Intents.DATA_SMS_RECEIVED_ACTION); 1485 Uri uri = Uri.parse("sms://localhost:" + destPort); 1486 intent.setData(uri); 1487 intent.setComponent(null); 1488 } 1489 1490 Bundle options = handleSmsWhitelisting(intent.getComponent(), isClass0); 1491 dispatchIntent(intent, android.Manifest.permission.RECEIVE_SMS, 1492 AppOpsManager.OPSTR_RECEIVE_SMS, options, resultReceiver, UserHandle.SYSTEM, subId); 1493 } 1494 1495 /** 1496 * Function to detect and handle duplicate messages. If the received message should replace an 1497 * existing message in the raw db, this function deletes the existing message. If an existing 1498 * message takes priority (for eg, existing message has already been broadcast), then this new 1499 * message should be dropped. 1500 * @return true if the message represented by the passed in tracker should be dropped, 1501 * false otherwise 1502 */ checkAndHandleDuplicate(InboundSmsTracker tracker)1503 private boolean checkAndHandleDuplicate(InboundSmsTracker tracker) throws SQLException { 1504 Pair<String, String[]> exactMatchQuery = tracker.getExactMatchDupDetectQuery(); 1505 1506 Cursor cursor = null; 1507 try { 1508 // Check for duplicate message segments 1509 cursor = mResolver.query(sRawUri, PDU_DELETED_FLAG_PROJECTION, exactMatchQuery.first, 1510 exactMatchQuery.second, null); 1511 1512 // moveToNext() returns false if no duplicates were found 1513 if (cursor != null && cursor.moveToNext()) { 1514 if (cursor.getCount() != 1) { 1515 logeWithLocalLog("checkAndHandleDuplicate: Exact match query returned " 1516 + cursor.getCount() + " rows", tracker.getMessageId()); 1517 } 1518 1519 // if the exact matching row is marked deleted, that means this message has already 1520 // been received and processed, and can be discarded as dup 1521 if (cursor.getInt( 1522 PDU_DELETED_FLAG_PROJECTION_INDEX_MAPPING.get(DELETED_FLAG_COLUMN)) == 1) { 1523 logWithLocalLog("checkAndHandleDuplicate: Discarding duplicate " 1524 + "message/segment: " + tracker); 1525 logDupPduMismatch(cursor, tracker); 1526 return true; // reject message 1527 } else { 1528 // exact match duplicate is not marked deleted. If it is a multi-part segment, 1529 // the code below for inexact match will take care of it. If it is a single 1530 // part message, handle it here. 1531 if (tracker.getMessageCount() == 1) { 1532 // delete the old message segment permanently 1533 deleteFromRawTable(exactMatchQuery.first, exactMatchQuery.second, 1534 DELETE_PERMANENTLY); 1535 logWithLocalLog("checkAndHandleDuplicate: Replacing duplicate message: " 1536 + tracker); 1537 logDupPduMismatch(cursor, tracker); 1538 } 1539 } 1540 } 1541 } finally { 1542 if (cursor != null) { 1543 cursor.close(); 1544 } 1545 } 1546 1547 // The code above does an exact match. Multi-part message segments need an additional check 1548 // on top of that: if there is a message segment that conflicts this new one (may not be an 1549 // exact match), replace the old message segment with this one. 1550 if (tracker.getMessageCount() > 1) { 1551 Pair<String, String[]> inexactMatchQuery = tracker.getInexactMatchDupDetectQuery(); 1552 cursor = null; 1553 try { 1554 // Check for duplicate message segments 1555 cursor = mResolver.query(sRawUri, PDU_DELETED_FLAG_PROJECTION, 1556 inexactMatchQuery.first, inexactMatchQuery.second, null); 1557 1558 // moveToNext() returns false if no duplicates were found 1559 if (cursor != null && cursor.moveToNext()) { 1560 if (cursor.getCount() != 1) { 1561 logeWithLocalLog("checkAndHandleDuplicate: Inexact match query returned " 1562 + cursor.getCount() + " rows", tracker.getMessageId()); 1563 } 1564 // delete the old message segment permanently 1565 deleteFromRawTable(inexactMatchQuery.first, inexactMatchQuery.second, 1566 DELETE_PERMANENTLY); 1567 logWithLocalLog("checkAndHandleDuplicate: Replacing duplicate message segment: " 1568 + tracker); 1569 logDupPduMismatch(cursor, tracker); 1570 } 1571 } finally { 1572 if (cursor != null) { 1573 cursor.close(); 1574 } 1575 } 1576 } 1577 1578 return false; 1579 } 1580 logDupPduMismatch(Cursor cursor, InboundSmsTracker tracker)1581 private void logDupPduMismatch(Cursor cursor, InboundSmsTracker tracker) { 1582 String oldPduString = cursor.getString( 1583 PDU_DELETED_FLAG_PROJECTION_INDEX_MAPPING.get(PDU_COLUMN)); 1584 byte[] pdu = tracker.getPdu(); 1585 byte[] oldPdu = HexDump.hexStringToByteArray(oldPduString); 1586 if (!Arrays.equals(oldPdu, tracker.getPdu())) { 1587 logeWithLocalLog("Warning: dup message PDU of length " + pdu.length 1588 + " is different from existing PDU of length " + oldPdu.length, 1589 tracker.getMessageId()); 1590 } 1591 } 1592 1593 /** 1594 * Insert a message PDU into the raw table so we can acknowledge it immediately. 1595 * If the device crashes before the broadcast to listeners completes, it will be delivered 1596 * from the raw table on the next device boot. For single-part messages, the deleteWhere 1597 * and deleteWhereArgs fields of the tracker will be set to delete the correct row after 1598 * the ordered broadcast completes. 1599 * 1600 * @param tracker the tracker to add to the raw table 1601 * @return true on success; false on failure to write to database 1602 */ addTrackerToRawTable(InboundSmsTracker tracker, boolean deDup)1603 private int addTrackerToRawTable(InboundSmsTracker tracker, boolean deDup) { 1604 if (deDup) { 1605 try { 1606 if (checkAndHandleDuplicate(tracker)) { 1607 return Intents.RESULT_SMS_DUPLICATED; // reject message 1608 } 1609 } catch (SQLException e) { 1610 loge("addTrackerToRawTable: Can't access SMS database, " 1611 + SmsController.formatCrossStackMessageId(tracker.getMessageId()), e); 1612 return RESULT_SMS_DATABASE_ERROR; // reject message 1613 } 1614 } else { 1615 log("addTrackerToRawTable: Skipped message de-duping logic", tracker.getMessageId()); 1616 } 1617 1618 String address = tracker.getAddress(); 1619 String refNumber = Integer.toString(tracker.getReferenceNumber()); 1620 String count = Integer.toString(tracker.getMessageCount()); 1621 ContentValues values = tracker.getContentValues(); 1622 1623 if (VDBG) { 1624 log("addTrackerToRawTable: adding content values to raw table: " + values.toString(), 1625 tracker.getMessageId()); 1626 } 1627 Uri newUri = mResolver.insert(sRawUri, values); 1628 if (DBG) log("addTrackerToRawTable: URI of new row: " + newUri, tracker.getMessageId()); 1629 1630 try { 1631 long rowId = ContentUris.parseId(newUri); 1632 if (tracker.getMessageCount() == 1) { 1633 // set the delete selection args for single-part message 1634 tracker.setDeleteWhere(SELECT_BY_ID, new String[]{Long.toString(rowId)}); 1635 } else { 1636 // set the delete selection args for multi-part message 1637 String[] deleteWhereArgs = {address, refNumber, count}; 1638 tracker.setDeleteWhere(tracker.getQueryForSegments(), deleteWhereArgs); 1639 } 1640 return Intents.RESULT_SMS_HANDLED; 1641 } catch (Exception e) { 1642 loge("addTrackerToRawTable: error parsing URI for new row: " + newUri 1643 + " " + SmsController.formatCrossStackMessageId(tracker.getMessageId()), e); 1644 return RESULT_SMS_INVALID_URI; 1645 } 1646 } 1647 1648 /** 1649 * Returns whether the default message format for the current radio technology is 3GPP2. 1650 * @return true if the radio technology uses 3GPP2 format by default, false for 3GPP format 1651 */ isCurrentFormat3gpp2()1652 static boolean isCurrentFormat3gpp2() { 1653 int activePhone = TelephonyManager.getDefault().getCurrentPhoneType(); 1654 return (PHONE_TYPE_CDMA == activePhone); 1655 } 1656 1657 @VisibleForTesting 1658 public static int sTimeoutDurationMillis = 10 * 60 * 1000; // 10 minutes 1659 1660 /** 1661 * Handler for an {@link InboundSmsTracker} broadcast. Deletes PDUs from the raw table and 1662 * logs the broadcast duration (as an error if the other receivers were especially slow). 1663 */ 1664 public final class SmsBroadcastReceiver extends BroadcastReceiver { 1665 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) 1666 private final String mDeleteWhere; 1667 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) 1668 private final String[] mDeleteWhereArgs; 1669 private long mBroadcastTimeMillis; 1670 public Intent mWaitingForIntent; 1671 private final InboundSmsTracker mInboundSmsTracker; 1672 1673 /** 1674 * This method must be called anytime an ordered broadcast is sent that is expected to be 1675 * received by this receiver. 1676 */ setWaitingForIntent(Intent intent)1677 public synchronized void setWaitingForIntent(Intent intent) { 1678 mWaitingForIntent = intent; 1679 mBroadcastTimeMillis = System.currentTimeMillis(); 1680 removeMessages(EVENT_RECEIVER_TIMEOUT); 1681 sendMessageDelayed(EVENT_RECEIVER_TIMEOUT, sTimeoutDurationMillis); 1682 } 1683 SmsBroadcastReceiver(InboundSmsTracker tracker)1684 public SmsBroadcastReceiver(InboundSmsTracker tracker) { 1685 mDeleteWhere = tracker.getDeleteWhere(); 1686 mDeleteWhereArgs = tracker.getDeleteWhereArgs(); 1687 mInboundSmsTracker = tracker; 1688 } 1689 1690 /** 1691 * This method is called if the expected intent (mWaitingForIntent) is not received and 1692 * the timer for it expires. It fakes the receipt of the intent to unblock the state 1693 * machine. 1694 */ fakeNextAction()1695 public void fakeNextAction() { 1696 if (mWaitingForIntent != null) { 1697 logeWithLocalLog("fakeNextAction: " + mWaitingForIntent.getAction(), 1698 mInboundSmsTracker.getMessageId()); 1699 handleAction(mWaitingForIntent, false); 1700 } else { 1701 logeWithLocalLog("fakeNextAction: mWaitingForIntent is null", 1702 mInboundSmsTracker.getMessageId()); 1703 } 1704 } 1705 1706 @Override onReceive(Context context, Intent intent)1707 public void onReceive(Context context, Intent intent) { 1708 if (intent == null) { 1709 logeWithLocalLog("onReceive: received null intent, faking " + mWaitingForIntent, 1710 mInboundSmsTracker.getMessageId()); 1711 return; 1712 } 1713 handleAction(intent, true); 1714 } 1715 handleAction(@onNull Intent intent, boolean onReceive)1716 private synchronized void handleAction(@NonNull Intent intent, boolean onReceive) { 1717 String action = intent.getAction(); 1718 if (mWaitingForIntent == null || !mWaitingForIntent.getAction().equals(action)) { 1719 logeWithLocalLog("handleAction: Received " + action + " when expecting " 1720 + mWaitingForIntent == null ? "none" : mWaitingForIntent.getAction(), 1721 mInboundSmsTracker.getMessageId()); 1722 return; 1723 } 1724 1725 if (onReceive) { 1726 int durationMillis = (int) (System.currentTimeMillis() - mBroadcastTimeMillis); 1727 if (durationMillis >= 5000) { 1728 loge("Slow ordered broadcast completion time for " + action + ": " 1729 + durationMillis + " ms"); 1730 } else if (DBG) { 1731 log("Ordered broadcast completed for " + action + " in: " 1732 + durationMillis + " ms"); 1733 } 1734 } 1735 1736 int subId = intent.getIntExtra(SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX, 1737 SubscriptionManager.INVALID_SUBSCRIPTION_ID); 1738 if (action.equals(Intents.SMS_DELIVER_ACTION)) { 1739 // Now dispatch the notification only intent 1740 intent.setAction(Intents.SMS_RECEIVED_ACTION); 1741 // Allow registered broadcast receivers to get this intent even 1742 // when they are in the background. 1743 intent.setComponent(null); 1744 // All running users will be notified of the received sms. 1745 Bundle options = handleSmsWhitelisting(null, false /* bgActivityStartAllowed */); 1746 1747 setWaitingForIntent(intent); 1748 dispatchIntent(intent, android.Manifest.permission.RECEIVE_SMS, 1749 AppOpsManager.OPSTR_RECEIVE_SMS, 1750 options, this, UserHandle.ALL, subId); 1751 } else if (action.equals(Intents.WAP_PUSH_DELIVER_ACTION)) { 1752 // Now dispatch the notification only intent 1753 intent.setAction(Intents.WAP_PUSH_RECEIVED_ACTION); 1754 intent.setComponent(null); 1755 // Only the primary user will receive notification of incoming mms. 1756 // That app will do the actual downloading of the mms. 1757 long duration = mPowerWhitelistManager.whitelistAppTemporarilyForEvent( 1758 mContext.getPackageName(), 1759 PowerWhitelistManager.EVENT_MMS, 1760 REASON_EVENT_MMS, 1761 "mms-broadcast"); 1762 BroadcastOptions bopts = BroadcastOptions.makeBasic(); 1763 bopts.setTemporaryAppAllowlist(duration, 1764 TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED, 1765 REASON_EVENT_MMS, 1766 ""); 1767 Bundle options = bopts.toBundle(); 1768 1769 String mimeType = intent.getType(); 1770 1771 setWaitingForIntent(intent); 1772 dispatchIntent(intent, WapPushOverSms.getPermissionForType(mimeType), 1773 WapPushOverSms.getAppOpsStringPermissionForIntent(mimeType), options, this, 1774 UserHandle.SYSTEM, subId); 1775 } else { 1776 // Now that the intents have been deleted we can clean up the PDU data. 1777 if (!Intents.DATA_SMS_RECEIVED_ACTION.equals(action) 1778 && !Intents.SMS_RECEIVED_ACTION.equals(action) 1779 && !Intents.WAP_PUSH_RECEIVED_ACTION.equals(action)) { 1780 loge("unexpected BroadcastReceiver action: " + action); 1781 } 1782 1783 if (onReceive) { 1784 int rc = getResultCode(); 1785 if ((rc != Activity.RESULT_OK) && (rc != Intents.RESULT_SMS_HANDLED)) { 1786 loge("a broadcast receiver set the result code to " + rc 1787 + ", deleting from raw table anyway!"); 1788 } else if (DBG) { 1789 log("successful broadcast, deleting from raw table."); 1790 } 1791 } 1792 1793 deleteFromRawTable(mDeleteWhere, mDeleteWhereArgs, MARK_DELETED); 1794 mWaitingForIntent = null; 1795 removeMessages(EVENT_RECEIVER_TIMEOUT); 1796 sendMessage(EVENT_BROADCAST_COMPLETE); 1797 } 1798 } 1799 } 1800 1801 /** 1802 * Callback that handles filtering results by carrier services. 1803 */ 1804 private final class CarrierServicesSmsFilterCallback implements 1805 CarrierServicesSmsFilter.CarrierServicesSmsFilterCallbackInterface { 1806 private final byte[][] mPdus; 1807 private final int mDestPort; 1808 private final InboundSmsTracker mTracker; 1809 private final String mSmsFormat; 1810 private final SmsBroadcastReceiver mSmsBroadcastReceiver; 1811 private final boolean mUserUnlocked; 1812 private final boolean mIsClass0; 1813 private final int mSubId; 1814 private final long mMessageId; 1815 private final boolean mBlock; 1816 private final List<SmsFilter> mRemainingFilters; 1817 CarrierServicesSmsFilterCallback(byte[][] pdus, int destPort, InboundSmsTracker tracker, String smsFormat, SmsBroadcastReceiver smsBroadcastReceiver, boolean userUnlocked, boolean isClass0, int subId, long messageId, boolean block, List<SmsFilter> remainingFilters)1818 CarrierServicesSmsFilterCallback(byte[][] pdus, int destPort, InboundSmsTracker tracker, 1819 String smsFormat, SmsBroadcastReceiver smsBroadcastReceiver, boolean userUnlocked, 1820 boolean isClass0, int subId, long messageId, boolean block, 1821 List<SmsFilter> remainingFilters) { 1822 mPdus = pdus; 1823 mDestPort = destPort; 1824 mTracker = tracker; 1825 mSmsFormat = smsFormat; 1826 mSmsBroadcastReceiver = smsBroadcastReceiver; 1827 mUserUnlocked = userUnlocked; 1828 mIsClass0 = isClass0; 1829 mSubId = subId; 1830 mMessageId = messageId; 1831 mBlock = block; 1832 mRemainingFilters = remainingFilters; 1833 } 1834 1835 @Override onFilterComplete(int result)1836 public void onFilterComplete(int result) { 1837 log("onFilterComplete: result is " + result, mTracker.getMessageId()); 1838 1839 boolean carrierRequestedDrop = 1840 (result & CarrierMessagingService.RECEIVE_OPTIONS_DROP) != 0; 1841 if (carrierRequestedDrop) { 1842 // Carrier app asked the platform to drop the SMS. Drop it from the database and 1843 // complete processing. 1844 dropFilteredSms(mTracker, mSmsBroadcastReceiver, mBlock); 1845 return; 1846 } 1847 1848 boolean filterInvoked = filterSms(mPdus, mDestPort, mTracker, mSmsBroadcastReceiver, 1849 mUserUnlocked, mBlock, mRemainingFilters); 1850 if (filterInvoked) { 1851 // A remaining filter has assumed responsibility for further message processing. 1852 return; 1853 } 1854 1855 // Now that all filters have been invoked, drop the message if it is blocked. 1856 if (mBlock) { 1857 // Only delete the message if the user is unlocked. Otherwise, we should reprocess 1858 // the message after unlock so the filter has a chance to run while credential- 1859 // encrypted storage is available. 1860 if (mUserUnlocked) { 1861 log("onFilterComplete: dropping message as the sender is blocked", 1862 mTracker.getMessageId()); 1863 dropFilteredSms(mTracker, mSmsBroadcastReceiver, mBlock); 1864 } else { 1865 // Just complete handling of the message without dropping it. 1866 sendMessage(EVENT_BROADCAST_COMPLETE); 1867 } 1868 return; 1869 } 1870 1871 // Message matched no filters and is not blocked, so complete processing. 1872 if (mUserUnlocked) { 1873 dispatchSmsDeliveryIntent( 1874 mPdus, mSmsFormat, mDestPort, mSmsBroadcastReceiver, mIsClass0, mSubId, 1875 mMessageId); 1876 } else { 1877 // Don't do anything further, leave the message in the raw table if the 1878 // credential-encrypted storage is still locked and show the new message 1879 // notification if the message is visible to the user. 1880 if (!isSkipNotifyFlagSet(result)) { 1881 showNewMessageNotification(); 1882 } 1883 sendMessage(EVENT_BROADCAST_COMPLETE); 1884 } 1885 } 1886 } 1887 dropSms(SmsBroadcastReceiver receiver)1888 private void dropSms(SmsBroadcastReceiver receiver) { 1889 // Needs phone package permissions. 1890 deleteFromRawTable(receiver.mDeleteWhere, receiver.mDeleteWhereArgs, MARK_DELETED); 1891 sendMessage(EVENT_BROADCAST_COMPLETE); 1892 } 1893 1894 /** Checks whether the flag to skip new message notification is set in the bitmask returned 1895 * from the carrier app. 1896 */ 1897 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) isSkipNotifyFlagSet(int callbackResult)1898 private boolean isSkipNotifyFlagSet(int callbackResult) { 1899 return (callbackResult 1900 & RECEIVE_OPTIONS_SKIP_NOTIFY_WHEN_CREDENTIAL_PROTECTED_STORAGE_UNAVAILABLE) > 0; 1901 } 1902 1903 /** 1904 * Log with debug level in logcat and LocalLog 1905 * @param logMsg msg to log 1906 */ logWithLocalLog(String logMsg)1907 protected void logWithLocalLog(String logMsg) { 1908 log(logMsg); 1909 mLocalLog.log(logMsg); 1910 } 1911 1912 /** 1913 * Log with debug level in logcat and LocalLog 1914 * @param logMsg msg to log 1915 * @param id unique message id 1916 */ logWithLocalLog(String logMsg, long id)1917 protected void logWithLocalLog(String logMsg, long id) { 1918 log(logMsg, id); 1919 mLocalLog.log(logMsg + ", " + SmsController.formatCrossStackMessageId(id)); 1920 } 1921 1922 /** 1923 * Log with error level in logcat and LocalLog 1924 * @param logMsg msg to log 1925 */ logeWithLocalLog(String logMsg)1926 protected void logeWithLocalLog(String logMsg) { 1927 loge(logMsg); 1928 mLocalLog.log(logMsg); 1929 } 1930 1931 /** 1932 * Log with error level in logcat and LocalLog 1933 * @param logMsg msg to log 1934 * @param id unique message id 1935 */ logeWithLocalLog(String logMsg, long id)1936 protected void logeWithLocalLog(String logMsg, long id) { 1937 loge(logMsg, id); 1938 mLocalLog.log(logMsg + ", " + SmsController.formatCrossStackMessageId(id)); 1939 } 1940 1941 /** 1942 * Log with debug level. 1943 * @param s the string to log 1944 */ 1945 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) 1946 @Override log(String s)1947 protected void log(String s) { 1948 Rlog.d(getName(), s); 1949 } 1950 1951 /** 1952 * Log with debug level. 1953 * @param s the string to log 1954 * @param id unique message id 1955 */ log(String s, long id)1956 protected void log(String s, long id) { 1957 log(s + ", " + SmsController.formatCrossStackMessageId(id)); 1958 } 1959 1960 /** 1961 * Log with error level. 1962 * @param s the string to log 1963 */ 1964 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) 1965 @Override loge(String s)1966 protected void loge(String s) { 1967 Rlog.e(getName(), s); 1968 } 1969 1970 /** 1971 * Log with error level. 1972 * @param s the string to log 1973 * @param id unique message id 1974 */ loge(String s, long id)1975 protected void loge(String s, long id) { 1976 loge(s + ", " + SmsController.formatCrossStackMessageId(id)); 1977 } 1978 1979 /** 1980 * Log with error level. 1981 * @param s the string to log 1982 * @param e is a Throwable which logs additional information. 1983 */ 1984 @Override loge(String s, Throwable e)1985 protected void loge(String s, Throwable e) { 1986 Rlog.e(getName(), s, e); 1987 } 1988 1989 /** 1990 * Build up the SMS message body from the SmsMessage array of received SMS 1991 * 1992 * @param msgs The SmsMessage array of the received SMS 1993 * @return The text message body 1994 */ buildMessageBodyFromPdus(SmsMessage[] msgs)1995 private static String buildMessageBodyFromPdus(SmsMessage[] msgs) { 1996 if (msgs.length == 1) { 1997 // There is only one part, so grab the body directly. 1998 return replaceFormFeeds(msgs[0].getDisplayMessageBody()); 1999 } else { 2000 // Build up the body from the parts. 2001 StringBuilder body = new StringBuilder(); 2002 for (SmsMessage msg: msgs) { 2003 // getDisplayMessageBody() can NPE if mWrappedMessage inside is null. 2004 body.append(msg.getDisplayMessageBody()); 2005 } 2006 return replaceFormFeeds(body.toString()); 2007 } 2008 } 2009 2010 @Override dump(FileDescriptor fd, PrintWriter printWriter, String[] args)2011 public void dump(FileDescriptor fd, PrintWriter printWriter, String[] args) { 2012 IndentingPrintWriter pw = new IndentingPrintWriter(printWriter, " "); 2013 pw.println(getName() + " extends StateMachine:"); 2014 pw.increaseIndent(); 2015 super.dump(fd, pw, args); 2016 if (mCellBroadcastServiceManager != null) { 2017 mCellBroadcastServiceManager.dump(fd, pw, args); 2018 } 2019 pw.println("mLocalLog:"); 2020 pw.increaseIndent(); 2021 mLocalLog.dump(fd, pw, args); 2022 pw.decreaseIndent(); 2023 pw.println("mCarrierServiceLocalLog:"); 2024 pw.increaseIndent(); 2025 mCarrierServiceLocalLog.dump(fd, pw, args); 2026 pw.decreaseIndent(); 2027 pw.decreaseIndent(); 2028 } 2029 2030 // Some providers send formfeeds in their messages. Convert those formfeeds to newlines. replaceFormFeeds(String s)2031 private static String replaceFormFeeds(String s) { 2032 return s == null ? "" : s.replace('\f', '\n'); 2033 } 2034 2035 @VisibleForTesting getWakeLock()2036 public PowerManager.WakeLock getWakeLock() { 2037 return mWakeLock; 2038 } 2039 2040 @VisibleForTesting getWakeLockTimeout()2041 public int getWakeLockTimeout() { 2042 return mWakeLockTimeout; 2043 } 2044 2045 /** 2046 * Sets the wakelock timeout to {@link timeOut} milliseconds 2047 */ setWakeLockTimeout(int timeOut)2048 private void setWakeLockTimeout(int timeOut) { 2049 mWakeLockTimeout = timeOut; 2050 } 2051 2052 /** 2053 * Set the SMS filters used by {@link #filterSms} for testing purposes. 2054 * 2055 * @param smsFilters List of SMS filters, or null to restore the default filters. 2056 */ 2057 @VisibleForTesting setSmsFiltersForTesting(@ullable List<SmsFilter> smsFilters)2058 public void setSmsFiltersForTesting(@Nullable List<SmsFilter> smsFilters) { 2059 if (smsFilters == null) { 2060 mSmsFilters = createDefaultSmsFilters(); 2061 } else { 2062 mSmsFilters = smsFilters; 2063 } 2064 } 2065 2066 /** 2067 * Handler for the broadcast sent when the new message notification is clicked. It launches the 2068 * default SMS app. 2069 */ 2070 private static class NewMessageNotificationActionReceiver extends BroadcastReceiver { 2071 @Override onReceive(Context context, Intent intent)2072 public void onReceive(Context context, Intent intent) { 2073 if (ACTION_OPEN_SMS_APP.equals(intent.getAction())) { 2074 // do nothing if the user had not unlocked the device yet 2075 UserManager userManager = 2076 (UserManager) context.getSystemService(Context.USER_SERVICE); 2077 if (userManager.isUserUnlocked()) { 2078 context.startActivity(context.getPackageManager().getLaunchIntentForPackage( 2079 Telephony.Sms.getDefaultSmsPackage(context))); 2080 } 2081 } 2082 } 2083 } 2084 decodeHexString(String hexString)2085 protected byte[] decodeHexString(String hexString) { 2086 if (hexString == null || hexString.length() % 2 == 1) { 2087 return null; 2088 } 2089 byte[] bytes = new byte[hexString.length() / 2]; 2090 for (int i = 0; i < hexString.length(); i += 2) { 2091 bytes[i / 2] = hexToByte(hexString.substring(i, i + 2)); 2092 } 2093 return bytes; 2094 } 2095 hexToByte(String hexString)2096 private byte hexToByte(String hexString) { 2097 int firstDigit = toDigit(hexString.charAt(0)); 2098 int secondDigit = toDigit(hexString.charAt(1)); 2099 return (byte) ((firstDigit << 4) + secondDigit); 2100 } 2101 toDigit(char hexChar)2102 private int toDigit(char hexChar) { 2103 int digit = Character.digit(hexChar, 16); 2104 if (digit == -1) { 2105 return 0; 2106 } 2107 return digit; 2108 } 2109 2110 2111 /** 2112 * Registers the broadcast receiver to launch the default SMS app when the user clicks the 2113 * new message notification. 2114 */ registerNewMessageNotificationActionHandler(Context context)2115 static void registerNewMessageNotificationActionHandler(Context context) { 2116 IntentFilter userFilter = new IntentFilter(); 2117 userFilter.addAction(ACTION_OPEN_SMS_APP); 2118 context.registerReceiver(new NewMessageNotificationActionReceiver(), userFilter); 2119 } 2120 2121 protected abstract class CbTestBroadcastReceiver extends BroadcastReceiver { 2122 handleTestAction(Intent intent)2123 protected abstract void handleTestAction(Intent intent); 2124 2125 protected final String mTestAction; 2126 CbTestBroadcastReceiver(String testAction)2127 public CbTestBroadcastReceiver(String testAction) { 2128 mTestAction = testAction; 2129 } 2130 2131 @Override onReceive(Context context, Intent intent)2132 public void onReceive(Context context, Intent intent) { 2133 logd("Received test intent action=" + intent.getAction()); 2134 if (intent.getAction().equals(mTestAction)) { 2135 // Return early if phone_id is explicilty included and does not match mPhone. 2136 // If phone_id extra is not included, continue. 2137 int phoneId = mPhone.getPhoneId(); 2138 if (intent.getIntExtra("phone_id", phoneId) != phoneId) { 2139 return; 2140 } 2141 handleTestAction(intent); 2142 } 2143 } 2144 } 2145 2146 /** A filter for incoming messages allowing the normal processing flow to be skipped. */ 2147 @VisibleForTesting 2148 public interface SmsFilter { 2149 /** 2150 * Returns true if a filter is invoked and the SMS processing flow should be diverted, false 2151 * otherwise. 2152 * 2153 * <p>If the filter can immediately determine that the message matches, it must call 2154 * {@link #dropFilteredSms} to drop the message from the database once it has been 2155 * processed. 2156 * 2157 * <p>If the filter must perform some asynchronous work to determine if the message matches, 2158 * it should return true to defer processing. Once it has made a determination, if it finds 2159 * the message matches, it must call {@link #dropFilteredSms}. If the message does not 2160 * match, it must be passed through {@code remainingFilters} and either dropped if the 2161 * remaining filters all return false or if {@code block} is true, or else it must be 2162 * broadcast. 2163 */ filterSms(byte[][] pdus, int destPort, InboundSmsTracker tracker, SmsBroadcastReceiver resultReceiver, boolean userUnlocked, boolean block, List<SmsFilter> remainingFilters)2164 boolean filterSms(byte[][] pdus, int destPort, InboundSmsTracker tracker, 2165 SmsBroadcastReceiver resultReceiver, boolean userUnlocked, boolean block, 2166 List<SmsFilter> remainingFilters); 2167 } 2168 } 2169