Improve: disable network observer on screen off

This commit is contained in:
kr328 2021-11-16 20:23:54 +08:00
parent a3686c16d4
commit c7cb1dab38

View File

@ -1,14 +1,16 @@
package com.github.kr328.clash.service.clash.module package com.github.kr328.clash.service.clash.module
import android.app.Service import android.app.Service
import android.content.Intent
import android.net.* import android.net.*
import android.os.Build import android.os.PowerManager
import androidx.core.content.getSystemService import androidx.core.content.getSystemService
import com.github.kr328.clash.common.log.Log import com.github.kr328.clash.common.log.Log
import com.github.kr328.clash.core.Clash import com.github.kr328.clash.core.Clash
import com.github.kr328.clash.service.util.resolveDns import com.github.kr328.clash.service.util.resolveDns
import kotlinx.coroutines.NonCancellable import kotlinx.coroutines.NonCancellable
import kotlinx.coroutines.channels.Channel import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.selects.select
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
class NetworkObserveModule(service: Service) : class NetworkObserveModule(service: Service) :
@ -18,23 +20,9 @@ class NetworkObserveModule(service: Service) :
private val connectivity = service.getSystemService<ConnectivityManager>()!! private val connectivity = service.getSystemService<ConnectivityManager>()!!
private val networks: Channel<Network?> = Channel(Channel.CONFLATED) private val networks: Channel<Network?> = Channel(Channel.CONFLATED)
private val request = NetworkRequest.Builder().apply { private val request = NetworkRequest.Builder().apply {
addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
addTransportType(NetworkCapabilities.TRANSPORT_BLUETOOTH)
addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
addTransportType(NetworkCapabilities.TRANSPORT_ETHERNET)
addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN) addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN)
addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED) addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)
if (Build.VERSION.SDK_INT >= 26)
addTransportType(NetworkCapabilities.TRANSPORT_WIFI_AWARE)
if (Build.VERSION.SDK_INT >= 27)
addTransportType(NetworkCapabilities.TRANSPORT_LOWPAN)
if (Build.VERSION.SDK_INT >= 31)
addTransportType(NetworkCapabilities.TRANSPORT_USB)
if (Build.VERSION.SDK_INT == 23) { // workarounds for OEM bugs
removeCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED)
removeCapability(NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL)
}
}.build() }.build()
private val callback = object : ConnectivityManager.NetworkCallback() { private val callback = object : ConnectivityManager.NetworkCallback() {
@ -53,30 +41,70 @@ class NetworkObserveModule(service: Service) :
} }
} }
override suspend fun run() { private fun register(): Boolean {
try { return try {
connectivity.registerNetworkCallback(request, callback) connectivity.registerNetworkCallback(request, callback)
true
} catch (e: Exception) { } catch (e: Exception) {
Log.w("Observe network changed: $e", e) Log.w("Observe network changed: $e", e)
return false
}
}
private fun unregister(): Boolean {
try {
connectivity.unregisterNetworkCallback(callback)
} catch (e: Exception) {
// ignored
}
return false
}
override suspend fun run() {
val screenToggle = receiveBroadcast(false, Channel.CONFLATED) {
addAction(Intent.ACTION_SCREEN_ON)
addAction(Intent.ACTION_SCREEN_OFF)
}
if (service.getSystemService<PowerManager>()?.isInteractive != false) {
register()
} }
try { try {
while (true) { while (true) {
val network = networks.receive() val quit = select<Boolean> {
screenToggle.onReceive {
when (it.action) {
Intent.ACTION_SCREEN_ON ->
register()
Intent.ACTION_SCREEN_OFF ->
unregister()
else ->
false
}
}
networks.onReceive {
val dns = connectivity.resolveDns(it)
val dns = connectivity.resolveDns(network) Clash.notifyDnsChanged(dns)
Clash.notifyDnsChanged(dns) Log.d("Network changed, system dns = $dns")
Log.d("Network changed, system dns = $dns") enqueueEvent(NetworkChanged(it))
enqueueEvent(NetworkChanged(network)) false
}
}
if (quit) {
return
}
} }
} finally { } finally {
withContext(NonCancellable) { withContext(NonCancellable) {
connectivity.unregisterNetworkCallback(callback) unregister()
Clash.notifyDnsChanged(emptyList()) Clash.notifyDnsChanged(emptyList())
} }