Korzystanie z Binder IPC

Ta strona opisuje zmiany w sterowniku bindera w systemie Android 8, zawiera szczegółowe informacje na temat korzystania z IPC bindera i zawiera listę wymaganych zasad SELinux.

Zmiany w sterowniku spoiwa

Począwszy od systemu Android 8, platforma systemu Android i warstwy HAL komunikują się teraz ze sobą za pomocą spinacza. Ponieważ ta komunikacja znacznie zwiększa ruch w binderach, Android 8 zawiera kilka ulepszeń zaprojektowanych w celu utrzymania szybkości IPC binderów. SoC sprzedawców i producentów sprzętu należy połączyć bezpośrednio z odpowiednich gałęzi Android 4.4, Android 4.9 i wyższe o kernel / wspólnego projektu.

Wiele domen wiążących (konteksty)

Common-4.4 i wyższe, w tym upstream

Aby gładko ułamek ruch spoiwa między ramami (niezależne od urządzenia), a sprzedawca (specyficzny dla urządzenia) Kod Android 8 wprowadza się koncepcję związku wiążącego. Każdy kontekst spinacza ma własny węzeł urządzenia i własnego menedżera kontekstu (usługi). Dostęp do menedżera kontekstu można uzyskać tylko przez węzeł urządzenia, do którego należy, a podczas przekazywania węzła spinacza przez określony kontekst jest on dostępny z tego samego kontekstu tylko przez inny proces, całkowicie izolując w ten sposób domeny od siebie. Szczegółowe informacje o używaniu, zobacz vndbinder i vndservicemanager .

Rozpraszaj-zbieraj

Common-4.4 i wyższe, w tym upstream

W poprzednich wersjach systemu Android każdy element danych w wywołaniu segregatora został skopiowany trzykrotnie:

  • Raz, aby szeregować je w Parcel w procesie wywołującego
  • Raz w sterowniku jądra skopiować Parcel do procesu docelowego
  • Raz do unserialize się Parcel w procesie docelowej

Android 8 zastosowania rozproszenie-zebranie optymalizacji w celu zmniejszenia liczby kopii od 3 do 1. Zamiast szeregowania danych w Parcel pierwsze szczątki danych w jego pierwotnej struktury układu i pamięci, a kierowca natychmiast kopiuje go do procesu docelowego. Po tym, jak dane znajdą się w procesie docelowym, struktura i układ pamięci są takie same, a dane można odczytać bez konieczności wykonywania kolejnej kopii.

Blokowanie drobnoziarniste

Common-4.4 i wyższe, w tym upstream

W poprzednich wersjach systemu Android sterownik bindera wykorzystywał globalną blokadę w celu ochrony przed równoczesnym dostępem do krytycznych struktur danych. Chociaż rywalizacja o blokadę była minimalna, głównym problemem było to, że jeśli wątek o niskim priorytecie uzyska blokadę, a następnie zostanie wywłaszczony, może to poważnie opóźnić wątki o wyższym priorytecie, które wymagają uzyskania tej samej blokady. To spowodowało szarpnięcie w platformie.

Pierwsze próby rozwiązania tego problemu polegały na wyłączeniu wywłaszczania podczas utrzymywania blokady globalnej. Jednak było to bardziej włamanie niż prawdziwe rozwiązanie i ostatecznie zostało odrzucone przez upstream i odrzucone. Kolejne próby koncentrowały się na dopracowaniu blokowania, którego wersja działa na urządzeniach Pixel od stycznia 2017 roku. Podczas gdy większość tych zmian została upubliczniona, w kolejnych wersjach wprowadzono znaczne ulepszenia.

Po zidentyfikowaniu drobnych problemów w drobnoziarnistej implementacji blokowania opracowaliśmy ulepszone rozwiązanie z inną architekturą blokowania i przedstawiliśmy zmiany we wszystkich popularnych gałęziach jądra. Nadal testujemy tę implementację na wielu różnych urządzeniach; ponieważ nie znamy żadnych nierozstrzygniętych problemów, jest to zalecana implementacja dla urządzeń dostarczanych z systemem Android 8.

Dziedziczenie priorytetów w czasie rzeczywistym

Common-4,4 i common-4,9 (wkrótce w górę)

Sterownik bindera zawsze wspierał ładne dziedziczenie priorytetów. Ponieważ coraz większa liczba procesów w systemie Android działa z priorytetem czasu rzeczywistego, w niektórych przypadkach ma sens, że jeśli wątek czasu rzeczywistego wykonuje wywołanie spinacza, wątek w procesie, który obsługuje to wywołanie, również działa z priorytetem czasu rzeczywistego . Aby obsługiwać te przypadki użycia, system Android 8 implementuje teraz dziedziczenie priorytetów w czasie rzeczywistym w sterowniku spinacza.

Oprócz transakcji poziom priorytetu dziedziczenia, dziedziczenie pozwala priorytet węzeł węzeł (spoiwo obiektu serwisowego), aby określić priorytet minimalną, przy której powołuje do tego węzła powinny być wykonane. Poprzednie wersje systemu Android obsługiwały już dziedziczenie priorytetów węzłów z ładnymi wartościami, ale system Android 8 dodaje obsługę dziedziczenia węzłów zasad planowania w czasie rzeczywistym.

Zmiany w przestrzeni użytkownika

Android 8 obejmuje wszystkie Strefa zmienia wymagane do pracy z obecnym kierowcą spoiwa we wspólnym jądrze z jednym wyjątkiem: oryginalny realizację celu wyłączenia czasu rzeczywistego priorytetu dziedziczenia dla /dev/binder stosuje się ioctl . Późniejsze prace rozwojowe przełączyły kontrolę nad dziedziczeniem priorytetów na bardziej szczegółową metodę, która jest oparta na trybie powiązania (a nie na kontekst). Zatem ioctl nie jest w Android wspólnej gałęzi i zamiast składać w naszych wspólnych jąder .

Efektem tej zmiany jest to, że w czasie rzeczywistym priorytetem dziedziczenie jest domyślnie wyłączone dla każdego węzła. Zespół wydajność Android uznał za korzystne, aby umożliwić w czasie rzeczywistym pierwszeństwa dziedziczenia dla wszystkich węzłów w hwbinder domenie. Aby osiągnąć ten sam efekt, cherry-pick tę zmianę w przestrzeni użytkownika.

SHA dla popularnych jąder

Aby uzyskać niezbędne zmiany w sterowniku spinacza, zsynchronizuj z odpowiednim SHA:

  • Zwykłe-3,18
    cc8b90c121de ANDROID: binder: nie sprawdzaj uprawnień priorytetowych podczas przywracania.
  • Wspólne-4.4
    76b376eac7a2 ANDROID: binder: nie sprawdzaj uprawnień priorytetowych podczas przywracania.
  • Wspólne-4,9
    ecd972d4f9b5 ANDROID: binder: nie sprawdzaj uprawnień priorytetowych podczas przywracania.

Korzystanie z segregatora IPC

Historycznie, procesy dostawców używały do ​​komunikacji międzyprocesowej komunikacji spinacza (IPC). W Androida 8, /dev/binder węzeł urządzenie staje się wyłącznie w procesach ramowych, czyli procesy sprzedawca nie ma do niego dostęp. Procesy sprzedawca może uzyskać dostęp do /dev/hwbinder , ale musi konwertować swoje interfejsy AIDL do użytku HIDL. W przypadku dostawców, którzy chcą nadal używać interfejsów AIDL między procesami dostawców, system Android obsługuje IPC spinacza, jak opisano poniżej.

vndbinder

Android 8 obsługuje nową domeną spoiwo do wykorzystania przez dostawców usług, dostęp za pomocą /dev/vndbinder zamiast /dev/binder . Z dodatkiem /dev/vndbinder , Android ma obecnie następujące trzy domeny IPC:

Domena IPC Opis
/dev/binder IPC między frameworkami/procesami aplikacji z interfejsami AIDL
/dev/hwbinder IPC między procesami framework/dostawca z interfejsami HIDL
IPC między procesami dostawcy z interfejsami HIDL
/dev/vndbinder IPC między procesami dostawcy/dostawcy z interfejsami AIDL

Do /dev/vndbinder się pojawiać, zapewniają element Konfiguracja jądra CONFIG_ANDROID_BINDER_DEVICES jest ustawiony na "binder,hwbinder,vndbinder" (jest to ustawienie domyślne w typowych drzew jądra Androida).

Zwykle procesy sprzedawca nie otworzyć sterownik spoiwa i zamiast bezpośrednio połączyć przeciwko libbinder biblioteki przestrzeni użytkownika, który otwiera sterownik wiążącą. Dodawanie metodę ::android::ProcessState() wybiera kierowcę spoiwa dla libbinder . Procesy sprzedawca powinien wywołać tę metodę przed wywołaniem do ProcessState, IPCThreadState lub przed dokonaniem jakichkolwiek połączeń wiążącej w ogóle. Do użytku, należy umieścić następujące wywołanie po main() procesu dostawcy (klient i serwer):

ProcessState::initWithDriver("/dev/vndbinder");

vndservicemanager

Wcześniej, pochłaniacz usługi zostały zarejestrowane servicemanager , gdzie mogły być pobierane przez inne procesy. W Androidzie 8, servicemanager jest obecnie wykorzystywana wyłącznie przez ramowych i aplikacji procesów i procesów nie może już do niego dostęp dostawców.

Jednak dostawcy usług mogą teraz korzystać vndservicemanager , nową instancję servicemanager że używa /dev/vndbinder zamiast /dev/binder i który jest zbudowany z tych samych źródeł, jak ramowej servicemanager . Procesy sprzedawca nie ma potrzeby wprowadzania zmian do rozmowy vndservicemanager ; kiedy otwiera proces sprzedawca / dev/vndbinder , wyszukiwań serwis automatycznie przejść do vndservicemanager .

vndservicemanager binarny jest wliczone w makefile domyślne urządzenie z Androidem jest.

Polityka SELinux

Procesy dostawców, które chcą używać funkcji spinacza do komunikowania się ze sobą, potrzebują następujących elementów:

  1. Dostęp do /dev/vndbinder .
  2. Spoiwo {transfer, call} haki do vndservicemanager .
  3. binder_call(A, B) do każdej domeny dostawcy, który chce zadzwonić do domeny dostawcy B przez interfejs spoiwa sprzedawca.
  4. Pozwolenie na {add, find} usług vndservicemanager .

Aby spełnić wymagania 1 i 2, należy użyć vndbinder_use() makro:

vndbinder_use(some_vendor_process_domain);

Aby spełnić wymóg 3, binder_call(A, B) dla dostawcy procesów A i B, które trzeba omówić spoiwo może pozostać na swoim miejscu, i nie potrzebuje zmiany nazwy.

Aby spełnić wymaganie 4, należy wprowadzić zmiany w sposobie obsługi nazw usług, etykiet usług i reguł.

Szczegółowe informacje dotyczące SELinux, zobacz Security-Enhanced Linux w Androidzie . Szczegółowe informacje dotyczące SELinux w Androidzie 8.0, patrz SELinux dla Androida 8.0 .

Nazwy usług

Wcześniej procesy sprzedawca zarejestrowany nazw usług w service_contexts pliku i dodaje odpowiadający zasady dostępu do tego pliku. Przykład service_contexts Dane z device/google/marlin/sepolicy :

AtCmdFwd                              u:object_r:atfwd_service:s0
cneservice                            u:object_r:cne_service:s0
qti.ims.connectionmanagerservice      u:object_r:imscm_service:s0
rcs                                   u:object_r:radio_service:s0
uce                                   u:object_r:uce_service:s0
vendor.qcom.PeripheralManager         u:object_r:per_mgr_service:s0

W Androidzie 8, vndservicemanager ładunki z vndservice_contexts pliku zamiast. Usługi dostawców migrujące do vndservicemanager (i które są już w Starym service_contexts pliku) należy dodać do nowej vndservice_contexts pliku.

Etykiety serwisowe

Wcześniej usługa etykiety takie jak u:object_r:atfwd_service:s0 zostały zdefiniowane w service.te pliku. Przykład:

type atfwd_service,      service_manager_type;

W Androidzie 8, należy zmienić typ na vndservice_manager_type i przenieść regułę do vndservice.te pliku. Przykład:

type atfwd_service,      vndservice_manager_type;

Zasady ServiceManagera

Wcześniej zachowaniem zasad przyznano dostęp do domen dodać lub znaleźć usługi z servicemanager . Przykład:

allow atfwd atfwd_service:service_manager find;
allow some_vendor_app atfwd_service:service_manager add;

W Androidzie 8 takie reguły mogą pozostać na miejscu i używać tej samej klasy. Przykład:

allow atfwd atfwd_service:service_manager find;
allow some_vendor_app atfwd_service:service_manager add;