N04 — A toy HAL
An AIDL HAL in the modern shape: an interface with VINTF stability, a service that implements it, a manifest fragment that declares it, and a client that finds it. The vendor boundary, built by hand.
A HAL is where the platform stops trusting the vendor and starts negotiating with it. The interface is a contract; the manifest is the declaration of what a device actually implements; the service is one process talking to another over Binder. Build one small one and the Treble split stops being an org chart and becomes a directory layout.1
Hardware note: this needs a platform build and a boot, plus ideally a vendor image you control. The build sequence itself is the one from N01, which follows the AOSP build documentation.2
TL;DR#
- HALs are AIDL now. HIDL is deprecated as of Android 13; new HALs use AIDL.3
- The interface is an
.aidlfile annotated@VintfStability, with anaidl_interfacemodule that setsstability: "vintf". - The service is a process that registers its binder with the service manager.
- The VINTF manifest declares it, so the framework knows the device provides it.
- The boundary is enforced at runtime: a HAL not in the manifest is not supposed to be used.
What you are building#
One interface with one method, implemented by one service, declared in one manifest fragment, and called by a client that looks the service up by instance name. The feature is a string; the lesson is the four artefacts and how they must agree.
The four artefacts#
| Artefact | Lives in | Fails if wrong |
|---|---|---|
| The interface | an .aidl file in a hardware/interfaces-style package | the client and server disagree on the transaction |
| The build declaration | Android.bp with aidl_interface | the interface is not compiled for vendor, or not stable |
| The service | a binary that implements the interface and registers it | the client cannot find it |
| The VINTF fragment | an XML manifest fragment | the platform does not believe the device has the HAL |
Each of the four is checked separately, and each failure has a different symptom. That is the reason to build one.
Steps#
- Choose the interface package
Stable AIDL interfaces for HALs live in
4aidlfolders in the same base directories as the old HIDL interfaces;hardware/interfacesis the one for interfaces typically provided by hardware, andframeworks/hardware/interfacesandsystem/hardware/interfacesexist for the other cases.The package name follows the usual AIDL rules. Pick a package under your own namespace, for example
android.hardware.toy, so you are not claiming a Google-owned package.You should seeA directory under a hardware interfaces root. - Write the interface
Declare one method returning a string. Every type definition must be annotated
@VintfStability, and theaidl_interfacedeclaration must includestability: "vintf"— both requirements come from the AIDL-for-HALs page.4The annotation is the promise that this interface will not change incompatibly. It is what makes the interface usable across the vendor boundary.
You should seeA compilable .aidl file. - Declare the interface in Android.bp
The following is illustrative, modelled on AOSP's vibrator HAL definition:
aidl_interface { name: "android.hardware.toy", vendor_available: true, stability: "vintf", srcs: [ "android/hardware/toy/*.aidl", ], backend: { cpp: { enabled: true, }, }, }The real
4android.hardware.vibratormodule setsvendor_available: trueandstability: "vintf", and it enables the backends it needs while disabling the ones it does not.vendor_availableis what makes the interface usable from vendor code.You should seeThe build generates the stubs and the stability metadata. - Implement the service
Implement the generated interface in the server language you enabled in the backend, and register the binder. AIDL HAL services conventionally use an instance name of the form
$package.$type/$instance— the vibrator HAL, for example, is declared asandroid.hardware.vibrator.IVibrator/default.4If the interface is
@VintfStability, the service must be declared in the VINTF manifest; an ordinary AIDL service registers normally and does not need one. You are building the first kind.You should seeA binary that registers a binder under the right instance name. - Add the VINTF manifest fragment
A HAL entry in a device manifest has this shape, quoted from the AIDL-for-HALs page:
<hal format="aidl"> <name>android.hardware.toy</name> <version>1</version> <fqname>IToy/default</fqname> </hal>fqnameis the interface name and the instance, andnameis the package. The device manifest itself is read from locations such as/vendor/etc/vintf/manifest.xmland/odm/etc/vintf/manifest.xml.5The fragment you ship usually lives in the device or vendor tree and is installed into one of those locations or merged into the manifest at build time. Check the VINTF manifest page for the merge mechanism your release uses rather than assuming a single file.
You should seeThe manifest parses and names your HAL. - Start it at boot
A HAL is a service like any other: it needs an init service block, a
user/group, aseclabel, and a start trigger. Everything from N03 applies.You should seeThe service process exists. - Allow the client to find it
Two SELinux questions, not one: is the client allowed to
findthe service by name in the service manager, and is the HAL domain allowed toaddit? A missing rule appears asavc: deniedwith theservice_managerclass.6Policy lives under your device's
sepolicydirectory and is wired in withBOARD_SEPOLICY_DIRS.You should seeNo avc denial when the client calls. - Build, boot and call it
Build and boot your target, then check that the service is registered and the manifest lists it. The exact build and boot commands are those of N01.
You should seeThe client gets the string back.
adb shell service list | grep toy
adb shell dumpsys -l | grep toy
adb shell dmesg | grep avcExample output
Illustrative — names and output differ.The first command lists registered binder services. dumpsys -l lists the service names dumpsys
knows about; a HAL only appears there if it implements dumping, so an empty result is not a failure.
The third is the one that finds policy problems.
The files you touched#
- stable AIDL HAL interfaces live in aidl folders here, alongside the HIDL ones
- Android.bpa real aidl_interface with vendor_available and stability: vintf
- the base policy; read it, do not edit it
- where the service_manager rules for your HAL go
Verification#
Three checks that fail independently:
adb shell service listshows the instance — the service started and registered.- The device manifest on the device lists the HAL — the VINTF fragment was installed.
- The client's call returns — the interface version, the manifest and the client agree.
If 1 passes and 2 fails, the framework will refuse to use the HAL even though it is running. That gap is the whole point of VINTF: a running service is not a supported device.
What can go wrong#
- The interface is not stable. Missing
stability: "vintf"or a missing@VintfStabilityannotation makes the HAL unusable across the boundary. vendor_availableis missing. Framework code can see the interface; vendor code cannot, and the build fails or the service cannot be built into the vendor image.- The manifest does not match the interface. A version or
fqnamemismatch means the device advertises something the service does not implement. - The fragment is in the wrong place. Manifests are read from specific paths; a fragment that is not merged or installed is invisible.
- SELinux denies the lookup. The client cannot find the service, so it looks like the service is not running.
- You copied a HIDL example. HIDL is deprecated and its
.halfiles,hidl_interfacemodules andhwservicemanagerregistration are a different mechanism. New HALs use AIDL. - The package name collides. Using
android.hardware.<something>that Google owns will conflict with the interfaces already in the tree.
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.
- docsHardware abstraction layers (HALs)source.android.comaccessed 2026-10-27↩
- docsBuild Androidsource.android.comaccessed 2026-10-27↩
- docsHAL typessource.android.comaccessed 2026-10-27↩
- docsAIDL for HALssource.android.comaccessed 2026-10-27↩
- docsVendor interface objects (VINTF)source.android.comaccessed 2026-10-27↩
- docsSELinuxsource.android.comaccessed 2026-10-27↩