04 · 平台侧受理与执行(深入)
平台源码:
/home/zbc/pangu/yu7/miui/frameworks/telephony/。 本篇回答一个问题:点了「中国移动」之后,平台到底干了什么?为什么”成功了”网却没切? 平台 telephony 对接人:庄员 zhuangyuan@xiaomi.com(2026-08-31 亲述确认)。
1. 调用链全景
sequenceDiagram autonumber participant APP as MiCarSettings<br/>TelephonyUtil(反射) participant EX as TelephonyManagerEx<br/>(抽象类 :117-118) participant IMPL as TelephonyManagerImpl<br/>:736-758 participant AIDL as IAutoTelephony(binder) participant APIM as AutoPhoneInterfaceManager<br/>(radio 进程) participant MIRC as MultiInternetRouteController<br/>受理层 participant SDCC as SmartDataChannelController<br/>执行层 APP->>EX: setUserDefaultChannel(1) EX->>IMPL: (多实现之一) IMPL->>IMPL: getAutoTelephony() IMPL->>AIDL: manager.setUserDefaultChannel(1)<br/>异常→catch 返回 false(:742-745) AIDL->>APIM: binder 跨进程 APIM->>MIRC: setUserDefaultChannel(1) MIRC->>MIRC: isValidChannel? (:394)<br/>否 → return false MIRC->>MIRC: ==当前值? (:398)<br/>是 → return false("already set") MIRC->>MIRC: 写 Settings.Global[HMI_DATA_SIM_APN]=1 (:402) alt channel == 2(智能双卡 WISDOM) MIRC-->>APP: return true(不触发切换,:405-406) else channel 0/1 MIRC->>SDCC: setApnDefaultChannel(MULTI_INTERNET_2, 1, REASON_HMI_SET) SDCC->>SDCC: phoneId 无效→false<br/>rat 非 LTE/NR→false("ignore due to rat=0 !")<br/>否则 updateDataChannel 真切(:1709-1725) SDCC--xMIRC: 返回值被丢弃! MIRC-->>APP: **无条件 return true**(:409) end
2. 关键文件与行号
| 环节 | 文件:行号 | 要点 |
|---|---|---|
| 抽象 API | telephony/common/base/java/android/telephony/TelephonyManagerEx.java:117-118 | setUserDefaultChannel/getUserDefaultChannel 抽象方法 |
| 实现转发 | .../TelephonyManagerImpl.java:736-758 | 经 getAutoTelephony() 拿 binder,异常兜底 false/-1 |
| binder 接口 | .../base/java/android/telephony/IAutoTelephony.aidl | 跨进程接口 |
| radio 侧入口 | .../telephony/auto/com/android/phone/AutoPhoneInterfaceManager.java | aidl 实现,转调控制器 |
| 受理层 | .../auto/com/android/phone/data/MultiInternetRouteController.java:388-410 | 校验→写 key→转发→恒 true |
| 执行层 | .../auto/com/android/phone/data/SmartDataChannelController.java:1709-1725 | rat 校验→updateDataChannel |
| key 常量 | MultiInternetRouteController.java:44-45 | DEFAULT_DATA_SIM_APN / HMI_DATA_SIM_APN |
3. 受理层:MultiInternetRouteController.setUserDefaultChannel(:388-410)
public boolean setUserDefaultChannel(int channel) {
if (!isValidChannel(channel)) return false; // 非法值才 false
if (getUserDefaultChannel() == channel) return false; // 重复设置才 false("already set")
Settings.Global.putInt(cr, getHMIDefaultChannelSettingName(), channel); // 先记偏好
if (SmartDataChannelController.getInstance() != null) {
if (channel == WISDOM_DATA_CHANNEL) {
return true; // 智能双卡:不触发即时切换
}
SmartDataChannelController.getInstance()
.setApnDefaultChannel(MULTI_INTERNET_2, channel, REASON_HMI_SET);
// ↑↑↑ 返回值没!人!接!
}
return true; // 恒 true(受理语义)
}读侧(:416-418)就是把 HMI_DATA_SIM_APN 读出来,默认 WISDOM_DATA_CHANNEL(2):
public int getUserDefaultChannel() {
return Settings.Global.getInt(cr, getHMIDefaultChannelSettingName(), WISDOM_DATA_CHANNEL);
}4. 执行层:SmartDataChannelController.setApnDefaultChannel(:1709-1725)
public boolean setApnDefaultChannel(MultiInternetEnum item, int phoneId, int reason) {
if (!isValidatePhoneId(phoneId)) return false;
int rat = getCurRatByPhoneId(phoneId); // 取该卡当前数据网络制式
if (!isLteNrNwType(rat)) { // 必须是 LTE/NR(在网)
localLog("setApnDefaultChannel ignore due to rat=" + rat + " !");
return false; // 防护:无服务卡不切
}
updateDataChannel(item, phoneId, reason, isNowDsda() ? false : true);
return true;
}rat=0(无服务)防护是正确行为——强行把数据通道切到一张无服务的卡=整车断网。 问题不在防护本身,而在防护结果(false)没有回传给调用方。
5. 受理/执行分离:本模块最重要的设计事实
flowchart LR subgraph 受理["受理层(同步返回)"] A1[校验合法性] --> A2[写 HMI_DATA_SIM_APN] A2 --> A3[return true] end subgraph 执行["执行层(尽力而为)"] B1[rat 校验] -->|通过| B2[updateDataChannel<br/>真正切路由] B1 -->|rat=0 等| B3["localLog ignore<br/>return false → 被丢弃"] end 受理 --> 执行 A3 -. "UI 认为切换成功" .-> U["App Tab 选中保持"] B3 -. "实际路由没动" .-> N["网络仍在原卡<br/>右侧面板不变"]
契约缺陷的两层改进方向(N801PROB-138847 复盘结论):
| 层 | 现状 | 改进项 |
|---|---|---|
| 平台 | setApnDefaultChannel 的 false 没人接,无失败回调、无可用性查询 API | 执行失败回传(改 false 或回调) |
| App | 三 Tab 硬编码,无在位卡门控,点击不可达偏好零反馈 | 按活跃 sub 数门控 Tab + 失败提示 |
6. 智能双卡(channel=2)的语义
- App 选「智能双卡」→ 平台只写
HMI_DATA_SIM_APN=2,不做即时切换(:405-406) - 真正的自动倒换由平台策略引擎驱动:
MultiInternetPolicyEvent(MODE_LOW_COST / MODE_CONCURRENCY 等模式,:230-250)+SmartDataChannelController监听两张卡的 rat/信号质量,满足条件时自动updateDataChannel - 两套云端通道偏好写在
DEFAULT_DATA_SIM_APN{apnNumber}系列 key(:266,:273-275) - 所以「智能双卡」模式下 UI 显示选中态和当前实际数据通道本来就解耦——右侧面板 显示哪张卡,取决于平台当前把路由放在哪张卡
7. DDS 与路由的关系(排障判据)
执行层真切了的话,dumpsys 里应该看到:
defaultDataSubId/activeDataSubId迁移到目标 subcurrent route map中MULTI_INTERNET_2=<目标 phoneId>
138847 案里这两项全程没动(defaultDataSubId=1 恒为电信、MULTI_INTERNET_2=0),
是”执行从未发生”的裁决性证据。排查命令见 06 篇速查卡。