Phone 对象与 RIL 通信

0 阅读3分钟

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 号或主动指示来反馈结果。