From 0bb871bf0120a8f723dc309520cbb8a7247614c4 Mon Sep 17 00:00:00 2001 From: WhiteChi Date: Sat, 2 Dec 2023 17:36:34 +0800 Subject: [PATCH] `Shamrock`: fix #115 --- .../shamrock/ui/fragment/LabFragment.kt | 31 ++++++++---- .../fuqiuluo/shamrock/xposed/XposedEntry.kt | 7 +-- .../shamrock/xposed/actions/AntiDetection.kt | 2 - .../loader/{FuckAMS.kt => KeepAlive.kt} | 47 +++++++++++++++++-- 4 files changed, 66 insertions(+), 21 deletions(-) rename xposed/src/main/java/moe/fuqiuluo/shamrock/xposed/loader/{FuckAMS.kt => KeepAlive.kt} (71%) diff --git a/app/src/main/java/moe/fuqiuluo/shamrock/ui/fragment/LabFragment.kt b/app/src/main/java/moe/fuqiuluo/shamrock/ui/fragment/LabFragment.kt index 5dae5f7..b5f139a 100644 --- a/app/src/main/java/moe/fuqiuluo/shamrock/ui/fragment/LabFragment.kt +++ b/app/src/main/java/moe/fuqiuluo/shamrock/ui/fragment/LabFragment.kt @@ -122,16 +122,6 @@ fun LabFragment() { return@Function true } - Function( - title = "自动唤醒QQ", - desc = "QQ进程死亡时重新打开QQ进程,前提本进程存活。", - descColor = color, - isSwitch = ShamrockConfig.enableAutoStart(ctx) - ) { - ShamrockConfig.setAutoStart(ctx, it) - return@Function true - } - Function( title = "开启Shell接口", desc = "可能导致设备被入侵,请勿随意开启。", @@ -142,6 +132,16 @@ fun LabFragment() { return@Function true } + Function( + title = "自动唤醒QQ", + desc = "QQ进程死亡时重新打开QQ进程,前提本进程存活。", + descColor = color, + isSwitch = ShamrockConfig.enableAutoStart(ctx) + ) { + ShamrockConfig.setAutoStart(ctx, it) + return@Function true + } + kotlin.runCatching { ctx.getSharedPreferences("shared_config", Context.MODE_WORLD_READABLE) }.onSuccess { @@ -155,6 +155,17 @@ fun LabFragment() { scope.toast(ctx, LocalString.restartSysToast) return@Function true } + + Function( + title = "禁用Doze模式", + desc = "禁止系统进入节能模式。", + descColor = color, + isSwitch = it.getBoolean("hook_doze", false) + ) { value -> + it.edit().putBoolean("hook_doze", value).apply() + scope.toast(ctx, LocalString.restartSysToast) + return@Function true + } }.onFailure { AppRuntime.log("无法启用附加选项,LSPosed模块未激活或者不支持XSharedPreferences", Level.WARN) } diff --git a/xposed/src/main/java/moe/fuqiuluo/shamrock/xposed/XposedEntry.kt b/xposed/src/main/java/moe/fuqiuluo/shamrock/xposed/XposedEntry.kt index 6753acb..058faa7 100644 --- a/xposed/src/main/java/moe/fuqiuluo/shamrock/xposed/XposedEntry.kt +++ b/xposed/src/main/java/moe/fuqiuluo/shamrock/xposed/XposedEntry.kt @@ -5,16 +5,13 @@ import de.robv.android.xposed.IXposedHookLoadPackage import de.robv.android.xposed.XposedBridge import de.robv.android.xposed.callbacks.XC_LoadPackage import de.robv.android.xposed.XposedBridge.log -import moe.fuqiuluo.shamrock.helper.Level -import moe.fuqiuluo.shamrock.helper.LogCenter import moe.fuqiuluo.shamrock.utils.MMKVFetcher import moe.fuqiuluo.shamrock.xposed.loader.ActionLoader -import moe.fuqiuluo.shamrock.xposed.loader.FuckAMS +import moe.fuqiuluo.shamrock.xposed.loader.KeepAlive import moe.fuqiuluo.shamrock.xposed.loader.LuoClassloader import moe.fuqiuluo.shamrock.tools.FuzzySearchClass import moe.fuqiuluo.shamrock.tools.afterHook import moe.fuqiuluo.shamrock.utils.PlatformUtils -import moe.fuqiuluo.shamrock.xposed.loader.NativeLoader import mqq.app.MobileQQ import java.lang.reflect.Field import java.lang.reflect.Modifier @@ -42,7 +39,7 @@ internal class XposedEntry: IXposedHookLoadPackage { override fun handleLoadPackage(param: XC_LoadPackage.LoadPackageParam) { when (param.packageName) { PACKAGE_NAME_QQ -> entryMQQ(param.classLoader) - "android" -> FuckAMS.injectAMS(param.classLoader) + "android" -> KeepAlive(param.classLoader) PACKAGE_NAME_TIM -> entryTim(param.classLoader) } } diff --git a/xposed/src/main/java/moe/fuqiuluo/shamrock/xposed/actions/AntiDetection.kt b/xposed/src/main/java/moe/fuqiuluo/shamrock/xposed/actions/AntiDetection.kt index 5861098..952dd09 100644 --- a/xposed/src/main/java/moe/fuqiuluo/shamrock/xposed/actions/AntiDetection.kt +++ b/xposed/src/main/java/moe/fuqiuluo/shamrock/xposed/actions/AntiDetection.kt @@ -7,14 +7,12 @@ import android.content.pm.VersionedPackage import android.os.Build import de.robv.android.xposed.XC_MethodReplacement import de.robv.android.xposed.XSharedPreferences -import de.robv.android.xposed.XposedBridge import de.robv.android.xposed.XposedHelpers import moe.fuqiuluo.shamrock.helper.Level import moe.fuqiuluo.shamrock.helper.LogCenter import moe.fuqiuluo.shamrock.remote.service.config.ShamrockConfig import moe.fuqiuluo.shamrock.tools.hookMethod import moe.fuqiuluo.shamrock.xposed.XposedEntry -import moe.fuqiuluo.shamrock.xposed.loader.FuckAMS import moe.fuqiuluo.shamrock.xposed.loader.LuoClassloader import moe.fuqiuluo.shamrock.xposed.loader.NativeLoader diff --git a/xposed/src/main/java/moe/fuqiuluo/shamrock/xposed/loader/FuckAMS.kt b/xposed/src/main/java/moe/fuqiuluo/shamrock/xposed/loader/KeepAlive.kt similarity index 71% rename from xposed/src/main/java/moe/fuqiuluo/shamrock/xposed/loader/FuckAMS.kt rename to xposed/src/main/java/moe/fuqiuluo/shamrock/xposed/loader/KeepAlive.kt index e94002b..9f4586d 100644 --- a/xposed/src/main/java/moe/fuqiuluo/shamrock/xposed/loader/FuckAMS.kt +++ b/xposed/src/main/java/moe/fuqiuluo/shamrock/xposed/loader/KeepAlive.kt @@ -3,14 +3,15 @@ package moe.fuqiuluo.shamrock.xposed.loader import android.content.pm.ApplicationInfo import android.os.Build -import com.arthenica.ffmpegkit.BuildConfig +import android.os.Process import de.robv.android.xposed.XSharedPreferences import de.robv.android.xposed.XposedBridge import de.robv.android.xposed.XposedHelpers import moe.fuqiuluo.shamrock.tools.hookMethod import java.lang.reflect.Method +import kotlin.concurrent.timer -internal object FuckAMS { +internal object KeepAlive { private val KeepPackage = arrayOf( "com.tencent.mobileqq", "moe.fuqiuluo.shamrock" ) @@ -20,7 +21,46 @@ internal object FuckAMS { private lateinit var METHOD_IS_KILLED: Method private var allowPersistent: Boolean = false - fun injectAMS(loader: ClassLoader) { + operator fun invoke(loader: ClassLoader) { + val pref = XSharedPreferences("moe.fuqiuluo.shamrock", "shared_config") + hookAMS(pref, loader) + hookDoze(pref, loader) + } + + private fun hookDoze(pref: XSharedPreferences, loader: ClassLoader) { + if (pref.file.canRead() && pref.getBoolean("hook_doze", false)) { + val result = runCatching { + val DeviceIdleController = XposedHelpers.findClass("com.android.server.DeviceIdleController", loader) + ?: return@runCatching -1 + val becomeActiveLocked = XposedHelpers.findMethodBestMatch(DeviceIdleController, "becomeActiveLocked", String::class.java, Integer.TYPE) + ?: return@runCatching -2 + if (!becomeActiveLocked.isAccessible) { + becomeActiveLocked.isAccessible = true + } + DeviceIdleController.hookMethod("onStart").after { + XposedBridge.log("[Shamrock] DeviceIdleController onStart") + timer(initialDelay = 120_000L, period = 240_000L) { + XposedBridge.log("[Shamrock] try to wakeup screen") + becomeActiveLocked.invoke(it.thisObject, "screen", Process.myUid()) + } + } + DeviceIdleController.hookMethod("becomeInactiveIfAppropriateLocked").before { + XposedBridge.log("[Shamrock] DeviceIdleController becomeInactiveIfAppropriateLocked") + it.result = Unit + } + DeviceIdleController.hookMethod("stepIdleStateLocked").before { + XposedBridge.log("[Shamrock] DeviceIdleController stepIdleStateLocked") + it.result = Unit + } + return@runCatching 0 + }.getOrElse { -5 } + if(result < 0) { + XposedBridge.log("[Shamrock] Unable to hookDoze: $result") + } + } + } + + private fun hookAMS(pref: XSharedPreferences, loader: ClassLoader) { kotlin.runCatching { val ActivityManagerService = XposedHelpers.findClass("com.android.server.am.ActivityManagerService", loader) ActivityManagerService.hookMethod("newProcessRecordLocked").after { @@ -30,7 +70,6 @@ internal object FuckAMS { XposedBridge.log("[Shamrock] Plan A failed: ${it.message}") } - val pref = XSharedPreferences("moe.fuqiuluo.shamrock", "shared_config") if (pref.file.canRead()) { allowPersistent = pref.getBoolean("persistent", false) XposedBridge.log("[Shamrock] allowPersistent = $allowPersistent")