Android短信与电话模块分析

android 短信与电话模块分析

目的:

1. 何为AT指令?
2. 分析源码, 确认at指令的发送以及返回信息的内容, 是否可以抛到上层,
3. 当前的开关机检测机制是否准确?
4. 在适配rom的时候, 这方面涉及的到配置有哪些? rc文件, so库, system.prop

at指令

AT指令是一种 Command language, 也叫作 Hayes command set, 是 Dennis Hayes 在1981年为其发明的300波特率的调制解调器发明的语言. 这一命令集由一系列的短文本字符串组成, 这些指令可以联合起来产生拨打电话, 挂断电话, 改成连结参数等一系列操作指令. 更说细的内容请参考附录[2][3].

sms 和 mms 相关介绍参考附录[1]

每一条at指令需要回车符作为确认, 否则设备不认可

发送短信

1. AT+CMGF=1 回车             // 设置短信发送格式, 1 代表文本格式, 0 代表pdu格式
2. AT+CMCA="+86138******" 回车    // 设置电话号码, 一般模块都会默认设置
3. AT+CMCS="+86 手机号码" 回车 // 设备会返回一个 ">"
4. 输入需要发送的字符串, ctrl+Z 结束发送.

命令行示例:

AT+CMGF=1
OK
AT+CMGS="+31628870634"
> This is the text message.→
+CMGS: 198
OK

读取短信

1. AT+CMGR=X 回车     // X代表sim卡中第几条短信, 一般sim卡是30-50不等
2. 串口会返回一长字符串 // 一般是由短信标志, 来电号码, 短信内容, 发送, 时间等等几部分组成.
3. AT+CMGD=x 回车     // 当sim卡满时, 是不可以收到短信的, 当设备收到短信时, 串口会返回一串字符

命令行示例:

AT+CMGF=1
OK
AT+CMGL="ALL"
+CMGL: 1,"REC UNREAD","+31628870634",,"11/01/09,10:26:26+04"
This is text message 1
+CMGL: 2,"REC UNREAD","+31628870634",,"11/01/09,10:26:49+04"
This is text message 2
OK
AT+CMGD=1
OK
AT+CMGD=2
OK

以上参考附录[6]

更详细的at指令互动参考附录[7], 以及附件pdf(sending_sms_at_commands.pdf)

更详细的at命令列表(完整的at列表请参看附录[8]及附件pdf(supported_at_command_reference)):

AT – Check to see if the module is active. Should return ‘OK’
AT+CREG? – Is the module registered to the network? Set the mode first: AT+CREG=2
AT+COPS? – What network is the module registered?
AT+CMGF=1 – This puts the module into text mode so messages can be sent/received
AT+CMGS=”number”,129 <cr>< body of message> <1A> – Send a text message.
AT+CMGL=”ALL” – Lists all text messages that are on the device (or network)
AT+CMGR=<index> – Read SMS message at index number
AT+QBAND? – What band am I on?
AT+CIMI – Get the IMSI number from the module
AT+CSQ – Check the signal strength
AT+GSN – Get IMEI number
AT+QSPN – Get service provider name
AT+QCCID – Get CCID number from SIM
AT+CRSM – SIM card restricted access (still researching)
AT+CSIM – Generic SIM access (still researching)

通过以上的资料可知, 由调制解调器封装后返回信息并不是很多, 信息发送成功也只是返回OK, 发送失败, 是通过等待一定的时间来判断的. 那么接下来分析,源码是否可以获取得多的信息, 判断当前的开关机检测是否准确.

使用pdu 发送短信参考附件[9]

源码分析

com.android.internal.telephony.SMSDispatcher.java 调用接口sendText(…) 具体实现在下面两个类
com.android.internal.telephony.gsm.GsmSMSDispatcher.java 进一步跟踪,调用链为 sendText() -> sendSms() -> sendSmsByPstn()
com.android.internal.telephony.cdma.CdmaSMSDispather.java 同上

由上一步的GsmSMSDispatcher/CdmaSMSDispatcher 中的mCi.sendImsGsmIms 调用到 com.android.internal.telephony.RIL.java 中的 sendImsGsmSms()

最终是通过AIDL, 访问android.hardware.radio.V1_1.IRadio, 再通过hidl方问硬件so库, 具体调用链如下:
com.android.internal.telephony.RIL.java::sendImsGsmSms() ->
android.hardware.radio.V1_1.IRadio.java::sendImsSms() ->
android.os.HwParcel -> android.os.IHwBinder::transact(104/sendImsSms/, _hidl_request, _hidl_reply, android.os.IHwBinder.FLAG_ONEWAY);
com.android.internal.telephony.metrics.TelephonyMetrics.java::writeRilSendSms() /* 添加回调 */
com.android.internal.telephony.metrics.InProgressSmsSession.java ->
com.android.internal.telephony.nano.TelephonyProto.SmsSession.Event

解析串口数据, 通过 com.android.internal.telephony.nano.TelephonyProto::writeTo() 回调上一部注册的 SmsSession.Event
Event里的信息有: TelephonySettings, TelephonyServiceState, ImsConnectionsState, RilDataCall[], errorCode 是我们要关心的, 开关机检测主要关心ImsConnectionState.
ImsConnectionState 中有状态 STATE_UNKONWN, CONNECTED, PROGRESSING, RESUMED, SUSPENDED.
结合以上的at指令终端交互流程可知, ImsConnectionState, errorCode, 即为短信发送后可获取的具体状态.

接下来, 继续确定, framework层抛出的短信broadcast 是否依ImsConnectionState 状态决定的.

注册调用链:

com.android.internal.telephony.SMSDispatcher.java::sendText(.., deliveryIntent, mSenderCallback) ->
com.android.internal.telephony.SMSDispatcher.MultiparSmsSender::onServiceReady() ->
android.service.carrier.ICarrierMessagingService.aidl::sendMultipartTextSms(…,deliveryIntent, mSenderCallback) ->
com.android.internal.telephony.SMSDispatcher.SmsSenderCallback::onSendSmsComplete() ->
com.android.internal.telephony.CommandsInterface,
在CommandsInterface::setOnSmsStatus 回调中, 调用注册deliveryIntent, 向上层应用发送消息状态.

调用 mSenderCallback的流程:

SMSDispatcher 即为一个Handler, 处理短信发送相关的几个状态为:
EVENT_SEND_SMS_COMPLETE, EVENT_SEND_RETRY, EVENT_SEND_CONFIRMED_SMS, EVENT_STOP_SENDING, EVENT_HANDLE_STATUS_REPORT,
EVENT_SEND_LIMIT_REACHED_CONFIRMATION, EVENT_CONFIRM_SEND_TO_POSSIBLE_PREMIUM_SHORT_CODE
初始化SMSDISPATCHER的类为
com.android.internal.telephony.IccSmsInerfaceManager,
初始化的实类为 ImsSmsDispatcher, 在其handleMessage中 处理的消息为 EVENT_IMS_STATE_DONE, EVENT_IMS_STATE_CHANGED
触发这个消息的的类为
在CommandsInterface::registerForImsNetworkStateChanged(this, EVENT_IMS_STATE_CHANGED, null);
CommandsInterface 的实例 mCi 为 com.android.internal.telephony.Phone.java 中的单例
Phone的实例为 GsmCdmaPhone.java , 通过 TelephonyComponentFactory::makeIccSmsInterfaceManager(this) 传入
GsmCdmaPhone::initOnce() 中通过 TelephonyComponentFactory::makeGsmCdmaCallTracker() 初始化
在Phone系的构造函数中会构造TelephoneComponentFactory.makeAppSmsManager 初始化 AppSmsmanager 监听短信状态.
在IccSmsInterfaceManager 构造函数中初始化 ImsSMSDispatcher 会传递 phone.smsUsageMonitor, 初始化InBoundSmsHandler, SmsBroadcastUndelivered
在InboundSmsHandler::dispatchSmsDeliveryIntent 中会调用 mAppSmsManager.handleSmsReceiverdIntent
InboundSmsHandler::processMessage 调用 dispatchSmsDeliveryIntent, 在初始化 StartupState 中由消息 EVENT_BROADECAST_SMS 处理短信发送状态.

由InboundSmsHandler.StartupState 中的注释可知, 最终通知回调的类为SmsBroadcastUndevlivered, 其中亦有 EVENT_BROADECAST_SMS 消息事件处理, 逻辑为开一个线程轮询查询RawTable, 通过 ContentProvider 查询 PDU_PENDING_MESSAGE_PROJECTION, 通过 Telephony.Sms.CONTENT_URI (“content://sms/sent”)找到 SMS Provider 查询rawpdudata

那么表里的信息是何时写的呢? 在 InboundSmsHandler::writeInboxMessage 由 InboundSmsHandler::dispatchSmsDeliveryIntent 由SmsManager::getAutoPersisting()为true时触发

继续跟踪 InboundSmsHandler::dispatchSmsDeliveryIntent 的触发时机
由 android.telephony.CarrierMessagingServiceConnection.CarrierMessagingServiceConnection::onServiceConnected ->
android.telephony.CarrierMessagingServiceConnection::onServiceReady(在android.internal.telephony.CarrierServiceSmsFilter中实现) ->
android.internal.telephony.CarrierServiceSmsFilter::filterSms ->
InboundSmsHandler.CarrierServiceSmsFilterCallback::onFilterComplete ->
InboundSmsHandler::dispatchSmsDeliveryIntent

接下来 分析 CarrierMessagingServiceConnection 中的 ICarrierMessagingService::filterSms() 逻辑,
ICarrierMessagingService 由 CarrierMessagingSerivce 中的 ICarrierMessagingWrapper 作为service 端来实现具体业务

结合短信发送流程: 接收端收到一条短信, 会向SMS center 发送一条是否成功的报文, SMS center 再将这些信息返回给发送者(可参考附录10), 这时发送端相当于接收了一条pdu, android 作为接收端就是遍历这些pdu, 通过filterSms 来达确认是否成功送达或是一条新短信.

CarrierMessagingSerivce 编历的pdu, 是怎么获取的? 这里仍旧没有探索到.

分析至此, 已可知当前的短信开关机检测是与at命令的效果一致的.

因此当前的开关机检测可视为准确的.

PS: 时间有限, 关于此次分析相关的UML图, 流程图就先不画了, 直接采用文字描述. 有纰漏之处或者疑问, 欢迎指出, 进行进一步计论.

查看radio 日志

修改 system/core/liblog/logger_write.c 中 __android_log_buf_write() 方法, 将RIL, IMS, AT log都打开, 合并到radio buffer 中

adb logcat -b radio 查看 radio buffer 中的日志信息.

查看pdu, 在deliveringIntent 中的 pdu 中存储的. 只有联通给联通电信发, 电信给电信发, 移动给移动发才有.

附录:

  1. Everything You Need to Know About SMS & MMS on the iPhone
  2. SMS wiki
  3. Introduction to AT Commands
  4. Hayes command set
  5. SMS Tutorial
  6. gsm-modem-tutorial
  7. Send SMS using AT commands
  8. gsm-at-commands-set
  9. sms-pdu-mode
  10. Message Delivery Reports
版权声明:除特殊说明,博客文章均为Sophimp原创,依据CC BY-SA 4.0许可证进行授权,转载请附上出处链接及本声明。 由于可能会成为AI模型(如chatGPT)的训练样本,本博客禁止将AI自动生成内容作为文章上传(特别声明时除外)。
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇