Skip to content

Commit c4872e0

Browse files
committed
Refactor: Use DexKitCacheBridge for caching
1 parent bfca549 commit c4872e0

File tree

1 file changed

+74
-67
lines changed
  • app/src/main/java/io/github/chsbuffer/revancedxposed

1 file changed

+74
-67
lines changed

app/src/main/java/io/github/chsbuffer/revancedxposed/BaseHook.kt

Lines changed: 74 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ package io.github.chsbuffer.revancedxposed
22

33
import android.annotation.SuppressLint
44
import android.app.Application
5-
import android.content.Context
5+
import android.content.Context.MODE_PRIVATE
66
import android.os.Build
77
import app.revanced.extension.shared.Logger
88
import app.revanced.extension.shared.Utils
@@ -12,6 +12,8 @@ import de.robv.android.xposed.XposedHelpers
1212
import de.robv.android.xposed.callbacks.XC_LoadPackage.LoadPackageParam
1313
import io.github.chsbuffer.revancedxposed.BuildConfig.DEBUG
1414
import org.luckypray.dexkit.DexKitBridge
15+
import org.luckypray.dexkit.DexKitCacheBridge
16+
import org.luckypray.dexkit.annotations.DexKitExperimentalApi
1517
import org.luckypray.dexkit.result.ClassData
1618
import org.luckypray.dexkit.result.FieldData
1719
import org.luckypray.dexkit.result.MethodData
@@ -68,10 +70,51 @@ interface IHook {
6870
fun DexField.toField() = getFieldInstance(classLoader)
6971
}
7072

73+
@OptIn(DexKitExperimentalApi::class)
74+
class PrefCache(app: Application) : DexKitCacheBridge.Cache {
75+
val pref = app.getSharedPreferences("xprevanced", MODE_PRIVATE)!!
76+
private val map = mutableMapOf<String, String>().apply {
77+
putAll(pref.all as Map<String, String>)
78+
}
79+
80+
override fun clearAll() {
81+
map.clear()
82+
}
83+
84+
override fun get(key: String, default: String?): String? = map.getOrDefault(key, default)
85+
86+
override fun getAllKeys(): Collection<String> = map.keys
87+
88+
override fun getList(
89+
key: String, default: List<String>?
90+
): List<String>? = map.getOrDefault(key, null)?.split('|') ?: default
91+
92+
override fun put(key: String, value: String) {
93+
map.put(key, value)
94+
}
95+
96+
override fun putList(key: String, value: List<String>) {
97+
map.put(key, value.joinToString("|"))
98+
}
99+
100+
override fun remove(key: String) {
101+
map.remove(key)
102+
}
103+
104+
fun saveCache() {
105+
val edit = pref.edit()
106+
map.forEach { k, v ->
107+
edit.putString(k, v)
108+
}
109+
edit.commit()
110+
}
111+
}
112+
71113
class DependedHookFailedException(
72114
subHookName: String, exception: Throwable
73115
) : Exception("Depended hook $subHookName failed.", exception)
74116

117+
@OptIn(DexKitExperimentalApi::class)
75118
@SuppressLint("CommitPrefEdits")
76119
abstract class BaseHook(val app: Application, val lpparam: LoadPackageParam) : IHook {
77120
override val classLoader = lpparam.classLoader!!
@@ -83,10 +126,12 @@ abstract class BaseHook(val app: Application, val lpparam: LoadPackageParam) : I
83126

84127
// cache
85128
private val moduleRel = BuildConfig.VERSION_CODE
86-
private var pref = app.getSharedPreferences("xprevanced", Context.MODE_PRIVATE)!!
87-
private val map = mutableMapOf<String, String>()
88-
private lateinit var dexkit: DexKitBridge
89-
private var isCached: Boolean = false
129+
private var cache = PrefCache(app)
130+
private var dexkit = run {
131+
System.loadLibrary("dexkit")
132+
DexKitCacheBridge.init(cache)
133+
DexKitCacheBridge.create("", lpparam.appInfo.sourceDir)
134+
}
90135

91136
override fun Hook() {
92137
val t = measureTimeMillis {
@@ -96,7 +141,7 @@ abstract class BaseHook(val app: Application, val lpparam: LoadPackageParam) : I
96141
handleResult()
97142
logDebugInfo()
98143
} finally {
99-
closeDexKit()
144+
dexkit.close()
100145
}
101146
}
102147
Logger.printDebug { "${lpparam.packageName} handleLoadPackage: ${t}ms" }
@@ -109,29 +154,16 @@ abstract class BaseHook(val app: Application, val lpparam: LoadPackageParam) : I
109154
val packageInfo = app.packageManager.getPackageInfo(app.packageName, 0)
110155

111156
val id = "${packageInfo.lastUpdateTime}-$moduleRel"
112-
val cachedId = pref.getString("id", null)
113-
isCached = cachedId.equals(id) && !DEBUG
157+
val cachedId = cache.get("id", null)
158+
val isCached = cachedId.equals(id) && !DEBUG
114159

115160
Logger.printInfo { "cache ID : $id" }
116161
Logger.printInfo { "cached ID: ${cachedId ?: ""}" }
117162
Logger.printInfo { "Using cached keys: $isCached" }
118163

119-
if (isCached) {
120-
map.putAll(pref.all as Map<String, String>)
121-
} else {
122-
map["id"] = id
123-
createDexKit()
124-
}
125-
}
126-
127-
private fun createDexKit() {
128-
System.loadLibrary("dexkit")
129-
dexkit = DexKitBridge.create(lpparam.appInfo.sourceDir)
130-
}
131-
132-
private fun closeDexKit() {
133-
if (::dexkit.isInitialized) {
134-
dexkit.close()
164+
if (!isCached) {
165+
cache.clearAll()
166+
cache.put("id", id)
135167
}
136168
}
137169

@@ -147,15 +179,11 @@ abstract class BaseHook(val app: Application, val lpparam: LoadPackageParam) : I
147179
}
148180

149181
private fun handleResult() {
150-
// save cache if no failure
182+
cache.saveCache()
151183
val success = failedHooks.isEmpty()
152184
if (!success) {
153185
XposedBridge.log("${lpparam.appInfo.packageName} version: ${getAppVersion()}")
154186
Utils.showToastLong("Error while apply following Hooks:\n${failedHooks.joinToString { it.name }}")
155-
156-
clearCache()
157-
} else {
158-
saveCache()
159187
}
160188
}
161189

@@ -166,9 +194,6 @@ abstract class BaseHook(val app: Application, val lpparam: LoadPackageParam) : I
166194
if (success) {
167195
Utils.showToastLong("apply hooks success")
168196
}
169-
if (success && isCached) {
170-
map.forEach { key, value -> Logger.printDebug { "$key Matches: $value" } }
171-
}
172197
}
173198
}
174199

@@ -183,23 +208,6 @@ abstract class BaseHook(val app: Application, val lpparam: LoadPackageParam) : I
183208
return "$versionName ($versionCode)"
184209
}
185210

186-
private fun saveCache() {
187-
if (isCached) return
188-
189-
val edit = pref.edit()
190-
map.forEach { k, v ->
191-
edit.putString(k, v)
192-
}
193-
edit.commit()
194-
}
195-
196-
private fun clearCache() {
197-
Logger.printInfo { "clear cache" }
198-
pref.edit().clear().commit()
199-
isCached = false
200-
map.clear()
201-
}
202-
203211
fun dependsOn(vararg hooks: HookFunction) {
204212
hooks.forEach { hook ->
205213
if (appliedHooks.contains(hook)) return@forEach
@@ -217,36 +225,35 @@ abstract class BaseHook(val app: Application, val lpparam: LoadPackageParam) : I
217225
serialize: (T) -> String,
218226
deserialize: (String) -> R
219227
): R {
220-
return map[key]?.let { deserialize(it) } ?: findFunc!!(dexkit).let { result ->
221-
val serializedValue = serialize(result)
222-
map[key] = serializedValue
223-
Logger.printInfo { "$key Matches: $serializedValue" }
224-
deserialize(serializedValue)
225-
}
228+
return cache.get(key, null)?.let { deserialize(it) }
229+
?: findFunc!!(dexkit.bridge).let { result ->
230+
val serializedValue = serialize(result)
231+
cache.put(key, serializedValue)
232+
Logger.printInfo { "$key Matches: $serializedValue" }
233+
deserialize(serializedValue)
234+
}
226235
}
227236

228237
fun getDexClass(key: String, findFunc: (DexKitBridge.() -> ClassData)? = null): DexClass =
229-
getFromCacheOrFind(key, findFunc, { it.descriptor }, { DexClass(it) })
238+
if (findFunc == null) dexkit.getClassDirect(key) else dexkit.getClassDirect(key, findFunc)
230239

231240
fun getDexMethod(key: String, findFunc: (DexKitBridge.() -> MethodData)? = null): DexMethod =
232-
getFromCacheOrFind(key, findFunc, { it.descriptor }, { DexMethod(it) })
233-
234-
fun getDexMethods(
235-
key: String,
236-
findFunc: (DexKitBridge.() -> Iterable<MethodData>)? = null
237-
): Iterable<DexMethod> =
238-
getFromCacheOrFind(
239-
key, findFunc,
240-
{ it.joinToString("|") { it.descriptor } },
241-
{ it.split("|").map { DexMethod(it) } })
241+
if (findFunc == null) dexkit.getMethodDirect(key) else dexkit.getMethodDirect(key, findFunc)
242242

243243
fun getDexField(key: String, findFunc: (DexKitBridge.() -> FieldData)? = null): DexField =
244-
getFromCacheOrFind(key, findFunc, { it.descriptor }, { DexField(it) })
244+
if (findFunc == null) dexkit.getFieldDirect(key) else dexkit.getFieldDirect(key, findFunc)
245245

246246
fun getString(key: String, findFunc: (DexKitBridge.() -> String)? = null): String =
247247
getFromCacheOrFind(key, findFunc, { it }, { it })
248248

249249
fun getNumber(key: String, findFunc: (DexKitBridge.() -> Int)? = null): Int =
250250
getFromCacheOrFind(key, findFunc, { it.toString() }, { Integer.parseInt(it) })
251251

252+
fun getDexMethods(
253+
key: String, findFunc: (DexKitBridge.() -> List<MethodData>)? = null
254+
): List<DexMethod> = if (findFunc == null) {
255+
dexkit.getMethodsDirect(key)
256+
} else {
257+
dexkit.getMethodsDirect(key, findFunc)
258+
}
252259
}

0 commit comments

Comments
 (0)