Di Android 12, GKI 2.0 menggantikan alokator ION dengan heap DMA-BUF karena alasan berikut:
- Keamanan: Karena setiap heap DMA-BUF adalah perangkat karakter terpisah, akses
ke setiap heap dapat dikontrol secara terpisah dengan sepolicy. Hal ini tidak
mungkin dilakukan dengan ION karena alokasi dari heap mana pun hanya memerlukan akses ke
perangkat
/dev/ion
. - Stabilitas ABI: Tidak seperti ION, antarmuka IOCTL framework heap DMA-BUF stabil ABI karena dipertahankan di kernel Linux upstream.
- Standardisasi: Framework heap DMA-BUF menawarkan UAPI yang terdefinisi dengan baik. ION mengizinkan tanda kustom dan ID heap yang mencegah pengembangan framework pengujian umum karena setiap implementasi ION perangkat dapat berperilaku berbeda.
Cabang android12-5.10
dari Android Common Kernel dinonaktifkan
CONFIG_ION
pada 1 Maret 2021.
Latar belakang
Berikut adalah perbandingan singkat antara heap ION dan DMA-BUF.
Persamaan antara framework heap ION dan DMA-BUF
- Framework heap ION dan DMA-BUF adalah eksportir DMA-BUF berbasis heap.
- Keduanya memungkinkan setiap heap menentukan alokator dan operasi DMA-BUF-nya sendiri.
- Performa alokasi serupa karena kedua skema memerlukan satu IOCTL untuk alokasi.
Perbedaan antara framework heap ION dan DMA-BUF
Heap ION | Heap DMA-BUF |
---|---|
Semua alokasi ION dilakukan dengan /dev/ion .
|
Setiap heap DMA-BUF adalah perangkat karakter yang ada di /dev/dma_heap/<heap_name> .
|
ION mendukung flag pribadi heap. | Heap DMA-BUF tidak mendukung flag pribadi heap. Setiap jenis alokasi yang berbeda dilakukan dari heap yang berbeda. Misalnya, varian heap sistem yang di-cache dan
tidak di-cache adalah heap terpisah yang terletak di
/dev/dma_heap/system dan
/dev/dma_heap/system_uncached .
|
ID/masker dan flag heap harus ditentukan untuk alokasi. | Nama heap digunakan untuk alokasi. |
Bagian berikut mencantumkan komponen yang menangani ION dan menjelaskan cara mengalihkannya ke framework heap DMA-BUF.
Mengubah driver kernel dari ION ke heap DMA-BUF
Driver kernel yang menerapkan heap ION
Heap ION dan DMA-BUF memungkinkan setiap heap menerapkan alokator dan operasi DMA-BUF-nya sendiri. Jadi, Anda dapat beralih dari penerapan heap ION ke penerapan heap DMA-BUF dengan menggunakan serangkaian API yang berbeda untuk mendaftarkan heap. Tabel ini menampilkan API pendaftaran heap ION dan API heap DMA-BUF yang setara.
Heap ION | Heap 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);
|
Heap DMA-BUF tidak mendukung flag pribadi heap. Jadi, setiap varian heap
harus didaftarkan satu per satu menggunakan dma_heap_add()
API. Untuk memfasilitasi berbagi kode, sebaiknya daftarkan semua varian
tumpukan yang sama dalam driver yang sama.
Contoh dma-buf: system_heap ini
menunjukkan penerapan varian yang di-cache dan tidak di-cache dari heap
sistem.
Gunakan dma-buf: heaps: example template ini untuk membuat heap DMA-BUF dari awal.
Driver kernel yang mengalokasikan langsung dari heap ION
Framework heap DMA-BUF juga menawarkan antarmuka alokasi untuk klien dalam kernel. Daripada menentukan masker dan flag heap untuk memilih jenis alokasi, antarmuka yang ditawarkan oleh heap DMA-BUF menggunakan nama heap sebagai input.
Berikut ini menunjukkan API alokasi ION dalam kernel dan API alokasi heap DMA-BUF yang setara. Driver kernel dapat menggunakan dma_heap_find()
API untuk membuat kueri keberadaan heap. API menampilkan pointer ke instance
struct dma_heap, yang kemudian dapat diteruskan sebagai argumen ke
dma_heap_buffer_alloc()
API.
Heap ION | Heap DMA-BUF |
---|---|
struct dma_buf *ion_alloc(size_t len, unsigned int heap_id_mask, unsigned int flags)
|
|
Driver kernel yang menggunakan DMA-BUF
Tidak ada perubahan yang diperlukan untuk driver yang hanya mengimpor DMA-BUF, karena buffer yang dialokasikan dari heap ION berperilaku persis sama dengan buffer yang dialokasikan dari heap DMA-BUF yang setara.
Mentransisikan klien ruang pengguna ION ke heap DMA-BUF
Untuk mempermudah transisi bagi klien ruang pengguna ION, tersedia library abstraksi yang disebut
libdmabufheap
. libdmabufheap
mendukung alokasi di heap DMA-BUF
dan heap ION. Pertama-tama, fungsi ini akan memeriksa apakah ada heap DMA-BUF dengan nama yang ditentukan
dan jika tidak ada, akan melakukan penggantian ke heap ION yang setara, jika ada.
Klien harus melakukan inisialisasi objek BufferAllocator
selama inisialisasi, bukan membuka /dev/ion using
ion_open()
. Hal ini karena deskriptor file yang dibuat dengan membuka
/dev/ion
dan /dev/dma_heap/<heap_name>
dikelola
secara internal oleh objek BufferAllocator
.
Untuk beralih dari libion
ke libdmabufheap
, ubah perilaku klien sebagai
berikut:
- Lacak nama heap yang akan digunakan untuk alokasi, bukan ID/masker head dan flag heap.
- Ganti API
ion_alloc_fd()
, yang menggunakan argumen mask heap dan flag, dengan APIBufferAllocator::Alloc()
, yang menggunakan nama heap.
Tabel ini menggambarkan perubahan ini dengan menunjukkan cara libion
dan libdmabufheap
melakukan alokasi heap sistem yang tidak di-cache.
Jenis alokasi | libion | libdmabufheap |
---|---|---|
Alokasi yang di-cache dari heap sistem | ion_alloc_fd(ionfd, size, 0, ION_HEAP_SYSTEM, ION_FLAG_CACHED, &fd)
|
allocator->Alloc("system", size)
|
Alokasi yang tidak di-cache dari heap sistem | ion_alloc_fd(ionfd, size, 0, ION_HEAP_SYSTEM, 0, &fd)
|
allocator->Alloc("system-uncached", size)
|
Varian heap sistem yang tidak di-cache
sedang menunggu persetujuan di upstream, tetapi sudah menjadi bagian dari cabang android12-5.10
.
Untuk mendukung upgrade perangkat, MapNameToIonHeap()
API memungkinkan pemetaan nama heap ke parameter heap ION (nama atau mask heap dan flag) agar antarmuka tersebut dapat menggunakan alokasi berbasis nama. Berikut adalah contoh alokasi berbasis nama.
Dokumentasi untuk setiap API yang diekspos oleh
libdmabufheap
tersedia. Library
juga mengekspos file header untuk digunakan oleh klien C.
Implementasi Gralloc referensi
Implementasi gralloc Hikey960 menggunakan libdmabufheap
, sehingga Anda dapat menggunakannya sebagai implementasi
referensi.
Penambahan ueventd yang diperlukan
Untuk setiap heap DMA-BUF khusus perangkat baru yang dibuat, tambahkan entri baru ke file ueventd.rc
perangkat.
Contoh Menyiapkan ueventd untuk mendukung heap DMA-BUF ini menunjukkan cara melakukannya untuk heap sistem DMA-BUF.
Penambahan sepolicy yang diperlukan
Tambahkan izin sepolicy untuk memungkinkan klien ruang pengguna mengakses heap DMA-BUF baru. Contoh menambahkan izin yang diperlukan ini menunjukkan izin sepolicy yang dibuat untuk berbagai klien guna mengakses heap sistem DMA-BUF.
Mengakses heap vendor dari kode framework
Untuk memastikan kepatuhan Treble, kode framework hanya dapat mengalokasikan dari kategori heap vendor yang telah disetujui sebelumnya.
Berdasarkan masukan yang diterima dari partner, Google mengidentifikasi dua kategori tumpukan vendor yang harus diakses dari kode framework:
- Heap yang didasarkan pada heap sistem dengan pengoptimalan performa khusus perangkat atau SoC.
- Heap untuk dialokasikan dari memori yang dilindungi.
Heap berdasarkan heap sistem dengan pengoptimalan performa khusus perangkat atau SoC
Untuk mendukung kasus penggunaan ini, implementasi heap sistem DMA-BUF heap default dapat diganti.
CONFIG_DMABUF_HEAPS_SYSTEM
dinonaktifkan digki_defconfig
agar dapat menjadi modul vendor.- Pengujian kepatuhan VTS memastikan bahwa heap ada di
/dev/dma_heap/system
. Pengujian juga memverifikasi bahwa heap dapat dialokasikan dari, dan deskriptor file (fd
) yang ditampilkan dapat dipetakan ke memori (mmapped) dari ruang pengguna.
Poin-poin sebelumnya juga berlaku untuk varian heap sistem yang tidak di-cache, meskipun keberadaannya tidak wajib untuk perangkat yang sepenuhnya koheren dengan IO.
Heap untuk dialokasikan dari memori yang dilindungi
Implementasi heap aman harus khusus vendor karena Kernel Umum Android tidak mendukung implementasi heap aman generik.
- Daftarkan implementasi khusus vendor Anda sebagai
/dev/dma_heap/system-secure<vendor-suffix>
. - Implementasi heap ini bersifat opsional.
- Jika heap ada, pengujian VTS memastikan bahwa alokasi dapat dilakukan dari heap tersebut.
- Komponen framework disediakan dengan akses ke heap ini sehingga dapat mengaktifkan penggunaan heap melalui HAL/non-binderized Codec2, HAL dalam proses yang sama. Namun, fitur framework Android generik tidak dapat bergantung padanya karena variabilitas dalam detail implementasinya. Jika implementasi heap aman generik ditambahkan ke Android Common Kernel pada masa mendatang, implementasi tersebut harus menggunakan ABI yang berbeda untuk menghindari konflik dengan perangkat yang diupgrade.
Pengalokasi Codec 2 untuk heap DMA-BUF
Pengalokasi codec2 untuk antarmuka heap DMA-BUF tersedia di AOSP.
Antarmuka penyimpanan komponen yang memungkinkan parameter heap ditentukan dari HAL C2 tersedia dengan pengalokasi heap DMA-BUF C2.
Contoh alur transisi untuk heap ION
Untuk mempermudah transisi dari heap ION ke DMA-BUF, libdmabufheap
memungkinkan
pengalihan satu heap dalam satu waktu. Langkah-langkah berikut menunjukkan alur kerja yang disarankan
untuk mentransisikan heap ION non-warisan bernama my_heap
yang mendukung satu
flag, ION_FLAG_MY_FLAG
.
Langkah 1: Buat heap ION yang setara dalam framework DMA-BUF. Dalam contoh ini, karena heap ION my_heap
mendukung tanda ION_FLAG_MY_FLAG
, kita mendaftarkan dua heap DMA-BUF:
- Perilaku
my_heap
sama persis dengan perilaku heap ION dengan flagION_FLAG_MY_FLAG
dinonaktifkan. - Perilaku
my_heap_special
sama persis dengan perilaku heap ION dengan flagION_FLAG_MY_FLAG
diaktifkan.
Langkah 2: Buat perubahan ueventd untuk heap DMA-BUF my_heap
dan
my_heap_special
baru. Pada tahap ini, heap terlihat sebagai
/dev/dma_heap/my_heap
dan /dev/dma_heap/my_heap_special
, dengan
izin yang dimaksudkan.
Langkah 3: Untuk klien yang mengalokasikan dari my_heap
, ubah makefile mereka
untuk ditautkan ke libdmabufheap
. Selama inisialisasi klien, buat instance objek BufferAllocator
dan gunakan MapNameToIonHeap()
API untuk memetakan kombinasi <ION heap name/mask, flag>
ke nama heap DMA-BUF yang setara.
Contoh:
allocator->MapNameToIonHeap("my_heap_special" /* name of DMA-BUF heap */, "my_heap" /* name of the ION heap */, ION_FLAG_MY_FLAG /* ion flags */ )
Daripada menggunakan MapNameToIonHeap()
API dengan parameter nama dan flag, Anda dapat membuat pemetaan dari <ION heap mask, flag>
ke nama heap DMA-BUF yang setara dengan menyetel parameter nama heap ION ke kosong.
Langkah 4: Ganti pemanggilan ion_alloc_fd()
dengan
BufferAllocator::Alloc()
menggunakan nama heap yang sesuai.
Jenis alokasi | libion | libdmabufheap |
---|---|---|
Alokasi dari my_heap dengan flag
ION_FLAG_MY_FLAG tidak disetel
|
ion_alloc_fd(ionfd, size, 0, ION_HEAP_MY_HEAP, 0, &fd)
|
allocator->Alloc("my_heap", size)
|
Alokasi dari my_heap dengan flag
ION_FLAG_MY_FLAG yang ditetapkan
|
ion_alloc_fd(ionfd, size, 0, ION_HEAP_MY_HEAP,
ION_FLAG_MY_FLAG, &fd)
|
allocator->Alloc("my_heap_special", size)
|
Pada titik ini, klien berfungsi tetapi masih mengalokasikan dari heap ION karena tidak memiliki izin sepolicy yang diperlukan untuk membuka heap DMA-BUF.
Langkah 5: Buat izin sepolicy yang diperlukan agar klien dapat mengakses heap DMA-BUF baru. Klien kini sepenuhnya siap untuk mengalokasikan dari heap DMA-BUF baru.
Langkah 6: Verifikasi bahwa alokasi terjadi dari heap DMA-BUF baru dengan memeriksa logcat.
Langkah 7: Nonaktifkan heap ION my_heap
di kernel. Jika kode klien
tidak perlu mendukung upgrade perangkat (yang kernelnya mungkin hanya mendukung heap ION), Anda juga dapat menghapus pemanggilan MapNameToIonHeap()
.