Zygote
Connectivity, location & sensorsintermediate

Sensors

A phone has a dozen tiny instruments sampling continuously. The interesting engineering is not reading them — it is fanning one hardware stream out to every app without waking the processor for each sample.

11 minAPI 1–37 · 17interactivequizverified 2026-10-27

Every phone contains a small laboratory: an accelerometer, a gyroscope, a magnetometer, a barometer, a light sensor, a proximity sensor, sometimes a heart-rate sensor and a step counter. None of them is interesting alone. What is interesting is that the platform must serve all of them to all apps, continuously, without destroying the battery.

TL;DR#

  • Sensors follow the same HAL pattern as the radios: chip → vendor HAL → native sensorservice → SensorManager → your callback.
  • sensorservice is a single native daemon that multiplexes every app onto one hardware stream.
  • Batching lets samples accumulate in a hardware FIFO while the processor sleeps — this is how step counting works with the screen off.
  • Sampling faster than 200 Hz requires HIGH_SAMPLING_RATE_SENSORS, a normal permission added in API 31.
  • Microphone and camera gained system indicators and global toggles in the same privacy wave as location; sensor access is governed by permissions and AppOps rather than by a dialog per reading.

Mental model#

Think of a building's utility meters.

Each flat (app) wants readings from the same physical meters (sensors). It would be absurd to install a separate gas meter for every flat. So the building has one set of meters, a meter room (sensorservice) that reads them, and a distribution system that delivers readings to each flat at the rate it asked for.

Batching is the meter room's trick: instead of phoning each flat every second, it writes a day's readings to a log and lets the flat collect them when it wakes up.

Where the analogy breaks#

A meter room is passive. sensorservice is not: it decides when to wake the application processor, how to combine requests from apps that want different rates, and when to flush a FIFO because a consumer is about to need the data. It is a scheduler, not a pipe.

The big picture#

Loading diagram…
Text description of this diagram

A five-stage pipeline. The sensor chip, often behind a low-power sensor hub, produces raw counts. The vendor sensor HAL converts them to the Android sensor event format and declares range, resolution, power and minimum delay, and owns hardware FIFO batching. The native sensorservice multiplexes every app onto one hardware stream, enforces rate limits, tracks wake locks and decides when to flush a batch. SensorManager in the app process owns the app's event queue and delivers events through the Looper of the thread that registered the listener. The app callback runs on that thread and must stay within the frame budget.

The pipeline is the same for an accelerometer and a heart-rate monitor. What differs is the rate, the power and whether the sensor is one-shot, on-change or continuous.

Deep dive#

The three sensor kinds#

Android groups sensors by how they report:

  • Continuous. Accelerometer, gyroscope, magnetometer. They produce a stream at a requested rate.
  • On-change. Proximity, significant motion. They report only when something changes.
  • One-shot. A single event, such as a step-detection trigger or a sensor's first reading.

The distinction matters because it changes what a rate parameter means. For a continuous sensor, the rate is a sampling frequency. For an on-change sensor, the rate is a floor: the platform will not deliver more often than you asked, but it may deliver much less.

The HAL contract#

The sensor HAL declares, for every sensor it exposes:

  • a type (accelerometer, gyroscope, and so on), with vendor-specific types allowed,
  • a maximum range and resolution,
  • a power figure in milliamps,
  • a minimum delay between samples,
  • a FIFO size, if it supports batching,
  • whether it is a wake-up sensor (allowed to wake the AP) or a non-wake-up sensor.

That declaration is the contract. An app that asks for a rate faster than minDelay gets the minimum; one that asks for a rate the sensor cannot sustain silently gets a slower stream. Nothing throws.1

Multiplexing: one stream, many subscribers#

The hardware produces one stream. Multiple apps may want it at different rates. sensorservice solves this by:

  1. Choosing a hardware rate that satisfies the fastest subscriber.
  2. Delivering to each subscriber at its own requested rate, by decimating the stream.
  3. Holding a wake lock only while a wake-up subscriber needs one.
  4. Flushing FIFOs when a batch consumer's deadline approaches.

That is why two apps reading the accelerometer do not double the power cost — the hardware still runs at one rate. It is also why one badly behaved app that requests the maximum rate can affect the whole device's battery.

Batching, and how step counting works asleep#

Batching is the key mechanism behind the "your phone counted your steps while it was in your pocket" experience. The sensor hub or the sensor's FIFO accumulates events while the AP is suspended. When the AP wakes for any reason — a notification, an alarm, a call — sensorservice drains the FIFO and delivers the accumulated events.

The important consequence: you do not get real-time delivery while asleep, and you should not need it. An app that wants per-step timestamps gets them, batched. An app that wants "tell me when the user has walked 1,000 steps" should use a step-counter sensor with a batch deadline rather than waking for each step.

Rate limits and the 200 Hz permission#

Until API 31, an app could request any rate the hardware supported. That is a battery and side-channel problem: a high-rate accelerometer can be used to infer keystrokes or detect nearby speech through vibration.

API 31 added HIGH_SAMPLING_RATE_SENSORS, a normal permission required for rates above 200 Hz. It is granted at install, so it is not a user-facing dialog — but it is visible in the app's declared permissions, and apps that do not need high rates should not ask.2

Permission model: body sensors and activity recognition#

Most sensors need no permission at all. The accelerometer is not considered sensitive: it is used by every game and every step counter.

Two categories are different:

  • Body sensors (BODY_SENSORS, API 20) cover sensors that measure what is happening inside the body: heart rate, blood oxygen. This is a dangerous runtime permission.
  • Activity recognition (ACTIVITY_RECOGNITION, API 29) covers detecting walking, running, cycling and similar. Also dangerous.

The distinction is deliberate: the platform is not protecting the raw signal, it is protecting the inference about the person.

Microphone and camera are not sensors here#

It is tempting to lump the microphone and camera into "sensors", and at the HAL level they are adjacent. In Android's permission model they are separate: RECORD_AUDIO and CAMERA are dangerous permissions with their own runtime dialogs, and since API 31 they have system indicators and global toggles.

The reason to mention them here is that the pattern is the same as location: the platform increasingly separates "the app holds a permission" from "the user can see that it is being used right now".

How it evolved#

Permission changes7 releases
APIVersionWhat changed
184.3 Jelly Bean
  • App Ops (hidden) introduced for permission control
236.0 Marshmallow
  • requestPermissions() and the runtime permission flow
289 Pie
  • Foreground service permission
3011
  • One-time permissions
3112
  • Bluetooth scan/connect permissions
3313 Tiramisu
  • POST_NOTIFICATIONS runtime permission
3717 Cinnamon Bun
  • ACCESS_LOCAL_NETWORK runtime permission for local network access
2008–2011Raw accessA handful of sensors, direct rates, no batching.API 1
2013 →BatchingHardware FIFOs and sensor hubs make always-on sensing practical.API 19
2014 →Body sensorsHeart rate and similar get a runtime permission.API 20
2021 →High-rate gateAbove 200 Hz needs a declared permission.API 31

Under the hood#

Curiosity corner#

  • The accelerometer measures proper acceleration, not motion. A phone at rest on a table reports about 9.81 m/s² upward — that is gravity, not movement. This is why detecting free fall means looking for near zero, not for a large value.
  • The gyroscope drifts. Integrating angular velocity to get orientation accumulates error within seconds, which is why sensor fusion uses the accelerometer and magnetometer to correct it.
  • Proximity sensors are usually infrared. A phone call turns the screen off because an IR sensor sees your cheek, not because the phone knows you are on a call.

Try it#

List the sensors and read one

adb shell dumpsys sensorservice | head -60 adb shell cmd sensorservice get-sensor-list

Example output
Sensor List:
0x00000000) LSM6DSO Accelerometer | vendor: ST | version: 1 | type: android.sensor.accelerometer
maxRange: 39.2 | resolution: 0.002 | power: 0.15 | minDelay: 5000 | fifoMaxEventCount: 3000
...
accelerometer: x=-0.12 y=9.79 z=0.44 ts=123456789

The power and fifoMaxEventCount fields in the list are the ones that determine whether batching is worth using: a sensor with a large FIFO can hold minutes of samples, and one with zero cannot batch at all.

Check yourself#

Check yourself

1 / 12

Which component decides which network an app's socket should use?

0 answered · 0 correct

Sources#

Sources

Every version number, API level, class name and date on this page is traced to one of these. Pages are re-verified against them; last_verified above says when.

  1. docsSensorssource.android.comaccessed 2026-10-27↩
  2. docsManifest.permission | API referencedeveloper.android.comaccessed 2026-10-27↩
  3. docsSensors overviewdeveloper.android.comaccessed 2026-10-27↩
  4. docsBehavior changes: Apps targeting Android 12developer.android.comaccessed 2026-10-27↩
  5. docsPerubahan perilaku: aplikasi yang menargetkan API level 28+developer.android.comaccessed 2026-10-27↩