Support 16 KB page sizes

Historically, Android has only supported 4 KB memory page sizes, which has optimized system memory performance for the average amount of total memory that Android devices have typically had. Beginning with Android 15, Android supports devices that are configured to use a page size of 16 KB (16 KB devices). If your app uses any NDK libraries, either directly or indirectly through an SDK, then you will need to rebuild your app for it to work on these 16 KB devices.

Devices with larger page sizes can have improved performance for memory-intensive workloads. As device manufacturers continue to build devices with larger amounts of physical memory (RAM), many of these devices will adopt 16 KB (and eventually greater) page sizes to optimize the device's performance. Adding support for 16 KB page size devices enables your app to run on these devices and helps your app benefit from the associated performance improvements. We plan to make 16 KB page compatibility required for app uploads to the Google Play store next year.

As device manufacturers continue to build devices with larger amounts of physical memory (RAM), many of these devices will likely be configured with 16 KB (and eventually greater) page sizes to optimize the device's performance. Adding support for 16 KB devices enables your app to run on these devices and helps your app benefit from the associated performance improvements.

To help you add support for your app, we've provided guidance on how to check if your app is impacted, how to rebuild your app (if applicable), and how to test your app in a 16 KB environment using emulators (including Android 15 system images for the Android Emulator).

Benefits and performance gains

Devices configured with 16 KB page sizes use slightly more memory on average, but also gain various performance improvements for both the system and apps:

  • Lower app launch times while the system is under memory pressure: 3.16% lower on average, with more significant improvements (up to 30%) for some apps that we tested
  • Reduced power draw during app launch: 4.56% reduction on average
  • Faster camera launch: 4.48% faster hot starts on average, and 6.60% faster cold starts on average
  • Improved system boot time: improved by 1.5% (approximately 0.8 seconds) on average

These improvements are based on our initial testing, and results on actual devices will likely differ. We'll provide additional analysis of potential gains for apps as we continue our testing.

Check if your app is impacted

If your app uses any native code, then you should rebuild your app with support for 16 KB devices. If you are unsure if your app uses native code, you can use the APK Analyzer to identify whether any native code is present.

If your app only uses code written in the Java programming language or in Kotlin, including all libraries or SDKs, then your app already supports 16 KB devices. Nevertheless, we recommend that you test your app in a 16 KB environment to verify that there are no unexpected regressions in app behavior.

Does your app use native code?

Your app makes use of native code if any of the following apply:

  • Your app uses any C/C++ (native) code. If your app uses the Android NDK, then your app uses native code.
  • Your app links with any third-party native libraries or dependencies that use them.
  • Your app is built by a third-party app builder that uses native libraries on device.

Identify native libraries using APK Analyzer

APK Analyzer is a tool that lets you evaluate various aspects of a built APK. To identify whether your app uses native code or libraries, follow these steps:

  1. Open Android Studio, then click File > Open and choose any project.
  2. From the menu bar, click Build > Analyze APK...

    Studio Build menu option to launch APK
Analyzer

  3. Choose the APK you want to analyze.

  4. Look within the lib folder, which hosts shared object (.so) files if any are present. If any shared object files are present, your app uses native code. If no shared object files are present or there is no lib folder, then your app doesn't use native code.

    APK Analyzer view showing that shared object files are
present

Build your app with support for 16 KB devices

To support 16 KB devices, apps that use native code should complete the steps that are outlined in the following sections.

Update the packaging of your shared libraries

We recommend that you upgrade to AGP version 8.3 or higher and use uncompressed shared libraries.

AGP version 8.3 or higher

16 KB devices require apps that ship with uncompressed shared libraries to align them on a 16 KB zip-aligned boundary. To do this, you need to upgrade to Android Gradle Plugin (AGP) version 8.3 or higher. Refer to the Android Gradle plugin Upgrade Assistant section for details on the upgrade process.

AGP version 8.2 or lower

If you can't upgrade AGP to version 8.3 or higher, then the alternative is to switch to use compressed shared libraries. Update your Gradle configuration to have Gradle compress your shared libraries when packaging your app to avoid app installation issues with unaligned shared libraries.

Groovy

In your build.gradle file, add the following option:

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

Kotlin

In your build.gradle.kts file, add the following option:

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

Compile your app using 16 KB ELF alignment

16 KB devices require the shared libraries' ELF segments to be aligned properly using 16 KB ELF alignment in order for your app to run.

To compile your app using 16 KB ELF alignment, complete the steps in one of the following sections depending on the version of the Android NDK that you're using.

Android NDK r26 and lower

To support compiling 16 KB-aligned shared libraries with Android NDK version r26 or lower, you need to update your ndk-build or cmake configuration as follows:

ndk-build

Update your Android.mk to enable 16 KB ELF alignment:

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

CMake

Update your CMakeLists.txt to enable 16 KB ELF alignment:

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

Android NDK r27 and higher

To support compiling 16 KB-aligned shared libraries with Android NDK version r27 and higher, you need to update your ndk-build, build.gradle, build.gradle.kts, or linker flags as follows:

ndk-build

In your Application.mk:

APP_SUPPORT_FLEXIBLE_PAGE_SIZES := true

Groovy

In your build.gradle file, set the argument -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

In your build.gradle.kts file, set the argument -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")
      }
    }
  }
}

Other build systems

Specify the following linker flags:

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

Check for code instances that reference specific page sizes

Even if your app is 16 KB-aligned, your app can encounter errors if places in your code assume that a device is using a specific page size. To avoid this, complete the following steps:

  1. Remove any hard-coded dependencies that reference the PAGE_SIZE constant or instances in your code logic that assume that a device's page size is 4 KB (4096).

    Use getpagesize() or sysconf(_SC_PAGESIZE) instead.

  2. Look for usages of mmap() and other APIs that require page-aligned arguments and replace with alternatives where necessary.

In some cases, if your app uses PAGE_SIZE as a convenient value that isn't tied to the underlying page size, then this won't cause your app to break when used in 16 KB mode. However, if this value is passed to the kernel with mmap without MAP_FIXED, the kernel still uses an entire page, which wastes some memory. For these reasons, PAGE_SIZE is undefined when 16 KB mode is enabled on NDK r27 and higher.

If your app uses PAGE_SIZE in this way and never directly passes this value to the kernel, then instead of using PAGE_SIZE, create a new variable with a new name to reflect that it is used for other purposes and does not reflect a real memory page.

Test your app in a 16 KB environment

After you build your app with support for 16 KB devices, you'll want to test your app in a 16 KB environment to see whether your app experiences any regressions. To do this, follow these steps:

  1. Set up the Android 15 SDK.

  2. Set up one of the following testing environments:

  3. Start up your test device, then run the following command to verify that it's using a 16 KB environment:

    adb shell getconf PAGE_SIZE
    

    The command should return a value of 16384.

  4. For any shared libraries, verify that the shared libraries' ELF segments are aligned properly using 16 KB ELF alignment. You can use this script to help with this process:

    #!/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. Save the script to a file, such as alignment.sh.

    2. Extract your app's APK file:

      unzip APK_NAME.apk -d /tmp/my_apk_out
      
    3. Run the script on the extracted files in the /tmp/my_apk_out directory:

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

      The script outputs either ALIGNED or UNALIGNED for all the arm64-v8a shared libraries.

    4. If any arm64-v8a shared libraries are UNALIGNED, you'll need to update the packaging for those libraries, then recompile your app and retest by following the steps in this section.

  5. Run the following zipalign command to verify that your app is 16 KB-aligned, where APK_NAME is the name of your app's APK file:

    zipalign -c -P 16 -v 35 APK_NAME.apk
    
  6. Thoroughly test your app, focusing on any areas that might be affected by changing code instances that reference specific page sizes.

Set up the Android Emulator with a 16-KB-based, Android 15 system image

To set up a 16 KB environment using the Android Emulator, follow these steps:

  1. 16-KB-based, Android 15 emulator system images are compatible with Android Studio Jellyfish | 2023.3.1 or higher. However, for the best experience when working with the Android 15 Beta, download the latest preview version of Android Studio.

    Remember that you can keep your existing version of Android Studio installed, as you can install multiple versions side-by-side.

  2. In Android Studio, click Tools > SDK Manager.

  3. In the SDK Platforms tab, check Show Package Details, then expand the Android VanillaIceCream Preview section and select one or both of the following emulator system images, depending on the virtual devices you want to create:

    • Google APIs Experimental 16k Page Size ARM 64 v8a System Image
    • Google APIs Experimental 16k Page Size Intel x86_64 Atom System Image

    Download 16 KB emulator system images using the SDK Manager in Android
Studio

  4. Click Apply > OK to download whichever system images you selected.

  5. Follow the steps to set up a virtual device for Android 15, and when prompted to select a system image, select the 16 KB system image that you downloaded. If it's not recommended automatically, you can find the 16 KB system image in the Other Images tab.

    Find the 16 KB emulator image in the Other Images
tab