diff --git a/service/src/main/java/com/github/kr328/clash/service/clash/module/NetworkObserveModule.kt b/service/src/main/java/com/github/kr328/clash/service/clash/module/NetworkObserveModule.kt index 1b3bf1656..094a5cc5c 100644 --- a/service/src/main/java/com/github/kr328/clash/service/clash/module/NetworkObserveModule.kt +++ b/service/src/main/java/com/github/kr328/clash/service/clash/module/NetworkObserveModule.kt @@ -1,14 +1,16 @@ package com.github.kr328.clash.service.clash.module import android.app.Service +import android.content.Intent import android.net.* -import android.os.Build +import android.os.PowerManager import androidx.core.content.getSystemService import com.github.kr328.clash.common.log.Log import com.github.kr328.clash.core.Clash import com.github.kr328.clash.service.util.resolveDns import kotlinx.coroutines.NonCancellable import kotlinx.coroutines.channels.Channel +import kotlinx.coroutines.selects.select import kotlinx.coroutines.withContext class NetworkObserveModule(service: Service) : @@ -18,23 +20,9 @@ class NetworkObserveModule(service: Service) : private val connectivity = service.getSystemService()!! private val networks: Channel = Channel(Channel.CONFLATED) 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_INTERNET) 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() private val callback = object : ConnectivityManager.NetworkCallback() { @@ -53,30 +41,70 @@ class NetworkObserveModule(service: Service) : } } - override suspend fun run() { - try { + private fun register(): Boolean { + return try { connectivity.registerNetworkCallback(request, callback) + + true } catch (e: Exception) { 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()?.isInteractive != false) { + register() } try { while (true) { - val network = networks.receive() + val quit = select { + 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 { withContext(NonCancellable) { - connectivity.unregisterNetworkCallback(callback) + unregister() Clash.notifyDnsChanged(emptyList()) }