rust/bt-bap: Use BroadcastCode type Migrate all callsites in bt-bass and bt-broadcast-assistant from raw [u8; 16] byte arrays to the strongly typed BroadcastCode struct for consistency and type safety. Bug: 539983871 Test: cargo test, ./presubmit.sh Change-Id: I954bd6da90c71f9e12141d58af4d5f9430bfdd68 Reviewed-on: https://bluetooth-review.googlesource.com/c/bluetooth/+/3480
diff --git a/rust/bt-bap/src/types.rs b/rust/bt-bap/src/types.rs index 5e62c73..7f768e7 100644 --- a/rust/bt-bap/src/types.rs +++ b/rust/bt-bap/src/types.rs
@@ -88,14 +88,24 @@ /// A 16-octet (128-bit) Broadcast Code used for decrypting encrypted /// Broadcast Audio Streams. See BAP v1.0.1 Section 3.7.2.2 for more details. #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] -pub struct BroadcastCode(pub [u8; 16]); +pub struct BroadcastCode([u8; 16]); impl BroadcastCode { pub const BYTE_SIZE: usize = 16; - pub fn new(raw_value: [u8; 16]) -> Self { + pub const fn new(raw_value: [u8; 16]) -> Self { Self(raw_value) } + + pub const fn bytes(&self) -> &[u8; 16] { + &self.0 + } +} + +impl From<BroadcastCode> for [u8; 16] { + fn from(value: BroadcastCode) -> Self { + value.0 + } } /// To associate a PA, used to expose broadcast Audio Stream parameters, with a
diff --git a/rust/bt-bass/src/client.rs b/rust/bt-bass/src/client.rs index a1188c2..9532581 100644 --- a/rust/bt-bass/src/client.rs +++ b/rust/bt-bass/src/client.rs
@@ -93,7 +93,7 @@ broadcast_sources: Arc<Mutex<KnownBroadcastSources>>, /// Keeps track of the broadcast codes that were sent to the remote BASS /// server. - broadcast_codes: Arc<Mutex<HashMap<SourceId, [u8; 16]>>>, + broadcast_codes: Arc<Mutex<HashMap<SourceId, BroadcastCode>>>, // GATT notification streams for BRS characteristic value changes. notification_streams: Option< SelectAll<BoxStream<'static, Result<CharacteristicNotification, bt_gatt::types::Error>>>, @@ -367,11 +367,11 @@ pub async fn set_broadcast_code( &self, broadcast_id: BroadcastId, - broadcast_code: [u8; 16], + broadcast_code: BroadcastCode, ) -> Result<(), Error> { let source_id = self.get_source_id(&broadcast_id)?; - let op = SetBroadcastCodeOperation::new(source_id, BroadcastCode::new(broadcast_code)); + let op = SetBroadcastCodeOperation::new(source_id, broadcast_code); self.write_to_bascp(op).await?; // Save the broadcast code we sent. @@ -979,8 +979,10 @@ ); let mut noop_cx = futures::task::Context::from_waker(futures::task::noop_waker_ref()); - let set_code_fut = - client.set_broadcast_code(BroadcastId::try_from(0x030201).unwrap(), [1; 16]); + let set_code_fut = client.set_broadcast_code( + BroadcastId::try_from(0x030201).unwrap(), + BroadcastCode::new([1; 16]), + ); pin_mut!(set_code_fut); let polled = set_code_fut.poll_unpin(&mut noop_cx); assert_matches!(polled, Poll::Ready(Ok(_))); @@ -991,8 +993,10 @@ let (client, _) = setup_client(); let mut noop_cx = futures::task::Context::from_waker(futures::task::noop_waker_ref()); - let set_code_fut = - client.set_broadcast_code(BroadcastId::try_from(0x030201).unwrap(), [1; 16]); + let set_code_fut = client.set_broadcast_code( + BroadcastId::try_from(0x030201).unwrap(), + BroadcastCode::new([1; 16]), + ); pin_mut!(set_code_fut); let polled = set_code_fut.poll_unpin(&mut noop_cx);
diff --git a/rust/bt-bass/src/client/event.rs b/rust/bt-bass/src/client/event.rs index f7ad10b..6dd6e3f 100644 --- a/rust/bt-bass/src/client/event.rs +++ b/rust/bt-bass/src/client/event.rs
@@ -10,7 +10,7 @@ use futures::{Stream, StreamExt}; use parking_lot::Mutex; -use bt_bap::types::BroadcastId; +use bt_bap::types::{BroadcastCode, BroadcastId}; use bt_common::packet_encoding::Decodable; use bt_gatt::client::CharacteristicNotification; use bt_gatt::types::Error as BtGattError; @@ -33,7 +33,7 @@ // BASS server requires code to since the BIS is encrypted. BroadcastCodeRequired(BroadcastId), // BASS server failed to decrypt BIS using the previously provided code. - InvalidBroadcastCode(BroadcastId, [u8; 16]), + InvalidBroadcastCode(BroadcastId, BroadcastCode), // BASS server has autonomously synchronized to a BIS that is encrypted, and the server // has the correct encryption key to decrypt the BIS. Decrypting(BroadcastId), @@ -64,7 +64,7 @@ } EncryptionStatus::Decrypting => events.push(Event::Decrypting(broadcast_id)), EncryptionStatus::BadCode(code) => { - events.push(Event::InvalidBroadcastCode(broadcast_id, code.clone())) + events.push(Event::InvalidBroadcastCode(broadcast_id, code)) } _ => {} }; @@ -221,8 +221,9 @@ let mut event_streams = EventStream::new(streams, source_tracker); // Send notifications to underlying streams. - let bad_code_status = - EncryptionStatus::BadCode([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]); + let bad_code_status = EncryptionStatus::BadCode(BroadcastCode::new([ + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, + ])); #[rustfmt::skip] sender1 .unbounded_send(Ok(CharacteristicNotification { @@ -260,7 +261,7 @@ let mut noop_cx = futures::task::Context::from_waker(futures::task::noop_waker_ref()); let polled = event_streams.poll_next_unpin(&mut noop_cx); assert_matches!(polled, Poll::Ready(Some(Ok(event))) => { - assert_eq!(event, Event::AddedBroadcastSource(BroadcastId::try_from(0x030201).unwrap(), PaSyncState::FailedToSync, EncryptionStatus::BadCode([1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]))); + assert_eq!(event, Event::AddedBroadcastSource(BroadcastId::try_from(0x030201).unwrap(), PaSyncState::FailedToSync, EncryptionStatus::BadCode(BroadcastCode::new([1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16])))); }); let polled = event_streams.poll_next_unpin(&mut noop_cx);
diff --git a/rust/bt-bass/src/types.rs b/rust/bt-bass/src/types.rs index 64bf76c..8b1d3cf 100644 --- a/rust/bt-bass/src/types.rs +++ b/rust/bt-bass/src/types.rs
@@ -442,7 +442,7 @@ buf[0] = Self::opcode() as u8; buf[1] = self.source_id; - buf[2..2 + Self::BROADCAST_CODE_LEN].copy_from_slice(&self.broadcast_code.0); + buf[2..2 + Self::BROADCAST_CODE_LEN].copy_from_slice(self.broadcast_code.bytes()); Ok(()) } @@ -944,7 +944,7 @@ NotEncrypted, BroadcastCodeRequired, Decrypting, - BadCode([u8; 16]), + BadCode(BroadcastCode), } impl EncryptionStatus { @@ -978,7 +978,7 @@ if buf.len() < 17 { return (Err(PacketError::UnexpectedDataLength), buf.len()); } - (Ok(Self::BadCode(buf[1..17].try_into().unwrap())), 17) + (Ok(Self::BadCode(BroadcastCode::new(buf[1..17].try_into().unwrap()))), 17) } _ => (Err(PacketError::OutOfRange), buf.len()), } @@ -995,7 +995,7 @@ buf[0] = self.raw_value(); match self { - EncryptionStatus::BadCode(code) => buf[1..17].copy_from_slice(code), + EncryptionStatus::BadCode(code) => buf[1..17].copy_from_slice(code.bytes()), _ => {} } Ok(()) @@ -1022,10 +1022,10 @@ let not_encrypted = EncryptionStatus::NotEncrypted; let encrypted = EncryptionStatus::BroadcastCodeRequired; let decrypting = EncryptionStatus::Decrypting; - let bad_code = EncryptionStatus::BadCode([ + let bad_code = EncryptionStatus::BadCode(BroadcastCode::new([ 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x09, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, - ]); + ])); assert_eq!(0x00, not_encrypted.raw_value()); assert_eq!(0x01, encrypted.raw_value()); @@ -1050,10 +1050,10 @@ assert_eq!(len, 1); // Encoding bad code status with code. - let bad_code = EncryptionStatus::BadCode([ + let bad_code = EncryptionStatus::BadCode(BroadcastCode::new([ 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x09, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, - ]); + ])); assert_eq!(bad_code.encoded_len(), 17); let mut buf = vec![0; bad_code.encoded_len()]; let _ = bad_code.encode(&mut buf[..]).expect("should not fail"); @@ -1078,10 +1078,10 @@ let _ = not_encrypted.encode(&mut buf[..]).expect_err("should fail"); // Not enough buffer space for encoding. - let bad_code = EncryptionStatus::BadCode([ + let bad_code = EncryptionStatus::BadCode(BroadcastCode::new([ 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x09, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, - ]); + ])); let mut buf = vec![0; 1]; let _ = bad_code.encode(&mut buf[..]).expect_err("should fail"); @@ -1375,10 +1375,10 @@ source_adv_sid: AdvertisingSetId::try_from(0x01).unwrap(), broadcast_id: BroadcastId::try_from(0x00010203).unwrap(), pa_sync_state: PaSyncState::Synced, - big_encryption: EncryptionStatus::BadCode([ - 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x09, 0x08, 0x7, 0x06, 0x05, 0x04, 0x03, + big_encryption: EncryptionStatus::BadCode(BroadcastCode::new([ + 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x09, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, - ]), + ])), subgroups: vec![], }); assert_eq!(state.encoded_len(), 31);
diff --git a/rust/bt-broadcast-assistant/src/assistant/peer.rs b/rust/bt-broadcast-assistant/src/assistant/peer.rs index 2527fb6..8c5860d 100644 --- a/rust/bt-broadcast-assistant/src/assistant/peer.rs +++ b/rust/bt-broadcast-assistant/src/assistant/peer.rs
@@ -8,7 +8,7 @@ use std::sync::Arc; use thiserror::Error; -use bt_bap::types::BroadcastId; +use bt_bap::types::{BroadcastCode, BroadcastId}; use bt_bass::client::error::Error as BassClientError; use bt_bass::client::event::Event as BassEvent; use bt_bass::client::BroadcastAudioScanServiceClient; @@ -84,7 +84,7 @@ pub async fn send_broadcast_code( &self, broadcast_id: BroadcastId, - broadcast_code: [u8; 16], + broadcast_code: BroadcastCode, ) -> Result<(), Error> { self.bass.set_broadcast_code(broadcast_id, broadcast_code).await.map_err(Into::into) }
diff --git a/rust/bt-broadcast-assistant/src/debug.rs b/rust/bt-broadcast-assistant/src/debug.rs index b369c4e..b9d933c 100644 --- a/rust/bt-broadcast-assistant/src/debug.rs +++ b/rust/bt-broadcast-assistant/src/debug.rs
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -use bt_bap::types::BroadcastId; +use bt_bap::types::{BroadcastCode, BroadcastId}; use bt_bass::client::error::Error as BassClientError; use bt_bass::client::event::Event as BassEvent; use bt_bass::types::{BisSync, PaSync, SubgroupIndex}; @@ -192,7 +192,7 @@ /// The string is UTF-8 encoded and then padded with zeros on the right to a /// total length of 16 bytes. This result is a little-endian byte array /// equivalent to a 128-bit value. -fn passcode_to_broadcast_code(passcode: &str) -> Result<[u8; 16], String> { +fn passcode_to_broadcast_code(passcode: &str) -> Result<BroadcastCode, String> { if passcode.is_empty() { return Err("invalid broadcast code: passcode cannot be empty".to_string()); } @@ -206,7 +206,7 @@ } let mut broadcast_code = [0u8; 16]; broadcast_code[..code.len()].copy_from_slice(code); - Ok(broadcast_code) + Ok(BroadcastCode::new(broadcast_code)) } impl<T: bt_gatt::GattTypes + 'static, R: GetPeerAddr> CommandRunner for AssistantDebug<T, R> @@ -607,20 +607,20 @@ // UTF-8 string that is less than 16 bytes. // Source of truth test case from Bluetooth Spec. let code = "Børne House"; - let expected = [ + let expected = BroadcastCode::new([ 0x42, 0xc3, 0xb8, 0x72, 0x6e, 0x65, 0x20, 0x48, 0x6f, 0x75, 0x73, 0x65, 0x00, 0x00, 0x00, 0x00, - ]; + ]); let actual = passcode_to_broadcast_code(code).expect("should succeed"); assert_eq!(actual, expected); - assert_eq!(u128::from_le_bytes(actual), 0x00000000_6573756F_4820656E_72B8C342); + assert_eq!(u128::from_le_bytes(*actual.bytes()), 0x00000000_6573756F_4820656E_72B8C342); // Valid ASCII passcode, exactly 16 bytes. let code = "1234567890123456"; - let expected = [ + let expected = BroadcastCode::new([ 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, - ]; + ]); assert_eq!(passcode_to_broadcast_code(code).unwrap(), expected); // Invalid passcode, over 16 bytes.