02 · 蜂窝网络与卫星通信
蜂窝:
telecomm/TeleCommunicationSelectController.kt卫星:connection/controller/MobileNetworkSatelliteController.kt、satellite/SatelliteSettingDialog.kt、src/{xcddif,dcddif}/.../TelephonyUtil.kt网络:network/NetworkFlowGuideDialog.kt、network/QrCodeBitmapUtils.kt
1. 蜂窝网络(双卡运营商选择)
TeleCommunicationSelectController.kt:25-245,蜂窝网络分组在 DCD 平台整体隐藏(见 连接主页 §4)。
背景
注释 :35 说明:XCD P2.1 板子同时有两张 eSIM(卡1电信,卡2移动),这是该功能存在的硬件前提。三 Tab(:36-38,80-97):
- NETWORK_CTCC=0(中国电信)/ NETWORK_CMCC=1(中国移动)/ NETWORK_AUTO=2(智能双卡)
文案(直抄 strings.xml)
- title
micar_connection_vehicle_network_title= “优先运营商” - Tab:
micar_connection_vehicle_network_CT=“中国电信”、..._CMCC=“中国移动”、..._smart_mode=“智能双卡” - summary:CTCC=“优先使用中国电信,网络状态差时自动切换”;CMCC=“优先使用中国移动,网络状态差时自动切换”;auto=“根据网络状态动态切换运营商,提高网络服务质量”
关键行为
- 缓存
Settings.Global.VEHICLE_MOBILE_NETWORK_SELECTION(:32,185-191) onResumeInternal:99-125:读缓存→异步getCurrentMobileNet()实查→不一致则更新onSelectTabChanged:143-183:异步TelephonyUtil.setDefaultChannel(channel),失败回滚 UITelephonyUtil双卡实现在 xcd flavor(src/xcddif/.../TelephonyUtil.kt:119-172,反射TelephonyManagerEx.setUserDefaultChannel);dcd flavor 空实现(dcddif/.../:119-127,注释”dcd没有使用,为编译通过”)
通话状态保护
updateEnableState:56-68注册TelephonyCallback.PreciseCallStateListener(:204-210),CALL_STATE_OFFHOOK/RINGING 时 Tab 置灰- 禁用时点击
onDisabledTabClicked:70-78弹”SIM 切换失败”对话框(通话中禁用) - 多 TelephonyManager callback 用
ConcurrentHashMap<TelephonyManager, TelephonyCallback>(:48)一一对应——重要坑:FWK Binder 解注册只释放最后注册的,不一一对应会 callback 超限(注释 :43-47)
2. 卫星通信
能力判断
ConnectionSettingsTopFragment.java:195-197:!TelephonyUtil.isSupportSatelliteByDevice()→移除整个”移动网络”分组。TelephonyUtil(flavor 源码)反射隐藏类 android.telephony.TelephonyManagerEx 的 isSupportSatelliteByDevice()。
⚠️ 已确认 bug(对抗记录 Bug 1):dcddif 版(
:43,:47)invoke 传_defaultMgr(TelephonyManager 实例)而非telephonyMgrExDefault(TelephonyManagerEx),receiver 类型不匹配→IllegalArgumentException→catch→返回 false。DCD 平台卫星恒隐藏。xcddif 版传值正确。实际影响取决于 DCD 是否真支持卫星(需现场验证)。
入口与跳转
MobileNetworkSatelliteController.kt:22-93:
- XML 直接写
<intent android:action="android.settings.SATELLITE_COMMUNICATE"/>(connection_settings_fragment.xml:140),点击/点图标都拉起SatelliteSettingsActivity(manifest:101,109)
⚠️ 已确认问题(对抗记录 Bug 3):manifest
:109,113同时注册SATELLITE_COMMUNICATE(正确)和SATELLITE_COMMUNITE(拼写错误,少 C),推测兼容调用方笔误。
- 文案(直抄):title=“卫星通信”、summary=“可通过天通卫星接打电话”、status_on=“已开启”、status_off=“已关闭”
- 右侧文案:监听广播
com.android.app.action.SATELLITE_STATE_CHANGE(:36,40-53),extrais_enable,异步查isSatelliteEnable(SLOT_DEFAULT)(:79-92)
卫星弹窗流程
SatelliteSettingsActivity.kt:10-23 加载 SatelliteSettingDialog。三态:CONNECTING(0x1)/CONNECTED(0x2)/DISCONNECTED(0x3)(:311-314)。
- 进入:
isSatelliteEnable()决定初态(:282-283)+ registerTelephonyCallback(:285) - 点”开启”:异步
setSatelliteEnable(ctx,true)→CONNECTING+旋转动画+MSG_TIME_OUT_CHECK延时 TIME_TO_WAIT=120s(:190,317);超时未 STATE_IN_SERVICE→toast 失败+finish(:54-65) - 点”关闭”:
setSatelliteEnable(ctx,false)→DISCONNECTED→finish(:246-258) - 点”去拨号”:发
mi.car.intent.action.SELECT_SATELLITE,包名com.android.car.dialer(:319-320,260-268) ServiceState.STATE_IN_SERVICE回调→CONNECTED(:104-119)
卫星能力绑在 SIM slot 1:
SLOT_N801=1(:311 注释”n801默认卫星卡”)。registerTelephonyCallback(:123)反射SubscriptionManager.getSubscriptionId(slotId)拿 subId,失败用 -1 fallback(:131-136)。
sequenceDiagram participant U as 用户 participant Ctl as MobileNetworkSatelliteController participant Dlg as SatelliteSettingDialog participant Tu as TelephonyUtil(反射) participant TM as TelephonyManager(subId) participant FWK as Modem U->>Ctl: 点击"卫星通信" Ctl->>Dlg: intent SATELLITE_COMMUNICATE Dlg->>Tu: isSatelliteEnable() Dlg->>TM: registerTelephonyCallback(subId=getSubscriptionId(SLOT_N801=1)) U->>Dlg: 点"开启" Dlg->>Tu: setSatelliteEnable(ctx,true) Dlg->>Dlg: CONNECTING + 120s 超时 FWK->>TM: STATE_IN_SERVICE TM->>Dlg: onServiceStateChanged→CONNECTED U->>Dlg: 点"去拨号" Dlg->>U: 启动 com.android.car.dialer
⚠️ 已确认 bug(对抗记录 Bug 2):
:137注册在mTelephonyManager.createForSubscriptionId(finalSubId)返回的新实例,:275解注册在原mTelephonyManager上——实例不一致,callback 可能泄漏/解注册失败。
3. 网络引导与二维码
NetworkFlowGuideDialog(network/NetworkFlowGuideDialog.kt:18-101)
“流量赠送用户领取引导弹窗”,继承 BaseConflictDialogActivity。
- 接收 intent extra
content_data(JSON)→ContentData(popTitle, popContent, type, value)(:54-56,95-100) - 校验
type=="qr"才显示(:21,59-65),否则 finish QrCodeBitmapUtils.createQRCodeWithLogo(url,size,size,R.drawable.ic_network_guide,logoSize,logoSize)生成中间带 logo 二维码(:75-90),ViewOutlineProvider 圆角onPause直接 finish(:48-51)——一次性弹窗,被动接收(拉起方不在本仓)
QrCodeBitmapUtils(network/QrCodeBitmapUtils.kt:19-134)
通用二维码工具,zxing QRCodeWriter,纠错 M、utf-8、margin 0、deleteWhite 去白边(:68-75,120-133);createQRCodeWithLogo 中心贴 logo(:42-47)。被 NetworkFlowGuideDialog 与 HotspotQrCodeUtils 共用。
4. 平台差异与坑(DCD vs XCD)
- DCD 平台 =
ro.board.platform == "msmnile"(DeviceUtil.java:226-228) - DCD 隐藏蜂窝网络(双卡选择);XCD P2.1 双 eSIM 才显示
TelephonyUtilflavor:xcd 双卡实实现 / dcd 空实现仅占位编译- ⚠️ dcddif
isSupportSatelliteByDevice反射 receiver bug(见 §2) - ⚠️ manifest SATELLITE 双拼写(COMMUNICATE+COMMUNITE)
- ⚠️ SatelliteSettingDialog 注册/解注册 TelephonyManager 实例不一致
- 卫星连接最长等 120s,超时 toast 失败+finish,用户需重新点击
- 卫星能力绑 SIM slot 1(SLOT_N801=1)
关键调用点速查
| 关注点 | 位置 |
|---|---|
| 双卡 Tab 切换 | TeleCommunicationSelectController.kt:143-183 |
| setDefaultChannel(xcd) | src/xcddif/…/TelephonyUtil.kt:119-172 |
| 通话中禁用 | TeleCommunicationSelectController.kt:56-68,204-210 |
| 卫星入口状态刷新 | MobileNetworkSatelliteController.kt:36-53 |
| 卫星开关弹窗 | SatelliteSettingDialog.kt:190,246-258 |
| 卫星 120s 超时 | SatelliteSettingDialog.kt:54-65,317 |
| 卫星拨号 | SatelliteSettingDialog.kt:260-268,319-320 |
| isSupportSatelliteByDevice | src/{xcddif,dcddif}/…/TelephonyUtil.kt:35-63 |
| 网络引导 QR | NetworkFlowGuideDialog.kt:75-90 |
附录 A · 平台契约实证与对接人(N801PROB-138847, 2026-08-31)
「受理即 true」契约断点(源码实锤,/home/zbc/pangu/yu7):
- 受理层
miui/frameworks/telephony/common/telephony/auto/com/android/phone/data/MultiInternetRouteController.java:392setUserDefaultChannel:先写 Settings.Global 记偏好 → 调SmartDataChannelController.setApnDefaultChannel(...)丢弃其返回值 → 无条件return true(仅非法 channel / 同值重复才 false)。 - 执行层
.../data/SmartDataChannelController.java:1710setApnDefaultChannel:目标通道 rat 非 LTE/NR 时打setApnDefaultChannel ignore due to rat=X !并return false——false 已存在,断点在受理层没接住。 - API
common/base/java/android/telephony/TelephonyManagerEx.java:117,javadoc 仅 “success or not” 未定义受理/完成语义。 - 后果:调用方(车机设置优先运营商 Tab)按「true=成功」持久化并保持选中态,单卡/无服务环境下用户看到「选了移动但永远电信」零反馈。
- 修复落点:受理层透传执行层返回值,或对无卡/无服务通道直接 false;执行层 rat=0 防护不动(强切=整车断网)。
- 证据包:jira-data/N801PROB-138847/analysis/platform-evidence-package.md。
平台对接人(用户亲述,confirmed 2026-08-31):庄员 zhuangyuan@xiaomi.com——TelephonyManagerEx / SmartDataChannelController / 多网数据通道切换类问题直接转他。