androidfluttermemory-managementandroid-ndk

16KB memory page size for Flutter Android and ndkVersion requirement?


I've checked the migration guide, and already ensured my Android Gradle Plugin (AGP) version is 8.5.1 or higher; mine is at 8.7.3.

The second thing I've ensured is that the alignment of ELF segments support 16KB memory page size. I used the llvm-objdump-18 command in my Ubuntu linux machine and ran the following command from the project root (when the project was compiled for debugging and app was running in debug mode):

find | grep '\.so$' | xargs -I{} -exec llvm-objdump-18 -p "{}" | grep 'LOAD'

The output of the above command is:

LOAD off    0x0000000000000000 vaddr 0x0000000000000000 paddr 0x0000000000000000 align 2**16
LOAD off    0x0000000001dd0240 vaddr 0x0000000001de0240 paddr 0x0000000001de0240 align 2**16
LOAD off    0x00000000026f2370 vaddr 0x0000000002712370 paddr 0x0000000002712370 align 2**16
LOAD off    0x0000000002784490 vaddr 0x00000000027b4490 paddr 0x00000000027b4490 align 2**16
LOAD off    0x0000000000000000 vaddr 0x0000000000000000 paddr 0x0000000000000000 align 2**16
LOAD off    0x0000000001dd0240 vaddr 0x0000000001de0240 paddr 0x0000000001de0240 align 2**16
LOAD off    0x00000000026f2370 vaddr 0x0000000002712370 paddr 0x0000000002712370 align 2**16
LOAD off    0x0000000002784490 vaddr 0x00000000027b4490 paddr 0x00000000027b4490 align 2**16

Here, in the output, clearly, the load segments don't have values less than 2**14 == 16KiB.

The third thing I made sure was that my app ran perfectly well in Android Virtual Device (AVD) supporting 16KiB memory page size, by configuring a new API 36 AVD. My app seems to run well without resulting in any kind of errors.

I've read suggestions that I also need ndkVersion to be at least r28 or higher so that my app fully supports 16KiB memory page size. Or since, my current ndkVersion "27.0.12077973" also correctly compiled the .so libraries supporting 16KiB pages, can I be assured my app will run without related errors in 16KiB devices? Since, compiling to 16KiB-alignment is not default for ndkVersions lower than r28 how did my used version compile correctly?

References:


Solution

  • In this official Android video documentation it is stated that:

    Applications without native code are likely to work as is. Build with the latest tools to build for 16 KB automatically.

    It also suggests using Gradle 8.5.1 or higher and NDK r28+ to ensure 16KB page size support. (Among which the Gradle is mandatory while we have fixes for lower NDK versions.)

    It also suggests that if our tooling is not the latest yet, then we can compile with the option max-page-size of 16KB to tell the linker to align our executables. These options for configurations are also given as below:

    NDK Version 27:

    ANDROID_SUPPORT_FLEXIBLE_PAGE_SIZES=ON
    

    NDK Version 26 and lower:

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

    (my default tooling configuration in file <flutter_install_dir>/engine/src/build/config/compiler/BUILD.gn has defined the following option for the NDK version 26):

    # Currently defaults to 4k, but Android will be moving to 16k page size,
    # and for future-proofing, 64k boundaries will be required.
    "-Wl,-z,max-page-size=65536",
    

    which despite the comment, is aligned to 2^16==64KiB page size.

    NDK Version 22 and lower:

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

    These configuration for versions lower than r28 (in file BUILD.gn) will ensure that the Flutter engine (libFlutter.so) will be generated which is 16KB compatible.

    About Flutter engine (libflutter.so):

    libFlutter.so: This file serves as a shared library containing the Flutter engine, responsible for rendering the UI, handling input events, and managing the application lifecycle.

    Source