Dostawca – APEX

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_libi 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++.solibbase.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:

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>
  • 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";