As part of the module kernel requirements introduced in Android 8.0, all system-on-chip (SoC) kernels must support loadable kernel modules.
Kernel configuration options
To support loadable kernel modules, android-base.cfg in all common kernels includes the following kernel-config options (or their kernel-version equivalent):
CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y CONFIG_MODVERSIONS=y
All device kernels must enable these options. Kernel modules should also support unloading and reloading whenever possible.
Original device manufacturers (ODMs) can optionally enable module signing in their kernel configuration by enabling following kernel config options:
On devices required to support verified boot, Android requires kernel modules to be in the partitions that have dm-verity enabled. Module signing isn't mandatory and isn't tested against; however, if desired, an ODM can enable module signing as long as they have the key signing and other infrastructure required to ensure independent kernel and file system OTA updates in the future.
While Android 7.x and lower don't mandate against kernel modules (and include
rmmod), Android 8.x and
higher recommend the use of kernel modules in the ecosystem. The following
table shows potential board-specific peripheral support required across three
Android boot modes.
|Boot mode||Storage||Display||Keypad||Battery||PMIC||Touchscreen||NFC, Wi-Fi,
In addition to availability in Android boot modes, kernel modules may also be categorized by who owns them (the SoC vendor or the ODM). If kernel modules are being used, requirements for their placement in file system are as follows:
- All kernels should have built-in support for booting and mounting partitions.
- Kernel modules must be loaded from a read-only partition.
- For devices required to have verified boot, kernel modules should be loaded from verified partitions.
- Kernel modules shouldn't be located in
- Kernel modules from the SoC vendor that are required for full Android or
Charger modes should be located in
- If an ODM partition exists, kernel modules from the ODM that are required
for full Android or Charger modes should be located in
/odm/lib/modules. Otherwise, these modules should be located in
- Kernel modules from the SoC vendor and ODM that are required for Recovery
mode should be located in the recovery
- Kernel modules required for both Recovery mode and full Android or
Charger modes should exist both in the recovery
rootfsand either the
/odmpartitions (as described above).
- Kernel modules used in Recovery mode shouldn't depend on modules located
/odm, as those partitions aren't mounted in Recovery mode.
- SoC vendor kernel modules shouldn't depend on ODM kernel modules.
In Android 7.x and lower,
partitions are not mounted early. In Android 8.x and higher,
to make module loading from these partitions possible, provisions have been
made to mount partitions early for both
non-A/B and A/B devices. This also
ensures that the partitions are mounted in both Android and Charger modes.
Android build system support
BoardConfig.mk, the Android build defines a
BOARD_VENDOR_KERNEL_MODULES variable that provides a full list
of the kernel modules intended for the vendor image. The modules listed in
this variable are copied into the vendor image at
and, after being mounted in Android, appear in
/vendor/lib/modules (in accordance with the above requirements).
Example configuration of the vendor kernel modules:
vendor_lkm_dir := device/$(vendor)/lkm-4.x BOARD_VENDOR_KERNEL_MODULES := \ $(vendor_lkm_dir)/vendor_module_a.ko \ $(vendor_lkm_dir)/vendor_module_b.ko \ $(vendor_lkm_dir)/vendor_module_c.ko
In this example, a vendor kernel module pre-built repository is mapped into the Android build at the location listed above.
The recovery image may contain a subset of the vendor modules. The Android
build defines the variable
these modules. Example:
vendor_lkm_dir := device/$(vendor)/lkm-4.x BOARD_RECOVERY_KERNEL_MODULES := \ $(vendor_lkm_dir)/vendor_module_a.ko \ $(vendor_lkm_dir)/vendor_module_b.ko
The Android build takes care of running
depmod to generate the
modules.dep files in
Module loading and versioning
Load all kernel modules in one pass from
init.rc* by invoking
modprobe -a. This avoids the overhead of repeatedly initializing
the C runtime environment for the
modprobe binary. The
early-init event can be modified to invoke
on early-init exec u:r:modprobe:s0 -- /vendor/bin/modprobe -a -d \ /vendor/lib/modules module_a module_b module_c ...
Typically, a kernel module must be compiled with the kernel that the module is
to be used with (otherwise the kernel refuses to load the module).
CONFIG_MODVERSIONS provides a workaround by detecting breakages
in the application binary interface (ABI). This feature calculates a cyclic
redundancy check (CRC) value for the prototype of each exported symbol in the
kernel and stores the values as part of the kernel; for symbols used by a
kernel module, the values are also stored in the kernel module. When the
module is loaded, the values for the symbols used by the module are compared
with the ones in the kernel. If the values match, the module is loaded;
otherwise the load fails.
To enable the updating of the kernel image separately from the vendor image,
CONFIG_MODVERSIONS. Doing so allows small updates to the
kernel (such as bug fixes from LTS) to be made while maintaining compatibility
with existing kernel modules in the vendor image. However,
CONFIG_MODVERSIONS doesn't fix an ABI breakage by itself. If the
prototype of an exported symbol in the kernel changes, either due to
modification of the source or because the kernel configuration changed, this
breaks compatibility with kernel modules that use that symbol. In such cases,
the kernel module must be recompiled.
For example, the
task_struct structure in the kernel (defined in
include/linux/sched.h) contains many fields conditionally
included depending on the kernel configuration. The
field is present only if
CONFIG_SCHED_INFO is enabled (which
CONFIG_TASK_DELAY_ACCT are enabled). If these configuration
options change state, the layout of the
changes and any exported interfaces from the kernel that use
task_struct are altered (for example,
Compatibility with previously compiled kernel modules that use these
interfaces breaks, requiring those modules to be rebuilt with the new kernel
For more details on
CONFIG_MODVERSIONS, refer to the
documentation in the kernel tree at