libril.so - Android RIL 共享库全面分析

7 阅读5分钟

一、libril.so 概述

libril.so 是 Android Radio Interface Layer (RIL) 的核心共享库,充当 Android FrameworkVendor RIL 实现之间的桥梁。

1. 编译定义

LOCAL_MODULE:= libril
LOCAL_LICENSE_KINDS:= SPDX-license-identifier-Apache-2.0
LOCAL_LICENSE_CONDITIONS:= notice
LOCAL_NOTICE_FILE:= $(LOCAL_PATH)/NOTICE
LOCAL_SANITIZE := integer

include $(BUILD_SHARED_LIBRARY)

2. 源文件组成

LOCAL_SRC_FILES:= \
    ril.cpp \
    ril_event.cpp\
    RilSapSocket.cpp \
    ril_service.cpp \
    sap_service.cpp

3. 依赖的共享库

LOCAL_SHARED_LIBRARIES := \
    liblog \
    libutils \
    libcutils \
    libhardware_legacy \
    librilutils \
    android.hardware.radio@1.0 \
    android.hardware.radio@1.1 \
    libhidlbase \

二、libril.so 的架构角色

三层架构

┌─────────────────────────────────────────┐
│   Framework Layer (Java)                │
│   - RIL.java (frameworks_opt_telephony) │
│   - 通过 HIDL 接口通信                   │
└─────────────────┬───────────────────────┘
                  │ HIDL (android.hardware.radio@1.x)
┌─────────────────▼───────────────────────┐
│   libril.so (Native C/C++)              │
│   - ril.cpp: 核心逻辑                    │
│   - ril_service.cpp: HIDL 服务实现       │
│   - 事件循环、Socket 通信、消息分发      │
└─────────────────┬───────────────────────┘
                  │ dlopen/dlsym 动态加载
┌─────────────────▼───────────────────────┐
│   Vendor RIL (*.so)                     │
│   - 芯片厂商提供的实现                   │
│   - 实现 RIL_InitRIL_RadioFunctions  │
│   -Modem 通信 (AT 命令等)            │
└─────────────────────────────────────────┘

三、libril.so 的核心功能

1. 动态加载 Vendor RIL

rild 守护进程通过 dlopen() 加载厂商的 RIL 实现:

    dlHandle = dlopen(rilLibPath, RTLD_NOW);

    if (dlHandle == NULL) {
        RLOGE("dlopen failed: %s", dlerror());
        exit(EXIT_FAILURE);
    }

    RIL_startEventLoop();

    rilInit =
        (const RIL_RadioFunctions *(*)(const struct RIL_Env *, int, char **))
        dlsym(dlHandle, "RIL_Init");

    if (rilInit == NULL) {
        RLOGE("RIL_Init not defined or exported in %s\n", rilLibPath);
        exit(EXIT_FAILURE);
    }

关键点:

  • rilLibPath 通过系统属性 vendor.rild.libpathrild.libpath 指定
  • 使用 dlsym() 查找 Vendor RIL 中的 RIL_Init 函数
  • RIL_Init 返回 RIL_RadioFunctions 结构体,包含所有回调函数

2. RIL_RadioFunctions 结构体

这是 Vendor RIL 必须实现的接口:

typedef struct {
    int version;        /* set to RIL_VERSION */
    RIL_RequestFunc onRequest;
    RIL_RadioStateRequest onStateRequest;
    RIL_Supports supports;
    RIL_Cancel onCancel;
    RIL_GetVersion getVersion;
} RIL_RadioFunctions;

回调函数说明:

  • onRequest: 处理来自 Framework 的请求 (如拨号、发短信)
  • onStateRequest: 查询当前 Radio 状态
  • supports: 查询是否支持特定的 RIL 请求
  • onCancel: 取消正在进行的请求
  • getVersion: 返回 Vendor RIL 版本字符串

3. 注册 Vendor RIL 回调

    funcs = rilInit(&s_rilEnv, argc, rilArgv);
    RLOGD("RIL_Init rilInit completed");

    RIL_register(funcs);

RIL_register() 函数将 Vendor RIL 的回调保存到 libril.so 内部:

extern "C" void
RIL_register (const RIL_RadioFunctions *callbacks) {
    RLOGI("SIM_COUNT: %d", SIM_COUNT);

    if (callbacks == NULL) {
        RLOGE("RIL_register: RIL_RadioFunctions * null");
        return;
    }
    if (callbacks->version < RIL_VERSION_MIN) {
        RLOGE("RIL_register: version %d is to old, min version is %d",
             callbacks->version, RIL_VERSION_MIN);
        return;
    }

    RLOGE("RIL_register: RIL version %d", callbacks->version);

    if (s_registerCalled > 0) {
        RLOGE("RIL_register has been called more than once. "
                "Subsequent call ignored");
        return;
    }

    memcpy(&s_callbacks, callbacks, sizeof (RIL_RadioFunctions));

    s_registerCalled = 1;

    RLOGI("s_registerCalled flag set, %d", s_started);
    // Little self-check

    for (int i = 0; i < (int)NUM_ELEMS(s_commands); i++) {
        assert(i == s_commands[i].requestNumber);
    }

    for (int i = 0; i < (int)NUM_ELEMS(s_unsolResponses); i++) {
        assert(i + RIL_UNSOL_RESPONSE_BASE
                == s_unsolResponses[i].requestNumber);
    }

    radio::registerService(&s_callbacks, s_commands);
    RLOGI("RILHIDL called registerService");

}

4. HIDL 服务注册

radio::registerService() 将 libril 注册为 HIDL 服务,供 Framework 层调用:

    radio::registerService(&s_callbacks, s_commands);
    RLOGI("RILHIDL called registerService");

四、libril.so 的消息流

请求流 (Solicited)

Framework (RIL.java)
    ↓ HIDL IRadio::dial()
libril (ril_service.cpp)dispatchDial()
libril (ril.cpp)s_callbacks.onRequest(RIL_REQUEST_DIAL, ...)
Vendor RIL
    ↓ 发送 AT 命令到 Modem
    ↓ 接收 Modem 响应
    ↓ RIL_onRequestComplete(token, error, response)
libril (ril.cpp)
    ↓ HIDL callback
Framework (RIL.java)

主动上报流 (Unsolicited)

Modem
    ↓ 上报事件 (如来电)
Vendor RIL
    ↓ RIL_onUnsolicitedResponse(RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED)
libril (ril.cpp)
    ↓ s_unsolResponses[] 查表
    ↓ radio::callStateChangedInd()
libril (ril_service.cpp)
    ↓ HIDL IRadioIndication::callStateChanged()
Framework (RIL.java)

五、libril.so 的关键数据结构

1. s_callbacks (全局变量)

RIL_RadioFunctions s_callbacks = {0, NULL, NULL, NULL, NULL, NULL};
static int s_registerCalled = 0;

保存 Vendor RIL 注册的所有回调函数。

2. s_commands (命令表)

/** Index == requestNumber */
static CommandInfo s_commands[] = {
#include "ril_commands.h"
};

定义所有 RIL 请求的属性 (如请求号、分发函数、唤醒类型)。

3. s_unsolResponses (主动上报表)

static UnsolResponseInfo s_unsolResponses[] = {
#include "ril_unsol_commands.h"
};

定义所有主动上报事件的处理函数,例如:

    {RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED, radio::radioStateChangedInd, WAKE_PARTIAL},
    {RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED, radio::callStateChangedInd, WAKE_PARTIAL},
    {RIL_UNSOL_RESPONSE_VOICE_NETWORK_STATE_CHANGED, radio::networkStateChangedInd, WAKE_PARTIAL},
    {RIL_UNSOL_RESPONSE_NEW_SMS, radio::newSmsInd, WAKE_PARTIAL},
    {RIL_UNSOL_RESPONSE_NEW_SMS_STATUS_REPORT, radio::newSmsStatusReportInd, WAKE_PARTIAL},
    {RIL_UNSOL_RESPONSE_NEW_SMS_ON_SIM, radio::newSmsOnSimInd, WAKE_PARTIAL},
    {RIL_UNSOL_ON_USSD, radio::onUssdInd, WAKE_PARTIAL},
    {RIL_UNSOL_ON_USSD_REQUEST, radio::onUssdInd, DONT_WAKE},
    {RIL_UNSOL_NITZ_TIME_RECEIVED, radio::nitzTimeReceivedInd, WAKE_PARTIAL},
    {RIL_UNSOL_SIGNAL_STRENGTH, radio::currentSignalStrengthInd, DONT_WAKE},
    {RIL_UNSOL_DATA_CALL_LIST_CHANGED, radio::dataCallListChangedInd, WAKE_PARTIAL},
    {RIL_UNSOL_SUPP_SVC_NOTIFICATION, radio::suppSvcNotifyInd, WAKE_PARTIAL},
    {RIL_UNSOL_STK_SESSION_END, radio::stkSessionEndInd, WAKE_PARTIAL},
    {RIL_UNSOL_STK_PROACTIVE_COMMAND, radio::stkProactiveCommandInd, WAKE_PARTIAL},
    {RIL_UNSOL_STK_EVENT_NOTIFY, radio::stkEventNotifyInd, WAKE_PARTIAL},
    {RIL_UNSOL_STK_CALL_SETUP, radio::stkCallSetupInd, WAKE_PARTIAL},
    {RIL_UNSOL_SIM_SMS_STORAGE_FULL, radio::simSmsStorageFullInd, WAKE_PARTIAL},
    {RIL_UNSOL_SIM_REFRESH, radio::simRefreshInd, WAKE_PARTIAL},
    {RIL_UNSOL_CALL_RING, radio::callRingInd, WAKE_PARTIAL},
    {RIL_UNSOL_RESPONSE_SIM_STATUS_CHANGED, radio::simStatusChangedInd, WAKE_PARTIAL},
    {RIL_UNSOL_RESPONSE_CDMA_NEW_SMS, radio::cdmaNewSmsInd, WAKE_PARTIAL},
    {RIL_UNSOL_RESPONSE_NEW_BROADCAST_SMS, radio::newBroadcastSmsInd, WAKE_PARTIAL},
    {RIL_UNSOL_CDMA_RUIM_SMS_STORAGE_FULL, radio::cdmaRuimSmsStorageFullInd, WAKE_PARTIAL},
    {RIL_UNSOL_RESTRICTED_STATE_CHANGED, radio::restrictedStateChangedInd, WAKE_PARTIAL},
    {RIL_UNSOL_ENTER_EMERGENCY_CALLBACK_MODE, radio::enterEmergencyCallbackModeInd, WAKE_PARTIAL},
    {RIL_UNSOL_CDMA_CALL_WAITING, radio::cdmaCallWaitingInd, WAKE_PARTIAL},

六、libril.so 与 Vendor RIL 的接口

RIL_Env 结构体

libril.so 向 Vendor RIL 提供的环境接口 (RIL_Env):

    void (*RequestTimedCallback) (RIL_TimedCallback callback,
                                   void *param, const struct timeval *relativeTime);
   /**
    * "t" is parameter passed in on previous call RIL_Notification routine
    *
    * RIL_onRequestAck will be called by vendor when an Async RIL request was received
    * by them and an ack needs to be sent back to java ril.
    */
    void (*OnRequestAck) (RIL_Token t);

Vendor RIL 可以通过这些函数:

  1. OnRequestComplete: 返回请求结果
  2. OnUnsolicitedResponse: 上报主动事件
  3. RequestTimedCallback: 注册定时回调
  4. OnRequestAck: 确认收到异步请求

七、调试方法

1. 查看 RIL 日志

# libril 的日志标签
adb logcat -s RILC RILD RILJ RILHIDL

# 查看加载的 Vendor RIL 库
adb shell getprop vendor.rild.libpath
# 或
adb shell getprop rild.libpath

2. 查看进程信息

# 查看 rild 进程
adb shell ps -A | grep rild

# 查看加载的共享库
adb shell cat /proc/$(pidof rild)/maps | grep libril

3. Radio 命令工具

# 发送 Radio 命令 (需要 root)
adb shell service call phone 1 s16 "your_command"

八、总结

维度说明
定位Android Telephony 的中间层共享库
作用连接 Framework 和 Vendor RIL,实现 HIDL 服务
加载方式rild 通过 dlopen() 加载,然后 dlopen() Vendor RIL
核心文件ril.cpp, ril_service.cpp, sap_service.cpp
接口协议HIDL (android.hardware.radio@1.x)
配置属性vendor.rild.libpath / rild.libpath
关键函数RIL_register(), RIL_onRequestComplete(), RIL_onUnsolicitedResponse()

libril.so 是 Android Telephony 栈的"粘合剂",负责抽象硬件差异,统一上层接口,使得不同芯片厂商的 Modem 都能无缝接入 Android 系统。