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

Commit e97df3f9 authored by Nicolo' Mazzucato's avatar Nicolo' Mazzucato
Browse files

Open user switcher with status bar context when opened from chip

The user switcher dialog was being opened always with the shade context:
 it means it was always a subwindow of the shade window, and visible
 only when the shade was visible (after the changes introduced by
 I43b6d34ba24d338ea08ab67893a0e121cddcceb2)

Now, the ShowDialogRequestModel also supports a custom context. When
provided, the dialog is created with such context (e.g. when touching a
status bar user chip, the dialog will now appear on that display,
regardless of the shade window position.

Bug: 362719719
Bug: 414780857
Test: UserSwitcherInteractorTest
Flag: com.android.window.flags.enable_window_context_override_type
Flag: com.android.systemui.shade_window_goes_around
Change-Id: I6abd72194bfeb0b8915821f055cedd816822c8c4
parent d97f841e
Loading
Loading
Loading
Loading
+42 −0
Original line number Diff line number Diff line
@@ -996,6 +996,48 @@ class UserSwitcherInteractorTest : SysuiTestCase() {
        }
    }

    @Test
    fun showUserSwitcher_fullScreenDisabled_propagatesCustomContext() {
        createUserInteractor()
        testScope.runTest {
            val expandable = mock<Expandable>()
            val context = mock<Context>()
            underTest.showUserSwitcher(expandable, context)

            val dialogRequest = collectLastValue(underTest.dialogShowRequests)

            // Dialog is shown.
            assertThat(dialogRequest())
                .isEqualTo(ShowDialogRequestModel.ShowUserSwitcherDialog(expandable, context))

            underTest.onDialogShown()
            assertThat(dialogRequest()).isNull()
        }
    }

    @Test
    fun showUserSwitcher_fullScreenEnabled_propagatesCustomContext() {
        createUserInteractor()
        testScope.runTest {
            kosmos.fakeFeatureFlagsClassic.set(Flags.FULL_SCREEN_USER_SWITCHER, true)

            val expandable = mock<Expandable>()
            val context = mock<Context>()
            underTest.showUserSwitcher(expandable, context)

            val dialogRequest = collectLastValue(underTest.dialogShowRequests)

            // Dialog is shown.
            assertThat(dialogRequest())
                .isEqualTo(
                    ShowDialogRequestModel.ShowUserSwitcherFullscreenDialog(expandable, context)
                )

            underTest.onDialogShown()
            assertThat(dialogRequest()).isNull()
        }
    }

    @Test
    fun showUserSwitcher_fullScreenEnabled_launchesFullScreenDialog() {
        createUserInteractor()
+9 −3
Original line number Diff line number Diff line
@@ -542,11 +542,17 @@ constructor(
        }
    }

    fun showUserSwitcher(expandable: Expandable) {
    /**
     * Shows the user switcher dialog.
     *
     * If [context] is provided, the dialog will be created from that context. If not provided, the
     * shade context will be used.
     */
    fun showUserSwitcher(expandable: Expandable, context: Context? = null) {
        if (featureFlags.isEnabled(Flags.FULL_SCREEN_USER_SWITCHER)) {
            showDialog(ShowDialogRequestModel.ShowUserSwitcherFullscreenDialog(expandable))
            showDialog(ShowDialogRequestModel.ShowUserSwitcherFullscreenDialog(expandable, context))
        } else {
            showDialog(ShowDialogRequestModel.ShowUserSwitcherDialog(expandable))
            showDialog(ShowDialogRequestModel.ShowUserSwitcherDialog(expandable, context))
        }
    }

+12 −4
Original line number Diff line number Diff line
@@ -17,14 +17,22 @@

package com.android.systemui.user.domain.model

import android.content.Context
import android.os.UserHandle
import com.android.systemui.animation.Expandable
import com.android.systemui.qs.user.UserSwitchDialogController

/** Encapsulates a request to show a dialog. */
/**
 * Encapsulates a request to show a dialog.
 *
 * Requests might have a custom context as they need to be shown in a specific display (e.g. the
 * display of the status bar chip that was touched). If no custom context is provided, the dialog
 * will be shown as child of the shade window (and be visible only when the shade is visible)
 */
sealed class ShowDialogRequestModel(
    open val dialogShower: UserSwitchDialogController.DialogShower? = null,
    open val expandable: Expandable? = null,
    open val context: Context? = null,
) {
    data class ShowAddUserDialog(
        val userHandle: UserHandle,
@@ -33,9 +41,7 @@ sealed class ShowDialogRequestModel(
        override val dialogShower: UserSwitchDialogController.DialogShower?,
    ) : ShowDialogRequestModel(dialogShower)

    data class ShowUserCreationDialog(
        val isGuest: Boolean,
    ) : ShowDialogRequestModel()
    data class ShowUserCreationDialog(val isGuest: Boolean) : ShowDialogRequestModel()

    data class ShowExitGuestDialog(
        val guestUserId: Int,
@@ -49,9 +55,11 @@ sealed class ShowDialogRequestModel(
    /** Show the user switcher dialog */
    data class ShowUserSwitcherDialog(
        override val expandable: Expandable?,
        override val context: Context? = null,
    ) : ShowDialogRequestModel()

    data class ShowUserSwitcherFullscreenDialog(
        override val expandable: Expandable?,
        override val context: Context? = null,
    ) : ShowDialogRequestModel()
}
+3 −6
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ package com.android.systemui.user.ui.binder
import androidx.core.view.isVisible
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.repeatOnLifecycle
import com.android.app.tracing.coroutines.launchTraced as launch
import com.android.systemui.animation.Expandable
import com.android.systemui.common.ui.binder.TextViewBinder
import com.android.systemui.lifecycle.repeatWhenAttached
@@ -27,16 +28,12 @@ import com.android.systemui.statusbar.phone.userswitcher.StatusBarUserSwitcherCo
import com.android.systemui.user.ui.viewmodel.StatusBarUserChipViewModel
import kotlinx.coroutines.InternalCoroutinesApi
import kotlinx.coroutines.flow.collect
import com.android.app.tracing.coroutines.launchTraced as launch

@OptIn(InternalCoroutinesApi::class)
object StatusBarUserChipViewBinder {
    /** Binds the status bar user chip view model to the given view */
    @JvmStatic
    fun bind(
        view: StatusBarUserSwitcherContainer,
        viewModel: StatusBarUserChipViewModel,
    ) {
    fun bind(view: StatusBarUserSwitcherContainer, viewModel: StatusBarUserChipViewModel) {
        view.repeatWhenAttached {
            repeatOnLifecycle(Lifecycle.State.STARTED) {
                launch {
@@ -60,6 +57,6 @@ object StatusBarUserChipViewBinder {
        view: StatusBarUserSwitcherContainer,
        viewModel: StatusBarUserChipViewModel,
    ) {
        view.setOnClickListener { viewModel.onClick(Expandable.fromView(view)) }
        view.setOnClickListener { viewModel.onClick(Expandable.fromView(view), view.context) }
    }
}
+3 −9
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@
package com.android.systemui.user.ui.dialog

import android.app.Dialog
import com.android.app.tracing.coroutines.launchTraced as launch
import com.android.internal.jank.InteractionJankMonitor
import com.android.internal.logging.UiEventLogger
import com.android.settingslib.users.UserCreatingDialog
@@ -41,7 +42,6 @@ import javax.inject.Inject
import javax.inject.Provider
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.filterNotNull
import com.android.app.tracing.coroutines.launchTraced as launch

/** Coordinates dialogs for user switcher logic. */
@SysUISingleton
@@ -71,7 +71,7 @@ constructor(
    private fun startHandlingDialogShowRequests() {
        applicationScope.get().launch {
            interactor.get().dialogShowRequests.filterNotNull().collect { request ->
                val context = shadeDialogContextInteractor.get().context
                val context = request.context ?: shadeDialogContextInteractor.get().context
                val (dialog, dialogCuj) =
                    when (request) {
                        is ShowDialogRequestModel.ShowAddUserDialog ->
@@ -91,13 +91,7 @@ constructor(
                                ),
                            )
                        is ShowDialogRequestModel.ShowUserCreationDialog ->
                            Pair(
                                UserCreatingDialog(
                                    context,
                                    request.isGuest,
                                ),
                                null,
                            )
                            Pair(UserCreatingDialog(context, request.isGuest), null)
                        is ShowDialogRequestModel.ShowExitGuestDialog ->
                            Pair(
                                ExitGuestDialog(
Loading