支持 16 KB 的页面大小

一直以来,Android 仅支持 4 KB 的内存页面大小,针对 Android 设备通常拥有的平均总内存量,系统内存性能进行了优化。从 Android 15 开始,Android 支持配置为使用 16 KB 页面大小的设备(即 16 KB 设备)。

随着设备制造商不断打造具有更大物理内存 (RAM) 的设备,这些设备中的许多可能会配置 16 KB(最终更大)的页面大小,以优化设备的性能。添加对 16 KB 设备的支持可让您的应用在这些设备上运行,并帮助您的应用从相关性能改进中受益。为了帮助您解决此问题,我们提供了一些指南,帮助您了解如何检查您的应用是否受到影响、如何重新构建应用(如果适用),以及如何同时使用模拟器和实体设备在 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 分析器是一种工具,可让您评估所构建的 APK 的各个方面。如需确定您的应用使用的是原生代码还是库,请按以下步骤操作:

  1. 打开 Android Studio,然后依次点击 File > Open,然后选择任意项目。
  2. 在菜单栏中,依次点击 Build > Analyze 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 设备要求使用 16 KB ELF 对齐来正确对齐共享库的 ELF 段,以便您的应用运行。

如需使用 16 KB ELF 对齐编译您的应用,请根据您所使用的 Android NDK 版本完成以下某一部分中的步骤。

Android NDK r26 及更低版本

如需支持使用 Android NDK 版本 r26 或更低版本编译 16 KB 对齐的共享库,您需要按如下方式更新 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 版本 r27 及更高版本编译 16 KB 对齐的共享库,您需要按如下方式更新 ndk-buildbuild.gradlebuild.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 模式下使用时,不会导致应用崩溃。不过,如果将此值传递给包含 mmap 但不带 MAP_FIXED 的内核,内核仍会使用整个页面,而这会浪费一些内存。因此,在 NDK r27 及更高版本上启用 16 KB 模式时,PAGE_SIZE 未定义。

如果您的应用以这种方式使用 PAGE_SIZE 且从未将此值直接传递给内核,请不要使用 PAGE_SIZE,而是创建一个具有新名称的新变量,以反映它用于其他用途,而不是反映实际内存页面。

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

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

  1. 设置 Android 15 SDK

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

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

    adb shell getconf PAGE_SIZE
    

    该命令应返回值 16384

  4. 对于任何共享库,请使用 16 KB ELF 对齐方式验证共享库的 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"
      

      该脚本会为所有 arm64-v8a 共享库输出 ALIGNEDUNALIGNED

    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。

    请注意,您可以保留已安装的现有 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 Studio 中的 SDK 管理器下载 16 KB 模拟器系统映像

  4. 点击 Apply > OK 以下载您选择的任何系统映像。

  5. 按照针对 Android 15 设置虚拟设备的步骤进行操作,在系统提示您选择系统映像时,选择您下载的 16 KB 系统映像。如果系统未自动推荐该映像,您可以在 Other Images 标签页中找到 16 KB 系统映像。

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