Add config override and per-app proxy feature
This commit is contained in:
49
app/src/main/java/io/nekohasekai/sfa/bg/AppChangeReceiver.kt
Normal file
49
app/src/main/java/io/nekohasekai/sfa/bg/AppChangeReceiver.kt
Normal file
@@ -0,0 +1,49 @@
|
||||
package io.nekohasekai.sfa.bg
|
||||
|
||||
import android.content.BroadcastReceiver
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.util.Log
|
||||
import io.nekohasekai.sfa.database.Settings
|
||||
import io.nekohasekai.sfa.ui.configoverride.PerAppProxyActivity
|
||||
import kotlinx.coroutines.GlobalScope
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
class AppChangeReceiver : BroadcastReceiver() {
|
||||
|
||||
companion object {
|
||||
private const val TAG = "AppChangeReceiver"
|
||||
}
|
||||
|
||||
override fun onReceive(context: Context, intent: Intent) {
|
||||
Log.d(TAG, "onReceive: ${intent.action}")
|
||||
checkUpdate(context, intent)
|
||||
}
|
||||
|
||||
private fun checkUpdate(context: Context, intent: Intent) {
|
||||
if (!Settings.perAppProxyEnabled) {
|
||||
Log.d(TAG, "per app proxy disabled")
|
||||
return
|
||||
}
|
||||
val perAppProxyUpdateOnChange = Settings.perAppProxyUpdateOnChange
|
||||
if (perAppProxyUpdateOnChange != Settings.PER_APP_PROXY_DISABLED) {
|
||||
Log.d(TAG, "update on change disabled")
|
||||
return
|
||||
}
|
||||
val packageName = intent.dataString?.substringAfter("package:")
|
||||
if (packageName.isNullOrBlank()) {
|
||||
Log.d(TAG, "missing package name in intent")
|
||||
return
|
||||
}
|
||||
val isChinaApp = PerAppProxyActivity.scanChinaApps(listOf(packageName)).isNotEmpty()
|
||||
Log.d(TAG, "scan china app result for $packageName: $isChinaApp")
|
||||
if ((perAppProxyUpdateOnChange == Settings.PER_APP_PROXY_INCLUDE) xor !isChinaApp) {
|
||||
Settings.perAppProxyList = Settings.perAppProxyList + packageName
|
||||
Log.d(TAG, "added to list")
|
||||
} else {
|
||||
Settings.perAppProxyList = Settings.perAppProxyList - packageName
|
||||
Log.d(TAG, "removed from list")
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -39,12 +39,14 @@ class BoxService(
|
||||
private var initializeOnce = false
|
||||
private fun initialize() {
|
||||
if (initializeOnce) return
|
||||
val baseDir = Application.application.getExternalFilesDir(null) ?: return
|
||||
val baseDir = Application.application.filesDir
|
||||
baseDir.mkdirs()
|
||||
val workingDir = Application.application.getExternalFilesDir(null) ?: return
|
||||
workingDir.mkdirs()
|
||||
val tempDir = Application.application.cacheDir
|
||||
tempDir.mkdirs()
|
||||
Libbox.setup(baseDir.path, baseDir.path, tempDir.path, false)
|
||||
Libbox.redirectStderr(File(baseDir, "stderr.log").path)
|
||||
Libbox.setup(baseDir.path, workingDir.path, tempDir.path, false)
|
||||
Libbox.redirectStderr(File(workingDir, "stderr.log").path)
|
||||
initializeOnce = true
|
||||
return
|
||||
}
|
||||
@@ -65,6 +67,14 @@ class BoxService(
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
fun reload() {
|
||||
Application.application.sendBroadcast(
|
||||
Intent(Action.SERVICE_RELOAD).setPackage(
|
||||
Application.application.packageName
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
var fileDescriptor: ParcelFileDescriptor? = null
|
||||
@@ -82,6 +92,9 @@ class BoxService(
|
||||
Action.SERVICE_CLOSE -> {
|
||||
stopService()
|
||||
}
|
||||
Action.SERVICE_RELOAD -> {
|
||||
serviceReload()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -94,7 +107,6 @@ class BoxService(
|
||||
}
|
||||
|
||||
private suspend fun startService() {
|
||||
initialize()
|
||||
try {
|
||||
val selectedProfileId = Settings.selectedProfile
|
||||
if (selectedProfileId == -1L) {
|
||||
@@ -224,6 +236,7 @@ class BoxService(
|
||||
if (!receiverRegistered) {
|
||||
service.registerReceiver(receiver, IntentFilter().apply {
|
||||
addAction(Action.SERVICE_CLOSE)
|
||||
addAction(Action.SERVICE_RELOAD)
|
||||
})
|
||||
receiverRegistered = true
|
||||
}
|
||||
@@ -231,6 +244,7 @@ class BoxService(
|
||||
notification.show()
|
||||
GlobalScope.launch(Dispatchers.IO) {
|
||||
Settings.startedByUser = true
|
||||
initialize()
|
||||
try {
|
||||
startCommandServer()
|
||||
} catch (e: Exception) {
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
package io.nekohasekai.sfa.bg
|
||||
|
||||
import android.content.Intent
|
||||
import android.content.pm.PackageManager.NameNotFoundException
|
||||
import android.net.ProxyInfo
|
||||
import android.net.VpnService
|
||||
import android.os.Build
|
||||
import io.nekohasekai.libbox.TunOptions
|
||||
import io.nekohasekai.sfa.database.Settings
|
||||
|
||||
class VPNService : VpnService(), PlatformInterfaceWrapper {
|
||||
|
||||
@@ -80,17 +82,43 @@ class VPNService : VpnService(), PlatformInterfaceWrapper {
|
||||
builder.addRoute("::", 0)
|
||||
}
|
||||
|
||||
val includePackage = options.includePackage
|
||||
if (includePackage.hasNext()) {
|
||||
while (includePackage.hasNext()) {
|
||||
builder.addAllowedApplication(includePackage.next())
|
||||
if (Settings.perAppProxyEnabled) {
|
||||
val appList = Settings.perAppProxyList
|
||||
if (Settings.perAppProxyMode == Settings.PER_APP_PROXY_INCLUDE) {
|
||||
appList.forEach {
|
||||
try {
|
||||
builder.addAllowedApplication(it)
|
||||
} catch (_: NameNotFoundException) {
|
||||
}
|
||||
}
|
||||
builder.addAllowedApplication(packageName)
|
||||
} else {
|
||||
appList.forEach {
|
||||
try {
|
||||
builder.addDisallowedApplication(it)
|
||||
} catch (_: NameNotFoundException) {
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
val includePackage = options.includePackage
|
||||
if (includePackage.hasNext()) {
|
||||
while (includePackage.hasNext()) {
|
||||
try {
|
||||
builder.addAllowedApplication(includePackage.next())
|
||||
} catch (_: NameNotFoundException) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val excludePackage = options.excludePackage
|
||||
if (excludePackage.hasNext()) {
|
||||
while (excludePackage.hasNext()) {
|
||||
builder.addDisallowedApplication(excludePackage.next())
|
||||
val excludePackage = options.excludePackage
|
||||
if (excludePackage.hasNext()) {
|
||||
while (excludePackage.hasNext()) {
|
||||
try {
|
||||
builder.addDisallowedApplication(excludePackage.next())
|
||||
} catch (_: NameNotFoundException) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user