Commit f6ec072e authored by Mygod's avatar Mygod

Fix bandwidth listeners handled in wrong thread

parent 4da71a0b
......@@ -94,7 +94,7 @@ object BaseService {
}
}
class Binder(private var data: Data? = null) : IShadowsocksService.Stub(), AutoCloseable {
class Binder(private var data: Data? = null) : IShadowsocksService.Stub(), CoroutineScope, AutoCloseable {
val callbacks = object : RemoteCallbackList<IShadowsocksServiceCallback>() {
override fun onCallbackDied(callback: IShadowsocksServiceCallback?, cookie: Any?) {
super.onCallbackDied(callback, cookie)
......@@ -102,7 +102,8 @@ object BaseService {
}
}
private val bandwidthListeners = mutableMapOf<IBinder, Long>() // the binder is the real identifier
private val handler = Handler()
override val coroutineContext = Dispatchers.Main.immediate + Job()
private var looper: Job? = null
override fun getState(): Int = (data?.state ?: State.Idle).ordinal
override fun getProfileName(): String = data?.proxy?.profile?.name ?: "Idle"
......@@ -123,10 +124,9 @@ object BaseService {
callbacks.finishBroadcast()
}
private fun registerTimeout() {
handler.postDelayed(this::onTimeout, bandwidthListeners.values.min() ?: return)
}
private fun onTimeout() {
private suspend fun loop() {
while (true) {
delay(bandwidthListeners.values.min() ?: return)
val proxies = listOfNotNull(data?.proxy, data?.udpFallback)
val stats = proxies
.map { Pair(it.profile.id, it.trafficMonitor?.requestUpdate()) }
......@@ -141,17 +141,21 @@ object BaseService {
}
}
}
registerTimeout()
}
}
override fun startListeningForBandwidth(cb: IShadowsocksServiceCallback, timeout: Long) {
launch {
val wasEmpty = bandwidthListeners.isEmpty()
if (bandwidthListeners.put(cb.asBinder(), timeout) == null) {
if (wasEmpty) registerTimeout()
if (data?.state != State.Connected) return
if (wasEmpty) {
check(looper == null)
looper = launch { loop() }
}
if (data?.state != State.Connected) return@launch
var sum = TrafficStats()
val data = data
val proxy = data?.proxy ?: return
val proxy = data?.proxy ?: return@launch
proxy.trafficMonitor?.out.also { stats ->
cb.trafficUpdated(proxy.profile.id, if (stats == null) sum else {
sum += stats
......@@ -169,10 +173,14 @@ object BaseService {
cb.trafficUpdated(0, sum)
}
}
}
override fun stopListeningForBandwidth(cb: IShadowsocksServiceCallback) {
launch {
if (bandwidthListeners.remove(cb.asBinder()) != null && bandwidthListeners.isEmpty()) {
handler.removeCallbacksAndMessages(null)
looper!!.cancel()
looper = null
}
}
}
......@@ -194,7 +202,7 @@ object BaseService {
override fun close() {
callbacks.kill()
handler.removeCallbacksAndMessages(null)
cancel()
data = null
}
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment