GsmSMSDispatcher.java revision 4bd1dec4138ac11a91a8ec606a27fc4c5c63f14b
1c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville/*
2c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * Copyright (C) 2006 The Android Open Source Project
3c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville *
4c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * Licensed under the Apache License, Version 2.0 (the "License");
5c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * you may not use this file except in compliance with the License.
6c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * You may obtain a copy of the License at
7c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville *
8c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville *      http://www.apache.org/licenses/LICENSE-2.0
9c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville *
10c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * Unless required by applicable law or agreed to in writing, software
11c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * distributed under the License is distributed on an "AS IS" BASIS,
12c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * See the License for the specific language governing permissions and
14c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * limitations under the License.
15c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville */
16c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
17c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savillepackage com.android.internal.telephony.gsm;
18c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
19c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleimport android.app.Activity;
208d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wangimport android.app.AppOpsManager;
21c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleimport android.app.PendingIntent;
22c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleimport android.app.PendingIntent.CanceledException;
238d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wangimport android.content.BroadcastReceiver;
24c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleimport android.content.Intent;
25c99dab56e20222b28cbc6238645feac938f1c333Ye Wenimport android.net.Uri;
26c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleimport android.os.AsyncResult;
27c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleimport android.os.Message;
28c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleimport android.provider.Telephony.Sms;
29c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleimport android.provider.Telephony.Sms.Intents;
30ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Savilleimport android.telephony.Rlog;
31a0c22039b77054d659151537896c1db90c7057f7Shishir Agrawalimport android.telephony.ServiceState;
32c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
33c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleimport com.android.internal.telephony.GsmAlphabet;
34ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowaimport com.android.internal.telephony.ImsSMSDispatcher;
35ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowaimport com.android.internal.telephony.InboundSmsHandler;
36c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleimport com.android.internal.telephony.PhoneBase;
37c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleimport com.android.internal.telephony.SMSDispatcher;
380d4bcdf379842af4b6304809156971e926f374f0Jake Hambyimport com.android.internal.telephony.SmsConstants;
39c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleimport com.android.internal.telephony.SmsHeader;
40c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleimport com.android.internal.telephony.SmsUsageMonitor;
411260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowaimport com.android.internal.telephony.uicc.IccRecords;
42d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenkaimport com.android.internal.telephony.uicc.IccUtils;
431260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowaimport com.android.internal.telephony.uicc.UiccCardApplication;
441260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowaimport com.android.internal.telephony.uicc.UiccController;
45c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
46c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleimport java.util.HashMap;
47c99dab56e20222b28cbc6238645feac938f1c333Ye Wenimport java.util.concurrent.atomic.AtomicBoolean;
48c99dab56e20222b28cbc6238645feac938f1c333Ye Wenimport java.util.concurrent.atomic.AtomicInteger;
491260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowaimport java.util.concurrent.atomic.AtomicReference;
50c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
51c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savillepublic final class GsmSMSDispatcher extends SMSDispatcher {
52cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville    private static final String TAG = "GsmSMSDispatcher";
531260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa    private static final boolean VDBG = false;
541260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa    protected UiccController mUiccController = null;
551260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa    private AtomicReference<IccRecords> mIccRecords = new AtomicReference<IccRecords>();
561260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa    private AtomicReference<UiccCardApplication> mUiccApplication =
571260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa            new AtomicReference<UiccCardApplication>();
581260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa    private GsmInboundSmsHandler mGsmInboundSmsHandler;
59c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
60c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /** Status report received */
61c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private static final int EVENT_NEW_SMS_STATUS_REPORT = 100;
62c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
63ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa    public GsmSMSDispatcher(PhoneBase phone, SmsUsageMonitor usageMonitor,
64ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa            ImsSMSDispatcher imsSMSDispatcher,
651260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa            GsmInboundSmsHandler gsmInboundSmsHandler) {
66ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa        super(phone, usageMonitor, imsSMSDispatcher);
6722d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        mCi.setOnSmsStatus(this, EVENT_NEW_SMS_STATUS_REPORT, null);
681260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa        mGsmInboundSmsHandler = gsmInboundSmsHandler;
69ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa        mUiccController = UiccController.getInstance();
70ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa        mUiccController.registerForIccChanged(this, EVENT_ICC_CHANGED, null);
711260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa        Rlog.d(TAG, "GsmSMSDispatcher created");
72c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
73c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
74c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    @Override
75c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    public void dispose() {
760d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        super.dispose();
7722d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        mCi.unSetOnSmsStatus(this);
78ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa        mUiccController.unregisterForIccChanged(this);
79c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
80c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
81c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    @Override
82c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    protected String getFormat() {
83c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        return SmsConstants.FORMAT_3GPP;
84c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
85c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
86c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /**
87c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * Handles 3GPP format-specific events coming from the phone stack.
88c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * Other events are handled by {@link SMSDispatcher#handleMessage}.
89c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *
90c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * @param msg the message to handle
91c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     */
92c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    @Override
93c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    public void handleMessage(Message msg) {
94c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        switch (msg.what) {
95c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        case EVENT_NEW_SMS_STATUS_REPORT:
96c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            handleStatusReport((AsyncResult) msg.obj);
97c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            break;
98c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
991260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa        case EVENT_NEW_ICC_SMS:
1001260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa        // pass to InboundSmsHandler to process
1011260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa        mGsmInboundSmsHandler.sendMessage(InboundSmsHandler.EVENT_NEW_SMS, msg.obj);
1021260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa        break;
1031260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa
1041260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa        case EVENT_ICC_CHANGED:
1051260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa            onUpdateIccAvailability();
1061260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa            break;
1071260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa
108c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        default:
109c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            super.handleMessage(msg);
110c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
111c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
112c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
113c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /**
114c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * Called when a status report is received.  This should correspond to
115c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * a previously successful SEND.
116c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *
117c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * @param ar AsyncResult passed into the message handler.  ar.result should
118c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *           be a String representing the status report PDU, as ASCII hex.
119c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     */
120c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private void handleStatusReport(AsyncResult ar) {
121c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        String pduString = (String) ar.result;
122c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        SmsMessage sms = SmsMessage.newFromCDS(pduString);
123c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
124c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (sms != null) {
125c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            int tpStatus = sms.getStatus();
12622d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            int messageRef = sms.mMessageRef;
127c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            for (int i = 0, count = deliveryPendingList.size(); i < count; i++) {
128c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                SmsTracker tracker = deliveryPendingList.get(i);
129c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                if (tracker.mMessageRef == messageRef) {
130c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    // Found it.  Remove from list and broadcast.
131c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    if(tpStatus >= Sms.STATUS_FAILED || tpStatus < Sms.STATUS_PENDING ) {
132c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                       deliveryPendingList.remove(i);
1330217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braun                       // Update the message status (COMPLETE or FAILED)
1340217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braun                       tracker.updateSentMessageStatus(mContext, tpStatus);
135c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    }
136c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    PendingIntent intent = tracker.mDeliveryIntent;
137c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    Intent fillIn = new Intent();
138c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    fillIn.putExtra("pdu", IccUtils.hexStringToBytes(pduString));
1391260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa                    fillIn.putExtra("format", getFormat());
140c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    try {
141c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        intent.send(mContext, Activity.RESULT_OK, fillIn);
142c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    } catch (CanceledException ex) {}
143c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
144c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    // Only expect to see one tracker matching this messageref
145c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    break;
146c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                }
147c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            }
148c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
1490d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        mCi.acknowledgeLastIncomingGsmSms(true, Intents.RESULT_SMS_HANDLED, null);
150c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
151c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
152c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /** {@inheritDoc} */
153c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    @Override
154c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    protected void sendData(String destAddr, String scAddr, int destPort,
155c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            byte[] data, PendingIntent sentIntent, PendingIntent deliveryIntent) {
156c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        SmsMessage.SubmitPdu pdu = SmsMessage.getSubmitPdu(
157c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                scAddr, destAddr, destPort, data, (deliveryIntent != null));
158c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (pdu != null) {
159ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa            HashMap map = getSmsTrackerMap(destAddr, scAddr, destPort, data, pdu);
160c99dab56e20222b28cbc6238645feac938f1c333Ye Wen            SmsTracker tracker = getSmsTracker(map, sentIntent, deliveryIntent, getFormat(),
1614bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen                    null /*messageUri*/, false /*isExpectMore*/, null /*fullMessageText*/);
1621260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa            sendRawPdu(tracker);
163c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else {
164ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville            Rlog.e(TAG, "GsmSMSDispatcher.sendData(): getSubmitPdu() returned null");
165c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
166c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
167c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
168c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /** {@inheritDoc} */
169c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    @Override
170b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen    protected void sendText(String destAddr, String scAddr, String text, PendingIntent sentIntent,
171b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen            PendingIntent deliveryIntent, Uri messageUri, String callingPkg) {
172c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        SmsMessage.SubmitPdu pdu = SmsMessage.getSubmitPdu(
173c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                scAddr, destAddr, text, (deliveryIntent != null));
174c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (pdu != null) {
175ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa            HashMap map = getSmsTrackerMap(destAddr, scAddr, text, pdu);
176c99dab56e20222b28cbc6238645feac938f1c333Ye Wen            SmsTracker tracker = getSmsTracker(map, sentIntent, deliveryIntent, getFormat(),
1774bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen                    messageUri, false /*isExpectMore*/, text /*fullMessageText*/);
1781260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa            sendRawPdu(tracker);
179c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else {
180ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville            Rlog.e(TAG, "GsmSMSDispatcher.sendText(): getSubmitPdu() returned null");
181c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
182c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
183c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
184c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /** {@inheritDoc} */
185c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    @Override
18663418bbd2a9d7cc88ae24cc5ae776c01d688fc3aAnil Muthineni    protected void injectSmsPdu(byte[] pdu, String format, PendingIntent receivedIntent) {
18763418bbd2a9d7cc88ae24cc5ae776c01d688fc3aAnil Muthineni        throw new IllegalStateException("This method must be called only on ImsSMSDispatcher");
18863418bbd2a9d7cc88ae24cc5ae776c01d688fc3aAnil Muthineni    }
18963418bbd2a9d7cc88ae24cc5ae776c01d688fc3aAnil Muthineni
19063418bbd2a9d7cc88ae24cc5ae776c01d688fc3aAnil Muthineni    /** {@inheritDoc} */
19163418bbd2a9d7cc88ae24cc5ae776c01d688fc3aAnil Muthineni    @Override
192c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    protected GsmAlphabet.TextEncodingDetails calculateLength(CharSequence messageBody,
193c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            boolean use7bitOnly) {
194c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        return SmsMessage.calculateLength(messageBody, use7bitOnly);
195c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
196c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
197c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /** {@inheritDoc} */
198c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    @Override
199c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    protected void sendNewSubmitPdu(String destinationAddress, String scAddress,
200c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            String message, SmsHeader smsHeader, int encoding,
201c99dab56e20222b28cbc6238645feac938f1c333Ye Wen            PendingIntent sentIntent, PendingIntent deliveryIntent, boolean lastPart,
2024bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen            AtomicInteger unsentPartCount, AtomicBoolean anyPartFailed, Uri messageUri,
2034bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen            String fullMessageText) {
204c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        SmsMessage.SubmitPdu pdu = SmsMessage.getSubmitPdu(scAddress, destinationAddress,
205c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                message, deliveryIntent != null, SmsHeader.toByteArray(smsHeader),
206c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                encoding, smsHeader.languageTable, smsHeader.languageShiftTable);
207c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (pdu != null) {
208ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa            HashMap map =  getSmsTrackerMap(destinationAddress, scAddress,
2091260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa                    message, pdu);
210ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa            SmsTracker tracker = getSmsTracker(map, sentIntent,
21178d39a9fab86a26f4f39585af5cfe2a07c756fceShishir Agrawal                    deliveryIntent, getFormat(), unsentPartCount, anyPartFailed, messageUri,
2124bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen                    smsHeader, !lastPart, fullMessageText);
2131260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa            sendRawPdu(tracker);
214c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else {
215ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville            Rlog.e(TAG, "GsmSMSDispatcher.sendNewSubmitPdu(): getSubmitPdu() returned null");
216c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
217c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
218c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
219c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /** {@inheritDoc} */
220c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    @Override
221c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    protected void sendSms(SmsTracker tracker) {
222c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        HashMap<String, Object> map = tracker.mData;
223c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
224c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        byte pdu[] = (byte[]) map.get("pdu");
225c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
226454c5783e7695feec276325920550b2d4dcc3e16Rika Brooks        if (tracker.mRetryCount > 0) {
227454c5783e7695feec276325920550b2d4dcc3e16Rika Brooks            Rlog.d(TAG, "sendSms: "
228454c5783e7695feec276325920550b2d4dcc3e16Rika Brooks                    + " mRetryCount=" + tracker.mRetryCount
229454c5783e7695feec276325920550b2d4dcc3e16Rika Brooks                    + " mMessageRef=" + tracker.mMessageRef
230454c5783e7695feec276325920550b2d4dcc3e16Rika Brooks                    + " SS=" + mPhone.getServiceState().getState());
231454c5783e7695feec276325920550b2d4dcc3e16Rika Brooks
232454c5783e7695feec276325920550b2d4dcc3e16Rika Brooks            // per TS 23.040 Section 9.2.3.6:  If TP-MTI SMS-SUBMIT (0x01) type
233454c5783e7695feec276325920550b2d4dcc3e16Rika Brooks            //   TP-RD (bit 2) is 1 for retry
234454c5783e7695feec276325920550b2d4dcc3e16Rika Brooks            //   and TP-MR is set to previously failed sms TP-MR
235454c5783e7695feec276325920550b2d4dcc3e16Rika Brooks            if (((0x01 & pdu[0]) == 0x01)) {
236454c5783e7695feec276325920550b2d4dcc3e16Rika Brooks                pdu[0] |= 0x04; // TP-RD
237454c5783e7695feec276325920550b2d4dcc3e16Rika Brooks                pdu[1] = (byte) tracker.mMessageRef; // TP-MR
238454c5783e7695feec276325920550b2d4dcc3e16Rika Brooks            }
239454c5783e7695feec276325920550b2d4dcc3e16Rika Brooks        }
2401260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa        Rlog.d(TAG, "sendSms: "
2418d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang                + " isIms()=" + isIms()
2428d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang                + " mRetryCount=" + tracker.mRetryCount
2438d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang                + " mImsRetry=" + tracker.mImsRetry
2448d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang                + " mMessageRef=" + tracker.mMessageRef
2458d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang                + " SS=" + mPhone.getServiceState().getState());
2468d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang
2478d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang        // Send SMS via the carrier app.
2488d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang        BroadcastReceiver resultReceiver = new SMSDispatcherReceiver(tracker);
2498d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang
2508d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang        Intent intent = new Intent(Intents.SMS_SEND_ACTION);
251a0c22039b77054d659151537896c1db90c7057f7Shishir Agrawal        String carrierPackage = getCarrierAppPackageName(intent);
252a0c22039b77054d659151537896c1db90c7057f7Shishir Agrawal        if (carrierPackage != null) {
253a0c22039b77054d659151537896c1db90c7057f7Shishir Agrawal            intent.setPackage(carrierPackage);
254a0c22039b77054d659151537896c1db90c7057f7Shishir Agrawal            intent.putExtra("pdu", pdu);
255a0c22039b77054d659151537896c1db90c7057f7Shishir Agrawal            intent.putExtra("smsc", (byte[]) map.get("smsc"));
256a0c22039b77054d659151537896c1db90c7057f7Shishir Agrawal            intent.putExtra("format", getFormat());
25778d39a9fab86a26f4f39585af5cfe2a07c756fceShishir Agrawal            if (tracker.mSmsHeader != null && tracker.mSmsHeader.concatRef != null) {
25878d39a9fab86a26f4f39585af5cfe2a07c756fceShishir Agrawal                SmsHeader.ConcatRef concatRef = tracker.mSmsHeader.concatRef;
25978d39a9fab86a26f4f39585af5cfe2a07c756fceShishir Agrawal                intent.putExtra("concat.refNumber", concatRef.refNumber);
26078d39a9fab86a26f4f39585af5cfe2a07c756fceShishir Agrawal                intent.putExtra("concat.seqNumber", concatRef.seqNumber);
26178d39a9fab86a26f4f39585af5cfe2a07c756fceShishir Agrawal                intent.putExtra("concat.msgCount", concatRef.msgCount);
26278d39a9fab86a26f4f39585af5cfe2a07c756fceShishir Agrawal            }
263a0c22039b77054d659151537896c1db90c7057f7Shishir Agrawal            intent.addFlags(Intent.FLAG_RECEIVER_NO_ABORT);
264a0c22039b77054d659151537896c1db90c7057f7Shishir Agrawal            Rlog.d(TAG, "Sending SMS by carrier app.");
265a0c22039b77054d659151537896c1db90c7057f7Shishir Agrawal            mContext.sendOrderedBroadcast(intent, android.Manifest.permission.RECEIVE_SMS,
266a0c22039b77054d659151537896c1db90c7057f7Shishir Agrawal                                          AppOpsManager.OP_RECEIVE_SMS, resultReceiver,
267a0c22039b77054d659151537896c1db90c7057f7Shishir Agrawal                                          null, Activity.RESULT_CANCELED, null, null);
268a0c22039b77054d659151537896c1db90c7057f7Shishir Agrawal        } else {
269a0c22039b77054d659151537896c1db90c7057f7Shishir Agrawal            sendSmsByPstn(tracker);
270a0c22039b77054d659151537896c1db90c7057f7Shishir Agrawal        }
2718d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang    }
2728d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang
2738d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang    /** {@inheritDoc} */
2748d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang    @Override
2758d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang    protected void sendSmsByPstn(SmsTracker tracker) {
276a0c22039b77054d659151537896c1db90c7057f7Shishir Agrawal        int ss = mPhone.getServiceState().getState();
277a0c22039b77054d659151537896c1db90c7057f7Shishir Agrawal        // if sms over IMS is not supported on data and voice is not available...
278a0c22039b77054d659151537896c1db90c7057f7Shishir Agrawal        if (!isIms() && ss != ServiceState.STATE_IN_SERVICE) {
279a0c22039b77054d659151537896c1db90c7057f7Shishir Agrawal            tracker.onFailed(mContext, getNotInServiceError(ss), 0/*errorCode*/);
280a0c22039b77054d659151537896c1db90c7057f7Shishir Agrawal            return;
281a0c22039b77054d659151537896c1db90c7057f7Shishir Agrawal        }
282a0c22039b77054d659151537896c1db90c7057f7Shishir Agrawal
2838d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang        HashMap<String, Object> map = tracker.mData;
2848d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang
2858d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang        byte smsc[] = (byte[]) map.get("smsc");
2868d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang        byte[] pdu = (byte[]) map.get("pdu");
2878d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang        Message reply = obtainMessage(EVENT_SEND_SMS_COMPLETE, tracker);
2881260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa
2891260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa        // sms over gsm is used:
2901260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa        //   if sms over IMS is not supported AND
2911260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa        //   this is not a retry case after sms over IMS failed
2921260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa        //     indicated by mImsRetry > 0
2931260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa        if (0 == tracker.mImsRetry && !isIms()) {
2941260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa            if (tracker.mRetryCount > 0) {
2951260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa                // per TS 23.040 Section 9.2.3.6:  If TP-MTI SMS-SUBMIT (0x01) type
2961260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa                //   TP-RD (bit 2) is 1 for retry
2971260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa                //   and TP-MR is set to previously failed sms TP-MR
2981260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa                if (((0x01 & pdu[0]) == 0x01)) {
2991260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa                    pdu[0] |= 0x04; // TP-RD
3001260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa                    pdu[1] = (byte) tracker.mMessageRef; // TP-MR
3011260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa                }
3021260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa            }
3036ad88a8a2caf739e78c8d5f7f50fc7fa84a07ca7Chaitanya Saggurthi            if (tracker.mRetryCount == 0 && tracker.mExpectMore) {
3046ad88a8a2caf739e78c8d5f7f50fc7fa84a07ca7Chaitanya Saggurthi                mCi.sendSMSExpectMore(IccUtils.bytesToHexString(smsc),
3056ad88a8a2caf739e78c8d5f7f50fc7fa84a07ca7Chaitanya Saggurthi                        IccUtils.bytesToHexString(pdu), reply);
3066ad88a8a2caf739e78c8d5f7f50fc7fa84a07ca7Chaitanya Saggurthi            } else {
3076ad88a8a2caf739e78c8d5f7f50fc7fa84a07ca7Chaitanya Saggurthi                mCi.sendSMS(IccUtils.bytesToHexString(smsc),
3086ad88a8a2caf739e78c8d5f7f50fc7fa84a07ca7Chaitanya Saggurthi                        IccUtils.bytesToHexString(pdu), reply);
3096ad88a8a2caf739e78c8d5f7f50fc7fa84a07ca7Chaitanya Saggurthi            }
3101260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa        } else {
3111260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa            mCi.sendImsGsmSms(IccUtils.bytesToHexString(smsc),
3121260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa                    IccUtils.bytesToHexString(pdu), tracker.mImsRetry,
3131260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa                    tracker.mMessageRef, reply);
3141260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa            // increment it here, so in case of SMS_FAIL_RETRY over IMS
3151260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa            // next retry will be sent using IMS request again.
3161260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa            tracker.mImsRetry++;
3171260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa        }
3181260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa    }
3191260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa
3208d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang    /** {@inheritDoc} */
3218d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang    @Override
3228d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang    protected void updateSmsSendStatus(int messageRef, boolean success) {
3238d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang        // This function should be defined in ImsDispatcher.
3248d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang        Rlog.e(TAG, "updateSmsSendStatus should never be called from here!");
3258d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang    }
3268d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang
3271260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa    protected UiccCardApplication getUiccCardApplication() {
328a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            Rlog.d(TAG, "GsmSMSDispatcher: subId = " + mPhone.getSubId()
329a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    + " slotId = " + mPhone.getPhoneId());
330a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                return mUiccController.getUiccCardApplication(mPhone.getPhoneId(),
331a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                        UiccController.APP_FAM_3GPP);
3321260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa    }
3331260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa
3341260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa    private void onUpdateIccAvailability() {
3351260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa        if (mUiccController == null ) {
3361260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa            return;
3371260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa        }
3381260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa
3391260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa        UiccCardApplication newUiccApplication = getUiccCardApplication();
3401260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa
3411260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa        UiccCardApplication app = mUiccApplication.get();
3421260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa        if (app != newUiccApplication) {
3431260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa            if (app != null) {
3441260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa                Rlog.d(TAG, "Removing stale icc objects.");
3451260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa                if (mIccRecords.get() != null) {
3461260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa                    mIccRecords.get().unregisterForNewSms(this);
3471260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa                }
3481260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa                mIccRecords.set(null);
3491260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa                mUiccApplication.set(null);
3501260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa            }
3511260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa            if (newUiccApplication != null) {
3521260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa                Rlog.d(TAG, "New Uicc application found");
3531260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa                mUiccApplication.set(newUiccApplication);
3541260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa                mIccRecords.set(newUiccApplication.getIccRecords());
3551260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa                if (mIccRecords.get() != null) {
3561260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa                    mIccRecords.get().registerForNewSms(this, EVENT_NEW_ICC_SMS, null);
3571260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa                }
3581260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa            }
3591260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa        }
3601260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa    }
361c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville}
362