Imagen del sistema compartida

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.

Particiones e interfaces alrededor del diagrama de bloques del SSI

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 /system o de una imagen /system y 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 /product para 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 /odm separada, 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 system y system_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
  • 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 /product deben 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 /product no 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 /system o /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

Particiones sugeridas 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.

Cómo heredar `generic_system.mk` para la imagen del sistema del OEM

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.

Cómo quitar los archivos agregados de la GSI del OEM

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.

Define una lista de entidades permitidas para reducir la lista de archivos modificados 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.

Haz que la GSI del OEM tenga los mismos objetos binarios que la GSI del AOSP

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.

  1. 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.

  2. 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).

  3. Crea subdirectorios de sysconfig específicos del SKU en /product/etc/sysconfig/ con la convención de nomenclatura sku_<SKU_NAME>. El sistema carga automáticamente las configuraciones del directorio que coincide con la propiedad ro.boot.hardware.sku. Ejemplo de ruta: /product/etc/sysconfig/sku_basic_model/.

  4. 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 directorio sku_<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.