HAL de la cámara del vehículo

Android contiene una capa de abstracción de hardware (HAL) HIDL automotriz que Permite la captura y visualización de imágenes en las primeras etapas del proceso de inicio de Android. y sigue funcionando durante toda la vida del sistema. La HAL incluye una pila de sistema de visión exterior (EVS) que, por lo general, se usa para admitir la vista posterior. Pantallas de cámara y vista envolvente en vehículos con vehículos integrados en el vehículo basados en Android Sistemas de infoentretenimiento (IVI). EVS también permite implementar funciones avanzadas en las apps del usuario.

Android también incluye un controlador de captura y pantalla específico de EVS (en /hardware/interfaces/automotive/evs/1.0). Mientras esté Es posible compilar una app de cámara retrovisora sobre una de Android existente. servicios de cámara y visualización, esa aplicación probablemente se ejecutaría demasiado tarde el proceso de inicio de Android. El uso de una HAL dedicada permite una interfaz optimizada y deja en claro lo que un OEM debe implementar para admitir la pila de EVS.

Componentes del sistema

EVS incluye los siguientes componentes del sistema:

Sistema EVS
diagrama de componentes
Figura 1: Descripción general de los componentes del sistema EVS

App de EVS

Una app de ejemplo de EVS de C++ (/packages/services/Car/evs/app) sirve como referencia. para implementarlos. Esta app se encarga de solicitar fotogramas de video a el administrador de EVS y enviar los fotogramas finalizados para que se muestren de vuelta al administrador de EVS. Se espera que se inicie con init en cuanto el EVS y el servicio de vehículos estén disponibles, orientadas dentro de los dos (2) segundos posteriores al encendido. Los OEM pueden modificar o reemplazar el EVS app como desees.

Administrador de EVS

El administrador de EVS (/packages/services/Car/evs/manager) proporciona los componentes básicos que necesita una aplicación de EVS para implementar cualquier cosa, desde un una simple pantalla de cámara posterior hasta una renderización de varias cámaras 6DOF. Su interfaz se presenta a través de HIDL y está diseñado para aceptar múltiples clientes simultáneos. Otras apps y servicios (específicamente, el servicio de vehículos) pueden consultar el EVS Estado del administrador para saber cuándo el sistema EVS está activo.

Interfaz HIDL de EVS

El sistema EVS, tanto los elementos de cámara como los de pantalla, se define en la android.hardware.automotive.evs. Una implementación de muestra que utiliza la interfaz (genera imágenes de prueba sintéticas y valida el imágenes en el recorrido de ida y vuelta) se proporcionan en /hardware/interfaces/automotive/evs/1.0/default

El OEM es responsable de implementar la API expresada en los archivos .hal. en /hardware/interfaces/automotive/evs. Estas implementaciones son de configurar y recopilar datos de cámaras físicas y a través de búferes de memoria compartida reconocibles por Gralloc. La pantalla de la implementación se encarga de proporcionar un búfer de memoria compartido que puede completar la app (generalmente con renderización EGL) y presentar los marcos terminados, en lugar de todo lo que quieras que aparezca la pantalla física. Las implementaciones de proveedores de la interfaz de EVS pueden almacenarse en /vendor/… /device/… o hardware/… (p.ej., /hardware/[vendor]/[platform]/evs).

Controladores de kernel

Un dispositivo que admite la pila de EVS requiere controladores de kernel. En lugar de creando nuevos controladores, los OEM tienen la opción de admitir las funciones requeridas por EVS a través de controladores existentes de hardware de cámara o pantalla. Reutilizar controladores podría ser ventajoso, especialmente para los controladores de Display, donde la presentación de imágenes puede que requieran coordinación con otros subprocesos activos. Android 8.0 incluye una versión basada en v4l2 controlador de ejemplo (en packages/services/Car/evs/sampleDriver) que depende del kernel para ser compatible con v4l2 y de SurfaceFlinger para presentar la imagen de salida.

Descripción de la interfaz de hardware de EVS

En esta sección, se describe la HAL. Se espera que los proveedores implementaciones de esta API adaptadas a su hardware.

IEvsEnumerator

Este objeto es responsable de enumerar el hardware de EVS disponible en el (una o más cámaras y un solo dispositivo de visualización).

getCameraList() generates (vec<CameraDesc> cameras);

Devuelve un vector que contiene descripciones de todas las cámaras del sistema. Sí se supone que el conjunto de cámaras es fijo y se puede conocer al momento del inicio. Para obtener detalles descripciones de las cámaras, consulta CameraDesc.

openCamera(string camera_id) generates (IEvsCamera camera);

Obtiene un objeto de interfaz que se usa para interactuar con una cámara específica que se identifica a través de la cadena única de camera_id. Muestra un valor NULL en caso de error. Los intentos de volver a abrir una cámara que ya está abierta no pueden fallar. Para evitar carrera condiciones asociadas con el inicio y el cierre de la app, y la reapertura de una cámara debería cerrar la instancia anterior para que se pueda entregar la nueva solicitud. R instancia de cámara interrumpida de esta forma debe colocarse en un estado a la espera de la destrucción final y respondiendo a cualquier solicitud de afectar al el estado de la cámara con un código de retorno de OWNERSHIP_LOST.

closeCamera(IEvsCamera camera);

Libera la interfaz IEvsCamera (y es opuesta la openCamera()). La transmisión de video de la cámara se debe se detuvo llamando a stopVideoStream() antes de llamar a closeCamera.

openDisplay() generates (IEvsDisplay display);

Obtiene un objeto de interfaz que se usa para interactuar exclusivamente con la API del sistema Pantalla de EVS Solo un cliente puede tener una instancia funcional de IEvsDisplay en tiempo. De manera similar al comportamiento de apertura agresiva que se describe en openCamera, se puede crear un objeto IEvsDisplay nuevo en cualquier momento e inhabilita individuales. Las instancias invalidadas siguen existiendo y responden a llamadas a función de sus propietarios, pero no debe realizar operaciones de mutación cuando fallecen. Con el tiempo, se espera que la app cliente detecte el error OWNERSHIP_LOST los códigos de retorno y cerrar y liberar la interfaz inactiva.

closeDisplay(IEvsDisplay display);

Libera la interfaz IEvsDisplay (y es opuesto al openDisplay()). Los búferes pendientes recibidos con Las llamadas de getTargetBuffer() se deben devolver a la pantalla antes cerrando la pantalla.

getDisplayState() generates (DisplayState state);

Obtiene el estado de visualización actual. La implementación del HAL debe informar estado actual real, que podría diferir del estado solicitado más recientemente. La lógica responsable de cambiar los estados de la pantalla debe existir encima del dispositivo. por lo que no desea que la implementación de HAL cambie espontáneamente estados de visualización. Si ningún cliente mantiene la pantalla actualmente (mediante una llamada a openDisplay), esta función muestra NOT_OPEN. De lo contrario, informa el estado actual de la pantalla de EVS (consulta API de IEvsDisplay).

struct CameraDesc {
    string      camera_id;
    int32       vendor_flags;       // Opaque value
}
  • camera_id Es una cadena que identifica de forma única una cámara determinada. Puede ser el nombre del dispositivo de kernel o un nombre para el dispositivo, como revisión. La implementación de HAL elige el valor de esta cadena y se usa opacamente en la pila de arriba.
  • vendor_flags Un método para pasar el ID de cámara especializado información opaca desde el conductor hasta una aplicación de EVS personalizada. Se aprueba. no se puede interpretar desde el conductor hasta la app de EVS, que se puede ignorar que la modifica.

IEvsCamera

Este objeto representa una sola cámara y es la interfaz principal de para capturar imágenes.

getCameraInfo() generates (CameraDesc info);

Muestra CameraDesc de esta cámara.

setMaxFramesInFlight(int32 bufferCount) generates (EvsResult result);

Especifica la profundidad de la cadena de búfer que se solicita que admita la cámara. Hasta el cliente de IEvsCamera puede retener esta cantidad de fotogramas al mismo tiempo. Si esta muchos fotogramas se entregaron al receptor sin ser devueltos por doneWithFrame: La transmisión omite fotogramas hasta que se muestra un búfer. para reutilizarlo. Es legal que esta llamada se realice en cualquier momento, incluso mientras las transmisiones ya se están ejecutando, en cuyo caso los búferes se deben agregar o quitar de la cadena según corresponda. Si no se realizan llamadas a este punto de entrada, IEvsCamera admite al menos un fotograma de forma predeterminada; sea más aceptable.

Si no se puede admitir el bufferCount solicitado, la función muestra BUFFER_NOT_AVAILABLE o algún otro código de error relevante. En este caso, el sistema seguirá funcionando con el valor establecido previamente.

startVideoStream(IEvsCameraStream receiver) generates (EvsResult result);

Solicita la entrega de fotogramas de la cámara EVS de esta cámara. IEvsCameraStream comienza a recibir llamadas periódicas con nuevos marcos de imagen hasta Se llama a stopVideoStream(). Los marcos deben comenzar a publicarse en un plazo de 500 ms desde la llamada a startVideoStream y después del inicio, debe generados a un mínimo de 10 FPS. El tiempo necesario para iniciar la transmisión de video por Internet se considera eficazmente contra cualquier requisito de tiempo de inicio de la cámara retrovisora. Si el botón no se inicia una transmisión continua, se debe mostrar un código de error. De lo contrario, se muestra OK.

oneway doneWithFrame(BufferDesc buffer);

Devuelve un fotograma que se envió a IEvsCameraStream. Cuando hayas terminado consumiendo un fotograma entregado a la interfaz IEvsCameraStream, el fotograma debe se devuelve a IEvsCamera para su reutilización. Una cantidad pequeña y finita de búferes disponible (posiblemente tan pequeña como una) y, si se agota, no más las tramas se entregan hasta que se devuelve un búfer, lo que puede dar como resultado fotogramas omitidos (un búfer con un controlador nulo denota el final de una transmisión y no no es necesario devolverlos a través de esta función). Devuelve OK si la operación es exitosa, o código de error adecuado, que posiblemente incluya INVALID_ARG o BUFFER_NOT_AVAILABLE

stopVideoStream();

Detiene la publicación de fotogramas de la cámara EVS. Debido a que la entrega es asíncrona, Es posible que los fotogramas sigan llegando durante un tiempo después de que se regrese esta llamada. Cada marco se debe devolver hasta que se indique el cierre de la transmisión al IEvsCameraStream. Es legal llamar a stopVideoStream en una transmisión que ya se detuvo o que nunca se inició, en cuyo caso se ignora.

getExtendedInfo(int32 opaqueIdentifier) generates (int32 value);

Solicita información específica del controlador de la implementación de HAL. Valores permitidos para opaqueIdentifier son específicos del controlador, pero no tienen valores que se aprueban podría causar una falla en el controlador. El conductor debe mostrar 0 para cualquier error no reconocido opaqueIdentifier

setExtendedInfo(int32 opaqueIdentifier, int32 opaqueValue) generates (EvsResult result);

Envía un valor específico del controlador a la implementación de HAL. Esta extensión es se proporciona solo para facilitar extensiones específicas del vehículo, sin HAL. implementación debería requerir que esta llamada funcione en un estado predeterminado. Si el botón el controlador reconoce y acepta los valores, y se debe mostrar OK; de lo contrario Se debe mostrar INVALID_ARG o algún otro código de error representativo.

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
}

Describe una imagen que se pasó a través de la API. La unidad HAL es responsable de esta estructura para describir el búfer de imagen y el cliente HAL debería tratar esta estructura como de solo lectura. Los campos contienen suficiente información. para permitir que el cliente reconstruya un objeto ANativeWindowBuffer, según sea necesario para usar la imagen con EGL con el eglCreateImageKHR().

  • width Es el ancho en píxeles de la imagen presentada.
  • height Es la altura en píxeles de la imagen presentada.
  • stride El número de píxeles que cada fila ocupa en la memoria, y considerar el relleno para la alineación de las filas. Expresado en píxeles para coincidir la convención adoptada por gralloc para sus descripciones de búfer.
  • pixelSize la cantidad de bytes que ocupa cada píxel individual, lo que permite calcular el tamaño en bytes necesarios para pasar de una fila a otra en la imagen (stride en bytes = stride en píxeles * pixelSize).
  • format Formato de píxeles que usa la imagen. El formato proporcionado Debe ser compatible con la implementación de OpenGL de la plataforma. Para aprobar las pruebas de compatibilidad, HAL_PIXEL_FORMAT_YCRCB_420_SP debe preferido para el uso de la cámara, y RGBA o BGRA deben para la visualización.
  • usage Marcas de uso establecidas por la implementación de HAL. Clientes HAL se espera que pasen estos sin modificar (para obtener más información, consulta marcas relacionadas con Gralloc.h).
  • bufferId Un valor único especificado por la implementación de HAL para permiten que se reconozca un búfer después de un recorrido de ida y vuelta a través de las APIs de HAL. El almacenado en este campo puede ser elegido de forma arbitraria por la implementación de HAL.
  • memHandle El controlador del búfer de memoria subyacente que contiene los datos de la imagen. La implementación de HAL puede optar por almacenar un Gralloc del controlador de búfer.

Novedades de la cámara IEvs

El cliente implementa esta interfaz para recibir fotogramas de video asíncronos entregas.

deliverFrame(BufferDesc buffer);

Recibe llamadas del sistema HAL cada vez que un fotograma está listo para inspeccionarse. Los controladores del búfer recibidos por este método se deben devolver a través de llamadas a IEvsCamera::doneWithFrame() Cuando se detiene la transmisión de video por Internet con un llamada a IEvsCamera::stopVideoStream(), es posible que esta devolución de llamada continúe cuando se agota la canalización. Se debe devolver cada fotograma. cuando el último fotograma de la transmisión, se entrega un bufferHandle NULL que indica el final de la transmisión y no se realizan más entregas de fotogramas. El valor NULL No es necesario devolver el dispositivo bufferHandle con doneWithFrame(), pero se deben mostrar todos los demás identificadores

Si bien los formatos de búfer de propiedad son técnicamente posibles, la compatibilidad las pruebas requieren que el búfer esté en uno de los cuatro formatos compatibles: NV21 (YCrCb) 4:2:0 semiplanar), YV12 (YCrCb 4:2:0 planar), YUYV (YCrCb 4:2:2 intercalado), RGBA (32 bits R:G:B:x), BGRA (32 bits B:G:R:x). El formato seleccionado debe ser un Fuente de texturas GL en la implementación de GLES de la plataforma

La app no debe depender de ninguna correspondencia. entre el campo bufferId y el memHandle en el BufferDesc. Los valores de bufferId son Esencialmente privada para la implementación del controlador de HAL, y puede usar (y reutilizar) con ellos como estime conveniente.

IEvsDisplay

Este objeto representa la pantalla de Evs, controla el estado de la pantalla, y maneja la presentación real de las imágenes.

getDisplayInfo() generates (DisplayDesc info);

Devuelve información básica sobre la pantalla de EVS proporcionada por el sistema (consulta DisplayDesc).

setDisplayState(DisplayState state) generates (EvsResult result);

Establece el estado de visualización. Los clientes pueden configurar el estado de visualización para expresar el deseado, y la implementación de HAL debe aceptar correctamente una solicitud de cualquier estado mientras se encuentre en cualquier otro, aunque la respuesta puede ser ignorar el para cada solicitud.

Después de la inicialización, la pantalla se define para comenzar en la Estado NOT_VISIBLE, después del cual se espera que el cliente solicite el estado VISIBLE_ON_NEXT_FRAME y comenzará a proporcionar video. Cuando ya no se requiere visualización, se espera que el cliente solicite el NOT_VISIBLE después de pasar el último fotograma de video.

Es válida para cualquier estado que se solicite en cualquier momento. Si la pantalla es ya está visible, debería permanecer visible si se establece en VISIBLE_ON_NEXT_FRAME Siempre devuelve OK, a menos que el estado solicitado es un valor de enumeración no reconocido, en cuyo caso INVALID_ARG es que se devuelven.

getDisplayState() generates (DisplayState state);

Obtiene el estado de visualización. La implementación del HAL debe informar actual, que podría diferir del estado solicitado más recientemente. El La lógica responsable de cambiar los estados de la pantalla debe existir encima del dispositivo. por lo que no desea que la implementación de HAL cambie espontáneamente estados de visualización.

getTargetBuffer() generates (handle bufferHandle);

Devuelve un controlador para un búfer de fotogramas asociado con la pantalla. Este búfer puede estar bloqueado y escrito por software o GL. Se debe mostrar este búfer con una llamada a returnTargetBufferForDisplay(), incluso si la pantalla está ya no está visible.

Si bien los formatos de búfer de propiedad son técnicamente posibles, las pruebas de compatibilidad requiere que el búfer esté en uno de los cuatro formatos admitidos: NV21 (YCrCb 4:2:0). semiplanar), YV12 (YCrCb 4:2:0 plano), YUYV (YCrCb 4:2:2 intercalado), RGBA (R:G:B:x de 32 bits), BGRA (32 bits B:G:R:x). El formato seleccionado debe ser un GL válido el objetivo de renderización en la implementación de GLES de la plataforma.

En caso de error, se muestra un búfer con un controlador nulo, pero ese búfer no se deben devolver a returnTargetBufferForDisplay.

returnTargetBufferForDisplay(handle bufferHandle) generates (EvsResult result);

Indica a la pantalla que el búfer está listo para mostrarse. Solo se recuperaron los búferes mediante una llamada a getTargetBuffer() son válidos para usarse con esto llamada y el contenido de la BufferDesc no podrá ser modificado por la app cliente. Después de esta llamada, el búfer ya no es válido para que lo usen al cliente. Devuelve OK si la operación se realiza correctamente o muestra un código de error adecuado. incluidos INVALID_ARG o BUFFER_NOT_AVAILABLE.

struct DisplayDesc {
    string  display_id;
    int32   vendor_flags;  // Opaque value
}

Describe las propiedades básicas de una pantalla de EVS y requeridas por un EVS para implementarlos. La HAL es responsable de completar esta estructura para describir la pantalla de EVS. Puede ser una pantalla física o virtual se superpone o mezcla con otro dispositivo de presentación.

  • display_id Es una cadena que identifica la visualización de forma exclusiva. Puede ser el nombre del dispositivo de kernel o el nombre del dispositivo, como revisión. La HAL elige el valor de esta cadena y la pila de arriba lo usa opacamente.
  • vendor_flags Un método para pasar el ID de cámara especializado información opaca desde el conductor hasta una aplicación de EVS personalizada. Se aprueba. no se puede interpretar desde el conductor hasta la app de EVS, que se puede ignorar que la modifica.
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
}

Describe el estado de la pantalla del EVS, que se puede inhabilitar (no visibles para el conductor) o habilitadas (mostrando una imagen al conductor). Incluye un estado transitorio en el que la pantalla aún no es visible, pero está preparada. sea visible con la entrega del siguiente fotograma de imágenes con el returnTargetBufferForDisplay() llamada.

Administrador de EVS

EVS Manager proporciona la interfaz pública al sistema EVS para recopilar y presentar vistas de cámaras externas. Dónde lo permiten los controladores de hardware solo una interfaz activa por recurso (cámara o pantalla), el administrador de EVS facilita el acceso compartido a las cámaras. Una sola aplicación principal de EVS se es el primer cliente del administrador de EVS y es el único cliente con permiso para escribir mostrar datos (se puede otorgar acceso de solo lectura a los clientes adicionales a la cámara imágenes).

El administrador de EVS implementa la misma API que los controladores de HAL subyacentes y proporciona un servicio expandido gracias a la compatibilidad con varios clientes simultáneos (más de un cliente puede abrir una cámara a través de EVS Manager y recibir un video transmisión).

EVS Manager y
Diagrama de la API de hardware de EVS.
Figura 2: EVS Manager replica los EVS subyacentes API de Hardware.

Las apps no experimentan diferencias cuando operan a través de la HAL de hardware de EVS o la API de EVS Manager, excepto que la API de EVS Manager acceso simultáneo a la transmisión de la cámara. El administrador de EVS es el que está permitido cliente de la capa de HAL de hardware de EVS y actúa como proxy para el hardware de EVS HAL.

En las siguientes secciones, solo se describen las llamadas que tienen una definición Comportamiento (extendido) en la implementación de EVS Manager las llamadas restantes son idénticos a las descripciones de la HAL de EVS.

IEvsEnumerator

openCamera(string camera_id) generates (IEvsCamera camera);

Obtiene un objeto de interfaz que se usa para interactuar con una cámara específica que se identifica a través de la cadena única de camera_id. Muestra un valor NULL en caso de error. En la capa de EVS Manager, siempre que haya suficientes recursos del sistema disponibles, una cámara que ya está abierta puede ser abierta de nuevo por otro proceso, lo que permite de la transmisión de video por Internet a varias apps de consumo. El Las cadenas camera_id de la capa de EVS Manager son las mismas que las informados a la capa de hardware de EVS.

IEvsCamera

La implementación de IEvsCamera que proporcionó EVS Manager se virtualiza internamente por lo que las operaciones en una cámara por parte de un cliente no afectan a otros clientes, lo que conservar el acceso independiente a sus cámaras.

startVideoStream(IEvsCameraStream receiver) generates (EvsResult result);

Inicia las transmisiones de video por Internet. Los clientes pueden iniciar y detener transmisiones de video por Internet de forma independiente. en la misma cámara subyacente. La cámara subyacente se inicia cuando iniciar el cliente.

doneWithFrame(uint32 frameId, handle bufferHandle) generates (EvsResult result);

Muestra un fotograma. Cada cliente debe devolver sus marcos cuando hayan terminado, pero pueden conservar sus marcos el tiempo que deseen. Cuando el recuento de fotogramas retenido por un cliente alcanza su límite configurado, no recibirá más fotogramas hasta que muestre uno. La omisión de este fotograma no afecta a otras que siguen recibiendo todos los marcos como se esperaba.

stopVideoStream();

Detiene una transmisión de video por Internet. Cada cliente puede detener su transmisión de video por Internet en cualquier momento sin afectar a otros clientes. La transmisión de la cámara subyacente en la capa de hardware es se detiene cuando el último cliente de una cámara determinada detiene su transmisión.

setExtendedInfo(int32 opaqueIdentifier, int32 opaqueValue) generates (EvsResult result);

Envía un valor específico del controlador, lo que podría permitir que un cliente afecte. con otro cliente. Debido a que EVS Manager no puede comprender las implicaciones de palabras de control definidas por el proveedor, no están virtualizadas y tiene efectos se aplican a todos los clientes de una cámara determinada. Por ejemplo, si un proveedor utilizó esta llamada para cambiar las velocidades de fotogramas, todos los clientes de la cámara de la capa de hardware afectada y recibirán fotogramas a la nueva tasa.

IEvsDisplay

Solo se permite un propietario de la pantalla, incluso a nivel de EVS Manager. El Manager no agrega ninguna funcionalidad y simplemente pasa la interfaz de IEvsDisplay. directamente a la implementación de la HAL subyacente.

App de EVS

Android incluye una implementación de referencia de C++ nativa de un EVS. app que se comunica con el administrador de EVS y la HAL del vehículo proporcionan funciones básicas de cámara de retroceso. Se espera que la app se inicie al principio del proceso de inicio del sistema, con un video adecuado según las cámaras disponibles y el estado del vehículo (estado de los cambios de velocidad y de la señal de giro). Los OEMs pueden modificar o reemplazar la app de EVS por una app la lógica y la presentación.

Figura 3: Lógica de muestra de la app de EVS, obtener la cámara lista.


Figura 4: de muestra de la app de EVS, Frame.

Debido a que los datos de imágenes se presentan a la app en un formato gráfico estándar, búfer, la app se encarga de mover la imagen desde el archivo en el búfer de salida. Si bien esto presenta el costo de copiar los datos, también ofrece la oportunidad para que la app renderice la imagen en la de visualización del búfer de la manera que desee.

Por ejemplo, la app puede optar por mover los datos de los píxeles, tal vez con una escala en línea o una operación de rotación. La app podría puedes usar la imagen de origen como textura OpenGL y renderizar de la escena al búfer de salida, incluidos los elementos virtuales, como los íconos, pautas y animaciones. Una aplicación más sofisticada también puede seleccionar varias cámaras de entrada simultáneas y combinarlas en un único marco de salida (por ejemplo, para usarse en una vista virtual cenital del entorno del vehículo).

Usar el EGL/SurfaceFlinger en la HAL de la pantalla de EVS

En esta sección, se explica cómo usar EGL para renderizar una implementación de HAL de pantalla de EVS en Android 10.

Un EVS La implementación de referencia de HAL usa EGL para renderizar la vista previa de la cámara. la pantalla y usa libgui para crear la superficie de renderización de EGL de destino. En Android 8 (y versiones posteriores), libgui se clasifica como VNDK-private, que hace referencia a un grupo de bibliotecas disponibles para las bibliotecas del VNDK que los procesos del proveedor no pueden usar. Debido a que las implementaciones de HAL deben residir en la partición del proveedor, los proveedores no pueden usar Plataforma en implementaciones de HAL.

Cómo compilar libgui para los procesos de los proveedores

El uso de libgui es la única opción para utilizar EGL/SurfaceFlinger. en las implementaciones de HAL de Display de EVS. La forma más directa de implementar libgui es a través de frameworks/native/libs/gui directamente con un destino de compilación adicional en la secuencia de comandos de compilación. Este objetivo es exactamente el mismo que el objetivo libgui, excepto por la adición de dos campos:

  • 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", ], …

Nota: Los destinos de proveedores se crean con la macro NO_INPUT, que quita una palabra de 32 bits de los datos de parcelas. Debido a que SurfaceFlinger espera que se haya quitado este campo, SurfaceFlinger no puede analizar el paquete. Esto se observa como una falla de 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

Para solucionar esta condición, sigue estos pasos:

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);

Compilación de ejemplo más abajo. Debes recibir un $(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

Cómo usar Binder en la implementación de la HAL de EVS

En Android 8 (y versiones posteriores), el nodo del dispositivo /dev/binder pasó a ser exclusivo del del framework y, por lo tanto, inaccesible para los procesos del proveedor. En cambio, los procesos del proveedor deben usar /dev/hwbinder y deben convertir cualquier interfaz de AIDL a HIDL. Para quienes quieran seguir usando las interfaces del AIDL entre los procesos de los proveedores, usa el dominio de Binder /dev/vndbinder.

Dominio de IPC Descripción
/dev/binder IPC entre procesos de framework o apps con interfaces AIDL
/dev/hwbinder Es una IPC entre los procesos del framework y del proveedor con interfaces HIDL.
IPC entre procesos de proveedores con interfaces HIDL
/dev/vndbinder La IPC entre los procesos del proveedor con interfaces AIDL

Si bien SurfaceFlinger define las interfaces del AIDL, los procesos del proveedor solo pueden usar interfaces HIDL para comunicarse con los procesos del framework. Se necesita una cantidad importante de trabajo para convertir El AIDL se conecta con HIDL. Afortunadamente, Android proporciona un método para seleccionar el Binder. controlador para libbinder, al que se vinculan los procesos de la biblioteca de espacio de usuario

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));

Nota: Los procesos del proveedor deben llamar así antes de llamar a Process o IPCThreadState, o antes de realizar llamadas a Binder.

Políticas de SELinux

Si la implementación del dispositivo es de agudo total, SELinux evita que procesos usen /dev/binder. Por ejemplo, una muestra de la HAL de EVS implementación se asigna al dominio hal_evs_driver y requiere Permisos de lectura/escritura para el dominio 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

Sin embargo, agregar estos permisos provoca un error de compilación porque infringe lo siguiente reglas nunca permiten definidas en system/sepolicy/domain.te para un dispositivo de agudos completos.

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 es un atributo proporcionado para detectar un error y guiar el desarrollo. También se puede usar para resolver la infracción de Android 10 descrita anteriormente.

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)

Compila una implementación de referencia de la HAL de EVS como un proceso de proveedor

Como referencia, puedes aplicar los siguientes cambios a packages/services/Car/evs/Android.mk Asegúrate de confirmar lo siguiente: todos los cambios descritos funcionan para tu implementación.

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;