前言:最近需要做iot上的相关需求,设计到短信app,本文梳理了Framework层的大致流程。

短信发送包括发送一般的短信、彩信. 发送的请求从app层通过SmsManager对象的sendMultipartTextMessage方法调用,传递到了Telephony Framework层中,Telephony Framework层与RIL层交互,最终完成短信的发送请求,转换成RIL请求,其处理流程如下所示:

本文基于9.0的源码,梳理的流程。按照以上流程图,找出对应关键位置的源码,方便梳理整个短信发送在Framework层的整个流程。

SmsManager

//SmsManager
public void sendTextMessage(String destinationAddress, String scAddress, String text,PendingIntent sentIntent, PendingIntent deliveryIntent,int priority, boolean expectMore, int validityPeriod) {sendTextMessageInternal(destinationAddress, scAddress, text, sentIntent, deliveryIntent,true /* persistMessage*/, priority, expectMore, validityPeriod);
}private void sendTextMessageInternal(String destinationAddress, String scAddress, String text,PendingIntent sentIntent, PendingIntent deliveryIntent, boolean persistMessage,int priority, boolean expectMore, int validityPeriod) {...try {//AIDL 调用ISms iccISms = getISmsServiceOrThrow();if (iccISms != null) {// 搜索sendTextForSubscriberWithOptions,在UiccSmsController iccISms.sendTextForSubscriberWithOptions(getSubscriptionId(),ActivityThread.currentPackageName(), destinationAddress, scAddress, text,sentIntent, deliveryIntent, persistMessage,  priority, expectMore,validityPeriod);}} catch (RemoteException ex) {// ignore it}
}
复制代码

UiccSmsController

//com.android.internal.telephony.UiccSmsController
@Overridepublic void sendTextForSubscriberWithOptions(int subId, String callingPackage,String destAddr, String scAddr, String parts, PendingIntent sentIntents,PendingIntent deliveryIntents, boolean persistMessage, int priority,boolean expectMore, int validityPeriod) {IccSmsInterfaceManager iccSmsIntMgr = getIccSmsInterfaceManager(subId);if (iccSmsIntMgr != null ) {//调用 IccSmsInterfaceManager的 sendTextWithOptions 方法iccSmsIntMgr.sendTextWithOptions(callingPackage, destAddr, scAddr, parts, sentIntents,deliveryIntents, persistMessage,  priority, expectMore, validityPeriod);} else {Rlog.e(LOG_TAG,"sendTextWithOptions iccSmsIntMgr is null for" +" Subscription: " + subId);}}
复制代码

IccSmsInterfaceManager

//IccSmsInterfaceManager
public void sendMultipartText(String callingPackage, String destAddr, String scAddr,List<String> parts, List<PendingIntent> sentIntents,List<PendingIntent> deliveryIntents, boolean persistMessageForNonDefaultSmsApp) {sendMultipartTextWithOptions(callingPackage, destAddr, scAddr, parts, sentIntents,deliveryIntents, persistMessageForNonDefaultSmsApp,SMS_MESSAGE_PRIORITY_NOT_SPECIFIED, false /* expectMore */,SMS_MESSAGE_PERIOD_NOT_SPECIFIED);}//转移到 mDispatchersController
public void sendMultipartTextWithOptions(String callingPackage, String destAddr,String scAddr, List<String> parts, List<PendingIntent> sentIntents,List<PendingIntent> deliveryIntents, boolean persistMessageForNonDefaultSmsApp,int priority, boolean expectMore, int validityPeriod) {if (!checkCallingSendTextPermissions(persistMessageForNonDefaultSmsApp, callingPackage, "Sending SMS message")) {return;}if (Rlog.isLoggable("SMS", Log.VERBOSE)) {int i = 0;for (String part : parts) {log("sendMultipartTextWithOptions: destAddr=" + destAddr + ", srAddr=" + scAddr +", part[" + (i++) + "]=" + part);}}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);}mDispatchersController.sendText(destAddr, scAddr, singlePart,singleSentIntent, singleDeliveryIntent,null/*messageUri*/, callingPackage,persistMessageForNonDefaultSmsApp,priority, expectMore, validityPeriod);}return;}//转移到 mDispatchersControllermDispatchersController.sendMultipartText(destAddr,scAddr,(ArrayList<String>) parts,(ArrayList<PendingIntent>) sentIntents,(ArrayList<PendingIntent>) deliveryIntents,null, callingPackage, persistMessageForNonDefaultSmsApp,priority, expectMore, validityPeriod);}
复制代码

SMSDispatcher

转到SmsDispatchersController,分别调用 sendData、sendText、sendMultipartText

protected void sendMultipartText(String destAddr, String scAddr,ArrayList<String> parts, ArrayList<PendingIntent> sentIntents,ArrayList<PendingIntent> deliveryIntents, Uri messageUri, String callingPkg,boolean persistMessage, int priority, boolean expectMore, int validityPeriod) {if (mImsSmsDispatcher.isAvailable()) {mImsSmsDispatcher.sendMultipartText(destAddr, scAddr, parts, sentIntents,deliveryIntents, messageUri, callingPkg, persistMessage,SMS_MESSAGE_PRIORITY_NOT_SPECIFIED,false /*expectMore*/, SMS_MESSAGE_PERIOD_NOT_SPECIFIED);} else {if (isCdmaMo()) {mCdmaDispatcher.sendMultipartText(destAddr, scAddr, parts, sentIntents,deliveryIntents, messageUri, callingPkg, persistMessage, priority,expectMore, validityPeriod);} else {mGsmDispatcher.sendMultipartText(destAddr, scAddr, parts, sentIntents,deliveryIntents, messageUri, callingPkg, persistMessage, priority,expectMore, validityPeriod);}}}
复制代码

SMSDispatcher

protected void sendData(String destAddr, String scAddr, int destPort,byte[] data, PendingIntent sentIntent, PendingIntent deliveryIntent) {SmsMessageBase.SubmitPduBase pdu = getSubmitPdu(scAddr, destAddr, destPort, data, (deliveryIntent != null));if (pdu != null) {HashMap map = getSmsTrackerMap(destAddr, scAddr, destPort, data, pdu);SmsTracker tracker = getSmsTracker(map, sentIntent, deliveryIntent, getFormat(),null /*messageUri*/, false /*expectMore*/,null /*fullMessageText*/, false /*isText*/,true /*persistMessage*/);if (!sendSmsByCarrierApp(true /* isDataSms */, tracker)) {sendSubmitPdu(tracker);}} else {Rlog.e(TAG, "SMSDispatcher.sendData(): getSubmitPdu() returned null");triggerSentIntentForFailure(sentIntent);}}protected void sendMultipartText(String destAddr, String scAddr,ArrayList<String> parts, ArrayList<PendingIntent> sentIntents,ArrayList<PendingIntent> deliveryIntents, Uri messageUri, String callingPkg,boolean persistMessage, int priority, boolean expectMore, int validityPeriod) {final String fullMessageText = getMultipartMessageText(parts);int refNumber = getNextConcatenatedRef() & 0x00FF;int msgCount = parts.size();int encoding = SmsConstants.ENCODING_UNKNOWN;TextEncodingDetails[] encodingForParts = new TextEncodingDetails[msgCount];for (int i = 0; i < msgCount; i++) {TextEncodingDetails details = calculateLength(parts.get(i), false);if (encoding != details.codeUnitSize&& (encoding == SmsConstants.ENCODING_UNKNOWN|| encoding == SmsConstants.ENCODING_7BIT)) {encoding = details.codeUnitSize;}encodingForParts[i] = details;}SmsTracker[] trackers = new SmsTracker[msgCount];// States to track at the message level (for all parts)final AtomicInteger unsentPartCount = new AtomicInteger(msgCount);final AtomicBoolean anyPartFailed = new AtomicBoolean(false);for (int i = 0; i < msgCount; i++) {SmsHeader.ConcatRef concatRef = new SmsHeader.ConcatRef();concatRef.refNumber = refNumber;concatRef.seqNumber = i + 1;  // 1-based sequenceconcatRef.msgCount = msgCount;// TODO: We currently set this to true since our messaging app will never// send more than 255 parts (it converts the message to MMS well before that).// However, we should support 3rd party messaging apps that might need 16-bit// references// Note:  It's not sufficient to just flip this bit to true; it will have// ripple effects (several calculations assume 8-bit ref).concatRef.isEightBits = true;SmsHeader smsHeader = new SmsHeader();smsHeader.concatRef = concatRef;// Set the national language tables for 3GPP 7-bit encoding, if enabled.if (encoding == SmsConstants.ENCODING_7BIT) {smsHeader.languageTable = encodingForParts[i].languageTable;smsHeader.languageShiftTable = encodingForParts[i].languageShiftTable;}PendingIntent sentIntent = null;if (sentIntents != null && sentIntents.size() > i) {sentIntent = sentIntents.get(i);}PendingIntent deliveryIntent = null;if (deliveryIntents != null && deliveryIntents.size() > i) {deliveryIntent = deliveryIntents.get(i);}trackers[i] =getNewSubmitPduTracker(destAddr, scAddr, parts.get(i), smsHeader, encoding,sentIntent, deliveryIntent, (i == (msgCount - 1)),unsentPartCount, anyPartFailed, messageUri,fullMessageText, priority, expectMore, validityPeriod);trackers[i].mPersistMessage = persistMessage;}if (parts == null || trackers == null || trackers.length == 0|| trackers[0] == null) {Rlog.e(TAG, "Cannot send multipart text. parts=" + parts + " trackers=" + trackers);return;}String carrierPackage = getCarrierAppPackageName();if (carrierPackage != null) {Rlog.d(TAG, "Found carrier package.");MultipartSmsSender smsSender = new MultipartSmsSender(parts, trackers);smsSender.sendSmsByCarrierApp(carrierPackage,new MultipartSmsSenderCallback(smsSender));} else {Rlog.v(TAG, "No carrier package.");for (SmsTracker tracker : trackers) {if (tracker != null) {sendSubmitPdu(tracker);} else {Rlog.e(TAG, "Null tracker.");}}}}
复制代码

都调用sendSubmitPdu(tracker);

private void sendSubmitPdu(SmsTracker tracker) {if (shouldBlockSmsForEcbm()) {Rlog.d(TAG, "Block SMS in Emergency Callback mode");tracker.onFailed(mContext, SmsManager.RESULT_ERROR_NO_SERVICE, 0/*errorCode*/);} else {sendRawPdu(tracker);}}// sendRawPdu
@VisibleForTesting
public void sendRawPdu(SmsTracker tracker) {HashMap map = tracker.getData();byte pdu[] = (byte[]) map.get(MAP_KEY_PDU);if (mSmsSendDisabled) {Rlog.e(TAG, "Device does not support sending sms.");tracker.onFailed(mContext, RESULT_ERROR_NO_SERVICE, 0/*errorCode*/);return;}if (pdu == null) {Rlog.e(TAG, "Empty PDU");tracker.onFailed(mContext, RESULT_ERROR_NULL_PDU, 0/*errorCode*/);return;}// Get calling app package name via UID from Binder callPackageManager pm = mContext.getPackageManager();String[] packageNames = pm.getPackagesForUid(Binder.getCallingUid());if (packageNames == null || packageNames.length == 0) {// Refuse to send SMS if we can't get the calling package name.Rlog.e(TAG, "Can't get calling app package name: refusing to send SMS");tracker.onFailed(mContext, RESULT_ERROR_GENERIC_FAILURE, 0/*errorCode*/);return;}// Get package info via packagemanagerPackageInfo appInfo;try {// XXX this is lossy- apps can share a UIDappInfo = pm.getPackageInfoAsUser(packageNames[0], PackageManager.GET_SIGNATURES, tracker.mUserId);} catch (PackageManager.NameNotFoundException e) {Rlog.e(TAG, "Can't get calling app package info: refusing to send SMS");tracker.onFailed(mContext, RESULT_ERROR_GENERIC_FAILURE, 0/*errorCode*/);return;}// checkDestination() returns true if the destination is not a premium short code or the// sending app is approved to send to short codes. Otherwise, a message is sent to our// handler with the SmsTracker to request user confirmation before sending.if (checkDestination(tracker)) {// check for excessive outgoing SMS usage by this appif (!mSmsDispatchersController.getUsageMonitor().check(appInfo.packageName, SINGLE_PART_SMS)) {sendMessage(obtainMessage(EVENT_SEND_LIMIT_REACHED_CONFIRMATION, tracker));return;}//抽象方法:sendSms(tracker);}if (PhoneNumberUtils.isLocalEmergencyNumber(mContext, tracker.mDestAddress)) {new AsyncEmergencyContactNotifier(mContext).execute();}}//子类实现
/*** Send the message along to the radio.** @param tracker holds the SMS message to send*/protected abstract void sendSms(SmsTracker tracker);
复制代码

SMSDispatcher的子类 GsmSMSDispatcher、CdmaSMSDispatcher

/** {@inheritDoc} */@Overridepublic void sendSms(SmsTracker tracker) {Rlog.d(TAG, "sendSms: "+ " isIms()=" + isIms()+ " mRetryCount=" + tracker.mRetryCount+ " mImsRetry=" + tracker.mImsRetry+ " mMessageRef=" + tracker.mMessageRef+ " mUsesImsServiceForIms=" + tracker.mUsesImsServiceForIms+ " SS=" + mPhone.getServiceState().getState());int ss = mPhone.getServiceState().getState();// if sms over IMS is not supported on data and voice is not available...if (!isIms() && ss != ServiceState.STATE_IN_SERVICE) {tracker.onFailed(mContext, getNotInServiceError(ss), 0/*errorCode*/);return;}Message reply = obtainMessage(EVENT_SEND_SMS_COMPLETE, tracker);byte[] pdu = (byte[]) tracker.getData().get("pdu");int currentDataNetwork = mPhone.getServiceState().getDataNetworkType();boolean imsSmsDisabled = (currentDataNetwork == TelephonyManager.NETWORK_TYPE_EHRPD|| (ServiceState.isLte(currentDataNetwork)&& !mPhone.getServiceStateTracker().isConcurrentVoiceAndDataAllowed()))&& mPhone.getServiceState().getVoiceNetworkType()== TelephonyManager.NETWORK_TYPE_1xRTT&& ((GsmCdmaPhone) mPhone).mCT.mState != PhoneConstants.State.IDLE;// sms over cdma is used://   if sms over IMS is not supported AND//   this is not a retry case after sms over IMS failed//     indicated by mImsRetry > 0 OR//   SMS over IMS is disabled because of the network type OR//   SMS over IMS is being handled by the ImsSmsDispatcher implementation and has indicated//   that the message should fall back to sending over CS.if (0 == tracker.mImsRetry && !isIms() || imsSmsDisabled || tracker.mUsesImsServiceForIms) {mCi.sendCdmaSms(pdu, reply);} else {mCi.sendImsCdmaSms(pdu, tracker.mImsRetry, tracker.mMessageRef, reply);// increment it here, so in case of SMS_FAIL_RETRY over IMS// next retry will be sent using IMS request again.tracker.mImsRetry++;}}
复制代码

Phone(CommandsInterface)

SMSDispatcher类是通过sendSMS方法与RIL交互的,sendSMS方法又是由子类GSMDispatcher或者CDMADispatcher具体实现的。现在分析一下GSMDispatcher类中该方法的逻辑实现。

mCi.sendCdmaSms(pdu, reply); 以及mCi.sendImsCdmaSms(pdu, tracker.mImsRetry, tracker.mMessageRef, reply);中的 mCi是 Phone中的 CommandInterface接口对象。

PhoneProxy/GSMPhone/CDMAPhone

如果说RILJ提供了工具或管道,那么Phone接口的子类及PhoneFactory则为packages/app/Phone这个应用程序进程使用RILJ这个工具或管道提供了极大的方便,它们一个管理整个整个手机的Telephony功能。

GSMPhone和CDMAPhone实现了Phone中定义的接口。接口类Phone定义了一套API,这套API用于使用RILJ(见后述RIL类)发送AT命令请求,也还有一套register和unregister函数;当调用者对一些内部状态感兴趣时,可以调用对应的register函数,当状态变化时可以得到及时通知。

PhoneBase实现了Phone接口中定义的部分函数,还有一部分由其子类GSMPhone和CDMAPhone实现。PhoneProxy是GSMPhone和CDMAPhone的代理,让使用者不用关注手机到底是GSM还是CDMA,它遵守Phone定义的API接口,因此继承Phone。

PhoneFactory在创建Phone对象时,拥有的是PhoneProxy对象,PhoneProxy根据实际的网络类型创建对应的GSMPhone或CDMAPhone。

PhoneFactory同样拥有CommandInterface的接口对象,即RIL的实例,该RIL实例将被传递给GSMPhone或CDMAPhone,即GSMPhone或CDMAPhone引用它,实现与rild的交互。

//PhoneFactory中makeDefaultPhone 创建  Phone对象,并且创建Phone中的 sCommandsInterfaces = new RIL[numPhones], 即对应的RILpublic static void makeDefaultPhone(Context context) {....int[] networkModes = new int[numPhones];sPhones = new Phone[numPhones];sCommandsInterfaces = new RIL[numPhones];sTelephonyNetworkFactories = new TelephonyNetworkFactory[numPhones];for (int i = 0; i < numPhones; i++) {// reads the system properties and makes commandsinterface// Get preferred network type.networkModes[i] = RILConstants.PREFERRED_NETWORK_MODE;Rlog.i(LOG_TAG, "Network Mode set to " + Integer.toString(networkModes[i]));sCommandsInterfaces[i] = new RIL(context, networkModes[i],cdmaSubscription, i);}Rlog.i(LOG_TAG, "Creating SubscriptionController");SubscriptionController.init(context, sCommandsInterfaces);// Instantiate UiccController so that all other classes can just// call getInstance()sUiccController = UiccController.make(context, sCommandsInterfaces);....for (int i = 0; i < numPhones; i++) {Phone phone = null;int phoneType = TelephonyManager.getPhoneType(networkModes[i]);if (phoneType == PhoneConstants.PHONE_TYPE_GSM) {phone = new GsmCdmaPhone(context,sCommandsInterfaces[i], sPhoneNotifier, i,PhoneConstants.PHONE_TYPE_GSM,TelephonyComponentFactory.getInstance());} else if (phoneType == PhoneConstants.PHONE_TYPE_CDMA) {//把  RIL对象给到phonephone = new GsmCdmaPhone(context,sCommandsInterfaces[i], sPhoneNotifier, i,PhoneConstants.PHONE_TYPE_CDMA_LTE,TelephonyComponentFactory.getInstance());}Rlog.i(LOG_TAG, "Creating Phone with type = " + phoneType + " sub = " + i);sPhones[i] = phone;}
}
复制代码

RIL

首先查找:package com.android.internal.telephony; 下的RILConstants, 找到跟 SMS 相关的 Message常量,

//请求
int RIL_REQUEST_CDMA_SEND_SMS = 87;
int RIL_REQUEST_CDMA_SMS_ACKNOWLEDGE = 88;//接收
int RIL_UNSOL_RESPONSE_NEW_SMS = 1003;
int RIL_UNSOL_RESPONSE_NEW_SMS_STATUS_REPORT = 1004;
int RIL_UNSOL_RESPONSE_NEW_SMS_ON_SIM = 1005;// 在sim卡上写、删除sms
int RIL_REQUEST_WRITE_SMS_TO_SIM = 63;
int RIL_REQUEST_DELETE_SMS_ON_SIM = 64;//发送
int RIL_REQUEST_IMS_SEND_SMS = 113;复制代码

Framework层:package com.android.internal.telephony; 下的 RIL.java 文件包含两个class,class RILRequest public final class RIL extends BaseCommands implements CommandsInterface。

switch(response) {....case RIL_UNSOL_RESPONSE_NEW_SMS: {if (RILJ_LOGD) unsljLog(response);// FIXME this should move up a layerString a[] = new String[2];a[1] = (String)ret;SmsMessage sms;sms = SmsMessage.newFromCMT(a);if (mGsmSmsRegistrant != null) {mGsmSmsRegistrant.notifyRegistrant(new AsyncResult(null, sms, null));}break;}case RIL_UNSOL_RESPONSE_NEW_SMS_STATUS_REPORT:if (RILJ_LOGD) unsljLogRet(response, ret);if (mSmsStatusRegistrant != null) {mSmsStatusRegistrant.notifyRegistrant(new AsyncResult(null, ret, null));}break;case RIL_UNSOL_RESPONSE_NEW_SMS_ON_SIM:if (RILJ_LOGD) unsljLogRet(response, ret);int[] smsIndex = (int[])ret;if(smsIndex.length == 1) {if (mSmsOnSimRegistrant != null) {mSmsOnSimRegistrant.notifyRegistrant(new AsyncResult(null, smsIndex, null));}} else {if (RILJ_LOGD) riljLog(" NEW_SMS_ON_SIM ERROR with wrong length "+ smsIndex.length);}break;
复制代码

RIL中收发送短信的函数:

private voidconstructGsmSendSmsRilRequest (RILRequest rr, String smscPDU, String pdu) {rr.mParcel.writeInt(2);rr.mParcel.writeString(smscPDU);rr.mParcel.writeString(pdu);}public voidsendSMS (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);}@Overridepublic voidsendSMSExpectMore (String smscPDU, String pdu, Message result) {RILRequest rr= RILRequest.obtain(RIL_REQUEST_SEND_SMS_EXPECT_MORE, result);constructGsmSendSmsRilRequest(rr, smscPDU, pdu);if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));send(rr);}private voidconstructCdmaSendSmsRilRequest(RILRequest rr, byte[] pdu) {int address_nbr_of_digits;int subaddr_nbr_of_digits;int bearerDataLength;ByteArrayInputStream bais = new ByteArrayInputStream(pdu);DataInputStream dis = new DataInputStream(bais);try {rr.mParcel.writeInt(dis.readInt()); //teleServiceIdrr.mParcel.writeByte((byte) dis.readInt()); //servicePresentrr.mParcel.writeInt(dis.readInt()); //serviceCategoryrr.mParcel.writeInt(dis.read()); //address_digit_moderr.mParcel.writeInt(dis.read()); //address_nbr_moderr.mParcel.writeInt(dis.read()); //address_tonrr.mParcel.writeInt(dis.read()); //address_nbr_planaddress_nbr_of_digits = (byte) dis.read();rr.mParcel.writeByte((byte) address_nbr_of_digits);for(int i=0; i < address_nbr_of_digits; i++){rr.mParcel.writeByte(dis.readByte()); // address_orig_bytes[i]}rr.mParcel.writeInt(dis.read()); //subaddressTyperr.mParcel.writeByte((byte) dis.read()); //subaddr_oddsubaddr_nbr_of_digits = (byte) dis.read();rr.mParcel.writeByte((byte) subaddr_nbr_of_digits);for(int i=0; i < subaddr_nbr_of_digits; i++){rr.mParcel.writeByte(dis.readByte()); //subaddr_orig_bytes[i]}bearerDataLength = dis.read();rr.mParcel.writeInt(bearerDataLength);for(int i=0; i < bearerDataLength; i++){rr.mParcel.writeByte(dis.readByte()); //bearerData[i]}}catch (IOException ex){if (RILJ_LOGD) riljLog("sendSmsCdma: conversion from input stream to object failed: "+ ex);}}public voidsendCdmaSms(byte[] pdu, Message result) {RILRequest rr= RILRequest.obtain(RIL_REQUEST_CDMA_SEND_SMS, result);constructCdmaSendSmsRilRequest(rr, pdu);if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));send(rr);}public voidsendImsGsmSms (String smscPDU, String pdu, int retry, int messageRef,Message result) {RILRequest rr = RILRequest.obtain(RIL_REQUEST_IMS_SEND_SMS, result);rr.mParcel.writeInt(RILConstants.GSM_PHONE);rr.mParcel.writeByte((byte)retry);rr.mParcel.writeInt(messageRef);constructGsmSendSmsRilRequest(rr, smscPDU, pdu);if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));send(rr);}public voidsendImsCdmaSms(byte[] pdu, int retry, int messageRef, Message result) {RILRequest rr = RILRequest.obtain(RIL_REQUEST_IMS_SEND_SMS, result);rr.mParcel.writeInt(RILConstants.CDMA_PHONE);rr.mParcel.writeByte((byte)retry);rr.mParcel.writeInt(messageRef);constructCdmaSendSmsRilRequest(rr, pdu);if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));send(rr);}@Overridepublic void deleteSmsOnSim(int index, Message response) {RILRequest rr = RILRequest.obtain(RIL_REQUEST_DELETE_SMS_ON_SIM,response);rr.mParcel.writeInt(1);rr.mParcel.writeInt(index);if (RILJ_LOGV) riljLog(rr.serialString() + "> "+ requestToString(rr.mRequest)+ " " + index);send(rr);}@Overridepublic void deleteSmsOnRuim(int index, Message response) {RILRequest rr = RILRequest.obtain(RIL_REQUEST_CDMA_DELETE_SMS_ON_RUIM,response);rr.mParcel.writeInt(1);rr.mParcel.writeInt(index);if (RILJ_LOGV) riljLog(rr.serialString() + "> "+ requestToString(rr.mRequest)+ " " + index);send(rr);}@Overridepublic void writeSmsToSim(int status, String smsc, String pdu, Message response) {status = translateStatus(status);RILRequest rr = RILRequest.obtain(RIL_REQUEST_WRITE_SMS_TO_SIM,response);rr.mParcel.writeInt(status);rr.mParcel.writeString(pdu);rr.mParcel.writeString(smsc);if (RILJ_LOGV) riljLog(rr.serialString() + "> "+ requestToString(rr.mRequest)+ " " + status);send(rr);}@Overridepublic void writeSmsToRuim(int status, String pdu, Message response) {status = translateStatus(status);RILRequest rr = RILRequest.obtain(RIL_REQUEST_CDMA_WRITE_SMS_TO_RUIM,response);rr.mParcel.writeInt(status);rr.mParcel.writeString(pdu);if (RILJ_LOGV) riljLog(rr.serialString() + "> "+ requestToString(rr.mRequest)+ " " + status);send(rr);}/***  Translates EF_SMS status bits to a status value compatible with*  SMS AT commands.  See TS 27.005 3.1.*/private int translateStatus(int status) {switch(status & 0x7) {case SmsManager.STATUS_ON_ICC_READ:return 1;case SmsManager.STATUS_ON_ICC_UNREAD:return 0;case SmsManager.STATUS_ON_ICC_SENT:return 3;case SmsManager.STATUS_ON_ICC_UNSENT:return 2;}// Default to READ.return 1;}
复制代码

都是调用 send(RILRequest rr)函数, 通过Handler来处理的

private voidsend(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();}
复制代码

在RILSender(Handler)中处理请求:

class RILSender extends Handler implements Runnable {public RILSender(Looper looper) {super(looper);}// Only allocated oncebyte[] dataLength = new byte[4];//***** Runnable implementation@Overridepublic voidrun() {//setup if needed}//***** Handler implementation@Override public voidhandleMessage(Message msg) {RILRequest rr = (RILRequest)(msg.obj);RILRequest req = null;switch (msg.what) {case EVENT_SEND:try {LocalSocket s;s = mSocket;if (s == null) {rr.onError(RADIO_NOT_AVAILABLE, null);rr.release();decrementWakeLock();return;}synchronized (mRequestList) {mRequestList.append(rr.mSerial, rr);}byte[] data;data = rr.mParcel.marshall();rr.mParcel.recycle();rr.mParcel = null;if (data.length > RIL_MAX_COMMAND_BYTES) {throw new RuntimeException("Parcel larger than max bytes allowed! "+ data.length);}// parcel length in big endiandataLength[0] = dataLength[1] = 0;dataLength[2] = (byte)((data.length >> 8) & 0xff);dataLength[3] = (byte)((data.length) & 0xff);//Rlog.v(RILJ_LOG_TAG, "writing packet: " + data.length + " bytes");s.getOutputStream().write(dataLength);s.getOutputStream().write(data);} catch (IOException ex) {Rlog.e(RILJ_LOG_TAG, "IOException", ex);req = findAndRemoveRequestFromList(rr.mSerial);// make sure this request has not already been handled,// eg, if RILReceiver cleared the list.if (req != null) {rr.onError(RADIO_NOT_AVAILABLE, null);rr.release();decrementWakeLock();}} catch (RuntimeException exc) {Rlog.e(RILJ_LOG_TAG, "Uncaught exception ", exc);req = findAndRemoveRequestFromList(rr.mSerial);// make sure this request has not already been handled,// eg, if RILReceiver cleared the list.if (req != null) {rr.onError(GENERIC_FAILURE, null);rr.release();decrementWakeLock();}}break;case EVENT_WAKE_LOCK_TIMEOUT:// Haven't heard back from the last request.  Assume we're// not getting a response and  release the wake lock.// The timer of WAKE_LOCK_TIMEOUT is reset with each// new send request. So when WAKE_LOCK_TIMEOUT occurs// all requests in mRequestList already waited at// least DEFAULT_WAKE_LOCK_TIMEOUT but no response.//// Note: Keep mRequestList so that delayed response// can still be handled when response finally comes.synchronized (mRequestList) {if (clearWakeLock()) {if (RILJ_LOGD) {int count = mRequestList.size();Rlog.d(RILJ_LOG_TAG, "WAKE_LOCK_TIMEOUT " +" mRequestList=" + count);for (int i = 0; i < count; i++) {rr = mRequestList.valueAt(i);Rlog.d(RILJ_LOG_TAG, i + ": [" + rr.mSerial + "] "+ requestToString(rr.mRequest));}}}}break;}}}
复制代码

处理 关于 Sms的请求:

 private RILRequest findAndRemoveRequestFromList(int serial) {RILRequest rr = null;synchronized (mRequestList) {rr = mRequestList.get(serial);if (rr != null) {mRequestList.remove(serial);}}return rr;}private RILRequestprocessSolicited (Parcel p) {int serial, error;boolean found = false;serial = p.readInt();error = p.readInt();RILRequest rr;rr = findAndRemoveRequestFromList(serial);if (rr == null) {Rlog.w(RILJ_LOG_TAG, "Unexpected solicited response! sn: "+ serial + " error: " + error);return null;}Object ret = null;if (error == 0 || p.dataAvail() > 0) {// either command succeeds or command fails but with data payloadtry {switch (rr.mRequest) {。。。。。。。       case RIL_REQUEST_SEND_SMS: ret =  responseSMS(p); break;case RIL_REQUEST_SEND_SMS_EXPECT_MORE: ret =  responseSMS(p); break;case RIL_REQUEST_WRITE_SMS_TO_SIM: ret =  responseInts(p); break;case RIL_REQUEST_DELETE_SMS_ON_SIM: ret =  responseVoid(p); break;case RIL_REQUEST_CDMA_SEND_SMS: ret =  responseSMS(p); break;case RIL_REQUEST_CDMA_SMS_ACKNOWLEDGE: ret =  responseVoid(p); break;  case RIL_REQUEST_CDMA_WRITE_SMS_TO_RUIM: ret =  responseInts(p); break;case RIL_REQUEST_CDMA_DELETE_SMS_ON_RUIM: ret =  responseVoid(p); break;case RIL_REQUEST_REPORT_SMS_MEMORY_STATUS: ret = responseVoid(p); break;case RIL_REQUEST_IMS_SEND_SMS: ret =  responseSMS(p); break;...//break;}} catch (Throwable tr) {// Exceptions here usually mean invalid RIL responsesRlog.w(RILJ_LOG_TAG, rr.serialString() + "< "+ requestToString(rr.mRequest)+ " exception, possible invalid RIL response", tr);if (rr.mResult != null) {AsyncResult.forMessage(rr.mResult, null, tr);rr.mResult.sendToTarget();}return rr;}}       return rr;}
复制代码
private Object
responseSMS(Parcel p) {int messageRef, errorCode;String ackPDU;messageRef = p.readInt();ackPDU = p.readString();errorCode = p.readInt();SmsResponse response = new SmsResponse(messageRef, ackPDU, errorCode);return response;
}
复制代码
public interface CommandsInterface {void sendImsGsmSms (String smscPDU, String pdu, int retry, int messageRef,Message response);/*** smscPDU is smsc address in PDU form GSM BCD format prefixed*      by a length byte (as expected by TS 27.005) or NULL for default SMSC* pdu is SMS in PDU format as an ASCII hex string*      less the SMSC address*/void sendSMS (String smscPDU, String pdu, Message response);/*** @param pdu is CDMA-SMS in internal pseudo-PDU format* @param response sent when operation completes*/void sendCdmaSms(byte[] pdu, Message response);
}复制代码

暂时不太清楚Wear OS中关于SMS的相关逻辑,倘若阉割了或者需要实现一个简化版的(不需要或者简化彩信功能),实现方案可以参考接口扩展的方法需要实现两部分代码:

  1. 从APP至RIL,发送请求;
  2. 从RIL至APP,上报结果。

参考实现接口扩展:

Framework层SMS发送相关推荐

  1. Android10.0 Binder通信原理(八)-Framework层分析

    摘要:本节主要来讲解Android10.0 Binder 在Framework的使用分析 阅读本文大约需要花费15分钟. 文章首发微信公众号:IngresGe 专注于Android系统级源码分析,An ...

  2. android重复拉起app首页_Android进程管理:Framework层概念

    前情回顾 RickAi,公众号:安卓尖端技术研究Android进程管理:从Kernel到LowMemoryKiller 上一篇文章从Native角度讲解了Android进程管理的相关概念,本文将继续从 ...

  3. android在framework层增加自己的service仿照GPS

    不少公司在开发android产品的时候,都需要在android中增加自己的service,尤其是定制的工业用途的设备,我们公司的项目中就涉及到要增加一个service,是一个北斗通信service,具 ...

  4. android在framework层增加自己的service---仿照GPS

         不少公司在开发android产品的时候,都需要在android中增加自己的service,尤其是定制的工业用途的设备,我们公司的项目中就涉及到要增加一个service,是一个北斗通信serv ...

  5. Android开发如何定制framework层服务

    刚刚跨完年,新年第一篇文章,那么今天将对Android开发framework中间层的服务定制使用作个总结.首先我们先导入Android平台源码framework层的代码到开发工具eclipse中,代码 ...

  6. NXP Nfc模块Framework层移植遇到的坑【二】

    8173_M平台下移植NXP的Nfc模块时遇到的问题,同样也是 hal 层与 kernel 通信时出错,不过由于这个项目没有量产计划,所以供应商的支持也比较少,最后的解决方案是 Framework 层 ...

  7. Android源码分析 - Framework层的Binder(客户端篇)

    开篇 本篇以aosp分支android-11.0.0_r25作为基础解析 我们在之前的文章中,从驱动层面分析了Binder是怎样工作的,但Binder驱动只涉及传输部分,待传输对象是怎么产生的呢,这就 ...

  8. Android 原生设置收到消息后亮屏(framework层修改)

    最近碰到一个这样的需求,说是要收到任何消息后若手机处在锁屏状态时要自动亮屏,开始拿到这个需求后有点蒙,对于一个小安卓的我来说,感觉根本无从下手呀,但是客户是上帝(其实就是经理是上帝),没办法,身为底层 ...

  9. 带着问题分析Framework层源码(一):按键音声音太小,我们该如何增大?

    作为一名Android开发人员,对源码的阅读是必不可少的.但是Android源码那么庞大,从何开始阅读,如何开始阅读,很多人都会感觉无从下手,今天我来带着问题,去带大家分析一下Android源码,并解 ...

最新文章

  1. DataScience:风控场景之金融评分卡模型的简介、构建(逻辑回归)开发(转评分卡)、使用过程(线上实现)之详细攻略
  2. ROS中常见坐标系定义及基本单位
  3. spark job运行参数优化
  4. Hybrid A*论文解析(5)
  5. java声明一个函数_java – 如何声明一个函数参数来接受抛出的函数?
  6. android:layout_height、android:layout_width、android:height、android:width的关系与区别
  7. 【大数据】Azkaban学习笔记
  8. 冰点下载器手机版apk_冰点下载器安卓版下载
  9. linux如何安装yum
  10. JAVA实现度分秒单位换算
  11. atmega328p 设置熔丝位,atmega328p 刷机
  12. 计算机材料科学与技术,计算材料学(材料科学与计算机科学的交叉学科)_百度百科...
  13. 笔记本电脑刚回来没有计算机,刚买笔记本电脑我的笔记本电脑没有光驱,如果重新安装系统,怎么样操 爱问知识人...
  14. String的intern()方法浅析
  15. 方舟编译器只能编译Java_说说 方舟编译器
  16. 林中鸟计算机弹奏,用现象证实现象这叫复试,计算机的计算只是计算,与经络的现象无关。气感循行...
  17. [vdbench]vdbench典型配置
  18. 安卓 解析软件包时出现问题
  19. (15)卡巴斯基防病毒软件介绍-概述
  20. NOI试题(题目+答案)(三)(上)

热门文章

  1. 服务器经过交换机传递文件丢失,H3C交换机bin文件丢失后补救方案
  2. python数据结构与算法第10讲_Python数据结构与算法10:基本结构:练习题1
  3. ubuntu 下vivado关联vscode
  4. 售票统计表表格模板_财务常用四大报表模板,共二十张,会计小白入职有它被高看一眼...
  5. java反射方法_java反射之方法反射的基本操作方法
  6. mysql不能备份_mysql不能备份
  7. 优粮生活炒菜机器人_闫寒 - 外卖O2O「优粮生活」合伙人 | 到「在行」来约见我...
  8. java单例模式深入详解_javascript 模块依赖管理的本质深入详解
  9. python删除文件夹无法访问_Python:pip和mu安装第三方库的小麻烦及解决方法
  10. mysql 报500错误_java 项目开启mysql binlog参数后报500错误: