RenderScript

RenderScript adalah framework untuk menjalankan tugas-tugas yang intensif komputasi dengan performa tinggi di Android. Solusi ini dirancang untuk digunakan dengan komputasi paralel data, meskipun workload serial juga dapat memanfaatkannya. Runtime RenderScript menyejajarkan pekerjaan di seluruh prosesor yang tersedia di perangkat, seperti CPU dan GPU multi-core, sehingga developer dapat berfokus pada mengekspresikan algoritma, bukan menjadwalkan tugas. RenderScript sangat berguna untuk aplikasi yang melakukan pemrosesan gambar, fotografi komputasi, atau computer vision.

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

Gambar 1. Kode vendor yang tertaut ke library internal.

Perbedaan dari RenderScript di Android 7.x dan yang lebih lama mencakup:

  • Dua instance library internal RenderScript dalam suatu proses. Satu set adalah untuk jalur penggantian CPU dan berasal langsung dari /system/lib; set lainnya adalah untuk jalur GPU dan berasal dari /system/lib/vndk-sp.
  • Library internal RS di /system/lib dibuat sebagai bagian dari platform dan diperbarui saat system.img diupgrade. Namun, library di /system/lib/vndk-sp dibuat untuk vendor dan tidak diupdate saat system.img diupgrade (meskipun dapat diupdate untuk perbaikan keamanan, ABI-nya tetap sama).
  • Kode vendor (RS HAL, driver RS, dan bcc plugin) ditautkan ke library internal RenderScript yang terletak di /system/lib/vndk-sp. Library ini tidak dapat ditautkan ke lib di /system/lib karena lib dalam direktori tersebut dibuat untuk platform, sehingga mungkin tidak kompatibel dengan kode vendor (artinya, simbol dapat dihapus). Melakukan hal tersebut akan membuat OTA khusus framework tidak mungkin dilakukan.

Desain

Bagian berikut menjelaskan desain RenderScript di Android 8.0 dan yang lebih tinggi.

Library RenderScript yang tersedia untuk vendor

Bagian ini mencantumkan lib RenderScript (dikenal sebagai Vendor NDK untuk HAL Same-Process atau VNDK-SP) yang tersedia untuk kode vendor dan yang dapat ditautkan. File ini juga menjelaskan library tambahan yang tidak terkait dengan RenderScript, tetapi juga disediakan untuk kode vendor.

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

Library RenderScript Library 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 penaut

Batasan penautan yang mencegah library yang tidak ada di VNDK-SP digunakan oleh kode vendor diterapkan saat runtime menggunakan namespace penaut. (Untuk mengetahui detailnya, lihat presentasi Desain VNDK.)

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

Selain itu, namespace rs memungkinkan lebih banyak lib daripada yang disediakan oleh namespace lainnya. libmediandk.so dan libft2.so diekspos ke namespace rs karena libRS_internal.so memiliki dependensi internal ke library ini.

Gambar 2. Konfigurasi namespace untuk penaut.

Memuat driver

Jalur penggantian CPU

Bergantung pada keberadaan bit RS_CONTEXT_LOW_LATENCY saat membuat konteks RS, jalur CPU atau GPU akan dipilih. Saat jalur CPU dipilih, libRS_internal.so (implementasi utama framework RS) langsung dlopen dari namespace penaut default tempat versi platform library RS disediakan.

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

Gambar 3. 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 dalam namespace penaut yang berbeda yang disebut sphal. RS HAL kemudian dlopen libRS_internal.so dalam namespace penaut lain yang disebut rs.

Vendor dapat menyediakan driver RS-nya sendiri dengan menyetel tanda waktu build OVERRIDE_RS_DRIVER, yang disematkan ke dalam implementasi RS HAL (hardware/interfaces/renderscript/1.0/default/Context.cpp). Nama driver ini kemudian di-dlopen untuk konteks RS bagi jalur GPU.

Pembuatan objek RsContext didelegasikan ke implementasi HAL RS. HAL memanggil kembali framework RS menggunakan fungsi rsContextCreateVendor() dengan nama driver yang akan digunakan sebagai argumen. Framework RS kemudian memuat driver yang ditentukan saat RsContext diinisialisasi. Dalam hal ini, library driver dimuat ke namespace rs karena objek RsContext dibuat di dalam namespace rs dan /vendor/lib berada di jalur penelusuran namespace.

Gambar 4. Jalur penggantian GPU.

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

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

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

Baris ini menentukan bahwa penaut dinamis harus memuat libRS_internal.so dari namespace rs saat lib tidak dapat ditemukan/dimuat dari namespace sphal (yang selalu terjadi karena namespace sphal tidak menelusuri /system/lib/vndk-sp tempat 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 library yang disediakan vendor yang dimuat ke dalam compiler bcc. Karena bcc adalah proses sistem di direktori /system/bin, library bcc plugin dapat dianggap sebagai SP-HAL (yaitu, HAL vendor yang dapat langsung dimuat ke dalam proses sistem tanpa di-binder). Sebagai SP-HAL, library bcc-plugin:

  • Tidak dapat menautkan ke library khusus framework seperti libLLVM.so.
  • Hanya dapat ditautkan ke library VNDK-SP yang tersedia untuk vendor.

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

Gambar 5. Memuat plugin bcc, Android 7.x dan yang lebih lama.



Gambar 6. Memuat plugin bcc, Android 8.0 dan yang lebih tinggi.

Telusuri jalur untuk ld.mc

Saat mengeksekusi ld.mc, beberapa library runtime RS diberikan sebagai input ke penaut. Bitcode RS dari aplikasi ditautkan ke library runtime dan saat bitcode yang dikonversi dimuat ke dalam proses aplikasi, library runtime akan ditautkan lagi secara dinamis dari bitcode yang dikonversi.

Library runtime meliputi:

  • libcompiler_rt.so
  • libm.so
  • libc.so
  • Pengemudi RS (libRSDriver.so atau OVERRIDE_RS_DRIVER)

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

Untuk melakukannya, framework RS menggunakan jalur penelusuran yang berbeda untuk library runtime saat menjalankan ld.mc, bergantung pada apakah framework RS itu sendiri dimuat dari /system/lib atau dari /system/lib/vndk-sp. Hal ini dapat ditentukan dengan membaca alamat simbol arbitrer dari lib framework RS dan menggunakan dladdr() untuk mendapatkan jalur file yang dipetakan ke alamat.

Kebijakan SELinux

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

  • vendor_file harus berupa label default untuk semua file dalam partisi vendor. Kebijakan platform mewajibkan hal ini untuk mengakses implementasi HAL passthrough.
  • Semua exec_types baru yang ditambahkan di partisi vendor melalui SEPolicy vendor harus memiliki atribut vendor_file_type. Hal ini diterapkan melalui neverallows.
  • Untuk menghindari konflik dengan update platform/framework mendatang, hindari pemberian label pada file selain exec_types di partisi vendor.
  • Semua dependensi library untuk HAL proses yang sama yang diidentifikasi AOSP harus diberi label sebagai same_process_hal_file.

Untuk mengetahui detail tentang kebijakan SELinux, lihat Security-Enhanced Linux di Android.

Kompatibilitas ABI untuk bitcode

Jika tidak ada API baru yang ditambahkan, yang berarti tidak ada peningkatan versi HAL, framework RS akan terus menggunakan driver GPU (HAL 1.0) yang ada.

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

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

Pemakaian bitcode RenderScript terjadi dalam tiga tahap:

Stage Detail
Kompilasi
  • Bitcode input (.bc) untuk bcc harus dalam format bitcode LLVM 3.2 dan bcc harus kompatibel mundur dengan aplikasi (lama) yang ada.
  • Namun, metadata dalam .bc dapat berubah (mungkin ada fungsi runtime baru, misalnya, Penyetel alokasi ∓ pengambil, fungsi matematika, dll.). Sebagian fungsi runtime berada di libclcore.bc, sebagian lagi berada di LibRSDriver atau vendor yang setara.
  • Fungsi runtime baru atau perubahan metadata yang rusak memerlukan peningkatan level API bitcode. Karena driver vendor tidak akan dapat memakainya, versi HAL juga harus ditingkatkan.
  • Vendor mungkin memiliki compiler mereka sendiri, tetapi kesimpulan/persyaratan untuk bcc juga berlaku untuk compiler tersebut.
Link
  • File .o yang dikompilasi akan ditautkan dengan driver vendor, misalnya, libRSDriver_foo.so dan libcompiler_rt.so. Jalur CPU akan tertaut dengan libRSDriver.so.
  • Jika .o memerlukan API runtime baru dari libRSDriver_foo, driver vendor harus diupdate untuk mendukungnya.
  • Vendor tertentu mungkin memiliki penaut sendiri, tetapi argumen untuk ld.mc juga berlaku untuk mereka.
Pemuatan
  • libRSCpuRef memuat objek yang dibagikan. Jika ada perubahan pada antarmuka ini, peningkatan versi HAL diperlukan.
  • Vendor akan mengandalkan libRSCpuRef untuk memuat objek bersama, atau menerapkan objek mereka 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 langsung untuk mengubahnya di Android 8.0 dan seterusnya. Namun, jika antarmuka berubah, versi HAL juga akan bertambah.

Implementasi vendor

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

Modul driver

  • Modul driver tidak boleh bergantung pada library sistem yang tidak ada dalam daftar.
  • Driver harus menyediakan android.hardware.renderscript@1.0-impl_{NAME}-nya sendiri, atau mendeklarasikan implementasi default android.hardware.renderscript@1.0-impl sebagai dependensinya.
  • Implementasi CPU libRSDriver.so adalah contoh yang baik tentang cara menghapus dependensi non-VNDK-SP.

Compiler bitcode

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

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

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

Selain itu, vendor perlu melakukan perubahan berikut:

Gambar 7. Perubahan pada driver vendor.

  1. Salin libclcore.bc ke partisi /vendor. Tindakan ini memastikan libclcore.bc, libLLVM.so, dan libbcc.so disinkronkan.
  2. Ubah jalur ke bcc yang dapat dieksekusi dengan menetapkan RsdCpuScriptImpl::BCC_EXE_PATH dari implementasi HAL RS.

Kebijakan SELinux

Kebijakan SELinux memengaruhi driver dan file yang dapat dieksekusi compiler. Semua modul driver harus diberi label same_process_hal_file di file_contexts perangkat. Contoh:

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

Compiler yang dapat dieksekusi harus dapat dipanggil oleh proses aplikasi, seperti 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 lama adalah perangkat yang memenuhi kondisi 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 yang lebih tinggi, yang berarti driver dapat terus menautkan ke library di /system/lib[64]. Namun, karena perubahan arsitektur yang terkait dengan OVERRIDE_RS_DRIVER, android.hardware.renderscript@1.0-impl harus diinstal ke partisi /vendor; jika tidak, runtime RenderScript akan di-fallback ke jalur CPU.

Untuk mengetahui informasi tentang motivasi penghentian Renderscript, lihat Blog Developer Android: Komputasi GPU Android ke Depan. Informasi resource untuk penghentian ini mencakup hal berikut: