mirror of
https://gitlab.alpinelinux.org/alpine/aports.git
synced 2026-01-02 23:31:34 +01:00
This patch was merged upstream but isn't in a release yet. Without this, the panel keeps the CPU very busy when bluetooth is disabled. https://github.com/pop-os/cosmic-applets/pull/933
200 lines
8.7 KiB
Diff
200 lines
8.7 KiB
Diff
From 400418f52f1bc03cb7513b361a6c753cec55ed2c Mon Sep 17 00:00:00 2001
|
|
From: Ashley Wulber <ashley@system76.com>
|
|
Date: Tue, 6 May 2025 19:15:28 -0400
|
|
Subject: [PATCH] fix(bluetooth): cpu usage
|
|
|
|
---
|
|
cosmic-applet-bluetooth/src/app.rs | 16 ++++++-
|
|
cosmic-applet-bluetooth/src/bluetooth.rs | 55 +++++++++++++++++++-----
|
|
2 files changed, 58 insertions(+), 13 deletions(-)
|
|
|
|
diff --git a/cosmic-applet-bluetooth/src/app.rs b/cosmic-applet-bluetooth/src/app.rs
|
|
index eb03ddb7..a3798edd 100644
|
|
--- a/cosmic-applet-bluetooth/src/app.rs
|
|
+++ b/cosmic-applet-bluetooth/src/app.rs
|
|
@@ -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();
|
|
diff --git a/cosmic-applet-bluetooth/src/bluetooth.rs b/cosmic-applet-bluetooth/src/bluetooth.rs
|
|
index 762d0919..549f654b 100644
|
|
--- a/cosmic-applet-bluetooth/src/bluetooth.rs
|
|
+++ b/cosmic-applet-bluetooth/src/bluetooth.rs
|
|
@@ -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());
|