RenderScript

RenderScript adalah framework untuk menjalankan tugas yang intensif secara terkomputasi dengan performa tinggi di Android. Dirancang untuk digunakan dengan komputasi paralel data, meskipun beban kerja serial juga dapat berfungsi dengan baik. Runtime RenderScript menyejajarkan pekerjaan di seluruh prosesor yang tersedia di perangkat, seperti GPU dan CPU multi-core, sehingga memungkinkan developer fokus mengekspresikan algoritma, bukan menjadwalkan pekerjaan. RenderScript sangat berguna untuk aplikasi yang melakukan pemrosesan gambar, fotografi komputasional, 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 ditautkan ke library internal.

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

  • Dua instance library internal RenderScript dalam suatu proses. Satu set ditujukan untuk jalur penggantian CPU dan langsung dari /system/lib; set lainnya ditujukan untuk jalur GPU dan berasal dari /system/lib/vndk-sp.
  • Library internal RS di /system/lib dibuat sebagai bagian dari platform dan diupdate 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 dengan library internal RenderScript yang berada di /system/lib/vndk-sp. Mereka tidak dapat ditautkan dengan library di /system/lib karena library di direktori tersebut dibuat untuk platform dan dengan demikian mungkin tidak kompatibel dengan kode vendor (yaitu, simbol dapat dihapus). Jika demikian, OTA khusus framework tidak akan mungkin dilakukan.

Desain

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

Library RenderScript tersedia untuk vendor

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

Meskipun daftar library berikut mungkin berbeda di antara rilis Android, daftar ini tidak dapat diubah untuk rilis Android tertentu; untuk daftar library yang tersedia dan terbaru, lihat /system/etc/ld.config.txt.

RenderScript Libs 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 linker

Batasan penautan yang mencegah penggunaan library yang tidak ada di VNDK-SP oleh kode vendor diterapkan saat runtime menggunakan namespace linker. (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 linker sphal. RenderScript dimuat ke namespace khusus RenderScript rs, 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 lain tidak diizinkan memuat library dari partisi data).

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

Gambar 2. Konfigurasi namespace untuk linker.

Memuat {i>driver<i}

Jalur penggantian CPU

Bergantung pada keberadaan bit RS_CONTEXT_LOW_LATENCY saat membuat konteks RS, jalur CPU atau GPU akan dipilih. Jika jalur CPU dipilih, libRS_internal.so (implementasi utama framework RS) akan langsung di-dlopen dari namespace linker default tempat versi platform RS libs 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 namespace linker yang berbeda bernama sphal. HAL RS kemudian dlopens libRS_internal.so di namespace linker lain yang disebut rs.

Vendor dapat menyediakan driver RS mereka sendiri dengan menyetel tanda waktu build OVERRIDE_RS_DRIVER, yang disematkan ke penerapan HAL RS (hardware/interfaces/renderscript/1.0/default/Context.cpp). Nama driver ini kemudian di-dlopen untuk konteks RS untuk 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 dalam namespace rs karena objek RsContext dibuat di dalam namespace rs dan /vendor/lib ada di jalur penelusuran namespace.

Gambar 4. Jalur penggantian GPU.

Saat bertransisi dari namespace default ke namespace sphal, libhidltransport.so menggunakan fungsi android_load_sphal_library() untuk mengurutkan linker dinamis secara eksplisit agar 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 linker dinamis harus memuat libRS_internal.so dari namespace rs jika 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 dan dimuat ke dalam kompiler bcc. Karena bcc adalah proses sistem di direktori /system/bin, library bcc plugin dapat dianggap sebagai SP-HAL (yaitu, HAL vendor yang dapat dimuat langsung ke dalam proses sistem tanpa di-binderize). Sebagai SP-HAL, library bcc-plugin:

  • Tidak dapat menautkan ke library khusus framework seperti libLLVM.so.
  • Dapat ditautkan hanya dengan 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 yang tidak khusus untuk 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.

Menelusuri jalur untuk ld.mc

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

Lib runtime mencakup:

  • libcompiler_rt.so
  • libm.so
  • libc.so
  • Driver 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 mengeksekusi 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 library framework RS dan menggunakan dladdr() untuk mendapatkan jalur file yang dipetakan ke alamat.

Kebijakan SELinux

Sebagai hasil dari perubahan kebijakan SELinux di Android 8.0 dan yang lebih tinggi, Anda harus mengikuti aturan tertentu (diterapkan 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 mewajibkan hal ini untuk mengakses implementasi HAL teruskan.
  • 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 memberi label pada file selain exec_types di partisi vendor.
  • Semua dependensi library untuk HAL proses yang sama yang diidentifikasi AOSP harus diberi label same_process_hal_file.

Untuk mengetahui detail 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 kecil (HAL 1.1) yang tidak memengaruhi bitcode, framework harus melakukan penggantian 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 sebaiknya tidak memuat driver GPU yang disediakan vendor dan sebagai gantinya menggunakan jalur CPU atau Vulkan untuk akselerasi.

Penggunaan 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 yang ada (lama).
  • Namun, meta-data dalam .bc dapat berubah (mungkin ada fungsi runtime baru, misalnya, Penyetel & pengambil alokasi, fungsi matematika, dll.). Bagian dari fungsi runtime berada di libclcore.bc, sebagiannya berada di LibRSDriver atau yang setara dengan vendor.
  • Fungsi runtime baru atau perubahan meta-data yang merusak memerlukan peningkatan level API bitcode. Karena driver vendor tidak akan dapat menggunakannya, versi HAL juga harus di-upgrade.
  • Vendor mungkin memiliki compiler mereka sendiri, tetapi kesimpulan/persyaratan untuk bcc juga berlaku untuk compiler tersebut.
Link
  • .o yang dikompilasi akan ditautkan dengan driver vendor, misalnya, libRSDriver_foo.so, dan libcompiler_rt.so. Jalur CPU akan ditautkan dengan libRSDriver.so.
  • Jika .o memerlukan API runtime baru dari libRSDriver_foo, driver vendor harus diupdate untuk mendukungnya.
  • Vendor tertentu mungkin memiliki linker sendiri, tetapi argumen untuk ld.mc juga berlaku untuk mereka.
Muat
  • libRSCpuRef memuat objek bersama. Jika ada perubahan pada antarmuka ini, versi HAL perlu di-upgrade.
  • Vendor dapat mengandalkan libRSCpuRef untuk memuat objek bersama, atau menerapkan objek mereka sendiri.

Selain HAL, API runtime dan simbol yang diekspor juga merupakan antarmuka. Kedua antarmuka tidak berubah sejak Android 7.0 (API 24) dan tidak ada rencana langsung untuk mengubahnya di Android 8.0 dan yang lebih baru. 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 dapat berfungsi dengan benar.

Modul driver

  • Modul driver tidak boleh bergantung pada library sistem apa pun yang tidak ada dalam daftar.
  • Driver harus menyediakan android.hardware.renderscript@1.0-impl_{NAME}-nya sendiri, atau mendeklarasikan penerapan 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. Memanggil kompiler RenderScript khusus vendor di /vendor/bin/ (metode kompilasi GPU yang lebih disukai). Mirip dengan modul driver lainnya, biner compiler vendor tidak boleh 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 dihapus dengan mudah, 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. Hal ini memastikan libclcore.bc, libLLVM.so, dan libbcc.so disinkronkan.
  2. Ubah jalur ke file yang dapat dieksekusi bcc dengan menyetel RsdCpuScriptImpl::BCC_EXE_PATH dari implementasi RS HAL.

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

File yang dapat dieksekusi compiler 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, batasan tidak diterapkan saat mengupgrade ke Android 8.0 dan yang lebih tinggi, yang berarti driver dapat terus ditautkan ke library di /system/lib[64]. Namun, karena perubahan arsitektur terkait OVERRIDE_RS_DRIVER, android.hardware.renderscript@1.0-impl harus diinstal ke partisi /vendor; jika tidak, runtime RenderScript akan melakukan penggantian ke jalur CPU.

Untuk mengetahui informasi tentang motivasi penghentian penggunaan Renderscript, lihat Blog Android Developers: Android GPU Compute Going Forward. Informasi resource untuk penghentian penggunaan ini mencakup hal berikut: