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