Skip to content

Commit 3ea4aea

Browse files
committed
fix: improve network status monitoring
1 parent 68b41c8 commit 3ea4aea

25 files changed

+371
-277
lines changed

app/build.gradle.kts

+1-1
Original file line numberDiff line numberDiff line change
@@ -144,8 +144,8 @@ android {
144144
}
145145

146146
dependencies {
147-
148147
implementation(project(":logcatter"))
148+
implementation(project(":networkmonitor"))
149149

150150
implementation(libs.androidx.core.ktx)
151151
implementation(libs.androidx.lifecycle.runtime.ktx)

app/src/main/AndroidManifest.xml

+2-7
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,8 @@
33
xmlns:tools="http://schemas.android.com/tools">
44

55
<uses-permission android:name="android.permission.INTERNET" />
6-
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
7-
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
8-
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
9-
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
10-
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
11-
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
12-
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
6+
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
7+
138
<!--foreground service exempt android 14-->
149
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_SYSTEM_EXEMPTED" />
1510
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM"

app/src/main/java/com/zaneschepke/wireguardautotunnel/core/network/InternetConnectivityMonitor.kt

-161
This file was deleted.

app/src/main/java/com/zaneschepke/wireguardautotunnel/core/network/NetworkExtensions.kt

-16
This file was deleted.

app/src/main/java/com/zaneschepke/wireguardautotunnel/core/network/NetworkMonitor.kt

-13
This file was deleted.

app/src/main/java/com/zaneschepke/wireguardautotunnel/core/service/autotunnel/AutoTunnelService.kt

+42-43
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,42 @@
11
package com.zaneschepke.wireguardautotunnel.core.service.autotunnel
22

33
import android.content.Intent
4-
import android.net.NetworkCapabilities
54
import android.os.IBinder
65
import android.os.PowerManager
76
import androidx.core.app.ServiceCompat
87
import androidx.lifecycle.LifecycleService
98
import androidx.lifecycle.lifecycleScope
10-
import com.wireguard.android.util.RootShell
9+
import com.zaneschepke.networkmonitor.NetworkMonitor
10+
import com.zaneschepke.networkmonitor.NetworkStatus
1111
import com.zaneschepke.wireguardautotunnel.R
12-
import com.zaneschepke.wireguardautotunnel.domain.repository.AppDataRepository
13-
import com.zaneschepke.wireguardautotunnel.di.AppShell
14-
import com.zaneschepke.wireguardautotunnel.di.IoDispatcher
15-
import com.zaneschepke.wireguardautotunnel.di.MainImmediateDispatcher
16-
import com.zaneschepke.wireguardautotunnel.core.service.ServiceManager
17-
import com.zaneschepke.wireguardautotunnel.domain.state.AutoTunnelState
18-
import com.zaneschepke.wireguardautotunnel.domain.state.NetworkState
19-
import com.zaneschepke.wireguardautotunnel.core.network.InternetConnectivityMonitor
20-
import com.zaneschepke.wireguardautotunnel.core.network.NetworkMonitor
21-
import com.zaneschepke.wireguardautotunnel.domain.state.ConnectivityState
22-
import com.zaneschepke.wireguardautotunnel.domain.enums.NotificationAction
2312
import com.zaneschepke.wireguardautotunnel.core.notification.NotificationManager
2413
import com.zaneschepke.wireguardautotunnel.core.notification.WireGuardNotification
14+
import com.zaneschepke.wireguardautotunnel.core.service.ServiceManager
2515
import com.zaneschepke.wireguardautotunnel.core.tunnel.TunnelManager
16+
import com.zaneschepke.wireguardautotunnel.di.IoDispatcher
17+
import com.zaneschepke.wireguardautotunnel.di.MainImmediateDispatcher
2618
import com.zaneschepke.wireguardautotunnel.domain.entity.AppSettings
2719
import com.zaneschepke.wireguardautotunnel.domain.enums.BackendState
20+
import com.zaneschepke.wireguardautotunnel.domain.enums.NotificationAction
2821
import com.zaneschepke.wireguardautotunnel.domain.events.AutoTunnelEvent
2922
import com.zaneschepke.wireguardautotunnel.domain.events.KillSwitchEvent
23+
import com.zaneschepke.wireguardautotunnel.domain.repository.AppDataRepository
24+
import com.zaneschepke.wireguardautotunnel.domain.state.AutoTunnelState
25+
import com.zaneschepke.wireguardautotunnel.domain.state.NetworkState
3026
import com.zaneschepke.wireguardautotunnel.util.Constants
3127
import com.zaneschepke.wireguardautotunnel.util.extensions.Tunnels
32-
import com.zaneschepke.wireguardautotunnel.util.extensions.getCurrentWifiName
3328
import dagger.hilt.android.AndroidEntryPoint
3429
import kotlinx.coroutines.CompletableDeferred
3530
import kotlinx.coroutines.CoroutineDispatcher
31+
import kotlinx.coroutines.ExperimentalCoroutinesApi
3632
import kotlinx.coroutines.FlowPreview
3733
import kotlinx.coroutines.flow.Flow
3834
import kotlinx.coroutines.flow.MutableStateFlow
3935
import kotlinx.coroutines.flow.combine
4036
import kotlinx.coroutines.flow.debounce
4137
import kotlinx.coroutines.flow.distinctUntilChanged
38+
import kotlinx.coroutines.flow.flatMapLatest
39+
import kotlinx.coroutines.flow.flowOn
4240
import kotlinx.coroutines.flow.map
4341
import kotlinx.coroutines.flow.update
4442
import kotlinx.coroutines.launch
@@ -49,10 +47,6 @@ import javax.inject.Provider
4947
@AndroidEntryPoint
5048
class AutoTunnelService : LifecycleService() {
5149

52-
@Inject
53-
@AppShell
54-
lateinit var rootShell: Provider<RootShell>
55-
5650
@Inject
5751
lateinit var networkMonitor: NetworkMonitor
5852

@@ -161,49 +155,54 @@ class AutoTunnelService : LifecycleService() {
161155
}
162156
}
163157

164-
private suspend fun buildNetworkState(connectivityState: ConnectivityState): NetworkState {
158+
private fun buildNetworkState(networkStatus: NetworkStatus): NetworkState {
165159
return with(autoTunnelStateFlow.value.networkState) {
166-
val wifiName = when {
167-
connectivityState.wifiAvailable &&
168-
(wifiName == null || wifiName == Constants.UNREADABLE_SSID || networkMonitor.didWifiChangeSinceLastCapabilitiesQuery) -> {
169-
networkMonitor.getWifiCapabilities()?.let { getWifiName(it) } ?: wifiName
160+
val wifiName = when (networkStatus) {
161+
is NetworkStatus.Connected -> {
162+
networkStatus.wifiSsid
170163
}
171-
!connectivityState.wifiAvailable -> null
172-
else -> wifiName
164+
else -> null
173165
}
174166
copy(
175-
isWifiConnected = connectivityState.wifiAvailable,
176-
isMobileDataConnected = connectivityState.cellularAvailable,
177-
isEthernetConnected = isEthernetConnected,
167+
isWifiConnected = networkStatus.wifiConnected,
168+
isMobileDataConnected = networkStatus.cellularConnected,
169+
isEthernetConnected = networkStatus.ethernetConnected,
178170
wifiName = wifiName,
179171
)
180172
}
181173
}
182174

175+
@OptIn(ExperimentalCoroutinesApi::class)
183176
private fun startAutoTunnelStateJob() = lifecycleScope.launch(ioDispatcher) {
184177
combine(
185178
combineSettings(),
186-
networkMonitor.status.map {
187-
buildNetworkState(it)
188-
}.distinctUntilChanged(),
179+
appDataRepository.get().settings.flow
180+
.distinctUntilChanged { old, new -> old.isKernelEnabled == new.isKernelEnabled } // Only emit when isKernelEnabled changes
181+
.flatMapLatest { settings ->
182+
networkMonitor.getNetworkStatusFlow(true, settings.isKernelEnabled)
183+
.flowOn(ioDispatcher)
184+
.map { buildNetworkState(it) }
185+
}
186+
.distinctUntilChanged(),
189187
) { double, networkState ->
190-
AutoTunnelState(tunnelManager.activeTunnels.value, networkState, double.first, double.second)
188+
AutoTunnelState(
189+
tunnelManager.activeTunnels.value,
190+
networkState,
191+
double.first,
192+
double.second,
193+
)
191194
}.collect { state ->
192195
autoTunnelStateFlow.update {
193-
it.copy(activeTunnels = state.activeTunnels, networkState = state.networkState, settings = state.settings, tunnels = state.tunnels)
196+
it.copy(
197+
activeTunnels = state.activeTunnels,
198+
networkState = state.networkState,
199+
settings = state.settings,
200+
tunnels = state.tunnels,
201+
)
194202
}
195203
}
196204
}
197205

198-
private suspend fun getWifiName(wifiCapabilities: NetworkCapabilities): String? {
199-
val setting = appDataRepository.get().settings.get()
200-
return if (setting.isWifiNameByShellEnabled) {
201-
rootShell.get().getCurrentWifiName()
202-
} else {
203-
InternetConnectivityMonitor.getNetworkName(wifiCapabilities, this@AutoTunnelService)
204-
}
205-
}
206-
207206
private fun combineSettings(): Flow<Pair<AppSettings, Tunnels>> {
208207
return combine(
209208
appDataRepository.get().settings.flow,
@@ -240,7 +239,7 @@ class AutoTunnelService : LifecycleService() {
240239
Timber.d("Starting with debounce delay of: ${settings.debounceDelaySeconds} seconds")
241240
autoTunnelStateFlow.debounce(settings.debounceDelayMillis()).collect { watcherState ->
242241
if (watcherState == defaultState) return@collect
243-
Timber.d("New auto tunnel state emitted")
242+
Timber.d("New auto tunnel state emitted ${watcherState.networkState}")
244243
when (val event = watcherState.asAutoTunnelEvent()) {
245244
is AutoTunnelEvent.Start -> (event.tunnelConf ?: appDataRepository.get().getPrimaryOrFirstTunnel())?.let {
246245
tunnelManager.startTunnel(it)

0 commit comments

Comments
 (0)