1 use crate::btif::{BluetoothInterface, RawAddress, ToggleableProfile};
2 use crate::topstack::get_dispatchers;
3 
4 use std::sync::{Arc, Mutex};
5 use topshim_macros::{cb_variant, profile_enabled_or, profile_enabled_or_default};
6 
7 use log::warn;
8 
9 #[cxx::bridge(namespace = bluetooth::topshim::rust)]
10 pub mod ffi {
11     unsafe extern "C++" {
12         include!("types/raw_address.h");
13         #[namespace = ""]
14         type RawAddress = crate::btif::RawAddress;
15     }
16 
17     #[derive(Debug, Copy, Clone)]
18     pub enum BtLeAudioCodecIndex {
19         SrcLc3 = 0,
20         SrcInvalid = 1_000_000,
21     }
22 
23     #[derive(Debug, Copy, Clone)]
24     pub struct BtLeAudioCodecConfig {
25         pub codec_type: i32,
26     }
27 
28     #[derive(Debug, Copy, Clone)]
29     pub enum BtLeAudioConnectionState {
30         Disconnected = 0,
31         Connecting,
32         Connected,
33         Disconnecting,
34     }
35 
36     #[derive(Debug, Copy, Clone)]
37     pub enum BtLeAudioGroupStatus {
38         Inactive = 0,
39         Active,
40         TurnedIdleDuringCall,
41     }
42 
43     #[derive(Debug, Copy, Clone)]
44     pub enum BtLeAudioGroupNodeStatus {
45         Added = 1,
46         Removed,
47     }
48 
49     #[derive(Debug, Copy, Clone)]
50     pub enum BtLeAudioUsage {
51         AudioUsageUnknown = 0,
52         AudioUsageMedia = 1,
53         AudioUsageVoiceCommunication = 2,
54     }
55 
56     #[derive(Debug, Copy, Clone)]
57     pub enum BtLeAudioContentType {
58         AudioContentTypeUnknown = 0,
59         AudioContentTypeSpeech = 1,
60         AudioContentTypeMusic = 2,
61         AudioContentTypeMovie = 3,
62         AudioContentTypeSonification = 4,
63     }
64 
65     #[derive(Debug, Copy, Clone)]
66     pub enum BtLeAudioSource {
67         AudioSourceDefault = 0,
68         AudioSourceMic = 1,
69         AudioSourceVoiceUplink = 2,
70         AudioSourceVoiceDownlink = 3,
71         AudioSourceVoiceCall = 4,
72         AudioSourceCamcorder = 5,
73         AudioSourceVoiceRecognition = 6,
74         AudioSourceVoiceCommunication = 7,
75     }
76 
77     #[derive(Debug, Copy, Clone)]
78     #[repr(i32)]
79     pub enum BtLeStreamStartedStatus {
80         Canceled = -1,
81         Idle = 0,
82         Started = 1,
83     }
84 
85     #[derive(Debug, Default)]
86     pub struct BtLePcmConfig {
87         pub data_interval_us: u32,
88         pub sample_rate: u32,
89         pub bits_per_sample: u8,
90         pub channels_count: u8,
91     }
92 
93     #[derive(Debug, Copy, Clone)]
94     pub enum BtLeAudioUnicastMonitorModeStatus {
95         StreamingRequested = 0,
96         Streaming = 1,
97         StreamingSuspended = 2,
98     }
99 
100     #[derive(Debug, Copy, Clone)]
101     pub enum BtLeAudioDirection {
102         Sink = 1,
103         Source = 2,
104         Both = 3,
105     }
106 
107     #[derive(Debug, Copy, Clone)]
108     pub enum BtLeAudioGroupStreamStatus {
109         Idle = 0,
110         Streaming,
111         Releasing,
112         Suspending,
113         Suspended,
114         ConfiguredAutonomous,
115         ConfiguredByUser,
116         Destroyed,
117     }
118 
119     #[derive(Debug)]
120     pub struct SourceMetadata {
121         pub usage: BtLeAudioUsage,
122         pub content_type: BtLeAudioContentType,
123         pub gain: f64,
124     }
125 
126     #[derive(Debug)]
127     pub struct SinkMetadata {
128         pub source: BtLeAudioSource,
129         pub gain: f64,
130     }
131 
132     unsafe extern "C++" {
133         include!("le_audio/le_audio_shim.h");
134 
135         type LeAudioClientIntf;
136 
GetLeAudioClientProfile(btif: *const u8) -> UniquePtr<LeAudioClientIntf>137         unsafe fn GetLeAudioClientProfile(btif: *const u8) -> UniquePtr<LeAudioClientIntf>;
138 
init(self: Pin<&mut LeAudioClientIntf>)139         fn init(self: Pin<&mut LeAudioClientIntf>);
connect(self: Pin<&mut LeAudioClientIntf>, addr: RawAddress)140         fn connect(self: Pin<&mut LeAudioClientIntf>, addr: RawAddress);
disconnect(self: Pin<&mut LeAudioClientIntf>, addr: RawAddress)141         fn disconnect(self: Pin<&mut LeAudioClientIntf>, addr: RawAddress);
set_enable_state(self: Pin<&mut LeAudioClientIntf>, addr: RawAddress, enabled: bool)142         fn set_enable_state(self: Pin<&mut LeAudioClientIntf>, addr: RawAddress, enabled: bool);
cleanup(self: Pin<&mut LeAudioClientIntf>)143         fn cleanup(self: Pin<&mut LeAudioClientIntf>);
remove_device(self: Pin<&mut LeAudioClientIntf>, addr: RawAddress)144         fn remove_device(self: Pin<&mut LeAudioClientIntf>, addr: RawAddress);
group_add_node(self: Pin<&mut LeAudioClientIntf>, group_id: i32, addr: RawAddress)145         fn group_add_node(self: Pin<&mut LeAudioClientIntf>, group_id: i32, addr: RawAddress);
group_remove_node(self: Pin<&mut LeAudioClientIntf>, group_id: i32, addr: RawAddress)146         fn group_remove_node(self: Pin<&mut LeAudioClientIntf>, group_id: i32, addr: RawAddress);
group_set_active(self: Pin<&mut LeAudioClientIntf>, group_id: i32)147         fn group_set_active(self: Pin<&mut LeAudioClientIntf>, group_id: i32);
set_codec_config_preference( self: Pin<&mut LeAudioClientIntf>, group_id: i32, input_codec_config: BtLeAudioCodecConfig, output_codec_config: BtLeAudioCodecConfig, )148         fn set_codec_config_preference(
149             self: Pin<&mut LeAudioClientIntf>,
150             group_id: i32,
151             input_codec_config: BtLeAudioCodecConfig,
152             output_codec_config: BtLeAudioCodecConfig,
153         );
set_ccid_information(self: Pin<&mut LeAudioClientIntf>, ccid: i32, context_type: i32)154         fn set_ccid_information(self: Pin<&mut LeAudioClientIntf>, ccid: i32, context_type: i32);
set_in_call(self: Pin<&mut LeAudioClientIntf>, in_call: bool)155         fn set_in_call(self: Pin<&mut LeAudioClientIntf>, in_call: bool);
send_audio_profile_preferences( self: Pin<&mut LeAudioClientIntf>, group_id: i32, is_output_preference_le_audio: bool, is_duplex_preference_le_audio: bool, )156         fn send_audio_profile_preferences(
157             self: Pin<&mut LeAudioClientIntf>,
158             group_id: i32,
159             is_output_preference_le_audio: bool,
160             is_duplex_preference_le_audio: bool,
161         );
set_unicast_monitor_mode( self: Pin<&mut LeAudioClientIntf>, direction: BtLeAudioDirection, enable: bool, )162         fn set_unicast_monitor_mode(
163             self: Pin<&mut LeAudioClientIntf>,
164             direction: BtLeAudioDirection,
165             enable: bool,
166         );
167 
host_start_audio_request(self: Pin<&mut LeAudioClientIntf>) -> bool168         fn host_start_audio_request(self: Pin<&mut LeAudioClientIntf>) -> bool;
host_stop_audio_request(self: Pin<&mut LeAudioClientIntf>)169         fn host_stop_audio_request(self: Pin<&mut LeAudioClientIntf>);
peer_start_audio_request(self: Pin<&mut LeAudioClientIntf>) -> bool170         fn peer_start_audio_request(self: Pin<&mut LeAudioClientIntf>) -> bool;
peer_stop_audio_request(self: Pin<&mut LeAudioClientIntf>)171         fn peer_stop_audio_request(self: Pin<&mut LeAudioClientIntf>);
get_host_pcm_config(self: Pin<&mut LeAudioClientIntf>) -> BtLePcmConfig172         fn get_host_pcm_config(self: Pin<&mut LeAudioClientIntf>) -> BtLePcmConfig;
get_peer_pcm_config(self: Pin<&mut LeAudioClientIntf>) -> BtLePcmConfig173         fn get_peer_pcm_config(self: Pin<&mut LeAudioClientIntf>) -> BtLePcmConfig;
get_host_stream_started(self: Pin<&mut LeAudioClientIntf>) -> BtLeStreamStartedStatus174         fn get_host_stream_started(self: Pin<&mut LeAudioClientIntf>) -> BtLeStreamStartedStatus;
get_peer_stream_started(self: Pin<&mut LeAudioClientIntf>) -> BtLeStreamStartedStatus175         fn get_peer_stream_started(self: Pin<&mut LeAudioClientIntf>) -> BtLeStreamStartedStatus;
source_metadata_changed( self: Pin<&mut LeAudioClientIntf>, metadata: Vec<SourceMetadata>, )176         fn source_metadata_changed(
177             self: Pin<&mut LeAudioClientIntf>,
178             metadata: Vec<SourceMetadata>,
179         );
sink_metadata_changed(self: Pin<&mut LeAudioClientIntf>, metadata: Vec<SinkMetadata>)180         fn sink_metadata_changed(self: Pin<&mut LeAudioClientIntf>, metadata: Vec<SinkMetadata>);
181     }
182 
183     extern "Rust" {
le_audio_initialized_callback()184         fn le_audio_initialized_callback();
le_audio_connection_state_callback(state: BtLeAudioConnectionState, addr: RawAddress)185         fn le_audio_connection_state_callback(state: BtLeAudioConnectionState, addr: RawAddress);
le_audio_group_status_callback(group_id: i32, group_status: BtLeAudioGroupStatus)186         fn le_audio_group_status_callback(group_id: i32, group_status: BtLeAudioGroupStatus);
le_audio_group_node_status_callback( bd_addr: RawAddress, group_id: i32, node_status: BtLeAudioGroupNodeStatus, )187         fn le_audio_group_node_status_callback(
188             bd_addr: RawAddress,
189             group_id: i32,
190             node_status: BtLeAudioGroupNodeStatus,
191         );
le_audio_audio_conf_callback( direction: u8, group_id: i32, snk_audio_location: u32, src_audio_location: u32, avail_cont: u16, )192         fn le_audio_audio_conf_callback(
193             direction: u8,
194             group_id: i32,
195             snk_audio_location: u32,
196             src_audio_location: u32,
197             avail_cont: u16,
198         );
le_audio_sink_audio_location_available_callback( addr: RawAddress, snk_audio_locations: u32, )199         fn le_audio_sink_audio_location_available_callback(
200             addr: RawAddress,
201             snk_audio_locations: u32,
202         );
le_audio_audio_local_codec_capabilities_callback( local_input_capa_codec_conf: &Vec<BtLeAudioCodecConfig>, local_output_capa_codec_conf: &Vec<BtLeAudioCodecConfig>, )203         fn le_audio_audio_local_codec_capabilities_callback(
204             local_input_capa_codec_conf: &Vec<BtLeAudioCodecConfig>,
205             local_output_capa_codec_conf: &Vec<BtLeAudioCodecConfig>,
206         );
le_audio_audio_group_codec_conf_callback( group_id: i32, input_codec_conf: BtLeAudioCodecConfig, output_codec_conf: BtLeAudioCodecConfig, input_selectable_codec_conf: &Vec<BtLeAudioCodecConfig>, output_selectable_codec_conf: &Vec<BtLeAudioCodecConfig>, )207         fn le_audio_audio_group_codec_conf_callback(
208             group_id: i32,
209             input_codec_conf: BtLeAudioCodecConfig,
210             output_codec_conf: BtLeAudioCodecConfig,
211             input_selectable_codec_conf: &Vec<BtLeAudioCodecConfig>,
212             output_selectable_codec_conf: &Vec<BtLeAudioCodecConfig>,
213         );
le_audio_unicast_monitor_mode_status_callback( direction: BtLeAudioDirection, status: BtLeAudioUnicastMonitorModeStatus, )214         fn le_audio_unicast_monitor_mode_status_callback(
215             direction: BtLeAudioDirection,
216             status: BtLeAudioUnicastMonitorModeStatus,
217         );
218 
le_audio_group_stream_status_callback(group_id: i32, status: BtLeAudioGroupStreamStatus)219         fn le_audio_group_stream_status_callback(group_id: i32, status: BtLeAudioGroupStreamStatus);
220     }
221 }
222 
223 pub type BtLeAudioCodecConfig = ffi::BtLeAudioCodecConfig;
224 pub type BtLeAudioCodecIndex = ffi::BtLeAudioCodecIndex;
225 pub type BtLeAudioConnectionState = ffi::BtLeAudioConnectionState;
226 pub type BtLeAudioDirection = ffi::BtLeAudioDirection;
227 pub type BtLeAudioGroupStatus = ffi::BtLeAudioGroupStatus;
228 pub type BtLeAudioGroupNodeStatus = ffi::BtLeAudioGroupNodeStatus;
229 pub type BtLePcmConfig = ffi::BtLePcmConfig;
230 pub type BtLeStreamStartedStatus = ffi::BtLeStreamStartedStatus;
231 pub type BtLeAudioUsage = ffi::BtLeAudioUsage;
232 pub type BtLeAudioContentType = ffi::BtLeAudioContentType;
233 pub type BtLeAudioSource = ffi::BtLeAudioSource;
234 pub type BtLeAudioUnicastMonitorModeStatus = ffi::BtLeAudioUnicastMonitorModeStatus;
235 pub type BtLeAudioGroupStreamStatus = ffi::BtLeAudioGroupStreamStatus;
236 pub type SourceMetadata = ffi::SourceMetadata;
237 pub type SinkMetadata = ffi::SinkMetadata;
238 
239 impl From<BtLeAudioGroupStatus> for i32 {
from(value: BtLeAudioGroupStatus) -> Self240     fn from(value: BtLeAudioGroupStatus) -> Self {
241         match value {
242             BtLeAudioGroupStatus::Inactive => 0,
243             BtLeAudioGroupStatus::Active => 1,
244             BtLeAudioGroupStatus::TurnedIdleDuringCall => 2,
245             _ => panic!("Invalid value {:?} to BtLeAudioGroupStatus", value),
246         }
247     }
248 }
249 
250 impl From<i32> for BtLeAudioGroupStatus {
from(value: i32) -> Self251     fn from(value: i32) -> Self {
252         match value {
253             0 => BtLeAudioGroupStatus::Inactive,
254             1 => BtLeAudioGroupStatus::Active,
255             2 => BtLeAudioGroupStatus::TurnedIdleDuringCall,
256             _ => panic!("Invalid value {} for BtLeAudioGroupStatus", value),
257         }
258     }
259 }
260 
261 impl Default for BtLeAudioGroupStatus {
default() -> Self262     fn default() -> Self {
263         BtLeAudioGroupStatus::Inactive
264     }
265 }
266 
267 impl From<BtLeAudioGroupNodeStatus> for i32 {
from(value: BtLeAudioGroupNodeStatus) -> Self268     fn from(value: BtLeAudioGroupNodeStatus) -> Self {
269         match value {
270             BtLeAudioGroupNodeStatus::Added => 1,
271             BtLeAudioGroupNodeStatus::Removed => 2,
272             _ => panic!("Invalid value {:?} to BtLeAudioGroupNodeStatus", value),
273         }
274     }
275 }
276 
277 impl From<i32> for BtLeAudioGroupNodeStatus {
from(value: i32) -> Self278     fn from(value: i32) -> Self {
279         match value {
280             1 => BtLeAudioGroupNodeStatus::Added,
281             2 => BtLeAudioGroupNodeStatus::Removed,
282             _ => panic!("Invalid value {} for BtLeAudioGroupNodeStatus", value),
283         }
284     }
285 }
286 
287 impl From<BtLeAudioUsage> for i32 {
from(value: BtLeAudioUsage) -> Self288     fn from(value: BtLeAudioUsage) -> Self {
289         match value {
290             BtLeAudioUsage::AudioUsageUnknown => 0,
291             BtLeAudioUsage::AudioUsageMedia => 1,
292             BtLeAudioUsage::AudioUsageVoiceCommunication => 2,
293             _ => panic!("Invalid value {:?} for BtLeAudioUsage", value),
294         }
295     }
296 }
297 
298 impl From<i32> for BtLeAudioUsage {
from(value: i32) -> Self299     fn from(value: i32) -> Self {
300         match value {
301             0 => BtLeAudioUsage::AudioUsageUnknown,
302             1 => BtLeAudioUsage::AudioUsageMedia,
303             2 => BtLeAudioUsage::AudioUsageVoiceCommunication,
304             _ => panic!("Invalid value {} for BtLeAudioUsage", value),
305         }
306     }
307 }
308 
309 impl From<BtLeAudioContentType> for i32 {
from(value: BtLeAudioContentType) -> Self310     fn from(value: BtLeAudioContentType) -> Self {
311         match value {
312             BtLeAudioContentType::AudioContentTypeUnknown => 0,
313             BtLeAudioContentType::AudioContentTypeSpeech => 1,
314             BtLeAudioContentType::AudioContentTypeMusic => 2,
315             BtLeAudioContentType::AudioContentTypeMovie => 3,
316             BtLeAudioContentType::AudioContentTypeSonification => 4,
317             _ => panic!("Invalid value {:?} for BtLeAudioContentType", value),
318         }
319     }
320 }
321 
322 impl From<i32> for BtLeAudioContentType {
from(value: i32) -> Self323     fn from(value: i32) -> Self {
324         match value {
325             0 => BtLeAudioContentType::AudioContentTypeUnknown,
326             1 => BtLeAudioContentType::AudioContentTypeSpeech,
327             2 => BtLeAudioContentType::AudioContentTypeMusic,
328             3 => BtLeAudioContentType::AudioContentTypeMovie,
329             4 => BtLeAudioContentType::AudioContentTypeSonification,
330             _ => panic!("Invalid value {} for BtLeAudioContentType", value),
331         }
332     }
333 }
334 
335 impl From<BtLeAudioSource> for i32 {
from(value: BtLeAudioSource) -> Self336     fn from(value: BtLeAudioSource) -> Self {
337         match value {
338             BtLeAudioSource::AudioSourceDefault => 0,
339             BtLeAudioSource::AudioSourceMic => 1,
340             BtLeAudioSource::AudioSourceVoiceUplink => 2,
341             BtLeAudioSource::AudioSourceVoiceDownlink => 3,
342             BtLeAudioSource::AudioSourceVoiceCall => 4,
343             BtLeAudioSource::AudioSourceCamcorder => 5,
344             BtLeAudioSource::AudioSourceVoiceRecognition => 6,
345             BtLeAudioSource::AudioSourceVoiceCommunication => 7,
346             _ => panic!("Invalid value {:?} for BtLeAudioSource", value),
347         }
348     }
349 }
350 
351 impl From<i32> for BtLeAudioSource {
from(value: i32) -> Self352     fn from(value: i32) -> Self {
353         match value {
354             0 => BtLeAudioSource::AudioSourceDefault,
355             1 => BtLeAudioSource::AudioSourceMic,
356             2 => BtLeAudioSource::AudioSourceVoiceUplink,
357             3 => BtLeAudioSource::AudioSourceVoiceDownlink,
358             4 => BtLeAudioSource::AudioSourceVoiceCall,
359             5 => BtLeAudioSource::AudioSourceCamcorder,
360             6 => BtLeAudioSource::AudioSourceVoiceRecognition,
361             7 => BtLeAudioSource::AudioSourceVoiceCommunication,
362             _ => panic!("Invalid value {} for BtLeAudioSource", value),
363         }
364     }
365 }
366 
367 impl From<BtLeStreamStartedStatus> for i32 {
from(value: BtLeStreamStartedStatus) -> Self368     fn from(value: BtLeStreamStartedStatus) -> Self {
369         match value {
370             BtLeStreamStartedStatus::Canceled => -1,
371             BtLeStreamStartedStatus::Idle => 0,
372             BtLeStreamStartedStatus::Started => 1,
373             _ => panic!("Invalid value {:?} for BtLeStreamStartedStatus", value),
374         }
375     }
376 }
377 
378 impl From<i32> for BtLeStreamStartedStatus {
from(value: i32) -> Self379     fn from(value: i32) -> Self {
380         match value {
381             -1 => BtLeStreamStartedStatus::Canceled,
382             0 => BtLeStreamStartedStatus::Idle,
383             1 => BtLeStreamStartedStatus::Started,
384             _ => panic!("Invalid value {} for BtLeStreamStartedStatus", value),
385         }
386     }
387 }
388 impl From<BtLeAudioUnicastMonitorModeStatus> for i32 {
from(value: BtLeAudioUnicastMonitorModeStatus) -> Self389     fn from(value: BtLeAudioUnicastMonitorModeStatus) -> Self {
390         match value {
391             BtLeAudioUnicastMonitorModeStatus::StreamingRequested => 0,
392             BtLeAudioUnicastMonitorModeStatus::Streaming => 1,
393             BtLeAudioUnicastMonitorModeStatus::StreamingSuspended => 2,
394             _ => panic!("Invalid value {:?} to BtLeAudioUnicastMonitorModeStatus", value),
395         }
396     }
397 }
398 
399 impl From<i32> for BtLeAudioUnicastMonitorModeStatus {
from(value: i32) -> Self400     fn from(value: i32) -> Self {
401         match value {
402             0 => BtLeAudioUnicastMonitorModeStatus::StreamingRequested,
403             1 => BtLeAudioUnicastMonitorModeStatus::Streaming,
404             2 => BtLeAudioUnicastMonitorModeStatus::StreamingSuspended,
405             _ => panic!("Invalid value {} for BtLeAudioUnicastMonitorModeStatus", value),
406         }
407     }
408 }
409 
410 impl From<BtLeAudioGroupStreamStatus> for i32 {
from(value: BtLeAudioGroupStreamStatus) -> Self411     fn from(value: BtLeAudioGroupStreamStatus) -> Self {
412         match value {
413             BtLeAudioGroupStreamStatus::Idle => 0,
414             BtLeAudioGroupStreamStatus::Streaming => 1,
415             BtLeAudioGroupStreamStatus::Releasing => 2,
416             BtLeAudioGroupStreamStatus::Suspending => 3,
417             BtLeAudioGroupStreamStatus::Suspended => 4,
418             BtLeAudioGroupStreamStatus::ConfiguredAutonomous => 5,
419             BtLeAudioGroupStreamStatus::ConfiguredByUser => 6,
420             BtLeAudioGroupStreamStatus::Destroyed => 7,
421             _ => panic!("Invalid value {:?} to BtLeAudioGroupStreamStatus", value),
422         }
423     }
424 }
425 
426 impl From<i32> for BtLeAudioGroupStreamStatus {
from(value: i32) -> Self427     fn from(value: i32) -> Self {
428         match value {
429             0 => BtLeAudioGroupStreamStatus::Idle,
430             1 => BtLeAudioGroupStreamStatus::Streaming,
431             2 => BtLeAudioGroupStreamStatus::Releasing,
432             3 => BtLeAudioGroupStreamStatus::Suspending,
433             4 => BtLeAudioGroupStreamStatus::Suspended,
434             5 => BtLeAudioGroupStreamStatus::ConfiguredAutonomous,
435             6 => BtLeAudioGroupStreamStatus::ConfiguredByUser,
436             7 => BtLeAudioGroupStreamStatus::Destroyed,
437             _ => panic!("Invalid value {} to BtLeAudioGroupStreamStatus", value),
438         }
439     }
440 }
441 
442 impl Default for BtLeAudioGroupStreamStatus {
default() -> Self443     fn default() -> Self {
444         BtLeAudioGroupStreamStatus::Idle
445     }
446 }
447 
448 impl From<BtLeAudioDirection> for i32 {
from(value: BtLeAudioDirection) -> Self449     fn from(value: BtLeAudioDirection) -> Self {
450         match value {
451             BtLeAudioDirection::Sink => 1,
452             BtLeAudioDirection::Source => 2,
453             BtLeAudioDirection::Both => 3,
454             _ => panic!("Invalid value {:?} to BtLeAudioDirection", value),
455         }
456     }
457 }
458 
459 impl From<i32> for BtLeAudioDirection {
from(value: i32) -> Self460     fn from(value: i32) -> Self {
461         match value {
462             1 => BtLeAudioDirection::Sink,
463             2 => BtLeAudioDirection::Source,
464             3 => BtLeAudioDirection::Both,
465             _ => panic!("Invalid value {} for BtLeAudioDirection", value),
466         }
467     }
468 }
469 
470 #[derive(Debug)]
471 pub enum LeAudioClientCallbacks {
472     Initialized(),
473     ConnectionState(BtLeAudioConnectionState, RawAddress),
474     GroupStatus(i32, BtLeAudioGroupStatus),
475     GroupNodeStatus(RawAddress, i32, BtLeAudioGroupNodeStatus),
476     AudioConf(u8, i32, u32, u32, u16),
477     SinkAudioLocationAvailable(RawAddress, u32),
478     AudioLocalCodecCapabilities(Vec<BtLeAudioCodecConfig>, Vec<BtLeAudioCodecConfig>),
479     AudioGroupCodecConf(
480         i32,
481         BtLeAudioCodecConfig,
482         BtLeAudioCodecConfig,
483         Vec<BtLeAudioCodecConfig>,
484         Vec<BtLeAudioCodecConfig>,
485     ),
486     UnicastMonitorModeStatus(BtLeAudioDirection, BtLeAudioUnicastMonitorModeStatus),
487     GroupStreamStatus(i32, BtLeAudioGroupStreamStatus),
488 }
489 
490 pub struct LeAudioClientCallbacksDispatcher {
491     pub dispatch: Box<dyn Fn(LeAudioClientCallbacks) + Send>,
492 }
493 
494 type LeAudioClientCb = Arc<Mutex<LeAudioClientCallbacksDispatcher>>;
495 
496 cb_variant!(LeAudioClientCb,
497             le_audio_initialized_callback -> LeAudioClientCallbacks::Initialized);
498 
499 cb_variant!(LeAudioClientCb,
500             le_audio_connection_state_callback -> LeAudioClientCallbacks::ConnectionState,
501             BtLeAudioConnectionState, RawAddress);
502 
503 cb_variant!(LeAudioClientCb,
504             le_audio_group_status_callback -> LeAudioClientCallbacks::GroupStatus,
505             i32, BtLeAudioGroupStatus);
506 
507 cb_variant!(LeAudioClientCb,
508             le_audio_group_node_status_callback -> LeAudioClientCallbacks::GroupNodeStatus,
509             RawAddress, i32, BtLeAudioGroupNodeStatus);
510 
511 cb_variant!(LeAudioClientCb,
512             le_audio_audio_conf_callback -> LeAudioClientCallbacks::AudioConf,
513             u8, i32, u32, u32, u16);
514 
515 cb_variant!(LeAudioClientCb,
516             le_audio_sink_audio_location_available_callback -> LeAudioClientCallbacks::SinkAudioLocationAvailable,
517             RawAddress, u32);
518 
519 cb_variant!(LeAudioClientCb,
520             le_audio_unicast_monitor_mode_status_callback -> LeAudioClientCallbacks::UnicastMonitorModeStatus,
521             BtLeAudioDirection, BtLeAudioUnicastMonitorModeStatus);
522 
523 cb_variant!(LeAudioClientCb,
524             le_audio_group_stream_status_callback -> LeAudioClientCallbacks::GroupStreamStatus,
525             i32, BtLeAudioGroupStreamStatus);
526 
527 cb_variant!(LeAudioClientCb,
528 le_audio_audio_local_codec_capabilities_callback -> LeAudioClientCallbacks::AudioLocalCodecCapabilities,
529 &Vec<BtLeAudioCodecConfig>, &Vec<BtLeAudioCodecConfig>,
530 {
531     let _0: Vec<BtLeAudioCodecConfig> = _0.to_vec();
532     let _1: Vec<BtLeAudioCodecConfig> = _1.to_vec();
533 });
534 
535 cb_variant!(LeAudioClientCb,
536 le_audio_audio_group_codec_conf_callback -> LeAudioClientCallbacks::AudioGroupCodecConf,
537 i32, BtLeAudioCodecConfig, BtLeAudioCodecConfig,
538 &Vec<BtLeAudioCodecConfig>, &Vec<BtLeAudioCodecConfig>,
539 {
540     let _3: Vec<BtLeAudioCodecConfig> = _3.to_vec();
541     let _4: Vec<BtLeAudioCodecConfig> = _4.to_vec();
542 });
543 
544 pub struct LeAudioClient {
545     internal: cxx::UniquePtr<ffi::LeAudioClientIntf>,
546     is_init: bool,
547     is_enabled: bool,
548 }
549 
550 // For *const u8 opaque btif
551 // SAFETY: `LeAudioClientIntf` is thread-safe to make calls from.
552 unsafe impl Send for LeAudioClient {}
553 
554 impl ToggleableProfile for LeAudioClient {
is_enabled(&self) -> bool555     fn is_enabled(&self) -> bool {
556         self.is_enabled
557     }
558 
enable(&mut self) -> bool559     fn enable(&mut self) -> bool {
560         if self.is_enabled {
561             warn!("LeAudioClient is already enabled.");
562             return false;
563         }
564 
565         self.internal.pin_mut().init();
566         self.is_enabled = true;
567         true
568     }
569 
570     #[profile_enabled_or(false)]
disable(&mut self) -> bool571     fn disable(&mut self) -> bool {
572         if !self.is_enabled {
573             warn!("LeAudioClient is already disabled.");
574             return false;
575         }
576 
577         self.internal.pin_mut().cleanup();
578         self.is_enabled = false;
579         true
580     }
581 }
582 
583 impl LeAudioClient {
new(intf: &BluetoothInterface) -> LeAudioClient584     pub fn new(intf: &BluetoothInterface) -> LeAudioClient {
585         let lea_client_if: cxx::UniquePtr<ffi::LeAudioClientIntf>;
586 
587         // SAFETY: `intf.as_raw_ptr()` is a valid pointer to a `BluetoothInterface`
588         lea_client_if = unsafe { ffi::GetLeAudioClientProfile(intf.as_raw_ptr()) };
589 
590         LeAudioClient { internal: lea_client_if, is_init: false, is_enabled: false }
591     }
592 
is_initialized(&self) -> bool593     pub fn is_initialized(&self) -> bool {
594         self.is_init
595     }
596 
597     // `internal.init` is invoked during `ToggleableProfile::enable`
initialize(&mut self, callbacks: LeAudioClientCallbacksDispatcher) -> bool598     pub fn initialize(&mut self, callbacks: LeAudioClientCallbacksDispatcher) -> bool {
599         if self.is_init {
600             warn!("LeAudioClient has already been initialized");
601             return false;
602         }
603 
604         if get_dispatchers().lock().unwrap().set::<LeAudioClientCb>(Arc::new(Mutex::new(callbacks)))
605         {
606             panic!("Tried to set dispatcher for LeAudioClient callbacks while it already exists");
607         }
608 
609         self.is_init = true;
610 
611         true
612     }
613 
614     #[profile_enabled_or]
connect(&mut self, addr: RawAddress)615     pub fn connect(&mut self, addr: RawAddress) {
616         self.internal.pin_mut().connect(addr);
617     }
618 
619     #[profile_enabled_or]
disconnect(&mut self, addr: RawAddress)620     pub fn disconnect(&mut self, addr: RawAddress) {
621         self.internal.pin_mut().disconnect(addr);
622     }
623 
624     #[profile_enabled_or]
set_enable_state(&mut self, addr: RawAddress, enabled: bool)625     pub fn set_enable_state(&mut self, addr: RawAddress, enabled: bool) {
626         self.internal.pin_mut().set_enable_state(addr, enabled);
627     }
628 
629     #[profile_enabled_or]
cleanup(&mut self)630     pub fn cleanup(&mut self) {
631         self.internal.pin_mut().cleanup();
632     }
633 
634     #[profile_enabled_or]
remove_device(&mut self, addr: RawAddress)635     pub fn remove_device(&mut self, addr: RawAddress) {
636         self.internal.pin_mut().remove_device(addr);
637     }
638 
639     #[profile_enabled_or]
group_add_node(&mut self, group_id: i32, addr: RawAddress)640     pub fn group_add_node(&mut self, group_id: i32, addr: RawAddress) {
641         self.internal.pin_mut().group_add_node(group_id, addr);
642     }
643 
644     #[profile_enabled_or]
group_remove_node(&mut self, group_id: i32, addr: RawAddress)645     pub fn group_remove_node(&mut self, group_id: i32, addr: RawAddress) {
646         self.internal.pin_mut().group_remove_node(group_id, addr);
647     }
648 
649     #[profile_enabled_or]
group_set_active(&mut self, group_id: i32)650     pub fn group_set_active(&mut self, group_id: i32) {
651         self.internal.pin_mut().group_set_active(group_id);
652     }
653 
654     #[profile_enabled_or]
set_codec_config_preference( &mut self, group_id: i32, input_codec_config: BtLeAudioCodecConfig, output_codec_config: BtLeAudioCodecConfig, )655     pub fn set_codec_config_preference(
656         &mut self,
657         group_id: i32,
658         input_codec_config: BtLeAudioCodecConfig,
659         output_codec_config: BtLeAudioCodecConfig,
660     ) {
661         self.internal.pin_mut().set_codec_config_preference(
662             group_id,
663             input_codec_config,
664             output_codec_config,
665         );
666     }
667 
668     #[profile_enabled_or]
set_ccid_information(&mut self, ccid: i32, context_type: i32)669     pub fn set_ccid_information(&mut self, ccid: i32, context_type: i32) {
670         self.internal.pin_mut().set_ccid_information(ccid, context_type);
671     }
672 
673     #[profile_enabled_or]
set_in_call(&mut self, in_call: bool)674     pub fn set_in_call(&mut self, in_call: bool) {
675         self.internal.pin_mut().set_in_call(in_call);
676     }
677 
678     #[profile_enabled_or]
send_audio_profile_preferences( &mut self, group_id: i32, is_output_preference_le_audio: bool, is_duplex_preference_le_audio: bool, )679     pub fn send_audio_profile_preferences(
680         &mut self,
681         group_id: i32,
682         is_output_preference_le_audio: bool,
683         is_duplex_preference_le_audio: bool,
684     ) {
685         self.internal.pin_mut().send_audio_profile_preferences(
686             group_id,
687             is_output_preference_le_audio,
688             is_duplex_preference_le_audio,
689         );
690     }
691 
692     #[profile_enabled_or]
set_unicast_monitor_mode(&mut self, direction: BtLeAudioDirection, enable: bool)693     pub fn set_unicast_monitor_mode(&mut self, direction: BtLeAudioDirection, enable: bool) {
694         self.internal.pin_mut().set_unicast_monitor_mode(direction, enable);
695     }
696 
697     #[profile_enabled_or(false)]
host_start_audio_request(&mut self) -> bool698     pub fn host_start_audio_request(&mut self) -> bool {
699         self.internal.pin_mut().host_start_audio_request()
700     }
701 
702     #[profile_enabled_or]
host_stop_audio_request(&mut self)703     pub fn host_stop_audio_request(&mut self) {
704         self.internal.pin_mut().host_stop_audio_request();
705     }
706 
707     #[profile_enabled_or(false)]
peer_start_audio_request(&mut self) -> bool708     pub fn peer_start_audio_request(&mut self) -> bool {
709         self.internal.pin_mut().peer_start_audio_request()
710     }
711 
712     #[profile_enabled_or]
peer_stop_audio_request(&mut self)713     pub fn peer_stop_audio_request(&mut self) {
714         self.internal.pin_mut().peer_stop_audio_request();
715     }
716 
717     #[profile_enabled_or_default]
get_host_pcm_config(&mut self) -> BtLePcmConfig718     pub fn get_host_pcm_config(&mut self) -> BtLePcmConfig {
719         self.internal.pin_mut().get_host_pcm_config()
720     }
721 
722     #[profile_enabled_or_default]
get_peer_pcm_config(&mut self) -> BtLePcmConfig723     pub fn get_peer_pcm_config(&mut self) -> BtLePcmConfig {
724         self.internal.pin_mut().get_peer_pcm_config()
725     }
726 
727     #[profile_enabled_or(BtLeStreamStartedStatus::Idle)]
get_host_stream_started(&mut self) -> BtLeStreamStartedStatus728     pub fn get_host_stream_started(&mut self) -> BtLeStreamStartedStatus {
729         self.internal.pin_mut().get_host_stream_started()
730     }
731 
732     #[profile_enabled_or(BtLeStreamStartedStatus::Idle)]
get_peer_stream_started(&mut self) -> BtLeStreamStartedStatus733     pub fn get_peer_stream_started(&mut self) -> BtLeStreamStartedStatus {
734         self.internal.pin_mut().get_peer_stream_started()
735     }
736 
737     #[profile_enabled_or]
source_metadata_changed(&mut self, metadata: Vec<SourceMetadata>)738     pub fn source_metadata_changed(&mut self, metadata: Vec<SourceMetadata>) {
739         self.internal.pin_mut().source_metadata_changed(metadata);
740     }
741 
742     #[profile_enabled_or]
sink_metadata_changed(&mut self, metadata: Vec<SinkMetadata>)743     pub fn sink_metadata_changed(&mut self, metadata: Vec<SinkMetadata>) {
744         self.internal.pin_mut().sink_metadata_changed(metadata);
745     }
746 }
747