CdmaSMSDispatcher.java revision a01726a7fdd872cd8e1e8a9dfa52fb9cdbf01019
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;
24ce099c3226b33b43e0dd5d1f24347b14a2223ee1David Krauseimport android.content.SharedPreferences;
25767a662ecde33c3979bf02b793d392aca0403162Wink Savilleimport android.database.Cursor;
26767a662ecde33c3979bf02b793d392aca0403162Wink Savilleimport android.database.SQLException;
27767a662ecde33c3979bf02b793d392aca0403162Wink Savilleimport android.os.AsyncResult;
28767a662ecde33c3979bf02b793d392aca0403162Wink Savilleimport android.os.Message;
29117eace23924f575877ae8ecbb899af22e6f16c0Cheng Yangimport android.os.SystemProperties;
303960ced4638fdb24ddf904fcb6734dae0959671ejshimport android.provider.Telephony;
31867641ece36e2fd17faaea79cf19506ab17177c6jshimport android.provider.Telephony.Sms.Intents;
32ce099c3226b33b43e0dd5d1f24347b14a2223ee1David Krauseimport android.preference.PreferenceManager;
33767a662ecde33c3979bf02b793d392aca0403162Wink Savilleimport android.util.Config;
34767a662ecde33c3979bf02b793d392aca0403162Wink Savilleimport android.util.Log;
35a1c94ae4f75dab030219069864029f5bd9498fb0Richard Mengimport android.telephony.SmsManager;
36a01726a7fdd872cd8e1e8a9dfa52fb9cdbf01019jshimport android.telephony.SmsMessage.MessageClass;
37767a662ecde33c3979bf02b793d392aca0403162Wink Saville
38117eace23924f575877ae8ecbb899af22e6f16c0Cheng Yangimport com.android.internal.telephony.TelephonyProperties;
39867641ece36e2fd17faaea79cf19506ab17177c6jshimport com.android.internal.telephony.CommandsInterface;
40767a662ecde33c3979bf02b793d392aca0403162Wink Savilleimport com.android.internal.telephony.SmsHeader;
41767a662ecde33c3979bf02b793d392aca0403162Wink Savilleimport com.android.internal.telephony.SmsMessageBase;
42767a662ecde33c3979bf02b793d392aca0403162Wink Savilleimport com.android.internal.telephony.SMSDispatcher;
43767a662ecde33c3979bf02b793d392aca0403162Wink Savilleimport com.android.internal.telephony.cdma.SmsMessage;
44767a662ecde33c3979bf02b793d392aca0403162Wink Savilleimport com.android.internal.telephony.cdma.sms.SmsEnvelope;
45fc78f358cb1d1cee99758bcd6ef998a122ef27c9Tammo Spalinkimport com.android.internal.telephony.cdma.sms.UserData;
46767a662ecde33c3979bf02b793d392aca0403162Wink Savilleimport com.android.internal.util.HexDump;
47767a662ecde33c3979bf02b793d392aca0403162Wink Saville
48767a662ecde33c3979bf02b793d392aca0403162Wink Savilleimport java.io.ByteArrayOutputStream;
49767a662ecde33c3979bf02b793d392aca0403162Wink Savilleimport java.util.ArrayList;
50767a662ecde33c3979bf02b793d392aca0403162Wink Savilleimport java.util.HashMap;
51a1c94ae4f75dab030219069864029f5bd9498fb0Richard Mengimport java.lang.Boolean;
52767a662ecde33c3979bf02b793d392aca0403162Wink Saville
53767a662ecde33c3979bf02b793d392aca0403162Wink Saville
54767a662ecde33c3979bf02b793d392aca0403162Wink Savillefinal class CdmaSMSDispatcher extends SMSDispatcher {
55767a662ecde33c3979bf02b793d392aca0403162Wink Saville    private static final String TAG = "CDMA";
56767a662ecde33c3979bf02b793d392aca0403162Wink Saville
5764c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink    private CDMAPhone mCdmaPhone;
5864c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink
59767a662ecde33c3979bf02b793d392aca0403162Wink Saville    CdmaSMSDispatcher(CDMAPhone phone) {
60767a662ecde33c3979bf02b793d392aca0403162Wink Saville        super(phone);
6164c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink        mCdmaPhone = phone;
62767a662ecde33c3979bf02b793d392aca0403162Wink Saville    }
63767a662ecde33c3979bf02b793d392aca0403162Wink Saville
64767a662ecde33c3979bf02b793d392aca0403162Wink Saville    /**
65767a662ecde33c3979bf02b793d392aca0403162Wink Saville     * Called when a status report is received.  This should correspond to
66767a662ecde33c3979bf02b793d392aca0403162Wink Saville     * a previously successful SEND.
67767a662ecde33c3979bf02b793d392aca0403162Wink Saville     * Is a special GSM function, should never be called in CDMA!!
68767a662ecde33c3979bf02b793d392aca0403162Wink Saville     *
69767a662ecde33c3979bf02b793d392aca0403162Wink Saville     * @param ar AsyncResult passed into the message handler.  ar.result should
70767a662ecde33c3979bf02b793d392aca0403162Wink Saville     *           be a String representing the status report PDU, as ASCII hex.
71767a662ecde33c3979bf02b793d392aca0403162Wink Saville     */
72767a662ecde33c3979bf02b793d392aca0403162Wink Saville    protected void handleStatusReport(AsyncResult ar) {
73767a662ecde33c3979bf02b793d392aca0403162Wink Saville        Log.d(TAG, "handleStatusReport is a special GSM function, should never be called in CDMA!");
74767a662ecde33c3979bf02b793d392aca0403162Wink Saville    }
75767a662ecde33c3979bf02b793d392aca0403162Wink Saville
763960ced4638fdb24ddf904fcb6734dae0959671ejsh    /** {@inheritDoc} */
773960ced4638fdb24ddf904fcb6734dae0959671ejsh    protected int dispatchMessage(SmsMessageBase smsb) {
78767a662ecde33c3979bf02b793d392aca0403162Wink Saville
79767a662ecde33c3979bf02b793d392aca0403162Wink Saville        // If sms is null, means there was a parsing error.
80767a662ecde33c3979bf02b793d392aca0403162Wink Saville        if (smsb == null) {
813960ced4638fdb24ddf904fcb6734dae0959671ejsh            return Intents.RESULT_SMS_GENERIC_ERROR;
82767a662ecde33c3979bf02b793d392aca0403162Wink Saville        }
83767a662ecde33c3979bf02b793d392aca0403162Wink Saville
84117eace23924f575877ae8ecbb899af22e6f16c0Cheng Yang        String inEcm=SystemProperties.get(TelephonyProperties.PROPERTY_INECM_MODE, "false");
85117eace23924f575877ae8ecbb899af22e6f16c0Cheng Yang        if (inEcm.equals("true")) {
86117eace23924f575877ae8ecbb899af22e6f16c0Cheng Yang            return Intents.RESULT_SMS_GENERIC_ERROR;
87117eace23924f575877ae8ecbb899af22e6f16c0Cheng Yang        }
88117eace23924f575877ae8ecbb899af22e6f16c0Cheng Yang
89767a662ecde33c3979bf02b793d392aca0403162Wink Saville        // Decode BD stream and set sms variables.
9064c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink        SmsMessage sms = (SmsMessage) smsb;
91767a662ecde33c3979bf02b793d392aca0403162Wink Saville        sms.parseSms();
9264c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink        int teleService = sms.getTeleService();
9364c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink        boolean handled = false;
94767a662ecde33c3979bf02b793d392aca0403162Wink Saville
95a01726a7fdd872cd8e1e8a9dfa52fb9cdbf01019jsh        if ((SmsEnvelope.TELESERVICE_VMN == teleService) ||
96a01726a7fdd872cd8e1e8a9dfa52fb9cdbf01019jsh                (SmsEnvelope.TELESERVICE_MWI == teleService)) {
97a01726a7fdd872cd8e1e8a9dfa52fb9cdbf01019jsh            // handling Voicemail
98a01726a7fdd872cd8e1e8a9dfa52fb9cdbf01019jsh            int voicemailCount = sms.getNumOfVoicemails();
99a01726a7fdd872cd8e1e8a9dfa52fb9cdbf01019jsh            Log.d(TAG, "Voicemail count=" + voicemailCount);
100a01726a7fdd872cd8e1e8a9dfa52fb9cdbf01019jsh            // Store the voicemail count in preferences.
101a01726a7fdd872cd8e1e8a9dfa52fb9cdbf01019jsh            SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(
102a01726a7fdd872cd8e1e8a9dfa52fb9cdbf01019jsh                    ((CDMAPhone) mPhone).getContext());
103a01726a7fdd872cd8e1e8a9dfa52fb9cdbf01019jsh            SharedPreferences.Editor editor = sp.edit();
104a01726a7fdd872cd8e1e8a9dfa52fb9cdbf01019jsh            editor.putInt(CDMAPhone.VM_COUNT_CDMA, voicemailCount);
105a01726a7fdd872cd8e1e8a9dfa52fb9cdbf01019jsh            editor.commit();
106a01726a7fdd872cd8e1e8a9dfa52fb9cdbf01019jsh            ((CDMAPhone) mPhone).updateMessageWaitingIndicator(voicemailCount);
107a01726a7fdd872cd8e1e8a9dfa52fb9cdbf01019jsh            handled = true;
108a01726a7fdd872cd8e1e8a9dfa52fb9cdbf01019jsh        } else if ((sms.getUserData() == null)) {
109767a662ecde33c3979bf02b793d392aca0403162Wink Saville            if (Config.LOGD) {
110767a662ecde33c3979bf02b793d392aca0403162Wink Saville                Log.d(TAG, "Received SMS without user data");
111767a662ecde33c3979bf02b793d392aca0403162Wink Saville            }
11264c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink            handled = true;
113767a662ecde33c3979bf02b793d392aca0403162Wink Saville        }
114767a662ecde33c3979bf02b793d392aca0403162Wink Saville
1153960ced4638fdb24ddf904fcb6734dae0959671ejsh        if (handled) {
1163960ced4638fdb24ddf904fcb6734dae0959671ejsh            return Intents.RESULT_SMS_HANDLED;
1173960ced4638fdb24ddf904fcb6734dae0959671ejsh        }
118767a662ecde33c3979bf02b793d392aca0403162Wink Saville
119a01726a7fdd872cd8e1e8a9dfa52fb9cdbf01019jsh        if (!mStorageAvailable && (sms.getMessageClass() != MessageClass.CLASS_0)) {
120a01726a7fdd872cd8e1e8a9dfa52fb9cdbf01019jsh            // It's a storable message and there's no storage available.  Bail.
121a01726a7fdd872cd8e1e8a9dfa52fb9cdbf01019jsh            // (See C.S0015-B v2.0 for a description of "Immediate Display"
122a01726a7fdd872cd8e1e8a9dfa52fb9cdbf01019jsh            // messages, which we represent as CLASS_0.)
123a01726a7fdd872cd8e1e8a9dfa52fb9cdbf01019jsh            return Intents.RESULT_SMS_OUT_OF_MEMORY;
124a01726a7fdd872cd8e1e8a9dfa52fb9cdbf01019jsh        }
125a01726a7fdd872cd8e1e8a9dfa52fb9cdbf01019jsh
126c84401fb8b3ed90039bd132b343852303ef88ce6yong liu        if (SmsEnvelope.TELESERVICE_WAP == teleService) {
1273960ced4638fdb24ddf904fcb6734dae0959671ejsh            return processCdmaWapPdu(sms.getUserData(), sms.messageRef,
1283960ced4638fdb24ddf904fcb6734dae0959671ejsh                    sms.getOriginatingAddress());
129767a662ecde33c3979bf02b793d392aca0403162Wink Saville        }
130767a662ecde33c3979bf02b793d392aca0403162Wink Saville
13164c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink        /**
13264c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink         * TODO(cleanup): Why are we using a getter method for this
13364c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink         * (and for so many other sms fields)?  Trivial getters and
13464c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink         * setters like this are direct violations of the style guide.
13564c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink         * If the purpose is to protect agaist writes (by not
13664c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink         * providing a setter) then any protection is illusory (and
13764c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink         * hence bad) for cases where the values are not primitives,
13864c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink         * such as this call for the header.  Since this is an issue
13964c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink         * with the public API it cannot be changed easily, but maybe
14064c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink         * something can be done eventually.
14164c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink         */
14264c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink        SmsHeader smsHeader = sms.getUserDataHeader();
14364c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink
14464c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink        /**
14564c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink         * TODO(cleanup): Since both CDMA and GSM use the same header
14664c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink         * format, this dispatch processing is naturally identical,
14764c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink         * and code should probably not be replicated explicitly.
14864c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink         */
14964c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink        // See if message is partial or port addressed.
15064c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink        if ((smsHeader == null) || (smsHeader.concatRef == null)) {
15164c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink            // Message is not partial (not part of concatenated sequence).
152767a662ecde33c3979bf02b793d392aca0403162Wink Saville            byte[][] pdus = new byte[1][];
153767a662ecde33c3979bf02b793d392aca0403162Wink Saville            pdus[0] = sms.getPdu();
154767a662ecde33c3979bf02b793d392aca0403162Wink Saville
15531fd22923aaefc85652a5b5939c6d4aa6fa289e2jsh            if (smsHeader != null && smsHeader.portAddrs != null) {
15664c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink                if (smsHeader.portAddrs.destPort == SmsHeader.PORT_WAP_PUSH) {
15764c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink                    // GSM-style WAP indication
1583960ced4638fdb24ddf904fcb6734dae0959671ejsh                    return mWapPush.dispatchWapPdu(sms.getUserData());
1593960ced4638fdb24ddf904fcb6734dae0959671ejsh                } else {
1603960ced4638fdb24ddf904fcb6734dae0959671ejsh                    // The message was sent to a port, so concoct a URI for it.
1613960ced4638fdb24ddf904fcb6734dae0959671ejsh                    dispatchPortAddressedPdus(pdus, smsHeader.portAddrs.destPort);
162767a662ecde33c3979bf02b793d392aca0403162Wink Saville                }
163767a662ecde33c3979bf02b793d392aca0403162Wink Saville            } else {
16464c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink                // Normal short and non-port-addressed message, dispatch it.
165767a662ecde33c3979bf02b793d392aca0403162Wink Saville                dispatchPdus(pdus);
166767a662ecde33c3979bf02b793d392aca0403162Wink Saville            }
1673960ced4638fdb24ddf904fcb6734dae0959671ejsh            return Activity.RESULT_OK;
168767a662ecde33c3979bf02b793d392aca0403162Wink Saville        } else {
16964c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink            // Process the message part.
1703960ced4638fdb24ddf904fcb6734dae0959671ejsh            return processMessagePart(sms, smsHeader.concatRef, smsHeader.portAddrs);
171767a662ecde33c3979bf02b793d392aca0403162Wink Saville        }
172767a662ecde33c3979bf02b793d392aca0403162Wink Saville    }
173767a662ecde33c3979bf02b793d392aca0403162Wink Saville
174767a662ecde33c3979bf02b793d392aca0403162Wink Saville    /**
175767a662ecde33c3979bf02b793d392aca0403162Wink Saville     * Processes inbound messages that are in the WAP-WDP PDU format. See
176767a662ecde33c3979bf02b793d392aca0403162Wink Saville     * wap-259-wdp-20010614-a section 6.5 for details on the WAP-WDP PDU format.
177767a662ecde33c3979bf02b793d392aca0403162Wink Saville     * WDP segments are gathered until a datagram completes and gets dispatched.
178767a662ecde33c3979bf02b793d392aca0403162Wink Saville     *
179767a662ecde33c3979bf02b793d392aca0403162Wink Saville     * @param pdu The WAP-WDP PDU segment
1803960ced4638fdb24ddf904fcb6734dae0959671ejsh     * @return a result code from {@link Telephony.Sms.Intents}, or
1813960ced4638fdb24ddf904fcb6734dae0959671ejsh     *         {@link Activity#RESULT_OK} if the message has been broadcast
1823960ced4638fdb24ddf904fcb6734dae0959671ejsh     *         to applications
183767a662ecde33c3979bf02b793d392aca0403162Wink Saville     */
1843960ced4638fdb24ddf904fcb6734dae0959671ejsh    protected int processCdmaWapPdu(byte[] pdu, int referenceNumber, String address) {
185767a662ecde33c3979bf02b793d392aca0403162Wink Saville        int segment;
186767a662ecde33c3979bf02b793d392aca0403162Wink Saville        int totalSegments;
187767a662ecde33c3979bf02b793d392aca0403162Wink Saville        int index = 0;
188767a662ecde33c3979bf02b793d392aca0403162Wink Saville        int msgType;
189767a662ecde33c3979bf02b793d392aca0403162Wink Saville
1905c7d9e8194900a2b1699cd57f95b22ca5f7b9be2David Krause        int sourcePort = 0;
1915c7d9e8194900a2b1699cd57f95b22ca5f7b9be2David Krause        int destinationPort = 0;
192767a662ecde33c3979bf02b793d392aca0403162Wink Saville
193767a662ecde33c3979bf02b793d392aca0403162Wink Saville        msgType = pdu[index++];
194767a662ecde33c3979bf02b793d392aca0403162Wink Saville        if (msgType != 0){
195767a662ecde33c3979bf02b793d392aca0403162Wink Saville            Log.w(TAG, "Received a WAP SMS which is not WDP. Discard.");
1963960ced4638fdb24ddf904fcb6734dae0959671ejsh            return Intents.RESULT_SMS_HANDLED;
197767a662ecde33c3979bf02b793d392aca0403162Wink Saville        }
198767a662ecde33c3979bf02b793d392aca0403162Wink Saville        totalSegments = pdu[index++]; // >=1
199767a662ecde33c3979bf02b793d392aca0403162Wink Saville        segment = pdu[index++]; // >=0
200767a662ecde33c3979bf02b793d392aca0403162Wink Saville
2015c7d9e8194900a2b1699cd57f95b22ca5f7b9be2David Krause        // Only the first segment contains sourcePort and destination Port
2025c7d9e8194900a2b1699cd57f95b22ca5f7b9be2David Krause        if (segment == 0) {
2035c7d9e8194900a2b1699cd57f95b22ca5f7b9be2David Krause            //process WDP segment
2045c7d9e8194900a2b1699cd57f95b22ca5f7b9be2David Krause            sourcePort = (0xFF & pdu[index++]) << 8;
2055c7d9e8194900a2b1699cd57f95b22ca5f7b9be2David Krause            sourcePort |= 0xFF & pdu[index++];
2065c7d9e8194900a2b1699cd57f95b22ca5f7b9be2David Krause            destinationPort = (0xFF & pdu[index++]) << 8;
2075c7d9e8194900a2b1699cd57f95b22ca5f7b9be2David Krause            destinationPort |= 0xFF & pdu[index++];
2085c7d9e8194900a2b1699cd57f95b22ca5f7b9be2David Krause        }
209767a662ecde33c3979bf02b793d392aca0403162Wink Saville
210767a662ecde33c3979bf02b793d392aca0403162Wink Saville        // Lookup all other related parts
211767a662ecde33c3979bf02b793d392aca0403162Wink Saville        StringBuilder where = new StringBuilder("reference_number =");
212767a662ecde33c3979bf02b793d392aca0403162Wink Saville        where.append(referenceNumber);
213767a662ecde33c3979bf02b793d392aca0403162Wink Saville        where.append(" AND address = ?");
214767a662ecde33c3979bf02b793d392aca0403162Wink Saville        String[] whereArgs = new String[] {address};
215767a662ecde33c3979bf02b793d392aca0403162Wink Saville
216767a662ecde33c3979bf02b793d392aca0403162Wink Saville        Log.i(TAG, "Received WAP PDU. Type = " + msgType + ", originator = " + address
217767a662ecde33c3979bf02b793d392aca0403162Wink Saville                + ", src-port = " + sourcePort + ", dst-port = " + destinationPort
218767a662ecde33c3979bf02b793d392aca0403162Wink Saville                + ", ID = " + referenceNumber + ", segment# = " + segment + "/" + totalSegments);
219767a662ecde33c3979bf02b793d392aca0403162Wink Saville
220767a662ecde33c3979bf02b793d392aca0403162Wink Saville        byte[][] pdus = null;
221767a662ecde33c3979bf02b793d392aca0403162Wink Saville        Cursor cursor = null;
222767a662ecde33c3979bf02b793d392aca0403162Wink Saville        try {
223767a662ecde33c3979bf02b793d392aca0403162Wink Saville            cursor = mResolver.query(mRawUri, RAW_PROJECTION, where.toString(), whereArgs, null);
224767a662ecde33c3979bf02b793d392aca0403162Wink Saville            int cursorCount = cursor.getCount();
225767a662ecde33c3979bf02b793d392aca0403162Wink Saville            if (cursorCount != totalSegments - 1) {
226767a662ecde33c3979bf02b793d392aca0403162Wink Saville                // We don't have all the parts yet, store this one away
227767a662ecde33c3979bf02b793d392aca0403162Wink Saville                ContentValues values = new ContentValues();
228767a662ecde33c3979bf02b793d392aca0403162Wink Saville                values.put("date", new Long(0));
229767a662ecde33c3979bf02b793d392aca0403162Wink Saville                values.put("pdu", HexDump.toHexString(pdu, index, pdu.length - index));
230767a662ecde33c3979bf02b793d392aca0403162Wink Saville                values.put("address", address);
231767a662ecde33c3979bf02b793d392aca0403162Wink Saville                values.put("reference_number", referenceNumber);
232767a662ecde33c3979bf02b793d392aca0403162Wink Saville                values.put("count", totalSegments);
233767a662ecde33c3979bf02b793d392aca0403162Wink Saville                values.put("sequence", segment);
234767a662ecde33c3979bf02b793d392aca0403162Wink Saville                values.put("destination_port", destinationPort);
235767a662ecde33c3979bf02b793d392aca0403162Wink Saville
236767a662ecde33c3979bf02b793d392aca0403162Wink Saville                mResolver.insert(mRawUri, values);
237767a662ecde33c3979bf02b793d392aca0403162Wink Saville
2383960ced4638fdb24ddf904fcb6734dae0959671ejsh                return Intents.RESULT_SMS_HANDLED;
239767a662ecde33c3979bf02b793d392aca0403162Wink Saville            }
240767a662ecde33c3979bf02b793d392aca0403162Wink Saville
241767a662ecde33c3979bf02b793d392aca0403162Wink Saville            // All the parts are in place, deal with them
242767a662ecde33c3979bf02b793d392aca0403162Wink Saville            int pduColumn = cursor.getColumnIndex("pdu");
243767a662ecde33c3979bf02b793d392aca0403162Wink Saville            int sequenceColumn = cursor.getColumnIndex("sequence");
244767a662ecde33c3979bf02b793d392aca0403162Wink Saville
245767a662ecde33c3979bf02b793d392aca0403162Wink Saville            pdus = new byte[totalSegments][];
246767a662ecde33c3979bf02b793d392aca0403162Wink Saville            for (int i = 0; i < cursorCount; i++) {
247767a662ecde33c3979bf02b793d392aca0403162Wink Saville                cursor.moveToNext();
248767a662ecde33c3979bf02b793d392aca0403162Wink Saville                int cursorSequence = (int)cursor.getLong(sequenceColumn);
2495c7d9e8194900a2b1699cd57f95b22ca5f7b9be2David Krause                // Read the destination port from the first segment
2505c7d9e8194900a2b1699cd57f95b22ca5f7b9be2David Krause                if (cursorSequence == 0) {
2515c7d9e8194900a2b1699cd57f95b22ca5f7b9be2David Krause                    int destinationPortColumn = cursor.getColumnIndex("destination_port");
2525c7d9e8194900a2b1699cd57f95b22ca5f7b9be2David Krause                    destinationPort = (int)cursor.getLong(destinationPortColumn);
2535c7d9e8194900a2b1699cd57f95b22ca5f7b9be2David Krause                }
254767a662ecde33c3979bf02b793d392aca0403162Wink Saville                pdus[cursorSequence] = HexDump.hexStringToByteArray(
255767a662ecde33c3979bf02b793d392aca0403162Wink Saville                        cursor.getString(pduColumn));
256767a662ecde33c3979bf02b793d392aca0403162Wink Saville            }
257767a662ecde33c3979bf02b793d392aca0403162Wink Saville            // The last part will be added later
258767a662ecde33c3979bf02b793d392aca0403162Wink Saville
259767a662ecde33c3979bf02b793d392aca0403162Wink Saville            // Remove the parts from the database
260767a662ecde33c3979bf02b793d392aca0403162Wink Saville            mResolver.delete(mRawUri, where.toString(), whereArgs);
261767a662ecde33c3979bf02b793d392aca0403162Wink Saville        } catch (SQLException e) {
262767a662ecde33c3979bf02b793d392aca0403162Wink Saville            Log.e(TAG, "Can't access multipart SMS database", e);
2633960ced4638fdb24ddf904fcb6734dae0959671ejsh            return Intents.RESULT_SMS_GENERIC_ERROR;
264767a662ecde33c3979bf02b793d392aca0403162Wink Saville        } finally {
265767a662ecde33c3979bf02b793d392aca0403162Wink Saville            if (cursor != null) cursor.close();
266767a662ecde33c3979bf02b793d392aca0403162Wink Saville        }
267767a662ecde33c3979bf02b793d392aca0403162Wink Saville
268767a662ecde33c3979bf02b793d392aca0403162Wink Saville        // Build up the data stream
269767a662ecde33c3979bf02b793d392aca0403162Wink Saville        ByteArrayOutputStream output = new ByteArrayOutputStream();
270767a662ecde33c3979bf02b793d392aca0403162Wink Saville        for (int i = 0; i < totalSegments-1; i++) {
271767a662ecde33c3979bf02b793d392aca0403162Wink Saville            // reassemble the (WSP-)pdu
272767a662ecde33c3979bf02b793d392aca0403162Wink Saville            output.write(pdus[i], 0, pdus[i].length);
273767a662ecde33c3979bf02b793d392aca0403162Wink Saville        }
274767a662ecde33c3979bf02b793d392aca0403162Wink Saville
275767a662ecde33c3979bf02b793d392aca0403162Wink Saville        // This one isn't in the DB, so add it
276767a662ecde33c3979bf02b793d392aca0403162Wink Saville        output.write(pdu, index, pdu.length - index);
277767a662ecde33c3979bf02b793d392aca0403162Wink Saville
278767a662ecde33c3979bf02b793d392aca0403162Wink Saville        byte[] datagram = output.toByteArray();
279767a662ecde33c3979bf02b793d392aca0403162Wink Saville        // Dispatch the PDU to applications
280767a662ecde33c3979bf02b793d392aca0403162Wink Saville        switch (destinationPort) {
281767a662ecde33c3979bf02b793d392aca0403162Wink Saville        case SmsHeader.PORT_WAP_PUSH:
282767a662ecde33c3979bf02b793d392aca0403162Wink Saville            // Handle the PUSH
2833960ced4638fdb24ddf904fcb6734dae0959671ejsh            return mWapPush.dispatchWapPdu(datagram);
284767a662ecde33c3979bf02b793d392aca0403162Wink Saville
285767a662ecde33c3979bf02b793d392aca0403162Wink Saville        default:{
286767a662ecde33c3979bf02b793d392aca0403162Wink Saville            pdus = new byte[1][];
287767a662ecde33c3979bf02b793d392aca0403162Wink Saville            pdus[0] = datagram;
288767a662ecde33c3979bf02b793d392aca0403162Wink Saville            // The messages were sent to any other WAP port
289767a662ecde33c3979bf02b793d392aca0403162Wink Saville            dispatchPortAddressedPdus(pdus, destinationPort);
2903960ced4638fdb24ddf904fcb6734dae0959671ejsh            return Activity.RESULT_OK;
291767a662ecde33c3979bf02b793d392aca0403162Wink Saville        }
292767a662ecde33c3979bf02b793d392aca0403162Wink Saville        }
293767a662ecde33c3979bf02b793d392aca0403162Wink Saville    }
294767a662ecde33c3979bf02b793d392aca0403162Wink Saville
295767a662ecde33c3979bf02b793d392aca0403162Wink Saville    /** {@inheritDoc} */
2961f952a178db86559ff4bab79c4a9b5fae18096bfTammo Spalink    protected void sendData(String destAddr, String scAddr, int destPort,
2971f952a178db86559ff4bab79c4a9b5fae18096bfTammo Spalink            byte[] data, PendingIntent sentIntent, PendingIntent deliveryIntent) {
2981f952a178db86559ff4bab79c4a9b5fae18096bfTammo Spalink        SmsMessage.SubmitPdu pdu = SmsMessage.getSubmitPdu(
2991f952a178db86559ff4bab79c4a9b5fae18096bfTammo Spalink                scAddr, destAddr, destPort, data, (deliveryIntent != null));
3001f952a178db86559ff4bab79c4a9b5fae18096bfTammo Spalink        sendSubmitPdu(pdu, sentIntent, deliveryIntent);
3011f952a178db86559ff4bab79c4a9b5fae18096bfTammo Spalink    }
3021f952a178db86559ff4bab79c4a9b5fae18096bfTammo Spalink
3031f952a178db86559ff4bab79c4a9b5fae18096bfTammo Spalink    /** {@inheritDoc} */
3041f952a178db86559ff4bab79c4a9b5fae18096bfTammo Spalink    protected void sendText(String destAddr, String scAddr, String text,
3051f952a178db86559ff4bab79c4a9b5fae18096bfTammo Spalink            PendingIntent sentIntent, PendingIntent deliveryIntent) {
3061f952a178db86559ff4bab79c4a9b5fae18096bfTammo Spalink        SmsMessage.SubmitPdu pdu = SmsMessage.getSubmitPdu(
3071f952a178db86559ff4bab79c4a9b5fae18096bfTammo Spalink                scAddr, destAddr, text, (deliveryIntent != null), null);
3081f952a178db86559ff4bab79c4a9b5fae18096bfTammo Spalink        sendSubmitPdu(pdu, sentIntent, deliveryIntent);
3091f952a178db86559ff4bab79c4a9b5fae18096bfTammo Spalink    }
3101f952a178db86559ff4bab79c4a9b5fae18096bfTammo Spalink
3111f952a178db86559ff4bab79c4a9b5fae18096bfTammo Spalink    /** {@inheritDoc} */
31264c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink    protected void sendMultipartText(String destAddr, String scAddr,
313767a662ecde33c3979bf02b793d392aca0403162Wink Saville            ArrayList<String> parts, ArrayList<PendingIntent> sentIntents,
314767a662ecde33c3979bf02b793d392aca0403162Wink Saville            ArrayList<PendingIntent> deliveryIntents) {
315767a662ecde33c3979bf02b793d392aca0403162Wink Saville
31664c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink        /**
31764c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink         * TODO(cleanup): There is no real code difference between
31864c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink         * this and the GSM version, and hence it should be moved to
31964c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink         * the base class or consolidated somehow, provided calling
32064c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink         * the proper submitpdu stuff can be arranged.
32164c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink         */
322767a662ecde33c3979bf02b793d392aca0403162Wink Saville
32364c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink        int refNumber = getNextConcatenatedRef() & 0x00FF;
324767a662ecde33c3979bf02b793d392aca0403162Wink Saville
32564c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink        for (int i = 0, msgCount = parts.size(); i < msgCount; i++) {
32664c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink            SmsHeader.ConcatRef concatRef = new SmsHeader.ConcatRef();
32764c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink            concatRef.refNumber = refNumber;
32864c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink            concatRef.seqNumber = i + 1;  // 1-based sequence
32964c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink            concatRef.msgCount = msgCount;
33064c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink            concatRef.isEightBits = true;
33164c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink            SmsHeader smsHeader = new SmsHeader();
33264c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink            smsHeader.concatRef = concatRef;
333767a662ecde33c3979bf02b793d392aca0403162Wink Saville
33464c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink            PendingIntent sentIntent = null;
335767a662ecde33c3979bf02b793d392aca0403162Wink Saville            if (sentIntents != null && sentIntents.size() > i) {
336767a662ecde33c3979bf02b793d392aca0403162Wink Saville                sentIntent = sentIntents.get(i);
337767a662ecde33c3979bf02b793d392aca0403162Wink Saville            }
33864c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink
33964c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink            PendingIntent deliveryIntent = null;
340767a662ecde33c3979bf02b793d392aca0403162Wink Saville            if (deliveryIntents != null && deliveryIntents.size() > i) {
341767a662ecde33c3979bf02b793d392aca0403162Wink Saville                deliveryIntent = deliveryIntents.get(i);
342767a662ecde33c3979bf02b793d392aca0403162Wink Saville            }
343767a662ecde33c3979bf02b793d392aca0403162Wink Saville
344fc78f358cb1d1cee99758bcd6ef998a122ef27c9Tammo Spalink            UserData uData = new UserData();
345fc78f358cb1d1cee99758bcd6ef998a122ef27c9Tammo Spalink            uData.payloadStr = parts.get(i);
346fc78f358cb1d1cee99758bcd6ef998a122ef27c9Tammo Spalink            uData.userDataHeader = smsHeader;
347fc78f358cb1d1cee99758bcd6ef998a122ef27c9Tammo Spalink
348fc78f358cb1d1cee99758bcd6ef998a122ef27c9Tammo Spalink            SmsMessage.SubmitPdu submitPdu = SmsMessage.getSubmitPdu(destAddr,
349fc78f358cb1d1cee99758bcd6ef998a122ef27c9Tammo Spalink                    uData, deliveryIntent != null);
350767a662ecde33c3979bf02b793d392aca0403162Wink Saville
35164c499113a758cf80cddfd4d0183f944a1a6645aTammo Spalink            sendSubmitPdu(submitPdu, sentIntent, deliveryIntent);
352767a662ecde33c3979bf02b793d392aca0403162Wink Saville        }
353767a662ecde33c3979bf02b793d392aca0403162Wink Saville    }
354767a662ecde33c3979bf02b793d392aca0403162Wink Saville
3551f952a178db86559ff4bab79c4a9b5fae18096bfTammo Spalink    protected void sendSubmitPdu(SmsMessage.SubmitPdu pdu,
3561f952a178db86559ff4bab79c4a9b5fae18096bfTammo Spalink            PendingIntent sentIntent, PendingIntent deliveryIntent) {
3571f952a178db86559ff4bab79c4a9b5fae18096bfTammo Spalink        if (SystemProperties.getBoolean(TelephonyProperties.PROPERTY_INECM_MODE, false)) {
358a1c94ae4f75dab030219069864029f5bd9498fb0Richard Meng            if (sentIntent != null) {
359a1c94ae4f75dab030219069864029f5bd9498fb0Richard Meng                try {
360a1c94ae4f75dab030219069864029f5bd9498fb0Richard Meng                    sentIntent.send(SmsManager.RESULT_ERROR_NO_SERVICE);
361a1c94ae4f75dab030219069864029f5bd9498fb0Richard Meng                } catch (CanceledException ex) {}
362a1c94ae4f75dab030219069864029f5bd9498fb0Richard Meng            }
363a1c94ae4f75dab030219069864029f5bd9498fb0Richard Meng            if (Config.LOGD) {
364a1c94ae4f75dab030219069864029f5bd9498fb0Richard Meng                Log.d(TAG, "Block SMS in Emergency Callback mode");
365a1c94ae4f75dab030219069864029f5bd9498fb0Richard Meng            }
366a1c94ae4f75dab030219069864029f5bd9498fb0Richard Meng            return;
367a1c94ae4f75dab030219069864029f5bd9498fb0Richard Meng        }
3681f952a178db86559ff4bab79c4a9b5fae18096bfTammo Spalink        sendRawPdu(pdu.encodedScAddress, pdu.encodedMessage, sentIntent, deliveryIntent);
369a1c94ae4f75dab030219069864029f5bd9498fb0Richard Meng    }
370a1c94ae4f75dab030219069864029f5bd9498fb0Richard Meng
371767a662ecde33c3979bf02b793d392aca0403162Wink Saville    /** {@inheritDoc} */
372767a662ecde33c3979bf02b793d392aca0403162Wink Saville    protected void sendSms(SmsTracker tracker) {
373767a662ecde33c3979bf02b793d392aca0403162Wink Saville        HashMap map = tracker.mData;
374767a662ecde33c3979bf02b793d392aca0403162Wink Saville
375767a662ecde33c3979bf02b793d392aca0403162Wink Saville        byte smsc[] = (byte[]) map.get("smsc");
376767a662ecde33c3979bf02b793d392aca0403162Wink Saville        byte pdu[] = (byte[]) map.get("pdu");
377767a662ecde33c3979bf02b793d392aca0403162Wink Saville
378767a662ecde33c3979bf02b793d392aca0403162Wink Saville        Message reply = obtainMessage(EVENT_SEND_SMS_COMPLETE, tracker);
379767a662ecde33c3979bf02b793d392aca0403162Wink Saville
380767a662ecde33c3979bf02b793d392aca0403162Wink Saville        mCm.sendCdmaSms(pdu, reply);
381767a662ecde33c3979bf02b793d392aca0403162Wink Saville    }
382767a662ecde33c3979bf02b793d392aca0403162Wink Saville
383767a662ecde33c3979bf02b793d392aca0403162Wink Saville     /** {@inheritDoc} */
384767a662ecde33c3979bf02b793d392aca0403162Wink Saville    protected void sendMultipartSms (SmsTracker tracker) {
385767a662ecde33c3979bf02b793d392aca0403162Wink Saville        Log.d(TAG, "TODO: CdmaSMSDispatcher.sendMultipartSms not implemented");
386767a662ecde33c3979bf02b793d392aca0403162Wink Saville    }
387767a662ecde33c3979bf02b793d392aca0403162Wink Saville
388767a662ecde33c3979bf02b793d392aca0403162Wink Saville    /** {@inheritDoc} */
389867641ece36e2fd17faaea79cf19506ab17177c6jsh    protected void acknowledgeLastIncomingSms(boolean success, int result, Message response){
390767a662ecde33c3979bf02b793d392aca0403162Wink Saville        // FIXME unit test leaves cm == null. this should change
391117eace23924f575877ae8ecbb899af22e6f16c0Cheng Yang
392117eace23924f575877ae8ecbb899af22e6f16c0Cheng Yang        String inEcm=SystemProperties.get(TelephonyProperties.PROPERTY_INECM_MODE, "false");
393117eace23924f575877ae8ecbb899af22e6f16c0Cheng Yang        if (inEcm.equals("true")) {
394117eace23924f575877ae8ecbb899af22e6f16c0Cheng Yang            return;
395117eace23924f575877ae8ecbb899af22e6f16c0Cheng Yang        }
396117eace23924f575877ae8ecbb899af22e6f16c0Cheng Yang
397767a662ecde33c3979bf02b793d392aca0403162Wink Saville        if (mCm != null) {
398867641ece36e2fd17faaea79cf19506ab17177c6jsh            mCm.acknowledgeLastIncomingCdmaSms(success, resultToCause(result), response);
399767a662ecde33c3979bf02b793d392aca0403162Wink Saville        }
400767a662ecde33c3979bf02b793d392aca0403162Wink Saville    }
401767a662ecde33c3979bf02b793d392aca0403162Wink Saville
402767a662ecde33c3979bf02b793d392aca0403162Wink Saville    /** {@inheritDoc} */
403767a662ecde33c3979bf02b793d392aca0403162Wink Saville    protected void activateCellBroadcastSms(int activate, Message response) {
404e337d651a5199551ae3d3180176f8ac7d58c9acdjohnwang        mCm.setCdmaBroadcastActivation((activate == 0), response);
405767a662ecde33c3979bf02b793d392aca0403162Wink Saville    }
406767a662ecde33c3979bf02b793d392aca0403162Wink Saville
407767a662ecde33c3979bf02b793d392aca0403162Wink Saville    /** {@inheritDoc} */
408767a662ecde33c3979bf02b793d392aca0403162Wink Saville    protected void getCellBroadcastSmsConfig(Message response) {
409767a662ecde33c3979bf02b793d392aca0403162Wink Saville        mCm.getCdmaBroadcastConfig(response);
410767a662ecde33c3979bf02b793d392aca0403162Wink Saville    }
411767a662ecde33c3979bf02b793d392aca0403162Wink Saville
412767a662ecde33c3979bf02b793d392aca0403162Wink Saville    /** {@inheritDoc} */
413767a662ecde33c3979bf02b793d392aca0403162Wink Saville    protected void setCellBroadcastConfig(int[] configValuesArray, Message response) {
414767a662ecde33c3979bf02b793d392aca0403162Wink Saville        mCm.setCdmaBroadcastConfig(configValuesArray, response);
415767a662ecde33c3979bf02b793d392aca0403162Wink Saville    }
416767a662ecde33c3979bf02b793d392aca0403162Wink Saville
417867641ece36e2fd17faaea79cf19506ab17177c6jsh    private int resultToCause(int rc) {
418867641ece36e2fd17faaea79cf19506ab17177c6jsh        switch (rc) {
419867641ece36e2fd17faaea79cf19506ab17177c6jsh            case Activity.RESULT_OK:
420867641ece36e2fd17faaea79cf19506ab17177c6jsh            case Intents.RESULT_SMS_HANDLED:
421867641ece36e2fd17faaea79cf19506ab17177c6jsh                // Cause code is ignored on success.
422867641ece36e2fd17faaea79cf19506ab17177c6jsh                return 0;
423867641ece36e2fd17faaea79cf19506ab17177c6jsh            case Intents.RESULT_SMS_OUT_OF_MEMORY:
424867641ece36e2fd17faaea79cf19506ab17177c6jsh                return CommandsInterface.CDMA_SMS_FAIL_CAUSE_RESOURCE_SHORTAGE;
425867641ece36e2fd17faaea79cf19506ab17177c6jsh            case Intents.RESULT_SMS_GENERIC_ERROR:
426867641ece36e2fd17faaea79cf19506ab17177c6jsh            default:
427867641ece36e2fd17faaea79cf19506ab17177c6jsh                return CommandsInterface.CDMA_SMS_FAIL_CAUSE_OTHER_TERMINAL_PROBLEM;
428867641ece36e2fd17faaea79cf19506ab17177c6jsh        }
429867641ece36e2fd17faaea79cf19506ab17177c6jsh    }
430767a662ecde33c3979bf02b793d392aca0403162Wink Saville}
431