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 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.
- Standarisasi: Framework heap DMA-BUF menawarkan UAPI yang ditentukan dengan baik. ION mengizinkan flag kustom dan ID heap yang mencegah pengembangan framework pengujian umum karena implementasi ION setiap perangkat dapat berperilaku secara berbeda.
Cabang android12-5.10
dari Android Common Kernel menonaktifkan
CONFIG_ION
pada 1 Maret 2021.
Latar belakang
Berikut adalah perbandingan singkat antara heap ION dan DMA-BUF.
Kesamaan 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/mask heap dan flag harus ditentukan untuk alokasi. | Nama heap digunakan untuk alokasi. |
Bagian berikut mencantumkan komponen yang menangani ION dan menjelaskan cara beralih ke framework heap DMA-BUF.
Mentransisikan driver kernel dari heap ION ke DMA-BUF
Driver kernel yang menerapkan heap ION
Heap ION dan DMA-BUF memungkinkan setiap heap menerapkan alokator dan DMA-BUF op-nya sendiri. Jadi, Anda dapat beralih dari implementasi heap ION ke implementasi heap DMA-BUF menggunakan kumpulan API yang berbeda untuk mendaftarkan heap. Tabel ini menunjukkan 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 API
dma_heap_add()
. Untuk memudahkan berbagi kode, sebaiknya daftarkan semua varian
heap yang sama dalam driver yang sama.
Contoh dma-buf: system_heap ini
menunjukkan penerapan varian heap sistem
yang di-cache dan tidak di-cache.
Gunakan dma-buf: heaps: example template ini untuk membuat heap DMA-BUF dari awal.
Driver kernel mengalokasikan langsung dari heap ION
Framework heap DMA-BUF juga menawarkan antarmuka alokasi untuk klien dalam kernel. Alih-alih menentukan mask dan flag heap untuk memilih jenis alokasi, antarmuka yang ditawarkan oleh heap DMA-BUF menggunakan nama heap sebagai input.
Berikut adalah API alokasi ION dalam kernel dan API alokasi heap DMA-BUF
yang setara. Driver kernel dapat menggunakan dma_heap_find()
API untuk membuat kueri
adanya 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 buffering yang dialokasikan dari heap ION berperilaku sama persis dengan buffering 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, library
abstraksi yang disebut
libdmabufheap
tersedia. libdmabufheap
mendukung alokasi di heap DMA-BUF
dan heap ION. Pertama-tama, fungsi ini memeriksa apakah heap DMA-BUF dengan nama yang ditentukan ada
dan jika tidak, kembali 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/mask kepala dan flag heap.
- Ganti
ion_alloc_fd()
API, yang menggunakan mask heap dan argumen flag, denganBufferAllocator::Alloc()
API, yang menggunakan nama heap sebagai gantinya.
Tabel berikut mengilustrasikan 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 disimpan dalam 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 menunggu persetujuan 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 heap atau mask dan flag) untuk memungkinkan antarmuka
tersebut 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.
Referensi penerapan Gralloc
Penerapan gralloc Hikey960 menggunakan libdmabufheap
, sehingga Anda dapat menggunakannya sebagai
penerapan
referensi.
Penambahan ueventd yang diperlukan
Untuk heap DMA-BUF khusus perangkat baru yang dibuat, tambahkan entri baru ke
file ueventd.rc
perangkat.
Contoh Penyiapan ueventd untuk mendukung heap
DMA-BUF ini
menunjukkan cara melakukannya untuk heap sistem DMA-BUF.
Penambahan sepolicy yang diperlukan
Menambahkan 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 agar dapat mengakses heap sistem DMA-BUF.
Mengakses heap vendor dari kode framework
Untuk memastikan kepatuhan Treble, kode framework hanya dapat dialokasikan dari kategori heap vendor yang telah disetujui sebelumnya.
Berdasarkan masukan yang diterima dari partner, Google mengidentifikasi dua kategori heap 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 dari sistem heap DMA-BUF default dapat diganti.
CONFIG_DMABUF_HEAPS_SYSTEM
dinonaktifkan digki_defconfig
agar menjadi modul vendor.- Pengujian kepatuhan VTS memastikan bahwa heap ada di
/dev/dma_heap/system
. Pengujian juga memverifikasi bahwa heap dapat dialokasikan dari, dan bahwa deskriptor file yang ditampilkan (fd
) dapat dipetakan memori (mmapped) dari ruang pengguna.
Poin sebelumnya juga berlaku untuk varian heap sistem yang tidak di-cache, meskipun keberadaannya tidak wajib untuk perangkat yang sepenuhnya koheren dengan IO.
Heap yang akan dialokasikan dari memori yang dilindungi
Implementasi heap aman harus khusus vendor karena Android Common Kernel 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 akan memastikan bahwa alokasi dapat dilakukan dari heap tersebut.
- Komponen framework diberikan akses ke heap ini sehingga dapat mengaktifkan penggunaan heap melalui HAL Codec2/HAL non-binderized, proses yang sama. Namun, fitur framework Android generik tidak dapat bergantung pada fitur tersebut karena variabilitas dalam detail penerapannya. Jika implementasi heap aman umum ditambahkan ke Android Common Kernel pada masa mendatang, implementasi tersebut harus menggunakan ABI yang berbeda untuk menghindari konflik dengan perangkat yang diupgrade.
Alokator Codec 2 untuk heap DMA-BUF
Alokator codec2 untuk antarmuka heap DMA-BUF tersedia di AOSP.
Antarmuka penyimpanan komponen yang memungkinkan parameter heap ditentukan dari C2 HAL tersedia dengan alokator heap DMA-BUF C2.
Contoh alur transisi untuk heap ION
Untuk memperlancar transisi dari heap ION ke DMA-BUF, libdmabufheap
memungkinkan
pengalihan satu heap pada satu waktu. Langkah-langkah berikut menunjukkan alur kerja yang disarankan
untuk mentransisikan heap ION non-lama bernama my_heap
yang mendukung satu
tanda, ION_FLAG_MY_FLAG
.
Langkah 1: Buat setara dengan heap ION dalam framework DMA-BUF. Dalam
contoh ini, karena heap ION my_heap
mendukung flag ION_FLAG_MY_FLAG
, kita
mendaftarkan dua heap DMA-BUF:
- Perilaku
my_heap
sama persis dengan perilaku heap ION dengan tandaION_FLAG_MY_FLAG
dinonaktifkan. - Perilaku
my_heap_special
sama persis dengan perilaku heap ION dengan flagION_FLAG_MY_FLAG
yang 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 diinginkan.
Langkah 3: Untuk klien yang mengalokasikan dari my_heap
, ubah makefile mereka
agar 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 menetapkan 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 ditetapkan
|
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 ditetapkan
|
ion_alloc_fd(ionfd, size, 0, ION_HEAP_MY_HEAP,
ION_FLAG_MY_FLAG, &fd)
|
allocator->Alloc("my_heap_special", size)
|
Pada tahap 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 dapat mengalokasikan dari heap DMA-BUF baru.
Langkah 6: Pastikan 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 perangkat upgrade (yang kernelnya mungkin hanya mendukung heap
ION), Anda juga dapat menghapus pemanggilan MapNameToIonHeap()
.