CdmaSMSDispatcher.java revision 767a662ecde33c3979bf02b793d392aca0403162
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
20767a662ecde33c3979bf02b793d392aca0403162Wink Savilleimport android.app.PendingIntent;
21767a662ecde33c3979bf02b793d392aca0403162Wink Savilleimport android.content.ContentValues;
22767a662ecde33c3979bf02b793d392aca0403162Wink Savilleimport android.database.Cursor;
23767a662ecde33c3979bf02b793d392aca0403162Wink Savilleimport android.database.SQLException;
24767a662ecde33c3979bf02b793d392aca0403162Wink Savilleimport android.os.AsyncResult;
25767a662ecde33c3979bf02b793d392aca0403162Wink Savilleimport android.os.Message;
26767a662ecde33c3979bf02b793d392aca0403162Wink Savilleimport android.util.Config;
27767a662ecde33c3979bf02b793d392aca0403162Wink Savilleimport android.util.Log;
28767a662ecde33c3979bf02b793d392aca0403162Wink Saville
29767a662ecde33c3979bf02b793d392aca0403162Wink Savilleimport com.android.internal.telephony.SmsHeader;
30767a662ecde33c3979bf02b793d392aca0403162Wink Savilleimport com.android.internal.telephony.SmsMessageBase;
31767a662ecde33c3979bf02b793d392aca0403162Wink Savilleimport com.android.internal.telephony.SMSDispatcher;
32767a662ecde33c3979bf02b793d392aca0403162Wink Saville//import com.android.internal.telephony.SMSDispatcher.SmsTracker;
33767a662ecde33c3979bf02b793d392aca0403162Wink Savilleimport com.android.internal.telephony.cdma.SmsMessage;
34767a662ecde33c3979bf02b793d392aca0403162Wink Savilleimport com.android.internal.telephony.cdma.sms.SmsEnvelope;
35767a662ecde33c3979bf02b793d392aca0403162Wink Savilleimport com.android.internal.util.HexDump;
36767a662ecde33c3979bf02b793d392aca0403162Wink Saville
37767a662ecde33c3979bf02b793d392aca0403162Wink Savilleimport java.io.ByteArrayOutputStream;
38767a662ecde33c3979bf02b793d392aca0403162Wink Savilleimport java.util.ArrayList;
39767a662ecde33c3979bf02b793d392aca0403162Wink Savilleimport java.util.HashMap;
40767a662ecde33c3979bf02b793d392aca0403162Wink Saville
41767a662ecde33c3979bf02b793d392aca0403162Wink Saville
42767a662ecde33c3979bf02b793d392aca0403162Wink Savillefinal class CdmaSMSDispatcher extends SMSDispatcher {
43767a662ecde33c3979bf02b793d392aca0403162Wink Saville    private static final String TAG = "CDMA";
44767a662ecde33c3979bf02b793d392aca0403162Wink Saville
45767a662ecde33c3979bf02b793d392aca0403162Wink Saville    CdmaSMSDispatcher(CDMAPhone phone) {
46767a662ecde33c3979bf02b793d392aca0403162Wink Saville        super(phone);
47767a662ecde33c3979bf02b793d392aca0403162Wink Saville    }
48767a662ecde33c3979bf02b793d392aca0403162Wink Saville
49767a662ecde33c3979bf02b793d392aca0403162Wink Saville    /**
50767a662ecde33c3979bf02b793d392aca0403162Wink Saville     * Called when a status report is received.  This should correspond to
51767a662ecde33c3979bf02b793d392aca0403162Wink Saville     * a previously successful SEND.
52767a662ecde33c3979bf02b793d392aca0403162Wink Saville     * Is a special GSM function, should never be called in CDMA!!
53767a662ecde33c3979bf02b793d392aca0403162Wink Saville     *
54767a662ecde33c3979bf02b793d392aca0403162Wink Saville     * @param ar AsyncResult passed into the message handler.  ar.result should
55767a662ecde33c3979bf02b793d392aca0403162Wink Saville     *           be a String representing the status report PDU, as ASCII hex.
56767a662ecde33c3979bf02b793d392aca0403162Wink Saville     */
57767a662ecde33c3979bf02b793d392aca0403162Wink Saville    protected void handleStatusReport(AsyncResult ar) {
58767a662ecde33c3979bf02b793d392aca0403162Wink Saville        Log.d(TAG, "handleStatusReport is a special GSM function, should never be called in CDMA!");
59767a662ecde33c3979bf02b793d392aca0403162Wink Saville    }
60767a662ecde33c3979bf02b793d392aca0403162Wink Saville
61767a662ecde33c3979bf02b793d392aca0403162Wink Saville    /**
62767a662ecde33c3979bf02b793d392aca0403162Wink Saville     * Dispatches an incoming SMS messages.
63767a662ecde33c3979bf02b793d392aca0403162Wink Saville     *
64767a662ecde33c3979bf02b793d392aca0403162Wink Saville     * @param smsb the incoming message from the phone
65767a662ecde33c3979bf02b793d392aca0403162Wink Saville     */
66767a662ecde33c3979bf02b793d392aca0403162Wink Saville    protected void dispatchMessage(SmsMessageBase smsb) {
67767a662ecde33c3979bf02b793d392aca0403162Wink Saville
68767a662ecde33c3979bf02b793d392aca0403162Wink Saville        // If sms is null, means there was a parsing error.
69767a662ecde33c3979bf02b793d392aca0403162Wink Saville        // TODO: Should NAK this.
70767a662ecde33c3979bf02b793d392aca0403162Wink Saville        if (smsb == null) {
71767a662ecde33c3979bf02b793d392aca0403162Wink Saville            return;
72767a662ecde33c3979bf02b793d392aca0403162Wink Saville        }
73767a662ecde33c3979bf02b793d392aca0403162Wink Saville        SmsMessage sms = (SmsMessage) smsb;
74767a662ecde33c3979bf02b793d392aca0403162Wink Saville        int teleService;
75767a662ecde33c3979bf02b793d392aca0403162Wink Saville        boolean handled = false;
76767a662ecde33c3979bf02b793d392aca0403162Wink Saville
77767a662ecde33c3979bf02b793d392aca0403162Wink Saville        // Decode BD stream and set sms variables.
78767a662ecde33c3979bf02b793d392aca0403162Wink Saville        sms.parseSms();
79767a662ecde33c3979bf02b793d392aca0403162Wink Saville        teleService = sms.getTeleService();
80767a662ecde33c3979bf02b793d392aca0403162Wink Saville
81767a662ecde33c3979bf02b793d392aca0403162Wink Saville        // Teleservices W(E)MT and VMN are handled together:
82767a662ecde33c3979bf02b793d392aca0403162Wink Saville        if ((SmsEnvelope.TELESERVICE_WMT == teleService)
83767a662ecde33c3979bf02b793d392aca0403162Wink Saville                ||(SmsEnvelope.TELESERVICE_WEMT == teleService)
84767a662ecde33c3979bf02b793d392aca0403162Wink Saville                ||(SmsEnvelope.TELESERVICE_VMN == teleService)){
85767a662ecde33c3979bf02b793d392aca0403162Wink Saville            // From here on we need decoded BD.
86767a662ecde33c3979bf02b793d392aca0403162Wink Saville            // Special case the message waiting indicator messages
87767a662ecde33c3979bf02b793d392aca0403162Wink Saville            if (sms.isMWISetMessage()) {
88767a662ecde33c3979bf02b793d392aca0403162Wink Saville                ((CDMAPhone) mPhone).updateMessageWaitingIndicator(true);
89767a662ecde33c3979bf02b793d392aca0403162Wink Saville
90767a662ecde33c3979bf02b793d392aca0403162Wink Saville                if (sms.isMwiDontStore()) {
91767a662ecde33c3979bf02b793d392aca0403162Wink Saville                    handled = true;
92767a662ecde33c3979bf02b793d392aca0403162Wink Saville                }
93767a662ecde33c3979bf02b793d392aca0403162Wink Saville
94767a662ecde33c3979bf02b793d392aca0403162Wink Saville                if (Config.LOGD) {
95767a662ecde33c3979bf02b793d392aca0403162Wink Saville                    Log.d(TAG,
96767a662ecde33c3979bf02b793d392aca0403162Wink Saville                            "Received voice mail indicator set SMS shouldStore=" + !handled);
97767a662ecde33c3979bf02b793d392aca0403162Wink Saville                }
98767a662ecde33c3979bf02b793d392aca0403162Wink Saville            } else if (sms.isMWIClearMessage()) {
99767a662ecde33c3979bf02b793d392aca0403162Wink Saville                ((CDMAPhone) mPhone).updateMessageWaitingIndicator(false);
100767a662ecde33c3979bf02b793d392aca0403162Wink Saville
101767a662ecde33c3979bf02b793d392aca0403162Wink Saville                if (sms.isMwiDontStore()) {
102767a662ecde33c3979bf02b793d392aca0403162Wink Saville                    handled = true;
103767a662ecde33c3979bf02b793d392aca0403162Wink Saville                }
104767a662ecde33c3979bf02b793d392aca0403162Wink Saville
105767a662ecde33c3979bf02b793d392aca0403162Wink Saville                if (Config.LOGD) {
106767a662ecde33c3979bf02b793d392aca0403162Wink Saville                    Log.d(TAG,
107767a662ecde33c3979bf02b793d392aca0403162Wink Saville                            "Received voice mail indicator clear SMS shouldStore=" + !handled);
108767a662ecde33c3979bf02b793d392aca0403162Wink Saville                }
109767a662ecde33c3979bf02b793d392aca0403162Wink Saville            }
110767a662ecde33c3979bf02b793d392aca0403162Wink Saville        }
111767a662ecde33c3979bf02b793d392aca0403162Wink Saville
112767a662ecde33c3979bf02b793d392aca0403162Wink Saville        if (null == sms.getUserData()){
113767a662ecde33c3979bf02b793d392aca0403162Wink Saville            handled = true;
114767a662ecde33c3979bf02b793d392aca0403162Wink Saville            if (Config.LOGD) {
115767a662ecde33c3979bf02b793d392aca0403162Wink Saville                Log.d(TAG, "Received SMS without user data");
116767a662ecde33c3979bf02b793d392aca0403162Wink Saville            }
117767a662ecde33c3979bf02b793d392aca0403162Wink Saville        }
118767a662ecde33c3979bf02b793d392aca0403162Wink Saville
119767a662ecde33c3979bf02b793d392aca0403162Wink Saville        if (handled) return;
120767a662ecde33c3979bf02b793d392aca0403162Wink Saville
121767a662ecde33c3979bf02b793d392aca0403162Wink Saville        if (SmsEnvelope.TELESERVICE_WAP == teleService){
122767a662ecde33c3979bf02b793d392aca0403162Wink Saville            processCdmaWapPdu(sms.getUserData(), sms.messageRef, sms.getOriginatingAddress());
123767a662ecde33c3979bf02b793d392aca0403162Wink Saville            return;
124767a662ecde33c3979bf02b793d392aca0403162Wink Saville        }
125767a662ecde33c3979bf02b793d392aca0403162Wink Saville
126767a662ecde33c3979bf02b793d392aca0403162Wink Saville        // Parse the headers to see if this is partial, or port addressed
127767a662ecde33c3979bf02b793d392aca0403162Wink Saville        int referenceNumber = -1;
128767a662ecde33c3979bf02b793d392aca0403162Wink Saville        int count = 0;
129767a662ecde33c3979bf02b793d392aca0403162Wink Saville        int sequence = 0;
130767a662ecde33c3979bf02b793d392aca0403162Wink Saville        int destPort = -1;
131767a662ecde33c3979bf02b793d392aca0403162Wink Saville        // From here on we need BD distributed to SMS member variables.
132767a662ecde33c3979bf02b793d392aca0403162Wink Saville
133767a662ecde33c3979bf02b793d392aca0403162Wink Saville        SmsHeader header = sms.getUserDataHeader();
134767a662ecde33c3979bf02b793d392aca0403162Wink Saville        if (header != null) {
135767a662ecde33c3979bf02b793d392aca0403162Wink Saville            for (SmsHeader.Element element : header.getElements()) {
136767a662ecde33c3979bf02b793d392aca0403162Wink Saville                try {
137767a662ecde33c3979bf02b793d392aca0403162Wink Saville                    switch (element.getID()) {
138767a662ecde33c3979bf02b793d392aca0403162Wink Saville                        case SmsHeader.CONCATENATED_8_BIT_REFERENCE: {
139767a662ecde33c3979bf02b793d392aca0403162Wink Saville                            byte[] data = element.getData();
140767a662ecde33c3979bf02b793d392aca0403162Wink Saville
141767a662ecde33c3979bf02b793d392aca0403162Wink Saville                            referenceNumber = data[0] & 0xff;
142767a662ecde33c3979bf02b793d392aca0403162Wink Saville                            count = data[1] & 0xff;
143767a662ecde33c3979bf02b793d392aca0403162Wink Saville                            sequence = data[2] & 0xff;
144767a662ecde33c3979bf02b793d392aca0403162Wink Saville
145767a662ecde33c3979bf02b793d392aca0403162Wink Saville                            // Per TS 23.040, 9.2.3.24.1: If the count is zero, sequence
146767a662ecde33c3979bf02b793d392aca0403162Wink Saville                            // is zero, or sequence > count, ignore the entire element
147767a662ecde33c3979bf02b793d392aca0403162Wink Saville                            if (count == 0 || sequence == 0 || sequence > count) {
148767a662ecde33c3979bf02b793d392aca0403162Wink Saville                                referenceNumber = -1;
149767a662ecde33c3979bf02b793d392aca0403162Wink Saville                            }
150767a662ecde33c3979bf02b793d392aca0403162Wink Saville                            break;
151767a662ecde33c3979bf02b793d392aca0403162Wink Saville                        }
152767a662ecde33c3979bf02b793d392aca0403162Wink Saville
153767a662ecde33c3979bf02b793d392aca0403162Wink Saville                        case SmsHeader.CONCATENATED_16_BIT_REFERENCE: {
154767a662ecde33c3979bf02b793d392aca0403162Wink Saville                            byte[] data = element.getData();
155767a662ecde33c3979bf02b793d392aca0403162Wink Saville
156767a662ecde33c3979bf02b793d392aca0403162Wink Saville                            referenceNumber = (data[0] & 0xff) * 256 + (data[1] & 0xff);
157767a662ecde33c3979bf02b793d392aca0403162Wink Saville                            count = data[2] & 0xff;
158767a662ecde33c3979bf02b793d392aca0403162Wink Saville                            sequence = data[3] & 0xff;
159767a662ecde33c3979bf02b793d392aca0403162Wink Saville
160767a662ecde33c3979bf02b793d392aca0403162Wink Saville                            // Per TS 23.040, 9.2.3.24.8: If the count is zero, sequence
161767a662ecde33c3979bf02b793d392aca0403162Wink Saville                            // is zero, or sequence > count, ignore the entire element
162767a662ecde33c3979bf02b793d392aca0403162Wink Saville                            if (count == 0 || sequence == 0 || sequence > count) {
163767a662ecde33c3979bf02b793d392aca0403162Wink Saville                                referenceNumber = -1;
164767a662ecde33c3979bf02b793d392aca0403162Wink Saville                            }
165767a662ecde33c3979bf02b793d392aca0403162Wink Saville                            break;
166767a662ecde33c3979bf02b793d392aca0403162Wink Saville                        }
167767a662ecde33c3979bf02b793d392aca0403162Wink Saville
168767a662ecde33c3979bf02b793d392aca0403162Wink Saville                        case SmsHeader.APPLICATION_PORT_ADDRESSING_16_BIT: {
169767a662ecde33c3979bf02b793d392aca0403162Wink Saville                            byte[] data = element.getData();
170767a662ecde33c3979bf02b793d392aca0403162Wink Saville
171767a662ecde33c3979bf02b793d392aca0403162Wink Saville                            destPort = (data[0] & 0xff) << 8;
172767a662ecde33c3979bf02b793d392aca0403162Wink Saville                            destPort |= (data[1] & 0xff);
173767a662ecde33c3979bf02b793d392aca0403162Wink Saville
174767a662ecde33c3979bf02b793d392aca0403162Wink Saville                            break;
175767a662ecde33c3979bf02b793d392aca0403162Wink Saville                        }
176767a662ecde33c3979bf02b793d392aca0403162Wink Saville                    }
177767a662ecde33c3979bf02b793d392aca0403162Wink Saville                } catch (ArrayIndexOutOfBoundsException e) {
178767a662ecde33c3979bf02b793d392aca0403162Wink Saville                    Log.e(TAG, "Bad element in header", e);
179767a662ecde33c3979bf02b793d392aca0403162Wink Saville                    return;  // TODO: NACK the message or something, don't just discard.
180767a662ecde33c3979bf02b793d392aca0403162Wink Saville                }
181767a662ecde33c3979bf02b793d392aca0403162Wink Saville            }
182767a662ecde33c3979bf02b793d392aca0403162Wink Saville        }
183767a662ecde33c3979bf02b793d392aca0403162Wink Saville
184767a662ecde33c3979bf02b793d392aca0403162Wink Saville        if (referenceNumber == -1) {
185767a662ecde33c3979bf02b793d392aca0403162Wink Saville            // notify everyone of the message if it isn't partial
186767a662ecde33c3979bf02b793d392aca0403162Wink Saville            byte[][] pdus = new byte[1][];
187767a662ecde33c3979bf02b793d392aca0403162Wink Saville            pdus[0] = sms.getPdu();
188767a662ecde33c3979bf02b793d392aca0403162Wink Saville
189767a662ecde33c3979bf02b793d392aca0403162Wink Saville            if (destPort != -1) {// GSM-style WAP indication
190767a662ecde33c3979bf02b793d392aca0403162Wink Saville                if (destPort == SmsHeader.PORT_WAP_PUSH) {
191767a662ecde33c3979bf02b793d392aca0403162Wink Saville                    mWapPush.dispatchWapPdu(sms.getUserData());
192767a662ecde33c3979bf02b793d392aca0403162Wink Saville                }
193767a662ecde33c3979bf02b793d392aca0403162Wink Saville                // The message was sent to a port, so concoct a URI for it
194767a662ecde33c3979bf02b793d392aca0403162Wink Saville                dispatchPortAddressedPdus(pdus, destPort);
195767a662ecde33c3979bf02b793d392aca0403162Wink Saville            } else {
196767a662ecde33c3979bf02b793d392aca0403162Wink Saville                // It's a normal message, dispatch it
197767a662ecde33c3979bf02b793d392aca0403162Wink Saville                dispatchPdus(pdus);
198767a662ecde33c3979bf02b793d392aca0403162Wink Saville            }
199767a662ecde33c3979bf02b793d392aca0403162Wink Saville        } else {
200767a662ecde33c3979bf02b793d392aca0403162Wink Saville            // Process the message part
201767a662ecde33c3979bf02b793d392aca0403162Wink Saville            processMessagePart(sms, referenceNumber, sequence, count, destPort);
202767a662ecde33c3979bf02b793d392aca0403162Wink Saville        }
203767a662ecde33c3979bf02b793d392aca0403162Wink Saville    }
204767a662ecde33c3979bf02b793d392aca0403162Wink Saville
205767a662ecde33c3979bf02b793d392aca0403162Wink Saville    /**
206767a662ecde33c3979bf02b793d392aca0403162Wink Saville     * Processes inbound messages that are in the WAP-WDP PDU format. See
207767a662ecde33c3979bf02b793d392aca0403162Wink Saville     * wap-259-wdp-20010614-a section 6.5 for details on the WAP-WDP PDU format.
208767a662ecde33c3979bf02b793d392aca0403162Wink Saville     * WDP segments are gathered until a datagram completes and gets dispatched.
209767a662ecde33c3979bf02b793d392aca0403162Wink Saville     *
210767a662ecde33c3979bf02b793d392aca0403162Wink Saville     * @param pdu The WAP-WDP PDU segment
211767a662ecde33c3979bf02b793d392aca0403162Wink Saville     */
212767a662ecde33c3979bf02b793d392aca0403162Wink Saville    protected void processCdmaWapPdu(byte[] pdu, int referenceNumber, String address) {
213767a662ecde33c3979bf02b793d392aca0403162Wink Saville        int segment;
214767a662ecde33c3979bf02b793d392aca0403162Wink Saville        int totalSegments;
215767a662ecde33c3979bf02b793d392aca0403162Wink Saville        int index = 0;
216767a662ecde33c3979bf02b793d392aca0403162Wink Saville        int msgType;
217767a662ecde33c3979bf02b793d392aca0403162Wink Saville
218767a662ecde33c3979bf02b793d392aca0403162Wink Saville        int sourcePort;
219767a662ecde33c3979bf02b793d392aca0403162Wink Saville        int destinationPort;
220767a662ecde33c3979bf02b793d392aca0403162Wink Saville
221767a662ecde33c3979bf02b793d392aca0403162Wink Saville        msgType = pdu[index++];
222767a662ecde33c3979bf02b793d392aca0403162Wink Saville        if (msgType != 0){
223767a662ecde33c3979bf02b793d392aca0403162Wink Saville            Log.w(TAG, "Received a WAP SMS which is not WDP. Discard.");
224767a662ecde33c3979bf02b793d392aca0403162Wink Saville            return;
225767a662ecde33c3979bf02b793d392aca0403162Wink Saville        }
226767a662ecde33c3979bf02b793d392aca0403162Wink Saville        totalSegments = pdu[index++]; // >=1
227767a662ecde33c3979bf02b793d392aca0403162Wink Saville        segment = pdu[index++]; // >=0
228767a662ecde33c3979bf02b793d392aca0403162Wink Saville
229767a662ecde33c3979bf02b793d392aca0403162Wink Saville        //process WDP segment
230767a662ecde33c3979bf02b793d392aca0403162Wink Saville        sourcePort = (0xFF & pdu[index++]) << 8;
231767a662ecde33c3979bf02b793d392aca0403162Wink Saville        sourcePort |= 0xFF & pdu[index++];
232767a662ecde33c3979bf02b793d392aca0403162Wink Saville        destinationPort = (0xFF & pdu[index++]) << 8;
233767a662ecde33c3979bf02b793d392aca0403162Wink Saville        destinationPort |= 0xFF & pdu[index++];
234767a662ecde33c3979bf02b793d392aca0403162Wink Saville
235767a662ecde33c3979bf02b793d392aca0403162Wink Saville        // Lookup all other related parts
236767a662ecde33c3979bf02b793d392aca0403162Wink Saville        StringBuilder where = new StringBuilder("reference_number =");
237767a662ecde33c3979bf02b793d392aca0403162Wink Saville        where.append(referenceNumber);
238767a662ecde33c3979bf02b793d392aca0403162Wink Saville        where.append(" AND address = ?");
239767a662ecde33c3979bf02b793d392aca0403162Wink Saville        String[] whereArgs = new String[] {address};
240767a662ecde33c3979bf02b793d392aca0403162Wink Saville
241767a662ecde33c3979bf02b793d392aca0403162Wink Saville        Log.i(TAG, "Received WAP PDU. Type = " + msgType + ", originator = " + address
242767a662ecde33c3979bf02b793d392aca0403162Wink Saville                + ", src-port = " + sourcePort + ", dst-port = " + destinationPort
243767a662ecde33c3979bf02b793d392aca0403162Wink Saville                + ", ID = " + referenceNumber + ", segment# = " + segment + "/" + totalSegments);
244767a662ecde33c3979bf02b793d392aca0403162Wink Saville
245767a662ecde33c3979bf02b793d392aca0403162Wink Saville        byte[][] pdus = null;
246767a662ecde33c3979bf02b793d392aca0403162Wink Saville        Cursor cursor = null;
247767a662ecde33c3979bf02b793d392aca0403162Wink Saville        try {
248767a662ecde33c3979bf02b793d392aca0403162Wink Saville            cursor = mResolver.query(mRawUri, RAW_PROJECTION, where.toString(), whereArgs, null);
249767a662ecde33c3979bf02b793d392aca0403162Wink Saville            int cursorCount = cursor.getCount();
250767a662ecde33c3979bf02b793d392aca0403162Wink Saville            if (cursorCount != totalSegments - 1) {
251767a662ecde33c3979bf02b793d392aca0403162Wink Saville                // We don't have all the parts yet, store this one away
252767a662ecde33c3979bf02b793d392aca0403162Wink Saville                ContentValues values = new ContentValues();
253767a662ecde33c3979bf02b793d392aca0403162Wink Saville                values.put("date", new Long(0));
254767a662ecde33c3979bf02b793d392aca0403162Wink Saville                values.put("pdu", HexDump.toHexString(pdu, index, pdu.length - index));
255767a662ecde33c3979bf02b793d392aca0403162Wink Saville                values.put("address", address);
256767a662ecde33c3979bf02b793d392aca0403162Wink Saville                values.put("reference_number", referenceNumber);
257767a662ecde33c3979bf02b793d392aca0403162Wink Saville                values.put("count", totalSegments);
258767a662ecde33c3979bf02b793d392aca0403162Wink Saville                values.put("sequence", segment);
259767a662ecde33c3979bf02b793d392aca0403162Wink Saville                values.put("destination_port", destinationPort);
260767a662ecde33c3979bf02b793d392aca0403162Wink Saville
261767a662ecde33c3979bf02b793d392aca0403162Wink Saville                mResolver.insert(mRawUri, values);
262767a662ecde33c3979bf02b793d392aca0403162Wink Saville
263767a662ecde33c3979bf02b793d392aca0403162Wink Saville                return;
264767a662ecde33c3979bf02b793d392aca0403162Wink Saville            }
265767a662ecde33c3979bf02b793d392aca0403162Wink Saville
266767a662ecde33c3979bf02b793d392aca0403162Wink Saville            // All the parts are in place, deal with them
267767a662ecde33c3979bf02b793d392aca0403162Wink Saville            int pduColumn = cursor.getColumnIndex("pdu");
268767a662ecde33c3979bf02b793d392aca0403162Wink Saville            int sequenceColumn = cursor.getColumnIndex("sequence");
269767a662ecde33c3979bf02b793d392aca0403162Wink Saville
270767a662ecde33c3979bf02b793d392aca0403162Wink Saville            pdus = new byte[totalSegments][];
271767a662ecde33c3979bf02b793d392aca0403162Wink Saville            for (int i = 0; i < cursorCount; i++) {
272767a662ecde33c3979bf02b793d392aca0403162Wink Saville                cursor.moveToNext();
273767a662ecde33c3979bf02b793d392aca0403162Wink Saville                int cursorSequence = (int)cursor.getLong(sequenceColumn);
274767a662ecde33c3979bf02b793d392aca0403162Wink Saville                pdus[cursorSequence] = HexDump.hexStringToByteArray(
275767a662ecde33c3979bf02b793d392aca0403162Wink Saville                        cursor.getString(pduColumn));
276767a662ecde33c3979bf02b793d392aca0403162Wink Saville            }
277767a662ecde33c3979bf02b793d392aca0403162Wink Saville            // The last part will be added later
278767a662ecde33c3979bf02b793d392aca0403162Wink Saville
279767a662ecde33c3979bf02b793d392aca0403162Wink Saville            // Remove the parts from the database
280767a662ecde33c3979bf02b793d392aca0403162Wink Saville            mResolver.delete(mRawUri, where.toString(), whereArgs);
281767a662ecde33c3979bf02b793d392aca0403162Wink Saville        } catch (SQLException e) {
282767a662ecde33c3979bf02b793d392aca0403162Wink Saville            Log.e(TAG, "Can't access multipart SMS database", e);
283767a662ecde33c3979bf02b793d392aca0403162Wink Saville            return;  // TODO: NACK the message or something, don't just discard.
284767a662ecde33c3979bf02b793d392aca0403162Wink Saville        } finally {
285767a662ecde33c3979bf02b793d392aca0403162Wink Saville            if (cursor != null) cursor.close();
286767a662ecde33c3979bf02b793d392aca0403162Wink Saville        }
287767a662ecde33c3979bf02b793d392aca0403162Wink Saville
288767a662ecde33c3979bf02b793d392aca0403162Wink Saville        // Build up the data stream
289767a662ecde33c3979bf02b793d392aca0403162Wink Saville        ByteArrayOutputStream output = new ByteArrayOutputStream();
290767a662ecde33c3979bf02b793d392aca0403162Wink Saville        for (int i = 0; i < totalSegments-1; i++) {
291767a662ecde33c3979bf02b793d392aca0403162Wink Saville            // reassemble the (WSP-)pdu
292767a662ecde33c3979bf02b793d392aca0403162Wink Saville            output.write(pdus[i], 0, pdus[i].length);
293767a662ecde33c3979bf02b793d392aca0403162Wink Saville        }
294767a662ecde33c3979bf02b793d392aca0403162Wink Saville
295767a662ecde33c3979bf02b793d392aca0403162Wink Saville        // This one isn't in the DB, so add it
296767a662ecde33c3979bf02b793d392aca0403162Wink Saville        output.write(pdu, index, pdu.length - index);
297767a662ecde33c3979bf02b793d392aca0403162Wink Saville
298767a662ecde33c3979bf02b793d392aca0403162Wink Saville        byte[] datagram = output.toByteArray();
299767a662ecde33c3979bf02b793d392aca0403162Wink Saville        // Dispatch the PDU to applications
300767a662ecde33c3979bf02b793d392aca0403162Wink Saville        switch (destinationPort) {
301767a662ecde33c3979bf02b793d392aca0403162Wink Saville        case SmsHeader.PORT_WAP_PUSH:
302767a662ecde33c3979bf02b793d392aca0403162Wink Saville            // Handle the PUSH
303767a662ecde33c3979bf02b793d392aca0403162Wink Saville            mWapPush.dispatchWapPdu(datagram);
304767a662ecde33c3979bf02b793d392aca0403162Wink Saville            break;
305767a662ecde33c3979bf02b793d392aca0403162Wink Saville
306767a662ecde33c3979bf02b793d392aca0403162Wink Saville        default:{
307767a662ecde33c3979bf02b793d392aca0403162Wink Saville            pdus = new byte[1][];
308767a662ecde33c3979bf02b793d392aca0403162Wink Saville            pdus[0] = datagram;
309767a662ecde33c3979bf02b793d392aca0403162Wink Saville            // The messages were sent to any other WAP port
310767a662ecde33c3979bf02b793d392aca0403162Wink Saville            dispatchPortAddressedPdus(pdus, destinationPort);
311767a662ecde33c3979bf02b793d392aca0403162Wink Saville            break;
312767a662ecde33c3979bf02b793d392aca0403162Wink Saville        }
313767a662ecde33c3979bf02b793d392aca0403162Wink Saville        }
314767a662ecde33c3979bf02b793d392aca0403162Wink Saville    }
315767a662ecde33c3979bf02b793d392aca0403162Wink Saville
316767a662ecde33c3979bf02b793d392aca0403162Wink Saville    /** {@inheritDoc} */
317767a662ecde33c3979bf02b793d392aca0403162Wink Saville    protected void sendMultipartText(String destinationAddress, String scAddress,
318767a662ecde33c3979bf02b793d392aca0403162Wink Saville            ArrayList<String> parts, ArrayList<PendingIntent> sentIntents,
319767a662ecde33c3979bf02b793d392aca0403162Wink Saville            ArrayList<PendingIntent> deliveryIntents) {
320767a662ecde33c3979bf02b793d392aca0403162Wink Saville
321767a662ecde33c3979bf02b793d392aca0403162Wink Saville        int ref = ++sConcatenatedRef & 0xff;
322767a662ecde33c3979bf02b793d392aca0403162Wink Saville
323767a662ecde33c3979bf02b793d392aca0403162Wink Saville        for (int i = 0, count = parts.size(); i < count; i++) {
324767a662ecde33c3979bf02b793d392aca0403162Wink Saville            // build SmsHeader data
325767a662ecde33c3979bf02b793d392aca0403162Wink Saville            byte[] data = new byte[5];
326767a662ecde33c3979bf02b793d392aca0403162Wink Saville            data[0] = (byte) SmsHeader.CONCATENATED_8_BIT_REFERENCE;
327767a662ecde33c3979bf02b793d392aca0403162Wink Saville            data[1] = (byte) 3;   // 3 bytes follow
328767a662ecde33c3979bf02b793d392aca0403162Wink Saville            data[2] = (byte) ref;   // reference #, unique per message
329767a662ecde33c3979bf02b793d392aca0403162Wink Saville            data[3] = (byte) count; // total part count
330767a662ecde33c3979bf02b793d392aca0403162Wink Saville            data[4] = (byte) (i + 1);  // 1-based sequence
331767a662ecde33c3979bf02b793d392aca0403162Wink Saville
332767a662ecde33c3979bf02b793d392aca0403162Wink Saville            PendingIntent sentIntent = null;
333767a662ecde33c3979bf02b793d392aca0403162Wink Saville            PendingIntent deliveryIntent = null;
334767a662ecde33c3979bf02b793d392aca0403162Wink Saville
335767a662ecde33c3979bf02b793d392aca0403162Wink Saville            if (sentIntents != null && sentIntents.size() > i) {
336767a662ecde33c3979bf02b793d392aca0403162Wink Saville                sentIntent = sentIntents.get(i);
337767a662ecde33c3979bf02b793d392aca0403162Wink Saville            }
338767a662ecde33c3979bf02b793d392aca0403162Wink Saville            if (deliveryIntents != null && deliveryIntents.size() > i) {
339767a662ecde33c3979bf02b793d392aca0403162Wink Saville                deliveryIntent = deliveryIntents.get(i);
340767a662ecde33c3979bf02b793d392aca0403162Wink Saville            }
341767a662ecde33c3979bf02b793d392aca0403162Wink Saville
342767a662ecde33c3979bf02b793d392aca0403162Wink Saville            SmsMessage.SubmitPdu pdus = SmsMessage.getSubmitPdu(scAddress, destinationAddress,
343767a662ecde33c3979bf02b793d392aca0403162Wink Saville                    parts.get(i), deliveryIntent != null, data);
344767a662ecde33c3979bf02b793d392aca0403162Wink Saville
345767a662ecde33c3979bf02b793d392aca0403162Wink Saville            sendRawPdu(pdus.encodedScAddress, pdus.encodedMessage, sentIntent, deliveryIntent);
346767a662ecde33c3979bf02b793d392aca0403162Wink Saville        }
347767a662ecde33c3979bf02b793d392aca0403162Wink Saville    }
348767a662ecde33c3979bf02b793d392aca0403162Wink Saville
349767a662ecde33c3979bf02b793d392aca0403162Wink Saville    protected void sendRawPdu(byte[] smsc, byte[] pdu, PendingIntent sentIntent,
350767a662ecde33c3979bf02b793d392aca0403162Wink Saville            PendingIntent deliveryIntent) {
351767a662ecde33c3979bf02b793d392aca0403162Wink Saville        super.sendRawPdu(smsc, pdu, sentIntent, deliveryIntent);
352767a662ecde33c3979bf02b793d392aca0403162Wink Saville    }
353767a662ecde33c3979bf02b793d392aca0403162Wink Saville
354767a662ecde33c3979bf02b793d392aca0403162Wink Saville    /** {@inheritDoc} */
355767a662ecde33c3979bf02b793d392aca0403162Wink Saville    protected void sendSms(SmsTracker tracker) {
356767a662ecde33c3979bf02b793d392aca0403162Wink Saville        HashMap map = tracker.mData;
357767a662ecde33c3979bf02b793d392aca0403162Wink Saville
358767a662ecde33c3979bf02b793d392aca0403162Wink Saville        byte smsc[] = (byte[]) map.get("smsc");
359767a662ecde33c3979bf02b793d392aca0403162Wink Saville        byte pdu[] = (byte[]) map.get("pdu");
360767a662ecde33c3979bf02b793d392aca0403162Wink Saville
361767a662ecde33c3979bf02b793d392aca0403162Wink Saville        Message reply = obtainMessage(EVENT_SEND_SMS_COMPLETE, tracker);
362767a662ecde33c3979bf02b793d392aca0403162Wink Saville
363767a662ecde33c3979bf02b793d392aca0403162Wink Saville        mCm.sendCdmaSms(pdu, reply);
364767a662ecde33c3979bf02b793d392aca0403162Wink Saville    }
365767a662ecde33c3979bf02b793d392aca0403162Wink Saville
366767a662ecde33c3979bf02b793d392aca0403162Wink Saville     /** {@inheritDoc} */
367767a662ecde33c3979bf02b793d392aca0403162Wink Saville    protected void sendMultipartSms (SmsTracker tracker) {
368767a662ecde33c3979bf02b793d392aca0403162Wink Saville        Log.d(TAG, "TODO: CdmaSMSDispatcher.sendMultipartSms not implemented");
369767a662ecde33c3979bf02b793d392aca0403162Wink Saville    }
370767a662ecde33c3979bf02b793d392aca0403162Wink Saville
371767a662ecde33c3979bf02b793d392aca0403162Wink Saville    /** {@inheritDoc} */
372767a662ecde33c3979bf02b793d392aca0403162Wink Saville    protected void acknowledgeLastIncomingSms(boolean success, Message response){
373767a662ecde33c3979bf02b793d392aca0403162Wink Saville        // FIXME unit test leaves cm == null. this should change
374767a662ecde33c3979bf02b793d392aca0403162Wink Saville        if (mCm != null) {
375767a662ecde33c3979bf02b793d392aca0403162Wink Saville            mCm.acknowledgeLastIncomingCdmaSms(success, response);
376767a662ecde33c3979bf02b793d392aca0403162Wink Saville        }
377767a662ecde33c3979bf02b793d392aca0403162Wink Saville    }
378767a662ecde33c3979bf02b793d392aca0403162Wink Saville
379767a662ecde33c3979bf02b793d392aca0403162Wink Saville    /** {@inheritDoc} */
380767a662ecde33c3979bf02b793d392aca0403162Wink Saville    protected void activateCellBroadcastSms(int activate, Message response) {
381767a662ecde33c3979bf02b793d392aca0403162Wink Saville        mCm.activateCdmaBroadcastSms(activate, response);
382767a662ecde33c3979bf02b793d392aca0403162Wink Saville    }
383767a662ecde33c3979bf02b793d392aca0403162Wink Saville
384767a662ecde33c3979bf02b793d392aca0403162Wink Saville    /** {@inheritDoc} */
385767a662ecde33c3979bf02b793d392aca0403162Wink Saville    protected void getCellBroadcastSmsConfig(Message response) {
386767a662ecde33c3979bf02b793d392aca0403162Wink Saville        mCm.getCdmaBroadcastConfig(response);
387767a662ecde33c3979bf02b793d392aca0403162Wink Saville    }
388767a662ecde33c3979bf02b793d392aca0403162Wink Saville
389767a662ecde33c3979bf02b793d392aca0403162Wink Saville    /** {@inheritDoc} */
390767a662ecde33c3979bf02b793d392aca0403162Wink Saville    protected void setCellBroadcastConfig(int[] configValuesArray, Message response) {
391767a662ecde33c3979bf02b793d392aca0403162Wink Saville        mCm.setCdmaBroadcastConfig(configValuesArray, response);
392767a662ecde33c3979bf02b793d392aca0403162Wink Saville    }
393767a662ecde33c3979bf02b793d392aca0403162Wink Saville
394767a662ecde33c3979bf02b793d392aca0403162Wink Saville}
395