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 處理的時序圖