En esta página, se describen los cambios en el controlador de Binder de Android 8. Se proporcionan detalles sobre el uso de IPC de Binder y enumera la política de SELinux requerida.
Cambios en el controlador de Binder
A partir de Android 8, el framework y las HAL de Android se comunican con entre sí mediante Binder. Como esta comunicación aumenta drásticamente, de tráfico, Android 8 incluye varias mejoras diseñadas para mantener IPC de Binder rápido. Los proveedores de SoC y los OEMs deben combinarse directamente de las ramas relevantes de android-4.4, android-4.9 y versiones posteriores de la kernel/common.
Varios dominios de Binder (contextos)
Common 4.4 y versiones posteriores, incluido el upstreamPara dividir de forma clara el tráfico de Binder entre el framework (independiente del dispositivo) y (específico del dispositivo), Android 8 introdujo el concepto de un vinculador. contextual. Cada contexto de Binder tiene su propio nodo de dispositivo y su propio contexto (de servicio). Puedes acceder a Context Manager solo desde el dispositivo al que pertenece y, cuando se pasa un nodo Binder a través de un determinado se puede acceder desde ese mismo contexto solo por otro proceso, por lo tanto, y aislar por completo los dominios entre sí. Para obtener detalles sobre el uso, consulta vndbinder y vndservicemanager.
Dispersión
Common 4.4 y versiones posteriores, incluido el upstreamEn las versiones anteriores de Android, se copiaban todos los datos de una llamada a Binder. tres veces:
- Una vez para serializarlos
Parcel
en el proceso de llamada - Una vez en el controlador de kernel para copiar
Parcel
en el destino proceso - Una vez para anular la serialización de
Parcel
en el proceso de destino
Android 8 usa
dispersión-recopilación
para reducir la cantidad de copias de 3 a 1. En lugar de
serializar datos en un Parcel
primero, los datos permanecen en su original
el diseño de memoria y la estructura, y el controlador lo copia de inmediato en el destino
el proceso de administración de recursos. Una vez que los datos están en el proceso objetivo, la estructura y la memoria
el diseño es el mismo y los datos se pueden leer sin requerir otra copia.
Bloqueo detallado
Common 4.4 y versiones posteriores, incluido el upstreamEn versiones anteriores de Android, el controlador de Binder usaba un bloqueo global para proteger contra el acceso simultáneo a estructuras de datos críticas. Si bien había mínimo para el bloqueo, el problema principal era que si un subproceso de baja prioridad obtuvo el candado y se adelantó, esto podría retrasar subprocesos con mayor prioridad necesarios para obtener el mismo bloqueo. Esto provocó bloqueos en la plataforma.
Los intentos iniciales de resolver este problema incluyeron deshabilitar la interrupción mientras manteniendo el candado global. Sin embargo, se trataba más de un truco que de una verdadera solución. y, finalmente, fue rechazada por el upstream y se descartó. Intentos posteriores se enfoca en hacer que el bloqueo sea más detallado, una versión de la cual se ha en dispositivos Pixel desde enero de 2017. Si bien la mayoría de esos cambios fueron se hicieron públicas, se hicieron mejoras sustanciales en versiones posteriores.
Después de identificar problemas pequeños en la implementación de bloqueo detallada, ideó una solución mejorada con una arquitectura de bloqueo diferente y envió los cambios en todas las ramas comunes de kernel. Seguimos probando esto en una gran cantidad de dispositivos diferentes; ya que no conocemos problemas pendientes, esta es la implementación recomendada para el envío de dispositivos con Android 8.
Herencia de prioridad en tiempo real
Common-4.4 y common-4.9 (ascendente próximamente)El controlador de Binder siempre admitió una herencia de prioridad agradable. Como cada vez más procesos en Android que se ejecutan con prioridad en tiempo real, en algunos casos, ahora tiene sentido que, si un subproceso en tiempo real realiza una llamada a Binder, el en el proceso que controla esa llamada también se ejecuta con prioridad en tiempo real. Para para estos casos de uso, Android 8 ahora implementa la herencia de prioridad en tiempo real en el controlador de Binder.
Además de la herencia de prioridad a nivel de transacción, la prioridad de nodos herencia permite que un nodo (objeto de servicio de Binder) especifique un la prioridad con la que se deben ejecutar las llamadas a este nodo. Versiones anteriores de Android ya admitía la herencia de prioridad de nodo con valores agradables, pero En Android 8, se agrega compatibilidad con la herencia de nodos de políticas de programación en tiempo real.
Cambios en el espacio del usuario
Android 8 incluye todos los cambios de espacio del usuario necesarios para trabajar con la versión
controlador de Binder en el kernel común con una excepción: el controlador original
para inhabilitar la herencia de prioridad en tiempo real
/dev/binder
usó un
ioctl El desarrollo posterior cambió el control de prioridad.
la herencia a un método más detallado que sea por modo de Binder (y no por
contexto). Por lo tanto, ioctl no está en la rama común de Android y es
en nuestros kernels comunes.
El efecto de este cambio es que la herencia de prioridad en tiempo real se inhabilita
predeterminado para todos los nodos. El equipo de rendimiento de Android descubrió
beneficioso para habilitar la herencia de prioridad en tiempo real para todos los nodos de la
hwbinder
. Para lograr el mismo efecto,
este cambio en el espacio de usuario.
SHAs para kernels comunes
Para obtener los cambios necesarios en el controlador de Binder, sincronízalo con el SHA correspondiente:
- Común-3.18
cc8b90c121de ANDROID: binder: no verificas los permisos prioritarios durante el restablecimiento. - Común-4.4
76b376eac7a2 ANDROID: binder: no verifica los permisos prioritarios durante el restablecimiento. - Común-4.9
ecd972d4f9b5 ANDROID: binder: no verificas los permisos prioritarios durante el restablecimiento.
Trabaja con IPC de Binder
Históricamente, los procesos de los proveedores han utilizado comunicación entre procesos de Binder
(IPC) para comunicarse. En Android 8, el nodo del dispositivo /dev/binder
se vuelve exclusivo de los procesos del framework, lo que significa que los procesos de los proveedores ya no
tengan acceso a ellos. Los procesos del proveedor pueden acceder a /dev/hwbinder
, pero
deben convertir sus interfaces de AIDL para usar HIDL. Para los proveedores que desean continuar
usando interfaces de AIDL entre procesos del proveedor, Android admite Binder IPC como
que se describe a continuación. En Android 10, el AIDL estable permite
procesos para usar /dev/binder
y, al mismo tiempo, resolver los problemas de estabilidad
garantiza que se resuelvan HIDL y /dev/hwbinder
. Cómo usar el canal estable
AIDL, consulta
AIDL para HAL:
vndbinder
Android 8 admite un nuevo dominio de Binder para servicios de proveedores, a los que se accede
con /dev/vndbinder
en lugar de /dev/binder
. Con la
además de /dev/vndbinder
, Android ahora tiene los siguientes tres
Dominios de IPC:
Dominio de IPC | Descripción |
---|---|
/dev/binder |
IPC entre procesos de framework o apps con interfaces AIDL |
/dev/hwbinder |
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 |
Para que aparezca /dev/vndbinder
, asegúrate de que la configuración del kernel
Se estableció el elemento CONFIG_ANDROID_BINDER_DEVICES
como
"binder,hwbinder,vndbinder"
(esta es la configuración predeterminada en
árboles de kernel común).
Por lo general, los procesos de los proveedores no abren el controlador de Binder directamente, sino
con la biblioteca de espacio de usuario libbinder
, que abre la
controlador de Binder. Agregando un método para ::android::ProcessState()
selecciona el controlador de Binder para libbinder
. Los procesos de los proveedores deben
Llama a este método antes de llamar a ProcessState,
.
IPCThreadState
o antes de realizar llamadas a Binder en general Para
usa, realiza la siguiente llamada después de la main()
de un proceso de proveedor
(cliente y servidor):
ProcessState::initWithDriver("/dev/vndbinder");
vndservicemanager
Anteriormente, los servicios de Binder se registraban con servicemanager
.
y otros procesos las podrían recuperar. En Android 8,
Ahora el framework y la app usan servicemanager
exclusivamente
procesos y los procesos de los proveedores ya no pueden acceder a ella.
Sin embargo, los servicios de proveedores ahora pueden usar vndservicemanager
, un nuevo
instancia de servicemanager
que usa /dev/vndbinder
en lugar de /dev/binder
y que se compila a partir de las mismas fuentes que
framework servicemanager
. Los procesos de los proveedores no necesitan hacer
cambios para comunicarse con vndservicemanager
; cuando se abre el proceso de un proveedor
/dev/vndbinder
, las búsquedas de servicios se envían automáticamente a
vndservicemanager
El objeto binario vndservicemanager
se incluye en la configuración predeterminada de Android.
archivos makefile del dispositivo.
Política de SELinux
Los procesos de proveedores que desean usar la funcionalidad de Binder para comunicarse entre sí necesitan lo siguiente:
- Acceso a
/dev/vndbinder
. - Engancha a Binder
{transfer, call}
de Bindervndservicemanager
binder_call(A, B)
para cualquier dominio A de proveedor que desee llamar en el dominio B del proveedor a través de la interfaz de Binder del proveedor.- Permiso para
{add, find}
servicios envndservicemanager
Para cumplir con los requisitos 1 y 2, usa vndbinder_use()
.
macro:
vndbinder_use(some_vendor_process_domain);
Para cumplir con el requisito 3, se debe usar la binder_call(A, B)
del proveedor
los procesos A y B que necesitan comunicarse por Binder pueden permanecer en su lugar y no se
deben cambiarse de nombre.
Para cumplir con el requisito 4, debes hacer cambios en la forma en que las etiquetas de servicio y las reglas.
Para conocer detalles sobre SELinux, consulta Seguridad mejorada Linux en Android Para obtener detalles sobre SELinux en Android 8.0, consulta SELinux para Android 8.0
Nombres de servicios
Anteriormente, el proveedor procesaba nombres de servicios registrados en un
service_contexts
y se agregaron las reglas correspondientes para acceder
ese archivo. Archivo service_contexts
de ejemplo de
device/google/marlin/sepolicy
AtCmdFwd u:object_r:atfwd_service:s0 cneservice u:object_r:cne_service:s0 qti.ims.connectionmanagerservice u:object_r:imscm_service:s0 rcs u:object_r:radio_service:s0 uce u:object_r:uce_service:s0 vendor.qcom.PeripheralManager u:object_r:per_mgr_service:s0
En Android 8, vndservicemanager
carga
vndservice_contexts
archivo en su lugar. Los servicios de proveedores que migran a
vndservicemanager
(y que ya están en el
service_contexts
) al nuevo archivo
Archivo vndservice_contexts
.
Etiquetas de servicio
Anteriormente, las etiquetas de servicio, como u:object_r:atfwd_service:s0
se definieron en un archivo service.te
. Ejemplo:
type atfwd_service, service_manager_type;
En Android 8, debes cambiar el tipo a
vndservice_manager_type
y mueve la regla al
archivo vndservice.te
. Ejemplo:
type atfwd_service, vndservice_manager_type;
reglas de servicemanager
Anteriormente, las reglas concedían acceso a dominios para agregar o buscar servicios de
servicemanager
Ejemplo:
allow atfwd atfwd_service:service_manager find; allow some_vendor_app atfwd_service:service_manager add;
En Android 8, esas reglas pueden permanecer en su lugar y usar la misma clase. Ejemplo:
allow atfwd atfwd_service:service_manager find; allow some_vendor_app atfwd_service:service_manager add;