详解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(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。