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, AOSP 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.
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. Without recompiling, apps won't work on 16 KB devices in future Android releases.
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).
Google Play compatibility requirement
To ensure your app works correctly on the latest versions of Android, all apps targeting Android 15 (API level 35) and higher must support 16 KB memory page sizes on 64-bit devices on Google Play. Starting February 1, 2027, if your app updates don't support 16 KB memory page sizes, you won't be able to release these updates.
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 8% (approximately 950 milliseconds) 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 and then check the alignment of ELF segments for any shared libraries that you find. Android Studio also provides features that help you to automatically detect alignment issues.
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 (such as SDKs) 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 check whether your app uses native code (regardless of whether it is 16 KB compatible):
- Open Android Studio, then click File > Open and choose any project.
From the menu bar, click Build > Analyze APK...
Choose the APK you want to analyze.
Look within the
libfolder, which hosts shared object (.so) files if any are present. If any shared object files are present, your app uses native code. The Alignment column displays warning messages for any files that have alignment issues. If no shared object files are present or there is nolibfolder, then your app doesn't use native code.
Detect alignment issues with automated checks
Android Studio warns you proactively if your prebuilt libraries or APKs aren't 16 KB compliant. Use the APK Analyzer tool to review which libraries need to be updated or if any code changes are required.
Lint in Android Studio also highlights native libraries that aren't 16 KB aligned.
Check the alignment of ELF segments for shared libraries
For any shared libraries, verify that the shared libraries' ELF segments are aligned properly using 16 KB ELF alignment.
Use APK Analyzer (Recommended)
The easiest way to verify the alignment of your shared libraries is to use the APK Analyzer in Android Studio. If a shared object file is not 16 KB aligned, the Alignment column will display a warning message.
Use the check_elf_alignment.sh script (Linux or macOS)
If you are developing on either Linux or macOS and prefer to use a script, you
can use the check_elf_alignment.sh script:
Save the
check_elf_alignment.shscript to a file.Run the script on your app's APK file:
check_elf_alignment.sh APK_NAME.apkThe script outputs either
ALIGNEDorUNALIGNEDfor all thearm64-v8ashared libraries.If any
arm64-v8aorx86_64shared libraries areUNALIGNED, you'll need to update the packaging for those libraries, then recompile your app and retest by following the steps in this section.
Use command-line tools directly
Follow these steps to check the alignment of ELF segments using command-line tools directly:
- Make sure both Android SDK Build-Tools version 35.0.0 or higher and the
Android NDK are installed using the SDK Manager in Android Studio or
sdkmanagercommand-line tool. Extract your app's APK file:
Linux or macOS
unzip APK_NAME.apk -d /tmp/my_apk_outWindows (PowerShell)
Expand-Archive -Path .\APK_NAME.apk -DestinationPath ~\tmp\my_apk_outIn the temporary directory that you extracted your APK file to, check the contents of the
libdirectory for shared object (.so) files. These are the same shared object files that you would've seen while identifying native libraries using APK Analyzer. Run the following command on each shared object file:Linux or macOS
SDK_ROOT_LOCATION/Android/sdk/ndk/NDK_VERSION/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-objdump -p SHARED_OBJECT_FILE.so | grep LOADWindows (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"Where
SDK_ROOT_LOCATIONis the path to the directory where you've installed the Android SDK,SHARED_OBJECT_FILEis the name of the shared object file that you're checking, andNDK_VERSIONis the version of the Android NDK that you have installed (for example,28.0.12433566). The output will look something like the following for each file you check: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**14Check the output lines to ensure that the load segments don't have values less than
2**14. If any load segments are2**13,2**12, or lower values, you'll need to update the packaging for those libraries, then recompile your app and retest by following the steps in this section.Next, run the
zipaligncommand-line tool on your app's APK file:Linux or macOS
SDK_ROOT_LOCATION/Android/sdk/build-tools/35.0.0/zipalign -v -c -P 16 4 APK_NAME.apkWindows (PowerShell)
SDK_ROOT_LOCATION\Android\sdk\build-tools\35.0.0\zipalign.exe -v -c -P 16 4 APK_NAME.apkWhere
SDK_ROOT_LOCATIONis the path to the directory where you've installed the Android SDK, andAPK_NAMEis the name of your app's APK file. The last line of the output will say "Verification successful" if all of the shared libraries are aligned correctly.If the verification failed, some shared libraries need to be realigned, so you'll need to update the packaging for those libraries, then recompile your app and retest by following the steps in this section.
Check the RELRO security flag
To mitigate security exploits, modern linkers use the
Relocation Read-Only (RELRO) flag to make relocation target
sections (such as .got and .data.rel.ro) of the shared object file
read-only after dynamic relocations are complete.
Enable the RELRO flag in your build.
When GNU_RELRO shares a writable LOAD segment with subsequent writable data
(such as .data or .bss), the end address of the GNU_RELRO segment
(VirtAddr + MemSiz) must be 16 KB aligned (0x4000). Otherwise, when
the Android Linker marks the 16 KB page containing the end of
GNU_RELRO as read-only, any adjacent writable data residing in the remainder
of that same 16 KB page also becomes read-only, crashing the app at
runtime with a segmentation fault (SIGSEGV) when that data is written to.
This typically happens if the .so file was built with NDK toolchain r27 and
lower without enabling the relevant flags.
Use APK Analyzer (Recommended)
You can use the APK Analyzer in Android Studio to check the
RELRO alignment status of your shared object files directly.
Use command-line tools
If you prefer to check the alignment manually or need to automate the process, follow these steps:
Step 1: Inspect the program headers
Run the following command on each shared object file (on Linux, replace
darwin-x86_64 with linux-x86_64):
Linux or macOS
SDK_ROOT_LOCATION/Android/sdk/ndk/NDK_VERSION/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-readelf -Wl SHARED_OBJECT_FILE.so | grep 'LOAD\|RELRO\|Type'
Windows (PowerShell)
SDK_ROOT_LOCATION\Android\sdk\ndk\NDK_VERSION\toolchains\llvm\prebuilt\windows-x86_64\bin\llvm-readelf.exe -Wl SHARED_OBJECT_FILE.so | Select-String -Pattern 'LOAD|RELRO|Type'
The GNU_RELRO string is printed if there's a RELRO segment.
Step 2: Verify 16 KB compliance for RELRO
A shared object file is 16 KB compliant with respect to RELRO if any of the following conditions is met:
- No
GNU_RELROsegment exists in the program headers. - The
GNU_RELROend address is 16 KB aligned: The sum of its virtual address (VirtAddr) and memory size (MemSiz) divided by 16 KB (0x4000) leaves a remainder (modulo) of zero:(VirtAddr + MemSiz) % 0x4000 == 0. - No writable data follows
GNU_RELROin the sameLOADsegment:GNU_RELROoccupies the entire remainder of its containingLOADsegment (meaningLOAD.VirtAddr + LOAD.MemSiz == RELRO.VirtAddr + RELRO.MemSiz), so no writable.dataor.bsssections share the trailing page.
Examples
The following examples show how to evaluate llvm-readelf output for different
GNU_RELRO configurations.
Example 1: Non-aligned .so file (Non-compliant)
In this example, GNU_RELRO shares a RW LOAD segment with subsequent
writable data, and its end address isn't a multiple of 0x4000:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
LOAD 0x000000 0x0000000000000000 0x0000000000000000 0x0cfaf0 0x0cfaf0 R E 0x4000
LOAD 0x0cfaf0 0x00000000000dfaf0 0x00000000000dfaf0 0x02510 0x04510 RW 0x4000
GNU_RELRO 0x0cfaf0 0x00000000000dfaf0 0x00000000000dfaf0 0x01510 0x01510 R 0x1
- Formula:
(VirtAddr + MemSiz) % 0x4000 == 0 - Result:
(0xdfaf0 + 0x01510) % 0x4000 = 0xE1000 % 0x4000 == 0x1000
Since 0x1000 isn't zero, and the containing LOAD segment continues past
0xE1000 (ending at 0xdfaf0 + 0x04510 = 0xE4000), this .so file isn't
16 KB compliant. On a 16 KB device, the linker rounds the RELRO
protection range to 16 KB page boundaries, marking 0xDC000 (the previous
page break) through 0xE4000 as read-only. However, the .so file's writable
.data and .bss sections reside in the sub-range from 0xE1000 to 0xE4000,
resulting in a segmentation fault when modified at runtime. Rebuild this .so
file as described in the
Compile your app using 16 KB ELF alignment section.
Example 2: Aligned .so file with a RELRO segment (Compliant)
In this example, the end of the GNU_RELRO segment falls on a 16 KB page
boundary:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
LOAD 0x000000 0x0000000000000000 0x0000000000000000 0x0cfaf0 0x0cfaf0 R E 0x4000
LOAD 0x0cfaf0 0x00000000000dfaf0 0x00000000000dfaf0 0x01510 0x03510 RW 0x4000
GNU_RELRO 0x0cfaf0 0x00000000000dfaf0 0x00000000000dfaf0 0x00510 0x00510 R 0x1
- Formula:
(VirtAddr + MemSiz) % 0x4000 == 0 - Result:
(0xdfaf0 + 0x00510) % 0x4000 = 0xE0000 % 0x4000 == 0
Because the remainder is 0, the RELRO protection ends cleanly at the 0xE0000
page boundary, leaving any writable data starting at 0xE0000 unaffected.
Example 3: .so file without a RELRO segment (Compliant)
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
LOAD 0x000000 0x0000000000000000 0x0000000000000000 0x000680 0x000680 R E 0x4000
LOAD 0x000680 0x0000000000004680 0x0000000000004680 0x0001d8 0x0001d8 RW 0x4000
This .so file has no GNU_RELRO segment, so RELRO page-boundary issues don't
apply (though enabling RELRO is still recommended for security).
Example 4: GNU_RELRO in its own LOAD segment (Compliant)
In this example, GNU_RELRO does not end on a 16 KB boundary, but it is
still compliant because no writable data follows it in the same LOAD segment:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
LOAD 0x000000 0x0000000000000000 0x0000000000000000 0x000680 0x000680 R E 0x4000
LOAD 0x000680 0x0000000000004680 0x0000000000004680 0x0001d8 0x000980 RW 0x4000
GNU_RELRO 0x000680 0x0000000000004680 0x0000000000004680 0x0001d8 0x000980 R 0x1
- Formula:
(VirtAddr + MemSiz) % 0x4000 == 0 - Result:
(0x4680 + 0x0980) % 0x4000 = 0x5000 % 0x4000 == 0x1000
Although 0x1000 isn't zero, this .so file is still 16 KB compliant.
Comparing GNU_RELRO against its containing LOAD segment (the second LOAD
entry) shows that both start at VirtAddr 0x4680 and end at the exact same
address (0x4680 + 0x0980 = 0x5000).
Because the entire LOAD segment contains only RELRO data, there is no
writable .data or .bss data in the sub-range from 0x5000 to 0x8000
(either the library has no non-RELRO writable data, or any subsequent writable
LOAD segment begins on a separate 16 KB page boundary at 0x8000 or
beyond). The linker's read-only protection won't overlap with any writable data,
so no segmentation fault occurs.
Build your app with support for 16 KB devices
If your app uses native code, then complete the steps that are outlined in the following sections to make sure that your app supports 16 KB devices:
- Update the packaging of your shared libraries
- Compile your app using 16 KB ELF alignment
- Fix code and resolve runtime issues
- Optimize custom memory allocators (if applicable)
- Check SDKs for 16 KB support
Update the packaging of your shared libraries
Upgrade to AGP version 8.5.1 or higher and use uncompressed shared libraries.
Use bundletool to verify zip alignment
To see the alignment of your bundle, use:
bundletool dump config --bundle=<my .aab> | grep alignment
If you see PAGE_ALIGNMENT_16K then you know your bundle requests 16 KB
zip alignment. If you see PAGE_ALIGNMENT_4K, this instructs the APK built from
this AAB to have 4 KB aligned .so files in the zip file.
AGP version 8.5.1 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.5.1 or higher. Refer to the Android Gradle plugin Upgrade Assistant section for details on the upgrade process.
AGP version 8.5 or lower
If you can't upgrade AGP to version 8.5.1 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
}
}
}
AGP version 8.0 or lower
If you are using an AGP version same or lower than 8.0, you also need to disable
the uncompressed native library option for App Bundles in your
gradle.properties file:
android.bundle.enableUncompressedNativeLibs=false
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.
For game developers, if your game runs on top of Unity game engine, refer to the Unity guide. If your game runs on top of Unreal game engine, refer to the Unreal guide.For native game engines, continue with this guide.
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 r28 and higher
NDK version r28 and higher compile 16 KB-aligned by default.
Android NDK r27 and lower
To support compiling 16 KB-aligned shared libraries with Android NDK version r27 or lower, use the following linker flags:
-Wl,-z,max-page-size=16384
-Wl,-z,common-page-size=16384
Here's how to update your build system configuration files:
ndk-build
If you're using ndk-build, update your Android.mk to enable 16 KB ELF
alignment:
LOCAL_LDFLAGS += -Wl,-z,max-page-size=16384 -Wl,-z,common-page-size=16384
CMake
If you're using CMake, update your CMakeLists.txt to enable 16 KB ELF
alignment:
target_link_options(${CMAKE_PROJECT_NAME} PRIVATE
"-Wl,-z,max-page-size=16384"
"-Wl,-z,common-page-size=16384"
)
Fix code and resolve runtime issues
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:
Remove any hard-coded dependencies that reference the
PAGE_SIZEconstant or instances in your code logic that assume that a device's page size is 4 KB (4096).Use
getpagesize()orsysconf(_SC_PAGESIZE)instead.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.
Optimize custom memory allocators
On 16 KB systems, the smallest unit of physical memory the operating system allocates is four times larger than on 4 KB systems. If a custom allocator was designed around 4 KB assumptions, it can scatter small objects across multiple 16 KB pages and retain empty memory unnecessarily. This can substantially increase physical memory usage (RSS) and degrade compressed swap (ZRAM) efficiency.
If your code manages its own memory pools, follow these recommendations:
1. Avoid hard-coded byte thresholds for freeing memory
Many allocators use fixed byte limits to decide when to release memory back to
the OS using madvise(MADV_DONTNEED) (for example, only release memory if
active objects take up less than 8 KB).
On a 16 KB system, even a single 16-byte live object pins an entire 16 KB page (which is greater than 8 KB). As a result, the release threshold is never met, and the allocator never returns the surrounding unused memory to the kernel.
What to do: Never use hard-coded byte constants for page-release heuristics.
Scale release thresholds dynamically at runtime based on the actual page size
using sysconf(_SC_PAGESIZE).
2. Fill up already-used pages first (dense-first allocation)
If an allocator hands out memory in first-in-first-out (FIFO) or round-robin order, new allocations get scattered across many partially filled 16 KB pages. A single object on a page keeps all 16 KB resident in physical RAM.
What to do: Always allocate new objects from the most full (densest) page or slab before touching empty or lightly used pages. Concentrating new allocations on already-dirty pages allows lightly used pages to naturally drain to zero active objects, so the entire 16 KB page can be released to the OS.
3. Align memory pools to 16 KB and keep pool sizes moderate
Multi-page spans designed for 4 KB systems can hold excessive unreleased memory slack on 16 KB kernels. In addition, size classes that don't divide evenly into 16 KB cause fragmentation at the end of each page.
What to do:
- Ensure all memory pools, slab boundaries, and buffer alignments are exact multiples of the runtime page size.
- Re-evaluate multi-page span sizes for small-object classes to avoid allocating overly large slabs that trap idle memory.
4. Release physical memory for cached large buffers immediately
Custom allocators often cache large buffers (> 64 KB) in an in-memory pool
so they can be reused without paying the overhead of mmap or munmap system
calls. However, holding onto these dirty buffers in memory wastes megabytes of
physical RAM while waiting for an eviction timer.
What to do: Keep the virtual memory address range reserved for fast reuse,
but call madvise(..., MADV_DONTNEED) or madvise(..., MADV_FREE) immediately
when returning a buffer to the cache. The operating system reclaims the physical
RAM right away, while your app can still reuse the virtual address instantly
without re-allocating.
5. Zero out memory on free instead of on allocation for ZRAM compression
Android uses compressed swap (ZRAM) to keep background apps in memory. On 16 KB devices, if a page holds even one live object, the entire 16 KB page stays resident or gets swapped to ZRAM. Leftover garbage data (such as stale pointers and strings) on previously freed parts of that page compresses poorly.
If your allocator zeroes memory (such as for security or zero-initialized
allocations), consider zeroing upon deallocation (free()) rather than on
allocation:
- Pinned pages cost less: Idle memory on partially filled 16 KB pages compresses down to almost nothing in ZRAM, so pinned pages don't waste physical swap space.
- Minimal cache overhead: At the time
free()is called, the memory is already hot in the CPU cache, avoiding additional cache misses later.
Summary of recommendations
| Area | Recommendation | Expected impact |
|---|---|---|
| Purge thresholds | Scale release thresholds dynamically using sysconf(_SC_PAGESIZE). |
Prevents release logic from permanently deadlocking. |
| Allocation order | Allocate from the densest (almost full) page or slab first. | Reduces resident memory (RSS) by packing active objects together. |
| Span sizing | Align size classes to 16 KB multiples and avoid oversized slabs. | Eliminates tail-page fragmentation and reduces memory slack. |
| Buffer caches | Call madvise(MADV_DONTNEED) immediately when caching large buffers. |
Eliminates idle RAM bloat while keeping fast virtual reuse. |
| Swap / ZRAM | Zero out memory on free() instead of on allocation. |
Improves ZRAM compression ratios so pinned pages cost less. |
Check SDKs for 16 KB support
Many SDKs are compatible with 16 KB page sizes, especially if you build them yourself or get recent prebuilts. However, because some SDK prebuilts or SDK versions aren't 16 KB compatible, you should check the website for each SDK provider to determine which version to use with 16 KB.
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:
Set up the Android 15 SDK or higher.
Set up one of the following testing environments:
Start up your test device, then run the following command to verify that it's using a 16 KB environment:
adb shell getconf PAGE_SIZEThe command should return a value of
16384.Run the following
zipaligncommand 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 4 APK_NAME.apkThoroughly 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 system image
To set up a 16 KB environment using the Android Emulator, follow these steps:
- In Android Studio, click Tools > SDK Manager.
In the SDK Platforms tab, select Show Package Details, then expand the Android VanillaIceCream or higher section and select one or both of the following emulator system images, depending on the virtual devices you want to create:
- Google APIs Experimental 16 KB Page Size ARM 64 v8a System Image
- Google APIs Experimental 16 KB Page Size Intel x86_64 Atom System Image
Click Apply > OK to download whichever system images you selected.
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.
Launch the emulator
After you finish setting up the Android Emulator and virtual devices, launch the emulator from the target device menu, or from the command line.
Enable 16 KB mode on a device using developer options
Toggle the Boot with 16KB page size developer option to boot a device in 16 KB mode.
In QPR versions of Android 15, you can use the developer option that's available on certain devices to boot the device in 16 KB mode and perform on-device testing. Before using the developer option, go to Settings > System > Software updates and apply any updates that are available.
This developer option is available on the following devices:
Pixel 8 and 8 Pro (with Android 15 QPR1 or higher)
Pixel 8a (with Android 15 QPR1 or higher)
Pixel 9, 9 Pro, and 9 Pro XL (with Android 15 QPR2 or higher)
Pixel 9a (with Android 16 or higher)
16 KB backcompat mode
Warning in page size compat mode
The 16 KB backcompat option is available when a device is running with a 16 KB kernel. The package manager runs an app in 16 KB backcompat mode when the following conditions are met:
- If the app has ELF files (with an
.soextension) with a LOAD segment alignment of 4 KB. - If the zipped APK has uncompressed ELF files that are 4 KB ZIP aligned.
If the package manager has enabled 16 KB backcompat mode for an app, the app displays a warning when it's first launched saying that it's running in 16 KB backcompat mode.
16 KB backcompat mode allows some apps to work, but for best reliability and stability, apps should still be 16 KB aligned.
On the app info page, under Advanced, toggle the setting Run app with page size compat mode to enable or disable the 16 KB backcompat mode for specific app. This setting is visible only when the device is running with 16 KB page size.
Page size compat mode setting
To force 16 KB backcompat on for every app on the device:
adb shell setprop bionic.linker.16kb.app_compat.enabled true
adb shell setprop pm.16kb.app_compat.disabled false
To force 16 KB backcompat off for every app on the device:
adb shell setprop bionic.linker.16kb.app_compat.enabled false
adb shell setprop pm.16kb.app_compat.disabled true
In Android 17, you can also force 16 KB backcompat off for every app and cause any incompatible binary to immediately abort:
adb shell setprop bionic.linker.16kb.app_compat.enabled fatal
adb shell setprop pm.16kb.app_compat.disabled true
Set the android:pageSizeCompat property to enabled or disabled to turn on or
off backcompat mode for a specific app in its AndroidManifest.xml. When this
property is set, the app won't display backcompat mode warnings when it
launches.