ADFA-1167: Recompress APK deflated entries with advzip (7z deflate, optional zopfli) - #1565
Conversation
recompressApk now pipes deflatable entries through a single advzip -z -3 run (7-Zip's deflate encoder) and writes the APK with a minimal raw zip writer that injects the pre-compressed streams, since ZipOutputStream cannot emit raw deflate data. -Pzopfli switches to advzip -4 -i 5. - Applies to release APKs and CI builds (including CI debug); local dev debug builds are unaffected. Without advzip on the machine the task falls back to Deflater BEST_COMPRESSION, matching the previous output. - noCompress/STORED handling, zeroed timestamps, and re-signing are unchanged; stored payload verified byte-identical. - recompressApk can now run standalone against a built APK via -PrecompressAbi and -PrecompressBuildName. - debug.yml and release.yml install advancecomp (idempotent) so the self-hosted runners have advzip. Measured on v8 APKs (content CRCs verified, apksigner passes, app installs and launches on an arm64 emulator): - Release: 744.36 MB -> 742.21 MB (-2.14 MB, 90 s); -2.19 MB with -Pzopfli (~5 min). - CI debug: 79.68 MB -> 76.72 MB (-2.97 MB, +~2.3 min). 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.
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
📝 Walkthrough
WalkthroughThe APK recompression pipeline now supports standalone parameters, advzip-based compression with raw-deflate fallback, deterministic ZIP rewriting, and per-extension storage rules. Debug and release workflows install ChangesAPK recompression
Estimated code review effort: 4 (Complex) | ~60 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)
Warning There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure. 🔧 Checkov (3.3.8)app/build.gradle.ktsTraceback (most recent call last): 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.
Actionable comments posted: 2
🤖 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.
Inline comments:
In `@app/build.gradle.kts`:
- Around line 615-619: Update the APK replacement flow after signApk in the
surrounding build script to use a filesystem atomic move with replacement
semantics instead of unchecked apkFile.delete() and
tempZipFile.renameTo(apkFile). Propagate or fail clearly on move errors, and
ensure the original APK is not removed unless the replacement can be completed
safely.
- Around line 887-905: The RawZipWriter path in recompressApk must preserve
4-byte alignment for STORED APK entries before apksigner runs. Update
RawZipWriter.addEntry or the STORED entry handling around extensionOf and
noCompressExtensions to emit the required alignment padding, rather than using
zero extra-field length; do not rely on a later zipalign step unless that step
is explicitly restored before signing.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 8c2f400b-7f55-416e-8b0f-0ffd3f3f72a1
📒 Files selected for processing (3)
.github/workflows/debug.yml.github/workflows/release.ymlapp/build.gradle.kts
- Replace unchecked delete()/renameTo() with Files.move(REPLACE_EXISTING) so a failed replace throws instead of silently leaving no .apk. - RawZipWriter now 4-byte aligns STORED entry data via zero-padded extra fields (zipalign parity), so the runtime can mmap uncompressed assets. Verified: all 198 stored entries aligned, content CRCs unchanged, apksigner passes, APK installs and launches on an arm64 emulator. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Jira: ADFA-1167 (Epic ADFA-561, APK diet)
What
recompressApknow compresses the APK's deflatable entries with advzip (AdvanceCOMP) instead of Java's Deflater:advzip -z -3— 7-Zip's deflate encoder. Output is still standard deflate; only the encoder searches harder.-Pzopfli: switches toadvzip -4 -i 5(zopfli) for an extra ~50 KB at ~4x the CPU time.ZipOutputStreamcannot emit raw deflate data). Zeroed timestamps and deterministic output are preserved; re-signing is unchanged.Scope / gating
recompressApk, and even a manual run skips advzip for debug off-CI).BEST_COMPRESSIONfallback, byte-equivalent to the previous behavior. The build never breaks over the missing tool.noCompress/STORED handling is untouched: stored entries (.br,.zip,.ttf, ...) are never handed to advzip and were verified byte-identical.recompressApkcan now run standalone against an already-built APK:./gradlew :app:recompressApk -PrecompressAbi=v8 -PrecompressBuildName=release.debug.ymlandrelease.ymlgain an idempotentapt-get install advancecompstep (persistent self-hosted runners keep it after the first run). Follow-up: move advancecomp into the flox/base manifest once the ADFA-1938 asset work lands (its manifest.lock is currently in flight).Measurements (v8 APKs)
-3, default)-Pzopfli)-3)Zopfli iteration count is near-irrelevant (i=1 vs i=15: 0.05% on classes.dex), hence the fixed
-i 5. Repeat runs are byte-identical (deterministic).Verification
apksigner verifypasses with the same scheme profile as before (v3).GITHUB_ACTIONS=true; Deflater fallback path exercised with advzip absent semantics (debug off-CI).spotlessCheckgreen.🤖 Generated with Claude Code