feat: replace arti-mobile-ex with custom-built Arti native library

The Guardian Project's arti-mobile-ex AAR has three problems:
1. No 16KB page-aligned binaries (required for Google Play)
2. ArtiProxy's stop()+start() causes state file lock conflicts
   (lock is tied to TorClient object lifetime, released only on GC)
3. ~140MB AAR size

Replace with a custom JNI bridge built from Arti source, following
BitChat's proven approach:

Build tooling (tools/arti-build/):
- build-arti.sh: Clones official Arti, compiles with cargo-ndk
  for ARM64 + x86_64, NDK 25+ for 16KB page alignment
- Cargo.toml: Minimal deps with size-optimized release profile
- src/lib.rs: Custom SOCKS5 proxy with proper lifecycle:
  - initialize() creates TorClient once (holds state lock forever)
  - startSocksProxy() binds port and accepts connections
  - stopSocksProxy() aborts listener only (TorClient stays alive)
  This cleanly separates "stop routing traffic" from "destroy client"

Kotlin side:
- ArtiNative.kt: JNI declarations + ArtiLogCallback interface
- TorService.kt: Uses ArtiNative directly, start() initializes +
  starts proxy, stop() only stops proxy (no lock issues)
- TorManager.kt: Restored stop() calls for OFF/EXTERNAL modes
  since our native stop is now safe

Removed: arti-mobile-ex dependency from build.gradle and version catalog

Native libraries must be built separately:
  cd tools/arti-build && ./build-arti.sh

https://claude.ai/code/session_01BApgDd5udqBzMqysSRMpZu
This commit is contained in:
Claude
2026-04-01 16:36:12 +00:00
parent abe1082121
commit e50ae0fb1e
10 changed files with 827 additions and 60 deletions
+30
View File
@@ -0,0 +1,30 @@
[package]
name = "arti-android"
version = "1.2.3"
edition = "2021"
[lib]
crate-type = ["cdylib"]
[workspace]
[dependencies]
arti-client = { version = "0.25", features = [
"tokio",
"rustls",
"compression",
"bridge-client",
"onion-service-client",
"static-sqlite",
] }
tor-rtcompat = { version = "0.25", features = ["tokio", "rustls"] }
jni = "0.21"
tokio = { version = "1", features = ["full"] }
anyhow = "1"
[profile.release]
opt-level = "z"
lto = true
codegen-units = 1
strip = true
panic = "abort"