W Androidzie 12 GKI 2.0 zastępuje alokator ION DMA-BUF gromadzi się z następujących powodów:
- Bezpieczeństwo: każda sterta DMA-BUF jest oddzielnym urządzeniem znakowym, więc
do każdej sterty można sterować oddzielnie za pomocą metody sepolicy. To nie było
możliwe dzięki ION, ponieważ alokacja z dowolnej sterty wymaga dostępu jedynie do
urządzenie
/dev/ion
. - Stabilność ABI: w przeciwieństwie do ION, interfejs IOCTL platformy DMA-BUF jest Stabilny interfejs ABI, ponieważ znajduje się w nadrzędnym jądrze Linuksa.
- Standaryzacja: platforma stert DMA-BUF zapewnia dobrze zdefiniowany interfejs UAPI. jon mogą zawierać niestandardowe flagi i identyfikatory sterty, co uniemożliwiało opracowanie wspólnych testów ponieważ implementacja ION na poszczególnych urządzeniach może działać inaczej.
Gałąź android12-5.10
wspólnego jądra Androida została wyłączona
CONFIG_ION
1 marca 2021 r.
Tło
Poniżej znajduje się krótkie porównanie sterty ION i DMA-BUF.
Podobieństwa między strukturą sterty ION i DMA-BUF
- Zarówno platformy sterty ION, jak i DMA-BUF są eksporterami DMA-BUF opartymi na stercie.
- Każda sterta definiuje własne operacje przydzielające i operacje DMA-BUF.
- Wydajność alokacji jest podobna, ponieważ oba schematy wymagają jednego IOCTL do alokacji.
Różnice między strukturą sterty ION i DMA-BUF
Stosy ION | Stosy DMA-BUF |
---|---|
Wszystkie przydziały ION są realizowane za pomocą /dev/ion .
|
Każda sterta DMA-BUF to urządzenie znakowe, które znajduje się w /dev/dma_heap/<heap_name> .
|
ION obsługuje flagi prywatne stosu. | Stosy DMA-BUF nie obsługują prywatnych flag sterty. Każdy z nich
alokacja jest wykonywana na innej stercie. Na przykład pliki z pamięci podręcznej
niebuforowane warianty sterty systemu to osobne sterty znajdujące się na
/dev/dma_heap/system i
/dev/dma_heap/system_uncached
|
Na potrzeby alokacji należy określić identyfikator sterty/maskę i flagi. | Nazwa sterty służy do alokacji. |
W kolejnych sekcjach znajdziesz listę komponentów obsługujących ION na platformę DMA-BUF.
Przejście ze sterowników jądra ION na sterty DMA-BUF
Sterowniki jądra implementujące sterty ION
Dzięki sterom ION i DMA-BUF każda z nich może wdrażać własne alokatory Operacje DMA-BUF. Możesz więc przejść z implementacji sterty ION na stertę DMA-BUF przy użyciu innego zestawu interfejsów API do zarejestrowania stosu. Ta tabela pokazuje interfejsy API rejestracji sterty ION i odpowiadające im interfejsy API sterty DMA-BUF.
Stosy ION | Stosy DMA-BUF |
---|---|
void ion_device_add_heap(struct ion_heap *heap)
|
struct dma_heap *dma_heap_add(const struct dma_heap_export_info *exp_info);
|
void ion_device_remove_heap(struct ion_heap *heap)
|
void dma_heap_put(struct dma_heap *heap);
|
Stosy DMA-BUF nie obsługują prywatnych flag sterty. Każdy wariant stosu
należy zarejestrować indywidualnie za pomocą: dma_heap_add()
API. Aby ułatwić udostępnianie kodu, zalecamy zarejestrowanie wszystkich wariantów
w ramach tego samego sterownika.
Ten przykład dma-buf: system_heap
pokazuje implementację wariantów systemu z pamięci podręcznej i z niebuforowanej
sterta.
Użyj tego szablonu: dma-buf: heaps: przykładowy szablon aby utworzyć od podstaw stertę DMA-BUF.
Sterowniki jądra bezpośrednio przydzielające ze sterty ION
Platforma stertów DMA-BUF zapewnia również interfejs alokacji dla klientów w jądrze. Zamiast określać maskę stosu i flagi do wyboru typ alokacji, interfejs oferowany przez sterty DMA-BUF przyjmuje nazwę sterty jako dane wejściowe.
Poniżej widać interfejs API alokacji ION w jądrze i odpowiadający mu DMA-BUF
interfejsów API alokacji sterty. Sterowniki jądra mogą używać interfejsu API dma_heap_find()
do wysyłania zapytań
istnienie sterty. Interfejs API zwraca wskaźnik do instancji
struct dma_heap, który można następnie przekazać jako argument do funkcji
Interfejs API dma_heap_buffer_alloc()
.
Stosy ION | Stosy DMA-BUF |
---|---|
struct dma_buf *ion_alloc(size_t len, unsigned int heap_id_mask, unsigned int flags)
|
|
Sterowniki jądra używające komponentów DMA-BUF
W przypadku sterowników, które importują tylko pliki DMA-BUF, nie są wymagane żadne zmiany, ponieważ przydzielona ze stosu ION działa dokładnie tak samo jak bufor przydzielony z odpowiednią stertę DMA-BUF.
Przenieś klientów przestrzeni użytkownika ION do sterty DMA-BUF
Aby ułatwić przejście klientom w przestrzeni użytkownika ION,
biblioteka o nazwie
libdmabufheap
jest dostępna. libdmabufheap
obsługuje alokację na stertach DMA-BUF
i sterty ION. Najpierw sprawdza, czy istnieje sterta DMA-BUF o podanej nazwie
a w przeciwnym razie wybiera równoważną stertę ION, o ile taka istnieje.
Klienty powinny zainicjować
BufferAllocator
obiektu podczas inicjowania zamiast otwierania /dev/ion using
ion_open()
. Dzieje się tak, ponieważ deskryptory plików tworzone przez otwarcie
Aplikacje /dev/ion
i /dev/dma_heap/<heap_name>
są zarządzane
wewnętrznie przez obiekt BufferAllocator
.
Aby przejść z libion
na libdmabufheap
, zmodyfikuj działanie klientów jako
następujące:
- Śledź nazwę sterty na potrzeby alokacji, a nie w nagłówku Flaga identyfikatora/maski i sterty.
- Zastąp interfejs API
ion_alloc_fd()
, który przyjmuje maskę stosu i argument flagi. za pomocą interfejsu APIBufferAllocator::Alloc()
, który przyjmuje nazwę stosu.
Ta tabela ilustruje te zmiany, pokazując, jak funkcje libion
i libdmabufheap
i wykonanie alokacji sterty niebuforowanej w pamięci podręcznej.
Typ przydziału | Libion | libdmabufheap |
---|---|---|
Alokacja w pamięci podręcznej ze sterty systemu | ion_alloc_fd(ionfd, size, 0, ION_HEAP_SYSTEM, ION_FLAG_CACHED, &fd)
|
allocator->Alloc("system", size)
|
Niebuforowana alokacja ze sterty systemu | ion_alloc_fd(ionfd, size, 0, ION_HEAP_SYSTEM, 0, &fd)
|
allocator->Alloc("system-uncached", size)
|
wariant stosu systemu bez pamięci podręcznej
oczekuje na zatwierdzenie w hierarchii, ale jest już częścią android12-5.10
gałąź.
Aby ułatwić uaktualnianie urządzeń, interfejs API MapNameToIonHeap()
umożliwia mapowanie stosu
parametry stosu ION (nazwa sterty lub maska i flagi), aby umożliwić
a interfejsy API używają alokacji na podstawie nazw. Tutaj znajdziesz przydział oparty na nazwach
przykład.
Dokumentacja każdego interfejsu API udostępnianego przez
libdmabufheap
jest dostępna.
biblioteka
udostępnia też plik nagłówkowy do użytku przez klienty w języku C.
Referencyjna implementacja Gralloc
Implementacja Gralloc Hikey960 wykorzystuje pole libdmabufheap
, więc można go używać jako
odwołanie
Wymagane nieustawione dodatki
Dla każdego nowo utworzonego sterty DMA-BUF dla konkretnego urządzenia dodaj nowy wpis do sekcji
ueventd.rc
na urządzeniu.
Ta konfiguracja przestała obsługiwać sterty DMA-BUF
przykład
przedstawia sposób wykonania tego działania dla sterty systemu DMA-BUF.
Wymagane dodatki sepolicy
Dodaj uprawnienia Sepolicy, aby umożliwić klientowi przestrzeni użytkownika dostęp do nowego obiektu DMA-BUF sterta. Ta dodanie jest wymagane uprawnienia przykład uprawnień sepolicy utworzonych dla różnych klientów uzyskać dostęp do stosu systemu DMA-BUF.
Dostęp do stert dostawców z poziomu kodu platformy
Aby zapewnić zgodność z Treble, kod platformy można przydzielać tylko ze wstępnie zatwierdzonych i kategoriami stosów dostawców.
Na podstawie opinii partnerów zidentyfikowaliśmy 2 kategorie: sterty dostawców, do których dostęp musi być uzyskiwany za pomocą kodu platformy:
- Sterty oparte na stercie systemu z wydajnością specyficzną dla urządzenia lub układu SOC i optymalizacji.
- Stert, które mają zostać przydzielone z chronionej pamięci.
Stosy na podstawie stosu systemu z optymalizacją wydajności w zależności od urządzenia lub układu SOC
Aby obsługiwać ten przypadek użycia, implementacja sterty domyślnej sterty DMA-BUF może być zastąpiona.
- Funkcja
CONFIG_DMABUF_HEAPS_SYSTEM
została wyłączona w aplikacjigki_defconfig
, aby mogła moduł dostawcy. - Testy zgodności VTS sprawdzają, czy sterta istnieje pod adresem
/dev/dma_heap/system
. Testy sprawdzają też, czy stos może zostać przydzielonych i zwrócony deskryptor pliku (fd
) może być zmapowany na pamięć (zapisany) przez użytkownika; kosmosu.
Poprzednie punkty odnoszą się również do niebuforowanego wariantu sterty systemu, chociaż jego istnienie nie jest obowiązkowe w przypadku w pełni spójnych urządzeń reklamowych.
Stert, które mają zostać przydzielone z chronionej pamięci
Implementacje bezpiecznej sterty muszą być zależne od dostawcy, ponieważ Jądro nie obsługuje ogólnej implementacji bezpiecznej sterty.
- Zarejestruj implementacje swojego dostawcy jako
/dev/dma_heap/system-secure<vendor-suffix>
. - Te implementacje sterty są opcjonalne.
- Jeśli sterty istnieją, testy VTS służą do sprawdzania, czy można z nich korzystać przy alokacji.
- Komponenty platformy mają dostęp do tych stosu, pozwalają używać stosu za pomocą interfejsu HAL Codec2/niepowiązanej listy HAL korzystającej z tego samego procesu. Nie można jednak korzystać z ogólnych funkcji platformy Androida z powodu szczegóły implementacji. W przypadku ogólnej bezpiecznej sterty zostanie w przyszłości dodana do wspólnego jądra systemu Android, musi używać innego interfejsu ABI, aby uniknąć konfliktów z uaktualnianiem urządzeń.
Przypisujący kodek 2 dla stert DMA-BUF
Alokator kodeka dla stertów DMA-BUF jest dostępna w usłudze AOSP.
Interfejs magazynu komponentów, który umożliwia określenie parametrów sterty klucz HAL C2 jest dostępny z przydzielającym stertę C2 DMA-BUF.
Przykładowy proces przejścia dla sterty ION
Aby płynnie przejść ze sterty ION na sterty DMA-BUF, libdmabufheap
zezwala
zmieniać stertę naraz. Poniższe kroki przedstawiają sugerowany przepływ pracy
do przejścia na starszą wersję stosu ION o nazwie my_heap
, która ją obsługuje
flaga, ION_FLAG_MY_FLAG
.
Krok 1. Utwórz odpowiedniki sterty ION w ramach DMA-BUF. W tym
ponieważ sterta ION my_heap
obsługuje flagę ION_FLAG_MY_FLAG
,
zarejestrować dwie sterty DMA-BUF:
- Działanie
my_heap
jest dokładnie takie samo jak działanie sterty ION z parametrem flagaION_FLAG_MY_FLAG
wyłączona. - Zachowanie funkcji
my_heap_special
jest dokładnie takie samo jak działanie sterty ION z włączoną flagąION_FLAG_MY_FLAG
.
Krok 2. Utwórz nieoczekiwane zmiany w nowych my_heap
i
Stostki DMA-BUF (my_heap_special
). W tym momencie sterty są widoczne jako
/dev/dma_heap/my_heap
i /dev/dma_heap/my_heap_special
, z
z zamierzonych uprawnień.
Krok 3. W przypadku klientów, którzy przeprowadzają przydzielanie zadań z bazy danych my_heap
, zmodyfikuj pliki Maki
w celu połączenia z usługą libdmabufheap
. Podczas inicjowania klienta utwórz instancję
BufferAllocator
i użyj interfejsu API MapNameToIonHeap()
, aby zmapować
<ION heap name/mask, flag>
z odpowiadającymi im nazwami sterty DMA-BUF.
Na przykład:
allocator->MapNameToIonHeap("my_heap_special" /* name of DMA-BUF heap */, "my_heap" /* name of the ION heap */, ION_FLAG_MY_FLAG /* ion flags */ )
Zamiast używać interfejsu API MapNameToIonHeap()
z parametrami nazwy i flagi,
możesz utworzyć mapowanie
<ION heap mask, flag>
do równoważnej sterty DMA-BUF
nazwy
ustawiając parametr nazwy sterty ION na pusty.
Krok 4. Zastąp wywołania (ion_alloc_fd()
)
BufferAllocator::Alloc()
za pomocą odpowiedniej nazwy stosu.
Typ przydziału | Libion | libdmabufheap |
---|---|---|
Przydział z: my_heap z flagą
Usunięto: ION_FLAG_MY_FLAG
|
ion_alloc_fd(ionfd, size, 0, ION_HEAP_MY_HEAP, 0, &fd)
|
allocator->Alloc("my_heap", size)
|
Przydział z: my_heap z flagą
Ustawiono: ION_FLAG_MY_FLAG
|
ion_alloc_fd(ionfd, size, 0, ION_HEAP_MY_HEAP,
ION_FLAG_MY_FLAG, &fd)
|
allocator->Alloc("my_heap_special", size)
|
W tej chwili klient działa, ale nadal przydziela ze sterty ION ponieważ nie ma wymaganych uprawnień sepolicy do otwierania DMA-BUF sterta.
Krok 5. Utwórz uprawnienia sepolicy wymagane, aby klient miał dostęp nowe sterty DMA-BUF. Teraz klient może już Sterta DMA-BUF.
Krok 6. Sprawdź, czy przydziały są realizowane z nowej sterty DMA-BUF sprawdzając logcat.
Krok 7. Wyłącz stertę ION my_heap
w jądrze. Jeśli kod klienta
nie wymagają uaktualniania urządzeń (które jądra obsługują tylko ION);
sterty), możesz też usunąć wywołania MapNameToIonHeap()
.