2. Android Sensor系统架构:从App到HAL的完整数据流
做Sensor驱动开发,你首先得搞清楚一件事:数据是怎么从硬件跑到App里的?
我刚入行那会儿,以为Sensor HAL写好了就完事了。结果发现App拿不到数据,折腾了两天才知道是SensorService没注册上。嗯,从那以后,我养成了一个习惯——先看架构,再动手写代码。
今天我们就来拆解一下Android Sensor系统的完整链路。说白了,就是搞清楚三个关键角色:SensorManager、SensorService、SensorDevice。
2.1 整体架构概览
先给你一张图,这是我画了很多遍才总结出来的。你盯着看30秒,后面讲什么你都能跟上。
你看,从App到硬件,中间隔了四层。每一层都有它存在的道理。我见过不少工程师,上来就怼HAL代码,结果Framework层的接口没搞清楚,白忙活一场。
2.2 关键组件详解
2.2.1 SensorManager — App的入口
SensorManager是App开发者接触的第一个类。你想想看,App要读加速度计,怎么写?
// App端获取SensorManager
SensorManager sensorManager =
(SensorManager) getSystemService(Context.SENSOR_SERVICE);
// 获取加速度计
Sensor accelerometer =
sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
// 注册监听器
sensorManager.registerListener(
myListener,
accelerometer,
SensorManager.SENSOR_DELAY_NORMAL
);
这段代码看起来简单,但背后发生的事情可不少。SensorManager其实是一个代理,它不直接跟硬件打交道。它通过Binder IPC调用到SystemServer进程里的SensorService。
2.2.2 SensorService — 核心调度者
SensorService是Android Sensor系统的心脏。它运行在SystemServer进程里,负责三件事:
- 管理传感器列表 — 从HAL层读取所有可用传感器
- 调度数据分发 — 根据App注册的采样率和精度,控制数据上报频率
- 权限控制 — 检查App是否有权限访问特定传感器
SensorService启动时,会加载HAL库。具体来说,它通过SensorDevice这个C++类来操作HAL。
// frameworks/native/services/sensorservice/SensorService.cpp
void SensorService::onFirstBoot() {
// 初始化SensorDevice
mSensorDevice = &SensorDevice::getInstance();
// 枚举所有传感器
sensor_t const* list;
int count = mSensorDevice->getSensorList(&list);
// 注册到ServiceManager
for (int i = 0; i < count; i++) {
registerSensor(new HardwareSensor(list[i]));
}
}
这里有个细节要注意:SensorService是单例的。整个系统只有一个SensorService实例,所有App的传感器请求都经过它。所以它的性能很关键。
2.2.3 SensorDevice — HAL层的桥梁
SensorDevice是连接Framework和HAL的关键纽带。它定义在hardware/libhardware/include/hardware/sensors.h里。
它的核心数据结构是sensors_module_t和sensor_t:
// hardware/libhardware/include/hardware/sensors.h
typedef struct sensors_module_t {
struct hw_module_t common;
// 获取传感器列表
int (*get_sensors_list)(struct sensors_module_t* module,
struct sensor_t const** list);
} sensors_module_t;
typedef struct sensor_t {
const char* name; // 传感器名称
const char* vendor; // 厂商
int version; // 版本
int handle; // 句柄,唯一标识
int type; // 类型(加速度计、陀螺仪等)
float maxRange; // 量程
float resolution; // 分辨率
float power; // 功耗(mA)
int32_t minDelay; // 最小采样间隔(微秒)
uint32_t fifoReservedEventCount; // FIFO保留事件数
uint32_t fifoMaxEventCount; // FIFO最大事件数
} sensor_t;
你看这个sensor_t结构体,每个字段都有讲究。比如minDelay,它决定了这个传感器最快能跑多快。如果你填错了,App端设置再高的采样率也没用。
open()函数加载HAL库。Android系统会根据hardware/libhardware/hardware.c中的逻辑,去/vendor/lib/hw/或/system/lib/hw/目录下找对应的sensors.<platform>.so文件。
2.3 完整数据流:从App到HAL
好了,三个关键组件都认识了。我们串起来看看,一次完整的传感器数据请求是怎么走的。
- App调用registerListener() — SensorManager通过Binder向SensorService发送请求
- SensorService处理请求 — 检查权限、分配缓冲区、设置采样率
- SensorService调用SensorDevice — 通过HAL接口激活传感器
- HAL层操作硬件 — 通过ioctl或sysfs控制Kernel驱动
- 硬件产生数据 — 中断或轮询方式上报
- 数据逆流而上 — Kernel → HAL → SensorService → App
这里面最容易被忽略的是数据流向的控制。SensorService不是简单地转发数据,它会根据App的优先级和采样率做数据融合。比如两个App都注册了加速度计,一个要50Hz,一个要100Hz,SensorService会取最大值100Hz,然后分别分发给两个App。
adb shell dumpsys sensorservice命令。它会打印出当前所有注册的传感器、采样率、以及每个App的连接状态。这个命令我几乎天天用,比看log高效多了。
2.4 关键数据结构一览
为了方便你查阅,我把几个关键数据结构整理成了表格:
| 组件 | 关键类/结构体 | 所在文件 | 主要职责 |
|---|---|---|---|
| App层 | SensorManager | android.hardware.SensorManager | 提供Java API给App调用 |
| Framework | SensorService | SensorService.cpp | 调度、权限、数据分发 |
| Framework | SensorDevice | SensorDevice.cpp | 封装HAL接口调用 |
| HAL层 | sensors_module_t | sensors.h | HAL模块入口 |
| HAL层 | sensor_t | sensors.h | 传感器属性描述 |
| HAL层 | sensors_event_t | sensors.h | 传感器数据事件 |
2.5 小结
这一章我们走通了Android Sensor系统的完整链路。从App的SensorManager,到SystemServer里的SensorService,再到HAL层的SensorDevice,每一层各司其职。
你记住一句话:SensorManager是入口,SensorService是大脑,SensorDevice是桥梁。搞清楚了这三者的关系,后面写HAL代码的时候,你就知道每一行代码是在跟谁打交道。
下一章,我们会深入HAL层的具体实现,手把手教你写一个完整的Sensor HAL模块。到时候你会看到,今天讲的这些架构知识,全都会用上。