diff --git a/README.md b/README.md index 746c2284..cc7f99e4 100644 --- a/README.md +++ b/README.md @@ -77,6 +77,7 @@ Default settings are picked to suit general use cases and maximize compatibility but might still be bugged on devices heavily modified by OEM and/or carriers. Sometimes auto fallbacks to Poll. - Poll: (default) Update network information manually every second. Least battery efficient but it should work on most devices. Recommended to switch to other modes if possible. + - Poll with root: Same as Poll but polling is done using a root shell. ## Q & A diff --git a/mobile/src/main/java/be/mygod/vpnhotspot/net/monitor/IpMonitor.kt b/mobile/src/main/java/be/mygod/vpnhotspot/net/monitor/IpMonitor.kt index 6ec8c373..5ba6aadb 100644 --- a/mobile/src/main/java/be/mygod/vpnhotspot/net/monitor/IpMonitor.kt +++ b/mobile/src/main/java/be/mygod/vpnhotspot/net/monitor/IpMonitor.kt @@ -5,6 +5,7 @@ import android.system.OsConstants import be.mygod.vpnhotspot.App.Companion.app import be.mygod.vpnhotspot.DebugHelper import be.mygod.vpnhotspot.R +import be.mygod.vpnhotspot.util.RootSession import be.mygod.vpnhotspot.widget.SmartSnackbar import timber.log.Timber import java.io.IOException @@ -17,10 +18,11 @@ import kotlin.concurrent.thread abstract class IpMonitor : Runnable { companion object { const val KEY = "service.ipMonitor" + private val currentMode get() = Mode.valueOf(app.pref.getString(KEY, Mode.Poll.toString()) ?: "") } - enum class Mode { - Monitor, MonitorRoot, Poll + enum class Mode(val isMonitor: Boolean = false) { + Monitor(true), MonitorRoot(true), Poll, PollRoot } private class FlushFailure : RuntimeException() @@ -66,8 +68,8 @@ abstract class IpMonitor : Runnable { init { thread(name = "${javaClass.simpleName}-input") { - val mode = Mode.valueOf(app.pref.getString(KEY, Mode.Poll.toString()) ?: "") - if (mode != Mode.Poll) { + val mode = currentMode + if (mode.isMonitor) { if (mode != Mode.MonitorRoot) { // monitor may get rejected by SELinux enforcing handleProcess(ProcessBuilder("ip", "monitor", monitoredObject)) @@ -85,7 +87,7 @@ abstract class IpMonitor : Runnable { fun flush() = thread(name = "${javaClass.simpleName}-flush") { run() } - override fun run() { + private fun poll() { val process = ProcessBuilder("ip", monitoredObject) .redirectErrorStream(true) .start() @@ -101,6 +103,26 @@ abstract class IpMonitor : Runnable { process.inputStream.bufferedReader().useLines(this::processLines) } + override fun run() { + if (currentMode == Mode.Poll) try { + return poll() + } catch (e: IOException) { + DebugHelper.logEvent("ip_poll_failure") + Timber.d(e) + } + try { + val command = "ip $monitoredObject" + RootSession.use { + val result = it.execQuiet(command) + RootSession.checkOutput(command, result, false) + processLines(result.out.asSequence()) + } + } catch (e: RuntimeException) { + DebugHelper.logEvent("ip_su_poll_failure") + Timber.w(e) + } + } + fun destroy() { destroyed = true monitor?.destroy() diff --git a/mobile/src/main/res/values-zh-rCN/strings.xml b/mobile/src/main/res/values-zh-rCN/strings.xml index 08823872..31de0846 100644 --- a/mobile/src/main/res/values-zh-rCN/strings.xml +++ b/mobile/src/main/res/values-zh-rCN/strings.xml @@ -100,6 +100,7 @@ Netlink 监听 Netlink 监听 (root) 轮询 + 轮询 (root) 上游网络接口 自动检测系统 VPN 清理/重新应用路由规则 diff --git a/mobile/src/main/res/values/arrays.xml b/mobile/src/main/res/values/arrays.xml index de210ed6..2621de2d 100644 --- a/mobile/src/main/res/values/arrays.xml +++ b/mobile/src/main/res/values/arrays.xml @@ -26,10 +26,12 @@ @string/settings_service_ip_monitor_monitor @string/settings_service_ip_monitor_monitor_root @string/settings_service_ip_monitor_poll + @string/settings_service_ip_monitor_poll_root Monitor MonitorRoot Poll + PollRoot diff --git a/mobile/src/main/res/values/strings.xml b/mobile/src/main/res/values/strings.xml index c49a9294..1938576a 100644 --- a/mobile/src/main/res/values/strings.xml +++ b/mobile/src/main/res/values/strings.xml @@ -106,6 +106,7 @@ Netlink monitor Netlink monitor with root Poll + Poll with root Upstream network interface Auto detect system VPN Enable DHCP workaround