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 }