2. Android Sensor系统架构:从App到HAL的完整数据流

做Sensor驱动开发,你首先得搞清楚一件事:数据是怎么从硬件跑到App里的?

我刚入行那会儿,以为Sensor HAL写好了就完事了。结果发现App拿不到数据,折腾了两天才知道是SensorService没注册上。嗯,从那以后,我养成了一个习惯——先看架构,再动手写代码。

今天我们就来拆解一下Android Sensor系统的完整链路。说白了,就是搞清楚三个关键角色:SensorManager、SensorService、SensorDevice。

2.1 整体架构概览

先给你一张图,这是我画了很多遍才总结出来的。你盯着看30秒,后面讲什么你都能跟上。

Android Sensor 系统架构分层 Application 层 App 通过 SensorManager 获取传感器数据 Framework 层 SensorManager (Java API) SensorService (Native Service) HAL 层 SensorDevice (HAL Interface) Kernel 层 Sensor Driver / I2C / SPI 用户空间 内核空间

你看,从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。

我的经验:调试的时候,如果App拿不到传感器列表,别急着查HAL。先在SensorManager.getSensorList()这里打个断点,看看是不是Service没连上。我曾经在一个项目里,因为SELinux权限配置错了,SensorService启动失败,App端一直返回空列表。查了两天才定位到,亏大了。

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的传感器请求都经过它。所以它的性能很关键。

避坑指南:我曾经遇到过一个case,某个第三方App疯狂注册高频率的传感器监听,导致SensorService的Binder线程池被占满,其他App的传感器请求全部超时。解决方案是在SensorService里加了一个频率限制策略。所以你在做HAL适配时,一定要考虑多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端设置再高的采样率也没用。

重点:SensorDevice通过open()函数加载HAL库。Android系统会根据hardware/libhardware/hardware.c中的逻辑,去/vendor/lib/hw/或/system/lib/hw/目录下找对应的sensors.<platform>.so文件。

2.3 完整数据流:从App到HAL

好了,三个关键组件都认识了。我们串起来看看,一次完整的传感器数据请求是怎么走的。

  1. App调用registerListener() — SensorManager通过Binder向SensorService发送请求
  2. SensorService处理请求 — 检查权限、分配缓冲区、设置采样率
  3. SensorService调用SensorDevice — 通过HAL接口激活传感器
  4. HAL层操作硬件 — 通过ioctl或sysfs控制Kernel驱动
  5. 硬件产生数据 — 中断或轮询方式上报
  6. 数据逆流而上 — 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模块。到时候你会看到,今天讲的这些架构知识,全都会用上。

可可精品资料库