Dynamiczne partycjonowanie jest implementowane za pomocą modułu dm-linear device-mapper w jądrze Linuxa. Partycja super
zawiera metadane zawierające nazwy i zakresy bloków każdej partycji dynamicznej w super
. Na pierwszym etapie init
te metadane są analizowane i weryfikowane, a następnie tworzone są wirtualne urządzenia blokowe reprezentujące poszczególne partycje dynamiczne.
Podczas stosowania aktualizacji OTA partycje dynamiczne są automatycznie tworzone, zmieniane lub usuwane w razie potrzeby. W przypadku urządzeń A/B istnieją 2 kopie metadanych, a zmiany są stosowane tylko do kopii reprezentującej docelowy slot.
Partycje dynamiczne są implementowane w przestrzeni użytkownika, więc partycji potrzebnych do działania programu rozruchowego nie można uczynić dynamicznymi. Na przykład boot
, dtbo
i vbmeta
są odczytywane przez program rozruchowy, dlatego muszą pozostać jako partycje fizyczne.
Każda partycja dynamiczna może należeć do grupy aktualizacji. Te grupy ograniczają maksymalną ilość miejsca, jaką mogą zajmować partycje w danej grupie.
Na przykład pola system
i vendor
mogą należeć do grupy, która ogranicza łączną wielkość pól system
i vendor
.
Wdrażanie partycji dynamicznych na nowych urządzeniach
W tej sekcji znajdziesz szczegółowe informacje o wdrażaniu partycji dynamicznych na nowych urządzeniach z Androidem 10 lub nowszym. Aby zaktualizować istniejące urządzenia, przeczytaj artykuł Aktualizowanie urządzeń z Androidem.
Zmiany partycji
W przypadku urządzeń z Androidem 10 utwórz partycję o nazwie super
. Partycja super
obsługuje wewnętrznie gniazda A/B, więc urządzenia A/B nie wymagają oddzielnych partycji super_a
i super_b
.
Wszystkie partycje AOSP tylko do odczytu, które nie są używane przez program rozruchowy, muszą być dynamiczne i muszą zostać usunięte z tabeli partycji GUID (GPT).
Partycje specyficzne dla dostawców nie muszą być dynamiczne i można je umieścić w GPT.
Aby oszacować rozmiar super
, dodaj rozmiary partycji, które mają zostać usunięte z GPT. W przypadku urządzeń A/B wartość ta powinna zawierać rozmiar obu przedziałów. Rysunek 1 przedstawia przykładową tabelę partycji przed i po przekształceniu na partycje dynamiczne.
Obsługiwane partycje dynamiczne:
- System
- Dostawca
- Produkt
- System Ext
- ODM
W przypadku urządzeń uruchamianych z Androidem 10 opcja wiersza poleceń jądra androidboot.super_partition
musi być pusta, aby polecenie syspropro.boot.super_partition
było puste.
Wyrównanie partycji
Moduł device-mapper może działać mniej wydajnie, jeśli partycja super
nie jest prawidłowo wyrównana. Partycja super
MUSI być dopasowana do minimalnego rozmiaru żądania we/wy określonego przez warstwę bloku. Domyślnie system kompilacji (poprzez lpmake
, który generuje obraz partycji super
) zakłada, że wyrównanie 1 MiB jest wystarczające dla każdej partycji dynamicznej. Dostawcy powinni jednak zadbać o to, aby partycja super
była prawidłowo wyrównana.
Minimalny rozmiar żądania urządzenia blokującego można określić,
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
Wyrównanie partycji super
możesz sprawdzić w podobny sposób:
# cat /sys/block/sda/sda17/alignment_offset
Odsunięcie wyrównania MUSI wynosić 0.
Zmiany konfiguracji urządzenia
Aby włączyć dynamiczne partycjonowanie, dodaj tę flagę w pozycji:device.mk
:
PRODUCT_USE_DYNAMIC_PARTITIONS := true
Zmiany konfiguracji tablicy
Musisz ustawić rozmiar partycji super
:
BOARD_SUPER_PARTITION_SIZE := <size-in-bytes>
Na urządzeniach A/B system kompilacji zwraca błąd, jeśli łączny rozmiar obrazów dynamicznych partycji przekracza połowę super
rozmiaru partycji.
Listę partycji dynamicznych możesz skonfigurować w ten sposób: W przypadku urządzeń korzystających z grup aktualizacji podaj grupy w zmiennej BOARD_SUPER_PARTITION_GROUPS
. Każda nazwa grupy ma wtedy zmienne BOARD_group_SIZE
i BOARD_group_PARTITION_LIST
.
W przypadku urządzeń A/B maksymalny rozmiar grupy powinien obejmować tylko 1 przedział, ponieważ nazwy grup są dodawane wewnętrznie do przedziałów.
Oto przykład urządzenia, 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ład urządzenia, na którym usługi systemowe i usługi związane z produktami są umieszczane w group_foo
, a usługi 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ń z testem dynamicznym A/B suma maksymalnych rozmiarów wszystkich grup nie może przekroczyć:
BOARD_SUPER_PARTITION_SIZE
– overhead
Zobacz Wdrażanie testu dynamicznego A/B. -
W przypadku urządzeń z testem A/B suma maksymalnych rozmiarów wszystkich grup musi wynosić:
BOARD_SUPER_PARTITION_SIZE
/ 2 – overhead -
W przypadku urządzeń innych niż A/B i urządzeń z dodatkiem funkcji A/B suma maksymalnych rozmiarów wszystkich grup musi wynosić:
BOARD_SUPER_PARTITION_SIZE
– overhead - W momencie kompilacji suma rozmiarów obrazów każdej partycji w grupie aktualizacji nie może przekraczać maksymalnego rozmiaru grupy.
- Nadwyżka jest wymagana w obliczeniach, aby uwzględnić metadane, wyrównania itp. Rozsądny narzut wynosi 4 MiB, ale w razie potrzeby możesz wybrać większy.
Rozmiar partycji dynamicznych
Przed wprowadzeniem partycji dynamicznych rozmiary partycji były zawyżone, aby zapewnić wystarczającą ilość miejsca na przyszłe aktualizacje. Rzeczywisty rozmiar został przyjęty jako taki, jaki jest, a większość partycji tylko do odczytu miała pewną ilość wolnego miejsca w systemie plików. W partycjach dynamicznych to zwolnione miejsce jest bezużyteczne i można go wykorzystać do powiększania partycji podczas aktualizacji OTA. Należy zadbać o to, 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 na stałe rozmiaru partycji. System kompilacji dopasowuje obraz tak, aby w systemie plików było jak najmniej nieużywanego miejsca. Dzięki temu urządzenie nie będzie marnować miejsca, które można wykorzystać na aktualizacje OTA.
Dodatkowo obrazy ext4 można dodatkowo skompresować, włączając deduplikację na poziomie bloku. Aby włączyć tę funkcję, użyj tej konfiguracji:
BOARD_EXT4_SHARE_DUP_BLOCKS := true
Jeśli automatyczne przydzielanie minimalnego rozmiaru partycji jest niepożądane, możesz kontrolować rozmiar partycji na 2 sposoby. Możesz określić minimalną ilość wolnego miejsca za pomocą właściwości BOARD_partitionIMAGE_PARTITION_RESERVED_SIZE
lub użyć zasady BOARD_partitionIMAGE_PARTITION_SIZE
, aby wymusić stosowanie partycji dynamicznych z określonym rozmiarem. Żadna z nich nie jest zalecana, jeśli nie jest niezbędna.
Na przykład:
BOARD_PRODUCTIMAGE_PARTITION_RESERVED_SIZE := 52428800
Powoduje to, że w systemie plików product.img
pozostanie 50 MiB niewykorzystanego miejsca.
Zmiany w systemie działającym jako root
Urządzenia z Androidem 10 nie mogą używać systemu jako roota.
Urządzenia z partycjami dynamicznymi (czy to z partycjami dynamicznymi w wersji podstawowej, czy z partycjami dynamicznymi w wersji rozszerzonej) nie mogą używać systemu jako roota. Rdzeń Linuksa nie może interpretować partycji super
, więc nie może zamontować system
. Element system
jest teraz podłączony do pierwszego etapu init
, który znajduje się w dysku RAM.
Nie ustawiaj opcji BOARD_BUILD_SYSTEM_ROOT_IMAGE
. W Androidzie 10 flaga BOARD_BUILD_SYSTEM_ROOT_IMAGE
służy tylko do rozróżniania, czy system jest montowany przez jądro czy przez pierwszy etap init
w ramdisku.
Ustawienie wartości BOARD_BUILD_SYSTEM_ROOT_IMAGE
na true
powoduje błąd kompilacji, jeśli wartość PRODUCT_USE_DYNAMIC_PARTITIONS
to również true
.
Gdy zasada BOARD_USES_RECOVERY_AS_BOOT
ma wartość Prawda, obraz przywracania jest kompilowany jako Boot.img, który zawiera dysk ramdisk przywracania. Wcześniej bootloader używał parametru wiersza poleceń skip_initramfs
jądra do określenia trybu uruchamiania. W przypadku urządzeń z Androidem 10 program rozruchowy NIE MOŻE przekazywać pliku skip_initramfs
do wiersza poleceń jądra. Zamiast tego bootloader powinien przekazać wartość androidboot.force_normal_boot=1
, aby pominąć odzyskiwanie i uruchomić normalnego Androida. Urządzenia uruchamiane z Androidem 12 lub nowszym muszą używać bootconfig do przekazywania wartości androidboot.force_normal_boot=1
.
Zmiany konfiguracji AVB
Jeśli urządzenie korzysta z weryfikacji podczas uruchamiania w Androidzie 2.0, a nie używa łańcuchowych opisów partycji, nie musisz wprowadzać żadnych zmian. Jeśli jednak używasz partycji łańcuchowych, a jedna ze zweryfikowanych partycji jest dynamiczna, konieczne są zmiany.
Oto przykładowa konfiguracja urządzenia, które łączy vbmeta
w przypadku 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
W ramach tej konfiguracji bootloader oczekuje, że na końcu partycji system
i vendor
znajdzie stopkę VBmeta. Te partycje nie są już widoczne dla programu rozruchowego (znajdują się w: super
), dlatego potrzebne są 2 zmiany.
-
Dodaj partycje
vbmeta_system
ivbmeta_vendor
do tabeli partycji urządzenia. W przypadku urządzeń A/B dodaj:vbmeta_system_a
,vbmeta_system_b
,vbmeta_vendor_a
ivbmeta_vendor_b
. Jeśli dodajesz jedną lub więcej takich partycji, powinny one mieć taki sam rozmiar jak partycjavbmeta
. -
Zmień nazwy flag konfiguracji, dodając
VBMETA_
i określając, do których partycji ma się odnosić ł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 wtedy, gdy łańcuch jest tworzony do partycji logicznej.
Zmiany programu rozruchowego AVB
Jeśli bootloader zawiera wbudowaną bibliotekę libavb, dołącz te poprawki:
- 818cf56740775446285466eda984acedd4baeac0 – „libavb: odpytuj identyfikatory GUID partycji tylko wtedy, gdy wiersz poleceń ich wymaga”.
- 5abd6bc2578968d24406d834471adfd995a0c2e9 — „Allow system partition to be absent”
- 9ba3b6613b4e5130fa01a11d984c6b5f0eb3af05 — „Poprawka AvbSlotVerifyData->cmdline może być NULL”
Jeśli używasz połączonych partycji, dodaj dodatkową łatkę:
- 49936b4c0109411fdd38bd4ba3a32a01c40439a9 — „libavb: obsługa blobów vbmeta na początku partycji”.
Zmiany w wierszu poleceń jądra
Do wiersza poleceń jądra należy dodać nowy parametr androidboot.boot_devices
. init
używa tego do włączania /dev/block/by-name
linków symbolicznych. Powinien to być element ścieżki urządzenia do podstawowego symbolicznego linku nazwy utworzonego przez ueventd
, czyli /dev/block/platform/device-path/by-name/partition-name
.
Urządzenia uruchamiane z Androidem 12 lub nowszym muszą używać pliku bootconfig, aby przekazać wartość androidboot.boot_devices
do init
.
Jeśli na przykład symboliczny link do superpartycji oparty na nazwie to /dev/block/platform/soc/100000.ufshc/by-name/super
, możesz dodać parametr wiersza poleceń w pliku BoardConfig.mk w ten sposób:
BOARD_KERNEL_CMDLINE += androidboot.boot_devices=soc/100000.ufshc
BOARD_BOOTCONFIG += androidboot.boot_devices=soc/100000.ufshc
zmiany w pliku fstab.
Warstwy drzewa urządzenia i drzewa urządzenia nie mogą zawierać wpisów fstab. Użyj pliku fstab, który będzie częścią dysku ramdisk.
W przypadku partycji logicznych należy wprowadzić zmiany w pliku fstab:
-
Pole flag fs_mgr musi zawierać flagę
logical
i flagęfirst_stage_mount
wprowadzone w Androidzie 10, które wskazują, że partycja ma zostać podłączona w pierwszym etapie. -
Partycja może mieć ustawioną flagę
avb=vbmeta partition name
jako flagęfs_mgr
, a następnie wskazanavbmeta
partycja jest inicjowana w pierwszym etapieinit
przed próbą podłączenia jakichkolwiek urządzeń. -
Pole
dev
musi zawierać nazwę partycji.
Podane niżej wpisy fstab ustawiają system, producenta i produkt jako partycje logiczne zgodnie z podanymi wyżej 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 do pamięci RAM pierwszego etapu.
Zmiany w SELinux
Urządzenie blokujące super partycję musi być oznaczone etykietą
super_block_device
. Jeśli na przykład dowiązanie symboliczne superpartycji według nazwy to /dev/block/platform/soc/100000.ufshc/by-name/super
, dodaj do file_contexts
ten wiersz:
/dev/block/platform/soc/10000\.ufshc/by-name/super u:object_r:super_block_device:s0
fastbootd
Bootloader (lub inne narzędzie do flashowania niebędące narzędziem dla użytkownika) nie rozumie partycji dynamicznych, więc nie może ich flashować. Aby to umożliwić, urządzenia muszą używać implementacji protokołu fastboot w przestrzeni użytkownika, zwanej fastbootd.
Więcej informacji o wdrażaniu fastbootd znajdziesz w artykule Przenoszenie Fastboot do przestrzeni użytkownika.
adb remount
W przypadku deweloperów korzystających z kompilacji eng lub userdebug adb remount
jest niezwykle przydatne do szybkiego iterowania. Partycje dynamiczne stwarzają problem w przypadku adb remount
, ponieważ w każdym systemie plików nie ma już wolnego miejsca. Aby rozwiązać ten problem, urządzenia mogą włączyć overlayfs. Jeśli na superpartycji jest wolne miejsce, adb remount
automatycznie tworzy tymczasową partycję dynamiczną i używa do zapisów nakładek Tymczasowa partycja ma nazwę scratch
, więc nie używaj tej nazwy dla innych partycji.
Więcej informacji o włączaniu overlayfs znajdziesz w dokumentacji overlayfs README w AOSP.
Aktualizowanie urządzeń z Androidem
Jeśli po zaktualizowaniu urządzenia do Androida 10 chcesz włączyć obsługę partycji dynamicznych w OTA, nie musisz zmieniać wbudowanej tabeli partycji. Wymaga dodatkowej konfiguracji.
Zmiany konfiguracji urządzenia
Aby dostosować dynamiczne partycjonowanie, dodaj te flagi w plikudevice.mk
:
PRODUCT_USE_DYNAMIC_PARTITIONS := true PRODUCT_RETROFIT_DYNAMIC_PARTITIONS := true
Zmiany konfiguracji tablicy
Musisz ustawić te zmienne planszy:
- Ustaw
BOARD_SUPER_PARTITION_BLOCK_DEVICES
na listę urządzeń blokowych używanych do przechowywania zakresów partycji dynamicznych. Oto lista nazw istniejących partycji fizycznych na urządzeniu. - Ustaw
BOARD_SUPER_PARTITION_partition_DEVICE_SIZE
na rozmiary poszczególnych urządzeń blokujących w elementachBOARD_SUPER_PARTITION_BLOCK_DEVICES
. Jest to lista rozmiarów istniejących partycji fizycznych na urządzeniu. W istniejących konfiguracjach płytek jest to zwykleBOARD_partitionIMAGE_PARTITION_SIZE
. - Odznacz istniejące
BOARD_partitionIMAGE_PARTITION_SIZE
na wszystkich partycjach wBOARD_SUPER_PARTITION_BLOCK_DEVICES
. - Ustaw wartość
BOARD_SUPER_PARTITION_SIZE
na sumę wartości w kolumnieBOARD_SUPER_PARTITION_partition_DEVICE_SIZE
. - Ustaw
BOARD_SUPER_PARTITION_METADATA_DEVICE
na urządzenie blokujące, na którym są przechowywane metadane partycji dynamicznej. Musi to być wartość ze zbioruBOARD_SUPER_PARTITION_BLOCK_DEVICES
. Zwykle jest tosystem
. - Ustaw odpowiednio
BOARD_SUPER_PARTITION_GROUPS
,BOARD_group_SIZE
iBOARD_group_PARTITION_LIST
. Więcej informacji znajdziesz w artykule Zmiany konfiguracji tablicy na nowych urządzeniach.
Jeśli na przykład urządzenie ma już partycje systemowe i partycje dostawcy, a chcesz je przekonwertować na partycje dynamiczne oraz dodać nową partycję produktu podczas aktualizacji, ustaw tę konfigurację tablicy:
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 SELinux
Urządzenia blokujące super partycję muszą być oznaczone atrybutem super_block_device_type
. Jeśli na przykład urządzenie ma już partycje system
i vendor
, które chcesz używać jako urządzeń blokowych do przechowywania rozszerzeń partycji dynamicznych, a ich symboliczne linki 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 do pliku device.te
ten wiersz:
typeattribute system_block_device super_block_device_type;
Inne konfiguracje znajdziesz w artykule Implementowanie partycji dynamicznych na nowych urządzeniach.
Więcej informacji o aktualizacjach wstecznych znajdziesz w artykule OTA dla urządzeń A/B bez partycji dynamicznych.
Obrazy fabryczne
W przypadku urządzeń uruchamianych z obsługą partycji dynamicznych unikaj używania w trybie szybkiego rozruchu przestrzeni użytkownika do flashowania obrazów fabrycznych, ponieważ uruchamianie w przestrzeni użytkownika trwa wolniej niż inne metody flashowania.
Aby rozwiązać ten problem, make dist
tworzy teraz dodatkowy obraz super.img
, który można zainstalować bezpośrednio na superpartycji. Automatycznie grupuje zawartość partycji logicznych, co oznacza, że zawiera system.img
, vendor.img
itd., a także metadane partycji super
. Obraz można wgrać bezpośrednio na partycję super
bez użycia dodatkowych narzędzi lub fastbootd. Po kompilacji obiekt super.img
jest umieszczany w obiekcie ${ANDROID_PRODUCT_OUT}
.
W przypadku urządzeń A/B uruchamianych z partycjami dynamicznymi element super.img
zawiera obrazy w boksie A. Po zaflashowaniu superobrazu bezpośrednio oznaczysz slot A jako bootowalny przed ponownym uruchomieniem urządzenia.
W przypadku urządzeń do modernizacji make dist
tworzy zestaw obrazów super_*.img
, które można wgrać bezpośrednio na odpowiednie partycje fizyczne. Na przykład make dist
tworzy super_system.img
i super_vendor.img
, gdy BOARD_SUPER_PARTITION_BLOCK_DEVICES
jest dostawcą systemu. Te obrazy są umieszczane w folderze OTA w folderze target_files.zip
.
Dostosowanie pamięci urządzenia w ramach usługi mapowania urządzeń
Dynamiczne partycjonowanie obsługuje pewną liczbę niedeterministycznych obiektów device-mapper. Nie wszystkie z nich mogą zostać utworzone zgodnie z oczekiwaniami, dlatego musisz śledzić wszystkie zamontowane urządzenia i aktualizować właściwości Androida wszystkich powiązanych partycji z podłączonymi urządzeniami pamięci masowej.
Mechanizm w komponencie init
śledzi punkty zamontowania i asymetrycznie aktualizuje właściwości Androida. Nie ma gwarancji, że dokładnie minie określony czas, dlatego musisz zapewnić wystarczającą ilość czasu, aby wszystkie reguły on property
zareagowały. Właściwości to dev.mnt.blk.<partition>
, gdzie <partition>
to na przykład root
, system
, data
lub vendor
. Każda usługa jest powiązana z nazwą podstawowego urządzenia pamięci masowej, jak w tych 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 rozszerzenie właściwości Androida w ramach reguł, a urządzenia do przechowywania danych mogą być dostosowywane przez platformę w miarę 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
Gdy rozpocznie się przetwarzanie poleceń na drugim etapie init
, element epoll loop
stanie się aktywny, a wartości zaczną się aktualizować. Ponieważ jednak wyzwalacze w usłudze są aktywne dopiero pod koniec init
, nie można ich używać na początkowych etapach uruchamiania, aby obsługiwać root
, system
ani vendor
. Możesz oczekiwać, że domyślna wartość read_ahead_kb
jądra będzie wystarczająca, dopóki skrypty init.rc
nie będą mogły zostać zastąpione w early-fs
(gdy uruchamiają się różne demony i obiekty). Dlatego Google zaleca korzystanie z funkcji on property
w połączeniu z właściwością kontrolowanej przez init.rc
, taką jak sys.read_ahead_kb
, do zarządzania czasem działań i zapobiegania wyścigom, jak w tych 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}