Loading system/gd/rust/linux/stack/src/bluetooth.rs +77 −22 Original line number Original line Diff line number Diff line Loading @@ -357,7 +357,8 @@ struct BluetoothDeviceContext { /// Transport type reported by ACL connection (if completed). /// Transport type reported by ACL connection (if completed). pub acl_reported_transport: BtTransport, pub acl_reported_transport: BtTransport, pub acl_state: BtAclState, pub bredr_acl_state: BtAclState, pub ble_acl_state: BtAclState, pub bond_state: BtBondState, pub bond_state: BtBondState, pub info: BluetoothDevice, pub info: BluetoothDevice, pub last_seen: Instant, pub last_seen: Instant, Loading @@ -374,14 +375,16 @@ struct BluetoothDeviceContext { impl BluetoothDeviceContext { impl BluetoothDeviceContext { pub(crate) fn new( pub(crate) fn new( bond_state: BtBondState, bond_state: BtBondState, acl_state: BtAclState, bredr_acl_state: BtAclState, ble_acl_state: BtAclState, info: BluetoothDevice, info: BluetoothDevice, last_seen: Instant, last_seen: Instant, properties: Vec<BluetoothProperty>, properties: Vec<BluetoothProperty>, ) -> BluetoothDeviceContext { ) -> BluetoothDeviceContext { let mut device = BluetoothDeviceContext { let mut device = BluetoothDeviceContext { acl_reported_transport: BtTransport::Auto, acl_reported_transport: BtTransport::Auto, acl_state, bredr_acl_state, ble_acl_state, bond_state, bond_state, info, info, last_seen, last_seen, Loading Loading @@ -418,6 +421,59 @@ impl BluetoothDeviceContext { pub(crate) fn seen(&mut self) { pub(crate) fn seen(&mut self) { self.last_seen = Instant::now(); self.last_seen = Instant::now(); } } fn get_default_transport(&self) -> BtTransport { self.properties.get(&BtPropertyType::TypeOfDevice).map_or(BtTransport::Auto, |prop| { match prop { BluetoothProperty::TypeOfDevice(t) => match *t { BtDeviceType::Bredr => BtTransport::Bredr, BtDeviceType::Ble => BtTransport::Le, _ => BtTransport::Auto, }, _ => BtTransport::Auto, } }) } /// Check if it is connected in at least one transport. fn is_connected(&self) -> bool { self.bredr_acl_state == BtAclState::Connected || self.ble_acl_state == BtAclState::Connected } /// Set ACL state given transport. Return true if state changed. fn set_transport_state(&mut self, transport: &BtTransport, state: &BtAclState) -> bool { match (transport, self.get_default_transport()) { (t, d) if *t == BtTransport::Bredr || (*t == BtTransport::Auto && d == BtTransport::Bredr) => { if self.bredr_acl_state == *state { return false; } self.bredr_acl_state = state.clone(); } (t, d) if *t == BtTransport::Le || (*t == BtTransport::Auto && d == BtTransport::Le) => { if self.ble_acl_state == *state { return false; } self.ble_acl_state = state.clone(); } // both link transport and the default transport are Auto. _ => { warn!("Unable to decide the transport! Set current connection states bredr({:?}), ble({:?}) to {:?}", self.bredr_acl_state, self.ble_acl_state, *state); if self.bredr_acl_state == *state && self.ble_acl_state == *state { return false; } // There is no way for us to know which transport the link is referring to in this case. self.ble_acl_state = state.clone(); self.bredr_acl_state = state.clone(); return true; } }; true } } } /// Structure to track all the signals for SIGTERM. /// Structure to track all the signals for SIGTERM. Loading Loading @@ -626,7 +682,7 @@ impl Bluetooth { is_sock_listening is_sock_listening || self.remote_devices.values().any(|ctx| { || self.remote_devices.values().any(|ctx| { ctx.bond_state == BtBondState::Bonded ctx.bond_state == BtBondState::Bonded && ctx.acl_state == BtAclState::Disconnected && ctx.bredr_acl_state == BtAclState::Disconnected && ctx && ctx .properties .properties .get(&BtPropertyType::TypeOfDevice) .get(&BtPropertyType::TypeOfDevice) Loading Loading @@ -1033,7 +1089,7 @@ impl Bluetooth { pub(crate) fn get_bonded_and_connected_devices(&mut self) -> Vec<BluetoothDevice> { pub(crate) fn get_bonded_and_connected_devices(&mut self) -> Vec<BluetoothDevice> { self.remote_devices self.remote_devices .values() .values() .filter(|v| v.acl_state == BtAclState::Connected && v.bond_state == BtBondState::Bonded) .filter(|v| v.is_connected() && v.bond_state == BtBondState::Bonded) .map(|v| v.info.clone()) .map(|v| v.info.clone()) .collect() .collect() } } Loading @@ -1045,7 +1101,7 @@ impl Bluetooth { /// Gets whether a single device is connected with its address. /// Gets whether a single device is connected with its address. fn get_acl_state_by_addr(&self, addr: &RawAddress) -> bool { fn get_acl_state_by_addr(&self, addr: &RawAddress) -> bool { self.remote_devices.get(addr).map_or(false, |d| d.acl_state == BtAclState::Connected) self.remote_devices.get(addr).map_or(false, |d| d.is_connected()) } } /// Check whether remote devices are still fresh. If they're outside the /// Check whether remote devices are still fresh. If they're outside the Loading @@ -1057,9 +1113,7 @@ impl Bluetooth { // * It is currently connected. // * It is currently connected. fn is_fresh(d: &BluetoothDeviceContext, now: &Instant) -> bool { fn is_fresh(d: &BluetoothDeviceContext, now: &Instant) -> bool { let fresh_at = d.last_seen + FOUND_DEVICE_FRESHNESS; let fresh_at = d.last_seen + FOUND_DEVICE_FRESHNESS; now < &fresh_at now < &fresh_at || d.is_connected() || d.bond_state != BtBondState::NotBonded || d.acl_state == BtAclState::Connected || d.bond_state != BtBondState::NotBonded } } let now = Instant::now(); let now = Instant::now(); Loading Loading @@ -1088,7 +1142,7 @@ impl Bluetooth { } } fn send_metrics_remote_device_info(device: &BluetoothDeviceContext) { fn send_metrics_remote_device_info(device: &BluetoothDeviceContext) { if device.bond_state != BtBondState::Bonded && device.acl_state != BtAclState::Connected { if device.bond_state != BtBondState::Bonded && !device.is_connected() { return; return; } } Loading Loading @@ -1179,6 +1233,7 @@ impl Bluetooth { .or_insert(BluetoothDeviceContext::new( .or_insert(BluetoothDeviceContext::new( BtBondState::NotBonded, BtBondState::NotBonded, BtAclState::Disconnected, BtAclState::Disconnected, BtAclState::Disconnected, device_info, device_info, Instant::now(), Instant::now(), properties, properties, Loading Loading @@ -1600,6 +1655,7 @@ impl BtifBluetoothCallbacks for Bluetooth { .or_insert(BluetoothDeviceContext::new( .or_insert(BluetoothDeviceContext::new( BtBondState::Bonded, BtBondState::Bonded, BtAclState::Disconnected, BtAclState::Disconnected, BtAclState::Disconnected, BluetoothDevice::new(*addr, "".to_string()), BluetoothDevice::new(*addr, "".to_string()), Instant::now(), Instant::now(), vec![], vec![], Loading Loading @@ -1642,6 +1698,7 @@ impl BtifBluetoothCallbacks for Bluetooth { .or_insert(BluetoothDeviceContext::new( .or_insert(BluetoothDeviceContext::new( BtBondState::NotBonded, BtBondState::NotBonded, BtAclState::Disconnected, BtAclState::Disconnected, BtAclState::Disconnected, device_info, device_info, Instant::now(), Instant::now(), properties, properties, Loading Loading @@ -1808,6 +1865,7 @@ impl BtifBluetoothCallbacks for Bluetooth { let device = entry.or_insert(BluetoothDeviceContext::new( let device = entry.or_insert(BluetoothDeviceContext::new( BtBondState::Bonded, BtBondState::Bonded, BtAclState::Disconnected, BtAclState::Disconnected, BtAclState::Disconnected, BluetoothDevice::new(addr, "".to_string()), BluetoothDevice::new(addr, "".to_string()), Instant::now(), Instant::now(), vec![], vec![], Loading Loading @@ -1863,6 +1921,7 @@ impl BtifBluetoothCallbacks for Bluetooth { let device = self.remote_devices.entry(addr).or_insert(BluetoothDeviceContext::new( let device = self.remote_devices.entry(addr).or_insert(BluetoothDeviceContext::new( BtBondState::NotBonded, BtBondState::NotBonded, BtAclState::Disconnected, BtAclState::Disconnected, BtAclState::Disconnected, BluetoothDevice::new(addr, String::from("")), BluetoothDevice::new(addr, String::from("")), Instant::now(), Instant::now(), vec![], vec![], Loading Loading @@ -1960,18 +2019,18 @@ impl BtifBluetoothCallbacks for Bluetooth { let device = self.remote_devices.entry(addr).or_insert(BluetoothDeviceContext::new( let device = self.remote_devices.entry(addr).or_insert(BluetoothDeviceContext::new( BtBondState::NotBonded, BtBondState::NotBonded, BtAclState::Disconnected, BtAclState::Disconnected, BtAclState::Disconnected, BluetoothDevice::new(addr, String::from("")), BluetoothDevice::new(addr, String::from("")), Instant::now(), Instant::now(), vec![], vec![], )); )); // Only notify if there's been a change in state // Only notify if there's been a change in state if device.acl_state == state { if !device.set_transport_state(&link_type, &state) { return; return; } } let info = device.info.clone(); let info = device.info.clone(); device.acl_state = state.clone(); device.acl_reported_transport = link_type; device.acl_reported_transport = link_type; metrics::acl_connection_state_changed( metrics::acl_connection_state_changed( Loading Loading @@ -2000,9 +2059,11 @@ impl BtifBluetoothCallbacks for Bluetooth { }); }); } } BtAclState::Disconnected => { BtAclState::Disconnected => { if !device.is_connected() { self.connection_callbacks.for_all_callbacks(|callback| { self.connection_callbacks.for_all_callbacks(|callback| { callback.on_device_disconnected(info.clone()); callback.on_device_disconnected(info.clone()); }); }); } tokio::spawn(async move { tokio::spawn(async move { let _ = txl.send(Message::OnAclDisconnected(info)).await; let _ = txl.send(Message::OnAclDisconnected(info)).await; }); }); Loading Loading @@ -2559,13 +2620,7 @@ impl IBluetooth for Bluetooth { fn get_connected_devices(&self) -> Vec<BluetoothDevice> { fn get_connected_devices(&self) -> Vec<BluetoothDevice> { self.remote_devices self.remote_devices .values() .values() .filter_map(|d| { .filter_map(|d| if d.is_connected() { Some(d.info.clone()) } else { None }) if d.acl_state == BtAclState::Connected { Some(d.info.clone()) } else { None } }) .collect() .collect() } } Loading Loading
system/gd/rust/linux/stack/src/bluetooth.rs +77 −22 Original line number Original line Diff line number Diff line Loading @@ -357,7 +357,8 @@ struct BluetoothDeviceContext { /// Transport type reported by ACL connection (if completed). /// Transport type reported by ACL connection (if completed). pub acl_reported_transport: BtTransport, pub acl_reported_transport: BtTransport, pub acl_state: BtAclState, pub bredr_acl_state: BtAclState, pub ble_acl_state: BtAclState, pub bond_state: BtBondState, pub bond_state: BtBondState, pub info: BluetoothDevice, pub info: BluetoothDevice, pub last_seen: Instant, pub last_seen: Instant, Loading @@ -374,14 +375,16 @@ struct BluetoothDeviceContext { impl BluetoothDeviceContext { impl BluetoothDeviceContext { pub(crate) fn new( pub(crate) fn new( bond_state: BtBondState, bond_state: BtBondState, acl_state: BtAclState, bredr_acl_state: BtAclState, ble_acl_state: BtAclState, info: BluetoothDevice, info: BluetoothDevice, last_seen: Instant, last_seen: Instant, properties: Vec<BluetoothProperty>, properties: Vec<BluetoothProperty>, ) -> BluetoothDeviceContext { ) -> BluetoothDeviceContext { let mut device = BluetoothDeviceContext { let mut device = BluetoothDeviceContext { acl_reported_transport: BtTransport::Auto, acl_reported_transport: BtTransport::Auto, acl_state, bredr_acl_state, ble_acl_state, bond_state, bond_state, info, info, last_seen, last_seen, Loading Loading @@ -418,6 +421,59 @@ impl BluetoothDeviceContext { pub(crate) fn seen(&mut self) { pub(crate) fn seen(&mut self) { self.last_seen = Instant::now(); self.last_seen = Instant::now(); } } fn get_default_transport(&self) -> BtTransport { self.properties.get(&BtPropertyType::TypeOfDevice).map_or(BtTransport::Auto, |prop| { match prop { BluetoothProperty::TypeOfDevice(t) => match *t { BtDeviceType::Bredr => BtTransport::Bredr, BtDeviceType::Ble => BtTransport::Le, _ => BtTransport::Auto, }, _ => BtTransport::Auto, } }) } /// Check if it is connected in at least one transport. fn is_connected(&self) -> bool { self.bredr_acl_state == BtAclState::Connected || self.ble_acl_state == BtAclState::Connected } /// Set ACL state given transport. Return true if state changed. fn set_transport_state(&mut self, transport: &BtTransport, state: &BtAclState) -> bool { match (transport, self.get_default_transport()) { (t, d) if *t == BtTransport::Bredr || (*t == BtTransport::Auto && d == BtTransport::Bredr) => { if self.bredr_acl_state == *state { return false; } self.bredr_acl_state = state.clone(); } (t, d) if *t == BtTransport::Le || (*t == BtTransport::Auto && d == BtTransport::Le) => { if self.ble_acl_state == *state { return false; } self.ble_acl_state = state.clone(); } // both link transport and the default transport are Auto. _ => { warn!("Unable to decide the transport! Set current connection states bredr({:?}), ble({:?}) to {:?}", self.bredr_acl_state, self.ble_acl_state, *state); if self.bredr_acl_state == *state && self.ble_acl_state == *state { return false; } // There is no way for us to know which transport the link is referring to in this case. self.ble_acl_state = state.clone(); self.bredr_acl_state = state.clone(); return true; } }; true } } } /// Structure to track all the signals for SIGTERM. /// Structure to track all the signals for SIGTERM. Loading Loading @@ -626,7 +682,7 @@ impl Bluetooth { is_sock_listening is_sock_listening || self.remote_devices.values().any(|ctx| { || self.remote_devices.values().any(|ctx| { ctx.bond_state == BtBondState::Bonded ctx.bond_state == BtBondState::Bonded && ctx.acl_state == BtAclState::Disconnected && ctx.bredr_acl_state == BtAclState::Disconnected && ctx && ctx .properties .properties .get(&BtPropertyType::TypeOfDevice) .get(&BtPropertyType::TypeOfDevice) Loading Loading @@ -1033,7 +1089,7 @@ impl Bluetooth { pub(crate) fn get_bonded_and_connected_devices(&mut self) -> Vec<BluetoothDevice> { pub(crate) fn get_bonded_and_connected_devices(&mut self) -> Vec<BluetoothDevice> { self.remote_devices self.remote_devices .values() .values() .filter(|v| v.acl_state == BtAclState::Connected && v.bond_state == BtBondState::Bonded) .filter(|v| v.is_connected() && v.bond_state == BtBondState::Bonded) .map(|v| v.info.clone()) .map(|v| v.info.clone()) .collect() .collect() } } Loading @@ -1045,7 +1101,7 @@ impl Bluetooth { /// Gets whether a single device is connected with its address. /// Gets whether a single device is connected with its address. fn get_acl_state_by_addr(&self, addr: &RawAddress) -> bool { fn get_acl_state_by_addr(&self, addr: &RawAddress) -> bool { self.remote_devices.get(addr).map_or(false, |d| d.acl_state == BtAclState::Connected) self.remote_devices.get(addr).map_or(false, |d| d.is_connected()) } } /// Check whether remote devices are still fresh. If they're outside the /// Check whether remote devices are still fresh. If they're outside the Loading @@ -1057,9 +1113,7 @@ impl Bluetooth { // * It is currently connected. // * It is currently connected. fn is_fresh(d: &BluetoothDeviceContext, now: &Instant) -> bool { fn is_fresh(d: &BluetoothDeviceContext, now: &Instant) -> bool { let fresh_at = d.last_seen + FOUND_DEVICE_FRESHNESS; let fresh_at = d.last_seen + FOUND_DEVICE_FRESHNESS; now < &fresh_at now < &fresh_at || d.is_connected() || d.bond_state != BtBondState::NotBonded || d.acl_state == BtAclState::Connected || d.bond_state != BtBondState::NotBonded } } let now = Instant::now(); let now = Instant::now(); Loading Loading @@ -1088,7 +1142,7 @@ impl Bluetooth { } } fn send_metrics_remote_device_info(device: &BluetoothDeviceContext) { fn send_metrics_remote_device_info(device: &BluetoothDeviceContext) { if device.bond_state != BtBondState::Bonded && device.acl_state != BtAclState::Connected { if device.bond_state != BtBondState::Bonded && !device.is_connected() { return; return; } } Loading Loading @@ -1179,6 +1233,7 @@ impl Bluetooth { .or_insert(BluetoothDeviceContext::new( .or_insert(BluetoothDeviceContext::new( BtBondState::NotBonded, BtBondState::NotBonded, BtAclState::Disconnected, BtAclState::Disconnected, BtAclState::Disconnected, device_info, device_info, Instant::now(), Instant::now(), properties, properties, Loading Loading @@ -1600,6 +1655,7 @@ impl BtifBluetoothCallbacks for Bluetooth { .or_insert(BluetoothDeviceContext::new( .or_insert(BluetoothDeviceContext::new( BtBondState::Bonded, BtBondState::Bonded, BtAclState::Disconnected, BtAclState::Disconnected, BtAclState::Disconnected, BluetoothDevice::new(*addr, "".to_string()), BluetoothDevice::new(*addr, "".to_string()), Instant::now(), Instant::now(), vec![], vec![], Loading Loading @@ -1642,6 +1698,7 @@ impl BtifBluetoothCallbacks for Bluetooth { .or_insert(BluetoothDeviceContext::new( .or_insert(BluetoothDeviceContext::new( BtBondState::NotBonded, BtBondState::NotBonded, BtAclState::Disconnected, BtAclState::Disconnected, BtAclState::Disconnected, device_info, device_info, Instant::now(), Instant::now(), properties, properties, Loading Loading @@ -1808,6 +1865,7 @@ impl BtifBluetoothCallbacks for Bluetooth { let device = entry.or_insert(BluetoothDeviceContext::new( let device = entry.or_insert(BluetoothDeviceContext::new( BtBondState::Bonded, BtBondState::Bonded, BtAclState::Disconnected, BtAclState::Disconnected, BtAclState::Disconnected, BluetoothDevice::new(addr, "".to_string()), BluetoothDevice::new(addr, "".to_string()), Instant::now(), Instant::now(), vec![], vec![], Loading Loading @@ -1863,6 +1921,7 @@ impl BtifBluetoothCallbacks for Bluetooth { let device = self.remote_devices.entry(addr).or_insert(BluetoothDeviceContext::new( let device = self.remote_devices.entry(addr).or_insert(BluetoothDeviceContext::new( BtBondState::NotBonded, BtBondState::NotBonded, BtAclState::Disconnected, BtAclState::Disconnected, BtAclState::Disconnected, BluetoothDevice::new(addr, String::from("")), BluetoothDevice::new(addr, String::from("")), Instant::now(), Instant::now(), vec![], vec![], Loading Loading @@ -1960,18 +2019,18 @@ impl BtifBluetoothCallbacks for Bluetooth { let device = self.remote_devices.entry(addr).or_insert(BluetoothDeviceContext::new( let device = self.remote_devices.entry(addr).or_insert(BluetoothDeviceContext::new( BtBondState::NotBonded, BtBondState::NotBonded, BtAclState::Disconnected, BtAclState::Disconnected, BtAclState::Disconnected, BluetoothDevice::new(addr, String::from("")), BluetoothDevice::new(addr, String::from("")), Instant::now(), Instant::now(), vec![], vec![], )); )); // Only notify if there's been a change in state // Only notify if there's been a change in state if device.acl_state == state { if !device.set_transport_state(&link_type, &state) { return; return; } } let info = device.info.clone(); let info = device.info.clone(); device.acl_state = state.clone(); device.acl_reported_transport = link_type; device.acl_reported_transport = link_type; metrics::acl_connection_state_changed( metrics::acl_connection_state_changed( Loading Loading @@ -2000,9 +2059,11 @@ impl BtifBluetoothCallbacks for Bluetooth { }); }); } } BtAclState::Disconnected => { BtAclState::Disconnected => { if !device.is_connected() { self.connection_callbacks.for_all_callbacks(|callback| { self.connection_callbacks.for_all_callbacks(|callback| { callback.on_device_disconnected(info.clone()); callback.on_device_disconnected(info.clone()); }); }); } tokio::spawn(async move { tokio::spawn(async move { let _ = txl.send(Message::OnAclDisconnected(info)).await; let _ = txl.send(Message::OnAclDisconnected(info)).await; }); }); Loading Loading @@ -2559,13 +2620,7 @@ impl IBluetooth for Bluetooth { fn get_connected_devices(&self) -> Vec<BluetoothDevice> { fn get_connected_devices(&self) -> Vec<BluetoothDevice> { self.remote_devices self.remote_devices .values() .values() .filter_map(|d| { .filter_map(|d| if d.is_connected() { Some(d.info.clone()) } else { None }) if d.acl_state == BtAclState::Connected { Some(d.info.clone()) } else { None } }) .collect() .collect() } } Loading