• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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