fix(bluetooth): cpu usage
This commit is contained in:
parent
9eb4053d31
commit
b6bb982f2d
2 changed files with 58 additions and 13 deletions
|
|
@ -1,7 +1,7 @@
|
|||
// Copyright 2023 System76 <info@system76.com>
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
|
||||
use crate::bluetooth::{BluerDeviceStatus, BluerRequest, BluerState, DeviceProperty};
|
||||
use crate::bluetooth::{set_tick, BluerDeviceStatus, BluerRequest, BluerState, DeviceProperty};
|
||||
use cosmic::{
|
||||
app,
|
||||
applet::token::subscription::{activation_token_subscription, TokenRequest, TokenUpdate},
|
||||
|
|
@ -24,6 +24,7 @@ use cosmic::{
|
|||
Element, Task,
|
||||
};
|
||||
use cosmic_time::{anim, chain, id, once_cell::sync::Lazy, Instant, Timeline};
|
||||
use futures::FutureExt;
|
||||
use std::{collections::HashMap, time::Duration};
|
||||
use tokio::sync::mpsc::Sender;
|
||||
|
||||
|
|
@ -112,7 +113,13 @@ impl cosmic::Application for CosmicBluetoothApplet {
|
|||
match message {
|
||||
Message::TogglePopup => {
|
||||
if let Some(p) = self.popup.take() {
|
||||
return destroy_popup(p);
|
||||
return Task::batch(vec![
|
||||
destroy_popup(p),
|
||||
cosmic::task::future(
|
||||
set_tick(Duration::from_secs(10))
|
||||
.map(|_| cosmic::Action::App(Message::Ignore)),
|
||||
),
|
||||
]);
|
||||
} else {
|
||||
// TODO request update of state maybe
|
||||
let new_id = window::Id::unique();
|
||||
|
|
@ -138,6 +145,8 @@ impl cosmic::Application for CosmicBluetoothApplet {
|
|||
|_| cosmic::action::app(Message::Ignore),
|
||||
),
|
||||
get_popup(popup_settings),
|
||||
cosmic::task::future(set_tick(Duration::from_secs(3)))
|
||||
.map(|_: ()| cosmic::Action::App(Message::Ignore)),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
|
@ -286,6 +295,9 @@ impl cosmic::Application for CosmicBluetoothApplet {
|
|||
if Some(id) == self.popup {
|
||||
self.popup = None;
|
||||
}
|
||||
return cosmic::task::future(
|
||||
set_tick(Duration::from_secs(10)).map(|_| cosmic::Action::App(Message::Ignore)),
|
||||
);
|
||||
}
|
||||
Message::OpenSettings => {
|
||||
let exec = "cosmic-settings bluetooth".to_string();
|
||||
|
|
|
|||
|
|
@ -1,7 +1,14 @@
|
|||
// Copyright 2023 System76 <info@system76.com>
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
|
||||
use std::{collections::HashMap, fmt::Debug, hash::Hash, mem, sync::Arc, time::Duration};
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
fmt::Debug,
|
||||
hash::Hash,
|
||||
mem,
|
||||
sync::{Arc, LazyLock},
|
||||
time::Duration,
|
||||
};
|
||||
|
||||
pub use bluer::DeviceProperty;
|
||||
use bluer::{
|
||||
|
|
@ -24,11 +31,26 @@ use tokio::{
|
|||
spawn,
|
||||
sync::{
|
||||
mpsc::{channel, Receiver, Sender},
|
||||
Mutex,
|
||||
Mutex, RwLock,
|
||||
},
|
||||
task::JoinHandle,
|
||||
};
|
||||
|
||||
static TICK: LazyLock<RwLock<Duration>> = LazyLock::new(|| RwLock::new(Duration::from_secs(10)));
|
||||
|
||||
pub async fn set_tick(duration: Duration) {
|
||||
let mut guard = TICK.write().await;
|
||||
*guard = duration;
|
||||
}
|
||||
|
||||
pub async fn tick(interval: &mut tokio::time::Interval) {
|
||||
let guard = TICK.read().await;
|
||||
if *guard != interval.period() {
|
||||
*interval = tokio::time::interval(*guard);
|
||||
interval.set_missed_tick_behavior(tokio::time::MissedTickBehavior::Skip);
|
||||
}
|
||||
interval.tick().await;
|
||||
}
|
||||
// Copied from https://github.com/bluez/bluez/blob/39467578207889fd015775cbe81a3db9dd26abea/src/dbus-common.c#L53
|
||||
#[inline]
|
||||
fn device_type_to_icon(device_type: &str) -> &'static str {
|
||||
|
|
@ -68,8 +90,10 @@ pub fn bluetooth_subscription<I: 'static + Hash + Copy + Send + Sync + Debug>(
|
|||
}
|
||||
|
||||
retry_count = retry_count.saturating_add(1);
|
||||
_ = tokio::time::sleep(Duration::from_millis(2_u64.saturating_pow(retry_count)))
|
||||
.await;
|
||||
_ = tokio::time::sleep(Duration::from_millis(
|
||||
2_u64.saturating_pow(retry_count).max(68719476734),
|
||||
))
|
||||
.await;
|
||||
};
|
||||
|
||||
let state = bluer_state(&session_state.adapter).await;
|
||||
|
|
@ -116,8 +140,8 @@ pub fn bluetooth_subscription<I: 'static + Hash + Copy + Send + Sync + Debug>(
|
|||
_ = output.send(message).await;
|
||||
};
|
||||
|
||||
let mut interval = tokio::time::interval(Duration::from_secs(1));
|
||||
|
||||
let mut interval = tokio::time::interval(Duration::from_secs(10));
|
||||
interval.set_missed_tick_behavior(tokio::time::MissedTickBehavior::Skip);
|
||||
loop {
|
||||
let Some(mut session_rx) = session_state.rx.take() else {
|
||||
break;
|
||||
|
|
@ -126,8 +150,13 @@ pub fn bluetooth_subscription<I: 'static + Hash + Copy + Send + Sync + Debug>(
|
|||
if let Some(event) = session_rx.recv().await {
|
||||
event_handler(event).await;
|
||||
// Consume any additional available events.
|
||||
let mut count = 0;
|
||||
while let Some(event) = session_rx.try_recv().ok() {
|
||||
event_handler(event).await;
|
||||
count += 1;
|
||||
if count == 100 {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
|
|
@ -531,10 +560,11 @@ impl BluerSessionState {
|
|||
let wake_up_discover_tx = self.wake_up_discover_tx.clone();
|
||||
let _handle: JoinHandle<anyhow::Result<()>> = spawn(async move {
|
||||
let mut status = adapter_clone.is_powered().await.unwrap_or_default();
|
||||
let mut interval = tokio::time::interval(Duration::from_secs(3));
|
||||
let mut interval = tokio::time::interval(Duration::from_secs(10));
|
||||
interval.set_missed_tick_behavior(tokio::time::MissedTickBehavior::Skip);
|
||||
let mut devices = Vec::new();
|
||||
loop {
|
||||
interval.tick().await;
|
||||
tick(&mut interval).await;
|
||||
let new_status = adapter_clone.is_powered().await.unwrap_or_default();
|
||||
devices = build_device_list(devices, &adapter_clone).await;
|
||||
if new_status != status {
|
||||
|
|
@ -569,19 +599,23 @@ impl BluerSessionState {
|
|||
let _monitor_devices: tokio::task::JoinHandle<Result<(), anyhow::Error>> =
|
||||
spawn(async move {
|
||||
let mut devices: Vec<BluerDevice> = Vec::new();
|
||||
let mut interval = tokio::time::interval(Duration::from_secs(1));
|
||||
interval.set_missed_tick_behavior(tokio::time::MissedTickBehavior::Skip);
|
||||
|
||||
loop {
|
||||
interval.tick().await;
|
||||
let wakeup_fut = wake_up.recv();
|
||||
|
||||
// Listens for process changes and builds edvice lists.
|
||||
let listener_fut = async {
|
||||
let mut new_devices = Vec::new();
|
||||
let mut interval = tokio::time::interval(Duration::from_secs(1));
|
||||
let mut interval = tokio::time::interval(Duration::from_secs(10));
|
||||
interval.set_missed_tick_behavior(tokio::time::MissedTickBehavior::Skip);
|
||||
let mut change_stream =
|
||||
match adapter_clone.discover_devices_with_changes().await {
|
||||
Ok(stream) => stream,
|
||||
Err(_) => {
|
||||
interval.tick().await;
|
||||
tick(&mut interval).await;
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
|
@ -768,7 +802,6 @@ async fn bluer_state(adapter: &Adapter) -> BluerState {
|
|||
#[inline(never)]
|
||||
async fn build_device_list(mut devices: Vec<BluerDevice>, adapter: &Adapter) -> Vec<BluerDevice> {
|
||||
let addrs = adapter.device_addresses().await.unwrap_or_default();
|
||||
|
||||
devices.clear();
|
||||
if addrs.len() > devices.capacity() {
|
||||
devices.reserve(addrs.len() - devices.capacity());
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue