rust/bt-broadcast-assistant: Parse broadcast name from scan results Store broadcast name metadata discovered during central scanning into BroadcastSource records. This enables assistant utilities and user interfaces to present human-readable broadcast names to users when scanning for public broadcast audio streams, directly matching Public Broadcast Profile specifications. Bug: b/366310724 Test: cargo test Change-Id: I015f00552950d609f21e461f5da8fb85b6485919 Reviewed-on: https://bluetooth-review.googlesource.com/c/bluetooth/+/2960
diff --git a/rust/bt-broadcast-assistant/src/assistant.rs b/rust/bt-broadcast-assistant/src/assistant.rs index cde253a..b41dcd1 100644 --- a/rust/bt-broadcast-assistant/src/assistant.rs +++ b/rust/bt-broadcast-assistant/src/assistant.rs
@@ -216,6 +216,7 @@ broadcast_id: None, periodic_advertising_interval: None, endpoint: None, + broadcast_name: None, }; Ok(self @@ -254,6 +255,7 @@ broadcast_id: None, periodic_advertising_interval: None, endpoint: Some(endpoint), + broadcast_name: None, }; Ok(self @@ -308,6 +310,7 @@ broadcast_id: Some(bid1), periodic_advertising_interval: None, endpoint: None, + broadcast_name: None, } ); @@ -334,6 +337,7 @@ presentation_delay_ms: 32, big: vec![] }), + broadcast_name: None, } ); @@ -366,6 +370,7 @@ broadcast_id: Some(bid2), periodic_advertising_interval: None, endpoint: None, + broadcast_name: None, } );
diff --git a/rust/bt-broadcast-assistant/src/assistant/event.rs b/rust/bt-broadcast-assistant/src/assistant/event.rs index 40c32bc..1780cf1 100644 --- a/rust/bt-broadcast-assistant/src/assistant/event.rs +++ b/rust/bt-broadcast-assistant/src/assistant/event.rs
@@ -154,12 +154,19 @@ ) -> Result<Option<BroadcastSource>, PacketError> { let mut source = None; for datum in &scan_result.advertised { - let AdvertisingDatum::ServiceData(uuid, data) = datum else { - continue; - }; - if *uuid == BROADCAST_AUDIO_ANNOUNCEMENT_SERVICE { - let bid = BroadcastId::decode(data.as_slice()).0?; - source.get_or_insert(BroadcastSource::default()).with_broadcast_id(bid); + match datum { + AdvertisingDatum::ServiceData(uuid, data) + if *uuid == BROADCAST_AUDIO_ANNOUNCEMENT_SERVICE => + { + let bid = BroadcastId::decode(data.as_slice()).0?; + source.get_or_insert(BroadcastSource::default()).with_broadcast_id(bid); + } + AdvertisingDatum::BroadcastName(name) => { + source + .get_or_insert(BroadcastSource::default()) + .with_broadcast_name(name.clone()); + } + _ => {} } } if let Some(src) = &mut source { @@ -403,10 +410,13 @@ id: broadcast_source_pid, connectable: true, name: PeerName::Unknown, - advertised: vec![AdvertisingDatum::ServiceData( - BROADCAST_AUDIO_ANNOUNCEMENT_SERVICE, - vec![0x01, 0x02, 0x03], - )], + advertised: vec![ + AdvertisingDatum::ServiceData( + BROADCAST_AUDIO_ANNOUNCEMENT_SERVICE, + vec![0x01, 0x02, 0x03], + ), + AdvertisingDatum::BroadcastName("Test Broadcast".to_string()), + ], advertising_sid: Some(1), periodic_advertising_interval: Some(0x0100), })); @@ -473,6 +483,7 @@ assert_eq!(advertising_sid, AdvertisingSetId(1)); assert_eq!(source.periodic_advertising_interval, Some(PeriodicAdvertisingInterval(0x0100))); assert_eq!(source.address, Some([1, 2, 3, 4, 5, 6])); + assert_eq!(source.broadcast_name, Some("Test Broadcast".to_string())); }); // Verify that the PA sync was stopped (removed from active_syncs) to conserve
diff --git a/rust/bt-broadcast-assistant/src/types.rs b/rust/bt-broadcast-assistant/src/types.rs index 93f9715..e6d77d4 100644 --- a/rust/bt-broadcast-assistant/src/types.rs +++ b/rust/bt-broadcast-assistant/src/types.rs
@@ -20,6 +20,7 @@ pub(crate) broadcast_id: Option<BroadcastId>, pub(crate) periodic_advertising_interval: Option<PeriodicAdvertisingInterval>, pub(crate) endpoint: Option<BroadcastAudioSourceEndpoint>, + pub(crate) broadcast_name: Option<String>, } impl BroadcastSource { @@ -60,6 +61,11 @@ self } + pub fn with_broadcast_name(&mut self, name: String) -> &mut Self { + self.broadcast_name = Some(name); + self + } + /// Merge fields from other broadcast source into this broadcast source. /// Set fields in other source take priority over this source. /// If a field in the other broadcast source is none, it's ignored and @@ -80,6 +86,9 @@ if let Some(endpoint) = &other.endpoint { self.endpoint = Some(endpoint.clone()); } + if let Some(broadcast_name) = &other.broadcast_name { + self.broadcast_name = Some(broadcast_name.clone()); + } } /// Returns the representation of this object's endpoint field to