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.telephony.TelephonyManager.PHONE_TYPE_CDMA;
     20 
     21 import android.app.Activity;
     22 import android.app.ActivityManagerNative;
     23 import android.app.AppOpsManager;
     24 import android.app.PendingIntent;
     25 import android.app.PendingIntent.CanceledException;
     26 import android.content.BroadcastReceiver;
     27 import android.content.ComponentName;
     28 import android.content.ContentResolver;
     29 import android.content.ContentUris;
     30 import android.content.ContentValues;
     31 import android.content.Context;
     32 import android.content.Intent;
     33 import android.content.SharedPreferences;
     34 import android.content.pm.UserInfo;
     35 import android.content.pm.ApplicationInfo;
     36 import android.content.pm.PackageInfo;
     37 import android.content.pm.PackageManager;
     38 import android.content.pm.ResolveInfo;
     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.Message;
     46 import android.os.PowerManager;
     47 import android.os.RemoteException;
     48 import android.os.SystemProperties;
     49 import android.os.UserHandle;
     50 import android.os.UserManager;
     51 import android.preference.PreferenceManager;
     52 import android.provider.Telephony;
     53 import android.provider.Telephony.Sms.Intents;
     54 import android.service.carrier.CarrierMessagingService;
     55 import android.service.carrier.ICarrierMessagingCallback;
     56 import android.service.carrier.ICarrierMessagingService;
     57 import android.service.carrier.MessagePdu;
     58 import android.telephony.CarrierMessagingServiceManager;
     59 import android.telephony.Rlog;
     60 import android.telephony.SmsManager;
     61 import android.telephony.SmsMessage;
     62 import android.telephony.SubscriptionManager;
     63 import android.telephony.TelephonyManager;
     64 import android.text.TextUtils;
     65 
     66 import com.android.internal.telephony.uicc.UiccCard;
     67 import com.android.internal.telephony.uicc.UiccController;
     68 import com.android.internal.util.HexDump;
     69 import com.android.internal.util.State;
     70 import com.android.internal.util.StateMachine;
     71 
     72 import java.io.ByteArrayOutputStream;
     73 import java.util.Arrays;
     74 import java.util.ArrayList;
     75 import java.util.List;
     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     };
    112 
    113     static final int PDU_COLUMN = 0;
    114     static final int SEQUENCE_COLUMN = 1;
    115     static final int DESTINATION_PORT_COLUMN = 2;
    116     static final int DATE_COLUMN = 3;
    117     static final int REFERENCE_NUMBER_COLUMN = 4;
    118     static final int COUNT_COLUMN = 5;
    119     static final int ADDRESS_COLUMN = 6;
    120     static final int ID_COLUMN = 7;
    121 
    122     static final String SELECT_BY_ID = "_id=?";
    123     static final String SELECT_BY_REFERENCE = "address=? AND reference_number=? AND count=?";
    124 
    125     /** New SMS received as an AsyncResult. */
    126     public static final int EVENT_NEW_SMS = 1;
    127 
    128     /** Message type containing a {@link InboundSmsTracker} ready to broadcast to listeners. */
    129     static final int EVENT_BROADCAST_SMS = 2;
    130 
    131     /** Message from resultReceiver notifying {@link WaitingState} of a completed broadcast. */
    132     static final int EVENT_BROADCAST_COMPLETE = 3;
    133 
    134     /** Sent on exit from {@link WaitingState} to return to idle after sending all broadcasts. */
    135     static final int EVENT_RETURN_TO_IDLE = 4;
    136 
    137     /** Release wakelock after a short timeout when returning to idle state. */
    138     static final int EVENT_RELEASE_WAKELOCK = 5;
    139 
    140     /** Sent by {@link SmsBroadcastUndelivered} after cleaning the raw table. */
    141     static final int EVENT_START_ACCEPTING_SMS = 6;
    142 
    143     /** Update phone object */
    144     static final int EVENT_UPDATE_PHONE_OBJECT = 7;
    145 
    146     /** New SMS received as an AsyncResult. */
    147     public static final int EVENT_INJECT_SMS = 8;
    148 
    149     /** Wakelock release delay when returning to idle state. */
    150     private static final int WAKELOCK_TIMEOUT = 3000;
    151 
    152     /** URI for raw table of SMS provider. */
    153     private static final Uri sRawUri = Uri.withAppendedPath(Telephony.Sms.CONTENT_URI, "raw");
    154 
    155     protected final Context mContext;
    156     private final ContentResolver mResolver;
    157 
    158     /** Special handler for WAP push messages. */
    159     private final WapPushOverSms mWapPush;
    160 
    161     /** Wake lock to ensure device stays awake while dispatching the SMS intents. */
    162     final PowerManager.WakeLock mWakeLock;
    163 
    164     /** DefaultState throws an exception or logs an error for unhandled message types. */
    165     final DefaultState mDefaultState = new DefaultState();
    166 
    167     /** Startup state. Waiting for {@link SmsBroadcastUndelivered} to complete. */
    168     final StartupState mStartupState = new StartupState();
    169 
    170     /** Idle state. Waiting for messages to process. */
    171     final IdleState mIdleState = new IdleState();
    172 
    173     /** Delivering state. Saves the PDU in the raw table and acknowledges to SMSC. */
    174     final DeliveringState mDeliveringState = new DeliveringState();
    175 
    176     /** Broadcasting state. Waits for current broadcast to complete before delivering next. */
    177     final WaitingState mWaitingState = new WaitingState();
    178 
    179     /** Helper class to check whether storage is available for incoming messages. */
    180     protected SmsStorageMonitor mStorageMonitor;
    181 
    182     private final boolean mSmsReceiveDisabled;
    183 
    184     protected PhoneBase mPhone;
    185 
    186     protected CellBroadcastHandler mCellBroadcastHandler;
    187 
    188     private UserManager mUserManager;
    189 
    190     /**
    191      * Create a new SMS broadcast helper.
    192      * @param name the class name for logging
    193      * @param context the context of the phone app
    194      * @param storageMonitor the SmsStorageMonitor to check for storage availability
    195      */
    196     protected InboundSmsHandler(String name, Context context, SmsStorageMonitor storageMonitor,
    197             PhoneBase phone, CellBroadcastHandler cellBroadcastHandler) {
    198         super(name);
    199 
    200         mContext = context;
    201         mStorageMonitor = storageMonitor;
    202         mPhone = phone;
    203         mCellBroadcastHandler = cellBroadcastHandler;
    204         mResolver = context.getContentResolver();
    205         mWapPush = new WapPushOverSms(context);
    206 
    207         boolean smsCapable = mContext.getResources().getBoolean(
    208                 com.android.internal.R.bool.config_sms_capable);
    209         mSmsReceiveDisabled = !TelephonyManager.from(mContext).getSmsReceiveCapableForPhone(
    210                 mPhone.getPhoneId(), smsCapable);
    211 
    212         PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
    213         mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, name);
    214         mWakeLock.acquire();    // wake lock released after we enter idle state
    215         mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
    216 
    217         addState(mDefaultState);
    218         addState(mStartupState, mDefaultState);
    219         addState(mIdleState, mDefaultState);
    220         addState(mDeliveringState, mDefaultState);
    221             addState(mWaitingState, mDeliveringState);
    222 
    223         setInitialState(mStartupState);
    224         if (DBG) log("created InboundSmsHandler");
    225     }
    226 
    227     /**
    228      * Tell the state machine to quit after processing all messages.
    229      */
    230     public void dispose() {
    231         quit();
    232     }
    233 
    234     /**
    235      * Update the phone object when it changes.
    236      */
    237     public void updatePhoneObject(PhoneBase phone) {
    238         sendMessage(EVENT_UPDATE_PHONE_OBJECT, phone);
    239     }
    240 
    241     /**
    242      * Dispose of the WAP push object and release the wakelock.
    243      */
    244     @Override
    245     protected void onQuitting() {
    246         mWapPush.dispose();
    247 
    248         while (mWakeLock.isHeld()) {
    249             mWakeLock.release();
    250         }
    251     }
    252 
    253     // CAF_MSIM Is this used anywhere ? if not remove it
    254     public PhoneBase getPhone() {
    255         return mPhone;
    256     }
    257 
    258     /**
    259      * This parent state throws an exception (for debug builds) or prints an error for unhandled
    260      * message types.
    261      */
    262     class DefaultState extends State {
    263         @Override
    264         public boolean processMessage(Message msg) {
    265             switch (msg.what) {
    266                 case EVENT_UPDATE_PHONE_OBJECT: {
    267                     onUpdatePhoneObject((PhoneBase) msg.obj);
    268                     break;
    269                 }
    270                 default: {
    271                     String errorText = "processMessage: unhandled message type " + msg.what +
    272                         " currState=" + getCurrentState().getName();
    273                     if (Build.IS_DEBUGGABLE) {
    274                         loge("---- Dumping InboundSmsHandler ----");
    275                         loge("Total records=" + getLogRecCount());
    276                         for (int i = Math.max(getLogRecSize() - 20, 0); i < getLogRecSize(); i++) {
    277                             loge("Rec[%d]: %s\n" + i + getLogRec(i).toString());
    278                         }
    279                         loge("---- Dumped InboundSmsHandler ----");
    280 
    281                         throw new RuntimeException(errorText);
    282                     } else {
    283                         loge(errorText);
    284                     }
    285                     break;
    286                 }
    287             }
    288             return HANDLED;
    289         }
    290     }
    291 
    292     /**
    293      * The Startup state waits for {@link SmsBroadcastUndelivered} to process the raw table and
    294      * notify the state machine to broadcast any complete PDUs that might not have been broadcast.
    295      */
    296     class StartupState extends State {
    297         @Override
    298         public boolean processMessage(Message msg) {
    299             log("StartupState.processMessage:" + msg.what);
    300             switch (msg.what) {
    301                 case EVENT_NEW_SMS:
    302                 case EVENT_INJECT_SMS:
    303                 case EVENT_BROADCAST_SMS:
    304                     deferMessage(msg);
    305                     return HANDLED;
    306 
    307                 case EVENT_START_ACCEPTING_SMS:
    308                     transitionTo(mIdleState);
    309                     return HANDLED;
    310 
    311                 case EVENT_BROADCAST_COMPLETE:
    312                 case EVENT_RETURN_TO_IDLE:
    313                 case EVENT_RELEASE_WAKELOCK:
    314                 default:
    315                     // let DefaultState handle these unexpected message types
    316                     return NOT_HANDLED;
    317             }
    318         }
    319     }
    320 
    321     /**
    322      * In the idle state the wakelock is released until a new SM arrives, then we transition
    323      * to Delivering mode to handle it, acquiring the wakelock on exit.
    324      */
    325     class IdleState extends State {
    326         @Override
    327         public void enter() {
    328             if (DBG) log("entering Idle state");
    329             sendMessageDelayed(EVENT_RELEASE_WAKELOCK, WAKELOCK_TIMEOUT);
    330         }
    331 
    332         @Override
    333         public void exit() {
    334             mWakeLock.acquire();
    335             if (DBG) log("acquired wakelock, leaving Idle state");
    336         }
    337 
    338         @Override
    339         public boolean processMessage(Message msg) {
    340             log("IdleState.processMessage:" + msg.what);
    341             if (DBG) log("Idle state processing message type " + msg.what);
    342             switch (msg.what) {
    343                 case EVENT_NEW_SMS:
    344                 case EVENT_INJECT_SMS:
    345                 case EVENT_BROADCAST_SMS:
    346                     deferMessage(msg);
    347                     transitionTo(mDeliveringState);
    348                     return HANDLED;
    349 
    350                 case EVENT_RELEASE_WAKELOCK:
    351                     mWakeLock.release();
    352                     if (DBG) {
    353                         if (mWakeLock.isHeld()) {
    354                             // this is okay as long as we call release() for every acquire()
    355                             log("mWakeLock is still held after release");
    356                         } else {
    357                             log("mWakeLock released");
    358                         }
    359                     }
    360                     return HANDLED;
    361 
    362                 case EVENT_RETURN_TO_IDLE:
    363                     // already in idle state; ignore
    364                     return HANDLED;
    365 
    366                 case EVENT_BROADCAST_COMPLETE:
    367                 case EVENT_START_ACCEPTING_SMS:
    368                 default:
    369                     // let DefaultState handle these unexpected message types
    370                     return NOT_HANDLED;
    371             }
    372         }
    373     }
    374 
    375     /**
    376      * In the delivering state, the inbound SMS is processed and stored in the raw table.
    377      * The message is acknowledged before we exit this state. If there is a message to broadcast,
    378      * transition to {@link WaitingState} state to send the ordered broadcast and wait for the
    379      * results. When all messages have been processed, the halting state will release the wakelock.
    380      */
    381     class DeliveringState extends State {
    382         @Override
    383         public void enter() {
    384             if (DBG) log("entering Delivering state");
    385         }
    386 
    387         @Override
    388         public void exit() {
    389             if (DBG) log("leaving Delivering state");
    390         }
    391 
    392         @Override
    393         public boolean processMessage(Message msg) {
    394             log("DeliveringState.processMessage:" + msg.what);
    395             switch (msg.what) {
    396                 case EVENT_NEW_SMS:
    397                     // handle new SMS from RIL
    398                     handleNewSms((AsyncResult) msg.obj);
    399                     sendMessage(EVENT_RETURN_TO_IDLE);
    400                     return HANDLED;
    401 
    402                 case EVENT_INJECT_SMS:
    403                     // handle new injected SMS
    404                     handleInjectSms((AsyncResult) msg.obj);
    405                     sendMessage(EVENT_RETURN_TO_IDLE);
    406                     return HANDLED;
    407 
    408                 case EVENT_BROADCAST_SMS:
    409                     // if any broadcasts were sent, transition to waiting state
    410                     if (processMessagePart((InboundSmsTracker) msg.obj)) {
    411                         transitionTo(mWaitingState);
    412                     }
    413                     return HANDLED;
    414 
    415                 case EVENT_RETURN_TO_IDLE:
    416                     // return to idle after processing all other messages
    417                     transitionTo(mIdleState);
    418                     return HANDLED;
    419 
    420                 case EVENT_RELEASE_WAKELOCK:
    421                     mWakeLock.release();    // decrement wakelock from previous entry to Idle
    422                     if (!mWakeLock.isHeld()) {
    423                         // wakelock should still be held until 3 seconds after we enter Idle
    424                         loge("mWakeLock released while delivering/broadcasting!");
    425                     }
    426                     return HANDLED;
    427 
    428                 // we shouldn't get this message type in this state, log error and halt.
    429                 case EVENT_BROADCAST_COMPLETE:
    430                 case EVENT_START_ACCEPTING_SMS:
    431                 default:
    432                     // let DefaultState handle these unexpected message types
    433                     return NOT_HANDLED;
    434             }
    435         }
    436     }
    437 
    438     /**
    439      * The waiting state delegates handling of new SMS to parent {@link DeliveringState}, but
    440      * defers handling of the {@link #EVENT_BROADCAST_SMS} phase until after the current
    441      * result receiver sends {@link #EVENT_BROADCAST_COMPLETE}. Before transitioning to
    442      * {@link DeliveringState}, {@link #EVENT_RETURN_TO_IDLE} is sent to transition to
    443      * {@link IdleState} after any deferred {@link #EVENT_BROADCAST_SMS} messages are handled.
    444      */
    445     class WaitingState extends State {
    446         @Override
    447         public boolean processMessage(Message msg) {
    448             log("WaitingState.processMessage:" + msg.what);
    449             switch (msg.what) {
    450                 case EVENT_BROADCAST_SMS:
    451                     // defer until the current broadcast completes
    452                     deferMessage(msg);
    453                     return HANDLED;
    454 
    455                 case EVENT_BROADCAST_COMPLETE:
    456                     // return to idle after handling all deferred messages
    457                     sendMessage(EVENT_RETURN_TO_IDLE);
    458                     transitionTo(mDeliveringState);
    459                     return HANDLED;
    460 
    461                 case EVENT_RETURN_TO_IDLE:
    462                     // not ready to return to idle; ignore
    463                     return HANDLED;
    464 
    465                 default:
    466                     // parent state handles the other message types
    467                     return NOT_HANDLED;
    468             }
    469         }
    470     }
    471 
    472     void handleNewSms(AsyncResult ar) {
    473         if (ar.exception != null) {
    474             loge("Exception processing incoming SMS: " + ar.exception);
    475             return;
    476         }
    477 
    478         int result;
    479         try {
    480             SmsMessage sms = (SmsMessage) ar.result;
    481             result = dispatchMessage(sms.mWrappedSmsMessage);
    482         } catch (RuntimeException ex) {
    483             loge("Exception dispatching message", ex);
    484             result = Intents.RESULT_SMS_GENERIC_ERROR;
    485         }
    486 
    487         // RESULT_OK means that the SMS will be acknowledged by special handling,
    488         // e.g. for SMS-PP data download. Any other result, we should ack here.
    489         if (result != Activity.RESULT_OK) {
    490             boolean handled = (result == Intents.RESULT_SMS_HANDLED);
    491             notifyAndAcknowledgeLastIncomingSms(handled, result, null);
    492         }
    493     }
    494 
    495     /**
    496      * This method is called when a new SMS PDU is injected into application framework.
    497      * @param ar is the AsyncResult that has the SMS PDU to be injected.
    498      */
    499     void handleInjectSms(AsyncResult ar) {
    500         int result;
    501         PendingIntent receivedIntent = null;
    502         try {
    503             receivedIntent = (PendingIntent) ar.userObj;
    504             SmsMessage sms = (SmsMessage) ar.result;
    505             if (sms == null) {
    506               result = Intents.RESULT_SMS_GENERIC_ERROR;
    507             } else {
    508               result = dispatchMessage(sms.mWrappedSmsMessage);
    509             }
    510         } catch (RuntimeException ex) {
    511             loge("Exception dispatching message", ex);
    512             result = Intents.RESULT_SMS_GENERIC_ERROR;
    513         }
    514 
    515         if (receivedIntent != null) {
    516             try {
    517                 receivedIntent.send(result);
    518             } catch (CanceledException e) { }
    519         }
    520     }
    521 
    522     /**
    523      * Process an SMS message from the RIL, calling subclass methods to handle 3GPP and
    524      * 3GPP2-specific message types.
    525      *
    526      * @param smsb the SmsMessageBase object from the RIL
    527      * @return a result code from {@link android.provider.Telephony.Sms.Intents},
    528      *  or {@link Activity#RESULT_OK} for delayed acknowledgment to SMSC
    529      */
    530     public int dispatchMessage(SmsMessageBase smsb) {
    531         // If sms is null, there was a parsing error.
    532         if (smsb == null) {
    533             loge("dispatchSmsMessage: message is null");
    534             return Intents.RESULT_SMS_GENERIC_ERROR;
    535         }
    536 
    537         if (mSmsReceiveDisabled) {
    538             // Device doesn't support receiving SMS,
    539             log("Received short message on device which doesn't support "
    540                     + "receiving SMS. Ignored.");
    541             return Intents.RESULT_SMS_HANDLED;
    542         }
    543 
    544         return dispatchMessageRadioSpecific(smsb);
    545     }
    546 
    547     /**
    548      * Process voicemail notification, SMS-PP data download, CDMA CMAS, CDMA WAP push, and other
    549      * 3GPP/3GPP2-specific messages. Regular SMS messages are handled by calling the shared
    550      * {@link #dispatchNormalMessage} from this class.
    551      *
    552      * @param smsb the SmsMessageBase object from the RIL
    553      * @return a result code from {@link android.provider.Telephony.Sms.Intents},
    554      *  or {@link Activity#RESULT_OK} for delayed acknowledgment to SMSC
    555      */
    556     protected abstract int dispatchMessageRadioSpecific(SmsMessageBase smsb);
    557 
    558     /**
    559      * Send an acknowledge message to the SMSC.
    560      * @param success indicates that last message was successfully received.
    561      * @param result result code indicating any error
    562      * @param response callback message sent when operation completes.
    563      */
    564     protected abstract void acknowledgeLastIncomingSms(boolean success,
    565             int result, Message response);
    566 
    567     /**
    568      * Called when the phone changes the default method updates mPhone
    569      * mStorageMonitor and mCellBroadcastHandler.updatePhoneObject.
    570      * Override if different or other behavior is desired.
    571      *
    572      * @param phone
    573      */
    574     protected void onUpdatePhoneObject(PhoneBase phone) {
    575         mPhone = phone;
    576         mStorageMonitor = mPhone.mSmsStorageMonitor;
    577         log("onUpdatePhoneObject: phone=" + mPhone.getClass().getSimpleName());
    578     }
    579 
    580     /**
    581      * Notify interested apps if the framework has rejected an incoming SMS,
    582      * and send an acknowledge message to the network.
    583      * @param success indicates that last message was successfully received.
    584      * @param result result code indicating any error
    585      * @param response callback message sent when operation completes.
    586      */
    587     void notifyAndAcknowledgeLastIncomingSms(boolean success,
    588             int result, Message response) {
    589         if (!success) {
    590             // broadcast SMS_REJECTED_ACTION intent
    591             Intent intent = new Intent(Intents.SMS_REJECTED_ACTION);
    592             intent.putExtra("result", result);
    593             mContext.sendBroadcast(intent, android.Manifest.permission.RECEIVE_SMS);
    594         }
    595         acknowledgeLastIncomingSms(success, result, response);
    596     }
    597 
    598     /**
    599      * Return true if this handler is for 3GPP2 messages; false for 3GPP format.
    600      * @return true for the 3GPP2 handler; false for the 3GPP handler
    601      */
    602     protected abstract boolean is3gpp2();
    603 
    604     /**
    605      * Dispatch a normal incoming SMS. This is called from {@link #dispatchMessageRadioSpecific}
    606      * if no format-specific handling was required. Saves the PDU to the SMS provider raw table,
    607      * creates an {@link InboundSmsTracker}, then sends it to the state machine as an
    608      * {@link #EVENT_BROADCAST_SMS}. Returns {@link Intents#RESULT_SMS_HANDLED} or an error value.
    609      *
    610      * @param sms the message to dispatch
    611      * @return {@link Intents#RESULT_SMS_HANDLED} if the message was accepted, or an error status
    612      */
    613     protected int dispatchNormalMessage(SmsMessageBase sms) {
    614         SmsHeader smsHeader = sms.getUserDataHeader();
    615         InboundSmsTracker tracker;
    616 
    617         if ((smsHeader == null) || (smsHeader.concatRef == null)) {
    618             // Message is not concatenated.
    619             int destPort = -1;
    620             if (smsHeader != null && smsHeader.portAddrs != null) {
    621                 // The message was sent to a port.
    622                 destPort = smsHeader.portAddrs.destPort;
    623                 if (DBG) log("destination port: " + destPort);
    624             }
    625 
    626             tracker = new InboundSmsTracker(sms.getPdu(), sms.getTimestampMillis(), destPort,
    627                     is3gpp2(), false);
    628         } else {
    629             // Create a tracker for this message segment.
    630             SmsHeader.ConcatRef concatRef = smsHeader.concatRef;
    631             SmsHeader.PortAddrs portAddrs = smsHeader.portAddrs;
    632             int destPort = (portAddrs != null ? portAddrs.destPort : -1);
    633 
    634             tracker = new InboundSmsTracker(sms.getPdu(), sms.getTimestampMillis(), destPort,
    635                     is3gpp2(), sms.getOriginatingAddress(), concatRef.refNumber,
    636                     concatRef.seqNumber, concatRef.msgCount, false);
    637         }
    638 
    639         if (VDBG) log("created tracker: " + tracker);
    640         return addTrackerToRawTableAndSendMessage(tracker);
    641     }
    642 
    643     /**
    644      * Helper to add the tracker to the raw table and then send a message to broadcast it, if
    645      * successful. Returns the SMS intent status to return to the SMSC.
    646      * @param tracker the tracker to save to the raw table and then deliver
    647      * @return {@link Intents#RESULT_SMS_HANDLED} or {@link Intents#RESULT_SMS_GENERIC_ERROR}
    648      * or {@link Intents#RESULT_SMS_DUPLICATED}
    649      */
    650     protected int addTrackerToRawTableAndSendMessage(InboundSmsTracker tracker) {
    651         switch(addTrackerToRawTable(tracker)) {
    652         case Intents.RESULT_SMS_HANDLED:
    653             sendMessage(EVENT_BROADCAST_SMS, tracker);
    654             return Intents.RESULT_SMS_HANDLED;
    655 
    656         case Intents.RESULT_SMS_DUPLICATED:
    657             return Intents.RESULT_SMS_HANDLED;
    658 
    659         case Intents.RESULT_SMS_GENERIC_ERROR:
    660         default:
    661             return Intents.RESULT_SMS_GENERIC_ERROR;
    662         }
    663     }
    664 
    665     /**
    666      * Process the inbound SMS segment. If the message is complete, send it as an ordered
    667      * broadcast to interested receivers and return true. If the message is a segment of an
    668      * incomplete multi-part SMS, return false.
    669      * @param tracker the tracker containing the message segment to process
    670      * @return true if an ordered broadcast was sent; false if waiting for more message segments
    671      */
    672     boolean processMessagePart(InboundSmsTracker tracker) {
    673         int messageCount = tracker.getMessageCount();
    674         byte[][] pdus;
    675         int destPort = tracker.getDestPort();
    676 
    677         if (messageCount == 1) {
    678             // single-part message
    679             pdus = new byte[][]{tracker.getPdu()};
    680         } else {
    681             // multi-part message
    682             Cursor cursor = null;
    683             try {
    684                 // used by several query selection arguments
    685                 String address = tracker.getAddress();
    686                 String refNumber = Integer.toString(tracker.getReferenceNumber());
    687                 String count = Integer.toString(tracker.getMessageCount());
    688 
    689                 // query for all segments and broadcast message if we have all the parts
    690                 String[] whereArgs = {address, refNumber, count};
    691                 cursor = mResolver.query(sRawUri, PDU_SEQUENCE_PORT_PROJECTION,
    692                         SELECT_BY_REFERENCE, whereArgs, null);
    693 
    694                 int cursorCount = cursor.getCount();
    695                 if (cursorCount < messageCount) {
    696                     // Wait for the other message parts to arrive. It's also possible for the last
    697                     // segment to arrive before processing the EVENT_BROADCAST_SMS for one of the
    698                     // earlier segments. In that case, the broadcast will be sent as soon as all
    699                     // segments are in the table, and any later EVENT_BROADCAST_SMS messages will
    700                     // get a row count of 0 and return.
    701                     return false;
    702                 }
    703 
    704                 // All the parts are in place, deal with them
    705                 pdus = new byte[messageCount][];
    706                 while (cursor.moveToNext()) {
    707                     // subtract offset to convert sequence to 0-based array index
    708                     int index = cursor.getInt(SEQUENCE_COLUMN) - tracker.getIndexOffset();
    709 
    710                     pdus[index] = HexDump.hexStringToByteArray(cursor.getString(PDU_COLUMN));
    711 
    712                     // Read the destination port from the first segment (needed for CDMA WAP PDU).
    713                     // It's not a bad idea to prefer the port from the first segment in other cases.
    714                     if (index == 0 && !cursor.isNull(DESTINATION_PORT_COLUMN)) {
    715                         int port = cursor.getInt(DESTINATION_PORT_COLUMN);
    716                         // strip format flags and convert to real port number, or -1
    717                         port = InboundSmsTracker.getRealDestPort(port);
    718                         if (port != -1) {
    719                             destPort = port;
    720                         }
    721                     }
    722                 }
    723             } catch (SQLException e) {
    724                 loge("Can't access multipart SMS database", e);
    725                 return false;
    726             } finally {
    727                 if (cursor != null) {
    728                     cursor.close();
    729                 }
    730             }
    731         }
    732 
    733         SmsBroadcastReceiver resultReceiver = new SmsBroadcastReceiver(tracker);
    734 
    735         if (destPort == SmsHeader.PORT_WAP_PUSH) {
    736             // Build up the data stream
    737             ByteArrayOutputStream output = new ByteArrayOutputStream();
    738             for (byte[] pdu : pdus) {
    739                 // 3GPP needs to extract the User Data from the PDU; 3GPP2 has already done this
    740                 if (!tracker.is3gpp2()) {
    741                     SmsMessage msg = SmsMessage.createFromPdu(pdu, SmsConstants.FORMAT_3GPP);
    742                     pdu = msg.getUserData();
    743                 }
    744                 output.write(pdu, 0, pdu.length);
    745             }
    746             int result = mWapPush.dispatchWapPdu(output.toByteArray(), resultReceiver, this);
    747             if (DBG) log("dispatchWapPdu() returned " + result);
    748             // result is Activity.RESULT_OK if an ordered broadcast was sent
    749             return (result == Activity.RESULT_OK);
    750         }
    751 
    752         List<String> carrierPackages = null;
    753         UiccCard card = UiccController.getInstance().getUiccCard(mPhone.getPhoneId());
    754         if (card != null) {
    755             carrierPackages = card.getCarrierPackageNamesForIntent(
    756                     mContext.getPackageManager(),
    757                     new Intent(CarrierMessagingService.SERVICE_INTERFACE));
    758         } else {
    759             loge("UiccCard not initialized.");
    760         }
    761 
    762         List<String> systemPackages =
    763                 getSystemAppForIntent(new Intent(CarrierMessagingService.SERVICE_INTERFACE));
    764 
    765         if (carrierPackages != null && carrierPackages.size() == 1) {
    766             log("Found carrier package.");
    767             CarrierSmsFilter smsFilter = new CarrierSmsFilter(pdus, destPort,
    768                     tracker.getFormat(), resultReceiver);
    769             CarrierSmsFilterCallback smsFilterCallback = new CarrierSmsFilterCallback(smsFilter);
    770             smsFilter.filterSms(carrierPackages.get(0), smsFilterCallback);
    771         } else if (systemPackages != null && systemPackages.size() == 1) {
    772             log("Found system package.");
    773             CarrierSmsFilter smsFilter = new CarrierSmsFilter(pdus, destPort,
    774                     tracker.getFormat(), resultReceiver);
    775             CarrierSmsFilterCallback smsFilterCallback = new CarrierSmsFilterCallback(smsFilter);
    776             smsFilter.filterSms(systemPackages.get(0), smsFilterCallback);
    777         } else {
    778             logv("Unable to find carrier package: " + carrierPackages
    779                     + ", nor systemPackages: " + systemPackages);
    780             dispatchSmsDeliveryIntent(pdus, tracker.getFormat(), destPort, resultReceiver);
    781         }
    782 
    783         return true;
    784     }
    785 
    786     private List<String> getSystemAppForIntent(Intent intent) {
    787         List<String> packages = new ArrayList<String>();
    788         PackageManager packageManager = mContext.getPackageManager();
    789         List<ResolveInfo> receivers = packageManager.queryIntentServices(intent, 0);
    790         String carrierFilterSmsPerm = "android.permission.CARRIER_FILTER_SMS";
    791 
    792         for (ResolveInfo info : receivers) {
    793             if (info.serviceInfo == null) {
    794                 loge("Can't get service information from " + info);
    795                 continue;
    796             }
    797             String packageName = info.serviceInfo.packageName;
    798                 if (packageManager.checkPermission(carrierFilterSmsPerm, packageName) ==
    799                         packageManager.PERMISSION_GRANTED) {
    800                     packages.add(packageName);
    801                     if (DBG) log("getSystemAppForIntent: added package "+ packageName);
    802                 }
    803         }
    804         return packages;
    805     }
    806 
    807     /**
    808      * Dispatch the intent with the specified permission, appOp, and result receiver, using
    809      * this state machine's handler thread to run the result receiver.
    810      *
    811      * @param intent the intent to broadcast
    812      * @param permission receivers are required to have this permission
    813      * @param appOp app op that is being performed when dispatching to a receiver
    814      * @param user user to deliver the intent to
    815      */
    816     protected void dispatchIntent(Intent intent, String permission, int appOp,
    817             BroadcastReceiver resultReceiver, UserHandle user) {
    818         intent.addFlags(Intent.FLAG_RECEIVER_NO_ABORT);
    819         SubscriptionManager.putPhoneIdAndSubIdExtra(intent, mPhone.getPhoneId());
    820         if (user.equals(UserHandle.ALL)) {
    821             // Get a list of currently started users.
    822             int[] users = null;
    823             try {
    824                 users = ActivityManagerNative.getDefault().getRunningUserIds();
    825             } catch (RemoteException re) {
    826             }
    827             if (users == null) {
    828                 users = new int[] {user.getIdentifier()};
    829             }
    830             // Deliver the broadcast only to those running users that are permitted
    831             // by user policy.
    832             for (int i = users.length - 1; i >= 0; i--) {
    833                 UserHandle targetUser = new UserHandle(users[i]);
    834                 if (users[i] != UserHandle.USER_OWNER) {
    835                     // Is the user not allowed to use SMS?
    836                     if (mUserManager.hasUserRestriction(UserManager.DISALLOW_SMS, targetUser)) {
    837                         continue;
    838                     }
    839                     // Skip unknown users and managed profiles as well
    840                     UserInfo info = mUserManager.getUserInfo(users[i]);
    841                     if (info == null || info.isManagedProfile()) {
    842                         continue;
    843                     }
    844                 }
    845                 // Only pass in the resultReceiver when the USER_OWNER is processed.
    846                 mContext.sendOrderedBroadcastAsUser(intent, targetUser, permission, appOp,
    847                         users[i] == UserHandle.USER_OWNER ? resultReceiver : null,
    848                         getHandler(), Activity.RESULT_OK, null, null);
    849             }
    850         } else {
    851             mContext.sendOrderedBroadcastAsUser(intent, user, permission, appOp,
    852                     resultReceiver,
    853                     getHandler(), Activity.RESULT_OK, null, null);
    854         }
    855     }
    856 
    857     /**
    858      * Helper for {@link SmsBroadcastUndelivered} to delete an old message in the raw table.
    859      */
    860     void deleteFromRawTable(String deleteWhere, String[] deleteWhereArgs) {
    861         int rows = mResolver.delete(sRawUri, deleteWhere, deleteWhereArgs);
    862         if (rows == 0) {
    863             loge("No rows were deleted from raw table!");
    864         } else if (DBG) {
    865             log("Deleted " + rows + " rows from raw table.");
    866         }
    867     }
    868 
    869     /**
    870      * Creates and dispatches the intent to the default SMS app or the appropriate port.
    871      *
    872      * @param pdus message pdus
    873      * @param format the message format, typically "3gpp" or "3gpp2"
    874      * @param destPort the destination port
    875      * @param resultReceiver the receiver handling the delivery result
    876      */
    877     void dispatchSmsDeliveryIntent(byte[][] pdus, String format, int destPort,
    878             BroadcastReceiver resultReceiver) {
    879         Intent intent = new Intent();
    880         intent.putExtra("pdus", pdus);
    881         intent.putExtra("format", format);
    882 
    883         if (destPort == -1) {
    884             intent.setAction(Intents.SMS_DELIVER_ACTION);
    885             // Direct the intent to only the default SMS app. If we can't find a default SMS app
    886             // then sent it to all broadcast receivers.
    887             // We are deliberately delivering to the primary user's default SMS App.
    888             ComponentName componentName = SmsApplication.getDefaultSmsApplication(mContext, true);
    889             if (componentName != null) {
    890                 // Deliver SMS message only to this receiver.
    891                 intent.setComponent(componentName);
    892                 log("Delivering SMS to: " + componentName.getPackageName() +
    893                     " " + componentName.getClassName());
    894             } else {
    895                 intent.setComponent(null);
    896             }
    897 
    898             // TODO: Validate that this is the right place to store the SMS.
    899             if (SmsManager.getDefault().getAutoPersisting()) {
    900                 final Uri uri = writeInboxMessage(intent);
    901                 if (uri != null) {
    902                     // Pass this to SMS apps so that they know where it is stored
    903                     intent.putExtra("uri", uri.toString());
    904                 }
    905             }
    906         } else {
    907             intent.setAction(Intents.DATA_SMS_RECEIVED_ACTION);
    908             Uri uri = Uri.parse("sms://localhost:" + destPort);
    909             intent.setData(uri);
    910             intent.setComponent(null);
    911         }
    912 
    913         dispatchIntent(intent, android.Manifest.permission.RECEIVE_SMS,
    914                 AppOpsManager.OP_RECEIVE_SMS, resultReceiver, UserHandle.OWNER);
    915     }
    916 
    917     /**
    918      * Insert a message PDU into the raw table so we can acknowledge it immediately.
    919      * If the device crashes before the broadcast to listeners completes, it will be delivered
    920      * from the raw table on the next device boot. For single-part messages, the deleteWhere
    921      * and deleteWhereArgs fields of the tracker will be set to delete the correct row after
    922      * the ordered broadcast completes.
    923      *
    924      * @param tracker the tracker to add to the raw table
    925      * @return true on success; false on failure to write to database
    926      */
    927     private int addTrackerToRawTable(InboundSmsTracker tracker) {
    928         if (tracker.getMessageCount() != 1) {
    929             // check for duplicate message segments
    930             Cursor cursor = null;
    931             try {
    932                 // sequence numbers are 1-based except for CDMA WAP, which is 0-based
    933                 int sequence = tracker.getSequenceNumber();
    934 
    935                 // convert to strings for query
    936                 String address = tracker.getAddress();
    937                 String refNumber = Integer.toString(tracker.getReferenceNumber());
    938                 String count = Integer.toString(tracker.getMessageCount());
    939 
    940                 String seqNumber = Integer.toString(sequence);
    941 
    942                 // set the delete selection args for multi-part message
    943                 String[] deleteWhereArgs = {address, refNumber, count};
    944                 tracker.setDeleteWhere(SELECT_BY_REFERENCE, deleteWhereArgs);
    945 
    946                 // Check for duplicate message segments
    947                 cursor = mResolver.query(sRawUri, PDU_PROJECTION,
    948                         "address=? AND reference_number=? AND count=? AND sequence=?",
    949                         new String[] {address, refNumber, count, seqNumber}, null);
    950 
    951                 // moveToNext() returns false if no duplicates were found
    952                 if (cursor.moveToNext()) {
    953                     loge("Discarding duplicate message segment, refNumber=" + refNumber
    954                             + " seqNumber=" + seqNumber);
    955                     String oldPduString = cursor.getString(PDU_COLUMN);
    956                     byte[] pdu = tracker.getPdu();
    957                     byte[] oldPdu = HexDump.hexStringToByteArray(oldPduString);
    958                     if (!Arrays.equals(oldPdu, tracker.getPdu())) {
    959                         loge("Warning: dup message segment PDU of length " + pdu.length
    960                                 + " is different from existing PDU of length " + oldPdu.length);
    961                     }
    962                     return Intents.RESULT_SMS_DUPLICATED;   // reject message
    963                 }
    964                 cursor.close();
    965             } catch (SQLException e) {
    966                 loge("Can't access multipart SMS database", e);
    967                 return Intents.RESULT_SMS_GENERIC_ERROR;    // reject message
    968             } finally {
    969                 if (cursor != null) {
    970                     cursor.close();
    971                 }
    972             }
    973         }
    974 
    975         ContentValues values = tracker.getContentValues();
    976 
    977         if (VDBG) log("adding content values to raw table: " + values.toString());
    978         Uri newUri = mResolver.insert(sRawUri, values);
    979         if (DBG) log("URI of new row -> " + newUri);
    980 
    981         try {
    982             long rowId = ContentUris.parseId(newUri);
    983             if (tracker.getMessageCount() == 1) {
    984                 // set the delete selection args for single-part message
    985                 tracker.setDeleteWhere(SELECT_BY_ID, new String[]{Long.toString(rowId)});
    986             }
    987             return Intents.RESULT_SMS_HANDLED;
    988         } catch (Exception e) {
    989             loge("error parsing URI for new row: " + newUri, e);
    990             return Intents.RESULT_SMS_GENERIC_ERROR;
    991         }
    992     }
    993 
    994     /**
    995      * Returns whether the default message format for the current radio technology is 3GPP2.
    996      * @return true if the radio technology uses 3GPP2 format by default, false for 3GPP format
    997      */
    998     static boolean isCurrentFormat3gpp2() {
    999         int activePhone = TelephonyManager.getDefault().getCurrentPhoneType();
   1000         return (PHONE_TYPE_CDMA == activePhone);
   1001     }
   1002 
   1003     protected void storeVoiceMailCount() {
   1004         // Store the voice mail count in persistent memory.
   1005         String imsi = mPhone.getSubscriberId();
   1006         int mwi = mPhone.getVoiceMessageCount();
   1007 
   1008         log("Storing Voice Mail Count = " + mwi
   1009                     + " for mVmCountKey = " + mPhone.VM_COUNT
   1010                     + " vmId = " + mPhone.VM_ID
   1011                     + " in preferences.");
   1012 
   1013         SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(mContext);
   1014         SharedPreferences.Editor editor = sp.edit();
   1015         editor.putInt(mPhone.VM_COUNT, mwi);
   1016         editor.putString(mPhone.VM_ID, imsi);
   1017         editor.commit();
   1018     }
   1019 
   1020     /**
   1021      * Handler for an {@link InboundSmsTracker} broadcast. Deletes PDUs from the raw table and
   1022      * logs the broadcast duration (as an error if the other receivers were especially slow).
   1023      */
   1024     private final class SmsBroadcastReceiver extends BroadcastReceiver {
   1025         private final String mDeleteWhere;
   1026         private final String[] mDeleteWhereArgs;
   1027         private long mBroadcastTimeNano;
   1028 
   1029         SmsBroadcastReceiver(InboundSmsTracker tracker) {
   1030             mDeleteWhere = tracker.getDeleteWhere();
   1031             mDeleteWhereArgs = tracker.getDeleteWhereArgs();
   1032             mBroadcastTimeNano = System.nanoTime();
   1033         }
   1034 
   1035         @Override
   1036         public void onReceive(Context context, Intent intent) {
   1037             String action = intent.getAction();
   1038             if (action.equals(Intents.SMS_DELIVER_ACTION)) {
   1039                 // Now dispatch the notification only intent
   1040                 intent.setAction(Intents.SMS_RECEIVED_ACTION);
   1041                 intent.setComponent(null);
   1042                 // All running users will be notified of the received sms.
   1043                 dispatchIntent(intent, android.Manifest.permission.RECEIVE_SMS,
   1044                         AppOpsManager.OP_RECEIVE_SMS, this, UserHandle.ALL);
   1045             } else if (action.equals(Intents.WAP_PUSH_DELIVER_ACTION)) {
   1046                 // Now dispatch the notification only intent
   1047                 intent.setAction(Intents.WAP_PUSH_RECEIVED_ACTION);
   1048                 intent.setComponent(null);
   1049                 // Only the primary user will receive notification of incoming mms.
   1050                 // That app will do the actual downloading of the mms.
   1051                 dispatchIntent(intent, android.Manifest.permission.RECEIVE_SMS,
   1052                         AppOpsManager.OP_RECEIVE_SMS, this, UserHandle.OWNER);
   1053             } else {
   1054                 // Now that the intents have been deleted we can clean up the PDU data.
   1055                 if (!Intents.DATA_SMS_RECEIVED_ACTION.equals(action)
   1056                         && !Intents.SMS_RECEIVED_ACTION.equals(action)
   1057                         && !Intents.DATA_SMS_RECEIVED_ACTION.equals(action)
   1058                         && !Intents.WAP_PUSH_RECEIVED_ACTION.equals(action)) {
   1059                     loge("unexpected BroadcastReceiver action: " + action);
   1060                 }
   1061 
   1062                 int rc = getResultCode();
   1063                 if ((rc != Activity.RESULT_OK) && (rc != Intents.RESULT_SMS_HANDLED)) {
   1064                     loge("a broadcast receiver set the result code to " + rc
   1065                             + ", deleting from raw table anyway!");
   1066                 } else if (DBG) {
   1067                     log("successful broadcast, deleting from raw table.");
   1068                 }
   1069 
   1070                 deleteFromRawTable(mDeleteWhere, mDeleteWhereArgs);
   1071                 sendMessage(EVENT_BROADCAST_COMPLETE);
   1072 
   1073                 int durationMillis = (int) ((System.nanoTime() - mBroadcastTimeNano) / 1000000);
   1074                 if (durationMillis >= 5000) {
   1075                     loge("Slow ordered broadcast completion time: " + durationMillis + " ms");
   1076                 } else if (DBG) {
   1077                     log("ordered broadcast completed in: " + durationMillis + " ms");
   1078                 }
   1079             }
   1080         }
   1081     }
   1082 
   1083     /**
   1084      * Asynchronously binds to the carrier messaging service, and filters out the message if
   1085      * instructed to do so by the carrier messaging service. A new instance must be used for every
   1086      * message.
   1087      */
   1088     private final class CarrierSmsFilter extends CarrierMessagingServiceManager {
   1089         private final byte[][] mPdus;
   1090         private final int mDestPort;
   1091         private final String mSmsFormat;
   1092         private final SmsBroadcastReceiver mSmsBroadcastReceiver;
   1093         // Instantiated in filterSms.
   1094         private volatile CarrierSmsFilterCallback mSmsFilterCallback;
   1095 
   1096         CarrierSmsFilter(byte[][] pdus, int destPort, String smsFormat,
   1097                 SmsBroadcastReceiver smsBroadcastReceiver) {
   1098             mPdus = pdus;
   1099             mDestPort = destPort;
   1100             mSmsFormat = smsFormat;
   1101             mSmsBroadcastReceiver = smsBroadcastReceiver;
   1102         }
   1103 
   1104         /**
   1105          * Attempts to bind to a {@link ICarrierMessagingService}. Filtering is initiated
   1106          * asynchronously once the service is ready using {@link #onServiceReady}.
   1107          */
   1108         void filterSms(String carrierPackageName, CarrierSmsFilterCallback smsFilterCallback) {
   1109             mSmsFilterCallback = smsFilterCallback;
   1110             if (!bindToCarrierMessagingService(mContext, carrierPackageName)) {
   1111                 loge("bindService() for carrier messaging service failed");
   1112                 smsFilterCallback.onFilterComplete(true);
   1113             } else {
   1114                 logv("bindService() for carrier messaging service succeeded");
   1115             }
   1116         }
   1117 
   1118         /**
   1119          * Invokes the {@code carrierMessagingService} to filter messages. The filtering result is
   1120          * delivered to {@code smsFilterCallback}.
   1121          */
   1122         @Override
   1123         protected void onServiceReady(ICarrierMessagingService carrierMessagingService) {
   1124             try {
   1125                 carrierMessagingService.filterSms(
   1126                         new MessagePdu(Arrays.asList(mPdus)), mSmsFormat, mDestPort,
   1127                         mPhone.getSubId(), mSmsFilterCallback);
   1128             } catch (RemoteException e) {
   1129                 loge("Exception filtering the SMS: " + e);
   1130                 mSmsFilterCallback.onFilterComplete(true);
   1131             }
   1132         }
   1133     }
   1134 
   1135     /**
   1136      * A callback used to notify the platform of the carrier messaging app filtering result. Once
   1137      * the result is ready, the carrier messaging service connection is disposed.
   1138      */
   1139     private final class CarrierSmsFilterCallback extends ICarrierMessagingCallback.Stub {
   1140         private final CarrierSmsFilter mSmsFilter;
   1141 
   1142         CarrierSmsFilterCallback(CarrierSmsFilter smsFilter) {
   1143             mSmsFilter = smsFilter;
   1144         }
   1145 
   1146         /**
   1147          * This method should be called only once.
   1148          */
   1149         @Override
   1150         public void onFilterComplete(boolean keepMessage) {
   1151             mSmsFilter.disposeConnection(mContext);
   1152 
   1153             logv("onFilterComplete: keepMessage is "+ keepMessage);
   1154             if (keepMessage) {
   1155                 dispatchSmsDeliveryIntent(mSmsFilter.mPdus, mSmsFilter.mSmsFormat,
   1156                         mSmsFilter.mDestPort, mSmsFilter.mSmsBroadcastReceiver);
   1157             } else {
   1158                 // Drop this SMS.
   1159                 final long token = Binder.clearCallingIdentity();
   1160                 try {
   1161                     // Needs phone package permissions.
   1162                     deleteFromRawTable(mSmsFilter.mSmsBroadcastReceiver.mDeleteWhere,
   1163                             mSmsFilter.mSmsBroadcastReceiver.mDeleteWhereArgs);
   1164                 } finally {
   1165                     Binder.restoreCallingIdentity(token);
   1166                 }
   1167                 sendMessage(EVENT_BROADCAST_COMPLETE);
   1168             }
   1169         }
   1170 
   1171         @Override
   1172         public void onSendSmsComplete(int result, int messageRef) {
   1173             loge("Unexpected onSendSmsComplete call with result: " + result);
   1174         }
   1175 
   1176         @Override
   1177         public void onSendMultipartSmsComplete(int result, int[] messageRefs) {
   1178             loge("Unexpected onSendMultipartSmsComplete call with result: " + result);
   1179         }
   1180 
   1181         @Override
   1182         public void onSendMmsComplete(int result, byte[] sendConfPdu) {
   1183             loge("Unexpected onSendMmsComplete call with result: " + result);
   1184         }
   1185 
   1186         @Override
   1187         public void onDownloadMmsComplete(int result) {
   1188             loge("Unexpected onDownloadMmsComplete call with result: " + result);
   1189         }
   1190     }
   1191 
   1192     /**
   1193      * Log with debug level.
   1194      * @param s the string to log
   1195      */
   1196     @Override
   1197     protected void log(String s) {
   1198         Rlog.d(getName(), s);
   1199     }
   1200 
   1201     /**
   1202      * Log with error level.
   1203      * @param s the string to log
   1204      */
   1205     @Override
   1206     protected void loge(String s) {
   1207         Rlog.e(getName(), s);
   1208     }
   1209 
   1210     /**
   1211      * Log with error level.
   1212      * @param s the string to log
   1213      * @param e is a Throwable which logs additional information.
   1214      */
   1215     @Override
   1216     protected void loge(String s, Throwable e) {
   1217         Rlog.e(getName(), s, e);
   1218     }
   1219 
   1220     /**
   1221      * Store a received SMS into Telephony provider
   1222      *
   1223      * @param intent The intent containing the received SMS
   1224      * @return The URI of written message
   1225      */
   1226     private Uri writeInboxMessage(Intent intent) {
   1227         final SmsMessage[] messages = Telephony.Sms.Intents.getMessagesFromIntent(intent);
   1228         if (messages == null || messages.length < 1) {
   1229             loge("Failed to parse SMS pdu");
   1230             return null;
   1231         }
   1232         // Sometimes, SmsMessage.mWrappedSmsMessage is null causing NPE when we access
   1233         // the methods on it although the SmsMessage itself is not null. So do this check
   1234         // before we do anything on the parsed SmsMessages.
   1235         for (final SmsMessage sms : messages) {
   1236             try {
   1237                 sms.getDisplayMessageBody();
   1238             } catch (NullPointerException e) {
   1239                 loge("NPE inside SmsMessage");
   1240                 return null;
   1241             }
   1242         }
   1243         final ContentValues values = parseSmsMessage(messages);
   1244         final long identity = Binder.clearCallingIdentity();
   1245         try {
   1246             return mContext.getContentResolver().insert(Telephony.Sms.Inbox.CONTENT_URI, values);
   1247         } catch (Exception e) {
   1248             loge("Failed to persist inbox message", e);
   1249         } finally {
   1250             Binder.restoreCallingIdentity(identity);
   1251         }
   1252         return null;
   1253     }
   1254 
   1255     /**
   1256      * Convert SmsMessage[] into SMS database schema columns
   1257      *
   1258      * @param msgs The SmsMessage array of the received SMS
   1259      * @return ContentValues representing the columns of parsed SMS
   1260      */
   1261     private static ContentValues parseSmsMessage(SmsMessage[] msgs) {
   1262         final SmsMessage sms = msgs[0];
   1263         final ContentValues values = new ContentValues();
   1264         values.put(Telephony.Sms.Inbox.ADDRESS, sms.getDisplayOriginatingAddress());
   1265         values.put(Telephony.Sms.Inbox.BODY, buildMessageBodyFromPdus(msgs));
   1266         values.put(Telephony.Sms.Inbox.DATE_SENT, sms.getTimestampMillis());
   1267         values.put(Telephony.Sms.Inbox.DATE, System.currentTimeMillis());
   1268         values.put(Telephony.Sms.Inbox.PROTOCOL, sms.getProtocolIdentifier());
   1269         values.put(Telephony.Sms.Inbox.SEEN, 0);
   1270         values.put(Telephony.Sms.Inbox.READ, 0);
   1271         final String subject = sms.getPseudoSubject();
   1272         if (!TextUtils.isEmpty(subject)) {
   1273             values.put(Telephony.Sms.Inbox.SUBJECT, subject);
   1274         }
   1275         values.put(Telephony.Sms.Inbox.REPLY_PATH_PRESENT, sms.isReplyPathPresent() ? 1 : 0);
   1276         values.put(Telephony.Sms.Inbox.SERVICE_CENTER, sms.getServiceCenterAddress());
   1277         return values;
   1278     }
   1279 
   1280     /**
   1281      * Build up the SMS message body from the SmsMessage array of received SMS
   1282      *
   1283      * @param msgs The SmsMessage array of the received SMS
   1284      * @return The text message body
   1285      */
   1286     private static String buildMessageBodyFromPdus(SmsMessage[] msgs) {
   1287         if (msgs.length == 1) {
   1288             // There is only one part, so grab the body directly.
   1289             return replaceFormFeeds(msgs[0].getDisplayMessageBody());
   1290         } else {
   1291             // Build up the body from the parts.
   1292             StringBuilder body = new StringBuilder();
   1293             for (SmsMessage msg: msgs) {
   1294                 // getDisplayMessageBody() can NPE if mWrappedMessage inside is null.
   1295                 body.append(msg.getDisplayMessageBody());
   1296             }
   1297             return replaceFormFeeds(body.toString());
   1298         }
   1299     }
   1300 
   1301     // Some providers send formfeeds in their messages. Convert those formfeeds to newlines.
   1302     private static String replaceFormFeeds(String s) {
   1303         return s == null ? "" : s.replace('\f', '\n');
   1304     }
   1305 }
   1306