Android 音频子系统:Audio HAL Server 启动全流程深度解析
1. 背景与架构概述
在 Android Treble 架构中,音频系统的核心逻辑被拆分为 Framework 层(AudioFlinger) 与 Vendor 层(Audio HAL) 。android.hardware.audio.service 进程是 Vendor 层的守护进程,它的主要职责是:
- 对接硬件 :加载厂商实现的音频驱动库(
.so)。 - 提供接口:将硬件能力通过 HIDL 或 AIDL 接口暴露给系统服务。
- 常驻运行 :作为独立进程,处理来自
audioserver的 Binder 请求。
本文将深入分析该进程从编译、启动到最终与 AudioFlinger 握手的全过程。
2. 全链路启动流程图
AudioFlinger (Framework) hwservicemanager Audio HAL Service (vendor 分区) init 进程 AudioFlinger (Framework) hwservicemanager Audio HAL Service (vendor 分区) init 进程 ------ 阶段一:Framework 订阅监听 ------ ------ 阶段二:HAL 进程启动与初始化 ------ ------ 阶段三:动态发现与服务注册 ------ ------ 阶段四:跨进程握手 ------ 注册通知监听 (IDevicesFactory) 1 解析 init.rc 启动进程 2 main(): 初始化 Binder/AIDL 线程池 3 main(): 配置 hwbinder 共享内存大小 4 寻找版本匹配的 -impl.so 5 dlopen / dlsym (执行 HIDL_FETCH) 6 创建 DevicesFactory 对象 7 registerAsService("default") 8 发送通知:IDevicesFactory 已就绪 9 getService("default") 10 返回 Binder 代理 (Bp) 11 建立连接并监听死亡通知 12
3. 进程构建与配置
3.1 编译蓝图:cc_binary
Audio HAL Server 是一个标准的 C++ 二进制文件,通过 Android.bp 定义。
makefile
cc_binary {
name: "android.hardware.audio.service",
init_rc: ["android.hardware.audio.service.rc"],
relative_install_path: "hw",
vendor: true,
srcs: ["service.cpp"],
cflags: [
"-Wall",
"-Wextra",
"-Werror",
],
shared_libs: [
"libcutils",
"libbinder",
"libbinder_ndk",
"libhidlbase",
"liblog",
"libutils",
"libhardware",
],
defaults: [
"android_hardware_audio_config_defaults",
],
}
3.2 启动配置:init.rc
系统启动时由 init 进程拉起。注意其运行权限为 audioserver,并赋予了 SYS_NICE 权限以确保音频流的实时性。
c
service vendor.audio-hal /vendor/bin/hw/android.hardware.audio.service
class hal
user audioserver
# media gid needed for /dev/fm (radio) and for /data/misc/media (tee)
group audio camera drmrpc inet media mediadrm net_bt net_bt_admin net_bw_acct wakelock context_hub
capabilities BLOCK_SUSPEND SYS_NICE
# setting RLIMIT_RTPRIO allows binder RT priority inheritance
rlimit rtprio 10 10
ioprio rt 4
task_profiles ProcessCapacityHigh HighPerformance
onrestart restart audioserver
4. 源码深度解析:从 main 开始
4.1 进程入口:service.cpp
main 函数负责搭建整个 Binder 通信环境,并采用"从新到旧"的版本回退策略注册接口。
c
/**
* Audio HAL Service 进程入口函数
*
* 该 main 函数负责:
* 1. 初始化 vendor 侧 Binder(vndbinder / hwbinder / AIDL Binder)运行环境
* 2. 配置 Binder / HIDL RPC 线程池及共享内存参数
* 3. 注册 Audio 相关的 HIDL HAL 接口(必选 / 可选)
* 4. 通过 dlopen 方式加载并注册部分外部 HAL 实现(如 Bluetooth Audio)
* 5. 进入 Binder 线程池循环,作为常驻 Audio HAL 服务运行
*
* 该进程通常运行在 vendor 分区,
* 是 system_server 与底层音频硬件之间的核心服务节点。
*/
int main(int /* argc */, char* /* argv */ []) {
/**
* 忽略 SIGPIPE 信号。
*
* 在 Binder 或 socket 通信中:
* - 如果对端进程异常退出
* - 当前进程向已关闭的 fd 写数据
* 默认行为会触发 SIGPIPE 并导致进程被系统杀死。
*
* Audio HAL 是常驻服务进程,必须具备健壮性,
* 因此忽略 SIGPIPE,由代码自行处理错误返回。
*/
signal(SIGPIPE, SIG_IGN);
/**
* 初始化 android::ProcessState,并指定使用 /dev/vndbinder。
*
* 说明:
* - vndbinder 是 system binder 在 vendor 侧的镜像
* - 用于 system_server ↔ vendor HAL 的跨分区 Binder 通信
*
* Audio HAL 运行在 vendor 进程中,
* 必须显式使用 vndbinder,而不能使用 /dev/binder。
*/
::android::ProcessState::initWithDriver("/dev/vndbinder");
/**
* 启动 vndbinder 的 Binder 线程池。
*
* 该线程池用于:
* - 处理来自 system_server 的 HIDL / Binder 请求
* - 接收 Audio HAL 接口调用
*
* 如果不启动线程池,Binder 调用将无法被处理。
*/
::android::ProcessState::self()->startThreadPool();
/**
* 设置 AIDL(libbinder_ndk)线程池的最大线程数。
*
* Audio HAL 中的 AIDL 接口通常对并发要求不高,
* 限制线程数可以:
* - 减少竞态条件
* - 降低锁复杂度
* - 避免资源被过度并发访问
*/
ABinderProcess_setThreadPoolMaxThreadCount(1);
/**
* 启动 AIDL Binder 线程池。
*
* 使基于 AIDL 的 HAL 接口可以开始接收客户端请求。
*/
ABinderProcess_startThreadPool();
/**
* 定义系统属性默认值。
*
* 用于判断 hwbinder mmap 大小是否被厂商显式配置。
*/
const int32_t defaultValue = -1;
/**
* 从系统属性中读取 hwbinder mmap 大小配置(单位:KB)。
*
* hwbinder mmap 区域用于:
* - HIDL Binder 之间的大块数据传输
* - FMQ(Fast Message Queue)
* - 较大的参数结构体
*
* 在音频场景中,该大小可能影响:
* - 音频参数下发
* - offload / effect 配置
*/
int32_t value =
property_get_int32("persist.vendor.audio.service.hwbinder.size_kbyte", defaultValue);
/**
* 如果系统属性存在(即不等于默认值),
* 则使用该值重新配置 hwbinder 的 mmap 大小。
*/
if (value != defaultValue) {
/**
* 打印日志,记录当前使用的 mmap 配置。
*/
ALOGD("Configuring hwbinder with mmap size %d KBytes", value);
/**
* 将 KB 转换为 Byte,并初始化 hwbinder 的共享内存大小。
*
* 注意:
* - 该配置必须在 Binder 实际使用前完成
* - 否则配置将不会生效
*/
ProcessState::initWithMmapSize(static_cast<size_t>(value) * 1024);
}
/**
* 配置 HIDL RPC 线程池。
*
* 参数说明:
* - 16 :HIDL RPC 最大线程数
* - callerWillJoin = true:
* 表示 main 线程本身也会进入 RPC 线程池
*
* 这是 HIDL HAL 能够被 system_server 调用的必要条件。
*/
configureRpcThreadpool(16, true /*callerWillJoin*/);
// Automatic formatting tries to compact the lines, making them less readable
// clang-format off
/**
* 定义必须注册的 Audio HAL 接口族列表。
*
* 每个 InterfacesList 的结构为:
* - 第一个元素:接口族名称(仅用于日志)
* - 后续元素 :按"版本从新到旧"排列的 HIDL 接口全名
*
* 只要其中任意一个版本注册成功,
* 即认为该接口族在当前设备上可用。
*/
const std::vector<InterfacesList> mandatoryInterfaces = {
{
"Audio Core API",
"android.hardware.audio@7.1::IDevicesFactory",
"android.hardware.audio@7.0::IDevicesFactory",
"android.hardware.audio@6.0::IDevicesFactory", /*HidlServiceManagement: Registered android.hardware.audio@6.0::IDevicesFactory/default 当时注册成功的是*/
"android.hardware.audio@5.0::IDevicesFactory",
"android.hardware.audio@4.0::IDevicesFactory",
},
{
"Audio Effect API",
"android.hardware.audio.effect@7.0::IEffectsFactory",
"android.hardware.audio.effect@6.0::IEffectsFactory",
"android.hardware.audio.effect@5.0::IEffectsFactory",
"android.hardware.audio.effect@4.0::IEffectsFactory",
}
};
/**
* 定义可选注册的 Audio 相关 HAL 接口族。
*
* 这些接口通常依赖特定硬件能力:
* - SoundTrigger(语音唤醒)
* - Bluetooth Audio
*
* 注册失败不会影响 Audio 核心功能,
* 因此仅打印警告日志。
*/
const std::vector<InterfacesList> optionalInterfaces = {
{
"Soundtrigger API",
"android.hardware.soundtrigger@2.3::ISoundTriggerHw",
"android.hardware.soundtrigger@2.2::ISoundTriggerHw",
"android.hardware.soundtrigger@2.1::ISoundTriggerHw",
"android.hardware.soundtrigger@2.0::ISoundTriggerHw",
},
{
"Bluetooth Audio API",
"android.hardware.bluetooth.audio@2.2::IBluetoothAudioProvidersFactory",
"android.hardware.bluetooth.audio@2.1::IBluetoothAudioProvidersFactory",
"android.hardware.bluetooth.audio@2.0::IBluetoothAudioProvidersFactory",
},
{
/**
* 旧版 Bluetooth A2DP Offload HIDL 接口。
*
* 该接口在 Bluetooth Audio HAL V2
* 完全支持 offload 后可被移除。
*/
"Bluetooth Audio Offload API",
"android.hardware.bluetooth.a2dp@1.0::IBluetoothAudioOffload"
}
};
/**
* 定义通过共享库方式注册的可选 HAL 实现。
*
* 与 passthrough HAL 不同:
* - HAL 实现不与当前进程静态链接
* - 通过 dlopen 在运行期动态加载
*
* 常见于 Bluetooth Audio 等模块。
*/
const std::vector<std::pair<std::string,std::string>> optionalInterfaceSharedLibs = {
{
"android.hardware.bluetooth.audio-impl",
"createIBluetoothAudioProviderFactory",
},
{
"android.hardware.bluetooth.adapter1.audio-impl",
"createIBluetoothAudioProviderFactory",
},
};
// clang-format on
/**
* 注册所有必须存在的 Audio HAL 接口族。
*
* 若整个接口族注册失败,
* 表示系统无法提供核心 Audio 能力,
* 因此直接触发 fatal,终止进程。
*/
for (const auto& listIter : mandatoryInterfaces) {
auto iter = listIter.begin();
const std::string& interfaceFamilyName = *iter++;
LOG_ALWAYS_FATAL_IF(
!registerPassthroughServiceImplementations(iter, listIter.end()),
"Could not register %s", interfaceFamilyName.c_str());
}
/**
* 注册所有可选的 Audio HAL 接口族。
*
* 注册失败不会中断进程,
* 仅用于提示当前设备不支持对应能力。
*/
for (const auto& listIter : optionalInterfaces) {
auto iter = listIter.begin();
const std::string& interfaceFamilyName = *iter++;
ALOGW_IF(
!registerPassthroughServiceImplementations(iter, listIter.end()),
"Could not register %s", interfaceFamilyName.c_str());
}
/**
* 通过 dlopen 方式注册外部 HAL 服务实现。
*
* 每个共享库内部通常提供一个工厂函数,
* 用于创建并注册对应的 HAL Binder 服务。
*/
for (const auto& interfacePair : optionalInterfaceSharedLibs) {
const std::string& libraryName = interfacePair.first;
const std::string& interfaceLoaderFuncName = interfacePair.second;
if (registerExternalServiceImplementation(libraryName, interfaceLoaderFuncName)) {
ALOGI("%s() from %s success",
interfaceLoaderFuncName.c_str(), libraryName.c_str());
} else {
ALOGW("%s() from %s failed",
interfaceLoaderFuncName.c_str(), libraryName.c_str());
}
}
/**
* 当前线程加入 HIDL RPC 线程池。
*
* 该调用不会返回,
* main 线程进入 Binder 循环,
* 进程开始作为 Audio HAL 服务长期运行。
*/
joinRpcThreadpool();
}
4.2 接口注册核心逻辑:Passthrough 模式
在 Android 中,音频接口常通过 Passthrough 模式加载。这意味着 HAL 的具体实现代码直接加载到当前进程空间。
注册辅助函数
c
/**
* registerPassthroughServiceImplementations
*
* 用于注册一组 HIDL passthrough HAL 接口实现。
*
* 设计背景:
* - 同一 HAL 接口通常存在多个版本(如 audio@7.1 / 7.0 / 6.0)
* - 设备只需支持其中一个版本即可满足 framework 要求
* - 因此采用"从新到旧逐个尝试"的 fallback 策略
*
* 返回值语义:
* - 只要任意一个接口版本注册成功,即返回 true
* - 所有版本都失败才返回 false
*/
static bool registerPassthroughServiceImplementations(Iter first, Iter last) {
for (; first != last; ++first) {
/**
* 尝试注册当前接口版本对应的 passthrough HAL 实现。
*
* registerPassthroughServiceImplementation 内部会:
* - 查找该接口的 HAL 实现
* - 创建服务对象
* - 将服务注册到 hwservicemanager
*/
if (registerPassthroughServiceImplementation(*first) == OK) {
/**
* 当前接口版本注册成功,
* 认为整个接口族已经满足要求,立即返回成功。
*/
return true;
}
}
/**
* 所有接口版本均注册失败,
* 表示该接口族在当前设备上不可用。
*/
return false;
}
外部库动态加载逻辑
对于蓝牙音频等模块,通过 dlopen 灵活加载,避开了静态链接的限制。
c
/**
* registerExternalServiceImplementation
*
* 通过 dlopen + 工厂函数的方式,注册一个外部 HAL 服务实现。
*
* 设计背景:
* - 某些 HAL(如 Bluetooth Audio)不适合 passthrough 方式
* - HAL 实现可能依赖不同厂商库或运行时选择
* - 因此采用动态加载的方式进行注册
*
* 参数说明:
* - libName : 共享库名(不包含 .so)
* - funcName : 库中用于创建并注册 HAL 服务的工厂函数名
*/
static bool registerExternalServiceImplementation(const std::string& libName,
const std::string& funcName) {
constexpr int dlMode = RTLD_LAZY;
// 清除之前可能残留的 dlerror 状态
dlerror();
// 拼接出完整的共享库文件名
auto libPath = libName + ".so";
/**
* 动态加载共享库。
*
* 若加载失败,说明该 HAL 实现不适用于当前设备,
* 或者相关模块未编译进 vendor 镜像。
*/
void* handle = dlopen(libPath.c_str(), dlMode);
if (handle == nullptr) {
const char* error = dlerror();
ALOGE("Failed to dlopen %s: %s", libPath.c_str(),
error != nullptr ? error : "unknown error");
return false;
}
/**
* 查找 HAL 工厂函数。
*
* 该函数通常负责:
* - 创建 HAL Binder 服务实例
* - 将其注册到 Binder / hwservicemanager
*/
binder_status_t (*factoryFunction)();
*(void**)(&factoryFunction) = dlsym(handle, funcName.c_str());
if (!factoryFunction) {
const char* error = dlerror();
ALOGE("Factory function %s not found in libName %s: %s",
funcName.c_str(), libPath.c_str(),
error != nullptr ? error : "unknown error");
// 工厂函数不存在,释放共享库
dlclose(handle);
return false;
}
/**
* 调用工厂函数完成 HAL 注册。
*
* 仅当返回 STATUS_OK 时,
* 才认为外部 HAL 服务注册成功。
*/
return ((*factoryFunction)() == STATUS_OK);
}
5. 寻址与实例化:Passthrough 机制的终点
5.1 注册实现 (LegacySupport.cpp)
这是 HAL 实现被推送到 hwservicemanager 的最后一公里。
c
/**
* registerPassthroughServiceImplementation
*
* 用于注册一个 HIDL passthrough HAL 服务实例。
*
* 背景说明:
* - Passthrough HAL 的特点是:
* - HAL 实现代码直接运行在当前进程中
* - 不通过独立的 binderized HAL service 进程
* - 因此在注册前,必须:
* 1. 找到本地 HAL 实现(不能是 remote)
* 2. 校验其接口类型是否符合预期
* 3. 将该实现注册到 hwservicemanager
*
* 该函数是 Audio HAL / Effect HAL 等
* 在 vendor 进程中完成 HIDL 服务注册的"最后一道关卡"。
*
* 参数说明:
* - interfaceName : 用于查找 HAL 实现的接口名(可能是某个版本)
* - expectInterfaceName : 期望的接口 descriptor(用于安全校验)
* - registerServiceCb : 实际执行注册动作的回调函数
* - serviceName : HAL 服务名(通常是 "default")
*
* 返回值:
* - OK : 注册成功
* - EXIT_FAILURE : 任一步骤失败
*
* warn_unused_result:
* - 强制调用者必须检查返回值
* - 防止 HAL 注册失败却被忽略
*/
__attribute__((warn_unused_result))
status_t registerPassthroughServiceImplementation(
const std::string& interfaceName,
const std::string& expectInterfaceName,
RegisterServiceCb registerServiceCb,
const std::string& serviceName) {
/**
* 通过 HIDL 内部机制获取 passthrough HAL 实现对象。
*
* getRawServiceInternal 的关键行为:
* - 根据 interfaceName + serviceName 查找 HAL 实现
* - retry = true:
* 表示在首次失败时可进行重试(适配 HAL 初始化时序)
* - getStub = true:
* 强制获取 passthrough stub(即本地实现)
*
* 成功返回:
* - 一个运行在当前进程内的 HAL 对象(sp<IBase>)
*/
sp<IBase> service =
getRawServiceInternal(interfaceName,
serviceName,
true /* retry */,
true /* getStub */); // -----------------重点6 拿到 DevicesFactory 对象
/**
* 如果未能获取 HAL 实现,说明:
* - 该接口版本在当前设备上未实现
* - 或 HAL 模块未编译 / 未链接进当前进程
*/
if (service == nullptr) {
ALOGE("Could not get passthrough implementation for %s/%s.",
interfaceName.c_str(), serviceName.c_str());
return EXIT_FAILURE;
}
/**
* 校验该 HAL 实现是否为本地对象。
*
* 对于 passthrough HAL:
* - service->isRemote() 必须返回 false
*
* 如果是 remote,说明:
* - 该接口实际上是 binderized HAL
* - 或被错误地代理到了其他进程
*
* 这与 passthrough HAL 的设计目标相违背。
*/
if (service->isRemote()) {
ALOGE("Implementation of %s/%s is remote!",
interfaceName.c_str(), serviceName.c_str());
return EXIT_FAILURE;
}
/**
* 用于保存 HAL 实现实际声明的接口 descriptor。
*
* 该 descriptor 由 HAL 实现自身返回,
* 用于防止"接口名与实现类型不匹配"的错误注册。
*/
std::string actualName;
/**
* 通过 HIDL interfaceDescriptor() 获取实现的真实接口名。
*
* 示例返回值:
* - "android.hardware.audio@6.0::IDevicesFactory"
*
* 使用 Return<void> 是因为:
* - HIDL 接口调用本身是一次 Binder 风格调用
* - 需要显式检查通信是否成功
*/
Return<void> result = service->interfaceDescriptor(
[&actualName](const hidl_string& descriptor) {
actualName = descriptor;
});
/**
* 如果接口 descriptor 获取失败,说明:
* - HIDL 通信异常
* - HAL 实现不完整或存在严重错误
*/
if (!result.isOk()) {
ALOGE("Error retrieving interface name from %s/%s: %s",
interfaceName.c_str(),
serviceName.c_str(),
result.description().c_str());
return EXIT_FAILURE;
}
/**
* 校验 HAL 实现的真实接口类型是否符合预期。
*
* 该检查用于防止以下问题:
* - HAL 实现返回了错误的接口类型
* - 不同接口之间发生误注册
*
* 这是 Audio HAL 等核心模块的重要安全校验点。
*/
if (actualName != expectInterfaceName) {
ALOGE("Implementation of %s/%s is actually %s, not a %s!",
interfaceName.c_str(),
serviceName.c_str(),
actualName.c_str(),
expectInterfaceName.c_str());
return EXIT_FAILURE;
}
/**
* 调用注册回调函数,将 HAL 服务注册到 hwservicemanager。
*
* registerServiceCb 内部通常会:
* - 将 service 转换为具体接口类型
* - 调用 registerAsService(serviceName)
*/
status_t status = registerServiceCb(service, serviceName); // -----------------重点7 最终将 DevicesFactory 服务注册进 hwservicemanager 中
/**
* 根据注册结果打印日志。
*/
if (status == OK) {
ALOGI("Registration complete for %s/%s.",
interfaceName.c_str(), serviceName.c_str());
} else {
ALOGE("Could not register service %s/%s (%d).",
interfaceName.c_str(), serviceName.c_str(), status);
}
/**
* 返回最终注册结果。
*/
return status;
}
5.2 核心函数:getRawServiceInternal
该函数通过扫描 /vendor/lib64/hw 等目录,寻找符合命名的 .so 文件。
c
// 核心函数:根据 VINTF / 系统配置 / 运行模式,
// 获取指定 HIDL HAL 的"原始实现对象(IBase)"
//
// 该函数是 HIDL getService 体系的底层实现,
// 同时支持:
// 1) HWBinder HAL(独立进程)
// 2) Passthrough HAL(so 直连)
// 3) Legacy HAL(无 VINTF 声明的历史模式)
// 4) Treble 测试 / Stub 场景
sp<::android::hidl::base::V1_0::IBase> getRawServiceInternal(
const std::string& descriptor, // 接口全名,如 android.hardware.audio@6.0::IDevicesFactory
const std::string& instance, // 实例名,通常是 "default"
bool retry, // 是否允许在 HAL 未启动时重试等待
bool getStub) { // 是否只获取本地 stub(不走 Binder)
// Transport 表示 HAL 的部署方式(来自 VINTF)
// - HWBINDER : HAL 运行在独立进程,通过 Binder 通信
// - PASSTHROUGH : HAL 以 so 形式直接 dlopen 到当前进程
// - EMPTY : VINTF 未声明(legacy 场景)
using Transport = IServiceManager1_0::Transport;
// Waiter 用于在 HWBinder 模式下等待 HAL service 注册完成
// 解决 "client 启动早于 HAL server" 的时序问题
sp<Waiter> waiter;
// hwservicemanager(HIDL Service Manager)
sp<IServiceManager1_1> sm;
// 默认认为是 legacy(VINTF 未声明)
Transport transport = Transport::EMPTY;
// Recovery 模式是一个特例:
// - 没有 hwservicemanager
// - 没有完整 Binder 环境
// 因此只能使用 passthrough HAL
if (kIsRecovery) {
transport = Transport::PASSTHROUGH;
} else {
// 获取 hwservicemanager
sm = defaultServiceManager1_1();
-------------- system/libhidl/transport/ServiceManagement.cpp
+ // 获取 HIDL ServiceManager(V1.2 版本)的全局单例
+ //
+ // 这是 HIDL 世界中"所有 HAL 注册 / 查询"的根节点:
+ // - HAL Server 通过它 register()
+ // - HAL Client 通过它 get()
+ //
+ // 对应的远端服务是:
+ // /vendor/bin/hw/android.hidl.manager@1.2-service
+ //
+ // 本函数负责:
+ // 1. 延迟初始化(lazy init)
+ // 2. 线程安全的单例创建
+ // 3. 确保 hwservicemanager 已经启动
+ // 4. 建立当前进程到 hwservicemanager 的 Binder 通道
+ sp<IServiceManager1_2> defaultServiceManager1_2() {
+ using android::hidl::manager::V1_2::BnHwServiceManager;
+ using android::hidl::manager::V1_2::BpHwServiceManager;
+
+ // 全局 mutex:保护 ServiceManager 单例的创建过程
+ // 使用 new + 引用,避免静态析构顺序问题(AOSP 常见写法)
+ static std::mutex& gDefaultServiceManagerLock = *new std::mutex;
+
+ // 全局缓存的 IServiceManager 单例
+ // 一旦成功获取,后续所有调用都会直接返回
+ static sp<IServiceManager1_2>& gDefaultServiceManager =
+ *new sp<IServiceManager1_2>;
+
+ {
+ // 保证多线程环境下只初始化一次
+ std::lock_guard<std::mutex> _l(gDefaultServiceManagerLock);
+
+ // 如果已经初始化过,直接返回
+ if (gDefaultServiceManager != nullptr) {
+ return gDefaultServiceManager;
+ }
+
+ // 检查 hwbinder 设备节点是否存在且可访问
+ //
+ // 含义:
+ // - /dev/hwbinder 不存在 → 设备不支持 HIDL/HwBinder
+ // - 或当前进程无权限 → vendor/system 隔离或 SELinux 问题
+ //
+ // 在这些情况下,HIDL ServiceManager 不可用
+ if (access("/dev/hwbinder", F_OK | R_OK | W_OK) != 0) {
+ // HwBinder not available on this device or not accessible to
+ // this process.
+ return nullptr;
+ }
+
+ // 阻塞等待 hwservicemanager 启动完成
+ //
+ // hwservicemanager 是 HIDL 架构的"中枢服务",
+ // 必须先于所有 HAL client / server 启动。
+ //
+ // 如果它还没 ready,这里会一直等
+ waitForHwServiceManager();
+
+ // 尝试从 Binder context 中获取 hwservicemanager 的 Binder 对象
+ //
+ // ProcessState::self()->getContextObject(nullptr)
+ // → 获取 Binder Context Manager(类似 system_server 在 system binder 中的角色)
+ //
+ // fromBinder:
+ // - 把一个通用的 IBinder
+ // - 转换为强类型的 IServiceManager1_2 接口
+ //
+ // BpHwServiceManager : proxy(client 侧)
+ // BnHwServiceManager : stub(server 侧)
+ while (gDefaultServiceManager == nullptr) {
+ gDefaultServiceManager =
+ fromBinder<IServiceManager1_2,
+ BpHwServiceManager,
+ BnHwServiceManager>(
+ ProcessState::self()->getContextObject(nullptr)); // 通过这里拿到了 ServiceManager 的代理 BpHwServiceManager
+
+ // 理论上不常发生,但在系统启动早期可能出现:
+ // - Binder 驱动 ready
+ // - hwservicemanager 进程尚未完全注册
+ if (gDefaultServiceManager == nullptr) {
+ LOG(ERROR) << "Waited for hwservicemanager, but got nullptr.";
+ sleep(1);
+ }
+ }
+ }
+
+ // 返回全局唯一的 hwservicemanager 接口
+ return gDefaultServiceManager;
+ }
-------------->
if (sm == nullptr) {
// 正常系统中不应该发生,属于致命环境错误
ALOGE("getService: defaultServiceManager() is null");
return nullptr;
}
// 查询 VINTF manifest,确认该 HAL 的 Transport 类型
// 这是 Treble 架构下的"最终裁判"
Return<Transport> transportRet = sm->getTransport(descriptor, instance);
if (!transportRet.isOk()) {
// 无法从 hwservicemanager 获取 transport,直接失败
ALOGE("getService: defaultServiceManager()->getTransport returns %s",
transportRet.description().c_str());
return nullptr;
}
transport = transportRet;
}
// 根据 transport 派生出几种判断标志
const bool vintfHwbinder = (transport == Transport::HWBINDER); // 正规 HWBinder HAL
const bool vintfPassthru = (transport == Transport::PASSTHROUGH); // VINTF 声明为 passthrough
// Treble 测试模式(CTS / VTS)
// 在该模式下,系统会放宽某些 VINTF 限制
const bool trebleTestingOverride = isTrebleTestingOverride();
// 是否允许 legacy HAL(未写入 VINTF 的 HAL)
// 典型场景:
// - 老设备
// - 非 enforce VINTF 的系统
// - Treble 测试 + userdebug
const bool allowLegacy =
!kEnforceVintfManifest || (trebleTestingOverride && isDebuggable());
// VINTF 未声明,但系统允许 legacy,则进入 legacy 路径
const bool vintfLegacy = (transport == Transport::EMPTY) && allowLegacy;
// 如果没有强制启用 VINTF 校验,打印强烈警告
// 原因:
// - HAL 若未写入 VINTF
// - 且启动较慢
// 则 client 可能永远无法获取到 HAL(竞态条件)
if (!kEnforceVintfManifest) {
ALOGE("getService: Potential race detected. The VINTF manifest is not being enforced. If "
"a HAL server has a delay in starting and it is not in the manifest, it will not be "
"retrieved. Please make sure all HALs on this device are in the VINTF manifest and "
"enable PRODUCT_ENFORCE_VINTF_MANIFEST on this device (this is also enabled by "
"PRODUCT_FULL_TREBLE). PRODUCT_ENFORCE_VINTF_MANIFEST will ensure that no race "
"condition is possible here.");
// 粗暴但有效的兜底,给 HAL 一点启动时间
sleep(1);
}
// =========================
// HWBinder / Legacy 获取路径
// =========================
//
// 条件说明:
// - !getStub : 调用方期望获取真正的 HAL(非 stub)
// - vintfHwbinder : 正规 HWBinder HAL
// - vintfLegacy : legacy HAL(通过 hwservicemanager 暴露)
for (int tries = 0; !getStub && (vintfHwbinder || vintfLegacy); tries++) {
// 第二次及以后尝试时,创建 Waiter
// 用于等待 HAL service 注册完成
if (waiter == nullptr && tries > 0) {
waiter = new Waiter(descriptor, instance, sm);
}
// 每一轮尝试前重置 waiter 状态
if (waiter != nullptr) {
waiter->reset(); // 顺序不能乱,reset 内部有同步假设
}
// 从 hwservicemanager 获取 HAL
Return<sp<IBase>> ret = sm->get(descriptor, instance); // -----------------重点3 拿到 DevicesFactory 对象
--------- system/libhidl/transport/ServiceManagement.cpp
+ Return<sp<IBase>> get(const hidl_string& fqName,
+ const hidl_string& name) override {
+ // 最终返回的 HAL 实例(IBase 是所有 HIDL 接口的根)
+ sp<IBase> ret = nullptr;
+
+ /**
+ * openLibs 的职责:
+ * 1. 根据 fqName(例如 android.hardware.audio@6.0::IDevicesFactory)
+ * 2. 找到所有"可能匹配"的 HAL so
+ * 3. 逐个 dlopen
+ * 4. 对每个 so,回调下面这个 lambda
+ *
+ * ⚠️ 这是一个"遍历 + 尝试"的模型,不是只试一次
+ */
+ openLibs(fqName, [&](void* handle,
+ const std::string& lib,
+ const std::string& sym) {
+
+ /**
+ * 每个 Passthrough HAL so 必须导出一个"工厂函数"
+ * 典型名字类似:
+ * HIDL_FETCH_IDevicesFactory
+ *
+ * 这个函数的签名是:
+ * IBase* factory(const char* instanceName)
+ */
+ IBase* (*generator)(const char* name);
+
+ // 用 dlsym 从 so 里找这个 factory 符号
+ *(void **)(&generator) = dlsym(handle, sym.c_str());
+
+ if (!generator) {
+ // so 打开成功,但符号不存在
+ // 说明这个 so 并不是我们要的 HAL 实现
+ const char* error = dlerror();
+ LOG(ERROR)
+ << "Passthrough lookup opened " << lib
+ << " but could not find symbol " << sym
+ << ": " << (error == nullptr ? "unknown error" : error)
+ << ". Keeping library open.";
+
+ /**
+ * 为什么不 dlclose?
+ *
+ * - Passthrough HAL 可能被多个线程同时访问
+ * - dlclose + 并发调用 极其容易崩
+ * - Android 这里选择"宁愿泄露,也不炸进程"
+ */
+ return true; // 继续尝试下一个 so
+ }
+
+ /**
+ * 调用 factory 函数
+ * name 是 instance name,比如:
+ * "default"
+ * "primary"
+ */
+ ret = (*generator)(name.c_str()); // 这里会直接调用 HIDL_FETCH_IDevicesFactory 函数 ,这里创建了 DevicesFactory 对象; -----------------重点1 DevicesFactory 对象创建
+
+ if (ret == nullptr) {
+ // 这个 HAL so 存在,但不支持这个 instance
+ LOG(ERROR)
+ << "Could not find instance '" << name.c_str()
+ << "' in library " << lib
+ << ". Keeping library open.";
+
+ // 同样不 dlclose,理由同上
+ return true; // 继续找其他 so
+ }
+
+ /**
+ * ⚠️ 关键设计点:
+ *
+ * fqName 是"期望的接口名"
+ * 但 ret 可能是:
+ * - 子类
+ * - vendor 扩展实现
+ *
+ * 所以这里要:
+ * 1. 通过反射拿到"真实 descriptor"
+ * 2. 用真实 fqName 做引用注册
+ */
+ using ::android::hardware::details::getDescriptor;
+ std::string actualFqName = getDescriptor(ret.get());
+
+ CHECK(actualFqName.size() > 0);
+
+ /**
+ * registerReference 的作用:
+ * - 建立 "fqName + instance" → 实例 的映射
+ * - 防止重复创建
+ * - 便于调试 / 生命周期管理
+ */
+ registerReference(actualFqName, name);
+
+ // false 表示:已经找到合适实现,停止遍历
+ return false;
+ });
+ ----------
+ + static void openLibs(
+ + const std::string& fqName,
+ + const std::function<bool /* continue */ (
+ + void* /* handle */,
+ + const std::string& /* lib */,
+ + const std::string& /* sym */)>& eachLib) {
+ +
+ + /**
+ + * fqName 形如:
+ + * android.hardware.audio@7.0::IDevicesFactory
+ + *
+ + * 这是 HIDL 的"完全限定接口名":
+ + * package + version + interface
+ + *
+ + * Passthrough 模式下:
+ + * - 不通过 hwservicemanager
+ + * - 只能靠 fqName 来"反推出" HAL so 的名字
+ + */
+ +
+ + // 找到 "::",分离 package/version 与 interface 名
+ + size_t idx = fqName.find("::");
+ +
+ + // 如果 fqName 格式非法,直接失败
+ + if (idx == std::string::npos ||
+ + idx + strlen("::") + 1 >= fqName.size()) {
+ + LOG(ERROR) << "Invalid interface name passthrough lookup: " << fqName;
+ + return;
+ + }
+ +
+ + /**
+ + * packageAndVersion:
+ + * android.hardware.audio@6.0
+ + *
+ + * ifaceName:
+ + * IDevicesFactory
+ + */
+ + std::string packageAndVersion = fqName.substr(0, idx);
+ + std::string ifaceName = fqName.substr(idx + strlen("::"));
+ +
+ + /**
+ + * Passthrough HAL 的 so 命名约定:
+ + *
+ + * <package>@<version>-impl*.so
+ + *
+ + * 举例:
+ + * android.hardware.audio@6.0-impl.so
+ + * android.hardware.audio@6.0-impl-primary.so
+ + *
+ + * prefix 用于后面文件扫描
+ + */
+ + const std::string prefix = packageAndVersion + "-impl";
+ +
+ + /**
+ + * Passthrough HAL 必须导出的 factory 符号名:
+ + *
+ + * HIDL_FETCH_<InterfaceName>
+ + *
+ + * 举例:
+ + * HIDL_FETCH_IDevicesFactory
+ + *
+ + * 这是 HIDL 在编译期"强制约定"的 ABI
+ + */
+ + const std::string sym = "HIDL_FETCH_" + ifaceName;
+ +
+ + constexpr int dlMode = RTLD_LAZY;
+ + void* handle = nullptr;
+ +
+ + // 清空 dlerror,防止读到旧错误
+ + dlerror();
+ +
+ + /**
+ + * HAL 搜索路径说明(非常重要):
+ + *
+ + * Passthrough HAL 是 vendor 提供的 so,
+ + * 所以只能从「允许 vendor 访问的路径」加载
+ + *
+ + * 查找顺序体现了 Android 的分区优先级策略
+ + */
+ + static std::string halLibPathVndkSp = details::getVndkSpHwPath();
+ +
+ + std::vector<std::string> paths = {
+ + HAL_LIBRARY_PATH_ODM, // /odm/lib(64)/hw
+ + HAL_LIBRARY_PATH_VENDOR, // /vendor/lib(64)/hw
+ + halLibPathVndkSp, // /system/lib(64)/vndk-sp/hw
+ + #ifndef __ANDROID_VNDK__
+ + HAL_LIBRARY_PATH_SYSTEM, // /system/lib(64)/hw(非 VNDK 构建)
+ + #endif
+ + };
+ +
+ + /**
+ + * Treble Testing Override 场景:
+ + *
+ + * - VTS / CTS 测试
+ + * - HAL 可能被"静态链接"进测试进程
+ + * - 不存在真实的 so 文件
+ + *
+ + * 因此:
+ + * dlopen(nullptr) → 表示"当前进程本身"
+ + */
+ + if (details::isTrebleTestingOverride()) {
+ + handle = dlopen(nullptr, dlMode);
+ + if (handle == nullptr) {
+ + const char* error = dlerror();
+ + LOG(ERROR) << "Failed to dlopen self: "
+ + << (error == nullptr ? "unknown error" : error);
+ + } else if (!eachLib(handle, "SELF", sym)) {
+ + // 如果回调返回 false,表示已经找到目标 HAL
+ + return;
+ + }
+ + }
+ +
+ + /**
+ + * 正常路径:
+ + * 依次扫描每一个 HAL 目录
+ + */
+ + for (const std::string& path : paths) {
+ +
+ + /**
+ + * findFiles:
+ + * 在指定目录下查找:
+ + * prefix + "*.so"
+ + *
+ + * 举例:
+ + * android.hardware.audio@7.0-impl*.so
+ + */
+ + std::vector<std::string> libs = findFiles(path, prefix, ".so");
+ +
+ + for (const std::string &lib : libs) {
+ + const std::string fullPath = path + lib;
+ +
+ + /**
+ + * recovery 或 system 分区:
+ + * 使用普通 dlopen
+ + *
+ + * vendor / odm:
+ + * 必须使用 android_load_sphal_library
+ + *
+ + * 原因:
+ + * - linker namespace 隔离
+ + * - 防止 vendor HAL 直接依赖 system 私有符号
+ + */
+ + if (kIsRecovery || path == HAL_LIBRARY_PATH_SYSTEM) {
+ + handle = dlopen(fullPath.c_str(), dlMode);
+ + } else {
+ + #if !defined(__ANDROID_RECOVERY__) && defined(__ANDROID__)
+ + handle = android_load_sphal_library(fullPath.c_str(), dlMode);
+ + #endif
+ + }
+ +
+ + if (handle == nullptr) {
+ + const char* error = dlerror();
+ + LOG(ERROR) << "Failed to dlopen " << lib << ": "
+ + << (error == nullptr ? "unknown error" : error);
+ + continue;
+ + }
+ +
+ + /**
+ + * eachLib 回调的职责:
+ + * - dlsym(HIDL_FETCH_xxx)
+ + * - 调 factory(name)
+ + * - 判断是否是目标 instance
+ + *
+ + * 返回值含义:
+ + * true → 继续找下一个 so
+ + * false → 已经找到,立即停止遍历
+ + */
+ + if (!eachLib(handle, lib, sym)) {
+ + return;
+ + }
+ + }
+ }
+ }
+ ---------->
+
+ // 如果找到了就返回实例,找不到就是 nullptr
+ return ret; // -----------------重点2 返回 DevicesFactory 对象
+ }
--------->
if (!ret.isOk()) {
ALOGE("getService: defaultServiceManager()->get returns %s for %s/%s.",
ret.description().c_str(), descriptor.c_str(), instance.c_str());
break;
}
sp<IBase> base = ret; // -----------------重点4 拿到 DevicesFactory 对象
if (base != nullptr) {
// 校验返回的 Binder 对象是否真的实现了期望的接口
// 防止版本不匹配 / descriptor 错误
Return<bool> canCastRet =
details::canCastInterface(base.get(), descriptor.c_str(),
true /* emitError */);
// 接口匹配,成功获取 HAL
if (canCastRet.isOk() && canCastRet) {
if (waiter != nullptr) {
waiter->done();
}
// 返回 raw IBase(上层还会 wrap 成 BpXXX)
return base; // -----------------重点5 拿到 DevicesFactory 对象
}
// 接口不匹配或发生严重错误,是否继续尝试由错误类型决定
if (!handleCastError(canCastRet, descriptor, instance)) break;
}
// legacy HAL 或调用方不允许 retry,则不再等待
if (vintfLegacy || !retry) break;
// 等待 HAL server 注册(有超时)
if (waiter != nullptr) {
ALOGI("getService: Trying again for %s/%s...",
descriptor.c_str(), instance.c_str());
waiter->wait(true /* timeout */);
}
}
// 清理 waiter 状态
if (waiter != nullptr) {
waiter->done();
}
// =========================
// Passthrough / Stub 路径
// =========================
//
// 以下情况会进入:
// - getStub == true : 明确要求本地 stub
// - vintfPassthru == true : VINTF 声明为 passthrough
// - vintfLegacy == true : legacy HAL
if (getStub || vintfPassthru || vintfLegacy) {
// Passthrough Service Manager
// 负责 dlopen HAL so 并创建实例
const sp<IServiceManager1_0> pm = getPassthroughServiceManager();
if (pm != nullptr) {
sp<IBase> base = pm->get(descriptor, instance).withDefault(nullptr);
// wrapPassthrough:
// 将本地 C++ 对象包装成 Binder 风格接口,
// 使上层代码无需关心 transport 类型
if (!getStub || trebleTestingOverride) {
base = wrapPassthrough(base);
}
return base;
}
}
// 所有路径失败,返回 nullptr
return nullptr;
}
6. 对象的创建:HIDL_FETCH_xxx 工厂
在加载 .so 后,系统通过约定好的符号名调用工厂函数。
c
IDevicesFactory* HIDL_FETCH_IDevicesFactory(const char* name) {
return strcmp(name, "default") == 0 ? new DevicesFactory() : nullptr;
}
6.1 继承关系
DevicesFactory 实现类必须严格继承自生成的 HIDL 接口类。
c
class DevicesFactory : public IDevicesFactory
struct IDevicesFactory : public ::android::hidl::base::V1_0::IBase
7. 服务发现:AudioFlinger 如何连接 HAL
AudioFlinger 启动时,并不会由于 HAL 启动较慢而挂起。它采用了一种"注册-监听"的异步模式。
7.1 订阅通知
c
void DevicesFactoryHalHidl::onFirstRef() {
// 获取 hwservicemanager 的 Binder 代理
sp<IServiceManager> sm = IServiceManager::getService();
ALOG_ASSERT(sm != nullptr, "Hardware service manager is not running");
// 创建一个监听器对象
sp<ServiceNotificationListener> listener = new ServiceNotificationListener(this);
// 向 hwservicemanager 注册监听
Return<bool> result = sm->registerForNotifications(
IDevicesFactory::descriptor, "", listener);
if (result.isOk()) {
ALOGE_IF(!static_cast<bool>(result),
"Hardware service manager refused to register listener");
} else {
ALOGE("Failed to register for hardware service manager notifications: %s",
result.description().c_str());
}
}
7.2 异步获取服务
当 hwservicemanager 通知 HAL 已上线,AudioFlinger 才会真正调用 getService()。
c
class ServiceNotificationListener : public IServiceNotification {
public:
explicit ServiceNotificationListener(sp<DevicesFactoryHalHidl> factory)
: mFactory(factory) {}
// 当 DevicesFactory 注册这里就会拿到通知
Return<void> onRegistration(const hidl_string& /*fully_qualified_name*/,
const hidl_string& instance_name,
bool /*pre_existing*/) override {
if (static_cast<std::string>(instance_name) == "default") return Void();
sp<DevicesFactoryHalHidl> factory = mFactory.promote();
if (!factory) return Void();
sp<IDevicesFactory> halFactory = IDevicesFactory::getService(instance_name); // 这里 获得了 DevicesFactory 的 Bp 代理
if (halFactory) {
factory->addDeviceFactory(halFactory, true /*needToNotify*/);
}
return Void();
}
private:
wp<DevicesFactoryHalHidl> mFactory;
};
8. 总结
Android Audio HAL 的启动是一套严密的流程:
- 进程就绪 :
init开启沙盒进程。 - 环境搭建 :
main配置多种 Binder 池。 - 动态扫描 :利用
dlopen寻找厂商实现的.so。 - 服务挂名 :在
hwservicemanager注册。 - 异步握手 :
AudioFlinger通过监听机制最终实现跨进程调用。
这种设计保证了系统服务与厂商驱动的强解耦,即便硬件驱动初始化缓慢,也不会导致上层核心服务崩溃。