Android 12'de GKI 2.0, aşağıdaki nedenlerden dolayı ION ayırıcısını 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. Bu ION ile mümkün değildi çünkü herhangi bir yığından tahsis yalnızca
/dev/ion
cihazına erişim gerektiriyordu. - ABI kararlılığı: ION'dan farklı olarak, DMA-BUF yığın çerçevesinin IOCTL arayüzünün ABI kararlılığı garanti edilir çünkü yukarı akışlı Linux çekirdeğinde korunur.
- Standardizasyon: DMA-BUF yığın çerçevesi iyi tanımlanmış bir UAPI sunar. ION, her cihazın ION uygulamasının farklı davranabilmesi nedeniyle ortak bir test çerçevesi geliştirmeyi engelleyen özel bayraklara ve yığın kimliklerine izin verdi.
Android Common Kernel'in android12-5.10
dalı , 1 Mart 2021'de CONFIG_ION
devre dışı bıraktı.
Arka plan
Aşağıda ION ve DMA-BUF yığınları arasında kısa bir karşılaştırma yer almaktadır.
ION ve DMA-BUF yığın çerçevesi arasındaki benzerlikler
- ION ve DMA-BUF yığın çerçevelerinin her ikisi de yığın tabanlı DMA-BUF dışa aktarıcılarıdır.
- İkisi de her yığının kendi ayırıcısını ve DMA-BUF operasyonlarını tanımlamasına izin veriyor.
- Tahsis performansı benzer çünkü her iki şema da tahsis için tek bir IOCTL'ye ihtiyaç duyuyor.
ION ve DMA-BUF yığın çerçevesi arasındaki farklar
İYON yığınları | DMA-BUF yığınları |
---|---|
Tüm ION tahsisleri /dev/ion ile yapılır. | Her DMA-BUF yığını /dev/dma_heap/<heap_name> konumunda bulunan bir karakter aygıtıdır. |
ION, yığın özel bayraklarını destekler. | DMA-BUF yığınları, yığın özel işaretlerini desteklemez. Bunun yerine her farklı tahsis türü farklı bir yığından yapılır. Örneğin, önbelleğe alınmış ve önbelleğe alınmamış sistem yığını çeşitleri, /dev/dma_heap/system ve /dev/dma_heap/system_uncached konumunda bulunan ayrı yığınlardır. |
Tahsis için yığın kimliği/maskesi ve bayrakların belirtilmesi gerekir. | 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ığın çerçevesine nasıl aktarılacağı 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 operasyonlarını uygulamasına olanak tanır. Böylece, yığını kaydetmek için farklı bir API kümesi kullanarak bir ION yığın uygulamasından DMA-BUF yığın uygulamasına geçiş yapabilirsiniz. Bu tablo, ION yığın kaydı API'lerini ve bunların eşdeğer DMA-BUF yığın API'lerini gösterir.
İYON 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. Dolayısıyla yığının her bir çeşidinin dma_heap_add()
API'si kullanılarak ayrı ayrı kaydedilmesi gerekir. Kod paylaşımını kolaylaştırmak için aynı yığının tüm değişkenlerinin 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ış değişkenlerinin uygulanmasını gösterir.
Sıfırdan bir DMA-BUF yığını oluşturmak için bu dma-buf: heaps: örnek şablonunu kullanın.
ION yığınlarından doğrudan tahsis edilen çekirdek sürücüleri
DMA-BUF yığın çerçevesi aynı zamanda çekirdek içi istemciler için bir tahsis arayüzü de sunar. Tahsisat türünü seçmek için yığın maskesini ve bayrakları belirtmek yerine, DMA-BUF yığınları tarafından sunulan arayüz, giriş olarak bir yığın adı alır.
Aşağıda çekirdek içi ION ayırma API'si ve eşdeğer DMA-BUF yığın ayırma API'leri gösterilmektedir. Çekirdek sürücüleri bir yığının varlığı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 daha sonra dma_heap_buffer_alloc()
API'sine argüman olarak iletilebilir.
İYON yığınları | DMA-BUF yığınları |
---|---|
struct dma_buf *ion_alloc(size_t len, unsigned int heap_id_mask, unsigned int flags) | |
DMA-BUF'leri kullanan çekirdek sürücüleri
Yalnızca DMA-BUF'leri içe aktaran sürücüler için herhangi bir değişiklik yapılmasına gerek yoktur çünkü bir ION yığınından tahsis edilen bir arabellek, eşdeğer bir DMA-BUF yığınından tahsis edilen bir arabellek ile tam olarak aynı şekilde davranı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
adı verilen bir soyutlama kitaplığı mevcuttur. libdmabufheap
DMA-BUF yığınlarında ve ION yığınlarında tahsisi destekler. Öncelikle belirtilen adda bir DMA-BUF yığınının var olup olmadığını kontrol eder ve eğer yoksa eşdeğer bir ION yığınına (varsa) geri döner.
İstemciler, başlatma sırasında /dev/ion using ion_open()
açmak yerine BufferAllocator
nesnesini 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 dahili olarak BufferAllocator
nesnesi tarafından yönetilmesidir.
libion
libdmabufheap
geçiş yapmak için istemcilerin davranışını aşağıdaki gibi değiştirin:
- Tahsis için kullanılacak yığın adının, baş kimliği/maskesi ve yığın bayrağı yerine takip edin.
- Bir yığın maskesi ve bayrak bağımsız değişkeni alan
ion_alloc_fd()
API'sini, bunun yerine bir yığın adı alanBufferAllocator::Alloc()
API'si ile değiştirin.
Bu tablo, libion
ve libdmabufheap
önbelleğe alınmamış bir sistem yığın tahsisini nasıl yaptığını göstererek bu değişiklikleri göstermektedir.
Tahsis türü | libion | libdmabufheap |
---|---|---|
Sistem yığınından önbelleğe alınmış tahsis | 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ış tahsis | ion_alloc_fd(ionfd, size, 0, ION_HEAP_SYSTEM, 0, &fd) | allocator->Alloc("system-uncached", size) |
Önbelleğe alınmamış sistem yığını çeşidi yukarı yönde onay bekliyor ancak zaten android12-5.10
dalının bir parçası.
Cihazların yükseltilmesini desteklemek için, MapNameToIonHeap()
API'si, bir yığın adının ION yığın parametreleriyle (yığın adı/maskesi ve bayrakları) eşleştirilmesine ve bu arayüzlerin aynı zamanda isme dayalı ayırmalar kullanmasına olanak sağlar. Burada isme dayalı bir tahsis örneği verilmiştir.
libdmabufheap
tarafından kullanıma sunulan her API'nin belgeleri mevcuttur. Kitaplık ayrıca C istemcileri tarafından kullanılacak bir başlık dosyasını da kullanıma sunar.
Referans Gralloc uygulaması
Hikey960 gralloc uygulaması libdmabufheap
kullanır, dolayısıyla onu referans uygulaması olarak kullanabilirsiniz.
Gerekli olay ve eklemeler
Oluşturulan cihaza özel yeni DMA-BUF yığınları için cihazın ueventd.rc
dosyasına yeni bir giriş ekleyin. DMA-BUF yığınlarını desteklemeye yönelik bu Kurulum örneği, bunun DMA-BUF sistem yığını için nasıl yapıldığını gösterir.
Gerekli sepolitika 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.
Satıcı yığınlarına çerçeve kodundan erişme
Treble uyumluluğunu sağlamak için çerçeve kodu yalnızca önceden onaylanmış satıcı yığın kategorilerinden tahsis edilebilir.
İş ortaklarından alınan geri bildirimlere dayanarak Google, çerçeve kodundan erişilmesi gereken iki tedarikçi yığını kategorisi belirledi:
- Cihaza veya SoC'ye özgü performans optimizasyonlarına sahip sistem yığınını temel alan yığınlar.
- Korumalı bellekten ayrılacak yığınlar.
Cihaza veya SoC'ye özgü performans optimizasyonlarına sahip sistem yığınını temel alan yığınlar
Bu kullanım durumunu desteklemek için varsayılan DMA-BUF yığın sisteminin yığın uygulaması geçersiz kılınabilir.
-
CONFIG_DMABUF_HEAPS_SYSTEM
, satıcı modülü olmasına izin vermek içingki_defconfig
kapatılmıştır. - VTS uyumluluk testleri, yığının
/dev/dma_heap/system
konumunda mevcut olmasını sağlar. Testler ayrıca yığının tahsis edilebileceğini ve döndürülen dosya tanımlayıcısının (fd
) kullanıcı alanından bellek eşlemeli (mmapped) yapılabileceğini doğrular.
Yukarıdaki noktalar aynı zamanda sistem yığınının önbelleğe alınmamış değişkeni için de geçerlidir; ancak bunun varlığı tamamen GÇ uyumlu cihazlar için zorunlu değildir.
Korumalı bellekten ayrılacak yığınlar
Android Common Kernel genel bir güvenli yığın uygulamasını desteklemediğinden, güvenli yığın uygulamaları satıcıya özel olmalıdır.
- Satıcıya ö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 mevcutsa, VTS testleri tahsislerin bunlardan yapılabileceğini garanti eder.
- Çerçeve bileşenlerine, Codec2 HAL/bağlayıcı olmayan, aynı işlem HAL'leri aracılığıyla yığın kullanımını etkinleştirebilmeleri için bu yığınlara erişim sağlanır. Ancak genel Android çerçeve ö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 cihazlarıyla çakışmaları önlemek için farklı bir ABI kullanması gerekir.
DMA-BUF yığınları için Codec 2 ayırıcısı
AOSP'de DMA-BUF yığın arayüzü için bir codec2 ayırıcısı mevcuttur.
Yığın parametrelerinin C2 HAL'den belirtilmesine olanak tanıyan bileşen deposu arayüzü, C2 DMA-BUF yığın ayırıcıyla birlikte kullanılabilir.
Bir 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
aynı anda bir yığının değiştirilmesine izin verir. Aşağıdaki adımlarda, ION_FLAG_MY_FLAG
tek bayrağını destekleyen, my_heap
adlı eski olmayan bir ION yığınının geçişine yönelik önerilen bir iş akışı gösterilmektedir.
Adım 1: DMA-BUF çerçevesinde ION yığınının eşdeğerlerini oluşturun. Bu örnekte, ION yığını my_heap
bir ION_FLAG_MY_FLAG
bayrağını desteklediğinden, iki DMA-BUF yığınını kaydederiz:
-
my_heap
davranışı,ION_FLAG_MY_FLAG
bayrağının devre dışı olduğu ION yığınının davranışıyla tam olarak eşleşir. -
my_heap_special
davranışı,ION_FLAG_MY_FLAG
bayrağı etkinken ION yığınının davranışıyla tam olarak eşleşir.
Adım 2: Yeni my_heap
ve my_heap_special
DMA-BUF yığınları için ueventd değişikliklerini oluşturun. Bu noktada yığınlar, amaçlanan izinlerle birlikte /dev/dma_heap/my_heap
ve /dev/dma_heap/my_heap_special
olarak görünür.
Adım 3: my_heap
tahsis yapan istemciler için, makefile dosyalarını libdmabufheap
bağlanacak şekilde değiştirin. İstemci başlatma sırasında, bir BufferAllocator
nesnesi oluşturun ve <ION heap name/mask, flag>
birleşimini 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 */ )
MapNameToIonHeap()
API'sini ad ve bayrak parametreleriyle kullanmak yerine, ION yığın adı parametresini boş olarak ayarlayarak <ION heap mask, flag>
öğesinden eşdeğer DMA-BUF yığın adlarına eşleme oluşturabilirsiniz.
Adım 4: Uygun yığın adını kullanarak ion_alloc_fd()
çağrılarını BufferAllocator::Alloc()
ile değiştirin.
Tahsis türü | libion | libdmabufheap |
---|---|---|
ION_FLAG_MY_FLAG işaretiyle my_heap tahsis ayarlanmadı | ion_alloc_fd(ionfd, size, 0, ION_HEAP_MY_HEAP, 0, &fd) | allocator->Alloc("my_heap", size |
ION_FLAG_MY_FLAG bayrağı ayarlanmış olarak my_heap 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 hala ION yığınından tahsis yapmaktadır.
Adım 5: İstemcinin yeni DMA-BUF yığınlarına erişmesi için gerekli olan sepolicy izinlerini oluşturun. İstemci artık yeni DMA-BUF yığınından tahsis yapmak için tam donanıma sahiptir.
Adım 6: Logcat'i inceleyerek tahsislerin yeni DMA-BUF yığınından gerçekleştiğini doğrulayın.
Adım 7: Çekirdekteki ION yığını my_heap
devre dışı bırakın. İstemci kodunun yükseltme aygıtlarını (çekirdekleri yalnızca ION yığınlarını destekleyebilen) desteklemesi gerekmiyorsa, MapNameToIonHeap()
çağrılarını da kaldırabilirsiniz.