Overview of SensorService
SensorService is the central component in the Android Open Source Project (AOSP) that manages all sensor operations. Residing within the system_server process, it bridges the gap between hardware abstraction (Sensor HAL) and the application framework. Its primary responsibilities include managing concurrent client connections, multiplexing sensor data streams, enforcing power management policies, and facilitating high-speed data delivery via shared memory constructs like BitTube.
SensorService Connection Handling
When an application requests sensor data via SensorManager, the framework establishes a connection to SensorService through Binder IPC. Each client connection is encapsulated within a SensorEventConnection object.
The Connection Lifecycle
- Client Request: The application calls
SensorManager.registerListener(). - Binder IPC: The request crosses the process boundary to
SensorService::createSensorEventConnection(). - Connection Object: A new
SensorEventConnectionis instantiated, acting as the dedicated context for the client. - Registration: The connection registers the requested sensor, specifying parameters like sampling rate and reporting latency.
// frameworks/native/services/sensorservice/SensorService.cpp
sp<ISensorEventConnection> SensorService::createSensorEventConnection(
const String8& packageName, int requestedMode, const String16& opPackageName) {
// ... validation and permission checks ...
sp<SensorEventConnection> result(new SensorEventConnection(this, uid, packageName,
requestedMode == RESTRICTED, opPackageName));
return result;
}
The SensorEventConnection maintains a mapping of all sensors active for a specific client, managing their individual requested rates and batching parameters.
Sensor Data Delivery via BitTube
A critical performance bottleneck in sensor management is the overhead of delivering high-frequency sensor events across process boundaries. Relying purely on standard Binder transactions for every accelerometer or gyroscope reading would overwhelm the system. AOSP solves this using BitTube, a high-performance IPC mechanism based on shared memory and Unix domain sockets.
BitTube Architecture
A BitTube creates a unidirectional data channel. Internally, it pairs a socketpair for signaling with a fast path for data transfer.
- Initialization: When a
SensorEventConnectionis created, aBitTubeis allocated. The client receives the read end of the tube (a file descriptor). - Writing Data:
SensorServicewrites arrays ofsensors_event_tdirectly into theBitTube. - Reading Data: The client's
Looperwakes up when data is available on the file descriptor and reads the events natively.
// frameworks/native/libs/sensor/BitTube.cpp
ssize_t BitTube::write(const void* vaddr, size_t size) {
ssize_t err, len;
do {
len = ::send(mSendFd, vaddr, size, MSG_DONTWAIT | MSG_NOSIGNAL);
err = len < 0 ? errno : 0;
} while (err == EINTR);
return err == 0 ? len : -err;
}
This design allows for zero-copy or minimal-copy data transfer, easily handling thousands of events per second without saturating the Binder thread pool.
Rate and Batching Management
Multiple applications often request data from the same physical sensor but at different rates. SensorService must multiplex these requests efficiently.
Rate Multiplexing
If Client A requests the accelerometer at 50Hz and Client B requests it at 200Hz, SensorService configures the Sensor HAL to stream at 200Hz. It then delivers events to Client B at 200Hz, while down-sampling or selectively dropping events to deliver approximately 50Hz to Client A.
Hardware Batching (FIFO)
To save battery, modern sensors include hardware FIFOs. This allows the Application Processor (AP) to sleep while the sensor hub accumulates data. SensorService calculates the maximum allowable latency across all clients and configures the HAL accordingly.
// frameworks/native/services/sensorservice/SensorDevice.cpp
status_t SensorDevice::batch(void* ident, int handle, int flags,
int64_t samplingPeriodNs, int64_t maxBatchReportLatencyNs) {
// ... aggregate requested parameters across all clients ...
// Configure the HAL with the tightest constraints
return mSensors->batch(handle, samplingPeriodNs, maxBatchReportLatencyNs);
}
If a client specifies a maxBatchReportLatencyNs of 5 seconds, the AP can remain in deep sleep for up to 5 seconds before waking up to process the queued events.
Power State Management
SensorService plays a vital role in device power management by coordinating with PowerManagerService and the SuspendManager.
Wake-up vs. Non-wake-up Sensors
Sensors are classified into two categories:
- Non-wake-up sensors: Do not prevent the System on Chip (SoC) from going to sleep. Events are buffered in the FIFO or lost if the FIFO overflows while asleep.
- Wake-up sensors: Force the SoC to wake up when an event occurs (e.g., proximity sensor, significant motion).
When a wake-up sensor event is triggered, SensorService acquires a partial wakelock to ensure the AP stays awake long enough for the client application to receive and process the event.
// Example dumpsys command to inspect SensorService state
// adb shell dumpsys sensorservice
The output of dumpsys sensorservice provides invaluable debugging information, including active connections, requested sensor rates, FIFO allocations, and wakelock statistics.
// Sample dumpsys output snippet
Active sensors:
Accelerometer (handle=0x00000001, connections=2)
connection 1: rate=200Hz, batch=0ms
connection 2: rate=50Hz, batch=2000ms
By intelligently managing connections, rates, and power states, SensorService ensures that Android devices can support rich, sensor-driven experiences without severely degrading battery life.