Sensors HAL 接口在 sensors.h 中声明,表示 Android 框架与硬件专用软件之间的接口。HAL 实现必须定义 sensors.h 中声明的每个函数。主要函数包括:
get_sensors_list
- 返回所有传感器的列表。activate
- 启动或停止传感器。batch
- 设置传感器的参数,例如采样频率和最长报告延迟时间。setDelay
- 仅在 HAL 1.0 版本中使用。设置给定传感器的采样频率。flush
- 刷新指定传感器的 FIFO,并在完成时报告刷新完成事件。poll
- 返回可用的传感器事件。
实现必须是线程安全的,并允许从不同线程调用这些函数。
该接口还定义了这些函数使用的几种类型。主要类型包括:
sensors_module_t
sensors_poll_device_t
sensor_t
sensors_event_t
除了以下部分外,请参阅 sensors.h,详细了解这些类型。
get_sensors_list(list)
int (*get_sensors_list)(struct sensors_module_t* module, struct sensor_t const** list);
提供 HAL 实现的传感器列表。请参阅 sensor_t,详细了解如何定义传感器。
传感器在列表中出现的顺序就是传感器报告给应用的顺序。通常,基础传感器先出现,然后是复合传感器。
如果多个传感器共享相同的传感器类型和唤醒属性,则列表中第一个传感器称为“默认”传感器。它是 getDefaultSensor(int sensorType, bool wakeUp)
返回的传感器。
此函数返回列表中传感器的数量。
activate(sensor, true/false)
int (*activate)(struct sensors_poll_device_t *dev, int sensor_handle, int enabled);
激活或停用传感器。
sensor_handle
是要激活/停用传感器的句柄。传感器的句柄由其 sensor_t 结构的 handle
字段定义。
enabled
设置为 1 以启用传感器,设置为 0 以停用传感器。
单次触发传感器在接收到事件后会自动停用,但它们仍然必须接受通过调用 activate(..., enabled=0)
来停用。
非唤醒传感器永远不会阻止 SoC 进入暂停模式;也就是说,HAL 不应代表应用程序持有部分唤醒锁。
唤醒传感器在持续传递事件时,可以阻止 SoC 进入暂停模式,但是如果不需要传递任何事件,则必须释放部分唤醒锁。
如果 enabled
为 1 并且传感器已激活,则此函数为空操作并成功。
如果 enabled
为 0 并且传感器已停用,则此函数为空操作并成功。
此函数在成功时返回 0,否则返回负错误号。
batch(传感器, 标志, 采样周期, 最大报告延迟)
int (*batch)( struct sensors_poll_device_1* dev, int sensor_handle, int flags, int64_t sampling_period_ns, int64_t max_report_latency_ns);
设置传感器的参数,包括采样频率和最大报告延迟。可以在传感器激活时调用此函数,在这种情况下,它绝不能导致任何传感器测量结果丢失:从一个采样率过渡到另一个采样率不会导致事件丢失,从高最大报告延迟过渡到低最大报告延迟也不会导致事件丢失。
sensor_handle
是要配置的传感器的句柄。
flags
当前未使用。
sampling_period_ns
是传感器应运行的采样周期,以纳秒为单位。有关更多详细信息,请参见sampling_period_ns。
max_report_latency_ns
是事件在通过 HAL 报告之前可以延迟的最大时间,以纳秒为单位。有关更多详细信息,请参见max_report_latency_ns段落。
此函数在成功时返回 0,否则返回负错误号。
setDelay(传感器, 采样周期)
int (*setDelay)( struct sensors_poll_device_t *dev, int sensor_handle, int64_t sampling_period_ns);
在 HAL 1.0 版本之后,此函数已被弃用,并且永远不会被调用。而是调用 batch
函数来设置 sampling_period_ns
参数。
在 HAL 1.0 版本中,使用 setDelay 而不是 batch 来设置 sampling_period_ns。
flush(传感器)
int (*flush)(struct sensors_poll_device_1* dev, int sensor_handle);
为指定的传感器在硬件 FIFO 的末尾添加刷新完成事件并刷新 FIFO;这些事件像往常一样传递(即:好像最大报告延迟已过期)并从 FIFO 中删除。
刷新是异步发生的(即:此函数必须立即返回)。如果实现对多个传感器使用单个 FIFO,则刷新该 FIFO,并且仅为指定的传感器添加刷新完成事件。
如果指定的传感器没有 FIFO(无法缓冲),或者如果在调用时 FIFO 为空,则 flush
仍然必须成功并为该传感器发送刷新完成事件。这适用于除单次触发传感器之外的所有传感器。
当调用 flush
时,即使 FIFO 中已存在该传感器的刷新事件,也必须创建一个额外的刷新事件并将其添加到 FIFO 的末尾,并且必须刷新 FIFO。flush
调用的次数必须等于创建的刷新完成事件的数量。
flush
不适用于单次触发传感器;如果 sensor_handle
引用单次触发传感器,则 flush
必须返回 -EINVAL
并且不生成任何刷新完成元数据事件。
如果成功,此函数返回 0;如果指定的传感器是单次触发传感器或未启用,则返回 -EINVAL
;否则返回负错误号。
poll()
int (*poll)(struct sensors_poll_device_t *dev, sensors_event_t* data, int
count);
通过填充 data
参数返回传感器数据数组。此函数必须阻塞,直到事件可用。成功时,它将返回读取的事件数;如果发生错误,则返回负错误号。
在 data
中返回的事件数必须小于或等于 count
参数。此函数永远不应返回 0(无事件)。
调用顺序
当设备启动时,会调用 get_sensors_list
。
当传感器被激活时,将使用请求的参数调用 batch
函数,然后调用 activate(..., enable=1)
。
请注意,在 HAL 1_0 版本中,顺序相反:先调用 activate
,然后调用 set_delay
。
当传感器激活时,如果其请求的特性发生更改,则会调用 batch
函数。
可以随时调用 flush
,即使在未激活的传感器上也可以调用(在这种情况下,它必须返回 -EINVAL
)
当传感器被停用时,将调用 activate(..., enable=0)
。
与这些调用并行,将重复调用 poll
函数以请求数据。即使没有激活任何传感器,也可以调用 poll
。
sensors_module_t
sensors_module_t
是用于为传感器创建 Android 硬件模块的类型。HAL 的实现必须定义此类型的对象 HAL_MODULE_INFO_SYM
以公开 get_sensors_list 函数。有关更多信息,请参见 sensors.h 中 sensors_module_t
的定义以及 hw_module_t
的定义。
sensors_poll_device_t / sensors_poll_device_1_t
sensors_poll_device_1_t
包含上面定义的其余方法:activate
、batch
、flush
和 poll
。其 common
字段(类型为 hw_device_t)定义了 HAL 的版本号。
sensor_t
sensor_t
代表一个 Android 传感器。以下是它的一些重要字段
name: 代表传感器的用户可见字符串。此字符串通常包含底层传感器的部件名称、传感器的类型以及它是否是唤醒传感器。例如,“LIS2HH12 加速度计”、“MAX21000 未校准陀螺仪”、“BMP280 唤醒气压计”、“MPU6515 游戏旋转矢量”
handle: 注册到传感器或从中生成事件时用于引用传感器的整数。
type: 传感器的类型。有关更多详细信息,请参见 什么是 Android 传感器? 中的传感器类型说明,有关官方传感器类型,请参见 传感器类型。对于非官方传感器类型,type
必须以 SENSOR_TYPE_DEVICE_PRIVATE_BASE
开头
stringType: 传感器类型的字符串表示形式。当传感器具有官方类型时,设置为 SENSOR_STRING_TYPE_*
。当传感器具有制造商特定的类型时,stringType
必须以制造商反向域名开头。例如,由 Fictional-Company 的 Cool-product 团队定义的传感器(例如,独角兽检测器)可以使用 stringType="com.fictional_company.cool_product.unicorn_detector"
。stringType
用于唯一标识非官方传感器类型。有关类型和字符串类型的更多信息,请参见 sensors.h。
requiredPermission: 代表应用程序必须拥有的权限的字符串,才能查看传感器、注册到传感器并接收其数据。空字符串表示应用程序无需任何权限即可访问此传感器。某些传感器类型(例如心率监测器)具有强制性的 requiredPermission
。所有提供敏感用户信息(例如心率)的传感器都必须受到权限保护。
flags: 此传感器的标志,定义了传感器的报告模式以及传感器是否是唤醒传感器。例如,单次触发唤醒传感器将具有 flags = SENSOR_FLAG_ONE_SHOT_MODE | SENSOR_FLAG_WAKE_UP
。当前 HAL 版本中未使用的标志位必须保持为 0。
maxRange: 传感器可以报告的最大值,单位与报告值相同。传感器必须能够在 [-maxRange; maxRange]
范围内报告值而不会饱和。请注意,这意味着从广义上讲,传感器的总范围为 2*maxRange
。当传感器报告多个轴上的值时,该范围适用于每个轴。例如,“+/- 2g”加速度计将报告 maxRange = 2*9.81 = 2g
。
resolution: 传感器可以测量的最小数值差异。通常根据 maxRange
和测量中的位数计算得出。
power: 启用传感器的功耗,以毫安为单位。这几乎总是比底层传感器数据表中报告的功耗要高。有关更多详细信息,请参见基础传感器 != 物理传感器,有关如何测量传感器功耗的详细信息,请参见功耗测量过程。如果传感器的功耗取决于设备是否移动,则移动时的功耗是在 power
字段中报告的功耗。
minDelay: 对于连续传感器,采样周期以微秒为单位,对应于传感器支持的最快速率。有关如何使用此值的详细信息,请参见sampling_period_ns。请注意,minDelay
以微秒为单位表示,而 sampling_period_ns
以纳秒为单位表示。对于状态变化和特殊报告模式传感器,除非另有说明,否则 minDelay
必须为 0。对于单次触发传感器,它必须为 -1。
maxDelay: 对于连续和状态变化传感器,采样周期以微秒为单位,对应于传感器支持的最慢速率。有关如何使用此值的详细信息,请参见sampling_period_ns。请注意,maxDelay
以微秒为单位表示,而 sampling_period_ns
以纳秒为单位表示。对于特殊和单次触发传感器,maxDelay
必须为 0。
fifoReservedEventCount: 在硬件 FIFO 中为此传感器保留的事件数。如果此传感器有专用 FIFO,则 fifoReservedEventCount
是此专用 FIFO 的大小。如果 FIFO 与其他传感器共享,则 fifoReservedEventCount
是 FIFO 中为该传感器保留的部分的大小。在大多数共享 FIFO 系统以及没有硬件 FIFO 的系统上,此值为 0。
fifoMaxEventCount: 可以存储在此传感器的 FIFO 中的最大事件数。这始终大于或等于 fifoReservedEventCount
。此值用于估计以特定速率注册到传感器时 FIFO 将多快变满,假设没有激活其他传感器。在没有硬件 FIFO 的系统上,fifoMaxEventCount
为 0。有关更多详细信息,请参见批量处理。
对于具有官方传感器类型的传感器,某些字段会被框架覆盖。例如,加速度计传感器被强制为具有连续报告模式,而心率监测器被强制受到 SENSOR_PERMISSION_BODY_SENSORS
权限的保护。
sensors_event_t
由 Android 传感器生成并通过 poll 函数报告的传感器事件类型为 sensors_event_t
。以下是 sensors_event_t
的一些重要字段
version: 必须为 sizeof(struct sensors_event_t)
sensor: 生成事件的传感器的句柄,如 sensor_t.handle
所定义。
type: 生成事件的传感器的传感器类型,如 sensor_t.type
所定义。
timestamp: 事件的时间戳,以纳秒为单位。这是事件发生的时间(采取了一个步骤,或进行了加速度计测量),而不是报告事件的时间。timestamp
必须与 elapsedRealtimeNano
时钟同步,并且对于连续传感器,抖动必须很小。有时需要进行时间戳过滤才能满足 CDD 要求,因为仅使用 SoC 中断时间来设置时间戳会导致抖动过高,而仅使用传感器芯片时间来设置时间戳可能会导致与 elapsedRealtimeNano
时钟失去同步,因为传感器时钟会漂移。
data 和重叠字段: 传感器测得的值。这些字段的含义和单位特定于每种传感器类型。有关数据字段的说明,请参见 sensors.h 以及不同传感器类型的定义。对于某些传感器,读数的精度也通过 status
字段作为数据的一部分报告。此字段仅针对那些选定的传感器类型进行管道传输,在 SDK 层显示为精度值。对于这些传感器,在其传感器类型定义中提到了必须设置状态字段的事实。
元数据刷新完成事件
元数据事件与普通传感器事件具有相同的类型:sensors_event_meta_data_t = sensors_event_t
。它们与通过 poll 返回的其他传感器事件一起返回。它们具有以下字段
version: 必须为 META_DATA_VERSION
type: 必须为 SENSOR_TYPE_META_DATA
sensor、reserved 和 timestamp:必须为 0
meta_data.what: 包含此事件的元数据类型。当前只有一个有效的元数据类型:META_DATA_FLUSH_COMPLETE
。
META_DATA_FLUSH_COMPLETE
事件表示传感器 FIFO 刷新完成。当 meta_data.what=META_DATA_FLUSH_COMPLETE
时,meta_data.sensor
必须设置为已刷新的传感器的句柄。它们仅在对传感器调用 flush
时生成。有关更多信息,请参见关于 flush 函数的部分。