summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Chandru S <chandruis@google.com> 2025-02-10 10:04:40 -0800
committer Android (Google) Code Review <android-gerrit@google.com> 2025-02-10 10:04:40 -0800
commitd9d463320e7af5221cfa4e220cc8f6de5c17436c (patch)
treead468c8ac859c4ce918367c73cd130d90c85598a
parent83bbf97785c568b4d1c3ab9add64bf8d7efe93be (diff)
parentfc8a6a7efea114c9b799c43539029d49bfee98e3 (diff)
Merge changes from topics "blur-module-change", "disable-bouncer-blur" into main
* changes: Disable transparent bouncer and scrims when blur is not supported or disabled Add a flow that can be used to determine whether cross window blur is enabled/supported right now.
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.kt7
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java23
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java42
-rw-r--r--packages/SystemUI/src/com/android/systemui/shade/ShadeModule.kt6
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java41
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java17
-rw-r--r--packages/SystemUI/src/com/android/systemui/window/dagger/WindowRootViewBlurModule.kt35
-rw-r--r--packages/SystemUI/src/com/android/systemui/window/dagger/WindowRootViewBlurNotSupportedModule.kt35
-rw-r--r--packages/SystemUI/src/com/android/systemui/window/data/repository/NoopWindowRootViewBlurRepository.kt28
-rw-r--r--packages/SystemUI/src/com/android/systemui/window/data/repository/WindowRootViewBlurRepository.kt69
-rw-r--r--packages/SystemUI/src/com/android/systemui/window/domain/interactor/WindowRootViewBlurInteractor.kt6
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java6
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/kosmos/KosmosJavaAdapter.kt2
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/window/data/repository/WindowRootViewBlurRepositoryKosmos.kt13
14 files changed, 299 insertions, 31 deletions
diff --git a/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.kt
index fe665e658feb..24b9e847d621 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.kt
@@ -84,6 +84,7 @@ import com.android.systemui.util.mockito.mock
import com.android.systemui.util.mockito.whenever
import com.android.systemui.util.settings.GlobalSettings
import com.android.systemui.util.time.FakeSystemClock
+import com.android.systemui.window.domain.interactor.windowRootViewBlurInteractor
import com.google.common.truth.Truth
import junit.framework.Assert
import kotlinx.coroutines.flow.MutableStateFlow
@@ -280,9 +281,9 @@ class KeyguardSecurityContainerControllerTest : SysuiTestCase() {
kosmos.keyguardDismissTransitionInteractor,
{ primaryBouncerInteractor },
executor,
- ) {
- deviceEntryInteractor
- }
+ { deviceEntryInteractor },
+ { kosmos.windowRootViewBlurInteractor },
+ )
}
@Test
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
index 335a910eb106..73dc28230e65 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
@@ -98,7 +98,6 @@ import com.android.internal.widget.LockPatternUtils;
import com.android.keyguard.KeyguardSecurityModel.SecurityMode;
import com.android.settingslib.Utils;
import com.android.settingslib.drawable.CircleFramedDrawable;
-import com.android.systemui.Flags;
import com.android.systemui.FontStyles;
import com.android.systemui.Gefingerpoken;
import com.android.systemui.classifier.FalsingA11yDelegate;
@@ -121,6 +120,7 @@ public class KeyguardSecurityContainer extends ConstraintLayout {
static final int USER_TYPE_PRIMARY = 1;
static final int USER_TYPE_WORK_PROFILE = 2;
static final int USER_TYPE_SECONDARY_USER = 3;
+ private boolean mTransparentModeEnabled = false;
@IntDef({MODE_UNINITIALIZED, MODE_DEFAULT, MODE_ONE_HANDED, MODE_USER_SWITCHER})
public @interface Mode {}
@@ -814,15 +814,30 @@ public class KeyguardSecurityContainer extends ConstraintLayout {
mDisappearAnimRunning = false;
}
+ /**
+ * Make the bouncer background transparent
+ */
+ public void enableTransparentMode() {
+ mTransparentModeEnabled = true;
+ reloadBackgroundColor();
+ }
+
+ /**
+ * Make the bouncer background opaque
+ */
+ public void disableTransparentMode() {
+ mTransparentModeEnabled = false;
+ reloadBackgroundColor();
+ }
+
private void reloadBackgroundColor() {
- if (Flags.bouncerUiRevamp()) {
- // Keep the background transparent, otherwise the background color looks like a box
- // while scaling the bouncer for back animation or while transitioning to the bouncer.
+ if (mTransparentModeEnabled) {
setBackgroundColor(Color.TRANSPARENT);
} else {
setBackgroundColor(
getContext().getColor(com.android.internal.R.color.materialColorSurfaceDim));
}
+ invalidate();
}
void reloadColors() {
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
index ff7b2b025539..d10fce416150 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
@@ -70,6 +70,7 @@ import com.android.keyguard.KeyguardSecurityContainer.SwipeListener;
import com.android.keyguard.KeyguardSecurityModel.SecurityMode;
import com.android.keyguard.dagger.KeyguardBouncerScope;
import com.android.settingslib.utils.ThreadUtils;
+import com.android.systemui.Flags;
import com.android.systemui.Gefingerpoken;
import com.android.systemui.biometrics.FaceAuthAccessibilityDelegate;
import com.android.systemui.bouncer.domain.interactor.BouncerMessageInteractor;
@@ -96,6 +97,8 @@ import com.android.systemui.user.domain.interactor.SelectedUserInteractor;
import com.android.systemui.util.ViewController;
import com.android.systemui.util.kotlin.JavaAdapter;
import com.android.systemui.util.settings.GlobalSettings;
+import com.android.systemui.window.data.repository.WindowRootViewBlurRepository;
+import com.android.systemui.window.domain.interactor.WindowRootViewBlurInteractor;
import dagger.Lazy;
@@ -134,6 +137,7 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard
private final FalsingA11yDelegate mFalsingA11yDelegate;
private final DeviceEntryFaceAuthInteractor mDeviceEntryFaceAuthInteractor;
private final BouncerMessageInteractor mBouncerMessageInteractor;
+ private final Lazy<WindowRootViewBlurInteractor> mRootViewBlurInteractor;
private int mTranslationY;
private final KeyguardDismissTransitionInteractor mKeyguardDismissTransitionInteractor;
private final DevicePolicyManager mDevicePolicyManager;
@@ -431,6 +435,7 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard
private final Executor mBgExecutor;
@Nullable
private Job mSceneTransitionCollectionJob;
+ private Job mBlurEnabledCollectionJob;
@Inject
public KeyguardSecurityContainerController(KeyguardSecurityContainer view,
@@ -463,9 +468,11 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard
KeyguardDismissTransitionInteractor keyguardDismissTransitionInteractor,
Lazy<PrimaryBouncerInteractor> primaryBouncerInteractor,
@Background Executor bgExecutor,
- Provider<DeviceEntryInteractor> deviceEntryInteractor
+ Provider<DeviceEntryInteractor> deviceEntryInteractor,
+ Lazy<WindowRootViewBlurInteractor> rootViewBlurInteractorProvider
) {
super(view);
+ mRootViewBlurInteractor = rootViewBlurInteractorProvider;
view.setAccessibilityDelegate(faceAuthAccessibilityDelegate);
mLockPatternUtils = lockPatternUtils;
mUpdateMonitor = keyguardUpdateMonitor;
@@ -539,6 +546,32 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard
}
);
}
+
+ if (Flags.bouncerUiRevamp()) {
+ mBlurEnabledCollectionJob = mJavaAdapter.get().alwaysCollectFlow(
+ mRootViewBlurInteractor.get().isBlurCurrentlySupported(),
+ this::handleBlurSupportedChanged);
+ }
+ }
+
+ private void handleBlurSupportedChanged(boolean isWindowBlurSupported) {
+ if (isWindowBlurSupported) {
+ mView.enableTransparentMode();
+ } else {
+ mView.disableTransparentMode();
+ }
+ }
+
+ private void refreshBouncerBackground() {
+ // This is present solely for screenshot tests that disable blur by invoking setprop to
+ // disable blurs, however the mRootViewBlurInteractor#isBlurCurrentlySupported doesn't emit
+ // an updated value because sysui doesn't have a way to register for changes to setprop.
+ // KeyguardSecurityContainer view is inflated only once and doesn't re-inflate so it has to
+ // check the sysprop every time bouncer is about to be shown.
+ if (Flags.bouncerUiRevamp() && (ActivityManager.isRunningInUserTestHarness()
+ || ActivityManager.isRunningInTestHarness())) {
+ handleBlurSupportedChanged(!WindowRootViewBlurRepository.isDisableBlurSysPropSet());
+ }
}
@Override
@@ -552,6 +585,11 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard
mSceneTransitionCollectionJob.cancel(null);
mSceneTransitionCollectionJob = null;
}
+
+ if (mBlurEnabledCollectionJob != null) {
+ mBlurEnabledCollectionJob.cancel(null);
+ mBlurEnabledCollectionJob = null;
+ }
}
/** */
@@ -718,6 +756,8 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard
if (bouncerUserSwitcher != null) {
bouncerUserSwitcher.setAlpha(0f);
}
+
+ refreshBouncerBackground();
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/shade/ShadeModule.kt b/packages/SystemUI/src/com/android/systemui/shade/ShadeModule.kt
index b9df9f868dc3..7d4b0ed6304c 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/ShadeModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/ShadeModule.kt
@@ -45,13 +45,17 @@ import com.android.systemui.shade.domain.interactor.ShadeLockscreenInteractor
import com.android.systemui.shade.domain.interactor.ShadeLockscreenInteractorImpl
import com.android.systemui.shade.domain.interactor.ShadeModeInteractor
import com.android.systemui.shade.domain.interactor.ShadeModeInteractorImpl
+import com.android.systemui.window.dagger.WindowRootViewBlurModule
import dagger.Binds
import dagger.Module
import dagger.Provides
import javax.inject.Provider
/** Module for classes related to the notification shade. */
-@Module(includes = [StartShadeModule::class, ShadeViewProviderModule::class])
+@Module(
+ includes =
+ [StartShadeModule::class, ShadeViewProviderModule::class, WindowRootViewBlurModule::class]
+)
abstract class ShadeModule {
companion object {
@Provides
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
index 4d222fdb90ea..b2d337797b53 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
@@ -81,6 +81,9 @@ import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.util.kotlin.JavaAdapter;
import com.android.systemui.util.wakelock.DelayedWakeLock;
import com.android.systemui.util.wakelock.WakeLock;
+import com.android.systemui.window.domain.interactor.WindowRootViewBlurInteractor;
+
+import dagger.Lazy;
import kotlinx.coroutines.CoroutineDispatcher;
@@ -226,7 +229,7 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump
private float mScrimBehindAlphaKeyguard = KEYGUARD_SCRIM_ALPHA;
static final float TRANSPARENT_BOUNCER_SCRIM_ALPHA = 0.54f;
- private final float mDefaultScrimAlpha;
+ private float mDefaultScrimAlpha;
private float mRawPanelExpansionFraction;
private float mPanelScrimMinFraction;
@@ -257,6 +260,7 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump
private final TriConsumer<ScrimState, Float, GradientColors> mScrimStateListener;
private final LargeScreenShadeInterpolator mLargeScreenShadeInterpolator;
private final BlurConfig mBlurConfig;
+ private final Lazy<WindowRootViewBlurInteractor> mWindowRootViewBlurInteractor;
private Consumer<Integer> mScrimVisibleListener;
private boolean mBlankScreen;
private boolean mScreenBlankingCallbackCalled;
@@ -339,14 +343,13 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump
KeyguardInteractor keyguardInteractor,
@Main CoroutineDispatcher mainDispatcher,
LargeScreenShadeInterpolator largeScreenShadeInterpolator,
- BlurConfig blurConfig) {
+ BlurConfig blurConfig,
+ Lazy<WindowRootViewBlurInteractor> windowRootViewBlurInteractor) {
mScrimStateListener = lightBarController::setScrimState;
mLargeScreenShadeInterpolator = largeScreenShadeInterpolator;
mBlurConfig = blurConfig;
- // All scrims default alpha need to match bouncer background alpha to make sure the
- // transitions involving the bouncer are smooth and don't overshoot the bouncer alpha.
- mDefaultScrimAlpha =
- Flags.bouncerUiRevamp() ? TRANSPARENT_BOUNCER_SCRIM_ALPHA : BUSY_SCRIM_ALPHA;
+ mWindowRootViewBlurInteractor = windowRootViewBlurInteractor;
+ mDefaultScrimAlpha = BUSY_SCRIM_ALPHA;
mKeyguardStateController = keyguardStateController;
mDarkenWhileDragging = !mKeyguardStateController.canDismissLockScreen();
@@ -407,7 +410,7 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump
final ScrimState[] states = ScrimState.values();
for (int i = 0; i < states.length; i++) {
- states[i].init(mScrimInFront, mScrimBehind, mDozeParameters, mDockManager, mBlurConfig);
+ states[i].init(mScrimInFront, mScrimBehind, mDozeParameters, mDockManager);
states[i].setScrimBehindAlphaKeyguard(mScrimBehindAlphaKeyguard);
states[i].setDefaultScrimAlpha(mDefaultScrimAlpha);
}
@@ -485,6 +488,30 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump
Edge.Companion.create(Scenes.Communal, LOCKSCREEN),
Edge.Companion.create(GLANCEABLE_HUB, LOCKSCREEN)),
mGlanceableHubConsumer, mMainDispatcher);
+
+ if (Flags.bouncerUiRevamp()) {
+ collectFlow(behindScrim,
+ mWindowRootViewBlurInteractor.get().isBlurCurrentlySupported(),
+ this::handleBlurSupportedChanged);
+ }
+ }
+
+ private void updateDefaultScrimAlpha(float alpha) {
+ mDefaultScrimAlpha = alpha;
+ for (ScrimState state : ScrimState.values()) {
+ state.setDefaultScrimAlpha(mDefaultScrimAlpha);
+ }
+ applyAndDispatchState();
+ }
+
+ private void handleBlurSupportedChanged(boolean isBlurSupported) {
+ if (isBlurSupported) {
+ updateDefaultScrimAlpha(TRANSPARENT_BOUNCER_SCRIM_ALPHA);
+ ScrimState.BOUNCER_SCRIMMED.setNotifBlurRadius(mBlurConfig.getMaxBlurRadiusPx());
+ } else {
+ ScrimState.BOUNCER_SCRIMMED.setNotifBlurRadius(0f);
+ updateDefaultScrimAlpha(BUSY_SCRIM_ALPHA);
+ }
}
// TODO(b/270984686) recompute scrim height accurately, based on shade contents.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java
index 5f423cf35edd..071a57a8b298 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java
@@ -17,14 +17,12 @@
package com.android.systemui.statusbar.phone;
import static com.android.systemui.statusbar.phone.ScrimController.BUSY_SCRIM_ALPHA;
-import static com.android.systemui.statusbar.phone.ScrimController.TRANSPARENT_BOUNCER_SCRIM_ALPHA;
import android.graphics.Color;
import com.android.app.tracing.coroutines.TrackTracer;
import com.android.systemui.Flags;
import com.android.systemui.dock.DockManager;
-import com.android.systemui.keyguard.ui.transitions.BlurConfig;
import com.android.systemui.res.R;
import com.android.systemui.scrim.ScrimView;
import com.android.systemui.shade.ui.ShadeColors;
@@ -116,8 +114,8 @@ public enum ScrimState {
@Override
public void prepare(ScrimState previousState) {
if (Flags.bouncerUiRevamp()) {
- mBehindAlpha = mClipQsScrim ? 0.0f : TRANSPARENT_BOUNCER_SCRIM_ALPHA;
- mNotifAlpha = mClipQsScrim ? TRANSPARENT_BOUNCER_SCRIM_ALPHA : 0;
+ mBehindAlpha = mDefaultScrimAlpha;
+ mNotifAlpha = 0f;
mBehindTint = mNotifTint = mSurfaceColor;
mFrontAlpha = 0f;
return;
@@ -153,12 +151,11 @@ public enum ScrimState {
if (previousState == SHADE_LOCKED) {
mBehindAlpha = previousState.getBehindAlpha();
mNotifAlpha = previousState.getNotifAlpha();
- mNotifBlurRadius = mBlurConfig.getMaxBlurRadiusPx();
} else {
mNotifAlpha = 0f;
mBehindAlpha = 0f;
}
- mFrontAlpha = TRANSPARENT_BOUNCER_SCRIM_ALPHA;
+ mFrontAlpha = mDefaultScrimAlpha;
mFrontTint = mSurfaceColor;
return;
}
@@ -403,7 +400,6 @@ public enum ScrimState {
DozeParameters mDozeParameters;
DockManager mDockManager;
boolean mDisplayRequiresBlanking;
- protected BlurConfig mBlurConfig;
boolean mLaunchingAffordanceWithPreview;
boolean mOccludeAnimationPlaying;
boolean mWakeLockScreenSensorActive;
@@ -417,7 +413,7 @@ public enum ScrimState {
protected float mNotifBlurRadius = 0.0f;
public void init(ScrimView scrimInFront, ScrimView scrimBehind, DozeParameters dozeParameters,
- DockManager dockManager, BlurConfig blurConfig) {
+ DockManager dockManager) {
mBackgroundColor = scrimBehind.getContext().getColor(R.color.shade_scrim_background_dark);
mScrimInFront = scrimInFront;
mScrimBehind = scrimBehind;
@@ -425,7 +421,6 @@ public enum ScrimState {
mDozeParameters = dozeParameters;
mDockManager = dockManager;
mDisplayRequiresBlanking = dozeParameters.getDisplayNeedsBlanking();
- mBlurConfig = blurConfig;
}
/** Prepare state for transition. */
@@ -536,4 +531,8 @@ public enum ScrimState {
public float getNotifBlurRadius() {
return mNotifBlurRadius;
}
+
+ public void setNotifBlurRadius(float value) {
+ mNotifBlurRadius = value;
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/window/dagger/WindowRootViewBlurModule.kt b/packages/SystemUI/src/com/android/systemui/window/dagger/WindowRootViewBlurModule.kt
new file mode 100644
index 000000000000..95b3b68fa1ca
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/window/dagger/WindowRootViewBlurModule.kt
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2025 The Android Open Source 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 com.android.systemui.window.dagger
+
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.window.data.repository.WindowRootViewBlurRepository
+import com.android.systemui.window.data.repository.WindowRootViewBlurRepositoryImpl
+import dagger.Binds
+import dagger.Module
+
+/**
+ * Module that can be installed in sysui variants where we support cross window blur.
+ */
+@Module
+interface WindowRootViewBlurModule {
+ @Binds
+ @SysUISingleton
+ fun bindWindowRootViewBlurRepository(
+ windowRootViewBlurRepositoryImpl: WindowRootViewBlurRepositoryImpl
+ ): WindowRootViewBlurRepository
+}
diff --git a/packages/SystemUI/src/com/android/systemui/window/dagger/WindowRootViewBlurNotSupportedModule.kt b/packages/SystemUI/src/com/android/systemui/window/dagger/WindowRootViewBlurNotSupportedModule.kt
new file mode 100644
index 000000000000..ae917e072ff3
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/window/dagger/WindowRootViewBlurNotSupportedModule.kt
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2025 The Android Open Source 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 com.android.systemui.window.dagger
+
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.window.data.repository.NoopWindowRootViewBlurRepository
+import com.android.systemui.window.data.repository.WindowRootViewBlurRepository
+import dagger.Binds
+import dagger.Module
+
+/**
+ * Module that can be installed in sysui variants where we don't support cross window blur.
+ */
+@Module
+interface WindowRootViewBlurNotSupportedModule {
+ @Binds
+ @SysUISingleton
+ fun bindWindowRootViewBlurRepository(
+ windowRootViewBlurRepositoryImpl: NoopWindowRootViewBlurRepository
+ ): WindowRootViewBlurRepository
+}
diff --git a/packages/SystemUI/src/com/android/systemui/window/data/repository/NoopWindowRootViewBlurRepository.kt b/packages/SystemUI/src/com/android/systemui/window/data/repository/NoopWindowRootViewBlurRepository.kt
new file mode 100644
index 000000000000..80aa11a71569
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/window/data/repository/NoopWindowRootViewBlurRepository.kt
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2025 The Android Open Source 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 com.android.systemui.window.data.repository
+
+import com.android.systemui.window.data.repository.WindowRootViewBlurRepository
+import javax.inject.Inject
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.StateFlow
+
+class NoopWindowRootViewBlurRepository @Inject constructor() : WindowRootViewBlurRepository {
+ override val blurRadius: MutableStateFlow<Int> = MutableStateFlow(0)
+ override val isBlurOpaque: MutableStateFlow<Boolean> = MutableStateFlow(true)
+ override val isBlurSupported: StateFlow<Boolean> = MutableStateFlow(false)
+} \ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/window/data/repository/WindowRootViewBlurRepository.kt b/packages/SystemUI/src/com/android/systemui/window/data/repository/WindowRootViewBlurRepository.kt
index 22a74c86e0f1..41ceda033bdf 100644
--- a/packages/SystemUI/src/com/android/systemui/window/data/repository/WindowRootViewBlurRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/window/data/repository/WindowRootViewBlurRepository.kt
@@ -16,14 +16,77 @@
package com.android.systemui.window.data.repository
+import android.app.ActivityManager
+import android.os.SystemProperties
+import android.view.CrossWindowBlurListeners
+import com.android.systemui.common.coroutine.ChannelExt.trySendWithFailureLogging
import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.dagger.qualifiers.Main
+import com.android.systemui.utils.coroutines.flow.conflatedCallbackFlow
+import com.android.systemui.window.data.repository.WindowRootViewBlurRepository.Companion.isDisableBlurSysPropSet
+import java.util.concurrent.Executor
import javax.inject.Inject
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.SharingStarted
+import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.flow.stateIn
/** Repository that maintains state for the window blur effect. */
+interface WindowRootViewBlurRepository {
+ val blurRadius: MutableStateFlow<Int>
+ val isBlurOpaque: MutableStateFlow<Boolean>
+
+ /** Is blur supported based on settings toggle and battery power saver mode. */
+ val isBlurSupported: StateFlow<Boolean>
+
+ companion object {
+ /**
+ * Whether the `persist.sysui.disableBlur` is set, this is used to disable blur for tests.
+ */
+ @JvmStatic
+ fun isDisableBlurSysPropSet() = SystemProperties.getBoolean(DISABLE_BLUR_PROPERTY, false)
+
+ // property that can be used to disable the cross window blur for tests
+ private const val DISABLE_BLUR_PROPERTY = "persist.sysui.disableBlur"
+ }
+}
+
@SysUISingleton
-class WindowRootViewBlurRepository @Inject constructor() {
- val blurRadius = MutableStateFlow(0)
+class WindowRootViewBlurRepositoryImpl
+@Inject
+constructor(
+ crossWindowBlurListeners: CrossWindowBlurListeners,
+ @Main private val executor: Executor,
+ @Application private val scope: CoroutineScope,
+) : WindowRootViewBlurRepository {
+ override val blurRadius = MutableStateFlow(0)
+
+ override val isBlurOpaque = MutableStateFlow(false)
+
+ override val isBlurSupported: StateFlow<Boolean> =
+ conflatedCallbackFlow {
+ val sendUpdate = { value: Boolean ->
+ trySendWithFailureLogging(
+ isBlurAllowed() && value,
+ TAG,
+ "unable to send blur enabled/disable state change",
+ )
+ }
+ crossWindowBlurListeners.addListener(executor, sendUpdate)
+ sendUpdate(crossWindowBlurListeners.isCrossWindowBlurEnabled)
+
+ awaitClose { crossWindowBlurListeners.removeListener(sendUpdate) }
+ } // stateIn because this is backed by a binder call.
+ .stateIn(scope, SharingStarted.WhileSubscribed(), false)
+
+ private fun isBlurAllowed(): Boolean {
+ return ActivityManager.isHighEndGfx() && !isDisableBlurSysPropSet()
+ }
- val isBlurOpaque = MutableStateFlow(false)
+ companion object {
+ const val TAG = "WindowRootViewBlurRepository"
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/window/domain/interactor/WindowRootViewBlurInteractor.kt b/packages/SystemUI/src/com/android/systemui/window/domain/interactor/WindowRootViewBlurInteractor.kt
index 9e369347dea5..7a88a2ef966b 100644
--- a/packages/SystemUI/src/com/android/systemui/window/domain/interactor/WindowRootViewBlurInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/window/domain/interactor/WindowRootViewBlurInteractor.kt
@@ -75,6 +75,12 @@ constructor(
_onBlurAppliedEvent.emit(appliedBlurRadius)
}
+ /**
+ * Whether blur is enabled or not based on settings toggle, critical thermal state, battery save
+ * state and multimedia tunneling state.
+ */
+ val isBlurCurrentlySupported: StateFlow<Boolean> = repository.isBlurSupported
+
/** Radius of blur to be applied on the window root view. */
val blurRadius: StateFlow<Int> = repository.blurRadius.asStateFlow()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java
index a5234883ed77..14a1233045bb 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java
@@ -290,7 +290,8 @@ public class ScrimControllerTest extends SysuiTestCase {
mKeyguardInteractor,
mKosmos.getTestDispatcher(),
mLinearLargeScreenShadeInterpolator,
- new BlurConfig(0.0f, 0.0f));
+ new BlurConfig(0.0f, 0.0f),
+ mKosmos::getWindowRootViewBlurInteractor);
mScrimController.setScrimVisibleListener(visible -> mScrimVisibility = visible);
mScrimController.attachViews(mScrimBehind, mNotificationsScrim, mScrimInFront);
mScrimController.setAnimatorListener(mAnimatorListener);
@@ -1204,7 +1205,8 @@ public class ScrimControllerTest extends SysuiTestCase {
mKeyguardInteractor,
mKosmos.getTestDispatcher(),
mLinearLargeScreenShadeInterpolator,
- new BlurConfig(0.0f, 0.0f));
+ new BlurConfig(0.0f, 0.0f),
+ mKosmos::getWindowRootViewBlurInteractor);
mScrimController.setScrimVisibleListener(visible -> mScrimVisibility = visible);
mScrimController.attachViews(mScrimBehind, mNotificationsScrim, mScrimInFront);
mScrimController.setAnimatorListener(mAnimatorListener);
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/kosmos/KosmosJavaAdapter.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/kosmos/KosmosJavaAdapter.kt
index 446e10671afb..60b371aa8afb 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/kosmos/KosmosJavaAdapter.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/kosmos/KosmosJavaAdapter.kt
@@ -90,6 +90,7 @@ import com.android.systemui.statusbar.policy.domain.interactor.deviceProvisionin
import com.android.systemui.statusbar.ui.viewmodel.keyguardStatusBarViewModel
import com.android.systemui.util.time.systemClock
import com.android.systemui.volume.domain.interactor.volumeDialogInteractor
+import com.android.systemui.window.domain.interactor.windowRootViewBlurInteractor
/**
* Helper for using [Kosmos] from Java.
@@ -192,4 +193,5 @@ class KosmosJavaAdapter() {
val disableFlagsInteractor by lazy { kosmos.disableFlagsInteractor }
val fakeDisableFlagsRepository by lazy { kosmos.fakeDisableFlagsRepository }
val mockWindowRootViewProvider by lazy { kosmos.mockWindowRootViewProvider }
+ val windowRootViewBlurInteractor by lazy { kosmos.windowRootViewBlurInteractor }
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/window/data/repository/WindowRootViewBlurRepositoryKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/window/data/repository/WindowRootViewBlurRepositoryKosmos.kt
index 7281e03a5ea4..96992233375d 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/window/data/repository/WindowRootViewBlurRepositoryKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/window/data/repository/WindowRootViewBlurRepositoryKosmos.kt
@@ -17,5 +17,16 @@
package com.android.systemui.window.data.repository
import com.android.systemui.kosmos.Kosmos
+import kotlinx.coroutines.flow.MutableStateFlow
-val Kosmos.windowRootViewBlurRepository by Kosmos.Fixture { WindowRootViewBlurRepository() }
+val Kosmos.fakeWindowRootViewBlurRepository: FakeWindowRootViewBlurRepository by
+ Kosmos.Fixture { FakeWindowRootViewBlurRepository() }
+
+val Kosmos.windowRootViewBlurRepository: WindowRootViewBlurRepository by
+ Kosmos.Fixture { fakeWindowRootViewBlurRepository }
+
+class FakeWindowRootViewBlurRepository : WindowRootViewBlurRepository {
+ override val blurRadius: MutableStateFlow<Int> = MutableStateFlow(0)
+ override val isBlurOpaque: MutableStateFlow<Boolean> = MutableStateFlow(false)
+ override val isBlurSupported: MutableStateFlow<Boolean> = MutableStateFlow(false)
+}