NativeLib.kt (2732B) - raw
1 package me.rhunk.snapenhance.nativelib 2 3 import android.annotation.SuppressLint 4 import android.util.Log 5 import kotlin.math.absoluteValue 6 import kotlin.random.Random 7 8 class NativeLib { 9 var nativeUnaryCallCallback: (NativeRequestData) -> Unit = {} 10 var signatureCache: String? = null 11 12 companion object { 13 var initialized = false 14 private set 15 } 16 17 fun initOnce(callback: NativeLib.() -> Unit): () -> Unit { 18 if (initialized) throw IllegalStateException("NativeLib already initialized") 19 return runCatching { 20 System.loadLibrary(BuildConfig.NATIVE_NAME) 21 initialized = true 22 callback(this) 23 preInit() 24 return@runCatching { 25 signatureCache = init(signatureCache) ?: throw IllegalStateException("NativeLib init failed. Check logcat for more info") 26 } 27 }.onFailure { 28 initialized = false 29 Log.e("SnapEnhance", "NativeLib init failed", it) 30 }.getOrThrow() 31 } 32 33 @Suppress("unused") 34 private fun onNativeUnaryCall(uri: String, buffer: ByteArray): NativeRequestData? { 35 val nativeRequestData = NativeRequestData(uri, buffer) 36 runCatching { 37 nativeUnaryCallCallback(nativeRequestData) 38 }.onFailure { 39 Log.e("SnapEnhance", "nativeUnaryCallCallback failed", it) 40 } 41 if (nativeRequestData.canceled || !nativeRequestData.buffer.contentEquals(buffer)) return nativeRequestData 42 return null 43 } 44 45 fun loadNativeConfig(config: NativeConfig) { 46 if (!initialized) return 47 loadConfig(config) 48 } 49 50 fun lockNativeDatabase(name: String, callback: () -> Unit) { 51 if (!initialized) return 52 lockDatabase(name) { 53 runCatching { 54 callback() 55 }.onFailure { 56 Log.e("SnapEnhance", "lockNativeDatabase callback failed", it) 57 } 58 } 59 } 60 61 @SuppressLint("UnsafeDynamicallyLoadedCode") 62 fun loadSharedLibrary(content: ByteArray) { 63 if (!initialized) throw IllegalStateException("NativeLib not initialized") 64 val generatedPath = "/data/app/${Random.nextLong().absoluteValue.toString(16)}.so" 65 addLinkerSharedLibrary(generatedPath, content) 66 System.load(generatedPath) 67 } 68 69 private external fun preInit() 70 private external fun init(signatureCache: String?): String? 71 private external fun loadConfig(config: NativeConfig) 72 private external fun lockDatabase(name: String, callback: Runnable) 73 external fun setComposerLoader(code: String) 74 external fun composerEval(code: String): String? 75 private external fun addLinkerSharedLibrary(path: String, content: ByteArray) 76 }