Files
bitchat-android/tools/arti-build/README.md
T
b2febcee88 feat: add product flavors and TorProvider abstraction (#508)
* feat: add product flavors and TorProvider abstraction

Introduces build flavors to separate Tor functionality from the standard build, reducing APK size for users who don't need Tor.

- Creates `standard` and `tor` product flavors.
- The `standard` flavor is the default, lightweight build.
- The `tor` flavor includes the Arti (Tor) dependency and is identified by the `.tor` application ID suffix.
- Adds a `TorProvider` interface and a `TorProviderFactory` to abstract Tor implementation details between flavors.

Prepares architecture for optional Tor support to reduce APK size
from 142MB to ~4-5MB for standard builds

Related to #454

* Refactor: implement StandardTorProvider and RealTorProvider

This commit refactors the Tor integration by introducing a `TorProvider` interface and creating separate implementations for 'tor' and 'standard' product flavors.

- The original `TorManager` singleton has been moved into `RealTorProvider` for the 'tor' flavor.
- A no-op `StandardTorProvider` is introduced for the 'standard' flavor, which reports Tor as unavailable.
- A `TorProviderFactory` is used to create the appropriate provider at runtime based on the build variant.

* refactor: migrate to TorProvider abstraction

Replaced direct calls to the static `TorManager` with an instance obtained from `TorProviderFactory`.

This change allows for different Tor implementations based on build flavors, improving modularity and abstracting the Tor provider logic.

Updated `BitchatApplication`, `ChatHeader`, `OkHttpProvider`, and `AboutSheet` to use the new factory pattern for accessing Tor functionalities.

* build: add flavor-specific ProGuard rules and CI/CD

 - Split ProGuard rules: base, standard-specific, tor-specific
  - Move Arti/Guardian Project rules to proguard-tor.pro
  - Update CI/CD workflow to build both flavors
  - Add separate artifact uploads for each flavor
  - Add descriptive release notes template

  CI now builds both standard (~4-5MB) and tor (~140MB) APKs."

  resolves #454

* refactor: centralize network reset logic

Extracts the repeated network connection reset logic into a new private function `resetNetworkConnections()`.

This change also replaces direct `_statusFlow.value = ...` assignments with the safer `_statusFlow.update { ... }` function to prevent race conditions.

* ci: run separate build steps for flavors

* feat: disable Tor toggle if not available in build

* ci: parallelize builds and add conditional tor lint

Optimizes CI workflow:
- Parallel matrix builds (4 runners instead of sequential)
- Conditional tor lint only when app/src/tor/ changes in PRs
- Merged test+lint jobs to reduce setup overhead

Reduces CI time by ~50% (8-11 min vs 18-26 min)

* refactor: Unify Tor implementation and remove build flavors

This commit refactors the Tor integration by removing the `standard` and `tor` product flavors in favor of a single, unified build that always includes a custom-built Arti (Tor) library.

Key changes include:
*   **Removed Build Flavors:** Deleted the `standard` and `tor` product flavors from `build.gradle.kts`, simplifying the build process and CI configuration.
*   **Unified Tor Manager:** Replaced the `TorProvider` interface and flavor-specific implementations (`StandardTorProvider`, `RealTorProvider`) with a new singleton, `ArtiTorManager`. This class now manages the Arti lifecycle for all builds.
*   **Custom Arti Wrapper:** Introduced a new `ArtiProxy` class to provide a compatible API wrapper around the custom-built native Arti library (`libarti_android.so`). This replaces the dependency on the external `arti-mobile-ex` library.
*   **Updated Proguard:** Consolidated and updated Proguard rules into the main `proguard-rules.pro` file to keep the necessary `ArtiTorManager` and native library classes.
*   **CI/CD Simplification:** Updated GitHub Actions workflows (`release.yml`, `android-build.yml`) to build and release a single APK instead of separate ones for each flavor.

* build: Configure ABI filters for debug and release builds

For debug builds, include `x86_64` to support emulators.

For release builds, only include `arm64-v8a` to minimize the final APK size.

* feat: Ignore jniLibs directory

This change adds the `app/src/main/jniLibs/` directory to the `.gitignore` file to prevent native libraries from being committed to the repository.

* feat: Refine .gitignore for Arti build artifacts

Improves the `.gitignore` file by:
- Ignoring all `build/` directories except for `tools/arti-build/`.
- Adding specific ignores for Arti build artifacts, including the cloned source repository and the Rust build cache directory.

* feat: Update arti android native library

* feat: add build script and JNI wrapper for Arti

Adds a comprehensive build system for creating custom Arti (Tor in Rust) shared libraries for Android. This replaces the dependency on external, outdated AARs with a fully transparent and reproducible build process.

Key changes:
- Introduces `build-arti.sh`, a script to clone the official Arti repository, apply a JNI wrapper, and build `.so` files for Android.
- Adds `ARTI_VERSION` to pin the build to a specific Arti release (v1.7.0).
- Implements a new Rust JNI wrapper (`src/lib.rs`) that exposes core functions like `initialize`, `startSocksProxy`, and `stop` to the Android app.
- Includes a `Cargo.toml` with release profile optimizations for size (`lto`, `strip`, `opt-level = "z"`).
- Provides detailed documentation in `README.md` explaining the build process, prerequisites, and architecture.

* build script for mac

* consolidate both scripts

* improve script

---------

Co-authored-by: callebtc <93376500+callebtc@users.noreply.github.com>
2025-12-12 23:27:52 +07:00

224 lines
6.2 KiB
Markdown

# Arti Android Build Tools
This directory contains the build scripts and source files for compiling the custom Arti (Tor in Rust) library for Android.
## Overview
bitchat-android uses a custom-built Arti library instead of Guardian Project's outdated `arti-mobile-ex` AAR. This provides:
- **Smaller APK size**: ~11MB total vs ~140MB with Guardian Project AAR (28x reduction)
- **Latest Arti version**: Currently v1.7.0 with pure Rust TLS (rustls)
- **16KB page size support**: Required for Google Play (Nov 2025)
- **Full transparency**: Build from official Arti source + our JNI wrapper
## Quick Start
The pre-built `.so` files are committed to the repo, so you don't need to build unless you want to:
1. **Verify the binaries** match the source
2. **Update to a new Arti version**
3. **Modify the JNI wrapper**
## Directory Structure
```
tools/arti-build/
├── README.md # This file
├── build-arti.sh # Main build script (clones Arti, builds .so files)
├── ARTI_VERSION # Pinned Arti version tag (e.g., arti-v1.7.0)
├── Cargo.toml # Rust package configuration
├── src/
│ └── lib.rs # JNI wrapper (Rust -> Kotlin/Java bridge)
└── .arti-source/ # [GITIGNORED] Cloned official Arti repo
app/src/main/jniLibs/ # [COMMITTED] Pre-built native libraries
├── arm64-v8a/
│ └── libarti_android.so (~5.3MB)
└── x86_64/
└── libarti_android.so (~6.2MB)
```
## Rebuilding from Source
### Prerequisites
1. **Rust toolchain** with Android targets:
```bash
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
rustup target add aarch64-linux-android x86_64-linux-android
```
2. **cargo-ndk** for Android cross-compilation:
```bash
cargo install cargo-ndk
```
3. **Android NDK 25+** (for 16KB page size support):
```bash
# Via Android Studio SDK Manager, or:
$ANDROID_SDK_ROOT/cmdline-tools/latest/bin/sdkmanager "ndk;27.0.12077973"
# Set environment variable
export ANDROID_NDK_HOME="$HOME/Library/Android/sdk/ndk/27.0.12077973"
```
### Build Commands
```bash
cd tools/arti-build
# Build both architectures (arm64 + x86_64 for emulator)
./build-arti.sh
# Build ARM64 only (smaller, for production releases)
./build-arti.sh --release
# Clean rebuild (re-clone Arti source)
./build-arti.sh --clean
```
The script will:
1. Clone official Arti from https://gitlab.torproject.org/tpo/core/arti
2. Checkout the version specified in `ARTI_VERSION`
3. Copy our JNI wrapper into the cloned repo
4. Build with `cargo ndk`
5. Copy `.so` files to `app/src/main/jniLibs/`
### Verification
After building, verify the libraries:
```bash
# Check file sizes
ls -lh ../../app/src/main/jniLibs/*/libarti_android.so
# Verify JNI symbols are exported
nm -gU ../../app/src/main/jniLibs/arm64-v8a/libarti_android.so | grep Java_org_torproject
# Verify 16KB page alignment
readelf -l ../../app/src/main/jniLibs/arm64-v8a/libarti_android.so | grep LOAD
# Look for: Align 0x4000 (16KB)
```
## Updating Arti Version
1. **Check available versions**:
```bash
git ls-remote --tags https://gitlab.torproject.org/tpo/core/arti.git | grep arti-v
```
2. **Update the version file**:
```bash
echo "arti-v1.8.0" > ARTI_VERSION
```
3. **Rebuild from scratch**:
```bash
./build-arti.sh --clean
```
4. **Test the build**:
```bash
cd ../..
./gradlew clean assembleDebug
./gradlew installDebug
# Enable Tor in app and verify it works
```
5. **Commit the new libraries**:
```bash
git add app/src/main/jniLibs/ tools/arti-build/ARTI_VERSION
git commit -m "chore: update Arti to v1.8.0"
```
## JNI Wrapper Architecture
The `src/lib.rs` file implements a JNI bridge between Kotlin and Rust:
```
Kotlin (ArtiNative.kt)
↓ JNI
Rust (lib.rs)
Arti Client (TorClient)
SOCKS5 Proxy (localhost:9060)
```
**Exported JNI Functions**:
- `getVersion()` - Returns Arti version string
- `setLogCallback(callback)` - Registers log listener for bootstrap progress
- `initialize(dataDir)` - Creates Tokio runtime and TorClient
- `startSocksProxy(port)` - Starts SOCKS5 proxy on specified port
- `stop()` - Stops SOCKS proxy (TorClient is reused)
**Key Design Decisions**:
- Global `TorClient` persists across stop/start cycles (fixes Nov 2024 toggle bug)
- Tokio runtime created once and never destroyed
- Log messages bridged to Java via `GlobalRef` callback
## Feature Configuration
Edit `Cargo.toml` to customize Arti features:
```toml
[dependencies]
arti-client = {
path = "../crates/arti-client",
default-features = false,
features = [
"tokio", # Required: async runtime
"rustls", # Required: pure Rust TLS (no OpenSSL)
"compression", # Optional: directory compression
"bridge-client", # Optional: Tor bridge support
"onion-service-client", # Optional: .onion site support
"static-sqlite" # Required: bundled SQLite
]
}
```
## Size Comparison
| Configuration | arm64-v8a | x86_64 | Total | APK Size |
|---------------|-----------|--------|-------|----------|
| Guardian Project AAR | - | - | ~140 MB | ~150 MB |
| Custom (both arch) | 5.3 MB | 6.2 MB | 11.5 MB | ~15 MB |
| Custom (ARM-only) | 5.3 MB | - | 5.3 MB | ~10 MB |
**28x size reduction** vs Guardian Project implementation.
## Troubleshooting
### "cargo-ndk not found"
```bash
cargo install cargo-ndk
```
### "Android NDK not found"
```bash
export ANDROID_NDK_HOME="$HOME/Library/Android/sdk/ndk/27.0.12077973"
```
### "Rust target not installed"
```bash
rustup target add aarch64-linux-android x86_64-linux-android
```
### "Version not found"
Check available versions:
```bash
git ls-remote --tags https://gitlab.torproject.org/tpo/core/arti.git | grep arti-v | tail -10
```
### Library too large
1. Ensure building with `--release` flag
2. Verify `strip = true` in `Cargo.toml` `[profile.release]`
3. Consider removing optional features
## References
- [Arti Documentation](https://gitlab.torproject.org/tpo/core/arti/-/blob/main/doc/README.md)
- [cargo-ndk](https://github.com/bbqsrc/cargo-ndk)
- [Android NDK Guide](https://developer.android.com/ndk/guides)
- [Google Play 16KB Page Size](https://developer.android.com/guide/practices/page-sizes)