Układ partycji

W Androidzie 10 system plików katalogu głównego nie jest już uwzględniany w ramdisk.img, ale zamiast tego jest scalany z system.img (czyli system.img jest zawsze tworzony jako BOARD_BUILD_SYSTEM_ROOT_IMAGE, jeśli ustawiono BOARD_BUILD_SYSTEM_ROOT_IMAGE). Urządzenia z Androidem 10:

  • Użyj układu partycji z systemem jako root (jest on narzucany automatycznie przez kompilację i nie można zmienić tego zachowania).
  • Musisz użyć dysku RAM, który jest wymagany w przypadku dm-linear.
  • Musisz ustawić BOARD_BUILD_SYSTEM_ROOT_IMAGE jako false. To ustawienie służy tylko do rozróżniania urządzeń, które używają dysku RAM i urządzeń, które nie używają dysku RAM (zamiast tego montują system.img bezpośrednio).

Znaczenie konfiguracji systemu jako roota różni się w Androidzie 9 i Androidzie 10. W konfiguracji Androida 9 system-as-root parametr BOARD_BUILD_SYSTEM_ROOT_IMAGE ma wartość true, co powoduje, że kompilacja scala system plików root z plikami w katalogu system.img, a potem montuje system.img jako system plików root (rootfs). Ta konfiguracja jest obowiązkowa w przypadku urządzeń z Androidem 9, ale opcjonalna w przypadku urządzeń aktualizowanych do Androida 9 i urządzeń z starszymi wersjami Androida. W konfiguracji systemu jako roota w Androidzie 10 kompilacja zawsze scala $TARGET_SYSTEM_OUT$TARGET_ROOT_OUTsystem.img. Jest to domyślne zachowanie na wszystkich urządzeniach z Androidem 10.

Android 10 wprowadza dalsze zmiany, aby obsługiwać dynamiczne partycje – system partycjonowania przestrzeni użytkownika, który umożliwia tworzenie, zmianę rozmiaru i usuwanie partycji za pomocą aktualizacji OTA. W ramach tej zmiany jądro Linuksa nie może już zamontować partycji systemowej na urządzeniach z Androidem 10, więc ta operacja jest obsługiwana przez pierwszą fazę inicjalizacji.

W następnych sekcjach opisano wymagania dotyczące systemu jako roota w przypadku aktualizacji OTA tylko dla systemu oraz przedstawiono wskazówki dotyczące aktualizowania urządzeń w celu korzystania z systemu jako roota (w tym zmiany w układzie partycji i wymagania dotyczące jądra dm-verity). Szczegółowe informacje o zmianach dotyczących dysku RAM znajdziesz w artykule Dyski RAM.

Informacje o bezprzewodowych aktualizacjach systemu

Aktualizacje OTA dotyczące tylko systemu, które umożliwiają aktualizowanie wersji Androida do wersji system.imgproduct.img bez zmiany innych partycji, wymagają układu partycji system-as-root. Aby włączyć OTA tylko dla systemu, wszystkie urządzenia z Androidem 10 muszą używać układu partycji z systemem jako root.

  • Urządzenia A/B, które montują partycję system jako rootfs, korzystają już z systemu jako roota i nie wymagają wprowadzania zmian, aby obsługiwać aktualizacje OTA systemu.
  • Urządzenia inne niż A/B, które montują partycję system w miejscu /system, muszą zostać zaktualizowane, aby używać układu partycji z systemem jako root, który obsługuje OTA systemu.

Szczegółowe informacje o urządzeniach z usługą A/B i bez niej znajdziesz w artykule A/B (Seamless) System Updates (w języku angielskim).

Używanie nakładki dostawcy (wersja AOSP 14 lub starsza)

Nakładka dostawcy umożliwia nakładanie zmian na partycji vendor podczas uruchamiania urządzenia. Nakładka dostawcy to zestaw modułów dostawcy na partycji product, które są nakładane na partycję vendor podczas uruchamiania urządzenia, zastępując i dodając do istniejących modułów.

Gdy urządzenie się uruchomi, proces init zakończy pierwszy etap montażu i odczyta właściwości domyślne. Następnie wyszukiwa /product/vendor_overlay/<target_vendor_version> i montuje każdy podkatalog w odpowiednim katalogu partycji vendor, jeśli spełnione są te warunki:

  • Grupa /vendor/<overlay_dir> istnieje.
  • /product/vendor_overlay/<target_vendor_version>/<overlay_dir>ma ten sam kontekst pliku co /vendor/<overlay_dir>.
  • init może być zamontowany w kontekście pliku /vendor/<overlay_dir>.

Implementowanie nakładki dostawcy

Zainstaluj pliki nakładki dostawcy w /product/vendor_overlay/<target_vendor_version>. Te pliki nakładają się na partycję vendor podczas uruchamiania urządzenia, zastępując pliki o tej samej nazwie i dodając nowe pliki. Nakładka dostawcy nie może usuwać plików z partycji vendor.

Pliki nakładek dostawcy muszą mieć ten sam kontekst pliku co pliki docelowe, które zastępują w partycji vendor. Domyślnie pliki w katalogu /product/vendor_overlay/<target_vendor_version> mają kontekst vendor_file. Jeśli występują niezgodności kontekstu pliku między plikami zasobów dostawcy a plikami, które zastępują, określ to w pliku sepolicy dla konkretnego urządzenia. Kontekst pliku jest ustawiany na poziomie katalogu. Jeśli kontekst pliku katalogu zasobów dostawcy nie pasuje do katalogu docelowego, a w pliku sepolicy nie jest określony odpowiedni kontekst pliku, katalog zasobów dostawcy nie zostanie nałożony na katalog docelowy.

Aby korzystać z nakładki dostawcy, jądro musi włączyć OverlayFS za pomocą ustawienia CONFIG_OVERLAY_FS=y. Poza tym jądro musi być scalone z jądrem common kernel 4.4 lub nowszym albo zaktualizowane za pomocą "overlayfs: override_creds=off option bypass creator_cred".

Przykład implementacji nakładki dostawcy

Ta procedura pokazuje implementację nakładki dostawcy, która nakłada się na katalogi /vendor/lib/*, /vendor/etc/* i /vendor/app/*.

  1. Dodaj gotowe pliki dostawcy w teście device/<vendor>/<target>/vendor_overlay/<target_vendor_version>/:

    device/google/device/vendor_overlay/28/lib/libfoo.so
    device/google/device/vendor_overlay/28/lib/libbar.so
    device/google/device/vendor_overlay/28/etc/baz.xml
    device/google/device/vendor_overlay/28/app/qux.apk
  2. Zainstaluj w pliku product/vendor_overlay w konfiguracji device/google/device/device.mk:

    PRODUCT_COPY_FILES += \
        $(call find-copy-subdir-files,*,device/google/device/vendor_overlay,$(TARGET_COPY_OUT_PRODUCT)/vendor_overlay)
  3. Określ konteksty plików, jeśli docelowe pliki partycji vendor mają konteksty inne niż vendor_file. Ponieważ /vendor/lib/* używa kontekstu vendor_file, ten przykład nie zawiera tego katalogu.

    Dodaj do pliku device/google/device-sepolicy/private/file_contexts te informacje:

    /(product|system/product)/vendor_overlay/[0-9]+/etc(/.*)?   u:object_r:vendor_configs_file:s0
    /(product|system/product)/vendor_overlay/[0-9]+/app(/.*)?   u:object_r:vendor_app_file:s0
  4. Zezwól procesowi init na zamontowanie nakładki dostawcy w kontekście plików innym niż vendor_file. Ponieważ proces init ma już uprawnienia do zamontowania w kontekście vendor_file, ten przykład nie definiuje zasad dotyczących vendor_file.

    Dodaj do pliku device/google/device-sepolicy/public/init.te te informacje:

    allow init vendor_configs_file:dir mounton;
    allow init vendor_app_file:dir mounton;

Weryfikowanie nakładki dostawcy

Aby sprawdzić poprawność konfiguracji nakładki dostawcy, dodaj pliki w folderze /product/vendor_overlay/<target_vendor_version>/<overlay_dir> i sprawdź, czy nakładają się one na pliki w folderze /vendor/<overlay_dir>.

W przypadku kompilacji userdebug dostępny jest moduł testowy Atest:

$ atest -v fs_mgr_vendor_overlay_test

Aktualizacja do systemu jako root

Aby zaktualizować urządzenia inne niż A/B, aby używały systemu jako roota, musisz zaktualizować schemat partycjonowania w przypadku boot.img i system.img, skonfigurować dm-verity i usunąć wszystkie zależności rozruchu w folderach roota na urządzeniu.

Aktualizowanie partycji

W przeciwieństwie do urządzeń A/B, które wykorzystują partycję /boot jako partycję odzyskiwania, urządzenia niebędące A/B muszą mieć oddzielną partycję /recovery, ponieważ nie mają partycji zapasowej (na przykład z boot_a na boot_b). Jeśli partycja /recovery zostanie usunięta z urządzenia niebędącego A/B i skonfigurowana podobnie jak w przypadku urządzenia A/B, tryb odzyskiwania może przestać działać podczas nieudanej aktualizacji partycji /boot. Z tego powodu partycja /recovery musi być osobną partycją od partycji /boot na urządzeniach innych niż A/B, co oznacza, że obraz odzyskiwania będzie nadal aktualizowany w odrębny sposób (tak jak na urządzeniach z Androidem 8.1.0 lub starszym).

W poniższej tabeli znajdziesz różnice w partycjach obrazów na urządzeniach innych niż A/B przed i po Androidzie 9.

Obraz Ramdisk (wersja starsza niż 9) System jako root (po Androidzie 9)
boot.img Zawiera jądro i ramdisk.img:
ramdisk.img
  -/
    - init.rc
    - init
    - etc -> /system/etc
    - system/ (mount point)
    - vendor/ (mount point)
    - odm/ (mount point)
    ...
zawiera tylko zwykłe jądro rozruchowe.
recovery.img Zawiera jądro odzyskiwania i element odzyskiwania ramdisk.img.
system.img Zawiera:
system.img
  -/
    - bin/
    - etc
    - vendor -> /vendor
    - ...
Zawiera scalone treści z pierwotnych plików system.imgramdisk.img:
system.img
  -/
    - init.rc
    - init
    - etc -> /system/etc
    - system/
      - bin/
      - etc/
      - vendor -> /vendor
      - ...
    - vendor/ (mount point)
    - odm/ (mount point)
    ...

Same partycje się nie zmieniają. Zarówno partycja ramdisk, jak i partycja system-as-root korzystają z tego schematu partycji:

  • /boot
  • /system
  • /system
  • /recovery
  • /vendor itp.

Konfigurowanie dm-verity

W systemie jako root jądro musi zamontować system.img w / (punkt montowania) za pomocą dm-verity. AOSP obsługuje te implementacje dm-verity: system.img.

vboot 1.0

W przypadku vboot 1.0 jądro musi przeanalizować metadane dotyczące Androida na /system, a następnie przekonwertować je na parametry dm-verity, aby skonfigurować dm-verity (wymaga tych poprawek do jądra). Ten przykład pokazuje ustawienia dm-verity dotyczące systemu jako roota w wierszu poleceń jądra:

ro root=/dev/dm-0 rootwait skip_initramfs init=/init
dm="system none ro,0 1 android-verity /dev/sda34"
veritykeyid=id:7e4333f9bba00adfe0ede979e28ed1920492b40f

vboot 2.0

W przypadku vboot 2.0 (AVB) bootloader musi integrować external/avb/libavb, który następnie analizuje opis hashtree dla /system, konwertuje go na parametry dm-verity i na końcu przekazuje parametry do jądra za pomocą wiersza poleceń jądra. (Deskryptory /system mogą znajdować się w /vbmeta lub w /system).

vboot 2.0 wymaga tych poprawek do jądra:

Ten przykład pokazuje ustawienia dm-verity dotyczące systemu jako roota w wierszu poleceń jądra:

ro root=/dev/dm-0 rootwait  skip_initramfs init=/init

dm="1 vroot none ro 1,0 5159992 verity 1
PARTUUID=00000016-0000-0000-0000-000000000000
PARTUUID=00000016-0000-0000-0000-000000000000 4096 4096 644999 644999
sha1 d80b4a8be3b58a8ab86fad1b498640892d4843a2
8d08feed2f55c418fb63447fec0d32b1b107e42c 10 restart_on_corruption
ignore_zero_blocks use_fec_from_device
PARTUUID=00000016-0000-0000-0000-000000000000 fec_roots 2 fec_blocks
650080 fec_start 650080"

Korzystanie z folderów głównych na urządzeniu

W przypadku systemu jako root po zaflashowaniu ogólnego obrazu systemu (GSI) na urządzeniu (i przed uruchomieniem pakietu testów dostawcy) wszystkie foldery rootowe dodane za pomocą BOARD_ROOT_EXTRA_FOLDERS znikają, ponieważ cała zawartość katalogu głównego została zastąpiona przez GSI systemu jako root. Usunięcie tych folderów może spowodować, że urządzenie nie będzie się uruchamiać, jeśli istnieje zależność od folderów głównych na urządzeniu (na przykład są one używane jako punkty zamontowania).

Aby uniknąć tego problemu, nie używaj BOARD_ROOT_EXTRA_FOLDERS do dodawania folderów głównych na urządzeniu. Jeśli musisz podać punkty montażowe dla konkretnego urządzenia, użyj atrybutu /mnt/vendor/<mount point> (dodanego w tych listach zmian). Punkty montowania specyficzne dla danego dostawcy można określić bezpośrednio w drzewie urządzenia fstab (w przypadku podłączenia pierwszego poziomu) i w pliku /vendor/etc/fstab.{ro.hardware} bez dodatkowej konfiguracji (ponieważ fs_mgr tworzy je automatycznie w folderze /mnt/vendor/*).