10825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville/*
20825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville** Copyright 2007, 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.gsm;
180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
190825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.content.Context;
200825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.content.pm.PackageManager;
210825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.os.AsyncResult;
220825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.os.Binder;
230825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.os.Handler;
240825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.os.Message;
250825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.util.Log;
260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
270825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.internal.telephony.IccConstants;
280825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.internal.telephony.IccSmsInterfaceManager;
290825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.internal.telephony.IccUtils;
300825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.internal.telephony.IntRangeManager;
310825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.internal.telephony.SMSDispatcher;
320825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.internal.telephony.SmsRawData;
330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
340825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport java.util.ArrayList;
350825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport java.util.Arrays;
360825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport java.util.HashMap;
370825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport java.util.HashSet;
380825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport java.util.List;
390825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport java.util.Set;
400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
410825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport static android.telephony.SmsManager.STATUS_ON_ICC_FREE;
420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville/**
440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * SimSmsInterfaceManager to provide an inter-process communication to
450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * access Sms in Sim.
460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */
470825495a331bb44df395a0cdb79fab85e68db5d5Wink Savillepublic class SimSmsInterfaceManager extends IccSmsInterfaceManager {
480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    static final String LOG_TAG = "GSM";
490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    static final boolean DBG = true;
500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private final Object mLock = new Object();
520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private boolean mSuccess;
530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private List<SmsRawData> mSms;
540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private HashMap<Integer, HashSet<String>> mCellBroadcastSubscriptions =
550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            new HashMap<Integer, HashSet<String>>();
560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private CellBroadcastRangeManager mCellBroadcastRangeManager =
580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            new CellBroadcastRangeManager();
590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private static final int EVENT_LOAD_DONE = 1;
610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private static final int EVENT_UPDATE_DONE = 2;
620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private static final int EVENT_SET_BROADCAST_ACTIVATION_DONE = 3;
630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private static final int EVENT_SET_BROADCAST_CONFIG_DONE = 4;
640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private static final int SMS_CB_CODE_SCHEME_MIN = 0;
650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private static final int SMS_CB_CODE_SCHEME_MAX = 255;
660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    Handler mHandler = new Handler() {
680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        @Override
690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        public void handleMessage(Message msg) {
700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            AsyncResult ar;
710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            switch (msg.what) {
730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                case EVENT_UPDATE_DONE:
740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    ar = (AsyncResult) msg.obj;
750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    synchronized (mLock) {
760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        mSuccess = (ar.exception == null);
770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        mLock.notifyAll();
780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    }
790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    break;
800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                case EVENT_LOAD_DONE:
810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    ar = (AsyncResult)msg.obj;
820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    synchronized (mLock) {
830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        if (ar.exception == null) {
840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                            mSms  = buildValidRawData((ArrayList<byte[]>) ar.result);
850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        } else {
860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                            if(DBG) log("Cannot load Sms records");
870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                            if (mSms != null)
880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                                mSms.clear();
890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        }
900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        mLock.notifyAll();
910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    }
920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    break;
930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                case EVENT_SET_BROADCAST_ACTIVATION_DONE:
940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                case EVENT_SET_BROADCAST_CONFIG_DONE:
950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    ar = (AsyncResult) msg.obj;
960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    synchronized (mLock) {
970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        mSuccess = (ar.exception == null);
980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        mLock.notifyAll();
990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    }
1000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    break;
1010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            }
1020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
1030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    };
1040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public SimSmsInterfaceManager(GSMPhone phone, SMSDispatcher dispatcher) {
1060825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        super(phone);
1070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        mDispatcher = dispatcher;
1080825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
1090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public void dispose() {
1110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
1120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    @Override
1140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    protected void finalize() {
1150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        try {
1160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            super.finalize();
1170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        } catch (Throwable throwable) {
1180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            Log.e(LOG_TAG, "Error while finalizing:", throwable);
1190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
1200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if(DBG) Log.d(LOG_TAG, "SimSmsInterfaceManager finalized");
1210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
1220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /**
1240825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * Update the specified message on the SIM.
1250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *
1260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * @param index record index of message to update
1270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * @param status new message status (STATUS_ON_ICC_READ,
1280825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *                  STATUS_ON_ICC_UNREAD, STATUS_ON_ICC_SENT,
1290825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *                  STATUS_ON_ICC_UNSENT, STATUS_ON_ICC_FREE)
1300825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * @param pdu the raw PDU to store
1310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * @return success or not
1320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *
1330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     */
1340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public boolean
1350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    updateMessageOnIccEf(int index, int status, byte[] pdu) {
1360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (DBG) log("updateMessageOnIccEf: index=" + index +
1370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                " status=" + status + " ==> " +
1380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                "("+ Arrays.toString(pdu) + ")");
1390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        enforceReceiveAndSend("Updating message on SIM");
1400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        synchronized(mLock) {
1410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            mSuccess = false;
1420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            Message response = mHandler.obtainMessage(EVENT_UPDATE_DONE);
1430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            if (status == STATUS_ON_ICC_FREE) {
1450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                // Special case FREE: call deleteSmsOnSim instead of
1460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                // manipulating the SIM record
1470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                mPhone.mCM.deleteSmsOnSim(index, response);
1480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            } else {
1490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                byte[] record = makeSmsRecordData(status, pdu);
1500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                mPhone.getIccFileHandler().updateEFLinearFixed(
1510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        IccConstants.EF_SMS,
1520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        index, record, null, response);
1530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            }
1540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            try {
1550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                mLock.wait();
1560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            } catch (InterruptedException e) {
1570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                log("interrupted while trying to update by index");
1580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            }
1590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
1600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        return mSuccess;
1610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
1620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /**
1640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * Copy a raw SMS PDU to the SIM.
1650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *
1660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * @param pdu the raw PDU to store
1670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * @param status message status (STATUS_ON_ICC_READ, STATUS_ON_ICC_UNREAD,
1680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *               STATUS_ON_ICC_SENT, STATUS_ON_ICC_UNSENT)
1690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * @return success or not
1700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *
1710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     */
1720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public boolean copyMessageToIccEf(int status, byte[] pdu, byte[] smsc) {
1730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (DBG) log("copyMessageToIccEf: status=" + status + " ==> " +
1740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                "pdu=("+ Arrays.toString(pdu) +
1750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                "), smsm=(" + Arrays.toString(smsc) +")");
1760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        enforceReceiveAndSend("Copying message to SIM");
1770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        synchronized(mLock) {
1780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            mSuccess = false;
1790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            Message response = mHandler.obtainMessage(EVENT_UPDATE_DONE);
1800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            mPhone.mCM.writeSmsToSim(status, IccUtils.bytesToHexString(smsc),
1820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    IccUtils.bytesToHexString(pdu), response);
1830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            try {
1850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                mLock.wait();
1860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            } catch (InterruptedException e) {
1870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                log("interrupted while trying to update by index");
1880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            }
1890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
1900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        return mSuccess;
1910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
1920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /**
1940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * Retrieves all messages currently stored on ICC.
1950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *
1960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * @return list of SmsRawData of all sms on ICC
1970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     */
1980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public List<SmsRawData> getAllMessagesFromIccEf() {
1990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (DBG) log("getAllMessagesFromEF");
2000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
2010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        Context context = mPhone.getContext();
2020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
2030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        context.enforceCallingPermission(
2040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                "android.permission.RECEIVE_SMS",
2050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                "Reading messages from SIM");
2060825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        synchronized(mLock) {
2070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            Message response = mHandler.obtainMessage(EVENT_LOAD_DONE);
2080825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            mPhone.getIccFileHandler().loadEFLinearFixedAll(IccConstants.EF_SMS, response);
2090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
2100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            try {
2110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                mLock.wait();
2120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            } catch (InterruptedException e) {
2130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                log("interrupted while trying to load from the SIM");
2140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            }
2150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
2160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        return mSms;
2170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
2180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
2190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public boolean enableCellBroadcast(int messageIdentifier) {
2200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        return enableCellBroadcastRange(messageIdentifier, messageIdentifier);
2210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
2220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
2230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public boolean disableCellBroadcast(int messageIdentifier) {
2240825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        return disableCellBroadcastRange(messageIdentifier, messageIdentifier);
2250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
2260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
2270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public boolean enableCellBroadcastRange(int startMessageId, int endMessageId) {
2280825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (DBG) log("enableCellBroadcastRange");
2290825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
2300825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        Context context = mPhone.getContext();
2310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
2320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        context.enforceCallingPermission(
2330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                "android.permission.RECEIVE_SMS",
2340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                "Enabling cell broadcast SMS");
2350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
2360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        String client = context.getPackageManager().getNameForUid(
2370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                Binder.getCallingUid());
2380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
2390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (!mCellBroadcastRangeManager.enableRange(startMessageId, endMessageId, client)) {
2400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            log("Failed to add cell broadcast subscription for MID range " + startMessageId
2410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    + " to " + endMessageId + " from client " + client);
2420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            return false;
2430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
2440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
2450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (DBG)
2460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            log("Added cell broadcast subscription for MID range " + startMessageId
2470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    + " to " + endMessageId + " from client " + client);
2480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
2490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        setCellBroadcastActivation(!mCellBroadcastRangeManager.isEmpty());
2500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
2510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        return true;
2520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
2530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
2540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public boolean disableCellBroadcastRange(int startMessageId, int endMessageId) {
2550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (DBG) log("disableCellBroadcastRange");
2560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
2570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        Context context = mPhone.getContext();
2580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
2590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        context.enforceCallingPermission(
2600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                "android.permission.RECEIVE_SMS",
2610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                "Disabling cell broadcast SMS");
2620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
2630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        String client = context.getPackageManager().getNameForUid(
2640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                Binder.getCallingUid());
2650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
2660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (!mCellBroadcastRangeManager.disableRange(startMessageId, endMessageId, client)) {
2670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            log("Failed to remove cell broadcast subscription for MID range " + startMessageId
2680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    + " to " + endMessageId + " from client " + client);
2690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            return false;
2700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
2710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
2720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (DBG)
2730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            log("Removed cell broadcast subscription for MID range " + startMessageId
2740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    + " to " + endMessageId + " from client " + client);
2750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
2760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        setCellBroadcastActivation(!mCellBroadcastRangeManager.isEmpty());
2770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
2780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        return true;
2790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
2800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
2810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    class CellBroadcastRangeManager extends IntRangeManager {
2820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        private ArrayList<SmsBroadcastConfigInfo> mConfigList =
2830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                new ArrayList<SmsBroadcastConfigInfo>();
2840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
2850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        /**
2860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville         * Called when the list of enabled ranges has changed. This will be
2870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville         * followed by zero or more calls to {@link #addRange} followed by
2880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville         * a call to {@link #finishUpdate}.
2890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville         */
2900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        protected void startUpdate() {
2910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            mConfigList.clear();
2920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
2930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
2940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        /**
2950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville         * Called after {@link #startUpdate} to indicate a range of enabled
2960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville         * values.
2970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville         * @param startId the first id included in the range
2980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville         * @param endId the last id included in the range
2990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville         */
3000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        protected void addRange(int startId, int endId, boolean selected) {
3010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            mConfigList.add(new SmsBroadcastConfigInfo(startId, endId,
3020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        SMS_CB_CODE_SCHEME_MIN, SMS_CB_CODE_SCHEME_MAX, selected));
3030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
3040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        /**
3060825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville         * Called to indicate the end of a range update started by the
3070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville         * previous call to {@link #startUpdate}.
3080825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville         * @return true if successful, false otherwise
3090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville         */
3100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        protected boolean finishUpdate() {
3110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            if (mConfigList.isEmpty()) {
3120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                return true;
3130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            } else {
3140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                SmsBroadcastConfigInfo[] configs =
3150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        mConfigList.toArray(new SmsBroadcastConfigInfo[mConfigList.size()]);
3160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                return setCellBroadcastConfig(configs);
3170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            }
3180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
3190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
3200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private boolean setCellBroadcastConfig(SmsBroadcastConfigInfo[] configs) {
3220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (DBG)
3230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            log("Calling setGsmBroadcastConfig with " + configs.length + " configurations");
3240825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        synchronized (mLock) {
3260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            Message response = mHandler.obtainMessage(EVENT_SET_BROADCAST_CONFIG_DONE);
3270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3280825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            mSuccess = false;
3290825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            mPhone.mCM.setGsmBroadcastConfig(configs, response);
3300825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            try {
3320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                mLock.wait();
3330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            } catch (InterruptedException e) {
3340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                log("interrupted while trying to set cell broadcast config");
3350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            }
3360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
3370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        return mSuccess;
3390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
3400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private boolean setCellBroadcastActivation(boolean activate) {
3420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (DBG)
3430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            log("Calling setCellBroadcastActivation(" + activate + ')');
3440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        synchronized (mLock) {
3460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            Message response = mHandler.obtainMessage(EVENT_SET_BROADCAST_ACTIVATION_DONE);
3470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            mSuccess = false;
3490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            mPhone.mCM.setGsmBroadcastActivation(activate, response);
3500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            try {
3520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                mLock.wait();
3530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            } catch (InterruptedException e) {
3540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                log("interrupted while trying to set cell broadcast activation");
3550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            }
3560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
3570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        return mSuccess;
3590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
3600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    @Override
3620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    protected void log(String msg) {
3630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        Log.d(LOG_TAG, "[SimSmsInterfaceManager] " + msg);
3640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
3650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville}
366