7cc53aedc78d1f005e7ab4b045b98779a47b2a3e
6 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
7cc53aedc7 |
refactor(android): split C++ into wzp-native cdylib, loaded at runtime
Phase 1 of the big refactor. Escape the Tauri Android __init_tcb+4 symbol leak (rust-lang/rust#104707) by making wzp-desktop's Android .so pure Rust — ZERO cc::Build, no cpp/ files, no C++ in the rustc link step. All future C++ (Oboe audio bridge) lives in a new standalone cdylib crate `wzp-native` which is built with cargo-ndk (the same path the legacy wzp-android crate uses successfully on the same phone + same NDK), copied into Tauri's gen/android/app/src/main/jniLibs at build time, and dlopened by wzp-desktop at runtime via libloading. Changes in this commit: - NEW crate crates/wzp-native/ with crate-type = ["cdylib"] only (no staticlib, no rlib — rust#104707 shows mixing staticlib with cdylib leaks non-exported symbols, which is the original bug source). Phase 1 scaffold has TWO extern "C" functions: wzp_native_version() -> i32 (returns 42) wzp_native_hello(buf, cap) -> usize (writes a string) So we can verify dlopen + dlsym + cross-.so FFI end-to-end before adding any real C++. - desktop/src-tauri/cpp/ directory DELETED (7 files gone). - desktop/src-tauri/build.rs reduced to just the git hash capture + tauri_build::build(). No more cc::Build of any kind. - desktop/src-tauri/Cargo.toml: drop cc from build-dependencies, add libloading = "0.8" as an Android-only runtime dep. - desktop/src-tauri/src/lib.rs Builder::setup() now (on Android only) dlopens libwzp_native.so, calls wzp_native_version() and wzp_native_hello(), and logs the result: "wzp-native dlopen OK: version=42 msg=\"hello from wzp-native\"" If this log appears in logcat when the app launches and the home screen still renders, the split-cdylib pipeline is validated and Phase 2 (port the Oboe bridge into wzp-native) can proceed. - scripts/build-tauri-android.sh: insert a `cargo ndk -t arm64-v8a build --release -p wzp-native` step before `cargo tauri android build`, with `-o desktop/src-tauri/gen/android/app/src/main/jniLibs` so the resulting libwzp_native.so lands in the place gradle will package into the final APK. - Workspace Cargo.toml: add crates/wzp-native to [workspace] members. Phase 2 (separate commit, only if Phase 1 works): - Copy cpp/oboe_bridge.{h,cpp} + getauxval_fix.c from the legacy wzp-android crate into crates/wzp-native/cpp/. - Add cc = "1" as a build-dependency on wzp-native (safe: it's a single-cdylib crate with no staticlib, so no symbol leak). - Add build.rs that compiles the Oboe C++ and the wzp-native Rust FFI exposes the audio start/stop/read/write functions. - wzp-desktop::engine.rs dlopens wzp-native at CallEngine::start, uses its audio functions instead of CPAL on Android. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> |
||
|
|
c69195fe06 |
step C(android): compile engine.rs on Android with a stub CallEngine::start
Third incremental variable. Previously the engine module was cfg-gated out of the Android build entirely (`#[cfg(not(target_os = "android"))] mod engine;` in lib.rs). Now it's always compiled, so any link-time effect of having engine.rs in the compilation unit can be measured against the working baseline from build #19. Changes kept deliberately small: - lib.rs: drop the cfg gate on `mod engine;`. `use engine::CallEngine` stays gated because the Android-specific connect/disconnect/... stubs in lib.rs don't reference the type. - engine.rs: the `wzp_client::{audio_io, call}` imports + CodecId + QualityProfile are gated to non-Android (they require the `audio` feature on wzp-client which Android doesn't pull in). On Android we keep only the MediaTransport import for transport.close(). The impl block now has two `start()` methods: the full CPAL-backed one for desktop, and a 6-line Android stub that returns `Err("audio engine not yet wired on Android")` so attempts to `connect` from the UI fail cleanly. Goal: verify that linking in the compiled engine module (plus the types it references) on Android doesn't regress the working baseline. Home screen should still render and register_signal should still work. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> |
||
|
|
530993854f |
revert(android): roll back to build #6 (35642d1) — pre-oboe known-good state
Spent 10+ builds chasing a __init_tcb+4 / pthread_create SIGSEGV after adding the oboe audio backend. Every "fix" made things worse. Reverting all Android-specific files to the state at |
||
|
|
b314138caf |
feat(android): oboe/AAudio audio backend + runtime mic permission (step 3)
This is the big one — the Tauri Android app now has a real audio stack
capable of full-duplex VoIP, reusing the proven C++ Oboe bridge from the
legacy wzp-android crate.
Architecture:
- desktop/src-tauri/cpp/ — copies of oboe_bridge.{h,cpp}, oboe_stub.cpp,
and getauxval_fix.c from crates/wzp-android/cpp/. build.rs clones
google/oboe@1.8.1 into OUT_DIR and compiles the bridge + all Oboe
sources as "oboe_bridge" static lib, linking against shared libc++
(static would pull broken libc stubs that SIGSEGV in .so libraries).
- src/oboe_audio.rs — Rust side: an SPSC ring buffer matching the C++
bridge's AtomicI32 layout, plus OboeHandle::start() which returns
(capture_ring, playout_ring, owning_handle). The ring exposes the same
(available / read / write) methods as wzp_client::audio_ring::AudioRing
so CallEngine treats both backends interchangeably.
- src/engine.rs — compiled on every platform now. A cfg-switched type
alias picks wzp_client::audio_ring::AudioRing on desktop and
crate::oboe_audio::AudioRing on Android. The audio setup block has
three branches: VPIO/CPAL on macOS, CPAL on Linux/Windows, Oboe on
Android. Send/recv tasks are identical across platforms.
- src/lib.rs — removes all the "step 3 not done" Android stubs. The
engine module is no longer cfg-gated; connect / disconnect / toggle_mic
/ toggle_speaker / get_status are single implementations used by both
desktop and Android. Identity path resolves via app.path().app_data_dir()
from the Tauri setup() callback (already wired in step 1).
Runtime mic permission:
- scripts/build-tauri-android.sh now injects RECORD_AUDIO + MODIFY_AUDIO_
SETTINGS into gen/android/app/src/main/AndroidManifest.xml after init,
and overwrites MainActivity.kt with a version that calls
ActivityCompat.requestPermissions in onCreate. This is idempotent:
every build re-applies the patches so tauri re-init can't regress them.
Cargo.toml:
- cc is now an unconditional build-dep (build.rs runs on the host, so
target-gating build-deps doesn't work).
- wzp-client is now a dep on every platform. On Android it gets default
features only (no "audio"/"vpio") so CPAL isn't dragged in — oboe_audio
provides the capture/playout rings instead.
- tracing-android is added on Android so tracing events flow into logcat.
build.rs also gained embedded git hash (WZP_GIT_HASH) capture, which is
shown under the fingerprint on the home screen — already committed in
|
||
|
|
7639aaf08d |
feat(desktop): deterministic alias from seed + git hash on home screen + fix EACCES on Android
Three home-screen issues from the first Tauri Android APK: 1. Alias was empty (no seed-derived name). Port the adjective+noun word lists from the old Kotlin SettingsRepository into a `derive_alias()` helper that maps the first 4 bytes of the seed to indices in those lists. Same seed → same alias forever, different seeds → effectively random aliases — so reinstalls keep the user's identity AND the friendly name they're used to. 2. Build identity was invisible — couldn't tell which APK was actually installed (this caused us a lot of grief on the Kotlin app). build.rs now captures `git rev-parse --short HEAD` and emits it as `WZP_GIT_HASH`, exposed via a new `get_app_info` command. The frontend stamps `build <hash> • <alias>` under the fingerprint on the home screen. 3. Register on relay failed with `Permission denied (os error 13)`. Root cause: I hardcoded `/data/data/com.wzp.phone/files/.wzp` as the identity dir, but the Tauri Android package id is `com.wzp.desktop` — so the app was trying to write into another app's data directory and getting EACCES at the filesystem layer. Fix: resolve the data dir from Tauri's `path().app_data_dir()` API in the `setup()` callback and stash it in a `OnceLock<PathBuf>`. Works on Android, macOS, Linux, Windows without any cfg gymnastics. Also: `get_app_info` returns the resolved `data_dir` so we can debug storage issues from the UI (it's set as the build-hash element's title). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> |
||
|
|
e6f77a78a7 |
feat(desktop): split main.rs into lib.rs for Tauri Mobile (Android/iOS)
Tauri 2.x Mobile links the app as a cdylib loaded from a Java Activity, so all of the Builder/command code has to live in a library crate. Move the existing logic verbatim into src/lib.rs::run() and reduce src/main.rs to a two-line desktop entry point that calls into it. Cargo.toml gets a [lib] section (crate-types: staticlib + cdylib + rlib, named wzp_desktop_lib) and the wzp-client dependency — which pulls CPAL + VoiceProcessingIO — is moved behind cfg(not(target_os = "android")) so the Android cdylib doesn't need an audio backend yet. Engine-backed Tauri commands (connect/disconnect/toggle_mic/toggle_speaker/get_status) get Android stubs that return clear "not yet wired" errors. The signaling commands (register_signal/place_call/answer_call/get_signal_status/ ping_relay/get_identity) are platform-independent and unchanged. Also: get_identity / register_signal now auto-create the seed if missing instead of erroring with "connect to a room first", and the identity dir resolves to /data/data/com.wzp.phone/files/.wzp on Android (proper app-internal storage) vs \$HOME/.wzp on desktop. Side note: src/main.rs was previously untracked — desktop builds were working only because it existed in the local worktree. This commit fixes that too. Step 1 of the Android rewrite plan (tauri-mobile scaffold). No audio yet. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> |