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

前端之家收集整理的这篇文章主要介绍了详解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]< 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上报的短信息

  1. hardware/ril/reference-ril/reference-ril.c
  2. static void onUnsolicited (const char *s,const char *sms_pdu)
  3. {
  4. ... ...
  5. if (strStartsWith(s,"+CMT:")) {
  6. RIL_onUnsolicitedResponse (
  7. RIL_UNSOL_RESPONSE_NEW_SMS,/* 上报UNSOL_RESPONSE_NEW_SMS消息 */
  8. sms_pdu,strlen(sms_pdu));
  9. }
  10. ... ...
  11. }

2. RILD把短信息发送到RILJ

  1. hardware/ril/libril/ril.cpp
  2. extern "C"
  3. void RIL_onUnsolicitedResponse(int unsolResponse,void *data,size_t datalen)
  4. {
  5. ... ...
  6. unsolResponseIndex = unsolResponse - RIL_UNSOL_RESPONSE_BASE; /* 找出消息在s_unsolResponses[]的索引 */
  7. ... ...
  8. switch (s_unsolResponses[unsolResponseIndex].wakeType) { /* 禁止进入休眠 */
  9. case WAKE_PARTIAL:
  10. grabPartialWakeLock();
  11. shouldScheduleTimeout = true;
  12. break;
  13. ... ...
  14. }
  15. ... ...
  16. ret = s_unsolResponses[unsolResponseIndex] /* 调用消息处理函数responseString() */
  17. .responseFunction(p,data,datalen);
  18. ... ...
  19. ret = sendResponse(p); /* 发送Parcel中的信息内容到服务端RILJ */
  20. }
  21. static UnsolResponseInfo s_unsolResponses[] = {
  22. ... ...
  23. /* 消息对应的消息处理函数,新信息到来会唤醒系统 */
  24. {RIL_UNSOL_RESPONSE_NEW_SMS,responseString,WAKE_PARTIAL},... ...
  25. };
  26. static int responseString(Parcel &p,void *response,size_t responselen) {
  27. /* one string only */
  28. startResponse;
  29. appendPrintBuf("%s%s",printBuf,(char*)response);
  30. closeResponse;
  31. writeStringToParcel(p,(const char *)response); /* 把字符串格式的信息存到Parcel容器中 */
  32. return 0;
  33. }

二、解析短信息

1. RILJ获取短信息

  1. frameworks/opt/telephony/src/java/com/android/internal/telephony/RIL.java
  2. private void
  3. processUnsolicited (Parcel p) {
  4. ... ...
  5. case RIL_UNSOL_RESPONSE_NEW_SMS: ret = responseString(p); break;
  6. ... ...
  7. switch(response) {
  8. ... ...
  9. case RIL_UNSOL_RESPONSE_NEW_SMS: {
  10. if (RILJ_LOGD) unsljLog(response); /* 参考log:[UNSL]< UNSOL_RESPONSE_NEW_SMS */
  11. // FIXME this should move up a layer
  12. String a[] = new String[2];
  13. a[1] = (String)ret;
  14. SmsMessage sms;
  15. sms = SmsMessage.newFromCMT(a); /* 解析PDU格式的短信息 */
  16. if (mGsmSmsRegistrant != null) {
  17. mGsmSmsRegistrant
  18. .notifyRegistrant(new AsyncResult(null,sms,null));
  19. }
  20. break;
  21. }
  22. ... ...
  23. }
  24. ... ...
  25. }
  26. private Object
  27. responseString(Parcel p) {
  28. String response;
  29. response = p.readString(); /* 信息内容转换成Object */
  30. return response;
  31. }

2. 解析短信息

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

  1. frameworks/opt/telephony/src/java/android/telephony/SmsMessage.java
  2. public static SmsMessage newFromCMT(String[] lines) {
  3. // received SMS in 3GPP format
  4. SmsMessageBase wrappedMessage =
  5. com.android.internal.telephony.gsm.SmsMessage.newFromCMT(lines); /* 是对另一个newFromCMT的封装,因为有gsm和cdma两种短信,
  6. * 即cdma中也有newFromCMT,根据情况按需选择
  7. */
  8. return new SmsMessage(wrappedMessage);
  9. }
  10. com.android.internal.telephony.gsm.SmsMessage.newFromCMT(lines)的实现在
  11. frameworks/opt/telephony/src/java/com/android/internal/telephony/gsm/SmsMessage.java
  12. public class SmsMessage extends SmsMessageBase {
  13. ... ...
  14. public static SmsMessage newFromCMT(String[] lines) {
  15. try {
  16. SmsMessage msg = new SmsMessage();
  17. msg.parsePdu(IccUtils.hexStringToBytes(lines[1])); /* 解析PDU短信 */
  18. return msg;
  19. } catch (RuntimeException ex) {
  20. Rlog.e(LOG_TAG,"SMS PDU parsing Failed: ",ex);
  21. return null;
  22. }
  23. }
  24. ... ...
  25. }
  26. IccUtils.hexStringToBytes(lines[1])把十六进制的字符串转换成字节数组msg.parsePdu()解析这个数组的内容,最后获得短信内容
  27. frameworks/opt/telephony/src/java/com/android/internal/telephony/gsm/SmsMessage.java
  28. private void parsePdu(byte[] pdu) {
  29. ... ...
  30. mScAddress = p.getSCAddress();
  31. if (mScAddress != null) {
  32. if (VDBG) Rlog.d(LOG_TAG,"SMS SC address: " + mScAddress); /* 参考log:SMS SC address: +8613800755500 */
  33. }
  34. ... ...
  35. mMti = firstByte & 0x3;
  36. switch (mMti) {
  37. ... ...
  38. case 3: //GSM 03.40 9.2.3.1: MTI == 3 is Reserved.
  39. //This should be processed in the same way as MTI == 0 (Deliver)
  40. parseSmsDeliver(p,firstByte); /* 对短信类型为Deliver的短信进行解析 */
  41. break;
  42. ... ...
  43. }
  44. ... ...
  45. }
  46. private void parseSmsDeliver(PduParser p,int firstByte) {
  47. ... ...
  48. mOriginatingAddress = p.getAddress();
  49. if (mOriginatingAddress != null) {
  50. if (VDBG) Rlog.v(LOG_TAG,"SMS originating address: " /* 参考log: SMS originating address: +861371533xxxx */
  51. + mOriginatingAddress.address);
  52. }
  53. ... ...
  54. mProtocolIdentifier = p.getByte();
  55. // TP-Data-Coding-Scheme
  56. // see TS 23.038
  57. mDataCodingScheme = p.getByte();
  58. if (VDBG) {
  59. Rlog.v(LOG_TAG,"SMS TP-PID:" + mProtocolIdentifier
  60. + " data coding scheme: " + mDataCodingScheme); /* 参考log: SMS TP-PID:0 data coding scheme: 0 */
  61. }
  62. mScTimeMillis = p.getSCTimestampMillis();
  63. if (VDBG) Rlog.d(LOG_TAG,"SMS SC timestamp: " + mScTimeMillis); /* 参考log:SMS SC timestamp: 1571831129000 */
  64. boolean hasUserDataHeader = (firstByte & 0x40) == 0x40;
  65. parseUserData(p,hasUserDataHeader); /* 解析信息有效内容 */
  66. ... ...
  67. }
  68. private void parseUserData(PduParser p,boolean hasUserDataHeader) {
  69. ... ...
  70. if (VDBG) Rlog.v(LOG_TAG,"SMS message body (raw): '" + mMessageBody + "'"); /* 短信内容,参考log: SMS message body (raw): 'jchfbfh' */
  71. ... ...
  72. }

三、处理短信息  

用户有效的短信内容,最终保存在类型为String的mMessageBody变量中,该变量属于SmsMessageBase抽象类,而
SmsMessage继承于SmsMessageBase。
        回到前面frameworks/opt/telephony/src/java/com/android/internal/telephony/RIL.java中processUnsolicited(),
sms = SmsMessage.newFromCMT(a);解析完短信息后,返回一个SmsMessage并通知上层应用。

  1. frameworks/opt/telephony/src/java/com/android/internal/telephony/RIL.java
  2. mGsmSmsRegistrant
  3. .notifyRegistrant(new AsyncResult(null,null)); /* 把sms转成Object类型 */
  4. frameworks/base/core/java/android/os/AsyncResult.java
  5. public class AsyncResult
  6. {
  7. ... ...
  8. /** please note,this sets m.obj to be this */
  9. public
  10. AsyncResult (Object uo,Object r,Throwable ex)
  11. {
  12. userObj = uo;
  13. result = r;
  14. exception = ex;
  15. }
  16. ... ...
  17. }

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

  1. frameworks/opt/telephony/src/java/com/android/internal/telephony/BaseCommands.java
  2. public abstract class BaseCommands implements CommandsInterface {
  3. ... ...
  4. @Override
  5. public void setOnNewGsmSms(Handler h,int what,Object obj) { /* mGsmSmsRegistrant.notifyRegistrant(new AsyncResult(null,null))中的mGsmSmsRegistrant是在这里创建的 */
  6. mGsmSmsRegistrant = new Registrant (h,what,obj);
  7. }
  8. ... ...
  9. }

封装消息EVENT_NEW_SMS消息

  1. frameworks/base/core/java/android/os/Registrant.java
  2. public class Registrant
  3. {
  4. public
  5. Registrant(Handler h,Object obj) /* 传入需要处理消息为what的事件处理Handler h,obj为事件内容,参考phone.mCi.setOnNewGsmSms(getHandler(),EVENT_NEW_SMS,null); */
  6. {
  7. refH = new WeakReference(h);
  8. this.what = what;
  9. userObj = obj;
  10. }
  11. ... ...
  12. /**
  13. * This makes a copy of @param ar
  14. */
  15. public void
  16. notifyRegistrant(AsyncResult ar) /* 参考mGsmSmsRegistrant.notifyRegistrant(new AsyncResult(null,null)) */
  17. {
  18. internalNotifyRegistrant (ar.result,ar.exception); /* ar.result为sms */
  19. }
  20. /*package*/ void
  21. internalNotifyRegistrant (Object result,Throwable exception) /* internalNotifyRegistrant (sms,Throwable exception) */
  22. {
  23. Handler h = getHandler();
  24. if (h == null) {
  25. clear();
  26. } else {
  27. Message msg = Message.obtain(); /* 创建一个消息 */
  28. msg.what = what; /* 消息类型EVENT_NEW_SMS */
  29. msg.obj = new AsyncResult(userObj,result,exception); /* 消息内容sms */
  30. h.sendMessage(msg); /* 发送消息到注册了这个消息的Handler,参考phone.mCi.setOnNewGsmSms(getHandler(),null);的getHandler() */
  31. }
  32. }
  33. ... ...
  34. }

然而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这个消息从哪里来,然后到哪里去
就行了。

  1. ./frameworks/opt/telephony/src/java/com/android/internal/telephony/ImsSMSDispatcher.java
  2. public final class ImsSMSDispatcher extends SMSDispatcher {
  3. ... ...
  4. mGsmInboundSmsHandler = GsmInboundSmsHandler.makeInboundSmsHandler(phone.getContext(),/* 获取mGsmInboundSmsHandler,并启动状态机 */
  5. storageMonitor,phone);
  6. ... ...
  7. }
  8. ./frameworks/opt/telephony/src/java/com/android/internal/telephony/gsm/GsmInboundSmsHandler.java
  9. public class GsmInboundSmsHandler extends InboundSmsHandler {
  10. ... ...
  11. /**
  12. * Create a new GSM inbound SMS handler.
  13. */
  14. private GsmInboundSmsHandler(Context context,SmsStorageMonitor storageMonitor,PhoneBase phone) {
  15. super("GsmInboundSmsHandler",context,storageMonitor,phone,/* 构造GsmInboundSmsHandler时,通过super()调用InboundSmsHandler的构造函数 */
  16. GsmCellBroadcastHandler.makeGsmCellBroadcastHandler(context,phone));
  17. phone.mCi.setOnNewGsmSms(getHandler(),null); /* 注册EVENT_NEW_SMS消息 */
  18. mDataDownloadHandler = new UsimDataDownloadHandler(phone.mCi);
  19. }
  20. ... ...
  21. /**
  22. * Wait for state machine to enter startup state. We can't send any messages until then.
  23. */
  24. public static GsmInboundSmsHandler makeInboundSmsHandler(Context context,PhoneBase phone) {
  25. GsmInboundSmsHandler handler = new GsmInboundSmsHandler(context,phone); /* 实例化GsmInboundSmsHandler */
  26. handler.start(); /* 抽象类InboundSmsHandler继承与StateMachine,而GsmInboundSmsHandler继承于InboundSmsHandler,
  27. * GsmInboundSmsHandler调用启动状态机方法start()
  28. */
  29. return handler;
  30. }
  31. ... ...
  32. }
  33. ./frameworks/opt/telephony/src/java/com/android/internal/telephony/InboundSmsHandler.java
  34. public abstract class InboundSmsHandler extends StateMachine {
  35. ... ...
  36. protected InboundSmsHandler(String name,Context context,PhoneBase phone,CellBroadcastHandler cellBroadcastHandler) {
  37. ... ...
  38. addState(mDefaultState); /* 构造InboundSmsHandler时,添加状态机的状态 */
  39. addState(mStartupState,mDefaultState);
  40. addState(mIdleState,mDefaultState);
  41. addState(mDeliveringState,mDefaultState);
  42. addState(mWaitingState,mDeliveringState);
  43. setInitialState(mStartupState); /* 初始化状态机 */
  44. if (DBG) log("created InboundSmsHandler");
  45. }
  46. ... ...
  47. class IdleState extends State {
  48. @Override
  49. public void enter() {
  50. if (DBG) log("entering Idle state");
  51. sendMessageDelayed(EVENT_RELEASE_WAKELOCK,WAKELOCK_TIMEOUT);
  52. }
  53. @Override
  54. public void exit() {
  55. mWakeLock.acquire();
  56. if (DBG) log("acquired wakelock,leaving Idle state");
  57. }
  58. @Override
  59. public boolean processMessage(Message msg) {
  60. if (DBG) log("Idle state processing message type " + msg.what);
  61. switch (msg.what) {
  62. case EVENT_NEW_SMS: /* 空闲时,接收到短信 */
  63. case EVENT_BROADCAST_SMS:
  64. deferMessage(msg);
  65. transitionTo(mDeliveringState); /* 转到mDeliveringState */
  66. return HANDLED;
  67. ... ...
  68. }
  69. }
  70. }
  71. ... ...
  72. class DeliveringState extends State { /* 转到mDeliveringState状态 */
  73. @Override
  74. public void enter() {
  75. if (DBG) log("entering Delivering state");
  76. }
  77. @Override
  78. public void exit() {
  79. if (DBG) log("leaving Delivering state");
  80. }
  81. @Override
  82. public boolean processMessage(Message msg) {
  83. switch (msg.what) {
  84. case EVENT_NEW_SMS:
  85. // handle new SMS from RIL
  86. handleNewSms((AsyncResult) msg.obj); /* 处理新SMS */
  87. sendMessage(EVENT_RETURN_TO_IDLE); /* 处理完回到空闲状态 */
  88. return HANDLED;
  89. ... ...
  90. }
  91. }
  92. ... ...
  93. }
  94. }
  95. void handleNewSms(AsyncResult ar) {
  96. ... ...
  97. SmsMessage sms = (SmsMessage) ar.result;
  98. result = dispatchMessage(sms.mWrappedSmsMessage);
  99. ... ...
  100. }
  101. public int dispatchMessage(SmsMessageBase smsb) {
  102. ... ...
  103. return dispatchMessageRadioSpecific(smsb);
  104. ... ...
  105. }

通过以上流程可以了解到,当状态机接收到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)把消息广播出去。

  1. ./frameworks/opt/telephony/src/java/com/android/internal/telephony/InboundSmsHandler.java
  2.  
  3. class DeliveringState extends State {
  4. ... ...
  5. public boolean processMessage(Message msg) {
  6. switch (msg.what) {
  7. ... ...
  8. case EVENT_BROADCAST_SMS: /* 接收到EVENT_BROADCAST_SMS消息并处理 */
  9. // if any broadcasts were sent,transition to waiting state
  10. if (processMessagePart((InboundSmsTracker) msg.obj)) {
  11. transitionTo(mWaitingState);
  12. }
  13. return HANDLED;
  14. ... ...
  15. }
  16. }
  17. ... ...
  18.  
  19. }
  20.  
  21. boolean processMessagePart(InboundSmsTracker tracker) {
  22. ... ...
  23. BroadcastReceiver resultReceiver = new SmsBroadcastReceiver(tracker); /* 创建一个广播接收者,用来处理短信广播的结果 */
  24. ... ...
  25. intent = new Intent(Intents.SMS_DELIVER_ACTION); /* 设置当前intent的action为SMS_DELIVER_ACTION */
  26.  
  27. // Direct the intent to only the default SMS app. If we can't find a default SMS app
  28. // then sent it to all broadcast receivers.
  29. ComponentName componentName = SmsApplication.getDefaultSmsApplication(mContext,true); /* 这个action只会发送给carrier app,而且carrier app可以通过set result为RESULT_CANCELED来终止这个广播 */
  30. if (componentName != null) {
  31. // Deliver SMS message only to this receiver
  32. intent.setComponent(componentName);
  33. log("Delivering SMS to: " + componentName.getPackageName() +
  34. " " + componentName.getClassName());
  35. }
  36. ... ...
  37. dispatchIntent(intent,android.Manifest.permission.RECEIVE_SMS,/* 广播intent */
  38. AppOpsManager.OP_RECEIVE_SMS,resultReceiver);
  39. ... ...
  40. }
  41.  
  42. private final class SmsBroadcastReceiver extends BroadcastReceiver {
  43. ... ...
  44. public void onReceive(Context context,Intent intent) {
  45. ... ...
  46. // Now that the intents have been deleted we can clean up the PDU data.
  47. if (!Intents.DATA_SMS_RECEIVED_ACTION.equals(action)
  48. && !Intents.DATA_SMS_RECEIVED_ACTION.equals(action)
  49. && !Intents.WAP_PUSH_RECEIVED_ACTION.equals(action)) {
  50. loge("unexpected BroadcastReceiver action: " + action);
  51. }
  52.  
  53. int rc = getResultCode();
  54. if ((rc != Activity.RESULT_OK) && (rc != Intents.RESULT_SMS_HANDLED)) {
  55. loge("a broadcast receiver set the result code to " + rc
  56. + ",deleting from raw table anyway!");
  57. } else if (DBG) {
  58. log("successful broadcast,deleting from raw table.");
  59. }
  60.  
  61. deleteFromRawTable(mDeleteWhere,mDeleteWhereArgs);
  62. sendMessage(EVENT_BROADCAST_COMPLETE); /* 成功广播 */
  63.  
  64. ... ...
  65. }
  66. ... ...
  67. }

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

总结

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

猜你在找的Android相关文章