Zgodnie z wymaganiami dotyczącymi modułów jądra wprowadzonymi w Androidzie 8.0 wszystkie jądra systemów na chipie (SoC) muszą obsługiwać ładowalne moduły jądra.
Opcje konfiguracji jądra
Aby obsługiwać ładowalne moduły jądra, android-base.config we wszystkich popularnych jądrach zawiera te opcje konfiguracji jądra (lub ich odpowiedniki w wersji jądra):
CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y CONFIG_MODVERSIONS=y
Te opcje muszą być włączone we wszystkich jądrach urządzeń. Moduły jądra powinny też obsługiwać wyładowywanie i ponowne wczytywanie, o ile to możliwe.
Podpisywanie modułów
  Podpisywanie modułów nie jest obsługiwane w przypadku modułów dostawców GKI. Na urządzeniach, które muszą obsługiwać uruchamianie w trybie zweryfikowanym, Android wymaga, aby moduły jądra znajdowały się na partycjach z włączoną funkcją dm-verity. Dzięki temu nie trzeba podpisywać poszczególnych modułów w celu potwierdzenia ich autentyczności.
  Android 13 wprowadził koncepcję modułów GKI. Moduł GKI korzysta z infrastruktury podpisywania w czasie kompilacji jądra, aby rozróżniać GKI od innych modułów w czasie wykonywania.
  Moduły bez podpisu mogą się wczytywać, o ile używają tylko symboli znajdujących się na liście dozwolonych lub dostarczonych przez inne moduły bez podpisu.
  Aby ułatwić podpisywanie modułów GKI podczas kompilacji GKI za pomocą pary kluczy kompilacji jądra, w konfiguracji jądra GKI włączono CONFIG_MODULE_SIG_ALL=y.
  Aby uniknąć podpisywania modułów innych niż GKI podczas kompilowania jądra urządzenia, musisz dodać
  # CONFIG_MODULE_SIG_ALL is not set jako część fragmentów konfiguracji jądra.
Lokalizacje plików
  Chociaż Android 7.x i starsze nie wymagają korzystania z modułów jądra (i obsługują insmod i rmmod), w Androidzie 8.x i nowszych zalecamy używanie modułów jądra w ekosystemie. Tabela poniżej przedstawia potencjalne wymagania dotyczące obsługi urządzeń peryferyjnych w ramach trzech trybów uruchamiania Androida.
| Tryb uruchamiania | Miejsce na dane | Wyświetlacz | Klawiatura | Bateria | PMIC | Ekran dotykowy | NFC, Wi-Fi, Bluetooth | Czujniki | Aparat | 
|---|---|---|---|---|---|---|---|---|---|
| Odzyskiwanie | |||||||||
| Ładowarka | |||||||||
| Android | 
Oprócz dostępności w trybach rozruchu Androida moduły jądra mogą być też kategoryzowane według tego, kto jest ich właścicielem (dostawca SoC lub ODM). Jeśli używane są moduły jądra, wymagania dotyczące ich umieszczenia w systemie plików są następujące:
- Wszystkie jądra powinny mieć wbudowane wsparcie dla uruchamiania i montowania partycji.
- Moduły jądra muszą być ładowane z partycji tylko do odczytu.
- W przypadku urządzeń wymagających uruchamiania w trybie zweryfikowanym moduły jądra powinny być ładowane z partycji zweryfikowanych.
- Moduły jądra nie powinny znajdować się w katalogu /system.
- Moduły GKI wymagane na urządzeniu powinny być ładowane z /system/lib/modules, który jest linkiem symbolicznym do/system_dlkm/lib/modules.
- Moduły jądra od dostawcy układu SoC, które są wymagane do pełnego systemu Android lub trybów ładowarki, powinny znajdować się w /vendor/lib/modules.
- Jeśli partycja ODM istnieje, moduły jądra z ODM, które są wymagane w trybie pełnego Androida lub trybie ładowania, powinny znajdować się w /odm/lib/modules. W przeciwnym razie te moduły powinny znajdować się w folderze/vendor/lib/modules.
- Moduły jądra od dostawcy SoC i ODM, które są wymagane w trybie odzyskiwania, powinny znajdować się w pliku ramfsw katalogu/lib/modules.
- Moduły jądra wymagane zarówno w trybie odzyskiwania, jak i w pełnym systemie Android lub w trybie ładowania powinny znajdować się zarówno w partycji rootfs, jak i w partycji/vendorlub/odm(jak opisano powyżej).
- Moduły jądra używane w trybie odzyskiwania nie powinny zależeć od modułów znajdujących się tylko w /vendorlub/odm, ponieważ te partycje nie są montowane w tym trybie.
- Moduł jądra dostawcy SoC nie powinien zależeć od modułów jądra ODM.
  W Androidzie 7.x i starszych partycje /vendor i /odm nie są montowane wcześniej. W Androidzie 8.x i nowszych, aby umożliwić wczytywanie modułów z tych partycji, wprowadzono postanowienia dotyczące wczesnego montowania partycji na urządzeniach z wsparciem i bez obsługi testów A/B. Dzięki temu partycje są montowane zarówno w trybie Androida, jak i w trybie ładowania.
Obsługa systemu kompilacji Androida
  W BoardConfig.mk kompilacja Androida definiuje zmienną BOARD_VENDOR_KERNEL_MODULES, która zawiera pełną listę modułów jądra przeznaczonych dla obrazu dostawcy. Modułów wymienionych w tej zmiennej kopia jest tworzona w obrazie dostawcy w miejscu /lib/modules/, a po zamontowaniu w Androidzie są one widoczne w miejscu /vendor/lib/modules (zgodnie z wymaganiami wymienionymi powyżej).
  Przykładowa konfiguracja modułów dostawcy jądra:
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
W tym przykładzie repozytorium z gotowym modułem jądra dostawcy jest mapowane na kompilację Androida w wymienionej powyżej lokalizacji.
  Obraz odzyskiwania może zawierać podzbiór modułów dostawcy. Kompilacja Androida definiuje zmienną BOARD_RECOVERY_KERNEL_MODULES dla tych modułów. Przykład:
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
  Kompilacja Androida uruchamia narzędzie depmod, aby wygenerować wymagane pliki modules.dep w katalogach /vendor/lib/modules i /lib/modules (recovery ramfs).
Ładowanie modułów i uwzględnianie wersji
  Załaduj wszystkie moduły jądra w jednym przejściu z poziomu init.rc*, wywołując modprobe -a. Dzięki temu unikniesz nadmiernego obciążania procesora podczas wielokrotnego inicjowania środowiska wykonawczego C dla binarnego pliku modprobe. Zdarzenie early-init można zmodyfikować, aby wywołać zdarzenie modprobe:
on early-init
    exec u:r:vendor_modprobe:s0 -- /vendor/bin/modprobe -a -d \
        /vendor/lib/modules module_a module_b module_c ...
  Zazwyczaj moduł jądra musi być skompilowany z jądrem, z którym ma być używany (w przeciwnym razie jądro odmówi załadowania modułu).
  CONFIG_MODVERSIONS oferuje obejście problemu przez wykrywanie awarii w interfejsie binarnym aplikacji (ABI). Ta funkcja oblicza wartość CRC dla prototypu każdego wyeksportowanego symbolu w jądrze i przechowuje wartości jako część jądra. W przypadku symboli używanych przez moduł jądra wartości są również przechowywane w module jądra. Podczas ładowania modułu wartości symboli używanych przez moduł są porównywane z wartościami w jądrze. Jeśli wartości są zgodne, moduł jest wczytywany. W przeciwnym razie wczytywanie kończy się niepowodzeniem.
  Aby umożliwić aktualizowanie obrazu jądra oddzielnie od obrazu dostawcy, włącz CONFIG_MODVERSIONS. Dzięki temu można wprowadzać drobne aktualizacje jądra (np. poprawki błędów z wersji LTS) przy zachowaniu zgodności z dotychczasowymi modułami jądra w obrazie dostawcy. Jednak CONFIG_MODVERSIONS nie naprawia samodzielnie naruszenia ABI. Jeśli prototyp wyeksportowanego symbolu w jądrze ulegnie zmianie (z powodu modyfikacji źródła lub zmiany konfiguracji jądra), spowoduje to utratę zgodności z modułami jądra, które używają tego symbolu. W takich przypadkach należy ponownie skompilować moduł jądra.
  Na przykład struktura task_struct w rdzeniu (zdefiniowana w include/linux/sched.h) zawiera wiele pól uwzględnianych warunkowo w zależności od konfiguracji rdzenia. Pole sched_info jest obecne tylko wtedy, gdy włączona jest zasada CONFIG_SCHED_INFO (co ma miejsce, gdy włączone są zasady CONFIG_SCHEDSTATS lub CONFIG_TASK_DELAY_ACCT). Jeśli te opcje konfiguracji zmienią stan, układ struktury task_struct ulegnie zmianie, a wszystkie wyeksportowane interfejsy jądra, które używają task_struct, zostaną zmienione (na przykład set_cpus_allowed_ptr w kernel/sched/core.c). Spowoduje to utratę zgodności z wcześniej skompilowanymi modułami jądra, które używają tych interfejsów. Konieczne będzie ich ponowne skompilowanie z nową konfiguracją jądra.
  Więcej informacji o CONFIG_MODVERSIONS znajdziesz w dokumentacji w drzewie jądra na stronie Documentation/kbuild/modules.rst.
