diff --git a/crates/wzp-android/src/audio_ring.rs b/crates/wzp-android/src/audio_ring.rs index 897fe8f..7d8490a 100644 --- a/crates/wzp-android/src/audio_ring.rs +++ b/crates/wzp-android/src/audio_ring.rs @@ -19,7 +19,7 @@ const RING_MASK: usize = RING_CAPACITY - 1; /// Lock-free single-producer single-consumer ring buffer for i16 PCM samples. pub struct AudioRing { - buf: Box<[i16; RING_CAPACITY]>, + buf: Box<[i16]>, /// Monotonically increasing write cursor. ONLY written by producer. write_pos: AtomicUsize, /// Monotonically increasing read cursor. ONLY written by consumer. @@ -41,7 +41,7 @@ impl AudioRing { pub fn new() -> Self { debug_assert!(RING_CAPACITY.is_power_of_two()); Self { - buf: Box::new([0i16; RING_CAPACITY]), + buf: vec![0i16; RING_CAPACITY].into_boxed_slice(), write_pos: AtomicUsize::new(0), read_pos: AtomicUsize::new(0), overflow_count: AtomicU64::new(0), diff --git a/crates/wzp-android/src/jni_bridge.rs b/crates/wzp-android/src/jni_bridge.rs index 54e8614..0dff475 100644 --- a/crates/wzp-android/src/jni_bridge.rs +++ b/crates/wzp-android/src/jni_bridge.rs @@ -35,11 +35,16 @@ static INIT_LOGGING: Once = Once::new(); /// Safe to call multiple times — only the first call takes effect. fn init_logging() { INIT_LOGGING.call_once(|| { - use tracing_subscriber::layer::SubscriberExt; - use tracing_subscriber::util::SubscriberInitExt; - if let Ok(layer) = tracing_android::layer("wzp_android") { - let _ = tracing_subscriber::registry().with(layer).try_init(); - } + // Wrap in catch_unwind — sharded_slab allocation inside + // tracing_subscriber::registry() can crash on some Android + // devices if scudo malloc fails during early initialization. + let _ = std::panic::catch_unwind(|| { + use tracing_subscriber::layer::SubscriberExt; + use tracing_subscriber::util::SubscriberInitExt; + if let Ok(layer) = tracing_android::layer("wzp_android") { + let _ = tracing_subscriber::registry().with(layer).try_init(); + } + }); }); }