一、libril.so 概述
libril.so 是 Android Radio Interface Layer (RIL) 的核心共享库,充当 Android Framework 和 Vendor 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_Init 和 RIL_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.libpath或rild.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 可以通过这些函数:
OnRequestComplete: 返回请求结果OnUnsolicitedResponse: 上报主动事件RequestTimedCallback: 注册定时回调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 系统。