<lambda>null1 package com.android.systemui.statusbar
2
3 import android.app.StatusBarManager.DISABLE2_NOTIFICATION_SHADE
4 import android.testing.AndroidTestingRunner
5 import android.testing.TestableLooper
6 import android.testing.TestableLooper.RunWithLooper
7 import androidx.test.filters.SmallTest
8 import com.android.systemui.ExpandHelper
9 import com.android.systemui.R
10 import com.android.systemui.SysuiTestCase
11 import com.android.systemui.classifier.FalsingCollector
12 import com.android.systemui.classifier.FalsingCollectorFake
13 import com.android.systemui.dump.DumpManager
14 import com.android.systemui.keyguard.WakefulnessLifecycle
15 import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
16 import com.android.systemui.media.controls.ui.MediaHierarchyManager
17 import com.android.systemui.plugins.ActivityStarter
18 import com.android.systemui.plugins.FalsingManager
19 import com.android.systemui.plugins.qs.QS
20 import com.android.systemui.power.data.repository.FakePowerRepository
21 import com.android.systemui.power.domain.interactor.PowerInteractor
22 import com.android.systemui.shade.ShadeViewController
23 import com.android.systemui.shade.data.repository.FakeShadeRepository
24 import com.android.systemui.shade.domain.interactor.ShadeInteractor
25 import com.android.systemui.statusbar.disableflags.data.model.DisableFlagsModel
26 import com.android.systemui.statusbar.disableflags.data.repository.FakeDisableFlagsRepository
27 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
28 import com.android.systemui.statusbar.notification.row.NotificationTestHelper
29 import com.android.systemui.statusbar.notification.stack.AmbientState
30 import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout
31 import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController
32 import com.android.systemui.statusbar.phone.CentralSurfaces
33 import com.android.systemui.statusbar.phone.KeyguardBypassController
34 import com.android.systemui.statusbar.phone.LSShadeTransitionLogger
35 import com.android.systemui.statusbar.phone.ScrimController
36 import com.android.systemui.statusbar.pipeline.mobile.data.repository.FakeUserSetupRepository
37 import com.android.systemui.statusbar.policy.FakeConfigurationController
38 import com.android.systemui.util.mockito.mock
39 import kotlinx.coroutines.ExperimentalCoroutinesApi
40 import kotlinx.coroutines.test.StandardTestDispatcher
41 import kotlinx.coroutines.test.TestScope
42 import kotlinx.coroutines.test.runCurrent
43 import org.junit.After
44 import org.junit.Assert.assertFalse
45 import org.junit.Assert.assertNotNull
46 import org.junit.Assert.assertNull
47 import org.junit.Assert.assertTrue
48 import org.junit.Before
49 import org.junit.Rule
50 import org.junit.Test
51 import org.junit.runner.RunWith
52 import org.mockito.ArgumentMatchers.anyBoolean
53 import org.mockito.ArgumentMatchers.anyFloat
54 import org.mockito.ArgumentMatchers.anyInt
55 import org.mockito.ArgumentMatchers.anyLong
56 import org.mockito.ArgumentMatchers.eq
57 import org.mockito.Mock
58 import org.mockito.Mockito
59 import org.mockito.Mockito.clearInvocations
60 import org.mockito.Mockito.never
61 import org.mockito.Mockito.verify
62 import org.mockito.Mockito.verifyZeroInteractions
63 import org.mockito.junit.MockitoJUnit
64 import org.mockito.Mockito.`when` as whenever
65
66 private fun <T> anyObject(): T {
67 return Mockito.anyObject<T>()
68 }
69
70 @SmallTest
71 @RunWithLooper(setAsMainLooper = true)
72 @RunWith(AndroidTestingRunner::class)
73 @OptIn(ExperimentalCoroutinesApi::class)
74 class LockscreenShadeTransitionControllerTest : SysuiTestCase() {
75
76 private val testScope = TestScope(StandardTestDispatcher())
77
78 lateinit var transitionController: LockscreenShadeTransitionController
79 lateinit var row: ExpandableNotificationRow
80 @Mock lateinit var statusbarStateController: SysuiStatusBarStateController
81 @Mock lateinit var logger: LSShadeTransitionLogger
82 @Mock lateinit var dumpManager: DumpManager
83 @Mock lateinit var keyguardBypassController: KeyguardBypassController
84 @Mock lateinit var lockScreenUserManager: NotificationLockscreenUserManager
85 @Mock lateinit var falsingCollector: FalsingCollector
86 @Mock lateinit var ambientState: AmbientState
87 @Mock lateinit var wakefulnessLifecycle: WakefulnessLifecycle
88 @Mock lateinit var mediaHierarchyManager: MediaHierarchyManager
89 @Mock lateinit var scrimController: ScrimController
90 @Mock lateinit var falsingManager: FalsingManager
91 @Mock lateinit var shadeViewController: ShadeViewController
92 @Mock lateinit var nsslController: NotificationStackScrollLayoutController
93 @Mock lateinit var depthController: NotificationShadeDepthController
94 @Mock lateinit var stackscroller: NotificationStackScrollLayout
95 @Mock lateinit var expandHelperCallback: ExpandHelper.Callback
96 @Mock lateinit var mCentralSurfaces: CentralSurfaces
97 @Mock lateinit var qS: QS
98 @Mock lateinit var singleShadeOverScroller: SingleShadeLockScreenOverScroller
99 @Mock lateinit var splitShadeOverScroller: SplitShadeLockScreenOverScroller
100 @Mock lateinit var qsTransitionController: LockscreenShadeQsTransitionController
101 @Mock lateinit var activityStarter: ActivityStarter
102 @Mock lateinit var transitionControllerCallback: LockscreenShadeTransitionController.Callback
103 private val disableFlagsRepository = FakeDisableFlagsRepository()
104 private val keyguardRepository = FakeKeyguardRepository()
105 private val shadeInteractor = ShadeInteractor(
106 testScope.backgroundScope,
107 disableFlagsRepository,
108 keyguardRepository,
109 userSetupRepository = FakeUserSetupRepository(),
110 deviceProvisionedController = mock(),
111 userInteractor = mock(),
112 )
113 private val powerInteractor = PowerInteractor(
114 FakePowerRepository(),
115 keyguardRepository,
116 FalsingCollectorFake(),
117 screenOffAnimationController = mock(),
118 statusBarStateController = mock(),
119 )
120 @JvmField @Rule val mockito = MockitoJUnit.rule()
121
122 private val configurationController = FakeConfigurationController()
123
124 @Before
setupnull125 fun setup() {
126 // By default, have the shade enabled
127 disableFlagsRepository.disableFlags.value = DisableFlagsModel()
128 testScope.runCurrent()
129
130 val helper = NotificationTestHelper(
131 mContext,
132 mDependency,
133 TestableLooper.get(this))
134 row = helper.createRow()
135 context.getOrCreateTestableResources()
136 .addOverride(R.bool.config_use_split_notification_shade, false)
137 context.getOrCreateTestableResources()
138 .addOverride(R.dimen.lockscreen_shade_depth_controller_transition_distance, 100)
139 transitionController =
140 LockscreenShadeTransitionController(
141 statusBarStateController = statusbarStateController,
142 logger = logger,
143 keyguardBypassController = keyguardBypassController,
144 lockScreenUserManager = lockScreenUserManager,
145 falsingCollector = falsingCollector,
146 ambientState = ambientState,
147 mediaHierarchyManager = mediaHierarchyManager,
148 depthController = depthController,
149 wakefulnessLifecycle = wakefulnessLifecycle,
150 context = context,
151 configurationController = configurationController,
152 falsingManager = falsingManager,
153 dumpManager = dumpManager,
154 splitShadeOverScrollerFactory = { _, _ -> splitShadeOverScroller },
155 singleShadeOverScrollerFactory = { singleShadeOverScroller },
156 scrimTransitionController =
157 LockscreenShadeScrimTransitionController(
158 scrimController, context, configurationController, dumpManager),
159 keyguardTransitionControllerFactory = { notificationPanelController ->
160 LockscreenShadeKeyguardTransitionController(
161 mediaHierarchyManager,
162 notificationPanelController,
163 context,
164 configurationController,
165 dumpManager)
166 },
167 qsTransitionControllerFactory = { qsTransitionController },
168 activityStarter = activityStarter,
169 shadeRepository = FakeShadeRepository(),
170 shadeInteractor = shadeInteractor,
171 powerInteractor = powerInteractor,
172 )
173 transitionController.addCallback(transitionControllerCallback)
174 whenever(nsslController.view).thenReturn(stackscroller)
175 whenever(nsslController.expandHelperCallback).thenReturn(expandHelperCallback)
176 transitionController.shadeViewController = shadeViewController
177 transitionController.centralSurfaces = mCentralSurfaces
178 transitionController.qS = qS
179 transitionController.setStackScroller(nsslController)
180 whenever(statusbarStateController.state).thenReturn(StatusBarState.KEYGUARD)
181 whenever(nsslController.isInLockedDownShade).thenReturn(false)
182 whenever(qS.isFullyCollapsed).thenReturn(true)
183 whenever(lockScreenUserManager.userAllowsPrivateNotificationsInPublic(anyInt())).thenReturn(
184 true)
185 whenever(lockScreenUserManager.shouldShowLockscreenNotifications()).thenReturn(true)
186 whenever(lockScreenUserManager.isLockscreenPublicMode(anyInt())).thenReturn(true)
187 whenever(falsingCollector.shouldEnforceBouncer()).thenReturn(false)
188 whenever(keyguardBypassController.bypassEnabled).thenReturn(false)
189 clearInvocations(mCentralSurfaces)
190 }
191
192 @After
tearDownnull193 fun tearDown() {
194 transitionController.dragDownAnimator?.cancel()
195 }
196
197 @Test
testCantDragDownWhenQSExpandednull198 fun testCantDragDownWhenQSExpanded() {
199 assertTrue("Can't drag down on keyguard", transitionController.canDragDown())
200 whenever(qS.isFullyCollapsed).thenReturn(false)
201 assertFalse("Can drag down when QS is expanded", transitionController.canDragDown())
202 }
203
204 @Test
testCanDragDownInLockedDownShadenull205 fun testCanDragDownInLockedDownShade() {
206 whenever(statusbarStateController.state).thenReturn(StatusBarState.SHADE_LOCKED)
207 assertFalse("Can drag down in shade locked", transitionController.canDragDown())
208 whenever(nsslController.isInLockedDownShade).thenReturn(true)
209 assertTrue("Can't drag down in locked down shade", transitionController.canDragDown())
210 }
211
212 @Test
testGoingToLockedShadenull213 fun testGoingToLockedShade() {
214 transitionController.goToLockedShade(null)
215 verify(statusbarStateController).setState(StatusBarState.SHADE_LOCKED)
216 }
217
218 @Test
testWakingToShadeLockedWhenDozingnull219 fun testWakingToShadeLockedWhenDozing() {
220 whenever(statusbarStateController.isDozing).thenReturn(true)
221 transitionController.goToLockedShade(null)
222 verify(statusbarStateController).setState(StatusBarState.SHADE_LOCKED)
223 assertTrue("Not waking to shade locked", transitionController.isWakingToShadeLocked)
224 }
225
226 @Test
testNotWakingToShadeLockedWhenNotDozingnull227 fun testNotWakingToShadeLockedWhenNotDozing() {
228 whenever(statusbarStateController.isDozing).thenReturn(false)
229 transitionController.goToLockedShade(null)
230 verify(statusbarStateController).setState(StatusBarState.SHADE_LOCKED)
231 assertFalse("Waking to shade locked when not dozing",
232 transitionController.isWakingToShadeLocked)
233 }
234
235 @Test
testGoToLockedShadeOnlyOnKeyguardnull236 fun testGoToLockedShadeOnlyOnKeyguard() {
237 whenever(statusbarStateController.state).thenReturn(StatusBarState.SHADE_LOCKED)
238 transitionController.goToLockedShade(null)
239 whenever(statusbarStateController.state).thenReturn(StatusBarState.SHADE)
240 transitionController.goToLockedShade(null)
241 verify(statusbarStateController, never()).setState(anyInt())
242 }
243
244 @Test
testDontGoWhenShadeDisablednull245 fun testDontGoWhenShadeDisabled() {
246 disableFlagsRepository.disableFlags.value = DisableFlagsModel(
247 disable2 = DISABLE2_NOTIFICATION_SHADE,
248 )
249 testScope.runCurrent()
250 transitionController.goToLockedShade(null)
251 verify(statusbarStateController, never()).setState(anyInt())
252 }
253
254 @Test
testUserExpandsViewOnGoingToFullShadenull255 fun testUserExpandsViewOnGoingToFullShade() {
256 assertFalse("Row shouldn't be user expanded yet", row.isUserExpanded)
257 transitionController.goToLockedShade(row)
258 assertTrue("Row wasn't user expanded on drag down", row.isUserExpanded)
259 }
260
261 @Test
testTriggeringBouncerNoNotificationsOnLockscreennull262 fun testTriggeringBouncerNoNotificationsOnLockscreen() {
263 whenever(lockScreenUserManager.shouldShowLockscreenNotifications()).thenReturn(false)
264 transitionController.goToLockedShade(null)
265 verify(statusbarStateController, never()).setState(anyInt())
266 verify(statusbarStateController).setLeaveOpenOnKeyguardHide(true)
267 verify(mCentralSurfaces).showBouncerWithDimissAndCancelIfKeyguard(anyObject(), anyObject())
268 }
269
270 @Test
testGoToLockedShadeCreatesQSAnimationnull271 fun testGoToLockedShadeCreatesQSAnimation() {
272 transitionController.goToLockedShade(null)
273 verify(statusbarStateController).setState(StatusBarState.SHADE_LOCKED)
274 verify(shadeViewController).transitionToExpandedShade(anyLong())
275 assertNotNull(transitionController.dragDownAnimator)
276 }
277
278 @Test
testGoToLockedShadeDoesntCreateQSAnimationnull279 fun testGoToLockedShadeDoesntCreateQSAnimation() {
280 transitionController.goToLockedShade(null, needsQSAnimation = false)
281 verify(statusbarStateController).setState(StatusBarState.SHADE_LOCKED)
282 verify(shadeViewController).transitionToExpandedShade(anyLong())
283 assertNull(transitionController.dragDownAnimator)
284 }
285
286 @Test
testGoToLockedShadeAlwaysCreatesQSAnimationInSplitShadenull287 fun testGoToLockedShadeAlwaysCreatesQSAnimationInSplitShade() {
288 enableSplitShade()
289 transitionController.goToLockedShade(null, needsQSAnimation = true)
290 verify(shadeViewController).transitionToExpandedShade(anyLong())
291 assertNotNull(transitionController.dragDownAnimator)
292 }
293
294 @Test
testDragDownAmountDoesntCallOutInLockedDownShadenull295 fun testDragDownAmountDoesntCallOutInLockedDownShade() {
296 whenever(nsslController.isInLockedDownShade).thenReturn(true)
297 transitionController.dragDownAmount = 10f
298 verify(nsslController, never()).setTransitionToFullShadeAmount(anyFloat())
299 verify(mediaHierarchyManager, never()).setTransitionToFullShadeAmount(anyFloat())
300 verify(scrimController, never()).setTransitionToFullShadeProgress(anyFloat(), anyFloat())
301 verify(transitionControllerCallback, never()).setTransitionToFullShadeAmount(anyFloat(),
302 anyBoolean(), anyLong())
303 verify(qsTransitionController, never()).dragDownAmount = anyFloat()
304 }
305
306 @Test
testDragDownAmountCallsOutnull307 fun testDragDownAmountCallsOut() {
308 transitionController.dragDownAmount = 10f
309 verify(nsslController).setTransitionToFullShadeAmount(anyFloat())
310 verify(mediaHierarchyManager).setTransitionToFullShadeAmount(anyFloat())
311 verify(scrimController).setTransitionToFullShadeProgress(anyFloat(), anyFloat())
312 verify(transitionControllerCallback).setTransitionToFullShadeAmount(anyFloat(),
313 anyBoolean(), anyLong())
314 verify(qsTransitionController).dragDownAmount = 10f
315 verify(depthController).transitionToFullShadeProgress = anyFloat()
316 }
317
318 @Test
testDragDownAmount_depthDistanceIsZero_setsProgressToZeronull319 fun testDragDownAmount_depthDistanceIsZero_setsProgressToZero() {
320 context.getOrCreateTestableResources()
321 .addOverride(R.dimen.lockscreen_shade_depth_controller_transition_distance, 0)
322 configurationController.notifyConfigurationChanged()
323
324 transitionController.dragDownAmount = 10f
325
326 verify(depthController).transitionToFullShadeProgress = 0f
327 }
328
329 @Test
testDragDownAmount_depthDistanceNonZero_setsProgressBasedOnDistancenull330 fun testDragDownAmount_depthDistanceNonZero_setsProgressBasedOnDistance() {
331 context.getOrCreateTestableResources()
332 .addOverride(R.dimen.lockscreen_shade_depth_controller_transition_distance, 100)
333 configurationController.notifyConfigurationChanged()
334
335 transitionController.dragDownAmount = 10f
336
337 verify(depthController).transitionToFullShadeProgress = 0.1f
338 }
339
340 @Test
setDragAmount_setsKeyguardTransitionProgressnull341 fun setDragAmount_setsKeyguardTransitionProgress() {
342 transitionController.dragDownAmount = 10f
343
344 verify(shadeViewController).setKeyguardTransitionProgress(anyFloat(), anyInt())
345 }
346
347 @Test
setDragAmount_setsKeyguardAlphaBasedOnDistancenull348 fun setDragAmount_setsKeyguardAlphaBasedOnDistance() {
349 val alphaDistance = context.resources.getDimensionPixelSize(
350 R.dimen.lockscreen_shade_npvc_keyguard_content_alpha_transition_distance)
351 transitionController.dragDownAmount = 10f
352
353 val expectedAlpha = 1 - 10f / alphaDistance
354 verify(shadeViewController)
355 .setKeyguardTransitionProgress(eq(expectedAlpha), anyInt())
356 }
357
358 @Test
setDragAmount_notInSplitShade_setsKeyguardTranslationToZeronull359 fun setDragAmount_notInSplitShade_setsKeyguardTranslationToZero() {
360 val mediaTranslationY = 123
361 disableSplitShade()
362 whenever(mediaHierarchyManager.isCurrentlyInGuidedTransformation()).thenReturn(true)
363 whenever(mediaHierarchyManager.getGuidedTransformationTranslationY())
364 .thenReturn(mediaTranslationY)
365
366 transitionController.dragDownAmount = 10f
367
368 verify(shadeViewController).setKeyguardTransitionProgress(anyFloat(), eq(0))
369 }
370
371 @Test
setDragAmount_inSplitShade_setsKeyguardTranslationBasedOnMediaTranslationnull372 fun setDragAmount_inSplitShade_setsKeyguardTranslationBasedOnMediaTranslation() {
373 val mediaTranslationY = 123
374 enableSplitShade()
375 whenever(mediaHierarchyManager.isCurrentlyInGuidedTransformation()).thenReturn(true)
376 whenever(mediaHierarchyManager.getGuidedTransformationTranslationY())
377 .thenReturn(mediaTranslationY)
378
379 transitionController.dragDownAmount = 10f
380
381 verify(shadeViewController)
382 .setKeyguardTransitionProgress(anyFloat(), eq(mediaTranslationY))
383 }
384
385 @Test
setDragAmount_inSplitShade_mediaNotShowing_setsKeyguardTranslationBasedOnDistancenull386 fun setDragAmount_inSplitShade_mediaNotShowing_setsKeyguardTranslationBasedOnDistance() {
387 enableSplitShade()
388 whenever(mediaHierarchyManager.isCurrentlyInGuidedTransformation()).thenReturn(false)
389 whenever(mediaHierarchyManager.getGuidedTransformationTranslationY()).thenReturn(123)
390
391 transitionController.dragDownAmount = 10f
392
393 val distance =
394 context.resources.getDimensionPixelSize(
395 R.dimen.lockscreen_shade_keyguard_transition_distance)
396 val offset =
397 context.resources.getDimensionPixelSize(
398 R.dimen.lockscreen_shade_keyguard_transition_vertical_offset)
399 val expectedTranslation = 10f / distance * offset
400 verify(shadeViewController)
401 .setKeyguardTransitionProgress(anyFloat(), eq(expectedTranslation.toInt()))
402 }
403
404 @Test
setDragDownAmount_setsValueOnMediaHierarchyManagernull405 fun setDragDownAmount_setsValueOnMediaHierarchyManager() {
406 transitionController.dragDownAmount = 10f
407
408 verify(mediaHierarchyManager).setTransitionToFullShadeAmount(10f)
409 }
410
411 @Test
setDragAmount_setsScrimProgressBasedOnScrimDistancenull412 fun setDragAmount_setsScrimProgressBasedOnScrimDistance() {
413 val distance = 10
414 context.orCreateTestableResources
415 .addOverride(R.dimen.lockscreen_shade_scrim_transition_distance, distance)
416 configurationController.notifyConfigurationChanged()
417
418 transitionController.dragDownAmount = 5f
419
420 verify(scrimController).transitionToFullShadeProgress(
421 progress = eq(0.5f),
422 lockScreenNotificationsProgress = anyFloat()
423 )
424 }
425
426 @Test
setDragAmount_setsNotificationsScrimProgressBasedOnNotificationsScrimDistanceAndDelaynull427 fun setDragAmount_setsNotificationsScrimProgressBasedOnNotificationsScrimDistanceAndDelay() {
428 val distance = 100
429 val delay = 10
430 context.orCreateTestableResources.addOverride(
431 R.dimen.lockscreen_shade_notifications_scrim_transition_distance, distance)
432 context.orCreateTestableResources.addOverride(
433 R.dimen.lockscreen_shade_notifications_scrim_transition_delay, delay)
434 configurationController.notifyConfigurationChanged()
435
436 transitionController.dragDownAmount = 20f
437
438 verify(scrimController).transitionToFullShadeProgress(
439 progress = anyFloat(),
440 lockScreenNotificationsProgress = eq(0.1f)
441 )
442 }
443
444 @Test
setDragAmount_dragAmountLessThanNotifDelayDistance_setsNotificationsScrimProgressToZeronull445 fun setDragAmount_dragAmountLessThanNotifDelayDistance_setsNotificationsScrimProgressToZero() {
446 val distance = 100
447 val delay = 50
448 context.orCreateTestableResources.addOverride(
449 R.dimen.lockscreen_shade_notifications_scrim_transition_distance, distance)
450 context.orCreateTestableResources.addOverride(
451 R.dimen.lockscreen_shade_notifications_scrim_transition_delay, delay)
452 configurationController.notifyConfigurationChanged()
453
454 transitionController.dragDownAmount = 20f
455
456 verify(scrimController).transitionToFullShadeProgress(
457 progress = anyFloat(),
458 lockScreenNotificationsProgress = eq(0f)
459 )
460 }
461
462 @Test
setDragAmount_dragAmountMoreThanTotalDistance_setsNotificationsScrimProgressToOnenull463 fun setDragAmount_dragAmountMoreThanTotalDistance_setsNotificationsScrimProgressToOne() {
464 val distance = 100
465 val delay = 50
466 context.orCreateTestableResources.addOverride(
467 R.dimen.lockscreen_shade_notifications_scrim_transition_distance, distance)
468 context.orCreateTestableResources.addOverride(
469 R.dimen.lockscreen_shade_notifications_scrim_transition_delay, delay)
470 configurationController.notifyConfigurationChanged()
471
472 transitionController.dragDownAmount = 999999f
473
474 verify(scrimController).transitionToFullShadeProgress(
475 progress = anyFloat(),
476 lockScreenNotificationsProgress = eq(1f)
477 )
478 }
479
480 @Test
setDragDownAmount_inSplitShade_setsValueOnMediaHierarchyManagernull481 fun setDragDownAmount_inSplitShade_setsValueOnMediaHierarchyManager() {
482 enableSplitShade()
483
484 transitionController.dragDownAmount = 10f
485
486 verify(mediaHierarchyManager).setTransitionToFullShadeAmount(10f)
487 }
488
489 @Test
setDragAmount_notInSplitShade_forwardsToSingleShadeOverScrollernull490 fun setDragAmount_notInSplitShade_forwardsToSingleShadeOverScroller() {
491 disableSplitShade()
492
493 transitionController.dragDownAmount = 10f
494
495 verify(singleShadeOverScroller).expansionDragDownAmount = 10f
496 verifyZeroInteractions(splitShadeOverScroller)
497 }
498
499 @Test
setDragAmount_inSplitShade_forwardsToSplitShadeOverScrollernull500 fun setDragAmount_inSplitShade_forwardsToSplitShadeOverScroller() {
501 enableSplitShade()
502
503 transitionController.dragDownAmount = 10f
504
505 verify(splitShadeOverScroller).expansionDragDownAmount = 10f
506 verifyZeroInteractions(singleShadeOverScroller)
507 }
508
509 @Test
setDragDownAmount_inSplitShade_setsKeyguardStatusBarAlphaBasedOnDistancenull510 fun setDragDownAmount_inSplitShade_setsKeyguardStatusBarAlphaBasedOnDistance() {
511 val alphaDistance = context.resources.getDimensionPixelSize(
512 R.dimen.lockscreen_shade_npvc_keyguard_content_alpha_transition_distance)
513 val dragDownAmount = 10f
514 enableSplitShade()
515
516 transitionController.dragDownAmount = dragDownAmount
517
518 val expectedAlpha = 1 - dragDownAmount / alphaDistance
519 verify(shadeViewController).setKeyguardStatusBarAlpha(expectedAlpha)
520 }
521
522 @Test
setDragDownAmount_notInSplitShade_setsKeyguardStatusBarAlphaToMinusOnenull523 fun setDragDownAmount_notInSplitShade_setsKeyguardStatusBarAlphaToMinusOne() {
524 disableSplitShade()
525
526 transitionController.dragDownAmount = 10f
527
528 verify(shadeViewController).setKeyguardStatusBarAlpha(-1f)
529 }
530
enableSplitShadenull531 private fun enableSplitShade() {
532 setSplitShadeEnabled(true)
533 }
534
disableSplitShadenull535 private fun disableSplitShade() {
536 setSplitShadeEnabled(false)
537 }
538
setSplitShadeEnablednull539 private fun setSplitShadeEnabled(enabled: Boolean) {
540 overrideResource(R.bool.config_use_split_notification_shade, enabled)
541 configurationController.notifyConfigurationChanged()
542 }
543
544 /**
545 * Wrapper around [ScrimController.transitionToFullShadeProgress] that has named parameters for
546 * clarify and easier refactoring of parameter names.
547 */
transitionToFullShadeProgressnull548 private fun ScrimController.transitionToFullShadeProgress(
549 progress: Float,
550 lockScreenNotificationsProgress: Float
551 ) {
552 scrimController.setTransitionToFullShadeProgress(
553 progress,
554 lockScreenNotificationsProgress
555 )
556 }
557 }
558