diff options
| author | 2025-02-10 10:04:40 -0800 | |
|---|---|---|
| committer | 2025-02-10 10:04:40 -0800 | |
| commit | d9d463320e7af5221cfa4e220cc8f6de5c17436c (patch) | |
| tree | ad468c8ac859c4ce918367c73cd130d90c85598a | |
| parent | 83bbf97785c568b4d1c3ab9add64bf8d7efe93be (diff) | |
| parent | fc8a6a7efea114c9b799c43539029d49bfee98e3 (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.
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) +} |