From 35bbd3b2f8801d119f52c364814e069a024e3ce5 Mon Sep 17 00:00:00 2001 From: amehfooz Date: Thu, 21 Nov 2024 21:21:59 +0000 Subject: Rename StatusBarTouchableRegionManager Renaming to ShadeTouchableRegionManager to bring it inline with its actual function. The class manages the touchable region for the shade. FLAG: EXEMPT renaming file Bug: b/380134385 Change-Id: Ibd3ecb4bfe5099f7f1012fcab754be59caa9c37d --- .../NotificationPanelViewControllerBaseTest.java | 8 +- .../shade/QuickSettingsControllerImplBaseTest.java | 6 +- .../phone/ShadeTouchableRegionManagerTest.kt | 135 ++++++++ .../phone/StatusBarTouchableRegionManagerTest.kt | 135 -------- .../shade/NotificationPanelViewController.java | 10 +- .../shade/QuickSettingsControllerImpl.java | 10 +- .../statusbar/phone/CentralSurfacesImpl.java | 18 +- .../phone/ShadeTouchableRegionManager.java | 341 +++++++++++++++++++++ .../phone/StatusBarTouchableRegionManager.java | 341 --------------------- .../statusbar/phone/CentralSurfacesImplTest.java | 4 +- .../phone/ShadeTouchableRegionManagerKosmos.kt | 48 +++ .../phone/StatusBarTouchableRegionManagerKosmos.kt | 48 --- 12 files changed, 552 insertions(+), 552 deletions(-) create mode 100644 packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/ShadeTouchableRegionManagerTest.kt delete mode 100644 packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/StatusBarTouchableRegionManagerTest.kt create mode 100644 packages/SystemUI/src/com/android/systemui/statusbar/phone/ShadeTouchableRegionManager.java delete mode 100644 packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarTouchableRegionManager.java create mode 100644 packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/phone/ShadeTouchableRegionManagerKosmos.kt delete mode 100644 packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/phone/StatusBarTouchableRegionManagerKosmos.kt diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/NotificationPanelViewControllerBaseTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/NotificationPanelViewControllerBaseTest.java index d720e1a6595d..0d8d57e52dbf 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/NotificationPanelViewControllerBaseTest.java +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/NotificationPanelViewControllerBaseTest.java @@ -178,7 +178,7 @@ import com.android.systemui.statusbar.phone.LockscreenGestureLogger; import com.android.systemui.statusbar.phone.ScreenOffAnimationController; import com.android.systemui.statusbar.phone.ScrimController; import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager; -import com.android.systemui.statusbar.phone.StatusBarTouchableRegionManager; +import com.android.systemui.statusbar.phone.ShadeTouchableRegionManager; import com.android.systemui.statusbar.phone.TapAgainViewController; import com.android.systemui.statusbar.phone.UnlockedScreenOffAnimationController; import com.android.systemui.statusbar.policy.CastController; @@ -245,7 +245,7 @@ public class NotificationPanelViewControllerBaseTest extends SysuiTestCase { @Mock protected NotificationPanelView mView; @Mock protected LayoutInflater mLayoutInflater; @Mock protected DynamicPrivacyController mDynamicPrivacyController; - @Mock protected StatusBarTouchableRegionManager mStatusBarTouchableRegionManager; + @Mock protected ShadeTouchableRegionManager mShadeTouchableRegionManager; @Mock protected KeyguardStateController mKeyguardStateController; @Mock protected DozeLog mDozeLog; private final ShadeLogger mShadeLog = new ShadeLogger(logcatLogBuffer()); @@ -703,7 +703,7 @@ public class NotificationPanelViewControllerBaseTest extends SysuiTestCase { mMetricsLogger, mShadeLog, mConfigurationController, - () -> flingAnimationUtilsBuilder, mStatusBarTouchableRegionManager, + () -> flingAnimationUtilsBuilder, mShadeTouchableRegionManager, mConversationNotificationManager, mMediaHierarchyManager, mStatusBarKeyguardViewManager, mGutsManager, @@ -819,7 +819,7 @@ public class NotificationPanelViewControllerBaseTest extends SysuiTestCase { mLockscreenShadeTransitionController, mNotificationShadeDepthController, mShadeHeaderController, - mStatusBarTouchableRegionManager, + mShadeTouchableRegionManager, () -> mStatusBarLongPressGestureDetector, mKeyguardStateController, mKeyguardBypassController, diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/QuickSettingsControllerImplBaseTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/QuickSettingsControllerImplBaseTest.java index 61d4c9968d49..b58c13c34505 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/QuickSettingsControllerImplBaseTest.java +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/QuickSettingsControllerImplBaseTest.java @@ -71,8 +71,8 @@ import com.android.systemui.statusbar.phone.KeyguardStatusBarView; import com.android.systemui.statusbar.phone.LightBarController; import com.android.systemui.statusbar.phone.LockscreenGestureLogger; import com.android.systemui.statusbar.phone.ScrimController; +import com.android.systemui.statusbar.phone.ShadeTouchableRegionManager; import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager; -import com.android.systemui.statusbar.phone.StatusBarTouchableRegionManager; import com.android.systemui.statusbar.policy.CastController; import com.android.systemui.statusbar.policy.KeyguardStateController; import com.android.systemui.statusbar.policy.ResourcesSplitShadeStateController; @@ -125,7 +125,7 @@ public class QuickSettingsControllerImplBaseTest extends SysuiTestCase { @Mock protected LockscreenShadeTransitionController mLockscreenShadeTransitionController; @Mock protected NotificationShadeDepthController mNotificationShadeDepthController; @Mock protected ShadeHeaderController mShadeHeaderController; - @Mock protected StatusBarTouchableRegionManager mStatusBarTouchableRegionManager; + @Mock protected ShadeTouchableRegionManager mShadeTouchableRegionManager; @Mock protected StatusBarLongPressGestureDetector mStatusBarLongPressGestureDetector; @Mock protected DozeParameters mDozeParameters; @Mock protected KeyguardStateController mKeyguardStateController; @@ -250,7 +250,7 @@ public class QuickSettingsControllerImplBaseTest extends SysuiTestCase { mLockscreenShadeTransitionController, mNotificationShadeDepthController, mShadeHeaderController, - mStatusBarTouchableRegionManager, + mShadeTouchableRegionManager, () -> mStatusBarLongPressGestureDetector, mKeyguardStateController, mKeyguardBypassController, diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/ShadeTouchableRegionManagerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/ShadeTouchableRegionManagerTest.kt new file mode 100644 index 000000000000..d82cb86406ec --- /dev/null +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/ShadeTouchableRegionManagerTest.kt @@ -0,0 +1,135 @@ +/* + * Copyright (C) 2024 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.statusbar.phone + +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.filters.SmallTest +import com.android.compose.animation.scene.ObservableTransitionState +import com.android.systemui.SysuiTestCase +import com.android.systemui.communal.data.repository.fakeCommunalSceneRepository +import com.android.systemui.communal.shared.model.CommunalScenes +import com.android.systemui.flags.DisableSceneContainer +import com.android.systemui.flags.EnableSceneContainer +import com.android.systemui.kosmos.testScope +import com.android.systemui.scene.data.repository.sceneContainerRepository +import com.android.systemui.scene.shared.model.Scenes +import com.android.systemui.testKosmos +import com.android.systemui.util.kotlin.getValue +import com.google.common.truth.Truth.assertThat +import dagger.Lazy +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.flow.flowOf +import kotlinx.coroutines.test.runCurrent +import kotlinx.coroutines.test.runTest +import org.junit.Test +import org.junit.runner.RunWith + +@SmallTest +@RunWith(AndroidJUnit4::class) +@OptIn(ExperimentalCoroutinesApi::class) +class ShadeTouchableRegionManagerTest : SysuiTestCase() { + private val kosmos = testKosmos() + private val testScope = kosmos.testScope + private val sceneRepository = kosmos.sceneContainerRepository + + private val underTest by Lazy { kosmos.shadeTouchableRegionManager } + + @Test + @EnableSceneContainer + fun entireScreenTouchable_sceneContainerEnabled_isRemoteUserInteractionOngoing() = + testScope.runTest { + sceneRepository.setTransitionState( + flowOf(ObservableTransitionState.Idle(currentScene = Scenes.Gone)) + ) + runCurrent() + assertThat(underTest.shouldMakeEntireScreenTouchable()).isFalse() + + sceneRepository.isRemoteUserInputOngoing.value = true + runCurrent() + assertThat(underTest.shouldMakeEntireScreenTouchable()).isTrue() + + sceneRepository.isRemoteUserInputOngoing.value = false + runCurrent() + assertThat(underTest.shouldMakeEntireScreenTouchable()).isFalse() + } + + @Test + @DisableSceneContainer + fun entireScreenTouchable_sceneContainerDisabled_isRemoteUserInteractionOngoing() = + testScope.runTest { + assertThat(underTest.shouldMakeEntireScreenTouchable()).isFalse() + + sceneRepository.isRemoteUserInputOngoing.value = true + runCurrent() + + assertThat(underTest.shouldMakeEntireScreenTouchable()).isFalse() + } + + @Test + @EnableSceneContainer + fun entireScreenTouchable_sceneContainerEnabled_isIdleOnGone() = + testScope.runTest { + sceneRepository.setTransitionState( + flowOf(ObservableTransitionState.Idle(currentScene = Scenes.Gone)) + ) + runCurrent() + assertThat(underTest.shouldMakeEntireScreenTouchable()).isFalse() + + sceneRepository.setTransitionState( + flowOf(ObservableTransitionState.Idle(currentScene = Scenes.Shade)) + ) + runCurrent() + assertThat(underTest.shouldMakeEntireScreenTouchable()).isTrue() + + sceneRepository.setTransitionState( + flowOf(ObservableTransitionState.Idle(currentScene = Scenes.Gone)) + ) + runCurrent() + assertThat(underTest.shouldMakeEntireScreenTouchable()).isFalse() + } + + @Test + @DisableSceneContainer + fun entireScreenTouchable_sceneContainerDisabled_isIdleOnGone() = + testScope.runTest { + assertThat(underTest.shouldMakeEntireScreenTouchable()).isFalse() + + sceneRepository.setTransitionState( + flowOf(ObservableTransitionState.Idle(currentScene = Scenes.Shade)) + ) + runCurrent() + + assertThat(underTest.shouldMakeEntireScreenTouchable()).isFalse() + } + + @Test + @DisableSceneContainer + fun entireScreenTouchable_communalVisible() = + testScope.runTest { + assertThat(underTest.shouldMakeEntireScreenTouchable()).isFalse() + + kosmos.fakeCommunalSceneRepository.snapToScene(CommunalScenes.Communal) + runCurrent() + + assertThat(underTest.shouldMakeEntireScreenTouchable()).isTrue() + + kosmos.fakeCommunalSceneRepository.snapToScene(CommunalScenes.Blank) + runCurrent() + + assertThat(underTest.shouldMakeEntireScreenTouchable()).isFalse() + } +} diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/StatusBarTouchableRegionManagerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/StatusBarTouchableRegionManagerTest.kt deleted file mode 100644 index a00858842742..000000000000 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/StatusBarTouchableRegionManagerTest.kt +++ /dev/null @@ -1,135 +0,0 @@ -/* - * Copyright (C) 2024 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.statusbar.phone - -import androidx.test.ext.junit.runners.AndroidJUnit4 -import androidx.test.filters.SmallTest -import com.android.compose.animation.scene.ObservableTransitionState -import com.android.systemui.SysuiTestCase -import com.android.systemui.communal.data.repository.fakeCommunalSceneRepository -import com.android.systemui.communal.shared.model.CommunalScenes -import com.android.systemui.flags.DisableSceneContainer -import com.android.systemui.flags.EnableSceneContainer -import com.android.systemui.kosmos.testScope -import com.android.systemui.scene.data.repository.sceneContainerRepository -import com.android.systemui.scene.shared.model.Scenes -import com.android.systemui.testKosmos -import com.android.systemui.util.kotlin.getValue -import com.google.common.truth.Truth.assertThat -import dagger.Lazy -import kotlinx.coroutines.ExperimentalCoroutinesApi -import kotlinx.coroutines.flow.flowOf -import kotlinx.coroutines.test.runCurrent -import kotlinx.coroutines.test.runTest -import org.junit.Test -import org.junit.runner.RunWith - -@SmallTest -@RunWith(AndroidJUnit4::class) -@OptIn(ExperimentalCoroutinesApi::class) -class StatusBarTouchableRegionManagerTest : SysuiTestCase() { - private val kosmos = testKosmos() - private val testScope = kosmos.testScope - private val sceneRepository = kosmos.sceneContainerRepository - - private val underTest by Lazy { kosmos.statusBarTouchableRegionManager } - - @Test - @EnableSceneContainer - fun entireScreenTouchable_sceneContainerEnabled_isRemoteUserInteractionOngoing() = - testScope.runTest { - sceneRepository.setTransitionState( - flowOf(ObservableTransitionState.Idle(currentScene = Scenes.Gone)) - ) - runCurrent() - assertThat(underTest.shouldMakeEntireScreenTouchable()).isFalse() - - sceneRepository.isRemoteUserInputOngoing.value = true - runCurrent() - assertThat(underTest.shouldMakeEntireScreenTouchable()).isTrue() - - sceneRepository.isRemoteUserInputOngoing.value = false - runCurrent() - assertThat(underTest.shouldMakeEntireScreenTouchable()).isFalse() - } - - @Test - @DisableSceneContainer - fun entireScreenTouchable_sceneContainerDisabled_isRemoteUserInteractionOngoing() = - testScope.runTest { - assertThat(underTest.shouldMakeEntireScreenTouchable()).isFalse() - - sceneRepository.isRemoteUserInputOngoing.value = true - runCurrent() - - assertThat(underTest.shouldMakeEntireScreenTouchable()).isFalse() - } - - @Test - @EnableSceneContainer - fun entireScreenTouchable_sceneContainerEnabled_isIdleOnGone() = - testScope.runTest { - sceneRepository.setTransitionState( - flowOf(ObservableTransitionState.Idle(currentScene = Scenes.Gone)) - ) - runCurrent() - assertThat(underTest.shouldMakeEntireScreenTouchable()).isFalse() - - sceneRepository.setTransitionState( - flowOf(ObservableTransitionState.Idle(currentScene = Scenes.Shade)) - ) - runCurrent() - assertThat(underTest.shouldMakeEntireScreenTouchable()).isTrue() - - sceneRepository.setTransitionState( - flowOf(ObservableTransitionState.Idle(currentScene = Scenes.Gone)) - ) - runCurrent() - assertThat(underTest.shouldMakeEntireScreenTouchable()).isFalse() - } - - @Test - @DisableSceneContainer - fun entireScreenTouchable_sceneContainerDisabled_isIdleOnGone() = - testScope.runTest { - assertThat(underTest.shouldMakeEntireScreenTouchable()).isFalse() - - sceneRepository.setTransitionState( - flowOf(ObservableTransitionState.Idle(currentScene = Scenes.Shade)) - ) - runCurrent() - - assertThat(underTest.shouldMakeEntireScreenTouchable()).isFalse() - } - - @Test - @DisableSceneContainer - fun entireScreenTouchable_communalVisible() = - testScope.runTest { - assertThat(underTest.shouldMakeEntireScreenTouchable()).isFalse() - - kosmos.fakeCommunalSceneRepository.snapToScene(CommunalScenes.Communal) - runCurrent() - - assertThat(underTest.shouldMakeEntireScreenTouchable()).isTrue() - - kosmos.fakeCommunalSceneRepository.snapToScene(CommunalScenes.Blank) - runCurrent() - - assertThat(underTest.shouldMakeEntireScreenTouchable()).isFalse() - } -} diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java index 0c0add2dd237..88522d559c30 100644 --- a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java +++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java @@ -219,8 +219,8 @@ import com.android.systemui.statusbar.phone.LockscreenGestureLogger; import com.android.systemui.statusbar.phone.LockscreenGestureLogger.LockscreenUiEvent; import com.android.systemui.statusbar.phone.ScreenOffAnimationController; import com.android.systemui.statusbar.phone.ScrimController; +import com.android.systemui.statusbar.phone.ShadeTouchableRegionManager; import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager; -import com.android.systemui.statusbar.phone.StatusBarTouchableRegionManager; import com.android.systemui.statusbar.phone.TapAgainViewController; import com.android.systemui.statusbar.phone.UnlockedScreenOffAnimationController; import com.android.systemui.statusbar.policy.ConfigurationController; @@ -298,7 +298,7 @@ public final class NotificationPanelViewController implements ShadeSurface, Dump * The minimum scale to "squish" the Shade and associated elements down to, for Back gesture */ public static final float SHADE_BACK_ANIM_MIN_SCALE = 0.9f; - private final StatusBarTouchableRegionManager mStatusBarTouchableRegionManager; + private final ShadeTouchableRegionManager mShadeTouchableRegionManager; private final Resources mResources; private final KeyguardStateController mKeyguardStateController; private final SysuiStatusBarStateController mStatusBarStateController; @@ -695,7 +695,7 @@ public final class NotificationPanelViewController implements ShadeSurface, Dump ShadeLogger shadeLogger, @ShadeDisplayAware ConfigurationController configurationController, Provider flingAnimationUtilsBuilder, - StatusBarTouchableRegionManager statusBarTouchableRegionManager, + ShadeTouchableRegionManager shadeTouchableRegionManager, ConversationNotificationManager conversationNotificationManager, MediaHierarchyManager mediaHierarchyManager, StatusBarKeyguardViewManager statusBarKeyguardViewManager, @@ -840,7 +840,7 @@ public final class NotificationPanelViewController implements ShadeSurface, Dump mVibratorHelper = vibratorHelper; mMSDLPlayer = msdlPlayer; mVibrateOnOpening = mResources.getBoolean(R.bool.config_vibrateOnIconAnimation); - mStatusBarTouchableRegionManager = statusBarTouchableRegionManager; + mShadeTouchableRegionManager = shadeTouchableRegionManager; mSystemClock = systemClock; mKeyguardMediaController = keyguardMediaController; mMetricsLogger = metricsLogger; @@ -1551,7 +1551,7 @@ public final class NotificationPanelViewController implements ShadeSurface, Dump private Rect calculateGestureExclusionRect() { Rect exclusionRect = null; - Region touchableRegion = mStatusBarTouchableRegionManager.calculateTouchableRegion(); + Region touchableRegion = mShadeTouchableRegionManager.calculateTouchableRegion(); if (isFullyCollapsed() && touchableRegion != null) { // Note: The manager also calculates the non-pinned touchable region exclusionRect = touchableRegion.getBounds(); diff --git a/packages/SystemUI/src/com/android/systemui/shade/QuickSettingsControllerImpl.java b/packages/SystemUI/src/com/android/systemui/shade/QuickSettingsControllerImpl.java index 04f89be97e0a..0df2299eb8dd 100644 --- a/packages/SystemUI/src/com/android/systemui/shade/QuickSettingsControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/shade/QuickSettingsControllerImpl.java @@ -98,7 +98,7 @@ import com.android.systemui.statusbar.phone.LightBarController; import com.android.systemui.statusbar.phone.LockscreenGestureLogger; import com.android.systemui.statusbar.phone.ScrimController; import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager; -import com.android.systemui.statusbar.phone.StatusBarTouchableRegionManager; +import com.android.systemui.statusbar.phone.ShadeTouchableRegionManager; import com.android.systemui.statusbar.policy.CastController; import com.android.systemui.statusbar.policy.KeyguardStateController; import com.android.systemui.statusbar.policy.SplitShadeStateController; @@ -141,7 +141,7 @@ public class QuickSettingsControllerImpl implements QuickSettingsController, Dum private final LockscreenShadeTransitionController mLockscreenShadeTransitionController; private final NotificationShadeDepthController mDepthController; private final ShadeHeaderController mShadeHeaderController; - private final StatusBarTouchableRegionManager mStatusBarTouchableRegionManager; + private final ShadeTouchableRegionManager mShadeTouchableRegionManager; private final Provider mStatusBarLongPressGestureDetector; private final KeyguardStateController mKeyguardStateController; private final KeyguardBypassController mKeyguardBypassController; @@ -317,7 +317,7 @@ public class QuickSettingsControllerImpl implements QuickSettingsController, Dum LockscreenShadeTransitionController lockscreenShadeTransitionController, NotificationShadeDepthController notificationShadeDepthController, ShadeHeaderController shadeHeaderController, - StatusBarTouchableRegionManager statusBarTouchableRegionManager, + ShadeTouchableRegionManager shadeTouchableRegionManager, Provider statusBarLongPressGestureDetector, KeyguardStateController keyguardStateController, KeyguardBypassController keyguardBypassController, @@ -366,7 +366,7 @@ public class QuickSettingsControllerImpl implements QuickSettingsController, Dum mLockscreenShadeTransitionController = lockscreenShadeTransitionController; mDepthController = notificationShadeDepthController; mShadeHeaderController = shadeHeaderController; - mStatusBarTouchableRegionManager = statusBarTouchableRegionManager; + mShadeTouchableRegionManager = shadeTouchableRegionManager; mStatusBarLongPressGestureDetector = statusBarLongPressGestureDetector; mKeyguardStateController = keyguardStateController; mKeyguardBypassController = keyguardBypassController; @@ -695,7 +695,7 @@ public class QuickSettingsControllerImpl implements QuickSettingsController, Dum /* right= */ (int) mQsFrame.getX() + mQsFrame.getWidth(), /* bottom= */ headerBottom + frameTop); // Also allow QS to intercept if the touch is near the notch. - mStatusBarTouchableRegionManager.updateRegionForNotch(mInterceptRegion); + mShadeTouchableRegionManager.updateRegionForNotch(mInterceptRegion); final boolean onHeader = mInterceptRegion.contains((int) x, (int) y); if (getExpanded()) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java index 7fa6707eb99d..c6af3280eef1 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java @@ -401,7 +401,7 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces { private final KeyguardBypassController mKeyguardBypassController; private final KeyguardStateController mKeyguardStateController; private final HeadsUpManager mHeadsUpManager; - private final StatusBarTouchableRegionManager mStatusBarTouchableRegionManager; + private final ShadeTouchableRegionManager mShadeTouchableRegionManager; private final FalsingCollector mFalsingCollector; private final FalsingManager mFalsingManager; private final BroadcastDispatcher mBroadcastDispatcher; @@ -681,7 +681,7 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces { KeyguardIndicationController keyguardIndicationController, DemoModeController demoModeController, Lazy notificationShadeDepthControllerLazy, - StatusBarTouchableRegionManager statusBarTouchableRegionManager, + ShadeTouchableRegionManager shadeTouchableRegionManager, BrightnessSliderController.Factory brightnessSliderFactory, ScreenOffAnimationController screenOffAnimationController, WallpaperController wallpaperController, @@ -724,7 +724,7 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces { mHeadsUpManager = headsUpManager; mBackActionInteractor = backActionInteractor; mKeyguardIndicationController = keyguardIndicationController; - mStatusBarTouchableRegionManager = statusBarTouchableRegionManager; + mShadeTouchableRegionManager = shadeTouchableRegionManager; mFalsingCollector = falsingCollector; mFalsingManager = falsingManager; mBroadcastDispatcher = broadcastDispatcher; @@ -1232,7 +1232,7 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces { mStatusBarInitializer.initializeStatusBar(); } - mStatusBarTouchableRegionManager.setup(getNotificationShadeWindowView()); + mShadeTouchableRegionManager.setup(getNotificationShadeWindowView()); if (!StatusBarConnectedDisplays.isEnabled()) { createNavigationBar(result); @@ -1856,10 +1856,10 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces { pw.println(" mHeadsUpManager: null"); } - if (mStatusBarTouchableRegionManager != null) { - mStatusBarTouchableRegionManager.dump(pw, args); + if (mShadeTouchableRegionManager != null) { + mShadeTouchableRegionManager.dump(pw, args); } else { - pw.println(" mStatusBarTouchableRegionManager: null"); + pw.println(" mShadeTouchableRegionManager: null"); } if (mLightBarController != null) { @@ -2566,7 +2566,7 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces { dismissVolumeDialog(); mWakeUpCoordinator.setFullyAwake(false); mKeyguardBypassController.onStartedGoingToSleep(); - mStatusBarTouchableRegionManager.updateTouchableRegion(); + mShadeTouchableRegionManager.updateTouchableRegion(); // The unlocked screen off and fold to aod animations might use our LightRevealScrim - // we need to be expanded for it to be visible. @@ -2655,7 +2655,7 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces { // once we fully woke up. updateRevealEffect(true /* wakingUp */); updateNotificationPanelTouchState(); - mStatusBarTouchableRegionManager.updateTouchableRegion(); + mShadeTouchableRegionManager.updateTouchableRegion(); // If we are waking up during the screen off animation, we should undo making the // expanded visible (we did that so the LightRevealScrim would be visible). diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ShadeTouchableRegionManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ShadeTouchableRegionManager.java new file mode 100644 index 000000000000..bea8397fed62 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ShadeTouchableRegionManager.java @@ -0,0 +1,341 @@ +/* + * Copyright (C) 2019 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.statusbar.phone; + +import android.annotation.NonNull; +import android.content.Context; +import android.content.res.Resources; +import android.graphics.Rect; +import android.graphics.Region; +import android.util.Log; +import android.view.DisplayCutout; +import android.view.Gravity; +import android.view.View; +import android.view.ViewTreeObserver; +import android.view.ViewTreeObserver.OnComputeInternalInsetsListener; +import android.view.WindowInsets; + +import androidx.annotation.VisibleForTesting; + +import com.android.compose.animation.scene.ObservableTransitionState; +import com.android.internal.policy.SystemBarUtils; +import com.android.systemui.Dumpable; +import com.android.systemui.ScreenDecorations; +import com.android.systemui.bouncer.domain.interactor.AlternateBouncerInteractor; +import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerInteractor; +import com.android.systemui.communal.domain.interactor.CommunalSceneInteractor; +import com.android.systemui.dagger.SysUISingleton; +import com.android.systemui.res.R; +import com.android.systemui.scene.domain.interactor.SceneInteractor; +import com.android.systemui.scene.shared.flag.SceneContainerFlag; +import com.android.systemui.scene.shared.model.Scenes; +import com.android.systemui.shade.domain.interactor.ShadeInteractor; +import com.android.systemui.statusbar.NotificationShadeWindowController; +import com.android.systemui.statusbar.policy.ConfigurationController; +import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener; +import com.android.systemui.statusbar.notification.headsup.HeadsUpManager; +import com.android.systemui.statusbar.notification.headsup.OnHeadsUpChangedListener; +import com.android.systemui.util.kotlin.JavaAdapter; + +import java.io.PrintWriter; + +import javax.inject.Inject; +import javax.inject.Provider; + +/** + * Manages what parts of the status bar are touchable. Clients are primarily UI that display in the + * status bar even though the UI doesn't look like part of the status bar. Currently this consists + * of HeadsUpNotifications. + */ +@SysUISingleton +public final class ShadeTouchableRegionManager implements Dumpable { + private static final String TAG = "TouchableRegionManager"; + + private final Context mContext; + private final HeadsUpManager mHeadsUpManager; + private final NotificationShadeWindowController mNotificationShadeWindowController; + private final UnlockedScreenOffAnimationController mUnlockedScreenOffAnimationController; + + private boolean mIsStatusBarExpanded = false; + // Whether the scene container has no UI to render, i.e. is in idle state on the Gone scene and + // without any overlays to display. + private boolean mIsSceneContainerUiEmpty = true; + private boolean mIsRemoteUserInteractionOngoing = false; + private boolean mShouldAdjustInsets = false; + private View mNotificationShadeWindowView; + private View mNotificationPanelView; + private boolean mForceCollapsedUntilLayout = false; + private Boolean mCommunalVisible = false; + + private Region mTouchableRegion = new Region(); + private int mDisplayCutoutTouchableRegionSize; + private int mStatusBarHeight; + private final PrimaryBouncerInteractor mPrimaryBouncerInteractor; + private final AlternateBouncerInteractor mAlternateBouncerInteractor; + + private final OnComputeInternalInsetsListener mOnComputeInternalInsetsListener; + + @Inject + public ShadeTouchableRegionManager( + Context context, + NotificationShadeWindowController notificationShadeWindowController, + ConfigurationController configurationController, + HeadsUpManager headsUpManager, + ShadeInteractor shadeInteractor, + Provider sceneInteractor, + JavaAdapter javaAdapter, + UnlockedScreenOffAnimationController unlockedScreenOffAnimationController, + PrimaryBouncerInteractor primaryBouncerInteractor, + AlternateBouncerInteractor alternateBouncerInteractor, + CommunalSceneInteractor communalSceneInteractor + ) { + mContext = context; + initResources(); + configurationController.addCallback(new ConfigurationListener() { + @Override + public void onDensityOrFontScaleChanged() { + initResources(); + } + + @Override + public void onThemeChanged() { + initResources(); + } + }); + + mHeadsUpManager = headsUpManager; + mHeadsUpManager.addListener( + new OnHeadsUpChangedListener() { + @Override + public void onHeadsUpPinnedModeChanged(boolean hasPinnedNotification) { + if (Log.isLoggable(TAG, Log.WARN)) { + Log.w(TAG, "onHeadsUpPinnedModeChanged"); + } + updateTouchableRegion(); + } + }); + mHeadsUpManager.addHeadsUpPhoneListener(this::onHeadsUpAnimatingAwayStateChanged); + + mNotificationShadeWindowController = notificationShadeWindowController; + mNotificationShadeWindowController.setForcePluginOpenListener((forceOpen) -> { + updateTouchableRegion(); + }); + + mUnlockedScreenOffAnimationController = unlockedScreenOffAnimationController; + + if (SceneContainerFlag.isEnabled()) { + javaAdapter.alwaysCollectFlow( + sceneInteractor.get().getTransitionState(), + this::onSceneContainerTransition); + javaAdapter.alwaysCollectFlow( + sceneInteractor.get().isRemoteUserInteractionOngoing(), + this::onRemoteUserInteractionOngoingChanged); + } else { + javaAdapter.alwaysCollectFlow( + shadeInteractor.isAnyExpanded(), + this::onShadeOrQsExpanded); + javaAdapter.alwaysCollectFlow( + communalSceneInteractor.isCommunalVisible(), + this::onCommunalVisible); + } + + mPrimaryBouncerInteractor = primaryBouncerInteractor; + mAlternateBouncerInteractor = alternateBouncerInteractor; + mOnComputeInternalInsetsListener = this::onComputeInternalInsets; + } + + protected void setup(@NonNull View notificationShadeWindowView) { + mNotificationShadeWindowView = notificationShadeWindowView; + mNotificationPanelView = mNotificationShadeWindowView.findViewById(R.id.notification_panel); + } + + @Override + public void dump(PrintWriter pw, String[] args) { + pw.println("ShadeTouchableRegionManager state:"); + pw.print(" mTouchableRegion="); + pw.println(mTouchableRegion); + } + + private void onShadeOrQsExpanded(Boolean isExpanded) { + if (isExpanded != mIsStatusBarExpanded) { + mIsStatusBarExpanded = isExpanded; + if (isExpanded) { + // make sure our state is sensible + mForceCollapsedUntilLayout = false; + } + updateTouchableRegion(); + } + } + + private void onSceneContainerTransition(ObservableTransitionState transitionState) { + boolean isSceneContainerUiEmpty = transitionState.isIdle(Scenes.Gone) + && ((ObservableTransitionState.Idle) transitionState).getCurrentOverlays() + .isEmpty(); + if (isSceneContainerUiEmpty != mIsSceneContainerUiEmpty) { + mIsSceneContainerUiEmpty = isSceneContainerUiEmpty; + if (!isSceneContainerUiEmpty) { + // make sure our state is sensible + mForceCollapsedUntilLayout = false; + } + updateTouchableRegion(); + } + } + + private void onRemoteUserInteractionOngoingChanged(Boolean ongoing) { + if (ongoing != mIsRemoteUserInteractionOngoing) { + mIsRemoteUserInteractionOngoing = ongoing; + updateTouchableRegion(); + } + } + + private void onCommunalVisible(Boolean visible) { + mCommunalVisible = visible; + } + + /** + * Calculates the touch region needed for heads up notifications, taking into consideration + * any existing display cutouts (notch) + * @return the heads up notification touch area + */ + public Region calculateTouchableRegion() { + // Update touchable region for HeadsUp notifications + final Region headsUpTouchableRegion = mHeadsUpManager.getTouchableRegion(); + if (headsUpTouchableRegion != null) { + mTouchableRegion.set(headsUpTouchableRegion); + } else { + // If there aren't any HUNs, update the touch region to the status bar + // width/height, potentially adjusting for a display cutout (notch) + mTouchableRegion.set(0, 0, mNotificationShadeWindowView.getWidth(), + mStatusBarHeight); + updateRegionForNotch(mTouchableRegion); + } + return mTouchableRegion; + } + + private void initResources() { + Resources resources = mContext.getResources(); + mDisplayCutoutTouchableRegionSize = resources.getDimensionPixelSize( + com.android.internal.R.dimen.display_cutout_touchable_region_size); + mStatusBarHeight = SystemBarUtils.getStatusBarHeight(mContext); + } + + /** + * Set the touchable portion of the status bar based on what elements are visible. + */ + public void updateTouchableRegion() { + boolean hasCutoutInset = (mNotificationShadeWindowView != null) + && (mNotificationShadeWindowView.getRootWindowInsets() != null) + && (mNotificationShadeWindowView.getRootWindowInsets().getDisplayCutout() != null); + boolean shouldObserve = mHeadsUpManager.hasPinnedHeadsUp() + || mHeadsUpManager.isHeadsUpAnimatingAwayValue() + || mForceCollapsedUntilLayout + || hasCutoutInset + || mNotificationShadeWindowController.getForcePluginOpen(); + if (shouldObserve == mShouldAdjustInsets) { + return; + } + + if (shouldObserve) { + mNotificationShadeWindowView.getViewTreeObserver() + .addOnComputeInternalInsetsListener(mOnComputeInternalInsetsListener); + mNotificationShadeWindowView.requestLayout(); + } else { + mNotificationShadeWindowView.getViewTreeObserver() + .removeOnComputeInternalInsetsListener(mOnComputeInternalInsetsListener); + } + mShouldAdjustInsets = shouldObserve; + } + + /** + * Calls {@code updateTouchableRegion()} after a layout pass completes. + */ + private void updateTouchableRegionAfterLayout() { + if (mNotificationPanelView != null) { + mForceCollapsedUntilLayout = true; + mNotificationPanelView.addOnLayoutChangeListener(new View.OnLayoutChangeListener() { + @Override + public void onLayoutChange(View v, int left, int top, int right, int bottom, + int oldLeft, int oldTop, int oldRight, int oldBottom) { + if (!mNotificationPanelView.isVisibleToUser()) { + mNotificationPanelView.removeOnLayoutChangeListener(this); + mForceCollapsedUntilLayout = false; + updateTouchableRegion(); + } + } + }); + } + } + + public void updateRegionForNotch(Region touchableRegion) { + WindowInsets windowInsets = mNotificationShadeWindowView.getRootWindowInsets(); + if (windowInsets == null) { + Log.w(TAG, "StatusBarWindowView is not attached."); + return; + } + DisplayCutout cutout = windowInsets.getDisplayCutout(); + if (cutout == null) { + return; + } + + // Expand touchable region such that we also catch touches that just start below the notch + // area. + Rect bounds = new Rect(); + ScreenDecorations.DisplayCutoutView.boundsFromDirection(cutout, Gravity.TOP, bounds); + bounds.offset(0, mDisplayCutoutTouchableRegionSize); + touchableRegion.union(bounds); + } + + /** + * Helper to let us know when calculating the region is not needed because we know the entire + * screen needs to be touchable. + */ + @VisibleForTesting + boolean shouldMakeEntireScreenTouchable() { + // The touchable region is always the full area when expanded, whether we're showing the + // shade or the bouncer. It's also fully touchable when the screen off animation is playing + // since we don't want stray touches to go through the light reveal scrim to whatever is + // underneath. + return mIsStatusBarExpanded + || (SceneContainerFlag.isEnabled() + && (!mIsSceneContainerUiEmpty || mIsRemoteUserInteractionOngoing)) + || mPrimaryBouncerInteractor.isShowing().getValue() + || mAlternateBouncerInteractor.isVisibleState() + // The glanceable hub is a full-screen UI within the notification shade window. When + // it's visible, the touchable region should be the full screen. + || mCommunalVisible + || mUnlockedScreenOffAnimationController.isAnimationPlaying(); + } + + private void onHeadsUpAnimatingAwayStateChanged(boolean headsUpAnimatingAway) { + if (!headsUpAnimatingAway) { + updateTouchableRegionAfterLayout(); + } else { + updateTouchableRegion(); + } + } + + private void onComputeInternalInsets(ViewTreeObserver.InternalInsetsInfo info) { + if (shouldMakeEntireScreenTouchable()) { + return; + } + + // Update touch insets to include any area needed for touching features that live in + // the status bar (ie: heads up notifications) + info.setTouchableInsets(ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_REGION); + info.touchableRegion.set(calculateTouchableRegion()); + } +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarTouchableRegionManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarTouchableRegionManager.java deleted file mode 100644 index c09b9c52bb53..000000000000 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarTouchableRegionManager.java +++ /dev/null @@ -1,341 +0,0 @@ -/* - * Copyright (C) 2019 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.statusbar.phone; - -import android.annotation.NonNull; -import android.content.Context; -import android.content.res.Resources; -import android.graphics.Rect; -import android.graphics.Region; -import android.util.Log; -import android.view.DisplayCutout; -import android.view.Gravity; -import android.view.View; -import android.view.ViewTreeObserver; -import android.view.ViewTreeObserver.OnComputeInternalInsetsListener; -import android.view.WindowInsets; - -import androidx.annotation.VisibleForTesting; - -import com.android.compose.animation.scene.ObservableTransitionState; -import com.android.internal.policy.SystemBarUtils; -import com.android.systemui.Dumpable; -import com.android.systemui.ScreenDecorations; -import com.android.systemui.bouncer.domain.interactor.AlternateBouncerInteractor; -import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerInteractor; -import com.android.systemui.communal.domain.interactor.CommunalSceneInteractor; -import com.android.systemui.dagger.SysUISingleton; -import com.android.systemui.res.R; -import com.android.systemui.scene.domain.interactor.SceneInteractor; -import com.android.systemui.scene.shared.flag.SceneContainerFlag; -import com.android.systemui.scene.shared.model.Scenes; -import com.android.systemui.shade.domain.interactor.ShadeInteractor; -import com.android.systemui.statusbar.NotificationShadeWindowController; -import com.android.systemui.statusbar.policy.ConfigurationController; -import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener; -import com.android.systemui.statusbar.notification.headsup.HeadsUpManager; -import com.android.systemui.statusbar.notification.headsup.OnHeadsUpChangedListener; -import com.android.systemui.util.kotlin.JavaAdapter; - -import java.io.PrintWriter; - -import javax.inject.Inject; -import javax.inject.Provider; - -/** - * Manages what parts of the status bar are touchable. Clients are primarily UI that display in the - * status bar even though the UI doesn't look like part of the status bar. Currently this consists - * of HeadsUpNotifications. - */ -@SysUISingleton -public final class StatusBarTouchableRegionManager implements Dumpable { - private static final String TAG = "TouchableRegionManager"; - - private final Context mContext; - private final HeadsUpManager mHeadsUpManager; - private final NotificationShadeWindowController mNotificationShadeWindowController; - private final UnlockedScreenOffAnimationController mUnlockedScreenOffAnimationController; - - private boolean mIsStatusBarExpanded = false; - // Whether the scene container has no UI to render, i.e. is in idle state on the Gone scene and - // without any overlays to display. - private boolean mIsSceneContainerUiEmpty = true; - private boolean mIsRemoteUserInteractionOngoing = false; - private boolean mShouldAdjustInsets = false; - private View mNotificationShadeWindowView; - private View mNotificationPanelView; - private boolean mForceCollapsedUntilLayout = false; - private Boolean mCommunalVisible = false; - - private Region mTouchableRegion = new Region(); - private int mDisplayCutoutTouchableRegionSize; - private int mStatusBarHeight; - private final PrimaryBouncerInteractor mPrimaryBouncerInteractor; - private final AlternateBouncerInteractor mAlternateBouncerInteractor; - - private final OnComputeInternalInsetsListener mOnComputeInternalInsetsListener; - - @Inject - public StatusBarTouchableRegionManager( - Context context, - NotificationShadeWindowController notificationShadeWindowController, - ConfigurationController configurationController, - HeadsUpManager headsUpManager, - ShadeInteractor shadeInteractor, - Provider sceneInteractor, - JavaAdapter javaAdapter, - UnlockedScreenOffAnimationController unlockedScreenOffAnimationController, - PrimaryBouncerInteractor primaryBouncerInteractor, - AlternateBouncerInteractor alternateBouncerInteractor, - CommunalSceneInteractor communalSceneInteractor - ) { - mContext = context; - initResources(); - configurationController.addCallback(new ConfigurationListener() { - @Override - public void onDensityOrFontScaleChanged() { - initResources(); - } - - @Override - public void onThemeChanged() { - initResources(); - } - }); - - mHeadsUpManager = headsUpManager; - mHeadsUpManager.addListener( - new OnHeadsUpChangedListener() { - @Override - public void onHeadsUpPinnedModeChanged(boolean hasPinnedNotification) { - if (Log.isLoggable(TAG, Log.WARN)) { - Log.w(TAG, "onHeadsUpPinnedModeChanged"); - } - updateTouchableRegion(); - } - }); - mHeadsUpManager.addHeadsUpPhoneListener(this::onHeadsUpAnimatingAwayStateChanged); - - mNotificationShadeWindowController = notificationShadeWindowController; - mNotificationShadeWindowController.setForcePluginOpenListener((forceOpen) -> { - updateTouchableRegion(); - }); - - mUnlockedScreenOffAnimationController = unlockedScreenOffAnimationController; - - if (SceneContainerFlag.isEnabled()) { - javaAdapter.alwaysCollectFlow( - sceneInteractor.get().getTransitionState(), - this::onSceneContainerTransition); - javaAdapter.alwaysCollectFlow( - sceneInteractor.get().isRemoteUserInteractionOngoing(), - this::onRemoteUserInteractionOngoingChanged); - } else { - javaAdapter.alwaysCollectFlow( - shadeInteractor.isAnyExpanded(), - this::onShadeOrQsExpanded); - javaAdapter.alwaysCollectFlow( - communalSceneInteractor.isCommunalVisible(), - this::onCommunalVisible); - } - - mPrimaryBouncerInteractor = primaryBouncerInteractor; - mAlternateBouncerInteractor = alternateBouncerInteractor; - mOnComputeInternalInsetsListener = this::onComputeInternalInsets; - } - - protected void setup(@NonNull View notificationShadeWindowView) { - mNotificationShadeWindowView = notificationShadeWindowView; - mNotificationPanelView = mNotificationShadeWindowView.findViewById(R.id.notification_panel); - } - - @Override - public void dump(PrintWriter pw, String[] args) { - pw.println("StatusBarTouchableRegionManager state:"); - pw.print(" mTouchableRegion="); - pw.println(mTouchableRegion); - } - - private void onShadeOrQsExpanded(Boolean isExpanded) { - if (isExpanded != mIsStatusBarExpanded) { - mIsStatusBarExpanded = isExpanded; - if (isExpanded) { - // make sure our state is sensible - mForceCollapsedUntilLayout = false; - } - updateTouchableRegion(); - } - } - - private void onSceneContainerTransition(ObservableTransitionState transitionState) { - boolean isSceneContainerUiEmpty = transitionState.isIdle(Scenes.Gone) - && ((ObservableTransitionState.Idle) transitionState).getCurrentOverlays() - .isEmpty(); - if (isSceneContainerUiEmpty != mIsSceneContainerUiEmpty) { - mIsSceneContainerUiEmpty = isSceneContainerUiEmpty; - if (!isSceneContainerUiEmpty) { - // make sure our state is sensible - mForceCollapsedUntilLayout = false; - } - updateTouchableRegion(); - } - } - - private void onRemoteUserInteractionOngoingChanged(Boolean ongoing) { - if (ongoing != mIsRemoteUserInteractionOngoing) { - mIsRemoteUserInteractionOngoing = ongoing; - updateTouchableRegion(); - } - } - - private void onCommunalVisible(Boolean visible) { - mCommunalVisible = visible; - } - - /** - * Calculates the touch region needed for heads up notifications, taking into consideration - * any existing display cutouts (notch) - * @return the heads up notification touch area - */ - public Region calculateTouchableRegion() { - // Update touchable region for HeadsUp notifications - final Region headsUpTouchableRegion = mHeadsUpManager.getTouchableRegion(); - if (headsUpTouchableRegion != null) { - mTouchableRegion.set(headsUpTouchableRegion); - } else { - // If there aren't any HUNs, update the touch region to the status bar - // width/height, potentially adjusting for a display cutout (notch) - mTouchableRegion.set(0, 0, mNotificationShadeWindowView.getWidth(), - mStatusBarHeight); - updateRegionForNotch(mTouchableRegion); - } - return mTouchableRegion; - } - - private void initResources() { - Resources resources = mContext.getResources(); - mDisplayCutoutTouchableRegionSize = resources.getDimensionPixelSize( - com.android.internal.R.dimen.display_cutout_touchable_region_size); - mStatusBarHeight = SystemBarUtils.getStatusBarHeight(mContext); - } - - /** - * Set the touchable portion of the status bar based on what elements are visible. - */ - public void updateTouchableRegion() { - boolean hasCutoutInset = (mNotificationShadeWindowView != null) - && (mNotificationShadeWindowView.getRootWindowInsets() != null) - && (mNotificationShadeWindowView.getRootWindowInsets().getDisplayCutout() != null); - boolean shouldObserve = mHeadsUpManager.hasPinnedHeadsUp() - || mHeadsUpManager.isHeadsUpAnimatingAwayValue() - || mForceCollapsedUntilLayout - || hasCutoutInset - || mNotificationShadeWindowController.getForcePluginOpen(); - if (shouldObserve == mShouldAdjustInsets) { - return; - } - - if (shouldObserve) { - mNotificationShadeWindowView.getViewTreeObserver() - .addOnComputeInternalInsetsListener(mOnComputeInternalInsetsListener); - mNotificationShadeWindowView.requestLayout(); - } else { - mNotificationShadeWindowView.getViewTreeObserver() - .removeOnComputeInternalInsetsListener(mOnComputeInternalInsetsListener); - } - mShouldAdjustInsets = shouldObserve; - } - - /** - * Calls {@code updateTouchableRegion()} after a layout pass completes. - */ - private void updateTouchableRegionAfterLayout() { - if (mNotificationPanelView != null) { - mForceCollapsedUntilLayout = true; - mNotificationPanelView.addOnLayoutChangeListener(new View.OnLayoutChangeListener() { - @Override - public void onLayoutChange(View v, int left, int top, int right, int bottom, - int oldLeft, int oldTop, int oldRight, int oldBottom) { - if (!mNotificationPanelView.isVisibleToUser()) { - mNotificationPanelView.removeOnLayoutChangeListener(this); - mForceCollapsedUntilLayout = false; - updateTouchableRegion(); - } - } - }); - } - } - - public void updateRegionForNotch(Region touchableRegion) { - WindowInsets windowInsets = mNotificationShadeWindowView.getRootWindowInsets(); - if (windowInsets == null) { - Log.w(TAG, "StatusBarWindowView is not attached."); - return; - } - DisplayCutout cutout = windowInsets.getDisplayCutout(); - if (cutout == null) { - return; - } - - // Expand touchable region such that we also catch touches that just start below the notch - // area. - Rect bounds = new Rect(); - ScreenDecorations.DisplayCutoutView.boundsFromDirection(cutout, Gravity.TOP, bounds); - bounds.offset(0, mDisplayCutoutTouchableRegionSize); - touchableRegion.union(bounds); - } - - /** - * Helper to let us know when calculating the region is not needed because we know the entire - * screen needs to be touchable. - */ - @VisibleForTesting - boolean shouldMakeEntireScreenTouchable() { - // The touchable region is always the full area when expanded, whether we're showing the - // shade or the bouncer. It's also fully touchable when the screen off animation is playing - // since we don't want stray touches to go through the light reveal scrim to whatever is - // underneath. - return mIsStatusBarExpanded - || (SceneContainerFlag.isEnabled() - && (!mIsSceneContainerUiEmpty || mIsRemoteUserInteractionOngoing)) - || mPrimaryBouncerInteractor.isShowing().getValue() - || mAlternateBouncerInteractor.isVisibleState() - // The glanceable hub is a full-screen UI within the notification shade window. When - // it's visible, the touchable region should be the full screen. - || mCommunalVisible - || mUnlockedScreenOffAnimationController.isAnimationPlaying(); - } - - private void onHeadsUpAnimatingAwayStateChanged(boolean headsUpAnimatingAway) { - if (!headsUpAnimatingAway) { - updateTouchableRegionAfterLayout(); - } else { - updateTouchableRegion(); - } - } - - private void onComputeInternalInsets(ViewTreeObserver.InternalInsetsInfo info) { - if (shouldMakeEntireScreenTouchable()) { - return; - } - - // Update touch insets to include any area needed for touching features that live in - // the status bar (ie: heads up notifications) - info.setTouchableInsets(ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_REGION); - info.touchableRegion.set(calculateTouchableRegion()); - } -} diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java index 8b4c3355443c..6912eda3c3d4 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java @@ -334,7 +334,7 @@ public class CentralSurfacesImplTest extends SysuiTestCase { @Mock private CentralSurfacesCommandQueueCallbacks mCentralSurfacesCommandQueueCallbacks; @Mock private PluginManager mPluginManager; @Mock private ViewMediatorCallback mViewMediatorCallback; - @Mock private StatusBarTouchableRegionManager mStatusBarTouchableRegionManager; + @Mock private ShadeTouchableRegionManager mShadeTouchableRegionManager; @Mock private PluginDependencyProvider mPluginDependencyProvider; @Mock private ExtensionController mExtensionController; @Mock private UserInfoControllerImpl mUserInfoControllerImpl; @@ -617,7 +617,7 @@ public class CentralSurfacesImplTest extends SysuiTestCase { mKeyguardIndicationController, mDemoModeController, mNotificationShadeDepthControllerLazy, - mStatusBarTouchableRegionManager, + mShadeTouchableRegionManager, mBrightnessSliderFactory, mScreenOffAnimationController, mWallpaperController, diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/phone/ShadeTouchableRegionManagerKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/phone/ShadeTouchableRegionManagerKosmos.kt new file mode 100644 index 000000000000..5b7f23b0cff2 --- /dev/null +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/phone/ShadeTouchableRegionManagerKosmos.kt @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2024 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.statusbar.phone + +import android.content.applicationContext +import com.android.systemui.bouncer.domain.interactor.alternateBouncerInteractor +import com.android.systemui.bouncer.domain.interactor.primaryBouncerInteractor +import com.android.systemui.communal.domain.interactor.communalSceneInteractor +import com.android.systemui.kosmos.Kosmos +import com.android.systemui.kosmos.testScope +import com.android.systemui.scene.domain.interactor.sceneInteractor +import com.android.systemui.shade.domain.interactor.shadeInteractor +import com.android.systemui.statusbar.notification.headsup.headsUpManager +import com.android.systemui.statusbar.notificationShadeWindowController +import com.android.systemui.statusbar.policy.configurationController +import com.android.systemui.util.kotlin.JavaAdapter +import com.android.systemui.util.mockito.mock + +var Kosmos.shadeTouchableRegionManager by + Kosmos.Fixture { + ShadeTouchableRegionManager( + applicationContext, + notificationShadeWindowController, + configurationController, + headsUpManager, + shadeInteractor, + { sceneInteractor }, + JavaAdapter(testScope.backgroundScope), + mock(), + primaryBouncerInteractor, + alternateBouncerInteractor, + communalSceneInteractor, + ) + } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/phone/StatusBarTouchableRegionManagerKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/phone/StatusBarTouchableRegionManagerKosmos.kt deleted file mode 100644 index 6eb6fe87b6c1..000000000000 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/phone/StatusBarTouchableRegionManagerKosmos.kt +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (C) 2024 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.statusbar.phone - -import android.content.applicationContext -import com.android.systemui.bouncer.domain.interactor.alternateBouncerInteractor -import com.android.systemui.bouncer.domain.interactor.primaryBouncerInteractor -import com.android.systemui.communal.domain.interactor.communalSceneInteractor -import com.android.systemui.kosmos.Kosmos -import com.android.systemui.kosmos.testScope -import com.android.systemui.scene.domain.interactor.sceneInteractor -import com.android.systemui.shade.domain.interactor.shadeInteractor -import com.android.systemui.statusbar.notification.headsup.headsUpManager -import com.android.systemui.statusbar.notificationShadeWindowController -import com.android.systemui.statusbar.policy.configurationController -import com.android.systemui.util.kotlin.JavaAdapter -import com.android.systemui.util.mockito.mock - -var Kosmos.statusBarTouchableRegionManager by - Kosmos.Fixture { - StatusBarTouchableRegionManager( - applicationContext, - notificationShadeWindowController, - configurationController, - headsUpManager, - shadeInteractor, - { sceneInteractor }, - JavaAdapter(testScope.backgroundScope), - mock(), - primaryBouncerInteractor, - alternateBouncerInteractor, - communalSceneInteractor, - ) - } -- cgit v1.2.3-59-g8ed1b