我来为你详细总结 Request(下发) 和 Indication(上报) 的完整流程。
🔄 完整流程总览
scss
┌─────────────────────────────────────────────────────────────────────────────────────┐
│ Android Telephony 架构 │
├─────────────────────────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────────────────────────────────────────────────────────────────┐ │
│ │ FRAMEWORK 层 (Java) │ │
│ │ frameworks/opt/telephony/src/... │ │
│ │ │ │
│ │ ┌──────────┐ ┌──────────┐ ┌─────────────────────────────────────┐ │ │
│ │ │ Phone │────►│ RIL │────►│ RadioModemProxy/ RadioDataProxy │ │ │
│ │ │ │◄────│ │◄────│ RadioVoiceProxy/ ... │ │ │
│ │ └──────────┘ └────┬─────┘ └─────────────────────────────────────┘ │ │
│ │ ▲ │ │ │ │
│ │ │ │ │ │ │
│ │ Registrant Response HIDL IPC │ │
│ │ notifyRegistrants() processResponse() (HIDL Proxy) │ │
│ │ ▲ │ │ │
│ │ │ │ │ │ │
│ │ └───────────────┴─────────────────────────┘ │ │
│ │ │ │ │
│ │ ┌────────────────────────────────────────────────────────────────────────┐│ │
│ │ │ Response/Indication (Callback) ││ │
│ │ │ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────────┐ ││ │
│ │ │ │ RadioResponse │ │RadioIndication │ │ ModemIndication │ ││ │
│ │ │ │ extends Stub │ │extends Stub │ │ extends Stub │ ││ │
│ │ │ └─────────────────┘ └─────────────────┘ └─────────────────────┘ ││ │
│ │ └────────────────────────────────────────────────────────────────────────┘│ │
│ └─────────────────────────────────────────────────────────────────────────────┘ │
│ │ │
│ │ HIDL/AIDL IPC (Binder) │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────────────────────────┐ │
│ │ HAL 层 (C++) │ │
│ │ hardware/ril/libril/... │ │
│ │ │ │
│ │ ┌─────────────────────────────────────────────────────────────────────────┐│ │
│ │ │ RadioImpl (struct) ││ │
│ │ │ struct RadioImpl : public V1_1::IRadio ││ │
│ │ │ ││ │
│ │ │ ┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐ ││ │
│ │ │ │ Request 处理 │ │ Response 回调 │ │ Indication 回调 │ ││ │
│ │ │ │ │ │ │ │ │ ││ │
│ │ │ │ getIccCardStatus │ │getIccCardStatus │ │ radioStateChanged│ ││ │
│ │ │ │ setRadioPower │ │Response │ │ callStateChanged │ ││ │
│ │ │ │ dial │ │ │ │ networkStateCh...│ ││ │
│ │ │ │ setupDataCall │ │ mRadioResponse-> │ │ mRadioIndication─│─►┼┼──┤
│ │ │ │ │ │ getIccCardStat..│ │ ->radioState... │ ││ │
│ │ │ └────────┬─────────┘ └──────────────────┘ └──────────────────┘ ││ │
│ │ │ │ ││ │
│ │ │ │ dispatchVoid/dispatchInts ││ │
│ │ │ ▼ ││ │
│ │ │ ┌─────────────────────────────────────────────────────────────────┐ ││ │
│ │ │ │ s_vendorFunctions->onRequest() │ ││ │
│ │ │ │ (函数指针指向厂商 RIL 实现) │ ││ │
│ │ │ └─────────────────────────────────────────────────────────────────┘ ││ │
│ │ └─────────────────────────────────────────────────────────────────────────┘│ │
│ │ │ │ │
│ │ │ 函数指针调用 │ │
│ │ ▼ │ │
│ │ ┌─────────────────────────────────────────────────────────────────────────┐│ │
│ │ │ Vendor RIL (厂商实现) ││ │
│ │ │ hardware/ril/reference-ril/reference-ril.c ││ │
│ │ │ ││ │
│ │ │ ┌─────────────────────────────────────────────────────────────────┐ ││ │
│ │ │ │ static const RIL_RadioFunctions s_callbacks = { │ ││ │
│ │ │ │ RIL_VERSION, │ ││ │
│ │ │ │ onRequest, ◄────── 处理所有 Request │ ││ │
│ │ │ │ currentState, │ ││ │
│ │ │ │ onSupports, │ ││ │
│ │ │ │ onCancel, │ ││ │
│ │ │ │ getVersion │ ││ │
│ │ │ │ }; │ ││ │
│ │ │ │ │ ││ │
│ │ │ │ static void onRequest(int request, void *data, │ ││ │
│ │ │ │ size_t datalen, RIL_Token t) { │ ││ │
│ │ │ │ switch (request) { │ ││ │
│ │ │ │ case RIL_REQUEST_GET_SIM_STATUS: │ ││ │
│ │ │ │ getSIMStatus(t); │ ││ │
│ │ │ │ break; │ ││ │
│ │ │ │ case RIL_REQUEST_RADIO_POWER: │ ││ │
│ │ │ │ setRadioPower(data, datalen, t); │ ││ │
│ │ │ │ break; │ ││ │
│ │ │ │ // ... 更多请求处理 │ ││ │
│ │ │ │ } │ ││ │
│ │ │ │ } │ ││ │
│ │ │ └─────────────────────────────────────────────────────────────────┘ ││ │
│ │ │ ││ │
│ │ │ ┌─────────────────────────────────────────────────────────────────┐ ││ │
│ │ │ │ // 发送 AT 命令到 Modem │ ││ │
│ │ │ │ at_send_command("AT+CFUN=1", ...); // 开启 Radio │ ││ │
│ │ │ │ at_send_command("AT+CLCC", ...); // 查询通话 │ ││ │
│ │ │ │ at_send_command("AT+CGDCONT=...",...); // 设置 APN │ ││ │
│ │ │ │ │ ││ │
│ │ │ │ // 发送响应回调到上层 │ ││ │
│ │ │ │ RIL_onRequestComplete(t, RIL_E_SUCCESS, response, len); │ ││ │
│ │ │ │ │ ││ │
│ │ │ │ // 发送主动上报到上层 │ ││ │
│ │ │ │ RIL_onUnsolicitedResponse(RIL_UNSOL_SIGNAL_STRENGTH, ...); │ ││ │
│ │ │ └─────────────────────────────────────────────────────────────────┘ ││ │
│ │ └─────────────────────────────────────────────────────────────────────────┘│ │
│ │ │ │ │
│ │ │ 串口/USB/QMI/RPC │
│ │ ▼ │ │
│ │ ┌──────────────┐ │ │
│ │ │ Modem │ │ │
│ │ │ 基带芯片 │ │ │
│ │ └──────────────┘ │ │
│ └─────────────────────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────────────────────┘
📤 Request 流程(下发)详细步骤
Step 1: Framework 层发起请求
java
// frameworks_opt_telephony/.../Phone.java 或 GsmCdmaPhone.java
public void setRadioPower(boolean power) {
mCi.setRadioPower(power, null); // mCi = CommandsInterface (RIL 实例)
}
// frameworks_opt_telephony/.../RIL.java
public void setRadioPower(boolean power, Message result) {
IRadio radioProxy = getRadioProxy(result); // 获取 HIDL Proxy
if (radioProxy != null) {
RILRequest rr = obtainRequest(RIL_REQUEST_RADIO_POWER, result);
// ... 构建请求
// 通过 Proxy 调用 HIDL 接口
radioServiceInvokeHelper(
HAL_SERVICE_MODEM, rr, "setRadioPower", () -> {
modemProxy.setRadioPower(rr.mSerial, power);
});
}
}
Step 2: RadioXxxProxy 调用 HIDL
java
// frameworks_opt_telephony/.../RadioModemProxy.java
public void setRadioPower(int serial, boolean on) throws RemoteException {
if (isEmpty()) return;
if (isAidl()) {
// AIDL 方式调用
mModemProxy.setRadioPower(serial, on);
} else {
// HIDL 方式调用
mRadioProxy.setRadioPower(serial, on);
}
}
Step 3: HIDL IPC 传输
HIDL 自动生成代码处理 Binder IPC:
cpp
// 自动生成的 HIDL Proxy 代码
Return<void> setRadioPower(int32_t serial, bool on) override {
// 序列化参数
// 通过 Binder 发送到 HAL 进程
}
Step 4: HAL 层 - RadioImpl 接收请求
cpp
// hardware_ril/libril/ril_service.cpp
// RadioImpl 继承自 V1_1::IRadio
struct RadioImpl : public V1_1::IRadio {
sp<IRadioResponse> mRadioResponse;
sp<IRadioIndication> mRadioIndication;
// 实现 setRadioPower 方法
Return<void> setRadioPower(int32_t serial, bool on) {
RLOGD("setRadioPower: serial %d on %d", serial, on);
// 将 HIDL 调用转换为 legacy RIL 请求
dispatchInts(serial, mSlotId, RIL_REQUEST_RADIO_POWER, 1,
BOOL_TO_INT(on));
return Void();
}
// 实现 getIccCardStatus 方法
Return<void> getIccCardStatus(int32_t serial) {
dispatchVoid(serial, mSlotId, RIL_REQUEST_GET_SIM_STATUS);
return Void();
}
};
// dispatch 函数
void dispatchVoid(int serial, int slotId, int request) {
RequestInfo *pRI = android::addRequestToList(serial, slotId, request);
// 调用厂商 RIL 的 onRequest
CALL_ONREQUEST(request, NULL, 0, pRI, slotId);
}
void dispatchInts(int serial, int slotId, int request, int count, ...) {
// 打包整数参数
// 调用厂商 RIL 的 onRequest
CALL_ONREQUEST(request, data, datalen, pRI, slotId);
}
Step 5: Vendor RIL 处理
c
// hardware_ril/reference-ril/reference-ril.c
// RIL 函数表
static const RIL_RadioFunctions s_callbacks = {
RIL_VERSION,
onRequest, // 处理请求的入口
currentState,
onSupports,
onCancel,
getVersion
};
// 请求处理主函数
static void onRequest (int request, void *data, size_t datalen, RIL_Token t) {
switch (request) {
case RIL_REQUEST_GET_SIM_STATUS:
// 发送 AT 命令获取 SIM 状态
getSIMStatus(t);
break;
case RIL_REQUEST_RADIO_POWER:
// 发送 AT 命令控制 Radio 电源
setRadioPower(data, datalen, t);
break;
case RIL_REQUEST_DIAL:
// 发送 ATD 命令拨号
dial(data, datalen, t);
break;
case RIL_REQUEST_SETUP_DATA_CALL:
// 建立数据连接
setupDataCall(data, datalen, t);
break;
// ... 更多请求处理
}
}
// 具体实现示例:设置 Radio 电源
static void setRadioPower(void *data, size_t datalen, RIL_Token t) {
int onOff = ((int *)data)[0];
// 发送 AT 命令
if (onOff) {
at_send_command("AT+CFUN=1", NULL); // 开机
} else {
at_send_command("AT+CFUN=0", NULL); // 关机
}
// 发送响应回调
RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
}
// 发送 AT 命令
static void at_send_command(const char *command, ATResponse **outResponse) {
// 通过串口/USB 发送命令到 Modem
write(mFd, command, strlen(command));
// 等待并解析响应
}
Step 6: Response 回调流程
c
// Vendor RIL 发送响应
RIL_onRequestComplete(t, RIL_E_SUCCESS, response, responseLen);
回到 HAL 层:
cpp
// hardware_ril/libril/ril_service.cpp
// Response 回调函数
int setRadioPowerResponse(int slotId, int responseType, int serial,
RIL_Errno e, void *response, size_t responselen) {
// 获取 RadioImpl 实例
sp<RadioImpl> radioService = getRadioService(slotId);
// 调用 mRadioResponse 的回调方法
radioService->mRadioResponse->setRadioPowerResponse(
{responseType, serial, e, 0}, // RadioResponseInfo
response
);
return 0;
}
回到 Framework 层:
java
// frameworks_opt_telephony/.../RadioResponse.java
public void setRadioPowerResponse(RadioResponseInfo responseInfo) {
// 处理响应
RILRequest rr = mRil.processResponse(responseInfo);
if (rr != null) {
// 发送消息给请求发起者
sendMessageResponse(rr.mResult, null);
mRil.processResponseDone(rr, responseInfo, null);
}
}
📥 Indication 流程(上报)详细步骤
Step 1: Modem 主动上报
Modem 检测到状态变化(如信号强度变化、网络状态变化等),通过串口/USB 上报给 Vendor RIL。
Step 2: Vendor RIL 接收并转发
c
// hardware_ril/reference-ril/reference-ril.c
// 读取 Modem 上报的数据
static void onUnsolicited(const char *s, const char *sms_pdu) {
// 解析主动上报
if (strStartsWith(s, "+CMT:")) {
// 新短信上报
RIL_onUnsolicitedResponse(RIL_UNSOL_RESPONSE_NEW_SMS,
sms_pdu, strlen(sms_pdu));
}
else if (strStartsWith(s, "+CREG:")) {
// 网络注册状态变化
RIL_onUnsolicitedResponse(RIL_UNSOL_RESPONSE_NETWORK_STATE_CHANGED,
NULL, 0);
}
else if (strStartsWith(s, "^RSSI:")) {
// 信号强度变化
int rssi = parseSignalStrength(s);
RIL_onUnsolicitedResponse(RIL_UNSOL_SIGNAL_STRENGTH,
&rssi, sizeof(rssi));
}
// ... 更多上报
}
Step 3: HAL 层转发到 Framework
cpp
// hardware_ril/libril/ril_service.cpp
// Indication 回调函数
int radioStateChangedInd(int slotId, int indicationType, int token,
RIL_Errno e, void *response, size_t responseLen) {
sp<RadioImpl> radioService = getRadioService(slotId);
// 调用 mRadioIndication 的方法
radioService->mRadioIndication->radioStateChanged(
indicationType, // UNSOLICITED 或 UNSOLICITED_ACK_EXP
(RadioState)response // 新的 Radio 状态
);
return 0;
}
int networkStateChangedInd(int slotId, int indType, int token,
RIL_Errno e, void *response, size_t responselen) {
sp<RadioImpl> radioService = getRadioService(slotId);
radioService->mRadioIndication->networkStateChanged(indType);
return 0;
}
Step 4: Framework 层 - RadioIndication 接收
java
// frameworks_opt_telephony/.../RadioIndication.java
public class RadioIndication extends IRadioIndication.Stub {
RIL mRil;
// Radio 状态变化上报
public void radioStateChanged(int indicationType, int radioState) {
// 1. 处理指示类型(是否需要 ACK)
mRil.processIndication(HAL_SERVICE_RADIO, indicationType);
// 2. 转换状态
int state = RILUtils.convertHalRadioState(radioState);
// 3. 设置 Radio 状态
mRil.setRadioState(state, false);
}
// 网络状态变化上报
public void networkStateChanged(int indicationType) {
mRil.processIndication(HAL_SERVICE_RADIO, indicationType);
if (mRil.isLogOrTrace()) {
mRil.unsljLog(RIL_UNSOL_RESPONSE_NETWORK_STATE_CHANGED);
}
// 通知所有注册的监听者
mRil.mNetworkStateRegistrants.notifyRegistrants();
}
// 新短信上报
public void newSms(int indicationType, ArrayList<Byte> pdu) {
mRil.processIndication(HAL_SERVICE_RADIO, indicationType);
byte[] pduArray = RILUtils.arrayListToPrimitiveArray(pdu);
// 转换为 SmsMessage 并通知
if (mRil.mGsmSmsRegistrant != null) {
mRil.mGsmSmsRegistrant.notifyRegistrant(
new AsyncResult(null, new SmsMessage(smsb), null));
}
}
// 通话状态变化上报
public void callStateChanged(int indicationType) {
mRil.processIndication(HAL_SERVICE_RADIO, indicationType);
// 通知通话状态监听者
mRil.mCallStateRegistrants.notifyRegistrants();
}
// 信号强度上报
public void currentSignalStrength_1_4(int indicationType,
android.hardware.radio.V1_4.SignalStrength signalStrength) {
mRil.processIndication(HAL_SERVICE_RADIO, indicationType);
SignalStrength ss = RILUtils.convertHalSignalStrength(signalStrength);
// 通知信号强度监听者
if (mRil.mSignalStrengthRegistrant != null) {
mRil.mSignalStrengthRegistrant.notifyRegistrant(
new AsyncResult(null, ss, null));
}
}
}
Step 5: RIL 处理 Indication
java
// frameworks_opt_telephony/.../RIL.java
// 处理 Indication 回调
void processIndication(int service, int indicationType) {
if (indicationType == RadioIndicationType.UNSOLICITED_ACK_EXP) {
// 需要发送 ACK 确认
sendAck(service);
if (RILJ_LOGD) riljLog("Unsol response received; Sending ack to ril.cpp");
}
// 其他类型不需要特殊处理
}
Step 6: Registrant 通知上层
java
// frameworks_opt_telephony/.../ServiceStateTracker.java (构造函数中注册)
public ServiceStateTracker(GsmCdmaPhone phone, CommandsInterface ci) {
// ... 其他初始化
// 注册网络状态变化监听
mCi.registerForAvailable(this, EVENT_RADIO_AVAILABLE, null);
mCi.registerForNotAvailable(this, EVENT_RADIO_NOT_AVAILABLE, null);
// 注册 Radio 状态变化监听
mCi.registerForRadioStateChanged(this, EVENT_RADIO_STATE_CHANGED, null);
// 注册 NITZ 时间上报监听
mCi.setOnNITZTime(this, EVENT_NITZ_TIME, null);
// 注册网络状态变化监听
mCi.registerForVoiceNetworkStateChanged(this, EVENT_NETWORK_STATE_CHANGED, null);
}
// 处理上报事件
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case EVENT_RADIO_STATE_CHANGED:
// Radio 状态变化,查询新状态
pollState();
break;
case EVENT_NETWORK_STATE_CHANGED:
// 网络状态变化,查询服务状态
pollState();
break;
case EVENT_NITZ_TIME:
// NITZ 时间上报,设置系统时间
setTimeFromNITZString((String) ar.result);
break;
case EVENT_SIGNAL_STRENGTH_UPDATE:
// 信号强度更新
notifySignalStrength();
break;
}
}
🔑 关键代码路径总结
Request 路径
| 层级 | 文件 | 关键类/方法 |
|---|---|---|
| Framework | RIL.java |
setRadioPower(), obtainRequest() |
| Framework | RadioModemProxy.java |
setRadioPower() |
| HIDL IPC | 自动生成 | HIDL Proxy → Stub |
| HAL | ril_service.cpp |
RadioImpl::setRadioPower(), dispatchInts() |
| Vendor | reference-ril.c |
onRequest(), at_send_command() |
| Response | ril_service.cpp |
setRadioPowerResponse() |
| Response | RadioResponse.java |
setRadioPowerResponse() |
Indication 路径
| 层级 | 文件 | 关键类/方法 |
|---|---|---|
| Modem | - | 主动上报数据 |
| Vendor | reference-ril.c |
onUnsolicited(), RIL_onUnsolicitedResponse() |
| HAL | ril_service.cpp |
radioStateChangedInd(), mRadioIndication->radioStateChanged() |
| HIDL IPC | 自动生成 | HIDL Indication |
| Framework | RadioIndication.java |
radioStateChanged(), mRil.mRegistrants.notifyRegistrants() |
| Framework | ServiceStateTracker.java |
handleMessage(), pollState() |
📊 时序图
Request 时序
lua
Phone RIL Proxy RadioImpl Vendor RIL Modem
| | | | | |
| setRadioPower| | | | |
|------------->| | | | |
| | modemProxy.setRadioPower() | | |
| |---------------------------->| | |
| | | HIDL IPC | | |
| | |------------->| | |
| | | | dispatchInts() |
| | | |------------->| |
| | | | onRequest() | |
| | | |------------->| |
| | | | | AT+CFUN=1 |
| | | | |------------->|
| | | | | OK |
| | | | |<-------------|
| | | | RIL_onRequestComplete() |
| | | |<-------------| |
| | | | mRadioResponse-> |
| | | | setRadioPowerResponse() |
| | | HIDL IPC |<-------------| |
| | |<-------------| | |
| | RadioResponse.setRadioPowerResponse() |
| |<-------------| | | |
| 回调通知 | | | | |
|<-------------| | | | |
Indication 时序
rust
Modem Vendor RIL RadioImpl Proxy RadioIndication RIL Phone
| | | | | | |
| +CREG: 1 | | | | | |
|------------->| | | | | |
| |RIL_onUnsolicitedResponse() | | | |
| |------------->| | | | |
| | | networkStateChangedInd() | | |
| | | mRadioIndication-> | | |
| | | networkStateChanged() | | |
| | |------------->| HIDL IPC | | |
| | | |------------->| | |
| | | | | processIndication() |
| | | | | mNetworkStateRegistrants |
| | | | | .notifyRegistrants() |
| | | | |------------->| |
| | | | | | handleMessage|
| | | | | | (EVENT_...) |
| | | | | |------------->|
| | | | | | pollState() |
| | | | | |------------->|
这个完整的流程涵盖了从 Framework 到 Modem 的所有层级,以及反向的上报流程。