Loading packages/SystemUI/multivalentTests/src/com/android/systemui/communal/domain/interactor/CommunalInteractorTest.kt +47 −0 Original line number Diff line number Diff line Loading @@ -641,6 +641,53 @@ class CommunalInteractorTest : SysuiTestCase() { assertThat(isIdleOnCommunal).isEqualTo(false) } @Test fun isCommunalVisible() = testScope.runTest { val transitionState = MutableStateFlow<ObservableCommunalTransitionState>( ObservableCommunalTransitionState.Idle(CommunalSceneKey.Blank) ) communalRepository.setTransitionState(transitionState) // isCommunalVisible is false when not on communal. val isCommunalVisible by collectLastValue(underTest.isCommunalVisible) assertThat(isCommunalVisible).isEqualTo(false) // Start transition to communal. transitionState.value = ObservableCommunalTransitionState.Transition( fromScene = CommunalSceneKey.Blank, toScene = CommunalSceneKey.Communal, progress = flowOf(0f), isInitiatedByUserInput = false, isUserInputOngoing = flowOf(false), ) // isCommunalVisible is true once transition starts. assertThat(isCommunalVisible).isEqualTo(true) // Finish transition to communal transitionState.value = ObservableCommunalTransitionState.Idle(CommunalSceneKey.Communal) // isCommunalVisible is true since we're on communal. assertThat(isCommunalVisible).isEqualTo(true) // Start transition away from communal. transitionState.value = ObservableCommunalTransitionState.Transition( fromScene = CommunalSceneKey.Communal, toScene = CommunalSceneKey.Blank, progress = flowOf(1.0f), isInitiatedByUserInput = false, isUserInputOngoing = flowOf(false), ) // isCommunalVisible is still true as the false as soon as transition away runs. assertThat(isCommunalVisible).isEqualTo(true) } @Test fun testShowWidgetEditorStartsActivity() = testScope.runTest { Loading packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/touch/CommunalTouchHandlerTest.java +0 −10 Original line number Diff line number Diff line Loading @@ -28,7 +28,6 @@ import androidx.test.filters.SmallTest; import com.android.systemui.SysuiTestCase; import com.android.systemui.shared.system.InputChannelCompat; import com.android.systemui.statusbar.NotificationShadeWindowController; import com.android.systemui.statusbar.phone.CentralSurfaces; import org.junit.Before; Loading @@ -47,8 +46,6 @@ public class CommunalTouchHandlerTest extends SysuiTestCase { @Mock CentralSurfaces mCentralSurfaces; @Mock NotificationShadeWindowController mNotificationShadeWindowController; @Mock DreamTouchHandler.TouchSession mTouchSession; CommunalTouchHandler mTouchHandler; Loading @@ -59,16 +56,9 @@ public class CommunalTouchHandlerTest extends SysuiTestCase { MockitoAnnotations.initMocks(this); mTouchHandler = new CommunalTouchHandler( Optional.of(mCentralSurfaces), mNotificationShadeWindowController, INITIATION_WIDTH); } @Test public void testSessionStartForcesShadeOpen() { mTouchHandler.onSessionStart(mTouchSession); verify(mNotificationShadeWindowController).setForcePluginOpen(true, mTouchHandler); } @Test public void testEventPropagation() { final MotionEvent motionEvent = Mockito.mock(MotionEvent.class); Loading packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalInteractor.kt +21 −2 Original line number Diff line number Diff line Loading @@ -129,9 +129,18 @@ constructor( .distinctUntilChanged() /** * Flow that emits a boolean if the communal UI is showing, ie. the [desiredScene] is the * [CommunalSceneKey.Communal]. * Flow that emits a boolean if the communal UI is the target scene, ie. the [desiredScene] is * the [CommunalSceneKey.Communal]. * * This will be true as soon as the desired scene is set programmatically or at whatever point * during a fling that SceneTransitionLayout determines that the end state will be the communal * scene. The value also does not change while flinging away until the target scene is no longer * communal. * * If you need a flow that is only true when communal is fully showing and not in transition, * use [isIdleOnCommunal]. */ // TODO(b/323215860): rename to something more appropriate after cleaning up usages val isCommunalShowing: Flow<Boolean> = communalRepository.desiredScene.map { it == CommunalSceneKey.Communal } Loading @@ -146,6 +155,16 @@ constructor( it is ObservableCommunalTransitionState.Idle && it.scene == CommunalSceneKey.Communal } /** * Flow that emits a boolean if any portion of the communal UI is visible at all. * * This flow will be true during any transition and when idle on the communal scene. */ val isCommunalVisible: Flow<Boolean> = communalRepository.transitionState.map { !(it is ObservableCommunalTransitionState.Idle && it.scene == CommunalSceneKey.Blank) } /** Callback received whenever the [SceneTransitionLayout] finishes a scene transition. */ fun onSceneChanged(newScene: CommunalSceneKey) { communalRepository.setDesiredScene(newScene) Loading packages/SystemUI/src/com/android/systemui/dreams/touch/CommunalTouchHandler.java +2 −7 Original line number Diff line number Diff line Loading @@ -23,7 +23,6 @@ import android.graphics.Region; import android.view.GestureDetector; import android.view.MotionEvent; import com.android.systemui.statusbar.NotificationShadeWindowController; import com.android.systemui.statusbar.phone.CentralSurfaces; import java.util.Optional; Loading @@ -34,17 +33,14 @@ import javax.inject.Named; /** {@link DreamTouchHandler} responsible for handling touches to open communal hub. **/ public class CommunalTouchHandler implements DreamTouchHandler { private final int mInitiationWidth; private final NotificationShadeWindowController mNotificationShadeWindowController; private final Optional<CentralSurfaces> mCentralSurfaces; @Inject public CommunalTouchHandler( Optional<CentralSurfaces> centralSurfaces, NotificationShadeWindowController notificationShadeWindowController, @Named(COMMUNAL_GESTURE_INITIATION_WIDTH) int initiationWidth) { mInitiationWidth = initiationWidth; mCentralSurfaces = centralSurfaces; mNotificationShadeWindowController = notificationShadeWindowController; } @Override Loading @@ -60,9 +56,8 @@ public class CommunalTouchHandler implements DreamTouchHandler { } private void handleSessionStart(CentralSurfaces surfaces, TouchSession session) { // Force the notification shade window open (otherwise the hub won't show while swiping). mNotificationShadeWindowController.setForcePluginOpen(true, this); // Notification shade window has its own logic to be visible if the hub is open, no need to // do anything here other than send touch events over. session.registerInputListener(ev -> { surfaces.handleDreamTouch((MotionEvent) ev); if (ev != null && ((MotionEvent) ev).getAction() == MotionEvent.ACTION_UP) { Loading packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowControllerImpl.java +11 −8 Original line number Diff line number Diff line Loading @@ -331,8 +331,8 @@ public class NotificationShadeWindowControllerImpl implements NotificationShadeW ); collectFlow( mWindowRootView, mCommunalInteractor.get().isCommunalShowing(), this::onCommunalShowingChanged mCommunalInteractor.get().isCommunalVisible(), this::onCommunalVisibleChanged ); } Loading Loading @@ -475,6 +475,9 @@ public class NotificationShadeWindowControllerImpl implements NotificationShadeW } visible = true; mLogger.d("Visibility forced to be true"); } else if (state.communalVisible) { visible = true; mLogger.d("Visibility forced to be true by communal"); } if (mWindowRootView != null) { if (visible) { Loading Loading @@ -510,15 +513,15 @@ public class NotificationShadeWindowControllerImpl implements NotificationShadeW } private void applyUserActivityTimeout(NotificationShadeWindowState state) { final Boolean communalShowing = state.isCommunalShowingAndNotOccluded(); final Boolean communalVisible = state.isCommunalVisibleAndNotOccluded(); final Boolean keyguardShowing = state.isKeyguardShowingAndNotOccluded(); long timeout = -1; if ((communalShowing || keyguardShowing) if ((communalVisible || keyguardShowing) && state.statusBarState == StatusBarState.KEYGUARD && !state.qsExpanded) { if (state.bouncerShowing) { timeout = KeyguardViewMediator.AWAKE_INTERVAL_BOUNCER_MS; } else if (communalShowing) { } else if (communalVisible) { timeout = CommunalInteractor.AWAKE_INTERVAL_MS; } else if (keyguardShowing) { timeout = mLockScreenDisplayTimeout; Loading Loading @@ -624,7 +627,7 @@ public class NotificationShadeWindowControllerImpl implements NotificationShadeW state.dozing, state.scrimsVisibility, state.backgroundBlurRadius, state.communalShowing state.communalVisible ); } Loading Loading @@ -749,8 +752,8 @@ public class NotificationShadeWindowControllerImpl implements NotificationShadeW } @VisibleForTesting void onCommunalShowingChanged(Boolean showing) { mCurrentState.communalShowing = showing; void onCommunalVisibleChanged(Boolean visible) { mCurrentState.communalVisible = visible; apply(mCurrentState); } Loading Loading
packages/SystemUI/multivalentTests/src/com/android/systemui/communal/domain/interactor/CommunalInteractorTest.kt +47 −0 Original line number Diff line number Diff line Loading @@ -641,6 +641,53 @@ class CommunalInteractorTest : SysuiTestCase() { assertThat(isIdleOnCommunal).isEqualTo(false) } @Test fun isCommunalVisible() = testScope.runTest { val transitionState = MutableStateFlow<ObservableCommunalTransitionState>( ObservableCommunalTransitionState.Idle(CommunalSceneKey.Blank) ) communalRepository.setTransitionState(transitionState) // isCommunalVisible is false when not on communal. val isCommunalVisible by collectLastValue(underTest.isCommunalVisible) assertThat(isCommunalVisible).isEqualTo(false) // Start transition to communal. transitionState.value = ObservableCommunalTransitionState.Transition( fromScene = CommunalSceneKey.Blank, toScene = CommunalSceneKey.Communal, progress = flowOf(0f), isInitiatedByUserInput = false, isUserInputOngoing = flowOf(false), ) // isCommunalVisible is true once transition starts. assertThat(isCommunalVisible).isEqualTo(true) // Finish transition to communal transitionState.value = ObservableCommunalTransitionState.Idle(CommunalSceneKey.Communal) // isCommunalVisible is true since we're on communal. assertThat(isCommunalVisible).isEqualTo(true) // Start transition away from communal. transitionState.value = ObservableCommunalTransitionState.Transition( fromScene = CommunalSceneKey.Communal, toScene = CommunalSceneKey.Blank, progress = flowOf(1.0f), isInitiatedByUserInput = false, isUserInputOngoing = flowOf(false), ) // isCommunalVisible is still true as the false as soon as transition away runs. assertThat(isCommunalVisible).isEqualTo(true) } @Test fun testShowWidgetEditorStartsActivity() = testScope.runTest { Loading
packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/touch/CommunalTouchHandlerTest.java +0 −10 Original line number Diff line number Diff line Loading @@ -28,7 +28,6 @@ import androidx.test.filters.SmallTest; import com.android.systemui.SysuiTestCase; import com.android.systemui.shared.system.InputChannelCompat; import com.android.systemui.statusbar.NotificationShadeWindowController; import com.android.systemui.statusbar.phone.CentralSurfaces; import org.junit.Before; Loading @@ -47,8 +46,6 @@ public class CommunalTouchHandlerTest extends SysuiTestCase { @Mock CentralSurfaces mCentralSurfaces; @Mock NotificationShadeWindowController mNotificationShadeWindowController; @Mock DreamTouchHandler.TouchSession mTouchSession; CommunalTouchHandler mTouchHandler; Loading @@ -59,16 +56,9 @@ public class CommunalTouchHandlerTest extends SysuiTestCase { MockitoAnnotations.initMocks(this); mTouchHandler = new CommunalTouchHandler( Optional.of(mCentralSurfaces), mNotificationShadeWindowController, INITIATION_WIDTH); } @Test public void testSessionStartForcesShadeOpen() { mTouchHandler.onSessionStart(mTouchSession); verify(mNotificationShadeWindowController).setForcePluginOpen(true, mTouchHandler); } @Test public void testEventPropagation() { final MotionEvent motionEvent = Mockito.mock(MotionEvent.class); Loading
packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalInteractor.kt +21 −2 Original line number Diff line number Diff line Loading @@ -129,9 +129,18 @@ constructor( .distinctUntilChanged() /** * Flow that emits a boolean if the communal UI is showing, ie. the [desiredScene] is the * [CommunalSceneKey.Communal]. * Flow that emits a boolean if the communal UI is the target scene, ie. the [desiredScene] is * the [CommunalSceneKey.Communal]. * * This will be true as soon as the desired scene is set programmatically or at whatever point * during a fling that SceneTransitionLayout determines that the end state will be the communal * scene. The value also does not change while flinging away until the target scene is no longer * communal. * * If you need a flow that is only true when communal is fully showing and not in transition, * use [isIdleOnCommunal]. */ // TODO(b/323215860): rename to something more appropriate after cleaning up usages val isCommunalShowing: Flow<Boolean> = communalRepository.desiredScene.map { it == CommunalSceneKey.Communal } Loading @@ -146,6 +155,16 @@ constructor( it is ObservableCommunalTransitionState.Idle && it.scene == CommunalSceneKey.Communal } /** * Flow that emits a boolean if any portion of the communal UI is visible at all. * * This flow will be true during any transition and when idle on the communal scene. */ val isCommunalVisible: Flow<Boolean> = communalRepository.transitionState.map { !(it is ObservableCommunalTransitionState.Idle && it.scene == CommunalSceneKey.Blank) } /** Callback received whenever the [SceneTransitionLayout] finishes a scene transition. */ fun onSceneChanged(newScene: CommunalSceneKey) { communalRepository.setDesiredScene(newScene) Loading
packages/SystemUI/src/com/android/systemui/dreams/touch/CommunalTouchHandler.java +2 −7 Original line number Diff line number Diff line Loading @@ -23,7 +23,6 @@ import android.graphics.Region; import android.view.GestureDetector; import android.view.MotionEvent; import com.android.systemui.statusbar.NotificationShadeWindowController; import com.android.systemui.statusbar.phone.CentralSurfaces; import java.util.Optional; Loading @@ -34,17 +33,14 @@ import javax.inject.Named; /** {@link DreamTouchHandler} responsible for handling touches to open communal hub. **/ public class CommunalTouchHandler implements DreamTouchHandler { private final int mInitiationWidth; private final NotificationShadeWindowController mNotificationShadeWindowController; private final Optional<CentralSurfaces> mCentralSurfaces; @Inject public CommunalTouchHandler( Optional<CentralSurfaces> centralSurfaces, NotificationShadeWindowController notificationShadeWindowController, @Named(COMMUNAL_GESTURE_INITIATION_WIDTH) int initiationWidth) { mInitiationWidth = initiationWidth; mCentralSurfaces = centralSurfaces; mNotificationShadeWindowController = notificationShadeWindowController; } @Override Loading @@ -60,9 +56,8 @@ public class CommunalTouchHandler implements DreamTouchHandler { } private void handleSessionStart(CentralSurfaces surfaces, TouchSession session) { // Force the notification shade window open (otherwise the hub won't show while swiping). mNotificationShadeWindowController.setForcePluginOpen(true, this); // Notification shade window has its own logic to be visible if the hub is open, no need to // do anything here other than send touch events over. session.registerInputListener(ev -> { surfaces.handleDreamTouch((MotionEvent) ev); if (ev != null && ((MotionEvent) ev).getAction() == MotionEvent.ACTION_UP) { Loading
packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowControllerImpl.java +11 −8 Original line number Diff line number Diff line Loading @@ -331,8 +331,8 @@ public class NotificationShadeWindowControllerImpl implements NotificationShadeW ); collectFlow( mWindowRootView, mCommunalInteractor.get().isCommunalShowing(), this::onCommunalShowingChanged mCommunalInteractor.get().isCommunalVisible(), this::onCommunalVisibleChanged ); } Loading Loading @@ -475,6 +475,9 @@ public class NotificationShadeWindowControllerImpl implements NotificationShadeW } visible = true; mLogger.d("Visibility forced to be true"); } else if (state.communalVisible) { visible = true; mLogger.d("Visibility forced to be true by communal"); } if (mWindowRootView != null) { if (visible) { Loading Loading @@ -510,15 +513,15 @@ public class NotificationShadeWindowControllerImpl implements NotificationShadeW } private void applyUserActivityTimeout(NotificationShadeWindowState state) { final Boolean communalShowing = state.isCommunalShowingAndNotOccluded(); final Boolean communalVisible = state.isCommunalVisibleAndNotOccluded(); final Boolean keyguardShowing = state.isKeyguardShowingAndNotOccluded(); long timeout = -1; if ((communalShowing || keyguardShowing) if ((communalVisible || keyguardShowing) && state.statusBarState == StatusBarState.KEYGUARD && !state.qsExpanded) { if (state.bouncerShowing) { timeout = KeyguardViewMediator.AWAKE_INTERVAL_BOUNCER_MS; } else if (communalShowing) { } else if (communalVisible) { timeout = CommunalInteractor.AWAKE_INTERVAL_MS; } else if (keyguardShowing) { timeout = mLockScreenDisplayTimeout; Loading Loading @@ -624,7 +627,7 @@ public class NotificationShadeWindowControllerImpl implements NotificationShadeW state.dozing, state.scrimsVisibility, state.backgroundBlurRadius, state.communalShowing state.communalVisible ); } Loading Loading @@ -749,8 +752,8 @@ public class NotificationShadeWindowControllerImpl implements NotificationShadeW } @VisibleForTesting void onCommunalShowingChanged(Boolean showing) { mCurrentState.communalShowing = showing; void onCommunalVisibleChanged(Boolean visible) { mCurrentState.communalVisible = visible; apply(mCurrentState); } Loading