The Sensors Hardware Abstraction Layer (HAL) is the interface between the Android sensor framework and a device's sensors, such as an accelerometer or gyroscope. The Sensors HAL defines the functions that must be implemented to allow the framework to control the sensors.
The Sensors AIDL HAL is available in Android 13 and higher for new and upgraded devices. The Sensors AIDL HAL, which is based on Sensors HAL 2.1, uses the AIDL HAL interface and exposes the head tracker and limited-axis IMU sensor types.
AIDL HAL Interface
The main source of documentation for the Sensors AIDL HAL is within the HAL definition at hardware/interfaces/sensors/aidl/android/hardware/sensors/ISensors.aidl.
Implement the Sensors AIDL HAL
To implement the Sensors AIDL HAL, an object must extend the ISensors
interface and implement all functions defined in
hardware/interfaces/sensors/aidl/android/hardware/sensors/ISensors.aidl.
Initialize the HAL
The Sensors HAL must be initialized by the Android sensor framework before it
can be used. The framework calls the initialize()
function to provide three
parameters to the Sensors HAL: two FMQ descriptors and one pointer to an
ISensorsCallback
object.
The HAL uses the first descriptor to create the Event FMQ used to write sensor
events to the framework. The HAL uses the second descriptor to create the Wake
Lock FMQ used to synchronize when the HAL releases its wake lock for WAKE_UP
sensor events. The HAL must save a pointer to the ISensorsCallback
object so
that any necessary callback functions may be invoked.
The initialize()
function must be the first function called when initializing
the Sensors HAL.
Expose available sensors
To get a list of all of the available static sensors in the device, use the
getSensorsList()
function. This function returns a list of sensors, each
uniquely identified by its handle. The handle for a given sensor must not change
when the process hosting the Sensors HAL restarts. Handles might change across
device reboots, and across system server restarts.
If several sensors share the same sensor type and wake-up property, then the
first sensor in the list is called the default sensor and is returned to
apps that utilize the getDefaultSensor(int sensorType, bool wakeUp)
function.
Stability of sensors list
After a Sensors HAL restart, if the data returned by getSensorsList()
indicates a significant change compared to the sensor list retrieved before the
restart, the framework triggers a restart of the
Android runtime. Significant changes to the sensor list include cases where a
sensor with a given handle is missing or has changed attributes, or where new
sensors are introduced. Although restarting the Android runtime is disruptive
to the user, it's required because the Android framework can no longer meet the
Android API contract that static (nondynamic) sensors don't change during the
lifetime of an app. This may also prevent the framework from reestablishing
active sensor requests made by apps. Therefore, HAL vendors are advised to
prevent avoidable sensor list changes.
To ensure stable sensor handles, the HAL must deterministically map a given physical sensor in the device to its handle. Although no specific implementation is mandated by the Sensors HAL interface, developers have a number of options available to meet this requirement.
For example, the sensor list can be sorted using a combination of each sensor's
fixed attributes, such as vendor, model, and sensor type. Another option relies
on the fact that the device's set of static sensors is fixed in hardware, so the
HAL needs to know when all expected sensors have completed initialization before
returning from getSensorsList()
. This list of
expected sensors can be compiled into the HAL binary or stored in a
configuration file in the file system, and the order of appearance can be used
to derive stable handles. Although the best solution depends on your HAL's
specific implementation details, the key requirement is that sensor handles
don't change across HAL restarts.
Configure sensors
Before a sensor is activated, the sensor must be configured with a sampling
period and maximum reporting latency using the batch()
function.
A sensor must be able to be reconfigured at any time using batch()
without the
loss of sensor data.
Sampling period
The sampling period has a different meaning based on the sensor type that's being configured:
- Continuous: Sensor events are generated at a continuous rate.
- On-change: Events are generated no faster than the sampling period and may be generated at a rate slower than the sampling period if the measured value doesn't change.
- One-shot: The sampling period is ignored.
- Special: For more details, see Sensor types.
To learn about the interaction between a sampling period and a sensor's reporting modes, see Reporting modes.
Maximum reporting latency
The maximum reporting latency sets the maximum time in nanoseconds that events can be delayed and stored in the hardware FIFO before being written to the Event FMQ through the HAL while the SoC is awake.
A value of zero signifies that the events must be reported as soon as they're measured, either skipping the FIFO altogether, or emptying the FIFO as soon as one event from the sensor is present in the FIFO.
For example, an accelerometer activated at 50 Hz with a maximum reporting latency of zero triggers interrupts 50 times per second when the SoC is awake.
When the maximum reporting latency is greater than zero, sensor events don't need to be reported as soon as they're detected. Events can be temporarily stored in the hardware FIFO and reported in batches, as long as no event is delayed by more than the maximum reporting latency. All events since the previous batch are recorded and returned at once. This reduces the number of interrupts sent to the SoC and allows the SoC to switch to a lower power mode while the sensor is capturing and batching data.
Each event has a timestamp associated with it. Delaying the time at which an event is reported must not impact the event timestamp. The timestamp must be accurate and correspond to the time at which the event physically happened, not the time it was reported.
For additional information and requirements on reporting sensor events with nonzero maximum reporting latency, see Batching.
Activate sensors
The framework enables and disables sensors using the activate()
function.
Prior to activating a sensor, the framework must first configure the sensor
using batch()
.
After a sensor is deactivated, additional sensor events from that sensor must not be written to the Event FMQ.
Flush sensors
If a sensor is configured to batch sensor data, the framework can force
an immediate flush of batched sensor events by calling flush()
. This causes
the batched sensor events for the specified sensor handle to be immediately
written to the Event FMQ. The Sensors HAL must append a flush complete event
to the end of the sensor events that are written as a result of a call to
flush()
.
The flush happens asynchronously (that is, this function must return immediately). If the implementation uses a single FIFO for several sensors, that FIFO is flushed and the flush complete event is added only for the specified sensor.
If the specified sensor has no FIFO (no buffering possible), or if the FIFO was
empty at the time of the call, flush()
must still succeed and send a flush
complete event for that sensor. This applies to all sensors other than one-shot
sensors.
If flush()
is called for a one-shot sensor, then flush()
must return
BAD_VALUE
and not generate a flush complete event.
Write sensor events to the FMQ
The Event FMQ is used by the Sensors HAL to push sensor events into the Android sensor framework.
The Event FMQ is a synchronized FMQ, which means that any attempt to write more events to the FMQ than the available space allows results in a failed write. In such case, the HAL should determine whether to write the current set of events as two smaller groups of events or to write all of the events together when enough space is available.
When the Sensors HAL has written the desired number of sensor events to the
Event FMQ, the Sensors HAL must notify the framework that events are ready by
writing the EventQueueFlagBits::READ_AND_PROCESS
bit to the Event FMQ's
EventFlag::wake
function. The EventFlag can be created from the Event FMQ
using EventFlag::createEventFlag
and the Event FMQ's getEventFlagWord()
function.
The Sensors AIDL HAL supports both write
and writeBlocking
on the Event FMQ.
The default implementation provides a reference for using write
. If the
writeBlocking
function is used, the readNotification
flag must be set to
EventQueueFlagBits::EVENTS_READ
, which is set by the framework when it reads
events from the Event FMQ. The write notification flag must be set to
EventQueueFlagBits::READ_AND_PROCESS
, which notifies the framework that events
have been written to the Event FMQ.
WAKE_UP events
WAKE_UP
events are sensor events that cause the application processor (AP) to
wake up and handle the event immediately. Whenever a WAKE_UP
event is written
to the Event FMQ, the Sensors HAL must secure a wake lock to ensure that the
system stays awake until the framework can handle the event. Upon receiving a
WAKE_UP
event, the framework secures its own wake lock, allowing for the
Sensors HAL to release its wake lock. To synchronize when the Sensors HAL
releases its wake lock, use the Wake Lock FMQ.
The Sensors HAL must read the Wake Lock FMQ to determine the number of WAKE_UP
events that the framework has handled. The HAL should only release its wake lock
for WAKE_UP
events if the total number of unhandled WAKE_UP
events is zero.
After handling sensor events, the framework counts the number of events that are
marked as WAKE_UP
events and writes this number back to the Wake Lock FMQ.
The framework sets the WakeLockQueueFlagBits::DATA_WRITTEN
write
notification on the Wake Lock FMQ whenever it writes data to the Wake Lock FMQ.
Dynamic sensors
Dynamic sensors are sensors that aren't physically a part of the device but can be used as input to the device, such as a gamepad with an accelerometer.
When a dynamic sensor is connected, the onDynamicSensorConnected
function in
ISensorsCallback
must be called from the Sensors HAL. This notifies the
framework of the new dynamic sensor and allows the sensor to be controlled
through the framework and to have the sensor's events be consumed by clients.
Similarly, when a dynamic sensor is disconnected, the
onDynamicSensorDisconnected
function in ISensorsCallback
must be called so
that the framework can remove any sensor that is no longer available.
Direct channel
Direct channel is a method of operation where sensor events are written to
specific memory instead of to the Event FMQ bypassing the Android Sensors
Framework. A client that registers a direct channel must read the sensor events
directly from the memory that was used to create the direct channel and won't
receive the sensor events through the framework. The configDirectReport()
function is similar to batch()
for normal operation and configures the direct
report channel.
The registerDirectChannel()
and unregisterDirectChannel()
functions create
or destroy a new direct channel.
Operation modes
The setOperationMode()
function allows for the framework to configure a sensor
so that the framework can inject sensor data into the sensor. This is useful for
testing, especially for algorithms that exist below the framework.
The injectSensorData()
function is normally used to push operational
parameters into the Sensors HAL. The function can also be used to inject sensor
events into a specific sensor.
Validation
To validate your implementation of the Sensors HAL, run the sensor CTS and VTS tests.
CTS tests
Sensor CTS tests exist in both automated CTS tests and the manual CTS Verifier app.
The automated tests are located in cts/tests/sensor/src/android/hardware/cts. These tests verify standard functionality of sensors, such as activating sensors, batching, and sensor event rates.
The CTS Verifier tests are located in cts/apps/CtsVerifier/src/com/android/cts/verifier/sensors. These tests require manual input from the test operator and ensure that sensors report accurate values.
Passing the CTS tests is critical to ensuring that the device under test meets all CDD requirements.
VTS tests
VTS tests for the Sensors AIDL HAL are located in
hardware/interfaces/sensors/aidl/vts/.
These tests ensure that the Sensors HAL is implemented properly and that all
requirements within ISensors.aidl
and ISensorsCallback.aidl
are properly met.
Initialize the HAL
The initialize()
function must be supported to establish FMQs between the
framework and HAL.
Expose available sensors
In the Sensors AIDL HAL, the getSensorsList()
function must return the same value
during a single device boot, even across Sensors HAL restarts. A new requirement
of the getSensorsList()
function is that it must return the same value during
a single device boot, even across Sensors HAL restarts. This allows for the
framework to attempt to reestablish sensor connections if the system server
restarts. The value returned by getSensorsList()
can change after the device
performs a reboot.
Write sensor events to the FMQ
Instead of waiting for poll()
to be called, in the Sensors AIDL HAL, the Sensors
HAL must proactively write sensor events to the Event FMQ whenever sensor events
are available. The HAL is also responsible for writing the correct bits to
EventFlag
to cause an FMQ read within the framework.
WAKE_UP events
In Sensors HAL 1.0, the HAL was able to release its wake lock for any WAKE_UP
event on any subsequent call to poll()
after a WAKE_UP
was posted to
poll()
because this indicated that the framework had processed all sensor
events and had obtained a wake lock, if necessary. Because, in the Sensors AIDL
HAL, the HAL is no longer notified when the framework has processed events
written to the FMQ, the Wake Lock FMQ allows the framework to communicate to the
HAL when it has handled WAKE_UP
events.
In the Sensors AIDL HAL, the wake lock secured by the Sensors HAL for WAKE_UP
events must start with SensorsHAL_WAKEUP
.
Dynamic sensors
Dynamic sensors were returned using the poll()
function in Sensors HAL 1.0.
The Sensors AIDL HAL requires that onDynamicSensorsConnected
and
onDynamicSensorsDisconnected
in ISensorsCallback
be called whenever dynamic
sensor connections change. These callbacks are available as part of the
ISensorsCallback
pointer that is provided through the initialize()
function.
Operation modes
The DATA_INJECTION
mode for WAKE_UP
sensors must be supported.
Multi-HAL support
The Sensors AIDL HAL supports multi-HAL using the Sensors Multi-HAL framework. For implementation details, see Porting from Sensors HAL 2.1.