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