1 // Copyright 2024, The Android Open Source Project 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 use android_hardware_bluetooth_offload_leaudio::{aidl, binder}; 16 17 use crate::arbiter::Arbiter; 18 use aidl::android::hardware::bluetooth::offload::leaudio::IHciProxy::{ 19 BnHciProxy, BpHciProxy, IHciProxy, 20 }; 21 use aidl::android::hardware::bluetooth::offload::leaudio::IHciProxyCallbacks::IHciProxyCallbacks; 22 use binder::{BinderFeatures, ExceptionCode, Interface, Result as BinderResult, Strong}; 23 use bluetooth_offload_hci::IsoData; 24 use std::collections::HashMap; 25 use std::sync::{Arc, LazyLock, Mutex, Weak}; 26 27 pub(crate) use aidl::android::hardware::bluetooth::offload::leaudio::StreamConfiguration::StreamConfiguration; 28 29 pub(crate) struct Service { 30 state: Arc<Mutex<State>>, 31 } 32 33 static SERVICE: LazyLock<Service> = LazyLock::new(|| { 34 let state = Arc::new(Mutex::new(State::default())); 35 HciProxy::register(state.clone()); 36 Service { state } 37 }); 38 39 #[derive(Default)] 40 struct State { 41 arbiter: Weak<Arbiter>, 42 streams: HashMap<u16, StreamConfiguration>, 43 callbacks: Option<Strong<dyn IHciProxyCallbacks>>, 44 } 45 46 impl Service { register()47 pub(crate) fn register() { 48 LazyLock::force(&SERVICE); 49 } 50 reset(arbiter: Weak<Arbiter>)51 pub(crate) fn reset(arbiter: Weak<Arbiter>) { 52 let mut state = SERVICE.state.lock().unwrap(); 53 *state = State { arbiter, ..Default::default() } 54 } 55 start_stream(handle: u16, config: StreamConfiguration)56 pub(crate) fn start_stream(handle: u16, config: StreamConfiguration) { 57 let mut state = SERVICE.state.lock().unwrap(); 58 if let Some(callbacks) = &state.callbacks { 59 let _ = callbacks.startStream(handle.into(), &config); 60 } else { 61 log::warn!("Stream started without registered client"); 62 }; 63 state.streams.insert(handle, config); 64 } 65 stop_stream(handle: u16)66 pub(crate) fn stop_stream(handle: u16) { 67 let mut state = SERVICE.state.lock().unwrap(); 68 state.streams.remove(&handle); 69 if let Some(callbacks) = &state.callbacks { 70 let _ = callbacks.stopStream(handle.into()); 71 }; 72 } 73 } 74 75 struct HciProxy { 76 state: Arc<Mutex<State>>, 77 } 78 79 impl Interface for HciProxy {} 80 81 impl HciProxy { register(state: Arc<Mutex<State>>)82 fn register(state: Arc<Mutex<State>>) { 83 binder::add_service( 84 &format!("{}/default", BpHciProxy::get_descriptor()), 85 BnHciProxy::new_binder(Self { state }, BinderFeatures::default()).as_binder(), 86 ) 87 .expect("Failed to register service"); 88 } 89 } 90 91 impl IHciProxy for HciProxy { registerCallbacks(&self, callbacks: &Strong<dyn IHciProxyCallbacks>) -> BinderResult<()>92 fn registerCallbacks(&self, callbacks: &Strong<dyn IHciProxyCallbacks>) -> BinderResult<()> { 93 let mut state = self.state.lock().unwrap(); 94 state.callbacks = Some(callbacks.clone()); 95 for (handle, config) in &state.streams { 96 let _ = callbacks.startStream((*handle).into(), config); 97 } 98 Ok(()) 99 } 100 sendPacket(&self, handle: i32, seqnum: i32, data: &[u8]) -> BinderResult<()>101 fn sendPacket(&self, handle: i32, seqnum: i32, data: &[u8]) -> BinderResult<()> { 102 let handle: u16 = handle.try_into().map_err(|_| ExceptionCode::ILLEGAL_ARGUMENT)?; 103 let seqnum: u16 = seqnum.try_into().map_err(|_| ExceptionCode::ILLEGAL_ARGUMENT)?; 104 105 let state = self.state.lock().unwrap(); 106 if let Some(arbiter) = state.arbiter.upgrade() { 107 assert!( 108 data.len() <= arbiter.max_buf_len(), 109 "SDU Fragmentation over HCI is not supported" 110 ); 111 arbiter.push_audio(&IsoData::new(handle, seqnum, data)); 112 } else { 113 log::warn!("Trashing packet received in bad state"); 114 } 115 116 Ok(()) 117 } 118 } 119