From a31d38f979cd5b243a1ca27481ea60dd26b5e7e6 Mon Sep 17 00:00:00 2001 From: sekaiacg Date: Sun, 13 Sep 2026 15:43:40 +0800 Subject: [PATCH] feat(Battery-saver): Battery-saver mode allows enabling haptic feedback and locking FPS --- .../main/res/values-zh-rCN/strings_app.xml | 2 + .../core/src/main/res/values/strings_app.xml | 2 + .../main/res/xml/security_center_battery.xml | 10 ++++ .../libhook/app/SecurityCenter.java | 4 ++ .../BatterySaverEnableHapticFeedback.kt | 60 +++++++++++++++++++ .../battery/BatterySaverLockFps.kt | 60 +++++++++++++++++++ 6 files changed, 138 insertions(+) create mode 100644 library/libhook/src/main/java/com/sevtinge/hyperceiler/libhook/rules/securitycenter/battery/BatterySaverEnableHapticFeedback.kt create mode 100644 library/libhook/src/main/java/com/sevtinge/hyperceiler/libhook/rules/securitycenter/battery/BatterySaverLockFps.kt diff --git a/library/core/src/main/res/values-zh-rCN/strings_app.xml b/library/core/src/main/res/values-zh-rCN/strings_app.xml index 34b466a8dc..0b158066d7 100644 --- a/library/core/src/main/res/values-zh-rCN/strings_app.xml +++ b/library/core/src/main/res/values-zh-rCN/strings_app.xml @@ -1560,6 +1560,8 @@ 解锁低温超级续航 显示更多电池信息 实验性功能,具体支持显示内容因设备而异 + 省电模式开启触摸反馈 + 省电模式锁定当前帧率 解锁晕车缓解 需要 \"弹幕通知\" 支持 禁用网络助手离线配置 diff --git a/library/core/src/main/res/values/strings_app.xml b/library/core/src/main/res/values/strings_app.xml index db3ac8106e..3f4407955b 100644 --- a/library/core/src/main/res/values/strings_app.xml +++ b/library/core/src/main/res/values/strings_app.xml @@ -1607,6 +1607,8 @@ Unlock Cold endurance mode Show more battery info Experimental feature. The additional battery information displayed may vary depending on the device. + Enable haptic feedback in battery saver + Battery saver lock FPS Unlock Motion sickness relief Needs \"Barrage\" support Disable network assistant offline info diff --git a/library/core/src/main/res/xml/security_center_battery.xml b/library/core/src/main/res/xml/security_center_battery.xml index 17cf47528c..d30f5e31d1 100644 --- a/library/core/src/main/res/xml/security_center_battery.xml +++ b/library/core/src/main/res/xml/security_center_battery.xml @@ -63,5 +63,15 @@ android:key="prefs_key_security_center_unlock_smart_charge" android:title="@string/security_center_unlock_smart_charge_title" /> + + + + \ No newline at end of file diff --git a/library/libhook/src/main/java/com/sevtinge/hyperceiler/libhook/app/SecurityCenter.java b/library/libhook/src/main/java/com/sevtinge/hyperceiler/libhook/app/SecurityCenter.java index 17b1f786b8..a9bba16f31 100644 --- a/library/libhook/src/main/java/com/sevtinge/hyperceiler/libhook/app/SecurityCenter.java +++ b/library/libhook/src/main/java/com/sevtinge/hyperceiler/libhook/app/SecurityCenter.java @@ -47,6 +47,8 @@ import com.sevtinge.hyperceiler.libhook.rules.securitycenter.app.AppRestrict; import com.sevtinge.hyperceiler.libhook.rules.securitycenter.app.OpenByDefaultSetting; import com.sevtinge.hyperceiler.libhook.rules.securitycenter.battery.BatteryHealth; +import com.sevtinge.hyperceiler.libhook.rules.securitycenter.battery.BatterySaverEnableHapticFeedback; +import com.sevtinge.hyperceiler.libhook.rules.securitycenter.battery.BatterySaverLockFps; import com.sevtinge.hyperceiler.libhook.rules.securitycenter.battery.MoreBatteryInfoNew; import com.sevtinge.hyperceiler.libhook.rules.securitycenter.battery.PowerConsumptionRanking; import com.sevtinge.hyperceiler.libhook.rules.securitycenter.battery.ScreenUsedTime; @@ -100,6 +102,8 @@ public void onPackageLoaded() { initHook(BatteryHealth.INSTANCE, PrefsBridge.getBoolean("security_center_show_battery_health")); initHook(new UnlockLowTempExtEndurance(), PrefsBridge.getBoolean("security_center_battery_unlock_low_temp_ext_endurance")); initHook(MoreBatteryInfoNew.INSTANCE, PrefsBridge.getBoolean("secutity_center_battery_show_more_info")); + initHook(BatterySaverEnableHapticFeedback.INSTANCE, PrefsBridge.getBoolean("secutity_center_battery_saver_enable_haptic_feedback")); + initHook(BatterySaverLockFps.INSTANCE, PrefsBridge.getBoolean("secutity_center_battery_saver_lock_fps")); // 隐私保护 initHook(new AppLockPinScramble(), PrefsBridge.getBoolean("security_center_applock_pin_scramble")); diff --git a/library/libhook/src/main/java/com/sevtinge/hyperceiler/libhook/rules/securitycenter/battery/BatterySaverEnableHapticFeedback.kt b/library/libhook/src/main/java/com/sevtinge/hyperceiler/libhook/rules/securitycenter/battery/BatterySaverEnableHapticFeedback.kt new file mode 100644 index 0000000000..3306c1351d --- /dev/null +++ b/library/libhook/src/main/java/com/sevtinge/hyperceiler/libhook/rules/securitycenter/battery/BatterySaverEnableHapticFeedback.kt @@ -0,0 +1,60 @@ +/* + * This file is part of HyperCeiler. + + * HyperCeiler is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + + * Copyright (C) 2023-2026 HyperCeiler Contributions +*/ +package com.sevtinge.hyperceiler.libhook.rules.securitycenter.battery + +import com.sevtinge.hyperceiler.common.log.XposedLog +import com.sevtinge.hyperceiler.libhook.base.BaseHook +import io.github.lingqiqi5211.ezhooktool.xposed.dsl.createHook +import java.lang.reflect.Method +import java.lang.reflect.Modifier + +object BatterySaverEnableHapticFeedback : BaseHook() { + override fun useDexKit() = true + + override fun initDexKit(): Boolean { + hapticFeedbackMethodList + return true + } + + private val hapticFeedbackMethodList by lazy> { + optionalMemberList("BatterySaverLockHapticFeedback") { + it.findMethod { + matcher { + declaredClass { + usingEqStrings("sys.haptic.motor", "power_center_haptic_feed_back_mode", "haptic_feedback_enabled") + } + usingEqStrings("power_center_haptic_feed_back_mode", "haptic_feedback_enabled") + modifiers = Modifier.PUBLIC + returnType = "void" + paramCount = 1 + paramTypes("android.content.Context") + } + } + } + } + + override fun init() { + hapticFeedbackMethodList.forEach { + it.createHook { + returnConstant(null) + } + } + } +} + diff --git a/library/libhook/src/main/java/com/sevtinge/hyperceiler/libhook/rules/securitycenter/battery/BatterySaverLockFps.kt b/library/libhook/src/main/java/com/sevtinge/hyperceiler/libhook/rules/securitycenter/battery/BatterySaverLockFps.kt new file mode 100644 index 0000000000..cee0626c98 --- /dev/null +++ b/library/libhook/src/main/java/com/sevtinge/hyperceiler/libhook/rules/securitycenter/battery/BatterySaverLockFps.kt @@ -0,0 +1,60 @@ +/* + * This file is part of HyperCeiler. + + * HyperCeiler is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + + * Copyright (C) 2023-2026 HyperCeiler Contributions +*/ +package com.sevtinge.hyperceiler.libhook.rules.securitycenter.battery + +import com.sevtinge.hyperceiler.common.log.XposedLog +import com.sevtinge.hyperceiler.libhook.base.BaseHook +import io.github.lingqiqi5211.ezhooktool.xposed.dsl.createHook +import java.lang.reflect.Method +import java.lang.reflect.Modifier + +object BatterySaverLockFps : BaseHook() { + override fun useDexKit() = true + + override fun initDexKit(): Boolean { + lockFpsMethod + return true + } + + private val lockFpsMethod by lazy { + optionalMember("BatterySaverLockFps") { + it.findMethod { + matcher { + declaredClass { + usingEqStrings("LowFpsPowerMode", "user_refresh_rate", "miui_refresh_rate") + } + usingEqStrings("user_refresh_rate", "miui_refresh_rate") + modifiers = Modifier.PRIVATE + returnType = "void" + paramCount = 2 + paramTypes("android.content.Context", "int") + } + }.singleOrNull() + } + } + + override fun init() { + lockFpsMethod?.let { + it.createHook { + returnConstant(null) + } + } + } +} +