@@ -2,7 +2,7 @@ package io.github.chsbuffer.revancedxposed
22
33import android.annotation.SuppressLint
44import android.app.Application
5- import android.content.Context
5+ import android.content.Context.MODE_PRIVATE
66import android.os.Build
77import app.revanced.extension.shared.Logger
88import app.revanced.extension.shared.Utils
@@ -12,6 +12,8 @@ import de.robv.android.xposed.XposedHelpers
1212import de.robv.android.xposed.callbacks.XC_LoadPackage.LoadPackageParam
1313import io.github.chsbuffer.revancedxposed.BuildConfig.DEBUG
1414import org.luckypray.dexkit.DexKitBridge
15+ import org.luckypray.dexkit.DexKitCacheBridge
16+ import org.luckypray.dexkit.annotations.DexKitExperimentalApi
1517import org.luckypray.dexkit.result.ClassData
1618import org.luckypray.dexkit.result.FieldData
1719import 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+
71113class DependedHookFailedException (
72114 subHookName : String , exception : Throwable
73115) : Exception(" Depended hook $subHookName failed." , exception)
74116
117+ @OptIn(DexKitExperimentalApi ::class )
75118@SuppressLint(" CommitPrefEdits" )
76119abstract 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