10d4bcdf379842af4b6304809156971e926f374f0Jake Hamby/*
20d4bcdf379842af4b6304809156971e926f374f0Jake Hamby * Copyright (C) 2013 The Android Open Source Project
30d4bcdf379842af4b6304809156971e926f374f0Jake Hamby *
40d4bcdf379842af4b6304809156971e926f374f0Jake Hamby * Licensed under the Apache License, Version 2.0 (the "License");
50d4bcdf379842af4b6304809156971e926f374f0Jake Hamby * you may not use this file except in compliance with the License.
60d4bcdf379842af4b6304809156971e926f374f0Jake Hamby * You may obtain a copy of the License at
70d4bcdf379842af4b6304809156971e926f374f0Jake Hamby *
80d4bcdf379842af4b6304809156971e926f374f0Jake Hamby *      http://www.apache.org/licenses/LICENSE-2.0
90d4bcdf379842af4b6304809156971e926f374f0Jake Hamby *
100d4bcdf379842af4b6304809156971e926f374f0Jake Hamby * Unless required by applicable law or agreed to in writing, software
110d4bcdf379842af4b6304809156971e926f374f0Jake Hamby * distributed under the License is distributed on an "AS IS" BASIS,
120d4bcdf379842af4b6304809156971e926f374f0Jake Hamby * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
130d4bcdf379842af4b6304809156971e926f374f0Jake Hamby * See the License for the specific language governing permissions and
140d4bcdf379842af4b6304809156971e926f374f0Jake Hamby * limitations under the License.
150d4bcdf379842af4b6304809156971e926f374f0Jake Hamby */
160d4bcdf379842af4b6304809156971e926f374f0Jake Hamby
170d4bcdf379842af4b6304809156971e926f374f0Jake Hambypackage com.android.internal.telephony.cdma;
180d4bcdf379842af4b6304809156971e926f374f0Jake Hamby
190d4bcdf379842af4b6304809156971e926f374f0Jake Hambyimport android.app.Activity;
200d4bcdf379842af4b6304809156971e926f374f0Jake Hambyimport android.content.Context;
210d4bcdf379842af4b6304809156971e926f374f0Jake Hambyimport android.content.res.Resources;
220d4bcdf379842af4b6304809156971e926f374f0Jake Hambyimport android.os.Message;
230d4bcdf379842af4b6304809156971e926f374f0Jake Hambyimport android.os.SystemProperties;
240d4bcdf379842af4b6304809156971e926f374f0Jake Hambyimport android.provider.Telephony.Sms.Intents;
250d4bcdf379842af4b6304809156971e926f374f0Jake Hambyimport android.telephony.SmsCbMessage;
260d4bcdf379842af4b6304809156971e926f374f0Jake Hamby
270d4bcdf379842af4b6304809156971e926f374f0Jake Hambyimport com.android.internal.telephony.CellBroadcastHandler;
280d4bcdf379842af4b6304809156971e926f374f0Jake Hambyimport com.android.internal.telephony.CommandsInterface;
290d4bcdf379842af4b6304809156971e926f374f0Jake Hambyimport com.android.internal.telephony.InboundSmsHandler;
300d4bcdf379842af4b6304809156971e926f374f0Jake Hambyimport com.android.internal.telephony.InboundSmsTracker;
310d4bcdf379842af4b6304809156971e926f374f0Jake Hambyimport com.android.internal.telephony.PhoneBase;
320d4bcdf379842af4b6304809156971e926f374f0Jake Hambyimport com.android.internal.telephony.SmsConstants;
330d4bcdf379842af4b6304809156971e926f374f0Jake Hambyimport com.android.internal.telephony.SmsMessageBase;
340d4bcdf379842af4b6304809156971e926f374f0Jake Hambyimport com.android.internal.telephony.SmsStorageMonitor;
350d4bcdf379842af4b6304809156971e926f374f0Jake Hambyimport com.android.internal.telephony.TelephonyProperties;
360d4bcdf379842af4b6304809156971e926f374f0Jake Hambyimport com.android.internal.telephony.WspTypeDecoder;
370d4bcdf379842af4b6304809156971e926f374f0Jake Hambyimport com.android.internal.telephony.cdma.sms.SmsEnvelope;
380d4bcdf379842af4b6304809156971e926f374f0Jake Hamby
390d4bcdf379842af4b6304809156971e926f374f0Jake Hambyimport java.util.Arrays;
400d4bcdf379842af4b6304809156971e926f374f0Jake Hamby
410d4bcdf379842af4b6304809156971e926f374f0Jake Hamby/**
420d4bcdf379842af4b6304809156971e926f374f0Jake Hamby * Subclass of {@link InboundSmsHandler} for 3GPP2 type messages.
430d4bcdf379842af4b6304809156971e926f374f0Jake Hamby */
440d4bcdf379842af4b6304809156971e926f374f0Jake Hambypublic class CdmaInboundSmsHandler extends InboundSmsHandler {
450d4bcdf379842af4b6304809156971e926f374f0Jake Hamby
460d4bcdf379842af4b6304809156971e926f374f0Jake Hamby    private final CdmaSMSDispatcher mSmsDispatcher;
470d4bcdf379842af4b6304809156971e926f374f0Jake Hamby    private final CdmaServiceCategoryProgramHandler mServiceCategoryProgramHandler;
480d4bcdf379842af4b6304809156971e926f374f0Jake Hamby
490d4bcdf379842af4b6304809156971e926f374f0Jake Hamby    private byte[] mLastDispatchedSmsFingerprint;
500d4bcdf379842af4b6304809156971e926f374f0Jake Hamby    private byte[] mLastAcknowledgedSmsFingerprint;
510d4bcdf379842af4b6304809156971e926f374f0Jake Hamby
520d4bcdf379842af4b6304809156971e926f374f0Jake Hamby    private final boolean mCheckForDuplicatePortsInOmadmWapPush = Resources.getSystem().getBoolean(
530d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            com.android.internal.R.bool.config_duplicate_port_omadm_wappush);
540d4bcdf379842af4b6304809156971e926f374f0Jake Hamby
550d4bcdf379842af4b6304809156971e926f374f0Jake Hamby    /**
560d4bcdf379842af4b6304809156971e926f374f0Jake Hamby     * Create a new inbound SMS handler for CDMA.
570d4bcdf379842af4b6304809156971e926f374f0Jake Hamby     */
580d4bcdf379842af4b6304809156971e926f374f0Jake Hamby    private CdmaInboundSmsHandler(Context context, SmsStorageMonitor storageMonitor,
590d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            PhoneBase phone, CdmaSMSDispatcher smsDispatcher) {
60d2feaf918ab0c1173d4ada182532e48d0c0d3f77Wink Saville        super("CdmaInboundSmsHandler", context, storageMonitor, phone,
61fce951e90d421ba2ab3da3f64d0f5192ab769e22Sukanya Rajkhowa                CellBroadcastHandler.makeCellBroadcastHandler(context, phone));
620d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        mSmsDispatcher = smsDispatcher;
630d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        mServiceCategoryProgramHandler = CdmaServiceCategoryProgramHandler.makeScpHandler(context,
640d4bcdf379842af4b6304809156971e926f374f0Jake Hamby                phone.mCi);
650d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        phone.mCi.setOnNewCdmaSms(getHandler(), EVENT_NEW_SMS, null);
660d4bcdf379842af4b6304809156971e926f374f0Jake Hamby    }
670d4bcdf379842af4b6304809156971e926f374f0Jake Hamby
680d4bcdf379842af4b6304809156971e926f374f0Jake Hamby    /**
690d4bcdf379842af4b6304809156971e926f374f0Jake Hamby     * Unregister for CDMA SMS.
700d4bcdf379842af4b6304809156971e926f374f0Jake Hamby     */
710d4bcdf379842af4b6304809156971e926f374f0Jake Hamby    @Override
720d4bcdf379842af4b6304809156971e926f374f0Jake Hamby    protected void onQuitting() {
730d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        mPhone.mCi.unSetOnNewCdmaSms(getHandler());
740d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        mCellBroadcastHandler.dispose();
750d4bcdf379842af4b6304809156971e926f374f0Jake Hamby
760d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        if (DBG) log("unregistered for 3GPP2 SMS");
770d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        super.onQuitting();
780d4bcdf379842af4b6304809156971e926f374f0Jake Hamby    }
790d4bcdf379842af4b6304809156971e926f374f0Jake Hamby
800d4bcdf379842af4b6304809156971e926f374f0Jake Hamby    /**
810d4bcdf379842af4b6304809156971e926f374f0Jake Hamby     * Wait for state machine to enter startup state. We can't send any messages until then.
820d4bcdf379842af4b6304809156971e926f374f0Jake Hamby     */
830d4bcdf379842af4b6304809156971e926f374f0Jake Hamby    public static CdmaInboundSmsHandler makeInboundSmsHandler(Context context,
840d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            SmsStorageMonitor storageMonitor, PhoneBase phone, CdmaSMSDispatcher smsDispatcher) {
850d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        CdmaInboundSmsHandler handler = new CdmaInboundSmsHandler(context, storageMonitor,
860d4bcdf379842af4b6304809156971e926f374f0Jake Hamby                phone, smsDispatcher);
870d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        handler.start();
880d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        return handler;
890d4bcdf379842af4b6304809156971e926f374f0Jake Hamby    }
900d4bcdf379842af4b6304809156971e926f374f0Jake Hamby
910d4bcdf379842af4b6304809156971e926f374f0Jake Hamby    /**
920d4bcdf379842af4b6304809156971e926f374f0Jake Hamby     * Return whether the device is in Emergency Call Mode (only for 3GPP2).
930d4bcdf379842af4b6304809156971e926f374f0Jake Hamby     * @return true if the device is in ECM; false otherwise
940d4bcdf379842af4b6304809156971e926f374f0Jake Hamby     */
950d4bcdf379842af4b6304809156971e926f374f0Jake Hamby    private static boolean isInEmergencyCallMode() {
960d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        String inEcm = SystemProperties.get(TelephonyProperties.PROPERTY_INECM_MODE, "false");
970d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        return "true".equals(inEcm);
980d4bcdf379842af4b6304809156971e926f374f0Jake Hamby    }
990d4bcdf379842af4b6304809156971e926f374f0Jake Hamby
1000d4bcdf379842af4b6304809156971e926f374f0Jake Hamby    /**
1010d4bcdf379842af4b6304809156971e926f374f0Jake Hamby     * Return true if this handler is for 3GPP2 messages; false for 3GPP format.
1020d4bcdf379842af4b6304809156971e926f374f0Jake Hamby     * @return true (3GPP2)
1030d4bcdf379842af4b6304809156971e926f374f0Jake Hamby     */
1040d4bcdf379842af4b6304809156971e926f374f0Jake Hamby    @Override
1050d4bcdf379842af4b6304809156971e926f374f0Jake Hamby    protected boolean is3gpp2() {
1060d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        return true;
1070d4bcdf379842af4b6304809156971e926f374f0Jake Hamby    }
1080d4bcdf379842af4b6304809156971e926f374f0Jake Hamby
1090d4bcdf379842af4b6304809156971e926f374f0Jake Hamby    /**
1100d4bcdf379842af4b6304809156971e926f374f0Jake Hamby     * Process Cell Broadcast, Voicemail Notification, and other 3GPP/3GPP2-specific messages.
1110d4bcdf379842af4b6304809156971e926f374f0Jake Hamby     * @param smsb the SmsMessageBase object from the RIL
1120d4bcdf379842af4b6304809156971e926f374f0Jake Hamby     * @return true if the message was handled here; false to continue processing
1130d4bcdf379842af4b6304809156971e926f374f0Jake Hamby     */
1140d4bcdf379842af4b6304809156971e926f374f0Jake Hamby    @Override
1150d4bcdf379842af4b6304809156971e926f374f0Jake Hamby    protected int dispatchMessageRadioSpecific(SmsMessageBase smsb) {
1160d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        if (isInEmergencyCallMode()) {
1170d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            return Activity.RESULT_OK;
1180d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        }
1190d4bcdf379842af4b6304809156971e926f374f0Jake Hamby
1200d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        SmsMessage sms = (SmsMessage) smsb;
1210d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        boolean isBroadcastType = (SmsEnvelope.MESSAGE_TYPE_BROADCAST == sms.getMessageType());
1220d4bcdf379842af4b6304809156971e926f374f0Jake Hamby
1230d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        // Handle CMAS emergency broadcast messages.
1240d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        if (isBroadcastType) {
1250d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            log("Broadcast type message");
1260d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            SmsCbMessage cbMessage = sms.parseBroadcastSms();
1270d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            if (cbMessage != null) {
1280d4bcdf379842af4b6304809156971e926f374f0Jake Hamby                mCellBroadcastHandler.dispatchSmsMessage(cbMessage);
1290d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            } else {
1300d4bcdf379842af4b6304809156971e926f374f0Jake Hamby                loge("error trying to parse broadcast SMS");
1310d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            }
1320d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            return Intents.RESULT_SMS_HANDLED;
1330d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        }
1340d4bcdf379842af4b6304809156971e926f374f0Jake Hamby
1350d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        // Initialize fingerprint field, and see if we have a network duplicate SMS.
1360d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        mLastDispatchedSmsFingerprint = sms.getIncomingSmsFingerprint();
1370d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        if (mLastAcknowledgedSmsFingerprint != null &&
1380d4bcdf379842af4b6304809156971e926f374f0Jake Hamby                Arrays.equals(mLastDispatchedSmsFingerprint, mLastAcknowledgedSmsFingerprint)) {
1390d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            return Intents.RESULT_SMS_HANDLED;
1400d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        }
1410d4bcdf379842af4b6304809156971e926f374f0Jake Hamby
1420d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        // Decode BD stream and set sms variables.
1430d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        sms.parseSms();
1440d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        int teleService = sms.getTeleService();
1450d4bcdf379842af4b6304809156971e926f374f0Jake Hamby
1460d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        switch (teleService) {
1470d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            case SmsEnvelope.TELESERVICE_VMN:
1480d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            case SmsEnvelope.TELESERVICE_MWI:
1490d4bcdf379842af4b6304809156971e926f374f0Jake Hamby                // handle voicemail indication
1500d4bcdf379842af4b6304809156971e926f374f0Jake Hamby                handleVoicemailTeleservice(sms);
1510d4bcdf379842af4b6304809156971e926f374f0Jake Hamby                return Intents.RESULT_SMS_HANDLED;
1520d4bcdf379842af4b6304809156971e926f374f0Jake Hamby
1530d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            case SmsEnvelope.TELESERVICE_WMT:
1540d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            case SmsEnvelope.TELESERVICE_WEMT:
1550d4bcdf379842af4b6304809156971e926f374f0Jake Hamby                if (sms.isStatusReportMessage()) {
1560d4bcdf379842af4b6304809156971e926f374f0Jake Hamby                    mSmsDispatcher.sendStatusReportMessage(sms);
1570d4bcdf379842af4b6304809156971e926f374f0Jake Hamby                    return Intents.RESULT_SMS_HANDLED;
1580d4bcdf379842af4b6304809156971e926f374f0Jake Hamby                }
1590d4bcdf379842af4b6304809156971e926f374f0Jake Hamby                break;
1600d4bcdf379842af4b6304809156971e926f374f0Jake Hamby
1610d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            case SmsEnvelope.TELESERVICE_SCPT:
1620d4bcdf379842af4b6304809156971e926f374f0Jake Hamby                mServiceCategoryProgramHandler.dispatchSmsMessage(sms);
1630d4bcdf379842af4b6304809156971e926f374f0Jake Hamby                return Intents.RESULT_SMS_HANDLED;
1640d4bcdf379842af4b6304809156971e926f374f0Jake Hamby
1650d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            case SmsEnvelope.TELESERVICE_WAP:
1660d4bcdf379842af4b6304809156971e926f374f0Jake Hamby                // handled below, after storage check
1670d4bcdf379842af4b6304809156971e926f374f0Jake Hamby                break;
1680d4bcdf379842af4b6304809156971e926f374f0Jake Hamby
1690d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            default:
1700d4bcdf379842af4b6304809156971e926f374f0Jake Hamby                loge("unsupported teleservice 0x" + Integer.toHexString(teleService));
1710d4bcdf379842af4b6304809156971e926f374f0Jake Hamby                return Intents.RESULT_SMS_UNSUPPORTED;
1720d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        }
1730d4bcdf379842af4b6304809156971e926f374f0Jake Hamby
1740d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        if (!mStorageMonitor.isStorageAvailable() &&
1750d4bcdf379842af4b6304809156971e926f374f0Jake Hamby                sms.getMessageClass() != SmsConstants.MessageClass.CLASS_0) {
1760d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            // It's a storable message and there's no storage available.  Bail.
1770d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            // (See C.S0015-B v2.0 for a description of "Immediate Display"
1780d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            // messages, which we represent as CLASS_0.)
1790d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            return Intents.RESULT_SMS_OUT_OF_MEMORY;
1800d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        }
1810d4bcdf379842af4b6304809156971e926f374f0Jake Hamby
1820d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        if (SmsEnvelope.TELESERVICE_WAP == teleService) {
1830d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            return processCdmaWapPdu(sms.getUserData(), sms.mMessageRef,
1840d4bcdf379842af4b6304809156971e926f374f0Jake Hamby                    sms.getOriginatingAddress(), sms.getTimestampMillis());
1850d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        }
1860d4bcdf379842af4b6304809156971e926f374f0Jake Hamby
1870d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        return dispatchNormalMessage(smsb);
1880d4bcdf379842af4b6304809156971e926f374f0Jake Hamby    }
1890d4bcdf379842af4b6304809156971e926f374f0Jake Hamby
1900d4bcdf379842af4b6304809156971e926f374f0Jake Hamby    /**
1910d4bcdf379842af4b6304809156971e926f374f0Jake Hamby     * Send an acknowledge message.
1920d4bcdf379842af4b6304809156971e926f374f0Jake Hamby     * @param success indicates that last message was successfully received.
1930d4bcdf379842af4b6304809156971e926f374f0Jake Hamby     * @param result result code indicating any error
1940d4bcdf379842af4b6304809156971e926f374f0Jake Hamby     * @param response callback message sent when operation completes.
1950d4bcdf379842af4b6304809156971e926f374f0Jake Hamby     */
1960d4bcdf379842af4b6304809156971e926f374f0Jake Hamby    @Override
1970d4bcdf379842af4b6304809156971e926f374f0Jake Hamby    protected void acknowledgeLastIncomingSms(boolean success, int result, Message response) {
1980d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        if (isInEmergencyCallMode()) {
1990d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            return;
2000d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        }
2010d4bcdf379842af4b6304809156971e926f374f0Jake Hamby
2020d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        int causeCode = resultToCause(result);
2030d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        mPhone.mCi.acknowledgeLastIncomingCdmaSms(success, causeCode, response);
2040d4bcdf379842af4b6304809156971e926f374f0Jake Hamby
2050d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        if (causeCode == 0) {
2060d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            mLastAcknowledgedSmsFingerprint = mLastDispatchedSmsFingerprint;
2070d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        }
2080d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        mLastDispatchedSmsFingerprint = null;
2090d4bcdf379842af4b6304809156971e926f374f0Jake Hamby    }
2100d4bcdf379842af4b6304809156971e926f374f0Jake Hamby
2110d4bcdf379842af4b6304809156971e926f374f0Jake Hamby    /**
212d2feaf918ab0c1173d4ada182532e48d0c0d3f77Wink Saville     * Called when the phone changes the default method updates mPhone
213d2feaf918ab0c1173d4ada182532e48d0c0d3f77Wink Saville     * mStorageMonitor and mCellBroadcastHandler.updatePhoneObject.
214d2feaf918ab0c1173d4ada182532e48d0c0d3f77Wink Saville     * Override if different or other behavior is desired.
215d2feaf918ab0c1173d4ada182532e48d0c0d3f77Wink Saville     *
216d2feaf918ab0c1173d4ada182532e48d0c0d3f77Wink Saville     * @param phone
217d2feaf918ab0c1173d4ada182532e48d0c0d3f77Wink Saville     */
218d2feaf918ab0c1173d4ada182532e48d0c0d3f77Wink Saville    @Override
219d2feaf918ab0c1173d4ada182532e48d0c0d3f77Wink Saville    protected void onUpdatePhoneObject(PhoneBase phone) {
220d2feaf918ab0c1173d4ada182532e48d0c0d3f77Wink Saville        super.onUpdatePhoneObject(phone);
221d2feaf918ab0c1173d4ada182532e48d0c0d3f77Wink Saville        mCellBroadcastHandler.updatePhoneObject(phone);
222d2feaf918ab0c1173d4ada182532e48d0c0d3f77Wink Saville    }
223d2feaf918ab0c1173d4ada182532e48d0c0d3f77Wink Saville
224d2feaf918ab0c1173d4ada182532e48d0c0d3f77Wink Saville    /**
2250d4bcdf379842af4b6304809156971e926f374f0Jake Hamby     * Convert Android result code to CDMA SMS failure cause.
2260d4bcdf379842af4b6304809156971e926f374f0Jake Hamby     * @param rc the Android SMS intent result value
2270d4bcdf379842af4b6304809156971e926f374f0Jake Hamby     * @return 0 for success, or a CDMA SMS failure cause value
2280d4bcdf379842af4b6304809156971e926f374f0Jake Hamby     */
2290d4bcdf379842af4b6304809156971e926f374f0Jake Hamby    private static int resultToCause(int rc) {
2300d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        switch (rc) {
2310d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        case Activity.RESULT_OK:
2320d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        case Intents.RESULT_SMS_HANDLED:
2330d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            // Cause code is ignored on success.
2340d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            return 0;
2350d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        case Intents.RESULT_SMS_OUT_OF_MEMORY:
2360d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            return CommandsInterface.CDMA_SMS_FAIL_CAUSE_RESOURCE_SHORTAGE;
2370d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        case Intents.RESULT_SMS_UNSUPPORTED:
2380d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            return CommandsInterface.CDMA_SMS_FAIL_CAUSE_INVALID_TELESERVICE_ID;
2390d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        case Intents.RESULT_SMS_GENERIC_ERROR:
2400d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        default:
2410d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            return CommandsInterface.CDMA_SMS_FAIL_CAUSE_ENCODING_PROBLEM;
2420d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        }
2430d4bcdf379842af4b6304809156971e926f374f0Jake Hamby    }
2440d4bcdf379842af4b6304809156971e926f374f0Jake Hamby
2450d4bcdf379842af4b6304809156971e926f374f0Jake Hamby    /**
2460d4bcdf379842af4b6304809156971e926f374f0Jake Hamby     * Handle {@link SmsEnvelope#TELESERVICE_VMN} and {@link SmsEnvelope#TELESERVICE_MWI}.
2470d4bcdf379842af4b6304809156971e926f374f0Jake Hamby     * @param sms the message to process
2480d4bcdf379842af4b6304809156971e926f374f0Jake Hamby     */
2490d4bcdf379842af4b6304809156971e926f374f0Jake Hamby    private void handleVoicemailTeleservice(SmsMessage sms) {
2500d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        int voicemailCount = sms.getNumOfVoicemails();
2510d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        if (DBG) log("Voicemail count=" + voicemailCount);
2520d4bcdf379842af4b6304809156971e926f374f0Jake Hamby
25326a4150cfb8cd317eb64994b9d9fd6109bd87ba7Sukanya Rajkhowa        // range check
25426a4150cfb8cd317eb64994b9d9fd6109bd87ba7Sukanya Rajkhowa        if (voicemailCount < 0) {
25526a4150cfb8cd317eb64994b9d9fd6109bd87ba7Sukanya Rajkhowa            voicemailCount = -1;
25626a4150cfb8cd317eb64994b9d9fd6109bd87ba7Sukanya Rajkhowa        } else if (voicemailCount > 99) {
25726a4150cfb8cd317eb64994b9d9fd6109bd87ba7Sukanya Rajkhowa            // C.S0015-B v2, 4.5.12
25826a4150cfb8cd317eb64994b9d9fd6109bd87ba7Sukanya Rajkhowa            // range: 0-99
25926a4150cfb8cd317eb64994b9d9fd6109bd87ba7Sukanya Rajkhowa            voicemailCount = 99;
26026a4150cfb8cd317eb64994b9d9fd6109bd87ba7Sukanya Rajkhowa        }
26126a4150cfb8cd317eb64994b9d9fd6109bd87ba7Sukanya Rajkhowa        // update voice mail count in phone
26226a4150cfb8cd317eb64994b9d9fd6109bd87ba7Sukanya Rajkhowa        mPhone.setVoiceMessageCount(voicemailCount);
26326a4150cfb8cd317eb64994b9d9fd6109bd87ba7Sukanya Rajkhowa        // store voice mail count in preferences
26426a4150cfb8cd317eb64994b9d9fd6109bd87ba7Sukanya Rajkhowa        storeVoiceMailCount();
2650d4bcdf379842af4b6304809156971e926f374f0Jake Hamby    }
2660d4bcdf379842af4b6304809156971e926f374f0Jake Hamby
2670d4bcdf379842af4b6304809156971e926f374f0Jake Hamby    /**
2680d4bcdf379842af4b6304809156971e926f374f0Jake Hamby     * Processes inbound messages that are in the WAP-WDP PDU format. See
2690d4bcdf379842af4b6304809156971e926f374f0Jake Hamby     * wap-259-wdp-20010614-a section 6.5 for details on the WAP-WDP PDU format.
2700d4bcdf379842af4b6304809156971e926f374f0Jake Hamby     * WDP segments are gathered until a datagram completes and gets dispatched.
2710d4bcdf379842af4b6304809156971e926f374f0Jake Hamby     *
2720d4bcdf379842af4b6304809156971e926f374f0Jake Hamby     * @param pdu The WAP-WDP PDU segment
2730d4bcdf379842af4b6304809156971e926f374f0Jake Hamby     * @return a result code from {@link android.provider.Telephony.Sms.Intents}, or
2740d4bcdf379842af4b6304809156971e926f374f0Jake Hamby     *         {@link Activity#RESULT_OK} if the message has been broadcast
2750d4bcdf379842af4b6304809156971e926f374f0Jake Hamby     *         to applications
2760d4bcdf379842af4b6304809156971e926f374f0Jake Hamby     */
2770d4bcdf379842af4b6304809156971e926f374f0Jake Hamby    private int processCdmaWapPdu(byte[] pdu, int referenceNumber, String address,
2780d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            long timestamp) {
2790d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        int index = 0;
2800d4bcdf379842af4b6304809156971e926f374f0Jake Hamby
2810d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        int msgType = (0xFF & pdu[index++]);
2820d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        if (msgType != 0) {
2830d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            log("Received a WAP SMS which is not WDP. Discard.");
2840d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            return Intents.RESULT_SMS_HANDLED;
2850d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        }
2860d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        int totalSegments = (0xFF & pdu[index++]);   // >= 1
2870d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        int segment = (0xFF & pdu[index++]);         // >= 0
2880d4bcdf379842af4b6304809156971e926f374f0Jake Hamby
2890d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        if (segment >= totalSegments) {
2900d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            loge("WDP bad segment #" + segment + " expecting 0-" + (totalSegments - 1));
2910d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            return Intents.RESULT_SMS_HANDLED;
2920d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        }
2930d4bcdf379842af4b6304809156971e926f374f0Jake Hamby
2940d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        // Only the first segment contains sourcePort and destination Port
2950d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        int sourcePort = 0;
2960d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        int destinationPort = 0;
2970d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        if (segment == 0) {
2980d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            //process WDP segment
2990d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            sourcePort = (0xFF & pdu[index++]) << 8;
3000d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            sourcePort |= 0xFF & pdu[index++];
3010d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            destinationPort = (0xFF & pdu[index++]) << 8;
3020d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            destinationPort |= 0xFF & pdu[index++];
3030d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            // Some carriers incorrectly send duplicate port fields in omadm wap pushes.
3040d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            // If configured, check for that here
3050d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            if (mCheckForDuplicatePortsInOmadmWapPush) {
3060d4bcdf379842af4b6304809156971e926f374f0Jake Hamby                if (checkDuplicatePortOmadmWapPush(pdu, index)) {
3070d4bcdf379842af4b6304809156971e926f374f0Jake Hamby                    index = index + 4; // skip duplicate port fields
3080d4bcdf379842af4b6304809156971e926f374f0Jake Hamby                }
3090d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            }
3100d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        }
3110d4bcdf379842af4b6304809156971e926f374f0Jake Hamby
3120d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        // Lookup all other related parts
3130d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        log("Received WAP PDU. Type = " + msgType + ", originator = " + address
3140d4bcdf379842af4b6304809156971e926f374f0Jake Hamby                + ", src-port = " + sourcePort + ", dst-port = " + destinationPort
3150d4bcdf379842af4b6304809156971e926f374f0Jake Hamby                + ", ID = " + referenceNumber + ", segment# = " + segment + '/' + totalSegments);
3160d4bcdf379842af4b6304809156971e926f374f0Jake Hamby
3170d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        // pass the user data portion of the PDU to the shared handler in SMSDispatcher
3180d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        byte[] userData = new byte[pdu.length - index];
3190d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        System.arraycopy(pdu, index, userData, 0, pdu.length - index);
3200d4bcdf379842af4b6304809156971e926f374f0Jake Hamby
3210d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        InboundSmsTracker tracker = new InboundSmsTracker(userData, timestamp, destinationPort,
3228b61e10b480d3a7bae41025a97f3bd27ee5ed610Jake Hamby                true, address, referenceNumber, segment, totalSegments, true);
3230d4bcdf379842af4b6304809156971e926f374f0Jake Hamby
3240d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        return addTrackerToRawTableAndSendMessage(tracker);
3250d4bcdf379842af4b6304809156971e926f374f0Jake Hamby    }
3260d4bcdf379842af4b6304809156971e926f374f0Jake Hamby
3270d4bcdf379842af4b6304809156971e926f374f0Jake Hamby    /**
3280d4bcdf379842af4b6304809156971e926f374f0Jake Hamby     * Optional check to see if the received WapPush is an OMADM notification with erroneous
3290d4bcdf379842af4b6304809156971e926f374f0Jake Hamby     * extra port fields.
3300d4bcdf379842af4b6304809156971e926f374f0Jake Hamby     * - Some carriers make this mistake.
3310d4bcdf379842af4b6304809156971e926f374f0Jake Hamby     * ex: MSGTYPE-TotalSegments-CurrentSegment
3320d4bcdf379842af4b6304809156971e926f374f0Jake Hamby     *       -SourcePortDestPort-SourcePortDestPort-OMADM PDU
3330d4bcdf379842af4b6304809156971e926f374f0Jake Hamby     * @param origPdu The WAP-WDP PDU segment
3340d4bcdf379842af4b6304809156971e926f374f0Jake Hamby     * @param index Current Index while parsing the PDU.
3350d4bcdf379842af4b6304809156971e926f374f0Jake Hamby     * @return True if OrigPdu is OmaDM Push Message which has duplicate ports.
3360d4bcdf379842af4b6304809156971e926f374f0Jake Hamby     *         False if OrigPdu is NOT OmaDM Push Message which has duplicate ports.
3370d4bcdf379842af4b6304809156971e926f374f0Jake Hamby     */
3380d4bcdf379842af4b6304809156971e926f374f0Jake Hamby    private static boolean checkDuplicatePortOmadmWapPush(byte[] origPdu, int index) {
3390d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        index += 4;
3400d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        byte[] omaPdu = new byte[origPdu.length - index];
3410d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        System.arraycopy(origPdu, index, omaPdu, 0, omaPdu.length);
3420d4bcdf379842af4b6304809156971e926f374f0Jake Hamby
3430d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        WspTypeDecoder pduDecoder = new WspTypeDecoder(omaPdu);
3440d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        int wspIndex = 2;
3450d4bcdf379842af4b6304809156971e926f374f0Jake Hamby
3460d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        // Process header length field
3470d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        if (!pduDecoder.decodeUintvarInteger(wspIndex)) {
3480d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            return false;
3490d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        }
3500d4bcdf379842af4b6304809156971e926f374f0Jake Hamby
3510d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        wspIndex += pduDecoder.getDecodedDataLength();  // advance to next field
3520d4bcdf379842af4b6304809156971e926f374f0Jake Hamby
3530d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        // Process content type field
3540d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        if (!pduDecoder.decodeContentType(wspIndex)) {
3550d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            return false;
3560d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        }
3570d4bcdf379842af4b6304809156971e926f374f0Jake Hamby
3580d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        String mimeType = pduDecoder.getValueString();
3590d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        return (WspTypeDecoder.CONTENT_TYPE_B_PUSH_SYNCML_NOTI.equals(mimeType));
3600d4bcdf379842af4b6304809156971e926f374f0Jake Hamby    }
3610d4bcdf379842af4b6304809156971e926f374f0Jake Hamby}
362