Android URC 介绍及源码案例参考
1. URC 含义
URC 是 Unsolicited Result Code(非请求结果码)的缩写。
- 它是 modem(基带)在不需要 AP 主动请求的情况下向上层主动上报的消息。
- 典型例子:短信到达提示、网络状态变更、来电通知、信号质量变化等。
- URC 一般以 AT 命令扩展的形式从 modem 发到 AP,例如串口、QMI、RIL 通道。
- URC 通常以字符串或特定消息 ID 的形式携带信息,比如:
这些信息不是某个 AT command 的直接响应,而是 modem 主动推送的。+CMTI: "SM",3 RING +CREG: 1,"1234","5678"
2. 在 Android 中 modem URC 的处理流程
在 Android 平台,modem 与 Android Telephony Framework 通信主要通过 RIL(Radio Interface Layer)。
URC 在 Android 中通常叫 Unsolicited Response(非请求消息),它的流程大致如下:
典型处理链路
Modem(基带模块)↓ (AT字符串, QMI, 或其它协议)
RIL Daemon (rild) --> Vendor RIL 实现↓
RILJ (Java层 Radio Interface Layer)↓
PhoneBase / GsmCdmaPhone / ServiceStateTracker 等↓
TelephonyManager / Broadcast / App
-
modem --> Vendor RIL
Modem 通过串口 / QMI / IPC 接口向 vendor RIL driver 上报 URC,vendor RIL driver 收到数据后,调用RIL_onUnsolicitedResponse()
通知上层。
-
Vendor RIL --> rild (RIL Daemon)
rild
进程读取并解析这些非请求 URC,然后通过libril.so
提供的回调封装成 RadioIndication 发送给 Java 层。 -
RILJ(Java层)
在 frameworks/opt/telephony/RIL.java 中有很多处理 unsolicited 事件的 case,例如:case RIL_UNSOL_RESPONSE_NEW_SMS:if (RILJ_LOGD) unsljLogRet(response, ret);if (mSmsRegistrant != null) {mSmsRegistrant.notifyRegistrant(new AsyncResult(null, ret, null));}break; case RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED:pollCallsWhenSafe();break;
这些就是 modem 上报 URC(短信、新呼叫、网络状态变更等)的处理入口。
-
Telephony Framework --> Apps
上层组件(ServiceStateTracker
、GsmCdmaCallTracker
、InboundSmsHandler
等)根据收到的 URC 更新状态并向应用广播,例如:- 短信到达:会发出
SMS_RECEIVED
广播。 - 来电:触发 Telephony UI 更新,启动拨号界面。
- 网络状态变更:通过
ServiceState
回调给TelephonyManager
。
- 短信到达:会发出
3. Android 上可以参考的功能代码
URC 在 Android 中处理方案可以参考 AOSP 源码,位置大概如下:
C/C++ 层(RIL Daemon 与 Vendor RIL 接口)
hardware/ril/libril/ril.cpp
- 函数:
RIL_onUnsolicitedResponse()
用来把 modem 上报的 URC 往 Java 层送。
- 函数:
hardware/ril/libril/
中的核心处理
Java 层(RILJ)
frameworks/opt/telephony/src/java/com/android/internal/telephony/RIL.java
processUnsolicited()
方法:集中处理底层来的 URC- 不同的 case 对应不同的
RIL_UNSOL_*
常量。
frameworks/opt/telephony/src/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java
- 处理网络注册相关的 URC
frameworks/opt/telephony/src/java/com/android/internal/telephony/InboundSmsHandler.java
- 处理短信的 URC(
RIL_UNSOL_RESPONSE_NEW_SMS
)
- 处理短信的 URC(
frameworks/opt/telephony/src/java/com/android/internal/telephony/GsmCdmaCallTracker.java
- 处理来电(
RIL_UNSOL_CALL_STATE_CHANGED
)
- 处理来电(
4. 一个简单的 URC 上报示例
假设 modem 收到一条新的短信,会发出 URC:
+CMTI: "SM",3
处理流程:
- modem 主动通过 AT 接口发送
+CMTI
URC 给 RIL。 - Vendor RIL 在解析到
+CMTI
后调用:RIL_onUnsolicitedResponse(RIL_UNSOL_RESPONSE_NEW_SMS, pduData, pduLen);
- libril 通知 RILJ(Java 层):
case RIL_UNSOL_RESPONSE_NEW_SMS:mSmsRegistrant.notifyRegistrant(new AsyncResult(null, ret, null));
InboundSmsHandler
收到通知,存储短信并发SMS_RECEIVED
广播给上层应用。
✅ 总结:
- URC:modem 主动通知上层的异步消息,RIL 叫 unsolicited response。
- Android 中可参考:
- C/C++:
hardware/ril/libril/ril.cpp
(RIL_onUnsolicitedResponse) - Java:
RIL.java
的processUnsolicited
逻辑 - 各 tracker(ServiceStateTracker、CallTracker、InboundSmsHandler)的注册与处理。
- C/C++:
- 为了调试,可以开 modem log(AT 口)结合
adb logcat -b radio
看 u-r-c 相关日志。
URC 在 Android 处理的时序图