Compatibilidad con tamaños de página de 16 KB

Hasta ahora, Android solo admitía tamaños de página de memoria de 4 KB, que tienen rendimiento optimizado de la memoria del sistema para la cantidad promedio de memoria total que Los dispositivos Android solían tener. A partir de Android 15, AOSP admite dispositivos configurados para usar un tamaño de página de 16 KB (16 KB) dispositivos). Si tu app usa bibliotecas del NDK, hazlo directamente o indirectamente a través de un SDK, tendrás que recompilar tu app para que Funciona en estos dispositivos de 16 KB.

A medida que los fabricantes siguen creando dispositivos con mayores cantidades memoria física (RAM), muchos de estos dispositivos adoptarán 16 KB (y eventualmente mayores) para optimizar el rendimiento del dispositivo. Agregando la compatibilidad con dispositivos de tamaño de página de 16 KB permite que tu app se ejecute en estos y ayuda a que tu app se aproveche del rendimiento asociado mejoras continuas. Sin la recompilación, es posible que las apps no funcionen en dispositivos de 16 KB. cuando se producen en versiones futuras de Android.

Para ayudarte a que tu aplicación sea compatible, proporcionamos orientación sobre cómo verificar si tu app se ve afectada, cómo volver a compilar tu app (si corresponde) y saber cómo probarla en un entorno de 16 KB con emuladores (incluido Android 15 imágenes del sistema para Android Emulator).

Beneficios y mejoras de rendimiento

Los dispositivos configurados con tamaños de página de 16 KB usan un poco más de memoria en promedio, pero también obtienen varias mejoras de rendimiento para el sistema y las apps:

  • Tiempos de inicio de la app más bajos mientras el sistema está bajo presión de memoria: un 3.16% más bajo en promedio, con mejoras más significativas (hasta un 30%) para algunas apps que probamos
  • Menor consumo de energía durante el lanzamiento de la app: Reducción promedio del 4.56%
  • Inicio más rápido de la cámara: Inicios en caliente un 4.48% más rápidos en promedio y, en promedio, un 6.60% más rápidos en frío
  • Mejor tiempo de inicio del sistema: se mejoró en un 8% (aproximadamente 950 milisegundos) en promedio.

Estas mejoras se basan en nuestras pruebas iniciales, y es probable que los resultados en los dispositivos reales difieran. Proporcionaremos análisis adicionales de posibles ganancias para las apps a medida que continuemos con las pruebas.

Verifica si tu app se ve afectada

Si tu app usa código nativo, debes volver a compilarla con compatibilidad para dispositivos de 16 KB. Si no estás seguro de si tu app usa código nativo, puedes usar el Analizador de APK para identificar si hay código nativo y, luego, revisar la alineación de los segmentos ELF para detectar bibliotecas compartidas.

Si tu app solo usa código escrito en el lenguaje de programación Java o Kotlin, incluidos todos los SDKs y las bibliotecas, quiere decir que es compatible con dispositivos de 16 KB. Sin embargo, te recomendamos que pruebes tu app en un entorno de 16 KB para verificar que no haya regresiones inesperadas en el comportamiento de la app.

¿Tu app usa código nativo?

Tu app usa código nativo si se cumple alguna de las siguientes condiciones:

  • Si tu app usa código (nativo) C/C++. Si tu app usa el NDK de Android, significa que usa código nativo.
  • Tu app se vincula con cualquier biblioteca o dependencia nativa de terceros (como los SDKs) que las usen.
  • Tu app se compiló mediante un compilador de apps de terceros que usa bibliotecas nativas en el dispositivo.

Identifica bibliotecas nativas con el Analizador de APK

El Analizador de APK es una herramienta que te permite evaluar varios aspectos de un APK compilado. Para identificar si tu app usa código nativo o bibliotecas, sigue estos pasos:

  1. Abre Android Studio, haz clic en File > Open y elige cualquier proyecto.
  2. En la barra de menú, haz clic en Build > Analyze APK….

    Opción del menú Build de Studio para iniciar el Analizador de APK

  3. Elige el APK que quieres analizar.

  4. Busca en la carpeta lib, que aloja archivos de objetos compartidos (.so) si los hay. Si hay archivos de objetos compartidos, tu app usa código nativo. Si no hay archivos de objetos compartidos o no hay una carpeta lib, tu app no usa código nativo.

    Vista del Analizador de APK que muestra que hay archivos de objetos compartidos

Verifica la alineación de los segmentos ELF para las bibliotecas compartidas

En el caso de las bibliotecas compartidas, verifica que los segmentos ELF de las bibliotecas compartidas estén alineados correctamente con la alineación ELF de 16 KB. Si desarrollas en Linux o macOS, puedes usar la secuencia de comandos check_elf_alignment.sh como se describe en la siguiente sección. También puedes usar las herramientas de línea de comandos directamente.

Usa la secuencia de comandos check_elf_alignment.sh (Linux o macOS)

Sigue estos pasos para verificar la alineación de los segmentos ELF con la secuencia de comandos check_elf_alignment.sh:

  1. Guarda la secuencia de comandos check_elf_alignment.sh en un archivo.

  2. Ejecuta la secuencia de comandos en el archivo APK de tu app:

    check_elf_alignment.sh APK_NAME.apk
    

    La secuencia de comandos muestra ALIGNED o UNALIGNED para todas las bibliotecas compartidas de arm64-v8a.

  3. Si alguna biblioteca compartida de arm64-v8a o x86_64 es UNALIGNED, deberás actualizar el empaquetado de esas bibliotecas, volver a compilar tu app y volver a realizar la prueba siguiendo los pasos de esta sección.

Usa herramientas de línea de comandos directamente

Sigue estos pasos para verificar la alineación de los segmentos ELF con herramientas de línea de comandos directamente:

  1. Asegúrate de que la versión 35.0.0 o posterior de las Herramientas de compilación del SDK de Android y el NDK de Android estén instalados con el Administrador de SDK en Android Studio o la herramienta de línea de comandos sdkmanager.
  2. Extrae el archivo APK de tu app:

    Linux o macOS

    unzip APK_NAME.apk -d /tmp/my_apk_out
    

    Windows (PowerShell)

    Expand-Archive -Path .\APK_NAME.apk -DestinationPath ~\tmp\my_apk_out
    
  3. En el directorio temporal al que extrajiste el archivo APK, verifica el contenido del directorio lib en busca de archivos de objetos compartidos (.so). Estos son los mismos archivos de objetos compartidos que verías cuando identificas bibliotecas nativas con el Analizador de APK. Ejecuta el siguiente comando en cada archivo de objeto compartido:

    Linux o macOS

    SDK_ROOT_LOCATION/Android/sdk/ndk/NDK_VERSION/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-objdump -p SHARED_OBJECT_FILE.so | grep LOAD
    

    Windows (PowerShell)

    SDK_ROOT_LOCATION\Android\sdk\ndk\NDK_VERSION\toolchains\llvm\prebuilt\windows-x86_64\bin\llvm-objdump.exe -p SHARED_OBJECT_FILE.so | Select-String -Pattern "LOAD"
    

    En el que SDK_ROOT_LOCATION es la ruta de acceso al directorio en el que instalaste el SDK de Android, SHARED_OBJECT_FILE es el nombre del archivo de objeto compartido que estás verificando y NDK_VERSION es la versión del NDK de Android que instalaste (por ejemplo, 28.0.12433566). El resultado se verá de la siguiente manera para cada archivo que verifiques:

    LOAD off    0x0000000000000000 vaddr 0x0000000000000000 paddr 0x0000000000000000 align 2**14
    LOAD off    0x0000000000042a90 vaddr 0x0000000000043a90 paddr 0x0000000000043a90 align 2**14
    LOAD off    0x0000000000046230 vaddr 0x0000000000048230 paddr 0x0000000000048230 align 2**14
    
  4. Verifica las líneas de salida para asegurarte de que los segmentos de carga no tengan valores menores que 2**14. Si algún segmento de carga es 2**13, 2**12 o valores inferiores, deberás actualizar el empaquetado de esas bibliotecas, luego volver a compilar tu app y volver a realizar la prueba siguiendo los pasos que se indican en esta sección.

  5. A continuación, ejecuta la herramienta de línea de comandos de zipalign en el archivo APK de tu app:

    Linux o macOS

    SDK_ROOT_LOCATION/Android/sdk/build-tools/35.0.0/zipalign -v -c -P 16 4 APK_NAME.apk
    

    Windows (PowerShell)

    SDK_ROOT_LOCATION\Android\sdk\build-tools\35.0.0\zipalign.exe -v -c -P 16 4 APK_NAME.apk
    

    Donde SDK_ROOT_LOCATION es la ruta de acceso al directorio en el que instalaste el SDK de Android, y APK_NAME es el nombre del archivo APK de tu app. La última línea del resultado dirá "Verification successful" si todas las bibliotecas compartidas están alineadas correctamente.

    Si la verificación falló, es necesario volver a alinear algunas bibliotecas compartidas, por lo que deberás actualizar el empaquetado de esas bibliotecas, luego volver a compilar tu app y volver a realizar la prueba siguiendo los pasos que se indican en esta sección.

Compila tu app con compatibilidad con dispositivos de 16 KB

Para admitir dispositivos de 16 KB, las apps que usan código nativo deben completar los pasos que se describen en las siguientes secciones. Si actualizas a la versión 8.5.1 o posterior de AGP y a la versión r28 o posterior del NDK, y usas dependencias precompiladas compatibles con 16 KB, las apps serán compatibles con 16 KB de forma predeterminada.

Actualiza el empaquetado de tus bibliotecas compartidas

Te recomendamos que actualices a la versión 8.5.1 de AGP o una posterior y que uses bibliotecas compartidas sin comprimir.

AGP versión 8.5.1 o posterior

Los dispositivos de 16 KB requieren apps que se envíen con bibliotecas compartidas sin comprimir para alinearlas en un límite de 16 KB alineado con ZIP. Para ello, debes actualizar a la versión 8.5.1 o posterior del complemento de Android para Gradle (AGP). Consulta la sección Asistente de actualización del complemento de Android para Gradle para obtener detalles sobre el proceso de actualización.

AGP versión 8.5 o versiones anteriores

Si no puedes actualizar AGP a la versión 8.5.1 o una posterior, la alternativa es cambiar a bibliotecas compartidas comprimidas. Actualiza la configuración de Gradle para que Gradle comprima tus bibliotecas compartidas cuando empaquetes tu app para evitar problemas de instalación de la app con bibliotecas compartidas no alineadas.

Groovy

En tu archivo build.gradle, agrega la siguiente opción:

android {
  ...
  packagingOptions {
      jniLibs {
        useLegacyPackaging true
      }
  }
}

Kotlin

En tu archivo build.gradle.kts, agrega la siguiente opción:

android {
  ...
  packagingOptions {
      jniLibs {
        useLegacyPackaging = true
      }
  }
}

Compila tu app con alineación ELF de 16 KB

Los dispositivos de 16 KB requieren que los segmentos ELF de las bibliotecas compartidas se alineen correctamente con la alineación ELF de 16 KB para que se ejecute la app.

Para compilar tu app con alineación ELF de 16 KB, completa los pasos de una de las siguientes secciones según la versión del NDK de Android que uses.

NDK de Android r28 y versiones posteriores

La versión r28 del NDK y versiones posteriores compilan 16 KB alineados de forma predeterminada.

NDK de Android r27

Para admitir la compilación de bibliotecas compartidas alineadas de 16 KB con la versión r27 del NDK de Android y versiones posteriores, debes actualizar las marcas ndk-build, build.gradle, build.gradle.kts o del vinculador de la siguiente manera:

ndk-build

En tu Application.mk:

APP_SUPPORT_FLEXIBLE_PAGE_SIZES := true

Groovy

En tu archivo build.gradle, establece el argumento -DANDROID_SUPPORT_FLEXIBLE_PAGE_SIZES=ON:

android {
  ...
  defaultConfig {
    ...
    // This block is different from the one you use to link Gradle
    // to your CMake or ndk-build script.
    externalNativeBuild {
      // For ndk-build, instead use the ndkBuild block.
      cmake {
        // Passes optional arguments to CMake.
        arguments "-DANDROID_SUPPORT_FLEXIBLE_PAGE_SIZES=ON"
      }
    }
  }
}

Kotlin

En tu archivo build.gradle.kts, establece el argumento -DANDROID_SUPPORT_FLEXIBLE_PAGE_SIZES=ON:

android {
  ...
  defaultConfig {
    ...
    // This block is different from the one you use to link Gradle
    // to your CMake or ndk-build script.
    externalNativeBuild {
      // For ndk-build, instead use the ndkBuild block.
      cmake {
        // Passes optional arguments to CMake.
        arguments += listOf("-DANDROID_SUPPORT_FLEXIBLE_PAGE_SIZES=ON")
      }
    }
  }
}

Otros sistemas de compilaciones

Especifica las siguientes marcas del vinculador:

-Wl,-z,max-page-size=16384

NDK de Android r26 y versiones anteriores

Para admitir la compilación de bibliotecas compartidas alineadas de 16 KB con la versión r26 o anterior del NDK de Android, debes actualizar la configuración de ndk-build o cmake de la siguiente manera:

ndk-build

Actualiza tu Android.mk para habilitar la alineación ELF de 16 KB:

LOCAL_LDFLAGS += "-Wl,-z,max-page-size=16384"

CMake

Actualiza tu CMakeLists.txt para habilitar la alineación ELF de 16 KB:

target_link_options(${CMAKE_PROJECT_NAME} PRIVATE "-Wl,-z,max-page-size=16384")

Verifica si hay instancias de código que hagan referencia a tamaños de página específicos

Incluso si tu app está alineada en 16 KB, puede encontrar errores si en algunos lugares de tu código se supone que un dispositivo usa un tamaño de página específico. Para evitar esto, completa los siguientes pasos:

  1. Quita las dependencias fijas que hagan referencia a la constante PAGE_SIZE o a instancias en la lógica de tu código que den por sentado que el tamaño de página de un dispositivo es de 4 KB (4096).

    En su lugar, usa getpagesize() o sysconf(_SC_PAGESIZE).

  2. Busca usos de mmap() y otras APIs que requieran argumentos alineados con la página y reemplázalos por alternativas cuando sea necesario.

En algunos casos, si tu app usa PAGE_SIZE como un valor conveniente que no está vinculado al tamaño de página subyacente, esto no hará que la app falle cuando se use en el modo de 16 KB. Sin embargo, si este valor se pasa al kernel con mmap sin MAP_FIXED, el kernel aún usa una página completa, lo que desperdicia memoria. Por estos motivos, PAGE_SIZE no se define cuando se habilita el modo de 16 KB en el NDK r27 y versiones posteriores.

Si tu app usa PAGE_SIZE de esta manera y nunca pasa este valor directamente al kernel, en lugar de usar PAGE_SIZE, crea una variable nueva con un nombre nuevo para reflejar que se usa para otros fines y no refleja una página de memoria real.

Verifica la compatibilidad de los SDKs con 16 KB

Muchos SDKs son compatibles con tamaños de página de 16 KB, en especial si los compilas por tu cuenta o obtienes compilaciones previas recientes. Sin embargo, como algunas compilaciones previas o versiones del SDK no son compatibles con 16 KB, debes consultar el sitio web de cada proveedor del SDK para determinar qué versión usar con 16 KB.

Prueba tu app en un entorno de 16 KB

Después de compilar tu app con compatibilidad para dispositivos de 16 KB, te recomendamos que la pruebes en un entorno de 16 KB para ver si experimenta alguna regresión. Para hacerlo, sigue estos pasos:

  1. Configura el SDK de Android 15.

  2. Configura uno de los siguientes entornos de prueba:

  3. Inicia el dispositivo de prueba y, luego, ejecuta el siguiente comando para verificar que esté usando un entorno de 16 KB:

    adb shell getconf PAGE_SIZE
    

    El comando debería mostrar un valor de 16384.

  4. Ejecuta el siguiente comando zipalign para verificar que tu app esté alineada con 16 KB, en el que APK_NAME es el nombre del archivo APK de tu app:

    zipalign -c -P 16 -v 4 APK_NAME.apk
    
  5. Prueba tu app en detalle y enfócate en las áreas que podrían verse afectadas por el cambio de instancias de código que hacen referencia a tamaños de página específicos.

Configura Android Emulator con una imagen del sistema de Android 15 basada en 16 KB

Para configurar un entorno de 16 KB con Android Emulator, sigue estos pasos:

  1. Las imágenes del sistema del emulador de Android 15 basadas en 16 KB son compatibles con Android Studio Jellyfish | 2023.3.1 o versiones posteriores. Sin embargo, para obtener la mejor experiencia cuando trabajes con la versión beta de Android 15, descarga la versión preliminar más reciente de Android Studio.

    Recuerda que no es necesario desinstalar la versión actual que tienes de Android Studio, ya que puedes tener varias versiones instaladas al mismo tiempo.

  2. En Android Studio, haz clic en Tools > SDK Manager.

  3. En la pestaña SDK Platforms, marca Show Package Details y, luego, expande la sección Android VanillaIceCream Preview y selecciona una o ambas de las siguientes imágenes del sistema del emulador, según los dispositivos virtuales que quieras crear:

    • Imagen del sistema experimental de APIs de Google con tamaño de página de 16 K y ARM 64 v8a
    • Imagen del sistema experimental de Google APIs con tamaño de página de 16 K para Intel x86_64 Atom

    Descarga imágenes del sistema del emulador de 16 KB con SDK Manager en Android Studio

  4. Haz clic en Apply > OK para descargar las imágenes del sistema que seleccionaste.

  5. Sigue los pasos para configurar un dispositivo virtual para Android 15 y, cuando se te solicite que selecciones una imagen del sistema, elige la imagen del sistema de 16 KB que descargaste. Si no se recomienda automáticamente, puedes encontrar la imagen del sistema de 16 KB en la pestaña Otras imágenes.

    Busca la imagen del emulador de 16 KB en la pestaña Otras imágenes.

  1. En el Administrador de dispositivos, haz clic en los 3 puntos junto a la imagen de 16 KB y, luego, en Mostrar en el disco.
  2. En esta carpeta, busca el archivo config.ini.
  3. Agrega la siguiente línea al archivo config.ini y guarda los cambios:

    kernel.parameters = androidboot.page_shift=14
    
  4. Para verificar los cambios, ejecuta el siguiente comando, que debería mostrar 16384:

    adb shell getconf PAGE_SIZE
    

Cómo habilitar el modo de 16 KB en un dispositivo mediante las opciones para desarrolladores

Activa o desactiva el desarrollador de Inicio con un tamaño de página de 16 KB. para iniciar un dispositivo en modo de 16 KB.

A partir de QPR1 para Android 15, puedes utilizar la opción para desarrolladores que está disponible en determinados que inicien el dispositivo en modo de 16 KB y realicen pruebas en el dispositivo.

Esta opción para desarrolladores está disponible en los siguientes dispositivos:

  • Pixel 8 y 8 Pro (con Android 15 QPR1 beta 1 o versiones posteriores)