Android URC 消息透传 MTK 代码方案
1、背景简介
介绍 Android RIL / Modem URC(Unsolicited Result Code)消息在 ServiceStateTracker(或者 Telephony framework)层的接入流程。
目标:一个能落地的添加监听回调的方法。
Q:(有案例表示)为什么不需要像 Android 默认 URC 逻辑,在 RIL 定义(mtk_ril.h)接口/变量映射值?
相关知识:Android URC 介绍及源码案例参考
1.1 URC 原理回顾
在target侧代码(如 modem_6878/mcu/interface/protocol/general/atp_dmf_cmd_def.h
)中新增了:
// Define URC structure
#ifdef DMF_URC_IND_SEC
DMF_URC_IND(DMF_DATA_STATE_IND, dmf_data_class_info_urc_ind_struct, data_class_info_ind_struct)DMF_FIELD_VAR(kal_uint32, cause, UNUSED_FIELD) DMF_FIELD_STRING(reject, 27)DMF_FIELD_VAR(kal_bool, Support, UNUSED_FIELD)DMF_FIELD_VAR(kal_bool, Accessible, UNUSED_FIELD)
DMF_URC_IND_END(dmf_data_class_info_urc_ind_struct)
在 Modem 协议中定义了一种新的 上行异步通知(URC),它属于 DMF_DATA_STATE_IND
类型,Modem 会在某些条件下主动把 cause/reject/Support/Accessible
信息发给 AP(Application Processor)。
Android 上 Telephony 层想监听这个 URC,需要走一条链路:
Modem URC → RILD → Vendor RIL → Telephony(RIL.java) → PhoneBase → ServiceStateTracker
1.2 URC 数据格式
+EDMFAPP:2,25102,...
是Modem ATP 层输出的 URC 文本格式,其中 2,25102 就是两级“类别码”和“消息 ID”,它并不是随便写的,而是 在 Modem 的 DMF/ATP 协议头文件里定义的枚举值。
-
第一个数字
2
对应 URC 类别号(class ID),即 DMF 协议的DMF_DATA_CLASS_INFO_IND
的数值。
这个枚举一般在类似:modem_u_6878/mcu/interface/protocol/general/atp_dmf_cmd_def.h
或者
modem_u_6878/mcu/interface/protocol/general/dmf_cmd_id.h
里,定义为:
typedef enum {DMF_DATA_CLASS_COMMON_IND = 1,DMF_DATA_CLASS_INFO_IND = 2, // ← 这个就是第一个 "2"... } dmf_data_class_id_enum;
-
第二个数字
25102
是该类下具体的 URC 消息编号(message ID / cmd id),对应在DMF_URC_IND(...)
宏展开后生成的 ID。
DMF 协议通常用 “类号 * 10000 + 序号” 这样的规则生成唯一的数值,比如:#define MSG_ID_DMF_DATA_CLASS_INFO_URC_IND (DMF_DATA_CLASS_IND * 10000 + 2102)
实际数值取决于
dmf_data_class_info_urc_ind_struct
注册时的枚举定义,可以在 modem 的*_msg_id.h
或工具生成的 ID 文件查到,比如:out/interface/protocol/mtk_modem/atp_dmf_msg_id.h
1.3 URC 参考日志
09-01 18:34:19.506 1234 1425 D RmmOemUrcHandler: [0] handleOemUrc,
urc = +EDMFAPP: 2,25102,“”,1,0
- Modem 已经能发出 +EDMFAPP: 2,25102,“”,1,0 这种 AT URC
- AP 端已经有 RmmOemUrcHandler 这种类在打 handleOemUrc 的 log
说明 vendor RIL / OEM handler 层,其实已经解析到该字符串,只是还没有往 Android Telephony(ServiceStateTracker, SST)这一层继续分发
Q:mobile radiolog 已经有如上日志上报,AP 的 SST 应该如何接收响应这种 URC消息?如何让 ServiceStateTracker (SST) 直接收到这个 URC?
1.4 AP 侧如何 URC 中的数据
ATP 层的 AT 文本只是人类可读/调试输出,AP 侧真正用的其实是底层二进制协议里的 ClassID + MsgID。
在 AP / vendor RIL 中,会有一个 DMF 协议解析器(可能是由 .h
自动生成的 C 文件),它会根据收到的二进制报文头部解析出:
struct dmf_msg_hdr {uint16 class_id; // 2uint16 msg_id; // 25102...
};
然后查找注册表,调用对应的回调函数,例如:
case DMF_DATA_CLASS_INFO_IND:switch(msg_id) {case MSG_ID_DMF_DATA_CLASS_INFO_URC_IND:onDmfDataClassInfo(&payload);break;...}
如果是自定义新增的 URC,那么需要在 AP 侧解析器里也声明这个 MSG_ID_DMF_DATA_CLASS_INFO_URC_IND
,并映射到一个 RIL_UNSOL 事件(后文代码解读会讲这部分)。
1.5 小结
3
= URC 类的 ID (DMF_DATA_CLASS_INFO_IND
)25102
= 这个类下的具体 URC 消息 ID (MSG_ID_DMF_DATA_CLASS_NFO_URC_IND
)- 定义位置:Modem 侧 DMF 协议的枚举头文件(
atp_dmf_cmd_def.h
,*_msg_id.h
) - AP 用法:Vendor RIL/DMF 解码器用它来分发给对应的 handler,或映射到 Android Telephony 的 callback。
Note:如果源码里定义了 25102
这个 ID 的真实宏名,这样 AP 在解析的时候不用直接写魔法数字了。
2. AOSP 逻辑思路
2.1 添加新 URC 的关键步骤
2.1.1 Modem 协议栈侧
平台已经在 .h
定义了该 URC,接下来需要保证:
- 在 Modem 连 AP 的跨核接口(如 CCCI, HIDL, socket)中正确发送 URC
- URC 有唯一的 RIL_UNSOL_XXXX ID
比如:
#define RIL_UNSOL_DATA_CLASS_INFO 11042 // 自定义,不与已有冲突
在 vendor ril
实现里,把 DMF 协议的 URC 转成 RIL_UNSOL 事件,通过 RIL_onUnsolicitedResponse
发送给 Android Telephony。
例子:
static void onDmfDataClassInfo(const dmf_data_class_info_urc_ind_struct *urc)
{Parcel p;p.writeInt32(urc->cause);p.writeString(urc->rejecct)