<lambda>null1 package com.android.systemui.statusbar
2
3 import android.app.StatusBarManager.DISABLE2_NOTIFICATION_SHADE
4 import android.testing.TestableLooper
5 import android.testing.TestableLooper.RunWithLooper
6 import androidx.test.ext.junit.runners.AndroidJUnit4
7 import androidx.test.filters.SmallTest
8 import com.android.systemui.ExpandHelper
9 import com.android.systemui.SysUITestModule
10 import com.android.systemui.SysuiTestCase
11 import com.android.systemui.TestMocksModule
12 import com.android.systemui.biometrics.domain.BiometricsDomainLayerModule
13 import com.android.systemui.classifier.FalsingCollectorFake
14 import com.android.systemui.classifier.FalsingManagerFake
15 import com.android.systemui.dagger.SysUISingleton
16 import com.android.systemui.flags.FakeFeatureFlagsClassicModule
17 import com.android.systemui.flags.Flags
18 import com.android.systemui.keyguard.domain.interactor.NaturalScrollingSettingObserver
19 import com.android.systemui.media.controls.ui.controller.MediaHierarchyManager
20 import com.android.systemui.plugins.qs.QS
21 import com.android.systemui.power.domain.interactor.PowerInteractor
22 import com.android.systemui.qs.ui.adapter.FakeQSSceneAdapter
23 import com.android.systemui.res.R
24 import com.android.systemui.shade.domain.interactor.ShadeLockscreenInteractor
25 import com.android.systemui.shade.data.repository.FakeShadeRepository
26 import com.android.systemui.shade.domain.interactor.ShadeInteractor
27 import com.android.systemui.statusbar.disableflags.data.model.DisableFlagsModel
28 import com.android.systemui.statusbar.disableflags.data.repository.FakeDisableFlagsRepository
29 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
30 import com.android.systemui.statusbar.notification.row.NotificationTestHelper
31 import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout
32 import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController
33 import com.android.systemui.statusbar.phone.CentralSurfaces
34 import com.android.systemui.statusbar.phone.KeyguardBypassController
35 import com.android.systemui.statusbar.phone.ScrimController
36 import com.android.systemui.statusbar.policy.FakeConfigurationController
37 import com.android.systemui.statusbar.policy.ResourcesSplitShadeStateController
38 import com.android.systemui.user.domain.UserDomainLayerModule
39 import com.android.systemui.util.mockito.any
40 import com.android.systemui.util.mockito.argumentCaptor
41 import com.android.systemui.util.mockito.mock
42 import dagger.BindsInstance
43 import dagger.Component
44 import kotlinx.coroutines.ExperimentalCoroutinesApi
45 import kotlinx.coroutines.test.TestScope
46 import kotlinx.coroutines.test.runCurrent
47 import org.junit.After
48 import org.junit.Assert.assertFalse
49 import org.junit.Assert.assertNotNull
50 import org.junit.Assert.assertNull
51 import org.junit.Assert.assertTrue
52 import org.junit.Before
53 import org.junit.Rule
54 import org.junit.Test
55 import org.junit.runner.RunWith
56 import org.mockito.ArgumentMatchers.anyBoolean
57 import org.mockito.ArgumentMatchers.anyFloat
58 import org.mockito.ArgumentMatchers.anyInt
59 import org.mockito.ArgumentMatchers.anyLong
60 import org.mockito.ArgumentMatchers.eq
61 import org.mockito.ArgumentMatchers.isNull
62 import org.mockito.Mock
63 import org.mockito.Mockito
64 import org.mockito.Mockito.clearInvocations
65 import org.mockito.Mockito.never
66 import org.mockito.Mockito.verify
67 import org.mockito.Mockito.verifyZeroInteractions
68 import org.mockito.junit.MockitoJUnit
69 import org.mockito.Mockito.`when` as whenever
70
71 private fun <T> anyObject(): T {
72 return Mockito.anyObject<T>()
73 }
74
75 @SmallTest
76 @RunWithLooper(setAsMainLooper = true)
77 @RunWith(AndroidJUnit4::class)
78 @OptIn(ExperimentalCoroutinesApi::class)
79 class LockscreenShadeTransitionControllerTest : SysuiTestCase() {
80
81 private lateinit var transitionController: LockscreenShadeTransitionController
82 private lateinit var testComponent: TestComponent
83 private val configurationController
84 get() = testComponent.configurationController
85 private val disableFlagsRepository
86 get() = testComponent.disableFlagsRepository
87 private val testScope
88 get() = testComponent.testScope
89
<lambda>null90 private val qsSceneAdapter = FakeQSSceneAdapter({ mock() })
91
92 lateinit var row: ExpandableNotificationRow
93
94 @Mock lateinit var centralSurfaces: CentralSurfaces
95 @Mock lateinit var depthController: NotificationShadeDepthController
96 @Mock lateinit var expandHelperCallback: ExpandHelper.Callback
97 @Mock lateinit var keyguardBypassController: KeyguardBypassController
98 @Mock lateinit var lockScreenUserManager: NotificationLockscreenUserManager
99 @Mock lateinit var mediaHierarchyManager: MediaHierarchyManager
100 @Mock lateinit var nsslController: NotificationStackScrollLayoutController
101 @Mock lateinit var qS: QS
102 @Mock lateinit var qsTransitionController: LockscreenShadeQsTransitionController
103 @Mock lateinit var scrimController: ScrimController
104 @Mock lateinit var shadeLockscreenInteractor: ShadeLockscreenInteractor
105 @Mock lateinit var singleShadeOverScroller: SingleShadeLockScreenOverScroller
106 @Mock lateinit var splitShadeOverScroller: SplitShadeLockScreenOverScroller
107 @Mock lateinit var stackscroller: NotificationStackScrollLayout
108 @Mock lateinit var statusbarStateController: SysuiStatusBarStateController
109 @Mock lateinit var transitionControllerCallback: LockscreenShadeTransitionController.Callback
110 @Mock lateinit var naturalScrollingSettingObserver: NaturalScrollingSettingObserver
111
112 @JvmField @Rule val mockito = MockitoJUnit.rule()
113
114 @Before
setupnull115 fun setup() {
116 val helper = NotificationTestHelper(mContext, mDependency, TestableLooper.get(this))
117 row = helper.createRow()
118 context
119 .getOrCreateTestableResources()
120 .addOverride(R.bool.config_use_split_notification_shade, false)
121 context
122 .getOrCreateTestableResources()
123 .addOverride(R.dimen.lockscreen_shade_depth_controller_transition_distance, 100)
124
125 whenever(nsslController.view).thenReturn(stackscroller)
126 whenever(nsslController.expandHelperCallback).thenReturn(expandHelperCallback)
127 whenever(statusbarStateController.state).thenReturn(StatusBarState.KEYGUARD)
128 whenever(nsslController.isInLockedDownShade).thenReturn(false)
129 whenever(qS.isFullyCollapsed).thenReturn(true)
130 whenever(lockScreenUserManager.userAllowsPrivateNotificationsInPublic(anyInt()))
131 .thenReturn(true)
132 whenever(lockScreenUserManager.shouldShowLockscreenNotifications()).thenReturn(true)
133 whenever(lockScreenUserManager.isLockscreenPublicMode(anyInt())).thenReturn(true)
134 whenever(keyguardBypassController.bypassEnabled).thenReturn(false)
135 whenever(naturalScrollingSettingObserver.isNaturalScrollingEnabled).thenReturn(true)
136
137 testComponent =
138 DaggerLockscreenShadeTransitionControllerTest_TestComponent.factory()
139 .create(
140 test = this,
141 featureFlags =
142 FakeFeatureFlagsClassicModule {
143 set(Flags.FULL_SCREEN_USER_SWITCHER, false)
144 },
145 mocks =
146 TestMocksModule(
147 notificationShadeDepthController = depthController,
148 keyguardBypassController = keyguardBypassController,
149 mediaHierarchyManager = mediaHierarchyManager,
150 notificationLockscreenUserManager = lockScreenUserManager,
151 notificationStackScrollLayoutController = nsslController,
152 scrimController = scrimController,
153 statusBarStateController = statusbarStateController,
154 )
155 )
156
157 transitionController =
158 LockscreenShadeTransitionController(
159 statusBarStateController = statusbarStateController,
160 logger = mock(),
161 keyguardBypassController = keyguardBypassController,
162 lockScreenUserManager = lockScreenUserManager,
163 falsingCollector = FalsingCollectorFake(),
164 ambientState = mock(),
165 mediaHierarchyManager = mediaHierarchyManager,
166 scrimTransitionController =
167 LockscreenShadeScrimTransitionController(
168 scrimController = scrimController,
169 context = context,
170 configurationController = configurationController,
171 dumpManager = mock(),
172 splitShadeStateController = ResourcesSplitShadeStateController()
173 ),
174 keyguardTransitionControllerFactory = { notificationPanelController ->
175 LockscreenShadeKeyguardTransitionController(
176 mediaHierarchyManager = mediaHierarchyManager,
177 shadeLockscreenInteractor = notificationPanelController,
178 context = context,
179 configurationController = configurationController,
180 dumpManager = mock(),
181 splitShadeStateController = ResourcesSplitShadeStateController()
182 )
183 },
184 depthController = depthController,
185 context = context,
186 splitShadeOverScrollerFactory = { _, _ -> splitShadeOverScroller },
187 singleShadeOverScrollerFactory = { singleShadeOverScroller },
188 activityStarter = mock(),
189 wakefulnessLifecycle = mock(),
190 configurationController = configurationController,
191 falsingManager = FalsingManagerFake(),
192 dumpManager = mock(),
193 qsTransitionControllerFactory = { qsTransitionController },
194 shadeRepository = testComponent.shadeRepository,
195 shadeInteractor = testComponent.shadeInteractor,
196 splitShadeStateController = ResourcesSplitShadeStateController(),
197 shadeLockscreenInteractorLazy = {shadeLockscreenInteractor},
198 naturalScrollingSettingObserver = naturalScrollingSettingObserver,
199 lazyQSSceneAdapter = { qsSceneAdapter }
200 )
201
202 transitionController.addCallback(transitionControllerCallback)
203 transitionController.centralSurfaces = centralSurfaces
204 transitionController.qS = qS
205 transitionController.setStackScroller(nsslController)
206 clearInvocations(centralSurfaces)
207
208 testScope.runCurrent()
209 }
210
211 @After
tearDownnull212 fun tearDown() {
213 transitionController.dragDownAnimator?.cancel()
214 }
215
216 @Test
testCantDragDownWhenQSExpandednull217 fun testCantDragDownWhenQSExpanded() {
218 assertTrue("Can't drag down on keyguard", transitionController.canDragDown())
219 whenever(qS.isFullyCollapsed).thenReturn(false)
220 assertFalse("Can drag down when QS is expanded", transitionController.canDragDown())
221 }
222
223 @Test
testCanDragDownInLockedDownShadenull224 fun testCanDragDownInLockedDownShade() {
225 whenever(statusbarStateController.state).thenReturn(StatusBarState.SHADE_LOCKED)
226 assertFalse("Can drag down in shade locked", transitionController.canDragDown())
227 whenever(nsslController.isInLockedDownShade).thenReturn(true)
228 assertTrue("Can't drag down in locked down shade", transitionController.canDragDown())
229 }
230
231 @Test
testGoingToLockedShadenull232 fun testGoingToLockedShade() {
233 transitionController.goToLockedShade(null)
234 verify(statusbarStateController).setState(StatusBarState.SHADE_LOCKED)
235 }
236
237 @Test
testWakingToShadeLockedWhenDozingnull238 fun testWakingToShadeLockedWhenDozing() {
239 whenever(statusbarStateController.isDozing).thenReturn(true)
240 transitionController.goToLockedShade(null)
241 verify(statusbarStateController).setState(StatusBarState.SHADE_LOCKED)
242 assertTrue("Not waking to shade locked", transitionController.isWakingToShadeLocked)
243 }
244
245 @Test
testNotWakingToShadeLockedWhenNotDozingnull246 fun testNotWakingToShadeLockedWhenNotDozing() {
247 whenever(statusbarStateController.isDozing).thenReturn(false)
248 transitionController.goToLockedShade(null)
249 verify(statusbarStateController).setState(StatusBarState.SHADE_LOCKED)
250 assertFalse(
251 "Waking to shade locked when not dozing",
252 transitionController.isWakingToShadeLocked
253 )
254 }
255
256 @Test
testGoToLockedShadeOnlyOnKeyguardnull257 fun testGoToLockedShadeOnlyOnKeyguard() {
258 whenever(statusbarStateController.state).thenReturn(StatusBarState.SHADE_LOCKED)
259 transitionController.goToLockedShade(null)
260 whenever(statusbarStateController.state).thenReturn(StatusBarState.SHADE)
261 transitionController.goToLockedShade(null)
262 verify(statusbarStateController, never()).setState(anyInt())
263 }
264
265 @Test
testDontGoWhenShadeDisablednull266 fun testDontGoWhenShadeDisabled() {
267 disableFlagsRepository.disableFlags.value =
268 DisableFlagsModel(
269 disable2 = DISABLE2_NOTIFICATION_SHADE,
270 )
271 testScope.runCurrent()
272 transitionController.goToLockedShade(null)
273 verify(statusbarStateController, never()).setState(anyInt())
274 }
275
276 @Test
testUserExpandsViewOnGoingToFullShadenull277 fun testUserExpandsViewOnGoingToFullShade() {
278 assertFalse("Row shouldn't be user expanded yet", row.isUserExpanded)
279 transitionController.goToLockedShade(row)
280 assertTrue("Row wasn't user expanded on drag down", row.isUserExpanded)
281 }
282
283 @Test
testTriggeringBouncerNoNotificationsOnLockscreennull284 fun testTriggeringBouncerNoNotificationsOnLockscreen() {
285 whenever(lockScreenUserManager.shouldShowLockscreenNotifications()).thenReturn(false)
286 transitionController.goToLockedShade(null)
287 verify(statusbarStateController, never()).setState(anyInt())
288 verify(statusbarStateController).setLeaveOpenOnKeyguardHide(true)
289 verify(centralSurfaces).showBouncerWithDimissAndCancelIfKeyguard(anyObject(), anyObject())
290 }
291
292 @Test
testGoToLockedShadeCreatesQSAnimationnull293 fun testGoToLockedShadeCreatesQSAnimation() {
294 transitionController.goToLockedShade(null)
295 verify(statusbarStateController).setState(StatusBarState.SHADE_LOCKED)
296 verify(shadeLockscreenInteractor).transitionToExpandedShade(anyLong())
297 assertNotNull(transitionController.dragDownAnimator)
298 }
299
300 @Test
testGoToLockedShadeDoesntCreateQSAnimationnull301 fun testGoToLockedShadeDoesntCreateQSAnimation() {
302 transitionController.goToLockedShade(null, needsQSAnimation = false)
303 verify(statusbarStateController).setState(StatusBarState.SHADE_LOCKED)
304 verify(shadeLockscreenInteractor).transitionToExpandedShade(anyLong())
305 assertNull(transitionController.dragDownAnimator)
306 }
307
308 @Test
testGoToLockedShadeAlwaysCreatesQSAnimationInSplitShadenull309 fun testGoToLockedShadeAlwaysCreatesQSAnimationInSplitShade() {
310 enableSplitShade()
311 transitionController.goToLockedShade(null, needsQSAnimation = true)
312 verify(shadeLockscreenInteractor).transitionToExpandedShade(anyLong())
313 assertNotNull(transitionController.dragDownAnimator)
314 }
315
316 @Test
testGoToLockedShadeCancelDoesntLeaveShadeOpenOnKeyguardHidenull317 fun testGoToLockedShadeCancelDoesntLeaveShadeOpenOnKeyguardHide() {
318 whenever(lockScreenUserManager.shouldShowLockscreenNotifications()).thenReturn(false)
319 whenever(lockScreenUserManager.isLockscreenPublicMode(any())).thenReturn(true)
320 transitionController.goToLockedShade(null)
321 val captor = argumentCaptor<Runnable>()
322 verify(centralSurfaces).showBouncerWithDimissAndCancelIfKeyguard(isNull(), captor.capture())
323 captor.value.run()
324 verify(statusbarStateController).setLeaveOpenOnKeyguardHide(false)
325 }
326
327 @Test
testDragDownAmountDoesntCallOutInLockedDownShadenull328 fun testDragDownAmountDoesntCallOutInLockedDownShade() {
329 whenever(nsslController.isInLockedDownShade).thenReturn(true)
330 transitionController.dragDownAmount = 10f
331 verify(nsslController, never()).setTransitionToFullShadeAmount(anyFloat())
332 verify(mediaHierarchyManager, never()).setTransitionToFullShadeAmount(anyFloat())
333 verify(scrimController, never()).setTransitionToFullShadeProgress(anyFloat(), anyFloat())
334 verify(transitionControllerCallback, never())
335 .setTransitionToFullShadeAmount(anyFloat(), anyBoolean(), anyLong())
336 verify(qsTransitionController, never()).dragDownAmount = anyFloat()
337 }
338
339 @Test
testDragDownAmountCallsOutnull340 fun testDragDownAmountCallsOut() {
341 transitionController.dragDownAmount = 10f
342 verify(nsslController).setTransitionToFullShadeAmount(anyFloat())
343 verify(mediaHierarchyManager).setTransitionToFullShadeAmount(anyFloat())
344 verify(scrimController).setTransitionToFullShadeProgress(anyFloat(), anyFloat())
345 verify(transitionControllerCallback)
346 .setTransitionToFullShadeAmount(anyFloat(), anyBoolean(), anyLong())
347 verify(qsTransitionController).dragDownAmount = 10f
348 verify(depthController).transitionToFullShadeProgress = anyFloat()
349 }
350
351 @Test
testDragDownAmount_depthDistanceIsZero_setsProgressToZeronull352 fun testDragDownAmount_depthDistanceIsZero_setsProgressToZero() {
353 context
354 .getOrCreateTestableResources()
355 .addOverride(R.dimen.lockscreen_shade_depth_controller_transition_distance, 0)
356 configurationController.notifyConfigurationChanged()
357
358 transitionController.dragDownAmount = 10f
359
360 verify(depthController).transitionToFullShadeProgress = 0f
361 }
362
363 @Test
testDragDownAmount_depthDistanceNonZero_setsProgressBasedOnDistancenull364 fun testDragDownAmount_depthDistanceNonZero_setsProgressBasedOnDistance() {
365 context
366 .getOrCreateTestableResources()
367 .addOverride(R.dimen.lockscreen_shade_depth_controller_transition_distance, 100)
368 configurationController.notifyConfigurationChanged()
369
370 transitionController.dragDownAmount = 10f
371
372 verify(depthController).transitionToFullShadeProgress = 0.1f
373 }
374
375 @Test
setDragAmount_setsKeyguardTransitionProgressnull376 fun setDragAmount_setsKeyguardTransitionProgress() {
377 transitionController.dragDownAmount = 10f
378
379 verify(shadeLockscreenInteractor).setKeyguardTransitionProgress(anyFloat(), anyInt())
380 }
381
382 @Test
setDragAmount_setsKeyguardAlphaBasedOnDistancenull383 fun setDragAmount_setsKeyguardAlphaBasedOnDistance() {
384 val alphaDistance =
385 context.resources.getDimensionPixelSize(
386 R.dimen.lockscreen_shade_npvc_keyguard_content_alpha_transition_distance
387 )
388 transitionController.dragDownAmount = 10f
389
390 val expectedAlpha = 1 - 10f / alphaDistance
391 verify(shadeLockscreenInteractor).setKeyguardTransitionProgress(eq(expectedAlpha), anyInt())
392 }
393
394 @Test
setDragAmount_notInSplitShade_setsKeyguardTranslationToZeronull395 fun setDragAmount_notInSplitShade_setsKeyguardTranslationToZero() {
396 val mediaTranslationY = 123
397 disableSplitShade()
398 whenever(mediaHierarchyManager.isCurrentlyInGuidedTransformation()).thenReturn(true)
399 whenever(mediaHierarchyManager.getGuidedTransformationTranslationY())
400 .thenReturn(mediaTranslationY)
401
402 transitionController.dragDownAmount = 10f
403
404 verify(shadeLockscreenInteractor).setKeyguardTransitionProgress(anyFloat(), eq(0))
405 }
406
407 @Test
setDragAmount_inSplitShade_setsKeyguardTranslationBasedOnMediaTranslationnull408 fun setDragAmount_inSplitShade_setsKeyguardTranslationBasedOnMediaTranslation() {
409 val mediaTranslationY = 123
410 enableSplitShade()
411 whenever(mediaHierarchyManager.isCurrentlyInGuidedTransformation()).thenReturn(true)
412 whenever(mediaHierarchyManager.getGuidedTransformationTranslationY())
413 .thenReturn(mediaTranslationY)
414
415 transitionController.dragDownAmount = 10f
416
417 verify(shadeLockscreenInteractor)
418 .setKeyguardTransitionProgress(anyFloat(), eq(mediaTranslationY))
419 }
420
421 @Test
setDragAmount_inSplitShade_mediaNotShowing_setsKeyguardTranslationBasedOnDistancenull422 fun setDragAmount_inSplitShade_mediaNotShowing_setsKeyguardTranslationBasedOnDistance() {
423 enableSplitShade()
424 whenever(mediaHierarchyManager.isCurrentlyInGuidedTransformation()).thenReturn(false)
425 whenever(mediaHierarchyManager.getGuidedTransformationTranslationY()).thenReturn(123)
426
427 transitionController.dragDownAmount = 10f
428
429 val distance =
430 context.resources.getDimensionPixelSize(
431 R.dimen.lockscreen_shade_keyguard_transition_distance
432 )
433 val offset =
434 context.resources.getDimensionPixelSize(
435 R.dimen.lockscreen_shade_keyguard_transition_vertical_offset
436 )
437 val expectedTranslation = 10f / distance * offset
438 verify(shadeLockscreenInteractor)
439 .setKeyguardTransitionProgress(anyFloat(), eq(expectedTranslation.toInt()))
440 }
441
442 @Test
setDragDownAmount_setsValueOnMediaHierarchyManagernull443 fun setDragDownAmount_setsValueOnMediaHierarchyManager() {
444 transitionController.dragDownAmount = 10f
445
446 verify(mediaHierarchyManager).setTransitionToFullShadeAmount(10f)
447 }
448
449 @Test
setDragAmount_setsScrimProgressBasedOnScrimDistancenull450 fun setDragAmount_setsScrimProgressBasedOnScrimDistance() {
451 val distance = 10
452 context.orCreateTestableResources.addOverride(
453 R.dimen.lockscreen_shade_scrim_transition_distance,
454 distance
455 )
456 configurationController.notifyConfigurationChanged()
457
458 transitionController.dragDownAmount = 5f
459
460 verify(scrimController)
461 .transitionToFullShadeProgress(
462 progress = eq(0.5f),
463 lockScreenNotificationsProgress = anyFloat()
464 )
465 }
466
467 @Test
setDragAmount_setsNotificationsScrimProgressBasedOnNotificationsScrimDistanceAndDelaynull468 fun setDragAmount_setsNotificationsScrimProgressBasedOnNotificationsScrimDistanceAndDelay() {
469 val distance = 100
470 val delay = 10
471 context.orCreateTestableResources.addOverride(
472 R.dimen.lockscreen_shade_notifications_scrim_transition_distance,
473 distance
474 )
475 context.orCreateTestableResources.addOverride(
476 R.dimen.lockscreen_shade_notifications_scrim_transition_delay,
477 delay
478 )
479 configurationController.notifyConfigurationChanged()
480
481 transitionController.dragDownAmount = 20f
482
483 verify(scrimController)
484 .transitionToFullShadeProgress(
485 progress = anyFloat(),
486 lockScreenNotificationsProgress = eq(0.1f)
487 )
488 }
489
490 @Test
setDragAmount_dragAmountLessThanNotifDelayDistance_setsNotificationsScrimProgressToZeronull491 fun setDragAmount_dragAmountLessThanNotifDelayDistance_setsNotificationsScrimProgressToZero() {
492 val distance = 100
493 val delay = 50
494 context.orCreateTestableResources.addOverride(
495 R.dimen.lockscreen_shade_notifications_scrim_transition_distance,
496 distance
497 )
498 context.orCreateTestableResources.addOverride(
499 R.dimen.lockscreen_shade_notifications_scrim_transition_delay,
500 delay
501 )
502 configurationController.notifyConfigurationChanged()
503
504 transitionController.dragDownAmount = 20f
505
506 verify(scrimController)
507 .transitionToFullShadeProgress(
508 progress = anyFloat(),
509 lockScreenNotificationsProgress = eq(0f)
510 )
511 }
512
513 @Test
setDragAmount_dragAmountMoreThanTotalDistance_setsNotificationsScrimProgressToOnenull514 fun setDragAmount_dragAmountMoreThanTotalDistance_setsNotificationsScrimProgressToOne() {
515 val distance = 100
516 val delay = 50
517 context.orCreateTestableResources.addOverride(
518 R.dimen.lockscreen_shade_notifications_scrim_transition_distance,
519 distance
520 )
521 context.orCreateTestableResources.addOverride(
522 R.dimen.lockscreen_shade_notifications_scrim_transition_delay,
523 delay
524 )
525 configurationController.notifyConfigurationChanged()
526
527 transitionController.dragDownAmount = 999999f
528
529 verify(scrimController)
530 .transitionToFullShadeProgress(
531 progress = anyFloat(),
532 lockScreenNotificationsProgress = eq(1f)
533 )
534 }
535
536 @Test
setDragDownAmount_inSplitShade_setsValueOnMediaHierarchyManagernull537 fun setDragDownAmount_inSplitShade_setsValueOnMediaHierarchyManager() {
538 enableSplitShade()
539
540 transitionController.dragDownAmount = 10f
541
542 verify(mediaHierarchyManager).setTransitionToFullShadeAmount(10f)
543 }
544
545 @Test
setDragAmount_notInSplitShade_forwardsToSingleShadeOverScrollernull546 fun setDragAmount_notInSplitShade_forwardsToSingleShadeOverScroller() {
547 disableSplitShade()
548
549 transitionController.dragDownAmount = 10f
550
551 verify(singleShadeOverScroller).expansionDragDownAmount = 10f
552 verifyZeroInteractions(splitShadeOverScroller)
553 }
554
555 @Test
setDragAmount_inSplitShade_forwardsToSplitShadeOverScrollernull556 fun setDragAmount_inSplitShade_forwardsToSplitShadeOverScroller() {
557 enableSplitShade()
558
559 transitionController.dragDownAmount = 10f
560
561 verify(splitShadeOverScroller).expansionDragDownAmount = 10f
562 verifyZeroInteractions(singleShadeOverScroller)
563 }
564
565 @Test
setDragDownAmount_inSplitShade_setsKeyguardStatusBarAlphaBasedOnDistancenull566 fun setDragDownAmount_inSplitShade_setsKeyguardStatusBarAlphaBasedOnDistance() {
567 val alphaDistance =
568 context.resources.getDimensionPixelSize(
569 R.dimen.lockscreen_shade_npvc_keyguard_content_alpha_transition_distance
570 )
571 val dragDownAmount = 10f
572 enableSplitShade()
573
574 transitionController.dragDownAmount = dragDownAmount
575
576 val expectedAlpha = 1 - dragDownAmount / alphaDistance
577 verify(shadeLockscreenInteractor).setKeyguardStatusBarAlpha(expectedAlpha)
578 }
579
580 @Test
setDragDownAmount_notInSplitShade_setsKeyguardStatusBarAlphaToMinusOnenull581 fun setDragDownAmount_notInSplitShade_setsKeyguardStatusBarAlphaToMinusOne() {
582 disableSplitShade()
583
584 transitionController.dragDownAmount = 10f
585
586 verify(shadeLockscreenInteractor).setKeyguardStatusBarAlpha(-1f)
587 }
588
589 @Test
nullQs_canDragDownFromAdapternull590 fun nullQs_canDragDownFromAdapter() {
591 transitionController.qS = null
592
593 qsSceneAdapter.isQsFullyCollapsed = true
594 assertTrue("Can't drag down on keyguard", transitionController.canDragDown())
595 qsSceneAdapter.isQsFullyCollapsed = false
596 assertFalse("Can drag down when QS is expanded", transitionController.canDragDown())
597 }
598
enableSplitShadenull599 private fun enableSplitShade() {
600 setSplitShadeEnabled(true)
601 }
602
disableSplitShadenull603 private fun disableSplitShade() {
604 setSplitShadeEnabled(false)
605 }
606
setSplitShadeEnablednull607 private fun setSplitShadeEnabled(enabled: Boolean) {
608 overrideResource(R.bool.config_use_split_notification_shade, enabled)
609 configurationController.notifyConfigurationChanged()
610 }
611
612 /**
613 * Wrapper around [ScrimController.transitionToFullShadeProgress] that has named parameters for
614 * clarify and easier refactoring of parameter names.
615 */
transitionToFullShadeProgressnull616 private fun ScrimController.transitionToFullShadeProgress(
617 progress: Float,
618 lockScreenNotificationsProgress: Float
619 ) {
620 setTransitionToFullShadeProgress(progress, lockScreenNotificationsProgress)
621 }
622
623 @SysUISingleton
624 @Component(
625 modules =
626 [
627 SysUITestModule::class,
628 UserDomainLayerModule::class,
629 BiometricsDomainLayerModule::class,
630 ]
631 )
632 interface TestComponent {
633
634 val configurationController: FakeConfigurationController
635 val disableFlagsRepository: FakeDisableFlagsRepository
636 val powerInteractor: PowerInteractor
637 val shadeInteractor: ShadeInteractor
638 val shadeRepository: FakeShadeRepository
639 val testScope: TestScope
640
641 @Component.Factory
642 interface Factory {
createnull643 fun create(
644 @BindsInstance test: SysuiTestCase,
645 featureFlags: FakeFeatureFlagsClassicModule,
646 mocks: TestMocksModule,
647 ): TestComponent
648 }
649 }
650 }
651