ADFA-2306: Compress native libs in release APKs via legacy jniLibs packaging - #1527
Conversation
…ckaging Release and instrumentation APKs now set jniLibs.useLegacyPackaging = true per-variant (behind the existing hasBundledAssets gate), so lib/<abi>/*.so ship deflate-compressed and the installer extracts them at install time. Measured on v8 release: libs shrink 7.37 MB -> 1.44 MB, APK is 5.99 MB smaller. Debug builds keep modern packaging (uncompressed, loaded straight from the APK) via the false default in app/build.gradle.kts. The release recompressApk post-step now uses a no-compress list without "so" (noCompressRelease); it previously forced .so entries back to STORED, which would silently undo the saving. Debug keeps "so" stored, as loading libs directly from the APK requires it. Also removed the dead module-level useLegacyPackaging = true in AndroidModuleConf.kt that app/build.gradle.kts always overrode. libshizuku.so still works: it is an executable the adb shell runs from nativeLibraryDir, which install-time extraction continues to provide. Verified on an arm64 emulator: installer-extracted libs in nativeLibraryDir, clean launch, Kotlin tree-sitter highlighting, terminal, no link errors. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
There was a problem hiding this comment.
Claude Code Review
This repository is configured for manual code reviews. Comment @claude review for a one-time review, or @claude review always to subscribe this PR to a review on every future push.
Tip: disable this comment in your organization's Code Review settings.
📝 Walkthrough
WalkthroughThe build logic adds explicit v7/v8 ABI flavors, applies legacy JNI packaging to bundled-assets variants, and derives ABI version increments from variant names. Release APK recompression now excludes ChangesNative library packaging
Estimated code review effort: 3 (Moderate) | ~20 minutes Possibly related PRs
Suggested reviewers: Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
🧹 Nitpick comments (2)
composite-builds/build-logic/plugins/src/main/java/com/itsaky/androidide/plugins/conf/AndroidModuleConf.kt (1)
174-179: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick winPrefer matching on
variant.flavorNameinstead of a substring search onvariant.name.Using
variant.name.containscan lead to false positives if other build types or future flavor dimensions accidentally contain "v7" or "v8" (e.g., a custom build type namedv7Release). Since this logic determines the ABI version code increment, matching directly against theflavorNameproperty is safer and more explicit.♻️ Proposed refactor
- val verCodeIncrement = - when { - variant.name.contains("v8", ignoreCase = true) -> flavorsAbis["arm64-v8a"] - variant.name.contains("v7", ignoreCase = true) -> flavorsAbis["armeabi-v7a"] - else -> 1 - } ?: 1 + val verCodeIncrement = + when (variant.flavorName) { + "v8" -> flavorsAbis["arm64-v8a"] + "v7" -> flavorsAbis["armeabi-v7a"] + else -> 1 + } ?: 1🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@composite-builds/build-logic/plugins/src/main/java/com/itsaky/androidide/plugins/conf/AndroidModuleConf.kt` around lines 174 - 179, Update the ABI version-code selection in the verCodeIncrement when expression to match against variant.flavorName rather than substring-searching variant.name. Preserve the existing arm64-v8a, armeabi-v7a, and fallback increment mappings while preventing build-type names from affecting the result.app/build.gradle.kts (1)
485-485: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick winEnsure the resulting collection is explicitly a
Setto prevent a silent cast failure.The
recompressApktask casts the passed property to aSet<String>usingas? Set<String>(around line 440). If the originalnoCompresscollection is not aSet, the Kotlinminusoperator (noCompress - "so") will yield aList. This would cause theas? Set<String>runtime cast to fail, silently falling back to anemptySet(), and unintentionally compressing files that must remain uncompressed (like.tflite).Append
.toSet()to guarantee compatibility with the expected type downstream.🛡️ Proposed refactor
-val noCompressRelease = noCompress - "so" +val noCompressRelease = (noCompress - "so").toSet()🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@app/build.gradle.kts` at line 485, Update the noCompressRelease assignment to convert the result of removing "so" from noCompress into a Set using toSet(), ensuring compatibility with recompressApk’s Set<String> cast and preserving the intended uncompressed entries.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@app/build.gradle.kts`:
- Line 485: Update the noCompressRelease assignment to convert the result of
removing "so" from noCompress into a Set using toSet(), ensuring compatibility
with recompressApk’s Set<String> cast and preserving the intended uncompressed
entries.
In
`@composite-builds/build-logic/plugins/src/main/java/com/itsaky/androidide/plugins/conf/AndroidModuleConf.kt`:
- Around line 174-179: Update the ABI version-code selection in the
verCodeIncrement when expression to match against variant.flavorName rather than
substring-searching variant.name. Preserve the existing arm64-v8a, armeabi-v7a,
and fallback increment mappings while preventing build-type names from affecting
the result.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 3c60f1ab-4035-405d-93b3-60d199ec3aad
📒 Files selected for processing (3)
ARCHITECTURE.mdapp/build.gradle.ktscomposite-builds/build-logic/plugins/src/main/java/com/itsaky/androidide/plugins/conf/AndroidModuleConf.kt
Fixes ADFA-2306.
What
Release and instrumentation APKs now ship their native libs deflate-compressed:
jniLibs.useLegacyPackaging = trueis set per-variant behind the existinghasBundledAssetsgate, so the installer extractslib/<abi>/*.sotonativeLibraryDirat install time. Measured on v8 release: libs shrink 7.37 MB -> 1.44 MB (libtree-sitter-kotlin.soalone 4.18 MB -> 339 kB), final APK is 5.99 MB smaller. Debug APKs are byte-for-byte unaffected.Why this approach
The ticket proposed brotli-compressing the libs into assets with app-side extraction. That was fully implemented and device-verified first, but measurement showed plain legacy packaging saves slightly more in aggregate (5.99 vs 5.60 MB) because deflate also covers
libbrotli.so(1.08 MB -> 474 kB), which a brotli scheme must keep uncompressed as its own decompressor — with zero runtime code changes instead of ~17 modified files. The brotli implementation is preserved (patch + files) inlmr-automate/tmp/ADFA-2306-brotli-so-backup/; layering it on top later would net a further ~290 kB.Details
recompressApk's release no-compress list now excludes"so"(noCompressRelease): the post-step previously forced.soentries back to STORED, silently undoing AGP's compression. Debug keeps"so"stored — debug loads libs directly from the APK, which requires stored entries.useLegacyPackaging = trueinAndroidModuleConf.ktthatapp/build.gradle.ktsalways overrode.libshizuku.so(an executable the adb shell runs fromnativeLibraryDir) keeps working: install-time extraction still provides it there.recompressApkcoupling.Verification
On an arm64 emulator with the v8 release APK:
extractNativeLibs=truein the merged manifest; installer extracted them tonativeLibraryDir/arm64/at install.UnsatisfiedLinkError/ crashes in logcat.:testing:unit:testgreen; Spotless applied.🤖 Generated with Claude Code