Bağlayıcı IPC kullan

Bu sayfada, Android 8'deki binder sürücüsünde yapılan değişiklikler açıklanmakta, binder IPC'nin kullanımıyla ilgili ayrıntılar sağlanmakta ve gerekli SELinux politikası listelenmektedir.

Ciltleme sürücüsünde yapılan değişiklikler

Android 8'den itibaren Android çerçevesi ve HAL'ler, binder'ı kullanarak birbirleriyle iletişim kurar. Bu iletişim, bağlayıcı trafiğini önemli ölçüde artırdığı için Android 8, bağlayıcı IPC'nin hızlı kalmasını sağlamak için tasarlanmış çeşitli iyileştirmeler içerir. SoC tedarikçileri ve OEM'ler, kernel/common projesinin android-4.4, android-4.9 ve sonraki sürümlerinin ilgili dallarından doğrudan birleştirme yapmalıdır.

Birden çok bağlayıcı alanı (bağlam)

Yaygın: Yayın tarafı da dahil olmak üzere 4.4 ve sonraki sürümler

Android 8, bağlayıcı trafiğini çerçeve (cihazdan bağımsız) ve tedarikçi (cihaza özel) kod arasında net bir şekilde bölmek için bağlantı bağlamı kavramını kullanıma sundu. Her bağlayıcı bağlamının kendi cihaz düğümü ve kendi bağlam (hizmet) yöneticisi vardır. Bağlam yöneticisine yalnızca ait olduğu cihaz düğümü üzerinden erişebilirsiniz. Bir bağlayıcı düğümü belirli bir bağlamda iletilirken aynı bağlamda yalnızca başka bir işlem tarafından erişilebilir. Bu sayede alanlar birbirinden tamamen izole edilir. Kullanımla ilgili ayrıntılar için vndbinder ve vndservicemanager başlıklı makaleleri inceleyin.

Dağılım-toplama

Yaygın: Yayın tarafı da dahil olmak üzere 4.4 ve sonraki sürümler

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

  • Bir kez serileştirmek için Parcel çağrı sürecinde
  • Çekirdek sürücüsüne girdikten sonra Parcel'yi hedef işleme kopyalamak için
  • Hedef işlemde Parcel'nin seri bağlamasını kaldırmak için bir kez

Android 8, kopya sayısını 3'ten 1'e düşürmek için dağıt-topla optimizasyonunu kullanır. Veriler önce Parcel içinde seri hale getirilmek yerine orijinal yapısında ve bellek düzeninde kalır ve sürücü tarafından hemen hedef sürece kopyalanır. Veriler hedef işleme aktarıldıktan sonra yapı ve bellek düzeni aynıdır ve veriler başka bir kopya gerektirmeden okunabilir.

Ayrıntılı kilitleme

Yaygın: Yayın tarafı da dahil olmak üzere 4.4 ve sonraki sürümler

Ö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 çok az çekişme olsa da asıl sorun, düşük öncelikli bir iş parçacığının kilidi alması ve ardından önceliğinin alınması durumunda, aynı kilidi alması gereken daha yüksek öncelikli iş parçacıklarının ciddi şekilde gecikmesiydi. Bu durum platformda takılmalara neden oldu.

Bu sorunu çözmeye yönelik ilk girişimler, global kilidi tutarken öncelikli almayı devre dışı bırakmayı içeriyordu. Ancak bu, gerçek bir çözümden ziyade bir hile olduğundan, yukarı akış tarafından reddedildi ve elden çıkarıldı. Sonraki çalışmalarda, kilitleme işleminin daha ayrıntılı hale getirilmesi üzerinde duruldu. Bu özelliğin bir sürümü Ocak 2017'den beri Pixel cihazlarda kullanılmaktadır. Bu değişikliklerin çoğu herkese açık olarak yayınlansa da sonraki sürümlerde önemli iyileştirmeler yapıldı.

Ayrıntılı kilitleme uygulamasında küçük sorunlar tespit ettikten sonra farklı bir kilitleme mimarisi içeren iyileştirilmiş bir çözüm geliştirdik ve değişiklikleri tüm ortak çekirdek dallarına gönderdik. Bu uygulamayı çok sayıda farklı cihazda test etmeye devam ediyoruz. Henüz çözülmemiş bir sorunla karşılaşmadığımız için Android 8 yüklü cihazlarda bu uygulamayı kullanmanızı öneririz.

Gerçek zamanlı öncelik devralma

Common-4.4 ve common-4.9 (yakında yayına sunulacak)

Ciltleyici sürücüsü her zaman güzel bir öncelik devralmayı desteklemiştir. Android'de gerçek zamanlı öncelikli olarak çalışan işlem sayısı arttıkça, bazı durumlarda gerçek zamanlı bir iş parçacığı bağlayıcı çağrısı yaptığında, bu çağrıyı işleyen işlemdeki iş parçacığının da gerçek zamanlı öncelikli olarak çalışması mantıklı hale geliyor. Android 8, bu kullanım alanlarını desteklemek için artık bağlayıcı sürücüsünde gerçek zamanlı öncelik devralınmasını uygulamaktadır.

Düğüm önceliği devralma, işlem düzeyinde öncelik devralmaya ek olarak bir düğümün (bağlantılayıcı hizmet nesnesi) bu düğüme yapılan çağrıların yürütüleceği minimum önceliği belirtmesine olanak tanır. Android'in önceki sürümleri, iyi değerlerle düğüm önceliği devralmayı zaten destekliyordu ancak Android 8, gerçek zamanlı planlama politikaları düğüm devralma desteğini ekliyor.

Kullanıcı alanı değişiklikleri

Android 8, ortak çekirdekteki mevcut bağlayıcı sürücüsüyle çalışmak için gereken tüm kullanıcı alanı değişikliklerini içerir. Bunun tek istisnası, /dev/binder için gerçek zamanlı öncelik devralınmasını devre dışı bırakmak üzere kullanılan orijinal uygulamada bir ioctl kullanılmasıdır. Sonraki geliştirmelerde, öncelik devralınmasının kontrolü, bağlam başına değil, bağlayıcı modu başına daha ayrıntılı bir yönteme geçirildi. Bu nedenle ioctl, Android ortak dalında değil, ortak çekirdeklerimizde gönderilir.

Bu değişikliğin etkisi, her düğüm için gerçek zamanlı öncelik devralımının varsayılan olarak devre dışı bırakılmasıdır. Android performans ekibi, hwbinder alanındaki tüm düğümler için gerçek zamanlı öncelik devralınmasını etkinleştirmenin yararlı olduğunu tespit etti. Aynı etkiyi elde etmek için kullanıcı alanında bu değişikliği seçin.

Yaygın çekirdekler için SHA'lar

Bağlayıcı sürücüsünde gerekli değişiklikleri almak için uygun SHA ile senkronize edin:

  • Common-3.18
    cc8b90c121de ANDROID: binder: don't check prio permissions on restore.
  • Common-4.4
    76b376eac7a2 ANDROID: binder: don't check prio permissions on restore.
  • Common-4.9
    ecd972d4f9b5 ANDROID: binder: don't check prio permissions on restore.

Binder IPC ile çalışma

Tedarikçi firma süreçleri, geçmişte iletişim kurmak için bağlayıcı işlemler arası iletişimi (IPC) kullanıyordu. Android 8'de /dev/binder cihaz düğümü, çerçeve işlemlerine özel hale gelir. Bu, tedarikçi firma işlemlerinin artık bu düğüme erişemeyeceği anlamına gelir. Tedarikçi firma işlemleri /dev/hwbinder'e erişebilir ancak AIDL arayüzlerini HIDL kullanacak şekilde dönüştürmelidir. Tedarikçi firma işlemleri arasında AIDL arayüzlerini kullanmaya devam etmek isteyen tedarikçiler için Android, aşağıda açıklandığı gibi bağlayıcı IPC'yi destekler. Android 10'da kararlı AIDL, tüm işlemlerin /dev/binder kullanmasına izin verirken HIDL ve /dev/hwbinder'un sağladığı kararlılık garantilerini de çözer. Sabit AIDL'nin nasıl kullanılacağı hakkında bilgi edinmek için HAL'ler için AIDL başlıklı makaleyi inceleyin.

vndbinder

Android 8, tedarikçi firma hizmetleri tarafından kullanılmak üzere /dev/binder yerine /dev/vndbinder kullanılarak erişilen yeni bir bağlayıcı alanı destekler. /dev/vndbinder'ün eklenmesiyle Android'de artık aşağıdaki üç IPC alanı vardır:

IPC Alanı Açıklama
/dev/binder AIDL arayüzleriyle çerçeve/uygulama işlemleri arasında IPC
/dev/hwbinder HIDL arayüzlerine sahip çerçeve/tedarikçi süreçleri arasında IPC
HIDL arayüzlerine sahip tedarikçi süreçleri arasında IPC
/dev/vndbinder AIDL arayüzleriyle tedarikçi firma/tedarikçi firma işlemleri arasında IPC

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

Normalde tedarikçi firma işlemleri, bağlayıcı sürücüsünü doğrudan açmaz. Bunun yerine, bağlayıcı sürücüsünü açan libbinder kullanıcı alanı kitaplığına bağlantı verir. ::android::ProcessState() için bir yöntem eklediğinizde libbinder için bağlayıcı sürücüsü seçilir. Tedarikçi süreçleri, ProcessState, IPCThreadState'i çalmadan veya genel olarak herhangi bir bağlayıcı çağrısı yapmadan önce bu yöntemi çağırmalıdır. Kullanmak için bir tedarikçi sürecinin (istemci ve sunucu) main()'sinden sonra aşağıdaki çağrıyı yerleştirin:

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

vndservicemanager

Daha önce, bağlayıcı hizmetler servicemanager'e kaydediliyordu. Bu hizmetler, diğer işlemler tarafından alınabiliyordu. Android 8'de servicemanager artık yalnızca çerçeve ve uygulama işlemleri tarafından kullanılıyor ve tedarikçi firma işlemleri artık buna erişemiyor.

Ancak tedarikçi hizmetleri artık /dev/binder yerine /dev/vndbinder kullanan ve servicemanager çerçevesiyle aynı kaynaklardan oluşturulan yeni bir servicemanager örneği olan vndservicemanager'ü kullanabilir. Tedarikçi firma süreçlerinin vndservicemanager ile iletişime geçmek için değişiklik yapması gerekmez. Bir tedarikçi firma süreci /dev/vndbinder açıldığında hizmet aramaları otomatik olarak vndservicemanager'e gider.

vndservicemanager ikili dosyası, Android'in varsayılan cihaz makefile'lerine dahildir.

SELinux politikası

Birbirleriyle iletişim kurmak için bağlayıcı işlevini kullanmak isteyen tedarikçi firma işlemlerinin aşağıdakilere ihtiyacı vardır:

  1. /dev/vndbinder'a erişim.
  2. Bağlayıcı {transfer, call}, vndservicemanager'e bağlanır.
  3. Tedarikçi firma bağlayıcı arayüzü üzerinden tedarikçi firma B alanına çağrı yapmak isteyen herhangi bir tedarikçi firma A alanı için binder_call(A, B).
  4. vndservicemanager'daki {add, find} hizmetlerine erişim izni.

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

vndbinder_use(some_vendor_process_domain);

3. koşulu karşılamak için, bağlayıcı üzerinden iletişim kurması gereken A ve B tedarikçi firma işlemleri için binder_call(A, B) yerinde kalabilir ve yeniden adlandırılmasına gerek yoktur.

4. koşulu karşılamak için hizmet adları, hizmet etiketleri ve kuralların ele alınma biçiminde değişiklik yapmanız gerekir.

SELinux hakkında ayrıntılı bilgi için Android'de Güvenlik Gelişmiş Linux başlıklı makaleyi inceleyin. Android 8.0'daki SELinux hakkında ayrıntılı bilgi için Android 8.0 için SELinux başlıklı makaleyi inceleyin.

Hizmet adları

Daha önce satıcı, kayıtlı hizmet adlarını bir service_contexts dosyasında işleyip bu dosyaya erişmek için ilgili kuralları ekliyordu. device/google/marlin/sepolicy kaynağından örnek service_contexts dosyası:

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'e taşınan (ve eski service_contexts dosyasında bulunan) tedarikçi firma hizmetleri yeni vndservice_contexts dosyasına eklenmelidir.

Hizmet etiketleri

Daha önce 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ştirmeniz ve kuralı vndservice.te dosyasına taşımanız gerekir. Örnek:

type atfwd_service,      vndservice_manager_type;

servicemanager kuralları

Daha önce kurallar, alanlara servicemanager'ten hizmet ekleme veya bulma erişimi 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 geçerliliğini koruyabilir ve aynı sınıfı kullanabilir. Örnek:

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