/*
 * Copyright (C) 2013 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.internal.telephony;

import static android.provider.Telephony.Sms.Intents.RESULT_SMS_DATABASE_ERROR;
import static android.provider.Telephony.Sms.Intents.RESULT_SMS_DISPATCH_FAILURE;
import static android.provider.Telephony.Sms.Intents.RESULT_SMS_INVALID_URI;
import static android.provider.Telephony.Sms.Intents.RESULT_SMS_NULL_MESSAGE;
import static android.provider.Telephony.Sms.Intents.RESULT_SMS_NULL_PDU;
import static android.service.carrier.CarrierMessagingService.RECEIVE_OPTIONS_SKIP_NOTIFY_WHEN_CREDENTIAL_PROTECTED_STORAGE_UNAVAILABLE;
import static android.telephony.TelephonyManager.PHONE_TYPE_CDMA;

import android.app.Activity;
import android.app.AppOpsManager;
import android.app.BroadcastOptions;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.IPackageManager;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.database.SQLException;
import android.net.Uri;
import android.os.AsyncResult;
import android.os.Binder;
import android.os.Bundle;
import android.os.Message;
import android.os.PowerManager;
import android.os.PowerWhitelistManager;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.UserHandle;
import android.os.UserManager;
import android.os.storage.StorageManager;
import android.provider.Telephony;
import android.provider.Telephony.Sms.Intents;
import android.service.carrier.CarrierMessagingService;
import android.telephony.SmsMessage;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.LocalLog;
import android.util.Pair;

import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.telephony.SmsConstants.MessageClass;
import com.android.internal.telephony.metrics.TelephonyMetrics;
import com.android.internal.telephony.util.NotificationChannelController;
import com.android.internal.telephony.util.TelephonyUtils;
import com.android.internal.util.HexDump;
import com.android.internal.util.State;
import com.android.internal.util.StateMachine;
import com.android.telephony.Rlog;

import java.io.ByteArrayOutputStream;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * This class broadcasts incoming SMS messages to interested apps after storing them in
 * the SmsProvider "raw" table and ACKing them to the SMSC. After each message has been
 * broadcast, its parts are removed from the raw table. If the device crashes after ACKing
 * but before the broadcast completes, the pending messages will be rebroadcast on the next boot.
 *
 * <p>The state machine starts in {@link IdleState} state. When the {@link SMSDispatcher} receives a
 * new SMS from the radio, it calls {@link #dispatchNormalMessage},
 * which sends a message to the state machine, causing the wakelock to be acquired in
 * {@link #haltedProcessMessage}, which transitions to {@link DeliveringState} state, where the message
 * is saved to the raw table, then acknowledged via the {@link SMSDispatcher} which called us.
 *
 * <p>After saving the SMS, if the message is complete (either single-part or the final segment
 * of a multi-part SMS), we broadcast the completed PDUs as an ordered broadcast, then transition to
 * {@link WaitingState} state to wait for the broadcast to complete. When the local
 * {@link BroadcastReceiver} is called with the result, it sends {@link #EVENT_BROADCAST_COMPLETE}
 * to the state machine, causing us to either broadcast the next pending message (if one has
 * arrived while waiting for the broadcast to complete), or to transition back to the halted state
 * after all messages are processed. Then the wakelock is released and we wait for the next SMS.
 */
public abstract class InboundSmsHandler extends StateMachine {
    protected static final boolean DBG = true;
    protected static final boolean VDBG = false; // STOPSHIP if true, logs user data

    /** Query projection for checking for duplicate message segments. */
    private static final String[] PDU_DELETED_FLAG_PROJECTION = {
            "pdu",
            "deleted"
    };

    /** Mapping from DB COLUMN to PDU_SEQUENCE_PORT PROJECTION index */
    private static final Map<Integer, Integer> PDU_DELETED_FLAG_PROJECTION_INDEX_MAPPING =
            new HashMap<Integer, Integer>() {{
            put(PDU_COLUMN, 0);
            put(DELETED_FLAG_COLUMN, 1);
            }};

    /** Query projection for combining concatenated message segments. */
    private static final String[] PDU_SEQUENCE_PORT_PROJECTION = {
            "pdu",
            "sequence",
            "destination_port",
            "display_originating_addr",
            "date"
    };

    /** Mapping from DB COLUMN to PDU_SEQUENCE_PORT PROJECTION index */
    private static final Map<Integer, Integer> PDU_SEQUENCE_PORT_PROJECTION_INDEX_MAPPING =
            new HashMap<Integer, Integer>() {{
                put(PDU_COLUMN, 0);
                put(SEQUENCE_COLUMN, 1);
                put(DESTINATION_PORT_COLUMN, 2);
                put(DISPLAY_ADDRESS_COLUMN, 3);
                put(DATE_COLUMN, 4);
    }};

    public static final int PDU_COLUMN = 0;
    public static final int SEQUENCE_COLUMN = 1;
    public static final int DESTINATION_PORT_COLUMN = 2;
    public static final int DATE_COLUMN = 3;
    public static final int REFERENCE_NUMBER_COLUMN = 4;
    public static final int COUNT_COLUMN = 5;
    public static final int ADDRESS_COLUMN = 6;
    public static final int ID_COLUMN = 7;
    public static final int MESSAGE_BODY_COLUMN = 8;
    public static final int DISPLAY_ADDRESS_COLUMN = 9;
    public static final int DELETED_FLAG_COLUMN = 10;
    public static final int SUBID_COLUMN = 11;

    public static final String SELECT_BY_ID = "_id=?";

    /** New SMS received as an AsyncResult. */
    public static final int EVENT_NEW_SMS = 1;

    /** Message type containing a {@link InboundSmsTracker} ready to broadcast to listeners. */
    public static final int EVENT_BROADCAST_SMS = 2;

    /** Message from resultReceiver notifying {@link WaitingState} of a completed broadcast. */
    private static final int EVENT_BROADCAST_COMPLETE = 3;

    /** Sent on exit from {@link WaitingState} to return to idle after sending all broadcasts. */
    private static final int EVENT_RETURN_TO_IDLE = 4;

    /** Release wakelock after {@link #mWakeLockTimeout} when returning to idle state. */
    private static final int EVENT_RELEASE_WAKELOCK = 5;

    /** Sent by {@link SmsBroadcastUndelivered} after cleaning the raw table. */
    public static final int EVENT_START_ACCEPTING_SMS = 6;

    /** New SMS received as an AsyncResult. */
    public static final int EVENT_INJECT_SMS = 7;

    /** Update the sms tracker */
    public static final int EVENT_UPDATE_TRACKER = 8;

    /** Wakelock release delay when returning to idle state. */
    private static final int WAKELOCK_TIMEOUT = 3000;

    // The notitfication tag used when showing a notification. The combination of notification tag
    // and notification id should be unique within the phone app.
    private static final String NOTIFICATION_TAG = "InboundSmsHandler";
    private static final int NOTIFICATION_ID_NEW_MESSAGE = 1;

    /** URI for raw table of SMS provider. */
    protected static final Uri sRawUri = Uri.withAppendedPath(Telephony.Sms.CONTENT_URI, "raw");
    protected static final Uri sRawUriPermanentDelete =
            Uri.withAppendedPath(Telephony.Sms.CONTENT_URI, "raw/permanentDelete");

    @UnsupportedAppUsage
    protected final Context mContext;
    @UnsupportedAppUsage
    private final ContentResolver mResolver;

    /** Special handler for WAP push messages. */
    @UnsupportedAppUsage
    private final WapPushOverSms mWapPush;

    /** Wake lock to ensure device stays awake while dispatching the SMS intents. */
    @UnsupportedAppUsage
    private final PowerManager.WakeLock mWakeLock;

    /** DefaultState throws an exception or logs an error for unhandled message types. */
    private final DefaultState mDefaultState = new DefaultState();

    /** Startup state. Waiting for {@link SmsBroadcastUndelivered} to complete. */
    private final StartupState mStartupState = new StartupState();

    /** Idle state. Waiting for messages to process. */
    @UnsupportedAppUsage
    private final IdleState mIdleState = new IdleState();

    /** Delivering state. Saves the PDU in the raw table and acknowledges to SMSC. */
    @UnsupportedAppUsage
    private final DeliveringState mDeliveringState = new DeliveringState();

    /** Broadcasting state. Waits for current broadcast to complete before delivering next. */
    @UnsupportedAppUsage
    private final WaitingState mWaitingState = new WaitingState();

    /** Helper class to check whether storage is available for incoming messages. */
    protected SmsStorageMonitor mStorageMonitor;

    private final boolean mSmsReceiveDisabled;

    @UnsupportedAppUsage
    protected Phone mPhone;

    @UnsupportedAppUsage
    private UserManager mUserManager;

    protected TelephonyMetrics mMetrics = TelephonyMetrics.getInstance();

    private LocalLog mLocalLog = new LocalLog(64);

    PowerWhitelistManager mPowerWhitelistManager;

    protected CellBroadcastServiceManager mCellBroadcastServiceManager;

    // Delete permanently from raw table
    private final int DELETE_PERMANENTLY = 1;
    // Only mark deleted, but keep in db for message de-duping
    private final int MARK_DELETED = 2;

    private static String ACTION_OPEN_SMS_APP =
        "com.android.internal.telephony.OPEN_DEFAULT_SMS_APP";

    /** Timeout for releasing wakelock */
    private int mWakeLockTimeout;

    /** Indicates if last SMS was injected. This is used to recognize SMS received over IMS from
        others in order to update metrics. */
    private boolean mLastSmsWasInjected = false;

    /**
     * Create a new SMS broadcast helper.
     * @param name the class name for logging
     * @param context the context of the phone app
     * @param storageMonitor the SmsStorageMonitor to check for storage availability
     */
    protected InboundSmsHandler(String name, Context context, SmsStorageMonitor storageMonitor,
            Phone phone) {
        super(name);

        mContext = context;
        mStorageMonitor = storageMonitor;
        mPhone = phone;
        mResolver = context.getContentResolver();
        mWapPush = new WapPushOverSms(context);

        boolean smsCapable = mContext.getResources().getBoolean(
                com.android.internal.R.bool.config_sms_capable);
        mSmsReceiveDisabled = !TelephonyManager.from(mContext).getSmsReceiveCapableForPhone(
                mPhone.getPhoneId(), smsCapable);

        PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
        mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, name);
        mWakeLock.acquire();    // wake lock released after we enter idle state
        mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
        mPowerWhitelistManager =
                (PowerWhitelistManager) mContext.getSystemService(Context.POWER_WHITELIST_MANAGER);
        mCellBroadcastServiceManager = new CellBroadcastServiceManager(context, phone);

        addState(mDefaultState);
        addState(mStartupState, mDefaultState);
        addState(mIdleState, mDefaultState);
        addState(mDeliveringState, mDefaultState);
            addState(mWaitingState, mDeliveringState);

        setInitialState(mStartupState);
        if (DBG) log("created InboundSmsHandler");
    }

    /**
     * Tell the state machine to quit after processing all messages.
     */
    public void dispose() {
        quit();
    }

    /**
     * Dispose of the WAP push object and release the wakelock.
     */
    @Override
    protected void onQuitting() {
        mWapPush.dispose();
        mCellBroadcastServiceManager.disable();

        while (mWakeLock.isHeld()) {
            mWakeLock.release();
        }
    }

    // CAF_MSIM Is this used anywhere ? if not remove it
    @UnsupportedAppUsage
    public Phone getPhone() {
        return mPhone;
    }

    /**
     * This parent state throws an exception (for debug builds) or prints an error for unhandled
     * message types.
     */
    private class DefaultState extends State {
        @Override
        public boolean processMessage(Message msg) {
            switch (msg.what) {
                default: {
                    String errorText = "processMessage: unhandled message type " + msg.what +
                        " currState=" + getCurrentState().getName();
                    if (TelephonyUtils.IS_DEBUGGABLE) {
                        loge("---- Dumping InboundSmsHandler ----");
                        loge("Total records=" + getLogRecCount());
                        for (int i = Math.max(getLogRecSize() - 20, 0); i < getLogRecSize(); i++) {
                            loge("Rec[%d]: %s\n" + i + getLogRec(i).toString());
                        }
                        loge("---- Dumped InboundSmsHandler ----");

                        throw new RuntimeException(errorText);
                    } else {
                        loge(errorText);
                    }
                    break;
                }
            }
            return HANDLED;
        }
    }

    /**
     * The Startup state waits for {@link SmsBroadcastUndelivered} to process the raw table and
     * notify the state machine to broadcast any complete PDUs that might not have been broadcast.
     */
    private class StartupState extends State {
        @Override
        public void enter() {
            if (DBG) log("entering Startup state");
            // Set wakelock timeout to 0 during startup, this will ensure that the wakelock is not
            // held if there are no pending messages to be handled.
            setWakeLockTimeout(0);
        }

        @Override
        public boolean processMessage(Message msg) {
            log("StartupState.processMessage:" + msg.what);
            switch (msg.what) {
                case EVENT_NEW_SMS:
                case EVENT_INJECT_SMS:
                case EVENT_BROADCAST_SMS:
                    deferMessage(msg);
                    return HANDLED;

                case EVENT_START_ACCEPTING_SMS:
                    transitionTo(mIdleState);
                    return HANDLED;

                case EVENT_BROADCAST_COMPLETE:
                case EVENT_RETURN_TO_IDLE:
                case EVENT_RELEASE_WAKELOCK:
                default:
                    // let DefaultState handle these unexpected message types
                    return NOT_HANDLED;
            }
        }
    }

    /**
     * In the idle state the wakelock is released until a new SM arrives, then we transition
     * to Delivering mode to handle it, acquiring the wakelock on exit.
     */
    private class IdleState extends State {
        @Override
        public void enter() {
            if (DBG) log("entering Idle state");
            sendMessageDelayed(EVENT_RELEASE_WAKELOCK, getWakeLockTimeout());
        }

        @Override
        public void exit() {
            mWakeLock.acquire();
            if (DBG) log("acquired wakelock, leaving Idle state");
        }

        @Override
        public boolean processMessage(Message msg) {
            log("IdleState.processMessage:" + msg.what);
            if (DBG) log("Idle state processing message type " + msg.what);
            switch (msg.what) {
                case EVENT_NEW_SMS:
                case EVENT_INJECT_SMS:
                case EVENT_BROADCAST_SMS:
                    deferMessage(msg);
                    transitionTo(mDeliveringState);
                    return HANDLED;

                case EVENT_RELEASE_WAKELOCK:
                    mWakeLock.release();
                    if (DBG) {
                        if (mWakeLock.isHeld()) {
                            // this is okay as long as we call release() for every acquire()
                            log("mWakeLock is still held after release");
                        } else {
                            log("mWakeLock released");
                        }
                    }
                    return HANDLED;

                case EVENT_RETURN_TO_IDLE:
                    // already in idle state; ignore
                    return HANDLED;

                case EVENT_BROADCAST_COMPLETE:
                case EVENT_START_ACCEPTING_SMS:
                default:
                    // let DefaultState handle these unexpected message types
                    return NOT_HANDLED;
            }
        }
    }

    /**
     * In the delivering state, the inbound SMS is processed and stored in the raw table.
     * The message is acknowledged before we exit this state. If there is a message to broadcast,
     * transition to {@link WaitingState} state to send the ordered broadcast and wait for the
     * results. When all messages have been processed, the halting state will release the wakelock.
     */
    private class DeliveringState extends State {
        @Override
        public void enter() {
            if (DBG) log("entering Delivering state");
        }

        @Override
        public void exit() {
            if (DBG) log("leaving Delivering state");
        }

        @Override
        public boolean processMessage(Message msg) {
            log("DeliveringState.processMessage:" + msg.what);
            switch (msg.what) {
                case EVENT_NEW_SMS:
                    // handle new SMS from RIL
                    handleNewSms((AsyncResult) msg.obj);
                    sendMessage(EVENT_RETURN_TO_IDLE);
                    return HANDLED;

                case EVENT_INJECT_SMS:
                    // handle new injected SMS
                    handleInjectSms((AsyncResult) msg.obj);
                    sendMessage(EVENT_RETURN_TO_IDLE);
                    return HANDLED;

                case EVENT_BROADCAST_SMS:
                    // if any broadcasts were sent, transition to waiting state
                    InboundSmsTracker inboundSmsTracker = (InboundSmsTracker) msg.obj;
                    if (processMessagePart(inboundSmsTracker)) {
                        sendMessage(obtainMessage(EVENT_UPDATE_TRACKER, msg.obj));
                        transitionTo(mWaitingState);
                    } else {
                        // if event is sent from SmsBroadcastUndelivered.broadcastSms(), and
                        // processMessagePart() returns false, the state machine will be stuck in
                        // DeliveringState until next message is received. Send message to
                        // transition to idle to avoid that so that wakelock can be released
                        log("No broadcast sent on processing EVENT_BROADCAST_SMS in Delivering " +
                                "state. Return to Idle state");
                        sendMessage(EVENT_RETURN_TO_IDLE);
                    }
                    return HANDLED;

                case EVENT_RETURN_TO_IDLE:
                    // return to idle after processing all other messages
                    transitionTo(mIdleState);
                    return HANDLED;

                case EVENT_RELEASE_WAKELOCK:
                    mWakeLock.release();    // decrement wakelock from previous entry to Idle
                    if (!mWakeLock.isHeld()) {
                        // wakelock should still be held until 3 seconds after we enter Idle
                        loge("mWakeLock released while delivering/broadcasting!");
                    }
                    return HANDLED;

                case EVENT_UPDATE_TRACKER:
                    logd("process tracker message in DeliveringState " + msg.arg1);
                    return HANDLED;

                // we shouldn't get this message type in this state, log error and halt.
                case EVENT_BROADCAST_COMPLETE:
                case EVENT_START_ACCEPTING_SMS:
                default:
                    String errorMsg = "Unhandled msg in delivering state, msg.what = " + msg.what;
                    loge(errorMsg);
                    mLocalLog.log(errorMsg);
                    // let DefaultState handle these unexpected message types
                    return NOT_HANDLED;
            }
        }
    }

    /**
     * The waiting state delegates handling of new SMS to parent {@link DeliveringState}, but
     * defers handling of the {@link #EVENT_BROADCAST_SMS} phase until after the current
     * result receiver sends {@link #EVENT_BROADCAST_COMPLETE}. Before transitioning to
     * {@link DeliveringState}, {@link #EVENT_RETURN_TO_IDLE} is sent to transition to
     * {@link IdleState} after any deferred {@link #EVENT_BROADCAST_SMS} messages are handled.
     */
    private class WaitingState extends State {

        private InboundSmsTracker mLastDeliveredSmsTracker;

        @Override
        public void enter() {
            if (DBG) log("entering Waiting state");
        }

        @Override
        public void exit() {
            if (DBG) log("exiting Waiting state");
            // Before moving to idle state, set wakelock timeout to WAKE_LOCK_TIMEOUT milliseconds
            // to give any receivers time to take their own wake locks
            setWakeLockTimeout(WAKELOCK_TIMEOUT);
            mPhone.getIccSmsInterfaceManager().mDispatchersController.sendEmptyMessage(
                    SmsDispatchersController.EVENT_SMS_HANDLER_EXITING_WAITING_STATE);
        }

        @Override
        public boolean processMessage(Message msg) {
            log("WaitingState.processMessage:" + msg.what);
            switch (msg.what) {
                case EVENT_BROADCAST_SMS:
                    // defer until the current broadcast completes
                    if (mLastDeliveredSmsTracker != null) {
                        String str = "Defer sms broadcast due to undelivered sms, "
                                + " messageCount = " + mLastDeliveredSmsTracker.getMessageCount()
                                + " destPort = " + mLastDeliveredSmsTracker.getDestPort()
                                + " timestamp = " + mLastDeliveredSmsTracker.getTimestamp()
                                + " currentTimestamp = " + System.currentTimeMillis();
                        logd(str);
                        mLocalLog.log(str);
                    }
                    deferMessage(msg);
                    return HANDLED;

                case EVENT_BROADCAST_COMPLETE:
                    mLastDeliveredSmsTracker = null;
                    // return to idle after handling all deferred messages
                    sendMessage(EVENT_RETURN_TO_IDLE);
                    transitionTo(mDeliveringState);
                    return HANDLED;

                case EVENT_RETURN_TO_IDLE:
                    // not ready to return to idle; ignore
                    return HANDLED;

                case EVENT_UPDATE_TRACKER:
                    mLastDeliveredSmsTracker = (InboundSmsTracker) msg.obj;
                    return HANDLED;

                default:
                    // parent state handles the other message types
                    return NOT_HANDLED;
            }
        }
    }

    @UnsupportedAppUsage
    private void handleNewSms(AsyncResult ar) {
        if (ar.exception != null) {
            loge("Exception processing incoming SMS: " + ar.exception);
            return;
        }

        int result;
        try {
            SmsMessage sms = (SmsMessage) ar.result;
            mLastSmsWasInjected = false;
            result = dispatchMessage(sms.mWrappedSmsMessage);
        } catch (RuntimeException ex) {
            loge("Exception dispatching message", ex);
            result = RESULT_SMS_DISPATCH_FAILURE;
        }

        // RESULT_OK means that the SMS will be acknowledged by special handling,
        // e.g. for SMS-PP data download. Any other result, we should ack here.
        if (result != Activity.RESULT_OK) {
            boolean handled = (result == Intents.RESULT_SMS_HANDLED);
            notifyAndAcknowledgeLastIncomingSms(handled, result, null);
        }
    }

    /**
     * This method is called when a new SMS PDU is injected into application framework.
     * @param ar is the AsyncResult that has the SMS PDU to be injected.
     */
    @UnsupportedAppUsage
    private void handleInjectSms(AsyncResult ar) {
        int result;
        SmsDispatchersController.SmsInjectionCallback callback = null;
        try {
            callback = (SmsDispatchersController.SmsInjectionCallback) ar.userObj;
            SmsMessage sms = (SmsMessage) ar.result;
            if (sms == null) {
                loge("Null injected sms");
                result = RESULT_SMS_NULL_PDU;
            } else {
                mLastSmsWasInjected = true;
                result = dispatchMessage(sms.mWrappedSmsMessage);
            }
        } catch (RuntimeException ex) {
            loge("Exception dispatching message", ex);
            result = RESULT_SMS_DISPATCH_FAILURE;
        }

        if (callback != null) {
            callback.onSmsInjectedResult(result);
        }
    }

    /**
     * Process an SMS message from the RIL, calling subclass methods to handle 3GPP and
     * 3GPP2-specific message types.
     *
     * @param smsb the SmsMessageBase object from the RIL
     * @return a result code from {@link android.provider.Telephony.Sms.Intents},
     *  or {@link Activity#RESULT_OK} for delayed acknowledgment to SMSC
     */
    private int dispatchMessage(SmsMessageBase smsb) {
        // If sms is null, there was a parsing error.
        if (smsb == null) {
            loge("dispatchSmsMessage: message is null");
            return RESULT_SMS_NULL_MESSAGE;
        }

        if (mSmsReceiveDisabled) {
            // Device doesn't support receiving SMS,
            log("Received short message on device which doesn't support "
                    + "receiving SMS. Ignored.");
            return Intents.RESULT_SMS_HANDLED;
        }

        // onlyCore indicates if the device is in cryptkeeper
        boolean onlyCore = false;
        try {
            onlyCore = IPackageManager.Stub.asInterface(ServiceManager.getService("package"))
                    .isOnlyCoreApps();
        } catch (RemoteException e) {
        }
        if (onlyCore) {
            // Device is unable to receive SMS in encrypted state
            log("Received a short message in encrypted state. Rejecting.");
            return Intents.RESULT_SMS_RECEIVED_WHILE_ENCRYPTED;
        }

        int result = dispatchMessageRadioSpecific(smsb);

        // In case of error, add to metrics. This is not required in case of success, as the
        // data will be tracked when the message is processed (processMessagePart).
        if (result != Intents.RESULT_SMS_HANDLED) {
            mMetrics.writeIncomingSmsError(mPhone.getPhoneId(), mLastSmsWasInjected, result);
        }
        return result;
    }

    /**
     * Process voicemail notification, SMS-PP data download, CDMA CMAS, CDMA WAP push, and other
     * 3GPP/3GPP2-specific messages. Regular SMS messages are handled by calling the shared
     * {@link #dispatchNormalMessage} from this class.
     *
     * @param smsb the SmsMessageBase object from the RIL
     * @return a result code from {@link android.provider.Telephony.Sms.Intents},
     *  or {@link Activity#RESULT_OK} for delayed acknowledgment to SMSC
     */
    protected abstract int dispatchMessageRadioSpecific(SmsMessageBase smsb);

    /**
     * Send an acknowledge message to the SMSC.
     * @param success indicates that last message was successfully received.
     * @param result result code indicating any error
     * @param response callback message sent when operation completes.
     */
    @UnsupportedAppUsage
    protected abstract void acknowledgeLastIncomingSms(boolean success,
            int result, Message response);

    /**
     * Notify interested apps if the framework has rejected an incoming SMS,
     * and send an acknowledge message to the network.
     * @param success indicates that last message was successfully received.
     * @param result result code indicating any error
     * @param response callback message sent when operation completes.
     */
    private void notifyAndAcknowledgeLastIncomingSms(boolean success,
            int result, Message response) {
        if (!success) {
            // broadcast SMS_REJECTED_ACTION intent
            Intent intent = new Intent(Intents.SMS_REJECTED_ACTION);
            intent.putExtra("result", result);
            intent.putExtra("subId", mPhone.getSubId());
            mContext.sendBroadcast(intent, android.Manifest.permission.RECEIVE_SMS);
        }
        acknowledgeLastIncomingSms(success, result, response);
    }

    /**
     * Return true if this handler is for 3GPP2 messages; false for 3GPP format.
     * @return true for the 3GPP2 handler; false for the 3GPP handler
     */
    protected abstract boolean is3gpp2();

    /**
     * Dispatch a normal incoming SMS. This is called from {@link #dispatchMessageRadioSpecific}
     * if no format-specific handling was required. Saves the PDU to the SMS provider raw table,
     * creates an {@link InboundSmsTracker}, then sends it to the state machine as an
     * {@link #EVENT_BROADCAST_SMS}. Returns {@link Intents#RESULT_SMS_HANDLED} or an error value.
     *
     * @param sms the message to dispatch
     * @return {@link Intents#RESULT_SMS_HANDLED} if the message was accepted, or an error status
     */
    @UnsupportedAppUsage
    protected int dispatchNormalMessage(SmsMessageBase sms) {
        SmsHeader smsHeader = sms.getUserDataHeader();
        InboundSmsTracker tracker;

        if ((smsHeader == null) || (smsHeader.concatRef == null)) {
            // Message is not concatenated.
            int destPort = -1;
            if (smsHeader != null && smsHeader.portAddrs != null) {
                // The message was sent to a port.
                destPort = smsHeader.portAddrs.destPort;
                if (DBG) log("destination port: " + destPort);
            }
            tracker = TelephonyComponentFactory.getInstance()
                    .inject(InboundSmsTracker.class.getName())
                    .makeInboundSmsTracker(mContext, sms.getPdu(),
                    sms.getTimestampMillis(), destPort, is3gpp2(), false,
                    sms.getOriginatingAddress(), sms.getDisplayOriginatingAddress(),
                    sms.getMessageBody(), sms.getMessageClass() == MessageClass.CLASS_0,
                            mPhone.getSubId());
        } else {
            // Create a tracker for this message segment.
            SmsHeader.ConcatRef concatRef = smsHeader.concatRef;
            SmsHeader.PortAddrs portAddrs = smsHeader.portAddrs;
            int destPort = (portAddrs != null ? portAddrs.destPort : -1);
            tracker = TelephonyComponentFactory.getInstance()
                    .inject(InboundSmsTracker.class.getName())
                    .makeInboundSmsTracker(mContext, sms.getPdu(),
                    sms.getTimestampMillis(), destPort, is3gpp2(), sms.getOriginatingAddress(),
                    sms.getDisplayOriginatingAddress(), concatRef.refNumber, concatRef.seqNumber,
                    concatRef.msgCount, false, sms.getMessageBody(),
                    sms.getMessageClass() == MessageClass.CLASS_0, mPhone.getSubId());
        }

        if (VDBG) log("created tracker: " + tracker);

        // de-duping is done only for text messages
        // destPort = -1 indicates text messages, otherwise it's a data sms
        return addTrackerToRawTableAndSendMessage(tracker,
                tracker.getDestPort() == -1 /* de-dup if text message */);
    }

    /**
     * Helper to add the tracker to the raw table and then send a message to broadcast it, if
     * successful. Returns the SMS intent status to return to the SMSC.
     * @param tracker the tracker to save to the raw table and then deliver
     * @return {@link Intents#RESULT_SMS_HANDLED} or one of these errors:<br>
     * <code>RESULT_SMS_UNSUPPORTED</code><br>
     * <code>RESULT_SMS_DUPLICATED</code><br>
     * <code>RESULT_SMS_DISPATCH_FAILURE</code><br>
     * <code>RESULT_SMS_NULL_PDU</code><br>
     * <code>RESULT_SMS_NULL_MESSAGE</code><br>
     * <code>RESULT_SMS_RECEIVED_WHILE_ENCRYPTED</code><br>
     * <code>RESULT_SMS_DATABASE_ERROR</code><br>
     * <code>RESULT_SMS_INVALID_URI</code><br>
     */
    protected int addTrackerToRawTableAndSendMessage(InboundSmsTracker tracker, boolean deDup) {
        int result = addTrackerToRawTable(tracker, deDup);
        switch(result) {
            case Intents.RESULT_SMS_HANDLED:
                sendMessage(EVENT_BROADCAST_SMS, tracker);
                return Intents.RESULT_SMS_HANDLED;

            case Intents.RESULT_SMS_DUPLICATED:
                return Intents.RESULT_SMS_HANDLED;

            default:
                return result;
        }
    }

    /**
     * Process the inbound SMS segment. If the message is complete, send it as an ordered
     * broadcast to interested receivers and return true. If the message is a segment of an
     * incomplete multi-part SMS, return false.
     * @param tracker the tracker containing the message segment to process
     * @return true if an ordered broadcast was sent; false if waiting for more message segments
     */
    @UnsupportedAppUsage
    private boolean processMessagePart(InboundSmsTracker tracker) {
        int messageCount = tracker.getMessageCount();
        byte[][] pdus;
        long[] timestamps;
        int destPort = tracker.getDestPort();
        boolean block = false;
        String address = tracker.getAddress();

        // Do not process when the message count is invalid.
        if (messageCount <= 0) {
            loge("processMessagePart: returning false due to invalid message count "
                    + messageCount
                    + " id: " + tracker.getMessageId());
            return false;
        }

        if (messageCount == 1) {
            // single-part message
            pdus = new byte[][]{tracker.getPdu()};
            timestamps = new long[]{tracker.getTimestamp()};
            block = BlockChecker.isBlocked(mContext, tracker.getDisplayAddress(), null);
        } else {
            // multi-part message
            Cursor cursor = null;
            try {
                // used by several query selection arguments
                String refNumber = Integer.toString(tracker.getReferenceNumber());
                String count = Integer.toString(tracker.getMessageCount());

                // query for all segments and broadcast message if we have all the parts
                String[] whereArgs = {address, refNumber, count};
                cursor = mResolver.query(sRawUri, PDU_SEQUENCE_PORT_PROJECTION,
                        tracker.getQueryForSegments(), whereArgs, null);

                int cursorCount = cursor.getCount();
                if (cursorCount < messageCount) {
                    // Wait for the other message parts to arrive. It's also possible for the last
                    // segment to arrive before processing the EVENT_BROADCAST_SMS for one of the
                    // earlier segments. In that case, the broadcast will be sent as soon as all
                    // segments are in the table, and any later EVENT_BROADCAST_SMS messages will
                    // get a row count of 0 and return.
                    return false;
                }

                // All the parts are in place, deal with them
                pdus = new byte[messageCount][];
                timestamps = new long[messageCount];
                while (cursor.moveToNext()) {
                    // subtract offset to convert sequence to 0-based array index
                    int index = cursor.getInt(PDU_SEQUENCE_PORT_PROJECTION_INDEX_MAPPING
                            .get(SEQUENCE_COLUMN)) - tracker.getIndexOffset();

                    // The invalid PDUs can be received and stored in the raw table. The range
                    // check ensures the process not crash even if the seqNumber in the
                    // UserDataHeader is invalid.
                    if (index >= pdus.length || index < 0) {
                        loge(String.format(
                                "processMessagePart: invalid seqNumber = %d, messageCount = %d,"
                                + " id = %s",
                                index + tracker.getIndexOffset(),
                                messageCount,
                                tracker.getMessageId()));
                        continue;
                    }

                    pdus[index] = HexDump.hexStringToByteArray(cursor.getString(
                            PDU_SEQUENCE_PORT_PROJECTION_INDEX_MAPPING.get(PDU_COLUMN)));

                    // Read the destination port from the first segment (needed for CDMA WAP PDU).
                    // It's not a bad idea to prefer the port from the first segment in other cases.
                    if (index == 0 && !cursor.isNull(PDU_SEQUENCE_PORT_PROJECTION_INDEX_MAPPING
                            .get(DESTINATION_PORT_COLUMN))) {
                        int port = cursor.getInt(PDU_SEQUENCE_PORT_PROJECTION_INDEX_MAPPING
                                .get(DESTINATION_PORT_COLUMN));
                        // strip format flags and convert to real port number, or -1
                        port = InboundSmsTracker.getRealDestPort(port);
                        if (port != -1) {
                            destPort = port;
                        }
                    }

                    timestamps[index] = cursor.getLong(
                            PDU_SEQUENCE_PORT_PROJECTION_INDEX_MAPPING.get(DATE_COLUMN));

                    // check if display address should be blocked or not
                    if (!block) {
                        // Depending on the nature of the gateway, the display origination address
                        // is either derived from the content of the SMS TP-OA field, or the TP-OA
                        // field contains a generic gateway address and the from address is added
                        // at the beginning in the message body. In that case only the first SMS
                        // (part of Multi-SMS) comes with the display originating address which
                        // could be used for block checking purpose.
                        block = BlockChecker.isBlocked(mContext,
                                cursor.getString(PDU_SEQUENCE_PORT_PROJECTION_INDEX_MAPPING
                                        .get(DISPLAY_ADDRESS_COLUMN)), null);
                    }
                }
            } catch (SQLException e) {
                loge("Can't access multipart SMS database"
                        + " id: " + tracker.getMessageId(),
                        e);
                return false;
            } finally {
                if (cursor != null) {
                    cursor.close();
                }
            }
        }

        final boolean isWapPush = (destPort == SmsHeader.PORT_WAP_PUSH);

        // At this point, all parts of the SMS are received. Update metrics for incoming SMS.
        // WAP-PUSH messages are handled below to also keep track of the result of the processing.
        String format = tracker.getFormat();
        if (!isWapPush) {
            mMetrics.writeIncomingSmsSession(mPhone.getPhoneId(), mLastSmsWasInjected,
                    format, timestamps, block, tracker.getMessageId());
        }

        // Do not process null pdu(s). Check for that and return false in that case.
        List<byte[]> pduList = Arrays.asList(pdus);
        if (pduList.size() == 0 || pduList.contains(null)) {
            String errorMsg = "processMessagePart: returning false due to "
                    + (pduList.size() == 0 ? "pduList.size() == 0" : "pduList.contains(null)"
                    + " id: " + tracker.getMessageId());
            loge(errorMsg);
            mLocalLog.log(errorMsg);
            return false;
        }

        ByteArrayOutputStream output = new ByteArrayOutputStream();
        if (isWapPush) {
            for (byte[] pdu : pdus) {
                // 3GPP needs to extract the User Data from the PDU; 3GPP2 has already done this
                if (format == SmsConstants.FORMAT_3GPP) {
                    SmsMessage msg = SmsMessage.createFromPdu(pdu, SmsConstants.FORMAT_3GPP);
                    if (msg != null) {
                        pdu = msg.getUserData();
                    } else {
                        loge("processMessagePart: SmsMessage.createFromPdu returned null"
                                + " id: "
                                + tracker.getMessageId());
                        mMetrics.writeIncomingWapPush(mPhone.getPhoneId(), mLastSmsWasInjected,
                                SmsConstants.FORMAT_3GPP, timestamps, false,
                                tracker.getMessageId());
                        return false;
                    }
                }
                output.write(pdu, 0, pdu.length);
            }
        }

        SmsBroadcastReceiver resultReceiver = new SmsBroadcastReceiver(tracker);

        if (!mUserManager.isUserUnlocked()) {
            return processMessagePartWithUserLocked(
                    tracker,
                    (isWapPush ? new byte[][] {output.toByteArray()} : pdus),
                    destPort,
                    resultReceiver);
        }

        if (isWapPush) {
            int result = mWapPush.dispatchWapPdu(output.toByteArray(), resultReceiver,
                    this, address, tracker.getSubId(), tracker.getMessageId());
            if (DBG) log("dispatchWapPdu() returned " + result);
            // Add result of WAP-PUSH into metrics. RESULT_SMS_HANDLED indicates that the WAP-PUSH
            // needs to be ignored, so treating it as a success case.
            if (result == Activity.RESULT_OK || result == Intents.RESULT_SMS_HANDLED) {
                mMetrics.writeIncomingWapPush(mPhone.getPhoneId(), mLastSmsWasInjected,
                        format, timestamps, true, tracker.getMessageId());
            } else {
                mMetrics.writeIncomingWapPush(mPhone.getPhoneId(), mLastSmsWasInjected,
                        format, timestamps, false, tracker.getMessageId());
            }
            // result is Activity.RESULT_OK if an ordered broadcast was sent
            if (result == Activity.RESULT_OK) {
                return true;
            } else {
                deleteFromRawTable(tracker.getDeleteWhere(), tracker.getDeleteWhereArgs(),
                        MARK_DELETED);
                return false;
            }
        }

        if (block) {
            deleteFromRawTable(tracker.getDeleteWhere(), tracker.getDeleteWhereArgs(),
                    DELETE_PERMANENTLY);
            return false;
        }

        boolean filterInvoked = filterSms(
            pdus, destPort, tracker, resultReceiver, true /* userUnlocked */);

        if (!filterInvoked) {
            dispatchSmsDeliveryIntent(pdus, format, destPort, resultReceiver,
                    tracker.isClass0(), tracker.getSubId(), tracker.getMessageId());
        }

        return true;
    }

    /**
     * Processes the message part while the credential-encrypted storage is still locked.
     *
     * <p>If the message is a regular MMS, show a new message notification. If the message is a
     * SMS, ask the carrier app to filter it and show the new message notification if the carrier
     * app asks to keep the message.
     *
     * @return true if an ordered broadcast was sent to the carrier app; false otherwise.
     */
    private boolean processMessagePartWithUserLocked(InboundSmsTracker tracker,
            byte[][] pdus, int destPort, SmsBroadcastReceiver resultReceiver) {
        log("Credential-encrypted storage not available. Port: " + destPort);
        if (destPort == SmsHeader.PORT_WAP_PUSH && mWapPush.isWapPushForMms(pdus[0], this)) {
            showNewMessageNotification();
            return false;
        }
        if (destPort == -1) {
            // This is a regular SMS - hand it to the carrier or system app for filtering.
            boolean filterInvoked = filterSms(
                pdus, destPort, tracker, resultReceiver, false /* userUnlocked */);
            if (filterInvoked) {
                // filter invoked, wait for it to return the result.
                return true;
            } else {
                // filter not invoked, show the notification and do nothing further.
                showNewMessageNotification();
                return false;
            }
        }
        return false;
    }

    @UnsupportedAppUsage
    private void showNewMessageNotification() {
        // Do not show the notification on non-FBE devices.
        if (!StorageManager.isFileEncryptedNativeOrEmulated()) {
            return;
        }
        log("Show new message notification.");
        PendingIntent intent = PendingIntent.getBroadcast(
            mContext,
            0,
            new Intent(ACTION_OPEN_SMS_APP),
            PendingIntent.FLAG_ONE_SHOT);
        Notification.Builder mBuilder = new Notification.Builder(mContext)
                .setSmallIcon(com.android.internal.R.drawable.sym_action_chat)
                .setAutoCancel(true)
                .setVisibility(Notification.VISIBILITY_PUBLIC)
                .setDefaults(Notification.DEFAULT_ALL)
                .setContentTitle(mContext.getString(R.string.new_sms_notification_title))
                .setContentText(mContext.getString(R.string.new_sms_notification_content))
                .setContentIntent(intent)
                .setChannelId(NotificationChannelController.CHANNEL_ID_SMS);
        NotificationManager mNotificationManager =
            (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
        mNotificationManager.notify(
                NOTIFICATION_TAG, NOTIFICATION_ID_NEW_MESSAGE, mBuilder.build());
    }

    static void cancelNewMessageNotification(Context context) {
        NotificationManager mNotificationManager =
            (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
        mNotificationManager.cancel(InboundSmsHandler.NOTIFICATION_TAG,
            InboundSmsHandler.NOTIFICATION_ID_NEW_MESSAGE);
    }

    /**
     * Filters the SMS.
     *
     * <p>currently 3 filters exists: the carrier package, the system package, and the
     * VisualVoicemailSmsFilter.
     *
     * <p>The filtering process is:
     *
     * <p>If the carrier package exists, the SMS will be filtered with it first. If the carrier
     * package did not drop the SMS, then the VisualVoicemailSmsFilter will filter it in the
     * callback.
     *
     * <p>If the carrier package does not exists, we will let the VisualVoicemailSmsFilter filter
     * it. If the SMS passed the filter, then we will try to find the system package to do the
     * filtering.
     *
     * @return true if a filter is invoked and the SMS processing flow is diverted, false otherwise.
     */
    private boolean filterSms(byte[][] pdus, int destPort,
        InboundSmsTracker tracker, SmsBroadcastReceiver resultReceiver, boolean userUnlocked) {
        CarrierServicesSmsFilterCallback filterCallback =
                new CarrierServicesSmsFilterCallback(
                        pdus, destPort, tracker.getFormat(), resultReceiver, userUnlocked,
                        tracker.isClass0(), tracker.getSubId(), tracker.getMessageId());
        CarrierServicesSmsFilter carrierServicesFilter = new CarrierServicesSmsFilter(
                mContext, mPhone, pdus, destPort, tracker.getFormat(),
                filterCallback, getName(), mLocalLog);
        if (carrierServicesFilter.filter()) {
            return true;
        }

        if (VisualVoicemailSmsFilter.filter(
                mContext, pdus, tracker.getFormat(), destPort, tracker.getSubId())) {
            log("Visual voicemail SMS dropped");
            dropSms(resultReceiver);
            return true;
        }

        MissedIncomingCallSmsFilter missedIncomingCallSmsFilter =
                new MissedIncomingCallSmsFilter(mPhone);
        if (missedIncomingCallSmsFilter.filter(pdus, tracker.getFormat())) {
            log("Missed incoming call SMS received.");
            dropSms(resultReceiver);
            return true;
        }

        return false;
    }

    /**
     * Dispatch the intent with the specified permission, appOp, and result receiver, using
     * this state machine's handler thread to run the result receiver.
     *
     * @param intent the intent to broadcast
     * @param permission receivers are required to have this permission
     * @param appOp app op that is being performed when dispatching to a receiver
     * @param user user to deliver the intent to
     */
    @UnsupportedAppUsage
    public void dispatchIntent(Intent intent, String permission, String appOp,
            Bundle opts, BroadcastReceiver resultReceiver, UserHandle user, int subId) {
        intent.addFlags(Intent.FLAG_RECEIVER_NO_ABORT);
        final String action = intent.getAction();
        SubscriptionManager.putPhoneIdAndSubIdExtra(intent, mPhone.getPhoneId());

        // override the subId value in the intent with the values from tracker as they can be
        // different, specifically if the message is coming from SmsBroadcastUndelivered
        if (SubscriptionManager.isValidSubscriptionId(subId)) {
            SubscriptionManager.putSubscriptionIdExtra(intent, subId);
        }

        if (user.equals(UserHandle.ALL)) {
            // Get a list of currently started users.
            int[] users = null;
            final List<UserHandle> userHandles = mUserManager.getUserHandles(false);
            final List<UserHandle> runningUserHandles = new ArrayList();
            for (UserHandle handle : userHandles) {
                if (mUserManager.isUserRunning(handle)) {
                    runningUserHandles.add(handle);
                }
            }
            if (runningUserHandles.isEmpty()) {
                users = new int[] {user.getIdentifier()};
            } else {
                users = new int[runningUserHandles.size()];
                for (int i = 0; i < runningUserHandles.size(); i++) {
                    users[i] = runningUserHandles.get(i).getIdentifier();
                }
            }
            // Deliver the broadcast only to those running users that are permitted
            // by user policy.
            for (int i = users.length - 1; i >= 0; i--) {
                UserHandle targetUser = UserHandle.of(users[i]);
                if (users[i] != UserHandle.SYSTEM.getIdentifier()) {
                    // Is the user not allowed to use SMS?
                    if (hasUserRestriction(UserManager.DISALLOW_SMS, targetUser)) {
                        continue;
                    }
                    // Skip unknown users and managed profiles as well
                    if (mUserManager.isManagedProfile(users[i])) {
                        continue;
                    }
                }
                // Only pass in the resultReceiver when the user SYSTEM is processed.
                try {
                    mContext.createPackageContextAsUser(mContext.getPackageName(), 0, targetUser)
                            .sendOrderedBroadcast(intent, Activity.RESULT_OK, permission, appOp,
                                    users[i] == UserHandle.SYSTEM.getIdentifier()
                                            ? resultReceiver : null, getHandler(),
                                    null /* initialData */, null /* initialExtras */, opts);
                } catch (PackageManager.NameNotFoundException ignored) {
                }
            }
        } else {
            try {
                mContext.createPackageContextAsUser(mContext.getPackageName(), 0, user)
                        .sendOrderedBroadcast(intent, Activity.RESULT_OK, permission, appOp,
                                resultReceiver, getHandler(), null /* initialData */,
                                null /* initialExtras */, opts);
            } catch (PackageManager.NameNotFoundException ignored) {
            }
        }
    }

    private boolean hasUserRestriction(String restrictionKey, UserHandle userHandle) {
        final List<UserManager.EnforcingUser> sources = mUserManager
                .getUserRestrictionSources(restrictionKey, userHandle);
        return (sources != null && !sources.isEmpty());
    }

    /**
     * Helper for {@link SmsBroadcastUndelivered} to delete an old message in the raw table.
     */
    @UnsupportedAppUsage
    private void deleteFromRawTable(String deleteWhere, String[] deleteWhereArgs,
                                    int deleteType) {
        Uri uri = deleteType == DELETE_PERMANENTLY ? sRawUriPermanentDelete : sRawUri;
        int rows = mResolver.delete(uri, deleteWhere, deleteWhereArgs);
        if (rows == 0) {
            loge("No rows were deleted from raw table!");
        } else if (DBG) {
            log("Deleted " + rows + " rows from raw table.");
        }
    }

    @UnsupportedAppUsage
    private Bundle handleSmsWhitelisting(ComponentName target, boolean bgActivityStartAllowed) {
        String pkgName;
        String reason;
        if (target != null) {
            pkgName = target.getPackageName();
            reason = "sms-app";
        } else {
            pkgName = mContext.getPackageName();
            reason = "sms-broadcast";
        }
        BroadcastOptions bopts = null;
        Bundle bundle = null;
        if (bgActivityStartAllowed) {
            bopts = BroadcastOptions.makeBasic();
            bopts.setBackgroundActivityStartsAllowed(true);
            bundle = bopts.toBundle();
        }
        long duration = mPowerWhitelistManager.whitelistAppTemporarilyForEvent(
                pkgName, PowerWhitelistManager.EVENT_SMS, reason);
        if (bopts == null) bopts = BroadcastOptions.makeBasic();
        bopts.setTemporaryAppWhitelistDuration(duration);
        bundle = bopts.toBundle();

        return bundle;
    }

    /**
     * Creates and dispatches the intent to the default SMS app, appropriate port or via the {@link
     * AppSmsManager}.
     *
     * @param pdus message pdus
     * @param format the message format, typically "3gpp" or "3gpp2"
     * @param destPort the destination port
     * @param resultReceiver the receiver handling the delivery result
     */
    private void dispatchSmsDeliveryIntent(byte[][] pdus, String format, int destPort,
            SmsBroadcastReceiver resultReceiver, boolean isClass0, int subId, long messageId) {
        Intent intent = new Intent();
        intent.putExtra("pdus", pdus);
        intent.putExtra("format", format);
        if (messageId != 0L) {
            intent.putExtra("messageId", messageId);
        }

        if (destPort == -1) {
            intent.setAction(Intents.SMS_DELIVER_ACTION);
            // Direct the intent to only the default SMS app. If we can't find a default SMS app
            // then sent it to all broadcast receivers.
            // We are deliberately delivering to the primary user's default SMS App.
            ComponentName componentName = SmsApplication.getDefaultSmsApplication(mContext, true);
            if (componentName != null) {
                // Deliver SMS message only to this receiver.
                intent.setComponent(componentName);
                log("Delivering SMS to: " + componentName.getPackageName()
                        + " " + componentName.getClassName()
                        + " id: " + messageId);
            } else {
                intent.setComponent(null);
            }

            // Handle app specific sms messages.
            AppSmsManager appManager = mPhone.getAppSmsManager();
            if (appManager.handleSmsReceivedIntent(intent)) {
                // The AppSmsManager handled this intent, we're done.
                dropSms(resultReceiver);
                return;
            }
        } else {
            intent.setAction(Intents.DATA_SMS_RECEIVED_ACTION);
            Uri uri = Uri.parse("sms://localhost:" + destPort);
            intent.setData(uri);
            intent.setComponent(null);
        }

        Bundle options = handleSmsWhitelisting(intent.getComponent(), isClass0);
        dispatchIntent(intent, android.Manifest.permission.RECEIVE_SMS,
                AppOpsManager.OPSTR_RECEIVE_SMS, options, resultReceiver, UserHandle.SYSTEM, subId);
    }

    /**
     * Function to detect and handle duplicate messages. If the received message should replace an
     * existing message in the raw db, this function deletes the existing message. If an existing
     * message takes priority (for eg, existing message has already been broadcast), then this new
     * message should be dropped.
     * @return true if the message represented by the passed in tracker should be dropped,
     * false otherwise
     */
    private boolean checkAndHandleDuplicate(InboundSmsTracker tracker) throws SQLException {
        Pair<String, String[]> exactMatchQuery = tracker.getExactMatchDupDetectQuery();

        Cursor cursor = null;
        try {
            // Check for duplicate message segments
            cursor = mResolver.query(sRawUri, PDU_DELETED_FLAG_PROJECTION, exactMatchQuery.first,
                    exactMatchQuery.second, null);

            // moveToNext() returns false if no duplicates were found
            if (cursor != null && cursor.moveToNext()) {
                if (cursor.getCount() != 1) {
                    loge("Exact match query returned " + cursor.getCount() + " rows"
                            + " id: " + tracker.getMessageId());
                }

                // if the exact matching row is marked deleted, that means this message has already
                // been received and processed, and can be discarded as dup
                if (cursor.getInt(
                        PDU_DELETED_FLAG_PROJECTION_INDEX_MAPPING.get(DELETED_FLAG_COLUMN)) == 1) {
                    loge("Discarding duplicate message segment: " + tracker);
                    logDupPduMismatch(cursor, tracker);
                    return true;   // reject message
                } else {
                    // exact match duplicate is not marked deleted. If it is a multi-part segment,
                    // the code below for inexact match will take care of it. If it is a single
                    // part message, handle it here.
                    if (tracker.getMessageCount() == 1) {
                        // delete the old message segment permanently
                        deleteFromRawTable(exactMatchQuery.first, exactMatchQuery.second,
                                DELETE_PERMANENTLY);
                        loge("Replacing duplicate message: " + tracker);
                        logDupPduMismatch(cursor, tracker);
                    }
                }
            }
        } finally {
            if (cursor != null) {
                cursor.close();
            }
        }

        // The code above does an exact match. Multi-part message segments need an additional check
        // on top of that: if there is a message segment that conflicts this new one (may not be an
        // exact match), replace the old message segment with this one.
        if (tracker.getMessageCount() > 1) {
            Pair<String, String[]> inexactMatchQuery = tracker.getInexactMatchDupDetectQuery();
            cursor = null;
            try {
                // Check for duplicate message segments
                cursor = mResolver.query(sRawUri, PDU_DELETED_FLAG_PROJECTION,
                        inexactMatchQuery.first, inexactMatchQuery.second, null);

                // moveToNext() returns false if no duplicates were found
                if (cursor != null && cursor.moveToNext()) {
                    if (cursor.getCount() != 1) {
                        loge("Inexact match query returned " + cursor.getCount() + " rows"
                                + " id: " + tracker.getMessageId());
                    }
                    // delete the old message segment permanently
                    deleteFromRawTable(inexactMatchQuery.first, inexactMatchQuery.second,
                            DELETE_PERMANENTLY);
                    loge("Replacing duplicate message segment: " + tracker);
                    logDupPduMismatch(cursor, tracker);
                }
            } finally {
                if (cursor != null) {
                    cursor.close();
                }
            }
        }

        return false;
    }

    private void logDupPduMismatch(Cursor cursor, InboundSmsTracker tracker) {
        String oldPduString = cursor.getString(
                PDU_DELETED_FLAG_PROJECTION_INDEX_MAPPING.get(PDU_COLUMN));
        byte[] pdu = tracker.getPdu();
        byte[] oldPdu = HexDump.hexStringToByteArray(oldPduString);
        if (!Arrays.equals(oldPdu, tracker.getPdu())) {
            loge("Warning: dup message PDU of length " + pdu.length
                    + " is different from existing PDU of length " + oldPdu.length
                    + " id: " + tracker.getMessageId());
        }
    }

    /**
     * Insert a message PDU into the raw table so we can acknowledge it immediately.
     * If the device crashes before the broadcast to listeners completes, it will be delivered
     * from the raw table on the next device boot. For single-part messages, the deleteWhere
     * and deleteWhereArgs fields of the tracker will be set to delete the correct row after
     * the ordered broadcast completes.
     *
     * @param tracker the tracker to add to the raw table
     * @return true on success; false on failure to write to database
     */
    private int addTrackerToRawTable(InboundSmsTracker tracker, boolean deDup) {
        if (deDup) {
            try {
                if (checkAndHandleDuplicate(tracker)) {
                    return Intents.RESULT_SMS_DUPLICATED;   // reject message
                }
            } catch (SQLException e) {
                loge("Can't access SMS database"
                        + " id: " + tracker.getMessageId(),
                        e);
                return RESULT_SMS_DATABASE_ERROR;    // reject message
            }
        } else {
            logd("Skipped message de-duping logic");
        }

        String address = tracker.getAddress();
        String refNumber = Integer.toString(tracker.getReferenceNumber());
        String count = Integer.toString(tracker.getMessageCount());
        ContentValues values = tracker.getContentValues();

        if (VDBG) log("adding content values to raw table: " + values.toString());
        Uri newUri = mResolver.insert(sRawUri, values);
        if (DBG) log("URI of new row -> " + newUri);

        try {
            long rowId = ContentUris.parseId(newUri);
            if (tracker.getMessageCount() == 1) {
                // set the delete selection args for single-part message
                tracker.setDeleteWhere(SELECT_BY_ID, new String[]{Long.toString(rowId)});
            } else {
                // set the delete selection args for multi-part message
                String[] deleteWhereArgs = {address, refNumber, count};
                tracker.setDeleteWhere(tracker.getQueryForSegments(), deleteWhereArgs);
            }
            return Intents.RESULT_SMS_HANDLED;
        } catch (Exception e) {
            loge("error parsing URI for new row: " + newUri
                    + " id: " + tracker.getMessageId(), e);
            return RESULT_SMS_INVALID_URI;
        }
    }

    /**
     * Returns whether the default message format for the current radio technology is 3GPP2.
     * @return true if the radio technology uses 3GPP2 format by default, false for 3GPP format
     */
    static boolean isCurrentFormat3gpp2() {
        int activePhone = TelephonyManager.getDefault().getCurrentPhoneType();
        return (PHONE_TYPE_CDMA == activePhone);
    }

    /**
     * Handler for an {@link InboundSmsTracker} broadcast. Deletes PDUs from the raw table and
     * logs the broadcast duration (as an error if the other receivers were especially slow).
     */
    private final class SmsBroadcastReceiver extends BroadcastReceiver {
        @UnsupportedAppUsage
        private final String mDeleteWhere;
        @UnsupportedAppUsage
        private final String[] mDeleteWhereArgs;
        private long mBroadcastTimeNano;

        SmsBroadcastReceiver(InboundSmsTracker tracker) {
            mDeleteWhere = tracker.getDeleteWhere();
            mDeleteWhereArgs = tracker.getDeleteWhereArgs();
            mBroadcastTimeNano = System.nanoTime();
        }

        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            int subId = intent.getIntExtra(SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX,
                    SubscriptionManager.INVALID_SUBSCRIPTION_ID);
            if (action.equals(Intents.SMS_DELIVER_ACTION)) {
                // Now dispatch the notification only intent
                intent.setAction(Intents.SMS_RECEIVED_ACTION);
                // Allow registered broadcast receivers to get this intent even
                // when they are in the background.
                intent.setComponent(null);
                // All running users will be notified of the received sms.
                Bundle options = handleSmsWhitelisting(null, false /* bgActivityStartAllowed */);

                dispatchIntent(intent, android.Manifest.permission.RECEIVE_SMS,
                        AppOpsManager.OPSTR_RECEIVE_SMS,
                        options, this, UserHandle.ALL, subId);
            } else if (action.equals(Intents.WAP_PUSH_DELIVER_ACTION)) {
                // Now dispatch the notification only intent
                intent.setAction(Intents.WAP_PUSH_RECEIVED_ACTION);
                intent.setComponent(null);
                // Only the primary user will receive notification of incoming mms.
                // That app will do the actual downloading of the mms.
                long duration = mPowerWhitelistManager.whitelistAppTemporarilyForEvent(
                        mContext.getPackageName(),
                        PowerWhitelistManager.EVENT_MMS,
                        "mms-broadcast");
                BroadcastOptions bopts = BroadcastOptions.makeBasic();
                bopts.setTemporaryAppWhitelistDuration(duration);
                Bundle options = bopts.toBundle();

                String mimeType = intent.getType();
                dispatchIntent(intent, WapPushOverSms.getPermissionForType(mimeType),
                        WapPushOverSms.getAppOpsStringPermissionForIntent(mimeType), options, this,
                        UserHandle.SYSTEM, subId);
            } else {
                // Now that the intents have been deleted we can clean up the PDU data.
                if (!Intents.DATA_SMS_RECEIVED_ACTION.equals(action)
                        && !Intents.SMS_RECEIVED_ACTION.equals(action)
                        && !Intents.DATA_SMS_RECEIVED_ACTION.equals(action)
                        && !Intents.WAP_PUSH_RECEIVED_ACTION.equals(action)) {
                    loge("unexpected BroadcastReceiver action: " + action);
                }

                int rc = getResultCode();
                if ((rc != Activity.RESULT_OK) && (rc != Intents.RESULT_SMS_HANDLED)) {
                    loge("a broadcast receiver set the result code to " + rc
                            + ", deleting from raw table anyway!");
                } else if (DBG) {
                    log("successful broadcast, deleting from raw table.");
                }

                deleteFromRawTable(mDeleteWhere, mDeleteWhereArgs, MARK_DELETED);
                sendMessage(EVENT_BROADCAST_COMPLETE);

                int durationMillis = (int) ((System.nanoTime() - mBroadcastTimeNano) / 1000000);
                if (durationMillis >= 5000) {
                    loge("Slow ordered broadcast completion time: " + durationMillis + " ms");
                } else if (DBG) {
                    log("ordered broadcast completed in: " + durationMillis + " ms");
                }
            }
        }
    }

    /**
     * Callback that handles filtering results by carrier services.
     */
    private final class CarrierServicesSmsFilterCallback implements
            CarrierServicesSmsFilter.CarrierServicesSmsFilterCallbackInterface {
        private final byte[][] mPdus;
        private final int mDestPort;
        private final String mSmsFormat;
        private final SmsBroadcastReceiver mSmsBroadcastReceiver;
        private final boolean mUserUnlocked;
        private final boolean mIsClass0;
        private final int mSubId;
        private final long mMessageId;

        CarrierServicesSmsFilterCallback(byte[][] pdus, int destPort, String smsFormat,
                SmsBroadcastReceiver smsBroadcastReceiver,  boolean userUnlocked,
                boolean isClass0, int subId, long messageId) {
            mPdus = pdus;
            mDestPort = destPort;
            mSmsFormat = smsFormat;
            mSmsBroadcastReceiver = smsBroadcastReceiver;
            mUserUnlocked = userUnlocked;
            mIsClass0 = isClass0;
            mSubId = subId;
            mMessageId = messageId;
        }

        @Override
        public void onFilterComplete(int result) {
            logv("onFilterComplete: result is " + result);
            if ((result & CarrierMessagingService.RECEIVE_OPTIONS_DROP) == 0) {
                if (VisualVoicemailSmsFilter.filter(mContext, mPdus,
                        mSmsFormat, mDestPort, mSubId)) {
                    log("Visual voicemail SMS dropped"
                            + " id: " + mMessageId);
                    dropSms(mSmsBroadcastReceiver);
                    return;
                }

                if (mUserUnlocked) {
                    dispatchSmsDeliveryIntent(
                            mPdus, mSmsFormat, mDestPort, mSmsBroadcastReceiver, mIsClass0, mSubId,
                            mMessageId);
                } else {
                    // Don't do anything further, leave the message in the raw table if the
                    // credential-encrypted storage is still locked and show the new message
                    // notification if the message is visible to the user.
                    if (!isSkipNotifyFlagSet(result)) {
                        showNewMessageNotification();
                    }
                    sendMessage(EVENT_BROADCAST_COMPLETE);
                }
            } else {
                // Drop this SMS.
                dropSms(mSmsBroadcastReceiver);
            }
        }
    }

    private void dropSms(SmsBroadcastReceiver receiver) {
        // Needs phone package permissions.
        deleteFromRawTable(receiver.mDeleteWhere, receiver.mDeleteWhereArgs, MARK_DELETED);
        sendMessage(EVENT_BROADCAST_COMPLETE);
    }

    /** Checks whether the flag to skip new message notification is set in the bitmask returned
     *  from the carrier app.
     */
    @UnsupportedAppUsage
    private boolean isSkipNotifyFlagSet(int callbackResult) {
        return (callbackResult
            & RECEIVE_OPTIONS_SKIP_NOTIFY_WHEN_CREDENTIAL_PROTECTED_STORAGE_UNAVAILABLE) > 0;
    }

    /**
     * Log with debug level.
     * @param s the string to log
     */
    @UnsupportedAppUsage
    @Override
    protected void log(String s) {
        Rlog.d(getName(), s);
    }

    /**
     * Log with error level.
     * @param s the string to log
     */
    @UnsupportedAppUsage
    @Override
    protected void loge(String s) {
        Rlog.e(getName(), s);
    }

    /**
     * Log with error level.
     * @param s the string to log
     * @param e is a Throwable which logs additional information.
     */
    @Override
    protected void loge(String s, Throwable e) {
        Rlog.e(getName(), s, e);
    }

    /**
     * Store a received SMS into Telephony provider
     *
     * @param intent The intent containing the received SMS
     * @return The URI of written message
     */
    @UnsupportedAppUsage
    private Uri writeInboxMessage(Intent intent) {
        final SmsMessage[] messages = Telephony.Sms.Intents.getMessagesFromIntent(intent);
        if (messages == null || messages.length < 1) {
            loge("Failed to parse SMS pdu");
            return null;
        }
        // Sometimes, SmsMessage is null if it can’t be parsed correctly.
        for (final SmsMessage sms : messages) {
            if (sms == null) {
                loge("Can’t write null SmsMessage");
                return null;
            }
        }
        final ContentValues values = parseSmsMessage(messages);
        final long identity = Binder.clearCallingIdentity();
        try {
            return mContext.getContentResolver().insert(Telephony.Sms.Inbox.CONTENT_URI, values);
        } catch (Exception e) {
            loge("Failed to persist inbox message", e);
        } finally {
            Binder.restoreCallingIdentity(identity);
        }
        return null;
    }

    /**
     * Convert SmsMessage[] into SMS database schema columns
     *
     * @param msgs The SmsMessage array of the received SMS
     * @return ContentValues representing the columns of parsed SMS
     */
    private static ContentValues parseSmsMessage(SmsMessage[] msgs) {
        final SmsMessage sms = msgs[0];
        final ContentValues values = new ContentValues();
        values.put(Telephony.Sms.Inbox.ADDRESS, sms.getDisplayOriginatingAddress());
        values.put(Telephony.Sms.Inbox.BODY, buildMessageBodyFromPdus(msgs));
        values.put(Telephony.Sms.Inbox.DATE_SENT, sms.getTimestampMillis());
        values.put(Telephony.Sms.Inbox.DATE, System.currentTimeMillis());
        values.put(Telephony.Sms.Inbox.PROTOCOL, sms.getProtocolIdentifier());
        values.put(Telephony.Sms.Inbox.SEEN, 0);
        values.put(Telephony.Sms.Inbox.READ, 0);
        final String subject = sms.getPseudoSubject();
        if (!TextUtils.isEmpty(subject)) {
            values.put(Telephony.Sms.Inbox.SUBJECT, subject);
        }
        values.put(Telephony.Sms.Inbox.REPLY_PATH_PRESENT, sms.isReplyPathPresent() ? 1 : 0);
        values.put(Telephony.Sms.Inbox.SERVICE_CENTER, sms.getServiceCenterAddress());
        return values;
    }

    /**
     * Build up the SMS message body from the SmsMessage array of received SMS
     *
     * @param msgs The SmsMessage array of the received SMS
     * @return The text message body
     */
    private static String buildMessageBodyFromPdus(SmsMessage[] msgs) {
        if (msgs.length == 1) {
            // There is only one part, so grab the body directly.
            return replaceFormFeeds(msgs[0].getDisplayMessageBody());
        } else {
            // Build up the body from the parts.
            StringBuilder body = new StringBuilder();
            for (SmsMessage msg: msgs) {
                // getDisplayMessageBody() can NPE if mWrappedMessage inside is null.
                body.append(msg.getDisplayMessageBody());
            }
            return replaceFormFeeds(body.toString());
        }
    }

    @Override
    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
        super.dump(fd, pw, args);
        if (mCellBroadcastServiceManager != null) {
            mCellBroadcastServiceManager.dump(fd, pw, args);
        }
        mLocalLog.dump(fd, pw, args);
    }

    // Some providers send formfeeds in their messages. Convert those formfeeds to newlines.
    private static String replaceFormFeeds(String s) {
        return s == null ? "" : s.replace('\f', '\n');
    }

    @VisibleForTesting
    public PowerManager.WakeLock getWakeLock() {
        return mWakeLock;
    }

    @VisibleForTesting
    public int getWakeLockTimeout() {
        return mWakeLockTimeout;
    }

    /**
    * Sets the wakelock timeout to {@link timeOut} milliseconds
    */
    private void setWakeLockTimeout(int timeOut) {
        mWakeLockTimeout = timeOut;
    }

    /**
     * Handler for the broadcast sent when the new message notification is clicked. It launches the
     * default SMS app.
     */
    private static class NewMessageNotificationActionReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            if (ACTION_OPEN_SMS_APP.equals(intent.getAction())) {
                // do nothing if the user had not unlocked the device yet
                UserManager userManager =
                        (UserManager) context.getSystemService(Context.USER_SERVICE);
                if (userManager.isUserUnlocked()) {
                    context.startActivity(context.getPackageManager().getLaunchIntentForPackage(
                            Telephony.Sms.getDefaultSmsPackage(context)));
                }
            }
        }
    }

    protected byte[] decodeHexString(String hexString) {
        if (hexString == null || hexString.length() % 2 == 1) {
            return null;
        }
        byte[] bytes = new byte[hexString.length() / 2];
        for (int i = 0; i < hexString.length(); i += 2) {
            bytes[i / 2] = hexToByte(hexString.substring(i, i + 2));
        }
        return bytes;
    }

    private byte hexToByte(String hexString) {
        int firstDigit = toDigit(hexString.charAt(0));
        int secondDigit = toDigit(hexString.charAt(1));
        return (byte) ((firstDigit << 4) + secondDigit);
    }

    private int toDigit(char hexChar) {
        int digit = Character.digit(hexChar, 16);
        if (digit == -1) {
            return 0;
        }
        return digit;
    }


    /**
     * Registers the broadcast receiver to launch the default SMS app when the user clicks the
     * new message notification.
     */
    static void registerNewMessageNotificationActionHandler(Context context) {
        IntentFilter userFilter = new IntentFilter();
        userFilter.addAction(ACTION_OPEN_SMS_APP);
        context.registerReceiver(new NewMessageNotificationActionReceiver(), userFilter);
    }

    protected abstract class CbTestBroadcastReceiver extends BroadcastReceiver {

        protected abstract void handleTestAction(Intent intent);

        protected final String mTestAction;

        public CbTestBroadcastReceiver(String testAction) {
            mTestAction = testAction;
        }

        @Override
        public void onReceive(Context context, Intent intent) {
            logd("Received test intent action=" + intent.getAction());
            if (intent.getAction().equals(mTestAction)) {
                // Return early if phone_id is explicilty included and does not match mPhone.
                // If phone_id extra is not included, continue.
                int phoneId = mPhone.getPhoneId();
                if (intent.getIntExtra("phone_id", phoneId) != phoneId) {
                    return;
                }
                handleTestAction(intent);
            }
        }
    }
}
