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());
9132319dd852709b975e53360f479634e43db4d224Jake Hamby                fillIn.putExtra("format", android.telephony.SmsMessage.FORMAT_3GPP2);
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} */
101145ff609de3206b585819ef974fab20cdc2d9f5eJake Hamby    @Override
1022b8bcfe5b74e1a34d136f4ff46e3c94397f38f82Wink Saville    public int dispatchMessage(SmsMessageBase smsb) {
103767a662ecde33c3979bf02b793d392aca0403162Wink Saville
104767a662ecde33c3979bf02b793d392aca0403162Wink Saville        // If sms is null, means there was a parsing error.
105767a662ecde33c3979bf02b793d392aca0403162Wink Saville        if (smsb == null) {
1064219797afc2f5369c27cf7be752e9bc3bdb8057djsh            Log.e(TAG, "dispatchMessage: message is null");
1073960ced4638fdb24ddf904fcb6734dae0959671ejsh            return Intents.RESULT_SMS_GENERIC_ERROR;
108767a662ecde33c3979bf02b793d392aca0403162Wink Saville        }
109767a662ecde33c3979bf02b793d392aca0403162Wink Saville
110117eace23924f575877ae8ecbb899af22e6f16c0Cheng Yang        String inEcm=SystemProperties.get(TelephonyProperties.PROPERTY_INECM_MODE, "false");
111117eace23924f575877ae8ecbb899af22e6f16c0Cheng Yang        if (inEcm.equals("true")) {
112ea803b8e0cc613309d0ce096df9c13e9690243ffSatish Roddom            return Activity.RESULT_OK;
113117eace23924f575877ae8ecbb899af22e6f16c0Cheng Yang        }
114117eace23924f575877ae8ecbb899af22e6f16c0Cheng Yang
115cde0233512f8dbbc62238e90c850c310894e3972Wink Saville        if (mSmsReceiveDisabled) {
116cde0233512f8dbbc62238e90c850c310894e3972Wink Saville            // Device doesn't support receiving SMS,
117c049f9ad5b4f5bc32f368646e624aef7707b7252John Wang            Log.d(TAG, "Received short message on device which doesn't support "
118cde0233512f8dbbc62238e90c850c310894e3972Wink Saville                    + "receiving SMS. Ignored.");
119c049f9ad5b4f5bc32f368646e624aef7707b7252John Wang            return Intents.RESULT_SMS_HANDLED;
120c049f9ad5b4f5bc32f368646e624aef7707b7252John Wang        }
121c049f9ad5b4f5bc32f368646e624aef7707b7252John Wang
1229d34319f1ce5be4124a0b6293162587f4573496fChristian Gustafsson        // See if we have a network duplicate SMS.
12364c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink        SmsMessage sms = (SmsMessage) smsb;
1249d34319f1ce5be4124a0b6293162587f4573496fChristian Gustafsson        mLastDispatchedSmsFingerprint = sms.getIncomingSmsFingerprint();
1259d34319f1ce5be4124a0b6293162587f4573496fChristian Gustafsson        if (mLastAcknowledgedSmsFingerprint != null &&
1269d34319f1ce5be4124a0b6293162587f4573496fChristian Gustafsson                Arrays.equals(mLastDispatchedSmsFingerprint, mLastAcknowledgedSmsFingerprint)) {
1279d34319f1ce5be4124a0b6293162587f4573496fChristian Gustafsson            return Intents.RESULT_SMS_HANDLED;
1289d34319f1ce5be4124a0b6293162587f4573496fChristian Gustafsson        }
1299d34319f1ce5be4124a0b6293162587f4573496fChristian Gustafsson        // Decode BD stream and set sms variables.
130767a662ecde33c3979bf02b793d392aca0403162Wink Saville        sms.parseSms();
13164c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink        int teleService = sms.getTeleService();
13264c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink        boolean handled = false;
133767a662ecde33c3979bf02b793d392aca0403162Wink Saville
134a01726a7fdd872cd8e1e8a9dfa52fb9cdbf01019jsh        if ((SmsEnvelope.TELESERVICE_VMN == teleService) ||
135a01726a7fdd872cd8e1e8a9dfa52fb9cdbf01019jsh                (SmsEnvelope.TELESERVICE_MWI == teleService)) {
136a01726a7fdd872cd8e1e8a9dfa52fb9cdbf01019jsh            // handling Voicemail
137a01726a7fdd872cd8e1e8a9dfa52fb9cdbf01019jsh            int voicemailCount = sms.getNumOfVoicemails();
138a01726a7fdd872cd8e1e8a9dfa52fb9cdbf01019jsh            Log.d(TAG, "Voicemail count=" + voicemailCount);
139a01726a7fdd872cd8e1e8a9dfa52fb9cdbf01019jsh            // Store the voicemail count in preferences.
140a01726a7fdd872cd8e1e8a9dfa52fb9cdbf01019jsh            SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(
141b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby                    mContext);
142a01726a7fdd872cd8e1e8a9dfa52fb9cdbf01019jsh            SharedPreferences.Editor editor = sp.edit();
143a01726a7fdd872cd8e1e8a9dfa52fb9cdbf01019jsh            editor.putInt(CDMAPhone.VM_COUNT_CDMA, voicemailCount);
144fa8e271636b9e9b86f247cdb4c91d9ebe9675c27Brad Fitzpatrick            editor.apply();
145b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby            mPhone.setVoiceMessageWaiting(1, voicemailCount);
146a01726a7fdd872cd8e1e8a9dfa52fb9cdbf01019jsh            handled = true;
147d304ae583d862250a21b5949fc3dbdf3af1febacTammo Spalink        } else if (((SmsEnvelope.TELESERVICE_WMT == teleService) ||
148d304ae583d862250a21b5949fc3dbdf3af1febacTammo Spalink                (SmsEnvelope.TELESERVICE_WEMT == teleService)) &&
149d304ae583d862250a21b5949fc3dbdf3af1febacTammo Spalink                sms.isStatusReportMessage()) {
150d304ae583d862250a21b5949fc3dbdf3af1febacTammo Spalink            handleCdmaStatusReport(sms);
151d304ae583d862250a21b5949fc3dbdf3af1febacTammo Spalink            handled = true;
152a01726a7fdd872cd8e1e8a9dfa52fb9cdbf01019jsh        } else if ((sms.getUserData() == null)) {
15343a17654cf4bfe7f1ec22bd8b7b32daccdf27c09Joe Onorato            if (false) {
154767a662ecde33c3979bf02b793d392aca0403162Wink Saville                Log.d(TAG, "Received SMS without user data");
155767a662ecde33c3979bf02b793d392aca0403162Wink Saville            }
15664c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink            handled = true;
157767a662ecde33c3979bf02b793d392aca0403162Wink Saville        }
158767a662ecde33c3979bf02b793d392aca0403162Wink Saville
1593960ced4638fdb24ddf904fcb6734dae0959671ejsh        if (handled) {
1603960ced4638fdb24ddf904fcb6734dae0959671ejsh            return Intents.RESULT_SMS_HANDLED;
1613960ced4638fdb24ddf904fcb6734dae0959671ejsh        }
162767a662ecde33c3979bf02b793d392aca0403162Wink Saville
163b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby        if (!mStorageMonitor.isStorageAvailable() &&
164b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby                sms.getMessageClass() != MessageClass.CLASS_0) {
165a01726a7fdd872cd8e1e8a9dfa52fb9cdbf01019jsh            // It's a storable message and there's no storage available.  Bail.
166a01726a7fdd872cd8e1e8a9dfa52fb9cdbf01019jsh            // (See C.S0015-B v2.0 for a description of "Immediate Display"
167a01726a7fdd872cd8e1e8a9dfa52fb9cdbf01019jsh            // messages, which we represent as CLASS_0.)
168a01726a7fdd872cd8e1e8a9dfa52fb9cdbf01019jsh            return Intents.RESULT_SMS_OUT_OF_MEMORY;
169a01726a7fdd872cd8e1e8a9dfa52fb9cdbf01019jsh        }
170a01726a7fdd872cd8e1e8a9dfa52fb9cdbf01019jsh
171c84401fb8b3ed90039bd132b343852303ef88ce6yong liu        if (SmsEnvelope.TELESERVICE_WAP == teleService) {
1723960ced4638fdb24ddf904fcb6734dae0959671ejsh            return processCdmaWapPdu(sms.getUserData(), sms.messageRef,
1733960ced4638fdb24ddf904fcb6734dae0959671ejsh                    sms.getOriginatingAddress());
174767a662ecde33c3979bf02b793d392aca0403162Wink Saville        }
175767a662ecde33c3979bf02b793d392aca0403162Wink Saville
1767e207afd497f8822ca34babe1d9cd1f6d5402fadTammo Spalink        // Reject (NAK) any messages with teleservice ids that have
1777e207afd497f8822ca34babe1d9cd1f6d5402fadTammo Spalink        // not yet been handled and also do not correspond to the two
1787e207afd497f8822ca34babe1d9cd1f6d5402fadTammo Spalink        // kinds that are processed below.
1797e207afd497f8822ca34babe1d9cd1f6d5402fadTammo Spalink        if ((SmsEnvelope.TELESERVICE_WMT != teleService) &&
18083fd7b0d53f2fecb5b92cb911910e07659e246caJohn Joseph                (SmsEnvelope.TELESERVICE_WEMT != teleService) &&
18183fd7b0d53f2fecb5b92cb911910e07659e246caJohn Joseph                (SmsEnvelope.MESSAGE_TYPE_BROADCAST != sms.getMessageType())) {
1827e207afd497f8822ca34babe1d9cd1f6d5402fadTammo Spalink            return Intents.RESULT_SMS_UNSUPPORTED;
1837e207afd497f8822ca34babe1d9cd1f6d5402fadTammo Spalink        }
1847e207afd497f8822ca34babe1d9cd1f6d5402fadTammo Spalink
185b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby        return dispatchNormalMessage(smsb);
186767a662ecde33c3979bf02b793d392aca0403162Wink Saville    }
187767a662ecde33c3979bf02b793d392aca0403162Wink Saville
188767a662ecde33c3979bf02b793d392aca0403162Wink Saville    /**
189767a662ecde33c3979bf02b793d392aca0403162Wink Saville     * Processes inbound messages that are in the WAP-WDP PDU format. See
190767a662ecde33c3979bf02b793d392aca0403162Wink Saville     * wap-259-wdp-20010614-a section 6.5 for details on the WAP-WDP PDU format.
191767a662ecde33c3979bf02b793d392aca0403162Wink Saville     * WDP segments are gathered until a datagram completes and gets dispatched.
192767a662ecde33c3979bf02b793d392aca0403162Wink Saville     *
193767a662ecde33c3979bf02b793d392aca0403162Wink Saville     * @param pdu The WAP-WDP PDU segment
1943960ced4638fdb24ddf904fcb6734dae0959671ejsh     * @return a result code from {@link Telephony.Sms.Intents}, or
1953960ced4638fdb24ddf904fcb6734dae0959671ejsh     *         {@link Activity#RESULT_OK} if the message has been broadcast
1963960ced4638fdb24ddf904fcb6734dae0959671ejsh     *         to applications
197767a662ecde33c3979bf02b793d392aca0403162Wink Saville     */
1983960ced4638fdb24ddf904fcb6734dae0959671ejsh    protected int processCdmaWapPdu(byte[] pdu, int referenceNumber, String address) {
199767a662ecde33c3979bf02b793d392aca0403162Wink Saville        int index = 0;
200767a662ecde33c3979bf02b793d392aca0403162Wink Saville
201929ca5e49760c3d5af8c7455cd38e29336b5e262Jake Hamby        int msgType = (0xFF & pdu[index++]);
202b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby        if (msgType != 0) {
203767a662ecde33c3979bf02b793d392aca0403162Wink Saville            Log.w(TAG, "Received a WAP SMS which is not WDP. Discard.");
2043960ced4638fdb24ddf904fcb6734dae0959671ejsh            return Intents.RESULT_SMS_HANDLED;
205767a662ecde33c3979bf02b793d392aca0403162Wink Saville        }
206929ca5e49760c3d5af8c7455cd38e29336b5e262Jake Hamby        int totalSegments = (0xFF & pdu[index++]);   // >= 1
207929ca5e49760c3d5af8c7455cd38e29336b5e262Jake Hamby        int segment = (0xFF & pdu[index++]);         // >= 0
208929ca5e49760c3d5af8c7455cd38e29336b5e262Jake Hamby
209929ca5e49760c3d5af8c7455cd38e29336b5e262Jake Hamby        if (segment >= totalSegments) {
210929ca5e49760c3d5af8c7455cd38e29336b5e262Jake Hamby            Log.e(TAG, "WDP bad segment #" + segment + " expecting 0-" + (totalSegments - 1));
211929ca5e49760c3d5af8c7455cd38e29336b5e262Jake Hamby            return Intents.RESULT_SMS_HANDLED;
212929ca5e49760c3d5af8c7455cd38e29336b5e262Jake Hamby        }
213767a662ecde33c3979bf02b793d392aca0403162Wink Saville
2145c7d9e8194900a2b1699cd57f95b22ca5f7b9be2David Krause        // Only the first segment contains sourcePort and destination Port
215b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby        int sourcePort = 0;
216b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby        int destinationPort = 0;
2175c7d9e8194900a2b1699cd57f95b22ca5f7b9be2David Krause        if (segment == 0) {
2185c7d9e8194900a2b1699cd57f95b22ca5f7b9be2David Krause            //process WDP segment
2195c7d9e8194900a2b1699cd57f95b22ca5f7b9be2David Krause            sourcePort = (0xFF & pdu[index++]) << 8;
2205c7d9e8194900a2b1699cd57f95b22ca5f7b9be2David Krause            sourcePort |= 0xFF & pdu[index++];
2215c7d9e8194900a2b1699cd57f95b22ca5f7b9be2David Krause            destinationPort = (0xFF & pdu[index++]) << 8;
2225c7d9e8194900a2b1699cd57f95b22ca5f7b9be2David Krause            destinationPort |= 0xFF & pdu[index++];
223d027329cd6105c05c157e3858a170e4f04eb0e3eSoojung Shin            // Some carriers incorrectly send duplicate port fields in omadm wap pushes.
224d027329cd6105c05c157e3858a170e4f04eb0e3eSoojung Shin            // If configured, check for that here
225d027329cd6105c05c157e3858a170e4f04eb0e3eSoojung Shin            if (mCheckForDuplicatePortsInOmadmWapPush) {
226d027329cd6105c05c157e3858a170e4f04eb0e3eSoojung Shin                if (checkDuplicatePortOmadmWappush(pdu,index)) {
227d027329cd6105c05c157e3858a170e4f04eb0e3eSoojung Shin                    index = index + 4; // skip duplicate port fields
228d027329cd6105c05c157e3858a170e4f04eb0e3eSoojung Shin                }
229d027329cd6105c05c157e3858a170e4f04eb0e3eSoojung Shin            }
2305c7d9e8194900a2b1699cd57f95b22ca5f7b9be2David Krause        }
231767a662ecde33c3979bf02b793d392aca0403162Wink Saville
232767a662ecde33c3979bf02b793d392aca0403162Wink Saville        // Lookup all other related parts
233767a662ecde33c3979bf02b793d392aca0403162Wink Saville        Log.i(TAG, "Received WAP PDU. Type = " + msgType + ", originator = " + address
234767a662ecde33c3979bf02b793d392aca0403162Wink Saville                + ", src-port = " + sourcePort + ", dst-port = " + destinationPort
235b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby                + ", ID = " + referenceNumber + ", segment# = " + segment + '/' + totalSegments);
236767a662ecde33c3979bf02b793d392aca0403162Wink Saville
237b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby        // pass the user data portion of the PDU to the shared handler in SMSDispatcher
238b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby        byte[] userData = new byte[pdu.length - index];
239b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby        System.arraycopy(pdu, index, userData, 0, pdu.length - index);
240767a662ecde33c3979bf02b793d392aca0403162Wink Saville
241b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby        return processMessagePart(userData, address, referenceNumber, segment, totalSegments,
242b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby                0L, destinationPort, true);
243767a662ecde33c3979bf02b793d392aca0403162Wink Saville    }
244767a662ecde33c3979bf02b793d392aca0403162Wink Saville
245767a662ecde33c3979bf02b793d392aca0403162Wink Saville    /** {@inheritDoc} */
246145ff609de3206b585819ef974fab20cdc2d9f5eJake Hamby    @Override
2471f952a178db86559ff4bab79c4a9b5fae18096bfTammo Spalink    protected void sendData(String destAddr, String scAddr, int destPort,
2481f952a178db86559ff4bab79c4a9b5fae18096bfTammo Spalink            byte[] data, PendingIntent sentIntent, PendingIntent deliveryIntent) {
2491f952a178db86559ff4bab79c4a9b5fae18096bfTammo Spalink        SmsMessage.SubmitPdu pdu = SmsMessage.getSubmitPdu(
2501f952a178db86559ff4bab79c4a9b5fae18096bfTammo Spalink                scAddr, destAddr, destPort, data, (deliveryIntent != null));
2511f952a178db86559ff4bab79c4a9b5fae18096bfTammo Spalink        sendSubmitPdu(pdu, sentIntent, deliveryIntent);
2521f952a178db86559ff4bab79c4a9b5fae18096bfTammo Spalink    }
2531f952a178db86559ff4bab79c4a9b5fae18096bfTammo Spalink
2541f952a178db86559ff4bab79c4a9b5fae18096bfTammo Spalink    /** {@inheritDoc} */
255145ff609de3206b585819ef974fab20cdc2d9f5eJake Hamby    @Override
2561f952a178db86559ff4bab79c4a9b5fae18096bfTammo Spalink    protected void sendText(String destAddr, String scAddr, String text,
2571f952a178db86559ff4bab79c4a9b5fae18096bfTammo Spalink            PendingIntent sentIntent, PendingIntent deliveryIntent) {
2581f952a178db86559ff4bab79c4a9b5fae18096bfTammo Spalink        SmsMessage.SubmitPdu pdu = SmsMessage.getSubmitPdu(
2591f952a178db86559ff4bab79c4a9b5fae18096bfTammo Spalink                scAddr, destAddr, text, (deliveryIntent != null), null);
2601f952a178db86559ff4bab79c4a9b5fae18096bfTammo Spalink        sendSubmitPdu(pdu, sentIntent, deliveryIntent);
2611f952a178db86559ff4bab79c4a9b5fae18096bfTammo Spalink    }
2621f952a178db86559ff4bab79c4a9b5fae18096bfTammo Spalink
2631f952a178db86559ff4bab79c4a9b5fae18096bfTammo Spalink    /** {@inheritDoc} */
264145ff609de3206b585819ef974fab20cdc2d9f5eJake Hamby    @Override
265b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby    protected TextEncodingDetails calculateLength(CharSequence messageBody,
266b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby            boolean use7bitOnly) {
267b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby        return SmsMessage.calculateLength(messageBody, use7bitOnly);
268b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby    }
269767a662ecde33c3979bf02b793d392aca0403162Wink Saville
270b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby    /** {@inheritDoc} */
271b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby    @Override
272b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby    protected void sendNewSubmitPdu(String destinationAddress, String scAddress,
273b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby            String message, SmsHeader smsHeader, int encoding,
274b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby            PendingIntent sentIntent, PendingIntent deliveryIntent, boolean lastPart) {
275b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby        UserData uData = new UserData();
276b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby        uData.payloadStr = message;
277b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby        uData.userDataHeader = smsHeader;
278b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby        if (encoding == android.telephony.SmsMessage.ENCODING_7BIT) {
279b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby            uData.msgEncoding = UserData.ENCODING_GSM_7BIT_ALPHABET;
280b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby        } else { // assume UTF-16
281b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby            uData.msgEncoding = UserData.ENCODING_UNICODE_16;
282b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby        }
283b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby        uData.msgEncodingSet = true;
284fc78f358cb1d1cee99758bcd6ef998a122ef27c9Tammo Spalink
285b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby        /* By setting the statusReportRequested bit only for the
286b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby         * last message fragment, this will result in only one
287b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby         * callback to the sender when that last fragment delivery
288b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby         * has been acknowledged. */
289b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby        SmsMessage.SubmitPdu submitPdu = SmsMessage.getSubmitPdu(destinationAddress,
290b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby                uData, (deliveryIntent != null) && lastPart);
291767a662ecde33c3979bf02b793d392aca0403162Wink Saville
292b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby        sendSubmitPdu(submitPdu, sentIntent, deliveryIntent);
293767a662ecde33c3979bf02b793d392aca0403162Wink Saville    }
294767a662ecde33c3979bf02b793d392aca0403162Wink Saville
2951f952a178db86559ff4bab79c4a9b5fae18096bfTammo Spalink    protected void sendSubmitPdu(SmsMessage.SubmitPdu pdu,
2961f952a178db86559ff4bab79c4a9b5fae18096bfTammo Spalink            PendingIntent sentIntent, PendingIntent deliveryIntent) {
2971f952a178db86559ff4bab79c4a9b5fae18096bfTammo Spalink        if (SystemProperties.getBoolean(TelephonyProperties.PROPERTY_INECM_MODE, false)) {
298a1c94ae4f75dab030219069864029f5bd9498fb0Richard Meng            if (sentIntent != null) {
299a1c94ae4f75dab030219069864029f5bd9498fb0Richard Meng                try {
300a1c94ae4f75dab030219069864029f5bd9498fb0Richard Meng                    sentIntent.send(SmsManager.RESULT_ERROR_NO_SERVICE);
301a1c94ae4f75dab030219069864029f5bd9498fb0Richard Meng                } catch (CanceledException ex) {}
302a1c94ae4f75dab030219069864029f5bd9498fb0Richard Meng            }
30343a17654cf4bfe7f1ec22bd8b7b32daccdf27c09Joe Onorato            if (false) {
304a1c94ae4f75dab030219069864029f5bd9498fb0Richard Meng                Log.d(TAG, "Block SMS in Emergency Callback mode");
305a1c94ae4f75dab030219069864029f5bd9498fb0Richard Meng            }
306a1c94ae4f75dab030219069864029f5bd9498fb0Richard Meng            return;
307a1c94ae4f75dab030219069864029f5bd9498fb0Richard Meng        }
3081f952a178db86559ff4bab79c4a9b5fae18096bfTammo Spalink        sendRawPdu(pdu.encodedScAddress, pdu.encodedMessage, sentIntent, deliveryIntent);
309a1c94ae4f75dab030219069864029f5bd9498fb0Richard Meng    }
310a1c94ae4f75dab030219069864029f5bd9498fb0Richard Meng
311767a662ecde33c3979bf02b793d392aca0403162Wink Saville    /** {@inheritDoc} */
312145ff609de3206b585819ef974fab20cdc2d9f5eJake Hamby    @Override
313767a662ecde33c3979bf02b793d392aca0403162Wink Saville    protected void sendSms(SmsTracker tracker) {
314145ff609de3206b585819ef974fab20cdc2d9f5eJake Hamby        HashMap<String, Object> map = tracker.mData;
315767a662ecde33c3979bf02b793d392aca0403162Wink Saville
316059fe88115ccb70d9870698e490ed5b4c88da50cJake Hamby        // byte smsc[] = (byte[]) map.get("smsc");  // unused for CDMA
317767a662ecde33c3979bf02b793d392aca0403162Wink Saville        byte pdu[] = (byte[]) map.get("pdu");
318767a662ecde33c3979bf02b793d392aca0403162Wink Saville
319767a662ecde33c3979bf02b793d392aca0403162Wink Saville        Message reply = obtainMessage(EVENT_SEND_SMS_COMPLETE, tracker);
320767a662ecde33c3979bf02b793d392aca0403162Wink Saville        mCm.sendCdmaSms(pdu, reply);
321767a662ecde33c3979bf02b793d392aca0403162Wink Saville    }
322767a662ecde33c3979bf02b793d392aca0403162Wink Saville
323767a662ecde33c3979bf02b793d392aca0403162Wink Saville    /** {@inheritDoc} */
324145ff609de3206b585819ef974fab20cdc2d9f5eJake Hamby    @Override
325b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby    protected void acknowledgeLastIncomingSms(boolean success, int result, Message response) {
326117eace23924f575877ae8ecbb899af22e6f16c0Cheng Yang        String inEcm=SystemProperties.get(TelephonyProperties.PROPERTY_INECM_MODE, "false");
327117eace23924f575877ae8ecbb899af22e6f16c0Cheng Yang        if (inEcm.equals("true")) {
328117eace23924f575877ae8ecbb899af22e6f16c0Cheng Yang            return;
329117eace23924f575877ae8ecbb899af22e6f16c0Cheng Yang        }
330117eace23924f575877ae8ecbb899af22e6f16c0Cheng Yang
331b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby        int causeCode = resultToCause(result);
332b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby        mCm.acknowledgeLastIncomingCdmaSms(success, causeCode, response);
3339d34319f1ce5be4124a0b6293162587f4573496fChristian Gustafsson
334b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby        if (causeCode == 0) {
335b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby            mLastAcknowledgedSmsFingerprint = mLastDispatchedSmsFingerprint;
336767a662ecde33c3979bf02b793d392aca0403162Wink Saville        }
337b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby        mLastDispatchedSmsFingerprint = null;
338767a662ecde33c3979bf02b793d392aca0403162Wink Saville    }
339767a662ecde33c3979bf02b793d392aca0403162Wink Saville
340b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby    private static int resultToCause(int rc) {
341867641ece36e2fd17faaea79cf19506ab17177c6jsh        switch (rc) {
3427e207afd497f8822ca34babe1d9cd1f6d5402fadTammo Spalink        case Activity.RESULT_OK:
3437e207afd497f8822ca34babe1d9cd1f6d5402fadTammo Spalink        case Intents.RESULT_SMS_HANDLED:
3447e207afd497f8822ca34babe1d9cd1f6d5402fadTammo Spalink            // Cause code is ignored on success.
3457e207afd497f8822ca34babe1d9cd1f6d5402fadTammo Spalink            return 0;
3467e207afd497f8822ca34babe1d9cd1f6d5402fadTammo Spalink        case Intents.RESULT_SMS_OUT_OF_MEMORY:
3477e207afd497f8822ca34babe1d9cd1f6d5402fadTammo Spalink            return CommandsInterface.CDMA_SMS_FAIL_CAUSE_RESOURCE_SHORTAGE;
3487e207afd497f8822ca34babe1d9cd1f6d5402fadTammo Spalink        case Intents.RESULT_SMS_UNSUPPORTED:
3497e207afd497f8822ca34babe1d9cd1f6d5402fadTammo Spalink            return CommandsInterface.CDMA_SMS_FAIL_CAUSE_INVALID_TELESERVICE_ID;
3507e207afd497f8822ca34babe1d9cd1f6d5402fadTammo Spalink        case Intents.RESULT_SMS_GENERIC_ERROR:
3517e207afd497f8822ca34babe1d9cd1f6d5402fadTammo Spalink        default:
3523ff560d7ba9fcedc4d388f63b756108a715266f4jsh            return CommandsInterface.CDMA_SMS_FAIL_CAUSE_ENCODING_PROBLEM;
353867641ece36e2fd17faaea79cf19506ab17177c6jsh        }
354867641ece36e2fd17faaea79cf19506ab17177c6jsh    }
355d027329cd6105c05c157e3858a170e4f04eb0e3eSoojung Shin
356d027329cd6105c05c157e3858a170e4f04eb0e3eSoojung Shin    /**
357d027329cd6105c05c157e3858a170e4f04eb0e3eSoojung Shin     * Optional check to see if the received WapPush is an OMADM notification with erroneous
358d027329cd6105c05c157e3858a170e4f04eb0e3eSoojung Shin     * extra port fields.
359d027329cd6105c05c157e3858a170e4f04eb0e3eSoojung Shin     * - Some carriers make this mistake.
360d027329cd6105c05c157e3858a170e4f04eb0e3eSoojung Shin     * ex: MSGTYPE-TotalSegments-CurrentSegment
361d027329cd6105c05c157e3858a170e4f04eb0e3eSoojung Shin     *       -SourcePortDestPort-SourcePortDestPort-OMADM PDU
362d027329cd6105c05c157e3858a170e4f04eb0e3eSoojung Shin     * @param origPdu The WAP-WDP PDU segment
363d027329cd6105c05c157e3858a170e4f04eb0e3eSoojung Shin     * @param index Current Index while parsing the PDU.
364d027329cd6105c05c157e3858a170e4f04eb0e3eSoojung Shin     * @return True if OrigPdu is OmaDM Push Message which has duplicate ports.
365d027329cd6105c05c157e3858a170e4f04eb0e3eSoojung Shin     *         False if OrigPdu is NOT OmaDM Push Message which has duplicate ports.
366d027329cd6105c05c157e3858a170e4f04eb0e3eSoojung Shin     */
367b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby    private static boolean checkDuplicatePortOmadmWappush(byte[] origPdu, int index) {
368d027329cd6105c05c157e3858a170e4f04eb0e3eSoojung Shin        index += 4;
369d027329cd6105c05c157e3858a170e4f04eb0e3eSoojung Shin        byte[] omaPdu = new byte[origPdu.length - index];
370d027329cd6105c05c157e3858a170e4f04eb0e3eSoojung Shin        System.arraycopy(origPdu, index, omaPdu, 0, omaPdu.length);
371d027329cd6105c05c157e3858a170e4f04eb0e3eSoojung Shin
372d027329cd6105c05c157e3858a170e4f04eb0e3eSoojung Shin        WspTypeDecoder pduDecoder = new WspTypeDecoder(omaPdu);
373d027329cd6105c05c157e3858a170e4f04eb0e3eSoojung Shin        int wspIndex = 2;
374d027329cd6105c05c157e3858a170e4f04eb0e3eSoojung Shin
375d027329cd6105c05c157e3858a170e4f04eb0e3eSoojung Shin        // Process header length field
376d027329cd6105c05c157e3858a170e4f04eb0e3eSoojung Shin        if (pduDecoder.decodeUintvarInteger(wspIndex) == false) {
377d027329cd6105c05c157e3858a170e4f04eb0e3eSoojung Shin            return false;
378d027329cd6105c05c157e3858a170e4f04eb0e3eSoojung Shin        }
379d027329cd6105c05c157e3858a170e4f04eb0e3eSoojung Shin
380d027329cd6105c05c157e3858a170e4f04eb0e3eSoojung Shin        wspIndex += pduDecoder.getDecodedDataLength(); // advance to next field
381d027329cd6105c05c157e3858a170e4f04eb0e3eSoojung Shin
382d027329cd6105c05c157e3858a170e4f04eb0e3eSoojung Shin        // Process content type field
383d027329cd6105c05c157e3858a170e4f04eb0e3eSoojung Shin        if (pduDecoder.decodeContentType(wspIndex) == false) {
384d027329cd6105c05c157e3858a170e4f04eb0e3eSoojung Shin            return false;
385d027329cd6105c05c157e3858a170e4f04eb0e3eSoojung Shin        }
386d027329cd6105c05c157e3858a170e4f04eb0e3eSoojung Shin
387d027329cd6105c05c157e3858a170e4f04eb0e3eSoojung Shin        String mimeType = pduDecoder.getValueString();
388d8f9a83cab34de38981dc3ba5ca9df8dda02dbc0Marco Nelissen        if (mimeType != null && mimeType.equals(WspTypeDecoder.CONTENT_TYPE_B_PUSH_SYNCML_NOTI)) {
389d8f9a83cab34de38981dc3ba5ca9df8dda02dbc0Marco Nelissen            return true;
390d027329cd6105c05c157e3858a170e4f04eb0e3eSoojung Shin        }
391d027329cd6105c05c157e3858a170e4f04eb0e3eSoojung Shin        return false;
392d027329cd6105c05c157e3858a170e4f04eb0e3eSoojung Shin    }
393767a662ecde33c3979bf02b793d392aca0403162Wink Saville}
394