Hacer cumplir las interfaces de partición de productos

Android 11 desagrega la partición del product , lo que la hace independiente de las particiones del system y del vendor . Como parte de estos cambios, ahora puede controlar el acceso de la partición del product a las interfaces nativas y de Java (que es similar a cómo funciona la aplicación de la interfaz para las particiones de los vendor ).

Aplicación de interfaces nativas

Para habilitar la aplicación de la interfaz nativa, establezca PRODUCT_PRODUCT_VNDK_VERSION en current . (La versión se configura automáticamente como current cuando el nivel de API de envío para el destino es superior a 29). La aplicación permite:

  • Módulos nativos en la partición del product para vincular:
    • Estática o dinámicamente a otros módulos en la partición del product que incluyen bibliotecas estáticas, compartidas o de encabezado.
    • Dinámicamente a bibliotecas VNDK en la partición del system .
  • Bibliotecas JNI en APK desagregados en la partición del product para vincular bibliotecas en /product/lib o /product/lib64 (esto es además de las bibliotecas NDK).

La aplicación no permite otros enlaces a particiones que no sean la partición del product .

Cumplimiento del tiempo de compilación (Android.bp)

En Android 11, los módulos del sistema pueden crear una variante de imagen del producto además de las variantes de imagen principal y de proveedor. Cuando la aplicación de la interfaz nativa está habilitada ( PRODUCT_PRODUCT_VNDK_VERSION está configurado como current ):

  • Los módulos nativos en la partición del product están en la variante del producto en lugar de la variante principal.

  • Los módulos con vendor_available: true en sus archivos Android.bp están disponibles para la variante del producto y la variante del proveedor.

  • Las bibliotecas o archivos binarios que especifican product_specific: true pueden vincularse a otras bibliotecas que especifican product_specific: true o vendor_available: true en sus archivos Android.bp .

  • Las bibliotecas de VNDK deben tener vendor_available: true en sus archivos Android.bp para que los archivos binarios del product puedan vincularse a las bibliotecas de VNDK.

La siguiente tabla resume las propiedades de Android.bp utilizadas para crear variantes de imágenes.

Propiedades en Android.bp Variantes creadas
Antes de la ejecución Después de la ejecución
predeterminado (ninguno) centro

(incluye /system , /system_ext y /product )

centro

(incluye /system y /system_ext pero no /product )

system_ext_specific: true centro centro
product_specific: true centro producto
vendor: true vendedor vendedor
vendor_available: true núcleo, proveedor núcleo, producto, vendedor
system_ext_specific: true Y vendor_available: true núcleo, proveedor núcleo, producto, vendedor
product_specific: true Y vendor_available: true núcleo, proveedor producto, vendedor

Cumplimiento del tiempo de compilación (Android.mk)

Cuando la aplicación de la interfaz nativa está habilitada, los módulos nativos instalados en la partición del product tienen un tipo de vínculo native:product que solo se puede vincular a otros módulos native:product o native:vndk . Intentar vincular a cualquier módulo que no sea este hace que el sistema de compilación genere un error de verificación de tipo de vínculo.

Cumplimiento del tiempo de ejecución

Cuando la aplicación de la interfaz nativa está habilitada, la configuración del enlazador para el enlazador biónico no permite que los procesos del sistema usen bibliotecas de product , lo que crea una sección de product para los procesos de product que no pueden vincularse a bibliotecas fuera de la partición del product (sin embargo, dichos procesos pueden enlace a bibliotecas VNDK). Los intentos de violar la configuración del enlace de tiempo de ejecución hacen que el proceso falle y genere un mensaje de error CANNOT LINK EXECUTABLE .

Hacer cumplir las interfaces de Java

Para habilitar la aplicación de la interfaz de Java, establezca PRODUCT_ENFORCE_PRODUCT_PARTITION_INTERFACE en true . (El valor se establece automáticamente en true cuando el nivel de API de envío para el destino es superior a 29). Cuando está habilitado, la aplicación permite/no permite el siguiente acceso.

API /sistema /ext_sistema /producto /vendedor /datos
API pública
@SistemaApi
@ocultar API

Al igual que en la partición del vendor , una aplicación o una biblioteca de Java en la partición del product solo puede usar API públicas y del sistema; no se permite vincular a una biblioteca que utiliza API ocultas. Esta restricción incluye la vinculación en tiempo de compilación y la reflexión en tiempo de ejecución.

Cumplimiento del tiempo de construcción

En el momento de la compilación, Make y Soong verifican que los módulos de Java en la partición del product no usen API ocultas al verificar los campos platform_apis y sdk_version . La sdk_version de las aplicaciones en la partición del product debe completarse con la versión current , system_current del sistema o numérica de la API, y el campo platform_apis debe estar vacío.

Cumplimiento del tiempo de ejecución

El tiempo de ejecución de Android verifica que las aplicaciones en la partición del product no usen API ocultas, incluida la reflexión. Para obtener más información, consulte Restricciones en las interfaces que no pertenecen al SDK .

Habilitación de la aplicación de la interfaz del producto

Utilice los pasos de esta sección para habilitar la aplicación de la interfaz del producto.

Paso Tarea Requerido
1 Defina su propio archivo MAKE del sistema que especifique los paquetes para la partición del system , luego establezca la verificación de requisitos de ruta de artefactos en el device.mk (para evitar que los módulos que no son del sistema se instalen en la partición del system ). norte
2 Limpia la lista de permitidos. norte
3 Refuerce las interfaces nativas e identifique fallas de enlaces en tiempo de ejecución (puede ejecutarse en paralelo con la aplicación de Java). Y
4 Refuerce las interfaces de Java y verifique el comportamiento del tiempo de ejecución (se puede ejecutar en paralelo con la aplicación nativa). Y
5 Compruebe los comportamientos de tiempo de ejecución. Y
6 Actualice device.mk con la aplicación de la interfaz del producto. Y

Paso 1: Cree un archivo MAKE y habilite la verificación de la ruta del artefacto

En este paso, define el archivo MAKE del system .

  1. Cree un archivo MAKE que defina los paquetes para la partición del system . Por ejemplo, cree un archivo oem_system.mk con lo siguiente:

    $(call inherit-product, $(SRC_TARGET_DIR)/product/handheld_system.mk)
    $(call inherit-product, $(SRC_TARGET_DIR)/product/telephony_system.mk)
    
    # Applications
    PRODUCT_PACKAGES += \
        CommonSystemApp1 \
        CommonSystemApp2 \
        CommonSystemApp3 \
    
    # Binaries
    PRODUCT_PACKAGES += \
        CommonSystemBin1 \
        CommonSystemBin2 \
        CommonSystemBin3 \
    
    # Libraries
    PRODUCT_PACKAGES += \
        CommonSystemLib1 \
        CommonSystemLib2 \
        CommonSystemLib3 \
    
    PRODUCT_SYSTEM_NAME := oem_system
    PRODUCT_SYSTEM_BRAND := Android
    PRODUCT_SYSTEM_MANUFACTURER := Android
    PRODUCT_SYSTEM_MODEL := oem_system
    PRODUCT_SYSTEM_DEVICE := generic
    
    # For system-as-root devices, system.img should be mounted at /, so we
    # include ROOT here.
    _my_paths := \
     $(TARGET_COPY_OUT_ROOT)/ \
     $(TARGET_COPY_OUT_SYSTEM)/ \
    
    $(call require-artifacts-in-path, $(_my_paths),)
    
  2. En el archivo device.mk , herede el archivo MAKE común para la partición del system y habilite la verificación de requisitos de la ruta del artefacto. Por ejemplo:

    $(call inherit-product, $(SRC_TARGET_DIR)/product/oem_system.mk)
    
    # Enable artifact path requirements checking
    PRODUCT_ENFORCE_ARTIFACT_PATH_REQUIREMENTS := strict
    

Acerca de los requisitos de la ruta del artefacto

Cuando PRODUCT_ENFORCE_ARTIFACT_PATH_REQUIREMENTS se establece en true o strict , el sistema de compilación evita que los paquetes definidos en otros archivos make se instalen en las rutas definidas en require-artifacts-in-path y evita que los paquetes definidos en el archivo make actual instalen artefactos fuera de las rutas definidas en require-artifacts-in-path .

En el ejemplo anterior, con PRODUCT_ENFORCE_ARTIFACT_PATH_REQUIREMENTS establecido en strict , los archivos MAKE fuera oem_system.mk no pueden incluir módulos instalados en la partición root o del system . Para incluir estos módulos, debe definirlos en el propio archivo oem_system.mk o en un archivo MAKE incluido. Los intentos de instalar módulos en rutas no permitidas provocan interrupciones en la compilación. Para corregir los descansos, realice una de las siguientes acciones:

  • Opción 1: Incluya el módulo del sistema en los archivos MAKE incluidos en oem_system.mk . Esto hace que se cumpla el requisito de la ruta del artefacto (ya que los módulos ahora existen en un archivo MAKE incluido) y, por lo tanto, permite la instalación en el conjunto de rutas en `require-artifacts-in-path.

  • Opción 2: instale módulos en system_ext o partición del product (y no instale módulos en la partición del system ).

  • Opción 3: Agregar módulos a PRODUCT_ARTIFACT_PATH_REQUIREMENT_ALLOWED_LIST . Esto enumera los módulos permitidos para ser instalados.

Paso 2: vaciar la lista de permitidos

En este paso, vacíe PRODUCT_ARTIFACT_PATH_REQUIREMENT_ALLOWED_LIST para que todos los dispositivos que comparten oem_system.mk también puedan compartir una sola imagen system . Para vaciar la lista de permitidos, mueva los módulos de la lista a system_ext o partición de product o agréguelos a los archivos de creación del system . Este paso es opcional porque no es necesario definir una imagen de system común para habilitar la aplicación de la interfaz del producto. Sin embargo, vaciar la lista permitida es útil para definir el límite del system con system_ext .

Paso 3: hacer cumplir las interfaces nativas

En este paso, configura PRODUCT_PRODUCT_VNDK_VERSION := current , luego busca errores de compilación y tiempo de ejecución y los resuelve. Para verificar el inicio y los registros del dispositivo y encontrar y reparar fallas de enlaces en tiempo de ejecución:

  1. Establecer PRODUCT_PRODUCT_VNDK_VERSION := current .

  2. Construya el dispositivo y busque errores de construcción. Es probable que vea algunas interrupciones de compilación por variantes de productos faltantes o variantes principales. Los descansos comunes incluyen:

    • Cualquier módulo hidl_interface que tenga product_specific: true no estará disponible para los módulos del sistema. Para solucionarlo, reemplace product_specific: true con system_ext_specfic: true .
    • Es posible que a los módulos les falte la variante de producto necesaria para los módulos de producto. Para solucionarlo, haga que ese módulo esté disponible para la partición del product configurando vendor_available: true o mueva el módulo a la partición del product configurando product_specific: true .
  3. Resuelva los errores de compilación y asegúrese de que el dispositivo se compile correctamente.

  4. Muestre la imagen y busque errores de tiempo de ejecución en el inicio y los registros del dispositivo.

    • Si la etiqueta del linker de un registro de caso de prueba muestra un mensaje CANNOT LINK EXECUTABLE , el archivo de creación no tiene una dependencia (y no se capturó en el momento de la compilación).
    • Para verificarlo desde el sistema de compilación, agregue la biblioteca requerida al shared_libs: o required:
  5. Resuelva las dependencias que faltan utilizando la guía proporcionada anteriormente.

Paso 4: hacer cumplir las interfaces de Java

En este paso, configura PRODUCT_ENFORCE_PRODUCT_PARTITION_INTERFACE := true , luego busca y corrige los errores de compilación resultantes. Busque dos tipos específicos de errores:

  • Errores de tipo de enlace. Este error indica que una aplicación se vincula a módulos de Java que tienen una sdk_version más amplia. Para solucionarlo, puede ampliar el sdk_version de la aplicación o restringir el sdk_version de la biblioteca. Error de ejemplo:

    error: frameworks/base/packages/SystemUI/Android.bp:138:1: module "SystemUI" variant "android_common": compiles against system API, but dependency "telephony-common" is compiling against private API.Adjust sdk_version: property of the source or target module so that target module is built with the same or smaller API set than the source.
    
  • Errores de símbolo. Este error indica que no se puede encontrar un símbolo porque está en una API oculta. Para solucionarlo, use una API visible (no oculta) o busque una alternativa. Error de ejemplo:

    frameworks/opt/net/voip/src/java/com/android/server/sip/SipSessionGroup.java:1051: error: cannot find symbol
                ProxyAuthenticate proxyAuth = (ProxyAuthenticate)response.getHeader(
                                               ^
      symbol:   class ProxyAuthenticate
      location: class SipSessionGroup.SipSessionImpl
    

Paso 5: Comprueba los comportamientos de tiempo de ejecución

En este paso, verifica que los comportamientos de tiempo de ejecución sean los esperados. Para las aplicaciones que se pueden depurar, puede monitorear el uso de la API oculta mediante el registro mediante StrictMode.detectNonSdkApiUsage (que genera un registro cuando la aplicación usa una API oculta). Alternativamente, puede usar la herramienta de análisis estático veridex para obtener el tipo de uso (enlace o reflexión), el nivel de restricción y la pila de llamadas.

  • Sintaxis de Veridex:

    ./art/tools/veridex/appcompat.sh --dex-file={apk file}
    
  • Ejemplo de resultado veridex:

    #1: Linking greylist-max-o Landroid/animation/AnimationHandler;-><init>()V use(s):
           Lcom/android/systemui/pip/phone/PipMotionHelper;-><init>(Landroid/content/Context;Landroid/app/IActivityManager;Landroid/app/IActivityTaskManager;Lcom/android/systemui/pip/phone/PipMenuActivityController;Lcom/android/internal/policy/PipSnapAlgorithm;Lcom/android/systemui/statusbar/FlingAnimationUtils;)V
    
    #1332: Reflection greylist Landroid/app/Activity;->mMainThread use(s):
           Landroidx/core/app/ActivityRecreator;->getMainThreadField()Ljava/lang/reflect/Field;
    

Para obtener detalles sobre el uso de veridex, consulte Probar con la herramienta veridex .

Paso 6: Actualizar dispositivo.mk

Después de corregir todas las fallas de compilación y tiempo de ejecución, y verificar que los comportamientos del tiempo de ejecución son los esperados, configure lo siguiente en device.mk :

  • PRODUCT_PRODUCT_VNDK_VERSION := current
  • PRODUCT_ENFORCE_PRODUCT_PARTITION_INTERFACE := true