Android berisi HIDL Hardware Abstraksi Layer (HAL) HIDL otomotif yang menyediakan pengambilan dan menampilkan citra di awal proses booting Android dan terus berfungsi untuk masa pakai sistem. HAL meliputi tumpukan sistem tampilan eksterior (EVS) dan biasanya digunakan untuk mendukung tampilan kaca tampilan kamera dan tampilan surround di kendaraan dengan Dalam Kendaraan berbasis Android Sistem infotainment (IVI). EVS juga memungkinkan fitur lanjutan untuk diimplementasikan pada aplikasi pengguna.
Android juga menyertakan driver penangkapan dan tampilan khusus EVS
antarmuka (di /hardware/interfaces/automotive/evs/1.0
). Meskipun
membangun aplikasi kamera belakang
di atas Android yang ada
layanan kamera dan tampilan, aplikasi seperti itu
mungkin akan terlambat dijalankan
proses booting Android. Menggunakan HAL khusus memungkinkan antarmuka yang disederhanakan
serta memperjelas hal yang perlu diterapkan oleh OEM untuk mendukung stack EVS.
Komponen sistem
EVS mencakup komponen sistem berikut:
![Sistem EVS
diagram komponen](https://source.android.com/static/docs/automotive/images/vhal_evs_components.png?authuser=0&hl=id)
aplikasi EVS
Contoh aplikasi EVS C++
(/packages/services/Car/evs/app
) berfungsi sebagai referensi
terlepas dari implementasi layanan. Aplikasi ini bertanggung jawab untuk meminta {i>frame<i} video dari
Pengelola EVS dan mengirim bingkai yang sudah selesai untuk ditampilkan kembali ke Pengelola EVS.
Diharapkan dapat dimulai oleh init segera setelah EVS dan Layanan Mobil tersedia,
yang ditargetkan dalam waktu 2 (dua) detik setelah dinyalakan. OEM dapat memodifikasi atau mengganti EVS
sesuai keinginan.
Pengelola EVS
Pengelola EVS (/packages/services/Car/evs/manager
) memberikan
fondasi yang diperlukan aplikasi EVS
untuk mengimplementasikan apa pun mulai
tampilan kamera belakang yang sederhana menjadi rendering multi-kamera 6DOF. Antarmukanya
disajikan melalui HIDL dan dibuat untuk menerima beberapa klien serentak.
Aplikasi dan layanan lain (khususnya Layanan Mobil) dapat mengkueri EVS
Status pengelola untuk mengetahui kapan sistem EVS aktif.
Antarmuka EVS HIDL
Sistem EVS, baik kamera maupun elemen layar, didefinisikan dalam
android.hardware.automotive.evs
. Contoh implementasi
yang melatih antarmuka (menghasilkan image pengujian sintetis dan memvalidasi
gambar untuk perjalanan pulang pergi) disediakan di
/hardware/interfaces/automotive/evs/1.0/default
.
OEM bertanggung jawab untuk menerapkan API yang dinyatakan oleh file .hal
di /hardware/interfaces/automotive/evs
. Implementasi tersebut adalah
bertanggung jawab untuk mengkonfigurasi dan
mengumpulkan data dari kamera fisik dan
menyampaikannya melalui {i>buffer<i} memori
bersama yang dapat dikenali oleh Gralloc. Layar
implementasi bertanggung jawab untuk
menyediakan {i>buffer <i}memori bersama
yang dapat diisi oleh aplikasi (biasanya dengan rendering EGL) dan menyajikan
{i>frame <i}yang sudah selesai dan lebih diutamakan
dari hal lain yang mungkin ingin muncul di
tampilan fisik. Implementasi vendor dari antarmuka EVS dapat disimpan
di bawah /vendor/… /device/…
atau hardware/…
(mis.,
/hardware/[vendor]/[platform]/evs
).
Driver kernel
Perangkat yang mendukung stack EVS memerlukan driver kernel. Daripada fokus pada
menciptakan {i>driver<i} baru, OEM memiliki opsi untuk mendukung fitur yang
{i>driver<i} kamera atau perangkat
keras layar yang ada. Menggunakan kembali {i>driver<i} bisa
menguntungkan, terutama untuk {i>driver<i} tampilan di mana presentasi gambar mungkin
memerlukan koordinasi dengan
thread aktif lainnya. Android 8.0 menyertakan berbasis v4l2
contoh driver (di packages/services/Car/evs/sampleDriver
) yang
tergantung pada {i>kernel<i} untuk dukungan v4l2 dan pada SurfaceFlinger untuk menyajikan
gambar output.
Deskripsi antarmuka hardware EVS
Bagian ini menjelaskan HAL. Vendor diharapkan untuk menyediakan implementasi API ini yang telah diadaptasikan untuk perangkat kerasnya.
IEvsEnumerator
Objek ini bertanggung jawab untuk menghitung hardware EVS yang tersedia dalam (satu atau beberapa kamera dan satu perangkat layar).
getCameraList() generates (vec<CameraDesc> cameras);
Menampilkan vektor yang berisi deskripsi untuk semua kamera dalam sistem. Penting
mengasumsikan bahwa set kamera telah diperbaiki dan
dapat diketahui pada saat {i>booting<i}. Untuk mengetahui detail tentang
deskripsi kamera, lihat CameraDesc
.
openCamera(string camera_id) generates (IEvsCamera camera);
Memperoleh objek antarmuka yang digunakan untuk berinteraksi dengan kamera tertentu
yang diidentifikasi oleh string camera_id unik. Menampilkan NULL saat gagal.
Upaya untuk membuka kembali kamera yang sudah terbuka tidak dapat gagal. Untuk menghindari ras
kondisi yang terkait dengan startup dan penonaktifan aplikasi, membuka kembali kamera
harus mematikan instance sebelumnya sehingga permintaan baru dapat dipenuhi. J
instance kamera yang telah di-preempt dengan cara ini harus
negara bagian, menunggu pemusnahan akhir dan menanggapi setiap permintaan untuk mempengaruhi
status kamera dengan kode pengembalian OWNERSHIP_LOST
.
closeCamera(IEvsCamera camera);
Merilis antarmuka IEvsCamera (dan merupakan kebalikan dari
openCamera()
panggilan). Streaming video kamera harus
dihentikan dengan memanggil stopVideoStream()
sebelum memanggil closeCamera
.
openDisplay() generates (IEvsDisplay display);
Memperoleh objek antarmuka yang digunakan untuk berinteraksi secara eksklusif dengan
Layar EVS. Hanya satu klien yang dapat memegang instance fungsional IEvsDisplay di
baik. Mirip dengan perilaku terbuka agresif yang dijelaskan dalam openCamera
,
objek IEvsDisplay baru dapat dibuat kapan saja dan menonaktifkan semua objek
instance Compute Engine. Instance yang tidak valid akan terus ada dan merespons panggilan fungsi
dari pemiliknya, tetapi tidak boleh
melakukan operasi mutasi ketika sudah mati. Pada akhirnya,
aplikasi klien diharapkan melihat error OWNERSHIP_LOST
mengembalikan kode dan menutup dan
melepaskan antarmuka yang tidak aktif.
closeDisplay(IEvsDisplay display);
Merilis antarmuka IEvsDisplay (dan merupakan kebalikan dari
openDisplay()
panggilan). Penyanggaan luar biasa yang diterima dengan
Panggilan getTargetBuffer()
harus ditampilkan ke layar sebelum
menutup layar.
getDisplayState() generates (DisplayState state);
Mendapatkan status tampilan saat ini. Implementasi HAL harus melaporkan
status saat ini, yang mungkin berbeda dari status yang terakhir diminta.
Logika yang bertanggung jawab untuk mengubah status tampilan harus ada di atas perangkat
sehingga tidak diinginkan bagi implementasi HAL untuk berubah secara spontan
status tampilan. Jika saat ini layar tidak dipegang oleh klien mana pun (melalui panggilan ke
openDisplay), fungsi ini akan menampilkan NOT_OPEN
. Jika tidak, akan
melaporkan status Layar EVS saat ini (lihat
IEvsDisplay API).
struct CameraDesc { string camera_id; int32 vendor_flags; // Opaque value }
camera_id
. String yang mengidentifikasi kamera tertentu secara unik. Bisa berupa nama perangkat kernel atau nama perangkat, seperti kaca spion. Nilai untuk string ini dipilih oleh implementasi HAL dan digunakan secara buram oleh stack di atas.vendor_flags
. Metode untuk meneruskan kamera khusus buram dari pengemudi ke aplikasi EVS kustom. Dilewati tidak ditafsirkan dari pengemudi hingga ke aplikasi EVS, yang dapat diabaikan anotasi.
Kamera IEv
Objek ini mewakili satu kamera dan merupakan antarmuka utama untuk mengambil gambar.
getCameraInfo() generates (CameraDesc info);
Menampilkan CameraDesc
kamera ini.
setMaxFramesInFlight(int32 bufferCount) generates (EvsResult result);
Menentukan kedalaman rantai buffer yang diminta untuk didukung kamera. Hingga
{i>frame<i} sebanyak ini dapat dipegang
secara bersamaan oleh klien IEvsCamera. Jika ini
banyak {i>frame<i} yang telah dikirim ke
penerima tanpa dikembalikan oleh
doneWithFrame
, streaming melewati frame hingga buffer ditampilkan
untuk digunakan kembali. Panggilan semacam ini dapat dilakukan kapan saja, meskipun streaming sedang berlangsung
sudah berjalan, dalam hal ini buffer harus ditambahkan atau dihapus dari rantai
sebagaimana mestinya. Jika tidak ada panggilan yang dilakukan ke titik entri ini, IEvsCamera mendukung
setidaknya satu {i>frame<i} secara {i>default<i}; dengan lebih dapat diterima.
Jika bufferCount yang diminta tidak dapat diakomodasi, fungsi tersebut akan menampilkan
BUFFER_NOT_AVAILABLE
atau kode error lain yang relevan. Dalam kasus ini,
sistem terus beroperasi dengan nilai yang telah ditetapkan sebelumnya.
startVideoStream(IEvsCameraStream receiver) generates (EvsResult result);
Meminta pengiriman frame kamera EVS dari kamera ini. IEvsCameraStream
mulai menerima panggilan berkala dengan bingkai gambar baru hingga
stopVideoStream()
dipanggil. Frame harus mulai dikirim
dalam 500 md dari panggilan startVideoStream
dan setelah dimulai, harus
dihasilkan minimal 10 FPS. Waktu yang diperlukan untuk memulai streaming video
efektif dihitung berdasarkan persyaratan waktu startup kamera kaca. Jika
streaming belum dimulai, kode error harus ditampilkan; jika tidak, OK akan
ditampilkan.
oneway doneWithFrame(BufferDesc buffer);
Menampilkan frame yang dikirimkan oleh ke IEvsCameraStream. Setelah selesai
memakai {i>frame<i} yang dikirim ke antarmuka
IEvsCameraStream, {i>frame<i} itu harus
dikembalikan ke IEvsCamera untuk digunakan kembali. Sebuah {i>buffer<i} dalam jumlah yang
kecil dan terbatas
tersedia (mungkin hanya sekecil satu), dan jika pasokan habis, tidak ada
{i>frame<i} dikirimkan sampai {i>buffer<i}
dikembalikan, yang berpotensi mengakibatkan
frame yang dilewati (buffer dengan handle null menunjukkan akhir streaming dan
tidak perlu ditampilkan melalui fungsi ini). Menampilkan OK jika berhasil, atau
kode error yang sesuai mungkin menyertakan INVALID_ARG
atau
BUFFER_NOT_AVAILABLE
.
stopVideoStream();
Menghentikan pengiriman frame kamera EVS. Karena pengiriman bersifat asinkron,
frame mungkin terus masuk selama beberapa waktu setelah panggilan ini kembali. Setiap frame
harus dikembalikan hingga penutupan aliran diberi sinyal ke
IEvsCameraStream. Anda dapat memanggil stopVideoStream
di streaming
yang telah dihentikan atau tidak pernah dimulai, dalam hal ini akan diabaikan.
getExtendedInfo(int32 opaqueIdentifier) generates (int32 value);
Meminta informasi khusus pengemudi dari implementasi HAL. Nilai-nilai
diizinkan untuk opaqueIdentifier
bersifat khusus driver, tetapi tidak ada nilai
dilewati, dapat membuat
pengemudi {i>driver<i} tidak bekerja. Pengemudi harus mengembalikan 0 untuk
opaqueIdentifier
.
setExtendedInfo(int32 opaqueIdentifier, int32 opaqueValue) generates (EvsResult result);
Mengirim nilai khusus driver ke implementasi HAL. Ekstensi ini
disediakan hanya untuk memfasilitasi perluasan khusus kendaraan dan tanpa HAL
harus membutuhkan panggilan ini agar berfungsi dalam status default. Jika
pengemudi mengenali dan menerima nilai, OK harus dikembalikan; sebaliknya
INVALID_ARG
atau kode error representatif lainnya akan ditampilkan.
struct BufferDesc { uint32 width; // Units of pixels uint32 height; // Units of pixels uint32 stride; // Units of pixels uint32 pixelSize; // Size of single pixel in bytes uint32 format; // May contain values from android_pixel_format_t uint32 usage; // May contain values from Gralloc.h uint32 bufferId; // Opaque value handle memHandle; // gralloc memory buffer handle }
Menjelaskan image yang diteruskan melalui API. {i>Drive <i}HAL bertanggung jawab untuk
mengisi struktur ini untuk menjelaskan {i>buffer <i}gambar dan klien HAL
harus memperlakukan struktur
ini sebagai hanya-baca. Kolom berisi informasi yang cukup
untuk memungkinkan klien merekonstruksi objek ANativeWindowBuffer
,
mungkin diperlukan untuk menggunakan gambar dengan EGL dengan
ekstensi eglCreateImageKHR()
.
width
. Lebar piksel gambar yang ditampilkan.height
. Tinggi gambar yang ditampilkan dalam piksel.stride
. Jumlah {i>pixel<i} yang ditempati oleh setiap baris dalam memori, memperhitungkan setiap pelapis untuk penyelarasan baris. Dinyatakan dalam piksel agar sesuai konvensi yang diadopsi oleh gralloc untuk deskripsi {i>buffer-nya<i}.pixelSize
. Jumlah byte yang ditempati oleh setiap {i>pixel<i} individu, memungkinkan komputasi ukuran dalam byte yang diperlukan untuk berpindah antar baris dalam gambar (stride
dalam byte =stride
dalam piksel *pixelSize
).format
. Format piksel yang digunakan oleh gambar. Format yang disediakan harus kompatibel dengan implementasi OpenGL platform. Untuk lulus pengujian kompatibilitas,HAL_PIXEL_FORMAT_YCRCB_420_SP
harus disarankan untuk penggunaan kamera, danRGBA
atauBGRA
harus lebih disukai untuk tampilan.usage
. Tanda penggunaan yang ditetapkan oleh implementasi HAL. Klien HAL diharapkan untuk meneruskan teks yang tidak dimodifikasi ini (untuk detailnya, lihat tanda terkaitGralloc.h
).bufferId
. Nilai unik yang ditentukan oleh implementasi HAL untuk memungkinkan buffer dikenali setelah perjalanan bolak-balik melalui HAL API. Tujuan yang disimpan di isian ini dapat dipilih secara arbitrer oleh implementasi HAL.memHandle
. Penanganan untuk buffer memori yang mendasarinya berisi data gambar. Implementasi HAL mungkin memilih untuk menyimpan Gralloc buffer di sini.
IEvsCameraStream
Klien menerapkan antarmuka ini untuk menerima frame video asinkron pengiriman barang.
deliverFrame(BufferDesc buffer);
Menerima panggilan dari HAL setiap kali frame video siap untuk diperiksa.
Tuas buffer yang diterima oleh metode ini harus ditampilkan melalui panggilan ke
IEvsCamera::doneWithFrame()
. Saat streaming video dihentikan dengan
panggilan ke IEvsCamera::stopVideoStream()
, callback ini mungkin berlanjut
ketika pipeline terkuras. Setiap frame tetap harus ditampilkan; saat frame terakhir
dalam aliran data telah dikirimkan, bufferHandle
NULL dikirimkan,
menandakan akhir streaming dan tidak ada lagi pengiriman {i>frame<i} yang dilakukan. NULL
bufferHandle
sendiri tidak perlu dikirim kembali dengan
doneWithFrame()
, tetapi semua nama sebutan channel lainnya harus ditampilkan
Meskipun format buffer eksklusif secara teknis dimungkinkan, pengujian memerlukan buffer dalam salah satu dari empat format yang didukung: NV21 (YCrCb 4:2:0 Semi-Planar), YV12 (YCrCb 4:2:0 Planar), YUYV (YCrCb 4:2:2 Interleaved), RGBA (32 bit R:G:B:x), BGRA (32 bit B:G:R:x). Format yang dipilih harus valid Sumber tekstur GL pada implementasi GLES platform.
Aplikasi tidak boleh bergantung pada korespondensi apa pun
antara kolom bufferId
dan memHandle
di
BufferDesc
. Nilai bufferId
pada dasarnya bersifat pribadi untuk implementasi driver HAL, dan dapat menggunakan (dan menggunakannya kembali)
mereka sesuai keinginan.
Tampilan Ivs
Objek ini mewakili tampilan Evs, mengontrol status tampilan, dan menangani presentasi gambar yang sebenarnya.
getDisplayInfo() generates (DisplayDesc info);
Menampilkan informasi dasar tentang layar EVS yang disediakan sistem (lihat DisplayDesc).
setDisplayState(DisplayState state) generates (EvsResult result);
Menetapkan status tampilan. Klien dapat menetapkan status tampilan untuk menyatakan keadaan yang diinginkan, dan implementasi HAL harus menerima permintaan untuk status apa pun sementara dalam keadaan lain, meskipun responsnya mungkin mengabaikan permintaan.
Setelah diinisialisasi, tampilan ditetapkan untuk dimulai di
Status NOT_VISIBLE
, yang setelahnya klien diharapkan akan meminta
status VISIBLE_ON_NEXT_FRAME
dan mulai menyediakan video. Jika
gambar tidak lagi diperlukan, klien diharapkan untuk meminta
Status NOT_VISIBLE
setelah meneruskan frame video terakhir.
Izin ini berlaku bagi negara bagian mana pun yang dapat diminta kapan saja. Jika layar
sudah terlihat, harus tetap terlihat jika diatur ke
VISIBLE_ON_NEXT_FRAME
. Selalu menampilkan OK kecuali jika status yang diminta
adalah nilai enum yang tidak dikenal, dalam hal ini INVALID_ARG
adalah
dikembalikan.
getDisplayState() generates (DisplayState state);
Mendapatkan status tampilan. Implementasi HAL harus melaporkan peristiwa status saat ini, yang mungkin berbeda dari status terbaru yang diminta. Tujuan logika yang bertanggung jawab untuk mengubah status tampilan harus ada di atas perangkat sehingga tidak diinginkan bagi implementasi HAL untuk berubah secara spontan status tampilan.
getTargetBuffer() generates (handle bufferHandle);
Menampilkan handle ke buffering frame yang terkait dengan tampilan. {i>Buffer<i} ini
dapat dikunci dan ditulis oleh perangkat
lunak dan/atau GL. Buffer ini harus ditampilkan
dengan panggilan ke returnTargetBufferForDisplay()
meskipun layar
tidak lagi terlihat.
Meskipun format {i>buffer<i} eksklusif secara teknis dimungkinkan, pengujian kompatibilitas membutuhkan buffer dalam salah satu dari empat format yang didukung: NV21 (YCrCb 4:2:0 Semi-Planar), YV12 (YCrCb 4:2:0 Planar), YUYV (YCrCb 4:2:2 Interleaved), RGBA (32 bit R:G:B:x), BGRA (32 bit B:G:R:x). Format yang dipilih harus berupa GL yang valid target render pada implementasi GLES platform.
Jika error, buffer dengan handle null akan ditampilkan, tetapi buffer seperti itu tidak
harus diteruskan kembali ke returnTargetBufferForDisplay
.
returnTargetBufferForDisplay(handle bufferHandle) generates (EvsResult result);
Memberi tahu layar bahwa buffer siap untuk ditampilkan. Hanya buffer yang diambil
melalui panggilan ke getTargetBuffer()
valid untuk digunakan dengan
panggilan, dan isi BufferDesc
tidak boleh diubah oleh
aplikasi klien. Setelah panggilan ini, buffer tidak lagi valid untuk digunakan oleh
klien. Menampilkan OK jika berhasil, atau kode error yang sesuai mungkin
termasuk INVALID_ARG
atau BUFFER_NOT_AVAILABLE
.
struct DisplayDesc { string display_id; int32 vendor_flags; // Opaque value }
Menjelaskan sifat dasar tampilan EVS dan yang diperlukan oleh EVS terlepas dari implementasi layanan. HAL bertanggung jawab untuk mengisi struktur ini untuk menjelaskan tampilan EVS. Dapat berupa tampilan fisik atau tampilan virtual yang ditempatkan atau dicampur dengan perangkat presentasi lain.
display_id
. String yang mengidentifikasi tampilan secara unik. Bisa jadi ini adalah nama perangkat {i> kernel<i} perangkat, atau nama perangkat, seperti spion. Nilai untuk string ini dipilih oleh HAL dan digunakan secara buram oleh stack di atas.vendor_flags
. Metode untuk meneruskan kamera khusus dari pengemudi ke Aplikasi EVS khusus. Dilewati tidak ditafsirkan dari pengemudi hingga ke aplikasi EVS, yang dapat diabaikan anotasi.
enum DisplayState : uint32 { NOT_OPEN, // Display has not been “opened” yet NOT_VISIBLE, // Display is inhibited VISIBLE_ON_NEXT_FRAME, // Will become visible with next frame VISIBLE, // Display is currently active DEAD, // Display is not available. Interface should be closed }
Menjelaskan status layar EVS, yang dapat dinonaktifkan (bukan
terlihat oleh pengemudi) atau diaktifkan (menampilkan gambar kepada pengemudi).
Menyertakan status sementara ketika layar belum terlihat, tetapi sudah disiapkan
terlihat pada pengiriman bingkai citra berikutnya dengan
Panggilan returnTargetBufferForDisplay()
.
Pengelola EVS
Pengelola EVS menyediakan antarmuka publik ke sistem EVS untuk mengumpulkan dan menyajikan tampilan kamera eksternal. Di mana {i>driver<i} perangkat keras memungkinkan hanya ada satu antarmuka aktif per resource (kamera atau layar), EVS Manager memfasilitasi akses bersama ke kamera. Satu aplikasi EVS utama klien pertama Pengelola EVS, dan merupakan satu-satunya klien yang diizinkan menulis data tampilan (klien tambahan dapat diberi akses hanya baca ke kamera gambar).
EVS Manager mengimplementasikan API yang sama dengan driver HAL yang mendasarinya dan menyediakan layanan yang diperluas dengan mendukung beberapa klien serentak (lebih dari satu klien dapat membuka kamera melalui EVS Manager dan menerima video streaming).
![Pengelola EVS dan
Diagram EVS Hardware API.](https://source.android.com/static/docs/automotive/images/vhal_evs_manager.png?authuser=0&hl=id)
Aplikasi tidak melihat perbedaan saat beroperasi melalui EVS Hardware HAL atau EVS Manager API kecuali bahwa EVS Manager API memungkinkan akses streaming kamera serentak. Pengelola EVS itu sendiri yang mengizinkan lapisan HAL Perangkat Keras EVS, dan bertindak sebagai proxy untuk Perangkat Keras EVS HAL.
Bagian berikut ini hanya menjelaskan panggilan yang memiliki perilaku (diperluas) dalam implementasi EVS Manager; panggilan yang tersisa identik dengan deskripsi EVS HAL.
IEvsEnumerator
openCamera(string camera_id) generates (IEvsCamera camera);
Memperoleh objek antarmuka yang digunakan untuk berinteraksi dengan kamera tertentu
yang diidentifikasi oleh string camera_id unik. Menampilkan NULL saat gagal.
Di lapisan EVS Manager, selama sumber
daya sistem yang memadai tersedia,
kamera yang sudah terbuka dapat dibuka
kembali oleh proses lain, memungkinkan
teeing streaming video ke beberapa aplikasi konsumen. Tujuan
String camera_id
di lapisan EVS Manager sama dengan yang
dilaporkan ke lapisan EVS Hardware.
Kamera IEv
EVS Manager menyediakan implementasi IEvsCamera divirtualisasikan secara internal sehingga operasi pada kamera oleh satu klien tidak mempengaruhi klien lain, sehingga mempertahankan akses independen ke kamera mereka.
startVideoStream(IEvsCameraStream receiver) generates (EvsResult result);
Memulai streaming video. Klien dapat memulai dan menghentikan streaming video secara mandiri pada kamera dasar yang sama. Kamera yang mendasarinya dimulai saat klien dimulai.
doneWithFrame(uint32 frameId, handle bufferHandle) generates (EvsResult result);
Menampilkan frame. Setiap klien harus mengembalikan {i>frame<i} mereka ketika selesai, tetapi diizinkan untuk menyimpan {i>frame<i} mereka selama yang mereka inginkan. Jika jumlah frame yang ditahan oleh klien mencapai batas terkonfigurasinya, klien ini tidak akan menerima {i>frame<i} lagi sampai menghasilkan satu. Melewatkan frame ini tidak memengaruhi tetap menerima semua {i>frame<i} seperti yang diharapkan.
stopVideoStream();
Menghentikan streaming video. Setiap klien dapat menghentikan streaming videonya kapan saja tanpa mempengaruhi klien lain. Aliran data kamera yang mendasarinya pada lapisan hardware dihentikan saat klien terakhir dari kamera tertentu menghentikan streamingnya.
setExtendedInfo(int32 opaqueIdentifier, int32 opaqueValue) generates (EvsResult result);
Mengirim nilai khusus driver, yang berpotensi memungkinkan satu klien memengaruhi klien lain. Karena Pengelola EVS tidak dapat memahami implikasi dari kata-kata kontrol yang ditentukan vendor, kata-kata itu tidak divirtualisasikan dan memiliki efek samping berlaku untuk semua klien kamera tertentu. Misalnya, jika vendor menggunakan panggilan ini untuk mengubah kecepatan bingkai, semua klien kamera lapisan perangkat keras yang terpengaruh akan menerima frame dengan kecepatan baru.
Tampilan Ivs
Hanya satu pemilik layar yang diizinkan, bahkan di tingkat Pengelola EVS. Tujuan Manager tidak menambahkan fungsi dan hanya meneruskan antarmuka IEvsDisplay langsung melalui implementasi HAL yang mendasarinya.
aplikasi EVS
Android menyertakan implementasi referensi C++ native untuk EVS yang berkomunikasi dengan Pengelola EVS dan HAL Kendaraan untuk menyediakan fungsi dasar kamera belakang. Aplikasi diharapkan dapat dimulai paling awal dalam proses {i>booting<i} sistem, dengan menampilkan video yang cocok tergantung pada kamera yang tersedia dan status mobil (status roda gigi dan sinyal belok). OEM dapat memodifikasi atau mengganti aplikasi EVS dengan aplikasi khusus kendaraan mereka sendiri logika dan presentasi.
![](https://source.android.com/static/docs/automotive/images/vhal_evs_get_camera.png?authuser=0&hl=id)
![](https://source.android.com/static/docs/automotive/images/vhal_evs_receive_frame.png?authuser=0&hl=id)
Karena data gambar disajikan ke aplikasi dalam grafik standar buffer, aplikasi bertanggung jawab untuk memindahkan gambar dari sumber ke buffer output. Meskipun ini mengenai biaya penyalinan data, cara ini juga menawarkan kesempatan bagi aplikasi untuk merender gambar ke dalam menampilkan {i>buffer<i} dengan cara apa pun yang diinginkan.
Misalnya, aplikasi dapat memilih untuk memindahkan data {i>pixel<i} itu sendiri, mungkin dengan skala inline atau operasi rotasi. Aplikasi tersebut dapat juga memilih untuk menggunakan gambar sumber sebagai tekstur OpenGL dan merender kompleks ke buffer output, termasuk elemen virtual seperti ikon, pedoman, dan animasi. Aplikasi yang lebih canggih juga dapat memilih beberapa kamera input serentak dan menggabungkannya menjadi satu frame output (misalnya untuk digunakan dalam tampilan virtual atas-ke bawah di lingkungan kendaraan).
Gunakan EGL/SurfaceFlinger di EVS Display HAL
Bagian ini menjelaskan cara menggunakan EGL untuk merender implementasi HAL Tampilan EVS di Android 10.
EVS
Implementasi referensi HAL menggunakan EGL untuk merender pratinjau kamera
layar dan menggunakan libgui
untuk membuat platform render EGL target. Di Android 8 (dan yang lebih baru), libgui
diklasifikasikan sebagai VNDK-private,
yang mengacu pada sekelompok {i>library<i} yang tersedia untuk library VNDK yang tidak dapat digunakan oleh proses vendor.
Karena implementasi HAL harus berada di partisi vendor, vendor tidak boleh menggunakan
Permukaan di implementasi HAL.
Membangun libgui untuk proses vendor
Penggunaan libgui
berfungsi sebagai satu-satunya opsi untuk menggunakan EGL/SurfaceFlinger
dalam implementasi HAL Display EVS. Cara paling mudah untuk menerapkan libgui
adalah
sampai
frameworks/native/libs/gui
secara langsung menggunakan target build tambahan dalam skrip build. Target ini sama persis dengan
target libgui
, kecuali untuk penambahan dua kolom:
name
vendor_available
cc_library_shared { name: "libgui_vendor", vendor_available: true, vndk: { enabled: false, }, double_loadable: true,
defaults: ["libgui_bufferqueue-defaults"],
srcs: [ … // bufferhub is not used when building libgui for vendors target: { vendor: { cflags: [ "-DNO_BUFFERHUB", "-DNO_INPUT", ], …
Catatan: Target vendor dibuat dengan makro NO_INPUT
, yang menghapus satu kata 32-bit dari data paket. Karena SurfaceFlinger mengharapkan kolom ini yang telah dihapus, SurfaceFlinger gagal mengurai paket. Hal ini diamati sebagai kegagalan fcntl
:
W Parcel : Attempt to read object from Parcel 0x78d9cffad8 at offset 428 that is not in the object list E Parcel : fcntl(F_DUPFD_CLOEXEC) failed in Parcel::read, i is 0, fds[i] is 0, fd_count is 20, error: Unknown error 2147483647 W Parcel : Attempt to read object from Parcel 0x78d9cffad8 at offset 544 that is not in the object list
Untuk mengatasi kondisi ini:
diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp index 6066421fa..25cf5f0ce 100644 --- a/libs/gui/LayerState.cpp +++ b/libs/gui/LayerState.cpp @@ -54,6 +54,9 @@ status_t layer_state_t::write(Parcel& output) const output.writeFloat(color.b); #ifndef NO_INPUT inputInfo.write(output); +#else + // Write a dummy 32-bit word. + output.writeInt32(0); #endif output.write(transparentRegion); output.writeUint32(transform);
Contoh build
petunjuk disediakan di bawah ini. Bersiaplah untuk menerima
$(ANDROID_PRODUCT_OUT)/system/lib64/libgui_vendor.so
.
$ cd <your_android_source_tree_top> $ . ./build/envsetup. $ lunch <product_name>-<build_variant> ============================================ PLATFORM_VERSION_CODENAME=REL PLATFORM_VERSION=10 TARGET_PRODUCT=<product_name> TARGET_BUILD_VARIANT=<build_variant> TARGET_BUILD_TYPE=release TARGET_ARCH=arm64 TARGET_ARCH_VARIANT=armv8-a TARGET_CPU_VARIANT=generic TARGET_2ND_ARCH=arm TARGET_2ND_ARCH_VARIANT=armv7-a-neon TARGET_2ND_CPU_VARIANT=cortex-a9 HOST_ARCH=x86_64 HOST_2ND_ARCH=x86 HOST_OS=linux HOST_OS_EXTRA=<host_linux_version> HOST_CROSS_OS=windows HOST_CROSS_ARCH=x86 HOST_CROSS_2ND_ARCH=x86_64 HOST_BUILD_TYPE=release BUILD_ID=QT OUT_DIR=out ============================================
$ m -j libgui_vendor … $ find $ANDROID_PRODUCT_OUT/system -name "libgui_vendor*" .../out/target/product/hawk/system/lib64/libgui_vendor.so .../out/target/product/hawk/system/lib/libgui_vendor.so
Menggunakan binder di implementasi EVS HAL
Di Android 8 (dan yang lebih tinggi), node perangkat /dev/binder
menjadi eksklusif untuk
proses kerangka kerja dan, oleh karena itu, tidak dapat diakses oleh proses vendor. Sebagai gantinya,
proses vendor harus menggunakan /dev/hwbinder
dan harus mengonversi antarmuka AIDL apa pun
ke HIDL. Bagi mereka yang ingin terus menggunakan
antarmuka AIDL di antara proses vendor,
menggunakan domain binder, /dev/vndbinder
.
Domain IPC | Deskripsi |
---|---|
/dev/binder |
IPC antara proses framework/aplikasi dengan antarmuka AIDL |
/dev/hwbinder |
IPC antara proses framework/vendor dengan antarmuka HIDL IPC antara proses vendor dengan antarmuka HIDL |
/dev/vndbinder |
IPC antara proses vendor/vendor dengan Antarmuka AIDL |
Meskipun SurfaceFlinger mendefinisikan antarmuka AIDL, proses vendor hanya dapat menggunakan antarmuka HIDL untuk
berkomunikasi dengan proses kerangka kerja. Diperlukan upaya yang cukup besar untuk mengonversi
antarmuka AIDL ke HIDL. Untungnya, Android menyediakan sebuah metode untuk memilih binder
driver untuk libbinder
, yang ditautkan ke proses library userspace.
diff --git a/evs/sampleDriver/service.cpp b/evs/sampleDriver/service.cpp index d8fb3166..5fd02935 100644 --- a/evs/sampleDriver/service.cpp +++ b/evs/sampleDriver/service.cpp @@ -21,6 +21,7 @@ #include <utils/Errors.h> #include <utils/StrongPointer.h> #include <utils/Log.h> +#include <binder/ProcessState.h> #include "ServiceNames.h" #include "EvsEnumerator.h" @@ -43,6 +44,9 @@ using namespace android; int main() { ALOGI("EVS Hardware Enumerator service is starting"); + // Use /dev/binder for SurfaceFlinger + ProcessState::initWithDriver("/dev/binder"); + // Start a thread to listen to video device addition events. std::atomic<bool> running { true }; std::thread ueventHandler(EvsEnumerator::EvsUeventThread, std::ref(running));
Catatan: Proses vendor harus memanggil metode ini sebelum memanggil
Process
atau IPCThreadState
, atau sebelum melakukan panggilan binder.
Kebijakan SELinux
Jika implementasi perangkat adalah treble penuh, SELinux mencegah vendor
proses menggunakan /dev/binder
. Misalnya, contoh EVS HAL
penerapan ditetapkan ke domain hal_evs_driver
dan memerlukan
izin r/w ke domain binder_device
.
W ProcessState: Opening '/dev/binder' failed: Permission denied F ProcessState: Binder driver could not be opened. Terminating. F libc : Fatal signal 6 (SIGABRT), code -1 (SI_QUEUE) in tid 9145 (android.hardwar), pid 9145 (android.hardwar) W android.hardwar: type=1400 audit(0.0:974): avc: denied { read write } for name="binder" dev="tmpfs" ino=2208 scontext=u:r:hal_evs_driver:s0 tcontext=u:object_r:binder_device:s0 tclass=chr_file permissive=0
Akan tetapi, menambahkan izin ini akan menyebabkan kegagalan build karena melanggar
aturan notallow yang ditentukan di system/sepolicy/domain.te
untuk perangkat dengan treble penuh.
libsepol.report_failure: neverallow on line 631 of system/sepolicy/public/domain.te (or line 12436 of policy.conf) violated by allow hal_evs_driver binder_device:chr_file { read write }; libsepol.check_assertions: 1 neverallow failures occurred
full_treble_only(` neverallow { domain -coredomain -appdomain -binder_in_vendor_violators } binder_device:chr_file rw_file_perms; ')
binder_in_vendor_violators
adalah atribut yang disediakan untuk menangkap {i>bug<i} dan memandu pengembangan. Alat ini juga dapat digunakan untuk
menyelesaikan pelanggaran Android 10 yang dijelaskan di atas.
diff --git a/evs/sepolicy/evs_driver.te b/evs/sepolicy/evs_driver.te index f1f31e9fc..6ee67d88e 100644 --- a/evs/sepolicy/evs_driver.te +++ b/evs/sepolicy/evs_driver.te @@ -3,6 +3,9 @@ type hal_evs_driver, domain, coredomain; hal_server_domain(hal_evs_driver, hal_evs) hal_client_domain(hal_evs_driver, hal_evs) +# Allow to use /dev/binder +typeattribute hal_evs_driver binder_in_vendor_violators; + # allow init to launch processes in this context type hal_evs_driver_exec, exec_type, file_type, system_file_type; init_daemon_domain(hal_evs_driver)
Membangun implementasi referensi EVS HAL sebagai proses vendor
Sebagai referensi, Anda dapat menerapkan perubahan berikut pada
packages/services/Car/evs/Android.mk
. Pastikan untuk mengonfirmasi bahwa
semua perubahan yang dijelaskan berfungsi untuk penerapan Anda.
diff --git a/evs/sampleDriver/Android.mk b/evs/sampleDriver/Android.mk index 734feea7d..0d257214d 100644 --- a/evs/sampleDriver/Android.mk +++ b/evs/sampleDriver/Android.mk @@ -16,7 +16,7 @@ LOCAL_SRC_FILES := \ LOCAL_SHARED_LIBRARIES := \ android.hardware.automotive.evs@1.0 \ libui \ - libgui \ + libgui_vendor \ libEGL \ libGLESv2 \ libbase \ @@ -33,6 +33,7 @@ LOCAL_SHARED_LIBRARIES := \ LOCAL_INIT_RC := android.hardware.automotive.evs@1.0-sample.rc LOCAL_MODULE := android.hardware.automotive.evs@1.0-sample +LOCAL_PROPRIETARY_MODULE := true LOCAL_MODULE_TAGS := optional LOCAL_STRIP_MODULE := keep_symbols @@ -40,6 +41,7 @@ LOCAL_STRIP_MODULE := keep_symbols LOCAL_CFLAGS += -DLOG_TAG=\"EvsSampleDriver\" LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES LOCAL_CFLAGS += -Wall -Werror -Wunused -Wunreachable-code +LOCAL_CFLAGS += -Iframeworks/native/include #NOTE: It can be helpful, while debugging, to disable optimizations #LOCAL_CFLAGS += -O0 -g diff --git a/evs/sampleDriver/service.cpp b/evs/sampleDriver/service.cpp index d8fb31669..5fd029358 100644 --- a/evs/sampleDriver/service.cpp +++ b/evs/sampleDriver/service.cpp @@ -21,6 +21,7 @@ #include <utils/Errors.h> #include <utils/StrongPointer.h> #include <utils/Log.h> +#include <binder/ProcessState.h> #include "ServiceNames.h" #include "EvsEnumerator.h" @@ -43,6 +44,9 @@ using namespace android; int main() { ALOGI("EVS Hardware Enumerator service is starting"); + // Use /dev/binder for SurfaceFlinger + ProcessState::initWithDriver("/dev/binder"); + // Start a thread to listen video device addition events. std::atomic<bool> running { true }; std::thread ueventHandler(EvsEnumerator::EvsUeventThread, std::ref(running)); diff --git a/evs/sepolicy/evs_driver.te b/evs/sepolicy/evs_driver.te index f1f31e9fc..632fc7337 100644 --- a/evs/sepolicy/evs_driver.te +++ b/evs/sepolicy/evs_driver.te @@ -3,6 +3,9 @@ type hal_evs_driver, domain, coredomain; hal_server_domain(hal_evs_driver, hal_evs) hal_client_domain(hal_evs_driver, hal_evs) +# allow to use /dev/binder +typeattribute hal_evs_driver binder_in_vendor_violators; + # allow init to launch processes in this context type hal_evs_driver_exec, exec_type, file_type, system_file_type; init_daemon_domain(hal_evs_driver) @@ -22,3 +25,7 @@ allow hal_evs_driver ion_device:chr_file r_file_perms; # Allow the driver to access kobject uevents allow hal_evs_driver self:netlink_kobject_uevent_socket create_socket_perms_no_ioctl; + +# Allow the driver to use the binder device +allow hal_evs_driver binder_device:chr_file rw_file_perms;