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