短信发送Framework流程,源代码的版本是4.4
1、通过Mms源代码可以知道短信发送最后调用的关键api如下:
SmsSingleRecipientSender.java
- SmsManager smsManager = SmsManager.getDefault();
- ...
- try {
- smsManager.sendMultipartTextMessage(mDest, mServiceCenter, messages, sentIntents, deliveryIntents);
- } catch (Exception ex) {
- Log.e(TAG, "SmsMessageSender.sendMessage: caught", ex);
- throw new MmsException("SmsMessageSender.sendMessage: caught " + ex +
- " from SmsManager.sendTextMessage()");
- }
- ...
smsManager对应的文件是SmsManager.java
2、SmsManager源代码路径是frameworks/opt/telephony/src/java/android/telephony/gsm/SmsManager.java
SmsManager这里用了单例模式初始化
-
- private static final SmsManager sInstance = new SmsManager();
-
-
-
-
-
- public static SmsManager getDefault() {
- return sInstance;
- }
sendMultipartTextMessage的实现如下:
- public void sendMultipartTextMessage(
- String destinationAddress, String scAddress, ArrayList<String> parts,
- ArrayList<PendingIntent> sentIntents, ArrayList<PendingIntent> deliveryIntents) {
- if (TextUtils.isEmpty(destinationAddress)) {
- throw new IllegalArgumentException("Invalid destinationAddress");
- }
- if (parts == null || parts.size() < 1) {
- throw new IllegalArgumentException("Invalid message body");
- }
-
-
- if (parts.size() > 1) {
- try {
- ISms iccISms = ISms.Stub.asInterface(ServiceManager.getService("isms"));
- if (iccISms != null) {
- iccISms.sendMultipartText(ActivityThread.currentPackageName(),
- destinationAddress, scAddress, parts,
- sentIntents, deliveryIntents);
- }
- } catch (RemoteException ex) {
-
- }
- } else {
- PendingIntent sentIntent = null;
- PendingIntent deliveryIntent = null;
- if (sentIntents != null && sentIntents.size() > 0) {
- sentIntent = sentIntents.get(0);
- }
- if (deliveryIntents != null && deliveryIntents.size() > 0) {
- deliveryIntent = deliveryIntents.get(0);
- }
- sendTextMessage(destinationAddress, scAddress, parts.get(0),
- sentIntent, deliveryIntent);
- }
- }
如果短信的内容被划分成了多个部分,将进入icc.sendMultipartText(),即如下
- try {
- ISms iccISms = ISms.Stub.asInterface(ServiceManager.getService("isms"));
- if (iccISms != null) {
- iccISms.sendMultipartText(ActivityThread.currentPackageName(),
- destinationAddress, scAddress, parts,
- sentIntents, deliveryIntents);
- }
- } catch (RemoteException ex) {
-
- }
如果短信的内容只有一部分,则继续调用sendTextMessage(),即如下
- <span style="white-space:pre"> </span> PendingIntent sentIntent = null;
- PendingIntent deliveryIntent = null;
- if (sentIntents != null && sentIntents.size() > 0) {
- sentIntent = sentIntents.get(0);
- }
- if (deliveryIntents != null && deliveryIntents.size() > 0) {
- deliveryIntent = deliveryIntents.get(0);
- }
- sendTextMessage(destinationAddress, scAddress, parts.get(0),
- sentIntent, deliveryIntent);
下面的流程主要针对sendTextMessage( )分析,sendMultipartText到此为止。
短信在发送之前会检查发送字符串是否超过最大长度,如果超过会被划分成几部分,对应这里的ArrayList<string> parts,
划分的具体实现对应smsManager.divideMessage(mMsgText)
-
-
-
-
-
-
-
-
-
-
- public ArrayList<String> divideMessage(String text) {
- if (null == text) {
- throw new IllegalArgumentException("text is null");
- }
- return SmsMessage.fragmentText(text);
- }
很明显这里调用SmsMessage.fragmentText()
SmsMessage的路径是frameworks/opt/telephony/src/java/android/telephony/SmsMessage.java
fragmentText的具体实现如下:
-
-
-
-
-
-
-
-
-
-
- public static ArrayList<String> fragmentText(String text) {
-
- TextEncodingDetails ted = (useCdmaFormatForMoSms()) ?
- com.android.internal.telephony.cdma.SmsMessage.calculateLength(text, false) :
- com.android.internal.telephony.gsm.SmsMessage.calculateLength(text, false);
-
-
-
-
-
- int limit;
- if (ted.codeUnitSize == SmsConstants.ENCODING_7BIT) {
- int udhLength;
- if (ted.languageTable != 0 && ted.languageShiftTable != 0) {
- udhLength = GsmAlphabet.UDH_SEPTET_COST_TWO_SHIFT_TABLES;
- } else if (ted.languageTable != 0 || ted.languageShiftTable != 0) {
- udhLength = GsmAlphabet.UDH_SEPTET_COST_ONE_SHIFT_TABLE;
- } else {
- udhLength = 0;
- }
-
- if (ted.msgCount > 1) {
- udhLength += GsmAlphabet.UDH_SEPTET_COST_CONCATENATED_MESSAGE;
- }
-
- if (udhLength != 0) {
- udhLength += GsmAlphabet.UDH_SEPTET_COST_LENGTH;
- }
-
- limit = SmsConstants.MAX_USER_DATA_SEPTETS - udhLength;
- } else {
- if (ted.msgCount > 1) {
- limit = SmsConstants.MAX_USER_DATA_BYTES_WITH_HEADER;
- } else {
- limit = SmsConstants.MAX_USER_DATA_BYTES;
- }
- }
-
- int pos = 0;
- int textLen = text.length();
- ArrayList<String> result = new ArrayList<String>(ted.msgCount);
- while (pos < textLen) {
- int nextPos = 0;
- if (ted.codeUnitSize == SmsConstants.ENCODING_7BIT) {
- if (useCdmaFormatForMoSms() && ted.msgCount == 1) {
-
- nextPos = pos + Math.min(limit, textLen - pos);
- } else {
-
- nextPos = GsmAlphabet.findGsmSeptetLimitIndex(text, pos, limit,
- ted.languageTable, ted.languageShiftTable);
- }
- } else {
- nextPos = pos + Math.min(limit / 2, textLen - pos);
- }
- if ((nextPos <= pos) || (nextPos > textLen)) {
- Rlog.e(LOG_TAG, "fragmentText failed (" + pos + " >= " + nextPos + " or " +
- nextPos + " >= " + textLen + ")");
- break;
- }
- result.add(text.substring(pos, nextPos));
- pos = nextPos;
- }
- return result;
- }
3、sendText()的实现如下:
- public void sendTextMessage(
- String destinationAddress, String scAddress, String text,
- PendingIntent sentIntent, PendingIntent deliveryIntent) {
- if (TextUtils.isEmpty(destinationAddress)) {
- throw new IllegalArgumentException("Invalid destinationAddress");
- }
-
- if (TextUtils.isEmpty(text)) {
- throw new IllegalArgumentException("Invalid message body");
- }
-
- try {
- ISms iccISms = ISms.Stub.asInterface(ServiceManager.getService("isms"));
- if (iccISms != null) {
- iccISms.sendText(ActivityThread.currentPackageName(), destinationAddress,
- scAddress, text, sentIntent, deliveryIntent);
- }
- } catch (RemoteException ex) {
-
- }
- }
这里使用aidl的方式远程调用isms服务进行后续的发送流程,即
,IccSmsInterfaceManagerProxy的路径是frameworks/opt/telephony/src/java/com/android/internal/telephony/IccSmsInterfaceManagerProxy.java
关于isms服务的注册,它是在初始化phone进程时注册的
- public IccSmsInterfaceManagerProxy(Context context,
- IccSmsInterfaceManager iccSmsInterfaceManager) {
- this.mContext = context;
- mIccSmsInterfaceManager = iccSmsInterfaceManager;
- if(ServiceManager.getService("isms") == null) {
- ServiceManager.addService("isms", this);
- }
-
- createWakelock();
- }
iccISms.sendSms()的实现如下:
- @Override
- public void sendText(String callingPackage, String destAddr, String scAddr,
- String text, PendingIntent sentIntent, PendingIntent deliveryIntent) {
- mContext.enforceCallingPermission(
- android.Manifest.permission.SEND_SMS,
- "Sending SMS message");
- if (mIccSmsInterfaceManager.isShortSMSCode(destAddr)) {
- mIccSmsInterfaceManager.sendText(callingPackage, destAddr, scAddr, text,
- sentIntent, deliveryIntent);
- return;
- }
- ArrayList<String> parts = new ArrayList<String>();
- parts.add(text);
- ArrayList<PendingIntent> sentIntents = new ArrayList<PendingIntent>();
- sentIntents.add(sentIntent);
- ArrayList<PendingIntent> deliveryIntents = new ArrayList<PendingIntent>();
- deliveryIntents.add(deliveryIntent);
- broadcastOutgoingSms(callingPackage, destAddr, scAddr, false, parts, sentIntents,
- deliveryIntents, -1);
- }
检查发送短信的APP是否有SEND_SMS权限,再调用broadcastOutgoingSms()
- private void broadcastOutgoingSms(String callingPackage, String destAddr, String scAddr,
- boolean multipart, ArrayList<String> parts,
- ArrayList<PendingIntent> sentIntents, ArrayList<PendingIntent> deliveryIntents,
- int priority) {
- Intent broadcast = new Intent(Intent.ACTION_NEW_OUTGOING_SMS);
- broadcast.putExtra("destAddr", destAddr);
- broadcast.putExtra("scAddr", scAddr);
- broadcast.putExtra("multipart", multipart);
- broadcast.putExtra("callingPackage", callingPackage);
- broadcast.putExtra("callingUid", android.os.Binder.getCallingUid());
- broadcast.putStringArrayListExtra("parts", parts);
- broadcast.putParcelableArrayListExtra("sentIntents", sentIntents);
- broadcast.putParcelableArrayListExtra("deliveryIntents", deliveryIntents);
- broadcast.putExtra("priority", priority);
- mContext.sendOrderedBroadcastAsUser(broadcast, UserHandle.OWNER,
- android.Manifest.permission.INTERCEPT_SMS,
- mReceiver, null, Activity.RESULT_OK, destAddr, null);
- }
发送广播,Action为ACTION_NEW_OUTGOING_SMS,广播接收器就是参数中的mReceiver,mReceiver的定义如下:
- private BroadcastReceiver mReceiver = new BroadcastReceiver() {
- public void onReceive(Context context, Intent intent) {
-
- if (getResultCode() != Activity.RESULT_OK) {
- return;
- }
- String destAddr = getResultData();
- String scAddr = intent.getStringExtra("scAddr");
- String callingPackage = intent.getStringExtra("callingPackage");
- ArrayList<String> parts = intent.getStringArrayListExtra("parts");
- ArrayList<PendingIntent> sentIntents =
- intent.getParcelableArrayListExtra("sentIntents");
- ArrayList<PendingIntent> deliveryIntents =
- intent.getParcelableArrayListExtra("deliveryIntents");
-
- if (intent.getIntExtra("callingUid", 0) != 0) {
- callingPackage = callingPackage + "\\" + intent.getIntExtra("callingUid", 0);
- }
-
- if (intent.getBooleanExtra("multipart", false)) {
- mIccSmsInterfaceManager.sendMultipartText(callingPackage, destAddr, scAddr,
- parts, sentIntents, deliveryIntents);
- return;
- }
-
- PendingIntent sentIntent = null;
- if (sentIntents != null && sentIntents.size() > 0) {
- sentIntent = sentIntents.get(0);
- }
- PendingIntent deliveryIntent = null;
- if (deliveryIntents != null && deliveryIntents.size() > 0) {
- deliveryIntent = deliveryIntents.get(0);
- }
- String text = null;
- if (parts != null && parts.size() > 0) {
- text = parts.get(0);
- }
- mIccSmsInterfaceManager.sendText(callingPackage, destAddr, scAddr, text,
- sentIntent, deliveryIntent);
- }
- };
这里调用mIccSmsInterfaceManager.sendText()继续发送流程
mIccSmsInterfaceManager对应的类是IccSmsInterfaceManager,路径是
framework/opt/telephony/src/java/com/android/internal/telephony/IccSmsInterfaceManager.java
mIccSmsInterfaceManager.sendText()的实现如下:
- public void sendText(String callingPackage, String destAddr, String scAddr,
- String text, PendingIntent sentIntent, PendingIntent deliveryIntent) {
- int callingUid = Binder.getCallingUid();
-
- String[] callingParts = callingPackage.split("\\\\");
- if (callingUid == android.os.Process.PHONE_UID &&
- callingParts.length > 1) {
- callingUid = Integer.parseInt(callingParts[1]);
- }
-
- if (Binder.getCallingPid() != android.os.Process.myPid()) {
- 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, callingUid,
- callingParts[0]) != AppOpsManager.MODE_ALLOWED) {
- return;
- }
- mDispatcher.sendText(destAddr, scAddr, text, sentIntent, deliveryIntent);
- }
这里调用mDispatcher.sendText()继续发送流程
mDispatcher对应的类是SmsDispatcher,源代码的路径是
framework/opt/telephony/src/java/com/android/internal/telephony/SMSDispatcher.java
SMSDispatcher是一个abstract类,继承它的子类有CdmaSMSDispatcher、GsmSMSDispatcher和IccSMSDispatcher,
这里的mDispatcher初始化如下:
- protected IccSmsInterfaceManager(PhoneBase phone) {
- mPhone = phone;
- mContext = phone.getContext();
- mAppOps = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE);
- mDispatcher = new ImsSMSDispatcher(phone,
- phone.mSmsStorageMonitor, phone.mSmsUsageMonitor);
- }
mDispatcher.sendText()是一个abstract方法,所以是在IccSMSDispatcher中实现,代码如下:
- @Override
- protected void sendText(String destAddr, String scAddr, String text,
- PendingIntent sentIntent, PendingIntent deliveryIntent) {
- Rlog.d(TAG, "sendText");
- if (isCdmaMo()) {
- mCdmaDispatcher.sendText(destAddr, scAddr,
- text, sentIntent, deliveryIntent);
- } else {
- mGsmDispatcher.sendText(destAddr, scAddr,
- text, sentIntent, deliveryIntent);
- }
- }
这里根据sim卡的类型决定调用CdmaSMSDispatcher还是GsmSMSDispatcher,这里选择Gsm继续跟进。
mGsmDispatcher对应的类是GsmSMSDispatcher,源代码路径是
framework/opt/telephony/src/java/com/android/internal/telephony/GsmSMSDispatcher.java
mGsmDispatcher.sendText()的流程如下:
- @Override
- protected void sendText(String destAddr, String scAddr, String text,
- PendingIntent sentIntent, PendingIntent deliveryIntent) {
- SmsMessage.SubmitPdu pdu = SmsMessage.getSubmitPdu(
- scAddr, destAddr, text, (deliveryIntent != null));
- if (pdu != null) {
- HashMap map = getSmsTrackerMap(destAddr, scAddr, text, pdu);
- SmsTracker tracker = getSmsTracker(map, sentIntent, deliveryIntent,
- getFormat());
- sendRawPdu(tracker);
- } else {
- Rlog.e(TAG, "GsmSMSDispatcher.sendText(): getSubmitPdu() returned null");
- }
- }
这里构造了SubmitPdu和SmsTracker对象,然后执行sendRawPdu(),这个方法是在父类SMSDiapatcher中实现的,代码如下:
- protected void sendRawPdu(SmsTracker tracker) {
- n style="white-space:pre"> </span>...
-
-
-
-
- if (checkDestination(tracker)) {
-
- if (!mUsageMonitor.check(appInfo.packageName, SINGLE_PART_SMS)) {
- sendMessage(obtainMessage(EVENT_SEND_LIMIT_REACHED_CONFIRMATION, tracker));
- return;
- }
-
- int ss = mPhone.getServiceState().getState();
-
-
- if (!isIms() && ss != ServiceState.STATE_IN_SERVICE) {
- handleNotInService(ss, tracker.mSentIntent);
- } else {
- sendSms(tracker);
- }
- }
- }
这里调用sendSms()继续发送流程,sendSms()是一个abstract方法,所以这里是在子类GsmSMSDispatcher中实现的,代码如下:
- @Override
- protected void sendSms(SmsTracker tracker) {
- HashMap<String, Object> map = tracker.mData;
-
- byte smsc[] = (byte[]) map.get("smsc");
- byte pdu[] = (byte[]) map.get("pdu");
-
- Message reply = obtainMessage(EVENT_SEND_SMS_COMPLETE, tracker);
-
- if (tracker.mRetryCount > 0) {
- Rlog.d(TAG, "sendSms: "
- + " mRetryCount=" + tracker.mRetryCount
- + " mMessageRef=" + tracker.mMessageRef
- + " SS=" + mPhone.getServiceState().getState());
-
-
-
-
- if (((0x01 & pdu[0]) == 0x01)) {
- pdu[0] |= 0x04;
- pdu[1] = (byte) tracker.mMessageRef;
- }
- }
- Rlog.d(TAG, "sendSms: "
- +" isIms()="+isIms()
- +" mRetryCount="+tracker.mRetryCount
- +" mImsRetry="+tracker.mImsRetry
- +" mMessageRef="+tracker.mMessageRef
- +" SS=" +mPhone.getServiceState().getState());
-
-
-
-
-
- if (0 == tracker.mImsRetry && !isIms()) {
- if (tracker.mRetryCount > 0) {
-
-
-
- if (((0x01 & pdu[0]) == 0x01)) {
- pdu[0] |= 0x04;
- pdu[1] = (byte) tracker.mMessageRef;
- }
- }
- mCi.sendSMS(IccUtils.bytesToHexString(smsc),
- IccUtils.bytesToHexString(pdu), reply);
- } else {
- mCi.sendImsGsmSms(IccUtils.bytesToHexString(smsc),
- IccUtils.bytesToHexString(pdu), tracker.mImsRetry,
- tracker.mMessageRef, reply);
-
-
- tracker.mImsRetry++;
- }
- }
这里最终调用mCi.sendSms()继续发送流程,
mCi对应的类是CommandInterface,CommandInterface是一个Interface,RIL是它的一个子类,
也就是说短信发送在此处会调用RIL.java,执行sendText()方法,代码如下:
- public void
- sendSMS (String smscPDU, String pdu, Message result) {
- RILRequest rr
- = RILRequest.obtain(RIL_REQUEST_SEND_SMS, result);
-
- constructGsmSendSmsRilRequest(rr, smscPDU, pdu);
-
- if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
-
- send(rr);
- }
程序交给send(RILRequest req)继续执行,代码如下:
- protected void
- send(RILRequest rr) {
- Message msg;
-
- if (mSocket == null) {
- rr.onError(RADIO_NOT_AVAILABLE, null);
- rr.release();
- return;
- }
-
- msg = mSender.obtainMessage(EVENT_SEND, rr);
-
- acquireWakeLock();
-
- msg.sendToTarget();
- }
接下来RIL会将pdu等信息打包,通过socket发送给下层处理,最终形成at指令发送短信。
如果短信发送成功,还记得在发送时,从GsmSmsDispatcher.java传递到RIL.java中的Message吗,在发送之后,RIL.java会回调此Message,这个Message如下
- Message reply = obtainMessage(EVENT_SEND_SMS_COMPLETE, tracker);
What = EVENT_SEND_SMS_COMPLETE,Object = tricker。SmsDispacher.java本身是一个Handler,所以这个Message最终在SmsDispacher.java中处理,处理逻辑代码如下:
- @Override
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case EVENT_SEND_SMS_COMPLETE:
-
- handleSendComplete((AsyncResult) msg.obj);
- break;
handleSendComplete的实现如下:
- protected void handleSendComplete(AsyncResult ar) {
- SmsTracker tracker = (SmsTracker) ar.userObj;
- PendingIntent sentIntent = tracker.mSentIntent;
-
- if (ar.result != null) {
- tracker.mMessageRef = ((SmsResponse)ar.result).mMessageRef;
- } else {
- Rlog.d(TAG, "SmsResponse was null");
- }
-
- if (ar.exception == null) {
- if (DBG) Rlog.d(TAG, "SMS send complete. Broadcasting intent: " + sentIntent);
-
- if (SmsApplication.shouldWriteMessageForPackage(
- tracker.mAppInfo.applicationInfo.packageName, mContext)) {
-
-
- tracker.writeSentMessage(mContext);
- }
-
- if (tracker.mDeliveryIntent != null) {
-
- deliveryPendingList.add(tracker);
- }
-
- if (sentIntent != null) {
- try {
- if (mRemainingMessages > -1) {
- mRemainingMessages--;
- }
-
- if (mRemainingMessages == 0) {
- Intent sendNext = new Intent();
- sendNext.putExtra(SEND_NEXT_MSG_EXTRA, true);
- sentIntent.send(mContext, Activity.RESULT_OK, sendNext);
- } else {
- sentIntent.send(Activity.RESULT_OK);
- }
- } catch (CanceledException ex) {}
- }
- } else {
- if (DBG) Rlog.d(TAG, "SMS send failed");
-
- int ss = mPhone.getServiceState().getState();
-
- if ( tracker.mImsRetry > 0 && ss != ServiceState.STATE_IN_SERVICE) {
-
-
-
- tracker.mRetryCount = MAX_SEND_RETRIES;
-
- Rlog.d(TAG, "handleSendComplete: Skipping retry: "
- +" isIms()="+isIms()
- +" mRetryCount="+tracker.mRetryCount
- +" mImsRetry="+tracker.mImsRetry
- +" mMessageRef="+tracker.mMessageRef
- +" SS= "+mPhone.getServiceState().getState());
- }
-
-
- if (!isIms() && ss != ServiceState.STATE_IN_SERVICE) {
- handleNotInService(ss, tracker.mSentIntent);
- } else if ((((CommandException)(ar.exception)).getCommandError()
- == CommandException.Error.SMS_FAIL_RETRY) &&
- tracker.mRetryCount < MAX_SEND_RETRIES) {
-
-
-
-
-
-
-
-
- tracker.mRetryCount++;
- Message retryMsg = obtainMessage(EVENT_SEND_RETRY, tracker);
- sendMessageDelayed(retryMsg, SEND_RETRY_DELAY);
- } else if (tracker.mSentIntent != null) {
- int error = RESULT_ERROR_GENERIC_FAILURE;
-
- if (((CommandException)(ar.exception)).getCommandError()
- == CommandException.Error.FDN_CHECK_FAILURE) {
- error = RESULT_ERROR_FDN_CHECK_FAILURE;
- }
-
- try {
- Intent fillIn = new Intent();
- if (ar.result != null) {
- fillIn.putExtra("errorCode", ((SmsResponse)ar.result).mErrorCode);
- }
- if (mRemainingMessages > -1) {
- mRemainingMessages--;
- }
-
- if (mRemainingMessages == 0) {
- fillIn.putExtra(SEND_NEXT_MSG_EXTRA, true);
- }
-
- tracker.mSentIntent.send(mContext, error, fillIn);
- } catch (CanceledException ex) {}
- }
- }
- }
至此就是短信发送的在framework中的大体流程
首先检查AsyncResult对象中是否存在异常,如果成功发送的信息,那么不存在异常,如果发送失败,那么是存在Exception的,会进行异常的相应的逻辑处理,大体流程相似,故本处介绍无异常时的流程逻辑。
- if (SmsApplication.shouldWriteMessageForPackage(
- tracker.mAppInfo.applicationInfo.packageName, mContext)) {
-
-
- tracker.writeSentMessage(mContext);
- }
这里判断发送短信的app是否是默认短信,如果不是则保存该条短信到TelephonyProvider中。
最后会发送一个广播,这个广播的intent是PendingIntent,是在Mms中构造的,SmsReceiverService.java会接受该广播并处理,比如保存短信的状态,失败或者发送成功。
发送流程大概就是这样了。
转自:http://blog.csdn.net/aiai373824745/article/details/20614371