summaryrefslogtreecommitdiff
path: root/packages/SystemUI/src
diff options
context:
space:
mode:
Diffstat (limited to 'packages/SystemUI/src')
-rw-r--r--packages/SystemUI/src/com/android/keyguard/CarrierTextController.java27
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputView.java21
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java26
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardPatternView.java5
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputView.java19
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java12
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardSecurityModel.java7
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java2
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java3
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java50
-rw-r--r--packages/SystemUI/src/com/android/systemui/Dependency.java35
-rw-r--r--packages/SystemUI/src/com/android/systemui/ForegroundServiceLifetimeExtender.java10
-rw-r--r--packages/SystemUI/src/com/android/systemui/ForegroundServiceNotificationListener.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/ImageWallpaper.java54
-rw-r--r--packages/SystemUI/src/com/android/systemui/LatencyTester.java33
-rw-r--r--packages/SystemUI/src/com/android/systemui/ScreenDecorations.java270
-rw-r--r--packages/SystemUI/src/com/android/systemui/SizeCompatModeActivityController.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/SliceBroadcastRelayHandler.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/SysUIToast.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/SystemBars.java88
-rw-r--r--packages/SystemUI/src/com/android/systemui/SystemUI.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/SystemUIAppComponentFactory.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/SystemUIApplication.java19
-rw-r--r--packages/SystemUI/src/com/android/systemui/SystemUIFactory.java40
-rw-r--r--packages/SystemUI/src/com/android/systemui/SystemUIService.java31
-rw-r--r--packages/SystemUI/src/com/android/systemui/VendorServices.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/assist/AssistHandleBehaviorController.java33
-rw-r--r--packages/SystemUI/src/com/android/systemui/assist/AssistHandleViewController.java191
-rw-r--r--packages/SystemUI/src/com/android/systemui/assist/AssistModule.java10
-rw-r--r--packages/SystemUI/src/com/android/systemui/assist/ui/DefaultUiController.java39
-rw-r--r--packages/SystemUI/src/com/android/systemui/assist/ui/EdgeLight.java43
-rw-r--r--packages/SystemUI/src/com/android/systemui/assist/ui/InvocationLightsView.java23
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricView.java155
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java225
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java115
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/AuthCredentialPasswordView.java121
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/AuthCredentialPatternView.java105
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/AuthCredentialView.java265
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/AuthDialog.java37
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/AuthDialogCallback.java14
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/AuthPanelController.java118
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/Utils.java59
-rw-r--r--packages/SystemUI/src/com/android/systemui/broadcast/BroadcastDispatcher.kt17
-rw-r--r--packages/SystemUI/src/com/android/systemui/broadcast/UserBroadcastDispatcher.kt8
-rw-r--r--packages/SystemUI/src/com/android/systemui/bubbles/Bubble.java32
-rw-r--r--packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java65
-rw-r--r--packages/SystemUI/src/com/android/systemui/bubbles/BubbleData.java11
-rw-r--r--packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java12
-rw-r--r--packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java13
-rw-r--r--packages/SystemUI/src/com/android/systemui/bubbles/BubbleView.java12
-rw-r--r--packages/SystemUI/src/com/android/systemui/classifier/FalsingLog.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerProxy.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/classifier/brightline/PointerCountClassifier.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/dagger/ActivityBinder.java (renamed from packages/SystemUI/src/com/android/systemui/ActivityBinder.java)3
-rw-r--r--packages/SystemUI/src/com/android/systemui/dagger/ComponentBinder.java (renamed from packages/SystemUI/src/com/android/systemui/ComponentBinder.java)2
-rw-r--r--packages/SystemUI/src/com/android/systemui/dagger/ContextComponentHelper.java (renamed from packages/SystemUI/src/com/android/systemui/ContextComponentHelper.java)4
-rw-r--r--packages/SystemUI/src/com/android/systemui/dagger/ContextComponentResolver.java (renamed from packages/SystemUI/src/com/android/systemui/ContextComponentResolver.java)4
-rw-r--r--packages/SystemUI/src/com/android/systemui/dagger/DependencyBinder.java (renamed from packages/SystemUI/src/com/android/systemui/DependencyBinder.java)28
-rw-r--r--packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java (renamed from packages/SystemUI/src/com/android/systemui/DependencyProvider.java)111
-rw-r--r--packages/SystemUI/src/com/android/systemui/dagger/ServiceBinder.java (renamed from packages/SystemUI/src/com/android/systemui/ServiceBinder.java)17
-rw-r--r--packages/SystemUI/src/com/android/systemui/dagger/SystemServicesModule.java130
-rw-r--r--packages/SystemUI/src/com/android/systemui/dagger/SystemUIBinder.java83
-rw-r--r--packages/SystemUI/src/com/android/systemui/dagger/SystemUIDefaultModule.java (renamed from packages/SystemUI/src/com/android/systemui/SystemUIDefaultModule.java)19
-rw-r--r--packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java (renamed from packages/SystemUI/src/com/android/systemui/SystemUIModule.java)14
-rw-r--r--packages/SystemUI/src/com/android/systemui/dagger/SystemUIRootComponent.java (renamed from packages/SystemUI/src/com/android/systemui/SystemUIRootComponent.java)15
-rw-r--r--packages/SystemUI/src/com/android/systemui/dagger/qualifiers/BgHandler.java (renamed from packages/SystemUI/src/com/android/systemui/SystemUIBinder.java)26
-rw-r--r--packages/SystemUI/src/com/android/systemui/dagger/qualifiers/BgLooper.java30
-rw-r--r--packages/SystemUI/src/com/android/systemui/dagger/qualifiers/MainHandler.java30
-rw-r--r--packages/SystemUI/src/com/android/systemui/dagger/qualifiers/MainLooper.java30
-rw-r--r--packages/SystemUI/src/com/android/systemui/dagger/qualifiers/MainResources.java31
-rw-r--r--packages/SystemUI/src/com/android/systemui/doze/DozeDockHandler.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/doze/DozeEvent.java154
-rw-r--r--packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java108
-rw-r--r--packages/SystemUI/src/com/android/systemui/doze/DozeHost.java11
-rw-r--r--packages/SystemUI/src/com/android/systemui/doze/DozeLog.java421
-rw-r--r--packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java19
-rw-r--r--packages/SystemUI/src/com/android/systemui/doze/DozeScreenState.java28
-rw-r--r--packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java76
-rw-r--r--packages/SystemUI/src/com/android/systemui/doze/DozeService.java12
-rw-r--r--packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java68
-rw-r--r--packages/SystemUI/src/com/android/systemui/doze/DozeUi.java15
-rw-r--r--packages/SystemUI/src/com/android/systemui/doze/DozeWallpaperState.java18
-rw-r--r--packages/SystemUI/src/com/android/systemui/fragments/FragmentService.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsComponent.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java30
-rw-r--r--packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsImpl.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/glwallpaper/EglHelper.java43
-rw-r--r--packages/SystemUI/src/com/android/systemui/glwallpaper/ImageRevealHelper.java11
-rw-r--r--packages/SystemUI/src/com/android/systemui/glwallpaper/ImageWallpaperRenderer.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyboard/KeyboardUI.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/KeyguardLifecyclesDispatcher.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java23
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java27
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java107
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/WorkLockActivity.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/log/Event.java67
-rw-r--r--packages/SystemUI/src/com/android/systemui/log/RichEvent.java107
-rw-r--r--packages/SystemUI/src/com/android/systemui/log/SysuiLog.java163
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/RingtonePlayer.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/pip/BasePipManager.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/pip/PipBoundsHandler.java34
-rw-r--r--packages/SystemUI/src/com/android/systemui/pip/PipUI.java19
-rw-r--r--packages/SystemUI/src/com/android/systemui/pip/phone/PipDismissViewController.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java43
-rw-r--r--packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java25
-rw-r--r--packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivityController.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java50
-rw-r--r--packages/SystemUI/src/com/android/systemui/power/PowerUI.java22
-rw-r--r--packages/SystemUI/src/com/android/systemui/privacy/PrivacyItemController.kt17
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/DoubleLineTileLayout.kt133
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java12
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSCarrierGroup.java91
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSMediaPlayer.java301
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSPanel.java121
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QuickQSMediaPlayer.java203
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java44
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java14
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/TileLayout.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java20
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java38
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java18
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java18
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/external/TileServiceManager.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/external/TileServices.java12
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java10
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java10
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java14
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/ControlsTile.java197
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java14
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java18
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/Recents.java35
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/RecentsModule.java53
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/RecentsOnboarding.java18
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java54
-rw-r--r--packages/SystemUI/src/com/android/systemui/shortcut/ShortcutKeyDispatcher.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/AlertingNotificationManager.java12
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java230
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/FeatureFlags.java81
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java17
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NavigationBarController.java20
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NotificationListener.java32
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java37
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java37
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java41
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NotificationUiAdjustment.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java32
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/PulseExpansionHandler.kt14
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/SmartReplyController.java14
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateControllerImpl.java19
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/SysuiStatusBarStateController.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/ActivityLaunchAnimator.java19
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/DynamicPrivacyController.java37
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/InstantAppNotifier.java17
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/NewNotifPipeline.java49
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationAlertingManager.java14
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java102
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationFilter.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationInterruptionStateProvider.java26
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationListController.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationSectionsFeatureManager.kt73
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationUtils.java14
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt8
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/VisualStabilityManager.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/DismissedByUserStats.java38
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollection.java426
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollectionListener.java46
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifLifetimeExtender.java58
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifListBuilder.java43
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationData.java118
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java114
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationRowBinderImpl.java19
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotifEvent.java160
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotifLog.java125
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationLogger.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleHub.kt44
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleHubModule.kt47
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleHubNotificationListener.kt272
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleHubViewController.kt133
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleNotificationIdentifier.kt36
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/people/ViewPipeline.kt44
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java12
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationBlockingHelperManager.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflater.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGuts.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java17
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMediaTemplateViewWrapper.java30
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapper.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AmbientState.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationRoundnessManager.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.java115
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java34
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/PeopleHubView.kt65
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoHideController.java130
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/BarTransitions.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java55
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java18
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/DoubleTapHelper.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java64
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java22
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeServiceHost.java465
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/EdgeBackGestureHandler.java32
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/FloatingRotationButton.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceController.java12
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java30
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java52
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java25
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBypassController.kt10
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardLiftController.kt8
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarController.java165
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarTransitionsController.java10
-rwxr-xr-xpackages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java49
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenWallpaper.java38
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NPVPluginManager.kt14
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java201
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java28
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupAlertTransferHelper.java63
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java50
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java16
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java120
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java23
-rwxr-xr-xpackages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java14
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/RegionSamplingHelper.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java178
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java50
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java1092
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java42
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java24
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java16
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallback.java29
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java18
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java395
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowViewController.java564
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/SystemUIDialog.java16
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockMethodCache.java229
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothControllerImpl.java11
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java26
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceProvisionedControllerImpl.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/ExtensionController.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/ExtensionControllerImpl.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java10
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/InflatedSmartReplies.java10
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitor.java81
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitorImpl.java183
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardStateController.java177
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardStateControllerImpl.java326
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationControllerImpl.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java108
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyConstants.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java59
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/tv/AudioRecordingDisclosureBar.java203
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/tv/OWNERS8
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java29
-rw-r--r--packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/tuner/TunerServiceImpl.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/usb/UsbConfirmActivity.java18
-rw-r--r--packages/SystemUI/src/com/android/systemui/usb/UsbPermissionActivity.java18
-rw-r--r--packages/SystemUI/src/com/android/systemui/util/InjectionInflationController.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/util/NotificationChannels.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/util/leak/DumpTruck.java19
-rw-r--r--packages/SystemUI/src/com/android/systemui/util/leak/GarbageMonitor.java134
-rwxr-xr-xpackages/SystemUI/src/com/android/systemui/util/sensors/AsyncSensorManager.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/util/sensors/ProximitySensor.java23
-rw-r--r--packages/SystemUI/src/com/android/systemui/util/wakelock/DelayedWakeLock.java45
-rw-r--r--packages/SystemUI/src/com/android/systemui/volume/VolumeDialogComponent.java17
-rw-r--r--packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java13
-rw-r--r--packages/SystemUI/src/com/android/systemui/volume/VolumeUI.java14
282 files changed, 10965 insertions, 4433 deletions
diff --git a/packages/SystemUI/src/com/android/keyguard/CarrierTextController.java b/packages/SystemUI/src/com/android/keyguard/CarrierTextController.java
index 3410883efac7..7cc16cf014fd 100644
--- a/packages/SystemUI/src/com/android/keyguard/CarrierTextController.java
+++ b/packages/SystemUI/src/com/android/keyguard/CarrierTextController.java
@@ -35,6 +35,7 @@ import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.Log;
+import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
import com.android.internal.telephony.IccCardConstants;
@@ -59,6 +60,7 @@ public class CarrierTextController {
private static final String TAG = "CarrierTextController";
private final boolean mIsEmergencyCallCapable;
+ private final Handler mMainHandler;
private boolean mTelephonyCapable;
private boolean mShowMissingSim;
private boolean mShowAirplaneMode;
@@ -67,6 +69,7 @@ public class CarrierTextController {
private WifiManager mWifiManager;
private boolean[] mSimErrorState;
private final int mSimSlotsNumber;
+ @Nullable // Check for nullability before dispatching
private CarrierTextCallback mCarrierTextCallback;
private Context mContext;
private CharSequence mSeparator;
@@ -76,12 +79,12 @@ public class CarrierTextController {
new WakefulnessLifecycle.Observer() {
@Override
public void onFinishedWakingUp() {
- mCarrierTextCallback.finishedWakingUp();
+ if (mCarrierTextCallback != null) mCarrierTextCallback.finishedWakingUp();
}
@Override
public void onStartedGoingToSleep() {
- mCarrierTextCallback.startedGoingToSleep();
+ if (mCarrierTextCallback != null) mCarrierTextCallback.startedGoingToSleep();
}
};
@@ -170,8 +173,9 @@ public class CarrierTextController {
mSeparator = separator;
mWakefulnessLifecycle = Dependency.get(WakefulnessLifecycle.class);
mSimSlotsNumber = ((TelephonyManager) context.getSystemService(
- Context.TELEPHONY_SERVICE)).getPhoneCount();
+ Context.TELEPHONY_SERVICE)).getSupportedModemCount();
mSimErrorState = new boolean[mSimSlotsNumber];
+ mMainHandler = Dependency.get(Dependency.MAIN_HANDLER);
}
/**
@@ -230,7 +234,12 @@ public class CarrierTextController {
if (whitelistIpcs(() -> ConnectivityManager.from(mContext).isNetworkSupported(
ConnectivityManager.TYPE_MOBILE))) {
mKeyguardUpdateMonitor = Dependency.get(KeyguardUpdateMonitor.class);
- mKeyguardUpdateMonitor.registerCallback(mCallback);
+ // Keyguard update monitor expects callbacks from main thread
+ mMainHandler.post(() -> {
+ if (mKeyguardUpdateMonitor != null) {
+ mKeyguardUpdateMonitor.registerCallback(mCallback);
+ }
+ });
mWakefulnessLifecycle.addObserver(mWakefulnessObserver);
telephonyManager.listen(mPhoneStateListener,
LISTEN_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGE);
@@ -242,7 +251,12 @@ public class CarrierTextController {
} else {
mCarrierTextCallback = null;
if (mKeyguardUpdateMonitor != null) {
- mKeyguardUpdateMonitor.removeCallback(mCallback);
+ // Keyguard update monitor expects callbacks from main thread
+ mMainHandler.post(() -> {
+ if (mKeyguardUpdateMonitor != null) {
+ mKeyguardUpdateMonitor.removeCallback(mCallback);
+ }
+ });
mWakefulnessLifecycle.removeObserver(mWakefulnessObserver);
}
telephonyManager.listen(mPhoneStateListener, LISTEN_NONE);
@@ -374,10 +388,9 @@ public class CarrierTextController {
@VisibleForTesting
protected void postToCallback(CarrierTextCallbackInfo info) {
- Handler handler = Dependency.get(Dependency.MAIN_HANDLER);
final CarrierTextCallback callback = mCarrierTextCallback;
if (callback != null) {
- handler.post(() -> callback.updateCarrierInfo(info));
+ mMainHandler.post(() -> callback.updateCarrierInfo(info));
}
}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputView.java
index 6cc881dc5320..6f955f936c9a 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputView.java
@@ -33,10 +33,9 @@ import android.widget.LinearLayout;
import com.android.internal.util.LatencyTracker;
import com.android.internal.widget.LockPatternChecker;
import com.android.internal.widget.LockPatternUtils;
+import com.android.internal.widget.LockscreenCredential;
import com.android.systemui.R;
-import java.util.Arrays;
-
/**
* Base class for PIN and password unlock screens.
*/
@@ -132,19 +131,19 @@ public abstract class KeyguardAbsKeyInputView extends LinearLayout
protected void verifyPasswordAndUnlock() {
if (mDismissing) return; // already verified but haven't been dismissed; don't do it again.
- final byte[] entry = getPasswordText();
+ final LockscreenCredential password = getEnteredCredential();
setPasswordEntryInputEnabled(false);
if (mPendingLockCheck != null) {
mPendingLockCheck.cancel(false);
}
final int userId = KeyguardUpdateMonitor.getCurrentUser();
- if (entry.length <= MINIMUM_PASSWORD_LENGTH_BEFORE_REPORT) {
+ if (password.size() <= MINIMUM_PASSWORD_LENGTH_BEFORE_REPORT) {
// to avoid accidental lockout, only count attempts that are long enough to be a
// real password. This may require some tweaking.
setPasswordEntryInputEnabled(true);
onPasswordChecked(userId, false /* matched */, 0, false /* not valid - too short */);
- Arrays.fill(entry, (byte) 0);
+ password.zeroize();
return;
}
@@ -152,9 +151,9 @@ public abstract class KeyguardAbsKeyInputView extends LinearLayout
LatencyTracker.getInstance(mContext).onActionStart(ACTION_CHECK_CREDENTIAL);
LatencyTracker.getInstance(mContext).onActionStart(ACTION_CHECK_CREDENTIAL_UNLOCKED);
}
- mPendingLockCheck = LockPatternChecker.checkPassword(
+ mPendingLockCheck = LockPatternChecker.checkCredential(
mLockPatternUtils,
- entry,
+ password,
userId,
new LockPatternChecker.OnCheckCallback() {
@@ -166,7 +165,7 @@ public abstract class KeyguardAbsKeyInputView extends LinearLayout
}
onPasswordChecked(userId, true /* matched */, 0 /* timeoutMs */,
true /* isValidPassword */);
- Arrays.fill(entry, (byte) 0);
+ password.zeroize();
}
@Override
@@ -181,7 +180,7 @@ public abstract class KeyguardAbsKeyInputView extends LinearLayout
onPasswordChecked(userId, false /* matched */, timeoutMs,
true /* isValidPassword */);
}
- Arrays.fill(entry, (byte) 0);
+ password.zeroize();
}
@Override
@@ -192,7 +191,7 @@ public abstract class KeyguardAbsKeyInputView extends LinearLayout
LatencyTracker.getInstance(mContext).onActionEnd(
ACTION_CHECK_CREDENTIAL_UNLOCKED);
}
- Arrays.fill(entry, (byte) 0);
+ password.zeroize();
}
});
}
@@ -224,7 +223,7 @@ public abstract class KeyguardAbsKeyInputView extends LinearLayout
}
protected abstract void resetPasswordText(boolean animate, boolean announce);
- protected abstract byte[] getPasswordText();
+ protected abstract LockscreenCredential getEnteredCredential();
protected abstract void setPasswordEntryEnabled(boolean enabled);
protected abstract void setPasswordEntryInputEnabled(boolean enabled);
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java
index eaaa3ed78654..f8f3dc8d6ecd 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java
@@ -36,6 +36,7 @@ import android.view.inputmethod.InputMethodSubtype;
import android.widget.TextView;
import android.widget.TextView.OnEditorActionListener;
+import com.android.internal.widget.LockscreenCredential;
import com.android.internal.widget.TextViewInputDisabler;
import com.android.systemui.R;
@@ -86,13 +87,12 @@ public class KeyguardPasswordView extends KeyguardAbsKeyInputView
mSecurityMessageDisplay.setMessage("");
}
final boolean wasDisabled = mPasswordEntry.isEnabled();
- // Don't set enabled password entry & showSoftInput when PasswordEntry is invisible or in
- // pausing stage.
+ setPasswordEntryEnabled(true);
+ setPasswordEntryInputEnabled(true);
+ // Don't call showSoftInput when PasswordEntry is invisible or in pausing stage.
if (!mResumed || !mPasswordEntry.isVisibleToUser()) {
return;
}
- setPasswordEntryEnabled(true);
- setPasswordEntryInputEnabled(true);
if (wasDisabled) {
mImm.showSoftInput(mPasswordEntry, InputMethodManager.SHOW_IMPLICIT);
}
@@ -244,8 +244,8 @@ public class KeyguardPasswordView extends KeyguardAbsKeyInputView
}
@Override
- protected byte[] getPasswordText() {
- return charSequenceToByteArray(mPasswordEntry.getText());
+ protected LockscreenCredential getEnteredCredential() {
+ return LockscreenCredential.createPasswordOrNone(mPasswordEntry.getText());
}
@Override
@@ -380,18 +380,4 @@ public class KeyguardPasswordView extends KeyguardAbsKeyInputView
return getContext().getString(
com.android.internal.R.string.keyguard_accessibility_password_unlock);
}
-
- /*
- * This method avoids creating a new string when getting a byte array from EditView#getText().
- */
- private static byte[] charSequenceToByteArray(CharSequence chars) {
- if (chars == null) {
- return null;
- }
- byte[] bytes = new byte[chars.length()];
- for (int i = 0; i < chars.length(); i++) {
- bytes[i] = (byte) chars.charAt(i);
- }
- return bytes;
- }
}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPatternView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPatternView.java
index 9c0688e20aa0..ef48a530e914 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardPatternView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPatternView.java
@@ -39,6 +39,7 @@ import com.android.internal.util.LatencyTracker;
import com.android.internal.widget.LockPatternChecker;
import com.android.internal.widget.LockPatternUtils;
import com.android.internal.widget.LockPatternView;
+import com.android.internal.widget.LockscreenCredential;
import com.android.settingslib.animation.AppearAnimationCreator;
import com.android.settingslib.animation.AppearAnimationUtils;
import com.android.settingslib.animation.DisappearAnimationUtils;
@@ -297,9 +298,9 @@ public class KeyguardPatternView extends LinearLayout implements KeyguardSecurit
LatencyTracker.getInstance(mContext).onActionStart(ACTION_CHECK_CREDENTIAL);
LatencyTracker.getInstance(mContext).onActionStart(ACTION_CHECK_CREDENTIAL_UNLOCKED);
}
- mPendingLockCheck = LockPatternChecker.checkPattern(
+ mPendingLockCheck = LockPatternChecker.checkCredential(
mLockPatternUtils,
- pattern,
+ LockscreenCredential.createPattern(pattern),
userId,
new LockPatternChecker.OnCheckCallback() {
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputView.java
index 274f739d8c29..c67deccb1f62 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputView.java
@@ -23,6 +23,7 @@ import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
+import com.android.internal.widget.LockscreenCredential;
import com.android.systemui.R;
/**
@@ -167,8 +168,8 @@ public abstract class KeyguardPinBasedInputView extends KeyguardAbsKeyInputView
}
@Override
- protected byte[] getPasswordText() {
- return charSequenceToByteArray(mPasswordEntry.getText());
+ protected LockscreenCredential getEnteredCredential() {
+ return LockscreenCredential.createPinOrNone(mPasswordEntry.getText());
}
@Override
@@ -266,18 +267,4 @@ public abstract class KeyguardPinBasedInputView extends KeyguardAbsKeyInputView
return getContext().getString(
com.android.internal.R.string.keyguard_accessibility_pin_unlock);
}
-
- /*
- * This method avoids creating a new string when getting a byte array from EditView#getText().
- */
- private static byte[] charSequenceToByteArray(CharSequence chars) {
- if (chars == null) {
- return null;
- }
- byte[] bytes = new byte[chars.length()];
- for (int i = 0; i < chars.length(); i++) {
- bytes[i] = (byte) chars.charAt(i);
- }
- return bytes;
- }
}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
index 35eb272bdaef..b9fe9334d14c 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
@@ -49,7 +49,7 @@ import com.android.keyguard.KeyguardSecurityModel.SecurityMode;
import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.SystemUIFactory;
-import com.android.systemui.statusbar.phone.UnlockMethodCache;
+import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.util.InjectionInflationController;
public class KeyguardSecurityContainer extends FrameLayout implements KeyguardSecurityView {
@@ -76,7 +76,7 @@ public class KeyguardSecurityContainer extends FrameLayout implements KeyguardSe
// How much you need to drag the bouncer to trigger an auth retry (in dps.)
private static final float MIN_DRAG_SIZE = 10;
// How much to scale the default slop by, to avoid accidental drags.
- private static final float SLOP_SCALE = 2f;
+ private static final float SLOP_SCALE = 4f;
private KeyguardSecurityModel mSecurityModel;
private LockPatternUtils mLockPatternUtils;
@@ -94,7 +94,7 @@ public class KeyguardSecurityContainer extends FrameLayout implements KeyguardSe
private final SpringAnimation mSpringAnimation;
private final VelocityTracker mVelocityTracker = VelocityTracker.obtain();
private final KeyguardUpdateMonitor mUpdateMonitor;
- private final UnlockMethodCache mUnlockMethodCache;
+ private final KeyguardStateController mKeyguardStateController;
private final MetricsLogger mMetricsLogger = Dependency.get(MetricsLogger.class);
private float mLastTouchY = -1;
@@ -128,14 +128,14 @@ public class KeyguardSecurityContainer extends FrameLayout implements KeyguardSe
public KeyguardSecurityContainer(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
- mSecurityModel = new KeyguardSecurityModel(context);
+ mSecurityModel = Dependency.get(KeyguardSecurityModel.class);
mLockPatternUtils = new LockPatternUtils(context);
mUpdateMonitor = Dependency.get(KeyguardUpdateMonitor.class);
mSpringAnimation = new SpringAnimation(this, DynamicAnimation.Y);
mInjectionInflationController = new InjectionInflationController(
SystemUIFactory.getInstance().getRootComponent());
- mUnlockMethodCache = UnlockMethodCache.getInstance(context);
mViewConfiguration = ViewConfiguration.get(context);
+ mKeyguardStateController = Dependency.get(KeyguardStateController.class);
}
public void setSecurityCallback(SecurityCallback callback) {
@@ -272,7 +272,7 @@ public class KeyguardSecurityContainer extends FrameLayout implements KeyguardSe
*/
private void updateBiometricRetry() {
SecurityMode securityMode = getSecurityMode();
- mSwipeUpToRetry = mUnlockMethodCache.isFaceAuthEnabled()
+ mSwipeUpToRetry = mKeyguardStateController.isFaceAuthEnabled()
&& securityMode != SecurityMode.SimPin
&& securityMode != SecurityMode.SimPuk
&& securityMode != SecurityMode.None;
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityModel.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityModel.java
index bb89959b7a11..1395fd9e3482 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityModel.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityModel.java
@@ -25,6 +25,10 @@ import com.android.internal.telephony.IccCardConstants;
import com.android.internal.widget.LockPatternUtils;
import com.android.systemui.Dependency;
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+@Singleton
public class KeyguardSecurityModel {
/**
@@ -46,6 +50,7 @@ public class KeyguardSecurityModel {
private LockPatternUtils mLockPatternUtils;
+ @Inject
KeyguardSecurityModel(Context context) {
mContext = context;
mLockPatternUtils = new LockPatternUtils(context);
@@ -57,7 +62,7 @@ public class KeyguardSecurityModel {
mLockPatternUtils = utils;
}
- SecurityMode getSecurityMode(int userId) {
+ public SecurityMode getSecurityMode(int userId) {
KeyguardUpdateMonitor monitor = Dependency.get(KeyguardUpdateMonitor.class);
if (mIsPukScreenAvailable && SubscriptionManager.isValidSubscriptionId(
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java
index af4e61b3f6bc..5d35169cf926 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java
@@ -31,6 +31,7 @@ import android.app.PendingIntent;
import android.content.Context;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
+import android.graphics.text.LineBreaker;
import android.net.Uri;
import android.os.Trace;
import android.provider.Settings;
@@ -152,6 +153,7 @@ public class KeyguardSliceView extends LinearLayout implements View.OnClickListe
mRowWithHeaderTextSize = mContext.getResources().getDimensionPixelSize(
R.dimen.header_row_font_size);
mTitle.setOnClickListener(this);
+ mTitle.setBreakStrategy(LineBreaker.BREAK_STRATEGY_BALANCED);
}
@Override
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
index 63da5339efe7..5a1c9976f021 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
@@ -22,7 +22,6 @@ import android.content.Context;
import android.content.res.Resources;
import android.graphics.Color;
import android.os.Handler;
-import android.os.Looper;
import android.os.RemoteException;
import android.os.UserHandle;
import android.text.TextUtils;
@@ -135,7 +134,7 @@ public class KeyguardStatusView extends GridLayout implements
super(context, attrs, defStyle);
mIActivityManager = ActivityManager.getService();
mLockPatternUtils = new LockPatternUtils(getContext());
- mHandler = new Handler(Looper.myLooper());
+ mHandler = new Handler();
onDensityOrFontScaleChanged();
}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index f2a359e67e29..e73a27bb4eb2 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -39,7 +39,6 @@ import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STR
import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_TIMEOUT;
import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN;
import static com.android.systemui.DejankUtils.whitelistIpcs;
-import static com.android.systemui.Dependency.MAIN_LOOPER_NAME;
import android.annotation.AnyThread;
import android.annotation.MainThread;
@@ -58,6 +57,7 @@ import android.content.IntentFilter;
import android.content.pm.IPackageManager;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
+import android.content.pm.UserInfo;
import android.database.ContentObserver;
import android.hardware.biometrics.BiometricManager;
import android.hardware.biometrics.BiometricSourceType;
@@ -98,7 +98,9 @@ import com.android.internal.telephony.PhoneConstants;
import com.android.internal.telephony.TelephonyIntents;
import com.android.internal.widget.LockPatternUtils;
import com.android.settingslib.WirelessUtils;
+import com.android.systemui.DejankUtils;
import com.android.systemui.R;
+import com.android.systemui.dagger.qualifiers.MainLooper;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.TaskStackChangeListener;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
@@ -116,13 +118,14 @@ import java.util.TimeZone;
import java.util.function.Consumer;
import javax.inject.Inject;
-import javax.inject.Named;
+import javax.inject.Singleton;
/**
* Watches for updates that may be interesting to the keyguard, and provides
* the up to date information as well as a registration for callbacks that care
* to be updated.
*/
+@Singleton
public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
private static final String TAG = "KeyguardUpdateMonitor";
@@ -219,7 +222,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
private final Context mContext;
private final boolean mIsPrimaryUser;
- HashMap<Integer, SimData> mSimDatas = new HashMap<Integer, SimData>();
+ HashMap<Integer, SimData> mSimDatas = new HashMap<>();
HashMap<Integer, ServiceState> mServiceStates = new HashMap<Integer, ServiceState>();
private int mRingMode;
@@ -329,6 +332,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
private SparseBooleanArray mUserIsUnlocked = new SparseBooleanArray();
private SparseBooleanArray mUserHasTrust = new SparseBooleanArray();
private SparseBooleanArray mUserTrustIsManaged = new SparseBooleanArray();
+ private SparseBooleanArray mUserTrustIsUsuallyManaged = new SparseBooleanArray();
private SparseBooleanArray mUserFingerprintAuthenticated = new SparseBooleanArray();
private SparseBooleanArray mUserFaceAuthenticated = new SparseBooleanArray();
private SparseBooleanArray mUserFaceUnlockRunning = new SparseBooleanArray();
@@ -472,6 +476,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
public void onTrustManagedChanged(boolean managed, int userId) {
checkIsHandlerThread();
mUserTrustIsManaged.put(userId, managed);
+ mUserTrustIsUsuallyManaged.put(userId, mTrustManager.isTrustUsuallyManaged(userId));
for (int i = 0; i < mCallbacks.size(); i++) {
KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
if (cb != null) {
@@ -925,6 +930,14 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
return mUserTrustIsManaged.get(userId) && !isTrustDisabled(userId);
}
+ /**
+ * Cached version of {@link TrustManager#isTrustUsuallyManaged(int)}.
+ */
+ public boolean isTrustUsuallyManaged(int userId) {
+ checkIsHandlerThread();
+ return mUserTrustIsUsuallyManaged.get(userId);
+ }
+
public boolean isUnlockingWithBiometricAllowed() {
return mStrongAuthTracker.isUnlockingWithBiometricAllowed();
}
@@ -1424,6 +1437,8 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
}
private void handleScreenTurnedOff() {
+ final String tag = "KeyguardUpdateMonitor#handleScreenTurnedOff";
+ DejankUtils.startDetectingBlockingIpcs(tag);
checkIsHandlerThread();
mHardwareFingerprintUnavailableRetryCount = 0;
mHardwareFaceUnavailableRetryCount = 0;
@@ -1433,6 +1448,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
cb.onScreenTurnedOff();
}
}
+ DejankUtils.stopDetectingBlockingIpcs(tag);
}
private void handleDreamingStateChanged(int dreamStart) {
@@ -1474,14 +1490,16 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
mUserIsUnlocked.put(userId, mUserManager.isUserUnlocked(userId));
}
- private void handleUserRemoved(int userId) {
+ @VisibleForTesting
+ void handleUserRemoved(int userId) {
checkIsHandlerThread();
mUserIsUnlocked.delete(userId);
+ mUserTrustIsUsuallyManaged.delete(userId);
}
@VisibleForTesting
@Inject
- protected KeyguardUpdateMonitor(Context context, @Named(MAIN_LOOPER_NAME) Looper mainLooper) {
+ protected KeyguardUpdateMonitor(Context context, @MainLooper Looper mainLooper) {
mContext = context;
mSubscriptionManager = SubscriptionManager.from(context);
mDeviceProvisioned = isDeviceProvisionedInSettingsDb();
@@ -1662,7 +1680,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
e.rethrowAsRuntimeException();
}
- mTrustManager = (TrustManager) context.getSystemService(Context.TRUST_SERVICE);
+ mTrustManager = context.getSystemService(TrustManager.class);
mTrustManager.registerTrustListener(this);
mLockPatternUtils = new LockPatternUtils(context);
mLockPatternUtils.registerStrongAuthTracker(mStrongAuthTracker);
@@ -1697,6 +1715,11 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
mUserIsUnlocked.put(user, mUserManager.isUserUnlocked(user));
mDevicePolicyManager = context.getSystemService(DevicePolicyManager.class);
mLogoutEnabled = mDevicePolicyManager.isLogoutEnabled();
+ List<UserInfo> allUsers = mUserManager.getUsers();
+ for (UserInfo userInfo : allUsers) {
+ mUserTrustIsUsuallyManaged.put(userInfo.id,
+ mTrustManager.isTrustUsuallyManaged(userInfo.id));
+ }
updateAirplaneModeState();
TelephonyManager telephony =
@@ -2048,6 +2071,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
*/
private void handleUserSwitching(int userId, IRemoteCallback reply) {
checkIsHandlerThread();
+ mUserTrustIsUsuallyManaged.put(userId, mTrustManager.isTrustUsuallyManaged(userId));
for (int i = 0; i < mCallbacks.size(); i++) {
KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
if (cb != null) {
@@ -2522,8 +2546,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
@MainThread
public void reportSimUnlocked(int subId) {
if (DEBUG_SIM_STATES) Log.v(TAG, "reportSimUnlocked(subId=" + subId + ")");
- int slotId = SubscriptionManager.getSlotIndex(subId);
- handleSimStateChange(subId, slotId, State.READY);
+ handleSimStateChange(subId, getSlotId(subId), State.READY);
}
/**
@@ -2596,6 +2619,13 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
}
}
+ private int getSlotId(int subId) {
+ if (!mSimDatas.containsKey(subId)) {
+ refreshSimState(subId, SubscriptionManager.getSlotIndex(subId));
+ }
+ return mSimDatas.get(subId).slotId;
+ }
+
private final TaskStackChangeListener
mTaskStackListener = new TaskStackChangeListener() {
@Override
@@ -2750,7 +2780,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
for (int i = 0; i < list.size(); i++) {
final SubscriptionInfo info = list.get(i);
final int id = info.getSubscriptionId();
- int slotId = SubscriptionManager.getSlotIndex(id);
+ int slotId = getSlotId(id);
if (state == getSimState(id) && bestSlotId > slotId) {
resultId = id;
bestSlotId = slotId;
@@ -2792,7 +2822,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
private void checkIsHandlerThread() {
if (!mHandler.getLooper().isCurrentThread()) {
- Log.wtf(TAG, "must call on mHandler's thread "
+ Log.wtfStack(TAG, "must call on mHandler's thread "
+ mHandler.getLooper().getThread() + ", not " + Thread.currentThread());
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/Dependency.java b/packages/SystemUI/src/com/android/systemui/Dependency.java
index 7771f8655128..486d02c207db 100644
--- a/packages/SystemUI/src/com/android/systemui/Dependency.java
+++ b/packages/SystemUI/src/com/android/systemui/Dependency.java
@@ -17,6 +17,7 @@ package com.android.systemui;
import android.annotation.Nullable;
import android.app.AlarmManager;
import android.app.INotificationManager;
+import android.app.IWallpaperManager;
import android.content.res.Configuration;
import android.hardware.SensorPrivacyManager;
import android.hardware.display.NightDisplayListener;
@@ -30,6 +31,7 @@ import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.statusbar.IStatusBarService;
import com.android.internal.util.Preconditions;
+import com.android.keyguard.KeyguardSecurityModel;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.keyguard.clock.ClockManager;
import com.android.settingslib.bluetooth.LocalBluetoothManager;
@@ -38,6 +40,10 @@ import com.android.systemui.assist.AssistManager;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.bubbles.BubbleController;
import com.android.systemui.colorextraction.SysuiColorExtractor;
+import com.android.systemui.dagger.qualifiers.BgHandler;
+import com.android.systemui.dagger.qualifiers.BgLooper;
+import com.android.systemui.dagger.qualifiers.MainHandler;
+import com.android.systemui.dagger.qualifiers.MainLooper;
import com.android.systemui.dock.DockManager;
import com.android.systemui.fragments.FragmentService;
import com.android.systemui.keyguard.ScreenLifecycle;
@@ -76,6 +82,7 @@ import com.android.systemui.statusbar.notification.row.ChannelEditorDialogContro
import com.android.systemui.statusbar.notification.row.NotificationBlockingHelperManager;
import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
import com.android.systemui.statusbar.phone.AutoHideController;
+import com.android.systemui.statusbar.phone.DozeParameters;
import com.android.systemui.statusbar.phone.KeyguardDismissUtil;
import com.android.systemui.statusbar.phone.LightBarController;
import com.android.systemui.statusbar.phone.LockscreenGestureLogger;
@@ -97,7 +104,7 @@ import com.android.systemui.statusbar.policy.DeviceProvisionedController;
import com.android.systemui.statusbar.policy.ExtensionController;
import com.android.systemui.statusbar.policy.FlashlightController;
import com.android.systemui.statusbar.policy.HotspotController;
-import com.android.systemui.statusbar.policy.KeyguardMonitor;
+import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.statusbar.policy.LocationController;
import com.android.systemui.statusbar.policy.NetworkController;
import com.android.systemui.statusbar.policy.NextAlarmController;
@@ -145,16 +152,16 @@ public class Dependency {
/**
* Key for getting a the main looper.
*/
- public static final String MAIN_LOOPER_NAME = "main_looper";
+ private static final String MAIN_LOOPER_NAME = "main_looper";
/**
* Key for getting a background Looper for background work.
*/
- public static final String BG_LOOPER_NAME = "background_looper";
+ private static final String BG_LOOPER_NAME = "background_looper";
/**
* Key for getting a background Handler for background work.
*/
- public static final String BG_HANDLER_NAME = "background_handler";
+ private static final String BG_HANDLER_NAME = "background_handler";
/**
* Key for getting a Handler for receiving time tick broadcasts on.
*/
@@ -162,7 +169,7 @@ public class Dependency {
/**
* Generic handler on the main thread.
*/
- public static final String MAIN_HANDLER_NAME = "main_handler";
+ private static final String MAIN_HANDLER_NAME = "main_handler";
/**
* An email address to send memory leak reports to by default.
@@ -221,7 +228,7 @@ public class Dependency {
@Inject Lazy<FlashlightController> mFlashlightController;
@Inject Lazy<UserSwitcherController> mUserSwitcherController;
@Inject Lazy<UserInfoController> mUserInfoController;
- @Inject Lazy<KeyguardMonitor> mKeyguardMonitor;
+ @Inject Lazy<KeyguardStateController> mKeyguardMonitor;
@Inject Lazy<KeyguardUpdateMonitor> mKeyguardUpdateMonitor;
@Inject Lazy<BatteryController> mBatteryController;
@Inject Lazy<NightDisplayListener> mNightDisplayListener;
@@ -297,10 +304,10 @@ public class Dependency {
@Inject Lazy<AutoHideController> mAutoHideController;
@Inject Lazy<ForegroundServiceNotificationListener> mForegroundServiceNotificationListener;
@Inject Lazy<PrivacyItemController> mPrivacyItemController;
- @Inject @Named(BG_LOOPER_NAME) Lazy<Looper> mBgLooper;
- @Inject @Named(BG_HANDLER_NAME) Lazy<Handler> mBgHandler;
- @Inject @Named(MAIN_LOOPER_NAME) Lazy<Looper> mMainLooper;
- @Inject @Named(MAIN_HANDLER_NAME) Lazy<Handler> mMainHandler;
+ @Inject @BgLooper Lazy<Looper> mBgLooper;
+ @Inject @BgHandler Lazy<Handler> mBgHandler;
+ @Inject @MainLooper Lazy<Looper> mMainLooper;
+ @Inject @MainHandler Lazy<Handler> mMainHandler;
@Inject @Named(TIME_TICK_HANDLER_NAME) Lazy<Handler> mTimeTickHandler;
@Nullable
@Inject @Named(LEAK_REPORT_EMAIL_NAME) Lazy<String> mLeakReportEmail;
@@ -316,6 +323,9 @@ public class Dependency {
@Inject Lazy<FalsingManager> mFalsingManager;
@Inject Lazy<SysUiState> mSysUiStateFlagsContainer;
@Inject Lazy<AlarmManager> mAlarmManager;
+ @Inject Lazy<KeyguardSecurityModel> mKeyguardSecurityModel;
+ @Inject Lazy<DozeParameters> mDozeParameters;
+ @Inject Lazy<IWallpaperManager> mWallpaperManager;
@Inject
public Dependency() {
@@ -355,7 +365,7 @@ public class Dependency {
mProviders.put(FlashlightController.class, mFlashlightController::get);
- mProviders.put(KeyguardMonitor.class, mKeyguardMonitor::get);
+ mProviders.put(KeyguardStateController.class, mKeyguardMonitor::get);
mProviders.put(KeyguardUpdateMonitor.class, mKeyguardUpdateMonitor::get);
@@ -501,6 +511,9 @@ public class Dependency {
mProviders.put(FalsingManager.class, mFalsingManager::get);
mProviders.put(SysUiState.class, mSysUiStateFlagsContainer::get);
mProviders.put(AlarmManager.class, mAlarmManager::get);
+ mProviders.put(KeyguardSecurityModel.class, mKeyguardSecurityModel::get);
+ mProviders.put(DozeParameters.class, mDozeParameters::get);
+ mProviders.put(IWallpaperManager.class, mWallpaperManager::get);
// TODO(b/118592525): to support multi-display , we start to add something which is
// per-display, while others may be global. I think it's time to add
diff --git a/packages/SystemUI/src/com/android/systemui/ForegroundServiceLifetimeExtender.java b/packages/SystemUI/src/com/android/systemui/ForegroundServiceLifetimeExtender.java
index 0e079e36a175..362014f51e36 100644
--- a/packages/SystemUI/src/com/android/systemui/ForegroundServiceLifetimeExtender.java
+++ b/packages/SystemUI/src/com/android/systemui/ForegroundServiceLifetimeExtender.java
@@ -50,13 +50,13 @@ public class ForegroundServiceLifetimeExtender implements NotificationLifetimeEx
@Override
public boolean shouldExtendLifetime(@NonNull NotificationEntry entry) {
- if ((entry.notification.getNotification().flags
+ if ((entry.getSbn().getNotification().flags
& Notification.FLAG_FOREGROUND_SERVICE) == 0) {
return false;
}
long currentTime = System.currentTimeMillis();
- return currentTime - entry.notification.getPostTime() < MIN_FGS_TIME_MS;
+ return currentTime - entry.getSbn().getPostTime() < MIN_FGS_TIME_MS;
}
@Override
@@ -79,11 +79,13 @@ public class ForegroundServiceLifetimeExtender implements NotificationLifetimeEx
if (mManagedEntries.contains(entry)) {
mManagedEntries.remove(entry);
if (mNotificationSafeToRemoveCallback != null) {
- mNotificationSafeToRemoveCallback.onSafeToRemove(entry.key);
+ mNotificationSafeToRemoveCallback.onSafeToRemove(entry.getKey());
}
}
};
- mHandler.postDelayed(r, MIN_FGS_TIME_MS);
+ long delayAmt = MIN_FGS_TIME_MS
+ - (System.currentTimeMillis() - entry.getSbn().getPostTime());
+ mHandler.postDelayed(r, delayAmt);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/ForegroundServiceNotificationListener.java b/packages/SystemUI/src/com/android/systemui/ForegroundServiceNotificationListener.java
index f9d877142d21..4a3b6df6ac90 100644
--- a/packages/SystemUI/src/com/android/systemui/ForegroundServiceNotificationListener.java
+++ b/packages/SystemUI/src/com/android/systemui/ForegroundServiceNotificationListener.java
@@ -50,12 +50,12 @@ public class ForegroundServiceNotificationListener {
notificationEntryManager.addNotificationEntryListener(new NotificationEntryListener() {
@Override
public void onPendingEntryAdded(NotificationEntry entry) {
- addNotification(entry.notification, entry.getImportance());
+ addNotification(entry.getSbn(), entry.getImportance());
}
@Override
public void onPostEntryUpdated(NotificationEntry entry) {
- updateNotification(entry.notification, entry.getImportance());
+ updateNotification(entry.getSbn(), entry.getImportance());
}
@Override
@@ -63,7 +63,7 @@ public class ForegroundServiceNotificationListener {
NotificationEntry entry,
NotificationVisibility visibility,
boolean removedByUser) {
- removeNotification(entry.notification);
+ removeNotification(entry.getSbn());
}
});
diff --git a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
index bd91333100bd..29a7167394ae 100644
--- a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
+++ b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
@@ -20,6 +20,7 @@ import android.app.ActivityManager;
import android.content.Context;
import android.graphics.Rect;
import android.os.HandlerThread;
+import android.os.Trace;
import android.service.wallpaper.WallpaperService;
import android.util.Log;
import android.util.Size;
@@ -37,6 +38,8 @@ import com.android.systemui.statusbar.phone.DozeParameters;
import java.io.FileDescriptor;
import java.io.PrintWriter;
+import javax.inject.Inject;
+
/**
* Default built-in wallpaper that simply shows a static image.
*/
@@ -48,8 +51,16 @@ public class ImageWallpaper extends WallpaperService {
private static final int DELAY_FINISH_RENDERING = 1000;
private static final int INTERVAL_WAIT_FOR_RENDERING = 100;
private static final int PATIENCE_WAIT_FOR_RENDERING = 10;
+ private static final boolean DEBUG = true;
+ private final DozeParameters mDozeParameters;
private HandlerThread mWorker;
+ @Inject
+ public ImageWallpaper(DozeParameters dozeParameters) {
+ super();
+ mDozeParameters = dozeParameters;
+ }
+
@Override
public void onCreate() {
super.onCreate();
@@ -59,7 +70,7 @@ public class ImageWallpaper extends WallpaperService {
@Override
public Engine onCreateEngine() {
- return new GLEngine(this);
+ return new GLEngine(this, mDozeParameters);
}
@Override
@@ -87,9 +98,9 @@ public class ImageWallpaper extends WallpaperService {
// This variable can only be accessed in synchronized block.
private boolean mWaitingForRendering;
- GLEngine(Context context) {
+ GLEngine(Context context, DozeParameters dozeParameters) {
mNeedTransition = ActivityManager.isHighEndGfx()
- && !DozeParameters.getInstance(context).getDisplayNeedsBlanking();
+ && !dozeParameters.getDisplayNeedsBlanking();
// We will preserve EGL context when we are in lock screen or aod
// to avoid janking in following transition, we need to release when back to home.
@@ -125,6 +136,10 @@ public class ImageWallpaper extends WallpaperService {
@Override
public void onAmbientModeChanged(boolean inAmbientMode, long animationDuration) {
if (!mNeedTransition) return;
+ if (DEBUG) {
+ Log.d(TAG, "onAmbientModeChanged: inAmbient=" + inAmbientMode
+ + ", duration=" + animationDuration);
+ }
mWorker.getThreadHandler().post(
() -> mRenderer.updateAmbientMode(inAmbientMode, animationDuration));
if (inAmbientMode && animationDuration == 0) {
@@ -184,17 +199,32 @@ public class ImageWallpaper extends WallpaperService {
@Override
public void onSurfaceRedrawNeeded(SurfaceHolder holder) {
+ if (DEBUG) {
+ Log.d(TAG, "onSurfaceRedrawNeeded: mNeedRedraw=" + mNeedRedraw);
+ }
+
mWorker.getThreadHandler().post(() -> {
if (mNeedRedraw) {
- preRender();
- requestRender();
- postRender();
+ drawFrame();
mNeedRedraw = false;
}
});
}
@Override
+ public void onVisibilityChanged(boolean visible) {
+ if (DEBUG) {
+ Log.d(TAG, "wallpaper visibility changes: " + visible);
+ }
+ }
+
+ private void drawFrame() {
+ preRender();
+ requestRender();
+ postRender();
+ }
+
+ @Override
public void onStatePostChange() {
// When back to home, we try to release EGL, which is preserved in lock screen or aod.
if (mController.getState() == StatusBarState.SHADE) {
@@ -205,7 +235,9 @@ public class ImageWallpaper extends WallpaperService {
@Override
public void preRender() {
// This method should only be invoked from worker thread.
+ Trace.beginSection("ImageWallpaper#preRender");
preRenderInternal();
+ Trace.endSection();
}
private void preRenderInternal() {
@@ -240,7 +272,9 @@ public class ImageWallpaper extends WallpaperService {
@Override
public void requestRender() {
// This method should only be invoked from worker thread.
+ Trace.beginSection("ImageWallpaper#requestRender");
requestRenderInternal();
+ Trace.endSection();
}
private void requestRenderInternal() {
@@ -263,8 +297,10 @@ public class ImageWallpaper extends WallpaperService {
@Override
public void postRender() {
// This method should only be invoked from worker thread.
+ Trace.beginSection("ImageWallpaper#postRender");
notifyWaitingThread();
scheduleFinishRendering();
+ Trace.endSection();
}
private void notifyWaitingThread() {
@@ -289,12 +325,14 @@ public class ImageWallpaper extends WallpaperService {
}
private void finishRendering() {
+ Trace.beginSection("ImageWallpaper#finishRendering");
if (mEglHelper != null) {
mEglHelper.destroyEglSurface();
if (!needPreserveEglContext()) {
mEglHelper.destroyEglContext();
}
}
+ Trace.endSection();
}
private boolean needPreserveEglContext() {
@@ -310,9 +348,9 @@ public class ImageWallpaper extends WallpaperService {
boolean isHighEndGfx = ActivityManager.isHighEndGfx();
out.print(prefix); out.print("isHighEndGfx="); out.println(isHighEndGfx);
- DozeParameters dozeParameters = DozeParameters.getInstance(getApplicationContext());
out.print(prefix); out.print("displayNeedsBlanking=");
- out.println(dozeParameters != null ? dozeParameters.getDisplayNeedsBlanking() : "null");
+ out.println(
+ mDozeParameters != null ? mDozeParameters.getDisplayNeedsBlanking() : "null");
out.print(prefix); out.print("mNeedTransition="); out.println(mNeedTransition);
out.print(prefix); out.print("StatusBarState=");
diff --git a/packages/SystemUI/src/com/android/systemui/LatencyTester.java b/packages/SystemUI/src/com/android/systemui/LatencyTester.java
index 50f1b44b05b1..30a60abfcd86 100644
--- a/packages/SystemUI/src/com/android/systemui/LatencyTester.java
+++ b/packages/SystemUI/src/com/android/systemui/LatencyTester.java
@@ -16,6 +16,8 @@
package com.android.systemui;
+import static android.os.PowerManager.WAKE_REASON_UNKNOWN;
+
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@@ -28,18 +30,33 @@ import android.os.SystemClock;
import com.android.internal.util.LatencyTracker;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.systemui.statusbar.phone.BiometricUnlockController;
-import com.android.systemui.statusbar.phone.StatusBar;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
/**
* Class that only runs on debuggable builds that listens to broadcasts that simulate actions in the
* system that are used for testing the latency.
*/
+@Singleton
public class LatencyTester extends SystemUI {
- private static final String ACTION_FINGERPRINT_WAKE =
+ private static final String
+ ACTION_FINGERPRINT_WAKE =
"com.android.systemui.latency.ACTION_FINGERPRINT_WAKE";
- private static final String ACTION_TURN_ON_SCREEN =
+ private static final String
+ ACTION_TURN_ON_SCREEN =
"com.android.systemui.latency.ACTION_TURN_ON_SCREEN";
+ private final BiometricUnlockController mBiometricUnlockController;
+ private final PowerManager mPowerManager;
+
+ @Inject
+ public LatencyTester(Context context, BiometricUnlockController biometricUnlockController,
+ PowerManager powerManager) {
+ super(context);
+ mBiometricUnlockController = biometricUnlockController;
+ mPowerManager = powerManager;
+ }
@Override
public void start() {
@@ -64,19 +81,17 @@ public class LatencyTester extends SystemUI {
}
private void fakeTurnOnScreen() {
- PowerManager powerManager = mContext.getSystemService(PowerManager.class);
if (LatencyTracker.isEnabled(mContext)) {
LatencyTracker.getInstance(mContext).onActionStart(
LatencyTracker.ACTION_TURN_ON_SCREEN);
}
- powerManager.wakeUp(SystemClock.uptimeMillis(), "android.policy:LATENCY_TESTS");
+ mPowerManager.wakeUp(
+ SystemClock.uptimeMillis(), WAKE_REASON_UNKNOWN, "android.policy:LATENCY_TESTS");
}
private void fakeWakeAndUnlock() {
- BiometricUnlockController biometricUnlockController = getComponent(StatusBar.class)
- .getBiometricUnlockController();
- biometricUnlockController.onBiometricAcquired(BiometricSourceType.FINGERPRINT);
- biometricUnlockController.onBiometricAuthenticated(
+ mBiometricUnlockController.onBiometricAcquired(BiometricSourceType.FINGERPRINT);
+ mBiometricUnlockController.onBiometricAuthenticated(
KeyguardUpdateMonitor.getCurrentUser(), BiometricSourceType.FINGERPRINT);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
index f38b4f259c88..ad209861d273 100644
--- a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
+++ b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
@@ -25,9 +25,6 @@ import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_M
import static com.android.systemui.tuner.TunablePadding.FLAG_END;
import static com.android.systemui.tuner.TunablePadding.FLAG_START;
-import android.animation.Animator;
-import android.animation.AnimatorSet;
-import android.animation.ObjectAnimator;
import android.annotation.Dimension;
import android.app.ActivityManager;
import android.app.Fragment;
@@ -52,7 +49,6 @@ import android.os.SystemProperties;
import android.provider.Settings.Secure;
import android.util.DisplayMetrics;
import android.util.Log;
-import android.util.MathUtils;
import android.view.DisplayCutout;
import android.view.DisplayInfo;
import android.view.Gravity;
@@ -64,9 +60,6 @@ import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.view.ViewTreeObserver;
import android.view.WindowManager;
-import android.view.animation.AccelerateInterpolator;
-import android.view.animation.Interpolator;
-import android.view.animation.PathInterpolator;
import android.widget.FrameLayout;
import android.widget.ImageView;
@@ -78,10 +71,7 @@ import com.android.systemui.fragments.FragmentHostManager;
import com.android.systemui.fragments.FragmentHostManager.FragmentListener;
import com.android.systemui.plugins.qs.QS;
import com.android.systemui.qs.SecureSetting;
-import com.android.systemui.shared.system.QuickStepContract;
import com.android.systemui.statusbar.phone.CollapsedStatusBarFragment;
-import com.android.systemui.statusbar.phone.NavigationBarTransitions;
-import com.android.systemui.statusbar.phone.NavigationModeController;
import com.android.systemui.statusbar.phone.StatusBar;
import com.android.systemui.tuner.TunablePadding;
import com.android.systemui.tuner.TunerService;
@@ -95,8 +85,7 @@ import java.util.List;
* An overlay that draws screen decorations in software (e.g for rounded corners or display cutout)
* for antialiasing and emulation purposes.
*/
-public class ScreenDecorations extends SystemUI implements Tunable,
- NavigationBarTransitions.DarkIntensityListener {
+public class ScreenDecorations extends SystemUI implements Tunable {
private static final boolean DEBUG = false;
private static final String TAG = "ScreenDecorations";
@@ -120,15 +109,11 @@ public class ScreenDecorations extends SystemUI implements Tunable,
private float mDensity;
private WindowManager mWindowManager;
private int mRotation;
- private boolean mAssistHintVisible;
private DisplayCutoutView mCutoutTop;
private DisplayCutoutView mCutoutBottom;
private SecureSetting mColorInversionSetting;
private boolean mPendingRotationChange;
private Handler mHandler;
- private boolean mAssistHintBlocked = false;
- private boolean mIsReceivingNavBarColor = false;
- private boolean mInGesturalMode;
/**
* Converts a set of {@link Rect}s into a {@link Region}
@@ -147,166 +132,15 @@ public class ScreenDecorations extends SystemUI implements Tunable,
return result;
}
+ public ScreenDecorations(Context context) {
+ super(context);
+ }
+
@Override
public void start() {
mHandler = startHandlerThread();
mHandler.post(this::startOnScreenDecorationsThread);
setupStatusBarPaddingIfNeeded();
- putComponent(ScreenDecorations.class, this);
- mInGesturalMode = QuickStepContract.isGesturalMode(
- Dependency.get(NavigationModeController.class)
- .addListener(this::handleNavigationModeChange));
- }
-
- @VisibleForTesting
- void handleNavigationModeChange(int navigationMode) {
- if (!mHandler.getLooper().isCurrentThread()) {
- mHandler.post(() -> handleNavigationModeChange(navigationMode));
- return;
- }
- boolean inGesturalMode = QuickStepContract.isGesturalMode(navigationMode);
- if (mInGesturalMode != inGesturalMode) {
- mInGesturalMode = inGesturalMode;
-
- if (mInGesturalMode && mOverlay == null) {
- setupDecorations();
- if (mOverlay != null) {
- updateLayoutParams();
- }
- }
- }
- }
-
- /**
- * Returns an animator that animates the given view from start to end over durationMs. Start and
- * end represent total animation progress: 0 is the start, 1 is the end, 1.1 would be an
- * overshoot.
- */
- Animator getHandleAnimator(View view, float start, float end, boolean isLeft, long durationMs,
- Interpolator interpolator) {
- // Note that lerp does allow overshoot, in cases where start and end are outside of [0,1].
- float scaleStart = MathUtils.lerp(2f, 1f, start);
- float scaleEnd = MathUtils.lerp(2f, 1f, end);
- Animator scaleX = ObjectAnimator.ofFloat(view, View.SCALE_X, scaleStart, scaleEnd);
- Animator scaleY = ObjectAnimator.ofFloat(view, View.SCALE_Y, scaleStart, scaleEnd);
- float translationStart = MathUtils.lerp(0.2f, 0f, start);
- float translationEnd = MathUtils.lerp(0.2f, 0f, end);
- int xDirection = isLeft ? -1 : 1;
- Animator translateX = ObjectAnimator.ofFloat(view, View.TRANSLATION_X,
- xDirection * translationStart * view.getWidth(),
- xDirection * translationEnd * view.getWidth());
- Animator translateY = ObjectAnimator.ofFloat(view, View.TRANSLATION_Y,
- translationStart * view.getHeight(), translationEnd * view.getHeight());
-
- AnimatorSet set = new AnimatorSet();
- set.play(scaleX).with(scaleY);
- set.play(scaleX).with(translateX);
- set.play(scaleX).with(translateY);
- set.setDuration(durationMs);
- set.setInterpolator(interpolator);
- return set;
- }
-
- private void fade(View view, boolean fadeIn, boolean isLeft) {
- if (fadeIn) {
- view.animate().cancel();
- view.setAlpha(1f);
- view.setVisibility(View.VISIBLE);
-
- // A piecewise spring-like interpolation.
- // End value in one animator call must match the start value in the next, otherwise
- // there will be a discontinuity.
- AnimatorSet anim = new AnimatorSet();
- Animator first = getHandleAnimator(view, 0, 1.1f, isLeft, 750,
- new PathInterpolator(0, 0.45f, .67f, 1f));
- Interpolator secondInterpolator = new PathInterpolator(0.33f, 0, 0.67f, 1f);
- Animator second = getHandleAnimator(view, 1.1f, 0.97f, isLeft, 400,
- secondInterpolator);
- Animator third = getHandleAnimator(view, 0.97f, 1.02f, isLeft, 400,
- secondInterpolator);
- Animator fourth = getHandleAnimator(view, 1.02f, 1f, isLeft, 400,
- secondInterpolator);
- anim.play(first).before(second);
- anim.play(second).before(third);
- anim.play(third).before(fourth);
- anim.start();
- } else {
- view.animate().cancel();
- view.animate()
- .setInterpolator(new AccelerateInterpolator(1.5f))
- .setDuration(250)
- .alpha(0f);
- }
-
- }
-
- /**
- * Controls the visibility of the assist gesture handles.
- *
- * @param visible whether the handles should be shown
- */
- public void setAssistHintVisible(boolean visible) {
- if (!mHandler.getLooper().isCurrentThread()) {
- mHandler.post(() -> setAssistHintVisible(visible));
- return;
- }
-
- if (mAssistHintBlocked && visible) {
- if (VERBOSE) {
- Log.v(TAG, "Assist hint blocked, cannot make it visible");
- }
- return;
- }
-
- if (mOverlay == null || mBottomOverlay == null) {
- return;
- }
-
- if (mAssistHintVisible != visible) {
- mAssistHintVisible = visible;
-
- CornerHandleView assistHintTopLeft = mOverlay.findViewById(R.id.assist_hint_left);
- CornerHandleView assistHintTopRight = mOverlay.findViewById(R.id.assist_hint_right);
- CornerHandleView assistHintBottomLeft = mBottomOverlay.findViewById(
- R.id.assist_hint_left);
- CornerHandleView assistHintBottomRight = mBottomOverlay.findViewById(
- R.id.assist_hint_right);
-
- switch (mRotation) {
- case RotationUtils.ROTATION_NONE:
- fade(assistHintBottomLeft, mAssistHintVisible, /* isLeft = */ true);
- fade(assistHintBottomRight, mAssistHintVisible, /* isLeft = */ false);
- break;
- case RotationUtils.ROTATION_LANDSCAPE:
- fade(assistHintTopRight, mAssistHintVisible, /* isLeft = */ true);
- fade(assistHintBottomRight, mAssistHintVisible, /* isLeft = */ false);
- break;
- case RotationUtils.ROTATION_SEASCAPE:
- fade(assistHintTopLeft, mAssistHintVisible, /* isLeft = */ false);
- fade(assistHintBottomLeft, mAssistHintVisible, /* isLeft = */ true);
- break;
- case RotationUtils.ROTATION_UPSIDE_DOWN:
- fade(assistHintTopLeft, mAssistHintVisible, /* isLeft = */ false);
- fade(assistHintTopRight, mAssistHintVisible, /* isLeft = */ true);
- break;
- }
- }
- updateWindowVisibilities();
- }
-
- /**
- * Prevents the assist hint from becoming visible even if `mAssistHintVisible` is true.
- */
- public void setAssistHintBlocked(boolean blocked) {
- if (!mHandler.getLooper().isCurrentThread()) {
- mHandler.post(() -> setAssistHintBlocked(blocked));
- return;
- }
-
- mAssistHintBlocked = blocked;
- if (mAssistHintVisible && mAssistHintBlocked) {
- hideAssistHandles();
- }
}
@VisibleForTesting
@@ -316,15 +150,11 @@ public class ScreenDecorations extends SystemUI implements Tunable,
return thread.getThreadHandler();
}
- private boolean shouldHostHandles() {
- return mInGesturalMode;
- }
-
private void startOnScreenDecorationsThread() {
mRotation = RotationUtils.getExactRotation(mContext);
mWindowManager = mContext.getSystemService(WindowManager.class);
updateRoundedCornerRadii();
- if (hasRoundedCorners() || shouldDrawCutout() || shouldHostHandles()) {
+ if (hasRoundedCorners() || shouldDrawCutout()) {
setupDecorations();
}
@@ -501,26 +331,10 @@ public class ScreenDecorations extends SystemUI implements Tunable,
if (mOverlay != null) {
updateLayoutParams();
updateViews();
- if (mAssistHintVisible) {
- // If assist handles are visible, hide them without animation and then make them
- // show once again (with corrected rotation).
- hideAssistHandles();
- setAssistHintVisible(true);
- }
}
}
}
- private void hideAssistHandles() {
- if (mOverlay != null && mBottomOverlay != null) {
- mOverlay.findViewById(R.id.assist_hint_left).setVisibility(View.GONE);
- mOverlay.findViewById(R.id.assist_hint_right).setVisibility(View.GONE);
- mBottomOverlay.findViewById(R.id.assist_hint_left).setVisibility(View.GONE);
- mBottomOverlay.findViewById(R.id.assist_hint_right).setVisibility(View.GONE);
- mAssistHintVisible = false;
- }
- }
-
private void updateRoundedCornerRadii() {
final int newRoundedDefault = mContext.getResources().getDimensionPixelSize(
com.android.internal.R.dimen.rounded_corner_radius);
@@ -569,52 +383,12 @@ public class ScreenDecorations extends SystemUI implements Tunable,
updateView(bottomRight, Gravity.TOP | Gravity.LEFT, 0);
}
- updateAssistantHandleViews();
mCutoutTop.setRotation(mRotation);
mCutoutBottom.setRotation(mRotation);
updateWindowVisibilities();
}
- private void updateAssistantHandleViews() {
- View assistHintTopLeft = mOverlay.findViewById(R.id.assist_hint_left);
- View assistHintTopRight = mOverlay.findViewById(R.id.assist_hint_right);
- View assistHintBottomLeft = mBottomOverlay.findViewById(R.id.assist_hint_left);
- View assistHintBottomRight = mBottomOverlay.findViewById(R.id.assist_hint_right);
-
- final int assistHintVisibility = mAssistHintVisible ? View.VISIBLE : View.INVISIBLE;
-
- if (mRotation == RotationUtils.ROTATION_NONE) {
- assistHintTopLeft.setVisibility(View.GONE);
- assistHintTopRight.setVisibility(View.GONE);
- assistHintBottomLeft.setVisibility(assistHintVisibility);
- assistHintBottomRight.setVisibility(assistHintVisibility);
- updateView(assistHintBottomLeft, Gravity.BOTTOM | Gravity.LEFT, 270);
- updateView(assistHintBottomRight, Gravity.BOTTOM | Gravity.RIGHT, 180);
- } else if (mRotation == RotationUtils.ROTATION_LANDSCAPE) {
- assistHintTopLeft.setVisibility(View.GONE);
- assistHintTopRight.setVisibility(assistHintVisibility);
- assistHintBottomLeft.setVisibility(View.GONE);
- assistHintBottomRight.setVisibility(assistHintVisibility);
- updateView(assistHintTopRight, Gravity.BOTTOM | Gravity.LEFT, 270);
- updateView(assistHintBottomRight, Gravity.BOTTOM | Gravity.RIGHT, 180);
- } else if (mRotation == RotationUtils.ROTATION_UPSIDE_DOWN) {
- assistHintTopLeft.setVisibility(assistHintVisibility);
- assistHintTopRight.setVisibility(assistHintVisibility);
- assistHintBottomLeft.setVisibility(View.GONE);
- assistHintBottomRight.setVisibility(View.GONE);
- updateView(assistHintTopLeft, Gravity.BOTTOM | Gravity.LEFT, 270);
- updateView(assistHintTopRight, Gravity.BOTTOM | Gravity.RIGHT, 180);
- } else if (mRotation == RotationUtils.ROTATION_SEASCAPE) {
- assistHintTopLeft.setVisibility(assistHintVisibility);
- assistHintTopRight.setVisibility(View.GONE);
- assistHintBottomLeft.setVisibility(assistHintVisibility);
- assistHintBottomRight.setVisibility(View.GONE);
- updateView(assistHintTopLeft, Gravity.BOTTOM | Gravity.RIGHT, 180);
- updateView(assistHintBottomLeft, Gravity.BOTTOM | Gravity.LEFT, 270);
- }
- }
-
private void updateView(View v, int gravity, int rotation) {
((FrameLayout.LayoutParams) v.getLayoutParams()).gravity = gravity;
v.setRotation(rotation);
@@ -629,10 +403,7 @@ public class ScreenDecorations extends SystemUI implements Tunable,
boolean visibleForCutout = shouldDrawCutout()
&& overlay.findViewById(R.id.display_cutout).getVisibility() == View.VISIBLE;
boolean visibleForRoundedCorners = hasRoundedCorners();
- boolean visibleForHandles = overlay.findViewById(R.id.assist_hint_left).getVisibility()
- == View.VISIBLE || overlay.findViewById(R.id.assist_hint_right).getVisibility()
- == View.VISIBLE;
- overlay.setVisibility(visibleForCutout || visibleForRoundedCorners || visibleForHandles
+ overlay.setVisibility(visibleForCutout || visibleForRoundedCorners
? View.VISIBLE : View.GONE);
}
@@ -689,7 +460,7 @@ public class ScreenDecorations extends SystemUI implements Tunable,
| WindowManager.LayoutParams.FLAG_SLIPPERY
| WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN,
PixelFormat.TRANSLUCENT);
- lp.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS
+ lp.privateFlags |= WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS
| WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION;
if (!DEBUG_SCREENSHOT_ROUNDED_CORNERS) {
@@ -766,31 +537,6 @@ public class ScreenDecorations extends SystemUI implements Tunable,
view.setLayoutParams(params);
}
- @Override
- public void onDarkIntensity(float darkIntensity) {
- if (!mHandler.getLooper().isCurrentThread()) {
- mHandler.post(() -> onDarkIntensity(darkIntensity));
- return;
- }
- if (mOverlay != null) {
- CornerHandleView assistHintTopLeft = mOverlay.findViewById(R.id.assist_hint_left);
- CornerHandleView assistHintTopRight = mOverlay.findViewById(R.id.assist_hint_right);
-
- assistHintTopLeft.updateDarkness(darkIntensity);
- assistHintTopRight.updateDarkness(darkIntensity);
- }
-
- if (mBottomOverlay != null) {
- CornerHandleView assistHintBottomLeft = mBottomOverlay.findViewById(
- R.id.assist_hint_left);
- CornerHandleView assistHintBottomRight = mBottomOverlay.findViewById(
- R.id.assist_hint_right);
-
- assistHintBottomLeft.updateDarkness(darkIntensity);
- assistHintBottomRight.updateDarkness(darkIntensity);
- }
- }
-
@VisibleForTesting
static class TunablePaddingTagListener implements FragmentListener {
diff --git a/packages/SystemUI/src/com/android/systemui/SizeCompatModeActivityController.java b/packages/SystemUI/src/com/android/systemui/SizeCompatModeActivityController.java
index c54f6306ddb1..10009f5f5582 100644
--- a/packages/SystemUI/src/com/android/systemui/SizeCompatModeActivityController.java
+++ b/packages/SystemUI/src/com/android/systemui/SizeCompatModeActivityController.java
@@ -59,12 +59,13 @@ public class SizeCompatModeActivityController extends SystemUI implements Comman
/** Only show once automatically in the process life. */
private boolean mHasShownHint;
- public SizeCompatModeActivityController() {
- this(ActivityManagerWrapper.getInstance());
+ public SizeCompatModeActivityController(Context context) {
+ this(context, ActivityManagerWrapper.getInstance());
}
@VisibleForTesting
- SizeCompatModeActivityController(ActivityManagerWrapper am) {
+ SizeCompatModeActivityController(Context context, ActivityManagerWrapper am) {
+ super(context);
am.registerTaskStackListener(new TaskStackChangeListener() {
@Override
public void onSizeCompatModeActivityChanged(int displayId, IBinder activityToken) {
@@ -202,7 +203,7 @@ public class SizeCompatModeActivityController extends SystemUI implements Comman
mWinParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
| WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
mWinParams.format = PixelFormat.TRANSLUCENT;
- mWinParams.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
+ mWinParams.privateFlags |= WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS;
mWinParams.setTitle(SizeCompatModeActivityController.class.getSimpleName()
+ context.getDisplayId());
}
diff --git a/packages/SystemUI/src/com/android/systemui/SliceBroadcastRelayHandler.java b/packages/SystemUI/src/com/android/systemui/SliceBroadcastRelayHandler.java
index b3fc69e8a49d..92fbd259b471 100644
--- a/packages/SystemUI/src/com/android/systemui/SliceBroadcastRelayHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/SliceBroadcastRelayHandler.java
@@ -39,6 +39,10 @@ public class SliceBroadcastRelayHandler extends SystemUI {
private final ArrayMap<Uri, BroadcastRelay> mRelays = new ArrayMap<>();
+ public SliceBroadcastRelayHandler(Context context) {
+ super(context);
+ }
+
@Override
public void start() {
if (DEBUG) Log.d(TAG, "Start");
diff --git a/packages/SystemUI/src/com/android/systemui/SysUIToast.java b/packages/SystemUI/src/com/android/systemui/SysUIToast.java
index 8bcf0571b2d0..0f7f1bebae57 100644
--- a/packages/SystemUI/src/com/android/systemui/SysUIToast.java
+++ b/packages/SystemUI/src/com/android/systemui/SysUIToast.java
@@ -31,7 +31,7 @@ public class SysUIToast {
public static Toast makeText(Context context, CharSequence text, @Duration int duration) {
Toast toast = Toast.makeText(context, text, duration);
toast.getWindowParams().privateFlags |=
- WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
+ WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS;
return toast;
}
diff --git a/packages/SystemUI/src/com/android/systemui/SystemBars.java b/packages/SystemUI/src/com/android/systemui/SystemBars.java
deleted file mode 100644
index c4c0fd6da124..000000000000
--- a/packages/SystemUI/src/com/android/systemui/SystemBars.java
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software distributed under the
- * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the specific language governing
- * permissions and limitations under the License.
- */
-
-package com.android.systemui;
-
-import android.util.Log;
-
-import com.android.systemui.statusbar.phone.StatusBar;
-
-import java.io.FileDescriptor;
-import java.io.PrintWriter;
-
-/**
- * Ensure a single status bar service implementation is running at all times, using the in-process
- * implementation according to the product config.
- */
-public class SystemBars extends SystemUI {
- private static final String TAG = "SystemBars";
- private static final boolean DEBUG = false;
- private static final int WAIT_FOR_BARS_TO_DIE = 500;
-
- // in-process fallback implementation, per the product config
- private SystemUI mStatusBar;
-
- @Override
- public void start() {
- if (DEBUG) Log.d(TAG, "start");
- createStatusBarFromConfig();
- }
-
- @Override
- public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- if (mStatusBar != null) {
- mStatusBar.dump(fd, pw, args);
- }
- }
-
- @Override
- public void onBootCompleted() {
- if (mStatusBar != null) {
- mStatusBar.onBootCompleted();
- }
- }
-
- private void createStatusBarFromConfig() {
- if (DEBUG) Log.d(TAG, "createStatusBarFromConfig");
- final String clsName = mContext.getString(R.string.config_statusBarComponent);
- if (clsName == null || clsName.length() == 0) {
- throw andLog("No status bar component configured", null);
- }
- Class<?> cls = null;
- try {
- cls = mContext.getClassLoader().loadClass(clsName);
- } catch (Throwable t) {
- throw andLog("Error loading status bar component: " + clsName, t);
- }
- try {
- mStatusBar = (SystemUI) cls.newInstance();
- } catch (Throwable t) {
- throw andLog("Error creating status bar component: " + clsName, t);
- }
- mStatusBar.mContext = mContext;
- mStatusBar.mComponents = mComponents;
- if (mStatusBar instanceof StatusBar) {
- SystemUIFactory.getInstance().getRootComponent()
- .getStatusBarInjector()
- .createStatusBar((StatusBar) mStatusBar);
- }
- mStatusBar.start();
- if (DEBUG) Log.d(TAG, "started " + mStatusBar.getClass().getSimpleName());
- }
-
- private RuntimeException andLog(String msg, Throwable t) {
- Log.w(TAG, msg, t);
- throw new RuntimeException(msg, t);
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUI.java b/packages/SystemUI/src/com/android/systemui/SystemUI.java
index 30fbef6cbefb..75700379caca 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUI.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUI.java
@@ -26,9 +26,13 @@ import java.io.PrintWriter;
import java.util.Map;
public abstract class SystemUI implements SysUiServiceProvider {
- public Context mContext;
+ protected final Context mContext;
public Map<Class<?>, Object> mComponents;
+ public SystemUI(Context context) {
+ mContext = context;
+ }
+
public abstract void start();
protected void onConfigurationChanged(Configuration newConfig) {
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIAppComponentFactory.java b/packages/SystemUI/src/com/android/systemui/SystemUIAppComponentFactory.java
index 2c8324cafca0..746515a816b3 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIAppComponentFactory.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIAppComponentFactory.java
@@ -27,6 +27,8 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.app.AppComponentFactory;
+import com.android.systemui.dagger.ContextComponentHelper;
+
import javax.inject.Inject;
/**
@@ -92,6 +94,12 @@ public class SystemUIAppComponentFactory extends AppComponentFactory {
public Activity instantiateActivityCompat(@NonNull ClassLoader cl, @NonNull String className,
@Nullable Intent intent)
throws InstantiationException, IllegalAccessException, ClassNotFoundException {
+ if (mComponentHelper == null) {
+ // This shouldn't happen, but is seen on occasion.
+ // Bug filed against framework to take a look: http://b/141008541
+ SystemUIFactory.getInstance().getRootComponent().inject(
+ SystemUIAppComponentFactory.this);
+ }
Activity activity = mComponentHelper.resolveActivity(className);
if (activity != null) {
return activity;
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
index 56b5d080acc0..022bf06838a6 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
@@ -34,6 +34,7 @@ import android.util.ArraySet;
import android.util.Log;
import android.util.TimingsTraceLog;
+import com.android.systemui.dagger.ContextComponentHelper;
import com.android.systemui.plugins.OverlayPlugin;
import com.android.systemui.plugins.PluginListener;
import com.android.systemui.shared.plugins.PluginManager;
@@ -42,6 +43,8 @@ import com.android.systemui.statusbar.phone.StatusBar;
import com.android.systemui.statusbar.phone.StatusBarWindowController;
import com.android.systemui.util.NotificationChannels;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Map;
@@ -193,18 +196,18 @@ public class SystemUIApplication extends Application implements SysUiServiceProv
try {
SystemUI obj = mComponentHelper.resolveSystemUI(clsName);
if (obj == null) {
- obj = (SystemUI) Class.forName(clsName).newInstance();
+ Constructor constructor = Class.forName(clsName).getConstructor(Context.class);
+ obj = (SystemUI) constructor.newInstance(this);
}
mServices[i] = obj;
- } catch (ClassNotFoundException ex) {
- throw new RuntimeException(ex);
- } catch (IllegalAccessException ex) {
- throw new RuntimeException(ex);
- } catch (InstantiationException ex) {
+ } catch (ClassNotFoundException
+ | NoSuchMethodException
+ | IllegalAccessException
+ | InstantiationException
+ | InvocationTargetException ex) {
throw new RuntimeException(ex);
}
- mServices[i].mContext = this;
mServices[i].mComponents = mComponents;
if (DEBUG) Log.d(TAG, "running: " + mServices[i]);
mServices[i].start();
@@ -235,7 +238,7 @@ public class SystemUIApplication extends Application implements SysUiServiceProv
if (statusBar != null) {
plugin.setup(statusBar.getStatusBarWindow(),
statusBar.getNavigationBarView(), new Callback(plugin),
- DozeParameters.getInstance(getBaseContext()));
+ Dependency.get(DozeParameters.class));
}
}
});
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
index 8e693185ab7f..0a547b6bf051 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
@@ -17,7 +17,6 @@
package com.android.systemui;
import android.annotation.NonNull;
-import android.app.AlarmManager;
import android.content.Context;
import android.os.Handler;
import android.os.Looper;
@@ -25,33 +24,26 @@ import android.util.Log;
import android.view.ViewGroup;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.colorextraction.ColorExtractor.GradientColors;
-import com.android.internal.util.function.TriConsumer;
import com.android.internal.widget.LockPatternUtils;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.keyguard.ViewMediatorCallback;
+import com.android.systemui.dagger.DaggerSystemUIRootComponent;
+import com.android.systemui.dagger.DependencyProvider;
+import com.android.systemui.dagger.SystemUIRootComponent;
import com.android.systemui.keyguard.DismissCallbackRegistry;
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.KeyguardIndicationController;
import com.android.systemui.statusbar.NotificationMediaManager;
-import com.android.systemui.statusbar.ScrimView;
import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator;
import com.android.systemui.statusbar.phone.DozeParameters;
import com.android.systemui.statusbar.phone.KeyguardBouncer;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
import com.android.systemui.statusbar.phone.LockIcon;
-import com.android.systemui.statusbar.phone.LockscreenWallpaper;
import com.android.systemui.statusbar.phone.NotificationIconAreaController;
-import com.android.systemui.statusbar.phone.ScrimController;
-import com.android.systemui.statusbar.phone.ScrimState;
import com.android.systemui.statusbar.phone.StatusBar;
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
-import com.android.systemui.statusbar.phone.UnlockMethodCache;
-import com.android.systemui.statusbar.policy.KeyguardMonitor;
-import com.android.systemui.volume.VolumeDialogComponent;
-
-import java.util.function.Consumer;
+import com.android.systemui.statusbar.policy.KeyguardStateController;
import dagger.Module;
import dagger.Provides;
@@ -118,7 +110,7 @@ public class SystemUIFactory {
protected SystemUIRootComponent buildSystemUIRootComponent(Context context) {
return DaggerSystemUIRootComponent.builder()
- .dependencyProvider(new com.android.systemui.DependencyProvider())
+ .dependencyProvider(new DependencyProvider())
.contextHolder(new ContextHolder(context))
.build();
}
@@ -136,24 +128,15 @@ public class SystemUIFactory {
LockPatternUtils lockPatternUtils, ViewGroup container,
DismissCallbackRegistry dismissCallbackRegistry,
KeyguardBouncer.BouncerExpansionCallback expansionCallback,
- FalsingManager falsingManager, KeyguardBypassController bypassController) {
+ KeyguardStateController keyguardStateController, FalsingManager falsingManager,
+ KeyguardBypassController bypassController) {
return new KeyguardBouncer(context, callback, lockPatternUtils, container,
dismissCallbackRegistry, falsingManager,
- expansionCallback, UnlockMethodCache.getInstance(context),
+ expansionCallback, keyguardStateController,
Dependency.get(KeyguardUpdateMonitor.class), bypassController,
new Handler(Looper.getMainLooper()));
}
- public ScrimController createScrimController(ScrimView scrimBehind, ScrimView scrimInFront,
- ScrimView scrimForBubble,
- LockscreenWallpaper lockscreenWallpaper,
- TriConsumer<ScrimState, Float, GradientColors> scrimStateListener,
- Consumer<Integer> scrimVisibleListener, DozeParameters dozeParameters,
- AlarmManager alarmManager, KeyguardMonitor keyguardMonitor) {
- return new ScrimController(scrimBehind, scrimInFront, scrimForBubble, scrimStateListener,
- scrimVisibleListener, dozeParameters, alarmManager, keyguardMonitor);
- }
-
public NotificationIconAreaController createNotificationIconAreaController(Context context,
StatusBar statusBar,
NotificationWakeUpCoordinator wakeUpCoordinator,
@@ -161,7 +144,8 @@ public class SystemUIFactory {
StatusBarStateController statusBarStateController) {
return new NotificationIconAreaController(context, statusBar, statusBarStateController,
wakeUpCoordinator, keyguardBypassController,
- Dependency.get(NotificationMediaManager.class));
+ Dependency.get(NotificationMediaManager.class),
+ Dependency.get(DozeParameters.class));
}
public KeyguardIndicationController createKeyguardIndicationController(Context context,
@@ -169,10 +153,6 @@ public class SystemUIFactory {
return new KeyguardIndicationController(context, indicationArea, lockIcon);
}
- public VolumeDialogComponent createVolumeDialogComponent(SystemUI systemUi, Context context) {
- return new VolumeDialogComponent(systemUi, context);
- }
-
@Module
public static class ContextHolder {
private Context mContext;
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIService.java b/packages/SystemUI/src/com/android/systemui/SystemUIService.java
index 8f1fcae8e0f7..3f56ff07b24d 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIService.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIService.java
@@ -16,6 +16,7 @@
package com.android.systemui;
+import android.annotation.NonNull;
import android.app.Service;
import android.content.Intent;
import android.os.Build;
@@ -66,7 +67,13 @@ public class SystemUIService extends Service {
@Override
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ if (args != null && args.length > 0 && args[0].equals("--config")) {
+ dumpConfig(pw);
+ return;
+ }
+
dumpServices(((SystemUIApplication) getApplication()).getServices(), fd, pw, args);
+ dumpConfig(pw);
}
static void dumpServices(
@@ -95,5 +102,29 @@ public class SystemUIService extends Service {
}
}
}
+
+ private void dumpConfig(@NonNull PrintWriter pw) {
+ pw.println("SystemUiServiceComponents configuration:");
+
+ pw.print("vendor component: ");
+ pw.println(getResources().getString(R.string.config_systemUIVendorServiceComponent));
+
+ dumpConfig(pw, "global", R.array.config_systemUIServiceComponents);
+ dumpConfig(pw, "per-user", R.array.config_systemUIServiceComponentsPerUser);
+ }
+
+ private void dumpConfig(@NonNull PrintWriter pw, @NonNull String type, int resId) {
+ final String[] services = getResources().getStringArray(resId);
+ pw.print(type); pw.print(": ");
+ if (services == null) {
+ pw.println("N/A");
+ return;
+ }
+ pw.print(services.length);
+ pw.println(" services");
+ for (int i = 0; i < services.length; i++) {
+ pw.print(" "); pw.print(i); pw.print(": "); pw.println(services[i]);
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/VendorServices.java b/packages/SystemUI/src/com/android/systemui/VendorServices.java
index 0be6b12fa365..13d847bf93c4 100644
--- a/packages/SystemUI/src/com/android/systemui/VendorServices.java
+++ b/packages/SystemUI/src/com/android/systemui/VendorServices.java
@@ -16,11 +16,17 @@
package com.android.systemui;
+import android.content.Context;
+
/**
* Placeholder for any vendor-specific services.
*/
public class VendorServices extends SystemUI {
+ public VendorServices(Context context) {
+ super(context);
+ }
+
@Override
public void start() {
// no-op
diff --git a/packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java b/packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java
index ef171d305d28..f616d57e90aa 100644
--- a/packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java
@@ -16,8 +16,6 @@
package com.android.systemui.appops;
-import static com.android.systemui.Dependency.BG_LOOPER_NAME;
-
import android.app.AppOpsManager;
import android.content.Context;
import android.content.pm.PackageManager;
@@ -31,6 +29,7 @@ import android.util.Log;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.systemui.Dumpable;
+import com.android.systemui.dagger.qualifiers.BgLooper;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -39,7 +38,6 @@ import java.util.List;
import java.util.Set;
import javax.inject.Inject;
-import javax.inject.Named;
import javax.inject.Singleton;
/**
@@ -79,7 +77,7 @@ public class AppOpsControllerImpl implements AppOpsController,
};
@Inject
- public AppOpsControllerImpl(Context context, @Named(BG_LOOPER_NAME) Looper bgLooper) {
+ public AppOpsControllerImpl(Context context, @BgLooper Looper bgLooper) {
this(context, bgLooper, new PermissionFlagsCache(context));
}
diff --git a/packages/SystemUI/src/com/android/systemui/assist/AssistHandleBehaviorController.java b/packages/SystemUI/src/com/android/systemui/assist/AssistHandleBehaviorController.java
index 9bdfa03408aa..4516996345b9 100644
--- a/packages/SystemUI/src/com/android/systemui/assist/AssistHandleBehaviorController.java
+++ b/packages/SystemUI/src/com/android/systemui/assist/AssistHandleBehaviorController.java
@@ -32,7 +32,6 @@ import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.systemui.DumpController;
import com.android.systemui.Dumpable;
-import com.android.systemui.ScreenDecorations;
import com.android.systemui.shared.system.QuickStepContract;
import com.android.systemui.statusbar.phone.NavigationModeController;
@@ -71,7 +70,7 @@ public final class AssistHandleBehaviorController implements AssistHandleCallbac
private final Handler mHandler;
private final Runnable mHideHandles = this::hideHandles;
private final Runnable mShowAndGo = this::showAndGoInternal;
- private final Provider<ScreenDecorations> mScreenDecorations;
+ private final Provider<AssistHandleViewController> mAssistHandleViewController;
private final PhenotypeHelper mPhenotypeHelper;
private final Map<AssistHandleBehavior, BehaviorController> mBehaviorMap;
@@ -90,7 +89,7 @@ public final class AssistHandleBehaviorController implements AssistHandleCallbac
Context context,
AssistUtils assistUtils,
@Named(ASSIST_HANDLE_THREAD_NAME) Handler handler,
- Provider<ScreenDecorations> screenDecorations,
+ Provider<AssistHandleViewController> assistHandleViewController,
PhenotypeHelper phenotypeHelper,
Map<AssistHandleBehavior, BehaviorController> behaviorMap,
NavigationModeController navigationModeController,
@@ -98,7 +97,7 @@ public final class AssistHandleBehaviorController implements AssistHandleCallbac
mContext = context;
mAssistUtils = assistUtils;
mHandler = handler;
- mScreenDecorations = screenDecorations;
+ mAssistHandleViewController = assistHandleViewController;
mPhenotypeHelper = phenotypeHelper;
mBehaviorMap = behaviorMap;
@@ -193,7 +192,7 @@ public final class AssistHandleBehaviorController implements AssistHandleCallbac
try {
setBehavior(AssistHandleBehavior.valueOf(behavior));
} catch (IllegalArgumentException | NullPointerException e) {
- Log.e(TAG, "Invalid behavior: " + behavior, e);
+ Log.e(TAG, "Invalid behavior: " + behavior);
}
}
@@ -229,12 +228,13 @@ public final class AssistHandleBehaviorController implements AssistHandleCallbac
}
if (handlesUnblocked(ignoreThreshold)) {
- ScreenDecorations screenDecorations = mScreenDecorations.get();
- if (screenDecorations == null) {
- Log.w(TAG, "Couldn't show handles, ScreenDecorations unavailable");
+ mHandlesShowing = true;
+ AssistHandleViewController assistHandleViewController =
+ mAssistHandleViewController.get();
+ if (assistHandleViewController == null) {
+ Log.w(TAG, "Couldn't show handles, AssistHandleViewController unavailable");
} else {
- mHandlesShowing = true;
- screenDecorations.setAssistHintVisible(true);
+ assistHandleViewController.setAssistHintVisible(true);
}
}
}
@@ -244,13 +244,14 @@ public final class AssistHandleBehaviorController implements AssistHandleCallbac
return;
}
- ScreenDecorations screenDecorations = mScreenDecorations.get();
- if (screenDecorations == null) {
- Log.w(TAG, "Couldn't hide handles, ScreenDecorations unavailable");
+ mHandlesShowing = false;
+ mHandlesLastHiddenAt = SystemClock.elapsedRealtime();
+ AssistHandleViewController assistHandleViewController =
+ mAssistHandleViewController.get();
+ if (assistHandleViewController == null) {
+ Log.w(TAG, "Couldn't show handles, AssistHandleViewController unavailable");
} else {
- mHandlesShowing = false;
- mHandlesLastHiddenAt = SystemClock.elapsedRealtime();
- screenDecorations.setAssistHintVisible(false);
+ assistHandleViewController.setAssistHintVisible(false);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/assist/AssistHandleViewController.java b/packages/SystemUI/src/com/android/systemui/assist/AssistHandleViewController.java
new file mode 100644
index 000000000000..5010f319f8b4
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/assist/AssistHandleViewController.java
@@ -0,0 +1,191 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.assist;
+
+import android.animation.Animator;
+import android.animation.AnimatorSet;
+import android.animation.ObjectAnimator;
+import android.os.Handler;
+import android.util.Log;
+import android.util.MathUtils;
+import android.view.View;
+import android.view.animation.AccelerateInterpolator;
+import android.view.animation.Interpolator;
+import android.view.animation.PathInterpolator;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.systemui.CornerHandleView;
+import com.android.systemui.R;
+import com.android.systemui.statusbar.phone.NavigationBarTransitions;
+
+/**
+ * A class for managing Assistant handle show, hide and animation.
+ */
+public class AssistHandleViewController implements NavigationBarTransitions.DarkIntensityListener {
+
+ private static final boolean DEBUG = false;
+ private static final String TAG = "AssistHandleViewController";
+
+ private Handler mHandler;
+ private CornerHandleView mAssistHintLeft;
+ private CornerHandleView mAssistHintRight;
+ private int mBottomOffset;
+
+ @VisibleForTesting
+ boolean mAssistHintVisible;
+ @VisibleForTesting
+ boolean mAssistHintBlocked = false;
+
+ public AssistHandleViewController(Handler handler, View navBar) {
+ mHandler = handler;
+ mAssistHintLeft = navBar.findViewById(R.id.assist_hint_left);
+ mAssistHintRight = navBar.findViewById(R.id.assist_hint_right);
+ }
+
+ @Override
+ public void onDarkIntensity(float darkIntensity) {
+ mAssistHintLeft.updateDarkness(darkIntensity);
+ mAssistHintRight.updateDarkness(darkIntensity);
+ }
+
+ /**
+ * Set the bottom offset.
+ *
+ * @param bottomOffset the bottom offset to translate.
+ */
+ public void setBottomOffset(int bottomOffset) {
+ if (mBottomOffset != bottomOffset) {
+ mBottomOffset = bottomOffset;
+ if (mAssistHintVisible) {
+ // If assist handles are visible, hide them without animation and then make them
+ // show once again (with corrected bottom offset).
+ hideAssistHandles();
+ setAssistHintVisible(true);
+ }
+ }
+ }
+
+ /**
+ * Controls the visibility of the assist gesture handles.
+ *
+ * @param visible whether the handles should be shown
+ */
+ public void setAssistHintVisible(boolean visible) {
+ if (!mHandler.getLooper().isCurrentThread()) {
+ mHandler.post(() -> setAssistHintVisible(visible));
+ return;
+ }
+
+ if (mAssistHintBlocked && visible) {
+ if (DEBUG) {
+ Log.v(TAG, "Assist hint blocked, cannot make it visible");
+ }
+ return;
+ }
+
+ if (mAssistHintVisible != visible) {
+ mAssistHintVisible = visible;
+ fade(mAssistHintLeft, mAssistHintVisible, /* isLeft = */ true);
+ fade(mAssistHintRight, mAssistHintVisible, /* isLeft = */ false);
+ }
+ }
+
+ /**
+ * Prevents the assist hint from becoming visible even if `mAssistHintVisible` is true.
+ */
+ public void setAssistHintBlocked(boolean blocked) {
+ if (!mHandler.getLooper().isCurrentThread()) {
+ mHandler.post(() -> setAssistHintBlocked(blocked));
+ return;
+ }
+
+ mAssistHintBlocked = blocked;
+ if (mAssistHintVisible && mAssistHintBlocked) {
+ hideAssistHandles();
+ }
+ }
+
+ private void hideAssistHandles() {
+ mAssistHintLeft.setVisibility(View.GONE);
+ mAssistHintRight.setVisibility(View.GONE);
+ mAssistHintVisible = false;
+ }
+
+ /**
+ * Returns an animator that animates the given view from start to end over durationMs. Start and
+ * end represent total animation progress: 0 is the start, 1 is the end, 1.1 would be an
+ * overshoot.
+ */
+ Animator getHandleAnimator(View view, float start, float end, boolean isLeft, long durationMs,
+ Interpolator interpolator) {
+ // Note that lerp does allow overshoot, in cases where start and end are outside of [0,1].
+ float scaleStart = MathUtils.lerp(2f, 1f, start);
+ float scaleEnd = MathUtils.lerp(2f, 1f, end);
+ Animator scaleX = ObjectAnimator.ofFloat(view, View.SCALE_X, scaleStart, scaleEnd);
+ Animator scaleY = ObjectAnimator.ofFloat(view, View.SCALE_Y, scaleStart, scaleEnd);
+ float translationStart = MathUtils.lerp(0.2f, 0f, start);
+ float translationEnd = MathUtils.lerp(0.2f, 0f, end);
+ int xDirection = isLeft ? -1 : 1;
+ Animator translateX = ObjectAnimator.ofFloat(view, View.TRANSLATION_X,
+ xDirection * translationStart * view.getWidth(),
+ xDirection * translationEnd * view.getWidth());
+ Animator translateY = ObjectAnimator.ofFloat(view, View.TRANSLATION_Y,
+ translationStart * view.getHeight() + mBottomOffset,
+ translationEnd * view.getHeight() + mBottomOffset);
+
+ AnimatorSet set = new AnimatorSet();
+ set.play(scaleX).with(scaleY);
+ set.play(scaleX).with(translateX);
+ set.play(scaleX).with(translateY);
+ set.setDuration(durationMs);
+ set.setInterpolator(interpolator);
+ return set;
+ }
+
+ private void fade(View view, boolean fadeIn, boolean isLeft) {
+ if (fadeIn) {
+ view.animate().cancel();
+ view.setAlpha(1f);
+ view.setVisibility(View.VISIBLE);
+
+ // A piecewise spring-like interpolation.
+ // End value in one animator call must match the start value in the next, otherwise
+ // there will be a discontinuity.
+ AnimatorSet anim = new AnimatorSet();
+ Animator first = getHandleAnimator(view, 0, 1.1f, isLeft, 750,
+ new PathInterpolator(0, 0.45f, .67f, 1f));
+ Interpolator secondInterpolator = new PathInterpolator(0.33f, 0, 0.67f, 1f);
+ Animator second = getHandleAnimator(view, 1.1f, 0.97f, isLeft, 400,
+ secondInterpolator);
+ Animator third = getHandleAnimator(view, 0.97f, 1.02f, isLeft, 400,
+ secondInterpolator);
+ Animator fourth = getHandleAnimator(view, 1.02f, 1f, isLeft, 400,
+ secondInterpolator);
+ anim.play(first).before(second);
+ anim.play(second).before(third);
+ anim.play(third).before(fourth);
+ anim.start();
+ } else {
+ view.animate().cancel();
+ view.animate()
+ .setInterpolator(new AccelerateInterpolator(1.5f))
+ .setDuration(250)
+ .alpha(0f);
+ }
+
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/assist/AssistModule.java b/packages/SystemUI/src/com/android/systemui/assist/AssistModule.java
index 2a82d215e44a..6f5a17dca432 100644
--- a/packages/SystemUI/src/com/android/systemui/assist/AssistModule.java
+++ b/packages/SystemUI/src/com/android/systemui/assist/AssistModule.java
@@ -21,11 +21,11 @@ import android.os.Handler;
import android.os.HandlerThread;
import android.os.SystemClock;
+import androidx.annotation.Nullable;
import androidx.slice.Clock;
import com.android.internal.app.AssistUtils;
-import com.android.systemui.ScreenDecorations;
-import com.android.systemui.SysUiServiceProvider;
+import com.android.systemui.statusbar.NavigationBarController;
import java.util.EnumMap;
import java.util.Map;
@@ -69,8 +69,10 @@ public abstract class AssistModule {
}
@Provides
- static ScreenDecorations provideScreenDecorations(Context context) {
- return SysUiServiceProvider.getComponent(context, ScreenDecorations.class);
+ @Nullable
+ static AssistHandleViewController provideAssistHandleViewController(
+ NavigationBarController navigationBarController) {
+ return navigationBarController.getAssistHandlerViewController();
}
@Provides
diff --git a/packages/SystemUI/src/com/android/systemui/assist/ui/DefaultUiController.java b/packages/SystemUI/src/com/android/systemui/assist/ui/DefaultUiController.java
index 0c4f05123c79..4cb1708468ea 100644
--- a/packages/SystemUI/src/com/android/systemui/assist/ui/DefaultUiController.java
+++ b/packages/SystemUI/src/com/android/systemui/assist/ui/DefaultUiController.java
@@ -17,6 +17,7 @@
package com.android.systemui.assist.ui;
import static com.android.systemui.assist.AssistManager.DISMISS_REASON_INVOCATION_CANCELLED;
+import static com.android.systemui.assist.AssistManager.INVOCATION_TYPE_GESTURE;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
@@ -24,6 +25,7 @@ import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.PixelFormat;
import android.metrics.LogMaker;
+import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import android.view.Gravity;
@@ -36,9 +38,11 @@ import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.systemui.Dependency;
import com.android.systemui.R;
-import com.android.systemui.ScreenDecorations;
-import com.android.systemui.SysUiServiceProvider;
+import com.android.systemui.assist.AssistHandleViewController;
import com.android.systemui.assist.AssistManager;
+import com.android.systemui.statusbar.NavigationBarController;
+
+import java.util.Locale;
/**
* Default UiController implementation. Shows white edge lights along the bottom of the phone,
@@ -50,6 +54,9 @@ public class DefaultUiController implements AssistManager.UiController {
private static final long ANIM_DURATION_MS = 200;
+ private static final boolean VERBOSE = Build.TYPE.toLowerCase(Locale.ROOT).contains("debug")
+ || Build.TYPE.toLowerCase(Locale.ROOT).equals("eng");
+
protected final FrameLayout mRoot;
protected InvocationLightsView mInvocationLightsView;
@@ -114,6 +121,7 @@ public class DefaultUiController implements AssistManager.UiController {
@Override // AssistManager.UiController
public void onGestureCompletion(float velocity) {
animateInvocationCompletion(AssistManager.INVOCATION_TYPE_GESTURE, velocity);
+ logInvocationProgressMetrics(INVOCATION_TYPE_GESTURE, 1, mInvocationInProgress);
}
@Override // AssistManager.UiController
@@ -127,16 +135,28 @@ public class DefaultUiController implements AssistManager.UiController {
updateAssistHandleVisibility();
}
- protected static void logInvocationProgressMetrics(
+ protected void logInvocationProgressMetrics(
int type, float progress, boolean invocationWasInProgress) {
// Logs assistant invocation start.
+ if (progress == 1f) {
+ if (VERBOSE) {
+ Log.v(TAG, "Invocation complete: type=" + type);
+ }
+ }
if (!invocationWasInProgress && progress > 0.f) {
+ if (VERBOSE) {
+ Log.v(TAG, "Invocation started: type=" + type);
+ }
MetricsLogger.action(new LogMaker(MetricsEvent.ASSISTANT)
.setType(MetricsEvent.TYPE_ACTION)
.setSubtype(Dependency.get(AssistManager.class).toLoggingSubType(type)));
}
// Logs assistant invocation cancelled.
- if (invocationWasInProgress && progress == 0f) {
+ if ((mInvocationAnimator == null || !mInvocationAnimator.isRunning())
+ && invocationWasInProgress && progress == 0f) {
+ if (VERBOSE) {
+ Log.v(TAG, "Invocation cancelled: type=" + type);
+ }
MetricsLogger.action(new LogMaker(MetricsEvent.ASSISTANT)
.setType(MetricsEvent.TYPE_DISMISS)
.setSubtype(DISMISS_REASON_INVOCATION_CANCELLED));
@@ -144,9 +164,14 @@ public class DefaultUiController implements AssistManager.UiController {
}
private void updateAssistHandleVisibility() {
- ScreenDecorations decorations = SysUiServiceProvider.getComponent(mRoot.getContext(),
- ScreenDecorations.class);
- decorations.setAssistHintBlocked(mInvocationInProgress);
+ NavigationBarController navigationBarController =
+ Dependency.get(NavigationBarController.class);
+ AssistHandleViewController controller =
+ navigationBarController == null
+ ? null : navigationBarController.getAssistHandlerViewController();
+ if (controller != null) {
+ controller.setAssistHintBlocked(mInvocationInProgress);
+ }
}
private void attach() {
diff --git a/packages/SystemUI/src/com/android/systemui/assist/ui/EdgeLight.java b/packages/SystemUI/src/com/android/systemui/assist/ui/EdgeLight.java
index 9ae02c5e3104..baa3a4a938c1 100644
--- a/packages/SystemUI/src/com/android/systemui/assist/ui/EdgeLight.java
+++ b/packages/SystemUI/src/com/android/systemui/assist/ui/EdgeLight.java
@@ -16,6 +16,8 @@
package com.android.systemui.assist.ui;
+import android.util.Log;
+
import androidx.annotation.ColorInt;
/**
@@ -29,9 +31,12 @@ import androidx.annotation.ColorInt;
* counter-clockwise.
*/
public final class EdgeLight {
+
+ private static final String TAG = "EdgeLight";
+
@ColorInt
private int mColor;
- private float mOffset;
+ private float mStart;
private float mLength;
/** Copies a list of EdgeLights. */
@@ -45,13 +50,13 @@ public final class EdgeLight {
public EdgeLight(@ColorInt int color, float offset, float length) {
mColor = color;
- mOffset = offset;
+ mStart = offset;
mLength = length;
}
public EdgeLight(EdgeLight sourceLight) {
mColor = sourceLight.getColor();
- mOffset = sourceLight.getOffset();
+ mStart = sourceLight.getStart();
mLength = sourceLight.getLength();
}
@@ -77,23 +82,41 @@ public final class EdgeLight {
}
/**
- * Returns the current offset, in units of the total device perimeter and measured from the
- * bottom-left corner (see class description).
+ * Sets the endpoints of the edge light, both measured from the bottom-left corner (see class
+ * description). This is a convenience method to avoid separate setStart and setLength calls.
*/
- public float getOffset() {
- return mOffset;
+ public void setEndpoints(float start, float end) {
+ if (start > end) {
+ Log.e(TAG, String.format("Endpoint must be >= start (add 1 if necessary). Got [%f, %f]",
+ start, end));
+ return;
+ }
+ mStart = start;
+ mLength = end - start;
+ }
+
+ /**
+ * Returns the current starting position, in units of the total device perimeter and measured
+ * from the bottom-left corner (see class description).
+ */
+ public float getStart() {
+ return mStart;
}
/**
* Sets the current offset, in units of the total device perimeter and measured from the
* bottom-left corner (see class description).
*/
- public void setOffset(float offset) {
- mOffset = offset;
+ public void setStart(float start) {
+ mStart = start;
+ }
+
+ public float getEnd() {
+ return mStart + mLength;
}
/** Returns the center, measured from the bottom-left corner (see class description). */
public float getCenter() {
- return mOffset + (mLength / 2.f);
+ return mStart + (mLength / 2.f);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/assist/ui/InvocationLightsView.java b/packages/SystemUI/src/com/android/systemui/assist/ui/InvocationLightsView.java
index bb3bd781df66..570b911cd400 100644
--- a/packages/SystemUI/src/com/android/systemui/assist/ui/InvocationLightsView.java
+++ b/packages/SystemUI/src/com/android/systemui/assist/ui/InvocationLightsView.java
@@ -140,10 +140,10 @@ public class InvocationLightsView extends View
float rightStart = mGuide.getRegionWidth(PerimeterPathGuide.Region.BOTTOM)
+ (cornerLengthNormalized - arcOffsetNormalized) * (1 - progress);
- setLight(0, leftStart, lightLength);
- setLight(1, leftStart + lightLength, lightLength);
- setLight(2, rightStart - (lightLength * 2), lightLength);
- setLight(3, rightStart - lightLength, lightLength);
+ setLight(0, leftStart, leftStart + lightLength);
+ setLight(1, leftStart + lightLength, leftStart + lightLength * 2);
+ setLight(2, rightStart - (lightLength * 2), rightStart - lightLength);
+ setLight(3, rightStart - lightLength, rightStart);
setVisibility(View.VISIBLE);
}
invalidate();
@@ -155,7 +155,7 @@ public class InvocationLightsView extends View
public void hide() {
setVisibility(GONE);
for (EdgeLight light : mAssistInvocationLights) {
- light.setLength(0);
+ light.setEndpoints(0, 0);
}
attemptUnregisterNavBarListener();
}
@@ -235,12 +235,11 @@ public class InvocationLightsView extends View
}
}
- protected void setLight(int index, float offset, float length) {
+ protected void setLight(int index, float start, float end) {
if (index < 0 || index >= 4) {
Log.w(TAG, "invalid invocation light index: " + index);
}
- mAssistInvocationLights.get(index).setOffset(offset);
- mAssistInvocationLights.get(index).setLength(length);
+ mAssistInvocationLights.get(index).setEndpoints(start, end);
}
/**
@@ -268,9 +267,11 @@ public class InvocationLightsView extends View
}
private void renderLight(EdgeLight light, Canvas canvas) {
- mGuide.strokeSegment(mPath, light.getOffset(), light.getOffset() + light.getLength());
- mPaint.setColor(light.getColor());
- canvas.drawPath(mPath, mPaint);
+ if (light.getLength() > 0) {
+ mGuide.strokeSegment(mPath, light.getStart(), light.getStart() + light.getLength());
+ mPaint.setColor(light.getColor());
+ canvas.drawPath(mPath, mPaint);
+ }
}
private void attemptRegisterNavBarListener() {
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricView.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricView.java
index 73bbce9c5b35..d20cd72f0712 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricView.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricView.java
@@ -16,8 +16,6 @@
package com.android.systemui.biometrics;
-import static android.view.accessibility.AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE;
-
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
@@ -25,6 +23,7 @@ import android.animation.ValueAnimator;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.app.admin.DevicePolicyManager;
import android.content.Context;
import android.hardware.biometrics.BiometricPrompt;
import android.os.Bundle;
@@ -34,7 +33,7 @@ import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
-import android.view.accessibility.AccessibilityEvent;
+import android.view.ViewGroup;
import android.view.accessibility.AccessibilityManager;
import android.widget.Button;
import android.widget.ImageView;
@@ -42,10 +41,13 @@ import android.widget.LinearLayout;
import android.widget.TextView;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.widget.LockPatternUtils;
import com.android.systemui.R;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
+import java.util.ArrayList;
+import java.util.List;
/**
* Contains the Biometric views (title, subtitle, icon, buttons, etc) and its controllers.
@@ -97,6 +99,7 @@ public abstract class AuthBiometricView extends LinearLayout {
int ACTION_BUTTON_NEGATIVE = 3;
int ACTION_BUTTON_TRY_AGAIN = 4;
int ACTION_ERROR = 5;
+ int ACTION_USE_DEVICE_CREDENTIAL = 6;
/**
* When an action has occurred. The caller will only invoke this when the callback should
@@ -145,6 +148,14 @@ public abstract class AuthBiometricView extends LinearLayout {
public int getDelayAfterError() {
return BiometricPrompt.HIDE_DIALOG_DELAY;
}
+
+ public int getMediumToLargeAnimationDurationMs() {
+ return AuthDialog.ANIMATE_MEDIUM_TO_LARGE_DURATION_MS;
+ }
+
+ public int getAnimateCredentialStartDelayMs() {
+ return AuthDialog.ANIMATE_CREDENTIAL_START_DELAY_MS;
+ }
}
private final Injector mInjector;
@@ -154,8 +165,9 @@ public abstract class AuthBiometricView extends LinearLayout {
private final int mTextColorHint;
private AuthPanelController mPanelController;
- private Bundle mBundle;
+ private Bundle mBiometricPromptBundle;
private boolean mRequireConfirmation;
+ private int mUserId;
@AuthDialog.DialogSize int mSize = AuthDialog.SIZE_UNKNOWN;
private TextView mTitleView;
@@ -212,6 +224,9 @@ public abstract class AuthBiometricView extends LinearLayout {
} else if (mSize == AuthDialog.SIZE_SMALL) {
Log.w(TAG, "Ignoring background click during small dialog");
return;
+ } else if (mSize == AuthDialog.SIZE_LARGE) {
+ Log.w(TAG, "Ignoring background click during large dialog");
+ return;
}
mCallback.onAction(Callback.ACTION_USER_CANCELED);
};
@@ -256,7 +271,7 @@ public abstract class AuthBiometricView extends LinearLayout {
}
public void setBiometricPromptBundle(Bundle bundle) {
- mBundle = bundle;
+ mBiometricPromptBundle = bundle;
}
public void setCallback(Callback callback) {
@@ -267,6 +282,10 @@ public abstract class AuthBiometricView extends LinearLayout {
backgroundView.setOnClickListener(mBackgroundClickListener);
}
+ public void setUserId(int userId) {
+ mUserId = userId;
+ }
+
public void setRequireConfirmation(boolean requireConfirmation) {
mRequireConfirmation = requireConfirmation;
}
@@ -287,7 +306,7 @@ public abstract class AuthBiometricView extends LinearLayout {
final int newHeight = mIconView.getHeight() + 2 * (int) iconPadding;
mPanelController.updateForContentDimensions(mMediumWidth, newHeight,
- false /* animate */);
+ 0 /* animateDurationMs */);
mSize = newSize;
} else if (mSize == AuthDialog.SIZE_SMALL && newSize == AuthDialog.SIZE_MEDIUM) {
@@ -305,10 +324,8 @@ public abstract class AuthBiometricView extends LinearLayout {
// Animate the text
final ValueAnimator opacityAnimator = ValueAnimator.ofFloat(0, 1);
- opacityAnimator.setDuration(AuthDialog.ANIMATE_DURATION_MS);
opacityAnimator.addUpdateListener((animation) -> {
final float opacity = (float) animation.getAnimatedValue();
-
mTitleView.setAlpha(opacity);
mIndicatorView.setAlpha(opacity);
mNegativeButton.setAlpha(opacity);
@@ -324,7 +341,7 @@ public abstract class AuthBiometricView extends LinearLayout {
// Choreograph together
final AnimatorSet as = new AnimatorSet();
- as.setDuration(AuthDialog.ANIMATE_DURATION_MS);
+ as.setDuration(AuthDialog.ANIMATE_SMALL_TO_MEDIUM_DURATION_MS);
as.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationStart(Animator animation) {
@@ -355,11 +372,73 @@ public abstract class AuthBiometricView extends LinearLayout {
as.start();
// Animate the panel
mPanelController.updateForContentDimensions(mMediumWidth, mMediumHeight,
- true /* animate */);
+ AuthDialog.ANIMATE_SMALL_TO_MEDIUM_DURATION_MS);
} else if (newSize == AuthDialog.SIZE_MEDIUM) {
mPanelController.updateForContentDimensions(mMediumWidth, mMediumHeight,
- false /* animate */);
+ 0 /* animateDurationMs */);
mSize = newSize;
+ } else if (newSize == AuthDialog.SIZE_LARGE) {
+ final boolean isManagedProfile = Utils.isManagedProfile(mContext, mUserId);
+
+ // If it's a managed profile, animate the contents and panel down, since the credential
+ // contents will be shown on the same "layer" as the background. If it's not a managed
+ // profile, animate the contents up and expand the panel to full-screen - the credential
+ // contents will be shown on the same "layer" as the panel.
+ final float translationY = isManagedProfile ?
+ -getResources().getDimension(
+ R.dimen.biometric_dialog_animation_translation_offset)
+ : getResources().getDimension(
+ R.dimen.biometric_dialog_medium_to_large_translation_offset);
+ final AuthBiometricView biometricView = this;
+
+ // Translate at full duration
+ final ValueAnimator translationAnimator = ValueAnimator.ofFloat(
+ biometricView.getY(), biometricView.getY() - translationY);
+ translationAnimator.setDuration(mInjector.getMediumToLargeAnimationDurationMs());
+ translationAnimator.addUpdateListener((animation) -> {
+ final float translation = (float) animation.getAnimatedValue();
+ biometricView.setTranslationY(translation);
+ });
+ translationAnimator.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ super.onAnimationEnd(animation);
+ if (biometricView.getParent() != null) {
+ ((ViewGroup) biometricView.getParent()).removeView(biometricView);
+ }
+ mSize = newSize;
+ }
+ });
+
+ // Opacity to 0 in half duration
+ final ValueAnimator opacityAnimator = ValueAnimator.ofFloat(1, 0);
+ opacityAnimator.setDuration(mInjector.getMediumToLargeAnimationDurationMs() / 2);
+ opacityAnimator.addUpdateListener((animation) -> {
+ final float opacity = (float) animation.getAnimatedValue();
+ biometricView.setAlpha(opacity);
+ });
+
+ if (!isManagedProfile) {
+ mPanelController.setUseFullScreen(true);
+ mPanelController.updateForContentDimensions(
+ mPanelController.getContainerWidth(),
+ mPanelController.getContainerHeight(),
+ mInjector.getMediumToLargeAnimationDurationMs());
+ }
+
+ // Start the animations together
+ AnimatorSet as = new AnimatorSet();
+ List<Animator> animators = new ArrayList<>();
+ animators.add(translationAnimator);
+ animators.add(opacityAnimator);
+ if (isManagedProfile) {
+ animators.add(mPanelController.getTranslationAnimator(translationY));
+ animators.add(mPanelController.getAlphaAnimator(0));
+ }
+ as.playTogether(animators);
+ as.setDuration(isManagedProfile ? mInjector.getMediumToLargeAnimationDurationMs()
+ : mInjector.getMediumToLargeAnimationDurationMs() * 2 / 3);
+ as.start();
} else {
Log.e(TAG, "Unknown transition from: " + mSize + " to: " + newSize);
}
@@ -528,7 +607,11 @@ public abstract class AuthBiometricView extends LinearLayout {
if (mState == STATE_PENDING_CONFIRMATION) {
mCallback.onAction(Callback.ACTION_USER_CANCELED);
} else {
- mCallback.onAction(Callback.ACTION_BUTTON_NEGATIVE);
+ if (isDeviceCredentialAllowed()) {
+ startTransitionToCredentialUI();
+ } else {
+ mCallback.onAction(Callback.ACTION_BUTTON_NEGATIVE);
+ }
}
});
@@ -544,6 +627,16 @@ public abstract class AuthBiometricView extends LinearLayout {
});
}
+ /**
+ * Kicks off the animation process and invokes the callback.
+ */
+ void startTransitionToCredentialUI() {
+ updateSize(AuthDialog.SIZE_LARGE);
+ mHandler.postDelayed(() -> {
+ mCallback.onAction(Callback.ACTION_USE_DEVICE_CREDENTIAL);
+ }, mInjector.getAnimateCredentialStartDelayMs());
+ }
+
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
@@ -556,11 +649,37 @@ public abstract class AuthBiometricView extends LinearLayout {
*/
@VisibleForTesting
void onAttachedToWindowInternal() {
- setText(mTitleView, mBundle.getString(BiometricPrompt.KEY_TITLE));
- setText(mNegativeButton, mBundle.getString(BiometricPrompt.KEY_NEGATIVE_TEXT));
+ setText(mTitleView, mBiometricPromptBundle.getString(BiometricPrompt.KEY_TITLE));
+
+ final String negativeText;
+ if (isDeviceCredentialAllowed()) {
+
+ final @Utils.CredentialType int credentialType =
+ Utils.getCredentialType(mContext, mUserId);
+ switch(credentialType) {
+ case Utils.CREDENTIAL_PIN:
+ negativeText = getResources().getString(R.string.biometric_dialog_use_pin);
+ break;
+ case Utils.CREDENTIAL_PATTERN:
+ negativeText = getResources().getString(R.string.biometric_dialog_use_pattern);
+ break;
+ case Utils.CREDENTIAL_PASSWORD:
+ negativeText = getResources().getString(R.string.biometric_dialog_use_password);
+ break;
+ default:
+ negativeText = getResources().getString(R.string.biometric_dialog_use_password);
+ break;
+ }
- setTextOrHide(mSubtitleView, mBundle.getString(BiometricPrompt.KEY_SUBTITLE));
- setTextOrHide(mDescriptionView, mBundle.getString(BiometricPrompt.KEY_DESCRIPTION));
+ } else {
+ negativeText = mBiometricPromptBundle.getString(BiometricPrompt.KEY_NEGATIVE_TEXT);
+ }
+ setText(mNegativeButton, negativeText);
+
+ setTextOrHide(mSubtitleView,
+ mBiometricPromptBundle.getString(BiometricPrompt.KEY_SUBTITLE));
+ setTextOrHide(mDescriptionView,
+ mBiometricPromptBundle.getString(BiometricPrompt.KEY_DESCRIPTION));
if (mSavedState == null) {
updateState(STATE_AUTHENTICATING_ANIMATING_IN);
@@ -655,4 +774,8 @@ public abstract class AuthBiometricView extends LinearLayout {
}
}
}
+
+ private boolean isDeviceCredentialAllowed() {
+ return Utils.isDeviceCredentialAllowed(mBiometricPromptBundle);
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java
index 6555c75f677a..f1abdb31b5f8 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java
@@ -24,7 +24,9 @@ import android.content.Context;
import android.graphics.PixelFormat;
import android.graphics.PorterDuff;
import android.graphics.drawable.Drawable;
+import android.hardware.biometrics.Authenticator;
import android.hardware.biometrics.BiometricAuthenticator;
+import android.hardware.biometrics.BiometricPrompt;
import android.os.Binder;
import android.os.Bundle;
import android.os.IBinder;
@@ -36,6 +38,7 @@ import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.view.animation.Interpolator;
+import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ScrollView;
@@ -72,17 +75,20 @@ public class AuthContainerView extends LinearLayout
@interface ContainerState {}
final Config mConfig;
+ private final Injector mInjector;
private final IBinder mWindowToken = new Binder();
private final WindowManager mWindowManager;
private final AuthPanelController mPanelController;
private final Interpolator mLinearOutSlowIn;
@VisibleForTesting final BiometricCallback mBiometricCallback;
+ private final CredentialCallback mCredentialCallback;
- private final ViewGroup mContainerView;
- private final AuthBiometricView mBiometricView;
+ @VisibleForTesting final FrameLayout mFrameLayout;
+ @VisibleForTesting @Nullable AuthBiometricView mBiometricView;
+ @VisibleForTesting @Nullable AuthCredentialView mCredentialView;
private final ImageView mBackgroundView;
- private final ScrollView mScrollView;
+ @VisibleForTesting final ScrollView mBiometricScrollView;
private final View mPanelView;
private final float mTranslationY;
@@ -145,7 +151,31 @@ public class AuthContainerView extends LinearLayout
public AuthContainerView build(int modalityMask) {
mConfig.mModalityMask = modalityMask;
- return new AuthContainerView(mConfig);
+ return new AuthContainerView(mConfig, new Injector());
+ }
+ }
+
+ public static class Injector {
+ ScrollView getBiometricScrollView(FrameLayout parent) {
+ return parent.findViewById(R.id.biometric_scrollview);
+ }
+
+ FrameLayout inflateContainerView(LayoutInflater factory, ViewGroup root) {
+ return (FrameLayout) factory.inflate(
+ R.layout.auth_container_view, root, false /* attachToRoot */);
+ }
+
+ AuthPanelController getPanelController(Context context, View panelView,
+ boolean isManagedProfile) {
+ return new AuthPanelController(context, panelView, isManagedProfile);
+ }
+
+ ImageView getBackgroundView(FrameLayout parent) {
+ return parent.findViewById(R.id.background);
+ }
+
+ View getPanelView(FrameLayout parent) {
+ return parent.findViewById(R.id.panel);
}
}
@@ -155,7 +185,7 @@ public class AuthContainerView extends LinearLayout
public void onAction(int action) {
switch (action) {
case AuthBiometricView.Callback.ACTION_AUTHENTICATED:
- animateAway(AuthDialogCallback.DISMISSED_AUTHENTICATED);
+ animateAway(AuthDialogCallback.DISMISSED_BIOMETRIC_AUTHENTICATED);
break;
case AuthBiometricView.Callback.ACTION_USER_CANCELED:
animateAway(AuthDialogCallback.DISMISSED_USER_CANCELED);
@@ -169,17 +199,30 @@ public class AuthContainerView extends LinearLayout
case AuthBiometricView.Callback.ACTION_ERROR:
animateAway(AuthDialogCallback.DISMISSED_ERROR);
break;
+ case AuthBiometricView.Callback.ACTION_USE_DEVICE_CREDENTIAL:
+ mConfig.mCallback.onDeviceCredentialPressed();
+ addCredentialView(false /* animatePanel */, true /* animateContents */);
+ break;
default:
Log.e(TAG, "Unhandled action: " + action);
}
}
}
+ final class CredentialCallback implements AuthCredentialView.Callback {
+ @Override
+ public void onCredentialMatched() {
+ animateAway(AuthDialogCallback.DISMISSED_CREDENTIAL_AUTHENTICATED);
+ }
+ }
+
@VisibleForTesting
- AuthContainerView(Config config) {
+ AuthContainerView(Config config, Injector injector) {
super(config.mContext);
mConfig = config;
+ mInjector = injector;
+
mWindowManager = mContext.getSystemService(WindowManager.class);
mWakefulnessLifecycle = Dependency.get(WakefulnessLifecycle.class);
@@ -187,51 +230,48 @@ public class AuthContainerView extends LinearLayout
.getDimension(R.dimen.biometric_dialog_animation_translation_offset);
mLinearOutSlowIn = Interpolators.LINEAR_OUT_SLOW_IN;
mBiometricCallback = new BiometricCallback();
+ mCredentialCallback = new CredentialCallback();
final LayoutInflater factory = LayoutInflater.from(mContext);
- mContainerView = (ViewGroup) factory.inflate(
- R.layout.auth_container_view, this, false /* attachToRoot */);
-
- mPanelView = mContainerView.findViewById(R.id.panel);
- mPanelController = new AuthPanelController(mContext, mPanelView);
-
- // TODO: Update with new controllers if multi-modal authentication can occur simultaneously
- if (config.mModalityMask == BiometricAuthenticator.TYPE_FINGERPRINT) {
- mBiometricView = (AuthBiometricFingerprintView)
- factory.inflate(R.layout.auth_biometric_fingerprint_view, null, false);
- } else if (config.mModalityMask == BiometricAuthenticator.TYPE_FACE) {
- mBiometricView = (AuthBiometricFaceView)
- factory.inflate(R.layout.auth_biometric_face_view, null, false);
- } else {
- Log.e(TAG, "Unsupported modality mask: " + config.mModalityMask);
- mBiometricView = null;
- mBackgroundView = null;
- mScrollView = null;
- return;
+ mFrameLayout = mInjector.inflateContainerView(factory, this);
+
+ final boolean isManagedProfile = Utils.isManagedProfile(mContext, mConfig.mUserId);
+
+ mPanelView = mInjector.getPanelView(mFrameLayout);
+ mPanelController = mInjector.getPanelController(mContext, mPanelView, isManagedProfile);
+
+ // Inflate biometric view only if necessary.
+ if (Utils.isBiometricAllowed(mConfig.mBiometricPromptBundle)) {
+ if (config.mModalityMask == BiometricAuthenticator.TYPE_FINGERPRINT) {
+ mBiometricView = (AuthBiometricFingerprintView)
+ factory.inflate(R.layout.auth_biometric_fingerprint_view, null, false);
+ } else if (config.mModalityMask == BiometricAuthenticator.TYPE_FACE) {
+ mBiometricView = (AuthBiometricFaceView)
+ factory.inflate(R.layout.auth_biometric_face_view, null, false);
+ } else {
+ Log.e(TAG, "Unsupported biometric modality: " + config.mModalityMask);
+ mBiometricView = null;
+ mBackgroundView = null;
+ mBiometricScrollView = null;
+ return;
+ }
}
- mBackgroundView = mContainerView.findViewById(R.id.background);
+ mBiometricScrollView = mInjector.getBiometricScrollView(mFrameLayout);
+ mBackgroundView = mInjector.getBackgroundView(mFrameLayout);
+
- UserManager userManager = mContext.getSystemService(UserManager.class);
- DevicePolicyManager dpm = mContext.getSystemService(DevicePolicyManager.class);
- if (userManager.isManagedProfile(mConfig.mUserId)) {
+ if (isManagedProfile) {
final Drawable image = getResources().getDrawable(R.drawable.work_challenge_background,
mContext.getTheme());
+ final DevicePolicyManager dpm = mContext.getSystemService(DevicePolicyManager.class);
image.setColorFilter(dpm.getOrganizationColorForUser(mConfig.mUserId),
PorterDuff.Mode.DARKEN);
mBackgroundView.setScaleType(ImageView.ScaleType.CENTER_CROP);
mBackgroundView.setImageDrawable(image);
}
- mBiometricView.setRequireConfirmation(mConfig.mRequireConfirmation);
- mBiometricView.setPanelController(mPanelController);
- mBiometricView.setBiometricPromptBundle(config.mBiometricPromptBundle);
- mBiometricView.setCallback(mBiometricCallback);
- mBiometricView.setBackgroundView(mBackgroundView);
-
- mScrollView = mContainerView.findViewById(R.id.scrollview);
- mScrollView.addView(mBiometricView);
- addView(mContainerView);
+ addView(mFrameLayout);
setOnKeyListener((v, keyCode, event) -> {
if (keyCode != KeyEvent.KEYCODE_BACK) {
@@ -248,6 +288,53 @@ public class AuthContainerView extends LinearLayout
}
@Override
+ public boolean isAllowDeviceCredentials() {
+ return Utils.isDeviceCredentialAllowed(mConfig.mBiometricPromptBundle);
+ }
+
+ private void addBiometricView() {
+ mBiometricView.setRequireConfirmation(mConfig.mRequireConfirmation);
+ mBiometricView.setPanelController(mPanelController);
+ mBiometricView.setBiometricPromptBundle(mConfig.mBiometricPromptBundle);
+ mBiometricView.setCallback(mBiometricCallback);
+ mBiometricView.setBackgroundView(mBackgroundView);
+ mBiometricView.setUserId(mConfig.mUserId);
+ mBiometricScrollView.addView(mBiometricView);
+ }
+
+ /**
+ * Adds the credential view. When going from biometric to credential view, the biometric
+ * view starts the panel expansion animation. If the credential view is being shown first,
+ * it should own the panel expansion.
+ * @param animatePanel if the credential view needs to own the panel expansion animation
+ */
+ private void addCredentialView(boolean animatePanel, boolean animateContents) {
+ final LayoutInflater factory = LayoutInflater.from(mContext);
+ final int credentialType = Utils.getCredentialType(mContext, mConfig.mUserId);
+ switch (credentialType) {
+ case Utils.CREDENTIAL_PATTERN:
+ mCredentialView = (AuthCredentialView) factory.inflate(
+ R.layout.auth_credential_pattern_view, null, false);
+ break;
+ case Utils.CREDENTIAL_PIN:
+ case Utils.CREDENTIAL_PASSWORD:
+ mCredentialView = (AuthCredentialView) factory.inflate(
+ R.layout.auth_credential_password_view, null, false);
+ break;
+ default:
+ throw new IllegalStateException("Unknown credential type: " + credentialType);
+ }
+
+ mCredentialView.setContainerView(this);
+ mCredentialView.setUser(mConfig.mUserId);
+ mCredentialView.setCallback(mCredentialCallback);
+ mCredentialView.setBiometricPromptBundle(mConfig.mBiometricPromptBundle);
+ mCredentialView.setPanelController(mPanelController, animatePanel);
+ mCredentialView.setShouldAnimateContents(animateContents);
+ mFrameLayout.addView(mCredentialView);
+ }
+
+ @Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
mPanelController.setContainerDimensions(getMeasuredWidth(), getMeasuredHeight());
@@ -256,8 +343,22 @@ public class AuthContainerView extends LinearLayout
@Override
public void onAttachedToWindow() {
super.onAttachedToWindow();
+ onAttachedToWindowInternal();
+ }
+
+ @VisibleForTesting
+ void onAttachedToWindowInternal() {
mWakefulnessLifecycle.addObserver(this);
+ if (Utils.isBiometricAllowed(mConfig.mBiometricPromptBundle)) {
+ addBiometricView();
+ } else if (Utils.isDeviceCredentialAllowed(mConfig.mBiometricPromptBundle)) {
+ addCredentialView(true /* animatePanel */, false /* animateContents */);
+ } else {
+ throw new IllegalStateException("Unknown configuration: "
+ + Utils.getAuthenticators(mConfig.mBiometricPromptBundle));
+ }
+
if (mConfig.mSkipIntro) {
mContainerState = STATE_SHOWING;
} else {
@@ -265,7 +366,7 @@ public class AuthContainerView extends LinearLayout
// The background panel and content are different views since we need to be able to
// animate them separately in other places.
mPanelView.setY(mTranslationY);
- mScrollView.setY(mTranslationY);
+ mBiometricScrollView.setY(mTranslationY);
setAlpha(0f);
postOnAnimation(() -> {
@@ -276,12 +377,21 @@ public class AuthContainerView extends LinearLayout
.withLayer()
.withEndAction(this::onDialogAnimatedIn)
.start();
- mScrollView.animate()
+ mBiometricScrollView.animate()
.translationY(0)
.setDuration(ANIMATION_DURATION_SHOW_MS)
.setInterpolator(mLinearOutSlowIn)
.withLayer()
.start();
+ if (mCredentialView != null && mCredentialView.isAttachedToWindow()) {
+ mCredentialView.setY(mTranslationY);
+ mCredentialView.animate()
+ .translationY(0)
+ .setDuration(ANIMATION_DURATION_SHOW_MS)
+ .setInterpolator(mLinearOutSlowIn)
+ .withLayer()
+ .start();
+ }
animate()
.alpha(1f)
.setDuration(ANIMATION_DURATION_SHOW_MS)
@@ -305,7 +415,9 @@ public class AuthContainerView extends LinearLayout
@Override
public void show(WindowManager wm, @Nullable Bundle savedState) {
- mBiometricView.restoreState(savedState);
+ if (mBiometricView != null) {
+ mBiometricView.restoreState(savedState);
+ }
wm.addView(this, getLayoutParams(mWindowToken));
}
@@ -346,7 +458,15 @@ public class AuthContainerView extends LinearLayout
@Override
public void onSaveState(@NonNull Bundle outState) {
outState.putInt(AuthDialog.KEY_CONTAINER_STATE, mContainerState);
- mBiometricView.onSaveState(outState);
+ // In the case where biometric and credential are both allowed, we can assume that
+ // biometric isn't showing if credential is showing since biometric is shown first.
+ outState.putBoolean(AuthDialog.KEY_BIOMETRIC_SHOWING,
+ mBiometricView != null && mCredentialView == null);
+ outState.putBoolean(AuthDialog.KEY_CREDENTIAL_SHOWING, mCredentialView != null);
+
+ if (mBiometricView != null) {
+ mBiometricView.onSaveState(outState);
+ }
}
@Override
@@ -354,6 +474,11 @@ public class AuthContainerView extends LinearLayout
return mConfig.mOpPackageName;
}
+ @Override
+ public void animateToCredentialUI() {
+ mBiometricView.startTransitionToCredentialUI();
+ }
+
@VisibleForTesting
void animateAway(int reason) {
animateAway(true /* sendReason */, reason);
@@ -391,12 +516,20 @@ public class AuthContainerView extends LinearLayout
.withLayer()
.withEndAction(endActionRunnable)
.start();
- mScrollView.animate()
+ mBiometricScrollView.animate()
.translationY(mTranslationY)
.setDuration(ANIMATION_DURATION_AWAY_MS)
.setInterpolator(mLinearOutSlowIn)
.withLayer()
.start();
+ if (mCredentialView != null && mCredentialView.isAttachedToWindow()) {
+ mCredentialView.animate()
+ .translationY(mTranslationY)
+ .setDuration(ANIMATION_DURATION_AWAY_MS)
+ .setInterpolator(mLinearOutSlowIn)
+ .withLayer()
+ .start();
+ }
animate()
.alpha(0f)
.setDuration(ANIMATION_DURATION_AWAY_MS)
@@ -431,7 +564,9 @@ public class AuthContainerView extends LinearLayout
return;
}
mContainerState = STATE_SHOWING;
- mBiometricView.onDialogAnimatedIn();
+ if (mBiometricView != null) {
+ mBiometricView.onDialogAnimatedIn();
+ }
}
/**
@@ -445,7 +580,7 @@ public class AuthContainerView extends LinearLayout
WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL,
WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED,
PixelFormat.TRANSLUCENT);
- lp.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
+ lp.privateFlags |= WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS;
lp.setTitle("BiometricPrompt");
lp.token = windowToken;
return lp;
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
index d10a3fede412..b75873100025 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
@@ -16,6 +16,9 @@
package com.android.systemui.biometrics;
+import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FACE;
+import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FINGERPRINT;
+
import android.app.ActivityManager;
import android.app.ActivityTaskManager;
import android.app.IActivityTaskManager;
@@ -23,8 +26,12 @@ import android.app.TaskStackListener;
import android.content.Context;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
+import android.hardware.biometrics.Authenticator;
+import android.hardware.biometrics.BiometricConstants;
import android.hardware.biometrics.BiometricPrompt;
import android.hardware.biometrics.IBiometricServiceReceiverInternal;
+import android.hardware.face.FaceManager;
+import android.hardware.fingerprint.FingerprintManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
@@ -32,6 +39,7 @@ import android.os.RemoteException;
import android.util.Log;
import android.view.WindowManager;
+import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.os.SomeArgs;
import com.android.systemui.SystemUI;
@@ -105,6 +113,15 @@ public class AuthController extends SystemUI implements CommandQueue.Callbacks,
}
@Override
+ public void onDeviceCredentialPressed() {
+ try {
+ mReceiver.onDeviceCredentialPressed();
+ } catch (RemoteException e) {
+ Log.e(TAG, "RemoteException when handling credential button", e);
+ }
+ }
+
+ @Override
public void onDismissed(@DismissedReason int reason) {
switch (reason) {
case AuthDialogCallback.DISMISSED_USER_CANCELED:
@@ -116,11 +133,12 @@ public class AuthController extends SystemUI implements CommandQueue.Callbacks,
break;
case AuthDialogCallback.DISMISSED_BUTTON_POSITIVE:
- sendResultAndCleanUp(BiometricPrompt.DISMISSED_REASON_CONFIRMED);
+ sendResultAndCleanUp(BiometricPrompt.DISMISSED_REASON_BIOMETRIC_CONFIRMED);
break;
- case AuthDialogCallback.DISMISSED_AUTHENTICATED:
- sendResultAndCleanUp(BiometricPrompt.DISMISSED_REASON_CONFIRM_NOT_REQUIRED);
+ case AuthDialogCallback.DISMISSED_BIOMETRIC_AUTHENTICATED:
+ sendResultAndCleanUp(
+ BiometricPrompt.DISMISSED_REASON_BIOMETRIC_CONFIRM_NOT_REQUIRED);
break;
case AuthDialogCallback.DISMISSED_ERROR:
@@ -131,6 +149,10 @@ public class AuthController extends SystemUI implements CommandQueue.Callbacks,
sendResultAndCleanUp(BiometricPrompt.DISMISSED_REASON_SERVER_REQUESTED);
break;
+ case AuthDialogCallback.DISMISSED_CREDENTIAL_AUTHENTICATED:
+ sendResultAndCleanUp(BiometricPrompt.DISMISSED_REASON_CREDENTIAL_CONFIRMED);
+ break;
+
default:
Log.e(TAG, "Unhandled reason: " + reason);
break;
@@ -156,12 +178,13 @@ public class AuthController extends SystemUI implements CommandQueue.Callbacks,
}
}
- public AuthController() {
- this(new Injector());
+ public AuthController(Context context) {
+ this(context, new Injector());
}
@VisibleForTesting
- AuthController(Injector injector) {
+ AuthController(Context context, Injector injector) {
+ super(context);
mInjector = injector;
}
@@ -185,16 +208,19 @@ public class AuthController extends SystemUI implements CommandQueue.Callbacks,
}
@Override
- public void showBiometricDialog(Bundle bundle, IBiometricServiceReceiverInternal receiver,
- int type, boolean requireConfirmation, int userId, String opPackageName) {
+ public void showAuthenticationDialog(Bundle bundle, IBiometricServiceReceiverInternal receiver,
+ int biometricModality, boolean requireConfirmation, int userId, String opPackageName) {
+ final int authenticators = Utils.getAuthenticators(bundle);
+
if (DEBUG) {
- Log.d(TAG, "showBiometricDialog, type: " + type
+ Log.d(TAG, "showAuthenticationDialog, authenticators: " + authenticators
+ + ", biometricModality: " + biometricModality
+ ", requireConfirmation: " + requireConfirmation);
}
SomeArgs args = SomeArgs.obtain();
args.arg1 = bundle;
args.arg2 = receiver;
- args.argi1 = type;
+ args.argi1 = biometricModality;
args.arg3 = requireConfirmation;
args.argi2 = userId;
args.arg4 = opPackageName;
@@ -204,19 +230,13 @@ public class AuthController extends SystemUI implements CommandQueue.Callbacks,
Log.w(TAG, "mCurrentDialog: " + mCurrentDialog);
skipAnimation = true;
}
+
showDialog(args, skipAnimation, null /* savedState */);
}
@Override
- public void onBiometricAuthenticated(boolean authenticated, String failureReason) {
- if (DEBUG) Log.d(TAG, "onBiometricAuthenticated: " + authenticated
- + " reason: " + failureReason);
-
- if (authenticated) {
- mCurrentDialog.onAuthenticationSucceeded();
- } else {
- mCurrentDialog.onAuthenticationFailed(failureReason);
- }
+ public void onBiometricAuthenticated() {
+ mCurrentDialog.onAuthenticationSucceeded();
}
@Override
@@ -226,15 +246,51 @@ public class AuthController extends SystemUI implements CommandQueue.Callbacks,
mCurrentDialog.onHelp(message);
}
+ private String getErrorString(int modality, int error, int vendorCode) {
+ switch (modality) {
+ case TYPE_FACE:
+ return FaceManager.getErrorString(mContext, error, vendorCode);
+
+ case TYPE_FINGERPRINT:
+ return FingerprintManager.getErrorString(mContext, error, vendorCode);
+
+ default:
+ return "";
+ }
+ }
+
@Override
- public void onBiometricError(String error) {
- if (DEBUG) Log.d(TAG, "onBiometricError: " + error);
- mCurrentDialog.onError(error);
+ public void onBiometricError(int modality, int error, int vendorCode) {
+ if (DEBUG) {
+ Log.d(TAG, String.format("onBiometricError(%d, %d, %d)", modality, error, vendorCode));
+ }
+
+ final boolean isLockout = (error == BiometricConstants.BIOMETRIC_ERROR_LOCKOUT)
+ || (error == BiometricConstants.BIOMETRIC_ERROR_LOCKOUT_PERMANENT);
+
+ // TODO(b/141025588): Create separate methods for handling hard and soft errors.
+ final boolean isSoftError = (error == BiometricConstants.BIOMETRIC_PAUSED_REJECTED
+ || error == BiometricConstants.BIOMETRIC_ERROR_TIMEOUT);
+
+ if (mCurrentDialog.isAllowDeviceCredentials() && isLockout) {
+ if (DEBUG) Log.d(TAG, "onBiometricError, lockout");
+ mCurrentDialog.animateToCredentialUI();
+ } else if (isSoftError) {
+ final String errorMessage = (error == BiometricConstants.BIOMETRIC_PAUSED_REJECTED)
+ ? mContext.getString(R.string.biometric_not_recognized)
+ : getErrorString(modality, error, vendorCode);
+ if (DEBUG) Log.d(TAG, "onBiometricError, soft error: " + errorMessage);
+ mCurrentDialog.onAuthenticationFailed(errorMessage);
+ } else {
+ final String errorMessage = getErrorString(modality, error, vendorCode);
+ if (DEBUG) Log.d(TAG, "onBiometricError, hard error: " + errorMessage);
+ mCurrentDialog.onError(errorMessage);
+ }
}
@Override
- public void hideBiometricDialog() {
- if (DEBUG) Log.d(TAG, "hideBiometricDialog");
+ public void hideAuthenticationDialog() {
+ if (DEBUG) Log.d(TAG, "hideAuthenticationDialog");
mCurrentDialog.dismissFromSystemServer();
}
@@ -262,7 +318,7 @@ public class AuthController extends SystemUI implements CommandQueue.Callbacks,
}
if (DEBUG) {
- Log.d(TAG, "showDialog, "
+ Log.d(TAG, "showDialog: " + args
+ " savedState: " + savedState
+ " mCurrentDialog: " + mCurrentDialog
+ " newDialog: " + newDialog
@@ -306,6 +362,15 @@ public class AuthController extends SystemUI implements CommandQueue.Callbacks,
// to send its pending callback immediately.
if (savedState.getInt(AuthDialog.KEY_CONTAINER_STATE)
!= AuthContainerView.STATE_ANIMATING_OUT) {
+ final boolean credentialShowing =
+ savedState.getBoolean(AuthDialog.KEY_CREDENTIAL_SHOWING);
+ if (credentialShowing) {
+ // TODO: Clean this up
+ Bundle bundle = (Bundle) mCurrentDialogArgs.arg1;
+ bundle.putInt(BiometricPrompt.KEY_AUTHENTICATORS_ALLOWED,
+ Authenticator.TYPE_CREDENTIAL);
+ }
+
showDialog(mCurrentDialogArgs, true /* skipAnimation */, savedState);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthCredentialPasswordView.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthCredentialPasswordView.java
new file mode 100644
index 000000000000..bebaa4b688db
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthCredentialPasswordView.java
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.biometrics;
+
+import android.content.Context;
+import android.text.InputType;
+import android.util.AttributeSet;
+import android.view.KeyEvent;
+import android.view.inputmethod.EditorInfo;
+import android.view.inputmethod.InputMethodManager;
+import android.widget.EditText;
+import android.widget.TextView;
+
+import com.android.internal.widget.LockPatternChecker;
+import com.android.internal.widget.LockscreenCredential;
+import com.android.systemui.R;
+
+/**
+ * Pin and Password UI
+ */
+public class AuthCredentialPasswordView extends AuthCredentialView
+ implements TextView.OnEditorActionListener {
+
+ private static final String TAG = "BiometricPrompt/AuthCredentialPasswordView";
+
+ private final InputMethodManager mImm;
+ private EditText mPasswordField;
+
+ public AuthCredentialPasswordView(Context context,
+ AttributeSet attrs) {
+ super(context, attrs);
+ mImm = mContext.getSystemService(InputMethodManager.class);
+ }
+
+ @Override
+ protected void onFinishInflate() {
+ super.onFinishInflate();
+ mPasswordField = findViewById(R.id.lockPassword);
+ mPasswordField.setOnEditorActionListener(this);
+ mPasswordField.setOnKeyListener((v, keyCode, event) -> {
+ if (keyCode != KeyEvent.KEYCODE_BACK) {
+ return false;
+ }
+ if (event.getAction() == KeyEvent.ACTION_UP) {
+ mContainerView.animateAway(AuthDialogCallback.DISMISSED_USER_CANCELED);
+ }
+ return true;
+ });
+ }
+
+ @Override
+ protected void onAttachedToWindow() {
+ super.onAttachedToWindow();
+
+ if (mCredentialType == Utils.CREDENTIAL_PIN) {
+ mPasswordField.setInputType(
+ InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_VARIATION_PASSWORD);
+ }
+
+ // Wait a bit to focus the field so the focusable flag on the window is already set then.
+ post(() -> {
+ mPasswordField.requestFocus();
+ mImm.showSoftInput(mPasswordField, InputMethodManager.SHOW_IMPLICIT);
+ });
+ }
+
+ @Override
+ public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
+ // Check if this was the result of hitting the enter key
+ final boolean isSoftImeEvent = event == null
+ && (actionId == EditorInfo.IME_NULL
+ || actionId == EditorInfo.IME_ACTION_DONE
+ || actionId == EditorInfo.IME_ACTION_NEXT);
+ final boolean isKeyboardEnterKey = event != null
+ && KeyEvent.isConfirmKey(event.getKeyCode())
+ && event.getAction() == KeyEvent.ACTION_DOWN;
+ if (isSoftImeEvent || isKeyboardEnterKey) {
+ checkPasswordAndUnlock();
+ return true;
+ }
+ return false;
+ }
+
+ private void checkPasswordAndUnlock() {
+ try (LockscreenCredential password = mCredentialType == Utils.CREDENTIAL_PIN
+ ? LockscreenCredential.createPinOrNone(mPasswordField.getText())
+ : LockscreenCredential.createPasswordOrNone(mPasswordField.getText())) {
+ if (password.isNone()) {
+ return;
+ }
+
+ mPendingLockCheck = LockPatternChecker.checkCredential(mLockPatternUtils,
+ password, mUserId, this::onCredentialChecked);
+ }
+ }
+
+ @Override
+ protected void onCredentialChecked(boolean matched, int timeoutMs) {
+ super.onCredentialChecked(matched, timeoutMs);
+
+ if (matched) {
+ mImm.hideSoftInputFromWindow(getWindowToken(), 0 /* flags */);
+ } else {
+ mPasswordField.setText("");
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthCredentialPatternView.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthCredentialPatternView.java
new file mode 100644
index 000000000000..14414a4225de
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthCredentialPatternView.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.biometrics;
+
+import android.content.Context;
+import android.util.AttributeSet;
+
+import com.android.internal.widget.LockPatternChecker;
+import com.android.internal.widget.LockPatternUtils;
+import com.android.internal.widget.LockPatternView;
+import com.android.internal.widget.LockscreenCredential;
+import com.android.systemui.R;
+
+import java.util.List;
+
+/**
+ * Pattern UI
+ */
+public class AuthCredentialPatternView extends AuthCredentialView {
+
+ private LockPatternView mLockPatternView;
+
+ private class UnlockPatternListener implements LockPatternView.OnPatternListener {
+
+ @Override
+ public void onPatternStart() {
+
+ }
+
+ @Override
+ public void onPatternCleared() {
+
+ }
+
+ @Override
+ public void onPatternCellAdded(List<LockPatternView.Cell> pattern) {
+
+ }
+
+ @Override
+ public void onPatternDetected(List<LockPatternView.Cell> pattern) {
+ if (mPendingLockCheck != null) {
+ mPendingLockCheck.cancel(false);
+ }
+
+ mLockPatternView.setEnabled(false);
+
+ if (pattern.size() < LockPatternUtils.MIN_PATTERN_REGISTER_FAIL) {
+ // Pattern size is less than the minimum, do not count it as a failed attempt.
+ onPatternChecked(false /* matched */, 0 /* timeoutMs */);
+ return;
+ }
+
+ try (LockscreenCredential credential = LockscreenCredential.createPattern(pattern)) {
+ mPendingLockCheck = LockPatternChecker.checkCredential(
+ mLockPatternUtils,
+ credential,
+ mUserId,
+ this::onPatternChecked);
+ }
+ }
+
+ private void onPatternChecked(boolean matched, int timeoutMs) {
+ AuthCredentialPatternView.this.onCredentialChecked(matched, timeoutMs);
+ if (timeoutMs > 0) {
+ mLockPatternView.setEnabled(false);
+ } else {
+ mLockPatternView.setEnabled(true);
+ }
+ }
+ }
+
+ @Override
+ protected void onErrorTimeoutFinish() {
+ super.onErrorTimeoutFinish();
+ mLockPatternView.setEnabled(true);
+ }
+
+ public AuthCredentialPatternView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ @Override
+ protected void onFinishInflate() {
+ super.onFinishInflate();
+ mLockPatternView = findViewById(R.id.lockPattern);
+ mLockPatternView.setOnPatternListener(new UnlockPatternListener());
+ mLockPatternView.setInStealthMode(!mLockPatternUtils.isVisiblePatternEnabled(mUserId));
+ mLockPatternView.setTactileFeedbackEnabled(mLockPatternUtils.isTactileFeedbackEnabled());
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthCredentialView.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthCredentialView.java
new file mode 100644
index 000000000000..8c8611e49dfb
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthCredentialView.java
@@ -0,0 +1,265 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.biometrics;
+
+import android.content.Context;
+import android.hardware.biometrics.BiometricPrompt;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.os.CountDownTimer;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.SystemClock;
+import android.text.TextUtils;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.accessibility.AccessibilityManager;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import com.android.internal.widget.LockPatternUtils;
+import com.android.systemui.Interpolators;
+import com.android.systemui.R;
+
+/**
+ * Abstract base class for Pin, Pattern, or Password authentication, for
+ * {@link BiometricPrompt.Builder#setDeviceCredentialAllowed(boolean)}
+ */
+public abstract class AuthCredentialView extends LinearLayout {
+
+ private static final String TAG = "BiometricPrompt/AuthCredentialView";
+ private static final int ERROR_DURATION_MS = 3000;
+
+ private final AccessibilityManager mAccessibilityManager;
+
+ protected final Handler mHandler;
+
+ private Bundle mBiometricPromptBundle;
+ private AuthPanelController mPanelController;
+ private boolean mShouldAnimatePanel;
+ private boolean mShouldAnimateContents;
+
+ private TextView mTitleView;
+ private TextView mSubtitleView;
+ private TextView mDescriptionView;
+ protected TextView mErrorView;
+
+ protected @Utils.CredentialType int mCredentialType;
+ protected final LockPatternUtils mLockPatternUtils;
+ protected AuthContainerView mContainerView;
+ protected Callback mCallback;
+ protected AsyncTask<?, ?, ?> mPendingLockCheck;
+ protected int mUserId;
+ protected ErrorTimer mErrorTimer;
+
+ interface Callback {
+ void onCredentialMatched();
+ }
+
+ protected static class ErrorTimer extends CountDownTimer {
+ private final TextView mErrorView;
+ private final Context mContext;
+
+ /**
+ * @param millisInFuture The number of millis in the future from the call
+ * to {@link #start()} until the countdown is done and {@link
+ * #onFinish()}
+ * is called.
+ * @param countDownInterval The interval along the way to receive
+ * {@link #onTick(long)} callbacks.
+ */
+ public ErrorTimer(Context context, long millisInFuture, long countDownInterval,
+ TextView errorView) {
+ super(millisInFuture, countDownInterval);
+ mErrorView = errorView;
+ mContext = context;
+ }
+
+ @Override
+ public void onTick(long millisUntilFinished) {
+ final int secondsCountdown = (int) (millisUntilFinished / 1000);
+ mErrorView.setText(mContext.getString(
+ R.string.biometric_dialog_credential_too_many_attempts, secondsCountdown));
+ }
+
+ @Override
+ public void onFinish() {
+ mErrorView.setText("");
+ }
+ }
+
+ protected final Runnable mClearErrorRunnable = new Runnable() {
+ @Override
+ public void run() {
+ mErrorView.setText("");
+ }
+ };
+
+ public AuthCredentialView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+
+ mLockPatternUtils = new LockPatternUtils(mContext);
+ mHandler = new Handler(Looper.getMainLooper());
+ mAccessibilityManager = mContext.getSystemService(AccessibilityManager.class);
+ }
+
+ protected void showError(String error) {
+ mHandler.removeCallbacks(mClearErrorRunnable);
+ mErrorView.setText(error);
+ mHandler.postDelayed(mClearErrorRunnable, ERROR_DURATION_MS);
+ }
+
+ private void setTextOrHide(TextView view, String string) {
+ if (TextUtils.isEmpty(string)) {
+ view.setVisibility(View.GONE);
+ } else {
+ view.setText(string);
+ }
+
+ Utils.notifyAccessibilityContentChanged(mAccessibilityManager, this);
+ }
+
+ private void setText(TextView view, String string) {
+ view.setText(string);
+ }
+
+ void setUser(int user) {
+ mUserId = user;
+ }
+
+ void setCallback(Callback callback) {
+ mCallback = callback;
+ }
+
+ void setBiometricPromptBundle(Bundle bundle) {
+ mBiometricPromptBundle = bundle;
+ }
+
+ void setPanelController(AuthPanelController panelController, boolean animatePanel) {
+ mPanelController = panelController;
+ mShouldAnimatePanel = animatePanel;
+ }
+
+ void setShouldAnimateContents(boolean animateContents) {
+ mShouldAnimateContents = animateContents;
+ }
+
+ void setContainerView(AuthContainerView containerView) {
+ mContainerView = containerView;
+ }
+
+ @Override
+ protected void onAttachedToWindow() {
+ super.onAttachedToWindow();
+
+ mCredentialType = Utils.getCredentialType(mContext, mUserId);
+
+ setText(mTitleView, mBiometricPromptBundle.getString(BiometricPrompt.KEY_TITLE));
+ setTextOrHide(mSubtitleView,
+ mBiometricPromptBundle.getString(BiometricPrompt.KEY_SUBTITLE));
+ setTextOrHide(mDescriptionView,
+ mBiometricPromptBundle.getString(BiometricPrompt.KEY_DESCRIPTION));
+
+ // Only animate this if we're transitioning from a biometric view.
+ if (mShouldAnimateContents) {
+ setTranslationY(getResources()
+ .getDimension(R.dimen.biometric_dialog_credential_translation_offset));
+ setAlpha(0);
+
+ postOnAnimation(() -> {
+ animate().translationY(0)
+ .setDuration(AuthDialog.ANIMATE_CREDENTIAL_INITIAL_DURATION_MS)
+ .alpha(1.f)
+ .setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN)
+ .withLayer()
+ .start();
+ });
+ }
+ }
+
+ @Override
+ protected void onDetachedFromWindow() {
+ super.onDetachedFromWindow();
+ if (mErrorTimer != null) {
+ mErrorTimer.cancel();
+ }
+ }
+
+ @Override
+ protected void onFinishInflate() {
+ super.onFinishInflate();
+ mTitleView = findViewById(R.id.title);
+ mSubtitleView = findViewById(R.id.subtitle);
+ mDescriptionView = findViewById(R.id.description);
+ mErrorView = findViewById(R.id.error);
+ }
+
+ @Override
+ protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+ super.onLayout(changed, left, top, right, bottom);
+
+ if (mShouldAnimatePanel) {
+ // Credential view is always full screen.
+ mPanelController.setUseFullScreen(true);
+ mPanelController.updateForContentDimensions(mPanelController.getContainerWidth(),
+ mPanelController.getContainerHeight(), 0 /* animateDurationMs */);
+ mShouldAnimatePanel = false;
+ }
+ }
+
+ protected void onErrorTimeoutFinish() {}
+
+ protected void onCredentialChecked(boolean matched, int timeoutMs) {
+ if (matched) {
+ mClearErrorRunnable.run();
+ mCallback.onCredentialMatched();
+ } else {
+ if (timeoutMs > 0) {
+ mHandler.removeCallbacks(mClearErrorRunnable);
+ long deadline = mLockPatternUtils.setLockoutAttemptDeadline(mUserId, timeoutMs);
+ mErrorTimer = new ErrorTimer(mContext,
+ deadline - SystemClock.elapsedRealtime(),
+ LockPatternUtils.FAILED_ATTEMPT_COUNTDOWN_INTERVAL_MS,
+ mErrorView) {
+ @Override
+ public void onFinish() {
+ onErrorTimeoutFinish();
+ mClearErrorRunnable.run();
+ }
+ };
+ mErrorTimer.start();
+ } else {
+ final int error;
+ switch (mCredentialType) {
+ case Utils.CREDENTIAL_PIN:
+ error = R.string.biometric_dialog_wrong_pin;
+ break;
+ case Utils.CREDENTIAL_PATTERN:
+ error = R.string.biometric_dialog_wrong_pattern;
+ break;
+ case Utils.CREDENTIAL_PASSWORD:
+ error = R.string.biometric_dialog_wrong_password;
+ break;
+ default:
+ error = R.string.biometric_dialog_wrong_password;
+ break;
+ }
+ showError(getResources().getString(error));
+ }
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthDialog.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthDialog.java
index edb29538874c..ca95f9d736fc 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthDialog.java
@@ -31,6 +31,8 @@ import java.lang.annotation.RetentionPolicy;
public interface AuthDialog {
String KEY_CONTAINER_STATE = "container_state";
+ String KEY_BIOMETRIC_SHOWING = "biometric_showing";
+ String KEY_CREDENTIAL_SHOWING = "credential_showing";
String KEY_BIOMETRIC_TRY_AGAIN_VISIBILITY = "try_agian_visibility";
String KEY_BIOMETRIC_STATE = "state";
@@ -40,17 +42,38 @@ public interface AuthDialog {
String KEY_BIOMETRIC_DIALOG_SIZE = "size";
int SIZE_UNKNOWN = 0;
+ /**
+ * Minimal UI, showing only biometric icon.
+ */
int SIZE_SMALL = 1;
+ /**
+ * Normal-sized biometric UI, showing title, icon, buttons, etc.
+ */
int SIZE_MEDIUM = 2;
+ /**
+ * Full-screen credential UI.
+ */
int SIZE_LARGE = 3;
@Retention(RetentionPolicy.SOURCE)
@IntDef({SIZE_UNKNOWN, SIZE_SMALL, SIZE_MEDIUM, SIZE_LARGE})
@interface DialogSize {}
/**
- * Animation duration, e.g. small to medium dialog, icon translation, etc.
+ * Animation duration, from small to medium dialog, including back panel, icon translation, etc
+ */
+ int ANIMATE_SMALL_TO_MEDIUM_DURATION_MS = 150;
+ /**
+ * Animation duration from medium to large dialog, including biometric fade out, back panel, etc
+ */
+ int ANIMATE_MEDIUM_TO_LARGE_DURATION_MS = 450;
+ /**
+ * Delay before notifying {@link AuthCredentialView} to start animating in.
+ */
+ int ANIMATE_CREDENTIAL_START_DELAY_MS = ANIMATE_MEDIUM_TO_LARGE_DURATION_MS * 2 / 3;
+ /**
+ * Animation duration when sliding in credential UI
*/
- int ANIMATE_DURATION_MS = 150;
+ int ANIMATE_CREDENTIAL_INITIAL_DURATION_MS = 150;
/**
* Show the dialog.
@@ -101,4 +124,14 @@ public interface AuthDialog {
* Get the client's package name
*/
String getOpPackageName();
+
+ /**
+ * Animate to credential UI. Typically called after biometric is locked out.
+ */
+ void animateToCredentialUI();
+
+ /**
+ * @return true if device credential is allowed.
+ */
+ boolean isAllowDeviceCredentials();
}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthDialogCallback.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthDialogCallback.java
index 70752f5f860e..12bb1228a53b 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthDialogCallback.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthDialogCallback.java
@@ -27,17 +27,18 @@ public interface AuthDialogCallback {
int DISMISSED_USER_CANCELED = 1;
int DISMISSED_BUTTON_NEGATIVE = 2;
int DISMISSED_BUTTON_POSITIVE = 3;
-
- int DISMISSED_AUTHENTICATED = 4;
+ int DISMISSED_BIOMETRIC_AUTHENTICATED = 4;
int DISMISSED_ERROR = 5;
int DISMISSED_BY_SYSTEM_SERVER = 6;
+ int DISMISSED_CREDENTIAL_AUTHENTICATED = 7;
@IntDef({DISMISSED_USER_CANCELED,
DISMISSED_BUTTON_NEGATIVE,
DISMISSED_BUTTON_POSITIVE,
- DISMISSED_AUTHENTICATED,
+ DISMISSED_BIOMETRIC_AUTHENTICATED,
DISMISSED_ERROR,
- DISMISSED_BY_SYSTEM_SERVER})
+ DISMISSED_BY_SYSTEM_SERVER,
+ DISMISSED_CREDENTIAL_AUTHENTICATED})
@interface DismissedReason {}
/**
@@ -50,4 +51,9 @@ public interface AuthDialogCallback {
* Invoked when the "try again" button is clicked
*/
void onTryAgainPressed();
+
+ /**
+ * Invoked when the "use password" button is clicked
+ */
+ void onDeviceCredentialPressed();
}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthPanelController.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthPanelController.java
index 55ba0491dc1e..2b8b586961ff 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthPanelController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthPanelController.java
@@ -16,15 +16,17 @@
package com.android.systemui.biometrics;
+import android.animation.AnimatorSet;
import android.animation.ValueAnimator;
import android.content.Context;
+import android.graphics.Color;
import android.graphics.Outline;
import android.util.Log;
import android.view.View;
import android.view.ViewOutlineProvider;
+import android.view.animation.AccelerateDecelerateInterpolator;
import com.android.systemui.R;
-import com.android.systemui.biometrics.AuthDialog;
/**
* Controls the back panel and its animations for the BiometricPrompt UI.
@@ -36,8 +38,9 @@ public class AuthPanelController extends ViewOutlineProvider {
private final Context mContext;
private final View mPanelView;
- private final float mCornerRadius;
- private final int mBiometricMargin;
+ private final boolean mIsManagedProfile;
+
+ private boolean mUseFullScreen;
private int mContainerWidth;
private int mContainerHeight;
@@ -45,14 +48,23 @@ public class AuthPanelController extends ViewOutlineProvider {
private int mContentWidth;
private int mContentHeight;
+ private float mCornerRadius;
+ private int mMargin;
+
@Override
public void getOutline(View view, Outline outline) {
final int left = (mContainerWidth - mContentWidth) / 2;
final int right = mContainerWidth - left;
+
+ // If the content fits within the container, shrink the height to wrap the content.
+ // Otherwise, set the outline to be the display size minus the margin - the content within
+ // is scrollable.
final int top = mContentHeight < mContainerHeight
- ? mContainerHeight - mContentHeight - mBiometricMargin
- : mBiometricMargin;
- final int bottom = mContainerHeight - mBiometricMargin;
+ ? mContainerHeight - mContentHeight - mMargin
+ : mMargin;
+
+ // TODO(b/139954942) Likely don't need to "+1" after we resolve the navbar styling.
+ final int bottom = mContainerHeight - mMargin + 1;
outline.setRoundRect(left, top, right, bottom, mCornerRadius);
}
@@ -64,11 +76,34 @@ public class AuthPanelController extends ViewOutlineProvider {
mContainerHeight = containerHeight;
}
- public void updateForContentDimensions(int contentWidth, int contentHeight, boolean animate) {
+ public void setUseFullScreen(boolean fullScreen) {
+ mUseFullScreen = fullScreen;
+ }
+
+ public ValueAnimator getTranslationAnimator(float relativeTranslationY) {
+ final ValueAnimator animator = ValueAnimator.ofFloat(
+ mPanelView.getY(), mPanelView.getY() - relativeTranslationY);
+ animator.addUpdateListener(animation -> {
+ final float translation = (float) animation.getAnimatedValue();
+ mPanelView.setTranslationY(translation);
+ });
+ return animator;
+ }
+
+ public ValueAnimator getAlphaAnimator(float alpha) {
+ final ValueAnimator animator = ValueAnimator.ofFloat(mPanelView.getAlpha(), alpha);
+ animator.addUpdateListener(animation -> {
+ mPanelView.setAlpha((float) animation.getAnimatedValue());
+ });
+ return animator;
+ }
+
+ public void updateForContentDimensions(int contentWidth, int contentHeight,
+ int animateDurationMs) {
if (DEBUG) {
Log.v(TAG, "Content Width: " + contentWidth
+ " Height: " + contentHeight
- + " Animate: " + animate);
+ + " Animate: " + animateDurationMs);
}
if (mContainerWidth == 0 || mContainerHeight == 0) {
@@ -76,27 +111,86 @@ public class AuthPanelController extends ViewOutlineProvider {
return;
}
- if (animate) {
+ final int margin = mUseFullScreen ? 0 : (int) mContext.getResources()
+ .getDimension(R.dimen.biometric_dialog_border_padding);
+ final float cornerRadius = mUseFullScreen ? 0 : mContext.getResources()
+ .getDimension(R.dimen.biometric_dialog_corner_size);
+
+ // When going to full-screen for managed profiles, fade away so the managed profile
+ // background behind this view becomes visible.
+ final boolean shouldFadeAway = mUseFullScreen && mIsManagedProfile;
+ final int alpha = shouldFadeAway ? 0 : 255;
+ final float elevation = shouldFadeAway ? 0 :
+ mContext.getResources().getDimension(R.dimen.biometric_dialog_elevation);
+
+ if (animateDurationMs > 0) {
+ // Animate margin
+ ValueAnimator marginAnimator = ValueAnimator.ofInt(mMargin, margin);
+ marginAnimator.addUpdateListener((animation) -> {
+ mMargin = (int) animation.getAnimatedValue();
+ });
+
+ // Animate corners
+ ValueAnimator cornerAnimator = ValueAnimator.ofFloat(mCornerRadius, cornerRadius);
+ cornerAnimator.addUpdateListener((animation) -> {
+ mCornerRadius = (float) animation.getAnimatedValue();
+ });
+
+ // Animate height
ValueAnimator heightAnimator = ValueAnimator.ofInt(mContentHeight, contentHeight);
- heightAnimator.setDuration(AuthDialog.ANIMATE_DURATION_MS);
heightAnimator.addUpdateListener((animation) -> {
mContentHeight = (int) animation.getAnimatedValue();
mPanelView.invalidateOutline();
});
heightAnimator.start();
+
+ // Animate width
+ ValueAnimator widthAnimator = ValueAnimator.ofInt(mContentWidth, contentWidth);
+ widthAnimator.addUpdateListener((animation) -> {
+ mContentWidth = (int) animation.getAnimatedValue();
+ });
+
+ // Animate background
+ ValueAnimator alphaAnimator = ValueAnimator.ofInt(
+ mPanelView.getBackground().getAlpha(), alpha);
+ alphaAnimator.addUpdateListener((animation) -> {
+ if (shouldFadeAway) {
+ mPanelView.getBackground().setAlpha((int) animation.getAnimatedValue());
+ }
+ });
+
+ // Play together
+ AnimatorSet as = new AnimatorSet();
+ as.setDuration(animateDurationMs);
+ as.setInterpolator(new AccelerateDecelerateInterpolator());
+ as.playTogether(cornerAnimator, widthAnimator, marginAnimator, alphaAnimator);
+ as.start();
+
} else {
+ mMargin = margin;
+ mCornerRadius = cornerRadius;
mContentWidth = contentWidth;
mContentHeight = contentHeight;
+ mPanelView.getBackground().setAlpha(alpha);
mPanelView.invalidateOutline();
}
}
- AuthPanelController(Context context, View panelView) {
+ int getContainerWidth() {
+ return mContainerWidth;
+ }
+
+ int getContainerHeight() {
+ return mContainerHeight;
+ }
+
+ AuthPanelController(Context context, View panelView, boolean isManagedProfile) {
mContext = context;
mPanelView = panelView;
+ mIsManagedProfile = isManagedProfile;
mCornerRadius = context.getResources()
.getDimension(R.dimen.biometric_dialog_corner_size);
- mBiometricMargin = (int) context.getResources()
+ mMargin = (int) context.getResources()
.getDimension(R.dimen.biometric_dialog_border_padding);
mPanelView.setOutlineProvider(this);
mPanelView.setClipToOutline(true);
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/Utils.java b/packages/SystemUI/src/com/android/systemui/biometrics/Utils.java
index e00cf6abafaa..d6f830dd2e7a 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/Utils.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/Utils.java
@@ -18,14 +18,36 @@ package com.android.systemui.biometrics;
import static android.view.accessibility.AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE;
+import android.annotation.IntDef;
+import android.app.admin.DevicePolicyManager;
import android.content.Context;
+import android.hardware.biometrics.Authenticator;
+import android.hardware.biometrics.BiometricPrompt;
+import android.os.Bundle;
+import android.os.UserManager;
import android.util.DisplayMetrics;
import android.view.View;
import android.view.ViewGroup;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityManager;
+import com.android.internal.widget.LockPatternUtils;
+import com.android.systemui.R;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
public class Utils {
+
+ public static final int CREDENTIAL_PIN = 1;
+ public static final int CREDENTIAL_PATTERN = 2;
+ public static final int CREDENTIAL_PASSWORD = 3;
+
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({CREDENTIAL_PIN, CREDENTIAL_PATTERN, CREDENTIAL_PASSWORD})
+ @interface CredentialType {}
+
+
static float dpToPixels(Context context, float dp) {
return dp * ((float) context.getResources().getDisplayMetrics().densityDpi
/ DisplayMetrics.DENSITY_DEFAULT);
@@ -46,4 +68,41 @@ public class Utils {
view.sendAccessibilityEventUnchecked(event);
view.notifySubtreeAccessibilityStateChanged(view, view, CONTENT_CHANGE_TYPE_SUBTREE);
}
+
+ static boolean isDeviceCredentialAllowed(Bundle biometricPromptBundle) {
+ final int authenticators = getAuthenticators(biometricPromptBundle);
+ return (authenticators & Authenticator.TYPE_CREDENTIAL) != 0;
+ }
+
+ static boolean isBiometricAllowed(Bundle biometricPromptBundle) {
+ final int authenticators = getAuthenticators(biometricPromptBundle);
+ return (authenticators & Authenticator.TYPE_BIOMETRIC) != 0;
+ }
+
+ static int getAuthenticators(Bundle biometricPromptBundle) {
+ return biometricPromptBundle.getInt(BiometricPrompt.KEY_AUTHENTICATORS_ALLOWED);
+ }
+
+ static @CredentialType int getCredentialType(Context context, int userId) {
+ final LockPatternUtils lpu = new LockPatternUtils(context);
+ switch (lpu.getKeyguardStoredPasswordQuality(userId)) {
+ case DevicePolicyManager.PASSWORD_QUALITY_SOMETHING:
+ return CREDENTIAL_PATTERN;
+ case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC:
+ case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX:
+ return CREDENTIAL_PIN;
+ case DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC:
+ case DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC:
+ case DevicePolicyManager.PASSWORD_QUALITY_COMPLEX:
+ case DevicePolicyManager.PASSWORD_QUALITY_MANAGED:
+ return CREDENTIAL_PASSWORD;
+ default:
+ return CREDENTIAL_PASSWORD;
+ }
+ }
+
+ static boolean isManagedProfile(Context context, int userId) {
+ final UserManager userManager = context.getSystemService(UserManager.class);
+ return userManager.isManagedProfile(userId);
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/broadcast/BroadcastDispatcher.kt b/packages/SystemUI/src/com/android/systemui/broadcast/BroadcastDispatcher.kt
index f0e8c16e650a..ff4711cb208a 100644
--- a/packages/SystemUI/src/com/android/systemui/broadcast/BroadcastDispatcher.kt
+++ b/packages/SystemUI/src/com/android/systemui/broadcast/BroadcastDispatcher.kt
@@ -26,13 +26,12 @@ import android.os.UserHandle
import android.util.Log
import android.util.SparseArray
import com.android.internal.annotations.VisibleForTesting
-import com.android.systemui.Dependency.BG_LOOPER_NAME
-import com.android.systemui.Dependency.MAIN_HANDLER_NAME
import com.android.systemui.Dumpable
+import com.android.systemui.dagger.qualifiers.BgLooper
+import com.android.systemui.dagger.qualifiers.MainHandler
import java.io.FileDescriptor
import java.io.PrintWriter
import javax.inject.Inject
-import javax.inject.Named
import javax.inject.Singleton
data class ReceiverData(
@@ -61,8 +60,8 @@ private const val DEBUG = false
@Singleton
open class BroadcastDispatcher @Inject constructor (
private val context: Context,
- @Named(MAIN_HANDLER_NAME) private val mainHandler: Handler,
- @Named(BG_LOOPER_NAME) private val bgLooper: Looper
+ @MainHandler private val mainHandler: Handler,
+ @BgLooper private val bgLooper: Looper
) : Dumpable {
// Only modify in BG thread
@@ -75,7 +74,7 @@ open class BroadcastDispatcher @Inject constructor (
* @param filter A filter to determine what broadcasts should be dispatched to this receiver.
* It will only take into account actions and categories for filtering.
* @param handler A handler to dispatch [BroadcastReceiver.onReceive]. By default, it is the
- * main handler.
+ * main handler. Pass `null` to use the default.
* @param user A user handle to determine which broadcast should be dispatched to this receiver.
* By default, it is the current user.
*/
@@ -83,10 +82,12 @@ open class BroadcastDispatcher @Inject constructor (
fun registerReceiver(
receiver: BroadcastReceiver,
filter: IntentFilter,
- handler: Handler = mainHandler,
+ handler: Handler? = mainHandler,
user: UserHandle = context.user
) {
- this.handler.obtainMessage(MSG_ADD_RECEIVER, ReceiverData(receiver, filter, handler, user))
+ this.handler
+ .obtainMessage(MSG_ADD_RECEIVER,
+ ReceiverData(receiver, filter, handler ?: mainHandler, user))
.sendToTarget()
}
diff --git a/packages/SystemUI/src/com/android/systemui/broadcast/UserBroadcastDispatcher.kt b/packages/SystemUI/src/com/android/systemui/broadcast/UserBroadcastDispatcher.kt
index d44b63e813e6..54f9950239c2 100644
--- a/packages/SystemUI/src/com/android/systemui/broadcast/UserBroadcastDispatcher.kt
+++ b/packages/SystemUI/src/com/android/systemui/broadcast/UserBroadcastDispatcher.kt
@@ -34,7 +34,7 @@ import java.util.concurrent.atomic.AtomicBoolean
private const val MSG_REGISTER_RECEIVER = 0
private const val MSG_UNREGISTER_RECEIVER = 1
-private const val TAG = "UniversalReceiver"
+private const val TAG = "UserBroadcastDispatcher"
private const val DEBUG = false
/**
@@ -97,7 +97,7 @@ class UserBroadcastDispatcher(
private val receiverToReceiverData = ArrayMap<BroadcastReceiver, MutableSet<ReceiverData>>()
override fun onReceive(context: Context, intent: Intent) {
- bgHandler.post(HandleBroadcastRunnable(actionsToReceivers, context, intent))
+ bgHandler.post(HandleBroadcastRunnable(actionsToReceivers, context, intent, pendingResult))
}
/**
@@ -160,7 +160,8 @@ class UserBroadcastDispatcher(
private class HandleBroadcastRunnable(
val actionsToReceivers: Map<String, Set<ReceiverData>>,
val context: Context,
- val intent: Intent
+ val intent: Intent,
+ val pendingResult: PendingResult
) : Runnable {
override fun run() {
if (DEBUG) Log.w(TAG, "Dispatching $intent")
@@ -171,6 +172,7 @@ class UserBroadcastDispatcher(
?.forEach {
it.handler.post {
if (DEBUG) Log.w(TAG, "Dispatching to ${it.receiver}")
+ it.receiver.pendingResult = pendingResult
it.receiver.onReceive(context, intent)
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/Bubble.java b/packages/SystemUI/src/com/android/systemui/bubbles/Bubble.java
index c3cee35d37fb..7600b2f3ed7a 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/Bubble.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/Bubble.java
@@ -83,23 +83,23 @@ class Bubble {
private boolean mSuppressFlyout;
public static String groupId(NotificationEntry entry) {
- UserHandle user = entry.notification.getUser();
- return user.getIdentifier() + "|" + entry.notification.getPackageName();
+ UserHandle user = entry.getSbn().getUser();
+ return user.getIdentifier() + "|" + entry.getSbn().getPackageName();
}
/** Used in tests when no UI is required. */
@VisibleForTesting(visibility = PRIVATE)
Bubble(Context context, NotificationEntry e) {
mEntry = e;
- mKey = e.key;
- mLastUpdated = e.notification.getPostTime();
+ mKey = e.getKey();
+ mLastUpdated = e.getSbn().getPostTime();
mGroupId = groupId(e);
PackageManager pm = context.getPackageManager();
ApplicationInfo info;
try {
info = pm.getApplicationInfo(
- mEntry.notification.getPackageName(),
+ mEntry.getSbn().getPackageName(),
PackageManager.MATCH_UNINSTALLED_PACKAGES
| PackageManager.MATCH_DISABLED_COMPONENTS
| PackageManager.MATCH_DIRECT_BOOT_UNAWARE
@@ -107,10 +107,10 @@ class Bubble {
if (info != null) {
mAppName = String.valueOf(pm.getApplicationLabel(info));
}
- Drawable appIcon = pm.getApplicationIcon(mEntry.notification.getPackageName());
- mUserBadgedAppIcon = pm.getUserBadgedIcon(appIcon, mEntry.notification.getUser());
+ Drawable appIcon = pm.getApplicationIcon(mEntry.getSbn().getPackageName());
+ mUserBadgedAppIcon = pm.getUserBadgedIcon(appIcon, mEntry.getSbn().getUser());
} catch (PackageManager.NameNotFoundException unused) {
- mAppName = mEntry.notification.getPackageName();
+ mAppName = mEntry.getSbn().getPackageName();
}
}
@@ -127,7 +127,7 @@ class Bubble {
}
public String getPackageName() {
- return mEntry.notification.getPackageName();
+ return mEntry.getSbn().getPackageName();
}
public String getAppName() {
@@ -190,7 +190,7 @@ class Bubble {
void updateEntry(NotificationEntry entry) {
mEntry = entry;
- mLastUpdated = entry.notification.getPostTime();
+ mLastUpdated = entry.getSbn().getPostTime();
if (mInflated) {
mIconView.update(this);
mExpandedView.update(this);
@@ -287,7 +287,7 @@ class Bubble {
* is an ongoing bubble.
*/
boolean isOngoing() {
- int flags = mEntry.notification.getNotification().flags;
+ int flags = mEntry.getSbn().getNotification().flags;
return (flags & Notification.FLAG_FOREGROUND_SERVICE) != 0;
}
@@ -296,8 +296,8 @@ class Bubble {
boolean useRes = data.getDesiredHeightResId() != 0;
if (useRes) {
return getDimenForPackageUser(context, data.getDesiredHeightResId(),
- mEntry.notification.getPackageName(),
- mEntry.notification.getUser().getIdentifier());
+ mEntry.getSbn().getPackageName(),
+ mEntry.getSbn().getUser().getIdentifier());
} else {
return data.getDesiredHeight()
* context.getResources().getDisplayMetrics().density;
@@ -316,7 +316,7 @@ class Bubble {
@Nullable
PendingIntent getBubbleIntent(Context context) {
- Notification notif = mEntry.notification.getNotification();
+ Notification notif = mEntry.getSbn().getNotification();
Notification.BubbleMetadata data = notif.getBubbleMetadata();
if (BubbleController.canLaunchInActivityView(context, mEntry) && data != null) {
return data.getIntent();
@@ -327,7 +327,7 @@ class Bubble {
Intent getSettingsIntent() {
final Intent intent = new Intent(Settings.ACTION_APP_NOTIFICATION_BUBBLE_SETTINGS);
intent.putExtra(Settings.EXTRA_APP_PACKAGE, getPackageName());
- intent.putExtra(Settings.EXTRA_APP_UID, mEntry.notification.getUid());
+ intent.putExtra(Settings.EXTRA_APP_UID, mEntry.getSbn().getUid());
intent.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
@@ -339,7 +339,7 @@ class Bubble {
* notification, based on its type. Returns null if there should not be an update message.
*/
CharSequence getUpdateMessage(Context context) {
- final Notification underlyingNotif = mEntry.notification.getNotification();
+ final Notification underlyingNotif = mEntry.getSbn().getNotification();
final Class<? extends Notification.Style> style = underlyingNotif.getNotificationStyle();
try {
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
index 72ada6e90cd0..0231b562ad04 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
@@ -18,7 +18,6 @@ package com.android.systemui.bubbles;
import static android.app.Notification.FLAG_AUTOGROUP_SUMMARY;
import static android.app.Notification.FLAG_BUBBLE;
-import static android.content.pm.ActivityInfo.DOCUMENT_LAUNCH_ALWAYS;
import static android.service.notification.NotificationListenerService.REASON_APP_CANCEL;
import static android.service.notification.NotificationListenerService.REASON_APP_CANCEL_ALL;
import static android.service.notification.NotificationListenerService.REASON_CANCEL;
@@ -126,8 +125,6 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
static final int DISMISS_GROUP_CANCELLED = 9;
static final int DISMISS_INVALID_INTENT = 10;
- public static final int MAX_BUBBLES = 5; // TODO: actually enforce this
-
private final Context mContext;
private final NotificationEntryManager mNotificationEntryManager;
private final BubbleTaskStackListener mTaskStackListener;
@@ -265,7 +262,7 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
// More notifications could be added causing summary to no longer
// be suppressed -- in this case need to remove the key.
final String groupKey = group.summary != null
- ? group.summary.notification.getGroupKey()
+ ? group.summary.getSbn().getGroupKey()
: null;
if (!suppressed && groupKey != null
&& mBubbleData.isSummarySuppressed(groupKey)) {
@@ -349,7 +346,7 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
return;
}
for (NotificationEntry e : notificationData.getNotificationsForCurrentUser()) {
- if (savedBubbleKeys.contains(e.key)
+ if (savedBubbleKeys.contains(e.getKey())
&& mNotificationInterruptionStateProvider.shouldBubbleUp(e)
&& canLaunchInActivityView(mContext, e)) {
updateBubble(e, /* suppressFlyout= */ true);
@@ -448,7 +445,7 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
boolean isBubbleAndSuppressed = mBubbleData.hasBubbleWithKey(key)
&& !mBubbleData.getBubbleWithKey(key).showInShadeWhenBubble();
NotificationEntry entry = mNotificationEntryManager.getNotificationData().get(key);
- String groupKey = entry != null ? entry.notification.getGroupKey() : null;
+ String groupKey = entry != null ? entry.getSbn().getGroupKey() : null;
boolean isSuppressedSummary = mBubbleData.isSummarySuppressed(groupKey);
boolean isSummary = key.equals(mBubbleData.getSummaryKey(groupKey));
return (isSummary && isSuppressedSummary) || isBubbleAndSuppressed;
@@ -531,14 +528,14 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
@Override
public boolean onNotificationRemoveRequested(String key, int reason) {
NotificationEntry entry = mNotificationEntryManager.getNotificationData().get(key);
- String groupKey = entry != null ? entry.notification.getGroupKey() : null;
+ String groupKey = entry != null ? entry.getSbn().getGroupKey() : null;
ArrayList<Bubble> bubbleChildren = mBubbleData.getBubblesInGroup(groupKey);
boolean inBubbleData = mBubbleData.hasBubbleWithKey(key);
boolean isSuppressedSummary = (mBubbleData.isSummarySuppressed(groupKey)
&& mBubbleData.getSummaryKey(groupKey).equals(key));
boolean isSummary = entry != null
- && entry.notification.getNotification().isGroupSummary();
+ && entry.getSbn().getNotification().isGroupSummary();
boolean isSummaryOfBubbles = (isSuppressedSummary || isSummary)
&& bubbleChildren != null && !bubbleChildren.isEmpty();
@@ -569,9 +566,10 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
bubble.setShowInShadeWhenBubble(false);
bubble.setShowBubbleDot(false);
if (mStackView != null) {
- mStackView.updateDotVisibility(entry.key);
+ mStackView.updateDotVisibility(entry.getKey());
}
- mNotificationEntryManager.updateNotifications();
+ mNotificationEntryManager.updateNotifications(
+ "BubbleController.onNotificationRemoveRequested");
return true;
} else if (!userRemovedNotif && entry != null) {
// This wasn't a user removal so we should remove the bubble as well
@@ -584,7 +582,7 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
private boolean handleSummaryRemovalInterception(NotificationEntry summary,
boolean userRemovedNotif) {
- String groupKey = summary.notification.getGroupKey();
+ String groupKey = summary.getSbn().getGroupKey();
ArrayList<Bubble> bubbleChildren = mBubbleData.getBubblesInGroup(groupKey);
if (userRemovedNotif) {
@@ -605,13 +603,14 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
// If the summary was auto-generated we don't need to keep that notification around
// because apps can't cancel it; so we only intercept & suppress real summaries.
- boolean isAutogroupSummary = (summary.notification.getNotification().flags
+ boolean isAutogroupSummary = (summary.getSbn().getNotification().flags
& FLAG_AUTOGROUP_SUMMARY) != 0;
if (!isAutogroupSummary) {
- mBubbleData.addSummaryToSuppress(summary.notification.getGroupKey(),
- summary.key);
+ mBubbleData.addSummaryToSuppress(summary.getSbn().getGroupKey(),
+ summary.getKey());
// Tell shade to update for the suppression
- mNotificationEntryManager.updateNotifications();
+ mNotificationEntryManager.updateNotifications(
+ "BubbleController.handleSummaryRemovalInterception");
}
return !isAutogroupSummary;
} else {
@@ -642,11 +641,11 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
public void onPreEntryUpdated(NotificationEntry entry) {
boolean shouldBubble = mNotificationInterruptionStateProvider.shouldBubbleUp(entry)
&& canLaunchInActivityView(mContext, entry);
- if (!shouldBubble && mBubbleData.hasBubbleWithKey(entry.key)) {
+ if (!shouldBubble && mBubbleData.hasBubbleWithKey(entry.getKey())) {
// It was previously a bubble but no longer a bubble -- lets remove it
- removeBubble(entry.key, DISMISS_NO_LONGER_BUBBLE);
+ removeBubble(entry.getKey(), DISMISS_NO_LONGER_BUBBLE);
} else if (shouldBubble) {
- Bubble b = mBubbleData.getBubbleWithKey(entry.key);
+ Bubble b = mBubbleData.getBubbleWithKey(entry.getKey());
updateBubble(entry);
}
}
@@ -696,10 +695,10 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
&& !bubble.showInShadeWhenBubble()) {
// The bubble is gone & the notification is gone, time to actually remove it
mNotificationEntryManager.performRemoveNotification(
- bubble.getEntry().notification, UNDEFINED_DISMISS_REASON);
+ bubble.getEntry().getSbn(), UNDEFINED_DISMISS_REASON);
} else {
// Update the flag for SysUI
- bubble.getEntry().notification.getNotification().flags &= ~FLAG_BUBBLE;
+ bubble.getEntry().getSbn().getNotification().flags &= ~FLAG_BUBBLE;
// Make sure NoMan knows it's not a bubble anymore so anyone querying it
// will get right result back
@@ -713,7 +712,7 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
// Check if removed bubble has an associated suppressed group summary that needs
// to be removed now.
- final String groupKey = bubble.getEntry().notification.getGroupKey();
+ final String groupKey = bubble.getEntry().getSbn().getGroupKey();
if (mBubbleData.isSummarySuppressed(groupKey)
&& mBubbleData.getBubblesInGroup(groupKey).isEmpty()) {
// Time to actually remove the summary.
@@ -722,20 +721,21 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
NotificationEntry entry =
mNotificationEntryManager.getNotificationData().get(notifKey);
mNotificationEntryManager.performRemoveNotification(
- entry.notification, UNDEFINED_DISMISS_REASON);
+ entry.getSbn(), UNDEFINED_DISMISS_REASON);
}
// Check if summary should be removed from NoManGroup
NotificationEntry summary = mNotificationGroupManager.getLogicalGroupSummary(
- bubble.getEntry().notification);
+ bubble.getEntry().getSbn());
if (summary != null) {
ArrayList<NotificationEntry> summaryChildren =
- mNotificationGroupManager.getLogicalChildren(summary.notification);
- boolean isSummaryThisNotif = summary.key.equals(bubble.getEntry().key);
+ mNotificationGroupManager.getLogicalChildren(summary.getSbn());
+ boolean isSummaryThisNotif = summary.getKey().equals(
+ bubble.getEntry().getKey());
if (!isSummaryThisNotif
&& (summaryChildren == null || summaryChildren.isEmpty())) {
mNotificationEntryManager.performRemoveNotification(
- summary.notification, UNDEFINED_DISMISS_REASON);
+ summary.getSbn(), UNDEFINED_DISMISS_REASON);
}
}
}
@@ -762,7 +762,8 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
mStackView.setExpanded(true);
}
- mNotificationEntryManager.updateNotifications();
+ mNotificationEntryManager.updateNotifications(
+ "BubbleData.Listener.applyUpdate");
updateStack();
if (DEBUG_BUBBLE_CONTROLLER) {
@@ -964,16 +965,6 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
+ intent);
return false;
}
- if (info.documentLaunchMode != DOCUMENT_LAUNCH_ALWAYS) {
- Log.w(TAG, "Unable to send as bubble -- activity is not documentLaunchMode=always "
- + "for intent: " + intent);
- return false;
- }
- if ((info.flags & ActivityInfo.FLAG_ALLOW_EMBEDDED) == 0) {
- Log.w(TAG, "Unable to send as bubble -- activity is not embeddable for intent: "
- + intent);
- return false;
- }
return true;
}
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleData.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleData.java
index d43e030ed9eb..4e229c00b891 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleData.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleData.java
@@ -183,8 +183,8 @@ public class BubbleData {
if (DEBUG_BUBBLE_DATA) {
Log.d(TAG, "notificationEntryUpdated: " + entry);
}
- Bubble bubble = getBubbleWithKey(entry.key);
- suppressFlyout = !entry.isVisuallyInterruptive || suppressFlyout;
+ Bubble bubble = getBubbleWithKey(entry.getKey());
+ suppressFlyout = !entry.getRanking().visuallyInterruptive() || suppressFlyout;
if (bubble == null) {
// Create a new bubble
@@ -217,7 +217,7 @@ public class BubbleData {
if (DEBUG_BUBBLE_DATA) {
Log.d(TAG, "notificationEntryRemoved: entry=" + entry + " reason=" + reason);
}
- doRemove(entry.key, reason);
+ doRemove(entry.getKey(), reason);
dispatchPendingChanges();
}
@@ -290,7 +290,7 @@ public class BubbleData {
return bubbleChildren;
}
for (Bubble b : mBubbles) {
- if (groupKey.equals(b.getEntry().notification.getGroupKey())) {
+ if (groupKey.equals(b.getEntry().getSbn().getGroupKey())) {
bubbleChildren.add(b);
}
}
@@ -633,7 +633,8 @@ public class BubbleData {
try {
deleteIntent.send();
} catch (PendingIntent.CanceledException e) {
- Log.w(TAG, "Failed to send delete intent for bubble with key: " + entry.key);
+ Log.w(TAG, "Failed to send delete intent for bubble with key: "
+ + entry.getKey());
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java
index 521ebde7d2f0..1d9f6b27fcdd 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java
@@ -16,6 +16,8 @@
package com.android.systemui.bubbles;
+import static android.content.Intent.FLAG_ACTIVITY_MULTIPLE_TASK;
+import static android.content.Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
import static android.view.Display.INVALID_DISPLAY;
import static com.android.systemui.bubbles.BubbleDebugConfig.DEBUG_BUBBLE_EXPANDED_VIEW;
@@ -128,8 +130,12 @@ public class BubbleExpandedView extends LinearLayout implements View.OnClickList
Log.d(TAG, "onActivityViewReady: calling startActivity, "
+ "bubble=" + getBubbleKey());
}
+ Intent fillInIntent = new Intent();
+ // Apply flags to make behaviour match documentLaunchMode=always.
+ fillInIntent.addFlags(FLAG_ACTIVITY_NEW_DOCUMENT);
+ fillInIntent.addFlags(FLAG_ACTIVITY_MULTIPLE_TASK);
try {
- mActivityView.startActivity(mBubbleIntent, options);
+ mActivityView.startActivity(mBubbleIntent, fillInIntent, options);
} catch (RuntimeException e) {
// If there's a runtime exception here then there's something
// wrong with the intent, we can't really recover / try to populate
@@ -495,7 +501,7 @@ public class BubbleExpandedView extends LinearLayout implements View.OnClickList
if (id == R.id.settings_button) {
Intent intent = mBubble.getSettingsIntent();
mStackView.collapseStack(() -> {
- mContext.startActivityAsUser(intent, mBubble.getEntry().notification.getUser());
+ mContext.startActivityAsUser(intent, mBubble.getEntry().getSbn().getUser());
logBubbleClickEvent(mBubble,
StatsLog.BUBBLE_UICHANGED__ACTION__HEADER_GO_TO_SETTINGS);
});
@@ -603,7 +609,7 @@ public class BubbleExpandedView extends LinearLayout implements View.OnClickList
* @param action the user interaction enum.
*/
private void logBubbleClickEvent(Bubble bubble, int action) {
- StatusBarNotification notification = bubble.getEntry().notification;
+ StatusBarNotification notification = bubble.getEntry().getSbn();
StatsLog.write(StatsLog.BUBBLE_UI_CHANGED,
notification.getPackageName(),
notification.getNotification().getChannelId(),
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
index 31cf853dce04..e5af3897dff2 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
@@ -181,7 +181,9 @@ public class BubbleStackView extends FrameLayout {
*/
private float mVerticalPosPercentBeforeRotation = -1;
+ private int mMaxBubbles;
private int mBubbleSize;
+ private int mBubbleElevation;
private int mBubblePaddingTop;
private int mBubbleTouchPadding;
private int mExpandedViewPadding;
@@ -326,7 +328,9 @@ public class BubbleStackView extends FrameLayout {
mInflater = LayoutInflater.from(context);
Resources res = getResources();
+ mMaxBubbles = res.getInteger(R.integer.bubbles_max_rendered);
mBubbleSize = res.getDimensionPixelSize(R.dimen.individual_bubble_size);
+ mBubbleElevation = res.getDimensionPixelSize(R.dimen.bubble_elevation);
mBubblePaddingTop = res.getDimensionPixelSize(R.dimen.bubble_padding_top);
mBubbleTouchPadding = res.getDimensionPixelSize(R.dimen.bubble_touch_padding);
mExpandedAnimateXDistance =
@@ -625,7 +629,7 @@ public class BubbleStackView extends FrameLayout {
}
Bubble topBubble = mBubbleData.getBubbles().get(0);
String appName = topBubble.getAppName();
- Notification notification = topBubble.getEntry().notification.getNotification();
+ Notification notification = topBubble.getEntry().getSbn().getNotification();
CharSequence titleCharSeq = notification.extras.getCharSequence(Notification.EXTRA_TITLE);
String titleStr = getResources().getString(R.string.stream_notification);
if (titleCharSeq != null) {
@@ -1597,8 +1601,7 @@ public class BubbleStackView extends FrameLayout {
for (int i = 0; i < bubbleCount; i++) {
BubbleView bv = (BubbleView) mBubbleContainer.getChildAt(i);
bv.updateDotVisibility(true /* animate */);
- bv.setZ((BubbleController.MAX_BUBBLES
- * getResources().getDimensionPixelSize(R.dimen.bubble_elevation)) - i);
+ bv.setZ((mMaxBubbles * mBubbleElevation) - i);
// If the dot is on the left, and so is the stack, we need to change the dot position.
if (bv.getDotPositionOnLeft() == mStackOnLeftOrWillBe) {
bv.setDotPosition(!mStackOnLeftOrWillBe, animate);
@@ -1678,7 +1681,7 @@ public class BubbleStackView extends FrameLayout {
*/
private void logBubbleEvent(@Nullable Bubble bubble, int action) {
if (bubble == null || bubble.getEntry() == null
- || bubble.getEntry().notification == null) {
+ || bubble.getEntry().getSbn() == null) {
StatsLog.write(StatsLog.BUBBLE_UI_CHANGED,
null /* package name */,
null /* notification channel */,
@@ -1692,7 +1695,7 @@ public class BubbleStackView extends FrameLayout {
false /* on-going bubble */,
false /* isAppForeground (unused) */);
} else {
- StatusBarNotification notification = bubble.getEntry().notification;
+ StatusBarNotification notification = bubble.getEntry().getSbn();
StatsLog.write(StatsLog.BUBBLE_UI_CHANGED,
notification.getPackageName(),
notification.getNotification().getChannelId(),
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleView.java
index 4512aa822e3b..fe4fa90a272d 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleView.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleView.java
@@ -39,7 +39,6 @@ import com.android.launcher3.icons.ShadowGenerator;
import com.android.systemui.Interpolators;
import com.android.systemui.R;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
-import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
/**
* A floating object on the screen that can post message updates.
@@ -141,15 +140,6 @@ public class BubbleView extends FrameLayout {
mUserBadgedAppIcon = appIcon;
}
- /**
- * @return the {@link ExpandableNotificationRow} view to display notification content when the
- * bubble is expanded.
- */
- @Nullable
- public ExpandableNotificationRow getRowView() {
- return (mBubble != null) ? mBubble.getEntry().getRow() : null;
- }
-
/** Changes the dot's visibility to match the bubble view's state. */
void updateDotVisibility(boolean animate) {
updateDotVisibility(animate, null /* after */);
@@ -230,7 +220,7 @@ public class BubbleView extends FrameLayout {
}
// Update icon.
Notification.BubbleMetadata metadata = mBubble.getEntry().getBubbleMetadata();
- Notification n = mBubble.getEntry().notification.getNotification();
+ Notification n = mBubble.getEntry().getSbn().getNotification();
Icon ic = metadata.getIcon();
boolean needsTint = ic.getType() != Icon.TYPE_ADAPTIVE_BITMAP;
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingLog.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingLog.java
index cb7c998fad8e..8105c6a6e940 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingLog.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingLog.java
@@ -37,7 +37,7 @@ import java.util.Locale;
* adb shell setprop debug.falsing_log true
*
* The log gets dumped as part of the SystemUI services. To dump on demand:
- * adb shell dumpsys activity service com.android.systemui SystemBars | grep -A 999 FALSING | less
+ * adb shell dumpsys activity service com.android.systemui StatusBar | grep -A 999 FALSING | less
*
* To dump into logcat:
* adb shell setprop debug.falsing_logcat true
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerProxy.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerProxy.java
index 914258f48b46..db85fa0a3203 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerProxy.java
@@ -17,7 +17,6 @@
package com.android.systemui.classifier;
import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.BRIGHTLINE_FALSING_MANAGER_ENABLED;
-import static com.android.systemui.Dependency.MAIN_HANDLER_NAME;
import android.content.Context;
import android.hardware.SensorManager;
@@ -31,6 +30,7 @@ import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.systemui.Dependency;
import com.android.systemui.classifier.brightline.BrightLineFalsingManager;
import com.android.systemui.classifier.brightline.FalsingDataProvider;
+import com.android.systemui.dagger.qualifiers.MainHandler;
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.plugins.FalsingPlugin;
import com.android.systemui.plugins.PluginListener;
@@ -41,7 +41,6 @@ import com.android.systemui.util.sensors.ProximitySensor;
import java.io.PrintWriter;
import javax.inject.Inject;
-import javax.inject.Named;
import javax.inject.Singleton;
/**
@@ -62,7 +61,7 @@ public class FalsingManagerProxy implements FalsingManager {
@Inject
FalsingManagerProxy(Context context, PluginManager pluginManager,
- @Named(MAIN_HANDLER_NAME) Handler handler,
+ @MainHandler Handler handler,
ProximitySensor proximitySensor,
DeviceConfigProxy deviceConfig) {
mProximitySensor = proximitySensor;
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/brightline/PointerCountClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/brightline/PointerCountClassifier.java
index 85a4d234b5df..b726c3e2783f 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/brightline/PointerCountClassifier.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/brightline/PointerCountClassifier.java
@@ -16,6 +16,9 @@
package com.android.systemui.classifier.brightline;
+import static com.android.systemui.classifier.Classifier.NOTIFICATION_DRAG_DOWN;
+import static com.android.systemui.classifier.Classifier.QUICK_SETTINGS;
+
import android.view.MotionEvent;
import java.util.Locale;
@@ -29,6 +32,7 @@ import java.util.Locale;
class PointerCountClassifier extends FalsingClassifier {
private static final int MAX_ALLOWED_POINTERS = 1;
+ private static final int MAX_ALLOWED_POINTERS_SWIPE_DOWN = 2;
private int mMaxPointerCount;
PointerCountClassifier(FalsingDataProvider dataProvider) {
@@ -50,6 +54,10 @@ class PointerCountClassifier extends FalsingClassifier {
@Override
public boolean isFalseTouch() {
+ int interactionType = getInteractionType();
+ if (interactionType == QUICK_SETTINGS || interactionType == NOTIFICATION_DRAG_DOWN) {
+ return mMaxPointerCount > MAX_ALLOWED_POINTERS_SWIPE_DOWN;
+ }
return mMaxPointerCount > MAX_ALLOWED_POINTERS;
}
diff --git a/packages/SystemUI/src/com/android/systemui/ActivityBinder.java b/packages/SystemUI/src/com/android/systemui/dagger/ActivityBinder.java
index 2c8a67270d94..4be610fcd9ee 100644
--- a/packages/SystemUI/src/com/android/systemui/ActivityBinder.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/ActivityBinder.java
@@ -14,10 +14,11 @@
* limitations under the License.
*/
-package com.android.systemui;
+package com.android.systemui.dagger;
import android.app.Activity;
+import com.android.systemui.ForegroundServicesDialog;
import com.android.systemui.tuner.TunerActivity;
import dagger.Binds;
diff --git a/packages/SystemUI/src/com/android/systemui/ComponentBinder.java b/packages/SystemUI/src/com/android/systemui/dagger/ComponentBinder.java
index 3b35c61e8eb2..4e4c06e9d447 100644
--- a/packages/SystemUI/src/com/android/systemui/ComponentBinder.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/ComponentBinder.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.systemui;
+package com.android.systemui.dagger;
import dagger.Binds;
import dagger.Module;
diff --git a/packages/SystemUI/src/com/android/systemui/ContextComponentHelper.java b/packages/SystemUI/src/com/android/systemui/dagger/ContextComponentHelper.java
index 2cf0f8dafcad..d6d1e418240a 100644
--- a/packages/SystemUI/src/com/android/systemui/ContextComponentHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/ContextComponentHelper.java
@@ -14,11 +14,13 @@
* limitations under the License.
*/
-package com.android.systemui;
+package com.android.systemui.dagger;
import android.app.Activity;
import android.app.Service;
+import com.android.systemui.SystemUI;
+
/**
* Interface necessary to make Dagger happy. See {@link ContextComponentResolver}.
*/
diff --git a/packages/SystemUI/src/com/android/systemui/ContextComponentResolver.java b/packages/SystemUI/src/com/android/systemui/dagger/ContextComponentResolver.java
index 995263240e2d..d7822c9fc6da 100644
--- a/packages/SystemUI/src/com/android/systemui/ContextComponentResolver.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/ContextComponentResolver.java
@@ -14,11 +14,13 @@
* limitations under the License.
*/
-package com.android.systemui;
+package com.android.systemui.dagger;
import android.app.Activity;
import android.app.Service;
+import com.android.systemui.SystemUI;
+
import java.util.Map;
import javax.inject.Inject;
diff --git a/packages/SystemUI/src/com/android/systemui/DependencyBinder.java b/packages/SystemUI/src/com/android/systemui/dagger/DependencyBinder.java
index 4df7f0d440df..9032c6fc8639 100644
--- a/packages/SystemUI/src/com/android/systemui/DependencyBinder.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/DependencyBinder.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2018 The Android Open Source Project
+ * Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,11 +14,13 @@
* limitations under the License.
*/
-package com.android.systemui;
+package com.android.systemui.dagger;
+import com.android.systemui.ActivityStarterDelegate;
import com.android.systemui.appops.AppOpsController;
import com.android.systemui.appops.AppOpsControllerImpl;
import com.android.systemui.classifier.FalsingManagerProxy;
+import com.android.systemui.doze.DozeHost;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.DarkIconDispatcher;
import com.android.systemui.plugins.FalsingManager;
@@ -30,7 +32,9 @@ import com.android.systemui.qs.QSHost;
import com.android.systemui.qs.QSTileHost;
import com.android.systemui.statusbar.NotificationRemoteInputManager;
import com.android.systemui.statusbar.StatusBarStateControllerImpl;
+import com.android.systemui.statusbar.SysuiStatusBarStateController;
import com.android.systemui.statusbar.phone.DarkIconDispatcherImpl;
+import com.android.systemui.statusbar.phone.DozeServiceHost;
import com.android.systemui.statusbar.phone.ManagedProfileController;
import com.android.systemui.statusbar.phone.ManagedProfileControllerImpl;
import com.android.systemui.statusbar.phone.StatusBarIconController;
@@ -48,8 +52,8 @@ import com.android.systemui.statusbar.policy.FlashlightController;
import com.android.systemui.statusbar.policy.FlashlightControllerImpl;
import com.android.systemui.statusbar.policy.HotspotController;
import com.android.systemui.statusbar.policy.HotspotControllerImpl;
-import com.android.systemui.statusbar.policy.KeyguardMonitor;
-import com.android.systemui.statusbar.policy.KeyguardMonitorImpl;
+import com.android.systemui.statusbar.policy.KeyguardStateController;
+import com.android.systemui.statusbar.policy.KeyguardStateControllerImpl;
import com.android.systemui.statusbar.policy.LocationController;
import com.android.systemui.statusbar.policy.LocationControllerImpl;
import com.android.systemui.statusbar.policy.NetworkController;
@@ -146,7 +150,8 @@ public abstract class DependencyBinder {
/**
*/
@Binds
- public abstract KeyguardMonitor provideKeyguardMonitor(KeyguardMonitorImpl controllerImpl);
+ public abstract KeyguardStateController provideKeyguardMonitor(
+ KeyguardStateControllerImpl controllerImpl);
/**
*/
@@ -198,6 +203,12 @@ public abstract class DependencyBinder {
/**
*/
@Binds
+ public abstract SysuiStatusBarStateController providesSysuiStatusBarStateController(
+ StatusBarStateControllerImpl statusBarStateControllerImpl);
+
+ /**
+ */
+ @Binds
public abstract StatusBarIconController provideStatusBarIconController(
StatusBarIconControllerImpl controllerImpl);
@@ -232,5 +243,10 @@ public abstract class DependencyBinder {
/**
*/
@Binds
- public abstract FalsingManager provideFalsingmanager(FalsingManagerProxy falsingManagerImpl);
+ public abstract FalsingManager provideFalsingManager(FalsingManagerProxy falsingManagerImpl);
+
+ /**
+ */
+ @Binds
+ public abstract DozeHost provideDozeHost(DozeServiceHost dozeServiceHost);
}
diff --git a/packages/SystemUI/src/com/android/systemui/DependencyProvider.java b/packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java
index 239cbfe38975..87434f344729 100644
--- a/packages/SystemUI/src/com/android/systemui/DependencyProvider.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2018 The Android Open Source Project
+ * Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,40 +14,37 @@
* limitations under the License.
*/
-package com.android.systemui;
+package com.android.systemui.dagger;
-import static com.android.systemui.Dependency.BG_HANDLER_NAME;
-import static com.android.systemui.Dependency.BG_LOOPER_NAME;
-import static com.android.systemui.Dependency.MAIN_HANDLER_NAME;
-import static com.android.systemui.Dependency.MAIN_LOOPER_NAME;
import static com.android.systemui.Dependency.TIME_TICK_HANDLER_NAME;
-import android.annotation.Nullable;
-import android.app.AlarmManager;
import android.app.INotificationManager;
import android.content.Context;
-import android.hardware.SensorPrivacyManager;
+import android.hardware.display.AmbientDisplayConfiguration;
import android.hardware.display.NightDisplayListener;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Process;
import android.os.ServiceManager;
-import android.os.UserHandle;
import android.util.DisplayMetrics;
import android.view.IWindowManager;
-import android.view.WindowManagerGlobal;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.statusbar.IStatusBarService;
-import com.android.settingslib.bluetooth.LocalBluetoothManager;
+import com.android.internal.widget.LockPatternUtils;
+import com.android.systemui.dagger.qualifiers.BgHandler;
+import com.android.systemui.dagger.qualifiers.BgLooper;
+import com.android.systemui.dagger.qualifiers.MainHandler;
+import com.android.systemui.dagger.qualifiers.MainLooper;
+import com.android.systemui.doze.AlwaysOnDisplayPolicy;
import com.android.systemui.plugins.PluginInitializerImpl;
import com.android.systemui.shared.plugins.PluginManager;
import com.android.systemui.shared.plugins.PluginManagerImpl;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.DevicePolicyManagerWrapper;
-import com.android.systemui.shared.system.PackageManagerWrapper;
import com.android.systemui.statusbar.NavigationBarController;
+import com.android.systemui.statusbar.NotificationRemoteInputManager;
import com.android.systemui.statusbar.phone.AutoHideController;
import com.android.systemui.statusbar.phone.ConfigurationControllerImpl;
import com.android.systemui.statusbar.policy.ConfigurationController;
@@ -65,6 +62,10 @@ import dagger.Provides;
/**
* Provides dependencies for the root component of sysui injection.
+ *
+ * Only SystemUI owned classes and instances should go in here. Other, framework-owned classes
+ * should go in {@link SystemServicesModule}.
+ *
* See SystemUI/docs/dagger.md
*/
@Module
@@ -73,7 +74,7 @@ public class DependencyProvider {
@Singleton
@Provides
@Named(TIME_TICK_HANDLER_NAME)
- public Handler provideHandler() {
+ public Handler provideTimeTickHandler() {
HandlerThread thread = new HandlerThread("TimeTick");
thread.start();
return new Handler(thread.getLooper());
@@ -81,7 +82,7 @@ public class DependencyProvider {
@Singleton
@Provides
- @Named(BG_LOOPER_NAME)
+ @BgLooper
public Looper provideBgLooper() {
HandlerThread thread = new HandlerThread("SysUiBg",
Process.THREAD_PRIORITY_BACKGROUND);
@@ -90,52 +91,50 @@ public class DependencyProvider {
}
/** Main Looper */
- @Singleton
@Provides
- @Named(MAIN_LOOPER_NAME)
+ @MainLooper
public Looper provideMainLooper() {
return Looper.getMainLooper();
}
@Singleton
@Provides
- @Named(BG_HANDLER_NAME)
- public Handler provideBgHandler(@Named(BG_LOOPER_NAME) Looper bgLooper) {
+ @BgHandler
+ public Handler provideBgHandler(@BgLooper Looper bgLooper) {
return new Handler(bgLooper);
}
@Singleton
@Provides
- @Named(MAIN_HANDLER_NAME)
- public Handler provideMainHandler(@Named(MAIN_LOOPER_NAME) Looper mainLooper) {
+ @MainHandler
+ public Handler provideMainHandler(@MainLooper Looper mainLooper) {
return new Handler(mainLooper);
}
- @Singleton
+ /** */
@Provides
- public DataSaverController provideDataSaverController(NetworkController networkController) {
- return networkController.getDataSaverController();
+ public AmbientDisplayConfiguration provideAmbientDispalyConfiguration(Context context) {
+ return new AmbientDisplayConfiguration(context);
}
- @Singleton
+ /** */
@Provides
- @Nullable
- public LocalBluetoothManager provideLocalBluetoothController(Context context,
- @Named(BG_HANDLER_NAME) Handler bgHandler) {
- return LocalBluetoothManager.create(context, bgHandler,
- UserHandle.ALL);
+ public Handler provideHandler() {
+ return new Handler();
}
@Singleton
@Provides
- public MetricsLogger provideMetricsLogger() {
- return new MetricsLogger();
+ public DataSaverController provideDataSaverController(NetworkController networkController) {
+ return networkController.getDataSaverController();
}
@Singleton
@Provides
- public IWindowManager provideIWindowManager() {
- return WindowManagerGlobal.getWindowManagerService();
+ // Single instance of DisplayMetrics, gets updated by StatusBar, but can be used
+ // anywhere it is needed.
+ public DisplayMetrics provideDisplayMetrics() {
+ return new DisplayMetrics();
}
@Singleton
@@ -155,29 +154,21 @@ public class DependencyProvider {
@Singleton
@Provides
- // Single instance of DisplayMetrics, gets updated by StatusBar, but can be used
- // anywhere it is needed.
- public DisplayMetrics provideDisplayMetrics() {
- return new DisplayMetrics();
- }
+ public LeakDetector provideLeakDetector() {
+ return LeakDetector.create();
- @Singleton
- @Provides
- public SensorPrivacyManager provideSensorPrivacyManager(Context context) {
- return context.getSystemService(SensorPrivacyManager.class);
}
@Singleton
@Provides
- public LeakDetector provideLeakDetector() {
- return LeakDetector.create();
-
+ public MetricsLogger provideMetricsLogger() {
+ return new MetricsLogger();
}
@Singleton
@Provides
public NightDisplayListener provideNightDisplayListener(Context context,
- @Named(BG_HANDLER_NAME) Handler bgHandler) {
+ @BgHandler Handler bgHandler) {
return new NightDisplayListener(context, bgHandler);
}
@@ -190,7 +181,7 @@ public class DependencyProvider {
@Singleton
@Provides
public NavigationBarController provideNavigationBarController(Context context,
- @Named(MAIN_HANDLER_NAME) Handler mainHandler) {
+ @MainHandler Handler mainHandler) {
return new NavigationBarController(context, mainHandler);
}
@@ -203,8 +194,11 @@ public class DependencyProvider {
@Singleton
@Provides
public AutoHideController provideAutoHideController(Context context,
- @Named(MAIN_HANDLER_NAME) Handler mainHandler) {
- return new AutoHideController(context, mainHandler);
+ @MainHandler Handler mainHandler,
+ NotificationRemoteInputManager notificationRemoteInputManager,
+ IWindowManager iWindowManager) {
+ return new AutoHideController(context, mainHandler, notificationRemoteInputManager,
+ iWindowManager);
}
@Singleton
@@ -221,21 +215,20 @@ public class DependencyProvider {
@Singleton
@Provides
- public PackageManagerWrapper providePackageManagerWrapper() {
- return PackageManagerWrapper.getInstance();
+ public DeviceProvisionedController provideDeviceProvisionedController(Context context,
+ @MainHandler Handler mainHandler) {
+ return new DeviceProvisionedControllerImpl(context, mainHandler);
}
- @Singleton
+ /** */
@Provides
- public DeviceProvisionedController provideDeviceProvisionedController(Context context,
- @Named(MAIN_HANDLER_NAME) Handler mainHandler) {
- return new DeviceProvisionedControllerImpl(context, mainHandler);
+ public LockPatternUtils provideLockPatternUtils(Context context) {
+ return new LockPatternUtils(context);
}
/** */
- @Singleton
@Provides
- public AlarmManager provideAlarmManager(Context context) {
- return context.getSystemService(AlarmManager.class);
+ public AlwaysOnDisplayPolicy provideAlwaysOnDisplayPolicy(Context context) {
+ return new AlwaysOnDisplayPolicy(context);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/ServiceBinder.java b/packages/SystemUI/src/com/android/systemui/dagger/ServiceBinder.java
index e761a2be0b0f..1f2c0a18f928 100644
--- a/packages/SystemUI/src/com/android/systemui/ServiceBinder.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/ServiceBinder.java
@@ -14,11 +14,13 @@
* limitations under the License.
*/
-package com.android.systemui;
+package com.android.systemui.dagger;
import android.app.Service;
+import com.android.systemui.ImageWallpaper;
import com.android.systemui.doze.DozeService;
+import com.android.systemui.keyguard.KeyguardService;
import dagger.Binds;
import dagger.Module;
@@ -30,8 +32,21 @@ import dagger.multibindings.IntoMap;
*/
@Module
public abstract class ServiceBinder {
+ /** */
@Binds
@IntoMap
@ClassKey(DozeService.class)
public abstract Service bindDozeService(DozeService service);
+
+ /** */
+ @Binds
+ @IntoMap
+ @ClassKey(ImageWallpaper.class)
+ public abstract Service bindImageWallpaper(ImageWallpaper service);
+
+ /** */
+ @Binds
+ @IntoMap
+ @ClassKey(KeyguardService.class)
+ public abstract Service bindKeyguardService(KeyguardService service);
}
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemServicesModule.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemServicesModule.java
new file mode 100644
index 000000000000..fffba8cc1639
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemServicesModule.java
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.dagger;
+
+import android.annotation.Nullable;
+import android.annotation.SuppressLint;
+import android.app.ActivityManager;
+import android.app.AlarmManager;
+import android.app.IActivityManager;
+import android.app.IWallpaperManager;
+import android.app.WallpaperManager;
+import android.content.Context;
+import android.content.res.Resources;
+import android.hardware.SensorPrivacyManager;
+import android.os.Handler;
+import android.os.PowerManager;
+import android.os.ServiceManager;
+import android.os.UserHandle;
+import android.view.IWindowManager;
+import android.view.WindowManager;
+import android.view.WindowManagerGlobal;
+
+import com.android.internal.util.LatencyTracker;
+import com.android.settingslib.bluetooth.LocalBluetoothManager;
+import com.android.systemui.dagger.qualifiers.BgHandler;
+import com.android.systemui.dagger.qualifiers.MainResources;
+import com.android.systemui.shared.system.PackageManagerWrapper;
+
+import javax.inject.Singleton;
+
+import dagger.Module;
+import dagger.Provides;
+
+/**
+ * Provides Non-SystemUI, Framework-Owned instances to the dependency graph.
+ */
+@Module
+public class SystemServicesModule {
+
+ @Singleton
+ @Provides
+ static AlarmManager provideAlarmManager(Context context) {
+ return context.getSystemService(AlarmManager.class);
+ }
+
+ @Singleton
+ @Provides
+ static IActivityManager provideIActivityManager() {
+ return ActivityManager.getService();
+ }
+
+ @Provides
+ @Nullable
+ static IWallpaperManager provideIWallPaperManager() {
+ return IWallpaperManager.Stub.asInterface(
+ ServiceManager.getService(Context.WALLPAPER_SERVICE));
+ }
+
+ @Singleton
+ @Provides
+ static IWindowManager provideIWindowManager() {
+ return WindowManagerGlobal.getWindowManagerService();
+ }
+
+ @Singleton
+ @Provides
+ static LatencyTracker provideLatencyTracker(Context context) {
+ return LatencyTracker.getInstance(context);
+ }
+
+ @SuppressLint("MissingPermission")
+ @Singleton
+ @Provides
+ @Nullable
+ static LocalBluetoothManager provideLocalBluetoothController(Context context,
+ @BgHandler Handler bgHandler) {
+ return LocalBluetoothManager.create(context, bgHandler, UserHandle.ALL);
+ }
+
+ @Singleton
+ @Provides
+ static PackageManagerWrapper providePackageManagerWrapper() {
+ return PackageManagerWrapper.getInstance();
+ }
+
+ /** */
+ @Singleton
+ @Provides
+ static PowerManager providePowerManager(Context context) {
+ return context.getSystemService(PowerManager.class);
+ }
+
+ @Provides
+ @MainResources
+ static Resources provideResources(Context context) {
+ return context.getResources();
+ }
+
+ @Singleton
+ @Provides
+ static SensorPrivacyManager provideSensorPrivacyManager(Context context) {
+ return context.getSystemService(SensorPrivacyManager.class);
+ }
+
+ @Provides
+ static WallpaperManager provideWallpaperManager(Context context) {
+ return (WallpaperManager) context.getSystemService(Context.WALLPAPER_SERVICE);
+ }
+
+ @Singleton
+ @Provides
+ static WindowManager provideWindowManager(Context context) {
+ return context.getSystemService(WindowManager.class);
+ }
+
+}
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIBinder.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIBinder.java
new file mode 100644
index 000000000000..71c2e389f059
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIBinder.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.dagger;
+
+import com.android.systemui.LatencyTester;
+import com.android.systemui.SystemUI;
+import com.android.systemui.keyguard.KeyguardViewMediator;
+import com.android.systemui.pip.PipUI;
+import com.android.systemui.power.PowerUI;
+import com.android.systemui.recents.Recents;
+import com.android.systemui.recents.RecentsModule;
+import com.android.systemui.util.leak.GarbageMonitor;
+import com.android.systemui.volume.VolumeUI;
+
+import dagger.Binds;
+import dagger.Module;
+import dagger.multibindings.ClassKey;
+import dagger.multibindings.IntoMap;
+
+/**
+ * SystemUI objects that are injectable should go here.
+ */
+@Module(includes = {RecentsModule.class})
+public abstract class SystemUIBinder {
+
+ /** Inject into GarbageMonitor.Service. */
+ @Binds
+ @IntoMap
+ @ClassKey(GarbageMonitor.Service.class)
+ public abstract SystemUI bindGarbageMonitorService(GarbageMonitor.Service service);
+
+ /** Inject into KeyguardViewMediator. */
+ @Binds
+ @IntoMap
+ @ClassKey(KeyguardViewMediator.class)
+ public abstract SystemUI bindKeyguardViewMediator(KeyguardViewMediator sysui);
+
+ /** Inject into LatencyTests. */
+ @Binds
+ @IntoMap
+ @ClassKey(LatencyTester.class)
+ public abstract SystemUI bindLatencyTester(LatencyTester sysui);
+
+ /** Inject into PipUI. */
+ @Binds
+ @IntoMap
+ @ClassKey(PipUI.class)
+ public abstract SystemUI bindPipUI(PipUI sysui);
+
+ /** Inject into PowerUI. */
+ @Binds
+ @IntoMap
+ @ClassKey(PowerUI.class)
+ public abstract SystemUI bindPowerUI(PowerUI sysui);
+
+ /** Inject into Recents. */
+ @Binds
+ @IntoMap
+ @ClassKey(Recents.class)
+ public abstract SystemUI bindRecents(Recents sysui);
+
+
+ /** Inject into VolumeUI. */
+ @Binds
+ @IntoMap
+ @ClassKey(VolumeUI.class)
+ public abstract SystemUI bindVolumeUI(VolumeUI sysui);
+
+}
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIDefaultModule.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIDefaultModule.java
index 262b5ec50d83..c95b50b195b3 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIDefaultModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIDefaultModule.java
@@ -14,15 +14,14 @@
* limitations under the License.
*/
-package com.android.systemui;
+package com.android.systemui.dagger;
import static com.android.systemui.Dependency.ALLOW_NOTIFICATION_LONG_PRESS_NAME;
import static com.android.systemui.Dependency.LEAK_REPORT_EMAIL_NAME;
-import android.content.Context;
-
import androidx.annotation.Nullable;
+import com.android.systemui.SystemUI;
import com.android.systemui.dock.DockManager;
import com.android.systemui.dock.DockManagerImpl;
import com.android.systemui.power.EnhancedEstimates;
@@ -40,6 +39,8 @@ import javax.inject.Singleton;
import dagger.Binds;
import dagger.Module;
import dagger.Provides;
+import dagger.multibindings.ClassKey;
+import dagger.multibindings.IntoMap;
/**
* A dagger module for injecting default implementations of components of System UI that may be
@@ -70,11 +71,13 @@ abstract class SystemUIDefaultModule {
abstract NotificationData.KeyguardEnvironment bindKeyguardEnvironment(
KeyguardEnvironmentImpl keyguardEnvironment);
- @Singleton
- @Provides
- static ShadeController provideShadeController(Context context) {
- return SysUiServiceProvider.getComponent(context, StatusBar.class);
- }
+ @Binds
+ abstract ShadeController provideShadeController(StatusBar statusBar);
+
+ @Binds
+ @IntoMap
+ @ClassKey(StatusBar.class)
+ public abstract SystemUI providesStatusBar(StatusBar statusBar);
@Singleton
@Provides
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIModule.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
index b0316e22de06..4e60f194e552 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
@@ -14,15 +14,17 @@
* limitations under the License.
*/
-package com.android.systemui;
+package com.android.systemui.dagger;
import android.annotation.Nullable;
import android.content.Context;
import android.content.pm.PackageManager;
+import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.systemui.assist.AssistModule;
import com.android.systemui.model.SysUiState;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.statusbar.notification.people.PeopleHubModule;
import com.android.systemui.statusbar.phone.KeyguardLiftController;
import com.android.systemui.util.sensors.AsyncSensorManager;
@@ -35,7 +37,9 @@ import dagger.Provides;
* A dagger module for injecting components of System UI that are not overridden by the System UI
* implementation.
*/
-@Module(includes = {AssistModule.class, ComponentBinder.class})
+@Module(includes = {AssistModule.class,
+ ComponentBinder.class,
+ PeopleHubModule.class})
public abstract class SystemUIModule {
@Singleton
@@ -43,11 +47,13 @@ public abstract class SystemUIModule {
@Nullable
static KeyguardLiftController provideKeyguardLiftController(Context context,
StatusBarStateController statusBarStateController,
- AsyncSensorManager asyncSensorManager) {
+ AsyncSensorManager asyncSensorManager,
+ KeyguardUpdateMonitor keyguardUpdateMonitor) {
if (!context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_FACE)) {
return null;
}
- return new KeyguardLiftController(statusBarStateController, asyncSensorManager);
+ return new KeyguardLiftController(statusBarStateController, asyncSensorManager,
+ keyguardUpdateMonitor);
}
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIRootComponent.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIRootComponent.java
index c70b2fc3292a..113c9c845d95 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIRootComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIRootComponent.java
@@ -14,16 +14,18 @@
* limitations under the License.
*/
-package com.android.systemui;
+package com.android.systemui.dagger;
import static com.android.systemui.Dependency.ALLOW_NOTIFICATION_LONG_PRESS_NAME;
import android.content.ContentProvider;
+import com.android.systemui.Dependency;
+import com.android.systemui.SystemUIAppComponentFactory;
+import com.android.systemui.SystemUIFactory;
import com.android.systemui.fragments.FragmentService;
import com.android.systemui.statusbar.phone.StatusBar;
import com.android.systemui.util.InjectionInflationController;
-import com.android.systemui.util.leak.GarbageMonitor;
import javax.inject.Named;
import javax.inject.Singleton;
@@ -37,13 +39,14 @@ import dagger.Component;
@Component(modules = {
DependencyProvider.class,
DependencyBinder.class,
+ SystemServicesModule.class,
SystemUIFactory.ContextHolder.class,
SystemUIModule.class,
SystemUIDefaultModule.class})
public interface SystemUIRootComponent {
/**
- * Creates a GarbageMonitor.
+ * Creates a ContextComponentHelper.
*/
@Singleton
ContextComponentHelper getContextComponentHelper();
@@ -72,12 +75,6 @@ public interface SystemUIRootComponent {
InjectionInflationController.ViewCreator createViewCreator();
/**
- * Creates a GarbageMonitor.
- */
- @Singleton
- GarbageMonitor createGarbageMonitor();
-
- /**
* Whether notification long press is allowed.
*/
@Named(ALLOW_NOTIFICATION_LONG_PRESS_NAME)
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIBinder.java b/packages/SystemUI/src/com/android/systemui/dagger/qualifiers/BgHandler.java
index 4531c892a022..bc6b83ba1def 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIBinder.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/qualifiers/BgHandler.java
@@ -14,23 +14,17 @@
* limitations under the License.
*/
-package com.android.systemui;
+package com.android.systemui.dagger.qualifiers;
-import com.android.systemui.keyguard.KeyguardViewMediator;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
-import dagger.Binds;
-import dagger.Module;
-import dagger.multibindings.ClassKey;
-import dagger.multibindings.IntoMap;
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
-/**
- * SystemUI objects that are injectable should go here.
- */
-@Module
-public abstract class SystemUIBinder {
- /** Inject into KeyguardViewMediator. */
- @Binds
- @IntoMap
- @ClassKey(KeyguardViewMediator.class)
- public abstract SystemUI bindKeyguardViewMediator(KeyguardViewMediator sysui);
+import javax.inject.Qualifier;
+
+@Qualifier
+@Documented
+@Retention(RUNTIME)
+public @interface BgHandler {
}
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/qualifiers/BgLooper.java b/packages/SystemUI/src/com/android/systemui/dagger/qualifiers/BgLooper.java
new file mode 100644
index 000000000000..2aadda1215d5
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/dagger/qualifiers/BgLooper.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.dagger.qualifiers;
+
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+
+import javax.inject.Qualifier;
+
+@Qualifier
+@Documented
+@Retention(RUNTIME)
+public @interface BgLooper {
+}
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/qualifiers/MainHandler.java b/packages/SystemUI/src/com/android/systemui/dagger/qualifiers/MainHandler.java
new file mode 100644
index 000000000000..79661fa4a738
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/dagger/qualifiers/MainHandler.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.dagger.qualifiers;
+
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+
+import javax.inject.Qualifier;
+
+@Qualifier
+@Documented
+@Retention(RUNTIME)
+public @interface MainHandler {
+}
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/qualifiers/MainLooper.java b/packages/SystemUI/src/com/android/systemui/dagger/qualifiers/MainLooper.java
new file mode 100644
index 000000000000..750d7d72035c
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/dagger/qualifiers/MainLooper.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.dagger.qualifiers;
+
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+
+import javax.inject.Qualifier;
+
+@Qualifier
+@Documented
+@Retention(RUNTIME)
+public @interface MainLooper {
+}
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/qualifiers/MainResources.java b/packages/SystemUI/src/com/android/systemui/dagger/qualifiers/MainResources.java
new file mode 100644
index 000000000000..3daeda550b4c
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/dagger/qualifiers/MainResources.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.dagger.qualifiers;
+
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+
+import javax.inject.Qualifier;
+
+@Qualifier
+@Documented
+@Retention(RUNTIME)
+public @interface MainResources {
+ // TODO: use attribute to get other, non-main resources?
+}
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeDockHandler.java b/packages/SystemUI/src/com/android/systemui/doze/DozeDockHandler.java
index 1d7e9eacbd2e..419fd622d1df 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeDockHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeDockHandler.java
@@ -82,7 +82,7 @@ public class DozeDockHandler implements DozeMachine.Part {
private void requestPulse(State dozeState) {
if (!mDozeHost.isPulsingBlocked() && dozeState.canPulse()) {
- mMachine.requestPulse(DozeLog.PULSE_REASON_DOCKING);
+ mMachine.requestPulse(DozeEvent.PULSE_REASON_DOCKING);
}
mPulsePending = false;
}
@@ -91,7 +91,7 @@ public class DozeDockHandler implements DozeMachine.Part {
if (dozeState == State.DOZE_REQUEST_PULSE || dozeState == State.DOZE_PULSING
|| dozeState == State.DOZE_PULSING_BRIGHT) {
final int pulseReason = mMachine.getPulseReason();
- if (pulseReason == DozeLog.PULSE_REASON_DOCKING) {
+ if (pulseReason == DozeEvent.PULSE_REASON_DOCKING) {
mDozeHost.stopPulsing();
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeEvent.java b/packages/SystemUI/src/com/android/systemui/doze/DozeEvent.java
new file mode 100644
index 000000000000..ea1def07a309
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeEvent.java
@@ -0,0 +1,154 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.doze;
+
+import android.annotation.IntDef;
+
+import com.android.systemui.log.RichEvent;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * An event related to dozing. {@link DozeLog} stores and prints these events for debugging
+ * and triaging purposes.
+ */
+public class DozeEvent extends RichEvent {
+ public static final int TOTAL_EVENT_TYPES = 19;
+
+ public DozeEvent(int logLevel, int type, String reason) {
+ super(logLevel, type, reason);
+ }
+
+ /**
+ * Event labels for each doze event
+ * Index corresponds to the integer associated with each {@link EventType}
+ */
+ @Override
+ public String[] getEventLabels() {
+ final String[] events = new String[]{
+ "PickupWakeup",
+ "PulseStart",
+ "PulseFinish",
+ "NotificationPulse",
+ "Dozing",
+ "Fling",
+ "EmergencyCall",
+ "KeyguardBouncerChanged",
+ "ScreenOn",
+ "ScreenOff",
+ "MissedTick",
+ "TimeTickScheduled",
+ "KeyguardVisibilityChanged",
+ "DozeStateChanged",
+ "WakeDisplay",
+ "ProximityResult",
+ "PulseDropped",
+ "PulseDisabledByProx",
+ "SensorTriggered"
+ };
+
+ if (events.length != TOTAL_EVENT_TYPES) {
+ throw new IllegalStateException("DozeEvent events.length should match TOTAL_EVENT_TYPES"
+ + " events.length=" + events.length
+ + " TOTAL_EVENT_LENGTH=" + TOTAL_EVENT_TYPES);
+ }
+ return events;
+ }
+
+ /**
+ * Converts the reason (integer) to a user-readable string
+ */
+ public static String reasonToString(@Reason int pulseReason) {
+ switch (pulseReason) {
+ case PULSE_REASON_INTENT: return "intent";
+ case PULSE_REASON_NOTIFICATION: return "notification";
+ case PULSE_REASON_SENSOR_SIGMOTION: return "sigmotion";
+ case REASON_SENSOR_PICKUP: return "pickup";
+ case REASON_SENSOR_DOUBLE_TAP: return "doubletap";
+ case PULSE_REASON_SENSOR_LONG_PRESS: return "longpress";
+ case PULSE_REASON_DOCKING: return "docking";
+ case PULSE_REASON_SENSOR_WAKE_LOCK_SCREEN: return "wakelockscreen";
+ case REASON_SENSOR_WAKE_UP: return "wakeup";
+ case REASON_SENSOR_TAP: return "tap";
+ default: throw new IllegalArgumentException("invalid reason: " + pulseReason);
+ }
+ }
+
+ /**
+ * Builds a DozeEvent.
+ */
+ public static class DozeEventBuilder extends RichEvent.Builder<DozeEventBuilder> {
+ @Override
+ public DozeEventBuilder getBuilder() {
+ return this;
+ }
+
+ @Override
+ public RichEvent build() {
+ return new DozeEvent(mLogLevel, mType, mReason);
+ }
+ }
+
+ @IntDef({PICKUP_WAKEUP, PULSE_START, PULSE_FINISH, NOTIFICATION_PULSE, DOZING, FLING,
+ EMERGENCY_CALL, KEYGUARD_BOUNCER_CHANGED, SCREEN_ON, SCREEN_OFF, MISSED_TICK,
+ TIME_TICK_SCHEDULED, KEYGUARD_VISIBILITY_CHANGE, DOZE_STATE_CHANGED, WAKE_DISPLAY,
+ PROXIMITY_RESULT, PULSE_DROPPED, PULSE_DISABLED_BY_PROX, SENSOR_TRIGGERED})
+ /**
+ * Types of DozeEvents
+ */
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface EventType {}
+ public static final int PICKUP_WAKEUP = 0;
+ public static final int PULSE_START = 1;
+ public static final int PULSE_FINISH = 2;
+ public static final int NOTIFICATION_PULSE = 3;
+ public static final int DOZING = 4;
+ public static final int FLING = 5;
+ public static final int EMERGENCY_CALL = 6;
+ public static final int KEYGUARD_BOUNCER_CHANGED = 7;
+ public static final int SCREEN_ON = 8;
+ public static final int SCREEN_OFF = 9;
+ public static final int MISSED_TICK = 10;
+ public static final int TIME_TICK_SCHEDULED = 11;
+ public static final int KEYGUARD_VISIBILITY_CHANGE = 12;
+ public static final int DOZE_STATE_CHANGED = 13;
+ public static final int WAKE_DISPLAY = 14;
+ public static final int PROXIMITY_RESULT = 15;
+ public static final int PULSE_DROPPED = 16;
+ public static final int PULSE_DISABLED_BY_PROX = 17;
+ public static final int SENSOR_TRIGGERED = 18;
+
+ public static final int TOTAL_REASONS = 10;
+ @IntDef({PULSE_REASON_NONE, PULSE_REASON_INTENT, PULSE_REASON_NOTIFICATION,
+ PULSE_REASON_SENSOR_SIGMOTION, REASON_SENSOR_PICKUP, REASON_SENSOR_DOUBLE_TAP,
+ PULSE_REASON_SENSOR_LONG_PRESS, PULSE_REASON_DOCKING, REASON_SENSOR_WAKE_UP,
+ PULSE_REASON_SENSOR_WAKE_LOCK_SCREEN, REASON_SENSOR_TAP})
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface Reason {}
+ public static final int PULSE_REASON_NONE = -1;
+ public static final int PULSE_REASON_INTENT = 0;
+ public static final int PULSE_REASON_NOTIFICATION = 1;
+ public static final int PULSE_REASON_SENSOR_SIGMOTION = 2;
+ public static final int REASON_SENSOR_PICKUP = 3;
+ public static final int REASON_SENSOR_DOUBLE_TAP = 4;
+ public static final int PULSE_REASON_SENSOR_LONG_PRESS = 5;
+ public static final int PULSE_REASON_DOCKING = 6;
+ public static final int REASON_SENSOR_WAKE_UP = 7;
+ public static final int PULSE_REASON_SENSOR_WAKE_LOCK_SCREEN = 8;
+ public static final int REASON_SENSOR_TAP = 9;
+}
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java b/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java
index bb8c7f1dabf8..33f68cfc1492 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java
@@ -16,8 +16,10 @@
package com.android.systemui.doze;
+import android.annotation.Nullable;
import android.app.AlarmManager;
import android.app.Application;
+import android.app.IWallpaperManager;
import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorManager;
@@ -25,7 +27,6 @@ import android.hardware.display.AmbientDisplayConfiguration;
import android.os.Handler;
import com.android.keyguard.KeyguardUpdateMonitor;
-import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.SystemUIApplication;
import com.android.systemui.dock.DockManager;
@@ -33,49 +34,84 @@ import com.android.systemui.keyguard.WakefulnessLifecycle;
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.statusbar.phone.BiometricUnlockController;
import com.android.systemui.statusbar.phone.DozeParameters;
+import com.android.systemui.statusbar.policy.BatteryController;
import com.android.systemui.util.sensors.AsyncSensorManager;
+import com.android.systemui.util.sensors.ProximitySensor;
import com.android.systemui.util.wakelock.DelayedWakeLock;
import com.android.systemui.util.wakelock.WakeLock;
+import javax.inject.Inject;
+
public class DozeFactory {
- public DozeFactory() {
+ private final FalsingManager mFalsingManager;
+ private final DozeLog mDozeLog;
+ private final DozeParameters mDozeParameters;
+ private final BatteryController mBatteryController;
+ private final AsyncSensorManager mAsyncSensorManager;
+ private final AlarmManager mAlarmManager;
+ private final WakefulnessLifecycle mWakefulnessLifecycle;
+ private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
+ private final DockManager mDockManager;
+ private final IWallpaperManager mWallpaperManager;
+ private final ProximitySensor mProximitySensor;
+ private final DelayedWakeLock.Builder mDelayedWakeLockBuilder;
+ private final Handler mHandler;
+ private final BiometricUnlockController mBiometricUnlockController;
+
+ @Inject
+ public DozeFactory(FalsingManager falsingManager, DozeLog dozeLog,
+ DozeParameters dozeParameters, BatteryController batteryController,
+ AsyncSensorManager asyncSensorManager, AlarmManager alarmManager,
+ WakefulnessLifecycle wakefulnessLifecycle, KeyguardUpdateMonitor keyguardUpdateMonitor,
+ DockManager dockManager, @Nullable IWallpaperManager wallpaperManager,
+ ProximitySensor proximitySensor,
+ DelayedWakeLock.Builder delayedWakeLockBuilder, Handler handler,
+ BiometricUnlockController biometricUnlockController) {
+ mFalsingManager = falsingManager;
+ mDozeLog = dozeLog;
+ mDozeParameters = dozeParameters;
+ mBatteryController = batteryController;
+ mAsyncSensorManager = asyncSensorManager;
+ mAlarmManager = alarmManager;
+ mWakefulnessLifecycle = wakefulnessLifecycle;
+ mKeyguardUpdateMonitor = keyguardUpdateMonitor;
+ mDockManager = dockManager;
+ mWallpaperManager = wallpaperManager;
+ mProximitySensor = proximitySensor;
+ mDelayedWakeLockBuilder = delayedWakeLockBuilder;
+ mHandler = handler;
+ mBiometricUnlockController = biometricUnlockController;
}
/** Creates a DozeMachine with its parts for {@code dozeService}. */
- public DozeMachine assembleMachine(DozeService dozeService, FalsingManager falsingManager) {
- Context context = dozeService;
- AsyncSensorManager sensorManager = Dependency.get(AsyncSensorManager.class);
- AlarmManager alarmManager = context.getSystemService(AlarmManager.class);
- DockManager dockManager = Dependency.get(DockManager.class);
- WakefulnessLifecycle wakefulnessLifecycle = Dependency.get(WakefulnessLifecycle.class);
-
+ DozeMachine assembleMachine(DozeService dozeService) {
DozeHost host = getHost(dozeService);
- AmbientDisplayConfiguration config = new AmbientDisplayConfiguration(context);
- DozeParameters params = DozeParameters.getInstance(context);
- Handler handler = new Handler();
- WakeLock wakeLock = new DelayedWakeLock(handler,
- WakeLock.createPartial(context, "Doze"));
+ AmbientDisplayConfiguration config = new AmbientDisplayConfiguration(dozeService);
+ WakeLock wakeLock = mDelayedWakeLockBuilder.setHandler(mHandler).setTag("Doze").build();
DozeMachine.Service wrappedService = dozeService;
wrappedService = new DozeBrightnessHostForwarder(wrappedService, host);
- wrappedService = DozeScreenStatePreventingAdapter.wrapIfNeeded(wrappedService, params);
- wrappedService = DozeSuspendScreenStatePreventingAdapter.wrapIfNeeded(wrappedService,
- params);
+ wrappedService = DozeScreenStatePreventingAdapter.wrapIfNeeded(
+ wrappedService, mDozeParameters);
+ wrappedService = DozeSuspendScreenStatePreventingAdapter.wrapIfNeeded(
+ wrappedService, mDozeParameters);
DozeMachine machine = new DozeMachine(wrappedService, config, wakeLock,
- wakefulnessLifecycle);
+ mWakefulnessLifecycle, mBatteryController, mDozeLog);
machine.setParts(new DozeMachine.Part[]{
- new DozePauser(handler, machine, alarmManager, params.getPolicy()),
- new DozeFalsingManagerAdapter(falsingManager),
- createDozeTriggers(context, sensorManager, host, alarmManager, config, params,
- handler, wakeLock, machine, dockManager),
- createDozeUi(context, host, wakeLock, machine, handler, alarmManager, params),
- new DozeScreenState(wrappedService, handler, params, wakeLock),
- createDozeScreenBrightness(context, wrappedService, sensorManager, host, params,
- handler),
- new DozeWallpaperState(context, getBiometricUnlockController(dozeService)),
- new DozeDockHandler(context, machine, host, config, handler, dockManager),
+ new DozePauser(mHandler, machine, mAlarmManager, mDozeParameters.getPolicy()),
+ new DozeFalsingManagerAdapter(mFalsingManager),
+ createDozeTriggers(dozeService, mAsyncSensorManager, host, mAlarmManager, config,
+ mDozeParameters, mHandler, wakeLock, machine, mDockManager, mDozeLog),
+ createDozeUi(dozeService, host, wakeLock, machine, mHandler, mAlarmManager,
+ mDozeParameters, mDozeLog),
+ new DozeScreenState(wrappedService, mHandler, host, mDozeParameters, wakeLock),
+ createDozeScreenBrightness(dozeService, wrappedService, mAsyncSensorManager, host,
+ mDozeParameters, mHandler),
+ new DozeWallpaperState(
+ mWallpaperManager, mBiometricUnlockController, mDozeParameters),
+ new DozeDockHandler(dozeService, machine, host, config, mHandler, mDockManager),
new DozeAuthRemover(dozeService)
});
@@ -94,17 +130,19 @@ public class DozeFactory {
private DozeTriggers createDozeTriggers(Context context, AsyncSensorManager sensorManager,
DozeHost host, AlarmManager alarmManager, AmbientDisplayConfiguration config,
DozeParameters params, Handler handler, WakeLock wakeLock, DozeMachine machine,
- DockManager dockManager) {
+ DockManager dockManager, DozeLog dozeLog) {
boolean allowPulseTriggers = true;
return new DozeTriggers(context, machine, host, alarmManager, config, params,
- sensorManager, handler, wakeLock, allowPulseTriggers, dockManager);
+ sensorManager, handler, wakeLock, allowPulseTriggers, dockManager,
+ mProximitySensor, dozeLog);
+
}
private DozeMachine.Part createDozeUi(Context context, DozeHost host, WakeLock wakeLock,
DozeMachine machine, Handler handler, AlarmManager alarmManager,
- DozeParameters params) {
+ DozeParameters params, DozeLog dozeLog) {
return new DozeUi(context, alarmManager, machine, wakeLock, host, handler, params,
- Dependency.get(KeyguardUpdateMonitor.class));
+ mKeyguardUpdateMonitor, dozeLog);
}
public static DozeHost getHost(DozeService service) {
@@ -112,10 +150,4 @@ public class DozeFactory {
final SystemUIApplication app = (SystemUIApplication) appCandidate;
return app.getComponent(DozeHost.class);
}
-
- public static BiometricUnlockController getBiometricUnlockController(DozeService service) {
- Application appCandidate = service.getApplication();
- final SystemUIApplication app = (SystemUIApplication) appCandidate;
- return app.getComponent(BiometricUnlockController.class);
- }
}
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeHost.java b/packages/SystemUI/src/com/android/systemui/doze/DozeHost.java
index 07dd2cd77043..d1047e216ec4 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeHost.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeHost.java
@@ -63,9 +63,16 @@ public interface DozeHost {
void setDozeScreenBrightness(int value);
/**
- * Makes scrims black and changes animation durations.
+ * Fade out screen before switching off the display power mode.
+ * @param onDisplayOffCallback Executed when the display is black.
*/
- default void prepareForGentleWakeUp() {}
+ void prepareForGentleSleep(Runnable onDisplayOffCallback);
+
+ /**
+ * Cancel pending {@code onDisplayOffCallback} callback.
+ * @see #prepareForGentleSleep(Runnable)
+ */
+ void cancelGentleSleep();
void onIgnoreTouchWhilePulsing(boolean ignore);
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeLog.java b/packages/SystemUI/src/com/android/systemui/doze/DozeLog.java
index 8fe9f929b880..2e4466d47927 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeLog.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeLog.java
@@ -16,282 +16,284 @@
package com.android.systemui.doze;
-import android.content.Context;
-import android.os.Build;
-import android.util.Log;
import android.util.TimeUtils;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.keyguard.KeyguardUpdateMonitorCallback;
-import com.android.systemui.Dependency;
+import com.android.systemui.DumpController;
+import com.android.systemui.log.SysuiLog;
import java.io.PrintWriter;
-import java.text.SimpleDateFormat;
import java.util.Date;
-public class DozeLog {
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+/**
+ * Logs doze events for debugging and triaging purposes. Logs are dumped in bugreports or on demand:
+ * adb shell dumpsys activity service com.android.systemui/.SystemUIService \
+ * dependency DumpController DozeLog
+ */
+@Singleton
+public class DozeLog extends SysuiLog {
private static final String TAG = "DozeLog";
- private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
- private static final boolean ENABLED = true;
- private static final int SIZE = Build.IS_DEBUGGABLE ? 400 : 50;
- static final SimpleDateFormat FORMAT = new SimpleDateFormat("MM-dd HH:mm:ss.SSS");
-
- public static final int REASONS = 10;
-
- public static final int PULSE_REASON_NONE = -1;
- public static final int PULSE_REASON_INTENT = 0;
- public static final int PULSE_REASON_NOTIFICATION = 1;
- public static final int PULSE_REASON_SENSOR_SIGMOTION = 2;
- public static final int REASON_SENSOR_PICKUP = 3;
- public static final int REASON_SENSOR_DOUBLE_TAP = 4;
- public static final int PULSE_REASON_SENSOR_LONG_PRESS = 5;
- public static final int PULSE_REASON_DOCKING = 6;
- public static final int REASON_SENSOR_WAKE_UP = 7;
- public static final int PULSE_REASON_SENSOR_WAKE_LOCK_SCREEN = 8;
- public static final int REASON_SENSOR_TAP = 9;
-
- private static boolean sRegisterKeyguardCallback = true;
-
- private static long[] sTimes;
- private static String[] sMessages;
- private static int sPosition;
- private static int sCount;
- private static boolean sPulsing;
-
- private static long sSince;
- private static SummaryStats sPickupPulseNearVibrationStats;
- private static SummaryStats sPickupPulseNotNearVibrationStats;
- private static SummaryStats sNotificationPulseStats;
- private static SummaryStats sScreenOnPulsingStats;
- private static SummaryStats sScreenOnNotPulsingStats;
- private static SummaryStats sEmergencyCallStats;
- private static SummaryStats[][] sProxStats; // [reason][near/far]
-
- public static void tracePickupWakeUp(Context context, boolean withinVibrationThreshold) {
- if (!ENABLED) return;
- init(context);
- log("pickupWakeUp withinVibrationThreshold=" + withinVibrationThreshold);
- (withinVibrationThreshold ? sPickupPulseNearVibrationStats
- : sPickupPulseNotNearVibrationStats).append();
+
+ private boolean mPulsing;
+ private long mSince;
+ private SummaryStats mPickupPulseNearVibrationStats;
+ private SummaryStats mPickupPulseNotNearVibrationStats;
+ private SummaryStats mNotificationPulseStats;
+ private SummaryStats mScreenOnPulsingStats;
+ private SummaryStats mScreenOnNotPulsingStats;
+ private SummaryStats mEmergencyCallStats;
+ private SummaryStats[][] mProxStats; // [reason][near/far]
+
+ @Inject
+ public DozeLog(KeyguardUpdateMonitor keyguardUpdateMonitor, DumpController dumpController) {
+ super(dumpController, TAG, MAX_DOZE_DEBUG_LOGS, MAX_DOZE_LOGS);
+ mSince = System.currentTimeMillis();
+ mPickupPulseNearVibrationStats = new SummaryStats();
+ mPickupPulseNotNearVibrationStats = new SummaryStats();
+ mNotificationPulseStats = new SummaryStats();
+ mScreenOnPulsingStats = new SummaryStats();
+ mScreenOnNotPulsingStats = new SummaryStats();
+ mEmergencyCallStats = new SummaryStats();
+ mProxStats = new SummaryStats[DozeEvent.TOTAL_REASONS][2];
+ for (int i = 0; i < DozeEvent.TOTAL_REASONS; i++) {
+ mProxStats[i][0] = new SummaryStats();
+ mProxStats[i][1] = new SummaryStats();
+ }
+
+ if (keyguardUpdateMonitor != null) {
+ keyguardUpdateMonitor.registerCallback(mKeyguardCallback);
+ }
}
- public static void tracePulseStart(int reason) {
- if (!ENABLED) return;
- sPulsing = true;
- log("pulseStart reason=" + reasonToString(reason));
+ /**
+ * Appends pickup wakeup event to the logs
+ */
+ public void tracePickupWakeUp(boolean withinVibrationThreshold) {
+ if (log(DozeEvent.PICKUP_WAKEUP,
+ "withinVibrationThreshold=" + withinVibrationThreshold)) {
+ (withinVibrationThreshold ? mPickupPulseNearVibrationStats
+ : mPickupPulseNotNearVibrationStats).append();
+ }
}
- public static void tracePulseFinish() {
- if (!ENABLED) return;
- sPulsing = false;
- log("pulseFinish");
+ /**
+ * Appends pulse started event to the logs.
+ * @param reason why the pulse started
+ */
+ public void tracePulseStart(@DozeEvent.Reason int reason) {
+ if (log(DozeEvent.PULSE_START, DozeEvent.reasonToString(reason))) {
+ mPulsing = true;
+ }
}
- public static void traceNotificationPulse(Context context) {
- if (!ENABLED) return;
- init(context);
- log("notificationPulse");
- sNotificationPulseStats.append();
+ /**
+ * Appends pulse finished event to the logs
+ */
+ public void tracePulseFinish() {
+ if (log(DozeEvent.PULSE_FINISH)) {
+ mPulsing = false;
+ }
}
- private static void init(Context context) {
- synchronized (DozeLog.class) {
- if (sMessages == null) {
- sTimes = new long[SIZE];
- sMessages = new String[SIZE];
- sSince = System.currentTimeMillis();
- sPickupPulseNearVibrationStats = new SummaryStats();
- sPickupPulseNotNearVibrationStats = new SummaryStats();
- sNotificationPulseStats = new SummaryStats();
- sScreenOnPulsingStats = new SummaryStats();
- sScreenOnNotPulsingStats = new SummaryStats();
- sEmergencyCallStats = new SummaryStats();
- sProxStats = new SummaryStats[REASONS][2];
- for (int i = 0; i < REASONS; i++) {
- sProxStats[i][0] = new SummaryStats();
- sProxStats[i][1] = new SummaryStats();
- }
- log("init");
- if (sRegisterKeyguardCallback) {
- Dependency.get(KeyguardUpdateMonitor.class).registerCallback(sKeyguardCallback);
- }
- }
+ /**
+ * Appends pulse event to the logs
+ */
+ public void traceNotificationPulse() {
+ if (log(DozeEvent.NOTIFICATION_PULSE)) {
+ mNotificationPulseStats.append();
}
}
- public static void traceDozing(Context context, boolean dozing) {
- if (!ENABLED) return;
- sPulsing = false;
- init(context);
- log("dozing " + dozing);
+ /**
+ * Appends dozing event to the logs
+ * @param dozing true if dozing, else false
+ */
+ public void traceDozing(boolean dozing) {
+ if (log(DozeEvent.DOZING, "dozing=" + dozing)) {
+ mPulsing = false;
+ }
}
- public static void traceFling(boolean expand, boolean aboveThreshold, boolean thresholdNeeded,
+ /**
+ * Appends fling event to the logs
+ */
+ public void traceFling(boolean expand, boolean aboveThreshold, boolean thresholdNeeded,
boolean screenOnFromTouch) {
- if (!ENABLED) return;
- log("fling expand=" + expand + " aboveThreshold=" + aboveThreshold + " thresholdNeeded="
- + thresholdNeeded + " screenOnFromTouch=" + screenOnFromTouch);
+ log(DozeEvent.FLING, "expand=" + expand
+ + " aboveThreshold=" + aboveThreshold
+ + " thresholdNeeded=" + thresholdNeeded
+ + " screenOnFromTouch=" + screenOnFromTouch);
}
- public static void traceEmergencyCall() {
- if (!ENABLED) return;
- log("emergencyCall");
- sEmergencyCallStats.append();
+ /**
+ * Appends emergency call event to the logs
+ */
+ public void traceEmergencyCall() {
+ if (log(DozeEvent.EMERGENCY_CALL)) {
+ mEmergencyCallStats.append();
+ }
}
- public static void traceKeyguardBouncerChanged(boolean showing) {
- if (!ENABLED) return;
- log("bouncer " + showing);
+ /**
+ * Appends keyguard bouncer changed event to the logs
+ * @param showing true if the keyguard bouncer is showing, else false
+ */
+ public void traceKeyguardBouncerChanged(boolean showing) {
+ log(DozeEvent.KEYGUARD_BOUNCER_CHANGED, "showing=" + showing);
}
- public static void traceScreenOn() {
- if (!ENABLED) return;
- log("screenOn pulsing=" + sPulsing);
- (sPulsing ? sScreenOnPulsingStats : sScreenOnNotPulsingStats).append();
- sPulsing = false;
+ /**
+ * Appends screen-on event to the logs
+ */
+ public void traceScreenOn() {
+ if (log(DozeEvent.SCREEN_ON, "pulsing=" + mPulsing)) {
+ (mPulsing ? mScreenOnPulsingStats : mScreenOnNotPulsingStats).append();
+ mPulsing = false;
+ }
}
- public static void traceScreenOff(int why) {
- if (!ENABLED) return;
- log("screenOff why=" + why);
+ /**
+ * Appends screen-off event to the logs
+ * @param why reason the screen is off
+ */
+ public void traceScreenOff(int why) {
+ log(DozeEvent.SCREEN_OFF, "why=" + why);
}
- public static void traceMissedTick(String delay) {
- if (!ENABLED) return;
- log("missedTick by=" + delay);
+ /**
+ * Appends missed tick event to the logs
+ * @param delay of the missed tick
+ */
+ public void traceMissedTick(String delay) {
+ log(DozeEvent.MISSED_TICK, "delay=" + delay);
}
- public static void traceTimeTickScheduled(long when, long triggerAt) {
- if (!ENABLED) return;
- log("timeTickScheduled at=" + FORMAT.format(new Date(when)) + " triggerAt="
- + FORMAT.format(new Date(triggerAt)));
+ /**
+ * Appends time tick scheduled event to the logs
+ * @param when time tick scheduled at
+ * @param triggerAt time tick trigger at
+ */
+ public void traceTimeTickScheduled(long when, long triggerAt) {
+ log(DozeEvent.TIME_TICK_SCHEDULED,
+ "scheduledAt=" + DATE_FORMAT.format(new Date(when))
+ + " triggerAt=" + DATE_FORMAT.format(new Date(triggerAt)));
}
- public static void traceKeyguard(boolean showing) {
- if (!ENABLED) return;
- log("keyguard " + showing);
- if (!showing) {
- sPulsing = false;
+ /**
+ * Appends keyguard visibility change event to the logs
+ * @param showing whether the keyguard is now showing
+ */
+ public void traceKeyguard(boolean showing) {
+ if (log(DozeEvent.KEYGUARD_VISIBILITY_CHANGE, "showing=" + showing)
+ && !showing) {
+ mPulsing = false;
}
}
- public static void traceState(DozeMachine.State state) {
- if (!ENABLED) return;
- log("state " + state);
+ /**
+ * Appends doze state changed event to the logs
+ * @param state new DozeMachine state
+ */
+ public void traceState(DozeMachine.State state) {
+ log(DozeEvent.DOZE_STATE_CHANGED, state.name());
}
/**
* Appends wake-display event to the logs.
* @param wake if we're waking up or sleeping.
*/
- public static void traceWakeDisplay(boolean wake) {
- if (!ENABLED) return;
- log("wakeDisplay " + wake);
- }
-
- public static void traceProximityResult(Context context, boolean near, long millis,
- int reason) {
- if (!ENABLED) return;
- init(context);
- log("proximityResult reason=" + reasonToString(reason) + " near=" + near
- + " millis=" + millis);
- sProxStats[reason][near ? 0 : 1].append();
+ public void traceWakeDisplay(boolean wake) {
+ log(DozeEvent.WAKE_DISPLAY, "wake=" + wake);
}
- public static String reasonToString(int pulseReason) {
- switch (pulseReason) {
- case PULSE_REASON_INTENT: return "intent";
- case PULSE_REASON_NOTIFICATION: return "notification";
- case PULSE_REASON_SENSOR_SIGMOTION: return "sigmotion";
- case REASON_SENSOR_PICKUP: return "pickup";
- case REASON_SENSOR_DOUBLE_TAP: return "doubletap";
- case PULSE_REASON_SENSOR_LONG_PRESS: return "longpress";
- case PULSE_REASON_DOCKING: return "docking";
- case PULSE_REASON_SENSOR_WAKE_LOCK_SCREEN: return "wakelockscreen";
- case REASON_SENSOR_WAKE_UP: return "wakeup";
- case REASON_SENSOR_TAP: return "tap";
- default: throw new IllegalArgumentException("bad reason: " + pulseReason);
+ /**
+ * Appends proximity result event to the logs
+ * @param near true if near, else false
+ * @param millis
+ * @param reason why proximity result was triggered
+ */
+ public void traceProximityResult(boolean near, long millis, @DozeEvent.Reason int reason) {
+ if (log(DozeEvent.PROXIMITY_RESULT,
+ " reason=" + DozeEvent.reasonToString(reason)
+ + " near=" + near
+ + " millis=" + millis)) {
+ mProxStats[reason][near ? 0 : 1].append();
}
}
- public static void dump(PrintWriter pw) {
+ /**
+ * Prints doze log timeline and consolidated stats
+ * @param pw
+ */
+ public void dump(PrintWriter pw) {
synchronized (DozeLog.class) {
- if (sMessages == null) return;
- pw.println(" Doze log:");
- final int start = (sPosition - sCount + SIZE) % SIZE;
- for (int i = 0; i < sCount; i++) {
- final int j = (start + i) % SIZE;
- pw.print(" ");
- pw.print(FORMAT.format(new Date(sTimes[j])));
- pw.print(' ');
- pw.println(sMessages[j]);
- }
+ super.dump(null, pw, null); // prints timeline
+
pw.print(" Doze summary stats (for ");
- TimeUtils.formatDuration(System.currentTimeMillis() - sSince, pw);
+ TimeUtils.formatDuration(System.currentTimeMillis() - mSince, pw);
pw.println("):");
- sPickupPulseNearVibrationStats.dump(pw, "Pickup pulse (near vibration)");
- sPickupPulseNotNearVibrationStats.dump(pw, "Pickup pulse (not near vibration)");
- sNotificationPulseStats.dump(pw, "Notification pulse");
- sScreenOnPulsingStats.dump(pw, "Screen on (pulsing)");
- sScreenOnNotPulsingStats.dump(pw, "Screen on (not pulsing)");
- sEmergencyCallStats.dump(pw, "Emergency call");
- for (int i = 0; i < REASONS; i++) {
- final String reason = reasonToString(i);
- sProxStats[i][0].dump(pw, "Proximity near (" + reason + ")");
- sProxStats[i][1].dump(pw, "Proximity far (" + reason + ")");
+ mPickupPulseNearVibrationStats.dump(pw, "Pickup pulse (near vibration)");
+ mPickupPulseNotNearVibrationStats.dump(pw, "Pickup pulse (not near vibration)");
+ mNotificationPulseStats.dump(pw, "Notification pulse");
+ mScreenOnPulsingStats.dump(pw, "Screen on (pulsing)");
+ mScreenOnNotPulsingStats.dump(pw, "Screen on (not pulsing)");
+ mEmergencyCallStats.dump(pw, "Emergency call");
+ for (int i = 0; i < DozeEvent.TOTAL_REASONS; i++) {
+ final String reason = DozeEvent.reasonToString(i);
+ mProxStats[i][0].dump(pw, "Proximity near (" + reason + ")");
+ mProxStats[i][1].dump(pw, "Proximity far (" + reason + ")");
}
}
}
- private static void log(String msg) {
- synchronized (DozeLog.class) {
- if (sMessages == null) return;
- sTimes[sPosition] = System.currentTimeMillis();
- sMessages[sPosition] = msg;
- sPosition = (sPosition + 1) % SIZE;
- sCount = Math.min(sCount + 1, SIZE);
- }
- if (DEBUG) Log.d(TAG, msg);
+ private boolean log(@DozeEvent.EventType int eventType) {
+ return log(eventType, "");
}
- public static void tracePulseDropped(Context context, boolean pulsePending,
- DozeMachine.State state, boolean blocked) {
- if (!ENABLED) return;
- init(context);
- log("pulseDropped pulsePending=" + pulsePending + " state="
- + state + " blocked=" + blocked);
+ private boolean log(@DozeEvent.EventType int eventType, String msg) {
+ return super.log(new DozeEvent.DozeEventBuilder()
+ .setType(eventType)
+ .setReason(msg)
+ .build());
}
- public static void tracePulseDropped(Context context, String why) {
- if (!ENABLED) return;
- init(context);
- log("pulseDropped why=" + why);
+ /**
+ * Appends pulse dropped event to logs
+ */
+ public void tracePulseDropped(boolean pulsePending, DozeMachine.State state, boolean blocked) {
+ log(DozeEvent.PULSE_DROPPED, "pulsePending=" + pulsePending + " state="
+ + state.name() + " blocked=" + blocked);
}
- public static void tracePulseTouchDisabledByProx(Context context, boolean disabled) {
- if (!ENABLED) return;
- init(context);
- log("pulseTouchDisabledByProx " + disabled);
+ /**
+ * Appends pulse dropped event to logs
+ * @param reason why the pulse was dropped
+ */
+ public void tracePulseDropped(String reason) {
+ log(DozeEvent.PULSE_DROPPED, "why=" + reason);
}
- public static void setRegisterKeyguardCallback(boolean registerKeyguardCallback) {
- if (!ENABLED) return;
- synchronized (DozeLog.class) {
- if (sRegisterKeyguardCallback != registerKeyguardCallback && sMessages != null) {
- throw new IllegalStateException("Cannot change setRegisterKeyguardCallback "
- + "after init()");
- }
- sRegisterKeyguardCallback = registerKeyguardCallback;
- }
+ /**
+ * Appends pulse touch displayed by prox sensor event to logs
+ * @param disabled
+ */
+ public void tracePulseTouchDisabledByProx(boolean disabled) {
+ log(DozeEvent.PULSE_DISABLED_BY_PROX, "disabled=" + disabled);
}
- public static void traceSensor(Context context, int reason) {
- if (!ENABLED) return;
- init(context);
- log("sensor type=" + reasonToString(reason));
+ /**
+ * Appends sensor triggered event to logs
+ * @param reason why the sensor was triggered
+ */
+ public void traceSensor(@DozeEvent.Reason int reason) {
+ log(DozeEvent.SENSOR_TRIGGERED, "type=" + DozeEvent.reasonToString(reason));
}
- private static class SummaryStats {
+ private class SummaryStats {
private int mCount;
public void append() {
@@ -305,7 +307,7 @@ public class DozeLog {
pw.print(": n=");
pw.print(mCount);
pw.print(" (");
- final double perHr = (double) mCount / (System.currentTimeMillis() - sSince)
+ final double perHr = (double) mCount / (System.currentTimeMillis() - mSince)
* 1000 * 60 * 60;
pw.print(perHr);
pw.print("/hr)");
@@ -313,7 +315,7 @@ public class DozeLog {
}
}
- private static final KeyguardUpdateMonitorCallback sKeyguardCallback =
+ private final KeyguardUpdateMonitorCallback mKeyguardCallback =
new KeyguardUpdateMonitorCallback() {
@Override
public void onEmergencyCallAction() {
@@ -340,4 +342,7 @@ public class DozeLog {
traceKeyguard(showing);
}
};
+
+ private static final int MAX_DOZE_DEBUG_LOGS = 400;
+ private static final int MAX_DOZE_LOGS = 50;
}
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java b/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java
index 93a51cc20db2..75b1d6c87800 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java
@@ -27,6 +27,7 @@ import com.android.internal.util.Preconditions;
import com.android.systemui.keyguard.WakefulnessLifecycle;
import com.android.systemui.keyguard.WakefulnessLifecycle.Wakefulness;
import com.android.systemui.statusbar.phone.DozeParameters;
+import com.android.systemui.statusbar.policy.BatteryController;
import com.android.systemui.util.Assert;
import com.android.systemui.util.wakelock.WakeLock;
@@ -45,6 +46,7 @@ public class DozeMachine {
static final String TAG = "DozeMachine";
static final boolean DEBUG = DozeService.DEBUG;
+ private final DozeLog mDozeLog;
private static final String REASON_CHANGE_STATE = "DozeMachine#requestState";
private static final String REASON_HELD_FOR_STATE = "DozeMachine#heldForState";
@@ -121,6 +123,7 @@ public class DozeMachine {
private final WakeLock mWakeLock;
private final AmbientDisplayConfiguration mConfig;
private final WakefulnessLifecycle mWakefulnessLifecycle;
+ private final BatteryController mBatteryController;
private Part[] mParts;
private final ArrayList<State> mQueuedRequests = new ArrayList<>();
@@ -129,11 +132,14 @@ public class DozeMachine {
private boolean mWakeLockHeldForCurrentState = false;
public DozeMachine(Service service, AmbientDisplayConfiguration config,
- WakeLock wakeLock, WakefulnessLifecycle wakefulnessLifecycle) {
+ WakeLock wakeLock, WakefulnessLifecycle wakefulnessLifecycle,
+ BatteryController batteryController, DozeLog dozeLog) {
mDozeService = service;
mConfig = config;
mWakefulnessLifecycle = wakefulnessLifecycle;
mWakeLock = wakeLock;
+ mBatteryController = batteryController;
+ mDozeLog = dozeLog;
}
/** Initializes the set of {@link Part}s. Must be called exactly once after construction. */
@@ -155,7 +161,7 @@ public class DozeMachine {
@MainThread
public void requestState(State requestedState) {
Preconditions.checkArgument(requestedState != State.DOZE_REQUEST_PULSE);
- requestState(requestedState, DozeLog.PULSE_REASON_NONE);
+ requestState(requestedState, DozeEvent.PULSE_REASON_NONE);
}
@MainThread
@@ -243,7 +249,7 @@ public class DozeMachine {
State oldState = mState;
mState = newState;
- DozeLog.traceState(newState);
+ mDozeLog.traceState(newState);
Trace.traceCounter(Trace.TRACE_TAG_APP, "doze_machine_state", newState.ordinal());
updatePulseReason(newState, oldState, pulseReason);
@@ -257,7 +263,7 @@ public class DozeMachine {
if (newState == State.DOZE_REQUEST_PULSE) {
mPulseReason = pulseReason;
} else if (oldState == State.DOZE_PULSE_DONE) {
- mPulseReason = DozeLog.PULSE_REASON_NONE;
+ mPulseReason = DozeEvent.PULSE_REASON_NONE;
}
}
@@ -316,6 +322,9 @@ public class DozeMachine {
Log.i(TAG, "Dropping pulse done because current state is already done: " + mState);
return mState;
}
+ if (requestedState == State.DOZE_AOD && mBatteryController.isAodPowerSave()) {
+ return State.DOZE;
+ }
if (requestedState == State.DOZE_REQUEST_PULSE && !mState.canPulse()) {
Log.i(TAG, "Dropping pulse request because current state can't pulse: " + mState);
return mState;
@@ -349,7 +358,7 @@ public class DozeMachine {
nextState = State.DOZE;
}
- transitionTo(nextState, DozeLog.PULSE_REASON_NONE);
+ transitionTo(nextState, DozeEvent.PULSE_REASON_NONE);
break;
default:
break;
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenState.java b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenState.java
index 38ee2fed136d..e1b4f3122861 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenState.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenState.java
@@ -16,6 +16,12 @@
package com.android.systemui.doze;
+import static com.android.systemui.doze.DozeMachine.State.DOZE;
+import static com.android.systemui.doze.DozeMachine.State.DOZE_AOD;
+import static com.android.systemui.doze.DozeMachine.State.DOZE_AOD_PAUSED;
+import static com.android.systemui.doze.DozeMachine.State.DOZE_AOD_PAUSING;
+import static com.android.systemui.doze.DozeMachine.State.DOZE_PULSE_DONE;
+
import android.os.Handler;
import android.util.Log;
import android.view.Display;
@@ -48,21 +54,24 @@ public class DozeScreenState implements DozeMachine.Part {
private final Handler mHandler;
private final Runnable mApplyPendingScreenState = this::applyPendingScreenState;
private final DozeParameters mParameters;
+ private final DozeHost mDozeHost;
private int mPendingScreenState = Display.STATE_UNKNOWN;
private SettableWakeLock mWakeLock;
- public DozeScreenState(DozeMachine.Service service, Handler handler,
+ public DozeScreenState(DozeMachine.Service service, Handler handler, DozeHost host,
DozeParameters parameters, WakeLock wakeLock) {
mDozeService = service;
mHandler = handler;
mParameters = parameters;
+ mDozeHost = host;
mWakeLock = new SettableWakeLock(wakeLock, TAG);
}
@Override
public void transitionTo(DozeMachine.State oldState, DozeMachine.State newState) {
int screenState = newState.screenState(mParameters);
+ mDozeHost.cancelGentleSleep();
if (newState == DozeMachine.State.FINISH) {
// Make sure not to apply the screen state after DozeService was destroyed.
@@ -79,12 +88,13 @@ public class DozeScreenState implements DozeMachine.Part {
return;
}
- boolean messagePending = mHandler.hasCallbacks(mApplyPendingScreenState);
- boolean pulseEnding = oldState == DozeMachine.State.DOZE_PULSE_DONE
- && newState == DozeMachine.State.DOZE_AOD;
- boolean turningOn = (oldState == DozeMachine.State.DOZE_AOD_PAUSED
- || oldState == DozeMachine.State.DOZE) && newState == DozeMachine.State.DOZE_AOD;
- boolean justInitialized = oldState == DozeMachine.State.INITIALIZED;
+ final boolean messagePending = mHandler.hasCallbacks(mApplyPendingScreenState);
+ final boolean pulseEnding = oldState == DOZE_PULSE_DONE && newState == DOZE_AOD;
+ final boolean turningOn = (oldState == DOZE_AOD_PAUSED
+ || oldState == DOZE) && newState == DOZE_AOD;
+ final boolean turningOff = (oldState == DOZE_AOD && newState == DOZE)
+ || (oldState == DOZE_AOD_PAUSING && newState == DOZE_AOD_PAUSED);
+ final boolean justInitialized = oldState == DozeMachine.State.INITIALIZED;
if (messagePending || justInitialized || pulseEnding || turningOn) {
// During initialization, we hide the navigation bar. That is however only applied after
// a traversal; setting the screen state here is immediate however, so it can happen
@@ -93,7 +103,7 @@ public class DozeScreenState implements DozeMachine.Part {
mPendingScreenState = screenState;
// Delay screen state transitions even longer while animations are running.
- boolean shouldDelayTransition = newState == DozeMachine.State.DOZE_AOD
+ boolean shouldDelayTransition = newState == DOZE_AOD
&& mParameters.shouldControlScreenOff() && !turningOn;
if (shouldDelayTransition) {
@@ -114,6 +124,8 @@ public class DozeScreenState implements DozeMachine.Part {
} else if (DEBUG) {
Log.d(TAG, "Pending display state change to " + screenState);
}
+ } else if (turningOff) {
+ mDozeHost.prepareForGentleSleep(() -> applyScreenState(screenState));
} else {
applyScreenState(screenState);
}
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
index 67eefc5588e3..05a234f1e431 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
@@ -42,9 +42,7 @@ import androidx.annotation.VisibleForTesting;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto;
-import com.android.systemui.Dependency;
import com.android.systemui.plugins.SensorManagerPlugin;
-import com.android.systemui.shared.plugins.PluginManager;
import com.android.systemui.statusbar.phone.DozeParameters;
import com.android.systemui.util.sensors.AsyncSensorManager;
import com.android.systemui.util.sensors.ProximitySensor;
@@ -82,7 +80,8 @@ public class DozeSensors {
public DozeSensors(Context context, AlarmManager alarmManager, AsyncSensorManager sensorManager,
DozeParameters dozeParameters, AmbientDisplayConfiguration config, WakeLock wakeLock,
- Callback callback, Consumer<Boolean> proxCallback, AlwaysOnDisplayPolicy policy) {
+ Callback callback, Consumer<Boolean> proxCallback, AlwaysOnDisplayPolicy policy,
+ DozeLog dozeLog) {
mContext = context;
mAlarmManager = alarmManager;
mSensorManager = sensorManager;
@@ -99,59 +98,69 @@ public class DozeSensors {
mSensorManager.getDefaultSensor(Sensor.TYPE_SIGNIFICANT_MOTION),
null /* setting */,
dozeParameters.getPulseOnSigMotion(),
- DozeLog.PULSE_REASON_SENSOR_SIGMOTION, false /* touchCoords */,
- false /* touchscreen */),
+ DozeEvent.PULSE_REASON_SENSOR_SIGMOTION, false /* touchCoords */,
+ false /* touchscreen */, dozeLog),
mPickupSensor = new TriggerSensor(
mSensorManager.getDefaultSensor(Sensor.TYPE_PICK_UP_GESTURE),
Settings.Secure.DOZE_PICK_UP_GESTURE,
true /* settingDef */,
config.dozePickupSensorAvailable(),
- DozeLog.REASON_SENSOR_PICKUP, false /* touchCoords */,
+ DozeEvent.REASON_SENSOR_PICKUP, false /* touchCoords */,
false /* touchscreen */,
- false /* ignoresSetting */),
+ false /* ignoresSetting */,
+ dozeLog),
new TriggerSensor(
findSensorWithType(config.doubleTapSensorType()),
Settings.Secure.DOZE_DOUBLE_TAP_GESTURE,
true /* configured */,
- DozeLog.REASON_SENSOR_DOUBLE_TAP,
+ DozeEvent.REASON_SENSOR_DOUBLE_TAP,
dozeParameters.doubleTapReportsTouchCoordinates(),
- true /* touchscreen */),
+ true /* touchscreen */,
+ dozeLog),
new TriggerSensor(
findSensorWithType(config.tapSensorType()),
Settings.Secure.DOZE_TAP_SCREEN_GESTURE,
true /* configured */,
- DozeLog.REASON_SENSOR_TAP,
+ DozeEvent.REASON_SENSOR_TAP,
false /* reports touch coordinates */,
- true /* touchscreen */),
+ true /* touchscreen */,
+ dozeLog),
new TriggerSensor(
findSensorWithType(config.longPressSensorType()),
Settings.Secure.DOZE_PULSE_ON_LONG_PRESS,
false /* settingDef */,
true /* configured */,
- DozeLog.PULSE_REASON_SENSOR_LONG_PRESS,
+ DozeEvent.PULSE_REASON_SENSOR_LONG_PRESS,
true /* reports touch coordinates */,
- true /* touchscreen */),
+ true /* touchscreen */,
+ dozeLog),
new PluginSensor(
new SensorManagerPlugin.Sensor(TYPE_WAKE_DISPLAY),
Settings.Secure.DOZE_WAKE_DISPLAY_GESTURE,
mConfig.wakeScreenGestureAvailable() && alwaysOn,
- DozeLog.REASON_SENSOR_WAKE_UP,
+ DozeEvent.REASON_SENSOR_WAKE_UP,
false /* reports touch coordinates */,
- false /* touchscreen */),
+ false /* touchscreen */,
+ dozeLog),
new PluginSensor(
new SensorManagerPlugin.Sensor(TYPE_WAKE_LOCK_SCREEN),
Settings.Secure.DOZE_WAKE_LOCK_SCREEN_GESTURE,
mConfig.wakeScreenGestureAvailable(),
- DozeLog.PULSE_REASON_SENSOR_WAKE_LOCK_SCREEN,
+ DozeEvent.PULSE_REASON_SENSOR_WAKE_LOCK_SCREEN,
false /* reports touch coordinates */,
- false /* touchscreen */, mConfig.getWakeLockScreenDebounce()),
+ false /* touchscreen */,
+ mConfig.getWakeLockScreenDebounce(),
+ dozeLog),
};
- mProximitySensor = new ProximitySensor(
- context, sensorManager, Dependency.get(PluginManager.class));
+ mProximitySensor = new ProximitySensor(context.getResources(), sensorManager);
mProximitySensor.register(
- proximityEvent -> mProxCallback.accept(!proximityEvent.getNear()));
+ proximityEvent -> {
+ if (proximityEvent != null) {
+ mProxCallback.accept(!proximityEvent.getNear());
+ }
+ });
}
/**
@@ -305,23 +314,24 @@ public class DozeSensors {
protected boolean mRegistered;
protected boolean mDisabled;
protected boolean mIgnoresSetting;
+ protected final DozeLog mDozeLog;
public TriggerSensor(Sensor sensor, String setting, boolean configured, int pulseReason,
- boolean reportsTouchCoordinates, boolean requiresTouchscreen) {
+ boolean reportsTouchCoordinates, boolean requiresTouchscreen, DozeLog dozeLog) {
this(sensor, setting, true /* settingDef */, configured, pulseReason,
- reportsTouchCoordinates, requiresTouchscreen);
+ reportsTouchCoordinates, requiresTouchscreen, dozeLog);
}
public TriggerSensor(Sensor sensor, String setting, boolean settingDef,
boolean configured, int pulseReason, boolean reportsTouchCoordinates,
- boolean requiresTouchscreen) {
+ boolean requiresTouchscreen, DozeLog dozeLog) {
this(sensor, setting, settingDef, configured, pulseReason, reportsTouchCoordinates,
- requiresTouchscreen, false /* ignoresSetting */);
+ requiresTouchscreen, false /* ignoresSetting */, dozeLog);
}
private TriggerSensor(Sensor sensor, String setting, boolean settingDef,
boolean configured, int pulseReason, boolean reportsTouchCoordinates,
- boolean requiresTouchscreen, boolean ignoresSetting) {
+ boolean requiresTouchscreen, boolean ignoresSetting, DozeLog dozeLog) {
mSensor = sensor;
mSetting = setting;
mSettingDefault = settingDef;
@@ -330,6 +340,7 @@ public class DozeSensors {
mReportsTouchCoordinates = reportsTouchCoordinates;
mRequiresTouchscreen = requiresTouchscreen;
mIgnoresSetting = ignoresSetting;
+ mDozeLog = dozeLog;
}
public void setListening(boolean listen) {
@@ -386,7 +397,7 @@ public class DozeSensors {
@Override
@AnyThread
public void onTrigger(TriggerEvent event) {
- DozeLog.traceSensor(mContext, mPulseReason);
+ mDozeLog.traceSensor(mPulseReason);
mHandler.post(mWakeLock.wrap(() -> {
if (DEBUG) Log.d(TAG, "onTrigger: " + triggerEventToString(event));
if (mSensor != null && mSensor.getType() == Sensor.TYPE_PICK_UP_GESTURE) {
@@ -442,16 +453,17 @@ public class DozeSensors {
private long mDebounce;
PluginSensor(SensorManagerPlugin.Sensor sensor, String setting, boolean configured,
- int pulseReason, boolean reportsTouchCoordinates, boolean requiresTouchscreen) {
+ int pulseReason, boolean reportsTouchCoordinates, boolean requiresTouchscreen,
+ DozeLog dozeLog) {
this(sensor, setting, configured, pulseReason, reportsTouchCoordinates,
- requiresTouchscreen, 0L /* debounce */);
+ requiresTouchscreen, 0L /* debounce */, dozeLog);
}
PluginSensor(SensorManagerPlugin.Sensor sensor, String setting, boolean configured,
int pulseReason, boolean reportsTouchCoordinates, boolean requiresTouchscreen,
- long debounce) {
+ long debounce, DozeLog dozeLog) {
super(null, setting, configured, pulseReason, reportsTouchCoordinates,
- requiresTouchscreen);
+ requiresTouchscreen, dozeLog);
mPluginSensor = sensor;
mDebounce = debounce;
}
@@ -497,7 +509,7 @@ public class DozeSensors {
@Override
public void onSensorChanged(SensorManagerPlugin.SensorEvent event) {
- DozeLog.traceSensor(mContext, mPulseReason);
+ mDozeLog.traceSensor(mPulseReason);
mHandler.post(mWakeLock.wrap(() -> {
final long now = SystemClock.uptimeMillis();
if (now < mDebounceFrom + mDebounce) {
@@ -514,7 +526,7 @@ public class DozeSensors {
/**
* Called when a sensor requests a pulse
- * @param pulseReason Requesting sensor, e.g. {@link DozeLog#REASON_SENSOR_PICKUP}
+ * @param pulseReason Requesting sensor, e.g. {@link DozeEvent#REASON_SENSOR_PICKUP}
* @param screenX the location on the screen where the sensor fired or -1
* if the sensor doesn't support reporting screen locations.
* @param screenY the location on the screen where the sensor fired or -1
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeService.java b/packages/SystemUI/src/com/android/systemui/doze/DozeService.java
index e92acfc7f219..08734d27ba55 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeService.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeService.java
@@ -22,10 +22,8 @@ import android.os.SystemClock;
import android.service.dreams.DreamService;
import android.util.Log;
-import com.android.systemui.Dependency;
import com.android.systemui.plugins.DozeServicePlugin;
import com.android.systemui.plugins.DozeServicePlugin.RequestDoze;
-import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.plugins.PluginListener;
import com.android.systemui.shared.plugins.PluginManager;
@@ -38,16 +36,17 @@ public class DozeService extends DreamService
implements DozeMachine.Service, RequestDoze, PluginListener<DozeServicePlugin> {
private static final String TAG = "DozeService";
static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
- private final FalsingManager mFalsingManager;
+ private final DozeFactory mDozeFactory;
private DozeMachine mDozeMachine;
private DozeServicePlugin mDozePlugin;
private PluginManager mPluginManager;
@Inject
- public DozeService(FalsingManager falsingManager) {
+ public DozeService(DozeFactory dozeFactory, PluginManager pluginManager) {
setDebug(DEBUG);
- mFalsingManager = falsingManager;
+ mDozeFactory = dozeFactory;
+ mPluginManager = pluginManager;
}
@Override
@@ -60,9 +59,8 @@ public class DozeService extends DreamService
finish();
return;
}
- mPluginManager = Dependency.get(PluginManager.class);
mPluginManager.addPluginListener(this, DozeServicePlugin.class, false /* allowMultiple */);
- mDozeMachine = new DozeFactory().assembleMachine(this, mFalsingManager);
+ mDozeMachine = mDozeFactory.assembleMachine(this);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
index 80d4b631314a..b212884ebb98 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
@@ -67,12 +67,12 @@ public class DozeTriggers implements DozeMachine.Part {
private final Context mContext;
private final DozeMachine mMachine;
+ private final DozeLog mDozeLog;
private final DozeSensors mDozeSensors;
private final DozeHost mDozeHost;
private final AmbientDisplayConfiguration mConfig;
private final DozeParameters mDozeParameters;
private final AsyncSensorManager mSensorManager;
- private final Handler mHandler;
private final WakeLock mWakeLock;
private final boolean mAllowPulseTriggers;
private final UiModeManager mUiModeManager;
@@ -89,24 +89,24 @@ public class DozeTriggers implements DozeMachine.Part {
public DozeTriggers(Context context, DozeMachine machine, DozeHost dozeHost,
AlarmManager alarmManager, AmbientDisplayConfiguration config,
DozeParameters dozeParameters, AsyncSensorManager sensorManager, Handler handler,
- WakeLock wakeLock, boolean allowPulseTriggers, DockManager dockManager) {
+ WakeLock wakeLock, boolean allowPulseTriggers, DockManager dockManager,
+ ProximitySensor proximitySensor,
+ DozeLog dozeLog) {
mContext = context;
mMachine = machine;
mDozeHost = dozeHost;
mConfig = config;
mDozeParameters = dozeParameters;
mSensorManager = sensorManager;
- mHandler = handler;
mWakeLock = wakeLock;
mAllowPulseTriggers = allowPulseTriggers;
mDozeSensors = new DozeSensors(context, alarmManager, mSensorManager, dozeParameters,
config, wakeLock, this::onSensor, this::onProximityFar,
- dozeParameters.getPolicy());
+ dozeParameters.getPolicy(), dozeLog);
mUiModeManager = mContext.getSystemService(UiModeManager.class);
mDockManager = dockManager;
- mProxCheck = new ProximitySensor.ProximityCheck(
- new ProximitySensor(mContext, mSensorManager, null),
- mHandler);
+ mProxCheck = new ProximitySensor.ProximityCheck(proximitySensor, handler);
+ mDozeLog = dozeLog;
}
private void onNotification(Runnable onPulseSuppressedListener) {
@@ -116,18 +116,18 @@ public class DozeTriggers implements DozeMachine.Part {
if (!sWakeDisplaySensorState) {
Log.d(TAG, "Wake display false. Pulse denied.");
runIfNotNull(onPulseSuppressedListener);
- DozeLog.tracePulseDropped(mContext, "wakeDisplaySensor");
+ mDozeLog.tracePulseDropped("wakeDisplaySensor");
return;
}
mNotificationPulseTime = SystemClock.elapsedRealtime();
if (!mConfig.pulseOnNotificationEnabled(UserHandle.USER_CURRENT)) {
runIfNotNull(onPulseSuppressedListener);
- DozeLog.tracePulseDropped(mContext, "pulseOnNotificationsDisabled");
+ mDozeLog.tracePulseDropped("pulseOnNotificationsDisabled");
return;
}
- requestPulse(DozeLog.PULSE_REASON_NOTIFICATION, false /* performedProxCheck */,
+ requestPulse(DozeEvent.PULSE_REASON_NOTIFICATION, false /* performedProxCheck */,
onPulseSuppressedListener);
- DozeLog.traceNotificationPulse(mContext);
+ mDozeLog.traceNotificationPulse();
}
private static void runIfNotNull(Runnable runnable) {
@@ -148,8 +148,7 @@ public class DozeTriggers implements DozeMachine.Part {
final long start = SystemClock.uptimeMillis();
mProxCheck.check(PROXIMITY_TIMEOUT_DELAY_MS, near -> {
final long end = SystemClock.uptimeMillis();
- DozeLog.traceProximityResult(
- mContext,
+ mDozeLog.traceProximityResult(
near == null ? false : near,
end - start,
reason);
@@ -162,12 +161,12 @@ public class DozeTriggers implements DozeMachine.Part {
@VisibleForTesting
void onSensor(int pulseReason, float screenX, float screenY, float[] rawValues) {
- boolean isDoubleTap = pulseReason == DozeLog.REASON_SENSOR_DOUBLE_TAP;
- boolean isTap = pulseReason == DozeLog.REASON_SENSOR_TAP;
- boolean isPickup = pulseReason == DozeLog.REASON_SENSOR_PICKUP;
- boolean isLongPress = pulseReason == DozeLog.PULSE_REASON_SENSOR_LONG_PRESS;
- boolean isWakeDisplay = pulseReason == DozeLog.REASON_SENSOR_WAKE_UP;
- boolean isWakeLockScreen = pulseReason == DozeLog.PULSE_REASON_SENSOR_WAKE_LOCK_SCREEN;
+ boolean isDoubleTap = pulseReason == DozeEvent.REASON_SENSOR_DOUBLE_TAP;
+ boolean isTap = pulseReason == DozeEvent.REASON_SENSOR_TAP;
+ boolean isPickup = pulseReason == DozeEvent.REASON_SENSOR_PICKUP;
+ boolean isLongPress = pulseReason == DozeEvent.PULSE_REASON_SENSOR_LONG_PRESS;
+ boolean isWakeDisplay = pulseReason == DozeEvent.REASON_SENSOR_WAKE_UP;
+ boolean isWakeLockScreen = pulseReason == DozeEvent.PULSE_REASON_SENSOR_WAKE_LOCK_SCREEN;
boolean wakeEvent = rawValues != null && rawValues.length > 0 && rawValues[0] != 0;
if (isWakeDisplay) {
@@ -182,7 +181,7 @@ public class DozeTriggers implements DozeMachine.Part {
}
} else {
proximityCheckThenCall((result) -> {
- if (result) {
+ if (result != null && result) {
// In pocket, drop event.
return;
}
@@ -204,7 +203,7 @@ public class DozeTriggers implements DozeMachine.Part {
SystemClock.elapsedRealtime() - mNotificationPulseTime;
final boolean withinVibrationThreshold =
timeSinceNotification < mDozeParameters.getPickupVibrationThreshold();
- DozeLog.tracePickupWakeUp(mContext, withinVibrationThreshold);
+ mDozeLog.tracePickupWakeUp(withinVibrationThreshold);
}
}
@@ -266,12 +265,12 @@ public class DozeTriggers implements DozeMachine.Part {
* transitions.
*/
private void onWakeScreen(boolean wake, @Nullable DozeMachine.State state) {
- DozeLog.traceWakeDisplay(wake);
+ mDozeLog.traceWakeDisplay(wake);
sWakeDisplaySensorState = wake;
if (wake) {
proximityCheckThenCall((result) -> {
- if (result) {
+ if (result != null && result) {
// In pocket, drop event.
return;
}
@@ -280,9 +279,9 @@ public class DozeTriggers implements DozeMachine.Part {
// Logs AOD open due to sensor wake up.
mMetricsLogger.write(new LogMaker(MetricsEvent.DOZING)
.setType(MetricsEvent.TYPE_OPEN)
- .setSubtype(DozeLog.REASON_SENSOR_WAKE_UP));
+ .setSubtype(DozeEvent.REASON_SENSOR_WAKE_UP));
}
- }, true /* alreadyPerformedProxCheck */, DozeLog.REASON_SENSOR_WAKE_UP);
+ }, true /* alreadyPerformedProxCheck */, DozeEvent.REASON_SENSOR_WAKE_UP);
} else {
boolean paused = (state == DozeMachine.State.DOZE_AOD_PAUSED);
boolean pausing = (state == DozeMachine.State.DOZE_AOD_PAUSING);
@@ -291,7 +290,7 @@ public class DozeTriggers implements DozeMachine.Part {
// Logs AOD close due to sensor wake up.
mMetricsLogger.write(new LogMaker(MetricsEvent.DOZING)
.setType(MetricsEvent.TYPE_CLOSE)
- .setSubtype(DozeLog.REASON_SENSOR_WAKE_UP));
+ .setSubtype(DozeEvent.REASON_SENSOR_WAKE_UP));
}
}
}
@@ -349,7 +348,6 @@ public class DozeTriggers implements DozeMachine.Part {
private void checkTriggersAtInit() {
if (mUiModeManager.getCurrentModeType() == Configuration.UI_MODE_TYPE_CAR
- || mDozeHost.isPowerSaveActive()
|| mDozeHost.isBlockingDoze()
|| !mDozeHost.isProvisioned()) {
mMachine.requestState(DozeMachine.State.FINISH);
@@ -364,14 +362,14 @@ public class DozeTriggers implements DozeMachine.Part {
// When already pulsing we're allowed to show the wallpaper directly without
// requesting a new pulse.
if (mMachine.getState() == DozeMachine.State.DOZE_PULSING
- && reason == DozeLog.PULSE_REASON_SENSOR_WAKE_LOCK_SCREEN) {
+ && reason == DozeEvent.PULSE_REASON_SENSOR_WAKE_LOCK_SCREEN) {
mMachine.requestState(DozeMachine.State.DOZE_PULSING_BRIGHT);
return;
}
if (mPulsePending || !mAllowPulseTriggers || !canPulse()) {
if (mAllowPulseTriggers) {
- DozeLog.tracePulseDropped(mContext, mPulsePending, mMachine.getState(),
+ mDozeLog.tracePulseDropped(mPulsePending, mMachine.getState(),
mDozeHost.isPulsingBlocked());
}
runIfNotNull(onPulseSuppressedListener);
@@ -380,9 +378,9 @@ public class DozeTriggers implements DozeMachine.Part {
mPulsePending = true;
proximityCheckThenCall((result) -> {
- if (result) {
+ if (result != null && result) {
// in pocket, abort pulse
- DozeLog.tracePulseDropped(mContext, "inPocket");
+ mDozeLog.tracePulseDropped("inPocket");
mPulsePending = false;
runIfNotNull(onPulseSuppressedListener);
} else {
@@ -404,7 +402,7 @@ public class DozeTriggers implements DozeMachine.Part {
private void continuePulseRequest(int reason) {
mPulsePending = false;
if (mDozeHost.isPulsingBlocked() || !canPulse()) {
- DozeLog.tracePulseDropped(mContext, mPulsePending, mMachine.getState(),
+ mDozeLog.tracePulseDropped(mPulsePending, mMachine.getState(),
mDozeHost.isPulsingBlocked());
return;
}
@@ -428,7 +426,7 @@ public class DozeTriggers implements DozeMachine.Part {
public void onReceive(Context context, Intent intent) {
if (PULSE_ACTION.equals(intent.getAction())) {
if (DozeMachine.DEBUG) Log.d(TAG, "Received pulse intent");
- requestPulse(DozeLog.PULSE_REASON_INTENT, false, /* performedProxCheck */
+ requestPulse(DozeEvent.PULSE_REASON_INTENT, false, /* performedProxCheck */
null /* onPulseSupressedListener */);
}
if (UiModeManager.ACTION_ENTER_CAR_MODE.equals(intent.getAction())) {
@@ -485,8 +483,8 @@ public class DozeTriggers implements DozeMachine.Part {
@Override
public void onPowerSaveChanged(boolean active) {
- if (active) {
- mMachine.requestState(DozeMachine.State.FINISH);
+ if (mDozeHost.isPowerSaveActive()) {
+ mMachine.requestState(DozeMachine.State.DOZE);
}
}
};
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java b/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java
index 1f33af8c3f55..f1557838fd73 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java
@@ -49,6 +49,7 @@ public class DozeUi implements DozeMachine.Part {
private final AlarmTimeout mTimeTicker;
private final boolean mCanAnimateTransition;
private final DozeParameters mDozeParameters;
+ private final DozeLog mDozeLog;
private boolean mKeyguardShowing;
private final KeyguardUpdateMonitorCallback mKeyguardVisibilityCallback =
@@ -65,7 +66,8 @@ public class DozeUi implements DozeMachine.Part {
public DozeUi(Context context, AlarmManager alarmManager, DozeMachine machine,
WakeLock wakeLock, DozeHost host, Handler handler,
- DozeParameters params, KeyguardUpdateMonitor keyguardUpdateMonitor) {
+ DozeParameters params, KeyguardUpdateMonitor keyguardUpdateMonitor,
+ DozeLog dozeLog) {
mContext = context;
mMachine = machine;
mWakeLock = wakeLock;
@@ -75,6 +77,7 @@ public class DozeUi implements DozeMachine.Part {
mDozeParameters = params;
mTimeTicker = new AlarmTimeout(alarmManager, this::onTimeTick, "doze_time_tick", handler);
keyguardUpdateMonitor.registerCallback(mKeyguardVisibilityCallback);
+ mDozeLog = dozeLog;
}
/**
@@ -83,7 +86,8 @@ public class DozeUi implements DozeMachine.Part {
*/
private void updateAnimateScreenOff() {
if (mCanAnimateTransition) {
- final boolean controlScreenOff = mDozeParameters.getAlwaysOn() && mKeyguardShowing;
+ final boolean controlScreenOff = mDozeParameters.getAlwaysOn() && mKeyguardShowing
+ && !mHost.isPowerSaveActive();
mDozeParameters.setControlScreenOffAnimation(controlScreenOff);
mHost.setAnimateScreenOff(controlScreenOff);
}
@@ -96,7 +100,7 @@ public class DozeUi implements DozeMachine.Part {
public void onPulseStarted() {
try {
mMachine.requestState(
- reason == DozeLog.PULSE_REASON_SENSOR_WAKE_LOCK_SCREEN
+ reason == DozeEvent.PULSE_REASON_SENSOR_WAKE_LOCK_SCREEN
? DozeMachine.State.DOZE_PULSING_BRIGHT
: DozeMachine.State.DOZE_PULSING);
} catch (IllegalStateException e) {
@@ -131,7 +135,6 @@ public class DozeUi implements DozeMachine.Part {
break;
case DOZE:
case DOZE_AOD_PAUSED:
- mHost.prepareForGentleWakeUp();
unscheduleTimeTick();
break;
case DOZE_REQUEST_PULSE:
@@ -175,7 +178,7 @@ public class DozeUi implements DozeMachine.Part {
long delta = roundToNextMinute(time) - System.currentTimeMillis();
boolean scheduled = mTimeTicker.schedule(delta, AlarmTimeout.MODE_IGNORE_IF_SCHEDULED);
if (scheduled) {
- DozeLog.traceTimeTickScheduled(time, time + delta);
+ mDozeLog.traceTimeTickScheduled(time, time + delta);
}
mLastTimeTickElapsed = SystemClock.elapsedRealtime();
}
@@ -192,7 +195,7 @@ public class DozeUi implements DozeMachine.Part {
long millisSinceLastTick = SystemClock.elapsedRealtime() - mLastTimeTickElapsed;
if (millisSinceLastTick > TIME_TICK_DEADLINE_MILLIS) {
String delay = Formatter.formatShortElapsedTime(mContext, millisSinceLastTick);
- DozeLog.traceMissedTick(delay);
+ mDozeLog.traceMissedTick(delay);
Log.e(DozeMachine.TAG, "Missed AOD time tick by " + delay);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeWallpaperState.java b/packages/SystemUI/src/com/android/systemui/doze/DozeWallpaperState.java
index 35c8b741381c..9457dc9e580b 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeWallpaperState.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeWallpaperState.java
@@ -17,12 +17,9 @@
package com.android.systemui.doze;
import android.app.IWallpaperManager;
-import android.content.Context;
import android.os.RemoteException;
-import android.os.ServiceManager;
import android.util.Log;
-import com.android.internal.annotations.VisibleForTesting;
import com.android.systemui.statusbar.notification.stack.StackStateAnimator;
import com.android.systemui.statusbar.phone.BiometricUnlockController;
import com.android.systemui.statusbar.phone.DozeParameters;
@@ -42,17 +39,10 @@ public class DozeWallpaperState implements DozeMachine.Part {
private final BiometricUnlockController mBiometricUnlockController;
private boolean mIsAmbientMode;
- public DozeWallpaperState(Context context,
- BiometricUnlockController biometricUnlockController) {
- this(IWallpaperManager.Stub.asInterface(
- ServiceManager.getService(Context.WALLPAPER_SERVICE)),
- biometricUnlockController,
- DozeParameters.getInstance(context));
- }
-
- @VisibleForTesting
- DozeWallpaperState(IWallpaperManager wallpaperManagerService,
- BiometricUnlockController biometricUnlockController, DozeParameters parameters) {
+ public DozeWallpaperState(
+ IWallpaperManager wallpaperManagerService,
+ BiometricUnlockController biometricUnlockController,
+ DozeParameters parameters) {
mWallpaperManagerService = wallpaperManagerService;
mBiometricUnlockController = biometricUnlockController;
mDozeParameters = parameters;
diff --git a/packages/SystemUI/src/com/android/systemui/fragments/FragmentService.java b/packages/SystemUI/src/com/android/systemui/fragments/FragmentService.java
index b4cc571be061..1b4857ebb209 100644
--- a/packages/SystemUI/src/com/android/systemui/fragments/FragmentService.java
+++ b/packages/SystemUI/src/com/android/systemui/fragments/FragmentService.java
@@ -22,7 +22,7 @@ import android.view.View;
import com.android.systemui.ConfigurationChangedReceiver;
import com.android.systemui.Dumpable;
-import com.android.systemui.SystemUIRootComponent;
+import com.android.systemui.dagger.SystemUIRootComponent;
import com.android.systemui.qs.QSFragment;
import com.android.systemui.statusbar.phone.NavigationBarFragment;
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsComponent.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsComponent.java
index e8ef454bd466..c11127d1dc0b 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsComponent.java
@@ -35,6 +35,10 @@ public class GlobalActionsComponent extends SystemUI implements Callbacks, Globa
private Extension<GlobalActions> mExtension;
private IStatusBarService mBarService;
+ public GlobalActionsComponent(Context context) {
+ super(context);
+ }
+
@Override
public void start() {
mBarService = IStatusBarService.Stub.asInterface(
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
index c9c6a0c6868b..22846bc02a38 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
@@ -90,14 +90,15 @@ import com.android.systemui.Dependency;
import com.android.systemui.Interpolators;
import com.android.systemui.MultiListLayout;
import com.android.systemui.MultiListLayout.MultiListAdapter;
+import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.colorextraction.SysuiColorExtractor;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.GlobalActions.GlobalActionsManager;
import com.android.systemui.plugins.GlobalActionsPanelPlugin;
import com.android.systemui.statusbar.phone.ScrimController;
import com.android.systemui.statusbar.phone.StatusBarWindowController;
-import com.android.systemui.statusbar.phone.UnlockMethodCache;
import com.android.systemui.statusbar.policy.ConfigurationController;
+import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.util.EmergencyDialerConstants;
import com.android.systemui.util.leak.RotationUtils;
import com.android.systemui.volume.SystemUIInterpolators.LogAccelerateInterpolator;
@@ -187,7 +188,7 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener,
filter.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
filter.addAction(Intent.ACTION_SCREEN_OFF);
filter.addAction(TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED);
- context.registerReceiver(mBroadcastReceiver, filter);
+ Dependency.get(BroadcastDispatcher.class).registerReceiver(mBroadcastReceiver, filter);
ConnectivityManager cm = (ConnectivityManager)
context.getSystemService(Context.CONNECTIVITY_SERVICE);
@@ -213,14 +214,17 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener,
Dependency.get(ConfigurationController.class).addCallback(this);
mActivityStarter = Dependency.get(ActivityStarter.class);
- UnlockMethodCache unlockMethodCache = UnlockMethodCache.getInstance(context);
- unlockMethodCache.addListener(
- () -> {
- if (mDialog != null && mDialog.mPanelController != null) {
- boolean locked = !unlockMethodCache.canSkipBouncer();
- mDialog.mPanelController.onDeviceLockStateChanged(locked);
- }
- });
+ KeyguardStateController keyguardStateController =
+ Dependency.get(KeyguardStateController.class);
+ keyguardStateController.addCallback(new KeyguardStateController.Callback() {
+ @Override
+ public void onUnlockedChanged() {
+ if (mDialog != null && mDialog.mPanelController != null) {
+ boolean locked = !keyguardStateController.canDismissLockScreen();
+ mDialog.mPanelController.onDeviceLockStateChanged(locked);
+ }
+ }
+ });
}
/**
@@ -665,8 +669,7 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener,
// Take an "interactive" bugreport.
MetricsLogger.action(mContext,
MetricsEvent.ACTION_BUGREPORT_FROM_POWER_MENU_INTERACTIVE);
- ActivityManager.getService().requestBugReport(
- ActivityManager.BUGREPORT_OPTION_INTERACTIVE);
+ ActivityManager.getService().requestInteractiveBugReport();
} catch (RemoteException e) {
}
}
@@ -683,8 +686,7 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener,
try {
// Take a "full" bugreport.
MetricsLogger.action(mContext, MetricsEvent.ACTION_BUGREPORT_FROM_POWER_MENU_FULL);
- ActivityManager.getService().requestBugReport(
- ActivityManager.BUGREPORT_OPTION_FULL);
+ ActivityManager.getService().requestFullBugReport();
} catch (RemoteException e) {
}
return false;
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsImpl.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsImpl.java
index 6f8665a87dee..b9fe827bb1c9 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsImpl.java
@@ -40,14 +40,14 @@ import com.android.systemui.plugins.GlobalActionsPanelPlugin;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
import com.android.systemui.statusbar.policy.ExtensionController;
-import com.android.systemui.statusbar.policy.KeyguardMonitor;
+import com.android.systemui.statusbar.policy.KeyguardStateController;
public class GlobalActionsImpl implements GlobalActions, CommandQueue.Callbacks {
private static final float SHUTDOWN_SCRIM_ALPHA = 0.95f;
private final Context mContext;
- private final KeyguardMonitor mKeyguardMonitor;
+ private final KeyguardStateController mKeyguardStateController;
private final DeviceProvisionedController mDeviceProvisionedController;
private final ExtensionController.Extension<GlobalActionsPanelPlugin> mPanelExtension;
private GlobalActionsDialog mGlobalActions;
@@ -55,7 +55,7 @@ public class GlobalActionsImpl implements GlobalActions, CommandQueue.Callbacks
public GlobalActionsImpl(Context context) {
mContext = context;
- mKeyguardMonitor = Dependency.get(KeyguardMonitor.class);
+ mKeyguardStateController = Dependency.get(KeyguardStateController.class);
mDeviceProvisionedController = Dependency.get(DeviceProvisionedController.class);
SysUiServiceProvider.getComponent(context, CommandQueue.class).addCallback(this);
mPanelExtension = Dependency.get(ExtensionController.class)
@@ -79,7 +79,7 @@ public class GlobalActionsImpl implements GlobalActions, CommandQueue.Callbacks
if (mGlobalActions == null) {
mGlobalActions = new GlobalActionsDialog(mContext, manager);
}
- mGlobalActions.showDialog(mKeyguardMonitor.isShowing(),
+ mGlobalActions.showDialog(mKeyguardStateController.isShowing(),
mDeviceProvisionedController.isDeviceProvisioned(),
mPanelExtension.get());
Dependency.get(KeyguardUpdateMonitor.class).requestFaceAuth();
diff --git a/packages/SystemUI/src/com/android/systemui/glwallpaper/EglHelper.java b/packages/SystemUI/src/com/android/systemui/glwallpaper/EglHelper.java
index aac721e3cb56..c6812a75b3bf 100644
--- a/packages/SystemUI/src/com/android/systemui/glwallpaper/EglHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/glwallpaper/EglHelper.java
@@ -22,6 +22,7 @@ import static android.opengl.EGL14.EGL_CONFIG_CAVEAT;
import static android.opengl.EGL14.EGL_CONTEXT_CLIENT_VERSION;
import static android.opengl.EGL14.EGL_DEFAULT_DISPLAY;
import static android.opengl.EGL14.EGL_DEPTH_SIZE;
+import static android.opengl.EGL14.EGL_EXTENSIONS;
import static android.opengl.EGL14.EGL_GREEN_SIZE;
import static android.opengl.EGL14.EGL_NONE;
import static android.opengl.EGL14.EGL_NO_CONTEXT;
@@ -41,6 +42,7 @@ import static android.opengl.EGL14.eglGetDisplay;
import static android.opengl.EGL14.eglGetError;
import static android.opengl.EGL14.eglInitialize;
import static android.opengl.EGL14.eglMakeCurrent;
+import static android.opengl.EGL14.eglQueryString;
import static android.opengl.EGL14.eglSwapBuffers;
import static android.opengl.EGL14.eglTerminate;
@@ -63,6 +65,8 @@ public class EglHelper {
// Below two constants make drawing at low priority, so other things can preempt our drawing.
private static final int EGL_CONTEXT_PRIORITY_LEVEL_IMG = 0x3100;
private static final int EGL_CONTEXT_PRIORITY_LOW_IMG = 0x3103;
+ private static final boolean DEBUG = true;
+ private static final String EGL_IMG_CONTEXT_PRIORITY = "EGL_IMG_context_priority";
private EGLDisplay mEglDisplay;
private EGLConfig mEglConfig;
@@ -70,6 +74,7 @@ public class EglHelper {
private EGLSurface mEglSurface;
private final int[] mEglVersion = new int[2];
private boolean mEglReady;
+ private boolean mContextPrioritySupported;
/**
* Initialize EGL and prepare EglSurface.
@@ -105,10 +110,22 @@ public class EglHelper {
return false;
}
+ mContextPrioritySupported = isContextPrioritySuppported();
+
mEglReady = true;
return true;
}
+ private boolean isContextPrioritySuppported() {
+ String[] extensions = eglQueryString(mEglDisplay, EGL_EXTENSIONS).split(" ");
+ for (String extension : extensions) {
+ if (extension.equals(EGL_IMG_CONTEXT_PRIORITY)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
private EGLConfig chooseEglConfig() {
int[] configsCount = new int[1];
EGLConfig[] configs = new EGLConfig[1];
@@ -146,6 +163,10 @@ public class EglHelper {
* @return true if EglSurface is ready.
*/
public boolean createEglSurface(SurfaceHolder surfaceHolder) {
+ if (DEBUG) {
+ Log.d(TAG, "createEglSurface start");
+ }
+
if (hasEglDisplay()) {
mEglSurface = eglCreateWindowSurface(mEglDisplay, mEglConfig, surfaceHolder, null, 0);
} else {
@@ -163,6 +184,9 @@ public class EglHelper {
return false;
}
+ if (DEBUG) {
+ Log.d(TAG, "createEglSurface done");
+ }
return true;
}
@@ -190,8 +214,19 @@ public class EglHelper {
* @return true if EglContext is ready.
*/
public boolean createEglContext() {
- int[] attrib_list = new int[] {EGL_CONTEXT_CLIENT_VERSION, 2,
- EGL_CONTEXT_PRIORITY_LEVEL_IMG, EGL_CONTEXT_PRIORITY_LOW_IMG, EGL_NONE};
+ if (DEBUG) {
+ Log.d(TAG, "createEglContext start");
+ }
+
+ int[] attrib_list = new int[5];
+ int idx = 0;
+ attrib_list[idx++] = EGL_CONTEXT_CLIENT_VERSION;
+ attrib_list[idx++] = 2;
+ if (mContextPrioritySupported) {
+ attrib_list[idx++] = EGL_CONTEXT_PRIORITY_LEVEL_IMG;
+ attrib_list[idx++] = EGL_CONTEXT_PRIORITY_LOW_IMG;
+ }
+ attrib_list[idx++] = EGL_NONE;
if (hasEglDisplay()) {
mEglContext = eglCreateContext(mEglDisplay, mEglConfig, EGL_NO_CONTEXT, attrib_list, 0);
} else {
@@ -203,6 +238,10 @@ public class EglHelper {
Log.w(TAG, "eglCreateContext failed: " + GLUtils.getEGLErrorString(eglGetError()));
return false;
}
+
+ if (DEBUG) {
+ Log.d(TAG, "createEglContext done");
+ }
return true;
}
diff --git a/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageRevealHelper.java b/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageRevealHelper.java
index b154e66a846e..99c55f13a8a3 100644
--- a/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageRevealHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageRevealHelper.java
@@ -19,6 +19,7 @@ package com.android.systemui.glwallpaper;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
+import android.util.Log;
import com.android.systemui.Interpolators;
@@ -30,6 +31,7 @@ class ImageRevealHelper {
private static final String TAG = ImageRevealHelper.class.getSimpleName();
private static final float MAX_REVEAL = 0f;
private static final float MIN_REVEAL = 1f;
+ private static final boolean DEBUG = true;
private final ValueAnimator mAnimator;
private final RevealStateListener mRevealListener;
@@ -57,6 +59,9 @@ class ImageRevealHelper {
@Override
public void onAnimationEnd(Animator animation) {
if (!mIsCanceled && mRevealListener != null) {
+ if (DEBUG) {
+ Log.d(TAG, "transition end");
+ }
mRevealListener.onRevealEnd();
}
mIsCanceled = false;
@@ -65,6 +70,9 @@ class ImageRevealHelper {
@Override
public void onAnimationStart(Animator animation) {
if (mRevealListener != null) {
+ if (DEBUG) {
+ Log.d(TAG, "transition start");
+ }
mRevealListener.onRevealStart(true /* animate */);
}
}
@@ -82,6 +90,9 @@ class ImageRevealHelper {
}
void updateAwake(boolean awake, long duration) {
+ if (DEBUG) {
+ Log.d(TAG, "updateAwake: awake=" + awake + ", duration=" + duration);
+ }
mAwake = awake;
mAnimator.setDuration(duration);
if (duration == 0) {
diff --git a/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageWallpaperRenderer.java b/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageWallpaperRenderer.java
index 29606347f009..a8371e31d71c 100644
--- a/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageWallpaperRenderer.java
+++ b/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageWallpaperRenderer.java
@@ -46,6 +46,7 @@ public class ImageWallpaperRenderer implements GLWallpaperRenderer,
private static final String TAG = ImageWallpaperRenderer.class.getSimpleName();
private static final float SCALE_VIEWPORT_MIN = 1f;
private static final float SCALE_VIEWPORT_MAX = 1.1f;
+ private static final boolean DEBUG = true;
private final WallpaperManager mWallpaperManager;
private final ImageGLProgram mProgram;
@@ -107,6 +108,9 @@ public class ImageWallpaperRenderer implements GLWallpaperRenderer,
}
private boolean loadBitmap() {
+ if (DEBUG) {
+ Log.d(TAG, "loadBitmap: mBitmap=" + mBitmap);
+ }
if (mWallpaperManager != null && mBitmap == null) {
mBitmap = mWallpaperManager.getBitmap();
mWallpaperManager.forgetLoadedWallpaper();
@@ -119,6 +123,9 @@ public class ImageWallpaperRenderer implements GLWallpaperRenderer,
mSurfaceSize.set(0, 0, surfaceWidth, surfaceHeight);
}
}
+ if (DEBUG) {
+ Log.d(TAG, "loadBitmap done");
+ }
return mBitmap != null;
}
@@ -223,6 +230,7 @@ public class ImageWallpaperRenderer implements GLWallpaperRenderer,
out.print(prefix); out.print("mXOffset="); out.print(mXOffset);
out.print(prefix); out.print("mYOffset="); out.print(mYOffset);
out.print(prefix); out.print("threshold="); out.print(mImageProcessHelper.getThreshold());
+ out.print(prefix); out.print("mReveal="); out.print(mImageRevealHelper.getReveal());
mWallpaper.dump(prefix, fd, out, args);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyboard/KeyboardUI.java b/packages/SystemUI/src/com/android/systemui/keyboard/KeyboardUI.java
index 7d52a9a08c2a..42f455af7df4 100644
--- a/packages/SystemUI/src/com/android/systemui/keyboard/KeyboardUI.java
+++ b/packages/SystemUI/src/com/android/systemui/keyboard/KeyboardUI.java
@@ -117,6 +117,10 @@ public class KeyboardUI extends SystemUI implements InputManager.OnTabletModeCha
private int mState;
+ public KeyboardUI(Context context) {
+ super(context);
+ }
+
@Override
public void start() {
mContext = super.mContext;
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardLifecyclesDispatcher.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardLifecyclesDispatcher.java
index b3481c52d7f2..4a33590f64d2 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardLifecyclesDispatcher.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardLifecyclesDispatcher.java
@@ -19,9 +19,13 @@ package com.android.systemui.keyguard;
import android.os.Handler;
import android.os.Message;
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
/**
* Dispatches the lifecycles keyguard gets from WindowManager on the main thread.
*/
+@Singleton
public class KeyguardLifecyclesDispatcher {
static final int SCREEN_TURNING_ON = 0;
@@ -37,6 +41,7 @@ public class KeyguardLifecyclesDispatcher {
private final ScreenLifecycle mScreenLifecycle;
private final WakefulnessLifecycle mWakefulnessLifecycle;
+ @Inject
public KeyguardLifecyclesDispatcher(ScreenLifecycle screenLifecycle,
WakefulnessLifecycle wakefulnessLifecycle) {
mScreenLifecycle = screenLifecycle;
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
index 81247cd2f727..9f4056fdf65b 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
@@ -33,25 +33,30 @@ import com.android.internal.policy.IKeyguardDrawnCallback;
import com.android.internal.policy.IKeyguardExitCallback;
import com.android.internal.policy.IKeyguardService;
import com.android.internal.policy.IKeyguardStateCallback;
-import com.android.systemui.Dependency;
import com.android.systemui.SystemUIApplication;
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+@Singleton
public class KeyguardService extends Service {
static final String TAG = "KeyguardService";
static final String PERMISSION = android.Manifest.permission.CONTROL_KEYGUARD;
- private KeyguardViewMediator mKeyguardViewMediator;
- private KeyguardLifecyclesDispatcher mKeyguardLifecyclesDispatcher;
+ private final KeyguardViewMediator mKeyguardViewMediator;
+ private final KeyguardLifecyclesDispatcher mKeyguardLifecyclesDispatcher;
+
+ @Inject
+ public KeyguardService(KeyguardViewMediator keyguardViewMediator,
+ KeyguardLifecyclesDispatcher keyguardLifecyclesDispatcher) {
+ super();
+ mKeyguardViewMediator = keyguardViewMediator;
+ mKeyguardLifecyclesDispatcher = keyguardLifecyclesDispatcher;
+ }
@Override
public void onCreate() {
((SystemUIApplication) getApplication()).startServicesIfNeeded();
- mKeyguardViewMediator =
- ((SystemUIApplication) getApplication()).getComponent(KeyguardViewMediator.class);
- mKeyguardLifecyclesDispatcher = new KeyguardLifecyclesDispatcher(
- Dependency.get(ScreenLifecycle.class),
- Dependency.get(WakefulnessLifecycle.class));
-
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java
index 1d2de6027d76..e66a9fadb937 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java
@@ -60,7 +60,6 @@ import com.android.systemui.statusbar.phone.KeyguardBypassController;
import com.android.systemui.statusbar.policy.NextAlarmController;
import com.android.systemui.statusbar.policy.NextAlarmControllerImpl;
import com.android.systemui.statusbar.policy.ZenModeController;
-import com.android.systemui.statusbar.policy.ZenModeControllerImpl;
import com.android.systemui.util.wakelock.SettableWakeLock;
import com.android.systemui.util.wakelock.WakeLock;
@@ -107,8 +106,8 @@ public class KeyguardSliceProvider extends SliceProvider implements
protected final Uri mMediaUri;
private final Date mCurrentTime = new Date();
private final Handler mHandler;
+ private final Handler mMediaHandler;
private final AlarmManager.OnAlarmListener mUpdateNextAlarm = this::updateNextAlarm;
- private final Object mMediaToken = new Object();
private DozeParameters mDozeParameters;
@VisibleForTesting
protected SettableWakeLock mMediaWakeLock;
@@ -174,17 +173,13 @@ public class KeyguardSliceProvider extends SliceProvider implements
}
};
- public KeyguardSliceProvider() {
- this(new Handler());
- }
-
public static KeyguardSliceProvider getAttachedInstance() {
return KeyguardSliceProvider.sInstance;
}
- @VisibleForTesting
- KeyguardSliceProvider(Handler handler) {
- mHandler = handler;
+ public KeyguardSliceProvider() {
+ mHandler = new Handler();
+ mMediaHandler = new Handler();
mSliceUri = Uri.parse(KEYGUARD_SLICE_URI);
mHeaderUri = Uri.parse(KEYGUARD_HEADER_URI);
mDateUri = Uri.parse(KEYGUARD_DATE_URI);
@@ -328,7 +323,7 @@ public class KeyguardSliceProvider extends SliceProvider implements
mContentResolver = getContext().getContentResolver();
mNextAlarmController = new NextAlarmControllerImpl(getContext());
mNextAlarmController.addCallback(this);
- mZenModeController = new ZenModeControllerImpl(getContext(), mHandler);
+ mZenModeController = Dependency.get(ZenModeController.class);
mZenModeController.addCallback(this);
mDatePattern = getContext().getString(R.string.system_ui_aod_date_pattern);
mPendingIntent = PendingIntent.getActivity(getContext(), 0, new Intent(), 0);
@@ -470,16 +465,18 @@ public class KeyguardSliceProvider extends SliceProvider implements
public void onMetadataOrStateChanged(MediaMetadata metadata, @PlaybackState.State int state) {
synchronized (this) {
boolean nextVisible = NotificationMediaManager.isPlayingState(state);
- mHandler.removeCallbacksAndMessages(mMediaToken);
+ mMediaHandler.removeCallbacksAndMessages(null);
if (mMediaIsVisible && !nextVisible && mStatusBarState != StatusBarState.SHADE) {
// We need to delay this event for a few millis when stopping to avoid jank in the
// animation. The media app might not send its update when buffering, and the slice
// would end up without a header for 0.5 second.
mMediaWakeLock.setAcquired(true);
- mHandler.postDelayed(() -> {
- updateMediaStateLocked(metadata, state);
- mMediaWakeLock.setAcquired(false);
- }, mMediaToken, 2000);
+ mMediaHandler.postDelayed(() -> {
+ synchronized (this) {
+ updateMediaStateLocked(metadata, state);
+ mMediaWakeLock.setAcquired(false);
+ }
+ }, 2000);
} else {
mMediaWakeLock.setAcquired(false);
updateMediaStateLocked(metadata, state);
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 7fb6909be724..800d021c4ce7 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -68,6 +68,7 @@ import android.view.WindowManagerPolicyConstants;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.policy.IKeyguardDismissCallback;
import com.android.internal.policy.IKeyguardDrawnCallback;
import com.android.internal.policy.IKeyguardExitCallback;
@@ -100,6 +101,7 @@ import java.io.PrintWriter;
import java.util.ArrayList;
import javax.inject.Inject;
+import javax.inject.Singleton;
/**
* Mediates requests related to the keyguard. This includes queries about the
@@ -142,6 +144,7 @@ import javax.inject.Inject;
* directly to the keyguard UI is posted to a {@link android.os.Handler} to ensure it is taken on the UI
* thread of the keyguard.
*/
+@Singleton
public class KeyguardViewMediator extends SystemUI {
private static final int KEYGUARD_DISPLAY_TIMEOUT_DELAY_DEFAULT = 30000;
private static final long KEYGUARD_DONE_PENDING_TIMEOUT_MS = 3000;
@@ -232,7 +235,7 @@ public class KeyguardViewMediator extends SystemUI {
*/
private PowerManager.WakeLock mShowKeyguardWakeLock;
- private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
+ private final StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
// these are protected by synchronized (this)
@@ -315,7 +318,7 @@ public class KeyguardViewMediator extends SystemUI {
* the keyguard.
*/
private boolean mWaitingUntilKeyguardVisible = false;
- private LockPatternUtils mLockPatternUtils;
+ private final LockPatternUtils mLockPatternUtils;
private boolean mKeyguardDonePending = false;
private boolean mHideAnimationRun = false;
private boolean mHideAnimationRunning = false;
@@ -648,29 +651,26 @@ public class KeyguardViewMediator extends SystemUI {
@Override
public int getBouncerPromptReason() {
- // TODO(b/140053364)
- return whitelistIpcs(() -> {
- int currentUser = ActivityManager.getCurrentUser();
- boolean trust = mTrustManager.isTrustUsuallyManaged(currentUser);
- boolean biometrics = mUpdateMonitor.isUnlockingWithBiometricsPossible(currentUser);
- boolean any = trust || biometrics;
- KeyguardUpdateMonitor.StrongAuthTracker strongAuthTracker =
- mUpdateMonitor.getStrongAuthTracker();
- int strongAuth = strongAuthTracker.getStrongAuthForUser(currentUser);
-
- if (any && !strongAuthTracker.hasUserAuthenticatedSinceBoot()) {
- return KeyguardSecurityView.PROMPT_REASON_RESTART;
- } else if (any && (strongAuth & STRONG_AUTH_REQUIRED_AFTER_TIMEOUT) != 0) {
- return KeyguardSecurityView.PROMPT_REASON_TIMEOUT;
- } else if (any && (strongAuth & STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW) != 0) {
- return KeyguardSecurityView.PROMPT_REASON_DEVICE_ADMIN;
- } else if (trust && (strongAuth & SOME_AUTH_REQUIRED_AFTER_USER_REQUEST) != 0) {
- return KeyguardSecurityView.PROMPT_REASON_USER_REQUEST;
- } else if (any && (strongAuth & STRONG_AUTH_REQUIRED_AFTER_LOCKOUT) != 0) {
- return KeyguardSecurityView.PROMPT_REASON_AFTER_LOCKOUT;
- }
- return KeyguardSecurityView.PROMPT_REASON_NONE;
- });
+ int currentUser = KeyguardUpdateMonitor.getCurrentUser();
+ boolean trust = mUpdateMonitor.isTrustUsuallyManaged(currentUser);
+ boolean biometrics = mUpdateMonitor.isUnlockingWithBiometricsPossible(currentUser);
+ boolean any = trust || biometrics;
+ KeyguardUpdateMonitor.StrongAuthTracker strongAuthTracker =
+ mUpdateMonitor.getStrongAuthTracker();
+ int strongAuth = strongAuthTracker.getStrongAuthForUser(currentUser);
+
+ if (any && !strongAuthTracker.hasUserAuthenticatedSinceBoot()) {
+ return KeyguardSecurityView.PROMPT_REASON_RESTART;
+ } else if (any && (strongAuth & STRONG_AUTH_REQUIRED_AFTER_TIMEOUT) != 0) {
+ return KeyguardSecurityView.PROMPT_REASON_TIMEOUT;
+ } else if (any && (strongAuth & STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW) != 0) {
+ return KeyguardSecurityView.PROMPT_REASON_DEVICE_ADMIN;
+ } else if (trust && (strongAuth & SOME_AUTH_REQUIRED_AFTER_USER_REQUEST) != 0) {
+ return KeyguardSecurityView.PROMPT_REASON_USER_REQUEST;
+ } else if (any && (strongAuth & STRONG_AUTH_REQUIRED_AFTER_LOCKOUT) != 0) {
+ return KeyguardSecurityView.PROMPT_REASON_AFTER_LOCKOUT;
+ }
+ return KeyguardSecurityView.PROMPT_REASON_NONE;
}
@Override
@@ -682,10 +682,26 @@ public class KeyguardViewMediator extends SystemUI {
};
@Inject
- public KeyguardViewMediator(FalsingManager falsingManager) {
- super();
-
+ public KeyguardViewMediator(
+ Context context,
+ FalsingManager falsingManager,
+ LockPatternUtils lockPatternUtils) {
+ this(context, falsingManager, lockPatternUtils, SystemUIFactory.getInstance());
+ }
+
+ @VisibleForTesting
+ KeyguardViewMediator(
+ Context context,
+ FalsingManager falsingManager,
+ LockPatternUtils lockPatternUtils,
+ SystemUIFactory systemUIFactory) {
+ super(context);
mFalsingManager = falsingManager;
+ mLockPatternUtils = lockPatternUtils;
+ mStatusBarKeyguardViewManager = systemUIFactory.createStatusBarKeyguardViewManager(
+ mContext,
+ mViewMediatorCallback,
+ mLockPatternUtils);
}
public void userActivity() {
@@ -699,7 +715,7 @@ public class KeyguardViewMediator extends SystemUI {
private void setupLocked() {
mPM = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
- mTrustManager = (TrustManager) mContext.getSystemService(Context.TRUST_SERVICE);
+ mTrustManager = mContext.getSystemService(TrustManager.class);
mShowKeyguardWakeLock = mPM.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "show keyguard");
mShowKeyguardWakeLock.setReferenceCounted(false);
@@ -723,7 +739,6 @@ public class KeyguardViewMediator extends SystemUI {
mUpdateMonitor = Dependency.get(KeyguardUpdateMonitor.class);
- mLockPatternUtils = new LockPatternUtils(mContext);
KeyguardUpdateMonitor.setCurrentUser(ActivityManager.getCurrentUser());
// Assume keyguard is showing (unless it's disabled) until we know for sure, unless Keyguard
@@ -737,9 +752,6 @@ public class KeyguardViewMediator extends SystemUI {
setShowingLocked(false /* showing */, true /* forceCallbacks */);
}
- mStatusBarKeyguardViewManager =
- SystemUIFactory.getInstance().createStatusBarKeyguardViewManager(mContext,
- mViewMediatorCallback, mLockPatternUtils);
final ContentResolver cr = mContext.getContentResolver();
mDeviceInteractive = mPM.isInteractive();
@@ -789,7 +801,6 @@ public class KeyguardViewMediator extends SystemUI {
synchronized (this) {
setupLocked();
}
- putComponent(KeyguardViewMediator.class, this);
}
/**
@@ -822,6 +833,11 @@ public class KeyguardViewMediator extends SystemUI {
mDeviceInteractive = false;
mGoingToSleep = true;
+ // Reset keyguard going away state so we can start listening for fingerprint. We
+ // explicitly DO NOT want to call mStatusBarWindowController.setKeyguardGoingAway(false)
+ // here, since that will mess with the device lock state.
+ mUpdateMonitor.setKeyguardGoingAway(false);
+
// Lock immediately based on setting if secure (user has a pin/pattern/password).
// This also "locks" the device when not secure to provide easy access to the
// camera while preventing unwanted input.
@@ -1569,12 +1585,14 @@ public class KeyguardViewMediator extends SystemUI {
handleNotifyFinishedGoingToSleep();
break;
case NOTIFY_SCREEN_TURNING_ON:
- Trace.beginSection("KeyguardViewMediator#handleMessage NOTIFY_SCREEN_TURNING_ON");
+ Trace.beginSection(
+ "KeyguardViewMediator#handleMessage NOTIFY_SCREEN_TURNING_ON");
handleNotifyScreenTurningOn((IKeyguardDrawnCallback) msg.obj);
Trace.endSection();
break;
case NOTIFY_SCREEN_TURNED_ON:
- Trace.beginSection("KeyguardViewMediator#handleMessage NOTIFY_SCREEN_TURNED_ON");
+ Trace.beginSection(
+ "KeyguardViewMediator#handleMessage NOTIFY_SCREEN_TURNED_ON");
handleNotifyScreenTurnedOn();
Trace.endSection();
break;
@@ -1582,7 +1600,8 @@ public class KeyguardViewMediator extends SystemUI {
handleNotifyScreenTurnedOff();
break;
case NOTIFY_STARTED_WAKING_UP:
- Trace.beginSection("KeyguardViewMediator#handleMessage NOTIFY_STARTED_WAKING_UP");
+ Trace.beginSection(
+ "KeyguardViewMediator#handleMessage NOTIFY_STARTED_WAKING_UP");
handleNotifyStartedWakingUp();
Trace.endSection();
break;
@@ -1611,14 +1630,16 @@ public class KeyguardViewMediator extends SystemUI {
handleDismiss(message.getCallback(), message.getMessage());
break;
case START_KEYGUARD_EXIT_ANIM:
- Trace.beginSection("KeyguardViewMediator#handleMessage START_KEYGUARD_EXIT_ANIM");
+ Trace.beginSection(
+ "KeyguardViewMediator#handleMessage START_KEYGUARD_EXIT_ANIM");
StartKeyguardExitAnimParams params = (StartKeyguardExitAnimParams) msg.obj;
handleStartKeyguardExitAnimation(params.startTime, params.fadeoutDuration);
mFalsingManager.onSucccessfulUnlock();
Trace.endSection();
break;
case KEYGUARD_DONE_PENDING_TIMEOUT:
- Trace.beginSection("KeyguardViewMediator#handleMessage KEYGUARD_DONE_PENDING_TIMEOUT");
+ Trace.beginSection("KeyguardViewMediator#handleMessage"
+ + " KEYGUARD_DONE_PENDING_TIMEOUT");
Log.w(TAG, "Timeout while waiting for activity drawn!");
Trace.endSection();
break;
@@ -1796,8 +1817,8 @@ public class KeyguardViewMediator extends SystemUI {
mHideAnimationRun = false;
adjustStatusBarLocked();
userActivity();
- mUpdateMonitor.setKeyguardGoingAway(false /* away */);
- mStatusBarWindowController.setKeyguardGoingAway(false /* goingAway */);
+ mUpdateMonitor.setKeyguardGoingAway(false);
+ mStatusBarWindowController.setKeyguardGoingAway(false);
mShowKeyguardWakeLock.release();
}
mKeyguardDisplayManager.show();
@@ -1829,8 +1850,8 @@ public class KeyguardViewMediator extends SystemUI {
.KEYGUARD_GOING_AWAY_FLAG_SUBTLE_WINDOW_ANIMATIONS;
}
- mUpdateMonitor.setKeyguardGoingAway(true /* goingAway */);
- mStatusBarWindowController.setKeyguardGoingAway(true /* goingAway */);
+ mUpdateMonitor.setKeyguardGoingAway(true);
+ mStatusBarWindowController.setKeyguardGoingAway(true);
// Don't actually hide the Keyguard at the moment, wait for window
// manager until it tells us it's safe to do so with
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/WorkLockActivity.java b/packages/SystemUI/src/com/android/systemui/keyguard/WorkLockActivity.java
index a9fe54bae19d..4d061e18ebba 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/WorkLockActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/WorkLockActivity.java
@@ -49,6 +49,12 @@ public class WorkLockActivity extends Activity {
private static final String TAG = "WorkLockActivity";
/**
+ * Add additional extra {@link com.android.settings.password.ConfirmDeviceCredentialActivity} to
+ * enable device policy management enforcement from systemui.
+ */
+ public static final String EXTRA_FROM_WORK_LOCK_ACTIVITY = "from_work_lock_activity";
+
+ /**
* Contains a {@link TaskDescription} for the activity being covered.
*/
static final String EXTRA_TASK_DESCRIPTION =
@@ -151,6 +157,7 @@ public class WorkLockActivity extends Activity {
if (target != null) {
credential.putExtra(Intent.EXTRA_INTENT, target.getIntentSender());
+ credential.putExtra(EXTRA_FROM_WORK_LOCK_ACTIVITY, true);
}
startActivityForResult(credential, REQUEST_CODE_CONFIRM_CREDENTIALS);
diff --git a/packages/SystemUI/src/com/android/systemui/log/Event.java b/packages/SystemUI/src/com/android/systemui/log/Event.java
new file mode 100644
index 000000000000..92862a2bc74c
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/log/Event.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.log;
+
+import android.annotation.IntDef;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Stores information about an event that occurred in SystemUI to be used for debugging and triage.
+ * Every event has a time stamp, log level and message.
+ * Events are stored in {@link SysuiLog} and can be printed in a dumpsys.
+ */
+public class Event {
+ public static final int UNINITIALIZED = -1;
+
+ @IntDef({ERROR, WARN, INFO, DEBUG, VERBOSE})
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface Level {}
+ public static final int VERBOSE = 2;
+ public static final int DEBUG = 3;
+ public static final int INFO = 4;
+ public static final int WARN = 5;
+ public static final int ERROR = 6;
+
+ private long mTimestamp;
+ private @Level int mLogLevel = DEBUG;
+ protected String mMessage;
+
+ public Event(String message) {
+ mTimestamp = System.currentTimeMillis();
+ mMessage = message;
+ }
+
+ public Event(@Level int logLevel, String message) {
+ mTimestamp = System.currentTimeMillis();
+ mLogLevel = logLevel;
+ mMessage = message;
+ }
+
+ public String getMessage() {
+ return mMessage;
+ }
+
+ public long getTimestamp() {
+ return mTimestamp;
+ }
+
+ public @Level int getLogLevel() {
+ return mLogLevel;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/log/RichEvent.java b/packages/SystemUI/src/com/android/systemui/log/RichEvent.java
new file mode 100644
index 000000000000..89b7a8181c44
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/log/RichEvent.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.log;
+
+/**
+ * Stores information about an event that occurred in SystemUI to be used for debugging and triage.
+ * Every rich event has a time stamp, event type, and log level, with the option to provide the
+ * reason this event was triggered.
+ * Events are stored in {@link SysuiLog} and can be printed in a dumpsys.
+ */
+public abstract class RichEvent extends Event {
+ private final int mType;
+ private final String mReason;
+
+ /**
+ * Create a rich event that includes an event type that matches with an index in the array
+ * getEventLabels().
+ */
+ public RichEvent(@Event.Level int logLevel, int type, String reason) {
+ super(logLevel, null);
+ final int numEvents = getEventLabels().length;
+ if (type < 0 || type >= numEvents) {
+ throw new IllegalArgumentException("Unsupported event type. Events only supported"
+ + " from 0 to " + (numEvents - 1) + ", but given type=" + type);
+ }
+ mType = type;
+ mReason = reason;
+ mMessage = getEventLabels()[mType] + " " + mReason;
+ }
+
+ /**
+ * Returns an array of the event labels. The index represents the event type and the
+ * corresponding String stored at that index is the user-readable representation of that event.
+ * @return array of user readable events, where the index represents its event type constant
+ */
+ public abstract String[] getEventLabels();
+
+ public int getType() {
+ return mType;
+ }
+
+ public String getReason() {
+ return mReason;
+ }
+
+ /**
+ * Builder to build a RichEvent.
+ * @param <B> Log specific builder that is extending this builder
+ */
+ public abstract static class Builder<B extends Builder<B>> {
+ public static final int UNINITIALIZED = -1;
+
+ private B mBuilder = getBuilder();
+ protected int mType = UNINITIALIZED;
+ protected String mReason;
+ protected @Level int mLogLevel;
+
+ /**
+ * Get the log-specific builder.
+ */
+ public abstract B getBuilder();
+
+ /**
+ * Build the log-specific event.
+ */
+ public abstract RichEvent build();
+
+ /**
+ * Optional - set the log level. Defaults to DEBUG.
+ */
+ public B setLogLevel(@Level int logLevel) {
+ mLogLevel = logLevel;
+ return mBuilder;
+ }
+
+ /**
+ * Required - set the event type. These events must correspond with the events from
+ * getEventLabels().
+ */
+ public B setType(int type) {
+ mType = type;
+ return mBuilder;
+ }
+
+ /**
+ * Optional - set the reason why this event was triggered.
+ */
+ public B setReason(String reason) {
+ mReason = reason;
+ return mBuilder;
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/log/SysuiLog.java b/packages/SystemUI/src/com/android/systemui/log/SysuiLog.java
new file mode 100644
index 000000000000..a6e10e6b345b
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/log/SysuiLog.java
@@ -0,0 +1,163 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.log;
+
+import android.os.Build;
+import android.os.SystemProperties;
+import android.util.Log;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.systemui.DumpController;
+import com.android.systemui.Dumpable;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.text.SimpleDateFormat;
+import java.util.ArrayDeque;
+import java.util.Locale;
+
+/**
+ * Thread-safe logger in SystemUI which prints logs to logcat and stores logs to be
+ * printed by the DumpController. This is an alternative to printing directly
+ * to avoid logs being deleted by chatty. The number of logs retained is varied based on
+ * whether the build is {@link Build.IS_DEBUGGABLE}.
+ *
+ * To manually view the logs via adb:
+ * adb shell dumpsys activity service com.android.systemui/.SystemUIService \
+ * dependency DumpController <SysuiLogId>
+ */
+public class SysuiLog implements Dumpable {
+ public static final SimpleDateFormat DATE_FORMAT =
+ new SimpleDateFormat("MM-dd HH:mm:ss", Locale.US);
+
+ private final Object mDataLock = new Object();
+ private final String mId;
+ private final int mMaxLogs;
+ private boolean mEnabled;
+
+ @VisibleForTesting protected ArrayDeque<Event> mTimeline;
+
+ /**
+ * Creates a SysuiLog
+ * To enable or disable logs, set the system property and then restart the device:
+ * adb shell setprop sysui.log.enabled.<id> true/false && adb reboot
+ * @param dumpController where to register this logger's dumpsys
+ * @param id user-readable tag for this logger
+ * @param maxDebugLogs maximum number of logs to retain when {@link sDebuggable} is true
+ * @param maxLogs maximum number of logs to retain when {@link sDebuggable} is false
+ */
+ public SysuiLog(DumpController dumpController, String id, int maxDebugLogs, int maxLogs) {
+ this(dumpController, id, sDebuggable ? maxDebugLogs : maxLogs,
+ SystemProperties.getBoolean(SYSPROP_ENABLED_PREFIX + id, DEFAULT_ENABLED));
+ }
+
+ @VisibleForTesting
+ protected SysuiLog(DumpController dumpController, String id, int maxLogs, boolean enabled) {
+ mId = id;
+ mMaxLogs = maxLogs;
+ mEnabled = enabled;
+ mTimeline = mEnabled ? new ArrayDeque<>(mMaxLogs) : null;
+ dumpController.registerDumpable(mId, this);
+ }
+
+ public SysuiLog(DumpController dumpController, String id) {
+ this(dumpController, id, DEFAULT_MAX_DEBUG_LOGS, DEFAULT_MAX_LOGS);
+ }
+
+ /**
+ * Logs an event to the timeline which can be printed by the dumpsys.
+ * May also log to logcat if enabled.
+ * @return true if event was logged, else false
+ */
+ public boolean log(Event event) {
+ if (!mEnabled) {
+ return false;
+ }
+
+ synchronized (mDataLock) {
+ if (mTimeline.size() >= mMaxLogs) {
+ mTimeline.removeFirst();
+ }
+
+ mTimeline.add(event);
+ }
+
+ if (LOG_TO_LOGCAT_ENABLED) {
+ final String strEvent = eventToString(event);
+ switch (event.getLogLevel()) {
+ case Event.VERBOSE:
+ Log.v(mId, strEvent);
+ break;
+ case Event.DEBUG:
+ Log.d(mId, strEvent);
+ break;
+ case Event.ERROR:
+ Log.e(mId, strEvent);
+ break;
+ case Event.INFO:
+ Log.i(mId, strEvent);
+ break;
+ case Event.WARN:
+ Log.w(mId, strEvent);
+ break;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * @return user-readable string of the given event
+ */
+ public String eventToString(Event event) {
+ StringBuilder sb = new StringBuilder();
+ sb.append(SysuiLog.DATE_FORMAT.format(event.getTimestamp()));
+ sb.append(" ");
+ sb.append(event.getMessage());
+ return sb.toString();
+ }
+
+ /**
+ * only call on this method if you have the mDataLock
+ */
+ private void dumpTimelineLocked(PrintWriter pw) {
+ pw.println("\tTimeline:");
+
+ for (Event event : mTimeline) {
+ pw.println("\t" + eventToString(event));
+ }
+ }
+
+ @Override
+ public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ pw.println(mId + ":");
+
+ if (mEnabled) {
+ synchronized (mDataLock) {
+ dumpTimelineLocked(pw);
+ }
+ } else {
+ pw.print(" - Logging disabled.");
+ }
+ }
+
+ private static boolean sDebuggable = Build.IS_DEBUGGABLE;
+ private static final String SYSPROP_ENABLED_PREFIX = "sysui.log.enabled.";
+ private static final boolean LOG_TO_LOGCAT_ENABLED = sDebuggable;
+ private static final boolean DEFAULT_ENABLED = sDebuggable;
+ private static final int DEFAULT_MAX_DEBUG_LOGS = 100;
+ private static final int DEFAULT_MAX_LOGS = 50;
+}
diff --git a/packages/SystemUI/src/com/android/systemui/media/RingtonePlayer.java b/packages/SystemUI/src/com/android/systemui/media/RingtonePlayer.java
index aebadf936e0c..4c96de232810 100644
--- a/packages/SystemUI/src/com/android/systemui/media/RingtonePlayer.java
+++ b/packages/SystemUI/src/com/android/systemui/media/RingtonePlayer.java
@@ -59,6 +59,10 @@ public class RingtonePlayer extends SystemUI {
private final NotificationPlayer mAsyncPlayer = new NotificationPlayer(TAG);
private final HashMap<IBinder, Client> mClients = new HashMap<IBinder, Client>();
+ public RingtonePlayer(Context context) {
+ super(context);
+ }
+
@Override
public void start() {
mAsyncPlayer.setUsesWakeLock(mContext);
diff --git a/packages/SystemUI/src/com/android/systemui/pip/BasePipManager.java b/packages/SystemUI/src/com/android/systemui/pip/BasePipManager.java
index e0fc31bc70b8..05be4259dd3b 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/BasePipManager.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/BasePipManager.java
@@ -27,5 +27,6 @@ public interface BasePipManager {
default void expandPip() {}
default void hidePipMenu(Runnable onStartCallback, Runnable onEndCallback) {}
void onConfigurationChanged(Configuration newConfig);
+ default void setShelfHeight(boolean visible, int height) {}
default void dump(PrintWriter pw) {}
}
diff --git a/packages/SystemUI/src/com/android/systemui/pip/PipBoundsHandler.java b/packages/SystemUI/src/com/android/systemui/pip/PipBoundsHandler.java
index 6795bff6409a..686e7db86c3b 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/PipBoundsHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/PipBoundsHandler.java
@@ -55,6 +55,12 @@ public class PipBoundsHandler {
private final Rect mTmpInsets = new Rect();
private final Point mTmpDisplaySize = new Point();
+ /**
+ * Tracks the destination bounds, used for any following
+ * {@link #onMovementBoundsChanged(Rect, Rect, Rect, DisplayInfo)} calculations.
+ */
+ private final Rect mLastDestinationBounds = new Rect();
+
private IPinnedStackController mPinnedStackController;
private ComponentName mLastPipComponentName;
private float mReentrySnapFraction = INVALID_SNAP_FRACTION;
@@ -120,19 +126,26 @@ public class PipBoundsHandler {
}
/**
- * Responds to IPinnedStackListener on IME visibility change.
+ * Sets both shelf visibility and its height if applicable.
+ * @return {@code true} if the internal shelf state is changed, {@code false} otherwise.
*/
- public void onImeVisibilityChanged(boolean imeVisible, int imeHeight) {
- mIsImeShowing = imeVisible;
- mImeHeight = imeHeight;
+ public boolean setShelfHeight(boolean shelfVisible, int shelfHeight) {
+ final boolean shelfShowing = shelfVisible && shelfHeight > 0;
+ if (shelfShowing == mIsShelfShowing && shelfHeight == mShelfHeight) {
+ return false;
+ }
+
+ mIsShelfShowing = shelfVisible;
+ mShelfHeight = shelfHeight;
+ return true;
}
/**
- * Responds to IPinnedStackListener on shelf visibility change.
+ * Responds to IPinnedStackListener on IME visibility change.
*/
- public void onShelfVisibilityChanged(boolean shelfVisible, int shelfHeight) {
- mIsShelfShowing = shelfVisible;
- mShelfHeight = shelfHeight;
+ public void onImeVisibilityChanged(boolean imeVisible, int imeHeight) {
+ mIsImeShowing = imeVisible;
+ mImeHeight = imeHeight;
}
/**
@@ -185,6 +198,10 @@ public class PipBoundsHandler {
mLastPipComponentName = null;
}
+ public Rect getLastDestinationBounds() {
+ return mLastDestinationBounds;
+ }
+
/**
* Responds to IPinnedStackListener on {@link DisplayInfo} change.
* It will normally follow up with a
@@ -232,6 +249,7 @@ public class PipBoundsHandler {
try {
mPinnedStackController.startAnimation(destinationBounds, sourceRectHint,
-1 /* animationDuration */);
+ mLastDestinationBounds.set(destinationBounds);
} catch (RemoteException e) {
Log.e(TAG, "Failed to start PiP animation from SysUI", e);
}
diff --git a/packages/SystemUI/src/com/android/systemui/pip/PipUI.java b/packages/SystemUI/src/com/android/systemui/pip/PipUI.java
index 37c8163702cf..f1e801b3a474 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/PipUI.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/PipUI.java
@@ -19,6 +19,7 @@ package com.android.systemui.pip;
import static android.content.pm.PackageManager.FEATURE_LEANBACK_ONLY;
import static android.content.pm.PackageManager.FEATURE_PICTURE_IN_PICTURE;
+import android.content.Context;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.os.UserHandle;
@@ -30,15 +31,24 @@ import com.android.systemui.statusbar.CommandQueue;
import java.io.FileDescriptor;
import java.io.PrintWriter;
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
/**
* Controls the picture-in-picture window.
*/
+@Singleton
public class PipUI extends SystemUI implements CommandQueue.Callbacks {
private BasePipManager mPipManager;
private boolean mSupportsPip;
+ @Inject
+ public PipUI(Context context) {
+ super(context);
+ }
+
@Override
public void start() {
PackageManager pm = mContext.getPackageManager();
@@ -59,7 +69,6 @@ public class PipUI extends SystemUI implements CommandQueue.Callbacks {
mPipManager.initialize(mContext);
getComponent(CommandQueue.class).addCallback(this);
- putComponent(PipUI.class, this);
}
@Override
@@ -85,6 +94,14 @@ public class PipUI extends SystemUI implements CommandQueue.Callbacks {
mPipManager.onConfigurationChanged(newConfig);
}
+ public void setShelfHeight(boolean visible, int height) {
+ if (mPipManager == null) {
+ return;
+ }
+
+ mPipManager.setShelfHeight(visible, height);
+ }
+
@Override
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
if (mPipManager == null) {
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipDismissViewController.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipDismissViewController.java
index 8224365e7b96..3f15966c7fbb 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipDismissViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipDismissViewController.java
@@ -107,7 +107,7 @@ public class PipDismissViewController {
| LayoutParams.FLAG_NOT_FOCUSABLE,
PixelFormat.TRANSLUCENT);
lp.setTitle("pip-dismiss-overlay");
- lp.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
+ lp.privateFlags |= WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS;
lp.gravity = Gravity.TOP | Gravity.CENTER_HORIZONTAL;
mWindowManager.addView(mDismissView, lp);
}
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java
index 8dfae32a1939..369073c6564d 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java
@@ -143,14 +143,6 @@ public class PipManager implements BasePipManager {
}
@Override
- public void onShelfVisibilityChanged(boolean shelfVisible, int shelfHeight) {
- mHandler.post(() -> {
- mPipBoundsHandler.onShelfVisibilityChanged(shelfVisible, shelfHeight);
- mTouchHandler.onShelfVisibilityChanged(shelfVisible, shelfHeight);
- });
- }
-
- @Override
public void onMinimizedStateChanged(boolean isMinimized) {
mHandler.post(() -> {
mPipBoundsHandler.onMinimizedStateChanged(isMinimized);
@@ -161,14 +153,8 @@ public class PipManager implements BasePipManager {
@Override
public void onMovementBoundsChanged(Rect animatingBounds, boolean fromImeAdjustment,
boolean fromShelfAdjustment) {
- mHandler.post(() -> {
- // Populate the inset / normal bounds and DisplayInfo from mPipBoundsHandler first.
- mPipBoundsHandler.onMovementBoundsChanged(mTmpInsetBounds, mTmpNormalBounds,
- animatingBounds, mTmpDisplayInfo);
- mTouchHandler.onMovementBoundsChanged(mTmpInsetBounds, mTmpNormalBounds,
- animatingBounds, fromImeAdjustment, fromShelfAdjustment,
- mTmpDisplayInfo.rotation);
- });
+ mHandler.post(() -> updateMovementBounds(animatingBounds, fromImeAdjustment,
+ fromShelfAdjustment));
}
@Override
@@ -280,6 +266,31 @@ public class PipManager implements BasePipManager {
}
/**
+ * Sets both shelf visibility and its height.
+ */
+ @Override
+ public void setShelfHeight(boolean visible, int height) {
+ mHandler.post(() -> {
+ final boolean changed = mPipBoundsHandler.setShelfHeight(visible, height);
+ if (changed) {
+ mTouchHandler.onShelfVisibilityChanged(visible, height);
+ updateMovementBounds(mPipBoundsHandler.getLastDestinationBounds(),
+ false /* fromImeAdjustment */, true /* fromShelfAdjustment */);
+ }
+ });
+ }
+
+ private void updateMovementBounds(Rect animatingBounds, boolean fromImeAdjustment,
+ boolean fromShelfAdjustment) {
+ // Populate inset / normal bounds and DisplayInfo from mPipBoundsHandler first.
+ mPipBoundsHandler.onMovementBoundsChanged(mTmpInsetBounds, mTmpNormalBounds,
+ animatingBounds, mTmpDisplayInfo);
+ mTouchHandler.onMovementBoundsChanged(mTmpInsetBounds, mTmpNormalBounds,
+ animatingBounds, fromImeAdjustment, fromShelfAdjustment,
+ mTmpDisplayInfo.rotation);
+ }
+
+ /**
* Gets an instance of {@link PipManager}.
*/
public static PipManager getInstance() {
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java
index 4f2a6d82a08e..c452f64ff6f0 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java
@@ -90,7 +90,7 @@ public class PipMenuActivity extends Activity {
public static final int MESSAGE_UPDATE_ACTIONS = 4;
public static final int MESSAGE_UPDATE_DISMISS_FRACTION = 5;
public static final int MESSAGE_ANIMATION_ENDED = 6;
- public static final int MESSAGE_TOUCH_EVENT = 7;
+ public static final int MESSAGE_POINTER_EVENT = 7;
private static final int INITIAL_DISMISS_DELAY = 3500;
private static final int POST_INTERACTION_DISMISS_DELAY = 2000;
@@ -165,9 +165,9 @@ public class PipMenuActivity extends Activity {
break;
}
- case MESSAGE_TOUCH_EVENT: {
+ case MESSAGE_POINTER_EVENT: {
final MotionEvent ev = (MotionEvent) msg.obj;
- dispatchTouchEvent(ev);
+ dispatchPointerEvent(ev);
break;
}
}
@@ -219,6 +219,9 @@ public class PipMenuActivity extends Activity {
updateFromIntent(getIntent());
setTitle(R.string.pip_menu_title);
setDisablePreviewScreenshots(true);
+
+ // Hide without an animation.
+ getWindow().setExitTransition(null);
}
@Override
@@ -247,6 +250,9 @@ public class PipMenuActivity extends Activity {
protected void onStop() {
super.onStop();
+ // In cases such as device lock, hide and finish it so that it can be recreated on the top
+ // next time it starts, see also {@link #onUserLeaveHint}
+ hideMenu();
cancelDelayedFinish();
}
@@ -266,6 +272,17 @@ public class PipMenuActivity extends Activity {
}
}
+ /**
+ * Dispatch a pointer event from {@link PipTouchHandler}.
+ */
+ private void dispatchPointerEvent(MotionEvent event) {
+ if (event.isTouchEvent()) {
+ dispatchTouchEvent(event);
+ } else {
+ dispatchGenericMotionEvent(event);
+ }
+ }
+
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
if (!mAllowTouches) {
@@ -285,8 +302,6 @@ public class PipMenuActivity extends Activity {
public void finish() {
notifyActivityCallback(null);
super.finish();
- // Hide without an animation (the menu should already be invisible at this point)
- overridePendingTransition(0, 0);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivityController.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivityController.java
index 62c59e5842ff..b8e0b81e5e8e 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivityController.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivityController.java
@@ -508,12 +508,12 @@ public class PipMenuActivityController {
}
/**
- * Handles touch event sent from pip input consumer.
+ * Handles a pointer event sent from pip input consumer.
*/
- void handleTouchEvent(MotionEvent ev) {
+ void handlePointerEvent(MotionEvent ev) {
if (mToActivityMessenger != null) {
Message m = Message.obtain();
- m.what = PipMenuActivity.MESSAGE_TOUCH_EVENT;
+ m.what = PipMenuActivity.MESSAGE_POINTER_EVENT;
m.obj = ev;
try {
mToActivityMessenger.send(m);
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
index 1f36d97ce308..f59b372762bd 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
@@ -132,6 +132,7 @@ public class PipTouchHandler {
private boolean mSendingHoverAccessibilityEvents;
private boolean mMovementWithinMinimize;
private boolean mMovementWithinDismiss;
+ private PipAccessibilityInteractionConnection mConnection;
// Touch state
private final PipTouchState mTouchState;
@@ -213,9 +214,10 @@ public class PipTouchHandler {
// Register the listener for input consumer touch events
inputConsumerController.setInputListener(this::handleTouchEvent);
inputConsumerController.setRegistrationListener(this::onRegistrationChanged);
- onRegistrationChanged(inputConsumerController.isRegistered());
mPipBoundsHandler = pipBoundsHandler;
+ mConnection = new PipAccessibilityInteractionConnection(mMotionHelper,
+ this::onAccessibilityShowMenu, mHandler);
}
public void setTouchEnabled(boolean enabled) {
@@ -339,9 +341,7 @@ public class PipTouchHandler {
private void onRegistrationChanged(boolean isRegistered) {
mAccessibilityManager.setPictureInPictureActionReplacingConnection(isRegistered
- ? new PipAccessibilityInteractionConnection(mMotionHelper,
- this::onAccessibilityShowMenu, mHandler) : null);
-
+ ? mConnection : null);
if (!isRegistered && mTouchState.isUserInteracting()) {
// If the input consumer is unregistered while the user is interacting, then we may not
// get the final TOUCH_UP event, so clean up the dismiss target as well
@@ -409,27 +409,15 @@ public class PipTouchHandler {
}
case MotionEvent.ACTION_HOVER_ENTER:
case MotionEvent.ACTION_HOVER_MOVE: {
- if (mAccessibilityManager.isEnabled() && !mSendingHoverAccessibilityEvents) {
- AccessibilityEvent event = AccessibilityEvent.obtain(
- AccessibilityEvent.TYPE_VIEW_HOVER_ENTER);
- event.setImportantForAccessibility(true);
- event.setSourceNodeId(AccessibilityNodeInfo.ROOT_NODE_ID);
- event.setWindowId(
- AccessibilityWindowInfo.PICTURE_IN_PICTURE_ACTION_REPLACER_WINDOW_ID);
- mAccessibilityManager.sendAccessibilityEvent(event);
+ if (!shouldDeliverToMenu && !mSendingHoverAccessibilityEvents) {
+ sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_ENTER);
mSendingHoverAccessibilityEvents = true;
}
break;
}
case MotionEvent.ACTION_HOVER_EXIT: {
- if (mAccessibilityManager.isEnabled() && mSendingHoverAccessibilityEvents) {
- AccessibilityEvent event = AccessibilityEvent.obtain(
- AccessibilityEvent.TYPE_VIEW_HOVER_EXIT);
- event.setImportantForAccessibility(true);
- event.setSourceNodeId(AccessibilityNodeInfo.ROOT_NODE_ID);
- event.setWindowId(
- AccessibilityWindowInfo.PICTURE_IN_PICTURE_ACTION_REPLACER_WINDOW_ID);
- mAccessibilityManager.sendAccessibilityEvent(event);
+ if (!shouldDeliverToMenu && mSendingHoverAccessibilityEvents) {
+ sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_EXIT);
mSendingHoverAccessibilityEvents = false;
}
break;
@@ -445,12 +433,25 @@ public class PipTouchHandler {
mMenuController.pokeMenu();
}
- mMenuController.handleTouchEvent(cloneEvent);
+ mMenuController.handlePointerEvent(cloneEvent);
}
return true;
}
+ private void sendAccessibilityHoverEvent(int type) {
+ if (!mAccessibilityManager.isEnabled()) {
+ return;
+ }
+
+ AccessibilityEvent event = AccessibilityEvent.obtain(type);
+ event.setImportantForAccessibility(true);
+ event.setSourceNodeId(AccessibilityNodeInfo.ROOT_NODE_ID);
+ event.setWindowId(
+ AccessibilityWindowInfo.PICTURE_IN_PICTURE_ACTION_REPLACER_WINDOW_ID);
+ mAccessibilityManager.sendAccessibilityEvent(event);
+ }
+
/**
* Updates the appearance of the menu and scrim on top of the PiP while dismissing.
*/
@@ -523,6 +524,10 @@ public class PipTouchHandler {
* Sets the menu visibility.
*/
private void setMenuState(int menuState, boolean resize) {
+ if (mMenuState == menuState && !resize) {
+ return;
+ }
+
if (menuState == MENU_STATE_FULL && mMenuState != MENU_STATE_FULL) {
// Save the current snap fraction and if we do not drag or move the PiP, then
// we store back to this snap fraction. Otherwise, we'll reset the snap
@@ -571,6 +576,9 @@ public class PipTouchHandler {
}
mMenuState = menuState;
updateMovementBounds(menuState);
+ // If pip menu has dismissed, we should register the A11y ActionReplacingConnection for pip
+ // as well, or it can't handle a11y focus and pip menu can't perform any action.
+ onRegistrationChanged(menuState == MENU_STATE_NONE);
if (menuState != MENU_STATE_CLOSE) {
MetricsLoggerWrapper.logPictureInPictureMenuVisible(mContext, menuState == MENU_STATE_FULL);
}
diff --git a/packages/SystemUI/src/com/android/systemui/power/PowerUI.java b/packages/SystemUI/src/com/android/systemui/power/PowerUI.java
index 75dc39722bcf..f60d9db7ac9c 100644
--- a/packages/SystemUI/src/com/android/systemui/power/PowerUI.java
+++ b/packages/SystemUI/src/com/android/systemui/power/PowerUI.java
@@ -45,6 +45,7 @@ import com.android.settingslib.utils.ThreadUtils;
import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.SystemUI;
+import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.statusbar.phone.StatusBar;
import java.io.FileDescriptor;
@@ -53,6 +54,12 @@ import java.time.Duration;
import java.util.Arrays;
import java.util.concurrent.Future;
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+import dagger.Lazy;
+
+@Singleton
public class PowerUI extends SystemUI {
static final String TAG = "PowerUI";
@@ -97,6 +104,16 @@ public class PowerUI extends SystemUI {
private IThermalEventListener mSkinThermalEventListener;
private IThermalEventListener mUsbThermalEventListener;
+ private final BroadcastDispatcher mBroadcastDispatcher;
+ private final Lazy<StatusBar> mStatusBarLazy;
+
+ @Inject
+ public PowerUI(Context context, BroadcastDispatcher broadcastDispatcher,
+ Lazy<StatusBar> statusBarLazy) {
+ super(context);
+ mBroadcastDispatcher = broadcastDispatcher;
+ mStatusBarLazy = statusBarLazy;
+ }
public void start() {
mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
@@ -211,7 +228,7 @@ public class PowerUI extends SystemUI {
filter.addAction(Intent.ACTION_SCREEN_OFF);
filter.addAction(Intent.ACTION_SCREEN_ON);
filter.addAction(Intent.ACTION_USER_SWITCHED);
- mContext.registerReceiver(this, filter, null, mHandler);
+ mBroadcastDispatcher.registerReceiver(this, filter, mHandler);
}
@Override
@@ -653,8 +670,7 @@ public class PowerUI extends SystemUI {
int status = temp.getStatus();
if (status >= Temperature.THROTTLING_EMERGENCY) {
- StatusBar statusBar = getComponent(StatusBar.class);
- if (statusBar != null && !statusBar.isDeviceInVrMode()) {
+ if (!mStatusBarLazy.get().isDeviceInVrMode()) {
mWarnings.showHighTemperatureWarning();
Slog.d(TAG, "SkinThermalEventListener: notifyThrottling was called "
+ ", current skin status = " + status
diff --git a/packages/SystemUI/src/com/android/systemui/privacy/PrivacyItemController.kt b/packages/SystemUI/src/com/android/systemui/privacy/PrivacyItemController.kt
index 631b8b7a14a0..22fb4c0dbdb5 100644
--- a/packages/SystemUI/src/com/android/systemui/privacy/PrivacyItemController.kt
+++ b/packages/SystemUI/src/com/android/systemui/privacy/PrivacyItemController.kt
@@ -22,25 +22,20 @@ import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
-import android.os.Handler
-import android.os.Looper
-import android.os.Message
-import android.os.UserHandle
-import android.os.UserManager
+import android.os.*
import android.provider.DeviceConfig
import com.android.internal.annotations.VisibleForTesting
import com.android.internal.config.sysui.SystemUiDeviceConfigFlags
-import com.android.systemui.Dependency.BG_HANDLER_NAME
-import com.android.systemui.Dependency.MAIN_HANDLER_NAME
+import com.android.systemui.Dumpable
import com.android.systemui.R
import com.android.systemui.appops.AppOpItem
import com.android.systemui.appops.AppOpsController
-import com.android.systemui.Dumpable
+import com.android.systemui.dagger.qualifiers.BgHandler
+import com.android.systemui.dagger.qualifiers.MainHandler
import java.io.FileDescriptor
import java.io.PrintWriter
import java.lang.ref.WeakReference
import javax.inject.Inject
-import javax.inject.Named
import javax.inject.Singleton
fun isPermissionsHubEnabled() = DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_PRIVACY,
@@ -50,8 +45,8 @@ fun isPermissionsHubEnabled() = DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_P
class PrivacyItemController @Inject constructor(
val context: Context,
private val appOpsController: AppOpsController,
- @Named(MAIN_HANDLER_NAME) private val uiHandler: Handler,
- @Named(BG_HANDLER_NAME) private val bgHandler: Handler
+ @MainHandler private val uiHandler: Handler,
+ @BgHandler private val bgHandler: Handler
) : Dumpable {
@VisibleForTesting
diff --git a/packages/SystemUI/src/com/android/systemui/qs/DoubleLineTileLayout.kt b/packages/SystemUI/src/com/android/systemui/qs/DoubleLineTileLayout.kt
new file mode 100644
index 000000000000..f710f7fc47e2
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/DoubleLineTileLayout.kt
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs
+
+import android.content.Context
+import android.content.res.Configuration
+import android.view.View
+import android.view.ViewGroup
+import com.android.systemui.R
+import com.android.systemui.qs.TileLayout.exactly
+
+class DoubleLineTileLayout(context: Context) : ViewGroup(context), QSPanel.QSTileLayout {
+
+ protected val mRecords = ArrayList<QSPanel.TileRecord>()
+ private var _listening = false
+ private var smallTileSize = 0
+ private val twoLineHeight
+ get() = smallTileSize * 2 + cellMarginVertical
+ private var cellMarginHorizontal = 0
+ private var cellMarginVertical = 0
+
+ init {
+ isFocusableInTouchMode = true
+ clipChildren = false
+ clipToPadding = false
+
+ updateResources()
+ }
+
+ override fun addTile(tile: QSPanel.TileRecord) {
+ mRecords.add(tile)
+ tile.tile.setListening(this, _listening)
+ addTileView(tile)
+ }
+
+ protected fun addTileView(tile: QSPanel.TileRecord) {
+ addView(tile.tileView)
+ }
+
+ override fun removeTile(tile: QSPanel.TileRecord) {
+ mRecords.remove(tile)
+ tile.tile.setListening(this, false)
+ removeView(tile.tileView)
+ }
+
+ override fun removeAllViews() {
+ mRecords.forEach { it.tile.setListening(this, false) }
+ mRecords.clear()
+ super.removeAllViews()
+ }
+
+ override fun getOffsetTop(tile: QSPanel.TileRecord?) = top
+
+ override fun updateResources(): Boolean {
+ with(mContext.resources) {
+ smallTileSize = getDimensionPixelSize(R.dimen.qs_quick_tile_size)
+ cellMarginHorizontal = getDimensionPixelSize(R.dimen.qs_tile_margin_horizontal)
+ cellMarginVertical = getDimensionPixelSize(R.dimen.new_qs_vertical_margin)
+ }
+ requestLayout()
+ return false
+ }
+
+ override fun setListening(listening: Boolean) {
+ if (_listening == listening) return
+ _listening = listening
+ for (record in mRecords) {
+ record.tile.setListening(this, listening)
+ }
+ }
+
+ override fun getNumVisibleTiles() = mRecords.size
+
+ override fun onConfigurationChanged(newConfig: Configuration) {
+ super.onConfigurationChanged(newConfig)
+ updateResources()
+ }
+
+ override fun onFinishInflate() {
+ updateResources()
+ }
+
+ override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
+ var previousView: View = this
+ var tiles = 0
+
+ mRecords.forEach {
+ val tileView = it.tileView
+ if (tileView.visibility != View.GONE) {
+ tileView.updateAccessibilityOrder(previousView)
+ previousView = tileView
+ tiles++
+ tileView.measure(exactly(smallTileSize), exactly(smallTileSize))
+ }
+ }
+
+ val height = twoLineHeight
+ val columns = tiles / 2
+ val width = paddingStart + paddingEnd +
+ columns * smallTileSize +
+ (columns - 1) * cellMarginHorizontal
+ setMeasuredDimension(width, height)
+ }
+
+ override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) {
+ val tiles = mRecords.filter { it.tileView.visibility != View.GONE }
+ tiles.forEachIndexed {
+ index, tile ->
+ val column = index % (tiles.size / 2)
+ val left = getLeftForColumn(column)
+ val top = if (index < tiles.size / 2) 0 else getTopBottomRow()
+ tile.tileView.layout(left, top, left + smallTileSize, top + smallTileSize)
+ }
+ }
+
+ private fun getLeftForColumn(column: Int) = column * (smallTileSize + cellMarginHorizontal)
+
+ private fun getTopBottomRow() = smallTileSize + cellMarginVertical
+} \ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java b/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
index 9221b6852112..a267bbb92ee7 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
@@ -14,6 +14,7 @@
package com.android.systemui.qs;
+import android.provider.Settings;
import android.util.Log;
import android.view.View;
import android.view.View.OnAttachStateChangeListener;
@@ -267,6 +268,17 @@ public class QSAnimator implements Callback, PageListener, Listener, OnLayoutCha
mAllViews.add(tileView);
count++;
}
+
+
+ int flag = Settings.System.getInt(mQsPanel.getContext().getContentResolver(),
+ "qs_media_player", 0);
+ if (flag == 1) {
+ View qsMediaView = mQsPanel.getMediaPanel();
+ View qqsMediaView = mQuickQsPanel.getMediaPlayer().getView();
+ translationXBuilder.addFloat(qsMediaView, "alpha", 0, 1);
+ translationXBuilder.addFloat(qqsMediaView, "alpha", 1, 0);
+ }
+
if (mAllowFancy) {
// Make brightness appear static position and alpha in through second half.
View brightness = mQsPanel.getBrightnessView();
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSCarrierGroup.java b/packages/SystemUI/src/com/android/systemui/qs/QSCarrierGroup.java
index 27a517c52458..8fe687ba297c 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSCarrierGroup.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSCarrierGroup.java
@@ -17,12 +17,15 @@
package com.android.systemui.qs;
import static com.android.systemui.Dependency.BG_HANDLER;
-import static com.android.systemui.Dependency.BG_HANDLER_NAME;
+import static com.android.systemui.Dependency.MAIN_LOOPER;
import static com.android.systemui.util.InjectionInflationController.VIEW_CONTEXT;
+import android.annotation.MainThread;
import android.content.Context;
import android.content.Intent;
import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
import android.provider.Settings;
import android.telephony.SubscriptionManager;
import android.util.AttributeSet;
@@ -36,9 +39,13 @@ import androidx.annotation.VisibleForTesting;
import com.android.keyguard.CarrierTextController;
import com.android.systemui.Dependency;
import com.android.systemui.R;
+import com.android.systemui.dagger.qualifiers.BgHandler;
+import com.android.systemui.dagger.qualifiers.MainLooper;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.statusbar.policy.NetworkController;
+import java.util.function.Consumer;
+
import javax.inject.Inject;
import javax.inject.Named;
@@ -46,7 +53,6 @@ import javax.inject.Named;
* Displays Carrier name and network status in QS
*/
public class QSCarrierGroup extends LinearLayout implements
- CarrierTextController.CarrierTextCallback,
NetworkController.SignalCallback, View.OnClickListener {
private static final String TAG = "QSCarrierGroup";
@@ -56,12 +62,14 @@ public class QSCarrierGroup extends LinearLayout implements
private static final int SIM_SLOTS = 3;
private final NetworkController mNetworkController;
private final Handler mBgHandler;
+ private final H mMainHandler;
private View[] mCarrierDividers = new View[SIM_SLOTS - 1];
private QSCarrier[] mCarrierGroups = new QSCarrier[SIM_SLOTS];
private TextView mNoSimTextView;
private final CellSignalState[] mInfos = new CellSignalState[SIM_SLOTS];
private CarrierTextController mCarrierTextController;
+ private CarrierTextController.CarrierTextCallback mCallback;
private ActivityStarter mActivityStarter;
private boolean mListening;
@@ -69,11 +77,19 @@ public class QSCarrierGroup extends LinearLayout implements
@Inject
public QSCarrierGroup(@Named(VIEW_CONTEXT) Context context, AttributeSet attrs,
NetworkController networkController, ActivityStarter activityStarter,
- @Named(BG_HANDLER_NAME) Handler handler) {
+ @BgHandler Handler handler,
+ @MainLooper Looper looper) {
super(context, attrs);
mNetworkController = networkController;
mActivityStarter = activityStarter;
mBgHandler = handler;
+ mMainHandler = new H(looper, this::handleUpdateCarrierInfo, this::handleUpdateState);
+ mCallback = new Callback(mMainHandler);
+ }
+
+ @VisibleForTesting
+ protected CarrierTextController.CarrierTextCallback getCallback() {
+ return mCallback;
}
@VisibleForTesting
@@ -81,7 +97,8 @@ public class QSCarrierGroup extends LinearLayout implements
this(context, attrs,
Dependency.get(NetworkController.class),
Dependency.get(ActivityStarter.class),
- Dependency.get(BG_HANDLER));
+ Dependency.get(BG_HANDLER),
+ Dependency.get(MAIN_LOOPER));
}
@Override
@@ -136,14 +153,20 @@ public class QSCarrierGroup extends LinearLayout implements
if (mNetworkController.hasVoiceCallingFeature()) {
mNetworkController.addCallback(this);
}
- mCarrierTextController.setListening(this);
+ mCarrierTextController.setListening(mCallback);
} else {
mNetworkController.removeCallback(this);
mCarrierTextController.setListening(null);
}
}
+ @MainThread
private void handleUpdateState() {
+ if (!mMainHandler.getLooper().isCurrentThread()) {
+ mMainHandler.obtainMessage(H.MSG_UPDATE_STATE).sendToTarget();
+ return;
+ }
+
for (int i = 0; i < SIM_SLOTS; i++) {
mCarrierGroups[i].updateState(mInfos[i]);
}
@@ -163,8 +186,13 @@ public class QSCarrierGroup extends LinearLayout implements
return SubscriptionManager.getSlotIndex(subscriptionId);
}
- @Override
- public void updateCarrierInfo(CarrierTextController.CarrierTextCallbackInfo info) {
+ @MainThread
+ private void handleUpdateCarrierInfo(CarrierTextController.CarrierTextCallbackInfo info) {
+ if (!mMainHandler.getLooper().isCurrentThread()) {
+ mMainHandler.obtainMessage(H.MSG_UPDATE_CARRIER_INFO, info).sendToTarget();
+ return;
+ }
+
mNoSimTextView.setVisibility(View.GONE);
if (!info.airplaneMode && info.anySimReady) {
boolean[] slotSeen = new boolean[SIM_SLOTS];
@@ -207,7 +235,7 @@ public class QSCarrierGroup extends LinearLayout implements
mNoSimTextView.setText(info.carrierText);
mNoSimTextView.setVisibility(View.VISIBLE);
}
- handleUpdateState();
+ handleUpdateState(); // handleUpdateCarrierInfo is always called from main thread.
}
@Override
@@ -231,7 +259,7 @@ public class QSCarrierGroup extends LinearLayout implements
mInfos[slotIndex].contentDescription = statusIcon.contentDescription;
mInfos[slotIndex].typeContentDescription = typeContentDescription;
mInfos[slotIndex].roaming = roaming;
- handleUpdateState();
+ mMainHandler.obtainMessage(H.MSG_UPDATE_STATE).sendToTarget();
}
@Override
@@ -241,7 +269,7 @@ public class QSCarrierGroup extends LinearLayout implements
mInfos[i].visible = false;
}
}
- handleUpdateState();
+ mMainHandler.obtainMessage(H.MSG_UPDATE_STATE).sendToTarget();
}
static final class CellSignalState {
@@ -251,4 +279,47 @@ public class QSCarrierGroup extends LinearLayout implements
String typeContentDescription;
boolean roaming;
}
+
+ private static class H extends Handler {
+ private Consumer<CarrierTextController.CarrierTextCallbackInfo> mUpdateCarrierInfo;
+ private Runnable mUpdateState;
+ static final int MSG_UPDATE_CARRIER_INFO = 0;
+ static final int MSG_UPDATE_STATE = 1;
+
+ H(Looper looper,
+ Consumer<CarrierTextController.CarrierTextCallbackInfo> updateCarrierInfo,
+ Runnable updateState) {
+ super(looper);
+ mUpdateCarrierInfo = updateCarrierInfo;
+ mUpdateState = updateState;
+ }
+
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case MSG_UPDATE_CARRIER_INFO:
+ mUpdateCarrierInfo.accept(
+ (CarrierTextController.CarrierTextCallbackInfo) msg.obj);
+ break;
+ case MSG_UPDATE_STATE:
+ mUpdateState.run();
+ break;
+ default:
+ super.handleMessage(msg);
+ }
+ }
+ }
+
+ private static class Callback implements CarrierTextController.CarrierTextCallback {
+ private H mMainHandler;
+
+ Callback(H handler) {
+ mMainHandler = handler;
+ }
+
+ @Override
+ public void updateCarrierInfo(CarrierTextController.CarrierTextCallbackInfo info) {
+ mMainHandler.obtainMessage(H.MSG_UPDATE_CARRIER_INFO, info).sendToTarget();
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSMediaPlayer.java b/packages/SystemUI/src/com/android/systemui/qs/QSMediaPlayer.java
new file mode 100644
index 000000000000..af418f6308a0
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSMediaPlayer.java
@@ -0,0 +1,301 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs;
+
+import android.app.Notification;
+import android.app.PendingIntent;
+import android.content.Context;
+import android.content.Intent;
+import android.content.res.ColorStateList;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Matrix;
+import android.graphics.Paint;
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.GradientDrawable;
+import android.graphics.drawable.Icon;
+import android.graphics.drawable.RippleDrawable;
+import android.media.MediaMetadata;
+import android.media.session.MediaController;
+import android.media.session.MediaSession;
+import android.media.session.PlaybackState;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ImageButton;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.RemoteViews;
+import android.widget.TextView;
+
+import androidx.core.graphics.drawable.RoundedBitmapDrawable;
+import androidx.core.graphics.drawable.RoundedBitmapDrawableFactory;
+
+import com.android.settingslib.media.MediaOutputSliceConstants;
+import com.android.systemui.Dependency;
+import com.android.systemui.R;
+import com.android.systemui.plugins.ActivityStarter;
+import com.android.systemui.statusbar.MediaTransferManager;
+
+/**
+ * Single media player for carousel in QSPanel
+ */
+public class QSMediaPlayer {
+
+ private static final String TAG = "QSMediaPlayer";
+
+ private Context mContext;
+ private LinearLayout mMediaNotifView;
+ private MediaSession.Token mToken;
+ private MediaController mController;
+ private int mWidth;
+ private int mHeight;
+
+ /**
+ *
+ * @param context
+ * @param parent
+ * @param width
+ * @param height
+ */
+ public QSMediaPlayer(Context context, ViewGroup parent, int width, int height) {
+ mContext = context;
+ LayoutInflater inflater = LayoutInflater.from(mContext);
+ mMediaNotifView = (LinearLayout) inflater.inflate(R.layout.qs_media_panel, parent, false);
+
+ mWidth = width;
+ mHeight = height;
+ }
+
+ public View getView() {
+ return mMediaNotifView;
+ }
+
+ /**
+ *
+ * @param token token for this media session
+ * @param icon app notification icon
+ * @param iconColor foreground color (for text, icons)
+ * @param bgColor background color
+ * @param actionsContainer a LinearLayout containing the media action buttons
+ * @param notif
+ */
+ public void setMediaSession(MediaSession.Token token, Icon icon, int iconColor, int bgColor,
+ View actionsContainer, Notification notif) {
+ Log.d(TAG, "got media session: " + token);
+ mToken = token;
+ mController = new MediaController(mContext, token);
+ MediaMetadata mMediaMetadata = mController.getMetadata();
+ Notification.Builder builder = Notification.Builder.recoverBuilder(mContext, notif);
+
+ // Album art
+ addAlbumArtBackground(mMediaMetadata, bgColor, mWidth, mHeight);
+
+ // Reuse notification header instead of reimplementing everything
+ RemoteViews headerRemoteView = builder.makeNotificationHeader();
+ LinearLayout headerView = mMediaNotifView.findViewById(R.id.header);
+ View result = headerRemoteView.apply(mContext, headerView);
+ result.setPadding(0, 0, 0, 0);
+ LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
+ ViewGroup.LayoutParams.WRAP_CONTENT, 75);
+ result.setLayoutParams(lp);
+ headerView.removeAllViews();
+ headerView.addView(result);
+
+ View seamless = headerView.findViewById(com.android.internal.R.id.media_seamless);
+ seamless.setVisibility(View.VISIBLE);
+
+ // App icon
+ ImageView appIcon = headerView.findViewById(com.android.internal.R.id.icon);
+ Drawable iconDrawable = icon.loadDrawable(mContext);
+ iconDrawable.setTint(iconColor);
+ appIcon.setImageDrawable(iconDrawable);
+
+ // App title
+ TextView appName = headerView.findViewById(com.android.internal.R.id.app_name_text);
+ String appNameString = builder.loadHeaderAppName();
+ appName.setText(appNameString);
+ appName.setTextColor(iconColor);
+
+ // Action
+ mMediaNotifView.setOnClickListener(v -> {
+ try {
+ notif.contentIntent.send();
+ // Also close shade
+ mContext.sendBroadcast(new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS));
+ } catch (PendingIntent.CanceledException e) {
+ Log.e(TAG, "Pending intent was canceled");
+ e.printStackTrace();
+ }
+ });
+
+ // Separator
+ TextView separator = headerView.findViewById(com.android.internal.R.id.header_text_divider);
+ separator.setTextColor(iconColor);
+
+ // Album name
+ TextView albumName = headerView.findViewById(com.android.internal.R.id.header_text);
+ String albumString = mMediaMetadata.getString(MediaMetadata.METADATA_KEY_ALBUM);
+ if (!albumString.isEmpty()) {
+ albumName.setText(albumString);
+ albumName.setTextColor(iconColor);
+ albumName.setVisibility(View.VISIBLE);
+ separator.setVisibility(View.VISIBLE);
+ } else {
+ albumName.setVisibility(View.GONE);
+ separator.setVisibility(View.GONE);
+ }
+
+ // Transfer chip
+ MediaTransferManager mediaTransferManager = new MediaTransferManager(mContext);
+ View transferBackgroundView = headerView.findViewById(
+ com.android.internal.R.id.media_seamless);
+ LinearLayout viewLayout = (LinearLayout) transferBackgroundView;
+ RippleDrawable bkgDrawable = (RippleDrawable) viewLayout.getBackground();
+ GradientDrawable rect = (GradientDrawable) bkgDrawable.getDrawable(0);
+ rect.setStroke(2, iconColor);
+ rect.setColor(bgColor);
+ ImageView transferIcon = headerView.findViewById(
+ com.android.internal.R.id.media_seamless_image);
+ transferIcon.setBackgroundColor(bgColor);
+ transferIcon.setImageTintList(ColorStateList.valueOf(iconColor));
+ TextView transferText = headerView.findViewById(
+ com.android.internal.R.id.media_seamless_text);
+ transferText.setTextColor(iconColor);
+
+ ActivityStarter mActivityStarter = Dependency.get(ActivityStarter.class);
+ transferBackgroundView.setOnClickListener(v -> {
+ final Intent intent = new Intent()
+ .setAction(MediaOutputSliceConstants.ACTION_MEDIA_OUTPUT);
+ mActivityStarter.startActivity(intent, false, true /* dismissShade */,
+ Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
+ });
+
+ // Artist name
+ TextView artistText = mMediaNotifView.findViewById(R.id.header_title);
+ String artistName = mMediaMetadata.getString(MediaMetadata.METADATA_KEY_ARTIST);
+ artistText.setText(artistName);
+ artistText.setTextColor(iconColor);
+
+ // Song name
+ TextView titleText = mMediaNotifView.findViewById(R.id.header_text);
+ String songName = mMediaMetadata.getString(MediaMetadata.METADATA_KEY_TITLE);
+ titleText.setText(songName);
+ titleText.setTextColor(iconColor);
+
+ // Media controls
+ LinearLayout parentActionsLayout = (LinearLayout) actionsContainer;
+ final int[] actionIds = {
+ R.id.action0,
+ R.id.action1,
+ R.id.action2,
+ R.id.action3,
+ R.id.action4
+ };
+ final int[] notifActionIds = {
+ com.android.internal.R.id.action0,
+ com.android.internal.R.id.action1,
+ com.android.internal.R.id.action2,
+ com.android.internal.R.id.action3,
+ com.android.internal.R.id.action4
+ };
+ for (int i = 0; i < parentActionsLayout.getChildCount() && i < actionIds.length; i++) {
+ ImageButton thisBtn = mMediaNotifView.findViewById(actionIds[i]);
+ ImageButton thatBtn = parentActionsLayout.findViewById(notifActionIds[i]);
+ if (thatBtn == null || thatBtn.getDrawable() == null) {
+ thisBtn.setVisibility(View.GONE);
+ continue;
+ }
+
+ Drawable thatIcon = thatBtn.getDrawable();
+ thisBtn.setImageDrawable(thatIcon.mutate());
+ thisBtn.setVisibility(View.VISIBLE);
+ thisBtn.setOnClickListener(v -> {
+ Log.d(TAG, "clicking on other button");
+ thatBtn.performClick();
+ });
+ }
+ }
+
+ public MediaSession.Token getMediaSessionToken() {
+ return mToken;
+ }
+
+ public String getMediaPlayerPackage() {
+ return mController.getPackageName();
+ }
+
+ /**
+ * Check whether the media controlled by this player is currently playing
+ * @return whether it is playing, or false if no controller information
+ */
+ public boolean isPlaying() {
+ if (mController == null) {
+ return false;
+ }
+
+ PlaybackState state = mController.getPlaybackState();
+ if (state == null) {
+ return false;
+ }
+
+ return (state.getState() == PlaybackState.STATE_PLAYING);
+ }
+
+ private void addAlbumArtBackground(MediaMetadata metadata, int bgColor, int width, int height) {
+ Bitmap albumArt = metadata.getBitmap(MediaMetadata.METADATA_KEY_ALBUM_ART);
+ if (albumArt != null) {
+
+ Bitmap original = albumArt.copy(Bitmap.Config.ARGB_8888, true);
+ Bitmap scaled = scaleBitmap(original, width, height);
+ Canvas canvas = new Canvas(scaled);
+
+ // Add translucent layer over album art to improve contrast
+ Paint p = new Paint();
+ p.setStyle(Paint.Style.FILL);
+ p.setColor(bgColor);
+ p.setAlpha(200);
+ canvas.drawRect(0, 0, canvas.getWidth(), canvas.getHeight(), p);
+
+ RoundedBitmapDrawable roundedDrawable = RoundedBitmapDrawableFactory.create(
+ mContext.getResources(), scaled);
+ roundedDrawable.setCornerRadius(20);
+
+ mMediaNotifView.setBackground(roundedDrawable);
+ } else {
+ Log.e(TAG, "No album art available");
+ }
+ }
+
+ private Bitmap scaleBitmap(Bitmap original, int width, int height) {
+ Bitmap cropped = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
+ Canvas canvas = new Canvas(cropped);
+
+ float scale = (float) cropped.getWidth() / (float) original.getWidth();
+ float dy = (cropped.getHeight() - original.getHeight() * scale) / 2.0f;
+ Matrix transformation = new Matrix();
+ transformation.postTranslate(0, dy);
+ transformation.preScale(scale, scale);
+
+ Paint paint = new Paint();
+ paint.setFilterBitmap(true);
+ canvas.drawBitmap(original, transformation, paint);
+
+ return cropped;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
index 00b57da846fe..4c813482f58e 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
@@ -24,14 +24,22 @@ import android.content.ComponentName;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
+import android.graphics.drawable.Icon;
+import android.media.session.MediaSession;
import android.metrics.LogMaker;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
+import android.provider.Settings;
+import android.service.notification.StatusBarNotification;
import android.service.quicksettings.Tile;
import android.util.AttributeSet;
+import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
+import android.view.ViewGroup;
+import android.widget.FrameLayout;
+import android.widget.HorizontalScrollView;
import android.widget.LinearLayout;
import com.android.internal.logging.MetricsLogger;
@@ -49,6 +57,8 @@ import com.android.systemui.qs.customize.QSCustomizer;
import com.android.systemui.qs.external.CustomTile;
import com.android.systemui.settings.BrightnessController;
import com.android.systemui.settings.ToggleSliderView;
+import com.android.systemui.shared.plugins.PluginManager;
+import com.android.systemui.statusbar.phone.NPVPluginManager;
import com.android.systemui.statusbar.policy.BrightnessMirrorController;
import com.android.systemui.statusbar.policy.BrightnessMirrorController.BrightnessMirrorListener;
import com.android.systemui.tuner.TunerService;
@@ -78,6 +88,9 @@ public class QSPanel extends LinearLayout implements Tunable, Callback, Brightne
private final MetricsLogger mMetricsLogger = Dependency.get(MetricsLogger.class);
private final QSTileRevealController mQsTileRevealController;
+ private final LinearLayout mMediaCarousel;
+ private final ArrayList<QSMediaPlayer> mMediaPlayers = new ArrayList<>();
+
protected boolean mExpanded;
protected boolean mListening;
@@ -98,6 +111,10 @@ public class QSPanel extends LinearLayout implements Tunable, Callback, Brightne
private BrightnessMirrorController mBrightnessMirrorController;
private View mDivider;
+ private FrameLayout mPluginFrame;
+ private final PluginManager mPluginManager;
+ private NPVPluginManager mNPVPluginManager;
+
public QSPanel(Context context) {
this(context, null);
}
@@ -106,9 +123,13 @@ public class QSPanel extends LinearLayout implements Tunable, Callback, Brightne
this(context, attrs, null);
}
+ public QSPanel(Context context, AttributeSet attrs, DumpController dumpController) {
+ this(context, attrs, dumpController, null);
+ }
+
@Inject
public QSPanel(@Named(VIEW_CONTEXT) Context context, AttributeSet attrs,
- DumpController dumpController) {
+ DumpController dumpController, PluginManager pluginManager) {
super(context, attrs);
mContext = context;
@@ -128,6 +149,27 @@ public class QSPanel extends LinearLayout implements Tunable, Callback, Brightne
addDivider();
+ // Add media carousel
+ int flag = Settings.System.getInt(context.getContentResolver(), "qs_media_player", 0);
+ if (flag == 1) {
+ HorizontalScrollView mediaScrollView = new HorizontalScrollView(mContext);
+ mediaScrollView.setHorizontalScrollBarEnabled(false);
+ int playerHeight = (int) getResources().getDimension(R.dimen.qs_media_height);
+ int padding = (int) getResources().getDimension(R.dimen.qs_media_padding);
+ LayoutParams lpView = new LayoutParams(LayoutParams.MATCH_PARENT, playerHeight);
+ lpView.setMarginStart(padding);
+ lpView.setMarginEnd(padding);
+ addView(mediaScrollView, lpView);
+
+ LayoutParams lpCarousel = new LayoutParams(LayoutParams.MATCH_PARENT,
+ LayoutParams.WRAP_CONTENT);
+ mMediaCarousel = new LinearLayout(mContext);
+ mMediaCarousel.setOrientation(LinearLayout.HORIZONTAL);
+ mediaScrollView.addView(mMediaCarousel, lpCarousel);
+ } else {
+ mMediaCarousel = null;
+ }
+
mFooter = new QSSecurityFooter(this, context);
addView(mFooter.getView());
@@ -136,6 +178,82 @@ public class QSPanel extends LinearLayout implements Tunable, Callback, Brightne
mDumpController = dumpController;
updateResources();
+
+ mPluginManager = pluginManager;
+ if (mPluginManager != null && Settings.System.getInt(
+ mContext.getContentResolver(), "npv_plugin_flag", 0) == 2) {
+ mPluginFrame = (FrameLayout) LayoutInflater.from(mContext).inflate(
+ R.layout.status_bar_expanded_plugin_frame, this, false);
+ addView(mPluginFrame);
+ mNPVPluginManager = new NPVPluginManager(mPluginFrame, mPluginManager);
+ }
+
+ }
+
+ /**
+ * Add or update a player for the associated media session
+ * @param token
+ * @param icon
+ * @param iconColor
+ * @param bgColor
+ * @param actionsContainer
+ * @param notif
+ */
+ public void addMediaSession(MediaSession.Token token, Icon icon, int iconColor, int bgColor,
+ View actionsContainer, StatusBarNotification notif) {
+ int flag = Settings.System.getInt(mContext.getContentResolver(), "qs_media_player", 0);
+ if (flag != 1) {
+ // Shouldn't happen, but just in case
+ Log.e(TAG, "Tried to add media session without player!");
+ return;
+ }
+ QSMediaPlayer player = null;
+ String packageName = notif.getPackageName();
+ for (QSMediaPlayer p : mMediaPlayers) {
+ if (p.getMediaSessionToken().equals(token)) {
+ Log.d(TAG, "a player for this session already exists");
+ player = p;
+ break;
+ }
+
+ if (packageName.equals(p.getMediaPlayerPackage())) {
+ Log.d(TAG, "found an old session for this app");
+ player = p;
+ break;
+ }
+ }
+
+ int playerHeight = (int) getResources().getDimension(R.dimen.qs_media_height);
+ int playerWidth = (int) getResources().getDimension(R.dimen.qs_media_width);
+ int padding = (int) getResources().getDimension(R.dimen.qs_media_padding);
+ LayoutParams lp = new LayoutParams(playerWidth, ViewGroup.LayoutParams.MATCH_PARENT);
+ lp.setMarginStart(padding);
+ lp.setMarginEnd(padding);
+
+ if (player == null) {
+ Log.d(TAG, "creating new player");
+
+ player = new QSMediaPlayer(mContext, this, playerWidth, playerHeight);
+
+ if (player.isPlaying()) {
+ mMediaCarousel.addView(player.getView(), 0, lp); // add in front
+ } else {
+ mMediaCarousel.addView(player.getView(), lp); // add at end
+ }
+ } else if (player.isPlaying()) {
+ // move it to the front
+ mMediaCarousel.removeView(player.getView());
+ mMediaCarousel.addView(player.getView(), 0, lp);
+ }
+
+ Log.d(TAG, "setting player session");
+ player.setMediaSession(token, icon, iconColor, bgColor, actionsContainer,
+ notif.getNotification());
+ mMediaPlayers.add(player);
+ }
+
+ protected View getMediaPanel() {
+ return mMediaCarousel;
}
protected void addDivider() {
@@ -380,6 +498,7 @@ public class QSPanel extends LinearLayout implements Tunable, Callback, Brightne
if (mListening) {
refreshAllTiles();
}
+ if (mNPVPluginManager != null) mNPVPluginManager.setListening(listening);
}
public void setListening(boolean listening, boolean expanded) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java b/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java
index 1e763cf79240..b395c3c336d3 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java
@@ -30,11 +30,12 @@ import android.service.quicksettings.Tile;
import android.text.TextUtils;
import android.util.Log;
-import com.android.systemui.Dependency;
import com.android.systemui.DumpController;
import com.android.systemui.Dumpable;
import com.android.systemui.R;
import com.android.systemui.SysUiServiceProvider;
+import com.android.systemui.dagger.qualifiers.BgLooper;
+import com.android.systemui.dagger.qualifiers.MainHandler;
import com.android.systemui.plugins.PluginListener;
import com.android.systemui.plugins.qs.QSFactory;
import com.android.systemui.plugins.qs.QSTile;
@@ -61,7 +62,6 @@ import java.util.List;
import java.util.function.Predicate;
import javax.inject.Inject;
-import javax.inject.Named;
import javax.inject.Provider;
import javax.inject.Singleton;
@@ -94,8 +94,8 @@ public class QSTileHost implements QSHost, Tunable, PluginListener<QSFactory>, D
public QSTileHost(Context context,
StatusBarIconController iconController,
QSFactoryImpl defaultFactory,
- @Named(Dependency.MAIN_HANDLER_NAME) Handler mainHandler,
- @Named(Dependency.BG_LOOPER_NAME) Looper bgLooper,
+ @MainHandler Handler mainHandler,
+ @BgLooper Looper bgLooper,
PluginManager pluginManager,
TunerService tunerService,
Provider<AutoTileManager> autoTiles,
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickQSMediaPlayer.java b/packages/SystemUI/src/com/android/systemui/qs/QuickQSMediaPlayer.java
new file mode 100644
index 000000000000..ae66cd576765
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickQSMediaPlayer.java
@@ -0,0 +1,203 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Matrix;
+import android.graphics.Paint;
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.Icon;
+import android.media.MediaMetadata;
+import android.media.session.MediaController;
+import android.media.session.MediaSession;
+import android.media.session.PlaybackState;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ImageButton;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import androidx.core.graphics.drawable.RoundedBitmapDrawable;
+import androidx.core.graphics.drawable.RoundedBitmapDrawableFactory;
+
+import com.android.systemui.R;
+
+/**
+ * QQS mini media player
+ */
+public class QuickQSMediaPlayer {
+
+ private static final String TAG = "QQSMediaPlayer";
+
+ private Context mContext;
+ private LinearLayout mMediaNotifView;
+ private MediaSession.Token mToken;
+ private MediaController mController;
+
+ /**
+ *
+ * @param context
+ * @param parent
+ */
+ public QuickQSMediaPlayer(Context context, ViewGroup parent) {
+ mContext = context;
+ LayoutInflater inflater = LayoutInflater.from(mContext);
+ mMediaNotifView = (LinearLayout) inflater.inflate(R.layout.qqs_media_panel, parent, false);
+ }
+
+ public View getView() {
+ return mMediaNotifView;
+ }
+
+ /**
+ *
+ * @param token token for this media session
+ * @param icon app notification icon
+ * @param iconColor foreground color (for text, icons)
+ * @param bgColor background color
+ * @param actionsContainer a LinearLayout containing the media action buttons
+ */
+ public void setMediaSession(MediaSession.Token token, Icon icon, int iconColor, int bgColor,
+ View actionsContainer) {
+ Log.d(TAG, "Setting media session: " + token);
+ mToken = token;
+ mController = new MediaController(mContext, token);
+ MediaMetadata mMediaMetadata = mController.getMetadata();
+
+ // Album art
+ addAlbumArtBackground(mMediaMetadata, bgColor);
+
+ // App icon
+ ImageView appIcon = mMediaNotifView.findViewById(R.id.icon);
+ Drawable iconDrawable = icon.loadDrawable(mContext);
+ iconDrawable.setTint(iconColor);
+ appIcon.setImageDrawable(iconDrawable);
+
+ // Artist name
+ TextView appText = mMediaNotifView.findViewById(R.id.header_title);
+ String artistName = mMediaMetadata.getString(MediaMetadata.METADATA_KEY_ARTIST);
+ appText.setText(artistName);
+ appText.setTextColor(iconColor);
+
+ // Song name
+ TextView titleText = mMediaNotifView.findViewById(R.id.header_text);
+ String songName = mMediaMetadata.getString(MediaMetadata.METADATA_KEY_TITLE);
+ titleText.setText(songName);
+ titleText.setTextColor(iconColor);
+
+ // Action buttons
+ LinearLayout parentActionsLayout = (LinearLayout) actionsContainer;
+ final int[] actionIds = {R.id.action0, R.id.action1, R.id.action2};
+
+ // TODO some apps choose different buttons to show in compact mode
+ final int[] notifActionIds = {
+ com.android.internal.R.id.action1,
+ com.android.internal.R.id.action2,
+ com.android.internal.R.id.action3
+ };
+ for (int i = 0; i < parentActionsLayout.getChildCount() && i < actionIds.length; i++) {
+ ImageButton thisBtn = mMediaNotifView.findViewById(actionIds[i]);
+ ImageButton thatBtn = parentActionsLayout.findViewById(notifActionIds[i]);
+ if (thatBtn == null || thatBtn.getDrawable() == null) {
+ thisBtn.setVisibility(View.GONE);
+ continue;
+ }
+
+ Drawable thatIcon = thatBtn.getDrawable();
+ thisBtn.setImageDrawable(thatIcon.mutate());
+ thisBtn.setVisibility(View.VISIBLE);
+
+ thisBtn.setOnClickListener(v -> {
+ Log.d(TAG, "clicking on other button");
+ thatBtn.performClick();
+ });
+ }
+ }
+
+ public MediaSession.Token getMediaSessionToken() {
+ return mToken;
+ }
+
+ /**
+ * Check whether the media controlled by this player is currently playing
+ * @return whether it is playing, or false if no controller information
+ */
+ public boolean isPlaying() {
+ if (mController == null) {
+ return false;
+ }
+
+ PlaybackState state = mController.getPlaybackState();
+ if (state == null) {
+ return false;
+ }
+
+ return (state.getState() == PlaybackState.STATE_PLAYING);
+ }
+
+ private void addAlbumArtBackground(MediaMetadata metadata, int bgColor) {
+ Bitmap albumArt = metadata.getBitmap(MediaMetadata.METADATA_KEY_ALBUM_ART);
+ if (albumArt != null) {
+ Rect bounds = new Rect();
+ mMediaNotifView.getBoundsOnScreen(bounds);
+ int width = bounds.width();
+ int height = bounds.height();
+
+ Bitmap original = albumArt.copy(Bitmap.Config.ARGB_8888, true);
+ Bitmap scaled = scaleBitmap(original, width, height);
+ Canvas canvas = new Canvas(scaled);
+
+ // Add translucent layer over album art to improve contrast
+ Paint p = new Paint();
+ p.setStyle(Paint.Style.FILL);
+ p.setColor(bgColor);
+ p.setAlpha(200);
+ canvas.drawRect(0, 0, canvas.getWidth(), canvas.getHeight(), p);
+
+ RoundedBitmapDrawable roundedDrawable = RoundedBitmapDrawableFactory.create(
+ mContext.getResources(), scaled);
+ roundedDrawable.setCornerRadius(20);
+
+ mMediaNotifView.setBackground(roundedDrawable);
+ } else {
+ Log.e(TAG, "No album art available");
+ }
+ }
+
+ private Bitmap scaleBitmap(Bitmap original, int width, int height) {
+ Bitmap cropped = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
+ Canvas canvas = new Canvas(cropped);
+
+ float scale = (float) cropped.getWidth() / (float) original.getWidth();
+ float dy = (cropped.getHeight() - original.getHeight() * scale) / 2.0f;
+ Matrix transformation = new Matrix();
+ transformation.postTranslate(0, dy);
+ transformation.preScale(scale, scale);
+
+ Paint paint = new Paint();
+ paint.setFilterBitmap(true);
+ canvas.drawBitmap(original, transformation, paint);
+
+ return cropped;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java
index 85aafa06961a..dcd4633a79d2 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java
@@ -21,6 +21,7 @@ import static com.android.systemui.util.InjectionInflationController.VIEW_CONTEX
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.Rect;
+import android.provider.Settings;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.View;
@@ -55,6 +56,7 @@ public class QuickQSPanel extends QSPanel {
private boolean mDisabledByPolicy;
private int mMaxTiles;
protected QSPanel mFullPanel;
+ private QuickQSMediaPlayer mMediaPlayer;
@Inject
public QuickQSPanel(@Named(VIEW_CONTEXT) Context context, AttributeSet attrs,
@@ -69,11 +71,43 @@ public class QuickQSPanel extends QSPanel {
}
removeView((View) mTileLayout);
}
- sDefaultMaxTiles = getResources().getInteger(R.integer.quick_qs_panel_max_columns);
- mTileLayout = new HeaderTileLayout(context);
- mTileLayout.setListening(mListening);
- addView((View) mTileLayout, 0 /* Between brightness and footer */);
- super.setPadding(0, 0, 0, 0);
+
+ int flag = Settings.System.getInt(context.getContentResolver(), "qs_media_player", 0);
+ if (flag == 1) {
+ LinearLayout mHorizontalLinearLayout = new LinearLayout(mContext);
+ mHorizontalLinearLayout.setOrientation(LinearLayout.HORIZONTAL);
+ mHorizontalLinearLayout.setClipChildren(false);
+ mHorizontalLinearLayout.setClipToPadding(false);
+
+ LayoutParams lp = new LayoutParams(0, LayoutParams.MATCH_PARENT, 1);
+
+ mTileLayout = new DoubleLineTileLayout(context);
+ lp.setMarginEnd(10);
+ lp.setMarginStart(0);
+ mHorizontalLinearLayout.addView((View) mTileLayout, lp);
+
+ mMediaPlayer = new QuickQSMediaPlayer(mContext, mHorizontalLinearLayout);
+
+ lp.setMarginEnd(0);
+ lp.setMarginStart(10);
+ mHorizontalLinearLayout.addView(mMediaPlayer.getView(), lp);
+
+ sDefaultMaxTiles = getResources().getInteger(R.integer.quick_qs_panel_max_columns);
+
+ mTileLayout.setListening(mListening);
+ addView(mHorizontalLinearLayout, 0 /* Between brightness and footer */);
+ super.setPadding(0, 0, 0, 0);
+ } else {
+ sDefaultMaxTiles = getResources().getInteger(R.integer.quick_qs_panel_max_columns);
+ mTileLayout = new HeaderTileLayout(context);
+ mTileLayout.setListening(mListening);
+ addView((View) mTileLayout, 0 /* Between brightness and footer */);
+ super.setPadding(0, 0, 0, 0);
+ }
+ }
+
+ public QuickQSMediaPlayer getMediaPlayer() {
+ return mMediaPlayer;
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
index d20b22815805..592e3881ea97 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
@@ -257,10 +257,6 @@ public class QuickStatusBarHeader extends RelativeLayout implements
mNextAlarmTextView.setSelected(true);
mPermissionsHubEnabled = PrivacyItemControllerKt.isPermissionsHubEnabled();
- // Change the ignored slots when DeviceConfig flag changes
- DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_PRIVACY,
- mContext.getMainExecutor(), mPropertiesListener);
-
}
private List<String> getIgnoredIconSlots() {
@@ -396,9 +392,15 @@ public class QuickStatusBarHeader extends RelativeLayout implements
mSystemIconsView.setLayoutParams(mSystemIconsView.getLayoutParams());
FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) getLayoutParams();
+
+ int flag = Settings.System.getInt(mContext.getContentResolver(), "qs_media_player", 0);
if (mQsDisabled) {
lp.height = resources.getDimensionPixelSize(
com.android.internal.R.dimen.quick_qs_offset_height);
+ } else if (flag == 1) {
+ lp.height = Math.max(getMinimumHeight(),
+ resources.getDimensionPixelSize(
+ com.android.internal.R.dimen.quick_qs_total_height_with_media));
} else {
lp.height = Math.max(getMinimumHeight(),
resources.getDimensionPixelSize(
@@ -489,6 +491,9 @@ public class QuickStatusBarHeader extends RelativeLayout implements
super.onAttachedToWindow();
mStatusBarIconController.addIconGroup(mIconManager);
requestApplyInsets();
+ // Change the ignored slots when DeviceConfig flag changes
+ DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_PRIVACY,
+ mContext.getMainExecutor(), mPropertiesListener);
}
@Override
@@ -527,6 +532,7 @@ public class QuickStatusBarHeader extends RelativeLayout implements
public void onDetachedFromWindow() {
setListening(false);
mStatusBarIconController.removeIconGroup(mIconManager);
+ DeviceConfig.removeOnPropertiesChangedListener(mPropertiesListener);
super.onDetachedFromWindow();
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/TileLayout.java b/packages/SystemUI/src/com/android/systemui/qs/TileLayout.java
index 14addb99c0c5..37743ec55517 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/TileLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/TileLayout.java
@@ -2,6 +2,7 @@ package com.android.systemui.qs;
import android.content.Context;
import android.content.res.Resources;
+import android.provider.Settings;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
@@ -31,6 +32,9 @@ public class TileLayout extends ViewGroup implements QSTileLayout {
private boolean mListening;
protected int mMaxAllowedRows = 3;
+ // Prototyping with less rows
+ private final boolean mLessRows;
+
public TileLayout(Context context) {
this(context, null);
}
@@ -38,7 +42,9 @@ public class TileLayout extends ViewGroup implements QSTileLayout {
public TileLayout(Context context, AttributeSet attrs) {
super(context, attrs);
setFocusableInTouchMode(true);
+ mLessRows = Settings.System.getInt(context.getContentResolver(), "qs_less_rows", 0) != 0;
updateResources();
+
}
@Override
@@ -89,6 +95,7 @@ public class TileLayout extends ViewGroup implements QSTileLayout {
mCellMarginTop = res.getDimensionPixelSize(R.dimen.qs_tile_margin_top);
mSidePadding = res.getDimensionPixelOffset(R.dimen.qs_tile_layout_margin_side);
mMaxAllowedRows = Math.max(1, getResources().getInteger(R.integer.quick_settings_max_rows));
+ if (mLessRows) mMaxAllowedRows = Math.max(1, mMaxAllowedRows - 1);
if (mColumns != columns) {
mColumns = columns;
requestLayout();
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
index 38153ecd59c9..7fb520766977 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
@@ -46,8 +46,8 @@ import com.android.systemui.qs.QSDetailClipper;
import com.android.systemui.qs.QSTileHost;
import com.android.systemui.statusbar.phone.LightBarController;
import com.android.systemui.statusbar.phone.NotificationsQuickSettingsContainer;
-import com.android.systemui.statusbar.policy.KeyguardMonitor;
-import com.android.systemui.statusbar.policy.KeyguardMonitor.Callback;
+import com.android.systemui.statusbar.policy.KeyguardStateController;
+import com.android.systemui.statusbar.policy.KeyguardStateController.Callback;
import java.util.ArrayList;
import java.util.List;
@@ -68,7 +68,7 @@ public class QSCustomizer extends LinearLayout implements OnMenuItemClickListene
private final QSDetailClipper mClipper;
private final LightBarController mLightBarController;
- private KeyguardMonitor mKeyguardMonitor;
+ private KeyguardStateController mKeyguardStateController;
private final ScreenLifecycle mScreenLifecycle;
private final TileQueryHelper mTileQueryHelper;
private final View mTransparentView;
@@ -89,7 +89,7 @@ public class QSCustomizer extends LinearLayout implements OnMenuItemClickListene
@Inject
public QSCustomizer(Context context, AttributeSet attrs,
LightBarController lightBarController,
- KeyguardMonitor keyguardMonitor,
+ KeyguardStateController keyguardStateController,
ScreenLifecycle screenLifecycle) {
super(new ContextThemeWrapper(context, R.style.edit_theme), attrs);
@@ -124,7 +124,7 @@ public class QSCustomizer extends LinearLayout implements OnMenuItemClickListene
animator.setMoveDuration(TileAdapter.MOVE_DURATION);
mRecyclerView.setItemAnimator(animator);
mLightBarController = lightBarController;
- mKeyguardMonitor = keyguardMonitor;
+ mKeyguardStateController = keyguardStateController;
mScreenLifecycle = screenLifecycle;
updateNavBackDrop(getResources().getConfiguration());
}
@@ -187,7 +187,7 @@ public class QSCustomizer extends LinearLayout implements OnMenuItemClickListene
queryTiles();
mNotifQsContainer.setCustomizerAnimating(true);
mNotifQsContainer.setCustomizerShowing(true);
- mKeyguardMonitor.addCallback(mKeyguardCallback);
+ mKeyguardStateController.addCallback(mKeyguardCallback);
updateNavColors();
}
}
@@ -203,7 +203,7 @@ public class QSCustomizer extends LinearLayout implements OnMenuItemClickListene
queryTiles();
mNotifQsContainer.setCustomizerAnimating(false);
mNotifQsContainer.setCustomizerShowing(true);
- mKeyguardMonitor.addCallback(mKeyguardCallback);
+ mKeyguardStateController.addCallback(mKeyguardCallback);
updateNavColors();
}
}
@@ -227,7 +227,7 @@ public class QSCustomizer extends LinearLayout implements OnMenuItemClickListene
}
mNotifQsContainer.setCustomizerAnimating(animate);
mNotifQsContainer.setCustomizerShowing(false);
- mKeyguardMonitor.removeCallback(mKeyguardCallback);
+ mKeyguardStateController.removeCallback(mKeyguardCallback);
updateNavColors();
}
}
@@ -283,7 +283,7 @@ public class QSCustomizer extends LinearLayout implements OnMenuItemClickListene
public void saveInstanceState(Bundle outState) {
if (isShown) {
- mKeyguardMonitor.removeCallback(mKeyguardCallback);
+ mKeyguardStateController.removeCallback(mKeyguardCallback);
}
outState.putBoolean(EXTRA_QS_CUSTOMIZING, mCustomizing);
}
@@ -315,7 +315,7 @@ public class QSCustomizer extends LinearLayout implements OnMenuItemClickListene
@Override
public void onKeyguardShowingChanged() {
if (!isAttachedToWindow()) return;
- if (mKeyguardMonitor.isShowing() && !mOpening) {
+ if (mKeyguardStateController.isShowing() && !mOpening) {
hide();
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java b/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
index 2542abdbef72..bd3297b3d39c 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
@@ -277,20 +277,7 @@ public class TileAdapter extends RecyclerView.Adapter<Holder> implements TileSta
selectPosition(holder.getAdapterPosition(), v);
}
});
- if (mNeedsFocus) {
- // Wait for this to get laid out then set its focus.
- // Ensure that tile gets laid out so we get the callback.
- holder.mTileView.requestLayout();
- holder.mTileView.addOnLayoutChangeListener(new OnLayoutChangeListener() {
- @Override
- public void onLayoutChange(View v, int left, int top, int right, int bottom,
- int oldLeft, int oldTop, int oldRight, int oldBottom) {
- holder.mTileView.removeOnLayoutChangeListener(this);
- holder.mTileView.requestFocus();
- }
- });
- mNeedsFocus = false;
- }
+ focusOnHolder(holder);
return;
}
@@ -330,16 +317,38 @@ public class TileAdapter extends RecyclerView.Adapter<Holder> implements TileSta
} else {
if (position < mEditIndex && canRemoveTiles()) {
showAccessibilityDialog(position, v);
+ } else if (position < mEditIndex && !canRemoveTiles()) {
+ startAccessibleMove(position);
} else {
startAccessibleAdd(position);
}
}
}
});
+ if (position == mAccessibilityFromIndex) {
+ focusOnHolder(holder);
+ }
}
}
}
+ private void focusOnHolder(Holder holder) {
+ if (mNeedsFocus) {
+ // Wait for this to get laid out then set its focus.
+ // Ensure that tile gets laid out so we get the callback.
+ holder.mTileView.requestLayout();
+ holder.mTileView.addOnLayoutChangeListener(new OnLayoutChangeListener() {
+ @Override
+ public void onLayoutChange(View v, int left, int top, int right, int bottom,
+ int oldLeft, int oldTop, int oldRight, int oldBottom) {
+ holder.mTileView.removeOnLayoutChangeListener(this);
+ holder.mTileView.requestFocus();
+ }
+ });
+ mNeedsFocus = false;
+ }
+ }
+
private boolean canRemoveTiles() {
return mCurrentSpecs.size() > mMinNumTiles;
}
@@ -396,6 +405,7 @@ public class TileAdapter extends RecyclerView.Adapter<Holder> implements TileSta
mAccessibilityFromIndex = position;
mAccessibilityFromLabel = mTiles.get(position).state.label;
mAccessibilityAction = ACTION_MOVE;
+ mNeedsFocus = true;
notifyDataSetChanged();
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java b/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java
index 466c8082f0b9..411980b399bd 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java
@@ -39,6 +39,7 @@ import android.text.format.DateUtils;
import android.util.Log;
import android.view.IWindowManager;
import android.view.WindowManagerGlobal;
+import android.widget.Switch;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.systemui.Dependency;
@@ -82,6 +83,11 @@ public class CustomTile extends QSTileImpl<State> implements TileChangeListener
mTile = new Tile();
updateDefaultTileAndIcon();
mServiceManager = host.getTileServices().getTileWrapper(this);
+ if (mServiceManager.isBooleanTile()) {
+ // Replace states with BooleanState
+ resetStates();
+ }
+
mService = mServiceManager.getTileService();
mServiceManager.setTileChangeListener(this);
mUser = ActivityManager.getCurrentUser();
@@ -246,8 +252,10 @@ public class CustomTile extends QSTileImpl<State> implements TileChangeListener
@Override
public State newTileState() {
- State state = new State();
- return state;
+ if (mServiceManager != null && mServiceManager.isBooleanTile()) {
+ return new BooleanState();
+ }
+ return new State();
}
@Override
@@ -336,6 +344,12 @@ public class CustomTile extends QSTileImpl<State> implements TileChangeListener
} else {
state.contentDescription = state.label;
}
+
+ if (state instanceof BooleanState) {
+ state.expandedAccessibilityClassName = Switch.class.getName();
+ ((BooleanState) state).value = (state.state == Tile.STATE_ACTIVE);
+ }
+
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java b/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java
index effea6a877b8..f59e0c2d9bc2 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java
@@ -131,6 +131,24 @@ public class TileLifecycleManager extends BroadcastReceiver implements
}
/**
+ * Determines whether the associated TileService is a Boolean Tile.
+ *
+ * @return true if {@link TileService#META_DATA_BOOLEAN_TILE} is set to {@code true} for this
+ * tile
+ * @see TileService#META_DATA_BOOLEAN_TILE
+ */
+ public boolean isBooleanTile() {
+ try {
+ ServiceInfo info = mPackageManagerAdapter.getServiceInfo(mIntent.getComponent(),
+ PackageManager.MATCH_UNINSTALLED_PACKAGES | PackageManager.GET_META_DATA);
+ return info.metaData != null
+ && info.metaData.getBoolean(TileService.META_DATA_BOOLEAN_TILE, false);
+ } catch (PackageManager.NameNotFoundException e) {
+ return false;
+ }
+ }
+
+ /**
* Binds just long enough to send any queued messages, then unbinds.
*/
public void flushMessagesAndUnbind() {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/TileServiceManager.java b/packages/SystemUI/src/com/android/systemui/qs/external/TileServiceManager.java
index 2a7e55fe6f8f..0b4e6485551c 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/TileServiceManager.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/TileServiceManager.java
@@ -123,6 +123,10 @@ public class TileServiceManager {
return mStateManager.isActiveTile();
}
+ public boolean isBooleanTile() {
+ return mStateManager.isBooleanTile();
+ }
+
public void setShowingDialog(boolean dialog) {
mShowingDialog = dialog;
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/TileServices.java b/packages/SystemUI/src/com/android/systemui/qs/external/TileServices.java
index 23f36e94abae..13cfa78b7c1e 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/TileServices.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/TileServices.java
@@ -39,7 +39,7 @@ import com.android.internal.statusbar.StatusBarIcon;
import com.android.systemui.Dependency;
import com.android.systemui.qs.QSTileHost;
import com.android.systemui.statusbar.phone.StatusBarIconController;
-import com.android.systemui.statusbar.policy.KeyguardMonitor;
+import com.android.systemui.statusbar.policy.KeyguardStateController;
import java.util.ArrayList;
import java.util.Collections;
@@ -296,14 +296,16 @@ public class TileServices extends IQSService.Stub {
@Override
public boolean isLocked() {
- KeyguardMonitor keyguardMonitor = Dependency.get(KeyguardMonitor.class);
- return keyguardMonitor.isShowing();
+ KeyguardStateController keyguardStateController =
+ Dependency.get(KeyguardStateController.class);
+ return keyguardStateController.isShowing();
}
@Override
public boolean isSecure() {
- KeyguardMonitor keyguardMonitor = Dependency.get(KeyguardMonitor.class);
- return keyguardMonitor.isSecure() && keyguardMonitor.isShowing();
+ KeyguardStateController keyguardStateController =
+ Dependency.get(KeyguardStateController.class);
+ return keyguardStateController.isMethodSecure() && keyguardStateController.isShowing();
}
private CustomTile getTileForToken(IBinder token) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java
index daaee4cd5336..1c8e451e52f7 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java
@@ -16,6 +16,7 @@ package com.android.systemui.qs.tileimpl;
import android.content.Context;
import android.os.Build;
+import android.provider.Settings;
import android.util.Log;
import android.view.ContextThemeWrapper;
@@ -32,6 +33,7 @@ import com.android.systemui.qs.tiles.BluetoothTile;
import com.android.systemui.qs.tiles.CastTile;
import com.android.systemui.qs.tiles.CellularTile;
import com.android.systemui.qs.tiles.ColorInversionTile;
+import com.android.systemui.qs.tiles.ControlsTile;
import com.android.systemui.qs.tiles.DataSaverTile;
import com.android.systemui.qs.tiles.DndTile;
import com.android.systemui.qs.tiles.FlashlightTile;
@@ -58,6 +60,7 @@ public class QSFactoryImpl implements QSFactory {
private final Provider<WifiTile> mWifiTileProvider;
private final Provider<BluetoothTile> mBluetoothTileProvider;
+ private final Provider<ControlsTile> mControlsTileProvider;
private final Provider<CellularTile> mCellularTileProvider;
private final Provider<DndTile> mDndTileProvider;
private final Provider<ColorInversionTile> mColorInversionTileProvider;
@@ -81,6 +84,7 @@ public class QSFactoryImpl implements QSFactory {
@Inject
public QSFactoryImpl(Provider<WifiTile> wifiTileProvider,
Provider<BluetoothTile> bluetoothTileProvider,
+ Provider<ControlsTile> controlsTileProvider,
Provider<CellularTile> cellularTileProvider,
Provider<DndTile> dndTileProvider,
Provider<ColorInversionTile> colorInversionTileProvider,
@@ -100,6 +104,7 @@ public class QSFactoryImpl implements QSFactory {
Provider<UiModeNightTile> uiModeNightTileProvider) {
mWifiTileProvider = wifiTileProvider;
mBluetoothTileProvider = bluetoothTileProvider;
+ mControlsTileProvider = controlsTileProvider;
mCellularTileProvider = cellularTileProvider;
mDndTileProvider = dndTileProvider;
mColorInversionTileProvider = colorInversionTileProvider;
@@ -138,6 +143,11 @@ public class QSFactoryImpl implements QSFactory {
return mWifiTileProvider.get();
case "bt":
return mBluetoothTileProvider.get();
+ case "controls":
+ if (Settings.System.getInt(mHost.getContext().getContentResolver(),
+ "qs_controls_tile_enabled", 0) == 1) {
+ return mControlsTileProvider.get();
+ } else return null;
case "cell":
return mCellularTileProvider.get();
case "dnd":
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java
index 681de378ff57..e0f26cd1a267 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java
@@ -139,6 +139,11 @@ public abstract class QSTileImpl<TState extends State> implements QSTile, Lifecy
mQSSettingsPanelOption = QSSettingsControllerKt.getQSSettingsPanelOption();
}
+ protected final void resetStates() {
+ mState = newTileState();
+ mTmpState = newTileState();
+ }
+
@NonNull
@Override
public Lifecycle getLifecycle() {
@@ -629,6 +634,11 @@ public abstract class QSTileImpl<TState extends State> implements QSTile, Lifecy
}
}
+ /**
+ * Dumps the state of this tile along with its name.
+ *
+ * This may be used for CTS testing of tiles.
+ */
@Override
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
pw.println(this.getClass().getSimpleName() + ":");
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
index 2f1e01421ea5..d4e9fdff1b24 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
@@ -46,7 +46,7 @@ import com.android.systemui.qs.tileimpl.QSTileImpl;
import com.android.systemui.statusbar.phone.SystemUIDialog;
import com.android.systemui.statusbar.policy.CastController;
import com.android.systemui.statusbar.policy.CastController.CastDevice;
-import com.android.systemui.statusbar.policy.KeyguardMonitor;
+import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.statusbar.policy.NetworkController;
import java.util.ArrayList;
@@ -62,7 +62,7 @@ public class CastTile extends QSTileImpl<BooleanState> {
private final CastController mController;
private final CastDetailAdapter mDetailAdapter;
- private final KeyguardMonitor mKeyguard;
+ private final KeyguardStateController mKeyguard;
private final NetworkController mNetworkController;
private final Callback mCallback = new Callback();
private final ActivityStarter mActivityStarter;
@@ -71,12 +71,13 @@ public class CastTile extends QSTileImpl<BooleanState> {
private static final String WFD_ENABLE = "persist.debug.wfd.enable";
@Inject
- public CastTile(QSHost host, CastController castController, KeyguardMonitor keyguardMonitor,
- NetworkController networkController, ActivityStarter activityStarter) {
+ public CastTile(QSHost host, CastController castController,
+ KeyguardStateController keyguardStateController, NetworkController networkController,
+ ActivityStarter activityStarter) {
super(host);
mController = castController;
mDetailAdapter = new CastDetailAdapter();
- mKeyguard = keyguardMonitor;
+ mKeyguard = keyguardStateController;
mNetworkController = networkController;
mActivityStarter = activityStarter;
mController.observe(this, mCallback);
@@ -266,7 +267,8 @@ public class CastTile extends QSTileImpl<BooleanState> {
}
};
- private final class Callback implements CastController.Callback, KeyguardMonitor.Callback {
+ private final class Callback implements CastController.Callback,
+ KeyguardStateController.Callback {
@Override
public void onCastDevicesChanged() {
refreshState();
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
index 2967cf5ea427..e32fc32d4aa0 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
@@ -98,6 +98,9 @@ public class CellularTile extends QSTileImpl<SignalState> {
@Override
public Intent getLongClickIntent() {
+ if (getState().state == Tile.STATE_UNAVAILABLE) {
+ return new Intent(Settings.ACTION_WIRELESS_SETTINGS);
+ }
return getCellularSettingIntent();
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/ControlsTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/ControlsTile.java
new file mode 100644
index 000000000000..0a59618b59a1
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/ControlsTile.java
@@ -0,0 +1,197 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.tiles;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.LinearLayout;
+
+import com.android.systemui.R;
+import com.android.systemui.plugins.ActivityStarter;
+import com.android.systemui.plugins.HomeControlsPlugin;
+import com.android.systemui.plugins.PluginListener;
+import com.android.systemui.plugins.qs.DetailAdapter;
+import com.android.systemui.plugins.qs.QSTile.BooleanState;
+import com.android.systemui.qs.QSHost;
+import com.android.systemui.qs.tileimpl.QSTileImpl;
+import com.android.systemui.shared.plugins.PluginManager;
+
+import javax.inject.Inject;
+
+
+/**
+ * Temporary control test for prototyping
+ */
+public class ControlsTile extends QSTileImpl<BooleanState> {
+ private ControlsDetailAdapter mDetailAdapter;
+ private final ActivityStarter mActivityStarter;
+ private PluginManager mPluginManager;
+ private HomeControlsPlugin mPlugin;
+ private Intent mHomeAppIntent;
+
+ @Inject
+ public ControlsTile(QSHost host,
+ ActivityStarter activityStarter,
+ PluginManager pluginManager) {
+ super(host);
+ mActivityStarter = activityStarter;
+ mPluginManager = pluginManager;
+ mDetailAdapter = (ControlsDetailAdapter) createDetailAdapter();
+
+ mHomeAppIntent = new Intent(Intent.ACTION_VIEW);
+ mHomeAppIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ mHomeAppIntent.setComponent(new ComponentName("com.google.android.apps.chromecast.app",
+ "com.google.android.apps.chromecast.app.DiscoveryActivity"));
+ }
+
+ @Override
+ public DetailAdapter getDetailAdapter() {
+ return mDetailAdapter;
+ }
+
+ @Override
+ public BooleanState newTileState() {
+ return new BooleanState();
+ }
+
+ @Override
+ public void handleSetListening(boolean listening) {
+
+ }
+
+ @Override
+ public void setDetailListening(boolean listening) {
+ if (mPlugin == null) return;
+
+ mPlugin.setVisible(listening);
+ }
+
+ @Override
+ protected void handleClick() {
+ showDetail(true);
+ }
+
+ @Override
+ public Intent getLongClickIntent() {
+ return mHomeAppIntent;
+ }
+
+ @Override
+ protected void handleSecondaryClick() {
+ showDetail(true);
+ }
+
+ @Override
+ public CharSequence getTileLabel() {
+ return "Controls";
+ }
+
+ @Override
+ protected void handleUpdateState(BooleanState state, Object arg) {
+ state.icon = ResourceIcon.get(R.drawable.ic_lightbulb_outline_gm2_24px);
+ state.label = "Controls";
+ }
+
+ @Override
+ public boolean supportsDetailView() {
+ return getDetailAdapter() != null && mQSSettingsPanelOption == QSSettingsPanel.OPEN_CLICK;
+ }
+
+ @Override
+ public int getMetricsCategory() {
+ return -1;
+ }
+
+ @Override
+ protected String composeChangeAnnouncement() {
+ if (mState.value) {
+ return "On";
+ } else {
+ return "Off";
+ }
+ }
+
+ @Override
+ public boolean isAvailable() {
+ return true;
+ }
+
+ @Override
+ protected DetailAdapter createDetailAdapter() {
+ mDetailAdapter = new ControlsDetailAdapter();
+ return mDetailAdapter;
+ }
+
+ private class ControlsDetailAdapter implements DetailAdapter {
+ private View mDetailView;
+ protected LinearLayout mHomeControlsLayout;
+
+ public CharSequence getTitle() {
+ return "Controls";
+ }
+
+ public Boolean getToggleState() {
+ return null;
+ }
+
+ public boolean getToggleEnabled() {
+ return false;
+ }
+
+ public View createDetailView(Context context, View convertView, final ViewGroup parent) {
+ mHomeControlsLayout = (LinearLayout) LayoutInflater.from(context).inflate(
+ R.layout.home_controls, parent, false);
+ mHomeControlsLayout.setVisibility(View.VISIBLE);
+ mPluginManager.addPluginListener(
+ new PluginListener<HomeControlsPlugin>() {
+ @Override
+ public void onPluginConnected(HomeControlsPlugin plugin,
+ Context pluginContext) {
+ mPlugin = plugin;
+ mPlugin.sendParentGroup(mHomeControlsLayout);
+ mPlugin.setVisible(true);
+ }
+
+ @Override
+ public void onPluginDisconnected(HomeControlsPlugin plugin) {
+
+ }
+ }, HomeControlsPlugin.class, false);
+ return mHomeControlsLayout;
+ }
+
+ public Intent getSettingsIntent() {
+ return mHomeAppIntent;
+ }
+
+ public void setToggleState(boolean state) {
+
+ }
+
+ public int getMetricsCategory() {
+ return -1;
+ }
+
+ public boolean hasHeader() {
+ return false;
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java
index 2755e9880b58..dafdd89ee62c 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java
@@ -101,11 +101,15 @@ public class FlashlightTile extends QSTileImpl<BooleanState> implements
state.slash = new SlashState();
}
state.label = mHost.getContext().getString(R.string.quick_settings_flashlight_label);
+ state.secondaryLabel = "";
if (!mFlashlightController.isAvailable()) {
state.icon = mIcon;
state.slash.isSlashed = true;
+ state.secondaryLabel = mContext.getString(
+ R.string.quick_settings_flashlight_camera_in_use);
state.contentDescription = mContext.getString(
- R.string.accessibility_quick_settings_flashlight_unavailable);
+ R.string.accessibility_quick_settings_flashlight_unavailable)
+ + ", " + state.secondaryLabel;
state.state = Tile.STATE_UNAVAILABLE;
return;
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java
index 837ea9fc5f4e..fbdca3ba1c7b 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java
@@ -28,7 +28,7 @@ import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.qs.QSTile.BooleanState;
import com.android.systemui.qs.QSHost;
import com.android.systemui.qs.tileimpl.QSTileImpl;
-import com.android.systemui.statusbar.policy.KeyguardMonitor;
+import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.statusbar.policy.LocationController;
import com.android.systemui.statusbar.policy.LocationController.LocationChangeCallback;
@@ -40,16 +40,16 @@ public class LocationTile extends QSTileImpl<BooleanState> {
private final Icon mIcon = ResourceIcon.get(R.drawable.ic_location);
private final LocationController mController;
- private final KeyguardMonitor mKeyguard;
+ private final KeyguardStateController mKeyguard;
private final ActivityStarter mActivityStarter;
private final Callback mCallback = new Callback();
@Inject
public LocationTile(QSHost host, LocationController locationController,
- KeyguardMonitor keyguardMonitor, ActivityStarter activityStarter) {
+ KeyguardStateController keyguardStateController, ActivityStarter activityStarter) {
super(host);
mController = locationController;
- mKeyguard = keyguardMonitor;
+ mKeyguard = keyguardStateController;
mActivityStarter = activityStarter;
mController.observe(this, mCallback);
mKeyguard.observe(this, mCallback);
@@ -71,7 +71,7 @@ public class LocationTile extends QSTileImpl<BooleanState> {
@Override
protected void handleClick() {
- if (mKeyguard.isSecure() && mKeyguard.isShowing()) {
+ if (mKeyguard.isMethodSecure() && mKeyguard.isShowing()) {
mActivityStarter.postQSRunnableDismissingKeyguard(() -> {
final boolean wasEnabled = mState.value;
mHost.openPanels();
@@ -97,7 +97,7 @@ public class LocationTile extends QSTileImpl<BooleanState> {
// Work around for bug 15916487: don't show location tile on top of lock screen. After the
// bug is fixed, this should be reverted to only hiding it on secure lock screens:
- // state.visible = !(mKeyguard.isSecure() && mKeyguard.isShowing());
+ // state.visible = !(mKeyguard.isMethodSecure() && mKeyguard.isShowing());
state.value = locationEnabled;
checkIfRestrictionEnforcedByAdminOnly(state, UserManager.DISALLOW_SHARE_LOCATION);
if (state.disabledByPolicy == false) {
@@ -133,7 +133,7 @@ public class LocationTile extends QSTileImpl<BooleanState> {
}
private final class Callback implements LocationChangeCallback,
- KeyguardMonitor.Callback {
+ KeyguardStateController.Callback {
@Override
public void onLocationSettingsChanged(boolean enabled) {
refreshState();
diff --git a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
index 9268ee0705a2..3fc139882693 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
@@ -58,6 +58,7 @@ import com.android.internal.policy.ScreenDecorationsUtils;
import com.android.systemui.Dumpable;
import com.android.systemui.SysUiServiceProvider;
import com.android.systemui.model.SysUiState;
+import com.android.systemui.pip.PipUI;
import com.android.systemui.recents.OverviewProxyService.OverviewProxyListener;
import com.android.systemui.shared.recents.IOverviewProxy;
import com.android.systemui.shared.recents.ISystemUiProxy;
@@ -100,6 +101,7 @@ public class OverviewProxyService implements CallbackController<OverviewProxyLis
private static final long MAX_BACKOFF_MILLIS = 10 * 60 * 1000;
private final Context mContext;
+ private final PipUI mPipUI;
private SysUiState mSysUiState;
private final Handler mHandler;
private final NavigationBarController mNavBarController;
@@ -353,6 +355,19 @@ public class OverviewProxyService implements CallbackController<OverviewProxyLis
}
}
+ @Override
+ public void setShelfHeight(boolean visible, int shelfHeight) {
+ if (!verifyCaller("setShelfHeight")) {
+ return;
+ }
+ long token = Binder.clearCallingIdentity();
+ try {
+ mPipUI.setShelfHeight(visible, shelfHeight);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
private boolean verifyCaller(String reason) {
final int callerId = Binder.getCallingUserHandle().getIdentifier();
if (callerId != mCurrentBoundedUserId) {
@@ -464,8 +479,9 @@ public class OverviewProxyService implements CallbackController<OverviewProxyLis
public OverviewProxyService(Context context, DeviceProvisionedController provisionController,
NavigationBarController navBarController, NavigationModeController navModeController,
StatusBarWindowController statusBarWinController,
- SysUiState sysUiState) {
+ SysUiState sysUiState, PipUI pipUI) {
mContext = context;
+ mPipUI = pipUI;
mHandler = new Handler();
mNavBarController = navBarController;
mStatusBarWinController = statusBarWinController;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/Recents.java b/packages/SystemUI/src/com/android/systemui/recents/Recents.java
index 0fc4fe72bd54..0a8264bcef87 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/Recents.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/Recents.java
@@ -17,29 +17,36 @@
package com.android.systemui.recents;
import android.content.ContentResolver;
+import android.content.Context;
import android.content.res.Configuration;
import android.graphics.Rect;
import android.provider.Settings;
-import com.android.systemui.R;
import com.android.systemui.SystemUI;
import com.android.systemui.statusbar.CommandQueue;
import java.io.FileDescriptor;
import java.io.PrintWriter;
+import javax.inject.Inject;
+
/**
* A proxy to a Recents implementation.
*/
public class Recents extends SystemUI implements CommandQueue.Callbacks {
- private RecentsImplementation mImpl;
+ private final RecentsImplementation mImpl;
+
+ @Inject
+ public Recents(Context context, RecentsImplementation impl) {
+ super(context);
+ mImpl = impl;
+ }
@Override
public void start() {
getComponent(CommandQueue.class).addCallback(this);
putComponent(Recents.class, this);
- mImpl = createRecentsImplementationFromConfig();
mImpl.onStart(mContext, this);
}
@@ -139,28 +146,6 @@ public class Recents extends SystemUI implements CommandQueue.Callbacks {
(Settings.Secure.getInt(cr, Settings.Secure.USER_SETUP_COMPLETE, 0) != 0);
}
- /**
- * @return The recents implementation from the config.
- */
- private RecentsImplementation createRecentsImplementationFromConfig() {
- final String clsName = mContext.getString(R.string.config_recentsComponent);
- if (clsName == null || clsName.length() == 0) {
- throw new RuntimeException("No recents component configured", null);
- }
- Class<?> cls = null;
- try {
- cls = mContext.getClassLoader().loadClass(clsName);
- } catch (Throwable t) {
- throw new RuntimeException("Error loading recents component: " + clsName, t);
- }
- try {
- RecentsImplementation impl = (RecentsImplementation) cls.newInstance();
- return impl;
- } catch (Throwable t) {
- throw new RuntimeException("Error creating recents component: " + clsName, t);
- }
- }
-
@Override
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
mImpl.dump(pw);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsModule.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsModule.java
new file mode 100644
index 000000000000..55552850890f
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsModule.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.recents;
+
+import android.content.Context;
+
+import com.android.systemui.R;
+
+import dagger.Module;
+import dagger.Provides;
+
+/**
+ * Dagger injection module for {@link RecentsImplementation}
+ */
+@Module
+public class RecentsModule {
+ /**
+ * @return The {@link RecentsImplementation} from the config.
+ */
+ @Provides
+ public RecentsImplementation provideRecentsImpl(Context context) {
+ final String clsName = context.getString(R.string.config_recentsComponent);
+ if (clsName == null || clsName.length() == 0) {
+ throw new RuntimeException("No recents component configured", null);
+ }
+ Class<?> cls = null;
+ try {
+ cls = context.getClassLoader().loadClass(clsName);
+ } catch (Throwable t) {
+ throw new RuntimeException("Error loading recents component: " + clsName, t);
+ }
+ try {
+ RecentsImplementation impl = (RecentsImplementation) cls.newInstance();
+ return impl;
+ } catch (Throwable t) {
+ throw new RuntimeException("Error creating recents component: " + clsName, t);
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsOnboarding.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsOnboarding.java
index d0c47345a83a..aa6444973a6f 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsOnboarding.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsOnboarding.java
@@ -61,8 +61,10 @@ import android.view.animation.DecelerateInterpolator;
import android.widget.ImageView;
import android.widget.TextView;
+import com.android.systemui.Dependency;
import com.android.systemui.Prefs;
import com.android.systemui.R;
+import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.shared.recents.IOverviewProxy;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.QuickStepContract;
@@ -245,10 +247,15 @@ public class RecentsOnboarding {
private final View.OnAttachStateChangeListener mOnAttachStateChangeListener
= new View.OnAttachStateChangeListener() {
+
+ private final BroadcastDispatcher mBroadcastDispatcher = Dependency.get(
+ BroadcastDispatcher.class);
+
@Override
public void onViewAttachedToWindow(View view) {
if (view == mLayout) {
- mContext.registerReceiver(mReceiver, new IntentFilter(Intent.ACTION_SCREEN_OFF));
+ mBroadcastDispatcher.registerReceiver(mReceiver,
+ new IntentFilter(Intent.ACTION_SCREEN_OFF));
mLayoutAttachedToWindow = true;
if (view.getTag().equals(R.string.recents_swipe_up_onboarding)) {
mHasDismissedSwipeUpTip = false;
@@ -273,7 +280,7 @@ public class RecentsOnboarding {
}
mOverviewOpenedCountSinceQuickScrubTipDismiss = 0;
}
- mContext.unregisterReceiver(mReceiver);
+ mBroadcastDispatcher.unregisterReceiver(mReceiver);
}
}
};
@@ -335,10 +342,11 @@ public class RecentsOnboarding {
private void notifyOnTip(int action, int target) {
try {
IOverviewProxy overviewProxy = mOverviewProxyService.getProxy();
- if(overviewProxy != null) {
+ if (overviewProxy != null) {
overviewProxy.onTip(action, target);
}
- } catch (RemoteException e) {}
+ } catch (RemoteException e) {
+ }
}
public void onNavigationModeChanged(int mode) {
@@ -489,7 +497,7 @@ public class RecentsOnboarding {
WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY,
flags,
PixelFormat.TRANSLUCENT);
- lp.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
+ lp.privateFlags |= WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS;
lp.setTitle("RecentsOnboarding");
lp.gravity = gravity;
return lp;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java b/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java
index c3c0d63f66c4..2d1c08719119 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java
@@ -47,6 +47,7 @@ import android.widget.TextView;
import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.SysUiServiceProvider;
+import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.shared.system.QuickStepContract;
import com.android.systemui.shared.system.WindowManagerWrapper;
import com.android.systemui.statusbar.phone.NavigationBarView;
@@ -127,7 +128,7 @@ public class ScreenPinningRequest implements View.OnClickListener,
| WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
PixelFormat.TRANSLUCENT);
lp.token = new Binder();
- lp.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
+ lp.privateFlags |= WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS;
lp.setTitle("ScreenPinningConfirmation");
lp.gravity = Gravity.FILL;
return lp;
@@ -159,6 +160,8 @@ public class ScreenPinningRequest implements View.OnClickListener,
private ValueAnimator mColorAnim;
private ViewGroup mLayout;
private boolean mShowCancel;
+ private final BroadcastDispatcher mBroadcastDispatcher =
+ Dependency.get(BroadcastDispatcher.class);
public RequestWindowView(Context context, boolean showCancel) {
super(context);
@@ -212,7 +215,7 @@ public class ScreenPinningRequest implements View.OnClickListener,
IntentFilter filter = new IntentFilter(Intent.ACTION_CONFIGURATION_CHANGED);
filter.addAction(Intent.ACTION_USER_SWITCHED);
filter.addAction(Intent.ACTION_SCREEN_OFF);
- mContext.registerReceiver(mReceiver, filter);
+ mBroadcastDispatcher.registerReceiver(mReceiver, filter);
}
private void inflateView(int rotation) {
@@ -313,7 +316,7 @@ public class ScreenPinningRequest implements View.OnClickListener,
@Override
public void onDetachedFromWindow() {
- mContext.unregisterReceiver(mReceiver);
+ mBroadcastDispatcher.unregisterReceiver(mReceiver);
}
protected void onConfigurationChanged() {
diff --git a/packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java b/packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java
index 1e0a9f157ff5..176676fcb9b3 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java
+++ b/packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java
@@ -152,6 +152,20 @@ public class BrightnessController implements ToggleSlider.Listener {
private final Runnable mStartListeningRunnable = new Runnable() {
@Override
public void run() {
+ if (mListening) {
+ return;
+ }
+ mListening = true;
+
+ if (mVrManager != null) {
+ try {
+ mVrManager.registerListener(mVrStateCallbacks);
+ mIsVrModeEnabled = mVrManager.getVrModeState();
+ } catch (RemoteException e) {
+ Log.e(TAG, "Failed to register VR mode state listener: ", e);
+ }
+ }
+
mBrightnessObserver.startObserving();
mUserTracker.startTracking();
@@ -167,6 +181,19 @@ public class BrightnessController implements ToggleSlider.Listener {
private final Runnable mStopListeningRunnable = new Runnable() {
@Override
public void run() {
+ if (!mListening) {
+ return;
+ }
+ mListening = false;
+
+ if (mVrManager != null) {
+ try {
+ mVrManager.unregisterListener(mVrStateCallbacks);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Failed to unregister VR mode state listener: ", e);
+ }
+ }
+
mBrightnessObserver.stopObserving();
mUserTracker.stopTracking();
@@ -297,39 +324,12 @@ public class BrightnessController implements ToggleSlider.Listener {
}
public void registerCallbacks() {
- if (mListening) {
- return;
- }
-
- if (mVrManager != null) {
- try {
- mVrManager.registerListener(mVrStateCallbacks);
- mIsVrModeEnabled = mVrManager.getVrModeState();
- } catch (RemoteException e) {
- Log.e(TAG, "Failed to register VR mode state listener: ", e);
- }
- }
-
mBackgroundHandler.post(mStartListeningRunnable);
- mListening = true;
}
/** Unregister all call backs, both to and from the controller */
public void unregisterCallbacks() {
- if (!mListening) {
- return;
- }
-
- if (mVrManager != null) {
- try {
- mVrManager.unregisterListener(mVrStateCallbacks);
- } catch (RemoteException e) {
- Log.e(TAG, "Failed to unregister VR mode state listener: ", e);
- }
- }
-
mBackgroundHandler.post(mStopListeningRunnable);
- mListening = false;
mControlValueInitialized = false;
}
diff --git a/packages/SystemUI/src/com/android/systemui/shortcut/ShortcutKeyDispatcher.java b/packages/SystemUI/src/com/android/systemui/shortcut/ShortcutKeyDispatcher.java
index 07675e248906..df9791d1bd37 100644
--- a/packages/SystemUI/src/com/android/systemui/shortcut/ShortcutKeyDispatcher.java
+++ b/packages/SystemUI/src/com/android/systemui/shortcut/ShortcutKeyDispatcher.java
@@ -19,6 +19,7 @@ package com.android.systemui.shortcut;
import static android.app.ActivityTaskManager.SPLIT_SCREEN_CREATE_MODE_BOTTOM_OR_RIGHT;
import static android.app.ActivityTaskManager.SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT;
+import android.content.Context;
import android.content.res.Configuration;
import android.os.RemoteException;
import android.util.Log;
@@ -52,6 +53,10 @@ public class ShortcutKeyDispatcher extends SystemUI
protected final long SC_DOCK_LEFT = META_MASK | KeyEvent.KEYCODE_LEFT_BRACKET;
protected final long SC_DOCK_RIGHT = META_MASK | KeyEvent.KEYCODE_RIGHT_BRACKET;
+ public ShortcutKeyDispatcher(Context context) {
+ super(context);
+ }
+
/**
* Registers a shortcut key to window manager.
* @param shortcutCode packed representation of shortcut key code and meta information
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java b/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java
index cd2074fd64b8..c8b2b6aee0b3 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java
@@ -19,6 +19,7 @@ package com.android.systemui.stackdivider;
import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
+import android.content.Context;
import android.content.res.Configuration;
import android.os.RemoteException;
import android.util.Log;
@@ -50,6 +51,10 @@ public class Divider extends SystemUI implements DividerView.DividerCallbacks {
private boolean mHomeStackResizable = false;
private ForcedResizableInfoActivityController mForcedResizableController;
+ public Divider(Context context) {
+ super(context);
+ }
+
@Override
public void start() {
mWindowManager = new DividerWindowManager(mContext);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/AlertingNotificationManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/AlertingNotificationManager.java
index 33bcefb323f8..e24a3625769c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/AlertingNotificationManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/AlertingNotificationManager.java
@@ -65,7 +65,7 @@ public abstract class AlertingNotificationManager implements NotificationLifetim
Log.v(TAG, "showNotification");
}
addAlertEntry(entry);
- updateNotification(entry.key, true /* alert */);
+ updateNotification(entry.getKey(), true /* alert */);
entry.setInterruption();
}
@@ -182,7 +182,7 @@ public abstract class AlertingNotificationManager implements NotificationLifetim
protected final void addAlertEntry(@NonNull NotificationEntry entry) {
AlertEntry alertEntry = createAlertEntry();
alertEntry.setEntry(entry);
- mAlertEntries.put(entry.key, alertEntry);
+ mAlertEntries.put(entry.getKey(), alertEntry);
onAlertEntryAdded(alertEntry);
entry.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
}
@@ -251,7 +251,7 @@ public abstract class AlertingNotificationManager implements NotificationLifetim
@Override
public boolean shouldExtendLifetime(NotificationEntry entry) {
- return !canRemoveImmediately(entry.key);
+ return !canRemoveImmediately(entry.getKey());
}
@Override
@@ -260,7 +260,7 @@ public abstract class AlertingNotificationManager implements NotificationLifetim
mExtendedLifetimeAlertEntries.add(entry);
// We need to make sure that entries are stopping to alert eventually, let's remove
// this as soon as possible.
- AlertEntry alertEntry = mAlertEntries.get(entry.key);
+ AlertEntry alertEntry = mAlertEntries.get(entry.getKey());
alertEntry.removeAsSoonAsPossible();
} else {
mExtendedLifetimeAlertEntries.remove(entry);
@@ -276,7 +276,7 @@ public abstract class AlertingNotificationManager implements NotificationLifetim
@Nullable protected Runnable mRemoveAlertRunnable;
public void setEntry(@NonNull final NotificationEntry entry) {
- setEntry(entry, () -> removeAlertEntry(entry.key));
+ setEntry(entry, () -> removeAlertEntry(entry.getKey()));
}
public void setEntry(@NonNull final NotificationEntry entry,
@@ -332,7 +332,7 @@ public abstract class AlertingNotificationManager implements NotificationLifetim
public int compareTo(@NonNull AlertEntry alertEntry) {
return (mPostTime < alertEntry.mPostTime)
? 1 : ((mPostTime == alertEntry.mPostTime)
- ? mEntry.key.compareTo(alertEntry.mEntry.key) : -1);
+ ? mEntry.getKey().compareTo(alertEntry.mEntry.getKey()) : -1);
}
public void reset() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
index 134d4b87a159..34f543702d96 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
@@ -22,6 +22,8 @@ import static android.inputmethodservice.InputMethodService.BACK_DISPOSITION_DEF
import static android.inputmethodservice.InputMethodService.IME_INVISIBLE;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.Display.INVALID_DISPLAY;
+import static android.view.InsetsState.TYPE_NAVIGATION_BAR;
+import static android.view.InsetsState.TYPE_TOP_BAR;
import static com.android.systemui.statusbar.phone.StatusBar.ONLY_CORE_APPS;
@@ -43,12 +45,17 @@ import android.os.Looper;
import android.os.Message;
import android.util.Pair;
import android.util.SparseArray;
+import android.view.InsetsFlags;
+import android.view.InsetsState.InternalInsetType;
+import android.view.View;
+import android.view.WindowInsetsController.Appearance;
import androidx.annotation.VisibleForTesting;
import com.android.internal.os.SomeArgs;
import com.android.internal.statusbar.IStatusBar;
import com.android.internal.statusbar.StatusBarIcon;
+import com.android.internal.view.AppearanceRegion;
import com.android.systemui.SystemUI;
import com.android.systemui.statusbar.CommandQueue.Callbacks;
import com.android.systemui.statusbar.policy.CallbackController;
@@ -76,7 +83,7 @@ public class CommandQueue extends IStatusBar.Stub implements CallbackController<
private static final int MSG_EXPAND_NOTIFICATIONS = 3 << MSG_SHIFT;
private static final int MSG_COLLAPSE_PANELS = 4 << MSG_SHIFT;
private static final int MSG_EXPAND_SETTINGS = 5 << MSG_SHIFT;
- private static final int MSG_SET_SYSTEMUI_VISIBILITY = 6 << MSG_SHIFT;
+ private static final int MSG_SYSTEM_BAR_APPEARANCE_CHANGED = 6 << MSG_SHIFT;
private static final int MSG_DISPLAY_READY = 7 << MSG_SHIFT;
private static final int MSG_SHOW_IME_BUTTON = 8 << MSG_SHIFT;
private static final int MSG_TOGGLE_RECENT_APPS = 9 << MSG_SHIFT;
@@ -115,6 +122,9 @@ public class CommandQueue extends IStatusBar.Stub implements CallbackController<
private static final int MSG_SHOW_PINNING_TOAST_ENTER_EXIT = 45 << MSG_SHIFT;
private static final int MSG_SHOW_PINNING_TOAST_ESCAPE = 46 << MSG_SHIFT;
private static final int MSG_RECENTS_ANIMATION_STATE_CHANGED = 47 << MSG_SHIFT;
+ private static final int MSG_SHOW_TRANSIENT = 48 << MSG_SHIFT;
+ private static final int MSG_ABORT_TRANSIENT = 49 << MSG_SHIFT;
+ private static final int MSG_TOP_APP_WINDOW_CHANGED = 50 << MSG_SHIFT;
public static final int FLAG_EXCLUDE_NONE = 0;
public static final int FLAG_EXCLUDE_SEARCH_PANEL = 1 << 0;
@@ -160,28 +170,6 @@ public class CommandQueue extends IStatusBar.Stub implements CallbackController<
default void animateExpandSettingsPanel(String obj) { }
/**
- * Called to notify visibility flag changes.
- * @see IStatusBar#setSystemUiVisibility(int, int, int, int, int, Rect, Rect).
- *
- * @param displayId The id of the display to notify.
- * @param vis The visibility flags except SYSTEM_UI_FLAG_LIGHT_STATUS_BAR which will
- * be reported separately in fullscreenStackVis and dockedStackVis.
- * @param fullscreenStackVis The flags which only apply in the region of the fullscreen
- * stack, which is currently only SYSTEM_UI_FLAG_LIGHT_STATUS_BAR.
- * @param dockedStackVis The flags that only apply in the region of the docked stack, which
- * is currently only SYSTEM_UI_FLAG_LIGHT_STATUS_BAR.
- * @param mask Which flags to change.
- * @param fullscreenStackBounds The current bounds of the fullscreen stack, in screen
- * coordinates.
- * @param dockedStackBounds The current bounds of the docked stack, in screen coordinates.
- * @param navbarColorManagedByIme {@code true} if navigation bar color is managed by IME.
- */
- default void setSystemUiVisibility(int displayId, int vis, int fullscreenStackVis,
- int dockedStackVis, int mask, Rect fullscreenStackBounds, Rect dockedStackBounds,
- boolean navbarColorManagedByIme) {
- }
-
- /**
* Called to notify IME window status changes.
*
* @param displayId The id of the display to notify.
@@ -270,12 +258,13 @@ public class CommandQueue extends IStatusBar.Stub implements CallbackController<
default void onRotationProposal(int rotation, boolean isValid) { }
- default void showBiometricDialog(Bundle bundle, IBiometricServiceReceiverInternal receiver,
- int type, boolean requireConfirmation, int userId, String opPackageName) { }
- default void onBiometricAuthenticated(boolean authenticated, String failureReason) { }
+ default void showAuthenticationDialog(Bundle bundle,
+ IBiometricServiceReceiverInternal receiver, int biometricModality,
+ boolean requireConfirmation, int userId, String opPackageName) { }
+ default void onBiometricAuthenticated() { }
default void onBiometricHelp(String message) { }
- default void onBiometricError(String error) { }
- default void hideBiometricDialog() { }
+ default void onBiometricError(int modality, int error, int vendorCode) { }
+ default void hideAuthenticationDialog() { }
/**
* @see IStatusBar#onDisplayReady(int)
@@ -291,6 +280,28 @@ public class CommandQueue extends IStatusBar.Stub implements CallbackController<
* @see IStatusBar#onRecentsAnimationStateChanged(boolean)
*/
default void onRecentsAnimationStateChanged(boolean running) { }
+
+ /**
+ * @see IStatusBar#onSystemBarAppearanceChanged(int, int, AppearanceRegion[], boolean).
+ */
+ default void onSystemBarAppearanceChanged(int displayId, @Appearance int appearance,
+ AppearanceRegion[] appearanceRegions, boolean navbarColorManagedByIme) { }
+
+ /**
+ * @see IStatusBar#showTransient(int, int[]).
+ */
+ default void showTransient(int displayId, @InternalInsetType int[] types) { }
+
+ /**
+ * @see IStatusBar#abortTransient(int, int[]).
+ */
+ default void abortTransient(int displayId, @InternalInsetType int[] types) { }
+
+ /**
+ * @see IStatusBar#topAppWindowChanged(int, boolean, boolean).
+ */
+ default void topAppWindowChanged(int displayId, boolean isFullscreen, boolean isImmersive) {
+ }
}
@VisibleForTesting
@@ -455,28 +466,53 @@ public class CommandQueue extends IStatusBar.Stub implements CallbackController<
}
}
+ // TODO(b/118118435): Remove this function after migration
@Override
public void setSystemUiVisibility(int displayId, int vis, int fullscreenStackVis,
int dockedStackVis, int mask, Rect fullscreenStackBounds, Rect dockedStackBounds,
boolean navbarColorManagedByIme) {
synchronized (mLock) {
- // Don't coalesce these, since it might have one time flags set such as
- // STATUS_BAR_UNHIDE which might get lost.
+ final boolean hasDockedStack = !dockedStackBounds.isEmpty();
+ final boolean transientStatus = (vis & View.STATUS_BAR_TRANSIENT) != 0;
+ final boolean transientNavigation = (vis & View.NAVIGATION_BAR_TRANSIENT) != 0;
+ if (transientStatus && transientNavigation) {
+ showTransient(displayId, new int[]{TYPE_TOP_BAR, TYPE_NAVIGATION_BAR});
+ } else if (transientStatus) {
+ showTransient(displayId, new int[]{TYPE_TOP_BAR});
+ abortTransient(displayId, new int[]{TYPE_NAVIGATION_BAR});
+ } else if (transientNavigation) {
+ showTransient(displayId, new int[]{TYPE_NAVIGATION_BAR});
+ abortTransient(displayId, new int[]{TYPE_TOP_BAR});
+ } else {
+ abortTransient(displayId, new int[]{TYPE_TOP_BAR, TYPE_NAVIGATION_BAR});
+ }
SomeArgs args = SomeArgs.obtain();
args.argi1 = displayId;
- args.argi2 = vis;
- args.argi3 = fullscreenStackVis;
- args.argi4 = dockedStackVis;
- args.argi5 = mask;
- args.argi6 = navbarColorManagedByIme ? 1 : 0;
- args.arg1 = fullscreenStackBounds;
- args.arg2 = dockedStackBounds;
- mHandler.obtainMessage(MSG_SET_SYSTEMUI_VISIBILITY, args).sendToTarget();
+ args.argi2 = InsetsFlags.getAppearance(vis);
+ args.argi3 = navbarColorManagedByIme ? 1 : 0;
+ final int fullscreenAppearance = InsetsFlags.getAppearance(fullscreenStackVis);
+ final int dockedAppearance = InsetsFlags.getAppearance(dockedStackVis);
+ args.arg1 = hasDockedStack
+ ? new AppearanceRegion[]{
+ new AppearanceRegion(fullscreenAppearance, fullscreenStackBounds),
+ new AppearanceRegion(dockedAppearance, dockedStackBounds)}
+ : new AppearanceRegion[]{
+ new AppearanceRegion(fullscreenAppearance, fullscreenStackBounds)};
+ mHandler.obtainMessage(MSG_SYSTEM_BAR_APPEARANCE_CHANGED, args).sendToTarget();
}
}
@Override
- public void topAppWindowChanged(int displayId, boolean menuVisible) { }
+ public void topAppWindowChanged(int displayId, boolean isFullscreen, boolean isImmersive) {
+ synchronized (mLock) {
+ SomeArgs args = SomeArgs.obtain();
+ args.argi1 = displayId;
+ args.argi2 = isFullscreen ? 1 : 0;
+ args.argi3 = isImmersive ? 1 : 0;
+ mHandler.obtainMessage(MSG_TOP_APP_WINDOW_CHANGED, args).sendToTarget();
+ }
+
+ }
@Override
public void setImeWindowStatus(int displayId, IBinder token, int vis, int backDisposition,
@@ -740,13 +776,13 @@ public class CommandQueue extends IStatusBar.Stub implements CallbackController<
}
@Override
- public void showBiometricDialog(Bundle bundle, IBiometricServiceReceiverInternal receiver,
- int type, boolean requireConfirmation, int userId, String opPackageName) {
+ public void showAuthenticationDialog(Bundle bundle, IBiometricServiceReceiverInternal receiver,
+ int biometricModality, boolean requireConfirmation, int userId, String opPackageName) {
synchronized (mLock) {
SomeArgs args = SomeArgs.obtain();
args.arg1 = bundle;
args.arg2 = receiver;
- args.argi1 = type;
+ args.argi1 = biometricModality;
args.arg3 = requireConfirmation;
args.argi2 = userId;
args.arg4 = opPackageName;
@@ -756,12 +792,9 @@ public class CommandQueue extends IStatusBar.Stub implements CallbackController<
}
@Override
- public void onBiometricAuthenticated(boolean authenticated, String failureReason) {
+ public void onBiometricAuthenticated() {
synchronized (mLock) {
- SomeArgs args = SomeArgs.obtain();
- args.arg1 = authenticated;
- args.arg2 = failureReason;
- mHandler.obtainMessage(MSG_BIOMETRIC_AUTHENTICATED, args).sendToTarget();
+ mHandler.obtainMessage(MSG_BIOMETRIC_AUTHENTICATED).sendToTarget();
}
}
@@ -773,14 +806,18 @@ public class CommandQueue extends IStatusBar.Stub implements CallbackController<
}
@Override
- public void onBiometricError(String error) {
+ public void onBiometricError(int modality, int error, int vendorCode) {
synchronized (mLock) {
- mHandler.obtainMessage(MSG_BIOMETRIC_ERROR, error).sendToTarget();
+ SomeArgs args = SomeArgs.obtain();
+ args.argi1 = modality;
+ args.argi2 = error;
+ args.argi3 = vendorCode;
+ mHandler.obtainMessage(MSG_BIOMETRIC_ERROR, args).sendToTarget();
}
}
@Override
- public void hideBiometricDialog() {
+ public void hideAuthenticationDialog() {
synchronized (mLock) {
mHandler.obtainMessage(MSG_BIOMETRIC_HIDE).sendToTarget();
}
@@ -826,6 +863,33 @@ public class CommandQueue extends IStatusBar.Stub implements CallbackController<
}
}
+ @Override
+ public void onSystemBarAppearanceChanged(int displayId, @Appearance int appearance,
+ AppearanceRegion[] appearanceRegions, boolean navbarColorManagedByIme) {
+ synchronized (mLock) {
+ SomeArgs args = SomeArgs.obtain();
+ args.argi1 = displayId;
+ args.argi2 = appearance;
+ args.argi3 = navbarColorManagedByIme ? 1 : 0;
+ args.arg1 = appearanceRegions;
+ mHandler.obtainMessage(MSG_SYSTEM_BAR_APPEARANCE_CHANGED, args).sendToTarget();
+ }
+ }
+
+ @Override
+ public void showTransient(int displayId, int[] types) {
+ synchronized (mLock) {
+ mHandler.obtainMessage(MSG_SHOW_TRANSIENT, displayId, 0, types).sendToTarget();
+ }
+ }
+
+ @Override
+ public void abortTransient(int displayId, int[] types) {
+ synchronized (mLock) {
+ mHandler.obtainMessage(MSG_ABORT_TRANSIENT, displayId, 0, types).sendToTarget();
+ }
+ }
+
private final class H extends Handler {
private H(Looper l) {
super(l);
@@ -878,15 +942,6 @@ public class CommandQueue extends IStatusBar.Stub implements CallbackController<
mCallbacks.get(i).animateExpandSettingsPanel((String) msg.obj);
}
break;
- case MSG_SET_SYSTEMUI_VISIBILITY:
- args = (SomeArgs) msg.obj;
- for (int i = 0; i < mCallbacks.size(); i++) {
- mCallbacks.get(i).setSystemUiVisibility(args.argi1, args.argi2, args.argi3,
- args.argi4, args.argi5, (Rect) args.arg1, (Rect) args.arg2,
- args.argi6 == 1);
- }
- args.recycle();
- break;
case MSG_SHOW_IME_BUTTON:
args = (SomeArgs) msg.obj;
handleShowImeButton(args.argi1 /* displayId */, (IBinder) args.arg1 /* token */,
@@ -1032,10 +1087,10 @@ public class CommandQueue extends IStatusBar.Stub implements CallbackController<
mHandler.removeMessages(MSG_BIOMETRIC_AUTHENTICATED);
SomeArgs someArgs = (SomeArgs) msg.obj;
for (int i = 0; i < mCallbacks.size(); i++) {
- mCallbacks.get(i).showBiometricDialog(
+ mCallbacks.get(i).showAuthenticationDialog(
(Bundle) someArgs.arg1,
(IBiometricServiceReceiverInternal) someArgs.arg2,
- someArgs.argi1 /* type */,
+ someArgs.argi1 /* biometricModality */,
(boolean) someArgs.arg3 /* requireConfirmation */,
someArgs.argi2 /* userId */,
(String) someArgs.arg4 /* opPackageName */);
@@ -1044,13 +1099,9 @@ public class CommandQueue extends IStatusBar.Stub implements CallbackController<
break;
}
case MSG_BIOMETRIC_AUTHENTICATED: {
- SomeArgs someArgs = (SomeArgs) msg.obj;
for (int i = 0; i < mCallbacks.size(); i++) {
- mCallbacks.get(i).onBiometricAuthenticated(
- (boolean) someArgs.arg1 /* authenticated */,
- (String) someArgs.arg2 /* failureReason */);
+ mCallbacks.get(i).onBiometricAuthenticated();
}
- someArgs.recycle();
break;
}
case MSG_BIOMETRIC_HELP:
@@ -1059,13 +1110,19 @@ public class CommandQueue extends IStatusBar.Stub implements CallbackController<
}
break;
case MSG_BIOMETRIC_ERROR:
+ SomeArgs someArgs = (SomeArgs) msg.obj;
for (int i = 0; i < mCallbacks.size(); i++) {
- mCallbacks.get(i).onBiometricError((String) msg.obj);
+ mCallbacks.get(i).onBiometricError(
+ someArgs.argi1 /* modality */,
+ someArgs.argi2 /* error */,
+ someArgs.argi3 /* vendorCode */
+ );
}
+ someArgs.recycle();
break;
case MSG_BIOMETRIC_HIDE:
for (int i = 0; i < mCallbacks.size(); i++) {
- mCallbacks.get(i).hideBiometricDialog();
+ mCallbacks.get(i).hideAuthenticationDialog();
}
break;
case MSG_SHOW_CHARGING_ANIMATION:
@@ -1093,6 +1150,39 @@ public class CommandQueue extends IStatusBar.Stub implements CallbackController<
mCallbacks.get(i).onRecentsAnimationStateChanged(msg.arg1 > 0);
}
break;
+ case MSG_SYSTEM_BAR_APPEARANCE_CHANGED:
+ args = (SomeArgs) msg.obj;
+ for (int i = 0; i < mCallbacks.size(); i++) {
+ mCallbacks.get(i).onSystemBarAppearanceChanged(args.argi1, args.argi2,
+ (AppearanceRegion[]) args.arg1, args.argi3 == 1);
+ }
+ args.recycle();
+ break;
+ case MSG_SHOW_TRANSIENT: {
+ final int displayId = msg.arg1;
+ final int[] types = (int[]) msg.obj;
+ for (int i = 0; i < mCallbacks.size(); i++) {
+ mCallbacks.get(i).showTransient(displayId, types);
+ }
+ break;
+ }
+ case MSG_ABORT_TRANSIENT: {
+ final int displayId = msg.arg1;
+ final int[] types = (int[]) msg.obj;
+ for (int i = 0; i < mCallbacks.size(); i++) {
+ mCallbacks.get(i).abortTransient(displayId, types);
+ }
+ break;
+ }
+ case MSG_TOP_APP_WINDOW_CHANGED: {
+ args = (SomeArgs) msg.obj;
+ for (int i = 0; i < mCallbacks.size(); i++) {
+ mCallbacks.get(i).topAppWindowChanged(
+ args.argi1, args.argi2 != 0, args.argi3 != 0);
+ }
+ args.recycle();
+ break;
+ }
}
}
}
@@ -1100,6 +1190,10 @@ public class CommandQueue extends IStatusBar.Stub implements CallbackController<
// Need this class since CommandQueue already extends IStatusBar.Stub, so CommandQueueStart
// is needed so it can extend SystemUI.
public static class CommandQueueStart extends SystemUI {
+ public CommandQueueStart(Context context) {
+ super(context);
+ }
+
@Override
public void start() {
putComponent(CommandQueue.class, new CommandQueue(mContext));
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/FeatureFlags.java b/packages/SystemUI/src/com/android/systemui/statusbar/FeatureFlags.java
new file mode 100644
index 000000000000..341c49a87156
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/FeatureFlags.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar;
+
+import android.annotation.NonNull;
+import android.os.Handler;
+import android.os.HandlerExecutor;
+import android.provider.DeviceConfig;
+import android.util.ArrayMap;
+
+import com.android.systemui.dagger.qualifiers.BgHandler;
+
+import java.util.Map;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+/**
+ * Class to manage simple DeviceConfig-based feature flags.
+ *
+ * To enable or disable a flag, run:
+ *
+ * {@code
+ * $ adb shell device_config put systemui <key> <true|false>
+* }
+ *
+ * You will probably need to restart systemui for the changes to be picked up:
+ *
+ * {@code
+ * $ adb shell am crash com.android.systemui
+ * }
+ */
+@Singleton
+public class FeatureFlags {
+ private final Map<String, Boolean> mCachedDeviceConfigFlags = new ArrayMap<>();
+
+ @Inject
+ public FeatureFlags(@BgHandler Handler bgHandler) {
+ DeviceConfig.addOnPropertiesChangedListener(
+ "systemui",
+ new HandlerExecutor(bgHandler),
+ this::onPropertiesChanged);
+ }
+
+ public boolean isNewNotifPipelineEnabled() {
+ return getDeviceConfigFlag("notification.newpipeline.enabled", false);
+ }
+
+ private void onPropertiesChanged(@NonNull DeviceConfig.Properties properties) {
+ synchronized (mCachedDeviceConfigFlags) {
+ for (String key : properties.getKeyset()) {
+ mCachedDeviceConfigFlags.remove(key);
+ }
+ }
+ }
+
+ private boolean getDeviceConfigFlag(String key, boolean defaultValue) {
+ synchronized (mCachedDeviceConfigFlags) {
+ Boolean flag = mCachedDeviceConfigFlags.get(key);
+ if (flag == null) {
+ flag = DeviceConfig.getBoolean("systemui", key, defaultValue);
+ mCachedDeviceConfigFlags.put(key, flag);
+ }
+ return flag;
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
index 156e3c072dbe..681f3abaea91 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
@@ -57,8 +57,8 @@ import com.android.systemui.statusbar.phone.LockIcon;
import com.android.systemui.statusbar.phone.LockscreenGestureLogger;
import com.android.systemui.statusbar.phone.ShadeController;
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
-import com.android.systemui.statusbar.phone.UnlockMethodCache;
import com.android.systemui.statusbar.policy.AccessibilityController;
+import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.statusbar.policy.UserInfoController;
import com.android.systemui.util.wakelock.SettableWakeLock;
import com.android.systemui.util.wakelock.WakeLock;
@@ -72,7 +72,7 @@ import java.util.IllegalFormatConversionException;
* Controls the indications and error messages shown on the Keyguard
*/
public class KeyguardIndicationController implements StateListener,
- UnlockMethodCache.OnUnlockMethodChangedListener {
+ KeyguardStateController.Callback {
private static final String TAG = "KeyguardIndication";
private static final boolean DEBUG_CHARGING_SPEED = false;
@@ -86,7 +86,7 @@ public class KeyguardIndicationController implements StateListener,
private final Context mContext;
private final ShadeController mShadeController;
private final AccessibilityController mAccessibilityController;
- private final UnlockMethodCache mUnlockMethodCache;
+ private final KeyguardStateController mKeyguardStateController;
private final StatusBarStateController mStatusBarStateController;
private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
private ViewGroup mIndicationArea;
@@ -137,7 +137,7 @@ public class KeyguardIndicationController implements StateListener,
WakeLock.createPartial(context, "Doze:KeyguardIndication"),
Dependency.get(ShadeController.class),
Dependency.get(AccessibilityController.class),
- UnlockMethodCache.getInstance(context),
+ Dependency.get(KeyguardStateController.class),
Dependency.get(StatusBarStateController.class),
Dependency.get(KeyguardUpdateMonitor.class));
}
@@ -148,14 +148,15 @@ public class KeyguardIndicationController implements StateListener,
@VisibleForTesting
KeyguardIndicationController(Context context, ViewGroup indicationArea, LockIcon lockIcon,
LockPatternUtils lockPatternUtils, WakeLock wakeLock, ShadeController shadeController,
- AccessibilityController accessibilityController, UnlockMethodCache unlockMethodCache,
+ AccessibilityController accessibilityController,
+ KeyguardStateController keyguardStateController,
StatusBarStateController statusBarStateController,
KeyguardUpdateMonitor keyguardUpdateMonitor) {
mContext = context;
mLockIcon = lockIcon;
mShadeController = shadeController;
mAccessibilityController = accessibilityController;
- mUnlockMethodCache = unlockMethodCache;
+ mKeyguardStateController = keyguardStateController;
mStatusBarStateController = statusBarStateController;
mKeyguardUpdateMonitor = keyguardUpdateMonitor;
// lock icon is not used on all form factors.
@@ -181,7 +182,7 @@ public class KeyguardIndicationController implements StateListener,
mKeyguardUpdateMonitor.registerCallback(getKeyguardCallback());
mKeyguardUpdateMonitor.registerCallback(mTickReceiver);
mStatusBarStateController.addCallback(this);
- mUnlockMethodCache.addListener(this);
+ mKeyguardStateController.addCallback(this);
}
public void setIndicationArea(ViewGroup indicationArea) {
@@ -583,7 +584,7 @@ public class KeyguardIndicationController implements StateListener,
}
@Override
- public void onUnlockMethodStateChanged() {
+ public void onUnlockedChanged() {
updateIndication(!mDozing);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NavigationBarController.java b/packages/SystemUI/src/com/android/systemui/statusbar/NavigationBarController.java
index 7bcbd3683130..1f389049f423 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NavigationBarController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NavigationBarController.java
@@ -18,7 +18,6 @@ package com.android.systemui.statusbar;
import static android.view.Display.DEFAULT_DISPLAY;
-import static com.android.systemui.Dependency.MAIN_HANDLER_NAME;
import static com.android.systemui.SysUiServiceProvider.getComponent;
import android.content.Context;
@@ -37,6 +36,8 @@ import androidx.annotation.Nullable;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.statusbar.RegisterStatusBarResult;
import com.android.systemui.Dependency;
+import com.android.systemui.assist.AssistHandleViewController;
+import com.android.systemui.dagger.qualifiers.MainHandler;
import com.android.systemui.plugins.DarkIconDispatcher;
import com.android.systemui.statusbar.CommandQueue.Callbacks;
import com.android.systemui.statusbar.phone.AutoHideController;
@@ -47,7 +48,6 @@ import com.android.systemui.statusbar.phone.NavigationBarView;
import com.android.systemui.statusbar.policy.BatteryController;
import javax.inject.Inject;
-import javax.inject.Named;
import javax.inject.Singleton;
@@ -66,7 +66,7 @@ public class NavigationBarController implements Callbacks {
SparseArray<NavigationBarFragment> mNavigationBars = new SparseArray<>();
@Inject
- public NavigationBarController(Context context, @Named(MAIN_HANDLER_NAME) Handler handler) {
+ public NavigationBarController(Context context, @MainHandler Handler handler) {
mContext = context;
mHandler = handler;
mDisplayManager = (DisplayManager) mContext.getSystemService(Context.DISPLAY_SERVICE);
@@ -151,9 +151,11 @@ public class NavigationBarController implements Callbacks {
// Dependency problem.
AutoHideController autoHideController = isOnDefaultDisplay
? Dependency.get(AutoHideController.class)
- : new AutoHideController(context, mHandler);
+ : new AutoHideController(context, mHandler,
+ Dependency.get(NotificationRemoteInputManager.class),
+ Dependency.get(IWindowManager.class));
navBar.setAutoHideController(autoHideController);
- navBar.restoreSystemUiVisibilityState();
+ navBar.restoreAppearanceAndTransientState();
mNavigationBars.append(displayId, navBar);
if (result != null) {
@@ -230,7 +232,15 @@ public class NavigationBarController implements Callbacks {
}
/** @return {@link NavigationBarFragment} on the default display. */
+ @Nullable
public NavigationBarFragment getDefaultNavigationBarFragment() {
return mNavigationBars.get(DEFAULT_DISPLAY);
}
+
+ /** @return {@link AssistHandleViewController} (only on the default display). */
+ @Nullable
+ public AssistHandleViewController getAssistHandlerViewController() {
+ NavigationBarFragment navBar = getDefaultNavigationBarFragment();
+ return navBar == null ? null : navBar.getAssistHandlerViewController();
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationListener.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationListener.java
index 14009214bdc5..c4de2d3572bd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationListener.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationListener.java
@@ -21,6 +21,7 @@ import static com.android.systemui.statusbar.notification.NotificationEntryManag
import static com.android.systemui.statusbar.phone.StatusBar.DEBUG;
import static com.android.systemui.statusbar.phone.StatusBar.ENABLE_CHILD_NOTIFICATIONS;
+import android.annotation.Nullable;
import android.annotation.SuppressLint;
import android.app.NotificationManager;
import android.content.ComponentName;
@@ -57,8 +58,9 @@ public class NotificationListener extends NotificationListenerWithPlugins {
private final NotificationGroupManager mGroupManager =
Dependency.get(NotificationGroupManager.class);
- private final ArrayList<NotificationSettingsListener> mSettingsListeners = new ArrayList<>();
private final Context mContext;
+ private final ArrayList<NotificationSettingsListener> mSettingsListeners = new ArrayList<>();
+ @Nullable private NotifServiceListener mDownstreamListener;
@Inject
public NotificationListener(Context context) {
@@ -69,6 +71,10 @@ public class NotificationListener extends NotificationListenerWithPlugins {
mSettingsListeners.add(listener);
}
+ public void setDownstreamListener(NotifServiceListener downstreamListener) {
+ mDownstreamListener = downstreamListener;
+ }
+
@Override
public void onListenerConnected() {
if (DEBUG) Log.d(TAG, "onListenerConnected");
@@ -81,6 +87,9 @@ public class NotificationListener extends NotificationListenerWithPlugins {
final RankingMap currentRanking = getCurrentRanking();
Dependency.get(Dependency.MAIN_HANDLER).post(() -> {
for (StatusBarNotification sbn : notifications) {
+ if (mDownstreamListener != null) {
+ mDownstreamListener.onNotificationPosted(sbn, currentRanking);
+ }
mEntryManager.addNotification(sbn, currentRanking);
}
});
@@ -95,6 +104,11 @@ public class NotificationListener extends NotificationListenerWithPlugins {
if (sbn != null && !onPluginNotificationPosted(sbn, rankingMap)) {
Dependency.get(Dependency.MAIN_HANDLER).post(() -> {
processForRemoteInput(sbn.getNotification(), mContext);
+
+ if (mDownstreamListener != null) {
+ mDownstreamListener.onNotificationPosted(sbn, rankingMap);
+ }
+
String key = sbn.getKey();
boolean isUpdate =
mEntryManager.getNotificationData().get(key) != null;
@@ -113,7 +127,7 @@ public class NotificationListener extends NotificationListenerWithPlugins {
mEntryManager.removeNotification(key, rankingMap, UNDEFINED_DISMISS_REASON);
} else {
mEntryManager.getNotificationData()
- .updateRanking(rankingMap);
+ .updateRanking(rankingMap, "onNotificationPosted");
}
return;
}
@@ -133,6 +147,9 @@ public class NotificationListener extends NotificationListenerWithPlugins {
if (sbn != null && !onPluginNotificationRemoved(sbn, rankingMap)) {
final String key = sbn.getKey();
Dependency.get(Dependency.MAIN_HANDLER).post(() -> {
+ if (mDownstreamListener != null) {
+ mDownstreamListener.onNotificationRemoved(sbn, rankingMap, reason);
+ }
mEntryManager.removeNotification(key, rankingMap, reason);
});
}
@@ -149,6 +166,9 @@ public class NotificationListener extends NotificationListenerWithPlugins {
if (rankingMap != null) {
RankingMap r = onPluginRankingUpdate(rankingMap);
Dependency.get(Dependency.MAIN_HANDLER).post(() -> {
+ if (mDownstreamListener != null) {
+ mDownstreamListener.onNotificationRankingUpdate(rankingMap);
+ }
mEntryManager.updateNotificationRanking(r);
});
}
@@ -175,4 +195,12 @@ public class NotificationListener extends NotificationListenerWithPlugins {
default void onStatusBarIconsBehaviorChanged(boolean hideSilentStatusIcons) { }
}
+
+ /** Interface for listening to add/remove events that we receive from NotificationManager. */
+ public interface NotifServiceListener {
+ void onNotificationPosted(StatusBarNotification sbn, RankingMap rankingMap);
+ void onNotificationRemoved(StatusBarNotification sbn, RankingMap rankingMap);
+ void onNotificationRemoved(StatusBarNotification sbn, RankingMap rankingMap, int reason);
+ void onNotificationRankingUpdate(RankingMap rankingMap);
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java
index f782fab7e49f..7adf7af89f0d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java
@@ -54,7 +54,7 @@ import com.android.systemui.statusbar.notification.NotificationUtils;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.logging.NotificationLogger;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
-import com.android.systemui.statusbar.policy.KeyguardMonitor;
+import com.android.systemui.statusbar.policy.KeyguardStateController;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -76,7 +76,8 @@ public class NotificationLockscreenUserManagerImpl implements
private final DeviceProvisionedController mDeviceProvisionedController =
Dependency.get(DeviceProvisionedController.class);
- private final KeyguardMonitor mKeyguardMonitor = Dependency.get(KeyguardMonitor.class);
+ private final KeyguardStateController mKeyguardStateController = Dependency.get(
+ KeyguardStateController.class);
// Lazy
private NotificationEntryManager mEntryManager;
@@ -105,7 +106,7 @@ public class NotificationLockscreenUserManagerImpl implements
isCurrentProfile(getSendingUserId())) {
mUsersAllowingPrivateNotifications.clear();
updateLockscreenNotificationSetting();
- getEntryManager().updateNotifications();
+ getEntryManager().updateNotifications("ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED");
}
}
};
@@ -123,7 +124,7 @@ public class NotificationLockscreenUserManagerImpl implements
updatePublicMode();
// The filtering needs to happen before the update call below in order to make sure
// the presenter has the updated notifications from the new user
- getEntryManager().getNotificationData().filterAndSort();
+ getEntryManager().getNotificationData().filterAndSort("user switched");
mPresenter.onUserSwitched(mCurrentUserId);
for (UserChangedListener listener : mListeners) {
@@ -204,7 +205,8 @@ public class NotificationLockscreenUserManagerImpl implements
mUsersAllowingNotifications.clear();
// ... and refresh all the notifications
updateLockscreenNotificationSetting();
- getEntryManager().updateNotifications();
+ getEntryManager().updateNotifications("LOCK_SCREEN_SHOW_NOTIFICATIONS,"
+ + " or LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS change");
}
};
@@ -213,7 +215,8 @@ public class NotificationLockscreenUserManagerImpl implements
public void onChange(boolean selfChange) {
updateLockscreenNotificationSetting();
if (mDeviceProvisionedController.isDeviceProvisioned()) {
- getEntryManager().updateNotifications();
+ getEntryManager().updateNotifications("LOCK_SCREEN_ALLOW_REMOTE_INPUT"
+ + " or ZEN_MODE change");
}
}
};
@@ -320,7 +323,7 @@ public class NotificationLockscreenUserManagerImpl implements
exceedsPriorityThreshold = entry.getBucket() != BUCKET_SILENT;
} else {
exceedsPriorityThreshold =
- !getEntryManager().getNotificationData().isAmbient(entry.key);
+ !getEntryManager().getNotificationData().isAmbient(entry.getKey());
}
return mShowLockscreenNotifications && exceedsPriorityThreshold;
}
@@ -442,15 +445,15 @@ public class NotificationLockscreenUserManagerImpl implements
/** @return true if the entry needs redaction when on the lockscreen. */
public boolean needsRedaction(NotificationEntry ent) {
- int userId = ent.notification.getUserId();
+ int userId = ent.getSbn().getUserId();
boolean currentUserWantsRedaction = !userAllowsPrivateNotificationsInPublic(mCurrentUserId);
boolean notiUserWantsRedaction = !userAllowsPrivateNotificationsInPublic(userId);
boolean redactedLockscreen = currentUserWantsRedaction || notiUserWantsRedaction;
boolean notificationRequestsRedaction =
- ent.notification.getNotification().visibility == Notification.VISIBILITY_PRIVATE;
- boolean userForcesRedaction = packageHasVisibilityOverride(ent.notification.getKey());
+ ent.getSbn().getNotification().visibility == Notification.VISIBILITY_PRIVATE;
+ boolean userForcesRedaction = packageHasVisibilityOverride(ent.getSbn().getKey());
return userForcesRedaction || notificationRequestsRedaction && redactedLockscreen;
}
@@ -507,8 +510,8 @@ public class NotificationLockscreenUserManagerImpl implements
// asking if the keyguard is showing. We still need to check it though because showing the
// camera on the keyguard has a state of SHADE but the keyguard is still showing.
final boolean showingKeyguard = mState != StatusBarState.SHADE
- || mKeyguardMonitor.isShowing();
- final boolean devicePublic = showingKeyguard && isSecure(getCurrentUserId());
+ || mKeyguardStateController.isShowing();
+ final boolean devicePublic = showingKeyguard && mKeyguardStateController.isMethodSecure();
// Look for public mode users. Users are considered public in either case of:
@@ -523,7 +526,7 @@ public class NotificationLockscreenUserManagerImpl implements
boolean needsSeparateChallenge = whitelistIpcs(() ->
mLockPatternUtils.isSeparateProfileChallengeEnabled(userId));
if (!devicePublic && userId != getCurrentUserId()
- && needsSeparateChallenge && isSecure(userId)) {
+ && needsSeparateChallenge && mLockPatternUtils.isSecure(userId)) {
// Keyguard.isDeviceLocked is updated asynchronously, assume that all profiles
// with separate challenge are locked when keyguard is visible to avoid race.
isProfilePublic = showingKeyguard || mKeyguardManager.isDeviceLocked(userId);
@@ -531,7 +534,7 @@ public class NotificationLockscreenUserManagerImpl implements
setLockscreenPublicMode(isProfilePublic, userId);
mUsersWithSeperateWorkChallenge.put(userId, needsSeparateChallenge);
}
- getEntryManager().updateNotifications();
+ getEntryManager().updateNotifications("NotificationLockscreenUserManager.updatePublicMode");
}
@Override
@@ -545,7 +548,7 @@ public class NotificationLockscreenUserManagerImpl implements
// // asking if the keyguard is showing. We still need to check it though because showing the
// // camera on the keyguard has a state of SHADE but the keyguard is still showing.
// final boolean showingKeyguard = mState != StatusBarState.SHADE
-// || mKeyguardMonitor.isShowing();
+// || mKeyguardStateController.isShowing();
// final boolean devicePublic = showingKeyguard && isSecure(getCurrentUserId());
//
//
@@ -570,10 +573,6 @@ public class NotificationLockscreenUserManagerImpl implements
// }
// }
- private boolean isSecure(int userId) {
- return mKeyguardMonitor.isSecure() || mLockPatternUtils.isSecure(userId);
- }
-
@Override
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
pw.println("NotificationLockscreenUserManager state:");
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java
index 00a12a9e4409..0988e347945c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java
@@ -17,10 +17,6 @@ package com.android.systemui.statusbar;
import static com.android.systemui.Dependency.MAIN_HANDLER;
import static com.android.systemui.statusbar.StatusBarState.KEYGUARD;
-import static com.android.systemui.statusbar.phone.BiometricUnlockController.MODE_UNLOCK_FADING;
-import static com.android.systemui.statusbar.phone.BiometricUnlockController.MODE_WAKE_AND_UNLOCK;
-import static com.android.systemui.statusbar.phone.BiometricUnlockController
- .MODE_WAKE_AND_UNLOCK_PULSING;
import static com.android.systemui.statusbar.phone.StatusBar.DEBUG_MEDIA_FAKE_ARTWORK;
import static com.android.systemui.statusbar.phone.StatusBar.ENABLE_LOCKSCREEN_WALLPAPER;
import static com.android.systemui.statusbar.phone.StatusBar.SHOW_LOCKSCREEN_MEDIA_ARTWORK;
@@ -67,7 +63,7 @@ import com.android.systemui.statusbar.phone.ScrimController;
import com.android.systemui.statusbar.phone.ScrimState;
import com.android.systemui.statusbar.phone.ShadeController;
import com.android.systemui.statusbar.phone.StatusBarWindowController;
-import com.android.systemui.statusbar.policy.KeyguardMonitor;
+import com.android.systemui.statusbar.policy.KeyguardStateController;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -94,7 +90,8 @@ public class NotificationMediaManager implements Dumpable {
private final StatusBarStateController mStatusBarStateController
= Dependency.get(StatusBarStateController.class);
private final SysuiColorExtractor mColorExtractor = Dependency.get(SysuiColorExtractor.class);
- private final KeyguardMonitor mKeyguardMonitor = Dependency.get(KeyguardMonitor.class);
+ private final KeyguardStateController mKeyguardStateController = Dependency.get(
+ KeyguardStateController.class);
private final KeyguardBypassController mKeyguardBypassController;
private static final HashSet<Integer> PAUSED_MEDIA_STATES = new HashSet<>();
static {
@@ -207,7 +204,7 @@ public class NotificationMediaManager implements Dumpable {
NotificationEntry entry,
NotificationVisibility visibility,
boolean removedByUser) {
- onNotificationRemoved(entry.key);
+ onNotificationRemoved(entry.getKey());
}
});
@@ -287,7 +284,7 @@ public class NotificationMediaManager implements Dumpable {
if (entry.isMediaNotification()) {
final MediaSession.Token token =
- entry.notification.getNotification().extras.getParcelable(
+ entry.getSbn().getNotification().extras.getParcelable(
Notification.EXTRA_MEDIA_SESSION);
if (token != null) {
MediaController aController = new MediaController(mContext, token);
@@ -295,7 +292,7 @@ public class NotificationMediaManager implements Dumpable {
getMediaControllerPlaybackState(aController)) {
if (DEBUG_MEDIA) {
Log.v(TAG, "DEBUG_MEDIA: found mediastyle controller matching "
- + entry.notification.getKey());
+ + entry.getSbn().getKey());
}
mediaNotification = entry;
controller = aController;
@@ -324,10 +321,10 @@ public class NotificationMediaManager implements Dumpable {
for (int i = 0; i < N; i++) {
final NotificationEntry entry = activeNotifications.get(i);
- if (entry.notification.getPackageName().equals(pkg)) {
+ if (entry.getSbn().getPackageName().equals(pkg)) {
if (DEBUG_MEDIA) {
Log.v(TAG, "DEBUG_MEDIA: found controller matching "
- + entry.notification.getKey());
+ + entry.getSbn().getKey());
}
controller = aController;
mediaNotification = entry;
@@ -354,8 +351,8 @@ public class NotificationMediaManager implements Dumpable {
}
if (mediaNotification != null
- && !mediaNotification.notification.getKey().equals(mMediaNotificationKey)) {
- mMediaNotificationKey = mediaNotification.notification.getKey();
+ && !mediaNotification.getSbn().getKey().equals(mMediaNotificationKey)) {
+ mMediaNotificationKey = mediaNotification.getSbn().getKey();
if (DEBUG_MEDIA) {
Log.v(TAG, "DEBUG_MEDIA: Found new media notification: key="
+ mMediaNotificationKey);
@@ -364,7 +361,7 @@ public class NotificationMediaManager implements Dumpable {
}
if (metaDataChanged) {
- mEntryManager.updateNotifications();
+ mEntryManager.updateNotifications("NotificationMediaManager - metaDataChanged");
}
dispatchUpdateMediaMetaData(metaDataChanged, true /* allowEnterAnimation */);
@@ -461,7 +458,7 @@ public class NotificationMediaManager implements Dumpable {
boolean wakeAndUnlock = mBiometricUnlockController != null
&& mBiometricUnlockController.isWakeAndUnlock();
- if (mKeyguardMonitor.isLaunchTransitionFadingAway() || wakeAndUnlock) {
+ if (mKeyguardStateController.isLaunchTransitionFadingAway() || wakeAndUnlock) {
mBackdrop.setVisibility(View.INVISIBLE);
Trace.endSection();
return;
@@ -599,7 +596,7 @@ public class NotificationMediaManager implements Dumpable {
boolean cannotAnimateDoze = shadeController != null
&& shadeController.isDozing()
&& !ScrimState.AOD.getAnimateChange();
- boolean needsBypassFading = mKeyguardMonitor.isBypassFadingAnimation();
+ boolean needsBypassFading = mKeyguardStateController.isBypassFadingAnimation();
if (((mBiometricUnlockController != null && mBiometricUnlockController.getMode()
== BiometricUnlockController.MODE_WAKE_AND_UNLOCK_PULSING
|| cannotAnimateDoze) && !needsBypassFading)
@@ -626,10 +623,12 @@ public class NotificationMediaManager implements Dumpable {
mBackdropBack.setImageDrawable(null);
mHandler.post(mHideBackdropFront);
});
- if (mKeyguardMonitor.isKeyguardFadingAway()) {
+ if (mKeyguardStateController.isKeyguardFadingAway()) {
mBackdrop.animate()
- .setDuration(mKeyguardMonitor.getShortenedFadingAwayDuration())
- .setStartDelay(mKeyguardMonitor.getKeyguardFadingAwayDelay())
+ .setDuration(
+ mKeyguardStateController.getShortenedFadingAwayDuration())
+ .setStartDelay(
+ mKeyguardStateController.getKeyguardFadingAwayDelay())
.setInterpolator(Interpolators.LINEAR)
.start();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java
index c9050d492191..c838ac5315a7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java
@@ -17,8 +17,6 @@ package com.android.systemui.statusbar;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY;
-import static com.android.systemui.Dependency.MAIN_HANDLER_NAME;
-
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityManager;
@@ -52,6 +50,7 @@ import com.android.internal.statusbar.IStatusBarService;
import com.android.internal.statusbar.NotificationVisibility;
import com.android.systemui.Dumpable;
import com.android.systemui.R;
+import com.android.systemui.dagger.qualifiers.MainHandler;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.notification.NotificationEntryListener;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
@@ -69,7 +68,6 @@ import java.util.Objects;
import java.util.Set;
import javax.inject.Inject;
-import javax.inject.Named;
import javax.inject.Singleton;
import dagger.Lazy;
@@ -262,7 +260,7 @@ public class NotificationRemoteInputManager implements Dumpable {
NotificationEntryManager notificationEntryManager,
Lazy<ShadeController> shadeController,
StatusBarStateController statusBarStateController,
- @Named(MAIN_HANDLER_NAME) Handler mainHandler) {
+ @MainHandler Handler mainHandler) {
mContext = context;
mLockscreenUserManager = lockscreenUserManager;
mSmartReplyController = smartReplyController;
@@ -293,7 +291,7 @@ public class NotificationRemoteInputManager implements Dumpable {
mSmartReplyController.stopSending(entry);
if (removedByUser && entry != null) {
- onPerformRemoveNotification(entry, entry.key);
+ onPerformRemoveNotification(entry, entry.getKey());
}
}
});
@@ -307,8 +305,8 @@ public class NotificationRemoteInputManager implements Dumpable {
@Override
public void onRemoteInputSent(NotificationEntry entry) {
if (FORCE_REMOTE_INPUT_HISTORY
- && isNotificationKeptForRemoteInputHistory(entry.key)) {
- mNotificationLifetimeFinishedCallback.onSafeToRemove(entry.key);
+ && isNotificationKeptForRemoteInputHistory(entry.getKey())) {
+ mNotificationLifetimeFinishedCallback.onSafeToRemove(entry.getKey());
} else if (mEntriesKeptForRemoteInputActive.contains(entry)) {
// We're currently holding onto this notification, but from the apps point of
// view it is already canceled, so we'll need to cancel it on the apps behalf
@@ -316,18 +314,18 @@ public class NotificationRemoteInputManager implements Dumpable {
// bit.
mMainHandler.postDelayed(() -> {
if (mEntriesKeptForRemoteInputActive.remove(entry)) {
- mNotificationLifetimeFinishedCallback.onSafeToRemove(entry.key);
+ mNotificationLifetimeFinishedCallback.onSafeToRemove(entry.getKey());
}
}, REMOTE_INPUT_KEPT_ENTRY_AUTO_CANCEL_DELAY);
}
try {
- mBarService.onNotificationDirectReplied(entry.notification.getKey());
+ mBarService.onNotificationDirectReplied(entry.getSbn().getKey());
if (entry.editedSuggestionInfo != null) {
boolean modifiedBeforeSending =
!TextUtils.equals(entry.remoteInputText,
entry.editedSuggestionInfo.originalText);
mBarService.onNotificationSmartReplySent(
- entry.notification.getKey(),
+ entry.getSbn().getKey(),
entry.editedSuggestionInfo.index,
entry.editedSuggestionInfo.originalText,
NotificationLogger
@@ -487,7 +485,7 @@ public class NotificationRemoteInputManager implements Dumpable {
NotificationEntry entry = mEntriesKeptForRemoteInputActive.valueAt(i);
mRemoteInputController.removeRemoteInput(entry, null);
if (mNotificationLifetimeFinishedCallback != null) {
- mNotificationLifetimeFinishedCallback.onSafeToRemove(entry.key);
+ mNotificationLifetimeFinishedCallback.onSafeToRemove(entry.getKey());
}
}
mEntriesKeptForRemoteInputActive.clear();
@@ -501,14 +499,15 @@ public class NotificationRemoteInputManager implements Dumpable {
if (!FORCE_REMOTE_INPUT_HISTORY) {
return false;
}
- return (mRemoteInputController.isSpinning(entry.key) || entry.hasJustSentRemoteInput());
+ return (mRemoteInputController.isSpinning(entry.getKey())
+ || entry.hasJustSentRemoteInput());
}
public boolean shouldKeepForSmartReplyHistory(NotificationEntry entry) {
if (!FORCE_REMOTE_INPUT_HISTORY) {
return false;
}
- return mSmartReplyController.isSendingSmartReply(entry.key);
+ return mSmartReplyController.isSendingSmartReply(entry.getKey());
}
public void checkRemoteInputOutside(MotionEvent event) {
@@ -529,7 +528,7 @@ public class NotificationRemoteInputManager implements Dumpable {
@VisibleForTesting
StatusBarNotification rebuildNotificationWithRemoteInput(NotificationEntry entry,
CharSequence remoteInputText, boolean showSpinner) {
- StatusBarNotification sbn = entry.notification;
+ StatusBarNotification sbn = entry.getSbn();
Notification.Builder b = Notification.Builder
.recoverBuilder(mContext, sbn.getNotification().clone());
@@ -637,12 +636,12 @@ public class NotificationRemoteInputManager implements Dumpable {
if (Log.isLoggable(TAG, Log.DEBUG)) {
Log.d(TAG, "Keeping notification around after sending remote input "
- + entry.key);
+ + entry.getKey());
}
- mKeysKeptForRemoteInputHistory.add(entry.key);
+ mKeysKeptForRemoteInputHistory.add(entry.getKey());
} else {
- mKeysKeptForRemoteInputHistory.remove(entry.key);
+ mKeysKeptForRemoteInputHistory.remove(entry.getKey());
}
}
}
@@ -675,12 +674,12 @@ public class NotificationRemoteInputManager implements Dumpable {
if (Log.isLoggable(TAG, Log.DEBUG)) {
Log.d(TAG, "Keeping notification around after sending smart reply "
- + entry.key);
+ + entry.getKey());
}
- mKeysKeptForRemoteInputHistory.add(entry.key);
+ mKeysKeptForRemoteInputHistory.add(entry.getKey());
} else {
- mKeysKeptForRemoteInputHistory.remove(entry.key);
+ mKeysKeptForRemoteInputHistory.remove(entry.getKey());
mSmartReplyController.stopSending(entry);
}
}
@@ -701,7 +700,7 @@ public class NotificationRemoteInputManager implements Dumpable {
if (shouldExtend) {
if (Log.isLoggable(TAG, Log.DEBUG)) {
Log.d(TAG, "Keeping notification around while remote input active "
- + entry.key);
+ + entry.getKey());
}
mEntriesKeptForRemoteInputActive.add(entry);
} else {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationUiAdjustment.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationUiAdjustment.java
index 266fe8dc2708..564d8bc14c8c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationUiAdjustment.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationUiAdjustment.java
@@ -54,7 +54,7 @@ public class NotificationUiAdjustment {
public static NotificationUiAdjustment extractFromNotificationEntry(
NotificationEntry entry) {
return new NotificationUiAdjustment(
- entry.key, entry.getSmartActions(), entry.getSmartReplies());
+ entry.getKey(), entry.getSmartActions(), entry.getSmartReplies());
}
public static boolean needReinflate(
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java
index 50d9bae77bea..d6b87afc53b9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java
@@ -16,19 +16,19 @@
package com.android.systemui.statusbar;
-import static com.android.systemui.Dependency.MAIN_HANDLER_NAME;
-
import android.content.Context;
import android.content.res.Resources;
import android.os.Handler;
import android.os.Trace;
import android.os.UserHandle;
+import android.provider.Settings;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import com.android.systemui.R;
import com.android.systemui.bubbles.BubbleController;
+import com.android.systemui.dagger.qualifiers.MainHandler;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.notification.DynamicPrivacyController;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
@@ -47,7 +47,6 @@ import java.util.List;
import java.util.Stack;
import javax.inject.Inject;
-import javax.inject.Named;
import javax.inject.Singleton;
import dagger.Lazy;
@@ -88,6 +87,7 @@ public class NotificationViewHierarchyManager implements DynamicPrivacyControlle
private final BubbleController mBubbleController;
private final DynamicPrivacyController mDynamicPrivacyController;
private final KeyguardBypassController mBypassController;
+ private final Context mContext;
private NotificationPresenter mPresenter;
private NotificationListContainer mListContainer;
@@ -99,8 +99,7 @@ public class NotificationViewHierarchyManager implements DynamicPrivacyControlle
private boolean mIsHandleDynamicPrivacyChangeScheduled;
@Inject
- public NotificationViewHierarchyManager(Context context,
- @Named(MAIN_HANDLER_NAME) Handler mainHandler,
+ public NotificationViewHierarchyManager(Context context, @MainHandler Handler mainHandler,
NotificationLockscreenUserManager notificationLockscreenUserManager,
NotificationGroupManager groupManager,
VisualStabilityManager visualStabilityManager,
@@ -110,6 +109,7 @@ public class NotificationViewHierarchyManager implements DynamicPrivacyControlle
KeyguardBypassController bypassController,
BubbleController bubbleController,
DynamicPrivacyController privacyController) {
+ mContext = context;
mHandler = mainHandler;
mLockscreenUserManager = notificationLockscreenUserManager;
mBypassController = bypassController;
@@ -146,14 +146,18 @@ public class NotificationViewHierarchyManager implements DynamicPrivacyControlle
final int N = activeNotifications.size();
for (int i = 0; i < N; i++) {
NotificationEntry ent = activeNotifications.get(i);
+ int flag = Settings.System.getInt(mContext.getContentResolver(),
+ "qs_media_player", 0);
+ boolean hideMedia = (flag == 1);
if (ent.isRowDismissed() || ent.isRowRemoved()
- || mBubbleController.isBubbleNotificationSuppressedFromShade(ent.key)) {
+ || (ent.isMediaNotification() && hideMedia)
+ || mBubbleController.isBubbleNotificationSuppressedFromShade(ent.getKey())) {
// we don't want to update removed notifications because they could
// temporarily become children if they were isolated before.
continue;
}
- int userId = ent.notification.getUserId();
+ int userId = ent.getSbn().getUserId();
// Display public version of the notification if we need to redact.
// TODO: This area uses a lot of calls into NotificationLockscreenUserManager.
@@ -174,8 +178,8 @@ public class NotificationViewHierarchyManager implements DynamicPrivacyControlle
currentUserId);
ent.setSensitive(sensitive, deviceSensitive);
ent.getRow().setNeedsRedaction(needsRedaction);
- if (mGroupManager.isChildInGroupWithSummary(ent.notification)) {
- NotificationEntry summary = mGroupManager.getGroupSummary(ent.notification);
+ if (mGroupManager.isChildInGroupWithSummary(ent.getSbn())) {
+ NotificationEntry summary = mGroupManager.getGroupSummary(ent.getSbn());
List<ExpandableNotificationRow> orderedChildren =
mTmpChildOrderMap.get(summary.getRow());
if (orderedChildren == null) {
@@ -382,7 +386,7 @@ public class NotificationViewHierarchyManager implements DynamicPrivacyControlle
ExpandableNotificationRow row = stack.pop();
NotificationEntry entry = row.getEntry();
boolean isChildNotification =
- mGroupManager.isChildInGroupWithSummary(entry.notification);
+ mGroupManager.isChildInGroupWithSummary(entry.getSbn());
row.setOnKeyguard(onKeyguard);
@@ -394,15 +398,15 @@ public class NotificationViewHierarchyManager implements DynamicPrivacyControlle
&& !row.isLowPriority()));
}
- int userId = entry.notification.getUserId();
+ int userId = entry.getSbn().getUserId();
boolean suppressedSummary = mGroupManager.isSummaryOfSuppressedGroup(
- entry.notification) && !entry.isRowRemoved();
+ entry.getSbn()) && !entry.isRowRemoved();
boolean showOnKeyguard = mLockscreenUserManager.shouldShowOnKeyguard(entry);
if (!showOnKeyguard) {
// min priority notifications should show if their summary is showing
- if (mGroupManager.isChildInGroupWithSummary(entry.notification)) {
+ if (mGroupManager.isChildInGroupWithSummary(entry.getSbn())) {
NotificationEntry summary = mGroupManager.getLogicalGroupSummary(
- entry.notification);
+ entry.getSbn());
if (summary != null && mLockscreenUserManager.shouldShowOnKeyguard(summary)) {
showOnKeyguard = true;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/PulseExpansionHandler.kt b/packages/SystemUI/src/com/android/systemui/statusbar/PulseExpansionHandler.kt
index a70dc7c0ec5d..e516af590e34 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/PulseExpansionHandler.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/PulseExpansionHandler.kt
@@ -27,7 +27,6 @@ import android.os.SystemClock
import android.view.MotionEvent
import android.view.VelocityTracker
import android.view.ViewConfiguration
-import com.android.systemui.Dependency
import com.android.systemui.Gefingerpoken
import com.android.systemui.Interpolators
@@ -58,7 +57,8 @@ constructor(
private val bypassController: KeyguardBypassController,
private val headsUpManager: HeadsUpManagerPhone,
private val roundnessManager: NotificationRoundnessManager,
- private val statusBarStateController: StatusBarStateController
+ private val statusBarStateController: StatusBarStateController,
+ private val falsingManager: FalsingManager
) : Gefingerpoken {
companion object {
private val RUBBERBAND_FACTOR_STATIC = 0.25f
@@ -99,7 +99,6 @@ constructor(
private val mTemp2 = IntArray(2)
private var mDraggedFarEnough: Boolean = false
private var mStartingChild: ExpandableView? = null
- private val mFalsingManager: FalsingManager
private var mPulsing: Boolean = false
var isWakingToShadeLocked: Boolean = false
private set
@@ -109,7 +108,7 @@ constructor(
private var velocityTracker: VelocityTracker? = null
private val isFalseTouch: Boolean
- get() = mFalsingManager.isFalseTouch
+ get() = falsingManager.isFalseTouch
var qsExpanded: Boolean = false
var pulseExpandAbortListener: Runnable? = null
var bouncerShowing: Boolean = false
@@ -118,7 +117,6 @@ constructor(
mMinDragDistance = context.resources.getDimensionPixelSize(
R.dimen.keyguard_drag_down_min_distance)
mTouchSlop = ViewConfiguration.get(context).scaledTouchSlop.toFloat()
- mFalsingManager = Dependency.get(FalsingManager::class.java)
mPowerManager = context.getSystemService(PowerManager::class.java)
}
@@ -151,7 +149,7 @@ constructor(
MotionEvent.ACTION_MOVE -> {
val h = y - mInitialTouchY
if (h > mTouchSlop && h > Math.abs(x - mInitialTouchX)) {
- mFalsingManager.onStartExpandingFromPulse()
+ falsingManager.onStartExpandingFromPulse()
isExpanding = true
captureStartingChild(mInitialTouchX, mInitialTouchY)
mInitialTouchY = y
@@ -192,7 +190,7 @@ constructor(
velocityTracker!!.computeCurrentVelocity(1000 /* units */)
val canExpand = moveDistance > 0 && velocityTracker!!.getYVelocity() > -1000 &&
statusBarStateController.state != StatusBarState.SHADE
- if (!mFalsingManager.isUnlockingDisabled && !isFalseTouch && canExpand) {
+ if (!falsingManager.isUnlockingDisabled && !isFalseTouch && canExpand) {
finishExpansion()
} else {
cancelExpansion()
@@ -297,7 +295,7 @@ constructor(
private fun cancelExpansion() {
isExpanding = false
- mFalsingManager.onExpansionFromPulseStopped()
+ falsingManager.onExpansionFromPulseStopped()
if (mStartingChild != null) {
reset(mStartingChild!!)
mStartingChild = null
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/SmartReplyController.java b/packages/SystemUI/src/com/android/systemui/statusbar/SmartReplyController.java
index 736b9ebea5c3..7bdb21d0eac5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/SmartReplyController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/SmartReplyController.java
@@ -58,9 +58,9 @@ public class SmartReplyController {
public void smartReplySent(NotificationEntry entry, int replyIndex, CharSequence reply,
int notificationLocation, boolean modifiedBeforeSending) {
mCallback.onSmartReplySent(entry, reply);
- mSendingKeys.add(entry.key);
+ mSendingKeys.add(entry.getKey());
try {
- mBarService.onNotificationSmartReplySent(entry.notification.getKey(), replyIndex, reply,
+ mBarService.onNotificationSmartReplySent(entry.getSbn().getKey(), replyIndex, reply,
notificationLocation, modifiedBeforeSending);
} catch (RemoteException e) {
// Nothing to do, system going down
@@ -74,14 +74,14 @@ public class SmartReplyController {
NotificationEntry entry, int actionIndex, Notification.Action action,
boolean generatedByAssistant) {
final int count = mEntryManager.getNotificationData().getActiveNotifications().size();
- final int rank = mEntryManager.getNotificationData().getRank(entry.key);
+ final int rank = mEntryManager.getNotificationData().getRank(entry.getKey());
NotificationVisibility.NotificationLocation location =
NotificationLogger.getNotificationLocation(entry);
final NotificationVisibility nv = NotificationVisibility.obtain(
- entry.key, rank, count, true, location);
+ entry.getKey(), rank, count, true, location);
try {
mBarService.onNotificationActionClick(
- entry.key, actionIndex, action, nv, generatedByAssistant);
+ entry.getKey(), actionIndex, action, nv, generatedByAssistant);
} catch (RemoteException e) {
// Nothing to do, system going down
}
@@ -101,7 +101,7 @@ public class SmartReplyController {
public void smartSuggestionsAdded(final NotificationEntry entry, int replyCount,
int actionCount, boolean generatedByAssistant, boolean editBeforeSending) {
try {
- mBarService.onNotificationSmartSuggestionsAdded(entry.notification.getKey(), replyCount,
+ mBarService.onNotificationSmartSuggestionsAdded(entry.getSbn().getKey(), replyCount,
actionCount, generatedByAssistant, editBeforeSending);
} catch (RemoteException e) {
// Nothing to do, system going down
@@ -110,7 +110,7 @@ public class SmartReplyController {
public void stopSending(final NotificationEntry entry) {
if (entry != null) {
- mSendingKeys.remove(entry.notification.getKey());
+ mSendingKeys.remove(entry.getSbn().getKey());
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateControllerImpl.java
index 8b9268e1888a..e81e5cae5bfc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateControllerImpl.java
@@ -21,7 +21,6 @@ import android.animation.ValueAnimator;
import android.text.format.DateFormat;
import android.util.FloatProperty;
import android.util.Log;
-import android.view.View;
import android.view.animation.Interpolator;
import com.android.internal.annotations.GuardedBy;
@@ -80,9 +79,14 @@ public class StatusBarStateControllerImpl implements SysuiStatusBarStateControll
private HistoricalState[] mHistoricalRecords = new HistoricalState[HISTORY_SIZE];
/**
- * Current SystemUiVisibility
+ * If any of the system bars is hidden.
*/
- private int mSystemUiVisibility = View.SYSTEM_UI_FLAG_VISIBLE;
+ private boolean mIsFullscreen = false;
+
+ /**
+ * If the navigation bar can stay hidden when the display gets tapped.
+ */
+ private boolean mIsImmersive = false;
/**
* If the device is currently pulsing (AOD2).
@@ -320,12 +324,13 @@ public class StatusBarStateControllerImpl implements SysuiStatusBarStateControll
}
@Override
- public void setSystemUiVisibility(int visibility) {
- if (mSystemUiVisibility != visibility) {
- mSystemUiVisibility = visibility;
+ public void setFullscreenState(boolean isFullscreen, boolean isImmersive) {
+ if (mIsFullscreen != isFullscreen || mIsImmersive != isImmersive) {
+ mIsFullscreen = isFullscreen;
+ mIsImmersive = isImmersive;
synchronized (mListeners) {
for (RankedListener rl : new ArrayList<>(mListeners)) {
- rl.mListener.onSystemUiVisibilityChanged(mSystemUiVisibility);
+ rl.mListener.onFullscreenStateChanged(isFullscreen, isImmersive);
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/SysuiStatusBarStateController.java b/packages/SystemUI/src/com/android/systemui/statusbar/SysuiStatusBarStateController.java
index 2ad979ab64e3..07b35502478f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/SysuiStatusBarStateController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/SysuiStatusBarStateController.java
@@ -111,9 +111,9 @@ public interface SysuiStatusBarStateController extends StatusBarStateController
boolean isKeyguardRequested();
/**
- * Set systemui visibility
+ * Set the fullscreen state
*/
- void setSystemUiVisibility(int visibility);
+ void setFullscreenState(boolean isFullscreen, boolean isImmersive);
/**
* Set pulsing
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/ActivityLaunchAnimator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/ActivityLaunchAnimator.java
index 13c6f2730d08..9b312341c583 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/ActivityLaunchAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/ActivityLaunchAnimator.java
@@ -38,7 +38,7 @@ import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
import com.android.systemui.statusbar.phone.CollapsedStatusBarFragment;
import com.android.systemui.statusbar.phone.NotificationPanelView;
-import com.android.systemui.statusbar.phone.StatusBarWindowView;
+import com.android.systemui.statusbar.phone.StatusBarWindowViewController;
/**
* A class that allows activities to be launched in a seamless way where the notification
@@ -55,8 +55,8 @@ public class ActivityLaunchAnimator {
private static final long LAUNCH_TIMEOUT = 500;
private final NotificationPanelView mNotificationPanel;
private final NotificationListContainer mNotificationContainer;
- private final StatusBarWindowView mStatusBarWindow;
private final float mWindowCornerRadius;
+ private final StatusBarWindowViewController mStatusBarWindowViewController;
private Callback mCallback;
private final Runnable mTimeoutRunnable = () -> {
setAnimationPending(false);
@@ -66,16 +66,17 @@ public class ActivityLaunchAnimator {
private boolean mAnimationRunning;
private boolean mIsLaunchForActivity;
- public ActivityLaunchAnimator(StatusBarWindowView statusBarWindow,
+ public ActivityLaunchAnimator(
+ StatusBarWindowViewController statusBarWindowViewController,
Callback callback,
NotificationPanelView notificationPanel,
NotificationListContainer container) {
mNotificationPanel = notificationPanel;
mNotificationContainer = container;
- mStatusBarWindow = statusBarWindow;
+ mStatusBarWindowViewController = statusBarWindowViewController;
mCallback = callback;
mWindowCornerRadius = ScreenDecorationsUtils
- .getWindowCornerRadius(statusBarWindow.getResources());
+ .getWindowCornerRadius(mStatusBarWindowViewController.getView().getResources());
}
public RemoteAnimationAdapter getLaunchAnimation(
@@ -112,11 +113,11 @@ public class ActivityLaunchAnimator {
private void setAnimationPending(boolean pending) {
mAnimationPending = pending;
- mStatusBarWindow.setExpandAnimationPending(pending);
+ mStatusBarWindowViewController.setExpandAnimationPending(pending);
if (pending) {
- mStatusBarWindow.postDelayed(mTimeoutRunnable, LAUNCH_TIMEOUT);
+ mStatusBarWindowViewController.getView().postDelayed(mTimeoutRunnable, LAUNCH_TIMEOUT);
} else {
- mStatusBarWindow.removeCallbacks(mTimeoutRunnable);
+ mStatusBarWindowViewController.getView().removeCallbacks(mTimeoutRunnable);
}
}
@@ -246,7 +247,7 @@ public class ActivityLaunchAnimator {
private void setExpandAnimationRunning(boolean running) {
mNotificationPanel.setLaunchingNotification(running);
mSourceNotification.setExpandAnimationRunning(running);
- mStatusBarWindow.setExpandAnimationRunning(running);
+ mStatusBarWindowViewController.setExpandAnimationRunning(running);
mNotificationContainer.setExpandingNotification(running ? mSourceNotification : null);
mAnimationRunning = running;
if (!running) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/DynamicPrivacyController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/DynamicPrivacyController.java
index e4bd4fa1ae75..a0b144b4497c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/DynamicPrivacyController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/DynamicPrivacyController.java
@@ -16,16 +16,13 @@
package com.android.systemui.statusbar.notification;
-import android.content.Context;
import android.util.ArraySet;
-import com.android.internal.annotations.VisibleForTesting;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
-import com.android.systemui.statusbar.phone.UnlockMethodCache;
-import com.android.systemui.statusbar.policy.KeyguardMonitor;
+import com.android.systemui.statusbar.policy.KeyguardStateController;
import javax.inject.Inject;
import javax.inject.Singleton;
@@ -34,12 +31,11 @@ import javax.inject.Singleton;
* A controller which dynamically controls the visibility of Notification content
*/
@Singleton
-public class DynamicPrivacyController implements UnlockMethodCache.OnUnlockMethodChangedListener {
+public class DynamicPrivacyController implements KeyguardStateController.Callback {
- private final UnlockMethodCache mUnlockMethodCache;
+ private final KeyguardStateController mKeyguardStateController;
private final NotificationLockscreenUserManager mLockscreenUserManager;
private final StatusBarStateController mStateController;
- private final KeyguardMonitor mKeyguardMonitor;
private ArraySet<Listener> mListeners = new ArraySet<>();
private boolean mLastDynamicUnlocked;
@@ -47,30 +43,18 @@ public class DynamicPrivacyController implements UnlockMethodCache.OnUnlockMetho
private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
@Inject
- DynamicPrivacyController(Context context,
- KeyguardMonitor keyguardMonitor,
- NotificationLockscreenUserManager notificationLockscreenUserManager,
- StatusBarStateController stateController) {
- this(notificationLockscreenUserManager, keyguardMonitor,
- UnlockMethodCache.getInstance(context),
- stateController);
- }
-
- @VisibleForTesting
DynamicPrivacyController(NotificationLockscreenUserManager notificationLockscreenUserManager,
- KeyguardMonitor keyguardMonitor,
- UnlockMethodCache unlockMethodCache,
+ KeyguardStateController keyguardStateController,
StatusBarStateController stateController) {
mLockscreenUserManager = notificationLockscreenUserManager;
mStateController = stateController;
- mUnlockMethodCache = unlockMethodCache;
- mKeyguardMonitor = keyguardMonitor;
- mUnlockMethodCache.addListener(this);
+ mKeyguardStateController = keyguardStateController;
+ mKeyguardStateController.addCallback(this);
mLastDynamicUnlocked = isDynamicallyUnlocked();
}
@Override
- public void onUnlockMethodStateChanged() {
+ public void onUnlockedChanged() {
if (isDynamicPrivacyEnabled()) {
// We only want to notify our listeners if dynamic privacy is actually active
boolean dynamicallyUnlocked = isDynamicallyUnlocked();
@@ -92,8 +76,9 @@ public class DynamicPrivacyController implements UnlockMethodCache.OnUnlockMetho
}
public boolean isDynamicallyUnlocked() {
- return (mUnlockMethodCache.canSkipBouncer() || mKeyguardMonitor.isKeyguardGoingAway()
- || mKeyguardMonitor.isKeyguardFadingAway())
+ return (mKeyguardStateController.canDismissLockScreen()
+ || mKeyguardStateController.isKeyguardGoingAway()
+ || mKeyguardStateController.isKeyguardFadingAway())
&& isDynamicPrivacyEnabled();
}
@@ -107,7 +92,7 @@ public class DynamicPrivacyController implements UnlockMethodCache.OnUnlockMetho
*/
public boolean isInLockedDownShade() {
if (!mStatusBarKeyguardViewManager.isShowing()
- || !mUnlockMethodCache.isMethodSecure()) {
+ || !mKeyguardStateController.isMethodSecure()) {
return false;
}
int state = mStateController.getState();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/InstantAppNotifier.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/InstantAppNotifier.java
index f3201ec73d63..f284f737b26d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/InstantAppNotifier.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/InstantAppNotifier.java
@@ -31,6 +31,7 @@ import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.SynchronousUserSwitchObserver;
import android.content.ComponentName;
+import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.IPackageManager;
@@ -55,16 +56,16 @@ import com.android.systemui.SysUiServiceProvider;
import com.android.systemui.SystemUI;
import com.android.systemui.UiOffloadThread;
import com.android.systemui.statusbar.CommandQueue;
-import com.android.systemui.statusbar.policy.KeyguardMonitor;
+import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.util.NotificationChannels;
import java.util.List;
-/** The clsss to show notification(s) of instant apps. This may show multiple notifications on
+/** The class to show notification(s) of instant apps. This may show multiple notifications on
* splitted screen.
*/
public class InstantAppNotifier extends SystemUI
- implements CommandQueue.Callbacks, KeyguardMonitor.Callback {
+ implements CommandQueue.Callbacks, KeyguardStateController.Callback {
private static final String TAG = "InstantAppNotifier";
public static final int NUM_TASKS_FOR_INSTANT_APP_INFO = 5;
@@ -72,13 +73,15 @@ public class InstantAppNotifier extends SystemUI
private final UiOffloadThread mUiOffloadThread = Dependency.get(UiOffloadThread.class);
private final ArraySet<Pair<String, Integer>> mCurrentNotifs = new ArraySet<>();
private boolean mDockedStackExists;
- private KeyguardMonitor mKeyguardMonitor;
+ private KeyguardStateController mKeyguardStateController;
- public InstantAppNotifier() {}
+ public InstantAppNotifier(Context context) {
+ super(context);
+ }
@Override
public void start() {
- mKeyguardMonitor = Dependency.get(KeyguardMonitor.class);
+ mKeyguardStateController = Dependency.get(KeyguardStateController.class);
// listen for user / profile change.
try {
@@ -88,7 +91,7 @@ public class InstantAppNotifier extends SystemUI
}
SysUiServiceProvider.getComponent(mContext, CommandQueue.class).addCallback(this);
- mKeyguardMonitor.addCallback(this);
+ mKeyguardStateController.addCallback(this);
DockedStackExistsListener.register(
exists -> {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NewNotifPipeline.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NewNotifPipeline.java
new file mode 100644
index 000000000000..31921a436747
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NewNotifPipeline.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.notification;
+
+import android.util.Log;
+
+import com.android.systemui.statusbar.NotificationListener;
+import com.android.systemui.statusbar.notification.collection.NotifCollection;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+/**
+ * Initialization code for the new notification pipeline.
+ */
+@Singleton
+public class NewNotifPipeline {
+ private final NotifCollection mNotifCollection;
+
+ @Inject
+ public NewNotifPipeline(
+ NotifCollection notifCollection) {
+ mNotifCollection = notifCollection;
+ }
+
+ /** Hooks the new pipeline up to NotificationManager */
+ public void initialize(
+ NotificationListener notificationService) {
+ mNotifCollection.attach(notificationService);
+
+ Log.d(TAG, "Notif pipeline initialized");
+ }
+
+ private static final String TAG = "NewNotifPipeline";
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationAlertingManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationAlertingManager.java
index d71d40781f2e..005f01dc8df0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationAlertingManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationAlertingManager.java
@@ -80,7 +80,7 @@ public class NotificationAlertingManager {
NotificationEntry entry,
NotificationVisibility visibility,
boolean removedByUser) {
- stopAlerting(entry.key);
+ stopAlerting(entry.getKey());
}
});
}
@@ -104,7 +104,7 @@ public class NotificationAlertingManager {
mHeadsUpManager.showNotification(entry);
if (!mShadeController.get().isDozing()) {
// Mark as seen immediately
- setNotificationShown(entry.notification);
+ setNotificationShown(entry.getSbn());
}
} else {
entry.freeContentViewWhenSafe(FLAG_CONTENT_VIEW_HEADS_UP);
@@ -113,16 +113,16 @@ public class NotificationAlertingManager {
}
private void updateAlertState(NotificationEntry entry) {
- boolean alertAgain = alertAgain(entry, entry.notification.getNotification());
+ boolean alertAgain = alertAgain(entry, entry.getSbn().getNotification());
boolean shouldAlert;
shouldAlert = mNotificationInterruptionStateProvider.shouldHeadsUp(entry);
- final boolean wasAlerting = mHeadsUpManager.isAlerting(entry.key);
+ final boolean wasAlerting = mHeadsUpManager.isAlerting(entry.getKey());
if (wasAlerting) {
if (shouldAlert) {
- mHeadsUpManager.updateNotification(entry.key, alertAgain);
- } else if (!mHeadsUpManager.isEntryAutoHeadsUpped(entry.key)) {
+ mHeadsUpManager.updateNotification(entry.getKey(), alertAgain);
+ } else if (!mHeadsUpManager.isEntryAutoHeadsUpped(entry.getKey())) {
// We don't want this to be interrupting anymore, let's remove it
- mHeadsUpManager.removeNotification(entry.key, false /* removeImmediately */);
+ mHeadsUpManager.removeNotification(entry.getKey(), false /* removeImmediately */);
}
} else if (shouldAlert && alertAgain) {
// This notification was updated to be alerting, show it!
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java
index b6b149dd049a..b4dc538f8e0c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java
@@ -20,8 +20,8 @@ import static android.service.notification.NotificationListenerService.REASON_ER
import android.annotation.Nullable;
import android.app.Notification;
-import android.content.Context;
import android.service.notification.NotificationListenerService;
+import android.service.notification.NotificationListenerService.Ranking;
import android.service.notification.StatusBarNotification;
import android.util.ArrayMap;
import android.util.Log;
@@ -40,6 +40,8 @@ import com.android.systemui.statusbar.notification.collection.NotificationData;
import com.android.systemui.statusbar.notification.collection.NotificationData.KeyguardEnvironment;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.NotificationRowBinder;
+import com.android.systemui.statusbar.notification.logging.NotifEvent;
+import com.android.systemui.statusbar.notification.logging.NotifLog;
import com.android.systemui.statusbar.notification.logging.NotificationLogger;
import com.android.systemui.statusbar.notification.row.NotificationContentInflater;
import com.android.systemui.statusbar.notification.row.NotificationContentInflater.InflationFlag;
@@ -92,6 +94,7 @@ public class NotificationEntryManager implements
private NotificationListenerService.RankingMap mLatestRankingMap;
@VisibleForTesting
protected NotificationData mNotificationData;
+ private NotifLog mNotifLog;
@VisibleForTesting
final ArrayList<NotificationLifetimeExtender> mNotificationLifetimeExtenders
@@ -107,7 +110,7 @@ public class NotificationEntryManager implements
pw.println("null");
} else {
for (NotificationEntry entry : mPendingNotifications.values()) {
- pw.println(entry.notification);
+ pw.println(entry.getSbn());
}
}
pw.println(" Lifetime-extended notifications:");
@@ -116,15 +119,18 @@ public class NotificationEntryManager implements
} else {
for (Map.Entry<NotificationEntry, NotificationLifetimeExtender> entry
: mRetainedNotifications.entrySet()) {
- pw.println(" " + entry.getKey().notification + " retained by "
+ pw.println(" " + entry.getKey().getSbn() + " retained by "
+ entry.getValue().getClass().getName());
}
}
}
@Inject
- public NotificationEntryManager(Context context) {
- mNotificationData = new NotificationData(context);
+ public NotificationEntryManager(
+ NotificationData notificationData,
+ NotifLog notifLog) {
+ mNotificationData = notificationData;
+ mNotifLog = notifLog;
}
/** Adds a {@link NotificationEntryListener}. */
@@ -132,6 +138,14 @@ public class NotificationEntryManager implements
mNotificationEntryListeners.add(listener);
}
+ /**
+ * Removes a {@link NotificationEntryListener} previously registered via
+ * {@link #addNotificationEntryListener(NotificationEntryListener)}.
+ */
+ public void removeNotificationEntryListener(NotificationEntryListener listener) {
+ mNotificationEntryListeners.remove(listener);
+ }
+
/** Sets the {@link NotificationRemoveInterceptor}. */
public void setNotificationRemoveInterceptor(NotificationRemoveInterceptor interceptor) {
mRemoveInterceptor = interceptor;
@@ -178,7 +192,7 @@ public class NotificationEntryManager implements
@Override
public void onReorderingAllowed() {
- updateNotifications();
+ updateNotifications("reordering is now allowed");
}
/**
@@ -203,15 +217,19 @@ public class NotificationEntryManager implements
return NotificationVisibility.obtain(key, rank, count, true, location);
}
- private void abortExistingInflation(String key) {
+ private void abortExistingInflation(String key, String reason) {
if (mPendingNotifications.containsKey(key)) {
NotificationEntry entry = mPendingNotifications.get(key);
entry.abortTask();
mPendingNotifications.remove(key);
+ mNotifLog.log(NotifEvent.INFLATION_ABORTED, entry.getSbn(), null,
+ "PendingNotification aborted. " + reason);
}
NotificationEntry addedEntry = mNotificationData.get(key);
if (addedEntry != null) {
addedEntry.abortTask();
+ mNotifLog.log(NotifEvent.INFLATION_ABORTED, addedEntry.getSbn(),
+ null, reason);
}
}
@@ -234,11 +252,11 @@ public class NotificationEntryManager implements
@Override
public void onAsyncInflationFinished(NotificationEntry entry,
@InflationFlag int inflatedFlags) {
- mPendingNotifications.remove(entry.key);
+ mPendingNotifications.remove(entry.getKey());
// If there was an async task started after the removal, we don't want to add it back to
// the list, otherwise we might get leaks.
if (!entry.isRowRemoved()) {
- boolean isNew = mNotificationData.get(entry.key) == null;
+ boolean isNew = mNotificationData.get(entry.getKey()) == null;
if (isNew) {
for (NotificationEntryListener listener : mNotificationEntryListeners) {
listener.onEntryInflated(entry, inflatedFlags);
@@ -247,7 +265,7 @@ public class NotificationEntryManager implements
for (NotificationEntryListener listener : mNotificationEntryListeners) {
listener.onBeforeNotificationAdded(entry);
}
- updateNotifications();
+ updateNotifications("onAsyncInflationFinished");
for (NotificationEntryListener listener : mNotificationEntryListeners) {
listener.onNotificationAdded(entry);
}
@@ -276,7 +294,8 @@ public class NotificationEntryManager implements
if (mRemoveInterceptor != null
&& mRemoveInterceptor.onNotificationRemoveRequested(key, reason)) {
- // Remove intercepted; skip
+ // Remove intercepted; log and skip
+ mNotifLog.log(NotifEvent.REMOVE_INTERCEPTED);
return;
}
@@ -291,13 +310,17 @@ public class NotificationEntryManager implements
if (extender.shouldExtendLifetimeForPendingNotification(pendingEntry)) {
extendLifetime(pendingEntry, extender);
lifetimeExtended = true;
+ mNotifLog.log(
+ NotifEvent.LIFETIME_EXTENDED,
+ pendingEntry.getSbn(),
+ "pendingEntry extendedBy=" + extender.toString());
}
}
}
}
if (!lifetimeExtended) {
- abortExistingInflation(key);
+ abortExistingInflation(key, "removeNotification");
}
if (entry != null) {
@@ -310,6 +333,10 @@ public class NotificationEntryManager implements
mLatestRankingMap = ranking;
extendLifetime(entry, extender);
lifetimeExtended = true;
+ mNotifLog.log(
+ NotifEvent.LIFETIME_EXTENDED,
+ entry.getSbn(),
+ "entry extendedBy=" + extender.toString());
break;
}
}
@@ -329,10 +356,12 @@ public class NotificationEntryManager implements
handleGroupSummaryRemoved(key);
mNotificationData.remove(key, ranking);
- updateNotifications();
+ updateNotifications("removeNotificationInternal");
Dependency.get(LeakDetector.class).trackGarbage(entry);
removedByUser |= entryDismissed;
+ mNotifLog.log(NotifEvent.NOTIF_REMOVED, entry.getSbn(),
+ "removedByUser=" + removedByUser);
for (NotificationEntryListener listener : mNotificationEntryListeners) {
listener.onEntryRemoved(entry, visibility, removedByUser);
}
@@ -353,7 +382,7 @@ public class NotificationEntryManager implements
private void handleGroupSummaryRemoved(String key) {
NotificationEntry entry = mNotificationData.get(key);
if (entry != null && entry.rowExists() && entry.isSummaryWithChildren()) {
- if (entry.notification.getOverrideGroupKey() != null && !entry.isRowDismissed()) {
+ if (entry.getSbn().getOverrideGroupKey() != null && !entry.isRowDismissed()) {
// We don't want to remove children for autobundled notifications as they are not
// always cancelled. We only remove them if they were dismissed by the user.
return;
@@ -364,7 +393,7 @@ public class NotificationEntryManager implements
}
for (int i = 0; i < childEntries.size(); i++) {
NotificationEntry childEntry = childEntries.get(i);
- boolean isForeground = (entry.notification.getNotification().flags
+ boolean isForeground = (entry.getSbn().getNotification().flags
& Notification.FLAG_FOREGROUND_SERVICE) != 0;
boolean keepForReply =
getRemoteInputManager().shouldKeepForRemoteInputHistory(childEntry)
@@ -389,8 +418,8 @@ public class NotificationEntryManager implements
Log.d(TAG, "addNotification key=" + key);
}
- mNotificationData.updateRanking(rankingMap);
- NotificationListenerService.Ranking ranking = new NotificationListenerService.Ranking();
+ mNotificationData.updateRanking(rankingMap, "addNotificationInternal");
+ Ranking ranking = new Ranking();
rankingMap.getRanking(key, ranking);
NotificationEntry entry = new NotificationEntry(notification, ranking);
@@ -400,9 +429,9 @@ public class NotificationEntryManager implements
requireBinder().inflateViews(entry, () -> performRemoveNotification(notification,
REASON_CANCEL));
- abortExistingInflation(key);
-
+ abortExistingInflation(key, "addNotification");
mPendingNotifications.put(key, entry);
+ mNotifLog.log(NotifEvent.NOTIF_ADDED, entry.getSbn());
for (NotificationEntryListener listener : mNotificationEntryListeners) {
listener.onPendingEntryAdded(entry);
}
@@ -423,7 +452,7 @@ public class NotificationEntryManager implements
if (DEBUG) Log.d(TAG, "updateNotification(" + notification + ")");
final String key = notification.getKey();
- abortExistingInflation(key);
+ abortExistingInflation(key, "updateNotification");
NotificationEntry entry = mNotificationData.get(key);
if (entry == null) {
return;
@@ -433,15 +462,15 @@ public class NotificationEntryManager implements
// to keep its lifetime extended.
cancelLifetimeExtension(entry);
- mNotificationData.update(entry, ranking, notification);
-
+ mNotificationData.update(entry, ranking, notification, "updateNotificationInternal");
+ mNotifLog.log(NotifEvent.NOTIF_UPDATED, entry.getSbn(), entry.getRanking());
for (NotificationEntryListener listener : mNotificationEntryListeners) {
listener.onPreEntryUpdated(entry);
}
requireBinder().inflateViews(entry, () -> performRemoveNotification(notification,
REASON_CANCEL));
- updateNotifications();
+ updateNotifications("updateNotificationInternal");
if (DEBUG) {
// Is this for you?
@@ -465,8 +494,12 @@ public class NotificationEntryManager implements
}
}
- public void updateNotifications() {
- mNotificationData.filterAndSort();
+ /**
+ * Update the notifications
+ * @param reason why the notifications are updating
+ */
+ public void updateNotifications(String reason) {
+ mNotificationData.filterAndSort(reason);
if (mPresenter != null) {
mPresenter.updateNotificationViews();
}
@@ -484,24 +517,24 @@ public class NotificationEntryManager implements
for (NotificationEntry entry : entries) {
NotificationUiAdjustment adjustment =
NotificationUiAdjustment.extractFromNotificationEntry(entry);
- oldAdjustments.put(entry.key, adjustment);
- oldImportances.put(entry.key, entry.getImportance());
+ oldAdjustments.put(entry.getKey(), adjustment);
+ oldImportances.put(entry.getKey(), entry.getImportance());
}
// Populate notification entries from the new rankings.
- mNotificationData.updateRanking(rankingMap);
+ mNotificationData.updateRanking(rankingMap, "updateNotificationRanking");
updateRankingOfPendingNotifications(rankingMap);
// By comparing the old and new UI adjustments, reinflate the view accordingly.
for (NotificationEntry entry : entries) {
requireBinder().onNotificationRankingUpdated(
entry,
- oldImportances.get(entry.key),
- oldAdjustments.get(entry.key),
+ oldImportances.get(entry.getKey()),
+ oldAdjustments.get(entry.getKey()),
NotificationUiAdjustment.extractFromNotificationEntry(entry));
}
- updateNotifications();
+ updateNotifications("updateNotificationRanking");
for (NotificationEntryListener listener : mNotificationEntryListeners) {
listener.onNotificationRankingUpdated(rankingMap);
@@ -513,10 +546,11 @@ public class NotificationEntryManager implements
if (rankingMap == null) {
return;
}
- NotificationListenerService.Ranking ranking = new NotificationListenerService.Ranking();
for (NotificationEntry pendingNotification : mPendingNotifications.values()) {
- rankingMap.getRanking(pendingNotification.key, ranking);
- pendingNotification.setRanking(ranking);
+ Ranking ranking = new Ranking();
+ if (rankingMap.getRanking(pendingNotification.getKey(), ranking)) {
+ pendingNotification.setRanking(ranking);
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationFilter.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationFilter.java
index 5a0b88cbdc28..b1164093acdd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationFilter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationFilter.java
@@ -85,7 +85,7 @@ public class NotificationFilter {
* @return true if the provided notification should NOT be shown right now.
*/
public boolean shouldFilterOut(NotificationEntry entry) {
- final StatusBarNotification sbn = entry.notification;
+ final StatusBarNotification sbn = entry.getSbn();
if (!(getEnvironment().isDeviceProvisioned()
|| showNotificationEvenIfUnprovisioned(sbn))) {
return true;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationInterruptionStateProvider.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationInterruptionStateProvider.java
index 9362d2d5e2c9..7d09932dcad0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationInterruptionStateProvider.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationInterruptionStateProvider.java
@@ -39,6 +39,7 @@ import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.NotificationPresenter;
import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.policy.BatteryController;
import com.android.systemui.statusbar.policy.HeadsUpManager;
import javax.inject.Inject;
@@ -63,6 +64,7 @@ public class NotificationInterruptionStateProvider {
private final Context mContext;
private final PowerManager mPowerManager;
private final IDreamManager mDreamManager;
+ private final BatteryController mBatteryController;
private NotificationPresenter mPresenter;
private HeadsUpManager mHeadsUpManager;
@@ -75,13 +77,14 @@ public class NotificationInterruptionStateProvider {
@Inject
public NotificationInterruptionStateProvider(Context context, NotificationFilter filter,
- StatusBarStateController stateController) {
+ StatusBarStateController stateController, BatteryController batteryController) {
this(context,
(PowerManager) context.getSystemService(Context.POWER_SERVICE),
IDreamManager.Stub.asInterface(
ServiceManager.checkService(DreamService.DREAM_SERVICE)),
new AmbientDisplayConfiguration(context),
filter,
+ batteryController,
stateController);
}
@@ -92,10 +95,12 @@ public class NotificationInterruptionStateProvider {
IDreamManager dreamManager,
AmbientDisplayConfiguration ambientDisplayConfiguration,
NotificationFilter notificationFilter,
+ BatteryController batteryController,
StatusBarStateController statusBarStateController) {
mContext = context;
mPowerManager = powerManager;
mDreamManager = dreamManager;
+ mBatteryController = batteryController;
mAmbientDisplayConfiguration = ambientDisplayConfiguration;
mNotificationFilter = notificationFilter;
mStatusBarStateController = statusBarStateController;
@@ -159,7 +164,7 @@ public class NotificationInterruptionStateProvider {
* @return true if the entry should bubble up, false otherwise
*/
public boolean shouldBubbleUp(NotificationEntry entry) {
- final StatusBarNotification sbn = entry.notification;
+ final StatusBarNotification sbn = entry.getSbn();
if (!canAlertCommon(entry)) {
return false;
@@ -211,7 +216,7 @@ public class NotificationInterruptionStateProvider {
}
private boolean shouldHeadsUpWhenAwake(NotificationEntry entry) {
- StatusBarNotification sbn = entry.notification;
+ StatusBarNotification sbn = entry.getSbn();
if (!mUseHeadsUp) {
if (DEBUG_HEADS_UP) {
@@ -284,7 +289,7 @@ public class NotificationInterruptionStateProvider {
* @return true if the entry should ambient pulse, false otherwise
*/
private boolean shouldHeadsUpWhenDozing(NotificationEntry entry) {
- StatusBarNotification sbn = entry.notification;
+ StatusBarNotification sbn = entry.getSbn();
if (!mAmbientDisplayConfiguration.pulseOnNotificationEnabled(UserHandle.USER_CURRENT)) {
if (DEBUG_HEADS_UP) {
@@ -293,6 +298,13 @@ public class NotificationInterruptionStateProvider {
return false;
}
+ if (mBatteryController.isAodPowerSave()) {
+ if (DEBUG_HEADS_UP) {
+ Log.d(TAG, "No pulsing: disabled by battery saver: " + sbn.getKey());
+ }
+ return false;
+ }
+
if (!canAlertCommon(entry)) {
if (DEBUG_HEADS_UP) {
Log.d(TAG, "No pulsing: notification shouldn't alert: " + sbn.getKey());
@@ -324,7 +336,7 @@ public class NotificationInterruptionStateProvider {
*/
@VisibleForTesting
public boolean canAlertCommon(NotificationEntry entry) {
- StatusBarNotification sbn = entry.notification;
+ StatusBarNotification sbn = entry.getSbn();
if (mNotificationFilter.shouldFilterOut(entry)) {
if (DEBUG || DEBUG_HEADS_UP) {
@@ -351,7 +363,7 @@ public class NotificationInterruptionStateProvider {
*/
@VisibleForTesting
public boolean canAlertAwakeCommon(NotificationEntry entry) {
- StatusBarNotification sbn = entry.notification;
+ StatusBarNotification sbn = entry.getSbn();
if (mPresenter.isDeviceInVrMode()) {
if (DEBUG_HEADS_UP) {
@@ -411,7 +423,7 @@ public class NotificationInterruptionStateProvider {
* @return {@code true} if we should launch the full screen intent
*/
public boolean shouldLaunchFullScreenIntentWhenAdded(NotificationEntry entry) {
- return entry.notification.getNotification().fullScreenIntent != null
+ return entry.getSbn().getNotification().fullScreenIntent != null
&& (!shouldHeadsUp(entry)
|| mStatusBarStateController.getState() == StatusBarState.KEYGUARD);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationListController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationListController.java
index 769cbb7b984c..533dfb6ee4aa 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationListController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationListController.java
@@ -73,7 +73,7 @@ public class NotificationListController {
@Override
public void onBeforeNotificationAdded(NotificationEntry entry) {
- tagForeground(entry.notification);
+ tagForeground(entry.getSbn());
}
};
@@ -81,7 +81,7 @@ public class NotificationListController {
new DeviceProvisionedListener() {
@Override
public void onDeviceProvisionedChanged() {
- mEntryManager.updateNotifications();
+ mEntryManager.updateNotifications("device provisioned changed");
}
};
@@ -106,7 +106,7 @@ public class NotificationListController {
if (foregroundKey != null) {
mEntryManager
.getNotificationData().updateAppOp(appOp, uid, pkg, foregroundKey, showIcon);
- mEntryManager.updateNotifications();
+ mEntryManager.updateNotifications("app opp changed pkg=" + pkg);
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationSectionsFeatureManager.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationSectionsFeatureManager.kt
new file mode 100644
index 000000000000..009551168010
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationSectionsFeatureManager.kt
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.notification
+
+import android.content.Context
+import android.provider.DeviceConfig
+
+import com.android.internal.annotations.VisibleForTesting
+import com.android.internal.config.sysui.SystemUiDeviceConfigFlags.NOTIFICATIONS_USE_PEOPLE_FILTERING
+import com.android.systemui.statusbar.notification.stack.NotificationSectionsManager.BUCKET_ALERTING
+import com.android.systemui.statusbar.notification.stack.NotificationSectionsManager.BUCKET_PEOPLE
+import com.android.systemui.statusbar.notification.stack.NotificationSectionsManager.BUCKET_SILENT
+import com.android.systemui.util.DeviceConfigProxy
+
+import javax.inject.Inject
+
+private var sUsePeopleFiltering: Boolean? = null
+
+/**
+ * Feature controller for the NOTIFICATIONS_USE_PEOPLE_FILTERING config.
+ */
+class NotificationSectionsFeatureManager @Inject constructor(
+ val proxy: DeviceConfigProxy,
+ val context: Context
+) {
+
+ fun isFilteringEnabled(): Boolean {
+ return usePeopleFiltering(proxy)
+ }
+
+ fun getNotificationBuckets(): IntArray {
+ return when {
+ isFilteringEnabled() ->
+ intArrayOf(BUCKET_PEOPLE, BUCKET_ALERTING, BUCKET_SILENT)
+ NotificationUtils.useNewInterruptionModel(context) ->
+ intArrayOf(BUCKET_ALERTING, BUCKET_SILENT)
+ else ->
+ intArrayOf(BUCKET_ALERTING)
+ }
+ }
+
+ fun getNumberOfBuckets(): Int {
+ return getNotificationBuckets().size
+ }
+
+ @VisibleForTesting
+ fun clearCache() {
+ sUsePeopleFiltering = null
+ }
+}
+
+private fun usePeopleFiltering(proxy: DeviceConfigProxy): Boolean {
+ if (sUsePeopleFiltering == null) {
+ sUsePeopleFiltering = proxy.getBoolean(
+ DeviceConfig.NAMESPACE_SYSTEMUI, NOTIFICATIONS_USE_PEOPLE_FILTERING, true)
+ }
+
+ return sUsePeopleFiltering!!
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationUtils.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationUtils.java
index dfbbf987dd96..1af47dd0f4c0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationUtils.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationUtils.java
@@ -36,7 +36,6 @@ public class NotificationUtils {
private static final int[] sLocationOffset = new int[2];
@Nullable private static Boolean sUseNewInterruptionModel = null;
- @Nullable private static Boolean sUsePeopleFiltering = null;
public static boolean isGrayscale(ImageView v, ContrastColorUtil colorUtil) {
Object isGrayscale = v.getTag(R.id.icon_is_grayscale);
@@ -88,17 +87,4 @@ public class NotificationUtils {
}
return sUseNewInterruptionModel;
}
-
- /**
- * Caches and returns the value of the people filtering setting. Cannot change except through
- * process restarts.
- */
- public static boolean usePeopleFiltering(Context context) {
- if (sUsePeopleFiltering == null) {
- sUsePeopleFiltering = context.getResources().getBoolean(
- R.bool.config_usePeopleFiltering);
- }
-
- return sUsePeopleFiltering;
- }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt
index 2f67f90a115e..8a23e3796e9b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt
@@ -37,10 +37,10 @@ import javax.inject.Singleton
@Singleton
class NotificationWakeUpCoordinator @Inject constructor(
- private val mContext: Context,
private val mHeadsUpManagerPhone: HeadsUpManagerPhone,
private val statusBarStateController: StatusBarStateController,
- private val bypassController: KeyguardBypassController)
+ private val bypassController: KeyguardBypassController,
+ private val dozeParameters: DozeParameters)
: OnHeadsUpChangedListener, StatusBarStateController.StateListener,
PanelExpansionListener {
@@ -67,7 +67,6 @@ class NotificationWakeUpCoordinator @Inject constructor(
private var mVisibilityAmount = 0.0f
private var mLinearVisibilityAmount = 0.0f
private val mEntrySetToClearWhenFinished = mutableSetOf<NotificationEntry>()
- private val mDozeParameters: DozeParameters
private var pulseExpanding: Boolean = false
private val wakeUpListeners = arrayListOf<WakeUpListener>()
private var state: Int = StatusBarState.KEYGUARD
@@ -146,7 +145,6 @@ class NotificationWakeUpCoordinator @Inject constructor(
init {
mHeadsUpManagerPhone.addListener(this)
statusBarStateController.addCallback(this)
- mDozeParameters = DozeParameters.getInstance(mContext)
addListener(object : WakeUpListener {
override fun onFullyHiddenChanged(isFullyHidden: Boolean) {
if (isFullyHidden && mNotificationsVisibleForExpansion) {
@@ -377,7 +375,7 @@ class NotificationWakeUpCoordinator @Inject constructor(
}
private fun shouldAnimateVisibility() =
- mDozeParameters.getAlwaysOn() && !mDozeParameters.getDisplayNeedsBlanking()
+ dozeParameters.getAlwaysOn() && !dozeParameters.getDisplayNeedsBlanking()
interface WakeUpListener {
/**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/VisualStabilityManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/VisualStabilityManager.java
index 6fe4abee6133..1daf48492ea0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/VisualStabilityManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/VisualStabilityManager.java
@@ -16,8 +16,6 @@
package com.android.systemui.statusbar.notification;
-import static com.android.systemui.Dependency.MAIN_HANDLER_NAME;
-
import android.os.Handler;
import android.os.SystemClock;
import android.view.View;
@@ -25,6 +23,7 @@ import android.view.View;
import androidx.collection.ArraySet;
import com.android.systemui.Dumpable;
+import com.android.systemui.dagger.qualifiers.MainHandler;
import com.android.systemui.statusbar.NotificationPresenter;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
@@ -35,7 +34,6 @@ import java.io.PrintWriter;
import java.util.ArrayList;
import javax.inject.Inject;
-import javax.inject.Named;
import javax.inject.Singleton;
/**
@@ -64,8 +62,7 @@ public class VisualStabilityManager implements OnHeadsUpChangedListener, Dumpabl
@Inject
public VisualStabilityManager(
- NotificationEntryManager notificationEntryManager,
- @Named(MAIN_HANDLER_NAME) Handler handler) {
+ NotificationEntryManager notificationEntryManager, @MainHandler Handler handler) {
mHandler = handler;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/DismissedByUserStats.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/DismissedByUserStats.java
new file mode 100644
index 000000000000..ecce6ea1b211
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/DismissedByUserStats.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.notification.collection;
+
+import android.service.notification.NotificationStats.DismissalSentiment;
+import android.service.notification.NotificationStats.DismissalSurface;
+
+import com.android.internal.statusbar.NotificationVisibility;
+
+/** Information that must be supplied when dismissing a notification on the behalf of the user. */
+public class DismissedByUserStats {
+ public final @DismissalSurface int dismissalSurface;
+ public final @DismissalSentiment int dismissalSentiment;
+ public final NotificationVisibility notificationVisibility;
+
+ public DismissedByUserStats(
+ @DismissalSurface int dismissalSurface,
+ @DismissalSentiment int dismissalSentiment,
+ NotificationVisibility notificationVisibility) {
+ this.dismissalSurface = dismissalSurface;
+ this.dismissalSentiment = dismissalSentiment;
+ this.notificationVisibility = notificationVisibility;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollection.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollection.java
new file mode 100644
index 000000000000..b5513529d7ba
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollection.java
@@ -0,0 +1,426 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.notification.collection;
+
+import static android.service.notification.NotificationListenerService.REASON_APP_CANCEL;
+import static android.service.notification.NotificationListenerService.REASON_APP_CANCEL_ALL;
+import static android.service.notification.NotificationListenerService.REASON_CANCEL_ALL;
+import static android.service.notification.NotificationListenerService.REASON_CHANNEL_BANNED;
+import static android.service.notification.NotificationListenerService.REASON_CLICK;
+import static android.service.notification.NotificationListenerService.REASON_ERROR;
+import static android.service.notification.NotificationListenerService.REASON_GROUP_OPTIMIZATION;
+import static android.service.notification.NotificationListenerService.REASON_GROUP_SUMMARY_CANCELED;
+import static android.service.notification.NotificationListenerService.REASON_LISTENER_CANCEL;
+import static android.service.notification.NotificationListenerService.REASON_LISTENER_CANCEL_ALL;
+import static android.service.notification.NotificationListenerService.REASON_PACKAGE_BANNED;
+import static android.service.notification.NotificationListenerService.REASON_PACKAGE_CHANGED;
+import static android.service.notification.NotificationListenerService.REASON_PACKAGE_SUSPENDED;
+import static android.service.notification.NotificationListenerService.REASON_PROFILE_TURNED_OFF;
+import static android.service.notification.NotificationListenerService.REASON_SNOOZED;
+import static android.service.notification.NotificationListenerService.REASON_TIMEOUT;
+import static android.service.notification.NotificationListenerService.REASON_UNAUTOBUNDLED;
+import static android.service.notification.NotificationListenerService.REASON_USER_STOPPED;
+
+import static com.android.internal.util.Preconditions.checkNotNull;
+
+import android.annotation.IntDef;
+import android.annotation.MainThread;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.os.RemoteException;
+import android.service.notification.NotificationListenerService.Ranking;
+import android.service.notification.NotificationListenerService.RankingMap;
+import android.service.notification.StatusBarNotification;
+import android.util.ArrayMap;
+import android.util.Log;
+
+import com.android.internal.statusbar.IStatusBarService;
+import com.android.systemui.statusbar.NotificationListener;
+import com.android.systemui.statusbar.NotificationListener.NotifServiceListener;
+import com.android.systemui.util.Assert;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+/**
+ * Keeps a record of all of the "active" notifications, i.e. the notifications that are currently
+ * posted to the phone. This collection is unsorted, ungrouped, and unfiltered. Just because a
+ * notification appears in this collection doesn't mean that it's currently present in the shade
+ * (notifications can be hidden for a variety of reasons). Code that cares about what notifications
+ * are *visible* right now should register listeners later in the pipeline.
+ *
+ * Each notification is represented by a {@link NotificationEntry}, which is itself made up of two
+ * parts: a {@link StatusBarNotification} and a {@link Ranking}. When notifications are updated,
+ * their underlying SBNs and Rankings are swapped out, but the enclosing NotificationEntry (and its
+ * associated key) remain the same. In general, an SBN can only be updated when the notification is
+ * reposted by the source app; Rankings are updated much more often, usually every time there is an
+ * update from any kind from NotificationManager.
+ *
+ * In general, this collection closely mirrors the list maintained by NotificationManager, but it
+ * can occasionally diverge due to lifetime extenders (see
+ * {@link #addNotificationLifetimeExtender(NotifLifetimeExtender)}).
+ *
+ * Interested parties can register listeners
+ * ({@link #addCollectionListener(NotifCollectionListener)}) to be informed when notifications are
+ * added, updated, or removed.
+ */
+@MainThread
+@Singleton
+public class NotifCollection {
+ private final IStatusBarService mStatusBarService;
+
+ private final Map<String, NotificationEntry> mNotificationSet = new ArrayMap<>();
+ private final Collection<NotificationEntry> mReadOnlyNotificationSet =
+ Collections.unmodifiableCollection(mNotificationSet.values());
+
+ @Nullable private NotifListBuilder mListBuilder;
+ private final List<NotifCollectionListener> mNotifCollectionListeners = new ArrayList<>();
+ private final List<NotifLifetimeExtender> mLifetimeExtenders = new ArrayList<>();
+
+ private boolean mAttached = false;
+ private boolean mAmDispatchingToOtherCode;
+
+ @Inject
+ public NotifCollection(IStatusBarService statusBarService) {
+ Assert.isMainThread();
+ mStatusBarService = statusBarService;
+ }
+
+ /** Initializes the NotifCollection and registers it to receive notification events. */
+ public void attach(NotificationListener listenerService) {
+ Assert.isMainThread();
+ if (mAttached) {
+ throw new RuntimeException("attach() called twice");
+ }
+ mAttached = true;
+
+ listenerService.setDownstreamListener(mNotifServiceListener);
+ }
+
+ /**
+ * Sets the class responsible for converting the collection into the list of currently-visible
+ * notifications.
+ */
+ public void setListBuilder(NotifListBuilder listBuilder) {
+ Assert.isMainThread();
+ mListBuilder = listBuilder;
+ }
+
+ /**
+ * Returns the list of "active" notifications, i.e. the notifications that are currently posted
+ * to the phone. In general, this tracks closely to the list maintained by NotificationManager,
+ * but it can diverge slightly due to lifetime extenders.
+ *
+ * The returned list is read-only, unsorted, unfiltered, and ungrouped.
+ */
+ public Collection<NotificationEntry> getNotifs() {
+ Assert.isMainThread();
+ return mReadOnlyNotificationSet;
+ }
+
+ /**
+ * Registers a listener to be informed when notifications are added, removed or updated.
+ */
+ public void addCollectionListener(NotifCollectionListener listener) {
+ Assert.isMainThread();
+ mNotifCollectionListeners.add(listener);
+ }
+
+ /**
+ * Registers a lifetime extender. Lifetime extenders can cause notifications that have been
+ * dismissed or retracted to be temporarily retained in the collection.
+ */
+ public void addNotificationLifetimeExtender(NotifLifetimeExtender extender) {
+ Assert.isMainThread();
+ checkForReentrantCall();
+ if (mLifetimeExtenders.contains(extender)) {
+ throw new IllegalArgumentException("Extender " + extender + " already added.");
+ }
+ mLifetimeExtenders.add(extender);
+ extender.setCallback(this::onEndLifetimeExtension);
+ }
+
+ /**
+ * Dismiss a notification on behalf of the user.
+ */
+ public void dismissNotification(
+ NotificationEntry entry,
+ @CancellationReason int reason,
+ @NonNull DismissedByUserStats stats) {
+ Assert.isMainThread();
+ checkNotNull(stats);
+ checkForReentrantCall();
+
+ removeNotification(entry.getKey(), null, reason, stats);
+ }
+
+ private void onNotificationPosted(StatusBarNotification sbn, RankingMap rankingMap) {
+ Assert.isMainThread();
+
+ NotificationEntry entry = mNotificationSet.get(sbn.getKey());
+
+ if (entry == null) {
+ // A new notification!
+ Log.d(TAG, "POSTED " + sbn.getKey());
+
+ entry = new NotificationEntry(sbn, requireRanking(rankingMap, sbn.getKey()));
+ mNotificationSet.put(sbn.getKey(), entry);
+ applyRanking(rankingMap);
+
+ dispatchOnEntryAdded(entry);
+
+ } else {
+ // Update to an existing entry
+ Log.d(TAG, "UPDATED " + sbn.getKey());
+
+ // Notification is updated so it is essentially re-added and thus alive again. Don't
+ // need to keep its lifetime extended.
+ cancelLifetimeExtension(entry);
+
+ entry.setSbn(sbn);
+ applyRanking(rankingMap);
+
+ dispatchOnEntryUpdated(entry);
+ }
+
+ rebuildList();
+ }
+
+ private void onNotificationRemoved(
+ StatusBarNotification sbn,
+ @Nullable RankingMap rankingMap,
+ int reason) {
+ Assert.isMainThread();
+ Log.d(TAG, "REMOVED " + sbn.getKey() + " reason=" + reason);
+ removeNotification(sbn.getKey(), rankingMap, reason, null);
+ }
+
+ private void onNotificationRankingUpdate(RankingMap rankingMap) {
+ Assert.isMainThread();
+ applyRanking(rankingMap);
+ rebuildList();
+ }
+
+ private void removeNotification(
+ String key,
+ @Nullable RankingMap rankingMap,
+ @CancellationReason int reason,
+ DismissedByUserStats dismissedByUserStats) {
+
+ NotificationEntry entry = mNotificationSet.get(key);
+ if (entry == null) {
+ throw new IllegalStateException("No notification to remove with key " + key);
+ }
+
+ entry.mLifetimeExtenders.clear();
+ mAmDispatchingToOtherCode = true;
+ for (NotifLifetimeExtender extender : mLifetimeExtenders) {
+ if (extender.shouldExtendLifetime(entry, reason)) {
+ entry.mLifetimeExtenders.add(extender);
+ }
+ }
+ mAmDispatchingToOtherCode = false;
+
+ if (!isLifetimeExtended(entry)) {
+ mNotificationSet.remove(entry.getKey());
+
+ if (dismissedByUserStats != null) {
+ try {
+ mStatusBarService.onNotificationClear(
+ entry.getSbn().getPackageName(),
+ entry.getSbn().getTag(),
+ entry.getSbn().getId(),
+ entry.getSbn().getUser().getIdentifier(),
+ entry.getSbn().getKey(),
+ dismissedByUserStats.dismissalSurface,
+ dismissedByUserStats.dismissalSentiment,
+ dismissedByUserStats.notificationVisibility);
+ } catch (RemoteException e) {
+ // system process is dead if we're here.
+ }
+ }
+
+ if (rankingMap != null) {
+ applyRanking(rankingMap);
+ }
+
+ dispatchOnEntryRemoved(entry, reason, dismissedByUserStats != null /* removedByUser */);
+ }
+
+ rebuildList();
+ }
+
+ private void applyRanking(RankingMap rankingMap) {
+ for (NotificationEntry entry : mNotificationSet.values()) {
+ if (!isLifetimeExtended(entry)) {
+ Ranking ranking = requireRanking(rankingMap, entry.getKey());
+ entry.setRanking(ranking);
+ }
+ }
+ }
+
+ private void rebuildList() {
+ if (mListBuilder != null) {
+ mListBuilder.onBuildList(mReadOnlyNotificationSet);
+ }
+ }
+
+ private void onEndLifetimeExtension(NotifLifetimeExtender extender, NotificationEntry entry) {
+ Assert.isMainThread();
+ if (!mAttached) {
+ return;
+ }
+ checkForReentrantCall();
+
+ if (!entry.mLifetimeExtenders.remove(extender)) {
+ throw new IllegalStateException(
+ String.format(
+ "Cannot end lifetime extension for extender \"%s\" (%s)",
+ extender.getName(),
+ extender));
+ }
+
+ if (!isLifetimeExtended(entry)) {
+ // TODO: This doesn't need to be undefined -- we can set either EXTENDER_EXPIRED or
+ // save the original reason
+ removeNotification(entry.getKey(), null, REASON_UNKNOWN, null);
+ }
+ }
+
+ private void cancelLifetimeExtension(NotificationEntry entry) {
+ mAmDispatchingToOtherCode = true;
+ for (NotifLifetimeExtender extender : entry.mLifetimeExtenders) {
+ extender.cancelLifetimeExtension(entry);
+ }
+ mAmDispatchingToOtherCode = false;
+ entry.mLifetimeExtenders.clear();
+ }
+
+ private boolean isLifetimeExtended(NotificationEntry entry) {
+ return entry.mLifetimeExtenders.size() > 0;
+ }
+
+ private void checkForReentrantCall() {
+ if (mAmDispatchingToOtherCode) {
+ throw new IllegalStateException("Reentrant call detected");
+ }
+ }
+
+ private static Ranking requireRanking(RankingMap rankingMap, String key) {
+ // TODO: Modify RankingMap so that we don't have to make a copy here
+ Ranking ranking = new Ranking();
+ if (!rankingMap.getRanking(key, ranking)) {
+ throw new IllegalArgumentException("Ranking map doesn't contain key: " + key);
+ }
+ return ranking;
+ }
+
+ private void dispatchOnEntryAdded(NotificationEntry entry) {
+ mAmDispatchingToOtherCode = true;
+ if (mListBuilder != null) {
+ mListBuilder.onBeginDispatchToListeners();
+ }
+ for (NotifCollectionListener listener : mNotifCollectionListeners) {
+ listener.onEntryAdded(entry);
+ }
+ mAmDispatchingToOtherCode = false;
+ }
+
+ private void dispatchOnEntryUpdated(NotificationEntry entry) {
+ mAmDispatchingToOtherCode = true;
+ if (mListBuilder != null) {
+ mListBuilder.onBeginDispatchToListeners();
+ }
+ for (NotifCollectionListener listener : mNotifCollectionListeners) {
+ listener.onEntryUpdated(entry);
+ }
+ mAmDispatchingToOtherCode = false;
+ }
+
+ private void dispatchOnEntryRemoved(
+ NotificationEntry entry,
+ @CancellationReason int reason,
+ boolean removedByUser) {
+ mAmDispatchingToOtherCode = true;
+ if (mListBuilder != null) {
+ mListBuilder.onBeginDispatchToListeners();
+ }
+ for (NotifCollectionListener listener : mNotifCollectionListeners) {
+ listener.onEntryRemoved(entry, reason, removedByUser);
+ }
+ mAmDispatchingToOtherCode = false;
+ }
+
+ private final NotifServiceListener mNotifServiceListener = new NotifServiceListener() {
+ @Override
+ public void onNotificationPosted(StatusBarNotification sbn, RankingMap rankingMap) {
+ NotifCollection.this.onNotificationPosted(sbn, rankingMap);
+ }
+
+ @Override
+ public void onNotificationRemoved(StatusBarNotification sbn, RankingMap rankingMap) {
+ NotifCollection.this.onNotificationRemoved(sbn, rankingMap, REASON_UNKNOWN);
+ }
+
+ @Override
+ public void onNotificationRemoved(StatusBarNotification sbn, RankingMap rankingMap,
+ int reason) {
+ NotifCollection.this.onNotificationRemoved(sbn, rankingMap, reason);
+ }
+
+ @Override
+ public void onNotificationRankingUpdate(RankingMap rankingMap) {
+ NotifCollection.this.onNotificationRankingUpdate(rankingMap);
+ }
+ };
+
+ private static final String TAG = "NotifCollection";
+
+ @IntDef(prefix = { "REASON_" }, value = {
+ REASON_UNKNOWN,
+ REASON_CLICK,
+ REASON_CANCEL_ALL,
+ REASON_ERROR,
+ REASON_PACKAGE_CHANGED,
+ REASON_USER_STOPPED,
+ REASON_PACKAGE_BANNED,
+ REASON_APP_CANCEL,
+ REASON_APP_CANCEL_ALL,
+ REASON_LISTENER_CANCEL,
+ REASON_LISTENER_CANCEL_ALL,
+ REASON_GROUP_SUMMARY_CANCELED,
+ REASON_GROUP_OPTIMIZATION,
+ REASON_PACKAGE_SUSPENDED,
+ REASON_PROFILE_TURNED_OFF,
+ REASON_UNAUTOBUNDLED,
+ REASON_CHANNEL_BANNED,
+ REASON_SNOOZED,
+ REASON_TIMEOUT,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ @interface CancellationReason {}
+
+ public static final int REASON_UNKNOWN = 0;
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollectionListener.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollectionListener.java
new file mode 100644
index 000000000000..032620e14336
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollectionListener.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.notification.collection;
+
+import com.android.systemui.statusbar.notification.collection.NotifCollection.CancellationReason;
+
+/**
+ * Listener interface for {@link NotifCollection}.
+ */
+public interface NotifCollectionListener {
+ /**
+ * Called whenever a notification with a new key is posted.
+ */
+ default void onEntryAdded(NotificationEntry entry) {
+ }
+
+ /**
+ * Called whenever a notification with the same key as an existing notification is posted. By
+ * the time this listener is called, the entry's SBN and Ranking will already have been updated.
+ */
+ default void onEntryUpdated(NotificationEntry entry) {
+ }
+
+ /**
+ * Called immediately after a notification has been removed from the collection.
+ */
+ default void onEntryRemoved(
+ NotificationEntry entry,
+ @CancellationReason int reason,
+ boolean removedByUser) {
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifLifetimeExtender.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifLifetimeExtender.java
new file mode 100644
index 000000000000..2c7b13866c10
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifLifetimeExtender.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.notification.collection;
+
+import com.android.systemui.statusbar.notification.collection.NotifCollection.CancellationReason;
+
+/**
+ * A way for other code to temporarily extend the lifetime of a notification after it has been
+ * retracted. See {@link NotifCollection#addNotificationLifetimeExtender(NotifLifetimeExtender)}.
+ */
+public interface NotifLifetimeExtender {
+ /** Name to associate with this extender (for the purposes of debugging) */
+ String getName();
+
+ /**
+ * Called on the extender immediately after it has been registered. The extender should hang on
+ * to this callback and execute it whenever it no longer needs to extend the lifetime of a
+ * notification.
+ */
+ void setCallback(OnEndLifetimeExtensionCallback callback);
+
+ /**
+ * Called by the NotifCollection whenever a notification has been retracted (by the app) or
+ * dismissed (by the user). If the extender returns true, it is considered to be extending the
+ * lifetime of that notification. Lifetime-extended notifications are kept around until all
+ * active extenders expire their extension by calling onEndLifetimeExtension(). This method is
+ * called on all lifetime extenders even if earlier ones return true (in other words, multiple
+ * lifetime extenders can be extending a notification at the same time).
+ */
+ boolean shouldExtendLifetime(NotificationEntry entry, @CancellationReason int reason);
+
+ /**
+ * Called by the NotifCollection to inform a lifetime extender that its extension of a notif
+ * is no longer valid (usually because the notif has been reposted and so no longer needs
+ * lifetime extension). The extender should clean up any references it has to the notif in
+ * question.
+ */
+ void cancelLifetimeExtension(NotificationEntry entry);
+
+ /** Callback for notifying the NotifCollection that a lifetime extension has expired. */
+ interface OnEndLifetimeExtensionCallback {
+ void onEndLifetimeExtension(NotifLifetimeExtender extender, NotificationEntry entry);
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifListBuilder.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifListBuilder.java
new file mode 100644
index 000000000000..17fef6850f97
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifListBuilder.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.notification.collection;
+
+import java.util.Collection;
+
+/**
+ * Interface for the class responsible for converting a NotifCollection into the final sorted,
+ * filtered, and grouped list of currently visible notifications.
+ */
+public interface NotifListBuilder {
+ /**
+ * Called after the NotifCollection has received an update from NotificationManager but before
+ * it dispatches any change events to its listeners. This is to inform the list builder that
+ * the first stage of the pipeline has been triggered. After events have been dispatched,
+ * onBuildList() will be called.
+ *
+ * While onBuildList() is always called after this method is called, the converse is not always
+ * true: sometimes the NotifCollection applies an update that does not need to dispatch events,
+ * in which case this method will be skipped and onBuildList will be called directly.
+ */
+ void onBeginDispatchToListeners();
+
+ /**
+ * Called by the NotifCollection to indicate that something in the collection has changed and
+ * that the list builder should regenerate the list.
+ */
+ void onBuildList(Collection<NotificationEntry> entries);
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationData.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationData.java
index aacb2dd0682f..7d0ce5c4fa28 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationData.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationData.java
@@ -24,7 +24,6 @@ import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.Person;
-import android.content.Context;
import android.service.notification.NotificationListenerService.Ranking;
import android.service.notification.NotificationListenerService.RankingMap;
import android.service.notification.SnoozeCriterion;
@@ -35,7 +34,10 @@ import com.android.internal.annotations.VisibleForTesting;
import com.android.systemui.Dependency;
import com.android.systemui.statusbar.NotificationMediaManager;
import com.android.systemui.statusbar.notification.NotificationFilter;
-import com.android.systemui.statusbar.notification.NotificationUtils;
+import com.android.systemui.statusbar.notification.NotificationSectionsFeatureManager;
+import com.android.systemui.statusbar.notification.logging.NotifEvent;
+import com.android.systemui.statusbar.notification.logging.NotifLog;
+import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier;
import com.android.systemui.statusbar.phone.NotificationGroupManager;
import com.android.systemui.statusbar.policy.HeadsUpManager;
@@ -46,6 +48,8 @@ import java.util.Comparator;
import java.util.List;
import java.util.Objects;
+import javax.inject.Inject;
+
/**
* The list of currently displaying notifications.
*/
@@ -72,9 +76,17 @@ public class NotificationData {
private RankingMap mRankingMap;
private final Ranking mTmpRanking = new Ranking();
private final boolean mUsePeopleFiltering;
+ private final NotifLog mNotifLog;
+ private final PeopleNotificationIdentifier mPeopleNotificationIdentifier;
- public NotificationData(Context context) {
- mUsePeopleFiltering = NotificationUtils.usePeopleFiltering(context);
+ @Inject
+ public NotificationData(
+ NotificationSectionsFeatureManager sectionsFeatureManager,
+ NotifLog notifLog,
+ PeopleNotificationIdentifier peopleNotificationIdentifier) {
+ mUsePeopleFiltering = sectionsFeatureManager.isFilteringEnabled();
+ mNotifLog = notifLog;
+ mPeopleNotificationIdentifier = peopleNotificationIdentifier;
}
public void setHeadsUpManager(HeadsUpManager headsUpManager) {
@@ -86,10 +98,13 @@ public class NotificationData {
new Comparator<NotificationEntry>() {
@Override
public int compare(NotificationEntry a, NotificationEntry b) {
- final StatusBarNotification na = a.notification;
- final StatusBarNotification nb = b.notification;
- int aRank = getRank(a.key);
- int bRank = getRank(b.key);
+ final StatusBarNotification na = a.getSbn();
+ final StatusBarNotification nb = b.getSbn();
+ int aRank = getRank(a.getKey());
+ int bRank = getRank(b.getKey());
+
+ boolean aPeople = isPeopleNotification(a);
+ boolean bPeople = isPeopleNotification(b);
boolean aMedia = isImportantMedia(a);
boolean bMedia = isImportantMedia(b);
@@ -100,8 +115,8 @@ public class NotificationData {
boolean aHeadsUp = a.isRowHeadsUp();
boolean bHeadsUp = b.isRowHeadsUp();
- if (mUsePeopleFiltering && a.hasAssociatedPeople() != b.hasAssociatedPeople()) {
- return a.hasAssociatedPeople() ? -1 : 1;
+ if (mUsePeopleFiltering && aPeople != bPeople) {
+ return aPeople ? -1 : 1;
} else if (aHeadsUp != bHeadsUp) {
return aHeadsUp ? -1 : 1;
} else if (aHeadsUp) {
@@ -157,7 +172,7 @@ public class NotificationData {
final int len = mEntries.size();
for (int i = 0; i < len; i++) {
NotificationEntry entry = mEntries.valueAt(i);
- final StatusBarNotification sbn = entry.notification;
+ final StatusBarNotification sbn = entry.getSbn();
if (!getEnvironment().isNotificationForCurrentProfiles(sbn)) {
continue;
}
@@ -173,11 +188,11 @@ public class NotificationData {
public void add(NotificationEntry entry) {
synchronized (mEntries) {
- mEntries.put(entry.notification.getKey(), entry);
+ mEntries.put(entry.getSbn().getKey(), entry);
}
mGroupManager.onEntryAdded(entry);
- updateRankingAndSort(mRankingMap);
+ updateRankingAndSort(mRankingMap, "addEntry=" + entry.getSbn());
}
public NotificationEntry remove(String key, RankingMap ranking) {
@@ -187,7 +202,7 @@ public class NotificationData {
}
if (removed == null) return null;
mGroupManager.onEntryRemoved(removed);
- updateRankingAndSort(ranking);
+ updateRankingAndSort(ranking, "removeEntry=" + removed.getSbn());
return removed;
}
@@ -195,15 +210,19 @@ public class NotificationData {
public void update(
NotificationEntry entry,
RankingMap ranking,
- StatusBarNotification notification) {
- updateRanking(ranking);
- final StatusBarNotification oldNotification = entry.notification;
- entry.setNotification(notification);
+ StatusBarNotification notification,
+ String reason) {
+ updateRanking(ranking, reason);
+ final StatusBarNotification oldNotification = entry.getSbn();
+ entry.setSbn(notification);
mGroupManager.onEntryUpdated(entry, oldNotification);
}
- public void updateRanking(RankingMap ranking) {
- updateRankingAndSort(ranking);
+ /**
+ * Update ranking and trigger a re-sort
+ */
+ public void updateRanking(RankingMap ranking, String reason) {
+ updateRankingAndSort(ranking, reason);
}
public void updateAppOp(int appOp, int uid, String pkg, String key, boolean showIcon) {
@@ -211,9 +230,9 @@ public class NotificationData {
final int len = mEntries.size();
for (int i = 0; i < len; i++) {
NotificationEntry entry = mEntries.valueAt(i);
- if (uid == entry.notification.getUid()
- && pkg.equals(entry.notification.getPackageName())
- && key.equals(entry.key)) {
+ if (uid == entry.getSbn().getUid()
+ && pkg.equals(entry.getSbn().getPackageName())
+ && key.equals(entry.getKey())) {
if (showIcon) {
entry.mActiveAppOps.add(appOp);
} else {
@@ -240,7 +259,7 @@ public class NotificationData {
final ArrayList<NotificationEntry> logicalChildren =
mGroupManager.getLogicalChildren(statusBarNotification);
for (NotificationEntry child : logicalChildren) {
- if (isHighPriority(child.notification)) {
+ if (isHighPriority(child.getSbn())) {
return true;
}
}
@@ -327,17 +346,17 @@ public class NotificationData {
}
private boolean isImportantMedia(NotificationEntry e) {
- int importance = e.ranking().getImportance();
- boolean media = e.key.equals(getMediaManager().getMediaNotificationKey())
+ int importance = e.getRanking().getImportance();
+ boolean media = e.getKey().equals(getMediaManager().getMediaNotificationKey())
&& importance > NotificationManager.IMPORTANCE_MIN;
return media;
}
private boolean isSystemMax(NotificationEntry e) {
- int importance = e.ranking().getImportance();
+ int importance = e.getRanking().getImportance();
boolean sys = importance >= NotificationManager.IMPORTANCE_HIGH
- && isSystemNotification(e.notification);
+ && isSystemNotification(e.getSbn());
return sys;
}
@@ -350,7 +369,7 @@ public class NotificationData {
return false;
}
- private void updateRankingAndSort(RankingMap rankingMap) {
+ private void updateRankingAndSort(RankingMap rankingMap, String reason) {
if (rankingMap != null) {
mRankingMap = rankingMap;
synchronized (mEntries) {
@@ -358,22 +377,22 @@ public class NotificationData {
for (int i = 0; i < len; i++) {
NotificationEntry entry = mEntries.valueAt(i);
Ranking newRanking = new Ranking();
- if (!getRanking(entry.key, newRanking)) {
+ if (!getRanking(entry.getKey(), newRanking)) {
continue;
}
entry.setRanking(newRanking);
- final StatusBarNotification oldSbn = entry.notification.cloneLight();
+ final StatusBarNotification oldSbn = entry.getSbn().cloneLight();
final String overrideGroupKey = newRanking.getOverrideGroupKey();
if (!Objects.equals(oldSbn.getOverrideGroupKey(), overrideGroupKey)) {
- entry.notification.setOverrideGroupKey(overrideGroupKey);
+ entry.getSbn().setOverrideGroupKey(overrideGroupKey);
mGroupManager.onEntryUpdated(entry, oldSbn);
}
- entry.setIsHighPriority(isHighPriority(entry.notification));
+ entry.setIsHighPriority(isHighPriority(entry.getSbn()));
}
}
}
- filterAndSort();
+ filterAndSort(reason);
}
/**
@@ -391,7 +410,11 @@ public class NotificationData {
// TODO: This should not be public. Instead the Environment should notify this class when
// anything changed, and this class should call back the UI so it updates itself.
- public void filterAndSort() {
+ /**
+ * Filters and sorts the list of notification entries
+ */
+ public void filterAndSort(String reason) {
+ mNotifLog.log(NotifEvent.FILTER_AND_SORT, reason);
mSortedAndFiltered.clear();
synchronized (mEntries) {
@@ -432,7 +455,7 @@ public class NotificationData {
boolean isHeadsUp,
boolean isMedia,
boolean isSystemMax) {
- if (mUsePeopleFiltering && e.hasAssociatedPeople()) {
+ if (mUsePeopleFiltering && isPeopleNotification(e)) {
e.setBucket(BUCKET_PEOPLE);
} else if (isHeadsUp || isMedia || isSystemMax || e.isHighPriority()) {
e.setBucket(BUCKET_ALERTING);
@@ -441,6 +464,10 @@ public class NotificationData {
}
}
+ private boolean isPeopleNotification(NotificationEntry e) {
+ return mPeopleNotificationIdentifier.isPeopleNotification(e.getSbn());
+ }
+
public void dump(PrintWriter pw, String indent) {
int filteredLen = mSortedAndFiltered.size();
pw.print(indent);
@@ -466,10 +493,10 @@ public class NotificationData {
}
private void dumpEntry(PrintWriter pw, String indent, int i, NotificationEntry e) {
- getRanking(e.key, mTmpRanking);
+ getRanking(e.getKey(), mTmpRanking);
pw.print(indent);
- pw.println(" [" + i + "] key=" + e.key + " icon=" + e.icon);
- StatusBarNotification n = e.notification;
+ pw.println(" [" + i + "] key=" + e.getKey() + " icon=" + e.icon);
+ StatusBarNotification n = e.getSbn();
pw.print(indent);
pw.println(" pkg=" + n.getPackageName() + " id=" + n.getId() + " importance="
+ mTmpRanking.getImportance());
@@ -483,19 +510,6 @@ public class NotificationData {
}
/**
- * Get the current set of buckets for notification entries, as defined here
- */
- public static int[] getNotificationBuckets(Context context) {
- if (NotificationUtils.usePeopleFiltering(context)) {
- return new int[]{BUCKET_PEOPLE, BUCKET_ALERTING, BUCKET_SILENT};
- } else if (NotificationUtils.useNewInterruptionModel(context)) {
- return new int[]{BUCKET_ALERTING, BUCKET_SILENT};
- } else {
- return new int[]{BUCKET_ALERTING};
- }
- }
-
- /**
* Provides access to keyguard state and user settings dependent data.
*/
public interface KeyguardEnvironment {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java
index c3211e307845..71fc5490d656 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java
@@ -30,6 +30,7 @@ import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_NOTIFICAT
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_PEEK;
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_STATUS_BAR;
+import static com.android.internal.util.Preconditions.checkNotNull;
import static com.android.systemui.statusbar.notification.stack.NotificationSectionsManager.BUCKET_ALERTING;
import android.annotation.NonNull;
@@ -84,23 +85,30 @@ import java.util.Objects;
* clean this up in the future.
*/
public final class NotificationEntry {
- private static final long LAUNCH_COOLDOWN = 2000;
- private static final long REMOTE_INPUT_COOLDOWN = 500;
- private static final long INITIALIZATION_DELAY = 400;
- private static final long NOT_LAUNCHED_YET = -LAUNCH_COOLDOWN;
- private static final int COLOR_INVALID = 1;
- public final String key;
- public StatusBarNotification notification;
+ private final String mKey;
+ private StatusBarNotification mSbn;
private Ranking mRanking;
- public boolean noisy;
+
+ /*
+ * Bookkeeping members
+ */
+
+ /** List of lifetime extenders that are extending the lifetime of this notification. */
+ final List<NotifLifetimeExtender> mLifetimeExtenders = new ArrayList<>();
+
+
+ /*
+ * Old members
+ * TODO: Remove every member beneath this line if possible
+ */
+
public StatusBarIconView icon;
public StatusBarIconView expandedIcon;
public StatusBarIconView centeredIcon;
public StatusBarIconView aodIcon;
private boolean interruption;
- public boolean autoRedacted; // whether the redacted notification was generated by us
public int targetSdk;
private long lastFullScreenIntentLaunchTime = NOT_LAUNCHED_YET;
public CharSequence remoteInputText;
@@ -141,12 +149,6 @@ public final class NotificationEntry {
private boolean hasSentReply;
/**
- * Whether this notification has changed in visual appearance since the previous post.
- * New notifications are interruptive by default.
- */
- public boolean isVisuallyInterruptive;
-
- /**
* Whether this notification is shown to the user as a high priority notification: visible on
* the lock screen/status bar and in the top section in the shade.
*/
@@ -161,34 +163,42 @@ public final class NotificationEntry {
public NotificationEntry(
@NonNull StatusBarNotification sbn,
@NonNull Ranking ranking) {
- this.key = sbn.getKey();
- setNotification(sbn);
+ checkNotNull(sbn);
+ checkNotNull(sbn.getKey());
+ checkNotNull(ranking);
+
+ mKey = sbn.getKey();
+ setSbn(sbn);
setRanking(ranking);
}
/** The key for this notification. Guaranteed to be immutable and unique */
- public String key() {
- return key;
+ public String getKey() {
+ return mKey;
}
/**
* The StatusBarNotification that represents one half of a NotificationEntry (the other half
* being the Ranking). This object is swapped out whenever a notification is updated.
*/
- public StatusBarNotification sbn() {
- return notification;
+ public StatusBarNotification getSbn() {
+ return mSbn;
}
/**
* Should only be called by NotificationEntryManager and friends.
* TODO: Make this package-private
*/
- public void setNotification(StatusBarNotification sbn) {
- if (sbn.getKey() != null && key != null && !sbn.getKey().equals(key)) {
+ public void setSbn(@NonNull StatusBarNotification sbn) {
+ checkNotNull(sbn);
+ checkNotNull(sbn.getKey());
+
+ if (!sbn.getKey().equals(mKey)) {
throw new IllegalArgumentException("New key " + sbn.getKey()
- + " doesn't match existing key " + key);
+ + " doesn't match existing key " + mKey);
}
- notification = sbn;
+
+ mSbn = sbn;
updatePeopleList();
}
@@ -197,7 +207,7 @@ public final class NotificationEntry {
* StatusBarNotification). This object is swapped out whenever a the ranking is updated (which
* generally occurs whenever anything changes in the notification list).
*/
- public Ranking ranking() {
+ public Ranking getRanking() {
return mRanking;
}
@@ -206,14 +216,22 @@ public final class NotificationEntry {
* TODO: Make this package-private
*/
public void setRanking(@NonNull Ranking ranking) {
- if (!ranking.getKey().equals(key)) {
+ checkNotNull(ranking);
+ checkNotNull(ranking.getKey());
+
+ if (!ranking.getKey().equals(mKey)) {
throw new IllegalArgumentException("New key " + ranking.getKey()
- + " doesn't match existing key " + key);
+ + " doesn't match existing key " + mKey);
}
+
mRanking = ranking;
- isVisuallyInterruptive = ranking.visuallyInterruptive();
}
+
+ /*
+ * Convenience getters for SBN and Ranking members
+ */
+
public NotificationChannel getChannel() {
return mRanking.getChannel();
}
@@ -261,6 +279,12 @@ public final class NotificationEntry {
}
+ /*
+ * Old methods
+ *
+ * TODO: Remove as many of these as possible
+ */
+
public void setInterruption() {
interruption = true;
}
@@ -278,13 +302,13 @@ public final class NotificationEntry {
}
public boolean isBubble() {
- return (notification.getNotification().flags & FLAG_BUBBLE) != 0;
+ return (mSbn.getNotification().flags & FLAG_BUBBLE) != 0;
}
private void updatePeopleList() {
mAssociatedPeople.clear();
- Bundle extras = notification.getNotification().extras;
+ Bundle extras = mSbn.getNotification().extras;
if (extras == null) {
return;
}
@@ -296,7 +320,7 @@ public final class NotificationEntry {
}
if (Notification.MessagingStyle.class.equals(
- notification.getNotification().getNotificationStyle())) {
+ mSbn.getNotification().getNotificationStyle())) {
final Parcelable[] messages = extras.getParcelableArray(EXTRA_MESSAGES);
if (!ArrayUtils.isEmpty(messages)) {
for (Notification.MessagingStyle.Message message :
@@ -316,7 +340,7 @@ public final class NotificationEntry {
* Returns the data needed for a bubble for this notification, if it exists.
*/
public Notification.BubbleMetadata getBubbleMetadata() {
- return notification.getNotification().getBubbleMetadata();
+ return mSbn.getNotification().getBubbleMetadata();
}
/**
@@ -438,7 +462,7 @@ public final class NotificationEntry {
});
// Construct the centered icon
- if (notification.getNotification().isMediaNotification()) {
+ if (mSbn.getNotification().isMediaNotification()) {
centeredIcon = new StatusBarIconView(context,
sbn.getPackageName() + "/0x" + Integer.toHexString(sbn.getId()), sbn);
centeredIcon.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
@@ -478,8 +502,8 @@ public final class NotificationEntry {
// Update the icon
Notification n = sbn.getNotification();
final StatusBarIcon ic = new StatusBarIcon(
- notification.getUser(),
- notification.getPackageName(),
+ mSbn.getUser(),
+ mSbn.getPackageName(),
n.getSmallIcon(),
n.iconLevel,
n.number,
@@ -503,7 +527,7 @@ public final class NotificationEntry {
public int getContrastedColor(Context context, boolean isLowPriority,
int backgroundColor) {
int rawColor = isLowPriority ? Notification.COLOR_DEFAULT :
- notification.getNotification().color;
+ mSbn.getNotification().color;
if (mCachedContrastColorIsFor == rawColor && mCachedContrastColor != COLOR_INVALID) {
return mCachedContrastColor;
}
@@ -569,7 +593,7 @@ public final class NotificationEntry {
if (!hasSentReply) {
return false;
}
- Bundle extras = notification.getNotification().extras;
+ Bundle extras = mSbn.getNotification().extras;
CharSequence[] replyTexts = extras.getCharSequenceArray(
Notification.EXTRA_REMOTE_INPUT_HISTORY);
if (!ArrayUtils.isEmpty(replyTexts)) {
@@ -771,7 +795,7 @@ public final class NotificationEntry {
* @see #canViewBeDismissed()
*/
public boolean isClearable() {
- if (notification == null || !notification.isClearable()) {
+ if (!mSbn.isClearable()) {
return false;
}
@@ -794,15 +818,15 @@ public final class NotificationEntry {
@VisibleForTesting
boolean isExemptFromDndVisualSuppression() {
- if (isNotificationBlockedByPolicy(notification.getNotification())) {
+ if (isNotificationBlockedByPolicy(mSbn.getNotification())) {
return false;
}
- if ((notification.getNotification().flags
+ if ((mSbn.getNotification().flags
& Notification.FLAG_FOREGROUND_SERVICE) != 0) {
return true;
}
- if (notification.getNotification().isMediaNotification()) {
+ if (mSbn.getNotification().isMediaNotification()) {
return true;
}
if (mIsSystemNotification != null && mIsSystemNotification) {
@@ -935,4 +959,10 @@ public final class NotificationEntry {
this.index = index;
}
}
+
+ private static final long LAUNCH_COOLDOWN = 2000;
+ private static final long REMOTE_INPUT_COOLDOWN = 500;
+ private static final long INITIALIZATION_DELAY = 400;
+ private static final long NOT_LAUNCHED_YET = -LAUNCH_COOLDOWN;
+ private static final int COLOR_INVALID = 1;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationRowBinderImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationRowBinderImpl.java
index 60cf995ad8d1..396c5fefd8b7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationRowBinderImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationRowBinderImpl.java
@@ -41,6 +41,8 @@ import com.android.systemui.statusbar.NotificationUiAdjustment;
import com.android.systemui.statusbar.notification.InflationException;
import com.android.systemui.statusbar.notification.NotificationClicker;
import com.android.systemui.statusbar.notification.NotificationInterruptionStateProvider;
+import com.android.systemui.statusbar.notification.logging.NotifEvent;
+import com.android.systemui.statusbar.notification.logging.NotifLog;
import com.android.systemui.statusbar.notification.logging.NotificationLogger;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.row.NotificationContentInflater;
@@ -72,6 +74,7 @@ public class NotificationRowBinderImpl implements NotificationRowBinder {
private final boolean mAllowLongPress;
private final KeyguardBypassController mKeyguardBypassController;
private final StatusBarStateController mStatusBarStateController;
+ private final NotifLog mNotifLog;
private NotificationRemoteInputManager mRemoteInputManager;
private NotificationPresenter mPresenter;
@@ -85,12 +88,14 @@ public class NotificationRowBinderImpl implements NotificationRowBinder {
public NotificationRowBinderImpl(Context context, boolean allowLongPress,
KeyguardBypassController keyguardBypassController,
- StatusBarStateController statusBarStateController) {
+ StatusBarStateController statusBarStateController,
+ NotifLog notifLog) {
mContext = context;
mMessagingUtil = new NotificationMessagingUtil(context);
mAllowLongPress = allowLongPress;
mKeyguardBypassController = keyguardBypassController;
mStatusBarStateController = statusBarStateController;
+ mNotifLog = notifLog;
}
private NotificationRemoteInputManager getRemoteInputManager() {
@@ -130,9 +135,9 @@ public class NotificationRowBinderImpl implements NotificationRowBinder {
throws InflationException {
ViewGroup parent = mListContainer.getViewParentForNotification(entry);
PackageManager pmUser = StatusBar.getPackageManagerForUser(mContext,
- entry.notification.getUser().getIdentifier());
+ entry.getSbn().getUser().getIdentifier());
- final StatusBarNotification sbn = entry.notification;
+ final StatusBarNotification sbn = entry.getSbn();
if (entry.rowExists()) {
entry.updateIcons(mContext, sbn);
entry.reset();
@@ -143,6 +148,7 @@ public class NotificationRowBinderImpl implements NotificationRowBinder {
row -> {
bindRow(entry, pmUser, sbn, row, onDismissRunnable);
updateNotification(entry, pmUser, sbn, row);
+ mNotifLog.log(NotifEvent.INFLATED, sbn);
});
}
}
@@ -150,7 +156,7 @@ public class NotificationRowBinderImpl implements NotificationRowBinder {
private void bindRow(NotificationEntry entry, PackageManager pmUser,
StatusBarNotification sbn, ExpandableNotificationRow row,
Runnable onDismissRunnable) {
- row.setExpansionLogger(mExpansionLogger, entry.notification.getKey());
+ row.setExpansionLogger(mExpansionLogger, entry.getSbn().getKey());
row.setBypassController(mKeyguardBypassController);
row.setStatusBarStateController(mStatusBarStateController);
row.setGroupManager(mGroupManager);
@@ -207,8 +213,8 @@ public class NotificationRowBinderImpl implements NotificationRowBinder {
entry.reset();
PackageManager pmUser = StatusBar.getPackageManagerForUser(
mContext,
- entry.notification.getUser().getIdentifier());
- updateNotification(entry, pmUser, entry.notification, entry.getRow());
+ entry.getSbn().getUser().getIdentifier());
+ updateNotification(entry, pmUser, entry.getSbn(), entry.getRow());
} else {
// Once the RowInflaterTask is done, it will pick up the updated entry, so
// no-op here.
@@ -242,7 +248,6 @@ public class NotificationRowBinderImpl implements NotificationRowBinder {
// TODO: should updates to the entry be happening somewhere else?
entry.setIconTag(R.id.icon_is_pre_L, entry.targetSdk < Build.VERSION_CODES.LOLLIPOP);
- entry.autoRedacted = entry.notification.getNotification().publicVersion == null;
entry.setRow(row);
row.setOnActivatedListener(mPresenter);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotifEvent.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotifEvent.java
new file mode 100644
index 000000000000..8ebbca26fa5b
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotifEvent.java
@@ -0,0 +1,160 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.notification.logging;
+
+import android.annotation.IntDef;
+import android.service.notification.NotificationListenerService.Ranking;
+import android.service.notification.StatusBarNotification;
+
+import com.android.systemui.log.RichEvent;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * An event related to notifications. {@link NotifLog} stores and prints these events for debugging
+ * and triaging purposes. We do not store a copy of the status bar notification nor ranking
+ * here to mitigate memory usage.
+ */
+public class NotifEvent extends RichEvent {
+ public static final int TOTAL_EVENT_TYPES = 11;
+
+ /**
+ * Creates a NotifEvent with an event type that matches with an index in the array
+ * getSupportedEvents() and {@link EventType}.
+ *
+ * The status bar notification and ranking objects are stored as shallow copies of the current
+ * state of the event when this event occurred.
+ */
+ public NotifEvent(int logLevel, int type, String reason, StatusBarNotification sbn,
+ Ranking ranking) {
+ super(logLevel, type, reason);
+ mMessage += getExtraInfo(sbn, ranking);
+ }
+
+ private String getExtraInfo(StatusBarNotification sbn, Ranking ranking) {
+ StringBuilder extraInfo = new StringBuilder();
+
+ if (sbn != null) {
+ extraInfo.append(" Sbn=");
+ extraInfo.append(sbn);
+ }
+
+ if (ranking != null) {
+ extraInfo.append(" Ranking=");
+ extraInfo.append(ranking);
+ }
+
+ return extraInfo.toString();
+ }
+
+ /**
+ * Event labels for NotifEvents
+ * Index corresponds to the {@link EventType}
+ */
+ @Override
+ public String[] getEventLabels() {
+ final String[] events = new String[]{
+ "NotifAdded",
+ "NotifRemoved",
+ "NotifUpdated",
+ "Filter",
+ "Sort",
+ "FilterAndSort",
+ "NotifVisibilityChanged",
+ "LifetimeExtended",
+ "RemoveIntercepted",
+ "InflationAborted",
+ "Inflated"
+ };
+
+ if (events.length != TOTAL_EVENT_TYPES) {
+ throw new IllegalStateException("NotifEvents events.length should match "
+ + TOTAL_EVENT_TYPES
+ + " events.length=" + events.length
+ + " TOTAL_EVENT_LENGTH=" + TOTAL_EVENT_TYPES);
+ }
+ return events;
+ }
+
+ /**
+ * Builds a NotifEvent.
+ */
+ public static class NotifEventBuilder extends RichEvent.Builder<NotifEventBuilder> {
+ private StatusBarNotification mSbn;
+ private Ranking mRanking;
+
+ @Override
+ public NotifEventBuilder getBuilder() {
+ return this;
+ }
+
+ /**
+ * Stores the status bar notification object. A shallow copy is stored in the NotifEvent's
+ * constructor.
+ */
+ public NotifEventBuilder setSbn(StatusBarNotification sbn) {
+ mSbn = sbn;
+ return this;
+ }
+
+ /**
+ * Stores the ranking object. A shallow copy is stored in the NotifEvent's
+ * constructor.
+ */
+ public NotifEventBuilder setRanking(Ranking ranking) {
+ mRanking = ranking;
+ return this;
+ }
+
+ @Override
+ public RichEvent build() {
+ return new NotifEvent(mLogLevel, mType, mReason, mSbn, mRanking);
+ }
+ }
+
+ @IntDef({NOTIF_ADDED,
+ NOTIF_REMOVED,
+ NOTIF_UPDATED,
+ FILTER,
+ SORT,
+ FILTER_AND_SORT,
+ NOTIF_VISIBILITY_CHANGED,
+ LIFETIME_EXTENDED,
+ REMOVE_INTERCEPTED,
+ INFLATION_ABORTED,
+ INFLATED
+ })
+
+ /**
+ * Types of NotifEvents
+ */
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface EventType {}
+ public static final int NOTIF_ADDED = 0;
+ public static final int NOTIF_REMOVED = 1;
+ public static final int NOTIF_UPDATED = 2;
+ public static final int FILTER = 3;
+ public static final int SORT = 4;
+ public static final int FILTER_AND_SORT = 5;
+ public static final int NOTIF_VISIBILITY_CHANGED = 6;
+ public static final int LIFETIME_EXTENDED = 7;
+ // unable to remove notif - removal intercepted by {@link NotificationRemoveInterceptor}
+ public static final int REMOVE_INTERCEPTED = 8;
+ public static final int INFLATION_ABORTED = 9;
+ public static final int INFLATED = 10;
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotifLog.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotifLog.java
new file mode 100644
index 000000000000..129283107894
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotifLog.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.notification.logging;
+
+import android.service.notification.NotificationListenerService.Ranking;
+import android.service.notification.StatusBarNotification;
+
+import com.android.systemui.DumpController;
+import com.android.systemui.log.SysuiLog;
+import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+/**
+ * Logs systemui notification events for debugging and triaging purposes. Logs are dumped in
+ * bugreports or on demand:
+ * adb shell dumpsys activity service com.android.systemui/.SystemUIService \
+ * dependency DumpController NotifLog
+ */
+@Singleton
+public class NotifLog extends SysuiLog {
+ private static final String TAG = "NotifLog";
+ private static final int MAX_DOZE_DEBUG_LOGS = 400;
+ private static final int MAX_DOZE_LOGS = 50;
+
+ @Inject
+ public NotifLog(DumpController dumpController) {
+ super(dumpController, TAG, MAX_DOZE_DEBUG_LOGS, MAX_DOZE_LOGS);
+ }
+
+ /**
+ * Logs a {@link NotifEvent} with a notification, ranking and message
+ * @return true if successfully logged, else false
+ */
+ public boolean log(@NotifEvent.EventType int eventType, StatusBarNotification sbn,
+ Ranking ranking, String msg) {
+ return log(new NotifEvent.NotifEventBuilder()
+ .setType(eventType)
+ .setSbn(sbn)
+ .setRanking(ranking)
+ .setReason(msg)
+ .build());
+ }
+
+ /**
+ * Logs a {@link NotifEvent}
+ * @return true if successfully logged, else false
+ */
+ public boolean log(@NotifEvent.EventType int eventType) {
+ return log(eventType, null, null, null);
+ }
+
+ /**
+ * Logs a {@link NotifEvent} with a message
+ * @return true if successfully logged, else false
+ */
+ public boolean log(@NotifEvent.EventType int eventType, String msg) {
+ return log(eventType, null, null, msg);
+ }
+
+ /**
+ * Logs a {@link NotifEvent} with a notification
+ * @return true if successfully logged, else false
+ */
+ public boolean log(@NotifEvent.EventType int eventType, StatusBarNotification sbn) {
+ return log(eventType, sbn, null, "");
+ }
+
+ /**
+ * Logs a {@link NotifEvent} with a notification
+ * @return true if successfully logged, else false
+ */
+ public boolean log(@NotifEvent.EventType int eventType, StatusBarNotification sbn, String msg) {
+ return log(eventType, sbn, null, msg);
+ }
+
+ /**
+ * Logs a {@link NotifEvent} with a ranking
+ * @return true if successfully logged, else false
+ */
+ public boolean log(@NotifEvent.EventType int eventType, Ranking ranking) {
+ return log(eventType, null, ranking, "");
+ }
+
+ /**
+ * Logs a {@link NotifEvent} with a notification and ranking
+ * @return true if successfully logged, else false
+ */
+ public boolean log(@NotifEvent.EventType int eventType, StatusBarNotification sbn,
+ Ranking ranking) {
+ return log(eventType, sbn, ranking, "");
+ }
+
+ /**
+ * Logs a {@link NotifEvent} with a notification entry
+ * @return true if successfully logged, else false
+ */
+ public boolean log(@NotifEvent.EventType int eventType, NotificationEntry entry) {
+ return log(eventType, entry.getSbn(), entry.getRanking(), "");
+ }
+
+ /**
+ * Logs a {@link NotifEvent} with a notification entry
+ * @return true if successfully logged, else false
+ */
+ public boolean log(@NotifEvent.EventType int eventType, NotificationEntry entry,
+ String msg) {
+ return log(eventType, entry.getSbn(), entry.getRanking(), msg);
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationLogger.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationLogger.java
index 81275fda57e5..b7f408ebe557 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationLogger.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationLogger.java
@@ -126,7 +126,7 @@ public class NotificationLogger implements StateListener {
int N = activeNotifications.size();
for (int i = 0; i < N; i++) {
NotificationEntry entry = activeNotifications.get(i);
- String key = entry.notification.getKey();
+ String key = entry.getSbn().getKey();
boolean isVisible = mListContainer.isInVisibleLocation(entry);
NotificationVisibility visObj = NotificationVisibility.obtain(key, i, N, isVisible,
getNotificationLocation(entry));
@@ -214,14 +214,14 @@ public class NotificationLogger implements StateListener {
NotificationVisibility visibility,
boolean removedByUser) {
if (removedByUser && visibility != null) {
- logNotificationClear(entry.key, entry.notification, visibility);
+ logNotificationClear(entry.getKey(), entry.getSbn(), visibility);
}
- mExpansionStateLogger.onEntryRemoved(entry.key);
+ mExpansionStateLogger.onEntryRemoved(entry.getKey());
}
@Override
public void onEntryReinflated(NotificationEntry entry) {
- mExpansionStateLogger.onEntryReinflated(entry.key);
+ mExpansionStateLogger.onEntryReinflated(entry.getKey());
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleHub.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleHub.kt
new file mode 100644
index 000000000000..2c0c9420a8c4
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleHub.kt
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.notification.people
+
+import android.app.PendingIntent
+import android.graphics.drawable.Drawable
+
+/** `ViewModel` for PeopleHub view. */
+data class PeopleHubViewModel(val people: Sequence<PersonViewModel>, val isVisible: Boolean)
+
+/** `ViewModel` for a single "Person' in PeopleHub. */
+data class PersonViewModel(
+ val name: CharSequence,
+ val icon: Drawable,
+ val onClick: () -> Unit
+)
+
+/** `Model` for PeopleHub. */
+data class PeopleHubModel(val people: Collection<PersonModel>)
+
+/** `Model` for a single "Person" in PeopleHub. */
+data class PersonModel(
+ val key: PersonKey,
+ val name: CharSequence,
+ val avatar: Drawable,
+ val clickIntent: PendingIntent
+)
+
+/** Unique identifier for a Person in PeopleHub. */
+typealias PersonKey = String \ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleHubModule.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleHubModule.kt
new file mode 100644
index 000000000000..45709893a7b5
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleHubModule.kt
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.notification.people
+
+import dagger.Binds
+import dagger.Module
+
+@Module
+abstract class PeopleHubModule {
+
+ @Binds
+ abstract fun peopleHubSectionFooterViewController(
+ impl: PeopleHubSectionFooterViewAdapterImpl
+ ): PeopleHubSectionFooterViewAdapter
+
+ @Binds
+ abstract fun peopleHubDataSource(impl: PeopleHubDataSourceImpl): DataSource<PeopleHubModel>
+
+ @Binds
+ abstract fun peopleHubViewModelFactoryDataSource(
+ impl: PeopleHubViewModelFactoryDataSourceImpl
+ ): DataSource<PeopleHubViewModelFactory>
+
+ @Binds
+ abstract fun peopleNotificationIdentifier(
+ impl: PeopleNotificationIdentifierImpl
+ ): PeopleNotificationIdentifier
+
+ @Binds
+ abstract fun notificationPersonExtractor(
+ pluginImpl: NotificationPersonExtractorPluginBoundary
+ ): NotificationPersonExtractor
+} \ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleHubNotificationListener.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleHubNotificationListener.kt
new file mode 100644
index 000000000000..fe257d9fd252
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleHubNotificationListener.kt
@@ -0,0 +1,272 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.notification.people
+
+import android.app.Notification
+import android.content.Context
+import android.graphics.Canvas
+import android.graphics.ColorFilter
+import android.graphics.PixelFormat
+import android.graphics.drawable.BitmapDrawable
+import android.graphics.drawable.Drawable
+import android.os.UserHandle
+import android.service.notification.StatusBarNotification
+import android.util.TypedValue
+import android.view.View
+import android.view.ViewGroup
+import android.widget.ImageView
+import com.android.internal.statusbar.NotificationVisibility
+import com.android.internal.widget.MessagingGroup
+import com.android.launcher3.icons.BaseIconFactory
+import com.android.systemui.R
+import com.android.systemui.plugins.NotificationPersonExtractorPlugin
+import com.android.systemui.statusbar.notification.NotificationEntryListener
+import com.android.systemui.statusbar.notification.NotificationEntryManager
+import com.android.systemui.statusbar.notification.collection.NotificationEntry
+import com.android.systemui.statusbar.policy.ExtensionController
+import java.util.ArrayDeque
+import javax.inject.Inject
+import javax.inject.Singleton
+
+private const val MAX_STORED_INACTIVE_PEOPLE = 10
+
+interface NotificationPersonExtractor {
+ fun extractPerson(sbn: StatusBarNotification): PersonModel?
+ fun extractPersonKey(sbn: StatusBarNotification): String?
+}
+
+@Singleton
+class NotificationPersonExtractorPluginBoundary @Inject constructor(
+ extensionController: ExtensionController,
+ private val context: Context
+) : NotificationPersonExtractor {
+
+ private var plugin: NotificationPersonExtractorPlugin? = null
+
+ init {
+ plugin = extensionController
+ .newExtension(NotificationPersonExtractorPlugin::class.java)
+ .withPlugin(NotificationPersonExtractorPlugin::class.java)
+ .withCallback { extractor ->
+ plugin = extractor
+ }
+ .build()
+ .get()
+ }
+
+ override fun extractPerson(sbn: StatusBarNotification) =
+ plugin?.extractPerson(sbn)?.let { data ->
+ val badged = addBadgeToDrawable(data.avatar, context, sbn.packageName, sbn.user)
+ PersonModel(data.key, data.name, badged, data.clickIntent)
+ }
+
+ override fun extractPersonKey(sbn: StatusBarNotification) = plugin?.extractPersonKey(sbn)
+}
+
+@Singleton
+class PeopleHubDataSourceImpl @Inject constructor(
+ private val notificationEntryManager: NotificationEntryManager,
+ private val peopleHubManager: PeopleHubManager,
+ private val extractor: NotificationPersonExtractor
+) : DataSource<PeopleHubModel> {
+
+ private val dataListeners = mutableListOf<DataListener<PeopleHubModel>>()
+
+ private val notificationEntryListener = object : NotificationEntryListener {
+ override fun onEntryInflated(entry: NotificationEntry, inflatedFlags: Int) =
+ addVisibleEntry(entry)
+
+ override fun onEntryReinflated(entry: NotificationEntry) = addVisibleEntry(entry)
+
+ override fun onPostEntryUpdated(entry: NotificationEntry) = addVisibleEntry(entry)
+
+ override fun onEntryRemoved(
+ entry: NotificationEntry,
+ visibility: NotificationVisibility?,
+ removedByUser: Boolean
+ ) = removeVisibleEntry(entry)
+ }
+
+ private fun removeVisibleEntry(entry: NotificationEntry) {
+ val key = extractor.extractPersonKey(entry.sbn) ?: entry.extractPersonKey()
+ if (key?.let(peopleHubManager::removeActivePerson) == true) {
+ updateUi()
+ }
+ }
+
+ private fun addVisibleEntry(entry: NotificationEntry) {
+ val personModel = extractor.extractPerson(entry.sbn) ?: entry.extractPerson()
+ if (personModel?.let(peopleHubManager::addActivePerson) == true) {
+ updateUi()
+ }
+ }
+
+ override fun registerListener(listener: DataListener<PeopleHubModel>): Subscription {
+ val registerWithNotificationEntryManager = dataListeners.isEmpty()
+ dataListeners.add(listener)
+ if (registerWithNotificationEntryManager) {
+ notificationEntryManager.addNotificationEntryListener(notificationEntryListener)
+ } else {
+ listener.onDataChanged(peopleHubManager.getPeopleHubModel())
+ }
+ return object : Subscription {
+ override fun unsubscribe() {
+ dataListeners.remove(listener)
+ if (dataListeners.isEmpty()) {
+ notificationEntryManager
+ .removeNotificationEntryListener(notificationEntryListener)
+ }
+ }
+ }
+ }
+
+ private fun updateUi() {
+ val model = peopleHubManager.getPeopleHubModel()
+ for (listener in dataListeners) {
+ listener.onDataChanged(model)
+ }
+ }
+}
+
+@Singleton
+class PeopleHubManager @Inject constructor() {
+
+ private val activePeople = mutableMapOf<PersonKey, PersonModel>()
+ private val inactivePeople = ArrayDeque<PersonModel>(MAX_STORED_INACTIVE_PEOPLE)
+
+ fun removeActivePerson(key: PersonKey): Boolean {
+ activePeople.remove(key)?.let { data ->
+ if (inactivePeople.size >= MAX_STORED_INACTIVE_PEOPLE) {
+ inactivePeople.removeLast()
+ }
+ inactivePeople.push(data)
+ return true
+ }
+ return false
+ }
+
+ fun addActivePerson(person: PersonModel): Boolean {
+ activePeople[person.key] = person
+ return inactivePeople.removeIf { it.key == person.key }
+ }
+
+ fun getPeopleHubModel(): PeopleHubModel = PeopleHubModel(inactivePeople)
+}
+
+private val ViewGroup.children
+ get(): Sequence<View> = sequence {
+ for (i in 0 until childCount) {
+ yield(getChildAt(i))
+ }
+ }
+
+private fun ViewGroup.childrenWithId(id: Int): Sequence<View> = children.filter { it.id == id }
+
+private fun NotificationEntry.extractPerson(): PersonModel? {
+ if (!isMessagingNotification()) {
+ return null
+ }
+ val clickIntent = sbn.notification.contentIntent
+ ?: return null
+ val extras = sbn.notification.extras
+ val name = extras.getString(Notification.EXTRA_CONVERSATION_TITLE)
+ ?: extras.getString(Notification.EXTRA_TITLE)
+ ?: return null
+ val drawable = extractAvatarFromRow(this) ?: return null
+ val badgedAvatar = addBadgeToDrawable(drawable, row.context, sbn.packageName, sbn.user)
+ return PersonModel(key, name, badgedAvatar, clickIntent)
+}
+
+private fun addBadgeToDrawable(
+ drawable: Drawable,
+ context: Context,
+ packageName: String,
+ user: UserHandle
+): Drawable {
+ val pm = context.packageManager
+ val appInfo = pm.getApplicationInfoAsUser(packageName, 0, user)
+ return object : Drawable() {
+ override fun draw(canvas: Canvas) {
+ val iconBounds = getBounds()
+ val factory = object : BaseIconFactory(
+ context,
+ 0 /* unused */,
+ iconBounds.width(),
+ true) {}
+ val badge = factory.createBadgedIconBitmap(
+ appInfo.loadIcon(pm),
+ user,
+ true,
+ appInfo.isInstantApp,
+ null)
+ val badgeDrawable = BitmapDrawable(context.resources, badge.icon)
+ .apply {
+ alpha = drawable.alpha
+ colorFilter = drawable.colorFilter
+ val badgeWidth = TypedValue.applyDimension(
+ TypedValue.COMPLEX_UNIT_DIP,
+ 15f,
+ context.resources.displayMetrics
+ ).toInt()
+ setBounds(
+ iconBounds.left + (iconBounds.width() - badgeWidth),
+ iconBounds.top + (iconBounds.height() - badgeWidth),
+ iconBounds.right,
+ iconBounds.bottom)
+ }
+ drawable.bounds = iconBounds
+ drawable.draw(canvas)
+ badgeDrawable.draw(canvas)
+ }
+
+ override fun setAlpha(alpha: Int) {
+ drawable.alpha = alpha
+ }
+
+ override fun setColorFilter(colorFilter: ColorFilter?) {
+ drawable.colorFilter = colorFilter
+ }
+
+ @PixelFormat.Opacity
+ override fun getOpacity(): Int = PixelFormat.OPAQUE
+ }
+}
+
+private fun extractAvatarFromRow(entry: NotificationEntry): Drawable? =
+ entry.row
+ ?.childrenWithId(R.id.expanded)
+ ?.mapNotNull { it as? ViewGroup }
+ ?.flatMap {
+ it.childrenWithId(com.android.internal.R.id.status_bar_latest_event_content)
+ }
+ ?.mapNotNull {
+ it.findViewById<ViewGroup>(com.android.internal.R.id.notification_messaging)
+ }
+ ?.mapNotNull { messagesView ->
+ messagesView.children
+ .mapNotNull { it as? MessagingGroup }
+ .lastOrNull()
+ ?.findViewById<ImageView>(com.android.internal.R.id.message_icon)
+ ?.drawable
+ }
+ ?.firstOrNull()
+
+private fun NotificationEntry.extractPersonKey(): PersonKey? =
+ if (isMessagingNotification()) key else null
+
+private fun NotificationEntry.isMessagingNotification() =
+ sbn.notification.notificationStyle == Notification.MessagingStyle::class.java \ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleHubViewController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleHubViewController.kt
new file mode 100644
index 000000000000..5c354089dfe9
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleHubViewController.kt
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.notification.people
+
+import android.view.View
+import com.android.systemui.plugins.ActivityStarter
+import com.android.systemui.statusbar.notification.stack.NotificationSectionsManager
+import javax.inject.Inject
+import javax.inject.Singleton
+
+/** Boundary between the View and PeopleHub, as seen by the View. */
+interface PeopleHubSectionFooterViewAdapter {
+ fun bindView(viewBoundary: PeopleHubSectionFooterViewBoundary)
+}
+
+/** Abstract `View` representation of PeopleHub footer in [NotificationSectionsManager]. */
+interface PeopleHubSectionFooterViewBoundary {
+ /** View used for animating the activity launch caused by clicking a person in the hub. */
+ val associatedViewForClickAnimation: View
+
+ /** [DataListener]s for individual people in the hub. */
+ val personViewAdapters: Sequence<DataListener<PersonViewModel?>>
+
+ /** Sets the visibility of the Hub in the notification shade. */
+ fun setVisible(isVisible: Boolean)
+}
+
+/** Creates a [PeopleHubViewModel] given some additional information required from the `View`. */
+interface PeopleHubViewModelFactory {
+
+ /**
+ * Creates a [PeopleHubViewModel] that, when clicked, starts an activity using an animation
+ * involving the given [view].
+ */
+ fun createWithAssociatedClickView(view: View): PeopleHubViewModel
+}
+
+/**
+ * Wraps a [PeopleHubSectionFooterViewBoundary] in a [DataListener], and connects it to the data
+ * pipeline.
+ *
+ * @param dataSource PeopleHub data pipeline.
+ */
+@Singleton
+class PeopleHubSectionFooterViewAdapterImpl @Inject constructor(
+ private val dataSource: DataSource<@JvmSuppressWildcards PeopleHubViewModelFactory>
+) : PeopleHubSectionFooterViewAdapter {
+
+ override fun bindView(viewBoundary: PeopleHubSectionFooterViewBoundary) {
+ dataSource.registerListener(PeopleHubDataListenerImpl(viewBoundary))
+ }
+}
+
+private class PeopleHubDataListenerImpl(
+ private val viewBoundary: PeopleHubSectionFooterViewBoundary
+) : DataListener<PeopleHubViewModelFactory> {
+
+ override fun onDataChanged(data: PeopleHubViewModelFactory) {
+ val viewModel = data.createWithAssociatedClickView(
+ viewBoundary.associatedViewForClickAnimation
+ )
+ viewBoundary.setVisible(viewModel.isVisible)
+ val padded = viewModel.people + repeated(null)
+ for ((personAdapter, personModel) in viewBoundary.personViewAdapters.zip(padded)) {
+ personAdapter.onDataChanged(personModel)
+ }
+ }
+}
+
+/**
+ * Converts [PeopleHubModel]s into [PeopleHubViewModelFactory]s.
+ *
+ * This class serves as the glue between the View layer (which depends on
+ * [PeopleHubSectionFooterViewBoundary]) and the Data layer (which produces [PeopleHubModel]s).
+ */
+@Singleton
+class PeopleHubViewModelFactoryDataSourceImpl @Inject constructor(
+ private val activityStarter: ActivityStarter,
+ private val dataSource: DataSource<@JvmSuppressWildcards PeopleHubModel>
+) : DataSource<PeopleHubViewModelFactory> {
+
+ override fun registerListener(listener: DataListener<PeopleHubViewModelFactory>) =
+ dataSource.registerListener(PeopleHubModelListenerImpl(activityStarter, listener))
+}
+
+private class PeopleHubModelListenerImpl(
+ private val activityStarter: ActivityStarter,
+ private val dataListener: DataListener<PeopleHubViewModelFactory>
+) : DataListener<PeopleHubModel> {
+
+ override fun onDataChanged(data: PeopleHubModel) =
+ dataListener.onDataChanged(PeopleHubViewModelFactoryImpl(data, activityStarter))
+}
+
+private class PeopleHubViewModelFactoryImpl(
+ private val data: PeopleHubModel,
+ private val activityStarter: ActivityStarter
+) : PeopleHubViewModelFactory {
+
+ override fun createWithAssociatedClickView(view: View): PeopleHubViewModel {
+ val personViewModels = data.people.asSequence().map { personModel ->
+ val onClick = {
+ activityStarter.startPendingIntentDismissingKeyguard(
+ personModel.clickIntent,
+ null,
+ view
+ )
+ }
+ PersonViewModel(personModel.name, personModel.avatar, onClick)
+ }
+ return PeopleHubViewModel(personViewModels, data.people.isNotEmpty())
+ }
+}
+
+private fun <T> repeated(value: T): Sequence<T> = sequence {
+ while (true) {
+ yield(value)
+ }
+} \ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleNotificationIdentifier.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleNotificationIdentifier.kt
new file mode 100644
index 000000000000..bfd4070846f3
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleNotificationIdentifier.kt
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.notification.people
+
+import android.app.Notification
+import android.service.notification.StatusBarNotification
+import javax.inject.Inject
+import javax.inject.Singleton
+
+interface PeopleNotificationIdentifier {
+ fun isPeopleNotification(sbn: StatusBarNotification): Boolean
+}
+
+@Singleton
+class PeopleNotificationIdentifierImpl @Inject constructor(
+ private val personExtractor: NotificationPersonExtractor
+) : PeopleNotificationIdentifier {
+
+ override fun isPeopleNotification(sbn: StatusBarNotification) =
+ sbn.notification.notificationStyle == Notification.MessagingStyle::class.java ||
+ personExtractor.extractPersonKey(sbn) != null
+} \ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/ViewPipeline.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/ViewPipeline.kt
new file mode 100644
index 000000000000..3ca3792a680f
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/ViewPipeline.kt
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.notification.people
+
+/** Boundary between a View and data pipeline, as seen by the pipeline. */
+interface DataListener<in T> {
+ fun onDataChanged(data: T)
+}
+
+/** Convert all data using the given [mapper] before invoking this [DataListener]. */
+fun <S, T> DataListener<T>.contraMap(mapper: (S) -> T): DataListener<S> = object : DataListener<S> {
+ override fun onDataChanged(data: S) = onDataChanged(mapper(data))
+}
+
+/** Boundary between a View and data pipeline, as seen by the View. */
+interface DataSource<out T> {
+ fun registerListener(listener: DataListener<T>): Subscription
+}
+
+/** Represents a registration with a [DataSource]. */
+interface Subscription {
+ /** Removes the previously registered [DataListener] from the [DataSource] */
+ fun unsubscribe()
+}
+
+/** Transform all data coming out of this [DataSource] using the given [mapper]. */
+fun <S, T> DataSource<S>.map(mapper: (S) -> T): DataSource<T> = object : DataSource<T> {
+ override fun registerListener(listener: DataListener<T>) =
+ registerListener(listener.contraMap(mapper))
+} \ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java
index 8d7325118139..a817f54e77ca 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java
@@ -180,6 +180,10 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView
initDimens();
}
+ public FalsingManager getFalsingManager() {
+ return mFalsingManager;
+ }
+
private void updateColors() {
mNormalColor = mContext.getColor(R.color.notification_material_background_color);
mTintedRippleColor = mContext.getColor(
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
index 0f6ce2153488..536db67a8795 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
@@ -74,7 +74,6 @@ import com.android.internal.widget.CachingIconView;
import com.android.systemui.Dependency;
import com.android.systemui.Interpolators;
import com.android.systemui.R;
-import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.plugins.PluginListener;
import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin.MenuItem;
@@ -221,7 +220,6 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
private ViewStub mGutsStub;
private boolean mIsSystemChildExpanded;
private boolean mIsPinned;
- private FalsingManager mFalsingManager;
private boolean mExpandAnimationRunning;
private AboveShelfChangedListener mAboveShelfChangedListener;
private HeadsUpManager mHeadsUpManager;
@@ -444,7 +442,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
*/
public void setEntry(@NonNull NotificationEntry entry) {
mEntry = entry;
- mStatusBarNotification = entry.notification;
+ mStatusBarNotification = entry.getSbn();
cacheIsSystemNotification();
}
@@ -1205,7 +1203,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
// Let's update our childrencontainer. This is intentionally not guarded with
// mIsSummaryWithChildren since we might have had children but not anymore.
if (mChildrenContainer != null) {
- mChildrenContainer.reInflateViews(mExpandClickListener, mEntry.notification);
+ mChildrenContainer.reInflateViews(mExpandClickListener, mEntry.getSbn());
}
if (mGuts != null) {
NotificationGuts oldGuts = mGuts;
@@ -1449,6 +1447,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
}
setDismissed(fromAccessibility);
if (mEntry.isClearable()) {
+ // TODO: beverlyt, log dismissal
// TODO: track dismiss sentiment
if (mOnDismissRunnable != null) {
mOnDismissRunnable.run();
@@ -1636,7 +1635,6 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
public ExpandableNotificationRow(Context context, AttributeSet attrs) {
super(context, attrs);
- mFalsingManager = Dependency.get(FalsingManager.class); // TODO: inject into a controller.
mNotificationInflater = new NotificationContentInflater(this);
mMenuRow = new NotificationMenuRow(mContext);
mImageResolver = new NotificationInlineImageResolver(context,
@@ -2208,7 +2206,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
* @param allowChildExpansion whether a call to this method allows expanding children
*/
public void setUserExpanded(boolean userExpanded, boolean allowChildExpansion) {
- mFalsingManager.setNotificationExpanded();
+ getFalsingManager().setNotificationExpanded();
if (mIsSummaryWithChildren && !shouldShowPublic() && allowChildExpansion
&& !mChildrenContainer.showingAsLowPriority()) {
final boolean wasExpanded = mGroupManager.isGroupExpanded(mStatusBarNotification);
@@ -2305,7 +2303,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
private void updateRippleAllowed() {
boolean allowed = isOnKeyguard()
- || mEntry.notification.getNotification().contentIntent == null;
+ || mEntry.getSbn().getNotification().contentIntent == null;
setRippleAllowed(allowed);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationBlockingHelperManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationBlockingHelperManager.java
index 73093c6f471f..37f63c9779f8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationBlockingHelperManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationBlockingHelperManager.java
@@ -139,7 +139,8 @@ public class NotificationBlockingHelperManager {
mBlockingHelperRow.setBlockingHelperShowing(false);
if (mBlockingHelperRow.isAttachedToWindow()) {
- Dependency.get(NotificationEntryManager.class).updateNotifications();
+ Dependency.get(NotificationEntryManager.class).updateNotifications(
+ "dismissCurrentBlockingHelper");
}
mBlockingHelperRow = null;
return true;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflater.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflater.java
index a612a1721c41..a91a119d4ea7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflater.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflater.java
@@ -230,7 +230,7 @@ public class NotificationContentInflater {
}
// Only inflate the ones that are set.
reInflateFlags &= mInflationFlags;
- StatusBarNotification sbn = mRow.getEntry().notification;
+ StatusBarNotification sbn = mRow.getEntry().getSbn();
// To check if the notification has inline image and preload inline image if necessary.
mRow.getImageResolver().preloadImages(sbn.getNotification());
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java
index f30a8b12ab39..b12c76c750a8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java
@@ -1097,7 +1097,7 @@ public class NotificationContentView extends FrameLayout {
}
public void onNotificationUpdated(NotificationEntry entry) {
- mStatusBarNotification = entry.notification;
+ mStatusBarNotification = entry.getSbn();
mOnContentViewInactiveListeners.clear();
mBeforeN = entry.targetSdk < Build.VERSION_CODES.N;
updateAllSingleLineViews();
@@ -1179,7 +1179,7 @@ public class NotificationContentView extends FrameLayout {
: mHeadsUpInflatedSmartReplies.getSmartRepliesAndActions();
if (DEBUG) {
Log.d(TAG, String.format("Adding suggestions for %s, %d actions, and %d replies.",
- entry.notification.getKey(),
+ entry.getSbn().getKey(),
mCurrentSmartRepliesAndActions.smartActions == null ? 0 :
mCurrentSmartRepliesAndActions.smartActions.actions.size(),
mCurrentSmartRepliesAndActions.smartReplies == null ? 0 :
@@ -1253,7 +1253,7 @@ public class NotificationContentView extends FrameLayout {
}
}
if (hasRemoteInput) {
- int color = entry.notification.getNotification().color;
+ int color = entry.getSbn().getNotification().color;
if (color == Notification.COLOR_DEFAULT) {
color = mContext.getColor(R.color.default_remote_input_background);
}
@@ -1267,7 +1267,7 @@ public class NotificationContentView extends FrameLayout {
if (existingPendingIntent != null || existing.isActive()) {
// The current action could be gone, or the pending intent no longer valid.
// If we find a matching action in the new notification, focus, otherwise close.
- Notification.Action[] actions = entry.notification.getNotification().actions;
+ Notification.Action[] actions = entry.getSbn().getNotification().actions;
if (existingPendingIntent != null) {
existing.setPendingIntent(existingPendingIntent);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGuts.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGuts.java
index 4700baae8fab..18d436ff7659 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGuts.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGuts.java
@@ -421,7 +421,7 @@ public class NotificationGuts extends FrameLayout {
}
/** Listener for animations executed in {@link #animateClose(int, int, boolean)}. */
- private static class AnimateCloseListener extends AnimatorListenerAdapter {
+ private class AnimateCloseListener extends AnimatorListenerAdapter {
final View mView;
private final GutsContent mGutsContent;
@@ -433,8 +433,10 @@ public class NotificationGuts extends FrameLayout {
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
- mView.setVisibility(View.GONE);
- mGutsContent.onFinishedClosing();
+ if (!isExposed()) {
+ mView.setVisibility(View.GONE);
+ mGutsContent.onFinishedClosing();
+ }
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java
index 9d0dd6b683cf..1de2cbb982a9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java
@@ -100,6 +100,7 @@ public class NotificationGutsManager implements Dumpable, NotificationLifetimeEx
protected String mKeyToRemoveOnGutsClosed;
private StatusBar mStatusBar;
+ private Runnable mOpenRunnable;
@Inject
public NotificationGutsManager(
@@ -343,6 +344,7 @@ public class NotificationGutsManager implements Dumpable, NotificationLifetimeEx
public void closeAndSaveGuts(boolean removeLeavebehinds, boolean force, boolean removeControls,
int x, int y, boolean resetMenu) {
if (mNotificationGutsExposed != null) {
+ mNotificationGutsExposed.removeCallbacks(mOpenRunnable);
mNotificationGutsExposed.closeControls(removeLeavebehinds, removeControls, x, y, force);
}
if (resetMenu) {
@@ -445,7 +447,7 @@ public class NotificationGutsManager implements Dumpable, NotificationLifetimeEx
// ensure that it's laid but not visible until actually laid out
guts.setVisibility(View.INVISIBLE);
// Post to ensure the the guts are properly laid out.
- guts.post(new Runnable() {
+ mOpenRunnable = new Runnable() {
@Override
public void run() {
if (row.getWindowToken() == null) {
@@ -470,7 +472,8 @@ public class NotificationGutsManager implements Dumpable, NotificationLifetimeEx
mListContainer.onHeightChanged(row, true /* needsAnimation */);
mGutsMenuItem = menuItem;
}
- });
+ };
+ guts.post(mOpenRunnable);
return true;
}
@@ -491,15 +494,17 @@ public class NotificationGutsManager implements Dumpable, NotificationLifetimeEx
@Override
public void setShouldManageLifetime(NotificationEntry entry, boolean shouldExtend) {
if (shouldExtend) {
- mKeyToRemoveOnGutsClosed = entry.key;
+ mKeyToRemoveOnGutsClosed = entry.getKey();
if (Log.isLoggable(TAG, Log.DEBUG)) {
- Log.d(TAG, "Keeping notification because it's showing guts. " + entry.key);
+ Log.d(TAG, "Keeping notification because it's showing guts. " + entry.getKey());
}
} else {
- if (mKeyToRemoveOnGutsClosed != null && mKeyToRemoveOnGutsClosed.equals(entry.key)) {
+ if (mKeyToRemoveOnGutsClosed != null
+ && mKeyToRemoveOnGutsClosed.equals(entry.getKey())) {
mKeyToRemoveOnGutsClosed = null;
if (Log.isLoggable(TAG, Log.DEBUG)) {
- Log.d(TAG, "Notification that was kept for guts was updated. " + entry.key);
+ Log.d(TAG, "Notification that was kept for guts was updated. "
+ + entry.getKey());
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMediaTemplateViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMediaTemplateViewWrapper.java
index 0e0802ef233f..23643133e121 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMediaTemplateViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMediaTemplateViewWrapper.java
@@ -28,6 +28,7 @@ import android.media.session.MediaSession;
import android.media.session.PlaybackState;
import android.metrics.LogMaker;
import android.os.Handler;
+import android.provider.Settings;
import android.text.format.DateUtils;
import android.view.LayoutInflater;
import android.view.View;
@@ -43,9 +44,12 @@ import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.widget.MediaNotificationView;
import com.android.systemui.Dependency;
+import com.android.systemui.qs.QSPanel;
+import com.android.systemui.qs.QuickQSPanel;
import com.android.systemui.statusbar.NotificationMediaManager;
import com.android.systemui.statusbar.TransformableView;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
+import com.android.systemui.statusbar.phone.StatusBarWindowController;
import java.util.Timer;
import java.util.TimerTask;
@@ -188,9 +192,29 @@ public class NotificationMediaTemplateViewWrapper extends NotificationTemplateVi
mActions = mView.findViewById(com.android.internal.R.id.media_actions);
mIsViewVisible = mView.isShown();
- final MediaSession.Token token = mRow.getEntry().notification.getNotification().extras
+ final MediaSession.Token token = mRow.getEntry().getSbn().getNotification().extras
.getParcelable(Notification.EXTRA_MEDIA_SESSION);
+ int flag = Settings.System.getInt(mContext.getContentResolver(), "qs_media_player", 0);
+ if (flag == 1) {
+ StatusBarWindowController ctrl = Dependency.get(StatusBarWindowController.class);
+ QuickQSPanel panel = ctrl.getStatusBarView().findViewById(
+ com.android.systemui.R.id.quick_qs_panel);
+ panel.getMediaPlayer().setMediaSession(token,
+ mRow.getStatusBarNotification().getNotification().getSmallIcon(),
+ getNotificationHeader().getOriginalIconColor(),
+ mRow.getCurrentBackgroundTint(),
+ mActions);
+ QSPanel bigPanel = ctrl.getStatusBarView().findViewById(
+ com.android.systemui.R.id.quick_settings_panel);
+ bigPanel.addMediaSession(token,
+ mRow.getStatusBarNotification().getNotification().getSmallIcon(),
+ getNotificationHeader().getOriginalIconColor(),
+ mRow.getCurrentBackgroundTint(),
+ mActions,
+ mRow.getStatusBarNotification());
+ }
+
boolean showCompactSeekbar = mMediaManager.getShowCompactMediaSeekbar();
if (token == null || (COMPACT_MEDIA_TAG.equals(mView.getTag()) && !showCompactSeekbar)) {
if (mSeekBarView != null) {
@@ -431,7 +455,7 @@ public class NotificationMediaTemplateViewWrapper extends NotificationTemplateVi
* @return new LogMaker
*/
private LogMaker newLog(int event) {
- String packageName = mRow.getEntry().notification.getPackageName();
+ String packageName = mRow.getEntry().getSbn().getPackageName();
return new LogMaker(MetricsEvent.MEDIA_NOTIFICATION_SEEKBAR)
.setType(event)
@@ -443,7 +467,7 @@ public class NotificationMediaTemplateViewWrapper extends NotificationTemplateVi
* @return new LogMaker
*/
private LogMaker newLog(int event, int subtype) {
- String packageName = mRow.getEntry().notification.getPackageName();
+ String packageName = mRow.getEntry().getSbn().getPackageName();
return new LogMaker(MetricsEvent.MEDIA_NOTIFICATION_SEEKBAR)
.setType(event)
.setSubtype(subtype)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapper.java
index 3950003e64ce..c2eff8a6a776 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapper.java
@@ -63,7 +63,7 @@ public abstract class NotificationViewWrapper implements TransformableView {
return new NotificationMessagingTemplateViewWrapper(ctx, v, row);
}
Class<? extends Notification.Style> style =
- row.getEntry().notification.getNotification().getNotificationStyle();
+ row.getEntry().getSbn().getNotification().getNotificationStyle();
if (Notification.DecoratedCustomViewStyle.class.equals(style)) {
return new NotificationDecoratedCustomViewWrapper(ctx, v, row);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AmbientState.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AmbientState.java
index f3d068a9d610..ecab188a7481 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AmbientState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AmbientState.java
@@ -22,7 +22,6 @@ import android.content.Context;
import android.util.MathUtils;
import android.view.View;
-import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.statusbar.NotificationShelf;
import com.android.systemui.statusbar.StatusBarState;
@@ -410,7 +409,7 @@ public class AmbientState {
if (!mPulsing || mHeadUpManager == null) {
return false;
}
- return mHeadUpManager.isAlerting(entry.key);
+ return mHeadUpManager.isAlerting(entry.getKey());
}
public boolean isPanelTracking() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationRoundnessManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationRoundnessManager.java
index ec0c6348fd89..b4f7b59349d2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationRoundnessManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationRoundnessManager.java
@@ -16,10 +16,9 @@
package com.android.systemui.statusbar.notification.stack;
-import android.content.Context;
import android.util.MathUtils;
-import com.android.systemui.statusbar.notification.collection.NotificationData;
+import com.android.systemui.statusbar.notification.NotificationSectionsFeatureManager;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.row.ActivatableNotificationView;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
@@ -52,8 +51,8 @@ public class NotificationRoundnessManager implements OnHeadsUpChangedListener {
@Inject
NotificationRoundnessManager(
KeyguardBypassController keyguardBypassController,
- Context context) {
- int numberOfSections = NotificationData.getNotificationBuckets(context).length;
+ NotificationSectionsFeatureManager sectionsFeatureManager) {
+ int numberOfSections = sectionsFeatureManager.getNumberOfBuckets();
mFirstInSectionViews = new ActivatableNotificationView[numberOfSections];
mLastInSectionViews = new ActivatableNotificationView[numberOfSections];
mTmpFirstInSectionViews = new ActivatableNotificationView[numberOfSections];
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.java
index d0444ae81b89..54d406615ae0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.java
@@ -23,6 +23,7 @@ import static java.lang.annotation.RetentionPolicy.SOURCE;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.app.PendingIntent;
import android.content.Intent;
import android.provider.Settings;
import android.view.LayoutInflater;
@@ -33,6 +34,10 @@ import com.android.systemui.R;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.StatusBarState;
+import com.android.systemui.statusbar.notification.people.DataListener;
+import com.android.systemui.statusbar.notification.people.PeopleHubSectionFooterViewAdapter;
+import com.android.systemui.statusbar.notification.people.PeopleHubSectionFooterViewBoundary;
+import com.android.systemui.statusbar.notification.people.PersonViewModel;
import com.android.systemui.statusbar.notification.row.ActivatableNotificationView;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.policy.ConfigurationController;
@@ -42,6 +47,8 @@ import java.lang.annotation.Retention;
import java.util.ArrayList;
import java.util.List;
+import kotlin.sequences.Sequence;
+
/**
* Manages the boundaries of the two notification sections (high priority and low priority). Also
* shows/hides the headers for those sections where appropriate.
@@ -58,11 +65,39 @@ public class NotificationSectionsManager implements StackScrollAlgorithm.Section
private final StatusBarStateController mStatusBarStateController;
private final ConfigurationController mConfigurationController;
private final int mNumberOfSections;
-
private boolean mInitialized = false;
+
private SectionHeaderView mGentleHeader;
private boolean mGentleHeaderVisible = false;
+ private boolean mPeopleHubVisible = false;
+ private PeopleHubView mPeopleHubView;
+ private final PeopleHubSectionFooterViewAdapter mPeopleHubViewAdapter;
+ private final PeopleHubSectionFooterViewBoundary mPeopleHubViewBoundary =
+ new PeopleHubSectionFooterViewBoundary() {
+ @Override
+ public void setVisible(boolean isVisible) {
+ if (mPeopleHubVisible != isVisible) {
+ mPeopleHubVisible = isVisible;
+ if (mInitialized) {
+ updateSectionBoundaries();
+ }
+ }
+ }
+
+ @NonNull
+ @Override
+ public View getAssociatedViewForClickAnimation() {
+ return mPeopleHubView;
+ }
+
+ @NonNull
+ @Override
+ public Sequence<DataListener<PersonViewModel>> getPersonViewAdapters() {
+ return mPeopleHubView.getPersonViewAdapters();
+ }
+ };
+
@Nullable private View.OnClickListener mOnClearGentleNotifsClickListener;
NotificationSectionsManager(
@@ -70,11 +105,13 @@ public class NotificationSectionsManager implements StackScrollAlgorithm.Section
ActivityStarter activityStarter,
StatusBarStateController statusBarStateController,
ConfigurationController configurationController,
+ PeopleHubSectionFooterViewAdapter peopleHubViewAdapter,
int numberOfSections) {
mParent = parent;
mActivityStarter = activityStarter;
mStatusBarStateController = statusBarStateController;
mConfigurationController = configurationController;
+ mPeopleHubViewAdapter = peopleHubViewAdapter;
mNumberOfSections = numberOfSections;
}
@@ -94,6 +131,7 @@ public class NotificationSectionsManager implements StackScrollAlgorithm.Section
}
mInitialized = true;
reinflateViews(layoutInflater);
+ mPeopleHubViewAdapter.bindView(mPeopleHubViewBoundary);
mConfigurationController.addCallback(mConfigurationListener);
}
@@ -101,23 +139,39 @@ public class NotificationSectionsManager implements StackScrollAlgorithm.Section
* Reinflates the entire notification header, including all decoration views.
*/
void reinflateViews(LayoutInflater layoutInflater) {
- int oldPos = -1;
+ int oldGentleHeaderPos = -1;
+ int oldPeopleHubPos = -1;
if (mGentleHeader != null) {
if (mGentleHeader.getTransientContainer() != null) {
mGentleHeader.getTransientContainer().removeView(mGentleHeader);
} else if (mGentleHeader.getParent() != null) {
- oldPos = mParent.indexOfChild(mGentleHeader);
+ oldGentleHeaderPos = mParent.indexOfChild(mGentleHeader);
mParent.removeView(mGentleHeader);
}
}
+ if (mPeopleHubView != null) {
+ if (mPeopleHubView.getTransientContainer() != null) {
+ mPeopleHubView.getTransientContainer().removeView(mPeopleHubView);
+ } else if (mPeopleHubView.getParent() != null) {
+ oldPeopleHubPos = mParent.indexOfChild(mPeopleHubView);
+ mParent.removeView(mPeopleHubView);
+ }
+ }
mGentleHeader = (SectionHeaderView) layoutInflater.inflate(
R.layout.status_bar_notification_section_header, mParent, false);
mGentleHeader.setOnHeaderClickListener(this::onGentleHeaderClick);
mGentleHeader.setOnClearAllClickListener(this::onClearGentleNotifsClick);
- if (oldPos != -1) {
- mParent.addView(mGentleHeader, oldPos);
+ if (oldGentleHeaderPos != -1) {
+ mParent.addView(mGentleHeader, oldGentleHeaderPos);
+ }
+
+ mPeopleHubView = (PeopleHubView) layoutInflater.inflate(
+ R.layout.people_strip, mParent, false);
+
+ if (oldPeopleHubPos != -1) {
+ mParent.addView(mPeopleHubView, oldPeopleHubPos);
}
}
@@ -145,7 +199,7 @@ public class NotificationSectionsManager implements StackScrollAlgorithm.Section
}
if (!begin) {
- begin = view == mGentleHeader;
+ begin = view == mGentleHeader || previous == mPeopleHubView;
}
return begin;
@@ -161,6 +215,8 @@ public class NotificationSectionsManager implements StackScrollAlgorithm.Section
return ((ExpandableNotificationRow) view).getEntry().getBucket();
} else if (view == mGentleHeader) {
return BUCKET_SILENT;
+ } else if (view == mPeopleHubView) {
+ return BUCKET_PEOPLE;
}
throw new IllegalArgumentException("I don't know how to find a bucket for this view :(");
@@ -175,6 +231,7 @@ public class NotificationSectionsManager implements StackScrollAlgorithm.Section
return;
}
+ int lastPersonIndex = -1;
int firstGentleNotifIndex = -1;
final int n = mParent.getChildCount();
@@ -183,6 +240,9 @@ public class NotificationSectionsManager implements StackScrollAlgorithm.Section
if (child instanceof ExpandableNotificationRow
&& child.getVisibility() != View.GONE) {
ExpandableNotificationRow row = (ExpandableNotificationRow) child;
+ if (row.getEntry().getBucket() == BUCKET_PEOPLE) {
+ lastPersonIndex = i;
+ }
if (row.getEntry().getBucket() == BUCKET_SILENT) {
firstGentleNotifIndex = i;
break;
@@ -190,6 +250,11 @@ public class NotificationSectionsManager implements StackScrollAlgorithm.Section
}
}
+ if (adjustPeopleHubVisibilityAndPosition(lastPersonIndex)) {
+ // make room for peopleHub
+ firstGentleNotifIndex++;
+ }
+
adjustGentleHeaderVisibilityAndPosition(firstGentleNotifIndex);
mGentleHeader.setAreThereDismissableGentleNotifs(
@@ -232,6 +297,36 @@ public class NotificationSectionsManager implements StackScrollAlgorithm.Section
}
}
+ private boolean adjustPeopleHubVisibilityAndPosition(int lastPersonIndex) {
+ final boolean showPeopleHeader = mPeopleHubVisible
+ && mNumberOfSections > 2
+ && mStatusBarStateController.getState() != StatusBarState.KEYGUARD;
+ final int currentHubIndex = mParent.indexOfChild(mPeopleHubView);
+ final boolean currentlyVisible = currentHubIndex >= 0;
+ int targetIndex = lastPersonIndex + 1;
+
+ if (!showPeopleHeader) {
+ if (currentlyVisible) {
+ mParent.removeView(mPeopleHubView);
+ }
+ } else {
+ if (!currentlyVisible) {
+ if (mPeopleHubView.getTransientContainer() != null) {
+ mPeopleHubView.getTransientContainer().removeTransientView(mPeopleHubView);
+ mPeopleHubView.setTransientContainer(null);
+ }
+ mParent.addView(mPeopleHubView, targetIndex);
+ return true;
+ } else if (currentHubIndex != targetIndex - 1) {
+ if (currentHubIndex < targetIndex) {
+ targetIndex--;
+ }
+ mParent.changeViewPosition(mPeopleHubView, targetIndex);
+ }
+ }
+ return false;
+ }
+
/**
* Updates the boundaries (as tracked by their first and last views) of the priority sections.
*
@@ -284,12 +379,12 @@ public class NotificationSectionsManager implements StackScrollAlgorithm.Section
ActivatableNotificationView first = s.getFirstVisibleChild();
String fs = first == null ? "(null)"
: (first instanceof ExpandableNotificationRow)
- ? ((ExpandableNotificationRow) first).getEntry().key
+ ? ((ExpandableNotificationRow) first).getEntry().getKey()
: Integer.toHexString(System.identityHashCode(first));
ActivatableNotificationView last = s.getLastVisibleChild();
String ls = last == null ? "(null)"
: (last instanceof ExpandableNotificationRow)
- ? ((ExpandableNotificationRow) last).getEntry().key
+ ? ((ExpandableNotificationRow) last).getEntry().getKey()
: Integer.toHexString(System.identityHashCode(last));
android.util.Log.d(TAG, "updateSections: f=" + fs + " s=" + i);
android.util.Log.d(TAG, "updateSections: l=" + ls + " s=" + i);
@@ -324,6 +419,10 @@ public class NotificationSectionsManager implements StackScrollAlgorithm.Section
}
}
+ private void handlePeopleHubClick(PendingIntent pendingIntent) {
+ mActivityStarter.startPendingIntentDismissingKeyguard(pendingIntent, null, mPeopleHubView);
+ }
+
/**
* For now, declare the available notification buckets (sections) here so that other
* presentation code can decide what to do based on an entry's buckets
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
index a67018ef9710..6dca7ee9e872 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
@@ -109,13 +109,14 @@ import com.android.systemui.statusbar.notification.DynamicPrivacyController;
import com.android.systemui.statusbar.notification.FakeShadowView;
import com.android.systemui.statusbar.notification.NotificationEntryListener;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
+import com.android.systemui.statusbar.notification.NotificationSectionsFeatureManager;
import com.android.systemui.statusbar.notification.NotificationUtils;
import com.android.systemui.statusbar.notification.ShadeViewRefactor;
import com.android.systemui.statusbar.notification.ShadeViewRefactor.RefactorComponent;
import com.android.systemui.statusbar.notification.VisualStabilityManager;
-import com.android.systemui.statusbar.notification.collection.NotificationData;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.logging.NotificationLogger;
+import com.android.systemui.statusbar.notification.people.PeopleHubSectionFooterViewAdapter;
import com.android.systemui.statusbar.notification.row.ActivatableNotificationView;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.row.ExpandableView;
@@ -473,8 +474,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
private int mHeadsUpInset;
private HeadsUpAppearanceController mHeadsUpAppearanceController;
private NotificationIconAreaController mIconAreaController;
- private final NotificationLockscreenUserManager mLockscreenUserManager =
- Dependency.get(NotificationLockscreenUserManager.class);
+ private final NotificationLockscreenUserManager mLockscreenUserManager;
private final Rect mTmpRect = new Rect();
private final NotificationEntryManager mEntryManager =
Dependency.get(NotificationEntryManager.class);
@@ -497,8 +497,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
private NotificationPanelView mNotificationPanel;
private final ShadeController mShadeController = Dependency.get(ShadeController.class);
- private final NotificationGutsManager
- mNotificationGutsManager = Dependency.get(NotificationGutsManager.class);
+ private final NotificationGutsManager mNotificationGutsManager;
private final NotificationSectionsManager mSectionsManager;
private boolean mAnimateBottomOnLayout;
private float mLastSentAppear;
@@ -517,7 +516,11 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
StatusBarStateController statusBarStateController,
HeadsUpManagerPhone headsUpManager,
KeyguardBypassController keyguardBypassController,
- FalsingManager falsingManager) {
+ FalsingManager falsingManager,
+ NotificationLockscreenUserManager notificationLockscreenUserManager,
+ NotificationGutsManager notificationGutsManager,
+ NotificationSectionsFeatureManager sectionsFeatureManager,
+ PeopleHubSectionFooterViewAdapter peopleHubViewAdapter) {
super(context, attrs, 0, 0);
Resources res = getResources();
@@ -525,19 +528,22 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
mRoundnessManager = notificationRoundnessManager;
+ mLockscreenUserManager = notificationLockscreenUserManager;
+ mNotificationGutsManager = notificationGutsManager;
mHeadsUpManager = headsUpManager;
mHeadsUpManager.addListener(mRoundnessManager);
mHeadsUpManager.setAnimationStateHandler(this::setHeadsUpGoingAwayAnimationsAllowed);
mKeyguardBypassController = keyguardBypassController;
mFalsingManager = falsingManager;
- int[] buckets = NotificationData.getNotificationBuckets(context);
+ int[] buckets = sectionsFeatureManager.getNotificationBuckets();
mSectionsManager =
new NotificationSectionsManager(
this,
activityStarter,
statusBarStateController,
configurationController,
+ peopleHubViewAdapter,
buckets.length);
mSectionsManager.initialize(LayoutInflater.from(context));
mSectionsManager.setOnClearGentleNotifsClickListener(v -> {
@@ -599,7 +605,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
mEntryManager.addNotificationEntryListener(new NotificationEntryListener() {
@Override
public void onPostEntryUpdated(NotificationEntry entry) {
- if (!entry.notification.isClearable()) {
+ if (!entry.getSbn().isClearable()) {
// The user may have performed a dismiss action on the notification, since it's
// not clearable we should snap it back.
snapViewIfNeeded(entry);
@@ -1624,7 +1630,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
if (!mIsExpanded && row.isHeadsUp() && row.isPinned()
&& mHeadsUpManager.getTopEntry().getRow() != row
&& mGroupManager.getGroupSummary(
- mHeadsUpManager.getTopEntry().notification)
+ mHeadsUpManager.getTopEntry().getSbn())
!= entry) {
continue;
}
@@ -5332,7 +5338,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
requestChildrenUpdate();
onUpdateRowStates();
- mEntryManager.updateNotifications();
+ mEntryManager.updateNotifications("StatusBar state changed");
updateVisibility();
}
@@ -5522,12 +5528,12 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
// TODO: This is a listener method; we shouldn't be calling it. Can we just
// call performRemoveNotification as below?
mEntryManager.removeNotification(
- rowToRemove.getEntry().key,
+ rowToRemove.getEntry().getKey(),
null /* ranking */,
NotificationListenerService.REASON_CANCEL_ALL);
} else {
mEntryManager.performRemoveNotification(
- rowToRemove.getEntry().notification,
+ rowToRemove.getEntry().getSbn(),
NotificationListenerService.REASON_CANCEL_ALL);
}
} else {
@@ -6491,12 +6497,12 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
@Override
public void onGroupCreatedFromChildren(NotificationGroupManager.NotificationGroup group) {
- mStatusBar.requestNotificationUpdate();
+ mStatusBar.requestNotificationUpdate("onGroupCreatedFromChildren");
}
@Override
public void onGroupsChanged() {
- mStatusBar.requestNotificationUpdate();
+ mStatusBar.requestNotificationUpdate("onGroupsChanged");
}
};
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/PeopleHubView.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/PeopleHubView.kt
new file mode 100644
index 000000000000..e31ee024fa36
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/PeopleHubView.kt
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.notification.stack
+
+import android.content.Context
+import android.util.AttributeSet
+import android.view.View
+import android.view.ViewGroup
+import android.widget.ImageView
+import android.widget.LinearLayout
+import android.widget.TextView
+import com.android.systemui.R
+import com.android.systemui.statusbar.notification.people.PersonViewModel
+import com.android.systemui.statusbar.notification.people.DataListener
+import com.android.systemui.statusbar.notification.row.ActivatableNotificationView
+
+class PeopleHubView(context: Context, attrs: AttributeSet) :
+ ActivatableNotificationView(context, attrs) {
+
+ private lateinit var contents: ViewGroup
+ private lateinit var personControllers: List<PersonDataListenerImpl>
+ val personViewAdapters: Sequence<DataListener<PersonViewModel?>>
+ get() = personControllers.asSequence()
+
+ override fun onFinishInflate() {
+ super.onFinishInflate()
+ contents = requireViewById(R.id.people_list)
+ personControllers = (0 until contents.childCount)
+ .asSequence()
+ .mapNotNull { idx ->
+ (contents.getChildAt(idx) as? LinearLayout)?.let(::PersonDataListenerImpl)
+ }
+ .toList()
+ }
+
+ override fun getContentView(): View = contents
+
+ private inner class PersonDataListenerImpl(val viewGroup: ViewGroup) :
+ DataListener<PersonViewModel?> {
+
+ val nameView = viewGroup.requireViewById<TextView>(R.id.person_name)
+ val avatarView = viewGroup.requireViewById<ImageView>(R.id.person_icon)
+
+ override fun onDataChanged(data: PersonViewModel?) {
+ viewGroup.visibility = data?.let { View.VISIBLE } ?: View.INVISIBLE
+ nameView.text = data?.name
+ avatarView.setImageDrawable(data?.icon)
+ viewGroup.setOnClickListener { data?.onClick?.invoke() }
+ }
+ }
+} \ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoHideController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoHideController.java
index 5912cd7b6433..f9b936763308 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoHideController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoHideController.java
@@ -16,75 +16,52 @@
package com.android.systemui.statusbar.phone;
-import static com.android.systemui.Dependency.MAIN_HANDLER_NAME;
-import static com.android.systemui.statusbar.phone.BarTransitions.MODE_SEMI_TRANSPARENT;
-
import android.content.Context;
-import android.graphics.Rect;
import android.os.Handler;
import android.os.RemoteException;
import android.util.Log;
import android.view.IWindowManager;
import android.view.MotionEvent;
-import android.view.View;
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.systemui.Dependency;
-import com.android.systemui.SysUiServiceProvider;
-import com.android.systemui.statusbar.CommandQueue;
+import com.android.systemui.dagger.qualifiers.MainHandler;
import com.android.systemui.statusbar.NotificationRemoteInputManager;
import javax.inject.Inject;
-import javax.inject.Named;
/** A controller to control all auto-hide things. */
-public class AutoHideController implements CommandQueue.Callbacks {
+public class AutoHideController {
private static final String TAG = "AutoHideController";
private final IWindowManager mWindowManagerService;
private final Handler mHandler;
private final NotificationRemoteInputManager mRemoteInputManager;
- private final CommandQueue mCommandQueue;
private StatusBar mStatusBar;
private NavigationBarFragment mNavigationBar;
- @VisibleForTesting
- int mDisplayId;
- @VisibleForTesting
- int mSystemUiVisibility;
- // last value sent to window manager
- private int mLastDispatchedSystemUiVisibility = ~View.SYSTEM_UI_FLAG_VISIBLE;
+ private int mDisplayId;
private boolean mAutoHideSuspended;
- private static final long AUTOHIDE_TIMEOUT_MS = 2250;
+ private static final long AUTO_HIDE_TIMEOUT_MS = 2250;
private final Runnable mAutoHide = () -> {
- int requested = mSystemUiVisibility & ~getTransientMask();
- if (mSystemUiVisibility != requested) {
- notifySystemUiVisibilityChanged(requested);
+ if (isAnyTransientBarShown()) {
+ hideTransientBars();
}
};
@Inject
- public AutoHideController(Context context, @Named(MAIN_HANDLER_NAME) Handler handler) {
- mCommandQueue = SysUiServiceProvider.getComponent(context, CommandQueue.class);
- mCommandQueue.addCallback(this);
+ public AutoHideController(Context context, @MainHandler Handler handler,
+ NotificationRemoteInputManager notificationRemoteInputManager,
+ IWindowManager iWindowManager) {
mHandler = handler;
- mRemoteInputManager = Dependency.get(NotificationRemoteInputManager.class);
- mWindowManagerService = Dependency.get(IWindowManager.class);
+ mRemoteInputManager = notificationRemoteInputManager;
+ mWindowManagerService = iWindowManager;
mDisplayId = context.getDisplayId();
}
- @Override
- public void onDisplayRemoved(int displayId) {
- if (displayId == mDisplayId) {
- mCommandQueue.removeCallback(this);
- }
- }
-
void setStatusBar(StatusBar statusBar) {
mStatusBar = statusBar;
}
@@ -93,50 +70,18 @@ public class AutoHideController implements CommandQueue.Callbacks {
mNavigationBar = navigationBar;
}
- @Override
- public void setSystemUiVisibility(int displayId, int vis, int fullscreenStackVis,
- int dockedStackVis, int mask, Rect fullscreenStackBounds, Rect dockedStackBounds,
- boolean navbarColorManagedByIme) {
- if (displayId != mDisplayId) {
- return;
- }
- int oldVal = mSystemUiVisibility;
- int newVal = (oldVal & ~mask) | (vis & mask);
- int diff = newVal ^ oldVal;
-
- if (diff != 0) {
- mSystemUiVisibility = newVal;
-
- // ready to unhide
- if (hasStatusBar() && (vis & View.STATUS_BAR_UNHIDE) != 0) {
- mSystemUiVisibility &= ~View.STATUS_BAR_UNHIDE;
- }
-
- if (hasNavigationBar() && (vis & View.NAVIGATION_BAR_UNHIDE) != 0) {
- mSystemUiVisibility &= ~View.NAVIGATION_BAR_UNHIDE;
- }
-
- // Re-send setSystemUiVisibility to update un-hide status.
- if (mSystemUiVisibility != newVal) {
- mCommandQueue.setSystemUiVisibility(mDisplayId, mSystemUiVisibility,
- fullscreenStackVis, dockedStackVis, mask, fullscreenStackBounds,
- dockedStackBounds, navbarColorManagedByIme);
- }
-
- notifySystemUiVisibilityChanged(mSystemUiVisibility);
- }
- }
-
- @VisibleForTesting
- void notifySystemUiVisibilityChanged(int vis) {
+ private void hideTransientBars() {
try {
- if (mLastDispatchedSystemUiVisibility != vis) {
- mWindowManagerService.statusBarVisibilityChanged(mDisplayId, vis);
- mLastDispatchedSystemUiVisibility = vis;
- }
+ mWindowManagerService.hideTransientBars(mDisplayId);
} catch (RemoteException ex) {
Log.w(TAG, "Cannot get WindowManager");
}
+ if (mStatusBar != null) {
+ mStatusBar.clearTransient();
+ }
+ if (mNavigationBar != null) {
+ mNavigationBar.clearTransient();
+ }
}
void resumeSuspendedAutoHide() {
@@ -155,13 +100,12 @@ public class AutoHideController implements CommandQueue.Callbacks {
if (checkBarModesRunnable != null) {
mHandler.removeCallbacks(checkBarModesRunnable);
}
- mAutoHideSuspended = (mSystemUiVisibility & getTransientMask()) != 0;
+ mAutoHideSuspended = isAnyTransientBarShown();
}
void touchAutoHide() {
// update transient bar auto hide
- if ((hasStatusBar() && mStatusBar.getStatusBarMode() == MODE_SEMI_TRANSPARENT)
- || hasNavigationBar() && mNavigationBar.isSemiTransparent()) {
+ if (isAnyTransientBarShown()) {
scheduleAutoHide();
} else {
cancelAutoHide();
@@ -169,9 +113,9 @@ public class AutoHideController implements CommandQueue.Callbacks {
}
private Runnable getCheckBarModesRunnable() {
- if (hasStatusBar()) {
+ if (mStatusBar != null) {
return () -> mStatusBar.checkBarModes();
- } else if (hasNavigationBar()) {
+ } else if (mNavigationBar != null) {
return () -> mNavigationBar.checkNavBarModes();
} else {
return null;
@@ -185,15 +129,14 @@ public class AutoHideController implements CommandQueue.Callbacks {
private void scheduleAutoHide() {
cancelAutoHide();
- mHandler.postDelayed(mAutoHide, AUTOHIDE_TIMEOUT_MS);
+ mHandler.postDelayed(mAutoHide, AUTO_HIDE_TIMEOUT_MS);
}
void checkUserAutoHide(MotionEvent event) {
- boolean shouldAutoHide =
- (mSystemUiVisibility & getTransientMask()) != 0 // a transient bar is revealed.
+ boolean shouldAutoHide = isAnyTransientBarShown()
&& event.getAction() == MotionEvent.ACTION_OUTSIDE // touch outside the source bar.
&& event.getX() == 0 && event.getY() == 0;
- if (hasStatusBar()) {
+ if (mStatusBar != null) {
// a touch outside both bars
shouldAutoHide &= !mRemoteInputManager.getController().isRemoteInputActive();
}
@@ -207,23 +150,8 @@ public class AutoHideController implements CommandQueue.Callbacks {
mHandler.postDelayed(mAutoHide, 350); // longer than app gesture -> flag clear
}
- private int getTransientMask() {
- int mask = 0;
- if (hasStatusBar()) {
- mask |= View.STATUS_BAR_TRANSIENT;
- }
- if (hasNavigationBar()) {
- mask |= View.NAVIGATION_BAR_TRANSIENT;
- }
- return mask;
- }
-
- boolean hasNavigationBar() {
- return mNavigationBar != null;
- }
-
- @VisibleForTesting
- boolean hasStatusBar() {
- return mStatusBar != null;
+ private boolean isAnyTransientBarShown() {
+ return (mStatusBar != null && mStatusBar.isTransientShown())
+ || mNavigationBar != null && mNavigationBar.isTransientShown();
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java
index 007c50c8765d..837517e2cc9b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java
@@ -21,7 +21,7 @@ import android.os.Handler;
import android.provider.Settings.Secure;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.systemui.Dependency;
+import com.android.systemui.dagger.qualifiers.BgHandler;
import com.android.systemui.qs.AutoAddTracker;
import com.android.systemui.qs.QSTileHost;
import com.android.systemui.qs.SecureSetting;
@@ -33,7 +33,6 @@ import com.android.systemui.statusbar.policy.HotspotController;
import com.android.systemui.statusbar.policy.HotspotController.Callback;
import javax.inject.Inject;
-import javax.inject.Named;
/**
* Manages which tiles should be automatically added to QS.
@@ -58,7 +57,7 @@ public class AutoTileManager {
@Inject
public AutoTileManager(Context context, AutoAddTracker autoAddTracker, QSTileHost host,
- @Named(Dependency.BG_HANDLER_NAME) Handler handler,
+ @BgHandler Handler handler,
HotspotController hotspotController,
DataSaverController dataSaverController,
ManagedProfileController managedProfileController,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BarTransitions.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BarTransitions.java
index 211a40a91101..e6731e6b8a34 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BarTransitions.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BarTransitions.java
@@ -44,11 +44,11 @@ public class BarTransitions {
private static final boolean DEBUG = false;
private static final boolean DEBUG_COLORS = false;
- public static final int MODE_OPAQUE = 0;
+ public static final int MODE_TRANSPARENT = 0;
public static final int MODE_SEMI_TRANSPARENT = 1;
public static final int MODE_TRANSLUCENT = 2;
public static final int MODE_LIGHTS_OUT = 3;
- public static final int MODE_TRANSPARENT = 4;
+ public static final int MODE_OPAQUE = 4;
public static final int MODE_WARNING = 5;
public static final int MODE_LIGHTS_OUT_TRANSPARENT = 6;
@@ -72,7 +72,7 @@ public class BarTransitions {
private final View mView;
protected final BarBackgroundDrawable mBarBackground;
- private int mMode;
+ private @TransitionMode int mMode;
private boolean mAlwaysOpaque = false;
public BarTransitions(View view, int gradientResourceId) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
index 2d012c93f42b..bd3d848eaf7f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
@@ -18,6 +18,7 @@ package com.android.systemui.statusbar.phone;
import android.annotation.IntDef;
import android.content.Context;
+import android.content.res.Resources;
import android.hardware.biometrics.BiometricSourceType;
import android.metrics.LogMaker;
import android.os.Handler;
@@ -34,24 +35,28 @@ import com.android.keyguard.KeyguardConstants;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.keyguard.KeyguardUpdateMonitorCallback;
import com.android.systemui.Dependency;
+import com.android.systemui.dagger.qualifiers.MainResources;
import com.android.systemui.keyguard.KeyguardViewMediator;
import com.android.systemui.keyguard.ScreenLifecycle;
import com.android.systemui.keyguard.WakefulnessLifecycle;
import com.android.systemui.statusbar.NotificationMediaManager;
+import com.android.systemui.statusbar.policy.KeyguardStateController;
import java.io.PrintWriter;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
+import javax.inject.Inject;
+
/**
* Controller which coordinates all the biometric unlocking actions with the UI.
*/
public class BiometricUnlockController extends KeyguardUpdateMonitorCallback {
- private static final String TAG = "BiometricUnlockController";
+ private static final String TAG = "BiometricUnlockCtrl";
private static final boolean DEBUG_BIO_WAKELOCK = KeyguardConstants.DEBUG_BIOMETRIC_WAKELOCK;
private static final long BIOMETRIC_WAKELOCK_TIMEOUT_MS = 15 * 1000;
- private static final String BIOMETRIC_WAKE_LOCK_NAME = "wake-and-unlock wakelock";
+ private static final String BIOMETRIC_WAKE_LOCK_NAME = "wake-and-unlock:wakelock";
@IntDef(prefix = { "MODE_" }, value = {
MODE_NONE,
@@ -127,7 +132,8 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback {
private final KeyguardBypassController mKeyguardBypassController;
private PowerManager.WakeLock mWakeLock;
private final KeyguardUpdateMonitor mUpdateMonitor;
- private final UnlockMethodCache mUnlockMethodCache;
+ private DozeParameters mDozeParameters;
+ private final KeyguardStateController mKeyguardStateController;
private final StatusBarWindowController mStatusBarWindowController;
private final Context mContext;
private final int mWakeUpDelay;
@@ -143,36 +149,20 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback {
private boolean mHasScreenTurnedOnSinceAuthenticating;
private boolean mFadedAwayAfterWakeAndUnlock;
- private final MetricsLogger mMetricsLogger = Dependency.get(MetricsLogger.class);
+ private final MetricsLogger mMetricsLogger;
- public BiometricUnlockController(Context context,
- DozeScrimController dozeScrimController,
- KeyguardViewMediator keyguardViewMediator,
- ScrimController scrimController,
- StatusBar statusBar,
- UnlockMethodCache unlockMethodCache, Handler handler,
+ @Inject
+ public BiometricUnlockController(Context context, DozeScrimController dozeScrimController,
+ KeyguardViewMediator keyguardViewMediator, ScrimController scrimController,
+ StatusBar statusBar, KeyguardStateController keyguardStateController, Handler handler,
KeyguardUpdateMonitor keyguardUpdateMonitor,
- KeyguardBypassController keyguardBypassController) {
- this(context, dozeScrimController, keyguardViewMediator, scrimController, statusBar,
- unlockMethodCache, handler, keyguardUpdateMonitor,
- context.getResources()
- .getInteger(com.android.internal.R.integer.config_wakeUpDelayDoze),
- keyguardBypassController);
- }
-
- @VisibleForTesting
- protected BiometricUnlockController(Context context,
- DozeScrimController dozeScrimController,
- KeyguardViewMediator keyguardViewMediator,
- ScrimController scrimController,
- StatusBar statusBar,
- UnlockMethodCache unlockMethodCache, Handler handler,
- KeyguardUpdateMonitor keyguardUpdateMonitor,
- int wakeUpDelay,
- KeyguardBypassController keyguardBypassController) {
+ @MainResources Resources resources,
+ KeyguardBypassController keyguardBypassController, DozeParameters dozeParameters,
+ MetricsLogger metricsLogger) {
mContext = context;
mPowerManager = context.getSystemService(PowerManager.class);
mUpdateMonitor = keyguardUpdateMonitor;
+ mDozeParameters = dozeParameters;
mUpdateMonitor.registerCallback(this);
mMediaManager = Dependency.get(NotificationMediaManager.class);
Dependency.get(WakefulnessLifecycle.class).addObserver(mWakefulnessObserver);
@@ -182,11 +172,12 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback {
mKeyguardViewMediator = keyguardViewMediator;
mScrimController = scrimController;
mStatusBar = statusBar;
- mUnlockMethodCache = unlockMethodCache;
+ mKeyguardStateController = keyguardStateController;
mHandler = handler;
- mWakeUpDelay = wakeUpDelay;
+ mWakeUpDelay = resources.getInteger(com.android.internal.R.integer.config_wakeUpDelayDoze);
mKeyguardBypassController = keyguardBypassController;
mKeyguardBypassController.setUnlockController(this);
+ mMetricsLogger = metricsLogger;
}
public void setStatusBarKeyguardViewManager(
@@ -286,7 +277,7 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback {
}
// During wake and unlock, we need to draw black before waking up to avoid abrupt
// brightness changes due to display state transitions.
- boolean alwaysOnEnabled = DozeParameters.getInstance(mContext).getAlwaysOn();
+ boolean alwaysOnEnabled = mDozeParameters.getAlwaysOn();
boolean delayWakeUp = mode == MODE_WAKE_AND_UNLOCK && alwaysOnEnabled && mWakeUpDelay > 0;
Runnable wakeUp = ()-> {
if (!wasDeviceInteractive) {
@@ -416,7 +407,7 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback {
return MODE_ONLY_WAKE;
} else if (mDozeScrimController.isPulsing() && unlockingAllowed) {
return MODE_WAKE_AND_UNLOCK_PULSING;
- } else if (unlockingAllowed || !mUnlockMethodCache.isMethodSecure()) {
+ } else if (unlockingAllowed || !mKeyguardStateController.isMethodSecure()) {
return MODE_WAKE_AND_UNLOCK;
} else {
return MODE_SHOW_BOUNCER;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java
index d655b2fef411..e78b85e5fd57 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java
@@ -38,7 +38,7 @@ import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.phone.StatusBarIconController.DarkIconManager;
import com.android.systemui.statusbar.policy.EncryptionHelper;
-import com.android.systemui.statusbar.policy.KeyguardMonitor;
+import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.statusbar.policy.NetworkController;
import com.android.systemui.statusbar.policy.NetworkController.SignalCallback;
@@ -57,7 +57,7 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue
public static final int FADE_IN_DELAY = 50;
private PhoneStatusBarView mStatusBar;
private StatusBarStateController mStatusBarStateController;
- private KeyguardMonitor mKeyguardMonitor;
+ private KeyguardStateController mKeyguardStateController;
private NetworkController mNetworkController;
private LinearLayout mSystemIconArea;
private View mClockView;
@@ -79,7 +79,7 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- mKeyguardMonitor = Dependency.get(KeyguardMonitor.class);
+ mKeyguardStateController = Dependency.get(KeyguardStateController.class);
mNetworkController = Dependency.get(NetworkController.class);
mStatusBarStateController = Dependency.get(StatusBarStateController.class);
mStatusBarComponent = SysUiServiceProvider.getComponent(getContext(), StatusBar.class);
@@ -207,8 +207,8 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue
state |= DISABLE_CLOCK;
}
- if (!mKeyguardMonitor.isLaunchTransitionFadingAway()
- && !mKeyguardMonitor.isKeyguardFadingAway()
+ if (!mKeyguardStateController.isLaunchTransitionFadingAway()
+ && !mKeyguardStateController.isKeyguardFadingAway()
&& shouldHideNotificationIcons()
&& !(mStatusBarStateController.getState() == StatusBarState.KEYGUARD
&& headsUpVisible)) {
@@ -268,7 +268,7 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue
* don't set the clock GONE otherwise it'll mess up the animation.
*/
private int clockHiddenMode() {
- if (!mStatusBar.isClosed() && !mKeyguardMonitor.isShowing()
+ if (!mStatusBar.isClosed() && !mKeyguardStateController.isShowing()
&& !mStatusBarStateController.isDozing()) {
return View.INVISIBLE;
}
@@ -345,11 +345,11 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue
.withEndAction(null);
// Synchronize the motion with the Keyguard fading if necessary.
- if (mKeyguardMonitor.isKeyguardFadingAway()) {
+ if (mKeyguardStateController.isKeyguardFadingAway()) {
v.animate()
- .setDuration(mKeyguardMonitor.getKeyguardFadingAwayDuration())
+ .setDuration(mKeyguardStateController.getKeyguardFadingAwayDuration())
.setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN)
- .setStartDelay(mKeyguardMonitor.getKeyguardFadingAwayDelay())
+ .setStartDelay(mKeyguardStateController.getKeyguardFadingAwayDelay())
.start();
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DoubleTapHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DoubleTapHelper.java
index 0d62703cbced..78ea5c03a7b5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DoubleTapHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DoubleTapHelper.java
@@ -100,6 +100,7 @@ public class DoubleTapHelper {
event.getY() - mActivationY);
}
if (withinDoubleTapSlop) {
+ makeInactive();
if (!mDoubleTapListener.onDoubleTap()) {
return false;
}
@@ -134,6 +135,7 @@ public class DoubleTapHelper {
if (mActivated) {
mActivated = false;
mActivationListener.onActiveChanged(false);
+ mView.removeCallbacks(mTapTimeoutRunnable);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
index bb6a38e1dcf5..bc482353753d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
@@ -16,7 +16,7 @@
package com.android.systemui.statusbar.phone;
-import android.content.Context;
+import android.content.res.Resources;
import android.hardware.display.AmbientDisplayConfiguration;
import android.os.PowerManager;
import android.os.SystemProperties;
@@ -24,18 +24,21 @@ import android.os.UserHandle;
import android.provider.Settings;
import android.util.MathUtils;
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.systemui.Dependency;
import com.android.systemui.R;
+import com.android.systemui.dagger.qualifiers.MainResources;
import com.android.systemui.doze.AlwaysOnDisplayPolicy;
import com.android.systemui.doze.DozeScreenState;
import com.android.systemui.tuner.TunerService;
import java.io.PrintWriter;
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
/**
* Retrieve doze information
*/
+@Singleton
public class DozeParameters implements TunerService.Tunable,
com.android.systemui.plugins.statusbar.DozeParameters {
private static final int MAX_DURATION = 60 * 1000;
@@ -44,35 +47,33 @@ public class DozeParameters implements TunerService.Tunable,
public static final boolean FORCE_BLANKING =
SystemProperties.getBoolean("debug.force_blanking", false);
- private static DozeParameters sInstance;
-
- private final Context mContext;
private final AmbientDisplayConfiguration mAmbientDisplayConfiguration;
private final PowerManager mPowerManager;
private final AlwaysOnDisplayPolicy mAlwaysOnPolicy;
+ private final Resources mResources;
private boolean mDozeAlwaysOn;
private boolean mControlScreenOffAnimation;
- public static DozeParameters getInstance(Context context) {
- if (sInstance == null) {
- sInstance = new DozeParameters(context);
- }
- return sInstance;
- }
-
- @VisibleForTesting
- protected DozeParameters(Context context) {
- mContext = context.getApplicationContext();
- mAmbientDisplayConfiguration = new AmbientDisplayConfiguration(mContext);
- mAlwaysOnPolicy = new AlwaysOnDisplayPolicy(mContext);
+ @Inject
+ protected DozeParameters(
+ @MainResources Resources resources,
+ AmbientDisplayConfiguration ambientDisplayConfiguration,
+ AlwaysOnDisplayPolicy alwaysOnDisplayPolicy,
+ PowerManager powerManager,
+ TunerService tunerService) {
+ mResources = resources;
+ mAmbientDisplayConfiguration = ambientDisplayConfiguration;
+ mAlwaysOnPolicy = alwaysOnDisplayPolicy;
mControlScreenOffAnimation = !getDisplayNeedsBlanking();
- mPowerManager = mContext.getSystemService(PowerManager.class);
+ mPowerManager = powerManager;
mPowerManager.setDozeAfterScreenOff(!mControlScreenOffAnimation);
- Dependency.get(TunerService.class).addTunable(this, Settings.Secure.DOZE_ALWAYS_ON,
+ tunerService.addTunable(
+ this,
+ Settings.Secure.DOZE_ALWAYS_ON,
Settings.Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED);
}
@@ -95,7 +96,7 @@ public class DozeParameters implements TunerService.Tunable,
}
public boolean getDozeSuspendDisplayStateSupported() {
- return mContext.getResources().getBoolean(R.bool.doze_suspend_display_state_supported);
+ return mResources.getBoolean(R.bool.doze_suspend_display_state_supported);
}
public int getPulseDuration() {
@@ -103,7 +104,7 @@ public class DozeParameters implements TunerService.Tunable,
}
public float getScreenBrightnessDoze() {
- return mContext.getResources().getInteger(
+ return mResources.getInteger(
com.android.internal.R.integer.config_screenBrightnessDoze) / 255f;
}
@@ -173,7 +174,7 @@ public class DozeParameters implements TunerService.Tunable,
* @return {@code true} if screen needs to be completely black before a power transition.
*/
public boolean getDisplayNeedsBlanking() {
- return FORCE_BLANKING || !FORCE_NO_BLANKING && mContext.getResources().getBoolean(
+ return FORCE_BLANKING || !FORCE_NO_BLANKING && mResources.getBoolean(
com.android.internal.R.bool.config_displayBlanksAfterDoze);
}
@@ -186,33 +187,24 @@ public class DozeParameters implements TunerService.Tunable,
return;
}
mControlScreenOffAnimation = controlScreenOffAnimation;
- getPowerManager().setDozeAfterScreenOff(!controlScreenOffAnimation);
- }
-
- @VisibleForTesting
- protected PowerManager getPowerManager() {
- return mPowerManager;
+ mPowerManager.setDozeAfterScreenOff(!controlScreenOffAnimation);
}
private boolean getBoolean(String propName, int resId) {
- return SystemProperties.getBoolean(propName, mContext.getResources().getBoolean(resId));
+ return SystemProperties.getBoolean(propName, mResources.getBoolean(resId));
}
private int getInt(String propName, int resId) {
- int value = SystemProperties.getInt(propName, mContext.getResources().getInteger(resId));
+ int value = SystemProperties.getInt(propName, mResources.getInteger(resId));
return MathUtils.constrain(value, 0, MAX_DURATION);
}
- private String getString(String propName, int resId) {
- return SystemProperties.get(propName, mContext.getString(resId));
- }
-
public int getPulseVisibleDurationExtended() {
return 2 * getPulseVisibleDuration();
}
public boolean doubleTapReportsTouchCoordinates() {
- return mContext.getResources().getBoolean(R.bool.doze_double_tap_reports_touch_coordinates);
+ return mResources.getBoolean(R.bool.doze_double_tap_reports_touch_coordinates);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java
index 60e381a776d2..1ecc4899d5e7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java
@@ -22,18 +22,24 @@ import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
import com.android.systemui.Dependency;
+import com.android.systemui.doze.DozeEvent;
import com.android.systemui.doze.DozeHost;
import com.android.systemui.doze.DozeLog;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener;
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
/**
* Controller which handles all the doze animations of the scrims.
*/
+@Singleton
public class DozeScrimController implements StateListener {
private static final String TAG = "DozeScrimController";
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+ private final DozeLog mDozeLog;
private final DozeParameters mDozeParameters;
private final Handler mHandler = new Handler();
@@ -47,7 +53,7 @@ public class DozeScrimController implements StateListener {
public void onDisplayBlanked() {
if (DEBUG) {
Log.d(TAG, "Pulse in, mDozing=" + mDozing + " mPulseReason="
- + DozeLog.reasonToString(mPulseReason));
+ + DozeEvent.reasonToString(mPulseReason));
}
if (!mDozing) {
return;
@@ -68,8 +74,8 @@ public class DozeScrimController implements StateListener {
// Notifications should time out on their own. Pulses due to notifications should
// instead be managed externally based off the notification's lifetime.
// Dock also controls the time out by self.
- if (mPulseReason != DozeLog.PULSE_REASON_NOTIFICATION
- && mPulseReason != DozeLog.PULSE_REASON_DOCKING) {
+ if (mPulseReason != DozeEvent.PULSE_REASON_NOTIFICATION
+ && mPulseReason != DozeEvent.PULSE_REASON_DOCKING) {
mHandler.postDelayed(mPulseOut, mDozeParameters.getPulseVisibleDuration());
mHandler.postDelayed(mPulseOutExtended,
mDozeParameters.getPulseVisibleDurationExtended());
@@ -90,14 +96,16 @@ public class DozeScrimController implements StateListener {
*/
@Override
public boolean shouldTimeoutWallpaper() {
- return mPulseReason == DozeLog.PULSE_REASON_DOCKING;
+ return mPulseReason == DozeEvent.PULSE_REASON_DOCKING;
}
};
- public DozeScrimController(DozeParameters dozeParameters) {
+ @Inject
+ public DozeScrimController(DozeParameters dozeParameters, DozeLog dozeLog) {
mDozeParameters = dozeParameters;
//Never expected to be destroyed
Dependency.get(StatusBarStateController.class).addCallback(this);
+ mDozeLog = dozeLog;
}
@VisibleForTesting
@@ -168,14 +176,14 @@ public class DozeScrimController implements StateListener {
}
private void pulseStarted() {
- DozeLog.tracePulseStart(mPulseReason);
+ mDozeLog.tracePulseStart(mPulseReason);
if (mPulseCallback != null) {
mPulseCallback.onPulseStarted();
}
}
private void pulseFinished() {
- DozeLog.tracePulseFinish();
+ mDozeLog.tracePulseFinish();
if (mPulseCallback != null) {
mPulseCallback.onPulseFinished();
mPulseCallback = null;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeServiceHost.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeServiceHost.java
new file mode 100644
index 000000000000..28543555bf4d
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeServiceHost.java
@@ -0,0 +1,465 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.phone;
+
+import static com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_AWAKE;
+import static com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_WAKING;
+
+import android.annotation.NonNull;
+import android.os.Bundle;
+import android.os.PowerManager;
+import android.os.SystemClock;
+import android.os.SystemProperties;
+import android.util.Log;
+import android.view.MotionEvent;
+import android.view.View;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.keyguard.KeyguardUpdateMonitor;
+import com.android.systemui.assist.AssistManager;
+import com.android.systemui.doze.DozeEvent;
+import com.android.systemui.doze.DozeHost;
+import com.android.systemui.doze.DozeLog;
+import com.android.systemui.doze.DozeReceiver;
+import com.android.systemui.keyguard.KeyguardViewMediator;
+import com.android.systemui.keyguard.WakefulnessLifecycle;
+import com.android.systemui.statusbar.PulseExpansionHandler;
+import com.android.systemui.statusbar.StatusBarState;
+import com.android.systemui.statusbar.SysuiStatusBarStateController;
+import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator;
+import com.android.systemui.statusbar.notification.VisualStabilityManager;
+import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.policy.BatteryController;
+import com.android.systemui.statusbar.policy.DeviceProvisionedController;
+
+import java.util.ArrayList;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+import dagger.Lazy;
+
+/**
+ * Implementation of DozeHost for SystemUI.
+ */
+@Singleton
+public final class DozeServiceHost implements DozeHost {
+ private static final String TAG = "DozeServiceHost";
+ private final ArrayList<Callback> mCallbacks = new ArrayList<>();
+ private final DozeLog mDozeLog;
+ private final PowerManager mPowerManager;
+ private boolean mAnimateWakeup;
+ private boolean mAnimateScreenOff;
+ private boolean mIgnoreTouchWhilePulsing;
+ private Runnable mPendingScreenOffCallback;
+ @VisibleForTesting
+ boolean mWakeLockScreenPerformsAuth = SystemProperties.getBoolean(
+ "persist.sysui.wake_performs_auth", true);
+ private boolean mDozingRequested;
+ private boolean mDozing;
+ private boolean mPulsing;
+ private WakefulnessLifecycle mWakefulnessLifecycle;
+ private final SysuiStatusBarStateController mStatusBarStateController;
+ private final DeviceProvisionedController mDeviceProvisionedController;
+ private final HeadsUpManagerPhone mHeadsUpManagerPhone;
+ private final BatteryController mBatteryController;
+ private final ScrimController mScrimController;
+ private final Lazy<BiometricUnlockController> mBiometricUnlockControllerLazy;
+ private BiometricUnlockController mBiometricUnlockController;
+ private final KeyguardViewMediator mKeyguardViewMediator;
+ private final AssistManager mAssistManager;
+ private final DozeScrimController mDozeScrimController;
+ private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
+ private final VisualStabilityManager mVisualStabilityManager;
+ private final PulseExpansionHandler mPulseExpansionHandler;
+ private final StatusBarWindowController mStatusBarWindowController;
+ private final NotificationWakeUpCoordinator mNotificationWakeUpCoordinator;
+ private NotificationIconAreaController mNotificationIconAreaController;
+ private StatusBarWindowViewController mStatusBarWindowViewController;
+ private StatusBarWindowView mStatusBarWindow;
+ private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
+ private NotificationPanelView mNotificationPanel;
+ private View mAmbientIndicationContainer;
+ private StatusBar mStatusBar;
+
+ @Inject
+ public DozeServiceHost(DozeLog dozeLog, PowerManager powerManager,
+ WakefulnessLifecycle wakefulnessLifecycle,
+ SysuiStatusBarStateController statusBarStateController,
+ DeviceProvisionedController deviceProvisionedController,
+ HeadsUpManagerPhone headsUpManagerPhone, BatteryController batteryController,
+ ScrimController scrimController,
+ Lazy<BiometricUnlockController> biometricUnlockControllerLazy,
+ KeyguardViewMediator keyguardViewMediator,
+ AssistManager assistManager,
+ DozeScrimController dozeScrimController, KeyguardUpdateMonitor keyguardUpdateMonitor,
+ VisualStabilityManager visualStabilityManager,
+ PulseExpansionHandler pulseExpansionHandler,
+ StatusBarWindowController statusBarWindowController,
+ NotificationWakeUpCoordinator notificationWakeUpCoordinator) {
+ super();
+ mDozeLog = dozeLog;
+ mPowerManager = powerManager;
+ mWakefulnessLifecycle = wakefulnessLifecycle;
+ mStatusBarStateController = statusBarStateController;
+ mDeviceProvisionedController = deviceProvisionedController;
+ mHeadsUpManagerPhone = headsUpManagerPhone;
+ mBatteryController = batteryController;
+ mScrimController = scrimController;
+ mBiometricUnlockControllerLazy = biometricUnlockControllerLazy;
+ mKeyguardViewMediator = keyguardViewMediator;
+ mAssistManager = assistManager;
+ mDozeScrimController = dozeScrimController;
+ mKeyguardUpdateMonitor = keyguardUpdateMonitor;
+ mVisualStabilityManager = visualStabilityManager;
+ mPulseExpansionHandler = pulseExpansionHandler;
+ mStatusBarWindowController = statusBarWindowController;
+ mNotificationWakeUpCoordinator = notificationWakeUpCoordinator;
+ }
+
+ // TODO: we should try to not pass status bar in here if we can avoid it.
+
+ /**
+ * Initialize instance with objects only available later during execution.
+ */
+ public void initialize(StatusBar statusBar,
+ NotificationIconAreaController notificationIconAreaController,
+ StatusBarWindowViewController statusBarWindowViewController,
+ StatusBarWindowView statusBarWindow,
+ StatusBarKeyguardViewManager statusBarKeyguardViewManager,
+ NotificationPanelView notificationPanel, View ambientIndicationContainer) {
+ mStatusBar = statusBar;
+ mNotificationIconAreaController = notificationIconAreaController;
+ mStatusBarWindowViewController = statusBarWindowViewController;
+ mStatusBarWindow = statusBarWindow;
+ mStatusBarKeyguardViewManager = statusBarKeyguardViewManager;
+ mNotificationPanel = notificationPanel;
+ mAmbientIndicationContainer = ambientIndicationContainer;
+ mBiometricUnlockController = mBiometricUnlockControllerLazy.get();
+ }
+
+ @Override
+ public String toString() {
+ return "PSB.DozeServiceHost[mCallbacks=" + mCallbacks.size() + "]";
+ }
+
+ void firePowerSaveChanged(boolean active) {
+ for (Callback callback : mCallbacks) {
+ callback.onPowerSaveChanged(active);
+ }
+ }
+
+ void fireNotificationPulse(NotificationEntry entry) {
+ Runnable pulseSuppressedListener = () -> {
+ entry.setPulseSuppressed(true);
+ mNotificationIconAreaController.updateAodNotificationIcons();
+ };
+ for (Callback callback : mCallbacks) {
+ callback.onNotificationAlerted(pulseSuppressedListener);
+ }
+ }
+
+ boolean getDozingRequested() {
+ return mDozingRequested;
+ }
+
+ boolean isPulsing() {
+ return mPulsing;
+ }
+
+
+ @Override
+ public void addCallback(@NonNull Callback callback) {
+ mCallbacks.add(callback);
+ }
+
+ @Override
+ public void removeCallback(@NonNull Callback callback) {
+ mCallbacks.remove(callback);
+ }
+
+ @Override
+ public void startDozing() {
+ if (!mDozingRequested) {
+ mDozingRequested = true;
+ mDozeLog.traceDozing(mDozing);
+ updateDozing();
+ mStatusBar.updateIsKeyguard();
+ }
+ }
+
+ void updateDozing() {
+ // When in wake-and-unlock while pulsing, keep dozing state until fully unlocked.
+ boolean
+ dozing =
+ mDozingRequested && mStatusBarStateController.getState() == StatusBarState.KEYGUARD
+ || mBiometricUnlockController.getMode()
+ == BiometricUnlockController.MODE_WAKE_AND_UNLOCK_PULSING;
+ // When in wake-and-unlock we may not have received a change to StatusBarState
+ // but we still should not be dozing, manually set to false.
+ if (mBiometricUnlockController.getMode()
+ == BiometricUnlockController.MODE_WAKE_AND_UNLOCK) {
+ dozing = false;
+ }
+
+
+ mStatusBarStateController.setIsDozing(dozing);
+ }
+
+ @Override
+ public void pulseWhileDozing(@NonNull PulseCallback callback, int reason) {
+ if (reason == DozeEvent.PULSE_REASON_SENSOR_LONG_PRESS) {
+ mPowerManager.wakeUp(SystemClock.uptimeMillis(), PowerManager.WAKE_REASON_GESTURE,
+ "com.android.systemui:LONG_PRESS");
+ mAssistManager.startAssist(new Bundle());
+ return;
+ }
+
+ if (reason == DozeEvent.PULSE_REASON_SENSOR_WAKE_LOCK_SCREEN) {
+ mScrimController.setWakeLockScreenSensorActive(true);
+ }
+
+ if (reason == DozeEvent.PULSE_REASON_DOCKING && mStatusBarWindow != null) {
+ mStatusBarWindowViewController.suppressWakeUpGesture(true);
+ }
+
+ boolean passiveAuthInterrupt = reason == DozeEvent.PULSE_REASON_SENSOR_WAKE_LOCK_SCREEN
+ && mWakeLockScreenPerformsAuth;
+ // Set the state to pulsing, so ScrimController will know what to do once we ask it to
+ // execute the transition. The pulse callback will then be invoked when the scrims
+ // are black, indicating that StatusBar is ready to present the rest of the UI.
+ mPulsing = true;
+ mDozeScrimController.pulse(new PulseCallback() {
+ @Override
+ public void onPulseStarted() {
+ callback.onPulseStarted();
+ mStatusBar.updateNotificationPanelTouchState();
+ setPulsing(true);
+ }
+
+ @Override
+ public void onPulseFinished() {
+ mPulsing = false;
+ callback.onPulseFinished();
+ mStatusBar.updateNotificationPanelTouchState();
+ mScrimController.setWakeLockScreenSensorActive(false);
+ if (mStatusBarWindow != null) {
+ mStatusBarWindowViewController.suppressWakeUpGesture(false);
+ }
+ setPulsing(false);
+ }
+
+ private void setPulsing(boolean pulsing) {
+ mStatusBarStateController.setPulsing(pulsing);
+ mStatusBarKeyguardViewManager.setPulsing(pulsing);
+ mKeyguardViewMediator.setPulsing(pulsing);
+ mNotificationPanel.setPulsing(pulsing);
+ mVisualStabilityManager.setPulsing(pulsing);
+ mStatusBarWindowViewController.setPulsing(pulsing);
+ mIgnoreTouchWhilePulsing = false;
+ if (mKeyguardUpdateMonitor != null && passiveAuthInterrupt) {
+ mKeyguardUpdateMonitor.onAuthInterruptDetected(pulsing /* active */);
+ }
+ mStatusBar.updateScrimController();
+ mPulseExpansionHandler.setPulsing(pulsing);
+ mNotificationWakeUpCoordinator.setPulsing(pulsing);
+ }
+ }, reason);
+ // DozeScrimController is in pulse state, now let's ask ScrimController to start
+ // pulsing and draw the black frame, if necessary.
+ mStatusBar.updateScrimController();
+ }
+
+ @Override
+ public void stopDozing() {
+ if (mDozingRequested) {
+ mDozingRequested = false;
+ mDozeLog.traceDozing(mDozing);
+ updateDozing();
+ }
+ }
+
+ @Override
+ public void onIgnoreTouchWhilePulsing(boolean ignore) {
+ if (ignore != mIgnoreTouchWhilePulsing) {
+ mDozeLog.tracePulseTouchDisabledByProx(ignore);
+ }
+ mIgnoreTouchWhilePulsing = ignore;
+ if (mDozing && ignore) {
+ mStatusBarWindowViewController.cancelCurrentTouch();
+ }
+ }
+
+ @Override
+ public void dozeTimeTick() {
+ mNotificationPanel.dozeTimeTick();
+ if (mAmbientIndicationContainer instanceof DozeReceiver) {
+ ((DozeReceiver) mAmbientIndicationContainer).dozeTimeTick();
+ }
+ }
+
+ @Override
+ public boolean isPowerSaveActive() {
+ return mBatteryController.isAodPowerSave();
+ }
+
+ @Override
+ public boolean isPulsingBlocked() {
+ return mBiometricUnlockController.getMode()
+ == BiometricUnlockController.MODE_WAKE_AND_UNLOCK;
+ }
+
+ @Override
+ public boolean isProvisioned() {
+ return mDeviceProvisionedController.isDeviceProvisioned()
+ && mDeviceProvisionedController.isCurrentUserSetup();
+ }
+
+ @Override
+ public boolean isBlockingDoze() {
+ if (mBiometricUnlockController.hasPendingAuthentication()) {
+ Log.i(StatusBar.TAG, "Blocking AOD because fingerprint has authenticated");
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public void extendPulse(int reason) {
+ if (reason == DozeEvent.PULSE_REASON_SENSOR_WAKE_LOCK_SCREEN) {
+ mScrimController.setWakeLockScreenSensorActive(true);
+ }
+ if (mDozeScrimController.isPulsing() && mHeadsUpManagerPhone.hasNotifications()) {
+ mHeadsUpManagerPhone.extendHeadsUp();
+ } else {
+ mDozeScrimController.extendPulse();
+ }
+ }
+
+ @Override
+ public void stopPulsing() {
+ if (mDozeScrimController.isPulsing()) {
+ mDozeScrimController.pulseOutNow();
+ }
+ }
+
+ @Override
+ public void setAnimateWakeup(boolean animateWakeup) {
+ if (mWakefulnessLifecycle.getWakefulness() == WAKEFULNESS_AWAKE
+ || mWakefulnessLifecycle.getWakefulness() == WAKEFULNESS_WAKING) {
+ // Too late to change the wakeup animation.
+ return;
+ }
+ mAnimateWakeup = animateWakeup;
+ }
+
+ @Override
+ public void setAnimateScreenOff(boolean animateScreenOff) {
+ mAnimateScreenOff = animateScreenOff;
+ }
+
+ @Override
+ public void onSlpiTap(float screenX, float screenY) {
+ if (screenX > 0 && screenY > 0 && mAmbientIndicationContainer != null
+ && mAmbientIndicationContainer.getVisibility() == View.VISIBLE) {
+ int[] locationOnScreen = new int[2];
+ mAmbientIndicationContainer.getLocationOnScreen(locationOnScreen);
+ float viewX = screenX - locationOnScreen[0];
+ float viewY = screenY - locationOnScreen[1];
+ if (0 <= viewX && viewX <= mAmbientIndicationContainer.getWidth()
+ && 0 <= viewY && viewY <= mAmbientIndicationContainer.getHeight()) {
+
+ // Dispatch a tap
+ long now = SystemClock.elapsedRealtime();
+ MotionEvent ev = MotionEvent.obtain(
+ now, now, MotionEvent.ACTION_DOWN, screenX, screenY, 0);
+ mAmbientIndicationContainer.dispatchTouchEvent(ev);
+ ev.recycle();
+ ev = MotionEvent.obtain(
+ now, now, MotionEvent.ACTION_UP, screenX, screenY, 0);
+ mAmbientIndicationContainer.dispatchTouchEvent(ev);
+ ev.recycle();
+ }
+ }
+ }
+
+ @Override
+ public void setDozeScreenBrightness(int value) {
+ mStatusBarWindowController.setDozeScreenBrightness(value);
+ }
+
+ @Override
+ public void setAodDimmingScrim(float scrimOpacity) {
+ mScrimController.setAodFrontScrimAlpha(scrimOpacity);
+ }
+
+
+
+ @Override
+ public void prepareForGentleSleep(Runnable onDisplayOffCallback) {
+ if (mPendingScreenOffCallback != null) {
+ Log.w(TAG, "Overlapping onDisplayOffCallback. Ignoring previous one.");
+ }
+ mPendingScreenOffCallback = onDisplayOffCallback;
+ mStatusBar.updateScrimController();
+ }
+
+ @Override
+ public void cancelGentleSleep() {
+ mPendingScreenOffCallback = null;
+ if (mScrimController.getState() == ScrimState.OFF) {
+ mStatusBar.updateScrimController();
+ }
+ }
+
+ /**
+ * When the dozing host is waiting for scrims to fade out to change the display state.
+ */
+ boolean hasPendingScreenOffCallback() {
+ return mPendingScreenOffCallback != null;
+ }
+
+ /**
+ * Executes an nullifies the pending display state callback.
+ *
+ * @see #hasPendingScreenOffCallback()
+ * @see #prepareForGentleSleep(Runnable)
+ */
+ void executePendingScreenOffCallback() {
+ if (mPendingScreenOffCallback == null) {
+ return;
+ }
+ mPendingScreenOffCallback.run();
+ mPendingScreenOffCallback = null;
+ }
+
+ boolean shouldAnimateWakeup() {
+ return mAnimateWakeup;
+ }
+
+ boolean shouldAnimateScreenOff() {
+ return mAnimateScreenOff;
+ }
+
+ public void setDozing(boolean dozing) {
+ mDozing = dozing;
+ }
+
+ boolean getIgnoreTouchWhilePulsing() {
+ return mIgnoreTouchWhilePulsing;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/EdgeBackGestureHandler.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/EdgeBackGestureHandler.java
index 4cd3ad27ab34..1c8e832d03d2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/EdgeBackGestureHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/EdgeBackGestureHandler.java
@@ -54,9 +54,7 @@ import com.android.systemui.R;
import com.android.systemui.bubbles.BubbleController;
import com.android.systemui.model.SysUiState;
import com.android.systemui.recents.OverviewProxyService;
-import com.android.systemui.shared.system.PinnedStackListenerForwarder.PinnedStackListener;
import com.android.systemui.shared.system.QuickStepContract;
-import com.android.systemui.shared.system.WindowManagerWrapper;
import java.io.PrintWriter;
import java.util.concurrent.Executor;
@@ -70,15 +68,6 @@ public class EdgeBackGestureHandler implements DisplayListener {
private static final int MAX_LONG_PRESS_TIMEOUT = SystemProperties.getInt(
"gestures.back_timeout", 250);
- private final PinnedStackListener mImeChangedListener = new PinnedStackListener() {
- @Override
- public void onImeVisibilityChanged(boolean imeVisible, int imeHeight) {
- // No need to thread jump, assignments are atomic
- mImeHeight = imeVisible ? imeHeight : 0;
- // TODO: Probably cancel any existing gesture
- }
- };
-
private ISystemGestureExclusionListener mGestureExclusionListener =
new ISystemGestureExclusionListener.Stub() {
@Override
@@ -126,11 +115,10 @@ public class EdgeBackGestureHandler implements DisplayListener {
private boolean mInRejectedExclusion = false;
private boolean mIsOnLeftEdge;
- private int mImeHeight = 0;
-
private boolean mIsAttached;
private boolean mIsGesturalModeEnabled;
private boolean mIsEnabled;
+ private boolean mIsNavBarShownTransiently;
private InputMonitor mInputMonitor;
private InputEventReceiver mInputEventReceiver;
@@ -195,6 +183,10 @@ public class EdgeBackGestureHandler implements DisplayListener {
updateCurrentUserResources(currentUserContext.getResources());
}
+ public void onNavBarTransientStateChanged(boolean isTransient) {
+ mIsNavBarShownTransiently = isTransient;
+ }
+
private void disposeInputChannel() {
if (mInputEventReceiver != null) {
mInputEventReceiver.dispose();
@@ -222,7 +214,6 @@ public class EdgeBackGestureHandler implements DisplayListener {
}
if (!mIsEnabled) {
- WindowManagerWrapper.getInstance().removePinnedStackListener(mImeChangedListener);
mContext.getSystemService(DisplayManager.class).unregisterDisplayListener(this);
try {
@@ -239,7 +230,6 @@ public class EdgeBackGestureHandler implements DisplayListener {
mContext.getMainThreadHandler());
try {
- WindowManagerWrapper.getInstance().addPinnedStackListener(mImeChangedListener);
WindowManagerGlobal.getWindowManagerService()
.registerSystemGestureExclusionListener(
mGestureExclusionListener, mDisplayId);
@@ -267,7 +257,7 @@ public class EdgeBackGestureHandler implements DisplayListener {
| WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN,
PixelFormat.TRANSLUCENT);
mEdgePanelLp.privateFlags |=
- WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
+ WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS;
mEdgePanelLp.setTitle(TAG + mDisplayId);
mEdgePanelLp.accessibilityTitle = mContext.getString(R.string.nav_bar_edge_panel);
mEdgePanelLp.windowAnimations = 0;
@@ -296,13 +286,16 @@ public class EdgeBackGestureHandler implements DisplayListener {
}
private boolean isWithinTouchRegion(int x, int y) {
- if (y > (mDisplaySize.y - Math.max(mImeHeight, mNavBarHeight))) {
+ // Disallow if too far from the edge
+ if (x > mEdgeWidth + mLeftInset && x < (mDisplaySize.x - mEdgeWidth - mRightInset)) {
return false;
}
- if (x > mEdgeWidth + mLeftInset && x < (mDisplaySize.x - mEdgeWidth - mRightInset)) {
- return false;
+ // Always allow if the user is in a transient sticky immersive state
+ if (mIsNavBarShownTransiently) {
+ return true;
}
+
boolean isInExcludedRegion = mExcludeRegion.contains(x, y);
if (isInExcludedRegion) {
mOverviewProxyService.notifyBackAction(false /* completed */, -1, -1,
@@ -470,7 +463,6 @@ public class EdgeBackGestureHandler implements DisplayListener {
pw.println(" mInRejectedExclusion" + mInRejectedExclusion);
pw.println(" mExcludeRegion=" + mExcludeRegion);
pw.println(" mUnrestrictedExcludeRegion=" + mUnrestrictedExcludeRegion);
- pw.println(" mImeHeight=" + mImeHeight);
pw.println(" mIsAttached=" + mIsAttached);
pw.println(" mEdgeWidth=" + mEdgeWidth);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/FloatingRotationButton.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/FloatingRotationButton.java
index deb314bae5c9..a7849847387d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/FloatingRotationButton.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/FloatingRotationButton.java
@@ -82,7 +82,7 @@ public class FloatingRotationButton implements RotationButton {
final WindowManager.LayoutParams lp = new WindowManager.LayoutParams(mDiameter, mDiameter,
mMargin, mMargin, WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL, flags,
PixelFormat.TRANSLUCENT);
- lp.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
+ lp.privateFlags |= WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS;
lp.setTitle("FloatingRotationButton");
switch (mWindowManager.getDefaultDisplay().getRotation()) {
case Surface.ROTATION_0:
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceController.java
index f53c4e8c818e..ce96005aa306 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceController.java
@@ -39,7 +39,7 @@ import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
-import com.android.systemui.statusbar.policy.KeyguardMonitor;
+import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener;
import java.util.function.BiConsumer;
@@ -89,7 +89,7 @@ public class HeadsUpAppearanceController implements OnHeadsUpChangedListener,
};
private boolean mAnimationsEnabled = true;
Point mPoint;
- private KeyguardMonitor mKeyguardMonitor;
+ private KeyguardStateController mKeyguardStateController;
public HeadsUpAppearanceController(
@@ -98,9 +98,10 @@ public class HeadsUpAppearanceController implements OnHeadsUpChangedListener,
View statusbarView,
SysuiStatusBarStateController statusBarStateController,
KeyguardBypassController keyguardBypassController,
+ KeyguardStateController keyguardStateController,
NotificationWakeUpCoordinator wakeUpCoordinator) {
this(notificationIconAreaController, headsUpManager, statusBarStateController,
- keyguardBypassController, wakeUpCoordinator,
+ keyguardBypassController, wakeUpCoordinator, keyguardStateController,
statusbarView.findViewById(R.id.heads_up_status_bar_view),
statusbarView.findViewById(R.id.notification_stack_scroller),
statusbarView.findViewById(R.id.notification_panel),
@@ -116,6 +117,7 @@ public class HeadsUpAppearanceController implements OnHeadsUpChangedListener,
StatusBarStateController stateController,
KeyguardBypassController bypassController,
NotificationWakeUpCoordinator wakeUpCoordinator,
+ KeyguardStateController keyguardStateController,
HeadsUpStatusBarView headsUpStatusBarView,
NotificationStackScrollLayout stackScroller,
NotificationPanelView panelView,
@@ -160,7 +162,7 @@ public class HeadsUpAppearanceController implements OnHeadsUpChangedListener,
mWakeUpCoordinator = wakeUpCoordinator;
wakeUpCoordinator.addListener(this);
mCommandQueue = getComponent(headsUpStatusBarView.getContext(), CommandQueue.class);
- mKeyguardMonitor = Dependency.get(KeyguardMonitor.class);
+ mKeyguardStateController = keyguardStateController;
}
@@ -378,7 +380,7 @@ public class HeadsUpAppearanceController implements OnHeadsUpChangedListener,
boolean canShow = !mIsExpanded && notificationsShown;
if (mBypassController.getBypassEnabled() &&
(mStatusBarStateController.getState() == StatusBarState.KEYGUARD
- || mKeyguardMonitor.isKeyguardGoingAway())
+ || mKeyguardStateController.isKeyguardGoingAway())
&& notificationsShown) {
canShow = true;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java
index a7e7f085ffd7..4e06c84c30be 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java
@@ -29,6 +29,7 @@ import android.view.DisplayCutout;
import android.view.Gravity;
import android.view.View;
import android.view.ViewTreeObserver;
+import android.view.WindowInsets;
import androidx.collection.ArraySet;
@@ -196,9 +197,9 @@ public class HeadsUpManagerPhone extends HeadsUpManager implements Dumpable,
mReleaseOnExpandFinish = false;
} else {
for (NotificationEntry entry : mEntriesToRemoveAfterExpand) {
- if (isAlerting(entry.key)) {
+ if (isAlerting(entry.getKey())) {
// Maybe the heads-up was removed already
- removeAlertEntry(entry.key);
+ removeAlertEntry(entry.getKey());
}
}
}
@@ -290,7 +291,7 @@ public class HeadsUpManagerPhone extends HeadsUpManager implements Dumpable,
*/
public void setRemoteInputActive(
@NonNull NotificationEntry entry, boolean remoteInputActive) {
- HeadsUpEntryPhone headsUpEntry = getHeadsUpEntryPhone(entry.key);
+ HeadsUpEntryPhone headsUpEntry = getHeadsUpEntryPhone(entry.getKey());
if (headsUpEntry != null && headsUpEntry.remoteInputActive != remoteInputActive) {
headsUpEntry.remoteInputActive = remoteInputActive;
if (remoteInputActive) {
@@ -306,7 +307,7 @@ public class HeadsUpManagerPhone extends HeadsUpManager implements Dumpable,
* area if it's pinned until it's hidden again.
*/
public void setMenuShown(@NonNull NotificationEntry entry, boolean menuShown) {
- HeadsUpEntry headsUpEntry = getHeadsUpEntry(entry.key);
+ HeadsUpEntry headsUpEntry = getHeadsUpEntry(entry.getKey());
if (headsUpEntry instanceof HeadsUpEntryPhone && entry.isRowPinned()) {
((HeadsUpEntryPhone) headsUpEntry).setMenuShownPinned(menuShown);
}
@@ -374,7 +375,7 @@ public class HeadsUpManagerPhone extends HeadsUpManager implements Dumpable,
} else {
if (topEntry.isChildInGroup()) {
final NotificationEntry groupSummary =
- mGroupManager.getGroupSummary(topEntry.notification);
+ mGroupManager.getGroupSummary(topEntry.getSbn());
if (groupSummary != null) {
topEntry = groupSummary;
}
@@ -390,7 +391,12 @@ public class HeadsUpManagerPhone extends HeadsUpManager implements Dumpable,
}
private void updateRegionForNotch(Region region) {
- DisplayCutout cutout = mStatusBarWindowView.getRootWindowInsets().getDisplayCutout();
+ WindowInsets windowInsets = mStatusBarWindowView.getRootWindowInsets();
+ if (windowInsets == null) {
+ Log.w(TAG, "StatusBarWindowView is not attached.");
+ return;
+ }
+ DisplayCutout cutout = windowInsets.getDisplayCutout();
if (cutout == null) {
return;
}
@@ -423,9 +429,9 @@ public class HeadsUpManagerPhone extends HeadsUpManager implements Dumpable,
public void onReorderingAllowed() {
mAnimationStateHandler.setHeadsUpGoingAwayAnimationsAllowed(false);
for (NotificationEntry entry : mEntriesToRemoveWhenReorderingAllowed) {
- if (isAlerting(entry.key)) {
+ if (isAlerting(entry.getKey())) {
// Maybe the heads-up was removed already
- removeAlertEntry(entry.key);
+ removeAlertEntry(entry.getKey());
}
}
mEntriesToRemoveWhenReorderingAllowed.clear();
@@ -442,7 +448,7 @@ public class HeadsUpManagerPhone extends HeadsUpManager implements Dumpable,
@Override
protected void onAlertEntryRemoved(AlertEntry alertEntry) {
- mKeysToRemoveWhenLeavingKeyguard.remove(alertEntry.mEntry.key);
+ mKeysToRemoveWhenLeavingKeyguard.remove(alertEntry.mEntry.getKey());
super.onAlertEntryRemoved(alertEntry);
mEntryPool.release((HeadsUpEntryPhone) alertEntry);
}
@@ -527,9 +533,9 @@ public class HeadsUpManagerPhone extends HeadsUpManager implements Dumpable,
} else if (mTrackingHeadsUp) {
mEntriesToRemoveAfterExpand.add(entry);
} else if (mIsAutoHeadsUp && mStatusBarState == StatusBarState.KEYGUARD) {
- mKeysToRemoveWhenLeavingKeyguard.add(entry.key);
+ mKeysToRemoveWhenLeavingKeyguard.add(entry.getKey());
} else {
- removeAlertEntry(entry.key);
+ removeAlertEntry(entry.getKey());
}
};
@@ -547,7 +553,7 @@ public class HeadsUpManagerPhone extends HeadsUpManager implements Dumpable,
if (mEntriesToRemoveWhenReorderingAllowed.contains(mEntry)) {
mEntriesToRemoveWhenReorderingAllowed.remove(mEntry);
}
- mKeysToRemoveWhenLeavingKeyguard.remove(mEntry.key);
+ mKeysToRemoveWhenLeavingKeyguard.remove(mEntry.getKey());
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
index 2bcbc026d561..99da47a00c0e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
@@ -81,6 +81,7 @@ import com.android.systemui.statusbar.policy.AccessibilityController;
import com.android.systemui.statusbar.policy.ExtensionController;
import com.android.systemui.statusbar.policy.ExtensionController.Extension;
import com.android.systemui.statusbar.policy.FlashlightController;
+import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.statusbar.policy.PreviewInflater;
import com.android.systemui.tuner.LockscreenFragment.LockButtonFactory;
import com.android.systemui.tuner.TunerService;
@@ -90,7 +91,7 @@ import com.android.systemui.tuner.TunerService;
* text.
*/
public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickListener,
- UnlockMethodCache.OnUnlockMethodChangedListener,
+ KeyguardStateController.Callback,
AccessibilityController.AccessibilityStateChangedCallback {
final static String TAG = "StatusBar/KeyguardBottomAreaView";
@@ -118,7 +119,10 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
private static final int DOZE_ANIMATION_ELEMENT_DURATION = 250;
private EmergencyCarrierArea mEmergencyCarrierArea;
- private final UnlockMethodCache mUnlockMethodCache;
+
+ private final boolean mShowLeftAffordance;
+ private final boolean mShowCameraAffordance;
+
private KeyguardAffordanceView mRightAffordanceView;
private KeyguardAffordanceView mLeftAffordanceView;
private ViewGroup mIndicationArea;
@@ -130,7 +134,7 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
private View mCameraPreview;
private ActivityStarter mActivityStarter;
- private LockPatternUtils mLockPatternUtils;
+ private KeyguardStateController mKeyguardStateController;
private FlashlightController mFlashlightController;
private PreviewInflater mPreviewInflater;
private AccessibilityController mAccessibilityController;
@@ -185,7 +189,9 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
public KeyguardBottomAreaView(Context context, AttributeSet attrs, int defStyleAttr,
int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
- mUnlockMethodCache = UnlockMethodCache.getInstance(getContext());
+ mShowLeftAffordance = getResources().getBoolean(R.bool.config_keyguardShowLeftAffordance);
+ mShowCameraAffordance = getResources()
+ .getBoolean(R.bool.config_keyguardShowCameraAffordance);
}
private AccessibilityDelegate mAccessibilityDelegate = new AccessibilityDelegate() {
@@ -227,7 +233,6 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
@Override
protected void onFinishInflate() {
super.onFinishInflate();
- mLockPatternUtils = new LockPatternUtils(mContext);
mPreviewInflater = new PreviewInflater(mContext, new LockPatternUtils(mContext),
new ActivityIntentHelper(mContext));
mPreviewContainer = findViewById(R.id.preview_container);
@@ -242,6 +247,8 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
mBurnInYOffset = getResources().getDimensionPixelSize(
R.dimen.default_burn_in_prevention_offset);
updateCameraVisibility();
+ mKeyguardStateController = Dependency.get(KeyguardStateController.class);
+ mKeyguardStateController.addCallback(this);
setClipChildren(false);
setClipToPadding(false);
inflateCameraPreview();
@@ -279,13 +286,13 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
getContext().registerReceiverAsUser(mDevicePolicyReceiver,
UserHandle.ALL, filter, null, null);
Dependency.get(KeyguardUpdateMonitor.class).registerCallback(mUpdateMonitorCallback);
- mUnlockMethodCache.addListener(this);
+ mKeyguardStateController.addCallback(this);
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
- mUnlockMethodCache.removeListener(this);
+ mKeyguardStateController.removeCallback(this);
mAccessibilityController.removeStateChangedCallback(this);
mRightExtension.destroy();
mLeftExtension.destroy();
@@ -372,8 +379,8 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
// Things are not set up yet; reply hazy, ask again later
return;
}
- mRightAffordanceView.setVisibility(!mDozing && mRightButton.getIcon().isVisible
- ? View.VISIBLE : View.GONE);
+ mRightAffordanceView.setVisibility(!mDozing && mShowCameraAffordance
+ && mRightButton.getIcon().isVisible ? View.VISIBLE : View.GONE);
}
/**
@@ -385,8 +392,12 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
}
private void updateLeftAffordanceIcon() {
+ if (!mShowLeftAffordance || mDozing) {
+ mLeftAffordanceView.setVisibility(GONE);
+ return;
+ }
IconState state = mLeftButton.getIcon();
- mLeftAffordanceView.setVisibility(!mDozing && state.isVisible ? View.VISIBLE : View.GONE);
+ mLeftAffordanceView.setVisibility(state.isVisible ? View.VISIBLE : View.GONE);
if (state.drawable != mLeftAffordanceView.getDrawable()
|| state.tint != mLeftAffordanceView.shouldTint()) {
mLeftAffordanceView.setImageDrawable(state.drawable, state.tint);
@@ -547,7 +558,7 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
mAssistManager.launchVoiceAssistFromKeyguard();
}
};
- if (mStatusBar.isKeyguardCurrentlySecure()) {
+ if (!mKeyguardStateController.canDismissLockScreen()) {
AsyncTask.execute(runnable);
} else {
boolean dismissShade = !TextUtils.isEmpty(mRightButtonStr)
@@ -612,7 +623,7 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
}
@Override
- public void onUnlockMethodStateChanged() {
+ public void onUnlockedChanged() {
updateCameraVisibility();
}
@@ -771,10 +782,8 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
@Override
public IconState getIcon() {
mLeftIsVoiceAssist = canLaunchVoiceAssist();
- final boolean showAffordance =
- getResources().getBoolean(R.bool.config_keyguardShowLeftAffordance);
if (mLeftIsVoiceAssist) {
- mIconState.isVisible = mUserSetupComplete && showAffordance;
+ mIconState.isVisible = mUserSetupComplete && mShowLeftAffordance;
if (mLeftAssistIcon == null) {
mIconState.drawable = mContext.getDrawable(R.drawable.ic_mic_26dp);
} else {
@@ -783,7 +792,8 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
mIconState.contentDescription = mContext.getString(
R.string.accessibility_voice_assist_button);
} else {
- mIconState.isVisible = mUserSetupComplete && showAffordance && isPhoneVisible();
+ mIconState.isVisible = mUserSetupComplete && mShowLeftAffordance
+ && isPhoneVisible();
mIconState.drawable = mContext.getDrawable(
com.android.internal.R.drawable.ic_phone);
mIconState.contentDescription = mContext.getString(
@@ -806,7 +816,7 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
public IconState getIcon() {
boolean isCameraDisabled = (mStatusBar != null) && !mStatusBar.isCameraAllowedByAdmin();
mIconState.isVisible = !isCameraDisabled
- && getResources().getBoolean(R.bool.config_keyguardShowCameraAffordance)
+ && mShowCameraAffordance
&& mUserSetupComplete
&& resolveCameraIntent() != null;
mIconState.drawable = mContext.getDrawable(R.drawable.ic_camera_alt_24dp);
@@ -817,11 +827,9 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
@Override
public Intent getIntent() {
- KeyguardUpdateMonitor updateMonitor = Dependency.get(KeyguardUpdateMonitor.class);
- boolean canSkipBouncer = updateMonitor.getUserCanSkipBouncer(
- KeyguardUpdateMonitor.getCurrentUser());
- boolean secure = mUnlockMethodCache.isMethodSecure();
- return (secure && !canSkipBouncer) ? SECURE_CAMERA_INTENT : INSECURE_CAMERA_INTENT;
+ boolean canDismissLs = mKeyguardStateController.canDismissLockScreen();
+ boolean secure = mKeyguardStateController.isMethodSecure();
+ return (secure && !canDismissLs) ? SECURE_CAMERA_INTENT : INSECURE_CAMERA_INTENT;
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
index d7f67cef033e..f34c15c7099d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
@@ -17,7 +17,6 @@
package com.android.systemui.statusbar.phone;
import static com.android.keyguard.KeyguardSecurityModel.SecurityMode;
-import static com.android.systemui.DejankUtils.whitelistIpcs;
import static com.android.systemui.plugins.ActivityStarter.OnDismissAction;
import android.content.Context;
@@ -38,14 +37,17 @@ import android.view.WindowInsets;
import com.android.internal.widget.LockPatternUtils;
import com.android.keyguard.KeyguardHostView;
+import com.android.keyguard.KeyguardSecurityModel;
import com.android.keyguard.KeyguardSecurityView;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.keyguard.KeyguardUpdateMonitorCallback;
import com.android.keyguard.ViewMediatorCallback;
import com.android.systemui.DejankUtils;
+import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.keyguard.DismissCallbackRegistry;
import com.android.systemui.plugins.FalsingManager;
+import com.android.systemui.statusbar.policy.KeyguardStateController;
import java.io.PrintWriter;
@@ -69,7 +71,7 @@ public class KeyguardBouncer {
private final Handler mHandler;
private final BouncerExpansionCallback mExpansionCallback;
private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
- private final UnlockMethodCache mUnlockMethodCache;
+ private final KeyguardStateController mKeyguardStateController;
private final KeyguardUpdateMonitorCallback mUpdateMonitorCallback =
new KeyguardUpdateMonitorCallback() {
@Override
@@ -97,7 +99,8 @@ public class KeyguardBouncer {
public KeyguardBouncer(Context context, ViewMediatorCallback callback,
LockPatternUtils lockPatternUtils, ViewGroup container,
DismissCallbackRegistry dismissCallbackRegistry, FalsingManager falsingManager,
- BouncerExpansionCallback expansionCallback, UnlockMethodCache unlockMethodCache,
+ BouncerExpansionCallback expansionCallback,
+ KeyguardStateController keyguardStateController,
KeyguardUpdateMonitor keyguardUpdateMonitor,
KeyguardBypassController keyguardBypassController, Handler handler) {
mContext = context;
@@ -109,7 +112,7 @@ public class KeyguardBouncer {
mDismissCallbackRegistry = dismissCallbackRegistry;
mExpansionCallback = expansionCallback;
mHandler = handler;
- mUnlockMethodCache = unlockMethodCache;
+ mKeyguardStateController = keyguardStateController;
mKeyguardUpdateMonitor.registerCallback(mUpdateMonitorCallback);
mKeyguardBypassController = keyguardBypassController;
}
@@ -173,7 +176,7 @@ public class KeyguardBouncer {
// Split up the work over multiple frames.
DejankUtils.removeCallbacks(mResetRunnable);
- if (mUnlockMethodCache.isFaceAuthEnabled() && !needsFullscreenBouncer()
+ if (mKeyguardStateController.isFaceAuthEnabled() && !needsFullscreenBouncer()
&& !mKeyguardUpdateMonitor.userNeedsStrongAuth()
&& !mKeyguardBypassController.getBypassEnabled()) {
mHandler.postDelayed(mShowRunnable, BOUNCER_FACE_DELAY);
@@ -459,15 +462,9 @@ public class KeyguardBouncer {
* notifications on Keyguard, like SIM PIN/PUK.
*/
public boolean needsFullscreenBouncer() {
- // TODO(b/140059518)
- return whitelistIpcs(() -> {
- ensureView();
- if (mKeyguardView != null) {
- SecurityMode mode = mKeyguardView.getSecurityMode();
- return mode == SecurityMode.SimPin || mode == SecurityMode.SimPuk;
- }
- return false;
- });
+ SecurityMode mode = Dependency.get(KeyguardSecurityModel.class).getSecurityMode(
+ KeyguardUpdateMonitor.getCurrentUser());
+ return mode == SecurityMode.SimPin || mode == SecurityMode.SimPuk;
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBypassController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBypassController.kt
index 832ea9e3d72e..aca7f443ea0c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBypassController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBypassController.kt
@@ -23,6 +23,7 @@ import android.provider.Settings
import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.statusbar.NotificationLockscreenUserManager
import com.android.systemui.statusbar.StatusBarState
+import com.android.systemui.statusbar.policy.KeyguardStateController
import com.android.systemui.tuner.TunerService
import java.io.PrintWriter
import javax.inject.Inject
@@ -31,7 +32,7 @@ import javax.inject.Singleton
@Singleton
class KeyguardBypassController {
- private val unlockMethodCache: UnlockMethodCache
+ private val mKeyguardStateController: KeyguardStateController
private val statusBarStateController: StatusBarStateController
private var hasFaceFeature: Boolean
@@ -47,7 +48,7 @@ class KeyguardBypassController {
* If face unlock dismisses the lock screen or keeps user on keyguard for the current user.
*/
var bypassEnabled: Boolean = false
- get() = field && unlockMethodCache.isFaceAuthEnabled
+ get() = field && mKeyguardStateController.isFaceAuthEnabled
private set
var bouncerShowing: Boolean = false
@@ -66,9 +67,10 @@ class KeyguardBypassController {
context: Context,
tunerService: TunerService,
statusBarStateController: StatusBarStateController,
- lockscreenUserManager: NotificationLockscreenUserManager
+ lockscreenUserManager: NotificationLockscreenUserManager,
+ keyguardStateController: KeyguardStateController
) {
- unlockMethodCache = UnlockMethodCache.getInstance(context)
+ this.mKeyguardStateController = keyguardStateController
this.statusBarStateController = statusBarStateController
hasFaceFeature = context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_FACE)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardLiftController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardLiftController.kt
index 00b764bfbe9b..bf887044e05b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardLiftController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardLiftController.kt
@@ -21,17 +21,16 @@ import android.hardware.TriggerEvent
import android.hardware.TriggerEventListener
import com.android.keyguard.KeyguardUpdateMonitor
import com.android.keyguard.KeyguardUpdateMonitorCallback
-import com.android.systemui.Dependency
import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.util.Assert
import com.android.systemui.util.sensors.AsyncSensorManager
class KeyguardLiftController constructor(
private val statusBarStateController: StatusBarStateController,
- private val asyncSensorManager: AsyncSensorManager
+ private val asyncSensorManager: AsyncSensorManager,
+ private val keyguardUpdateMonitor: KeyguardUpdateMonitor
) : StatusBarStateController.StateListener, KeyguardUpdateMonitorCallback() {
- private val keyguardUpdateMonitor = Dependency.get(KeyguardUpdateMonitor::class.java)
private val pickupSensor = asyncSensorManager.getDefaultSensor(Sensor.TYPE_PICK_UP_GESTURE)
private var isListening = false
private var bouncerVisible = false
@@ -66,6 +65,9 @@ class KeyguardLiftController constructor(
}
private fun updateListeningState() {
+ if (pickupSensor == null) {
+ return
+ }
val onKeyguard = keyguardUpdateMonitor.isKeyguardVisible &&
!statusBarStateController.isDozing
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarController.java
index b0b656a1a951..2e776e39b54c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarController.java
@@ -16,15 +16,20 @@
package com.android.systemui.statusbar.phone;
+import static android.view.WindowInsetsController.APPEARANCE_LIGHT_SIDE_BARS;
+import static android.view.WindowInsetsController.APPEARANCE_LIGHT_TOP_BAR;
+
import static com.android.systemui.statusbar.phone.BarTransitions.MODE_LIGHTS_OUT_TRANSPARENT;
import static com.android.systemui.statusbar.phone.BarTransitions.MODE_TRANSPARENT;
import android.content.Context;
import android.graphics.Color;
-import android.graphics.Rect;
-import android.view.View;
+import android.view.InsetsFlags;
+import android.view.ViewDebug;
+import android.view.WindowInsetsController.Appearance;
import com.android.internal.colorextraction.ColorExtractor.GradientColors;
+import com.android.internal.view.AppearanceRegion;
import com.android.systemui.Dumpable;
import com.android.systemui.R;
import com.android.systemui.plugins.DarkIconDispatcher;
@@ -49,13 +54,10 @@ public class LightBarController implements BatteryController.BatteryStateChangeC
private BiometricUnlockController mBiometricUnlockController;
private LightBarTransitionsController mNavigationBarController;
- private int mSystemUiVisibility;
- private int mFullscreenStackVisibility;
- private int mDockedStackVisibility;
- private boolean mFullscreenLight;
- private boolean mDockedLight;
- private int mLastStatusBarMode;
- private int mLastNavigationBarMode;
+ private @Appearance int mAppearance;
+ private AppearanceRegion[] mAppearanceRegions = new AppearanceRegion[0];
+ private int mStatusBarMode;
+ private int mNavigationBarMode;
private final Color mDarkModeColor;
/**
@@ -75,8 +77,6 @@ public class LightBarController implements BatteryController.BatteryStateChangeC
*/
private boolean mForceDarkForScrim;
- private final Rect mLastFullscreenBounds = new Rect();
- private final Rect mLastDockedBounds = new Rect();
private boolean mQsCustomizing;
private boolean mDirectReplying;
@@ -101,45 +101,32 @@ public class LightBarController implements BatteryController.BatteryStateChangeC
mBiometricUnlockController = biometricUnlockController;
}
- public void onSystemUiVisibilityChanged(int fullscreenStackVis, int dockedStackVis,
- int mask, Rect fullscreenStackBounds, Rect dockedStackBounds, boolean sbModeChanged,
+ void onStatusBarAppearanceChanged(AppearanceRegion[] appearanceRegions, boolean sbModeChanged,
int statusBarMode, boolean navbarColorManagedByIme) {
- int oldFullscreen = mFullscreenStackVisibility;
- int newFullscreen = (oldFullscreen & ~mask) | (fullscreenStackVis & mask);
- int diffFullscreen = newFullscreen ^ oldFullscreen;
- int oldDocked = mDockedStackVisibility;
- int newDocked = (oldDocked & ~mask) | (dockedStackVis & mask);
- int diffDocked = newDocked ^ oldDocked;
- if ((diffFullscreen & View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR) != 0
- || (diffDocked & View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR) != 0
- || sbModeChanged
- || !mLastFullscreenBounds.equals(fullscreenStackBounds)
- || !mLastDockedBounds.equals(dockedStackBounds)) {
-
- mFullscreenLight = isLight(newFullscreen, statusBarMode,
- View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
- mDockedLight = isLight(newDocked, statusBarMode, View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
- updateStatus(fullscreenStackBounds, dockedStackBounds);
+ final int numStacks = appearanceRegions.length;
+ boolean stackAppearancesChanged = mAppearanceRegions.length != numStacks;
+ for (int i = 0; i < numStacks && !stackAppearancesChanged; i++) {
+ stackAppearancesChanged |= !appearanceRegions[i].equals(mAppearanceRegions[i]);
+ }
+ if (stackAppearancesChanged || sbModeChanged) {
+ mAppearanceRegions = appearanceRegions;
+ onStatusBarModeChanged(statusBarMode);
}
-
- mFullscreenStackVisibility = newFullscreen;
- mDockedStackVisibility = newDocked;
- mLastStatusBarMode = statusBarMode;
mNavbarColorManagedByIme = navbarColorManagedByIme;
- mLastFullscreenBounds.set(fullscreenStackBounds);
- mLastDockedBounds.set(dockedStackBounds);
}
- public void onNavigationVisibilityChanged(int vis, int mask, boolean nbModeChanged,
+ void onStatusBarModeChanged(int newBarMode) {
+ mStatusBarMode = newBarMode;
+ updateStatus();
+ }
+
+ void onNavigationBarAppearanceChanged(@Appearance int appearance, boolean nbModeChanged,
int navigationBarMode, boolean navbarColorManagedByIme) {
- int oldVis = mSystemUiVisibility;
- int newVis = (oldVis & ~mask) | (vis & mask);
- int diffVis = newVis ^ oldVis;
- if ((diffVis & View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR) != 0
- || nbModeChanged) {
- boolean last = mNavigationLight;
- mHasLightNavigationBar = isLight(vis, navigationBarMode,
- View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR);
+ int diff = appearance ^ mAppearance;
+ if ((diff & APPEARANCE_LIGHT_SIDE_BARS) != 0 || nbModeChanged) {
+ final boolean last = mNavigationLight;
+ mHasLightNavigationBar = isLight(appearance, navigationBarMode,
+ APPEARANCE_LIGHT_SIDE_BARS);
mNavigationLight = mHasLightNavigationBar
&& (mDirectReplying && mNavbarColorManagedByIme || !mForceDarkForScrim)
&& !mQsCustomizing;
@@ -147,17 +134,20 @@ public class LightBarController implements BatteryController.BatteryStateChangeC
updateNavigation();
}
}
- mSystemUiVisibility = newVis;
- mLastNavigationBarMode = navigationBarMode;
+ mAppearance = appearance;
+ mNavigationBarMode = navigationBarMode;
mNavbarColorManagedByIme = navbarColorManagedByIme;
}
+ void onNavigationBarModeChanged(int newBarMode) {
+ mHasLightNavigationBar = isLight(mAppearance, newBarMode, APPEARANCE_LIGHT_SIDE_BARS);
+ }
+
private void reevaluate() {
- onSystemUiVisibilityChanged(mFullscreenStackVisibility,
- mDockedStackVisibility, 0 /* mask */, mLastFullscreenBounds, mLastDockedBounds,
- true /* sbModeChange*/, mLastStatusBarMode, mNavbarColorManagedByIme);
- onNavigationVisibilityChanged(mSystemUiVisibility, 0 /* mask */, true /* nbModeChanged */,
- mLastNavigationBarMode, mNavbarColorManagedByIme);
+ onStatusBarAppearanceChanged(mAppearanceRegions, true /* sbModeChange */, mStatusBarMode,
+ mNavbarColorManagedByIme);
+ onNavigationBarAppearanceChanged(mAppearance, true /* nbModeChanged */,
+ mNavigationBarMode, mNavbarColorManagedByIme);
}
public void setQsCustomizing(boolean customizing) {
@@ -191,10 +181,10 @@ public class LightBarController implements BatteryController.BatteryStateChangeC
}
}
- private boolean isLight(int vis, int barMode, int flag) {
- boolean isTransparentBar = (barMode == MODE_TRANSPARENT
+ private static boolean isLight(int appearance, int barMode, int flag) {
+ final boolean isTransparentBar = (barMode == MODE_TRANSPARENT
|| barMode == MODE_LIGHTS_OUT_TRANSPARENT);
- boolean light = (vis & flag) != 0;
+ final boolean light = (appearance & flag) != 0;
return isTransparentBar && light;
}
@@ -207,49 +197,49 @@ public class LightBarController implements BatteryController.BatteryStateChangeC
&& unlockMode != BiometricUnlockController.MODE_WAKE_AND_UNLOCK;
}
- private void updateStatus(Rect fullscreenStackBounds, Rect dockedStackBounds) {
- boolean hasDockedStack = !dockedStackBounds.isEmpty();
+ private void updateStatus() {
+ final int numStacks = mAppearanceRegions.length;
+ int numLightStacks = 0;
+
+ // We can only have maximum one light stack.
+ int indexLightStack = -1;
- // If both are light or fullscreen is light and there is no docked stack, all icons get
- // dark.
- if ((mFullscreenLight && mDockedLight) || (mFullscreenLight && !hasDockedStack)) {
+ for (int i = 0; i < numStacks; i++) {
+ if (isLight(mAppearanceRegions[i].getAppearance(), mStatusBarMode,
+ APPEARANCE_LIGHT_TOP_BAR)) {
+ numLightStacks++;
+ indexLightStack = i;
+ }
+ }
+
+ // If all stacks are light, all icons get dark.
+ if (numLightStacks == numStacks) {
mStatusBarIconController.setIconsDarkArea(null);
mStatusBarIconController.getTransitionsController().setIconsDark(true, animateChange());
}
- // If no one is light or the fullscreen is not light and there is no docked stack,
- // all icons become white.
- else if ((!mFullscreenLight && !mDockedLight) || (!mFullscreenLight && !hasDockedStack)) {
+ // If no one is light, all icons become white.
+ else if (numLightStacks == 0) {
mStatusBarIconController.getTransitionsController().setIconsDark(
false, animateChange());
}
// Not the same for every stack, magic!
else {
- Rect bounds = mFullscreenLight ? fullscreenStackBounds : dockedStackBounds;
- if (bounds.isEmpty()) {
- mStatusBarIconController.setIconsDarkArea(null);
- } else {
- mStatusBarIconController.setIconsDarkArea(bounds);
- }
+ mStatusBarIconController.setIconsDarkArea(
+ mAppearanceRegions[indexLightStack].getBounds());
mStatusBarIconController.getTransitionsController().setIconsDark(true, animateChange());
}
}
private void updateNavigation() {
if (mNavigationBarController != null) {
- mNavigationBarController.setIconsDark(
- mNavigationLight, animateChange());
+ mNavigationBarController.setIconsDark(mNavigationLight, animateChange());
}
}
@Override
- public void onBatteryLevelChanged(int level, boolean pluggedIn, boolean charging) {
-
- }
-
- @Override
public void onPowerSaveChanged(boolean isPowerSave) {
reevaluate();
}
@@ -257,24 +247,21 @@ public class LightBarController implements BatteryController.BatteryStateChangeC
@Override
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
pw.println("LightBarController: ");
- pw.print(" mSystemUiVisibility=0x"); pw.print(
- Integer.toHexString(mSystemUiVisibility));
- pw.print(" mFullscreenStackVisibility=0x"); pw.print(
- Integer.toHexString(mFullscreenStackVisibility));
- pw.print(" mDockedStackVisibility=0x"); pw.println(
- Integer.toHexString(mDockedStackVisibility));
-
- pw.print(" mFullscreenLight="); pw.print(mFullscreenLight);
- pw.print(" mDockedLight="); pw.println(mDockedLight);
-
- pw.print(" mLastFullscreenBounds="); pw.print(mLastFullscreenBounds);
- pw.print(" mLastDockedBounds="); pw.println(mLastDockedBounds);
+ pw.print(" mAppearance=0x"); pw.println(ViewDebug.flagsToString(
+ InsetsFlags.class, "appearance", mAppearance));
+ final int numStacks = mAppearanceRegions.length;
+ for (int i = 0; i < numStacks; i++) {
+ final boolean isLight = isLight(mAppearanceRegions[i].getAppearance(), mStatusBarMode,
+ APPEARANCE_LIGHT_TOP_BAR);
+ pw.print(" stack #"); pw.print(i); pw.print(": ");
+ pw.print(mAppearanceRegions[i].toString()); pw.print(" isLight="); pw.println(isLight);
+ }
pw.print(" mNavigationLight="); pw.print(mNavigationLight);
pw.print(" mHasLightNavigationBar="); pw.println(mHasLightNavigationBar);
- pw.print(" mLastStatusBarMode="); pw.print(mLastStatusBarMode);
- pw.print(" mLastNavigationBarMode="); pw.println(mLastNavigationBarMode);
+ pw.print(" mStatusBarMode="); pw.print(mStatusBarMode);
+ pw.print(" mNavigationBarMode="); pw.println(mNavigationBarMode);
pw.print(" mForceDarkForScrim="); pw.print(mForceDarkForScrim);
pw.print(" mQsCustomizing="); pw.print(mQsCustomizing);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarTransitionsController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarTransitionsController.java
index d7097309ce20..de660ce18263 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarTransitionsController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarTransitionsController.java
@@ -31,7 +31,7 @@ import com.android.systemui.SysUiServiceProvider;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.CommandQueue.Callbacks;
-import com.android.systemui.statusbar.policy.KeyguardMonitor;
+import com.android.systemui.statusbar.policy.KeyguardStateController;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -47,7 +47,7 @@ public class LightBarTransitionsController implements Dumpable, Callbacks,
private final Handler mHandler;
private final DarkIntensityApplier mApplier;
- private final KeyguardMonitor mKeyguardMonitor;
+ private final KeyguardStateController mKeyguardStateController;
private final StatusBarStateController mStatusBarStateController;
private boolean mTransitionDeferring;
@@ -73,7 +73,7 @@ public class LightBarTransitionsController implements Dumpable, Callbacks,
public LightBarTransitionsController(Context context, DarkIntensityApplier applier) {
mApplier = applier;
mHandler = new Handler();
- mKeyguardMonitor = Dependency.get(KeyguardMonitor.class);
+ mKeyguardStateController = Dependency.get(KeyguardStateController.class);
mStatusBarStateController = Dependency.get(StatusBarStateController.class);
SysUiServiceProvider.getComponent(context, CommandQueue.class)
.addCallback(this);
@@ -101,7 +101,7 @@ public class LightBarTransitionsController implements Dumpable, Callbacks,
@Override
public void appTransitionPending(int displayId, boolean forced) {
- if (mDisplayId != displayId || mKeyguardMonitor.isKeyguardGoingAway() && !forced) {
+ if (mDisplayId != displayId || mKeyguardStateController.isKeyguardGoingAway() && !forced) {
return;
}
mTransitionPending = true;
@@ -123,7 +123,7 @@ public class LightBarTransitionsController implements Dumpable, Callbacks,
@Override
public void appTransitionStarting(int displayId, long startTime, long duration,
boolean forced) {
- if (mDisplayId != displayId || mKeyguardMonitor.isKeyguardGoingAway() && !forced) {
+ if (mDisplayId != displayId || mKeyguardStateController.isKeyguardGoingAway() && !forced) {
return;
}
if (mTransitionPending && mTintChangePending) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java
index 67810738b17e..4927ec8a9a47 100755
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java
@@ -53,7 +53,7 @@ import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator
import com.android.systemui.statusbar.phone.ScrimController.ScrimVisibility;
import com.android.systemui.statusbar.policy.AccessibilityController;
import com.android.systemui.statusbar.policy.ConfigurationController;
-import com.android.systemui.statusbar.policy.KeyguardMonitor;
+import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener;
import com.android.systemui.statusbar.policy.UserInfoController.OnUserInfoChangedListener;
@@ -68,9 +68,8 @@ import javax.inject.Named;
*/
public class LockIcon extends KeyguardAffordanceView implements OnUserInfoChangedListener,
StatusBarStateController.StateListener, ConfigurationController.ConfigurationListener,
- UnlockMethodCache.OnUnlockMethodChangedListener,
- NotificationWakeUpCoordinator.WakeUpListener, ViewTreeObserver.OnPreDrawListener,
- OnHeadsUpChangedListener {
+ KeyguardStateController.Callback, NotificationWakeUpCoordinator.WakeUpListener,
+ ViewTreeObserver.OnPreDrawListener, OnHeadsUpChangedListener {
private static final int STATE_LOCKED = 0;
private static final int STATE_LOCK_OPEN = 1;
@@ -78,11 +77,10 @@ public class LockIcon extends KeyguardAffordanceView implements OnUserInfoChange
private static final int STATE_BIOMETRICS_ERROR = 3;
private final ConfigurationController mConfigurationController;
private final StatusBarStateController mStatusBarStateController;
- private final UnlockMethodCache mUnlockMethodCache;
private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
private final AccessibilityController mAccessibilityController;
private final DockManager mDockManager;
- private final KeyguardMonitor mKeyguardMonitor;
+ private final KeyguardStateController mKeyguardStateController;
private final KeyguardBypassController mBypassController;
private final NotificationWakeUpCoordinator mWakeUpCoordinator;
private final HeadsUpManagerPhone mHeadsUpManager;
@@ -107,13 +105,13 @@ public class LockIcon extends KeyguardAffordanceView implements OnUserInfoChange
private boolean mUpdatePending;
private boolean mBouncerPreHideAnimation;
- private final KeyguardMonitor.Callback mKeyguardMonitorCallback =
- new KeyguardMonitor.Callback() {
+ private final KeyguardStateController.Callback mKeyguardMonitorCallback =
+ new KeyguardStateController.Callback() {
@Override
public void onKeyguardShowingChanged() {
boolean force = false;
boolean wasShowing = mKeyguardShowing;
- mKeyguardShowing = mKeyguardMonitor.isShowing();
+ mKeyguardShowing = mKeyguardStateController.isShowing();
if (!wasShowing && mKeyguardShowing && mBlockUpdates) {
mBlockUpdates = false;
force = true;
@@ -126,7 +124,7 @@ public class LockIcon extends KeyguardAffordanceView implements OnUserInfoChange
@Override
public void onKeyguardFadingAwayChanged() {
- if (!mKeyguardMonitor.isKeyguardFadingAway()) {
+ if (!mKeyguardStateController.isKeyguardFadingAway()) {
mBouncerPreHideAnimation = false;
if (mBlockUpdates) {
mBlockUpdates = false;
@@ -134,6 +132,11 @@ public class LockIcon extends KeyguardAffordanceView implements OnUserInfoChange
}
}
}
+
+ @Override
+ public void onUnlockedChanged() {
+ update();
+ }
};
private final DockManager.DockEventListener mDockEventListener =
new DockManager.DockEventListener() {
@@ -181,19 +184,18 @@ public class LockIcon extends KeyguardAffordanceView implements OnUserInfoChange
AccessibilityController accessibilityController,
KeyguardBypassController bypassController,
NotificationWakeUpCoordinator wakeUpCoordinator,
- KeyguardMonitor keyguardMonitor,
+ KeyguardStateController keyguardStateController,
@Nullable DockManager dockManager,
HeadsUpManagerPhone headsUpManager) {
super(context, attrs);
mContext = context;
- mUnlockMethodCache = UnlockMethodCache.getInstance(context);
mKeyguardUpdateMonitor = Dependency.get(KeyguardUpdateMonitor.class);
mAccessibilityController = accessibilityController;
mConfigurationController = configurationController;
mStatusBarStateController = statusBarStateController;
mBypassController = bypassController;
mWakeUpCoordinator = wakeUpCoordinator;
- mKeyguardMonitor = keyguardMonitor;
+ mKeyguardStateController = keyguardStateController;
mDockManager = dockManager;
mHeadsUpManager = headsUpManager;
}
@@ -203,9 +205,8 @@ public class LockIcon extends KeyguardAffordanceView implements OnUserInfoChange
super.onAttachedToWindow();
mStatusBarStateController.addCallback(this);
mConfigurationController.addCallback(this);
- mKeyguardMonitor.addCallback(mKeyguardMonitorCallback);
+ mKeyguardStateController.addCallback(mKeyguardMonitorCallback);
mKeyguardUpdateMonitor.registerCallback(mUpdateMonitorCallback);
- mUnlockMethodCache.addListener(this);
mWakeUpCoordinator.addListener(this);
mSimLocked = mKeyguardUpdateMonitor.isSimPinSecure();
if (mDockManager != null) {
@@ -221,9 +222,8 @@ public class LockIcon extends KeyguardAffordanceView implements OnUserInfoChange
mStatusBarStateController.removeCallback(this);
mConfigurationController.removeCallback(this);
mKeyguardUpdateMonitor.removeCallback(mUpdateMonitorCallback);
- mKeyguardMonitor.removeCallback(mKeyguardMonitorCallback);
+ mKeyguardStateController.removeCallback(mKeyguardMonitorCallback);
mWakeUpCoordinator.removeListener(this);
- mUnlockMethodCache.removeListener(this);
if (mDockManager != null) {
mDockManager.removeListener(mDockEventListener);
}
@@ -370,15 +370,15 @@ public class LockIcon extends KeyguardAffordanceView implements OnUserInfoChange
}
private boolean canBlockUpdates() {
- return mKeyguardShowing || mKeyguardMonitor.isKeyguardFadingAway();
+ return mKeyguardShowing || mKeyguardStateController.isKeyguardFadingAway();
}
private void updateClickability() {
if (mAccessibilityController == null) {
return;
}
- boolean canLock = mUnlockMethodCache.isMethodSecure()
- && mUnlockMethodCache.canSkipBouncer();
+ boolean canLock = mKeyguardStateController.isMethodSecure()
+ && mKeyguardStateController.canDismissLockScreen();
boolean clickToUnlock = mAccessibilityController.isAccessibilityEnabled();
setClickable(clickToUnlock);
setLongClickable(canLock && !clickToUnlock);
@@ -523,8 +523,8 @@ public class LockIcon extends KeyguardAffordanceView implements OnUserInfoChange
private int getState() {
KeyguardUpdateMonitor updateMonitor = Dependency.get(KeyguardUpdateMonitor.class);
- if ((mUnlockMethodCache.canSkipBouncer() || !mKeyguardShowing || mBouncerPreHideAnimation
- || mKeyguardMonitor.isKeyguardGoingAway()) && !mSimLocked) {
+ if ((mKeyguardStateController.canDismissLockScreen() || !mKeyguardShowing
+ || mKeyguardStateController.isKeyguardGoingAway()) && !mSimLocked) {
return STATE_LOCK_OPEN;
} else if (mTransientBiometricsError) {
return STATE_BIOMETRICS_ERROR;
@@ -582,11 +582,6 @@ public class LockIcon extends KeyguardAffordanceView implements OnUserInfoChange
update(true /* force */);
}
- @Override
- public void onUnlockMethodStateChanged() {
- update();
- }
-
/**
* We need to hide the lock whenever there's a fingerprint unlock, otherwise you'll see the
* icon on top of the black front scrim.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenWallpaper.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenWallpaper.java
index e34c639a23c2..4d6b54ccfaff 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenWallpaper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenWallpaper.java
@@ -22,7 +22,6 @@ import android.app.IWallpaperManager;
import android.app.IWallpaperManagerCallback;
import android.app.WallpaperColors;
import android.app.WallpaperManager;
-import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
@@ -35,7 +34,6 @@ import android.os.AsyncTask;
import android.os.Handler;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
-import android.os.ServiceManager;
import android.os.UserHandle;
import android.util.Log;
@@ -47,9 +45,13 @@ import libcore.io.IoUtils;
import java.util.Objects;
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
/**
* Manages the lockscreen wallpaper.
*/
+@Singleton
public class LockscreenWallpaper extends IWallpaperManagerCallback.Stub implements Runnable {
private static final String TAG = "LockscreenWallpaper";
@@ -57,9 +59,8 @@ public class LockscreenWallpaper extends IWallpaperManagerCallback.Stub implemen
private final NotificationMediaManager mMediaManager =
Dependency.get(NotificationMediaManager.class);
- private final StatusBar mBar;
private final WallpaperManager mWallpaperManager;
- private final Handler mH;
+ private Handler mH;
private final KeyguardUpdateMonitor mUpdateMonitor;
private boolean mCached;
@@ -70,25 +71,32 @@ public class LockscreenWallpaper extends IWallpaperManagerCallback.Stub implemen
private UserHandle mSelectedUser;
private AsyncTask<Void, Void, LoaderResult> mLoader;
- public LockscreenWallpaper(Context ctx, StatusBar bar, Handler h) {
- mBar = bar;
- mH = h;
- mWallpaperManager = (WallpaperManager) ctx.getSystemService(Context.WALLPAPER_SERVICE);
+ @Inject
+ public LockscreenWallpaper(WallpaperManager wallpaperManager,
+ @Nullable IWallpaperManager iWallpaperManager,
+ KeyguardUpdateMonitor keyguardUpdateMonitor) {
+ mWallpaperManager = wallpaperManager;
mCurrentUserId = ActivityManager.getCurrentUser();
- mUpdateMonitor = Dependency.get(KeyguardUpdateMonitor.class);
+ mUpdateMonitor = keyguardUpdateMonitor;
- IWallpaperManager service = IWallpaperManager.Stub.asInterface(
- ServiceManager.getService(Context.WALLPAPER_SERVICE));
- if (service != null) {
+ if (iWallpaperManager != null) {
// Service is disabled on some devices like Automotive
try {
- service.setLockWallpaperCallback(this);
+ iWallpaperManager.setLockWallpaperCallback(this);
} catch (RemoteException e) {
Log.e(TAG, "System dead?" + e);
}
}
}
+ void setHandler(Handler handler) {
+ if (mH != null) {
+ Log.wtfStack(TAG, "Handler has already been set. Trying to double initialize?");
+ return;
+ }
+ mH = handler;
+ }
+
public Bitmap getBitmap() {
if (mCached) {
return mCache;
@@ -176,6 +184,10 @@ public class LockscreenWallpaper extends IWallpaperManagerCallback.Stub implemen
}
private void postUpdateWallpaper() {
+ if (mH == null) {
+ Log.wtfStack(TAG, "Trying to use LockscreenWallpaper before initialization.");
+ return;
+ }
mH.removeCallbacks(this);
mH.post(this);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NPVPluginManager.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NPVPluginManager.kt
index 7dcc2fcfe2b2..53601babfd56 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NPVPluginManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NPVPluginManager.kt
@@ -18,6 +18,7 @@ package com.android.systemui.statusbar.phone
import android.content.Context
import android.view.View
+import android.view.ViewGroup.MarginLayoutParams
import android.widget.FrameLayout
import com.android.systemui.plugins.NPVPlugin
import com.android.systemui.plugins.PluginListener
@@ -36,6 +37,7 @@ class NPVPluginManager(
private var plugin: NPVPlugin? = null
private var animator = createAnimator()
+ private var yOffset = 0f
private fun createAnimator() = TouchAnimator.Builder()
.addFloat(parent, "alpha", 1f, 0f)
@@ -76,7 +78,7 @@ class NPVPluginManager(
}
fun setExpansion(expansion: Float, headerTranslation: Float, heightDiff: Float) {
- parent.setTranslationY(expansion * heightDiff + headerTranslation)
+ parent.setTranslationY(expansion * heightDiff + headerTranslation + yOffset)
if (!expansion.isNaN()) animator.setPosition(expansion)
}
@@ -88,5 +90,13 @@ class NPVPluginManager(
animator = createAnimator()
}
- fun getHeight() = if (plugin != null) parent.height else 0
+ fun getHeight() =
+ if (plugin != null) {
+ parent.height + (parent.getLayoutParams() as MarginLayoutParams).topMargin
+ } else 0
+
+ fun setYOffset(y: Float) {
+ yOffset = y
+ parent.setTranslationY(yOffset)
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
index 2b8c86b8c549..7030dfc4c33b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
@@ -21,6 +21,10 @@ import static android.app.StatusBarManager.WINDOW_STATE_SHOWING;
import static android.app.StatusBarManager.WindowType;
import static android.app.StatusBarManager.WindowVisibleState;
import static android.app.StatusBarManager.windowStateToString;
+import static android.view.InsetsState.TYPE_NAVIGATION_BAR;
+import static android.view.InsetsState.containsType;
+import static android.view.WindowInsetsController.APPEARANCE_LOW_PROFILE_BARS;
+import static android.view.WindowInsetsController.APPEARANCE_OPAQUE_SIDE_BARS;
import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_3BUTTON;
import static com.android.systemui.recents.OverviewProxyService.OverviewProxyListener;
@@ -31,7 +35,6 @@ import static com.android.systemui.statusbar.phone.BarTransitions.MODE_LIGHTS_OU
import static com.android.systemui.statusbar.phone.BarTransitions.MODE_LIGHTS_OUT_TRANSPARENT;
import static com.android.systemui.statusbar.phone.BarTransitions.MODE_OPAQUE;
import static com.android.systemui.statusbar.phone.BarTransitions.MODE_SEMI_TRANSPARENT;
-import static com.android.systemui.statusbar.phone.BarTransitions.MODE_TRANSLUCENT;
import static com.android.systemui.statusbar.phone.BarTransitions.MODE_TRANSPARENT;
import static com.android.systemui.statusbar.phone.BarTransitions.TransitionMode;
import static com.android.systemui.statusbar.phone.StatusBar.DEBUG_WINDOW_STATE;
@@ -52,7 +55,6 @@ import android.content.IntentFilter;
import android.content.res.Configuration;
import android.database.ContentObserver;
import android.graphics.PixelFormat;
-import android.graphics.Rect;
import android.inputmethodservice.InputMethodService;
import android.net.Uri;
import android.os.Binder;
@@ -67,12 +69,14 @@ import android.telecom.TelecomManager;
import android.text.TextUtils;
import android.util.Log;
import android.view.Display;
+import android.view.InsetsState.InternalInsetType;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.Surface;
import android.view.View;
import android.view.ViewGroup;
+import android.view.WindowInsetsController.Appearance;
import android.view.WindowManager;
import android.view.WindowManager.LayoutParams;
import android.view.accessibility.AccessibilityEvent;
@@ -84,11 +88,13 @@ import androidx.annotation.VisibleForTesting;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.util.LatencyTracker;
+import com.android.internal.view.AppearanceRegion;
import com.android.systemui.Dependency;
import com.android.systemui.R;
-import com.android.systemui.ScreenDecorations;
import com.android.systemui.SysUiServiceProvider;
+import com.android.systemui.assist.AssistHandleViewController;
import com.android.systemui.assist.AssistManager;
+import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.fragments.FragmentHostManager;
import com.android.systemui.fragments.FragmentHostManager.FragmentListener;
import com.android.systemui.model.SysUiState;
@@ -127,7 +133,8 @@ public class NavigationBarFragment extends LifecycleFragment implements Callback
private static final boolean DEBUG = false;
private static final String EXTRA_DISABLE_STATE = "disabled_state";
private static final String EXTRA_DISABLE2_STATE = "disabled2_state";
- private static final String EXTRA_SYSTEM_UI_VISIBILITY = "system_ui_visibility";
+ private static final String EXTRA_APPEARANCE = "appearance";
+ private static final String EXTRA_TRANSIENT_STATE = "transient_state";
/** Allow some time inbetween the long press for back and recents. */
private static final int LOCK_TO_APP_GESTURE_TOLERENCE = 200;
@@ -139,6 +146,7 @@ public class NavigationBarFragment extends LifecycleFragment implements Callback
private final MetricsLogger mMetricsLogger;
private final DeviceProvisionedController mDeviceProvisionedController;
private final StatusBarStateController mStatusBarStateController;
+ private final NavigationModeController mNavigationModeController;
protected NavigationBarView mNavigationBarView = null;
@@ -163,18 +171,26 @@ public class NavigationBarFragment extends LifecycleFragment implements Callback
private Locale mLocale;
private int mLayoutDirection;
- private int mSystemUiVisibility = View.SYSTEM_UI_FLAG_VISIBLE;
+ /** @see android.view.WindowInsetsController#setSystemBarsAppearance(int) */
+ private @Appearance int mAppearance;
+
+ private boolean mTransientShown;
private int mNavBarMode = NAV_BAR_MODE_3BUTTON;
private LightBarController mLightBarController;
private AutoHideController mAutoHideController;
private OverviewProxyService mOverviewProxyService;
+ private final BroadcastDispatcher mBroadcastDispatcher;
+
@VisibleForTesting
public int mDisplayId;
private boolean mIsOnDefaultDisplay;
public boolean mHomeBlockedThisTouch;
- private ScreenDecorations mScreenDecorations;
+
+ /** Only for default display */
+ @Nullable
+ private AssistHandleViewController mAssistHandlerViewController;
private Handler mHandler = Dependency.get(Dependency.MAIN_HANDLER);
@@ -248,7 +264,8 @@ public class NavigationBarFragment extends LifecycleFragment implements Callback
AssistManager assistManager, OverviewProxyService overviewProxyService,
NavigationModeController navigationModeController,
StatusBarStateController statusBarStateController,
- SysUiState sysUiFlagsContainer) {
+ SysUiState sysUiFlagsContainer,
+ BroadcastDispatcher broadcastDispatcher) {
mAccessibilityManagerWrapper = accessibilityManagerWrapper;
mDeviceProvisionedController = deviceProvisionedController;
mStatusBarStateController = statusBarStateController;
@@ -257,7 +274,9 @@ public class NavigationBarFragment extends LifecycleFragment implements Callback
mSysUiFlagsContainer = sysUiFlagsContainer;
mAssistantAvailable = mAssistManager.getAssistInfoForUser(UserHandle.USER_CURRENT) != null;
mOverviewProxyService = overviewProxyService;
+ mNavigationModeController = navigationModeController;
mNavBarMode = navigationModeController.addListener(this);
+ mBroadcastDispatcher = broadcastDispatcher;
}
// ----- Fragment Lifecycle Callbacks -----
@@ -285,7 +304,8 @@ public class NavigationBarFragment extends LifecycleFragment implements Callback
if (savedInstanceState != null) {
mDisabledFlags1 = savedInstanceState.getInt(EXTRA_DISABLE_STATE, 0);
mDisabledFlags2 = savedInstanceState.getInt(EXTRA_DISABLE2_STATE, 0);
- mSystemUiVisibility = savedInstanceState.getInt(EXTRA_SYSTEM_UI_VISIBILITY, 0);
+ mAppearance = savedInstanceState.getInt(EXTRA_APPEARANCE, 0);
+ mTransientShown = savedInstanceState.getBoolean(EXTRA_TRANSIENT_STATE, false);
}
mAccessibilityManagerWrapper.addCallback(mAccessibilityListener);
@@ -296,6 +316,7 @@ public class NavigationBarFragment extends LifecycleFragment implements Callback
@Override
public void onDestroy() {
super.onDestroy();
+ mNavigationModeController.removeListener(this);
mAccessibilityManagerWrapper.removeCallback(mAccessibilityListener);
mContentResolver.unregisterContentObserver(mMagnificationObserver);
mContentResolver.unregisterContentObserver(mAssistContentObserver);
@@ -334,7 +355,8 @@ public class NavigationBarFragment extends LifecycleFragment implements Callback
IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_OFF);
filter.addAction(Intent.ACTION_SCREEN_ON);
filter.addAction(Intent.ACTION_USER_SWITCHED);
- getContext().registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL, filter, null, null);
+ mBroadcastDispatcher.registerReceiver(mBroadcastReceiver, filter, Handler.getMain(),
+ UserHandle.ALL);
notifyNavigationBarScreenOn();
mOverviewProxyService.addCallback(mOverviewProxyListener);
@@ -357,22 +379,27 @@ public class NavigationBarFragment extends LifecycleFragment implements Callback
mDisabledFlags2 |= StatusBarManager.DISABLE2_ROTATE_SUGGESTIONS;
}
setDisabled2Flags(mDisabledFlags2);
-
- mScreenDecorations = SysUiServiceProvider.getComponent(getContext(),
- ScreenDecorations.class);
- getBarTransitions().addDarkIntensityListener(mScreenDecorations);
+ if (mIsOnDefaultDisplay) {
+ mAssistHandlerViewController =
+ new AssistHandleViewController(mHandler, mNavigationBarView);
+ getBarTransitions().addDarkIntensityListener(mAssistHandlerViewController);
+ }
}
@Override
public void onDestroyView() {
super.onDestroyView();
if (mNavigationBarView != null) {
- mNavigationBarView.getBarTransitions().removeDarkIntensityListener(mScreenDecorations);
+ if (mIsOnDefaultDisplay) {
+ mNavigationBarView.getBarTransitions()
+ .removeDarkIntensityListener(mAssistHandlerViewController);
+ mAssistHandlerViewController = null;
+ }
mNavigationBarView.getBarTransitions().destroy();
mNavigationBarView.getLightTransitionsController().destroy(getContext());
}
mOverviewProxyService.removeCallback(mOverviewProxyListener);
- getContext().unregisterReceiver(mBroadcastReceiver);
+ mBroadcastDispatcher.unregisterReceiver(mBroadcastReceiver);
}
@Override
@@ -380,7 +407,8 @@ public class NavigationBarFragment extends LifecycleFragment implements Callback
super.onSaveInstanceState(outState);
outState.putInt(EXTRA_DISABLE_STATE, mDisabledFlags1);
outState.putInt(EXTRA_DISABLE2_STATE, mDisabledFlags2);
- outState.putInt(EXTRA_SYSTEM_UI_VISIBILITY, mSystemUiVisibility);
+ outState.putInt(EXTRA_APPEARANCE, mAppearance);
+ outState.putBoolean(EXTRA_TRANSIENT_STATE, mTransientShown);
if (mNavigationBarView != null) {
mNavigationBarView.getLightTransitionsController().saveState(outState);
}
@@ -501,77 +529,107 @@ public class NavigationBarFragment extends LifecycleFragment implements Callback
rotationButtonController.onRotationProposal(rotation, winRotation, isValid);
}
- /** Restores the System UI flags saved state to {@link NavigationBarFragment}. */
- public void restoreSystemUiVisibilityState() {
- final int barMode = computeBarMode(0, mSystemUiVisibility);
- if (barMode != -1) {
- mNavigationBarMode = barMode;
- }
+ /** Restores the appearance and the transient saved state to {@link NavigationBarFragment}. */
+ public void restoreAppearanceAndTransientState() {
+ final int barMode = barMode(mTransientShown, mAppearance);
+ mNavigationBarMode = barMode;
checkNavBarModes();
mAutoHideController.touchAutoHide();
- mLightBarController.onNavigationVisibilityChanged(mSystemUiVisibility, 0 /* mask */,
- true /* nbModeChanged */, mNavigationBarMode, false /* navbarColorManagedByIme */);
+ mLightBarController.onNavigationBarAppearanceChanged(mAppearance, true /* nbModeChanged */,
+ barMode, false /* navbarColorManagedByIme */);
}
@Override
- public void setSystemUiVisibility(int displayId, int vis, int fullscreenStackVis,
- int dockedStackVis, int mask, Rect fullscreenStackBounds, Rect dockedStackBounds,
- boolean navbarColorManagedByIme) {
+ public void onSystemBarAppearanceChanged(int displayId, @Appearance int appearance,
+ AppearanceRegion[] appearanceRegions, boolean navbarColorManagedByIme) {
if (displayId != mDisplayId) {
return;
}
- final int oldVal = mSystemUiVisibility;
- final int newVal = (oldVal & ~mask) | (vis & mask);
- final int diff = newVal ^ oldVal;
boolean nbModeChanged = false;
- if (diff != 0) {
- mSystemUiVisibility = newVal;
-
- // update navigation bar mode
- final int nbMode = getView() == null
- ? -1 : computeBarMode(oldVal, newVal);
- nbModeChanged = nbMode != -1;
- if (nbModeChanged) {
- if (mNavigationBarMode != nbMode) {
- if (mNavigationBarMode == MODE_TRANSPARENT
- || mNavigationBarMode == MODE_LIGHTS_OUT_TRANSPARENT) {
- mNavigationBarView.hideRecentsOnboarding();
- }
- mNavigationBarMode = nbMode;
- checkNavBarModes();
- }
- mAutoHideController.touchAutoHide();
+ if (mAppearance != appearance) {
+ mAppearance = appearance;
+ if (getView() == null) {
+ return;
}
+ nbModeChanged = updateBarMode(barMode(mTransientShown, appearance));
+ }
+ mLightBarController.onNavigationBarAppearanceChanged(appearance, nbModeChanged,
+ mNavigationBarMode, navbarColorManagedByIme);
+ }
+
+ @Override
+ public void showTransient(int displayId, @InternalInsetType int[] types) {
+ if (displayId != mDisplayId) {
+ return;
+ }
+ if (!containsType(types, TYPE_NAVIGATION_BAR)) {
+ return;
+ }
+ if (!mTransientShown) {
+ mTransientShown = true;
+ handleTransientChanged();
+ }
+ }
+
+ @Override
+ public void abortTransient(int displayId, @InternalInsetType int[] types) {
+ if (displayId != mDisplayId) {
+ return;
}
- mLightBarController.onNavigationVisibilityChanged(
- vis, mask, nbModeChanged, mNavigationBarMode, navbarColorManagedByIme);
+ if (!containsType(types, TYPE_NAVIGATION_BAR)) {
+ return;
+ }
+ clearTransient();
}
- private @TransitionMode int computeBarMode(int oldVis, int newVis) {
- final int oldMode = barMode(oldVis);
- final int newMode = barMode(newVis);
- if (oldMode == newMode) {
- return -1; // no mode change
+ void clearTransient() {
+ if (mTransientShown) {
+ mTransientShown = false;
+ handleTransientChanged();
+ }
+ }
+
+ private void handleTransientChanged() {
+ if (getView() == null) {
+ return;
+ }
+ if (mNavigationBarView != null) {
+ mNavigationBarView.onTransientStateChanged(mTransientShown);
+ }
+ final int barMode = barMode(mTransientShown, mAppearance);
+ if (updateBarMode(barMode)) {
+ mLightBarController.onNavigationBarModeChanged(barMode);
+ }
+ }
+
+ // Returns true if the bar mode is changed.
+ private boolean updateBarMode(int barMode) {
+ if (mNavigationBarMode != barMode) {
+ if (mNavigationBarMode == MODE_TRANSPARENT
+ || mNavigationBarMode == MODE_LIGHTS_OUT_TRANSPARENT) {
+ mNavigationBarView.hideRecentsOnboarding();
+ }
+ mNavigationBarMode = barMode;
+ checkNavBarModes();
+ mAutoHideController.touchAutoHide();
+ return true;
}
- return newMode;
+ return false;
}
- private @TransitionMode int barMode(int vis) {
- final int lightsOutTransparent =
- View.SYSTEM_UI_FLAG_LOW_PROFILE | View.NAVIGATION_BAR_TRANSIENT;
- if ((vis & View.NAVIGATION_BAR_TRANSIENT) != 0) {
+ private static @TransitionMode int barMode(boolean isTransient, int appearance) {
+ final int lightsOutOpaque = APPEARANCE_LOW_PROFILE_BARS | APPEARANCE_OPAQUE_SIDE_BARS;
+ if (isTransient) {
return MODE_SEMI_TRANSPARENT;
- } else if ((vis & View.NAVIGATION_BAR_TRANSLUCENT) != 0) {
- return MODE_TRANSLUCENT;
- } else if ((vis & lightsOutTransparent) == lightsOutTransparent) {
- return MODE_LIGHTS_OUT_TRANSPARENT;
- } else if ((vis & View.NAVIGATION_BAR_TRANSPARENT) != 0) {
- return MODE_TRANSPARENT;
- } else if ((vis & View.SYSTEM_UI_FLAG_LOW_PROFILE) != 0) {
+ } else if ((appearance & lightsOutOpaque) == lightsOutOpaque) {
return MODE_LIGHTS_OUT;
- } else {
+ } else if ((appearance & APPEARANCE_LOW_PROFILE_BARS) != 0) {
+ return MODE_LIGHTS_OUT_TRANSPARENT;
+ } else if ((appearance & APPEARANCE_OPAQUE_SIDE_BARS) != 0) {
return MODE_OPAQUE;
+ } else {
+ return MODE_TRANSPARENT;
}
}
@@ -970,8 +1028,8 @@ public class NavigationBarFragment extends LifecycleFragment implements Callback
mAutoHideController.setNavigationBar(this);
}
- public boolean isSemiTransparent() {
- return mNavigationBarMode == MODE_SEMI_TRANSPARENT;
+ boolean isTransientShown() {
+ return mTransientShown;
}
private void checkBarModes() {
@@ -1019,6 +1077,11 @@ public class NavigationBarFragment extends LifecycleFragment implements Callback
delay + StackStateAnimator.ANIMATION_DURATION_GO_TO_FULL_SHADE);
}
+ @Nullable
+ public AssistHandleViewController getAssistHandlerViewController() {
+ return mAssistHandlerViewController;
+ }
+
/**
* Performs transitions on navigation bar.
*
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
index fa4812dc4876..4b4a35bae05d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -67,6 +67,7 @@ import com.android.systemui.DockedStackExistsListener;
import com.android.systemui.Interpolators;
import com.android.systemui.R;
import com.android.systemui.SysUiServiceProvider;
+import com.android.systemui.assist.AssistHandleViewController;
import com.android.systemui.assist.AssistManager;
import com.android.systemui.model.SysUiState;
import com.android.systemui.recents.OverviewProxyService;
@@ -75,6 +76,7 @@ import com.android.systemui.recents.RecentsOnboarding;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.QuickStepContract;
import com.android.systemui.shared.system.WindowManagerWrapper;
+import com.android.systemui.statusbar.NavigationBarController;
import com.android.systemui.statusbar.policy.DeadZone;
import com.android.systemui.statusbar.policy.KeyButtonDrawable;
@@ -364,6 +366,10 @@ public class NavigationBarView extends FrameLayout implements
return super.onTouchEvent(event);
}
+ void onTransientStateChanged(boolean isTransient) {
+ mEdgeBackGestureHandler.onNavBarTransientStateChanged(isTransient);
+ }
+
void onBarTransition(int newMode) {
if (newMode == MODE_OPAQUE) {
// If the nav bar background is opaque, stop auto tinting since we know the icons are
@@ -829,7 +835,11 @@ public class NavigationBarView extends FrameLayout implements
mRecentsOnboarding.onNavigationModeChanged(mNavBarMode);
getRotateSuggestionButton().onNavigationModeChanged(mNavBarMode);
- mRegionSamplingHelper.start(mSamplingBounds);
+ if (isGesturalMode(mNavBarMode)) {
+ mRegionSamplingHelper.start(mSamplingBounds);
+ } else {
+ mRegionSamplingHelper.stop();
+ }
}
public void setAccessibilityButtonState(final boolean visible, final boolean longClickable) {
@@ -1194,6 +1204,22 @@ public class NavigationBarView extends FrameLayout implements
// we're passing the insets onto the gesture handler since the back arrow is only
// conditionally added and doesn't always get all the insets.
mEdgeBackGestureHandler.setInsets(leftInset, rightInset);
+
+ // this allows assist handle to be drawn outside its bound so that it can align screen
+ // bottom by translating its y position.
+ final boolean shouldClip =
+ !isGesturalMode(mNavBarMode) || insets.getSystemWindowInsetBottom() == 0;
+ setClipChildren(shouldClip);
+ setClipToPadding(shouldClip);
+
+ NavigationBarController navigationBarController =
+ Dependency.get(NavigationBarController.class);
+ AssistHandleViewController controller =
+ navigationBarController == null
+ ? null : navigationBarController.getAssistHandlerViewController();
+ if (controller != null) {
+ controller.setBottomOffset(insets.getSystemWindowInsetBottom());
+ }
return super.onApplyWindowInsets(insets);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupAlertTransferHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupAlertTransferHelper.java
index 4d69f77e744d..2798285c073d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupAlertTransferHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupAlertTransferHelper.java
@@ -105,7 +105,7 @@ public class NotificationGroupAlertTransferHelper implements OnHeadsUpChangedLis
* @return true if the entry was transferred to and should inflate + alert
*/
public boolean isAlertTransferPending(@NonNull NotificationEntry entry) {
- PendingAlertInfo alertInfo = mPendingAlerts.get(entry.key);
+ PendingAlertInfo alertInfo = mPendingAlerts.get(entry.getKey());
return alertInfo != null && alertInfo.isStillValid();
}
@@ -141,7 +141,7 @@ public class NotificationGroupAlertTransferHelper implements OnHeadsUpChangedLis
@Override
public void onGroupSuppressionChanged(NotificationGroup group, boolean suppressed) {
if (suppressed) {
- if (mHeadsUpManager.isAlerting(group.summary.key)) {
+ if (mHeadsUpManager.isAlerting(group.summary.getKey())) {
handleSuppressedSummaryAlerted(group.summary, mHeadsUpManager);
}
} else {
@@ -151,11 +151,11 @@ public class NotificationGroupAlertTransferHelper implements OnHeadsUpChangedLis
return;
}
GroupAlertEntry groupAlertEntry = mGroupAlertEntries.get(mGroupManager.getGroupKey(
- group.summary.notification));
+ group.summary.getSbn()));
// Group is no longer suppressed. We should check if we need to transfer the alert
// back to the summary now that it's no longer suppressed.
if (groupAlertEntry.mAlertSummaryOnNextAddition) {
- if (!mHeadsUpManager.isAlerting(group.summary.key)) {
+ if (!mHeadsUpManager.isAlerting(group.summary.getKey())) {
alertNotificationWhenPossible(group.summary, mHeadsUpManager);
}
groupAlertEntry.mAlertSummaryOnNextAddition = false;
@@ -173,7 +173,7 @@ public class NotificationGroupAlertTransferHelper implements OnHeadsUpChangedLis
private void onAlertStateChanged(NotificationEntry entry, boolean isAlerting,
AlertingNotificationManager alertManager) {
- if (isAlerting && mGroupManager.isSummaryOfSuppressedGroup(entry.notification)) {
+ if (isAlerting && mGroupManager.isSummaryOfSuppressedGroup(entry.getSbn())) {
handleSuppressedSummaryAlerted(entry, alertManager);
}
}
@@ -184,7 +184,7 @@ public class NotificationGroupAlertTransferHelper implements OnHeadsUpChangedLis
// see as early as we can if we need to abort a transfer.
@Override
public void onPendingEntryAdded(NotificationEntry entry) {
- String groupKey = mGroupManager.getGroupKey(entry.notification);
+ String groupKey = mGroupManager.getGroupKey(entry.getSbn());
GroupAlertEntry groupAlertEntry = mGroupAlertEntries.get(groupKey);
if (groupAlertEntry != null) {
checkShouldTransferBack(groupAlertEntry);
@@ -195,7 +195,7 @@ public class NotificationGroupAlertTransferHelper implements OnHeadsUpChangedLis
// then show the alert.
@Override
public void onEntryReinflated(NotificationEntry entry) {
- PendingAlertInfo alertInfo = mPendingAlerts.remove(entry.key);
+ PendingAlertInfo alertInfo = mPendingAlerts.remove(entry.getKey());
if (alertInfo != null) {
if (alertInfo.isStillValid()) {
alertNotificationWhenPossible(entry, mHeadsUpManager);
@@ -214,7 +214,7 @@ public class NotificationGroupAlertTransferHelper implements OnHeadsUpChangedLis
// Removes any alerts pending on this entry. Note that this will not stop any inflation
// tasks started by a transfer, so this should only be used as clean-up for when
// inflation is stopped and the pending alert no longer needs to happen.
- mPendingAlerts.remove(entry.key);
+ mPendingAlerts.remove(entry.getKey());
}
};
@@ -267,10 +267,10 @@ public class NotificationGroupAlertTransferHelper implements OnHeadsUpChangedLis
*/
private boolean isPendingNotificationInGroup(@NonNull NotificationEntry entry,
@NonNull NotificationGroup group) {
- String groupKey = mGroupManager.getGroupKey(group.summary.notification);
- return mGroupManager.isGroupChild(entry.notification)
- && Objects.equals(mGroupManager.getGroupKey(entry.notification), groupKey)
- && !group.children.containsKey(entry.key);
+ String groupKey = mGroupManager.getGroupKey(group.summary.getSbn());
+ return mGroupManager.isGroupChild(entry.getSbn())
+ && Objects.equals(mGroupManager.getGroupKey(entry.getSbn()), groupKey)
+ && !group.children.containsKey(entry.getKey());
}
/**
@@ -284,10 +284,10 @@ public class NotificationGroupAlertTransferHelper implements OnHeadsUpChangedLis
*/
private void handleSuppressedSummaryAlerted(@NonNull NotificationEntry summary,
@NonNull AlertingNotificationManager alertManager) {
- StatusBarNotification sbn = summary.notification;
+ StatusBarNotification sbn = summary.getSbn();
GroupAlertEntry groupAlertEntry =
mGroupAlertEntries.get(mGroupManager.getGroupKey(sbn));
- if (!mGroupManager.isSummaryOfSuppressedGroup(summary.notification)
+ if (!mGroupManager.isSummaryOfSuppressedGroup(summary.getSbn())
|| !alertManager.isAlerting(sbn.getKey())
|| groupAlertEntry == null) {
return;
@@ -298,7 +298,8 @@ public class NotificationGroupAlertTransferHelper implements OnHeadsUpChangedLis
return;
}
- NotificationEntry child = mGroupManager.getLogicalChildren(summary.notification).iterator().next();
+ NotificationEntry child =
+ mGroupManager.getLogicalChildren(summary.getSbn()).iterator().next();
if (child != null) {
if (child.getRow().keepInParent()
|| child.isRowRemoved()
@@ -306,7 +307,7 @@ public class NotificationGroupAlertTransferHelper implements OnHeadsUpChangedLis
// The notification is actually already removed. No need to alert it.
return;
}
- if (!alertManager.isAlerting(child.key) && onlySummaryAlerts(summary)) {
+ if (!alertManager.isAlerting(child.getKey()) && onlySummaryAlerts(summary)) {
groupAlertEntry.mLastAlertTransferTime = SystemClock.elapsedRealtime();
}
transferAlertState(summary, child, alertManager);
@@ -324,7 +325,7 @@ public class NotificationGroupAlertTransferHelper implements OnHeadsUpChangedLis
*/
private void transferAlertState(@NonNull NotificationEntry fromEntry, @NonNull NotificationEntry toEntry,
@NonNull AlertingNotificationManager alertManager) {
- alertManager.removeNotification(fromEntry.key, true /* releaseImmediately */);
+ alertManager.removeNotification(fromEntry.getKey(), true /* releaseImmediately */);
alertNotificationWhenPossible(toEntry, alertManager);
}
@@ -347,7 +348,8 @@ public class NotificationGroupAlertTransferHelper implements OnHeadsUpChangedLis
if (!onlySummaryAlerts(summary)) {
return;
}
- ArrayList<NotificationEntry> children = mGroupManager.getLogicalChildren(summary.notification);
+ ArrayList<NotificationEntry> children = mGroupManager.getLogicalChildren(
+ summary.getSbn());
int numChildren = children.size();
int numPendingChildren = getPendingChildrenNotAlerting(groupAlertEntry.mGroup);
numChildren += numPendingChildren;
@@ -357,17 +359,18 @@ public class NotificationGroupAlertTransferHelper implements OnHeadsUpChangedLis
boolean releasedChild = false;
for (int i = 0; i < children.size(); i++) {
NotificationEntry entry = children.get(i);
- if (onlySummaryAlerts(entry) && mHeadsUpManager.isAlerting(entry.key)) {
+ if (onlySummaryAlerts(entry) && mHeadsUpManager.isAlerting(entry.getKey())) {
releasedChild = true;
- mHeadsUpManager.removeNotification(entry.key, true /* releaseImmediately */);
+ mHeadsUpManager.removeNotification(
+ entry.getKey(), true /* releaseImmediately */);
}
- if (mPendingAlerts.containsKey(entry.key)) {
+ if (mPendingAlerts.containsKey(entry.getKey())) {
// This is the child that would've been removed if it was inflated.
releasedChild = true;
- mPendingAlerts.get(entry.key).mAbortOnInflation = true;
+ mPendingAlerts.get(entry.getKey()).mAbortOnInflation = true;
}
}
- if (releasedChild && !mHeadsUpManager.isAlerting(summary.key)) {
+ if (releasedChild && !mHeadsUpManager.isAlerting(summary.getKey())) {
boolean notifyImmediately = (numChildren - numPendingChildren) > 1;
if (notifyImmediately) {
alertNotificationWhenPossible(summary, mHeadsUpManager);
@@ -391,20 +394,20 @@ public class NotificationGroupAlertTransferHelper implements OnHeadsUpChangedLis
@NonNull AlertingNotificationManager alertManager) {
@InflationFlag int contentFlag = alertManager.getContentFlag();
if (!entry.getRow().isInflationFlagSet(contentFlag)) {
- mPendingAlerts.put(entry.key, new PendingAlertInfo(entry));
+ mPendingAlerts.put(entry.getKey(), new PendingAlertInfo(entry));
entry.getRow().updateInflationFlag(contentFlag, true /* shouldInflate */);
entry.getRow().inflateViews();
return;
}
- if (alertManager.isAlerting(entry.key)) {
- alertManager.updateNotification(entry.key, true /* alert */);
+ if (alertManager.isAlerting(entry.getKey())) {
+ alertManager.updateNotification(entry.getKey(), true /* alert */);
} else {
alertManager.showNotification(entry);
}
}
private boolean onlySummaryAlerts(NotificationEntry entry) {
- return entry.notification.getNotification().getGroupAlertBehavior()
+ return entry.getSbn().getNotification().getGroupAlertBehavior()
== Notification.GROUP_ALERT_SUMMARY;
}
@@ -431,7 +434,7 @@ public class NotificationGroupAlertTransferHelper implements OnHeadsUpChangedLis
boolean mAbortOnInflation;
PendingAlertInfo(NotificationEntry entry) {
- mOriginalNotification = entry.notification;
+ mOriginalNotification = entry.getSbn();
mEntry = entry;
}
@@ -445,11 +448,11 @@ public class NotificationGroupAlertTransferHelper implements OnHeadsUpChangedLis
// Notification is aborted due to the transfer being explicitly cancelled
return false;
}
- if (mEntry.notification.getGroupKey() != mOriginalNotification.getGroupKey()) {
+ if (mEntry.getSbn().getGroupKey() != mOriginalNotification.getGroupKey()) {
// Groups have changed
return false;
}
- if (mEntry.notification.getNotification().isGroupSummary()
+ if (mEntry.getSbn().getNotification().isGroupSummary()
!= mOriginalNotification.getNotification().isGroupSummary()) {
// Notification has changed from group summary to not or vice versa
return false;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java
index adaea9379c71..e11fc1b46a5b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java
@@ -103,8 +103,8 @@ public class NotificationGroupManager implements OnHeadsUpChangedListener, State
}
public void onEntryRemoved(NotificationEntry removed) {
- onEntryRemovedInternal(removed, removed.notification);
- mIsolatedEntries.remove(removed.key);
+ onEntryRemovedInternal(removed, removed.getSbn());
+ mIsolatedEntries.remove(removed.getKey());
}
/**
@@ -126,7 +126,7 @@ public class NotificationGroupManager implements OnHeadsUpChangedListener, State
return;
}
if (isGroupChild(sbn)) {
- group.children.remove(removed.key);
+ group.children.remove(removed.getKey());
} else {
group.summary = null;
}
@@ -145,7 +145,7 @@ public class NotificationGroupManager implements OnHeadsUpChangedListener, State
if (added.isRowRemoved()) {
added.setDebugThrowable(new Throwable());
}
- final StatusBarNotification sbn = added.notification;
+ final StatusBarNotification sbn = added.getSbn();
boolean isGroupChild = isGroupChild(sbn);
String groupKey = getGroupKey(sbn);
NotificationGroup group = mGroupMap.get(groupKey);
@@ -157,17 +157,17 @@ public class NotificationGroupManager implements OnHeadsUpChangedListener, State
}
}
if (isGroupChild) {
- NotificationEntry existing = group.children.get(added.key);
+ NotificationEntry existing = group.children.get(added.getKey());
if (existing != null && existing != added) {
Throwable existingThrowable = existing.getDebugThrowable();
- Log.wtf(TAG, "Inconsistent entries found with the same key " + added.key
+ Log.wtf(TAG, "Inconsistent entries found with the same key " + added.getKey()
+ "existing removed: " + existing.isRowRemoved()
+ (existingThrowable != null
? Log.getStackTraceString(existingThrowable) + "\n": "")
+ " added removed" + added.isRowRemoved()
, new Throwable());
}
- group.children.put(added.key, added);
+ group.children.put(added.getKey(), added);
updateSuppression(group);
} else {
group.summary = added;
@@ -210,7 +210,7 @@ public class NotificationGroupManager implements OnHeadsUpChangedListener, State
group.suppressed = group.summary != null && !group.expanded
&& (childCount == 1
|| (childCount == 0
- && group.summary.notification.getNotification().isGroupSummary()
+ && group.summary.getSbn().getNotification().isGroupSummary()
&& (hasIsolatedChildren(group) || hasBubbles)));
if (prevSuppressed != group.suppressed) {
for (OnGroupChangeListener listener : mListeners) {
@@ -223,7 +223,7 @@ public class NotificationGroupManager implements OnHeadsUpChangedListener, State
}
private boolean hasIsolatedChildren(NotificationGroup group) {
- return getNumberOfIsolatedChildren(group.summary.notification.getGroupKey()) != 0;
+ return getNumberOfIsolatedChildren(group.summary.getSbn().getGroupKey()) != 0;
}
private int getNumberOfIsolatedChildren(String groupKey) {
@@ -248,18 +248,18 @@ public class NotificationGroupManager implements OnHeadsUpChangedListener, State
public void onEntryUpdated(NotificationEntry entry,
StatusBarNotification oldNotification) {
String oldKey = oldNotification.getGroupKey();
- String newKey = entry.notification.getGroupKey();
+ String newKey = entry.getSbn().getGroupKey();
boolean groupKeysChanged = !oldKey.equals(newKey);
boolean wasGroupChild = isGroupChild(oldNotification);
- boolean isGroupChild = isGroupChild(entry.notification);
+ boolean isGroupChild = isGroupChild(entry.getSbn());
mIsUpdatingUnchangedGroup = !groupKeysChanged && wasGroupChild == isGroupChild;
if (mGroupMap.get(getGroupKey(oldNotification)) != null) {
onEntryRemovedInternal(entry, oldNotification);
}
onEntryAdded(entry);
mIsUpdatingUnchangedGroup = false;
- if (isIsolated(entry.notification)) {
- mIsolatedEntries.put(entry.key, entry.notification);
+ if (isIsolated(entry.getSbn())) {
+ mIsolatedEntries.put(entry.getKey(), entry.getSbn());
if (groupKeysChanged) {
updateSuppression(mGroupMap.get(oldKey));
updateSuppression(mGroupMap.get(newKey));
@@ -284,7 +284,7 @@ public class NotificationGroupManager implements OnHeadsUpChangedListener, State
}
NotificationEntry logicalGroupSummary = getLogicalGroupSummary(sbn);
return logicalGroupSummary != null
- && !logicalGroupSummary.notification.equals(sbn);
+ && !logicalGroupSummary.getSbn().equals(sbn);
}
private int getTotalNumberOfChildren(StatusBarNotification sbn) {
@@ -351,7 +351,7 @@ public class NotificationGroupManager implements OnHeadsUpChangedListener, State
if (group == null || group.summary == null) {
return false;
}
- return !group.children.isEmpty() && Objects.equals(group.summary.notification, sbn);
+ return !group.children.isEmpty() && Objects.equals(group.summary.getSbn(), sbn);
}
/**
@@ -404,7 +404,7 @@ public class NotificationGroupManager implements OnHeadsUpChangedListener, State
* will update the suppression of that group.
*/
public void updateSuppression(NotificationEntry entry) {
- NotificationGroup group = mGroupMap.get(getGroupKey(entry.notification));
+ NotificationGroup group = mGroupMap.get(getGroupKey(entry.getSbn()));
if (group != null) {
updateSuppression(group);
}
@@ -489,12 +489,12 @@ public class NotificationGroupManager implements OnHeadsUpChangedListener, State
*/
private boolean shouldIsolate(NotificationEntry entry) {
- StatusBarNotification sbn = entry.notification;
+ StatusBarNotification sbn = entry.getSbn();
NotificationGroup notificationGroup = mGroupMap.get(sbn.getGroupKey());
if (!sbn.isGroup() || sbn.getNotification().isGroupSummary()) {
return false;
}
- if (mHeadsUpManager != null && !mHeadsUpManager.isAlerting(entry.key)) {
+ if (mHeadsUpManager != null && !mHeadsUpManager.isAlerting(entry.getKey())) {
return false;
}
return (sbn.getNotification().fullScreenIntent != null
@@ -509,10 +509,10 @@ public class NotificationGroupManager implements OnHeadsUpChangedListener, State
* @param entry the notification to isolate
*/
private void isolateNotification(NotificationEntry entry) {
- StatusBarNotification sbn = entry.notification;
+ StatusBarNotification sbn = entry.getSbn();
// We will be isolated now, so lets update the groups
- onEntryRemovedInternal(entry, entry.notification);
+ onEntryRemovedInternal(entry, entry.getSbn());
mIsolatedEntries.put(sbn.getKey(), sbn);
@@ -521,7 +521,7 @@ public class NotificationGroupManager implements OnHeadsUpChangedListener, State
// even before the groupManager knows about the notification at all.
// When the notification gets added afterwards it is already isolated and therefore
// it doesn't lead to an update.
- updateSuppression(mGroupMap.get(entry.notification.getGroupKey()));
+ updateSuppression(mGroupMap.get(entry.getSbn().getGroupKey()));
for (OnGroupChangeListener listener : mListeners) {
listener.onGroupsChanged();
}
@@ -533,10 +533,10 @@ public class NotificationGroupManager implements OnHeadsUpChangedListener, State
* @param entry the notification to un-isolate
*/
private void stopIsolatingNotification(NotificationEntry entry) {
- StatusBarNotification sbn = entry.notification;
+ StatusBarNotification sbn = entry.getSbn();
if (mIsolatedEntries.containsKey(sbn.getKey())) {
// not isolated anymore, we need to update the groups
- onEntryRemovedInternal(entry, entry.notification);
+ onEntryRemovedInternal(entry, entry.getSbn());
mIsolatedEntries.remove(sbn.getKey());
onEntryAdded(entry);
for (OnGroupChangeListener listener : mListeners) {
@@ -584,13 +584,13 @@ public class NotificationGroupManager implements OnHeadsUpChangedListener, State
@Override
public String toString() {
String result = " summary:\n "
- + (summary != null ? summary.notification : "null")
+ + (summary != null ? summary.getSbn() : "null")
+ (summary != null && summary.getDebugThrowable() != null
? Log.getStackTraceString(summary.getDebugThrowable())
: "");
result += "\n children size: " + children.size();
for (NotificationEntry child : children.values()) {
- result += "\n " + child.notification
+ result += "\n " + child.getSbn()
+ (child.getDebugThrowable() != null
? Log.getStackTraceString(child.getDebugThrowable())
: "");
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
index 1a3560ece1d7..1e10b6f025f2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
@@ -80,11 +80,14 @@ public class NotificationIconAreaController implements DarkReceiver,
private boolean mAodIconsVisible;
private boolean mIsPulsing;
- public NotificationIconAreaController(Context context, StatusBar statusBar,
+ public NotificationIconAreaController(
+ Context context,
+ StatusBar statusBar,
StatusBarStateController statusBarStateController,
NotificationWakeUpCoordinator wakeUpCoordinator,
KeyguardBypassController keyguardBypassController,
- NotificationMediaManager notificationMediaManager) {
+ NotificationMediaManager notificationMediaManager,
+ DozeParameters dozeParameters) {
mStatusBar = statusBar;
mContrastColorUtil = ContrastColorUtil.getInstance(context);
mContext = context;
@@ -92,7 +95,7 @@ public class NotificationIconAreaController implements DarkReceiver,
mStatusBarStateController = statusBarStateController;
mStatusBarStateController.addCallback(this);
mMediaManager = notificationMediaManager;
- mDozeParameters = DozeParameters.getInstance(mContext);
+ mDozeParameters = dozeParameters;
mWakeUpCoordinator = wakeUpCoordinator;
wakeUpCoordinator.addListener(this);
mBypassController = keyguardBypassController;
@@ -244,10 +247,10 @@ public class NotificationIconAreaController implements DarkReceiver,
if (hideCenteredIcon && isCenteredNotificationIcon && !entry.isRowHeadsUp()) {
return false;
}
- if (mEntryManager.getNotificationData().isAmbient(entry.key) && !showAmbient) {
+ if (mEntryManager.getNotificationData().isAmbient(entry.getKey()) && !showAmbient) {
return false;
}
- if (hideCurrentMedia && entry.key.equals(mMediaManager.getMediaNotificationKey())) {
+ if (hideCurrentMedia && entry.getKey().equals(mMediaManager.getMediaNotificationKey())) {
return false;
}
if (!entry.isTopLevelChild()) {
@@ -533,8 +536,7 @@ public class NotificationIconAreaController implements DarkReceiver,
}
public void appearAodIcons() {
- DozeParameters dozeParameters = DozeParameters.getInstance(mContext);
- if (dozeParameters.shouldControlScreenOff()) {
+ if (mDozeParameters.shouldControlScreenOff()) {
mAodIcons.setTranslationY(-mAodIconAppearTranslation);
mAodIcons.setAlpha(0);
animateInAodIconTranslation();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index ea113dffa658..30fe68a28ef2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -43,6 +43,7 @@ import android.hardware.biometrics.BiometricSourceType;
import android.os.PowerManager;
import android.os.SystemClock;
import android.provider.DeviceConfig;
+import android.provider.Settings;
import android.util.AttributeSet;
import android.util.Log;
import android.util.MathUtils;
@@ -68,6 +69,7 @@ import com.android.systemui.DejankUtils;
import com.android.systemui.Dependency;
import com.android.systemui.Interpolators;
import com.android.systemui.R;
+import com.android.systemui.doze.DozeLog;
import com.android.systemui.fragments.FragmentHostManager;
import com.android.systemui.fragments.FragmentHostManager.FragmentListener;
import com.android.systemui.plugins.FalsingManager;
@@ -88,6 +90,7 @@ import com.android.systemui.statusbar.NotificationShelf;
import com.android.systemui.statusbar.PulseExpansionHandler;
import com.android.systemui.statusbar.RemoteInputController;
import com.android.systemui.statusbar.StatusBarState;
+import com.android.systemui.statusbar.SysuiStatusBarStateController;
import com.android.systemui.statusbar.notification.ActivityLaunchAnimator;
import com.android.systemui.statusbar.notification.AnimatableProperty;
import com.android.systemui.statusbar.notification.DynamicPrivacyController;
@@ -102,7 +105,7 @@ import com.android.systemui.statusbar.notification.stack.AnimationProperties;
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
import com.android.systemui.statusbar.notification.stack.StackStateAnimator;
import com.android.systemui.statusbar.policy.ConfigurationController;
-import com.android.systemui.statusbar.policy.KeyguardMonitor;
+import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.statusbar.policy.KeyguardUserSwitcher;
import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener;
import com.android.systemui.statusbar.policy.ZenModeController;
@@ -143,6 +146,7 @@ public class NotificationPanelView extends PanelView implements
* Fling until QS is completely hidden.
*/
public static final int FLING_HIDE = 2;
+ private final DozeParameters mDozeParameters;
private double mQqsSplitFraction;
@@ -205,11 +209,11 @@ public class NotificationPanelView extends PanelView implements
mDelayShowingKeyguardStatusBar = false;
}
};
- private final KeyguardMonitor.Callback mKeyguardMonitorCallback =
- new KeyguardMonitor.Callback() {
+ private final KeyguardStateController.Callback mKeyguardMonitorCallback =
+ new KeyguardStateController.Callback() {
@Override
public void onKeyguardFadingAwayChanged() {
- if (!mKeyguardMonitor.isKeyguardFadingAway()) {
+ if (!mKeyguardStateController.isKeyguardFadingAway()) {
mFirstBypassAttempt = false;
mDelayShowingKeyguardStatusBar = false;
}
@@ -407,14 +411,11 @@ public class NotificationPanelView extends PanelView implements
.setDuration(200)
.setAnimationFinishListener(mAnimatorListenerAdapter)
.setCustomInterpolator(PANEL_ALPHA.getProperty(), Interpolators.ALPHA_IN);
- private final NotificationEntryManager mEntryManager =
- Dependency.get(NotificationEntryManager.class);
+ private final NotificationEntryManager mEntryManager;
private final CommandQueue mCommandQueue;
- private final NotificationLockscreenUserManager mLockscreenUserManager =
- Dependency.get(NotificationLockscreenUserManager.class);
- private final ShadeController mShadeController =
- Dependency.get(ShadeController.class);
+ private final NotificationLockscreenUserManager mLockscreenUserManager;
+ private final ShadeController mShadeController;
private int mDisplayId;
/**
@@ -454,13 +455,17 @@ public class NotificationPanelView extends PanelView implements
@Inject
public NotificationPanelView(@Named(VIEW_CONTEXT) Context context, AttributeSet attrs,
InjectionInflationController injectionInflationController,
- NotificationWakeUpCoordinator coordinator,
- PulseExpansionHandler pulseExpansionHandler,
+ NotificationWakeUpCoordinator coordinator, PulseExpansionHandler pulseExpansionHandler,
DynamicPrivacyController dynamicPrivacyController,
- KeyguardBypassController bypassController,
- FalsingManager falsingManager,
- PluginManager pluginManager) {
- super(context, attrs);
+ KeyguardBypassController bypassController, FalsingManager falsingManager,
+ PluginManager pluginManager, ShadeController shadeController,
+ NotificationLockscreenUserManager notificationLockscreenUserManager,
+ NotificationEntryManager notificationEntryManager,
+ KeyguardStateController keyguardStateController,
+ StatusBarStateController statusBarStateController, DozeLog dozeLog,
+ DozeParameters dozeParameters) {
+ super(context, attrs, falsingManager, dozeLog, keyguardStateController,
+ (SysuiStatusBarStateController) statusBarStateController);
setWillNotDraw(!DEBUG);
mInjectionInflationController = injectionInflationController;
mFalsingManager = falsingManager;
@@ -473,6 +478,7 @@ public class NotificationPanelView extends PanelView implements
mCommandQueue = getComponent(context, CommandQueue.class);
mDisplayId = context.getDisplayId();
mPulseExpansionHandler = pulseExpansionHandler;
+ mDozeParameters = dozeParameters;
pulseExpansionHandler.setPulseExpandAbortListener(() -> {
if (mQs != null) {
mQs.animateHeaderSlidingOut();
@@ -482,7 +488,7 @@ public class NotificationPanelView extends PanelView implements
mKeyguardBypassController = bypassController;
mUpdateMonitor = Dependency.get(KeyguardUpdateMonitor.class);
mFirstBypassAttempt = mKeyguardBypassController.getBypassEnabled();
- mKeyguardMonitor.addCallback(mKeyguardMonitorCallback);
+ mKeyguardStateController.addCallback(mKeyguardMonitorCallback);
dynamicPrivacyController.addListener(this);
mBottomAreaShadeAlphaAnimator = ValueAnimator.ofFloat(1f, 0);
@@ -493,6 +499,11 @@ public class NotificationPanelView extends PanelView implements
mBottomAreaShadeAlphaAnimator.setDuration(160);
mBottomAreaShadeAlphaAnimator.setInterpolator(Interpolators.ALPHA_OUT);
mPluginManager = pluginManager;
+ mShadeController = shadeController;
+ mLockscreenUserManager = notificationLockscreenUserManager;
+ mEntryManager = notificationEntryManager;
+
+ setBackgroundColor(Color.TRANSPARENT);
}
/**
@@ -507,9 +518,11 @@ public class NotificationPanelView extends PanelView implements
mKeyguardBottomArea.setStatusBar(mStatusBar);
}
- @Override
- protected void onFinishInflate() {
- super.onFinishInflate();
+ /**
+ * Call after this view has been fully inflated and had its children attached.
+ */
+ public void onChildrenAttached() {
+ loadDimens();
mKeyguardStatusBar = findViewById(R.id.keyguard_header);
mKeyguardStatusView = findViewById(R.id.keyguard_status_view);
@@ -528,7 +541,10 @@ public class NotificationPanelView extends PanelView implements
mQsNavbarScrim = findViewById(R.id.qs_navbar_scrim);
mLastOrientation = getResources().getConfiguration().orientation;
mPluginFrame = findViewById(R.id.plugin_frame);
- mNPVPluginManager = new NPVPluginManager(mPluginFrame, mPluginManager);
+ if (Settings.System.getInt(
+ mContext.getContentResolver(), "npv_plugin_flag", 0) == 1) {
+ mNPVPluginManager = new NPVPluginManager(mPluginFrame, mPluginManager);
+ }
initBottomArea();
@@ -552,7 +568,7 @@ public class NotificationPanelView extends PanelView implements
}
});
- Dependency.get(PluginManager.class).addPluginListener(
+ mPluginManager.addPluginListener(
new PluginListener<HomeControlsPlugin>() {
@Override
@@ -652,8 +668,7 @@ public class NotificationPanelView extends PanelView implements
mNotificationStackScroller.setLayoutParams(lp);
}
int sideMargin = res.getDimensionPixelOffset(R.dimen.notification_side_paddings);
- int topMargin =
- res.getDimensionPixelOffset(com.android.internal.R.dimen.quick_qs_total_height);
+ int topMargin = sideMargin;
lp = (FrameLayout.LayoutParams) mPluginFrame.getLayoutParams();
if (lp.width != qsWidth || lp.gravity != panelGravity || lp.leftMargin != sideMargin
|| lp.rightMargin != sideMargin || lp.topMargin != topMargin) {
@@ -755,6 +770,11 @@ public class NotificationPanelView extends PanelView implements
int sideMargin = res.getDimensionPixelOffset(R.dimen.notification_side_paddings);
int topMargin =
res.getDimensionPixelOffset(com.android.internal.R.dimen.quick_qs_total_height);
+ int flag = Settings.System.getInt(mContext.getContentResolver(), "qs_media_player", 0);
+ if (flag == 1) {
+ topMargin = res.getDimensionPixelOffset(
+ com.android.internal.R.dimen.quick_qs_total_height_with_media);
+ }
lp = (FrameLayout.LayoutParams) mPluginFrame.getLayoutParams();
if (lp.width != qsWidth || lp.gravity != panelGravity || lp.leftMargin != sideMargin
|| lp.rightMargin != sideMargin || lp.topMargin != topMargin) {
@@ -766,7 +786,7 @@ public class NotificationPanelView extends PanelView implements
mPluginFrame.setLayoutParams(lp);
}
- mNPVPluginManager.replaceFrameLayout(mPluginFrame);
+ if (mNPVPluginManager != null) mNPVPluginManager.replaceFrameLayout(mPluginFrame);
}
private void initBottomArea() {
@@ -796,7 +816,10 @@ public class NotificationPanelView extends PanelView implements
int oldMaxHeight = mQsMaxExpansionHeight;
if (mQs != null) {
mQsMinExpansionHeight = mKeyguardShowing ? 0 : mQs.getQsMinExpansionHeight();
- mQsMinExpansionHeight += mNPVPluginManager.getHeight();
+ if (mNPVPluginManager != null) {
+ mNPVPluginManager.setYOffset(mQsMinExpansionHeight);
+ mQsMinExpansionHeight += mNPVPluginManager.getHeight();
+ }
mQsMaxExpansionHeight = mQs.getDesiredHeight();
mNotificationStackScroller.setMaxTopPadding(
mQsMaxExpansionHeight + mQsNotificationTopPadding);
@@ -1683,7 +1706,7 @@ public class NotificationPanelView extends PanelView implements
@Override
public void onStateChanged(int statusBarState) {
boolean goingToFullShade = mStatusBarStateController.goingToFullShade();
- boolean keyguardFadingAway = mKeyguardMonitor.isKeyguardFadingAway();
+ boolean keyguardFadingAway = mKeyguardStateController.isKeyguardFadingAway();
int oldState = mBarState;
boolean keyguardShowing = statusBarState == StatusBarState.KEYGUARD;
setKeyguardStatusViewVisibility(statusBarState, keyguardFadingAway, goingToFullShade);
@@ -1701,7 +1724,7 @@ public class NotificationPanelView extends PanelView implements
&& (goingToFullShade || statusBarState == StatusBarState.SHADE_LOCKED)) {
animateKeyguardStatusBarOut();
long delay = mBarState == StatusBarState.SHADE_LOCKED
- ? 0 : mKeyguardMonitor.calculateGoingToFullShadeDelay();
+ ? 0 : mKeyguardStateController.calculateGoingToFullShadeDelay();
mQs.animateHeaderSlidingIn(delay);
} else if (oldState == StatusBarState.SHADE_LOCKED
&& statusBarState == StatusBarState.KEYGUARD) {
@@ -1778,13 +1801,13 @@ public class NotificationPanelView extends PanelView implements
private void animateKeyguardStatusBarOut() {
ValueAnimator anim = ValueAnimator.ofFloat(mKeyguardStatusBar.getAlpha(), 0f);
anim.addUpdateListener(mStatusBarAnimateAlphaListener);
- anim.setStartDelay(mKeyguardMonitor.isKeyguardFadingAway()
- ? mKeyguardMonitor.getKeyguardFadingAwayDelay()
+ anim.setStartDelay(mKeyguardStateController.isKeyguardFadingAway()
+ ? mKeyguardStateController.getKeyguardFadingAwayDelay()
: 0);
long duration;
- if (mKeyguardMonitor.isKeyguardFadingAway()) {
- duration = mKeyguardMonitor.getShortenedFadingAwayDuration();
+ if (mKeyguardStateController.isKeyguardFadingAway()) {
+ duration = mKeyguardStateController.getShortenedFadingAwayDuration();
} else {
duration = StackStateAnimator.ANIMATION_DURATION_STANDARD;
}
@@ -1831,8 +1854,8 @@ public class NotificationPanelView extends PanelView implements
if (goingToFullShade) {
mKeyguardBottomArea.animate()
.alpha(0f)
- .setStartDelay(mKeyguardMonitor.getKeyguardFadingAwayDelay())
- .setDuration(mKeyguardMonitor.getShortenedFadingAwayDuration())
+ .setStartDelay(mKeyguardStateController.getKeyguardFadingAwayDelay())
+ .setDuration(mKeyguardStateController.getShortenedFadingAwayDuration())
.setInterpolator(Interpolators.ALPHA_OUT)
.withEndAction(mAnimateKeyguardBottomAreaInvisibleEndRunnable)
.start();
@@ -1860,8 +1883,8 @@ public class NotificationPanelView extends PanelView implements
.withEndAction(mAnimateKeyguardStatusViewGoneEndRunnable);
if (keyguardFadingAway) {
mKeyguardStatusView.animate()
- .setStartDelay(mKeyguardMonitor.getKeyguardFadingAwayDelay())
- .setDuration(mKeyguardMonitor.getShortenedFadingAwayDuration())
+ .setStartDelay(mKeyguardStateController.getKeyguardFadingAwayDelay())
+ .setDuration(mKeyguardStateController.getShortenedFadingAwayDuration())
.start();
}
} else if (mBarState == StatusBarState.SHADE_LOCKED
@@ -1902,9 +1925,11 @@ public class NotificationPanelView extends PanelView implements
mBarState != StatusBarState.KEYGUARD && (!mQsExpanded
|| mQsExpansionFromOverscroll));
updateEmptyShadeView();
- mNPVPluginManager.changeVisibility((mBarState != StatusBarState.KEYGUARD)
- ? View.VISIBLE
- : View.INVISIBLE);
+ if (mNPVPluginManager != null) {
+ mNPVPluginManager.changeVisibility((mBarState != StatusBarState.KEYGUARD)
+ ? View.VISIBLE
+ : View.INVISIBLE);
+ }
mQsNavbarScrim.setVisibility(mBarState == StatusBarState.SHADE && mQsExpanded
&& !mStackScrollerOverscrolling && mQsScrimEnabled
? View.VISIBLE
@@ -1962,7 +1987,9 @@ public class NotificationPanelView extends PanelView implements
float qsExpansionFraction = getQsExpansionFraction();
mQs.setQsExpansion(qsExpansionFraction, getHeaderTranslation());
int heightDiff = mQs.getDesiredHeight() - mQs.getQsMinExpansionHeight();
- mNPVPluginManager.setExpansion(qsExpansionFraction, getHeaderTranslation(), heightDiff);
+ if (mNPVPluginManager != null) {
+ mNPVPluginManager.setExpansion(qsExpansionFraction, getHeaderTranslation(), heightDiff);
+ }
mNotificationStackScroller.setQsExpansionFraction(qsExpansionFraction);
}
@@ -2383,7 +2410,7 @@ public class NotificationPanelView extends PanelView implements
appearAmount = mNotificationStackScroller.calculateAppearFractionBypass();
}
startHeight = -mQs.getQsMinExpansionHeight();
- startHeight -= mNPVPluginManager.getHeight();
+ if (mNPVPluginManager != null) startHeight -= mNPVPluginManager.getHeight();
}
float translation = MathUtils.lerp(startHeight, 0,
Math.min(1.0f, appearAmount))
@@ -2527,7 +2554,7 @@ public class NotificationPanelView extends PanelView implements
mKeyguardStatusBar.setListening(listening);
if (mQs == null) return;
mQs.setListening(listening);
- mNPVPluginManager.setListening(listening);
+ if (mNPVPluginManager != null) mNPVPluginManager.setListening(listening);
}
@Override
@@ -2556,7 +2583,7 @@ public class NotificationPanelView extends PanelView implements
@Override
protected void onTrackingStarted() {
- mFalsingManager.onTrackingStarted(mStatusBar.isKeyguardCurrentlySecure());
+ mFalsingManager.onTrackingStarted(!mKeyguardStateController.canDismissLockScreen());
super.onTrackingStarted();
if (mQsFullyExpanded) {
mQsExpandImmediate = true;
@@ -2846,7 +2873,7 @@ public class NotificationPanelView extends PanelView implements
@Override
protected boolean shouldUseDismissingAnimation() {
return mBarState != StatusBarState.SHADE
- && (!mStatusBar.isKeyguardCurrentlySecure() || !isTracking());
+ && (mKeyguardStateController.canDismissLockScreen() || !isTracking());
}
@Override
@@ -3412,9 +3439,8 @@ public class NotificationPanelView extends PanelView implements
public void setPulsing(boolean pulsing) {
mPulsing = pulsing;
- DozeParameters dozeParameters = DozeParameters.getInstance(mContext);
- final boolean animatePulse = !dozeParameters.getDisplayNeedsBlanking()
- && dozeParameters.getAlwaysOn();
+ final boolean animatePulse = !mDozeParameters.getDisplayNeedsBlanking()
+ && mDozeParameters.getAlwaysOn();
if (animatePulse) {
mAnimateNextPositionUpdate = true;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
index 938eeafb6a8c..b3051b3dd26e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
@@ -44,13 +44,12 @@ import com.android.systemui.Interpolators;
import com.android.systemui.R;
import com.android.systemui.doze.DozeLog;
import com.android.systemui.plugins.FalsingManager;
-import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.FlingAnimationUtils;
import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.SysuiStatusBarStateController;
import com.android.systemui.statusbar.VibratorHelper;
import com.android.systemui.statusbar.phone.HeadsUpManagerPhone;
-import com.android.systemui.statusbar.policy.KeyguardMonitor;
+import com.android.systemui.statusbar.policy.KeyguardStateController;
import android.util.BoostFramework;
import java.io.FileDescriptor;
@@ -113,6 +112,7 @@ public abstract class PanelView extends FrameLayout {
private FlingAnimationUtils mFlingAnimationUtilsClosing;
private FlingAnimationUtils mFlingAnimationUtilsDismissing;
private final FalsingManager mFalsingManager;
+ private final DozeLog mDozeLog;
private final VibratorHelper mVibratorHelper;
/**
@@ -150,9 +150,8 @@ public abstract class PanelView extends FrameLayout {
private boolean mGestureWaitForTouchSlop;
private boolean mIgnoreXTouchSlop;
private boolean mExpandLatencyTracking;
- protected final KeyguardMonitor mKeyguardMonitor = Dependency.get(KeyguardMonitor.class);
- protected final SysuiStatusBarStateController mStatusBarStateController =
- (SysuiStatusBarStateController) Dependency.get(StatusBarStateController.class);
+ protected final KeyguardStateController mKeyguardStateController;
+ protected final SysuiStatusBarStateController mStatusBarStateController;
protected void onExpandingFinished() {
mBar.onExpandingFinished();
@@ -210,8 +209,12 @@ public abstract class PanelView extends FrameLayout {
mJustPeeked = true;
}
- public PanelView(Context context, AttributeSet attrs) {
+ public PanelView(Context context, AttributeSet attrs, FalsingManager falsingManager,
+ DozeLog dozeLog, KeyguardStateController keyguardStateController,
+ SysuiStatusBarStateController statusBarStateController) {
super(context, attrs);
+ mKeyguardStateController = keyguardStateController;
+ mStatusBarStateController = statusBarStateController;
mFlingAnimationUtils = new FlingAnimationUtils(context, 0.6f /* maxLengthSeconds */,
0.6f /* speedUpFactor */);
mFlingAnimationUtilsClosing = new FlingAnimationUtils(context, 0.5f /* maxLengthSeconds */,
@@ -220,7 +223,8 @@ public abstract class PanelView extends FrameLayout {
0.5f /* maxLengthSeconds */, 0.2f /* speedUpFactor */, 0.6f /* x2 */,
0.84f /* y2 */);
mBounceInterpolator = new BounceInterpolator();
- mFalsingManager = Dependency.get(FalsingManager.class); // TODO: inject into a controller.
+ mFalsingManager = falsingManager;
+ mDozeLog = dozeLog;
mNotificationsDragEnabled =
getResources().getBoolean(R.bool.config_enableNotificationShadeDrag);
mVibratorHelper = Dependency.get(VibratorHelper.class);
@@ -485,7 +489,7 @@ public abstract class PanelView extends FrameLayout {
boolean expand = flingExpands(vel, vectorVel, x, y)
|| event.getActionMasked() == MotionEvent.ACTION_CANCEL
|| forceCancel;
- DozeLog.traceFling(expand, mTouchAboveFalsingThreshold,
+ mDozeLog.traceFling(expand, mTouchAboveFalsingThreshold,
mStatusBar.isFalsingThresholdNeeded(),
mStatusBar.isWakeUpComingFromTouch());
// Log collapse gesture if on lock screen.
@@ -504,7 +508,8 @@ public abstract class PanelView extends FrameLayout {
mUpdateFlingVelocity = vel;
}
} else if (mPanelClosedOnDown && !mHeadsUpManager.hasPinnedHeadsUp() && !mTracking
- && !mStatusBar.isBouncerShowing() && !mKeyguardMonitor.isKeyguardFadingAway()) {
+ && !mStatusBar.isBouncerShowing()
+ && !mKeyguardStateController.isKeyguardFadingAway()) {
long timePassed = SystemClock.uptimeMillis() - mDownTime;
if (timePassed < ViewConfiguration.getLongPressTimeout()) {
// Lets show the user that he can actually expand the panel
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
index 6c27a04752a3..fabd67e9ab5d 100755
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
@@ -58,7 +58,7 @@ import com.android.systemui.statusbar.policy.DataSaverController.Listener;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
import com.android.systemui.statusbar.policy.DeviceProvisionedController.DeviceProvisionedListener;
import com.android.systemui.statusbar.policy.HotspotController;
-import com.android.systemui.statusbar.policy.KeyguardMonitor;
+import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.statusbar.policy.LocationController;
import com.android.systemui.statusbar.policy.NextAlarmController;
import com.android.systemui.statusbar.policy.RotationLockController;
@@ -83,7 +83,7 @@ public class PhoneStatusBarPolicy
Listener,
ZenModeController.Callback,
DeviceProvisionedListener,
- KeyguardMonitor.Callback,
+ KeyguardStateController.Callback,
PrivacyItemController.Callback,
LocationController.LocationChangeCallback {
private static final String TAG = "PhoneStatusBarPolicy";
@@ -120,7 +120,7 @@ public class PhoneStatusBarPolicy
private final DataSaverController mDataSaver;
private final ZenModeController mZenController;
private final DeviceProvisionedController mProvisionedController;
- private final KeyguardMonitor mKeyguardMonitor;
+ private final KeyguardStateController mKeyguardStateController;
private final LocationController mLocationController;
private final PrivacyItemController mPrivacyItemController;
private final UiOffloadThread mUiOffloadThread = Dependency.get(UiOffloadThread.class);
@@ -154,7 +154,7 @@ public class PhoneStatusBarPolicy
mDataSaver = Dependency.get(DataSaverController.class);
mZenController = Dependency.get(ZenModeController.class);
mProvisionedController = Dependency.get(DeviceProvisionedController.class);
- mKeyguardMonitor = Dependency.get(KeyguardMonitor.class);
+ mKeyguardStateController = Dependency.get(KeyguardStateController.class);
mLocationController = Dependency.get(LocationController.class);
mPrivacyItemController = Dependency.get(PrivacyItemController.class);
mSensorPrivacyController = Dependency.get(SensorPrivacyController.class);
@@ -254,7 +254,7 @@ public class PhoneStatusBarPolicy
mHotspot.addCallback(mHotspotCallback);
mNextAlarmController.addCallback(mNextAlarmCallback);
mDataSaver.addCallback(this);
- mKeyguardMonitor.addCallback(this);
+ mKeyguardStateController.addCallback(this);
mPrivacyItemController.addCallback(this);
mSensorPrivacyController.addCallback(mSensorPrivacyListener);
mLocationController.addCallback(this);
@@ -470,8 +470,8 @@ public class PhoneStatusBarPolicy
boolean isManagedProfile = mUserManager.isManagedProfile(userId);
mHandler.post(() -> {
final boolean showIcon;
- if (isManagedProfile &&
- (!mKeyguardMonitor.isShowing() || mKeyguardMonitor.isOccluded())) {
+ if (isManagedProfile && (!mKeyguardStateController.isShowing()
+ || mKeyguardStateController.isOccluded())) {
showIcon = true;
mIconController.setIcon(mSlotManagedProfile,
R.drawable.stat_sys_managed_profile_status,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/RegionSamplingHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/RegionSamplingHelper.java
index c1ff572bb210..1a6b415f87db 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/RegionSamplingHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/RegionSamplingHelper.java
@@ -127,6 +127,11 @@ public class RegionSamplingHelper implements View.OnAttachStateChangeListener,
updateSamplingListener();
}
+ void stopAndDestroy() {
+ stop();
+ mSamplingListener.destroy();
+ }
+
@Override
public void onViewAttachedToWindow(View view) {
updateSamplingListener();
@@ -134,9 +139,7 @@ public class RegionSamplingHelper implements View.OnAttachStateChangeListener,
@Override
public void onViewDetachedFromWindow(View view) {
- // isAttachedToWindow is only changed after this call to the listeners, so let's post it
- // instead
- postUpdateSamplingListener();
+ stopAndDestroy();
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
index 8c927799c31c..35039a0d74f9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
@@ -21,7 +21,7 @@ import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
import android.annotation.IntDef;
import android.app.AlarmManager;
-import android.content.Context;
+import android.content.res.Resources;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.os.Handler;
@@ -41,13 +41,14 @@ import com.android.internal.graphics.ColorUtils;
import com.android.internal.util.function.TriConsumer;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.keyguard.KeyguardUpdateMonitorCallback;
-import com.android.systemui.Dependency;
+import com.android.systemui.DejankUtils;
import com.android.systemui.Dumpable;
import com.android.systemui.R;
import com.android.systemui.colorextraction.SysuiColorExtractor;
+import com.android.systemui.dagger.qualifiers.MainResources;
import com.android.systemui.statusbar.ScrimView;
import com.android.systemui.statusbar.notification.stack.ViewState;
-import com.android.systemui.statusbar.policy.KeyguardMonitor;
+import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.util.AlarmTimeout;
import com.android.systemui.util.wakelock.DelayedWakeLock;
import com.android.systemui.util.wakelock.WakeLock;
@@ -58,10 +59,14 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.function.Consumer;
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
/**
* Controls both the scrim behind the notifications and in front of the notifications (when a
* security method gets shown).
*/
+@Singleton
public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnColorsChangedListener,
Dumpable {
@@ -123,13 +128,12 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo
private static final float NOT_INITIALIZED = -1;
private ScrimState mState = ScrimState.UNINITIALIZED;
- private final Context mContext;
- protected final ScrimView mScrimInFront;
- protected final ScrimView mScrimBehind;
- protected final ScrimView mScrimForBubble;
+ private ScrimView mScrimInFront;
+ private ScrimView mScrimBehind;
+ private ScrimView mScrimForBubble;
- private final UnlockMethodCache mUnlockMethodCache;
+ private final KeyguardStateController mKeyguardStateController;
private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
private final DozeParameters mDozeParameters;
private final AlarmTimeout mTimeTicker;
@@ -140,22 +144,21 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo
private GradientColors mColors;
private boolean mNeedsDrawableColorUpdate;
- protected float mScrimBehindAlpha;
- protected float mScrimBehindAlphaResValue;
- protected float mScrimBehindAlphaKeyguard = SCRIM_BEHIND_ALPHA_KEYGUARD;
+ private float mScrimBehindAlpha;
+ private float mScrimBehindAlphaResValue;
+ private float mScrimBehindAlphaKeyguard = SCRIM_BEHIND_ALPHA_KEYGUARD;
// Assuming the shade is expanded during initialization
private float mExpansionFraction = 1f;
private boolean mDarkenWhileDragging;
private boolean mExpansionAffectsAlpha = true;
- protected boolean mAnimateChange;
+ private boolean mAnimateChange;
private boolean mUpdatePending;
private boolean mTracking;
- protected long mAnimationDuration = -1;
+ private long mAnimationDuration = -1;
private long mAnimationDelay;
- private Runnable mOnAnimationFinished;
- private boolean mDeferFinishedListener;
+ private Animator.AnimatorListener mAnimatorListener;
private final Interpolator mInterpolator = new DecelerateInterpolator();
private float mInFrontAlpha = NOT_INITIALIZED;
@@ -169,7 +172,7 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo
private boolean mWallpaperVisibilityTimedOut;
private int mScrimsVisibility;
private final TriConsumer<ScrimState, Float, GradientColors> mScrimStateListener;
- private final Consumer<Integer> mScrimVisibleListener;
+ private Consumer<Integer> mScrimVisibleListener;
private boolean mBlankScreen;
private boolean mScreenBlankingCallbackCalled;
private Callback mCallback;
@@ -184,44 +187,50 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo
private boolean mWakeLockHeld;
private boolean mKeyguardOccluded;
- public ScrimController(ScrimView scrimBehind, ScrimView scrimInFront, ScrimView scrimForBubble,
- TriConsumer<ScrimState, Float, GradientColors> scrimStateListener,
- Consumer<Integer> scrimVisibleListener, DozeParameters dozeParameters,
- AlarmManager alarmManager, KeyguardMonitor keyguardMonitor) {
- mScrimBehind = scrimBehind;
- mScrimInFront = scrimInFront;
- mScrimForBubble = scrimForBubble;
+ @Inject
+ public ScrimController(LightBarController lightBarController, DozeParameters dozeParameters,
+ AlarmManager alarmManager, KeyguardStateController keyguardStateController,
+ @MainResources Resources resources,
+ DelayedWakeLock.Builder delayedWakeLockBuilder, Handler handler,
+ KeyguardUpdateMonitor keyguardUpdateMonitor, SysuiColorExtractor sysuiColorExtractor) {
- mScrimStateListener = scrimStateListener;
- mScrimVisibleListener = scrimVisibleListener;
+ mScrimStateListener = lightBarController::setScrimState;
- mContext = scrimBehind.getContext();
- mUnlockMethodCache = UnlockMethodCache.getInstance(mContext);
- mDarkenWhileDragging = !mUnlockMethodCache.canSkipBouncer();
- mKeyguardUpdateMonitor = Dependency.get(KeyguardUpdateMonitor.class);
+ mKeyguardStateController = keyguardStateController;
+ mDarkenWhileDragging = !mKeyguardStateController.canDismissLockScreen();
+ mKeyguardUpdateMonitor = keyguardUpdateMonitor;
mKeyguardVisibilityCallback = new KeyguardVisibilityCallback();
- mKeyguardUpdateMonitor.registerCallback(mKeyguardVisibilityCallback);
- mScrimBehindAlphaResValue = mContext.getResources().getFloat(R.dimen.scrim_behind_alpha);
- mHandler = getHandler();
+ mScrimBehindAlphaResValue = resources.getFloat(R.dimen.scrim_behind_alpha);
+ mHandler = handler;
mTimeTicker = new AlarmTimeout(alarmManager, this::onHideWallpaperTimeout,
"hide_aod_wallpaper", mHandler);
- mWakeLock = createWakeLock();
+ mWakeLock = delayedWakeLockBuilder.setHandler(mHandler).setTag("Scrims").build();
// Scrim alpha is initially set to the value on the resource but might be changed
// to make sure that text on top of it is legible.
mScrimBehindAlpha = mScrimBehindAlphaResValue;
mDozeParameters = dozeParameters;
- keyguardMonitor.addCallback(new KeyguardMonitor.Callback() {
+ keyguardStateController.addCallback(new KeyguardStateController.Callback() {
@Override
public void onKeyguardFadingAwayChanged() {
- setKeyguardFadingAway(keyguardMonitor.isKeyguardFadingAway(),
- keyguardMonitor.getKeyguardFadingAwayDuration());
+ setKeyguardFadingAway(keyguardStateController.isKeyguardFadingAway(),
+ keyguardStateController.getKeyguardFadingAwayDuration());
}
});
- mColorExtractor = Dependency.get(SysuiColorExtractor.class);
+ mColorExtractor = sysuiColorExtractor;
mColorExtractor.addOnColorsChangedListener(this);
mColors = mColorExtractor.getNeutralColors();
mNeedsDrawableColorUpdate = true;
+ }
+
+ /**
+ * Attach the controller to the supplied views.
+ */
+ public void attachViews(
+ ScrimView scrimBehind, ScrimView scrimInFront, ScrimView scrimForBubble) {
+ mScrimBehind = scrimBehind;
+ mScrimInFront = scrimInFront;
+ mScrimForBubble = scrimForBubble;
final ScrimState[] states = ScrimState.values();
for (int i = 0; i < states.length; i++) {
@@ -232,8 +241,12 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo
mScrimBehind.setDefaultFocusHighlightEnabled(false);
mScrimInFront.setDefaultFocusHighlightEnabled(false);
mScrimForBubble.setDefaultFocusHighlightEnabled(false);
-
updateScrims();
+ mKeyguardUpdateMonitor.registerCallback(mKeyguardVisibilityCallback);
+ }
+
+ void setScrimVisibleListener(Consumer<Integer> listener) {
+ mScrimVisibleListener = listener;
}
public void transitionTo(ScrimState state) {
@@ -257,7 +270,7 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo
final ScrimState oldState = mState;
mState = state;
- Trace.traceCounter(Trace.TRACE_TAG_APP, "scrim_state", mState.getIndex());
+ Trace.traceCounter(Trace.TRACE_TAG_APP, "scrim_state", mState.ordinal());
if (mCallback != null) {
mCallback.onCancelled();
@@ -311,10 +324,12 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo
// Docking pulses may take a long time, wallpapers should also fade away after a while.
mWallpaperVisibilityTimedOut = false;
if (shouldFadeAwayWallpaper()) {
- mTimeTicker.schedule(mDozeParameters.getWallpaperAodDuration(),
- AlarmTimeout.MODE_IGNORE_IF_SCHEDULED);
+ DejankUtils.postAfterTraversal(() -> {
+ mTimeTicker.schedule(mDozeParameters.getWallpaperAodDuration(),
+ AlarmTimeout.MODE_IGNORE_IF_SCHEDULED);
+ });
} else {
- mTimeTicker.cancel();
+ DejankUtils.postAfterTraversal(mTimeTicker::cancel);
}
if (mKeyguardUpdateMonitor.needsSlowUnlockTransition() && mState == ScrimState.UNLOCKED) {
@@ -367,7 +382,7 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo
public void onTrackingStarted() {
mTracking = true;
- mDarkenWhileDragging = !mUnlockMethodCache.canSkipBouncer();
+ mDarkenWhileDragging = !mKeyguardStateController.canDismissLockScreen();
}
public void onExpandingFinished() {
@@ -430,8 +445,10 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo
// and docking.
if (mWallpaperVisibilityTimedOut) {
mWallpaperVisibilityTimedOut = false;
- mTimeTicker.schedule(mDozeParameters.getWallpaperAodDuration(),
- AlarmTimeout.MODE_IGNORE_IF_SCHEDULED);
+ DejankUtils.postAfterTraversal(() -> {
+ mTimeTicker.schedule(mDozeParameters.getWallpaperAodDuration(),
+ AlarmTimeout.MODE_IGNORE_IF_SCHEDULED);
+ });
}
}
}
@@ -514,22 +531,6 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo
}
/**
- * Set front scrim to black, cancelling animations, in order to prepare to fade them
- * away once the display turns on.
- */
- public void prepareForGentleWakeUp() {
- if (mState == ScrimState.AOD && mDozeParameters.getAlwaysOn()) {
- mInFrontAlpha = 1f;
- mInFrontTint = Color.BLACK;
- mBehindTint = Color.BLACK;
- mAnimateChange = false;
- updateScrims();
- mAnimateChange = true;
- mAnimationDuration = ANIMATION_DURATION_LONG;
- }
- }
-
- /**
* If the lock screen sensor is active.
*/
public void setWakeLockScreenSensorActive(boolean active) {
@@ -590,6 +591,8 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo
setScrimAlpha(mScrimInFront, mInFrontAlpha);
setScrimAlpha(mScrimBehind, mBehindAlpha);
setScrimAlpha(mScrimForBubble, mBubbleAlpha);
+ // The animation could have all already finished, let's call onFinished just in case
+ onFinished();
dispatchScrimsVisible();
}
@@ -667,6 +670,9 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo
private void startScrimAnimation(final View scrim, float current) {
ValueAnimator anim = ValueAnimator.ofFloat(0f, 1f);
+ if (mAnimatorListener != null) {
+ anim.addListener(mAnimatorListener);
+ }
final int initialScrimTint = scrim instanceof ScrimView ? ((ScrimView) scrim).getTint() :
Color.TRANSPARENT;
anim.addUpdateListener(animation -> {
@@ -688,15 +694,10 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo
@Override
public void onAnimationEnd(Animator animation) {
+ scrim.setTag(TAG_KEY_ANIM, null);
onFinished(lastCallback);
- scrim.setTag(TAG_KEY_ANIM, null);
dispatchScrimsVisible();
-
- if (!mDeferFinishedListener && mOnAnimationFinished != null) {
- mOnAnimationFinished.run();
- mOnAnimationFinished = null;
- }
}
});
@@ -741,11 +742,6 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo
mCallback.onStart();
}
updateScrims();
- if (mOnAnimationFinished != null && !isAnimating(mScrimInFront)
- && !isAnimating(mScrimBehind)) {
- mOnAnimationFinished.run();
- mOnAnimationFinished = null;
- }
return true;
}
@@ -754,6 +750,16 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo
}
private void onFinished(Callback callback) {
+ if (isAnimating(mScrimBehind)
+ || isAnimating(mScrimInFront)
+ || isAnimating(mScrimForBubble)) {
+ if (callback != null && callback != mCallback) {
+ // Since we only notify the callback that we're finished once everything has
+ // finished, we need to make sure that any changing callbacks are also invoked
+ callback.onFinished();
+ }
+ return;
+ }
if (mWakeLockHeld) {
mWakeLock.release(TAG);
mWakeLockHeld = false;
@@ -773,6 +779,9 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo
mInFrontTint = Color.TRANSPARENT;
mBehindTint = Color.TRANSPARENT;
mBubbleTint = Color.TRANSPARENT;
+ updateScrimColor(mScrimInFront, mInFrontAlpha, mInFrontTint);
+ updateScrimColor(mScrimBehind, mBehindAlpha, mBehindTint);
+ updateScrimColor(mScrimForBubble, mBubbleAlpha, mBubbleTint);
}
}
@@ -781,8 +790,8 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo
}
@VisibleForTesting
- void setOnAnimationFinished(Runnable onAnimationFinished) {
- mOnAnimationFinished = onAnimationFinished;
+ void setAnimatorListener(Animator.AnimatorListener animatorListener) {
+ mAnimatorListener = animatorListener;
}
private void updateScrim(ScrimView scrim, float alpha) {
@@ -790,16 +799,11 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo
ValueAnimator previousAnimator = ViewState.getChildTag(scrim, TAG_KEY_ANIM);
if (previousAnimator != null) {
- if (mAnimateChange) {
- // We are not done yet! Defer calling the finished listener.
- mDeferFinishedListener = true;
- }
// Previous animators should always be cancelled. Not doing so would cause
// overlap, especially on states that don't animate, leading to flickering,
// and in the worst case, an internal state that doesn't represent what
// transitionTo requested.
cancelAnimator(previousAnimator);
- mDeferFinishedListener = false;
}
if (mPendingFrameCallback != null) {
@@ -831,15 +835,11 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo
} else {
// update the alpha directly
updateScrimColor(scrim, alpha, getCurrentScrimTint(scrim));
- onFinished();
}
- } else {
- onFinished();
}
}
- @VisibleForTesting
- protected void cancelAnimator(ValueAnimator previousAnimator) {
+ private void cancelAnimator(ValueAnimator previousAnimator) {
if (previousAnimator != null) {
previousAnimator.cancel();
}
@@ -887,11 +887,6 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo
mScrimBehind.postOnAnimationDelayed(callback, 32 /* delayMillis */);
}
- @VisibleForTesting
- protected Handler getHandler() {
- return new Handler();
- }
-
public int getBackgroundColor() {
int color = mColors.getMainColor();
return Color.argb((int) (mScrimBehind.getViewAlpha() * Color.alpha(color)),
@@ -913,11 +908,6 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo
scheduleUpdate();
}
- @VisibleForTesting
- protected WakeLock createWakeLock() {
- return new DelayedWakeLock(mHandler, WakeLock.createPartial(mContext, "Scrims"));
- }
-
@Override
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
pw.println(" ScrimController: ");
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java
index 7463c7c232bd..13055ffb2f77 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java
@@ -30,12 +30,35 @@ public enum ScrimState {
/**
* Initial state.
*/
- UNINITIALIZED(-1),
+ UNINITIALIZED,
+
+ /**
+ * When turned off by sensors (prox, presence.)
+ */
+ OFF {
+ @Override
+ public void prepare(ScrimState previousState) {
+ mFrontTint = Color.BLACK;
+ mBehindTint = Color.BLACK;
+ mBubbleTint = previousState.mBubbleTint;
+
+ mFrontAlpha = 1f;
+ mBehindAlpha = 1f;
+ mBubbleAlpha = previousState.mBubbleAlpha;
+
+ mAnimationDuration = ScrimController.ANIMATION_DURATION_LONG;
+ }
+
+ @Override
+ public boolean isLowPowerState() {
+ return true;
+ }
+ },
/**
* On the lock screen.
*/
- KEYGUARD(0) {
+ KEYGUARD {
@Override
public void prepare(ScrimState previousState) {
mBlankScreen = false;
@@ -65,7 +88,7 @@ public enum ScrimState {
/**
* Showing password challenge on the keyguard.
*/
- BOUNCER(1) {
+ BOUNCER {
@Override
public void prepare(ScrimState previousState) {
mBehindAlpha = ScrimController.GRADIENT_SCRIM_ALPHA_BUSY;
@@ -77,7 +100,7 @@ public enum ScrimState {
/**
* Showing password challenge on top of a FLAG_SHOW_WHEN_LOCKED activity.
*/
- BOUNCER_SCRIMMED(2) {
+ BOUNCER_SCRIMMED {
@Override
public void prepare(ScrimState previousState) {
mBehindAlpha = 0;
@@ -89,7 +112,7 @@ public enum ScrimState {
/**
* Changing screen brightness from quick settings.
*/
- BRIGHTNESS_MIRROR(3) {
+ BRIGHTNESS_MIRROR {
@Override
public void prepare(ScrimState previousState) {
mBehindAlpha = 0;
@@ -101,7 +124,7 @@ public enum ScrimState {
/**
* Always on display or screen off.
*/
- AOD(4) {
+ AOD {
@Override
public void prepare(ScrimState previousState) {
final boolean alwaysOnEnabled = mDozeParameters.getAlwaysOn();
@@ -136,7 +159,7 @@ public enum ScrimState {
/**
* When phone wakes up because you received a notification.
*/
- PULSING(5) {
+ PULSING {
@Override
public void prepare(ScrimState previousState) {
mFrontAlpha = mAodFrontScrimAlpha;
@@ -164,7 +187,7 @@ public enum ScrimState {
/**
* Unlocked on top of an app (launcher or any other activity.)
*/
- UNLOCKED(6) {
+ UNLOCKED {
@Override
public void prepare(ScrimState previousState) {
// State that UI will sync to.
@@ -201,7 +224,7 @@ public enum ScrimState {
/**
* Unlocked with a bubble expanded.
*/
- BUBBLE_EXPANDED(7) {
+ BUBBLE_EXPANDED {
@Override
public void prepare(ScrimState previousState) {
mFrontTint = Color.TRANSPARENT;
@@ -237,17 +260,12 @@ public enum ScrimState {
DozeParameters mDozeParameters;
boolean mDisplayRequiresBlanking;
boolean mWallpaperSupportsAmbientMode;
- int mIndex;
boolean mHasBackdrop;
boolean mLaunchingAffordanceWithPreview;
boolean mWakeLockScreenSensorActive;
boolean mKeyguardFadingAway;
long mKeyguardFadingAwayDuration;
- ScrimState(int index) {
- mIndex = index;
- }
-
public void init(ScrimView scrimInFront, ScrimView scrimBehind, ScrimView scrimForBubble,
DozeParameters dozeParameters) {
mScrimInFront = scrimInFront;
@@ -262,10 +280,6 @@ public enum ScrimState {
public void prepare(ScrimState previousState) {
}
- public int getIndex() {
- return mIndex;
- }
-
public float getFrontAlpha() {
return mFrontAlpha;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index 90894b08dc7f..11080619a5d4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -24,8 +24,12 @@ import static android.app.StatusBarManager.WindowType;
import static android.app.StatusBarManager.WindowVisibleState;
import static android.app.StatusBarManager.windowStateToString;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY;
+import static android.view.InsetsFlags.getAppearance;
+import static android.view.InsetsState.TYPE_TOP_BAR;
+import static android.view.InsetsState.containsType;
+import static android.view.WindowInsetsController.APPEARANCE_LOW_PROFILE_BARS;
+import static android.view.WindowInsetsController.APPEARANCE_OPAQUE_TOP_BAR;
-import static com.android.systemui.DejankUtils.whitelistIpcs;
import static com.android.systemui.Dependency.ALLOW_NOTIFICATION_LONG_PRESS_NAME;
import static com.android.systemui.Dependency.BG_HANDLER;
import static com.android.systemui.Dependency.MAIN_HANDLER;
@@ -46,12 +50,10 @@ import static com.android.systemui.statusbar.phone.BarTransitions.TransitionMode
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
-import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityManager;
import android.app.ActivityOptions;
import android.app.ActivityTaskManager;
-import android.app.AlarmManager;
import android.app.AppOpsManager;
import android.app.IWallpaperManager;
import android.app.KeyguardManager;
@@ -76,7 +78,6 @@ import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Point;
import android.graphics.PointF;
-import android.graphics.Rect;
import android.media.AudioAttributes;
import android.metrics.LogMaker;
import android.net.Uri;
@@ -105,6 +106,7 @@ import android.util.Log;
import android.util.Slog;
import android.view.Display;
import android.view.IWindowManager;
+import android.view.InsetsState.InternalInsetType;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.MotionEvent;
@@ -113,6 +115,7 @@ import android.view.ThreadedRenderer;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
+import android.view.WindowInsetsController.Appearance;
import android.view.WindowManager;
import android.view.WindowManagerGlobal;
import android.view.accessibility.AccessibilityManager;
@@ -125,6 +128,7 @@ import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.statusbar.IStatusBarService;
import com.android.internal.statusbar.RegisterStatusBarResult;
+import com.android.internal.view.AppearanceRegion;
import com.android.internal.widget.LockPatternUtils;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.keyguard.KeyguardUpdateMonitorCallback;
@@ -147,13 +151,13 @@ import com.android.systemui.SystemUIFactory;
import com.android.systemui.UiOffloadThread;
import com.android.systemui.appops.AppOpsController;
import com.android.systemui.assist.AssistManager;
+import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.bubbles.BubbleController;
import com.android.systemui.charging.WirelessChargingAnimation;
import com.android.systemui.classifier.FalsingLog;
import com.android.systemui.colorextraction.SysuiColorExtractor;
import com.android.systemui.doze.DozeHost;
import com.android.systemui.doze.DozeLog;
-import com.android.systemui.doze.DozeReceiver;
import com.android.systemui.fragments.ExtensionFragmentListener;
import com.android.systemui.fragments.FragmentHostManager;
import com.android.systemui.keyguard.KeyguardSliceProvider;
@@ -178,6 +182,7 @@ import com.android.systemui.statusbar.BackDropView;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.CrossFadeHelper;
import com.android.systemui.statusbar.EmptyShadeView;
+import com.android.systemui.statusbar.FeatureFlags;
import com.android.systemui.statusbar.GestureRecorder;
import com.android.systemui.statusbar.KeyboardShortcuts;
import com.android.systemui.statusbar.KeyguardIndicationController;
@@ -197,6 +202,7 @@ import com.android.systemui.statusbar.VibratorHelper;
import com.android.systemui.statusbar.notification.ActivityLaunchAnimator;
import com.android.systemui.statusbar.notification.BypassHeadsUpNotifier;
import com.android.systemui.statusbar.notification.DynamicPrivacyController;
+import com.android.systemui.statusbar.notification.NewNotifPipeline;
import com.android.systemui.statusbar.notification.NotificationActivityStarter;
import com.android.systemui.statusbar.notification.NotificationAlertingManager;
import com.android.systemui.statusbar.notification.NotificationClicker;
@@ -208,11 +214,11 @@ import com.android.systemui.statusbar.notification.ViewGroupFadeHelper;
import com.android.systemui.statusbar.notification.VisualStabilityManager;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.NotificationRowBinderImpl;
+import com.android.systemui.statusbar.notification.logging.NotifLog;
import com.android.systemui.statusbar.notification.logging.NotificationLogger;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
-import com.android.systemui.statusbar.phone.UnlockMethodCache.OnUnlockMethodChangedListener;
import com.android.systemui.statusbar.policy.BatteryController;
import com.android.systemui.statusbar.policy.BatteryController.BatteryStateChangeCallback;
import com.android.systemui.statusbar.policy.BrightnessMirrorController;
@@ -222,7 +228,7 @@ import com.android.systemui.statusbar.policy.DeviceProvisionedController;
import com.android.systemui.statusbar.policy.DeviceProvisionedController.DeviceProvisionedListener;
import com.android.systemui.statusbar.policy.ExtensionController;
import com.android.systemui.statusbar.policy.HeadsUpManager;
-import com.android.systemui.statusbar.policy.KeyguardMonitor;
+import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.statusbar.policy.KeyguardUserSwitcher;
import com.android.systemui.statusbar.policy.NetworkController;
import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener;
@@ -242,11 +248,14 @@ import java.util.Map;
import javax.inject.Inject;
import javax.inject.Named;
+import javax.inject.Singleton;
+import dagger.Lazy;
import dagger.Subcomponent;
+@Singleton
public class StatusBar extends SystemUI implements DemoMode,
- ActivityStarter, OnUnlockMethodChangedListener,
+ ActivityStarter, KeyguardStateController.Callback,
OnHeadsUpChangedListener, CommandQueue.Callbacks, ZenModeController.Callback,
ColorExtractor.OnColorsChangedListener, ConfigurationListener,
StatusBarStateController.StateListener, ShadeController,
@@ -335,7 +344,7 @@ public class StatusBar extends SystemUI implements DemoMode,
/**
* The {@link StatusBarState} of the status bar.
*/
- protected int mState;
+ protected int mState; // TODO: remove this. Just use StatusBarStateController
protected boolean mBouncerShowing;
private PhoneStatusBarPolicy mIconPolicy;
@@ -344,51 +353,49 @@ public class StatusBar extends SystemUI implements DemoMode,
private VolumeComponent mVolumeComponent;
private BrightnessMirrorController mBrightnessMirrorController;
private boolean mBrightnessMirrorVisible;
- protected BiometricUnlockController mBiometricUnlockController;
- private LightBarController mLightBarController;
+ private BiometricUnlockController mBiometricUnlockController;
+ private final LightBarController mLightBarController;
+ private final Lazy<LockscreenWallpaper> mLockscreenWallpaperLazy;
protected LockscreenWallpaper mLockscreenWallpaper;
- @VisibleForTesting
- protected AutoHideController mAutoHideController;
+ private final AutoHideController mAutoHideController;
private int mNaturalBarHeight = -1;
private final Point mCurrentDisplaySize = new Point();
+ protected StatusBarWindowViewController mStatusBarWindowViewController;
protected StatusBarWindowView mStatusBarWindow;
protected PhoneStatusBarView mStatusBarView;
private int mStatusBarWindowState = WINDOW_STATE_SHOWING;
protected StatusBarWindowController mStatusBarWindowController;
- protected UnlockMethodCache mUnlockMethodCache;
- @VisibleForTesting
- KeyguardUpdateMonitor mKeyguardUpdateMonitor;
+ private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
@VisibleForTesting
- DozeServiceHost mDozeServiceHost = new DozeServiceHost();
+ DozeServiceHost mDozeServiceHost;
private boolean mWakeUpComingFromTouch;
private PointF mWakeUpTouchLocation;
private final Object mQueueLock = new Object();
- protected StatusBarIconController mIconController;
- @Inject
- InjectionInflationController mInjectionInflater;
- @Inject
- PulseExpansionHandler mPulseExpansionHandler;
- @Inject
- NotificationWakeUpCoordinator mWakeUpCoordinator;
- @Inject
- KeyguardBypassController mKeyguardBypassController;
- @Inject
- protected HeadsUpManagerPhone mHeadsUpManager;
- @Inject
- DynamicPrivacyController mDynamicPrivacyController;
- @Inject
- BypassHeadsUpNotifier mBypassHeadsUpNotifier;
- @Nullable
- @Inject
- protected KeyguardLiftController mKeyguardLiftController;
- @Inject
- @Named(ALLOW_NOTIFICATION_LONG_PRESS_NAME)
- boolean mAllowNotificationLongPress;
+ private final FeatureFlags mFeatureFlags;
+ private final StatusBarIconController mIconController;
+ private final DozeLog mDozeLog;
+ private final InjectionInflationController mInjectionInflater;
+ private final PulseExpansionHandler mPulseExpansionHandler;
+ private final NotificationWakeUpCoordinator mWakeUpCoordinator;
+ private final KeyguardBypassController mKeyguardBypassController;
+ private final KeyguardStateController mKeyguardStateController;
+ private final HeadsUpManagerPhone mHeadsUpManager;
+ private final DynamicPrivacyController mDynamicPrivacyController;
+ private final BypassHeadsUpNotifier mBypassHeadsUpNotifier;
+ private final boolean mAllowNotificationLongPress;
+ private final Lazy<NewNotifPipeline> mNewNotifPipeline;
+ private final FalsingManager mFalsingManager;
+ private final BroadcastDispatcher mBroadcastDispatcher;
+ private final ConfigurationController mConfigurationController;
+ private final StatusBarWindowViewController.Builder mStatusBarWindowViewControllerBuilder;
+ private final NotifLog mNotifLog;
+ private final DozeParameters mDozeParameters;
+ private final Lazy<BiometricUnlockController> mBiometricUnlockControllerLazy;
// expanded notifications
protected NotificationPanelView mNotificationPanel; // the sliding/resizing panel within the notification window
@@ -401,8 +408,7 @@ public class StatusBar extends SystemUI implements DemoMode,
// RemoteInputView to be activated after unlock
private View mPendingRemoteInputView;
- private RemoteInputQuickSettingsDisabler mRemoteInputQuickSettingsDisabler =
- Dependency.get(RemoteInputQuickSettingsDisabler.class);
+ private final RemoteInputQuickSettingsDisabler mRemoteInputQuickSettingsDisabler;
private View mReportRejectedTouch;
@@ -411,29 +417,31 @@ public class StatusBar extends SystemUI implements DemoMode,
private final int[] mAbsPos = new int[2];
private final ArrayList<Runnable> mPostCollapseRunnables = new ArrayList<>();
- private NotificationGutsManager mGutsManager;
- protected NotificationLogger mNotificationLogger;
- protected NotificationEntryManager mEntryManager;
+ private final NotificationGutsManager mGutsManager;
+ private final NotificationLogger mNotificationLogger;
+ private final NotificationEntryManager mEntryManager;
private NotificationListController mNotificationListController;
- private NotificationInterruptionStateProvider mNotificationInterruptionStateProvider;
- protected NotificationViewHierarchyManager mViewHierarchyManager;
- protected ForegroundServiceController mForegroundServiceController;
- protected AppOpsController mAppOpsController;
- protected KeyguardViewMediator mKeyguardViewMediator;
- private ZenModeController mZenController;
- private final NotificationAlertingManager mNotificationAlertingManager =
- Dependency.get(NotificationAlertingManager.class);
+ private final NotificationInterruptionStateProvider mNotificationInterruptionStateProvider;
+ private final NotificationViewHierarchyManager mViewHierarchyManager;
+ private final ForegroundServiceController mForegroundServiceController;
+ private final AppOpsController mAppOpsController;
+ private final KeyguardViewMediator mKeyguardViewMediator;
+ private final ZenModeController mZenController;
+ private final NotificationAlertingManager mNotificationAlertingManager;
// for disabling the status bar
private int mDisabled1 = 0;
private int mDisabled2 = 0;
- // tracking calls to View.setSystemUiVisibility()
- private int mSystemUiVisibility = View.SYSTEM_UI_FLAG_VISIBLE;
- private final Rect mLastFullscreenStackBounds = new Rect();
- private final Rect mLastDockedStackBounds = new Rect();
+ /** @see android.view.WindowInsetsController#setSystemBarsAppearance(int) */
+ private @Appearance int mAppearance;
- private final DisplayMetrics mDisplayMetrics = Dependency.get(DisplayMetrics.class);
+ private boolean mTransientShown;
+
+ private boolean mAppFullscreen;
+ private boolean mAppImmersive;
+
+ private final DisplayMetrics mDisplayMetrics;
// XXX: gesture research
private final GestureRecorder mGestureRec = DEBUG_GESTURES
@@ -442,7 +450,7 @@ public class StatusBar extends SystemUI implements DemoMode,
private ScreenPinningRequest mScreenPinningRequest;
- private final MetricsLogger mMetricsLogger = Dependency.get(MetricsLogger.class);
+ private final MetricsLogger mMetricsLogger;
// ensure quick settings is disabled until the current user makes it through the setup wizard
@VisibleForTesting
@@ -477,16 +485,15 @@ public class StatusBar extends SystemUI implements DemoMode,
private @TransitionMode int mStatusBarMode;
private ViewMediatorCallback mKeyguardViewMediatorCallback;
- protected ScrimController mScrimController;
+ private final ScrimController mScrimController;
protected DozeScrimController mDozeScrimController;
- private final UiOffloadThread mUiOffloadThread = Dependency.get(UiOffloadThread.class);
+ private final UiOffloadThread mUiOffloadThread;
protected boolean mDozing;
- private boolean mDozingRequested;
- private NotificationMediaManager mMediaManager;
- protected NotificationLockscreenUserManager mLockscreenUserManager;
- protected NotificationRemoteInputManager mRemoteInputManager;
+ private final NotificationMediaManager mMediaManager;
+ private final NotificationLockscreenUserManager mLockscreenUserManager;
+ private final NotificationRemoteInputManager mRemoteInputManager;
private boolean mWallpaperSupported;
private final BroadcastReceiver mWallpaperChangedReceiver = new BroadcastReceiver() {
@@ -501,8 +508,7 @@ public class StatusBar extends SystemUI implements DemoMode,
WallpaperInfo info = wallpaperManager.getWallpaperInfo(UserHandle.USER_CURRENT);
final boolean deviceSupportsAodWallpaper = mContext.getResources().getBoolean(
com.android.internal.R.bool.config_dozeSupportsAodWallpaper);
- final boolean imageWallpaperInAmbient =
- !DozeParameters.getInstance(mContext).getDisplayNeedsBlanking();
+ final boolean imageWallpaperInAmbient = !mDozeParameters.getDisplayNeedsBlanking();
// If WallpaperInfo is null, it must be ImageWallpaper.
final boolean supportsAmbientMode = deviceSupportsAodWallpaper
&& ((info == null && imageWallpaperInAmbient)
@@ -545,7 +551,7 @@ public class StatusBar extends SystemUI implements DemoMode,
+ "mStatusBarKeyguardViewManager was null");
return;
}
- if (mKeyguardMonitor.isKeyguardFadingAway()) {
+ if (mKeyguardStateController.isKeyguardFadingAway()) {
mStatusBarKeyguardViewManager.onKeyguardFadedAway();
}
}
@@ -557,19 +563,18 @@ public class StatusBar extends SystemUI implements DemoMode,
};
private KeyguardUserSwitcher mKeyguardUserSwitcher;
- protected UserSwitcherController mUserSwitcherController;
- private NetworkController mNetworkController;
- private KeyguardMonitor mKeyguardMonitor = Dependency.get(KeyguardMonitor.class);
- private BatteryController mBatteryController;
+ private final UserSwitcherController mUserSwitcherController;
+ private final NetworkController mNetworkController;
+ private final BatteryController mBatteryController;
protected boolean mPanelExpanded;
private UiModeManager mUiModeManager;
protected boolean mIsKeyguard;
private LogMaker mStatusBarStateLog;
protected NotificationIconAreaController mNotificationIconAreaController;
@Nullable private View mAmbientIndicationContainer;
- private SysuiColorExtractor mColorExtractor;
- private ScreenLifecycle mScreenLifecycle;
- @VisibleForTesting WakefulnessLifecycle mWakefulnessLifecycle;
+ private final SysuiColorExtractor mColorExtractor;
+ private final ScreenLifecycle mScreenLifecycle;
+ private final WakefulnessLifecycle mWakefulnessLifecycle;
private final View.OnClickListener mGoToLockedShadeListener = v -> {
if (mState == StatusBarState.KEYGUARD) {
@@ -578,9 +583,7 @@ public class StatusBar extends SystemUI implements DemoMode,
}
};
private boolean mNoAnimationOnNextBarModeChange;
- protected FalsingManager mFalsingManager;
- private final SysuiStatusBarStateController mStatusBarStateController =
- (SysuiStatusBarStateController) Dependency.get(StatusBarStateController.class);
+ private final SysuiStatusBarStateController mStatusBarStateController;
private final KeyguardUpdateMonitorCallback mUpdateCallback =
new KeyguardUpdateMonitorCallback() {
@@ -594,26 +597,21 @@ public class StatusBar extends SystemUI implements DemoMode,
@Override
public void onStrongAuthStateChanged(int userId) {
super.onStrongAuthStateChanged(userId);
- mEntryManager.updateNotifications();
+ mEntryManager.updateNotifications("onStrongAuthStateChanged");
}
};
private final Handler mMainThreadHandler = new Handler(Looper.getMainLooper());
private HeadsUpAppearanceController mHeadsUpAppearanceController;
private boolean mVibrateOnOpening;
- private VibratorHelper mVibratorHelper;
+ private final VibratorHelper mVibratorHelper;
private ActivityLaunchAnimator mActivityLaunchAnimator;
protected StatusBarNotificationPresenter mPresenter;
private NotificationActivityStarter mNotificationActivityStarter;
- private boolean mPulsing;
- protected BubbleController mBubbleController;
- private final BubbleController.BubbleExpandListener mBubbleExpandListener =
- (isExpanding, key) -> {
- mEntryManager.updateNotifications();
- updateScrimController();
- };
+ private final BubbleController mBubbleController;
+ private final BubbleController.BubbleExpandListener mBubbleExpandListener;
+
private ActivityIntentHelper mActivityIntentHelper;
- private ShadeController mShadeController;
@Override
public void onActiveStateChanged(int code, int uid, String packageName, boolean active) {
@@ -629,46 +627,155 @@ public class StatusBar extends SystemUI implements DemoMode,
AppOpsManager.OP_COARSE_LOCATION,
AppOpsManager.OP_FINE_LOCATION};
+ @Inject
+ public StatusBar(
+ Context context,
+ FeatureFlags featureFlags,
+ LightBarController lightBarController,
+ AutoHideController autoHideController,
+ KeyguardUpdateMonitor keyguardUpdateMonitor,
+ StatusBarIconController statusBarIconController,
+ DozeLog dozeLog,
+ InjectionInflationController injectionInflationController,
+ PulseExpansionHandler pulseExpansionHandler,
+ NotificationWakeUpCoordinator notificationWakeUpCoordinator,
+ KeyguardBypassController keyguardBypassController,
+ KeyguardStateController keyguardStateController,
+ HeadsUpManagerPhone headsUpManagerPhone,
+ DynamicPrivacyController dynamicPrivacyController,
+ BypassHeadsUpNotifier bypassHeadsUpNotifier,
+ @Named(ALLOW_NOTIFICATION_LONG_PRESS_NAME) boolean allowNotificationLongPress,
+ Lazy<NewNotifPipeline> newNotifPipeline,
+ FalsingManager falsingManager,
+ BroadcastDispatcher broadcastDispatcher,
+ RemoteInputQuickSettingsDisabler remoteInputQuickSettingsDisabler,
+ NotificationGutsManager notificationGutsManager,
+ NotificationLogger notificationLogger,
+ NotificationEntryManager notificationEntryManager,
+ NotificationInterruptionStateProvider notificationInterruptionStateProvider,
+ NotificationViewHierarchyManager notificationViewHierarchyManager,
+ ForegroundServiceController foregroundServiceController,
+ AppOpsController appOpsController,
+ KeyguardViewMediator keyguardViewMediator,
+ ZenModeController zenModeController,
+ NotificationAlertingManager notificationAlertingManager,
+ DisplayMetrics displayMetrics,
+ MetricsLogger metricsLogger,
+ UiOffloadThread uiOffloadThread,
+ NotificationMediaManager notificationMediaManager,
+ NotificationLockscreenUserManager lockScreenUserManager,
+ NotificationRemoteInputManager remoteInputManager,
+ UserSwitcherController userSwitcherController,
+ NetworkController networkController,
+ BatteryController batteryController,
+ SysuiColorExtractor colorExtractor,
+ ScreenLifecycle screenLifecycle,
+ WakefulnessLifecycle wakefulnessLifecycle,
+ SysuiStatusBarStateController statusBarStateController,
+ VibratorHelper vibratorHelper,
+ BubbleController bubbleController,
+ NotificationGroupManager groupManager,
+ NotificationGroupAlertTransferHelper groupAlertTransferHelper,
+ VisualStabilityManager visualStabilityManager,
+ DeviceProvisionedController deviceProvisionedController,
+ NavigationBarController navigationBarController,
+ AssistManager assistManager,
+ NotificationListener notificationListener,
+ ConfigurationController configurationController,
+ StatusBarWindowController statusBarWindowController,
+ StatusBarWindowViewController.Builder statusBarWindowViewControllerBuilder,
+ NotifLog notifLog,
+ DozeParameters dozeParameters,
+ ScrimController scrimController,
+ Lazy<LockscreenWallpaper> lockscreenWallpaperLazy,
+ Lazy<BiometricUnlockController> biometricUnlockControllerLazy,
+ DozeServiceHost dozeServiceHost,
+ PowerManager powerManager,
+ DozeScrimController dozeScrimController) {
+ super(context);
+ mFeatureFlags = featureFlags;
+ mLightBarController = lightBarController;
+ mAutoHideController = autoHideController;
+ mKeyguardUpdateMonitor = keyguardUpdateMonitor;
+ mIconController = statusBarIconController;
+ mDozeLog = dozeLog;
+ mInjectionInflater = injectionInflationController;
+ mPulseExpansionHandler = pulseExpansionHandler;
+ mWakeUpCoordinator = notificationWakeUpCoordinator;
+ mKeyguardBypassController = keyguardBypassController;
+ mKeyguardStateController = keyguardStateController;
+ mHeadsUpManager = headsUpManagerPhone;
+ mDynamicPrivacyController = dynamicPrivacyController;
+ mBypassHeadsUpNotifier = bypassHeadsUpNotifier;
+ mAllowNotificationLongPress = allowNotificationLongPress;
+ mNewNotifPipeline = newNotifPipeline;
+ mFalsingManager = falsingManager;
+ mBroadcastDispatcher = broadcastDispatcher;
+ mRemoteInputQuickSettingsDisabler = remoteInputQuickSettingsDisabler;
+ mGutsManager = notificationGutsManager;
+ mNotificationLogger = notificationLogger;
+ mEntryManager = notificationEntryManager;
+ mNotificationInterruptionStateProvider = notificationInterruptionStateProvider;
+ mViewHierarchyManager = notificationViewHierarchyManager;
+ mForegroundServiceController = foregroundServiceController;
+ mAppOpsController = appOpsController;
+ mKeyguardViewMediator = keyguardViewMediator;
+ mZenController = zenModeController;
+ mNotificationAlertingManager = notificationAlertingManager;
+ mDisplayMetrics = displayMetrics;
+ mMetricsLogger = metricsLogger;
+ mUiOffloadThread = uiOffloadThread;
+ mMediaManager = notificationMediaManager;
+ mLockscreenUserManager = lockScreenUserManager;
+ mRemoteInputManager = remoteInputManager;
+ mUserSwitcherController = userSwitcherController;
+ mNetworkController = networkController;
+ mBatteryController = batteryController;
+ mColorExtractor = colorExtractor;
+ mScreenLifecycle = screenLifecycle;
+ mWakefulnessLifecycle = wakefulnessLifecycle;
+ mStatusBarStateController = statusBarStateController;
+ mVibratorHelper = vibratorHelper;
+ mBubbleController = bubbleController;
+ mGroupManager = groupManager;
+ mGroupAlertTransferHelper = groupAlertTransferHelper;
+ mVisualStabilityManager = visualStabilityManager;
+ mDeviceProvisionedController = deviceProvisionedController;
+ mNavigationBarController = navigationBarController;
+ mAssistManager = assistManager;
+ mNotificationListener = notificationListener;
+ mConfigurationController = configurationController;
+ mStatusBarWindowController = statusBarWindowController;
+ mStatusBarWindowViewControllerBuilder = statusBarWindowViewControllerBuilder;
+ mNotifLog = notifLog;
+ mDozeServiceHost = dozeServiceHost;
+ mPowerManager = powerManager;
+ mDozeParameters = dozeParameters;
+ mScrimController = scrimController;
+ mLockscreenWallpaperLazy = lockscreenWallpaperLazy;
+ mDozeScrimController = dozeScrimController;
+ mBiometricUnlockControllerLazy = biometricUnlockControllerLazy;
+
+ mBubbleExpandListener =
+ (isExpanding, key) -> {
+ mEntryManager.updateNotifications("onBubbleExpandChanged");
+ updateScrimController();
+ };
+ }
+
@Override
public void start() {
- mGroupManager = Dependency.get(NotificationGroupManager.class);
- mGroupAlertTransferHelper = Dependency.get(NotificationGroupAlertTransferHelper.class);
- mVisualStabilityManager = Dependency.get(VisualStabilityManager.class);
- mNotificationLogger = Dependency.get(NotificationLogger.class);
- mRemoteInputManager = Dependency.get(NotificationRemoteInputManager.class);
- mNotificationListener = Dependency.get(NotificationListener.class);
mNotificationListener.registerAsSystemService();
- mNetworkController = Dependency.get(NetworkController.class);
- mUserSwitcherController = Dependency.get(UserSwitcherController.class);
- mScreenLifecycle = Dependency.get(ScreenLifecycle.class);
mScreenLifecycle.addObserver(mScreenObserver);
- mWakefulnessLifecycle = Dependency.get(WakefulnessLifecycle.class);
mWakefulnessLifecycle.addObserver(mWakefulnessObserver);
- mBatteryController = Dependency.get(BatteryController.class);
- mAssistManager = Dependency.get(AssistManager.class);
mUiModeManager = mContext.getSystemService(UiModeManager.class);
- mLockscreenUserManager = Dependency.get(NotificationLockscreenUserManager.class);
- mGutsManager = Dependency.get(NotificationGutsManager.class);
- mMediaManager = Dependency.get(NotificationMediaManager.class);
- mEntryManager = Dependency.get(NotificationEntryManager.class);
mBypassHeadsUpNotifier.setUp(mEntryManager);
- mNotificationInterruptionStateProvider =
- Dependency.get(NotificationInterruptionStateProvider.class);
- mViewHierarchyManager = Dependency.get(NotificationViewHierarchyManager.class);
- mForegroundServiceController = Dependency.get(ForegroundServiceController.class);
- mAppOpsController = Dependency.get(AppOpsController.class);
- mZenController = Dependency.get(ZenModeController.class);
- mKeyguardViewMediator = getComponent(KeyguardViewMediator.class);
- mColorExtractor = Dependency.get(SysuiColorExtractor.class);
- mDeviceProvisionedController = Dependency.get(DeviceProvisionedController.class);
- mNavigationBarController = Dependency.get(NavigationBarController.class);
- mBubbleController = Dependency.get(BubbleController.class);
mBubbleController.setExpandListener(mBubbleExpandListener);
mActivityIntentHelper = new ActivityIntentHelper(mContext);
KeyguardSliceProvider sliceProvider = KeyguardSliceProvider.getAttachedInstance();
if (sliceProvider != null) {
sliceProvider.initDependencies(mMediaManager, mStatusBarStateController,
- mKeyguardBypassController, DozeParameters.getInstance(mContext));
+ mKeyguardBypassController, mDozeParameters);
} else {
Log.w(TAG, "Cannot init KeyguardSliceProvider dependencies");
}
@@ -687,7 +794,6 @@ public class StatusBar extends SystemUI implements DemoMode,
mVibrateOnOpening = mContext.getResources().getBoolean(
R.bool.config_vibrateOnIconAnimation);
- mVibratorHelper = Dependency.get(VibratorHelper.class);
DateTimeView.setReceiverHandler(Dependency.get(Dependency.TIME_TICK_HANDLER));
putComponent(StatusBar.class, this);
@@ -700,8 +806,6 @@ public class StatusBar extends SystemUI implements DemoMode,
mAccessibilityManager = (AccessibilityManager)
mContext.getSystemService(Context.ACCESSIBILITY_SERVICE);
- mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
- mKeyguardUpdateMonitor = Dependency.get(KeyguardUpdateMonitor.class);
mKeyguardUpdateMonitor.setKeyguardBypassController(mKeyguardBypassController);
mBarService = IStatusBarService.Stub.asInterface(
ServiceManager.getService(Context.STATUS_BAR_SERVICE));
@@ -709,7 +813,6 @@ public class StatusBar extends SystemUI implements DemoMode,
mRecents = getComponent(Recents.class);
mKeyguardManager = (KeyguardManager) mContext.getSystemService(Context.KEYGUARD_SERVICE);
- mFalsingManager = Dependency.get(FalsingManager.class);
// Connect in to the status bar manager service
mCommandQueue = getComponent(CommandQueue.class);
@@ -740,10 +843,22 @@ public class StatusBar extends SystemUI implements DemoMode,
// Set up the initial notification state. This needs to happen before CommandQueue.disable()
setUpPresenter();
- setSystemUiVisibility(mDisplayId, result.mSystemUiVisibility,
- result.mFullscreenStackSysUiVisibility, result.mDockedStackSysUiVisibility,
- 0xffffffff, result.mFullscreenStackBounds, result.mDockedStackBounds,
- result.mNavbarColorManagedByIme);
+ if ((result.mSystemUiVisibility & View.STATUS_BAR_TRANSIENT) != 0) {
+ showTransientUnchecked();
+ }
+ final int fullscreenAppearance = getAppearance(result.mFullscreenStackSysUiVisibility);
+ final int dockedAppearance = getAppearance(result.mDockedStackSysUiVisibility);
+ final AppearanceRegion[] appearanceRegions = result.mDockedStackBounds.isEmpty()
+ ? new AppearanceRegion[]{
+ new AppearanceRegion(fullscreenAppearance, result.mFullscreenStackBounds)}
+ : new AppearanceRegion[]{
+ new AppearanceRegion(fullscreenAppearance, result.mFullscreenStackBounds),
+ new AppearanceRegion(dockedAppearance, result.mDockedStackBounds)};
+ onSystemBarAppearanceChanged(mDisplayId, getAppearance(result.mSystemUiVisibility),
+ appearanceRegions, result.mNavbarColorManagedByIme);
+ mAppFullscreen = result.mAppFullscreen;
+ mAppImmersive = result.mAppImmersive;
+
// StatusBarManagerService has a back up of IME token and it's restored here.
setImeWindowStatus(mDisplayId, result.mImeToken, result.mImeWindowVis,
result.mImeBackDisposition, result.mShowImeSwitcher);
@@ -786,18 +901,20 @@ public class StatusBar extends SystemUI implements DemoMode,
mIconPolicy = new PhoneStatusBarPolicy(mContext, mIconController);
mSignalPolicy = new StatusBarSignalPolicy(mContext, mIconController);
- mUnlockMethodCache = UnlockMethodCache.getInstance(mContext);
- mUnlockMethodCache.addListener(this);
+ mKeyguardStateController.addCallback(this);
startKeyguard();
mKeyguardUpdateMonitor.registerCallback(mUpdateCallback);
+ mDozeServiceHost.initialize(this, mNotificationIconAreaController,
+ mStatusBarWindowViewController, mStatusBarWindow, mStatusBarKeyguardViewManager,
+ mNotificationPanel, mAmbientIndicationContainer);
putComponent(DozeHost.class, mDozeServiceHost);
mScreenPinningRequest = new ScreenPinningRequest(mContext);
Dependency.get(ActivityStarterDelegate.class).setActivityStarterImpl(this);
- Dependency.get(ConfigurationController.class).addCallback(this);
+ mConfigurationController.addCallback(this);
// set the initial view visibility
Dependency.get(InitController.class).addPostInitTask(this::updateAreThereNotifications);
@@ -817,8 +934,7 @@ public class StatusBar extends SystemUI implements DemoMode,
updateTheme();
inflateStatusBarWindow(context);
- mStatusBarWindow.setService(this);
- mStatusBarWindow.setBypassController(mKeyguardBypassController);
+ mStatusBarWindowViewController.setService(this);
mStatusBarWindow.setOnTouchListener(getStatusBarWindowTouchListener());
// TODO: Deal with the ugliness that comes from having some of the statusbar broken out
@@ -830,6 +946,8 @@ public class StatusBar extends SystemUI implements DemoMode,
NotificationListContainer notifListContainer = (NotificationListContainer) mStackScroller;
mNotificationLogger.setUpWithContainer(notifListContainer);
+ // TODO: make this injectable. Currently that would create a circular dependency between
+ // NotificationIconAreaController and StatusBar.
mNotificationIconAreaController = SystemUIFactory.getInstance()
.createNotificationIconAreaController(context, this,
mWakeUpCoordinator, mKeyguardBypassController,
@@ -882,9 +1000,9 @@ public class StatusBar extends SystemUI implements DemoMode,
mHeadsUpAppearanceController = new HeadsUpAppearanceController(
mNotificationIconAreaController, mHeadsUpManager, mStatusBarWindow,
mStatusBarStateController, mKeyguardBypassController,
- mWakeUpCoordinator);
+ mKeyguardStateController, mWakeUpCoordinator);
mHeadsUpAppearanceController.readFrom(oldController);
- mStatusBarWindow.setStatusBarView(mStatusBarView);
+ mStatusBarWindowViewController.setStatusBarView(mStatusBarView);
updateAreThereNotifications();
checkBarModes();
}).getFragmentManager()
@@ -892,10 +1010,9 @@ public class StatusBar extends SystemUI implements DemoMode,
.replace(R.id.status_bar_container, new CollapsedStatusBarFragment(),
CollapsedStatusBarFragment.TAG)
.commit();
- mIconController = Dependency.get(StatusBarIconController.class);
mHeadsUpManager.setUp(mStatusBarWindow, mGroupManager, this, mVisualStabilityManager);
- Dependency.get(ConfigurationController.class).addCallback(mHeadsUpManager);
+ mConfigurationController.addCallback(mHeadsUpManager);
mHeadsUpManager.addListener(this);
mHeadsUpManager.addListener(mNotificationPanel);
mHeadsUpManager.addListener(mGroupManager);
@@ -910,7 +1027,8 @@ public class StatusBar extends SystemUI implements DemoMode,
createNavigationBar(result);
if (ENABLE_LOCKSCREEN_WALLPAPER) {
- mLockscreenWallpaper = new LockscreenWallpaper(mContext, this, mHandler);
+ mLockscreenWallpaper = mLockscreenWallpaperLazy.get();
+ mLockscreenWallpaper.setHandler(mHandler);
}
mKeyguardIndicationController =
@@ -938,31 +1056,22 @@ public class StatusBar extends SystemUI implements DemoMode,
}
});
- mAutoHideController = Dependency.get(AutoHideController.class);
mAutoHideController.setStatusBar(this);
- mLightBarController = Dependency.get(LightBarController.class);
-
ScrimView scrimBehind = mStatusBarWindow.findViewById(R.id.scrim_behind);
ScrimView scrimInFront = mStatusBarWindow.findViewById(R.id.scrim_in_front);
ScrimView scrimForBubble = mStatusBarWindow.findViewById(R.id.scrim_for_bubble);
- mScrimController = SystemUIFactory.getInstance().createScrimController(
- scrimBehind, scrimInFront, scrimForBubble, mLockscreenWallpaper,
- (state, alpha, color) -> mLightBarController.setScrimState(state, alpha, color),
- scrimsVisible -> {
- if (mStatusBarWindowController != null) {
- mStatusBarWindowController.setScrimsVisibility(scrimsVisible);
- }
- if (mStatusBarWindow != null) {
- mStatusBarWindow.onScrimVisibilityChanged(scrimsVisible);
- }
- }, DozeParameters.getInstance(mContext),
- mContext.getSystemService(AlarmManager.class),
- mKeyguardMonitor);
+ mScrimController.setScrimVisibleListener(scrimsVisible -> {
+ mStatusBarWindowController.setScrimsVisibility(scrimsVisible);
+ if (mStatusBarWindow != null) {
+ mStatusBarWindowViewController.onScrimVisibilityChanged(scrimsVisible);
+ }
+ });
+ mScrimController.attachViews(scrimBehind, scrimInFront, scrimForBubble);
+
mNotificationPanel.initDependencies(this, mGroupManager, mNotificationShelf,
mHeadsUpManager, mNotificationIconAreaController, mScrimController);
- mDozeScrimController = new DozeScrimController(DozeParameters.getInstance(context));
BackDropView backdrop = mStatusBarWindow.findViewById(R.id.backdrop);
mMediaManager.setup(backdrop, backdrop.findViewById(R.id.backdrop_front),
@@ -977,7 +1086,7 @@ public class StatusBar extends SystemUI implements DemoMode,
}
mNotificationPanel.setLaunchAffordanceListener(
- mStatusBarWindow::onShowingLaunchAffordanceChanged);
+ mStatusBarWindowViewController::onShowingLaunchAffordanceChanged);
// Set up the quick settings tile panel
View container = mStatusBarWindow.findViewById(R.id.qs_frame);
@@ -1032,11 +1141,10 @@ public class StatusBar extends SystemUI implements DemoMode,
});
}
- PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
- if (!pm.isScreenOn()) {
+ if (!mPowerManager.isScreenOn()) {
mBroadcastReceiver.onReceive(mContext, new Intent(Intent.ACTION_SCREEN_OFF));
}
- mGestureWakeLock = pm.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK,
+ mGestureWakeLock = mPowerManager.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK,
"GestureWakeLock");
mVibrator = mContext.getSystemService(Vibrator.class);
int[] pattern = mContext.getResources().getIntArray(
@@ -1047,11 +1155,7 @@ public class StatusBar extends SystemUI implements DemoMode,
}
// receive broadcasts
- IntentFilter filter = new IntentFilter();
- filter.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
- filter.addAction(Intent.ACTION_SCREEN_OFF);
- filter.addAction(DevicePolicyManager.ACTION_SHOW_DEVICE_MONITORING_DIALOG);
- context.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL, filter, null, null);
+ registerBroadcastReceiver();
IntentFilter demoFilter = new IntentFilter();
if (DEBUG_MEDIA_FAKE_ARTWORK) {
@@ -1072,6 +1176,15 @@ public class StatusBar extends SystemUI implements DemoMode,
ThreadedRenderer.overrideProperty("ambientRatio", String.valueOf(1.5f));
}
+ @VisibleForTesting
+ protected void registerBroadcastReceiver() {
+ IntentFilter filter = new IntentFilter();
+ filter.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
+ filter.addAction(Intent.ACTION_SCREEN_OFF);
+ filter.addAction(DevicePolicyManager.ACTION_SHOW_DEVICE_MONITORING_DIALOG);
+ mBroadcastDispatcher.registerReceiver(mBroadcastReceiver, filter, null, UserHandle.ALL);
+ }
+
protected QS createDefaultQSFragment() {
return FragmentHostManager.get(mStatusBarWindow).create(QSFragment.class);
}
@@ -1079,7 +1192,7 @@ public class StatusBar extends SystemUI implements DemoMode,
private void setUpPresenter() {
// Set up the initial notification state.
mActivityLaunchAnimator = new ActivityLaunchAnimator(
- mStatusBarWindow, this, mNotificationPanel,
+ mStatusBarWindowViewController, this, mNotificationPanel,
(NotificationListContainer) mStackScroller);
final NotificationRowBinderImpl rowBinder =
@@ -1087,12 +1200,13 @@ public class StatusBar extends SystemUI implements DemoMode,
mContext,
mAllowNotificationLongPress,
mKeyguardBypassController,
- mStatusBarStateController);
+ mStatusBarStateController,
+ mNotifLog);
mPresenter = new StatusBarNotificationPresenter(mContext, mNotificationPanel,
mHeadsUpManager, mStatusBarWindow, mStackScroller, mDozeScrimController,
mScrimController, mActivityLaunchAnimator, mDynamicPrivacyController,
- mNotificationAlertingManager, rowBinder);
+ mNotificationAlertingManager, rowBinder, mKeyguardStateController);
mNotificationListController =
new NotificationListController(
@@ -1108,7 +1222,6 @@ public class StatusBar extends SystemUI implements DemoMode,
final StatusBarRemoteInputCallback mStatusBarRemoteInputCallback =
(StatusBarRemoteInputCallback) Dependency.get(
NotificationRemoteInputManager.Callback.class);
- mShadeController = Dependency.get(ShadeController.class);
final ActivityStarter activityStarter = Dependency.get(ActivityStarter.class);
mNotificationActivityStarter = new StatusBarNotificationActivityStarter(mContext,
@@ -1116,7 +1229,7 @@ public class StatusBar extends SystemUI implements DemoMode,
mHeadsUpManager, activityStarter, mActivityLaunchAnimator,
mBarService, mStatusBarStateController, mKeyguardManager, mDreamManager,
mRemoteInputManager, mStatusBarRemoteInputCallback, mGroupManager,
- mLockscreenUserManager, mShadeController, mKeyguardMonitor,
+ mLockscreenUserManager, this, mKeyguardStateController,
mNotificationInterruptionStateProvider, mMetricsLogger,
new LockPatternUtils(mContext), Dependency.get(MAIN_HANDLER),
Dependency.get(BG_HANDLER), mActivityIntentHelper, mBubbleController);
@@ -1125,10 +1238,14 @@ public class StatusBar extends SystemUI implements DemoMode,
mEntryManager.setRowBinder(rowBinder);
rowBinder.setNotificationClicker(new NotificationClicker(
- this, Dependency.get(BubbleController.class), mNotificationActivityStarter));
+ this, mBubbleController, mNotificationActivityStarter));
mGroupAlertTransferHelper.bind(mEntryManager, mGroupManager);
mNotificationListController.bind();
+
+ if (mFeatureFlags.isNewNotifPipelineEnabled()) {
+ mNewNotifPipeline.get().initialize(mNotificationListener);
+ }
}
/**
@@ -1153,8 +1270,8 @@ public class StatusBar extends SystemUI implements DemoMode,
@Override
public void wakeUpIfDozing(long time, View where, String why) {
if (mDozing) {
- PowerManager pm = mContext.getSystemService(PowerManager.class);
- pm.wakeUp(time, PowerManager.WAKE_REASON_GESTURE, "com.android.systemui:" + why);
+ mPowerManager.wakeUp(
+ time, PowerManager.WAKE_REASON_GESTURE, "com.android.systemui:" + why);
mWakeUpComingFromTouch = true;
where.getLocationInWindow(mTmpInt2);
mWakeUpTouchLocation = new PointF(mTmpInt2[0] + where.getWidth() / 2,
@@ -1250,17 +1367,16 @@ public class StatusBar extends SystemUI implements DemoMode,
protected void inflateStatusBarWindow(Context context) {
mStatusBarWindow = (StatusBarWindowView) mInjectionInflater.injectable(
LayoutInflater.from(context)).inflate(R.layout.super_status_bar, null);
+ mStatusBarWindowViewController = mStatusBarWindowViewControllerBuilder
+ .setStatusBarWindowView(mStatusBarWindow)
+ .setShadeController(this)
+ .build();
}
protected void startKeyguard() {
Trace.beginSection("StatusBar#startKeyguard");
- KeyguardViewMediator keyguardViewMediator = getComponent(KeyguardViewMediator.class);
- mBiometricUnlockController = new BiometricUnlockController(mContext,
- mDozeScrimController, keyguardViewMediator,
- mScrimController, this, UnlockMethodCache.getInstance(mContext),
- new Handler(), mKeyguardUpdateMonitor, mKeyguardBypassController);
- putComponent(BiometricUnlockController.class, mBiometricUnlockController);
- mStatusBarKeyguardViewManager = keyguardViewMediator.registerStatusBar(this,
+ mBiometricUnlockController = mBiometricUnlockControllerLazy.get();
+ mStatusBarKeyguardViewManager = mKeyguardViewMediator.registerStatusBar(this,
getBouncerContainer(), mNotificationPanel, mBiometricUnlockController,
mStatusBarWindow.findViewById(R.id.lock_icon_container), mStackScroller,
mKeyguardBypassController);
@@ -1270,7 +1386,7 @@ public class StatusBar extends SystemUI implements DemoMode,
mRemoteInputManager.getController().addCallback(mStatusBarKeyguardViewManager);
mDynamicPrivacyController.setStatusBarKeyguardViewManager(mStatusBarKeyguardViewManager);
- mKeyguardViewMediatorCallback = keyguardViewMediator.getViewMediatorCallback();
+ mKeyguardViewMediatorCallback = mKeyguardViewMediator.getViewMediatorCallback();
mLightBarController.setBiometricUnlockController(mBiometricUnlockController);
mMediaManager.setBiometricUnlockController(mBiometricUnlockController);
Dependency.get(KeyguardDismissUtil.class).setDismissHandler(this::executeWhenUnlocked);
@@ -1366,15 +1482,19 @@ public class StatusBar extends SystemUI implements DemoMode,
return mZenController.areNotificationsHiddenInShade();
}
- public void requestNotificationUpdate() {
- mEntryManager.updateNotifications();
+ /**
+ * Request a notification update
+ * @param reason why we're requesting a notification update
+ */
+ public void requestNotificationUpdate(String reason) {
+ mEntryManager.updateNotifications(reason);
}
/**
* Asks {@link KeyguardUpdateMonitor} to run face auth.
*/
public void requestFaceAuth() {
- if (!mUnlockMethodCache.canSkipBouncer()) {
+ if (!mKeyguardStateController.canDismissLockScreen()) {
mKeyguardUpdateMonitor.requestFaceAuth();
}
}
@@ -1558,9 +1678,8 @@ public class StatusBar extends SystemUI implements DemoMode,
logStateToEventlog();
}
- @Override // UnlockMethodCache.OnUnlockMethodChangedListener
- public void onUnlockMethodStateChanged() {
- // Unlock method state changed. Notify KeguardMonitor
+ @Override
+ public void onUnlockedChanged() {
updateKeyguardState();
logStateToEventlog();
}
@@ -1609,11 +1728,11 @@ public class StatusBar extends SystemUI implements DemoMode,
@Override
public void onHeadsUpStateChanged(NotificationEntry entry, boolean isHeadsUp) {
- mEntryManager.updateNotifications();
+ mEntryManager.updateNotifications("onHeadsUpStateChanged");
if (isDozing() && isHeadsUp) {
entry.setPulseSuppressed(false);
mDozeServiceHost.fireNotificationPulse(entry);
- if (mPulsing) {
+ if (mDozeServiceHost.isPulsing()) {
mDozeScrimController.cancelPendingPulseTimeout();
}
}
@@ -1623,10 +1742,6 @@ public class StatusBar extends SystemUI implements DemoMode,
}
}
- public boolean isKeyguardCurrentlySecure() {
- return !mUnlockMethodCache.canSkipBouncer();
- }
-
public void setPanelExpanded(boolean isExpanded) {
mPanelExpanded = isExpanded;
updateHideIconsForBouncer(false /* animate */);
@@ -1649,7 +1764,7 @@ public class StatusBar extends SystemUI implements DemoMode,
}
public boolean isPulsing() {
- return mPulsing;
+ return mDozeServiceHost.isPulsing();
}
public boolean hideStatusBarIconsWhenExpanded() {
@@ -1761,6 +1876,16 @@ public class StatusBar extends SystemUI implements DemoMode,
return mPresenter;
}
+ @VisibleForTesting
+ void setBarStateForTest(int state) {
+ mState = state;
+ }
+
+ @VisibleForTesting
+ void setUserSetupForTest(boolean userSetup) {
+ mUserSetup = userSetup;
+ }
+
/**
* All changes to the status bar and notifications funnel through here and are batched.
*/
@@ -1793,7 +1918,7 @@ public class StatusBar extends SystemUI implements DemoMode,
public void maybeEscalateHeadsUp() {
mHeadsUpManager.getAllEntries().forEach(entry -> {
- final StatusBarNotification sbn = entry.notification;
+ final StatusBarNotification sbn = entry.getSbn();
final Notification notification = sbn.getNotification();
if (notification.fullScreenIntent != null) {
if (DEBUG) {
@@ -1818,8 +1943,8 @@ public class StatusBar extends SystemUI implements DemoMode,
@Override
public void handleSystemKey(int key) {
if (SPEW) Log.d(TAG, "handleNavigationKey: " + key);
- if (!mCommandQueue.panelsEnabled() || !mKeyguardMonitor.isDeviceInteractive()
- || mKeyguardMonitor.isShowing() && !mKeyguardMonitor.isOccluded()) {
+ if (!mCommandQueue.panelsEnabled() || !mKeyguardUpdateMonitor.isDeviceInteractive()
+ || mKeyguardStateController.isShowing() && !mKeyguardStateController.isOccluded()) {
return;
}
@@ -1948,7 +2073,7 @@ public class StatusBar extends SystemUI implements DemoMode,
// release focus immediately to kick off focus change transition
mStatusBarWindowController.setStatusBarFocusable(false);
- mStatusBarWindow.cancelExpandHelper();
+ mStatusBarWindowViewController.cancelExpandHelper();
mStatusBarView.collapsePanel(true /* animate */, delayed, speedUpFactor);
} else {
mBubbleController.collapseStack();
@@ -2128,49 +2253,104 @@ public class StatusBar extends SystemUI implements DemoMode,
}
}
- @Override // CommandQueue
- public void setSystemUiVisibility(int displayId, int vis, int fullscreenStackVis,
- int dockedStackVis, int mask, Rect fullscreenStackBounds, Rect dockedStackBounds,
- boolean navbarColorManagedByIme) {
+ @Override
+ public void onSystemBarAppearanceChanged(int displayId, @Appearance int appearance,
+ AppearanceRegion[] appearanceRegions, boolean navbarColorManagedByIme) {
if (displayId != mDisplayId) {
return;
}
- final int oldVal = mSystemUiVisibility;
- final int newVal = (oldVal&~mask) | (vis&mask);
- final int diff = newVal ^ oldVal;
- if (DEBUG) Log.d(TAG, String.format(
- "setSystemUiVisibility displayId=%d vis=%s mask=%s oldVal=%s newVal=%s diff=%s",
- displayId, Integer.toHexString(vis), Integer.toHexString(mask),
- Integer.toHexString(oldVal), Integer.toHexString(newVal),
- Integer.toHexString(diff)));
- boolean sbModeChanged = false;
- if (diff != 0) {
- mSystemUiVisibility = newVal;
+ boolean barModeChanged = false;
+ final int diff = mAppearance ^ appearance;
+ if (mAppearance != appearance) {
+ mAppearance = appearance;
// update low profile
- if ((diff & View.SYSTEM_UI_FLAG_LOW_PROFILE) != 0) {
+ if ((diff & APPEARANCE_LOW_PROFILE_BARS) != 0) {
updateAreThereNotifications();
}
+ barModeChanged = updateBarMode(barMode(mTransientShown, appearance));
+ }
+ mLightBarController.onStatusBarAppearanceChanged(appearanceRegions, barModeChanged,
+ mStatusBarMode, navbarColorManagedByIme);
+ }
- // ready to unhide
- if ((vis & View.STATUS_BAR_UNHIDE) != 0) {
- mNoAnimationOnNextBarModeChange = true;
- }
+ @Override
+ public void showTransient(int displayId, @InternalInsetType int[] types) {
+ if (displayId != mDisplayId) {
+ return;
+ }
+ if (!containsType(types, TYPE_TOP_BAR)) {
+ return;
+ }
+ showTransientUnchecked();
+ }
- // update status bar mode
- final int sbMode = computeStatusBarMode(oldVal, newVal);
+ private void showTransientUnchecked() {
+ if (!mTransientShown) {
+ mTransientShown = true;
+ mNoAnimationOnNextBarModeChange = true;
+ handleTransientChanged();
+ }
+ }
- sbModeChanged = sbMode != -1;
- if (sbModeChanged && sbMode != mStatusBarMode) {
- mStatusBarMode = sbMode;
- checkBarModes();
- mAutoHideController.touchAutoHide();
- }
- mStatusBarStateController.setSystemUiVisibility(mSystemUiVisibility);
+ @Override
+ public void abortTransient(int displayId, @InternalInsetType int[] types) {
+ if (displayId != mDisplayId) {
+ return;
+ }
+ if (!containsType(types, TYPE_TOP_BAR)) {
+ return;
}
- mLightBarController.onSystemUiVisibilityChanged(fullscreenStackVis, dockedStackVis,
- mask, fullscreenStackBounds, dockedStackBounds, sbModeChanged, mStatusBarMode,
- navbarColorManagedByIme);
+ clearTransient();
+ }
+
+ void clearTransient() {
+ if (mTransientShown) {
+ mTransientShown = false;
+ handleTransientChanged();
+ }
+ }
+
+ private void handleTransientChanged() {
+ final int barMode = barMode(mTransientShown, mAppearance);
+ if (updateBarMode(barMode)) {
+ mLightBarController.onStatusBarModeChanged(barMode);
+ }
+ }
+
+ private boolean updateBarMode(int barMode) {
+ if (mStatusBarMode != barMode) {
+ mStatusBarMode = barMode;
+ checkBarModes();
+ mAutoHideController.touchAutoHide();
+ return true;
+ }
+ return false;
+ }
+
+ private static @TransitionMode int barMode(boolean isTransient, int appearance) {
+ final int lightsOutOpaque = APPEARANCE_LOW_PROFILE_BARS | APPEARANCE_OPAQUE_TOP_BAR;
+ if (isTransient) {
+ return MODE_SEMI_TRANSPARENT;
+ } else if ((appearance & lightsOutOpaque) == lightsOutOpaque) {
+ return MODE_LIGHTS_OUT;
+ } else if ((appearance & APPEARANCE_LOW_PROFILE_BARS) != 0) {
+ return MODE_LIGHTS_OUT_TRANSPARENT;
+ } else if ((appearance & APPEARANCE_OPAQUE_TOP_BAR) != 0) {
+ return MODE_OPAQUE;
+ } else {
+ return MODE_TRANSPARENT;
+ }
+ }
+
+ @Override
+ public void topAppWindowChanged(int displayId, boolean isFullscreen, boolean isImmersive) {
+ if (displayId != mDisplayId) {
+ return;
+ }
+ mAppFullscreen = isFullscreen;
+ mAppImmersive = isImmersive;
+ mStatusBarStateController.setFullscreenState(isFullscreen, isImmersive);
}
@Override
@@ -2201,40 +2381,10 @@ public class StatusBar extends SystemUI implements DemoMode,
setInteracting(StatusBarManager.WINDOW_NAVIGATION_BAR, running);
}
- protected @TransitionMode int computeStatusBarMode(int oldVal, int newVal) {
- return computeBarMode(oldVal, newVal);
- }
-
protected BarTransitions getStatusBarTransitions() {
return mStatusBarView.getBarTransitions();
}
- protected @TransitionMode int computeBarMode(int oldVis, int newVis) {
- final int oldMode = barMode(oldVis);
- final int newMode = barMode(newVis);
- if (oldMode == newMode) {
- return -1; // no mode change
- }
- return newMode;
- }
-
- private @TransitionMode int barMode(int vis) {
- int lightsOutTransparent = View.SYSTEM_UI_FLAG_LOW_PROFILE | View.STATUS_BAR_TRANSPARENT;
- if ((vis & View.STATUS_BAR_TRANSIENT) != 0) {
- return MODE_SEMI_TRANSPARENT;
- } else if ((vis & View.STATUS_BAR_TRANSLUCENT) != 0) {
- return MODE_TRANSLUCENT;
- } else if ((vis & lightsOutTransparent) == lightsOutTransparent) {
- return MODE_LIGHTS_OUT_TRANSPARENT;
- } else if ((vis & View.STATUS_BAR_TRANSPARENT) != 0) {
- return MODE_TRANSPARENT;
- } else if ((vis & View.SYSTEM_UI_FLAG_LOW_PROFILE) != 0) {
- return MODE_LIGHTS_OUT;
- } else {
- return MODE_OPAQUE;
- }
- }
-
void checkBarModes() {
if (mDemoMode) return;
if (mStatusBarView != null) checkBarMode(mStatusBarMode, mStatusBarWindowState,
@@ -2290,20 +2440,16 @@ public class StatusBar extends SystemUI implements DemoMode,
/** Returns whether the top activity is in fullscreen mode. */
public boolean inFullscreenMode() {
- return 0
- != (mSystemUiVisibility
- & (View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION));
+ return mAppFullscreen;
}
/** Returns whether the top activity is in immersive mode. */
public boolean inImmersiveMode() {
- return 0
- != (mSystemUiVisibility
- & (View.SYSTEM_UI_FLAG_IMMERSIVE | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY));
+ return mAppImmersive;
}
private boolean areLightsOn() {
- return 0 == (mSystemUiVisibility & View.SYSTEM_UI_FLAG_LOW_PROFILE);
+ return 0 == (mAppearance & APPEARANCE_LOW_PROFILE_BARS);
}
public static String viewInfo(View v) {
@@ -2339,8 +2485,8 @@ public class StatusBar extends SystemUI implements DemoMode,
dumpBarTransitions(pw, "mStatusBarView", mStatusBarView.getBarTransitions());
}
pw.println(" StatusBarWindowView: ");
- if (mStatusBarWindow != null) {
- mStatusBarWindow.dump(fd, pw, args);
+ if (mStatusBarWindowViewController != null) {
+ mStatusBarWindowViewController.dump(fd, pw, args);
}
pw.println(" mMediaManager: ");
@@ -2369,7 +2515,7 @@ public class StatusBar extends SystemUI implements DemoMode,
final boolean lightWpTheme = mContext.getThemeResId() == R.style.Theme_SystemUI_Light;
pw.println(" light wallpaper theme: " + lightWpTheme);
- DozeLog.dump(pw);
+ mDozeLog.dump(pw);
if (mBiometricUnlockController != null) {
mBiometricUnlockController.dump(pw);
@@ -2428,10 +2574,6 @@ public class StatusBar extends SystemUI implements DemoMode,
mLightBarController.dump(fd, pw, args);
}
- if (mUnlockMethodCache != null) {
- mUnlockMethodCache.dump(pw);
- }
-
if (mKeyguardBypassController != null) {
mKeyguardBypassController.dump(pw);
}
@@ -2440,7 +2582,7 @@ public class StatusBar extends SystemUI implements DemoMode,
mKeyguardUpdateMonitor.dump(fd, pw, args);
}
- Dependency.get(FalsingManager.class).dump(pw);
+ mFalsingManager.dump(pw);
FalsingLog.dump(pw);
pw.println("SharedPreferences:");
@@ -2456,7 +2598,6 @@ public class StatusBar extends SystemUI implements DemoMode,
public void createAndAddWindows(@Nullable RegisterStatusBarResult result) {
makeStatusBarView(result);
- mStatusBarWindowController = Dependency.get(StatusBarWindowController.class);
mStatusBarWindowController.add(mStatusBarWindow, getStatusBarHeight());
}
@@ -2684,9 +2825,9 @@ public class StatusBar extends SystemUI implements DemoMode,
public void dismissKeyguardThenExecute(OnDismissAction action, Runnable cancelAction,
boolean afterKeyguardGone) {
if (mWakefulnessLifecycle.getWakefulness() == WAKEFULNESS_ASLEEP
- && mUnlockMethodCache.canSkipBouncer()
+ && mKeyguardStateController.canDismissLockScreen()
&& !mStatusBarStateController.leaveOpenOnKeyguardHide()
- && isPulsing()) {
+ && mDozeServiceHost.isPulsing()) {
// Reuse the biometric wake-and-unlock transition if we dismiss keyguard from a pulse.
// TODO: Factor this transition out of BiometricUnlockController.
mBiometricUnlockController.startWakeAndUnlock(
@@ -2700,7 +2841,6 @@ public class StatusBar extends SystemUI implements DemoMode,
}
}
- // SystemUIService notifies SystemBars of configuration changes, which then calls down here
@Override
public void onConfigChanged(Configuration newConfig) {
updateResources();
@@ -2827,14 +2967,14 @@ public class StatusBar extends SystemUI implements DemoMode,
boolean isShowing = mStatusBarKeyguardViewManager.isShowing();
boolean isOccluded = mStatusBarKeyguardViewManager.isOccluded();
boolean isBouncerShowing = mStatusBarKeyguardViewManager.isBouncerShowing();
- boolean isSecure = mUnlockMethodCache.isMethodSecure();
- boolean canSkipBouncer = mUnlockMethodCache.canSkipBouncer();
+ boolean isSecure = mKeyguardStateController.isMethodSecure();
+ boolean unlocked = mKeyguardStateController.canDismissLockScreen();
int stateFingerprint = getLoggingFingerprint(mState,
isShowing,
isOccluded,
isBouncerShowing,
isSecure,
- canSkipBouncer);
+ unlocked);
if (stateFingerprint != mLastLoggedStateFingerprint) {
if (mStatusBarStateLog == null) {
mStatusBarStateLog = new LogMaker(MetricsEvent.VIEW_UNKNOWN);
@@ -2848,7 +2988,7 @@ public class StatusBar extends SystemUI implements DemoMode,
isOccluded ? 1 : 0,
isBouncerShowing ? 1 : 0,
isSecure ? 1 : 0,
- canSkipBouncer ? 1 : 0);
+ unlocked ? 1 : 0);
mLastLoggedStateFingerprint = stateFingerprint;
}
}
@@ -3018,7 +3158,7 @@ public class StatusBar extends SystemUI implements DemoMode,
return mState == StatusBarState.FULLSCREEN_USER_SWITCHER;
}
- private boolean updateIsKeyguard() {
+ boolean updateIsKeyguard() {
boolean wakeAndUnlocking = mBiometricUnlockController.getMode()
== BiometricUnlockController.MODE_WAKE_AND_UNLOCK;
@@ -3026,8 +3166,8 @@ public class StatusBar extends SystemUI implements DemoMode,
// there's no surface we can show to the user. Note that the device goes fully interactive
// late in the transition, so we also allow the device to start dozing once the screen has
// turned off fully.
- boolean keyguardForDozing = mDozingRequested &&
- (!mDeviceInteractive || isGoingToSleep() && (isScreenFullyOff() || mIsKeyguard));
+ boolean keyguardForDozing = mDozeServiceHost.getDozingRequested()
+ && (!mDeviceInteractive || isGoingToSleep() && (isScreenFullyOff() || mIsKeyguard));
boolean shouldBeKeyguard = (mStatusBarStateController.isKeyguardRequested()
|| keyguardForDozing) && !wakeAndUnlocking;
if (keyguardForDozing) {
@@ -3048,7 +3188,7 @@ public class StatusBar extends SystemUI implements DemoMode,
public void showKeyguardImpl() {
mIsKeyguard = true;
- if (mKeyguardMonitor.isLaunchTransitionFadingAway()) {
+ if (mKeyguardStateController.isLaunchTransitionFadingAway()) {
mNotificationPanel.animate().cancel();
onLaunchTransitionFadingEnded();
}
@@ -3080,7 +3220,7 @@ public class StatusBar extends SystemUI implements DemoMode,
mNotificationPanel.onAffordanceLaunchEnded();
releaseGestureWakeLock();
runLaunchTransitionEndRunnable();
- mKeyguardMonitor.setLaunchTransitionFadingAway(false);
+ mKeyguardStateController.setLaunchTransitionFadingAway(false);
mPresenter.updateMediaMetaData(true /* metaDataChanged */, true);
}
@@ -3105,7 +3245,7 @@ public class StatusBar extends SystemUI implements DemoMode,
mHandler.removeMessages(MSG_LAUNCH_TRANSITION_TIMEOUT);
mLaunchTransitionEndRunnable = endRunnable;
Runnable hideRunnable = () -> {
- mKeyguardMonitor.setLaunchTransitionFadingAway(true);
+ mKeyguardStateController.setLaunchTransitionFadingAway(true);
if (beforeFading != null) {
beforeFading.run();
}
@@ -3198,7 +3338,7 @@ public class StatusBar extends SystemUI implements DemoMode,
if (!mStatusBarStateController.isKeyguardRequested()) {
mStatusBarStateController.setLeaveOpenOnKeyguardHide(false);
}
- long delay = mKeyguardMonitor.calculateGoingToFullShadeDelay();
+ long delay = mKeyguardStateController.calculateGoingToFullShadeDelay();
mNotificationPanel.animateToFullShade(delay);
if (mDraggedDownEntry != null) {
mDraggedDownEntry.setUserLocked(false);
@@ -3240,7 +3380,7 @@ public class StatusBar extends SystemUI implements DemoMode,
public void keyguardGoingAway() {
// Treat Keyguard exit animation as an app transition to achieve nice transition for status
// bar.
- mKeyguardMonitor.notifyKeyguardGoingAway(true);
+ mKeyguardStateController.notifyKeyguardGoingAway(true);
mCommandQueue.appTransitionPending(mDisplayId, true /* forced */);
}
@@ -3260,14 +3400,14 @@ public class StatusBar extends SystemUI implements DemoMode,
mCommandQueue.appTransitionStarting(mDisplayId,
startTime - LightBarTransitionsController.DEFAULT_TINT_ANIMATION_DURATION,
LightBarTransitionsController.DEFAULT_TINT_ANIMATION_DURATION, true);
- mKeyguardMonitor.notifyKeyguardFadingAway(delay, fadeoutDuration, isBypassFading);
+ mKeyguardStateController.notifyKeyguardFadingAway(delay, fadeoutDuration, isBypassFading);
}
/**
* Notifies that the Keyguard fading away animation is done.
*/
public void finishKeyguardFadingAway() {
- mKeyguardMonitor.notifyKeyguardDoneFading();
+ mKeyguardStateController.notifyKeyguardDoneFading();
mScrimController.setExpansionAffectsAlpha(true);
}
@@ -3282,7 +3422,7 @@ public class StatusBar extends SystemUI implements DemoMode,
final int themeResId = lockDarkText ? R.style.Theme_SystemUI_Light : R.style.Theme_SystemUI;
if (mContext.getThemeResId() != themeResId) {
mContext.setTheme(themeResId);
- Dependency.get(ConfigurationController.class).notifyThemeChanged();
+ mConfigurationController.notifyThemeChanged();
}
}
@@ -3443,7 +3583,7 @@ public class StatusBar extends SystemUI implements DemoMode,
public void onStateChanged(int newState) {
mState = newState;
updateReportRejectedTouchVisibility();
- updateDozing();
+ mDozeServiceHost.updateDozing();
updateTheme();
mNavigationBarController.touchAutoDim(mDisplayId);
Trace.beginSection("StatusBar#updateKeyguardState");
@@ -3481,40 +3621,25 @@ public class StatusBar extends SystemUI implements DemoMode,
public void onDozingChanged(boolean isDozing) {
Trace.beginSection("StatusBar#updateDozing");
mDozing = isDozing;
+ mDozeServiceHost.setDozing(mDozing);
// Collapse the notification panel if open
- boolean dozingAnimated = mDozingRequested
- && DozeParameters.getInstance(mContext).shouldControlScreenOff();
+ boolean dozingAnimated = mDozeServiceHost.getDozingRequested()
+ && mDozeParameters.shouldControlScreenOff();
mNotificationPanel.resetViews(dozingAnimated);
updateQsExpansionEnabled();
mKeyguardViewMediator.setDozing(mDozing);
- mEntryManager.updateNotifications();
- updateDozingState();
+ mEntryManager.updateNotifications("onDozingChanged");
+ mDozeServiceHost.updateDozing();
updateScrimController();
updateReportRejectedTouchVisibility();
Trace.endSection();
}
- private void updateDozing() {
- // When in wake-and-unlock while pulsing, keep dozing state until fully unlocked.
- boolean dozing = mDozingRequested && mState == StatusBarState.KEYGUARD
- || mBiometricUnlockController.getMode()
- == BiometricUnlockController.MODE_WAKE_AND_UNLOCK_PULSING;
- // When in wake-and-unlock we may not have received a change to mState
- // but we still should not be dozing, manually set to false.
- if (mBiometricUnlockController.getMode() ==
- BiometricUnlockController.MODE_WAKE_AND_UNLOCK) {
- dozing = false;
- }
-
- mStatusBarStateController.setIsDozing(dozing);
- }
-
private void updateKeyguardState() {
- mKeyguardMonitor.notifyKeyguardState(mStatusBarKeyguardViewManager.isShowing(),
- mUnlockMethodCache.isMethodSecure(),
+ mKeyguardStateController.notifyKeyguardState(mStatusBarKeyguardViewManager.isShowing(),
mStatusBarKeyguardViewManager.isOccluded());
}
@@ -3562,7 +3687,7 @@ public class StatusBar extends SystemUI implements DemoMode,
public void onTrackingStopped(boolean expand) {
if (mState == StatusBarState.KEYGUARD || mState == StatusBarState.SHADE_LOCKED) {
- if (!expand && !mUnlockMethodCache.canSkipBouncer()) {
+ if (!expand && !mKeyguardStateController.canDismissLockScreen()) {
showBouncer(false /* scrimmed */);
}
}
@@ -3602,9 +3727,7 @@ public class StatusBar extends SystemUI implements DemoMode,
// Indicate that the group expansion is changing at this time -- this way the group
// and children backgrounds / divider animations will look correct.
entry.setGroupExpansionChanging(true);
- if (entry.notification != null) {
- userId = entry.notification.getUserId();
- }
+ userId = entry.getSbn().getUserId();
}
boolean fullShadeNeedsBouncer = !mLockscreenUserManager.
userAllowsPrivateNotificationsInPublic(mLockscreenUserManager.getCurrentUserId())
@@ -3640,7 +3763,7 @@ public class StatusBar extends SystemUI implements DemoMode,
mBouncerShowing = bouncerShowing;
mKeyguardBypassController.setBouncerShowing(bouncerShowing);
mPulseExpansionHandler.setBouncerShowing(bouncerShowing);
- mStatusBarWindow.setBouncerShowingScrimmed(isBouncerShowingScrimmed());
+ mStatusBarWindowViewController.setBouncerShowingScrimmed(isBouncerShowingScrimmed());
if (mStatusBarView != null) mStatusBarView.setBouncerShowing(bouncerShowing);
updateHideIconsForBouncer(true /* animate */);
mCommandQueue.recomputeDisableFlags(mDisplayId, true /* animate */);
@@ -3655,7 +3778,7 @@ public class StatusBar extends SystemUI implements DemoMode,
*/
public void collapseShade() {
if (mNotificationPanel.isTracking()) {
- mStatusBarWindow.cancelCurrentTouch();
+ mStatusBarWindowViewController.cancelCurrentTouch();
}
if (mPanelExpanded && mState == StatusBarState.SHADE) {
animateCollapsePanels();
@@ -3676,7 +3799,7 @@ public class StatusBar extends SystemUI implements DemoMode,
updateVisibleToUser();
updateNotificationPanelTouchState();
- mStatusBarWindow.cancelCurrentTouch();
+ mStatusBarWindowViewController.cancelCurrentTouch();
if (mLaunchCameraOnFinishedGoingToSleep) {
mLaunchCameraOnFinishedGoingToSleep = false;
@@ -3739,10 +3862,11 @@ public class StatusBar extends SystemUI implements DemoMode,
* collapse the panel after we expanded it, and thus we would end up with a blank
* Keyguard.
*/
- private void updateNotificationPanelTouchState() {
+ void updateNotificationPanelTouchState() {
boolean goingToSleepWithoutAnimation = isGoingToSleep()
- && !DozeParameters.getInstance(mContext).shouldControlScreenOff();
- boolean disabled = (!mDeviceInteractive && !mPulsing) || goingToSleepWithoutAnimation;
+ && !mDozeParameters.shouldControlScreenOff();
+ boolean disabled = (!mDeviceInteractive && !mDozeServiceHost.isPulsing())
+ || goingToSleepWithoutAnimation;
mNotificationPanel.setTouchAndAnimationDisabled(disabled);
mNotificationIconAreaController.setAnimationsEnabled(!disabled);
}
@@ -3787,7 +3911,7 @@ public class StatusBar extends SystemUI implements DemoMode,
@Override
public void showScreenPinningRequest(int taskId) {
- if (mKeyguardMonitor.isShowing()) {
+ if (mKeyguardStateController.isShowing()) {
// Don't allow apps to trigger this from keyguard.
return;
}
@@ -3830,8 +3954,7 @@ public class StatusBar extends SystemUI implements DemoMode,
return;
}
if (!mDeviceInteractive) {
- PowerManager pm = mContext.getSystemService(PowerManager.class);
- pm.wakeUp(SystemClock.uptimeMillis(), PowerManager.WAKE_REASON_CAMERA_LAUNCH,
+ mPowerManager.wakeUp(SystemClock.uptimeMillis(), PowerManager.WAKE_REASON_CAMERA_LAUNCH,
"com.android.systemui:CAMERA_GESTURE");
}
vibrateForCameraGesture();
@@ -3870,20 +3993,17 @@ public class StatusBar extends SystemUI implements DemoMode,
}
boolean isCameraAllowedByAdmin() {
- // TODO(b/140060745)
- return whitelistIpcs(() -> {
- if (mDevicePolicyManager.getCameraDisabled(null,
- mLockscreenUserManager.getCurrentUserId())) {
- return false;
- } else if (mStatusBarKeyguardViewManager == null
- || (isKeyguardShowing() && isKeyguardSecure())) {
- // Check if the admin has disabled the camera specifically for the keyguard
- return (mDevicePolicyManager.getKeyguardDisabledFeatures(null,
- mLockscreenUserManager.getCurrentUserId())
- & DevicePolicyManager.KEYGUARD_DISABLE_SECURE_CAMERA) == 0;
- }
- return true;
- });
+ if (mDevicePolicyManager.getCameraDisabled(null,
+ mLockscreenUserManager.getCurrentUserId())) {
+ return false;
+ } else if (mStatusBarKeyguardViewManager == null
+ || (isKeyguardShowing() && isKeyguardSecure())) {
+ // Check if the admin has disabled the camera specifically for the keyguard
+ return (mDevicePolicyManager.getKeyguardDisabledFeatures(null,
+ mLockscreenUserManager.getCurrentUserId())
+ & DevicePolicyManager.KEYGUARD_DISABLE_SECURE_CAMERA) == 0;
+ }
+ return true;
}
private boolean isGoingToSleep() {
@@ -3897,9 +4017,10 @@ public class StatusBar extends SystemUI implements DemoMode,
}
public void notifyBiometricAuthModeChanged() {
- updateDozing();
+ mDozeServiceHost.updateDozing();
updateScrimController();
- mStatusBarWindow.onBiometricAuthModeChanged(mBiometricUnlockController.isWakeAndUnlock(),
+ mStatusBarWindowViewController.onBiometricAuthModeChanged(
+ mBiometricUnlockController.isWakeAndUnlock(),
mBiometricUnlockController.isBiometricUnlock());
}
@@ -3910,7 +4031,7 @@ public class StatusBar extends SystemUI implements DemoMode,
// We don't want to end up in KEYGUARD state when we're unlocking with
// fingerprint from doze. We should cross fade directly from black.
boolean unlocking = mBiometricUnlockController.isWakeAndUnlock()
- || mKeyguardMonitor.isKeyguardFadingAway();
+ || mKeyguardStateController.isKeyguardFadingAway();
// Do not animate the scrim expansion when triggered by the fingerprint sensor.
mScrimController.setExpansionAffectsAlpha(
@@ -3932,9 +4053,16 @@ public class StatusBar extends SystemUI implements DemoMode,
mScrimController.transitionTo(ScrimState.UNLOCKED, mUnlockScrimCallback);
} else if (mBrightnessMirrorVisible) {
mScrimController.transitionTo(ScrimState.BRIGHTNESS_MIRROR);
- } else if (isPulsing()) {
+ } else if (mDozeServiceHost.isPulsing()) {
mScrimController.transitionTo(ScrimState.PULSING,
mDozeScrimController.getScrimCallback());
+ } else if (mDozeServiceHost.hasPendingScreenOffCallback()) {
+ mScrimController.transitionTo(ScrimState.OFF, new ScrimController.Callback() {
+ @Override
+ public void onFinished() {
+ mDozeServiceHost.executePendingScreenOffCallback();
+ }
+ });
} else if (mDozing && !unlocking) {
mScrimController.transitionTo(ScrimState.AOD);
} else if (mIsKeyguard && !unlocking) {
@@ -3955,263 +4083,8 @@ public class StatusBar extends SystemUI implements DemoMode,
return mStatusBarKeyguardViewManager.isShowing();
}
- @VisibleForTesting
- final class DozeServiceHost implements DozeHost {
- private final ArrayList<Callback> mCallbacks = new ArrayList<>();
- private boolean mAnimateWakeup;
- private boolean mAnimateScreenOff;
- private boolean mIgnoreTouchWhilePulsing;
- @VisibleForTesting
- boolean mWakeLockScreenPerformsAuth = SystemProperties.getBoolean(
- "persist.sysui.wake_performs_auth", true);
-
- @Override
- public String toString() {
- return "PSB.DozeServiceHost[mCallbacks=" + mCallbacks.size() + "]";
- }
-
- public void firePowerSaveChanged(boolean active) {
- for (Callback callback : mCallbacks) {
- callback.onPowerSaveChanged(active);
- }
- }
-
- public void fireNotificationPulse(NotificationEntry entry) {
- Runnable pulseSupressedListener = () -> {
- entry.setPulseSuppressed(true);
- mNotificationIconAreaController.updateAodNotificationIcons();
- };
- for (Callback callback : mCallbacks) {
- callback.onNotificationAlerted(pulseSupressedListener);
- }
- }
-
- @Override
- public void addCallback(@NonNull Callback callback) {
- mCallbacks.add(callback);
- }
-
- @Override
- public void removeCallback(@NonNull Callback callback) {
- mCallbacks.remove(callback);
- }
-
- @Override
- public void startDozing() {
- if (!mDozingRequested) {
- mDozingRequested = true;
- DozeLog.traceDozing(mContext, mDozing);
- updateDozing();
- updateIsKeyguard();
- }else{
- mDozingRequested = true;
- }
- }
-
- @Override
- public void pulseWhileDozing(@NonNull PulseCallback callback, int reason) {
- if (reason == DozeLog.PULSE_REASON_SENSOR_LONG_PRESS) {
- mPowerManager.wakeUp(SystemClock.uptimeMillis(), PowerManager.WAKE_REASON_GESTURE,
- "com.android.systemui:LONG_PRESS");
- startAssist(new Bundle());
- return;
- }
-
- if (reason == DozeLog.PULSE_REASON_SENSOR_WAKE_LOCK_SCREEN) {
- mScrimController.setWakeLockScreenSensorActive(true);
- }
-
- if (reason == DozeLog.PULSE_REASON_DOCKING && mStatusBarWindow != null) {
- mStatusBarWindow.suppressWakeUpGesture(true);
- }
-
- boolean passiveAuthInterrupt = reason == DozeLog.PULSE_REASON_SENSOR_WAKE_LOCK_SCREEN
- && mWakeLockScreenPerformsAuth;
- // Set the state to pulsing, so ScrimController will know what to do once we ask it to
- // execute the transition. The pulse callback will then be invoked when the scrims
- // are black, indicating that StatusBar is ready to present the rest of the UI.
- mPulsing = true;
- mDozeScrimController.pulse(new PulseCallback() {
- @Override
- public void onPulseStarted() {
- callback.onPulseStarted();
- updateNotificationPanelTouchState();
- setPulsing(true);
- }
-
- @Override
- public void onPulseFinished() {
- mPulsing = false;
- callback.onPulseFinished();
- updateNotificationPanelTouchState();
- mScrimController.setWakeLockScreenSensorActive(false);
- if (mStatusBarWindow != null) {
- mStatusBarWindow.suppressWakeUpGesture(false);
- }
- setPulsing(false);
- }
-
- private void setPulsing(boolean pulsing) {
- mStatusBarStateController.setPulsing(pulsing);
- mStatusBarKeyguardViewManager.setPulsing(pulsing);
- mKeyguardViewMediator.setPulsing(pulsing);
- mNotificationPanel.setPulsing(pulsing);
- mVisualStabilityManager.setPulsing(pulsing);
- mStatusBarWindow.setPulsing(pulsing);
- mIgnoreTouchWhilePulsing = false;
- if (mKeyguardUpdateMonitor != null && passiveAuthInterrupt) {
- mKeyguardUpdateMonitor.onAuthInterruptDetected(pulsing /* active */);
- }
- updateScrimController();
- mPulseExpansionHandler.setPulsing(pulsing);
- mWakeUpCoordinator.setPulsing(pulsing);
- }
- }, reason);
- // DozeScrimController is in pulse state, now let's ask ScrimController to start
- // pulsing and draw the black frame, if necessary.
- updateScrimController();
- }
-
- @Override
- public void stopDozing() {
- if (mDozingRequested) {
- mDozingRequested = false;
- DozeLog.traceDozing(mContext, mDozing);
- updateDozing();
- }
- }
-
- @Override
- public void onIgnoreTouchWhilePulsing(boolean ignore) {
- if (ignore != mIgnoreTouchWhilePulsing) {
- DozeLog.tracePulseTouchDisabledByProx(mContext, ignore);
- }
- mIgnoreTouchWhilePulsing = ignore;
- if (isDozing() && ignore) {
- mStatusBarWindow.cancelCurrentTouch();
- }
- }
-
- @Override
- public void dozeTimeTick() {
- mNotificationPanel.dozeTimeTick();
- if (mAmbientIndicationContainer instanceof DozeReceiver) {
- ((DozeReceiver) mAmbientIndicationContainer).dozeTimeTick();
- }
- }
-
- @Override
- public boolean isPowerSaveActive() {
- return mBatteryController.isAodPowerSave();
- }
-
- @Override
- public boolean isPulsingBlocked() {
- return mBiometricUnlockController.getMode()
- == BiometricUnlockController.MODE_WAKE_AND_UNLOCK;
- }
-
- @Override
- public boolean isProvisioned() {
- return mDeviceProvisionedController.isDeviceProvisioned()
- && mDeviceProvisionedController.isCurrentUserSetup();
- }
-
- @Override
- public boolean isBlockingDoze() {
- if (mBiometricUnlockController.hasPendingAuthentication()) {
- Log.i(TAG, "Blocking AOD because fingerprint has authenticated");
- return true;
- }
- return false;
- }
-
- @Override
- public void extendPulse(int reason) {
- if (reason == DozeLog.PULSE_REASON_SENSOR_WAKE_LOCK_SCREEN) {
- mScrimController.setWakeLockScreenSensorActive(true);
- }
- if (mDozeScrimController.isPulsing() && mHeadsUpManager.hasNotifications()) {
- mHeadsUpManager.extendHeadsUp();
- } else {
- mDozeScrimController.extendPulse();
- }
- }
-
- @Override
- public void stopPulsing() {
- if (mDozeScrimController.isPulsing()) {
- mDozeScrimController.pulseOutNow();
- }
- }
-
- @Override
- public void setAnimateWakeup(boolean animateWakeup) {
- if (mWakefulnessLifecycle.getWakefulness() == WAKEFULNESS_AWAKE
- || mWakefulnessLifecycle.getWakefulness() == WAKEFULNESS_WAKING) {
- // Too late to change the wakeup animation.
- return;
- }
- mAnimateWakeup = animateWakeup;
- }
-
- @Override
- public void setAnimateScreenOff(boolean animateScreenOff) {
- mAnimateScreenOff = animateScreenOff;
- }
-
- @Override
- public void onSlpiTap(float screenX, float screenY) {
- if (screenX > 0 && screenY > 0 && mAmbientIndicationContainer != null
- && mAmbientIndicationContainer.getVisibility() == View.VISIBLE) {
- mAmbientIndicationContainer.getLocationOnScreen(mTmpInt2);
- float viewX = screenX - mTmpInt2[0];
- float viewY = screenY - mTmpInt2[1];
- if (0 <= viewX && viewX <= mAmbientIndicationContainer.getWidth()
- && 0 <= viewY && viewY <= mAmbientIndicationContainer.getHeight()) {
- dispatchTap(mAmbientIndicationContainer, viewX, viewY);
- }
- }
- }
-
- @Override
- public void setDozeScreenBrightness(int value) {
- mStatusBarWindowController.setDozeScreenBrightness(value);
- }
-
- @Override
- public void setAodDimmingScrim(float scrimOpacity) {
- mScrimController.setAodFrontScrimAlpha(scrimOpacity);
- }
-
- @Override
- public void prepareForGentleWakeUp() {
- mScrimController.prepareForGentleWakeUp();
- }
-
- private void dispatchTap(View view, float x, float y) {
- long now = SystemClock.elapsedRealtime();
- dispatchTouchEvent(view, x, y, now, MotionEvent.ACTION_DOWN);
- dispatchTouchEvent(view, x, y, now, MotionEvent.ACTION_UP);
- }
-
- private void dispatchTouchEvent(View view, float x, float y, long now, int action) {
- MotionEvent ev = MotionEvent.obtain(now, now, action, x, y, 0 /* meta */);
- view.dispatchTouchEvent(ev);
- ev.recycle();
- }
-
- private boolean shouldAnimateWakeup() {
- return mAnimateWakeup;
- }
-
- public boolean shouldAnimateScreenOff() {
- return mAnimateScreenOff;
- }
- }
-
public boolean shouldIgnoreTouch() {
- return isDozing() && mDozeServiceHost.mIgnoreTouchWhilePulsing;
+ return isDozing() && mDozeServiceHost.getIgnoreTouchWhilePulsing();
}
// Begin Extra BaseStatusBar methods.
@@ -4222,12 +4095,11 @@ public class StatusBar extends SystemUI implements DemoMode,
// all notifications
protected ViewGroup mStackScroller;
- protected NotificationGroupManager mGroupManager;
-
- protected NotificationGroupAlertTransferHelper mGroupAlertTransferHelper;
+ private final NotificationGroupManager mGroupManager;
+ private final NotificationGroupAlertTransferHelper mGroupAlertTransferHelper;
// handling reordering
- protected VisualStabilityManager mVisualStabilityManager;
+ private final VisualStabilityManager mVisualStabilityManager;
protected AccessibilityManager mAccessibilityManager;
@@ -4239,14 +4111,13 @@ public class StatusBar extends SystemUI implements DemoMode,
private boolean mVisibleToUser;
protected DevicePolicyManager mDevicePolicyManager;
- protected PowerManager mPowerManager;
+ private final PowerManager mPowerManager;
protected StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
protected KeyguardManager mKeyguardManager;
- private DeviceProvisionedController mDeviceProvisionedController
- = Dependency.get(DeviceProvisionedController.class);
+ private final DeviceProvisionedController mDeviceProvisionedController;
- protected NavigationBarController mNavigationBarController;
+ private final NavigationBarController mNavigationBarController;
// UI-specific methods
@@ -4262,7 +4133,7 @@ public class StatusBar extends SystemUI implements DemoMode,
protected NotificationShelf mNotificationShelf;
protected EmptyShadeView mEmptyShadeView;
- protected AssistManager mAssistManager;
+ private final AssistManager mAssistManager;
public boolean isDeviceInteractive() {
return mDeviceInteractive;
@@ -4321,7 +4192,7 @@ public class StatusBar extends SystemUI implements DemoMode,
}
}
- protected NotificationListener mNotificationListener;
+ private final NotificationListener mNotificationListener;
public void setNotificationSnoozed(StatusBarNotification sbn, SnoozeOption snoozeOption) {
if (snoozeOption.getSnoozeCriterion() != null) {
@@ -4457,8 +4328,7 @@ public class StatusBar extends SystemUI implements DemoMode,
executeActionDismissingKeyguard(() -> {
try {
intent.send(null, 0, null, null, null, null, getActivityOptions(
- mActivityLaunchAnimator.getLaunchAnimation(associatedView,
- mShadeController.isOccluded())));
+ mActivityLaunchAnimator.getLaunchAnimation(associatedView, isOccluded())));
} catch (PendingIntent.CanceledException e) {
// the stack trace isn't very helpful here.
// Just log the exception message.
@@ -4546,7 +4416,7 @@ public class StatusBar extends SystemUI implements DemoMode,
*/
public void onBouncerPreHideAnimation() {
mNotificationPanel.onBouncerPreHideAnimation();
- mStatusBarWindow.onBouncerPreHideAnimation();
+ mStatusBarWindowViewController.onBouncerPreHideAnimation();
}
/**
@@ -4611,8 +4481,8 @@ public class StatusBar extends SystemUI implements DemoMode,
void createStatusBar(StatusBar statusbar);
}
- public @TransitionMode int getStatusBarMode() {
- return mStatusBarMode;
+ boolean isTransientShown() {
+ return mTransientShown;
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
index bb8ba055276a..8683586326d3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -33,6 +33,8 @@ import android.view.ViewGroup;
import android.view.ViewRootImpl;
import android.view.WindowManagerGlobal;
+import androidx.annotation.VisibleForTesting;
+
import com.android.internal.util.LatencyTracker;
import com.android.internal.widget.LockPatternUtils;
import com.android.keyguard.KeyguardUpdateMonitor;
@@ -56,8 +58,7 @@ import com.android.systemui.statusbar.SysuiStatusBarStateController;
import com.android.systemui.statusbar.notification.ViewGroupFadeHelper;
import com.android.systemui.statusbar.phone.KeyguardBouncer.BouncerExpansionCallback;
import com.android.systemui.statusbar.policy.ConfigurationController;
-import com.android.systemui.statusbar.policy.KeyguardMonitor;
-import com.android.systemui.statusbar.policy.KeyguardMonitorImpl;
+import com.android.systemui.statusbar.policy.KeyguardStateController;
import java.io.PrintWriter;
import java.util.ArrayList;
@@ -161,12 +162,13 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
private boolean mLastLockVisible;
private OnDismissAction mAfterKeyguardGoneAction;
+ private Runnable mKeyguardGoneCancelAction;
private final ArrayList<Runnable> mAfterKeyguardGoneRunnables = new ArrayList<>();
// Dismiss action to be launched when we stop dozing or the keyguard is gone.
private DismissWithActionRequest mPendingWakeupAction;
- private final KeyguardMonitorImpl mKeyguardMonitor =
- (KeyguardMonitorImpl) Dependency.get(KeyguardMonitor.class);
+ private final KeyguardStateController mKeyguardStateController = Dependency.get(
+ KeyguardStateController.class);
private final NotificationMediaManager mMediaManager =
Dependency.get(NotificationMediaManager.class);
private final SysuiStatusBarStateController mStatusBarStateController =
@@ -221,7 +223,7 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
mBiometricUnlockController = biometricUnlockController;
mBouncer = SystemUIFactory.getInstance().createKeyguardBouncer(mContext,
mViewMediatorCallback, mLockPatternUtils, container, dismissCallbackRegistry,
- mExpansionCallback, falsingManager, bypassController);
+ mExpansionCallback, mKeyguardStateController, falsingManager, bypassController);
mNotificationPanelView = notificationPanelView;
notificationPanelView.addExpansionListener(this);
mBypassController = bypassController;
@@ -245,7 +247,7 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
mBouncer.setExpansion(expansion);
}
if (expansion != KeyguardBouncer.EXPANSION_HIDDEN && tracking
- && mStatusBar.isKeyguardCurrentlySecure()
+ && !mKeyguardStateController.canDismissLockScreen()
&& !mBouncer.isShowing() && !mBouncer.isAnimatingAway()) {
mBouncer.show(false /* resetSecuritySelection */, false /* scrimmed */);
}
@@ -269,7 +271,7 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
boolean keyguardWithoutQs = mStatusBarStateController.getState() == StatusBarState.KEYGUARD
&& !mNotificationPanelView.isQsExpanded();
boolean lockVisible = (mBouncer.isShowing() || keyguardWithoutQs)
- && !mBouncer.isAnimatingAway() && !mKeyguardMonitor.isKeyguardFadingAway();
+ && !mBouncer.isAnimatingAway() && !mKeyguardStateController.isKeyguardFadingAway();
if (mLastLockVisible != lockVisible) {
mLastLockVisible = lockVisible;
@@ -299,8 +301,8 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
public void show(Bundle options) {
mShowing = true;
mStatusBarWindowController.setKeyguardShowing(true);
- mKeyguardMonitor.notifyKeyguardState(
- mShowing, mKeyguardMonitor.isSecure(), mKeyguardMonitor.isOccluded());
+ mKeyguardStateController.notifyKeyguardState(mShowing,
+ mKeyguardStateController.isOccluded());
reset(true /* hideBouncerWhenShowing */);
StatsLog.write(StatsLog.KEYGUARD_STATE_CHANGED,
StatsLog.KEYGUARD_STATE_CHANGED__STATE__SHOWN);
@@ -329,10 +331,20 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
return false;
}
- private void hideBouncer(boolean destroyView) {
+ @VisibleForTesting
+ void hideBouncer(boolean destroyView) {
if (mBouncer == null) {
return;
}
+ if (mShowing) {
+ // If we were showing the bouncer and then aborting, we need to also clear out any
+ // potential actions unless we actually unlocked.
+ mAfterKeyguardGoneAction = null;
+ if (mKeyguardGoneCancelAction != null) {
+ mKeyguardGoneCancelAction.run();
+ mKeyguardGoneCancelAction = null;
+ }
+ }
mBouncer.hide(destroyView);
cancelPendingWakeupAction();
}
@@ -365,6 +377,7 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
mBouncer.showWithDismissAction(r, cancelAction);
} else {
mAfterKeyguardGoneAction = r;
+ mKeyguardGoneCancelAction = cancelAction;
mBouncer.show(false /* resetSecuritySelection */);
}
}
@@ -530,8 +543,8 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
*/
public void hide(long startTime, long fadeoutDuration) {
mShowing = false;
- mKeyguardMonitor.notifyKeyguardState(
- mShowing, mKeyguardMonitor.isSecure(), mKeyguardMonitor.isOccluded());
+ mKeyguardStateController.notifyKeyguardState(mShowing,
+ mKeyguardStateController.isOccluded());
launchPendingWakeupAction();
if (Dependency.get(KeyguardUpdateMonitor.class).needsSlowUnlockTransition()) {
@@ -672,6 +685,7 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
mAfterKeyguardGoneAction.onDismiss();
mAfterKeyguardGoneAction = null;
}
+ mKeyguardGoneCancelAction = null;
for (int i = 0; i < mAfterKeyguardGoneRunnables.size(); i++) {
mAfterKeyguardGoneRunnables.get(i).run();
}
@@ -739,8 +753,8 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
}
private long getNavBarShowDelay() {
- if (mKeyguardMonitor.isKeyguardFadingAway()) {
- return mKeyguardMonitor.getKeyguardFadingAwayDelay();
+ if (mKeyguardStateController.isKeyguardFadingAway()) {
+ return mKeyguardStateController.getKeyguardFadingAwayDelay();
} else if (mBouncer.isShowing()) {
return NAV_BAR_SHOW_DELAY_BOUNCER;
} else {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
index 320243b3ee22..64a45e16d749 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
@@ -68,7 +68,7 @@ import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.logging.NotificationLogger;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.policy.HeadsUpUtil;
-import com.android.systemui.statusbar.policy.KeyguardMonitor;
+import com.android.systemui.statusbar.policy.KeyguardStateController;
/**
* Status bar implementation of {@link NotificationActivityStarter}.
@@ -84,7 +84,7 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit
private final NotificationRemoteInputManager mRemoteInputManager;
private final NotificationLockscreenUserManager mLockscreenUserManager;
private final ShadeController mShadeController;
- private final KeyguardMonitor mKeyguardMonitor;
+ private final KeyguardStateController mKeyguardStateController;
private final ActivityStarter mActivityStarter;
private final NotificationEntryManager mEntryManager;
private final StatusBarStateController mStatusBarStateController;
@@ -125,7 +125,7 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit
NotificationGroupManager groupManager,
NotificationLockscreenUserManager lockscreenUserManager,
ShadeController shadeController,
- KeyguardMonitor keyguardMonitor,
+ KeyguardStateController keyguardStateController,
NotificationInterruptionStateProvider notificationInterruptionStateProvider,
MetricsLogger metricsLogger,
LockPatternUtils lockPatternUtils,
@@ -145,7 +145,7 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit
mRemoteInputManager = remoteInputManager;
mLockscreenUserManager = lockscreenUserManager;
mShadeController = shadeController;
- mKeyguardMonitor = keyguardMonitor;
+ mKeyguardStateController = keyguardStateController;
mActivityStarter = activityStarter;
mEntryManager = entryManager;
mStatusBarStateController = statusBarStateController;
@@ -204,7 +204,7 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit
&& mActivityIntentHelper.wouldLaunchResolverActivity(intent.getIntent(),
mLockscreenUserManager.getCurrentUserId());
final boolean wasOccluded = mShadeController.isOccluded();
- boolean showOverLockscreen = mKeyguardMonitor.isShowing() && intent != null
+ boolean showOverLockscreen = mKeyguardStateController.isShowing() && intent != null
&& mActivityIntentHelper.wouldShowOverLockscreen(intent.getIntent(),
mLockscreenUserManager.getCurrentUserId());
ActivityStarter.OnDismissAction postKeyguardAction =
@@ -245,7 +245,7 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit
StatusBarNotification parentToCancel = null;
if (shouldAutoCancel(sbn) && mGroupManager.isOnlyChildInGroup(sbn)) {
StatusBarNotification summarySbn =
- mGroupManager.getLogicalGroupSummary(sbn).notification;
+ mGroupManager.getLogicalGroupSummary(sbn).getSbn();
if (shouldAutoCancel(summarySbn)) {
parentToCancel = summarySbn;
}
@@ -258,7 +258,7 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit
if (showOverLockscreen) {
mShadeController.addPostCollapseAction(runnable);
mShadeController.collapsePanel(true /* animate */);
- } else if (mKeyguardMonitor.isShowing()
+ } else if (mKeyguardStateController.isShowing()
&& mShadeController.isOccluded()) {
mShadeController.addAfterKeyguardGoneRunnable(runnable);
mShadeController.collapsePanel();
@@ -310,7 +310,7 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit
if (!TextUtils.isEmpty(entry.remoteInputText)) {
remoteInputText = entry.remoteInputText;
}
- if (!TextUtils.isEmpty(remoteInputText) && !controller.isSpinning(entry.key)) {
+ if (!TextUtils.isEmpty(remoteInputText) && !controller.isSpinning(entry.getKey())) {
fillInIntent = new Intent().putExtra(Notification.EXTRA_REMOTE_INPUT_DRAFT,
remoteInputText.toString());
}
@@ -409,11 +409,11 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit
if (mNotificationInterruptionStateProvider.shouldLaunchFullScreenIntentWhenAdded(entry)) {
if (shouldSuppressFullScreenIntent(entry)) {
if (DEBUG) {
- Log.d(TAG, "No Fullscreen intent: suppressed by DND: " + entry.key);
+ Log.d(TAG, "No Fullscreen intent: suppressed by DND: " + entry.getKey());
}
} else if (entry.getImportance() < NotificationManager.IMPORTANCE_HIGH) {
if (DEBUG) {
- Log.d(TAG, "No Fullscreen intent: not important enough: " + entry.key);
+ Log.d(TAG, "No Fullscreen intent: not important enough: " + entry.getKey());
}
} else {
// Stop screensaver if the notification has a fullscreen intent.
@@ -432,8 +432,8 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit
}
try {
EventLog.writeEvent(EventLogTags.SYSUI_FULLSCREEN_NOTIFICATION,
- entry.key);
- entry.notification.getNotification().fullScreenIntent.send();
+ entry.getKey());
+ entry.getSbn().getNotification().fullScreenIntent.send();
entry.notifyFullScreenIntentLaunched();
mMetricsLogger.count("note_fullscreen", 1);
} catch (PendingIntent.CanceledException e) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java
index 4732049d635e..b01a8d4b82e4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java
@@ -74,7 +74,7 @@ import com.android.systemui.statusbar.notification.row.NotificationGutsManager.O
import com.android.systemui.statusbar.notification.row.NotificationInfo.CheckSaveListener;
import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
import com.android.systemui.statusbar.policy.ConfigurationController;
-import com.android.systemui.statusbar.policy.KeyguardMonitor;
+import com.android.systemui.statusbar.policy.KeyguardStateController;
import java.util.ArrayList;
@@ -89,7 +89,7 @@ public class StatusBarNotificationPresenter implements NotificationPresenter,
private final ShadeController mShadeController = Dependency.get(ShadeController.class);
private final ActivityStarter mActivityStarter = Dependency.get(ActivityStarter.class);
- private final KeyguardMonitor mKeyguardMonitor = Dependency.get(KeyguardMonitor.class);
+ private final KeyguardStateController mKeyguardStateController;
private final NotificationViewHierarchyManager mViewHierarchyManager =
Dependency.get(NotificationViewHierarchyManager.class);
private final NotificationLockscreenUserManager mLockscreenUserManager =
@@ -123,7 +123,6 @@ public class StatusBarNotificationPresenter implements NotificationPresenter,
private final DynamicPrivacyController mDynamicPrivacyController;
private boolean mReinflateNotificationsOnUserSwitched;
private boolean mDispatchUiModeChangeOnUserSwitched;
- private final UnlockMethodCache mUnlockMethodCache;
private TextView mNotificationPanelDebugText;
protected boolean mVrMode;
@@ -139,8 +138,10 @@ public class StatusBarNotificationPresenter implements NotificationPresenter,
ActivityLaunchAnimator activityLaunchAnimator,
DynamicPrivacyController dynamicPrivacyController,
NotificationAlertingManager notificationAlertingManager,
- NotificationRowBinderImpl notificationRowBinder) {
+ NotificationRowBinderImpl notificationRowBinder,
+ KeyguardStateController keyguardStateController) {
mContext = context;
+ mKeyguardStateController = keyguardStateController;
mNotificationPanel = panel;
mHeadsUpManager = headsUp;
mDynamicPrivacyController = dynamicPrivacyController;
@@ -152,7 +153,6 @@ public class StatusBarNotificationPresenter implements NotificationPresenter,
mAccessibilityManager = context.getSystemService(AccessibilityManager.class);
mDozeScrimController = dozeScrimController;
mScrimController = scrimController;
- mUnlockMethodCache = UnlockMethodCache.getInstance(mContext);
mKeyguardManager = context.getSystemService(KeyguardManager.class);
mMaxAllowedKeyguardNotifications = context.getResources().getInteger(
R.integer.keyguard_max_notification_count);
@@ -201,7 +201,7 @@ public class StatusBarNotificationPresenter implements NotificationPresenter,
NotificationVisibility visibility,
boolean removedByUser) {
StatusBarNotificationPresenter.this.onNotificationRemoved(
- entry.key, entry.notification);
+ entry.getKey(), entry.getSbn());
if (removedByUser) {
maybeEndAmbientPulse();
}
@@ -366,7 +366,7 @@ public class StatusBarNotificationPresenter implements NotificationPresenter,
return false;
} else {
// we only allow head-up on the lockscreen if it doesn't have a fullscreen intent
- return !mKeyguardMonitor.isShowing()
+ return !mKeyguardStateController.isShowing()
|| mShadeController.isOccluded();
}
}
@@ -398,7 +398,7 @@ public class StatusBarNotificationPresenter implements NotificationPresenter,
public void onBindRow(NotificationEntry entry, PackageManager pmUser,
StatusBarNotification sbn, ExpandableNotificationRow row) {
row.setAboveShelfChangedListener(mAboveShelfObserver);
- row.setSecureStateProvider(mUnlockMethodCache::canSkipBouncer);
+ row.setSecureStateProvider(mKeyguardStateController::canDismissLockScreen);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallback.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallback.java
index 13d4b8edb8d4..1def89b3af54 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallback.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallback.java
@@ -35,7 +35,6 @@ import android.view.View;
import android.view.ViewParent;
import com.android.systemui.ActivityIntentHelper;
-import com.android.systemui.Dependency;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.CommandQueue;
@@ -47,8 +46,7 @@ import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.SysuiStatusBarStateController;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
-import com.android.systemui.statusbar.policy.KeyguardMonitor;
-import com.android.systemui.statusbar.policy.RemoteInputView;
+import com.android.systemui.statusbar.policy.KeyguardStateController;
import javax.inject.Inject;
import javax.inject.Singleton;
@@ -59,18 +57,16 @@ import javax.inject.Singleton;
public class StatusBarRemoteInputCallback implements Callback, Callbacks,
StatusBarStateController.StateListener {
- private final KeyguardMonitor mKeyguardMonitor = Dependency.get(KeyguardMonitor.class);
- private final SysuiStatusBarStateController mStatusBarStateController =
- (SysuiStatusBarStateController) Dependency.get(StatusBarStateController.class);
- private final NotificationLockscreenUserManager mLockscreenUserManager =
- Dependency.get(NotificationLockscreenUserManager.class);
- private final ActivityStarter mActivityStarter = Dependency.get(ActivityStarter.class);
+ private final KeyguardStateController mKeyguardStateController;
+ private final SysuiStatusBarStateController mStatusBarStateController;
+ private final NotificationLockscreenUserManager mLockscreenUserManager;
+ private final ActivityStarter mActivityStarter;
+ private final ShadeController mShadeController;
private final Context mContext;
private final ActivityIntentHelper mActivityIntentHelper;
private final NotificationGroupManager mGroupManager;
private View mPendingWorkRemoteInputView;
private View mPendingRemoteInputView;
- private final ShadeController mShadeController = Dependency.get(ShadeController.class);
private KeyguardManager mKeyguardManager;
private final CommandQueue mCommandQueue;
private int mDisabled2;
@@ -80,10 +76,19 @@ public class StatusBarRemoteInputCallback implements Callback, Callbacks,
/**
*/
@Inject
- public StatusBarRemoteInputCallback(Context context, NotificationGroupManager groupManager) {
+ public StatusBarRemoteInputCallback(Context context, NotificationGroupManager groupManager,
+ NotificationLockscreenUserManager notificationLockscreenUserManager,
+ KeyguardStateController keyguardStateController,
+ StatusBarStateController statusBarStateController,
+ ActivityStarter activityStarter, ShadeController shadeController) {
mContext = context;
mContext.registerReceiverAsUser(mChallengeReceiver, UserHandle.ALL,
new IntentFilter(ACTION_DEVICE_LOCKED_CHANGED), null, null);
+ mLockscreenUserManager = notificationLockscreenUserManager;
+ mKeyguardStateController = keyguardStateController;
+ mStatusBarStateController = (SysuiStatusBarStateController) statusBarStateController;
+ mShadeController = shadeController;
+ mActivityStarter = activityStarter;
mStatusBarStateController.addCallback(this);
mKeyguardManager = context.getSystemService(KeyguardManager.class);
mCommandQueue = getComponent(context, CommandQueue.class);
@@ -165,7 +170,7 @@ public class StatusBarRemoteInputCallback implements Callback, Callbacks,
@Override
public void onMakeExpandedVisibleForRemoteInput(ExpandableNotificationRow row,
View clickedView) {
- if (mKeyguardMonitor.isShowing()) {
+ if (mKeyguardStateController.isShowing()) {
onLockedRemoteInput(row, clickedView);
} else {
if (row.isChildInGroup() && !row.areChildrenExpanded()) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java
index 724b46297e75..ca7a936d58f7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java
@@ -21,7 +21,6 @@ import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_M
import static com.android.systemui.DejankUtils.whitelistIpcs;
import static com.android.systemui.statusbar.NotificationRemoteInputManager.ENABLE_REMOTE_INPUT;
-import android.app.ActivityManager;
import android.app.IActivityManager;
import android.content.Context;
import android.content.pm.ActivityInfo;
@@ -39,8 +38,6 @@ import android.view.ViewGroup;
import android.view.WindowManager;
import android.view.WindowManager.LayoutParams;
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.systemui.Dependency;
import com.android.systemui.Dumpable;
import com.android.systemui.R;
import com.android.systemui.colorextraction.SysuiColorExtractor;
@@ -94,24 +91,14 @@ public class StatusBarWindowController implements Callback, Dumpable, Configurat
private final ArrayList<WeakReference<StatusBarWindowCallback>>
mCallbacks = Lists.newArrayList();
- private final SysuiColorExtractor mColorExtractor = Dependency.get(SysuiColorExtractor.class);
+ private final SysuiColorExtractor mColorExtractor;
@Inject
- public StatusBarWindowController(Context context,
- StatusBarStateController statusBarStateController,
- ConfigurationController configurationController,
- KeyguardBypassController keyguardBypassController) {
- this(context, context.getSystemService(WindowManager.class), ActivityManager.getService(),
- DozeParameters.getInstance(context), statusBarStateController,
- configurationController, keyguardBypassController);
- }
-
- @VisibleForTesting
public StatusBarWindowController(Context context, WindowManager windowManager,
IActivityManager activityManager, DozeParameters dozeParameters,
StatusBarStateController statusBarStateController,
ConfigurationController configurationController,
- KeyguardBypassController keyguardBypassController) {
+ KeyguardBypassController keyguardBypassController, SysuiColorExtractor colorExtractor) {
mContext = context;
mWindowManager = windowManager;
mActivityManager = activityManager;
@@ -120,6 +107,7 @@ public class StatusBarWindowController implements Callback, Dumpable, Configurat
mScreenBrightnessDoze = mDozeParameters.getScreenBrightnessDoze();
mLpChanged = new LayoutParams();
mKeyguardBypassController = keyguardBypassController;
+ mColorExtractor = colorExtractor;
mLockScreenDisplayTimeout = context.getResources()
.getInteger(R.integer.config_lockScreenDisplayTimeout);
((SysuiStatusBarStateController) statusBarStateController)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
index a9e818df6bc3..6b513919e912 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
@@ -19,29 +19,19 @@ package com.android.systemui.statusbar.phone;
import android.annotation.ColorInt;
import android.annotation.DrawableRes;
import android.annotation.LayoutRes;
-import android.app.StatusBarManager;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.TypedArray;
import android.graphics.Canvas;
+import android.graphics.Insets;
import android.graphics.Paint;
-import android.graphics.PorterDuff;
-import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
-import android.hardware.display.AmbientDisplayConfiguration;
-import android.media.AudioManager;
-import android.media.session.MediaSessionLegacyHelper;
import android.net.Uri;
import android.os.Bundle;
-import android.os.SystemClock;
-import android.os.UserHandle;
-import android.provider.Settings;
import android.util.AttributeSet;
import android.view.ActionMode;
import android.view.DisplayCutout;
-import android.view.GestureDetector;
-import android.view.InputDevice;
import android.view.InputQueue;
import android.view.KeyEvent;
import android.view.LayoutInflater;
@@ -53,24 +43,13 @@ import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.view.Window;
+import android.view.WindowInsets;
import android.view.WindowInsetsController;
import android.widget.FrameLayout;
-import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.view.FloatingActionMode;
import com.android.internal.widget.FloatingToolbar;
-import com.android.systemui.Dependency;
-import com.android.systemui.ExpandHelper;
import com.android.systemui.R;
-import com.android.systemui.plugins.FalsingManager;
-import com.android.systemui.plugins.statusbar.StatusBarStateController;
-import com.android.systemui.statusbar.DragDownHelper;
-import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
-import com.android.systemui.statusbar.phone.ScrimController.ScrimVisibility;
-import com.android.systemui.tuner.TunerService;
-
-import java.io.FileDescriptor;
-import java.io.PrintWriter;
/**
* Combined status bar and notification panel view. Also holding backdrop and scrims.
@@ -79,91 +58,26 @@ public class StatusBarWindowView extends FrameLayout {
public static final String TAG = "StatusBarWindowView";
public static final boolean DEBUG = StatusBar.DEBUG;
- private final GestureDetector mGestureDetector;
- private final StatusBarStateController mStatusBarStateController;
- private boolean mDoubleTapEnabled;
- private boolean mSingleTapEnabled;
- private DragDownHelper mDragDownHelper;
- private NotificationStackScrollLayout mStackScrollLayout;
- private NotificationPanelView mNotificationPanel;
- private View mBrightnessMirror;
- private LockIcon mLockIcon;
- private PhoneStatusBarView mStatusBarView;
-
private int mRightInset = 0;
private int mLeftInset = 0;
- private StatusBar mService;
- private final Paint mTransparentSrcPaint = new Paint();
- private FalsingManager mFalsingManager;
-
// Implements the floating action mode for TextView's Cut/Copy/Past menu. Normally provided by
// DecorView, but since this is a special window we have to roll our own.
private View mFloatingActionModeOriginatingView;
private ActionMode mFloatingActionMode;
private FloatingToolbar mFloatingToolbar;
private ViewTreeObserver.OnPreDrawListener mFloatingToolbarPreDrawListener;
- private boolean mTouchCancelled;
- private boolean mTouchActive;
- private boolean mExpandAnimationRunning;
- private boolean mExpandAnimationPending;
- private boolean mSuppressingWakeUpGesture;
-
- private final GestureDetector.SimpleOnGestureListener mGestureListener =
- new GestureDetector.SimpleOnGestureListener() {
- @Override
- public boolean onSingleTapConfirmed(MotionEvent e) {
- if (mSingleTapEnabled && !mSuppressingWakeUpGesture) {
- mService.wakeUpIfDozing(SystemClock.uptimeMillis(), StatusBarWindowView.this,
- "SINGLE_TAP");
- return true;
- }
- return false;
- }
- @Override
- public boolean onDoubleTap(MotionEvent e) {
- if (mDoubleTapEnabled || mSingleTapEnabled) {
- mService.wakeUpIfDozing(SystemClock.uptimeMillis(), StatusBarWindowView.this,
- "DOUBLE_TAP");
- return true;
- }
- return false;
- }
- };
- private final TunerService.Tunable mTunable = (key, newValue) -> {
- AmbientDisplayConfiguration configuration = new AmbientDisplayConfiguration(mContext);
- switch (key) {
- case Settings.Secure.DOZE_DOUBLE_TAP_GESTURE:
- mDoubleTapEnabled = configuration.doubleTapGestureEnabled(UserHandle.USER_CURRENT);
- break;
- case Settings.Secure.DOZE_TAP_SCREEN_GESTURE:
- mSingleTapEnabled = configuration.tapGestureEnabled(UserHandle.USER_CURRENT);
- }
- };
-
- /**
- * If set to true, the current gesture started below the notch and we need to dispatch touch
- * events manually as it's outside of the regular view bounds.
- */
- private boolean mExpandingBelowNotch;
- private KeyguardBypassController mBypassController;
+ private InteractionEventHandler mInteractionEventHandler;
public StatusBarWindowView(Context context, AttributeSet attrs) {
super(context, attrs);
setMotionEventSplittingEnabled(false);
- mTransparentSrcPaint.setColor(0);
- mTransparentSrcPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC));
- mFalsingManager = Dependency.get(FalsingManager.class); // TODO: inject into a controller.
- mGestureDetector = new GestureDetector(context, mGestureListener);
- mStatusBarStateController = Dependency.get(StatusBarStateController.class);
- Dependency.get(TunerService.class).addTunable(mTunable,
- Settings.Secure.DOZE_DOUBLE_TAP_GESTURE,
- Settings.Secure.DOZE_TAP_SCREEN_GESTURE);
}
@Override
- protected boolean fitSystemWindows(Rect insets) {
+ public WindowInsets onApplyWindowInsets(WindowInsets windowInsets) {
+ final Insets insets = windowInsets.getMaxInsets(WindowInsets.Type.systemBars());
if (getFitsSystemWindows()) {
boolean paddingChanged = insets.top != getPaddingTop()
|| insets.bottom != getPaddingBottom();
@@ -189,9 +103,6 @@ public class StatusBarWindowView extends FrameLayout {
if (paddingChanged) {
setPadding(0, 0, 0, 0);
}
- insets.left = 0;
- insets.top = 0;
- insets.right = 0;
} else {
if (mRightInset != 0 || mLeftInset != 0) {
mRightInset = 0;
@@ -205,9 +116,8 @@ public class StatusBarWindowView extends FrameLayout {
if (changed) {
setPadding(0, 0, 0, 0);
}
- insets.top = 0;
}
- return false;
+ return windowInsets;
}
private void applyMargins() {
@@ -226,11 +136,6 @@ public class StatusBarWindowView extends FrameLayout {
}
}
- @VisibleForTesting
- protected NotificationStackScrollLayout getStackScrollLayout() {
- return mStackScrollLayout;
- }
-
@Override
public FrameLayout.LayoutParams generateLayoutParams(AttributeSet attrs) {
return new LayoutParams(getContext(), attrs);
@@ -242,61 +147,6 @@ public class StatusBarWindowView extends FrameLayout {
}
@Override
- protected void onFinishInflate() {
- super.onFinishInflate();
- mStackScrollLayout = findViewById(R.id.notification_stack_scroller);
- mNotificationPanel = findViewById(R.id.notification_panel);
- mBrightnessMirror = findViewById(R.id.brightness_mirror);
- mLockIcon = findViewById(R.id.lock_icon);
- }
-
- @Override
- public void onViewAdded(View child) {
- super.onViewAdded(child);
- if (child.getId() == R.id.brightness_mirror) {
- mBrightnessMirror = child;
- }
- }
-
- /**
- * Propagate {@link StatusBar} pulsing state.
- */
- public void setPulsing(boolean pulsing) {
- if (mLockIcon != null) {
- mLockIcon.setPulsing(pulsing);
- }
- }
-
- /**
- * Called when the biometric authentication mode changes.
- * @param wakeAndUnlock If the type is {@link BiometricUnlockController#isWakeAndUnlock()}
- * @param isUnlock If the type is {@link BiometricUnlockController#isBiometricUnlock()} ()
- */
- public void onBiometricAuthModeChanged(boolean wakeAndUnlock, boolean isUnlock) {
- if (mLockIcon != null) {
- mLockIcon.onBiometricAuthModeChanged(wakeAndUnlock, isUnlock);
- }
- }
-
- public void setStatusBarView(PhoneStatusBarView statusBarView) {
- mStatusBarView = statusBarView;
- }
-
- public void setService(StatusBar service) {
- mService = service;
- NotificationStackScrollLayout stackScrollLayout = getStackScrollLayout();
- ExpandHelper.Callback expandHelperCallback = stackScrollLayout.getExpandHelperCallback();
- DragDownHelper.DragDownCallback dragDownCallback = stackScrollLayout.getDragDownCallback();
- setDragDownHelper(new DragDownHelper(getContext(), this, expandHelperCallback,
- dragDownCallback, mFalsingManager));
- }
-
- @VisibleForTesting
- void setDragDownHelper(DragDownHelper dragDownHelper) {
- mDragDownHelper = dragDownHelper;
- }
-
- @Override
protected void onAttachedToWindow () {
super.onAttachedToWindow();
setWillNotDraw(!DEBUG);
@@ -304,152 +154,53 @@ public class StatusBarWindowView extends FrameLayout {
@Override
public boolean dispatchKeyEvent(KeyEvent event) {
- if (mService.interceptMediaKey(event)) {
+ if (mInteractionEventHandler.interceptMediaKey(event)) {
return true;
}
+
if (super.dispatchKeyEvent(event)) {
return true;
}
- boolean down = event.getAction() == KeyEvent.ACTION_DOWN;
- switch (event.getKeyCode()) {
- case KeyEvent.KEYCODE_BACK:
- if (!down) {
- mService.onBackPressed();
- }
- return true;
- case KeyEvent.KEYCODE_MENU:
- if (!down) {
- return mService.onMenuPressed();
- }
- case KeyEvent.KEYCODE_SPACE:
- if (!down) {
- return mService.onSpacePressed();
- }
- break;
- case KeyEvent.KEYCODE_VOLUME_DOWN:
- case KeyEvent.KEYCODE_VOLUME_UP:
- if (mService.isDozing()) {
- MediaSessionLegacyHelper.getHelper(mContext).sendVolumeKeyEvent(
- event, AudioManager.USE_DEFAULT_STREAM_TYPE, true);
- return true;
- }
- break;
- }
- return false;
- }
- public void setTouchActive(boolean touchActive) {
- mTouchActive = touchActive;
+ return mInteractionEventHandler.dispatchKeyEvent(event);
}
- void suppressWakeUpGesture(boolean suppress) {
- mSuppressingWakeUpGesture = suppress;
+ protected void setInteractionEventHandler(InteractionEventHandler listener) {
+ mInteractionEventHandler = listener;
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
- boolean isDown = ev.getActionMasked() == MotionEvent.ACTION_DOWN;
- boolean isUp = ev.getActionMasked() == MotionEvent.ACTION_UP;
- boolean isCancel = ev.getActionMasked() == MotionEvent.ACTION_CANCEL;
-
- // Reset manual touch dispatch state here but make sure the UP/CANCEL event still gets
- // delivered.
- boolean expandingBelowNotch = mExpandingBelowNotch;
- if (isUp || isCancel) {
- mExpandingBelowNotch = false;
- }
-
- if (!isCancel && mService.shouldIgnoreTouch()) {
- return false;
- }
- if (isDown && mNotificationPanel.isFullyCollapsed()) {
- mNotificationPanel.startExpandLatencyTracking();
- }
- if (isDown) {
- setTouchActive(true);
- mTouchCancelled = false;
- } else if (ev.getActionMasked() == MotionEvent.ACTION_UP
- || ev.getActionMasked() == MotionEvent.ACTION_CANCEL) {
- setTouchActive(false);
- }
- if (mTouchCancelled || mExpandAnimationRunning || mExpandAnimationPending) {
- return false;
- }
- mFalsingManager.onTouchEvent(ev, getWidth(), getHeight());
- mGestureDetector.onTouchEvent(ev);
- if (mBrightnessMirror != null && mBrightnessMirror.getVisibility() == VISIBLE) {
- // Disallow new pointers while the brightness mirror is visible. This is so that you
- // can't touch anything other than the brightness slider while the mirror is showing
- // and the rest of the panel is transparent.
- if (ev.getActionMasked() == MotionEvent.ACTION_POINTER_DOWN) {
- return false;
- }
- }
- if (isDown) {
- getStackScrollLayout().closeControlsIfOutsideTouch(ev);
- }
- if (mService.isDozing()) {
- mService.mDozeScrimController.extendPulse();
- }
+ Boolean result = mInteractionEventHandler.handleDispatchTouchEvent(ev);
- // In case we start outside of the view bounds (below the status bar), we need to dispatch
- // the touch manually as the view system can't accomodate for touches outside of the
- // regular view bounds.
- if (isDown && ev.getY() >= mBottom) {
- mExpandingBelowNotch = true;
- expandingBelowNotch = true;
- }
- if (expandingBelowNotch) {
- return mStatusBarView.dispatchTouchEvent(ev);
- }
-
- return super.dispatchTouchEvent(ev);
+ return result != null ? result : super.dispatchTouchEvent(ev);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
- NotificationStackScrollLayout stackScrollLayout = getStackScrollLayout();
- if (mService.isDozing() && !mService.isPulsing()) {
- // Capture all touch events in always-on.
- return true;
- }
- boolean intercept = false;
- if (mNotificationPanel.isFullyExpanded()
- && mDragDownHelper.isDragDownEnabled()
- && !mService.isBouncerShowing()
- && !mService.isDozing()) {
- intercept = mDragDownHelper.onInterceptTouchEvent(ev);
- }
+ boolean intercept = mInteractionEventHandler.shouldInterceptTouchEvent(ev);
if (!intercept) {
- super.onInterceptTouchEvent(ev);
+ intercept = super.onInterceptTouchEvent(ev);
}
if (intercept) {
- MotionEvent cancellation = MotionEvent.obtain(ev);
- cancellation.setAction(MotionEvent.ACTION_CANCEL);
- stackScrollLayout.onInterceptTouchEvent(cancellation);
- mNotificationPanel.onInterceptTouchEvent(cancellation);
- cancellation.recycle();
+ mInteractionEventHandler.didIntercept(ev);
}
+
return intercept;
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
- boolean handled = false;
- if (mService.isDozing()) {
- handled = !mService.isPulsing();
- }
- if ((mDragDownHelper.isDragDownEnabled() && !handled) || mDragDownHelper.isDraggingDown()) {
- // we still want to finish our drag down gesture when locking the screen
- handled = mDragDownHelper.onTouchEvent(ev);
- }
+ boolean handled = mInteractionEventHandler.handleTouchEvent(ev);
+
if (!handled) {
handled = super.onTouchEvent(ev);
}
- final int action = ev.getAction();
- if (!handled && (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL)) {
- mService.setInteracting(StatusBarManager.WINDOW_STATUS_BAR, false);
+
+ if (!handled) {
+ mInteractionEventHandler.didNotHandleTouchEvent(ev);
}
+
return handled;
}
@@ -465,77 +216,6 @@ public class StatusBarWindowView extends FrameLayout {
}
}
- public void cancelExpandHelper() {
- NotificationStackScrollLayout stackScrollLayout = getStackScrollLayout();
- if (stackScrollLayout != null) {
- stackScrollLayout.cancelExpandHelper();
- }
- }
-
- public void cancelCurrentTouch() {
- if (mTouchActive) {
- final long now = SystemClock.uptimeMillis();
- MotionEvent event = MotionEvent.obtain(now, now,
- MotionEvent.ACTION_CANCEL, 0.0f, 0.0f, 0);
- event.setSource(InputDevice.SOURCE_TOUCHSCREEN);
- dispatchTouchEvent(event);
- event.recycle();
- mTouchCancelled = true;
- }
- }
-
- public void setExpandAnimationRunning(boolean expandAnimationRunning) {
- mExpandAnimationRunning = expandAnimationRunning;
- }
-
- public void setExpandAnimationPending(boolean pending) {
- mExpandAnimationPending = pending;
- }
-
- public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- pw.print(" mExpandAnimationPending="); pw.println(mExpandAnimationPending);
- pw.print(" mExpandAnimationRunning="); pw.println(mExpandAnimationRunning);
- pw.print(" mTouchCancelled="); pw.println(mTouchCancelled);
- pw.print(" mTouchActive="); pw.println(mTouchActive);
- }
-
- /**
- * Called whenever the scrims become opaque, transparent or semi-transparent.
- */
- public void onScrimVisibilityChanged(@ScrimVisibility int scrimsVisible) {
- if (mLockIcon != null) {
- mLockIcon.onScrimVisibilityChanged(scrimsVisible);
- }
- }
-
- /**
- * When we're launching an affordance, like double pressing power to open camera.
- */
- public void onShowingLaunchAffordanceChanged(boolean showing) {
- if (mLockIcon != null) {
- mLockIcon.onShowingLaunchAffordanceChanged(showing);
- }
- }
-
- public void setBypassController(KeyguardBypassController bypassController) {
- mBypassController = bypassController;
- }
-
- public void setBouncerShowingScrimmed(boolean bouncerShowing) {
- if (mLockIcon != null) {
- mLockIcon.setBouncerShowingScrimmed(bouncerShowing);
- }
- }
-
- /**
- * When {@link KeyguardBouncer} starts to be dismissed and starts to play its animation.
- */
- public void onBouncerPreHideAnimation() {
- if (mLockIcon != null) {
- mLockIcon.onBouncerPreHideAnimation();
- }
- }
-
public class LayoutParams extends FrameLayout.LayoutParams {
public boolean ignoreRightInset;
@@ -657,6 +337,35 @@ public class StatusBarWindowView extends FrameLayout {
}
}
+ interface InteractionEventHandler {
+ /**
+ * Returns a result for {@link ViewGroup#dispatchTouchEvent(MotionEvent)} or null to defer
+ * to the super method.
+ */
+ Boolean handleDispatchTouchEvent(MotionEvent ev);
+
+ /**
+ * Returns if the view should intercept the touch event.
+ *
+ * The touch event may still be interecepted if
+ * {@link ViewGroup#onInterceptTouchEvent(MotionEvent)} decides to do so.
+ */
+ boolean shouldInterceptTouchEvent(MotionEvent ev);
+
+ /**
+ * Called when the view decides to intercept the touch event.
+ */
+ void didIntercept(MotionEvent ev);
+
+ boolean handleTouchEvent(MotionEvent ev);
+
+ void didNotHandleTouchEvent(MotionEvent ev);
+
+ boolean interceptMediaKey(KeyEvent event);
+
+ boolean dispatchKeyEvent(KeyEvent event);
+ }
+
/**
* Minimal window to satisfy FloatingToolbar.
*/
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowViewController.java
new file mode 100644
index 000000000000..fd3f9c803c12
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowViewController.java
@@ -0,0 +1,564 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.phone;
+
+import android.app.StatusBarManager;
+import android.hardware.display.AmbientDisplayConfiguration;
+import android.media.AudioManager;
+import android.media.session.MediaSessionLegacyHelper;
+import android.os.SystemClock;
+import android.os.UserHandle;
+import android.provider.Settings;
+import android.view.GestureDetector;
+import android.view.InputDevice;
+import android.view.KeyEvent;
+import android.view.LayoutInflater;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.ViewStub;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.systemui.ExpandHelper;
+import com.android.systemui.R;
+import com.android.systemui.doze.DozeLog;
+import com.android.systemui.plugins.FalsingManager;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.shared.plugins.PluginManager;
+import com.android.systemui.statusbar.DragDownHelper;
+import com.android.systemui.statusbar.NotificationLockscreenUserManager;
+import com.android.systemui.statusbar.PulseExpansionHandler;
+import com.android.systemui.statusbar.SysuiStatusBarStateController;
+import com.android.systemui.statusbar.notification.DynamicPrivacyController;
+import com.android.systemui.statusbar.notification.NotificationEntryManager;
+import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator;
+import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
+import com.android.systemui.statusbar.policy.KeyguardStateController;
+import com.android.systemui.tuner.TunerService;
+import com.android.systemui.util.InjectionInflationController;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+
+import javax.inject.Inject;
+
+/**
+ * Controller for {@link StatusBarWindowView}.
+ */
+public class StatusBarWindowViewController {
+ private final StatusBarWindowView mView;
+ private final FalsingManager mFalsingManager;
+ private final GestureDetector mGestureDetector;
+ private View mBrightnessMirror;
+ private boolean mTouchActive;
+ private boolean mTouchCancelled;
+ private boolean mExpandAnimationPending;
+ private boolean mExpandAnimationRunning;
+ private NotificationStackScrollLayout mStackScrollLayout;
+ private LockIcon mLockIcon;
+ private PhoneStatusBarView mStatusBarView;
+ private StatusBar mService;
+ private DragDownHelper mDragDownHelper;
+ private boolean mSuppressingWakeUpGesture;
+ private boolean mDoubleTapEnabled;
+ private boolean mSingleTapEnabled;
+ private boolean mExpandingBelowNotch;
+
+ private StatusBarWindowViewController(
+ StatusBarWindowView view,
+ InjectionInflationController injectionInflationController,
+ NotificationWakeUpCoordinator coordinator,
+ PulseExpansionHandler pulseExpansionHandler,
+ DynamicPrivacyController dynamicPrivacyController,
+ KeyguardBypassController bypassController,
+ FalsingManager falsingManager,
+ PluginManager pluginManager,
+ TunerService tunerService,
+ ShadeController shadeController,
+ NotificationLockscreenUserManager notificationLockscreenUserManager,
+ NotificationEntryManager notificationEntryManager,
+ KeyguardStateController keyguardStateController,
+ SysuiStatusBarStateController statusBarStateController,
+ DozeLog dozeLog,
+ DozeParameters dozeParameters) {
+ mView = view;
+ mFalsingManager = falsingManager;
+
+ // TODO: create controller for NotificationPanelView
+ NotificationPanelView notificationPanelView = new NotificationPanelView(
+ view.getContext(),
+ null,
+ injectionInflationController,
+ coordinator,
+ pulseExpansionHandler,
+ dynamicPrivacyController,
+ bypassController,
+ falsingManager,
+ pluginManager,
+ shadeController,
+ notificationLockscreenUserManager,
+ notificationEntryManager,
+ keyguardStateController,
+ statusBarStateController,
+ dozeLog,
+ dozeParameters);
+ ViewGroup.LayoutParams lp = new ViewGroup.LayoutParams(
+ ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
+ notificationPanelView.setVisibility(View.INVISIBLE);
+ notificationPanelView.setId(R.id.notification_panel);
+ LayoutInflater li = injectionInflationController.injectable(
+ LayoutInflater.from(mView.getContext()));
+
+ li.inflate(R.layout.status_bar_expanded, notificationPanelView);
+ notificationPanelView.onChildrenAttached();
+
+ ViewStub statusBarExpanded = view.findViewById(R.id.status_bar_expanded);
+ mView.addView(notificationPanelView, mView.indexOfChild(statusBarExpanded), lp);
+ mView.removeView(statusBarExpanded);
+
+ mStackScrollLayout = mView.findViewById(R.id.notification_stack_scroller);
+ mLockIcon = mView.findViewById(R.id.lock_icon);
+ mBrightnessMirror = mView.findViewById(R.id.brightness_mirror);
+
+ TunerService.Tunable tunable = (key, newValue) -> {
+ AmbientDisplayConfiguration configuration =
+ new AmbientDisplayConfiguration(mView.getContext());
+ switch (key) {
+ case Settings.Secure.DOZE_DOUBLE_TAP_GESTURE:
+ mDoubleTapEnabled = configuration.doubleTapGestureEnabled(
+ UserHandle.USER_CURRENT);
+ break;
+ case Settings.Secure.DOZE_TAP_SCREEN_GESTURE:
+ mSingleTapEnabled = configuration.tapGestureEnabled(UserHandle.USER_CURRENT);
+ }
+ };
+ tunerService.addTunable(tunable,
+ Settings.Secure.DOZE_DOUBLE_TAP_GESTURE,
+ Settings.Secure.DOZE_TAP_SCREEN_GESTURE);
+
+ GestureDetector.SimpleOnGestureListener gestureListener =
+ new GestureDetector.SimpleOnGestureListener() {
+ @Override
+ public boolean onSingleTapConfirmed(MotionEvent e) {
+ if (mSingleTapEnabled && !mSuppressingWakeUpGesture) {
+ mService.wakeUpIfDozing(
+ SystemClock.uptimeMillis(), mView, "SINGLE_TAP");
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public boolean onDoubleTap(MotionEvent e) {
+ if (mDoubleTapEnabled || mSingleTapEnabled) {
+ mService.wakeUpIfDozing(
+ SystemClock.uptimeMillis(), mView, "DOUBLE_TAP");
+ return true;
+ }
+ return false;
+ }
+ };
+ mGestureDetector = new GestureDetector(mView.getContext(), gestureListener);
+
+ mView.setInteractionEventHandler(new StatusBarWindowView.InteractionEventHandler() {
+ @Override
+ public Boolean handleDispatchTouchEvent(MotionEvent ev) {
+ boolean isDown = ev.getActionMasked() == MotionEvent.ACTION_DOWN;
+ boolean isUp = ev.getActionMasked() == MotionEvent.ACTION_UP;
+ boolean isCancel = ev.getActionMasked() == MotionEvent.ACTION_CANCEL;
+
+ if (isUp || isCancel) {
+ mExpandingBelowNotch = false;
+ }
+
+ // Reset manual touch dispatch state here but make sure the UP/CANCEL event still
+ // gets
+ // delivered.
+
+ if (!isCancel && mService.shouldIgnoreTouch()) {
+ return false;
+ }
+ if (isDown && notificationPanelView.isFullyCollapsed()) {
+ notificationPanelView.startExpandLatencyTracking();
+ }
+ if (isDown) {
+ setTouchActive(true);
+ mTouchCancelled = false;
+ } else if (ev.getActionMasked() == MotionEvent.ACTION_UP
+ || ev.getActionMasked() == MotionEvent.ACTION_CANCEL) {
+ setTouchActive(false);
+ }
+ if (mTouchCancelled || mExpandAnimationRunning || mExpandAnimationPending) {
+ return false;
+ }
+ mFalsingManager.onTouchEvent(ev, mView.getWidth(), mView.getHeight());
+ mGestureDetector.onTouchEvent(ev);
+ if (mBrightnessMirror != null
+ && mBrightnessMirror.getVisibility() == View.VISIBLE) {
+ // Disallow new pointers while the brightness mirror is visible. This is so that
+ // you can't touch anything other than the brightness slider while the mirror is
+ // showing and the rest of the panel is transparent.
+ if (ev.getActionMasked() == MotionEvent.ACTION_POINTER_DOWN) {
+ return false;
+ }
+ }
+ if (isDown) {
+ getStackScrollLayout().closeControlsIfOutsideTouch(ev);
+ }
+ if (mService.isDozing()) {
+ mService.mDozeScrimController.extendPulse();
+ }
+ // In case we start outside of the view bounds (below the status bar), we need to
+ // dispatch
+ // the touch manually as the view system can't accommodate for touches outside of
+ // the
+ // regular view bounds.
+ if (isDown && ev.getY() >= mView.getBottom()) {
+ mExpandingBelowNotch = true;
+ }
+ if (mExpandingBelowNotch) {
+ return mStatusBarView.dispatchTouchEvent(ev);
+ }
+
+ return null;
+ }
+
+ @Override
+ public boolean shouldInterceptTouchEvent(MotionEvent ev) {
+ if (mService.isDozing() && !mService.isPulsing()) {
+ // Capture all touch events in always-on.
+ return true;
+ }
+ boolean intercept = false;
+ if (notificationPanelView.isFullyExpanded()
+ && mDragDownHelper.isDragDownEnabled()
+ && !mService.isBouncerShowing()
+ && !mService.isDozing()) {
+ intercept = mDragDownHelper.onInterceptTouchEvent(ev);
+ }
+
+ return intercept;
+
+ }
+
+ @Override
+ public void didIntercept(MotionEvent ev) {
+ NotificationStackScrollLayout stackScrollLayout = getStackScrollLayout();
+ MotionEvent cancellation = MotionEvent.obtain(ev);
+ cancellation.setAction(MotionEvent.ACTION_CANCEL);
+ stackScrollLayout.onInterceptTouchEvent(cancellation);
+ notificationPanelView.onInterceptTouchEvent(cancellation);
+ cancellation.recycle();
+ }
+
+ @Override
+ public boolean handleTouchEvent(MotionEvent ev) {
+ boolean handled = false;
+ if (mService.isDozing()) {
+ handled = !mService.isPulsing();
+ }
+ if ((mDragDownHelper.isDragDownEnabled() && !handled)
+ || mDragDownHelper.isDraggingDown()) {
+ // we still want to finish our drag down gesture when locking the screen
+ handled = mDragDownHelper.onTouchEvent(ev);
+ }
+
+ return handled;
+ }
+
+ @Override
+ public void didNotHandleTouchEvent(MotionEvent ev) {
+ final int action = ev.getActionMasked();
+ if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) {
+ mService.setInteracting(StatusBarManager.WINDOW_STATUS_BAR, false);
+ }
+ }
+
+ @Override
+ public boolean interceptMediaKey(KeyEvent event) {
+ return mService.interceptMediaKey(event);
+ }
+
+ @Override
+ public boolean dispatchKeyEvent(KeyEvent event) {
+ boolean down = event.getAction() == KeyEvent.ACTION_DOWN;
+ switch (event.getKeyCode()) {
+ case KeyEvent.KEYCODE_BACK:
+ if (!down) {
+ mService.onBackPressed();
+ }
+ return true;
+ case KeyEvent.KEYCODE_MENU:
+ if (!down) {
+ return mService.onMenuPressed();
+ }
+ break;
+ case KeyEvent.KEYCODE_SPACE:
+ if (!down) {
+ return mService.onSpacePressed();
+ }
+ break;
+ case KeyEvent.KEYCODE_VOLUME_DOWN:
+ case KeyEvent.KEYCODE_VOLUME_UP:
+ if (mService.isDozing()) {
+ MediaSessionLegacyHelper.getHelper(mView.getContext())
+ .sendVolumeKeyEvent(
+ event, AudioManager.USE_DEFAULT_STREAM_TYPE, true);
+ return true;
+ }
+ break;
+ }
+ return false;
+ }
+ });
+
+ mView.setOnHierarchyChangeListener(new ViewGroup.OnHierarchyChangeListener() {
+ @Override
+ public void onChildViewAdded(View parent, View child) {
+ if (child.getId() == R.id.brightness_mirror) {
+ mBrightnessMirror = child;
+ }
+ }
+
+ @Override
+ public void onChildViewRemoved(View parent, View child) {
+ }
+ });
+ }
+
+ public StatusBarWindowView getView() {
+ return mView;
+ }
+
+ public void setTouchActive(boolean touchActive) {
+ mTouchActive = touchActive;
+ }
+
+ public void cancelCurrentTouch() {
+ if (mTouchActive) {
+ final long now = SystemClock.uptimeMillis();
+ MotionEvent event = MotionEvent.obtain(now, now,
+ MotionEvent.ACTION_CANCEL, 0.0f, 0.0f, 0);
+ event.setSource(InputDevice.SOURCE_TOUCHSCREEN);
+ mView.dispatchTouchEvent(event);
+ event.recycle();
+ mTouchCancelled = true;
+ }
+ }
+
+ public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ pw.print(" mExpandAnimationPending=");
+ pw.println(mExpandAnimationPending);
+ pw.print(" mExpandAnimationRunning=");
+ pw.println(mExpandAnimationRunning);
+ pw.print(" mTouchCancelled=");
+ pw.println(mTouchCancelled);
+ pw.print(" mTouchActive=");
+ pw.println(mTouchActive);
+ }
+
+ public void setExpandAnimationPending(boolean pending) {
+ mExpandAnimationPending = pending;
+ }
+
+ public void setExpandAnimationRunning(boolean running) {
+ mExpandAnimationRunning = running;
+ }
+
+ public void cancelExpandHelper() {
+ NotificationStackScrollLayout stackScrollLayout = getStackScrollLayout();
+ if (stackScrollLayout != null) {
+ stackScrollLayout.cancelExpandHelper();
+ }
+ }
+
+ @VisibleForTesting
+ protected NotificationStackScrollLayout getStackScrollLayout() {
+ return mStackScrollLayout;
+ }
+
+ /**
+ * Called whenever the scrims become opaque, transparent or semi-transparent.
+ */
+ public void onScrimVisibilityChanged(Integer scrimsVisible) {
+ if (mLockIcon != null) {
+ mLockIcon.onScrimVisibilityChanged(scrimsVisible);
+ }
+ }
+
+ /**
+ * Propagate {@link StatusBar} pulsing state.
+ */
+ public void setPulsing(boolean pulsing) {
+ if (mLockIcon != null) {
+ mLockIcon.setPulsing(pulsing);
+ }
+ }
+
+ /**
+ * Called when the biometric authentication mode changes.
+ *
+ * @param wakeAndUnlock If the type is {@link BiometricUnlockController#isWakeAndUnlock()}
+ * @param isUnlock If the type is {@link BiometricUnlockController#isBiometricUnlock()} ()
+ */
+ public void onBiometricAuthModeChanged(boolean wakeAndUnlock, boolean isUnlock) {
+ if (mLockIcon != null) {
+ mLockIcon.onBiometricAuthModeChanged(wakeAndUnlock, isUnlock);
+ }
+ }
+
+ public void setStatusBarView(PhoneStatusBarView statusBarView) {
+ mStatusBarView = statusBarView;
+ }
+
+ public void setService(StatusBar statusBar) {
+ mService = statusBar;
+ NotificationStackScrollLayout stackScrollLayout = getStackScrollLayout();
+ ExpandHelper.Callback expandHelperCallback = stackScrollLayout.getExpandHelperCallback();
+ DragDownHelper.DragDownCallback dragDownCallback = stackScrollLayout.getDragDownCallback();
+ setDragDownHelper(
+ new DragDownHelper(
+ mView.getContext(), mView, expandHelperCallback,
+ dragDownCallback, mFalsingManager));
+ }
+
+ @VisibleForTesting
+ void setDragDownHelper(DragDownHelper dragDownHelper) {
+ mDragDownHelper = dragDownHelper;
+ }
+
+ public void suppressWakeUpGesture(boolean suppress) {
+ mSuppressingWakeUpGesture = suppress;
+ }
+
+ /**
+ * When we're launching an affordance, like double pressing power to open camera.
+ */
+ public void onShowingLaunchAffordanceChanged(Boolean showing) {
+ if (mLockIcon != null) {
+ mLockIcon.onShowingLaunchAffordanceChanged(showing);
+ }
+ }
+
+ public void setBouncerShowingScrimmed(boolean bouncerShowing) {
+ if (mLockIcon != null) {
+ mLockIcon.setBouncerShowingScrimmed(bouncerShowing);
+ }
+ }
+
+ /**
+ * When {@link KeyguardBouncer} starts to be dismissed and starts to play its animation.
+ */
+ public void onBouncerPreHideAnimation() {
+ if (mLockIcon != null) {
+ mLockIcon.onBouncerPreHideAnimation();
+ }
+ }
+
+ /**
+ * Builder for {@link StatusBarWindowViewController}.
+ */
+ public static class Builder {
+ private final InjectionInflationController mInjectionInflationController;
+ private final NotificationWakeUpCoordinator mCoordinator;
+ private final PulseExpansionHandler mPulseExpansionHandler;
+ private final DynamicPrivacyController mDynamicPrivacyController;
+ private final KeyguardBypassController mBypassController;
+ private final FalsingManager mFalsingManager;
+ private final PluginManager mPluginManager;
+ private final TunerService mTunerService;
+ private final KeyguardStateController mKeyguardStateController;
+ private final SysuiStatusBarStateController mStatusBarStateController;
+ private ShadeController mShadeController;
+ private final NotificationLockscreenUserManager mNotificationLockScreenUserManager;
+ private final NotificationEntryManager mNotificationEntryManager;
+ private final DozeLog mDozeLog;
+ private final DozeParameters mDozeParameters;
+ private StatusBarWindowView mView;
+
+ @Inject
+ public Builder(
+ InjectionInflationController injectionInflationController,
+ NotificationWakeUpCoordinator coordinator,
+ PulseExpansionHandler pulseExpansionHandler,
+ DynamicPrivacyController dynamicPrivacyController,
+ KeyguardBypassController bypassController,
+ FalsingManager falsingManager,
+ PluginManager pluginManager,
+ TunerService tunerService,
+ NotificationLockscreenUserManager notificationLockscreenUserManager,
+ NotificationEntryManager notificationEntryManager,
+ KeyguardStateController keyguardStateController,
+ StatusBarStateController statusBarStateController,
+ DozeLog dozeLog,
+ DozeParameters dozeParameters) {
+ mInjectionInflationController = injectionInflationController;
+ mCoordinator = coordinator;
+ mPulseExpansionHandler = pulseExpansionHandler;
+ mDynamicPrivacyController = dynamicPrivacyController;
+ mBypassController = bypassController;
+ mFalsingManager = falsingManager;
+ mPluginManager = pluginManager;
+ mTunerService = tunerService;
+ mNotificationLockScreenUserManager = notificationLockscreenUserManager;
+ mNotificationEntryManager = notificationEntryManager;
+ mKeyguardStateController = keyguardStateController;
+ mStatusBarStateController = (SysuiStatusBarStateController) statusBarStateController;
+ mDozeLog = dozeLog;
+ mDozeParameters = dozeParameters;
+ }
+
+ /**
+ * Provide {@link StatusBarWindowView} to attach this controller to.
+ */
+ public Builder setStatusBarWindowView(StatusBarWindowView view) {
+ mView = view;
+ return this;
+ }
+
+ /**
+ * Provide {@link ShadeController} that this view needs.
+ */
+ public Builder setShadeController(ShadeController shadeController) {
+ mShadeController = shadeController;
+ return this;
+ }
+
+ /**
+ * Build a {@link StatusBarWindowView}.
+ */
+ public StatusBarWindowViewController build() {
+ return new StatusBarWindowViewController(
+ mView,
+ mInjectionInflationController,
+ mCoordinator,
+ mPulseExpansionHandler,
+ mDynamicPrivacyController,
+ mBypassController,
+ mFalsingManager,
+ mPluginManager,
+ mTunerService,
+ mShadeController,
+ mNotificationLockScreenUserManager,
+ mNotificationEntryManager,
+ mKeyguardStateController,
+ mStatusBarStateController,
+ mDozeLog,
+ mDozeParameters);
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SystemUIDialog.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SystemUIDialog.java
index e61a67c77602..44be6bc282a7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SystemUIDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SystemUIDialog.java
@@ -28,7 +28,8 @@ import android.view.WindowManager.LayoutParams;
import com.android.systemui.Dependency;
import com.android.systemui.R;
-import com.android.systemui.statusbar.policy.KeyguardMonitor;
+import com.android.systemui.broadcast.BroadcastDispatcher;
+import com.android.systemui.statusbar.policy.KeyguardStateController;
/**
@@ -92,15 +93,15 @@ public class SystemUIDialog extends AlertDialog {
public static void setShowForAllUsers(Dialog dialog, boolean show) {
if (show) {
dialog.getWindow().getAttributes().privateFlags |=
- WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
+ WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS;
} else {
dialog.getWindow().getAttributes().privateFlags &=
- ~WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
+ ~WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS;
}
}
public static void setWindowOnTop(Dialog dialog) {
- if (Dependency.get(KeyguardMonitor.class).isShowing()) {
+ if (Dependency.get(KeyguardStateController.class).isShowing()) {
dialog.getWindow().setType(LayoutParams.TYPE_STATUS_BAR_PANEL);
} else {
dialog.getWindow().setType(LayoutParams.TYPE_STATUS_BAR_SUB_PANEL);
@@ -138,20 +139,21 @@ public class SystemUIDialog extends AlertDialog {
private final Dialog mDialog;
private boolean mRegistered;
+ private final BroadcastDispatcher mBroadcastDispatcher;
DismissReceiver(Dialog dialog) {
mDialog = dialog;
+ mBroadcastDispatcher = Dependency.get(BroadcastDispatcher.class);
}
void register() {
- mDialog.getContext()
- .registerReceiverAsUser(this, UserHandle.CURRENT, INTENT_FILTER, null, null);
+ mBroadcastDispatcher.registerReceiver(this, INTENT_FILTER, null, UserHandle.CURRENT);
mRegistered = true;
}
void unregister() {
if (mRegistered) {
- mDialog.getContext().unregisterReceiver(this);
+ mBroadcastDispatcher.unregisterReceiver(this);
mRegistered = false;
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockMethodCache.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockMethodCache.java
deleted file mode 100644
index c76f93e5ebaa..000000000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockMethodCache.java
+++ /dev/null
@@ -1,229 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.systemui.statusbar.phone;
-
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.hardware.biometrics.BiometricSourceType;
-import android.os.Build;
-import android.os.Trace;
-
-import com.android.internal.widget.LockPatternUtils;
-import com.android.keyguard.KeyguardUpdateMonitor;
-import com.android.keyguard.KeyguardUpdateMonitorCallback;
-import com.android.systemui.DejankUtils;
-import com.android.systemui.Dependency;
-
-import java.io.PrintWriter;
-import java.util.ArrayList;
-
-/**
- * Caches whether the current unlock method is insecure, taking trust into account. This information
- * might be a little bit out of date and should not be used for actual security decisions; it should
- * be only used for visual indications.
- */
-public class UnlockMethodCache {
-
- private static UnlockMethodCache sInstance;
- private static final boolean DEBUG_AUTH_WITH_ADB = false;
- private static final String AUTH_BROADCAST_KEY = "debug_trigger_auth";
-
- private final LockPatternUtils mLockPatternUtils;
- private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
- private final ArrayList<OnUnlockMethodChangedListener> mListeners = new ArrayList<>();
- /** Whether the user configured a secure unlock method (PIN, password, etc.) */
- private boolean mSecure;
- /** Whether the unlock method is currently insecure (insecure method or trusted environment) */
- private boolean mCanSkipBouncer;
- private boolean mTrustManaged;
- private boolean mTrusted;
- private boolean mDebugUnlocked = false;
- private boolean mFaceAuthEnabled;
-
- private UnlockMethodCache(Context ctx) {
- mLockPatternUtils = new LockPatternUtils(ctx);
- mKeyguardUpdateMonitor = Dependency.get(KeyguardUpdateMonitor.class);
- Dependency.get(KeyguardUpdateMonitor.class).registerCallback(mCallback);
- update(true /* updateAlways */);
- if (Build.IS_DEBUGGABLE && DEBUG_AUTH_WITH_ADB) {
- // Watch for interesting updates
- final IntentFilter filter = new IntentFilter();
- filter.addAction(AUTH_BROADCAST_KEY);
- ctx.registerReceiver(new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- if (DEBUG_AUTH_WITH_ADB && AUTH_BROADCAST_KEY.equals(intent.getAction())) {
- mDebugUnlocked = !mDebugUnlocked;
- update(true /* updateAlways */);
- }
- }
- }, filter, null, null);
- }
- }
-
- public static UnlockMethodCache getInstance(Context context) {
- if (sInstance == null) {
- sInstance = new UnlockMethodCache(context);
- }
- return sInstance;
- }
-
- /**
- * @return whether the user configured a secure unlock method like PIN, password, etc.
- */
- public boolean isMethodSecure() {
- return mSecure;
- }
-
- public boolean isTrusted() {
- return mTrusted;
- }
-
- /**
- * @return whether the lockscreen is currently insecure, and the bouncer won't be shown
- */
- public boolean canSkipBouncer() {
- return mCanSkipBouncer;
- }
-
- public void addListener(OnUnlockMethodChangedListener listener) {
- mListeners.add(listener);
- }
-
- public void removeListener(OnUnlockMethodChangedListener listener) {
- mListeners.remove(listener);
- }
-
- /**
- * If there are faces enrolled and user enabled face auth on keyguard.
- */
- public boolean isFaceAuthEnabled() {
- return mFaceAuthEnabled;
- }
-
- private void update(boolean updateAlways) {
- Trace.beginSection("UnlockMethodCache#update");
- int user = KeyguardUpdateMonitor.getCurrentUser();
- boolean secure = mLockPatternUtils.isSecure(user);
- boolean canSkipBouncer = !secure || mKeyguardUpdateMonitor.getUserCanSkipBouncer(user)
- || (Build.IS_DEBUGGABLE && DEBUG_AUTH_WITH_ADB && mDebugUnlocked);
- boolean trustManaged = mKeyguardUpdateMonitor.getUserTrustIsManaged(user);
- boolean trusted = mKeyguardUpdateMonitor.getUserHasTrust(user);
- boolean faceAuthEnabled = mKeyguardUpdateMonitor.isFaceAuthEnabledForUser(user);
- boolean changed = secure != mSecure || canSkipBouncer != mCanSkipBouncer
- || trustManaged != mTrustManaged
- || mFaceAuthEnabled != faceAuthEnabled;
- if (changed || updateAlways) {
- mSecure = secure;
- mCanSkipBouncer = canSkipBouncer;
- mTrusted = trusted;
- mTrustManaged = trustManaged;
- mFaceAuthEnabled = faceAuthEnabled;
- Trace.endSection();
- notifyListeners();
- } else {
- Trace.endSection();
- }
- }
-
- private void notifyListeners() {
- String tag = "UnlockMethodCache#notifyListeners";
- DejankUtils.startDetectingBlockingIpcs(tag);
- for (OnUnlockMethodChangedListener listener : mListeners) {
- listener.onUnlockMethodStateChanged();
- }
- DejankUtils.stopDetectingBlockingIpcs(tag);
- }
-
- public void dump(PrintWriter pw) {
- pw.println("UnlockMethodCache");
- pw.println(" mSecure: " + mSecure);
- pw.println(" mCanSkipBouncer: " + mCanSkipBouncer);
- pw.println(" mTrustManaged: " + mTrustManaged);
- pw.println(" mTrusted: " + mTrusted);
- pw.println(" mDebugUnlocked: " + mDebugUnlocked);
- pw.println(" mFaceAuthEnabled: " + mFaceAuthEnabled);
- }
-
- private final KeyguardUpdateMonitorCallback mCallback = new KeyguardUpdateMonitorCallback() {
- @Override
- public void onUserSwitchComplete(int userId) {
- update(false /* updateAlways */);
- }
-
- @Override
- public void onTrustChanged(int userId) {
- update(false /* updateAlways */);
- }
-
- @Override
- public void onTrustManagedChanged(int userId) {
- update(false /* updateAlways */);
- }
-
- @Override
- public void onStartedWakingUp() {
- update(false /* updateAlways */);
- }
-
- @Override
- public void onBiometricAuthenticated(int userId, BiometricSourceType biometricSourceType) {
- Trace.beginSection("KeyguardUpdateMonitorCallback#onBiometricAuthenticated");
- if (!mKeyguardUpdateMonitor.isUnlockingWithBiometricAllowed()) {
- Trace.endSection();
- return;
- }
- update(false /* updateAlways */);
- Trace.endSection();
- }
-
- @Override
- public void onFaceUnlockStateChanged(boolean running, int userId) {
- update(false /* updateAlways */);
- }
-
- @Override
- public void onStrongAuthStateChanged(int userId) {
- update(false /* updateAlways */);
- }
-
- @Override
- public void onScreenTurnedOff() {
- update(false /* updateAlways */);
- }
-
- @Override
- public void onKeyguardVisibilityChanged(boolean showing) {
- update(false /* updateAlways */);
- }
-
- @Override
- public void onBiometricsCleared() {
- update(false /* alwaysUpdate */);
- }
- };
-
- public boolean isTrustManaged() {
- return mTrustManaged;
- }
-
- public static interface OnUnlockMethodChangedListener {
- void onUnlockMethodStateChanged();
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java
index 111cdd2cc32a..738d076e13c5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java
@@ -45,9 +45,7 @@ public interface BatteryController extends DemoMode, Dumpable,
/**
* Returns {@code true} if AOD was disabled by power saving policies.
*/
- default boolean isAodPowerSave() {
- return isPowerSave();
- }
+ boolean isAodPowerSave();
/**
* A listener that will be notified whenever a change in battery level or power save mode has
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothControllerImpl.java
index 0a2fb2e783a9..76683b6a5e6a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothControllerImpl.java
@@ -16,9 +16,6 @@
package com.android.systemui.statusbar.policy;
-import static com.android.systemui.Dependency.BG_LOOPER_NAME;
-import static com.android.systemui.Dependency.MAIN_LOOPER_NAME;
-
import android.annotation.Nullable;
import android.app.ActivityManager;
import android.bluetooth.BluetoothAdapter;
@@ -36,6 +33,8 @@ import com.android.settingslib.bluetooth.BluetoothCallback;
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
import com.android.settingslib.bluetooth.LocalBluetoothManager;
import com.android.settingslib.bluetooth.LocalBluetoothProfileManager;
+import com.android.systemui.dagger.qualifiers.BgLooper;
+import com.android.systemui.dagger.qualifiers.MainLooper;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -46,7 +45,6 @@ import java.util.List;
import java.util.WeakHashMap;
import javax.inject.Inject;
-import javax.inject.Named;
import javax.inject.Singleton;
/**
@@ -74,9 +72,8 @@ public class BluetoothControllerImpl implements BluetoothController, BluetoothCa
/**
*/
@Inject
- public BluetoothControllerImpl(Context context, @Named(BG_LOOPER_NAME) Looper bgLooper,
- @Named(MAIN_LOOPER_NAME) Looper mainLooper,
- @Nullable LocalBluetoothManager localBluetoothManager) {
+ public BluetoothControllerImpl(Context context, @BgLooper Looper bgLooper,
+ @MainLooper Looper mainLooper, @Nullable LocalBluetoothManager localBluetoothManager) {
mLocalBluetoothManager = localBluetoothManager;
mBgHandler = new Handler(bgLooper);
mHandler = new H(mainLooper);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java
index c2c3f81527e8..b331fc3bf0ce 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java
@@ -16,6 +16,8 @@
package com.android.systemui.statusbar.policy;
+import static com.android.systemui.util.InjectionInflationController.VIEW_CONTEXT;
+
import android.app.StatusBarManager;
import android.content.BroadcastReceiver;
import android.content.Context;
@@ -44,6 +46,7 @@ import com.android.systemui.Dependency;
import com.android.systemui.FontSizeUtils;
import com.android.systemui.R;
import com.android.systemui.SysUiServiceProvider;
+import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.plugins.DarkIconDispatcher;
import com.android.systemui.plugins.DarkIconDispatcher.DarkReceiver;
import com.android.systemui.settings.CurrentUserTracker;
@@ -60,6 +63,9 @@ import java.util.Calendar;
import java.util.Locale;
import java.util.TimeZone;
+import javax.inject.Inject;
+import javax.inject.Named;
+
/**
* Digital clock for the status bar.
*/
@@ -107,15 +113,20 @@ public class Clock extends TextView implements DemoMode, Tunable, CommandQueue.C
*/
private int mNonAdaptedColor;
- public Clock(Context context) {
- this(context, null);
- }
+ private final BroadcastDispatcher mBroadcastDispatcher;
public Clock(Context context, AttributeSet attrs) {
- this(context, attrs, 0);
+ this(context, attrs, null);
+ }
+
+ @Inject
+ public Clock(@Named(VIEW_CONTEXT) Context context, AttributeSet attrs,
+ BroadcastDispatcher broadcastDispatcher) {
+ this(context, attrs, 0, broadcastDispatcher);
}
- public Clock(Context context, AttributeSet attrs, int defStyle) {
+ public Clock(Context context, AttributeSet attrs, int defStyle,
+ BroadcastDispatcher broadcastDispatcher) {
super(context, attrs, defStyle);
TypedArray a = context.getTheme().obtainStyledAttributes(
attrs,
@@ -134,6 +145,7 @@ public class Clock extends TextView implements DemoMode, Tunable, CommandQueue.C
mCurrentUserId = newUserId;
}
};
+ mBroadcastDispatcher = broadcastDispatcher;
}
@Override
@@ -358,11 +370,11 @@ public class Clock extends TextView implements DemoMode, Tunable, CommandQueue.C
}
IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_OFF);
filter.addAction(Intent.ACTION_SCREEN_ON);
- mContext.registerReceiver(mScreenReceiver, filter);
+ mBroadcastDispatcher.registerReceiver(mScreenReceiver, filter);
}
} else {
if (mSecondsHandler != null) {
- mContext.unregisterReceiver(mScreenReceiver);
+ mBroadcastDispatcher.unregisterReceiver(mScreenReceiver);
mSecondsHandler.removeCallbacks(mSecondTick);
mSecondsHandler = null;
updateClock();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceProvisionedControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceProvisionedControllerImpl.java
index 089d5c924de8..0a40b3c4831c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceProvisionedControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceProvisionedControllerImpl.java
@@ -14,8 +14,6 @@
package com.android.systemui.statusbar.policy;
-import static com.android.systemui.Dependency.MAIN_HANDLER_NAME;
-
import android.app.ActivityManager;
import android.content.ContentResolver;
import android.content.Context;
@@ -26,12 +24,12 @@ import android.provider.Settings.Global;
import android.provider.Settings.Secure;
import android.util.Log;
+import com.android.systemui.dagger.qualifiers.MainHandler;
import com.android.systemui.settings.CurrentUserTracker;
import java.util.ArrayList;
import javax.inject.Inject;
-import javax.inject.Named;
import javax.inject.Singleton;
/**
@@ -51,8 +49,7 @@ public class DeviceProvisionedControllerImpl extends CurrentUserTracker implemen
/**
*/
@Inject
- public DeviceProvisionedControllerImpl(Context context,
- @Named(MAIN_HANDLER_NAME) Handler mainHandler) {
+ public DeviceProvisionedControllerImpl(Context context, @MainHandler Handler mainHandler) {
super(context);
mContext = context;
mContentResolver = context.getContentResolver();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ExtensionController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ExtensionController.java
index cade5dc46388..3ce62396fbb5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ExtensionController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ExtensionController.java
@@ -57,7 +57,7 @@ public interface ExtensionController {
ExtensionBuilder<T> withCallback(Consumer<T> callback);
ExtensionBuilder<T> withUiMode(int mode, Supplier<T> def);
ExtensionBuilder<T> withFeature(String feature, Supplier<T> def);
- Extension build();
+ Extension<T> build();
}
public interface PluginConverter<T, P> {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ExtensionControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ExtensionControllerImpl.java
index fd030d133be0..eeef726ace75 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ExtensionControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ExtensionControllerImpl.java
@@ -135,7 +135,7 @@ public class ExtensionControllerImpl implements ExtensionController {
}
@Override
- public ExtensionController.Extension build() {
+ public ExtensionController.Extension<T> build() {
// Sort items in ascending order
Collections.sort(mExtension.mProducers, Comparator.comparingInt(Item::sortOrder));
mExtension.notifyChanged();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java
index b84dc476dd6f..6828c322dea2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java
@@ -117,7 +117,7 @@ public abstract class HeadsUpManager extends AlertingNotificationManager {
}
protected boolean hasFullScreenIntent(@NonNull NotificationEntry entry) {
- return entry.notification.getNotification().fullScreenIntent != null;
+ return entry.getSbn().getNotification().fullScreenIntent != null;
}
protected void setEntryPinned(
@@ -206,7 +206,7 @@ public abstract class HeadsUpManager extends AlertingNotificationManager {
public void snooze() {
for (String key : mAlertEntries.keySet()) {
AlertEntry entry = getHeadsUpEntry(key);
- String packageName = entry.mEntry.notification.getPackageName();
+ String packageName = entry.mEntry.getSbn().getPackageName();
mSnoozedPackages.put(snoozeKey(packageName, mUser),
mClock.currentTimeMillis() + mSnoozeLengthMs);
}
@@ -328,8 +328,8 @@ public abstract class HeadsUpManager extends AlertingNotificationManager {
* one should be ranked higher and 0 if they are equal.
*/
public int compare(@NonNull NotificationEntry a, @NonNull NotificationEntry b) {
- AlertEntry aEntry = getHeadsUpEntry(a.key);
- AlertEntry bEntry = getHeadsUpEntry(b.key);
+ AlertEntry aEntry = getHeadsUpEntry(a.getKey());
+ AlertEntry bEntry = getHeadsUpEntry(b.getKey());
if (aEntry == null || bEntry == null) {
return aEntry == null ? 1 : -1;
}
@@ -341,7 +341,7 @@ public abstract class HeadsUpManager extends AlertingNotificationManager {
* until it's collapsed again.
*/
public void setExpanded(@NonNull NotificationEntry entry, boolean expanded) {
- HeadsUpEntry headsUpEntry = getHeadsUpEntry(entry.key);
+ HeadsUpEntry headsUpEntry = getHeadsUpEntry(entry.getKey());
if (headsUpEntry != null && entry.isRowPinned()) {
headsUpEntry.setExpanded(expanded);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java
index 4df0c6051f42..e8bc7db6d5c7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java
@@ -16,8 +16,6 @@
package com.android.systemui.statusbar.policy;
-import static com.android.systemui.Dependency.MAIN_HANDLER_NAME;
-
import android.app.ActivityManager;
import android.content.Context;
import android.net.ConnectivityManager;
@@ -26,12 +24,13 @@ import android.os.Handler;
import android.os.UserManager;
import android.util.Log;
+import com.android.systemui.dagger.qualifiers.MainHandler;
+
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
import javax.inject.Inject;
-import javax.inject.Named;
import javax.inject.Singleton;
/**
@@ -56,7 +55,7 @@ public class HotspotControllerImpl implements HotspotController, WifiManager.Sof
/**
*/
@Inject
- public HotspotControllerImpl(Context context, @Named(MAIN_HANDLER_NAME) Handler mainHandler) {
+ public HotspotControllerImpl(Context context, @MainHandler Handler mainHandler) {
mContext = context;
mConnectivityManager =
(ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/InflatedSmartReplies.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/InflatedSmartReplies.java
index be27741b4dc8..c6ae669d5d08 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/InflatedSmartReplies.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/InflatedSmartReplies.java
@@ -144,13 +144,13 @@ public class InflatedSmartReplies {
return false;
}
// If we are showing the spinner we don't want to add the buttons.
- boolean showingSpinner = entry.notification.getNotification()
+ boolean showingSpinner = entry.getSbn().getNotification()
.extras.getBoolean(Notification.EXTRA_SHOW_REMOTE_INPUT_SPINNER, false);
if (showingSpinner) {
return false;
}
// If we are keeping the notification around while sending we don't want to add the buttons.
- boolean hideSmartReplies = entry.notification.getNotification()
+ boolean hideSmartReplies = entry.getSbn().getNotification()
.extras.getBoolean(Notification.EXTRA_HIDE_SMART_REPLIES, false);
if (hideSmartReplies) {
return false;
@@ -168,7 +168,7 @@ public class InflatedSmartReplies {
public static SmartRepliesAndActions chooseSmartRepliesAndActions(
SmartReplyConstants smartReplyConstants,
final NotificationEntry entry) {
- Notification notification = entry.notification.getNotification();
+ Notification notification = entry.getSbn().getNotification();
Pair<RemoteInput, Notification.Action> remoteInputActionPair =
notification.findRemoteInputActionPair(false /* freeform */);
Pair<RemoteInput, Notification.Action> freeformRemoteInputActionPair =
@@ -177,7 +177,7 @@ public class InflatedSmartReplies {
if (!smartReplyConstants.isEnabled()) {
if (DEBUG) {
Log.d(TAG, "Smart suggestions not enabled, not adding suggestions for "
- + entry.notification.getKey());
+ + entry.getSbn().getKey());
}
return new SmartRepliesAndActions(null, null);
}
@@ -271,7 +271,7 @@ public class InflatedSmartReplies {
* through the remote input.
*/
public static boolean hasFreeformRemoteInput(NotificationEntry entry) {
- Notification notification = entry.notification.getNotification();
+ Notification notification = entry.getSbn().getNotification();
return null != notification.findRemoteInputActionPair(true /* freeform */);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitor.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitor.java
deleted file mode 100644
index 6dc90b9028fa..000000000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitor.java
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software distributed under the
- * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the specific language governing
- * permissions and limitations under the License.
- */
-
-package com.android.systemui.statusbar.policy;
-
-import com.android.systemui.statusbar.policy.KeyguardMonitor.Callback;
-
-public interface KeyguardMonitor extends CallbackController<Callback> {
-
- boolean isSecure();
- boolean isShowing();
- boolean isOccluded();
- boolean isKeyguardFadingAway();
- boolean isKeyguardGoingAway();
- boolean isLaunchTransitionFadingAway();
- long getKeyguardFadingAwayDuration();
- long getKeyguardFadingAwayDelay();
- long calculateGoingToFullShadeDelay();
-
- /**
- * @return a shortened fading away duration similar to
- * {{@link #getKeyguardFadingAwayDuration()}} which may only span half of the duration, unless
- * we're bypassing
- */
- default long getShortenedFadingAwayDuration() {
- if (isBypassFadingAnimation()) {
- return getKeyguardFadingAwayDuration();
- } else {
- return getKeyguardFadingAwayDuration() / 2;
- }
- }
-
- default boolean isDeviceInteractive() {
- return false;
- }
-
- default void setLaunchTransitionFadingAway(boolean b) {
- }
-
- default void notifyKeyguardGoingAway(boolean b) {
- }
-
- /**
- * @return {@code true} if the current fading away animation is the fast bypass fading.
- */
- default boolean isBypassFadingAnimation() {
- return false;
- }
-
- /**
- * Notifies that the Keyguard is fading away with the specified timings.
- * @param delay the precalculated animation delay in milliseconds
- * @param fadeoutDuration the duration of the exit animation, in milliseconds
- * @param isBypassFading is this a fading away animation while bypassing
- */
- default void notifyKeyguardFadingAway(long delay, long fadeoutDuration,
- boolean isBypassFading) {
- }
-
- default void notifyKeyguardDoneFading() {
- }
-
- default void notifyKeyguardState(boolean showing, boolean methodSecure, boolean occluded) {
- }
-
- interface Callback {
- default void onKeyguardShowingChanged() {}
- default void onKeyguardFadingAwayChanged() {}
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitorImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitorImpl.java
deleted file mode 100644
index e8b0f9b2864e..000000000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitorImpl.java
+++ /dev/null
@@ -1,183 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.statusbar.policy;
-
-import android.annotation.NonNull;
-import android.content.Context;
-
-import com.android.internal.util.Preconditions;
-import com.android.keyguard.KeyguardUpdateMonitor;
-import com.android.keyguard.KeyguardUpdateMonitorCallback;
-import com.android.systemui.Dependency;
-
-import java.util.ArrayList;
-
-import javax.inject.Inject;
-import javax.inject.Singleton;
-
-/**
- */
-@Singleton
-public class KeyguardMonitorImpl extends KeyguardUpdateMonitorCallback
- implements KeyguardMonitor {
-
- private final ArrayList<Callback> mCallbacks = new ArrayList<>();
-
- private final Context mContext;
- private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
-
- private boolean mShowing;
- private boolean mSecure;
- private boolean mOccluded;
-
- private boolean mListening;
- private boolean mKeyguardFadingAway;
- private long mKeyguardFadingAwayDelay;
- private long mKeyguardFadingAwayDuration;
- private boolean mKeyguardGoingAway;
- private boolean mLaunchTransitionFadingAway;
- private boolean mBypassFadingAnimation;
-
- /**
- */
- @Inject
- public KeyguardMonitorImpl(Context context) {
- mContext = context;
- mKeyguardUpdateMonitor = Dependency.get(KeyguardUpdateMonitor.class);
- }
-
- @Override
- public void addCallback(@NonNull Callback callback) {
- Preconditions.checkNotNull(callback, "Callback must not be null. b/128895449");
- mCallbacks.add(callback);
- if (mCallbacks.size() != 0 && !mListening) {
- mListening = true;
- mKeyguardUpdateMonitor.registerCallback(this);
- }
- }
-
- @Override
- public void removeCallback(@NonNull Callback callback) {
- Preconditions.checkNotNull(callback, "Callback must not be null. b/128895449");
- if (mCallbacks.remove(callback) && mCallbacks.size() == 0 && mListening) {
- mListening = false;
- mKeyguardUpdateMonitor.removeCallback(this);
- }
- }
-
- @Override
- public boolean isShowing() {
- return mShowing;
- }
-
- @Override
- public boolean isSecure() {
- return mSecure;
- }
-
- @Override
- public boolean isOccluded() {
- return mOccluded;
- }
-
- public void notifyKeyguardState(boolean showing, boolean secure, boolean occluded) {
- if (mShowing == showing && mSecure == secure && mOccluded == occluded) return;
- mShowing = showing;
- mSecure = secure;
- mOccluded = occluded;
- notifyKeyguardChanged();
- }
-
- @Override
- public void onTrustChanged(int userId) {
- notifyKeyguardChanged();
- }
-
- public boolean isDeviceInteractive() {
- return mKeyguardUpdateMonitor.isDeviceInteractive();
- }
-
- private void notifyKeyguardChanged() {
- // Copy the list to allow removal during callback.
- new ArrayList<>(mCallbacks).forEach(Callback::onKeyguardShowingChanged);
- }
-
- public void notifyKeyguardFadingAway(long delay, long fadeoutDuration, boolean isBypassFading) {
- mKeyguardFadingAwayDelay = delay;
- mKeyguardFadingAwayDuration = fadeoutDuration;
- mBypassFadingAnimation = isBypassFading;
- setKeyguardFadingAway(true);
- }
-
- private void setKeyguardFadingAway(boolean keyguardFadingAway) {
- if (mKeyguardFadingAway != keyguardFadingAway) {
- mKeyguardFadingAway = keyguardFadingAway;
- ArrayList<Callback> callbacks = new ArrayList<>(mCallbacks);
- for (int i = 0; i < callbacks.size(); i++) {
- callbacks.get(i).onKeyguardFadingAwayChanged();
- }
- }
- }
-
- public void notifyKeyguardDoneFading() {
- mKeyguardGoingAway = false;
- setKeyguardFadingAway(false);
- }
-
- @Override
- public boolean isKeyguardFadingAway() {
- return mKeyguardFadingAway;
- }
-
- @Override
- public boolean isKeyguardGoingAway() {
- return mKeyguardGoingAway;
- }
-
- @Override
- public boolean isBypassFadingAnimation() {
- return mBypassFadingAnimation;
- }
-
- @Override
- public long getKeyguardFadingAwayDelay() {
- return mKeyguardFadingAwayDelay;
- }
-
- @Override
- public long getKeyguardFadingAwayDuration() {
- return mKeyguardFadingAwayDuration;
- }
-
- @Override
- public long calculateGoingToFullShadeDelay() {
- return mKeyguardFadingAwayDelay + mKeyguardFadingAwayDuration;
- }
-
- public void notifyKeyguardGoingAway(boolean keyguardGoingAway) {
- mKeyguardGoingAway = keyguardGoingAway;
- }
-
- public void setLaunchTransitionFadingAway(boolean fadingAway) {
- mLaunchTransitionFadingAway = fadingAway;
- }
-
- @Override
- public boolean isLaunchTransitionFadingAway() {
- return mLaunchTransitionFadingAway;
- }
-} \ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardStateController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardStateController.java
new file mode 100644
index 000000000000..692c34c62dd8
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardStateController.java
@@ -0,0 +1,177 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.policy;
+
+import com.android.systemui.statusbar.StatusBarState;
+import com.android.systemui.statusbar.policy.KeyguardStateController.Callback;
+
+/**
+ * Source of truth for keyguard state: If locked, occluded, has password, trusted etc.
+ */
+public interface KeyguardStateController extends CallbackController<Callback> {
+
+ /**
+ * If the device is locked or unlocked.
+ */
+ default boolean isUnlocked() {
+ return !isShowing() || canDismissLockScreen();
+ }
+
+ /**
+ * If the lock screen is visible.
+ * The keyguard is also visible when the device is asleep or in always on mode, except when
+ * the screen timed out and the user can unlock by quickly pressing power.
+ *
+ * This is unrelated to being locked or not.
+ *
+ * @see #isUnlocked()
+ * @see #canDismissLockScreen()
+ */
+ boolean isShowing();
+
+ /**
+ * If swiping up will unlock without asking for a password.
+ * @see #isUnlocked()
+ */
+ boolean canDismissLockScreen();
+
+ /**
+ * If the device has PIN/pattern/password or a lock screen at all.
+ */
+ boolean isMethodSecure();
+
+ /**
+ * When there's an {@link android.app.Activity} on top of the keyguard, where
+ * {@link android.app.Activity#setShowWhenLocked(boolean)} is true.
+ */
+ boolean isOccluded();
+
+ /**
+ * If a {@link android.service.trust.TrustAgentService} is keeping the device unlocked.
+ * {@link #canDismissLockScreen()} is better source of truth that also considers this state.
+ */
+ boolean isTrusted();
+
+ /**
+ * If the keyguard dismissal animation is running.
+ * @see #isKeyguardGoingAway()
+ */
+ boolean isKeyguardFadingAway();
+
+ /**
+ * When the keyguard challenge was successfully solved, and {@link android.app.ActivityManager}
+ * is launching the activity that will be revealed.
+ *
+ * This also includes the animation of the keyguard being dismissed, meaning that this will
+ * return {@code true} whenever {@link #isKeyguardFadingAway()} also returns {@code true}.
+ */
+ boolean isKeyguardGoingAway();
+
+ /**
+ * @return a shortened fading away duration similar to
+ * {{@link #getKeyguardFadingAwayDuration()}} which may only span half of the duration, unless
+ * we're bypassing
+ */
+ default long getShortenedFadingAwayDuration() {
+ if (isBypassFadingAnimation()) {
+ return getKeyguardFadingAwayDuration();
+ } else {
+ return getKeyguardFadingAwayDuration() / 2;
+ }
+ }
+
+ /**
+ * @return {@code true} if the current fading away animation is the fast bypass fading.
+ */
+ default boolean isBypassFadingAnimation() {
+ return false;
+ }
+
+ /**
+ * Notifies that the Keyguard is fading away with the specified timings.
+ * @param delay the precalculated animation delay in milliseconds
+ * @param fadeoutDuration the duration of the exit animation, in milliseconds
+ * @param isBypassFading is this a fading away animation while bypassing
+ */
+ default void notifyKeyguardFadingAway(long delay, long fadeoutDuration,
+ boolean isBypassFading) {
+ }
+
+ /**
+ * If there are faces enrolled and user enabled face auth on keyguard.
+ */
+ default boolean isFaceAuthEnabled() {
+ return false;
+ }
+
+ /**
+ * If the animation that morphs a notification into an app window is playing.
+ */
+ boolean isLaunchTransitionFadingAway();
+
+ /**
+ * How long the keyguard dismissal animation should take when unlocking.
+ */
+ long getKeyguardFadingAwayDuration();
+
+ /**
+ * Delay for {@link #getKeyguardFadingAwayDuration()}.
+ */
+ long getKeyguardFadingAwayDelay();
+
+ /**
+ * Delay when going from {@link StatusBarState#KEYGUARD} to {@link StatusBarState#SHADE} or
+ * {@link StatusBarState#SHADE_LOCKED}.
+ */
+ long calculateGoingToFullShadeDelay();
+
+ /** **/
+ default void setLaunchTransitionFadingAway(boolean b) {}
+ /** **/
+ default void notifyKeyguardGoingAway(boolean b) {}
+ /** **/
+ default void notifyKeyguardDoneFading() {}
+ /** **/
+ default void notifyKeyguardState(boolean showing, boolean occluded) {}
+
+ /**
+ * Callback for authentication events.
+ */
+ interface Callback {
+ /**
+ * Called when the locked state of the device changes. The lock screen might still be
+ * showing on some cases, like when a {@link android.service.trust.TrustAgentService} is
+ * active, or face auth was triggered but the user didn't swipe up to dismiss the lock
+ * screen yet.
+ */
+ default void onUnlockedChanged() {}
+
+ /**
+ * If the lock screen is active or not. This is different from being locked, since the lock
+ * screen can be visible but unlocked by {@link android.service.trust.TrustAgentService} or
+ * face unlock.
+ *
+ * @see #isShowing()
+ */
+ default void onKeyguardShowingChanged() {}
+
+ /**
+ * Triggered when the device was just unlocked and the lock screen is being dismissed.
+ */
+ default void onKeyguardFadingAwayChanged() {}
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardStateControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardStateControllerImpl.java
new file mode 100644
index 000000000000..1cb2bd430199
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardStateControllerImpl.java
@@ -0,0 +1,326 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.policy;
+
+import android.annotation.NonNull;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.hardware.biometrics.BiometricSourceType;
+import android.os.Build;
+import android.os.Trace;
+
+import androidx.annotation.VisibleForTesting;
+
+import com.android.internal.util.Preconditions;
+import com.android.internal.widget.LockPatternUtils;
+import com.android.keyguard.KeyguardUpdateMonitor;
+import com.android.keyguard.KeyguardUpdateMonitorCallback;
+import com.android.systemui.Dumpable;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+/**
+ */
+@Singleton
+public class KeyguardStateControllerImpl implements KeyguardStateController, Dumpable {
+
+ private static final boolean DEBUG_AUTH_WITH_ADB = false;
+ private static final String AUTH_BROADCAST_KEY = "debug_trigger_auth";
+
+ private final ArrayList<Callback> mCallbacks = new ArrayList<>();
+ private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
+ private final LockPatternUtils mLockPatternUtils;
+ private final KeyguardUpdateMonitorCallback mKeyguardUpdateMonitorCallback =
+ new UpdateMonitorCallback();
+
+ private boolean mCanDismissLockScreen;
+ private boolean mShowing;
+ private boolean mSecure;
+ private boolean mOccluded;
+
+ private boolean mKeyguardFadingAway;
+ private long mKeyguardFadingAwayDelay;
+ private long mKeyguardFadingAwayDuration;
+ private boolean mKeyguardGoingAway;
+ private boolean mLaunchTransitionFadingAway;
+ private boolean mBypassFadingAnimation;
+ private boolean mTrustManaged;
+ private boolean mTrusted;
+ private boolean mDebugUnlocked = false;
+ private boolean mFaceAuthEnabled;
+
+ /**
+ */
+ @Inject
+ public KeyguardStateControllerImpl(Context context,
+ KeyguardUpdateMonitor keyguardUpdateMonitor, LockPatternUtils lockPatternUtils) {
+ mKeyguardUpdateMonitor = keyguardUpdateMonitor;
+ mLockPatternUtils = lockPatternUtils;
+ mKeyguardUpdateMonitor.registerCallback(mKeyguardUpdateMonitorCallback);
+
+ update(true /* updateAlways */);
+ if (Build.IS_DEBUGGABLE && DEBUG_AUTH_WITH_ADB) {
+ // Watch for interesting updates
+ final IntentFilter filter = new IntentFilter();
+ filter.addAction(AUTH_BROADCAST_KEY);
+ context.registerReceiver(new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (DEBUG_AUTH_WITH_ADB && AUTH_BROADCAST_KEY.equals(intent.getAction())) {
+ mDebugUnlocked = !mDebugUnlocked;
+ update(true /* updateAlways */);
+ }
+ }
+ }, filter, null, null);
+ }
+ }
+
+ @Override
+ public void addCallback(@NonNull Callback callback) {
+ Preconditions.checkNotNull(callback, "Callback must not be null. b/128895449");
+ if (!mCallbacks.contains(callback)) {
+ mCallbacks.add(callback);
+ }
+ }
+
+ @Override
+ public void removeCallback(@NonNull Callback callback) {
+ Preconditions.checkNotNull(callback, "Callback must not be null. b/128895449");
+ mCallbacks.remove(callback);
+ }
+
+ @Override
+ public boolean isShowing() {
+ return mShowing;
+ }
+
+ @Override
+ public boolean isMethodSecure() {
+ return mSecure;
+ }
+
+ @Override
+ public boolean isOccluded() {
+ return mOccluded;
+ }
+
+ @Override
+ public boolean isTrusted() {
+ return mTrusted;
+ }
+
+ @Override
+ public void notifyKeyguardState(boolean showing, boolean occluded) {
+ if (mShowing == showing && mOccluded == occluded) return;
+ mShowing = showing;
+ mOccluded = occluded;
+ notifyKeyguardChanged();
+ }
+
+ private void notifyKeyguardChanged() {
+ Trace.beginSection("KeyguardStateController#notifyKeyguardChanged");
+ // Copy the list to allow removal during callback.
+ new ArrayList<>(mCallbacks).forEach(Callback::onKeyguardShowingChanged);
+ Trace.endSection();
+ }
+
+ private void notifyUnlockedChanged() {
+ Trace.beginSection("KeyguardStateController#notifyUnlockedChanged");
+ // Copy the list to allow removal during callback.
+ new ArrayList<>(mCallbacks).forEach(Callback::onUnlockedChanged);
+ Trace.endSection();
+ }
+
+ @Override
+ public void notifyKeyguardFadingAway(long delay, long fadeoutDuration, boolean isBypassFading) {
+ mKeyguardFadingAwayDelay = delay;
+ mKeyguardFadingAwayDuration = fadeoutDuration;
+ mBypassFadingAnimation = isBypassFading;
+ setKeyguardFadingAway(true);
+ }
+
+ private void setKeyguardFadingAway(boolean keyguardFadingAway) {
+ if (mKeyguardFadingAway != keyguardFadingAway) {
+ mKeyguardFadingAway = keyguardFadingAway;
+ ArrayList<Callback> callbacks = new ArrayList<>(mCallbacks);
+ for (int i = 0; i < callbacks.size(); i++) {
+ callbacks.get(i).onKeyguardFadingAwayChanged();
+ }
+ }
+ }
+
+ @Override
+ public void notifyKeyguardDoneFading() {
+ mKeyguardGoingAway = false;
+ setKeyguardFadingAway(false);
+ }
+
+ @VisibleForTesting
+ void update(boolean updateAlways) {
+ Trace.beginSection("KeyguardStateController#update");
+ int user = KeyguardUpdateMonitor.getCurrentUser();
+ boolean secure = mLockPatternUtils.isSecure(user);
+ boolean canDismissLockScreen = !secure || mKeyguardUpdateMonitor.getUserCanSkipBouncer(user)
+ || (Build.IS_DEBUGGABLE && DEBUG_AUTH_WITH_ADB && mDebugUnlocked);
+ boolean trustManaged = mKeyguardUpdateMonitor.getUserTrustIsManaged(user);
+ boolean trusted = mKeyguardUpdateMonitor.getUserHasTrust(user);
+ boolean faceAuthEnabled = mKeyguardUpdateMonitor.isFaceAuthEnabledForUser(user);
+ boolean changed = secure != mSecure || canDismissLockScreen != mCanDismissLockScreen
+ || trustManaged != mTrustManaged || mTrusted != trusted
+ || mFaceAuthEnabled != faceAuthEnabled;
+ if (changed || updateAlways) {
+ mSecure = secure;
+ mCanDismissLockScreen = canDismissLockScreen;
+ mTrusted = trusted;
+ mTrustManaged = trustManaged;
+ mFaceAuthEnabled = faceAuthEnabled;
+ notifyUnlockedChanged();
+ }
+ Trace.endSection();
+ }
+
+ @Override
+ public boolean canDismissLockScreen() {
+ return mCanDismissLockScreen;
+ }
+
+ @Override
+ public boolean isFaceAuthEnabled() {
+ return mFaceAuthEnabled;
+ }
+
+ @Override
+ public boolean isKeyguardFadingAway() {
+ return mKeyguardFadingAway;
+ }
+
+ @Override
+ public boolean isKeyguardGoingAway() {
+ return mKeyguardGoingAway;
+ }
+
+ @Override
+ public boolean isBypassFadingAnimation() {
+ return mBypassFadingAnimation;
+ }
+
+ @Override
+ public long getKeyguardFadingAwayDelay() {
+ return mKeyguardFadingAwayDelay;
+ }
+
+ @Override
+ public long getKeyguardFadingAwayDuration() {
+ return mKeyguardFadingAwayDuration;
+ }
+
+ @Override
+ public long calculateGoingToFullShadeDelay() {
+ return mKeyguardFadingAwayDelay + mKeyguardFadingAwayDuration;
+ }
+
+ @Override
+ public void notifyKeyguardGoingAway(boolean keyguardGoingAway) {
+ mKeyguardGoingAway = keyguardGoingAway;
+ }
+
+ @Override
+ public void setLaunchTransitionFadingAway(boolean fadingAway) {
+ mLaunchTransitionFadingAway = fadingAway;
+ }
+
+ @Override
+ public boolean isLaunchTransitionFadingAway() {
+ return mLaunchTransitionFadingAway;
+ }
+
+ /**
+ * Dumps internal state for debugging.
+ * @param pw Where to dump.
+ */
+ @Override
+ public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ pw.println("KeyguardStateController:");
+ pw.println(" mSecure: " + mSecure);
+ pw.println(" mCanDismissLockScreen: " + mCanDismissLockScreen);
+ pw.println(" mTrustManaged: " + mTrustManaged);
+ pw.println(" mTrusted: " + mTrusted);
+ pw.println(" mDebugUnlocked: " + mDebugUnlocked);
+ pw.println(" mFaceAuthEnabled: " + mFaceAuthEnabled);
+ }
+
+ private class UpdateMonitorCallback extends KeyguardUpdateMonitorCallback {
+ @Override
+ public void onUserSwitchComplete(int userId) {
+ update(false /* updateAlways */);
+ }
+
+ @Override
+ public void onTrustChanged(int userId) {
+ update(false /* updateAlways */);
+ notifyKeyguardChanged();
+ }
+
+ @Override
+ public void onTrustManagedChanged(int userId) {
+ update(false /* updateAlways */);
+ }
+
+ @Override
+ public void onStartedWakingUp() {
+ update(false /* updateAlways */);
+ }
+
+ @Override
+ public void onBiometricAuthenticated(int userId, BiometricSourceType biometricSourceType) {
+ Trace.beginSection("KeyguardUpdateMonitorCallback#onBiometricAuthenticated");
+ if (!mKeyguardUpdateMonitor.isUnlockingWithBiometricAllowed()) {
+ Trace.endSection();
+ return;
+ }
+ update(false /* updateAlways */);
+ Trace.endSection();
+ }
+
+ @Override
+ public void onFaceUnlockStateChanged(boolean running, int userId) {
+ update(false /* updateAlways */);
+ }
+
+ @Override
+ public void onStrongAuthStateChanged(int userId) {
+ update(false /* updateAlways */);
+ }
+
+ @Override
+ public void onKeyguardVisibilityChanged(boolean showing) {
+ update(false /* updateAlways */);
+ }
+
+ @Override
+ public void onBiometricsCleared() {
+ update(false /* alwaysUpdate */);
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationControllerImpl.java
index 683cdbb326dc..5a97eedd9b2c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationControllerImpl.java
@@ -17,7 +17,6 @@
package com.android.systemui.statusbar.policy;
import static com.android.settingslib.Utils.updateLocationEnabled;
-import static com.android.systemui.Dependency.BG_LOOPER_NAME;
import android.app.ActivityManager;
import android.app.AppOpsManager;
@@ -36,13 +35,13 @@ import android.provider.Settings;
import androidx.annotation.VisibleForTesting;
+import com.android.systemui.dagger.qualifiers.BgLooper;
import com.android.systemui.util.Utils;
import java.util.ArrayList;
import java.util.List;
import javax.inject.Inject;
-import javax.inject.Named;
import javax.inject.Singleton;
/**
@@ -66,7 +65,7 @@ public class LocationControllerImpl extends BroadcastReceiver implements Locatio
private final H mHandler = new H();
@Inject
- public LocationControllerImpl(Context context, @Named(BG_LOOPER_NAME) Looper bgLooper) {
+ public LocationControllerImpl(Context context, @BgLooper Looper bgLooper) {
mContext = context;
// Register to listen for changes in location settings.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
index 67739835a3fd..e36d28383bda 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
@@ -24,7 +24,6 @@ import static android.net.wifi.WifiManager.TrafficStateCallback.DATA_ACTIVITY_OU
import static android.telephony.PhoneStateListener.LISTEN_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGE;
import static com.android.internal.telephony.PhoneConstants.MAX_PHONE_COUNT_DUAL_SIM;
-import static com.android.systemui.Dependency.BG_LOOPER_NAME;
import android.content.BroadcastReceiver;
import android.content.Context;
@@ -65,6 +64,7 @@ import com.android.systemui.ConfigurationChangedReceiver;
import com.android.systemui.DemoMode;
import com.android.systemui.Dumpable;
import com.android.systemui.R;
+import com.android.systemui.dagger.qualifiers.BgLooper;
import com.android.systemui.settings.CurrentUserTracker;
import com.android.systemui.statusbar.policy.DeviceProvisionedController.DeviceProvisionedListener;
import com.android.systemui.statusbar.policy.MobileSignalController.MobileIconGroup;
@@ -81,7 +81,6 @@ import java.util.Locale;
import java.util.Map;
import javax.inject.Inject;
-import javax.inject.Named;
import javax.inject.Singleton;
/** Platform implementation of the network controller. **/
@@ -172,7 +171,7 @@ public class NetworkControllerImpl extends BroadcastReceiver
* Construct this controller object and register for updates.
*/
@Inject
- public NetworkControllerImpl(Context context, @Named(BG_LOOPER_NAME) Looper bgLooper,
+ public NetworkControllerImpl(Context context, @BgLooper Looper bgLooper,
DeviceProvisionedController deviceProvisionedController) {
this(context, (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE),
(TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE),
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java
index 43795dc08c91..502a9bd34b12 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java
@@ -23,12 +23,16 @@ import android.app.ActivityManager;
import android.app.Notification;
import android.app.PendingIntent;
import android.app.RemoteInput;
+import android.content.ClipDescription;
import android.content.Context;
import android.content.Intent;
+import android.content.pm.PackageManager;
import android.content.pm.ShortcutManager;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
+import android.net.Uri;
import android.os.Bundle;
+import android.os.ServiceManager;
import android.os.SystemClock;
import android.os.UserHandle;
import android.text.Editable;
@@ -53,8 +57,13 @@ import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.TextView;
+import androidx.core.view.inputmethod.EditorInfoCompat;
+import androidx.core.view.inputmethod.InputConnectionCompat;
+import androidx.core.view.inputmethod.InputContentInfoCompat;
+
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto;
+import com.android.internal.statusbar.IStatusBarService;
import com.android.systemui.Dependency;
import com.android.systemui.Interpolators;
import com.android.systemui.R;
@@ -65,6 +74,7 @@ import com.android.systemui.statusbar.notification.row.wrapper.NotificationViewW
import com.android.systemui.statusbar.notification.stack.StackStateAnimator;
import com.android.systemui.statusbar.phone.LightBarController;
+import java.util.HashMap;
import java.util.function.Consumer;
/**
@@ -88,6 +98,8 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene
private RemoteInputController mController;
private RemoteInputQuickSettingsDisabler mRemoteInputQuickSettingsDisabler;
+ private IStatusBarService mStatusBarManagerService;
+
private NotificationEntry mEntry;
private boolean mRemoved;
@@ -103,6 +115,8 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene
public RemoteInputView(Context context, AttributeSet attrs) {
super(context, attrs);
mRemoteInputQuickSettingsDisabler = Dependency.get(RemoteInputQuickSettingsDisabler.class);
+ mStatusBarManagerService = IStatusBarService.Stub.asInterface(
+ ServiceManager.getService(Context.STATUS_BAR_SERVICE));
}
@Override
@@ -128,7 +142,7 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene
if (isSoftImeEvent || isKeyboardEnterKey) {
if (mEditText.length() > 0) {
- sendRemoteInput();
+ sendRemoteInput(prepareRemoteInputFromText());
}
// Consume action to prevent IME from closing.
return true;
@@ -141,7 +155,7 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene
mEditText.mRemoteInputView = this;
}
- private void sendRemoteInput() {
+ protected Intent prepareRemoteInputFromText() {
Bundle results = new Bundle();
results.putString(mRemoteInput.getResultKey(), mEditText.getText().toString());
Intent fillInIntent = new Intent().addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
@@ -153,12 +167,31 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene
RemoteInput.setResultsSource(fillInIntent, RemoteInput.SOURCE_CHOICE);
}
+ return fillInIntent;
+ }
+
+ protected Intent prepareRemoteInputFromData(String contentType, Uri data) {
+ HashMap<String, Uri> results = new HashMap<>();
+ results.put(contentType, data);
+ try {
+ mStatusBarManagerService.grantInlineReplyUriPermission(
+ mEntry.getSbn().getKey(), data);
+ } catch (Exception e) {
+ Log.e(TAG, "Failed to grant URI permissions:" + e.getMessage(), e);
+ }
+ Intent fillInIntent = new Intent().addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
+ RemoteInput.addDataResultToIntent(mRemoteInput, fillInIntent, results);
+
+ return fillInIntent;
+ }
+
+ private void sendRemoteInput(Intent intent) {
mEditText.setEnabled(false);
mSendButton.setVisibility(INVISIBLE);
mProgressBar.setVisibility(VISIBLE);
mEntry.remoteInputText = mEditText.getText();
mEntry.lastRemoteInputSent = SystemClock.elapsedRealtime();
- mController.addSpinning(mEntry.key, mToken);
+ mController.addSpinning(mEntry.getKey(), mToken);
mController.removeRemoteInput(mEntry, mToken);
mEditText.mShowImeOnInputConnection = false;
mController.remoteInputSent(mEntry);
@@ -170,17 +203,17 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene
// but that's an edge case, and also because we can't always know which package will receive
// an intent, so we just reset for the publisher.
getContext().getSystemService(ShortcutManager.class).onApplicationActive(
- mEntry.notification.getPackageName(),
- mEntry.notification.getUser().getIdentifier());
+ mEntry.getSbn().getPackageName(),
+ mEntry.getSbn().getUser().getIdentifier());
MetricsLogger.action(mContext, MetricsProto.MetricsEvent.ACTION_REMOTE_INPUT_SEND,
- mEntry.notification.getPackageName());
+ mEntry.getSbn().getPackageName());
try {
- mPendingIntent.send(mContext, 0, fillInIntent);
+ mPendingIntent.send(mContext, 0, intent);
} catch (PendingIntent.CanceledException e) {
Log.i(TAG, "Unable to send remote input result", e);
MetricsLogger.action(mContext, MetricsProto.MetricsEvent.ACTION_REMOTE_INPUT_FAIL,
- mEntry.notification.getPackageName());
+ mEntry.getSbn().getPackageName());
}
}
@@ -195,7 +228,9 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene
LayoutInflater.from(context).inflate(R.layout.remote_input, root, false);
v.mController = controller;
v.mEntry = entry;
- v.mEditText.setTextOperationUser(computeTextOperationUser(entry.notification.getUser()));
+ UserHandle user = computeTextOperationUser(entry.getSbn().getUser());
+ v.mEditText.mUser = user;
+ v.mEditText.setTextOperationUser(user);
v.setTag(VIEW_TAG);
return v;
@@ -204,7 +239,7 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene
@Override
public void onClick(View v) {
if (v == mSendButton) {
- sendRemoteInput();
+ sendRemoteInput(prepareRemoteInputFromText());
}
}
@@ -249,7 +284,7 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene
mRemoteInputQuickSettingsDisabler.setRemoteInputActive(false);
MetricsLogger.action(mContext, MetricsProto.MetricsEvent.ACTION_REMOTE_INPUT_CLOSE,
- mEntry.notification.getPackageName());
+ mEntry.getSbn().getPackageName());
}
@Override
@@ -269,7 +304,7 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene
return;
}
mController.removeRemoteInput(mEntry, mToken);
- mController.removeSpinning(mEntry.key, mToken);
+ mController.removeSpinning(mEntry.getKey(), mToken);
}
public void setPendingIntent(PendingIntent pendingIntent) {
@@ -314,7 +349,7 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene
public void focus() {
MetricsLogger.action(mContext, MetricsProto.MetricsEvent.ACTION_REMOTE_INPUT_OPEN,
- mEntry.notification.getPackageName());
+ mEntry.getSbn().getPackageName());
setVisibility(VISIBLE);
if (mWrapper != null) {
@@ -353,7 +388,7 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene
mEditText.setEnabled(true);
mSendButton.setVisibility(VISIBLE);
mProgressBar.setVisibility(INVISIBLE);
- mController.removeSpinning(mEntry.key, mToken);
+ mController.removeSpinning(mEntry.getKey(), mToken);
updateSendButton();
onDefocus(false /* animate */);
@@ -505,7 +540,7 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene
}
public boolean isSending() {
- return getVisibility() == VISIBLE && mController.isSpinning(mEntry.key, mToken);
+ return getVisibility() == VISIBLE && mController.isSpinning(mEntry.getKey(), mToken);
}
/**
@@ -518,6 +553,7 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene
private RemoteInputView mRemoteInputView;
boolean mShowImeOnInputConnection;
private LightBarController mLightBarController;
+ UserHandle mUser;
public RemoteEditText(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -617,11 +653,47 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene
@Override
public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
+ String[] allowedDataTypes = mRemoteInputView.mRemoteInput.getAllowedDataTypes()
+ .toArray(new String[0]);
+ EditorInfoCompat.setContentMimeTypes(outAttrs, allowedDataTypes);
final InputConnection inputConnection = super.onCreateInputConnection(outAttrs);
- if (mShowImeOnInputConnection && inputConnection != null) {
+ final InputConnectionCompat.OnCommitContentListener callback =
+ new InputConnectionCompat.OnCommitContentListener() {
+ @Override
+ public boolean onCommitContent(
+ InputContentInfoCompat inputContentInfoCompat, int i,
+ Bundle bundle) {
+ Uri contentUri = inputContentInfoCompat.getContentUri();
+ ClipDescription description = inputContentInfoCompat.getDescription();
+ String mimeType = null;
+ if (description != null && description.getMimeTypeCount() > 0) {
+ mimeType = description.getMimeType(0);
+ }
+ if (mimeType != null) {
+ Intent dataIntent = mRemoteInputView.prepareRemoteInputFromData(
+ mimeType, contentUri);
+ mRemoteInputView.sendRemoteInput(dataIntent);
+ }
+ return true;
+ }
+ };
+
+ InputConnection ic = inputConnection == null ? null :
+ InputConnectionCompat.createWrapper(inputConnection, outAttrs, callback);
+
+ Context userContext = null;
+ try {
+ userContext = mContext.createPackageContextAsUser(
+ mContext.getPackageName(), 0, mUser);
+ } catch (PackageManager.NameNotFoundException e) {
+ Log.e(TAG, "Unable to create user context:" + e.getMessage(), e);
+ }
+
+ if (mShowImeOnInputConnection && ic != null) {
+ Context targetContext = userContext != null ? userContext : getContext();
final InputMethodManager imm =
- getContext().getSystemService(InputMethodManager.class);
+ targetContext.getSystemService(InputMethodManager.class);
if (imm != null) {
// onCreateInputConnection is called by InputMethodManager in the middle of
// setting up the connection to the IME; wait with requesting the IME until that
@@ -636,7 +708,7 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene
}
}
- return inputConnection;
+ return ic;
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java
index d88ae78c5afb..6edd75b20fed 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java
@@ -15,8 +15,6 @@
*/
package com.android.systemui.statusbar.policy;
-import static com.android.systemui.Dependency.BG_HANDLER_NAME;
-
import android.app.ActivityManager;
import android.app.admin.DevicePolicyManager;
import android.content.BroadcastReceiver;
@@ -50,6 +48,7 @@ import com.android.internal.annotations.GuardedBy;
import com.android.internal.net.LegacyVpnInfo;
import com.android.internal.net.VpnConfig;
import com.android.systemui.R;
+import com.android.systemui.dagger.qualifiers.BgHandler;
import com.android.systemui.settings.CurrentUserTracker;
import java.io.FileDescriptor;
@@ -57,7 +56,6 @@ import java.io.PrintWriter;
import java.util.ArrayList;
import javax.inject.Inject;
-import javax.inject.Named;
import javax.inject.Singleton;
/**
@@ -102,7 +100,7 @@ public class SecurityControllerImpl extends CurrentUserTracker implements Securi
/**
*/
@Inject
- public SecurityControllerImpl(Context context, @Named(BG_HANDLER_NAME) Handler bgHandler) {
+ public SecurityControllerImpl(Context context, @BgHandler Handler bgHandler) {
this(context, bgHandler, null);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyConstants.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyConstants.java
index 655c29cbf687..347d3009c3ec 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyConstants.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyConstants.java
@@ -16,8 +16,6 @@
package com.android.systemui.statusbar.policy;
-import static com.android.systemui.Dependency.MAIN_HANDLER_NAME;
-
import android.app.RemoteInput;
import android.content.Context;
import android.content.res.Resources;
@@ -30,9 +28,9 @@ import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
import com.android.systemui.R;
+import com.android.systemui.dagger.qualifiers.MainHandler;
import javax.inject.Inject;
-import javax.inject.Named;
import javax.inject.Singleton;
@Singleton
@@ -67,7 +65,7 @@ public final class SmartReplyConstants {
private final KeyValueListParser mParser = new KeyValueListParser(',');
@Inject
- public SmartReplyConstants(@Named(MAIN_HANDLER_NAME) Handler handler, Context context) {
+ public SmartReplyConstants(@MainHandler Handler handler, Context context) {
mHandler = handler;
mContext = context;
final Resources resources = mContext.getResources();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java
index b5f660a84043..65bb28ffbe39 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java
@@ -350,7 +350,7 @@ public class SmartReplyView extends ViewGroup {
() -> {
smartReplyController.smartActionClicked(
entry, actionIndex, action, smartActions.fromAssistant);
- headsUpManager.removeNotification(entry.key, true);
+ headsUpManager.removeNotification(entry.getKey(), true);
}, entry.getRow());
if (useDelayedOnClickListener) {
onClickListener = new DelayedOnClickListener(onClickListener,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
index 4fa4b6c456e2..f2d2faed6a42 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
@@ -18,7 +18,6 @@ package com.android.systemui.statusbar.policy;
import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
import static com.android.systemui.DejankUtils.whitelistIpcs;
-import static com.android.systemui.Dependency.MAIN_HANDLER_NAME;
import android.app.ActivityManager;
import android.app.Dialog;
@@ -58,11 +57,11 @@ import com.android.systemui.Prefs;
import com.android.systemui.Prefs.Key;
import com.android.systemui.R;
import com.android.systemui.SystemUISecondaryUserService;
+import com.android.systemui.dagger.qualifiers.MainHandler;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.qs.DetailAdapter;
import com.android.systemui.qs.tiles.UserDetailView;
import com.android.systemui.statusbar.phone.SystemUIDialog;
-import com.android.systemui.statusbar.phone.UnlockMethodCache;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -71,7 +70,6 @@ import java.util.ArrayList;
import java.util.List;
import javax.inject.Inject;
-import javax.inject.Named;
import javax.inject.Singleton;
/**
@@ -93,7 +91,7 @@ public class UserSwitcherController implements Dumpable {
private final ArrayList<WeakReference<BaseUserAdapter>> mAdapters = new ArrayList<>();
private final GuestResumeSessionReceiver mGuestResumeSessionReceiver
= new GuestResumeSessionReceiver();
- private final KeyguardMonitor mKeyguardMonitor;
+ private final KeyguardStateController mKeyguardStateController;
protected final Handler mHandler;
private final ActivityStarter mActivityStarter;
@@ -110,13 +108,13 @@ public class UserSwitcherController implements Dumpable {
private SparseBooleanArray mForcePictureLoadForUserId = new SparseBooleanArray(2);
@Inject
- public UserSwitcherController(Context context, KeyguardMonitor keyguardMonitor,
- @Named(MAIN_HANDLER_NAME) Handler handler, ActivityStarter activityStarter) {
+ public UserSwitcherController(Context context, KeyguardStateController keyguardStateController,
+ @MainHandler Handler handler, ActivityStarter activityStarter) {
mContext = context;
if (!UserManager.isGuestUserEphemeral()) {
mGuestResumeSessionReceiver.register(context);
}
- mKeyguardMonitor = keyguardMonitor;
+ mKeyguardStateController = keyguardStateController;
mHandler = handler;
mActivityStarter = activityStarter;
mUserManager = UserManager.get(context);
@@ -149,7 +147,7 @@ public class UserSwitcherController implements Dumpable {
// Fetch initial values.
mSettingsObserver.onChange(false);
- keyguardMonitor.addCallback(mCallback);
+ keyguardStateController.addCallback(mCallback);
listenForCallState();
refreshUsers(UserHandle.USER_NULL);
@@ -315,7 +313,6 @@ public class UserSwitcherController implements Dumpable {
// adb shell settings put system enable_fullscreen_user_switcher 1 # Turn it on.
// Restart SystemUI or adb reboot.
final int DEFAULT = -1;
- // TODO(b/140061064)
final int overrideUseFullscreenUserSwitcher =
whitelistIpcs(() -> Settings.System.getInt(mContext.getContentResolver(),
"enable_fullscreen_user_switcher", DEFAULT));
@@ -597,20 +594,18 @@ public class UserSwitcherController implements Dumpable {
public static abstract class BaseUserAdapter extends BaseAdapter {
final UserSwitcherController mController;
- private final KeyguardMonitor mKeyguardMonitor;
- private final UnlockMethodCache mUnlockMethodCache;
+ private final KeyguardStateController mKeyguardStateController;
protected BaseUserAdapter(UserSwitcherController controller) {
mController = controller;
- mKeyguardMonitor = controller.mKeyguardMonitor;
- mUnlockMethodCache = UnlockMethodCache.getInstance(controller.mContext);
+ mKeyguardStateController = controller.mKeyguardStateController;
controller.addAdapter(new WeakReference<>(this));
}
public int getUserCount() {
- boolean secureKeyguardShowing = mKeyguardMonitor.isShowing()
- && mKeyguardMonitor.isSecure()
- && !mUnlockMethodCache.canSkipBouncer();
+ boolean secureKeyguardShowing = mKeyguardStateController.isShowing()
+ && mKeyguardStateController.isMethodSecure()
+ && !mKeyguardStateController.canDismissLockScreen();
if (!secureKeyguardShowing) {
return mController.getUsers().size();
}
@@ -630,9 +625,9 @@ public class UserSwitcherController implements Dumpable {
@Override
public int getCount() {
- boolean secureKeyguardShowing = mKeyguardMonitor.isShowing()
- && mKeyguardMonitor.isSecure()
- && !mUnlockMethodCache.canSkipBouncer();
+ boolean secureKeyguardShowing = mKeyguardStateController.isShowing()
+ && mKeyguardStateController.isMethodSecure()
+ && !mKeyguardStateController.canDismissLockScreen();
if (!secureKeyguardShowing) {
return mController.getUsers().size();
}
@@ -819,19 +814,21 @@ public class UserSwitcherController implements Dumpable {
}
};
- private final KeyguardMonitor.Callback mCallback = new KeyguardMonitor.Callback() {
- @Override
- public void onKeyguardShowingChanged() {
+ private final KeyguardStateController.Callback mCallback =
+ new KeyguardStateController.Callback() {
+ @Override
+ public void onKeyguardShowingChanged() {
- // When Keyguard is going away, we don't need to update our items immediately which
- // helps making the transition faster.
- if (!mKeyguardMonitor.isShowing()) {
- mHandler.post(UserSwitcherController.this::notifyAdapters);
- } else {
- notifyAdapters();
- }
- }
- };
+ // When Keyguard is going away, we don't need to update our items immediately
+ // which
+ // helps making the transition faster.
+ if (!mKeyguardStateController.isShowing()) {
+ mHandler.post(UserSwitcherController.this::notifyAdapters);
+ } else {
+ notifyAdapters();
+ }
+ }
+ };
private final class ExitGuestDialog extends SystemUIDialog implements
DialogInterface.OnClickListener {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java
index 29c42d24b3b4..1c7a1951b27d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java
@@ -16,8 +16,6 @@
package com.android.systemui.statusbar.policy;
-import static com.android.systemui.Dependency.MAIN_HANDLER_NAME;
-
import android.app.ActivityManager;
import android.app.AlarmManager;
import android.app.NotificationManager;
@@ -41,6 +39,7 @@ import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
import com.android.systemui.Dumpable;
+import com.android.systemui.dagger.qualifiers.MainHandler;
import com.android.systemui.qs.GlobalSetting;
import com.android.systemui.settings.CurrentUserTracker;
import com.android.systemui.util.Utils;
@@ -51,7 +50,6 @@ import java.util.ArrayList;
import java.util.Objects;
import javax.inject.Inject;
-import javax.inject.Named;
import javax.inject.Singleton;
/** Platform implementation of the zen mode controller. **/
@@ -79,7 +77,7 @@ public class ZenModeControllerImpl extends CurrentUserTracker
private NotificationManager.Policy mConsolidatedNotificationPolicy;
@Inject
- public ZenModeControllerImpl(Context context, @Named(MAIN_HANDLER_NAME) Handler handler) {
+ public ZenModeControllerImpl(Context context, @MainHandler Handler handler) {
super(context);
mContext = context;
mModeSetting = new GlobalSetting(mContext, handler, Global.ZEN_MODE) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tv/AudioRecordingDisclosureBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/tv/AudioRecordingDisclosureBar.java
new file mode 100644
index 000000000000..d6d0a3603c25
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tv/AudioRecordingDisclosureBar.java
@@ -0,0 +1,203 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.tv;
+
+import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
+import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
+
+import android.app.AppOpsManager;
+import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.graphics.PixelFormat;
+import android.graphics.drawable.Drawable;
+import android.util.Log;
+import android.view.Gravity;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.ViewTreeObserver;
+import android.view.WindowManager;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import com.android.systemui.R;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+class AudioRecordingDisclosureBar {
+ private static final String TAG = "AudioRecordingDisclosureBar";
+ private static final boolean DEBUG = false;
+
+ private static final String LAYOUT_PARAMS_TITLE = "AudioRecordingDisclosureBar";
+ private static final int ANIM_DURATION_MS = 150;
+
+ private final Context mContext;
+ private final List<String> mAudioRecordingApps = new ArrayList<>();
+ private View mView;
+ private ViewGroup mAppsInfoContainer;
+
+ AudioRecordingDisclosureBar(Context context) {
+ mContext = context;
+ }
+
+ void start() {
+ // Inflate and add audio recording disclosure bar
+ createView();
+
+ // Register AppOpsManager callback
+ final AppOpsManager appOpsManager = (AppOpsManager) mContext.getSystemService(
+ Context.APP_OPS_SERVICE);
+ appOpsManager.startWatchingActive(
+ new String[]{AppOpsManager.OPSTR_RECORD_AUDIO}, mContext.getMainExecutor(),
+ new OnActiveRecordingListener());
+ }
+
+ private void createView() {
+ mView = View.inflate(mContext,
+ R.layout.tv_status_bar_audio_recording, null);
+ mAppsInfoContainer = mView.findViewById(R.id.container);
+
+ final WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams(
+ MATCH_PARENT,
+ WRAP_CONTENT,
+ WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY,
+ WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
+ PixelFormat.TRANSLUCENT);
+ layoutParams.gravity = Gravity.BOTTOM;
+ layoutParams.setTitle(LAYOUT_PARAMS_TITLE);
+ layoutParams.packageName = mContext.getPackageName();
+
+ final WindowManager windowManager = (WindowManager) mContext.getSystemService(
+ Context.WINDOW_SERVICE);
+ windowManager.addView(mView, layoutParams);
+
+ // Set invisible first util it gains its actual size and we are able to hide it by moving
+ // off the screen
+ mView.setVisibility(View.INVISIBLE);
+ mView.getViewTreeObserver().addOnGlobalLayoutListener(
+ new ViewTreeObserver.OnGlobalLayoutListener() {
+ @Override
+ public void onGlobalLayout() {
+ // Now that we get the height, we can move the bar off ("below") the screen
+ final int height = mView.getHeight();
+ mView.setTranslationY(height);
+ // ... and make it visible
+ mView.setVisibility(View.VISIBLE);
+ // Remove the observer
+ mView.getViewTreeObserver()
+ .removeOnGlobalLayoutListener(this);
+ }
+ });
+ }
+
+ private void showAudioRecordingDisclosureBar() {
+ mView.animate()
+ .translationY(0f)
+ .setDuration(ANIM_DURATION_MS)
+ .start();
+ }
+
+ private void addToAudioRecordingDisclosureBar(String packageName) {
+ final PackageManager pm = mContext.getPackageManager();
+ final ApplicationInfo appInfo;
+ try {
+ appInfo = pm.getApplicationInfo(packageName, 0);
+ } catch (PackageManager.NameNotFoundException e) {
+ return;
+ }
+ final CharSequence label = pm.getApplicationLabel(appInfo);
+ final Drawable icon = pm.getApplicationIcon(appInfo);
+
+ final View view = LayoutInflater.from(mContext).inflate(R.layout.tv_item_app_info,
+ mAppsInfoContainer, false);
+ ((TextView) view.findViewById(R.id.title)).setText(label);
+ ((ImageView) view.findViewById(R.id.icon)).setImageDrawable(icon);
+
+ mAppsInfoContainer.addView(view);
+ }
+
+ private void removeFromAudioRecordingDisclosureBar(int index) {
+ mAppsInfoContainer.removeViewAt(index);
+ }
+
+ private void hideAudioRecordingDisclosureBar() {
+ mView.animate()
+ .translationY(mView.getHeight())
+ .setDuration(ANIM_DURATION_MS)
+ .start();
+ }
+
+ private class OnActiveRecordingListener implements AppOpsManager.OnOpActiveChangedListener {
+ private final List<String> mExemptApps;
+
+ private OnActiveRecordingListener() {
+ mExemptApps = Arrays.asList(mContext.getResources().getStringArray(
+ R.array.audio_recording_disclosure_exempt_apps));
+ }
+
+ @Override
+ public void onOpActiveChanged(String op, int uid, String packageName, boolean active) {
+ if (DEBUG) {
+ Log.d(TAG,
+ "OP_RECORD_AUDIO active change, active" + active + ", app=" + packageName);
+ }
+
+ if (mExemptApps.contains(packageName)) {
+ if (DEBUG) {
+ Log.d(TAG, "\t- exempt app");
+ }
+ return;
+ }
+
+ final boolean alreadyTracking = mAudioRecordingApps.contains(packageName);
+ if ((active && alreadyTracking) || (!active && !alreadyTracking)) {
+ if (DEBUG) {
+ Log.d(TAG, "\t- nothing changed");
+ }
+ return;
+ }
+
+ if (active) {
+ if (DEBUG) {
+ Log.d(TAG, "\t- new recording app");
+ }
+
+ if (mAudioRecordingApps.isEmpty()) {
+ showAudioRecordingDisclosureBar();
+ }
+
+ mAudioRecordingApps.add(packageName);
+ addToAudioRecordingDisclosureBar(packageName);
+ } else {
+ if (DEBUG) {
+ Log.d(TAG, "\t- not recording any more");
+ }
+
+ final int index = mAudioRecordingApps.indexOf(packageName);
+ removeFromAudioRecordingDisclosureBar(index);
+ mAudioRecordingApps.remove(index);
+
+ if (mAudioRecordingApps.isEmpty()) {
+ hideAudioRecordingDisclosureBar();
+ }
+ }
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tv/OWNERS b/packages/SystemUI/src/com/android/systemui/statusbar/tv/OWNERS
new file mode 100644
index 000000000000..a601e9b86ef4
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tv/OWNERS
@@ -0,0 +1,8 @@
+# Android TV Core Framework
+rgl@google.com
+valiiftime@google.com
+galinap@google.com
+patrikf@google.com
+robhor@google.com
+sergeynv@google.com
+
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
index 17d9cbe3af07..c2ed7df7cb2e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
@@ -23,28 +23,37 @@ import android.os.ServiceManager;
import com.android.internal.statusbar.IStatusBarService;
import com.android.systemui.SystemUI;
import com.android.systemui.statusbar.CommandQueue;
-import com.android.systemui.statusbar.CommandQueue.Callbacks;
+
/**
- * Status bar implementation for "large screen" products that mostly present no on-screen nav
+ * Status bar implementation for "large screen" products that mostly present no on-screen nav.
+ * Serves as a collection of UI components, rather than showing its own UI.
+ * The following is the list of elements that constitute the TV-specific status bar:
+ * <ul>
+ * <li> {@link AudioRecordingDisclosureBar} - shown whenever applications are conducting audio
+ * recording, discloses the responsible applications </li>
+ * </ul>
*/
+public class TvStatusBar extends SystemUI implements CommandQueue.Callbacks {
-public class TvStatusBar extends SystemUI implements Callbacks {
-
- private IStatusBarService mBarService;
+ public TvStatusBar(Context context) {
+ super(context);
+ }
@Override
public void start() {
putComponent(TvStatusBar.class, this);
- CommandQueue commandQueue = getComponent(CommandQueue.class);
- commandQueue.addCallback(this);
- mBarService = IStatusBarService.Stub.asInterface(
+
+ final IStatusBarService barService = IStatusBarService.Stub.asInterface(
ServiceManager.getService(Context.STATUS_BAR_SERVICE));
+ final CommandQueue commandQueue = getComponent(CommandQueue.class);
+ commandQueue.addCallback(this);
try {
- mBarService.registerStatusBar(commandQueue);
+ barService.registerStatusBar(commandQueue);
} catch (RemoteException ex) {
// If the system process isn't there we're doomed anyway.
}
- }
+ new AudioRecordingDisclosureBar(mContext).start();
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java b/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java
index 89aa7979e7d8..9a58a355c586 100644
--- a/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java
+++ b/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java
@@ -61,6 +61,10 @@ public class ThemeOverlayController extends SystemUI {
private ThemeOverlayManager mThemeManager;
private UserManager mUserManager;
+ public ThemeOverlayController(Context context) {
+ super(context);
+ }
+
@Override
public void start() {
if (DEBUG) Log.d(TAG, "Start");
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/TunerServiceImpl.java b/packages/SystemUI/src/com/android/systemui/tuner/TunerServiceImpl.java
index a55e2cf38e39..2d6027cb324d 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/TunerServiceImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/TunerServiceImpl.java
@@ -15,8 +15,6 @@
*/
package com.android.systemui.tuner;
-import static com.android.systemui.Dependency.MAIN_HANDLER_NAME;
-
import android.app.ActivityManager;
import android.content.ContentResolver;
import android.content.Context;
@@ -36,6 +34,7 @@ import android.util.ArraySet;
import com.android.internal.util.ArrayUtils;
import com.android.systemui.DejankUtils;
import com.android.systemui.DemoMode;
+import com.android.systemui.dagger.qualifiers.MainHandler;
import com.android.systemui.qs.QSTileHost;
import com.android.systemui.settings.CurrentUserTracker;
import com.android.systemui.statusbar.phone.StatusBarIconController;
@@ -46,7 +45,6 @@ import java.util.HashSet;
import java.util.Set;
import javax.inject.Inject;
-import javax.inject.Named;
import javax.inject.Singleton;
@@ -83,7 +81,7 @@ public class TunerServiceImpl extends TunerService {
/**
*/
@Inject
- public TunerServiceImpl(Context context, @Named(MAIN_HANDLER_NAME) Handler mainHandler,
+ public TunerServiceImpl(Context context, @MainHandler Handler mainHandler,
LeakDetector leakDetector) {
mContext = context;
mContentResolver = mContext.getContentResolver();
diff --git a/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java b/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java
index ff5bd03740bd..11885c55b51d 100644
--- a/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java
+++ b/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java
@@ -60,6 +60,10 @@ public class StorageNotification extends SystemUI {
private NotificationManager mNotificationManager;
private StorageManager mStorageManager;
+ public StorageNotification(Context context) {
+ super(context);
+ }
+
private static class MoveInfo {
public int moveId;
public Bundle extras;
diff --git a/packages/SystemUI/src/com/android/systemui/usb/UsbConfirmActivity.java b/packages/SystemUI/src/com/android/systemui/usb/UsbConfirmActivity.java
index 0a3e34ee951d..fd99ef389bec 100644
--- a/packages/SystemUI/src/com/android/systemui/usb/UsbConfirmActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/usb/UsbConfirmActivity.java
@@ -21,6 +21,7 @@ import android.content.ComponentName;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
+import android.content.PermissionChecker;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.hardware.usb.IUsbManager;
@@ -63,6 +64,7 @@ public class UsbConfirmActivity extends AlertActivity
mDevice = (UsbDevice) intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
mAccessory = (UsbAccessory)intent.getParcelableExtra(UsbManager.EXTRA_ACCESSORY);
mResolveInfo = (ResolveInfo) intent.getParcelableExtra("rinfo");
+ String packageName = intent.getStringExtra(UsbManager.EXTRA_PACKAGE);
PackageManager packageManager = getPackageManager();
String appName = mResolveInfo.loadLabel(packageManager).toString();
@@ -74,8 +76,20 @@ public class UsbConfirmActivity extends AlertActivity
mAccessory.getDescription());
mDisconnectedReceiver = new UsbDisconnectedReceiver(this, mAccessory);
} else {
- ap.mMessage = getString(R.string.usb_device_confirm_prompt, appName,
- mDevice.getProductName());
+ int uid = intent.getIntExtra(Intent.EXTRA_UID, -1);
+ boolean hasRecordPermission =
+ PermissionChecker.checkPermissionForPreflight(
+ this, android.Manifest.permission.RECORD_AUDIO, -1, uid,
+ packageName)
+ == android.content.pm.PackageManager.PERMISSION_GRANTED;
+ boolean isAudioCaptureDevice = mDevice.getHasAudioCapture();
+ boolean useRecordWarning = isAudioCaptureDevice && !hasRecordPermission;
+
+ int strID = useRecordWarning
+ ? R.string.usb_device_confirm_prompt_warn
+ : R.string.usb_device_confirm_prompt;
+
+ ap.mMessage = getString(strID, appName, mDevice.getProductName());
mDisconnectedReceiver = new UsbDisconnectedReceiver(this, mDevice);
}
ap.mPositiveButtonText = getString(android.R.string.ok);
diff --git a/packages/SystemUI/src/com/android/systemui/usb/UsbPermissionActivity.java b/packages/SystemUI/src/com/android/systemui/usb/UsbPermissionActivity.java
index a46f018af816..47b56e097ec9 100644
--- a/packages/SystemUI/src/com/android/systemui/usb/UsbPermissionActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/usb/UsbPermissionActivity.java
@@ -21,6 +21,7 @@ import android.app.PendingIntent;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
+import android.content.PermissionChecker;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.hardware.usb.IUsbManager;
@@ -84,14 +85,27 @@ public class UsbPermissionActivity extends AlertActivity
final AlertController.AlertParams ap = mAlertParams;
ap.mTitle = appName;
if (mDevice == null) {
+ // Accessory Case
+
ap.mMessage = getString(R.string.usb_accessory_permission_prompt, appName,
mAccessory.getDescription());
mDisconnectedReceiver = new UsbDisconnectedReceiver(this, mAccessory);
} else {
- ap.mMessage = getString(R.string.usb_device_permission_prompt, appName,
- mDevice.getProductName());
+ boolean hasRecordPermission =
+ PermissionChecker.checkPermissionForPreflight(
+ this, android.Manifest.permission.RECORD_AUDIO, -1, aInfo.uid,
+ mPackageName)
+ == android.content.pm.PackageManager.PERMISSION_GRANTED;
+ boolean isAudioCaptureDevice = mDevice.getHasAudioCapture();
+ boolean useRecordWarning = isAudioCaptureDevice && !hasRecordPermission;
+
+ int strID = useRecordWarning
+ ? R.string.usb_device_permission_prompt_warn
+ : R.string.usb_device_permission_prompt;
+ ap.mMessage = getString(strID, appName, mDevice.getProductName());
mDisconnectedReceiver = new UsbDisconnectedReceiver(this, mDevice);
}
+
ap.mPositiveButtonText = getString(android.R.string.ok);
ap.mNegativeButtonText = getString(android.R.string.cancel);
ap.mPositiveButtonListener = this;
diff --git a/packages/SystemUI/src/com/android/systemui/util/InjectionInflationController.java b/packages/SystemUI/src/com/android/systemui/util/InjectionInflationController.java
index e44e58a84dc8..5ed027d37def 100644
--- a/packages/SystemUI/src/com/android/systemui/util/InjectionInflationController.java
+++ b/packages/SystemUI/src/com/android/systemui/util/InjectionInflationController.java
@@ -26,7 +26,7 @@ import android.view.View;
import com.android.keyguard.KeyguardClockSwitch;
import com.android.keyguard.KeyguardMessageArea;
import com.android.keyguard.KeyguardSliceView;
-import com.android.systemui.SystemUIRootComponent;
+import com.android.systemui.dagger.SystemUIRootComponent;
import com.android.systemui.qs.QSCarrierGroup;
import com.android.systemui.qs.QSFooterImpl;
import com.android.systemui.qs.QSPanel;
@@ -37,6 +37,7 @@ import com.android.systemui.statusbar.NotificationShelf;
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
import com.android.systemui.statusbar.phone.LockIcon;
import com.android.systemui.statusbar.phone.NotificationPanelView;
+import com.android.systemui.statusbar.policy.Clock;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
@@ -178,6 +179,11 @@ public class InjectionInflationController {
* Creates the QSCustomizer.
*/
QSCustomizer createQSCustomizer();
+
+ /**
+ * Creates a Clock.
+ */
+ Clock createClock();
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/util/NotificationChannels.java b/packages/SystemUI/src/com/android/systemui/util/NotificationChannels.java
index f35af90edc3c..8c60747dffc7 100644
--- a/packages/SystemUI/src/com/android/systemui/util/NotificationChannels.java
+++ b/packages/SystemUI/src/com/android/systemui/util/NotificationChannels.java
@@ -38,6 +38,10 @@ public class NotificationChannels extends SystemUI {
public static String BATTERY = "BAT";
public static String HINTS = "HNT";
+ public NotificationChannels(Context context) {
+ super(context);
+ }
+
public static void createAll(Context context) {
final NotificationManager nm = context.getSystemService(NotificationManager.class);
final NotificationChannel batteryChannel = new NotificationChannel(BATTERY,
diff --git a/packages/SystemUI/src/com/android/systemui/util/leak/DumpTruck.java b/packages/SystemUI/src/com/android/systemui/util/leak/DumpTruck.java
index fa7af0be77f1..be5e0a0b12c5 100644
--- a/packages/SystemUI/src/com/android/systemui/util/leak/DumpTruck.java
+++ b/packages/SystemUI/src/com/android/systemui/util/leak/DumpTruck.java
@@ -36,6 +36,7 @@ import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
@@ -53,7 +54,7 @@ public class DumpTruck {
private final Context context;
private Uri hprofUri;
- private long pss;
+ private long rss;
final StringBuilder body = new StringBuilder();
public DumpTruck(Context context) {
@@ -66,7 +67,7 @@ public class DumpTruck {
* @param pids
* @return this, for chaining
*/
- public DumpTruck captureHeaps(int[] pids) {
+ public DumpTruck captureHeaps(List<Long> pids) {
final GarbageMonitor gm = Dependency.get(GarbageMonitor.class);
final File dumpDir = new File(context.getCacheDir(), FILEPROVIDER_PATH);
@@ -79,8 +80,8 @@ public class DumpTruck {
final ArrayList<String> paths = new ArrayList<String>();
final int myPid = android.os.Process.myPid();
- final int[] pids_copy = Arrays.copyOf(pids, pids.length);
- for (int pid : pids_copy) {
+ for (Long pidL : pids) {
+ final int pid = pidL.intValue();
body.append(" pid ").append(pid);
if (gm != null) {
GarbageMonitor.ProcessMemInfo info = gm.getMemInfo(pid);
@@ -88,11 +89,9 @@ public class DumpTruck {
body.append(":")
.append(" up=")
.append(info.getUptime())
- .append(" pss=")
- .append(info.currentPss)
- .append(" uss=")
- .append(info.currentUss);
- pss = info.currentPss;
+ .append(" rss=")
+ .append(info.currentRss);
+ rss = info.currentRss;
}
}
if (pid == myPid) {
@@ -147,7 +146,7 @@ public class DumpTruck {
shareIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
shareIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
shareIntent.putExtra(Intent.EXTRA_SUBJECT,
- String.format("SystemUI memory dump (pss=%dM)", pss / 1024));
+ String.format("SystemUI memory dump (rss=%dM)", rss / 1024));
shareIntent.putExtra(Intent.EXTRA_TEXT, body.toString());
diff --git a/packages/SystemUI/src/com/android/systemui/util/leak/GarbageMonitor.java b/packages/SystemUI/src/com/android/systemui/util/leak/GarbageMonitor.java
index 583f6b340d47..bff405c0bee6 100644
--- a/packages/SystemUI/src/com/android/systemui/util/leak/GarbageMonitor.java
+++ b/packages/SystemUI/src/com/android/systemui/util/leak/GarbageMonitor.java
@@ -20,7 +20,6 @@ import static android.service.quicksettings.Tile.STATE_ACTIVE;
import static android.telephony.ims.feature.ImsFeature.STATE_UNAVAILABLE;
import static com.android.internal.logging.MetricsLogger.VIEW_UNKNOWN;
-import static com.android.systemui.Dependency.BG_LOOPER_NAME;
import android.annotation.Nullable;
import android.app.ActivityManager;
@@ -35,7 +34,6 @@ import android.graphics.PorterDuff;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.os.Build;
-import android.os.Debug;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
@@ -49,7 +47,8 @@ import android.util.LongSparseArray;
import com.android.systemui.Dumpable;
import com.android.systemui.R;
import com.android.systemui.SystemUI;
-import com.android.systemui.SystemUIFactory;
+import com.android.systemui.dagger.qualifiers.BgLooper;
+import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.qs.QSTile;
import com.android.systemui.qs.QSHost;
import com.android.systemui.qs.tileimpl.QSTileImpl;
@@ -57,9 +56,9 @@ import com.android.systemui.qs.tileimpl.QSTileImpl;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
+import java.util.List;
import javax.inject.Inject;
-import javax.inject.Named;
import javax.inject.Singleton;
/**
@@ -102,7 +101,6 @@ public class GarbageMonitor implements Dumpable {
private final LongSparseArray<ProcessMemInfo> mData = new LongSparseArray<>();
private final ArrayList<Long> mPids = new ArrayList<>();
- private int[] mPidsArray = new int[1];
private long mHeapLimit;
@@ -111,7 +109,7 @@ public class GarbageMonitor implements Dumpable {
@Inject
public GarbageMonitor(
Context context,
- @Named(BG_LOOPER_NAME) Looper bgLooper,
+ @BgLooper Looper bgLooper,
LeakDetector leakDetector,
LeakReporter leakReporter) {
mContext = context.getApplicationContext();
@@ -164,8 +162,8 @@ public class GarbageMonitor implements Dumpable {
return mData.get(pid);
}
- public int[] getTrackedProcesses() {
- return mPidsArray;
+ public List<Long> getTrackedProcesses() {
+ return mPids;
}
public void startTrackingProcess(long pid, String name, long start) {
@@ -173,43 +171,40 @@ public class GarbageMonitor implements Dumpable {
if (mPids.contains(pid)) return;
mPids.add(pid);
- updatePidsArrayL();
+ logPids();
mData.put(pid, new ProcessMemInfo(pid, name, start));
}
}
- private void updatePidsArrayL() {
- final int N = mPids.size();
- mPidsArray = new int[N];
- StringBuffer sb = new StringBuffer("Now tracking processes: ");
- for (int i = 0; i < N; i++) {
- final int p = mPids.get(i).intValue();
- mPidsArray[i] = p;
- sb.append(p);
- sb.append(" ");
- }
- if (DEBUG) Log.v(TAG, sb.toString());
+ private void logPids() {
+ if (DEBUG) {
+ StringBuffer sb = new StringBuffer("Now tracking processes: ");
+ for (int i = 0; i < mPids.size(); i++) {
+ final int p = mPids.get(i).intValue();
+ sb.append(" ");
+ }
+ Log.v(TAG, sb.toString());
+ }
}
private void update() {
synchronized (mPids) {
- Debug.MemoryInfo[] dinfos = mAm.getProcessMemoryInfo(mPidsArray);
- for (int i = 0; i < dinfos.length; i++) {
- Debug.MemoryInfo dinfo = dinfos[i];
- if (i > mPids.size()) {
- if (DEBUG) Log.e(TAG, "update: unknown process info received: " + dinfo);
+ for (int i = 0; i < mPids.size(); i++) {
+ final int pid = mPids.get(i).intValue();
+ // rssValues contains [VmRSS, RssFile, RssAnon, VmSwap].
+ long[] rssValues = Process.getRss(pid);
+ if (rssValues == null && rssValues.length == 0) {
+ if (DEBUG) Log.e(TAG, "update: Process.getRss() didn't provide any values.");
break;
}
- final long pid = mPids.get(i).intValue();
+ long rss = rssValues[0];
final ProcessMemInfo info = mData.get(pid);
- info.pss[info.head] = info.currentPss = dinfo.getTotalPss();
- info.uss[info.head] = info.currentUss = dinfo.getTotalPrivateDirty();
- info.head = (info.head + 1) % info.pss.length;
- if (info.currentPss > info.max) info.max = info.currentPss;
- if (info.currentUss > info.max) info.max = info.currentUss;
- if (info.currentPss == 0) {
- if (DEBUG) Log.v(TAG, "update: pid " + pid + " has pss=0, it probably died");
+ info.rss[info.head] = info.currentRss = rss;
+ info.head = (info.head + 1) % info.rss.length;
+ if (info.currentRss > info.max) info.max = info.currentRss;
+ if (info.currentRss == 0) {
+ if (DEBUG) Log.v(TAG, "update: pid " + pid + " has rss=0, it probably died");
mData.remove(pid);
}
}
@@ -217,7 +212,7 @@ public class GarbageMonitor implements Dumpable {
final long pid = mPids.get(i).intValue();
if (mData.get(pid) == null) {
mPids.remove(i);
- updatePidsArrayL();
+ logPids();
}
}
}
@@ -270,7 +265,7 @@ public class GarbageMonitor implements Dumpable {
private static class MemoryIconDrawable extends Drawable {
- long pss, limit;
+ long rss, limit;
final Drawable baseIcon;
final Paint paint = new Paint();
final float dp;
@@ -281,9 +276,9 @@ public class GarbageMonitor implements Dumpable {
paint.setColor(QSTileImpl.getColorForState(context, STATE_ACTIVE));
}
- public void setPss(long pss) {
- if (pss != this.pss) {
- this.pss = pss;
+ public void setRss(long rss) {
+ if (rss != this.rss) {
+ this.rss = rss;
invalidateSelf();
}
}
@@ -299,8 +294,8 @@ public class GarbageMonitor implements Dumpable {
public void draw(Canvas canvas) {
baseIcon.draw(canvas);
- if (limit > 0 && pss > 0) {
- float frac = Math.min(1f, (float) pss / limit);
+ if (limit > 0 && rss > 0) {
+ float frac = Math.min(1f, (float) rss / limit);
final Rect bounds = getBounds();
canvas.translate(bounds.left + 8 * dp, bounds.top + 5 * dp);
@@ -361,10 +356,10 @@ public class GarbageMonitor implements Dumpable {
}
private static class MemoryGraphIcon extends QSTile.Icon {
- long pss, limit;
+ long rss, limit;
- public void setPss(long pss) {
- this.pss = pss;
+ public void setRss(long rss) {
+ this.rss = rss;
}
public void setHeapLimit(long limit) {
@@ -374,7 +369,7 @@ public class GarbageMonitor implements Dumpable {
@Override
public Drawable getDrawable(Context context) {
final MemoryIconDrawable drawable = new MemoryIconDrawable(context);
- drawable.setPss(pss);
+ drawable.setRss(rss);
drawable.setLimit(limit);
return drawable;
}
@@ -387,13 +382,15 @@ public class GarbageMonitor implements Dumpable {
public static final boolean ADD_TO_DEFAULT_ON_DEBUGGABLE_BUILDS = true;
private final GarbageMonitor gm;
+ private final ActivityStarter mActivityStarter;
private ProcessMemInfo pmi;
private boolean dumpInProgress;
@Inject
- public MemoryTile(QSHost host) {
+ public MemoryTile(QSHost host, GarbageMonitor monitor, ActivityStarter starter) {
super(host);
- gm = SystemUIFactory.getInstance().getRootComponent().createGarbageMonitor();
+ gm = monitor;
+ mActivityStarter = starter;
}
@Override
@@ -424,7 +421,7 @@ public class GarbageMonitor implements Dumpable {
dumpInProgress = false;
refreshState();
getHost().collapsePanels();
- mContext.startActivity(shareIntent);
+ mActivityStarter.postStartActivityDismissingKeyguard(shareIntent, 0);
});
}
}.start();
@@ -462,14 +459,14 @@ public class GarbageMonitor implements Dumpable {
? "Dumping..."
: mContext.getString(R.string.heap_dump_tile_name);
if (pmi != null) {
- icon.setPss(pmi.currentPss);
+ icon.setRss(pmi.currentRss);
state.secondaryLabel =
String.format(
- "pss: %s / %s",
- formatBytes(pmi.currentPss * 1024),
+ "rss: %s / %s",
+ formatBytes(pmi.currentRss * 1024),
formatBytes(gm.mHeapLimit * 1024));
} else {
- icon.setPss(0);
+ icon.setRss(0);
state.secondaryLabel = null;
}
state.icon = icon;
@@ -479,8 +476,8 @@ public class GarbageMonitor implements Dumpable {
refreshState();
}
- public long getPss() {
- return pmi != null ? pmi.currentPss : 0;
+ public long getRss() {
+ return pmi != null ? pmi.currentRss : 0;
}
public long getHeapLimit() {
@@ -493,9 +490,8 @@ public class GarbageMonitor implements Dumpable {
public long pid;
public String name;
public long startTime;
- public long currentPss, currentUss;
- public long[] pss = new long[HEAP_TRACK_HISTORY_LEN];
- public long[] uss = new long[HEAP_TRACK_HISTORY_LEN];
+ public long currentRss;
+ public long[] rss = new long[HEAP_TRACK_HISTORY_LEN];
public long max = 1;
public int head = 0;
@@ -517,25 +513,27 @@ public class GarbageMonitor implements Dumpable {
pw.print(name.replace('"', '-'));
pw.print("\", \"start\": ");
pw.print(startTime);
- pw.print(", \"pss\": [");
- // write pss values starting from the oldest, which is pss[head], wrapping around to
- // pss[(head-1) % pss.length]
- for (int i = 0; i < pss.length; i++) {
- if (i > 0) pw.print(",");
- pw.print(pss[(head + i) % pss.length]);
- }
- pw.print("], \"uss\": [");
- for (int i = 0; i < uss.length; i++) {
+ pw.print(", \"rss\": [");
+ // write rss values starting from the oldest, which is rss[head], wrapping around to
+ // rss[(head-1) % rss.length]
+ for (int i = 0; i < rss.length; i++) {
if (i > 0) pw.print(",");
- pw.print(uss[(head + i) % uss.length]);
+ pw.print(rss[(head + i) % rss.length]);
}
pw.println("] }");
}
}
/** */
+ @Singleton
public static class Service extends SystemUI implements Dumpable {
- private GarbageMonitor mGarbageMonitor;
+ private final GarbageMonitor mGarbageMonitor;
+
+ @Inject
+ public Service(Context context, GarbageMonitor garbageMonitor) {
+ super(context);
+ mGarbageMonitor = garbageMonitor;
+ }
@Override
public void start() {
@@ -543,8 +541,6 @@ public class GarbageMonitor implements Dumpable {
Settings.Secure.getInt(
mContext.getContentResolver(), FORCE_ENABLE_LEAK_REPORTING, 0)
!= 0;
- mGarbageMonitor = SystemUIFactory.getInstance().getRootComponent()
- .createGarbageMonitor();
if (LEAK_REPORTING_ENABLED || forceEnable) {
mGarbageMonitor.startLeakMonitor();
}
diff --git a/packages/SystemUI/src/com/android/systemui/util/sensors/AsyncSensorManager.java b/packages/SystemUI/src/com/android/systemui/util/sensors/AsyncSensorManager.java
index 9271bc282615..61de86698f1e 100755
--- a/packages/SystemUI/src/com/android/systemui/util/sensors/AsyncSensorManager.java
+++ b/packages/SystemUI/src/com/android/systemui/util/sensors/AsyncSensorManager.java
@@ -146,9 +146,11 @@ public class AsyncSensorManager extends SensorManager
@Override
protected boolean requestTriggerSensorImpl(TriggerEventListener listener, Sensor sensor) {
- if ( sensor == null ) {
- Log.e(TAG, "sensor cannot be null \n" + Log.getStackTraceString(new Throwable()));
- return false;
+ if (listener == null) {
+ throw new IllegalArgumentException("listener cannot be null");
+ }
+ if (sensor == null) {
+ throw new IllegalArgumentException("sensor cannot be null");
}
mHandler.post(() -> {
if ( sensor == null ) {
diff --git a/packages/SystemUI/src/com/android/systemui/util/sensors/ProximitySensor.java b/packages/SystemUI/src/com/android/systemui/util/sensors/ProximitySensor.java
index c48bdde6adef..a96977a338a9 100644
--- a/packages/SystemUI/src/com/android/systemui/util/sensors/ProximitySensor.java
+++ b/packages/SystemUI/src/com/android/systemui/util/sensors/ProximitySensor.java
@@ -16,7 +16,7 @@
package com.android.systemui.util.sensors;
-import android.content.Context;
+import android.content.res.Resources;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
@@ -24,8 +24,9 @@ import android.hardware.SensorManager;
import android.os.Handler;
import android.util.Log;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.systemui.R;
-import com.android.systemui.shared.plugins.PluginManager;
+import com.android.systemui.dagger.qualifiers.MainResources;
import java.util.ArrayList;
import java.util.List;
@@ -47,7 +48,7 @@ public class ProximitySensor {
private final float mMaxRange;
private List<ProximitySensorListener> mListeners = new ArrayList<>();
private String mTag = null;
- private ProximityEvent mLastEvent;
+ @VisibleForTesting ProximityEvent mLastEvent;
private int mSensorDelay = SensorManager.SENSOR_DELAY_NORMAL;
private boolean mPaused;
private boolean mRegistered;
@@ -64,10 +65,10 @@ public class ProximitySensor {
};
@Inject
- public ProximitySensor(
- Context context, AsyncSensorManager sensorManager, PluginManager pluginManager) {
+ public ProximitySensor(@MainResources Resources resources,
+ AsyncSensorManager sensorManager) {
mSensorManager = sensorManager;
- Sensor sensor = findBrightnessSensor(context);
+ Sensor sensor = findBrightnessSensor(resources);
if (sensor == null) {
mUsingBrightnessSensor = false;
@@ -107,8 +108,8 @@ public class ProximitySensor {
registerInternal();
}
- private Sensor findBrightnessSensor(Context context) {
- String sensorType = context.getString(R.string.doze_brightness_sensor_type);
+ private Sensor findBrightnessSensor(Resources resources) {
+ String sensorType = resources.getString(R.string.doze_brightness_sensor_type);
List<Sensor> sensorList = mSensorManager.getSensorList(Sensor.TYPE_ALL);
Sensor sensor = null;
for (Sensor s : sensorList) {
@@ -146,17 +147,17 @@ public class ProximitySensor {
return false;
}
- logDebug("Using brightness sensor? " + mUsingBrightnessSensor);
mListeners.add(listener);
registerInternal();
return true;
}
- private void registerInternal() {
+ protected void registerInternal() {
if (mRegistered || mPaused || mListeners.isEmpty()) {
return;
}
+ logDebug("Using brightness sensor? " + mUsingBrightnessSensor);
logDebug("Registering sensor listener");
mRegistered = true;
mSensorManager.registerListener(mSensorEventListener, mSensor, mSensorDelay);
@@ -175,7 +176,7 @@ public class ProximitySensor {
}
}
- private void unregisterInternal() {
+ protected void unregisterInternal() {
if (!mRegistered) {
return;
}
diff --git a/packages/SystemUI/src/com/android/systemui/util/wakelock/DelayedWakeLock.java b/packages/SystemUI/src/com/android/systemui/util/wakelock/DelayedWakeLock.java
index 7991e388af7e..e4ebea9483c7 100644
--- a/packages/SystemUI/src/com/android/systemui/util/wakelock/DelayedWakeLock.java
+++ b/packages/SystemUI/src/com/android/systemui/util/wakelock/DelayedWakeLock.java
@@ -16,8 +16,11 @@
package com.android.systemui.util.wakelock;
+import android.content.Context;
import android.os.Handler;
+import javax.inject.Inject;
+
/**
* A wake lock that has a built in delay when releasing to give the framebuffer time to update.
*/
@@ -53,4 +56,46 @@ public class DelayedWakeLock implements WakeLock {
public String toString() {
return TO_STRING_PREFIX + mInner;
}
+
+ /**
+ * An injectable builder for {@see DelayedWakeLock} that has the context already filled in.
+ */
+ public static class Builder {
+ private final Context mContext;
+ private String mTag;
+ private Handler mHandler;
+
+ /**
+ * Constructor for DelayedWakeLock.Builder
+ */
+ @Inject
+ public Builder(Context context) {
+ mContext = context;
+ }
+
+ /**
+ * Set the tag for the WakeLock.
+ */
+ public Builder setTag(String tag) {
+ mTag = tag;
+
+ return this;
+ }
+
+ /**
+ * Set the handler for the DelayedWakeLock.
+ */
+ public Builder setHandler(Handler handler) {
+ mHandler = handler;
+
+ return this;
+ }
+
+ /**
+ * Build the DelayedWakeLock.
+ */
+ public DelayedWakeLock build() {
+ return new DelayedWakeLock(mHandler, WakeLock.createPartial(mContext, mTag));
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogComponent.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogComponent.java
index d2f185a88bfd..25a5139bf661 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogComponent.java
@@ -27,7 +27,6 @@ import android.view.WindowManager.LayoutParams;
import com.android.settingslib.applications.InterestingConfigChanges;
import com.android.systemui.Dependency;
-import com.android.systemui.SystemUI;
import com.android.systemui.keyguard.KeyguardViewMediator;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.PluginDependencyProvider;
@@ -40,9 +39,13 @@ import com.android.systemui.tuner.TunerService;
import java.io.FileDescriptor;
import java.io.PrintWriter;
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
/**
* Implementation of VolumeComponent backed by the new volume dialog.
*/
+@Singleton
public class VolumeDialogComponent implements VolumeComponent, TunerService.Tunable,
VolumeDialogControllerImpl.UserActivityListener{
@@ -54,12 +57,12 @@ public class VolumeDialogComponent implements VolumeComponent, TunerService.Tuna
public static final boolean DEFAULT_VOLUME_UP_TO_EXIT_SILENT = false;
public static final boolean DEFAULT_DO_NOT_DISTURB_WHEN_SILENT = false;
- private final SystemUI mSysui;
protected final Context mContext;
private final VolumeDialogControllerImpl mController;
private final InterestingConfigChanges mConfigChanges = new InterestingConfigChanges(
ActivityInfo.CONFIG_FONT_SCALE | ActivityInfo.CONFIG_LOCALE
| ActivityInfo.CONFIG_ASSETS_PATHS | ActivityInfo.CONFIG_UI_MODE);
+ private final KeyguardViewMediator mKeyguardViewMediator;
private VolumeDialog mDialog;
private VolumePolicy mVolumePolicy = new VolumePolicy(
DEFAULT_VOLUME_DOWN_TO_ENTER_SILENT, // volumeDownToEnterSilent
@@ -68,9 +71,10 @@ public class VolumeDialogComponent implements VolumeComponent, TunerService.Tuna
400 // vibrateToSilentDebounce
);
- public VolumeDialogComponent(SystemUI sysui, Context context) {
- mSysui = sysui;
+ @Inject
+ public VolumeDialogComponent(Context context, KeyguardViewMediator keyguardViewMediator) {
mContext = context;
+ mKeyguardViewMediator = keyguardViewMediator;
mController = (VolumeDialogControllerImpl) Dependency.get(VolumeDialogController.class);
mController.setUserActivityListener(this);
// Allow plugins to reference the VolumeDialogController.
@@ -133,10 +137,7 @@ public class VolumeDialogComponent implements VolumeComponent, TunerService.Tuna
@Override
public void onUserActivity() {
- final KeyguardViewMediator kvm = mSysui.getComponent(KeyguardViewMediator.class);
- if (kvm != null) {
- kvm.userActivity();
- }
+ mKeyguardViewMediator.userActivity();
}
private void applyConfiguration() {
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java
index a6b5b38fd728..2c70fb4c50ec 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java
@@ -59,6 +59,7 @@ import com.android.settingslib.volume.MediaSessions;
import com.android.systemui.Dumpable;
import com.android.systemui.R;
import com.android.systemui.SysUiServiceProvider;
+import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.keyguard.WakefulnessLifecycle;
import com.android.systemui.plugins.VolumeDialogController;
import com.android.systemui.qs.tiles.DndTile;
@@ -137,9 +138,10 @@ public class VolumeDialogControllerImpl implements VolumeDialogController, Dumpa
private UserActivityListener mUserActivityListener;
protected final VC mVolumeController = new VC();
+ protected final BroadcastDispatcher mBroadcastDispatcher;
@Inject
- public VolumeDialogControllerImpl(Context context) {
+ public VolumeDialogControllerImpl(Context context, BroadcastDispatcher broadcastDispatcher) {
mContext = context.getApplicationContext();
mNotificationManager = (NotificationManager) mContext.getSystemService(
Context.NOTIFICATION_SERVICE);
@@ -152,6 +154,7 @@ public class VolumeDialogControllerImpl implements VolumeDialogController, Dumpa
mAudio = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
mNoMan = (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
mObserver = new SettingObserver(mWorker);
+ mBroadcastDispatcher = broadcastDispatcher;
mObserver.init();
mReceiver.init();
mVibrator = (Vibrator) mContext.getSystemService(Context.VIBRATOR_SERVICE);
@@ -618,7 +621,9 @@ public class VolumeDialogControllerImpl implements VolumeDialogController, Dumpa
.PRIORITY_CATEGORY_MEDIA) == 0;
boolean disallowSystem = (policy.priorityCategories & NotificationManager.Policy
.PRIORITY_CATEGORY_SYSTEM) == 0;
- boolean disallowRinger = ZenModeConfig.areAllPriorityOnlyNotificationZenSoundsMuted(policy);
+ // ringer controls notifications, ringer and system sounds, so only disallow ringer changes
+ // if all relevant (notifications + ringer + system) sounds are not allowed to bypass DND
+ boolean disallowRinger = ZenModeConfig.areAllPriorityOnlyRingerSoundsMuted(policy);
if (mState.disallowAlarms == disallowAlarms
&& mState.disallowMedia == disallowMedia
&& mState.disallowRinger == disallowRinger
@@ -1004,11 +1009,11 @@ public class VolumeDialogControllerImpl implements VolumeDialogController, Dumpa
filter.addAction(Intent.ACTION_CONFIGURATION_CHANGED);
filter.addAction(Intent.ACTION_SCREEN_OFF);
filter.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
- mContext.registerReceiver(this, filter, null, mWorker);
+ mBroadcastDispatcher.registerReceiver(this, filter, mWorker);
}
public void destroy() {
- mContext.unregisterReceiver(this);
+ mBroadcastDispatcher.unregisterReceiver(this);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeUI.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeUI.java
index f8cf79322b40..b74313975223 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeUI.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeUI.java
@@ -16,18 +16,22 @@
package com.android.systemui.volume;
+import android.content.Context;
import android.content.res.Configuration;
import android.os.Handler;
import android.util.Log;
import com.android.systemui.R;
import com.android.systemui.SystemUI;
-import com.android.systemui.SystemUIFactory;
import com.android.systemui.qs.tiles.DndTile;
import java.io.FileDescriptor;
import java.io.PrintWriter;
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+@Singleton
public class VolumeUI extends SystemUI {
private static final String TAG = "VolumeUI";
private static boolean LOGD = Log.isLoggable(TAG, Log.DEBUG);
@@ -37,6 +41,12 @@ public class VolumeUI extends SystemUI {
private boolean mEnabled;
private VolumeDialogComponent mVolumeComponent;
+ @Inject
+ public VolumeUI(Context context, VolumeDialogComponent volumeDialogComponent) {
+ super(context);
+ mVolumeComponent = volumeDialogComponent;
+ }
+
@Override
public void start() {
boolean enableVolumeUi = mContext.getResources().getBoolean(R.bool.enable_volume_ui);
@@ -45,8 +55,6 @@ public class VolumeUI extends SystemUI {
mEnabled = enableVolumeUi || enableSafetyWarning;
if (!mEnabled) return;
- mVolumeComponent = SystemUIFactory.getInstance()
- .createVolumeDialogComponent(this, mContext);
mVolumeComponent.setEnableDialogs(enableVolumeUi, enableSafetyWarning);
putComponent(VolumeComponent.class, getVolumeComponent());
setDefaultVolumeController();