Extensiones de WindowManager

La biblioteca de Jetpack WindowManager permite que los desarrolladores de aplicaciones admitan nuevos factores de forma de dispositivos y entornos multiventana.

WindowManager Extensions (Extensiones) es un módulo de la plataforma de Android que permite una variedad de funciones de WindowManager de Jetpack. El módulo se implementa en AOSP en frameworks/base/libs/WindowManager/Jetpack y se envía en dispositivos que admiten las funciones de WindowManager.

Distribución del módulo de extensiones

Las extensiones se compilan en una biblioteca .jar y se colocan en la partición system_ext de un dispositivo si las extensiones están habilitadas en el archivo makefile del dispositivo.

Para habilitar las extensiones en un dispositivo, agrega lo siguiente al archivo makefile del dispositivo del producto:

$(call inherit-product, $(SRC_TARGET_DIR)/product/window_extensions.mk)

Esto habilita los paquetes androidx.window.extensions y androidx.window.sidecar en el dispositivo y establece la propiedad persist.wm.extensions.enabled. Si incluyes estos paquetes en el archivo makefile, también se colocan declaraciones en etc/permissions/, lo que los pone a disposición de los procesos de la aplicación. Por lo general, los módulos se cargan y se ejecutan como parte del proceso de la aplicación en el tiempo de ejecución cuando los usa la biblioteca de WindowManager de Jetpack, lo que hace que su operación sea similar al código de framework del cliente, como se muestra en la siguiente figura:

Figura 1. Extensiones de WindowManager cargadas en el proceso de la aplicación de manera similar al código de la plataforma.

El módulo androidx.window.extensions es el módulo de extensiones actual en desarrollo activo. El módulo androidx.window.sidecar es un módulo heredado que se incluye para la compatibilidad con las versiones más recientes de WindowManager de Jetpack, pero el sidecar ya no se mantiene de forma activa.

En la siguiente figura, se muestra la lógica para determinar el uso de androidx.window.extensions o androidx.window.sidecar.

Figura 2. Árbol de decisión para acceder a androidx.window.extensions o androidx.window.sidecar.

Módulos de extensiones

Las extensiones proporcionan funciones de ventanas para dispositivos plegables de pantalla grande y dispositivos que admiten ventanas en pantallas externas. Las áreas de funciones incluyen lo siguiente:

Las implementaciones de extensiones de OEM pueden proporcionar componentes nulos o componentes con implementaciones predeterminadas o de código auxiliar de los métodos en la WindowExtensions interfaz si el hardware del dispositivo no admite las funciones correspondientes, a menos que la función se solicite específicamente en el documento de definición de compatibilidad (CDD) 7.1.1.1.

Extensiones y APIs de Jetpack

El módulo de extensiones de WindowManager proporciona su propia superficie de API, además de las APIs públicas de la plataforma. El módulo de extensiones se desarrolla públicamente en una biblioteca de Jetpack androidx.window.extensions que no está orientada a desarrolladores, de modo que WindowManager de Jetpack (androidx.window) pueda vincularse a ella en el tiempo de compilación. Por lo general, la superficie de la API de extensiones proporciona APIs de nivel inferior.

Las APIs que proporcionan las extensiones están diseñadas para que solo las use la biblioteca de WindowManager de Jetpack. Las APIs de extensiones no están diseñadas para que los desarrolladores de aplicaciones las llamen directamente. La biblioteca de extensiones no se debe agregar como dependencia para una aplicación en el archivo de compilación de Gradle para garantizar la funcionalidad correcta. Evita la compilación previa de la biblioteca de extensiones directamente en una aplicación. En su lugar, confía en la carga del tiempo de ejecución para evitar el caso de cargar una combinación de clases de extensiones compiladas previamente y proporcionadas por el tiempo de ejecución.

WindowManager de Jetpack (androidx.window) está diseñado para agregarse como una dependencia de la aplicación y proporciona las APIs públicas orientadas a desarrolladores, incluidas las de las funciones de extensiones de WindowManager. La biblioteca de WindowManager carga automáticamente las extensiones en el proceso de la aplicación y encapsula las APIs de extensiones de nivel inferior en abstracciones de nivel superior y en interfaces más enfocadas. Las APIs de WindowManager de Jetpack siguen los estándares del desarrollo moderno de aplicaciones para Android y están diseñadas para proporcionar una interoperabilidad conveniente mediante la integración con bases de código que usan otras bibliotecas de AndroidX.

Versiones y actualizaciones de extensiones

El módulo de extensiones se puede actualizar junto con las actualizaciones anuales o trimestrales de la plataforma de Android. Las actualizaciones trimestrales permiten aumentar el nivel de API de extensiones entre las actualizaciones de la API de la plataforma de Android, lo que permite una iteración más rápida y proporciona a los OEMs la oportunidad de agregar acceso oficial a la API a las funciones nuevas cerca de los lanzamientos de hardware.

En la siguiente tabla, se enumeran las versiones de la API de androidx.window.extensions para varias versiones de Android.

Versión de la plataforma de Android Nivel de API de extensiones de WindowManager Versión de la API de androidx.window.extensions
Android 15 6 1.5.0 (próximamente)
QPR3 para Android 14 5 1.4.0 (próximamente)
QPR1 para Android 14 4 1.3.0
Android 14 3 1.2.0
QPR3 para Android 13 2 1.1.0
Android 13 1 1.0.0
Android 12L 1 1.0.0

El nivel de API de extensiones (columna central) aumenta cada vez que se agrega algo a la superficie de API estable existente (columna derecha).

Compatibilidad con versiones anteriores y posteriores

WindowManager de Jetpack controla la complejidad de trabajar con actualizaciones frecuentes del nivel de API, la evolución rápida de la API y la compatibilidad con versiones anteriores. Cuando se ejecuta el código de la biblioteca en el proceso de la aplicación, la biblioteca verifica el nivel de API de extensiones declarado y proporciona acceso a las funciones según el nivel declarado.

Para proteger una aplicación de fallas en el tiempo de ejecución, WindowManager también realiza una verificación de reflexión de Java en tiempo de ejecución de las APIs de extensiones disponibles según el nivel de API de extensiones declarado. Si hay una falta de coincidencia, WindowManager puede inhabilitar el uso de extensiones (parcial o completamente) y informar que las funciones pertinentes no están disponibles para la aplicación.

Las extensiones de WindowManager se implementan como un módulo system_ext que usa APIs privadas de la plataforma para llamar al núcleo de WindowManager, DeviceStateManager, y otros servicios del sistema en la implementación de las funciones de extensiones.

Es posible que no se mantenga la compatibilidad con las versiones preliminares de extensiones antes de la versión trimestral o anual correspondiente de la plataforma de Android con la que se finalizan las versiones. El historial completo de las APIs de extensiones se puede encontrar en los archivos de texto de la API de la rama de lanzamiento window:extensions:extensionsfiles.

Las versiones más recientes de extensiones deben seguir funcionando con versiones anteriores de WindowManager compiladas en aplicaciones para mantener la compatibilidad con versiones posteriores. Para garantizar esto, cualquier versión nueva de la API de extensiones solo agrega APIs nuevas y no quita las anteriores. Como resultado, las aplicaciones con versiones anteriores de WindowManager pueden seguir usando las APIs de extensiones anteriores con las que se compilaron las apps.

La verificación de CTS garantiza que, para cualquier versión declarada de las APIs de extensiones en el dispositivo, todas las APIs de esa versión y las anteriores estén presentes y funcionen.

Rendimiento

El módulo de extensiones se almacena en caché en los cargadores de clases del sistema que no son bootclasspath de forma predeterminada a partir de Android 14 (nivel de API 34), por lo que no hay impacto en el rendimiento debido a la carga del módulo en la memoria al inicio de la app. El uso de funciones de módulos individuales puede tener una ligera influencia en las características de rendimiento de las apps cuando se realizan llamadas IPC adicionales entre el cliente y el servidor.

Módulos

Incorporación de actividad

El componente de incorporación de actividad permite que las aplicaciones optimicen su IU para dispositivos de pantalla grande y pantallas externas. La incorporación de actividad permite la presentación de dos actividades en paralelo en un diseño de varios paneles, lo que facilita el desarrollo de apps adaptables para aplicaciones heredadas.

El componente de incorporación de actividad debe estar disponible en todos los dispositivos que tengan una pantalla integrada igual o superior a sw600dp. La incorporación de actividad también debe habilitarse en dispositivos que admitan conexiones de pantallas externas, ya que la aplicación podría mostrarse en un tamaño más grande cuando las pantallas externas estén conectadas en el tiempo de ejecución.

Configuración del dispositivo

No se necesita ninguna configuración específica del dispositivo, además de habilitar el módulo de extensiones como se describe en la sección Distribución del módulo de extensiones. Es conveniente habilitar las extensiones en todos los dispositivos que admitan el modo multiventana. Es probable que las versiones futuras de Android requieran extensiones en las configuraciones comunes de dispositivos portátiles y de pantalla grande.

Información del diseño de la ventana

El componente de información del diseño de la ventana identifica la posición y el estado de la bisagra en un dispositivo plegable cuando la bisagra cruza una ventana de la aplicación. La información del diseño de la ventana permite que las aplicaciones respondan y muestren diseños optimizados en el modo de mesa en dispositivos plegables. Consulta Cómo hacer que tu app funcione en dispositivos plegables para obtener detalles de uso.

Los dispositivos Android plegables que incluyen una bisagra que conecta áreas de panel de visualización separadas o continuas deben poner a disposición de las aplicaciones la información sobre la bisagra a través de WindowLayoutComponent.

La posición y los límites de la bisagra deben informarse en relación con la ventana de la aplicación identificada por un Context que se pasa a la API. Si los límites de la ventana de la aplicación no se intersecan con los límites de la bisagra, la bisagra DisplayFeature no se debe informar. También es aceptable no informar las funciones de visualización cuando su posición no se pueda informar de manera confiable, como cuando el usuario puede mover libremente una ventana de la aplicación en el modo multiventana o en el modo de letterboxing de compatibilidad.

Para las funciones de plegado , las actualizaciones de estado se deben informar cuando la posición de la bisagra cambia entre los estados estables. De forma predeterminada, en un estado de visualización plana, la API debe informar FoldingFeature.State.FLAT. Si el hardware del dispositivo se puede dejar en un modo medio plegado en un estado estable, la API debe informar FoldingFeature.State.HALF_OPENED. No hay un estado cerrado en la API, ya que, en ese caso, la ventana de la aplicación no estaría visible o no cruzaría los límites de la bisagra.

Configuración del dispositivo

Para admitir la implementación de la función de plegado, los OEMs deben hacer lo siguiente:

  • Configurar los estados del dispositivo en device_state_configuration.xml para que los use DeviceStateManagerService. Consulta DeviceStateProviderImpl.java como referencia.

    Si las implementaciones predeterminadas de DeviceStateProvider o DeviceStatePolicy no son adecuadas para el dispositivo, se puede usar una implementación personalizada.

  • Habilita el módulo de extensiones como se describe en la sección Distribución del módulo de extensiones .

  • Especifica la ubicación de las funciones de visualización en el recurso de cadena com.android.internal.R.string.config_display_features (por lo general, en frameworks/base/core/res/res/values/config.xml en la superposición del dispositivo).

    El formato esperado para la cadena es el siguiente:

    <type>-[<left>,<top>,<right>,<bottom>]

    El type puede ser fold o hinge. Los valores de left, top, right y bottom son coordenadas de píxeles enteros en el espacio de coordenadas de visualización en la orientación de visualización natural. La cadena de configuración puede contener varias funciones de visualización separadas por punto y coma.

    Por ejemplo:

    <!-- Jetpack WindowManager display features -->
    <string name="config_display_features" translatable="false">fold-[1000,0,1000,2000]</string>
    
  • Define la asignación entre los identificadores de estado internos del dispositivo que se usan en DeviceStateManager y las constantes de estado públicas que se envían a los desarrolladores en com.android.internal.R.array.config_device_state_postures.

    El formato esperado para cada entrada es el siguiente:

    <device_specific_state_identifier>:<Jetpack WindowManager state identifier>

    Los identificadores de estado compatibles son los siguientes:

    • COMMON_STATE_NO_FOLDING_FEATURES = 1: El estado no tiene funciones de plegado para informar. Por ejemplo, puede ser el estado cerrado del dispositivo plegable típico con la pantalla principal en el lado interior.
    • COMMON_STATE_HALF_OPENED = 2: La función de plegado está medio abierta.
    • COMMON_STATE_FLAT = 3: La función de plegado es plana. Por ejemplo, puede ser el estado abierto del dispositivo plegable típico con la pantalla principal en el lado interior.
    • COMMON_STATE_USE_BASE_STATE = 1000: En Android 14, un valor que se puede usar para estados emulados en los que el estado de la bisagra se deriva con el estado base, como se define en CommonFoldingFeature.java

    See DeviceStateManager.DeviceStateCallback#onBaseStateChanged(int) for more information.

    Por ejemplo:

    <!-- Map of System DeviceState supplied by DeviceStateManager to WindowManager posture.-->
    <string-array name="config_device_state_postures" translatable="false">
      <item>0:1</item>    <!-- CLOSED       : COMMON_STATE_NO_FOLDING_FEATURES -->
      <item>1:2</item>    <!-- HALF_OPENED  : COMMON_STATE_HALF_OPENED -->
      <item>2:3</item>    <!-- OPENED       : COMMON_STATE_FLAT -->
      <item>3:1</item>    <!-- REAR_DISPLAY : COMMON_STATE_NO_FOLDING_FEATURES -->
      <item>4:1000</item> <!-- CONCURRENT   : COMMON_STATE_USE_BASE_STATE -->
    </string-array>
    

Área de la ventana

El componente de área de la ventana proporciona un conjunto de funciones que brindan a las aplicaciones acceso a pantallas y áreas de visualización adicionales en algunos dispositivos plegables y de varias pantallas.

El modo de pantalla posterior permite que una aplicación muestre la IU de vista previa de la cámara en la pantalla de la cubierta de un dispositivo plegable para permitir el uso de la cámara principal del dispositivo para selfies y videos. Los dispositivos que tienen una pantalla de cubierta compatible con Android (como se define en el CDD de Android en términos de atributos como tamaño, densidad y recursos de navegación disponibles) que se alinea con las cámaras posteriores del dispositivo deben proporcionar acceso al modo de pantalla posterior.

En Android 14, el modo de doble pantalla permite que las aplicaciones que se ejecutan en la pantalla interior de un dispositivo plegable muestren contenido adicional en la pantalla de la cubierta orientada a otros usuarios. Por ejemplo, la pantalla de la cubierta puede mostrar la vista previa de la cámara a la persona que se está fotografiando o grabando.

Configuración del dispositivo

Para admitir la implementación de la función de plegado, los OEMs deben hacer lo siguiente:

  • Configurar los estados del dispositivo en device_state_configuration.xml para que los use DeviceStateManagerService. Consulta DeviceStateProviderImpl.java para obtener más información.

    Si la implementación predeterminada de DeviceStateProvider o DeviceStatePolicy no es adecuada para el dispositivo, se puede usar una implementación personalizada.

  • Para los dispositivos plegables que admiten el modo abierto o plano, especifica los identificadores de estado correspondientes en com.android.internal.R.array.config_openDeviceStates.

  • Para los dispositivos plegables que admiten estados plegados, enumera los identificadores de estado correspondientes en com.android.internal.R.array.config_foldedDeviceStates.

  • Para los dispositivos plegables que admiten un estado medio plegado (la bisagra está medio abierta como una laptop), enumera los estados correspondientes en com.android.internal.R.array.config_halfFoldedDeviceStates.

  • Para los dispositivos que admiten el modo de pantalla posterior:

    • Enumera los estados correspondientes en com.android.internal.R.array.config_rearDisplayDeviceStates para DeviceStateManager.
    • Especifica la dirección física de la pantalla posterior en com.android.internal.R.string.config_rearDisplayPhysicalAddress.
    • Especifica el identificador de estado en com.android.internal.R.integer.config_deviceStateRearDisplay para que lo usen las extensiones.
    • Agrega el identificador de estado en com.android.internal.R.array.config_deviceStatesAvailableForAppRequests para que esté disponible para las aplicaciones.
  • En Android 14, para los dispositivos que admiten el modo de doble pantalla (simultánea):

    • Establece com.android.internal.R.bool.config_supportsConcurrentInternalDisplays en true.
    • Especifica la dirección física de la pantalla posterior en com.android.internal.R.config_deviceStateConcurrentRearDisplay.
    • Especifica el identificador de estado en com.android.internal.R.integer.config_deviceStateConcurrentRearDisplay para que lo usen las extensiones si el identificador está destinado a estar disponible para las aplicaciones.
    • Agrega el identificador de estado en com.android.internal.R.array.config_deviceStatesAvailableForAppRequests para que esté disponible para las aplicaciones.

Verificación

Los OEMs deben verificar sus implementaciones para garantizar el comportamiento esperado en situaciones comunes. Las pruebas de CTS y las pruebas con WindowManager de Jetpack están disponibles para que los OEMs prueben las implementaciones.

Pruebas de CTS

Para ejecutar las pruebas de CTS, consulta Cómo ejecutar pruebas de CTS. Las pruebas de CTS relacionadas con WindowManager de Jetpack se encuentran en cts/tests/framework/base/windowmanager/jetpack/. El nombre del módulo de prueba es CtsWindowManagerJetpackTestCases.

Pruebas de WindowManager

Para descargar las pruebas de WindowManager de Jetpack, sigue las instrucciones de Android Jetpack. Las pruebas se encuentran en la biblioteca de ventanas en el módulo window:window: window/window/src/androidTest/.

Para ejecutar las pruebas del dispositivo para el módulo window:window desde la línea de comandos, haz lo siguiente:

  1. Conecta un dispositivo que tenga habilitadas las opciones para desarrolladores y la depuración por USB.
  2. Permite que la computadora depure el dispositivo.
  3. Abre un shell en el directorio raíz del repositorio de androidx.
  4. Cambia el directorio a framework/support.
  5. Ejecuta el siguiente comando: ./gradlew window:window:connectedAndroidTest.
  6. Analiza los resultados.

Para ejecutar las pruebas desde Android Studio, haz lo siguiente:

  1. Abre Android Studio.
  2. Conecta un dispositivo que tenga habilitadas las opciones para desarrolladores y la depuración por USB.
  3. Permite que la computadora depure el dispositivo.
  4. Navega a una prueba dentro de la biblioteca de ventanas del módulo de ventana.
  5. Abre una clase de prueba y ejecútala con las flechas verdes en el lado derecho del editor.

Como alternativa, puedes crear una configuración en Android Studio para ejecutar un método de prueba, una clase de prueba o todas las pruebas en un módulo.

Los resultados se pueden analizar de forma manual mirando el resultado del shell. Se omiten algunas pruebas si el dispositivo no cumple con ciertos supuestos. Los resultados se guardan en una ubicación estándar, y los analistas pueden escribir una secuencia de comandos para automatizar el análisis de los resultados.