Binder IPC'yi kullanma

Bu sayfa, Android 8'deki bağlayıcı sürücüsündeki değişiklikleri açıklar, bağlayıcı IPC'yi kullanma hakkında ayrıntılar sağlar ve gerekli SELinux politikasını listeler.

Bağlayıcı sürücüsündeki değişiklikler

Android 8'den başlayarak, Android çerçevesi ve HAL'ler artık bağlayıcı kullanarak birbirleriyle iletişim kurar. Bu iletişim, bağlayıcı trafiğini önemli ölçüde artırdığından, Android 8, bağlayıcı IPC'yi hızlı tutmak için tasarlanmış çeşitli iyileştirmeler içerir. SoC satıcıları ve OEM'ler, çekirdek/ortak projenin android-4.4, android-4.9 ve daha üst sürümlerinin ilgili dallarından doğrudan birleşmelidir.

Birden çok bağlayıcı etki alanı (bağlamlar)

Yukarı akış dahil olmak üzere Common-4.4 ve üstü

Bağlayıcı trafiğini çerçeve (cihazdan bağımsız) ve satıcı (cihaza özel) kodu arasında temiz bir şekilde bölmek için Android 8, bir bağlayıcı bağlamı kavramını tanıttı. Her bağlayıcı bağlamının kendi aygıt düğümü ve kendi bağlam (hizmet) yöneticisi vardır. Bağlam yöneticisine yalnızca ait olduğu aygıt düğümü aracılığıyla erişebilirsiniz ve bir bağlayıcı düğümü belirli bir bağlamdan geçirirken, aynı bağlamdan yalnızca başka bir işlem tarafından erişilebilir, böylece etki alanlarını birbirinden tamamen yalıtır. Kullanımla ilgili ayrıntılar için bkz. vndbinder ve vndservicemanager .

dağıtmak-toplamak

Yukarı akış dahil olmak üzere Common-4.4 ve üstü

Android'in önceki sürümlerinde, bir bağlayıcı çağrıdaki her veri parçası üç kez kopyalandı:

  • Çağrı sürecinde bir Parcel seri hale getirmek için bir kez
  • Parcel hedef işleme kopyalamak için çekirdek sürücüsüne girdikten sonra
  • Hedef süreçte Parcel seri hale getirilmesi için bir kez

Android 8, kopya sayısını Parcel 1'e düşürmek için dağılım toplama optimizasyonu kullanır. Veriler hedef işleme girdikten sonra yapı ve bellek düzeni aynıdır ve veriler başka bir kopya gerektirmeden okunabilir.

İnce taneli kilitleme

Yukarı akış dahil olmak üzere Common-4.4 ve üstü

Önceki Android sürümlerinde, bağlayıcı sürücüsü, kritik veri yapılarına eşzamanlı erişime karşı koruma sağlamak için genel bir kilit kullanıyordu. Kilit için minimum çekişme olsa da, asıl sorun, düşük öncelikli bir iş parçacığı kilidi elde ederse ve daha sonra önlenirse, aynı kilidi elde etmesi gereken yüksek öncelikli iş parçacıklarını ciddi şekilde geciktirebilirdi. Bu, platformda çöplüğe neden oldu.

Bu sorunu çözmeye yönelik ilk girişimler, genel kilit tutulurken önceden almanın devre dışı bırakılmasını içeriyordu. Ancak bu, gerçek bir çözümden çok bir saldırıydı ve sonunda yukarı akış tarafından reddedildi ve atıldı. Sonraki girişimler, bir sürümü Ocak 2017'den beri Pixel cihazlarda çalışan kilitlemeyi daha ayrıntılı hale getirmeye odaklandı. Bu değişikliklerin çoğu kamuya açıklanırken, sonraki sürümlerde önemli iyileştirmeler yapıldı.

İnce taneli kilitleme uygulamasındaki küçük sorunları belirledikten sonra, farklı bir kilitleme mimarisi ile geliştirilmiş bir çözüm geliştirdik ve değişiklikleri tüm ortak çekirdek dallarında sunduk. Bu uygulamayı çok sayıda farklı cihazda test etmeye devam ediyoruz; Bekleyen herhangi bir sorunun farkında olmadığımız için, Android 8 ile gönderilen cihazlar için önerilen uygulama budur.

Gerçek zamanlı öncelikli devralma

Common-4.4 ve common-4.9 (yukarı akış yakında)

Cilt sürücüsü her zaman iyi öncelikli devralmayı desteklemiştir. Android'de giderek artan sayıda işlem gerçek zamanlı öncelikte çalıştığından, bazı durumlarda artık gerçek zamanlı bir iş parçacığı bir bağlayıcı çağrısı yaparsa, işlemdeki bu çağrıyı işleyen iş parçacığının da gerçek zamanlı önceliğe sahip olması mantıklıdır. . Bu kullanım durumlarını desteklemek için Android 8 artık cilt sürücüsünde gerçek zamanlı öncelikli devralma uygular.

İşlem düzeyinde öncelikli devralmaya ek olarak, düğüm öncelikli devralma , bir düğümün (bağlayıcı hizmet nesnesi), bu düğüme yapılan çağrıların yürütüleceği minimum önceliği belirtmesine izin verir. Android'in önceki sürümleri, Nice değerleriyle düğüm önceliği devralmayı zaten destekliyordu, ancak Android 8, gerçek zamanlı zamanlama ilkeleri düğüm devralması için destek ekler.

Kullanıcı alanı değişiklikleri

Android 8, bir istisna dışında, ortak çekirdekteki geçerli cilt sürücüsüyle çalışmak için gereken tüm kullanıcı alanı değişikliklerini içerir: /dev/binder için gerçek zamanlı öncelikli devralmayı devre dışı bırakmak için orijinal uygulama bir ioctl kullandı. Müteakip geliştirme, öncelikli kalıtımın denetimini, bağlayıcı modu başına (bağlam başına değil) daha ayrıntılı bir yönteme geçirdi. Bu nedenle, ioctl Android ortak dalında değildir ve bunun yerine ortak çekirdeklerimizde gönderilir .

Bu değişikliğin etkisi, her düğüm için gerçek zamanlı öncelikli devralmanın varsayılan olarak devre dışı bırakılmasıdır. Android performans ekibi, hwbinder etki alanındaki tüm düğümler için gerçek zamanlı öncelikli devralmayı etkinleştirmeyi faydalı buldu. Aynı etkiyi elde etmek için, kullanıcı alanındaki bu değişikliği kesin olarak seçin.

Ortak çekirdekler için SHA'lar

Bağlayıcı sürücüsünde gerekli değişiklikleri elde etmek için uygun SHA ile eşitleyin:

  • Ortak-3.18
    cc8b90c121de ANDROID: bağlayıcı: geri yükleme sırasında önceden izinleri kontrol etmeyin.
  • Ortak-4.4
    76b376eac7a2 ANDROID: bağlayıcı: geri yükleme sırasında ön izinleri kontrol etmeyin.
  • Ortak-4.9
    ecd972d4f9b5 ANDROID: bağlayıcı: geri yükleme sırasında ön izinleri kontrol etmeyin.

Bağlayıcı IPC'yi kullanma

Tarihsel olarak, satıcı süreçleri iletişim kurmak için bağlayıcı süreçler arası iletişimi (IPC) kullanmıştır. Android 8'de, /dev/binder cihaz düğümü çerçeve süreçlerine özel hale gelir, yani satıcı süreçlerinin artık ona erişimi yoktur. Satıcı süreçleri /dev/hwbinder , ancak AIDL arabirimlerini HIDL'yi kullanacak şekilde dönüştürmeleri gerekir. Satıcı süreçleri arasında AIDL arabirimlerini kullanmaya devam etmek isteyen satıcılar için Android, aşağıda açıklandığı gibi bağlayıcı IPC'yi destekler.

vndbinder

Android 8, satıcı hizmetleri tarafından kullanılmak üzere /dev/binder yerine /dev/binder /dev/vndbinder kullanılarak erişilen yeni bir bağlayıcı etki alanını destekler. /dev/vndbinder , Android artık aşağıdaki üç IPC etki alanına sahiptir:

IPC Etki Alanı Açıklama
/dev/binder AIDL arayüzleri ile çerçeve/uygulama süreçleri arasında IPC
/dev/hwbinder HIDL arayüzleri ile çerçeve/satıcı süreçleri arasında IPC
HIDL arayüzleri ile satıcı süreçleri arasında IPC
/dev/vndbinder AIDL Arayüzleri ile satıcı/satıcı süreçleri arasında IPC

/dev/vndbinder görünmesi için, CONFIG_ANDROID_BINDER_DEVICES çekirdek yapılandırma öğesinin "binder,hwbinder,vndbinder" olarak ayarlandığından emin olun (bu, Android'in ortak çekirdek ağaçlarında varsayılandır).

Normalde, satıcı süreçleri cilt sürücüsünü doğrudan açmaz ve bunun yerine cilt sürücüsünü açan libbinder kullanıcı alanı kitaplığına bağlanır. ::android::ProcessState() için bir yöntem eklemek, libbinder için cilt sürücüsünü seçer. Satıcı süreçleri, ProcessState, IPCThreadState çağrı yapmadan veya genel olarak herhangi bir bağlayıcı çağrı yapmadan önce bu yöntemi çağırmalıdır. Kullanmak için, bir satıcı sürecinin (istemci ve sunucu) main() öğesinden sonra aşağıdaki çağrıyı yapın:

ProcessState::initWithDriver("/dev/vndbinder");

vndservicemanager

Daha önce, bağlayıcı hizmetleri diğer işlemler tarafından alınabilecekleri servicemanager ile kaydediliyordu. Android 8'de servicemanager artık yalnızca çerçeve ve uygulama süreçleri tarafından kullanılıyor ve satıcı süreçleri artık ona erişemiyor.

Ancak, satıcı hizmetleri artık /dev/ /dev/binder yerine /dev/vndbinder kullanan ve framework servicemanager ile aynı kaynaklardan oluşturulmuş yeni bir servicemanager örneği olan vndservicemanager kullanabilir. Satıcı süreçlerinin vndservicemanager ile konuşmak için değişiklik yapmasına gerek yoktur; bir satıcı süreci / dev/vndbinder , hizmet aramaları otomatik olarak vndservicemanager .

vndservicemanager ikili dosyası, Android'in varsayılan cihaz yapım dosyalarına dahildir.

SELinux politikası

Birbirleriyle iletişim kurmak için bağlayıcı işlevini kullanmak isteyen satıcı işlemleri aşağıdakilere ihtiyaç duyar:

  1. /dev/vndbinder .
  2. Binder {transfer, call} vndservicemanager .
  3. Satıcı bağlayıcı arabirimi üzerinden satıcı etki alanı B'yi aramak isteyen herhangi bir satıcı etki alanı A için binder_call(A, B) .
  4. vndservicemanager içinde {add, find} hizmetlerine izin.

1. ve 2. gereksinimleri karşılamak için vndbinder_use() makrosunu kullanın:

vndbinder_use(some_vendor_process_domain);

Gereksinim 3'ü yerine getirmek için, bağlayıcı üzerinde konuşması gereken A ve B satıcı süreçleri için binder_call(A, B) yerinde kalabilir ve yeniden adlandırılması gerekmez.

4. gereksinimi karşılamak için hizmet adlarının, hizmet etiketlerinin ve kuralların işlenme biçiminde değişiklikler yapmanız gerekir.

SELinux ile ilgili ayrıntılar için bkz . Android'de Security-Enhanced Linux . Android 8.0'da SELinux ile ilgili ayrıntılar için bkz. Android 8.0 için SELinux .

Hizmet adları

Daha önce satıcı, bir service_contexts dosyasında kayıtlı hizmet adlarını işler ve bu dosyaya erişmek için ilgili kuralları ekler. device/google/marlin/sepolicy service_contexts

AtCmdFwd                              u:object_r:atfwd_service:s0
cneservice                            u:object_r:cne_service:s0
qti.ims.connectionmanagerservice      u:object_r:imscm_service:s0
rcs                                   u:object_r:radio_service:s0
uce                                   u:object_r:uce_service:s0
vendor.qcom.PeripheralManager         u:object_r:per_mgr_service:s0

Android 8'de vndservicemanager , bunun yerine vndservice_contexts dosyasını yükler. vndservicemanager (ve zaten eski service_contexts dosyasında bulunan) satıcı hizmetleri yeni vndservice_contexts dosyasına eklenmelidir.

Hizmet etiketleri

Önceden, u:object_r:atfwd_service:s0 gibi hizmet etiketleri bir service.te dosyasında tanımlanıyordu. Örnek:

type atfwd_service,      service_manager_type;

Android 8'de türü vndservice_manager_type olarak değiştirmeli ve kuralı vndservice.te dosyasına taşımalısınız. Örnek:

type atfwd_service,      vndservice_manager_type;

Servis yöneticisi kuralları

Önceden kurallar, alan adlarına servicemanager hizmet eklemek veya bu hizmeti bulmak için erişim izni veriyordu. Örnek:

allow atfwd atfwd_service:service_manager find;
allow some_vendor_app atfwd_service:service_manager add;

Android 8'de bu tür kurallar yerinde kalabilir ve aynı sınıfı kullanabilir. Örnek:

allow atfwd atfwd_service:service_manager find;
allow some_vendor_app atfwd_service:service_manager add;