fix: refine linux voice runtime behavior

This commit is contained in:
Edison Jwa
2026-05-25 18:26:49 +09:00
parent cd14aa7b98
commit d03ea937e6
9 changed files with 156 additions and 73 deletions
+10 -9
View File
@@ -816,10 +816,9 @@ pub async fn set_input_muted(muted: bool) -> Result<(), BridgeError> {
Ok(())
}
/// Toggle self output-mute (speaker). Mutes locally *and* informs
/// the server. The server uses this for the channel icon next to
/// the client name; the local mute kicks in immediately even
/// before the server acknowledges.
/// Toggle self output-mute (speaker). Mutes locally, informs the
/// server, and clamps local microphone transmit while speaker mute
/// is active so the user cannot continue talking while deafened.
pub async fn set_output_muted(muted: bool) -> Result<(), BridgeError> {
runtime()
.spawn(async move { session().set_self_muted(None, Some(muted)).await })
@@ -1230,8 +1229,7 @@ impl From<chanora_core::AudioProcessingStats> for BridgeAudioProcessingStats {
/// On non-Android targets or before a voice session opens the
/// section is omitted. Per SDD-090 every field in that section is
/// a device-side technical scalar — no PII admitted.
#[frb(sync)]
pub fn export_diagnostics() -> String {
pub async fn export_diagnostics() -> String {
let metadata = vec![
(
"crate_version".to_string(),
@@ -1247,12 +1245,15 @@ pub fn export_diagnostics() -> String {
// diagnostics snapshot from the process-global slot published
// by AndroidVoiceUnit::open(). Returns None on non-Android and
// before any voice session has opened.
#[cfg(target_os = "android")]
let android_audio_yaml =
chanora_audio::mobile_voice_backend::current_android_audio_diagnostics()
.map(|d| d.to_yaml_fragment());
let audio_health = runtime().block_on(async { session().audio_processing_stats().await.ok() });
let network_info = runtime().block_on(async { session().network_diagnostics_summary().await });
let protocol_events = runtime().block_on(async { session().drain_protocol_events().await });
#[cfg(not(target_os = "android"))]
let android_audio_yaml: Option<String> = None;
let audio_health = session().audio_processing_stats().await.ok();
let network_info = session().network_diagnostics_summary().await;
let protocol_events = session().drain_protocol_events().await;
let android_audio_yaml = android_audio_yaml.map(|mut yaml| {
if let Some(stats) = audio_health {
yaml.push_str(&format!(
+15 -9
View File
@@ -370,15 +370,16 @@ fn wire__crate__api__events_stream_impl(
)
}
fn wire__crate__api__export_diagnostics_impl(
port_: flutter_rust_bridge::for_generated::MessagePort,
ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr,
rust_vec_len_: i32,
data_len_: i32,
) -> flutter_rust_bridge::for_generated::WireSyncRust2DartSse {
FLUTTER_RUST_BRIDGE_HANDLER.wrap_sync::<flutter_rust_bridge::for_generated::SseCodec, _>(
) {
FLUTTER_RUST_BRIDGE_HANDLER.wrap_async::<flutter_rust_bridge::for_generated::SseCodec, _, _, _>(
flutter_rust_bridge::for_generated::TaskInfo {
debug_name: "export_diagnostics",
port: None,
mode: flutter_rust_bridge::for_generated::FfiCallMode::Sync,
port: Some(port_),
mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal,
},
move || {
let message = unsafe {
@@ -391,10 +392,15 @@ fn wire__crate__api__export_diagnostics_impl(
let mut deserializer =
flutter_rust_bridge::for_generated::SseDeserializer::new(message);
deserializer.end();
transform_result_sse::<_, ()>((move || {
let output_ok = Result::<_, ()>::Ok(crate::api::export_diagnostics())?;
Ok(output_ok)
})())
move |context| async move {
transform_result_sse::<_, crate::BridgeError>(
(move || async move {
let output_ok = crate::api::export_diagnostics().await;
Ok(output_ok)
})()
.await,
)
}
},
)
}
@@ -2509,6 +2515,7 @@ fn pde_ffi_dispatcher_primary_impl(
7 => wire__crate__api__disconnect_impl(port, ptr, rust_vec_len, data_len),
8 => wire__crate__api__enable_audio_debug_wav_dump_impl(port, ptr, rust_vec_len, data_len),
9 => wire__crate__api__events_stream_impl(port, ptr, rust_vec_len, data_len),
10 => wire__crate__api__export_diagnostics_impl(port, ptr, rust_vec_len, data_len),
11 => wire__crate__api__get_audio_processing_config_impl(port, ptr, rust_vec_len, data_len),
12 => wire__crate__api__get_ptt_binding_impl(port, ptr, rust_vec_len, data_len),
13 => wire__crate__api__get_release_tail_ms_impl(port, ptr, rust_vec_len, data_len),
@@ -2552,7 +2559,6 @@ fn pde_ffi_dispatcher_sync_impl(
) -> flutter_rust_bridge::for_generated::WireSyncRust2DartSse {
// Codec=Pde (Serialization + dispatch), see doc to use other codecs
match func_id {
10 => wire__crate__api__export_diagnostics_impl(ptr, rust_vec_len, data_len),
15 => wire__crate__api__handle_interruption_began_impl(ptr, rust_vec_len, data_len),
16 => wire__crate__api__handle_interruption_ended_impl(ptr, rust_vec_len, data_len),
17 => wire__crate__api__handle_media_services_reset_with_route_impl(