mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2026-10-21 18:54:01 -04:00
network(networkmanager): rebuild the Wi-Fi list once per scan (#3818)
This commit is contained in:
@@ -4,6 +4,7 @@ import (
|
||||
"fmt"
|
||||
"maps"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/AvengeMedia/DankMaterialShell/core/internal/log"
|
||||
"github.com/Wifx/gonetworkmanager/v2"
|
||||
@@ -80,6 +81,10 @@ type NetworkManagerBackend struct {
|
||||
sigWG sync.WaitGroup
|
||||
stopChan chan struct{}
|
||||
|
||||
wifiRefreshTimer *time.Timer
|
||||
wifiRefreshMu sync.Mutex
|
||||
wifiRefreshWG sync.WaitGroup
|
||||
|
||||
secretAgent *SecretAgent
|
||||
promptBroker PromptBroker
|
||||
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package network
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/AvengeMedia/DankMaterialShell/core/internal/log"
|
||||
"github.com/Wifx/gonetworkmanager/v2"
|
||||
"github.com/godbus/dbus/v5"
|
||||
@@ -10,6 +12,8 @@ const (
|
||||
dbusNMSettingsPath = "/org/freedesktop/NetworkManager/Settings"
|
||||
dbusNMSettingsInterface = "org.freedesktop.NetworkManager.Settings"
|
||||
dbusNMSettingsConnectionInterface = "org.freedesktop.NetworkManager.Settings.Connection"
|
||||
|
||||
wifiNetworksUpdateDelay = 500 * time.Millisecond
|
||||
)
|
||||
|
||||
func (b *NetworkManagerBackend) startSignalPump() error {
|
||||
@@ -287,7 +291,8 @@ func (b *NetworkManagerBackend) stopSignalPump() {
|
||||
}
|
||||
|
||||
b.sigWG.Wait()
|
||||
|
||||
b.cancelWiFiNetworksUpdate()
|
||||
b.wifiRefreshWG.Wait()
|
||||
}
|
||||
|
||||
func (b *NetworkManagerBackend) handleDBusSignal(sig *dbus.Signal) {
|
||||
@@ -537,7 +542,7 @@ func (b *NetworkManagerBackend) handleWiFiChange(changes map[string]dbus.Variant
|
||||
needsStateUpdate = true
|
||||
needsNetworkUpdate = true
|
||||
case "AccessPoints":
|
||||
needsNetworkUpdate = true
|
||||
b.scheduleWiFiNetworksUpdate()
|
||||
default:
|
||||
continue
|
||||
}
|
||||
@@ -547,6 +552,7 @@ func (b *NetworkManagerBackend) handleWiFiChange(changes map[string]dbus.Variant
|
||||
b.updateWiFiState()
|
||||
}
|
||||
if needsNetworkUpdate {
|
||||
b.cancelWiFiNetworksUpdate()
|
||||
b.updateWiFiNetworks()
|
||||
}
|
||||
if needsStateUpdate || needsNetworkUpdate {
|
||||
@@ -556,6 +562,41 @@ func (b *NetworkManagerBackend) handleWiFiChange(changes map[string]dbus.Variant
|
||||
}
|
||||
}
|
||||
|
||||
// A scan announces each new access point on its own, so rebuild the list
|
||||
// once per burst instead of once per access point.
|
||||
func (b *NetworkManagerBackend) scheduleWiFiNetworksUpdate() {
|
||||
b.wifiRefreshMu.Lock()
|
||||
defer b.wifiRefreshMu.Unlock()
|
||||
|
||||
if b.wifiRefreshTimer != nil {
|
||||
return
|
||||
}
|
||||
b.wifiRefreshWG.Add(1)
|
||||
b.wifiRefreshTimer = time.AfterFunc(wifiNetworksUpdateDelay, func() {
|
||||
defer b.wifiRefreshWG.Done()
|
||||
|
||||
b.wifiRefreshMu.Lock()
|
||||
b.wifiRefreshTimer = nil
|
||||
b.wifiRefreshMu.Unlock()
|
||||
|
||||
b.updateWiFiNetworks()
|
||||
if b.onStateChange != nil {
|
||||
b.onStateChange()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func (b *NetworkManagerBackend) cancelWiFiNetworksUpdate() {
|
||||
b.wifiRefreshMu.Lock()
|
||||
defer b.wifiRefreshMu.Unlock()
|
||||
|
||||
if b.wifiRefreshTimer == nil || !b.wifiRefreshTimer.Stop() {
|
||||
return
|
||||
}
|
||||
b.wifiRefreshTimer = nil
|
||||
b.wifiRefreshWG.Done()
|
||||
}
|
||||
|
||||
func (b *NetworkManagerBackend) handleAccessPointChange(changes map[string]dbus.Variant) {
|
||||
_, hasStrength := changes["Strength"]
|
||||
if !hasStrength {
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
package network
|
||||
|
||||
import (
|
||||
"sync/atomic"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
mock_gonetworkmanager "github.com/AvengeMedia/DankMaterialShell/core/internal/mocks/github.com/Wifx/gonetworkmanager/v2"
|
||||
"github.com/Wifx/gonetworkmanager/v2"
|
||||
@@ -98,3 +100,33 @@ func TestNetworkManagerBackend_HandleDeviceChange_UnmanagedRefreshesHotspotState
|
||||
defer backend.stateMutex.RUnlock()
|
||||
assert.False(t, backend.state.HotspotAvailable, "availability must be recomputed when the only AP-capable radio becomes unmanaged")
|
||||
}
|
||||
|
||||
func TestNetworkManagerBackend_HandleWiFiChange_CoalescesAccessPointBurst(t *testing.T) {
|
||||
mockNM := mock_gonetworkmanager.NewMockNetworkManager(t)
|
||||
mockWiFi := mock_gonetworkmanager.NewMockDeviceWireless(t)
|
||||
|
||||
backend, err := NewNetworkManagerBackend(mockNM)
|
||||
assert.NoError(t, err)
|
||||
backend.settings = emptySettingsMock(t)
|
||||
backend.wifiDevice = mockWiFi
|
||||
backend.wifiDev = mockWiFi
|
||||
|
||||
var stateChangeCalls atomic.Int32
|
||||
backend.onStateChange = func() {
|
||||
stateChangeCalls.Add(1)
|
||||
}
|
||||
|
||||
mockWiFi.EXPECT().GetAccessPoints().Return([]gonetworkmanager.AccessPoint{}, nil).Once()
|
||||
|
||||
changes := map[string]dbus.Variant{
|
||||
"AccessPoints": dbus.MakeVariant([]dbus.ObjectPath{}),
|
||||
}
|
||||
for range 5 {
|
||||
backend.handleWiFiChange(changes)
|
||||
}
|
||||
assert.Zero(t, stateChangeCalls.Load(), "the list must not be rebuilt per access point")
|
||||
|
||||
assert.Eventually(t, func() bool {
|
||||
return stateChangeCalls.Load() == 1
|
||||
}, 4*wifiNetworksUpdateDelay, 10*time.Millisecond)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user