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

Commit 02e7d838 authored by Shawn Lee's avatar Shawn Lee
Browse files

Make flexiglass window visible when swiping on launcher and status bar

When a touch is going to be proxied from launcher to shade, the flexiglass
window is made visible so touches can slip onto it. Touches on the status
bar are piped into flexiglass through SceneInteractor. Both invocation
methods open the shade scene directly at the moment, awaiting various blockers.

Bug: 290682366
Test: new unit test
Test: manually verified MotionEvents being detected in flexiglass from swipes
on launcher and status bar
Test: manually verified no behavior is changed when the feature flag is disabled

Change-Id: I0feb4b5b38f3bf00ac846e9bba735dbeff145f3c
parent cba02ebf
Loading
Loading
Loading
Loading
+8 −8
Original line number Diff line number Diff line
@@ -92,6 +92,14 @@ private fun Scene(
    onSceneChanged: (SceneModel) -> Unit,
    modifier: Modifier = Modifier,
) {
    val destinationScenes: Map<UserAction, SceneModel> by
        scene.destinationScenes(containerName).collectAsState()
    val swipeLeftDestinationScene = destinationScenes[UserAction.Swipe(Direction.LEFT)]
    val swipeUpDestinationScene = destinationScenes[UserAction.Swipe(Direction.UP)]
    val swipeRightDestinationScene = destinationScenes[UserAction.Swipe(Direction.RIGHT)]
    val swipeDownDestinationScene = destinationScenes[UserAction.Swipe(Direction.DOWN)]
    val backDestinationScene = destinationScenes[UserAction.Back]

    // TODO(b/280880714): replace with the real UI and make sure to call onTransitionProgress.
    Box(modifier) {
        Column(
@@ -103,14 +111,6 @@ private fun Scene(
                modifier = Modifier,
            )

            val destinationScenes: Map<UserAction, SceneModel> by
                scene.destinationScenes(containerName).collectAsState()
            val swipeLeftDestinationScene = destinationScenes[UserAction.Swipe(Direction.LEFT)]
            val swipeUpDestinationScene = destinationScenes[UserAction.Swipe(Direction.UP)]
            val swipeRightDestinationScene = destinationScenes[UserAction.Swipe(Direction.RIGHT)]
            val swipeDownDestinationScene = destinationScenes[UserAction.Swipe(Direction.DOWN)]
            val backDestinationScene = destinationScenes[UserAction.Back]

            Row(
                horizontalArrangement = Arrangement.spacedBy(8.dp),
            ) {
+31 −8
Original line number Diff line number Diff line
@@ -84,6 +84,8 @@ import com.android.systemui.Dumpable;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.flags.Flags;
import com.android.systemui.keyguard.KeyguardUnlockAnimationController;
import com.android.systemui.keyguard.ScreenLifecycle;
import com.android.systemui.keyguard.WakefulnessLifecycle;
@@ -94,6 +96,8 @@ import com.android.systemui.navigationbar.NavigationBarView;
import com.android.systemui.navigationbar.NavigationModeController;
import com.android.systemui.navigationbar.buttons.KeyButtonView;
import com.android.systemui.recents.OverviewProxyService.OverviewProxyListener;
import com.android.systemui.scene.domain.interactor.SceneInteractor;
import com.android.systemui.scene.shared.model.SceneContainerNames;
import com.android.systemui.settings.DisplayTracker;
import com.android.systemui.settings.UserTracker;
import com.android.systemui.shade.ShadeViewController;
@@ -120,6 +124,7 @@ import java.util.concurrent.Executor;
import java.util.function.Supplier;

import javax.inject.Inject;
import javax.inject.Provider;

/**
 * Class to send information from overview to launcher with a binder.
@@ -139,6 +144,7 @@ public class OverviewProxyService implements CallbackController<OverviewProxyLis
    private static final long MAX_BACKOFF_MILLIS = 10 * 60 * 1000;

    private final Context mContext;
    private final FeatureFlags mFeatureFlags;
    private final Executor mMainExecutor;
    private final ShellInterface mShellInterface;
    private final Lazy<Optional<CentralSurfaces>> mCentralSurfacesOptionalLazy;
@@ -147,6 +153,8 @@ public class OverviewProxyService implements CallbackController<OverviewProxyLis
    private final Handler mHandler;
    private final Lazy<NavigationBarController> mNavBarControllerLazy;
    private final NotificationShadeWindowController mStatusBarWinController;
    private final Provider<SceneInteractor> mSceneInteractor;

    private final Runnable mConnectionRunnable = () ->
            internalConnectToCurrentUser("runnable: startConnectionToCurrentUser");
    private final ComponentName mRecentsComponentName;
@@ -209,18 +217,29 @@ public class OverviewProxyService implements CallbackController<OverviewProxyLis
                            mInputFocusTransferStarted = true;
                            mInputFocusTransferStartY = event.getY();
                            mInputFocusTransferStartMillis = event.getEventTime();

                            // If scene framework is enabled, set the scene container window to
                            // visible and let the touch "slip" into that window.
                            if (mFeatureFlags.isEnabled(Flags.SCENE_CONTAINER)) {
                                mSceneInteractor.get().setVisible(
                                        SceneContainerNames.SYSTEM_UI_DEFAULT, true);
                            } else {
                                centralSurfaces.onInputFocusTransfer(
                                        mInputFocusTransferStarted, false /* cancel */,
                                        0 /* velocity */);
                            }
                        }
                        if (action == ACTION_UP || action == ACTION_CANCEL) {
                            mInputFocusTransferStarted = false;

                            if (!mFeatureFlags.isEnabled(Flags.SCENE_CONTAINER)) {
                                float velocity = (event.getY() - mInputFocusTransferStartY)
                                        / (event.getEventTime() - mInputFocusTransferStartMillis);
                                centralSurfaces.onInputFocusTransfer(mInputFocusTransferStarted,
                                        action == ACTION_CANCEL,
                                        velocity);
                            }
                        }
                        event.recycle();
                    });
                });
@@ -552,6 +571,7 @@ public class OverviewProxyService implements CallbackController<OverviewProxyLis
            NavigationModeController navModeController,
            NotificationShadeWindowController statusBarWinController,
            SysUiState sysUiState,
            Provider<SceneInteractor> sceneInteractor,
            UserTracker userTracker,
            ScreenLifecycle screenLifecycle,
            WakefulnessLifecycle wakefulnessLifecycle,
@@ -559,6 +579,7 @@ public class OverviewProxyService implements CallbackController<OverviewProxyLis
            DisplayTracker displayTracker,
            KeyguardUnlockAnimationController sysuiUnlockAnimationController,
            AssistUtils assistUtils,
            FeatureFlags featureFlags,
            DumpManager dumpManager,
            Optional<UnfoldTransitionProgressForwarder> unfoldTransitionProgressForwarder
    ) {
@@ -568,6 +589,7 @@ public class OverviewProxyService implements CallbackController<OverviewProxyLis
        }

        mContext = context;
        mFeatureFlags = featureFlags;
        mMainExecutor = mainExecutor;
        mShellInterface = shellInterface;
        mCentralSurfacesOptionalLazy = centralSurfacesOptionalLazy;
@@ -575,6 +597,7 @@ public class OverviewProxyService implements CallbackController<OverviewProxyLis
        mHandler = new Handler();
        mNavBarControllerLazy = navBarControllerLazy;
        mStatusBarWinController = statusBarWinController;
        mSceneInteractor = sceneInteractor;
        mUserTracker = userTracker;
        mConnectionBackoffAttempts = 0;
        mRecentsComponentName = ComponentName.unflattenFromString(context.getString(
+13 −0
Original line number Diff line number Diff line
@@ -18,11 +18,14 @@ package com.android.systemui.scene.domain.interactor

import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.scene.data.repository.SceneContainerRepository
import com.android.systemui.scene.shared.model.RemoteUserInput
import com.android.systemui.scene.shared.model.SceneKey
import com.android.systemui.scene.shared.model.SceneModel
import com.android.systemui.scene.shared.model.SceneTransitionModel
import javax.inject.Inject
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow

/**
 * Generic business logic and app state accessors for the scene framework.
@@ -92,4 +95,14 @@ constructor(
    fun sceneTransitions(containerName: String): StateFlow<SceneTransitionModel?> {
        return repository.sceneTransitions(containerName)
    }

    private val _remoteUserInput: MutableStateFlow<RemoteUserInput?> = MutableStateFlow(null)

    /** A flow of motion events originating from outside of the scene framework. */
    val remoteUserInput: StateFlow<RemoteUserInput?> = _remoteUserInput.asStateFlow()

    /** Handles a remote user input. */
    fun onRemoteUserInput(input: RemoteUserInput) {
        _remoteUserInput.value = input
    }
}
+35 −0
Original line number Diff line number Diff line
package com.android.systemui.scene.shared.model

import android.view.MotionEvent

/** A representation of user input that is used by the scene framework. */
data class RemoteUserInput(
    val x: Float,
    val y: Float,
    val action: RemoteUserInputAction,
) {
    companion object {
        fun translateMotionEvent(event: MotionEvent): RemoteUserInput {
            return RemoteUserInput(
                x = event.x,
                y = event.y,
                action =
                    when (event.actionMasked) {
                        MotionEvent.ACTION_DOWN -> RemoteUserInputAction.DOWN
                        MotionEvent.ACTION_MOVE -> RemoteUserInputAction.MOVE
                        MotionEvent.ACTION_UP -> RemoteUserInputAction.UP
                        MotionEvent.ACTION_CANCEL -> RemoteUserInputAction.CANCEL
                        else -> RemoteUserInputAction.UNKNOWN
                    }
            )
        }
    }
}

enum class RemoteUserInputAction {
    DOWN,
    MOVE,
    UP,
    CANCEL,
    UNKNOWN,
}
+13 −0
Original line number Diff line number Diff line
@@ -2,6 +2,7 @@ package com.android.systemui.scene.ui.view

import android.content.Context
import android.util.AttributeSet
import android.view.MotionEvent
import android.view.View
import com.android.systemui.scene.shared.model.Scene
import com.android.systemui.scene.shared.model.SceneContainerConfig
@@ -16,11 +17,15 @@ class SceneWindowRootView(
        context,
        attrs,
    ) {

    private lateinit var viewModel: SceneContainerViewModel

    fun init(
        viewModel: SceneContainerViewModel,
        containerConfig: SceneContainerConfig,
        scenes: Set<Scene>,
    ) {
        this.viewModel = viewModel
        SceneWindowRootViewBinder.bind(
            view = this@SceneWindowRootView,
            viewModel = viewModel,
@@ -32,6 +37,14 @@ class SceneWindowRootView(
        )
    }

    override fun onTouchEvent(event: MotionEvent?): Boolean {
        return event?.let {
            viewModel.onRemoteUserInput(event)
            true
        }
            ?: false
    }

    override fun setVisibility(visibility: Int) {
        // Do nothing. We don't want external callers to invoke this. Instead, we drive our own
        // visibility from our view-binder.
Loading