FileDocCategorySizeDatePackage
IccSmsInterfaceManager.javaAPI DocAndroid 5.1 API42970Thu Mar 12 22:22:54 GMT 2015com.android.internal.telephony

IccSmsInterfaceManager

public class IccSmsInterfaceManager extends Object
IccSmsInterfaceManager to provide an inter-process communication to access Sms in Icc.

Fields Summary
static final String
LOG_TAG
static final boolean
DBG
protected final Object
mLock
protected boolean
mSuccess
private List
mSms
private CellBroadcastRangeManager
mCellBroadcastRangeManager
private CdmaBroadcastRangeManager
mCdmaBroadcastRangeManager
private static final int
EVENT_LOAD_DONE
private static final int
EVENT_UPDATE_DONE
protected static final int
EVENT_SET_BROADCAST_ACTIVATION_DONE
protected static final int
EVENT_SET_BROADCAST_CONFIG_DONE
private static final int
SMS_CB_CODE_SCHEME_MIN
private static final int
SMS_CB_CODE_SCHEME_MAX
protected PhoneBase
mPhone
protected final android.content.Context
mContext
protected final android.app.AppOpsManager
mAppOps
private final android.os.UserManager
mUserManager
protected SMSDispatcher
mDispatcher
protected android.os.Handler
mHandler
Constructors Summary
protected IccSmsInterfaceManager(PhoneBase phone)


       
        mPhone = phone;
        mContext = phone.getContext();
        mAppOps = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE);
        mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
        mDispatcher = new ImsSMSDispatcher(phone,
                phone.mSmsStorageMonitor, phone.mSmsUsageMonitor);
    
Methods Summary
protected java.util.ArrayListbuildValidRawData(java.util.ArrayList messages)
create SmsRawData lists from all sms record byte[] Use null to indicate "free" record

param
messages List of message records from EF_SMS.
return
SmsRawData list of all in-used records

        int count = messages.size();
        ArrayList<SmsRawData> ret;

        ret = new ArrayList<SmsRawData>(count);

        for (int i = 0; i < count; i++) {
            byte[] ba = messages.get(i);
            if (ba[0] == STATUS_ON_ICC_FREE) {
                ret.add(null);
            } else {
                ret.add(new SmsRawData(messages.get(i)));
            }
        }

        return ret;
    
public booleancopyMessageToIccEf(java.lang.String callingPackage, int status, byte[] pdu, byte[] smsc)
Copy a raw SMS PDU to the Icc.

param
pdu the raw PDU to store
param
status message status (STATUS_ON_ICC_READ, STATUS_ON_ICC_UNREAD, STATUS_ON_ICC_SENT, STATUS_ON_ICC_UNSENT)
return
success or not

        //NOTE smsc not used in RUIM
        if (DBG) log("copyMessageToIccEf: status=" + status + " ==> " +
                "pdu=("+ Arrays.toString(pdu) +
                "), smsc=(" + Arrays.toString(smsc) +")");
        enforceReceiveAndSend("Copying message to Icc");
        if (mAppOps.noteOp(AppOpsManager.OP_WRITE_ICC_SMS, Binder.getCallingUid(),
                callingPackage) != AppOpsManager.MODE_ALLOWED) {
            return false;
        }
        synchronized(mLock) {
            mSuccess = false;
            Message response = mHandler.obtainMessage(EVENT_UPDATE_DONE);

            //RIL_REQUEST_WRITE_SMS_TO_SIM vs RIL_REQUEST_CDMA_WRITE_SMS_TO_RUIM
            if (PhoneConstants.PHONE_TYPE_GSM == mPhone.getPhoneType()) {
                mPhone.mCi.writeSmsToSim(status, IccUtils.bytesToHexString(smsc),
                        IccUtils.bytesToHexString(pdu), response);
            } else {
                mPhone.mCi.writeSmsToRuim(status, IccUtils.bytesToHexString(pdu),
                        response);
            }

            try {
                mLock.wait();
            } catch (InterruptedException e) {
                log("interrupted while trying to update by index");
            }
        }
        return mSuccess;
    
public synchronized booleandisableCdmaBroadcastRange(int startMessageId, int endMessageId)

        if (DBG) log("disableCdmaBroadcastRange");

        Context context = mPhone.getContext();

        context.enforceCallingPermission(
                "android.permission.RECEIVE_SMS",
                "Disabling cell broadcast SMS");

        String client = context.getPackageManager().getNameForUid(
                Binder.getCallingUid());

        if (!mCdmaBroadcastRangeManager.disableRange(startMessageId, endMessageId, client)) {
            log("Failed to remove cdma broadcast subscription for MID range " + startMessageId
                    + " to " + endMessageId + " from client " + client);
            return false;
        }

        if (DBG)
            log("Removed cdma broadcast subscription for MID range " + startMessageId
                    + " to " + endMessageId + " from client " + client);

        setCdmaBroadcastActivation(!mCdmaBroadcastRangeManager.isEmpty());

        return true;
    
public booleandisableCellBroadcast(int messageIdentifier, int ranType)

        return disableCellBroadcastRange(messageIdentifier, messageIdentifier, ranType);
    
public booleandisableCellBroadcastRange(int startMessageId, int endMessageId, int ranType)

        if (ranType == SmsManager.CELL_BROADCAST_RAN_TYPE_GSM ) {
            return disableGsmBroadcastRange(startMessageId, endMessageId);
        } else if (ranType == SmsManager.CELL_BROADCAST_RAN_TYPE_CDMA)  {
            return disableCdmaBroadcastRange(startMessageId, endMessageId);
        } else {
            throw new IllegalArgumentException("Not a supportted RAN Type");
        }
    
public synchronized booleandisableGsmBroadcastRange(int startMessageId, int endMessageId)

        if (DBG) log("disableGsmBroadcastRange");

        Context context = mPhone.getContext();

        context.enforceCallingPermission(
                "android.permission.RECEIVE_SMS",
                "Disabling cell broadcast SMS");

        String client = context.getPackageManager().getNameForUid(
                Binder.getCallingUid());

        if (!mCellBroadcastRangeManager.disableRange(startMessageId, endMessageId, client)) {
            log("Failed to remove GSM cell broadcast subscription for MID range " + startMessageId
                    + " to " + endMessageId + " from client " + client);
            return false;
        }

        if (DBG)
            log("Removed GSM cell broadcast subscription for MID range " + startMessageId
                    + " to " + endMessageId + " from client " + client);

        setCellBroadcastActivation(!mCellBroadcastRangeManager.isEmpty());

        return true;
    
public synchronized booleanenableCdmaBroadcastRange(int startMessageId, int endMessageId)

        if (DBG) log("enableCdmaBroadcastRange");

        Context context = mPhone.getContext();

        context.enforceCallingPermission(
                "android.permission.RECEIVE_SMS",
                "Enabling cdma broadcast SMS");

        String client = context.getPackageManager().getNameForUid(
                Binder.getCallingUid());

        if (!mCdmaBroadcastRangeManager.enableRange(startMessageId, endMessageId, client)) {
            log("Failed to add cdma broadcast subscription for MID range " + startMessageId
                    + " to " + endMessageId + " from client " + client);
            return false;
        }

        if (DBG)
            log("Added cdma broadcast subscription for MID range " + startMessageId
                    + " to " + endMessageId + " from client " + client);

        setCdmaBroadcastActivation(!mCdmaBroadcastRangeManager.isEmpty());

        return true;
    
public booleanenableCellBroadcast(int messageIdentifier, int ranType)

        return enableCellBroadcastRange(messageIdentifier, messageIdentifier, ranType);
    
public booleanenableCellBroadcastRange(int startMessageId, int endMessageId, int ranType)

        if (ranType == SmsManager.CELL_BROADCAST_RAN_TYPE_GSM) {
            return enableGsmBroadcastRange(startMessageId, endMessageId);
        } else if (ranType == SmsManager.CELL_BROADCAST_RAN_TYPE_CDMA) {
            return enableCdmaBroadcastRange(startMessageId, endMessageId);
        } else {
            throw new IllegalArgumentException("Not a supportted RAN Type");
        }
    
public synchronized booleanenableGsmBroadcastRange(int startMessageId, int endMessageId)

        if (DBG) log("enableGsmBroadcastRange");

        Context context = mPhone.getContext();

        context.enforceCallingPermission(
                "android.permission.RECEIVE_SMS",
                "Enabling cell broadcast SMS");

        String client = context.getPackageManager().getNameForUid(
                Binder.getCallingUid());

        if (!mCellBroadcastRangeManager.enableRange(startMessageId, endMessageId, client)) {
            log("Failed to add GSM cell broadcast subscription for MID range " + startMessageId
                    + " to " + endMessageId + " from client " + client);
            return false;
        }

        if (DBG)
            log("Added GSM cell broadcast subscription for MID range " + startMessageId
                    + " to " + endMessageId + " from client " + client);

        setCellBroadcastActivation(!mCellBroadcastRangeManager.isEmpty());

        return true;
    
private voidenforceCarrierPrivilege()

        UiccController controller = UiccController.getInstance();
        if (controller == null || controller.getUiccCard(mPhone.getPhoneId()) == null) {
            throw new SecurityException("No Carrier Privilege: No UICC");
        }
        if (controller.getUiccCard(mPhone.getPhoneId()).getCarrierPrivilegeStatusForCurrentTransaction(
                mContext.getPackageManager()) !=
                    TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) {
            throw new SecurityException("No Carrier Privilege.");
        }
    
protected voidenforceReceiveAndSend(java.lang.String message)

        mContext.enforceCallingOrSelfPermission(
                Manifest.permission.RECEIVE_SMS, message);
        mContext.enforceCallingOrSelfPermission(
                Manifest.permission.SEND_SMS, message);
    
private java.lang.StringfilterDestAddress(java.lang.String destAddr)

        String result  = null;
        result = SmsNumberUtils.filterDestAddr(mPhone, destAddr);
        return result != null ? result : destAddr;
    
public java.util.ListgetAllMessagesFromIccEf(java.lang.String callingPackage)
Retrieves all messages currently stored on Icc.

return
list of SmsRawData of all sms on Icc

        if (DBG) log("getAllMessagesFromEF");

        mContext.enforceCallingOrSelfPermission(
                Manifest.permission.RECEIVE_SMS,
                "Reading messages from Icc");
        if (mAppOps.noteOp(AppOpsManager.OP_READ_ICC_SMS, Binder.getCallingUid(),
                callingPackage) != AppOpsManager.MODE_ALLOWED) {
            return new ArrayList<SmsRawData>();
        }
        synchronized(mLock) {

            IccFileHandler fh = mPhone.getIccFileHandler();
            if (fh == null) {
                Rlog.e(LOG_TAG, "Cannot load Sms records. No icc card?");
                if (mSms != null) {
                    mSms.clear();
                    return mSms;
                }
            }

            Message response = mHandler.obtainMessage(EVENT_LOAD_DONE);
            fh.loadEFLinearFixedAll(IccConstants.EF_SMS, response);

            try {
                mLock.wait();
            } catch (InterruptedException e) {
                log("interrupted while trying to load from the Icc");
            }
        }
        return mSms;
    
public java.lang.StringgetImsSmsFormat()

        return mDispatcher.getImsSmsFormat();
    
public intgetPremiumSmsPermission(java.lang.String packageName)

        return mDispatcher.getPremiumSmsPermission(packageName);
    
public voidinjectSmsPdu(byte[] pdu, java.lang.String format, android.app.PendingIntent receivedIntent)
Inject an SMS PDU into the android application framework.

param
pdu is the byte array of pdu to be injected into android application framework
param
format is the format of SMS pdu (3gpp or 3gpp2)
param
receivedIntent if not NULL this PendingIntent is broadcast when the message is successfully received by the android application framework. This intent is broadcasted at the same time an SMS received from radio is acknowledged back.

        enforceCarrierPrivilege();
        if (Rlog.isLoggable("SMS", Log.VERBOSE)) {
            log("pdu: " + pdu +
                "\n format=" + format +
                "\n receivedIntent=" + receivedIntent);
        }
        mDispatcher.injectSmsPdu(pdu, format, receivedIntent);
    
private booleanisFailedOrDraft(android.content.ContentResolver resolver, android.net.Uri messageUri)

        // Clear the calling identity and query the database using the phone user id
        // Otherwise the AppOps check in TelephonyProvider would complain about mismatch
        // between the calling uid and the package uid
        final long identity = Binder.clearCallingIdentity();
        Cursor cursor = null;
        try {
            cursor = resolver.query(
                    messageUri,
                    new String[]{ Telephony.Sms.TYPE },
                    null/*selection*/,
                    null/*selectionArgs*/,
                    null/*sortOrder*/);
            if (cursor != null && cursor.moveToFirst()) {
                final int type = cursor.getInt(0);
                return type == Telephony.Sms.MESSAGE_TYPE_DRAFT
                        || type == Telephony.Sms.MESSAGE_TYPE_FAILED;
            }
        } catch (SQLiteException e) {
            Log.e(LOG_TAG, "[IccSmsInterfaceManager]isFailedOrDraft: query message type failed", e);
        } finally {
            if (cursor != null) {
                cursor.close();
            }
            Binder.restoreCallingIdentity(identity);
        }
        return false;
    
public booleanisImsSmsSupported()

        return mDispatcher.isIms();
    
private java.lang.String[]loadTextAndAddress(android.content.ContentResolver resolver, android.net.Uri messageUri)

        // Clear the calling identity and query the database using the phone user id
        // Otherwise the AppOps check in TelephonyProvider would complain about mismatch
        // between the calling uid and the package uid
        final long identity = Binder.clearCallingIdentity();
        Cursor cursor = null;
        try {
            cursor = resolver.query(
                    messageUri,
                    new String[]{
                            Telephony.Sms.BODY,
                            Telephony.Sms.ADDRESS
                    },
                    null/*selection*/,
                    null/*selectionArgs*/,
                    null/*sortOrder*/);
            if (cursor != null && cursor.moveToFirst()) {
                return new String[]{ cursor.getString(0), cursor.getString(1) };
            }
        } catch (SQLiteException e) {
            Log.e(LOG_TAG, "[IccSmsInterfaceManager]loadText: query message text failed", e);
        } finally {
            if (cursor != null) {
                cursor.close();
            }
            Binder.restoreCallingIdentity(identity);
        }
        return null;
    
protected voidlog(java.lang.String msg)

        Log.d(LOG_TAG, "[IccSmsInterfaceManager] " + msg);
    
protected byte[]makeSmsRecordData(int status, byte[] pdu)
Generates an EF_SMS record from status and raw PDU.

param
status Message status. See TS 51.011 10.5.3.
param
pdu Raw message PDU.
return
byte array for the record.

        byte[] data;
        if (PhoneConstants.PHONE_TYPE_GSM == mPhone.getPhoneType()) {
            data = new byte[IccConstants.SMS_RECORD_LENGTH];
        } else {
            data = new byte[IccConstants.CDMA_SMS_RECORD_LENGTH];
        }

        // Status bits for this record.  See TS 51.011 10.5.3
        data[0] = (byte)(status & 7);

        System.arraycopy(pdu, 0, data, 1, pdu.length);

        // Pad out with 0xFF's.
        for (int j = pdu.length+1; j < data.length; j++) {
            data[j] = -1;
        }

        return data;
    
protected voidmarkMessagesAsRead(java.util.ArrayList messages)

        if (messages == null) {
            return;
        }

        //IccFileHandler can be null, if icc card is absent.
        IccFileHandler fh = mPhone.getIccFileHandler();
        if (fh == null) {
            //shouldn't really happen, as messages are marked as read, only
            //after importing it from icc.
            if (Rlog.isLoggable("SMS", Log.DEBUG)) {
                log("markMessagesAsRead - aborting, no icc card present.");
            }
            return;
        }

        int count = messages.size();

        for (int i = 0; i < count; i++) {
             byte[] ba = messages.get(i);
             if (ba[0] == STATUS_ON_ICC_UNREAD) {
                 int n = ba.length;
                 byte[] nba = new byte[n - 1];
                 System.arraycopy(ba, 1, nba, 0, n - 1);
                 byte[] record = makeSmsRecordData(STATUS_ON_ICC_READ, nba);
                 fh.updateEFLinearFixed(IccConstants.EF_SMS, i + 1, record, null, null);
                 if (Rlog.isLoggable("SMS", Log.DEBUG)) {
                     log("SMS " + (i + 1) + " marked as read");
                 }
             }
        }
    
private voidreturnUnspecifiedFailure(android.app.PendingIntent pi)

        if (pi != null) {
            try {
                pi.send(SmsManager.RESULT_ERROR_GENERIC_FAILURE);
            } catch (PendingIntent.CanceledException e) {
                // ignore
            }
        }
    
private voidreturnUnspecifiedFailure(java.util.List pis)

        if (pis == null) {
            return;
        }
        for (PendingIntent pi : pis) {
            returnUnspecifiedFailure(pi);
        }
    
public voidsendData(java.lang.String callingPackage, java.lang.String destAddr, java.lang.String scAddr, int destPort, byte[] data, android.app.PendingIntent sentIntent, android.app.PendingIntent deliveryIntent)
Send a data based SMS to a specific application port.

param
destAddr the address to send the message to
param
scAddr is the service center address or null to use the current default SMSC
param
destPort the port to deliver the message to
param
data the body of the message to send
param
sentIntent if not NULL this PendingIntent is broadcast when the message is successfully sent, or failed. The result code will be Activity.RESULT_OK for success, or one of these errors:
RESULT_ERROR_GENERIC_FAILURE
RESULT_ERROR_RADIO_OFF
RESULT_ERROR_NULL_PDU
For RESULT_ERROR_GENERIC_FAILURE the sentIntent may include the extra "errorCode" containing a radio technology specific value, generally only useful for troubleshooting.
The per-application based SMS control checks sentIntent. If sentIntent is NULL the caller will be checked against all unknown applications, which cause smaller number of SMS to be sent in checking period.
param
deliveryIntent if not NULL this PendingIntent is broadcast when the message is delivered to the recipient. The raw pdu of the status report is in the extended data ("pdu").

        mPhone.getContext().enforceCallingPermission(
                Manifest.permission.SEND_SMS,
                "Sending SMS message");
        if (Rlog.isLoggable("SMS", Log.VERBOSE)) {
            log("sendData: destAddr=" + destAddr + " scAddr=" + scAddr + " destPort=" +
                destPort + " data='"+ HexDump.toHexString(data)  + "' sentIntent=" +
                sentIntent + " deliveryIntent=" + deliveryIntent);
        }
        if (mAppOps.noteOp(AppOpsManager.OP_SEND_SMS, Binder.getCallingUid(),
                callingPackage) != AppOpsManager.MODE_ALLOWED) {
            return;
        }
        destAddr = filterDestAddress(destAddr);
        mDispatcher.sendData(destAddr, scAddr, destPort, data, sentIntent, deliveryIntent);
    
public voidsendMultipartText(java.lang.String callingPackage, java.lang.String destAddr, java.lang.String scAddr, java.util.List parts, java.util.List sentIntents, java.util.List deliveryIntents)
Send a multi-part text based SMS.

param
destAddr the address to send the message to
param
scAddr is the service center address or null to use the current default SMSC
param
parts an ArrayList of strings that, in order, comprise the original message
param
sentIntents if not null, an ArrayList of PendingIntents (one for each message part) that is broadcast when the corresponding message part has been sent. The result code will be Activity.RESULT_OK for success, or one of these errors: RESULT_ERROR_GENERIC_FAILURE RESULT_ERROR_RADIO_OFF RESULT_ERROR_NULL_PDU. The per-application based SMS control checks sentIntent. If sentIntent is NULL the caller will be checked against all unknown applications, which cause smaller number of SMS to be sent in checking period.
param
deliveryIntents if not null, an ArrayList of PendingIntents (one for each message part) that is broadcast when the corresponding message part has been delivered to the recipient. The raw pdu of the status report is in the extended data ("pdu").

        mPhone.getContext().enforceCallingPermission(
                Manifest.permission.SEND_SMS,
                "Sending SMS message");
        if (Rlog.isLoggable("SMS", Log.VERBOSE)) {
            int i = 0;
            for (String part : parts) {
                log("sendMultipartText: destAddr=" + destAddr + ", srAddr=" + scAddr +
                        ", part[" + (i++) + "]=" + part);
            }
        }
        if (mAppOps.noteOp(AppOpsManager.OP_SEND_SMS, Binder.getCallingUid(),
                callingPackage) != AppOpsManager.MODE_ALLOWED) {
            return;
        }

        destAddr = filterDestAddress(destAddr);

        if (parts.size() > 1 && parts.size() < 10 && !SmsMessage.hasEmsSupport()) {
            for (int i = 0; i < parts.size(); i++) {
                // If EMS is not supported, we have to break down EMS into single segment SMS
                // and add page info " x/y".
                String singlePart = parts.get(i);
                if (SmsMessage.shouldAppendPageNumberAsPrefix()) {
                    singlePart = String.valueOf(i + 1) + '/" + parts.size() + ' " + singlePart;
                } else {
                    singlePart = singlePart.concat(' " + String.valueOf(i + 1) + '/" + parts.size());
                }

                PendingIntent singleSentIntent = null;
                if (sentIntents != null && sentIntents.size() > i) {
                    singleSentIntent = sentIntents.get(i);
                }

                PendingIntent singleDeliveryIntent = null;
                if (deliveryIntents != null && deliveryIntents.size() > i) {
                    singleDeliveryIntent = deliveryIntents.get(i);
                }

                mDispatcher.sendText(destAddr, scAddr, singlePart,
                        singleSentIntent, singleDeliveryIntent,
                        null/*messageUri*/, callingPackage);
            }
            return;
        }

        mDispatcher.sendMultipartText(destAddr, scAddr, (ArrayList<String>) parts,
                (ArrayList<PendingIntent>) sentIntents, (ArrayList<PendingIntent>) deliveryIntents,
                null/*messageUri*/, callingPackage);
    
public voidsendStoredMultipartText(java.lang.String callingPkg, android.net.Uri messageUri, java.lang.String scAddress, java.util.List sentIntents, java.util.List deliveryIntents)

        mPhone.getContext().enforceCallingPermission(Manifest.permission.SEND_SMS,
                "Sending SMS message");
        if (mAppOps.noteOp(AppOpsManager.OP_SEND_SMS, Binder.getCallingUid(), callingPkg)
                != AppOpsManager.MODE_ALLOWED) {
            return;
        }
        final ContentResolver resolver = mPhone.getContext().getContentResolver();
        if (!isFailedOrDraft(resolver, messageUri)) {
            Log.e(LOG_TAG, "[IccSmsInterfaceManager]sendStoredMultipartText: "
                    + "not FAILED or DRAFT message");
            returnUnspecifiedFailure(sentIntents);
            return;
        }
        final String[] textAndAddress = loadTextAndAddress(resolver, messageUri);
        if (textAndAddress == null) {
            Log.e(LOG_TAG, "[IccSmsInterfaceManager]sendStoredMultipartText: can not load text");
            returnUnspecifiedFailure(sentIntents);
            return;
        }
        final ArrayList<String> parts = SmsManager.getDefault().divideMessage(textAndAddress[0]);
        if (parts == null || parts.size() < 1) {
            Log.e(LOG_TAG, "[IccSmsInterfaceManager]sendStoredMultipartText: can not divide text");
            returnUnspecifiedFailure(sentIntents);
            return;
        }

        textAndAddress[1] = filterDestAddress(textAndAddress[1]);

        if (parts.size() > 1 && parts.size() < 10 && !SmsMessage.hasEmsSupport()) {
            for (int i = 0; i < parts.size(); i++) {
                // If EMS is not supported, we have to break down EMS into single segment SMS
                // and add page info " x/y".
                String singlePart = parts.get(i);
                if (SmsMessage.shouldAppendPageNumberAsPrefix()) {
                    singlePart = String.valueOf(i + 1) + '/" + parts.size() + ' " + singlePart;
                } else {
                    singlePart = singlePart.concat(' " + String.valueOf(i + 1) + '/" + parts.size());
                }

                PendingIntent singleSentIntent = null;
                if (sentIntents != null && sentIntents.size() > i) {
                    singleSentIntent = sentIntents.get(i);
                }

                PendingIntent singleDeliveryIntent = null;
                if (deliveryIntents != null && deliveryIntents.size() > i) {
                    singleDeliveryIntent = deliveryIntents.get(i);
                }

                mDispatcher.sendText(textAndAddress[1], scAddress, singlePart,
                        singleSentIntent, singleDeliveryIntent, messageUri, callingPkg);
            }
            return;
        }

        mDispatcher.sendMultipartText(
                textAndAddress[1], // destAddress
                scAddress,
                parts,
                (ArrayList<PendingIntent>) sentIntents,
                (ArrayList<PendingIntent>) deliveryIntents,
                messageUri,
                callingPkg);
    
public voidsendStoredText(java.lang.String callingPkg, android.net.Uri messageUri, java.lang.String scAddress, android.app.PendingIntent sentIntent, android.app.PendingIntent deliveryIntent)

        mPhone.getContext().enforceCallingPermission(Manifest.permission.SEND_SMS,
                "Sending SMS message");
        if (Rlog.isLoggable("SMS", Log.VERBOSE)) {
            log("sendStoredText: scAddr=" + scAddress + " messageUri=" + messageUri
                    + " sentIntent=" + sentIntent + " deliveryIntent=" + deliveryIntent);
        }
        if (mAppOps.noteOp(AppOpsManager.OP_SEND_SMS, Binder.getCallingUid(), callingPkg)
                != AppOpsManager.MODE_ALLOWED) {
            return;
        }
        final ContentResolver resolver = mPhone.getContext().getContentResolver();
        if (!isFailedOrDraft(resolver, messageUri)) {
            Log.e(LOG_TAG, "[IccSmsInterfaceManager]sendStoredText: not FAILED or DRAFT message");
            returnUnspecifiedFailure(sentIntent);
            return;
        }
        final String[] textAndAddress = loadTextAndAddress(resolver, messageUri);
        if (textAndAddress == null) {
            Log.e(LOG_TAG, "[IccSmsInterfaceManager]sendStoredText: can not load text");
            returnUnspecifiedFailure(sentIntent);
            return;
        }
        textAndAddress[1] = filterDestAddress(textAndAddress[1]);
        mDispatcher.sendText(textAndAddress[1], scAddress, textAndAddress[0],
                sentIntent, deliveryIntent, messageUri, callingPkg);
    
public voidsendText(java.lang.String callingPackage, java.lang.String destAddr, java.lang.String scAddr, java.lang.String text, android.app.PendingIntent sentIntent, android.app.PendingIntent deliveryIntent)
Send a text based SMS.

param
destAddr the address to send the message to
param
scAddr is the service center address or null to use the current default SMSC
param
text the body of the message to send
param
sentIntent if not NULL this PendingIntent is broadcast when the message is successfully sent, or failed. The result code will be Activity.RESULT_OK for success, or one of these errors:
RESULT_ERROR_GENERIC_FAILURE
RESULT_ERROR_RADIO_OFF
RESULT_ERROR_NULL_PDU
For RESULT_ERROR_GENERIC_FAILURE the sentIntent may include the extra "errorCode" containing a radio technology specific value, generally only useful for troubleshooting.
The per-application based SMS control checks sentIntent. If sentIntent is NULL the caller will be checked against all unknown applications, which cause smaller number of SMS to be sent in checking period.
param
deliveryIntent if not NULL this PendingIntent is broadcast when the message is delivered to the recipient. The raw pdu of the status report is in the extended data ("pdu").

        mPhone.getContext().enforceCallingPermission(
                Manifest.permission.SEND_SMS,
                "Sending SMS message");
        if (Rlog.isLoggable("SMS", Log.VERBOSE)) {
            log("sendText: destAddr=" + destAddr + " scAddr=" + scAddr +
                " text='"+ text + "' sentIntent=" +
                sentIntent + " deliveryIntent=" + deliveryIntent);
        }
        if (mAppOps.noteOp(AppOpsManager.OP_SEND_SMS, Binder.getCallingUid(),
                callingPackage) != AppOpsManager.MODE_ALLOWED) {
            return;
        }
        destAddr = filterDestAddress(destAddr);
        mDispatcher.sendText(destAddr, scAddr, text, sentIntent, deliveryIntent,
                null/*messageUri*/, callingPackage);
    
private booleansetCdmaBroadcastActivation(boolean activate)

        if (DBG)
            log("Calling setCdmaBroadcastActivation(" + activate + ")");

        synchronized (mLock) {
            Message response = mHandler.obtainMessage(EVENT_SET_BROADCAST_ACTIVATION_DONE);

            mSuccess = false;
            mPhone.mCi.setCdmaBroadcastActivation(activate, response);

            try {
                mLock.wait();
            } catch (InterruptedException e) {
                log("interrupted while trying to set cdma broadcast activation");
            }
        }

        return mSuccess;
    
private booleansetCdmaBroadcastConfig(com.android.internal.telephony.cdma.CdmaSmsBroadcastConfigInfo[] configs)

        if (DBG)
            log("Calling setCdmaBroadcastConfig with " + configs.length + " configurations");

        synchronized (mLock) {
            Message response = mHandler.obtainMessage(EVENT_SET_BROADCAST_CONFIG_DONE);

            mSuccess = false;
            mPhone.mCi.setCdmaBroadcastConfig(configs, response);

            try {
                mLock.wait();
            } catch (InterruptedException e) {
                log("interrupted while trying to set cdma broadcast config");
            }
        }

        return mSuccess;
    
private booleansetCellBroadcastActivation(boolean activate)

        if (DBG)
            log("Calling setCellBroadcastActivation(" + activate + ')");

        synchronized (mLock) {
            Message response = mHandler.obtainMessage(EVENT_SET_BROADCAST_ACTIVATION_DONE);

            mSuccess = false;
            mPhone.mCi.setGsmBroadcastActivation(activate, response);

            try {
                mLock.wait();
            } catch (InterruptedException e) {
                log("interrupted while trying to set cell broadcast activation");
            }
        }

        return mSuccess;
    
private booleansetCellBroadcastConfig(com.android.internal.telephony.gsm.SmsBroadcastConfigInfo[] configs)

        if (DBG)
            log("Calling setGsmBroadcastConfig with " + configs.length + " configurations");

        synchronized (mLock) {
            Message response = mHandler.obtainMessage(EVENT_SET_BROADCAST_CONFIG_DONE);

            mSuccess = false;
            mPhone.mCi.setGsmBroadcastConfig(configs, response);

            try {
                mLock.wait();
            } catch (InterruptedException e) {
                log("interrupted while trying to set cell broadcast config");
            }
        }

        return mSuccess;
    
public voidsetPremiumSmsPermission(java.lang.String packageName, int permission)

        mDispatcher.setPremiumSmsPermission(packageName, permission);
    
public booleanupdateMessageOnIccEf(java.lang.String callingPackage, int index, int status, byte[] pdu)
Update the specified message on the Icc.

param
index record index of message to update
param
status new message status (STATUS_ON_ICC_READ, STATUS_ON_ICC_UNREAD, STATUS_ON_ICC_SENT, STATUS_ON_ICC_UNSENT, STATUS_ON_ICC_FREE)
param
pdu the raw PDU to store
return
success or not

        if (DBG) log("updateMessageOnIccEf: index=" + index +
                " status=" + status + " ==> " +
                "("+ Arrays.toString(pdu) + ")");
        enforceReceiveAndSend("Updating message on Icc");
        if (mAppOps.noteOp(AppOpsManager.OP_WRITE_ICC_SMS, Binder.getCallingUid(),
                callingPackage) != AppOpsManager.MODE_ALLOWED) {
            return false;
        }
        synchronized(mLock) {
            mSuccess = false;
            Message response = mHandler.obtainMessage(EVENT_UPDATE_DONE);

            if (status == STATUS_ON_ICC_FREE) {
                // RIL_REQUEST_DELETE_SMS_ON_SIM vs RIL_REQUEST_CDMA_DELETE_SMS_ON_RUIM
                // Special case FREE: call deleteSmsOnSim/Ruim instead of
                // manipulating the record
                // Will eventually fail if icc card is not present.
                if (PhoneConstants.PHONE_TYPE_GSM == mPhone.getPhoneType()) {
                    mPhone.mCi.deleteSmsOnSim(index, response);
                } else {
                    mPhone.mCi.deleteSmsOnRuim(index, response);
                }
            } else {
                //IccFilehandler can be null if ICC card is not present.
                IccFileHandler fh = mPhone.getIccFileHandler();
                if (fh == null) {
                    response.recycle();
                    return mSuccess; /* is false */
                }
                byte[] record = makeSmsRecordData(status, pdu);
                fh.updateEFLinearFixed(
                        IccConstants.EF_SMS,
                        index, record, null, response);
            }
            try {
                mLock.wait();
            } catch (InterruptedException e) {
                log("interrupted while trying to update by index");
            }
        }
        return mSuccess;
    
protected voidupdatePhoneObject(PhoneBase phone)

        mPhone = phone;
        mDispatcher.updatePhoneObject(phone);