From d233777773b7be4e5a6fffacbe54cf4c034a6916 Mon Sep 17 00:00:00 2001 From: evermind Date: Tue, 13 Dec 2022 23:11:53 +0100 Subject: [PATCH] goto sleep on double tap on lockscreen This functionality is borrowed (link below) and quickly integrated into firefdskit. (only minimal invasive adjusted to suit here) https://github.com/evermind-zz/dark_tricks/tree/feat_framework_doubleTap_sdk29 borrowed from my commits there: - 02cd061 use isSecurityPatchAfterDecember2022() from Utils - 7cc004e android 10 support for trick_doubleTapLockScreen and trick_doubleTapStatusBar - 9b4d34a use FeatureFactory to determine if a feature should be visible in SettingsActivity - 5b60dfa Feature framework: refactor trick_doubleTap{StatusBar,LockScreen} and trick_quickPulldown --- README.md | 5 + .../firefds/q/firefdskit/FeatureFactory.java | 35 ++++++ .../q/firefdskit/XSysUIFeaturePackage.java | 11 ++ .../DoubleTapStatusBarOrLockScreenSdk29.java | 45 +++++++ ...apStatusBarOrLockScreenSdk31AndHigher.java | 117 ++++++++++++++++++ .../q/firefdskit/features/Feature.java | 20 +++ .../firefds/q/firefdskit/features/Utils.java | 34 +++++ .../q/firefdskit/utils/Preferences.java | 1 + firefdskit/src/main/res/values/strings.xml | 2 + .../src/main/res/xml/lockscreen_settings.xml | 6 + 10 files changed, 276 insertions(+) create mode 100644 firefdskit/src/main/java/sb/firefds/q/firefdskit/FeatureFactory.java create mode 100644 firefdskit/src/main/java/sb/firefds/q/firefdskit/features/DoubleTapStatusBarOrLockScreenSdk29.java create mode 100644 firefdskit/src/main/java/sb/firefds/q/firefdskit/features/DoubleTapStatusBarOrLockScreenSdk31AndHigher.java create mode 100644 firefdskit/src/main/java/sb/firefds/q/firefdskit/features/Feature.java create mode 100644 firefdskit/src/main/java/sb/firefds/q/firefdskit/features/Utils.java diff --git a/README.md b/README.md index 3784b807..ce39737d 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,8 @@ +#### Fork from evermind-zz +added goto sleep on double tap on lockscreen + +#### original readme content below: + # Firefds Kit [Q] Xposed, EdXposed 4 and EdXposed 5 module for Samsung Q devices. diff --git a/firefdskit/src/main/java/sb/firefds/q/firefdskit/FeatureFactory.java b/firefdskit/src/main/java/sb/firefds/q/firefdskit/FeatureFactory.java new file mode 100644 index 00000000..487c0ab6 --- /dev/null +++ b/firefdskit/src/main/java/sb/firefds/q/firefdskit/FeatureFactory.java @@ -0,0 +1,35 @@ +package sb.firefds.q.firefdskit; + +import sb.firefds.q.firefdskit.features.DoubleTapStatusBarOrLockScreenSdk29; +import sb.firefds.q.firefdskit.features.Feature; + +public class FeatureFactory { + + private FeatureFactory() { + } + + /** + * Create instances of features if available. + * + * @param featureName the feature you want to instantiate. See {@link sb.firefds.q.firefdskit.utils.Preferences} + * @return null if feature is not available other the feature you want. + */ + public static Feature createFeature(final String featureName) { + Feature feature = null; + + if (DoubleTapStatusBarOrLockScreenSdk29.isPlatformSupported(featureName)) { + feature = new DoubleTapStatusBarOrLockScreenSdk29(); + } + return feature; + } + + /** + * Check if a feature is available on this android platform. + * + * @param featureName the feature you want to instantiate. See {@link sb.firefds.q.firefdskit.utils.Preferences} + * @return true if available otherwise false + */ + public static boolean hasFeature(final String featureName) { + return DoubleTapStatusBarOrLockScreenSdk29.isPlatformSupported(featureName); + } +} diff --git a/firefdskit/src/main/java/sb/firefds/q/firefdskit/XSysUIFeaturePackage.java b/firefdskit/src/main/java/sb/firefds/q/firefdskit/XSysUIFeaturePackage.java index 81f25729..df9e3d5f 100644 --- a/firefdskit/src/main/java/sb/firefds/q/firefdskit/XSysUIFeaturePackage.java +++ b/firefdskit/src/main/java/sb/firefds/q/firefdskit/XSysUIFeaturePackage.java @@ -37,6 +37,9 @@ import de.robv.android.xposed.XSharedPreferences; import de.robv.android.xposed.XposedBridge; import de.robv.android.xposed.XposedHelpers; +import sb.firefds.q.firefdskit.features.Feature; +import sb.firefds.q.firefdskit.features.Utils; +import sb.firefds.q.firefdskit.utils.Preferences; import static sb.firefds.q.firefdskit.utils.Packages.SYSTEM_UI; import static sb.firefds.q.firefdskit.utils.Preferences.PREF_CLOCK_DATE_ON_RIGHT; @@ -80,6 +83,7 @@ public class XSysUIFeaturePackage { public static void doHook(XSharedPreferences prefs, ClassLoader classLoader) { + Utils utils = new Utils(); try { if (prefs.getBoolean(PREF_STATUSBAR_DOUBLE_TAP, false)) { XposedHelpers.findAndHookMethod(CUSTOM_SDK_MONITOR, @@ -88,6 +92,13 @@ public static void doHook(XSharedPreferences prefs, ClassLoader classLoader) { XC_MethodReplacement.returnConstant(Boolean.TRUE)); } + if (prefs.getBoolean(Preferences.PREF_LOCKSCREEN_DOUBLE_TAP, false)) { + Feature feature = FeatureFactory.createFeature(Preferences.PREF_LOCKSCREEN_DOUBLE_TAP); + if (feature != null) { + feature.inject(classLoader, prefs, utils); + } + } + if (prefs.getBoolean(PREF_DISABLE_EYE_STRAIN_DIALOG, false)) { XposedHelpers.findAndHookMethod(TOGGLE_SLIDER_VIEW, classLoader, diff --git a/firefdskit/src/main/java/sb/firefds/q/firefdskit/features/DoubleTapStatusBarOrLockScreenSdk29.java b/firefdskit/src/main/java/sb/firefds/q/firefdskit/features/DoubleTapStatusBarOrLockScreenSdk29.java new file mode 100644 index 00000000..cfa10443 --- /dev/null +++ b/firefdskit/src/main/java/sb/firefds/q/firefdskit/features/DoubleTapStatusBarOrLockScreenSdk29.java @@ -0,0 +1,45 @@ +package sb.firefds.q.firefdskit.features; + +import android.content.Context; +import android.os.Build; +import android.os.PowerManager; +import android.view.MotionEvent; + +import java.util.Objects; + +import de.robv.android.xposed.XC_MethodHook; +import de.robv.android.xposed.XSharedPreferences; +import sb.firefds.q.firefdskit.utils.Preferences; + +import static de.robv.android.xposed.XposedHelpers.findAndHookMethod; +import static de.robv.android.xposed.XposedHelpers.getObjectField; + +public class DoubleTapStatusBarOrLockScreenSdk29 extends DoubleTapStatusBarOrLockScreenSdk31AndHigher { + + public static boolean isPlatformSupported(final String featureName) { + return Build.VERSION.SDK_INT == 29 // Android 10 + && (Objects.equals(featureName, Preferences.PREF_LOCKSCREEN_DOUBLE_TAP)); + } + + @Override + public void inject(final ClassLoader classLoader, + final XSharedPreferences pref, + final Utils utils) { + findAndHookMethod("com.android.systemui.statusbar.phone.PanelView", classLoader, "onFinishInflate", new XC_MethodHook() { + @Override + protected void afterHookedMethod(MethodHookParam param) { + final Context context = (Context) getObjectField(param.thisObject, "mContext"); + if (mPowerManager == null) + mPowerManager = context.getSystemService(PowerManager.class); + registerGestureDetectorListener(param, context, mPowerManager); + } + }); + + findAndHookMethod("com.android.systemui.statusbar.phone.NotificationPanelView", classLoader, "onTouchEvent", MotionEvent.class, new XC_MethodHook() { + @Override + protected void beforeHookedMethod(MethodHookParam param) { + fireOnTouchEventIfPossible((MotionEvent) param.args[0], pref); + } + }); + } +} diff --git a/firefdskit/src/main/java/sb/firefds/q/firefdskit/features/DoubleTapStatusBarOrLockScreenSdk31AndHigher.java b/firefdskit/src/main/java/sb/firefds/q/firefdskit/features/DoubleTapStatusBarOrLockScreenSdk31AndHigher.java new file mode 100644 index 00000000..8bb50f6d --- /dev/null +++ b/firefdskit/src/main/java/sb/firefds/q/firefdskit/features/DoubleTapStatusBarOrLockScreenSdk31AndHigher.java @@ -0,0 +1,117 @@ +package sb.firefds.q.firefdskit.features; + +import android.content.Context; +import android.os.Build; +import android.os.PowerManager; +import android.view.GestureDetector; +import android.view.MotionEvent; +import android.view.View; + +import java.util.Objects; + +import de.robv.android.xposed.XC_MethodHook; +import de.robv.android.xposed.XSharedPreferences; + +import static de.robv.android.xposed.XposedHelpers.callMethod; +import static de.robv.android.xposed.XposedHelpers.findAndHookMethod; +import static de.robv.android.xposed.XposedHelpers.getBooleanField; +import static de.robv.android.xposed.XposedHelpers.getIntField; +import static de.robv.android.xposed.XposedHelpers.getObjectField; +import static sb.firefds.q.firefdskit.utils.Preferences.PREF_LOCKSCREEN_DOUBLE_TAP; + +public class DoubleTapStatusBarOrLockScreenSdk31AndHigher implements Feature { + + protected Object mNotificationPanelViewController; + protected GestureDetector mDoubleTapGesture; + protected int mStatusBarHeight = 0; + protected PowerManager mPowerManager; + private int mStatusBarHeaderHeight = 0; + private long mLastDownEvent = 0L; + + public static boolean isPlatformSupported(final String featureName) { + return Build.VERSION.SDK_INT >= 31 + && (Objects.equals(featureName, PREF_LOCKSCREEN_DOUBLE_TAP)); + } + + @Override + public void inject(final ClassLoader classLoader, + final XSharedPreferences pref, + final Utils utils) { + final String notificationPanelViewController = utils.getComAndroidSystemui_NotificationPanelViewControllerClassName(); + findAndHookMethod(notificationPanelViewController, classLoader, "onFinishInflate", new XC_MethodHook() { + + @Override + protected void afterHookedMethod(MethodHookParam param) { + if (mPowerManager == null) + mPowerManager = (PowerManager) getObjectField(param.thisObject, "mPowerManager"); + mStatusBarHeaderHeight = getIntField(param.thisObject, "mStatusBarHeaderHeightKeyguard"); + final View view = (View) getObjectField(param.thisObject, "mView"); + registerGestureDetectorListener(param, view.getContext(), mPowerManager); + } + }); + + String touchHandler = utils.isSecurityPatchAfterDecember2022() ? "com.android.systemui.shade.PanelViewController$TouchHandler" : "com.android.systemui.statusbar.phone.PanelViewController$TouchHandler"; + findAndHookMethod(touchHandler, classLoader, "onTouch", View.class, MotionEvent.class, new XC_MethodHook() { + @Override + protected void beforeHookedMethod(MethodHookParam param) { + final String notificationPanelView = utils.isSecurityPatchAfterDecember2022() ? "com.android.systemui.shade.NotificationPanelView" : "com.android.systemui.statusbar.phone.NotificationPanelView"; + if (param.args[0].getClass().getName().equals(notificationPanelView)) { + fireOnTouchEventIfPossible((MotionEvent) param.args[1], pref); + } + } + }); + + if (pref.getBoolean(PREF_LOCKSCREEN_DOUBLE_TAP, false)) { + findAndHookMethod("com.android.systemui.statusbar.DragDownHelper", classLoader, "onInterceptTouchEvent", MotionEvent.class, new XC_MethodHook() { + @Override + protected void beforeHookedMethod(MethodHookParam param) { + MotionEvent event = (MotionEvent) param.args[0]; + long time = event.getEventTime(); + View host = (View) getObjectField(param.thisObject, "host"); + if (mPowerManager == null) + mPowerManager = (PowerManager) host.getContext().getSystemService(Context.POWER_SERVICE); + if (event.getActionMasked() == MotionEvent.ACTION_DOWN + && event.getY() < mStatusBarHeaderHeight) { + if (time - mLastDownEvent < 300) { + callMethod(mPowerManager, "goToSleep", time); + } + mLastDownEvent = event.getEventTime(); + } + } + }); + } + } + + protected void registerGestureDetectorListener(final XC_MethodHook.MethodHookParam param, + final Context context, + final PowerManager powerManager) { + mNotificationPanelViewController = param.thisObject; + mStatusBarHeight = getIntField(param.thisObject, "mStatusBarMinHeight"); + + if (mDoubleTapGesture == null) { + mDoubleTapGesture = new GestureDetector(context, + new GestureDetector.SimpleOnGestureListener() { + @Override + public boolean onDoubleTap(MotionEvent e) { + callMethod(powerManager, "goToSleep", e.getEventTime()); + return true; + } + }); + } + } + + protected void fireOnTouchEventIfPossible(final MotionEvent event, + final XSharedPreferences pref) { + if (mNotificationPanelViewController != null && mDoubleTapGesture != null) { + boolean isExpanded = getBooleanField(mNotificationPanelViewController, "mQsExpanded"); + boolean isPulsing = getBooleanField(mNotificationPanelViewController, "mPulsing"); + boolean isDozing = getBooleanField(mNotificationPanelViewController, "mDozing"); + boolean isKeyguard = getIntField(mNotificationPanelViewController, "mBarState") == 1 + && !isPulsing && !isDozing; + //boolean isStatusBar = event.getY() < mStatusBarHeight && !isExpanded; + + if (isKeyguard && pref.getBoolean(PREF_LOCKSCREEN_DOUBLE_TAP, false)) + mDoubleTapGesture.onTouchEvent(event); + } + } +} diff --git a/firefdskit/src/main/java/sb/firefds/q/firefdskit/features/Feature.java b/firefdskit/src/main/java/sb/firefds/q/firefdskit/features/Feature.java new file mode 100644 index 00000000..e0707a6c --- /dev/null +++ b/firefdskit/src/main/java/sb/firefds/q/firefdskit/features/Feature.java @@ -0,0 +1,20 @@ +package sb.firefds.q.firefdskit.features; + +import de.robv.android.xposed.XSharedPreferences; +import sb.firefds.q.firefdskit.FeatureFactory; + +/** + * A feature is the implementation of an modification you want to do with Xposed. + *

+ * Every class that implements {@link Feature} should also implement a static method + * that determines if a feature is supported on which platforms. The static method + * should have a signature like this: + *

+ * static boolean hasFeature(String featureName); + *

+ * This method should be used in the {@link FeatureFactory} to + * actually create the feature if available. + */ +public interface Feature { + void inject(ClassLoader param, XSharedPreferences pref, Utils utils); +} diff --git a/firefdskit/src/main/java/sb/firefds/q/firefdskit/features/Utils.java b/firefdskit/src/main/java/sb/firefds/q/firefdskit/features/Utils.java new file mode 100644 index 00000000..0c043539 --- /dev/null +++ b/firefdskit/src/main/java/sb/firefds/q/firefdskit/features/Utils.java @@ -0,0 +1,34 @@ +package sb.firefds.q.firefdskit.features; + +import android.os.Build; + +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; + +public class Utils { + + private Date securityPatch; + private Date december; + + public Utils() { + initDates(); + } + + private void initDates() { + SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd"); + try { + securityPatch = format.parse(Build.VERSION.SECURITY_PATCH); + december = format.parse("2022-12-01"); + } catch (ParseException ignored) { + } + } + + public String getComAndroidSystemui_NotificationPanelViewControllerClassName() { + return isSecurityPatchAfterDecember2022() ? "com.android.systemui.shade.NotificationPanelViewController" : "com.android.systemui.statusbar.phone.NotificationPanelViewController"; + } + + public boolean isSecurityPatchAfterDecember2022() { + return securityPatch.after(december); + } +} diff --git a/firefdskit/src/main/java/sb/firefds/q/firefdskit/utils/Preferences.java b/firefdskit/src/main/java/sb/firefds/q/firefdskit/utils/Preferences.java index 4c613bd4..676b4474 100644 --- a/firefdskit/src/main/java/sb/firefds/q/firefdskit/utils/Preferences.java +++ b/firefdskit/src/main/java/sb/firefds/q/firefdskit/utils/Preferences.java @@ -19,6 +19,7 @@ public class Preferences { public static final String PREF_FIRST_LAUNCH = "isFirefdsKitFirstLaunch"; public static final String PREF_STATUSBAR_DOUBLE_TAP = "isStatusBarDoubleTapEnabled"; + public static final String PREF_LOCKSCREEN_DOUBLE_TAP = "doubleTapLockScreen"; public static final String PREF_ENABLE_SAMSUNG_BLUR = "enableSamsungBlur"; public static final String PREF_HIDE_USB_NOTIFICATION = "hideUsbNotification"; public static final String PREF_HIDE_CHARGING_NOTIFICATION = "hideChargingNotification"; diff --git a/firefdskit/src/main/res/values/strings.xml b/firefdskit/src/main/res/values/strings.xml index 8bb51e74..f27073e5 100644 --- a/firefdskit/src/main/res/values/strings.xml +++ b/firefdskit/src/main/res/values/strings.xml @@ -226,4 +226,6 @@ Quick panel power button replaced with search button Quick panel power button enabled Firefds Kit is active, but some permissions were not granted.\nSome features will not work correctly.\nPlease check your Magisk installation (sepolicy not granted). + enable double tap on the lockscreen (keyguard) + double tap on the lockscreen diff --git a/firefdskit/src/main/res/xml/lockscreen_settings.xml b/firefdskit/src/main/res/xml/lockscreen_settings.xml index 328b0c5e..ce29a88c 100644 --- a/firefdskit/src/main/res/xml/lockscreen_settings.xml +++ b/firefdskit/src/main/res/xml/lockscreen_settings.xml @@ -16,5 +16,11 @@ android:summary="@string/enable_biometrics_unlock_summary" android:title="@string/enable_biometrics_unlock_title" app:iconSpaceReserved="false" /> + \ No newline at end of file