Repository: react-native
Issue: Need support for 16KB page size on Android
Labels: Platform: Android,Resolution: Fixed,Never gets stale

### Description

Android 15 offers an option for OEMs to use a 16KB page size for better performance [1]. This change is significant, as all shared objects (`.so` files in APKs) must be recompiled with the new page size. According to the Android team [2][3], 16KB page size compatibility will be required for app uploads to the Play Store next year (2025).

It seems that React-Native is not compatible with the 16KB page size. If I try to run a React-Native project on an emulator with a 16KB page size, I get the following error in the logcat:

```text
Library 'libreact_render_componentregistry.so' is not PAGE(16384)-aligned - will not be able to open it directly from apk.
```

I checked all shared objects in the APK using my script [check_elf_page_size.py](https://gist.github.com/bc-lee/a0b3e9b44d92db6f9ab6ca5d0784a836) and found that all shared objects use a 4KB page size.

```shell
$ check_elf_page_size.py android/app/build/intermediates/stripped_native_libs/debug/out/lib/arm64-v8a/*.so
Page Size of android/app/build/intermediates/stripped_native_libs/debug/out/lib/arm64-v8a/libc++_shared.so: 4096
Page Size of android/app/build/intermediates/stripped_native_libs/debug/out/lib/arm64-v8a/libexpo-modules-core.so: 4096
Page Size of android/app/build/intermediates/stripped_native_libs/debug/out/lib/arm64-v8a/libfabricjni.so: 4096
Page Size of android/app/build/intermediates/stripped_native_libs/debug/out/lib/arm64-v8a/libfbjni.so: 4096
Page Size of android/app/build/intermediates/stripped_native_libs/debug/out/lib/arm64-v8a/libfolly_runtime.so: 4096
Page Size of android/app/build/intermediates/stripped_native_libs/debug/out/lib/arm64-v8a/libgifimage.so: 4096
Page Size of android/app/build/intermediates/stripped_native_libs/debug/out/lib/arm64-v8a/libglog.so: 4096
Page Size of android/app/build/intermediates/stripped_native_libs/debug/out/lib/arm64-v8a/libhermes.so: 4096
Page Size of android/app/build/intermediates/stripped_native_libs/debug/out/lib/arm64-v8a/libhermes_executor.so: 4096
Page Size of android/app/build/intermediates/stripped_native_libs/debug/out/lib/arm64-v8a/libhermesinstancejni.so: 4096
Page Size of android/app/build/intermediates/stripped_native_libs/debug/out/lib/arm64-v8a/libimagepipeline.so: 4096
Page Size of android/app/build/intermediates/stripped_native_libs/debug/out/lib/arm64-v8a/libjscinstance.so: 4096
Page Size of android/app/build/intermediates/stripped_native_libs/debug/out/lib/arm64-v8a/libjsi.so: 4096
Page Size of android/app/build/intermediates/stripped_native_libs/debug/out/lib/arm64-v8a/libjsijniprofiler.so: 4096
Page Size of android/app/build/intermediates/stripped_native_libs/debug/out/lib/arm64-v8a/libjsinspector.so: 4096
Page Size of android/app/build/intermediates/stripped_native_libs/debug/out/lib/arm64-v8a/libmapbufferjni.so: 4096
Page Size of android/app/build/intermediates/stripped_native_libs/debug/out/lib/arm64-v8a/libnative-filters.so: 4096
Page Size of android/app/build/intermediates/stripped_native_libs/debug/out/lib/arm64-v8a/libnative-imagetranscoder.so: 4096
Page Size of android/app/build/intermediates/stripped_native_libs/debug/out/lib/arm64-v8a/libreact_codegen_rncore.so: 4096
Page Size of android/app/build/intermediates/stripped_native_libs/debug/out/lib/arm64-v8a/libreact_cxxreactpackage.so: 4096
Page Size of android/app/build/intermediates/stripped_native_libs/debug/out/lib/arm64-v8a/libreact_debug.so: 4096
Page Size of android/app/build/intermediates/stripped_native_libs/debug/out/lib/arm64-v8a/libreact_devsupportjni.so: 4096
Page Size of android/app/build/intermediates/stripped_native_libs/debug/out/lib/arm64-v8a/libreact_featureflags.so: 4096
Page Size of android/app/build/intermediates/stripped_native_libs/debug/out/lib/arm64-v8a/libreact_featureflagsjni.so: 4096
Page Size of android/app/build/intermediates/stripped_native_libs/debug/out/lib/arm64-v8a/libreact_nativemodule_core.so: 4096
Page Size of android/app/build/intermediates/stripped_native_libs/debug/out/lib/arm64-v8a/libreact_newarchdefaults.so: 4096
Page Size of android/app/build/intermediates/stripped_native_libs/debug/out/lib/arm64-v8a/libreact_render_componentregistry.so: 4096
Page Size of android/app/build/intermediates/stripped_native_libs/debug/out/lib/arm64-v8a/libreact_render_core.so: 4096
Page Size of android/app/build/intermediates/stripped_native_libs/debug/out/lib/arm64-v8a/libreact_render_debug.so: 4096
Page Size of android/app/build/intermediates/stripped_native_libs/debug/out/lib/arm64-v8a/libreact_render_element.so: 4096
Page Size of android/app/build/intermediates/stripped_native_libs/debug/out/lib/arm64-v8a/libreact_render_graphics.so: 4096
Page Size of android/app/build/intermediates/stripped_native_libs/debug/out/lib/arm64-v8a/libreact_render_imagemanager.so: 4096
Page Size of android/app/build/intermediates/stripped_native_libs/debug/out/lib/arm64-v8a/libreact_render_mapbuffer.so: 4096
Page Size of android/app/build/intermediates/stripped_native_libs/debug/out/lib/arm64-v8a/libreact_utils.so: 4096
Page Size of android/app/build/intermediates/stripped_native_libs/debug/out/lib/arm64-v8a/libreactnativeblob.so: 4096
Page Size of android/app/build/intermediates/stripped_native_libs/debug/out/lib/arm64-v8a/libreactnativejni.so: 4096
Page Size of android/app/build/intermediates/stripped_native_libs/debug/out/lib/arm64-v8a/libreactperfloggerjni.so: 4096
Page Size of android/app/build/intermediates/stripped_native_libs/debug/out/lib/arm64-v8a/libreanimated.so: 4096
Page Size of android/app/build/intermediates/stripped_native_libs/debug/out/lib/arm64-v8a/librninstance.so: 4096
Page Size of android/app/build/intermediates/stripped_native_libs/debug/out/lib/arm64-v8a/librnscreens.so: 4096
Page Size of android/app/build/intermediates/stripped_native_libs/debug/out/lib/arm64-v8a/librrc_image.so: 4096
Page Size of android/app/build/intermediates/stripped_native_libs/debug/out/lib/arm64-v8a/librrc_legacyviewmanagerinterop.so: 4096
Page Size of android/app/build/intermediates/stripped_native_libs/debug/out/lib/arm64-v8a/librrc_view.so: 4096
Page Size of android/app/build/intermediates/stripped_native_libs/debug/out/lib/arm64-v8a/libruntimeexecutor.so: 4096
Page Size of android/app/build/intermediates/stripped_native_libs/debug/out/lib/arm64-v8a/libstatic-webp.so: 4096
Page Size of android/app/build/intermediates/stripped_native_libs/debug/out/lib/arm64-v8a/libturbomodulejsijni.so: 4096
Page Size of android/app/build/intermediates/stripped_native_libs/debug/out/lib/arm64-v8a/libuimanagerjni.so: 4096
Page Size of android/app/build/intermediates/stripped_native_libs/debug/out/lib/arm64-v8a/libyoga.so: 4096
```

(Of course, one can manually check the page size of each shared object using the `readelf -Wl` command.)

I think React-Native should support the 16KB page size for the future.

[1] https://developer.android.com/guide/practices/page-sizes
[2] https://android-developers.googleblog.com/2024/05/the-second-beta-of-android-15.html
[3] https://issuetracker.google.com/issues/346830813#comment3


### Steps to reproduce

1. Create a new Android emulator with a 16KB page size using the "Google APIs Experimental 16k Page Size Intel x86_64 Atom System Image" (see [1] for more details).
2. Create a new React-Native project using `npx react-native init`.
3. Build and run the project on the emulator using `npx expo run:android`.


### React Native Version

0.74.2

### Affected Platforms

Runtime - Android

### Output of `npx react-native info`

```text
$ npx react-native info
info Fetching system and libraries information...
System:
  OS: macOS 14.5
  CPU: (10) arm64 Apple M1 Max
  Memory: 101.97 MB / 32.00 GB
  Shell:
    version: 5.2.26
    path: /opt/homebrew/bin/bash
Binaries:
  Node:
    version: 18.20.2
    path: ~/.nvm/versions/node/v18.20.2/bin/node
  Yarn:
    version: 1.22.22
    path: ~/.nvm/versions/node/v18.20.2/bin/yarn
  npm:
    version: 10.7.0
    path: ~/.nvm/versions/node/v18.20.2/bin/npm
  Watchman:
    version: 2024.06.10.00
    path: /opt/homebrew/bin/watchman
Managers:
  CocoaPods:
    version: 1.15.2
    path: /Users/redacted/.rvm/gems/ruby-3.1.4/bin/pod
SDKs:
  iOS SDK:
    Platforms:
      - DriverKit 23.2
      - iOS 17.2
      - macOS 14.2
      - tvOS 17.2
      - visionOS 1.0
      - watchOS 10.2
  Android SDK: Not Found
IDEs:
  Android Studio: EAP AI-241.17890.1.2412.11972402 AI-241.17890.1.2412.11972402
  Xcode:
    version: 15.2/15C500b
    path: /usr/bin/xcodebuild
Languages:
  Java:
    version: 17.0.10
    path: /usr/bin/javac
  Ruby:
    version: 3.1.4
    path: /Users/redacted/.rvm/rubies/ruby-3.1.4/bin/ruby
npmPackages:
  "@react-native-community/cli": Not Found
  react:
    installed: 18.2.0
    wanted: 18.2.0
  react-native:
    installed: 0.74.2
    wanted: 0.74.2
  react-native-macos: Not Found
npmGlobalPackages:
  "*react-native*": Not Found
Android:
  hermesEnabled: true
  newArchEnabled: false
iOS:
  hermesEnabled: Not found
  newArchEnabled: Not found
```


### Stacktrace or Logs

```text
Library 'libreact_render_componentregistry.so' is not PAGE(16384)-aligned - will not be able to open it directly from apk.
```


### Reproducer

npx create-expo-app@latest

### Screenshots and Videos

<img width="1701" alt="Screenshot 2024-06-19 at 09 29 03" src="https://github.com/facebook/react-native/assets/7533290/3d7b5798-4bfd-4d93-bc18-263b7d8dcc43">