CdmaSMSDispatcher.java revision d8f9a83cab34de38981dc3ba5ca9df8dda02dbc0
1767a662ecde33c3979bf02b793d392aca0403162Wink Saville/*
2767a662ecde33c3979bf02b793d392aca0403162Wink Saville * Copyright (C) 2008 The Android Open Source Project
3767a662ecde33c3979bf02b793d392aca0403162Wink Saville *
4767a662ecde33c3979bf02b793d392aca0403162Wink Saville * Licensed under the Apache License, Version 2.0 (the "License");
5767a662ecde33c3979bf02b793d392aca0403162Wink Saville * you may not use this file except in compliance with the License.
6767a662ecde33c3979bf02b793d392aca0403162Wink Saville * You may obtain a copy of the License at
7767a662ecde33c3979bf02b793d392aca0403162Wink Saville *
8767a662ecde33c3979bf02b793d392aca0403162Wink Saville *      http://www.apache.org/licenses/LICENSE-2.0
9767a662ecde33c3979bf02b793d392aca0403162Wink Saville *
10767a662ecde33c3979bf02b793d392aca0403162Wink Saville * Unless required by applicable law or agreed to in writing, software
11767a662ecde33c3979bf02b793d392aca0403162Wink Saville * distributed under the License is distributed on an "AS IS" BASIS,
12767a662ecde33c3979bf02b793d392aca0403162Wink Saville * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13767a662ecde33c3979bf02b793d392aca0403162Wink Saville * See the License for the specific language governing permissions and
14767a662ecde33c3979bf02b793d392aca0403162Wink Saville * limitations under the License.
15767a662ecde33c3979bf02b793d392aca0403162Wink Saville */
16767a662ecde33c3979bf02b793d392aca0403162Wink Saville
17767a662ecde33c3979bf02b793d392aca0403162Wink Savillepackage com.android.internal.telephony.cdma;
18767a662ecde33c3979bf02b793d392aca0403162Wink Saville
19767a662ecde33c3979bf02b793d392aca0403162Wink Saville
20867641ece36e2fd17faaea79cf19506ab17177c6jshimport android.app.Activity;
21767a662ecde33c3979bf02b793d392aca0403162Wink Savilleimport android.app.PendingIntent;
22a1c94ae4f75dab030219069864029f5bd9498fb0Richard Mengimport android.app.PendingIntent.CanceledException;
23767a662ecde33c3979bf02b793d392aca0403162Wink Savilleimport android.content.ContentValues;
24d304ae583d862250a21b5949fc3dbdf3af1febacTammo Spalinkimport android.content.Intent;
25ce099c3226b33b43e0dd5d1f24347b14a2223ee1David Krauseimport android.content.SharedPreferences;
26767a662ecde33c3979bf02b793d392aca0403162Wink Savilleimport android.database.Cursor;
27767a662ecde33c3979bf02b793d392aca0403162Wink Savilleimport android.database.SQLException;
28767a662ecde33c3979bf02b793d392aca0403162Wink Savilleimport android.os.AsyncResult;
29767a662ecde33c3979bf02b793d392aca0403162Wink Savilleimport android.os.Message;
30117eace23924f575877ae8ecbb899af22e6f16c0Cheng Yangimport android.os.SystemProperties;
31059fe88115ccb70d9870698e490ed5b4c88da50cJake Hambyimport android.preference.PreferenceManager;
323960ced4638fdb24ddf904fcb6734dae0959671ejshimport android.provider.Telephony;
33867641ece36e2fd17faaea79cf19506ab17177c6jshimport android.provider.Telephony.Sms.Intents;
34a1c94ae4f75dab030219069864029f5bd9498fb0Richard Mengimport android.telephony.SmsManager;
35a01726a7fdd872cd8e1e8a9dfa52fb9cdbf01019jshimport android.telephony.SmsMessage.MessageClass;
36059fe88115ccb70d9870698e490ed5b4c88da50cJake Hambyimport android.util.Config;
37059fe88115ccb70d9870698e490ed5b4c88da50cJake Hambyimport android.util.Log;
38767a662ecde33c3979bf02b793d392aca0403162Wink Saville
39867641ece36e2fd17faaea79cf19506ab17177c6jshimport com.android.internal.telephony.CommandsInterface;
40059fe88115ccb70d9870698e490ed5b4c88da50cJake Hambyimport com.android.internal.telephony.SMSDispatcher;
41767a662ecde33c3979bf02b793d392aca0403162Wink Savilleimport com.android.internal.telephony.SmsHeader;
42767a662ecde33c3979bf02b793d392aca0403162Wink Savilleimport com.android.internal.telephony.SmsMessageBase;
431fa7fae1399f735ea15242484fb5def187e07fdeGilles Duboscqimport com.android.internal.telephony.SmsMessageBase.TextEncodingDetails;
44059fe88115ccb70d9870698e490ed5b4c88da50cJake Hambyimport com.android.internal.telephony.TelephonyProperties;
45d027329cd6105c05c157e3858a170e4f04eb0e3eSoojung Shinimport com.android.internal.telephony.WspTypeDecoder;
46767a662ecde33c3979bf02b793d392aca0403162Wink Savilleimport com.android.internal.telephony.cdma.sms.SmsEnvelope;
47fc78f358cb1d1cee99758bcd6ef998a122ef27c9Tammo Spalinkimport com.android.internal.telephony.cdma.sms.UserData;
48767a662ecde33c3979bf02b793d392aca0403162Wink Savilleimport com.android.internal.util.HexDump;
49767a662ecde33c3979bf02b793d392aca0403162Wink Saville
50767a662ecde33c3979bf02b793d392aca0403162Wink Savilleimport java.io.ByteArrayOutputStream;
51767a662ecde33c3979bf02b793d392aca0403162Wink Savilleimport java.util.ArrayList;
529d34319f1ce5be4124a0b6293162587f4573496fChristian Gustafssonimport java.util.Arrays;
53767a662ecde33c3979bf02b793d392aca0403162Wink Savilleimport java.util.HashMap;
54767a662ecde33c3979bf02b793d392aca0403162Wink Saville
55d027329cd6105c05c157e3858a170e4f04eb0e3eSoojung Shinimport android.content.res.Resources;
56d027329cd6105c05c157e3858a170e4f04eb0e3eSoojung Shin
57767a662ecde33c3979bf02b793d392aca0403162Wink Saville
58767a662ecde33c3979bf02b793d392aca0403162Wink Savillefinal class CdmaSMSDispatcher extends SMSDispatcher {
59767a662ecde33c3979bf02b793d392aca0403162Wink Saville    private static final String TAG = "CDMA";
60767a662ecde33c3979bf02b793d392aca0403162Wink Saville
619d34319f1ce5be4124a0b6293162587f4573496fChristian Gustafsson    private byte[] mLastDispatchedSmsFingerprint;
629d34319f1ce5be4124a0b6293162587f4573496fChristian Gustafsson    private byte[] mLastAcknowledgedSmsFingerprint;
639d34319f1ce5be4124a0b6293162587f4573496fChristian Gustafsson
64d027329cd6105c05c157e3858a170e4f04eb0e3eSoojung Shin    private boolean mCheckForDuplicatePortsInOmadmWapPush = Resources.getSystem().getBoolean(
65d027329cd6105c05c157e3858a170e4f04eb0e3eSoojung Shin            com.android.internal.R.bool.config_duplicate_port_omadm_wappush);
66d027329cd6105c05c157e3858a170e4f04eb0e3eSoojung Shin
67767a662ecde33c3979bf02b793d392aca0403162Wink Saville    CdmaSMSDispatcher(CDMAPhone phone) {
68767a662ecde33c3979bf02b793d392aca0403162Wink Saville        super(phone);
69767a662ecde33c3979bf02b793d392aca0403162Wink Saville    }
70767a662ecde33c3979bf02b793d392aca0403162Wink Saville
71767a662ecde33c3979bf02b793d392aca0403162Wink Saville    /**
72767a662ecde33c3979bf02b793d392aca0403162Wink Saville     * Called when a status report is received.  This should correspond to
73767a662ecde33c3979bf02b793d392aca0403162Wink Saville     * a previously successful SEND.
74767a662ecde33c3979bf02b793d392aca0403162Wink Saville     * Is a special GSM function, should never be called in CDMA!!
75767a662ecde33c3979bf02b793d392aca0403162Wink Saville     *
76767a662ecde33c3979bf02b793d392aca0403162Wink Saville     * @param ar AsyncResult passed into the message handler.  ar.result should
77767a662ecde33c3979bf02b793d392aca0403162Wink Saville     *           be a String representing the status report PDU, as ASCII hex.
78767a662ecde33c3979bf02b793d392aca0403162Wink Saville     */
79767a662ecde33c3979bf02b793d392aca0403162Wink Saville    protected void handleStatusReport(AsyncResult ar) {
80767a662ecde33c3979bf02b793d392aca0403162Wink Saville        Log.d(TAG, "handleStatusReport is a special GSM function, should never be called in CDMA!");
81767a662ecde33c3979bf02b793d392aca0403162Wink Saville    }
82767a662ecde33c3979bf02b793d392aca0403162Wink Saville
83d304ae583d862250a21b5949fc3dbdf3af1febacTammo Spalink    private void handleCdmaStatusReport(SmsMessage sms) {
84d304ae583d862250a21b5949fc3dbdf3af1febacTammo Spalink        for (int i = 0, count = deliveryPendingList.size(); i < count; i++) {
85d304ae583d862250a21b5949fc3dbdf3af1febacTammo Spalink            SmsTracker tracker = deliveryPendingList.get(i);
86d304ae583d862250a21b5949fc3dbdf3af1febacTammo Spalink            if (tracker.mMessageRef == sms.messageRef) {
87d304ae583d862250a21b5949fc3dbdf3af1febacTammo Spalink                // Found it.  Remove from list and broadcast.
88d304ae583d862250a21b5949fc3dbdf3af1febacTammo Spalink                deliveryPendingList.remove(i);
89d304ae583d862250a21b5949fc3dbdf3af1febacTammo Spalink                PendingIntent intent = tracker.mDeliveryIntent;
90d304ae583d862250a21b5949fc3dbdf3af1febacTammo Spalink                Intent fillIn = new Intent();
91d304ae583d862250a21b5949fc3dbdf3af1febacTammo Spalink                fillIn.putExtra("pdu", sms.getPdu());
92d304ae583d862250a21b5949fc3dbdf3af1febacTammo Spalink                try {
93d304ae583d862250a21b5949fc3dbdf3af1febacTammo Spalink                    intent.send(mContext, Activity.RESULT_OK, fillIn);
94d304ae583d862250a21b5949fc3dbdf3af1febacTammo Spalink                } catch (CanceledException ex) {}
95d304ae583d862250a21b5949fc3dbdf3af1febacTammo Spalink                break;  // Only expect to see one tracker matching this message.
96d304ae583d862250a21b5949fc3dbdf3af1febacTammo Spalink            }
97d304ae583d862250a21b5949fc3dbdf3af1febacTammo Spalink        }
98d304ae583d862250a21b5949fc3dbdf3af1febacTammo Spalink    }
99d304ae583d862250a21b5949fc3dbdf3af1febacTammo Spalink
1003960ced4638fdb24ddf904fcb6734dae0959671ejsh    /** {@inheritDoc} */
1013960ced4638fdb24ddf904fcb6734dae0959671ejsh    protected int dispatchMessage(SmsMessageBase smsb) {
102767a662ecde33c3979bf02b793d392aca0403162Wink Saville
103767a662ecde33c3979bf02b793d392aca0403162Wink Saville        // If sms is null, means there was a parsing error.
104767a662ecde33c3979bf02b793d392aca0403162Wink Saville        if (smsb == null) {
1054219797afc2f5369c27cf7be752e9bc3bdb8057djsh            Log.e(TAG, "dispatchMessage: message is null");
1063960ced4638fdb24ddf904fcb6734dae0959671ejsh            return Intents.RESULT_SMS_GENERIC_ERROR;
107767a662ecde33c3979bf02b793d392aca0403162Wink Saville        }
108767a662ecde33c3979bf02b793d392aca0403162Wink Saville
109117eace23924f575877ae8ecbb899af22e6f16c0Cheng Yang        String inEcm=SystemProperties.get(TelephonyProperties.PROPERTY_INECM_MODE, "false");
110117eace23924f575877ae8ecbb899af22e6f16c0Cheng Yang        if (inEcm.equals("true")) {
111ea803b8e0cc613309d0ce096df9c13e9690243ffSatish Roddom            return Activity.RESULT_OK;
112117eace23924f575877ae8ecbb899af22e6f16c0Cheng Yang        }
113117eace23924f575877ae8ecbb899af22e6f16c0Cheng Yang
1149d34319f1ce5be4124a0b6293162587f4573496fChristian Gustafsson        // See if we have a network duplicate SMS.
11564c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink        SmsMessage sms = (SmsMessage) smsb;
1169d34319f1ce5be4124a0b6293162587f4573496fChristian Gustafsson        mLastDispatchedSmsFingerprint = sms.getIncomingSmsFingerprint();
1179d34319f1ce5be4124a0b6293162587f4573496fChristian Gustafsson        if (mLastAcknowledgedSmsFingerprint != null &&
1189d34319f1ce5be4124a0b6293162587f4573496fChristian Gustafsson                Arrays.equals(mLastDispatchedSmsFingerprint, mLastAcknowledgedSmsFingerprint)) {
1199d34319f1ce5be4124a0b6293162587f4573496fChristian Gustafsson            return Intents.RESULT_SMS_HANDLED;
1209d34319f1ce5be4124a0b6293162587f4573496fChristian Gustafsson        }
1219d34319f1ce5be4124a0b6293162587f4573496fChristian Gustafsson        // Decode BD stream and set sms variables.
122767a662ecde33c3979bf02b793d392aca0403162Wink Saville        sms.parseSms();
12364c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink        int teleService = sms.getTeleService();
12464c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink        boolean handled = false;
125767a662ecde33c3979bf02b793d392aca0403162Wink Saville
126a01726a7fdd872cd8e1e8a9dfa52fb9cdbf01019jsh        if ((SmsEnvelope.TELESERVICE_VMN == teleService) ||
127a01726a7fdd872cd8e1e8a9dfa52fb9cdbf01019jsh                (SmsEnvelope.TELESERVICE_MWI == teleService)) {
128a01726a7fdd872cd8e1e8a9dfa52fb9cdbf01019jsh            // handling Voicemail
129a01726a7fdd872cd8e1e8a9dfa52fb9cdbf01019jsh            int voicemailCount = sms.getNumOfVoicemails();
130a01726a7fdd872cd8e1e8a9dfa52fb9cdbf01019jsh            Log.d(TAG, "Voicemail count=" + voicemailCount);
131a01726a7fdd872cd8e1e8a9dfa52fb9cdbf01019jsh            // Store the voicemail count in preferences.
132a01726a7fdd872cd8e1e8a9dfa52fb9cdbf01019jsh            SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(
133059fe88115ccb70d9870698e490ed5b4c88da50cJake Hamby                    mPhone.getContext());
134a01726a7fdd872cd8e1e8a9dfa52fb9cdbf01019jsh            SharedPreferences.Editor editor = sp.edit();
135a01726a7fdd872cd8e1e8a9dfa52fb9cdbf01019jsh            editor.putInt(CDMAPhone.VM_COUNT_CDMA, voicemailCount);
136fa8e271636b9e9b86f247cdb4c91d9ebe9675c27Brad Fitzpatrick            editor.apply();
137a01726a7fdd872cd8e1e8a9dfa52fb9cdbf01019jsh            ((CDMAPhone) mPhone).updateMessageWaitingIndicator(voicemailCount);
138a01726a7fdd872cd8e1e8a9dfa52fb9cdbf01019jsh            handled = true;
139d304ae583d862250a21b5949fc3dbdf3af1febacTammo Spalink        } else if (((SmsEnvelope.TELESERVICE_WMT == teleService) ||
140d304ae583d862250a21b5949fc3dbdf3af1febacTammo Spalink                (SmsEnvelope.TELESERVICE_WEMT == teleService)) &&
141d304ae583d862250a21b5949fc3dbdf3af1febacTammo Spalink                sms.isStatusReportMessage()) {
142d304ae583d862250a21b5949fc3dbdf3af1febacTammo Spalink            handleCdmaStatusReport(sms);
143d304ae583d862250a21b5949fc3dbdf3af1febacTammo Spalink            handled = true;
144a01726a7fdd872cd8e1e8a9dfa52fb9cdbf01019jsh        } else if ((sms.getUserData() == null)) {
145767a662ecde33c3979bf02b793d392aca0403162Wink Saville            if (Config.LOGD) {
146767a662ecde33c3979bf02b793d392aca0403162Wink Saville                Log.d(TAG, "Received SMS without user data");
147767a662ecde33c3979bf02b793d392aca0403162Wink Saville            }
14864c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink            handled = true;
149767a662ecde33c3979bf02b793d392aca0403162Wink Saville        }
150767a662ecde33c3979bf02b793d392aca0403162Wink Saville
1513960ced4638fdb24ddf904fcb6734dae0959671ejsh        if (handled) {
1523960ced4638fdb24ddf904fcb6734dae0959671ejsh            return Intents.RESULT_SMS_HANDLED;
1533960ced4638fdb24ddf904fcb6734dae0959671ejsh        }
154767a662ecde33c3979bf02b793d392aca0403162Wink Saville
155a01726a7fdd872cd8e1e8a9dfa52fb9cdbf01019jsh        if (!mStorageAvailable && (sms.getMessageClass() != MessageClass.CLASS_0)) {
156a01726a7fdd872cd8e1e8a9dfa52fb9cdbf01019jsh            // It's a storable message and there's no storage available.  Bail.
157a01726a7fdd872cd8e1e8a9dfa52fb9cdbf01019jsh            // (See C.S0015-B v2.0 for a description of "Immediate Display"
158a01726a7fdd872cd8e1e8a9dfa52fb9cdbf01019jsh            // messages, which we represent as CLASS_0.)
159a01726a7fdd872cd8e1e8a9dfa52fb9cdbf01019jsh            return Intents.RESULT_SMS_OUT_OF_MEMORY;
160a01726a7fdd872cd8e1e8a9dfa52fb9cdbf01019jsh        }
161a01726a7fdd872cd8e1e8a9dfa52fb9cdbf01019jsh
162c84401fb8b3ed90039bd132b343852303ef88ce6yong liu        if (SmsEnvelope.TELESERVICE_WAP == teleService) {
1633960ced4638fdb24ddf904fcb6734dae0959671ejsh            return processCdmaWapPdu(sms.getUserData(), sms.messageRef,
1643960ced4638fdb24ddf904fcb6734dae0959671ejsh                    sms.getOriginatingAddress());
165767a662ecde33c3979bf02b793d392aca0403162Wink Saville        }
166767a662ecde33c3979bf02b793d392aca0403162Wink Saville
1677e207afd497f8822ca34babe1d9cd1f6d5402fadTammo Spalink        // Reject (NAK) any messages with teleservice ids that have
1687e207afd497f8822ca34babe1d9cd1f6d5402fadTammo Spalink        // not yet been handled and also do not correspond to the two
1697e207afd497f8822ca34babe1d9cd1f6d5402fadTammo Spalink        // kinds that are processed below.
1707e207afd497f8822ca34babe1d9cd1f6d5402fadTammo Spalink        if ((SmsEnvelope.TELESERVICE_WMT != teleService) &&
17183fd7b0d53f2fecb5b92cb911910e07659e246caJohn Joseph                (SmsEnvelope.TELESERVICE_WEMT != teleService) &&
17283fd7b0d53f2fecb5b92cb911910e07659e246caJohn Joseph                (SmsEnvelope.MESSAGE_TYPE_BROADCAST != sms.getMessageType())) {
1737e207afd497f8822ca34babe1d9cd1f6d5402fadTammo Spalink            return Intents.RESULT_SMS_UNSUPPORTED;
1747e207afd497f8822ca34babe1d9cd1f6d5402fadTammo Spalink        }
1757e207afd497f8822ca34babe1d9cd1f6d5402fadTammo Spalink
1767e207afd497f8822ca34babe1d9cd1f6d5402fadTammo Spalink        /*
17764c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink         * TODO(cleanup): Why are we using a getter method for this
17864c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink         * (and for so many other sms fields)?  Trivial getters and
17964c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink         * setters like this are direct violations of the style guide.
180059fe88115ccb70d9870698e490ed5b4c88da50cJake Hamby         * If the purpose is to protect against writes (by not
18164c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink         * providing a setter) then any protection is illusory (and
18264c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink         * hence bad) for cases where the values are not primitives,
18364c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink         * such as this call for the header.  Since this is an issue
18464c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink         * with the public API it cannot be changed easily, but maybe
18564c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink         * something can be done eventually.
18664c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink         */
18764c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink        SmsHeader smsHeader = sms.getUserDataHeader();
18864c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink
1897e207afd497f8822ca34babe1d9cd1f6d5402fadTammo Spalink        /*
19064c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink         * TODO(cleanup): Since both CDMA and GSM use the same header
19164c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink         * format, this dispatch processing is naturally identical,
19264c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink         * and code should probably not be replicated explicitly.
19364c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink         */
1947e207afd497f8822ca34babe1d9cd1f6d5402fadTammo Spalink
19564c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink        // See if message is partial or port addressed.
19664c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink        if ((smsHeader == null) || (smsHeader.concatRef == null)) {
19764c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink            // Message is not partial (not part of concatenated sequence).
198767a662ecde33c3979bf02b793d392aca0403162Wink Saville            byte[][] pdus = new byte[1][];
199767a662ecde33c3979bf02b793d392aca0403162Wink Saville            pdus[0] = sms.getPdu();
200767a662ecde33c3979bf02b793d392aca0403162Wink Saville
20131fd22923aaefc85652a5b5939c6d4aa6fa289e2jsh            if (smsHeader != null && smsHeader.portAddrs != null) {
20264c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink                if (smsHeader.portAddrs.destPort == SmsHeader.PORT_WAP_PUSH) {
20364c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink                    // GSM-style WAP indication
2043960ced4638fdb24ddf904fcb6734dae0959671ejsh                    return mWapPush.dispatchWapPdu(sms.getUserData());
2053960ced4638fdb24ddf904fcb6734dae0959671ejsh                } else {
2063960ced4638fdb24ddf904fcb6734dae0959671ejsh                    // The message was sent to a port, so concoct a URI for it.
2073960ced4638fdb24ddf904fcb6734dae0959671ejsh                    dispatchPortAddressedPdus(pdus, smsHeader.portAddrs.destPort);
208767a662ecde33c3979bf02b793d392aca0403162Wink Saville                }
209767a662ecde33c3979bf02b793d392aca0403162Wink Saville            } else {
21064c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink                // Normal short and non-port-addressed message, dispatch it.
211767a662ecde33c3979bf02b793d392aca0403162Wink Saville                dispatchPdus(pdus);
212767a662ecde33c3979bf02b793d392aca0403162Wink Saville            }
2133960ced4638fdb24ddf904fcb6734dae0959671ejsh            return Activity.RESULT_OK;
214767a662ecde33c3979bf02b793d392aca0403162Wink Saville        } else {
21564c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink            // Process the message part.
2163960ced4638fdb24ddf904fcb6734dae0959671ejsh            return processMessagePart(sms, smsHeader.concatRef, smsHeader.portAddrs);
217767a662ecde33c3979bf02b793d392aca0403162Wink Saville        }
218767a662ecde33c3979bf02b793d392aca0403162Wink Saville    }
219767a662ecde33c3979bf02b793d392aca0403162Wink Saville
220767a662ecde33c3979bf02b793d392aca0403162Wink Saville    /**
221767a662ecde33c3979bf02b793d392aca0403162Wink Saville     * Processes inbound messages that are in the WAP-WDP PDU format. See
222767a662ecde33c3979bf02b793d392aca0403162Wink Saville     * wap-259-wdp-20010614-a section 6.5 for details on the WAP-WDP PDU format.
223767a662ecde33c3979bf02b793d392aca0403162Wink Saville     * WDP segments are gathered until a datagram completes and gets dispatched.
224767a662ecde33c3979bf02b793d392aca0403162Wink Saville     *
225767a662ecde33c3979bf02b793d392aca0403162Wink Saville     * @param pdu The WAP-WDP PDU segment
2263960ced4638fdb24ddf904fcb6734dae0959671ejsh     * @return a result code from {@link Telephony.Sms.Intents}, or
2273960ced4638fdb24ddf904fcb6734dae0959671ejsh     *         {@link Activity#RESULT_OK} if the message has been broadcast
2283960ced4638fdb24ddf904fcb6734dae0959671ejsh     *         to applications
229767a662ecde33c3979bf02b793d392aca0403162Wink Saville     */
2303960ced4638fdb24ddf904fcb6734dae0959671ejsh    protected int processCdmaWapPdu(byte[] pdu, int referenceNumber, String address) {
231767a662ecde33c3979bf02b793d392aca0403162Wink Saville        int segment;
232767a662ecde33c3979bf02b793d392aca0403162Wink Saville        int totalSegments;
233767a662ecde33c3979bf02b793d392aca0403162Wink Saville        int index = 0;
234767a662ecde33c3979bf02b793d392aca0403162Wink Saville        int msgType;
235767a662ecde33c3979bf02b793d392aca0403162Wink Saville
2365c7d9e8194900a2b1699cd57f95b22ca5f7b9be2David Krause        int sourcePort = 0;
2375c7d9e8194900a2b1699cd57f95b22ca5f7b9be2David Krause        int destinationPort = 0;
238767a662ecde33c3979bf02b793d392aca0403162Wink Saville
239767a662ecde33c3979bf02b793d392aca0403162Wink Saville        msgType = pdu[index++];
240767a662ecde33c3979bf02b793d392aca0403162Wink Saville        if (msgType != 0){
241767a662ecde33c3979bf02b793d392aca0403162Wink Saville            Log.w(TAG, "Received a WAP SMS which is not WDP. Discard.");
2423960ced4638fdb24ddf904fcb6734dae0959671ejsh            return Intents.RESULT_SMS_HANDLED;
243767a662ecde33c3979bf02b793d392aca0403162Wink Saville        }
244767a662ecde33c3979bf02b793d392aca0403162Wink Saville        totalSegments = pdu[index++]; // >=1
245767a662ecde33c3979bf02b793d392aca0403162Wink Saville        segment = pdu[index++]; // >=0
246767a662ecde33c3979bf02b793d392aca0403162Wink Saville
2475c7d9e8194900a2b1699cd57f95b22ca5f7b9be2David Krause        // Only the first segment contains sourcePort and destination Port
2485c7d9e8194900a2b1699cd57f95b22ca5f7b9be2David Krause        if (segment == 0) {
2495c7d9e8194900a2b1699cd57f95b22ca5f7b9be2David Krause            //process WDP segment
2505c7d9e8194900a2b1699cd57f95b22ca5f7b9be2David Krause            sourcePort = (0xFF & pdu[index++]) << 8;
2515c7d9e8194900a2b1699cd57f95b22ca5f7b9be2David Krause            sourcePort |= 0xFF & pdu[index++];
2525c7d9e8194900a2b1699cd57f95b22ca5f7b9be2David Krause            destinationPort = (0xFF & pdu[index++]) << 8;
2535c7d9e8194900a2b1699cd57f95b22ca5f7b9be2David Krause            destinationPort |= 0xFF & pdu[index++];
254d027329cd6105c05c157e3858a170e4f04eb0e3eSoojung Shin            // Some carriers incorrectly send duplicate port fields in omadm wap pushes.
255d027329cd6105c05c157e3858a170e4f04eb0e3eSoojung Shin            // If configured, check for that here
256d027329cd6105c05c157e3858a170e4f04eb0e3eSoojung Shin            if (mCheckForDuplicatePortsInOmadmWapPush) {
257d027329cd6105c05c157e3858a170e4f04eb0e3eSoojung Shin                if (checkDuplicatePortOmadmWappush(pdu,index)) {
258d027329cd6105c05c157e3858a170e4f04eb0e3eSoojung Shin                    index = index + 4; // skip duplicate port fields
259d027329cd6105c05c157e3858a170e4f04eb0e3eSoojung Shin                }
260d027329cd6105c05c157e3858a170e4f04eb0e3eSoojung Shin            }
2615c7d9e8194900a2b1699cd57f95b22ca5f7b9be2David Krause        }
262767a662ecde33c3979bf02b793d392aca0403162Wink Saville
263767a662ecde33c3979bf02b793d392aca0403162Wink Saville        // Lookup all other related parts
264767a662ecde33c3979bf02b793d392aca0403162Wink Saville        StringBuilder where = new StringBuilder("reference_number =");
265767a662ecde33c3979bf02b793d392aca0403162Wink Saville        where.append(referenceNumber);
266767a662ecde33c3979bf02b793d392aca0403162Wink Saville        where.append(" AND address = ?");
267767a662ecde33c3979bf02b793d392aca0403162Wink Saville        String[] whereArgs = new String[] {address};
268767a662ecde33c3979bf02b793d392aca0403162Wink Saville
269767a662ecde33c3979bf02b793d392aca0403162Wink Saville        Log.i(TAG, "Received WAP PDU. Type = " + msgType + ", originator = " + address
270767a662ecde33c3979bf02b793d392aca0403162Wink Saville                + ", src-port = " + sourcePort + ", dst-port = " + destinationPort
271767a662ecde33c3979bf02b793d392aca0403162Wink Saville                + ", ID = " + referenceNumber + ", segment# = " + segment + "/" + totalSegments);
272767a662ecde33c3979bf02b793d392aca0403162Wink Saville
273767a662ecde33c3979bf02b793d392aca0403162Wink Saville        byte[][] pdus = null;
274767a662ecde33c3979bf02b793d392aca0403162Wink Saville        Cursor cursor = null;
275767a662ecde33c3979bf02b793d392aca0403162Wink Saville        try {
276767a662ecde33c3979bf02b793d392aca0403162Wink Saville            cursor = mResolver.query(mRawUri, RAW_PROJECTION, where.toString(), whereArgs, null);
277767a662ecde33c3979bf02b793d392aca0403162Wink Saville            int cursorCount = cursor.getCount();
278767a662ecde33c3979bf02b793d392aca0403162Wink Saville            if (cursorCount != totalSegments - 1) {
279767a662ecde33c3979bf02b793d392aca0403162Wink Saville                // We don't have all the parts yet, store this one away
280767a662ecde33c3979bf02b793d392aca0403162Wink Saville                ContentValues values = new ContentValues();
281ab79ee4adcbc6eb9fb9c509766753f65d3857739Jake Hamby                values.put("date", (long) 0);
282767a662ecde33c3979bf02b793d392aca0403162Wink Saville                values.put("pdu", HexDump.toHexString(pdu, index, pdu.length - index));
283767a662ecde33c3979bf02b793d392aca0403162Wink Saville                values.put("address", address);
284767a662ecde33c3979bf02b793d392aca0403162Wink Saville                values.put("reference_number", referenceNumber);
285767a662ecde33c3979bf02b793d392aca0403162Wink Saville                values.put("count", totalSegments);
286767a662ecde33c3979bf02b793d392aca0403162Wink Saville                values.put("sequence", segment);
287767a662ecde33c3979bf02b793d392aca0403162Wink Saville                values.put("destination_port", destinationPort);
288767a662ecde33c3979bf02b793d392aca0403162Wink Saville
289767a662ecde33c3979bf02b793d392aca0403162Wink Saville                mResolver.insert(mRawUri, values);
290767a662ecde33c3979bf02b793d392aca0403162Wink Saville
2913960ced4638fdb24ddf904fcb6734dae0959671ejsh                return Intents.RESULT_SMS_HANDLED;
292767a662ecde33c3979bf02b793d392aca0403162Wink Saville            }
293767a662ecde33c3979bf02b793d392aca0403162Wink Saville
294767a662ecde33c3979bf02b793d392aca0403162Wink Saville            // All the parts are in place, deal with them
295767a662ecde33c3979bf02b793d392aca0403162Wink Saville            int pduColumn = cursor.getColumnIndex("pdu");
296767a662ecde33c3979bf02b793d392aca0403162Wink Saville            int sequenceColumn = cursor.getColumnIndex("sequence");
297767a662ecde33c3979bf02b793d392aca0403162Wink Saville
298767a662ecde33c3979bf02b793d392aca0403162Wink Saville            pdus = new byte[totalSegments][];
299767a662ecde33c3979bf02b793d392aca0403162Wink Saville            for (int i = 0; i < cursorCount; i++) {
300767a662ecde33c3979bf02b793d392aca0403162Wink Saville                cursor.moveToNext();
301767a662ecde33c3979bf02b793d392aca0403162Wink Saville                int cursorSequence = (int)cursor.getLong(sequenceColumn);
3025c7d9e8194900a2b1699cd57f95b22ca5f7b9be2David Krause                // Read the destination port from the first segment
3035c7d9e8194900a2b1699cd57f95b22ca5f7b9be2David Krause                if (cursorSequence == 0) {
3045c7d9e8194900a2b1699cd57f95b22ca5f7b9be2David Krause                    int destinationPortColumn = cursor.getColumnIndex("destination_port");
3055c7d9e8194900a2b1699cd57f95b22ca5f7b9be2David Krause                    destinationPort = (int)cursor.getLong(destinationPortColumn);
3065c7d9e8194900a2b1699cd57f95b22ca5f7b9be2David Krause                }
307767a662ecde33c3979bf02b793d392aca0403162Wink Saville                pdus[cursorSequence] = HexDump.hexStringToByteArray(
308767a662ecde33c3979bf02b793d392aca0403162Wink Saville                        cursor.getString(pduColumn));
309767a662ecde33c3979bf02b793d392aca0403162Wink Saville            }
310767a662ecde33c3979bf02b793d392aca0403162Wink Saville            // The last part will be added later
311767a662ecde33c3979bf02b793d392aca0403162Wink Saville
312767a662ecde33c3979bf02b793d392aca0403162Wink Saville            // Remove the parts from the database
313767a662ecde33c3979bf02b793d392aca0403162Wink Saville            mResolver.delete(mRawUri, where.toString(), whereArgs);
314767a662ecde33c3979bf02b793d392aca0403162Wink Saville        } catch (SQLException e) {
315767a662ecde33c3979bf02b793d392aca0403162Wink Saville            Log.e(TAG, "Can't access multipart SMS database", e);
3163960ced4638fdb24ddf904fcb6734dae0959671ejsh            return Intents.RESULT_SMS_GENERIC_ERROR;
317767a662ecde33c3979bf02b793d392aca0403162Wink Saville        } finally {
318767a662ecde33c3979bf02b793d392aca0403162Wink Saville            if (cursor != null) cursor.close();
319767a662ecde33c3979bf02b793d392aca0403162Wink Saville        }
320767a662ecde33c3979bf02b793d392aca0403162Wink Saville
321767a662ecde33c3979bf02b793d392aca0403162Wink Saville        // Build up the data stream
322767a662ecde33c3979bf02b793d392aca0403162Wink Saville        ByteArrayOutputStream output = new ByteArrayOutputStream();
32370f74b79c3e4c88e0e7b747796f76187e4ea8259Christian Gustafsson        for (int i = 0; i < totalSegments; i++) {
324767a662ecde33c3979bf02b793d392aca0403162Wink Saville            // reassemble the (WSP-)pdu
32570f74b79c3e4c88e0e7b747796f76187e4ea8259Christian Gustafsson            if (i == segment) {
32670f74b79c3e4c88e0e7b747796f76187e4ea8259Christian Gustafsson                // This one isn't in the DB, so add it
32770f74b79c3e4c88e0e7b747796f76187e4ea8259Christian Gustafsson                output.write(pdu, index, pdu.length - index);
32870f74b79c3e4c88e0e7b747796f76187e4ea8259Christian Gustafsson            } else {
32970f74b79c3e4c88e0e7b747796f76187e4ea8259Christian Gustafsson                output.write(pdus[i], 0, pdus[i].length);
33070f74b79c3e4c88e0e7b747796f76187e4ea8259Christian Gustafsson            }
331767a662ecde33c3979bf02b793d392aca0403162Wink Saville        }
332767a662ecde33c3979bf02b793d392aca0403162Wink Saville
333767a662ecde33c3979bf02b793d392aca0403162Wink Saville        byte[] datagram = output.toByteArray();
334767a662ecde33c3979bf02b793d392aca0403162Wink Saville        // Dispatch the PDU to applications
335767a662ecde33c3979bf02b793d392aca0403162Wink Saville        switch (destinationPort) {
336767a662ecde33c3979bf02b793d392aca0403162Wink Saville        case SmsHeader.PORT_WAP_PUSH:
337767a662ecde33c3979bf02b793d392aca0403162Wink Saville            // Handle the PUSH
3383960ced4638fdb24ddf904fcb6734dae0959671ejsh            return mWapPush.dispatchWapPdu(datagram);
339767a662ecde33c3979bf02b793d392aca0403162Wink Saville
340767a662ecde33c3979bf02b793d392aca0403162Wink Saville        default:{
341767a662ecde33c3979bf02b793d392aca0403162Wink Saville            pdus = new byte[1][];
342767a662ecde33c3979bf02b793d392aca0403162Wink Saville            pdus[0] = datagram;
343767a662ecde33c3979bf02b793d392aca0403162Wink Saville            // The messages were sent to any other WAP port
344767a662ecde33c3979bf02b793d392aca0403162Wink Saville            dispatchPortAddressedPdus(pdus, destinationPort);
3453960ced4638fdb24ddf904fcb6734dae0959671ejsh            return Activity.RESULT_OK;
346767a662ecde33c3979bf02b793d392aca0403162Wink Saville        }
347767a662ecde33c3979bf02b793d392aca0403162Wink Saville        }
348767a662ecde33c3979bf02b793d392aca0403162Wink Saville    }
349767a662ecde33c3979bf02b793d392aca0403162Wink Saville
350767a662ecde33c3979bf02b793d392aca0403162Wink Saville    /** {@inheritDoc} */
3511f952a178db86559ff4bab79c4a9b5fae18096bfTammo Spalink    protected void sendData(String destAddr, String scAddr, int destPort,
3521f952a178db86559ff4bab79c4a9b5fae18096bfTammo Spalink            byte[] data, PendingIntent sentIntent, PendingIntent deliveryIntent) {
3531f952a178db86559ff4bab79c4a9b5fae18096bfTammo Spalink        SmsMessage.SubmitPdu pdu = SmsMessage.getSubmitPdu(
3541f952a178db86559ff4bab79c4a9b5fae18096bfTammo Spalink                scAddr, destAddr, destPort, data, (deliveryIntent != null));
3551f952a178db86559ff4bab79c4a9b5fae18096bfTammo Spalink        sendSubmitPdu(pdu, sentIntent, deliveryIntent);
3561f952a178db86559ff4bab79c4a9b5fae18096bfTammo Spalink    }
3571f952a178db86559ff4bab79c4a9b5fae18096bfTammo Spalink
3581f952a178db86559ff4bab79c4a9b5fae18096bfTammo Spalink    /** {@inheritDoc} */
3591f952a178db86559ff4bab79c4a9b5fae18096bfTammo Spalink    protected void sendText(String destAddr, String scAddr, String text,
3601f952a178db86559ff4bab79c4a9b5fae18096bfTammo Spalink            PendingIntent sentIntent, PendingIntent deliveryIntent) {
3611f952a178db86559ff4bab79c4a9b5fae18096bfTammo Spalink        SmsMessage.SubmitPdu pdu = SmsMessage.getSubmitPdu(
3621f952a178db86559ff4bab79c4a9b5fae18096bfTammo Spalink                scAddr, destAddr, text, (deliveryIntent != null), null);
3631f952a178db86559ff4bab79c4a9b5fae18096bfTammo Spalink        sendSubmitPdu(pdu, sentIntent, deliveryIntent);
3641f952a178db86559ff4bab79c4a9b5fae18096bfTammo Spalink    }
3651f952a178db86559ff4bab79c4a9b5fae18096bfTammo Spalink
3661f952a178db86559ff4bab79c4a9b5fae18096bfTammo Spalink    /** {@inheritDoc} */
36764c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink    protected void sendMultipartText(String destAddr, String scAddr,
368767a662ecde33c3979bf02b793d392aca0403162Wink Saville            ArrayList<String> parts, ArrayList<PendingIntent> sentIntents,
369767a662ecde33c3979bf02b793d392aca0403162Wink Saville            ArrayList<PendingIntent> deliveryIntents) {
370767a662ecde33c3979bf02b793d392aca0403162Wink Saville
37164c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink        /**
37264c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink         * TODO(cleanup): There is no real code difference between
37364c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink         * this and the GSM version, and hence it should be moved to
37464c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink         * the base class or consolidated somehow, provided calling
37564c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink         * the proper submitpdu stuff can be arranged.
37664c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink         */
377767a662ecde33c3979bf02b793d392aca0403162Wink Saville
37864c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink        int refNumber = getNextConcatenatedRef() & 0x00FF;
3791fa7fae1399f735ea15242484fb5def187e07fdeGilles Duboscq        int msgCount = parts.size();
3801fa7fae1399f735ea15242484fb5def187e07fdeGilles Duboscq        int encoding = android.telephony.SmsMessage.ENCODING_UNKNOWN;
3811fa7fae1399f735ea15242484fb5def187e07fdeGilles Duboscq
3821fa7fae1399f735ea15242484fb5def187e07fdeGilles Duboscq        for (int i = 0; i < msgCount; i++) {
3831fa7fae1399f735ea15242484fb5def187e07fdeGilles Duboscq            TextEncodingDetails details = SmsMessage.calculateLength(parts.get(i), false);
3841fa7fae1399f735ea15242484fb5def187e07fdeGilles Duboscq            if (encoding != details.codeUnitSize
3851fa7fae1399f735ea15242484fb5def187e07fdeGilles Duboscq                    && (encoding == android.telephony.SmsMessage.ENCODING_UNKNOWN
3861fa7fae1399f735ea15242484fb5def187e07fdeGilles Duboscq                            || encoding == android.telephony.SmsMessage.ENCODING_7BIT)) {
3871fa7fae1399f735ea15242484fb5def187e07fdeGilles Duboscq                encoding = details.codeUnitSize;
3881fa7fae1399f735ea15242484fb5def187e07fdeGilles Duboscq            }
3891fa7fae1399f735ea15242484fb5def187e07fdeGilles Duboscq        }
390767a662ecde33c3979bf02b793d392aca0403162Wink Saville
3911fa7fae1399f735ea15242484fb5def187e07fdeGilles Duboscq        for (int i = 0; i < msgCount; i++) {
39264c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink            SmsHeader.ConcatRef concatRef = new SmsHeader.ConcatRef();
39364c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink            concatRef.refNumber = refNumber;
39464c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink            concatRef.seqNumber = i + 1;  // 1-based sequence
39564c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink            concatRef.msgCount = msgCount;
39664c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink            concatRef.isEightBits = true;
39764c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink            SmsHeader smsHeader = new SmsHeader();
39864c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink            smsHeader.concatRef = concatRef;
399767a662ecde33c3979bf02b793d392aca0403162Wink Saville
40064c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink            PendingIntent sentIntent = null;
401767a662ecde33c3979bf02b793d392aca0403162Wink Saville            if (sentIntents != null && sentIntents.size() > i) {
402767a662ecde33c3979bf02b793d392aca0403162Wink Saville                sentIntent = sentIntents.get(i);
403767a662ecde33c3979bf02b793d392aca0403162Wink Saville            }
40464c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink
40564c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink            PendingIntent deliveryIntent = null;
406767a662ecde33c3979bf02b793d392aca0403162Wink Saville            if (deliveryIntents != null && deliveryIntents.size() > i) {
407767a662ecde33c3979bf02b793d392aca0403162Wink Saville                deliveryIntent = deliveryIntents.get(i);
408767a662ecde33c3979bf02b793d392aca0403162Wink Saville            }
409767a662ecde33c3979bf02b793d392aca0403162Wink Saville
410fc78f358cb1d1cee99758bcd6ef998a122ef27c9Tammo Spalink            UserData uData = new UserData();
411fc78f358cb1d1cee99758bcd6ef998a122ef27c9Tammo Spalink            uData.payloadStr = parts.get(i);
412fc78f358cb1d1cee99758bcd6ef998a122ef27c9Tammo Spalink            uData.userDataHeader = smsHeader;
4131fa7fae1399f735ea15242484fb5def187e07fdeGilles Duboscq            if (encoding == android.telephony.SmsMessage.ENCODING_7BIT) {
4141fa7fae1399f735ea15242484fb5def187e07fdeGilles Duboscq                uData.msgEncoding = UserData.ENCODING_GSM_7BIT_ALPHABET;
4151fa7fae1399f735ea15242484fb5def187e07fdeGilles Duboscq            } else { // assume UTF-16
4161fa7fae1399f735ea15242484fb5def187e07fdeGilles Duboscq                uData.msgEncoding = UserData.ENCODING_UNICODE_16;
4171fa7fae1399f735ea15242484fb5def187e07fdeGilles Duboscq            }
4181fa7fae1399f735ea15242484fb5def187e07fdeGilles Duboscq            uData.msgEncodingSet = true;
419fc78f358cb1d1cee99758bcd6ef998a122ef27c9Tammo Spalink
420d304ae583d862250a21b5949fc3dbdf3af1febacTammo Spalink            /* By setting the statusReportRequested bit only for the
421d304ae583d862250a21b5949fc3dbdf3af1febacTammo Spalink             * last message fragment, this will result in only one
422d304ae583d862250a21b5949fc3dbdf3af1febacTammo Spalink             * callback to the sender when that last fragment delivery
423d304ae583d862250a21b5949fc3dbdf3af1febacTammo Spalink             * has been acknowledged. */
424fc78f358cb1d1cee99758bcd6ef998a122ef27c9Tammo Spalink            SmsMessage.SubmitPdu submitPdu = SmsMessage.getSubmitPdu(destAddr,
425d304ae583d862250a21b5949fc3dbdf3af1febacTammo Spalink                    uData, (deliveryIntent != null) && (i == (msgCount - 1)));
426767a662ecde33c3979bf02b793d392aca0403162Wink Saville
42764c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink            sendSubmitPdu(submitPdu, sentIntent, deliveryIntent);
428767a662ecde33c3979bf02b793d392aca0403162Wink Saville        }
429767a662ecde33c3979bf02b793d392aca0403162Wink Saville    }
430767a662ecde33c3979bf02b793d392aca0403162Wink Saville
4311f952a178db86559ff4bab79c4a9b5fae18096bfTammo Spalink    protected void sendSubmitPdu(SmsMessage.SubmitPdu pdu,
4321f952a178db86559ff4bab79c4a9b5fae18096bfTammo Spalink            PendingIntent sentIntent, PendingIntent deliveryIntent) {
4331f952a178db86559ff4bab79c4a9b5fae18096bfTammo Spalink        if (SystemProperties.getBoolean(TelephonyProperties.PROPERTY_INECM_MODE, false)) {
434a1c94ae4f75dab030219069864029f5bd9498fb0Richard Meng            if (sentIntent != null) {
435a1c94ae4f75dab030219069864029f5bd9498fb0Richard Meng                try {
436a1c94ae4f75dab030219069864029f5bd9498fb0Richard Meng                    sentIntent.send(SmsManager.RESULT_ERROR_NO_SERVICE);
437a1c94ae4f75dab030219069864029f5bd9498fb0Richard Meng                } catch (CanceledException ex) {}
438a1c94ae4f75dab030219069864029f5bd9498fb0Richard Meng            }
439a1c94ae4f75dab030219069864029f5bd9498fb0Richard Meng            if (Config.LOGD) {
440a1c94ae4f75dab030219069864029f5bd9498fb0Richard Meng                Log.d(TAG, "Block SMS in Emergency Callback mode");
441a1c94ae4f75dab030219069864029f5bd9498fb0Richard Meng            }
442a1c94ae4f75dab030219069864029f5bd9498fb0Richard Meng            return;
443a1c94ae4f75dab030219069864029f5bd9498fb0Richard Meng        }
4441f952a178db86559ff4bab79c4a9b5fae18096bfTammo Spalink        sendRawPdu(pdu.encodedScAddress, pdu.encodedMessage, sentIntent, deliveryIntent);
445a1c94ae4f75dab030219069864029f5bd9498fb0Richard Meng    }
446a1c94ae4f75dab030219069864029f5bd9498fb0Richard Meng
447767a662ecde33c3979bf02b793d392aca0403162Wink Saville    /** {@inheritDoc} */
448767a662ecde33c3979bf02b793d392aca0403162Wink Saville    protected void sendSms(SmsTracker tracker) {
449767a662ecde33c3979bf02b793d392aca0403162Wink Saville        HashMap map = tracker.mData;
450767a662ecde33c3979bf02b793d392aca0403162Wink Saville
451059fe88115ccb70d9870698e490ed5b4c88da50cJake Hamby        // byte smsc[] = (byte[]) map.get("smsc");  // unused for CDMA
452767a662ecde33c3979bf02b793d392aca0403162Wink Saville        byte pdu[] = (byte[]) map.get("pdu");
453767a662ecde33c3979bf02b793d392aca0403162Wink Saville
454767a662ecde33c3979bf02b793d392aca0403162Wink Saville        Message reply = obtainMessage(EVENT_SEND_SMS_COMPLETE, tracker);
455767a662ecde33c3979bf02b793d392aca0403162Wink Saville
456767a662ecde33c3979bf02b793d392aca0403162Wink Saville        mCm.sendCdmaSms(pdu, reply);
457767a662ecde33c3979bf02b793d392aca0403162Wink Saville    }
458767a662ecde33c3979bf02b793d392aca0403162Wink Saville
459767a662ecde33c3979bf02b793d392aca0403162Wink Saville     /** {@inheritDoc} */
460767a662ecde33c3979bf02b793d392aca0403162Wink Saville    protected void sendMultipartSms (SmsTracker tracker) {
461767a662ecde33c3979bf02b793d392aca0403162Wink Saville        Log.d(TAG, "TODO: CdmaSMSDispatcher.sendMultipartSms not implemented");
462767a662ecde33c3979bf02b793d392aca0403162Wink Saville    }
463767a662ecde33c3979bf02b793d392aca0403162Wink Saville
464767a662ecde33c3979bf02b793d392aca0403162Wink Saville    /** {@inheritDoc} */
465867641ece36e2fd17faaea79cf19506ab17177c6jsh    protected void acknowledgeLastIncomingSms(boolean success, int result, Message response){
466767a662ecde33c3979bf02b793d392aca0403162Wink Saville        // FIXME unit test leaves cm == null. this should change
467117eace23924f575877ae8ecbb899af22e6f16c0Cheng Yang
468117eace23924f575877ae8ecbb899af22e6f16c0Cheng Yang        String inEcm=SystemProperties.get(TelephonyProperties.PROPERTY_INECM_MODE, "false");
469117eace23924f575877ae8ecbb899af22e6f16c0Cheng Yang        if (inEcm.equals("true")) {
470117eace23924f575877ae8ecbb899af22e6f16c0Cheng Yang            return;
471117eace23924f575877ae8ecbb899af22e6f16c0Cheng Yang        }
472117eace23924f575877ae8ecbb899af22e6f16c0Cheng Yang
473767a662ecde33c3979bf02b793d392aca0403162Wink Saville        if (mCm != null) {
4749d34319f1ce5be4124a0b6293162587f4573496fChristian Gustafsson            int causeCode = resultToCause(result);
4759d34319f1ce5be4124a0b6293162587f4573496fChristian Gustafsson            mCm.acknowledgeLastIncomingCdmaSms(success, causeCode, response);
4769d34319f1ce5be4124a0b6293162587f4573496fChristian Gustafsson
4779d34319f1ce5be4124a0b6293162587f4573496fChristian Gustafsson            if (causeCode == 0) {
4789d34319f1ce5be4124a0b6293162587f4573496fChristian Gustafsson                mLastAcknowledgedSmsFingerprint = mLastDispatchedSmsFingerprint;
4799d34319f1ce5be4124a0b6293162587f4573496fChristian Gustafsson            }
4809d34319f1ce5be4124a0b6293162587f4573496fChristian Gustafsson            mLastDispatchedSmsFingerprint = null;
481767a662ecde33c3979bf02b793d392aca0403162Wink Saville        }
482767a662ecde33c3979bf02b793d392aca0403162Wink Saville    }
483767a662ecde33c3979bf02b793d392aca0403162Wink Saville
484ab79ee4adcbc6eb9fb9c509766753f65d3857739Jake Hamby    protected void handleBroadcastSms(AsyncResult ar) {
485ab79ee4adcbc6eb9fb9c509766753f65d3857739Jake Hamby        // Not supported
486ab79ee4adcbc6eb9fb9c509766753f65d3857739Jake Hamby        Log.e(TAG, "Error! Not implemented for CDMA.");
487767a662ecde33c3979bf02b793d392aca0403162Wink Saville    }
488767a662ecde33c3979bf02b793d392aca0403162Wink Saville
489867641ece36e2fd17faaea79cf19506ab17177c6jsh    private int resultToCause(int rc) {
490867641ece36e2fd17faaea79cf19506ab17177c6jsh        switch (rc) {
4917e207afd497f8822ca34babe1d9cd1f6d5402fadTammo Spalink        case Activity.RESULT_OK:
4927e207afd497f8822ca34babe1d9cd1f6d5402fadTammo Spalink        case Intents.RESULT_SMS_HANDLED:
4937e207afd497f8822ca34babe1d9cd1f6d5402fadTammo Spalink            // Cause code is ignored on success.
4947e207afd497f8822ca34babe1d9cd1f6d5402fadTammo Spalink            return 0;
4957e207afd497f8822ca34babe1d9cd1f6d5402fadTammo Spalink        case Intents.RESULT_SMS_OUT_OF_MEMORY:
4967e207afd497f8822ca34babe1d9cd1f6d5402fadTammo Spalink            return CommandsInterface.CDMA_SMS_FAIL_CAUSE_RESOURCE_SHORTAGE;
4977e207afd497f8822ca34babe1d9cd1f6d5402fadTammo Spalink        case Intents.RESULT_SMS_UNSUPPORTED:
4987e207afd497f8822ca34babe1d9cd1f6d5402fadTammo Spalink            return CommandsInterface.CDMA_SMS_FAIL_CAUSE_INVALID_TELESERVICE_ID;
4997e207afd497f8822ca34babe1d9cd1f6d5402fadTammo Spalink        case Intents.RESULT_SMS_GENERIC_ERROR:
5007e207afd497f8822ca34babe1d9cd1f6d5402fadTammo Spalink        default:
5013ff560d7ba9fcedc4d388f63b756108a715266f4jsh            return CommandsInterface.CDMA_SMS_FAIL_CAUSE_ENCODING_PROBLEM;
502867641ece36e2fd17faaea79cf19506ab17177c6jsh        }
503867641ece36e2fd17faaea79cf19506ab17177c6jsh    }
504d027329cd6105c05c157e3858a170e4f04eb0e3eSoojung Shin
505d027329cd6105c05c157e3858a170e4f04eb0e3eSoojung Shin    /**
506d027329cd6105c05c157e3858a170e4f04eb0e3eSoojung Shin     * Optional check to see if the received WapPush is an OMADM notification with erroneous
507d027329cd6105c05c157e3858a170e4f04eb0e3eSoojung Shin     * extra port fields.
508d027329cd6105c05c157e3858a170e4f04eb0e3eSoojung Shin     * - Some carriers make this mistake.
509d027329cd6105c05c157e3858a170e4f04eb0e3eSoojung Shin     * ex: MSGTYPE-TotalSegments-CurrentSegment
510d027329cd6105c05c157e3858a170e4f04eb0e3eSoojung Shin     *       -SourcePortDestPort-SourcePortDestPort-OMADM PDU
511d027329cd6105c05c157e3858a170e4f04eb0e3eSoojung Shin     * @param origPdu The WAP-WDP PDU segment
512d027329cd6105c05c157e3858a170e4f04eb0e3eSoojung Shin     * @param index Current Index while parsing the PDU.
513d027329cd6105c05c157e3858a170e4f04eb0e3eSoojung Shin     * @return True if OrigPdu is OmaDM Push Message which has duplicate ports.
514d027329cd6105c05c157e3858a170e4f04eb0e3eSoojung Shin     *         False if OrigPdu is NOT OmaDM Push Message which has duplicate ports.
515d027329cd6105c05c157e3858a170e4f04eb0e3eSoojung Shin     */
516d027329cd6105c05c157e3858a170e4f04eb0e3eSoojung Shin    private boolean checkDuplicatePortOmadmWappush(byte[] origPdu, int index) {
517d027329cd6105c05c157e3858a170e4f04eb0e3eSoojung Shin        index += 4;
518d027329cd6105c05c157e3858a170e4f04eb0e3eSoojung Shin        byte[] omaPdu = new byte[origPdu.length - index];
519d027329cd6105c05c157e3858a170e4f04eb0e3eSoojung Shin        System.arraycopy(origPdu, index, omaPdu, 0, omaPdu.length);
520d027329cd6105c05c157e3858a170e4f04eb0e3eSoojung Shin
521d027329cd6105c05c157e3858a170e4f04eb0e3eSoojung Shin        WspTypeDecoder pduDecoder = new WspTypeDecoder(omaPdu);
522d027329cd6105c05c157e3858a170e4f04eb0e3eSoojung Shin        int wspIndex = 2;
523d027329cd6105c05c157e3858a170e4f04eb0e3eSoojung Shin
524d027329cd6105c05c157e3858a170e4f04eb0e3eSoojung Shin        // Process header length field
525d027329cd6105c05c157e3858a170e4f04eb0e3eSoojung Shin        if (pduDecoder.decodeUintvarInteger(wspIndex) == false) {
526d027329cd6105c05c157e3858a170e4f04eb0e3eSoojung Shin            return false;
527d027329cd6105c05c157e3858a170e4f04eb0e3eSoojung Shin        }
528d027329cd6105c05c157e3858a170e4f04eb0e3eSoojung Shin
529d027329cd6105c05c157e3858a170e4f04eb0e3eSoojung Shin        wspIndex += pduDecoder.getDecodedDataLength(); // advance to next field
530d027329cd6105c05c157e3858a170e4f04eb0e3eSoojung Shin
531d027329cd6105c05c157e3858a170e4f04eb0e3eSoojung Shin        // Process content type field
532d027329cd6105c05c157e3858a170e4f04eb0e3eSoojung Shin        if (pduDecoder.decodeContentType(wspIndex) == false) {
533d027329cd6105c05c157e3858a170e4f04eb0e3eSoojung Shin            return false;
534d027329cd6105c05c157e3858a170e4f04eb0e3eSoojung Shin        }
535d027329cd6105c05c157e3858a170e4f04eb0e3eSoojung Shin
536d027329cd6105c05c157e3858a170e4f04eb0e3eSoojung Shin        String mimeType = pduDecoder.getValueString();
537d8f9a83cab34de38981dc3ba5ca9df8dda02dbc0Marco Nelissen        if (mimeType != null && mimeType.equals(WspTypeDecoder.CONTENT_TYPE_B_PUSH_SYNCML_NOTI)) {
538d8f9a83cab34de38981dc3ba5ca9df8dda02dbc0Marco Nelissen            return true;
539d027329cd6105c05c157e3858a170e4f04eb0e3eSoojung Shin        }
540d027329cd6105c05c157e3858a170e4f04eb0e3eSoojung Shin        return false;
541d027329cd6105c05c157e3858a170e4f04eb0e3eSoojung Shin    }
542767a662ecde33c3979bf02b793d392aca0403162Wink Saville}
543