10825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville/*
20825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Copyright (C) 2008 The Android Open Source Project
30825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville *
40825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Licensed under the Apache License, Version 2.0 (the "License");
50825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * you may not use this file except in compliance with the License.
60825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * You may obtain a copy of the License at
70825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville *
80825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville *      http://www.apache.org/licenses/LICENSE-2.0
90825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville *
100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Unless required by applicable law or agreed to in writing, software
110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * distributed under the License is distributed on an "AS IS" BASIS,
120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * See the License for the specific language governing permissions and
140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * limitations under the License.
150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */
160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
170825495a331bb44df395a0cdb79fab85e68db5d5Wink Savillepackage com.android.internal.telephony;
180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
19271770174f97e010dab9b7916034aecb270b1d81Ta-wei Yenimport static android.telephony.SmsManager.STATUS_ON_ICC_FREE;
20271770174f97e010dab9b7916034aecb270b1d81Ta-wei Yenimport static android.telephony.SmsManager.STATUS_ON_ICC_READ;
21271770174f97e010dab9b7916034aecb270b1d81Ta-wei Yenimport static android.telephony.SmsManager.STATUS_ON_ICC_UNREAD;
22271770174f97e010dab9b7916034aecb270b1d81Ta-wei Yen
237fce994eb223105829becb6c26e3af7a9739752cDianne Hackbornimport android.Manifest;
247fce994eb223105829becb6c26e3af7a9739752cDianne Hackbornimport android.app.AppOpsManager;
250825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.app.PendingIntent;
26b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wenimport android.content.ContentResolver;
270825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.content.Context;
284256e499c8e1e0a07998dcaf1f3aa127b693fc42Madhusudhan R. Adupalaimport android.content.Intent;
294256e499c8e1e0a07998dcaf1f3aa127b693fc42Madhusudhan R. Adupalaimport android.content.pm.PackageManager;
30b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wenimport android.database.Cursor;
31b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wenimport android.database.sqlite.SQLiteException;
32b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wenimport android.net.Uri;
33ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooksimport android.os.AsyncResult;
347fce994eb223105829becb6c26e3af7a9739752cDianne Hackbornimport android.os.Binder;
35ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooksimport android.os.Handler;
36ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooksimport android.os.Message;
37a2ce002a0327f0deb079cc6acad1c493e6ded442Amith Yamasaniimport android.os.UserManager;
38b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wenimport android.provider.Telephony;
394256e499c8e1e0a07998dcaf1f3aa127b693fc42Madhusudhan R. Adupalaimport android.service.carrier.CarrierMessagingService;
40ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Savilleimport android.telephony.Rlog;
41b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wenimport android.telephony.SmsManager;
42f3166841bf9df142e2fbd63b7647bae7da712044Xia Yingimport android.telephony.SmsMessage;
43271770174f97e010dab9b7916034aecb270b1d81Ta-wei Yenimport android.telephony.TelephonyManager;
440825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.util.Log;
450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
466f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowaimport com.android.internal.telephony.cdma.CdmaSmsBroadcastConfigInfo;
47271770174f97e010dab9b7916034aecb270b1d81Ta-wei Yenimport com.android.internal.telephony.gsm.SmsBroadcastConfigInfo;
48d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenkaimport com.android.internal.telephony.uicc.IccConstants;
49ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooksimport com.android.internal.telephony.uicc.IccFileHandler;
5017a3c8b39f73dac470b53934191679899450d97aAmit Mahajanimport com.android.internal.telephony.uicc.IccUtils;
51c9394399180abbc32d04f6a3652ce22d5931e0b8Shishir Agrawalimport com.android.internal.telephony.uicc.UiccController;
520825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.internal.util.HexDump;
530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
540825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport java.util.ArrayList;
55ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooksimport java.util.Arrays;
560825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport java.util.List;
570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville/**
590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * IccSmsInterfaceManager to provide an inter-process communication to
600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * access Sms in Icc.
610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */
62a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savillepublic class IccSmsInterfaceManager {
63cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville    static final String LOG_TAG = "IccSmsInterfaceManager";
64ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks    static final boolean DBG = true;
65ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks
66ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks    protected final Object mLock = new Object();
67ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks    protected boolean mSuccess;
68ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks    private List<SmsRawData> mSms;
69ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks
706f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa    private CellBroadcastRangeManager mCellBroadcastRangeManager =
716f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa            new CellBroadcastRangeManager();
726f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa    private CdmaBroadcastRangeManager mCdmaBroadcastRangeManager =
736f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa            new CdmaBroadcastRangeManager();
746f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa
75ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks    private static final int EVENT_LOAD_DONE = 1;
76ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks    private static final int EVENT_UPDATE_DONE = 2;
77ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks    protected static final int EVENT_SET_BROADCAST_ACTIVATION_DONE = 3;
78ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks    protected static final int EVENT_SET_BROADCAST_CONFIG_DONE = 4;
796f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa    private static final int SMS_CB_CODE_SCHEME_MIN = 0;
806f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa    private static final int SMS_CB_CODE_SCHEME_MAX = 255;
81ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks
821a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu    protected Phone mPhone;
837fce994eb223105829becb6c26e3af7a9739752cDianne Hackborn    final protected Context mContext;
847fce994eb223105829becb6c26e3af7a9739752cDianne Hackborn    final protected AppOpsManager mAppOps;
85a2ce002a0327f0deb079cc6acad1c493e6ded442Amith Yamasani    final private UserManager mUserManager;
860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    protected SMSDispatcher mDispatcher;
870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
88ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks    protected Handler mHandler = new Handler() {
89ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks        @Override
90ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks        public void handleMessage(Message msg) {
91ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks            AsyncResult ar;
92ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks
93ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks            switch (msg.what) {
94ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks                case EVENT_UPDATE_DONE:
95ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks                    ar = (AsyncResult) msg.obj;
96ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks                    synchronized (mLock) {
97ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks                        mSuccess = (ar.exception == null);
98ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks                        mLock.notifyAll();
99ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks                    }
100ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks                    break;
101ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks                case EVENT_LOAD_DONE:
102ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks                    ar = (AsyncResult)msg.obj;
103ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks                    synchronized (mLock) {
104ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks                        if (ar.exception == null) {
105ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa                            mSms = buildValidRawData((ArrayList<byte[]>) ar.result);
106ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks                            //Mark SMS as read after importing it from card.
107ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks                            markMessagesAsRead((ArrayList<byte[]>) ar.result);
108ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks                        } else {
1096f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa                            if (Rlog.isLoggable("SMS", Log.DEBUG)) {
1106f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa                                log("Cannot load Sms records");
1116f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa                            }
1123be9fb032307d7586b32dc57ddd486e8e9d43bd2fionaxu                            mSms = null;
113ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks                        }
114ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks                        mLock.notifyAll();
115ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks                    }
116ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks                    break;
117ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks                case EVENT_SET_BROADCAST_ACTIVATION_DONE:
118ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks                case EVENT_SET_BROADCAST_CONFIG_DONE:
119ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks                    ar = (AsyncResult) msg.obj;
120ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks                    synchronized (mLock) {
121ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks                        mSuccess = (ar.exception == null);
122ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks                        mLock.notifyAll();
123ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks                    }
124ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks                    break;
125ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks            }
126ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks        }
127ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks    };
128ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks
1291a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu    protected IccSmsInterfaceManager(Phone phone) {
1300825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        mPhone = phone;
1310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        mContext = phone.getContext();
1326f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa        mAppOps = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE);
133a2ce002a0327f0deb079cc6acad1c493e6ded442Amith Yamasani        mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
1341260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa        mDispatcher = new ImsSMSDispatcher(phone,
1351260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa                phone.mSmsStorageMonitor, phone.mSmsUsageMonitor);
1360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
1370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
138ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks    protected void markMessagesAsRead(ArrayList<byte[]> messages) {
139ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks        if (messages == null) {
140ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks            return;
141ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks        }
142ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks
143ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks        //IccFileHandler can be null, if icc card is absent.
144ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks        IccFileHandler fh = mPhone.getIccFileHandler();
145ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks        if (fh == null) {
146ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks            //shouldn't really happen, as messages are marked as read, only
147ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks            //after importing it from icc.
148ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks            if (Rlog.isLoggable("SMS", Log.DEBUG)) {
149ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks                log("markMessagesAsRead - aborting, no icc card present.");
150ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks            }
151ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks            return;
152ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks        }
153ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks
154ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks        int count = messages.size();
155ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks
156ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks        for (int i = 0; i < count; i++) {
157ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks             byte[] ba = messages.get(i);
158ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks             if (ba[0] == STATUS_ON_ICC_UNREAD) {
159ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks                 int n = ba.length;
160ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks                 byte[] nba = new byte[n - 1];
161ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks                 System.arraycopy(ba, 1, nba, 0, n - 1);
162ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks                 byte[] record = makeSmsRecordData(STATUS_ON_ICC_READ, nba);
163ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks                 fh.updateEFLinearFixed(IccConstants.EF_SMS, i + 1, record, null, null);
164ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks                 if (Rlog.isLoggable("SMS", Log.DEBUG)) {
165ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks                     log("SMS " + (i + 1) + " marked as read");
166ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks                 }
167ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks             }
168ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks        }
169ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks    }
170ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks
1711a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu    protected void updatePhoneObject(Phone phone) {
1726f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa        mPhone = phone;
1731260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa        mDispatcher.updatePhoneObject(phone);
1746f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa    }
1756f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa
1760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    protected void enforceReceiveAndSend(String message) {
177c6cbdea1423262784e0a155f93be75f3f72e242cxinhe        mContext.enforceCallingOrSelfPermission(
1787fce994eb223105829becb6c26e3af7a9739752cDianne Hackborn                Manifest.permission.RECEIVE_SMS, message);
179c6cbdea1423262784e0a155f93be75f3f72e242cxinhe        mContext.enforceCallingOrSelfPermission(
1807fce994eb223105829becb6c26e3af7a9739752cDianne Hackborn                Manifest.permission.SEND_SMS, message);
1810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
1820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /**
184ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks     * Update the specified message on the Icc.
185ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks     *
186ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks     * @param index record index of message to update
187ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks     * @param status new message status (STATUS_ON_ICC_READ,
188ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks     *                  STATUS_ON_ICC_UNREAD, STATUS_ON_ICC_SENT,
189ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks     *                  STATUS_ON_ICC_UNSENT, STATUS_ON_ICC_FREE)
190ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks     * @param pdu the raw PDU to store
191ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks     * @return success or not
192ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks     *
193ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks     */
194a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
195ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks    public boolean
1967fce994eb223105829becb6c26e3af7a9739752cDianne Hackborn    updateMessageOnIccEf(String callingPackage, int index, int status, byte[] pdu) {
197ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks        if (DBG) log("updateMessageOnIccEf: index=" + index +
198ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks                " status=" + status + " ==> " +
199ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks                "("+ Arrays.toString(pdu) + ")");
200ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks        enforceReceiveAndSend("Updating message on Icc");
2017fce994eb223105829becb6c26e3af7a9739752cDianne Hackborn        if (mAppOps.noteOp(AppOpsManager.OP_WRITE_ICC_SMS, Binder.getCallingUid(),
2027fce994eb223105829becb6c26e3af7a9739752cDianne Hackborn                callingPackage) != AppOpsManager.MODE_ALLOWED) {
2037fce994eb223105829becb6c26e3af7a9739752cDianne Hackborn            return false;
2047fce994eb223105829becb6c26e3af7a9739752cDianne Hackborn        }
205ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks        synchronized(mLock) {
206ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks            mSuccess = false;
207ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks            Message response = mHandler.obtainMessage(EVENT_UPDATE_DONE);
208ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks
209ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks            if (status == STATUS_ON_ICC_FREE) {
210ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks                // RIL_REQUEST_DELETE_SMS_ON_SIM vs RIL_REQUEST_CDMA_DELETE_SMS_ON_RUIM
211ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks                // Special case FREE: call deleteSmsOnSim/Ruim instead of
212ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks                // manipulating the record
213ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks                // Will eventually fail if icc card is not present.
2146f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa                if (PhoneConstants.PHONE_TYPE_GSM == mPhone.getPhoneType()) {
2156f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa                    mPhone.mCi.deleteSmsOnSim(index, response);
2166f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa                } else {
2176f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa                    mPhone.mCi.deleteSmsOnRuim(index, response);
2186f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa                }
219ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks            } else {
220ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks                //IccFilehandler can be null if ICC card is not present.
221ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks                IccFileHandler fh = mPhone.getIccFileHandler();
222ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks                if (fh == null) {
223ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks                    response.recycle();
224ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks                    return mSuccess; /* is false */
225ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks                }
226ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks                byte[] record = makeSmsRecordData(status, pdu);
227ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks                fh.updateEFLinearFixed(
228ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks                        IccConstants.EF_SMS,
229ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks                        index, record, null, response);
230ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks            }
231ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks            try {
232ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks                mLock.wait();
233ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks            } catch (InterruptedException e) {
234ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks                log("interrupted while trying to update by index");
235ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks            }
236ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks        }
237ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks        return mSuccess;
238ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks    }
239ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks
240ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks    /**
241ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks     * Copy a raw SMS PDU to the Icc.
242ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks     *
243ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks     * @param pdu the raw PDU to store
244ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks     * @param status message status (STATUS_ON_ICC_READ, STATUS_ON_ICC_UNREAD,
245ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks     *               STATUS_ON_ICC_SENT, STATUS_ON_ICC_UNSENT)
246ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks     * @return success or not
247ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks     *
248ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks     */
2497fce994eb223105829becb6c26e3af7a9739752cDianne Hackborn    public boolean copyMessageToIccEf(String callingPackage, int status, byte[] pdu, byte[] smsc) {
250ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks        //NOTE smsc not used in RUIM
251ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks        if (DBG) log("copyMessageToIccEf: status=" + status + " ==> " +
252ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks                "pdu=("+ Arrays.toString(pdu) +
253ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks                "), smsc=(" + Arrays.toString(smsc) +")");
254ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks        enforceReceiveAndSend("Copying message to Icc");
2557fce994eb223105829becb6c26e3af7a9739752cDianne Hackborn        if (mAppOps.noteOp(AppOpsManager.OP_WRITE_ICC_SMS, Binder.getCallingUid(),
2567fce994eb223105829becb6c26e3af7a9739752cDianne Hackborn                callingPackage) != AppOpsManager.MODE_ALLOWED) {
2577fce994eb223105829becb6c26e3af7a9739752cDianne Hackborn            return false;
2587fce994eb223105829becb6c26e3af7a9739752cDianne Hackborn        }
259ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks        synchronized(mLock) {
260ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks            mSuccess = false;
261ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks            Message response = mHandler.obtainMessage(EVENT_UPDATE_DONE);
262ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks
263ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks            //RIL_REQUEST_WRITE_SMS_TO_SIM vs RIL_REQUEST_CDMA_WRITE_SMS_TO_RUIM
2646f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa            if (PhoneConstants.PHONE_TYPE_GSM == mPhone.getPhoneType()) {
2656f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa                mPhone.mCi.writeSmsToSim(status, IccUtils.bytesToHexString(smsc),
2666f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa                        IccUtils.bytesToHexString(pdu), response);
2676f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa            } else {
2686f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa                mPhone.mCi.writeSmsToRuim(status, IccUtils.bytesToHexString(pdu),
2696f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa                        response);
2706f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa            }
271ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks
272ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks            try {
273ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks                mLock.wait();
274ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks            } catch (InterruptedException e) {
275ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks                log("interrupted while trying to update by index");
276ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks            }
277ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks        }
278ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks        return mSuccess;
279ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks    }
280ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks
281ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks    /**
282ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks     * Retrieves all messages currently stored on Icc.
283ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks     *
284ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks     * @return list of SmsRawData of all sms on Icc
285ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks     */
286a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
2877fce994eb223105829becb6c26e3af7a9739752cDianne Hackborn    public List<SmsRawData> getAllMessagesFromIccEf(String callingPackage) {
288ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks        if (DBG) log("getAllMessagesFromEF");
289ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks
290e5d7a8d946bf9496ffbe7533bffdeb83963489c3Jake Hamby        mContext.enforceCallingOrSelfPermission(
2917fce994eb223105829becb6c26e3af7a9739752cDianne Hackborn                Manifest.permission.RECEIVE_SMS,
292ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks                "Reading messages from Icc");
2937fce994eb223105829becb6c26e3af7a9739752cDianne Hackborn        if (mAppOps.noteOp(AppOpsManager.OP_READ_ICC_SMS, Binder.getCallingUid(),
2947fce994eb223105829becb6c26e3af7a9739752cDianne Hackborn                callingPackage) != AppOpsManager.MODE_ALLOWED) {
2957fce994eb223105829becb6c26e3af7a9739752cDianne Hackborn            return new ArrayList<SmsRawData>();
2967fce994eb223105829becb6c26e3af7a9739752cDianne Hackborn        }
297ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks        synchronized(mLock) {
298ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks
299ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks            IccFileHandler fh = mPhone.getIccFileHandler();
300ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks            if (fh == null) {
301ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks                Rlog.e(LOG_TAG, "Cannot load Sms records. No icc card?");
3023be9fb032307d7586b32dc57ddd486e8e9d43bd2fionaxu                mSms = null;
3033be9fb032307d7586b32dc57ddd486e8e9d43bd2fionaxu                return mSms;
304ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks            }
305ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks
306ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks            Message response = mHandler.obtainMessage(EVENT_LOAD_DONE);
307ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks            fh.loadEFLinearFixedAll(IccConstants.EF_SMS, response);
308ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks
309ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks            try {
310ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks                mLock.wait();
311ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks            } catch (InterruptedException e) {
312ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks                log("interrupted while trying to load from the Icc");
313ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks            }
314ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks        }
315ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks        return mSms;
316ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks    }
317ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks
318ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks    /**
319c55f67e3fa488c5f8aa90fda1ae43ef9d32cef52Nancy Chen     * A permissions check before passing to {@link IccSmsInterfaceManager#sendDataInternal}.
320c55f67e3fa488c5f8aa90fda1ae43ef9d32cef52Nancy Chen     * This method checks if the calling package or itself has the permission to send the data sms.
321c55f67e3fa488c5f8aa90fda1ae43ef9d32cef52Nancy Chen     */
322c55f67e3fa488c5f8aa90fda1ae43ef9d32cef52Nancy Chen    public void sendDataWithSelfPermissions(String callingPackage, String destAddr, String scAddr,
323c55f67e3fa488c5f8aa90fda1ae43ef9d32cef52Nancy Chen            int destPort, byte[] data, PendingIntent sentIntent, PendingIntent deliveryIntent) {
324c55f67e3fa488c5f8aa90fda1ae43ef9d32cef52Nancy Chen        mPhone.getContext().enforceCallingOrSelfPermission(
325c55f67e3fa488c5f8aa90fda1ae43ef9d32cef52Nancy Chen                Manifest.permission.SEND_SMS,
326c55f67e3fa488c5f8aa90fda1ae43ef9d32cef52Nancy Chen                "Sending SMS message");
327c55f67e3fa488c5f8aa90fda1ae43ef9d32cef52Nancy Chen        sendDataInternal(callingPackage, destAddr, scAddr, destPort, data, sentIntent,
328c55f67e3fa488c5f8aa90fda1ae43ef9d32cef52Nancy Chen                deliveryIntent);
329c55f67e3fa488c5f8aa90fda1ae43ef9d32cef52Nancy Chen    }
330c55f67e3fa488c5f8aa90fda1ae43ef9d32cef52Nancy Chen
331c55f67e3fa488c5f8aa90fda1ae43ef9d32cef52Nancy Chen    /**
332c55f67e3fa488c5f8aa90fda1ae43ef9d32cef52Nancy Chen     * A permissions check before passing to {@link IccSmsInterfaceManager#sendDataInternal}.
333c55f67e3fa488c5f8aa90fda1ae43ef9d32cef52Nancy Chen     * This method checks only if the calling package has the permission to send the data sms.
334c55f67e3fa488c5f8aa90fda1ae43ef9d32cef52Nancy Chen     */
335c55f67e3fa488c5f8aa90fda1ae43ef9d32cef52Nancy Chen    public void sendData(String callingPackage, String destAddr, String scAddr, int destPort,
336c55f67e3fa488c5f8aa90fda1ae43ef9d32cef52Nancy Chen            byte[] data, PendingIntent sentIntent, PendingIntent deliveryIntent) {
337c55f67e3fa488c5f8aa90fda1ae43ef9d32cef52Nancy Chen        mPhone.getContext().enforceCallingPermission(
338c55f67e3fa488c5f8aa90fda1ae43ef9d32cef52Nancy Chen                Manifest.permission.SEND_SMS,
339c55f67e3fa488c5f8aa90fda1ae43ef9d32cef52Nancy Chen                "Sending SMS message");
340c55f67e3fa488c5f8aa90fda1ae43ef9d32cef52Nancy Chen        sendDataInternal(callingPackage, destAddr, scAddr, destPort, data, sentIntent,
341c55f67e3fa488c5f8aa90fda1ae43ef9d32cef52Nancy Chen                deliveryIntent);
342c55f67e3fa488c5f8aa90fda1ae43ef9d32cef52Nancy Chen    }
343c55f67e3fa488c5f8aa90fda1ae43ef9d32cef52Nancy Chen
344c55f67e3fa488c5f8aa90fda1ae43ef9d32cef52Nancy Chen    /**
3450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * Send a data based SMS to a specific application port.
3460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *
3470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * @param destAddr the address to send the message to
3480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * @param scAddr is the service center address or null to use
3490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *  the current default SMSC
3500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * @param destPort the port to deliver the message to
3510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * @param data the body of the message to send
3520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * @param sentIntent if not NULL this <code>PendingIntent</code> is
3530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *  broadcast when the message is successfully sent, or failed.
3540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *  The result code will be <code>Activity.RESULT_OK<code> for success,
3550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *  or one of these errors:<br>
3560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *  <code>RESULT_ERROR_GENERIC_FAILURE</code><br>
3570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *  <code>RESULT_ERROR_RADIO_OFF</code><br>
3580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *  <code>RESULT_ERROR_NULL_PDU</code><br>
3590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *  For <code>RESULT_ERROR_GENERIC_FAILURE</code> the sentIntent may include
3600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *  the extra "errorCode" containing a radio technology specific value,
3610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *  generally only useful for troubleshooting.<br>
3620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *  The per-application based SMS control checks sentIntent. If sentIntent
3630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *  is NULL the caller will be checked against all unknown applications,
3640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *  which cause smaller number of SMS to be sent in checking period.
3650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * @param deliveryIntent if not NULL this <code>PendingIntent</code> is
3660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *  broadcast when the message is delivered to the recipient.  The
3670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *  raw pdu of the status report is in the extended data ("pdu").
3680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     */
369a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
370c55f67e3fa488c5f8aa90fda1ae43ef9d32cef52Nancy Chen    private void sendDataInternal(String callingPackage, String destAddr, String scAddr,
371c55f67e3fa488c5f8aa90fda1ae43ef9d32cef52Nancy Chen            int destPort, byte[] data, PendingIntent sentIntent, PendingIntent deliveryIntent) {
372ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville        if (Rlog.isLoggable("SMS", Log.VERBOSE)) {
3730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            log("sendData: destAddr=" + destAddr + " scAddr=" + scAddr + " destPort=" +
3740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                destPort + " data='"+ HexDump.toHexString(data)  + "' sentIntent=" +
3750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                sentIntent + " deliveryIntent=" + deliveryIntent);
3760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
3777fce994eb223105829becb6c26e3af7a9739752cDianne Hackborn        if (mAppOps.noteOp(AppOpsManager.OP_SEND_SMS, Binder.getCallingUid(),
3787fce994eb223105829becb6c26e3af7a9739752cDianne Hackborn                callingPackage) != AppOpsManager.MODE_ALLOWED) {
3797fce994eb223105829becb6c26e3af7a9739752cDianne Hackborn            return;
3807fce994eb223105829becb6c26e3af7a9739752cDianne Hackborn        }
38170dad6e7c56847c91bc55755c645680ea6c6fac3Xia Ying        destAddr = filterDestAddress(destAddr);
3820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        mDispatcher.sendData(destAddr, scAddr, destPort, data, sentIntent, deliveryIntent);
3830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
3840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /**
386c55f67e3fa488c5f8aa90fda1ae43ef9d32cef52Nancy Chen     * A permissions check before passing to {@link IccSmsInterfaceManager#sendTextInternal}.
387c55f67e3fa488c5f8aa90fda1ae43ef9d32cef52Nancy Chen     * This method checks only if the calling package has the permission to send the sms.
388c55f67e3fa488c5f8aa90fda1ae43ef9d32cef52Nancy Chen     */
389c55f67e3fa488c5f8aa90fda1ae43ef9d32cef52Nancy Chen    public void sendText(String callingPackage, String destAddr, String scAddr,
390a8f8c5a113a66de4854f4fb13a5825eb0705bd59Ji Yang            String text, PendingIntent sentIntent, PendingIntent deliveryIntent,
391a8f8c5a113a66de4854f4fb13a5825eb0705bd59Ji Yang            boolean persistMessageForNonDefaultSmsApp) {
392c55f67e3fa488c5f8aa90fda1ae43ef9d32cef52Nancy Chen        mPhone.getContext().enforceCallingPermission(
393c55f67e3fa488c5f8aa90fda1ae43ef9d32cef52Nancy Chen                Manifest.permission.SEND_SMS,
394c55f67e3fa488c5f8aa90fda1ae43ef9d32cef52Nancy Chen                "Sending SMS message");
395a8f8c5a113a66de4854f4fb13a5825eb0705bd59Ji Yang        sendTextInternal(callingPackage, destAddr, scAddr, text, sentIntent, deliveryIntent,
396a8f8c5a113a66de4854f4fb13a5825eb0705bd59Ji Yang            persistMessageForNonDefaultSmsApp);
397c55f67e3fa488c5f8aa90fda1ae43ef9d32cef52Nancy Chen    }
398c55f67e3fa488c5f8aa90fda1ae43ef9d32cef52Nancy Chen
399c55f67e3fa488c5f8aa90fda1ae43ef9d32cef52Nancy Chen    /**
400c55f67e3fa488c5f8aa90fda1ae43ef9d32cef52Nancy Chen     * A permissions check before passing to {@link IccSmsInterfaceManager#sendTextInternal}.
401c55f67e3fa488c5f8aa90fda1ae43ef9d32cef52Nancy Chen     * This method checks if the calling package or itself has the permission to send the sms.
402c55f67e3fa488c5f8aa90fda1ae43ef9d32cef52Nancy Chen     */
403c55f67e3fa488c5f8aa90fda1ae43ef9d32cef52Nancy Chen    public void sendTextWithSelfPermissions(String callingPackage, String destAddr, String scAddr,
404271770174f97e010dab9b7916034aecb270b1d81Ta-wei Yen            String text, PendingIntent sentIntent, PendingIntent deliveryIntent,
405271770174f97e010dab9b7916034aecb270b1d81Ta-wei Yen            boolean persistMessage) {
406c55f67e3fa488c5f8aa90fda1ae43ef9d32cef52Nancy Chen        mPhone.getContext().enforceCallingOrSelfPermission(
407c55f67e3fa488c5f8aa90fda1ae43ef9d32cef52Nancy Chen                Manifest.permission.SEND_SMS,
408c55f67e3fa488c5f8aa90fda1ae43ef9d32cef52Nancy Chen                "Sending SMS message");
409a8f8c5a113a66de4854f4fb13a5825eb0705bd59Ji Yang        sendTextInternal(callingPackage, destAddr, scAddr, text, sentIntent, deliveryIntent,
410271770174f97e010dab9b7916034aecb270b1d81Ta-wei Yen            persistMessage);
411c55f67e3fa488c5f8aa90fda1ae43ef9d32cef52Nancy Chen    }
412c55f67e3fa488c5f8aa90fda1ae43ef9d32cef52Nancy Chen
413c55f67e3fa488c5f8aa90fda1ae43ef9d32cef52Nancy Chen    /**
4140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * Send a text based SMS.
4150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *
4160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * @param destAddr the address to send the message to
4170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * @param scAddr is the service center address or null to use
4180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *  the current default SMSC
4190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * @param text the body of the message to send
4200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * @param sentIntent if not NULL this <code>PendingIntent</code> is
4210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *  broadcast when the message is successfully sent, or failed.
4220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *  The result code will be <code>Activity.RESULT_OK<code> for success,
4230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *  or one of these errors:<br>
4240825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *  <code>RESULT_ERROR_GENERIC_FAILURE</code><br>
4250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *  <code>RESULT_ERROR_RADIO_OFF</code><br>
4260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *  <code>RESULT_ERROR_NULL_PDU</code><br>
4270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *  For <code>RESULT_ERROR_GENERIC_FAILURE</code> the sentIntent may include
4280825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *  the extra "errorCode" containing a radio technology specific value,
4290825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *  generally only useful for troubleshooting.<br>
4300825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *  The per-application based SMS control checks sentIntent. If sentIntent
4310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *  is NULL the caller will be checked against all unknown applications,
4320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *  which cause smaller number of SMS to be sent in checking period.
4330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * @param deliveryIntent if not NULL this <code>PendingIntent</code> is
4340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *  broadcast when the message is delivered to the recipient.  The
4350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *  raw pdu of the status report is in the extended data ("pdu").
4360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     */
437a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
438c55f67e3fa488c5f8aa90fda1ae43ef9d32cef52Nancy Chen    private void sendTextInternal(String callingPackage, String destAddr, String scAddr,
439a8f8c5a113a66de4854f4fb13a5825eb0705bd59Ji Yang            String text, PendingIntent sentIntent, PendingIntent deliveryIntent,
440a8f8c5a113a66de4854f4fb13a5825eb0705bd59Ji Yang            boolean persistMessageForNonDefaultSmsApp) {
441ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville        if (Rlog.isLoggable("SMS", Log.VERBOSE)) {
4420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            log("sendText: destAddr=" + destAddr + " scAddr=" + scAddr +
4430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                " text='"+ text + "' sentIntent=" +
4440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                sentIntent + " deliveryIntent=" + deliveryIntent);
4450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
4467fce994eb223105829becb6c26e3af7a9739752cDianne Hackborn        if (mAppOps.noteOp(AppOpsManager.OP_SEND_SMS, Binder.getCallingUid(),
4477fce994eb223105829becb6c26e3af7a9739752cDianne Hackborn                callingPackage) != AppOpsManager.MODE_ALLOWED) {
4487fce994eb223105829becb6c26e3af7a9739752cDianne Hackborn            return;
4497fce994eb223105829becb6c26e3af7a9739752cDianne Hackborn        }
450a8f8c5a113a66de4854f4fb13a5825eb0705bd59Ji Yang        if (!persistMessageForNonDefaultSmsApp) {
451532c5ffb1d1ba6a3d642a21c107fd578ae64ef1cAbhijith Shastry            enforcePrivilegedAppPermissions();
452a8f8c5a113a66de4854f4fb13a5825eb0705bd59Ji Yang        }
45370dad6e7c56847c91bc55755c645680ea6c6fac3Xia Ying        destAddr = filterDestAddress(destAddr);
454b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen        mDispatcher.sendText(destAddr, scAddr, text, sentIntent, deliveryIntent,
455a8f8c5a113a66de4854f4fb13a5825eb0705bd59Ji Yang                null/*messageUri*/, callingPackage, persistMessageForNonDefaultSmsApp);
4560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
4570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
4580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /**
45963418bbd2a9d7cc88ae24cc5ae776c01d688fc3aAnil Muthineni     * Inject an SMS PDU into the android application framework.
46063418bbd2a9d7cc88ae24cc5ae776c01d688fc3aAnil Muthineni     *
46163418bbd2a9d7cc88ae24cc5ae776c01d688fc3aAnil Muthineni     * @param pdu is the byte array of pdu to be injected into android application framework
46263418bbd2a9d7cc88ae24cc5ae776c01d688fc3aAnil Muthineni     * @param format is the format of SMS pdu (3gpp or 3gpp2)
46363418bbd2a9d7cc88ae24cc5ae776c01d688fc3aAnil Muthineni     * @param receivedIntent if not NULL this <code>PendingIntent</code> is
46463418bbd2a9d7cc88ae24cc5ae776c01d688fc3aAnil Muthineni     *  broadcast when the message is successfully received by the
46563418bbd2a9d7cc88ae24cc5ae776c01d688fc3aAnil Muthineni     *  android application framework. This intent is broadcasted at
46663418bbd2a9d7cc88ae24cc5ae776c01d688fc3aAnil Muthineni     *  the same time an SMS received from radio is acknowledged back.
46763418bbd2a9d7cc88ae24cc5ae776c01d688fc3aAnil Muthineni     */
46863418bbd2a9d7cc88ae24cc5ae776c01d688fc3aAnil Muthineni    public void injectSmsPdu(byte[] pdu, String format, PendingIntent receivedIntent) {
469532c5ffb1d1ba6a3d642a21c107fd578ae64ef1cAbhijith Shastry        enforcePrivilegedAppPermissions();
47063418bbd2a9d7cc88ae24cc5ae776c01d688fc3aAnil Muthineni        if (Rlog.isLoggable("SMS", Log.VERBOSE)) {
47163418bbd2a9d7cc88ae24cc5ae776c01d688fc3aAnil Muthineni            log("pdu: " + pdu +
47263418bbd2a9d7cc88ae24cc5ae776c01d688fc3aAnil Muthineni                "\n format=" + format +
47363418bbd2a9d7cc88ae24cc5ae776c01d688fc3aAnil Muthineni                "\n receivedIntent=" + receivedIntent);
47463418bbd2a9d7cc88ae24cc5ae776c01d688fc3aAnil Muthineni        }
47563418bbd2a9d7cc88ae24cc5ae776c01d688fc3aAnil Muthineni        mDispatcher.injectSmsPdu(pdu, format, receivedIntent);
47663418bbd2a9d7cc88ae24cc5ae776c01d688fc3aAnil Muthineni    }
47763418bbd2a9d7cc88ae24cc5ae776c01d688fc3aAnil Muthineni
47863418bbd2a9d7cc88ae24cc5ae776c01d688fc3aAnil Muthineni    /**
4790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * Send a multi-part text based SMS.
4800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *
4810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * @param destAddr the address to send the message to
4820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * @param scAddr is the service center address or null to use
4830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *   the current default SMSC
4840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * @param parts an <code>ArrayList</code> of strings that, in order,
4850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *   comprise the original message
4860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * @param sentIntents if not null, an <code>ArrayList</code> of
4870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *   <code>PendingIntent</code>s (one for each message part) that is
4880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *   broadcast when the corresponding message part has been sent.
4890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *   The result code will be <code>Activity.RESULT_OK<code> for success,
4900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *   or one of these errors:
4910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *   <code>RESULT_ERROR_GENERIC_FAILURE</code>
4920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *   <code>RESULT_ERROR_RADIO_OFF</code>
4930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *   <code>RESULT_ERROR_NULL_PDU</code>.
4940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *  The per-application based SMS control checks sentIntent. If sentIntent
4950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *  is NULL the caller will be checked against all unknown applications,
4960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *  which cause smaller number of SMS to be sent in checking period.
4970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * @param deliveryIntents if not null, an <code>ArrayList</code> of
4980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *   <code>PendingIntent</code>s (one for each message part) that is
4990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *   broadcast when the corresponding message part has been delivered
5000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *   to the recipient.  The raw pdu of the status report is in the
5010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *   extended data ("pdu").
5020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     */
503a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
5047fce994eb223105829becb6c26e3af7a9739752cDianne Hackborn    public void sendMultipartText(String callingPackage, String destAddr, String scAddr,
5057fce994eb223105829becb6c26e3af7a9739752cDianne Hackborn            List<String> parts, List<PendingIntent> sentIntents,
506a8f8c5a113a66de4854f4fb13a5825eb0705bd59Ji Yang            List<PendingIntent> deliveryIntents, boolean persistMessageForNonDefaultSmsApp) {
5070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        mPhone.getContext().enforceCallingPermission(
5087fce994eb223105829becb6c26e3af7a9739752cDianne Hackborn                Manifest.permission.SEND_SMS,
5090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                "Sending SMS message");
510a8f8c5a113a66de4854f4fb13a5825eb0705bd59Ji Yang        if (!persistMessageForNonDefaultSmsApp) {
5114256e499c8e1e0a07998dcaf1f3aa127b693fc42Madhusudhan R. Adupala            // Only allow carrier app or carrier ims to skip auto message persistence.
512532c5ffb1d1ba6a3d642a21c107fd578ae64ef1cAbhijith Shastry            enforcePrivilegedAppPermissions();
513a8f8c5a113a66de4854f4fb13a5825eb0705bd59Ji Yang        }
514ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville        if (Rlog.isLoggable("SMS", Log.VERBOSE)) {
5150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            int i = 0;
5160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            for (String part : parts) {
5170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                log("sendMultipartText: destAddr=" + destAddr + ", srAddr=" + scAddr +
5180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        ", part[" + (i++) + "]=" + part);
5190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            }
5200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
5217fce994eb223105829becb6c26e3af7a9739752cDianne Hackborn        if (mAppOps.noteOp(AppOpsManager.OP_SEND_SMS, Binder.getCallingUid(),
5227fce994eb223105829becb6c26e3af7a9739752cDianne Hackborn                callingPackage) != AppOpsManager.MODE_ALLOWED) {
5237fce994eb223105829becb6c26e3af7a9739752cDianne Hackborn            return;
5247fce994eb223105829becb6c26e3af7a9739752cDianne Hackborn        }
525f3166841bf9df142e2fbd63b7647bae7da712044Xia Ying
526bd681a048599441c659f3d3a8300e47599783d54Xia Ying        destAddr = filterDestAddress(destAddr);
527bd681a048599441c659f3d3a8300e47599783d54Xia Ying
528f3166841bf9df142e2fbd63b7647bae7da712044Xia Ying        if (parts.size() > 1 && parts.size() < 10 && !SmsMessage.hasEmsSupport()) {
529f3166841bf9df142e2fbd63b7647bae7da712044Xia Ying            for (int i = 0; i < parts.size(); i++) {
530f3166841bf9df142e2fbd63b7647bae7da712044Xia Ying                // If EMS is not supported, we have to break down EMS into single segment SMS
531f3166841bf9df142e2fbd63b7647bae7da712044Xia Ying                // and add page info " x/y".
532f3166841bf9df142e2fbd63b7647bae7da712044Xia Ying                String singlePart = parts.get(i);
533f3166841bf9df142e2fbd63b7647bae7da712044Xia Ying                if (SmsMessage.shouldAppendPageNumberAsPrefix()) {
534f3166841bf9df142e2fbd63b7647bae7da712044Xia Ying                    singlePart = String.valueOf(i + 1) + '/' + parts.size() + ' ' + singlePart;
535f3166841bf9df142e2fbd63b7647bae7da712044Xia Ying                } else {
536f3166841bf9df142e2fbd63b7647bae7da712044Xia Ying                    singlePart = singlePart.concat(' ' + String.valueOf(i + 1) + '/' + parts.size());
537f3166841bf9df142e2fbd63b7647bae7da712044Xia Ying                }
538f3166841bf9df142e2fbd63b7647bae7da712044Xia Ying
539f3166841bf9df142e2fbd63b7647bae7da712044Xia Ying                PendingIntent singleSentIntent = null;
540f3166841bf9df142e2fbd63b7647bae7da712044Xia Ying                if (sentIntents != null && sentIntents.size() > i) {
541f3166841bf9df142e2fbd63b7647bae7da712044Xia Ying                    singleSentIntent = sentIntents.get(i);
542f3166841bf9df142e2fbd63b7647bae7da712044Xia Ying                }
543f3166841bf9df142e2fbd63b7647bae7da712044Xia Ying
544f3166841bf9df142e2fbd63b7647bae7da712044Xia Ying                PendingIntent singleDeliveryIntent = null;
545f3166841bf9df142e2fbd63b7647bae7da712044Xia Ying                if (deliveryIntents != null && deliveryIntents.size() > i) {
546f3166841bf9df142e2fbd63b7647bae7da712044Xia Ying                    singleDeliveryIntent = deliveryIntents.get(i);
547f3166841bf9df142e2fbd63b7647bae7da712044Xia Ying                }
548f3166841bf9df142e2fbd63b7647bae7da712044Xia Ying
549f3166841bf9df142e2fbd63b7647bae7da712044Xia Ying                mDispatcher.sendText(destAddr, scAddr, singlePart,
550f3166841bf9df142e2fbd63b7647bae7da712044Xia Ying                        singleSentIntent, singleDeliveryIntent,
551a8f8c5a113a66de4854f4fb13a5825eb0705bd59Ji Yang                        null/*messageUri*/, callingPackage,
552a8f8c5a113a66de4854f4fb13a5825eb0705bd59Ji Yang                        persistMessageForNonDefaultSmsApp);
553f3166841bf9df142e2fbd63b7647bae7da712044Xia Ying            }
554f3166841bf9df142e2fbd63b7647bae7da712044Xia Ying            return;
555f3166841bf9df142e2fbd63b7647bae7da712044Xia Ying        }
556f3166841bf9df142e2fbd63b7647bae7da712044Xia Ying
5570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        mDispatcher.sendMultipartText(destAddr, scAddr, (ArrayList<String>) parts,
558b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen                (ArrayList<PendingIntent>) sentIntents, (ArrayList<PendingIntent>) deliveryIntents,
559a8f8c5a113a66de4854f4fb13a5825eb0705bd59Ji Yang                null/*messageUri*/, callingPackage, persistMessageForNonDefaultSmsApp);
5600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
5610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
562a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
5634658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby    public int getPremiumSmsPermission(String packageName) {
5644658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby        return mDispatcher.getPremiumSmsPermission(packageName);
5654658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby    }
5664658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby
567a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
5684658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby    public void setPremiumSmsPermission(String packageName, int permission) {
5694658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby        mDispatcher.setPremiumSmsPermission(packageName, permission);
5704658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby    }
5714658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby
5720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /**
5730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * create SmsRawData lists from all sms record byte[]
5740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * Use null to indicate "free" record
5750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *
5760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * @param messages List of message records from EF_SMS.
5770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * @return SmsRawData list of all in-used records
5780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     */
5790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    protected ArrayList<SmsRawData> buildValidRawData(ArrayList<byte[]> messages) {
5800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        int count = messages.size();
5810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        ArrayList<SmsRawData> ret;
5820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
5830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        ret = new ArrayList<SmsRawData>(count);
5840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
5850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        for (int i = 0; i < count; i++) {
5860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            byte[] ba = messages.get(i);
5870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            if (ba[0] == STATUS_ON_ICC_FREE) {
5880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                ret.add(null);
5890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            } else {
5900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                ret.add(new SmsRawData(messages.get(i)));
5910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            }
5920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
5930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
5940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        return ret;
5950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
5960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
5970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /**
5980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * Generates an EF_SMS record from status and raw PDU.
5990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *
6000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * @param status Message status.  See TS 51.011 10.5.3.
6010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * @param pdu Raw message PDU.
6020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * @return byte array for the record.
6030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     */
6040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    protected byte[] makeSmsRecordData(int status, byte[] pdu) {
6050e4839f120dfe91f93bd164257fe61851530449bRakesh Pallerla        byte[] data;
6060e4839f120dfe91f93bd164257fe61851530449bRakesh Pallerla        if (PhoneConstants.PHONE_TYPE_GSM == mPhone.getPhoneType()) {
607444c570f0beab900e6c45f4270ab52c46a4c2d7fNathan Harold            data = new byte[SmsManager.SMS_RECORD_LENGTH];
6080e4839f120dfe91f93bd164257fe61851530449bRakesh Pallerla        } else {
609444c570f0beab900e6c45f4270ab52c46a4c2d7fNathan Harold            data = new byte[SmsManager.CDMA_SMS_RECORD_LENGTH];
6100e4839f120dfe91f93bd164257fe61851530449bRakesh Pallerla        }
6110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
6120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        // Status bits for this record.  See TS 51.011 10.5.3
6130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        data[0] = (byte)(status & 7);
6140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
6150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        System.arraycopy(pdu, 0, data, 1, pdu.length);
6160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
6170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        // Pad out with 0xFF's.
6180e4839f120dfe91f93bd164257fe61851530449bRakesh Pallerla        for (int j = pdu.length+1; j < data.length; j++) {
6190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            data[j] = -1;
6200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
6210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
6220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        return data;
6230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
6240825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
625a8064ed9c00ab7bdd584e722efebce429bcaa51bxinhe    public boolean enableCellBroadcast(int messageIdentifier, int ranType) {
626a8064ed9c00ab7bdd584e722efebce429bcaa51bxinhe        return enableCellBroadcastRange(messageIdentifier, messageIdentifier, ranType);
6276f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa    }
6286f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa
629a8064ed9c00ab7bdd584e722efebce429bcaa51bxinhe    public boolean disableCellBroadcast(int messageIdentifier, int ranType) {
630a8064ed9c00ab7bdd584e722efebce429bcaa51bxinhe        return disableCellBroadcastRange(messageIdentifier, messageIdentifier, ranType);
6316f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa    }
6326f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa
633a8064ed9c00ab7bdd584e722efebce429bcaa51bxinhe    public boolean enableCellBroadcastRange(int startMessageId, int endMessageId, int ranType) {
634a8064ed9c00ab7bdd584e722efebce429bcaa51bxinhe        if (ranType == SmsManager.CELL_BROADCAST_RAN_TYPE_GSM) {
6356f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa            return enableGsmBroadcastRange(startMessageId, endMessageId);
636a8064ed9c00ab7bdd584e722efebce429bcaa51bxinhe        } else if (ranType == SmsManager.CELL_BROADCAST_RAN_TYPE_CDMA) {
6376f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa            return enableCdmaBroadcastRange(startMessageId, endMessageId);
638a8064ed9c00ab7bdd584e722efebce429bcaa51bxinhe        } else {
639a8064ed9c00ab7bdd584e722efebce429bcaa51bxinhe            throw new IllegalArgumentException("Not a supportted RAN Type");
6406f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa        }
6416f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa    }
6426f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa
643a8064ed9c00ab7bdd584e722efebce429bcaa51bxinhe    public boolean disableCellBroadcastRange(int startMessageId, int endMessageId, int ranType) {
644a8064ed9c00ab7bdd584e722efebce429bcaa51bxinhe        if (ranType == SmsManager.CELL_BROADCAST_RAN_TYPE_GSM ) {
6456f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa            return disableGsmBroadcastRange(startMessageId, endMessageId);
646a8064ed9c00ab7bdd584e722efebce429bcaa51bxinhe        } else if (ranType == SmsManager.CELL_BROADCAST_RAN_TYPE_CDMA)  {
6476f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa            return disableCdmaBroadcastRange(startMessageId, endMessageId);
648a8064ed9c00ab7bdd584e722efebce429bcaa51bxinhe        } else {
649a8064ed9c00ab7bdd584e722efebce429bcaa51bxinhe            throw new IllegalArgumentException("Not a supportted RAN Type");
6506f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa        }
6516f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa    }
6526f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa
6536f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa    synchronized public boolean enableGsmBroadcastRange(int startMessageId, int endMessageId) {
6546f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa
6556f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa        Context context = mPhone.getContext();
6566f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa
6576f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa        context.enforceCallingPermission(
6586f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa                "android.permission.RECEIVE_SMS",
6596f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa                "Enabling cell broadcast SMS");
6606f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa
6616f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa        String client = context.getPackageManager().getNameForUid(
6626f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa                Binder.getCallingUid());
6636f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa
6646f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa        if (!mCellBroadcastRangeManager.enableRange(startMessageId, endMessageId, client)) {
665a8064ed9c00ab7bdd584e722efebce429bcaa51bxinhe            log("Failed to add GSM cell broadcast subscription for MID range " + startMessageId
6666f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa                    + " to " + endMessageId + " from client " + client);
6676f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa            return false;
6686f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa        }
6696f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa
6706f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa        if (DBG)
671a8064ed9c00ab7bdd584e722efebce429bcaa51bxinhe            log("Added GSM cell broadcast subscription for MID range " + startMessageId
6726f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa                    + " to " + endMessageId + " from client " + client);
6736f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa
6746f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa        setCellBroadcastActivation(!mCellBroadcastRangeManager.isEmpty());
6756f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa
6766f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa        return true;
6776f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa    }
6786f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa
6796f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa    synchronized public boolean disableGsmBroadcastRange(int startMessageId, int endMessageId) {
6806f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa
6816f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa        Context context = mPhone.getContext();
6826f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa
6836f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa        context.enforceCallingPermission(
6846f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa                "android.permission.RECEIVE_SMS",
6856f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa                "Disabling cell broadcast SMS");
6866f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa
6876f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa        String client = context.getPackageManager().getNameForUid(
6886f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa                Binder.getCallingUid());
6896f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa
6906f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa        if (!mCellBroadcastRangeManager.disableRange(startMessageId, endMessageId, client)) {
691a8064ed9c00ab7bdd584e722efebce429bcaa51bxinhe            log("Failed to remove GSM cell broadcast subscription for MID range " + startMessageId
6926f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa                    + " to " + endMessageId + " from client " + client);
6936f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa            return false;
6946f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa        }
6956f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa
6966f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa        if (DBG)
697a8064ed9c00ab7bdd584e722efebce429bcaa51bxinhe            log("Removed GSM cell broadcast subscription for MID range " + startMessageId
6986f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa                    + " to " + endMessageId + " from client " + client);
6996f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa
7006f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa        setCellBroadcastActivation(!mCellBroadcastRangeManager.isEmpty());
7016f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa
7026f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa        return true;
7036f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa    }
7046f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa
7056f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa    synchronized public boolean enableCdmaBroadcastRange(int startMessageId, int endMessageId) {
7066f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa
7076f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa        Context context = mPhone.getContext();
7086f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa
7096f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa        context.enforceCallingPermission(
7106f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa                "android.permission.RECEIVE_SMS",
7116f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa                "Enabling cdma broadcast SMS");
7126f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa
7136f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa        String client = context.getPackageManager().getNameForUid(
7146f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa                Binder.getCallingUid());
7156f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa
7166f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa        if (!mCdmaBroadcastRangeManager.enableRange(startMessageId, endMessageId, client)) {
7176f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa            log("Failed to add cdma broadcast subscription for MID range " + startMessageId
7186f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa                    + " to " + endMessageId + " from client " + client);
7196f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa            return false;
7206f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa        }
7216f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa
7226f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa        if (DBG)
7236f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa            log("Added cdma broadcast subscription for MID range " + startMessageId
7246f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa                    + " to " + endMessageId + " from client " + client);
7256f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa
7266f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa        setCdmaBroadcastActivation(!mCdmaBroadcastRangeManager.isEmpty());
7276f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa
7286f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa        return true;
7296f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa    }
7306f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa
7316f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa    synchronized public boolean disableCdmaBroadcastRange(int startMessageId, int endMessageId) {
7326f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa
7336f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa        Context context = mPhone.getContext();
7346f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa
7356f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa        context.enforceCallingPermission(
7366f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa                "android.permission.RECEIVE_SMS",
7376f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa                "Disabling cell broadcast SMS");
7386f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa
7396f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa        String client = context.getPackageManager().getNameForUid(
7406f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa                Binder.getCallingUid());
7416f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa
7426f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa        if (!mCdmaBroadcastRangeManager.disableRange(startMessageId, endMessageId, client)) {
7436f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa            log("Failed to remove cdma broadcast subscription for MID range " + startMessageId
7446f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa                    + " to " + endMessageId + " from client " + client);
7456f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa            return false;
7466f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa        }
7476f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa
7486f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa        if (DBG)
7496f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa            log("Removed cdma broadcast subscription for MID range " + startMessageId
7506f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa                    + " to " + endMessageId + " from client " + client);
7516f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa
7526f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa        setCdmaBroadcastActivation(!mCdmaBroadcastRangeManager.isEmpty());
7536f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa
7546f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa        return true;
7556f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa    }
7566f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa
7576f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa    class CellBroadcastRangeManager extends IntRangeManager {
7586f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa        private ArrayList<SmsBroadcastConfigInfo> mConfigList =
7596f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa                new ArrayList<SmsBroadcastConfigInfo>();
7606f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa
7616f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa        /**
7626f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa         * Called when the list of enabled ranges has changed. This will be
7636f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa         * followed by zero or more calls to {@link #addRange} followed by
7646f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa         * a call to {@link #finishUpdate}.
7656f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa         */
7666f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa        protected void startUpdate() {
7676f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa            mConfigList.clear();
7686f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa        }
7696f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa
7706f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa        /**
7716f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa         * Called after {@link #startUpdate} to indicate a range of enabled
7726f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa         * values.
7736f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa         * @param startId the first id included in the range
7746f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa         * @param endId the last id included in the range
7756f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa         */
7766f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa        protected void addRange(int startId, int endId, boolean selected) {
7776f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa            mConfigList.add(new SmsBroadcastConfigInfo(startId, endId,
7786f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa                        SMS_CB_CODE_SCHEME_MIN, SMS_CB_CODE_SCHEME_MAX, selected));
7796f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa        }
7806f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa
7816f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa        /**
7826f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa         * Called to indicate the end of a range update started by the
7836f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa         * previous call to {@link #startUpdate}.
7846f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa         * @return true if successful, false otherwise
7856f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa         */
7866f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa        protected boolean finishUpdate() {
7876f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa            if (mConfigList.isEmpty()) {
7886f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa                return true;
7896f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa            } else {
7906f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa                SmsBroadcastConfigInfo[] configs =
7916f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa                        mConfigList.toArray(new SmsBroadcastConfigInfo[mConfigList.size()]);
7926f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa                return setCellBroadcastConfig(configs);
7936f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa            }
7946f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa        }
7956f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa    }
7966f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa
7976f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa    class CdmaBroadcastRangeManager extends IntRangeManager {
7986f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa        private ArrayList<CdmaSmsBroadcastConfigInfo> mConfigList =
7996f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa                new ArrayList<CdmaSmsBroadcastConfigInfo>();
8006f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa
8016f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa        /**
8026f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa         * Called when the list of enabled ranges has changed. This will be
8036f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa         * followed by zero or more calls to {@link #addRange} followed by a
8046f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa         * call to {@link #finishUpdate}.
8056f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa         */
8066f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa        protected void startUpdate() {
8076f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa            mConfigList.clear();
8086f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa        }
809ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks
8106f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa        /**
8116f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa         * Called after {@link #startUpdate} to indicate a range of enabled
8126f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa         * values.
8136f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa         * @param startId the first id included in the range
8146f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa         * @param endId the last id included in the range
8156f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa         */
8166f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa        protected void addRange(int startId, int endId, boolean selected) {
8176f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa            mConfigList.add(new CdmaSmsBroadcastConfigInfo(startId, endId,
8186f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa                    1, selected));
8196f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa        }
820ebc3f0565ad0f9b8b7d3531afd8744843d96aadbRika Brooks
8216f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa        /**
8226f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa         * Called to indicate the end of a range update started by the previous
8236f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa         * call to {@link #startUpdate}.
8246f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa         * @return true if successful, false otherwise
8256f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa         */
8266f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa        protected boolean finishUpdate() {
8276f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa            if (mConfigList.isEmpty()) {
8286f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa                return true;
8296f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa            } else {
8306f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa                CdmaSmsBroadcastConfigInfo[] configs =
8316f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa                        mConfigList.toArray(new CdmaSmsBroadcastConfigInfo[mConfigList.size()]);
8326f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa                return setCdmaBroadcastConfig(configs);
8336f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa            }
8346f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa        }
8356f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa    }
8366f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa
8376f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa    private boolean setCellBroadcastConfig(SmsBroadcastConfigInfo[] configs) {
8386f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa        if (DBG)
8396f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa            log("Calling setGsmBroadcastConfig with " + configs.length + " configurations");
8400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
8416f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa        synchronized (mLock) {
8426f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa            Message response = mHandler.obtainMessage(EVENT_SET_BROADCAST_CONFIG_DONE);
8436f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa
8446f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa            mSuccess = false;
8456f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa            mPhone.mCi.setGsmBroadcastConfig(configs, response);
8466f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa
8476f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa            try {
8486f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa                mLock.wait();
8496f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa            } catch (InterruptedException e) {
8506f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa                log("interrupted while trying to set cell broadcast config");
8516f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa            }
8526f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa        }
8536f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa
8546f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa        return mSuccess;
8556f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa    }
8566f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa
8576f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa    private boolean setCellBroadcastActivation(boolean activate) {
8586f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa        if (DBG)
8596f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa            log("Calling setCellBroadcastActivation(" + activate + ')');
8606f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa
8616f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa        synchronized (mLock) {
8626f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa            Message response = mHandler.obtainMessage(EVENT_SET_BROADCAST_ACTIVATION_DONE);
8636f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa
8646f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa            mSuccess = false;
8656f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa            mPhone.mCi.setGsmBroadcastActivation(activate, response);
8666f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa
8676f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa            try {
8686f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa                mLock.wait();
8696f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa            } catch (InterruptedException e) {
8706f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa                log("interrupted while trying to set cell broadcast activation");
8716f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa            }
8726f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa        }
8736f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa
8746f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa        return mSuccess;
8756f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa    }
8766f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa
8776f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa    private boolean setCdmaBroadcastConfig(CdmaSmsBroadcastConfigInfo[] configs) {
8786f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa        if (DBG)
8796f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa            log("Calling setCdmaBroadcastConfig with " + configs.length + " configurations");
8806f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa
8816f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa        synchronized (mLock) {
8826f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa            Message response = mHandler.obtainMessage(EVENT_SET_BROADCAST_CONFIG_DONE);
8836f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa
8846f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa            mSuccess = false;
8856f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa            mPhone.mCi.setCdmaBroadcastConfig(configs, response);
8866f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa
8876f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa            try {
8886f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa                mLock.wait();
8896f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa            } catch (InterruptedException e) {
8906f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa                log("interrupted while trying to set cdma broadcast config");
8916f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa            }
8926f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa        }
8936f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa
8946f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa        return mSuccess;
8956f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa    }
8966f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa
8976f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa    private boolean setCdmaBroadcastActivation(boolean activate) {
8986f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa        if (DBG)
8996f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa            log("Calling setCdmaBroadcastActivation(" + activate + ")");
9006f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa
9016f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa        synchronized (mLock) {
9026f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa            Message response = mHandler.obtainMessage(EVENT_SET_BROADCAST_ACTIVATION_DONE);
9036f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa
9046f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa            mSuccess = false;
9056f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa            mPhone.mCi.setCdmaBroadcastActivation(activate, response);
9066f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa
9076f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa            try {
9086f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa                mLock.wait();
9096f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa            } catch (InterruptedException e) {
9106f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa                log("interrupted while trying to set cdma broadcast activation");
9116f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa            }
9126f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa        }
9136f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa
9146f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa        return mSuccess;
9156f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa    }
9166f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa
9176f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa    protected void log(String msg) {
9186f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa        Log.d(LOG_TAG, "[IccSmsInterfaceManager] " + msg);
9196f2a3e1ea86ae7ae2e04eb95582e54eec7a2f864Sukanya Rajkhowa    }
9201260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa
9211260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa    public boolean isImsSmsSupported() {
9221260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa        return mDispatcher.isIms();
9231260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa    }
9241260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa
9251260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa    public String getImsSmsFormat() {
9261260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa        return mDispatcher.getImsSmsFormat();
9271260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa    }
928b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen
929b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen    public void sendStoredText(String callingPkg, Uri messageUri, String scAddress,
930b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen            PendingIntent sentIntent, PendingIntent deliveryIntent) {
931b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen        mPhone.getContext().enforceCallingPermission(Manifest.permission.SEND_SMS,
932b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen                "Sending SMS message");
933b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen        if (Rlog.isLoggable("SMS", Log.VERBOSE)) {
934b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen            log("sendStoredText: scAddr=" + scAddress + " messageUri=" + messageUri
935b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen                    + " sentIntent=" + sentIntent + " deliveryIntent=" + deliveryIntent);
936b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen        }
937b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen        if (mAppOps.noteOp(AppOpsManager.OP_SEND_SMS, Binder.getCallingUid(), callingPkg)
938b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen                != AppOpsManager.MODE_ALLOWED) {
939b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen            return;
940b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen        }
941b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen        final ContentResolver resolver = mPhone.getContext().getContentResolver();
942b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen        if (!isFailedOrDraft(resolver, messageUri)) {
943b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen            Log.e(LOG_TAG, "[IccSmsInterfaceManager]sendStoredText: not FAILED or DRAFT message");
944b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen            returnUnspecifiedFailure(sentIntent);
945b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen            return;
946b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen        }
947b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen        final String[] textAndAddress = loadTextAndAddress(resolver, messageUri);
948b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen        if (textAndAddress == null) {
949b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen            Log.e(LOG_TAG, "[IccSmsInterfaceManager]sendStoredText: can not load text");
950b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen            returnUnspecifiedFailure(sentIntent);
951b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen            return;
952b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen        }
95370dad6e7c56847c91bc55755c645680ea6c6fac3Xia Ying        textAndAddress[1] = filterDestAddress(textAndAddress[1]);
954b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen        mDispatcher.sendText(textAndAddress[1], scAddress, textAndAddress[0],
955a8f8c5a113a66de4854f4fb13a5825eb0705bd59Ji Yang                sentIntent, deliveryIntent, messageUri, callingPkg,
956a8f8c5a113a66de4854f4fb13a5825eb0705bd59Ji Yang                true /* persistMessageForNonDefaultSmsApp */);
957b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen    }
958b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen
959b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen    public void sendStoredMultipartText(String callingPkg, Uri messageUri, String scAddress,
960b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen            List<PendingIntent> sentIntents, List<PendingIntent> deliveryIntents) {
961b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen        mPhone.getContext().enforceCallingPermission(Manifest.permission.SEND_SMS,
962b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen                "Sending SMS message");
963b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen        if (mAppOps.noteOp(AppOpsManager.OP_SEND_SMS, Binder.getCallingUid(), callingPkg)
964b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen                != AppOpsManager.MODE_ALLOWED) {
965b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen            return;
966b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen        }
967b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen        final ContentResolver resolver = mPhone.getContext().getContentResolver();
968b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen        if (!isFailedOrDraft(resolver, messageUri)) {
969b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen            Log.e(LOG_TAG, "[IccSmsInterfaceManager]sendStoredMultipartText: "
970b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen                    + "not FAILED or DRAFT message");
971b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen            returnUnspecifiedFailure(sentIntents);
972b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen            return;
973b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen        }
974b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen        final String[] textAndAddress = loadTextAndAddress(resolver, messageUri);
975b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen        if (textAndAddress == null) {
976b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen            Log.e(LOG_TAG, "[IccSmsInterfaceManager]sendStoredMultipartText: can not load text");
977b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen            returnUnspecifiedFailure(sentIntents);
978b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen            return;
979b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen        }
980b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen        final ArrayList<String> parts = SmsManager.getDefault().divideMessage(textAndAddress[0]);
981b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen        if (parts == null || parts.size() < 1) {
982b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen            Log.e(LOG_TAG, "[IccSmsInterfaceManager]sendStoredMultipartText: can not divide text");
983b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen            returnUnspecifiedFailure(sentIntents);
984b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen            return;
985b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen        }
986f3166841bf9df142e2fbd63b7647bae7da712044Xia Ying
987bd681a048599441c659f3d3a8300e47599783d54Xia Ying        textAndAddress[1] = filterDestAddress(textAndAddress[1]);
988bd681a048599441c659f3d3a8300e47599783d54Xia Ying
989f3166841bf9df142e2fbd63b7647bae7da712044Xia Ying        if (parts.size() > 1 && parts.size() < 10 && !SmsMessage.hasEmsSupport()) {
990f3166841bf9df142e2fbd63b7647bae7da712044Xia Ying            for (int i = 0; i < parts.size(); i++) {
991f3166841bf9df142e2fbd63b7647bae7da712044Xia Ying                // If EMS is not supported, we have to break down EMS into single segment SMS
992f3166841bf9df142e2fbd63b7647bae7da712044Xia Ying                // and add page info " x/y".
993f3166841bf9df142e2fbd63b7647bae7da712044Xia Ying                String singlePart = parts.get(i);
994f3166841bf9df142e2fbd63b7647bae7da712044Xia Ying                if (SmsMessage.shouldAppendPageNumberAsPrefix()) {
995f3166841bf9df142e2fbd63b7647bae7da712044Xia Ying                    singlePart = String.valueOf(i + 1) + '/' + parts.size() + ' ' + singlePart;
996f3166841bf9df142e2fbd63b7647bae7da712044Xia Ying                } else {
997f3166841bf9df142e2fbd63b7647bae7da712044Xia Ying                    singlePart = singlePart.concat(' ' + String.valueOf(i + 1) + '/' + parts.size());
998f3166841bf9df142e2fbd63b7647bae7da712044Xia Ying                }
999f3166841bf9df142e2fbd63b7647bae7da712044Xia Ying
1000f3166841bf9df142e2fbd63b7647bae7da712044Xia Ying                PendingIntent singleSentIntent = null;
1001f3166841bf9df142e2fbd63b7647bae7da712044Xia Ying                if (sentIntents != null && sentIntents.size() > i) {
1002f3166841bf9df142e2fbd63b7647bae7da712044Xia Ying                    singleSentIntent = sentIntents.get(i);
1003f3166841bf9df142e2fbd63b7647bae7da712044Xia Ying                }
1004f3166841bf9df142e2fbd63b7647bae7da712044Xia Ying
1005f3166841bf9df142e2fbd63b7647bae7da712044Xia Ying                PendingIntent singleDeliveryIntent = null;
1006f3166841bf9df142e2fbd63b7647bae7da712044Xia Ying                if (deliveryIntents != null && deliveryIntents.size() > i) {
1007f3166841bf9df142e2fbd63b7647bae7da712044Xia Ying                    singleDeliveryIntent = deliveryIntents.get(i);
1008f3166841bf9df142e2fbd63b7647bae7da712044Xia Ying                }
1009f3166841bf9df142e2fbd63b7647bae7da712044Xia Ying
1010f3166841bf9df142e2fbd63b7647bae7da712044Xia Ying                mDispatcher.sendText(textAndAddress[1], scAddress, singlePart,
1011a8f8c5a113a66de4854f4fb13a5825eb0705bd59Ji Yang                        singleSentIntent, singleDeliveryIntent, messageUri, callingPkg,
1012a8f8c5a113a66de4854f4fb13a5825eb0705bd59Ji Yang                        true  /* persistMessageForNonDefaultSmsApp */);
1013f3166841bf9df142e2fbd63b7647bae7da712044Xia Ying            }
1014f3166841bf9df142e2fbd63b7647bae7da712044Xia Ying            return;
1015f3166841bf9df142e2fbd63b7647bae7da712044Xia Ying        }
1016f3166841bf9df142e2fbd63b7647bae7da712044Xia Ying
1017b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen        mDispatcher.sendMultipartText(
1018b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen                textAndAddress[1], // destAddress
1019b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen                scAddress,
1020b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen                parts,
1021b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen                (ArrayList<PendingIntent>) sentIntents,
1022b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen                (ArrayList<PendingIntent>) deliveryIntents,
1023b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen                messageUri,
1024a8f8c5a113a66de4854f4fb13a5825eb0705bd59Ji Yang                callingPkg,
1025a8f8c5a113a66de4854f4fb13a5825eb0705bd59Ji Yang                true  /* persistMessageForNonDefaultSmsApp */);
1026b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen    }
1027b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen
1028b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen    private boolean isFailedOrDraft(ContentResolver resolver, Uri messageUri) {
102949754105adf232419410cfca7507aa63a9d05e3bYe Wen        // Clear the calling identity and query the database using the phone user id
103049754105adf232419410cfca7507aa63a9d05e3bYe Wen        // Otherwise the AppOps check in TelephonyProvider would complain about mismatch
103149754105adf232419410cfca7507aa63a9d05e3bYe Wen        // between the calling uid and the package uid
103249754105adf232419410cfca7507aa63a9d05e3bYe Wen        final long identity = Binder.clearCallingIdentity();
1033b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen        Cursor cursor = null;
1034b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen        try {
1035b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen            cursor = resolver.query(
1036b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen                    messageUri,
1037b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen                    new String[]{ Telephony.Sms.TYPE },
1038b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen                    null/*selection*/,
1039b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen                    null/*selectionArgs*/,
1040b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen                    null/*sortOrder*/);
1041b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen            if (cursor != null && cursor.moveToFirst()) {
1042b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen                final int type = cursor.getInt(0);
1043b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen                return type == Telephony.Sms.MESSAGE_TYPE_DRAFT
1044b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen                        || type == Telephony.Sms.MESSAGE_TYPE_FAILED;
1045b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen            }
1046b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen        } catch (SQLiteException e) {
1047b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen            Log.e(LOG_TAG, "[IccSmsInterfaceManager]isFailedOrDraft: query message type failed", e);
1048b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen        } finally {
1049b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen            if (cursor != null) {
1050b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen                cursor.close();
1051b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen            }
105249754105adf232419410cfca7507aa63a9d05e3bYe Wen            Binder.restoreCallingIdentity(identity);
1053b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen        }
1054b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen        return false;
1055b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen    }
1056b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen
1057b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen    // Return an array including both the SMS text (0) and address (1)
1058b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen    private String[] loadTextAndAddress(ContentResolver resolver, Uri messageUri) {
105949754105adf232419410cfca7507aa63a9d05e3bYe Wen        // Clear the calling identity and query the database using the phone user id
106049754105adf232419410cfca7507aa63a9d05e3bYe Wen        // Otherwise the AppOps check in TelephonyProvider would complain about mismatch
106149754105adf232419410cfca7507aa63a9d05e3bYe Wen        // between the calling uid and the package uid
106249754105adf232419410cfca7507aa63a9d05e3bYe Wen        final long identity = Binder.clearCallingIdentity();
1063b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen        Cursor cursor = null;
1064b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen        try {
1065b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen            cursor = resolver.query(
1066b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen                    messageUri,
1067b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen                    new String[]{
1068b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen                            Telephony.Sms.BODY,
1069b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen                            Telephony.Sms.ADDRESS
1070b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen                    },
1071b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen                    null/*selection*/,
1072b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen                    null/*selectionArgs*/,
1073b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen                    null/*sortOrder*/);
1074b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen            if (cursor != null && cursor.moveToFirst()) {
1075b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen                return new String[]{ cursor.getString(0), cursor.getString(1) };
1076b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen            }
1077b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen        } catch (SQLiteException e) {
1078b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen            Log.e(LOG_TAG, "[IccSmsInterfaceManager]loadText: query message text failed", e);
1079b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen        } finally {
1080b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen            if (cursor != null) {
1081b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen                cursor.close();
1082b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen            }
108349754105adf232419410cfca7507aa63a9d05e3bYe Wen            Binder.restoreCallingIdentity(identity);
1084b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen        }
1085b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen        return null;
1086b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen    }
1087b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen
1088b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen    private void returnUnspecifiedFailure(PendingIntent pi) {
1089b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen        if (pi != null) {
1090b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen            try {
1091b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen                pi.send(SmsManager.RESULT_ERROR_GENERIC_FAILURE);
1092b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen            } catch (PendingIntent.CanceledException e) {
1093b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen                // ignore
1094b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen            }
1095b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen        }
1096b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen    }
1097b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen
1098b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen    private void returnUnspecifiedFailure(List<PendingIntent> pis) {
1099b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen        if (pis == null) {
1100b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen            return;
1101b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen        }
1102b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen        for (PendingIntent pi : pis) {
1103b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen            returnUnspecifiedFailure(pi);
1104b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen        }
1105b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen    }
1106c9394399180abbc32d04f6a3652ce22d5931e0b8Shishir Agrawal
1107c9394399180abbc32d04f6a3652ce22d5931e0b8Shishir Agrawal    private void enforceCarrierPrivilege() {
110868515b655255005f653aec29e9f152412514982aShishir Agrawal        UiccController controller = UiccController.getInstance();
1109062a2a3838c8d8adf16f4d9fbde8d52450da0336Shishir Agrawal        if (controller == null || controller.getUiccCard(mPhone.getPhoneId()) == null) {
111068515b655255005f653aec29e9f152412514982aShishir Agrawal            throw new SecurityException("No Carrier Privilege: No UICC");
111168515b655255005f653aec29e9f152412514982aShishir Agrawal        }
1112062a2a3838c8d8adf16f4d9fbde8d52450da0336Shishir Agrawal        if (controller.getUiccCard(mPhone.getPhoneId()).getCarrierPrivilegeStatusForCurrentTransaction(
1113c9394399180abbc32d04f6a3652ce22d5931e0b8Shishir Agrawal                mContext.getPackageManager()) !=
1114c9394399180abbc32d04f6a3652ce22d5931e0b8Shishir Agrawal                    TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) {
1115c9394399180abbc32d04f6a3652ce22d5931e0b8Shishir Agrawal            throw new SecurityException("No Carrier Privilege.");
1116c9394399180abbc32d04f6a3652ce22d5931e0b8Shishir Agrawal        }
1117c9394399180abbc32d04f6a3652ce22d5931e0b8Shishir Agrawal    }
111870dad6e7c56847c91bc55755c645680ea6c6fac3Xia Ying
1119532c5ffb1d1ba6a3d642a21c107fd578ae64ef1cAbhijith Shastry    /**
1120a700124bf726680fe96675ab7f558e524fc024c9Abhijith Shastry     * Enforces that the caller has {@link android.Manifest.permission#MODIFY_PHONE_STATE}
1121a700124bf726680fe96675ab7f558e524fc024c9Abhijith Shastry     * permission or is one of the following apps:
1122532c5ffb1d1ba6a3d642a21c107fd578ae64ef1cAbhijith Shastry     * <ul>
1123532c5ffb1d1ba6a3d642a21c107fd578ae64ef1cAbhijith Shastry     *     <li> IMS App
1124532c5ffb1d1ba6a3d642a21c107fd578ae64ef1cAbhijith Shastry     *     <li> Carrier App
1125532c5ffb1d1ba6a3d642a21c107fd578ae64ef1cAbhijith Shastry     * </ul>
1126532c5ffb1d1ba6a3d642a21c107fd578ae64ef1cAbhijith Shastry     */
1127532c5ffb1d1ba6a3d642a21c107fd578ae64ef1cAbhijith Shastry    private void enforcePrivilegedAppPermissions() {
1128a700124bf726680fe96675ab7f558e524fc024c9Abhijith Shastry        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
1129a700124bf726680fe96675ab7f558e524fc024c9Abhijith Shastry                == PackageManager.PERMISSION_GRANTED) {
1130532c5ffb1d1ba6a3d642a21c107fd578ae64ef1cAbhijith Shastry            return;
1131532c5ffb1d1ba6a3d642a21c107fd578ae64ef1cAbhijith Shastry        }
1132532c5ffb1d1ba6a3d642a21c107fd578ae64ef1cAbhijith Shastry
1133a700124bf726680fe96675ab7f558e524fc024c9Abhijith Shastry        int callingUid = Binder.getCallingUid();
11344256e499c8e1e0a07998dcaf1f3aa127b693fc42Madhusudhan R. Adupala        String carrierImsPackage = CarrierSmsUtils.getCarrierImsPackageForIntent(mContext, mPhone,
11354256e499c8e1e0a07998dcaf1f3aa127b693fc42Madhusudhan R. Adupala                new Intent(CarrierMessagingService.SERVICE_INTERFACE));
11364256e499c8e1e0a07998dcaf1f3aa127b693fc42Madhusudhan R. Adupala        try {
11374256e499c8e1e0a07998dcaf1f3aa127b693fc42Madhusudhan R. Adupala            if (carrierImsPackage != null
11384256e499c8e1e0a07998dcaf1f3aa127b693fc42Madhusudhan R. Adupala                    && callingUid == mContext.getPackageManager().getPackageUid(
11394256e499c8e1e0a07998dcaf1f3aa127b693fc42Madhusudhan R. Adupala                            carrierImsPackage, 0)) {
11404256e499c8e1e0a07998dcaf1f3aa127b693fc42Madhusudhan R. Adupala              return;
11414256e499c8e1e0a07998dcaf1f3aa127b693fc42Madhusudhan R. Adupala            }
11424256e499c8e1e0a07998dcaf1f3aa127b693fc42Madhusudhan R. Adupala        } catch (PackageManager.NameNotFoundException e) {
11434256e499c8e1e0a07998dcaf1f3aa127b693fc42Madhusudhan R. Adupala            if (Rlog.isLoggable("SMS", Log.DEBUG)) {
11444256e499c8e1e0a07998dcaf1f3aa127b693fc42Madhusudhan R. Adupala                log("Cannot find configured carrier ims package");
11454256e499c8e1e0a07998dcaf1f3aa127b693fc42Madhusudhan R. Adupala            }
11464256e499c8e1e0a07998dcaf1f3aa127b693fc42Madhusudhan R. Adupala        }
1147a700124bf726680fe96675ab7f558e524fc024c9Abhijith Shastry
11484256e499c8e1e0a07998dcaf1f3aa127b693fc42Madhusudhan R. Adupala        enforceCarrierPrivilege();
11494256e499c8e1e0a07998dcaf1f3aa127b693fc42Madhusudhan R. Adupala    }
11504256e499c8e1e0a07998dcaf1f3aa127b693fc42Madhusudhan R. Adupala
115170dad6e7c56847c91bc55755c645680ea6c6fac3Xia Ying    private String filterDestAddress(String destAddr) {
115270dad6e7c56847c91bc55755c645680ea6c6fac3Xia Ying        String result  = null;
11533c36d8029ea2c92e0339cd0cbe26511e5478da09Xia Ying        result = SmsNumberUtils.filterDestAddr(mPhone, destAddr);
115470dad6e7c56847c91bc55755c645680ea6c6fac3Xia Ying        return result != null ? result : destAddr;
115570dad6e7c56847c91bc55755c645680ea6c6fac3Xia Ying    }
115670dad6e7c56847c91bc55755c645680ea6c6fac3Xia Ying
11570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville}
1158