Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9612fe39 authored by William Xiao's avatar William Xiao Committed by Android (Google) Code Review
Browse files

Merge "Fix touch handling for glanceable hub over dream" into main

parents 41290e71 691fe6a1
Loading
Loading
Loading
Loading
+47 −0
Original line number Diff line number Diff line
@@ -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 {
+0 −10
Original line number Diff line number Diff line
@@ -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;
@@ -47,8 +46,6 @@ public class CommunalTouchHandlerTest extends SysuiTestCase {
    @Mock
    CentralSurfaces mCentralSurfaces;
    @Mock
    NotificationShadeWindowController mNotificationShadeWindowController;
    @Mock
    DreamTouchHandler.TouchSession mTouchSession;
    CommunalTouchHandler mTouchHandler;

@@ -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);
+21 −2
Original line number Diff line number Diff line
@@ -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 }

@@ -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)
+2 −7
Original line number Diff line number Diff line
@@ -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;
@@ -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
@@ -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) {
+11 −8
Original line number Diff line number Diff line
@@ -331,8 +331,8 @@ public class NotificationShadeWindowControllerImpl implements NotificationShadeW
        );
        collectFlow(
                mWindowRootView,
                mCommunalInteractor.get().isCommunalShowing(),
                this::onCommunalShowingChanged
                mCommunalInteractor.get().isCommunalVisible(),
                this::onCommunalVisibleChanged
        );
    }

@@ -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) {
@@ -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;
@@ -624,7 +627,7 @@ public class NotificationShadeWindowControllerImpl implements NotificationShadeW
                state.dozing,
                state.scrimsVisibility,
                state.backgroundBlurRadius,
                state.communalShowing
                state.communalVisible
        );
    }

@@ -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