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