forked from starifly/NekoBoxForAndroid
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathPluginManager.kt
More file actions
98 lines (83 loc) · 3.07 KB
/
Copy pathPluginManager.kt
File metadata and controls
98 lines (83 loc) · 3.07 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
package io.nekohasekai.sagernet.plugin
import android.content.pm.ComponentInfo
import android.content.pm.ProviderInfo
import io.nekohasekai.sagernet.R
import io.nekohasekai.sagernet.SagerNet
import io.nekohasekai.sagernet.bg.BaseService
import io.nekohasekai.sagernet.ktx.Logs
import moe.matsuri.nb4a.plugin.Plugins
import java.io.File
import java.io.FileNotFoundException
object PluginManager {
class PluginNotFoundException(val plugin: String) : FileNotFoundException(plugin),
BaseService.ExpectedException {
override fun getLocalizedMessage() =
SagerNet.application.getString(R.string.plugin_unknown, plugin)
}
data class InitResult(
val path: String,
val info: ProviderInfo,
)
@Throws(Throwable::class)
fun init(pluginId: String): InitResult? {
if (pluginId.isEmpty()) return null
var throwable: Throwable? = null
try {
val result = initNative(pluginId)
if (result != null) return result
} catch (t: Throwable) {
throwable = t
Logs.w(t)
}
throw throwable ?: PluginNotFoundException(pluginId)
}
private fun initNative(pluginId: String): InitResult? {
val info = Plugins.getPlugin(pluginId) ?: return null
// internal so
if (info.applicationInfo == null) {
try {
initNativeInternal(pluginId)?.let { return InitResult(it, info) }
} catch (t: Throwable) {
Logs.w("initNativeInternal failed", t)
}
return null
}
try {
initNativeFaster(info)?.let { return InitResult(it, info) }
} catch (t: Throwable) {
Logs.w("initNativeFaster failed", t)
}
Logs.w("Init native returns empty result")
return null
}
private fun initNativeInternal(pluginId: String): String? {
fun soIfExist(soName: String): String? {
val f = File(SagerNet.application.applicationInfo.nativeLibraryDir, soName)
if (f.canExecute()) {
return f.absolutePath
}
return null
}
return when (pluginId) {
"hysteria-plugin" -> soIfExist("libhysteria.so")
"hysteria2-plugin" -> soIfExist("libhysteria2.so")
"mieru-plugin" -> soIfExist("libmieru.so")
else -> null
}
}
private fun initNativeFaster(provider: ProviderInfo): String? {
return provider.loadString(Plugins.METADATA_KEY_EXECUTABLE_PATH)
?.let { relativePath ->
File(provider.applicationInfo.nativeLibraryDir).resolve(relativePath).apply {
check(canExecute())
}.absolutePath
}
}
fun ComponentInfo.loadString(key: String) = when (val value = metaData.get(key)) {
is String -> value
is Int -> SagerNet.application.packageManager.getResourcesForApplication(applicationInfo)
.getString(value)
null -> null
else -> error("meta-data $key has invalid type ${value.javaClass}")
}
}