Android, Android önyükleme işleminin çok erken aşamalarında görüntülerin yakalanmasını ve görüntülenmesini sağlayan ve sistemin ömrü boyunca çalışmaya devam eden bir otomotiv HIDL Donanım Soyutlama Katmanı (HAL) içerir. HAL, dış görüş sistemi (EVS) yığınını içerir ve genellikle Android tabanlı Araç İçi Bilgi-Eğlence (IVI) sistemlerine sahip araçlarda arka görüş kamerasını ve surround görüş ekranlarını desteklemek için kullanılır. EVS ayrıca gelişmiş özelliklerin kullanıcı uygulamalarında uygulanmasına da olanak tanır.
Android ayrıca EVS'ye özel bir yakalama ve görüntüleme sürücüsü arayüzü içerir ( /hardware/interfaces/automotive/evs/1.0
içinde). Mevcut Android kamera ve görüntüleme hizmetlerinin üzerine bir arka görüş kamerası uygulaması oluşturmak mümkün olsa da, böyle bir uygulama muhtemelen Android önyükleme sürecinde çok geç çalışacaktır. Özel bir HAL kullanmak, kolaylaştırılmış bir arayüz sağlar ve bir OEM'in EVS yığınını desteklemek için neleri uygulaması gerektiğini netleştirir.
Sistem bileşenleri
EVS aşağıdaki sistem bileşenlerini içerir:
AGH uygulaması
Örnek bir C++ EVS uygulaması ( /packages/services/Car/evs/app
) referans uygulaması görevi görür. Bu uygulama, AGH Yöneticisinden video kareleri istemekten ve tamamlanmış kareleri görüntülenmek üzere AGH Yöneticisine geri göndermekten sorumludur. EVS ve Araç Hizmeti kullanılabilir hale gelir gelmez init tarafından başlatılması bekleniyor ve bu, güç açıldıktan sonraki iki (2) saniye içinde hedefleniyor. OEM'ler EVS uygulamasını istedikleri gibi değiştirebilir veya değiştirebilir.
AGH Müdürü
EVS Yöneticisi ( /packages/services/Car/evs/manager
), basit bir arka görüş kamerası ekranından 6DOF çoklu kamera görüntülemeye kadar her şeyi uygulamak için bir EVS uygulamasının ihtiyaç duyduğu yapı taşlarını sağlar. Arayüzü HIDL aracılığıyla sunulur ve birden fazla eşzamanlı istemciyi kabul edecek şekilde tasarlanmıştır. Diğer uygulamalar ve hizmetler (özellikle Araç Hizmeti), AGH sisteminin ne zaman aktif olduğunu öğrenmek için AGH Yöneticisi durumunu sorgulayabilir.
EVS HIDL arayüzü
EVS sistemi, hem kamera hem de ekran elemanları, android.hardware.automotive.evs
paketinde tanımlanmıştır. Arayüzü çalıştıran (sentetik test görüntüleri oluşturur ve görüntülerin gidiş dönüşünü doğrulayan) örnek bir uygulama /hardware/interfaces/automotive/evs/1.0/default
adresinde verilmiştir.
OEM /hardware/interfaces/automotive/evs
içindeki .hal dosyaları tarafından ifade edilen API'nin uygulanmasından sorumludur. Bu tür uygulamalar, fiziksel kameralardan verilerin yapılandırılması, toplanması ve Gralloc tarafından tanınabilen paylaşılan bellek arabellekleri aracılığıyla iletilmesinden sorumludur. Uygulamanın görüntüleme tarafı, uygulama tarafından doldurulabilen (genellikle EGL oluşturmayla) paylaşılan bir bellek arabelleği sağlamaktan ve fiziksel ekranda görünmesi isteyebilecek herhangi bir şeye tercihli olarak bitmiş kareleri sunmaktan sorumludur. EVS arayüzünün satıcı uygulamaları /vendor/… /device/…
veya hardware/…
(örneğin, /hardware/[vendor]/[platform]/evs
) altında saklanabilir.
Çekirdek sürücüleri
EVS yığınını destekleyen bir aygıt, çekirdek sürücüleri gerektirir. OEM'ler, yeni sürücüler oluşturmak yerine EVS'nin gerektirdiği özellikleri mevcut kamera veya ekran donanım sürücüleri aracılığıyla destekleme seçeneğine sahiptir. Sürücülerin yeniden kullanılması, özellikle görüntü sunumunun diğer etkin iş parçacıklarıyla koordinasyon gerektirebileceği ekran sürücüleri için avantajlı olabilir. Android 8.0, v4l2 desteği için çekirdeğe ve çıktı görüntüsünün sunulması için SurfaceFlinger'a bağlı olan v4l2 tabanlı bir örnek sürücü ( packages/services/Car/evs/sampleDriver
içinde) içerir.
EVS donanım arayüzü açıklaması
Bu bölümde HAL açıklanmaktadır. Satıcıların bu API'nin kendi donanımlarına uyarlanmış uygulamalarını sağlamaları bekleniyor.
IEvsEnumerator
Bu nesne, sistemdeki mevcut EVS donanımının (bir veya daha fazla kamera ve tek görüntüleme cihazı) numaralandırılmasından sorumludur.
getCameraList() generates (vec<CameraDesc> cameras);
Sistemdeki tüm kameralar için açıklamaları içeren bir vektör döndürür. Kamera setinin sabit olduğu ve önyükleme sırasında bilinebilir olduğu varsayılmaktadır. Kamera açıklamalarına ilişkin ayrıntılar için bkz. CameraDesc
.
openCamera(string camera_id) generates (IEvsCamera camera);
Benzersiz kamera_id dizesi tarafından tanımlanan belirli bir kamerayla etkileşimde bulunmak için kullanılan bir arayüz nesnesi elde eder. Başarısızlık durumunda NULL döndürür. Zaten açık olan bir kamerayı yeniden açma girişimleri başarısız olamaz. Uygulamanın başlatılması ve kapatılmasıyla ilişkili yarış koşullarından kaçınmak için, bir kameranın yeniden açılması, yeni isteğin yerine getirilebilmesi için önceki örneği kapatmalıdır. Bu şekilde önlenen bir kamera örneğinin, nihai imhayı bekleyen ve kamera durumunu etkilemeye yönelik herhangi bir isteğe OWNERSHIP_LOST
dönüş koduyla yanıt veren etkin olmayan bir duruma getirilmesi gerekir.
closeCamera(IEvsCamera camera);
IEvsCamera arayüzünü serbest bırakır (ve openCamera()
çağrısının tersidir). closeCamera
çağrılmadan önce stopVideoStream()
çağrılarak kamera video akışı durdurulmalıdır.
openDisplay() generates (IEvsDisplay display);
Sistemin EVS ekranıyla özel olarak etkileşimde bulunmak için kullanılan bir arayüz nesnesi elde eder. Aynı anda yalnızca bir istemci IEvsDisplay'in işlevsel bir örneğini tutabilir. openCamera
açıklanan agresif açma davranışına benzer şekilde, yeni bir IEvsDisplay nesnesi herhangi bir zamanda oluşturulabilir ve önceki örnekleri devre dışı bırakır. Geçersiz kılınmış örnekler var olmaya devam eder ve sahiplerinden gelen işlev çağrılarına yanıt verir, ancak öldüklerinde hiçbir mutasyon işlemi gerçekleştirmemelidir. Sonunda istemci uygulamasının OWNERSHIP_LOST
hata dönüş kodlarını fark etmesi ve etkin olmayan arayüzü kapatıp serbest bırakması beklenir.
closeDisplay(IEvsDisplay display);
IEvsDisplay arayüzünü serbest bırakır (ve openDisplay()
çağrısının tersidir). getTargetBuffer()
çağrılarıyla alınan bekleyen arabelleklerin, ekranı kapatmadan önce ekrana döndürülmesi gerekir.
getDisplayState() generates (DisplayState state);
Geçerli görüntü durumunu alır. HAL uygulaması, en son talep edilen durumdan farklı olabilecek gerçek mevcut durumu rapor etmelidir. Görüntüleme durumlarını değiştirmekten sorumlu olan mantık, cihaz katmanının üzerinde mevcut olmalıdır; bu da HAL uygulamasının görüntü durumlarını kendiliğinden değiştirmesini istenmeyen bir hale getirir. Eğer görüntü şu anda herhangi bir istemci tarafından tutulmuyorsa (openDisplay çağrısıyla), bu işlev NOT_OPEN
değerini döndürür. Aksi takdirde, EVS Ekranının mevcut durumunu bildirir (bkz. IEvsDisplay API ).
struct CameraDesc { string camera_id; int32 vendor_flags; // Opaque value }
-
camera_id
. Belirli bir kamerayı benzersiz şekilde tanımlayan bir dize. Aygıtın çekirdek aygıt adı veya dikiz gibi aygıt adı olabilir. Bu dizenin değeri HAL uygulaması tarafından seçilir ve yukarıdaki yığın tarafından opak bir şekilde kullanılır. -
vendor_flags
. Özel kamera bilgilerini sürücüden özel bir EVS uygulamasına opak bir şekilde aktarmaya yönelik bir yöntem. Sürücüden EVS uygulamasına yorumlanmadan aktarılır ve bu uygulama bunu göz ardı etmekte özgürdür.
IEvsKamera
Bu nesne tek bir kamerayı temsil eder ve görüntü yakalamak için birincil arayüzdür.
getCameraInfo() generates (CameraDesc info);
Bu kameranın CameraDesc
döndürür.
setMaxFramesInFlight(int32 bufferCount) generates (EvsResult result);
Kameranın desteklemesi istenen tampon zincirinin derinliğini belirtir. Bu kadar çok kare IEvsCamera istemcisi tarafından aynı anda tutulabilir. Bu kadar çok kare alıcıya, doneWithFrame
tarafından döndürülmeden teslim edildiyse, akış, yeniden kullanım için bir arabellek döndürülene kadar kareleri atlar. Bu çağrının, akışlar zaten çalışıyorken bile herhangi bir zamanda gelmesi yasaldır; bu durumda arabelleklerin uygun şekilde zincire eklenmesi veya zincirden çıkarılması gerekir. Bu giriş noktasına herhangi bir çağrı yapılmazsa IEvsCamera varsayılan olarak en az bir kareyi destekler; daha kabul edilebilir.
İstenen bufferCount karşılanamıyorsa işlev BUFFER_NOT_AVAILABLE
veya diğer ilgili hata kodunu döndürür. Bu durumda sistem önceden ayarlanan değerle çalışmaya devam eder.
startVideoStream(IEvsCameraStream receiver) generates (EvsResult result);
Bu kameradan EVS kamera karelerinin teslimini talep ediyor. IEvsCameraStream, stopVideoStream()
çağrılıncaya kadar yeni görüntü çerçeveleriyle periyodik çağrılar almaya başlar. Çerçeveler, startVideoStream
çağrısından sonraki 500 ms içinde teslim edilmeye başlamalı ve başlatıldıktan sonra minimum 10 FPS'de oluşturulmalıdır. Video akışını etkili bir şekilde başlatmak için gereken süre, herhangi bir arka görüş kamerası başlatma süresi gereksinimine dahil edilir. Akış başlatılmazsa bir hata kodu döndürülmelidir; aksi takdirde Tamam döndürülür.
oneway doneWithFrame(BufferDesc buffer);
IEvsCameraStream tarafından teslim edilen bir kareyi döndürür. IEvsCameraStream arayüzüne gönderilen bir çerçevenin tüketilmesi tamamlandığında, çerçevenin yeniden kullanılmak üzere IEvsCamera'ya iade edilmesi gerekir. Küçük, sınırlı sayıda arabellek mevcuttur (muhtemelen bir tane kadar küçük) ve eğer kaynak tükenirse, bir arabellek döndürülene kadar başka çerçeve teslim edilmez, bu da potansiyel olarak karelerin atlanmasına neden olur (boş tanıtıcılı bir arabellek, bitişi belirtir) bir akışın parçasıdır ve bu işlev aracılığıyla döndürülmesine gerek yoktur). Başarı durumunda Tamam'ı veya INVALID_ARG
veya BUFFER_NOT_AVAILABLE
dahil olmak üzere potansiyel olarak uygun hata kodunu döndürür.
stopVideoStream();
EVS kamera karelerinin dağıtımını durdurur. Teslimat eşzamansız olduğundan, bu çağrı geri döndükten sonra çerçeveler bir süre daha gelmeye devam edebilir. Akışın kapanması IEvsCameraStream'e bildirilinceye kadar her karenin döndürülmesi gerekir. Zaten durdurulmuş veya hiç başlatılmamış bir akışta stopVideoStream
çağrısını yapmak yasaldır; bu durumda bu çağrı dikkate alınmaz.
getExtendedInfo(int32 opaqueIdentifier) generates (int32 value);
HAL uygulamasından sürücüye özel bilgiler ister. opaqueIdentifier
için izin verilen değerler sürücüye özeldir ancak aktarılan hiçbir değer sürücüyü çökertemez. Tanınmayan herhangi bir opaqueIdentifier
için sürücünün 0 döndürmesi gerekir.
setExtendedInfo(int32 opaqueIdentifier, int32 opaqueValue) generates (EvsResult result);
HAL uygulamasına sürücüye özel bir değer gönderir. Bu uzantı yalnızca araca özel uzantıları kolaylaştırmak için sağlanmıştır ve hiçbir HAL uygulaması, bu çağrının varsayılan durumda çalışmasını gerektirmemelidir. Sürücü değerleri tanıyıp kabul ederse OK döndürülmelidir; aksi takdirde INVALID_ARG
veya diğer temsili hata kodu döndürülmelidir.
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 }
API'den geçirilen bir görüntüyü açıklar. HAL sürücüsü, görüntü arabelleğini tanımlamak için bu yapının doldurulmasından sorumludur ve HAL istemcisi bu yapıyı salt okunur olarak ele almalıdır. Alanlar, görüntünün eglCreateImageKHR()
uzantılı EGL ile kullanılması gerekebileceği gibi, istemcinin bir ANativeWindowBuffer
nesnesini yeniden yapılandırmasına imkan verecek yeterli bilgiyi içerir.
-
width
. Sunulan görüntünün piksel cinsinden genişliği. -
height
. Sunulan görüntünün piksel cinsinden yüksekliği. -
stride
. Her satırın aslında bellekte kapladığı piksel sayısı, satırların hizalanması için yapılan dolguları hesaba katar. Gralloc'un arabellek açıklamaları için benimsediği kurala uyacak şekilde piksel cinsinden ifade edilir. -
pixelSize
. Her bir pikselin kapladığı bayt sayısı; görüntüdeki satırlar arasında adım atmak için gereken boyutun bayt cinsinden hesaplanmasına olanak tanır (bayt cinsindenstride
= piksel cinsindenstride
*pixelSize
). -
format
. Görüntünün kullandığı piksel biçimi. Sağlanan format, platformun OpenGL uygulamasıyla uyumlu olmalıdır. Uyumluluk testini geçebilmek için kamera kullanımındaHAL_PIXEL_FORMAT_YCRCB_420_SP
, görüntüleme için iseRGBA
veyaBGRA
tercih edilmelidir. -
usage
. HAL uygulaması tarafından belirlenen kullanım bayrakları. HAL istemcilerinin bunları değiştirilmeden geçmesi beklenir (ayrıntılar içinGralloc.h
ile ilgili işaretlere bakın). -
bufferId
. HAL API'leri arasında gidiş-dönüş sonrasında bir arabelleğin tanınmasına izin vermek için HAL uygulaması tarafından belirtilen benzersiz bir değer. Bu alanda saklanan değer HAL uygulaması tarafından keyfi olarak seçilebilir. -
memHandle
. Görüntü verilerini içeren temel bellek arabelleğinin tanıtıcısı. HAL uygulaması burada bir Gralloc arabellek tanıtıcısını saklamayı seçebilir.
IEvsKamera Akışı
İstemci, eşzamansız video karesi teslimatlarını almak için bu arayüzü uygular.
deliverFrame(BufferDesc buffer);
Bir video karesi incelemeye her hazır olduğunda HAL'den çağrıları alır. Bu yöntemle alınan arabellek tanıtıcıları IEvsCamera::doneWithFrame()
çağrıları yoluyla döndürülmelidir. Video akışı IEvsCamera::stopVideoStream()
çağrısıyla durdurulduğunda, işlem hattı boşaldıkça bu geri çağırma devam edebilir. Her karenin yine de iade edilmesi gerekir; akıştaki son çerçeve teslim edildiğinde, akışın sonunu belirten bir NULL bufferHandle
teslim edilir ve başka çerçeve teslimatı gerçekleşmez. NULL bufferHandle
kendisinin doneWithFrame()
ile geri gönderilmesine gerek yoktur, ancak diğer tüm tanıtıcıların döndürülmesi gerekir
Tescilli arabellek formatları teknik olarak mümkün olsa da uyumluluk testleri, arabelleğin desteklenen dört formattan birinde olmasını gerektirir: NV21 (YCrCb 4:2:0 Yarı Düzlemsel), YV12 (YCrCb 4:2:0 Düzlemsel), YUYV (YCrCb 4: 2:2 Aralıklı), RGBA (32 bit R:G:B:x), BGRA (32 bit B:G:R:x). Seçilen format, platformun GLES uygulamasında geçerli bir GL doku kaynağı olmalıdır.
Uygulama, BufferDesc
yapısındaki bufferId
alanı ile memHandle
arasındaki herhangi bir yazışmaya dayanmamalıdır . bufferId
değerleri aslında HAL sürücüsü uygulamasına özeldir ve bunları uygun gördüğü şekilde kullanabilir (ve yeniden kullanabilir).
IEvsEkran
Bu nesne Evs ekranını temsil eder, ekranın durumunu kontrol eder ve görüntülerin gerçek sunumunu yönetir.
getDisplayInfo() generates (DisplayDesc info);
Sistem tarafından sağlanan EVS ekranı hakkında temel bilgileri döndürür (bkz. DisplayDesc ).
setDisplayState(DisplayState state) generates (EvsResult result);
Görüntüleme durumunu ayarlar. İstemciler, görüntü durumunu istenen durumu ifade edecek şekilde ayarlayabilir ve HAL uygulaması, herhangi bir durumdayken herhangi bir durum için bir isteği incelikli bir şekilde kabul etmelidir; ancak yanıt, isteğin göz ardı edilmesi olabilir.
Başlatma sonrasında, ekran NOT_VISIBLE
durumunda başlayacak şekilde tanımlanır; bundan sonra istemcinin VISIBLE_ON_NEXT_FRAME
durumunu talep etmesi ve video sağlamaya başlaması beklenir. Görüntüye artık ihtiyaç duyulmadığında, istemcinin son video karesini geçtikten sonra NOT_VISIBLE
durumunu talep etmesi beklenir.
Herhangi bir zamanda talep edilmesi her durum için geçerlidir. Ekran zaten görünürse, VISIBLE_ON_NEXT_FRAME
olarak ayarlandığında görünür kalmalıdır. İstenen durum tanınmayan bir numaralandırma değeri olmadığı sürece her zaman Tamam değerini döndürür; bu durumda INVALID_ARG
döndürülür.
getDisplayState() generates (DisplayState state);
Görüntüleme durumunu alır. HAL uygulaması, en son talep edilen durumdan farklı olabilecek gerçek mevcut durumu rapor etmelidir. Görüntüleme durumlarını değiştirmekten sorumlu olan mantık, cihaz katmanının üzerinde mevcut olmalıdır; bu da HAL uygulamasının görüntü durumlarını kendiliğinden değiştirmesini istenmeyen bir hale getirir.
getTargetBuffer() generates (handle bufferHandle);
Ekranla ilişkili çerçeve arabelleğine bir tanıtıcı döndürür. Bu arabellek yazılım ve/veya GL tarafından kilitlenebilir ve yazılabilir. Bu arabellek, ekran artık görünür olmasa bile, returnTargetBufferForDisplay()
çağrısıyla döndürülmelidir.
Tescilli arabellek formatları teknik olarak mümkün olsa da uyumluluk testleri, arabelleğin desteklenen dört formattan birinde olmasını gerektirir: NV21 (YCrCb 4:2:0 Yarı Düzlemsel), YV12 (YCrCb 4:2:0 Düzlemsel), YUYV (YCrCb 4: 2:2 Aralıklı), RGBA (32 bit R:G:B:x), BGRA (32 bit B:G:R:x). Seçilen format, platformun GLES uygulamasında geçerli bir GL oluşturma hedefi olmalıdır.
Hata durumunda, boş tanıtıcıya sahip bir arabellek döndürülür, ancak böyle bir arabelleğin returnTargetBufferForDisplay
öğesine geri iletilmesi gerekmez.
returnTargetBufferForDisplay(handle bufferHandle) generates (EvsResult result);
Ekrana arabelleğin görüntülenmeye hazır olduğunu söyler. Yalnızca getTargetBuffer()
çağrısı yoluyla alınan arabellekler bu çağrıyla kullanım için geçerlidir ve BufferDesc
içeriği istemci uygulaması tarafından değiştirilemez. Bu çağrıdan sonra arabellek artık istemci tarafından kullanım için geçerli değildir. Başarı durumunda Tamam'ı veya INVALID_ARG
veya BUFFER_NOT_AVAILABLE
dahil olmak üzere potansiyel olarak uygun hata kodunu döndürür.
struct DisplayDesc { string display_id; int32 vendor_flags; // Opaque value }
Bir EVS ekranının temel özelliklerini ve bir EVS uygulamasının gerektirdiği temel özellikleri açıklar. HAL, EVS ekranını tanımlamak için bu yapının doldurulmasından sorumludur. Fiziksel bir ekran veya başka bir sunum cihazıyla kaplanmış veya karıştırılmış sanal bir ekran olabilir.
-
display_id
. Ekranı benzersiz şekilde tanımlayan bir dize. Bu, aygıtın çekirdek aygıt adı veya aygıtın dikiz gibi bir adı olabilir. Bu dizenin değeri HAL uygulaması tarafından seçilir ve yukarıdaki yığın tarafından opak bir şekilde kullanılır. -
vendor_flags
. Özel kamera bilgilerini sürücüden özel bir EVS Uygulamasına opak bir şekilde aktarmaya yönelik bir yöntem. Sürücüden EVS uygulamasına yorumlanmadan aktarılır ve bu uygulama bunu göz ardı etmekte özgürdür.
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 }
Devre dışı bırakılabilen (sürücü tarafından görülemeyen) veya etkinleştirilebilen (sürücüye bir görüntü gösteren) EVS ekranının durumunu açıklar. Ekranın henüz görünür olmadığı ancak bir sonraki görüntü karesinin returnTargetBufferForDisplay()
çağrısıyla sunulmasıyla görünür olmaya hazırlandığı geçici bir durumu içerir.
AGH Müdürü
EVS Yöneticisi, harici kamera görüntülerini toplamak ve sunmak için EVS sistemine genel arayüz sağlar. Donanım sürücülerinin kaynak (kamera veya ekran) başına yalnızca bir aktif arayüze izin verdiği durumlarda EVS Yöneticisi, kameralara paylaşımlı erişimi kolaylaştırır. Tek bir birincil EVS uygulaması, EVS Manager'ın ilk istemcisidir ve ekran verilerini yazmasına izin verilen tek istemcidir (ek istemcilere kamera görüntülerine salt okunur erişim verilebilir).
EVS Yöneticisi, temel HAL sürücüleri ile aynı API'yi uygular ve birden fazla eşzamanlı istemciyi destekleyerek genişletilmiş hizmet sağlar (birden fazla istemci, EVS Yöneticisi aracılığıyla bir kamera açabilir ve bir video akışı alabilir).
Uygulamalar, EVS Donanım HAL uygulaması veya EVS Manager API'si aracılığıyla çalışırken, EVS Manager API'sinin eşzamanlı kamera akışı erişimine izin vermesi dışında hiçbir fark görmez. EVS Yöneticisi, EVS Donanım HAL katmanının izin verilen tek istemcisidir ve EVS Donanım HAL'i için bir proxy görevi görür.
Aşağıdaki bölümlerde yalnızca AGH Yöneticisi uygulamasında farklı (genişletilmiş) davranışa sahip olan çağrılar açıklanmaktadır; kalan aramalar EVS HAL açıklamalarıyla aynıdır.
IEvsEnumerator
openCamera(string camera_id) generates (IEvsCamera camera);
Benzersiz kamera_id dizesi tarafından tanımlanan belirli bir kamerayla etkileşimde bulunmak için kullanılan bir arayüz nesnesi elde eder. Başarısızlık durumunda NULL döndürür. EVS Yöneticisi katmanında, yeterli sistem kaynakları mevcut olduğu sürece, zaten açık olan bir kamera başka bir işlemle tekrar açılarak video akışının birden fazla tüketici uygulamasına bağlanmasına olanak tanır. EVS Yöneticisi katmanındaki camera_id
dizeleri, EVS Donanım katmanına bildirilenlerle aynıdır.
IEvsKamera
EVS Yöneticisi tarafından sağlanan IEvsCamera uygulaması dahili olarak sanallaştırılmıştır, böylece bir istemcinin bir kamera üzerinde yaptığı işlemler, kameralarına bağımsız erişime sahip olan diğer istemcileri etkilemez.
startVideoStream(IEvsCameraStream receiver) generates (EvsResult result);
Video akışlarını başlatır. İstemciler aynı temel kamera üzerinde video akışlarını bağımsız olarak başlatabilir ve durdurabilir. Temel kamera, ilk istemci başlatıldığında başlar.
doneWithFrame(uint32 frameId, handle bufferHandle) generates (EvsResult result);
Bir çerçeve döndürür. Her müşterinin işi bittiğinde çerçevelerini iade etmesi gerekir, ancak çerçevelerini istedikleri kadar tutmalarına izin verilir. İstemcinin tuttuğu kare sayısı yapılandırılmış sınırına ulaştığında, bir kare döndürene kadar daha fazla kare almaz. Bu çerçeve atlama, tüm çerçeveleri beklendiği gibi almaya devam eden diğer istemcileri etkilemez.
stopVideoStream();
Bir video akışını durdurur. Her istemci, diğer istemcileri etkilemeden video akışını istediği zaman durdurabilir. Belirli bir kameranın son istemcisi akışını durdurduğunda, donanım katmanındaki temel kamera akışı durdurulur.
setExtendedInfo(int32 opaqueIdentifier, int32 opaqueValue) generates (EvsResult result);
Sürücüye özel bir değer göndererek bir istemcinin başka bir istemciyi etkileme potansiyeline sahip olmasını sağlar. EVS Yöneticisi, satıcı tarafından tanımlanan kontrol kelimelerinin sonuçlarını anlayamadığından, bunlar sanallaştırılmaz ve herhangi bir yan etki, belirli bir kameranın tüm istemcilerine uygulanır. Örneğin, bir satıcı bu çağrıyı kare hızlarını değiştirmek için kullanırsa, etkilenen donanım katmanı kamerasının tüm istemcileri kareleri yeni hızda alacaktır.
IEvsEkran
AGH Yöneticisi düzeyinde bile ekranın yalnızca bir sahibine izin verilir. Yönetici hiçbir işlevsellik eklemez ve IEvsDisplay arayüzünü doğrudan temeldeki HAL uygulamasına aktarır.
AGH uygulaması
Android, temel arka görüş kamerası işlevlerini sağlamak için EVS Yöneticisi ve Araç HAL ile iletişim kuran bir EVS uygulamasının yerel C++ referans uygulamasını içerir. Uygulamanın, mevcut kameralara ve aracın durumuna (vites ve dönüş sinyali durumu) bağlı olarak uygun videonun gösterilmesiyle, sistem önyükleme sürecinin çok erken bir aşamasında başlaması bekleniyor. OEM'ler EVS uygulamasını kendi araca özel mantık ve sunumlarıyla değiştirebilir veya değiştirebilir.
Görüntü verileri uygulamaya standart bir grafik arabelleğinde sunulduğundan uygulama, görüntünün kaynak arabellekten çıkış arabelleğine taşınmasından sorumludur. Bu, bir veri kopyasının maliyetini beraberinde getirirken, aynı zamanda uygulamaya, görüntüyü ekran arabelleğine istediği şekilde işleme fırsatı da sunar.
Örneğin uygulama, potansiyel olarak satır içi ölçekleme veya döndürme işlemiyle piksel verilerini kendisi taşımayı seçebilir. Uygulama ayrıca kaynak görüntüyü bir OpenGL dokusu olarak kullanmayı ve simgeler, kılavuzlar ve animasyonlar gibi sanal öğeler dahil olmak üzere karmaşık bir sahneyi çıktı arabelleğine işlemeyi de seçebilir. Daha karmaşık bir uygulama aynı zamanda birden fazla eşzamanlı giriş kamerasını seçip bunları tek bir çıkış çerçevesinde birleştirebilir (örneğin, araç çevresinin yukarıdan aşağıya, sanal görünümünde kullanım için).
EVS Ekran HAL'inde EGL/SurfaceFlinger'ı kullanın
Bu bölümde, Android 10'da bir EVS Display HAL uygulaması oluşturmak için EGL'nin nasıl kullanılacağı açıklanmaktadır.
Bir EVS HAL referans uygulaması, ekranda kamera önizlemesini oluşturmak için EGL'yi kullanır ve hedef EGL oluşturma yüzeyini oluşturmak için libgui
kullanır. Android 8'de (ve üzeri), libgui
VNDK-private olarak sınıflandırılır; bu, VNDK kitaplıklarının kullanabileceği ve satıcı işlemlerinin kullanamayacağı bir kitaplık grubunu ifade eder. HAL uygulamalarının satıcı bölümünde bulunması gerektiğinden satıcıların HAL uygulamalarında Surface kullanması engellenir.
Satıcı süreçleri için libgui oluşturma
libgui
kullanımı, EVS Display HAL uygulamalarında EGL/SurfaceFlinger'ı kullanmanın tek seçeneği olarak hizmet vermektedir. libgui
uygulamanın en basit yolu, derleme betiğinde ek bir derleme hedefi kullanarak doğrudan çerçeveler/native/libs/gui'yi kullanmaktır. Bu hedef, iki alanın eklenmesi dışında libgui
hedefiyle tamamen aynıdır:
-
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", ], …
Not: Satıcı hedefleri, paket verilerinden 32 bitlik bir kelimeyi kaldıran NO_INPUT
makrosu ile oluşturulmuştur. SurfaceFlinger bu alanın kaldırılmasını beklediğinden SurfaceFlinger paketi ayrıştıramaz. Bu bir fcntl
hatası olarak gözlenir:
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
Bu durumu çözmek için:
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);
Örnek oluşturma talimatları aşağıda verilmiştir. $(ANDROID_PRODUCT_OUT)/system/lib64/libgui_vendor.so
almayı bekleyin.
$ 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
EVS HAL uygulamasında bağlayıcıyı kullanın
Android 8'de (ve üzeri), /dev/binder
aygıt düğümü çerçeve işlemlerine özel hale geldi ve bu nedenle satıcı işlemlerine erişilemez hale geldi. Bunun yerine satıcı işlemleri /dev/hwbinder
kullanmalı ve tüm AIDL arayüzlerini HIDL'ye dönüştürmelidir. Satıcı işlemleri arasında AIDL arayüzlerini kullanmaya devam etmek isteyenler için bağlayıcı etki alanını /dev/vndbinder
kullanın.
IPC Alanı | Tanım |
---|---|
/dev/binder | AIDL arayüzleriyle çerçeve/uygulama işlemleri arasındaki IPC |
/dev/hwbinder | HIDL arayüzleriyle çerçeve/satıcı işlemleri arasındaki IPC HIDL arayüzleriyle satıcı işlemleri arasında IPC |
/dev/vndbinder | AIDL Arayüzleriyle satıcı/satıcı işlemleri arasındaki IPC |
SurfaceFlinger, AIDL arayüzlerini tanımlarken satıcı işlemleri, çerçeve işlemleriyle iletişim kurmak için yalnızca HIDL arayüzlerini kullanabilir. Mevcut AIDL arayüzlerini HIDL'ye dönüştürmek için önemsiz miktarda çalışma gereklidir. Neyse ki Android, kullanıcı alanı kitaplığı işlemlerinin bağlı olduğu libbinder
için ciltleyici sürücüsünün seçileceği bir yöntem sağlar.
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));
Not: Satıcı işlemleri, Process
veya IPCThreadState
öğesini çağırmadan veya herhangi bir ciltleyici çağrısı yapmadan önce bunu çağırmalıdır.
SELinux politikaları
Cihaz uygulaması tam tiz ise, SELinux satıcı işlemlerinin /dev/binder
kullanmasını engeller. Örneğin, bir EVS HAL örnek uygulaması hal_evs_driver
alanına atanır ve binder_device
alanına r/w izinleri gerektirir.
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
Ancak bu izinlerin eklenmesi, tam tizli bir cihaz için system/sepolicy/domain.te
dosyasında tanımlanan aşağıdaki asla izin vermeme kurallarını ihlal ettiğinden derleme hatasına neden olur.
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
, bir hatayı yakalamak ve geliştirmeye rehberlik etmek için sağlanan bir özelliktir. Yukarıda açıklanan Android 10 ihlalini çözmek için de kullanılabilir.
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)
Satıcı süreci olarak EVS HAL referans uygulamasını oluşturun
Referans olarak aşağıdaki değişiklikleri packages/services/Car/evs/Android.mk
dosyasına uygulayabilirsiniz. Açıklanan tüm değişikliklerin uygulamanız için işe yaradığını doğruladığınızdan emin olun.
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;