Partycjonowanie dynamiczne jest realizowane przy użyciu modułu mapowania urządzeń dm-linear w jądrze Linuksa. super
partycja zawiera metadane zawierające nazwy i zakresy bloków każdej partycji dynamicznej w obrębie super
. Podczas pierwszego etapu init
te metadane są analizowane i sprawdzane, a następnie tworzone są wirtualne urządzenia blokowe reprezentujące każdą partycję dynamiczną.
Podczas stosowania OTA partycje dynamiczne są automatycznie tworzone, zmieniane ich rozmiar lub usuwane w razie potrzeby. W przypadku urządzeń A/B istnieją dwie kopie metadanych, a zmiany są stosowane tylko do kopii reprezentującej miejsce docelowe.
Ponieważ partycje dynamiczne są zaimplementowane w przestrzeni użytkownika, partycje potrzebne bootloaderowi nie mogą być dynamiczne. Na przykład boot
, dtbo
i vbmeta
są odczytywane przez program ładujący, więc muszą pozostać partycjami fizycznymi.
Każda partycja dynamiczna może należeć do grupy aktualizacji . Grupy te ograniczają maksymalną przestrzeń, jaką mogą zająć partycje w tej grupie. Na przykład system
i vendor
mogą należeć do grupy, która ogranicza całkowity rozmiar system
i vendor
.
Implementuj partycje dynamiczne na nowych urządzeniach
W tej sekcji szczegółowo opisano, jak wdrożyć partycje dynamiczne na nowych urządzeniach z systemem Android 10 i nowszym. Aby zaktualizować istniejące urządzenia, zobacz Aktualizowanie urządzeń z systemem Android .
Zmiany partycji
W przypadku urządzeń uruchamianych z systemem Android 10 utwórz partycję o nazwie super
. Partycja super
obsługuje wewnętrznie gniazda A/B, więc urządzenia A/B nie potrzebują oddzielnych partycji super_a
i super_b
. Wszystkie partycje AOSP tylko do odczytu, które nie są używane przez program ładujący, muszą być dynamiczne i muszą zostać usunięte z tabeli partycji GUID (GPT). Partycje specyficzne dla dostawcy nie muszą być dynamiczne i mogą być umieszczone w GPT.
Aby oszacować rozmiar super
, dodaj rozmiary partycji usuwanych z GPT. W przypadku urządzeń A/B powinno to obejmować rozmiar obu gniazd. Rysunek 1 przedstawia przykładową tablicę partycji przed i po konwersji na partycje dynamiczne.
Obsługiwane partycje dynamiczne to:
- System
- Sprzedawca
- Produkt
- System zewn
- ODM
W przypadku urządzeń uruchamianych z systemem Android 10 opcja wiersza poleceń jądra androidboot.super_partition
musi być pusta, aby polecenie sysprop ro.boot.super_partition
było puste.
Wyrównanie partycji
Moduł mapowania urządzeń może działać mniej wydajnie, jeśli super
partycja nie jest prawidłowo wyrównana. super
partycja MUSI być dostosowana do minimalnego rozmiaru żądania we/wy określonego przez warstwę blokową. Domyślnie system kompilacji (poprzez lpmake
, który generuje obraz super
partycji) zakłada, że dla każdej partycji dynamicznej wystarczające jest wyrównanie 1 MiB. Jednakże dostawcy powinni upewnić się, że super
partycja jest prawidłowo wyrównana.
Możesz określić minimalny rozmiar żądania urządzenia blokowego, sprawdzając sysfs
. Na przykład:
# ls -l /dev/block/by-name/super lrwxrwxrwx 1 root root 16 1970-04-05 01:41 /dev/block/by-name/super -> /dev/block/sda17 # cat /sys/block/sda/queue/minimum_io_size 786432
Możesz sprawdzić wyrównanie super
partycji w podobny sposób:
# cat /sys/block/sda/sda17/alignment_offset
Przesunięcie wyrównania MUSI wynosić 0.
Zmiany konfiguracji urządzenia
Aby włączyć partycjonowanie dynamiczne, dodaj następującą flagę w device.mk
:
PRODUCT_USE_DYNAMIC_PARTITIONS := true
Zmiany w konfiguracji płyty
Musisz ustawić rozmiar super
partycji:
BOARD_SUPER_PARTITION_SIZE := <size-in-bytes>
Na urządzeniach A/B system kompilacji zgłasza błąd, jeśli całkowity rozmiar obrazów partycji dynamicznych przekracza połowę rozmiaru super
partycji.
Listę partycji dynamicznych możesz skonfigurować w następujący sposób. W przypadku urządzeń korzystających z grup aktualizacji wypisz grupy w zmiennej BOARD_SUPER_PARTITION_GROUPS
. Każda nazwa grupy ma wówczas zmienną BOARD_ group _SIZE
i BOARD_ group _PARTITION_LIST
. W przypadku urządzeń A/B maksymalny rozmiar grupy powinien obejmować tylko jedno gniazdo, ponieważ nazwy grup są wewnętrznie opatrzone sufiksem gniazda.
Oto przykładowe urządzenie, które umieszcza wszystkie partycje w grupie o nazwie example_dynamic_partitions
:
BOARD_SUPER_PARTITION_GROUPS := example_dynamic_partitions BOARD_EXAMPLE_DYNAMIC_PARTITIONS_SIZE := 6442450944 BOARD_EXAMPLE_DYNAMIC_PARTITIONS_PARTITION_LIST := system vendor product
Oto przykładowe urządzenie, które umieszcza usługi systemowe i produktowe w group_foo
oraz vendor
, product
i odm
w group_bar
:
BOARD_SUPER_PARTITION_GROUPS := group_foo group_bar BOARD_GROUP_FOO_SIZE := 4831838208 BOARD_GROUP_FOO_PARTITION_LIST := system product_services BOARD_GROUP_BAR_SIZE := 1610612736 BOARD_GROUP_BAR_PARTITION_LIST := vendor product odm
- W przypadku urządzeń uruchamiających Virtual A/B suma maksymalnych rozmiarów wszystkich grup musi wynosić co najwyżej:
BOARD_SUPER_PARTITION_SIZE
– narzut
Zobacz Implementowanie wirtualnego A/B . - W przypadku urządzeń uruchamiających A/B suma maksymalnych rozmiarów wszystkich grup musi wynosić:
BOARD_SUPER_PARTITION_SIZE
/ 2 - narzut - W przypadku urządzeń innych niż A/B i urządzeń A/B do modernizacji suma maksymalnych rozmiarów wszystkich grup musi wynosić:
BOARD_SUPER_PARTITION_SIZE
– narzut - W czasie kompilacji suma rozmiarów obrazów każdej partycji w grupie aktualizacji nie może przekraczać maksymalnego rozmiaru grupy.
- W obliczeniach wymagane jest narzut , aby uwzględnić metadane, wyrównania i tak dalej. Rozsądny narzut wynosi 4 MiB, ale możesz wybrać większy narzut w zależności od potrzeb urządzenia.
Rozmiar partycji dynamicznych
Przed partycjami dynamicznymi rozmiary partycji były przydzielane za dużo, aby zapewnić wystarczającą ilość miejsca na przyszłe aktualizacje. Rzeczywisty rozmiar został przyjęty bez zmian, a większość partycji tylko do odczytu miała pewną ilość wolnego miejsca w systemie plików. W partycjach dynamicznych to wolne miejsce jest bezużyteczne i można je wykorzystać do powiększania partycji podczas OTA. Bardzo ważne jest, aby partycje nie marnowały miejsca i były przydzielone do minimalnego możliwego rozmiaru.
W przypadku obrazów ext4 tylko do odczytu system kompilacji automatycznie przydziela minimalny rozmiar, jeśli nie określono zakodowanego na stałe rozmiaru partycji. System kompilacji dopasowuje obraz tak, aby w systemie plików było jak najmniej niewykorzystanego miejsca. Dzięki temu urządzenie nie marnuje miejsca, które można wykorzystać na OTA.
Dodatkowo obrazy ext4 można dalej kompresować, włączając deduplikację na poziomie bloków. Aby to włączyć, użyj następującej konfiguracji:
BOARD_EXT4_SHARE_DUP_BLOCKS := true
Jeśli automatyczne przydzielanie minimalnego rozmiaru partycji jest niepożądane, istnieją dwa sposoby kontrolowania rozmiaru partycji. Możesz określić minimalną ilość wolnego miejsca za pomocą BOARD_ partition IMAGE_PARTITION_RESERVED_SIZE
lub możesz określić BOARD_ partition IMAGE_PARTITION_SIZE
, aby wymusić określony rozmiar partycji dynamicznych. Żadne z nich nie jest zalecane, jeśli nie jest to konieczne.
Na przykład:
BOARD_PRODUCTIMAGE_PARTITION_RESERVED_SIZE := 52428800
Zmusza to system plików w product.img
do posiadania 50 MiB niewykorzystanego miejsca.
Zmiany systemowe jako root
Urządzenia uruchamiane z systemem Android 10 nie mogą używać systemu jako root.
Urządzenia z partycjami dynamicznymi (niezależnie od tego, czy są uruchamiane z partycjami dynamicznymi, czy też je modernizują) nie mogą używać systemu jako root. Jądro Linuksa nie potrafi zinterpretować super
partycji, więc nie może zamontować samego system
. system
jest teraz montowany przez init
pierwszego etapu, który znajduje się w ramdysku.
Nie ustawiaj BOARD_BUILD_SYSTEM_ROOT_IMAGE
. W systemie Android 10 flaga BOARD_BUILD_SYSTEM_ROOT_IMAGE
służy tylko do rozróżnienia, czy system jest montowany przez jądro, czy przez init
pierwszego etapu w ramdysku.
Ustawienie BOARD_BUILD_SYSTEM_ROOT_IMAGE
na true
powoduje błąd kompilacji, gdy PRODUCT_USE_DYNAMIC_PARTITIONS
również ma true
.
Gdy BOARD_USES_RECOVERY_AS_BOOT
jest ustawione na true, obraz odzyskiwania jest tworzony jako boot.img i zawiera ramdysk odzyskiwania. Poprzednio program ładujący używał parametru wiersza poleceń jądra skip_initramfs
, aby zdecydować, w którym trybie ma zostać uruchomiony system. W przypadku urządzeń z systemem Android 10 program ładujący NIE MOŻE przekazywać skip_initramfs
do wiersza poleceń jądra. Zamiast tego program ładujący powinien przekazać androidboot.force_normal_boot=1
, aby pominąć odzyskiwanie i uruchomić normalny system Android. Urządzenia uruchamiane z systemem Android 12 lub nowszym muszą używać bootconfig, aby przekazać androidboot.force_normal_boot=1
.
Zmiany w konfiguracji AVB
W przypadku korzystania z Android Verified Boot 2.0 , jeśli urządzenie nie korzysta z połączonych deskryptorów partycji , nie jest konieczna żadna zmiana. Jeśli jednak używasz partycji łańcuchowych i jedna ze zweryfikowanych partycji jest dynamiczna, konieczne są zmiany.
Oto przykładowa konfiguracja urządzenia, które łączy vbmeta
dla partycji system
i vendor
.
BOARD_AVB_SYSTEM_KEY_PATH := external/avb/test/data/testkey_rsa2048.pem BOARD_AVB_SYSTEM_ALGORITHM := SHA256_RSA2048 BOARD_AVB_SYSTEM_ROLLBACK_INDEX := $(PLATFORM_SECURITY_PATCH_TIMESTAMP) BOARD_AVB_SYSTEM_ROLLBACK_INDEX_LOCATION := 1 BOARD_AVB_VENDOR_KEY_PATH := external/avb/test/data/testkey_rsa2048.pem BOARD_AVB_VENDOR_ALGORITHM := SHA256_RSA2048 BOARD_AVB_VENDOR_ROLLBACK_INDEX := $(PLATFORM_SECURITY_PATCH_TIMESTAMP) BOARD_AVB_VENDOR_ROLLBACK_INDEX_LOCATION := 1
Przy tej konfiguracji program ładujący spodziewa się znaleźć stopkę vbmeta na końcu partycji system
i vendor
. Ponieważ te partycje nie są już widoczne dla programu ładującego (znajdują się w super
), potrzebne są dwie zmiany.
- Dodaj partycje
vbmeta_system
ivbmeta_vendor
do tablicy partycji urządzenia. W przypadku urządzeń A/B dodajvbmeta_system_a
,vbmeta_system_b
,vbmeta_vendor_a
ivbmeta_vendor_b
. Jeśli dodasz jedną lub więcej takich partycji, powinny one mieć ten sam rozmiar co partycjavbmeta
. - Zmień nazwę flag konfiguracji, dodając
VBMETA_
i określ, do których partycji rozciąga się łańcuch:BOARD_AVB_VBMETA_SYSTEM := system BOARD_AVB_VBMETA_SYSTEM_KEY_PATH := external/avb/test/data/testkey_rsa2048.pem BOARD_AVB_VBMETA_SYSTEM_ALGORITHM := SHA256_RSA2048 BOARD_AVB_VBMETA_SYSTEM_ROLLBACK_INDEX := $(PLATFORM_SECURITY_PATCH_TIMESTAMP) BOARD_AVB_VBMETA_SYSTEM_ROLLBACK_INDEX_LOCATION := 1 BOARD_AVB_VBMETA_VENDOR := vendor BOARD_AVB_VBMETA_VENDOR_KEY_PATH := external/avb/test/data/testkey_rsa2048.pem BOARD_AVB_VBMETA_VENDOR_ALGORITHM := SHA256_RSA2048 BOARD_AVB_VBMETA_VENDOR_ROLLBACK_INDEX := $(PLATFORM_SECURITY_PATCH_TIMESTAMP) BOARD_AVB_VBMETA_VENDOR_ROLLBACK_INDEX_LOCATION := 1
Urządzenie może używać jednej, obu lub żadnej z tych partycji. Zmiany są potrzebne tylko w przypadku połączenia łańcuchowego z partycją logiczną.
Zmiany w programie ładującym AVB
Jeśli program ładujący ma wbudowaną wersję libavb , dołącz następujące poprawki:
- 818cf56740775446285466eda984acedd4baeac0 — „libavb: Zapytaj o identyfikatory GUID partycji tylko wtedy, gdy linia poleceń ich potrzebuje.”
- 5abd6bc2578968d24406d834471adfd995a0c2e9 — „Zezwalaj na nieobecność partycji systemowej”
- 9ba3b6613b4e5130fa01a11d984c6b5f0eb3af05 — „Napraw AvbSlotVerifyData->cmdline może mieć wartość NULL”
Jeśli używasz partycji łańcuchowych, dołącz dodatkową poprawkę:
- 49936b4c0109411fdd38bd4ba3a32a01c40439a9 — „libavb: Obsługa obiektów blob vbmeta na początku partycji”.
Zmiany w wierszu poleceń jądra
Do wiersza poleceń jądra należy dodać nowy parametr androidboot.boot_devices
. Jest to używane przez init
do włączania dowiązań symbolicznych /dev/block/by-name
. Powinien to być komponent ścieżki urządzenia do bazowego dowiązania symbolicznego według nazwy utworzonego przez ueventd
, czyli /dev/block/platform/ device-path /by-name/ partition-name
. Urządzenia uruchamiane z systemem Android 12 lub nowszym muszą użyć opcji bootconfig, aby przekazać androidboot.boot_devices
do init
.
Na przykład, jeśli dowiązanie symboliczne nazwy super partycji to /dev/block/platform/ soc/100000.ufshc /by-name/super
, możesz dodać parametr wiersza poleceń w pliku BoardConfig.mk w następujący sposób:
BOARD_KERNEL_CMDLINE += androidboot.boot_devices=soc/100000.ufshcMożesz dodać parametr bootconfig w pliku BoardConfig.mk w następujący sposób:
BOARD_BOOTCONFIG += androidboot.boot_devices=soc/100000.ufshc
zmiany w fstabie
Drzewo urządzeń i nakładki drzew urządzeń nie mogą zawierać wpisów fstab. Użyj pliku fstab, który będzie częścią ramdysku.
Należy dokonać zmian w pliku fstab dla partycji logicznych:
- Pole fs_mgr flags musi zawierać flagę
logical
oraz flagęfirst_stage_mount
, wprowadzoną w Androidzie 10, która wskazuje, że partycja ma być zamontowana w pierwszym etapie. - Partycja może określić
avb= vbmeta partition name
jako flagęfs_mgr
, a następnie określona partycjavbmeta
zostanie zainicjowana w ramach pierwszego etapuinit
przed próbą zamontowania jakichkolwiek urządzeń. - Pole
dev
musi być nazwą partycji.
Poniższe wpisy fstab ustawiają system, dostawcę i produkt jako partycje logiczne zgodnie z powyższymi regułami.
#<dev> <mnt_point> <type> <mnt_flags options> <fs_mgr_flags> system /system ext4 ro,barrier=1 wait,slotselect,avb=vbmeta,logical,first_stage_mount vendor /vendor ext4 ro,barrier=1 wait,slotselect,avb,logical,first_stage_mount product /product ext4 ro,barrier=1 wait,slotselect,avb,logical,first_stage_mount
Skopiuj plik fstab na ramdysk pierwszego stopnia.
Zmiany w SELinuxie
Urządzenie bloku super partycji musi być oznaczone etykietą super_block_device
. Na przykład, jeśli dowiązanie symboliczne super partycji to /dev/block/platform/ soc/100000.ufshc /by-name/super
, dodaj następujący wiersz do file_contexts
:
/dev/block/platform/soc/10000\.ufshc/by-name/super u:object_r:super_block_device:s0
fastboot
Program ładujący (lub dowolne narzędzie do flashowania spoza przestrzeni użytkownika) nie rozpoznaje partycji dynamicznych, więc nie może ich sflashować. Aby rozwiązać ten problem, urządzenia muszą korzystać z implementacji protokołu fastboot w przestrzeni użytkownika, zwanej fastbootd.
Aby uzyskać więcej informacji na temat implementacji fastbootd, zobacz Przenoszenie Fastboot do przestrzeni użytkownika .
ponowne zamontowanie adb
Dla programistów korzystających z kompilacji eng lub userdebug, adb remount
jest niezwykle przydatny do szybkiej iteracji. Partycje dynamiczne stwarzają problem przy adb remount
ponieważ w każdym systemie plików nie ma już wolnego miejsca. Aby rozwiązać ten problem, urządzenia mogą włączyć nakładki. Dopóki na super partycji jest wolne miejsce, adb remount
automatycznie tworzy tymczasową partycję dynamiczną i używa nakładek do zapisu. Partycja tymczasowa nosi nazwę scratch
, więc nie używaj tej nazwy w przypadku innych partycji.
Aby uzyskać więcej informacji na temat włączania overlayfs, zobacz plik README overlayfs w AOSP.
Aktualizuj urządzenia z Androidem
Jeśli uaktualnisz urządzenie do Androida 10 i chcesz włączyć obsługę partycji dynamicznych w OTA, nie musisz zmieniać wbudowanej tablicy partycji. Wymagana jest dodatkowa konfiguracja.
Zmiany konfiguracji urządzenia
Aby zmodernizować partycjonowanie dynamiczne, dodaj następujące flagi w device.mk
:
PRODUCT_USE_DYNAMIC_PARTITIONS := true PRODUCT_RETROFIT_DYNAMIC_PARTITIONS := true
Zmiany w konfiguracji płyty
Musisz ustawić następujące zmienne planszy:
- Ustaw
BOARD_SUPER_PARTITION_BLOCK_DEVICES
na listę urządzeń blokowych używanych do przechowywania zakresów partycji dynamicznych. To jest lista nazw istniejących partycji fizycznych na urządzeniu. - Ustaw
BOARD_SUPER_PARTITION_ partition _DEVICE_SIZE
na rozmiary każdego urządzenia blokowego odpowiednio wBOARD_SUPER_PARTITION_BLOCK_DEVICES
. To jest lista rozmiarów istniejących partycji fizycznych na urządzeniu. Zwykle jest toBOARD_ partition IMAGE_PARTITION_SIZE
w istniejących konfiguracjach płyty. - Usuń ustawienie istniejącej
BOARD_ partition IMAGE_PARTITION_SIZE
dla wszystkich partycji wBOARD_SUPER_PARTITION_BLOCK_DEVICES
. - Ustaw
BOARD_SUPER_PARTITION_SIZE
na sumęBOARD_SUPER_PARTITION_ partition _DEVICE_SIZE
. - Ustaw
BOARD_SUPER_PARTITION_METADATA_DEVICE
na urządzenie blokowe, w którym przechowywane są metadane partycji dynamicznej. Musi to być jedno zBOARD_SUPER_PARTITION_BLOCK_DEVICES
. Zwykle jest to ustawione nasystem
. - Ustaw odpowiednio
BOARD_SUPER_PARTITION_GROUPS
,BOARD_ group _SIZE
iBOARD_ group _PARTITION_LIST
. Aby uzyskać szczegółowe informacje, zobacz Zmiany w konfiguracji płytki na nowych urządzeniach .
Na przykład, jeśli urządzenie ma już partycje systemowe i dostawcy, a chcesz je przekonwertować na partycje dynamiczne i dodać nową partycję produktową podczas aktualizacji, ustaw następującą konfigurację płyty:
BOARD_SUPER_PARTITION_BLOCK_DEVICES := system vendor BOARD_SUPER_PARTITION_METADATA_DEVICE := system # Rename BOARD_SYSTEMIMAGE_PARTITION_SIZE to BOARD_SUPER_PARTITION_SYSTEM_DEVICE_SIZE. BOARD_SUPER_PARTITION_SYSTEM_DEVICE_SIZE := <size-in-bytes> # Rename BOARD_VENDORIMAGE_PARTITION_SIZE to BOARD_SUPER_PARTITION_VENDOR_DEVICE_SIZE BOARD_SUPER_PARTITION_VENDOR_DEVICE_SIZE := <size-in-bytes> # This is BOARD_SUPER_PARTITION_SYSTEM_DEVICE_SIZE + BOARD_SUPER_PARTITION_VENDOR_DEVICE_SIZE BOARD_SUPER_PARTITION_SIZE := <size-in-bytes> # Configuration for dynamic partitions. For example: BOARD_SUPER_PARTITION_GROUPS := group_foo BOARD_GROUP_FOO_SIZE := <size-in-bytes> BOARD_GROUP_FOO_PARTITION_LIST := system vendor product
Zmiany w SELinuxie
Urządzenia bloku super partycji muszą być oznaczone atrybutem super_block_device_type
. Na przykład, jeśli urządzenie ma już partycje system
i partycje vendor
, chcesz ich użyć jako urządzeń blokowych do przechowywania zakresów partycji dynamicznych, a ich dowiązania symboliczne po nazwie są oznaczone jako system_block_device
:
/dev/block/platform/soc/10000\.ufshc/by-name/system u:object_r:system_block_device:s0 /dev/block/platform/soc/10000\.ufshc/by-name/vendor u:object_r:system_block_device:s0
Następnie dodaj następujący wiersz do device.te
:
typeattribute system_block_device super_block_device_type;
Informacje na temat innych konfiguracji można znaleźć w sekcji Implementowanie partycji dynamicznych na nowych urządzeniach .
Aby uzyskać więcej informacji na temat aktualizacji modernizacyjnych, zobacz OTA dla urządzeń A/B bez partycji dynamicznych .
Obrazy fabryczne
W przypadku urządzenia uruchamianego z obsługą partycji dynamicznych unikaj używania funkcji fastboot w przestrzeni użytkownika do flashowania obrazów fabrycznych, ponieważ uruchamianie w przestrzeni użytkownika jest wolniejsze niż w przypadku innych metod flashowania.
Aby rozwiązać ten problem, make dist
tworzy teraz dodatkowy obraz super.img
, który można przesłać bezpośrednio na super partycję. Automatycznie pakuje zawartość partycji logicznych, co oznacza, że zawiera pliki system.img
, vendor.img
itd., oprócz metadanych super
partycji. Ten obraz można przesłać bezpośrednio na super
partycję bez użycia dodatkowych narzędzi lub użycia funkcji fastbootd. Po kompilacji super.img
jest umieszczany w ${ANDROID_PRODUCT_OUT}
.
W przypadku urządzeń A/B uruchamianych z partycjami dynamicznymi super.img
zawiera obrazy w slocie A. Po bezpośrednim flashowaniu super obrazu zaznacz gniazdo A jako bootowalne przed ponownym uruchomieniem urządzenia.
W przypadku urządzeń modernizowanych polecenie make dist
tworzy zestaw obrazów super_*.img
, które można przesłać bezpośrednio na odpowiednie partycje fizyczne. Na przykład make dist
kompilacje super_system.img
i super_vendor.img
, gdy dostawcą systemu jest BOARD_SUPER_PARTITION_BLOCK_DEVICES
. Obrazy te są umieszczane w folderze OTA w target_files.zip
.
Mapowanie urządzeń – strojenie urządzeń pamięci masowej
Partycjonowanie dynamiczne uwzględnia wiele niedeterministycznych obiektów mapujących urządzenia. Mogą nie zostać utworzone wszystkie instancje zgodnie z oczekiwaniami, dlatego należy śledzić wszystkie podłączenia i zaktualizować właściwości systemu Android wszystkich powiązanych partycji z odpowiadającymi im urządzeniami pamięci masowej.
Mechanizm wewnątrz init
śledzi montowania i asynchronicznie aktualizuje właściwości Androida. Nie ma gwarancji, że czas trwania tej operacji będzie mieścić się w określonym przedziale czasu, dlatego należy zapewnić wystarczającą ilość czasu, aby wszystkie wyzwalacze on property
mogły zareagować. Właściwości to dev.mnt.blk. <partition>
gdzie <partition>
to na przykład root
, system
, data
lub vendor
. Każda właściwość jest powiązana z podstawową nazwą urządzenia pamięci masowej, jak pokazano w poniższych przykładach:
taimen:/ % getprop | grep dev.mnt.blk [dev.mnt.blk.data]: [sda] [dev.mnt.blk.firmware]: [sde] [dev.mnt.blk.metadata]: [sde] [dev.mnt.blk.persist]: [sda] [dev.mnt.blk.root]: [dm-0] [dev.mnt.blk.vendor]: [dm-1] blueline:/ $ getprop | grep dev.mnt.blk [dev.mnt.blk.data]: [dm-4] [dev.mnt.blk.metadata]: [sda] [dev.mnt.blk.mnt.scratch]: [sda] [dev.mnt.blk.mnt.vendor.persist]: [sdf] [dev.mnt.blk.product]: [dm-2] [dev.mnt.blk.root]: [dm-0] [dev.mnt.blk.system_ext]: [dm-3] [dev.mnt.blk.vendor]: [dm-1] [dev.mnt.blk.vendor.firmware_mnt]: [sda]
Język init.rc
umożliwia rozszerzanie właściwości Androida w ramach reguł, a urządzenia pamięci masowej mogą być dostrajane przez platformę w razie potrzeby za pomocą takich poleceń:
write /sys/block/${dev.mnt.blk.root}/queue/read_ahead_kb 128 write /sys/block/${dev.mnt.blk.data}/queue/read_ahead_kb 128
Po rozpoczęciu przetwarzania poleceń w drugim etapie init
epoll loop
staje się aktywna i wartości zaczynają się aktualizować. Ponieważ jednak wyzwalacze właściwości nie są aktywne aż do późnej init
, nie można ich używać w początkowych etapach rozruchu do obsługi root
, system
lub vendor
. Możesz oczekiwać, że domyślne ustawienie jądra read_ahead_kb
będzie wystarczające, dopóki skrypty init.rc
nie będą mogły zastąpić early-fs
(kiedy uruchamiają się różne demony i funkcje). Dlatego Google zaleca użycie funkcji on property
w połączeniu z właściwością kontrolowaną przez init.rc
, taką jak sys.read_ahead_kb
, aby poradzić sobie z synchronizacją operacji i zapobiec warunkom wyścigowym, jak w poniższych przykładach:
on property:dev.mnt.blk.root=* && property:sys.read_ahead_kb=* write /sys/block/${dev.mnt.blk.root}/queue/read_ahead_kb ${sys.read_ahead_kb:-2048} on property:dev.mnt.blk.system=* && property:sys.read_ahead_kb=* write /sys/block/${dev.mnt.blk.system}/queue/read_ahead_kb ${sys.read_ahead_kb:-2048} on property:dev.mnt.blk.vendor=* && property:sys.read_ahead_kb=* write /sys/block/${dev.mnt.blk.vendor}/queue/read_ahead_kb ${sys.read_ahead_kb:-2048} on property:dev.mnt.blk.product=* && property:sys.read_ahead_kb=* write /sys/block/${dev.mnt.blk.system_ext}/queue/read_ahead_kb ${sys.read_ahead_kb:-2048} on property:dev.mnt.blk.oem=* && property:sys.read_ahead_kb=* write /sys/block/${dev.mnt.blk.oem}/queue/read_ahead_kb ${sys.read_ahead_kb:-2048} on property:dev.mnt.blk.data=* && property:sys.read_ahead_kb=* write /sys/block/${dev.mnt.blk.data}/queue/read_ahead_kb ${sys.read_ahead_kb:-2048} on early-fs: setprop sys.read_ahead_kb ${ro.read_ahead_kb.boot:-2048} on property:sys.boot_completed=1 setprop sys.read_ahead_kb ${ro.read_ahead_kb.bootcomplete:-128}