支持 16 KB 的页面大小

Android 过去仅支持 4 KB 内存页面大小, 优化了系统内存性能,以针对 Android 设备通常具备的功能。从 Android 15 开始,AOSP 支持 配置为使用 16 KB (16 KB) 页面大小的设备 设备)。如果您的应用使用任何 NDK 库,请直接使用 或者通过 SDK 间接创建,那么,您需要重新构建自己的应用 支持这些 16KB 设备。

随着设备制造商不断打造出 物理内存 (RAM),许多此类设备都会采用 16KB(以及 页面大小以优化设备的性能。正在添加 支持 16 KB 页面大小的设备,可使您的应用在这些设备上运行 并有助于您的应用从相关的广告效果中获益 改进。如果不重新编译,应用可能无法在 16KB 设备上运行 在未来的 Android 版本中正式推出。

为帮助您为应用添加支持,我们提供了有关如何检查 如果您的应用受到影响 重新构建您的应用(如果适用),以及如何在 Google Play 中 使用模拟器(包括 Android 15)的 16 KB 环境 系统映像)。

优势和性能提升

配置为 16 KB 页面的设备平均使用的内存会略多,但系统和应用性能也会有所提升:

  • 在系统面临内存压力时缩短应用启动时间:平均降低了 3.16%,对于我们测试过的一些应用而言,改进幅度更显著(提升幅度高达 30%)
  • 降低应用启动时的功耗:平均降低 4.56%
  • 相机启动速度更快:平均热启动速度加快 4.48%,冷启动速度平均加快 6.60%
  • 缩短了系统启动时间:平均缩短了 1.5%(约 0.8 秒)

这些改进基于我们的初始测试,实际设备上的结果可能会有所不同。在继续测试的过程中,我们会进一步分析应用的潜在益处。

检查您的应用是否受到影响

如果您的应用使用任何原生代码,则您应重新构建支持 16 KB 设备的应用。如果您不确定自己的应用是否使用了原生代码,可以使用 APK 分析器来确定是否存在任何原生代码

如果您的应用仅使用以 Java 编程语言或 Kotlin 编写的代码(包括所有库或 SDK),那么该应用已经支持 16 KB 设备。不过,我们建议您在 16 KB 的环境中测试应用,以确认应用行为是否存在意外回归问题。

您的应用是否使用了原生代码?

如果符合以下任一条件,则您的应用会使用原生代码:

  • 您的应用使用了任何 C/C++(原生)代码。如果您的应用使用的是 Android NDK,那么应用将使用原生代码。
  • 您的应用会与任何第三方原生库或依赖项相关联, 使用它们。
  • 您的应用由第三方应用构建程序构建,该构建程序使用 设备。

使用 APK 分析器识别原生库

APK 分析器是一款工具,可让您评估 build 的各个方面 APK。如需确定您的应用使用的是原生代码还是库,请按照以下提示操作 步骤:

  1. 打开 Android Studio,然后依次点击 File >打开并选择任意项目。
  2. 从菜单栏中,点击 Build >分析 APK...

    用于启动 APK 的 Studio Build 菜单选项
分析器

  3. 选择要分析的 APK。

  4. 查看 lib 文件夹,此文件夹中托管了共享对象 (.so) 文件(如有) 。如果存在任何共享对象文件,您的应用将使用原生 代码。如果不存在共享对象文件或没有 lib 文件夹, 那么您的应用就不会使用原生代码。

    APK 分析器视图显示共享对象文件
展示

构建支持 16KB 设备的应用

要支持 16 KB 设备,使用原生代码的应用应完成 具体步骤如下。

更新共享库的打包

我们建议您升级到 AGP 版本 8.3 或更高版本,并使用未压缩的 共享库。

AGP 版本 8.3 或更高版本

16 KB 设备要求附带未压缩共享库的应用 在 16 KB 压缩对齐边界上对齐。为此,您需要升级 Android Gradle 插件 (AGP) 8.3 或更高版本。请参阅 Android Gradle 插件升级助理部分,详细了解升级流程。

AGP 版本 8.2 或更低版本

如果您无法将 AGP 升级到版本 8.3 或更高版本,则替代方案是 改用压缩的共享库。将 Gradle 配置更新为 在打包应用时,让 Gradle 压缩共享库,以避免应用 未对齐的共享库的安装问题。

Groovy

build.gradle 文件中,添加以下选项:

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

Kotlin

build.gradle.kts 文件中,添加以下选项:

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

使用 16 KB ELF 对齐编译您的应用

16 KB 设备需要共享库的要对齐的 ELF 细分 正确使用 16 KB ELF 对齐,以便您的应用运行。

如需使用 16 KB ELF 对齐编译您的应用,请完成以下任一步骤 以下部分,具体取决于您要安装的 Android NDK 版本 使用。

Android NDK r26 及更低版本

支持使用 Android NDK 编译 16 KB 对齐的共享库 版本 r26 或更低版本,则需要更新 ndk-buildcmake 配置如下:

ndk-build

更新 Android.mk 以启用 16 KB ELF 对齐:

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

CMake

更新 CMakeLists.txt 以启用 16 KB ELF 对齐:

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

Android NDK r27 及更高版本

支持使用 Android NDK 编译 16 KB 对齐的共享库 版本 r27 及更高版本,则需要更新 ndk-buildbuild.gradle build.gradle.kts 或链接器标记,如下所示:

ndk-build

在您的 Application.mk 中:

APP_SUPPORT_FLEXIBLE_PAGE_SIZES := true

Groovy

build.gradle 文件中,设置参数 -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

build.gradle.kts 文件中,设置参数 -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")
      }
    }
  }
}

其他构建系统

指定以下链接器标志:

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

检查引用特定页面大小的代码实例

即使您的应用是 16 KB 对齐的,如果将 会假定设备使用的是特定的页面大小。为了避免这种情况 请完成以下步骤:

  1. 移除所有引用 PAGE_SIZE 的硬编码依赖项 常量或实例,它假定设备的页面 大小为 4 KB (4096)。

    请改用 getpagesize()sysconf(_SC_PAGESIZE)

  2. 查看是否使用了 mmap() 和其他需要页面对齐的 API 参数,并在必要时替换为替代参数。

在某些情况下,如果您的应用将 PAGE_SIZE 作为一个不方便使用的值, 与底层页面大小相关联,那么这不会导致应用中断 当在 16 KB 模式下使用时。不过,如果将该值传递给内核, 对于不带 MAP_FIXEDmmap,内核仍会使用整个页面, 会浪费一些内存因此,当大小为 16 KB 时,未定义 PAGE_SIZE。 模式在 NDK r27 及更高版本中启用。

如果您的应用以这种方式使用 PAGE_SIZE,并且从未将此值直接传递给 则不使用 PAGE_SIZE,而是创建一个具有新变量的新变量 表明相应信息已用于其他用途,并不反映真实情况 内存页。

在 16 KB 的环境中测试您的应用

在构建支持 16KB 设备的应用后,您需要 在 16 KB 环境中测试您的应用,看看您的应用能否正常体验 任何回归问题。为此,请按以下步骤操作:

  1. 设置 Android 15 SDK

  2. 设置以下测试环境之一:

  3. 启动测试设备,然后运行以下命令来验证 它使用的是 16 KB 的环境:

    adb shell getconf PAGE_SIZE
    

    该命令应返回值 16384

  4. 对于任何共享库,请确认共享库的ELF 细分 使用 16 KB ELF 对齐进行正确对齐。您可以使用此脚本 有关此流程的帮助:

    #!/bin/bash
    
    # usage: alignment.sh path to search for *.so files
    
    dir="$1"
    
    RED="\e[31m"
    GREEN="\e[32m"
    ENDCOLOR="\e[0m"
    
    matches="$(find $dir -name "*.so" -type f)"
    IFS=$'\n'
    for match in $matches; do
      res="$(objdump -p ${match} | grep LOAD | awk '{ print $NF }' | head -1)"
      if [[ $res =~ "2**14" ]] || [[ $res =~ "2**16" ]]; then
        echo -e "${match}: ${GREEN}ALIGNED${ENDCOLOR} ($res)"
      else
        echo -e "${match}: ${RED}UNALIGNED${ENDCOLOR} ($res)"
      fi
    done
    
    1. 将脚本保存到一个文件中,例如 alignment.sh

    2. 解压缩应用的 APK 文件:

      unzip APK_NAME.apk -d /tmp/my_apk_out
      
    3. /tmp/my_apk_out 中的提取文件上运行脚本 目录:

      alignment.sh /tmp/my_apk_out | grep "arm64-v8a"
      

      该脚本会针对所有参数输出 ALIGNEDUNALIGNEDarm64-v8a 个共享库。

    4. 如果任何 arm64-v8a 共享库为 UNALIGNED,您需要 更新这些库的包装,然后重新编译您的 应用,然后按照本部分中的步骤重新测试。

  5. 运行以下 zipalign 命令以验证您的应用 16 KB 对齐,其中 APK_NAME 是 您应用的 APK 文件:

    zipalign -c -P 16 -v 4 APK_NAME.apk
    
  6. 全面测试您的应用,重点关注可能会受到 更改引用特定页面大小的代码实例

使用基于 16 KB 的 Android 15 系统映像设置 Android 模拟器

如要使用 Android 模拟器设置 16 KB 的环境,请按照以下说明操作 步骤:

  1. 基于 16 KB 的 Android 15 模拟器系统映像 Android Studio Jellyfish |2023.3.1 或更高版本。不过,为了最好 使用 Android 15 Beta 版时的体验,请下载最新的 预览版

    请注意,您可以保留现有的 Android Studio 版本 因为您可以同时安装多个版本

  2. 在 Android Studio 中,依次点击 Tools > SDK Manager

  3. SDK Platforms 标签页中,选中 Show Package Details,然后展开 Android VanillaIceCream Preview 部分,然后选择 以下模拟器系统映像,具体取决于您要创建的虚拟设备 创建:

    • Google API 实验性 16k 页面大小 ARM 64 v8a 系统映像
    • Google API 实验性 16k 页面大小 Intel x86_64 Atom 系统映像

    在 Android 中使用 SDK 管理器下载 16 KB 模拟器系统映像
单间

  4. 点击应用 >确定以下载您选择的任何系统映像。

  5. 按照相关步骤针对 Android 15 设置虚拟设备,以及何时 根据提示选择系统映像,请选择 。如果系统未自动推荐该内容,您可以 Other Images 标签页中的 16 KB 系统映像。

    在“其他映像”中查找 16 KB 模拟器映像
标签页

  1. 在设备管理器中,点击 16 KB 图片旁边的 3 个点,然后点击 在磁盘上显示
  2. 在此文件夹中,找到 config.ini 文件。
  3. 将以下代码行添加到 config.ini 文件中并保存更改:

    kernel.parameters = androidboot.page_shift=14
    
  4. 如需验证您的更改,请运行以下命令,该命令应该会返回 16384:

    adb shell getconf PAGE_SIZE