Android: native libraries need 16 KB ELF page alignment before May 31, 2026 (Google Play mandate) #752
Labels
No labels
bug
documentation
duplicate
enhancement
good first issue
help wanted
invalid
question
stale
wontfix
No milestone
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
gh-streetpea/chiaki-ng#752
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Background
The Android subproject under
android/is currently on a 2023-era tech stack:namespacesupport, can't target SDK 35These issues collectively block Play Store submission and accumulate technical debt that makes future contributions harder.
Problem Statement
.sofiles not aligned to 16 KB pages will be rejected by May 31, 2026 on Android 15+ devices.namespace(required by AGP 8+), can't use KSP (kapt is deprecated), and references dead repositories (jcenter).chiaki-jni.c— avideo_sample_cbsignature mismatch (error) and asockaddr_storage**→sockaddr**implicit cast (warning).Planned Changes
I'm preparing a series of PRs to address all of the above. Each PR is independently reviewable and leaves the project in a buildable state.
PR 1 — Baseline hygiene (no SDK/AGP changes)
jcenter()→mavenCentral()lifecycle-extensions:2.2.0-Xuse-experimental→-opt-in(Kotlin 1.7+ syntax)kotlin-stdlib-jdk7→kotlin-stdlib(merged in Kotlin 1.8)Why: Dead dependencies and deprecated configs that will break on any future upgrade. Zero-risk cleanup.
PR 2 — AGP 8.7 LTS + Kotlin 1.9 + namespace migration
namespace "com.metallic.chiaki"inbuild.gradle, removepackage=fromAndroidManifest.xmlplugins {}DSL +dependencyResolutionManagementinsettings.gradleWhy: AGP 8+ is required for
namespace(which replaces the deprecated manifestpackageattribute). Kotlin 1.9 is the minimum for Moshi 1.15 codegen. JDK 17 is required by AGP 8+. These are prerequisite for targetSdk 35.PR 3 — targetSdk 35 + edge-to-edge + Predictive Back
compileSdk/targetSdk34 → 35SYSTEM_UI_FLAG_*withWindowInsetsControllerCompatinStreamActivityonBackPressed()withOnBackPressedDispatcherinMainActivityintent.getParcelableExtra<T>()withIntentCompat.getParcelableExtra()windowTranslucentStatus/windowTranslucentNavigationfromStreamTheme(ignored under targetSdk 35 edge-to-edge enforcement)Why: Play Store mandatory requirement since Aug 2025. The deprecated system UI APIs are no-ops on Android 15 and cause incorrect behavior under edge-to-edge enforcement.
PR 4 — NDK r28 + 16 KB ELF page alignment ⚠️ (this issue)
-DANDROID_SUPPORT_FLEXIBLE_PAGE_SIZES=ON-Wl,-z,max-page-size=16384 -Wl,-z,common-page-size=16384to ExternalProject builds (OpenSSL, json-c, miniupnpc)video_sample_cbsignature mismatch invideo-decoder.c/h(missingint32_t frames_lost, bool frame_recoveredparameters — error on NDK 29's Clang 18)sockaddr_storage**→sockaddr**cast inchiaki-jni.c:593Why: Google Play deadline May 31, 2026. All
.sofiles in the APK must have 16 KB aligned LOAD segments. This is the only PR that touches the parentcmake/directory and native code — see coordination question below.PR 5 — RxJava 2.x → Coroutines/Flow
Flowable→Flow,Single/Completable/Maybe→suspend funBehaviorSubject→MutableStateFlow(Preferences, DiscoveryManager, TouchControls, TouchpadView, ChiakiRxLog)CompositeDisposable→viewModelScope/lifecycleScopeObservables.combineLatest→combine()on FlowtoLiveData()→asLiveData()(fromlifecycle-livedata-ktx)RxLiveData.ktrxjava,rxkotlin,rxandroid,lifecycle-reactivestreams,room-rxjava2dependencieskotlinx-coroutines-android,lifecycle-livedata-ktxMutableStateFlow.value =is thread-safe, replacesBehaviorSubject.onNext()called from native threadsWhy: RxJava 2.x is EOL. Room, Lifecycle, and Kotlin all natively support Flow/Coroutines. This removes 3 transitive dependency trees and ~90 lines of glue code. Every ViewModel and data layer file is touched, but the changes are mechanical (type substitution, no logic changes).
PR 6 (future) — kapt → KSP + version catalog
PR 7 (future) — Minimal test scaffolding
Coordination Needed (PR 4)
The 16 KB alignment PR is the only one that touches code outside
android/. The ExternalProject builds (OpenSSL, json-c, miniupnpc) in the parentcmake/directory need linker flags propagated. Three options:Option A (recommended) — Android-guarded linker flag: pass the flags only when
CHIAKI_ENABLE_ANDROID=ON. Zero impact on iOS/Windows/Linux/Switch/SteamDeck.Option B — Unconditional linker flag: always pass 16 KB alignment. Safe on all ELF platforms, no-op on Mach-O/PE. Simpler but slight footprint change on non-Android Linux.
Option C — Static linking: link OpenSSL/json-c/miniupnpc statically into
libchiaki-jni.so. Removes per-lib alignment concern but much bigger refactor.Questions for maintainers
cmake/helper or per-ExternalProject?video_sample_cbsignature,sockaddrcast) — should these go in the 16 KB PR or a separate one?Verification
After the full series, on a release APK:
Dependency health:
What's NOT changing
Update: scope is smaller than the original issue described
After working through Phase 1b locally, I found the actual surface area is narrower than Option A suggested in the original post. Sharing the findings so the eventual PR is easier to review.
Finding: OpenSSL / json-c / miniupnpc don't ship as
.soin the APKAll three are built statically under
CHIAKI_ENABLE_ANDROID=ON:cmake/OpenSSLExternalProject.cmake— Configured withno-shared→libcrypto.a/libssl.acmake/JsoncExternalProject.cmake—BUILD_SHARED_LIBS=OFF→libjson-c.acmake/MiniupnpcExternalProject.cmake—UPNPC_BUILD_STATIC=ON, UPNPC_BUILD_SHARED=OFF→libminiupnpc.aThey get linked into
libchiaki-jni.so. Actual shared libraries in the APK (per ABI):So 16 KB alignment only needs to apply to libraries built within the Android CMake invocation (where
CMAKE_SHARED_LINKER_FLAGSnaturally propagates) plus the prefab Oboe.Minimal change that works
No parent
CMakeLists.txt/cmake/*.cmakechanges required. Onlyandroid/files:Plus bump Oboe
1.9.3 → 1.10.0(1.10.0 ships a 16 KB aligned prefab).Verification
After rebuilding with the above,
llvm-readelf -lon every 64-bit.soin the release APK reportsAlign 0x4000on all LOAD segments. Example:32-bit ABIs (
armeabi-v7a,x86) retain 4 KB pages — that's correct and not Play Store's concern.Implication for the PR
This collapses the Phase 1b PR to a 2-file, 4-line diff in
android/only. No upstream CMake surgery, no Option B/C. Will open as part of a broader Android modernization PR chain once the rest of the phases (AGP 8.7, targetSdk 35, Coroutines migration, etc.) are reviewed.This issue is stale because it has been open for 90 days with no activity.
Implemented in #791.
All seven planned PRs are in that one branch, one commit per phase.
Two findings differ from this issue:
android/are needed — OpenSSL, json-c, and miniupnpcare statically linked into
libchiaki-jni.so, so none of Option A/B/C applies.aligned — correcting my earlier comment, which said 32-bit would stay at 4 KB.
Happy to split it into separate PRs if that's easier to review.
Correcting one claim I made in my previous comment here, now that #791 has landed.
I wrote that "all four ABIs end up 16 KB aligned". That is not accurate. Alignment follows where each
.socomes from, not the ABI — measured across all 12 libraries in the release APK, every LOAD segment:libchiaki-jni.so0x40000x4000liboboe.so0x40000x4000libc++_shared.soANDROID_STL=c++_shared)0x10000x4000So the original statement in this issue — that 32-bit would stay at 4 KB — was right for the NDK's prebuilt
libc++_shared.so. My "correction" of it was an overreach; only the two libraries this project controls end up aligned on 32-bit.The conclusion is unchanged: all six 64-bit libraries are 16 KB aligned, which is what the requirement covers, since 16 KB page devices are arm64-only. The NDK follows the same policy — 64-bit prebuilts aligned, 32-bit left at 4 KB.
#791's description was corrected with the full table at the time; this comment brings the issue thread in line.