Menggunakan pengikat IPC

Halaman ini menjelaskan perubahan pada driver binder di Android 8, memberikan detail tentang penggunaan IPC binder, dan mencantumkan kebijakan SELinux yang diperlukan.

Perubahan pada driver pengikat

Mulai Android 8, framework Android dan HAL kini berkomunikasi satu sama lain menggunakan binder. Karena komunikasi ini secara dramatis meningkatkan lalu lintas pengikat, Android 8 menyertakan beberapa penyempurnaan yang dirancang untuk menjaga IPC pengikat tetap cepat. Vendor SoC dan OEM harus bergabung langsung dari cabang terkait Android-4.4, Android-4.9, dan yang lebih tinggi dari proyek kernel/umum .

Beberapa domain pengikat (konteks)

Common-4.4 dan lebih tinggi, termasuk hulu

Untuk memisahkan lalu lintas pengikat antara kode kerangka kerja (tidak bergantung pada perangkat) dan kode vendor (khusus perangkat), Android 8 memperkenalkan konsep konteks pengikat . Setiap konteks pengikat memiliki simpul perangkatnya sendiri dan pengelola konteksnya sendiri (layanan). Anda dapat mengakses pengelola konteks hanya melalui node perangkat yang memilikinya dan, saat meneruskan node pengikat melalui konteks tertentu, node tersebut hanya dapat diakses dari konteks yang sama melalui proses lain, sehingga sepenuhnya mengisolasi domain satu sama lain. Untuk detail penggunaan, lihat vndbinder dan vndservicemanager .

Menyebar-kumpul

Common-4.4 dan lebih tinggi, termasuk hulu

Pada rilis Android sebelumnya, setiap bagian data dalam panggilan pengikat disalin tiga kali:

  • Sekali untuk membuat serial menjadi Parcel dalam proses pemanggilan
  • Setelah di driver kernel untuk menyalin Parcel ke proses target
  • Sekali untuk membatalkan serialisasi Parcel dalam proses target

Android 8 menggunakan optimasi scatter-gather untuk mengurangi jumlah salinan dari 3 menjadi 1. Daripada membuat serial data dalam Parcel terlebih dahulu, data tetap berada dalam struktur dan tata letak memori aslinya dan driver segera menyalinnya ke proses target. Setelah data berada dalam proses target, struktur dan tata letak memori sama dan data dapat dibaca tanpa memerlukan salinan lagi.

Penguncian berbutir halus

Common-4.4 dan lebih tinggi, termasuk hulu

Pada rilis Android sebelumnya, driver binder menggunakan kunci global untuk melindungi terhadap akses bersamaan ke struktur data penting. Meskipun terdapat sedikit pertentangan mengenai kunci tersebut, masalah utamanya adalah jika thread berprioritas rendah mendapatkan kunci tersebut dan kemudian didahului, hal ini dapat menunda thread dengan prioritas lebih tinggi yang perlu mendapatkan kunci yang sama. Hal ini menyebabkan jank pada platform.

Upaya awal untuk menyelesaikan masalah ini melibatkan penonaktifan preemption sambil menahan kunci global. Namun, ini lebih merupakan peretasan daripada solusi sebenarnya, dan akhirnya ditolak oleh pihak upstream dan dibuang. Upaya selanjutnya berfokus pada menjadikan penguncian lebih detail, yang versinya telah berjalan di perangkat Pixel sejak Januari 2017. Meskipun sebagian besar perubahan tersebut dipublikasikan, peningkatan substansial dilakukan pada versi berikutnya.

Setelah mengidentifikasi masalah kecil dalam penerapan penguncian terperinci, kami merancang solusi yang lebih baik dengan arsitektur penguncian yang berbeda dan mengirimkan perubahan di semua cabang kernel umum. Kami terus menguji penerapan ini pada sejumlah besar perangkat berbeda; karena kami tidak mengetahui adanya masalah yang belum terselesaikan, ini adalah penerapan yang direkomendasikan untuk perangkat yang dikirimkan dengan Android 8.

Warisan prioritas waktu nyata

Common-4.4 dan common-4.9 (upstream segera hadir)

Pengandar pengikat selalu mendukung pewarisan prioritas yang bagus. Karena semakin banyak proses di Android yang berjalan pada prioritas real-time, dalam beberapa kasus kini masuk akal jika thread real-time membuat panggilan pengikat, thread dalam proses yang menangani panggilan tersebut juga berjalan pada prioritas real-time. . Untuk mendukung kasus penggunaan ini, Android 8 kini mengimplementasikan pewarisan prioritas real-time di driver binder.

Selain pewarisan prioritas tingkat transaksi, pewarisan prioritas simpul memungkinkan sebuah simpul (objek layanan pengikat) untuk menentukan prioritas minimum di mana panggilan ke simpul ini harus dieksekusi. Versi Android sebelumnya telah mendukung pewarisan prioritas simpul dengan nilai yang bagus, namun Android 8 menambahkan dukungan untuk kebijakan penjadwalan real-time pewarisan simpul.

Perubahan ruang pengguna

Android 8 menyertakan semua perubahan ruang pengguna yang diperlukan agar dapat berfungsi dengan driver binder saat ini di kernel umum, dengan satu pengecualian: Implementasi asli untuk menonaktifkan pewarisan prioritas real-time untuk /dev/binder menggunakan ioctl . Pengembangan selanjutnya mengalihkan kendali pewarisan prioritas ke metode yang lebih terperinci yaitu per mode pengikat (dan bukan per konteks). Jadi, ioctl tidak ada di cabang umum Android dan malah dikirimkan di kernel umum kita .

Dampak dari perubahan ini adalah pewarisan prioritas real-time dinonaktifkan secara default untuk setiap node. Tim kinerja Android merasakan manfaatnya dengan mengaktifkan pewarisan prioritas real-time untuk semua node di domain hwbinder . Untuk mencapai efek yang sama, pilih perubahan ini di ruang pengguna.

SHA untuk kernel umum

Untuk mendapatkan perubahan yang diperlukan pada driver pengikat, sinkronkan ke SHA yang sesuai:

  • Umum-3.18
    cc8b90c121de ANDROID: binder: jangan periksa izin prio saat pemulihan.
  • Umum-4.4
    76b376eac7a2 ANDROID: binder: jangan periksa izin prio saat pemulihan.
  • Umum-4.9
    ecd972d4f9b5 ANDROID: binder: jangan periksa izin prio saat pemulihan.

Menggunakan pengikat IPC

Secara historis, proses vendor telah menggunakan komunikasi antarproses pengikat (IPC) untuk berkomunikasi. Di Android 8, node perangkat /dev/binder menjadi eksklusif untuk proses framework, artinya proses vendor tidak lagi memiliki akses ke node tersebut. Proses vendor dapat mengakses /dev/hwbinder , tetapi harus mengonversi antarmuka AIDL mereka untuk menggunakan HIDL. Untuk vendor yang ingin terus menggunakan antarmuka AIDL antar proses vendor, Android mendukung binder IPC seperti dijelaskan di bawah. Di Android 10, AIDL Stabil memungkinkan semua proses menggunakan /dev/binder sekaligus menyelesaikan jaminan stabilitas HIDL dan /dev/hwbinder diselesaikan. Untuk mengetahui cara menggunakan AIDL Stabil, lihat AIDL untuk HALs .

vndbinder

Android 8 mendukung domain pengikat baru untuk digunakan oleh layanan vendor, diakses menggunakan /dev/vndbinder bukan /dev/binder . Dengan tambahan /dev/vndbinder , Android kini memiliki tiga domain IPC berikut:

Domain IPC Keterangan
/dev/binder IPC antara proses kerangka/aplikasi dengan antarmuka AIDL
/dev/hwbinder IPC antara proses framework/vendor dengan antarmuka HIDL
IPC antar proses vendor dengan antarmuka HIDL
/dev/vndbinder IPC antara proses vendor/vendor dengan Antarmuka AIDL

Agar /dev/vndbinder muncul, pastikan item konfigurasi kernel CONFIG_ANDROID_BINDER_DEVICES disetel ke "binder,hwbinder,vndbinder" (ini adalah default di pohon kernel umum Android).

Biasanya, proses vendor tidak membuka driver binder secara langsung dan malah terhubung dengan perpustakaan libbinder userspace, yang membuka driver binder. Menambahkan metode untuk ::android::ProcessState() akan memilih driver pengikat untuk libbinder . Proses vendor harus memanggil metode ini sebelum memanggil ProcessState, IPCThreadState , atau sebelum melakukan panggilan pengikat apa pun secara umum. Untuk menggunakannya, lakukan panggilan berikut setelah main() dari proses vendor (klien dan server):

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

vndservicemanager

Sebelumnya, layanan pengikat telah didaftarkan ke servicemanager , di mana layanan tersebut dapat diambil oleh proses lain. Di Android 8, servicemanager sekarang digunakan secara eksklusif oleh kerangka kerja dan proses aplikasi dan proses vendor tidak dapat lagi mengaksesnya.

Namun, layanan vendor sekarang dapat menggunakan vndservicemanager , sebuah instance baru dari servicemanager yang menggunakan /dev/vndbinder alih-alih /dev/binder dan yang dibangun dari sumber yang sama dengan kerangka servicemanager . Proses vendor tidak perlu melakukan perubahan untuk berbicara dengan vndservicemanager ; ketika proses vendor terbuka / dev/vndbinder , pencarian layanan secara otomatis masuk ke vndservicemanager .

Biner vndservicemanager disertakan dalam makefile perangkat default Android.

kebijakan SELinux

Proses vendor yang ingin menggunakan fungsionalitas pengikat untuk berkomunikasi satu sama lain memerlukan hal berikut:

  1. Akses ke /dev/vndbinder .
  2. Binder {transfer, call} terhubung ke vndservicemanager .
  3. binder_call(A, B) untuk setiap domain vendor A yang ingin memanggil domain vendor B melalui antarmuka vendor binder.
  4. Izin untuk {add, find} layanan di vndservicemanager .

Untuk memenuhi persyaratan 1 dan 2, gunakan makro vndbinder_use() :

vndbinder_use(some_vendor_process_domain);

Untuk memenuhi persyaratan 3, binder_call(A, B) untuk proses vendor A dan B yang perlu membicarakan binder dapat tetap di tempatnya, dan tidak perlu diganti namanya.

Untuk memenuhi persyaratan 4, Anda harus membuat perubahan pada cara penanganan nama layanan, label layanan, dan aturan.

Untuk detail tentang SELinux, lihat Linux dengan Keamanan yang Ditingkatkan di Android . Untuk detail tentang SELinux di Android 8.0, lihat SELinux untuk Android 8.0 .

Nama layanan

Sebelumnya, vendor memproses nama layanan terdaftar dalam file service_contexts dan menambahkan aturan terkait untuk mengakses file tersebut. Contoh file service_contexts dari device/google/marlin/sepolicy :

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

Di Android 8, vndservicemanager memuat file vndservice_contexts sebagai gantinya. Layanan vendor yang bermigrasi ke vndservicemanager (dan yang sudah ada di file service_contexts lama) harus ditambahkan ke file vndservice_contexts baru.

Label layanan

Sebelumnya, label layanan seperti u:object_r:atfwd_service:s0 didefinisikan dalam file service.te . Contoh:

type atfwd_service,      service_manager_type;

Di Android 8, Anda harus mengubah tipe menjadi vndservice_manager_type dan memindahkan aturan ke file vndservice.te . Contoh:

type atfwd_service,      vndservice_manager_type;

Aturan manajer layanan

Sebelumnya, aturan memberikan akses domain untuk menambah atau menemukan layanan dari servicemanager . Contoh:

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

Di Android 8, aturan seperti itu bisa tetap berlaku dan menggunakan kelas yang sama. Contoh:

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