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