improve selector

This commit is contained in:
arm64v8a 2023-03-18 17:18:02 +09:00
parent bb51a38474
commit 1f04d35e94
6 changed files with 46 additions and 24 deletions

View File

@ -16,6 +16,7 @@
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /> <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.WAKE_LOCK" /> <uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<uses-permission <uses-permission
android:name="android.permission.QUERY_ALL_PACKAGES" android:name="android.permission.QUERY_ALL_PACKAGES"

View File

@ -149,23 +149,14 @@ class BaseService {
stopRunner(false, (this as Context).getString(R.string.profile_empty)) stopRunner(false, (this as Context).getString(R.string.profile_empty))
} }
if (canReloadSelector()) { if (canReloadSelector()) {
var tag = "" val ent = SagerDatabase.proxyDao.getById(DataStore.selectedProxy)
var ent: ProxyEntity? = null val tag = data.proxy!!.config.profileTagMap[ent?.id] ?: ""
data.proxy!!.config.trafficMap.forEach { (t, list) ->
for (it in list) {
if (it.id == DataStore.selectedProxy) {
ent = it
tag = t
break
}
}
}
if (tag.isNotBlank() && ent != null) { if (tag.isNotBlank() && ent != null) {
val success = data.proxy!!.box.selectOutbound(tag) val success = data.proxy!!.box.selectOutbound(tag)
Logs.d("selectOutbound $tag $success") Logs.d("selectOutbound $tag $success")
runOnDefaultDispatcher { runOnDefaultDispatcher {
data.binder.broadcast { data.binder.broadcast {
it.stateChanged(-1, ent!!.displayName(), null) it.stateChanged(-1, ent.displayName(), null)
} }
} }
} }

View File

@ -12,6 +12,7 @@ class ProxyInstance(profile: ProxyEntity, var service: BaseService.Interface? =
BoxInstance(profile) { BoxInstance(profile) {
var lastSelectorGroupId = -1L var lastSelectorGroupId = -1L
var notTmp = true
// for TrafficLooper // for TrafficLooper
private var looper: TrafficLooper? = null private var looper: TrafficLooper? = null
@ -20,12 +21,13 @@ class ProxyInstance(profile: ProxyEntity, var service: BaseService.Interface? =
super.buildConfig() super.buildConfig()
lastSelectorGroupId = super.config.selectorGroupId lastSelectorGroupId = super.config.selectorGroupId
// //
Logs.d(config.config) if (notTmp) Logs.d(config.config)
if (BuildConfig.DEBUG) Logs.d(JavaUtil.gson.toJson(config.trafficMap)) if (notTmp && BuildConfig.DEBUG) Logs.d(JavaUtil.gson.toJson(config.trafficMap))
} }
// only use this in temporary instance // only use this in temporary instance
fun buildConfigTmp() { fun buildConfigTmp() {
notTmp = false
buildConfig() buildConfig()
} }

View File

@ -5,6 +5,7 @@ import io.nekohasekai.sagernet.aidl.TrafficData
import io.nekohasekai.sagernet.bg.BaseService import io.nekohasekai.sagernet.bg.BaseService
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_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.DurationUnit
@ -55,6 +56,8 @@ class TrafficLooper
var trafficUpdater: TrafficUpdater? = null var trafficUpdater: TrafficUpdater? = null
var proxy: ProxyInstance? var proxy: ProxyInstance?
// for display
var itemMain: TrafficUpdater.TrafficLooperData? = null var itemMain: TrafficUpdater.TrafficLooperData? = null
var itemMainBase: TrafficUpdater.TrafficLooperData? = null var itemMainBase: TrafficUpdater.TrafficLooperData? = null
var itemBypass: TrafficUpdater.TrafficLooperData? = null var itemBypass: TrafficUpdater.TrafficLooperData? = null
@ -77,7 +80,7 @@ class TrafficLooper
rx = ent.rx, rx = ent.rx,
tx = ent.tx, tx = ent.tx,
) )
if (ent.id == proxy.config.mainEntId) { if (proxy.config.selectorGroupId < 0L && ent.id == proxy.config.mainEntId) {
itemMain = item itemMain = item
itemMainBase = TrafficUpdater.TrafficLooperData( itemMainBase = TrafficUpdater.TrafficLooperData(
tag = tag, tag = tag,
@ -91,6 +94,10 @@ class TrafficLooper
Logs.d("traffic count $tag to ${ent.id}") Logs.d("traffic count $tag to ${ent.id}")
} }
} }
if (proxy.config.selectorGroupId >= 0L) {
itemMain = TrafficUpdater.TrafficLooperData(tag = TAG_PROXY)
itemMainBase = TrafficUpdater.TrafficLooperData(tag = TAG_PROXY)
}
// //
trafficUpdater = TrafficUpdater( trafficUpdater = TrafficUpdater(
box = proxy.box, items = items.values.toList() box = proxy.box, items = items.values.toList()

View File

@ -5,6 +5,7 @@ import io.nekohasekai.sagernet.Key
import io.nekohasekai.sagernet.bg.VpnService import io.nekohasekai.sagernet.bg.VpnService
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.ProxyEntity.Companion.TYPE_CHAIN
import io.nekohasekai.sagernet.database.ProxyEntity.Companion.TYPE_CONFIG import io.nekohasekai.sagernet.database.ProxyEntity.Companion.TYPE_CONFIG
import io.nekohasekai.sagernet.database.SagerDatabase import io.nekohasekai.sagernet.database.SagerDatabase
import io.nekohasekai.sagernet.fmt.ConfigBuildResult.IndexEntity import io.nekohasekai.sagernet.fmt.ConfigBuildResult.IndexEntity
@ -53,6 +54,7 @@ class ConfigBuildResult(
var externalIndex: List<IndexEntity>, var externalIndex: List<IndexEntity>,
var mainEntId: Long, var mainEntId: Long,
var trafficMap: Map<String, List<ProxyEntity>>, var trafficMap: Map<String, List<ProxyEntity>>,
var profileTagMap: Map<Long, String>,
val alerts: List<Pair<Int, String>>, val alerts: List<Pair<Int, String>>,
val selectorGroupId: Long, val selectorGroupId: Long,
) { ) {
@ -85,6 +87,7 @@ fun buildConfig(
listOf(), listOf(),
proxy.id, // proxy.id, //
mapOf(TAG_PROXY to listOf(proxy)), // mapOf(TAG_PROXY to listOf(proxy)), //
mapOf(proxy.id to TAG_PROXY), //
listOf(), listOf(),
-1L -1L
) )
@ -92,6 +95,7 @@ fun buildConfig(
} }
val trafficMap = HashMap<String, MutableList<ProxyEntity>>() val trafficMap = HashMap<String, MutableList<ProxyEntity>>()
val tagMap = HashMap<Long, String>()
val globalOutbounds = ArrayList<Long>() val globalOutbounds = ArrayList<Long>()
val group = SagerDatabase.groupDao.getById(proxy.groupId) val group = SagerDatabase.groupDao.getById(proxy.groupId)
var optionsToMerge = "" var optionsToMerge = ""
@ -126,9 +130,9 @@ fun buildConfig(
val extraRules = if (forTest) listOf() else SagerDatabase.rulesDao.enabledRules() val extraRules = if (forTest) listOf() else SagerDatabase.rulesDao.enabledRules()
val extraProxies = val extraProxies =
(if (forTest) mapOf() else SagerDatabase.proxyDao.getEntities(extraRules.mapNotNull { rule -> if (forTest) mapOf() else SagerDatabase.proxyDao.getEntities(extraRules.mapNotNull { rule ->
rule.outbound.takeIf { it > 0 && it != proxy.id } rule.outbound.takeIf { it > 0 && it != proxy.id }
}.toHashSet().toList()).associate { it.id to it.resolveChain() }).toMutableMap() }.toHashSet().toList()).associate { it.id to it }
val buildSelector = !forTest && group?.isSelector == true val buildSelector = !forTest && group?.isSelector == true
val uidListDNSRemote = mutableListOf<Int>() val uidListDNSRemote = mutableListOf<Int>()
val uidListDNSDirect = mutableListOf<Int>() val uidListDNSDirect = mutableListOf<Int>()
@ -261,8 +265,9 @@ fun buildConfig(
// returns outbound tag // returns outbound tag
fun buildChain( fun buildChain(
chainId: Long, profileList: List<ProxyEntity> chainId: Long, entity: ProxyEntity
): String { ): String {
val profileList = entity.resolveChain()
var currentOutbound = mutableMapOf<String, Any>() var currentOutbound = mutableMapOf<String, Any>()
lateinit var pastOutbound: MutableMap<String, Any> lateinit var pastOutbound: MutableMap<String, Any>
lateinit var pastInboundTag: String lateinit var pastInboundTag: String
@ -337,7 +342,7 @@ fun buildConfig(
// include g-xx & chain ent // include g-xx & chain ent
val mapList = mutableListOf(proxyEntity) val mapList = mutableListOf(proxyEntity)
if (index == 0 && profileList.size > 1) mapList.add(proxy) // chain ent if (index == 0 && entity.type == TYPE_CHAIN) mapList.add(proxy) // chain ent
trafficMap[tagOut] = mapList trafficMap[tagOut] = mapList
// Chain outbound // Chain outbound
@ -460,11 +465,10 @@ fun buildConfig(
} }
// build outbounds // build outbounds
val tagMap = mutableMapOf<Long, String>()
if (buildSelector) { if (buildSelector) {
val list = group?.id?.let { SagerDatabase.proxyDao.getByGroup(it) } val list = group?.id?.let { SagerDatabase.proxyDao.getByGroup(it) }
list?.forEach { list?.forEach {
tagMap[it.id] = buildChain(it.id, it.resolveChain()) tagMap[it.id] = buildChain(it.id, it)
} }
outbounds.add(0, Outbound_SelectorOptions().apply { outbounds.add(0, Outbound_SelectorOptions().apply {
type = "selector" type = "selector"
@ -473,11 +477,11 @@ fun buildConfig(
outbounds = tagMap.values.toList() outbounds = tagMap.values.toList()
}.asMap()) }.asMap())
} else { } else {
buildChain(0, proxy.resolveChain()) buildChain(0, proxy)
} }
// build outbounds from route item // build outbounds from route item
extraProxies.forEach { (key, entities) -> extraProxies.forEach { (key, p) ->
tagMap[key] = buildChain(key, entities) tagMap[key] = buildChain(key, p)
} }
// apply user rules // apply user rules
@ -756,6 +760,7 @@ fun buildConfig(
externalIndexMap, externalIndexMap,
proxy.id, proxy.id,
trafficMap, trafficMap,
tagMap,
alerts, alerts,
if (buildSelector) group!!.id else -1L if (buildSelector) group!!.id else -1L
) )

View File

@ -1,14 +1,19 @@
package io.nekohasekai.sagernet.ui package io.nekohasekai.sagernet.ui
import android.Manifest.permission.POST_NOTIFICATIONS
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.content.Intent import android.content.Intent
import android.content.pm.PackageManager
import android.net.Uri import android.net.Uri
import android.os.Build
import android.os.Bundle import android.os.Bundle
import android.os.RemoteException import android.os.RemoteException
import android.view.KeyEvent import android.view.KeyEvent
import android.view.MenuItem import android.view.MenuItem
import android.widget.Toast import android.widget.Toast
import androidx.annotation.IdRes import androidx.annotation.IdRes
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import androidx.core.view.ViewCompat import androidx.core.view.ViewCompat
import androidx.preference.PreferenceDataStore import androidx.preference.PreferenceDataStore
import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.google.android.material.dialog.MaterialAlertDialogBuilder
@ -82,6 +87,17 @@ class MainActivity : ThemedActivity(),
onNewIntent(intent) onNewIntent(intent)
} }
// sdk 33 notification
if (Build.VERSION.SDK_INT >= 33) {
val checkPermission =
ContextCompat.checkSelfPermission(this@MainActivity, POST_NOTIFICATIONS)
if (checkPermission != PackageManager.PERMISSION_GRANTED) {
//动态申请
ActivityCompat.requestPermissions(
this@MainActivity, arrayOf<String>(POST_NOTIFICATIONS), 0
)
}
}
} }
override fun onNewIntent(intent: Intent) { override fun onNewIntent(intent: Intent) {