Request(下发) 和 Indication(上报) 的完整流程

我来为你详细总结 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 的所有层级,以及反向的上报流程。

相关推荐
何中应1 小时前
使用jvisualvm提示“内存不足”
java·jvm·后端
何中应1 小时前
如何手动生成一个JVM内存溢出文件
java·jvm·后端
小灵吖1 小时前
LangChain4j Tool(Function Call)
java·后端
小灵吖2 小时前
LangChain4j Prompt 提示词工程
java·后端
小邓睡不饱耶2 小时前
Spring Boot 3 + MyBatis-Plus 高性能持久层开发实战:从入门到调优
spring boot·后端·mybatis
无名之逆3 小时前
你可能不需要WebSocket-服务器发送事件的简单力量
java·开发语言·前端·后端·计算机·rust·编程
锅包一切3 小时前
一、C++ 发展与程序创建
开发语言·c++·后端·学习·编程
古城小栈4 小时前
后端视角:拆解春晚背后的高可用技术架构
后端·架构