From 43edb4e86905182a7442c705bfd5e5cdcf45ccf2 Mon Sep 17 00:00:00 2001 From: rmp22 <195054967+rmp22@users.noreply.github.com> Date: Fri, 16 May 2025 07:04:39 +0800 Subject: [PATCH 1/8] services: Fixing default blur enablement value Change-Id: Ia90417fc2a062de61d1f71987ace25ab4d5f5fdf Signed-off-by: rmp22 <195054967+rmp22@users.noreply.github.com> Signed-off-by: Ghosuto Signed-off-by: TopexGuy --- services/core/java/com/android/server/wm/BlurController.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/services/core/java/com/android/server/wm/BlurController.java b/services/core/java/com/android/server/wm/BlurController.java index 03639449c3df1..886ff6ca44a21 100644 --- a/services/core/java/com/android/server/wm/BlurController.java +++ b/services/core/java/com/android/server/wm/BlurController.java @@ -136,7 +136,8 @@ private void notifyBlurEnabledChangedLocked(boolean enabled) { } private boolean getBlurDisabledSetting() { + boolean blurEnabledByDefault = android.os.SystemProperties.getBoolean("ro.custom.blur.enable", false); return Settings.Global.getInt(mContext.getContentResolver(), - Settings.Global.DISABLE_WINDOW_BLURS, 0) == 1; + Settings.Global.DISABLE_WINDOW_BLURS, blurEnabledByDefault ? 0 : 1) == 1; } } From 1b37b0eb1b415ab443644b59aba010ce0875e116 Mon Sep 17 00:00:00 2001 From: rmp22 <195054967+rmp22@users.noreply.github.com> Date: Fri, 23 Jan 2026 13:33:23 +0800 Subject: [PATCH 2/8] [feature] adding blur intensity settings Change-Id: I5c21a309c8ca16d0bb45b0708f0a7e04e848c492 Signed-off-by: Ghosuto Signed-off-by: TopexGuy --- ...ncerToPrimaryBouncerTransitionViewModel.kt | 19 +++++++++++++------ .../android/systemui/statusbar/BlurUtils.kt | 19 +++++++++++++------ .../NotificationShadeDepthController.kt | 7 ++++++- 3 files changed, 32 insertions(+), 13 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerToPrimaryBouncerTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerToPrimaryBouncerTransitionViewModel.kt index 1799d0a384ff3..82c2980dd66cf 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerToPrimaryBouncerTransitionViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerToPrimaryBouncerTransitionViewModel.kt @@ -29,6 +29,7 @@ import com.android.systemui.keyguard.ui.transitions.PrimaryBouncerTransition import com.android.systemui.scene.shared.flag.SceneContainerFlag import com.android.systemui.scene.shared.model.Overlays import com.android.systemui.scene.ui.composable.transitions.TO_BOUNCER_FADE_FRACTION +import com.android.systemui.util.settings.SecureSettings import javax.inject.Inject import kotlin.time.Duration.Companion.milliseconds import kotlinx.coroutines.flow.Flow @@ -41,8 +42,11 @@ import kotlinx.coroutines.flow.emptyFlow @SysUISingleton class AlternateBouncerToPrimaryBouncerTransitionViewModel @Inject -constructor(animationFlow: KeyguardTransitionAnimationFlow, blurConfig: BlurConfig) : - DeviceEntryIconTransition, PrimaryBouncerTransition { +constructor( + animationFlow: KeyguardTransitionAnimationFlow, + blurConfig: BlurConfig, + private val secureSettings: SecureSettings, +) : DeviceEntryIconTransition, PrimaryBouncerTransition { private val transitionAnimation = animationFlow .setup( @@ -88,12 +92,15 @@ constructor(animationFlow: KeyguardTransitionAnimationFlow, blurConfig: BlurConf alphaFlow } + val maxBlurRadius: Float + get() = secureSettings.getFloat("system_blur_radius", 34f) + override val notificationBlurRadius: Flow = if (Flags.bouncerUiRevamp()) { transitionAnimation.sharedFlowWithShade( duration = 1.milliseconds, onStep = { _, isShadeExpanded -> - if (isShadeExpanded) blurConfig.maxBlurRadiusPx else null + if (isShadeExpanded) maxBlurRadius else null }, ) } else { @@ -109,14 +116,14 @@ constructor(animationFlow: KeyguardTransitionAnimationFlow, blurConfig: BlurConf onStep = { step, isShadeExpanded -> if (isShadeExpanded) { if (Flags.notificationShadeBlur()) { - blurConfig.maxBlurRadiusPx + maxBlurRadius } else { blurConfig.minBlurRadiusPx } } else { transitionProgressToBlurRadius( starBlurRadius = blurConfig.minBlurRadiusPx, - endBlurRadius = blurConfig.maxBlurRadiusPx, + endBlurRadius = maxBlurRadius, transitionProgress = step, ) } @@ -125,7 +132,7 @@ constructor(animationFlow: KeyguardTransitionAnimationFlow, blurConfig: BlurConf if (isShadeExpanded && !Flags.notificationShadeBlur()) { blurConfig.minBlurRadiusPx } else { - blurConfig.maxBlurRadiusPx + maxBlurRadius } }, ) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BlurUtils.kt b/packages/SystemUI/src/com/android/systemui/statusbar/BlurUtils.kt index bad2d77d2075a..fe16970fe9e14 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/BlurUtils.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/BlurUtils.kt @@ -25,6 +25,7 @@ import android.os.Build import android.os.SystemProperties import android.os.Trace import android.os.Trace.TRACE_TAG_APP +import android.os.UserHandle import android.util.IndentingPrintWriter import android.util.Log import android.util.MathUtils @@ -41,8 +42,11 @@ import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.dump.DumpManager import com.android.systemui.keyguard.ui.transitions.BlurConfig import com.android.systemui.res.R +import com.android.systemui.util.settings.SettingsProxyExt.observerFlow +import com.android.systemui.util.settings.SecureSettings import java.io.PrintWriter import javax.inject.Inject +import kotlinx.coroutines.flow.* @SysUISingleton open class BlurUtils @@ -52,14 +56,17 @@ constructor( blurConfig: BlurConfig, private val crossWindowBlurListeners: CrossWindowBlurListeners, dumpManager: DumpManager, + private val secureSettings: SecureSettings, ) : Dumpable { val minBlurRadius = resources.getDimensionPixelSize(R.dimen.min_window_blur_radius).toFloat() - val maxBlurRadius = - if (Flags.notificationShadeBlur()) { - blurConfig.maxBlurRadiusPx - } else { - resources.getDimensionPixelSize(R.dimen.max_window_blur_radius).toFloat() - } + val maxBlurRadius: Float + get() = secureSettings.getFloatForUser("system_blur_radius", 34f, UserHandle.USER_CURRENT) + + val maxBlurRadiusFlow: Flow = secureSettings + .observerFlow("system_blur_radius") + .onStart { emit(Unit) } + .map { maxBlurRadius } + .distinctUntilChanged() private var lastAppliedBlur = 0 private var lastTargetViewRootImpl: ViewRootImpl? = null diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeDepthController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeDepthController.kt index a3cab4ed4d3e6..07fc3b3151ad4 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeDepthController.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeDepthController.kt @@ -138,7 +138,7 @@ constructor( private var isHomeFocused = true - val maxBlurRadiusPx = blurUtils.maxBlurRadius + val maxBlurRadiusPx get() = blurUtils.maxBlurRadius // Shade expansion offset that happens when pulling down on a HUN. var panelPullDownMinFraction = 0f @@ -513,6 +513,11 @@ constructor( } } } + applicationScope.launch { + blurUtils.maxBlurRadiusFlow.collect { + scheduleUpdate() + } + } initBlurListeners() } From 5f19bddd3949ceca8908f3ebd2f89203ab4112d7 Mon Sep 17 00:00:00 2001 From: minaripenguin Date: Thu, 10 Oct 2024 11:00:37 +0800 Subject: [PATCH 3/8] services: Introduce Shake Gestures Co-authored-by: AmeChanRain Change-Id: If2a3c094c2f30e3eb7bf1df811edb482554749bb Signed-off-by: Alvin Francis Signed-off-by: minaripenguin Signed-off-by: Ghosuto Signed-off-by: Mrick343 Signed-off-by: TopexGuy --- .../server/policy/PhoneWindowManager.java | 27 ++++ .../rising/server/ShakeGestureService.java | 106 +++++++++++++++ .../org/rising/server/ShakeGestureUtils.java | 128 ++++++++++++++++++ 3 files changed, 261 insertions(+) create mode 100644 services/core/java/org/rising/server/ShakeGestureService.java create mode 100644 services/core/java/org/rising/server/ShakeGestureUtils.java diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java index d98c36cd5b030..431bdf0da9070 100644 --- a/services/core/java/com/android/server/policy/PhoneWindowManager.java +++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java @@ -283,6 +283,8 @@ import org.lineageos.internal.buttons.LineageButtons; import org.lineageos.internal.util.ActionUtils; +import org.rising.server.ShakeGestureService; + import java.io.File; import java.io.FileNotFoundException; import java.io.FileReader; @@ -708,6 +710,8 @@ public void onDrawn() { ANBIHandler mANBIHandler; private boolean mANBIEnabled; + private ShakeGestureService mShakeGestures; + // Tracks user-customisable behavior for certain key events private Action mBackLongPressAction; private Action mHomeLongPressAction; @@ -722,6 +726,7 @@ public void onDrawn() { private Action mCornerLongSwipeAction; private Action mEdgeLongSwipeAction; private Action mThreeFingersSwipeAction; + private Action mShakeGestureAction; // support for activating the lock screen while the screen is on private HashSet mAllowLockscreenWhenOnDisplays = new HashSet<>(); @@ -1147,6 +1152,9 @@ void observe() { resolver.registerContentObserver(Settings.System.getUriFor( Settings.System.ANBI_ENABLED), false, this, UserHandle.USER_ALL); + resolver.registerContentObserver(LineageSettings.System.getUriFor( + LineageSettings.System.KEY_SHAKE_GESTURE_ACTION), false, this, + UserHandle.USER_ALL); updateSettings(); } @@ -3490,6 +3498,10 @@ private void updateKeyAssignments() { } } + mShakeGestureAction = Action.fromSettings(resolver, + LineageSettings.System.KEY_SHAKE_GESTURE_ACTION, + Action.NOTHING); + mShortPressOnWindowBehavior = SHORT_PRESS_WINDOW_NOTHING; if (mPackageManager.hasSystemFeature(FEATURE_PICTURE_IN_PICTURE)) { mShortPressOnWindowBehavior = SHORT_PRESS_WINDOW_PICTURE_IN_PICTURE; @@ -7071,6 +7083,21 @@ public void systemReady() { if (mVrManagerInternal != null) { mVrManagerInternal.addPersistentVrModeStateListener(mPersistentVrModeListener); } + + mShakeGestures = ShakeGestureService.getInstance(mContext, new ShakeGestureService.ShakeGesturesCallbacks() { + @Override + public void onShake() { + if (mShakeGestureAction == Action.NOTHING) + return; + long now = SystemClock.uptimeMillis(); + KeyEvent event = new KeyEvent(now, now, KeyEvent.ACTION_DOWN, + KeyEvent.KEYCODE_SYSRQ, 0, 0, KeyCharacterMap.VIRTUAL_KEYBOARD, 0, + KeyEvent.FLAG_FROM_SYSTEM, InputDevice.SOURCE_TOUCHSCREEN); + performKeyAction(mShakeGestureAction, event); + performHapticFeedback(HapticFeedbackConstants.LONG_PRESS, "Shake Gesture"); + } + }); + mShakeGestures.onStart(); mDockObserverInternal = LocalServices.getService(DockObserverInternal.class); if (mDockObserverInternal != null) { diff --git a/services/core/java/org/rising/server/ShakeGestureService.java b/services/core/java/org/rising/server/ShakeGestureService.java new file mode 100644 index 0000000000000..6dce9663f1ec5 --- /dev/null +++ b/services/core/java/org/rising/server/ShakeGestureService.java @@ -0,0 +1,106 @@ +/* + * Copyright (C) 2023-2024 The RisingOS Android Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.rising.server; + +import android.content.Context; +import android.database.ContentObserver; +import android.os.Handler; +import android.os.Looper; +import android.os.UserHandle; +import android.provider.Settings; + +public final class ShakeGestureService { + + private static final String TAG = "ShakeGestureService"; + + private static final String SHAKE_GESTURES_ENABLED = "shake_gestures_enabled"; + private static final String SHAKE_GESTURES_ACTION = "shake_gestures_action"; + private static final int USER_ALL = UserHandle.USER_ALL; + + private final Context mContext; + private ShakeGestureUtils mShakeGestureUtils; + private static volatile ShakeGestureService instance; + private final ShakeGesturesCallbacks mShakeCallbacks; + + private final SettingsObserver mSettingsObserver; + private boolean mShakeServiceEnabled = false; + + private ShakeGestureUtils.OnShakeListener mShakeListener; + + public interface ShakeGesturesCallbacks { + void onShake(); + } + + private ShakeGestureService(Context context, ShakeGesturesCallbacks callback) { + mContext = context; + mShakeCallbacks = callback; + mShakeListener = () -> { + if (mShakeServiceEnabled && mShakeCallbacks != null) { + mShakeCallbacks.onShake(); + } + }; + mSettingsObserver = new SettingsObserver(null); + } + + public static synchronized ShakeGestureService getInstance(Context context, ShakeGesturesCallbacks callback) { + if (instance == null) { + synchronized (ShakeGestureService.class) { + if (instance == null) { + instance = new ShakeGestureService(context, callback); + } + } + } + return instance; + } + + public void onStart() { + if (mShakeGestureUtils == null) { + mShakeGestureUtils = new ShakeGestureUtils(mContext); + } + updateSettings(); + mSettingsObserver.observe(); + if (mShakeServiceEnabled) { + mShakeGestureUtils.registerListener(mShakeListener); + } + } + + private void updateSettings() { + boolean wasShakeServiceEnabled = mShakeServiceEnabled; + mShakeServiceEnabled = Settings.System.getInt(mContext.getContentResolver(), + SHAKE_GESTURES_ENABLED, 0) == 1; + if (mShakeServiceEnabled && !wasShakeServiceEnabled) { + mShakeGestureUtils.registerListener(mShakeListener); + } else if (!mShakeServiceEnabled && wasShakeServiceEnabled) { + mShakeGestureUtils.unregisterListener(mShakeListener); + } + } + + class SettingsObserver extends ContentObserver { + SettingsObserver(Handler handler) { + super(handler); + } + void observe() { + mContext.getContentResolver().registerContentObserver( + Settings.System.getUriFor(SHAKE_GESTURES_ENABLED), false, this, USER_ALL); + mContext.getContentResolver().registerContentObserver( + Settings.System.getUriFor(SHAKE_GESTURES_ACTION), false, this, USER_ALL); + } + @Override + public void onChange(boolean selfChange) { + updateSettings(); + } + } +} diff --git a/services/core/java/org/rising/server/ShakeGestureUtils.java b/services/core/java/org/rising/server/ShakeGestureUtils.java new file mode 100644 index 0000000000000..76e9e02047d7e --- /dev/null +++ b/services/core/java/org/rising/server/ShakeGestureUtils.java @@ -0,0 +1,128 @@ +/* + * Copyright (C) 2023-2024 The RisingOS Android Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.rising.server; + +import android.content.Context; +import android.hardware.Sensor; +import android.hardware.SensorEvent; +import android.hardware.SensorEventListener; +import android.hardware.SensorManager; +import android.os.SystemClock; +import android.provider.Settings; + +import java.util.ArrayList; + +public class ShakeGestureUtils implements SensorEventListener { + + private static final String TAG = "ShakeGestureUtils"; + + private static final String SHAKE_GESTURES_SHAKE_INTENSITY = "shake_gestures_intensity"; + + private Context mContext; + private SensorManager mSensorManager; + private Sensor mAccelerometer; + private ArrayList mListeners = new ArrayList<>(); + private long mLastShakeTime = 0L; + private long mLastUpdateTime = 0L; + private int mShakeCount = 0; + private float mLastX = 0f; + private float mLastY = 0f; + private float mLastZ = 0f; + + public ShakeGestureUtils(Context context) { + mContext = context; + mSensorManager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE); + if (mSensorManager != null) { + mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); + } + } + + public interface OnShakeListener { + void onShake(); + } + + public void registerListener(OnShakeListener listener) { + if (!mListeners.contains(listener)) { + mListeners.add(listener); + startListening(); + } + } + + public void unregisterListener(OnShakeListener listener) { + mListeners.remove(listener); + if (mListeners.isEmpty()) { + stopListening(); + } + } + + private void startListening() { + if (mAccelerometer != null) { + mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_UI); + } + } + + private void stopListening() { + mSensorManager.unregisterListener(this); + } + + private int getShakeIntensity() { + return Settings.System.getInt(mContext.getContentResolver(), + SHAKE_GESTURES_SHAKE_INTENSITY, 3); + } + + @Override + public void onSensorChanged(SensorEvent event) { + if (event == null) { + return; + } + long curUpdateTime = System.currentTimeMillis(); + long timeInterval = curUpdateTime - mLastUpdateTime; + if (timeInterval < (getShakeIntensity() * 14f)) { + return; + } + if (event.values.length < 3) { + return; + } + mLastUpdateTime = curUpdateTime; + float x = event.values[0]; + float y = event.values[1]; + float z = event.values[2]; + float deltaX = x - mLastX; + float deltaY = y - mLastY; + float deltaZ = z - mLastZ; + mLastX = x; + mLastY = y; + mLastZ = z; + double speed = Math.sqrt(deltaX * deltaX + deltaY * deltaY + deltaZ * deltaZ) * 1000.0 / timeInterval; + if (speed >= getShakeIntensity() * 100f) { + notifyShakeListeners(); + } + } + + private void notifyShakeListeners() { + if (SystemClock.elapsedRealtime() - mLastShakeTime < 1000) { + return; + } + for (OnShakeListener listener : mListeners) { + listener.onShake(); + } + mLastShakeTime = SystemClock.elapsedRealtime(); + } + + @Override + public void onAccuracyChanged(Sensor sensor, int accuracy) {} +} From f7970fbdc9ba2585e8d95d4c9cef04fdacd7589f Mon Sep 17 00:00:00 2001 From: someone5678 Date: Tue, 21 May 2024 09:55:51 -0400 Subject: [PATCH 4/8] base: Allow to hide screen capture status from apps * Allow to hide screen capture detection from privacy invasive apps * This feature will be extended to screenrecord in the future release of Android (A15) Change-Id: Ie2a8e49614dcd8fce2311a644d615ab60670c094 Signed-off-by: someone5678 Signed-off-by: HDzungx Signed-off-by: TopexGuy --- core/java/android/provider/Settings.java | 6 ++++++ .../android/server/wm/WindowManagerService.java | 16 +++++++++++++++- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index a700455e1b50c..ffa686c54a5be 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -21528,6 +21528,12 @@ public static boolean putFloat(ContentResolver cr, String name, float value) { */ public static final String PM_DOWNGRADE_ALLOWED = "pm_downgrade_allowed"; + /** + * Control whether to hide screen capture status from apps. + * @hide + */ + public static final String HIDE_SCREEN_CAPTURE_STATUS = "hide_screen_capture_status"; + /** * Setting indicating whether Low Power Standby is enabled, if supported. * diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index c3bad3eaab173..1898a5d43ce31 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -10764,7 +10764,6 @@ public void markSurfaceSyncGroupReady(IBinder syncGroupToken) { mSurfaceSyncGroupController.markSyncGroupReady(syncGroupToken); } - /** * Must be called when a screenshot is taken via hardware chord. * @@ -10778,7 +10777,9 @@ public List notifyScreenshotListeners(int displayId) { "notifyScreenshotListeners()")) { throw new SecurityException("Requires STATUS_BAR_SERVICE permission"); } + synchronized (mGlobalLock) { + if (shouldHideScreenCapture()) return new ArrayList<>(); final DisplayContent displayContent = mRoot.getDisplayContent(displayId); if (displayContent == null) { return new ArrayList<>(); @@ -10880,6 +10881,10 @@ public void unregisterTrustedPresentationListener(ITrustedPresentationListener l @EnforcePermission(android.Manifest.permission.DETECT_SCREEN_RECORDING) @Override public boolean registerScreenRecordingCallback(IScreenRecordingCallback callback) { + if (shouldHideScreenCapture()) { + return false; + } + registerScreenRecordingCallback_enforcePermission(); return mScreenRecordingCallbackController.register(callback); } @@ -10892,6 +10897,10 @@ public void unregisterScreenRecordingCallback(IScreenRecordingCallback callback) } void onProcessActivityVisibilityChanged(int uid, boolean visible) { + if (shouldHideScreenCapture()) { + return; + } + mScreenRecordingCallbackController.onProcessActivityVisibilityChanged(uid, visible); } @@ -11020,4 +11029,9 @@ public void apply(@UserIdInt int userId) { } } } + + private boolean shouldHideScreenCapture() { + return Settings.Global.getInt(mContext.getContentResolver(), + Settings.Global.HIDE_SCREEN_CAPTURE_STATUS, 0) != 0; + } } From 7f878a8d9a32ebf33a23ee27360c7850fd852d65 Mon Sep 17 00:00:00 2001 From: LibXZR Date: Fri, 18 Mar 2022 10:12:37 +0800 Subject: [PATCH 5/8] base: Add support for window ignore secure Feature: yt/KSCOPE-23 Change-Id: Ia9447ca17f6b24152b64526c25710a77e1388ce6 Signed-off-by: LibXZR Signed-off-by: AnierinB Signed-off-by: TopexGuy --- core/java/android/provider/Settings.java | 7 +++++++ core/java/android/view/Window.java | 6 ++++++ 2 files changed, 13 insertions(+) diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index ffa686c54a5be..ffcd5b9581fe7 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -21522,6 +21522,13 @@ public static boolean putFloat(ContentResolver cr, String name, float value) { */ public static final String RESTRICTED_NETWORKING_MODE = "restricted_networking_mode"; + /** + * Control whether FLAG_SECURE is ignored for all windows. + * @hide + */ + @Readable + public static final String WINDOW_IGNORE_SECURE = "window_ignore_secure"; + /** * Control whether application downgrade is allowed. * @hide diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java index e849926e9375e..fc2c33b439ec5 100644 --- a/core/java/android/view/Window.java +++ b/core/java/android/view/Window.java @@ -20,6 +20,7 @@ import static android.Manifest.permission.HIDE_OVERLAY_WINDOWS; import static android.content.pm.PackageManager.PERMISSION_GRANTED; import static android.view.WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED; +import static android.view.WindowManager.LayoutParams.FLAG_SECURE; import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS; import android.annotation.ColorInt; @@ -52,6 +53,7 @@ import android.os.Bundle; import android.os.Handler; import android.os.IBinder; +import android.provider.Settings; import android.transition.Scene; import android.transition.Transition; import android.transition.TransitionManager; @@ -1364,6 +1366,10 @@ public void clearFlags(int flags) { * @see #clearFlags */ public void setFlags(int flags, int mask) { + if ((mask & FLAG_SECURE) != 0 && Settings.Global.getInt(mContext.getContentResolver(), + Settings.Global.WINDOW_IGNORE_SECURE, 0) == 1) { + mask &= ~FLAG_SECURE; + } final WindowManager.LayoutParams attrs = getAttributes(); attrs.flags = (attrs.flags&~mask) | (flags&mask); mForcedWindowFlags |= mask; From 3288fe7da0cddf36dab1542693f5c19a18877c65 Mon Sep 17 00:00:00 2001 From: rmp22 <195054967+rmp22@users.noreply.github.com> Date: Fri, 22 Aug 2025 08:59:03 +0800 Subject: [PATCH 6/8] [BUGFIX] fix ignore secure window flags Change-Id: Ibae64428fcbb44fb774d04dbe828b179d8a71234 Signed-off-by: rmp22 <195054967+rmp22@users.noreply.github.com> Signed-off-by: TopexGuy --- core/java/android/view/SurfaceView.java | 5 ++++- core/java/android/view/WindowManagerGlobal.java | 17 +++++++++++++++++ .../android/server/wm/WindowManagerService.java | 3 ++- 3 files changed, 23 insertions(+), 2 deletions(-) diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java index 49a7da2d88ed8..c3da50d5a1493 100644 --- a/core/java/android/view/SurfaceView.java +++ b/core/java/android/view/SurfaceView.java @@ -52,6 +52,7 @@ import android.os.Looper; import android.os.RemoteException; import android.os.SystemClock; +import android.provider.Settings; import android.text.TextUtils; import android.util.ArraySet; import android.util.AttributeSet; @@ -953,7 +954,9 @@ public boolean setZOrderedOnTop(boolean onTop, boolean allowDynamicChange) { * @param isSecure True if the surface view is secure. */ public void setSecure(boolean isSecure) { - if (isSecure) { + boolean ignoreSecure = Settings.Global.getInt(getContext().getContentResolver(), + Settings.Global.WINDOW_IGNORE_SECURE, 0) == 1; + if (isSecure && !ignoreSecure) { mSurfaceFlags |= SurfaceControl.SECURE; } else { mSurfaceFlags &= ~SurfaceControl.SECURE; diff --git a/core/java/android/view/WindowManagerGlobal.java b/core/java/android/view/WindowManagerGlobal.java index a64e9fa56993b..e563d1781b45a 100644 --- a/core/java/android/view/WindowManagerGlobal.java +++ b/core/java/android/view/WindowManagerGlobal.java @@ -40,6 +40,7 @@ import android.os.RemoteException; import android.os.ServiceManager; import android.os.SystemProperties; +import android.provider.Settings; import android.util.AndroidRuntimeException; import android.util.ArrayMap; import android.util.ArraySet; @@ -480,6 +481,14 @@ public void addView(View view, ViewGroup.LayoutParams params, windowlessSession, new WindowlessWindowLayout()); } + boolean ignoreSecure = Settings.Global.getInt( + view.getContext().getContentResolver(), + Settings.Global.WINDOW_IGNORE_SECURE, 0) == 1; + + if (ignoreSecure) { + wparams.flags &= ~WindowManager.LayoutParams.FLAG_SECURE; + } + view.setLayoutParams(wparams); mViews.add(view); @@ -510,6 +519,14 @@ public void updateViewLayout(View view, ViewGroup.LayoutParams params) { throw new IllegalArgumentException("Params must be WindowManager.LayoutParams"); } + boolean ignoreSecure = Settings.Global.getInt( + view.getContext().getContentResolver(), + Settings.Global.WINDOW_IGNORE_SECURE, 0) == 1; + + if (ignoreSecure) { + wparams.flags &= ~WindowManager.LayoutParams.FLAG_SECURE; + } + view.setLayoutParams(wparams); synchronized (mLock) { diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index 1898a5d43ce31..2cf181d1aefec 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -10916,7 +10916,8 @@ public void setGlobalDragListener(IGlobalDragListener listener) throws RemoteExc } boolean getDisableSecureWindows() { - return mDisableSecureWindows; + return Settings.Global.getInt(mContext.getContentResolver(), + Settings.Global.WINDOW_IGNORE_SECURE, 0) == 1 || mDisableSecureWindows; } /** From 265dda460354159040e89b0a9c16792d4a0bce64 Mon Sep 17 00:00:00 2001 From: someone5678 <59456192+someone5678@users.noreply.github.com> Date: Sat, 28 Dec 2024 20:37:31 +0900 Subject: [PATCH 7/8] SystemUI: Disable DebugLogger for release build Change-Id: I4175e5bc550eded51be1f3608dfa233d576570ef Signed-off-by: TopexGuy --- .../src-debug/com/android/systemui/log/DebugLogger.kt | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/packages/SystemUI/src-debug/com/android/systemui/log/DebugLogger.kt b/packages/SystemUI/src-debug/com/android/systemui/log/DebugLogger.kt index 8d1de0e65da54..a4330ba998a0f 100644 --- a/packages/SystemUI/src-debug/com/android/systemui/log/DebugLogger.kt +++ b/packages/SystemUI/src-debug/com/android/systemui/log/DebugLogger.kt @@ -71,12 +71,6 @@ object DebugLogger { error: Throwable? = null, message: () -> String, ) { - if (enabled) { - if (error == null) { - Log.println(priority, tag, message()) - } else { - Log.printlns(LOG_ID_MAIN, priority, tag, message(), error) - } - } + // no-op. } } From 8dbd931cf02cf7eb2c4f198499aa521867e5c27d Mon Sep 17 00:00:00 2001 From: Dmitrii Date: Thu, 26 Mar 2026 22:12:00 +0000 Subject: [PATCH 8/8] SystemUI: Introduce navbar pill auto-hide Signed-off-by: Dmitrii Signed-off-by: Ghosuto Signed-off-by: TopexGuy --- core/java/android/provider/Settings.java | 6 + .../navigationbar/views/NavigationBar.java | 149 +++++++++++++++++- 2 files changed, 152 insertions(+), 3 deletions(-) diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index ffcd5b9581fe7..732adbf5e2902 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -6844,6 +6844,12 @@ public static void setShowGTalkServiceStatusForUser(ContentResolver cr, boolean @Readable public static final String CUSTOM_RINGTONE_VIBRATION_PATTERN = "custom_ringtone_vibration_pattern"; + /** + * Gesture navbar auto-hide mode. + * @hide + */ + public static final String GESTURE_NAVBAR_AUTO_HIDE = "gesture_navbar_auto_hide"; + /** * Whether to show seconds next to clock in status bar * 0 - hide (default) diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/views/NavigationBar.java b/packages/SystemUI/src/com/android/systemui/navigationbar/views/NavigationBar.java index 67eecef96238d..537e83fce7de3 100644 --- a/packages/SystemUI/src/com/android/systemui/navigationbar/views/NavigationBar.java +++ b/packages/SystemUI/src/com/android/systemui/navigationbar/views/NavigationBar.java @@ -56,6 +56,9 @@ import android.annotation.IdRes; import android.annotation.NonNull; +import android.animation.ValueAnimator; +import android.view.animation.AccelerateInterpolator; +import android.view.animation.DecelerateInterpolator; import android.app.ActivityTaskManager; import android.app.IActivityTaskManager; import android.app.StatusBarManager; @@ -183,6 +186,8 @@ import javax.inject.Inject; +import lineageos.providers.LineageSettings; + /** * Contains logic for a navigation bar view. */ @@ -200,8 +205,14 @@ public class NavigationBar extends ViewController implements /** Allow some time inbetween the long press for back and recents. */ private static final int LOCK_TO_APP_GESTURE_TOLERANCE = 200; private static final long AUTODIM_TIMEOUT_MS = 2250; + private static final long NAVIGATION_HANDLE_AUTO_HIDE_TIMEOUT_MS = 4500; + private static final long NAVIGATION_HANDLE_FADE_DURATION_MS = 750; + private static final long NAVIGATION_HANDLE_FADE_IN_DURATION_MS = 150; private static final float QUICKSTEP_TOUCH_SLOP_RATIO_TWO_BUTTON = 3f; + @Nullable + private ValueAnimator mHomeHandleFadeAnimator; + private final Context mContext; private final Bundle mSavedState; private final WindowManager mWindowManager; @@ -243,6 +254,11 @@ public class NavigationBar extends ViewController implements private final ContentObserver mNavBarObserver; private @WindowVisibleState int mNavigationBarWindowState = WINDOW_STATE_SHOWING; + private final Runnable mAutoHideNavigationHandle = () -> { + if (shouldAutoHideNavigationHandle()) { + fadeOutHomeHandle(); + } + }; @NavbarFlags private int mNavbarFlags; @@ -705,9 +721,8 @@ public boolean isSamplingEnabled() { public void onChange(boolean selfChange, Uri uri) { super.onChange(selfChange, uri); if (mView != null) { - mView.setNavBarMode(mNavBarMode, mNavigationModeController.getImeDrawsImeNavBar() - && getShowNavBarIme()); - + setNavBarMode(mNavBarMode); + showNavigationHandleTemporarily(); } } }; @@ -720,6 +735,102 @@ private boolean getShowNavBarIme() { UserHandle.USER_CURRENT) == 1; } + private boolean getShowNavigationBarHint() { + return Settings.System.getIntForUser( + mContext.getContentResolver(), + LineageSettings.System.NAVIGATION_BAR_HINT, 1, + UserHandle.USER_CURRENT) == 1; + } + + private boolean getAutoHideNavigationBarHint() { + return Settings.System.getIntForUser( + mContext.getContentResolver(), + Settings.System.GESTURE_NAVBAR_AUTO_HIDE, 0, + UserHandle.USER_CURRENT) == 1; + } + + private boolean shouldAutoHideNavigationHandle() { + return isGesturalMode(mNavBarMode) + && getShowNavigationBarHint() + && getAutoHideNavigationBarHint(); + } + + private void setHomeHandleAlpha(float alpha) { + cancelHomeHandleFade(); + if (mView != null) { + ButtonDispatcher homeHandle = mView.getHomeHandle(); + homeHandle.setVisibility(alpha > 0f ? View.VISIBLE : View.INVISIBLE); + homeHandle.setAlpha(alpha, false /* animate */); + } + } + + private void fadeInHomeHandle() { + if (mView == null) return; + cancelHomeHandleFade(); + ButtonDispatcher homeHandle = mView.getHomeHandle(); + float startAlpha = homeHandle.getAlpha(); + if (startAlpha == 1f) { + homeHandle.setVisibility(View.VISIBLE); + return; + } + + homeHandle.setVisibility(View.VISIBLE); + mHomeHandleFadeAnimator = ValueAnimator.ofFloat(startAlpha, 1f); + mHomeHandleFadeAnimator.setDuration(NAVIGATION_HANDLE_FADE_IN_DURATION_MS); + mHomeHandleFadeAnimator.setInterpolator(new DecelerateInterpolator()); + mHomeHandleFadeAnimator.addUpdateListener(anim -> { + float value = (float) anim.getAnimatedValue(); + homeHandle.setAlpha(value, false /* animate */); + }); + mHomeHandleFadeAnimator.start(); + } + + private void fadeOutHomeHandle() { + if (mView == null) return; + cancelHomeHandleFade(); + ButtonDispatcher homeHandle = mView.getHomeHandle(); + float startAlpha = homeHandle.getAlpha(); + if (startAlpha == 0f) return; + + mHomeHandleFadeAnimator = ValueAnimator.ofFloat(startAlpha, 0f); + mHomeHandleFadeAnimator.setDuration(NAVIGATION_HANDLE_FADE_DURATION_MS); + mHomeHandleFadeAnimator.setInterpolator(new AccelerateInterpolator()); + mHomeHandleFadeAnimator.addUpdateListener(anim -> { + float value = (float) anim.getAnimatedValue(); + homeHandle.setAlpha(value, false /* animate */); + if (value == 0f) { + homeHandle.setVisibility(View.INVISIBLE); + } + }); + mHomeHandleFadeAnimator.start(); + } + + private void cancelHomeHandleFade() { + if (mHomeHandleFadeAnimator != null) { + mHomeHandleFadeAnimator.cancel(); + mHomeHandleFadeAnimator = null; + } + } + + private void showNavigationHandleTemporarily() { + mHandler.removeCallbacks(mAutoHideNavigationHandle); + if (!isGesturalMode(mNavBarMode) || !getShowNavigationBarHint()) { + setHomeHandleAlpha(0f); + return; + } + + fadeInHomeHandle(); + if (getAutoHideNavigationBarHint()) { + mHandler.postDelayed(mAutoHideNavigationHandle, getNavigationHandleAutoHideTimeout()); + } + } + + private int getNavigationHandleAutoHideTimeout() { + return mAccessibilityManager.getRecommendedTimeoutMillis( + (int) NAVIGATION_HANDLE_AUTO_HIDE_TIMEOUT_MS, + AccessibilityManager.FLAG_CONTENT_CONTROLS); + } + public NavigationBarView getView() { return mView; } @@ -892,6 +1003,7 @@ public void onViewAttached() { AutoHideController autoHideController = mAutoHideControllerStore.forDisplay(mDisplayId); setAutoHideController(autoHideController); restoreAppearanceAndTransientState(); + showNavigationHandleTemporarily(); mContext.getContentResolver().registerContentObserver( Settings.Secure.getUriFor(Settings.Secure.NAVBAR_IME_SPACE), @@ -899,6 +1011,18 @@ public void onViewAttached() { mNavBarObserver, UserHandle.USER_ALL ); + mContext.getContentResolver().registerContentObserver( + LineageSettings.System.getUriFor(LineageSettings.System.NAVIGATION_BAR_HINT), + false, + mNavBarObserver, + UserHandle.USER_ALL + ); + mContext.getContentResolver().registerContentObserver( + Settings.System.getUriFor(Settings.System.GESTURE_NAVBAR_AUTO_HIDE), + false, + mNavBarObserver, + UserHandle.USER_ALL + ); } @Override @@ -926,6 +1050,8 @@ public void onViewDetached() { mView.getViewTreeObserver().removeOnComputeInternalInsetsListener( mOnComputeInternalInsetsListener); mHandler.removeCallbacks(mAutoDim); + mHandler.removeCallbacks(mAutoHideNavigationHandle); + cancelHomeHandleFade(); mHandler.removeCallbacks(mOnVariableDurationHomeLongClick); mHandler.removeCallbacks(mEnableLayoutTransitions); mNavBarHelper.removeNavTaskStateUpdater(mNavbarTaskbarStateUpdater); @@ -1391,6 +1517,7 @@ private void updateScreenPinningGestures() { private void notifyNavigationBarScreenOn() { mView.updateNavButtonIcons(); + showNavigationHandleTemporarily(); } private void prepareNavigationBarView() { @@ -1404,6 +1531,9 @@ private void prepareNavigationBarView() { homeButton.setOnTouchListener(this::onHomeTouch); homeButton.setNavBarButtonClickLogger(mNavBarButtonClickLogger); + ButtonDispatcher homeHandle = mView.getHomeHandle(); + homeHandle.setOnTouchListener(this::onHomeHandleTouch); + ButtonDispatcher backButton = mView.getBackButton(); backButton.setNavBarButtonClickLogger(mNavBarButtonClickLogger); @@ -1502,6 +1632,13 @@ boolean onHomeTouch(View v, MotionEvent event) { return false; } + private boolean onHomeHandleTouch(View v, MotionEvent event) { + if (event.getActionMasked() == MotionEvent.ACTION_DOWN) { + showNavigationHandleTemporarily(); + } + return false; + } + private void onVerticalChanged(boolean isVertical) { // This check can probably be safely removed. It only remained to reduce regression // risk for a broad change that removed the CentralSurfaces reference in the if block @@ -1511,6 +1648,9 @@ private void onVerticalChanged(boolean isVertical) { } private boolean onNavigationTouch(View v, MotionEvent event) { + if (event.getActionMasked() == MotionEvent.ACTION_DOWN) { + showNavigationHandleTemporarily(); + } if (mAutoHideController != null) { mAutoHideController.checkUserAutoHide(event); } @@ -1717,6 +1857,7 @@ private void updateAssistantEntrypoints(boolean assistantAvailable, public void touchAutoDim() { getBarTransitions().setAutoDim(false); mHandler.removeCallbacks(mAutoDim); + showNavigationHandleTemporarily(); int state = mStatusBarStateController.getState(); if (state != StatusBarState.KEYGUARD && state != StatusBarState.SHADE_LOCKED) { mHandler.postDelayed(mAutoDim, AUTODIM_TIMEOUT_MS); @@ -2076,6 +2217,7 @@ private void setNavBarMode(int mode) { } else { mRegionSamplingHelper.stop(); } + } void onBarTransition(int newMode) { @@ -2105,6 +2247,7 @@ public void onNavigationModeChanged(int mode) { // Update the window layout params when the nav mode changes as that will affect the // system gesture insets setNavBarMode(mode); + showNavigationHandleTemporarily(); repositionNavigationBar(mCurrentRotation); if (!canShowSecondaryHandle()) {