En esta página, se presentan varios mecanismos que los OEM de Android pueden usar para tener una imagen del sistema compartida (SSI) en todas las líneas de productos. También propone un procedimiento para basar una SSI propiedad del OEM en una imagen genérica del sistema (GSI) compilada por el AOSP.
Fondo
El framework del Proyecto de código abierto de Android (AOSP) cumple con la arquitectura de Mainline para mantener la retrocompatibilidad con implementaciones de proveedores anteriores. Por ejemplo, una imagen genérica del sistema (GSI) compilada a partir de fuentes del AOSP de Android 10 se puede ejecutar en cualquier dispositivo compatible con Treble que ejecute Android 8 o versiones posteriores.
Mainline logra esto dividiendo Android en dos partes distintas: la implementación del proveedor específica del hardware y el marco de trabajo genérico del SO Android. Cada componente se instala en una partición independiente: la partición del proveedor para el software específico del hardware y la partición del sistema para el SO genérico. Entre ellos, se aplica una interfaz con versiones, denominada interfaz de proveedor (VINTF). Este sistema de particiones permite que los OEM modifiquen la partición del sistema sin tocar la partición del proveedor y viceversa.
Históricamente, los proveedores de SoC y los OEM modificaron en gran medida la versión del framework de Android que se incluía en los dispositivos para el consumidor (para obtener más detalles, consulta Ciclo de vida de una versión de Android). Debido a que estas extensiones del framework rara vez se diseñaron teniendo en cuenta la retrocompatibilidad, las modificaciones específicas del dispositivo aumentaron drásticamente la complejidad y el costo financiero de las actualizaciones posteriores del SO. En Android 10 (nivel de API 29) y versiones anteriores, el ecosistema carecía de una arquitectura clara y estandarizada que permitiera a los socios crear extensiones modulares para el framework de Android.
En esta página, se describe cómo los OEM y los proveedores de SoC pueden compilar una imagen del sistema compartida (SSI). Una SSI es una imagen de framework unificada compilada a partir de fuentes del SO Android que se puede reutilizar en varios dispositivos. Al mantener una compatibilidad con versiones anteriores limpia con las implementaciones de los proveedores a través de esta arquitectura particionada, una SSI reduce significativamente el costo y la complejidad de las actualizaciones del SO Android.
Para obtener detalles sobre la implementación, consulta Pasos sugeridos para la SSI basada en GSI. Los pasos son modulares. Según tu arquitectura, puedes optar por implementar etapas específicas (como Paso 1: Hereda generic_system.mk para la imagen del sistema del OEM (GSI del OEM)) en lugar de todas las etapas.
Descripción general de la SSI
Con la SSI, los componentes de software específicos del producto y las extensiones del OEM se colocan en una nueva partición /product. Los componentes de la partición /product usan una interfaz estable y bien definida para interactuar con los componentes de la partición /system. Los OEM pueden optar por compilar un solo SSI o tener una pequeña cantidad de SSI para usar en varios SKU de dispositivos. Cuando se lanza una nueva versión del SO Android, los OEM invierten solo una vez en actualizar sus SSI a la versión más reciente de Android. Pueden reutilizar los SSI para actualizar varios dispositivos sin actualizar la partición /product.
Los OEM y los proveedores de SoC pueden crear SSI que incluyan funciones y modificaciones personalizadas. Los mecanismos y las prácticas recomendadas que se proporcionan en esta página están destinados a que los OEM los usen para alcanzar estos objetivos clave:
- Reutiliza la SSI en varios SKU de dispositivos.
- Actualizar el sistema Android con las extensiones modulares para que las actualizaciones del SO sean más sencillas
La idea principal de separar los componentes específicos del producto en la partición del producto es similar a la de Mainline, que separa los componentes específicos del SoC en la partición del proveedor. Una interfaz de producto (similar a VINTF) permite la comunicación entre la SSI y la partición del producto. Con respecto a la SSI, el término componentes describe todos los recursos, archivos binarios, textos y bibliotecas que se instalan en las imágenes, que se convierten en particiones.
Particiones alrededor de la SSI
En la figura 1, se muestran las particiones alrededor de la SSI y las interfaces versionadas en las particiones y las políticas en las interfaces. En esta sección, se explica cada una de las particiones y las interfaces en detalle.
Figura 1: Particiones e interfaces en torno a la SSI.
Imágenes y particiones
La información de esta sección distingue entre los términos imagen y partición.
- Una imagen es una pieza conceptual de software que se puede actualizar de forma independiente.
- Una partición es una ubicación de almacenamiento física que se puede actualizar de forma independiente.
Las secciones de la figura 1 se definen de la siguiente manera:
SSI: Es una imagen común a un OEM que puede existir en varios dispositivos. No tiene componentes específicos del hardware o del producto. Por definición, todo lo que se encuentra en una SSI determinada se comparte entre todos los dispositivos que la usan. La SSI se compone de una sola imagen
/systemo de una imagen/systemy las particiones/system_ext.Imagen del producto: Es una colección de componentes específicos del producto o dispositivo que representan las personalizaciones y extensiones del OEM para el SO Android. Coloca los componentes específicos del SoC en la partición
/vendor. Los proveedores de SoC también pueden usar la partición/productpara los componentes adecuados, como los independientes del SoC. Por ejemplo, si un proveedor de SoC proporciona un componente independiente del SoC a sus clientes OEM (que es opcional para incluirlo en el producto), el proveedor de SoC puede colocar ese componente en la imagen del producto. La ubicación de un componente se determina según su propósito y no según su propiedad.Imagen del proveedor: Es una colección de componentes específicos del SoC.
Imagen del ODM: Es una colección de componentes específicos de la placa que no proporciona el SoC. Por lo general, el proveedor del SoC es propietario de la imagen del proveedor, mientras que el fabricante del dispositivo es propietario de la imagen del ODM. Cuando no hay una partición
/odmseparada, las imágenes del proveedor del SoC y del ODM se combinan en la partición/vendor.
La partición /system_ext
La partición /system_ext es opcional. Usa esta partición para cualquier extensión y función personalizada que esté estrechamente vinculada con los componentes basados en AOSP. Se supone que esta partición es la extensión específica del OEM para la partición /system, sin una interfaz definida en las dos particiones.
Los componentes de la partición /system_ext pueden realizar llamadas a la API privadas en la partición /system, y los componentes de la partición /system pueden realizar llamadas a la API privadas en la partición /system_ext.
Debido a que las dos particiones están estrechamente vinculadas, ambas se actualizan juntas cuando se lanza una nueva versión de Android. Una partición /system_ext creada para la versión anterior de Android no necesita ser compatible con la partición /system en la próxima versión de Android.
Para instalar un módulo en la partición /system_ext, agrega system_ext_specific:
true al archivo Android.bp. En los dispositivos que no tienen una partición /system_ext, instala esos módulos en el subdirectorio ./system_ext de la partición /system.
Historial: El objetivo de diseño original de la partición /system_ext era colocar todos los componentes específicos del OEM, independientemente de si son comunes, en la partición /product. Sin embargo, moverlos todos a la vez no era factible, en especial cuando algunos componentes tenían un acoplamiento estrecho con la partición /system. Para mover un componente con acoplamiento alto a la partición /product, se debe extender la interfaz del producto. A menudo, esto requería que el componente en sí se refactorizara de forma exhaustiva, lo que consumía mucho tiempo y esfuerzo. La partición /system_ext comenzó como un lugar para alojar temporalmente aquellos componentes que no están listos para moverse a la partición /product. El objetivo de la SSI era, en última instancia, eliminar la partición /system_ext.
Sin embargo, la partición /system_ext es útil para mantener la partición /system lo más cerca posible del AOSP. Con la SSI, la mayor parte del esfuerzo de actualización se dedica a los componentes de las particiones /system y /system_ext. Cuando la imagen del sistema se compila a partir de fuentes que son lo más similares posible a las de AOSP, puedes enfocar el esfuerzo de actualización en la imagen de system_ext.
Interfaces entre imágenes
Existen dos interfaces principales para las imágenes de proveedores y productos en torno a la SSI:
Interfaz del proveedor (VINTF): La VINTF es la interfaz para los componentes que residen en las imágenes del proveedor y del ODM. Los componentes de las imágenes del producto y del sistema solo pueden interactuar con las imágenes del proveedor y del ODM a través de esta interfaz. Por ejemplo, una imagen del proveedor no puede depender de una parte privada de la imagen del sistema, y viceversa. Esto se define en la arquitectura de Treble (ahora parte de la arquitectura más amplia de Mainline), que divide las imágenes en particiones del sistema y del proveedor. La interfaz se describe con los siguientes mecanismos:
- HIDL (el HAL de transferencia solo está disponible para los módulos
systemysystem_ext) - AIDL estable
- Configuraciones
- API de propiedades del sistema
- API de esquema del archivo de configuración
- VNDK
- APIs del SDK de Android
- Biblioteca del SDK de Java
- HIDL (el HAL de transferencia solo está disponible para los módulos
Interfaces del producto: La interfaz del producto es la interfaz entre el SSI y la imagen del producto. Definir una interfaz estable desacopla los componentes del producto de los componentes del sistema en una SSI.
Habilita SSI
En esta sección, se explica cómo admitir SSI en Android 11 y versiones posteriores.
Desagrupa componentes
Para separar la partición /product de los componentes del sistema, la partición /product debe tener la misma política de aplicación que la partición /vendor que ya se separó con Mainline.
- Interfaces integradas: Los módulos integrados en la partición
/productdeben separarse de las otras particiones. Las únicas dependencias permitidas de los módulos de productos son algunas bibliotecas del VNDK (incluido el LLNDK) de la partición/system. Las bibliotecas JNI de las que dependen las apps del producto deben ser bibliotecas del NDK. - Interfaces de Java: Los módulos de Java (app) en la partición
/productno pueden usar APIs ocultas porque son inestables. Estos módulos solo deben usar APIs públicas y APIs del sistema de la partición/system, y bibliotecas del SDK de Java en la partición/systemo/system_ext. Puedes definir bibliotecas del SDK de Java para APIs personalizadas.
Aplica las interfaces de productos
Para asegurarse de que la partición /product no esté agrupada, los OEM pueden hacer que sus dispositivos apliquen las interfaces del producto configurando PRODUCT_PRODUCT_VNDK_VERSION:= current para los módulos integrados y PRODUCT_ENFORCE_PRODUCT_PARTITION_INTERFACE:= true para los módulos de Java. Estas variables se configuran automáticamente si el PRODUCT_SHIPPING_API_LEVEL del dispositivo es mayor o igual que 30. Para obtener información detallada, consulta Cómo aplicar interfaces de partición de productos.
Pasos sugeridos para la SSI basada en GSI
Figura 2: Son las particiones sugeridas para la SSI basada en el GSI.
Una imagen genérica del sistema (GSI) es la imagen del sistema que se compila directamente desde el AOSP. Se usa para las pruebas de cumplimiento (por ejemplo, CTS en GSI) y como plataforma de referencia que los desarrolladores de apps pueden usar para probar la compatibilidad de sus apps cuando no tienen un dispositivo real que ejecute la versión requerida de Android.
Los OEM también pueden usar la GSI para crear su SSI. Como se explica en Imágenes y particiones, la SSI consta de la imagen del sistema para los componentes definidos por el AOSP y la imagen system_ext para los componentes definidos por el OEM. Cuando se usa la GSI como imagen system, el OEM puede enfocarse en la imagen system_ext para la actualización.
En esta sección, se proporciona orientación a los OEM que desean modularizar sus personalizaciones en las particiones /system_ext y /product cuando usan una imagen del sistema de AOSP o casi de AOSP. Si los OEM compilan la imagen del sistema a partir de fuentes de AOSP, pueden sustituir la imagen del sistema que compilan por la GSI que proporciona AOSP. Sin embargo, los OEM no necesitan alcanzar el paso final (usar la GSI tal como está) de inmediato.
Paso 1: Hereda generic_system.mk para la imagen del sistema del OEM (GSI del OEM)
Al heredar generic_system.mk (que se llamaba mainline_system.mk en Android 11 y se renombró como generic_system.mk en AOSP), la imagen del sistema (GSI del OEM) incluye todos los archivos que tiene la GSI del AOSP. Los OEM pueden modificar estos archivos para que la GSI del OEM contenga los archivos propietarios del OEM, además de los archivos de la GSI del AOSP.
Figura 3: Hereda generic_system.mk para la imagen del sistema del OEM.
Paso 2: Haz que la GSI del OEM tenga la misma lista de archivos que la GSI del AOSP
En esta etapa, la GSI del OEM no puede tener archivos adicionales, por lo que debes mover los archivos exclusivos del OEM a las particiones system_ext o product.
Figura 4: Quita los archivos agregados del GSI del OEM.
Paso 3: Define una lista de elementos permitidos para limitar los archivos modificados en la GSI del OEM
Para verificar los archivos modificados, los OEM pueden usar la herramienta compare_images y comparar la GSI de AOSP con la GSI del OEM. Obtén el GSI de AOSP del destino de compilación de AOSP generic_system_*.
Si ejecutas la herramienta compare_images periódicamente con el parámetro allowlist, puedes supervisar las diferencias fuera de la lista de entidades permitidas. Esto evita modificaciones adicionales en la GSI del OEM.
Figura 5: Define una lista de entidades permitidas para reducir la lista de archivos modificados en la GSI del OEM.
Paso 4: Haz que la GSI del OEM tenga los mismos objetos binarios que la GSI del AOSP
La limpieza de la lista de entidades permitidas permite que los OEM usen la GSI del AOSP como imagen del sistema para sus propios productos. Para limpiar la lista de entidades permitidas, los OEM pueden abandonar sus cambios en la GSI del OEM o transferir sus cambios al AOSP para que la GSI del AOSP los incluya.
Figura 6: Haz que la GSI del OEM tenga los mismos objetos binarios que la GSI del AOSP.
Cómo definir la SSI
Los OEM pueden usar la siguiente guía para definir su SSI.
Cómo proteger la partición /system durante el tiempo de compilación
Para evitar cualquier cambio específico del producto en la partición /system y definir la GSI del OEM, los OEM pueden usar una macro de makefile llamada require-artifacts-in-path para evitar cualquier declaración de módulos del sistema después de que se llame a la macro. Consulta el ejemplo en Paso 1: Crea un archivo make y habilita la verificación de la ruta de acceso del artefacto.
Los OEM pueden definir una lista para permitir que se instalen temporalmente módulos específicos del producto en la partición /system. Sin embargo, la lista debe estar vacía para que la GSI del OEM sea común a todos los productos del OEM. Este proceso sirve para definir la GSI del OEM y puede ser independiente de los pasos para la GSI de AOSP.
Cómo hacer que la partición /system_ext sea común
La partición /system_ext puede variar entre dispositivos, ya que puede tener módulos específicos del dispositivo y agrupados en el sistema. Debido a que el SSI consta de particiones /system y /system_ext, las diferencias en la partición /system_ext impiden que los OEM definan un SSI. Los OEM pueden tener su propio SSI y compartirlo entre varios dispositivos quitando las diferencias y haciendo que la partición /system_ext sea común.
En esta sección, se brindan recomendaciones para que la partición /system_ext sea común.
Expone APIs ocultas en la partición del sistema
Muchas apps específicas del producto no se pueden instalar en la partición del producto porque usan APIs ocultas, que están prohibidas en la partición del producto. Para trasladar las apps específicas para dispositivos a la partición del producto, quita el uso de las APIs ocultas.
La forma preferida de quitar las APIs ocultas de las apps es encontrar las APIs públicas o del sistema alternativas para reemplazarlas. Si no hay APIs para reemplazar las APIs ocultas, los OEM pueden contribuir al AOSP para definir las nuevas APIs del sistema para sus dispositivos.
Como alternativa, los OEM pueden definir APIs personalizadas creando su propia biblioteca del SDK de Java en la partición /system_ext. Esta biblioteca puede usar APIs ocultas en la partición del sistema y puede proporcionar las APIs a las apps en la partición del producto o del proveedor. Los OEM deben congelar las APIs orientadas al producto para garantizar la retrocompatibilidad.
Reemplaza la inhabilitación de la app específica del SKU
Android 16 dejó de estar disponible y quitó el mecanismo heredado para inhabilitar de forma selectiva los APKs según el SKU de hardware con superposiciones de recursos del framework (config_disableApksUnlessMatchedSku_apk_list y config_disableApkUnlessMatchedSku_skus_list). Para obtener más información, consulta aosp/3444399.
Se recomienda usar la configuración del sistema install-in-user-type en los directorios específicos del SKU. Este enfoque evita que el paquete se instale para cualquier usuario en un SKU específico, en lugar de solo inhabilitarlo después de la instalación.
Incluye todos los APKs (el superconjunto de todas las apps potenciales para todos los SKU en la imagen del sistema) en la imagen, por lo general, en la partición
/product.Asegúrate de que el SKU del dispositivo esté configurado correctamente en la propiedad del sistema
ro.boot.hardware.sku(que el sistema usa para identificar el SKU del dispositivo durante el inicio).Crea subdirectorios de sysconfig específicos del SKU en
/product/etc/sysconfig/con la convención de nomenclaturasku_<SKU_NAME>. El sistema carga automáticamente las configuraciones del directorio que coincide con la propiedadro.boot.hardware.sku. Ejemplo de ruta:/product/etc/sysconfig/sku_basic_model/.Configurar la prevención de instalación de apps Dentro del directorio específico del SKU, crea un archivo de configuración XML (por ejemplo,
disabled_apps.xml) y usa la etiqueta<do-not-install-in>para excluir paquetes específicos.
Ejemplo de XML (/product/etc/sysconfig/sku_basic_model/disabled_apps.xml):
<?xml version="1.0" encoding="utf-8"?>
<config>
<!-- Prevents this package from being installed for ANY user on this SKU -->
<install-in-user-type package="com.example.premium.feature.app" >
<do-not-install-in user-type="FULL" />
<do-not-install-in user-type="SYSTEM" />
</install-in-user-type>
</config>
A continuación, se incluye una comparación de los dos métodos:
| Función | Android 15 y versiones anteriores | Android 16 y versiones posteriores |
|---|---|---|
| Método de configuración | Superposiciones de recursos del framework | Archivos XML de SystemConfig |
| Ubicación de la lógica | config.xml (superposición de recursos) |
/product/etc/sysconfig/sku_<name>/ |
| Resultado | Inhabilita la app con PackageManager | Impide la instalación de la app para el usuario |
| Solidez | Los servicios del sistema pueden volver a habilitarlo. | El paquete nunca se instala para el usuario |
En los casos que requieren un control más detallado (es decir, inhabilitar una app que normalmente se instala de forma predeterminada en todos los SKU), Android también admite las etiquetas disabled-in-sku y enabled-in-sku-override en sysconfig:
<disabled-in-sku package="com.example.app" />inhabilita la app de forma global.<enabled-in-sku-override package="com.example.app" />vuelve a habilitar la app para un SKU específico cuando se coloca en el directoriosku_<name>correspondiente.
Define el RRO en lugar de usar la superposición de recursos estáticos
Una superposición de recursos estáticos manipula los paquetes superpuestos. Sin embargo, puede impedir la definición de una SSI, por lo que debes asegurarte de que las propiedades para el RRO estén activadas y configuradas correctamente. Si configuran las propiedades de la siguiente manera, los OEM pueden tener todas las superposiciones generadas automáticamente como RRO.
PRODUCT_ENFORCE_RRO_TARGETS := *
PRODUCT_ENFORCE_RRO_EXCLUDED_OVERLAYS := # leave it empty
Si se requiere una configuración detallada, define un RRO de forma manual en lugar de depender de uno generado automáticamente. Para obtener información detallada, consulta Cómo cambiar el valor de los recursos de una app en el tiempo de ejecución. Los OEM también pueden definir RRAs condicionales que dependen de las propiedades del sistema con los atributos android:requiredSystemPropertyName y android:requiredSystemPropertyValue.
Preguntas frecuentes
A continuación, se incluyen preguntas frecuentes sobre la SSI.
¿Puedo definir varias SSI?
Depende de la similitud y las características de los dispositivos (o del grupo de dispositivos). Los OEM pueden intentar que la partición system_ext sea común, como se describe en Cómo hacer que la partición system_ext sea común. Si un grupo de dispositivos tiene muchas diferencias, es mejor definir varias SSI.
¿Puedo quitar de generic_system.mk los módulos que entran en conflicto con mi implementación?
No. La GSI tiene un conjunto mínimo de módulos que se pueden iniciar y probar. Si crees que un módulo no es esencial, presenta un error para actualizar el archivo generic_system.mk.