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 bermanfaat. Runtime RenderScript memparalelkan pekerjaan di seluruh prosesor yang tersedia di perangkat, seperti CPU dan GPU multi-inti, memungkinkan pengembang untuk fokus pada ekspresi algoritme 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 menautkan ke lib internal

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

  • Dua instance lib internal RenderScript dalam suatu proses. Satu set untuk jalur fallback CPU dan langsung dari /system/lib ; set lainnya adalah untuk jalur GPU dan dari /system/lib/vndk-sp .
  • Lib internal RS di /system/lib dibangun sebagai bagian dari platform dan diperbarui saat system.img ditingkatkan. Namun, lib di /system/lib/vndk-sp dibuat untuk vendor dan tidak diperbarui saat system.img ditingkatkan (meskipun dapat diperbarui untuk perbaikan keamanan, ABI mereka 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 menautkan ke lib di /system/lib karena lib dalam direktori tersebut dibuat untuk platform dan dengan demikian mungkin tidak kompatibel dengan kode vendor (yaitu, simbol dapat dihapus). Melakukan hal itu akan membuat OTA kerangka-saja menjadi tidak mungkin.

Desain

Bagian berikut merinci desain RenderScript di Android 8.0 dan yang 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 yang dapat ditautkan. Ini juga merinci pustaka tambahan yang tidak terkait dengan RenderScript tetapi juga disediakan untuk kode vendor.

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

RenderScript Lib 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 penautan

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

Pada perangkat yang menjalankan Android 8.0 dan lebih tinggi, semua Same-Process HAL (SP-HAL) kecuali RenderScript dimuat di dalam linker namespace sphal . RenderScript dimuat ke dalam namespace khusus RenderScript rs , lokasi yang memungkinkan penegakan 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 memungkinkan lebih banyak lib daripada yang disediakan oleh namespace lain. libmediandk.so dan libft2.so diekspos ke rs namespace karena libRS_internal.so memiliki ketergantungan internal ke pustaka ini.

Gambar 2. Konfigurasi namespace untuk linker

Memuat driver

Jalur mundur 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 kerja RS) langsung dlopen dari namespace tautan default tempat versi platform lib RS disediakan.

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

Gambar 4. Jalur mundur 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 linker berbeda yang disebut sphal . RS HAL kemudian dlopen s libRS_internal.so di namespace linker lain yang disebut rs .

Vendor dapat menyediakan driver RS ​​mereka sendiri dengan menyetel flag waktu pembuatan 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 untuk jalur GPU.

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

Gambar 5. Jalur mundur GPU

Saat bertransisi dari namespace default ke namespace sphal , libhidltransport.so menggunakan fungsi android_load_sphal_library() untuk secara eksplisit memerintahkan dynamic linker untuk memuat library -impl.so dari namespace sphal .

Saat transisi 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 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 membuat transisi namespace.

Memuat plugin bcc

bcc plugin adalah pustaka 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 terikat). Sebagai SP-HAL, perpustakaan bcc-plugin :

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

Pembatasan ini diberlakukan 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 dimuat langsung oleh bcc itu sendiri. Opsi ini mengaktifkan jalur khusus non-Android ke proyek LLVM open source.

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


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

Cari jalur untuk ld.mc

Saat menjalankan ld.mc , beberapa lib runtime RS diberikan sebagai input ke linker. Bitcode RS dari aplikasi ditautkan ke lib runtime dan ketika bitcode yang dikonversi dimuat ke dalam proses aplikasi, lib runtime ditautkan lagi 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 kerja RS menggunakan jalur pencarian yang berbeda untuk lib runtime saat menjalankan ld.mc , tergantung pada apakah kerangka kerja RS itu sendiri dimuat dari /system/lib atau dari /system/lib/vndk-sp . Ini dapat ditentukan dengan membaca alamat simbol arbitrer dari lib kerangka kerja RS dan menggunakan dladdr() untuk mendapatkan jalur file yang dipetakan ke alamat tersebut.

kebijakan SELinux

Sebagai akibat dari perubahan kebijakan SELinux di Android 8.0 dan yang lebih tinggi, Anda harus mengikuti aturan khusus (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 SEPolicy vendor harus memiliki atribut vendor_file_type . Ini diberlakukan melalui neverallows .
  • Untuk menghindari konflik dengan pembaruan platform/kerangka kerja di masa mendatang, hindari pelabelan file selain exec_types di partisi vendor .
  • Semua dependensi perpustakaan untuk HAL proses yang sama yang diidentifikasi oleh AOSP harus diberi label sebagai same_process_hal_file .

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

Kompatibilitas ABI untuk bitcode

Jika tidak ada API baru yang ditambahkan, yang berarti tidak ada peningkatan versi HAL, kerangka kerja 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 mundur ke CPU untuk API yang baru ditambahkan ini dan tetap menggunakan driver GPU (HAL 1.0) di tempat lain.

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

Mengkonsumsi bitcode RenderScript terjadi dalam tiga tahap:

Panggung rincian
Menyusun
  • Bitcode input (.bc) untuk bcc harus dalam format bitcode LLVM 3.2 dan bcc harus kompatibel dengan aplikasi (lawas) yang ada.
  • Namun, meta-data dalam .bc dapat 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 yang setara dengan vendor.
  • Fungsi runtime baru atau perubahan meta-data yang melanggar memerlukan peningkatan level API bitcode. Karena driver vendor tidak akan dapat menggunakannya, versi HAL juga harus ditingkatkan.
  • Vendor mungkin memiliki kompiler mereka sendiri, tetapi kesimpulan/persyaratan untuk bcc juga berlaku untuk kompiler tersebut.
Tautan
  • .o yang dikompilasi akan ditautkan 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 penautnya sendiri, tetapi argumen untuk ld.mc juga berlaku untuk mereka.
Memuat
  • libRSCpuRef memuat objek bersama. Jika ada perubahan pada antarmuka ini, diperlukan versi HAL bump.
  • Vendor akan bergantung pada 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 segera untuk 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 driver

  • Modul driver tidak boleh bergantung pada pustaka 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 dependensinya.
  • Implementasi CPU libRSDriver.so adalah contoh yang baik tentang cara menghapus dependensi non-VNDK-SP.

Kompiler kode bit

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

  1. Panggil kompiler RenderScript khusus vendor di /vendor/bin/ (metode kompilasi GPU yang 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. Aktifkan system 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 vendor 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 /vendor .

Selain itu, vendor perlu melakukan perubahan berikut:

Gambar 8. Perubahan pada driver vendor
  1. Salin libclcore.bc ke partisi /vendor . 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 memengaruhi driver dan kompiler yang dapat dieksekusi. Semua modul driver harus diberi label same_process_hal_file di file_contexts perangkat. Sebagai contoh:

/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 vendor bcc ( /vendor/bin/bcc ). Sebagai contoh:

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 lawas, pembatasan tidak diterapkan saat memutakhirkan ke Android 8.0 dan lebih tinggi, artinya driver dapat terus menautkan ke pustaka 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 ; gagal melakukannya memaksa mundur runtime RenderScript ke jalur CPU.

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