[mtk6572源码解析]ISms.aidl 生成的源码 和 SmsManagerEx 中被调用到的函数

来源:互联网 发布:开源证券软件下载 编辑:程序博客网 时间:2024/06/08 19:10

 

mtk内置的应用 mms就是包含发短信功能的apk,当然它还有彩信的功能。

mtk的mms应用发短信并没有使用 android的标准api ,而是使用了自家的个性化的方法。

 

 

关键发送代码所在的文件为:

packages\apps\Mms\src\com\android\mms\transaction\SmsSingleRecipientSender.java

其内容如下(关键函数使用红色加粗标记):

package com.android.mms.transaction;

import java.util.ArrayList;

import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.provider.Telephony.Mms;
import android.telephony.PhoneNumberUtils;
import android.telephony.SmsManager;
import android.util.Log;

import com.android.mms.LogTag;
import com.android.mms.MmsConfig;
import com.google.android.mms.MmsException;
import android.provider.Telephony.Sms;

import com.android.mms.data.Conversation;
import com.android.mms.ui.MessageUtils;

/// M:
import android.content.SharedPreferences;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.telephony.SmsMessage;
import com.mediatek.encapsulation.android.telephony.gemini.EncapsulatedGeminiSmsManager;
import com.mediatek.encapsulation.android.telephony.EncapsulatedSmsManager;

import com.mediatek.encapsulation.com.android.internal.telephony.EncapsulatedPhone;
import com.android.mms.MmsApp;
import com.android.mms.ui.SmsPreferenceActivity;
import com.mediatek.encapsulation.com.mediatek.common.featureoption.EncapsulatedFeatureOption;
import com.mediatek.encapsulation.MmsLog;
import com.mediatek.encapsulation.android.telephony.EncapsulatedTelephony.SIMInfo;

public class SmsSingleRecipientSenderextends SmsMessageSender {

    private final boolean mRequestDeliveryReport;
    private String mDest;
    private Uri mUri;
    private static final String TAG = "SmsSingleRecipientSender";

    public SmsSingleRecipientSender(Context context, String dest, String msgText, long threadId,
            boolean requestDeliveryReport, Uri uri) {
        super(context, null, msgText, threadId);
        mRequestDeliveryReport = requestDeliveryReport;
        mDest = dest;
        mUri = uri;
    }

    public boolean sendMessage(long token) throws MmsException {
        if (LogTag.DEBUG_SEND) {
            Log.v(TAG, "sendMessage token: " + token);
        }
        /// M:Code analyze 001, convert sim id to slot id @{
        int slotId = SIMInfo.getSlotById(mContext, mSimId);
        MmsLog.d(MmsApp.TXN_TAG, "SmsSingleRecipientSender: sendMessage() simId=" + mSimId +"slotId=" + slotId);

        if (mMessageText == null) {
            // Don't try to send an empty message, and destination should be just
            // one.
            throw new MmsException("Null message body or have multiple destinations.");
        }

        /// M:Code analyze 002,add a variable to caculate the length of sms @{
        int codingType = SmsMessage.ENCODING_UNKNOWN;
        if (MmsConfig.getSmsEncodingTypeEnabled()) {
            codingType = MessageUtils.getSmsEncodingType(mContext);
        }
        /// @}

        //SmsManager smsManager = SmsManager.getDefault();
        ArrayList<String> messages = null;
        if ((MmsConfig.getEmailGateway() != null) && (Mms.isEmailAddress(mDest) || MessageUtils.isAlias(mDest))){
            String msgText;
            msgText = mDest + " " + mMessageText;
            mDest = MmsConfig.getEmailGateway();
            /// M:Code analyze 003,add a parameter codingType to caculate length of sms @{
            messages = EncapsulatedSmsManager.divideMessage(msgText, codingType);
            /// @}
        } else {
            /// M:Code analyze 003,add a parameter codingType to caculate length of sms @{
            messages = EncapsulatedSmsManager.divideMessage(mMessageText, codingType);
            /// @}
            // remove spaces and dashes from destination number
            // (e.g. "801 555 1212" -> "8015551212")
            // (e.g. "+8211-123-4567" -> "+82111234567")
            /// M:Code analyze 004, comment the line,using customized striping pattern to mDest @{
            //mDest = PhoneNumberUtils.stripSeparators(mDest);
            /** M: remove spaces from destination number (e.g. "801 555 1212" -> "8015551212") @{ */
            mDest = mDest.replaceAll(" ", "");
            mDest = mDest.replaceAll("-", "");
            /// @}
            mDest = Conversation.verifySingleRecipient(mContext, mThreadId, mDest);
        }
        int messageCount = messages.size();
        /// M:
        MmsLog.d(MmsApp.TXN_TAG, "SmsSingleRecipientSender: sendMessage(), Message Count=" + messageCount);

        if (messageCount == 0) {
            // Don't try to send an empty message.
            throw new MmsException("SmsMessageSender.sendMessage: divideMessage returned " +
                    "empty messages. Original message is \"" + mMessageText + "\"");
        }

        boolean moved = Sms.moveMessageToFolder(mContext, mUri, Sms.MESSAGE_TYPE_OUTBOX, 0);
        if (!moved) {
            throw new MmsException("SmsMessageSender.sendMessage: couldn't move message " +
                    "to outbox: " + mUri);
        }
        if (LogTag.DEBUG_SEND) {
            Log.v(TAG, "sendMessage mDest: " + mDest + " mRequestDeliveryReport: " +
                    mRequestDeliveryReport);
        }

        ArrayList<PendingIntent> deliveryIntents =  new ArrayList<PendingIntent>(messageCount);
        ArrayList<PendingIntent> sentIntents = new ArrayList<PendingIntent>(messageCount);

        for (int i = 0; i < messageCount; i++) {
            if (mRequestDeliveryReport && (i == (messageCount - 1))) {
                // TODO: Fix: It should not be necessary to
                // specify the class in this intent.  Doing that
                // unnecessarily limits customizability.
                /// M:Code analyze 005,change logic for gemini,add slotId info @{
                Intent intent = new Intent(
                                MessageStatusReceiver.MESSAGE_STATUS_RECEIVED_ACTION,
                                mUri,
                                mContext,
                                MessageStatusReceiver.class);
                if (EncapsulatedFeatureOption.MTK_GEMINI_SUPPORT) {
                    intent.putExtra(EncapsulatedPhone.GEMINI_SIM_ID_KEY, slotId);
                }
                //the parameter is used now! not as the google doc says "currently not used"
                deliveryIntents.add(PendingIntent.getBroadcast(mContext, i, intent, 0));
                /// @}
            } else {
                deliveryIntents.add(null);
            }
            Intent intent  = new Intent(SmsReceiverService.MESSAGE_SENT_ACTION,
                    mUri,
                    mContext,
                    SmsReceiver.class);
            /// M:Code analyze 007, comment the line,using different requestCode for every sub_message @{
            //int requestCode = 0;
            /// @}
            if (i == messageCount - 1) {
                // Changing the requestCode so that a different pending intent
                // is created for the last fragment with
                // EXTRA_MESSAGE_SENT_SEND_NEXT set to true.
                /// M:Code analyze 007, comment the line,using different requestCode for every sub_message @{
                //requestCode = 1;
                /// @}
                intent.putExtra(SmsReceiverService.EXTRA_MESSAGE_SENT_SEND_NEXT, true);
            }

            /// M:Code analyze 008, add for concatenation msg @{
            if (messageCount > 1) {
                intent.putExtra(SmsReceiverService.EXTRA_MESSAGE_CONCATENATION, true);
            }
            /// @}
            if (LogTag.DEBUG_SEND) {
                Log.v(TAG, "sendMessage sendIntent: " + intent);
            }
            /// M:Code analyze 009, add slotId for gemini @{
            if (EncapsulatedFeatureOption.MTK_GEMINI_SUPPORT) {
                intent.putExtra(EncapsulatedPhone.GEMINI_SIM_ID_KEY, slotId);
            }
            /// @}
            /// M:Code analyze 007, comment the line,using different requestCode for every sub_message @{
            sentIntents.add(PendingIntent.getBroadcast(mContext, i, intent, 0));
            /// @}
        }
        try {

            MmsLog.d(MmsApp.TXN_TAG, "\t Destination\t= " + mDest);
            MmsLog.d(MmsApp.TXN_TAG, "\t ServiceCenter\t= " + mServiceCenter);
            MmsLog.d(MmsApp.TXN_TAG, "\t Message\t= " + messages);
            MmsLog.d(MmsApp.TXN_TAG, "\t uri\t= " + mUri);
            MmsLog.d(MmsApp.TXN_TAG, "\t slotId\t= "+ slotId);
            MmsLog.d(MmsApp.TXN_TAG, "\t CodingType\t= " + codingType);
            /// @}

            /// M:Code analyze 009, modify logic for gemini,meantime,add a parameter codingType for
            /// sendMultipartTextMessageWithEncodingType to send multiparts messages@{
            if (EncapsulatedFeatureOption.MTK_GEMINI_SUPPORT) {
                        //xmx.add
        MmsLog.d(MmsApp.TXN_TAG, "[xmx] in sendmessage() : EncapsulatedFeatureOption.MTK_GEMINI_SUPPORT == true " );
    //xmx.add.end
                                if (MmsConfig.getSmsValidityPeriodEnabled()){  
                    SharedPreferences spref = PreferenceManager.getDefaultSharedPreferences(mContext);
                    final String validityKey = Long.toString(slotId) + "_" + SmsPreferenceActivity.SMS_VALIDITY_PERIOD;
                    int vailidity = spref.getInt(validityKey, EncapsulatedSmsManager.VALIDITY_PERIOD_NO_DURATION);
                    Bundle extra = new Bundle();
                //xmx.add
                MmsLog.d(MmsApp.TXN_TAG, "[xmx] in sendmessage() : MmsConfig.getSmsValidityPeriodEnabled() == true " );
                //xmx.add.end
                    extra.putInt(EncapsulatedSmsManager.EXTRA_PARAMS_VALIDITY_PERIOD, vailidity);
                    EncapsulatedGeminiSmsManager.sendMultipartTextMessageWithExtraParamsGemini(mDest, mServiceCenter, messages, extra, slotId, sentIntents, deliveryIntents);
                } else {MmsConfig.getSmsValidityPeriodEnabled()   为 false
                                //xmx.add
                MmsLog.d(MmsApp.TXN_TAG, "[xmx] in sendmessage() : MmsConfig.getSmsValidityPeriodEnabled() == false" );
                                //xmx.add.end

                          // 从短信发送102到10010,实际上走的是下面这个函数。
                    EncapsulatedGeminiSmsManager.sendMultipartTextMessageWithEncodingTypeGemini(mDest, mServiceCenter, messages, codingType, slotId/*mSimId*/, sentIntents, deliveryIntents);
                }
            } else

          {  //EncapsulatedFeatureOption.MTK_GEMINI_SUPPORT  = false
                        //xmx.add
            MmsLog.d(MmsApp.TXN_TAG, "[xmx] in sendmessage() : false:: call. sendMultipartTextMessageWithEncodingType " );
                        //xmx.add.end
                EncapsulatedSmsManager.sendMultipartTextMessageWithEncodingType(mDest, mServiceCenter, messages,
                        codingType, sentIntents, deliveryIntents);
            }
            /// @}
        } catch (Exception ex) {
            Log.e(TAG, "SmsMessageSender.sendMessage: caught", ex);
            throw new MmsException("SmsMessageSender.sendMessage: caught " + ex +
                    " from SmsManager.sendTextMessage()");
        }
        if (Log.isLoggable(LogTag.TRANSACTION, Log.VERBOSE) || LogTag.DEBUG_SEND) {
            log("sendMessage: address=" + mDest + ", threadId=" + mThreadId +
                    ", uri=" + mUri + ", msgs.count=" + messageCount);
        }
        return false;
    }

    private void log(String msg) {
        Log.d(LogTag.TAG, "[SmsSingleRecipientSender] " + msg);
    }
}

 

我们进一步来看 EncapsulatedGeminiSmsManager.sendMultipartTextMessageWithEncodingTypeGemini 方法的实现:

 

packages/apps/Mms/src/com/mediatek/encapsulation/android/telephony/gemini/EncapsulatedGeminiSmsManager.java

 

package com.mediatek.encapsulation.android.telephony.gemini;

import android.telephony.gemini.GeminiSmsManager;
import android.telephony.SmsManager;
import android.telephony.SmsMessage;
import android.os.Bundle;
import android.app.PendingIntent;
import android.os.RemoteException;
import android.os.ServiceManager;

import com.android.internal.telephony.ISms;
import com.mediatek.common.telephony.IccSmsStorageStatus;
import com.mediatek.encapsulation.EncapsulationConstant;
import com.mediatek.encapsulation.android.telephony.EncapsulatedSmsMemoryStatus;
import com.mediatek.telephony.SmsManagerEx;

import java.util.List;
import java.util.ArrayList;

/// M: ALPS00510627, SMS Framewrok API refactoring, EncapsulatedGeminiSmsManager -> SmsManagerEx 这里也写明了,EncapsulatedGeminiSmsManager 类,最终调用的是  SmsManagerEx 类的方法。


public class EncapsulatedGeminiSmsManager {

    /** M: MTK ADD */
    public static int copyTextMessageToIccCardGemini(String scAddress, String address,
            List<String> text, int status, long timestamp, int slotId) {
        if (EncapsulationConstant.USE_MTK_PLATFORM) {
            return SmsManagerEx.getDefault().copyTextMessageToIccCard(scAddress, address, text,
                    status, timestamp, slotId);
        } else {
            return 0;
        }
    }

    /** M: MTK ADD */
    public static EncapsulatedSmsMemoryStatus getSmsSimMemoryStatusGemini(int simId) {
        if (EncapsulationConstant.USE_MTK_PLATFORM) {
            IccSmsStorageStatus smsMemoryStatus
                    = SmsManagerEx.getDefault().getIccSmsStorageStatus(simId);
            if (smsMemoryStatus != null) {
                return new EncapsulatedSmsMemoryStatus(smsMemoryStatus);
            } else {
                return null;
            }
        } else {
            /** M: Can not complete for this branch. */
            return null;
        }
    }

    /** M: MTK ADD */
    public static int copyMessageToIccGemini(byte[] smsc, byte[] pdu, int status, int simId) {
        if (EncapsulationConstant.USE_MTK_PLATFORM) {
            return SmsManagerEx.getDefault().copySmsPduToIcc(smsc,pdu,status,simId);
        } else {
            /** M: Can not complete for this branch. */
            int result = SmsManager.getDefault().copyMessageToIcc(smsc, pdu, status) ? 0 : -1;

            return result;
        }
    }

    /** M: MTK ADD */
    public static void sendMultipartTextMessageWithExtraParamsGemini(String destAddr,
            String scAddr, ArrayList<String> parts, Bundle extraParams, int slotId,
            ArrayList<PendingIntent> sentIntents, ArrayList<PendingIntent> deliveryIntents) {
        if (EncapsulationConstant.USE_MTK_PLATFORM) {
             SmsManagerEx.getDefault().sendMultipartTextMessageWithExtraParams(destAddr, scAddr,
                    parts, extraParams, sentIntents, deliveryIntents, slotId);
        } else {
        }

    }

    /** M: MTK ADD */
    public static void sendMultipartTextMessageWithEncodingTypeGemini(String destAddr,
            String scAddr, ArrayList<String> parts, int encodingType, int slotId,
            ArrayList<PendingIntent> sentIntents, ArrayList<PendingIntent> deliveryIntents)

   {
        if (EncapsulationConstant.USE_MTK_PLATFORM)

        {

            // 这里 实际上是调用了framework 中  SmsManagerEx   类中的 sendMultipartTextMessageWithEncodingType 方法。
             SmsManagerEx.getDefault().sendMultipartTextMessageWithEncodingType(destAddr, scAddr, parts, encodingType, slotId, sentIntents, deliveryIntents);
        } else

        {
        }
    }


}

 

 

 

 

 

 

以下是对应的 framework的调用流程


mediatek/frameworks/opt/telephony/src/java/com/mediatek/telephony/SmsManagerEx.java

sendMultipartTextMessageWithEncodingType 调用 sendTextMessageWithEncodingType

而sendTextMessageWithEncodingType 做了如下操作。


mediatek/frameworks/opt/telephony/src/java/com/mediatek/telephony/SmsManagerEx.java
sendTextMessageWithEncodingType
::
    {
    import com.android.internal.telephony.ISms;
    String isms = getSmsServiceName(slotId);
    //ISms是个接口,定义于 ISms.aidl
    ISms iccISms = ISms.Stub.asInterface(ServiceManager.getService(isms));
==> iccISms.sendTextWithEncodingType
    }
   
关于ISms::start==>
frameworks/opt/telephony/src/java/com/android/internal/telephony/ISms.aidl
/** Interface for applications to access the ICC phone book.
 *
 * <p>The following code snippet demonstrates a static method to
 * retrieve the ISms interface from Android:</p>
 * <pre>private static ISms getSmsInterface()
            throws DeadObjectException {
    IServiceManager sm = ServiceManagerNative.getDefault();
    ISms ss;
    ss = ISms.Stub.asInterface(sm.getService("isms"));
    return ss;
}
 * </pre>
 */

interface ISms { ………… }
关于ISms::end<<==

   
mediatek\frameworks-ext\base\telephony\java\android\telephony\gemini\GeminiSmsManager.java
    @sendTextMessageWithEncodingTypeGemini(); 没有被调用。

frameworks/opt/telephony/src/java/com/android/internal/telephony/SMSDispatcher.java
    @sendTextWithEncodingType
   
frameworks/opt/telephony/src/java/com/android/internal/telephony/gsm/GsmSMSDispatcher.java
    @sendTextWithEncodingType
   
SMSDispatcher.java (frameworks\opt\telephony\src\java\com\android\internal\telephony)
    @sendRawPdu()
   
   

 

 

 

ISms.aidl 

 

out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/opt/telephony/src/java/com/android/internal/telephony/ISms.java

 

 /**
     * Send a multi-part text based SMS with specified encoding type.
     *
     * @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 <code>ArrayList</code> of strings that, in order,
     *   comprise the original message
     * @param encodingType the encoding type of content of message(GSM 7-bit, Unicode or Automatic)
     * @param sentIntents if not null, an <code>ArrayList</code> of
     *   <code>PendingIntent</code>s (one for each message part) that is
     *   broadcast when the corresponding message part has been sent.
     *   The result code will be <code>Activity.RESULT_OK<code> for success,
     *   or one of these errors:
     *   <code>RESULT_ERROR_GENERIC_FAILURE</code>
     *   <code>RESULT_ERROR_RADIO_OFF</code>
     *   <code>RESULT_ERROR_NULL_PDU</code>.
     * @param deliveryIntents if not null, an <code>ArrayList</code> of
     *   <code>PendingIntent</code>s (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").
     */
@Override public void sendMultipartTextWithEncodingType(java.lang.String destAddr, java.lang.String scAddr,
                             java.util.List<java.lang.String> parts, int encodingType,
                             java.util.List<android.app.PendingIntent> sentIntents,
                             java.util.List<android.app.PendingIntent> deliveryIntents) throws android.os.RemoteException
{
    android.os.Parcel _data = android.os.Parcel.obtain();
    android.os.Parcel _reply = android.os.Parcel.obtain();
    try {
        _data.writeInterfaceToken(DESCRIPTOR);
        _data.writeString(destAddr);
        _data.writeString(scAddr);
        _data.writeStringList(parts);
        _data.writeInt(encodingType);
        _data.writeTypedList(sentIntents);
        _data.writeTypedList(deliveryIntents);
        mRemote.transact(Stub.TRANSACTION_sendMultipartTextWithEncodingType, _data, _reply, 0);
        _reply.readException();
    }
    finally {
        _reply.recycle();
        _data.recycle();
    }
}

 

 

 

"mediatek/frameworks/opt/telephony/src/java/com/mediatek/telephony/SmsManagerEx.java"

/**

     * 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 encodingType the encoding type of message(gsm 7-bit, unicode or automatic)
     * @param slotId the sim card that user wants to access
     * @param sentIntent if not NULL this <code>PendingIntent</code> is
     *  broadcast when the message is sucessfully sent, or failed.
     *  The result code will be <code>Activity.RESULT_OK<code> for success,
     *  or one of these errors:<br>
     *  <code>RESULT_ERROR_GENERIC_FAILURE</code><br>
     *  <code>RESULT_ERROR_RADIO_OFF</code><br>
     *  <code>RESULT_ERROR_NULL_PDU</code><br>
     *  For <code>RESULT_ERROR_GENERIC_FAILURE</code> the sentIntent may include
     *  the extra "errorCode" containing a radio technology specific value,
     *  generally only useful for troubleshooting.<br>
     *  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 <code>PendingIntent</code> is
     *  broadcast when the message is delivered to the recipient.  The
     *  raw pdu of the status report is in the extended data ("pdu").
     *
     * @throws IllegalArgumentException if destinationAddress or text are empty
     * @hide
     */
    public static void sendTextMessageWithEncodingType(
            String destAddr,
            String scAddr,
            String text,
            int encodingType,
            int slotId,
            PendingIntent sentIntent,
            PendingIntent deliveryIntent) {
        // impl
        Log.d(TAG, "call sendTextMessageWithEncodingType, encoding = " + encodingType);

        if (!isValidParameters(destAddr, text, sentIntent)) {
            Log.d(TAG, "the parameters are invalid");
            return;
        }

        String isms = getSmsServiceName(slotId);
        try {
            ISms iccISms = ISms.Stub.asInterface(ServiceManager.getService(isms));
            if (iccISms != null) {
                Log.d(TAG, "call ISms interface to send text message");
                iccISms.sendTextWithEncodingType(destAddr,
                    scAddr, text, encodingType, sentIntent, deliveryIntent);
            } else {
                Log.d(TAG, "iccISms is null");
            }
        } catch (RemoteException ex) {
            // ignore it
            Log.d(TAG, "fail to get ISms");

       }

}

 

 

     /**
     * Send a multi-part text based SMS.  The callee should have already
     * divided the message into correctly sized parts by calling
     * <code>divideMessage</code>.
     *
     * @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 <code>ArrayList</code> of strings that, in order,
     *   comprise the original message
     * @param encodingType the encoding type of message(gsm 7-bit, unicode or automatic)
     * @param slotId the sim card that user wants to access
     * @param sentIntents if not null, an <code>ArrayList</code> of
     *   <code>PendingIntent</code>s (one for each message part) that is
     *   broadcast when the corresponding message part has been sent.
     *   The result code will be <code>Activity.RESULT_OK<code> for success,
     *   or one of these errors:<br>
     *   <code>RESULT_ERROR_GENERIC_FAILURE</code><br>
     *   <code>RESULT_ERROR_RADIO_OFF</code><br>
     *   <code>RESULT_ERROR_NULL_PDU</code><br>
     *   For <code>RESULT_ERROR_GENERIC_FAILURE</code> each sentIntent may include
     *   the extra "errorCode" containing a radio technology specific value,
     *   generally only useful for troubleshooting.<br>
     *   The per-application based SMS control checks sentIntent. If sentIntent
     *   is NULL the caller will be checked against all unknown applicaitons,
     *   which cause smaller number of SMS to be sent in checking period.
     * @param deliveryIntents if not null, an <code>ArrayList</code> of
     *   <code>PendingIntent</code>s (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").
     *
     * @throws IllegalArgumentException if destinationAddress or data are empty
     * @hide
     */

    public static void sendMultipartTextMessageWithEncodingType(
            String destAddr,
            String scAddr,
            ArrayList<String> parts,
            int encodingType,
            int slotId,
            ArrayList<PendingIntent> sentIntents,
            ArrayList<PendingIntent> deliveryIntents) {
        // impl
        Log.d(TAG, "call sendMultipartTextMessageWithEncodingType, encoding = " + encodingType);

        if (!isValidParameters(destAddr, parts, sentIntents)) {
            Log.d(TAG, "invalid parameters for multipart message");
            return;
        }

        String isms = getSmsServiceName(slotId);
        if (parts.size() > 1) {
            try {
                ISms iccISms = ISms.Stub.asInterface(ServiceManager.getService(isms));
                if (iccISms != null) {
                    Log.d(TAG, "call ISms.sendMultipartText");
                    iccISms.sendMultipartTextWithEncodingType(destAddr, scAddr, parts,
                            encodingType, sentIntents, deliveryIntents);
                }
            } catch (RemoteException ex) {
                // ignore it
            }
        } else {
            PendingIntent sentIntent = null;
            PendingIntent deliveryIntent = null;
            if (sentIntents != null && sentIntents.size() > 0) {
                sentIntent = sentIntents.get(0);
            }
            Log.d(TAG, "get sentIntent: " + sentIntent);
            if (deliveryIntents != null && deliveryIntents.size() > 0) {
                deliveryIntent = deliveryIntents.get(0);
            }
            Log.d(TAG, "send single message");
            if (parts != null) {
                Log.d(TAG, "parts.size = " + parts.size());
            }
            String text = (parts == null || parts.size() == 0) ? "" : parts.get(0);
            Log.d(TAG, "pass encoding type " + encodingType);
            sendTextMessageWithEncodingType(destAddr, scAddr, text, encodingType,
                    slotId, sentIntent, deliveryIntent);
        }
    }