• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //! BLE Advertising types and utilities
2 
3 use btif_macros::{btif_callback, btif_callbacks_dispatcher, log_cb_args};
4 
5 use bt_topshim::btif::{DisplayAddress, RawAddress, Uuid};
6 use bt_topshim::profiles::gatt::{AdvertisingStatus, Gatt, GattAdvCallbacks, LeDiscMode, LePhy};
7 
8 use itertools::Itertools;
9 use log::{debug, error, info, warn};
10 use num_traits::clamp;
11 use std::collections::{HashMap, VecDeque};
12 use std::sync::{Arc, Mutex};
13 use std::time::{Duration, Instant};
14 use tokio::sync::mpsc::Sender;
15 use tokio::task::JoinHandle;
16 use tokio::time;
17 
18 use crate::bluetooth::{Bluetooth, IBluetooth};
19 use crate::callbacks::Callbacks;
20 use crate::{Message, RPCProxy, SuspendMode};
21 
22 pub type AdvertiserId = i32;
23 pub type CallbackId = u32;
24 pub type RegId = i32;
25 pub type ManfId = u16;
26 
27 /// Advertising parameters for each BLE advertising set.
28 #[derive(Debug, Default, Clone)]
29 pub struct AdvertisingSetParameters {
30     /// Discoverable modes.
31     pub discoverable: LeDiscMode,
32     /// Whether the advertisement will be connectable.
33     pub connectable: bool,
34     /// Whether the advertisement will be scannable.
35     pub scannable: bool,
36     /// Whether the legacy advertisement will be used.
37     pub is_legacy: bool,
38     /// Whether the advertisement will be anonymous.
39     pub is_anonymous: bool,
40     /// Whether the TX Power will be included.
41     pub include_tx_power: bool,
42     /// Primary advertising phy. Valid values are: 1 (1M), 2 (2M), 3 (Coded).
43     pub primary_phy: LePhy,
44     /// Secondary advertising phy. Valid values are: 1 (1M), 2 (2M), 3 (Coded).
45     pub secondary_phy: LePhy,
46     /// The advertising interval. Bluetooth LE Advertising interval, in 0.625 ms unit.
47     /// The valid range is from 160 (100 ms) to 16777215 (10485.759375 sec).
48     /// Recommended values are: 160 (100 ms), 400 (250 ms), 1600 (1 sec).
49     pub interval: i32,
50     /// Transmission power of Bluetooth LE Advertising, in dBm. The valid range is [-127, 1].
51     /// Recommended values are: -21, -15, 7, 1.
52     pub tx_power_level: i32,
53     /// Own address type for advertising to control public or privacy mode.
54     /// The valid types are: -1 (default), 0 (public), 1 (random).
55     pub own_address_type: i32,
56 }
57 
58 /// Represents the data to be advertised and the scan response data for active scans.
59 #[derive(Debug, Default, Clone)]
60 pub struct AdvertiseData {
61     /// A list of service UUIDs within the advertisement that are used to identify
62     /// the Bluetooth GATT services.
63     pub service_uuids: Vec<Uuid>,
64     /// A list of service solicitation UUIDs within the advertisement that we invite to connect.
65     pub solicit_uuids: Vec<Uuid>,
66     /// A list of transport discovery data.
67     pub transport_discovery_data: Vec<Vec<u8>>,
68     /// A collection of manufacturer Id and the corresponding manufacturer specific data.
69     pub manufacturer_data: HashMap<ManfId, Vec<u8>>,
70     /// A map of 128-bit UUID and its corresponding service data.
71     pub service_data: HashMap<String, Vec<u8>>,
72     /// Whether TX Power level will be included in the advertising packet.
73     pub include_tx_power_level: bool,
74     /// Whether the device name will be included in the advertisement packet.
75     pub include_device_name: bool,
76 }
77 
78 /// Parameters of the periodic advertising packet for BLE advertising set.
79 #[derive(Debug, Default)]
80 pub struct PeriodicAdvertisingParameters {
81     /// Whether TX Power level will be included.
82     pub include_tx_power: bool,
83     /// Periodic advertising interval in 1.25 ms unit. Valid values are from 80 (100 ms) to
84     /// 65519 (81.89875 sec). Value from range [interval, interval+20ms] will be picked as
85     /// the actual value.
86     pub interval: i32,
87 }
88 
89 /// Interface for advertiser callbacks to clients, passed to
90 /// `IBluetoothGatt::start_advertising_set`.
91 pub trait IAdvertisingSetCallback: RPCProxy {
92     /// Callback triggered in response to `start_advertising_set` indicating result of
93     /// the operation.
94     ///
95     /// * `reg_id` - Identifies the advertising set registered by `start_advertising_set`.
96     /// * `advertiser_id` - ID for the advertising set. It will be used in other advertising methods
97     ///     and callbacks.
98     /// * `tx_power` - Transmit power that will be used for this advertising set.
99     /// * `status` - Status of this operation.
on_advertising_set_started( &mut self, reg_id: i32, advertiser_id: i32, tx_power: i32, status: AdvertisingStatus, )100     fn on_advertising_set_started(
101         &mut self,
102         reg_id: i32,
103         advertiser_id: i32,
104         tx_power: i32,
105         status: AdvertisingStatus,
106     );
107 
108     /// Callback triggered in response to `get_own_address` indicating result of the operation.
on_own_address_read(&mut self, advertiser_id: i32, address_type: i32, address: RawAddress)109     fn on_own_address_read(&mut self, advertiser_id: i32, address_type: i32, address: RawAddress);
110 
111     /// Callback triggered in response to `stop_advertising_set` indicating the advertising set
112     /// is stopped.
on_advertising_set_stopped(&mut self, advertiser_id: i32)113     fn on_advertising_set_stopped(&mut self, advertiser_id: i32);
114 
115     /// Callback triggered in response to `enable_advertising_set` indicating result of
116     /// the operation.
on_advertising_enabled( &mut self, advertiser_id: i32, enable: bool, status: AdvertisingStatus, )117     fn on_advertising_enabled(
118         &mut self,
119         advertiser_id: i32,
120         enable: bool,
121         status: AdvertisingStatus,
122     );
123 
124     /// Callback triggered in response to `set_advertising_data` indicating result of the operation.
on_advertising_data_set(&mut self, advertiser_id: i32, status: AdvertisingStatus)125     fn on_advertising_data_set(&mut self, advertiser_id: i32, status: AdvertisingStatus);
126 
127     /// Callback triggered in response to `set_scan_response_data` indicating result of
128     /// the operation.
on_scan_response_data_set(&mut self, advertiser_id: i32, status: AdvertisingStatus)129     fn on_scan_response_data_set(&mut self, advertiser_id: i32, status: AdvertisingStatus);
130 
131     /// Callback triggered in response to `set_advertising_parameters` indicating result of
132     /// the operation.
on_advertising_parameters_updated( &mut self, advertiser_id: i32, tx_power: i32, status: AdvertisingStatus, )133     fn on_advertising_parameters_updated(
134         &mut self,
135         advertiser_id: i32,
136         tx_power: i32,
137         status: AdvertisingStatus,
138     );
139 
140     /// Callback triggered in response to `set_periodic_advertising_parameters` indicating result of
141     /// the operation.
on_periodic_advertising_parameters_updated( &mut self, advertiser_id: i32, status: AdvertisingStatus, )142     fn on_periodic_advertising_parameters_updated(
143         &mut self,
144         advertiser_id: i32,
145         status: AdvertisingStatus,
146     );
147 
148     /// Callback triggered in response to `set_periodic_advertising_data` indicating result of
149     /// the operation.
on_periodic_advertising_data_set(&mut self, advertiser_id: i32, status: AdvertisingStatus)150     fn on_periodic_advertising_data_set(&mut self, advertiser_id: i32, status: AdvertisingStatus);
151 
152     /// Callback triggered in response to `set_periodic_advertising_enable` indicating result of
153     /// the operation.
on_periodic_advertising_enabled( &mut self, advertiser_id: i32, enable: bool, status: AdvertisingStatus, )154     fn on_periodic_advertising_enabled(
155         &mut self,
156         advertiser_id: i32,
157         enable: bool,
158         status: AdvertisingStatus,
159     );
160 
161     /// When advertising module changes its suspend mode due to system suspend/resume.
on_suspend_mode_change(&mut self, suspend_mode: SuspendMode)162     fn on_suspend_mode_change(&mut self, suspend_mode: SuspendMode);
163 }
164 
165 // Advertising interval range.
166 const INTERVAL_MAX: i32 = 0xff_ffff; // 10485.759375 sec
167 const INTERVAL_MIN: i32 = 160; // 100 ms
168 const INTERVAL_DELTA: i32 = 50; // 31.25 ms gap between min and max
169 
170 // Periodic advertising interval range.
171 const PERIODIC_INTERVAL_MAX: i32 = 65519; // 81.89875 sec
172 const PERIODIC_INTERVAL_MIN: i32 = 80; // 100 ms
173 const PERIODIC_INTERVAL_DELTA: i32 = 16; // 20 ms gap between min and max
174 
175 // Device name length.
176 const DEVICE_NAME_MAX: usize = 26;
177 
178 // Advertising data types.
179 const COMPLETE_LIST_16_BIT_SERVICE_UUIDS: u8 = 0x03;
180 const COMPLETE_LIST_32_BIT_SERVICE_UUIDS: u8 = 0x05;
181 const COMPLETE_LIST_128_BIT_SERVICE_UUIDS: u8 = 0x07;
182 const SHORTENED_LOCAL_NAME: u8 = 0x08;
183 const COMPLETE_LOCAL_NAME: u8 = 0x09;
184 const TX_POWER_LEVEL: u8 = 0x0a;
185 const LIST_16_BIT_SERVICE_SOLICITATION_UUIDS: u8 = 0x14;
186 const LIST_128_BIT_SERVICE_SOLICITATION_UUIDS: u8 = 0x15;
187 const SERVICE_DATA_16_BIT_UUID: u8 = 0x16;
188 const LIST_32_BIT_SERVICE_SOLICITATION_UUIDS: u8 = 0x1f;
189 const SERVICE_DATA_32_BIT_UUID: u8 = 0x20;
190 const SERVICE_DATA_128_BIT_UUID: u8 = 0x21;
191 const TRANSPORT_DISCOVERY_DATA: u8 = 0x26;
192 const MANUFACTURER_SPECIFIC_DATA: u8 = 0xff;
193 const SERVICE_AD_TYPES: [u8; 3] = [
194     COMPLETE_LIST_16_BIT_SERVICE_UUIDS,
195     COMPLETE_LIST_32_BIT_SERVICE_UUIDS,
196     COMPLETE_LIST_128_BIT_SERVICE_UUIDS,
197 ];
198 const SOLICIT_AD_TYPES: [u8; 3] = [
199     LIST_16_BIT_SERVICE_SOLICITATION_UUIDS,
200     LIST_32_BIT_SERVICE_SOLICITATION_UUIDS,
201     LIST_128_BIT_SERVICE_SOLICITATION_UUIDS,
202 ];
203 
204 const LEGACY_ADV_DATA_LEN_MAX: usize = 31;
205 const EXT_ADV_DATA_LEN_MAX: usize = 254;
206 
207 // Invalid advertising set id.
208 const INVALID_ADV_ID: i32 = 0xff;
209 
210 // Invalid advertising set id.
211 pub const INVALID_REG_ID: i32 = -1;
212 
213 impl From<AdvertisingSetParameters> for bt_topshim::profiles::gatt::AdvertiseParameters {
from(val: AdvertisingSetParameters) -> Self214     fn from(val: AdvertisingSetParameters) -> Self {
215         let mut props: u16 = 0;
216         let mut is_discoverable = false;
217         let mut address = RawAddress::default();
218         if val.connectable {
219             props |= 0x01;
220         }
221         if val.scannable {
222             props |= 0x02;
223         }
224         if val.is_legacy {
225             props |= 0x10;
226         }
227         if val.is_anonymous {
228             props |= 0x20;
229         }
230         if val.include_tx_power {
231             props |= 0x40;
232         }
233 
234         match val.discoverable {
235             LeDiscMode::GeneralDiscoverable => is_discoverable = true,
236             _ => {}
237         }
238 
239         let interval = clamp(val.interval, INTERVAL_MIN, INTERVAL_MAX - INTERVAL_DELTA);
240 
241         bt_topshim::profiles::gatt::AdvertiseParameters {
242             advertising_event_properties: props,
243             min_interval: interval as u32,
244             max_interval: (interval + INTERVAL_DELTA) as u32,
245             channel_map: 0x07_u8, // all channels
246             tx_power: val.tx_power_level as i8,
247             primary_advertising_phy: val.primary_phy.into(),
248             secondary_advertising_phy: val.secondary_phy.into(),
249             scan_request_notification_enable: 0_u8, // false
250             own_address_type: val.own_address_type as i8,
251             peer_address: address,
252             peer_address_type: 0x00 as i8,
253             discoverable: is_discoverable,
254         }
255     }
256 }
257 
258 impl AdvertiseData {
append_adv_data(dest: &mut Vec<u8>, ad_type: u8, ad_payload: &[u8])259     fn append_adv_data(dest: &mut Vec<u8>, ad_type: u8, ad_payload: &[u8]) {
260         let len = clamp(ad_payload.len(), 0, 254);
261         dest.push((len + 1) as u8);
262         dest.push(ad_type);
263         dest.extend(&ad_payload[..len]);
264     }
265 
append_uuids(dest: &mut Vec<u8>, ad_types: &[u8; 3], uuids: &Vec<Uuid>)266     fn append_uuids(dest: &mut Vec<u8>, ad_types: &[u8; 3], uuids: &Vec<Uuid>) {
267         let mut uuid16_bytes = Vec::<u8>::new();
268         let mut uuid32_bytes = Vec::<u8>::new();
269         let mut uuid128_bytes = Vec::<u8>::new();
270 
271         // For better transmission efficiency, we generate a compact
272         // advertisement data by converting UUIDs into shorter binary forms
273         // and then group them by their length in order.
274         // The data generated for UUIDs looks like:
275         // [16-bit_UUID_LIST, 32-bit_UUID_LIST, 128-bit_UUID_LIST].
276         for uuid in uuids {
277             let uuid_slice = uuid.get_shortest_slice();
278             let id: Vec<u8> = uuid_slice.iter().rev().cloned().collect();
279             match id.len() {
280                 2 => uuid16_bytes.extend(id),
281                 4 => uuid32_bytes.extend(id),
282                 16 => uuid128_bytes.extend(id),
283                 _ => (),
284             }
285         }
286 
287         let bytes_list = [uuid16_bytes, uuid32_bytes, uuid128_bytes];
288         for (ad_type, bytes) in
289             ad_types.iter().zip(bytes_list.iter()).filter(|(_, bytes)| !bytes.is_empty())
290         {
291             AdvertiseData::append_adv_data(dest, *ad_type, bytes);
292         }
293     }
294 
append_service_uuids(dest: &mut Vec<u8>, uuids: &Vec<Uuid>)295     fn append_service_uuids(dest: &mut Vec<u8>, uuids: &Vec<Uuid>) {
296         AdvertiseData::append_uuids(dest, &SERVICE_AD_TYPES, uuids);
297     }
298 
append_solicit_uuids(dest: &mut Vec<u8>, uuids: &Vec<Uuid>)299     fn append_solicit_uuids(dest: &mut Vec<u8>, uuids: &Vec<Uuid>) {
300         AdvertiseData::append_uuids(dest, &SOLICIT_AD_TYPES, uuids);
301     }
302 
append_service_data(dest: &mut Vec<u8>, service_data: &HashMap<String, Vec<u8>>)303     fn append_service_data(dest: &mut Vec<u8>, service_data: &HashMap<String, Vec<u8>>) {
304         for (uuid, data) in
305             service_data.iter().filter_map(|(s, d)| Uuid::from_string(s).map(|s| (s, d)))
306         {
307             let uuid_slice = uuid.get_shortest_slice();
308             let concated: Vec<u8> = uuid_slice.iter().rev().chain(data).cloned().collect();
309             match uuid_slice.len() {
310                 2 => AdvertiseData::append_adv_data(dest, SERVICE_DATA_16_BIT_UUID, &concated),
311                 4 => AdvertiseData::append_adv_data(dest, SERVICE_DATA_32_BIT_UUID, &concated),
312                 16 => AdvertiseData::append_adv_data(dest, SERVICE_DATA_128_BIT_UUID, &concated),
313                 _ => (),
314             }
315         }
316     }
317 
append_device_name(dest: &mut Vec<u8>, device_name: &String)318     fn append_device_name(dest: &mut Vec<u8>, device_name: &String) {
319         if device_name.is_empty() {
320             return;
321         }
322 
323         let (ad_type, name) = if device_name.len() > DEVICE_NAME_MAX {
324             (SHORTENED_LOCAL_NAME, [&device_name.as_bytes()[..DEVICE_NAME_MAX], &[0]].concat())
325         } else {
326             (COMPLETE_LOCAL_NAME, [device_name.as_bytes(), &[0]].concat())
327         };
328         AdvertiseData::append_adv_data(dest, ad_type, &name);
329     }
330 
append_manufacturer_data(dest: &mut Vec<u8>, manufacturer_data: &HashMap<ManfId, Vec<u8>>)331     fn append_manufacturer_data(dest: &mut Vec<u8>, manufacturer_data: &HashMap<ManfId, Vec<u8>>) {
332         for (m, data) in manufacturer_data.iter().sorted() {
333             let concated = [&m.to_le_bytes()[..], data].concat();
334             AdvertiseData::append_adv_data(dest, MANUFACTURER_SPECIFIC_DATA, &concated);
335         }
336     }
337 
append_transport_discovery_data( dest: &mut Vec<u8>, transport_discovery_data: &Vec<Vec<u8>>, )338     fn append_transport_discovery_data(
339         dest: &mut Vec<u8>,
340         transport_discovery_data: &Vec<Vec<u8>>,
341     ) {
342         for tdd in transport_discovery_data.iter().filter(|tdd| !tdd.is_empty()) {
343             AdvertiseData::append_adv_data(dest, TRANSPORT_DISCOVERY_DATA, tdd);
344         }
345     }
346 
347     /// Creates raw data from the AdvertiseData.
make_with(&self, device_name: &String) -> Vec<u8>348     pub fn make_with(&self, device_name: &String) -> Vec<u8> {
349         let mut bytes = Vec::<u8>::new();
350         if self.include_device_name {
351             AdvertiseData::append_device_name(&mut bytes, device_name);
352         }
353         if self.include_tx_power_level {
354             // Lower layers will fill tx power level.
355             AdvertiseData::append_adv_data(&mut bytes, TX_POWER_LEVEL, &[0]);
356         }
357         AdvertiseData::append_manufacturer_data(&mut bytes, &self.manufacturer_data);
358         AdvertiseData::append_service_uuids(&mut bytes, &self.service_uuids);
359         AdvertiseData::append_service_data(&mut bytes, &self.service_data);
360         AdvertiseData::append_solicit_uuids(&mut bytes, &self.solicit_uuids);
361         AdvertiseData::append_transport_discovery_data(&mut bytes, &self.transport_discovery_data);
362         bytes
363     }
364 
365     /// Validates the raw data as advertisement data.
validate_raw_data(is_legacy: bool, bytes: &Vec<u8>) -> bool366     pub fn validate_raw_data(is_legacy: bool, bytes: &Vec<u8>) -> bool {
367         bytes.len() <= if is_legacy { LEGACY_ADV_DATA_LEN_MAX } else { EXT_ADV_DATA_LEN_MAX }
368     }
369 
370     /// Checks if the advertisement can be upgraded to extended.
can_upgrade(parameters: &mut AdvertisingSetParameters, adv_bytes: &Vec<u8>) -> bool371     pub fn can_upgrade(parameters: &mut AdvertisingSetParameters, adv_bytes: &Vec<u8>) -> bool {
372         if parameters.is_legacy && !AdvertiseData::validate_raw_data(true, adv_bytes) {
373             info!("Auto upgrading advertisement to extended");
374             parameters.is_legacy = false;
375             return true;
376         }
377 
378         false
379     }
380 }
381 
382 impl From<PeriodicAdvertisingParameters>
383     for bt_topshim::profiles::gatt::PeriodicAdvertisingParameters
384 {
from(val: PeriodicAdvertisingParameters) -> Self385     fn from(val: PeriodicAdvertisingParameters) -> Self {
386         let mut p = bt_topshim::profiles::gatt::PeriodicAdvertisingParameters::default();
387 
388         let interval = clamp(
389             val.interval,
390             PERIODIC_INTERVAL_MIN,
391             PERIODIC_INTERVAL_MAX - PERIODIC_INTERVAL_DELTA,
392         );
393 
394         p.enable = true;
395         p.include_adi = false;
396         p.min_interval = interval as u16;
397         p.max_interval = p.min_interval + (PERIODIC_INTERVAL_DELTA as u16);
398         if val.include_tx_power {
399             p.periodic_advertising_properties |= 0x40;
400         }
401 
402         p
403     }
404 }
405 
406 // Keeps information of an advertising set.
407 #[derive(Debug, PartialEq, Copy, Clone)]
408 struct AdvertisingSetInfo {
409     /// Identifies the advertising set when it's started successfully.
410     adv_id: Option<AdvertiserId>,
411 
412     /// Identifies callback associated.
413     callback_id: CallbackId,
414 
415     /// Identifies the advertising set when it's registered.
416     reg_id: RegId,
417 
418     /// Whether the advertising set has been enabled.
419     enabled: bool,
420 
421     /// Whether the advertising set has been paused.
422     paused: bool,
423 
424     /// Whether the stop of advertising set is held.
425     /// This flag is set when an advertising set is stopped while we're not able to do it, such as:
426     /// - The system is suspending / suspended
427     /// - The advertising set is not yet valid (started)
428     ///
429     /// The advertising set will be stopped on system resumed / advertising set becomes ready.
430     stopped: bool,
431 
432     /// Advertising duration, in 10 ms unit.
433     adv_timeout: u16,
434 
435     /// Maximum number of extended advertising events the controller
436     /// shall attempt to send before terminating the extended advertising.
437     adv_events: u8,
438 
439     /// Whether the legacy advertisement will be used.
440     legacy: bool,
441 }
442 
443 impl AdvertisingSetInfo {
new( callback_id: CallbackId, adv_timeout: u16, adv_events: u8, legacy: bool, reg_id: RegId, ) -> Self444     fn new(
445         callback_id: CallbackId,
446         adv_timeout: u16,
447         adv_events: u8,
448         legacy: bool,
449         reg_id: RegId,
450     ) -> Self {
451         AdvertisingSetInfo {
452             adv_id: None,
453             callback_id,
454             reg_id,
455             enabled: false,
456             paused: false,
457             stopped: false,
458             adv_timeout,
459             adv_events,
460             legacy,
461         }
462     }
463 
464     /// Gets advertising set registration ID.
reg_id(&self) -> RegId465     fn reg_id(&self) -> RegId {
466         self.reg_id
467     }
468 
469     /// Gets associated callback ID.
callback_id(&self) -> CallbackId470     fn callback_id(&self) -> CallbackId {
471         self.callback_id
472     }
473 
474     /// Updates advertiser ID.
set_adv_id(&mut self, id: Option<AdvertiserId>)475     fn set_adv_id(&mut self, id: Option<AdvertiserId>) {
476         self.adv_id = id;
477     }
478 
479     /// Gets advertiser ID, which is required for advertising |BleAdvertiserInterface|.
adv_id(&self) -> u8480     fn adv_id(&self) -> u8 {
481         // As advertiser ID was from topshim originally, type casting is safe.
482         self.adv_id.unwrap_or(INVALID_ADV_ID) as u8
483     }
484 
485     /// Updates advertising set status.
set_enabled(&mut self, enabled: bool)486     fn set_enabled(&mut self, enabled: bool) {
487         self.enabled = enabled;
488     }
489 
490     /// Returns true if the advertising set has been enabled, false otherwise.
is_enabled(&self) -> bool491     fn is_enabled(&self) -> bool {
492         self.enabled
493     }
494 
495     /// Marks the advertising set as paused or not.
set_paused(&mut self, paused: bool)496     fn set_paused(&mut self, paused: bool) {
497         self.paused = paused;
498     }
499 
500     /// Returns true if the advertising set has been paused, false otherwise.
is_paused(&self) -> bool501     fn is_paused(&self) -> bool {
502         self.paused
503     }
504 
505     /// Marks the advertising set as stopped.
set_stopped(&mut self)506     fn set_stopped(&mut self) {
507         self.stopped = true;
508     }
509 
510     /// Returns true if the advertising set has been stopped, false otherwise.
is_stopped(&self) -> bool511     fn is_stopped(&self) -> bool {
512         self.stopped
513     }
514 
515     /// Gets adv_timeout.
adv_timeout(&self) -> u16516     fn adv_timeout(&self) -> u16 {
517         self.adv_timeout
518     }
519 
520     /// Gets adv_events.
adv_events(&self) -> u8521     fn adv_events(&self) -> u8 {
522         self.adv_events
523     }
524 
525     /// Returns whether the legacy advertisement will be used.
is_legacy(&self) -> bool526     fn is_legacy(&self) -> bool {
527         self.legacy
528     }
529 
530     /// Returns whether the advertising set is valid.
is_valid(&self) -> bool531     fn is_valid(&self) -> bool {
532         self.adv_id.is_some()
533     }
534 }
535 
536 // Manages advertising sets and the callbacks.
537 pub(crate) struct AdvertiseManager {
538     tx: Sender<Message>,
539     adv_manager_impl: Option<Box<dyn AdvertiseManagerOps + Send>>,
540 }
541 
542 impl AdvertiseManager {
new(tx: Sender<Message>) -> Self543     pub(crate) fn new(tx: Sender<Message>) -> Self {
544         AdvertiseManager { tx, adv_manager_impl: None }
545     }
546 
547     /// Initializes the AdvertiseManager
548     /// This needs to be called after Bluetooth is ready because we need to query LE features.
initialize( &mut self, gatt: Arc<Mutex<Gatt>>, adapter: Arc<Mutex<Box<Bluetooth>>>, )549     pub(crate) fn initialize(
550         &mut self,
551         gatt: Arc<Mutex<Gatt>>,
552         adapter: Arc<Mutex<Box<Bluetooth>>>,
553     ) {
554         let is_le_ext_adv_supported =
555             adapter.lock().unwrap().is_le_extended_advertising_supported();
556         self.adv_manager_impl = if is_le_ext_adv_supported {
557             info!("AdvertiseManager: Selected extended advertising stack");
558             Some(Box::new(AdvertiseManagerImpl::new(self.tx.clone(), gatt, adapter)))
559         } else {
560             info!("AdvertiseManager: Selected software rotation stack");
561             Some(Box::new(SoftwareRotationAdvertiseManagerImpl::new(
562                 self.tx.clone(),
563                 gatt,
564                 adapter,
565             )))
566         }
567     }
568 
get_impl(&mut self) -> &mut Box<dyn AdvertiseManagerOps + Send>569     pub fn get_impl(&mut self) -> &mut Box<dyn AdvertiseManagerOps + Send> {
570         self.adv_manager_impl.as_mut().unwrap()
571     }
572 }
573 
574 struct AdvertiseManagerImpl {
575     callbacks: Callbacks<dyn IAdvertisingSetCallback + Send>,
576     sets: HashMap<RegId, AdvertisingSetInfo>,
577     suspend_mode: SuspendMode,
578     gatt: Arc<Mutex<Gatt>>,
579     adapter: Arc<Mutex<Box<Bluetooth>>>,
580 }
581 
582 impl AdvertiseManagerImpl {
new( tx: Sender<Message>, gatt: Arc<Mutex<Gatt>>, adapter: Arc<Mutex<Box<Bluetooth>>>, ) -> Self583     fn new(
584         tx: Sender<Message>,
585         gatt: Arc<Mutex<Gatt>>,
586         adapter: Arc<Mutex<Box<Bluetooth>>>,
587     ) -> Self {
588         AdvertiseManagerImpl {
589             callbacks: Callbacks::new(tx, Message::AdvertiserCallbackDisconnected),
590             sets: HashMap::new(),
591             suspend_mode: SuspendMode::Normal,
592             gatt,
593             adapter,
594         }
595     }
596 
597     // Returns the minimum unoccupied register ID from 0.
new_reg_id(&mut self) -> RegId598     fn new_reg_id(&mut self) -> RegId {
599         (0..)
600             .find(|id| !self.sets.contains_key(id))
601             .expect("There must be an unoccupied register ID")
602     }
603 
604     /// Adds an advertising set.
add(&mut self, s: AdvertisingSetInfo)605     fn add(&mut self, s: AdvertisingSetInfo) {
606         if let Some(old) = self.sets.insert(s.reg_id(), s) {
607             warn!("An advertising set with the same reg_id ({}) exists. Drop it!", old.reg_id);
608         }
609     }
610 
611     /// Returns an iterator of valid advertising sets.
valid_sets(&self) -> impl Iterator<Item = &AdvertisingSetInfo>612     fn valid_sets(&self) -> impl Iterator<Item = &AdvertisingSetInfo> {
613         self.sets.iter().filter_map(|(_, s)| s.adv_id.map(|_| s))
614     }
615 
616     /// Returns an iterator of enabled advertising sets.
enabled_sets(&self) -> impl Iterator<Item = &AdvertisingSetInfo>617     fn enabled_sets(&self) -> impl Iterator<Item = &AdvertisingSetInfo> {
618         self.valid_sets().filter(|s| s.is_enabled())
619     }
620 
621     /// Returns an iterator of stopped advertising sets.
stopped_sets(&self) -> impl Iterator<Item = &AdvertisingSetInfo>622     fn stopped_sets(&self) -> impl Iterator<Item = &AdvertisingSetInfo> {
623         self.valid_sets().filter(|s| s.is_stopped())
624     }
625 
find_reg_id(&self, adv_id: AdvertiserId) -> Option<RegId>626     fn find_reg_id(&self, adv_id: AdvertiserId) -> Option<RegId> {
627         for (_, s) in &self.sets {
628             if s.adv_id == Some(adv_id) {
629                 return Some(s.reg_id());
630             }
631         }
632         None
633     }
634 
635     /// Returns a mutable reference to the advertising set with the reg_id specified.
get_mut_by_reg_id(&mut self, reg_id: RegId) -> Option<&mut AdvertisingSetInfo>636     fn get_mut_by_reg_id(&mut self, reg_id: RegId) -> Option<&mut AdvertisingSetInfo> {
637         self.sets.get_mut(&reg_id)
638     }
639 
640     /// Returns a shared reference to the advertising set with the reg_id specified.
get_by_reg_id(&self, reg_id: RegId) -> Option<&AdvertisingSetInfo>641     fn get_by_reg_id(&self, reg_id: RegId) -> Option<&AdvertisingSetInfo> {
642         self.sets.get(&reg_id)
643     }
644 
645     /// Returns a mutable reference to the advertising set with the advertiser ID specified.
get_mut_by_advertiser_id( &mut self, adv_id: AdvertiserId, ) -> Option<&mut AdvertisingSetInfo>646     fn get_mut_by_advertiser_id(
647         &mut self,
648         adv_id: AdvertiserId,
649     ) -> Option<&mut AdvertisingSetInfo> {
650         if let Some(reg_id) = self.find_reg_id(adv_id) {
651             return self.get_mut_by_reg_id(reg_id);
652         }
653         None
654     }
655 
656     /// Returns a shared reference to the advertising set with the advertiser ID specified.
get_by_advertiser_id(&self, adv_id: AdvertiserId) -> Option<&AdvertisingSetInfo>657     fn get_by_advertiser_id(&self, adv_id: AdvertiserId) -> Option<&AdvertisingSetInfo> {
658         if let Some(reg_id) = self.find_reg_id(adv_id) {
659             return self.get_by_reg_id(reg_id);
660         }
661         None
662     }
663 
664     /// Removes the advertising set with the reg_id specified.
665     ///
666     /// Returns the advertising set if found, None otherwise.
remove_by_reg_id(&mut self, reg_id: RegId) -> Option<AdvertisingSetInfo>667     fn remove_by_reg_id(&mut self, reg_id: RegId) -> Option<AdvertisingSetInfo> {
668         self.sets.remove(&reg_id)
669     }
670 
671     /// Removes the advertising set with the specified advertiser ID.
672     ///
673     /// Returns the advertising set if found, None otherwise.
remove_by_advertiser_id(&mut self, adv_id: AdvertiserId) -> Option<AdvertisingSetInfo>674     fn remove_by_advertiser_id(&mut self, adv_id: AdvertiserId) -> Option<AdvertisingSetInfo> {
675         if let Some(reg_id) = self.find_reg_id(adv_id) {
676             return self.remove_by_reg_id(reg_id);
677         }
678         None
679     }
680 
681     /// Returns callback of the advertising set.
get_callback( &mut self, s: &AdvertisingSetInfo, ) -> Option<&mut Box<dyn IAdvertisingSetCallback + Send>>682     fn get_callback(
683         &mut self,
684         s: &AdvertisingSetInfo,
685     ) -> Option<&mut Box<dyn IAdvertisingSetCallback + Send>> {
686         self.callbacks.get_by_id_mut(s.callback_id())
687     }
688 
689     /// Update suspend mode.
set_suspend_mode(&mut self, suspend_mode: SuspendMode)690     fn set_suspend_mode(&mut self, suspend_mode: SuspendMode) {
691         if suspend_mode != self.suspend_mode {
692             self.suspend_mode = suspend_mode;
693             self.notify_suspend_mode();
694         }
695     }
696 
697     /// Gets current suspend mode.
suspend_mode(&mut self) -> SuspendMode698     fn suspend_mode(&mut self) -> SuspendMode {
699         self.suspend_mode.clone()
700     }
701 
702     /// Notify current suspend mode to all active callbacks.
notify_suspend_mode(&mut self)703     fn notify_suspend_mode(&mut self) {
704         let suspend_mode = &self.suspend_mode;
705         self.callbacks.for_all_callbacks(|callback| {
706             callback.on_suspend_mode_change(suspend_mode.clone());
707         });
708     }
709 
get_adapter_name(&self) -> String710     fn get_adapter_name(&self) -> String {
711         self.adapter.lock().unwrap().get_name()
712     }
713 }
714 
715 pub enum AdvertiserActions {
716     /// Triggers the rotation of the advertising set.
717     /// Should only be used in the software rotation stack.
718     RunRotate,
719 }
720 
721 /// Defines all required ops for an AdvertiseManager to communicate with the upper/lower layers.
722 pub(crate) trait AdvertiseManagerOps:
723     IBluetoothAdvertiseManager + BtifGattAdvCallbacks
724 {
725     /// Prepares for suspend
enter_suspend(&mut self)726     fn enter_suspend(&mut self);
727 
728     /// Undoes previous suspend preparation
exit_suspend(&mut self)729     fn exit_suspend(&mut self);
730 
731     /// Handles advertise manager actions
handle_action(&mut self, action: AdvertiserActions)732     fn handle_action(&mut self, action: AdvertiserActions);
733 }
734 
735 impl AdvertiseManagerOps for AdvertiseManagerImpl {
enter_suspend(&mut self)736     fn enter_suspend(&mut self) {
737         if self.suspend_mode() != SuspendMode::Normal {
738             return;
739         }
740         self.set_suspend_mode(SuspendMode::Suspending);
741 
742         let mut pausing_cnt = 0;
743         for s in self.sets.values_mut().filter(|s| s.is_valid() && s.is_enabled()) {
744             s.set_paused(true);
745             self.gatt.lock().unwrap().advertiser.enable(
746                 s.adv_id(),
747                 false,
748                 s.adv_timeout(),
749                 s.adv_events(),
750             );
751             pausing_cnt += 1;
752         }
753 
754         if pausing_cnt == 0 {
755             self.set_suspend_mode(SuspendMode::Suspended);
756         }
757     }
758 
exit_suspend(&mut self)759     fn exit_suspend(&mut self) {
760         if self.suspend_mode() != SuspendMode::Suspended {
761             return;
762         }
763         for id in self.stopped_sets().map(|s| s.adv_id()).collect::<Vec<_>>() {
764             self.gatt.lock().unwrap().advertiser.unregister(id);
765             self.remove_by_advertiser_id(id as AdvertiserId);
766         }
767         for s in self.sets.values_mut().filter(|s| s.is_valid() && s.is_paused()) {
768             s.set_paused(false);
769             self.gatt.lock().unwrap().advertiser.enable(
770                 s.adv_id(),
771                 true,
772                 s.adv_timeout(),
773                 s.adv_events(),
774             );
775         }
776 
777         self.set_suspend_mode(SuspendMode::Normal);
778     }
779 
handle_action(&mut self, action: AdvertiserActions)780     fn handle_action(&mut self, action: AdvertiserActions) {
781         match action {
782             AdvertiserActions::RunRotate => {
783                 error!("Unexpected RunRotate call in hardware offloaded stack");
784             }
785         }
786     }
787 }
788 
789 pub trait IBluetoothAdvertiseManager {
790     /// Registers callback for BLE advertising.
register_callback(&mut self, callback: Box<dyn IAdvertisingSetCallback + Send>) -> u32791     fn register_callback(&mut self, callback: Box<dyn IAdvertisingSetCallback + Send>) -> u32;
792 
793     /// Unregisters callback for BLE advertising.
unregister_callback(&mut self, callback_id: u32) -> bool794     fn unregister_callback(&mut self, callback_id: u32) -> bool;
795 
796     /// Creates a new BLE advertising set and start advertising.
797     ///
798     /// Returns the reg_id for the advertising set, which is used in the callback
799     /// `on_advertising_set_started` to identify the advertising set started.
800     ///
801     /// * `parameters` - Advertising set parameters.
802     /// * `advertise_data` - Advertisement data to be broadcasted.
803     /// * `scan_response` - Scan response.
804     /// * `periodic_parameters` - Periodic advertising parameters. If None, periodic advertising
805     ///     will not be started.
806     /// * `periodic_data` - Periodic advertising data.
807     /// * `duration` - Advertising duration, in 10 ms unit. Valid range is from 1 (10 ms) to
808     ///     65535 (655.35 sec). 0 means no advertising timeout.
809     /// * `max_ext_adv_events` - Maximum number of extended advertising events the controller
810     ///     shall attempt to send before terminating the extended advertising, even if the
811     ///     duration has not expired. Valid range is from 1 to 255. 0 means event count limitation.
812     /// * `callback_id` - Identifies callback registered in register_advertiser_callback.
start_advertising_set( &mut self, parameters: AdvertisingSetParameters, advertise_data: AdvertiseData, scan_response: Option<AdvertiseData>, periodic_parameters: Option<PeriodicAdvertisingParameters>, periodic_data: Option<AdvertiseData>, duration: i32, max_ext_adv_events: i32, callback_id: u32, ) -> i32813     fn start_advertising_set(
814         &mut self,
815         parameters: AdvertisingSetParameters,
816         advertise_data: AdvertiseData,
817         scan_response: Option<AdvertiseData>,
818         periodic_parameters: Option<PeriodicAdvertisingParameters>,
819         periodic_data: Option<AdvertiseData>,
820         duration: i32,
821         max_ext_adv_events: i32,
822         callback_id: u32,
823     ) -> i32;
824 
825     /// Disposes a BLE advertising set.
stop_advertising_set(&mut self, advertiser_id: i32)826     fn stop_advertising_set(&mut self, advertiser_id: i32);
827 
828     /// Queries address associated with the advertising set.
get_own_address(&mut self, advertiser_id: i32)829     fn get_own_address(&mut self, advertiser_id: i32);
830 
831     /// Enables or disables an advertising set.
enable_advertising_set( &mut self, advertiser_id: i32, enable: bool, duration: i32, max_ext_adv_events: i32, )832     fn enable_advertising_set(
833         &mut self,
834         advertiser_id: i32,
835         enable: bool,
836         duration: i32,
837         max_ext_adv_events: i32,
838     );
839 
840     /// Updates advertisement data of the advertising set.
set_advertising_data(&mut self, advertiser_id: i32, data: AdvertiseData)841     fn set_advertising_data(&mut self, advertiser_id: i32, data: AdvertiseData);
842 
843     /// Set the advertisement data of the advertising set.
set_raw_adv_data(&mut self, advertiser_id: i32, data: Vec<u8>)844     fn set_raw_adv_data(&mut self, advertiser_id: i32, data: Vec<u8>);
845 
846     /// Updates scan response of the advertising set.
set_scan_response_data(&mut self, advertiser_id: i32, data: AdvertiseData)847     fn set_scan_response_data(&mut self, advertiser_id: i32, data: AdvertiseData);
848 
849     /// Updates advertising parameters of the advertising set.
850     ///
851     /// It must be called when advertising is not active.
set_advertising_parameters( &mut self, advertiser_id: i32, parameters: AdvertisingSetParameters, )852     fn set_advertising_parameters(
853         &mut self,
854         advertiser_id: i32,
855         parameters: AdvertisingSetParameters,
856     );
857 
858     /// Updates periodic advertising parameters.
set_periodic_advertising_parameters( &mut self, advertiser_id: i32, parameters: PeriodicAdvertisingParameters, )859     fn set_periodic_advertising_parameters(
860         &mut self,
861         advertiser_id: i32,
862         parameters: PeriodicAdvertisingParameters,
863     );
864 
865     /// Updates periodic advertisement data.
866     ///
867     /// It must be called after `set_periodic_advertising_parameters`, or after
868     /// advertising was started with periodic advertising data set.
set_periodic_advertising_data(&mut self, advertiser_id: i32, data: AdvertiseData)869     fn set_periodic_advertising_data(&mut self, advertiser_id: i32, data: AdvertiseData);
870 
871     /// Enables or disables periodic advertising.
set_periodic_advertising_enable( &mut self, advertiser_id: i32, enable: bool, include_adi: bool, )872     fn set_periodic_advertising_enable(
873         &mut self,
874         advertiser_id: i32,
875         enable: bool,
876         include_adi: bool,
877     );
878 }
879 
880 impl IBluetoothAdvertiseManager for AdvertiseManagerImpl {
register_callback(&mut self, callback: Box<dyn IAdvertisingSetCallback + Send>) -> u32881     fn register_callback(&mut self, callback: Box<dyn IAdvertisingSetCallback + Send>) -> u32 {
882         self.callbacks.add_callback(callback)
883     }
884 
unregister_callback(&mut self, callback_id: u32) -> bool885     fn unregister_callback(&mut self, callback_id: u32) -> bool {
886         for s in self.sets.values_mut().filter(|s| s.callback_id() == callback_id) {
887             if s.is_valid() {
888                 self.gatt.lock().unwrap().advertiser.unregister(s.adv_id());
889             } else {
890                 s.set_stopped();
891             }
892         }
893         self.sets.retain(|_, s| s.callback_id() != callback_id || !s.is_valid());
894 
895         self.callbacks.remove_callback(callback_id)
896     }
897 
start_advertising_set( &mut self, mut parameters: AdvertisingSetParameters, advertise_data: AdvertiseData, scan_response: Option<AdvertiseData>, periodic_parameters: Option<PeriodicAdvertisingParameters>, periodic_data: Option<AdvertiseData>, duration: i32, max_ext_adv_events: i32, callback_id: u32, ) -> i32898     fn start_advertising_set(
899         &mut self,
900         mut parameters: AdvertisingSetParameters,
901         advertise_data: AdvertiseData,
902         scan_response: Option<AdvertiseData>,
903         periodic_parameters: Option<PeriodicAdvertisingParameters>,
904         periodic_data: Option<AdvertiseData>,
905         duration: i32,
906         max_ext_adv_events: i32,
907         callback_id: u32,
908     ) -> i32 {
909         if self.suspend_mode() != SuspendMode::Normal {
910             return INVALID_REG_ID;
911         }
912 
913         let device_name = self.get_adapter_name();
914         let adv_bytes = advertise_data.make_with(&device_name);
915         // TODO(b/311417973): Remove this once we have more robust /device/bluetooth APIs to control extended advertising
916         let is_legacy =
917             parameters.is_legacy && !AdvertiseData::can_upgrade(&mut parameters, &adv_bytes);
918         let params = parameters.into();
919         if !AdvertiseData::validate_raw_data(is_legacy, &adv_bytes) {
920             warn!("Failed to start advertising set with invalid advertise data");
921             return INVALID_REG_ID;
922         }
923         let scan_bytes =
924             if let Some(d) = scan_response { d.make_with(&device_name) } else { Vec::<u8>::new() };
925         if !AdvertiseData::validate_raw_data(is_legacy, &scan_bytes) {
926             warn!("Failed to start advertising set with invalid scan response");
927             return INVALID_REG_ID;
928         }
929         let periodic_params = if let Some(p) = periodic_parameters {
930             p.into()
931         } else {
932             bt_topshim::profiles::gatt::PeriodicAdvertisingParameters::default()
933         };
934         let periodic_bytes =
935             if let Some(d) = periodic_data { d.make_with(&device_name) } else { Vec::<u8>::new() };
936         if !AdvertiseData::validate_raw_data(false, &periodic_bytes) {
937             warn!("Failed to start advertising set with invalid periodic data");
938             return INVALID_REG_ID;
939         }
940         let adv_timeout = clamp(duration, 0, 0xffff) as u16;
941         let adv_events = clamp(max_ext_adv_events, 0, 0xff) as u8;
942 
943         let reg_id = self.new_reg_id();
944         let s = AdvertisingSetInfo::new(callback_id, adv_timeout, adv_events, is_legacy, reg_id);
945         self.add(s);
946 
947         self.gatt.lock().unwrap().advertiser.start_advertising_set(
948             reg_id,
949             params,
950             adv_bytes,
951             scan_bytes,
952             periodic_params,
953             periodic_bytes,
954             adv_timeout,
955             adv_events,
956         );
957         reg_id
958     }
959 
stop_advertising_set(&mut self, advertiser_id: i32)960     fn stop_advertising_set(&mut self, advertiser_id: i32) {
961         let s = if let Some(s) = self.get_by_advertiser_id(advertiser_id) {
962             *s
963         } else {
964             return;
965         };
966 
967         if self.suspend_mode() != SuspendMode::Normal {
968             if !s.is_stopped() {
969                 info!("Deferred advertisement unregistering due to suspending");
970                 self.get_mut_by_advertiser_id(advertiser_id).unwrap().set_stopped();
971                 if let Some(cb) = self.get_callback(&s) {
972                     cb.on_advertising_set_stopped(advertiser_id);
973                 }
974             }
975             return;
976         }
977 
978         self.gatt.lock().unwrap().advertiser.unregister(s.adv_id());
979         if let Some(cb) = self.get_callback(&s) {
980             cb.on_advertising_set_stopped(advertiser_id);
981         }
982         self.remove_by_advertiser_id(advertiser_id);
983     }
984 
get_own_address(&mut self, advertiser_id: i32)985     fn get_own_address(&mut self, advertiser_id: i32) {
986         if self.suspend_mode() != SuspendMode::Normal {
987             return;
988         }
989 
990         if let Some(s) = self.get_by_advertiser_id(advertiser_id) {
991             self.gatt.lock().unwrap().advertiser.get_own_address(s.adv_id());
992         }
993     }
994 
enable_advertising_set( &mut self, advertiser_id: i32, enable: bool, duration: i32, max_ext_adv_events: i32, )995     fn enable_advertising_set(
996         &mut self,
997         advertiser_id: i32,
998         enable: bool,
999         duration: i32,
1000         max_ext_adv_events: i32,
1001     ) {
1002         if self.suspend_mode() != SuspendMode::Normal {
1003             return;
1004         }
1005 
1006         let adv_timeout = clamp(duration, 0, 0xffff) as u16;
1007         let adv_events = clamp(max_ext_adv_events, 0, 0xff) as u8;
1008 
1009         if let Some(s) = self.get_by_advertiser_id(advertiser_id) {
1010             self.gatt.lock().unwrap().advertiser.enable(
1011                 s.adv_id(),
1012                 enable,
1013                 adv_timeout,
1014                 adv_events,
1015             );
1016         }
1017     }
1018 
set_advertising_data(&mut self, advertiser_id: i32, data: AdvertiseData)1019     fn set_advertising_data(&mut self, advertiser_id: i32, data: AdvertiseData) {
1020         if self.suspend_mode() != SuspendMode::Normal {
1021             return;
1022         }
1023 
1024         let device_name = self.get_adapter_name();
1025         let bytes = data.make_with(&device_name);
1026 
1027         if let Some(s) = self.get_by_advertiser_id(advertiser_id) {
1028             if !AdvertiseData::validate_raw_data(s.is_legacy(), &bytes) {
1029                 warn!("AdvertiseManagerImpl {}: invalid advertise data to update", advertiser_id);
1030                 return;
1031             }
1032             self.gatt.lock().unwrap().advertiser.set_data(s.adv_id(), false, bytes);
1033         }
1034     }
1035 
set_raw_adv_data(&mut self, advertiser_id: i32, data: Vec<u8>)1036     fn set_raw_adv_data(&mut self, advertiser_id: i32, data: Vec<u8>) {
1037         if self.suspend_mode() != SuspendMode::Normal {
1038             return;
1039         }
1040 
1041         if let Some(s) = self.get_by_advertiser_id(advertiser_id) {
1042             if !AdvertiseData::validate_raw_data(s.is_legacy(), &data) {
1043                 warn!(
1044                     "AdvertiseManagerImpl {}: invalid raw advertise data to update",
1045                     advertiser_id
1046                 );
1047                 return;
1048             }
1049             self.gatt.lock().unwrap().advertiser.set_data(s.adv_id(), false, data);
1050         }
1051     }
1052 
set_scan_response_data(&mut self, advertiser_id: i32, data: AdvertiseData)1053     fn set_scan_response_data(&mut self, advertiser_id: i32, data: AdvertiseData) {
1054         if self.suspend_mode() != SuspendMode::Normal {
1055             return;
1056         }
1057 
1058         let device_name = self.get_adapter_name();
1059         let bytes = data.make_with(&device_name);
1060 
1061         if let Some(s) = self.get_by_advertiser_id(advertiser_id) {
1062             if !AdvertiseData::validate_raw_data(s.is_legacy(), &bytes) {
1063                 warn!("AdvertiseManagerImpl {}: invalid scan response to update", advertiser_id);
1064                 return;
1065             }
1066             self.gatt.lock().unwrap().advertiser.set_data(s.adv_id(), true, bytes);
1067         }
1068     }
1069 
set_advertising_parameters( &mut self, advertiser_id: i32, parameters: AdvertisingSetParameters, )1070     fn set_advertising_parameters(
1071         &mut self,
1072         advertiser_id: i32,
1073         parameters: AdvertisingSetParameters,
1074     ) {
1075         if self.suspend_mode() != SuspendMode::Normal {
1076             return;
1077         }
1078 
1079         let params = parameters.into();
1080 
1081         if let Some(s) = self.get_by_advertiser_id(advertiser_id) {
1082             let was_enabled = s.is_enabled();
1083             if was_enabled {
1084                 self.gatt.lock().unwrap().advertiser.enable(
1085                     s.adv_id(),
1086                     false,
1087                     s.adv_timeout(),
1088                     s.adv_events(),
1089                 );
1090             }
1091             self.gatt.lock().unwrap().advertiser.set_parameters(s.adv_id(), params);
1092             if was_enabled {
1093                 self.gatt.lock().unwrap().advertiser.enable(
1094                     s.adv_id(),
1095                     true,
1096                     s.adv_timeout(),
1097                     s.adv_events(),
1098                 );
1099             }
1100         }
1101     }
1102 
set_periodic_advertising_parameters( &mut self, advertiser_id: i32, parameters: PeriodicAdvertisingParameters, )1103     fn set_periodic_advertising_parameters(
1104         &mut self,
1105         advertiser_id: i32,
1106         parameters: PeriodicAdvertisingParameters,
1107     ) {
1108         if self.suspend_mode() != SuspendMode::Normal {
1109             return;
1110         }
1111 
1112         let params = parameters.into();
1113 
1114         if let Some(s) = self.get_by_advertiser_id(advertiser_id) {
1115             self.gatt
1116                 .lock()
1117                 .unwrap()
1118                 .advertiser
1119                 .set_periodic_advertising_parameters(s.adv_id(), params);
1120         }
1121     }
1122 
set_periodic_advertising_data(&mut self, advertiser_id: i32, data: AdvertiseData)1123     fn set_periodic_advertising_data(&mut self, advertiser_id: i32, data: AdvertiseData) {
1124         if self.suspend_mode() != SuspendMode::Normal {
1125             return;
1126         }
1127 
1128         let device_name = self.get_adapter_name();
1129         let bytes = data.make_with(&device_name);
1130 
1131         if let Some(s) = self.get_by_advertiser_id(advertiser_id) {
1132             if !AdvertiseData::validate_raw_data(false, &bytes) {
1133                 warn!("AdvertiseManagerImpl {}: invalid periodic data to update", advertiser_id);
1134                 return;
1135             }
1136             self.gatt.lock().unwrap().advertiser.set_periodic_advertising_data(s.adv_id(), bytes);
1137         }
1138     }
1139 
set_periodic_advertising_enable( &mut self, advertiser_id: i32, enable: bool, include_adi: bool, )1140     fn set_periodic_advertising_enable(
1141         &mut self,
1142         advertiser_id: i32,
1143         enable: bool,
1144         include_adi: bool,
1145     ) {
1146         if self.suspend_mode() != SuspendMode::Normal {
1147             return;
1148         }
1149         if let Some(s) = self.get_by_advertiser_id(advertiser_id) {
1150             self.gatt.lock().unwrap().advertiser.set_periodic_advertising_enable(
1151                 s.adv_id(),
1152                 enable,
1153                 include_adi,
1154             );
1155         }
1156     }
1157 }
1158 
1159 #[btif_callbacks_dispatcher(dispatch_le_adv_callbacks, GattAdvCallbacks)]
1160 pub(crate) trait BtifGattAdvCallbacks {
1161     #[btif_callback(OnAdvertisingSetStarted)]
on_advertising_set_started( &mut self, reg_id: i32, advertiser_id: u8, tx_power: i8, status: AdvertisingStatus, )1162     fn on_advertising_set_started(
1163         &mut self,
1164         reg_id: i32,
1165         advertiser_id: u8,
1166         tx_power: i8,
1167         status: AdvertisingStatus,
1168     );
1169 
1170     #[btif_callback(OnAdvertisingEnabled)]
on_advertising_enabled(&mut self, adv_id: u8, enabled: bool, status: AdvertisingStatus)1171     fn on_advertising_enabled(&mut self, adv_id: u8, enabled: bool, status: AdvertisingStatus);
1172 
1173     #[btif_callback(OnAdvertisingDataSet)]
on_advertising_data_set(&mut self, adv_id: u8, status: AdvertisingStatus)1174     fn on_advertising_data_set(&mut self, adv_id: u8, status: AdvertisingStatus);
1175 
1176     #[btif_callback(OnScanResponseDataSet)]
on_scan_response_data_set(&mut self, adv_id: u8, status: AdvertisingStatus)1177     fn on_scan_response_data_set(&mut self, adv_id: u8, status: AdvertisingStatus);
1178 
1179     #[btif_callback(OnAdvertisingParametersUpdated)]
on_advertising_parameters_updated( &mut self, adv_id: u8, tx_power: i8, status: AdvertisingStatus, )1180     fn on_advertising_parameters_updated(
1181         &mut self,
1182         adv_id: u8,
1183         tx_power: i8,
1184         status: AdvertisingStatus,
1185     );
1186 
1187     #[btif_callback(OnPeriodicAdvertisingParametersUpdated)]
on_periodic_advertising_parameters_updated(&mut self, adv_id: u8, status: AdvertisingStatus)1188     fn on_periodic_advertising_parameters_updated(&mut self, adv_id: u8, status: AdvertisingStatus);
1189 
1190     #[btif_callback(OnPeriodicAdvertisingDataSet)]
on_periodic_advertising_data_set(&mut self, adv_id: u8, status: AdvertisingStatus)1191     fn on_periodic_advertising_data_set(&mut self, adv_id: u8, status: AdvertisingStatus);
1192 
1193     #[btif_callback(OnPeriodicAdvertisingEnabled)]
on_periodic_advertising_enabled( &mut self, adv_id: u8, enabled: bool, status: AdvertisingStatus, )1194     fn on_periodic_advertising_enabled(
1195         &mut self,
1196         adv_id: u8,
1197         enabled: bool,
1198         status: AdvertisingStatus,
1199     );
1200 
1201     #[btif_callback(OnOwnAddressRead)]
on_own_address_read(&mut self, adv_id: u8, addr_type: u8, address: RawAddress)1202     fn on_own_address_read(&mut self, adv_id: u8, addr_type: u8, address: RawAddress);
1203 }
1204 
1205 impl BtifGattAdvCallbacks for AdvertiseManagerImpl {
1206     #[log_cb_args]
on_advertising_set_started( &mut self, reg_id: i32, advertiser_id: u8, tx_power: i8, status: AdvertisingStatus, )1207     fn on_advertising_set_started(
1208         &mut self,
1209         reg_id: i32,
1210         advertiser_id: u8,
1211         tx_power: i8,
1212         status: AdvertisingStatus,
1213     ) {
1214         let s = if let Some(s) = self.sets.get_mut(&reg_id) {
1215             s
1216         } else {
1217             error!("AdvertisingSetInfo not found");
1218             // An unknown advertising set has started. Unregister it anyway.
1219             self.gatt.lock().unwrap().advertiser.unregister(advertiser_id);
1220             return;
1221         };
1222 
1223         if s.is_stopped() {
1224             // The advertising set needs to be stopped. This could happen when |unregister_callback|
1225             // is called before an advertising becomes ready.
1226             self.gatt.lock().unwrap().advertiser.unregister(advertiser_id);
1227             self.sets.remove(&reg_id);
1228             return;
1229         }
1230 
1231         s.set_adv_id(Some(advertiser_id.into()));
1232         s.set_enabled(status == AdvertisingStatus::Success);
1233 
1234         if let Some(cb) = self.callbacks.get_by_id_mut(s.callback_id()) {
1235             cb.on_advertising_set_started(reg_id, advertiser_id.into(), tx_power.into(), status);
1236         }
1237 
1238         if status != AdvertisingStatus::Success {
1239             warn!(
1240                 "on_advertising_set_started(): failed! reg_id = {}, status = {:?}",
1241                 reg_id, status
1242             );
1243             self.sets.remove(&reg_id);
1244         }
1245     }
1246 
1247     #[log_cb_args]
on_advertising_enabled(&mut self, adv_id: u8, enabled: bool, status: AdvertisingStatus)1248     fn on_advertising_enabled(&mut self, adv_id: u8, enabled: bool, status: AdvertisingStatus) {
1249         let advertiser_id: i32 = adv_id.into();
1250 
1251         if let Some(s) = self.get_mut_by_advertiser_id(advertiser_id) {
1252             s.set_enabled(enabled);
1253         } else {
1254             return;
1255         }
1256 
1257         let s = *self.get_by_advertiser_id(advertiser_id).unwrap();
1258         if let Some(cb) = self.get_callback(&s) {
1259             cb.on_advertising_enabled(advertiser_id, enabled, status);
1260         }
1261 
1262         if self.suspend_mode() == SuspendMode::Suspending && self.enabled_sets().count() == 0 {
1263             self.set_suspend_mode(SuspendMode::Suspended);
1264         }
1265     }
1266 
1267     #[log_cb_args]
on_advertising_data_set(&mut self, adv_id: u8, status: AdvertisingStatus)1268     fn on_advertising_data_set(&mut self, adv_id: u8, status: AdvertisingStatus) {
1269         let advertiser_id: i32 = adv_id.into();
1270         if self.get_by_advertiser_id(advertiser_id).is_none() {
1271             return;
1272         }
1273         let s = *self.get_by_advertiser_id(advertiser_id).unwrap();
1274 
1275         if let Some(cb) = self.get_callback(&s) {
1276             cb.on_advertising_data_set(advertiser_id, status);
1277         }
1278     }
1279 
1280     #[log_cb_args]
on_scan_response_data_set(&mut self, adv_id: u8, status: AdvertisingStatus)1281     fn on_scan_response_data_set(&mut self, adv_id: u8, status: AdvertisingStatus) {
1282         let advertiser_id: i32 = adv_id.into();
1283         if self.get_by_advertiser_id(advertiser_id).is_none() {
1284             return;
1285         }
1286         let s = *self.get_by_advertiser_id(advertiser_id).unwrap();
1287 
1288         if let Some(cb) = self.get_callback(&s) {
1289             cb.on_scan_response_data_set(advertiser_id, status);
1290         }
1291     }
1292 
1293     #[log_cb_args]
on_advertising_parameters_updated( &mut self, adv_id: u8, tx_power: i8, status: AdvertisingStatus, )1294     fn on_advertising_parameters_updated(
1295         &mut self,
1296         adv_id: u8,
1297         tx_power: i8,
1298         status: AdvertisingStatus,
1299     ) {
1300         let advertiser_id: i32 = adv_id.into();
1301         if self.get_by_advertiser_id(advertiser_id).is_none() {
1302             return;
1303         }
1304         let s = *self.get_by_advertiser_id(advertiser_id).unwrap();
1305 
1306         if let Some(cb) = self.get_callback(&s) {
1307             cb.on_advertising_parameters_updated(advertiser_id, tx_power.into(), status);
1308         }
1309     }
1310 
1311     #[log_cb_args]
on_periodic_advertising_parameters_updated( &mut self, adv_id: u8, status: AdvertisingStatus, )1312     fn on_periodic_advertising_parameters_updated(
1313         &mut self,
1314         adv_id: u8,
1315         status: AdvertisingStatus,
1316     ) {
1317         let advertiser_id: i32 = adv_id.into();
1318         if self.get_by_advertiser_id(advertiser_id).is_none() {
1319             return;
1320         }
1321         let s = *self.get_by_advertiser_id(advertiser_id).unwrap();
1322 
1323         if let Some(cb) = self.get_callback(&s) {
1324             cb.on_periodic_advertising_parameters_updated(advertiser_id, status);
1325         }
1326     }
1327 
1328     #[log_cb_args]
on_periodic_advertising_data_set(&mut self, adv_id: u8, status: AdvertisingStatus)1329     fn on_periodic_advertising_data_set(&mut self, adv_id: u8, status: AdvertisingStatus) {
1330         let advertiser_id: i32 = adv_id.into();
1331         if self.get_by_advertiser_id(advertiser_id).is_none() {
1332             return;
1333         }
1334         let s = *self.get_by_advertiser_id(advertiser_id).unwrap();
1335 
1336         if let Some(cb) = self.get_callback(&s) {
1337             cb.on_periodic_advertising_data_set(advertiser_id, status);
1338         }
1339     }
1340 
1341     #[log_cb_args]
on_periodic_advertising_enabled( &mut self, adv_id: u8, enabled: bool, status: AdvertisingStatus, )1342     fn on_periodic_advertising_enabled(
1343         &mut self,
1344         adv_id: u8,
1345         enabled: bool,
1346         status: AdvertisingStatus,
1347     ) {
1348         let advertiser_id: i32 = adv_id.into();
1349         if self.get_by_advertiser_id(advertiser_id).is_none() {
1350             return;
1351         }
1352         let s = *self.get_by_advertiser_id(advertiser_id).unwrap();
1353 
1354         if let Some(cb) = self.get_callback(&s) {
1355             cb.on_periodic_advertising_enabled(advertiser_id, enabled, status);
1356         }
1357     }
1358 
1359     #[log_cb_args]
on_own_address_read(&mut self, adv_id: u8, addr_type: u8, address: RawAddress)1360     fn on_own_address_read(&mut self, adv_id: u8, addr_type: u8, address: RawAddress) {
1361         let advertiser_id: i32 = adv_id.into();
1362         if self.get_by_advertiser_id(advertiser_id).is_none() {
1363             return;
1364         }
1365         let s = *self.get_by_advertiser_id(advertiser_id).unwrap();
1366 
1367         if let Some(cb) = self.get_callback(&s) {
1368             cb.on_own_address_read(advertiser_id, addr_type.into(), address);
1369         }
1370     }
1371 }
1372 
1373 /// The underlying legacy advertising rotates every SOFTWARE_ROTATION_INTERVAL seconds.
1374 const SOFTWARE_ROTATION_INTERVAL: Duration = Duration::from_secs(2);
1375 
1376 /// The ID of a software rotation advertising.
1377 ///
1378 /// From DBus API's perspective this is used as both Advertiser ID and Register ID.
1379 /// Unlike the extended advertising stack we can't propagate the LibBluetooth Advertiser ID to
1380 /// DBus clients because there can be at most 1 advertiser in LibBluetooth layer at the same time.
1381 pub type SoftwareRotationAdvertierId = i32;
1382 
1383 struct SoftwareRotationAdvertiseInfo {
1384     id: SoftwareRotationAdvertierId,
1385     callback_id: u32,
1386 
1387     advertising_params: AdvertisingSetParameters,
1388     advertising_data: Vec<u8>,
1389     scan_response_data: Vec<u8>,
1390 
1391     /// Filled in on the first time the advertiser started.
1392     tx_power: Option<i32>,
1393 
1394     /// True if it's advertising (from DBus client's perspective), false otherwise.
1395     enabled: bool,
1396     duration: i32,
1397     /// None means no timeout
1398     expire_time: Option<Instant>,
1399 }
1400 
1401 enum SoftwareRotationAdvertiseState {
1402     /// No advertiser is running in LibBluetooth.
1403     Stopped,
1404     /// A StartAdvertisingSet call to LibBluetooth is pending.
1405     Pending(SoftwareRotationAdvertierId),
1406     /// An advertiser is running in LibBluetooth, i.e., an OnAdvertisingSetStarted is received.
1407     /// Parameters: ID, LibBluetooth BLE Advertiser ID, rotation timer handle
1408     Advertising(SoftwareRotationAdvertierId, u8, JoinHandle<()>),
1409 }
1410 
1411 struct SoftwareRotationAdvertiseManagerImpl {
1412     callbacks: Callbacks<dyn IAdvertisingSetCallback + Send>,
1413     suspend_mode: SuspendMode,
1414     gatt: Arc<Mutex<Gatt>>,
1415     adapter: Arc<Mutex<Box<Bluetooth>>>,
1416     tx: Sender<Message>,
1417 
1418     state: SoftwareRotationAdvertiseState,
1419     adv_info: HashMap<SoftwareRotationAdvertierId, SoftwareRotationAdvertiseInfo>,
1420     /// The enabled advertising sets to be rotate.
1421     /// When they are removed from the queue, OnAdvertisingEnabled needs to be sent.
1422     /// Note that the current advertiser running in LibBluetooth must *NOT* be in the queue.
1423     adv_queue: VecDeque<SoftwareRotationAdvertierId>,
1424 }
1425 
1426 impl SoftwareRotationAdvertiseManagerImpl {
new( tx: Sender<Message>, gatt: Arc<Mutex<Gatt>>, adapter: Arc<Mutex<Box<Bluetooth>>>, ) -> Self1427     fn new(
1428         tx: Sender<Message>,
1429         gatt: Arc<Mutex<Gatt>>,
1430         adapter: Arc<Mutex<Box<Bluetooth>>>,
1431     ) -> Self {
1432         Self {
1433             callbacks: Callbacks::new(tx.clone(), Message::AdvertiserCallbackDisconnected),
1434             suspend_mode: SuspendMode::Normal,
1435             gatt,
1436             adapter,
1437             tx,
1438             state: SoftwareRotationAdvertiseState::Stopped,
1439             adv_info: HashMap::new(),
1440             adv_queue: VecDeque::new(),
1441         }
1442     }
1443 }
1444 
1445 impl SoftwareRotationAdvertiseManagerImpl {
1446     /// Updates suspend mode.
set_suspend_mode(&mut self, suspend_mode: SuspendMode)1447     fn set_suspend_mode(&mut self, suspend_mode: SuspendMode) {
1448         if suspend_mode != self.suspend_mode {
1449             self.suspend_mode = suspend_mode.clone();
1450             self.callbacks.for_all_callbacks(|cb| {
1451                 cb.on_suspend_mode_change(suspend_mode.clone());
1452             });
1453         }
1454     }
1455 
get_adapter_name(&self) -> String1456     fn get_adapter_name(&self) -> String {
1457         self.adapter.lock().unwrap().get_name()
1458     }
1459 
1460     /// Returns the ID of the advertiser running in LibBluetooth.
current_id(&self) -> Option<SoftwareRotationAdvertierId>1461     fn current_id(&self) -> Option<SoftwareRotationAdvertierId> {
1462         match &self.state {
1463             SoftwareRotationAdvertiseState::Pending(id) => Some(*id),
1464             SoftwareRotationAdvertiseState::Advertising(id, _, _) => Some(*id),
1465             SoftwareRotationAdvertiseState::Stopped => None,
1466         }
1467     }
1468 
1469     /// Returns the minimum unoccupied ID from 0.
new_id(&mut self) -> SoftwareRotationAdvertierId1470     fn new_id(&mut self) -> SoftwareRotationAdvertierId {
1471         // The advertiser running in LibBluetooth may have been removed in this layer.
1472         // Avoid conflicting with it.
1473         let current_id = self.current_id();
1474         (0..)
1475             .find(|id| !self.adv_info.contains_key(id) && Some(*id) != current_id)
1476             .expect("There must be an unoccupied register ID")
1477     }
1478 
is_pending(&self) -> bool1479     fn is_pending(&self) -> bool {
1480         matches!(&self.state, SoftwareRotationAdvertiseState::Pending(_))
1481     }
1482 
is_stopped(&self) -> bool1483     fn is_stopped(&self) -> bool {
1484         matches!(&self.state, SoftwareRotationAdvertiseState::Stopped)
1485     }
1486 
1487     /// Clears the removed or disabled advertisers from the queue and invokes callback.
refresh_queue(&mut self)1488     fn refresh_queue(&mut self) {
1489         let now = Instant::now();
1490         let adv_info = &mut self.adv_info;
1491         let callbacks = &mut self.callbacks;
1492         self.adv_queue.retain(|id| {
1493             let Some(info) = adv_info.get_mut(id) else {
1494                 // This advertiser has been removed.
1495                 return false;
1496             };
1497             if info.expire_time.map_or(false, |t| t < now) {
1498                 // This advertiser has expired.
1499                 info.enabled = false;
1500                 if let Some(cb) = callbacks.get_by_id_mut(info.callback_id) {
1501                     cb.on_advertising_enabled(info.id, false, AdvertisingStatus::Success);
1502                 }
1503             }
1504             info.enabled
1505         });
1506     }
1507 
stop_current_advertising(&mut self)1508     fn stop_current_advertising(&mut self) {
1509         match &self.state {
1510             SoftwareRotationAdvertiseState::Advertising(id, adv_id, handle) => {
1511                 handle.abort();
1512                 self.gatt.lock().unwrap().advertiser.unregister(*adv_id);
1513                 self.adv_queue.push_back(*id);
1514                 self.state = SoftwareRotationAdvertiseState::Stopped;
1515             }
1516             SoftwareRotationAdvertiseState::Pending(_) => {
1517                 error!("stop_current_advertising: Unexpected Pending state");
1518             }
1519             SoftwareRotationAdvertiseState::Stopped => {}
1520         };
1521     }
1522 
start_next_advertising(&mut self)1523     fn start_next_advertising(&mut self) {
1524         match &self.state {
1525             SoftwareRotationAdvertiseState::Stopped => {
1526                 self.state = loop {
1527                     let Some(id) = self.adv_queue.pop_front() else {
1528                         break SoftwareRotationAdvertiseState::Stopped;
1529                     };
1530                     let Some(info) = self.adv_info.get(&id) else {
1531                         error!("start_next_advertising: Unknown ID, which means queue is not refreshed!");
1532                         continue;
1533                     };
1534                     self.gatt.lock().unwrap().advertiser.start_advertising_set(
1535                         id,
1536                         info.advertising_params.clone().into(),
1537                         info.advertising_data.clone(),
1538                         info.scan_response_data.clone(),
1539                         Default::default(), // Unsupported periodic_parameters
1540                         vec![],             // Unsupported periodic_data
1541                         0,                  // Set no timeout. Timeout is controlled in this layer.
1542                         0,                  // Unsupported max_ext_adv_events
1543                     );
1544                     break SoftwareRotationAdvertiseState::Pending(id);
1545                 }
1546             }
1547             SoftwareRotationAdvertiseState::Pending(_) => {
1548                 error!("start_next_advertising: Unexpected Pending state");
1549             }
1550             SoftwareRotationAdvertiseState::Advertising(_, _, _) => {
1551                 error!("start_next_advertising: Unexpected Advertising state");
1552             }
1553         };
1554     }
1555 
run_rotate(&mut self)1556     fn run_rotate(&mut self) {
1557         if self.is_pending() {
1558             return;
1559         }
1560         let Some(current_id) = self.current_id() else {
1561             // State is Stopped. Try to start next one.
1562             self.refresh_queue();
1563             self.start_next_advertising();
1564             return;
1565         };
1566         // We are Advertising. Checks if the current advertiser is still allowed
1567         // to advertise, or if we should schedule the next one in the queue.
1568         let current_is_enabled = {
1569             let now = Instant::now();
1570             if let Some(info) = self.adv_info.get(&current_id) {
1571                 if info.enabled {
1572                     info.expire_time.map_or(true, |t| t >= now)
1573                 } else {
1574                     false
1575                 }
1576             } else {
1577                 false
1578             }
1579         };
1580         if !current_is_enabled {
1581             // If current advertiser is not allowed to advertise,
1582             // stop it and then let |refresh_queue| handle the callback.
1583             self.stop_current_advertising();
1584             self.refresh_queue();
1585             self.start_next_advertising();
1586         } else {
1587             // Current advertiser is still enabled, refresh the other advertisers in the queue.
1588             self.refresh_queue();
1589             if self.adv_queue.is_empty() {
1590                 // No need to rotate.
1591             } else {
1592                 self.stop_current_advertising();
1593                 self.start_next_advertising();
1594             }
1595         }
1596     }
1597 }
1598 
1599 impl AdvertiseManagerOps for SoftwareRotationAdvertiseManagerImpl {
enter_suspend(&mut self)1600     fn enter_suspend(&mut self) {
1601         if self.suspend_mode != SuspendMode::Normal {
1602             return;
1603         }
1604 
1605         self.set_suspend_mode(SuspendMode::Suspending);
1606         if self.is_pending() {
1607             // We will unregister it on_advertising_set_started and then set mode to suspended.
1608             return;
1609         }
1610         self.stop_current_advertising();
1611         self.set_suspend_mode(SuspendMode::Suspended);
1612     }
1613 
exit_suspend(&mut self)1614     fn exit_suspend(&mut self) {
1615         if self.suspend_mode != SuspendMode::Suspended {
1616             return;
1617         }
1618         self.refresh_queue();
1619         self.start_next_advertising();
1620         self.set_suspend_mode(SuspendMode::Normal);
1621     }
1622 
handle_action(&mut self, action: AdvertiserActions)1623     fn handle_action(&mut self, action: AdvertiserActions) {
1624         match action {
1625             AdvertiserActions::RunRotate => {
1626                 if self.suspend_mode == SuspendMode::Normal {
1627                     self.run_rotate();
1628                 }
1629             }
1630         }
1631     }
1632 }
1633 
1634 /// Generates expire time from now per the definition in IBluetoothAdvertiseManager
1635 ///
1636 /// None means never timeout.
gen_expire_time_from_now(duration: i32) -> Option<Instant>1637 fn gen_expire_time_from_now(duration: i32) -> Option<Instant> {
1638     let duration = clamp(duration, 0, 0xffff) as u64;
1639     if duration != 0 {
1640         Some(Instant::now() + Duration::from_millis(duration * 10))
1641     } else {
1642         None
1643     }
1644 }
1645 
1646 impl IBluetoothAdvertiseManager for SoftwareRotationAdvertiseManagerImpl {
register_callback(&mut self, callback: Box<dyn IAdvertisingSetCallback + Send>) -> u321647     fn register_callback(&mut self, callback: Box<dyn IAdvertisingSetCallback + Send>) -> u32 {
1648         self.callbacks.add_callback(callback)
1649     }
1650 
unregister_callback(&mut self, callback_id: u32) -> bool1651     fn unregister_callback(&mut self, callback_id: u32) -> bool {
1652         self.adv_info.retain(|_, info| info.callback_id != callback_id);
1653         let ret = self.callbacks.remove_callback(callback_id);
1654         if let Some(current_id) = self.current_id() {
1655             if !self.adv_info.contains_key(&current_id) {
1656                 self.run_rotate();
1657             }
1658         }
1659         ret
1660     }
1661 
start_advertising_set( &mut self, advertising_params: AdvertisingSetParameters, advertising_data: AdvertiseData, scan_response_data: Option<AdvertiseData>, periodic_parameters: Option<PeriodicAdvertisingParameters>, periodic_data: Option<AdvertiseData>, duration: i32, max_ext_adv_events: i32, callback_id: u32, ) -> i321662     fn start_advertising_set(
1663         &mut self,
1664         advertising_params: AdvertisingSetParameters,
1665         advertising_data: AdvertiseData,
1666         scan_response_data: Option<AdvertiseData>,
1667         periodic_parameters: Option<PeriodicAdvertisingParameters>,
1668         periodic_data: Option<AdvertiseData>,
1669         duration: i32,
1670         max_ext_adv_events: i32,
1671         callback_id: u32,
1672     ) -> i32 {
1673         if self.suspend_mode != SuspendMode::Normal {
1674             return INVALID_REG_ID;
1675         }
1676 
1677         let is_legacy = advertising_params.is_legacy;
1678         let device_name = self.get_adapter_name();
1679 
1680         let advertising_data = advertising_data.make_with(&device_name);
1681         if !AdvertiseData::validate_raw_data(is_legacy, &advertising_data) {
1682             warn!("Failed to start advertising set with invalid advertising data");
1683             return INVALID_REG_ID;
1684         }
1685 
1686         let scan_response_data =
1687             scan_response_data.map_or(vec![], |data| data.make_with(&device_name));
1688         if !AdvertiseData::validate_raw_data(is_legacy, &scan_response_data) {
1689             warn!("Failed to start advertising set with invalid scan response data");
1690             return INVALID_REG_ID;
1691         }
1692 
1693         if periodic_parameters.is_some() {
1694             warn!("Periodic parameters is not supported in software rotation stack, ignored");
1695         }
1696         if periodic_data.is_some() {
1697             warn!("Periodic data is not supported in software rotation stack, ignored");
1698         }
1699         if max_ext_adv_events != 0 {
1700             warn!("max_ext_adv_events is not supported in software rotation stack, ignored");
1701         }
1702 
1703         let id = self.new_id();
1704 
1705         // expire_time will be determined on this advertiser is started at the first time.
1706         self.adv_info.insert(
1707             id,
1708             SoftwareRotationAdvertiseInfo {
1709                 id,
1710                 callback_id,
1711                 advertising_params,
1712                 advertising_data,
1713                 scan_response_data,
1714                 tx_power: None,
1715                 enabled: true,
1716                 duration,
1717                 expire_time: None,
1718             },
1719         );
1720         // Schedule it as the next one and rotate.
1721         self.adv_queue.push_front(id);
1722         self.run_rotate();
1723 
1724         id
1725     }
1726 
stop_advertising_set(&mut self, adv_id: i32)1727     fn stop_advertising_set(&mut self, adv_id: i32) {
1728         let current_id = self.current_id();
1729         let Some(info) = self.adv_info.remove(&adv_id) else {
1730             warn!("stop_advertising_set: Unknown adv_id {}", adv_id);
1731             return;
1732         };
1733         if let Some(cb) = self.callbacks.get_by_id_mut(info.callback_id) {
1734             cb.on_advertising_set_stopped(info.id);
1735         }
1736         if current_id == Some(info.id) {
1737             self.run_rotate();
1738         }
1739     }
1740 
get_own_address(&mut self, _adv_id: i32)1741     fn get_own_address(&mut self, _adv_id: i32) {
1742         error!("get_own_address is not supported in software rotation stack");
1743     }
1744 
enable_advertising_set( &mut self, adv_id: i32, enable: bool, duration: i32, max_ext_adv_events: i32, )1745     fn enable_advertising_set(
1746         &mut self,
1747         adv_id: i32,
1748         enable: bool,
1749         duration: i32,
1750         max_ext_adv_events: i32,
1751     ) {
1752         if self.suspend_mode != SuspendMode::Normal {
1753             return;
1754         }
1755 
1756         let current_id = self.current_id();
1757         let Some(info) = self.adv_info.get_mut(&adv_id) else {
1758             warn!("enable_advertising_set: Unknown adv_id {}", adv_id);
1759             return;
1760         };
1761 
1762         if max_ext_adv_events != 0 {
1763             warn!("max_ext_adv_events is not supported in software rotation stack, ignored");
1764         }
1765 
1766         info.enabled = enable;
1767         // We won't really call enable() to LibBluetooth so calculate the expire time right now.
1768         info.expire_time = gen_expire_time_from_now(duration);
1769         // This actually won't be used as the expire_time is already determined.
1770         // Still fill it in to keep the data updated.
1771         info.duration = duration;
1772 
1773         if enable && !self.adv_queue.contains(&info.id) && current_id != Some(info.id) {
1774             // The adv was not enabled and not in the queue. Invoke callback and queue it.
1775             if let Some(cb) = self.callbacks.get_by_id_mut(info.callback_id) {
1776                 cb.on_advertising_enabled(info.id, false, AdvertisingStatus::Success);
1777             }
1778             self.adv_queue.push_back(info.id);
1779             if self.is_stopped() {
1780                 self.start_next_advertising();
1781             }
1782         } else if !enable && current_id == Some(info.id) {
1783             self.run_rotate();
1784         }
1785     }
1786 
set_advertising_data(&mut self, adv_id: i32, data: AdvertiseData)1787     fn set_advertising_data(&mut self, adv_id: i32, data: AdvertiseData) {
1788         if self.suspend_mode != SuspendMode::Normal {
1789             return;
1790         }
1791 
1792         let current_id = self.current_id();
1793         let device_name = self.get_adapter_name();
1794         let Some(info) = self.adv_info.get_mut(&adv_id) else {
1795             warn!("set_advertising_data: Unknown adv_id {}", adv_id);
1796             return;
1797         };
1798         let data = data.make_with(&device_name);
1799         if !AdvertiseData::validate_raw_data(info.advertising_params.is_legacy, &data) {
1800             warn!("set_advertising_data {}: invalid advertise data to update", adv_id);
1801             return;
1802         }
1803         info.advertising_data = data;
1804         if let Some(cb) = self.callbacks.get_by_id_mut(info.callback_id) {
1805             cb.on_advertising_data_set(info.id, AdvertisingStatus::Success);
1806         }
1807 
1808         if current_id == Some(info.id) {
1809             self.run_rotate();
1810         }
1811     }
1812 
set_raw_adv_data(&mut self, adv_id: i32, data: Vec<u8>)1813     fn set_raw_adv_data(&mut self, adv_id: i32, data: Vec<u8>) {
1814         if self.suspend_mode != SuspendMode::Normal {
1815             return;
1816         }
1817 
1818         let current_id = self.current_id();
1819         let Some(info) = self.adv_info.get_mut(&adv_id) else {
1820             warn!("set_raw_adv_data: Unknown adv_id {}", adv_id);
1821             return;
1822         };
1823         if !AdvertiseData::validate_raw_data(info.advertising_params.is_legacy, &data) {
1824             warn!("set_raw_adv_data {}: invalid raw advertise data to update", adv_id);
1825             return;
1826         }
1827         info.advertising_data = data;
1828         if let Some(cb) = self.callbacks.get_by_id_mut(info.callback_id) {
1829             cb.on_advertising_data_set(info.id, AdvertisingStatus::Success);
1830         }
1831 
1832         if current_id == Some(info.id) {
1833             self.run_rotate();
1834         }
1835     }
1836 
set_scan_response_data(&mut self, adv_id: i32, data: AdvertiseData)1837     fn set_scan_response_data(&mut self, adv_id: i32, data: AdvertiseData) {
1838         if self.suspend_mode != SuspendMode::Normal {
1839             return;
1840         }
1841 
1842         let current_id = self.current_id();
1843         let device_name = self.get_adapter_name();
1844         let Some(info) = self.adv_info.get_mut(&adv_id) else {
1845             warn!("set_scan_response_data: Unknown adv_id {}", adv_id);
1846             return;
1847         };
1848         let data = data.make_with(&device_name);
1849         if !AdvertiseData::validate_raw_data(info.advertising_params.is_legacy, &data) {
1850             warn!("set_scan_response_data {}: invalid scan response to update", adv_id);
1851             return;
1852         }
1853         info.scan_response_data = data;
1854         if let Some(cb) = self.callbacks.get_by_id_mut(info.callback_id) {
1855             cb.on_scan_response_data_set(info.id, AdvertisingStatus::Success);
1856         }
1857 
1858         if current_id == Some(info.id) {
1859             self.run_rotate();
1860         }
1861     }
1862 
set_advertising_parameters(&mut self, adv_id: i32, params: AdvertisingSetParameters)1863     fn set_advertising_parameters(&mut self, adv_id: i32, params: AdvertisingSetParameters) {
1864         if self.suspend_mode != SuspendMode::Normal {
1865             return;
1866         }
1867 
1868         let current_id = self.current_id();
1869         let Some(info) = self.adv_info.get_mut(&adv_id) else {
1870             warn!("set_advertising_parameters: Unknown adv_id {}", adv_id);
1871             return;
1872         };
1873         info.advertising_params = params;
1874         let Some(tx_power) = info.tx_power else {
1875             error!("set_advertising_parameters: tx_power is None! Is this called before adv has started?");
1876             return;
1877         };
1878         if let Some(cb) = self.callbacks.get_by_id_mut(info.callback_id) {
1879             cb.on_advertising_parameters_updated(info.id, tx_power, AdvertisingStatus::Success);
1880         }
1881 
1882         if current_id == Some(info.id) {
1883             self.run_rotate();
1884         }
1885     }
1886 
set_periodic_advertising_parameters( &mut self, _adv_id: i32, _parameters: PeriodicAdvertisingParameters, )1887     fn set_periodic_advertising_parameters(
1888         &mut self,
1889         _adv_id: i32,
1890         _parameters: PeriodicAdvertisingParameters,
1891     ) {
1892         error!("set_periodic_advertising_parameters is not supported in software rotation stack");
1893     }
1894 
set_periodic_advertising_data(&mut self, _adv_id: i32, _data: AdvertiseData)1895     fn set_periodic_advertising_data(&mut self, _adv_id: i32, _data: AdvertiseData) {
1896         error!("set_periodic_advertising_data is not supported in software rotation stack");
1897     }
1898 
set_periodic_advertising_enable(&mut self, _adv_id: i32, _enable: bool, _include_adi: bool)1899     fn set_periodic_advertising_enable(&mut self, _adv_id: i32, _enable: bool, _include_adi: bool) {
1900         error!("set_periodic_advertising_enable is not supported in software rotation stack");
1901     }
1902 }
1903 
1904 impl BtifGattAdvCallbacks for SoftwareRotationAdvertiseManagerImpl {
on_advertising_set_started( &mut self, reg_id: i32, adv_id: u8, tx_power: i8, status: AdvertisingStatus, )1905     fn on_advertising_set_started(
1906         &mut self,
1907         reg_id: i32,
1908         adv_id: u8,
1909         tx_power: i8,
1910         status: AdvertisingStatus,
1911     ) {
1912         debug!(
1913             "on_advertising_set_started(): reg_id = {}, advertiser_id = {}, tx_power = {}, status = {:?}",
1914             reg_id, adv_id, tx_power, status
1915         );
1916 
1917         // Unregister if it's unexpected.
1918         match &self.state {
1919             SoftwareRotationAdvertiseState::Pending(pending_id) if pending_id == &reg_id => {}
1920             _ => {
1921                 error!(
1922                     "Unexpected on_advertising_set_started reg_id = {}, adv_id = {}, status = {:?}",
1923                     reg_id, adv_id, status
1924                 );
1925                 if status == AdvertisingStatus::Success {
1926                     self.gatt.lock().unwrap().advertiser.unregister(adv_id);
1927                 }
1928                 return;
1929             }
1930         }
1931         // Switch out from the pending state.
1932         self.state = if status != AdvertisingStatus::Success {
1933             warn!("on_advertising_set_started failed: reg_id = {}, status = {:?}", reg_id, status);
1934             SoftwareRotationAdvertiseState::Stopped
1935         } else {
1936             let txl = self.tx.clone();
1937             SoftwareRotationAdvertiseState::Advertising(
1938                 reg_id,
1939                 adv_id,
1940                 tokio::spawn(async move {
1941                     loop {
1942                         time::sleep(SOFTWARE_ROTATION_INTERVAL).await;
1943                         let _ = txl
1944                             .send(Message::AdvertiserActions(AdvertiserActions::RunRotate))
1945                             .await;
1946                     }
1947                 }),
1948             )
1949         };
1950 
1951         // 1. Handle on_advertising_set_started callback if it's the first time it started
1952         // 2. Stop advertising if it's removed or disabled
1953         // 3. Disable or remove the advertiser if it failed
1954         if let Some(info) = self.adv_info.get_mut(&reg_id) {
1955             if info.tx_power.is_none() {
1956                 // tx_power is none means it's the first time this advertiser started.
1957                 if status != AdvertisingStatus::Success {
1958                     if let Some(cb) = self.callbacks.get_by_id_mut(info.callback_id) {
1959                         cb.on_advertising_set_started(info.id, INVALID_ADV_ID, 0, status);
1960                     }
1961                     self.adv_info.remove(&reg_id);
1962                 } else {
1963                     info.tx_power = Some(tx_power.into());
1964                     info.expire_time = gen_expire_time_from_now(info.duration);
1965                     if let Some(cb) = self.callbacks.get_by_id_mut(info.callback_id) {
1966                         cb.on_advertising_set_started(info.id, info.id, tx_power.into(), status);
1967                     }
1968                 }
1969             } else {
1970                 // Not the first time. This means we are not able to report the failure through
1971                 // on_advertising_set_started if it failed. Disable it instead in that case.
1972                 if status != AdvertisingStatus::Success {
1973                     info.enabled = false;
1974                     // Push to the queue and let refresh_queue handle the disabled callback.
1975                     self.adv_queue.push_back(reg_id);
1976                 } else if !info.enabled {
1977                     self.stop_current_advertising();
1978                 }
1979             }
1980         } else {
1981             self.stop_current_advertising();
1982         }
1983 
1984         // Rotate again if the next advertiser is new. We need to consume all
1985         // "first time" advertiser before suspended to make sure callbacks are sent.
1986         if let Some(id) = self.adv_queue.front() {
1987             if let Some(info) = self.adv_info.get(id) {
1988                 if info.tx_power.is_none() {
1989                     self.run_rotate();
1990                     return;
1991                 }
1992             }
1993         }
1994 
1995         // We're fine to suspend since there is no advertiser pending callback.
1996         if self.suspend_mode != SuspendMode::Normal {
1997             self.stop_current_advertising();
1998             self.set_suspend_mode(SuspendMode::Suspended);
1999             return;
2000         }
2001 
2002         // If the current advertiser is stopped for some reason, schedule the next one.
2003         if self.is_stopped() {
2004             self.refresh_queue();
2005             self.start_next_advertising();
2006         }
2007     }
2008 
on_advertising_enabled(&mut self, _adv_id: u8, _enabled: bool, _status: AdvertisingStatus)2009     fn on_advertising_enabled(&mut self, _adv_id: u8, _enabled: bool, _status: AdvertisingStatus) {
2010         error!("Unexpected on_advertising_enabled in software rotation stack");
2011     }
2012 
on_advertising_data_set(&mut self, _adv_id: u8, _status: AdvertisingStatus)2013     fn on_advertising_data_set(&mut self, _adv_id: u8, _status: AdvertisingStatus) {
2014         error!("Unexpected on_advertising_data_set in software rotation stack");
2015     }
2016 
on_scan_response_data_set(&mut self, _adv_id: u8, _status: AdvertisingStatus)2017     fn on_scan_response_data_set(&mut self, _adv_id: u8, _status: AdvertisingStatus) {
2018         error!("Unexpected on_scan_response_data_set in software rotation stack");
2019     }
2020 
on_advertising_parameters_updated( &mut self, _adv_id: u8, _tx_power: i8, _status: AdvertisingStatus, )2021     fn on_advertising_parameters_updated(
2022         &mut self,
2023         _adv_id: u8,
2024         _tx_power: i8,
2025         _status: AdvertisingStatus,
2026     ) {
2027         error!("Unexpected on_advertising_parameters_updated in software rotation stack");
2028     }
2029 
on_periodic_advertising_parameters_updated( &mut self, _adv_id: u8, _status: AdvertisingStatus, )2030     fn on_periodic_advertising_parameters_updated(
2031         &mut self,
2032         _adv_id: u8,
2033         _status: AdvertisingStatus,
2034     ) {
2035         error!("Unexpected on_periodic_advertising_parameters_updated in software rotation stack");
2036     }
2037 
on_periodic_advertising_data_set(&mut self, _adv_id: u8, _status: AdvertisingStatus)2038     fn on_periodic_advertising_data_set(&mut self, _adv_id: u8, _status: AdvertisingStatus) {
2039         error!("Unexpected on_periodic_advertising_data_set in software rotation stack");
2040     }
2041 
on_periodic_advertising_enabled( &mut self, _adv_id: u8, _enabled: bool, _status: AdvertisingStatus, )2042     fn on_periodic_advertising_enabled(
2043         &mut self,
2044         _adv_id: u8,
2045         _enabled: bool,
2046         _status: AdvertisingStatus,
2047     ) {
2048         error!("Unexpected on_periodic_advertising_enabled in software rotation stack");
2049     }
2050 
on_own_address_read(&mut self, _adv_id: u8, _addr_type: u8, _address: RawAddress)2051     fn on_own_address_read(&mut self, _adv_id: u8, _addr_type: u8, _address: RawAddress) {
2052         error!("Unexpected on_own_address_read in software rotation stack");
2053     }
2054 }
2055 
2056 #[cfg(test)]
2057 mod tests {
2058     use super::*;
2059     use std::iter::FromIterator;
2060 
2061     #[test]
test_append_ad_data_clamped()2062     fn test_append_ad_data_clamped() {
2063         let mut bytes = Vec::<u8>::new();
2064         let mut ans = Vec::<u8>::new();
2065         ans.push(255);
2066         ans.push(102);
2067         ans.extend(Vec::<u8>::from_iter(0..254));
2068 
2069         let payload = Vec::<u8>::from_iter(0..255);
2070         AdvertiseData::append_adv_data(&mut bytes, 102, &payload);
2071         assert_eq!(bytes, ans);
2072     }
2073 
2074     #[test]
test_append_ad_data_multiple()2075     fn test_append_ad_data_multiple() {
2076         let mut bytes = Vec::<u8>::new();
2077 
2078         let payload = vec![0_u8, 1, 2, 3, 4];
2079         AdvertiseData::append_adv_data(&mut bytes, 100, &payload);
2080         AdvertiseData::append_adv_data(&mut bytes, 101, &[0]);
2081         assert_eq!(bytes, vec![6_u8, 100, 0, 1, 2, 3, 4, 2, 101, 0]);
2082     }
2083 
2084     #[test]
test_append_service_uuids()2085     fn test_append_service_uuids() {
2086         let mut bytes = Vec::<u8>::new();
2087         let uuid_16 = Uuid::from_string("0000fef3-0000-1000-8000-00805f9b34fb").unwrap();
2088         let uuids = vec![uuid_16];
2089         let exp_16: Vec<u8> = vec![3, 0x3, 0xf3, 0xfe];
2090         AdvertiseData::append_service_uuids(&mut bytes, &uuids);
2091         assert_eq!(bytes, exp_16);
2092 
2093         let mut bytes = Vec::<u8>::new();
2094         let uuid_32 = Uuid::from_string("00112233-0000-1000-8000-00805f9b34fb").unwrap();
2095         let uuids = vec![uuid_32];
2096         let exp_32: Vec<u8> = vec![5, 0x5, 0x33, 0x22, 0x11, 0x0];
2097         AdvertiseData::append_service_uuids(&mut bytes, &uuids);
2098         assert_eq!(bytes, exp_32);
2099 
2100         let mut bytes = Vec::<u8>::new();
2101         let uuid_128 = Uuid::from_string("00010203-0405-0607-0809-0a0b0c0d0e0f").unwrap();
2102         let uuids = vec![uuid_128];
2103         let exp_128: Vec<u8> = vec![
2104             17, 0x7, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0,
2105         ];
2106         AdvertiseData::append_service_uuids(&mut bytes, &uuids);
2107         assert_eq!(bytes, exp_128);
2108 
2109         let mut bytes = Vec::<u8>::new();
2110         let uuids = vec![uuid_16, uuid_32, uuid_128];
2111         let exp_bytes: Vec<u8> =
2112             [exp_16.as_slice(), exp_32.as_slice(), exp_128.as_slice()].concat();
2113         AdvertiseData::append_service_uuids(&mut bytes, &uuids);
2114         assert_eq!(bytes, exp_bytes);
2115 
2116         // Interleaved UUIDs.
2117         let mut bytes = Vec::<u8>::new();
2118         let uuid_16_2 = Uuid::from_string("0000aabb-0000-1000-8000-00805f9b34fb").unwrap();
2119         let uuids = vec![uuid_16, uuid_128, uuid_16_2, uuid_32];
2120         let exp_16: Vec<u8> = vec![5, 0x3, 0xf3, 0xfe, 0xbb, 0xaa];
2121         let exp_bytes: Vec<u8> =
2122             [exp_16.as_slice(), exp_32.as_slice(), exp_128.as_slice()].concat();
2123         AdvertiseData::append_service_uuids(&mut bytes, &uuids);
2124         assert_eq!(bytes, exp_bytes);
2125     }
2126 
2127     #[test]
test_append_solicit_uuids()2128     fn test_append_solicit_uuids() {
2129         let mut bytes = Vec::<u8>::new();
2130         let uuid_16 = Uuid::from_string("0000fef3-0000-1000-8000-00805f9b34fb").unwrap();
2131         let uuid_32 = Uuid::from_string("00112233-0000-1000-8000-00805f9b34fb").unwrap();
2132         let uuid_128 = Uuid::from_string("00010203-0405-0607-0809-0a0b0c0d0e0f").unwrap();
2133         let uuids = vec![uuid_16, uuid_32, uuid_128];
2134         let exp_16: Vec<u8> = vec![3, 0x14, 0xf3, 0xfe];
2135         let exp_32: Vec<u8> = vec![5, 0x1f, 0x33, 0x22, 0x11, 0x0];
2136         let exp_128: Vec<u8> = vec![
2137             17, 0x15, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1,
2138             0x0,
2139         ];
2140         let exp_bytes: Vec<u8> =
2141             [exp_16.as_slice(), exp_32.as_slice(), exp_128.as_slice()].concat();
2142         AdvertiseData::append_solicit_uuids(&mut bytes, &uuids);
2143         assert_eq!(bytes, exp_bytes);
2144     }
2145 
2146     #[test]
test_append_service_data_good_id()2147     fn test_append_service_data_good_id() {
2148         let mut bytes = Vec::<u8>::new();
2149         let uuid_str = "0000fef3-0000-1000-8000-00805f9b34fb".to_string();
2150         let mut service_data = HashMap::new();
2151         let data: Vec<u8> = vec![
2152             0x4A, 0x17, 0x23, 0x41, 0x39, 0x37, 0x45, 0x11, 0x16, 0x60, 0x1D, 0xB8, 0x27, 0xA2,
2153             0xEF, 0xAA, 0xFE, 0x58, 0x04, 0x9F, 0xE3, 0x8F, 0xD0, 0x04, 0x29, 0x4F, 0xC2,
2154         ];
2155         service_data.insert(uuid_str, data.clone());
2156         let mut exp_bytes: Vec<u8> = vec![30, 0x16, 0xf3, 0xfe];
2157         exp_bytes.extend(data);
2158         AdvertiseData::append_service_data(&mut bytes, &service_data);
2159         assert_eq!(bytes, exp_bytes);
2160     }
2161 
2162     #[test]
test_append_service_data_bad_id()2163     fn test_append_service_data_bad_id() {
2164         let mut bytes = Vec::<u8>::new();
2165         let uuid_str = "fef3".to_string();
2166         let mut service_data = HashMap::new();
2167         let data: Vec<u8> = vec![
2168             0x4A, 0x17, 0x23, 0x41, 0x39, 0x37, 0x45, 0x11, 0x16, 0x60, 0x1D, 0xB8, 0x27, 0xA2,
2169             0xEF, 0xAA, 0xFE, 0x58, 0x04, 0x9F, 0xE3, 0x8F, 0xD0, 0x04, 0x29, 0x4F, 0xC2,
2170         ];
2171         service_data.insert(uuid_str, data.clone());
2172         let exp_bytes: Vec<u8> = Vec::new();
2173         AdvertiseData::append_service_data(&mut bytes, &service_data);
2174         assert_eq!(bytes, exp_bytes);
2175     }
2176 
2177     #[test]
test_append_device_name()2178     fn test_append_device_name() {
2179         let mut bytes = Vec::<u8>::new();
2180         let complete_name = "abc".to_string();
2181         let exp_bytes: Vec<u8> = vec![5, 0x9, 0x61, 0x62, 0x63, 0x0];
2182         AdvertiseData::append_device_name(&mut bytes, &complete_name);
2183         assert_eq!(bytes, exp_bytes);
2184 
2185         let mut bytes = Vec::<u8>::new();
2186         let shortened_name = "abcdefghijklmnopqrstuvwxyz7890".to_string();
2187         let exp_bytes: Vec<u8> = vec![
2188             28, 0x8, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d,
2189             0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x0,
2190         ];
2191         AdvertiseData::append_device_name(&mut bytes, &shortened_name);
2192         assert_eq!(bytes, exp_bytes);
2193     }
2194 
2195     #[test]
test_append_manufacturer_data()2196     fn test_append_manufacturer_data() {
2197         let mut bytes = Vec::<u8>::new();
2198         let manufacturer_data = HashMap::from([(0x0123_u16, vec![0, 1, 2])]);
2199         let exp_bytes: Vec<u8> = vec![6, 0xff, 0x23, 0x01, 0x0, 0x1, 0x2];
2200         AdvertiseData::append_manufacturer_data(&mut bytes, &manufacturer_data);
2201         assert_eq!(bytes, exp_bytes);
2202     }
2203 
2204     #[test]
test_append_transport_discovery_data()2205     fn test_append_transport_discovery_data() {
2206         let mut bytes = Vec::<u8>::new();
2207         let transport_discovery_data = vec![vec![0, 1, 2]];
2208         let exp_bytes: Vec<u8> = vec![0x4, 0x26, 0x0, 0x1, 0x2];
2209         AdvertiseData::append_transport_discovery_data(&mut bytes, &transport_discovery_data);
2210         assert_eq!(bytes, exp_bytes);
2211 
2212         let mut bytes = Vec::<u8>::new();
2213         let transport_discovery_data = vec![vec![1, 2, 4, 8], vec![0xa, 0xb]];
2214         let exp_bytes: Vec<u8> = vec![0x5, 0x26, 0x1, 0x2, 0x4, 0x8, 3, 0x26, 0xa, 0xb];
2215         AdvertiseData::append_transport_discovery_data(&mut bytes, &transport_discovery_data);
2216         assert_eq!(bytes, exp_bytes);
2217     }
2218 }
2219