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