一、系统架构与基础概念
1. Telephony 整体架构
- 三层结构:Java Framework (Telephony) → HAL (HIDL/AIDL) → Modem RIL
- 关键角色:
Phone- 逻辑手机对象RIL(Radio Interface Layer) - 与 Modem 通信的中介ServiceStateTracker- 网络状态跟踪PhoneSwitcher- 多卡协调DataNetworkController- 数据网络管理
2. 多卡(DSDS)管理
- SubId vs PhoneId 的映射关系
- 默认数据卡、语音卡、彩信卡 的选择与切换
- MultiSimSettingController 的职责
3. Subscription 管理
SubscriptionManagerService的核心职责- 卡槽状态变化处理
- 默认设置的持久化
二、常见流程深度题目
问题 1:来电显示流程(Call Indication)
关键点:
- Modem 上报
RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED RadioIndication.callStateChanged()接收RIL.processIndication()处理Phone.notifyCallStateChanged()通知各个模块- 多卡设备如何区分来电是来自哪张卡
可能的深入问题:
- 如何处理多卡同时有来电的情况?
- 来电通知的优先级如何确定?
- 振铃音如何选择(哪张卡的铃声)?
代码关键路径:
RadioIndication.callStateChanged()
→ RIL.processIndication()
→ Phone.notifyCallStateChanged()
→ PhoneNotifier.notifyCallStateChanged()
→ TelephonyRegistryManager.notifyCallStateChanged()
问题 2:发送短信流程(Send SMS)
关键点:
- 应用调用
SmsManager.sendTextMessage(subId, ...)指定副卡 SmsSender获取对应副卡的Phone对象GsmSMSDispatcher或CdmaSMSDispatcher处理- 通过 RIL 发送给 Modem
- Modem 返回结果,通过 PendingIntent 回调
可能的深入问题:
- 如何确保副卡彩信也能正确发送?
- 短信失败重试机制?
- 如何处理运营商特定的发送参数?
代码关键路径:
SmsManager.sendTextMessage(subId, ...)
→ SmsSender.sendMessage()
→ GsmSMSDispatcher.sendMessage()
→ RIL.sendSMS()
→ RadioResponse.sendSmsResponse()
→ PendingIntent callback
问题 3:副卡彩信收发流程(Secondary SIM MMS)
关键点:
- 发送:指定 subId → MmsManager → MmsServiceBroker → RIL → MMSC
- 接收:WAP Push → 识别 subId → 下载 MMS → 存储到对应卡的数据库
- 关键: 多卡时数据连接的切换管理
- 权限检查: SEND_SMS/RECEIVE_MMS 权限
可能的深入问题:
- MMS 如何在多卡设备上优先级选择?
- MMS 数据连接与默认数据卡冲突如何处理?
- 如何从 WAP Push 的 slotIndex 映射到 subId?
代码关键路径:
MmsManager.sendMultimediaMessage(subId, ...)
→ MmsServiceBroker.sendMessage()
→ CarrierMessagingService.onSendMms()
→ 建立 MMS 数据连接
→ 通过 HTTP 发送 PDU 到 MMSC
问题 4:网络状态变化流程(Network State Change)
关键点:
- Modem 上报网络注册状态变化
RadioIndication.networkStateChanged()ServiceStateTracker更新网络状态Phone.notifyServiceStateChanged()- 触发 UI 更新(信号强度、网络制式等)
可能的深入问题:
- 如何区分 2G/3G/4G/5G 网络制式?
- 漫游状态如何判断和显示?
- 多卡时网络状态的独立性?
问题 5:数据连接建立流程(Data Network Setup)
关键点:
- 应用请求数据连接(Internet)
ConnectivityManager向 Telephony 请求DataNetworkController选择合适的 APNTelephonyNetworkFactory创建DataNetwork- 通过 RIL 向 Modem 发送
setupDataCall() - Modem 建立 PDP Context,返回网络参数
- 系统更新 LinkProperties,通知应用
可能的深入问题:
- 如何选择最合适的 APN(多个 APN 配置时)?
- 副卡数据连接建立时是否需要切换默认数据卡?
- 数据连接失败的重试策略?
- 4G 转 5G 的数据连接是否需要重新建立?
代码关键路径:
ConnectivityManager.requestNetwork()
→ TelephonyNetworkFactory.requestNetwork()
→ DataNetworkController.createDataNetwork()
→ DataProfileManager.selectDataProfile()
→ RIL.setupDataCall()
→ RadioResponse.setupDataCallResponse()
→ DataNetwork.onSetupDataCallSuccess()
问题 6:PhoneNotifier 与状态通知(PhoneNotifier & State Notification)
关键点:
- 为什么需要 PhoneNotifier? - 解耦 Phone 逻辑与系统通知
- DefaultPhoneNotifier 实现
- TelephonyRegistryManager 负责广播
- 监听者模式 - 各模块注册 Registrant 接收状态变化
可能的深入问题:
- 如何避免通知风暴(频繁更新状态导致的性能问题)?
- 通知的线程安全性如何保证?
- 多卡时如何避免通知混乱?
问题 7:RIL 异步处理模型(RIL Async Model)
关键点:
- 命令队列 -
RequestInfo链表管理待发送的命令 - Token 机制 - 每个请求有唯一 token,响应时通过 token 匹配
- 异步响应 -
RIL_onRequestComplete() - Wake Lock - 防止长时间请求时系统睡眠
可能的深入问题:
- 如何处理 Modem 响应超时?
- Modem 发生 Crash 时如何恢复?
- 队列中有多个请求时,哪个优先执行?
三、数据恢复与容错机制
DataStallRecoveryManager
- 数据连接卡死(Data Stall)的检测
- 4 级递进恢复机制:
GET_DATA_CALL_LISTCLEANUPRADIO_RESTARTRESET_MODEM
RescueParty
- 系统级容错
- 当频繁崩溃时,尝试重置设置、清除数据、工厂恢复
四、多卡专有流程
问题 8:多卡数据切换流程
当用户切换默认数据卡时:
- 系统更新
Settings.Global.MULTI_SIM_DATA_CALL_SUBSCRIPTION MultiSimSettingController监听到变化- 释放旧数据卡的数据连接
- 在新数据卡上重建数据连接
- 通知 ConnectivityService 切换
可能的深入问题:
- 切换过程中如何避免网络断连?
- 应用正在传输数据时切换如何处理?
- 两张卡都是 4G 时,切换延迟多长时间可接受?
五、面试常见考点总结表
| 考点 | 难度 | 关键词 |
|---|---|---|
| Phone 对象与 RIL 通信 | ⭐⭐ | Token、异步、RequestInfo |
| 来电显示与通知 | ⭐⭐⭐ | RadioIndication、PhoneNotifier、Registrant |
| 短信发送与回调 | ⭐⭐⭐ | SubId、PendingIntent、RIL |
| 副卡彩信 | ⭐⭐⭐⭐ | MMS 网络切换、MMSC、运营商服务 |
| 数据网络建立 | ⭐⭐⭐⭐ | APN 选择、PDP Context、LinkProperties |
| 多卡数据切换 | ⭐⭐⭐⭐⭐ | PhoneSwitcher、优先级、并发处理 |
| HIDL/AIDL 迁移 | ⭐⭐⭐ | 兼容层、版本管理 |
| 数据恢复机制 | ⭐⭐⭐⭐ | DataStall、Recovery Actions、RescueParty |
六、面试高频问题预测
-
"解释一下来电时系统的调用链" → 从 RIL 到 UI 更新的完整路径
-
"多卡设备副卡发送短信如何确保发送到正确的卡?" → SubId 的作用、RIL 的处理
-
"为什么需要 PhoneNotifier?直接让 Phone 通知不行吗?" → 解耦、系统架构分层
-
"数据连接卡死(Data Stall)了如何恢复?" → DataStallRecoveryManager 的 4 级机制
-
"Modem 向系统上报的无线指示(Unsolicited Indication)有多少种?" → RadioIndication 中的各个回调方法
-
"HIDL 和 AIDL 在 RIL 中的区别是什么?" → 接口定义方式、版本管理、兼容层
-
"多卡时默认数据卡与 MMS 数据连接如何协调?" → PhoneSwitcher 的作用、网络请求优先级
-
"RIL 中如何确保异步命令与响应一一对应?" → Token 机制、RequestInfo 队列
七、学习建议
- 从简到繁:先掌握单卡流程,再学多卡协调
- 代码阅读顺序:
- 先读 Java Framework 层的接口
- 再看 RIL 的具体实现
- 最后理解 HAL 的异步通信
- 关键文件要深入:
RIL.java- 核心枢纽Phone.java- 逻辑手机PhoneSwitcher.java- 多卡协调ServiceStateTracker.java- 网络状态DataNetworkController.java- 数据连接
祝您面试顺利!如果需要深入讲解某个具体流程,我可以为您查看对应的代码并详细解析。