详解Android4.4 RIL短信接收流程分析

详解Android4.4 RIL短信接收流程分析,第1张

概述详解Android4.4 RIL短信接收流程分析 最近有客户反馈Android接收不到短信,于是一头扎进RIL里面找原因.最后发现不是RIL的问题,而是BC72上报 短信的格式不对,AT+CNMA=1无作用等几个小问题导致的.尽管问题不在RIL,但总算把RIL短信接收流程搞清楚了. 接收到新信息的log: D/ATC ( 1269): AT< +CMT:,27 D/ATC ( 1268): AT< 0891683108705505F0040d91683117358313f500009101329154922307ea31da2c36 ...

最近有客户反馈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]< UNSol_RESPONSE_NEW_SMS
D/SmsMessage( 1792): SMS SC address: +8613800755500
V/SmsMessage( 1792): SMS originating address: +8613715338315
V/SmsMessage( 1792): SMS TP-PID:0 data Coding scheme: 0
D/SmsMessage( 1792): SMS SC timestamp: 1571831129000
V/SmsMessage( 1792): SMS message body (raw): 'jchfbfh'
D/GsmInboundSmsHandler( 1776): IDle state processing message type 1
D/GsmInboundSmsHandler( 1776): acquired wakelock,leaving IDle state
D/GsmInboundSmsHandler( 1776): entering Delivering state
D/GsmInboundSmsHandler( 1776): URI of new row -> content://raw/3
D/RILJ ( 1775): [3706]> SMS_ACKNowLEDGE true 0
D/RILC ( 1254): onRequest: SMS_ACKNowLEDGE
D/ATC ( 1254): AT> AT+CNMA=1
D/ATC ( 1254): AT< OK
D/RILJ ( 1775): [3706]< SMS_ACKNowLEDGE
D/GsmInboundSmsHandler( 1775): Delivering SMS to: com.androID.mms com.androID.mms.transaction.PrivilegedSmsReceiver
E/GsmInboundSmsHandler( 1775): unexpected broadcastReceiver action: androID.provIDer.Telephony.SMS_RECEIVED
D/GsmInboundSmsHandler( 1775): successful broadcast,deleting from raw table.
D/SmsMessage( 2124): SMS SC address: +8613800755500
D/GsmInboundSmsHandler( 1775): Deleted 1 rows from raw table.
D/GsmInboundSmsHandler( 1775): ordered broadcast completed in: 276 ms
D/GsmInboundSmsHandler( 1775): leaving Delivering state
D/GsmInboundSmsHandler( 1775): entering Delivering state
D/GsmInboundSmsHandler( 1775): leaving Delivering state
D/GsmInboundSmsHandler( 1775): entering IDle state
V/SmsMessage( 2124): SMS originating address: +8613715338315
V/SmsMessage( 2124): SMS TP-PID:0 data Coding scheme: 0
D/SmsMessage( 2124): SMS SC timestamp: 1572253549000
V/SmsMessage( 2124): SMS message body (raw): 'jchfbfh'
D/GsmInboundSmsHandler( 1775): IDle state processing message type 5
D/GsmInboundSmsHandler( 1775): mWakeLock released

一、短信接收

1. vendor ril接收到modem上报的短信息

harDWare/ril/reference-ril/reference-ril.cstatic voID onUnsolicited (const char *s,const char *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.cppextern "C"voID RIL_onUnsolicitedResponse(int unsolResponse,voID *data,size_t datalen){ ... ... unsolResponseIndex = unsolResponse - RIL_UNSol_RESPONSE_BASE; /* 找出消息在s_unsolResponses[]的索引 */ ... ... switch (s_unsolResponses[unsolResponseIndex].wakeType) {   /* 禁止进入休眠 */  case WAKE_PARTIAL:   grabPartialWakeLock();   shouldScheduleTimeout = true;  break;  ... ... } ... ... ret = s_unsolResponses[unsolResponseIndex]      /* 调用消息处理函数responseString() */    .responseFunction(p,data,datalen); ... ... ret = sendResponse(p);           /* 发送Parcel中的信息内容到服务端RILJ */}static UnsolResponseInfo s_unsolResponses[] = {... .../* 消息对应的消息处理函数,新信息到来会唤醒系统 */{RIL_UNSol_RESPONSE_NEW_SMS,responseString,WAKE_PARTIAL},... ...};static int responseString(Parcel &p,voID *response,size_t responselen) { /* one string only */ startResponse; appendPrintBuf("%s%s",printBuf,(char*)response); closeResponse; writeStringtoparcel(p,(const char *)response);     /* 把字符串格式的信息存到Parcel容器中 */ return 0;}

二、解析短信息

1. RILJ获取短信息

frameworks/opt/telephony/src/java/com/androID/internal/telephony/RIL.javaprivate voIDprocessUnsolicited (Parcel p) { ... ... case RIL_UNSol_RESPONSE_NEW_SMS: ret = responseString(p); break; ... ... switch(response) {  ... ...  case RIL_UNSol_RESPONSE_NEW_SMS: {   if (RILJ_LOGD) unsljLog(response);      /* 参考log:[UNSL]< UNSol_RESPONSE_NEW_SMS */   // FIXME this should move up a layer   String a[] = new String[2];   a[1] = (String)ret;   SmsMessage sms;   sms = SmsMessage.newFromCMT(a);       /* 解析PDU格式的短信息 */   if (mGsmSmsRegistrant != null) {    mGsmSmsRegistrant     .notifyRegistrant(new AsyncResult(null,sms,null));   }   break;  }  ... ... } ... ...}private ObjectresponseString(Parcel p) { String response; response = p.readString();               /* 信息内容转换成Object */ return response;}

2. 解析短信息

SmsMessage.newFromCMT(a);根据import androID.telephony.SmsMessage,得知代码路径:

frameworks/opt/telephony/src/java/androID/telephony/SmsMessage.javapublic static SmsMessage newFromCMT(String[] lines) { // received SMS in 3GPP format SmsMessageBase wrappedMessage =   com.androID.internal.telephony.gsm.SmsMessage.newFromCMT(lines);  /* 是对另一个newFromCMT的封装,因为有gsm和cdma两种短信,                     * 即cdma中也有newFromCMT,根据情况按需选择                     */ return new SmsMessage(wrappedMessage);}  com.androID.internal.telephony.gsm.SmsMessage.newFromCMT(lines)的实现在frameworks/opt/telephony/src/java/com/androID/internal/telephony/gsm/SmsMessage.javapublic class SmsMessage extends SmsMessageBase { ... ... public static SmsMessage newFromCMT(String[] lines) {  try {   SmsMessage msg = new SmsMessage();   msg.parsePdu(IccUtils.hexStringToBytes(lines[1]));    /* 解析PDU短信 */   return msg;  } catch (RuntimeException ex) {   Rlog.e(LOG_TAG,"SMS PDU parsing Failed: ",ex);   return null;  } } ... ...}  IccUtils.hexStringToBytes(lines[1])把十六进制的字符串转换成字节数组msg.parsePdu()解析这个数组的内容,最后获得短信内容frameworks/opt/telephony/src/java/com/androID/internal/telephony/gsm/SmsMessage.javaprivate voID parsePdu(byte[] pdu) { ... ... mScAddress = p.getSCAddress(); if (mScAddress != null) {  if (VDBG) Rlog.d(LOG_TAG,"SMS SC address: " + mScAddress);   /* 参考log:SMS SC address: +8613800755500 */ } ... ... mMti = firstByte & 0x3; switch (mMti) {  ... ...   case 3: //GSM 03.40 9.2.3.1: MTI == 3 is Reserved.     //This should be processed in the same way as MTI == 0 (Deliver)    parseSmsDeliver(p,firstByte);         /* 对短信类型为Deliver的短信进行解析 */    break;   ... ...  } ... ...}private voID parseSmsDeliver(PduParser p,int firstByte) { ... ... mOriginatingAddress = p.getAddress(); if (mOriginatingAddress != null) {  if (VDBG) Rlog.v(LOG_TAG,"SMS originating address: "    /* 参考log: SMS originating address: +861371533xxxx */    + mOriginatingAddress.address); } ... ... mProtocolIDentifIEr = p.getByte(); // TP-Data-Coding-Scheme // see TS 23.038 mDataCodingScheme = p.getByte(); if (VDBG) {  Rlog.v(LOG_TAG,"SMS TP-PID:" + mProtocolIDentifIEr    + " data Coding scheme: " + mDataCodingScheme);    /* 参考log: SMS TP-PID:0 data Coding scheme: 0 */ } mScTimeMillis = p.getSCTimestampMillis(); if (VDBG) Rlog.d(LOG_TAG,"SMS SC timestamp: " + mScTimeMillis);   /* 参考log:SMS SC timestamp: 1571831129000 */ boolean hasUserDataheader = (firstByte & 0x40) == 0x40; parseUserData(p,hasUserDataheader);          /* 解析信息有效内容 */ ... ...}private voID parseUserData(PduParser p,boolean hasUserDataheader) { ... ... if (VDBG) Rlog.v(LOG_TAG,"SMS message body (raw): '" + mMessageBody + "'"); /* 短信内容,参考log: SMS message body (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.javamGsmSmsRegistrant .notifyRegistrant(new AsyncResult(null,null));        /* 把sms转成Object类型 */frameworks/base/core/java/androID/os/AsyncResult.javapublic class AsyncResult{ ... ... /** please note,this sets m.obj to be this */ public AsyncResult (Object uo,Object r,Throwable ex) {  userObj = uo;  result = r;  exception = ex; } ... ...}

根据mGsmSmsRegistrant.notifyRegistrant(new AsyncResult(null,null));找到mGsmSmsRegistrant注册的代码:

frameworks/opt/telephony/src/java/com/androID/internal/telephony/BaseCommands.javapublic abstract class BaseCommands implements CommandsInterface { ... ... @OverrIDe public voID setonNewGsmSms(Handler h,int what,Object obj) {  /* mGsmSmsRegistrant.notifyRegistrant(new AsyncResult(null,null))中的mGsmSmsRegistrant是在这里创建的 */  mGsmSmsRegistrant = new Registrant (h,what,obj); } ... ...} 

封装消息EVENT_NEW_SMS消息

frameworks/base/core/java/androID/os/Registrant.javapublic class Registrant{ public Registrant(Handler h,Object obj)      /* 传入需要处理消息为what的事件处理Handler h,obj为事件内容,参考phone.mCi.setonNewGsmSms(getHandler(),EVENT_NEW_SMS,null); */ {  refH = new WeakReference(h);  this.what = what;  userObj = obj; } ... ... /**  * This makes a copy of @param ar  */ public voID notifyRegistrant(AsyncResult ar)         /* 参考mGsmSmsRegistrant.notifyRegistrant(new AsyncResult(null,null)) */ {  internalNotifyRegistrant (ar.result,ar.exception);   /* ar.result为sms */ } /*package*/ voID internalNotifyRegistrant (Object result,Throwable exception)  /* internalNotifyRegistrant (sms,Throwable exception) */ {  Handler h = getHandler();  if (h == null) {   clear();  } else {   Message msg = Message.obtain();       /* 创建一个消息 */   msg.what = what;           /* 消息类型EVENT_NEW_SMS */   msg.obj = new AsyncResult(userObj,result,exception); /* 消息内容sms */   h.sendMessage(msg);          /* 发送消息到注册了这个消息的Handler,参考phone.mCi.setonNewGsmSms(getHandler(),null);的getHandler() */  } } ... ...} 

然而BaseCommands是一个抽象类,实现了CommandsInterface中的setonNewGsmSms接口,这个接口由GsmInboundSmsHandler调用
(phone.mCi.setonNewGsmSms(getHandler(),null)),也就是说GsmInboundSmsHandler的getHandler()是EVENT_NEW_SMS
的监听者,也就是说frameworks/opt/telephony/src/java/com/androID/internal/telephony/RIL.java中mGsmSmsRegistrant.notifyRegistrant(new AsyncResult(null,null))
调用之后,会触发GsmInboundSmsHandler中getHandler()的Handler对EVENT_NEW_SMS消息进行解析。这个Handler肯定是GsmInboundSmsHandler
实例化的对象中的,这个对象在什么时候,在哪里创建的,暂且不管。我们只管EVENT_NEW_SMS这个消息从哪里来,然后到哪里去
就行了。

./frameworks/opt/telephony/src/java/com/androID/internal/telephony/imsSMSdispatcher.javapublic final class imsSMSdispatcher extends SMSdispatcher { ... ... mGsmInboundSmsHandler = GsmInboundSmsHandler.makeInboundSmsHandler(phone.getContext(),/* 获取mGsmInboundSmsHandler,并启动状态机 */   storageMonitor,phone); ... ...}./frameworks/opt/telephony/src/java/com/androID/internal/telephony/gsm/GsmInboundSmsHandler.javapublic class GsmInboundSmsHandler extends InboundSmsHandler { ... ... /**  * Create a new GSM inbound SMS handler.  */ private GsmInboundSmsHandler(Context context,SmsstorageMonitor storageMonitor,PhoneBase phone) {  super("GsmInboundSmsHandler",context,storageMonitor,phone,/* 构造GsmInboundSmsHandler时,通过super()调用InboundSmsHandler的构造函数 */    GsmCellbroadcastHandler.makeGsmCellbroadcastHandler(context,phone));  phone.mCi.setonNewGsmSms(getHandler(),null);        /* 注册EVENT_NEW_SMS消息 */  mDataDownloadHandler = new UsimDataDownloadHandler(phone.mCi); } ... ... /**  * Wait for state machine to enter startup state. We can't send any messages until then.  */ public static GsmInboundSmsHandler makeInboundSmsHandler(Context context,PhoneBase phone) {  GsmInboundSmsHandler handler = new GsmInboundSmsHandler(context,phone); /* 实例化GsmInboundSmsHandler */  handler.start();                   /* 抽象类InboundSmsHandler继承与StateMachine,而GsmInboundSmsHandler继承于InboundSmsHandler,                         * GsmInboundSmsHandler调用启动状态机方法start()                         */  return handler; } ... ...}./frameworks/opt/telephony/src/java/com/androID/internal/telephony/InboundSmsHandler.javapublic abstract class InboundSmsHandler extends StateMachine { ... ... protected InboundSmsHandler(String name,Context context,PhoneBase phone,CellbroadcastHandler cellbroadcastHandler) {  ... ...  addState(mDefaultState);                 /* 构造InboundSmsHandler时,添加状态机的状态 */  addState(mStartupState,mDefaultState);  addState(mIDleState,mDefaultState);  addState(mDeliveringState,mDefaultState);  addState(mWaitingState,mDeliveringState);  setinitialState(mStartupState);               /* 初始化状态机 */  if (DBG) log("created InboundSmsHandler"); } ... ... class IDleState extends State {  @OverrIDe  public voID enter() {   if (DBG) log("entering IDle state");   sendMessageDelayed(EVENT_RELEASE_WAKELOCK,WAKELOCK_TIMEOUT);  }  @OverrIDe  public voID exit() {   mWakeLock.acquire();   if (DBG) log("acquired wakelock,leaving IDle state");  }  @OverrIDe  public boolean processMessage(Message msg) {   if (DBG) log("IDle state processing message type " + msg.what);   switch (msg.what) {    case EVENT_NEW_SMS:                /* 空闲时,接收到短信 */    case EVENT_broADCAST_SMS:     deferMessage(msg);     TransitionTo(mDeliveringState);            /* 转到mDeliveringState */     return HANDLED;    ... ...   }  } }  ... ... class DeliveringState extends State {               /* 转到mDeliveringState状态 */  @OverrIDe  public voID enter() {   if (DBG) log("entering Delivering state");  }  @OverrIDe  public voID exit() {   if (DBG) log("leaving Delivering state");  }  @OverrIDe  public boolean processMessage(Message msg) {   switch (msg.what) {    case EVENT_NEW_SMS:     // handle new SMS from RIL     handleNewSms((AsyncResult) msg.obj);           /* 处理新SMS */     sendMessage(EVENT_RETURN_TO_IDLE);            /* 处理完回到空闲状态 */     return HANDLED;    ... ...   }  }   ... ... }}voID handleNewSms(AsyncResult ar) { ... ... SmsMessage sms = (SmsMessage) ar.result; result = dispatchMessage(sms.mWrappedSmsMessage); ... ...}public int dispatchMessage(SmsMessageBase smsb) { ... ... return dispatchMessageRadioSpecific(smsb); ... ...}

通过以上流程可以了解到,当状态机接收到SMS后,对消息进行分发,针对type zero,SMS-PP data download,
和3GPP/CPHS MWI type SMS判断,如果是normal SMS messages,则调用dispatchnormalMessage(smsb),然后创建
一个InboundSmsTracker对象,把信息保存到raw table,然后在通过sendMessage(EVENT_broADCAST_SMS,tracker)把消息广播出去。

./frameworks/opt/telephony/src/java/com/androID/internal/telephony/InboundSmsHandler.java class DeliveringState extends State { ... ... public boolean processMessage(Message msg) {  switch (msg.what) {   ... ...   case EVENT_broADCAST_SMS:               /* 接收到EVENT_broADCAST_SMS消息并处理 */    // if any broadcasts were sent,Transition to waiting state    if (processMessagePart((InboundSmsTracker) msg.obj)) {     TransitionTo(mWaitingState);    }    return HANDLED;   ... ...  } } ... ...}boolean processMessagePart(InboundSmsTracker tracker) { ... ... broadcastReceiver resultReceiver = new SmsbroadcastReceiver(tracker);     /* 创建一个广播接收者,用来处理短信广播的结果 */ ... ... intent = new Intent(Intents.SMS_DEliVER_ACTION);           /* 设置当前intent的action为SMS_DEliVER_ACTION */ // Direct the intent to only the default SMS app. If we can't find a default SMS app // then sent it to all broadcast receivers. Componentname componentname = SmsApplication.getDefaultSmsApplication(mContext,true); /* 这个action只会发送给carrIEr app,而且carrIEr app可以通过set result为RESulT_CANCELED来终止这个广播 */ if (componentname != null) {  // Deliver SMS message only to this receiver  intent.setComponent(componentname);  log("Delivering SMS to: " + componentname.getPackagename() +    " " + componentname.getClassname()); } ... ... dispatchIntent(intent,androID.Manifest.permission.RECEIVE_SMS,/* 广播intent */    AppOpsManager.OP_RECEIVE_SMS,resultReceiver); ... ...}private final class SmsbroadcastReceiver extends broadcastReceiver { ... ... public voID onReceive(Context context,Intent intent) {  ... ...  // Now that the intents have been deleted we can clean up the PDU data.  if (!Intents.DATA_SMS_RECEIVED_ACTION.equals(action)    && !Intents.DATA_SMS_RECEIVED_ACTION.equals(action)    && !Intents.WAP_PUSH_RECEIVED_ACTION.equals(action)) {   loge("unexpected broadcastReceiver action: " + action);  }  int rc = getResultCode();  if ((rc != Activity.RESulT_OK) && (rc != Intents.RESulT_SMS_HANDLED)) {   loge("a broadcast receiver set the result code to " + rc     + ",deleting from raw table anyway!");  } else if (DBG) {   log("successful broadcast,deleting from raw table.");  }  deleteFromrawtable(mDeleteWhere,mDeleteWhereArgs);  sendMessage(EVENT_broADCAST_COMPLETE);            /* 成功广播 */  ... ... } ... ...}

到这里,在应用层注册具有Intents.SMS_RECEIVED_ACTION这样action的广播,就可以获取到短信了。

总结

以上所述是小编给大家介绍的AndroID4.4 RIL短信接收流程分析,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对我们网站的支持!
如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢!

总结

以上是内存溢出为你收集整理的详解Android4.4 RIL短信接收流程分析全部内容,希望文章能够帮你解决详解Android4.4 RIL短信接收流程分析所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1144331.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-31
下一篇 2022-05-31

发表评论

登录后才能评论

评论列表(0条)

保存