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