Skip to content

ADR-0011: 16 KB page-size support

  • Status: Accepted (revised — supersedes this ADR's 2026-08-11 revision)
  • Date: 2026-08-13
  • Deciders: maintainers
  • Related: tooling.md

Supersedes the earlier Accepted revision (2026-08-11), which realigned the 4 KB-linked libsqlcipher.so at build time. That approach turned out not to satisfy the runtime 16 KB check on Android 17 devices.

Context

Google Play requires apps targeting Android 15+ to support 16 KB page sizes. The original revision of this ADR patched the 4 KB-aligned android-database-sqlcipher AAR at build time (PatchSqlcipherTask + scripts/patch_elf_16k.py), rewriting LOAD segment p_offset/p_align so p_offset ≡ p_vaddr (mod 16384) and p_align = 16384.

That patch passes zipalign -P 16 but does not survive Android 17's strict loader. ElfReader::FixMinAlignFor16KiB (added in Android 17) lowers min_align_ to 4096 when LOAD segments overlap after 16 KB page-rounding:

if (prev_load_end > page_start(phdr->p_vaddr)) { min_align_ = 4 * 1024; }

The patched libsqlcipher.so still has non-16 KB-aligned p_vaddr (0x3abc80, 0x3d3a10), so it fails this check and the device rejects it with program alignment (4096) cannot be smaller than system page size (16384). A file-offset patch cannot fix this — it would require relocating every vaddr-based structure (relinking).

Zetetic confirmed android-database-sqlcipher is end-of-life and will never ship a 16 KB build. The official replacement sqlcipher-android has been 16 KB-aligned since 4.6.1.

Decision

Migrate to net.zetetic:sqlcipher-android (4.17.0) and delete the build-time patch machinery:

  • Replace the dependency (android-database-sqlciphersqlcipher-android).
  • Replace net.sqlcipher.database.SupportFactory with net.zetetic.database.sqlcipher.SupportOpenHelperFactory, and call System.loadLibrary("sqlcipher") before opening (the new library no longer auto-loads its native code).
  • Drop PatchSqlcipherTask, scripts/patch_elf_16k.py, and scripts/patch_sqlcipher_aar.py.

The on-disk SQLCipher format is unchanged across 4.x, so existing encrypted databases open without a data migration.

Consequences

  • The shipped libsqlcipher.so is genuinely 16 KB-aligned and loads on 16 KB devices without any compat property.
  • No custom build step for native libraries; the patch scripts and Gradle task are gone.
  • Verified end-to-end: fresh install on a 16 KB emulator (no alignment crash) and in-place upgrade of an existing encrypted DB on a 4 KB emulator (data preserved, same DB file).
  • Encryption behavior is guarded by SqlcipherEncryptionTest (round-trip, wrong-passphrase rejection, not-plaintext).

Alternatives considered

  • Rebuilding android-database-sqlcipher from source with -Wl,-z,max-page-size=16384 — rejected: heavy native toolchain and upkeep, and the library is EOL.
  • Keeping the build-time ELF patch — rejected: fails Android 17's strict 16 KB loader (see Context).
  • Licensing the Commercial Edition — rejected: migration to the open-source replacement is sufficient.