Android 12'de GKI 2.0, ION ayırıcıyı aşağıdaki nedenlerle 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. Yığınlardan ayırma için yalnızca
/dev/ion
cihazına erişim gerektiğinden bu işlem ION ile mümkün değildi. - ABI kararlılığı: ION'un aksine, DMA-BUF yığınları çerçevesinin IOCTL arayüzü, yayın öncesi Linux çekirdeğinde korunduğ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ı davranabileceğinden ortak bir test çerçevesi geliştirilmesini engelleyen özel işaretlere ve yığın kimliklerine izin veriyordu.
Android Ortak Çekirdeği'nin android12-5.10
şubesi 1 Mart 2021'de devre dışı bırakıldıCONFIG_ION
.
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ığınları çerçevesi arasındaki benzerlikler
- ION ve DMA-BUF yığın çerçevelerinin ikisi de 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ını sağlar.
- Her iki şema da ayırma için tek bir IOCTL'ye ihtiyaç duyduğundan ayırma performansı benzerdir.
ION ve DMA-BUF yığın ç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> adresinde 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ı ayırma türü, farklı bir yığından yapılır. Örneğin, önbelleğe alınmış ve önbelleğe alınmamış sistem yığını varyantları, /dev/dma_heap/system ve /dev/dma_heap/system_uncached adreslerinde bulunan ayrı yığınlardır.
|
Ayırma için yığın kimliği/maskesi ve işaretlerin belirtilmesi gerekir. | Yığın adı, tahsis için kullanılır. |
Aşağıdaki bölümlerde, ION ile ilgili bileşenler listelenmiş 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. Böylece, 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 kayıt 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ığını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ın aynı sürücüye kaydedilmesi önerilir.
Bu dma-buf: system_heap örneği, sistem yığınının önbelleğe alınmış ve önbelleğe alınmamış varyantlarının uygulanmasını gösterir.
DMA-BUF yığınını sıfırdan oluşturmak için bu dma-buf: heaps: example şablonunu kullanın.
Doğrudan ION yığınlarından ayırma yapan çekirdek sürücüleri
DMA-BUF yığın çerçevesi, çekirdek içi istemciler için bir ayırma arayüzü de sunar. DMA-BUF yığınları tarafından sunulan arayüz, ayırma türünü seçmek için yığın maskesini ve işaretlerini belirtmek yerine giriş olarak bir yığın adı alır.
Aşağıda, çekirdek içi ION tahsis API'si ve eşdeğeri DMA-BUF yığın tahsis API'leri gösterilmektedir. Çekirdek sürücüleri, bir yığının varlığını sorgulamak için dma_heap_find()
API'yi kullanabilir. API, struct dma_heap örneğinin işaretçisini döndürür. Bu işaretçi daha sonra dma_heap_buffer_alloc()
API'ye 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 kullanan çekirdek sürücüleri
ION yığınından ayrılan bir arabellek, eşdeğer bir DMA-BUF yığınından ayrılan bir arabellekle tam olarak aynı şekilde davrandığından yalnızca DMA-BUF'ları içe aktaran sürücülerde değişiklik yapılması gerekmez.
ION'ın kullanıcı alanı istemcilerini DMA-BUF yığınlarına geçirin
ION'ın 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. İlk olarak, belirtilen ada sahip bir DMA-BUF yığınının olup olmadığını kontrol eder ve yoksa eşdeğer bir ION yığınına (varsa) geçer.
İstemciler, başlatma sırasında /dev/ion using
ion_open()
öğesini açmak yerine bir BufferAllocator
nesnesini başlatmalıdır. Bunun nedeni, /dev/ion
ve /dev/dma_heap/<heap_name>
'ün açılmasıyla oluşturulan dosya tanımlayıcılarının BufferAllocator
nesnesi tarafından dahili olarak yönetilmesidir.
libion
'ten libdmabufheap
'e 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şkenini alan
ion_alloc_fd()
API'yi, bunun yerine yığın adı alanBufferAllocator::Alloc()
API'siyle değiştirin.
Bu tabloda, libion
ve libdmabufheap
'ün önbelleğe alınmamış bir sistem yığını ayırma işlemini nasıl gerçekleştirdiğini göstererek bu değişiklikler açıklanmaktadır.
Tahsis türü | libion | libdmabufheap |
---|---|---|
Sistem yığınından önbelleğe alınan 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)
|
Önbelleğe alınmamış sistem yığını varyantı yukarı akış için onay bekliyor ancak zaten android12-5.10
şubesinin bir parçası.
Cihazların yükseltilmesini desteklemek amacıyla MapNameToIonHeap()
API, bir yığın adının ION yığın parametreleriyle (yığın adı veya maske ve işaretler) eşlenmesine izin verir. Böylece bu arayüzlerin ada dayalı ayırmalar kullanmasına izin verilir. Aşağıda ada dayalı bir tahsis örneği verilmiştir.
libdmabufheap
tarafından kullanıma sunulan her API ile ilgili dokümanlar mevcuttur. Kitaplık, C istemcileri tarafından kullanılacak bir üstbilgi dosyası da sağlar.
Referans Gralloc uygulaması
Hikey960 gralloc uygulamasında libdmabufheap
kullanıldığı için bu uygulamayı referans uygulama olarak kullanabilirsiniz.
Gerekli ueventd eklemeleri
Oluşturulan cihaza özgü yeni DMA-BUF yığınları için cihazın ueventd.rc
dosyasına yeni bir giriş ekleyin.
Bu 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
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ği, çeşitli istemcilerin DMA-BUF sistem yığınına erişmesi için oluşturulan sepolicy izinlerini gösterir.
Çerçeve kodundan tedarikçi firma yığınlarına erişme
Treble uyumluluğunu sağlamak için çerçeve kodu yalnızca önceden onaylanmış tedarikçi yığını kategorilerinden ayırt edebilir.
Google, iş ortaklarından alınan geri bildirimlere dayanarak çerçeve kodundan erişilmesi gereken iki tedarikçi firma yığını kategorisi belirledi:
- Cihaz veya SoC'ye özel performans optimizasyonları içeren sistem yığınına dayalı yığınlar.
- Korunan bellekten ayrılacak yığınlar.
Cihaza veya çip üzerinde sisteme (SoC) özel performans optimizasyonları içeren 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ü olması içingki_defconfig
'te devre dışı bırakılır.- VTS uygunluk testleri, yığının
/dev/dma_heap/system
adresinde bulunduğundan emin olur. Testler ayrıca, yığının kullanıcı alanından ayrılıp ayrılamayacağını ve döndürülen dosya tanımlayıcısının (fd
) kullanıcı alanından bellek haritasına eklenip eklenemeyeceğini de 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/Ç uyumlu cihazlar için zorunlu değildir.
Korunan bellekten ayrılacak yığınlar
Android Common Kernel, genel güvenli yığın uygulamasını desteklemediğinden güvenli yığın uygulamaları tedarikçiye özel olmalıdır.
- Tedarikçiye özgü 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, bunlardan tahsis yapılabileceğini doğrular.
- Çerçeve bileşenleri, Codec2 HAL/binder uygulanmamış, aynı işlem HAL'ler üzerinden yığın kullanımını etkinleştirebilmeleri için bu yığınlara erişebilir. Bununla birlikte, uygulama ayrıntılarındaki değişkenlikler nedeniyle genel Android çerçevesi özellikleri bunlara bağlı olamaz. Gelecekte Android Ortak Çekirdeği'ne genel bir güvenli yığın uygulaması eklenirse yükseltme yapan cihazlarla çakışmayı önlemek için farklı bir ABI kullanmalıdır.
DMA-BUF yığınları için Codec 2 ayırıcı
AOSP'de DMA-BUF yığın arayüzü için bir codec2 ayırıcı mevcuttur.
C2 HAL'den yığın parametrelerinin belirtilmesine olanak tanıyan bileşen mağazası arayüzü, C2 DMA-BUF yığın ayırıcısıyla 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ın değiştirilmesine olanak tanır. Aşağıdaki adımlarda, my_heap
adlı eski olmayan ve ION_FLAG_MY_FLAG
işaretini destekleyen bir ION yığınını taşımak 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, my_heap
ION yığını ION_FLAG_MY_FLAG
işaretini desteklediğinden iki DMA-BUF yığını kaydederiz:
my_heap
davranışı,ION_FLAG_MY_FLAG
işareti devre dışıyken ION yığınının davranışıyla tam olarak aynıdır.my_heap_special
davranışı,ION_FLAG_MY_FLAG
işareti etkinken ION yığınını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 istenen izinlerle /dev/dma_heap/my_heap
ve /dev/dma_heap/my_heap_special
olarak görünür.
3. Adım: my_heap
öğesinden ayırma yapan istemcilerde, oluşturma dosyalarını libdmabufheap
ile bağlantı kuracak şekilde değiştirin. İstemci başlatılırken 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.
Örnek:
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'yi 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 |
---|---|---|
ION_FLAG_MY_FLAG işareti ayarlanmamışken my_heap kaynağından tahsis
|
ion_alloc_fd(ionfd, size, 0, ION_HEAP_MY_HEAP, 0, &fd)
|
allocator->Alloc("my_heap", size)
|
ION_FLAG_MY_FLAG işareti ayarlanmış my_heap bölgesinden ayırma
|
ion_alloc_fd(ionfd, size, 0, ION_HEAP_MY_HEAP,
ION_FLAG_MY_FLAG, &fd)
|
allocator->Alloc("my_heap_special", size)
|
Bu noktada istemci çalışır durumdadır ancak DMA-BUF yığınını açmak için gerekli sepolicy izinlerine sahip olmadığından hâlâ ION yığınından ayırma işlemi yapmaktadır.
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ırmak için gerekli tüm özelliklere sahiptir.
6. adım: logcat'i inceleyerek ayırmaların yeni DMA-BUF yığınından yapıldığını doğrulayın.
7. Adım: Çekirdekteki ION yığınını (my_heap
) devre dışı bırakın. Müşteri kodunun, yükseltme yapan cihazları (çekirdekleri yalnızca ION yığınlarını destekleyebilir) desteklemesi gerekmiyorsa MapNameToIonHeap()
çağrılarını da kaldırabilirsiniz.