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;
20c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleimport android.app.PendingIntent;
21c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleimport android.app.PendingIntent.CanceledException;
22c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleimport android.content.Intent;
23c99dab56e20222b28cbc6238645feac938f1c333Ye Wenimport android.net.Uri;
24c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleimport android.os.AsyncResult;
25c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleimport android.os.Message;
26c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleimport android.provider.Telephony.Sms;
27c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleimport android.provider.Telephony.Sms.Intents;
28ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Savilleimport android.telephony.Rlog;
29a0c22039b77054d659151537896c1db90c7057f7Shishir Agrawalimport android.telephony.ServiceState;
30c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
315eccb26b2bcf3a51326596e1b0bb49b073d2f9fcAbhijith Shastryimport com.android.internal.annotations.VisibleForTesting;
32c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleimport com.android.internal.telephony.GsmAlphabet;
33ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowaimport com.android.internal.telephony.ImsSMSDispatcher;
34ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowaimport com.android.internal.telephony.InboundSmsHandler;
351a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yuimport com.android.internal.telephony.Phone;
36c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleimport com.android.internal.telephony.SMSDispatcher;
370d4bcdf379842af4b6304809156971e926f374f0Jake Hambyimport com.android.internal.telephony.SmsConstants;
38c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleimport com.android.internal.telephony.SmsHeader;
39c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleimport com.android.internal.telephony.SmsUsageMonitor;
401260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowaimport com.android.internal.telephony.uicc.IccRecords;
41d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenkaimport com.android.internal.telephony.uicc.IccUtils;
421260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowaimport com.android.internal.telephony.uicc.UiccCardApplication;
431260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowaimport com.android.internal.telephony.uicc.UiccController;
44c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
45c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleimport java.util.HashMap;
46c99dab56e20222b28cbc6238645feac938f1c333Ye Wenimport java.util.concurrent.atomic.AtomicBoolean;
47c99dab56e20222b28cbc6238645feac938f1c333Ye Wenimport java.util.concurrent.atomic.AtomicInteger;
481260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowaimport java.util.concurrent.atomic.AtomicReference;
49c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
50c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savillepublic final class GsmSMSDispatcher extends SMSDispatcher {
51cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville    private static final String TAG = "GsmSMSDispatcher";
521260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa    private static final boolean VDBG = false;
531260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa    protected UiccController mUiccController = null;
541260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa    private AtomicReference<IccRecords> mIccRecords = new AtomicReference<IccRecords>();
551260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa    private AtomicReference<UiccCardApplication> mUiccApplication =
561260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa            new AtomicReference<UiccCardApplication>();
571260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa    private GsmInboundSmsHandler mGsmInboundSmsHandler;
58c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
59c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /** Status report received */
60c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private static final int EVENT_NEW_SMS_STATUS_REPORT = 100;
61c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
621a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu    public GsmSMSDispatcher(Phone phone, SmsUsageMonitor usageMonitor,
63ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa            ImsSMSDispatcher imsSMSDispatcher,
641260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa            GsmInboundSmsHandler gsmInboundSmsHandler) {
65ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa        super(phone, usageMonitor, imsSMSDispatcher);
6622d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        mCi.setOnSmsStatus(this, EVENT_NEW_SMS_STATUS_REPORT, null);
671260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa        mGsmInboundSmsHandler = gsmInboundSmsHandler;
68ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa        mUiccController = UiccController.getInstance();
69ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa        mUiccController.registerForIccChanged(this, EVENT_ICC_CHANGED, null);
701260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa        Rlog.d(TAG, "GsmSMSDispatcher created");
71c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
72c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
73c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    @Override
74c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    public void dispose() {
750d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        super.dispose();
7622d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        mCi.unSetOnSmsStatus(this);
77ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa        mUiccController.unregisterForIccChanged(this);
78c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
79c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
80c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    @Override
81c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    protected String getFormat() {
82c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        return SmsConstants.FORMAT_3GPP;
83c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
84c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
85c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /**
86c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * Handles 3GPP format-specific events coming from the phone stack.
87c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * Other events are handled by {@link SMSDispatcher#handleMessage}.
88c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *
89c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * @param msg the message to handle
90c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     */
91c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    @Override
92c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    public void handleMessage(Message msg) {
93c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        switch (msg.what) {
94c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        case EVENT_NEW_SMS_STATUS_REPORT:
95c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            handleStatusReport((AsyncResult) msg.obj);
96c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            break;
97c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
981260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa        case EVENT_NEW_ICC_SMS:
991260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa        // pass to InboundSmsHandler to process
1001260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa        mGsmInboundSmsHandler.sendMessage(InboundSmsHandler.EVENT_NEW_SMS, msg.obj);
1011260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa        break;
1021260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa
1031260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa        case EVENT_ICC_CHANGED:
1041260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa            onUpdateIccAvailability();
1051260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa            break;
1061260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa
107c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        default:
108c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            super.handleMessage(msg);
109c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
110c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
111c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
112c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /**
113c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * Called when a status report is received.  This should correspond to
114c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * a previously successful SEND.
115c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *
116c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * @param ar AsyncResult passed into the message handler.  ar.result should
117c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *           be a String representing the status report PDU, as ASCII hex.
118c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     */
119c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private void handleStatusReport(AsyncResult ar) {
120c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        String pduString = (String) ar.result;
121c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        SmsMessage sms = SmsMessage.newFromCDS(pduString);
122c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
123c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (sms != null) {
124c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            int tpStatus = sms.getStatus();
12522d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            int messageRef = sms.mMessageRef;
126c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            for (int i = 0, count = deliveryPendingList.size(); i < count; i++) {
127c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                SmsTracker tracker = deliveryPendingList.get(i);
128c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                if (tracker.mMessageRef == messageRef) {
129c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    // Found it.  Remove from list and broadcast.
130c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    if(tpStatus >= Sms.STATUS_FAILED || tpStatus < Sms.STATUS_PENDING ) {
131c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                       deliveryPendingList.remove(i);
1320217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braun                       // Update the message status (COMPLETE or FAILED)
1330217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braun                       tracker.updateSentMessageStatus(mContext, tpStatus);
134c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    }
135c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    PendingIntent intent = tracker.mDeliveryIntent;
136c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    Intent fillIn = new Intent();
137c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    fillIn.putExtra("pdu", IccUtils.hexStringToBytes(pduString));
1381260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa                    fillIn.putExtra("format", getFormat());
139c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    try {
140c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        intent.send(mContext, Activity.RESULT_OK, fillIn);
141c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    } catch (CanceledException ex) {}
142c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
143c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    // Only expect to see one tracker matching this messageref
144c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    break;
145c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                }
146c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            }
147c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
1480d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        mCi.acknowledgeLastIncomingGsmSms(true, Intents.RESULT_SMS_HANDLED, null);
149c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
150c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
151c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /** {@inheritDoc} */
152c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    @Override
153c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    protected void sendData(String destAddr, String scAddr, int destPort,
154c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            byte[] data, PendingIntent sentIntent, PendingIntent deliveryIntent) {
155c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        SmsMessage.SubmitPdu pdu = SmsMessage.getSubmitPdu(
156c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                scAddr, destAddr, destPort, data, (deliveryIntent != null));
157c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (pdu != null) {
158ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa            HashMap map = getSmsTrackerMap(destAddr, scAddr, destPort, data, pdu);
159c99dab56e20222b28cbc6238645feac938f1c333Ye Wen            SmsTracker tracker = getSmsTracker(map, sentIntent, deliveryIntent, getFormat(),
16052a98d0a37731f48a316bc79fbc2c5a0f00a5e58Ye Wen                    null /*messageUri*/, false /*isExpectMore*/, null /*fullMessageText*/,
161a8f8c5a113a66de4854f4fb13a5825eb0705bd59Ji Yang                    false /*isText*/, true /*persistMessage*/);
1628215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang
1638215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang            String carrierPackage = getCarrierAppPackageName();
1648215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang            if (carrierPackage != null) {
1658215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang                Rlog.d(TAG, "Found carrier package.");
1668215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang                DataSmsSender smsSender = new DataSmsSender(tracker);
1678215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang                smsSender.sendSmsByCarrierApp(carrierPackage, new SmsSenderCallback(smsSender));
1688215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang            } else {
1698215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang                Rlog.v(TAG, "No carrier package.");
1708215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang                sendRawPdu(tracker);
1718215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang            }
172c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else {
173ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville            Rlog.e(TAG, "GsmSMSDispatcher.sendData(): getSubmitPdu() returned null");
174c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
175c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
176c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
177c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /** {@inheritDoc} */
1785eccb26b2bcf3a51326596e1b0bb49b073d2f9fcAbhijith Shastry    @VisibleForTesting
179c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    @Override
1805eccb26b2bcf3a51326596e1b0bb49b073d2f9fcAbhijith Shastry    public void sendText(String destAddr, String scAddr, String text, PendingIntent sentIntent,
181a8f8c5a113a66de4854f4fb13a5825eb0705bd59Ji Yang            PendingIntent deliveryIntent, Uri messageUri, String callingPkg,
182a8f8c5a113a66de4854f4fb13a5825eb0705bd59Ji Yang            boolean persistMessage) {
183c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        SmsMessage.SubmitPdu pdu = SmsMessage.getSubmitPdu(
184c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                scAddr, destAddr, text, (deliveryIntent != null));
185c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (pdu != null) {
186ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa            HashMap map = getSmsTrackerMap(destAddr, scAddr, text, pdu);
187c99dab56e20222b28cbc6238645feac938f1c333Ye Wen            SmsTracker tracker = getSmsTracker(map, sentIntent, deliveryIntent, getFormat(),
188a8f8c5a113a66de4854f4fb13a5825eb0705bd59Ji Yang                    messageUri, false /*isExpectMore*/, text /*fullMessageText*/, true /*isText*/,
189a8f8c5a113a66de4854f4fb13a5825eb0705bd59Ji Yang                    persistMessage);
1908215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang
1918215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang            String carrierPackage = getCarrierAppPackageName();
1928215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang            if (carrierPackage != null) {
1938215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang                Rlog.d(TAG, "Found carrier package.");
1948215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang                TextSmsSender smsSender = new TextSmsSender(tracker);
1958215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang                smsSender.sendSmsByCarrierApp(carrierPackage, new SmsSenderCallback(smsSender));
1968215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang            } else {
1978215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang                Rlog.v(TAG, "No carrier package.");
1988215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang                sendRawPdu(tracker);
1998215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang            }
200c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else {
201ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville            Rlog.e(TAG, "GsmSMSDispatcher.sendText(): getSubmitPdu() returned null");
202c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
203c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
204c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
205c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /** {@inheritDoc} */
206c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    @Override
20763418bbd2a9d7cc88ae24cc5ae776c01d688fc3aAnil Muthineni    protected void injectSmsPdu(byte[] pdu, String format, PendingIntent receivedIntent) {
20863418bbd2a9d7cc88ae24cc5ae776c01d688fc3aAnil Muthineni        throw new IllegalStateException("This method must be called only on ImsSMSDispatcher");
20963418bbd2a9d7cc88ae24cc5ae776c01d688fc3aAnil Muthineni    }
21063418bbd2a9d7cc88ae24cc5ae776c01d688fc3aAnil Muthineni
21163418bbd2a9d7cc88ae24cc5ae776c01d688fc3aAnil Muthineni    /** {@inheritDoc} */
21263418bbd2a9d7cc88ae24cc5ae776c01d688fc3aAnil Muthineni    @Override
213c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    protected GsmAlphabet.TextEncodingDetails calculateLength(CharSequence messageBody,
214c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            boolean use7bitOnly) {
215c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        return SmsMessage.calculateLength(messageBody, use7bitOnly);
216c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
217c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
218c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /** {@inheritDoc} */
219c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    @Override
2208215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang    protected SmsTracker getNewSubmitPduTracker(String destinationAddress, String scAddress,
221c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            String message, SmsHeader smsHeader, int encoding,
222c99dab56e20222b28cbc6238645feac938f1c333Ye Wen            PendingIntent sentIntent, PendingIntent deliveryIntent, boolean lastPart,
2234bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen            AtomicInteger unsentPartCount, AtomicBoolean anyPartFailed, Uri messageUri,
2244bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen            String fullMessageText) {
225c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        SmsMessage.SubmitPdu pdu = SmsMessage.getSubmitPdu(scAddress, destinationAddress,
226c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                message, deliveryIntent != null, SmsHeader.toByteArray(smsHeader),
227c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                encoding, smsHeader.languageTable, smsHeader.languageShiftTable);
228c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (pdu != null) {
229ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa            HashMap map =  getSmsTrackerMap(destinationAddress, scAddress,
2301260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa                    message, pdu);
2318215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang            return getSmsTracker(map, sentIntent,
23278d39a9fab86a26f4f39585af5cfe2a07c756fceShishir Agrawal                    deliveryIntent, getFormat(), unsentPartCount, anyPartFailed, messageUri,
233a8f8c5a113a66de4854f4fb13a5825eb0705bd59Ji Yang                    smsHeader, !lastPart, fullMessageText, true /*isText*/,
234a8f8c5a113a66de4854f4fb13a5825eb0705bd59Ji Yang                    false /*persistMessage*/);
235c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else {
236ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville            Rlog.e(TAG, "GsmSMSDispatcher.sendNewSubmitPdu(): getSubmitPdu() returned null");
2378215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang            return null;
238c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
239c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
240c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
2418215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang    @Override
2428215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang    protected void sendSubmitPdu(SmsTracker tracker) {
2438215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang        sendRawPdu(tracker);
2448215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang    }
2458215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang
246c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /** {@inheritDoc} */
247c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    @Override
248c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    protected void sendSms(SmsTracker tracker) {
2495d5ca33a24e6b73a48b575a0e1a5e790784d0bb7Amit Mahajan        HashMap<String, Object> map = tracker.getData();
250c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
251c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        byte pdu[] = (byte[]) map.get("pdu");
252c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
253454c5783e7695feec276325920550b2d4dcc3e16Rika Brooks        if (tracker.mRetryCount > 0) {
254454c5783e7695feec276325920550b2d4dcc3e16Rika Brooks            Rlog.d(TAG, "sendSms: "
255454c5783e7695feec276325920550b2d4dcc3e16Rika Brooks                    + " mRetryCount=" + tracker.mRetryCount
256454c5783e7695feec276325920550b2d4dcc3e16Rika Brooks                    + " mMessageRef=" + tracker.mMessageRef
257454c5783e7695feec276325920550b2d4dcc3e16Rika Brooks                    + " SS=" + mPhone.getServiceState().getState());
258454c5783e7695feec276325920550b2d4dcc3e16Rika Brooks
259454c5783e7695feec276325920550b2d4dcc3e16Rika Brooks            // per TS 23.040 Section 9.2.3.6:  If TP-MTI SMS-SUBMIT (0x01) type
260454c5783e7695feec276325920550b2d4dcc3e16Rika Brooks            //   TP-RD (bit 2) is 1 for retry
261454c5783e7695feec276325920550b2d4dcc3e16Rika Brooks            //   and TP-MR is set to previously failed sms TP-MR
262454c5783e7695feec276325920550b2d4dcc3e16Rika Brooks            if (((0x01 & pdu[0]) == 0x01)) {
263454c5783e7695feec276325920550b2d4dcc3e16Rika Brooks                pdu[0] |= 0x04; // TP-RD
264454c5783e7695feec276325920550b2d4dcc3e16Rika Brooks                pdu[1] = (byte) tracker.mMessageRef; // TP-MR
265454c5783e7695feec276325920550b2d4dcc3e16Rika Brooks            }
266454c5783e7695feec276325920550b2d4dcc3e16Rika Brooks        }
2671260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa        Rlog.d(TAG, "sendSms: "
2688d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang                + " isIms()=" + isIms()
2698d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang                + " mRetryCount=" + tracker.mRetryCount
2708d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang                + " mImsRetry=" + tracker.mImsRetry
2718d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang                + " mMessageRef=" + tracker.mMessageRef
2728d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang                + " SS=" + mPhone.getServiceState().getState());
2738d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang
2748215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang        sendSmsByPstn(tracker);
2758d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang    }
2768d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang
2778d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang    /** {@inheritDoc} */
2788d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang    @Override
2798d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang    protected void sendSmsByPstn(SmsTracker tracker) {
280a0c22039b77054d659151537896c1db90c7057f7Shishir Agrawal        int ss = mPhone.getServiceState().getState();
281a0c22039b77054d659151537896c1db90c7057f7Shishir Agrawal        // if sms over IMS is not supported on data and voice is not available...
282a0c22039b77054d659151537896c1db90c7057f7Shishir Agrawal        if (!isIms() && ss != ServiceState.STATE_IN_SERVICE) {
283a0c22039b77054d659151537896c1db90c7057f7Shishir Agrawal            tracker.onFailed(mContext, getNotInServiceError(ss), 0/*errorCode*/);
284a0c22039b77054d659151537896c1db90c7057f7Shishir Agrawal            return;
285a0c22039b77054d659151537896c1db90c7057f7Shishir Agrawal        }
286a0c22039b77054d659151537896c1db90c7057f7Shishir Agrawal
2875d5ca33a24e6b73a48b575a0e1a5e790784d0bb7Amit Mahajan        HashMap<String, Object> map = tracker.getData();
2888d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang
2898d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang        byte smsc[] = (byte[]) map.get("smsc");
2908d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang        byte[] pdu = (byte[]) map.get("pdu");
2918d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang        Message reply = obtainMessage(EVENT_SEND_SMS_COMPLETE, tracker);
2921260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa
2931260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa        // sms over gsm is used:
2941260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa        //   if sms over IMS is not supported AND
2951260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa        //   this is not a retry case after sms over IMS failed
2961260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa        //     indicated by mImsRetry > 0
2971260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa        if (0 == tracker.mImsRetry && !isIms()) {
2981260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa            if (tracker.mRetryCount > 0) {
2991260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa                // per TS 23.040 Section 9.2.3.6:  If TP-MTI SMS-SUBMIT (0x01) type
3001260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa                //   TP-RD (bit 2) is 1 for retry
3011260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa                //   and TP-MR is set to previously failed sms TP-MR
3021260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa                if (((0x01 & pdu[0]) == 0x01)) {
3031260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa                    pdu[0] |= 0x04; // TP-RD
3041260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa                    pdu[1] = (byte) tracker.mMessageRef; // TP-MR
3051260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa                }
3061260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa            }
3076ad88a8a2caf739e78c8d5f7f50fc7fa84a07ca7Chaitanya Saggurthi            if (tracker.mRetryCount == 0 && tracker.mExpectMore) {
3086ad88a8a2caf739e78c8d5f7f50fc7fa84a07ca7Chaitanya Saggurthi                mCi.sendSMSExpectMore(IccUtils.bytesToHexString(smsc),
3096ad88a8a2caf739e78c8d5f7f50fc7fa84a07ca7Chaitanya Saggurthi                        IccUtils.bytesToHexString(pdu), reply);
3106ad88a8a2caf739e78c8d5f7f50fc7fa84a07ca7Chaitanya Saggurthi            } else {
3116ad88a8a2caf739e78c8d5f7f50fc7fa84a07ca7Chaitanya Saggurthi                mCi.sendSMS(IccUtils.bytesToHexString(smsc),
3126ad88a8a2caf739e78c8d5f7f50fc7fa84a07ca7Chaitanya Saggurthi                        IccUtils.bytesToHexString(pdu), reply);
3136ad88a8a2caf739e78c8d5f7f50fc7fa84a07ca7Chaitanya Saggurthi            }
3141260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa        } else {
3151260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa            mCi.sendImsGsmSms(IccUtils.bytesToHexString(smsc),
3161260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa                    IccUtils.bytesToHexString(pdu), tracker.mImsRetry,
3171260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa                    tracker.mMessageRef, reply);
3181260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa            // increment it here, so in case of SMS_FAIL_RETRY over IMS
3191260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa            // next retry will be sent using IMS request again.
3201260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa            tracker.mImsRetry++;
3211260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa        }
3221260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa    }
3231260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa
3241260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa    protected UiccCardApplication getUiccCardApplication() {
325a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            Rlog.d(TAG, "GsmSMSDispatcher: subId = " + mPhone.getSubId()
326a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    + " slotId = " + mPhone.getPhoneId());
327a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                return mUiccController.getUiccCardApplication(mPhone.getPhoneId(),
328a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                        UiccController.APP_FAM_3GPP);
3291260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa    }
3301260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa
3311260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa    private void onUpdateIccAvailability() {
3321260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa        if (mUiccController == null ) {
3331260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa            return;
3341260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa        }
3351260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa
3361260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa        UiccCardApplication newUiccApplication = getUiccCardApplication();
3371260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa
3381260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa        UiccCardApplication app = mUiccApplication.get();
3391260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa        if (app != newUiccApplication) {
3401260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa            if (app != null) {
3411260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa                Rlog.d(TAG, "Removing stale icc objects.");
3421260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa                if (mIccRecords.get() != null) {
3431260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa                    mIccRecords.get().unregisterForNewSms(this);
3441260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa                }
3451260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa                mIccRecords.set(null);
3461260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa                mUiccApplication.set(null);
3471260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa            }
3481260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa            if (newUiccApplication != null) {
3491260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa                Rlog.d(TAG, "New Uicc application found");
3501260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa                mUiccApplication.set(newUiccApplication);
3511260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa                mIccRecords.set(newUiccApplication.getIccRecords());
3521260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa                if (mIccRecords.get() != null) {
3531260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa                    mIccRecords.get().registerForNewSms(this, EVENT_NEW_ICC_SMS, null);
3541260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa                }
3551260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa            }
3561260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa        }
3571260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa    }
358c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville}
359