commit d8e98d575bca8cca12c3cfa163ec89cb2abee5fd
parent 4b93ec7181d02dd11d27039adea082ac91870eaa
Author: rhunk <101876869+rhunk@users.noreply.github.com>
Date:   Thu, 27 Jun 2024 23:06:29 +0200

fix(core/xposed_loader): prevent loading in sub processes

Signed-off-by: rhunk <101876869+rhunk@users.noreply.github.com>

Diffstat:
Mcore/src/main/kotlin/me/rhunk/snapenhance/core/SnapEnhance.kt | 148++++++++++++++++++++++++++++++++++++++-----------------------------------------
Mcore/src/main/kotlin/me/rhunk/snapenhance/core/XposedLoader.kt | 12+++++++++++-
2 files changed, 83 insertions(+), 77 deletions(-)

diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/SnapEnhance.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/SnapEnhance.kt @@ -1,7 +1,6 @@ package me.rhunk.snapenhance.core import android.app.Activity -import android.app.Application import android.content.Context import android.content.res.Resources import android.os.Build @@ -53,91 +52,88 @@ class SnapEnhance { } } - init { - Application::class.java.hook("attach", HookStage.BEFORE) { param -> - appContext = ModContext( - androidContext = param.arg<Context>(0).also { classLoader = it.classLoader } - ) - appContext.apply { - bridgeClient = BridgeClient(this) - initConfigListener() - bridgeClient.addOnConnectedCallback { - bridgeClient.registerMessagingBridge(messagingBridge) - coroutineScope.launch { - runCatching { - syncRemote() - }.onFailure { - log.error("Failed to sync remote", it) - } + fun init(context: Context) { + appContext = ModContext( + androidContext = context.also { classLoader = it.classLoader } + ) + appContext.apply { + bridgeClient = BridgeClient(this) + initConfigListener() + bridgeClient.addOnConnectedCallback { + bridgeClient.registerMessagingBridge(messagingBridge) + coroutineScope.launch { + runCatching { + syncRemote() + }.onFailure { + log.error("Failed to sync remote", it) } } } + } - runBlocking { - var throwable: Throwable? = null - val canLoad = appContext.bridgeClient.connect { throwable = it } - if (canLoad == null) { - InAppOverlay.showCrashOverlay( - buildString { - append("Snapchat timed out while trying to connect to SnapEnhance\n\n") - append("Make sure you:\n") - append(" - Have installed the latest SnapEnhance version (https://github.com/rhunk/SnapEnhance)\n") - append(" - Disabled battery optimizations\n") - append(" - Excluded SnapEnhance and Snapchat in HideMyApplist") - }, - throwable - ) - appContext.logCritical("Cannot connect to the SnapEnhance app") - return@runBlocking - } - if (!canLoad) exitProcess(1) - runCatching { - LSPatchUpdater.onBridgeConnected(appContext) - }.onFailure { - appContext.log.error("Failed to init LSPatchUpdater", it) - } - jetpackComposeResourceHook() - runCatching { - measureTimeMillis { - init(this) - }.also { - appContext.log.verbose("init took ${it}ms") - } - }.onSuccess { - isBridgeInitialized = true - }.onFailure { - appContext.logCritical("Failed to initialize bridge", it) - InAppOverlay.showCrashOverlay("SnapEnhance failed to initialize. Please check logs for more details.", it) - } + runBlocking { + var throwable: Throwable? = null + val canLoad = appContext.bridgeClient.connect { throwable = it } + if (canLoad == null) { + InAppOverlay.showCrashOverlay( + buildString { + append("Snapchat timed out while trying to connect to SnapEnhance\n\n") + append("Make sure you:\n") + append(" - Have installed the latest SnapEnhance version (https://github.com/rhunk/SnapEnhance)\n") + append(" - Disabled battery optimizations\n") + append(" - Excluded SnapEnhance and Snapchat in HideMyApplist") + }, + throwable + ) + appContext.logCritical("Cannot connect to the SnapEnhance app") + return@runBlocking } - } + if (!canLoad) exitProcess(1) + runCatching { + LSPatchUpdater.onBridgeConnected(appContext) + }.onFailure { + appContext.log.error("Failed to init LSPatchUpdater", it) + } + jetpackComposeResourceHook() + runCatching { + measureTimeMillis { + init(this) + }.also { + appContext.log.verbose("init took ${it}ms") + } - hookMainActivity("onCreate") { - val isMainActivityNotNull = appContext.mainActivity != null - appContext.mainActivity = this - if (isMainActivityNotNull || !appContext.mappings.isMappingsLoaded) return@hookMainActivity - appContext.isMainActivityPaused = false - onActivityCreate() - appContext.actionManager.onNewIntent(intent) - } + hookMainActivity("onPostCreate") { + appContext.mainActivity = this + if (!appContext.mappings.isMappingsLoaded) return@hookMainActivity + appContext.isMainActivityPaused = false + onActivityCreate() + appContext.actionManager.onNewIntent(intent) + } - hookMainActivity("onPause") { - appContext.bridgeClient.closeOverlay() - appContext.isMainActivityPaused = true - } + hookMainActivity("onPause") { + appContext.bridgeClient.closeOverlay() + appContext.isMainActivityPaused = true + } - hookMainActivity("onNewIntent") { param -> - appContext.actionManager.onNewIntent(param.argNullable(0)) - } + hookMainActivity("onNewIntent") { param -> + appContext.actionManager.onNewIntent(param.argNullable(0)) + } - hookMainActivity("onResume") { - if (appContext.isMainActivityPaused.also { - appContext.isMainActivityPaused = false - }) { - appContext.reloadConfig() - appContext.executeAsync { - syncRemote() + hookMainActivity("onResume") { + if (appContext.isMainActivityPaused.also { + appContext.isMainActivityPaused = false + }) { + appContext.reloadConfig() + appContext.executeAsync { + syncRemote() + } + } } + }.onSuccess { + isBridgeInitialized = true + }.onFailure { + appContext.logCritical("Failed to initialize bridge", it) + InAppOverlay.showCrashOverlay("SnapEnhance failed to initialize. Please check logs for more details.", it) } } } diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/XposedLoader.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/XposedLoader.kt @@ -1,12 +1,22 @@ package me.rhunk.snapenhance.core +import android.app.Application import de.robv.android.xposed.IXposedHookLoadPackage +import de.robv.android.xposed.XposedBridge import de.robv.android.xposed.callbacks.XC_LoadPackage +import me.rhunk.snapenhance.common.BuildConfig import me.rhunk.snapenhance.common.Constants +import me.rhunk.snapenhance.core.util.hook.HookStage +import me.rhunk.snapenhance.core.util.hook.hook class XposedLoader : IXposedHookLoadPackage { override fun handleLoadPackage(p0: XC_LoadPackage.LoadPackageParam) { if (p0.packageName != Constants.SNAPCHAT_PACKAGE_NAME) return - SnapEnhance() + // prevent loading in sub-processes + if (p0.processName.contains(":")) return + XposedBridge.log("Loading SnapEnhance v${BuildConfig.VERSION_NAME}#${BuildConfig.GIT_HASH} (package: ${BuildConfig.APPLICATION_ID})") + Application::class.java.hook("attach", HookStage.BEFORE) { param -> + SnapEnhance().init(param.arg(0)) + } } } \ No newline at end of file