Support auto start services

Fixes #96.
This commit is contained in:
Mygod
2021-10-10 17:08:16 -04:00
parent 79422a05fd
commit aee1a45eba
13 changed files with 153 additions and 29 deletions

View File

@@ -1,8 +1,10 @@
package be.mygod.vpnhotspot
import android.content.Context
import android.content.Intent
import android.os.Build
import androidx.annotation.RequiresApi
import androidx.core.content.ContextCompat
import be.mygod.vpnhotspot.App.Companion.app
import be.mygod.vpnhotspot.net.Routing
import be.mygod.vpnhotspot.net.TetheringManager
@@ -10,6 +12,7 @@ import be.mygod.vpnhotspot.net.monitor.IpNeighbourMonitor
import be.mygod.vpnhotspot.util.Event0
import be.mygod.vpnhotspot.widget.SmartSnackbar
import kotlinx.coroutines.*
import kotlinx.parcelize.Parcelize
import timber.log.Timber
import java.util.concurrent.ConcurrentHashMap
@@ -17,6 +20,7 @@ class TetheringService : IpNeighbourMonitoringService(), TetheringManager.Tether
companion object {
const val EXTRA_ADD_INTERFACES = "interface.add"
const val EXTRA_ADD_INTERFACE_MONITOR = "interface.add.monitor"
const val EXTRA_ADD_INTERFACES_MONITOR = "interface.adds.monitor"
const val EXTRA_REMOVE_INTERFACE = "interface.remove"
}
@@ -39,6 +43,15 @@ class TetheringService : IpNeighbourMonitoringService(), TetheringManager.Tether
}
}
@Parcelize
data class Starter(val monitored: ArrayList<String>) : BootReceiver.Startable {
override fun start(context: Context) {
ContextCompat.startForegroundService(context, Intent(context, TetheringService::class.java).apply {
putStringArrayListExtra(EXTRA_ADD_INTERFACES_MONITOR, monitored)
})
}
}
/**
* Writes and critical reads to downstreams should be protected with this context.
*/
@@ -55,7 +68,7 @@ class TetheringService : IpNeighbourMonitoringService(), TetheringManager.Tether
val toRemove = downstreams.toMutableMap() // make a copy
for (iface in interfaces) {
val downstream = toRemove.remove(iface) ?: continue
if (downstream.monitor) downstream.start()
if (downstream.monitor && !downstream.start()) downstream.stop()
}
for ((iface, downstream) in toRemove) {
if (!downstream.monitor) check(downstreams.remove(iface, downstream))
@@ -81,6 +94,10 @@ class TetheringService : IpNeighbourMonitoringService(), TetheringManager.Tether
ServiceNotification.stopForeground(this)
stopSelf()
} else {
binder.monitoredIfaces.also {
if (it.isEmpty()) BootReceiver.delete<TetheringService>()
else BootReceiver.add<TetheringService>(Starter(ArrayList(it)))
}
if (!callbackRegistered) {
callbackRegistered = true
TetheringManager.registerTetheringEventCallbackCompat(this, this)
@@ -103,10 +120,12 @@ class TetheringService : IpNeighbourMonitoringService(), TetheringManager.Tether
if (start()) check(downstreams.put(iface, this) == null) else stop()
}
}
intent.getStringExtra(EXTRA_ADD_INTERFACE_MONITOR)?.also { iface ->
val monitorList = intent.getStringArrayListExtra(EXTRA_ADD_INTERFACES_MONITOR) ?:
intent.getStringExtra(EXTRA_ADD_INTERFACE_MONITOR)?.let { listOf(it) }
if (!monitorList.isNullOrEmpty()) for (iface in monitorList) {
val downstream = downstreams[iface]
if (downstream == null) Downstream(this@TetheringService, iface, true).apply {
start()
if (!start(true)) stop()
check(downstreams.put(iface, this) == null)
downstreams[iface] = this
} else downstream.monitor = true
@@ -120,6 +139,7 @@ class TetheringService : IpNeighbourMonitoringService(), TetheringManager.Tether
override fun onDestroy() {
launch {
BootReceiver.delete<TetheringService>()
unregisterReceiver()
downstreams.values.forEach { it.stop() } // force clean to prevent leakage
cancel()