Partycjonowanie dynamiczne jest zaimplementowane za pomocą modułu dm-linear device-mapper w jądrze Linux. Superpartycja zawiera metadane zawierające listę nazw i zakresów bloków każdej partycji dynamicznej super
super
Podczas pierwszego etapu init
metadane są analizowane i sprawdzane, a wirtualne urządzenia blokowe są tworzone w celu reprezentowania każdej partycji dynamicznej.
Podczas stosowania OTA partycje dynamiczne są automatycznie tworzone, zmieniane lub usuwane w razie potrzeby. W przypadku urządzeń A/B istnieją dwie kopie metadanych, a zmiany są stosowane tylko do kopii reprezentującej gniazdo 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 bootloader i dlatego muszą pozostać jako partycje fizyczne.
Każda partycja dynamiczna może należeć do grupy aktualizacji . Grupy te ograniczają maksymalną ilość miejsca, jaką mogą zajmować partycje w tej grupie. Na przykład system
i vendor
mogą należeć do grupy, która ogranicza łączny rozmiar system
i vendor
.
Wdrażanie partycji dynamicznych na nowych urządzeniach
W tej sekcji szczegółowo opisano, jak zaimplementować partycje dynamiczne na nowych urządzeniach uruchamianych z systemem Android 10 i nowszym. Aby zaktualizować istniejące urządzenia, zobacz Uaktualnianie urządzeń z systemem Android .
Zmiany partycjonowania
W przypadku urządzeń uruchamianych z systemem Android 10 utwórz partycję o nazwie super
. super_a
super
super_b
. Wszystkie partycje AOSP tylko do odczytu, które nie są używane przez bootloader, muszą być dynamiczne i muszą zostać usunięte z tabeli partycji GUID (GPT). Partycje specyficzne dla dostawcy nie muszą być dynamiczne i można je umieścić 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ą tabelę partycji przed i po konwersji na partycje dynamiczne.

Obsługiwane partycje dynamiczne to:
- System
- Sprzedawca
- Produkt
- Rozszerzenie systemu
- 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ądzenia może działać mniej wydajnie, jeśli super
nie jest odpowiednio wyrównana. super
MUSI być wyrównana do minimalnego rozmiaru żądania we/wy określonego przez warstwę blokową. Domyślnie system budowania (poprzez lpmake
, który generuje obraz super
) zakłada, że wyrównanie 1 MiB jest wystarczające dla każdej partycji dynamicznej. Jednak dostawcy powinni upewnić się, że super
jest odpowiednio 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 zweryfikować wyrównanie super
w podobny sposób:
# cat /sys/block/sda/sda17/alignment_offset
Przesunięcie wyrównania MUSI wynosić 0.
Zmiany w 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łytki
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
.
Listę partycji dynamicznych można skonfigurować w następujący sposób. W przypadku urządzeń korzystających z grup aktualizacji wymień grupy w zmiennej BOARD_SUPER_PARTITION_GROUPS
. Każda nazwa grupy ma wtedy 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 dodawane do 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
, a 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 wirtualnych urządzeń startowych A/B suma maksymalnych rozmiarów wszystkich grup musi wynosić co najwyżej:
BOARD_SUPER_PARTITION_SIZE
— narzut
Zobacz Implementacja wirtualnego A/B . - W przypadku urządzeń startowych 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 zmodernizowanych urządzeń A/B 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 wymagany jest narzut , aby uwzględnić metadane, wyrównania itd. Rozsądny narzut to 4 MiB, ale możesz wybrać większy narzut w zależności od potrzeb urządzenia.
Rozmiary partycji dynamicznych
Przed partycjami dynamicznymi rozmiary partycji były nadmiernie przydzielane, aby zapewnić wystarczającą ilość miejsca na przyszłe aktualizacje. Rzeczywisty rozmiar został wzięty bez zmian, a większość partycji tylko do odczytu miała pewną ilość wolnego miejsca w swoim systemie plików. W partycjach dynamicznych to wolne miejsce jest bezużyteczne i może być wykorzystane do powiększania partycji podczas OTA. Bardzo ważne jest, aby partycje nie marnowały miejsca i zostały przydzielone do minimalnego możliwego rozmiaru.
W przypadku obrazów ext4 tylko do odczytu system budowania automatycznie przydziela minimalny rozmiar, jeśli nie określono rozmiaru partycji zakodowanej na stałe. System kompilacji dopasowuje się do obrazu, aby system plików miał jak najmniej niewykorzystanego miejsca. Gwarantuje to, że urządzenie nie marnuje miejsca, które można wykorzystać do OTA.
Ponadto obrazy ext4 można dodatkowo skompresować, włączając deduplikację na poziomie bloków. Aby to umożliwić, 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 dla BOARD_ partition IMAGE_PARTITION_RESERVED_SIZE
lub możesz określić BOARD_ partition IMAGE_PARTITION_SIZE
, aby wymusić określony rozmiar partycji dynamicznych. Żadna z tych opcji nie jest zalecana, chyba że jest to konieczne.
Na przykład:
BOARD_PRODUCTIMAGE_PARTITION_RESERVED_SIZE := 52428800
Wymusza to, aby system plików w product.img
miał 50 MiB nieużywanego 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 może zinterpretować super
, a więc nie może zamontować samego system
. system
jest teraz montowany przez init
pierwszego stopnia, 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 zamontowany 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
ma również wartość true
.
Gdy BOARD_USES_RECOVERY_AS_BOOT
ma wartość true, obraz odzyskiwania jest tworzony jako boot.img, zawierający ramdysk odzyskiwania. Wcześniej bootloader używał parametru wiersza poleceń skip_initramfs
jądra, aby zdecydować, w którym trybie ma się uruchomić. W przypadku urządzeń z systemem Android 10 bootloader NIE MOŻE przekazywać skip_initramfs
do wiersza poleceń jądra. Zamiast tego bootloader 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 używa połączonych deskryptorów partycji , nie jest konieczna żadna zmiana. Jeśli jednak używasz partycji połączonych łańcuchem, a jedna ze zweryfikowanych partycji jest dynamiczna, konieczne są zmiany.
Oto przykładowa konfiguracja urządzenia, które vbmeta
dla partycji system
i partycji 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 tej konfiguracji bootloader spodziewa się znaleźć stopkę vbmeta na końcu partycji system
i partycji vendor
. Ponieważ te partycje nie są już widoczne dla bootloadera (znajdują się w super
), potrzebne są dwie zmiany.
- Dodaj
vbmeta_system
ivbmeta_vendor
do tabeli partycji urządzenia. W przypadku urządzeń A/B dodajvbmeta_system_a
,vbmeta_system_b
,vbmeta_vendor_a
ivbmeta_vendor_b
. Jeśli dodajesz jedną lub więcej z tych partycji, powinny one mieć taki sam rozmiar jak partycjavbmeta
. - Zmień nazwy flag konfiguracyjnych, 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 łączenia z partycją logiczną.
Zmiany w bootloaderze AVB
Jeśli bootloader ma osadzony libavb , dołącz następujące poprawki:
- 818cf56740775446285466eda984acedd4baeac0 — „libavb: zapytaj o identyfikatory GUID partycji tylko wtedy, gdy potrzebuje ich linia poleceń”.
- 5abd6bc2578968d24406d834471adfd995a0c2e9 — „Zezwól na brak partycji systemowej”
- 9ba3b6613b4e5130fa01a11d984c6b5f0eb3af05 — „Napraw AvbSlotVerifyData->cmdline może być NULL”
Jeśli używasz partycji połączonych, dołącz dodatkową poprawkę:
- 49936b4c0109411fdd38bd4ba3a32a01c40439a9 — "libavb: Obsługa obiektów blob vbmeta na początku partycji."
Zmiany w wierszu poleceń jądra
Do wiersza polecenia jądra należy dodać nowy parametr androidboot.boot_devices
. Jest to używane przez init
do włączenia dowiązań symbolicznych /dev/block/by-name
. Powinien to być składnik ś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żywać bootconfig, aby przekazać androidboot.boot_devices
do init
.
Na przykład, jeśli dowiązanie symboliczne superpartycji według nazwy 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 fstab
Drzewo urządzeń i nakładki drzewa urządzeń nie mogą zawierać wpisów fstab. Użyj pliku fstab, który będzie częścią ramdysku.
Należy wprowadzić zmiany w pliku fstab dla partycji logicznych:
- Pole fs_mgr flags musi zawierać flagę
logical
i flagęfirst_stage_mount
wprowadzoną w systemie Android 10, która wskazuje, że partycja ma zostać zamontowana w pierwszym etapie. - Partycja może określić
avb= vbmeta partition name
jako flagęfs_mgr
, a następnie określona partycjavbmeta
jest inicjowana przezinit
pierwszego etapu 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 do ramdysku pierwszego etapu.
Zmiany w SELinuksie
Urządzenie blokowe superpartycji musi być oznaczone etykietą super_block_device
. Na przykład, jeśli dowiązanie symboliczne /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
szybki rozruch
Bootloader (lub jakiekolwiek inne narzędzie do flashowania spoza przestrzeni użytkownika) nie rozumie partycji dynamicznych, więc nie może ich flashować. Aby rozwiązać ten problem, urządzenia muszą korzystać z implementacji protokołu fastboot w przestrzeni użytkownika, zwanego fastbootd.
Aby uzyskać więcej informacji na temat implementacji fastbootd, zobacz Przenoszenie Fastboot do przestrzeni użytkownika .
adb ponownie zamontować
Dla programistów używających kompilacji eng lub userdebug, adb remount
remount jest niezwykle przydatny do szybkiej iteracji. Partycje dynamiczne stanowią problem przy adb remount
, ponieważ nie ma już wolnego miejsca w każdym systemie plików. Aby temu zaradzić, urządzenia mogą włączyć nakładki. Tak długo, jak na super partycji jest wolne miejsce, adb remount
automatycznie tworzy tymczasową partycję dynamiczną i używa overlayfs do zapisu. Partycja tymczasowa nosi nazwę scratch
, więc nie używaj tej nazwy dla innych partycji.
Aby uzyskać więcej informacji na temat włączania overlayfs, zobacz README overlayfs w AOSP.
Uaktualnianie urządzeń z Androidem
Jeśli uaktualnisz urządzenie do systemu Android 10 i chcesz uwzględnić obsługę partycji dynamicznych w OTA, nie musisz zmieniać wbudowanej tabeli partycji. Wymagana jest dodatkowa konfiguracja.
Zmiany w 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łytki
Musisz ustawić następujące zmienne tablicy:
- Ustaw
BOARD_SUPER_PARTITION_BLOCK_DEVICES
na listę urządzeń blokowych używanych do przechowywania fragmentów partycji dynamicznych. To jest lista nazw istniejących partycji fizycznych na urządzeniu. - Ustaw
BOARD_SUPER_PARTITION_ partition _DEVICE_SIZE
odpowiednio na rozmiary każdego urządzenia blokowego 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łyt. - Anuluj 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, na którym są przechowywane metadane partycji dynamicznej. Musi to być jedno zBOARD_SUPER_PARTITION_BLOCK_DEVICES
. Zwykle jest to ustawione nasystem
. - Ustaw
BOARD_SUPER_PARTITION_GROUPS
,BOARD_ group _SIZE
iBOARD_ group _PARTITION_LIST
. Zobacz zmiany konfiguracji tablicy na nowych urządzeniach, aby uzyskać szczegółowe informacje.
Na przykład, jeśli urządzenie ma już partycje systemowe i dostawcy, a podczas aktualizacji chcesz przekonwertować je na partycje dynamiczne i dodać nową partycję produktu, ustaw tę 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 SELinuksie
Urządzenia blokowe superpartycji muszą być oznaczone atrybutem super_block_device_type
. Na przykład, jeśli urządzenie ma już partycje system
i vendor
, chcesz ich używać jako urządzeń blokowych do przechowywania fragmentów partycji dynamicznych, a ich dowiązania symboliczne według nazwy 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;
Inne konfiguracje znajdziesz w artykule Implementowanie partycji dynamicznych na nowych urządzeniach .
Aby uzyskać więcej informacji o aktualizacjach modernizacyjnych, zobacz OTA dla urządzeń A/B bez partycji dynamicznych .
Obrazy fabryczne
W przypadku uruchamiania urządzenia z obsługą partycji dynamicznych należy unikać używania 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 temu zaradzić, make dist
buduje teraz dodatkowy obraz super.img
, który można sflashować bezpośrednio na super partycję. Automatycznie łączy zawartość partycji logicznych, co oznacza, że zawiera system.img
, vendor.img
itd., oprócz metadanych super
. Ten obraz można przesłać bezpośrednio na super
partycję bez żadnych dodatkowych narzędzi lub przy użyciu 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 gnieździe A. Po bezpośrednim flashowaniu superobrazu zaznacz gniazdo A jako rozruchowe przed ponownym uruchomieniem urządzenia.
W przypadku urządzeń modernizowanych make dist
tworzy zestaw obrazów super_*.img
, które można przesłać bezpośrednio do odpowiednich partycji fizycznych. Na przykład twórz make dist
builds super_system.img
i super_vendor.img
, gdy dostawcą systemu jest BOARD_SUPER_PARTITION_BLOCK_DEVICES
. Te obrazy są umieszczane w folderze OTA w target_files.zip
.
Dostrajanie urządzeń pamięci masowej mapowania urządzeń
Partycjonowanie dynamiczne obsługuje wiele niedeterministycznych obiektów mapowania urządzeń. Nie wszystkie mogą tworzyć wystąpienia zgodnie z oczekiwaniami, dlatego należy śledzić wszystkie instalacje i aktualizować właściwości systemu Android wszystkich skojarzonych partycji z ich podstawowymi urządzeniami pamięci masowej.
Mechanizm wewnątrz init
śledzi instalacje i asynchronicznie aktualizuje właściwości systemu Android. Nie ma gwarancji, że czas, który to zajmie, mieści się w określonym przedziale czasu, więc musisz zapewnić wystarczająco dużo czasu, aby on property
aktywatory usługi zareagowały. 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 nazwą podstawowego 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ć dostosowywane przez platformę w razie potrzeby za pomocą poleceń takich jak:
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, a wartości zaczynają się aktualizować. Jednakże, ponieważ wyzwalacze właściwości nie są aktywne aż do późnego init
, nie można ich użyć na początkowych etapach rozruchu do obsługi root
, system
lub vendor
. Można oczekiwać, że domyślne ustawienie read_ahead_kb
w jądrze będzie wystarczające, dopóki skrypty init.rc
nie będą mogły nadpisać we early-fs
(kiedy uruchamiane są różne demony i udogodnienia). Dlatego Google zaleca korzystanie z funkcji on property
w połączeniu z właściwością kontrolowaną przez init.rc
, taką jak sys.read_ahead_kb
, w celu radzenia sobie z synchronizacją operacji i zapobiegania wyścigom, 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}