Android 11 desagrupa la partición product
, lo que la independiza de las particiones system
y vendor
. Como parte de estos cambios, ahora puedes controlar el acceso de la partición product
a interfaces nativas y Java (que es similar a cómo funciona la aplicación de la interfaz para las particiones vendor
).
Cómo aplicar interfaces nativas
Para habilitar la aplicación de la interfaz nativa, establece PRODUCT_PRODUCT_VNDK_VERSION
en current
. (La versión se establece automáticamente en current
cuando el nivel de API de envío del objetivo es superior a 29). La aplicación permite lo siguiente:
- Módulos nativos en la partición
product
para vincular:- De forma estática o dinámica a otros módulos en la partición
product
que incluyen bibliotecas estáticas, compartidas o de encabezado - De forma dinámica a las bibliotecas del VNDK en la partición
system
- De forma estática o dinámica a otros módulos en la partición
- Bibliotecas de JNI en APKs no empaquetados en la partición
product
para vincularse a bibliotecas en/product/lib
o/product/lib64
(esto se suma a las bibliotecas del NDK).
La aplicación de la política no permite otros vínculos a particiones que no sean 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 del producto, además de las variantes de imagen principal y del proveedor. Cuando se aplica la interfaz nativa (PRODUCT_PRODUCT_VNDK_VERSION
se establece en current
), ocurre lo siguiente:
Los módulos nativos de la partición
product
se encuentran en la variante del producto en lugar de en la variante principal.Los módulos con
product_available: true
en sus archivosAndroid.bp
están disponibles para la variante del producto.Las bibliotecas o los archivos binarios que especifican
product_specific: true
pueden vincularse a otras bibliotecas que especificanproduct_specific: true
oproduct_available: true
en sus archivosAndroid.bp
.Las bibliotecas de VNDK deben tener
product_available: true
en sus archivosAndroid.bp
para que los objetos binarios deproduct
puedan vincularse a las bibliotecas de VNDK.
En la siguiente tabla, se resumen las propiedades de Android.bp
que se usan para crear variantes de imágenes.
Propiedades en Android.bp | Se crearon variantes | |
---|---|---|
Antes de la aplicación | Después de la aplicación | |
predeterminado (ninguno) | core
(incluye /system , /system_ext y
/product ) |
core
(incluye /system y /system_ext , pero no
/product ) |
system_ext_specific: true |
core | core |
product_specific: true |
core | producto |
vendor: true |
de proveedor | de proveedor |
vendor_available: true |
core, vendor | core, vendor |
product_available: true |
N/A | principal, producto |
vendor_available: true Y product_available:
true |
N/A | principal, producto, proveedor |
system_ext_specific: true Y vendor_available:
true |
core, vendor | core, vendor |
product_specific: true Y vendor_available:
true |
core, vendor | producto, proveedor |
Aplicación del tiempo de compilación (Android.mk)
Cuando se habilita la aplicación de la 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
. Si intentas vincularte a otros módulos que no sean estos, el sistema de compilación generará un error de verificación del tipo de vínculo.
Aplicación durante el tiempo de ejecución
Cuando se habilita la aplicación de la interfaz nativa, la configuración del vinculador para el vinculador biónico no permite que los procesos del sistema usen bibliotecas product
, lo que crea una sección product
para los procesos product
que no se pueden vincular a bibliotecas fuera de la partición product
(sin embargo, esos procesos se pueden vincular a bibliotecas del VNDK). Los intentos de incumplir la configuración de la vinculación en el tiempo de ejecución provocan que el proceso falle y se genere un mensaje de error de CANNOT LINK EXECUTABLE
.
Cómo aplicar interfaces de Java
Para habilitar la aplicación de la interfaz de Java, establece PRODUCT_ENFORCE_PRODUCT_PARTITION_INTERFACE
en true
. (El valor se establece automáticamente en true
cuando el nivel de API de envío del objetivo es superior a 29). Cuando está habilitada, la aplicación forzosa permite o rechaza el siguiente acceso:
API | /system | /system_ext | /product | /vendor | /data |
---|---|---|---|---|---|
API pública | |||||
@SystemApi | |||||
@hide API |
Al igual que en la partición vendor
, una app o una biblioteca de Java en la partición product
solo pueden usar APIs públicas y del sistema. No se permite la vinculación a una biblioteca que use APIs ocultas. Esta restricción incluye la vinculación en el tiempo de compilación y la reflexión en el tiempo de ejecución.
Aplicación de políticas durante el tiempo de compilación
En el momento de la compilación, Make y Soong verifican que los módulos de Java en la partición product
no usen APIs ocultas. Para ello, verifican los campos platform_apis
y sdk_version
. El campo sdk_version
de las apps en la partición product
debe completarse con current
, system_current
o la versión numérica de la API, y el campo platform_apis
debe estar vacío.
Aplicación durante el tiempo de ejecución
El tiempo de ejecución de Android verifica que las apps en la partición product
no usen APIs ocultas, incluida la reflexión. Para obtener más información, consulta Restricciones en interfaces que no pertenecen al SDK.
Habilita la aplicación de la interfaz de productos
Sigue los pasos de esta sección para habilitar la aplicación de la interfaz de productos.
Paso | Tarea | Obligatorio |
---|---|---|
1 | Define tu propio archivo makefile del sistema que especifique los paquetes para la partición system y, luego, establece la verificación de requisitos de la ruta de acceso de artefactos en device.mk (para evitar que los módulos que no son del sistema se instalen en la partición system ). |
N |
2 | Limpia la lista de entidades permitidas. | N |
3 | Aplicar interfaces nativas y detectar errores de vinculación en el tiempo de ejecución (se puede ejecutar en paralelo con la aplicación de Java). | S |
4 | Aplicar interfaces de Java y verificar el comportamiento del tiempo de ejecución (se puede ejecutar en paralelo con la aplicación nativa). | S |
5 | Verifica los comportamientos del tiempo de ejecución. | S |
6 | Se actualizó device.mk con la aplicación de la interfaz del producto. |
S |
Paso 1: Crea un archivo makefile y habilita la verificación de la ruta de acceso del artefacto
En este paso, definirás el archivo Makefile system
.
Crea un archivo makefile que defina los paquetes para la partición
system
. Por ejemplo, crea un archivooem_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),)
En el archivo
device.mk
, hereda el archivo makefile común para la particiónsystem
y habilita la verificación de los requisitos de la ruta de acceso 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 de artefacto
Cuando PRODUCT_ENFORCE_ARTIFACT_PATH_REQUIREMENTS
se establece en true
o strict
, el sistema de compilación impide que los paquetes definidos en otros archivos make se instalen en las rutas de acceso definidas en require-artifacts-in-path
y evita que los paquetes definidos en el archivo make actual instalen artefactos fuera de las rutas de acceso definidas en require-artifacts-in-path
.
En el ejemplo anterior, con PRODUCT_ENFORCE_ARTIFACT_PATH_REQUIREMENTS
establecido en strict
, los archivos makefile fuera de oem_system.mk
no pueden incluir módulos instalados en la partición root
o system
. Para incluir estos módulos, debes definirlos en el archivo oem_system.mk
o en un archivo makefile incluido.
Si se intenta instalar módulos en rutas no permitidas, se producen interrupciones en la compilación. Para corregir los saltos, realiza una de las siguientes acciones:
Opción 1: Incluye el módulo del sistema en los archivos makefiles incluidos en
oem_system.mk
. Esto hace que se cumpla el requisito de la ruta de acceso del artefacto (ya que los módulos ahora existen en un archivo makefile incluido) y, por lo tanto, permite la instalación en el conjunto de rutas de acceso en "require-artifacts-in-path".Opción 2: Instala módulos en la partición
system_ext
oproduct
(y no instales módulos en la particiónsystem
).Opción 3: Agrega módulos al
PRODUCT_ARTIFACT_PATH_REQUIREMENT_ALLOWED_LIST
. En esta lista, se indican los módulos que se pueden instalar.
Paso 2: Vacía la lista de cuentas permitidas
En este paso, harás que PRODUCT_ARTIFACT_PATH_REQUIREMENT_ALLOWED_LIST
esté vacío para que todos los dispositivos que compartan oem_system.mk
también puedan compartir una sola imagen de system
. Para vaciar la lista de elementos permitidos, mueve los módulos de la lista a la partición system_ext
o product
, o bien agrégalos a los archivos de compilación system
. Este paso es opcional, ya que 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 de entidades permitidas es útil para definir el límite de system
con system_ext
.
Paso 3: Aplica interfaces nativas
En este paso, establecerás PRODUCT_PRODUCT_VNDK_VERSION := current
y, luego, buscarás errores de compilación y de tiempo de ejecución, y los resolverás. Para verificar el inicio y los registros del dispositivo, y encontrar y corregir las fallas de vínculos en tiempo de ejecución, haz lo siguiente:
Establece
PRODUCT_PRODUCT_VNDK_VERSION := current
.Compila el dispositivo y busca errores de compilación. Es probable que veas algunas interrupciones de compilación por falta de variantes de productos o variantes principales. Entre las pausas comunes, se incluyen las siguientes:
- Los módulos
hidl_interface
que tenganproduct_specific: true
no estarán disponibles para los módulos del sistema. Para corregir el error, reemplazaproduct_specific: true
porsystem_ext_specific: true
. - Es posible que a los módulos les falte la variante del producto necesaria para los módulos de productos. Para corregir el problema, haz que ese módulo esté disponible para la partición
product
configurandoproduct_available: true
o mueve el módulo a la particiónproduct
configurandoproduct_specific: true
.
- Los módulos
Resuelve los errores de compilación y asegúrate de que el dispositivo se compile correctamente.
Graba la imagen en la memoria flash y busca errores de tiempo de ejecución en el inicio y los registros del dispositivo.
- Si la etiqueta
linker
de un registro de caso de prueba muestra un mensajeCANNOT LINK EXECUTABLE
, significa que falta una dependencia en el archivo de compilación (y no se capturó en el momento de la compilación). - Para verificarlo desde el sistema de compilación, agrega la biblioteca requerida al campo
shared_libs:
orequired:
.
- Si la etiqueta
Resuelve las dependencias faltantes con la guía que se proporcionó anteriormente.
Paso 4: Aplica interfaces de Java
En este paso, establecerás PRODUCT_ENFORCE_PRODUCT_PARTITION_INTERFACE := true
y, luego, buscarás y corregirás los errores de compilación resultantes. Busca dos tipos específicos de errores:
Errores de tipo de vínculo. Este error indica que una app vincula módulos de Java que tienen un
sdk_version
más amplio. Para solucionarlo, puedes ampliar elsdk_version
de la app o restringir elsdk_version
de la biblioteca. Ejemplo de error: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ímbolos. Este error indica que no se puede encontrar un símbolo porque está en una API oculta. Para corregir el problema, usa una API visible (no oculta) o busca una alternativa. Ejemplo de error:
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: Verifica los comportamientos del tiempo de ejecución
En este paso, verificarás que los comportamientos del tiempo de ejecución sean los esperados. En el caso de las apps que se pueden depurar, puedes supervisar el uso de la API oculta por medio de registros con StrictMode.detectNonSdkApiUsage
(que genera un registro cuando la app usa una API oculta). Como alternativa, puedes usar la herramienta de análisis estático veridex para obtener el tipo de uso (vinculación 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, consulta Cómo realizar pruebas con la herramienta veridex.
Paso 6: Actualiza device.mk
Después de corregir todos los errores de compilación y de tiempo de ejecución, y verificar que los comportamientos del tiempo de ejecución sean los esperados, configura lo siguiente en device.mk
:
PRODUCT_PRODUCT_VNDK_VERSION := current
PRODUCT_ENFORCE_PRODUCT_PARTITION_INTERFACE := true