ION ABI-Änderungen

Geräte mit Kernel 4.14 und höher sind von einer umfassenden Refaktorisierung des ION-Kernelmoduls betroffen, das von vielen Hardware Abstraction Layer-Implementierungen (HAL) des Grafikspeicher-Allocators (gralloc) von Anbietern aufgerufen wird, um geteilte Speicher-Buffer zuzuweisen. Auf dieser Seite finden Sie eine Anleitung zur Migration von Legacy-Anbietercode zur neuen Version von ION und mögliche Probleme mit der Binärschnittstelle (Application Binary Interface, ABI) in Zukunft.

ION

ION ist Teil des Staging-Baums des Upstream-Kernels. Während der Staging-Phase kann die ABI zwischen Userspace und Kernel von ION zwischen den Hauptversionen des Kernels unterbrochen werden. ION-ABI-Unterbrechungen wirken sich nicht direkt auf normale Apps oder bereits auf den Markt gebrachte Geräte aus. Bei der Migration zu neuen Hauptkernelversionen können jedoch Änderungen auftreten, die sich auf den Anbietercode auswirken, der ION aufruft. Außerdem kann es zu zukünftigen ABI-Unterbrechungen kommen, da das Android-Systemteam mit Upstream zusammenarbeitet, um ION aus dem Staging-Tree zu entfernen.

Änderungen in android-4.14

Im Kernel 4.12 wurde der ION-Kernelcode stark überarbeitet. Dabei wurden Teile von ION bereinigt und entfernt, die sich mit anderen Kernel-Frameworks überschneiden. Daher sind viele ältere ION-ioctls nicht mehr relevant und wurden entfernt.

Entfernung von ION-Clients und ION-Handles

Vor Kernel 4.12 wurde beim Öffnen von /dev/ion ein ION-Client zugewiesen. Die ION_IOC_ALLOC-ioctl hat einen neuen Puffer zugewiesen und ihn als ION-Handle (eine opake Ganzzahl, die nur für den ION-Client, der sie zugewiesen hat, von Bedeutung ist) an den Userspace zurückgegeben. Um ION-Handles in den Userspace zuzuordnen oder für andere Prozesse freizugeben, wurden sie mithilfe der ION_IOC_SHARE-ioctl als dma-buf-Dateideskriptoren neu exportiert.

Im Kernel 4.12 gibt das ION_IOC_ALLOC-ioctl dma-buf-Dateien direkt aus. Der Zwischenstatus des ION-Handles wurde entfernt, ebenso wie alle ioctls, die ION-Handles verbrauchen oder erzeugen. Da dma-buf fds nicht an bestimmte ION-Clients gebunden sind, wird das ioctl ION_IOC_SHARE nicht mehr benötigt und die gesamte ION-Clientinfrastruktur wurde entfernt.

Hinzufügen von Cache-Kohärenz-ioctls

Vor Kernel 4.12 stellte ION ein ION_IOC_SYNC-ioctl bereit, um den Dateideskriptor mit dem Arbeitsspeicher zu synchronisieren. Diese ioctl war schlecht dokumentiert und nicht flexibel. Daher haben viele Anbieter benutzerdefinierte ioctls zur Cache-Wartung implementiert.

Kernel 4.12 hat ION_IOC_SYNC durch die in linux/dma-buf.h definierte DMA_BUF_IOCTL_SYNC ioctl ersetzt. Rufen Sie DMA_BUF_IOCTL_SYNC zu Beginn und am Ende jedes CPU-Zugriffs mit Flags auf, die angeben, ob es sich um Lese- und/oder Schreibvorgänge handelt. Obwohl DMA_BUF_IOCTL_SYNC ausführlicher als ION_IOC_SYNC ist, gibt es dem Nutzerbereich mehr Kontrolle über die zugrunde liegenden Cache-Wartungsvorgänge.

DMA_BUF_IOCTL_SYNC ist Teil der stabilen ABI des Kernels und kann mit allen dma-buf-Dateideskriptoren verwendet werden, unabhängig davon, ob sie von ION zugewiesen wurden oder nicht.

Anbietercode zu Android 4.12 oder höher migrieren

Für Userspace-Clients empfiehlt das Android-Systemteam dringend, libion zu verwenden, anstatt ioctl()-Aufrufe zu öffnen. Ab Android 9 erkennt libion das ION ABI zur Laufzeit automatisch und versucht, alle Unterschiede zwischen den Kerneln zu maskieren. Alle Libion-Funktionen, die ion_user_handle_t-Handle erstellt oder verbraucht haben, funktionieren jedoch nach Kernel 4.12 nicht mehr. Sie können diese Funktionen durch die folgenden äquivalenten Vorgänge auf dma-buf-Dateideskriptoren ersetzen, die mit allen aktuellen Kernelversionen funktionieren.

Alter ion_user_handle_t-Aufruf Äquivalenter dma-buf-fd-Aufruf
ion_alloc(ion_fd, …, &buf_handle) ion_alloc_fd(ion_fd, ..., &buf_fd)
ion_share(ion_fd, buf_handle, &buf_fd) – (dieser Aufruf ist bei dma-buf-Datenendpunkten nicht erforderlich)
ion_map(ion_fd, buf_handle, ...) mmap(buf_fd, ...)
ion_free(ion_fd, buf_handle) close(buf_fd)
ion_import(ion_fd, buf_fd, &buf_handle) – (dieser Aufruf ist bei dma-buf-Datenendpunkten nicht erforderlich)
ion_sync_fd(ion_fd, buf_fd)
If (ion_is_legacy(ion_fd))
    ion_sync_fd(ion_fd, buf_fd);
else
    ioctl(buf_fd, DMA_BUF_IOCTL_SYNC, ...);

Da ION keine Kernel-APIs mehr exportiert, müssen Treiber, die zuvor die In-Kernel-ION-Kernel-API mit ion_import_dma_buf_fd() verwendet haben, für die In-Kernel-DMA-Buf-API mit dma_buf_get() konvertiert werden.

Künftige ION ABI-Pausen

Bevor ION aus dem Staging-Tree verschoben werden kann, müssen zukünftige Kernel-Releases möglicherweise die ION-ABI wieder aufheben. Das Android-Systemteam erwartet nicht, dass sich diese Änderungen auf Geräte auswirken, die mit der nächsten Android-Version auf den Markt kommen. Sie können sich jedoch auf Geräte auswirken, die mit nachfolgenden Android-Versionen auf den Markt kommen.

Die Upstream-Community hat beispielsweise vorgeschlagen, den einzelnen Knoten /dev/ion in mehrere Knoten pro Heap (z. B. /dev/ion/heap0) aufzuteilen, damit Geräte unterschiedliche SELinux-Richtlinien auf jeden Heap anwenden können. Wenn diese Änderung in einer zukünftigen Kernelversion implementiert wird, würde das ION ABI aufgelöst.