支援 16 KB 網頁大小

以往 Android 僅支援 4 KB 的記憶體頁面大小, 最佳化系統記憶體效能 通常 Android 裝置都有這樣的功能。從 Android 15 開始,Android 開放原始碼計畫會支援 已設定頁面大小為 16 KB (16 KB) 的裝置 裝置)。如果應用程式直接使用任何 NDK 程式庫 或者間接透過 SDK 來重建應用程式, 支援這些 16 KB 裝置

隨著裝置製造商持續開發數量更多 實體記憶體 (RAM),這類裝置中有許多 16 KB ( ,以便最佳化裝置效能。正在新增 網頁大小支援 16 KB 頁面大小的裝置,可讓您的應用程式在這些裝置上執行 ,有助應用程式享有相關效能 如未重新編譯,應用程式可能無法在 16 KB 裝置上運作 。

為協助您為應用程式添加支援服務,我們提供了指南說明 如果您的應用程式受到影響,您可以瞭解如何 重新建構應用程式 (如適用),以及如何在 使用模擬器的 16 KB 環境 (包括 Android 15) Android Emulator 的系統映像檔)。

優點和效能提升

設定為 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 建構選單選項

  3. 選擇要分析的 APK。

  4. 查看 lib 資料夾,查看有否代管共用物件 (.so) 檔案。如果有任何共用物件檔案,表示應用程式使用原生程式碼。如果不存在共用物件檔案,或是沒有 lib 資料夾,應用程式就不會使用原生程式碼。

    APK 分析工具檢視畫面,顯示共用物件檔案

建構支援 16 KB 裝置的應用程式

如要支援 16 KB 裝置,使用原生程式碼的應用程式應完成下列各節所述的步驟。如果您更新至 AGP 8.5.1 以上版本和 NDK r28 以上版本,並使用 16 KB 相容的預先建構依附元件,則應用程式預設為 16 KB 相容。

更新共用程式庫的封裝

建議您升級至 AGP 8.5.1 以上版本,並使用未壓縮的共用程式庫。

AGP 8.5.1 以上版本

16 KB 裝置需要含有未壓縮共用程式庫的應用程式,才能使它們與 16 KB 的 zip 對齊邊界對齊。如要這樣做,您必須升級至 Android Gradle 外掛程式 (AGP) 8.5.1 以上版本。如要進一步瞭解升級程序,請參閱「Android Gradle 外掛程式升級小幫手」一節。

AGP 8.5 以下版本

如果無法將 AGP 升級至 8.5.1 以上版本,則可改用壓縮共用程式庫。更新 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 r28 以上版本

NDK 28 以上版本預設會編譯 16 KB 對齊。

Android NDK r27

如要支援使用 Android NDK 7 以上版本編譯 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

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")

檢查參照特定網頁大小的程式碼例項

即使應用程式對齊 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. 針對所有共用程式庫,請確認共用程式庫的 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
        ```
    
    1.  Run the script on the extracted files in the `/tmp/my_apk_out`
        directory:
    
    ```none {: .devsite-terminal .devsite-click-to-copy }
        alignment.sh /tmp/my_apk_out | grep "arm64-v8a"
        ```
    
    The script outputs either `ALIGNED` or `UNALIGNED` for all the `arm64-v8a`
        shared libraries.
    
    1.  If any `arm64-v8a` shared libraries are `UNALIGNED`, you'll need to
        [update the packaging for those libraries][20], then [recompile your
        app][21] and retest by following the steps in this section.
    
  5. 執行下列 zipalign 指令,確認應用程式是否已對齊 16 KB,其中 APK_NAME 是應用程式 APK 檔案的名稱:

    zipalign -c -P 16 -v 4 APK_NAME.apk
    
  6. 請徹底測試應用程式,並著重於變更參照特定頁面大小的程式碼例項可能受到影響的任何部分。

使用基於 16 KB 的 Android 15 系統映像檔設定 Android Emulator

如要使用 Android Emulator 設定 16 KB 環境,請按照下列步驟操作:

  1. 以 16 千位元為基礎的 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 APIs 實驗性 16k 頁面大小 ARM 64 v8a 版系統映像檔
    • Google API 實驗性 16k 頁面大小 Intel x86_64 Atom 系統映像檔

    使用 Android Studio 中的 SDK Manager 下載 16 KB 模擬器系統映像檔

  4. 按一下「Apply」>「OK」,下載您選取的系統映像檔。

  5. 按照步驟設定適用於 Android 15 的虛擬裝置,然後在系統提示您選取系統映像檔時,選取您下載的 16 KB 系統映像檔。如果系統不建議自動執行這項操作,您可以在「Other Images」(其他映像檔) 分頁中找到 16 KB 的系統映像檔。

    在「其他圖片」分頁中尋找 16 KB 模擬器圖片

  1. 在裝置管理工具中,按一下 16 KB 圖片旁邊的 3 點圖示,然後按一下「Show on Disk」
  2. 在這個資料夾中,找出 config.ini 檔案。
  3. config.ini 檔案中新增下列程式碼行,然後儲存變更:

    kernel.parameters = androidboot.page_shift=14
    
  4. 如要驗證變更,請執行下列指令,此處應會傳回 16384

    adb shell getconf PAGE_SIZE
    

使用開發人員選項在裝置上啟用 16 KB 模式

切換「使用 16 KB 頁面大小啟動」開發人員選項 這個選項可讓裝置啟動 16 KB 模式。

從 Android 15 QPR1 開始,你可以: 使用開發人員選項 裝置以 16 KB 模式啟動裝置,並執行裝置端測試。

這個開發人員選項適用於下列裝置:

  • Pixel 8 和 8 Pro (搭載 Android 15 QPR1 Beta 1 以上版本)