diff options
author | 2025-01-30 00:29:24 +0000 | |
---|---|---|
committer | 2025-01-30 17:05:17 +0000 | |
commit | 990d8097acf8bc8ef7fb6754182d87d9d5c27b76 (patch) | |
tree | 8d5958aaf492cfbe1ba4690da1fa6e8843d0d329 /offload | |
parent | f64f083469d2f61ae6f37b33ea1a370a1657f60b (diff) |
LE Audio Software offload:
- Fix death recipient registration
- Fix redeclaration of proxy service accross multiple initialization
Bug: 392120387
Bug: 391870839
Flag: EXEMPT, enabled by vendor
Test: mmm .
Change-Id: Ied24eaac4ee4b2c8f4640b3dc549334744418d6c
Diffstat (limited to 'offload')
-rw-r--r-- | offload/hal/service.rs | 51 | ||||
-rw-r--r-- | offload/leaudio/hci/proxy.rs | 10 | ||||
-rw-r--r-- | offload/leaudio/hci/service.rs | 48 |
3 files changed, 46 insertions, 63 deletions
diff --git a/offload/hal/service.rs b/offload/hal/service.rs index 779be6da8c..eb8c679b09 100644 --- a/offload/hal/service.rs +++ b/offload/hal/service.rs @@ -16,7 +16,7 @@ use crate::ffi::{CInterface, CStatus, Callbacks, DataCallbacks, Ffi}; use android_hardware_bluetooth::aidl::android::hardware::bluetooth::{ IBluetoothHci::IBluetoothHci, IBluetoothHciCallbacks::IBluetoothHciCallbacks, Status::Status, }; -use binder::{DeathRecipient, ExceptionCode, Interface, Result as BinderResult, Strong}; +use binder::{DeathRecipient, ExceptionCode, IBinder, Interface, Result as BinderResult, Strong}; use bluetooth_offload_hci::{Module, ModuleBuilder}; use std::sync::{Arc, RwLock}; @@ -41,7 +41,6 @@ struct SinkModule<T: Callbacks> { enum State { Closed, - Opening { ffi: Arc<Ffi<FfiCallbacks>>, proxy: Arc<dyn Module> }, Opened { proxy: Arc<dyn Module>, _death_recipient: DeathRecipient }, } @@ -73,10 +72,25 @@ impl IBluetoothHci for HciHalProxy { for m in self.modules.iter().rev() { proxy = m.build(proxy); } - let callbacks = FfiCallbacks::new(callbacks.clone(), proxy.clone(), self.state.clone()); - *state = State::Opening { ffi: self.ffi.clone(), proxy: proxy.clone() }; - (self.ffi.clone(), callbacks) + let mut death_recipient = { + let (ffi, state) = (self.ffi.clone(), self.state.clone()); + DeathRecipient::new(move || { + log::info!("Bluetooth stack has died"); + let mut state = state.write().unwrap(); + if !matches!(*state, State::Closed) { + ffi.close(); + } + *state = State::Closed; + }) + }; + callbacks.as_binder().link_to_death(&mut death_recipient)?; + + *state = State::Opened { proxy: proxy.clone(), _death_recipient: death_recipient }; + ( + self.ffi.clone(), + FfiCallbacks::new(callbacks.clone(), proxy.clone(), self.state.clone()), + ) }; ffi.initialize(callbacks); @@ -185,31 +199,12 @@ impl FfiCallbacks { impl Callbacks for FfiCallbacks { fn initialization_complete(&self, status: CStatus) { let mut state = self.state.write().unwrap(); - match status { - CStatus::Success => { - let State::Opening { ref ffi, ref proxy } = *state else { - panic!("Initialization completed called in bad state"); - }; - - *state = State::Opened { - proxy: proxy.clone(), - _death_recipient: { - let (ffi, state) = (ffi.clone(), self.state.clone()); - DeathRecipient::new(move || { - log::info!("Bluetooth stack has died"); - *state.write().unwrap() = State::Closed; - ffi.close(); - }) - }, - }; - } - - CStatus::AlreadyInitialized => panic!("Initialization completed called in bad state"), - _ => *state = State::Closed, - }; - + if status != CStatus::Success { + *state = State::Closed; + } if let Err(e) = self.callbacks.initializationComplete(status.into()) { log::error!("Cannot call-back client: {:?}", e); + *state = State::Closed; } } } diff --git a/offload/leaudio/hci/proxy.rs b/offload/leaudio/hci/proxy.rs index 413a7f84b5..79e45f06e1 100644 --- a/offload/leaudio/hci/proxy.rs +++ b/offload/leaudio/hci/proxy.rs @@ -29,7 +29,6 @@ pub struct LeAudioModuleBuilder {} pub(crate) struct LeAudioModule { next_module: Arc<dyn Module>, state: Mutex<State>, - service: Service, } #[derive(Default)] @@ -145,13 +144,14 @@ impl Stream { impl ModuleBuilder for LeAudioModuleBuilder { /// Build the HCI-Proxy module from the next module in the chain fn build(&self, next_module: Arc<dyn Module>) -> Arc<dyn Module> { + Service::register(); Arc::new(LeAudioModule::new(next_module)) } } impl LeAudioModule { pub(crate) fn new(next_module: Arc<dyn Module>) -> Self { - Self { next_module, state: Mutex::new(Default::default()), service: Service::new() } + Self { next_module, state: Mutex::new(Default::default()) } } #[cfg(test)] @@ -216,7 +216,7 @@ impl Module for LeAudioModule { ret.iso_data_packet_length.into(), ret.total_num_iso_data_packets.into(), ))); - self.service.reset(Arc::downgrade(state.arbiter.as_ref().unwrap())); + Service::reset(Arc::downgrade(state.arbiter.as_ref().unwrap())); } ReturnParameters::LeSetCigParameters(ref ret) if ret.status == Status::Success => { @@ -249,7 +249,7 @@ impl Module for LeAudioModule { IsoType::Bis { ref c_to_p } => c_to_p, }; - self.service.start_stream( + Service::start_stream( ret.connection_handle, StreamConfiguration { isoIntervalUs: stream.iso_interval_us as i32, @@ -265,7 +265,7 @@ impl Module for LeAudioModule { let mut state = self.state.lock().unwrap(); let stream = state.stream.get_mut(&ret.connection_handle).unwrap(); if stream.state == StreamState::Enabled { - self.service.stop_stream(ret.connection_handle); + Service::stop_stream(ret.connection_handle); } stream.state = StreamState::Disabled; } diff --git a/offload/leaudio/hci/service.rs b/offload/leaudio/hci/service.rs index 85fac7168c..05bc377287 100644 --- a/offload/leaudio/hci/service.rs +++ b/offload/leaudio/hci/service.rs @@ -19,12 +19,10 @@ use aidl::android::hardware::bluetooth::offload::leaudio::{ IHciProxy::{BnHciProxy, BpHciProxy, IHciProxy}, IHciProxyCallbacks::IHciProxyCallbacks, }; -use binder::{ - BinderFeatures, DeathRecipient, ExceptionCode, Interface, Result as BinderResult, Strong, -}; +use binder::{BinderFeatures, ExceptionCode, Interface, Result as BinderResult, Strong}; use bluetooth_offload_hci::IsoData; use std::collections::HashMap; -use std::sync::{Arc, Mutex, Weak}; +use std::sync::{Arc, LazyLock, Mutex, Weak}; pub(crate) use aidl::android::hardware::bluetooth::offload::leaudio::StreamConfiguration::StreamConfiguration; @@ -32,27 +30,31 @@ pub(crate) struct Service { state: Arc<Mutex<State>>, } +static SERVICE: LazyLock<Service> = LazyLock::new(|| { + let state = Arc::new(Mutex::new(State::default())); + HciProxy::register(state.clone()); + Service { state } +}); + #[derive(Default)] struct State { arbiter: Weak<Arbiter>, - callbacks: Option<Strong<dyn IHciProxyCallbacks>>, streams: HashMap<u16, StreamConfiguration>, + callbacks: Option<Strong<dyn IHciProxyCallbacks>>, } impl Service { - pub(crate) fn new() -> Self { - let state = Arc::new(Mutex::new(State::default())); - HciProxy::register(state.clone()); - Self { state } + pub(crate) fn register() { + LazyLock::force(&SERVICE); } - pub(crate) fn reset(&self, arbiter: Weak<Arbiter>) { - let mut state = self.state.lock().unwrap(); + pub(crate) fn reset(arbiter: Weak<Arbiter>) { + let mut state = SERVICE.state.lock().unwrap(); *state = State { arbiter, ..Default::default() } } - pub(crate) fn start_stream(&self, handle: u16, config: StreamConfiguration) { - let mut state = self.state.lock().unwrap(); + pub(crate) fn start_stream(handle: u16, config: StreamConfiguration) { + let mut state = SERVICE.state.lock().unwrap(); if let Some(callbacks) = &state.callbacks { let _ = callbacks.startStream(handle.into(), &config); } else { @@ -61,8 +63,8 @@ impl Service { state.streams.insert(handle, config); } - pub(crate) fn stop_stream(&self, handle: u16) { - let mut state = self.state.lock().unwrap(); + pub(crate) fn stop_stream(handle: u16) { + let mut state = SERVICE.state.lock().unwrap(); state.streams.remove(&handle); if let Some(callbacks) = &state.callbacks { let _ = callbacks.stopStream(handle.into()); @@ -72,28 +74,15 @@ impl Service { struct HciProxy { state: Arc<Mutex<State>>, - _death_recipient: DeathRecipient, } impl Interface for HciProxy {} impl HciProxy { fn register(state: Arc<Mutex<State>>) { - let death_recipient = { - let state = state.clone(); - DeathRecipient::new(move || { - log::info!("Client has died"); - state.lock().unwrap().callbacks = None; - }) - }; - binder::add_service( &format!("{}/default", BpHciProxy::get_descriptor()), - BnHciProxy::new_binder( - Self { state, _death_recipient: death_recipient }, - BinderFeatures::default(), - ) - .as_binder(), + BnHciProxy::new_binder(Self { state }, BinderFeatures::default()).as_binder(), ) .expect("Failed to register service"); } @@ -106,7 +95,6 @@ impl IHciProxy for HciProxy { for (handle, config) in &state.streams { let _ = callbacks.startStream((*handle).into(), config); } - Ok(()) } |