Android 12'de GKI 2.0, aşağıdaki nedenlerle ION ayırıcının yerini DMA-BUF yığınlarıyla değiştirir:
- Güvenlik: Her DMA-BUF yığını ayrı bir karakter cihazı olduğundan her yığına erişim, sepolicy ile ayrı ayrı kontrol edilebilir. ION'da bu mümkün değildi çünkü herhangi bir yığın tahsisi için yalnızca
/dev/ion
cihaza erişim gerekiyordu. - ABI kararlılığı: ION'un aksine, DMA-BUF yığınları çerçevesinin IOCTL arayüzü, yukarı akış Linux çekirdeğinde tutulduğu için ABI kararlıdır.
- Standartlaştırma: DMA-BUF yığınları çerçevesi, iyi tanımlanmış bir UAPI sunar. ION, her cihazın ION uygulaması farklı şekilde davranabileceğinden ortak bir test çerçevesinin geliştirilmesini engelleyen özel işaretlere ve yığın kimliklerine izin veriyordu.
Android Common Kernel'in android12-5.10
dalı, CONFIG_ION
tarihinde 1 Mart 2021'de devre dışı bırakıldı.
Arka plan
Aşağıda, ION ve DMA-BUF yığınları arasındaki kısa bir karşılaştırma verilmiştir.
ION ve DMA-BUF yığın çerçevesi arasındaki benzerlikler
- ION ve DMA-BUF yığın çerçeveleri, yığın tabanlı DMA-BUF dışa aktarıcılarıdır.
- Her ikisi de her yığının kendi ayırıcısını ve DMA-BUF işlemlerini tanımlamasına olanak tanır.
- Her iki şema da ayırma için tek bir IOCTL gerektirdiğinden ayırma performansı benzerdir.
ION ve DMA-BUF yığınları çerçevesi arasındaki farklar
ION yığınları | DMA-BUF yığınları |
---|---|
Tüm ION ayırmaları /dev/ion ile yapılır.
|
Her DMA-BUF yığını, /dev/dma_heap/<heap_name> konumunda bulunan bir karakter cihazıdır.
|
ION, yığın özel işaretlerini destekler. | DMA-BUF yığınları, yığın özel işaretlerini desteklemez. Her farklı türdeki
tahsis bunun yerine farklı bir yığın üzerinden yapılır. Örneğin, önbelleğe alınmış ve alınmamış sistem yığını varyantları, /dev/dma_heap/system ve /dev/dma_heap/system_uncached konumlarında bulunan ayrı yığınlardır.
|
Ayırma için yığın kimliği/maskesi ve işaretleri belirtilmelidir. | Yığın adı, tahsis için kullanılır. |
Aşağıdaki bölümlerde ION ile ilgili bileşenler listelenmekte ve bunların DMA-BUF yığınları çerçevesine nasıl geçirileceği açıklanmaktadır.
Çekirdek sürücülerini ION'dan DMA-BUF yığınlarına geçirme
ION yığınlarını uygulayan çekirdek sürücüleri
Hem ION hem de DMA-BUF yığınları, her yığının kendi ayırıcılarını ve DMA-BUF işlemlerini uygulamasına olanak tanır. Bu nedenle, yığını kaydetmek için farklı bir API grubu kullanarak ION yığın uygulamasından DMA-BUF yığın uygulamasına geçebilirsiniz. Bu tabloda, ION yığın kaydı API'leri ve bunların eşdeğer DMA-BUF yığın API'leri gösterilmektedir.
ION yığınları | DMA-BUF yığınları |
---|---|
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);
|
DMA-BUF yığınları, yığın özel işaretlerini desteklemez. Bu nedenle, yığınların her varyantı dma_heap_add()
API'si kullanılarak ayrı ayrı kaydedilmelidir. Kod paylaşımını kolaylaştırmak için aynı yığının tüm varyantlarını aynı sürücüye kaydetmeniz önerilir.
Bu dma-buf: system_heap örneğinde, sistem yığınının önbelleğe alınmış ve alınmamış varyantlarının uygulanması gösterilmektedir.
Sıfırdan DMA-BUF yığını oluşturmak için bu dma-buf: heaps: example template şablonunu kullanın.
Doğrudan ION yığınlarından yer ayıran çekirdek sürücüleri
DMA-BUF yığınları çerçevesi, çekirdek içi istemciler için bir ayırma arayüzü de sunar. Yığın maskesini ve ayrılma türünü seçmek için kullanılan işaretleri belirtmek yerine, DMA-BUF yığınları tarafından sunulan arayüz, yığın adını giriş olarak alır.
Aşağıda, çekirdek içi ION tahsis API'si ve eşdeğer DMA-BUF yığın tahsis API'leri gösterilmektedir. Çekirdek sürücüleri, yığın olup olmadığını sorgulamak için dma_heap_find()
API'sini kullanabilir. API, struct dma_heap örneğine bir işaretçi döndürür. Bu işaretçi daha sonra dma_heap_buffer_alloc()
API'sine bağımsız değişken olarak iletilebilir.
ION yığınları | DMA-BUF yığınları |
---|---|
struct dma_buf *ion_alloc(size_t len, unsigned int heap_id_mask, unsigned int flags)
|
|
DMA-BUF'ları kullanan çekirdek sürücüleri
Yalnızca DMA-BUF'ları içe aktaran sürücülerde değişiklik yapılması gerekmez. Bunun nedeni, bir ION yığınından ayrılan arabelleğin, eşdeğer bir DMA-BUF yığınından ayrılan arabellekle aynı şekilde davranmasıdır.
ION'un kullanıcı alanı istemcilerini DMA-BUF yığınlarına geçirme
ION'un kullanıcı alanı istemcileri için geçişi kolaylaştırmak amacıyla libdmabufheap
adlı bir soyutlama kitaplığı mevcuttur. libdmabufheap
, DMA-BUF yığınlarında ve ION yığınlarında tahsisi destekler. Öncelikle belirtilen ada sahip bir DMA-BUF yığını olup olmadığını kontrol eder. Yoksa varsa eşdeğer bir ION yığınına geri döner.
Müşteriler, /dev/ion using
ion_open()
açmak yerine başlatma sırasında bir BufferAllocator
nesnesi başlatmalıdır. Bunun nedeni, /dev/ion
ve /dev/dma_heap/<heap_name>
açılarak oluşturulan dosya tanımlayıcılarının BufferAllocator
nesnesi tarafından dahili olarak yönetilmesidir.
libion
'dan libdmabufheap
'ye geçmek için istemcilerin davranışını aşağıdaki gibi değiştirin:
- Başlık kimliği/maskesi ve yığın işareti yerine, ayırma için kullanılacak yığın adını takip edin.
- Yığın maskesi ve işaret bağımsız değişkeni alan
ion_alloc_fd()
API'sini, bunun yerine yığın adı alanBufferAllocator::Alloc()
API'siyle değiştirin.
Bu tabloda, libion
ve libdmabufheap
ile önbelleğe alınmamış sistem yığını ayırmanın nasıl yapıldığı gösterilerek bu değişiklikler açıklanmaktadır.
Ayırma türü | libion | libdmabufheap |
---|---|---|
Sistem bellek yığınından önbelleğe alınmış ayırma | ion_alloc_fd(ionfd, size, 0, ION_HEAP_SYSTEM, ION_FLAG_CACHED, &fd)
|
allocator->Alloc("system", size)
|
Sistem yığınından önbelleğe alınmamış ayırma | ion_alloc_fd(ionfd, size, 0, ION_HEAP_SYSTEM, 0, &fd)
|
allocator->Alloc("system-uncached", size)
|
The
uncached system heap variant
is awaiting approval upstream but is already part of the android12-5.10
branch.
Cihazların yükseltilmesini desteklemek için MapNameToIonHeap()
API, yığın adının ION yığın parametreleriyle (yığın adı veya maskesi ve işaretler) eşlenmesine olanak tanır. Böylece, bu arayüzler ada dayalı ayırmaları kullanabilir. Ada dayalı ayırma örneğini aşağıda görebilirsiniz.
libdmabufheap
tarafından kullanıma sunulan her API'nin
dokümanları mevcuttur. Kitaplık, C istemcileri tarafından kullanılmak üzere bir üstbilgi dosyası da sunar.
Referans Gralloc uygulaması
Hikey960 gralloc uygulaması libdmabufheap
kullandığından bunu referans uygulaması olarak kullanabilirsiniz.
Gerekli ueventd eklemeleri
Yeni oluşturulan cihaza özgü DMA-BUF yığınları için cihazın ueventd.rc
dosyasına yeni bir giriş ekleyin.
Bu Setup ueventd to support DMA-BUF heaps
example
(DMA-BUF yığınlarını desteklemek için ueventd'yi ayarlama örneği), bunun DMA-BUF sistem yığını için nasıl yapıldığını gösterir.
Gerekli sepolicy eklemeleri
Bir kullanıcı alanı istemcisinin yeni bir DMA-BUF yığınına erişmesini sağlamak için sepolicy izinleri ekleyin. Bu gerekli izinleri ekleme örneğinde, DMA-BUF sistem yığınına erişmek için çeşitli istemcilerde oluşturulan sepolicy izinleri gösterilmektedir.
Çerçeve kodundan tedarikçi yığınlarına erişme
Treble uyumluluğunu sağlamak için çerçeve kodu yalnızca önceden onaylanmış tedarikçi yığınları kategorilerinden yer ayırabilir.
Google, iş ortaklarından alınan geri bildirimlere dayanarak çerçeve kodundan erişilmesi gereken iki satıcı grubu kategorisi belirledi:
- Cihaza veya çip üzerinde sisteme özel performans optimizasyonlarıyla sistem yığınına dayalı yığınlar.
- Korunan bellekten ayrılacak yığınlar.
Cihaza veya çip üzerinde sisteme özel performans optimizasyonlarıyla sistem yığınına dayalı yığınlar
Bu kullanım alanını desteklemek için varsayılan DMA-BUF yığını sisteminin yığın uygulaması geçersiz kılınabilir.
CONFIG_DMABUF_HEAPS_SYSTEM
, tedarikçi modülü olarak kullanılabilmesi içingki_defconfig
içinde devre dışı bırakılır.- VTS uygunluk testleri, yığının
/dev/dma_heap/system
konumunda bulunduğunu doğrular. Testler ayrıca yığının ayrılıp ayrılamadığını ve döndürülen dosya tanımlayıcısının (fd
) kullanıcı alanından bellek eşlemeli (mmapped) olup olmadığını da doğrular.
Önceki noktalar, sistem yığınının önbelleğe alınmamış varyantı için de geçerlidir. Ancak bu varyantın varlığı, tamamen G/Ç tutarlı cihazlar için zorunlu değildir.
Korunan bellekten ayrılacak yığınlar
Android Common Kernel, genel bir güvenli yığın uygulamasını desteklemediğinden güvenli yığın uygulamaları tedarikçiye özel olmalıdır.
- Tedarikçiye özel uygulamalarınızı
/dev/dma_heap/system-secure<vendor-suffix>
olarak kaydedin. - Bu yığın uygulamaları isteğe bağlıdır.
- Yığınlar varsa VTS testleri, bu yığınlardan tahsisat yapılabilmesini sağlar.
- Çerçeve bileşenleri, Codec2 HAL/non-binderized, aynı süreçteki HAL'ler aracılığıyla yığın kullanımını etkinleştirebilmeleri için bu yığınlara erişimle birlikte sağlanır. Ancak genel Android çerçevesi özellikleri, uygulama ayrıntılarındaki değişkenlik nedeniyle bunlara bağlı olamaz. Gelecekte Android Common Kernel'e genel bir güvenli yığın uygulaması eklenirse yükseltme yapan cihazlarla çakışmayı önlemek için farklı bir ABI kullanması gerekir.
DMA-BUF yığınları için Codec 2 ayırıcı
AOSP'de DMA-BUF yığınları için bir codec2 ayırıcı arayüzü mevcuttur.
C2 HAL'den yığın parametrelerinin belirtilmesine olanak tanıyan bileşen deposu arayüzü, C2 DMA-BUF yığın ayırıcı ile kullanılabilir.
ION yığını için örnek geçiş akışı
ION'dan DMA-BUF yığınlarına geçişi kolaylaştırmak için libdmabufheap
, tek seferde bir yığın değiştirmenize olanak tanır. Aşağıdaki adımlarda, my_heap
adlı ve bir işareti destekleyen eski olmayan bir ION yığınını ION_FLAG_MY_FLAG
geçirme için önerilen iş akışı gösterilmektedir.
1. adım: DMA-BUF çerçevesinde ION yığınının eşdeğerlerini oluşturun. Bu örnekte, ION yığını my_heap
bir işareti ION_FLAG_MY_FLAG
desteklediği için iki DMA-BUF yığını kaydediyoruz:
my_heap
davranışı,ION_FLAG_MY_FLAG
işareti devre dışı bırakılmış ION yığınının davranışıyla tam olarak eşleşir.my_heap_special
davranışı,ION_FLAG_MY_FLAG
işaretinin etkin olduğu ION yığını davranışıyla tam olarak eşleşir.
2. adım: Yeni my_heap
ve my_heap_special
DMA-BUF yığınları için ueventd değişikliklerini oluşturun. Bu noktada, yığınlar /dev/dma_heap/my_heap
ve /dev/dma_heap/my_heap_special
olarak görünür ve amaçlanan izinlere sahiptir.
3. adım: my_heap
'den kaynak ayıran istemciler için makefile'larını libdmabufheap
'e bağlanacak şekilde değiştirin. İstemci başlatma sırasında bir BufferAllocator
nesnesi oluşturun ve <ION heap name/mask, flag>
kombinasyonunu eşdeğer DMA-BUF yığın adlarıyla eşlemek için MapNameToIonHeap()
API'sini kullanın.
Örneğin:
allocator->MapNameToIonHeap("my_heap_special" /* name of DMA-BUF heap */, "my_heap" /* name of the ION heap */, ION_FLAG_MY_FLAG /* ion flags */ )
Ad ve işaret parametreleriyle MapNameToIonHeap()
API'sini kullanmak yerine, ION yığın adı parametresini boş olarak ayarlayarak <ION heap mask, flag>
ile eşdeğer DMA-BUF yığın adları arasında eşleme oluşturabilirsiniz.
4. adım: Uygun yığın adını kullanarak ion_alloc_fd()
çağrılarını BufferAllocator::Alloc()
ile değiştirin.
Ayırma türü | libion | libdmabufheap |
---|---|---|
my_heap uygulamasından, ION_FLAG_MY_FLAG işareti kaldırılmış tahsis
|
ion_alloc_fd(ionfd, size, 0, ION_HEAP_MY_HEAP, 0, &fd)
|
allocator->Alloc("my_heap", size)
|
my_heap cihazından ION_FLAG_MY_FLAG işaretiyle yapılan tahsis
|
ion_alloc_fd(ionfd, size, 0, ION_HEAP_MY_HEAP,
ION_FLAG_MY_FLAG, &fd)
|
allocator->Alloc("my_heap_special", size)
|
Bu noktada, istemci işlevseldir ancak DMA-BUF yığınını açmak için gerekli sepolicy izinlerine sahip olmadığından ION yığınından bellek ayırmaya devam eder.
5. adım: İstemcinin yeni DMA-BUF yığınlarına erişmesi için gereken sepolicy izinlerini oluşturun. İstemci artık yeni DMA-BUF yığınından ayırma yapmaya tamamen hazır.
6. adım: logcat'i inceleyerek yeni DMA-BUF yığınından tahsislerin yapıldığını doğrulayın.
7. adım: Çekirdekte ION yığınını my_heap
devre dışı bırakın. İstemci kodu, cihazların yükseltilmesini desteklemesi gerekmiyorsa (çekirdekleri yalnızca ION yığınlarını destekliyor olabilir) MapNameToIonHeap()
çağrılarını da kaldırabilirsiniz.