CdmaSMSDispatcher.java revision b7945cae5ad0feaad09378d0db77f2b3105e5235
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.Message;
29117eace23924f575877ae8ecbb899af22e6f16c0Cheng Yangimport android.os.SystemProperties;
30059fe88115ccb70d9870698e490ed5b4c88da50cJake Hambyimport android.preference.PreferenceManager;
313960ced4638fdb24ddf904fcb6734dae0959671ejshimport android.provider.Telephony;
32867641ece36e2fd17faaea79cf19506ab17177c6jshimport android.provider.Telephony.Sms.Intents;
33a1c94ae4f75dab030219069864029f5bd9498fb0Richard Mengimport android.telephony.SmsManager;
34a01726a7fdd872cd8e1e8a9dfa52fb9cdbf01019jshimport android.telephony.SmsMessage.MessageClass;
35059fe88115ccb70d9870698e490ed5b4c88da50cJake Hambyimport android.util.Log;
36767a662ecde33c3979bf02b793d392aca0403162Wink Saville
37867641ece36e2fd17faaea79cf19506ab17177c6jshimport com.android.internal.telephony.CommandsInterface;
38059fe88115ccb70d9870698e490ed5b4c88da50cJake Hambyimport com.android.internal.telephony.SMSDispatcher;
39767a662ecde33c3979bf02b793d392aca0403162Wink Savilleimport com.android.internal.telephony.SmsHeader;
40767a662ecde33c3979bf02b793d392aca0403162Wink Savilleimport com.android.internal.telephony.SmsMessageBase;
411fa7fae1399f735ea15242484fb5def187e07fdeGilles Duboscqimport com.android.internal.telephony.SmsMessageBase.TextEncodingDetails;
42b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hambyimport com.android.internal.telephony.SmsStorageMonitor;
43b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hambyimport com.android.internal.telephony.SmsUsageMonitor;
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;
519d34319f1ce5be4124a0b6293162587f4573496fChristian Gustafssonimport java.util.Arrays;
52767a662ecde33c3979bf02b793d392aca0403162Wink Savilleimport java.util.HashMap;
53767a662ecde33c3979bf02b793d392aca0403162Wink Saville
54d027329cd6105c05c157e3858a170e4f04eb0e3eSoojung Shinimport android.content.res.Resources;
55d027329cd6105c05c157e3858a170e4f04eb0e3eSoojung Shin
56767a662ecde33c3979bf02b793d392aca0403162Wink Saville
57767a662ecde33c3979bf02b793d392aca0403162Wink Savillefinal class CdmaSMSDispatcher extends SMSDispatcher {
58767a662ecde33c3979bf02b793d392aca0403162Wink Saville    private static final String TAG = "CDMA";
59767a662ecde33c3979bf02b793d392aca0403162Wink Saville
609d34319f1ce5be4124a0b6293162587f4573496fChristian Gustafsson    private byte[] mLastDispatchedSmsFingerprint;
619d34319f1ce5be4124a0b6293162587f4573496fChristian Gustafsson    private byte[] mLastAcknowledgedSmsFingerprint;
629d34319f1ce5be4124a0b6293162587f4573496fChristian Gustafsson
63b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby    private final boolean mCheckForDuplicatePortsInOmadmWapPush = Resources.getSystem().getBoolean(
64d027329cd6105c05c157e3858a170e4f04eb0e3eSoojung Shin            com.android.internal.R.bool.config_duplicate_port_omadm_wappush);
65d027329cd6105c05c157e3858a170e4f04eb0e3eSoojung Shin
66b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby    CdmaSMSDispatcher(CDMAPhone phone, SmsStorageMonitor storageMonitor,
67b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby            SmsUsageMonitor usageMonitor) {
68b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby        super(phone, storageMonitor, usageMonitor);
69b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby        mCm.setOnNewCdmaSms(this, EVENT_NEW_SMS, null);
70b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby    }
71b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby
72b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby    @Override
73b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby    public void dispose() {
74b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby        mCm.unSetOnNewCdmaSms(this);
75767a662ecde33c3979bf02b793d392aca0403162Wink Saville    }
76767a662ecde33c3979bf02b793d392aca0403162Wink Saville
77145ff609de3206b585819ef974fab20cdc2d9f5eJake Hamby    @Override
78b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby    protected String getFormat() {
79b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby        return android.telephony.SmsMessage.FORMAT_3GPP2;
80767a662ecde33c3979bf02b793d392aca0403162Wink Saville    }
81767a662ecde33c3979bf02b793d392aca0403162Wink Saville
82d304ae583d862250a21b5949fc3dbdf3af1febacTammo Spalink    private void handleCdmaStatusReport(SmsMessage sms) {
83d304ae583d862250a21b5949fc3dbdf3af1febacTammo Spalink        for (int i = 0, count = deliveryPendingList.size(); i < count; i++) {
84d304ae583d862250a21b5949fc3dbdf3af1febacTammo Spalink            SmsTracker tracker = deliveryPendingList.get(i);
85d304ae583d862250a21b5949fc3dbdf3af1febacTammo Spalink            if (tracker.mMessageRef == sms.messageRef) {
86d304ae583d862250a21b5949fc3dbdf3af1febacTammo Spalink                // Found it.  Remove from list and broadcast.
87d304ae583d862250a21b5949fc3dbdf3af1febacTammo Spalink                deliveryPendingList.remove(i);
88d304ae583d862250a21b5949fc3dbdf3af1febacTammo Spalink                PendingIntent intent = tracker.mDeliveryIntent;
89d304ae583d862250a21b5949fc3dbdf3af1febacTammo Spalink                Intent fillIn = new Intent();
90d304ae583d862250a21b5949fc3dbdf3af1febacTammo Spalink                fillIn.putExtra("pdu", sms.getPdu());
91d304ae583d862250a21b5949fc3dbdf3af1febacTammo Spalink                try {
92d304ae583d862250a21b5949fc3dbdf3af1febacTammo Spalink                    intent.send(mContext, Activity.RESULT_OK, fillIn);
93d304ae583d862250a21b5949fc3dbdf3af1febacTammo Spalink                } catch (CanceledException ex) {}
94d304ae583d862250a21b5949fc3dbdf3af1febacTammo Spalink                break;  // Only expect to see one tracker matching this message.
95d304ae583d862250a21b5949fc3dbdf3af1febacTammo Spalink            }
96d304ae583d862250a21b5949fc3dbdf3af1febacTammo Spalink        }
97d304ae583d862250a21b5949fc3dbdf3af1febacTammo Spalink    }
98d304ae583d862250a21b5949fc3dbdf3af1febacTammo Spalink
993960ced4638fdb24ddf904fcb6734dae0959671ejsh    /** {@inheritDoc} */
100145ff609de3206b585819ef974fab20cdc2d9f5eJake Hamby    @Override
1012b8bcfe5b74e1a34d136f4ff46e3c94397f38f82Wink Saville    public 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
114cde0233512f8dbbc62238e90c850c310894e3972Wink Saville        if (mSmsReceiveDisabled) {
115cde0233512f8dbbc62238e90c850c310894e3972Wink Saville            // Device doesn't support receiving SMS,
116c049f9ad5b4f5bc32f368646e624aef7707b7252John Wang            Log.d(TAG, "Received short message on device which doesn't support "
117cde0233512f8dbbc62238e90c850c310894e3972Wink Saville                    + "receiving SMS. Ignored.");
118c049f9ad5b4f5bc32f368646e624aef7707b7252John Wang            return Intents.RESULT_SMS_HANDLED;
119c049f9ad5b4f5bc32f368646e624aef7707b7252John Wang        }
120c049f9ad5b4f5bc32f368646e624aef7707b7252John Wang
1219d34319f1ce5be4124a0b6293162587f4573496fChristian Gustafsson        // See if we have a network duplicate SMS.
12264c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink        SmsMessage sms = (SmsMessage) smsb;
1239d34319f1ce5be4124a0b6293162587f4573496fChristian Gustafsson        mLastDispatchedSmsFingerprint = sms.getIncomingSmsFingerprint();
1249d34319f1ce5be4124a0b6293162587f4573496fChristian Gustafsson        if (mLastAcknowledgedSmsFingerprint != null &&
1259d34319f1ce5be4124a0b6293162587f4573496fChristian Gustafsson                Arrays.equals(mLastDispatchedSmsFingerprint, mLastAcknowledgedSmsFingerprint)) {
1269d34319f1ce5be4124a0b6293162587f4573496fChristian Gustafsson            return Intents.RESULT_SMS_HANDLED;
1279d34319f1ce5be4124a0b6293162587f4573496fChristian Gustafsson        }
1289d34319f1ce5be4124a0b6293162587f4573496fChristian Gustafsson        // Decode BD stream and set sms variables.
129767a662ecde33c3979bf02b793d392aca0403162Wink Saville        sms.parseSms();
13064c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink        int teleService = sms.getTeleService();
13164c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink        boolean handled = false;
132767a662ecde33c3979bf02b793d392aca0403162Wink Saville
133a01726a7fdd872cd8e1e8a9dfa52fb9cdbf01019jsh        if ((SmsEnvelope.TELESERVICE_VMN == teleService) ||
134a01726a7fdd872cd8e1e8a9dfa52fb9cdbf01019jsh                (SmsEnvelope.TELESERVICE_MWI == teleService)) {
135a01726a7fdd872cd8e1e8a9dfa52fb9cdbf01019jsh            // handling Voicemail
136a01726a7fdd872cd8e1e8a9dfa52fb9cdbf01019jsh            int voicemailCount = sms.getNumOfVoicemails();
137a01726a7fdd872cd8e1e8a9dfa52fb9cdbf01019jsh            Log.d(TAG, "Voicemail count=" + voicemailCount);
138a01726a7fdd872cd8e1e8a9dfa52fb9cdbf01019jsh            // Store the voicemail count in preferences.
139a01726a7fdd872cd8e1e8a9dfa52fb9cdbf01019jsh            SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(
140b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby                    mContext);
141a01726a7fdd872cd8e1e8a9dfa52fb9cdbf01019jsh            SharedPreferences.Editor editor = sp.edit();
142a01726a7fdd872cd8e1e8a9dfa52fb9cdbf01019jsh            editor.putInt(CDMAPhone.VM_COUNT_CDMA, voicemailCount);
143fa8e271636b9e9b86f247cdb4c91d9ebe9675c27Brad Fitzpatrick            editor.apply();
144b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby            mPhone.setVoiceMessageWaiting(1, voicemailCount);
145a01726a7fdd872cd8e1e8a9dfa52fb9cdbf01019jsh            handled = true;
146d304ae583d862250a21b5949fc3dbdf3af1febacTammo Spalink        } else if (((SmsEnvelope.TELESERVICE_WMT == teleService) ||
147d304ae583d862250a21b5949fc3dbdf3af1febacTammo Spalink                (SmsEnvelope.TELESERVICE_WEMT == teleService)) &&
148d304ae583d862250a21b5949fc3dbdf3af1febacTammo Spalink                sms.isStatusReportMessage()) {
149d304ae583d862250a21b5949fc3dbdf3af1febacTammo Spalink            handleCdmaStatusReport(sms);
150d304ae583d862250a21b5949fc3dbdf3af1febacTammo Spalink            handled = true;
151a01726a7fdd872cd8e1e8a9dfa52fb9cdbf01019jsh        } else if ((sms.getUserData() == null)) {
15243a17654cf4bfe7f1ec22bd8b7b32daccdf27c09Joe Onorato            if (false) {
153767a662ecde33c3979bf02b793d392aca0403162Wink Saville                Log.d(TAG, "Received SMS without user data");
154767a662ecde33c3979bf02b793d392aca0403162Wink Saville            }
15564c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink            handled = true;
156767a662ecde33c3979bf02b793d392aca0403162Wink Saville        }
157767a662ecde33c3979bf02b793d392aca0403162Wink Saville
1583960ced4638fdb24ddf904fcb6734dae0959671ejsh        if (handled) {
1593960ced4638fdb24ddf904fcb6734dae0959671ejsh            return Intents.RESULT_SMS_HANDLED;
1603960ced4638fdb24ddf904fcb6734dae0959671ejsh        }
161767a662ecde33c3979bf02b793d392aca0403162Wink Saville
162b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby        if (!mStorageMonitor.isStorageAvailable() &&
163b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby                sms.getMessageClass() != MessageClass.CLASS_0) {
164a01726a7fdd872cd8e1e8a9dfa52fb9cdbf01019jsh            // It's a storable message and there's no storage available.  Bail.
165a01726a7fdd872cd8e1e8a9dfa52fb9cdbf01019jsh            // (See C.S0015-B v2.0 for a description of "Immediate Display"
166a01726a7fdd872cd8e1e8a9dfa52fb9cdbf01019jsh            // messages, which we represent as CLASS_0.)
167a01726a7fdd872cd8e1e8a9dfa52fb9cdbf01019jsh            return Intents.RESULT_SMS_OUT_OF_MEMORY;
168a01726a7fdd872cd8e1e8a9dfa52fb9cdbf01019jsh        }
169a01726a7fdd872cd8e1e8a9dfa52fb9cdbf01019jsh
170c84401fb8b3ed90039bd132b343852303ef88ce6yong liu        if (SmsEnvelope.TELESERVICE_WAP == teleService) {
1713960ced4638fdb24ddf904fcb6734dae0959671ejsh            return processCdmaWapPdu(sms.getUserData(), sms.messageRef,
1723960ced4638fdb24ddf904fcb6734dae0959671ejsh                    sms.getOriginatingAddress());
173767a662ecde33c3979bf02b793d392aca0403162Wink Saville        }
174767a662ecde33c3979bf02b793d392aca0403162Wink Saville
1757e207afd497f8822ca34babe1d9cd1f6d5402fadTammo Spalink        // Reject (NAK) any messages with teleservice ids that have
1767e207afd497f8822ca34babe1d9cd1f6d5402fadTammo Spalink        // not yet been handled and also do not correspond to the two
1777e207afd497f8822ca34babe1d9cd1f6d5402fadTammo Spalink        // kinds that are processed below.
1787e207afd497f8822ca34babe1d9cd1f6d5402fadTammo Spalink        if ((SmsEnvelope.TELESERVICE_WMT != teleService) &&
17983fd7b0d53f2fecb5b92cb911910e07659e246caJohn Joseph                (SmsEnvelope.TELESERVICE_WEMT != teleService) &&
18083fd7b0d53f2fecb5b92cb911910e07659e246caJohn Joseph                (SmsEnvelope.MESSAGE_TYPE_BROADCAST != sms.getMessageType())) {
1817e207afd497f8822ca34babe1d9cd1f6d5402fadTammo Spalink            return Intents.RESULT_SMS_UNSUPPORTED;
1827e207afd497f8822ca34babe1d9cd1f6d5402fadTammo Spalink        }
1837e207afd497f8822ca34babe1d9cd1f6d5402fadTammo Spalink
184b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby        return dispatchNormalMessage(smsb);
185767a662ecde33c3979bf02b793d392aca0403162Wink Saville    }
186767a662ecde33c3979bf02b793d392aca0403162Wink Saville
187767a662ecde33c3979bf02b793d392aca0403162Wink Saville    /**
188767a662ecde33c3979bf02b793d392aca0403162Wink Saville     * Processes inbound messages that are in the WAP-WDP PDU format. See
189767a662ecde33c3979bf02b793d392aca0403162Wink Saville     * wap-259-wdp-20010614-a section 6.5 for details on the WAP-WDP PDU format.
190767a662ecde33c3979bf02b793d392aca0403162Wink Saville     * WDP segments are gathered until a datagram completes and gets dispatched.
191767a662ecde33c3979bf02b793d392aca0403162Wink Saville     *
192767a662ecde33c3979bf02b793d392aca0403162Wink Saville     * @param pdu The WAP-WDP PDU segment
1933960ced4638fdb24ddf904fcb6734dae0959671ejsh     * @return a result code from {@link Telephony.Sms.Intents}, or
1943960ced4638fdb24ddf904fcb6734dae0959671ejsh     *         {@link Activity#RESULT_OK} if the message has been broadcast
1953960ced4638fdb24ddf904fcb6734dae0959671ejsh     *         to applications
196767a662ecde33c3979bf02b793d392aca0403162Wink Saville     */
1973960ced4638fdb24ddf904fcb6734dae0959671ejsh    protected int processCdmaWapPdu(byte[] pdu, int referenceNumber, String address) {
198767a662ecde33c3979bf02b793d392aca0403162Wink Saville        int index = 0;
199767a662ecde33c3979bf02b793d392aca0403162Wink Saville
200b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby        int msgType = pdu[index++];
201b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby        if (msgType != 0) {
202767a662ecde33c3979bf02b793d392aca0403162Wink Saville            Log.w(TAG, "Received a WAP SMS which is not WDP. Discard.");
2033960ced4638fdb24ddf904fcb6734dae0959671ejsh            return Intents.RESULT_SMS_HANDLED;
204767a662ecde33c3979bf02b793d392aca0403162Wink Saville        }
205b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby        int totalSegments = pdu[index++];   // >= 1
206b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby        int segment = pdu[index++];         // >= 0
207767a662ecde33c3979bf02b793d392aca0403162Wink Saville
2085c7d9e8194900a2b1699cd57f95b22ca5f7b9be2David Krause        // Only the first segment contains sourcePort and destination Port
209b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby        int sourcePort = 0;
210b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby        int destinationPort = 0;
2115c7d9e8194900a2b1699cd57f95b22ca5f7b9be2David Krause        if (segment == 0) {
2125c7d9e8194900a2b1699cd57f95b22ca5f7b9be2David Krause            //process WDP segment
2135c7d9e8194900a2b1699cd57f95b22ca5f7b9be2David Krause            sourcePort = (0xFF & pdu[index++]) << 8;
2145c7d9e8194900a2b1699cd57f95b22ca5f7b9be2David Krause            sourcePort |= 0xFF & pdu[index++];
2155c7d9e8194900a2b1699cd57f95b22ca5f7b9be2David Krause            destinationPort = (0xFF & pdu[index++]) << 8;
2165c7d9e8194900a2b1699cd57f95b22ca5f7b9be2David Krause            destinationPort |= 0xFF & pdu[index++];
217d027329cd6105c05c157e3858a170e4f04eb0e3eSoojung Shin            // Some carriers incorrectly send duplicate port fields in omadm wap pushes.
218d027329cd6105c05c157e3858a170e4f04eb0e3eSoojung Shin            // If configured, check for that here
219d027329cd6105c05c157e3858a170e4f04eb0e3eSoojung Shin            if (mCheckForDuplicatePortsInOmadmWapPush) {
220d027329cd6105c05c157e3858a170e4f04eb0e3eSoojung Shin                if (checkDuplicatePortOmadmWappush(pdu,index)) {
221d027329cd6105c05c157e3858a170e4f04eb0e3eSoojung Shin                    index = index + 4; // skip duplicate port fields
222d027329cd6105c05c157e3858a170e4f04eb0e3eSoojung Shin                }
223d027329cd6105c05c157e3858a170e4f04eb0e3eSoojung Shin            }
2245c7d9e8194900a2b1699cd57f95b22ca5f7b9be2David Krause        }
225767a662ecde33c3979bf02b793d392aca0403162Wink Saville
226767a662ecde33c3979bf02b793d392aca0403162Wink Saville        // Lookup all other related parts
227767a662ecde33c3979bf02b793d392aca0403162Wink Saville        Log.i(TAG, "Received WAP PDU. Type = " + msgType + ", originator = " + address
228767a662ecde33c3979bf02b793d392aca0403162Wink Saville                + ", src-port = " + sourcePort + ", dst-port = " + destinationPort
229b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby                + ", ID = " + referenceNumber + ", segment# = " + segment + '/' + totalSegments);
230767a662ecde33c3979bf02b793d392aca0403162Wink Saville
231b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby        // pass the user data portion of the PDU to the shared handler in SMSDispatcher
232b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby        byte[] userData = new byte[pdu.length - index];
233b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby        System.arraycopy(pdu, index, userData, 0, pdu.length - index);
234767a662ecde33c3979bf02b793d392aca0403162Wink Saville
235b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby        return processMessagePart(userData, address, referenceNumber, segment, totalSegments,
236b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby                0L, destinationPort, true);
237767a662ecde33c3979bf02b793d392aca0403162Wink Saville    }
238767a662ecde33c3979bf02b793d392aca0403162Wink Saville
239767a662ecde33c3979bf02b793d392aca0403162Wink Saville    /** {@inheritDoc} */
240145ff609de3206b585819ef974fab20cdc2d9f5eJake Hamby    @Override
2411f952a178db86559ff4bab79c4a9b5fae18096bfTammo Spalink    protected void sendData(String destAddr, String scAddr, int destPort,
2421f952a178db86559ff4bab79c4a9b5fae18096bfTammo Spalink            byte[] data, PendingIntent sentIntent, PendingIntent deliveryIntent) {
2431f952a178db86559ff4bab79c4a9b5fae18096bfTammo Spalink        SmsMessage.SubmitPdu pdu = SmsMessage.getSubmitPdu(
2441f952a178db86559ff4bab79c4a9b5fae18096bfTammo Spalink                scAddr, destAddr, destPort, data, (deliveryIntent != null));
2451f952a178db86559ff4bab79c4a9b5fae18096bfTammo Spalink        sendSubmitPdu(pdu, sentIntent, deliveryIntent);
2461f952a178db86559ff4bab79c4a9b5fae18096bfTammo Spalink    }
2471f952a178db86559ff4bab79c4a9b5fae18096bfTammo Spalink
2481f952a178db86559ff4bab79c4a9b5fae18096bfTammo Spalink    /** {@inheritDoc} */
249145ff609de3206b585819ef974fab20cdc2d9f5eJake Hamby    @Override
2501f952a178db86559ff4bab79c4a9b5fae18096bfTammo Spalink    protected void sendText(String destAddr, String scAddr, String text,
2511f952a178db86559ff4bab79c4a9b5fae18096bfTammo Spalink            PendingIntent sentIntent, PendingIntent deliveryIntent) {
2521f952a178db86559ff4bab79c4a9b5fae18096bfTammo Spalink        SmsMessage.SubmitPdu pdu = SmsMessage.getSubmitPdu(
2531f952a178db86559ff4bab79c4a9b5fae18096bfTammo Spalink                scAddr, destAddr, text, (deliveryIntent != null), null);
2541f952a178db86559ff4bab79c4a9b5fae18096bfTammo Spalink        sendSubmitPdu(pdu, sentIntent, deliveryIntent);
2551f952a178db86559ff4bab79c4a9b5fae18096bfTammo Spalink    }
2561f952a178db86559ff4bab79c4a9b5fae18096bfTammo Spalink
2571f952a178db86559ff4bab79c4a9b5fae18096bfTammo Spalink    /** {@inheritDoc} */
258145ff609de3206b585819ef974fab20cdc2d9f5eJake Hamby    @Override
259b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby    protected TextEncodingDetails calculateLength(CharSequence messageBody,
260b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby            boolean use7bitOnly) {
261b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby        return SmsMessage.calculateLength(messageBody, use7bitOnly);
262b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby    }
263767a662ecde33c3979bf02b793d392aca0403162Wink Saville
264b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby    /** {@inheritDoc} */
265b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby    @Override
266b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby    protected void sendNewSubmitPdu(String destinationAddress, String scAddress,
267b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby            String message, SmsHeader smsHeader, int encoding,
268b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby            PendingIntent sentIntent, PendingIntent deliveryIntent, boolean lastPart) {
269b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby        UserData uData = new UserData();
270b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby        uData.payloadStr = message;
271b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby        uData.userDataHeader = smsHeader;
272b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby        if (encoding == android.telephony.SmsMessage.ENCODING_7BIT) {
273b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby            uData.msgEncoding = UserData.ENCODING_GSM_7BIT_ALPHABET;
274b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby        } else { // assume UTF-16
275b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby            uData.msgEncoding = UserData.ENCODING_UNICODE_16;
276b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby        }
277b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby        uData.msgEncodingSet = true;
278fc78f358cb1d1cee99758bcd6ef998a122ef27c9Tammo Spalink
279b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby        /* By setting the statusReportRequested bit only for the
280b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby         * last message fragment, this will result in only one
281b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby         * callback to the sender when that last fragment delivery
282b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby         * has been acknowledged. */
283b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby        SmsMessage.SubmitPdu submitPdu = SmsMessage.getSubmitPdu(destinationAddress,
284b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby                uData, (deliveryIntent != null) && lastPart);
285767a662ecde33c3979bf02b793d392aca0403162Wink Saville
286b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby        sendSubmitPdu(submitPdu, sentIntent, deliveryIntent);
287767a662ecde33c3979bf02b793d392aca0403162Wink Saville    }
288767a662ecde33c3979bf02b793d392aca0403162Wink Saville
2891f952a178db86559ff4bab79c4a9b5fae18096bfTammo Spalink    protected void sendSubmitPdu(SmsMessage.SubmitPdu pdu,
2901f952a178db86559ff4bab79c4a9b5fae18096bfTammo Spalink            PendingIntent sentIntent, PendingIntent deliveryIntent) {
2911f952a178db86559ff4bab79c4a9b5fae18096bfTammo Spalink        if (SystemProperties.getBoolean(TelephonyProperties.PROPERTY_INECM_MODE, false)) {
292a1c94ae4f75dab030219069864029f5bd9498fb0Richard Meng            if (sentIntent != null) {
293a1c94ae4f75dab030219069864029f5bd9498fb0Richard Meng                try {
294a1c94ae4f75dab030219069864029f5bd9498fb0Richard Meng                    sentIntent.send(SmsManager.RESULT_ERROR_NO_SERVICE);
295a1c94ae4f75dab030219069864029f5bd9498fb0Richard Meng                } catch (CanceledException ex) {}
296a1c94ae4f75dab030219069864029f5bd9498fb0Richard Meng            }
29743a17654cf4bfe7f1ec22bd8b7b32daccdf27c09Joe Onorato            if (false) {
298a1c94ae4f75dab030219069864029f5bd9498fb0Richard Meng                Log.d(TAG, "Block SMS in Emergency Callback mode");
299a1c94ae4f75dab030219069864029f5bd9498fb0Richard Meng            }
300a1c94ae4f75dab030219069864029f5bd9498fb0Richard Meng            return;
301a1c94ae4f75dab030219069864029f5bd9498fb0Richard Meng        }
3021f952a178db86559ff4bab79c4a9b5fae18096bfTammo Spalink        sendRawPdu(pdu.encodedScAddress, pdu.encodedMessage, sentIntent, deliveryIntent);
303a1c94ae4f75dab030219069864029f5bd9498fb0Richard Meng    }
304a1c94ae4f75dab030219069864029f5bd9498fb0Richard Meng
305767a662ecde33c3979bf02b793d392aca0403162Wink Saville    /** {@inheritDoc} */
306145ff609de3206b585819ef974fab20cdc2d9f5eJake Hamby    @Override
307767a662ecde33c3979bf02b793d392aca0403162Wink Saville    protected void sendSms(SmsTracker tracker) {
308145ff609de3206b585819ef974fab20cdc2d9f5eJake Hamby        HashMap<String, Object> map = tracker.mData;
309767a662ecde33c3979bf02b793d392aca0403162Wink Saville
310059fe88115ccb70d9870698e490ed5b4c88da50cJake Hamby        // byte smsc[] = (byte[]) map.get("smsc");  // unused for CDMA
311767a662ecde33c3979bf02b793d392aca0403162Wink Saville        byte pdu[] = (byte[]) map.get("pdu");
312767a662ecde33c3979bf02b793d392aca0403162Wink Saville
313767a662ecde33c3979bf02b793d392aca0403162Wink Saville        Message reply = obtainMessage(EVENT_SEND_SMS_COMPLETE, tracker);
314767a662ecde33c3979bf02b793d392aca0403162Wink Saville        mCm.sendCdmaSms(pdu, reply);
315767a662ecde33c3979bf02b793d392aca0403162Wink Saville    }
316767a662ecde33c3979bf02b793d392aca0403162Wink Saville
317767a662ecde33c3979bf02b793d392aca0403162Wink Saville    /** {@inheritDoc} */
318145ff609de3206b585819ef974fab20cdc2d9f5eJake Hamby    @Override
319b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby    protected void acknowledgeLastIncomingSms(boolean success, int result, Message response) {
320117eace23924f575877ae8ecbb899af22e6f16c0Cheng Yang        String inEcm=SystemProperties.get(TelephonyProperties.PROPERTY_INECM_MODE, "false");
321117eace23924f575877ae8ecbb899af22e6f16c0Cheng Yang        if (inEcm.equals("true")) {
322117eace23924f575877ae8ecbb899af22e6f16c0Cheng Yang            return;
323117eace23924f575877ae8ecbb899af22e6f16c0Cheng Yang        }
324117eace23924f575877ae8ecbb899af22e6f16c0Cheng Yang
325b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby        int causeCode = resultToCause(result);
326b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby        mCm.acknowledgeLastIncomingCdmaSms(success, causeCode, response);
3279d34319f1ce5be4124a0b6293162587f4573496fChristian Gustafsson
328b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby        if (causeCode == 0) {
329b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby            mLastAcknowledgedSmsFingerprint = mLastDispatchedSmsFingerprint;
330767a662ecde33c3979bf02b793d392aca0403162Wink Saville        }
331b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby        mLastDispatchedSmsFingerprint = null;
332767a662ecde33c3979bf02b793d392aca0403162Wink Saville    }
333767a662ecde33c3979bf02b793d392aca0403162Wink Saville
334b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby    private static int resultToCause(int rc) {
335867641ece36e2fd17faaea79cf19506ab17177c6jsh        switch (rc) {
3367e207afd497f8822ca34babe1d9cd1f6d5402fadTammo Spalink        case Activity.RESULT_OK:
3377e207afd497f8822ca34babe1d9cd1f6d5402fadTammo Spalink        case Intents.RESULT_SMS_HANDLED:
3387e207afd497f8822ca34babe1d9cd1f6d5402fadTammo Spalink            // Cause code is ignored on success.
3397e207afd497f8822ca34babe1d9cd1f6d5402fadTammo Spalink            return 0;
3407e207afd497f8822ca34babe1d9cd1f6d5402fadTammo Spalink        case Intents.RESULT_SMS_OUT_OF_MEMORY:
3417e207afd497f8822ca34babe1d9cd1f6d5402fadTammo Spalink            return CommandsInterface.CDMA_SMS_FAIL_CAUSE_RESOURCE_SHORTAGE;
3427e207afd497f8822ca34babe1d9cd1f6d5402fadTammo Spalink        case Intents.RESULT_SMS_UNSUPPORTED:
3437e207afd497f8822ca34babe1d9cd1f6d5402fadTammo Spalink            return CommandsInterface.CDMA_SMS_FAIL_CAUSE_INVALID_TELESERVICE_ID;
3447e207afd497f8822ca34babe1d9cd1f6d5402fadTammo Spalink        case Intents.RESULT_SMS_GENERIC_ERROR:
3457e207afd497f8822ca34babe1d9cd1f6d5402fadTammo Spalink        default:
3463ff560d7ba9fcedc4d388f63b756108a715266f4jsh            return CommandsInterface.CDMA_SMS_FAIL_CAUSE_ENCODING_PROBLEM;
347867641ece36e2fd17faaea79cf19506ab17177c6jsh        }
348867641ece36e2fd17faaea79cf19506ab17177c6jsh    }
349d027329cd6105c05c157e3858a170e4f04eb0e3eSoojung Shin
350d027329cd6105c05c157e3858a170e4f04eb0e3eSoojung Shin    /**
351d027329cd6105c05c157e3858a170e4f04eb0e3eSoojung Shin     * Optional check to see if the received WapPush is an OMADM notification with erroneous
352d027329cd6105c05c157e3858a170e4f04eb0e3eSoojung Shin     * extra port fields.
353d027329cd6105c05c157e3858a170e4f04eb0e3eSoojung Shin     * - Some carriers make this mistake.
354d027329cd6105c05c157e3858a170e4f04eb0e3eSoojung Shin     * ex: MSGTYPE-TotalSegments-CurrentSegment
355d027329cd6105c05c157e3858a170e4f04eb0e3eSoojung Shin     *       -SourcePortDestPort-SourcePortDestPort-OMADM PDU
356d027329cd6105c05c157e3858a170e4f04eb0e3eSoojung Shin     * @param origPdu The WAP-WDP PDU segment
357d027329cd6105c05c157e3858a170e4f04eb0e3eSoojung Shin     * @param index Current Index while parsing the PDU.
358d027329cd6105c05c157e3858a170e4f04eb0e3eSoojung Shin     * @return True if OrigPdu is OmaDM Push Message which has duplicate ports.
359d027329cd6105c05c157e3858a170e4f04eb0e3eSoojung Shin     *         False if OrigPdu is NOT OmaDM Push Message which has duplicate ports.
360d027329cd6105c05c157e3858a170e4f04eb0e3eSoojung Shin     */
361b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby    private static boolean checkDuplicatePortOmadmWappush(byte[] origPdu, int index) {
362d027329cd6105c05c157e3858a170e4f04eb0e3eSoojung Shin        index += 4;
363d027329cd6105c05c157e3858a170e4f04eb0e3eSoojung Shin        byte[] omaPdu = new byte[origPdu.length - index];
364d027329cd6105c05c157e3858a170e4f04eb0e3eSoojung Shin        System.arraycopy(origPdu, index, omaPdu, 0, omaPdu.length);
365d027329cd6105c05c157e3858a170e4f04eb0e3eSoojung Shin
366d027329cd6105c05c157e3858a170e4f04eb0e3eSoojung Shin        WspTypeDecoder pduDecoder = new WspTypeDecoder(omaPdu);
367d027329cd6105c05c157e3858a170e4f04eb0e3eSoojung Shin        int wspIndex = 2;
368d027329cd6105c05c157e3858a170e4f04eb0e3eSoojung Shin
369d027329cd6105c05c157e3858a170e4f04eb0e3eSoojung Shin        // Process header length field
370d027329cd6105c05c157e3858a170e4f04eb0e3eSoojung Shin        if (pduDecoder.decodeUintvarInteger(wspIndex) == false) {
371d027329cd6105c05c157e3858a170e4f04eb0e3eSoojung Shin            return false;
372d027329cd6105c05c157e3858a170e4f04eb0e3eSoojung Shin        }
373d027329cd6105c05c157e3858a170e4f04eb0e3eSoojung Shin
374d027329cd6105c05c157e3858a170e4f04eb0e3eSoojung Shin        wspIndex += pduDecoder.getDecodedDataLength(); // advance to next field
375d027329cd6105c05c157e3858a170e4f04eb0e3eSoojung Shin
376d027329cd6105c05c157e3858a170e4f04eb0e3eSoojung Shin        // Process content type field
377d027329cd6105c05c157e3858a170e4f04eb0e3eSoojung Shin        if (pduDecoder.decodeContentType(wspIndex) == false) {
378d027329cd6105c05c157e3858a170e4f04eb0e3eSoojung Shin            return false;
379d027329cd6105c05c157e3858a170e4f04eb0e3eSoojung Shin        }
380d027329cd6105c05c157e3858a170e4f04eb0e3eSoojung Shin
381d027329cd6105c05c157e3858a170e4f04eb0e3eSoojung Shin        String mimeType = pduDecoder.getValueString();
382d8f9a83cab34de38981dc3ba5ca9df8dda02dbc0Marco Nelissen        if (mimeType != null && mimeType.equals(WspTypeDecoder.CONTENT_TYPE_B_PUSH_SYNCML_NOTI)) {
383d8f9a83cab34de38981dc3ba5ca9df8dda02dbc0Marco Nelissen            return true;
384d027329cd6105c05c157e3858a170e4f04eb0e3eSoojung Shin        }
385d027329cd6105c05c157e3858a170e4f04eb0e3eSoojung Shin        return false;
386d027329cd6105c05c157e3858a170e4f04eb0e3eSoojung Shin    }
387767a662ecde33c3979bf02b793d392aca0403162Wink Saville}
388