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

Commit 2183d918 authored by Ioana Alexandru's avatar Ioana Alexandru
Browse files

Revert^2 "Open modes settings on tile long press"

This reverts commit 2a6d10d8.

Reason for revert: fixed failing test by making it device-only

Change-Id: I98d9583e1167ad20dd3cc492dc149aec4fa9d0dd
parent 2a6d10d8
Loading
Loading
Loading
Loading
+1 −0
Original line number Original line Diff line number Diff line
@@ -258,6 +258,7 @@ filegroup {
        "tests/src/**/systemui/statusbar/policy/LocationControllerImplTest.java",
        "tests/src/**/systemui/statusbar/policy/LocationControllerImplTest.java",
        "tests/src/**/systemui/statusbar/policy/RemoteInputViewTest.java",
        "tests/src/**/systemui/statusbar/policy/RemoteInputViewTest.java",
        "tests/src/**/systemui/statusbar/policy/SmartReplyViewTest.java",
        "tests/src/**/systemui/statusbar/policy/SmartReplyViewTest.java",
        "tests/src/**/systemui/statusbar/policy/ui/dialog/ModesDialogDelegateTest.kt",
        "tests/src/**/systemui/statusbar/StatusBarStateControllerImplTest.kt",
        "tests/src/**/systemui/statusbar/StatusBarStateControllerImplTest.kt",
        "tests/src/**/systemui/theme/ThemeOverlayApplierTest.java",
        "tests/src/**/systemui/theme/ThemeOverlayApplierTest.java",
        "tests/src/**/systemui/touch/TouchInsetManagerTest.java",
        "tests/src/**/systemui/touch/TouchInsetManagerTest.java",
+35 −31
Original line number Original line Diff line number Diff line
@@ -21,64 +21,68 @@ import android.provider.Settings
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.SysuiTestCase
import com.android.systemui.animation.DialogTransitionAnimator
import com.android.systemui.animation.Expandable
import com.android.systemui.qs.tiles.base.actions.FakeQSTileIntentUserInputHandler
import com.android.systemui.qs.tiles.base.actions.QSTileIntentUserInputHandlerSubject
import com.android.systemui.qs.tiles.base.actions.QSTileIntentUserInputHandlerSubject
import com.android.systemui.qs.tiles.base.actions.qsTileIntentUserInputHandler
import com.android.systemui.qs.tiles.base.interactor.QSTileInputTestKtx
import com.android.systemui.qs.tiles.base.interactor.QSTileInputTestKtx
import com.android.systemui.qs.tiles.impl.modes.domain.model.ModesTileModel
import com.android.systemui.qs.tiles.impl.modes.domain.model.ModesTileModel
import com.android.systemui.statusbar.phone.SystemUIDialog
import com.android.systemui.statusbar.policy.ui.dialog.mockModesDialogDelegate
import com.android.systemui.statusbar.policy.ui.dialog.ModesDialogDelegate
import com.android.systemui.testKosmos
import com.google.common.truth.Truth
import com.google.common.truth.Truth.assertThat
import kotlin.coroutines.EmptyCoroutineContext
import kotlinx.coroutines.test.runTest
import kotlinx.coroutines.test.runTest
import org.junit.Before
import org.junit.Test
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runner.RunWith
import org.mockito.Mock
import org.mockito.kotlin.eq
import org.mockito.MockitoAnnotations
import org.mockito.kotlin.mock
import org.mockito.kotlin.verify
import org.mockito.kotlin.verify
import org.mockito.kotlin.whenever


@SmallTest
@SmallTest
@RunWith(AndroidJUnit4::class)
@RunWith(AndroidJUnit4::class)
@EnableFlags(android.app.Flags.FLAG_MODES_UI)
@EnableFlags(android.app.Flags.FLAG_MODES_UI)
class ModesTileUserActionInteractorTest : SysuiTestCase() {
class ModesTileUserActionInteractorTest : SysuiTestCase() {
    private val inputHandler = FakeQSTileIntentUserInputHandler()
    private val kosmos = testKosmos()
    private val inputHandler = kosmos.qsTileIntentUserInputHandler
    private val mockDialogDelegate = kosmos.mockModesDialogDelegate


    @Mock private lateinit var dialogTransitionAnimator: DialogTransitionAnimator
    private val underTest =
    @Mock private lateinit var dialogDelegate: ModesDialogDelegate
        ModesTileUserActionInteractor(
    @Mock private lateinit var mockDialog: SystemUIDialog
            inputHandler,
            mockDialogDelegate,
        )


    private lateinit var underTest: ModesTileUserActionInteractor
    @Test
    fun handleClick_active() = runTest {
        val expandable = mock<Expandable>()
        underTest.handleInput(
            QSTileInputTestKtx.click(data = ModesTileModel(true), expandable = expandable))


    @Before
        verify(mockDialogDelegate).showDialog(eq(expandable))
    fun setup() {
    }
        MockitoAnnotations.initMocks(this)


        whenever(dialogDelegate.createDialog()).thenReturn(mockDialog)
    @Test
    fun handleClick_inactive() = runTest {
        val expandable = mock<Expandable>()
        underTest.handleInput(
            QSTileInputTestKtx.click(data = ModesTileModel(false), expandable = expandable))


        underTest =
        verify(mockDialogDelegate).showDialog(eq(expandable))
            ModesTileUserActionInteractor(
                EmptyCoroutineContext,
                inputHandler,
                dialogTransitionAnimator,
                dialogDelegate,
            )
    }
    }


    @Test
    @Test
    fun handleClick() = runTest {
    fun handleLongClick_active() = runTest {
        underTest.handleInput(QSTileInputTestKtx.click(ModesTileModel(false)))
        underTest.handleInput(QSTileInputTestKtx.longClick(ModesTileModel(true)))


        verify(mockDialog).show()
        QSTileIntentUserInputHandlerSubject.assertThat(inputHandler).handledOneIntentInput {
            assertThat(it.intent.action).isEqualTo(Settings.ACTION_ZEN_MODE_SETTINGS)
        }
    }
    }


    @Test
    @Test
    fun handleLongClick() = runTest {
    fun handleLongClick_inactive() = runTest {
        underTest.handleInput(QSTileInputTestKtx.longClick(ModesTileModel(false)))
        underTest.handleInput(QSTileInputTestKtx.longClick(ModesTileModel(false)))


        QSTileIntentUserInputHandlerSubject.assertThat(inputHandler).handledOneIntentInput {
        QSTileIntentUserInputHandlerSubject.assertThat(inputHandler).handledOneIntentInput {
            Truth.assertThat(it.intent.action).isEqualTo(Settings.ACTION_ZEN_MODE_SETTINGS)
            assertThat(it.intent.action).isEqualTo(Settings.ACTION_ZEN_MODE_SETTINGS)
        }
        }
    }
    }
}
}
+67 −5
Original line number Original line Diff line number Diff line
@@ -18,6 +18,8 @@


package com.android.systemui.statusbar.policy.ui.dialog.viewmodel
package com.android.systemui.statusbar.policy.ui.dialog.viewmodel


import android.content.Intent
import android.provider.Settings
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import androidx.test.filters.SmallTest
import com.android.settingslib.notification.modes.TestModeBuilder
import com.android.settingslib.notification.modes.TestModeBuilder
@@ -27,6 +29,7 @@ import com.android.systemui.kosmos.testDispatcher
import com.android.systemui.kosmos.testScope
import com.android.systemui.kosmos.testScope
import com.android.systemui.statusbar.policy.data.repository.fakeZenModeRepository
import com.android.systemui.statusbar.policy.data.repository.fakeZenModeRepository
import com.android.systemui.statusbar.policy.domain.interactor.zenModeInteractor
import com.android.systemui.statusbar.policy.domain.interactor.zenModeInteractor
import com.android.systemui.statusbar.policy.ui.dialog.mockModesDialogDelegate
import com.android.systemui.testKosmos
import com.android.systemui.testKosmos
import com.google.common.truth.Truth.assertThat
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -34,16 +37,21 @@ import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runTest
import kotlinx.coroutines.test.runTest
import org.junit.Test
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runner.RunWith
import org.mockito.Mockito.clearInvocations
import org.mockito.kotlin.argumentCaptor
import org.mockito.kotlin.verify


@SmallTest
@SmallTest
@RunWith(AndroidJUnit4::class)
@RunWith(AndroidJUnit4::class)
class ModesDialogViewModelTest : SysuiTestCase() {
class ModesDialogViewModelTest : SysuiTestCase() {
    private val kosmos = testKosmos()
    private val kosmos = testKosmos()
    private val testScope = kosmos.testScope
    private val testScope = kosmos.testScope
    val repository = kosmos.fakeZenModeRepository
    private val repository = kosmos.fakeZenModeRepository
    val interactor = kosmos.zenModeInteractor
    private val interactor = kosmos.zenModeInteractor
    private val mockDialogDelegate = kosmos.mockModesDialogDelegate


    val underTest = ModesDialogViewModel(context, interactor, kosmos.testDispatcher)
    private val underTest =
        ModesDialogViewModel(context, interactor, kosmos.testDispatcher, mockDialogDelegate)


    @Test
    @Test
    fun tiles_filtersOutDisabledModes() =
    fun tiles_filtersOutDisabledModes() =
@@ -64,7 +72,8 @@ class ModesDialogViewModelTest : SysuiTestCase() {
                        .setEnabled(false)
                        .setEnabled(false)
                        .setManualInvocationAllowed(true)
                        .setManualInvocationAllowed(true)
                        .build(),
                        .build(),
                ))
                )
            )
            runCurrent()
            runCurrent()


            assertThat(tiles?.size).isEqualTo(2)
            assertThat(tiles?.size).isEqualTo(2)
@@ -108,7 +117,8 @@ class ModesDialogViewModelTest : SysuiTestCase() {
                        .setActive(false)
                        .setActive(false)
                        .setManualInvocationAllowed(false)
                        .setManualInvocationAllowed(false)
                        .build(),
                        .build(),
                ))
                )
            )
            runCurrent()
            runCurrent()


            assertThat(tiles?.size).isEqualTo(3)
            assertThat(tiles?.size).isEqualTo(3)
@@ -161,4 +171,56 @@ class ModesDialogViewModelTest : SysuiTestCase() {


            assertThat(tiles?.first()?.enabled).isFalse()
            assertThat(tiles?.first()?.enabled).isFalse()
        }
        }

    @Test
    fun onLongClick_launchesIntent() =
        testScope.runTest {
            val tiles by collectLastValue(underTest.tiles)
            val intentCaptor = argumentCaptor<Intent>()

            val modeId = "id"
            repository.addModes(
                listOf(
                    TestModeBuilder()
                        .setId(modeId)
                        .setId("A")
                        .setActive(true)
                        .setManualInvocationAllowed(true)
                        .build(),
                    TestModeBuilder()
                        .setId(modeId)
                        .setId("B")
                        .setActive(false)
                        .setManualInvocationAllowed(true)
                        .build(),
                )
            )
            runCurrent()

            assertThat(tiles?.size).isEqualTo(2)

            // Trigger onLongClick for A
            tiles?.first()?.onLongClick?.let { it() }
            runCurrent()

            // Check that it launched the correct intent
            verify(mockDialogDelegate).launchFromDialog(intentCaptor.capture())
            var intent = intentCaptor.lastValue
            assertThat(intent.action).isEqualTo(Settings.ACTION_AUTOMATIC_ZEN_RULE_SETTINGS)
            assertThat(intent.extras?.getString(Settings.EXTRA_AUTOMATIC_ZEN_RULE_ID))
                .isEqualTo("A")

            clearInvocations(mockDialogDelegate)

            // Trigger onLongClick for B
            tiles?.last()?.onLongClick?.let { it() }
            runCurrent()

            // Check that it launched the correct intent
            verify(mockDialogDelegate).launchFromDialog(intentCaptor.capture())
            intent = intentCaptor.lastValue
            assertThat(intent.action).isEqualTo(Settings.ACTION_AUTOMATIC_ZEN_RULE_SETTINGS)
            assertThat(intent.extras?.getString(Settings.EXTRA_AUTOMATIC_ZEN_RULE_ID))
                .isEqualTo("B")
        }
}
}
+7 −28
Original line number Original line Diff line number Diff line
@@ -16,14 +16,10 @@


package com.android.systemui.qs.tiles.impl.modes.domain.interactor
package com.android.systemui.qs.tiles.impl.modes.domain.interactor


//noinspection CleanArchitectureDependencyViolation: dialog needs to be opened on click
import android.content.Intent
import android.content.Intent
import android.provider.Settings
import android.provider.Settings
import com.android.internal.jank.InteractionJankMonitor
import com.android.systemui.animation.DialogCuj
import com.android.systemui.animation.DialogTransitionAnimator
import com.android.systemui.animation.Expandable
import com.android.systemui.animation.Expandable
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.qs.tiles.base.actions.QSTileIntentUserInputHandler
import com.android.systemui.qs.tiles.base.actions.QSTileIntentUserInputHandler
import com.android.systemui.qs.tiles.base.interactor.QSTileInput
import com.android.systemui.qs.tiles.base.interactor.QSTileInput
import com.android.systemui.qs.tiles.base.interactor.QSTileUserActionInteractor
import com.android.systemui.qs.tiles.base.interactor.QSTileUserActionInteractor
@@ -31,15 +27,13 @@ import com.android.systemui.qs.tiles.impl.modes.domain.model.ModesTileModel
import com.android.systemui.qs.tiles.viewmodel.QSTileUserAction
import com.android.systemui.qs.tiles.viewmodel.QSTileUserAction
import com.android.systemui.statusbar.policy.ui.dialog.ModesDialogDelegate
import com.android.systemui.statusbar.policy.ui.dialog.ModesDialogDelegate
import javax.inject.Inject
import javax.inject.Inject
import kotlin.coroutines.CoroutineContext
import kotlinx.coroutines.withContext


@SysUISingleton
class ModesTileUserActionInteractor
class ModesTileUserActionInteractor
@Inject
@Inject
constructor(
constructor(
    @Main private val coroutineContext: CoroutineContext,
    private val qsTileIntentUserInputHandler: QSTileIntentUserInputHandler,
    private val qsTileIntentUserActionHandler: QSTileIntentUserInputHandler,
    // TODO(b/353896370): The domain layer should not have to depend on the UI layer.
    private val dialogTransitionAnimator: DialogTransitionAnimator,
    private val dialogDelegate: ModesDialogDelegate,
    private val dialogDelegate: ModesDialogDelegate,
) : QSTileUserActionInteractor<ModesTileModel> {
) : QSTileUserActionInteractor<ModesTileModel> {
    val longClickIntent = Intent(Settings.ACTION_ZEN_MODE_SETTINGS)
    val longClickIntent = Intent(Settings.ACTION_ZEN_MODE_SETTINGS)
@@ -51,29 +45,14 @@ constructor(
                    handleClick(action.expandable)
                    handleClick(action.expandable)
                }
                }
                is QSTileUserAction.LongClick -> {
                is QSTileUserAction.LongClick -> {
                    qsTileIntentUserActionHandler.handle(action.expandable, longClickIntent)
                    qsTileIntentUserInputHandler.handle(action.expandable, longClickIntent)
                }
                }
            }
            }
        }
        }
    }
    }


    suspend fun handleClick(expandable: Expandable?) {
    suspend fun handleClick(expandable: Expandable?) {
        // Show a dialog with the list of modes to configure. Dialogs shown by the
        // Show a dialog with the list of modes to configure.
        // DialogTransitionAnimator must be created and shown on the main thread, so we post it to
        dialogDelegate.showDialog(expandable)
        // the UI handler.
        withContext(coroutineContext) {
            val dialog = dialogDelegate.createDialog()

            expandable
                ?.dialogTransitionController(
                    DialogCuj(InteractionJankMonitor.CUJ_SHADE_DIALOG_OPEN, INTERACTION_JANK_TAG)
                )
                ?.let { controller -> dialogTransitionAnimator.show(dialog, controller) }
                ?: dialog.show()
        }
    }

    companion object {
        private const val INTERACTION_JANK_TAG = "configure_priority_modes"
    }
    }
}
}
+120 −32
Original line number Original line Diff line number Diff line
@@ -18,45 +18,97 @@ package com.android.systemui.statusbar.policy.ui.dialog


import android.content.Intent
import android.content.Intent
import android.provider.Settings
import android.provider.Settings
import android.util.Log
import androidx.compose.material3.Text
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.res.stringResource
import androidx.lifecycle.DefaultLifecycleObserver
import androidx.lifecycle.LifecycleOwner
import com.android.compose.PlatformButton
import com.android.compose.PlatformButton
import com.android.compose.PlatformOutlinedButton
import com.android.compose.PlatformOutlinedButton
import com.android.internal.annotations.VisibleForTesting
import com.android.internal.jank.InteractionJankMonitor
import com.android.systemui.animation.DialogCuj
import com.android.systemui.animation.DialogTransitionAnimator
import com.android.systemui.animation.DialogTransitionAnimator
import com.android.systemui.animation.Expandable
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.dialog.ui.composable.AlertDialogContent
import com.android.systemui.dialog.ui.composable.AlertDialogContent
import com.android.systemui.plugins.ActivityStarter
import com.android.systemui.plugins.ActivityStarter
import com.android.systemui.res.R
import com.android.systemui.res.R
import com.android.systemui.statusbar.phone.ComponentSystemUIDialog
import com.android.systemui.statusbar.phone.SystemUIDialog
import com.android.systemui.statusbar.phone.SystemUIDialog
import com.android.systemui.statusbar.phone.SystemUIDialogFactory
import com.android.systemui.statusbar.phone.SystemUIDialogFactory
import com.android.systemui.statusbar.phone.create
import com.android.systemui.statusbar.phone.create
import com.android.systemui.statusbar.policy.ui.dialog.composable.ModeTileGrid
import com.android.systemui.statusbar.policy.ui.dialog.composable.ModeTileGrid
import com.android.systemui.statusbar.policy.ui.dialog.viewmodel.ModesDialogViewModel
import com.android.systemui.statusbar.policy.ui.dialog.viewmodel.ModesDialogViewModel
import com.android.systemui.util.Assert
import javax.inject.Inject
import javax.inject.Inject
import javax.inject.Provider
import kotlin.coroutines.CoroutineContext
import kotlinx.coroutines.withContext


@SysUISingleton
class ModesDialogDelegate
class ModesDialogDelegate
@Inject
@Inject
constructor(
constructor(
    private val sysuiDialogFactory: SystemUIDialogFactory,
    private val sysuiDialogFactory: SystemUIDialogFactory,
    private val dialogTransitionAnimator: DialogTransitionAnimator,
    private val dialogTransitionAnimator: DialogTransitionAnimator,
    private val activityStarter: ActivityStarter,
    private val activityStarter: ActivityStarter,
    private val viewModel: ModesDialogViewModel,
    // Using a provider to avoid a circular dependency.
    private val viewModel: Provider<ModesDialogViewModel>,
    @Main private val mainCoroutineContext: CoroutineContext,
) : SystemUIDialog.Delegate {
) : SystemUIDialog.Delegate {
    // NOTE: This should only be accessed/written from the main thread.
    @VisibleForTesting var currentDialog: ComponentSystemUIDialog? = null

    override fun createDialog(): SystemUIDialog {
    override fun createDialog(): SystemUIDialog {
        return sysuiDialogFactory.create { dialog ->
        Assert.isMainThread()
        if (currentDialog != null) {
            Log.w(TAG, "Dialog is already open, dismissing it and creating a new one.")
            currentDialog?.dismiss()
        }

        currentDialog = sysuiDialogFactory.create() { ModesDialogContent(it) }
        currentDialog
            ?.lifecycle
            ?.addObserver(
                object : DefaultLifecycleObserver {
                    override fun onStop(owner: LifecycleOwner) {
                        Assert.isMainThread()
                        currentDialog = null
                    }
                }
            )

        return currentDialog!!
    }

    @Composable
    private fun ModesDialogContent(dialog: SystemUIDialog) {
        AlertDialogContent(
        AlertDialogContent(
            title = { Text(stringResource(R.string.zen_modes_dialog_title)) },
            title = { Text(stringResource(R.string.zen_modes_dialog_title)) },
                content = { ModeTileGrid(viewModel) },
            content = { ModeTileGrid(viewModel.get()) },
            neutralButton = {
            neutralButton = {
                    PlatformOutlinedButton(
                PlatformOutlinedButton(onClick = { openSettings(dialog) }) {
                        onClick = {
                    Text(stringResource(R.string.zen_modes_dialog_settings))
                            val animationController =
                }
                                dialogTransitionAnimator.createActivityTransitionController(
            },
                                    dialog.getButton(SystemUIDialog.BUTTON_NEUTRAL)
            positiveButton = {
                PlatformButton(onClick = { dialog.dismiss() }) {
                    Text(stringResource(R.string.zen_modes_dialog_done))
                }
            },
        )
        )
    }

    private fun openSettings(dialog: SystemUIDialog) {
        val animationController =
            dialogTransitionAnimator.createActivityTransitionController(dialog)
        if (animationController == null) {
        if (animationController == null) {
                                // The controller will take care of dismissing for us after the
            // The controller will take care of dismissing for us after
                                // animation, but let's make sure we dismiss the dialog if we don't
            // the animation, but let's make sure we dismiss the dialog
                                // animate it.
            // if we don't animate it.
            dialog.dismiss()
            dialog.dismiss()
        }
        }
        activityStarter.startActivity(
        activityStarter.startActivity(
@@ -65,20 +117,56 @@ constructor(
            animationController
            animationController
        )
        )
    }
    }
                    ) {

                        Text(stringResource(R.string.zen_modes_dialog_settings))
    suspend fun showDialog(expandable: Expandable? = null): SystemUIDialog {
        // Dialogs shown by the DialogTransitionAnimator must be created and shown on the main
        // thread, so we post it to the UI handler.
        withContext(mainCoroutineContext) {
            // Create the dialog if necessary
            if (currentDialog == null) {
                createDialog()
            }
            }
                },

                positiveButton = {
            expandable
                    PlatformButton(onClick = { dialog.dismiss() }) {
                ?.dialogTransitionController(
                        Text(stringResource(R.string.zen_modes_dialog_done))
                    DialogCuj(InteractionJankMonitor.CUJ_SHADE_DIALOG_OPEN, INTERACTION_JANK_TAG)
                )
                ?.let { controller -> dialogTransitionAnimator.show(currentDialog!!, controller) }
                ?: currentDialog!!.show()
        }
        }
                },

        return currentDialog!!
    }

    /**
     * Launches the [intent] by animating from the dialog. If the dialog is not showing, just
     * launches it normally without animating.
     */
    fun launchFromDialog(intent: Intent) {
        Assert.isMainThread()
        if (currentDialog == null) {
            Log.w(
                TAG,
                "Cannot launch from dialog, the dialog is not present. " +
                    "Will launch activity without animating."
            )
            )
        }
        }

        val animationController =
            currentDialog?.let { dialogTransitionAnimator.createActivityTransitionController(it) }
        if (animationController == null) {
            currentDialog?.dismiss()
        }
        activityStarter.startActivity(
            intent,
            true, /* dismissShade */
            animationController,
        )
    }
    }


    companion object {
    companion object {
        private const val TAG = "ModesDialogDelegate"
        private val ZEN_MODE_SETTINGS_INTENT = Intent(Settings.ACTION_ZEN_MODE_SETTINGS)
        private val ZEN_MODE_SETTINGS_INTENT = Intent(Settings.ACTION_ZEN_MODE_SETTINGS)
        private const val INTERACTION_JANK_TAG = "configure_priority_modes"
    }
    }
}
}
Loading