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

Commit e4f5f6c4 authored by Matías Hernández's avatar Matías Hernández
Browse files

Update ZenModeInteractor.activeModes to include all relevant data

* Both remove unimportant details (like all fields of ZenMode except name and icon) and include the icon of the main active mode, so that consumers have all they need.
* Use ActiveZenModes from tile and Smartspace.
* Update status bar to also use the preloaded icon from ActiveZenModes (with the caveat that theming and size still need to be adjusted).

Bug: 360399800
Bug: 361611824
Test: atest ModesTileDataInteractorTest ModesTileMapperTest ModesTileUserActionInteractorTest ZenModeInteractorTest & atest KeyguardZenAlarmViewControllerTest PhoneStatusBarPolicyTest
Flag: android.app.modes_ui
Change-Id: Ie1e535717804a39edb32a79ab008ea40532bfd57
parent a3c982cc
Loading
Loading
Loading
Loading
+60 −21
Original line number Diff line number Diff line
@@ -24,9 +24,11 @@ import android.platform.test.annotations.DisableFlags
import android.platform.test.annotations.EnableFlags
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.internal.R
import com.android.settingslib.notification.modes.ZenIconLoader
import com.android.systemui.SysuiTestCase
import com.android.systemui.common.shared.model.asIcon
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.coroutines.collectValues
import com.android.systemui.kosmos.testDispatcher
import com.android.systemui.kosmos.testScope
@@ -60,9 +62,11 @@ class ModesTileDataInteractorTest : SysuiTestCase() {
    @Before
    fun setUp() {
        context.orCreateTestableResources.apply {
            addOverride(com.android.internal.R.drawable.ic_zen_mode_type_bedtime, BEDTIME_DRAWABLE)
            addOverride(com.android.internal.R.drawable.ic_zen_mode_type_driving, DRIVING_DRAWABLE)
            addOverride(MODES_DRAWABLE_ID, MODES_DRAWABLE)
            addOverride(R.drawable.ic_zen_mode_type_bedtime, BEDTIME_DRAWABLE)
            addOverride(R.drawable.ic_zen_mode_type_driving, DRIVING_DRAWABLE)
        }
        // TODO: b/360399800 - Remove; ZenIconLoader should always use direct executor for tests
        ZenIconLoader.setInstance(ZenIconLoader(MoreExecutors.newDirectExecutorService()))
    }

@@ -128,28 +132,34 @@ class ModesTileDataInteractorTest : SysuiTestCase() {

    @Test
    @EnableFlags(Flags.FLAG_MODES_UI, Flags.FLAG_MODES_UI_ICONS)
    fun changesIconWhenActiveModesChange() =
    fun tileData_iconsFlagEnabled_changesIconWhenActiveModesChange() =
        testScope.runTest {
            val dataList: List<ModesTileModel> by
                collectValues(
            val tileData by
                collectLastValue(
                    underTest.tileData(TEST_USER, flowOf(DataUpdateTrigger.InitialRequest))
                )

            // Tile starts with the generic Modes icon.
            runCurrent()
            assertThat(dataList.map { it.icon }).containsExactly(null).inOrder()
            assertThat(tileData?.icon).isEqualTo(MODES_ICON)
            assertThat(tileData?.iconResId).isEqualTo(MODES_DRAWABLE_ID)

            // Add an inactive mode: state hasn't changed, so this shouldn't cause another emission
            // Add an inactive mode -> Still modes icon
            zenModeRepository.addMode(id = "Mode", active = false)
            runCurrent()
            assertThat(dataList.map { it.icon }).containsExactly(null).inOrder()
            assertThat(tileData?.icon).isEqualTo(MODES_ICON)
            assertThat(tileData?.iconResId).isEqualTo(MODES_DRAWABLE_ID)

            // Add an active mode: icon should be the mode icon
            // Add an active mode: icon should be the mode icon. No iconResId, because we don't
            // really know that it's a system icon.
            zenModeRepository.addMode(
                id = "Bedtime",
                type = AutomaticZenRule.TYPE_BEDTIME,
                active = true
            )
            runCurrent()
            assertThat(dataList.map { it.icon }).containsExactly(null, BEDTIME_ICON).inOrder()
            assertThat(tileData?.icon).isEqualTo(BEDTIME_ICON)
            assertThat(tileData?.iconResId).isNull()

            // Add another, less-prioritized mode: icon should remain the first mode icon
            zenModeRepository.addMode(
@@ -158,29 +168,58 @@ class ModesTileDataInteractorTest : SysuiTestCase() {
                active = true
            )
            runCurrent()
            assertThat(dataList.map { it.icon })
                .containsExactly(null, BEDTIME_ICON, BEDTIME_ICON)
                .inOrder()
            assertThat(tileData?.icon).isEqualTo(BEDTIME_ICON)
            assertThat(tileData?.iconResId).isNull()

            // Deactivate more important mode: icon should be the less important, still active mode.
            // Deactivate more important mode: icon should be the less important, still active mode
            zenModeRepository.deactivateMode("Bedtime")
            runCurrent()
            assertThat(dataList.map { it.icon })
                .containsExactly(null, BEDTIME_ICON, BEDTIME_ICON, DRIVING_ICON)
                .inOrder()
            assertThat(tileData?.icon).isEqualTo(DRIVING_ICON)
            assertThat(tileData?.iconResId).isNull()

            // Deactivate remaining mode: no icon
            // Deactivate remaining mode: back to the default modes icon
            zenModeRepository.deactivateMode("Driving")
            runCurrent()
            assertThat(dataList.map { it.icon })
                .containsExactly(null, BEDTIME_ICON, BEDTIME_ICON, DRIVING_ICON, null)
                .inOrder()
            assertThat(tileData?.icon).isEqualTo(MODES_ICON)
            assertThat(tileData?.iconResId).isEqualTo(MODES_DRAWABLE_ID)
        }

    @Test
    @EnableFlags(Flags.FLAG_MODES_UI)
    @DisableFlags(Flags.FLAG_MODES_UI_ICONS)
    fun tileData_iconsFlagDisabled_hasPriorityModesIcon() =
        testScope.runTest {
            val tileData by
                collectLastValue(
                    underTest.tileData(TEST_USER, flowOf(DataUpdateTrigger.InitialRequest))
                )

            runCurrent()
            assertThat(tileData?.icon).isEqualTo(MODES_ICON)
            assertThat(tileData?.iconResId).isEqualTo(MODES_DRAWABLE_ID)

            // Activate a Mode -> Icon doesn't change.
            zenModeRepository.addMode(id = "Mode", active = true)
            runCurrent()
            assertThat(tileData?.icon).isEqualTo(MODES_ICON)
            assertThat(tileData?.iconResId).isEqualTo(MODES_DRAWABLE_ID)

            zenModeRepository.deactivateMode(id = "Mode")
            runCurrent()
            assertThat(tileData?.icon).isEqualTo(MODES_ICON)
            assertThat(tileData?.iconResId).isEqualTo(MODES_DRAWABLE_ID)
        }

    private companion object {
        val TEST_USER = UserHandle.of(1)!!

        val MODES_DRAWABLE_ID = com.android.systemui.res.R.drawable.qs_dnd_icon_off

        val MODES_DRAWABLE = TestStubDrawable("modes_icon")
        val BEDTIME_DRAWABLE = TestStubDrawable("bedtime")
        val DRIVING_DRAWABLE = TestStubDrawable("driving")

        val MODES_ICON = MODES_DRAWABLE.asIcon()
        val BEDTIME_ICON = BEDTIME_DRAWABLE.asIcon()
        val DRIVING_ICON = DRIVING_DRAWABLE.asIcon()
    }
+10 −10
Original line number Diff line number Diff line
@@ -16,12 +16,14 @@

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

import android.graphics.drawable.TestStubDrawable
import android.platform.test.annotations.EnableFlags
import android.provider.Settings
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.animation.Expandable
import com.android.systemui.common.shared.model.asIcon
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
@@ -54,10 +56,7 @@ class ModesTileUserActionInteractorTest : SysuiTestCase() {
    fun handleClick_active() = runTest {
        val expandable = mock<Expandable>()
        underTest.handleInput(
            QSTileInputTestKtx.click(
                data = ModesTileModel(true, listOf("DND")),
                expandable = expandable
            )
            QSTileInputTestKtx.click(data = modelOf(true, listOf("DND")), expandable = expandable)
        )

        verify(mockDialogDelegate).showDialog(eq(expandable))
@@ -67,10 +66,7 @@ class ModesTileUserActionInteractorTest : SysuiTestCase() {
    fun handleClick_inactive() = runTest {
        val expandable = mock<Expandable>()
        underTest.handleInput(
            QSTileInputTestKtx.click(
                data = ModesTileModel(false, emptyList()),
                expandable = expandable
            )
            QSTileInputTestKtx.click(data = modelOf(false, emptyList()), expandable = expandable)
        )

        verify(mockDialogDelegate).showDialog(eq(expandable))
@@ -78,7 +74,7 @@ class ModesTileUserActionInteractorTest : SysuiTestCase() {

    @Test
    fun handleLongClick_active() = runTest {
        underTest.handleInput(QSTileInputTestKtx.longClick(ModesTileModel(true, listOf("DND"))))
        underTest.handleInput(QSTileInputTestKtx.longClick(modelOf(true, listOf("DND"))))

        QSTileIntentUserInputHandlerSubject.assertThat(inputHandler).handledOneIntentInput {
            assertThat(it.intent.action).isEqualTo(Settings.ACTION_ZEN_MODE_SETTINGS)
@@ -87,10 +83,14 @@ class ModesTileUserActionInteractorTest : SysuiTestCase() {

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

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

    private fun modelOf(isActivated: Boolean, activeModeNames: List<String>): ModesTileModel {
        return ModesTileModel(isActivated, activeModeNames, TestStubDrawable("icon").asIcon(), 123)
    }
}
+52 −10
Original line number Diff line number Diff line
@@ -18,11 +18,12 @@ package com.android.systemui.qs.tiles.impl.modes.ui

import android.app.Flags
import android.graphics.drawable.TestStubDrawable
import android.platform.test.annotations.DisableFlags
import android.platform.test.annotations.EnableFlags
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.common.shared.model.Icon
import com.android.systemui.common.shared.model.asIcon
import com.android.systemui.qs.tiles.impl.modes.domain.model.ModesTileModel
import com.android.systemui.qs.tiles.viewmodel.QSTileConfigTestBuilder
import com.android.systemui.qs.tiles.viewmodel.QSTileState
@@ -58,47 +59,88 @@ class ModesTileMapperTest : SysuiTestCase() {

    @Test
    fun inactiveState() {
        val model = ModesTileModel(isActivated = false, activeModes = emptyList())
        val icon = TestStubDrawable("res123").asIcon()
        val model =
            ModesTileModel(
                isActivated = false,
                activeModes = emptyList(),
                icon = icon,
            )

        val state = underTest.map(config, model)

        assertThat(state.activationState).isEqualTo(QSTileState.ActivationState.INACTIVE)
        assertThat(state.iconRes).isEqualTo(R.drawable.qs_dnd_icon_off)
        assertThat(state.icon()).isEqualTo(icon)
        assertThat(state.secondaryLabel).isEqualTo("No active modes")
    }

    @Test
    fun activeState_oneMode() {
        val model = ModesTileModel(isActivated = true, activeModes = listOf("DND"))
        val icon = TestStubDrawable("res123").asIcon()
        val model =
            ModesTileModel(
                isActivated = true,
                activeModes = listOf("DND"),
                icon = icon,
            )

        val state = underTest.map(config, model)

        assertThat(state.activationState).isEqualTo(QSTileState.ActivationState.ACTIVE)
        assertThat(state.iconRes).isEqualTo(R.drawable.qs_dnd_icon_on)
        assertThat(state.icon()).isEqualTo(icon)
        assertThat(state.secondaryLabel).isEqualTo("DND is active")
    }

    @Test
    fun activeState_multipleModes() {
        val icon = TestStubDrawable("res123").asIcon()
        val model =
            ModesTileModel(isActivated = true, activeModes = listOf("Mode 1", "Mode 2", "Mode 3"))
            ModesTileModel(
                isActivated = true,
                activeModes = listOf("Mode 1", "Mode 2", "Mode 3"),
                icon = icon,
            )

        val state = underTest.map(config, model)

        assertThat(state.activationState).isEqualTo(QSTileState.ActivationState.ACTIVE)
        assertThat(state.iconRes).isEqualTo(R.drawable.qs_dnd_icon_on)
        assertThat(state.icon()).isEqualTo(icon)
        assertThat(state.secondaryLabel).isEqualTo("3 modes are active")
    }

    @Test
    @EnableFlags(Flags.FLAG_MODES_UI_ICONS)
    fun activeState_withIcon() {
        val icon = Icon.Resource(1234, contentDescription = null)
        val model = ModesTileModel(isActivated = true, activeModes = listOf("DND"), icon = icon)
    fun state_withEnabledFlag_noIconResId() {
        val icon = TestStubDrawable("res123").asIcon()
        val model =
            ModesTileModel(
                isActivated = false,
                activeModes = emptyList(),
                icon = icon,
                iconResId = 123 // Should not be populated, but is ignored even if present
            )

        val state = underTest.map(config, model)

        assertThat(state.icon()).isEqualTo(icon)
        assertThat(state.iconRes).isNull()
    }

    @Test
    @DisableFlags(Flags.FLAG_MODES_UI_ICONS)
    fun state_withDisabledFlag_includesIconResId() {
        val icon = TestStubDrawable("res123").asIcon()
        val model =
            ModesTileModel(
                isActivated = false,
                activeModes = emptyList(),
                icon = icon,
                iconResId = 123
            )

        val state = underTest.map(config, model)

        assertThat(state.icon()).isEqualTo(icon)
        assertThat(state.iconRes).isEqualTo(123)
    }
}
+14 −10
Original line number Diff line number Diff line
@@ -220,33 +220,37 @@ class ZenModeInteractorTest : SysuiTestCase() {
        }

    @Test
    fun mainActiveMode_returnsMainActiveMode() =
    fun activeModes_computesMainActiveMode() =
        testScope.runTest {
            val mainActiveMode by collectLastValue(underTest.mainActiveMode)
            val activeModes by collectLastValue(underTest.activeModes)

            zenModeRepository.addMode(id = "Bedtime", type = AutomaticZenRule.TYPE_BEDTIME)
            zenModeRepository.addMode(id = "Other", type = AutomaticZenRule.TYPE_OTHER)

            runCurrent()
            assertThat(mainActiveMode).isNull()
            assertThat(activeModes?.modeNames).hasSize(0)
            assertThat(activeModes?.mainMode).isNull()

            zenModeRepository.activateMode("Other")
            runCurrent()
            assertThat(mainActiveMode).isNotNull()
            assertThat(mainActiveMode!!.id).isEqualTo("Other")
            assertThat(activeModes?.modeNames).containsExactly("Mode Other")
            assertThat(activeModes?.mainMode?.name).isEqualTo("Mode Other")

            zenModeRepository.activateMode("Bedtime")
            runCurrent()
            assertThat(mainActiveMode).isNotNull()
            assertThat(mainActiveMode!!.id).isEqualTo("Bedtime")
            assertThat(activeModes?.modeNames)
                .containsExactly("Mode Bedtime", "Mode Other")
                .inOrder()
            assertThat(activeModes?.mainMode?.name).isEqualTo("Mode Bedtime")

            zenModeRepository.deactivateMode("Other")
            runCurrent()
            assertThat(mainActiveMode).isNotNull()
            assertThat(mainActiveMode!!.id).isEqualTo("Bedtime")
            assertThat(activeModes?.modeNames).containsExactly("Mode Bedtime")
            assertThat(activeModes?.mainMode?.name).isEqualTo("Mode Bedtime")

            zenModeRepository.deactivateMode("Bedtime")
            runCurrent()
            assertThat(mainActiveMode).isNull()
            assertThat(activeModes?.modeNames).hasSize(0)
            assertThat(activeModes?.mainMode).isNull()
        }
}
+1 −0
Original line number Diff line number Diff line
@@ -69,6 +69,7 @@ class ModesDialogViewModelTest : SysuiTestCase() {

    @Before
    fun setUp() {
        // TODO: b/360399800 - Remove; ZenIconLoader should always use direct executor for tests
        ZenIconLoader.setInstance(ZenIconLoader(MoreExecutors.newDirectExecutorService()))
    }

Loading