2. Android系统架构与HAL定位

要理解HAL Service开发,必须先建立一张清晰的“系统地图”:Android并不是一个单体操作系统,而是由应用层、框架层、原生库与运行时、HAL层、内核层共同组成的纵向分层体系。HAL(Hardware Abstraction Layer,硬件抽象层)位于Framework与Linux Kernel之间,是Android为硬件厂商保留的“标准接口层”。它既向上为Java/Kotlin框架提供稳定的硬件访问能力,又向下屏蔽具体SoC、外设和驱动差异,使Android框架不必为每一块硬件重新编译。

一、Android分层架构:从App到Kernel

从下往上观察,Android系统大致分为五层。最底层是Linux Kernel,负责进程调度、内存管理、文件系统、网络协议栈以及各类硬件驱动;其上是HAL层,通常以共享库(.so)或独立HAL Service进程形式存在,封装摄像头、音频、传感器、蓝牙、显示、电源等硬件能力;再往上是Native C/C++ Libraries与Android Runtime,提供libc、OpenGL ES、Vulkan、Media框架、SQLite以及ART虚拟机;接着是Java API Framework,即我们熟悉的ActivityManager、WindowManager、CameraManager、SensorManager等系统服务;最上层是System Apps与第三方应用。

这种分层的核心价值在于“解耦”:应用只依赖Framework API,Framework只依赖HAL接口,HAL只依赖内核驱动。任何一层内部实现变化,只要接口不变,就不会向上层扩散。对于HAL开发者而言,这意味着工作边界非常明确——你实现的是HAL接口,而不是直接修改Framework或内核。

Android 分层架构与 HAL 定位 HAL 是 Framework 与 Kernel 之间的硬件抽象桥梁 System Apps / 第三方应用 Camera App · 音频播放器 · 传感器应用 · 蓝牙设置 Java API Framework CameraManager · AudioService · SensorManager · BluetoothService 通过 Binder / AIDL 调用 Native 服务 Native C/C++ Libraries + ART libc · OpenGL ES · Vulkan · Media · SQLite · Binder IPC HAL 硬件抽象层 Camera HAL · Audio HAL · Sensor HAL · Bluetooth HAL · Power HAL 实现形式:HIDL / AIDL HAL Service(独立进程)或 Passthrough(.so) 向上暴露标准接口,向下调用内核驱动节点 Linux Kernel 进程调度 · 内存管理 · 文件系统 · 设备驱动(V4L2 / ALSA / IIO / HCI) HAL 接口稳定 厂商实现 进程隔离 关键 向上 标准 API 向下 驱动节点 HAL 层是 Android 为硬件厂商保留的“标准接口层”,也是 HAL Service 开发的主战场

二、HAL在系统中的精确位置

HAL并不是一个“可选插件”,而是Android兼容性定义文档(CDD)和供应商接口(VINTF)约束下的强制层。在Android 8.0之前,HAL多以共享库形式被Framework直接加载,运行在system_server或Native服务进程中;Android 8.0引入Project Treble后,HAL被要求以独立进程形式运行,通过HIDL(Android 8~10)或AIDL(Android 11+)与Framework通信。这一变化使HAL Service成为真正的“系统服务”,拥有自己的进程、生命周期和权限边界。

从进程视角看,HAL Service通常由init进程根据.rc文件启动,注册到ServiceManager,Framework通过Binder获取代理对象并调用。例如Camera HAL Service运行在独立的cameraserver或vendor进程中,Sensor HAL Service运行在android.hardware.sensors-service进程中。这种设计让HAL崩溃不会直接拖垮system_server,也让厂商可以独立升级HAL而不影响Framework。

三、HAL与Framework、Kernel的交互关系

HAL与Framework之间是“接口契约”关系:Framework定义接口(如ICameraProvider、ISensors),HAL实现接口。Framework不关心HAL内部如何操作硬件,只关心接口调用是否成功、数据格式是否正确、回调是否及时。HAL与Kernel之间是“驱动调用”关系:HAL通过open/ioctl/read/write/mmap等系统调用访问/dev下的设备节点,或通过sysfs、netlink、uevent等机制与驱动交互。

一个典型的调用链如下:应用调用CameraManager.openCamera() → Framework CameraService通过Binder调用ICameraProvider → HAL Service收到请求后打开/dev/video0并配置V4L2参数 → 驱动操作ISP和Sensor → 图像数据通过DMA写入缓冲区 → HAL将buffer回传给Framework → 应用收到预览帧。这条链路中,HAL既是“翻译官”,也是“调度员”。

层次 典型对象 与HAL的关系 开发者关注点
应用层 Camera App、Sensor App 不直接接触HAL API调用与权限
Framework层 CameraService、SensorService 通过Binder调用HAL接口 接口定义、VINTF声明
HAL层 Camera HAL、Sensor HAL 实现接口、调用驱动 接口实现、进程模型、线程模型
Kernel层 V4L2、ALSA、IIO驱动 被HAL通过系统调用访问 设备节点、ioctl参数、DMA

四、案例场景:Sensor HAL的一次数据上报

以加速度传感器为例。应用注册SensorEventListener后,Framework的SensorService通过ISensors接口向Sensor HAL发送activate和batch请求。HAL Service收到后,打开/dev/iio:device0,配置采样率和量程,并启动一个poll线程等待数据。当驱动产生中断并写入数据后,HAL读取event,按照sensors_event_t格式封装,再通过回调接口上报给Framework。Framework经过权限和速率过滤后,通过Binder回调给应用。整个过程中,HAL负责“把驱动原始数据变成Android标准事件”,这是HAL最核心的职责。

// 伪代码:Sensor HAL 数据上报核心逻辑
while (running) {
    poll(fd, POLLIN);
    read(fd, &raw_event, sizeof(raw_event));
    sensors_event_t event;
    event.sensor = handle;
    event.type = SENSOR_TYPE_ACCELEROMETER;
    event.acceleration.x = raw_event.x * scale;
    event.acceleration.y = raw_event.y * scale;
    event.acceleration.z = raw_event.z * scale;
    event.timestamp = raw_event.timestamp;
    callback->postEvents(&event, 1);
}

五、常见误区与复盘

误区一:把HAL当成驱动。HAL不是驱动,驱动在内核态,HAL在用户态。HAL可以调用驱动,但也可以完全用软件模拟(如虚拟传感器)。

误区二:认为HAL可以随意改接口。HAL接口受VINTF和CDD约束,修改接口会导致Framework兼容性检查失败,设备无法通过CTS/VTS。

误区三:忽略进程隔离。Treble之后HAL Service是独立进程,不能直接访问Framework内部变量,必须通过Binder通信,且要处理死亡通知和超时。

复盘建议:开发HAL Service时,先画清楚“应用→Framework→HAL→Kernel”的调用链,明确每一层的输入输出和线程模型;再确认VINTF manifest中声明的接口版本与Framework期望一致;最后用lshal、dumpsys、logcat和perfetto验证服务是否注册、调用是否到达、数据是否正确。

总结来说,Android分层架构决定了HAL的“中间人”角色:向上提供稳定、标准、可版本化的硬件访问接口,向下封装驱动差异和硬件细节。理解HAL在系统中的位置,以及它与Framework、Kernel的交互边界,是后续开发、调试和优化HAL Service的基础。