Aby pakować i instalować moduły systemu operacyjnego Android na niższym poziomie, możesz używać formatu pliku APEX. Pozwala na niezależne tworzenie instalacja komponentów takich jak usługi i biblioteki natywne, HAL wdrożenia, oprogramowanie układowe, pliki konfiguracyjne itp.
Dostawca APEX jest instalowany automatycznie przez system kompilacji w partycji /vendor
i aktywowany w czasie wykonywania przez apexd
, tak jak APEX w innych partycjach.
Przykłady zastosowań
Modułowe obrazy dostawców
Punkty APEX ułatwiają naturalne grupowanie i modularyzację cech implementacji na obrazach dostawców.
Gdy obrazy dostawcy są tworzone jako kombinacja niezależnie utworzonych przez dostawcę APEX-ów, producenci urządzeń mogą łatwo wybrać konkretne implementacje dostawcy, które chcą mieć na swoim urządzeniu. Producenci mogą nawet stworzyć wskaźnik APEX nowego dostawcy, jeśli żaden z nich nie odpowiada jego potrzebom lub Zupełnie nowy, niestandardowy sprzęt.
Na przykład producent OEM może stworzyć urządzenie z implementacją AOSP APEX dla Wi-Fi, implementacją APEX dla Bluetootha w systemie SoC oraz niestandardową implementacją APEX dla telefonii.
W przypadku implementacji bez punktów APEX dostawców jest tak wiele zależności wymaga dokładnej koordynacji i śledzenia. Dzięki temu, że wszystkie komponenty (w tym pliki konfiguracyjne i dodatkowe biblioteki) są zapakowane w APEX z wyraźnie zdefiniowanymi interfejsami w dowolnym punkcie komunikacji między funkcjami, różne komponenty stają się wymienne.
Iteracja dewelopera
APEX dostawców pomaga deweloperom w szybszej iteracji oraz opracowywanie modułów dostawców przez łączenie całej implementacji funkcji, na przykład interfejsu HAL Wi-Fi, w ramach jednego dostawcy. APEX. Deweloperzy mogą tworzyć i przesyłać pojedyncze wersje APEX dostawcy, aby przetestować zmiany, zamiast odtwarzać całą zawartość obrazu dostawcy.
Ułatwia to i przyspiesza cykl iteracji u deweloperów, którzy Pracują głównie w ramach jednego obszaru cech i chcesz wykorzystać tę cechę w pobliżu.
Naturalne grupowanie obszarów cech w APEX również upraszcza proces. tworzenia, wprowadzania i testowania zmian w danym obszarze cech. Na przykład ponowne instalowanie pakietu APEX powoduje automatyczne zaktualizowanie wszystkich pakietów biblioteki lub plików konfiguracji, które zawiera.
Dołączenie obszaru cech do punktu APEX upraszcza też debugowanie lub przywracanie, gdy zaobserwowane nieprawidłowe działanie urządzenia. Jeśli na przykład telefon nie działa słabo w nowej wersji, programiści mogą spróbować zainstalować starsze wdrożenia APEX na urządzeniu (bez konieczności aktualizowania pełnej kompilacji). czy wróci do normalnego działania.
Przykładowy przepływ pracy:
# Build the entire device and flash. OR, obtain an already-flashed device.
source build/envsetup.sh && lunch oem_device-userdebug
m
fastboot flashall -w
# Test the device.
... testing ...
# Check previous behavior using a vendor APEX from one week ago, downloaded from
# your continuous integration build.
... download command ...
adb install <path to downloaded APEX>
adb reboot
... testing ...
# Edit and rebuild just the APEX to change and test behavior.
... edit APEX source contents ...
m <apex module name>
adb install out/<path to built APEX>
adb reboot
... testing ...
Przykłady
Podstawy
Zobacz główną stronę Format pliku APEX, aby uzyskać informacje o ogólnym formacie APEX. informacje, w tym wymagania dotyczące urządzeń, szczegóły formatów plików kroków instalacji.
W pliku Android.bp
ustawienie właściwości vendor: true
powoduje, że moduł APEX staje się dostawcą APEX.
apex {
..
vendor: true,
..
}
pliki binarne i biblioteki udostępnione.
Pakiet APEX zawiera zależności tranzytowe w swojej łańcuchce, chyba że mają stabilne interfejsy.
Stabilne natywne interfejsy dla zależności APEX dostawcy obejmują cc_library
z bibliotekami stubs
i LLNDK. Te zależności są wykluczane z opakowania, a ich nazwy są zapisywane w pliku manifestu APEX. Plik manifestu jest przetwarzany przez linkerconfig
, aby zewnętrzne natywne zależności były dostępne w czasie wykonywania.
W tym fragmencie segment APEX zawiera zarówno plik binarny (my_service
), jak i jego parametr
zależności niestabilne (liczba plików: *.so
).
apex {
..
vendor: true,
binaries: ["my_service"],
..
}
W poniższym fragmencie interfejs APEX zawiera zasoby udostępniane
my_standalone_lib
i wszystkich jego niestabilnych zależności (jak opisano powyżej).
apex {
..
vendor: true,
native_shared_libs: ["my_standalone_lib"],
..
}
Pomniejszanie APEX
APEX może wzrosnąć, ponieważ obejmuje niestabilne zależności. Zalecamy stosowanie łączenia stałego. Typowe biblioteki, takie jak libc++.so
i libbase.so
, można połączyć statycznie z plikami binarnymi HAL. Utworzenie zależności w celu zapewnienia stabilnej
interfejs może być inną opcją. Zależność nie zostanie zgrupowana w APEX.
Implementacje HAL
Aby zdefiniować implementację HAL, udostępnij odpowiednie pliki binarne i biblioteki w APEX dostawcy, podobnie jak w następujących przykładach:
Aby w pełni ująć implementację HAL, APEX powinien też określać odpowiednie fragmenty VINTF i skrypty inicjalizacji.
Fragmenty VINTF
Fragmenty VINTF mogą być wyświetlane z apex dostawcy, jeśli fragmenty znajdują się w etc/vintf
apexa.
Aby umieścić fragmenty VINTF w APEX, użyj właściwości prebuilts
.
apex {
..
vendor: true,
prebuilts: ["fragment.xml"],
..
}
prebuilt_etc {
name: "fragment.xml",
src: "fragment.xml",
sub_dir: "vintf",
}
Interfejsy zapytań API
Po dodaniu fragmentów VINTF do APEX użyj interfejsów API libbinder_ndk
, aby uzyskać
mapowania interfejsów HAL i nazw APEX.
AServiceManager_isUpdatableViaApex("com.android.foo.IFoo/default")
:true
jeśli instancja HAL jest zdefiniowana w APEX.AServiceManager_getUpdatableApexName("com.android.foo.IFoo/default", ...)
: pobiera nazwę APEX, która definiuje instancję HAL.AServiceManager_openDeclaredPassthroughHal("mapper", "instance", ...)
: użyj go do otwarcia przekazującej części HAL.
Skrypty init
APEX może zawierać skrypty inicjalizacji na 2 sposoby: (A) w ramach wstępnie utworzonego pliku tekstowego w pakiecie danych APEX lub (B) w zwykłym pliku inicjalizacji w pliku /vendor/etc
. Możesz ustawić oba
dla tego samego wskaźnika APEX.
Skrypt inicjujący w Apex:
prebuilt_etc {
name: "myinit.rc",
src: "myinit.rc"
}
apex {
..
vendor: true,
prebuilts: ["myinit.rc"],
..
}
Scenariusze inicjalizacji w plikach APEX dostawcy mogą zawierać definicje service
i dyrektywy on <property or event>
.
Upewnij się, że definicja service
wskazuje plik binarny w tym samym pliku APEX.
Na przykład com.android.foo
APEX może zdefiniować usługę o nazwie foo-service
.
on foo-service /apex/com.android.foo/bin/foo
...
Zachowaj ostrożność podczas korzystania z dyrektyw on
. Skrypty inicjalizacji w APEX są analizowane i wykonywane po aktywowaniu APEX, więc niektórych zdarzeń i właściwości nie można używać. Użyj apex.all.ready=true
, aby jak najszybciej wywołać działania.
W przypadku węzłów APEX można używać parametru on init
, ale nie
on early-init
Oprogramowanie układowe
Przykład:
Wstaw oprogramowanie układowe do dostawcy APEX z typem modułu prebuilt_firmware
w następujący sposób.
prebuilt_firmware {
name: "my.bin",
src: "path_to_prebuilt_firmware",
vendor: true,
}
apex {
..
vendor: true,
prebuilts: ["my.bin"], // installed inside APEX as /etc/firmware/my.bin
..
}
<apex name>/etc/firmware
zawiera moduły prebuilt_firmware
katalogu APEX. ueventd
skanuje /apex/*/etc/firmware
katalogi do
modułów oprogramowania układowego.
Element file_contexts
APEX powinien oznaczyć etykietą wszystkie wpisy ładunku oprogramowania układowego
aby zapewnić, że ueventd
będzie mieć do nich dostęp w czasie działania;
zwykle wystarczy etykieta vendor_file
. Na przykład:
(/.*)? u:object_r:vendor_file:s0
Moduły jądra
Umieść moduły jądra w APEX dostawcy jako gotowe moduły w podany niżej sposób.
prebuilt_etc {
name: "my.ko",
src: "my.ko",
vendor: true,
sub_dir: "modules"
}
apex {
..
vendor: true,
prebuilts: ["my.ko"], // installed inside APEX as /etc/modules/my.ko
..
}
Pozycja file_contexts
punktu APEX powinna oznaczać etykietami wszystkie wpisy ładunku modułu jądra.
w dowolnym momencie. Na przykład:
/etc/modules(/.*)? u:object_r:vendor_kernel_modules:s0
Moduły jądra muszą być zainstalowane jawnie. Ten przykładowy skrypt init
na partycji dostawcy pokazuje instalację za pomocą insmod
:
my_init.rc
:
on early-boot
insmod /apex/myapex/etc/modules/my.ko
..
Nakładki zasobów środowiska wykonawczego
Przykład:
Umieszczanie nakładek zasobów środowiska wykonawczego w APEX dostawcy
za pomocą właściwości rros
.
runtime_resource_overlay {
name: "my_rro",
soc_specific: true,
}
apex {
..
vendor: true,
rros: ["my_rro"], // installed inside APEX as /overlay/my_rro.apk
..
}
Inne pliki konfiguracji
Punkty APEX dostawcy obsługują różne inne pliki konfiguracyjne, które zwykle można znaleźć u dostawcy. jako wstępnie utworzoną w węzłach APEX dostawcy i dodawane są kolejne.
Przykłady:
- Pliki XML deklaracji funkcji
- Czujniki mają pliki XML jako wstępnie utworzone w HAL dostawcy czujnika APEX.
- Wejściowe pliki konfiguracyjne
- Konfiguracje ekranu dotykowego jako wstępnie utworzone w APEX dostawcy tylko z konfiguracją
Wczytywanie dostawcy APEX
Niektóre usługi HAL, takie jak keymint
, powinny być dostępne, zanim APEX
Aktywowano. Te HALe zwykle ustawiają early_hal
w definicji usługi w skrypcie init. Inny przykład to klasa animation
, która jest zwykle rozpoczęta
wcześniej niż w przypadku zdarzenia post-fs-data
. Jeśli taka wczesna usługa HAL jest spakowana w usługę APEX dostawcy, ustaw wartość "vendorBootstrap": true
w pliku manifestu APEX, aby można było ją aktywować wcześniej. Pamiętaj, że bootstrap APEX można aktywować tylko z gotowej lokalizacji, takiej jak /vendor/apex
, a nie z /data/apex
.
Właściwości systemowe
Są to właściwości systemu rozpoznawane przez platformę w celu obsługi dostawcy Punkty APEX:
input_device.config_file.apex=<apex name>
– po ustawieniu wartości wejściowe. pliki konfiguracji (*.idc
,*.kl
i*.kcm
) są wyszukiwane z Katalog/etc/usr
indeksu APEX.ro.vulkan.apex=<apex name>
– gdy jest ustawione, sterownik Vulkan jest ładowany z a APEX. Ze względu na to, że sterownik Vulkan jest używany przez pierwsze platformy HAL, APEX Wczytaj APEX i skonfiguruj przestrzeń nazw tagu łączącego widoczne.
Ustaw właściwości systemu w skryptach init za pomocą polecenia setprop
.
Dodatkowe funkcje programistyczne
Wybór APEX podczas uruchamiania
Przykład:
Deweloperzy mogą też instalować wiele wersji APEX dostawcy, które mają tę samą nazwę i klucz APEX, a następnie wybierać, która wersja ma być aktywowana podczas każdego rozruchu za pomocą trwałych właściwości systemowych. W przypadku niektórych zastosowań może to być prostsze niż zainstalowanie nowej kopii APEX za pomocą adb install
.
Przykładowe zastosowania:
- Zainstaluj 3 wersje interfejsu APEX dostawcy Wi-Fi HAL: zespoły kontroli jakości mogą przeprowadzać konfigurację ręcznie lub automatyczne testowanie na podstawie jednej wersji, ponownie uruchomić testy, a następnie porównać ich ostateczne wyniki.
- Zainstaluj 2 wersje HAL APEX dostawcy aparatu: obecna i eksperymentalne: użytkownicy mogą używać wersji eksperymentalnej bez pobranie i zainstalowanie dodatkowego pliku, aby można było łatwo przywrócić nowy plik.
Podczas uruchamiania apexd
szuka atrybutów sysprop w określonym formacie, aby aktywować odpowiednią wersję APEX.
Oczekiwane formaty klucza usługi:
- Konfiguracja rozruchowa
- Służy do ustawiania wartości domyślnej w
BoardConfig.mk
. androidboot.vendor.apex.<apex name>
- Służy do ustawiania wartości domyślnej w
- Stały sysprop
- Służy do zmiany wartości domyślnej ustawionej na urządzeniu, które zostało już uruchomione.
- Zastępuje wartość bootconfig, jeśli jest podana.
persist.vendor.apex.<apex name>
Wartością tej właściwości powinien być plik APEX, który należy aktywować.
// Default version.
apex {
name: "com.oem.camera.hal.my_apex_default",
vendor: true,
..
}
// Non-default version.
apex {
name: "com.oem.camera.hal.my_apex_experimental",
vendor: true,
..
}
Wersję domyślną należy też skonfigurować za pomocą konfiguracji rozruchowej w
BoardConfig.mk
:
# Example for APEX "com.oem.camera.hal" with the default above:
BOARD_BOOTCONFIG += \
androidboot.vendor.apex.com.oem.camera.hal=com.oem.camera.hal.my_apex_default
Po uruchomieniu urządzenia zmień aktywną wersję, ustawiając wartość trwały sysprop:
$ adb root;
$ adb shell setprop \
persist.vendor.apex.com.oem.camera.hal \
com.oem.camera.hal.my_apex_experimental;
$ adb reboot;
Jeśli urządzenie obsługuje aktualizowanie bootconfig po przeflashowaniu (np. za pomocą poleceń fastboot
oem
), zmiana właściwości bootconfig dla zainstalowanego na wielu urządzeniach Apexa powoduje również zmianę wersji aktywowanej podczas uruchamiania.
W przypadku wirtualnych urządzeń referencyjnych opartych na Cuttlefish możesz użyć polecenia --extra_bootconfig_args
, aby ustawić właściwość bootconfig bezpośrednio podczas uruchamiania. Na przykład:
launch_cvd --noresume \
--extra_bootconfig_args "androidboot.vendor.apex.com.oem.camera.hal:=com.oem.camera.hal.my_apex_experimental";