summaryrefslogtreecommitdiff
path: root/offload
diff options
context:
space:
mode:
author Antoine SOULIER <asoulier@google.com> 2025-01-30 00:29:24 +0000
committer Antoine SOULIER <asoulier@google.com> 2025-01-30 17:05:17 +0000
commit990d8097acf8bc8ef7fb6754182d87d9d5c27b76 (patch)
tree8d5958aaf492cfbe1ba4690da1fa6e8843d0d329 /offload
parentf64f083469d2f61ae6f37b33ea1a370a1657f60b (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.rs51
-rw-r--r--offload/leaudio/hci/proxy.rs10
-rw-r--r--offload/leaudio/hci/service.rs48
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(())
}