Zygote
HALs, Treble & Mainlinebeginner

What a HAL is

A hardware abstraction layer is a contract between the framework and a piece of hardware. It says what you can ask for, not how the chip does it — and that distinction is worth billions of dollars of hardware support.

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

A camera is a sensor, a lens, an actuator and a bus. The Android framework does not want to know about any of that. It wants to say "give me a preview at 1080p" and get frames back. The thing in between is a HAL.

TL;DR#

  • A HAL is the contract between the framework and hardware. It describes operations, not implementations.
  • Before Android 8.0, a HAL was usually a shared library dlopened into the framework process, reached through a C struct of function pointers.
  • After Android 8.0, a HAL is usually a separate process reachable over , described in (or historically ).
  • The HAL exists because the vendor writes it and Google cannot. Standardising the boundary is what lets one framework ship on hundreds of different camera sensors.
  • Every HAL is declared in a manifest, so the phone can verify at boot that the pieces it has match the pieces it needs.

Mental model#

Think of a wall socket.

You do not need to know whether the electricity comes from a hydro dam or a gas turbine. You need to know that the socket takes a plug of a particular shape and delivers a particular voltage. The socket is the interface; the power station is the implementation.

A HAL is a wall socket for hardware. The camera HAL is the socket; the sensor driver and the ISP firmware are the power station.

Where the analogy breaks#

Wall sockets are standardised by committees over decades. Android has several generations of socket at once, and the shape changed underneath the appliance twice: once when HALs moved from in-process libraries to Binder services (Android 8.0), and once when the interface language moved from HIDL to AIDL (from Android 11 onward, with HIDL deprecated as of Android 13). A device can have all of these at once, which is why "the HAL" is not one thing.

The big picture#

Loading diagram…
Text description of this diagram

A side-by-side comparison. On the left, the pre-Android-8.0 arrangement: the app calls the framework, the framework dlopens a vendor shared library into its own address space, and that library makes ioctls to the driver. There is no version in the call and no separate process. On the right, the post-Treble arrangement: the app calls the framework, the framework checks a VINTF manifest and compatibility matrix, then makes a Binder call to a HAL service running in its own process, which makes the same ioctls. The right-hand side allows the system image and the vendor image to be updated independently.

Deep dive#

The legacy HAL: a struct of function pointers#

Before Android 8.0, the HAL interface was defined by hardware/libhardware. A HAL was a shared object with a known name, and the framework loaded it at runtime.

The mechanism was a C struct with a magic number and a version, plus a device struct with function pointers.1 The framework called hw_get_module() with a module ID, got back a hw_module_t, called its open() method, and received an hw_device_t whose function pointers were the actual operations.

Three properties followed from that design, and all three were problems:

  • Same address space. The vendor library ran inside the framework's process. A crash in the vendor code crashed the framework; a memory bug in the vendor code could corrupt framework state.
  • No version in the call. The contract was the C header. If the header changed, the caller had to be recompiled. There was a version field in the struct, but it was a coarse integer, not a negotiated interface.
  • No enumeration. A HAL existed if its .so was on the system. There was no way to ask the device "what HALs do you have" and get a structured answer.

The modern HAL: a process and an interface#

The modern HAL keeps the same idea — a contract — and changes the transport and the description.

The transport is Binder. A HAL service is a process, started by init, that registers itself with a service manager under a name. The framework looks up the name and gets a proxy.

The description is an interface definition language. HIDL was the first, introduced with Treble. AIDL, which already existed for app-to-framework IPC, became the recommended language for HALs and is now the only one for new work.

The consequences are the mirror image of the legacy problems:

  • Separate address space. A HAL crash is a process death. The service is restarted.
  • Version in the name. android.hardware.camera.provider@2.4 is not the same interface as @2.5, and both can exist.
  • Enumeration. The VINTF manifest declares exactly which HALs the device provides.

What a HAL interface looks like#

A modern HAL is an AIDL interface in a package under hardware/interfaces. The package name encodes the domain, and the interface name encodes the capability:

hardware/interfaces/vibrator/aidl/android/hardware/vibrator/IVibrator.aidl

The instance name a client looks up is the package, the interface and the instance, joined with dots and a slash:

android.hardware.vibrator.IVibrator/default

The framework asks for that name, gets a proxy, and calls getCapabilities(), on(), off(). It does not know whether the implementation is a tiny motor driver or a haptic engine with a DSP.

The four HALs you have already used#

Even if you have never written a HAL, you have depended on four of them.

HALWhat the framework asksWho implements it
CameraOpen a device, configure a stream, submit capture requests, receive resultsThe SoC vendor's camera provider
AudioOpen an output stream, write PCM, set volume and routingThe SoC's audio HAL, often with a DSP
SensorsEnable a sensor, set a rate, receive eventsThe sensor hub firmware, via a HAL
Graphics composerCompose these layers onto this displayThe display controller driver

Each of these is a place where the framework's behaviour is fixed and the hardware's behaviour is not. That is the entire justification for the abstraction.

Costs#

A HAL boundary is not free, and pretending otherwise makes the design hard to reason about.

  • Latency. A Binder transaction is microseconds, not nanoseconds. For a sensor at 200 Hz, one transaction per sample would be absurd, which is why sensor data flows through shared memory and the service is a control plane.
  • Complexity. A HAL needs a process, an .rc file, a SELinux domain, a VINTF entry and a service registration. The legacy .so needed a makefile rule.
  • Versioning discipline. Once an interface is published it cannot change incompatibly. That constrains the vendor as much as the platform.

The trade is deliberate: the platform pays complexity once so it does not pay a fork per device.

Lifecycle: HALs can sleep#

A HAL process that is always running costs memory even when nothing is using the camera. Modern Android lets HALs be lazy: the service starts on first request and exits when it has no clients.

The mechanism is documented in the dynamic lifecycle page: a HAL declares that it should not start automatically, hwservicemanager starts it when a client asks for an unregistered service, and the HAL uses a registrar that tracks client references so it can shut down when the last one goes away. The API is LazyServiceRegistrar for HIDL; AIDL HALs have an equivalent.3

How it evolved#

The updatability story9 releases
APIVersionWhat changed
11.0
  • Initial AOSP platform: Linux kernel, Dalvik VM, core libraries
174.2 Jelly Bean
  • SELinux enforcement begins in the kernel (behind the scenes)
194.4 KitKat
  • Kernel moved under a tighter vendor control
236.0 Marshmallow
  • Fingerprint HAL
247.0 Nougat
  • Project Treble groundwork
268.0 Oreo
  • Project Treble: the vendor interface separates vendor and system code
  • HIDL for HALs
289 Pie
  • Mainline groundwork
2910
  • Project Mainline: APEX and updatable system modules
  • Project Mainline starts shipping through Play
3011
  • GKI: the Generic Kernel Image splits the kernel into core + vendor modules

The arc is: in-process library (2008–2017), binderized and versioned (2017–2020), AIDL and lazy (2020 onward). Each step moved more of the contract into something machine-checkable — a header, then a .hal file, then an .aidl file with @VintfStability.

Under the hood#

Curiosity corner#

  • The same physical camera can appear as several logical cameras. The camera HAL exposes them; the framework has no idea they share a sensor.
  • A HAL does not have to be written by the hardware vendor. Some are written by Google or by the OEM, especially where the hardware is standard (a vibrator, a light).
  • The audio HAL is one of the oldest surviving interfaces. Its shape has changed far less than the camera's, because audio hardware has changed far less.

Try it#

List the HAL services on a device

adb shell service list | grep "android.hardware" adb shell dumpsys -l | grep -i hal

Every line you see is a HAL that has registered with a service manager. The android.hardware.* prefix is the convention that makes them identifiable.

Check yourself#

Check yourself

1 / 12

What was the core technical barrier that kept Android phones on old software before 2017?

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. docsHardware abstraction layers (HALs)source.android.comaccessed 2026-10-27↩
  2. docsHAL typessource.android.comaccessed 2026-10-27↩
  3. docsHAL dynamic lifecyclesource.android.comaccessed 2026-10-27↩
  4. docsHIDLsource.android.comaccessed 2026-10-27↩
  5. docsAIDL for HALssource.android.comaccessed 2026-10-27↩
  6. docsVendor interface objects (VINTF)source.android.comaccessed 2026-10-27↩
  7. docsAndroid Compatibility Definition Document (CDD)source.android.comaccessed 2026-10-27↩