系列文章目录本文是骁龙移动平台双卡双待DSDS的技术内幕系列的第三篇深入分析RIL层如何通过QMI协议实现AP与Modem的双通道通信。1. RIL在双卡架构中的角色1.1 RIL的定位RILRadio Interface Layer是Android系统中APApplication Processor与BPBaseband Processor/Modem之间的标准通信桥梁。在DSDS场景下┌──────────────────────────────────┐ │ Android Framework │ │ Phone[0] Phone[1] │ └──────┬─────────────────┬─────────┘ │ HIDL/AIDL │ HIDL/AIDL ┌──────▼─────────────────▼─────────┐ │ rild 进程 │ │ ┌─────────────┐ ┌─────────────┐ │ │ │RadioImpl[0] │ │RadioImpl[1] │ │ ← 两个 Radio HAL 实例 │ └──────┬──────┘ └──────┬──────┘ │ │ │ │ │ │ ┌──────▼──────┐ ┌──────▼──────┐ │ │ │ QMI Client │ │ QMI Client │ │ ← 独立的 QMI 连接 │ │ (Sub 0) │ │ (Sub 1) │ │ │ └──────┬──────┘ └──────┬──────┘ │ └─────────┼───────────────┼────────┘ │ QMI/SMD/GLINK │ ┌─────────▼───────────────▼────────┐ │ Modem Subsystem │ └──────────────────────────────────┘1.2 AOSP RIL vs 高通 RIL特性AOSP(参考实现)高通QC-RIL通信协议AT命令QMI(Qualcomm MSM Interface)性能文本解析较慢二进制TLV高效功能覆盖基础通话/数据完整Modem能力IMS/GPS/NV等双卡支持简单多实例完整Multi-Subscription维护状态维护状态AOSP示例高通proprietary2. QMI协议架构2.1 QMI是什么QMI(Qualcomm MSM Interface是高通设计的一套AP-Modem私有通信协议采用TLVType-Length-Value编码格式具有以下特点面向服务按功能域划分为多个ServiceNAS、WDS、DMS、Voice等异步消息支持Request/Response和Indication主动上报传输层无关可运行在SMD、GLINK、PCle等物理通道上2.2 QMI服务分类┌─────────────────────────────────────────────────────────┐ │ QMI Service 总览 │ ├───────────┬──────────────────────────────────────────────┤ │ Service │ 职责 │ ├───────────┼──────────────────────────────────────────────┤ │ QMI_NAS │ Network Access Service - 网络注册/信号/PLMN │ │ QMI_WDS │ Wireless Data Service - 数据拨号/PDN管理 │ │ QMI_DMS │ Device Management Service - 设备信息/操作 │ │ QMI_VOICE │ Voice Service - 通话控制 │ │ QMI_UIM │ UIM Service - SIM 卡管理 │ │ QMI_PBM │ Phonebook Manager - 电话本 │ │ QMI_IMS │ IMS Service - VoLTE/VoNR │ │ QMI_PDC │ Persistent Device Configuration - MBN配置 │ │ QMI_DSD │ Data System Determination - 数据系统选择 │ │ QMI_LOC │ Location Service - GNSS 定位 │ └───────────┴──────────────────────────────────────────────┘2.3 QMI消息格式┌────────────────────────────────────────────┐ │ QMI 消息格式 │ ├──────────────┬──────────────┬──────────────┤ │ QMUX Header │ Service Hdr │ Payload │ │ (传输层) │ (服务层) │ (TLV 数据) │ ├──────────────┼──────────────┼──────────────┤ │ IF Type (1B) │ Svc Type(2B) │ TLV Type(1B) │ │ Length (2B) │ Client ID(1B)│ TLV Len (2B) │ │ Ctrl Flag(1B)│ Msg ID (2B) │ TLV Value │ │ Svc Type(1B) │ Msg Len (2B) │ ... │ │ Client ID(1B)│ TX ID (2B) │ │ └──────────────┴──────────────┴──────────────┘TLV示例查询信号强度请求// 「信号强度查询请求」(NAS 服务) (Msg ID: 0x0020) Type: 0x10 (Request Mask) Length: 0x0002 Value: 0x00FF (请求所有信号类型)3. DSDS下的双QMI通道3.1 双通道建立过程┌─────────┐ ┌───────────┐ ┌──────────┐ │ rild │ │ QMUX Daemon│ │ Modem │ │ │ │ (qmuxd) │ │ │ └────┬────┘ └─────┬─────┘ └────┬─────┘ │ │ │ │ Open QMI Port 0 │ │ ├────────────────────►│ Bind Subscription 0 │ │ ├────────────────────►│ │ │◄────────────────────┤ │◄────────────────────┤ ACK │ │ │ │ │ Open QMI Port 1 │ │ ├────────────────────►│ Bind Subscription 1 │ │ ├────────────────────►│ │ │◄────────────────────┤ │◄────────────────────┤ ACK │ │ │ │ │ NAS Register (Sub0) │ │ ├────────────────────►├────────────────────►│ │ │ │ │ NAS Register (Sub1) │ │ ├────────────────────►├────────────────────►│3.2 QMI双栈绑定机制在DSDS模式下每个QMI Service Client需要通过Subscription Binding来确定它服务的是哪张SIM卡//绑定QMI Client到指定Subscriptionqmi_client_send_msg_sync(client_handle,[QMI枚举值],bind_req,// subscription_type: PRIMARY / SECONDARYsizeof(bind_req),bind_resp,sizeof(bind_resp),QMI_TIMEOUT);// bind_req 结构typedefstruct{[QMI结构体]subscription_type;// [QMI枚举值] 0x00// [QMI枚举值] 0x01}[QMI结构体];3.3 传输层SMD vs GLINK特性SMD (Shared Memory Driver)GLINK (Generic Link)适用平台老平台(MSM8996之前)新平台(SDM845)带宽较低更高延迟中等更低多通道固定通道数动态分配中断机制硬件中断虚拟中断设备节点#查看QMI通道设备ls/dev/smdcntl*#SMD方式ls/dev/qmi_*#GLINK方式#典型设备节点/dev/smdcntl0#QMI control channel for Sub0/dev/smdcntl8#QMI control channel for Sub14. 双RIL实例的生命周期管理4.1 初始化流程//PhoneFactory.java-创建双RIL实例publicstaticvoidmakeDefaultPhones(Contextcontext){intnumPhonesTelephonyManager.getDefault().getActiveModemCount();//numPhones 2 (DSDS模式)sCommandsInterfacesnewRIL[numPhones];for(inti0;inumPhones;i){sCommandsInterfaces[i]newRIL(context,RILConstants.PREFERRED_NETWORK_MODE,cdmaSubscription,i);// i instanceId}}4.2 消息路由机制RIL 如何确保消息发送到正确的 Modem Subscription┌─────────────────────────────────────────────┐ │ RIL Message Routing │ │ │ │ Phone[0].dial() │ │ │ │ │ ▼ │ │ RIL[0].dial(dialRequest) │ │ │ │ │ ▼ │ │ 「拨号请求」(Voice 服务) │ │ (routed to Sub0 via bound QMI client) │ │ │ │ │ ▼ │ │ Modem: NAS[Sub0] → CM[Sub0] → RF │ │ │ └─────────────────────────────────────────────┘4.3 Unsolicited Response 分发Modem 主动上报的消息Indication如何路由到正确的 Phone 实例// RadioIndication.javaOverridepublicvoidnetworkStateChanged(intindicationType){// 通过 mRil 实例的 mInstanceId 确定目标 PhonemRil.processIndication(HAL_SERVICE_NETWORK,indicationType);// 内部调用// mRil.mRegistrantLists[EVENT_NETWORK_STATE_CHANGED]// . notifyRegistrants(); - Phone[mInstanceId]}5. DSDS 特有的 QMI 交互5.1 跨 Subscription 事件通知某些事件需要跨两个 Subscription 通知例如场景Sub0通话中Sub1来电 1. Modem通过「全部呼叫状态指示」Voice服务通知 2. QMI_VOICE Client(Sub1收到INCOMING_CALL indication 3. RIL[1]上报UNSOL_RESPONSE_CALL_STATE_CHANGED 4. Phone[1]更新CallTracker 5. TelecomManager判断冲突 - Sub0已有活跃通话 - DSDS模式下不支持同时通话 6. 给用户提示挂断当前通话以接听新来电5.2 DDS Switch 的 QMI 实现// Default Data Subscription切换的QMI流程 AP → 「设置首选数据Modem请求」DSD服务target_sub Modem: 1. 断开当前Sub的数据通道 2. 释放RF资源 3. 重建目标Sub的数据通道 4. 分配RF资源给目标Sub Modem → 「设置首选数据Modem响应」DSD服务success Modem → 「分组数据服务状态指示」WDS服务Sub0disconnected Modem → 「分组数据服务状态指示」WDS服务Sub1connected5.3 SIM 卡热插拔处理// SIM卡热插拔的QMI消息流 // 拔出SIM1: Modem → 「SIM卡状态变更指示」UIM服务slot0card_stateABSENT → RIL[0] → UiccController → 清理Subscription → 如果SIM1是默认数据卡 → 自动切换到SIM2 // 插入SIM1: Modem → 「SIM卡状态变更指示」UIM服务slot0card_statePRESENT → RIL[0] → UiccController → 读取SIM信息 → 创建/恢复Subscription → 按用户设置恢复默认卡配置6. 实践指南6.1 QMI日志抓取# 使能 QMI 日志需 rootadb shellecho 1 /sys/module/libqmi/parameters/debug_mask# 查看 QMI 消息logcatadb logcat-bradio|grep-iqmi# QXDM 过滤推荐# Log Packets:# QMI NAS messages 相关日志分类具体 log code 见高通 QXDM 文档需 NDA# QMI WDS messages 相关日志分类具体 log code 见高通 QXDM 文档需 NDA# QMI Voice messages 相关日志分类具体 log code 见高通 QXDM 文档需 NDA# QMI UIM messages 相关日志分类具体 log code 见高通 QXDM 文档需 NDA6.2 常用调试方法# 查看 QMI 连接状态adb shellcat/sys/class/net/rmnet_data0/queues/rx-0/rps_cpus# 检查 Modem 是否正确绑定双 Subscriptionadb shell logcat-bradio|grepBind.*Subscription# 监控 DDS 切换adb logcat|grep-EDDS|preferred.*data|PhoneSwitcher# 查看 RIL 实例状态adb shell dumpsys activityservicecom.android.phone|grep-A5mInstanceId6.3 常见问题与解决问题原因分析解决方案第二张卡无法注册网络QMI NAS未正确Bind到Sub1检查qmuxd初始化日志DDS切换超时Modem RF资源释放卡住检查QMI_DSD响应可能需要Modem crash recovery来电漏接Tune-away时间不足以完成paging调整Modem tune-away参数数据连接建立失败QMI_WDS绑定了错误的Subscription验证WDS client的subscription binding7. 总结本文深入分析了RIL层的双通道通信机制和QMI协议栈QMI是高通AP-Modem通信的核心协议采用TLV编码、面向服务架构DSDS场景下通过Subscription Binding实现双QMI通道隔离RIL多实例通过instanceId确保消息正确路由关键场景包括DDS Switch、来电冲突、SIM热插拔等下一篇Modem侧RF资源调度与Tune-Away机制