mirror of
https://github.com/MatsuriDayo/NekoBoxForAndroid.git
synced 2025-12-19 22:50:05 +08:00
optimize binder usage
This commit is contained in:
parent
17c6844107
commit
962668c6f1
@ -6,7 +6,7 @@ interface ISagerNetService {
|
|||||||
int getState();
|
int getState();
|
||||||
String getProfileName();
|
String getProfileName();
|
||||||
|
|
||||||
void registerCallback(in ISagerNetServiceCallback cb);
|
void registerCallback(in ISagerNetServiceCallback cb, int id);
|
||||||
oneway void unregisterCallback(in ISagerNetServiceCallback cb);
|
oneway void unregisterCallback(in ISagerNetServiceCallback cb);
|
||||||
|
|
||||||
int urlTest();
|
int urlTest();
|
||||||
|
|||||||
@ -7,7 +7,6 @@ oneway interface ISagerNetServiceCallback {
|
|||||||
void stateChanged(int state, String profileName, String msg);
|
void stateChanged(int state, String profileName, String msg);
|
||||||
void missingPlugin(String profileName, String pluginName);
|
void missingPlugin(String profileName, String pluginName);
|
||||||
void routeAlert(int type, String routeName);
|
void routeAlert(int type, String routeName);
|
||||||
void updateWakeLockStatus(boolean acquired);
|
|
||||||
void cbSpeedUpdate(in SpeedDisplayData stats);
|
void cbSpeedUpdate(in SpeedDisplayData stats);
|
||||||
void cbTrafficUpdate(in TrafficData stats);
|
void cbTrafficUpdate(in TrafficData stats);
|
||||||
void cbLogUpdate(String str);
|
void cbLogUpdate(String str);
|
||||||
|
|||||||
@ -36,7 +36,7 @@ import io.nekohasekai.sagernet.database.DataStore
|
|||||||
|
|
||||||
@Suppress("DEPRECATION")
|
@Suppress("DEPRECATION")
|
||||||
class QuickToggleShortcut : Activity(), SagerConnection.Callback {
|
class QuickToggleShortcut : Activity(), SagerConnection.Callback {
|
||||||
private val connection = SagerConnection()
|
private val connection = SagerConnection(SagerConnection.CONNECTION_ID_SHORTCUT)
|
||||||
private var profileId = -1L
|
private var profileId = -1L
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
|||||||
@ -13,7 +13,6 @@ import io.nekohasekai.sagernet.aidl.ISagerNetService
|
|||||||
import io.nekohasekai.sagernet.aidl.ISagerNetServiceCallback
|
import io.nekohasekai.sagernet.aidl.ISagerNetServiceCallback
|
||||||
import io.nekohasekai.sagernet.bg.proto.ProxyInstance
|
import io.nekohasekai.sagernet.bg.proto.ProxyInstance
|
||||||
import io.nekohasekai.sagernet.database.DataStore
|
import io.nekohasekai.sagernet.database.DataStore
|
||||||
import io.nekohasekai.sagernet.database.ProxyEntity
|
|
||||||
import io.nekohasekai.sagernet.database.SagerDatabase
|
import io.nekohasekai.sagernet.database.SagerDatabase
|
||||||
import io.nekohasekai.sagernet.ktx.*
|
import io.nekohasekai.sagernet.ktx.*
|
||||||
import io.nekohasekai.sagernet.plugin.PluginManager
|
import io.nekohasekai.sagernet.plugin.PluginManager
|
||||||
@ -73,20 +72,22 @@ class BaseService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val callbackIdMap = mutableMapOf<ISagerNetServiceCallback, Int>()
|
||||||
|
|
||||||
override val coroutineContext = Dispatchers.Main.immediate + Job()
|
override val coroutineContext = Dispatchers.Main.immediate + Job()
|
||||||
|
|
||||||
override fun getState(): Int = (data?.state ?: State.Idle).ordinal
|
override fun getState(): Int = (data?.state ?: State.Idle).ordinal
|
||||||
override fun getProfileName(): String = data?.proxy?.profile?.displayName() ?: "Idle"
|
override fun getProfileName(): String = data?.proxy?.profile?.displayName() ?: "Idle"
|
||||||
|
|
||||||
override fun registerCallback(cb: ISagerNetServiceCallback) {
|
override fun registerCallback(cb: ISagerNetServiceCallback, id: Int) {
|
||||||
callbacks.register(cb)
|
callbacks.register(cb)
|
||||||
cb.updateWakeLockStatus(data?.proxy?.service?.wakeLock != null)
|
callbackIdMap[cb] = id
|
||||||
}
|
}
|
||||||
|
|
||||||
private val boardcastMutex = Mutex()
|
private val broadcastMutex = Mutex()
|
||||||
|
|
||||||
suspend fun broadcast(work: (ISagerNetServiceCallback) -> Unit) {
|
suspend fun broadcast(work: (ISagerNetServiceCallback) -> Unit) {
|
||||||
boardcastMutex.withLock {
|
broadcastMutex.withLock {
|
||||||
val count = callbacks.beginBroadcast()
|
val count = callbacks.beginBroadcast()
|
||||||
try {
|
try {
|
||||||
repeat(count) {
|
repeat(count) {
|
||||||
@ -103,6 +104,7 @@ class BaseService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun unregisterCallback(cb: ISagerNetServiceCallback) {
|
override fun unregisterCallback(cb: ISagerNetServiceCallback) {
|
||||||
|
callbackIdMap.remove(cb)
|
||||||
callbacks.unregister(cb)
|
callbacks.unregister(cb)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -155,9 +157,8 @@ class BaseService {
|
|||||||
val success = data.proxy!!.box.selectOutbound(tag)
|
val success = data.proxy!!.box.selectOutbound(tag)
|
||||||
if (success) runOnDefaultDispatcher {
|
if (success) runOnDefaultDispatcher {
|
||||||
data.proxy!!.looper?.selectMain(ent.id)
|
data.proxy!!.looper?.selectMain(ent.id)
|
||||||
data.binder.broadcast {
|
val title = ServiceNotification.genTitle(ent)
|
||||||
it.stateChanged(-1, ServiceNotification.genTitle(ent), null)
|
data.notification?.postNotificationTitle(title)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
@ -267,14 +268,10 @@ class BaseService {
|
|||||||
wakeLock?.apply {
|
wakeLock?.apply {
|
||||||
release()
|
release()
|
||||||
wakeLock = null
|
wakeLock = null
|
||||||
data.binder.broadcast {
|
data.notification?.postNotificationWakeLockStatus(false)
|
||||||
it.updateWakeLockStatus(false)
|
|
||||||
}
|
|
||||||
} ?: apply {
|
} ?: apply {
|
||||||
acquireWakeLock()
|
acquireWakeLock()
|
||||||
data.binder.broadcast {
|
data.notification?.postNotificationWakeLockStatus(true)
|
||||||
it.updateWakeLockStatus(true)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -286,13 +283,9 @@ class BaseService {
|
|||||||
|
|
||||||
if (DataStore.acquireWakeLock) {
|
if (DataStore.acquireWakeLock) {
|
||||||
acquireWakeLock()
|
acquireWakeLock()
|
||||||
data.binder.broadcast {
|
data.notification?.postNotificationWakeLockStatus(true)
|
||||||
it.updateWakeLockStatus(true)
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
data.binder.broadcast {
|
data.notification?.postNotificationWakeLockStatus(false)
|
||||||
it.updateWakeLockStatus(false)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -15,8 +15,10 @@ import io.nekohasekai.sagernet.aidl.TrafficData
|
|||||||
import io.nekohasekai.sagernet.database.DataStore
|
import io.nekohasekai.sagernet.database.DataStore
|
||||||
import io.nekohasekai.sagernet.ktx.runOnMainDispatcher
|
import io.nekohasekai.sagernet.ktx.runOnMainDispatcher
|
||||||
|
|
||||||
class SagerConnection(private var listenForDeath: Boolean = false) : ServiceConnection,
|
class SagerConnection(
|
||||||
IBinder.DeathRecipient {
|
private val connectionId: Int,
|
||||||
|
private var listenForDeath: Boolean = false
|
||||||
|
) : ServiceConnection, IBinder.DeathRecipient {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
val serviceClass
|
val serviceClass
|
||||||
@ -25,6 +27,10 @@ class SagerConnection(private var listenForDeath: Boolean = false) : ServiceConn
|
|||||||
Key.MODE_VPN -> VpnService::class // Key.MODE_TRANS -> TransproxyService::class
|
Key.MODE_VPN -> VpnService::class // Key.MODE_TRANS -> TransproxyService::class
|
||||||
else -> throw UnknownError()
|
else -> throw UnknownError()
|
||||||
}.java
|
}.java
|
||||||
|
|
||||||
|
val CONNECTION_ID_SHORTCUT = 0
|
||||||
|
val CONNECTION_ID_TILE = 1
|
||||||
|
val CONNECTION_ID_MAINACTIVITY = 2
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Callback {
|
interface Callback {
|
||||||
@ -90,9 +96,6 @@ class SagerConnection(private var listenForDeath: Boolean = false) : ServiceConn
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun updateWakeLockStatus(acquired: Boolean) {
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun cbLogUpdate(str: String?) {
|
override fun cbLogUpdate(str: String?) {
|
||||||
DataStore.postLogListener?.let {
|
DataStore.postLogListener?.let {
|
||||||
if (str != null) {
|
if (str != null) {
|
||||||
@ -114,7 +117,7 @@ class SagerConnection(private var listenForDeath: Boolean = false) : ServiceConn
|
|||||||
try {
|
try {
|
||||||
if (listenForDeath) binder.linkToDeath(this, 0)
|
if (listenForDeath) binder.linkToDeath(this, 0)
|
||||||
check(!callbackRegistered)
|
check(!callbackRegistered)
|
||||||
service.registerCallback(serviceCallback)
|
service.registerCallback(serviceCallback, connectionId)
|
||||||
callbackRegistered = true
|
callbackRegistered = true
|
||||||
} catch (e: RemoteException) {
|
} catch (e: RemoteException) {
|
||||||
e.printStackTrace()
|
e.printStackTrace()
|
||||||
|
|||||||
@ -13,9 +13,7 @@ import androidx.core.app.NotificationManagerCompat
|
|||||||
import io.nekohasekai.sagernet.Action
|
import io.nekohasekai.sagernet.Action
|
||||||
import io.nekohasekai.sagernet.R
|
import io.nekohasekai.sagernet.R
|
||||||
import io.nekohasekai.sagernet.SagerNet
|
import io.nekohasekai.sagernet.SagerNet
|
||||||
import io.nekohasekai.sagernet.aidl.ISagerNetServiceCallback
|
|
||||||
import io.nekohasekai.sagernet.aidl.SpeedDisplayData
|
import io.nekohasekai.sagernet.aidl.SpeedDisplayData
|
||||||
import io.nekohasekai.sagernet.aidl.TrafficData
|
|
||||||
import io.nekohasekai.sagernet.database.DataStore
|
import io.nekohasekai.sagernet.database.DataStore
|
||||||
import io.nekohasekai.sagernet.database.ProxyEntity
|
import io.nekohasekai.sagernet.database.ProxyEntity
|
||||||
import io.nekohasekai.sagernet.database.SagerDatabase
|
import io.nekohasekai.sagernet.database.SagerDatabase
|
||||||
@ -35,7 +33,7 @@ import io.nekohasekai.sagernet.utils.Theme
|
|||||||
* See also: https://github.com/aosp-mirror/platform_frameworks_base/commit/070d142993403cc2c42eca808ff3fafcee220ac4
|
* See also: https://github.com/aosp-mirror/platform_frameworks_base/commit/070d142993403cc2c42eca808ff3fafcee220ac4
|
||||||
*/
|
*/
|
||||||
class ServiceNotification(
|
class ServiceNotification(
|
||||||
private val service: BaseService.Interface, profileName: String,
|
private val service: BaseService.Interface, title: String,
|
||||||
channel: String, visible: Boolean = false,
|
channel: String, visible: Boolean = false,
|
||||||
) : BroadcastReceiver() {
|
) : BroadcastReceiver() {
|
||||||
companion object {
|
companion object {
|
||||||
@ -50,81 +48,63 @@ class ServiceNotification(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val showDirectSpeed = DataStore.showDirectSpeed
|
fun postNotificationSpeedUpdate(stats: SpeedDisplayData) {
|
||||||
|
builder.apply {
|
||||||
private val callback: ISagerNetServiceCallback by lazy {
|
if (showDirectSpeed) {
|
||||||
object : ISagerNetServiceCallback.Stub() {
|
val speedDetail = (service as Context).getString(
|
||||||
override fun cbSpeedUpdate(stats: SpeedDisplayData) {
|
R.string.speed_detail, service.getString(
|
||||||
builder.apply {
|
R.string.speed, Formatter.formatFileSize(service, stats.txRateProxy)
|
||||||
if (showDirectSpeed) {
|
), service.getString(
|
||||||
val speedDetail = (service as Context).getString(
|
R.string.speed, Formatter.formatFileSize(service, stats.rxRateProxy)
|
||||||
R.string.speed_detail, service.getString(
|
), service.getString(
|
||||||
R.string.speed, Formatter.formatFileSize(service, stats.txRateProxy)
|
R.string.speed,
|
||||||
), service.getString(
|
Formatter.formatFileSize(service, stats.txRateDirect)
|
||||||
R.string.speed, Formatter.formatFileSize(service, stats.rxRateProxy)
|
), service.getString(
|
||||||
), service.getString(
|
R.string.speed,
|
||||||
R.string.speed,
|
Formatter.formatFileSize(service, stats.rxRateDirect)
|
||||||
Formatter.formatFileSize(service, stats.txRateDirect)
|
|
||||||
), service.getString(
|
|
||||||
R.string.speed,
|
|
||||||
Formatter.formatFileSize(service, stats.rxRateDirect)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
setStyle(NotificationCompat.BigTextStyle().bigText(speedDetail))
|
|
||||||
setContentText(speedDetail)
|
|
||||||
} else {
|
|
||||||
val speedSimple = (service as Context).getString(
|
|
||||||
R.string.traffic, service.getString(
|
|
||||||
R.string.speed, Formatter.formatFileSize(service, stats.txRateProxy)
|
|
||||||
), service.getString(
|
|
||||||
R.string.speed, Formatter.formatFileSize(service, stats.rxRateProxy)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
setContentText(speedSimple)
|
|
||||||
}
|
|
||||||
setSubText(
|
|
||||||
service.getString(
|
|
||||||
R.string.traffic,
|
|
||||||
Formatter.formatFileSize(service, stats.txTotal),
|
|
||||||
Formatter.formatFileSize(service, stats.rxTotal)
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
}
|
)
|
||||||
update()
|
setStyle(NotificationCompat.BigTextStyle().bigText(speedDetail))
|
||||||
}
|
setContentText(speedDetail)
|
||||||
|
} else {
|
||||||
override fun cbTrafficUpdate(stats: TrafficData?) {
|
val speedSimple = (service as Context).getString(
|
||||||
}
|
R.string.traffic, service.getString(
|
||||||
|
R.string.speed, Formatter.formatFileSize(service, stats.txRateProxy)
|
||||||
override fun stateChanged(state: Int, profileName: String?, msg: String?) {
|
), service.getString(
|
||||||
if (state == -1) {
|
R.string.speed, Formatter.formatFileSize(service, stats.rxRateProxy)
|
||||||
builder.setContentTitle(profileName)
|
)
|
||||||
}
|
)
|
||||||
}
|
setContentText(speedSimple)
|
||||||
|
|
||||||
override fun missingPlugin(profileName: String?, pluginName: String?) {
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun routeAlert(type: Int, routeName: String?) {
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun updateWakeLockStatus(acquired: Boolean) {
|
|
||||||
updateActions(acquired)
|
|
||||||
builder.priority =
|
|
||||||
if (acquired) NotificationCompat.PRIORITY_HIGH else NotificationCompat.PRIORITY_LOW
|
|
||||||
update()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun cbLogUpdate(str: String?) {
|
|
||||||
}
|
}
|
||||||
|
setSubText(
|
||||||
|
service.getString(
|
||||||
|
R.string.traffic,
|
||||||
|
Formatter.formatFileSize(service, stats.txTotal),
|
||||||
|
Formatter.formatFileSize(service, stats.rxTotal)
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
update()
|
||||||
}
|
}
|
||||||
private var callbackRegistered = false
|
|
||||||
|
fun postNotificationTitle(newTitle: String) {
|
||||||
|
builder.setContentTitle(newTitle)
|
||||||
|
update()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun postNotificationWakeLockStatus(acquired: Boolean) {
|
||||||
|
updateActions(acquired)
|
||||||
|
builder.priority =
|
||||||
|
if (acquired) NotificationCompat.PRIORITY_HIGH else NotificationCompat.PRIORITY_LOW
|
||||||
|
update()
|
||||||
|
}
|
||||||
|
|
||||||
|
private val showDirectSpeed = DataStore.showDirectSpeed
|
||||||
|
|
||||||
private val builder = NotificationCompat.Builder(service as Context, channel)
|
private val builder = NotificationCompat.Builder(service as Context, channel)
|
||||||
.setWhen(0)
|
.setWhen(0)
|
||||||
.setTicker(service.getString(R.string.forward_success))
|
.setTicker(service.getString(R.string.forward_success))
|
||||||
.setContentTitle(profileName)
|
.setContentTitle(title)
|
||||||
.setOnlyAlertOnce(true)
|
.setOnlyAlertOnce(true)
|
||||||
.setContentIntent(SagerNet.configureIntent(service))
|
.setContentIntent(SagerNet.configureIntent(service))
|
||||||
.setSmallIcon(R.drawable.ic_service_active)
|
.setSmallIcon(R.drawable.ic_service_active)
|
||||||
@ -147,7 +127,7 @@ class ServiceNotification(
|
|||||||
show()
|
show()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun updateActions(wakeLockAcquired: Boolean) {
|
private fun updateActions(wakeLockAcquired: Boolean) {
|
||||||
service as Context
|
service as Context
|
||||||
|
|
||||||
builder.clearActions()
|
builder.clearActions()
|
||||||
@ -188,15 +168,11 @@ class ServiceNotification(
|
|||||||
if (service.data.state == BaseService.State.Connected) updateCallback(intent.action == Intent.ACTION_SCREEN_ON)
|
if (service.data.state == BaseService.State.Connected) updateCallback(intent.action == Intent.ACTION_SCREEN_ON)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var listenPostSpeed = false
|
||||||
|
|
||||||
private fun updateCallback(screenOn: Boolean) {
|
private fun updateCallback(screenOn: Boolean) {
|
||||||
if (DataStore.speedInterval == 0) return
|
if (DataStore.speedInterval == 0) return
|
||||||
if (screenOn) {
|
listenPostSpeed = screenOn
|
||||||
service.data.binder.registerCallback(callback)
|
|
||||||
callbackRegistered = true
|
|
||||||
} else if (callbackRegistered) { // unregister callback to save battery
|
|
||||||
service.data.binder.unregisterCallback(callback)
|
|
||||||
callbackRegistered = false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun show() = (service as Service).startForeground(notificationId, builder.build())
|
private fun show() = (service as Service).startForeground(notificationId, builder.build())
|
||||||
|
|||||||
@ -37,7 +37,7 @@ class TileService : BaseTileService(), SagerConnection.Callback {
|
|||||||
}
|
}
|
||||||
private var tapPending = false
|
private var tapPending = false
|
||||||
|
|
||||||
private val connection = SagerConnection()
|
private val connection = SagerConnection(SagerConnection.CONNECTION_ID_TILE)
|
||||||
override fun stateChanged(state: BaseService.State, profileName: String?, msg: String?) =
|
override fun stateChanged(state: BaseService.State, profileName: String?, msg: String?) =
|
||||||
updateTile(state) { profileName }
|
updateTile(state) { profileName }
|
||||||
|
|
||||||
|
|||||||
@ -3,14 +3,13 @@ package io.nekohasekai.sagernet.bg.proto
|
|||||||
import io.nekohasekai.sagernet.aidl.SpeedDisplayData
|
import io.nekohasekai.sagernet.aidl.SpeedDisplayData
|
||||||
import io.nekohasekai.sagernet.aidl.TrafficData
|
import io.nekohasekai.sagernet.aidl.TrafficData
|
||||||
import io.nekohasekai.sagernet.bg.BaseService
|
import io.nekohasekai.sagernet.bg.BaseService
|
||||||
|
import io.nekohasekai.sagernet.bg.SagerConnection
|
||||||
import io.nekohasekai.sagernet.database.DataStore
|
import io.nekohasekai.sagernet.database.DataStore
|
||||||
import io.nekohasekai.sagernet.database.ProfileManager
|
import io.nekohasekai.sagernet.database.ProfileManager
|
||||||
import io.nekohasekai.sagernet.fmt.TAG_BYPASS
|
import io.nekohasekai.sagernet.fmt.TAG_BYPASS
|
||||||
import io.nekohasekai.sagernet.fmt.TAG_PROXY
|
import io.nekohasekai.sagernet.fmt.TAG_PROXY
|
||||||
import io.nekohasekai.sagernet.ktx.Logs
|
import io.nekohasekai.sagernet.ktx.Logs
|
||||||
import kotlinx.coroutines.*
|
import kotlinx.coroutines.*
|
||||||
import kotlin.time.DurationUnit
|
|
||||||
import kotlin.time.toDuration
|
|
||||||
|
|
||||||
class TrafficLooper
|
class TrafficLooper
|
||||||
(
|
(
|
||||||
@ -64,9 +63,10 @@ class TrafficLooper
|
|||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun loop() {
|
private suspend fun loop() {
|
||||||
val delayMs = DataStore.speedInterval
|
val delayMs = DataStore.speedInterval.toLong()
|
||||||
val showDirectSpeed = DataStore.showDirectSpeed
|
val showDirectSpeed = DataStore.showDirectSpeed
|
||||||
if (delayMs == 0) return
|
val profileTrafficStatistics = DataStore.profileTrafficStatistics
|
||||||
|
if (delayMs == 0L) return
|
||||||
|
|
||||||
var trafficUpdater: TrafficUpdater? = null
|
var trafficUpdater: TrafficUpdater? = null
|
||||||
var proxy: ProxyInstance?
|
var proxy: ProxyInstance?
|
||||||
@ -77,7 +77,7 @@ class TrafficLooper
|
|||||||
var itemBypass: TrafficUpdater.TrafficLooperData? = null
|
var itemBypass: TrafficUpdater.TrafficLooperData? = null
|
||||||
|
|
||||||
while (sc.isActive) {
|
while (sc.isActive) {
|
||||||
delay(delayMs.toDuration(DurationUnit.MILLISECONDS))
|
delay(delayMs)
|
||||||
proxy = data.proxy ?: continue
|
proxy = data.proxy ?: continue
|
||||||
|
|
||||||
if (trafficUpdater == null) {
|
if (trafficUpdater == null) {
|
||||||
@ -134,30 +134,23 @@ class TrafficLooper
|
|||||||
itemMain!!.rx - itemMainBase!!.rx
|
itemMain!!.rx - itemMainBase!!.rx
|
||||||
)
|
)
|
||||||
|
|
||||||
// traffic
|
// broadcast (MainActivity)
|
||||||
val traffic = mutableMapOf<Long, TrafficData>()
|
data.binder.broadcast { b ->
|
||||||
if (DataStore.profileTrafficStatistics) {
|
if (data.binder.callbackIdMap[b] == SagerConnection.CONNECTION_ID_MAINACTIVITY) {
|
||||||
proxy.config.trafficMap.forEach { (_, ents) ->
|
b.cbSpeedUpdate(speed)
|
||||||
for (ent in ents) {
|
if (profileTrafficStatistics) {
|
||||||
val item = items[ent.id] ?: continue
|
items.forEach { (id, item) ->
|
||||||
ent.rx = item.rx
|
b.cbTrafficUpdate(
|
||||||
ent.tx = item.tx
|
TrafficData(id = id, rx = item.rx, tx = item.tx) // display
|
||||||
// ProfileManager.updateProfile(ent) // update DB
|
)
|
||||||
traffic[ent.id] = TrafficData(
|
}
|
||||||
id = ent.id,
|
|
||||||
rx = ent.rx,
|
|
||||||
tx = ent.tx,
|
|
||||||
) // display
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// broadcast
|
// ServiceNotification
|
||||||
data.binder.broadcast { b ->
|
data.notification?.apply {
|
||||||
b.cbSpeedUpdate(speed)
|
if (listenPostSpeed) postNotificationSpeedUpdate(speed)
|
||||||
for (t in traffic) {
|
|
||||||
b.cbTrafficUpdate(t.value)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,6 +6,12 @@ import moe.matsuri.nb4a.utils.Util
|
|||||||
import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
|
import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
|
||||||
import org.json.JSONObject
|
import org.json.JSONObject
|
||||||
|
|
||||||
|
fun ShadowsocksBean.fixPluginName() {
|
||||||
|
if (plugin.startsWith("simple-obfs")) {
|
||||||
|
plugin = plugin.replaceFirst("simple-obfs", "obfs-local")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun parseShadowsocks(url: String): ShadowsocksBean {
|
fun parseShadowsocks(url: String): ShadowsocksBean {
|
||||||
|
|
||||||
if (url.substringBefore("#").contains("@")) {
|
if (url.substringBefore("#").contains("@")) {
|
||||||
@ -31,6 +37,7 @@ fun parseShadowsocks(url: String): ShadowsocksBean {
|
|||||||
password = link.password
|
password = link.password
|
||||||
plugin = link.queryParameter("plugin") ?: ""
|
plugin = link.queryParameter("plugin") ?: ""
|
||||||
name = link.fragment
|
name = link.fragment
|
||||||
|
fixPluginName()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -43,6 +50,7 @@ fun parseShadowsocks(url: String): ShadowsocksBean {
|
|||||||
password = methodAndPswd.substringAfter(":")
|
password = methodAndPswd.substringAfter(":")
|
||||||
plugin = link.queryParameter("plugin") ?: ""
|
plugin = link.queryParameter("plugin") ?: ""
|
||||||
name = link.fragment
|
name = link.fragment
|
||||||
|
fixPluginName()
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// v2rayN style
|
// v2rayN style
|
||||||
|
|||||||
@ -381,7 +381,7 @@ class MainActivity : ThemedActivity(),
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val connection = SagerConnection(true)
|
val connection = SagerConnection(SagerConnection.CONNECTION_ID_MAINACTIVITY, true)
|
||||||
override fun onServiceConnected(service: ISagerNetService) = changeState(
|
override fun onServiceConnected(service: ISagerNetService) = changeState(
|
||||||
try {
|
try {
|
||||||
BaseService.State.values()[service.state]
|
BaseService.State.values()[service.state]
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user