Branches, GKI and the KMI
For years every phone shipped a different kernel, and a security fix could take years to arrive. GKI made the kernel a single signed binary and moved board support into loadable modules behind a frozen interface.
There is a version of Android's kernel problem that fits in one sentence: a phone's kernel used to be as unique as its fingerprint. Every SoC vendor forked the Android kernel, added board support, added drivers, added fixes, and shipped. When a CVE landed in Linux, someone had to port it into every fork, on every branch, for every device still supported. Often nobody did.
GKI is the fix, and it is one of the most consequential changes Android has ever made. It is also widely misunderstood, because it is usually described as "one kernel for all devices", which is not quite true. It is one binary for a given kernel version and architecture, with everything device-specific moved into modules that load into it.
TL;DR#
- An ACK (Android Common Kernel) is a Linux LTS release plus Android's patches. Branches are named for the Android release and kernel version together:
android14-6.1is the 6.1 branch used by Android 14. - GKI 1.0 arrived with Android 11 on 5.4 kernels. GKI 2.0 arrived with Android 12 on 5.10, and from Android 12 onward devices shipping with 5.10 or higher must ship the GKI kernel.
- GKI splits the kernel into a core (hardware-agnostic, built from ACK) and vendor modules (SoC and board support). The two sides meet at the , a stable symbol interface.
- The KMI is stable only within one LTS and one Android release, and only for symbols on the published list. Modules that need anything else fail to load.
- A KMI version looks like
5.4-android12-0: kernelw.x, Android release, and a generation counter. The patch levelyis deliberately not part of it.
Mental model#
Think about USB.
Before USB, every device had its own connector and its own driver. A new mouse meant a new driver, and a new OS version meant rewriting every driver. The interface was the product: once the socket was standard, devices and computers could evolve independently.
The KMI is a USB socket for kernel modules. The kernel side of the socket is frozen: a specific set of function and data symbols with specific signatures, published by Google and checked mechanically on every build. A vendor's camera driver plugs into that socket. It does not care which sublevel of 6.1 is running, and the kernel does not care which camera it is driving.
The difference from USB is that the socket is frozen per kernel version, not forever. 6.1's socket and 6.6's socket are different sockets. A module built for one will not fit the other.
Where the analogy breaks#
USB devices are hot-pluggable and forgiving. Kernel modules are neither. A module that calls a symbol outside the KMI does not degrade gracefully — the load fails, and on a phone that can mean a camera that does not exist. There is no fallback path and no partial compatibility.
The other break: USB has a single standards body. GKI has Google as the gatekeeper, with the AOSP Clang toolchain and a single gki_defconfig as the only permitted build configuration. It is a standard, but it is a standard with an owner, and that owner changes it when a security fix requires it.
The big picture#
Text description of this diagram
A timeline from 2013 to 2026 with three lanes: Android release, common kernel branch, and the GKI era. Android 4.4 in 2013 ran on kernel 3.4; Android 6.0 in 2015 on 3.18; Android 8.0 in 2017 on 4.4, the same year Treble split vendor from system; Android 10 in 2019 spanned 4.9 and 4.14. GKI 1.0 appears in 2020 with Android 11 on 5.4, and GKI 2.0 in 2021 with Android 12 on 5.10. The common kernel lane then shows android13-5.15 in 2022, android14-6.1 in 2023, android15-6.6 in 2024, android16-6.12 in 2025 and android17-6.18 in 2026. The pattern is that the platform release and the kernel release become independent choices.
The shape of that timeline is the whole argument. Before 2020, the two upper lanes move together: a new Android release brings a new kernel, and the kernel is whatever the vendor forked. After GKI, the lower lanes separate: the platform picks a kernel branch, the vendor picks modules, and neither has to match the other's patch level.
Deep dive#
The branch naming scheme#
An ACK branch is named android<release>-<kernel>. android14-6.1 is the 6.1 kernel for Android 14. That naming is doing real work: it says the branch is a supported combination, not an arbitrary pairing of a platform and a kernel.1
Two branches are special. android-mainline is the development branch, where Android's kernel work lands first and into which Linus Torvalds' releases are merged. New ACK branches are cut from it when an upstream LTS is declared. android12-5.10 and friends are the long-term support branches that devices actually ship.2
The support window is not indefinite, and it shrank recently:
| Branch | Kernel | Support lifetime |
|---|---|---|
android12-5.10 | 5.10 | 6 years |
android13-5.15 | 5.15 | 6 years |
android14-6.1 | 6.1 | 6 years |
android15-6.6 | 6.6 | 4 years |
android16-6.12 | 6.12 | 4 years |
android17-6.18 | 6.18 | 4 years |
From 6.6 onward the lifetime is four years rather than six, which tracks the shortening maintenance window of upstream LTS kernels. For a phone this matters: it means the kernel branch a device ships with will go out of support before a seven-year update commitment runs out, which is one reason devices get kernel upgrades during their life — the Pixel line has done this repeatedly — rather than staying on the kernel they launched with.
What GKI actually splits#
GKI divides the kernel into two halves.
The core kernel is built from ACK, contains no SoC-specific or board-specific code, and is identical across devices on the same branch. It provides scheduling, memory management, the driver core, filesystems, networking, and the KMI.
Vendor modules are loadable .ko files built by the SoC vendor or the ODM. They provide board support: the display controller driver, the camera sensor drivers, the touch controller, the modem interface. They are loaded into the GKI kernel at boot.
A third category exists too: GKI modules, which are modules built as part of the GKI build itself.3 They are signed by Google with the kernel's build-time key and are only compatible with the exact GKI they were built with — there is no ABI stability between the GKI and its own modules, so the two are always updated together.4
That last point is worth pausing on, because it is the exception that proves the rule. The KMI stabilises the interface between the kernel and vendor modules. It says nothing about the interface between the kernel and its own bundled modules, because those are rebuilt whenever the kernel is.
The KMI in detail#
The KMI is a list of symbols: functions and global data that vendor modules are allowed to use. It is not the whole kernel symbol table. Modules may use only KMI symbols, and the kernel enforces this by failing to load a module that requires anything else.5
Stability has hard boundaries:
- Same LTS and same Android release.
5.10-android13-0modules do not load on a 5.15 kernel, and a module for one Android release is not guaranteed on another. - No stability on
android-mainline. The development branch is explicitly excluded. - One build configuration. Only
gki_defconfigbuilds the kernel. Changing the config can change the KMI, so the config is frozen along with the symbols. - One toolchain. The AOSP-supplied Clang for that branch must be used, and the vendor's module toolchain must be compatible with it.
Changes are still allowed after the branch is frozen — config changes, code changes, even toolchain updates — but none of them may remove or alter a KMI symbol. That is what "frozen" means here: not that the code stops changing, but that the interface does.
Module loading at boot#
Modules live on read-only partitions and are loaded by init in a single pass. The paths are specific and worth knowing:
| Module type | Location |
|---|---|
| GKI modules | /system/lib/modules, a symlink to /system_dlkm/lib/modules |
| SoC vendor modules | /vendor/lib/modules |
| ODM modules | /odm/lib/modules when an ODM partition exists |
| Recovery modules | /lib/modules in the recovery ramfs |
Init invokes modprobe -a with a directory, which loads every module in dependency order. On modern devices this happens on the early-init trigger so the drivers exist before anything tries to use them.4
- init.rcthe boot triggers that start HALs and core services
- service.cpphow init launches and restarts a service
- first_stage_mount.cppmounting the partitions before /system exists
The android12-5.10 compatibility trick#
Devices that launched on Android 11 with a 5.4 kernel were the awkward middle generation. GKI 1.0 existed, but the boot image was not Google-signed and the split was less complete than 5.10's.
The scheme that followed is instructive: those devices could upgrade to Android 12 while staying on the 5.4 kernel, or move to the android12-5.10 branch and get GKI 2.0 proper. Either path was legitimate. What was not allowed was a device shipping Android 12 on kernel 5.10 without GKI. From that point the kernel binary is not the vendor's to modify.
Version strings, decoded#
A GKI kernel reports a version string in a fixed shape:
5.4.42-android12-0-00544-ged21d463f856Reading left to right: kernel release 5.4.42, Android release android12, KMI generation 0, build number, and the git commit. The corresponding KMI version drops the patch level and the build metadata:
5.4-android12-0That truncation is the whole design. The sublevel (42) changes constantly with stable updates, and a vendor module must not care. The KMI version changes only when the interface does — which, within a branch, is essentially never, except when a security fix forces the generation counter to increment.6
A corollary worth remembering: an OTA may not decrease the KMI version or the sublevel. If a device is on sublevel 42, an update to sublevel 40 is refused. Downgrades are how attackers reintroduce fixed vulnerabilities.
Where GKI stops#
GKI does not make the kernel universal. It makes it reproducible and independently updatable. The vendor still writes board support; it just writes it as a module rather than as a patch. The kernel still has to be built for a specific architecture (arm64, mostly), and a device with unusual hardware still needs vendor code to drive it.
What GKI bought is a supply chain. Google can build, sign and ship a GKI kernel with a security fix, and a device can take it without the vendor rebuilding their entire kernel tree. Everything else in the modularity story — Treble for the HAL boundary, Mainline for framework modules — follows the same logic of finding a seam and freezing it.7
How it evolved#
The timeline above compresses four distinct eras. It is worth naming them.
2008–2012: the wild west. Each device ran a vendor fork with no common base. Android's kernel patches lived in the kernel's staging tree.
2013–2016: the common kernel. ACK gave devices a shared starting point, but vendors still patched the kernel itself heavily. Out-of-tree code could be a large fraction of the kernel on a shipping device.
2017–2019: Treble, then the kernel. Treble split vendor from system at the HAL boundary in Android 8.0, and loadable modules became mandatory for SoC kernels the same year. That was the necessary precondition for GKI: you cannot move board support into modules if the build never produced modules.
2020 onward: GKI. GKI 1.0 with Android 11 on 5.4; GKI 2.0 with Android 12 on 5.10 and mandatory for new devices at that version or higher.
| API | Version | What changed |
|---|---|---|
| 26 | 8.0 Oreo |
|
| 28 | 9 Pie |
|
| 29 | 10 |
|
| 30 | 11 |
|
Under the hood#
- lmkd.cppa daemon whose behaviour depends on which kernel branches are in use
- first_stage_init.cppwhere module loading begins, before /system is mounted
- apexd.cppthe same modularity idea, applied to user-space components
Curiosity corner#
- The KMI generation counter exists for security fixes. It is normally
0. It increments only when a fix cannot be backported without changing the interface, which is a break-glass situation rather than a routine one. - A module built against the wrong branch fails loudly. The kernel checks symbol versions (
CONFIG_MODVERSIONS) and refuses the load, so the failure mode is a missing device, not silent corruption. - GKI modules are not the same as vendor modules. One set ships with the kernel and is rebuilt with it; the other is the vendor's and must match the KMI.
Try it#
adb shell uname -r
adb shell cat /proc/version
adb shell cat /proc/modules | head -20
adb shell getprop ro.vendor.api_level
Example output
Linux localhost 6.6.30-android15-8-... #1 SMP PREEMPT aarch64 Toybox
6.6.30-android15-8-g8f1d2c0a1b2c
6.6-android15-8
vendor_dlkm 4096 0
system_dlkm 8192 0The uname -r string is the fastest way to tell which GKI generation and branch a device is on. If it contains -android15- and a 6.6 prefix, the device is on android15-6.6; if it contains a vendor suffix that is not g..., the kernel was built outside the GKI pipeline.
Build it#
The N06 lab builds a module against a GKI kernel and loads it on an emulator. The exercise is deliberately anticlimactic: the interesting part is watching the loader reject a module built against the wrong branch.
Check yourself#
Check yourself
Ashmem, Android's original shared-memory driver, was replaced by which standard Linux mechanism?
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.
- docsAndroid Common Kernelsource.android.comaccessed 2026-10-27↩
- docsGeneric Kernel Image (GKI)source.android.comaccessed 2026-10-27↩
- docsKernel modules overviewsource.android.comaccessed 2026-10-27↩
- docsLoadable kernel modulessource.android.comaccessed 2026-10-27↩
- docsStable KMIsource.android.comaccessed 2026-10-27↩
- docsGKI versioningsource.android.comaccessed 2026-10-27↩
- docsModular system componentssource.android.comaccessed 2026-10-27↩