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