1 package com.android.systemui.statusbar
2 
3 import android.testing.TestableLooper
4 import androidx.test.ext.junit.runners.AndroidJUnit4
5 import androidx.test.filters.SmallTest
6 import kotlinx.coroutines.ExperimentalCoroutinesApi
7 import com.android.systemui.SysuiTestCase
8 import com.android.systemui.dump.DumpManager
9 import com.android.systemui.plugins.qs.QS
10 import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController
11 import com.android.systemui.statusbar.phone.ScrimController
12 import com.android.systemui.statusbar.policy.FakeConfigurationController
13 import com.android.systemui.util.mockito.mock
14 import org.junit.Before
15 import org.junit.Test
16 import org.junit.runner.RunWith
17 import org.mockito.Mock
18 import org.mockito.Mockito.atLeast
19 import org.mockito.Mockito.intThat
20 import org.mockito.Mockito.reset
21 import org.mockito.Mockito.verify
22 import org.mockito.Mockito.verifyNoMoreInteractions
23 import org.mockito.Mockito.`when` as whenever
24 import org.mockito.MockitoAnnotations
25 
26 @RunWith(AndroidJUnit4::class)
27 @SmallTest
28 @TestableLooper.RunWithLooper
29 class SplitShadeLockScreenOverScrollerTest : SysuiTestCase() {
30 
31     private val configurationController = FakeConfigurationController()
32 
33     @OptIn(ExperimentalCoroutinesApi::class)
34     @Mock private lateinit var scrimController: ScrimController
35     @Mock private lateinit var statusBarStateController: SysuiStatusBarStateController
36     private var qS: QS? = null
37     @Mock private lateinit var nsslController: NotificationStackScrollLayoutController
38     @Mock private lateinit var dumpManager: DumpManager
39 
40     private lateinit var overScroller: SplitShadeLockScreenOverScroller
41 
42     @Before
setUpnull43     fun setUp() {
44         MockitoAnnotations.initMocks(this)
45         qS = mock()
46 
47         whenever(nsslController.height).thenReturn(1800)
48 
49         overScroller =
50             SplitShadeLockScreenOverScroller(
51                 configurationController,
52                 dumpManager,
53                 context,
54                 scrimController,
55                 statusBarStateController,
56                 { qS },
57                 { nsslController })
58     }
59 
60     @Test
setDragDownAmount_onKeyguard_appliesOverScrollnull61     fun setDragDownAmount_onKeyguard_appliesOverScroll() {
62         whenever(statusBarStateController.state).thenReturn(StatusBarState.KEYGUARD)
63 
64         setDragAmount(1000f)
65 
66         verifyOverScrollPerformed()
67     }
68 
69     @Test
setDragDownAmount_notOnKeyguard_doesNotApplyOverScrollnull70     fun setDragDownAmount_notOnKeyguard_doesNotApplyOverScroll() {
71         whenever(statusBarStateController.state).thenReturn(StatusBarState.SHADE)
72 
73         setDragAmount(1000f)
74 
75         verifyNoMoreInteractions(qS)
76         verifyNoMoreInteractions(scrimController)
77         verifyNoMoreInteractions(nsslController)
78     }
79 
80     @Test
setDragAmount_onKeyguard_thenNotOnKeyguard_resetsOverScrollToZeronull81     fun setDragAmount_onKeyguard_thenNotOnKeyguard_resetsOverScrollToZero() {
82         whenever(statusBarStateController.state).thenReturn(StatusBarState.KEYGUARD)
83         setDragAmount(1000f)
84         verifyOverScrollPerformed()
85         reset(qS, scrimController, nsslController)
86 
87         whenever(statusBarStateController.state).thenReturn(StatusBarState.SHADE)
88         setDragAmount(999f)
89         verifyOverScrollResetToZero()
90     }
91 
92     @Test
setDragAmount_onKeyguard_thenNotOnKeyguard_multipleTimes_resetsOverScrollToZeroOnlyOncenull93     fun setDragAmount_onKeyguard_thenNotOnKeyguard_multipleTimes_resetsOverScrollToZeroOnlyOnce() {
94         whenever(statusBarStateController.state).thenReturn(StatusBarState.KEYGUARD)
95         setDragAmount(1000f)
96         whenever(statusBarStateController.state).thenReturn(StatusBarState.SHADE)
97         setDragAmount(999f)
98         reset(qS!!, scrimController, nsslController)
99 
100         setDragAmount(998f)
101         setDragAmount(997f)
102         setDragAmount(996f)
103         verifyNoMoreOverScrollChanges()
104     }
105 
106     @Test
qsNull_applyOverscroll_doesNotCrashnull107     fun qsNull_applyOverscroll_doesNotCrash() {
108         qS = null
109 
110         setDragAmount(100f)
111     }
112 
verifyOverScrollPerformednull113     private fun verifyOverScrollPerformed() {
114         verify(qS!!).setOverScrollAmount(intThat { it > 0 })
115         verify(scrimController).setNotificationsOverScrollAmount(intThat { it > 0 })
116         verify(nsslController).setOverScrollAmount(intThat { it > 0 })
117     }
118 
verifyOverScrollResetToZeronull119     private fun verifyOverScrollResetToZero() {
120         // Might be more than once as the animator might have multiple values close to zero that
121         // round down to zero.
122         verify(qS!!, atLeast(1)).setOverScrollAmount(0)
123         verify(scrimController, atLeast(1)).setNotificationsOverScrollAmount(0)
124         verify(nsslController, atLeast(1)).setOverScrollAmount(0)
125     }
126 
verifyNoMoreOverScrollChangesnull127     private fun verifyNoMoreOverScrollChanges() {
128         verifyNoMoreInteractions(qS)
129         verifyNoMoreInteractions(scrimController)
130         verifyNoMoreInteractions(nsslController)
131     }
132 
setDragAmountnull133     private fun setDragAmount(dragDownAmount: Float) {
134         overScroller.expansionDragDownAmount = dragDownAmount
135         overScroller.finishAnimations()
136     }
137 }
138