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