GsmSMSDispatcher.java revision c99dab56e20222b28cbc6238645feac938f1c333
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;
248d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wangimport android.content.ComponentName;
258d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wangimport android.content.Context;
26c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleimport android.content.Intent;
27c99dab56e20222b28cbc6238645feac938f1c333Ye Wenimport android.net.Uri;
28c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleimport android.os.AsyncResult;
29c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleimport android.os.Message;
30c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleimport android.provider.Telephony.Sms;
31c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleimport android.provider.Telephony.Sms.Intents;
32ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Savilleimport android.telephony.Rlog;
33c99dab56e20222b28cbc6238645feac938f1c333Ye Wenimport android.telephony.SubscriptionManager;
34c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
35c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleimport com.android.internal.telephony.GsmAlphabet;
36ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowaimport com.android.internal.telephony.ImsSMSDispatcher;
37ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowaimport com.android.internal.telephony.InboundSmsHandler;
38c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleimport com.android.internal.telephony.PhoneBase;
39c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleimport com.android.internal.telephony.SMSDispatcher;
400d4bcdf379842af4b6304809156971e926f374f0Jake Hambyimport com.android.internal.telephony.SmsConstants;
41c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleimport com.android.internal.telephony.SmsHeader;
42c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleimport com.android.internal.telephony.SmsUsageMonitor;
431260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowaimport com.android.internal.telephony.uicc.IccRecords;
44d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenkaimport com.android.internal.telephony.uicc.IccUtils;
451260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowaimport com.android.internal.telephony.uicc.UiccCardApplication;
461260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowaimport com.android.internal.telephony.uicc.UiccController;
47c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
48c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleimport java.util.HashMap;
49c99dab56e20222b28cbc6238645feac938f1c333Ye Wenimport java.util.concurrent.atomic.AtomicBoolean;
50c99dab56e20222b28cbc6238645feac938f1c333Ye Wenimport java.util.concurrent.atomic.AtomicInteger;
511260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowaimport java.util.concurrent.atomic.AtomicReference;
52c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
53c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savillepublic final class GsmSMSDispatcher extends SMSDispatcher {
54cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville    private static final String TAG = "GsmSMSDispatcher";
551260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa    private static final boolean VDBG = false;
561260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa    protected UiccController mUiccController = null;
571260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa    private AtomicReference<IccRecords> mIccRecords = new AtomicReference<IccRecords>();
581260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa    private AtomicReference<UiccCardApplication> mUiccApplication =
591260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa            new AtomicReference<UiccCardApplication>();
601260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa    private GsmInboundSmsHandler mGsmInboundSmsHandler;
61c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
62c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /** Status report received */
63c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private static final int EVENT_NEW_SMS_STATUS_REPORT = 100;
64c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
65ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa    public GsmSMSDispatcher(PhoneBase phone, SmsUsageMonitor usageMonitor,
66ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa            ImsSMSDispatcher imsSMSDispatcher,
671260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa            GsmInboundSmsHandler gsmInboundSmsHandler) {
68ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa        super(phone, usageMonitor, imsSMSDispatcher);
6922d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        mCi.setOnSmsStatus(this, EVENT_NEW_SMS_STATUS_REPORT, null);
701260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa        mGsmInboundSmsHandler = gsmInboundSmsHandler;
71ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa        mUiccController = UiccController.getInstance();
72ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa        mUiccController.registerForIccChanged(this, EVENT_ICC_CHANGED, null);
731260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa        Rlog.d(TAG, "GsmSMSDispatcher created");
74c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
75c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
76c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    @Override
77c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    public void dispose() {
780d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        super.dispose();
7922d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        mCi.unSetOnSmsStatus(this);
80ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa        mUiccController.unregisterForIccChanged(this);
81c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
82c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
83c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    @Override
84c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    protected String getFormat() {
85c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        return SmsConstants.FORMAT_3GPP;
86c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
87c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
88c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /**
89c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * Handles 3GPP format-specific events coming from the phone stack.
90c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * Other events are handled by {@link SMSDispatcher#handleMessage}.
91c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *
92c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * @param msg the message to handle
93c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     */
94c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    @Override
95c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    public void handleMessage(Message msg) {
96c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        switch (msg.what) {
97c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        case EVENT_NEW_SMS_STATUS_REPORT:
98c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            handleStatusReport((AsyncResult) msg.obj);
99c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            break;
100c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1011260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa        case EVENT_NEW_ICC_SMS:
1021260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa        // pass to InboundSmsHandler to process
1031260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa        mGsmInboundSmsHandler.sendMessage(InboundSmsHandler.EVENT_NEW_SMS, msg.obj);
1041260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa        break;
1051260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa
1061260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa        case EVENT_ICC_CHANGED:
1071260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa            onUpdateIccAvailability();
1081260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa            break;
1091260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa
110c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        default:
111c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            super.handleMessage(msg);
112c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
113c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
114c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
115c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /**
116c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * Called when a status report is received.  This should correspond to
117c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * a previously successful SEND.
118c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *
119c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * @param ar AsyncResult passed into the message handler.  ar.result should
120c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *           be a String representing the status report PDU, as ASCII hex.
121c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     */
122c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private void handleStatusReport(AsyncResult ar) {
123c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        String pduString = (String) ar.result;
124c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        SmsMessage sms = SmsMessage.newFromCDS(pduString);
125c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
126c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (sms != null) {
127c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            int tpStatus = sms.getStatus();
12822d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            int messageRef = sms.mMessageRef;
129c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            for (int i = 0, count = deliveryPendingList.size(); i < count; i++) {
130c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                SmsTracker tracker = deliveryPendingList.get(i);
131c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                if (tracker.mMessageRef == messageRef) {
132c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    // Found it.  Remove from list and broadcast.
133c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    if(tpStatus >= Sms.STATUS_FAILED || tpStatus < Sms.STATUS_PENDING ) {
134c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                       deliveryPendingList.remove(i);
1350217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braun                       // Update the message status (COMPLETE or FAILED)
1360217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braun                       tracker.updateSentMessageStatus(mContext, tpStatus);
137c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    }
138c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    PendingIntent intent = tracker.mDeliveryIntent;
139c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    Intent fillIn = new Intent();
140c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    fillIn.putExtra("pdu", IccUtils.hexStringToBytes(pduString));
1411260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa                    fillIn.putExtra("format", getFormat());
142c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    try {
143c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        intent.send(mContext, Activity.RESULT_OK, fillIn);
144c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    } catch (CanceledException ex) {}
145c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
146c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    // Only expect to see one tracker matching this messageref
147c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    break;
148c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                }
149c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            }
150c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
1510d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        mCi.acknowledgeLastIncomingGsmSms(true, Intents.RESULT_SMS_HANDLED, null);
152c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
153c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
154c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /** {@inheritDoc} */
155c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    @Override
156c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    protected void sendData(String destAddr, String scAddr, int destPort,
157c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            byte[] data, PendingIntent sentIntent, PendingIntent deliveryIntent) {
158c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        SmsMessage.SubmitPdu pdu = SmsMessage.getSubmitPdu(
159c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                scAddr, destAddr, destPort, data, (deliveryIntent != null));
160c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (pdu != null) {
161ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa            HashMap map = getSmsTrackerMap(destAddr, scAddr, destPort, data, pdu);
162c99dab56e20222b28cbc6238645feac938f1c333Ye Wen            SmsTracker tracker = getSmsTracker(map, sentIntent, deliveryIntent, getFormat(),
163c99dab56e20222b28cbc6238645feac938f1c333Ye Wen                    null/*messageUri*/);
1641260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa            sendRawPdu(tracker);
165c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else {
166ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville            Rlog.e(TAG, "GsmSMSDispatcher.sendData(): getSubmitPdu() returned null");
167c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
168c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
169c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
170c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /** {@inheritDoc} */
171c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    @Override
172c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    protected void sendText(String destAddr, String scAddr, String text,
173c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            PendingIntent sentIntent, PendingIntent deliveryIntent) {
174c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        SmsMessage.SubmitPdu pdu = SmsMessage.getSubmitPdu(
175c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                scAddr, destAddr, text, (deliveryIntent != null));
176c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (pdu != null) {
177c99dab56e20222b28cbc6238645feac938f1c333Ye Wen            final Uri messageUri = writeOutboxMessage(
178c99dab56e20222b28cbc6238645feac938f1c333Ye Wen                    SubscriptionManager.getPreferredSmsSubId(),
179c99dab56e20222b28cbc6238645feac938f1c333Ye Wen                    destAddr,
180c99dab56e20222b28cbc6238645feac938f1c333Ye Wen                    text,
181c99dab56e20222b28cbc6238645feac938f1c333Ye Wen                    deliveryIntent != null);
182ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa            HashMap map = getSmsTrackerMap(destAddr, scAddr, text, pdu);
183c99dab56e20222b28cbc6238645feac938f1c333Ye Wen            SmsTracker tracker = getSmsTracker(map, sentIntent, deliveryIntent, getFormat(),
184c99dab56e20222b28cbc6238645feac938f1c333Ye Wen                    messageUri);
1851260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa            sendRawPdu(tracker);
186c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else {
187ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville            Rlog.e(TAG, "GsmSMSDispatcher.sendText(): getSubmitPdu() returned null");
188c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
189c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
190c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
191c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /** {@inheritDoc} */
192c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    @Override
19363418bbd2a9d7cc88ae24cc5ae776c01d688fc3aAnil Muthineni    protected void injectSmsPdu(byte[] pdu, String format, PendingIntent receivedIntent) {
19463418bbd2a9d7cc88ae24cc5ae776c01d688fc3aAnil Muthineni        throw new IllegalStateException("This method must be called only on ImsSMSDispatcher");
19563418bbd2a9d7cc88ae24cc5ae776c01d688fc3aAnil Muthineni    }
19663418bbd2a9d7cc88ae24cc5ae776c01d688fc3aAnil Muthineni
19763418bbd2a9d7cc88ae24cc5ae776c01d688fc3aAnil Muthineni    /** {@inheritDoc} */
19863418bbd2a9d7cc88ae24cc5ae776c01d688fc3aAnil Muthineni    @Override
199c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    protected GsmAlphabet.TextEncodingDetails calculateLength(CharSequence messageBody,
200c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            boolean use7bitOnly) {
201c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        return SmsMessage.calculateLength(messageBody, use7bitOnly);
202c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
203c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
204c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /** {@inheritDoc} */
205c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    @Override
206c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    protected void sendNewSubmitPdu(String destinationAddress, String scAddress,
207c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            String message, SmsHeader smsHeader, int encoding,
208c99dab56e20222b28cbc6238645feac938f1c333Ye Wen            PendingIntent sentIntent, PendingIntent deliveryIntent, boolean lastPart,
209c99dab56e20222b28cbc6238645feac938f1c333Ye Wen            AtomicInteger unsentPartCount, AtomicBoolean anyPartFailed, Uri messageUri) {
210c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        SmsMessage.SubmitPdu pdu = SmsMessage.getSubmitPdu(scAddress, destinationAddress,
211c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                message, deliveryIntent != null, SmsHeader.toByteArray(smsHeader),
212c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                encoding, smsHeader.languageTable, smsHeader.languageShiftTable);
213c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (pdu != null) {
214ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa            HashMap map =  getSmsTrackerMap(destinationAddress, scAddress,
2151260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa                    message, pdu);
216ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa            SmsTracker tracker = getSmsTracker(map, sentIntent,
217c99dab56e20222b28cbc6238645feac938f1c333Ye Wen                    deliveryIntent, getFormat(), unsentPartCount, anyPartFailed, messageUri);
2181260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa            sendRawPdu(tracker);
219c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else {
220ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville            Rlog.e(TAG, "GsmSMSDispatcher.sendNewSubmitPdu(): getSubmitPdu() returned null");
221c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
222c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
223c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
224c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /** {@inheritDoc} */
225c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    @Override
226c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    protected void sendSms(SmsTracker tracker) {
227c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        HashMap<String, Object> map = tracker.mData;
228c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
229c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        byte pdu[] = (byte[]) map.get("pdu");
230c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
231454c5783e7695feec276325920550b2d4dcc3e16Rika Brooks        if (tracker.mRetryCount > 0) {
232454c5783e7695feec276325920550b2d4dcc3e16Rika Brooks            Rlog.d(TAG, "sendSms: "
233454c5783e7695feec276325920550b2d4dcc3e16Rika Brooks                    + " mRetryCount=" + tracker.mRetryCount
234454c5783e7695feec276325920550b2d4dcc3e16Rika Brooks                    + " mMessageRef=" + tracker.mMessageRef
235454c5783e7695feec276325920550b2d4dcc3e16Rika Brooks                    + " SS=" + mPhone.getServiceState().getState());
236454c5783e7695feec276325920550b2d4dcc3e16Rika Brooks
237454c5783e7695feec276325920550b2d4dcc3e16Rika Brooks            // per TS 23.040 Section 9.2.3.6:  If TP-MTI SMS-SUBMIT (0x01) type
238454c5783e7695feec276325920550b2d4dcc3e16Rika Brooks            //   TP-RD (bit 2) is 1 for retry
239454c5783e7695feec276325920550b2d4dcc3e16Rika Brooks            //   and TP-MR is set to previously failed sms TP-MR
240454c5783e7695feec276325920550b2d4dcc3e16Rika Brooks            if (((0x01 & pdu[0]) == 0x01)) {
241454c5783e7695feec276325920550b2d4dcc3e16Rika Brooks                pdu[0] |= 0x04; // TP-RD
242454c5783e7695feec276325920550b2d4dcc3e16Rika Brooks                pdu[1] = (byte) tracker.mMessageRef; // TP-MR
243454c5783e7695feec276325920550b2d4dcc3e16Rika Brooks            }
244454c5783e7695feec276325920550b2d4dcc3e16Rika Brooks        }
2451260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa        Rlog.d(TAG, "sendSms: "
2468d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang                + " isIms()=" + isIms()
2478d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang                + " mRetryCount=" + tracker.mRetryCount
2488d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang                + " mImsRetry=" + tracker.mImsRetry
2498d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang                + " mMessageRef=" + tracker.mMessageRef
2508d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang                + " SS=" + mPhone.getServiceState().getState());
2518d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang
2528d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang        // FIX this once the carrier app and SIM restricted API is finalized.
2538d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang        // We should direct the intent to only the default carrier app.
2548d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang
2558d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang        // Send SMS via the carrier app.
2568d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang        BroadcastReceiver resultReceiver = new SMSDispatcherReceiver(tracker);
2578d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang
2588d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang        Intent intent = new Intent(Intents.SMS_SEND_ACTION);
2598d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang        intent.putExtra("pdu", pdu);
2608d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang        intent.putExtra("smsc", (byte[]) map.get("smsc"));
2618d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang        intent.putExtra("format", getFormat());
2628d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang        intent.addFlags(Intent.FLAG_RECEIVER_NO_ABORT);
2638d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang        Rlog.d(TAG, "Sending SMS by carrier app.");
2648d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang
2658d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang        mContext.sendOrderedBroadcast(intent, android.Manifest.permission.RECEIVE_SMS,
2668d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang                                      AppOpsManager.OP_RECEIVE_SMS, resultReceiver,
2678d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang                                      null, Activity.RESULT_CANCELED, null, null);
2688d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang    }
2698d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang
2708d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang    /** {@inheritDoc} */
2718d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang    @Override
2728d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang    protected void sendSmsByPstn(SmsTracker tracker) {
2738d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang        HashMap<String, Object> map = tracker.mData;
2748d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang
2758d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang        byte smsc[] = (byte[]) map.get("smsc");
2768d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang        byte[] pdu = (byte[]) map.get("pdu");
2778d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang        Message reply = obtainMessage(EVENT_SEND_SMS_COMPLETE, tracker);
2781260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa
2791260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa        // sms over gsm is used:
2801260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa        //   if sms over IMS is not supported AND
2811260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa        //   this is not a retry case after sms over IMS failed
2821260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa        //     indicated by mImsRetry > 0
2831260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa        if (0 == tracker.mImsRetry && !isIms()) {
2841260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa            if (tracker.mRetryCount > 0) {
2851260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa                // per TS 23.040 Section 9.2.3.6:  If TP-MTI SMS-SUBMIT (0x01) type
2861260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa                //   TP-RD (bit 2) is 1 for retry
2871260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa                //   and TP-MR is set to previously failed sms TP-MR
2881260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa                if (((0x01 & pdu[0]) == 0x01)) {
2891260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa                    pdu[0] |= 0x04; // TP-RD
2901260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa                    pdu[1] = (byte) tracker.mMessageRef; // TP-MR
2911260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa                }
2921260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa            }
2931260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa            mCi.sendSMS(IccUtils.bytesToHexString(smsc),
2941260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa                    IccUtils.bytesToHexString(pdu), reply);
2951260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa        } else {
2961260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa            mCi.sendImsGsmSms(IccUtils.bytesToHexString(smsc),
2971260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa                    IccUtils.bytesToHexString(pdu), tracker.mImsRetry,
2981260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa                    tracker.mMessageRef, reply);
2991260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa            // increment it here, so in case of SMS_FAIL_RETRY over IMS
3001260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa            // next retry will be sent using IMS request again.
3011260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa            tracker.mImsRetry++;
3021260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa        }
3031260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa    }
3041260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa
3058d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang    /** {@inheritDoc} */
3068d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang    @Override
3078d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang    protected void updateSmsSendStatus(int messageRef, boolean success) {
3088d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang        // This function should be defined in ImsDispatcher.
3098d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang        Rlog.e(TAG, "updateSmsSendStatus should never be called from here!");
3108d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang    }
3118d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang
3121260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa    protected UiccCardApplication getUiccCardApplication() {
313a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            Rlog.d(TAG, "GsmSMSDispatcher: subId = " + mPhone.getSubId()
314a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    + " slotId = " + mPhone.getPhoneId());
315a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                return mUiccController.getUiccCardApplication(mPhone.getPhoneId(),
316a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                        UiccController.APP_FAM_3GPP);
3171260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa    }
3181260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa
3191260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa    private void onUpdateIccAvailability() {
3201260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa        if (mUiccController == null ) {
3211260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa            return;
3221260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa        }
3231260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa
3241260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa        UiccCardApplication newUiccApplication = getUiccCardApplication();
3251260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa
3261260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa        UiccCardApplication app = mUiccApplication.get();
3271260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa        if (app != newUiccApplication) {
3281260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa            if (app != null) {
3291260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa                Rlog.d(TAG, "Removing stale icc objects.");
3301260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa                if (mIccRecords.get() != null) {
3311260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa                    mIccRecords.get().unregisterForNewSms(this);
3321260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa                }
3331260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa                mIccRecords.set(null);
3341260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa                mUiccApplication.set(null);
3351260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa            }
3361260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa            if (newUiccApplication != null) {
3371260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa                Rlog.d(TAG, "New Uicc application found");
3381260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa                mUiccApplication.set(newUiccApplication);
3391260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa                mIccRecords.set(newUiccApplication.getIccRecords());
3401260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa                if (mIccRecords.get() != null) {
3411260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa                    mIccRecords.get().registerForNewSms(this, EVENT_NEW_ICC_SMS, null);
3421260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa                }
3431260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa            }
3441260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa        }
3451260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa    }
346c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville}
347