Renderscript

RenderScript adalah kerangka kerja untuk menjalankan tugas komputasi intensif dengan kinerja tinggi di Android. Ini dirancang untuk digunakan dengan komputasi paralel data, meskipun beban kerja serial juga dapat memperoleh manfaat. Runtime RenderScript memparalelkan pekerjaan di seluruh prosesor yang tersedia di perangkat, seperti CPU multi-core dan GPU, sehingga memungkinkan pengembang untuk fokus pada pengekspresian algoritma daripada menjadwalkan pekerjaan. RenderScript sangat berguna untuk aplikasi yang melakukan pemrosesan gambar, fotografi komputasi, atau visi komputer.

Perangkat yang menjalankan Android 8.0 dan lebih tinggi menggunakan kerangka kerja RenderScript dan HAL vendor berikut:

Gambar 1. Kode vendor yang tertaut ke lib internal

Perbedaan dari RenderScript di Android 7.x dan yang lebih rendah meliputi:

  • Dua contoh lib internal RenderScript dalam suatu proses. Satu set adalah untuk jalur fallback CPU dan berasal langsung dari /system/lib ; set lainnya adalah untuk jalur GPU dan berasal dari /system/lib/vndk-sp .
  • Lib internal RS di /system/lib dibuat sebagai bagian dari platform dan diperbarui saat system.img ditingkatkan. Namun, lib di /system/lib/vndk-sp dibuat untuk vendor dan tidak diperbarui ketika system.img ditingkatkan (walaupun dapat diperbarui untuk perbaikan keamanan, ABI-nya tetap sama).
  • Kode vendor (RS HAL, driver RS, dan bcc plugin ) ditautkan ke lib internal RenderScript yang terletak di /system/lib/vndk-sp . Mereka tidak dapat terhubung dengan lib di /system/lib karena lib di direktori tersebut dibuat untuk platform dan karenanya mungkin tidak kompatibel dengan kode vendor (yaitu, simbol dapat dihapus). Melakukan hal itu akan membuat OTA yang hanya kerangka kerja menjadi tidak mungkin.

Desain

Bagian berikut merinci desain RenderScript di Android 8.0 dan lebih tinggi.

Lib RenderScript tersedia untuk vendor

Bagian ini mencantumkan lib RenderScript (dikenal sebagai Vendor NDK untuk Same-Process HALs atau VNDK-SP) yang tersedia untuk kode vendor dan dapat ditautkan. Ini juga merinci perpustakaan tambahan yang tidak terkait dengan RenderScript tetapi juga disediakan untuk kode vendor.

Meskipun daftar pustaka berikut mungkin berbeda antar rilis Android, daftar tersebut tidak dapat diubah untuk rilis Android tertentu; untuk daftar terkini perpustakaan yang tersedia, lihat /system/etc/ld.config.txt .

Lib RenderScript Lib Non-RenderScript
  • android.hardware.graphics.renderscript@1.0.so
  • libRS_internal.so
  • libRSCpuRef.so
  • libblas.so
  • libbcinfo.so
  • libcompiler_rt.so
  • libRSDriver.so
  • libc.so
  • libm.so
  • libdl.so
  • libstdc++.so
  • liblog.so
  • libnativewindow.so
  • libsync.so
  • libvndksupport.so
  • libbase.so
  • libc++.so
  • libcutils.so
  • libutils.so
  • libhardware.so
  • libhidlbase.so
  • libhidltransport.so
  • libhwbinder.so
  • liblzma.so
  • libz.so
  • libEGL.so
  • libGLESv1_CM.so
  • libGLESv2.so

Konfigurasi namespace linker

Pembatasan penautan yang mencegah lib yang tidak ada di VNDK-SP digunakan oleh kode vendor diberlakukan saat runtime menggunakan namespace linker. (Untuk detailnya, lihat presentasi Desain VNDK .)

Pada perangkat yang menjalankan Android 8.0 dan lebih tinggi, semua HAL Proses yang Sama (SP-HAL) kecuali RenderScript dimuat di dalam namespace linker sphal . RenderScript dimuat ke dalam namespace khusus RenderScript rs , sebuah lokasi yang memungkinkan penerapan yang sedikit lebih longgar untuk lib RenderScript. Karena implementasi RS perlu memuat bitcode yang dikompilasi, /data/*/*.so ditambahkan ke jalur namespace rs (SP-HAL lain tidak diperbolehkan memuat lib dari partisi data).

Selain itu, namespace rs mengizinkan lebih banyak lib daripada yang disediakan oleh namespace lain. libmediandk.so dan libft2.so diekspos ke namespace rs karena libRS_internal.so memiliki ketergantungan internal pada perpustakaan ini.

Gambar 2. Konfigurasi namespace untuk linker

Memuat driver

Jalur penggantian CPU

Bergantung pada keberadaan bit RS_CONTEXT_LOW_LATENCY saat membuat konteks RS, jalur CPU atau GPU dipilih. Ketika jalur CPU dipilih, libRS_internal.so (implementasi utama kerangka RS) langsung dlopen dari namespace linker default tempat versi platform lib RS disediakan.

Implementasi RS HAL dari vendor tidak digunakan sama sekali ketika jalur fallback CPU diambil, dan objek RsContext dibuat dengan null mVendorDriverName . libRSDriver.so (secara default) dlopen dan lib driver dimuat dari namespace default karena pemanggil ( libRS_internal.so ) juga dimuat di namespace default .

Gambar 4. Jalur penggantian CPU

jalur GPU

Untuk jalur GPU, libRS_internal.so dimuat secara berbeda. Pertama, libRS.so menggunakan android.hardware.renderscript@1.0.so (dan libhidltransport.so yang mendasarinya) untuk memuat android.hardware.renderscript@1.0-impl.so (implementasi vendor RS HAL) ke namespace linker berbeda yang disebut sphal . RS HAL kemudian dlopen libRS_internal.so di namespace linker lain yang disebut rs .

Vendor dapat menyediakan driver RS ​​mereka sendiri dengan menyetel tanda waktu pembuatan OVERRIDE_RS_DRIVER , yang tertanam dalam implementasi RS HAL ( hardware/interfaces/renderscript/1.0/default/Context.cpp ). Nama driver ini kemudian dlopen untuk konteks RS untuk jalur GPU.

Pembuatan objek RsContext didelegasikan ke implementasi RS HAL. HAL memanggil kembali kerangka RS menggunakan fungsi rsContextCreateVendor() dengan nama driver untuk digunakan sebagai argumen. Kerangka RS kemudian memuat driver yang ditentukan ketika RsContext diinisialisasi. Dalam hal ini, pustaka driver dimuat ke dalam namespace rs karena objek RsContext dibuat di dalam namespace rs dan /vendor/lib berada di jalur pencarian namespace.

Gambar 5. Jalur fallback GPU

Saat bertransisi dari namespace default ke namespace sphal , libhidltransport.so menggunakan fungsi android_load_sphal_library() untuk secara eksplisit mengurutkan linker dinamis untuk memuat pustaka -impl.so dari namespace sphal .

Saat bertransisi dari namespace sphal ke namespace rs , pemuatan dilakukan secara tidak langsung melalui baris berikut di /system/etc/ld.config.txt :

namespace.sphal.link.rs.shared_libs = libRS_internal.so

Baris ini menentukan tautan dinamis harus memuat libRS_internal.so dari namespace rs ketika lib tidak dapat ditemukan/dimuat dari namespace sphal (yang selalu terjadi karena namespace sphal tidak mencari /system/lib/vndk-sp di mana libRS_internal.so berada). Dengan konfigurasi ini, panggilan dlopen() sederhana ke libRS_internal.so sudah cukup untuk melakukan transisi namespace.

Memuat plugin bcc

bcc plugin adalah perpustakaan yang disediakan vendor yang dimuat ke dalam kompiler bcc . Karena bcc adalah proses sistem di direktori /system/bin , pustaka bcc plugin dapat dianggap sebagai SP-HAL (yaitu, HAL vendor yang dapat langsung dimuat ke dalam proses sistem tanpa dibinderisasi). Sebagai SP-HAL, perpustakaan bcc-plugin :

  • Tidak dapat menautkan ke pustaka kerangka kerja saja seperti libLLVM.so .
  • Dapat menautkan hanya ke perpustakaan VNDK-SP yang tersedia untuk vendor.

Pembatasan ini diterapkan dengan memuat bcc plugin ke dalam namespace sphal menggunakan fungsi android_sphal_load_library() . Di versi Android sebelumnya, nama plugin ditentukan menggunakan opsi -load dan lib dimuat menggunakan dlopen() sederhana oleh libLLVM.so . Di Android 8.0 dan lebih tinggi, ini ditentukan dalam opsi -plugin dan lib langsung dimuat oleh bcc itu sendiri. Opsi ini mengaktifkan jalur khusus non-Android ke proyek LLVM sumber terbuka.

Gambar 6. Memuat plugin bcc, Android 7.x dan lebih rendah


Gambar 7. Memuat plugin bcc, Android 8.0 dan lebih tinggi

Jalur pencarian untuk ld.mc

Saat mengeksekusi ld.mc , beberapa lib runtime RS diberikan sebagai input ke linker. Bitcode RS dari aplikasi ditautkan dengan lib runtime dan ketika bitcode yang dikonversi dimuat ke dalam proses aplikasi, lib runtime kembali ditautkan secara dinamis dari bitcode yang dikonversi.

Lib runtime meliputi:

  • libcompiler_rt.so
  • libm.so
  • libc.so
  • Driver RS ​​(baik libRSDriver.so atau OVERRIDE_RS_DRIVER )

Saat memuat bitcode yang dikompilasi ke dalam proses aplikasi, sediakan pustaka yang sama persis dengan yang digunakan oleh ld.mc . Jika tidak, bitcode yang dikompilasi mungkin tidak menemukan simbol yang tersedia saat ditautkan.

Untuk melakukannya, kerangka RS menggunakan jalur pencarian yang berbeda untuk lib runtime saat mengeksekusi ld.mc , bergantung pada apakah kerangka RS itu sendiri dimuat dari /system/lib atau dari /system/lib/vndk-sp . Hal ini dapat ditentukan dengan membaca alamat simbol arbitrer dari lib kerangka RS dan menggunakan dladdr() untuk memetakan jalur file ke alamat tersebut.

kebijakan SELinux

Sebagai akibat dari perubahan kebijakan SELinux di Android 8.0 dan yang lebih tinggi, Anda harus mengikuti aturan tertentu (diberlakukan melalui neverallows ) saat memberi label pada file tambahan di partisi vendor :

  • vendor_file harus menjadi label default untuk semua file di partisi vendor . Kebijakan platform mengharuskan ini untuk mengakses implementasi HAL passthrough.
  • Semua exec_types baru yang ditambahkan di partisi vendor melalui vendor SEPolicy harus memiliki atribut vendor_file_type . Hal ini ditegakkan melalui neverallows .
  • Untuk menghindari konflik dengan pembaruan platform/kerangka kerja di masa mendatang, hindari memberi label file selain exec_types di partisi vendor .
  • Semua dependensi pustaka untuk HAL proses yang sama yang diidentifikasi oleh AOSP harus diberi label same_process_hal_file .

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

Kompatibilitas ABI untuk bitcode

Jika tidak ada API baru yang ditambahkan, yang berarti tidak ada perubahan versi HAL, kerangka RS akan tetap menggunakan driver GPU (HAL 1.0) yang ada.

Untuk perubahan kecil HAL (HAL 1.1) yang tidak memengaruhi bitcode, kerangka kerja harus kembali ke CPU untuk API yang baru ditambahkan ini dan tetap menggunakan driver GPU (HAL 1.0) di tempat lain.

Untuk perubahan HAL besar (HAL 2.0) yang memengaruhi kompilasi/penautan bitcode, kerangka kerja RS sebaiknya memilih untuk tidak memuat driver GPU yang disediakan vendor dan sebagai gantinya menggunakan jalur CPU atau Vulkan untuk akselerasi.

Penggunaan bitcode RenderScript terjadi dalam tiga tahap:

Panggung Detail
Menyusun
  • Bitcode input (.bc) untuk bcc harus dalam format bitcode LLVM 3.2 dan bcc harus kompatibel dengan aplikasi (lama) yang sudah ada.
  • Namun, meta-data di .bc bisa berubah (mungkin ada fungsi runtime baru, misalnya, penyetel alokasi ∓ pengambil, fungsi matematika, dll.). Sebagian dari fungsi runtime berada di libclcore.bc , sebagian lagi berada di LibRSDriver atau vendor yang setara.
  • Fungsi runtime baru atau perubahan metadata yang dapat mengganggu memerlukan penambahan level API bitcode. Karena driver vendor tidak dapat menggunakannya, versi HAL juga harus ditingkatkan.
  • Vendor mungkin memiliki kompilernya sendiri, namun kesimpulan/persyaratan untuk bcc juga berlaku untuk kompiler tersebut.
Tautan
  • .o yang dikompilasi akan dihubungkan dengan driver vendor, misalnya libRSDriver_foo.so , dan libcompiler_rt.so . Jalur CPU akan terhubung dengan libRSDriver.so .
  • Jika .o memerlukan API runtime baru dari libRSDriver_foo , driver vendor harus diperbarui untuk mendukungnya.
  • Vendor tertentu mungkin memiliki linkernya sendiri, namun argumen untuk ld.mc juga berlaku untuk mereka.
Memuat
  • libRSCpuRef memuat objek bersama. Jika ada perubahan pada antarmuka ini, diperlukan peningkatan versi HAL.
  • Vendor akan mengandalkan libRSCpuRef untuk memuat objek bersama, atau mengimplementasikannya sendiri.

Selain HAL, API runtime dan simbol yang diekspor juga merupakan antarmuka. Tidak ada antarmuka yang berubah sejak Android 7.0 (API 24) dan tidak ada rencana untuk segera mengubahnya di Android 8.0 dan seterusnya. Namun, jika antarmuka berubah, versi HAL juga akan bertambah.

Implementasi vendor

Android 8.0 dan lebih tinggi memerlukan beberapa perubahan driver GPU agar driver GPU berfungsi dengan benar.

Modul pengemudi

  • Modul driver tidak boleh bergantung pada perpustakaan sistem apa pun yang tidak ada dalam daftar .
  • Pengemudi harus menyediakan android.hardware.renderscript@1.0-impl_{NAME} miliknya sendiri, atau mendeklarasikan implementasi default android.hardware.renderscript@1.0-impl sebagai ketergantungannya.
  • Implementasi CPU libRSDriver.so adalah contoh bagus tentang cara menghapus dependensi non-VNDK-SP.

Kompiler bitcode

Anda dapat mengkompilasi bitcode RenderScript untuk driver vendor dengan dua cara:

  1. Panggil kompiler RenderScript khusus vendor di /vendor/bin/ (metode kompilasi GPU yang lebih disukai). Mirip dengan modul driver lainnya, biner kompiler vendor tidak dapat bergantung pada pustaka sistem apa pun yang tidak ada dalam daftar lib RenderScript yang tersedia untuk vendor .
  2. Panggil sistem bcc: /system/bin/bcc dengan bcc plugin yang disediakan vendor; plugin ini tidak dapat bergantung pada pustaka sistem apa pun yang tidak ada dalam daftar lib RenderScript yang tersedia untuk vendor .

Jika bcc plugin perlu mengganggu kompilasi CPU dan ketergantungannya pada libLLVM.so tidak dapat dihapus dengan mudah, vendor harus menyalin bcc (dan semua dependensi non-LL-NDK, termasuk libLLVM.so , libbcc.so ) ke dalam /vendor .

Selain itu, vendor perlu melakukan perubahan berikut:

Gambar 8. Perubahan pada driver vendor
  1. Salin libclcore.bc ke partisi /vendor . Hal ini memastikan libclcore.bc , libLLVM.so , dan libbcc.so sinkron.
  2. Ubah jalur ke bcc yang dapat dieksekusi dengan mengatur RsdCpuScriptImpl::BCC_EXE_PATH dari implementasi RS HAL.

kebijakan SELinux

Kebijakan SELinux mempengaruhi driver dan kompiler yang dapat dieksekusi. Semua modul driver harus diberi label same_process_hal_file di file_contexts perangkat. Misalnya:

/vendor/lib(64)?/libRSDriver_EXAMPLE\.so     u:object_r:same_process_hal_file:s0

Kompiler yang dapat dieksekusi harus dapat dipanggil oleh proses aplikasi, seperti halnya salinan bcc vendor ( /vendor/bin/bcc ). Misalnya:

device/vendor_foo/device_bar/sepolicy/file_contexts:
/vendor/bin/bcc                    u:object_r:same_process_hal_file:s0

Perangkat lama

Perangkat lawas adalah perangkat yang memenuhi ketentuan berikut:

  1. PRODUCT_SHIPPING_API_LEVEL lebih rendah dari 26.
  2. product_FULL_TREBLE_OVERRIDE tidak ditentukan.

Untuk perangkat lama, pembatasan tidak diterapkan saat mengupgrade ke Android 8.0 dan lebih tinggi, artinya driver dapat terus terhubung ke perpustakaan di /system/lib[64] . Namun, karena perubahan arsitektur terkait OVERRIDE_RS_DRIVER , android.hardware.renderscript@1.0-impl harus diinstal ke partisi /vendor ; kegagalan melakukan hal ini akan memaksa waktu proses RenderScript mundur ke jalur CPU.

Untuk informasi tentang alasan penghentian Renderscript, lihat Blog Pengembang Android: Komputasi GPU Android ke Depan . Informasi sumber daya untuk penghentian ini mencakup hal berikut: