详解Android4.4 RIL短信接收流程分析
 最近有客户反馈Android接收不到短信,于是一头扎进RIL里面找原因。最后发现不是RIL的问题,而是BC72上报
短信的格式不对,AT+CNMA=1无作用等几个小问题导致的。尽管问题不在RIL,但总算把RIL短信接收流程搞清楚了。
接收到新信息的log:
D/ATC(1269):AT<+CMT:,27
D/ATC(1268):AT<0891683108705505F0040d91683117358313f500009101329154922307ea31da2c36a301
D/RILJ(1792):[UNSL]D/SmsMessage(1792):SMSSCaddress:+8613800755500 
V/SmsMessage(1792):SMSoriginatingaddress:+8613715338315
V/SmsMessage(1792):SMSTP-PID:0datacodingscheme:0
D/SmsMessage(1792):SMSSCtimestamp:1571831129000
V/SmsMessage(1792):SMSmessagebody(raw):'jchfbfh'
D/GsmInboundSmsHandler(1776):Idlestateprocessingmessagetype1
D/GsmInboundSmsHandler(1776):acquiredwakelock,leavingIdlestate
D/GsmInboundSmsHandler(1776):enteringDeliveringstate
D/GsmInboundSmsHandler(1776):URIofnewrow->content://raw/3
D/RILJ(1775):[3706]>SMS_ACKNOWLEDGEtrue0
D/RILC(1254):onRequest:SMS_ACKNOWLEDGE
D/ATC(1254):AT>AT+CNMA=1
D/ATC(1254):ATD/RILJ(1775):[3706] D/GsmInboundSmsHandler(1775):DeliveringSMSto:com.android.mmscom.android.mms.transaction.PrivilegedSmsReceiver 
E/GsmInboundSmsHandler(1775):unexpectedBroadcastReceiveraction:android.provider.Telephony.SMS_RECEIVED
D/GsmInboundSmsHandler(1775):successfulbroadcast,deletingfromrawtable.
D/SmsMessage(2124):SMSSCaddress:+8613800755500
D/GsmInboundSmsHandler(1775):Deleted1rowsfromrawtable.
D/GsmInboundSmsHandler(1775):orderedbroadcastcompletedin:276ms
D/GsmInboundSmsHandler(1775):leavingDeliveringstate
D/GsmInboundSmsHandler(1775):enteringDeliveringstate
D/GsmInboundSmsHandler(1775):leavingDeliveringstate
D/GsmInboundSmsHandler(1775):enteringIdlestate
V/SmsMessage(2124):SMSoriginatingaddress:+8613715338315
V/SmsMessage(2124):SMSTP-PID:0datacodingscheme:0
D/SmsMessage(2124):SMSSCtimestamp:1572253549000
V/SmsMessage(2124):SMSmessagebody(raw):'jchfbfh'
D/GsmInboundSmsHandler(1775):Idlestateprocessingmessagetype5
D/GsmInboundSmsHandler(1775):mWakeLockreleased
一、短信接收
1.vendorril接收到modem上报的短信息
hardware/ril/reference-ril/reference-ril.c
staticvoidonUnsolicited(constchar*s,constchar*sms_pdu)
{
......
if(strStartsWith(s,"+CMT:")){
RIL_onUnsolicitedResponse(
RIL_UNSOL_RESPONSE_NEW_SMS,/*上报UNSOL_RESPONSE_NEW_SMS消息*/
sms_pdu,strlen(sms_pdu));
}
......
}
2.RILD把短信息发送到RILJ
hardware/ril/libril/ril.cpp
extern"C"
voidRIL_onUnsolicitedResponse(intunsolResponse,void*data,
size_tdatalen)
{
......
unsolResponseIndex=unsolResponse-RIL_UNSOL_RESPONSE_BASE;/*找出消息在s_unsolResponses[]的索引*/
......
switch(s_unsolResponses[unsolResponseIndex].wakeType){/*禁止进入休眠*/
caseWAKE_PARTIAL:
grabPartialWakeLock();
shouldScheduleTimeout=true;
break;
......
}
......
ret=s_unsolResponses[unsolResponseIndex]/*调用消息处理函数responseString()*/
.responseFunction(p,data,datalen);
......
ret=sendResponse(p);/*发送Parcel中的信息内容到服务端RILJ*/
}
staticUnsolResponseInfos_unsolResponses[]={
......
/*消息对应的消息处理函数,新信息到来会唤醒系统*/
{RIL_UNSOL_RESPONSE_NEW_SMS,responseString,WAKE_PARTIAL},
......
};
staticintresponseString(Parcel&p,void*response,size_tresponselen){
/*onestringonly*/
startResponse;
appendPrintBuf("%s%s",printBuf,(char*)response);
closeResponse;
writeStringToParcel(p,(constchar*)response);/*把字符串格式的信息存到Parcel容器中*/
return0;
}
二、解析短信息
1.RILJ获取短信息
 
frameworks/opt/telephony/src/java/com/android/internal/telephony/RIL.java
privatevoid
processUnsolicited(Parcelp){
......
caseRIL_UNSOL_RESPONSE_NEW_SMS:ret=responseString(p);break;
......
switch(response){
......
caseRIL_UNSOL_RESPONSE_NEW_SMS:{
if(RILJ_LOGD)unsljLog(response);/*参考log:[UNSL]
2.解析短信息
       SmsMessage.newFromCMT(a);根据importandroid.telephony.SmsMessage,得知代码路径:
 
frameworks/opt/telephony/src/java/android/telephony/SmsMessage.java
publicstaticSmsMessagenewFromCMT(String[]lines){
//receivedSMSin3GPPformat
SmsMessageBasewrappedMessage=
com.android.internal.telephony.gsm.SmsMessage.newFromCMT(lines);/*是对另一个newFromCMT的封装,因为有gsm和cdma两种短信,
*即cdma中也有newFromCMT,根据情况按需选择
*/
returnnewSmsMessage(wrappedMessage);
}
com.android.internal.telephony.gsm.SmsMessage.newFromCMT(lines)的实现在
frameworks/opt/telephony/src/java/com/android/internal/telephony/gsm/SmsMessage.java
publicclassSmsMessageextendsSmsMessageBase{
......
publicstaticSmsMessagenewFromCMT(String[]lines){
try{
SmsMessagemsg=newSmsMessage();
msg.parsePdu(IccUtils.hexStringToBytes(lines[1]));/*解析PDU短信*/
returnmsg;
}catch(RuntimeExceptionex){
Rlog.e(LOG_TAG,"SMSPDUparsingfailed:",ex);
returnnull;
}
}
......
}
IccUtils.hexStringToBytes(lines[1])把十六进制的字符串转换成字节数组msg.parsePdu()解析这个数组的内容,最后获得短信内容
frameworks/opt/telephony/src/java/com/android/internal/telephony/gsm/SmsMessage.java
privatevoidparsePdu(byte[]pdu){
......
mScAddress=p.getSCAddress();
if(mScAddress!=null){
if(VDBG)Rlog.d(LOG_TAG,"SMSSCaddress:"+mScAddress);/*参考log:SMSSCaddress:+8613800755500*/
}
......
mMti=firstByte&0x3;
switch(mMti){
......
case3://GSM03.409.2.3.1:MTI==3isReserved.
//ThisshouldbeprocessedinthesamewayasMTI==0(Deliver)
parseSmsDeliver(p,firstByte);/*对短信类型为Deliver的短信进行解析*/
break;
......
}
......
}
privatevoidparseSmsDeliver(PduParserp,intfirstByte){
......
mOriginatingAddress=p.getAddress();
if(mOriginatingAddress!=null){
if(VDBG)Rlog.v(LOG_TAG,"SMSoriginatingaddress:"/*参考log:SMSoriginatingaddress:+861371533xxxx*/
+mOriginatingAddress.address);
}
......
mProtocolIdentifier=p.getByte();
//TP-Data-Coding-Scheme
//seeTS23.038
mDataCodingScheme=p.getByte();
if(VDBG){
Rlog.v(LOG_TAG,"SMSTP-PID:"+mProtocolIdentifier
+"datacodingscheme:"+mDataCodingScheme);/*参考log:SMSTP-PID:0datacodingscheme:0*/
}
mScTimeMillis=p.getSCTimestampMillis();
if(VDBG)Rlog.d(LOG_TAG,"SMSSCtimestamp:"+mScTimeMillis);/*参考log:SMSSCtimestamp:1571831129000*/
booleanhasUserDataHeader=(firstByte&0x40)==0x40;
parseUserData(p,hasUserDataHeader);/*解析信息有效内容*/
......
}
privatevoidparseUserData(PduParserp,booleanhasUserDataHeader){
......
if(VDBG)Rlog.v(LOG_TAG,"SMSmessagebody(raw):'"+mMessageBody+"'");/*短信内容,参考log:SMSmessagebody(raw):'jchfbfh'*/
......
}
三、处理短信息    
       对用户有效的短信内容,最终保存在类型为String的mMessageBody变量中,该变量属于SmsMessageBase抽象类,而
SmsMessage继承于SmsMessageBase。
       回到前面frameworks/opt/telephony/src/java/com/android/internal/telephony/RIL.java中processUnsolicited(),
sms=SmsMessage.newFromCMT(a);解析完短信息后,返回一个SmsMessage并通知上层应用。
frameworks/opt/telephony/src/java/com/android/internal/telephony/RIL.java
mGsmSmsRegistrant
.notifyRegistrant(newAsyncResult(null,sms,null));/*把sms转成Object类型*/
frameworks/base/core/java/android/os/AsyncResult.java
publicclassAsyncResult
{
......
/**pleasenote,thissetsm.objtobethis*/
public
AsyncResult(Objectuo,Objectr,Throwableex)
{
userObj=uo;
result=r;
exception=ex;
}
......
}
       根据mGsmSmsRegistrant.notifyRegistrant(newAsyncResult(null,sms,null));找到mGsmSmsRegistrant注册的代码:
frameworks/opt/telephony/src/java/com/android/internal/telephony/BaseCommands.java
publicabstractclassBaseCommandsimplementsCommandsInterface{
......
@Override
publicvoidsetOnNewGsmSms(Handlerh,intwhat,Objectobj){/*mGsmSmsRegistrant.notifyRegistrant(newAsyncResult(null,sms,null))中的mGsmSmsRegistrant是在这里创建的*/
mGsmSmsRegistrant=newRegistrant(h,what,obj);
}
......
}
       封装消息EVENT_NEW_SMS消息
frameworks/base/core/java/android/os/Registrant.java
publicclassRegistrant
{
public
Registrant(Handlerh,intwhat,Objectobj)/*传入需要处理消息为what的事件处理Handlerh,obj为事件内容,参考phone.mCi.setOnNewGsmSms(getHandler(),EVENT_NEW_SMS,null);*/
{
refH=newWeakReference(h);
this.what=what;
userObj=obj;
}
......
/**
*Thismakesacopyof@paramar
*/
publicvoid
notifyRegistrant(AsyncResultar)/*参考mGsmSmsRegistrant.notifyRegistrant(newAsyncResult(null,sms,null))*/
{
internalNotifyRegistrant(ar.result,ar.exception);/*ar.result为sms*/
}
/*package*/void
internalNotifyRegistrant(Objectresult,Throwableexception)/*internalNotifyRegistrant(sms,Throwableexception)*/
{
Handlerh=getHandler();
if(h==null){
clear();
}else{
Messagemsg=Message.obtain();/*创建一个消息*/
msg.what=what;/*消息类型EVENT_NEW_SMS*/
msg.obj=newAsyncResult(userObj,result,exception);/*消息内容sms*/
h.sendMessage(msg);/*发送消息到注册了这个消息的Handler,参考phone.mCi.setOnNewGsmSms(getHandler(),EVENT_NEW_SMS,null);的getHandler()*/
}
}
......
}
       然而BaseCommands是一个抽象类,实现了CommandsInterface中的setOnNewGsmSms接口,这个接口由GsmInboundSmsHandler调用
(phone.mCi.setOnNewGsmSms(getHandler(),EVENT_NEW_SMS,null)),也就是说GsmInboundSmsHandler的getHandler()是EVENT_NEW_SMS
的监听者,也就是说frameworks/opt/telephony/src/java/com/android/internal/telephony/RIL.java中mGsmSmsRegistrant.notifyRegistrant(newAsyncResult(null,sms,null))
调用之后,会触发GsmInboundSmsHandler中getHandler()的Handler对EVENT_NEW_SMS消息进行解析。这个Handler肯定是GsmInboundSmsHandler
实例化的对象中的,这个对象在什么时候,在哪里创建的,暂且不管。我们只管EVENT_NEW_SMS这个消息从哪里来,然后到哪里去
就行了。
./frameworks/opt/telephony/src/java/com/android/internal/telephony/ImsSMSDispatcher.java
publicfinalclassImsSMSDispatcherextendsSMSDispatcher{
......
mGsmInboundSmsHandler=GsmInboundSmsHandler.makeInboundSmsHandler(phone.getContext(),/*获取mGsmInboundSmsHandler,并启动状态机*/
storageMonitor,phone);
......
}
./frameworks/opt/telephony/src/java/com/android/internal/telephony/gsm/GsmInboundSmsHandler.java
publicclassGsmInboundSmsHandlerextendsInboundSmsHandler{
......
/**
*CreateanewGSMinboundSMShandler.
*/
privateGsmInboundSmsHandler(Contextcontext,SmsStorageMonitorstorageMonitor,
PhoneBasephone){
super("GsmInboundSmsHandler",context,storageMonitor,phone,/*构造GsmInboundSmsHandler时,通过super()调用InboundSmsHandler的构造函数*/
GsmCellBroadcastHandler.makeGsmCellBroadcastHandler(context,phone));
phone.mCi.setOnNewGsmSms(getHandler(),EVENT_NEW_SMS,null);/*注册EVENT_NEW_SMS消息*/
mDataDownloadHandler=newUsimDataDownloadHandler(phone.mCi);
}
......
/**
*Waitforstatemachinetoenterstartupstate.Wecan'tsendanymessagesuntilthen.
*/
publicstaticGsmInboundSmsHandlermakeInboundSmsHandler(Contextcontext,
SmsStorageMonitorstorageMonitor,PhoneBasephone){
GsmInboundSmsHandlerhandler=newGsmInboundSmsHandler(context,storageMonitor,phone);/*实例化GsmInboundSmsHandler*/
handler.start();/*抽象类InboundSmsHandler继承与StateMachine,而GsmInboundSmsHandler继承于InboundSmsHandler,
*GsmInboundSmsHandler调用启动状态机方法start()
*/
returnhandler;
}
......
}
./frameworks/opt/telephony/src/java/com/android/internal/telephony/InboundSmsHandler.java
publicabstractclassInboundSmsHandlerextendsStateMachine{
......
protectedInboundSmsHandler(Stringname,Contextcontext,SmsStorageMonitorstorageMonitor,
PhoneBasephone,CellBroadcastHandlercellBroadcastHandler){
......
addState(mDefaultState);/*构造InboundSmsHandler时,添加状态机的状态*/
addState(mStartupState,mDefaultState);
addState(mIdleState,mDefaultState);
addState(mDeliveringState,mDefaultState);
addState(mWaitingState,mDeliveringState);
setInitialState(mStartupState);/*初始化状态机*/
if(DBG)log("createdInboundSmsHandler");
}
......
classIdleStateextendsState{
@Override
publicvoidenter(){
if(DBG)log("enteringIdlestate");
sendMessageDelayed(EVENT_RELEASE_WAKELOCK,WAKELOCK_TIMEOUT);
}
@Override
publicvoidexit(){
mWakeLock.acquire();
if(DBG)log("acquiredwakelock,leavingIdlestate");
}
@Override
publicbooleanprocessMessage(Messagemsg){
if(DBG)log("Idlestateprocessingmessagetype"+msg.what);
switch(msg.what){
caseEVENT_NEW_SMS:/*空闲时,接收到短信*/
caseEVENT_BROADCAST_SMS:
deferMessage(msg);
transitionTo(mDeliveringState);/*转到mDeliveringState*/
returnHANDLED;
......
}
}
}
......
classDeliveringStateextendsState{/*转到mDeliveringState状态*/
@Override
publicvoidenter(){
if(DBG)log("enteringDeliveringstate");
}
@Override
publicvoidexit(){
if(DBG)log("leavingDeliveringstate");
}
@Override
publicbooleanprocessMessage(Messagemsg){
switch(msg.what){
caseEVENT_NEW_SMS:
//handlenewSMSfromRIL
handleNewSms((AsyncResult)msg.obj);/*处理新SMS*/
sendMessage(EVENT_RETURN_TO_IDLE);/*处理完回到空闲状态*/
returnHANDLED;
......
}
}
......
}
}
voidhandleNewSms(AsyncResultar){
......
SmsMessagesms=(SmsMessage)ar.result;
result=dispatchMessage(sms.mWrappedSmsMessage);
......
}
publicintdispatchMessage(SmsMessageBasesmsb){
......
returndispatchMessageRadioSpecific(smsb);
......
}
 
       通过以上流程可以了解到,当状态机接收到SMS后,对消息进行分发,针对typezero,SMS-PPdatadownload,
和3GPP/CPHSMWItypeSMS判断,如果是NormalSMSmessages,则调用dispatchNormalMessage(smsb),然后创建
一个InboundSmsTracker对象,把信息保存到rawtable,然后在通过sendMessage(EVENT_BROADCAST_SMS,tracker)把消息广播出去。
./frameworks/opt/telephony/src/java/com/android/internal/telephony/InboundSmsHandler.java
classDeliveringStateextendsState{
......
publicbooleanprocessMessage(Messagemsg){
switch(msg.what){
......
caseEVENT_BROADCAST_SMS:/*接收到EVENT_BROADCAST_SMS消息并处理*/
//ifanybroadcastsweresent,transitiontowaitingstate
if(processMessagePart((InboundSmsTracker)msg.obj)){
transitionTo(mWaitingState);
}
returnHANDLED;
......
}
}
......
}
booleanprocessMessagePart(InboundSmsTrackertracker){
......
BroadcastReceiverresultReceiver=newSmsBroadcastReceiver(tracker);/*创建一个广播接收者,用来处理短信广播的结果*/
......
intent=newIntent(Intents.SMS_DELIVER_ACTION);/*设置当前intent的action为SMS_DELIVER_ACTION*/
//DirecttheintenttoonlythedefaultSMSapp.Ifwecan'tfindadefaultSMSapp
//thensentittoallbroadcastreceivers.
ComponentNamecomponentName=SmsApplication.getDefaultSmsApplication(mContext,true);/*这个action只会发送给carrierapp,而且carrierapp可以通过setresult为RESULT_CANCELED来终止这个广播*/
if(componentName!=null){
//DeliverSMSmessageonlytothisreceiver
intent.setComponent(componentName);
log("DeliveringSMSto:"+componentName.getPackageName()+
""+componentName.getClassName());
}
......
dispatchIntent(intent,android.Manifest.permission.RECEIVE_SMS,/*广播intent*/
AppOpsManager.OP_RECEIVE_SMS,resultReceiver);
......
}
privatefinalclassSmsBroadcastReceiverextendsBroadcastReceiver{
......
publicvoidonReceive(Contextcontext,Intentintent){
......
//NowthattheintentshavebeendeletedwecancleanupthePDUdata.
if(!Intents.DATA_SMS_RECEIVED_ACTION.equals(action)
&&!Intents.DATA_SMS_RECEIVED_ACTION.equals(action)
&&!Intents.WAP_PUSH_RECEIVED_ACTION.equals(action)){
loge("unexpectedBroadcastReceiveraction:"+action);
}
intrc=getResultCode();
if((rc!=Activity.RESULT_OK)&&(rc!=Intents.RESULT_SMS_HANDLED)){
loge("abroadcastreceiversettheresultcodeto"+rc
+",deletingfromrawtableanyway!");
}elseif(DBG){
log("successfulbroadcast,deletingfromrawtable.");
}
deleteFromRawTable(mDeleteWhere,mDeleteWhereArgs);
sendMessage(EVENT_BROADCAST_COMPLETE);/*成功广播*/
......
}
......
}
      到这里,在应用层注册具有Intents.SMS_RECEIVED_ACTION这样action的广播,就可以获取到短信了。
总结
以上所述是小编给大家介绍的Android4.4RIL短信接收流程分析,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对毛票票网站的支持!
如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢!
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。