Hacer cumplir las interfaces de partición de productos

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

Hacer cumplir las interfaces nativas

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

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

La aplicación no permite otros enlaces a particiones distintas a la partición product .

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

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

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

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

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

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

La siguiente tabla resume las propiedades 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 proveedor proveedor
vendor_available: true núcleo, proveedor núcleo, proveedor
product_available: true N / A producto principal
vendor_available: true Y product_available: true N / A núcleo, producto, proveedor
system_ext_specific: true Y vendor_available: true núcleo, proveedor núcleo, proveedor
product_specific: true Y vendor_available: true núcleo, proveedor producto, vendedor

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

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

Aplicación del tiempo de ejecución

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

Hacer cumplir las interfaces Java

Para habilitar la aplicación de la interfaz 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 mayor que 29). Cuando está habilitado, la aplicación permite o no permite el siguiente acceso.

API /sistema /ext_sistema /producto /proveedor /datos
API pública
@SystemApi
@ocultar API

Al igual que en la partición vendor , una aplicación o una biblioteca Java en la partición product solo puede utilizar 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 el momento de la compilación y la reflexión en el tiempo de ejecución.

Aplicación del tiempo de construcción

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

Aplicación del tiempo de ejecución

El tiempo de ejecución de Android verifica que las aplicaciones en la partición product no utilicen API ocultas, incluida la reflexión. Para obtener más información, consulte Restricciones en interfaces que no son 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 system , luego establezca la verificación de requisitos de ruta de los artefactos en el device.mk (para evitar que módulos que no son del sistema se instalen en la partición del system ). norte
2 Limpiar la lista de permitidos. norte
3 Aplique interfaces nativas e identifique fallas en los enlaces de tiempo de ejecución (puede ejecutarse en paralelo con la aplicación de Java). Y
4 Aplique interfaces Java y verifique el comportamiento del tiempo de ejecución (puede ejecutarse en paralelo con la aplicación nativa). Y
5 Verifique los comportamientos en tiempo de ejecución. Y
6 Actualice device.mk con la aplicación de la interfaz del producto. Y

Paso 1: crear un archivo MAKE y habilitar la verificación de ruta de artefacto

En este paso, usted define el archivo MAKE system .

  1. Cree un archivo MAKE que defina los paquetes para la partición 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 system y habilite la verificación de requisitos de ruta de 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 configurado en strict , los archivos MAKE fuera oem_system.mk no pueden incluir módulos instalados en la partición root o system . Para incluir estos módulos, debe definirlos en el 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 arreglar las roturas, haga una de las siguientes cosas:

  • Opción 1: incluir el módulo del sistema en los archivos MAKE incluidos en oem_system.mk . Esto hace que se cumpla el requisito de 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: Instalar módulos en system_ext o en la partición product (y no instalar módulos en la partición system ).

  • Opción 3: agregar módulos a PRODUCT_ARTIFACT_PATH_REQUIREMENT_ALLOWED_LIST . Esta lista permite instalar módulos.

Paso 2: vaciar la lista de permitidos

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

Paso 3: aplicar 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 buscar y corregir fallas en el enlace del tiempo de ejecución:

  1. Establecer PRODUCT_PRODUCT_VNDK_VERSION := current .

  2. Construya el dispositivo y busque errores de compilación. Es probable que vea algunas interrupciones en la compilación debido a 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 requerida para los módulos de producto. Para solucionarlo, haga que ese módulo esté disponible para la partición product configurando product_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 genere correctamente.

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

    • Si la etiqueta del linker de un registro de caso de prueba muestra un mensaje CANNOT LINK EXECUTABLE , al archivo de creación le falta 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 Java

En este paso, configura PRODUCT_ENFORCE_PRODUCT_PARTITION_INTERFACE := true y 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 Java que tienen una sdk_version más amplia. Para solucionarlo, puede ampliar sdk_version de la aplicación o restringir 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, utilice 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: comprobar los comportamientos en tiempo de ejecución

En este paso, verificará que los comportamientos en tiempo de ejecución sean los esperados. Para las aplicaciones que se pueden depurar, puede monitorear el uso de API oculta mediante el registro usando StrictMode.detectNonSdkApiUsage (que genera un registro cuando la aplicación usa una API oculta). Alternativamente, puede utilizar la herramienta de análisis estático veridex para obtener el tipo de uso (vínculo 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 de 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 Prueba usando la herramienta veridex .

Paso 6: actualice el dispositivo.mk

Después de corregir todos los errores de compilación y tiempo de ejecución, y verificar que el comportamiento del tiempo de ejecución sea el esperado, configure lo siguiente en device.mk :

  • PRODUCT_PRODUCT_VNDK_VERSION := current
  • PRODUCT_ENFORCE_PRODUCT_PARTITION_INTERFACE := true