Análisis del principio de SurfaceFlinger
SurfaceFlinger es parte de Android Multimedia, que en la implementación de Android es un servicio que proporciona funcionalidad de compositor de superficies en todo el sistema para combinar superficies 2D y 3D de diferentes aplicaciones.
Cada aplicación puede corresponder a una o más interfaces gráficas, y a cada interfaz la llamamos superficie o ventana. En la imagen de arriba, podemos ver cuatro superficies, una es la interfaz principal, tres superficies representadas por rojo, verde y azul, y dos botones que en realidad son el contenido de la interfaz principal. Estos dos botones son en realidad el contenido de la interfaz de la página de inicio. La situación que debemos considerar es:
En la práctica, hay dos formas de fusionar estas superficies, una es usar la forma de fusión de software y la otra es usar la forma de fusión de hardware, el software La forma es nuestro SurfaceFlinger y la forma del hardware es Overlay.
Dado que fusionar contenido por hardware es relativamente sencillo, comencemos con la superposición. Tomando IMX51 como ejemplo, cuando la IPU solicita FB desde el kernel, solicitará 3 FB, uno para la pantalla principal, uno para la pantalla secundaria y otro para superposición. En pocas palabras, Overlay significa que enviamos datos de formato e información de control aceptable para el hardware al Overlay FrameBuffer, y el controlador de hardware es responsable de fusionar el contenido del búfer de superposición y el búfer de la pantalla principal.
En términos generales, el hardware actual solo admite una superposición, que se utiliza principalmente para la reproducción de video y la vista previa de la cámara. Debido a que el contenido del video cambia constantemente, la combinación de hardware es mucho más eficiente que la combinación de software. SurfaceFlinger solo es responsable de fusionar los controles de Surface, como calcular el área de superposición de dos Surface, mientras que el contenido que Surface necesita mostrar se calcula mediante skia, opengl y pixflinger.
Proceso de creación
SurfaceFlinger es una clase de hilo que hereda de la clase Thread. Cuando crea un servicio SurfaceFlinger, se inicia un subproceso de escucha de SurfaceFlinger que espera a que se produzcan eventos, como un giro de superficie o un cambio de tamaño y posición de ventana. Una vez que ocurren estos eventos, SurfaceComposerClient emitirá señales a través de IBinder y el subproceso eventualmente esperará a que se manejen estos eventos y continuará esperando después de que se manejen los eventos, y así sucesivamente.
SurfaceComposerClient y SurfaceFlinger se sincronizan con señales a través de la clase SurfaceFlingerSynchro, que en realidad es solo una variable de condición. El hilo de escucha espera a que el valor de la variable de condición cambie a ABRIR, luego finaliza la espera y establece la variable de condición en CERRAR, y luego procesa el evento. Una vez completado el procesamiento, continúa esperando el valor de la condición. variable para cambiar a OPEN, y Surface del cliente notifica a SurfaceFlinger a través de IBinder. Cuando Surface cambia, el valor de la variable de condición cambia a OPEN y activa el hilo en espera, logrando así la sincronización de la señal a través del hilo.
El procesamiento de los cambios de estado de la ventana es un proceso muy complejo. SurfaceFlinger simplemente ejecuta las instrucciones del Administrador de Windows y decide cómo manejar los cambios ocasionales de tamaño, posición, transparencia y cómo ajustar el orden de las ventanas. capas SurfaceFlinger Simplemente lleva a cabo sus instrucciones. SurfaceFlinger simplemente sigue sus instrucciones.
Los controles comunes de Android, como TextView, Button y CheckBox, dibujan su interfaz de usuario en la parte superior de la superficie de dibujo de la ventana del host, lo que significa que su interfaz de usuario se dibuja en el hilo principal de la aplicación. Además de dibujar la interfaz de usuario, el hilo principal de la aplicación también debe responder a la entrada del usuario de manera oportuna; de lo contrario, el sistema pensará que la aplicación no responde. Para algunas pantallas de juegos o vistas previas de cámaras y reproducción de videos, la interfaz de usuario es más compleja y requiere un dibujo eficiente. Para aquellas vistas que requieren una interfaz de usuario compleja y eficiente, es importante generar una superficie de dibujo separada y utilizar un hilo separado para dibujar la interfaz de usuario de estas vistas.
El servicio SurfaceFlinger se ejecuta en el proceso del sistema Android y es responsable de administrar el búfer de fotogramas del sistema Android. Las aplicaciones de Android deben comunicarse con el servicio SurfaceFlinger para dibujar su interfaz de usuario en el búfer de fotogramas del sistema.
En el lado de la aplicación que realiza el dibujo, los datos obviamente se dibujan en el espacio de proceso de la aplicación, pero la ventana de vista debe mezclarse con la capa SurfaceFlinger para generar el cuadro final, y SurfaceFlinger está en otro servicio independiente Se ejecuta en el proceso, entonces, ¿cómo se transfieren los datos de visualización entre los dos procesos? Qué, la comunicación ordinaria de Binder definitivamente no funcionará, porque Binder no es adecuado para una cantidad tan grande de comunicación de datos, entonces, ¿qué método IPC se utiliza para la comunicación de datos de View? La respuesta es memoria compartida, o más exactamente, memoria compartida anónima. La memoria compartida es un mecanismo IPC que viene con Linux y adopta directamente este modo, pero realiza sus propias mejoras, formando así Android Anonymous Shared Memory-Ashmem. A través de Ashmem, el proceso de la APLICACIÓN y SurfaceFlinger**** usan una memoria, por lo que no es necesario copiar datos. El lado de la APLICACIÓN extrae, notifica al lado de SurfaceFlinger para que los sintetice y luego los envía a la pantalla del hardware.
Agregue una *** memoria compartida anónima para transmitir metadatos de la interfaz de usuario a la conexión entre cada aplicación de Android y el servicio SurfaceFlinger. La *** memoria compartida es SharedClient
En cada SharedClient, hay hasta 31 SharedBufferStack SharedBufferStack es la pila de búfer de aplicaciones de Android y SurfaceFlinger. SharedBufferStack es una pila de búfer para aplicaciones de Android y SurfaceFlinger.
Por lo general, utilizamos una técnica llamada "doble almacenamiento en búfer" al dibujar la interfaz de usuario. El almacenamiento en búfer doble se refiere al uso de dos búfer, uno de los cuales se llama búfer frontal (Búfer frontal) y el otro se llama búfer posterior (Búfer posterior). La interfaz de usuario siempre se dibuja primero en el búfer posterior y luego en el búfer frontal. buffer intercambiado y luego presentado al dispositivo de visualización. Ahora puede comprender el significado de SharedBufferStack. El servicio SurfaceFlinger simplemente sublima y abstrae la tecnología tradicional de "doble almacenamiento en búfer" en SharedBufferStack. Con SharedBufferStack, el servicio SurfaceFlinger puede dibujar la interfaz de usuario utilizando la tecnología N-buffer, con valores que van de 2 a 16. Por ejemplo, en Android 2.3, el valor de N es igual a 2 y en Android 4.1, el valor de N es igual a 3.
En el servicio SurfaceFlinger, cada SharedBufferStack corresponde a una Surface, es decir, una ventana. De esta manera, podemos entender por qué cada SharedClient contiene una serie de SharedBufferStacks en lugar de un único SharedBufferStack: un SharedClient corresponde a una aplicación de Android, y una aplicación de Android puede contener varias ventanas, es decir, Surfaces,
SharedBufferStack El Los búferes solo se utilizan para describir los metadatos de la interfaz de usuario, lo que significa que no contienen datos reales de la interfaz de usuario. Los datos reales de la interfaz de usuario se almacenan en un GraphicBuffer, que describiremos más adelante. Por lo tanto, para describir completamente la interfaz de usuario, cada búfer que se ha utilizado en SharedBufferStack corresponde a un GraphicBuffer que describe los datos reales de la interfaz de usuario. Cuando el servicio SurfaceFlinger almacena en caché el Buffer-1 y el Buffer-2, encuentra el GraphicBuffer correspondiente para poder dibujar la interfaz de usuario correspondiente.
Cuando una aplicación de Android necesita actualizar una Surface, encuentra su SharedBufferStack correspondiente y elimina un búfer libre del final de su lista de búferes libres, que se supone que es un índice numerado. Luego, la aplicación de Android solicita al servicio SurfaceFlinger que asigne un GraphicBuffer para el búfer con el número de índice.
Después de que el servicio SurfaceFlinger asigna el búfer de gráficos GraphicBuffer, establece su número en el índice y luego devuelve el búfer de gráficos GraphicBuffer a la aplicación de Android para su acceso. La aplicación de Android obtiene el búfer de gráficos devuelto por el servicio SurfaceFlinger y escribe datos de la interfaz de usuario en él. Después de escribir, el búfer correspondiente (es decir, el índice del número de búfer) se insertará en el encabezado de la lista de búfer usados en el SharedBufferStack correspondiente. Una vez hecho esto, la aplicación de Android notificará al servicio SurfaceFlinger para que dibuje el búfer usado descrito por GraphicBuffer. Tomando el ejemplo anterior como ejemplo, el servicio SurfaceFlinger necesita dibujar el GraphicBuffer correspondiente a los buffers numerados 1 y 2. Debido a que el servicio SurfaceFlinger sabe dónde están los búferes de gráficos para los búferes numerados 1 y 2, la aplicación de Android solo necesita indicarle al servicio SurfaceFlinger el número del búfer en el que dibujar. Cuando se extrae un búfer usado, vuelve a ser un búfer libre.
SharedBufferStack es compartido por aplicaciones de Android y servicios SurfaceFlinger***, pero específicamente, las aplicaciones de Android y los servicios SurfaceFlinger usan SharedBufferStack de manera diferente. Una aplicación de Android se preocupa por su lista de buffers libres, mientras que el servicio SurfaceFlinger se preocupa por su lista de buffers usados. Desde la perspectiva del servicio SurfaceFlinger, los buffers usados almacenados en SharedBufferStack en realidad están en cola para renderizarse.
Para facilitar el acceso de las aplicaciones de Android y los servicios SurfaceFlinger a SharedBufferStack, Android utiliza SharedBufferClient y SharedBufferServer respectivamente para describir SharedBufferStack. El sistema Android usa SharedBufferClient y SharedBufferServer respectivamente para describir SharedBufferStack. SharedBufferClient se usa en el lado de la aplicación de Android para acceder a la lista de búfer libre de SharedBufferStack, mientras que SharedBufferServer se usa en el servidor SurfaceFlinger para acceder a la lista de búfer de cola de SharedBufferStack.
Siempre que el número de buffers disponibles en SharedBufferStack sea mayor que 0, SharedBufferClient moverá la cola del puntero un paso hacia adelante y disminuirá el valor de los buffers disponibles para obtener buffers libres disponibles. Cuando una aplicación de Android escribe en un búfer libre, lo agrega al final de la lista de búferes de cola en SharedBufferStack, en la siguiente posición del puntero queue_head, a través de SharedBufferClient.
Cuando la aplicación de Android notifica al servicio SurfaceFlinger que actualice la interfaz de usuario, siempre que el número de búferes en cola en el SharedBufferStack correspondiente sea mayor que 0, SharedBufferServer dibujará el siguiente búfer en el encabezado del puntero y moverá el avance la cabeza del puntero un paso y disminuya el valor en cola en 1.
Referencia:
/luoshengyang/article/details/7846923