Gunakan IPC binder

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

Perubahan pada driver binder

Mulai Android 8, framework Android dan HAL sekarang berkomunikasi dengan satu sama lain menggunakan binder. Karena komunikasi ini secara dramatis meningkatkan binder Android 8 menyertakan beberapa peningkatan yang dirancang untuk mempertahankan IPC binder dengan cepat. Vendor SoC dan OEM harus bergabung langsung dari cabang yang relevan dari android-4.4, android-4.9, dan yang lebih tinggi pada kernel/common Google Cloud.

Beberapa domain binder (konteks)

Common-4.4 dan yang lebih tinggi, termasuk upstream

Untuk memisahkan traffic binder dengan rapi antara framework (tidak bergantung pada perangkat) dan kode vendor (khusus perangkat), Android 8 memperkenalkan konsep binder konteks tambahan. Setiap konteks binder memiliki node perangkat dan konteksnya sendiri pengelola (layanan). Anda hanya dapat mengakses pengelola konteks melalui perangkat yang dimilikinya dan, saat meneruskan simpul binder melalui jalur konteks tersebut, hanya dapat diakses dari konteks yang sama oleh proses lain, sehingga benar-benar mengisolasi domain dari satu sama lain. Untuk detail tentang penggunaan, lihat vndbinder dan vndservicemanager.

Sebar mengumpulkan

Common-4.4 dan yang lebih tinggi, termasuk upstream

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

  • Sekali untuk diserialisasi ke dalam Parcel dalam proses panggilan
  • Setelah berada di driver kernel untuk menyalin Parcel ke target proses
  • Sekali untuk membatalkan serialisasi Parcel dalam proses target

Android 8 menggunakan sebar-kumpul pengoptimalan untuk mengurangi jumlah salinan dari 3 menjadi 1. Daripada fokus pada membuat serialisasi data di Parcel terlebih dahulu, data tetap dalam aslinya struktur dan tata letak memori, dan {i>driver<i} segera menyalinnya ke target {i>checkout<i}. Setelah data berada dalam proses target, struktur dan memori tetap sama dan data dapat dibaca tanpa memerlukan salinan lainnya.

Penguncian terperinci

Common-4.4 dan yang lebih tinggi, termasuk upstream

Di rilis Android sebelumnya, driver binder menggunakan kunci global untuk melindungi terhadap akses serentak ke struktur data kritis. Meskipun ada sedikit pertentangan untuk kunci, masalah utamanya adalah bahwa jika thread prioritas rendah mendapatkan kunci tersebut dan kemudian diantisipasi, hal itu dapat menyebabkan penundaan yang serius thread dengan prioritas lebih tinggi yang perlu mendapatkan kunci yang sama. Hal ini menyebabkan jank pada terkelola sepenuhnya.

Upaya awal untuk mengatasi masalah ini melibatkan penonaktifan {i>preemption<i} saat memegang kunci global. Namun, ini lebih berupa peretasan daripada solusi yang sebenarnya, dan akhirnya ditolak oleh upstream dan dihapus. Percobaan berikutnya berfokus untuk membuat penguncian lebih perinci, versi yang telah berjalan di perangkat Pixel sejak Januari 2017. Meskipun sebagian besar perubahan tersebut dipublikasikan, peningkatan substansial dilakukan dalam versi berikutnya.

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

Pewarisan prioritas real-time

Common-4.4 dan common-4.9 (segera hadir)

Driver binder selalu mendukung pewarisan prioritas yang bagus. Sebagai seorang peningkatan jumlah proses di Android yang berjalan pada prioritas real-time, dalam beberapa sekarang masuk akal jika thread {i>real-time<i} melakukan panggilan binder, thread dalam proses yang menangani panggilan itu juga berjalan pada prioritas real-time. Kepada mendukung kasus penggunaan ini, Android 8 kini mengimplementasikan pewarisan prioritas real-time di driver binder.

Selain pewarisan prioritas tingkat transaksi, prioritas node pewarisan memungkinkan node (objek layanan binder) menentukan nilai minimum prioritas yang mengharuskan panggilan ke node ini harus dijalankan. Versi sebelumnya dari Android sudah mendukung pewarisan prioritas node dengan nilai yang bagus, tetapi Android 8 menambahkan dukungan untuk pewarisan node kebijakan penjadwalan secara real-time.

Perubahan ruang pengguna

Android 8 menyertakan semua perubahan userspace yang diperlukan untuk bekerja dengan {i>binder driver<i} di {i>kernel<i} umum dengan satu pengecualian: Versi asli implementasi untuk menonaktifkan pewarisan prioritas real-time bagi /dev/binder menggunakan ioctl. Pengembangan berikutnya mengalihkan kontrol prioritas pewarisan ke metode yang lebih halus yaitu per mode binder (dan bukan per konteks tertentu). Jadi, ioctl tidak berada di cabang umum Android dan dikirimkan di kernel umum.

Efek perubahan ini adalah pewarisan prioritas real-time dinonaktifkan oleh default untuk setiap node. Tim performa Android telah menemukannya bermanfaat untuk mengaktifkan pewarisan prioritas real-time untuk semua node dalam hwbinder. Untuk mendapatkan efek yang sama, pilih satu perubahan ini di userspace.

SHA untuk kernel umum

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

  • Umum-3.18
    cc8b90c121de ANDROID: binder: don't check prio permissions on Restore.
  • Umum-4,4
    76b376eac7a2 ANDROID: binder: don't check prio permissions on Restore.
  • Umum-4,9
    ecd972d4f9b5 ANDROID: binder: don't check prio permissions on Restore.

Menggunakan binder IPC

Secara historis, proses vendor telah menggunakan komunikasi antarproses {i>binder<i} (IPC) untuk berkomunikasi. Di Android 8, node perangkat /dev/binder menjadi eksklusif untuk proses kerangka kerja, yang berarti 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 melanjutkan menggunakan antarmuka AIDL di antara proses vendor, Android mendukung binder IPC sebagai yang dijelaskan di bawah. Di Android 10, AIDL Stabil memungkinkan semua proses untuk menggunakan /dev/binder sekaligus mengatasi masalah stabilitas menjamin HIDL dan /dev/hwbinder terpecahkan. Untuk cara menggunakan Stabil AIDL, lihat AIDL untuk HAL.

Vndbinder

Android 8 mendukung domain binder baru untuk digunakan oleh layanan vendor, yang dapat diakses menggunakan /dev/vndbinder, bukan /dev/binder. Dengan setelah /dev/vndbinder, Android kini memiliki tiga Domain IPC:

Domain IPC Deskripsi
/dev/binder IPC antara proses framework/aplikasi dengan antarmuka AIDL
/dev/hwbinder IPC di antara proses framework/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 konfigurasi kernel item CONFIG_ANDROID_BINDER_DEVICES ditetapkan ke "binder,hwbinder,vndbinder" (ini adalah setelan default di pohon {i>kernel<i} yang umum).

Biasanya, proses vendor tidak membuka {i>driver<i} binder secara langsung dan sebagai gantinya terhadap library userspace libbinder, yang akan membuka {i>binder driver<i}. Menambahkan metode untuk ::android::ProcessState() memilih driver binder untuk libbinder. Proses vendor harus panggil metode ini sebelum memanggil ProcessState, IPCThreadState, atau sebelum melakukan panggilan binder secara umum. Kepada digunakan, lakukan panggilan berikut setelah main() dari proses vendor (klien dan server):

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

{i>vndservicemanager<i}

Sebelumnya, layanan binder didaftarkan ke servicemanager, di mana mereka dapat diambil oleh proses lain. Di Android 8, servicemanager kini digunakan secara eksklusif oleh framework dan aplikasi proses dan proses vendor tidak dapat lagi mengaksesnya.

Namun, layanan vendor kini dapat menggunakan vndservicemanager, instance servicemanager yang menggunakan /dev/vndbinder bukan /dev/binder dan yang dibuat dari sumber yang sama dengan framework servicemanager. Proses vendor tidak perlu membuat perubahan untuk berkomunikasi dengan vndservicemanager; saat proses vendor membuka /dev/vndbinder, pencarian layanan akan otomatis membuka vndservicemanager.

Biner vndservicemanager disertakan dalam default Android makefile perangkat.

Kebijakan SELinux

Proses vendor yang ingin menggunakan fungsi {i>binder<i} untuk berkomunikasi dengan satu sama lain membutuhkan hal berikut:

  1. Akses ke /dev/vndbinder.
  2. Hubungkan hook {transfer, call} ke dalam vndservicemanager.
  3. binder_call(A, B) untuk domain vendor A apa pun yang ingin dipanggil ke domain vendor B melalui antarmuka pengikat vendor.
  4. Izin untuk {add, find} layanan di vndservicemanager.

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

vndbinder_use(some_vendor_process_domain);

Untuk memenuhi persyaratan 3, binder_call(A, B) untuk vendor proses A dan B yang memerlukan penanganan {i>binder<i} dapat tetap berada di tempatnya, dan tidak perlu diganti namanya.

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

Untuk mengetahui detail tentang SELinux, lihat Peningkatan Keamanan Linux di Android. Untuk detail tentang SELinux di Android 8.0, lihat SELinux untuk Android 8.0.

Nama layanan

Sebelumnya, vendor memproses nama layanan yang terdaftar di service_contexts file dan menambahkan aturan yang sesuai 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 vndservice_contexts. Layanan vendor yang bermigrasi ke vndservicemanager (dan yang sudah ada di versi lama service_contexts file) harus ditambahkan ke file baru File vndservice_contexts.

Label layanan

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

type atfwd_service,      service_manager_type;

Di Android 8, Anda harus mengubah jenis menjadi vndservice_manager_type dan pindahkan aturan ke File vndservice.te. Contoh:

type atfwd_service,      vndservice_manager_type;

aturan servicemanager

Sebelumnya, aturan memberikan akses ke domain untuk menambahkan 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 class yang sama. Contoh:

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