1 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
125     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
193     fun tearDown() {
194         transitionController.dragDownAnimator?.cancel()
195     }
196 
197     @Test
198     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
205     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
213     fun testGoingToLockedShade() {
214         transitionController.goToLockedShade(null)
215         verify(statusbarStateController).setState(StatusBarState.SHADE_LOCKED)
216     }
217 
218     @Test
219     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
227     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
236     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
245     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
255     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
262     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
271     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
279     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
287     fun testGoToLockedShadeAlwaysCreatesQSAnimationInSplitShade() {
288         enableSplitShade()
289         transitionController.goToLockedShade(null, needsQSAnimation = true)
290         verify(shadeViewController).transitionToExpandedShade(anyLong())
291         assertNotNull(transitionController.dragDownAnimator)
292     }
293 
294     @Test
295     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
307     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
319     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
330     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
341     fun setDragAmount_setsKeyguardTransitionProgress() {
342         transitionController.dragDownAmount = 10f
343 
344         verify(shadeViewController).setKeyguardTransitionProgress(anyFloat(), anyInt())
345     }
346 
347     @Test
348     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
359     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
372     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
386     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
405     fun setDragDownAmount_setsValueOnMediaHierarchyManager() {
406         transitionController.dragDownAmount = 10f
407 
408         verify(mediaHierarchyManager).setTransitionToFullShadeAmount(10f)
409     }
410 
411     @Test
412     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
427     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
445     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
463     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
481     fun setDragDownAmount_inSplitShade_setsValueOnMediaHierarchyManager() {
482         enableSplitShade()
483 
484         transitionController.dragDownAmount = 10f
485 
486         verify(mediaHierarchyManager).setTransitionToFullShadeAmount(10f)
487     }
488 
489     @Test
490     fun setDragAmount_notInSplitShade_forwardsToSingleShadeOverScroller() {
491         disableSplitShade()
492 
493         transitionController.dragDownAmount = 10f
494 
495         verify(singleShadeOverScroller).expansionDragDownAmount = 10f
496         verifyZeroInteractions(splitShadeOverScroller)
497     }
498 
499     @Test
500     fun setDragAmount_inSplitShade_forwardsToSplitShadeOverScroller() {
501         enableSplitShade()
502 
503         transitionController.dragDownAmount = 10f
504 
505         verify(splitShadeOverScroller).expansionDragDownAmount = 10f
506         verifyZeroInteractions(singleShadeOverScroller)
507     }
508 
509     @Test
510     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
523     fun setDragDownAmount_notInSplitShade_setsKeyguardStatusBarAlphaToMinusOne() {
524         disableSplitShade()
525 
526         transitionController.dragDownAmount = 10f
527 
528         verify(shadeViewController).setKeyguardStatusBarAlpha(-1f)
529     }
530 
531     private fun enableSplitShade() {
532         setSplitShadeEnabled(true)
533     }
534 
535     private fun disableSplitShade() {
536         setSplitShadeEnabled(false)
537     }
538 
539     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      */
548     private fun ScrimController.transitionToFullShadeProgress(
549         progress: Float,
550         lockScreenNotificationsProgress: Float
551     ) {
552         scrimController.setTransitionToFullShadeProgress(
553                 progress,
554                 lockScreenNotificationsProgress
555         )
556     }
557 }
558