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, kerangka kerja Android dan HAL sekarang berkomunikasi satu sama lain menggunakan pengikat. Karena komunikasi ini secara dramatis meningkatkan lalu lintas pengikat, Android 8 menyertakan beberapa peningkatan yang dirancang untuk menjaga agar pengikat IPC tetap cepat. Vendor SoC dan OEM harus bergabung langsung dari cabang yang relevan dari android-4.4, android-4.9, dan yang lebih tinggi dari kernel/proyek umum .

Beberapa domain pengikat (konteks)

Common-4.4 dan lebih tinggi, termasuk upstream

Untuk memisahkan lalu lintas pengikat dengan rapi antara kode kerangka kerja (tidak tergantung perangkat) dan vendor (khusus perangkat), Android 8 memperkenalkan konsep konteks pengikat . Setiap konteks pengikat memiliki simpul perangkatnya sendiri dan pengelola konteks (layanan) sendiri. Anda dapat mengakses manajer konteks hanya melalui simpul perangkat yang dimilikinya dan, ketika melewati simpul pengikat melalui konteks tertentu, itu dapat diakses dari konteks yang sama hanya dengan proses lain, sehingga sepenuhnya mengisolasi domain dari satu sama lain. Untuk detail tentang penggunaan, lihat vndbinder dan vndservicemanager .

Sebar-kumpul

Common-4.4 dan lebih tinggi, termasuk upstream

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

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

Android 8 menggunakan pengoptimalan scatter-gather untuk mengurangi jumlah salinan dari 3 menjadi 1. Alih-alih membuat serial data dalam Parcel terlebih dahulu, data tetap berada dalam struktur aslinya dan tata letak memori dan driver segera menyalinnya ke proses target. Setelah data 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 upstream

Dalam rilis Android sebelumnya, driver pengikat menggunakan kunci global untuk melindungi dari akses bersamaan ke struktur data penting. Meskipun ada sedikit perselisihan untuk kunci, masalah utamanya adalah jika utas berprioritas rendah memperoleh kunci dan kemudian didahulukan, itu dapat secara serius menunda utas dengan prioritas lebih tinggi yang perlu mendapatkan kunci yang sama. Hal ini menyebabkan jank di platform.

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

Setelah mengidentifikasi masalah kecil dalam implementasi penguncian berbutir halus, kami merancang solusi yang ditingkatkan dengan arsitektur penguncian yang berbeda dan mengirimkan perubahan di semua cabang kernel umum. Kami terus menguji implementasi ini pada sejumlah besar perangkat yang berbeda; karena kami tidak mengetahui adanya masalah yang belum terselesaikan, ini adalah implementasi yang disarankan untuk pengiriman perangkat 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 waktu nyata, dalam beberapa kasus sekarang masuk akal bahwa jika utas waktu nyata membuat panggilan pengikat, utas dalam proses yang menangani panggilan itu juga berjalan pada prioritas waktu nyata . Untuk mendukung kasus penggunaan ini, Android 8 sekarang mengimplementasikan pewarisan prioritas waktu nyata di driver pengikat.

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 dijalankan. Versi Android sebelumnya telah mendukung pewarisan prioritas simpul dengan nilai yang bagus, tetapi Android 8 menambahkan dukungan untuk pewarisan simpul kebijakan penjadwalan waktu nyata.

Perubahan ruang pengguna

Android 8 menyertakan semua perubahan ruang pengguna yang diperlukan untuk bekerja dengan driver pengikat saat ini di kernel umum dengan satu pengecualian: Implementasi asli untuk menonaktifkan pewarisan prioritas waktu nyata untuk /dev/binder menggunakan ioctl . Pengembangan selanjutnya mengalihkan kontrol dari pewarisan prioritas ke metode yang lebih halus yaitu per mode pengikat (dan bukan per konteks). Jadi, ioctl tidak ada di cabang umum Android dan malah dikirimkan di kernel umum kami .

Efek dari perubahan ini adalah pewarisan prioritas waktu nyata dinonaktifkan secara default untuk setiap node. Tim kinerja Android merasa bermanfaat untuk mengaktifkan pewarisan prioritas waktu nyata untuk semua node dalam 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: pengikat: jangan periksa izin sebelumnya saat memulihkan.
  • Umum-4.4
    76b376eac7a2 ANDROID: pengikat: jangan periksa izin sebelumnya saat memulihkan.
  • Umum-4.9
    ecd972d4f9b5 ANDROID: pengikat: jangan periksa izin sebelumnya saat memulihkan.

Menggunakan pengikat IPC

Secara historis, proses vendor telah menggunakan binder interprocess communication (IPC) untuk berkomunikasi. Di Android 8, simpul perangkat /dev/binder menjadi eksklusif untuk proses kerangka kerja, artinya proses vendor tidak lagi memiliki akses ke sana. 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 yang dijelaskan di bawah ini.

vndbinder

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

Domain IPC Keterangan
/dev/binder IPC antara kerangka kerja/proses aplikasi dengan antarmuka AIDL
/dev/hwbinder IPC antara proses kerangka kerja/vendor dengan antarmuka HIDL
IPC antara 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 diatur ke "binder,hwbinder,vndbinder" (ini adalah default di pohon kernel umum Android).

Biasanya, proses vendor tidak membuka driver pengikat secara langsung dan malah menautkan ke perpustakaan ruang pengguna libbinder , yang membuka driver pengikat. Menambahkan metode untuk ::android::ProcessState() memilih driver pengikat untuk libbinder . Proses vendor harus memanggil metode ini sebelum memanggil ProcessState, IPCThreadState , atau sebelum melakukan panggilan binder secara umum. Untuk menggunakannya, tempatkan panggilan berikut setelah main() dari proses vendor (klien dan server):

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

manajer layanan

Sebelumnya, layanan pengikat terdaftar dengan servicemanager , di mana mereka 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 , instance baru dari servicemanager yang menggunakan /dev/vndbinder alih-alih /dev/binder dan yang dibangun dari sumber yang sama dengan framework 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 dipanggil ke domain vendor B melalui antarmuka binder vendor.
  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 dalam cara penanganan nama layanan, label layanan, dan aturan.

Untuk detail tentang SELinux, lihat Linux yang Ditingkatkan Keamanan 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 yang 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 domain akses 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 tersebut dapat tetap berlaku dan menggunakan kelas yang sama. Contoh:

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