1️⃣ 架构概览
┌─────────────────────────────────────┐
│ Apps & Framework │
│ (Telecom, InCallUI, etc.) │
└──────────────────┬──────────────────┘
│
┌──────────────────▼──────────────────┐
│ Phone Object (GsmCdmaPhone) │
│ - Controls voice/data/messaging │
│ - Holds mCi reference │
└──────────────────┬──────────────────┘
│ mCi (CommandsInterface)
┌──────────────────▼──────────────────┐
│ RIL (implements CI) │
│ - Manages modem commands │
│ - Handles responses/indications │
└──────────────────┬──────────────────┘
│ HIDL/AIDL
┌──────────────────▼──────────────────┐
│ Radio HAL (Hardware Layer) │
│ - HIDL 1.0-1.6 / AIDL │
└──────────────────┬──────────────────┘
│ Socket IPC
┌──────────────────▼──────────────────┐
│ RIL Daemon (rild) │
└──────────────────┬──────────────────┘
│ AT Commands
┌──────────────────▼──────────────────┐
│ Modem (Hardware) │
└─────────────────────────────────────┘
2️⃣ Phone 对象结构
Phone 类的核心属性
Phone (基类)
├── mCi (CommandsInterface) ◄─── 关键!用于与 RIL 通信
├── mPhoneId ◄─── 物理 Modem 索引(0/1/2...)
├── mNotifier ◄─── 通知系统状态变化
├── mContext ◄─── 应用上下文
└── GsmCdmaPhone (具体实现)
├── mCT ◄─── GsmCdmaCallTracker(管理通话)
├── mSST ◄─── ServiceStateTracker(网络状态)
├── mImsPhone ◄─── IMS 电话实现
└── mUiccController ◄─--- UICC/SIM 卡管理
现在让我继续详细讲解:
3️⃣ 具体通信流程示例:拨打电话(Dial Call)
┌──────────────────────────────────────────────────────────────┐
│ 1. 应用层发起拨号 │
│ → Intent ACTION_CALL │
└─────────────────────┬────────────────────────────────────────┘
│
┌─────────────────────▼────────────────────────────────────────┐
│ 2. Telecom 转调 Phone.dial() │
│ GsmCdmaPhone.dial(String dialString, DialArgs args) │
└─────────────────────┬────────────────────────────────────────┘
│
┌─────────────────────▼────────────────────────────────────────┐
│ 3. Phone 调用 CallTracker 处理 MMI/CLIR │
│ → GsmCdmaCallTracker.dialGsm() │
│ → 创建 GsmCdmaConnection 对象 │
└─────────────────────┬────────────────────────────────────────┘
│
┌─────────────────────▼────────────────────────────────────────┐
│ 4. CallTracker 调用 RIL dial() 方法 │
│ mCi.dial(address, isEmergency, emergencyNumber, │
│ clirMode, uusInfo, Message response) │
│ │
│ 关键代码位置: │
│ GsmCdmaCallTracker.java:368-370 │
└─────────────────────┬────────────────────────────────────────┘
│
┌─────────────────────▼────────────────────────────────────────┐
│ 5. RIL 处理请求 │
│ → 序列化参数为 Parcel │
│ → 通过 HIDL/AIDL 发送给 Radio HAL │
│ → 等待响应(异步) │
│ │
│ 核心流程: │
│ RIL.java: │
│ - processRequests(Parcel p) │
│ - 维护 RILRequest 队列,关联 serial 号 │
└─────────────────────┬────────────────────────────────────────┘
│
┌─────────────────────▼────────────────────────────────────────┐
│ 6. Modem 处理 │
│ → 发送 AT+CLIR/DIAL 命令 │
│ → 触发用户界面拨号 │
└─────────────────────┬────────────────────────────────────────┘
│
┌─────────────┴─────────────────┐
│ │
响应路径 指示路径
│ │
┌───────▼────────────┐ ┌──────────▼──────────┐
│ 7a. Solicited │ │ 7b. Unsolicited │
│ Response │ │ Indication │
│ (DIAL_COMPLETE) │ │ (CALL_STATE_ │
│ │ │ CHANGED) │
└────────┬───────────┘ └────────┬────────────┘
│ │
┌────────▼───────────┐ ┌────────▼────────────┐
│ 8. RIL 回调 │ │ 8. Indication │
│ processResponse() │ │ Handler │
│ 匹配 serial 号 │ │ (接收主动上报) │
└────────┬───────────┘ └────────┬────────────┘
│ │
┌────────▼───────────────────────────▼─────────┐
│ 9. Phone/CallTracker 更新 │
│ → handleDialResponse() │
│ → pollCallsWhenSafe() │
│ → updatePhoneState() │
└────────┬───────────────────────────────────┬─┘
│ │
▼ ▼
┌─────────────────────┐ ┌────────────────────┐
│ 10. 通知上层 │ │ 10. 通知上层 │
│ (Telecom/InCallUI) │ │ (Telecom/InCallUI) │
└─────────────────────┘ └────────────────────┘
4️⃣ Phone 与 RIL 通信的关键方法
Voice 相关(来自 CallTracker)
// 拨号
mCi.dial(address, isEmergency, emergencyNumber,
clirMode, uusInfo, onComplete);
// 接听
mCi.acceptCall(onComplete);
// 挂断
mCi.hangupConnection(gsmConnection, onComplete);
mCi.hangupForegroundResumeBackground(onComplete);
// 获取通话列表
mCi.getCurrentCalls(onComplete);
// 切换前景/背景通话
mCi.switchWaitingOrHoldingAndActive(onComplete);
// USSD
mCi.sendUSSD(ussdString, onComplete);
Network 相关(来自 ServiceStateTracker)
// 获取网络注册状态
mCi.getVoiceRegistrationState(onComplete);
mCi.getDataRegistrationState(onComplete);
// 获取操作员信息
mCi.getOperator(onComplete);
// 信号强度
mCi.getSignalStrength(onComplete);
// 小区信息
mCi.getCellInfoList(onComplete);
// 网络扫描
mCi.startNetworkScan(request, onComplete);
Data 相关(来自 DataConnection)
// 建立数据连接
mCi.setupDataCall(accessNetworkType, dataProfile,
isRoaming, onComplete);
// 断开数据连接
mCi.deactivateDataCall(cid, reasonRadioShutdown, onComplete);
// 获取数据连接列表
mCi.getDataCallList(onComplete);
SIM/Messaging 相关
// 发送短信
mCi.sendSMS(smscPdu, pdu, onComplete);
// SIM 卡相关
mCi.getIccCardStatus(onComplete);
mCi.setUiccSubscription(selectUiccSub, onComplete);
// STK
mCi.sendEnvelopeWithStatus(contents, onComplete);
5️⃣ RIL 与 Phone 的注册关系
Phone 向 RIL 注册以接收主动上报的事件:
// 在 Phone 构造函数中
mCi.setOnCallRing(this, EVENT_CALL_RING, null);
mCi.registerForSrvccStateChanged(this, EVENT_SRVCC_STATE_CHANGED, null);
mCi.registerForIccRefresh(this, EVENT_ICC_CHANGED, null);
// CallManager 注册通话事件
mCi.registerForCallStateChanged(handler, EVENT_CALL_STATE_CHANGED, null);
mCi.registerForRingbackTone(handler, EVENT_RINGBACK_TONE, null);
// ServiceStateTracker 注册网络事件
mCi.registerForNetworkStateChanged(this, EVENT_NETWORK_STATE_CHANGED, null);
mCi.registerForVoiceRadioTechChanged(this, EVENT_VOICE_RADIO_TECH_CHANGED, null);
6️⃣ 异步请求-响应机制
Phone/CallTracker RIL Modem
│ │ │
├──────── dial() ─────────►│ │
│ (Message) + │ │
│ serial=123 │ │
│ ├──── AT+CLIR ────────►│
│ │ │
│ │◄──── +CONNECT ──────│
│ │ │
│◄──── processResponse() ──│ │
│ (serial=123 matched) │ │
│ (Message.sendToTarget())│ │
│ │ │
├─── handleMessage() ─────┐│ │
│ EVENT_DIAL_DONE ││ │
│◄────────────────────────┘│ │
关键特性:
- Serial Number: 每个请求都有唯一的 serial 号,用于匹配响应
- Message Handler: 异步回调,避免阻塞
- RILRequest Queue: RIL 内部维护待处理的请求队列
7️⃣ 主动指示(Unsolicited Indication)流程
Modem RIL HAL RIL Phone
│ │ │ │
├─── CALL_STATE_ ──►│ │ │
│ CHANGED │ │ │
│ (unsolicited) │ │ │
│ ├──► onCallStateChanged() ────────────────►│
│ │ (Indication Handler) │
│ │ │ │
│ │ ├─ handleMessage() │
│ │ │ EVENT_CALL_STATE_│
│ │ │ CHANGED │
│ │ │ │
│ │ ├─ getCurrentCalls()─────►│
│ │ │ (pollCalls) │
8️⃣ Phone 对象生命周期
// 1. 创建阶段
Phone phone = TelephonyComponentFactory.getInstance()
.makePhone(context, commandsInterface,
phoneNotifier, phoneId, ...);
// 2. 初始化 - 向 RIL 注册回调
// 在 Phone 构造函数中自动完成
// 3. 运行阶段 - 持续通信
phone.dial(number, args);
phone.acceptCall();
phone.sendSMS(pdu, smscPdu);
// 4. 销毁阶段
phone.dispose();
9️⃣ 多 Modem 场景
// 在 PhoneFactory 中
int numPhones = TelephonyManager.getDefault().getActiveModemCount();
Phone[] sPhones = new Phone[numPhones];
RIL[] sCommandsInterfaces = new RIL[numPhones];
for (int i = 0; i < numPhones; i++) {
// 为每个 Modem 创建独立的 RIL 和 Phone
sCommandsInterfaces[i] = new RIL(context, raf, cdmaSubscription, i);
sPhones[i] = createPhone(context, i); // mPhoneId = i
}
// Phone 通过 mPhoneId 区分 Modem 实例
🔟 Phone-RIL 通信的关键特点
| 特点 | 说明 |
|---|---|
| 异步 | 所有请求都是异步的,通过 Message 回调 |
| Serial 匹配 | 每个请求-响应对有唯一的 serial 号 |
| 主动指示 | RIL 可主动上报事件(如来电铃声) |
| 单一 CI | 一个 Phone 只有一个 CommandsInterface 实例 |
| 多 Phone | 多 Modem 时,多个 Phone 实例,各自有独立 RIL |
| Wake Lock | 重要操作会持有 wake lock,防止睡眠 |
| 超时控制 | 请求有超时时间,防止永久挂起 |
| Error 处理 | 响应包含 error code,通过 AsyncResult 返回 |
这就是 Phone 与 RIL 通信的完整架构和流程。核心就是通过 CommandsInterface 接口,Phone 以异步方式向 RIL 发送命令,RIL 通过匹配 serial 号或主动指示来反馈结果。