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

Commit ff5f6765 authored by Caitlin Shkuratov's avatar Caitlin Shkuratov
Browse files

[Notif] HeadsUpManagerImplTest: Move remaining tests, delete old file.

Bug: 378142453
Flag: EXEMPT refactor
Test: atest HeadsUpManagerImplTest
Change-Id: If1d42a14e9dad3633f1fde81916b12a206055543
parent bbfd5920
Loading
Loading
Loading
Loading
+0 −234
Original line number Diff line number Diff line
/*
 * Copyright (C) 2019 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.android.systemui.statusbar.notification.headsup

import android.os.Handler
import android.platform.test.annotations.DisableFlags
import android.platform.test.annotations.EnableFlags
import android.platform.test.flag.junit.FlagsParameterization
import android.testing.TestableLooper.RunWithLooper
import androidx.test.filters.SmallTest
import com.android.internal.logging.testing.UiEventLoggerFake
import com.android.systemui.SysuiTestCase
import com.android.systemui.dump.DumpManager
import com.android.systemui.kosmos.KosmosJavaAdapter
import com.android.systemui.log.logcatLogBuffer
import com.android.systemui.res.R
import com.android.systemui.shade.domain.interactor.ShadeInteractor
import com.android.systemui.statusbar.notification.collection.render.GroupMembershipManagerImpl
import com.android.systemui.statusbar.notification.headsup.HeadsUpManagerImpl.HeadsUpEntry
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
import com.android.systemui.statusbar.notification.shared.NotificationThrottleHun
import com.android.systemui.statusbar.policy.AccessibilityManagerWrapper
import com.android.systemui.util.concurrency.FakeExecutor
import com.android.systemui.util.concurrency.mockExecutorHandler
import com.android.systemui.util.kotlin.JavaAdapter
import com.android.systemui.util.settings.FakeGlobalSettings
import com.android.systemui.util.time.FakeSystemClock
import com.google.common.truth.Truth
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.flow.MutableStateFlow
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.ArgumentMatchers
import org.mockito.Mock
import org.mockito.Mockito
import org.mockito.invocation.InvocationOnMock
import org.mockito.junit.MockitoJUnit
import org.mockito.junit.MockitoRule
import platform.test.runner.parameterized.ParameterizedAndroidJunit4
import platform.test.runner.parameterized.Parameters

@SmallTest
@RunWithLooper
@RunWith(ParameterizedAndroidJunit4::class)
// TODO(b/378142453): Merge this with HeadsUpManagerImplTest.
open class HeadsUpManagerImplOldTest(flags: FlagsParameterization?) : SysuiTestCase() {
    protected var mKosmos: KosmosJavaAdapter = KosmosJavaAdapter(this)

    @JvmField @Rule var rule: MockitoRule = MockitoJUnit.rule()

    private val mUiEventLoggerFake = UiEventLoggerFake()

    private val mLogger: HeadsUpManagerLogger = Mockito.spy(HeadsUpManagerLogger(logcatLogBuffer()))

    @Mock private val mBgHandler: Handler? = null

    @Mock private val dumpManager: DumpManager? = null

    @Mock private val mShadeInteractor: ShadeInteractor? = null
    private var mAvalancheController: AvalancheController? = null

    @Mock private val mAccessibilityMgr: AccessibilityManagerWrapper? = null

    protected val globalSettings: FakeGlobalSettings = FakeGlobalSettings()
    protected val systemClock: FakeSystemClock = FakeSystemClock()
    protected val executor: FakeExecutor = FakeExecutor(systemClock)

    @Mock protected var mRow: ExpandableNotificationRow? = null

    private fun createHeadsUpManager(): HeadsUpManagerImpl {
        return HeadsUpManagerImpl(
            mContext,
            mLogger,
            mKosmos.statusBarStateController,
            mKosmos.keyguardBypassController,
            GroupMembershipManagerImpl(),
            mKosmos.visualStabilityProvider,
            mKosmos.configurationController,
            mockExecutorHandler(executor),
            globalSettings,
            systemClock,
            executor,
            mAccessibilityMgr,
            mUiEventLoggerFake,
            JavaAdapter(mKosmos.testScope),
            mShadeInteractor,
            mAvalancheController,
        )
    }

    open fun useAccessibilityTimeout(use: Boolean) {
        if (use) {
            Mockito.doReturn(TEST_A11Y_AUTO_DISMISS_TIME)
                .`when`(mAccessibilityMgr!!)
                .getRecommendedTimeoutMillis(ArgumentMatchers.anyInt(), ArgumentMatchers.anyInt())
        } else {
            Mockito.`when`(
                    mAccessibilityMgr!!.getRecommendedTimeoutMillis(
                        ArgumentMatchers.anyInt(),
                        ArgumentMatchers.anyInt(),
                    )
                )
                .then { i: InvocationOnMock -> i.getArgument(0) }
        }
    }

    init {
        mSetFlagsRule.setFlagsParameterization(flags!!)
    }

    @Throws(Exception::class)
    override fun SysuiSetup() {
        super.SysuiSetup()
        mContext.getOrCreateTestableResources().apply {
            this.addOverride(R.integer.ambient_notification_extension_time, TEST_EXTENSION_TIME)
            this.addOverride(R.integer.touch_acceptance_delay, TEST_TOUCH_ACCEPTANCE_TIME)
            this.addOverride(
                R.integer.heads_up_notification_minimum_time,
                TEST_MINIMUM_DISPLAY_TIME,
            )
            this.addOverride(
                R.integer.heads_up_notification_minimum_time_with_throttling,
                TEST_MINIMUM_DISPLAY_TIME,
            )
            this.addOverride(R.integer.heads_up_notification_decay, TEST_AUTO_DISMISS_TIME)
            this.addOverride(
                R.integer.sticky_heads_up_notification_time,
                TEST_STICKY_AUTO_DISMISS_TIME,
            )
        }

        mAvalancheController =
            AvalancheController(dumpManager!!, mUiEventLoggerFake, mLogger, mBgHandler!!)
        Mockito.`when`(mShadeInteractor!!.isAnyExpanded).thenReturn(MutableStateFlow(true))
        Mockito.`when`(mKosmos.keyguardBypassController.bypassEnabled).thenReturn(false)
    }

    @Test
    @EnableFlags(NotificationThrottleHun.FLAG_NAME)
    fun testPinEntry_logsPeek_throttleEnabled() {
        val hum = createHeadsUpManager()

        // Needs full screen intent in order to be pinned
        val entryToPin =
            hum.HeadsUpEntry(
                HeadsUpManagerTestUtil.createFullScreenIntentEntry(/* id= */ 0, mContext)
            )

        // Note: the standard way to show a notification would be calling showNotification rather
        // than onAlertEntryAdded. However, in practice showNotification in effect adds
        // the notification and then updates it; in order to not log twice, the entry needs
        // to have a functional ExpandableNotificationRow that can keep track of whether it's
        // pinned or not (via isRowPinned()). That feels like a lot to pull in to test this one bit.
        hum.onEntryAdded(entryToPin)

        assertThat(mUiEventLoggerFake.numLogs()).isEqualTo(2)
        assertThat(AvalancheController.ThrottleEvent.AVALANCHE_THROTTLING_HUN_SHOWN.getId())
            .isEqualTo(mUiEventLoggerFake.eventId(0))
        assertThat(HeadsUpManagerImpl.NotificationPeekEvent.NOTIFICATION_PEEK.id)
            .isEqualTo(mUiEventLoggerFake.eventId(1))
    }

    @Test
    @DisableFlags(NotificationThrottleHun.FLAG_NAME)
    fun testPinEntry_logsPeek_throttleDisabled() {
        val hum = createHeadsUpManager()

        // Needs full screen intent in order to be pinned
        val entryToPin =
            hum.HeadsUpEntry(
                HeadsUpManagerTestUtil.createFullScreenIntentEntry(/* id= */ 0, mContext)
            )

        // Note: the standard way to show a notification would be calling showNotification rather
        // than onAlertEntryAdded. However, in practice showNotification in effect adds
        // the notification and then updates it; in order to not log twice, the entry needs
        // to have a functional ExpandableNotificationRow that can keep track of whether it's
        // pinned or not (via isRowPinned()). That feels like a lot to pull in to test this one bit.
        hum.onEntryAdded(entryToPin)

        assertThat(mUiEventLoggerFake.numLogs()).isEqualTo(1)
        assertThat(HeadsUpManagerImpl.NotificationPeekEvent.NOTIFICATION_PEEK.id)
            .isEqualTo(mUiEventLoggerFake.eventId(0))
    }

    @Test
    fun testSetUserActionMayIndirectlyRemove() {
        val hum = createHeadsUpManager()
        val notifEntry = HeadsUpManagerTestUtil.createEntry(/* id= */ 0, mContext)

        hum.showNotification(notifEntry)

        assertThat(hum.canRemoveImmediately(notifEntry.key)).isFalse()

        hum.setUserActionMayIndirectlyRemove(notifEntry)

        assertThat(hum.canRemoveImmediately(notifEntry.key)).isTrue()
    }

    companion object {
        const val TEST_TOUCH_ACCEPTANCE_TIME: Int = 200
        const val TEST_A11Y_AUTO_DISMISS_TIME: Int = 1000
        const val TEST_EXTENSION_TIME = 500

        const val TEST_MINIMUM_DISPLAY_TIME: Int = 400
        const val TEST_AUTO_DISMISS_TIME: Int = 600
        const val TEST_STICKY_AUTO_DISMISS_TIME: Int = 800

        init {
            Truth.assertThat(TEST_MINIMUM_DISPLAY_TIME).isLessThan(TEST_AUTO_DISMISS_TIME)
            Truth.assertThat(TEST_AUTO_DISMISS_TIME).isLessThan(TEST_STICKY_AUTO_DISMISS_TIME)
            Truth.assertThat(TEST_STICKY_AUTO_DISMISS_TIME).isLessThan(TEST_A11Y_AUTO_DISMISS_TIME)
        }

        @get:Parameters(name = "{0}")
        @JvmStatic
        val flags: List<FlagsParameterization>
            get() = FlagsParameterization.allCombinationsOf(NotificationThrottleHun.FLAG_NAME)
    }
}
+95 −10
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@ import android.app.Notification
import android.app.PendingIntent
import android.app.Person
import android.os.Handler
import android.platform.test.annotations.DisableFlags
import android.platform.test.annotations.EnableFlags
import android.platform.test.flag.junit.FlagsParameterization
import android.testing.TestableLooper
@@ -27,7 +28,10 @@ import android.view.accessibility.accessibilityManager
import android.view.accessibility.accessibilityManagerWrapper
import androidx.test.filters.SmallTest
import com.android.internal.logging.uiEventLoggerFake
import com.android.systemui.SysuiTestCase
import com.android.systemui.concurrency.fakeExecutor
import com.android.systemui.dump.dumpManager
import com.android.systemui.flags.BrokenWithSceneContainer
import com.android.systemui.flags.andSceneContainer
import com.android.systemui.kosmos.runTest
import com.android.systemui.kosmos.testScope
@@ -50,6 +54,8 @@ import com.android.systemui.statusbar.sysuiStatusBarStateController
import com.android.systemui.testKosmos
import com.android.systemui.util.concurrency.mockExecutorHandler
import com.android.systemui.util.kotlin.JavaAdapter
import com.android.systemui.util.settings.fakeGlobalSettings
import com.android.systemui.util.time.fakeSystemClock
import com.google.common.truth.Truth.assertThat
import org.junit.Before
import org.junit.Ignore
@@ -68,17 +74,23 @@ import platform.test.runner.parameterized.Parameters
@SmallTest
@RunWith(ParameterizedAndroidJunit4::class)
@RunWithLooper
class HeadsUpManagerImplTest(flags: FlagsParameterization) : HeadsUpManagerImplOldTest(flags) {

    private val headsUpManagerLogger = mock<HeadsUpManagerLogger>()
class HeadsUpManagerImplTest(flags: FlagsParameterization) : SysuiTestCase() {
    init {
        mSetFlagsRule.setFlagsParameterization(flags)
    }

    private val kosmos = testKosmos().useUnconfinedTestDispatcher()
    private val testScope = kosmos.testScope

    private val groupManager = mock<GroupMembershipManager>()
    private val bgHandler = mock<Handler>()
    private val headsUpManagerLogger = mock<HeadsUpManagerLogger>()

    val statusBarStateController = kosmos.sysuiStatusBarStateController
    private val globalSettings = kosmos.fakeGlobalSettings
    private val systemClock = kosmos.fakeSystemClock
    private val executor = kosmos.fakeExecutor
    private val uiEventLoggerFake = kosmos.uiEventLoggerFake
    private val javaAdapter: JavaAdapter = JavaAdapter(testScope.backgroundScope)

    private lateinit var testHelper: NotificationTestHelper
@@ -113,7 +125,7 @@ class HeadsUpManagerImplTest(flags: FlagsParameterization) : HeadsUpManagerImplO
        avalancheController =
            AvalancheController(
                kosmos.dumpManager,
                kosmos.uiEventLoggerFake,
                uiEventLoggerFake,
                headsUpManagerLogger,
                bgHandler,
            )
@@ -131,7 +143,7 @@ class HeadsUpManagerImplTest(flags: FlagsParameterization) : HeadsUpManagerImplO
                systemClock,
                executor,
                kosmos.accessibilityManagerWrapper,
                kosmos.uiEventLoggerFake,
                uiEventLoggerFake,
                javaAdapter,
                kosmos.shadeInteractor,
                avalancheController,
@@ -392,7 +404,7 @@ class HeadsUpManagerImplTest(flags: FlagsParameterization) : HeadsUpManagerImplO
    fun testCanRemoveImmediately_notTopEntry() {
        val earlierEntry = HeadsUpManagerTestUtil.createEntry(/* id= */ 0, mContext)
        val laterEntry = HeadsUpManagerTestUtil.createEntry(/* id= */ 1, mContext)
        laterEntry.row = mRow
        laterEntry.row = mock<ExpandableNotificationRow>()
        underTest.showNotification(earlierEntry)
        underTest.showNotification(laterEntry)

@@ -618,11 +630,13 @@ class HeadsUpManagerImplTest(flags: FlagsParameterization) : HeadsUpManagerImplO
        }

    @Test
    @BrokenWithSceneContainer(381869885) // because `ShadeTestUtil.setShadeExpansion(0f)`
    // still causes `ShadeInteractor.isAnyExpanded` to emit `true`, when it should emit `false`.
    fun shouldHeadsUpBecomePinned_shadeNotExpanded_true() =
        kosmos.runTest {
            // GIVEN
            shadeTestUtil.setShadeExpansion(0f)
            // TODO(b/381869885): Determine why we need both of these ShadeTestUtil calls.
            // TODO(b/381869885): We should be able to use `ShadeTestUtil.setShadeExpansion(0f)`
            // instead.
            shadeTestUtil.setLegacyExpandedOrAwaitingInputTransfer(false)

            val entry = HeadsUpManagerTestUtil.createEntry(/* id= */ 0, mContext)
@@ -769,6 +783,63 @@ class HeadsUpManagerImplTest(flags: FlagsParameterization) : HeadsUpManagerImplO
        assertThat(activeRemoteInput.compareTo(incomingCall)).isGreaterThan(0)
    }

    @Test
    @EnableFlags(NotificationThrottleHun.FLAG_NAME)
    fun testPinEntry_logsPeek_throttleEnabled() {
        // Needs full screen intent in order to be pinned
        val entryToPin =
            underTest.HeadsUpEntry(
                HeadsUpManagerTestUtil.createFullScreenIntentEntry(/* id= */ 0, mContext)
            )

        // Note: the standard way to show a notification would be calling showNotification rather
        // than onAlertEntryAdded. However, in practice showNotification in effect adds
        // the notification and then updates it; in order to not log twice, the entry needs
        // to have a functional ExpandableNotificationRow that can keep track of whether it's
        // pinned or not (via isRowPinned()). That feels like a lot to pull in to test this one bit.
        underTest.onEntryAdded(entryToPin)

        assertThat(uiEventLoggerFake.numLogs()).isEqualTo(2)
        assertThat(AvalancheController.ThrottleEvent.AVALANCHE_THROTTLING_HUN_SHOWN.getId())
            .isEqualTo(uiEventLoggerFake.eventId(0))
        assertThat(HeadsUpManagerImpl.NotificationPeekEvent.NOTIFICATION_PEEK.id)
            .isEqualTo(uiEventLoggerFake.eventId(1))
    }

    @Test
    @DisableFlags(NotificationThrottleHun.FLAG_NAME)
    fun testPinEntry_logsPeek_throttleDisabled() {
        // Needs full screen intent in order to be pinned
        val entryToPin =
            underTest.HeadsUpEntry(
                HeadsUpManagerTestUtil.createFullScreenIntentEntry(/* id= */ 0, mContext)
            )

        // Note: the standard way to show a notification would be calling showNotification rather
        // than onAlertEntryAdded. However, in practice showNotification in effect adds
        // the notification and then updates it; in order to not log twice, the entry needs
        // to have a functional ExpandableNotificationRow that can keep track of whether it's
        // pinned or not (via isRowPinned()). That feels like a lot to pull in to test this one bit.
        underTest.onEntryAdded(entryToPin)

        assertThat(uiEventLoggerFake.numLogs()).isEqualTo(1)
        assertThat(HeadsUpManagerImpl.NotificationPeekEvent.NOTIFICATION_PEEK.id)
            .isEqualTo(uiEventLoggerFake.eventId(0))
    }

    @Test
    fun testSetUserActionMayIndirectlyRemove() {
        val notifEntry = HeadsUpManagerTestUtil.createEntry(/* id= */ 0, mContext)

        underTest.showNotification(notifEntry)

        assertThat(underTest.canRemoveImmediately(notifEntry.key)).isFalse()

        underTest.setUserActionMayIndirectlyRemove(notifEntry)

        assertThat(underTest.canRemoveImmediately(notifEntry.key)).isTrue()
    }

    private fun createStickyEntry(id: Int): NotificationEntry {
        val notif =
            Notification.Builder(mContext, "")
@@ -787,8 +858,7 @@ class HeadsUpManagerImplTest(flags: FlagsParameterization) : HeadsUpManagerImplO
        return HeadsUpManagerTestUtil.createEntry(id, notif)
    }

    override fun useAccessibilityTimeout(use: Boolean) {
        super.useAccessibilityTimeout(use)
    private fun useAccessibilityTimeout(use: Boolean) {
        if (use) {
            whenever(kosmos.accessibilityManager.getRecommendedTimeoutMillis(any(), any()))
                .thenReturn(TEST_A11Y_AUTO_DISMISS_TIME)
@@ -800,7 +870,22 @@ class HeadsUpManagerImplTest(flags: FlagsParameterization) : HeadsUpManagerImplO
    }

    companion object {
        const val TEST_TOUCH_ACCEPTANCE_TIME = 200
        const val TEST_A11Y_AUTO_DISMISS_TIME = 1000
        const val TEST_EXTENSION_TIME = 500

        const val TEST_MINIMUM_DISPLAY_TIME = 400
        const val TEST_AUTO_DISMISS_TIME = 600
        const val TEST_STICKY_AUTO_DISMISS_TIME = 800

        init {
            assertThat(TEST_MINIMUM_DISPLAY_TIME).isLessThan(TEST_AUTO_DISMISS_TIME)
            assertThat(TEST_AUTO_DISMISS_TIME).isLessThan(TEST_STICKY_AUTO_DISMISS_TIME)
            assertThat(TEST_STICKY_AUTO_DISMISS_TIME).isLessThan(TEST_A11Y_AUTO_DISMISS_TIME)
        }

        @get:Parameters(name = "{0}")
        @JvmStatic
        val flags: List<FlagsParameterization>
            get() = buildList {
                addAll(