diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/dagger/CentralSurfacesDependenciesModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/dagger/CentralSurfacesDependenciesModule.java index 83290af24f2ad..29411e63b1637 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/dagger/CentralSurfacesDependenciesModule.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/dagger/CentralSurfacesDependenciesModule.java @@ -61,6 +61,7 @@ import com.android.systemui.statusbar.notification.collection.legacy.VisualStabi import com.android.systemui.statusbar.notification.collection.notifcollection.CommonNotifCollection; import com.android.systemui.statusbar.notification.collection.render.NotificationVisibilityProvider; import com.android.systemui.statusbar.phone.CentralSurfaces; +import com.android.systemui.statusbar.phone.CentralSurfacesImpl; import com.android.systemui.statusbar.phone.KeyguardBypassController; import com.android.systemui.statusbar.phone.ManagedProfileController; import com.android.systemui.statusbar.phone.ManagedProfileControllerImpl; @@ -87,7 +88,7 @@ import dagger.Module; import dagger.Provides; /** - * This module provides instances needed to construct {@link CentralSurfaces}. These are moved to + * This module provides instances needed to construct {@link CentralSurfacesImpl}. These are moved to * this separate from {@link CentralSurfacesModule} module so that components that wish to build * their own version of CentralSurfaces can include just dependencies, without injecting * CentralSurfaces itself. diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/dagger/StartCentralSurfacesModule.kt b/packages/SystemUI/src/com/android/systemui/statusbar/dagger/StartCentralSurfacesModule.kt index fe55dea7333a9..e84d31dd6a0ff 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/dagger/StartCentralSurfacesModule.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/dagger/StartCentralSurfacesModule.kt @@ -18,6 +18,7 @@ package com.android.systemui.statusbar.dagger import com.android.systemui.CoreStartable import com.android.systemui.statusbar.phone.CentralSurfaces +import com.android.systemui.statusbar.phone.CentralSurfacesImpl import dagger.Binds import dagger.Module import dagger.multibindings.ClassKey @@ -29,5 +30,5 @@ interface StartCentralSurfacesModule { @Binds @IntoMap @ClassKey(CentralSurfaces::class) - abstract fun bindsCentralSurfaces(centralSurfaces: CentralSurfaces): CoreStartable + abstract fun bindsCentralSurfaces(centralSurfaces: CentralSurfacesImpl): CoreStartable } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java index 2d18bc22102ae..39d6b6ef2c8c7 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010 The Android Open Source Project + * Copyright (C) 2022 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. @@ -16,2352 +16,89 @@ package com.android.systemui.statusbar.phone; -import static android.app.StatusBarManager.WINDOW_STATE_HIDDEN; -import static android.app.StatusBarManager.WINDOW_STATE_SHOWING; -import static android.app.StatusBarManager.WindowVisibleState; -import static android.app.StatusBarManager.windowStateToString; -import static android.view.InsetsState.ITYPE_STATUS_BAR; -import static android.view.InsetsState.containsType; -import static android.view.WindowInsetsController.APPEARANCE_LOW_PROFILE_BARS; -import static android.view.WindowInsetsController.APPEARANCE_OPAQUE_STATUS_BARS; -import static android.view.WindowInsetsController.APPEARANCE_SEMI_TRANSPARENT_STATUS_BARS; - -import static androidx.core.view.ViewCompat.IMPORTANT_FOR_ACCESSIBILITY_AUTO; -import static androidx.core.view.ViewCompat.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS; -import static androidx.lifecycle.Lifecycle.State.RESUMED; - -import static com.android.systemui.Dependency.TIME_TICK_HANDLER_NAME; -import static com.android.systemui.charging.WirelessChargingLayout.UNKNOWN_BATTERY_LEVEL; -import static com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_ASLEEP; -import static com.android.systemui.statusbar.NotificationLockscreenUserManager.PERMISSION_SELF; -import static com.android.systemui.statusbar.phone.BarTransitions.MODE_LIGHTS_OUT; -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_TRANSPARENT; -import static com.android.systemui.statusbar.phone.BarTransitions.TransitionMode; import static com.android.wm.shell.transition.Transitions.ENABLE_SHELL_TRANSITIONS; import android.annotation.Nullable; -import android.app.ActivityManager; import android.app.ActivityOptions; -import android.app.ActivityTaskManager; -import android.app.IWallpaperManager; -import android.app.KeyguardManager; -import android.app.Notification; -import android.app.NotificationManager; import android.app.PendingIntent; -import android.app.StatusBarManager; -import android.app.TaskInfo; -import android.app.TaskStackBuilder; -import android.app.UiModeManager; -import android.app.WallpaperInfo; -import android.app.WallpaperManager; -import android.app.admin.DevicePolicyManager; -import android.content.BroadcastReceiver; -import android.content.ComponentCallbacks2; -import android.content.ComponentName; import android.content.Context; import android.content.Intent; -import android.content.IntentFilter; import android.content.pm.PackageManager; -import android.content.pm.PackageManager.NameNotFoundException; -import android.content.pm.ResolveInfo; -import android.content.res.Configuration; -import android.graphics.Point; -import android.graphics.PointF; -import android.hardware.devicestate.DeviceStateManager; -import android.metrics.LogMaker; -import android.net.Uri; import android.os.Bundle; -import android.os.Handler; -import android.os.Looper; -import android.os.PowerManager; -import android.os.RemoteException; -import android.os.ServiceManager; -import android.os.SystemClock; -import android.os.SystemProperties; -import android.os.Trace; import android.os.UserHandle; -import android.provider.Settings; -import android.service.dreams.DreamService; -import android.service.dreams.IDreamManager; import android.service.notification.StatusBarNotification; -import android.text.TextUtils; -import android.util.ArraySet; -import android.util.DisplayMetrics; -import android.util.EventLog; -import android.util.IndentingPrintWriter; -import android.util.Log; -import android.util.MathUtils; -import android.util.Slog; -import android.view.Display; -import android.view.IRemoteAnimationRunner; -import android.view.IWindowManager; import android.view.KeyEvent; import android.view.MotionEvent; import android.view.RemoteAnimationAdapter; -import android.view.ThreadedRenderer; import android.view.View; import android.view.ViewGroup; -import android.view.WindowInsetsController.Appearance; -import android.view.WindowManager; -import android.view.WindowManagerGlobal; -import android.view.accessibility.AccessibilityManager; -import android.widget.DateTimeView; import android.window.SplashScreen; import androidx.annotation.NonNull; import androidx.lifecycle.Lifecycle; import androidx.lifecycle.LifecycleOwner; -import androidx.lifecycle.LifecycleRegistry; import com.android.internal.annotations.VisibleForTesting; -import com.android.internal.colorextraction.ColorExtractor; -import com.android.internal.jank.InteractionJankMonitor; -import com.android.internal.logging.MetricsLogger; -import com.android.internal.logging.UiEvent; -import com.android.internal.logging.UiEventLogger; -import com.android.internal.logging.UiEventLoggerImpl; -import com.android.internal.logging.nano.MetricsProto.MetricsEvent; -import com.android.internal.statusbar.IStatusBarService; import com.android.internal.statusbar.RegisterStatusBarResult; -import com.android.keyguard.KeyguardUpdateMonitor; -import com.android.keyguard.KeyguardUpdateMonitorCallback; -import com.android.keyguard.ViewMediatorCallback; -import com.android.systemui.ActivityIntentHelper; -import com.android.systemui.AutoReinflateContainer; -import com.android.systemui.CoreStartable; -import com.android.systemui.DejankUtils; -import com.android.systemui.EventLogTags; -import com.android.systemui.InitController; -import com.android.systemui.Prefs; -import com.android.systemui.R; -import com.android.systemui.accessibility.floatingmenu.AccessibilityFloatingMenuController; +import com.android.systemui.Dumpable; import com.android.systemui.animation.ActivityLaunchAnimator; -import com.android.systemui.animation.DelegateLaunchAnimatorController; import com.android.systemui.animation.RemoteTransitionAdapter; -import com.android.systemui.assist.AssistManager; -import com.android.systemui.biometrics.AuthRippleController; -import com.android.systemui.broadcast.BroadcastDispatcher; -import com.android.systemui.camera.CameraIntents; -import com.android.systemui.charging.WirelessChargingAnimation; -import com.android.systemui.classifier.FalsingCollector; -import com.android.systemui.colorextraction.SysuiColorExtractor; -import com.android.systemui.dagger.qualifiers.Main; -import com.android.systemui.dagger.qualifiers.UiBackground; -import com.android.systemui.demomode.DemoMode; -import com.android.systemui.demomode.DemoModeController; -import com.android.systemui.dreams.DreamOverlayStateController; -import com.android.systemui.emergency.EmergencyGesture; -import com.android.systemui.flags.FeatureFlags; -import com.android.systemui.flags.Flags; -import com.android.systemui.fragments.ExtensionFragmentListener; -import com.android.systemui.fragments.FragmentHostManager; -import com.android.systemui.fragments.FragmentService; -import com.android.systemui.keyguard.KeyguardService; -import com.android.systemui.keyguard.KeyguardUnlockAnimationController; -import com.android.systemui.keyguard.KeyguardViewMediator; -import com.android.systemui.keyguard.ScreenLifecycle; -import com.android.systemui.keyguard.WakefulnessLifecycle; -import com.android.systemui.navigationbar.NavigationBarController; import com.android.systemui.navigationbar.NavigationBarView; import com.android.systemui.plugins.ActivityStarter; -import com.android.systemui.plugins.DarkIconDispatcher; -import com.android.systemui.plugins.FalsingManager; -import com.android.systemui.plugins.OverlayPlugin; -import com.android.systemui.plugins.PluginDependencyProvider; -import com.android.systemui.plugins.PluginListener; -import com.android.systemui.plugins.qs.QS; -import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper.SnoozeOption; -import com.android.systemui.plugins.statusbar.StatusBarStateController; -import com.android.systemui.qs.QSFragment; +import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper; import com.android.systemui.qs.QSPanelController; -import com.android.systemui.recents.ScreenPinningRequest; -import com.android.systemui.scrim.ScrimView; -import com.android.systemui.settings.brightness.BrightnessSliderController; -import com.android.systemui.shared.plugins.PluginManager; -import com.android.systemui.statusbar.AutoHideUiElement; -import com.android.systemui.statusbar.BackDropView; -import com.android.systemui.statusbar.CircleReveal; -import com.android.systemui.statusbar.CommandQueue; import com.android.systemui.statusbar.GestureRecorder; -import com.android.systemui.statusbar.KeyboardShortcuts; -import com.android.systemui.statusbar.KeyguardIndicationController; -import com.android.systemui.statusbar.LiftReveal; import com.android.systemui.statusbar.LightRevealScrim; -import com.android.systemui.statusbar.LockscreenShadeTransitionController; -import com.android.systemui.statusbar.NotificationLockscreenUserManager; -import com.android.systemui.statusbar.NotificationMediaManager; import com.android.systemui.statusbar.NotificationPresenter; -import com.android.systemui.statusbar.NotificationRemoteInputManager; -import com.android.systemui.statusbar.NotificationShadeDepthController; -import com.android.systemui.statusbar.NotificationShadeWindowController; -import com.android.systemui.statusbar.NotificationShelfController; -import com.android.systemui.statusbar.NotificationViewHierarchyManager; -import com.android.systemui.statusbar.PowerButtonReveal; -import com.android.systemui.statusbar.PulseExpansionHandler; -import com.android.systemui.statusbar.StatusBarState; -import com.android.systemui.statusbar.SysuiStatusBarStateController; -import com.android.systemui.statusbar.charging.WiredChargingRippleController; -import com.android.systemui.statusbar.connectivity.NetworkController; -import com.android.systemui.statusbar.core.StatusBarInitializer; -import com.android.systemui.statusbar.notification.DynamicPrivacyController; -import com.android.systemui.statusbar.notification.NotifPipelineFlags; -import com.android.systemui.statusbar.notification.NotificationActivityStarter; -import com.android.systemui.statusbar.notification.NotificationEntryManager; -import com.android.systemui.statusbar.notification.NotificationLaunchAnimatorControllerProvider; -import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator; -import com.android.systemui.statusbar.notification.collection.legacy.VisualStabilityManager; -import com.android.systemui.statusbar.notification.collection.render.NotifShadeEventSource; -import com.android.systemui.statusbar.notification.init.NotificationsController; -import com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProvider; -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.notification.stack.NotificationStackScrollLayout; -import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController; -import com.android.systemui.statusbar.phone.dagger.CentralSurfacesComponent; -import com.android.systemui.statusbar.phone.dagger.StatusBarPhoneModule; -import com.android.systemui.statusbar.phone.ongoingcall.OngoingCallController; -import com.android.systemui.statusbar.phone.panelstate.PanelExpansionChangeEvent; -import com.android.systemui.statusbar.phone.panelstate.PanelExpansionStateManager; -import com.android.systemui.statusbar.policy.BatteryController; -import com.android.systemui.statusbar.policy.BrightnessMirrorController; -import com.android.systemui.statusbar.policy.ConfigurationController; -import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener; -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.KeyguardStateController; -import com.android.systemui.statusbar.policy.UserInfoControllerImpl; -import com.android.systemui.statusbar.policy.UserSwitcherController; -import com.android.systemui.statusbar.window.StatusBarWindowController; -import com.android.systemui.statusbar.window.StatusBarWindowStateController; -import com.android.systemui.util.DumpUtilsKt; -import com.android.systemui.util.WallpaperController; -import com.android.systemui.util.concurrency.DelayableExecutor; -import com.android.systemui.util.concurrency.MessageRouter; -import com.android.systemui.volume.VolumeComponent; -import com.android.systemui.wmshell.BubblesManager; -import com.android.wm.shell.bubbles.Bubbles; -import com.android.wm.shell.startingsurface.SplashscreenContentDrawer; -import com.android.wm.shell.startingsurface.StartingSurface; import java.io.PrintWriter; -import java.io.StringWriter; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.concurrent.Executor; - -import javax.inject.Named; - -import dagger.Lazy; - -/** - * A class handling initialization and coordination between some of the key central surfaces in - * System UI: The notification shade, the keyguard (lockscreen), and the status bar. - * - * This class is not our ideal architecture because it doesn't enforce much isolation between these - * three mostly disparate surfaces. In an ideal world, this class would not exist. Instead, we would - * break it up into three modules -- one for each of those three surfaces -- and we would define any - * APIs that are needed for these surfaces to communicate with each other when necessary. - * - * If at all possible, please avoid adding additional code to this monstrous class! Our goal is - * to break up this class into many small classes, and any code added here will slow down that goal. - * - */ -public class CentralSurfaces extends CoreStartable implements - ActivityStarter, - LifecycleOwner { - public static final boolean MULTIUSER_DEBUG = false; - - protected static final int MSG_DISMISS_KEYBOARD_SHORTCUTS_MENU = 1027; +public interface CentralSurfaces extends Dumpable, ActivityStarter, LifecycleOwner { + boolean MULTIUSER_DEBUG = false; // Should match the values in PhoneWindowManager - public static final String SYSTEM_DIALOG_REASON_KEY = "reason"; - public static final String SYSTEM_DIALOG_REASON_RECENT_APPS = "recentapps"; - public static final String SYSTEM_DIALOG_REASON_DREAM = "dream"; - static public final String SYSTEM_DIALOG_REASON_SCREENSHOT = "screenshot"; - - private static final String BANNER_ACTION_CANCEL = - "com.android.systemui.statusbar.banner_action_cancel"; - private static final String BANNER_ACTION_SETUP = - "com.android.systemui.statusbar.banner_action_setup"; - public static final String TAG = "CentralSurfaces"; - public static final boolean DEBUG = false; - public static final boolean SPEW = false; - public static final boolean DUMPTRUCK = true; // extra dumpsys info - public static final boolean DEBUG_GESTURES = false; - public static final boolean DEBUG_MEDIA_FAKE_ARTWORK = false; - public static final boolean DEBUG_CAMERA_LIFT = false; - - public static final boolean DEBUG_WINDOW_STATE = false; - + String SYSTEM_DIALOG_REASON_KEY = "reason"; + String SYSTEM_DIALOG_REASON_RECENT_APPS = "recentapps"; + String SYSTEM_DIALOG_REASON_DREAM = "dream"; + String SYSTEM_DIALOG_REASON_SCREENSHOT = "screenshot"; + String TAG = "CentralSurfaces"; + boolean DEBUG = false; + boolean SPEW = false; + boolean DUMPTRUCK = true; // extra dumpsys info + boolean DEBUG_GESTURES = false; + boolean DEBUG_MEDIA_FAKE_ARTWORK = false; + boolean DEBUG_CAMERA_LIFT = false; + boolean DEBUG_WINDOW_STATE = false; // additional instrumentation for testing purposes; intended to be left on during development - public static final boolean CHATTY = DEBUG; - - public static final boolean SHOW_LOCKSCREEN_MEDIA_ARTWORK = true; - - public static final String ACTION_FAKE_ARTWORK = "fake_artwork"; - - private static final int MSG_OPEN_SETTINGS_PANEL = 1002; - private static final int MSG_LAUNCH_TRANSITION_TIMEOUT = 1003; - // 1020-1040 reserved for BaseStatusBar - - // Time after we abort the launch transition. - static final long LAUNCH_TRANSITION_TIMEOUT_MS = 5000; - - protected static final boolean CLOSE_PANEL_WHEN_EMPTIED = true; - - /** - * The delay to reset the hint text when the hint animation is finished running. - */ - private static final int HINT_RESET_DELAY_MS = 1200; - - public static final int FADE_KEYGUARD_START_DELAY = 100; - public static final int FADE_KEYGUARD_DURATION = 300; - public static final int FADE_KEYGUARD_DURATION_PULSING = 96; - - public static final long[] CAMERA_LAUNCH_GESTURE_VIBRATION_TIMINGS = + boolean CHATTY = DEBUG; + boolean SHOW_LOCKSCREEN_MEDIA_ARTWORK = true; + String ACTION_FAKE_ARTWORK = "fake_artwork"; + int FADE_KEYGUARD_START_DELAY = 100; + int FADE_KEYGUARD_DURATION = 300; + int FADE_KEYGUARD_DURATION_PULSING = 96; + long[] CAMERA_LAUNCH_GESTURE_VIBRATION_TIMINGS = new long[]{20, 20, 20, 20, 100, 20}; - public static final int[] CAMERA_LAUNCH_GESTURE_VIBRATION_AMPLITUDES = + int[] CAMERA_LAUNCH_GESTURE_VIBRATION_AMPLITUDES = new int[]{39, 82, 139, 213, 0, 127}; /** If true, the lockscreen will show a distinct wallpaper */ - public static final boolean ENABLE_LOCKSCREEN_WALLPAPER = true; + boolean ENABLE_LOCKSCREEN_WALLPAPER = true; + // Time after we abort the launch transition. + long LAUNCH_TRANSITION_TIMEOUT_MS = 5000; + int MSG_DISMISS_KEYBOARD_SHORTCUTS_MENU = 1027; - private static final UiEventLogger sUiEventLogger = new UiEventLoggerImpl(); + static final boolean CLOSE_PANEL_WHEN_EMPTIED = true; - private final LockscreenShadeTransitionController mLockscreenShadeTransitionController; - private final DreamOverlayStateController mDreamOverlayStateController; - private CentralSurfacesCommandQueueCallbacks mCommandQueueCallbacks; - private float mTransitionToFullShadeProgress = 0f; - private NotificationListContainer mNotifListContainer; - - private final KeyguardStateController.Callback mKeyguardStateControllerCallback = - new KeyguardStateController.Callback() { - @Override - public void onKeyguardShowingChanged() { - boolean occluded = mKeyguardStateController.isOccluded(); - mStatusBarHideIconsForBouncerManager.setIsOccludedAndTriggerUpdate(occluded); - mScrimController.setKeyguardOccluded(occluded); - } - }; - - void onStatusBarWindowStateChanged(@WindowVisibleState int state) { - updateBubblesVisibility(); - mStatusBarWindowState = state; - } - - void acquireGestureWakeLock(long time) { - mGestureWakeLock.acquire(time); - } - - boolean setAppearance(int appearance) { - if (mAppearance != appearance) { - mAppearance = appearance; - return updateBarMode(barMode(isTransientShown(), appearance)); - } - - return false; - } - - int getBarMode() { - return mStatusBarMode; - } - - void resendMessage(int msg) { - mMessageRouter.cancelMessages(msg); - mMessageRouter.sendMessage(msg); - } - - void resendMessage(Object msg) { - mMessageRouter.cancelMessages(msg.getClass()); - mMessageRouter.sendMessage(msg); - } - - int getDisabled1() { - return mDisabled1; - } - - void setDisabled1(int disabled) { - mDisabled1 = disabled; - } - - int getDisabled2() { - return mDisabled2; - } - - void setDisabled2(int disabled) { - mDisabled2 = disabled; - } - - void setLastCameraLaunchSource(int source) { - mLastCameraLaunchSource = source; - } - - void setLaunchCameraOnFinishedGoingToSleep(boolean launch) { - mLaunchCameraOnFinishedGoingToSleep = launch; - } - - void setLaunchCameraOnFinishedWaking(boolean launch) { - mLaunchCameraWhenFinishedWaking = launch; - } - - void setLaunchEmergencyActionOnFinishedGoingToSleep(boolean launch) { - mLaunchEmergencyActionOnFinishedGoingToSleep = launch; - } - - void setLaunchEmergencyActionOnFinishedWaking(boolean launch) { - mLaunchEmergencyActionWhenFinishedWaking = launch; - } - - void setTopHidesStatusBar(boolean hides) { - mTopHidesStatusBar = hides; - } - - QSPanelController getQSPanelController() { - return mQSPanelController; - } - - /** */ - public void animateExpandNotificationsPanel() { - mCommandQueueCallbacks.animateExpandNotificationsPanel(); - } - - /** */ - public void animateExpandSettingsPanel(@Nullable String subpanel) { - mCommandQueueCallbacks.animateExpandSettingsPanel(subpanel); - } - - /** */ - public void animateCollapsePanels(int flags, boolean force) { - mCommandQueueCallbacks.animateCollapsePanels(flags, force); - } - - /** */ - public void togglePanel() { - mCommandQueueCallbacks.togglePanel(); - } - /** - * The {@link StatusBarState} of the status bar. - */ - protected int mState; // TODO: remove this. Just use StatusBarStateController - protected boolean mBouncerShowing; - private boolean mBouncerShowingOverDream; - - private final PhoneStatusBarPolicy mIconPolicy; - - private final VolumeComponent mVolumeComponent; - private BrightnessMirrorController mBrightnessMirrorController; - private boolean mBrightnessMirrorVisible; - private BiometricUnlockController mBiometricUnlockController; - private final LightBarController mLightBarController; - private final Lazy mLockscreenWallpaperLazy; - private final LockscreenGestureLogger mLockscreenGestureLogger; - @Nullable - protected LockscreenWallpaper mLockscreenWallpaper; - private final AutoHideController mAutoHideController; - - private final Point mCurrentDisplaySize = new Point(); - - protected NotificationShadeWindowView mNotificationShadeWindowView; - protected PhoneStatusBarView mStatusBarView; - private PhoneStatusBarViewController mPhoneStatusBarViewController; - private PhoneStatusBarTransitions mStatusBarTransitions; - private AuthRippleController mAuthRippleController; - @WindowVisibleState private int mStatusBarWindowState = WINDOW_STATE_SHOWING; - protected final NotificationShadeWindowController mNotificationShadeWindowController; - private final StatusBarWindowController mStatusBarWindowController; - private final KeyguardUpdateMonitor mKeyguardUpdateMonitor; - @VisibleForTesting - DozeServiceHost mDozeServiceHost; - private boolean mWakeUpComingFromTouch; - private PointF mWakeUpTouchLocation; - private LightRevealScrim mLightRevealScrim; - private PowerButtonReveal mPowerButtonReveal; - - private final Object mQueueLock = new Object(); - - private final PulseExpansionHandler mPulseExpansionHandler; - private final NotificationWakeUpCoordinator mWakeUpCoordinator; - private final KeyguardBypassController mKeyguardBypassController; - private final KeyguardStateController mKeyguardStateController; - private final HeadsUpManagerPhone mHeadsUpManager; - private final StatusBarTouchableRegionManager mStatusBarTouchableRegionManager; - private final DynamicPrivacyController mDynamicPrivacyController; - private final FalsingCollector mFalsingCollector; - private final FalsingManager mFalsingManager; - private final BroadcastDispatcher mBroadcastDispatcher; - private final ConfigurationController mConfigurationController; - protected NotificationShadeWindowViewController mNotificationShadeWindowViewController; - private final DozeParameters mDozeParameters; - private final Lazy mBiometricUnlockControllerLazy; - private final CentralSurfacesComponent.Factory mCentralSurfacesComponentFactory; - private final PluginManager mPluginManager; - private final ShadeController mShadeController; - private final InitController mInitController; - - private final PluginDependencyProvider mPluginDependencyProvider; - private final KeyguardDismissUtil mKeyguardDismissUtil; - private final ExtensionController mExtensionController; - private final UserInfoControllerImpl mUserInfoControllerImpl; - private final DemoModeController mDemoModeController; - private final NotificationsController mNotificationsController; - private final OngoingCallController mOngoingCallController; - private final StatusBarSignalPolicy mStatusBarSignalPolicy; - private final StatusBarHideIconsForBouncerManager mStatusBarHideIconsForBouncerManager; - - // expanded notifications - // the sliding/resizing panel within the notification window - protected NotificationPanelViewController mNotificationPanelViewController; - - // settings - private QSPanelController mQSPanelController; - - KeyguardIndicationController mKeyguardIndicationController; - - private View mReportRejectedTouch; - - private boolean mExpandedVisible; - - private final int[] mAbsPos = new int[2]; - - private final NotifShadeEventSource mNotifShadeEventSource; - protected final NotificationEntryManager mEntryManager; - private final NotificationGutsManager mGutsManager; - private final NotificationLogger mNotificationLogger; - private final NotificationViewHierarchyManager mViewHierarchyManager; - private final PanelExpansionStateManager mPanelExpansionStateManager; - private final KeyguardViewMediator mKeyguardViewMediator; - protected final NotificationInterruptStateProvider mNotificationInterruptStateProvider; - private final BrightnessSliderController.Factory mBrightnessSliderFactory; - private final FeatureFlags mFeatureFlags; - private final FragmentService mFragmentService; - private final ScreenOffAnimationController mScreenOffAnimationController; - private final WallpaperController mWallpaperController; - private final KeyguardUnlockAnimationController mKeyguardUnlockAnimationController; - private final MessageRouter mMessageRouter; - private final WallpaperManager mWallpaperManager; - - private CentralSurfacesComponent mCentralSurfacesComponent; - - // Flags for disabling the status bar - // Two variables becaseu the first one evidently ran out of room for new flags. - private int mDisabled1 = 0; - private int mDisabled2 = 0; - - /** @see android.view.WindowInsetsController#setSystemBarsAppearance(int, int) */ - private @Appearance int mAppearance; - - private boolean mTransientShown; - - private final DisplayMetrics mDisplayMetrics; - - // XXX: gesture research - private final GestureRecorder mGestureRec = DEBUG_GESTURES - ? new GestureRecorder("/sdcard/statusbar_gestures.dat") - : null; - - private final ScreenPinningRequest mScreenPinningRequest; - - private final MetricsLogger mMetricsLogger; - - // ensure quick settings is disabled until the current user makes it through the setup wizard - @VisibleForTesting - protected boolean mUserSetup = false; - - @VisibleForTesting - public enum StatusBarUiEvent implements UiEventLogger.UiEventEnum { - @UiEvent(doc = "Secured lockscreen is opened.") - LOCKSCREEN_OPEN_SECURE(405), - - @UiEvent(doc = "Lockscreen without security is opened.") - LOCKSCREEN_OPEN_INSECURE(406), - - @UiEvent(doc = "Secured lockscreen is closed.") - LOCKSCREEN_CLOSE_SECURE(407), - - @UiEvent(doc = "Lockscreen without security is closed.") - LOCKSCREEN_CLOSE_INSECURE(408), - - @UiEvent(doc = "Secured bouncer is opened.") - BOUNCER_OPEN_SECURE(409), - - @UiEvent(doc = "Bouncer without security is opened.") - BOUNCER_OPEN_INSECURE(410), - - @UiEvent(doc = "Secured bouncer is closed.") - BOUNCER_CLOSE_SECURE(411), - - @UiEvent(doc = "Bouncer without security is closed.") - BOUNCER_CLOSE_INSECURE(412); - - private final int mId; - - StatusBarUiEvent(int id) { - mId = id; - } - - @Override - public int getId() { - return mId; - } - } - - private Handler mMainHandler; - private final DelayableExecutor mMainExecutor; - - private int mInteractingWindows; - private @TransitionMode int mStatusBarMode; - - private final ViewMediatorCallback mKeyguardViewMediatorCallback; - private final ScrimController mScrimController; - protected DozeScrimController mDozeScrimController; - private final Executor mUiBgExecutor; - - protected boolean mDozing; - private boolean mIsFullscreen; - - boolean mCloseQsBeforeScreenOff; - - private final NotificationMediaManager mMediaManager; - private final NotificationLockscreenUserManager mLockscreenUserManager; - private final NotificationRemoteInputManager mRemoteInputManager; - private boolean mWallpaperSupported; - - private Runnable mLaunchTransitionEndRunnable; - private Runnable mLaunchTransitionCancelRunnable; - private boolean mLaunchCameraWhenFinishedWaking; - private boolean mLaunchCameraOnFinishedGoingToSleep; - private boolean mLaunchEmergencyActionWhenFinishedWaking; - private boolean mLaunchEmergencyActionOnFinishedGoingToSleep; - private int mLastCameraLaunchSource; - protected PowerManager.WakeLock mGestureWakeLock; - - private final int[] mTmpInt2 = new int[2]; - - // Fingerprint (as computed by getLoggingFingerprint() of the last logged state. - private int mLastLoggedStateFingerprint; - private boolean mTopHidesStatusBar; - private boolean mStatusBarWindowHidden; - private boolean mIsLaunchingActivityOverLockscreen; - - private final UserSwitcherController mUserSwitcherController; - private final NetworkController mNetworkController; - private final LifecycleRegistry mLifecycle = new LifecycleRegistry(this); - protected final BatteryController mBatteryController; - protected boolean mPanelExpanded; - private UiModeManager mUiModeManager; - private LogMaker mStatusBarStateLog; - protected final NotificationIconAreaController mNotificationIconAreaController; - @Nullable private View mAmbientIndicationContainer; - private final SysuiColorExtractor mColorExtractor; - private final ScreenLifecycle mScreenLifecycle; - private final WakefulnessLifecycle mWakefulnessLifecycle; - - private boolean mNoAnimationOnNextBarModeChange; - private final SysuiStatusBarStateController mStatusBarStateController; - - private final ActivityLaunchAnimator mActivityLaunchAnimator; - private NotificationLaunchAnimatorControllerProvider mNotificationAnimationProvider; - protected NotificationPresenter mPresenter; - private NotificationActivityStarter mNotificationActivityStarter; - private final Lazy mNotificationShadeDepthControllerLazy; - private final Optional mBubblesManagerOptional; - private final Optional mBubblesOptional; - private final Bubbles.BubbleExpandListener mBubbleExpandListener; - private final Optional mStartingSurfaceOptional; - private final NotifPipelineFlags mNotifPipelineFlags; - - private final ActivityIntentHelper mActivityIntentHelper; - private NotificationStackScrollLayoutController mStackScrollerController; - - private final ColorExtractor.OnColorsChangedListener mOnColorsChangedListener = - (extractor, which) -> updateTheme(); - - private final InteractionJankMonitor mJankMonitor; - - - /** - * Public constructor for CentralSurfaces. - * - * CentralSurfaces is considered optional, and therefore can not be marked as @Inject directly. - * Instead, an @Provide method is included. See {@link StatusBarPhoneModule}. - */ - @SuppressWarnings("OptionalUsedAsFieldOrParameterType") - public CentralSurfaces( - Context context, - NotificationsController notificationsController, - FragmentService fragmentService, - LightBarController lightBarController, - AutoHideController autoHideController, - StatusBarWindowController statusBarWindowController, - StatusBarWindowStateController statusBarWindowStateController, - KeyguardUpdateMonitor keyguardUpdateMonitor, - StatusBarSignalPolicy statusBarSignalPolicy, - PulseExpansionHandler pulseExpansionHandler, - NotificationWakeUpCoordinator notificationWakeUpCoordinator, - KeyguardBypassController keyguardBypassController, - KeyguardStateController keyguardStateController, - HeadsUpManagerPhone headsUpManagerPhone, - DynamicPrivacyController dynamicPrivacyController, - FalsingManager falsingManager, - FalsingCollector falsingCollector, - BroadcastDispatcher broadcastDispatcher, - NotifShadeEventSource notifShadeEventSource, - NotificationEntryManager notificationEntryManager, - NotificationGutsManager notificationGutsManager, - NotificationLogger notificationLogger, - NotificationInterruptStateProvider notificationInterruptStateProvider, - NotificationViewHierarchyManager notificationViewHierarchyManager, - PanelExpansionStateManager panelExpansionStateManager, - KeyguardViewMediator keyguardViewMediator, - DisplayMetrics displayMetrics, - MetricsLogger metricsLogger, - @UiBackground Executor uiBgExecutor, - NotificationMediaManager notificationMediaManager, - NotificationLockscreenUserManager lockScreenUserManager, - NotificationRemoteInputManager remoteInputManager, - UserSwitcherController userSwitcherController, - NetworkController networkController, - BatteryController batteryController, - SysuiColorExtractor colorExtractor, - ScreenLifecycle screenLifecycle, - WakefulnessLifecycle wakefulnessLifecycle, - SysuiStatusBarStateController statusBarStateController, - Optional bubblesManagerOptional, - Optional bubblesOptional, - VisualStabilityManager visualStabilityManager, - DeviceProvisionedController deviceProvisionedController, - NavigationBarController navigationBarController, - AccessibilityFloatingMenuController accessibilityFloatingMenuController, - Lazy assistManagerLazy, - ConfigurationController configurationController, - NotificationShadeWindowController notificationShadeWindowController, - DozeParameters dozeParameters, - ScrimController scrimController, - Lazy lockscreenWallpaperLazy, - LockscreenGestureLogger lockscreenGestureLogger, - Lazy biometricUnlockControllerLazy, - DozeServiceHost dozeServiceHost, - PowerManager powerManager, - ScreenPinningRequest screenPinningRequest, - DozeScrimController dozeScrimController, - VolumeComponent volumeComponent, - CommandQueue commandQueue, - CentralSurfacesComponent.Factory centralSurfacesComponentFactory, - PluginManager pluginManager, - ShadeController shadeController, - StatusBarKeyguardViewManager statusBarKeyguardViewManager, - ViewMediatorCallback viewMediatorCallback, - InitController initController, - @Named(TIME_TICK_HANDLER_NAME) Handler timeTickHandler, - PluginDependencyProvider pluginDependencyProvider, - KeyguardDismissUtil keyguardDismissUtil, - ExtensionController extensionController, - UserInfoControllerImpl userInfoControllerImpl, - PhoneStatusBarPolicy phoneStatusBarPolicy, - KeyguardIndicationController keyguardIndicationController, - DemoModeController demoModeController, - Lazy notificationShadeDepthControllerLazy, - StatusBarTouchableRegionManager statusBarTouchableRegionManager, - NotificationIconAreaController notificationIconAreaController, - BrightnessSliderController.Factory brightnessSliderFactory, - ScreenOffAnimationController screenOffAnimationController, - WallpaperController wallpaperController, - OngoingCallController ongoingCallController, - StatusBarHideIconsForBouncerManager statusBarHideIconsForBouncerManager, - LockscreenShadeTransitionController lockscreenShadeTransitionController, - FeatureFlags featureFlags, - KeyguardUnlockAnimationController keyguardUnlockAnimationController, - @Main Handler mainHandler, - @Main DelayableExecutor delayableExecutor, - @Main MessageRouter messageRouter, - WallpaperManager wallpaperManager, - Optional startingSurfaceOptional, - ActivityLaunchAnimator activityLaunchAnimator, - NotifPipelineFlags notifPipelineFlags, - InteractionJankMonitor jankMonitor, - DeviceStateManager deviceStateManager, - DreamOverlayStateController dreamOverlayStateController, - WiredChargingRippleController wiredChargingRippleController) { - super(context); - mNotificationsController = notificationsController; - mFragmentService = fragmentService; - mLightBarController = lightBarController; - mAutoHideController = autoHideController; - mStatusBarWindowController = statusBarWindowController; - mKeyguardUpdateMonitor = keyguardUpdateMonitor; - mPulseExpansionHandler = pulseExpansionHandler; - mWakeUpCoordinator = notificationWakeUpCoordinator; - mKeyguardBypassController = keyguardBypassController; - mKeyguardStateController = keyguardStateController; - mHeadsUpManager = headsUpManagerPhone; - mKeyguardIndicationController = keyguardIndicationController; - mStatusBarTouchableRegionManager = statusBarTouchableRegionManager; - mDynamicPrivacyController = dynamicPrivacyController; - mFalsingCollector = falsingCollector; - mFalsingManager = falsingManager; - mBroadcastDispatcher = broadcastDispatcher; - mNotifShadeEventSource = notifShadeEventSource; - mEntryManager = notificationEntryManager; - mGutsManager = notificationGutsManager; - mNotificationLogger = notificationLogger; - mNotificationInterruptStateProvider = notificationInterruptStateProvider; - mViewHierarchyManager = notificationViewHierarchyManager; - mPanelExpansionStateManager = panelExpansionStateManager; - mKeyguardViewMediator = keyguardViewMediator; - mDisplayMetrics = displayMetrics; - mMetricsLogger = metricsLogger; - mUiBgExecutor = uiBgExecutor; - mMediaManager = notificationMediaManager; - mLockscreenUserManager = lockScreenUserManager; - mRemoteInputManager = remoteInputManager; - mUserSwitcherController = userSwitcherController; - mNetworkController = networkController; - mBatteryController = batteryController; - mColorExtractor = colorExtractor; - mScreenLifecycle = screenLifecycle; - mWakefulnessLifecycle = wakefulnessLifecycle; - mStatusBarStateController = statusBarStateController; - mBubblesManagerOptional = bubblesManagerOptional; - mBubblesOptional = bubblesOptional; - mVisualStabilityManager = visualStabilityManager; - mDeviceProvisionedController = deviceProvisionedController; - mNavigationBarController = navigationBarController; - mAccessibilityFloatingMenuController = accessibilityFloatingMenuController; - mAssistManagerLazy = assistManagerLazy; - mConfigurationController = configurationController; - mNotificationShadeWindowController = notificationShadeWindowController; - mDozeServiceHost = dozeServiceHost; - mPowerManager = powerManager; - mDozeParameters = dozeParameters; - mScrimController = scrimController; - mLockscreenWallpaperLazy = lockscreenWallpaperLazy; - mLockscreenGestureLogger = lockscreenGestureLogger; - mScreenPinningRequest = screenPinningRequest; - mDozeScrimController = dozeScrimController; - mBiometricUnlockControllerLazy = biometricUnlockControllerLazy; - mNotificationShadeDepthControllerLazy = notificationShadeDepthControllerLazy; - mVolumeComponent = volumeComponent; - mCommandQueue = commandQueue; - mCentralSurfacesComponentFactory = centralSurfacesComponentFactory; - mPluginManager = pluginManager; - mShadeController = shadeController; - mStatusBarKeyguardViewManager = statusBarKeyguardViewManager; - mKeyguardViewMediatorCallback = viewMediatorCallback; - mInitController = initController; - mPluginDependencyProvider = pluginDependencyProvider; - mKeyguardDismissUtil = keyguardDismissUtil; - mExtensionController = extensionController; - mUserInfoControllerImpl = userInfoControllerImpl; - mIconPolicy = phoneStatusBarPolicy; - mDemoModeController = demoModeController; - mNotificationIconAreaController = notificationIconAreaController; - mBrightnessSliderFactory = brightnessSliderFactory; - mWallpaperController = wallpaperController; - mOngoingCallController = ongoingCallController; - mStatusBarSignalPolicy = statusBarSignalPolicy; - mStatusBarHideIconsForBouncerManager = statusBarHideIconsForBouncerManager; - mFeatureFlags = featureFlags; - mKeyguardUnlockAnimationController = keyguardUnlockAnimationController; - mMainHandler = mainHandler; - mMainExecutor = delayableExecutor; - mMessageRouter = messageRouter; - mWallpaperManager = wallpaperManager; - mJankMonitor = jankMonitor; - mDreamOverlayStateController = dreamOverlayStateController; - - mLockscreenShadeTransitionController = lockscreenShadeTransitionController; - mStartingSurfaceOptional = startingSurfaceOptional; - mNotifPipelineFlags = notifPipelineFlags; - lockscreenShadeTransitionController.setCentralSurfaces(this); - statusBarWindowStateController.addListener(this::onStatusBarWindowStateChanged); - - mScreenOffAnimationController = screenOffAnimationController; - - mPanelExpansionStateManager.addExpansionListener(this::onPanelExpansionChanged); - - mBubbleExpandListener = - (isExpanding, key) -> mContext.getMainExecutor().execute(() -> { - mNotificationsController.requestNotificationUpdate("onBubbleExpandChanged"); - updateScrimController(); - }); - - mActivityIntentHelper = new ActivityIntentHelper(mContext); - mActivityLaunchAnimator = activityLaunchAnimator; - - // The status bar background may need updating when the ongoing call status changes. - mOngoingCallController.addCallback((animate) -> maybeUpdateBarMode()); - - // TODO(b/190746471): Find a better home for this. - DateTimeView.setReceiverHandler(timeTickHandler); - - mMessageRouter.subscribeTo(KeyboardShortcutsMessage.class, - data -> toggleKeyboardShortcuts(data.mDeviceId)); - mMessageRouter.subscribeTo(MSG_DISMISS_KEYBOARD_SHORTCUTS_MENU, - id -> dismissKeyboardShortcuts()); - mMessageRouter.subscribeTo(AnimateExpandSettingsPanelMessage.class, - data -> mCommandQueueCallbacks.animateExpandSettingsPanel(data.mSubpanel)); - mMessageRouter.subscribeTo(MSG_LAUNCH_TRANSITION_TIMEOUT, - id -> onLaunchTransitionTimeout()); - - deviceStateManager.registerCallback(mMainExecutor, - new FoldStateListener(mContext, this::onFoldedStateChanged)); - wiredChargingRippleController.registerCallbacks(); - } - - @Override - public void start() { - mScreenLifecycle.addObserver(mScreenObserver); - mWakefulnessLifecycle.addObserver(mWakefulnessObserver); - mUiModeManager = mContext.getSystemService(UiModeManager.class); - if (mBubblesOptional.isPresent()) { - mBubblesOptional.get().setExpandListener(mBubbleExpandListener); - } - - mStatusBarSignalPolicy.init(); - mKeyguardIndicationController.init(); - - mColorExtractor.addOnColorsChangedListener(mOnColorsChangedListener); - mStatusBarStateController.addCallback(mStateListener, - SysuiStatusBarStateController.RANK_STATUS_BAR); - - mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE); - mDreamManager = IDreamManager.Stub.asInterface( - ServiceManager.checkService(DreamService.DREAM_SERVICE)); - - mDisplay = mContext.getDisplay(); - mDisplayId = mDisplay.getDisplayId(); - updateDisplaySize(); - mStatusBarHideIconsForBouncerManager.setDisplayId(mDisplayId); - - // start old BaseStatusBar.start(). - mWindowManagerService = WindowManagerGlobal.getWindowManagerService(); - mDevicePolicyManager = (DevicePolicyManager) mContext.getSystemService( - Context.DEVICE_POLICY_SERVICE); - - mAccessibilityManager = (AccessibilityManager) - mContext.getSystemService(Context.ACCESSIBILITY_SERVICE); - - mKeyguardUpdateMonitor.setKeyguardBypassController(mKeyguardBypassController); - mBarService = IStatusBarService.Stub.asInterface( - ServiceManager.getService(Context.STATUS_BAR_SERVICE)); - - mKeyguardManager = (KeyguardManager) mContext.getSystemService(Context.KEYGUARD_SERVICE); - mWallpaperSupported = mWallpaperManager.isWallpaperSupported(); - - RegisterStatusBarResult result = null; - try { - result = mBarService.registerStatusBar(mCommandQueue); - } catch (RemoteException ex) { - ex.rethrowFromSystemServer(); - } - - createAndAddWindows(result); - - if (mWallpaperSupported) { - // Make sure we always have the most current wallpaper info. - IntentFilter wallpaperChangedFilter = new IntentFilter(Intent.ACTION_WALLPAPER_CHANGED); - mBroadcastDispatcher.registerReceiver(mWallpaperChangedReceiver, wallpaperChangedFilter, - null /* handler */, UserHandle.ALL); - mWallpaperChangedReceiver.onReceive(mContext, null); - } else if (DEBUG) { - Log.v(TAG, "start(): no wallpaper service "); - } - - // Set up the initial notification state. This needs to happen before CommandQueue.disable() - setUpPresenter(); - - if (containsType(result.mTransientBarTypes, ITYPE_STATUS_BAR)) { - showTransientUnchecked(); - } - mCommandQueueCallbacks.onSystemBarAttributesChanged(mDisplayId, result.mAppearance, - result.mAppearanceRegions, result.mNavbarColorManagedByIme, result.mBehavior, - result.mRequestedVisibilities, result.mPackageName); - - // StatusBarManagerService has a back up of IME token and it's restored here. - mCommandQueueCallbacks.setImeWindowStatus(mDisplayId, result.mImeToken, - result.mImeWindowVis, result.mImeBackDisposition, result.mShowImeSwitcher); - - // Set up the initial icon state - int numIcons = result.mIcons.size(); - for (int i = 0; i < numIcons; i++) { - mCommandQueue.setIcon(result.mIcons.keyAt(i), result.mIcons.valueAt(i)); - } - - if (DEBUG) { - Log.d(TAG, String.format( - "init: icons=%d disabled=0x%08x lights=0x%08x imeButton=0x%08x", - numIcons, - result.mDisabledFlags1, - result.mAppearance, - result.mImeWindowVis)); - } - - IntentFilter internalFilter = new IntentFilter(); - internalFilter.addAction(BANNER_ACTION_CANCEL); - internalFilter.addAction(BANNER_ACTION_SETUP); - mContext.registerReceiver(mBannerActionBroadcastReceiver, internalFilter, PERMISSION_SELF, - null, Context.RECEIVER_EXPORTED_UNAUDITED); - - if (mWallpaperSupported) { - IWallpaperManager wallpaperManager = IWallpaperManager.Stub.asInterface( - ServiceManager.getService(Context.WALLPAPER_SERVICE)); - try { - wallpaperManager.setInAmbientMode(false /* ambientMode */, 0L /* duration */); - } catch (RemoteException e) { - // Just pass, nothing critical. - } - } - - // end old BaseStatusBar.start(). - - // Lastly, call to the icon policy to install/update all the icons. - mIconPolicy.init(); - - mKeyguardStateController.addCallback(new KeyguardStateController.Callback() { - @Override - public void onUnlockedChanged() { - logStateToEventlog(); - } - }); - startKeyguard(); - - mKeyguardUpdateMonitor.registerCallback(mUpdateCallback); - mDozeServiceHost.initialize( - this, - mStatusBarKeyguardViewManager, - mNotificationShadeWindowViewController, - mNotificationPanelViewController, - mAmbientIndicationContainer); - updateLightRevealScrimVisibility(); - - mConfigurationController.addCallback(mConfigurationListener); - - mBatteryController.observe(mLifecycle, mBatteryStateChangeCallback); - mLifecycle.setCurrentState(RESUMED); - - mAccessibilityFloatingMenuController.init(); - - // set the initial view visibility - int disabledFlags1 = result.mDisabledFlags1; - int disabledFlags2 = result.mDisabledFlags2; - mInitController.addPostInitTask( - () -> setUpDisableFlags(disabledFlags1, disabledFlags2)); - - mFalsingManager.addFalsingBeliefListener(mFalsingBeliefListener); - - mPluginManager.addPluginListener( - new PluginListener() { - private final ArraySet mOverlays = new ArraySet<>(); - - @Override - public void onPluginConnected(OverlayPlugin plugin, Context pluginContext) { - mMainExecutor.execute( - () -> plugin.setup(getNotificationShadeWindowView(), - getNavigationBarView(), - new Callback(plugin), mDozeParameters)); - } - - @Override - public void onPluginDisconnected(OverlayPlugin plugin) { - mMainExecutor.execute(() -> { - mOverlays.remove(plugin); - mNotificationShadeWindowController - .setForcePluginOpen(mOverlays.size() != 0, this); - }); - } - - class Callback implements OverlayPlugin.Callback { - private final OverlayPlugin mPlugin; - - Callback(OverlayPlugin plugin) { - mPlugin = plugin; - } - - @Override - public void onHoldStatusBarOpenChange() { - if (mPlugin.holdStatusBarOpen()) { - mOverlays.add(mPlugin); - } else { - mOverlays.remove(mPlugin); - } - mMainExecutor.execute(() -> { - mNotificationShadeWindowController - .setStateListener(b -> mOverlays.forEach( - o -> o.setCollapseDesired(b))); - mNotificationShadeWindowController - .setForcePluginOpen(mOverlays.size() != 0, this); - }); - } - } - }, OverlayPlugin.class, true /* Allow multiple plugins */); - - mStartingSurfaceOptional.ifPresent(startingSurface -> startingSurface.setSysuiProxy( - (requestTopUi, componentTag) -> mMainExecutor.execute(() -> - mNotificationShadeWindowController.setRequestTopUi( - requestTopUi, componentTag)))); - } - - private void onFoldedStateChanged(boolean isFolded, boolean willGoToSleep) { - Trace.beginSection("CentralSurfaces#onFoldedStateChanged"); - onFoldedStateChangedInternal(isFolded, willGoToSleep); - Trace.endSection(); - } - - private void onFoldedStateChangedInternal(boolean isFolded, boolean willGoToSleep) { - // Folded state changes are followed by a screen off event. - // By default turning off the screen also closes the shade. - // We want to make sure that the shade status is kept after - // folding/unfolding. - boolean isShadeOpen = mShadeController.isShadeOpen(); - boolean leaveOpen = isShadeOpen && !willGoToSleep; - if (DEBUG) { - Log.d(TAG, String.format( - "#onFoldedStateChanged(): " - + "isFolded=%s, " - + "willGoToSleep=%s, " - + "isShadeOpen=%s, " - + "leaveOpen=%s", - isFolded, willGoToSleep, isShadeOpen, leaveOpen)); - } - if (leaveOpen) { - mStatusBarStateController.setLeaveOpenOnKeyguardHide(true); - if (mKeyguardStateController.isShowing()) { - // When device state changes on keyguard we don't want to keep the state of - // the shade and instead we open clean state of keyguard with shade closed. - // Normally some parts of QS state (like expanded/collapsed) are persisted and - // that causes incorrect UI rendering, especially when changing state with QS - // expanded. To prevent that we can close QS which resets QS and some parts of - // the shade to its default state. Read more in b/201537421 - mCloseQsBeforeScreenOff = true; - } - } - } - - // ================================================================================ - // Constructing the view - // ================================================================================ - protected void makeStatusBarView(@Nullable RegisterStatusBarResult result) { - updateDisplaySize(); // populates mDisplayMetrics - updateResources(); - updateTheme(); - - inflateStatusBarWindow(); - mNotificationShadeWindowView.setOnTouchListener(getStatusBarWindowTouchListener()); - mWallpaperController.setRootView(mNotificationShadeWindowView); - - // TODO: Deal with the ugliness that comes from having some of the status bar broken out - // into fragments, but the rest here, it leaves some awkward lifecycle and whatnot. - mNotificationLogger.setUpWithContainer(mNotifListContainer); - mNotificationIconAreaController.setupShelf(mNotificationShelfController); - mPanelExpansionStateManager.addExpansionListener(mWakeUpCoordinator); - mUserSwitcherController.init(mNotificationShadeWindowView); - - // Allow plugins to reference DarkIconDispatcher and StatusBarStateController - mPluginDependencyProvider.allowPluginDependency(DarkIconDispatcher.class); - mPluginDependencyProvider.allowPluginDependency(StatusBarStateController.class); - - // Set up CollapsedStatusBarFragment and PhoneStatusBarView - StatusBarInitializer initializer = mCentralSurfacesComponent.getStatusBarInitializer(); - initializer.setStatusBarViewUpdatedListener( - (statusBarView, statusBarViewController, statusBarTransitions) -> { - mStatusBarView = statusBarView; - mPhoneStatusBarViewController = statusBarViewController; - mStatusBarTransitions = statusBarTransitions; - mNotificationShadeWindowViewController - .setStatusBarViewController(mPhoneStatusBarViewController); - // Ensure we re-propagate panel expansion values to the panel controller and - // any listeners it may have, such as PanelBar. This will also ensure we - // re-display the notification panel if necessary (for example, if - // a heads-up notification was being displayed and should continue being - // displayed). - mNotificationPanelViewController.updatePanelExpansionAndVisibility(); - setBouncerShowingForStatusBarComponents(mBouncerShowing); - checkBarModes(); - }); - initializer.initializeStatusBar(mCentralSurfacesComponent); - - mStatusBarTouchableRegionManager.setup(this, mNotificationShadeWindowView); - mHeadsUpManager.addListener(mNotificationPanelViewController.getOnHeadsUpChangedListener()); - if (!mNotifPipelineFlags.isNewPipelineEnabled()) { - mHeadsUpManager.addListener(mVisualStabilityManager); - } - mNotificationPanelViewController.setHeadsUpManager(mHeadsUpManager); - - createNavigationBar(result); - - if (ENABLE_LOCKSCREEN_WALLPAPER && mWallpaperSupported) { - mLockscreenWallpaper = mLockscreenWallpaperLazy.get(); - } - - mNotificationPanelViewController.setKeyguardIndicationController( - mKeyguardIndicationController); - - mAmbientIndicationContainer = mNotificationShadeWindowView.findViewById( - R.id.ambient_indication_container); - - mAutoHideController.setStatusBar(new AutoHideUiElement() { - @Override - public void synchronizeState() { - checkBarModes(); - } - - @Override - public boolean shouldHideOnTouch() { - return !mRemoteInputManager.isRemoteInputActive(); - } - - @Override - public boolean isVisible() { - return isTransientShown(); - } - - @Override - public void hide() { - clearTransient(); - } - }); - - ScrimView scrimBehind = mNotificationShadeWindowView.findViewById(R.id.scrim_behind); - ScrimView notificationsScrim = mNotificationShadeWindowView - .findViewById(R.id.scrim_notifications); - ScrimView scrimInFront = mNotificationShadeWindowView.findViewById(R.id.scrim_in_front); - - mScrimController.setScrimVisibleListener(scrimsVisible -> { - mNotificationShadeWindowController.setScrimsVisibility(scrimsVisible); - }); - mScrimController.attachViews(scrimBehind, notificationsScrim, scrimInFront); - - mLightRevealScrim = mNotificationShadeWindowView.findViewById(R.id.light_reveal_scrim); - mLightRevealScrim.setScrimOpaqueChangedListener((opaque) -> { - Runnable updateOpaqueness = () -> { - mNotificationShadeWindowController.setLightRevealScrimOpaque( - mLightRevealScrim.isScrimOpaque()); - mScreenOffAnimationController - .onScrimOpaqueChanged(mLightRevealScrim.isScrimOpaque()); - }; - if (opaque) { - // Delay making the view opaque for a frame, because it needs some time to render - // otherwise this can lead to a flicker where the scrim doesn't cover the screen - mLightRevealScrim.post(updateOpaqueness); - } else { - updateOpaqueness.run(); - } - }); - - mScreenOffAnimationController.initialize(this, mLightRevealScrim); - updateLightRevealScrimVisibility(); - - mNotificationPanelViewController.initDependencies( - this, - this::makeExpandedInvisible, - mNotificationShelfController); - - BackDropView backdrop = mNotificationShadeWindowView.findViewById(R.id.backdrop); - mMediaManager.setup(backdrop, backdrop.findViewById(R.id.backdrop_front), - backdrop.findViewById(R.id.backdrop_back), mScrimController, mLockscreenWallpaper); - float maxWallpaperZoom = mContext.getResources().getFloat( - com.android.internal.R.dimen.config_wallpaperMaxScale); - mNotificationShadeDepthControllerLazy.get().addListener(depth -> { - float scale = MathUtils.lerp(maxWallpaperZoom, 1f, depth); - backdrop.setPivotX(backdrop.getWidth() / 2f); - backdrop.setPivotY(backdrop.getHeight() / 2f); - backdrop.setScaleX(scale); - backdrop.setScaleY(scale); - }); - - mNotificationPanelViewController.setUserSetupComplete(mUserSetup); - - // Set up the quick settings tile panel - final View container = mNotificationShadeWindowView.findViewById(R.id.qs_frame); - if (container != null) { - FragmentHostManager fragmentHostManager = FragmentHostManager.get(container); - ExtensionFragmentListener.attachExtensonToFragment(container, QS.TAG, R.id.qs_frame, - mExtensionController - .newExtension(QS.class) - .withPlugin(QS.class) - .withDefault(this::createDefaultQSFragment) - .build()); - mBrightnessMirrorController = new BrightnessMirrorController( - mNotificationShadeWindowView, - mNotificationPanelViewController, - mNotificationShadeDepthControllerLazy.get(), - mBrightnessSliderFactory, - (visible) -> { - mBrightnessMirrorVisible = visible; - updateScrimController(); - }); - fragmentHostManager.addTagListener(QS.TAG, (tag, f) -> { - QS qs = (QS) f; - if (qs instanceof QSFragment) { - mQSPanelController = ((QSFragment) qs).getQSPanelController(); - ((QSFragment) qs).setBrightnessMirrorController(mBrightnessMirrorController); - } - }); - } - - mReportRejectedTouch = mNotificationShadeWindowView - .findViewById(R.id.report_rejected_touch); - if (mReportRejectedTouch != null) { - updateReportRejectedTouchVisibility(); - mReportRejectedTouch.setOnClickListener(v -> { - Uri session = mFalsingManager.reportRejectedTouch(); - if (session == null) { return; } - - StringWriter message = new StringWriter(); - message.write("Build info: "); - message.write(SystemProperties.get("ro.build.description")); - message.write("\nSerial number: "); - message.write(SystemProperties.get("ro.serialno")); - message.write("\n"); - - startActivityDismissingKeyguard(Intent.createChooser(new Intent(Intent.ACTION_SEND) - .setType("*/*") - .putExtra(Intent.EXTRA_SUBJECT, "Rejected touch report") - .putExtra(Intent.EXTRA_STREAM, session) - .putExtra(Intent.EXTRA_TEXT, message.toString()), - "Share rejected touch report") - .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK), - true /* onlyProvisioned */, true /* dismissShade */); - }); - } - - if (!mPowerManager.isInteractive()) { - mBroadcastReceiver.onReceive(mContext, new Intent(Intent.ACTION_SCREEN_OFF)); - } - mGestureWakeLock = mPowerManager.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK, - "sysui:GestureWakeLock"); - - // receive broadcasts - registerBroadcastReceiver(); - - IntentFilter demoFilter = new IntentFilter(); - if (DEBUG_MEDIA_FAKE_ARTWORK) { - demoFilter.addAction(ACTION_FAKE_ARTWORK); - } - mContext.registerReceiverAsUser(mDemoReceiver, UserHandle.ALL, demoFilter, - android.Manifest.permission.DUMP, null, - Context.RECEIVER_EXPORTED_UNAUDITED); - - // listen for USER_SETUP_COMPLETE setting (per-user) - mDeviceProvisionedController.addCallback(mUserSetupObserver); - mUserSetupObserver.onUserSetupChanged(); - - // disable profiling bars, since they overlap and clutter the output on app windows - ThreadedRenderer.overrideProperty("disableProfileBars", "true"); - - // Private API call to make the shadows look better for Recents - ThreadedRenderer.overrideProperty("ambientRatio", String.valueOf(1.5f)); - } - - - /** - * When swiping up to dismiss the lock screen, the panel expansion fraction goes from 1f to 0f. - * This results in the clock/notifications/other content disappearing off the top of the screen. - * - * We also use the expansion fraction to animate in the app/launcher surface from the bottom of - * the screen, 'pushing' off the notifications and other content. To do this, we dispatch the - * expansion fraction to the KeyguardViewMediator if we're in the process of dismissing the - * keyguard. - */ - private void dispatchPanelExpansionForKeyguardDismiss(float fraction, boolean trackingTouch) { - // Things that mean we're not swiping to dismiss the keyguard, and should ignore this - // expansion: - // - Keyguard isn't even visible. - // - Keyguard is occluded. Expansion changes here are the shade being expanded over the - // occluding activity. - // - Keyguard is visible, but can't be dismissed (swiping up will show PIN/password prompt). - // - The SIM is locked, you can't swipe to unlock. If the SIM is locked but there is no - // device lock set, canDismissLockScreen returns true even though you should not be able - // to dismiss the lock screen until entering the SIM PIN. - // - QS is expanded and we're swiping - swiping up now will hide QS, not dismiss the - // keyguard. - if (!isKeyguardShowing() - || isOccluded() - || !mKeyguardStateController.canDismissLockScreen() - || mKeyguardViewMediator.isAnySimPinSecure() - || (mNotificationPanelViewController.isQsExpanded() && trackingTouch)) { - return; - } - - // Otherwise, we should let the keyguard know about this if we're tracking touch, or if we - // are already animating the keyguard dismiss (since we will need to either finish or cancel - // the animation). - if (trackingTouch - || mKeyguardViewMediator.isAnimatingBetweenKeyguardAndSurfaceBehindOrWillBe() - || mKeyguardUnlockAnimationController.isUnlockingWithSmartSpaceTransition()) { - mKeyguardStateController.notifyKeyguardDismissAmountChanged( - 1f - fraction, trackingTouch); - } - } - - private void onPanelExpansionChanged(PanelExpansionChangeEvent event) { - float fraction = event.getFraction(); - boolean tracking = event.getTracking(); - dispatchPanelExpansionForKeyguardDismiss(fraction, tracking); - - if (fraction == 0 || fraction == 1) { - if (getNavigationBarView() != null) { - getNavigationBarView().onStatusBarPanelStateChanged(); - } - if (getNotificationPanelViewController() != null) { - getNotificationPanelViewController().updateSystemUiStateFlags(); - } - } - } - - @NonNull - @Override - public Lifecycle getLifecycle() { - return mLifecycle; - } - - @VisibleForTesting - protected void registerBroadcastReceiver() { - IntentFilter filter = new IntentFilter(); - filter.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS); - filter.addAction(Intent.ACTION_SCREEN_OFF); - mBroadcastDispatcher.registerReceiver(mBroadcastReceiver, filter, null, UserHandle.ALL); - } - - protected QS createDefaultQSFragment() { - return FragmentHostManager.get(mNotificationShadeWindowView).create(QSFragment.class); - } - - private void setUpPresenter() { - // Set up the initial notification state. - mActivityLaunchAnimator.setCallback(mActivityLaunchAnimatorCallback); - mActivityLaunchAnimator.addListener(mActivityLaunchAnimatorListener); - mNotificationAnimationProvider = new NotificationLaunchAnimatorControllerProvider( - mNotificationShadeWindowViewController, - mNotifListContainer, - mHeadsUpManager, - mJankMonitor); - mNotificationShelfController.setOnActivatedListener(mPresenter); - mRemoteInputManager.addControllerCallback(mNotificationShadeWindowController); - mStackScrollerController.setNotificationActivityStarter(mNotificationActivityStarter); - mGutsManager.setNotificationActivityStarter(mNotificationActivityStarter); - mNotificationsController.initialize( - mPresenter, - mNotifListContainer, - mStackScrollerController.getNotifStackController(), - mNotificationActivityStarter, - mCentralSurfacesComponent.getBindRowCallback()); - } - - /** - * Post-init task of {@link #start()} - * @param state1 disable1 flags - * @param state2 disable2 flags - */ - protected void setUpDisableFlags(int state1, int state2) { - mCommandQueue.disable(mDisplayId, state1, state2, false /* animate */); - } - - /** - * Ask the display to wake up if currently dozing, else do nothing - * - * @param time when to wake up - * @param where the view requesting the wakeup - * @param why the reason for the wake up - */ - public void wakeUpIfDozing(long time, View where, String why) { - if (mDozing && mScreenOffAnimationController.allowWakeUpIfDozing()) { - mPowerManager.wakeUp( - time, PowerManager.WAKE_REASON_GESTURE, "com.android.systemui:" + why); - mWakeUpComingFromTouch = true; - where.getLocationInWindow(mTmpInt2); - - // NOTE, the incoming view can sometimes be the entire container... unsure if - // this location is valuable enough - mWakeUpTouchLocation = new PointF(mTmpInt2[0] + where.getWidth() / 2, - mTmpInt2[1] + where.getHeight() / 2); - mFalsingCollector.onScreenOnFromTouch(); - } - } - - // TODO(b/117478341): This was left such that CarStatusBar can override this method. - // Try to remove this. - protected void createNavigationBar(@Nullable RegisterStatusBarResult result) { - mNavigationBarController.createNavigationBars(true /* includeDefaultDisplay */, result); - } - - /** - * Returns the {@link android.view.View.OnTouchListener} that will be invoked when the - * background window of the status bar is clicked. - */ - protected View.OnTouchListener getStatusBarWindowTouchListener() { - return (v, event) -> { - mAutoHideController.checkUserAutoHide(event); - mRemoteInputManager.checkRemoteInputOutside(event); - if (event.getAction() == MotionEvent.ACTION_UP) { - if (mExpandedVisible) { - mShadeController.animateCollapsePanels(); - } - } - return mNotificationShadeWindowView.onTouchEvent(event); - }; - } - - private void inflateStatusBarWindow() { - if (mCentralSurfacesComponent != null) { - // Tear down - for (CentralSurfacesComponent.Startable s : mCentralSurfacesComponent.getStartables()) { - s.stop(); - } - } - mCentralSurfacesComponent = mCentralSurfacesComponentFactory.create(); - mFragmentService.addFragmentInstantiationProvider(mCentralSurfacesComponent); - - mNotificationShadeWindowView = mCentralSurfacesComponent.getNotificationShadeWindowView(); - mNotificationShadeWindowViewController = mCentralSurfacesComponent - .getNotificationShadeWindowViewController(); - mNotificationShadeWindowController.setNotificationShadeView(mNotificationShadeWindowView); - mNotificationShadeWindowViewController.setupExpandedStatusBar(); - mNotificationPanelViewController = - mCentralSurfacesComponent.getNotificationPanelViewController(); - mCentralSurfacesComponent.getLockIconViewController().init(); - mStackScrollerController = - mCentralSurfacesComponent.getNotificationStackScrollLayoutController(); - mStackScroller = mStackScrollerController.getView(); - mNotifListContainer = mCentralSurfacesComponent.getNotificationListContainer(); - mPresenter = mCentralSurfacesComponent.getNotificationPresenter(); - mNotificationActivityStarter = mCentralSurfacesComponent.getNotificationActivityStarter(); - mNotificationShelfController = mCentralSurfacesComponent.getNotificationShelfController(); - mAuthRippleController = mCentralSurfacesComponent.getAuthRippleController(); - mAuthRippleController.init(); - - mHeadsUpManager.addListener(mCentralSurfacesComponent.getStatusBarHeadsUpChangeListener()); - - // Listen for demo mode changes - mDemoModeController.addCallback(mDemoModeCallback); - - if (mCommandQueueCallbacks != null) { - mCommandQueue.removeCallback(mCommandQueueCallbacks); - } - mCommandQueueCallbacks = - mCentralSurfacesComponent.getCentralSurfacesCommandQueueCallbacks(); - // Connect in to the status bar manager service - mCommandQueue.addCallback(mCommandQueueCallbacks); - - // Perform all other initialization for CentralSurfacesScope - for (CentralSurfacesComponent.Startable s : mCentralSurfacesComponent.getStartables()) { - s.start(); - } - } - - protected void startKeyguard() { - Trace.beginSection("CentralSurfaces#startKeyguard"); - mBiometricUnlockController = mBiometricUnlockControllerLazy.get(); - mBiometricUnlockController.setBiometricModeListener( - new BiometricUnlockController.BiometricModeListener() { - @Override - public void onResetMode() { - setWakeAndUnlocking(false); - } - - @Override - public void onModeChanged(int mode) { - switch (mode) { - case BiometricUnlockController.MODE_WAKE_AND_UNLOCK_FROM_DREAM: - case BiometricUnlockController.MODE_WAKE_AND_UNLOCK_PULSING: - case BiometricUnlockController.MODE_WAKE_AND_UNLOCK: - setWakeAndUnlocking(true); - } - } - - @Override - public void notifyBiometricAuthModeChanged() { - CentralSurfaces.this.notifyBiometricAuthModeChanged(); - } - - private void setWakeAndUnlocking(boolean wakeAndUnlocking) { - if (getNavigationBarView() != null) { - getNavigationBarView().setWakeAndUnlocking(wakeAndUnlocking); - } - } - }); - mStatusBarKeyguardViewManager.registerCentralSurfaces( - /* statusBar= */ this, - mNotificationPanelViewController, - mPanelExpansionStateManager, - mBiometricUnlockController, - mStackScroller, - mKeyguardBypassController); - mKeyguardStateController.addCallback(mKeyguardStateControllerCallback); - mKeyguardIndicationController - .setStatusBarKeyguardViewManager(mStatusBarKeyguardViewManager); - mBiometricUnlockController.setKeyguardViewController(mStatusBarKeyguardViewManager); - mRemoteInputManager.addControllerCallback(mStatusBarKeyguardViewManager); - mDynamicPrivacyController.setStatusBarKeyguardViewManager(mStatusBarKeyguardViewManager); - - mLightBarController.setBiometricUnlockController(mBiometricUnlockController); - mMediaManager.setBiometricUnlockController(mBiometricUnlockController); - mKeyguardDismissUtil.setDismissHandler(this::executeWhenUnlocked); - Trace.endSection(); - } - - public NotificationShadeWindowView getNotificationShadeWindowView() { - return mNotificationShadeWindowView; - } - - public NotificationShadeWindowViewController getNotificationShadeWindowViewController() { - return mNotificationShadeWindowViewController; - } - - public NotificationPanelViewController getNotificationPanelViewController() { - return mNotificationPanelViewController; - } - - public ViewGroup getBouncerContainer() { - return mNotificationShadeWindowViewController.getBouncerContainer(); - } - - public int getStatusBarHeight() { - return mStatusBarWindowController.getStatusBarHeight(); - } - - /** - * Disable QS if device not provisioned. - * If the user switcher is simple then disable QS during setup because - * the user intends to use the lock screen user switcher, QS in not needed. - */ - void updateQsExpansionEnabled() { - final boolean expandEnabled = mDeviceProvisionedController.isDeviceProvisioned() - && (mUserSetup || mUserSwitcherController == null - || !mUserSwitcherController.isSimpleUserSwitcher()) - && !isShadeDisabled() - && ((mDisabled2 & StatusBarManager.DISABLE2_QUICK_SETTINGS) == 0) - && !mDozing; - mNotificationPanelViewController.setQsExpansionEnabledPolicy(expandEnabled); - Log.d(TAG, "updateQsExpansionEnabled - QS Expand enabled: " + expandEnabled); - } - - public boolean isShadeDisabled() { - return (mDisabled2 & StatusBarManager.DISABLE2_NOTIFICATION_SHADE) != 0; - } - - /** - * Request a notification update - * @param reason why we're requesting a notification update - */ - public void requestNotificationUpdate(String reason) { - mNotificationsController.requestNotificationUpdate(reason); - } - - /** - * Asks {@link KeyguardUpdateMonitor} to run face auth. - */ - public void requestFaceAuth(boolean userInitiatedRequest) { - if (!mKeyguardStateController.canDismissLockScreen()) { - mKeyguardUpdateMonitor.requestFaceAuth(userInitiatedRequest); - } - } - - private void updateReportRejectedTouchVisibility() { - if (mReportRejectedTouch == null) { - return; - } - mReportRejectedTouch.setVisibility(mState == StatusBarState.KEYGUARD && !mDozing - && mFalsingCollector.isReportingEnabled() ? View.VISIBLE : View.INVISIBLE); - } - - boolean areNotificationAlertsDisabled() { - return (mDisabled1 & StatusBarManager.DISABLE_NOTIFICATION_ALERTS) != 0; - } - - @Override - public void startActivity(Intent intent, boolean onlyProvisioned, boolean dismissShade, - int flags) { - startActivityDismissingKeyguard(intent, onlyProvisioned, dismissShade, flags); - } - - @Override - public void startActivity(Intent intent, boolean dismissShade) { - startActivityDismissingKeyguard(intent, false /* onlyProvisioned */, dismissShade); - } - - @Override - public void startActivity(Intent intent, boolean dismissShade, - @Nullable ActivityLaunchAnimator.Controller animationController, - boolean showOverLockscreenWhenLocked) { - startActivity(intent, dismissShade, animationController, showOverLockscreenWhenLocked, - getActivityUserHandle(intent)); - } - - @Override - public void startActivity(Intent intent, boolean dismissShade, - @Nullable ActivityLaunchAnimator.Controller animationController, - boolean showOverLockscreenWhenLocked, UserHandle userHandle) { - // Make sure that we dismiss the keyguard if it is directly dismissable or when we don't - // want to show the activity above it. - if (mKeyguardStateController.isUnlocked() || !showOverLockscreenWhenLocked) { - startActivityDismissingKeyguard(intent, false, dismissShade, - false /* disallowEnterPictureInPictureWhileLaunching */, null /* callback */, - 0 /* flags */, animationController, userHandle); - return; - } - - boolean animate = - animationController != null && shouldAnimateLaunch(true /* isActivityIntent */, - showOverLockscreenWhenLocked); - - ActivityLaunchAnimator.Controller controller = null; - if (animate) { - // Wrap the animation controller to dismiss the shade and set - // mIsLaunchingActivityOverLockscreen during the animation. - ActivityLaunchAnimator.Controller delegate = wrapAnimationController( - animationController, dismissShade); - controller = new DelegateLaunchAnimatorController(delegate) { - @Override - public void onIntentStarted(boolean willAnimate) { - getDelegate().onIntentStarted(willAnimate); - - if (willAnimate) { - CentralSurfaces.this.mIsLaunchingActivityOverLockscreen = true; - } - } - - @Override - public void onLaunchAnimationEnd(boolean isExpandingFullyAbove) { - // Set mIsLaunchingActivityOverLockscreen to false before actually finishing the - // animation so that we can assume that mIsLaunchingActivityOverLockscreen - // being true means that we will collapse the shade (or at least run the - // post collapse runnables) later on. - CentralSurfaces.this.mIsLaunchingActivityOverLockscreen = false; - getDelegate().onLaunchAnimationEnd(isExpandingFullyAbove); - } - - @Override - public void onLaunchAnimationCancelled() { - // Set mIsLaunchingActivityOverLockscreen to false before actually finishing the - // animation so that we can assume that mIsLaunchingActivityOverLockscreen - // being true means that we will collapse the shade (or at least run the - // post collapse runnables) later on. - CentralSurfaces.this.mIsLaunchingActivityOverLockscreen = false; - getDelegate().onLaunchAnimationCancelled(); - } - }; - } else if (dismissShade) { - // The animation will take care of dismissing the shade at the end of the animation. If - // we don't animate, collapse it directly. - collapseShade(); - } - - mActivityLaunchAnimator.startIntentWithAnimation(controller, animate, - intent.getPackage(), showOverLockscreenWhenLocked, (adapter) -> TaskStackBuilder - .create(mContext) - .addNextIntent(intent) - .startActivities(getActivityOptions(getDisplayId(), adapter), - userHandle)); - } - - /** - * Whether we are currently animating an activity launch above the lockscreen (occluding - * activity). - */ - public boolean isLaunchingActivityOverLockscreen() { - return mIsLaunchingActivityOverLockscreen; - } - - @Override - public void startActivity(Intent intent, boolean onlyProvisioned, boolean dismissShade) { - startActivityDismissingKeyguard(intent, onlyProvisioned, dismissShade); - } - - @Override - public void startActivity(Intent intent, boolean dismissShade, Callback callback) { - startActivityDismissingKeyguard(intent, false, dismissShade, - false /* disallowEnterPictureInPictureWhileLaunching */, callback, 0, - null /* animationController */, getActivityUserHandle(intent)); - } - - public void setQsExpanded(boolean expanded) { - mNotificationShadeWindowController.setQsExpanded(expanded); - mNotificationPanelViewController.setStatusAccessibilityImportance(expanded - ? View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS - : View.IMPORTANT_FOR_ACCESSIBILITY_AUTO); - mNotificationPanelViewController.updateSystemUiStateFlags(); - if (getNavigationBarView() != null) { - getNavigationBarView().onStatusBarPanelStateChanged(); - } - } - - public boolean isWakeUpComingFromTouch() { - return mWakeUpComingFromTouch; - } - - public boolean isFalsingThresholdNeeded() { - return true; - } - - /** - * To be called when there's a state change in StatusBarKeyguardViewManager. - */ - public void onKeyguardViewManagerStatesUpdated() { - logStateToEventlog(); - } - - public void setPanelExpanded(boolean isExpanded) { - if (mPanelExpanded != isExpanded) { - mNotificationLogger.onPanelExpandedChanged(isExpanded); - } - mPanelExpanded = isExpanded; - mStatusBarHideIconsForBouncerManager.setPanelExpandedAndTriggerUpdate(isExpanded); - mNotificationShadeWindowController.setPanelExpanded(isExpanded); - mStatusBarStateController.setPanelExpanded(isExpanded); - if (isExpanded && mStatusBarStateController.getState() != StatusBarState.KEYGUARD) { - if (DEBUG) { - Log.v(TAG, "clearing notification effects from Height"); - } - clearNotificationEffects(); - } - - if (!isExpanded) { - mRemoteInputManager.onPanelCollapsed(); - } - } - - public ViewGroup getNotificationScrollLayout() { - return mStackScroller; - } - - public boolean isPulsing() { - return mDozeServiceHost.isPulsing(); - } - - @Nullable - public View getAmbientIndicationContainer() { - return mAmbientIndicationContainer; - } - - /** - * When the keyguard is showing and covered by a "showWhenLocked" activity it - * is occluded. This is controlled by {@link com.android.server.policy.PhoneWindowManager} - * - * @return whether the keyguard is currently occluded - */ - public boolean isOccluded() { - return mKeyguardStateController.isOccluded(); - } - - /** A launch animation was cancelled. */ - //TODO: These can / should probably be moved to NotificationPresenter or ShadeController - public void onLaunchAnimationCancelled(boolean isLaunchForActivity) { - if (mPresenter.isPresenterFullyCollapsed() && !mPresenter.isCollapsing() - && isLaunchForActivity) { - onClosingFinished(); - } else { - mShadeController.collapsePanel(true /* animate */); - } - } - - /** A launch animation ended. */ - public void onLaunchAnimationEnd(boolean launchIsFullScreen) { - if (!mPresenter.isCollapsing()) { - onClosingFinished(); - } - if (launchIsFullScreen) { - instantCollapseNotificationPanel(); - } - } - - /** - * Whether we should animate an activity launch. - * - * Note: This method must be called *before* dismissing the keyguard. - */ - public boolean shouldAnimateLaunch(boolean isActivityIntent, boolean showOverLockscreen) { - // TODO(b/184121838): Support launch animations when occluded. - if (isOccluded()) { - return false; - } - - // Always animate if we are not showing the keyguard or if we animate over the lockscreen - // (without unlocking it). - if (showOverLockscreen || !mKeyguardStateController.isShowing()) { - return true; - } - - // If we are locked and have to dismiss the keyguard, only animate if remote unlock - // animations are enabled. We also don't animate non-activity launches as they can break the - // animation. - // TODO(b/184121838): Support non activity launches on the lockscreen. - return isActivityIntent && KeyguardService.sEnableRemoteKeyguardGoingAwayAnimation; - } - - /** Whether we should animate an activity launch. */ - public boolean shouldAnimateLaunch(boolean isActivityIntent) { - return shouldAnimateLaunch(isActivityIntent, false /* showOverLockscreen */); - } - - public boolean isDeviceInVrMode() { - return mPresenter.isDeviceInVrMode(); - } - - public NotificationPresenter getPresenter() { - return mPresenter; - } - - @VisibleForTesting - void setBarStateForTest(int state) { - mState = state; - } - - static class KeyboardShortcutsMessage { - final int mDeviceId; - - KeyboardShortcutsMessage(int deviceId) { - mDeviceId = deviceId; - } - } - - static class AnimateExpandSettingsPanelMessage { - final String mSubpanel; - - AnimateExpandSettingsPanelMessage(String subpanel) { - mSubpanel = subpanel; - } - } - - private void maybeEscalateHeadsUp() { - mHeadsUpManager.getAllEntries().forEach(entry -> { - final StatusBarNotification sbn = entry.getSbn(); - final Notification notification = sbn.getNotification(); - if (notification.fullScreenIntent != null) { - if (DEBUG) { - Log.d(TAG, "converting a heads up to fullScreen"); - } - try { - EventLog.writeEvent(EventLogTags.SYSUI_HEADS_UP_ESCALATION, - sbn.getKey()); - wakeUpForFullScreenIntent(); - notification.fullScreenIntent.send(); - entry.notifyFullScreenIntentLaunched(); - } catch (PendingIntent.CanceledException e) { - } - } - }); - mHeadsUpManager.releaseAllImmediately(); - } - - void wakeUpForFullScreenIntent() { - if (isGoingToSleep() || mDozing) { - mPowerManager.wakeUp( - SystemClock.uptimeMillis(), - PowerManager.WAKE_REASON_APPLICATION, - "com.android.systemui:full_screen_intent"); - mWakeUpComingFromTouch = false; - mWakeUpTouchLocation = null; - } - } - - void makeExpandedVisible(boolean force) { - if (SPEW) Log.d(TAG, "Make expanded visible: expanded visible=" + mExpandedVisible); - if (!force && (mExpandedVisible || !mCommandQueue.panelsEnabled())) { - return; - } - - mExpandedVisible = true; - - // Expand the window to encompass the full screen in anticipation of the drag. - // This is only possible to do atomically because the status bar is at the top of the screen! - mNotificationShadeWindowController.setPanelVisible(true); - - visibilityChanged(true); - mCommandQueue.recomputeDisableFlags(mDisplayId, !force /* animate */); - setInteracting(StatusBarManager.WINDOW_STATUS_BAR, true); - } - - public void postAnimateCollapsePanels() { - mMainExecutor.execute(mShadeController::animateCollapsePanels); - } - - public void postAnimateForceCollapsePanels() { - mMainExecutor.execute( - () -> mShadeController.animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_NONE, - true /* force */)); - } - - public void postAnimateOpenPanels() { - mMessageRouter.sendMessage(MSG_OPEN_SETTINGS_PANEL); - } - - public boolean isExpandedVisible() { - return mExpandedVisible; - } - - public boolean isPanelExpanded() { - return mPanelExpanded; - } - - /** - * Called when another window is about to transfer it's input focus. - */ - public void onInputFocusTransfer(boolean start, boolean cancel, float velocity) { - if (!mCommandQueue.panelsEnabled()) { - return; - } - - if (start) { - mNotificationPanelViewController.startWaitingForOpenPanelGesture(); - } else { - mNotificationPanelViewController.stopWaitingForOpenPanelGesture(cancel, velocity); - } - } - - public void animateCollapseQuickSettings() { - if (mState == StatusBarState.SHADE) { - mNotificationPanelViewController.collapsePanel( - true, false /* delayed */, 1.0f /* speedUpFactor */); - } - } - - void makeExpandedInvisible() { - if (SPEW) Log.d(TAG, "makeExpandedInvisible: mExpandedVisible=" + mExpandedVisible - + " mExpandedVisible=" + mExpandedVisible); - - if (!mExpandedVisible || mNotificationShadeWindowView == null) { - return; - } - - // Ensure the panel is fully collapsed (just in case; bug 6765842, 7260868) - mNotificationPanelViewController.collapsePanel(/*animate=*/ false, false /* delayed*/, - 1.0f /* speedUpFactor */); - - mNotificationPanelViewController.closeQs(); - - mExpandedVisible = false; - visibilityChanged(false); - - // Update the visibility of notification shade and status bar window. - mNotificationShadeWindowController.setPanelVisible(false); - mStatusBarWindowController.setForceStatusBarVisible(false); - - // Close any guts that might be visible - mGutsManager.closeAndSaveGuts(true /* removeLeavebehind */, true /* force */, - true /* removeControls */, -1 /* x */, -1 /* y */, true /* resetMenu */); - - mShadeController.runPostCollapseRunnables(); - setInteracting(StatusBarManager.WINDOW_STATUS_BAR, false); - if (!mNotificationActivityStarter.isCollapsingToShowActivityOverLockscreen()) { - showBouncerOrLockScreenIfKeyguard(); - } else if (DEBUG) { - Log.d(TAG, "Not showing bouncer due to activity showing over lockscreen"); - } - mCommandQueue.recomputeDisableFlags( - mDisplayId, - mNotificationPanelViewController.hideStatusBarIconsWhenExpanded() /* animate */); - - // Trimming will happen later if Keyguard is showing - doing it here might cause a jank in - // the bouncer appear animation. - if (!mStatusBarKeyguardViewManager.isShowing()) { - WindowManagerGlobal.getInstance().trimMemory(ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN); - } - } - - /** Called when a touch event occurred on {@link PhoneStatusBarView}. */ - public void onTouchEvent(MotionEvent event) { - // TODO(b/202981994): Move this touch debugging to a central location. (Right now, it's - // split between NotificationPanelViewController and here.) - if (DEBUG_GESTURES) { - if (event.getActionMasked() != MotionEvent.ACTION_MOVE) { - EventLog.writeEvent(EventLogTags.SYSUI_STATUSBAR_TOUCH, - event.getActionMasked(), (int) event.getX(), (int) event.getY(), - mDisabled1, mDisabled2); - } - - } - - if (SPEW) { - Log.d(TAG, "Touch: rawY=" + event.getRawY() + " event=" + event + " mDisabled1=" - + mDisabled1 + " mDisabled2=" + mDisabled2); - } else if (CHATTY) { - if (event.getAction() != MotionEvent.ACTION_MOVE) { - Log.d(TAG, String.format( - "panel: %s at (%f, %f) mDisabled1=0x%08x mDisabled2=0x%08x", - MotionEvent.actionToString(event.getAction()), - event.getRawX(), event.getRawY(), mDisabled1, mDisabled2)); - } - } - - if (DEBUG_GESTURES) { - mGestureRec.add(event); - } - - if (mStatusBarWindowState == WINDOW_STATE_SHOWING) { - final boolean upOrCancel = - event.getAction() == MotionEvent.ACTION_UP || - event.getAction() == MotionEvent.ACTION_CANCEL; - setInteracting(StatusBarManager.WINDOW_STATUS_BAR, !upOrCancel || mExpandedVisible); - } - } - - public GestureRecorder getGestureRecorder() { - return mGestureRec; - } - - public BiometricUnlockController getBiometricUnlockController() { - return mBiometricUnlockController; - } - - void showTransientUnchecked() { - if (!mTransientShown) { - mTransientShown = true; - mNoAnimationOnNextBarModeChange = true; - maybeUpdateBarMode(); - } - } - - - void clearTransient() { - if (mTransientShown) { - mTransientShown = false; - maybeUpdateBarMode(); - } - } - - private void maybeUpdateBarMode() { - final int barMode = barMode(mTransientShown, mAppearance); - if (updateBarMode(barMode)) { - mLightBarController.onStatusBarModeChanged(barMode); - updateBubblesVisibility(); - } - } - - private boolean updateBarMode(int barMode) { - if (mStatusBarMode != barMode) { - mStatusBarMode = barMode; - checkBarModes(); - mAutoHideController.touchAutoHide(); - return true; - } - return false; - } - - private @TransitionMode int barMode(boolean isTransient, int appearance) { - final int lightsOutOpaque = APPEARANCE_LOW_PROFILE_BARS | APPEARANCE_OPAQUE_STATUS_BARS; - if (mOngoingCallController.hasOngoingCall() && mIsFullscreen) { - return MODE_SEMI_TRANSPARENT; - } else 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_STATUS_BARS) != 0) { - return MODE_OPAQUE; - } else if ((appearance & APPEARANCE_SEMI_TRANSPARENT_STATUS_BARS) != 0) { - return MODE_SEMI_TRANSPARENT; - } else { - return MODE_TRANSPARENT; - } - } - - protected void showWirelessChargingAnimation(int batteryLevel) { - showChargingAnimation(batteryLevel, UNKNOWN_BATTERY_LEVEL, 0); - } - - protected void showChargingAnimation(int batteryLevel, int transmittingBatteryLevel, - long animationDelay) { - WirelessChargingAnimation.makeWirelessChargingAnimation(mContext, null, - transmittingBatteryLevel, batteryLevel, - new WirelessChargingAnimation.Callback() { - @Override - public void onAnimationStarting() { - mNotificationShadeWindowController.setRequestTopUi(true, TAG); - } - - @Override - public void onAnimationEnded() { - mNotificationShadeWindowController.setRequestTopUi(false, TAG); - } - }, false, sUiEventLogger).show(animationDelay); - } - - public void checkBarModes() { - if (mDemoModeController.isInDemoMode()) return; - if (mStatusBarTransitions != null) { - checkBarMode(mStatusBarMode, mStatusBarWindowState, mStatusBarTransitions); - } - mNavigationBarController.checkNavBarModes(mDisplayId); - mNoAnimationOnNextBarModeChange = false; - } - - // Called by NavigationBarFragment - public void setQsScrimEnabled(boolean scrimEnabled) { - mNotificationPanelViewController.setQsScrimEnabled(scrimEnabled); - } - - /** Temporarily hides Bubbles if the status bar is hidden. */ - void updateBubblesVisibility() { - mBubblesOptional.ifPresent(bubbles -> bubbles.onStatusBarVisibilityChanged( - mStatusBarMode != MODE_LIGHTS_OUT - && mStatusBarMode != MODE_LIGHTS_OUT_TRANSPARENT - && !mStatusBarWindowHidden)); - } - - void checkBarMode(@TransitionMode int mode, @WindowVisibleState int windowState, - BarTransitions transitions) { - final boolean anim = !mNoAnimationOnNextBarModeChange && mDeviceInteractive - && windowState != WINDOW_STATE_HIDDEN; - transitions.transitionTo(mode, anim); - } - - private void finishBarAnimations() { - if (mStatusBarTransitions != null) { - mStatusBarTransitions.finishAnimations(); - } - mNavigationBarController.finishBarAnimations(mDisplayId); - } - - private final Runnable mCheckBarModes = this::checkBarModes; - - public void setInteracting(int barWindow, boolean interacting) { - mInteractingWindows = interacting - ? (mInteractingWindows | barWindow) - : (mInteractingWindows & ~barWindow); - if (mInteractingWindows != 0) { - mAutoHideController.suspendAutoHide(); - } else { - mAutoHideController.resumeSuspendedAutoHide(); - } - checkBarModes(); - } - - private void dismissVolumeDialog() { - if (mVolumeComponent != null) { - mVolumeComponent.dismissNow(); - } - } - - public static String viewInfo(View v) { + static String viewInfo(View v) { return "[(" + v.getLeft() + "," + v.getTop() + ")(" + v.getRight() + "," + v.getBottom() + ") " + v.getWidth() + "x" + v.getHeight() + "]"; } - @Override - public void dump(PrintWriter pwOriginal, String[] args) { - IndentingPrintWriter pw = DumpUtilsKt.asIndenting(pwOriginal); - synchronized (mQueueLock) { - pw.println("Current Status Bar state:"); - pw.println(" mExpandedVisible=" + mExpandedVisible); - pw.println(" mDisplayMetrics=" + mDisplayMetrics); - pw.println(" mStackScroller: " + viewInfo(mStackScroller)); - pw.println(" mStackScroller: " + viewInfo(mStackScroller) - + " scroll " + mStackScroller.getScrollX() - + "," + mStackScroller.getScrollY()); - } - - pw.print(" mInteractingWindows="); pw.println(mInteractingWindows); - pw.print(" mStatusBarWindowState="); - pw.println(windowStateToString(mStatusBarWindowState)); - pw.print(" mStatusBarMode="); - pw.println(BarTransitions.modeToString(mStatusBarMode)); - pw.print(" mDozing="); pw.println(mDozing); - pw.print(" mWallpaperSupported= "); pw.println(mWallpaperSupported); - - pw.println(" ShadeWindowView: "); - if (mNotificationShadeWindowViewController != null) { - mNotificationShadeWindowViewController.dump(pw, args); - dumpBarTransitions(pw, "PhoneStatusBarTransitions", mStatusBarTransitions); - } - - pw.println(" mMediaManager: "); - if (mMediaManager != null) { - mMediaManager.dump(pw, args); - } - - pw.println(" Panels: "); - if (mNotificationPanelViewController != null) { - pw.println(" mNotificationPanel=" - + mNotificationPanelViewController.getView() + " params=" - + mNotificationPanelViewController.getView().getLayoutParams().debug("")); - pw.print (" "); - mNotificationPanelViewController.dump(pw, args); - } - pw.println(" mStackScroller: "); - if (mStackScroller != null) { - // Double indent until we rewrite the rest of this dump() - pw.increaseIndent(); - pw.increaseIndent(); - mStackScroller.dump(pw, args); - pw.decreaseIndent(); - pw.decreaseIndent(); - } - pw.println(" Theme:"); - String nightMode = mUiModeManager == null ? "null" : mUiModeManager.getNightMode() + ""; - pw.println(" dark theme: " + nightMode + - " (auto: " + UiModeManager.MODE_NIGHT_AUTO + - ", yes: " + UiModeManager.MODE_NIGHT_YES + - ", no: " + UiModeManager.MODE_NIGHT_NO + ")"); - final boolean lightWpTheme = mContext.getThemeResId() - == R.style.Theme_SystemUI_LightWallpaper; - pw.println(" light wallpaper theme: " + lightWpTheme); - - if (mKeyguardIndicationController != null) { - mKeyguardIndicationController.dump(pw, args); - } - - if (mScrimController != null) { - mScrimController.dump(pw, args); - } - - if (mLightRevealScrim != null) { - pw.println( - "mLightRevealScrim.getRevealEffect(): " + mLightRevealScrim.getRevealEffect()); - pw.println( - "mLightRevealScrim.getRevealAmount(): " + mLightRevealScrim.getRevealAmount()); - } - - if (mStatusBarKeyguardViewManager != null) { - mStatusBarKeyguardViewManager.dump(pw); - } - - mNotificationsController.dump(pw, args, DUMPTRUCK); - - if (DEBUG_GESTURES) { - pw.print(" status bar gestures: "); - mGestureRec.dump(pw, args); - } - - if (mHeadsUpManager != null) { - mHeadsUpManager.dump(pw, args); - } else { - pw.println(" mHeadsUpManager: null"); - } - - if (mStatusBarTouchableRegionManager != null) { - mStatusBarTouchableRegionManager.dump(pw, args); - } else { - pw.println(" mStatusBarTouchableRegionManager: null"); - } - - if (mLightBarController != null) { - mLightBarController.dump(pw, args); - } - - pw.println("SharedPreferences:"); - for (Map.Entry entry : Prefs.getAll(mContext).entrySet()) { - pw.print(" "); pw.print(entry.getKey()); pw.print("="); pw.println(entry.getValue()); - } - - pw.println("Camera gesture intents:"); - pw.println(" Insecure camera: " + CameraIntents.getInsecureCameraIntent(mContext)); - pw.println(" Secure camera: " + CameraIntents.getSecureCameraIntent(mContext)); - pw.println(" Override package: " - + CameraIntents.getOverrideCameraPackage(mContext)); - } - - public static void dumpBarTransitions( + static void dumpBarTransitions( PrintWriter pw, String var, @Nullable BarTransitions transitions) { - pw.print(" "); pw.print(var); pw.print(".BarTransitions.mMode="); + pw.print(" "); + pw.print(var); + pw.print(".BarTransitions.mMode="); if (transitions != null) { pw.println(BarTransitions.modeToString(transitions.getMode())); } else { @@ -2369,1691 +106,15 @@ public class CentralSurfaces extends CoreStartable implements } } - public void createAndAddWindows(@Nullable RegisterStatusBarResult result) { - makeStatusBarView(result); - mNotificationShadeWindowController.attach(); - mStatusBarWindowController.attach(); - } - - // called by makeStatusbar and also by PhoneStatusBarView - void updateDisplaySize() { - mDisplay.getMetrics(mDisplayMetrics); - mDisplay.getSize(mCurrentDisplaySize); - if (DEBUG_GESTURES) { - mGestureRec.tag("display", - String.format("%dx%d", mDisplayMetrics.widthPixels, mDisplayMetrics.heightPixels)); - } - } - - float getDisplayDensity() { - return mDisplayMetrics.density; - } - - public float getDisplayWidth() { - return mDisplayMetrics.widthPixels; - } - - public float getDisplayHeight() { - return mDisplayMetrics.heightPixels; - } - - int getRotation() { - return mDisplay.getRotation(); - } - - int getDisplayId() { - return mDisplayId; - } - - public void startActivityDismissingKeyguard(final Intent intent, boolean onlyProvisioned, - boolean dismissShade, int flags) { - startActivityDismissingKeyguard(intent, onlyProvisioned, dismissShade, - false /* disallowEnterPictureInPictureWhileLaunching */, null /* callback */, - flags, null /* animationController */, getActivityUserHandle(intent)); - } - - public void startActivityDismissingKeyguard(final Intent intent, boolean onlyProvisioned, - boolean dismissShade) { - startActivityDismissingKeyguard(intent, onlyProvisioned, dismissShade, 0); - } - - void startActivityDismissingKeyguard(final Intent intent, boolean onlyProvisioned, - final boolean dismissShade, final boolean disallowEnterPictureInPictureWhileLaunching, - final Callback callback, int flags, - @Nullable ActivityLaunchAnimator.Controller animationController, - final UserHandle userHandle) { - if (onlyProvisioned && !mDeviceProvisionedController.isDeviceProvisioned()) return; - - final boolean willLaunchResolverActivity = - mActivityIntentHelper.wouldLaunchResolverActivity(intent, - mLockscreenUserManager.getCurrentUserId()); - - boolean animate = - animationController != null && !willLaunchResolverActivity && shouldAnimateLaunch( - true /* isActivityIntent */); - ActivityLaunchAnimator.Controller animController = - animationController != null ? wrapAnimationController(animationController, - dismissShade) : null; - - // If we animate, we will dismiss the shade only once the animation is done. This is taken - // care of by the StatusBarLaunchAnimationController. - boolean dismissShadeDirectly = dismissShade && animController == null; - - Runnable runnable = () -> { - mAssistManagerLazy.get().hideAssist(); - intent.setFlags( - Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP); - intent.addFlags(flags); - int[] result = new int[]{ActivityManager.START_CANCELED}; - - mActivityLaunchAnimator.startIntentWithAnimation(animController, - animate, intent.getPackage(), (adapter) -> { - ActivityOptions options = new ActivityOptions( - getActivityOptions(mDisplayId, adapter)); - options.setDisallowEnterPictureInPictureWhileLaunching( - disallowEnterPictureInPictureWhileLaunching); - if (CameraIntents.isInsecureCameraIntent(intent)) { - // Normally an activity will set it's requested rotation - // animation on its window. However when launching an activity - // causes the orientation to change this is too late. In these cases - // the default animation is used. This doesn't look good for - // the camera (as it rotates the camera contents out of sync - // with physical reality). So, we ask the WindowManager to - // force the crossfade animation if an orientation change - // happens to occur during the launch. - options.setRotationAnimationHint( - WindowManager.LayoutParams.ROTATION_ANIMATION_SEAMLESS); - } - if (Settings.Panel.ACTION_VOLUME.equals(intent.getAction())) { - // Settings Panel is implemented as activity(not a dialog), so - // underlying app is paused and may enter picture-in-picture mode - // as a result. - // So we need to disable picture-in-picture mode here - // if it is volume panel. - options.setDisallowEnterPictureInPictureWhileLaunching(true); - } - - try { - result[0] = ActivityTaskManager.getService().startActivityAsUser( - null, mContext.getBasePackageName(), - mContext.getAttributionTag(), - intent, - intent.resolveTypeIfNeeded(mContext.getContentResolver()), - null, null, 0, Intent.FLAG_ACTIVITY_NEW_TASK, null, - options.toBundle(), userHandle.getIdentifier()); - } catch (RemoteException e) { - Log.w(TAG, "Unable to start activity", e); - } - return result[0]; - }); - - if (callback != null) { - callback.onActivityStarted(result[0]); - } - }; - Runnable cancelRunnable = () -> { - if (callback != null) { - callback.onActivityStarted(ActivityManager.START_CANCELED); - } - }; - executeRunnableDismissingKeyguard(runnable, cancelRunnable, dismissShadeDirectly, - willLaunchResolverActivity, true /* deferred */, animate); - } - - @Nullable - private ActivityLaunchAnimator.Controller wrapAnimationController( - ActivityLaunchAnimator.Controller animationController, boolean dismissShade) { - View rootView = animationController.getLaunchContainer().getRootView(); - - Optional controllerFromStatusBar = - mStatusBarWindowController.wrapAnimationControllerIfInStatusBar( - rootView, animationController); - if (controllerFromStatusBar.isPresent()) { - return controllerFromStatusBar.get(); - } - - if (dismissShade) { - // If the view is not in the status bar, then we are animating a view in the shade. - // We have to make sure that we collapse it when the animation ends or is cancelled. - return new StatusBarLaunchAnimatorController(animationController, this, - true /* isLaunchForActivity */); - } - - return animationController; - } - - public void readyForKeyguardDone() { - mStatusBarKeyguardViewManager.readyForKeyguardDone(); - } - - public void executeRunnableDismissingKeyguard(final Runnable runnable, - final Runnable cancelAction, - final boolean dismissShade, - final boolean afterKeyguardGone, - final boolean deferred) { - executeRunnableDismissingKeyguard(runnable, cancelAction, dismissShade, afterKeyguardGone, - deferred, false /* willAnimateOnKeyguard */); - } - - public void executeRunnableDismissingKeyguard(final Runnable runnable, - final Runnable cancelAction, - final boolean dismissShade, - final boolean afterKeyguardGone, - final boolean deferred, - final boolean willAnimateOnKeyguard) { - OnDismissAction onDismissAction = new OnDismissAction() { - @Override - public boolean onDismiss() { - if (runnable != null) { - if (mStatusBarKeyguardViewManager.isShowing() - && mStatusBarKeyguardViewManager.isOccluded()) { - mStatusBarKeyguardViewManager.addAfterKeyguardGoneRunnable(runnable); - } else { - mMainExecutor.execute(runnable); - } - } - if (dismissShade) { - if (mExpandedVisible && !mBouncerShowing) { - mShadeController.animateCollapsePanels( - CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL, - true /* force */, true /* delayed*/); - } else { - - // Do it after DismissAction has been processed to conserve the needed - // ordering. - mMainExecutor.execute(mShadeController::runPostCollapseRunnables); - } - } else if (CentralSurfaces.this.isInLaunchTransition() - && mNotificationPanelViewController.isLaunchTransitionFinished()) { - - // We are not dismissing the shade, but the launch transition is already - // finished, - // so nobody will call readyForKeyguardDone anymore. Post it such that - // keyguardDonePending gets called first. - mMainExecutor.execute(mStatusBarKeyguardViewManager::readyForKeyguardDone); - } - return deferred; - } - - @Override - public boolean willRunAnimationOnKeyguard() { - return willAnimateOnKeyguard; - } - }; - dismissKeyguardThenExecute(onDismissAction, cancelAction, afterKeyguardGone); - } - - private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - Trace.beginSection("CentralSurfaces#onReceive"); - if (DEBUG) Log.v(TAG, "onReceive: " + intent); - String action = intent.getAction(); - String reason = intent.getStringExtra(SYSTEM_DIALOG_REASON_KEY); - if (Intent.ACTION_CLOSE_SYSTEM_DIALOGS.equals(action)) { - KeyboardShortcuts.dismiss(); - mRemoteInputManager.closeRemoteInputs(); - if (mLockscreenUserManager.isCurrentProfile(getSendingUserId())) { - int flags = CommandQueue.FLAG_EXCLUDE_NONE; - if (reason != null) { - if (reason.equals(SYSTEM_DIALOG_REASON_RECENT_APPS)) { - flags |= CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL; - } - // Do not collapse notifications when starting dreaming if the notifications - // shade is used for the screen off animation. It might require expanded - // state for the scrims to be visible - if (reason.equals(SYSTEM_DIALOG_REASON_DREAM) - && mScreenOffAnimationController.shouldExpandNotifications()) { - flags |= CommandQueue.FLAG_EXCLUDE_NOTIFICATION_PANEL; - } - } - mShadeController.animateCollapsePanels(flags); - } - } else if (Intent.ACTION_SCREEN_OFF.equals(action)) { - if (mNotificationShadeWindowController != null) { - mNotificationShadeWindowController.setNotTouchable(false); - } - finishBarAnimations(); - resetUserExpandedStates(); - } - Trace.endSection(); - } - }; - - private final BroadcastReceiver mDemoReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - if (DEBUG) Log.v(TAG, "onReceive: " + intent); - String action = intent.getAction(); - if (ACTION_FAKE_ARTWORK.equals(action)) { - if (DEBUG_MEDIA_FAKE_ARTWORK) { - mPresenter.updateMediaMetaData(true, true); - } - } - } - }; - - public void resetUserExpandedStates() { - mNotificationsController.resetUserExpandedStates(); - } - - private void executeWhenUnlocked(OnDismissAction action, boolean requiresShadeOpen, - boolean afterKeyguardGone) { - if (mStatusBarKeyguardViewManager.isShowing() && requiresShadeOpen) { - mStatusBarStateController.setLeaveOpenOnKeyguardHide(true); - } - dismissKeyguardThenExecute(action, null /* cancelAction */, - afterKeyguardGone /* afterKeyguardGone */); - } - - protected void dismissKeyguardThenExecute(OnDismissAction action, boolean afterKeyguardGone) { - dismissKeyguardThenExecute(action, null /* cancelRunnable */, afterKeyguardGone); - } - - @Override - public void dismissKeyguardThenExecute(OnDismissAction action, Runnable cancelAction, - boolean afterKeyguardGone) { - if (mWakefulnessLifecycle.getWakefulness() == WAKEFULNESS_ASLEEP - && mKeyguardStateController.canDismissLockScreen() - && !mStatusBarStateController.leaveOpenOnKeyguardHide() - && 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( - BiometricUnlockController.MODE_WAKE_AND_UNLOCK_PULSING); - } - if (mStatusBarKeyguardViewManager.isShowing()) { - mStatusBarKeyguardViewManager.dismissWithAction(action, cancelAction, - afterKeyguardGone); - } else { - action.onDismiss(); - } - } - /** - * Notify the shade controller that the current user changed - * - * @param newUserId userId of the new user - */ - public void setLockscreenUser(int newUserId) { - if (mLockscreenWallpaper != null) { - mLockscreenWallpaper.setCurrentUser(newUserId); - } - mScrimController.setCurrentUser(newUserId); - if (mWallpaperSupported) { - mWallpaperChangedReceiver.onReceive(mContext, null); - } - } - - /** - * Reload some of our resources when the configuration changes. - * - * We don't reload everything when the configuration changes -- we probably - * should, but getting that smooth is tough. Someday we'll fix that. In the - * meantime, just update the things that we know change. - */ - void updateResources() { - // Update the quick setting tiles - if (mQSPanelController != null) { - mQSPanelController.updateResources(); - } - - if (mStatusBarWindowController != null) { - mStatusBarWindowController.refreshStatusBarHeight(); - } - - if (mNotificationPanelViewController != null) { - mNotificationPanelViewController.updateResources(); - } - if (mBrightnessMirrorController != null) { - mBrightnessMirrorController.updateResources(); - } - if (mStatusBarKeyguardViewManager != null) { - mStatusBarKeyguardViewManager.updateResources(); - } - - mPowerButtonReveal = new PowerButtonReveal(mContext.getResources().getDimensionPixelSize( - com.android.systemui.R.dimen.physical_power_button_center_screen_location_y)); - } - - // Visibility reporting - protected void handleVisibleToUserChanged(boolean visibleToUser) { - if (visibleToUser) { - handleVisibleToUserChangedImpl(visibleToUser); - mNotificationLogger.startNotificationLogging(); - } else { - mNotificationLogger.stopNotificationLogging(); - handleVisibleToUserChangedImpl(visibleToUser); - } - } - - // Visibility reporting - void handleVisibleToUserChangedImpl(boolean visibleToUser) { - if (visibleToUser) { - /* The LEDs are turned off when the notification panel is shown, even just a little bit. - * See also CentralSurfaces.setPanelExpanded for another place where we attempt to do - * this. - */ - boolean pinnedHeadsUp = mHeadsUpManager.hasPinnedHeadsUp(); - boolean clearNotificationEffects = - !mPresenter.isPresenterFullyCollapsed() && - (mState == StatusBarState.SHADE - || mState == StatusBarState.SHADE_LOCKED); - int notificationLoad = mNotificationsController.getActiveNotificationsCount(); - if (pinnedHeadsUp && mPresenter.isPresenterFullyCollapsed()) { - notificationLoad = 1; - } - final int finalNotificationLoad = notificationLoad; - mUiBgExecutor.execute(() -> { - try { - mBarService.onPanelRevealed(clearNotificationEffects, - finalNotificationLoad); - } catch (RemoteException ex) { - // Won't fail unless the world has ended. - } - }); - } else { - mUiBgExecutor.execute(() -> { - try { - mBarService.onPanelHidden(); - } catch (RemoteException ex) { - // Won't fail unless the world has ended. - } - }); - } - - } - - private void logStateToEventlog() { - boolean isShowing = mStatusBarKeyguardViewManager.isShowing(); - boolean isOccluded = mStatusBarKeyguardViewManager.isOccluded(); - boolean isBouncerShowing = mStatusBarKeyguardViewManager.isBouncerShowing(); - boolean isSecure = mKeyguardStateController.isMethodSecure(); - boolean unlocked = mKeyguardStateController.canDismissLockScreen(); - int stateFingerprint = getLoggingFingerprint(mState, - isShowing, - isOccluded, - isBouncerShowing, - isSecure, - unlocked); - if (stateFingerprint != mLastLoggedStateFingerprint) { - if (mStatusBarStateLog == null) { - mStatusBarStateLog = new LogMaker(MetricsEvent.VIEW_UNKNOWN); - } - mMetricsLogger.write(mStatusBarStateLog - .setCategory(isBouncerShowing ? MetricsEvent.BOUNCER : MetricsEvent.LOCKSCREEN) - .setType(isShowing ? MetricsEvent.TYPE_OPEN : MetricsEvent.TYPE_CLOSE) - .setSubtype(isSecure ? 1 : 0)); - EventLogTags.writeSysuiStatusBarState(mState, - isShowing ? 1 : 0, - isOccluded ? 1 : 0, - isBouncerShowing ? 1 : 0, - isSecure ? 1 : 0, - unlocked ? 1 : 0); - mLastLoggedStateFingerprint = stateFingerprint; - - StringBuilder uiEventValueBuilder = new StringBuilder(); - uiEventValueBuilder.append(isBouncerShowing ? "BOUNCER" : "LOCKSCREEN"); - uiEventValueBuilder.append(isShowing ? "_OPEN" : "_CLOSE"); - uiEventValueBuilder.append(isSecure ? "_SECURE" : "_INSECURE"); - sUiEventLogger.log(StatusBarUiEvent.valueOf(uiEventValueBuilder.toString())); - } - } - - /** - * Returns a fingerprint of fields logged to eventlog - */ - private static int getLoggingFingerprint(int statusBarState, boolean keyguardShowing, - boolean keyguardOccluded, boolean bouncerShowing, boolean secure, - boolean currentlyInsecure) { - // Reserve 8 bits for statusBarState. We'll never go higher than - // that, right? Riiiight. - return (statusBarState & 0xFF) - | ((keyguardShowing ? 1 : 0) << 8) - | ((keyguardOccluded ? 1 : 0) << 9) - | ((bouncerShowing ? 1 : 0) << 10) - | ((secure ? 1 : 0) << 11) - | ((currentlyInsecure ? 1 : 0) << 12); - } - - @Override - public void postQSRunnableDismissingKeyguard(final Runnable runnable) { - mMainExecutor.execute(() -> { - mStatusBarStateController.setLeaveOpenOnKeyguardHide(true); - executeRunnableDismissingKeyguard( - () -> mMainExecutor.execute(runnable), null, false, false, false); - }); - } - - @Override - public void postStartActivityDismissingKeyguard(PendingIntent intent) { - postStartActivityDismissingKeyguard(intent, null /* animationController */); - } - - @Override - public void postStartActivityDismissingKeyguard(final PendingIntent intent, - @Nullable ActivityLaunchAnimator.Controller animationController) { - mMainExecutor.execute(() -> startPendingIntentDismissingKeyguard(intent, - null /* intentSentUiThreadCallback */, animationController)); - } - - @Override - public void postStartActivityDismissingKeyguard(final Intent intent, int delay) { - postStartActivityDismissingKeyguard(intent, delay, null /* animationController */); - } - - @Override - public void postStartActivityDismissingKeyguard(Intent intent, int delay, - @Nullable ActivityLaunchAnimator.Controller animationController) { - mMainExecutor.executeDelayed( - () -> - startActivityDismissingKeyguard(intent, true /* onlyProvisioned */, - true /* dismissShade */, - false /* disallowEnterPictureInPictureWhileLaunching */, - null /* callback */, - 0 /* flags */, - animationController, - getActivityUserHandle(intent)), - delay); - } - - public void showKeyguard() { - mStatusBarStateController.setKeyguardRequested(true); - mStatusBarStateController.setLeaveOpenOnKeyguardHide(false); - updateIsKeyguard(); - mAssistManagerLazy.get().onLockscreenShown(); - } - - public boolean hideKeyguard() { - mStatusBarStateController.setKeyguardRequested(false); - return updateIsKeyguard(); - } - - boolean updateIsKeyguard() { - return updateIsKeyguard(false /* forceStateChange */); - } - - boolean updateIsKeyguard(boolean forceStateChange) { - boolean wakeAndUnlocking = mBiometricUnlockController.isWakeAndUnlock(); - - // For dozing, keyguard needs to be shown whenever the device is non-interactive. Otherwise - // 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 = mDozeServiceHost.getDozingRequested() - && (!mDeviceInteractive || (isGoingToSleep() - && (isScreenFullyOff() - || (mKeyguardStateController.isShowing() && !isOccluded())))); - boolean isWakingAndOccluded = isOccluded() && isWakingOrAwake(); - boolean shouldBeKeyguard = (mStatusBarStateController.isKeyguardRequested() - || keyguardForDozing) && !wakeAndUnlocking && !isWakingAndOccluded; - if (keyguardForDozing) { - updatePanelExpansionForKeyguard(); - } - if (shouldBeKeyguard) { - if (mScreenOffAnimationController.isKeyguardShowDelayed() - || (isGoingToSleep() - && mScreenLifecycle.getScreenState() == ScreenLifecycle.SCREEN_TURNING_OFF)) { - // Delay showing the keyguard until screen turned off. - } else { - showKeyguardImpl(); - } - } else { - // During folding a foldable device this might be called as a result of - // 'onScreenTurnedOff' call for the inner display. - // In this case: - // * When phone is locked on folding: it doesn't make sense to hide keyguard as it - // will be immediately locked again - // * When phone is unlocked: we still don't want to execute hiding of the keyguard - // as the animation could prepare 'fake AOD' interface (without actually - // transitioning to keyguard state) and this might reset the view states - if (!mScreenOffAnimationController.isKeyguardHideDelayed()) { - return hideKeyguardImpl(forceStateChange); - } - } - return false; - } - - public void showKeyguardImpl() { - Trace.beginSection("CentralSurfaces#showKeyguard"); - // In case we're locking while a smartspace transition is in progress, reset it. - mKeyguardUnlockAnimationController.resetSmartspaceTransition(); - if (mKeyguardStateController.isLaunchTransitionFadingAway()) { - mNotificationPanelViewController.cancelAnimation(); - onLaunchTransitionFadingEnded(); - } - mMessageRouter.cancelMessages(MSG_LAUNCH_TRANSITION_TIMEOUT); - if (!mLockscreenShadeTransitionController.isWakingToShadeLocked()) { - mStatusBarStateController.setState(StatusBarState.KEYGUARD); - } - updatePanelExpansionForKeyguard(); - Trace.endSection(); - } - - private void updatePanelExpansionForKeyguard() { - if (mState == StatusBarState.KEYGUARD && mBiometricUnlockController.getMode() - != BiometricUnlockController.MODE_WAKE_AND_UNLOCK && !mBouncerShowing) { - mShadeController.instantExpandNotificationsPanel(); - } - } - - private void onLaunchTransitionFadingEnded() { - mNotificationPanelViewController.resetAlpha(); - mNotificationPanelViewController.onAffordanceLaunchEnded(); - releaseGestureWakeLock(); - runLaunchTransitionEndRunnable(); - mKeyguardStateController.setLaunchTransitionFadingAway(false); - mPresenter.updateMediaMetaData(true /* metaDataChanged */, true); - } - - public boolean isInLaunchTransition() { - return mNotificationPanelViewController.isLaunchTransitionRunning() - || mNotificationPanelViewController.isLaunchTransitionFinished(); - } - - /** - * Fades the content of the keyguard away after the launch transition is done. - * - * @param beforeFading the runnable to be run when the circle is fully expanded and the fading - * starts - * @param endRunnable the runnable to be run when the transition is done. Will not run - * if the transition is cancelled, instead cancelRunnable will run - * @param cancelRunnable the runnable to be run if the transition is cancelled - */ - public void fadeKeyguardAfterLaunchTransition(final Runnable beforeFading, - Runnable endRunnable, Runnable cancelRunnable) { - mMessageRouter.cancelMessages(MSG_LAUNCH_TRANSITION_TIMEOUT); - mLaunchTransitionEndRunnable = endRunnable; - mLaunchTransitionCancelRunnable = cancelRunnable; - Runnable hideRunnable = () -> { - mKeyguardStateController.setLaunchTransitionFadingAway(true); - if (beforeFading != null) { - beforeFading.run(); - } - updateScrimController(); - mPresenter.updateMediaMetaData(false, true); - mNotificationPanelViewController.resetAlpha(); - mNotificationPanelViewController.fadeOut( - FADE_KEYGUARD_START_DELAY, FADE_KEYGUARD_DURATION, - this::onLaunchTransitionFadingEnded); - mCommandQueue.appTransitionStarting(mDisplayId, SystemClock.uptimeMillis(), - LightBarTransitionsController.DEFAULT_TINT_ANIMATION_DURATION, true); - }; - if (mNotificationPanelViewController.isLaunchTransitionRunning()) { - mNotificationPanelViewController.setLaunchTransitionEndRunnable(hideRunnable); - } else { - hideRunnable.run(); - } - } - - private void cancelAfterLaunchTransitionRunnables() { - if (mLaunchTransitionCancelRunnable != null) { - mLaunchTransitionCancelRunnable.run(); - } - mLaunchTransitionEndRunnable = null; - mLaunchTransitionCancelRunnable = null; - mNotificationPanelViewController.setLaunchTransitionEndRunnable(null); - } - - /** - * Fades the content of the Keyguard while we are dozing and makes it invisible when finished - * fading. - */ - public void fadeKeyguardWhilePulsing() { - mNotificationPanelViewController.fadeOut(0, FADE_KEYGUARD_DURATION_PULSING, - ()-> { - hideKeyguard(); - mStatusBarKeyguardViewManager.onKeyguardFadedAway(); - }).start(); - } - - /** - * Plays the animation when an activity that was occluding Keyguard goes away. - */ - public void animateKeyguardUnoccluding() { - mNotificationPanelViewController.setExpandedFraction(0f); - mCommandQueueCallbacks.animateExpandNotificationsPanel(); - mScrimController.setUnocclusionAnimationRunning(true); - } - - /** - * Starts the timeout when we try to start the affordances on Keyguard. We usually rely that - * Keyguard goes away via fadeKeyguardAfterLaunchTransition, however, that might not happen - * because the launched app crashed or something else went wrong. - */ - public void startLaunchTransitionTimeout() { - mMessageRouter.sendMessageDelayed( - MSG_LAUNCH_TRANSITION_TIMEOUT, LAUNCH_TRANSITION_TIMEOUT_MS); - } - - private void onLaunchTransitionTimeout() { - Log.w(TAG, "Launch transition: Timeout!"); - mNotificationPanelViewController.onAffordanceLaunchEnded(); - releaseGestureWakeLock(); - mNotificationPanelViewController.resetViews(false /* animate */); - } - - private void runLaunchTransitionEndRunnable() { - mLaunchTransitionCancelRunnable = null; - if (mLaunchTransitionEndRunnable != null) { - Runnable r = mLaunchTransitionEndRunnable; - - // mLaunchTransitionEndRunnable might call showKeyguard, which would execute it again, - // which would lead to infinite recursion. Protect against it. - mLaunchTransitionEndRunnable = null; - r.run(); - } - } - - /** - * @return true if we would like to stay in the shade, false if it should go away entirely - */ - public boolean hideKeyguardImpl(boolean forceStateChange) { - Trace.beginSection("CentralSurfaces#hideKeyguard"); - boolean staying = mStatusBarStateController.leaveOpenOnKeyguardHide(); - int previousState = mStatusBarStateController.getState(); - if (!(mStatusBarStateController.setState(StatusBarState.SHADE, forceStateChange))) { - //TODO: StatusBarStateController should probably know about hiding the keyguard and - // notify listeners. - - // If the state didn't change, we may still need to update public mode - mLockscreenUserManager.updatePublicMode(); - } - if (mStatusBarStateController.leaveOpenOnKeyguardHide()) { - if (!mStatusBarStateController.isKeyguardRequested()) { - mStatusBarStateController.setLeaveOpenOnKeyguardHide(false); - } - long delay = mKeyguardStateController.calculateGoingToFullShadeDelay(); - mLockscreenShadeTransitionController.onHideKeyguard(delay, previousState); - - // Disable layout transitions in navbar for this transition because the load is just - // too heavy for the CPU and GPU on any device. - mNavigationBarController.disableAnimationsDuringHide(mDisplayId, delay); - } else if (!mNotificationPanelViewController.isCollapsing()) { - instantCollapseNotificationPanel(); - } - - // Keyguard state has changed, but QS is not listening anymore. Make sure to update the tile - // visibilities so next time we open the panel we know the correct height already. - if (mQSPanelController != null) { - mQSPanelController.refreshAllTiles(); - } - mMessageRouter.cancelMessages(MSG_LAUNCH_TRANSITION_TIMEOUT); - releaseGestureWakeLock(); - mNotificationPanelViewController.onAffordanceLaunchEnded(); - mNotificationPanelViewController.resetAlpha(); - mNotificationPanelViewController.resetTranslation(); - mNotificationPanelViewController.resetViewGroupFade(); - updateDozingState(); - updateScrimController(); - Trace.endSection(); - return staying; - } - - private void releaseGestureWakeLock() { - if (mGestureWakeLock.isHeld()) { - mGestureWakeLock.release(); - } - } - - /** - * Notifies the status bar that Keyguard is going away very soon. - */ - public void keyguardGoingAway() { - // Treat Keyguard exit animation as an app transition to achieve nice transition for status - // bar. - mKeyguardStateController.notifyKeyguardGoingAway(true); - mCommandQueue.appTransitionPending(mDisplayId, true /* forced */); - updateScrimController(); - } - - /** - * Notifies the status bar the Keyguard is fading away with the specified timings. - * @param startTime the start time of the animations in uptime millis - * @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 - */ - public void setKeyguardFadingAway(long startTime, long delay, long fadeoutDuration, - boolean isBypassFading) { - mCommandQueue.appTransitionStarting(mDisplayId, startTime + fadeoutDuration - - LightBarTransitionsController.DEFAULT_TINT_ANIMATION_DURATION, - LightBarTransitionsController.DEFAULT_TINT_ANIMATION_DURATION, true); - mCommandQueue.recomputeDisableFlags(mDisplayId, fadeoutDuration > 0 /* animate */); - mCommandQueue.appTransitionStarting(mDisplayId, - startTime - LightBarTransitionsController.DEFAULT_TINT_ANIMATION_DURATION, - LightBarTransitionsController.DEFAULT_TINT_ANIMATION_DURATION, true); - mKeyguardStateController.notifyKeyguardFadingAway(delay, fadeoutDuration, isBypassFading); - } - - /** - * Notifies that the Keyguard fading away animation is done. - */ - public void finishKeyguardFadingAway() { - mKeyguardStateController.notifyKeyguardDoneFading(); - mScrimController.setExpansionAffectsAlpha(true); - - // If the device was re-locked while unlocking, we might have a pending lock that was - // delayed because the keyguard was in the middle of going away. - mKeyguardViewMediator.maybeHandlePendingLock(); - } - - /** - * Switches theme from light to dark and vice-versa. - */ - protected void updateTheme() { - // Set additional scrim only if the lock and system wallpaper are different to prevent - // applying the dimming effect twice. - mUiBgExecutor.execute(() -> { - float dimAmount = 0f; - if (mWallpaperManager.lockScreenWallpaperExists()) { - dimAmount = mWallpaperManager.getWallpaperDimAmount(); - } - final float scrimDimAmount = dimAmount; - mMainExecutor.execute(() -> { - mScrimController.setAdditionalScrimBehindAlphaKeyguard(scrimDimAmount); - mScrimController.applyCompositeAlphaOnScrimBehindKeyguard(); - }); - }); - - // Lock wallpaper defines the color of the majority of the views, hence we'll use it - // to set our default theme. - final boolean lockDarkText = mColorExtractor.getNeutralColors().supportsDarkText(); - final int themeResId = lockDarkText ? R.style.Theme_SystemUI_LightWallpaper - : R.style.Theme_SystemUI; - if (mContext.getThemeResId() != themeResId) { - mContext.setTheme(themeResId); - mConfigurationController.notifyThemeChanged(); - } - } - - private void updateDozingState() { - Trace.traceCounter(Trace.TRACE_TAG_APP, "dozing", mDozing ? 1 : 0); - Trace.beginSection("CentralSurfaces#updateDozingState"); - - boolean visibleNotOccluded = mStatusBarKeyguardViewManager.isShowing() - && !mStatusBarKeyguardViewManager.isOccluded(); - // If we're dozing and we'll be animating the screen off, the keyguard isn't currently - // visible but will be shortly for the animation, so we should proceed as if it's visible. - boolean visibleNotOccludedOrWillBe = - visibleNotOccluded || (mDozing && mDozeParameters.shouldDelayKeyguardShow()); - - boolean wakeAndUnlock = mBiometricUnlockController.getMode() - == BiometricUnlockController.MODE_WAKE_AND_UNLOCK; - boolean animate = (!mDozing && mDozeServiceHost.shouldAnimateWakeup() && !wakeAndUnlock) - || (mDozing && mDozeParameters.shouldControlScreenOff() - && visibleNotOccludedOrWillBe); - - mNotificationPanelViewController.setDozing(mDozing, animate, mWakeUpTouchLocation); - updateQsExpansionEnabled(); - Trace.endSection(); - } - - public void userActivity() { - if (mState == StatusBarState.KEYGUARD) { - mKeyguardViewMediatorCallback.userActivity(); - } - } - - public boolean interceptMediaKey(KeyEvent event) { - return mState == StatusBarState.KEYGUARD - && mStatusBarKeyguardViewManager.interceptMediaKey(event); - } - - /** - * While IME is active and a BACK event is detected, check with - * {@link StatusBarKeyguardViewManager#dispatchBackKeyEventPreIme()} to see if the event - * should be handled before routing to IME, in order to prevent the user having to hit back - * twice to exit bouncer. - */ - public boolean dispatchKeyEventPreIme(KeyEvent event) { - switch (event.getKeyCode()) { - case KeyEvent.KEYCODE_BACK: - if (mState == StatusBarState.KEYGUARD - && mStatusBarKeyguardViewManager.dispatchBackKeyEventPreIme()) { - return onBackPressed(); - } - } - return false; - } - - protected boolean shouldUnlockOnMenuPressed() { - return mDeviceInteractive && mState != StatusBarState.SHADE - && mStatusBarKeyguardViewManager.shouldDismissOnMenuPressed(); - } - - public boolean onMenuPressed() { - if (shouldUnlockOnMenuPressed()) { - mShadeController.animateCollapsePanels( - CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL /* flags */, true /* force */); - return true; - } - return false; - } - - public void endAffordanceLaunch() { - releaseGestureWakeLock(); - mNotificationPanelViewController.onAffordanceLaunchEnded(); - } - - public boolean onBackPressed() { - final boolean isScrimmedBouncer = - mScrimController.getState() == ScrimState.BOUNCER_SCRIMMED; - final boolean isBouncerOverDream = isBouncerShowingOverDream(); - - if (mStatusBarKeyguardViewManager.onBackPressed( - isScrimmedBouncer || isBouncerOverDream /* hideImmediately */)) { - if (isScrimmedBouncer || isBouncerOverDream) { - mStatusBarStateController.setLeaveOpenOnKeyguardHide(false); - } else { - mNotificationPanelViewController.expandWithoutQs(); - } - return true; - } - if (mNotificationPanelViewController.isQsCustomizing()) { - mNotificationPanelViewController.closeQsCustomizer(); - return true; - } - if (mNotificationPanelViewController.isQsExpanded()) { - if (mNotificationPanelViewController.isQsDetailShowing()) { - mNotificationPanelViewController.closeQsDetail(); - } else { - mNotificationPanelViewController.animateCloseQs(false /* animateAway */); - } - return true; - } - if (mNotificationPanelViewController.closeUserSwitcherIfOpen()) { - return true; - } - if (mState != StatusBarState.KEYGUARD && mState != StatusBarState.SHADE_LOCKED - && !isBouncerOverDream) { - if (mNotificationPanelViewController.canPanelBeCollapsed()) { - mShadeController.animateCollapsePanels(); - } - return true; - } - return false; - } - - public boolean onSpacePressed() { - if (mDeviceInteractive && mState != StatusBarState.SHADE) { - mShadeController.animateCollapsePanels( - CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL /* flags */, true /* force */); - return true; - } - return false; - } - - private void showBouncerOrLockScreenIfKeyguard() { - // If the keyguard is animating away, we aren't really the keyguard anymore and should not - // show the bouncer/lockscreen. - if (!mKeyguardViewMediator.isHiding() - && !mKeyguardUnlockAnimationController.isPlayingCannedUnlockAnimation()) { - if (mState == StatusBarState.SHADE_LOCKED - && mKeyguardUpdateMonitor.isUdfpsEnrolled()) { - // shade is showing while locked on the keyguard, so go back to showing the - // lock screen where users can use the UDFPS affordance to enter the device - mStatusBarKeyguardViewManager.reset(true); - } else if ((mState == StatusBarState.KEYGUARD - && !mStatusBarKeyguardViewManager.bouncerIsOrWillBeShowing()) - || mState == StatusBarState.SHADE_LOCKED) { - mStatusBarKeyguardViewManager.showGenericBouncer(true /* scrimmed */); - } - } - } - - /** - * Show the bouncer if we're currently on the keyguard or shade locked and aren't hiding. - * @param performAction the action to perform when the bouncer is dismissed. - * @param cancelAction the action to perform when unlock is aborted. - */ - public void showBouncerWithDimissAndCancelIfKeyguard(OnDismissAction performAction, - Runnable cancelAction) { - if ((mState == StatusBarState.KEYGUARD || mState == StatusBarState.SHADE_LOCKED) - && !mKeyguardViewMediator.isHiding()) { - mStatusBarKeyguardViewManager.dismissWithAction(performAction, cancelAction, - false /* afterKeyguardGone */); - } else if (cancelAction != null) { - cancelAction.run(); - } - } - - void instantCollapseNotificationPanel() { - mNotificationPanelViewController.instantCollapse(); - mShadeController.runPostCollapseRunnables(); - } - - /** - * Collapse the panel directly if we are on the main thread, post the collapsing on the main - * thread if we are not. - */ - void collapsePanelOnMainThread() { - if (Looper.getMainLooper().isCurrentThread()) { - mShadeController.collapsePanel(); - } else { - mContext.getMainExecutor().execute(mShadeController::collapsePanel); - } - } - - /** Collapse the panel. The collapsing will be animated for the given {@code duration}. */ - void collapsePanelWithDuration(int duration) { - mNotificationPanelViewController.collapseWithDuration(duration); - } - - /** - * Updates the light reveal effect to reflect the reason we're waking or sleeping (for example, - * from the power button). - * @param wakingUp Whether we're updating because we're waking up (true) or going to sleep - * (false). - */ - private void updateRevealEffect(boolean wakingUp) { - if (mLightRevealScrim == null) { - return; - } - - final boolean wakingUpFromPowerButton = wakingUp - && !(mLightRevealScrim.getRevealEffect() instanceof CircleReveal) - && mWakefulnessLifecycle.getLastWakeReason() - == PowerManager.WAKE_REASON_POWER_BUTTON; - final boolean sleepingFromPowerButton = !wakingUp - && mWakefulnessLifecycle.getLastSleepReason() - == PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON; - - if (wakingUpFromPowerButton || sleepingFromPowerButton) { - mLightRevealScrim.setRevealEffect(mPowerButtonReveal); - mLightRevealScrim.setRevealAmount(1f - mStatusBarStateController.getDozeAmount()); - } else if (!wakingUp || !(mLightRevealScrim.getRevealEffect() instanceof CircleReveal)) { - // If we're going to sleep, but it's not from the power button, use the default reveal. - // If we're waking up, only use the default reveal if the biometric controller didn't - // already set it to the circular reveal because we're waking up from a fingerprint/face - // auth. - mLightRevealScrim.setRevealEffect(LiftReveal.INSTANCE); - mLightRevealScrim.setRevealAmount(1f - mStatusBarStateController.getDozeAmount()); - } - } - - public LightRevealScrim getLightRevealScrim() { - return mLightRevealScrim; - } - - public void onTrackingStarted() { - mShadeController.runPostCollapseRunnables(); - } - - public void onClosingFinished() { - mShadeController.runPostCollapseRunnables(); - if (!mPresenter.isPresenterFullyCollapsed()) { - // if we set it not to be focusable when collapsing, we have to undo it when we aborted - // the closing - mNotificationShadeWindowController.setNotificationShadeFocusable(true); - } - } - - public void onUnlockHintStarted() { - mFalsingCollector.onUnlockHintStarted(); - mKeyguardIndicationController.showActionToUnlock(); - } - - public void onHintFinished() { - // Delay the reset a bit so the user can read the text. - mKeyguardIndicationController.hideTransientIndicationDelayed(HINT_RESET_DELAY_MS); - } - - public void onCameraHintStarted() { - mFalsingCollector.onCameraHintStarted(); - mKeyguardIndicationController.showTransientIndication(R.string.camera_hint); - } - - public void onVoiceAssistHintStarted() { - mFalsingCollector.onLeftAffordanceHintStarted(); - mKeyguardIndicationController.showTransientIndication(R.string.voice_hint); - } - - public void onPhoneHintStarted() { - mFalsingCollector.onLeftAffordanceHintStarted(); - mKeyguardIndicationController.showTransientIndication(R.string.phone_hint); - } - - public void onTrackingStopped(boolean expand) { - if (mState == StatusBarState.KEYGUARD || mState == StatusBarState.SHADE_LOCKED) { - if (!expand && !mKeyguardStateController.canDismissLockScreen()) { - mStatusBarKeyguardViewManager.showBouncer(false /* scrimmed */); - } - } - } - - // TODO: Figure out way to remove these. - public NavigationBarView getNavigationBarView() { - return mNavigationBarController.getNavigationBarView(mDisplayId); - } - - public boolean isOverviewEnabled() { - return mNavigationBarController.isOverviewEnabled(mDisplayId); - } - - public void showPinningEnterExitToast(boolean entering) { - mNavigationBarController.showPinningEnterExitToast(mDisplayId, entering); - } - - public void showPinningEscapeToast() { - mNavigationBarController.showPinningEscapeToast(mDisplayId); - } - - /** - * TODO: Remove this method. Views should not be passed forward. Will cause theme issues. - * @return bottom area view - */ - public KeyguardBottomAreaView getKeyguardBottomAreaView() { - return mNotificationPanelViewController.getKeyguardBottomAreaView(); - } - - /** - * Propagation of the bouncer state, indicating that it's fully visible. - */ - public void setBouncerShowing(boolean bouncerShowing) { - mBouncerShowing = bouncerShowing; - mKeyguardBypassController.setBouncerShowing(bouncerShowing); - mPulseExpansionHandler.setBouncerShowing(bouncerShowing); - setBouncerShowingForStatusBarComponents(bouncerShowing); - mStatusBarHideIconsForBouncerManager.setBouncerShowingAndTriggerUpdate(bouncerShowing); - mCommandQueue.recomputeDisableFlags(mDisplayId, true /* animate */); - updateScrimController(); - if (!mBouncerShowing) { - updatePanelExpansionForKeyguard(); - } - } - - /** - * Sets whether the bouncer over dream is showing. Note that the bouncer over dream is handled - * independently of the rest of the notification panel. As a result, setting this state via - * {@link #setBouncerShowing(boolean)} leads to unintended side effects from states modified - * behind the dream. - */ - public void setBouncerShowingOverDream(boolean bouncerShowingOverDream) { - mBouncerShowingOverDream = bouncerShowingOverDream; - } - - /** - * Propagate the bouncer state to status bar components. - * - * Separate from {@link #setBouncerShowing} because we sometimes re-create the status bar and - * should update only the status bar components. - */ - private void setBouncerShowingForStatusBarComponents(boolean bouncerShowing) { - int importance = bouncerShowing - ? IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS - : IMPORTANT_FOR_ACCESSIBILITY_AUTO; - if (mPhoneStatusBarViewController != null) { - mPhoneStatusBarViewController.setImportantForAccessibility(importance); - } - mNotificationPanelViewController.setImportantForAccessibility(importance); - mNotificationPanelViewController.setBouncerShowing(bouncerShowing); - } - - /** - * Collapses the notification shade if it is tracking or expanded. - */ - public void collapseShade() { - if (mNotificationPanelViewController.isTracking()) { - mNotificationShadeWindowViewController.cancelCurrentTouch(); - } - if (mPanelExpanded && mState == StatusBarState.SHADE) { - mShadeController.animateCollapsePanels(); - } - } - - @VisibleForTesting - final WakefulnessLifecycle.Observer mWakefulnessObserver = new WakefulnessLifecycle.Observer() { - @Override - public void onFinishedGoingToSleep() { - mNotificationPanelViewController.onAffordanceLaunchEnded(); - releaseGestureWakeLock(); - mLaunchCameraWhenFinishedWaking = false; - mDeviceInteractive = false; - mWakeUpComingFromTouch = false; - mWakeUpTouchLocation = null; - updateVisibleToUser(); - - updateNotificationPanelTouchState(); - mNotificationShadeWindowViewController.cancelCurrentTouch(); - if (mLaunchCameraOnFinishedGoingToSleep) { - mLaunchCameraOnFinishedGoingToSleep = false; - - // This gets executed before we will show Keyguard, so post it in order that the state - // is correct. - mMainExecutor.execute(() -> mCommandQueueCallbacks.onCameraLaunchGestureDetected( - mLastCameraLaunchSource)); - } - - if (mLaunchEmergencyActionOnFinishedGoingToSleep) { - mLaunchEmergencyActionOnFinishedGoingToSleep = false; - - // This gets executed before we will show Keyguard, so post it in order that the - // state is correct. - mMainExecutor.execute( - () -> mCommandQueueCallbacks.onEmergencyActionLaunchGestureDetected()); - } - updateIsKeyguard(); - } - - @Override - public void onStartedGoingToSleep() { - String tag = "CentralSurfaces#onStartedGoingToSleep"; - DejankUtils.startDetectingBlockingIpcs(tag); - - // cancel stale runnables that could put the device in the wrong state - cancelAfterLaunchTransitionRunnables(); - - updateRevealEffect(false /* wakingUp */); - updateNotificationPanelTouchState(); - maybeEscalateHeadsUp(); - dismissVolumeDialog(); - mWakeUpCoordinator.setFullyAwake(false); - mKeyguardBypassController.onStartedGoingToSleep(); - - // The unlocked screen off and fold to aod animations might use our LightRevealScrim - - // we need to be expanded for it to be visible. - if (mDozeParameters.shouldShowLightRevealScrim()) { - makeExpandedVisible(true); - } - - DejankUtils.stopDetectingBlockingIpcs(tag); - } - - @Override - public void onStartedWakingUp() { - String tag = "CentralSurfaces#onStartedWakingUp"; - DejankUtils.startDetectingBlockingIpcs(tag); - mNotificationShadeWindowController.batchApplyWindowLayoutParams(()-> { - mDeviceInteractive = true; - mWakeUpCoordinator.setWakingUp(true); - if (!mKeyguardBypassController.getBypassEnabled()) { - mHeadsUpManager.releaseAllImmediately(); - } - updateVisibleToUser(); - updateIsKeyguard(); - mDozeServiceHost.stopDozing(); - // This is intentionally below the stopDozing call above, since it avoids that we're - // unnecessarily animating the wakeUp transition. Animations should only be enabled - // once we fully woke up. - updateRevealEffect(true /* wakingUp */); - updateNotificationPanelTouchState(); - - // If we are waking up during the screen off animation, we should undo making the - // expanded visible (we did that so the LightRevealScrim would be visible). - if (mScreenOffAnimationController.shouldHideLightRevealScrimOnWakeUp()) { - makeExpandedInvisible(); - } - - }); - DejankUtils.stopDetectingBlockingIpcs(tag); - } - - @Override - public void onFinishedWakingUp() { - mWakeUpCoordinator.setFullyAwake(true); - mWakeUpCoordinator.setWakingUp(false); - if (mLaunchCameraWhenFinishedWaking) { - mNotificationPanelViewController.launchCamera( - false /* animate */, mLastCameraLaunchSource); - mLaunchCameraWhenFinishedWaking = false; - } - if (mLaunchEmergencyActionWhenFinishedWaking) { - mLaunchEmergencyActionWhenFinishedWaking = false; - Intent emergencyIntent = getEmergencyActionIntent(); - if (emergencyIntent != null) { - mContext.startActivityAsUser(emergencyIntent, - getActivityUserHandle(emergencyIntent)); - } - } - updateScrimController(); - } - }; - - /** - * We need to disable touch events because these might - * collapse the panel after we expanded it, and thus we would end up with a blank - * Keyguard. - */ - void updateNotificationPanelTouchState() { - boolean goingToSleepWithoutAnimation = isGoingToSleep() - && !mDozeParameters.shouldControlScreenOff(); - boolean disabled = (!mDeviceInteractive && !mDozeServiceHost.isPulsing()) - || goingToSleepWithoutAnimation; - mNotificationPanelViewController.setTouchAndAnimationDisabled(disabled); - mNotificationIconAreaController.setAnimationsEnabled(!disabled); - } - - final ScreenLifecycle.Observer mScreenObserver = new ScreenLifecycle.Observer() { - @Override - public void onScreenTurningOn(Runnable onDrawn) { - mFalsingCollector.onScreenTurningOn(); - mNotificationPanelViewController.onScreenTurningOn(); - } - - @Override - public void onScreenTurnedOn() { - mScrimController.onScreenTurnedOn(); - } - - @Override - public void onScreenTurnedOff() { - Trace.beginSection("CentralSurfaces#onScreenTurnedOff"); - mFalsingCollector.onScreenOff(); - mScrimController.onScreenTurnedOff(); - if (mCloseQsBeforeScreenOff) { - mNotificationPanelViewController.closeQs(); - mCloseQsBeforeScreenOff = false; - } - updateIsKeyguard(); - Trace.endSection(); - } - }; - - public int getWakefulnessState() { - return mWakefulnessLifecycle.getWakefulness(); - } - - /** - * @return true if the screen is currently fully off, i.e. has finished turning off and has - * since not started turning on. - */ - public boolean isScreenFullyOff() { - return mScreenLifecycle.getScreenState() == ScreenLifecycle.SCREEN_OFF; - } - - public void showScreenPinningRequest(int taskId, boolean allowCancel) { - mScreenPinningRequest.showPrompt(taskId, allowCancel); - } - - @Nullable Intent getEmergencyActionIntent() { - Intent emergencyIntent = new Intent(EmergencyGesture.ACTION_LAUNCH_EMERGENCY); - PackageManager pm = mContext.getPackageManager(); - List emergencyActivities = pm.queryIntentActivities(emergencyIntent, - PackageManager.MATCH_SYSTEM_ONLY); - ResolveInfo resolveInfo = getTopEmergencySosInfo(emergencyActivities); - if (resolveInfo == null) { - Log.wtf(TAG, "Couldn't find an app to process the emergency intent."); - return null; - } - emergencyIntent.setComponent(new ComponentName(resolveInfo.activityInfo.packageName, - resolveInfo.activityInfo.name)); - emergencyIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - return emergencyIntent; - } - - /** - * Select and return the "best" ResolveInfo for Emergency SOS Activity. - */ - private @Nullable ResolveInfo getTopEmergencySosInfo(List emergencyActivities) { - // No matched activity. - if (emergencyActivities == null || emergencyActivities.isEmpty()) { - return null; - } - - // Of multiple matched Activities, give preference to the pre-set package name. - String preferredAppPackageName = - mContext.getString(R.string.config_preferredEmergencySosPackage); - - // If there is no preferred app, then return first match. - if (TextUtils.isEmpty(preferredAppPackageName)) { - return emergencyActivities.get(0); - } - - for (ResolveInfo emergencyInfo: emergencyActivities) { - // If activity is from the preferred app, use it. - if (TextUtils.equals(emergencyInfo.activityInfo.packageName, preferredAppPackageName)) { - return emergencyInfo; - } - } - // No matching activity: return first match - return emergencyActivities.get(0); - } - - boolean isCameraAllowedByAdmin() { - 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; - } - - boolean isGoingToSleep() { - return mWakefulnessLifecycle.getWakefulness() - == WakefulnessLifecycle.WAKEFULNESS_GOING_TO_SLEEP; - } - - boolean isWakingOrAwake() { - return mWakefulnessLifecycle.getWakefulness() == WakefulnessLifecycle.WAKEFULNESS_WAKING - || mWakefulnessLifecycle.getWakefulness() == WakefulnessLifecycle.WAKEFULNESS_AWAKE; - } - - public void notifyBiometricAuthModeChanged() { - mDozeServiceHost.updateDozing(); - updateScrimController(); - } - - /** - * Set the amount of progress we are currently in if we're transitioning to the full shade. - * 0.0f means we're not transitioning yet, while 1 means we're all the way in the full - * shade. - */ - public void setTransitionToFullShadeProgress(float transitionToFullShadeProgress) { - mTransitionToFullShadeProgress = transitionToFullShadeProgress; - } - - /** - * Sets the amount of progress to the bouncer being fully hidden/visible. 1 means the bouncer - * is fully hidden, while 0 means the bouncer is visible. - */ - public void setBouncerHiddenFraction(float expansion) { - mScrimController.setBouncerHiddenFraction(expansion); - } - - @VisibleForTesting - public void updateScrimController() { - Trace.beginSection("CentralSurfaces#updateScrimController"); - - boolean unlocking = mKeyguardStateController.isShowing() && ( - mBiometricUnlockController.isWakeAndUnlock() - || mKeyguardStateController.isKeyguardFadingAway() - || mKeyguardStateController.isKeyguardGoingAway() - || mKeyguardViewMediator.requestedShowSurfaceBehindKeyguard() - || mKeyguardViewMediator.isAnimatingBetweenKeyguardAndSurfaceBehind()); - - mScrimController.setExpansionAffectsAlpha(!unlocking); - - boolean launchingAffordanceWithPreview = - mNotificationPanelViewController.isLaunchingAffordanceWithPreview(); - mScrimController.setLaunchingAffordanceWithPreview(launchingAffordanceWithPreview); - - if (mStatusBarKeyguardViewManager.isShowingAlternateAuth()) { - if (mState == StatusBarState.SHADE || mState == StatusBarState.SHADE_LOCKED - || mTransitionToFullShadeProgress > 0f) { - mScrimController.transitionTo(ScrimState.AUTH_SCRIMMED_SHADE); - } else { - mScrimController.transitionTo(ScrimState.AUTH_SCRIMMED); - } - } else if (mBouncerShowing && !unlocking) { - // Bouncer needs the front scrim when it's on top of an activity, - // tapping on a notification, editing QS or being dismissed by - // FLAG_DISMISS_KEYGUARD_ACTIVITY. - ScrimState state = mStatusBarKeyguardViewManager.bouncerNeedsScrimming() - ? ScrimState.BOUNCER_SCRIMMED : ScrimState.BOUNCER; - mScrimController.transitionTo(state); - } else if (launchingAffordanceWithPreview) { - // We want to avoid animating when launching with a preview. - mScrimController.transitionTo(ScrimState.UNLOCKED, mUnlockScrimCallback); - } else if (mBrightnessMirrorVisible) { - mScrimController.transitionTo(ScrimState.BRIGHTNESS_MIRROR); - } else if (mState == StatusBarState.SHADE_LOCKED) { - mScrimController.transitionTo(ScrimState.SHADE_LOCKED); - } 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 (mKeyguardStateController.isShowing() && !isOccluded() && !unlocking) { - mScrimController.transitionTo(ScrimState.KEYGUARD); - } else if (mKeyguardStateController.isShowing() && mKeyguardUpdateMonitor.isDreaming()) { - mScrimController.transitionTo(ScrimState.DREAMING); - } else { - mScrimController.transitionTo(ScrimState.UNLOCKED, mUnlockScrimCallback); - } - updateLightRevealScrimVisibility(); - - Trace.endSection(); - } - - public boolean isKeyguardShowing() { - if (mStatusBarKeyguardViewManager == null) { - Slog.i(TAG, "isKeyguardShowing() called before startKeyguard(), returning true"); - return true; - } - return mStatusBarKeyguardViewManager.isShowing(); - } - - public boolean shouldIgnoreTouch() { - return (mStatusBarStateController.isDozing() - && mDozeServiceHost.getIgnoreTouchWhilePulsing()) - || mScreenOffAnimationController.shouldIgnoreKeyguardTouches(); - } - - // Begin Extra BaseStatusBar methods. - - protected final CommandQueue mCommandQueue; - protected IStatusBarService mBarService; - - // all notifications - protected NotificationStackScrollLayout mStackScroller; - - // handling reordering - private final VisualStabilityManager mVisualStabilityManager; - - protected AccessibilityManager mAccessibilityManager; - - protected boolean mDeviceInteractive; - - protected boolean mVisible; - - // mScreenOnFromKeyguard && mVisible. - private boolean mVisibleToUser; - - protected DevicePolicyManager mDevicePolicyManager; - private final PowerManager mPowerManager; - protected StatusBarKeyguardViewManager mStatusBarKeyguardViewManager; - - protected KeyguardManager mKeyguardManager; - private final DeviceProvisionedController mDeviceProvisionedController; - - private final NavigationBarController mNavigationBarController; - private final AccessibilityFloatingMenuController mAccessibilityFloatingMenuController; - - // UI-specific methods - - protected WindowManager mWindowManager; - protected IWindowManager mWindowManagerService; - private IDreamManager mDreamManager; - - protected Display mDisplay; - private int mDisplayId; - - protected NotificationShelfController mNotificationShelfController; - - private final Lazy mAssistManagerLazy; - - public boolean isDeviceInteractive() { - return mDeviceInteractive; - } - - private final BroadcastReceiver mBannerActionBroadcastReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - String action = intent.getAction(); - if (BANNER_ACTION_CANCEL.equals(action) || BANNER_ACTION_SETUP.equals(action)) { - NotificationManager noMan = (NotificationManager) - mContext.getSystemService(Context.NOTIFICATION_SERVICE); - noMan.cancel(com.android.internal.messages.nano.SystemMessageProto.SystemMessage. - NOTE_HIDDEN_NOTIFICATIONS); - - Settings.Secure.putInt(mContext.getContentResolver(), - Settings.Secure.SHOW_NOTE_ABOUT_NOTIFICATION_HIDING, 0); - if (BANNER_ACTION_SETUP.equals(action)) { - mShadeController.animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL, - true /* force */); - mContext.startActivity(new Intent(Settings.ACTION_APP_NOTIFICATION_REDACTION) - .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) - - ); - } - } - } - }; - - public void setNotificationSnoozed(StatusBarNotification sbn, SnoozeOption snoozeOption) { - mNotificationsController.setNotificationSnoozed(sbn, snoozeOption); - } - - - public void awakenDreams() { - mUiBgExecutor.execute(() -> { - try { - mDreamManager.awaken(); - } catch (RemoteException e) { - e.printStackTrace(); - } - }); - } - - protected void toggleKeyboardShortcuts(int deviceId) { - KeyboardShortcuts.toggle(mContext, deviceId); - } - - protected void dismissKeyboardShortcuts() { - KeyboardShortcuts.dismiss(); - } - - /** - * Dismiss the keyguard then execute an action. - * - * @param action The action to execute after dismissing the keyguard. - * @param collapsePanel Whether we should collapse the panel after dismissing the keyguard. - * @param willAnimateOnKeyguard Whether {@param action} will run an animation on the keyguard if - * we are locked. - */ - private void executeActionDismissingKeyguard(Runnable action, boolean afterKeyguardGone, - boolean collapsePanel, boolean willAnimateOnKeyguard) { - if (!mDeviceProvisionedController.isDeviceProvisioned()) return; - - OnDismissAction onDismissAction = new OnDismissAction() { - @Override - public boolean onDismiss() { - new Thread(() -> { - try { - // The intent we are sending is for the application, which - // won't have permission to immediately start an activity after - // the user switches to home. We know it is safe to do at this - // point, so make sure new activity switches are now allowed. - ActivityManager.getService().resumeAppSwitches(); - } catch (RemoteException e) { - } - action.run(); - }).start(); - - return collapsePanel ? mShadeController.collapsePanel() : willAnimateOnKeyguard; - } - - @Override - public boolean willRunAnimationOnKeyguard() { - return willAnimateOnKeyguard; - } - }; - dismissKeyguardThenExecute(onDismissAction, afterKeyguardGone); - } - - @Override - public void startPendingIntentDismissingKeyguard(final PendingIntent intent) { - startPendingIntentDismissingKeyguard(intent, null); - } - - @Override - public void startPendingIntentDismissingKeyguard( - final PendingIntent intent, @Nullable final Runnable intentSentUiThreadCallback) { - startPendingIntentDismissingKeyguard(intent, intentSentUiThreadCallback, - (ActivityLaunchAnimator.Controller) null); - } - - @Override - public void startPendingIntentDismissingKeyguard(PendingIntent intent, - Runnable intentSentUiThreadCallback, View associatedView) { - ActivityLaunchAnimator.Controller animationController = null; - if (associatedView instanceof ExpandableNotificationRow) { - animationController = mNotificationAnimationProvider.getAnimatorController( - ((ExpandableNotificationRow) associatedView)); - } - - startPendingIntentDismissingKeyguard(intent, intentSentUiThreadCallback, - animationController); - } - - @Override - public void startPendingIntentDismissingKeyguard( - final PendingIntent intent, @Nullable final Runnable intentSentUiThreadCallback, - @Nullable ActivityLaunchAnimator.Controller animationController) { - final boolean willLaunchResolverActivity = intent.isActivity() - && mActivityIntentHelper.wouldLaunchResolverActivity(intent.getIntent(), - mLockscreenUserManager.getCurrentUserId()); - - boolean animate = !willLaunchResolverActivity - && animationController != null - && shouldAnimateLaunch(intent.isActivity()); - - // If we animate, don't collapse the shade and defer the keyguard dismiss (in case we run - // the animation on the keyguard). The animation will take care of (instantly) collapsing - // the shade and hiding the keyguard once it is done. - boolean collapse = !animate; - executeActionDismissingKeyguard(() -> { - try { - // We wrap animationCallback with a StatusBarLaunchAnimatorController so that the - // shade is collapsed after the animation (or when it is cancelled, aborted, etc). - ActivityLaunchAnimator.Controller controller = - animationController != null ? new StatusBarLaunchAnimatorController( - animationController, this, intent.isActivity()) : null; - - mActivityLaunchAnimator.startPendingIntentWithAnimation( - controller, animate, intent.getCreatorPackage(), - (animationAdapter) -> { - ActivityOptions options = new ActivityOptions( - getActivityOptions(mDisplayId, animationAdapter)); - // TODO b/221255671: restrict this to only be set for notifications - options.setEligibleForLegacyPermissionPrompt(true); - return intent.sendAndReturnResult(null, 0, null, null, null, - null, options.toBundle()); - }); - } catch (PendingIntent.CanceledException e) { - // the stack trace isn't very helpful here. - // Just log the exception message. - Log.w(TAG, "Sending intent failed: " + e); - if (!collapse) { - // executeActionDismissingKeyguard did not collapse for us already. - collapsePanelOnMainThread(); - } - // TODO: Dismiss Keyguard. - } - if (intent.isActivity()) { - mAssistManagerLazy.get().hideAssist(); - } - if (intentSentUiThreadCallback != null) { - postOnUiThread(intentSentUiThreadCallback); - } - }, willLaunchResolverActivity, collapse, animate); - } - - private void postOnUiThread(Runnable runnable) { - mMainExecutor.execute(runnable); - } - /** * Returns an ActivityOptions bundle created using the given parameters. * - * @param displayId The ID of the display to launch the activity in. Typically this would be the - * display the status bar is on. + * @param displayId The ID of the display to launch the activity in. Typically this would + * be the display the status bar is on. * @param animationAdapter The animation adapter used to start this activity, or {@code null} * for the default animation. */ - public static Bundle getActivityOptions(int displayId, + static Bundle getActivityOptions(int displayId, @Nullable RemoteAnimationAdapter animationAdapter) { ActivityOptions options = getDefaultActivityOptions(animationAdapter); options.setLaunchDisplayId(displayId); @@ -4064,15 +125,16 @@ public class CentralSurfaces extends CoreStartable implements /** * Returns an ActivityOptions bundle created using the given parameters. * - * @param displayId The ID of the display to launch the activity in. Typically this would be the - * display the status bar is on. - * @param animationAdapter The animation adapter used to start this activity, or {@code null} - * for the default animation. + * @param displayId The ID of the display to launch the activity in. Typically this + * would be the + * display the status bar is on. + * @param animationAdapter The animation adapter used to start this activity, or {@code null} + * for the default animation. * @param isKeyguardShowing Whether keyguard is currently showing. - * @param eventTime The event time in milliseconds since boot, not including sleep. See - * {@link ActivityOptions#setSourceInfo}. + * @param eventTime The event time in milliseconds since boot, not including sleep. See + * {@link ActivityOptions#setSourceInfo}. */ - public static Bundle getActivityOptions(int displayId, + static Bundle getActivityOptions(int displayId, @Nullable RemoteAnimationAdapter animationAdapter, boolean isKeyguardShowing, long eventTime) { ActivityOptions options = getDefaultActivityOptions(animationAdapter); @@ -4083,7 +145,7 @@ public class CentralSurfaces extends CoreStartable implements return options.toBundle(); } - public static ActivityOptions getDefaultActivityOptions( + static ActivityOptions getDefaultActivityOptions( @Nullable RemoteAnimationAdapter animationAdapter) { ActivityOptions options; if (animationAdapter != null) { @@ -4100,68 +162,11 @@ public class CentralSurfaces extends CoreStartable implements return options; } - void visibilityChanged(boolean visible) { - if (mVisible != visible) { - mVisible = visible; - if (!visible) { - mGutsManager.closeAndSaveGuts(true /* removeLeavebehind */, true /* force */, - true /* removeControls */, -1 /* x */, -1 /* y */, true /* resetMenu */); - } - } - updateVisibleToUser(); - } - - protected void updateVisibleToUser() { - boolean oldVisibleToUser = mVisibleToUser; - mVisibleToUser = mVisible && mDeviceInteractive; - - if (oldVisibleToUser != mVisibleToUser) { - handleVisibleToUserChanged(mVisibleToUser); - } - } - /** - * Clear Buzz/Beep/Blink. + * @return a PackageManager for userId or if userId is < 0 (USER_ALL etc) then + * return PackageManager for mContext */ - public void clearNotificationEffects() { - try { - mBarService.clearNotificationEffects(); - } catch (RemoteException e) { - // Won't fail unless the world has ended. - } - } - - /** - * @return Whether the security bouncer from Keyguard is showing. - */ - public boolean isBouncerShowing() { - return mBouncerShowing; - } - - /** - * @return Whether the security bouncer from Keyguard is showing. - */ - public boolean isBouncerShowingScrimmed() { - return isBouncerShowing() && mStatusBarKeyguardViewManager.bouncerNeedsScrimming(); - } - - public boolean isBouncerShowingOverDream() { - return mBouncerShowingOverDream; - } - - /** - * When {@link KeyguardBouncer} starts to be dismissed, playing its animation. - */ - public void onBouncerPreHideAnimation() { - mNotificationPanelViewController.onBouncerPreHideAnimation(); - - } - - /** - * @return a PackageManger for userId or if userId is < 0 (USER_ALL etc) then - * return PackageManager for mContext - */ - public static PackageManager getPackageManagerForUser(Context context, int userId) { + static PackageManager getPackageManagerForUser(Context context, int userId) { Context contextForUser = context; // UserHandle defines special userId as negative values, e.g. USER_ALL if (userId >= 0) { @@ -4170,353 +175,413 @@ public class CentralSurfaces extends CoreStartable implements // for user 0 we can still load information about the package. contextForUser = context.createPackageContextAsUser(context.getPackageName(), - Context.CONTEXT_RESTRICTED, - new UserHandle(userId)); - } catch (NameNotFoundException e) { + Context.CONTEXT_RESTRICTED, + new UserHandle(userId)); + } catch (PackageManager.NameNotFoundException e) { // Shouldn't fail to find the package name for system ui. } } return contextForUser.getPackageManager(); } - public boolean isKeyguardSecure() { - if (mStatusBarKeyguardViewManager == null) { - // startKeyguard() hasn't been called yet, so we don't know. - // Make sure anything that needs to know isKeyguardSecure() checks and re-checks this - // value onVisibilityChanged(). - Slog.w(TAG, "isKeyguardSecure() called before startKeyguard(), returning false", - new Throwable()); - return false; + void animateExpandNotificationsPanel(); + + void animateExpandSettingsPanel(@Nullable String subpanel); + + void animateCollapsePanels(int flags, boolean force); + + void collapsePanelOnMainThread(); + + void collapsePanelWithDuration(int duration); + + void togglePanel(); + + void start(); + + boolean updateIsKeyguard(); + + boolean updateIsKeyguard(boolean forceStateChange); + + @NonNull + @Override + Lifecycle getLifecycle(); + + void wakeUpIfDozing(long time, View where, String why); + + NotificationShadeWindowView getNotificationShadeWindowView(); + + NotificationShadeWindowViewController getNotificationShadeWindowViewController(); + + NotificationPanelViewController getNotificationPanelViewController(); + + ViewGroup getBouncerContainer(); + + int getStatusBarHeight(); + + void updateQsExpansionEnabled(); + + boolean isShadeDisabled(); + + void requestNotificationUpdate(String reason); + + void requestFaceAuth(boolean userInitiatedRequest); + + @Override + void startActivity(Intent intent, boolean onlyProvisioned, boolean dismissShade, + int flags); + + @Override + void startActivity(Intent intent, boolean dismissShade); + + @Override + void startActivity(Intent intent, boolean dismissShade, + @Nullable ActivityLaunchAnimator.Controller animationController, + boolean showOverLockscreenWhenLocked); + + @Override + void startActivity(Intent intent, boolean dismissShade, + @Nullable ActivityLaunchAnimator.Controller animationController, + boolean showOverLockscreenWhenLocked, UserHandle userHandle); + + boolean isLaunchingActivityOverLockscreen(); + + @Override + void startActivity(Intent intent, boolean onlyProvisioned, boolean dismissShade); + + @Override + void startActivity(Intent intent, boolean dismissShade, Callback callback); + + void setQsExpanded(boolean expanded); + + boolean isWakeUpComingFromTouch(); + + boolean isFalsingThresholdNeeded(); + + void onKeyguardViewManagerStatesUpdated(); + + void setPanelExpanded(boolean isExpanded); + + ViewGroup getNotificationScrollLayout(); + + boolean isPulsing(); + + @Nullable + View getAmbientIndicationContainer(); + + boolean isOccluded(); + + //TODO: These can / should probably be moved to NotificationPresenter or ShadeController + void onLaunchAnimationCancelled(boolean isLaunchForActivity); + + void onLaunchAnimationEnd(boolean launchIsFullScreen); + + boolean shouldAnimateLaunch(boolean isActivityIntent, boolean showOverLockscreen); + + boolean shouldAnimateLaunch(boolean isActivityIntent); + + boolean isDeviceInVrMode(); + + NotificationPresenter getPresenter(); + + void postAnimateCollapsePanels(); + + void postAnimateForceCollapsePanels(); + + void postAnimateOpenPanels(); + + boolean isExpandedVisible(); + + boolean isPanelExpanded(); + + void onInputFocusTransfer(boolean start, boolean cancel, float velocity); + + void animateCollapseQuickSettings(); + + void onTouchEvent(MotionEvent event); + + GestureRecorder getGestureRecorder(); + + BiometricUnlockController getBiometricUnlockController(); + + void showWirelessChargingAnimation(int batteryLevel); + + void checkBarModes(); + + // Called by NavigationBarFragment + void setQsScrimEnabled(boolean scrimEnabled); + + void updateBubblesVisibility(); + + void setInteracting(int barWindow, boolean interacting); + + @Override + void dump(PrintWriter pwOriginal, String[] args); + + void createAndAddWindows(@Nullable RegisterStatusBarResult result); + + float getDisplayWidth(); + + float getDisplayHeight(); + + void startActivityDismissingKeyguard(Intent intent, boolean onlyProvisioned, + boolean dismissShade, int flags); + + void startActivityDismissingKeyguard(Intent intent, boolean onlyProvisioned, + boolean dismissShade); + + void startActivityDismissingKeyguard(Intent intent, boolean onlyProvisioned, + boolean dismissShade, boolean disallowEnterPictureInPictureWhileLaunching, + Callback callback, int flags, + @Nullable ActivityLaunchAnimator.Controller animationController, + UserHandle userHandle); + + void readyForKeyguardDone(); + + void executeRunnableDismissingKeyguard(Runnable runnable, + Runnable cancelAction, + boolean dismissShade, + boolean afterKeyguardGone, + boolean deferred); + + void executeRunnableDismissingKeyguard(Runnable runnable, + Runnable cancelAction, + boolean dismissShade, + boolean afterKeyguardGone, + boolean deferred, + boolean willAnimateOnKeyguard); + + void resetUserExpandedStates(); + + @Override + void dismissKeyguardThenExecute(OnDismissAction action, Runnable cancelAction, + boolean afterKeyguardGone); + + void setLockscreenUser(int newUserId); + + @Override + void postQSRunnableDismissingKeyguard(Runnable runnable); + + @Override + void postStartActivityDismissingKeyguard(PendingIntent intent); + + @Override + void postStartActivityDismissingKeyguard(PendingIntent intent, + @Nullable ActivityLaunchAnimator.Controller animationController); + + @Override + void postStartActivityDismissingKeyguard(Intent intent, int delay); + + @Override + void postStartActivityDismissingKeyguard(Intent intent, int delay, + @Nullable ActivityLaunchAnimator.Controller animationController); + + void showKeyguard(); + + boolean hideKeyguard(); + + void showKeyguardImpl(); + + boolean isInLaunchTransition(); + + void fadeKeyguardAfterLaunchTransition(Runnable beforeFading, + Runnable endRunnable, Runnable cancelRunnable); + + void fadeKeyguardWhilePulsing(); + + void animateKeyguardUnoccluding(); + + void startLaunchTransitionTimeout(); + + boolean hideKeyguardImpl(boolean forceStateChange); + + void keyguardGoingAway(); + + void setKeyguardFadingAway(long startTime, long delay, long fadeoutDuration, + boolean isBypassFading); + + void finishKeyguardFadingAway(); + + void userActivity(); + + boolean interceptMediaKey(KeyEvent event); + + boolean dispatchKeyEventPreIme(KeyEvent event); + + boolean onMenuPressed(); + + void endAffordanceLaunch(); + + boolean onBackPressed(); + + boolean onSpacePressed(); + + void showBouncerWithDimissAndCancelIfKeyguard(OnDismissAction performAction, + Runnable cancelAction); + + LightRevealScrim getLightRevealScrim(); + + void onTrackingStarted(); + + void onClosingFinished(); + + void onUnlockHintStarted(); + + void onHintFinished(); + + void onCameraHintStarted(); + + void onVoiceAssistHintStarted(); + + void onPhoneHintStarted(); + + void onTrackingStopped(boolean expand); + + // TODO: Figure out way to remove these. + NavigationBarView getNavigationBarView(); + + boolean isOverviewEnabled(); + + void showPinningEnterExitToast(boolean entering); + + void showPinningEscapeToast(); + + KeyguardBottomAreaView getKeyguardBottomAreaView(); + + void setBouncerShowing(boolean bouncerShowing); + + void setBouncerShowingOverDream(boolean bouncerShowingOverDream); + + void collapseShade(); + + int getWakefulnessState(); + + boolean isScreenFullyOff(); + + void showScreenPinningRequest(int taskId, boolean allowCancel); + + @Nullable + Intent getEmergencyActionIntent(); + + boolean isCameraAllowedByAdmin(); + + boolean isGoingToSleep(); + + void notifyBiometricAuthModeChanged(); + + void setTransitionToFullShadeProgress(float transitionToFullShadeProgress); + + void setBouncerHiddenFraction(float expansion); + + @VisibleForTesting + void updateScrimController(); + + boolean isKeyguardShowing(); + + boolean shouldIgnoreTouch(); + + boolean isDeviceInteractive(); + + void setNotificationSnoozed(StatusBarNotification sbn, + NotificationSwipeActionHelper.SnoozeOption snoozeOption); + + void awakenDreams(); + + @Override + void startPendingIntentDismissingKeyguard(PendingIntent intent); + + @Override + void startPendingIntentDismissingKeyguard( + PendingIntent intent, @Nullable Runnable intentSentUiThreadCallback); + + @Override + void startPendingIntentDismissingKeyguard(PendingIntent intent, + Runnable intentSentUiThreadCallback, View associatedView); + + @Override + void startPendingIntentDismissingKeyguard( + PendingIntent intent, @Nullable Runnable intentSentUiThreadCallback, + @Nullable ActivityLaunchAnimator.Controller animationController); + + void clearNotificationEffects(); + + boolean isBouncerShowing(); + + boolean isBouncerShowingScrimmed(); + + boolean isBouncerShowingOverDream(); + + void onBouncerPreHideAnimation(); + + boolean isKeyguardSecure(); + + NotificationPanelViewController getPanelController(); + + NotificationGutsManager getGutsManager(); + + void updateNotificationPanelTouchState(); + + void makeExpandedVisible(boolean force); + + void instantCollapseNotificationPanel(); + + void visibilityChanged(boolean visible); + + int getDisplayId(); + + int getRotation(); + + @VisibleForTesting + void setBarStateForTest(int state); + + void wakeUpForFullScreenIntent(); + + void showTransientUnchecked(); + + void clearTransient(); + + void acquireGestureWakeLock(long time); + + boolean setAppearance(int appearance); + + int getBarMode(); + + void resendMessage(int msg); + + void resendMessage(Object msg); + + int getDisabled1(); + + void setDisabled1(int disabled); + + int getDisabled2(); + + void setDisabled2(int disabled); + + void setLastCameraLaunchSource(int source); + + void setLaunchCameraOnFinishedGoingToSleep(boolean launch); + + void setLaunchCameraOnFinishedWaking(boolean launch); + + void setLaunchEmergencyActionOnFinishedGoingToSleep(boolean launch); + + void setLaunchEmergencyActionOnFinishedWaking(boolean launch); + + void setTopHidesStatusBar(boolean hides); + + QSPanelController getQSPanelController(); + + boolean areNotificationAlertsDisabled(); + + float getDisplayDensity(); + + void extendDozePulse(); + + public static class KeyboardShortcutsMessage { + final int mDeviceId; + + KeyboardShortcutsMessage(int deviceId) { + mDeviceId = deviceId; } - return mStatusBarKeyguardViewManager.isSecure(); - } - public NotificationPanelViewController getPanelController() { - return mNotificationPanelViewController; - } - // End Extra BaseStatusBarMethods. - - public NotificationGutsManager getGutsManager() { - return mGutsManager; - } - - boolean isTransientShown() { - return mTransientShown; - } - - private void updateLightRevealScrimVisibility() { - if (mLightRevealScrim == null) { - // status bar may not be inflated yet - return; - } - - mLightRevealScrim.setAlpha(mScrimController.getState().getMaxLightRevealScrimAlpha()); - } - - private final KeyguardUpdateMonitorCallback mUpdateCallback = - new KeyguardUpdateMonitorCallback() { - @Override - public void onDreamingStateChanged(boolean dreaming) { - updateScrimController(); - if (dreaming) { - maybeEscalateHeadsUp(); - } - } - - // TODO: (b/145659174) remove when moving to NewNotifPipeline. Replaced by - // KeyguardCoordinator - @Override - public void onStrongAuthStateChanged(int userId) { - super.onStrongAuthStateChanged(userId); - mNotificationsController.requestNotificationUpdate("onStrongAuthStateChanged"); - } - }; - - - private final FalsingManager.FalsingBeliefListener mFalsingBeliefListener = - new FalsingManager.FalsingBeliefListener() { - @Override - public void onFalse() { - // Hides quick settings, bouncer, and quick-quick settings. - mStatusBarKeyguardViewManager.reset(true); - } - }; - - // Notifies StatusBarKeyguardViewManager every time the keyguard transition is over, - // this animation is tied to the scrim for historic reasons. - // TODO: notify when keyguard has faded away instead of the scrim. - private final ScrimController.Callback mUnlockScrimCallback = new ScrimController - .Callback() { - @Override - public void onFinished() { - if (mStatusBarKeyguardViewManager == null) { - Log.w(TAG, "Tried to notify keyguard visibility when " - + "mStatusBarKeyguardViewManager was null"); - return; - } - if (mKeyguardStateController.isKeyguardFadingAway()) { - mStatusBarKeyguardViewManager.onKeyguardFadedAway(); - } - } - - @Override - public void onCancelled() { - onFinished(); - } - }; - - private final DeviceProvisionedListener mUserSetupObserver = new DeviceProvisionedListener() { - @Override - public void onUserSetupChanged() { - final boolean userSetup = mDeviceProvisionedController.isCurrentUserSetup(); - Log.d(TAG, "mUserSetupObserver - DeviceProvisionedListener called for " - + "current user"); - if (MULTIUSER_DEBUG) { - Log.d(TAG, String.format("User setup changed: userSetup=%s mUserSetup=%s", - userSetup, mUserSetup)); - } - - if (userSetup != mUserSetup) { - mUserSetup = userSetup; - if (!mUserSetup) { - animateCollapseQuickSettings(); - } - if (mNotificationPanelViewController != null) { - mNotificationPanelViewController.setUserSetupComplete(mUserSetup); - } - updateQsExpansionEnabled(); - } - } - }; - - private final BroadcastReceiver mWallpaperChangedReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - if (!mWallpaperSupported) { - // Receiver should not have been registered at all... - Log.wtf(TAG, "WallpaperManager not supported"); - return; - } - WallpaperInfo info = mWallpaperManager.getWallpaperInfo(UserHandle.USER_CURRENT); - mWallpaperController.onWallpaperInfoUpdated(info); - - final boolean deviceSupportsAodWallpaper = mContext.getResources().getBoolean( - com.android.internal.R.bool.config_dozeSupportsAodWallpaper); - // If WallpaperInfo is null, it must be ImageWallpaper. - final boolean supportsAmbientMode = deviceSupportsAodWallpaper - && (info != null && info.supportsAmbientMode()); - - mNotificationShadeWindowController.setWallpaperSupportsAmbientMode(supportsAmbientMode); - mScrimController.setWallpaperSupportsAmbientMode(supportsAmbientMode); - mKeyguardViewMediator.setWallpaperSupportsAmbientMode(supportsAmbientMode); - } - }; - - private final ConfigurationListener mConfigurationListener = new ConfigurationListener() { - @Override - public void onConfigChanged(Configuration newConfig) { - updateResources(); - updateDisplaySize(); // populates mDisplayMetrics - - if (DEBUG) { - Log.v(TAG, "configuration changed: " + mContext.getResources().getConfiguration()); - } - - if (!mNotifPipelineFlags.isNewPipelineEnabled()) { - mViewHierarchyManager.updateRowStates(); - } - mScreenPinningRequest.onConfigurationChanged(); - } - - @Override - public void onDensityOrFontScaleChanged() { - // TODO: Remove this. - if (mBrightnessMirrorController != null) { - mBrightnessMirrorController.onDensityOrFontScaleChanged(); - } - // TODO: Bring these out of CentralSurfaces. - mUserInfoControllerImpl.onDensityOrFontScaleChanged(); - mUserSwitcherController.onDensityOrFontScaleChanged(); - mNotificationIconAreaController.onDensityOrFontScaleChanged(mContext); - mHeadsUpManager.onDensityOrFontScaleChanged(); - } - - @Override - public void onThemeChanged() { - if (mBrightnessMirrorController != null) { - mBrightnessMirrorController.onOverlayChanged(); - } - // We need the new R.id.keyguard_indication_area before recreating - // mKeyguardIndicationController - mNotificationPanelViewController.onThemeChanged(); - - if (mStatusBarKeyguardViewManager != null) { - mStatusBarKeyguardViewManager.onThemeChanged(); - } - if (mAmbientIndicationContainer instanceof AutoReinflateContainer) { - ((AutoReinflateContainer) mAmbientIndicationContainer).inflateLayout(); - } - mNotificationIconAreaController.onThemeChanged(); - } - - @Override - public void onUiModeChanged() { - if (mBrightnessMirrorController != null) { - mBrightnessMirrorController.onUiModeChanged(); - } - } - }; - - private StatusBarStateController.StateListener mStateListener = - new StatusBarStateController.StateListener() { - @Override - public void onStatePreChange(int oldState, int newState) { - // If we're visible and switched to SHADE_LOCKED (the user dragged - // down on the lockscreen), clear notification LED, vibration, - // ringing. - // Other transitions are covered in handleVisibleToUserChanged(). - if (mVisible && (newState == StatusBarState.SHADE_LOCKED - || mStatusBarStateController.goingToFullShade())) { - clearNotificationEffects(); - } - if (newState == StatusBarState.KEYGUARD) { - mRemoteInputManager.onPanelCollapsed(); - maybeEscalateHeadsUp(); - } - } - - @Override - public void onStateChanged(int newState) { - mState = newState; - updateReportRejectedTouchVisibility(); - mDozeServiceHost.updateDozing(); - updateTheme(); - mNavigationBarController.touchAutoDim(mDisplayId); - Trace.beginSection("CentralSurfaces#updateKeyguardState"); - if (mState == StatusBarState.KEYGUARD) { - mNotificationPanelViewController.cancelPendingPanelCollapse(); - } - updateDozingState(); - checkBarModes(); - updateScrimController(); - mPresenter.updateMediaMetaData(false, mState != StatusBarState.KEYGUARD); - Trace.endSection(); - } - - @Override - public void onDozeAmountChanged(float linear, float eased) { - if (mFeatureFlags.isEnabled(Flags.LOCKSCREEN_ANIMATIONS) - && !(mLightRevealScrim.getRevealEffect() instanceof CircleReveal)) { - mLightRevealScrim.setRevealAmount(1f - linear); - } - } - - @Override - public void onDozingChanged(boolean isDozing) { - Trace.beginSection("CentralSurfaces#updateDozing"); - mDozing = isDozing; - - // Collapse the notification panel if open - boolean dozingAnimated = mDozeServiceHost.getDozingRequested() - && mDozeParameters.shouldControlScreenOff(); - mNotificationPanelViewController.resetViews(dozingAnimated); - - updateQsExpansionEnabled(); - mKeyguardViewMediator.setDozing(mDozing); - - mNotificationsController.requestNotificationUpdate("onDozingChanged"); - updateDozingState(); - mDozeServiceHost.updateDozing(); - updateScrimController(); - updateReportRejectedTouchVisibility(); - Trace.endSection(); - } - - @Override - public void onFullscreenStateChanged(boolean isFullscreen) { - mIsFullscreen = isFullscreen; - maybeUpdateBarMode(); - } - }; - - private final BatteryController.BatteryStateChangeCallback mBatteryStateChangeCallback = - new BatteryController.BatteryStateChangeCallback() { - @Override - public void onPowerSaveChanged(boolean isPowerSave) { - mMainExecutor.execute(mCheckBarModes); - if (mDozeServiceHost != null) { - mDozeServiceHost.firePowerSaveChanged(isPowerSave); - } - } - }; - - private final ActivityLaunchAnimator.Callback mActivityLaunchAnimatorCallback = - new ActivityLaunchAnimator.Callback() { - @Override - public boolean isOnKeyguard() { - return mKeyguardStateController.isShowing(); - } - - @Override - public void hideKeyguardWithAnimation(IRemoteAnimationRunner runner) { - // We post to the main thread for 2 reasons: - // 1. KeyguardViewMediator is not thread-safe. - // 2. To ensure that ViewMediatorCallback#keyguardDonePending is called before - // ViewMediatorCallback#readyForKeyguardDone. The wrong order could occur - // when doing - // dismissKeyguardThenExecute { hideKeyguardWithAnimation(runner) }. - mMainExecutor.execute(() -> mKeyguardViewMediator.hideWithAnimation(runner)); - } - - @Override - public int getBackgroundColor(TaskInfo task) { - if (!mStartingSurfaceOptional.isPresent()) { - Log.w(TAG, "No starting surface, defaulting to SystemBGColor"); - return SplashscreenContentDrawer.getSystemBGColor(); - } - - return mStartingSurfaceOptional.get().getBackgroundColor(task); - } - }; - - private final ActivityLaunchAnimator.Listener mActivityLaunchAnimatorListener = - new ActivityLaunchAnimator.Listener() { - @Override - public void onLaunchAnimationStart() { - mKeyguardViewMediator.setBlursDisabledForAppLaunch(true); - } - - @Override - public void onLaunchAnimationEnd() { - mKeyguardViewMediator.setBlursDisabledForAppLaunch(false); - } - }; - - private final DemoMode mDemoModeCallback = new DemoMode() { - @Override - public void onDemoModeFinished() { - checkBarModes(); - } - - @Override - public void dispatchDemoCommand(String command, Bundle args) { } - }; - - /** - * Determines what UserHandle to use when launching an activity. - * - * We want to ensure that activities that are launched within the systemui process should be - * launched as user of the current process. - * @param intent - * @return UserHandle - */ - private UserHandle getActivityUserHandle(Intent intent) { - String[] packages = mContext.getResources().getStringArray(R.array.system_ui_packages); - for (String pkg : packages) { - if (intent.getComponent() == null) break; - if (pkg.equals(intent.getComponent().getPackageName())) { - return new UserHandle(UserHandle.myUserId()); - } - } - return UserHandle.CURRENT; } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java new file mode 100644 index 0000000000000..18092dccbd53b --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java @@ -0,0 +1,4536 @@ +/* + * Copyright (C) 2010 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 android.app.StatusBarManager.WINDOW_STATE_HIDDEN; +import static android.app.StatusBarManager.WINDOW_STATE_SHOWING; +import static android.app.StatusBarManager.WindowVisibleState; +import static android.app.StatusBarManager.windowStateToString; +import static android.view.InsetsState.ITYPE_STATUS_BAR; +import static android.view.InsetsState.containsType; +import static android.view.WindowInsetsController.APPEARANCE_LOW_PROFILE_BARS; +import static android.view.WindowInsetsController.APPEARANCE_OPAQUE_STATUS_BARS; +import static android.view.WindowInsetsController.APPEARANCE_SEMI_TRANSPARENT_STATUS_BARS; + +import static androidx.core.view.ViewCompat.IMPORTANT_FOR_ACCESSIBILITY_AUTO; +import static androidx.core.view.ViewCompat.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS; +import static androidx.lifecycle.Lifecycle.State.RESUMED; + +import static com.android.systemui.Dependency.TIME_TICK_HANDLER_NAME; +import static com.android.systemui.charging.WirelessChargingLayout.UNKNOWN_BATTERY_LEVEL; +import static com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_ASLEEP; +import static com.android.systemui.statusbar.NotificationLockscreenUserManager.PERMISSION_SELF; +import static com.android.systemui.statusbar.phone.BarTransitions.MODE_LIGHTS_OUT; +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_TRANSPARENT; +import static com.android.systemui.statusbar.phone.BarTransitions.TransitionMode; + +import android.annotation.Nullable; +import android.app.ActivityManager; +import android.app.ActivityOptions; +import android.app.ActivityTaskManager; +import android.app.IWallpaperManager; +import android.app.KeyguardManager; +import android.app.Notification; +import android.app.NotificationManager; +import android.app.PendingIntent; +import android.app.StatusBarManager; +import android.app.TaskInfo; +import android.app.TaskStackBuilder; +import android.app.UiModeManager; +import android.app.WallpaperInfo; +import android.app.WallpaperManager; +import android.app.admin.DevicePolicyManager; +import android.content.BroadcastReceiver; +import android.content.ComponentCallbacks2; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; +import android.content.res.Configuration; +import android.graphics.Point; +import android.graphics.PointF; +import android.hardware.devicestate.DeviceStateManager; +import android.metrics.LogMaker; +import android.net.Uri; +import android.os.Bundle; +import android.os.Handler; +import android.os.Looper; +import android.os.PowerManager; +import android.os.RemoteException; +import android.os.ServiceManager; +import android.os.SystemClock; +import android.os.SystemProperties; +import android.os.Trace; +import android.os.UserHandle; +import android.provider.Settings; +import android.service.dreams.DreamService; +import android.service.dreams.IDreamManager; +import android.service.notification.StatusBarNotification; +import android.text.TextUtils; +import android.util.ArraySet; +import android.util.DisplayMetrics; +import android.util.EventLog; +import android.util.IndentingPrintWriter; +import android.util.Log; +import android.util.MathUtils; +import android.util.Slog; +import android.view.Display; +import android.view.IRemoteAnimationRunner; +import android.view.IWindowManager; +import android.view.KeyEvent; +import android.view.MotionEvent; +import android.view.ThreadedRenderer; +import android.view.View; +import android.view.ViewGroup; +import android.view.WindowInsetsController.Appearance; +import android.view.WindowManager; +import android.view.WindowManagerGlobal; +import android.view.accessibility.AccessibilityManager; +import android.widget.DateTimeView; +import android.window.SplashScreen; + +import androidx.annotation.NonNull; +import androidx.lifecycle.Lifecycle; +import androidx.lifecycle.LifecycleRegistry; + +import com.android.internal.annotations.VisibleForTesting; +import com.android.internal.colorextraction.ColorExtractor; +import com.android.internal.jank.InteractionJankMonitor; +import com.android.internal.logging.MetricsLogger; +import com.android.internal.logging.UiEvent; +import com.android.internal.logging.UiEventLogger; +import com.android.internal.logging.UiEventLoggerImpl; +import com.android.internal.logging.nano.MetricsProto.MetricsEvent; +import com.android.internal.statusbar.IStatusBarService; +import com.android.internal.statusbar.RegisterStatusBarResult; +import com.android.keyguard.KeyguardUpdateMonitor; +import com.android.keyguard.KeyguardUpdateMonitorCallback; +import com.android.keyguard.ViewMediatorCallback; +import com.android.systemui.ActivityIntentHelper; +import com.android.systemui.AutoReinflateContainer; +import com.android.systemui.CoreStartable; +import com.android.systemui.DejankUtils; +import com.android.systemui.EventLogTags; +import com.android.systemui.InitController; +import com.android.systemui.Prefs; +import com.android.systemui.R; +import com.android.systemui.accessibility.floatingmenu.AccessibilityFloatingMenuController; +import com.android.systemui.animation.ActivityLaunchAnimator; +import com.android.systemui.animation.DelegateLaunchAnimatorController; +import com.android.systemui.assist.AssistManager; +import com.android.systemui.biometrics.AuthRippleController; +import com.android.systemui.broadcast.BroadcastDispatcher; +import com.android.systemui.camera.CameraIntents; +import com.android.systemui.charging.WirelessChargingAnimation; +import com.android.systemui.classifier.FalsingCollector; +import com.android.systemui.colorextraction.SysuiColorExtractor; +import com.android.systemui.dagger.SysUISingleton; +import com.android.systemui.dagger.qualifiers.Main; +import com.android.systemui.dagger.qualifiers.UiBackground; +import com.android.systemui.demomode.DemoMode; +import com.android.systemui.demomode.DemoModeController; +import com.android.systemui.dreams.DreamOverlayStateController; +import com.android.systemui.emergency.EmergencyGesture; +import com.android.systemui.flags.FeatureFlags; +import com.android.systemui.flags.Flags; +import com.android.systemui.fragments.ExtensionFragmentListener; +import com.android.systemui.fragments.FragmentHostManager; +import com.android.systemui.fragments.FragmentService; +import com.android.systemui.keyguard.KeyguardService; +import com.android.systemui.keyguard.KeyguardUnlockAnimationController; +import com.android.systemui.keyguard.KeyguardViewMediator; +import com.android.systemui.keyguard.ScreenLifecycle; +import com.android.systemui.keyguard.WakefulnessLifecycle; +import com.android.systemui.navigationbar.NavigationBarController; +import com.android.systemui.navigationbar.NavigationBarView; +import com.android.systemui.plugins.DarkIconDispatcher; +import com.android.systemui.plugins.FalsingManager; +import com.android.systemui.plugins.OverlayPlugin; +import com.android.systemui.plugins.PluginDependencyProvider; +import com.android.systemui.plugins.PluginListener; +import com.android.systemui.plugins.qs.QS; +import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper.SnoozeOption; +import com.android.systemui.plugins.statusbar.StatusBarStateController; +import com.android.systemui.qs.QSFragment; +import com.android.systemui.qs.QSPanelController; +import com.android.systemui.recents.ScreenPinningRequest; +import com.android.systemui.scrim.ScrimView; +import com.android.systemui.settings.brightness.BrightnessSliderController; +import com.android.systemui.shared.plugins.PluginManager; +import com.android.systemui.statusbar.AutoHideUiElement; +import com.android.systemui.statusbar.BackDropView; +import com.android.systemui.statusbar.CircleReveal; +import com.android.systemui.statusbar.CommandQueue; +import com.android.systemui.statusbar.GestureRecorder; +import com.android.systemui.statusbar.KeyboardShortcuts; +import com.android.systemui.statusbar.KeyguardIndicationController; +import com.android.systemui.statusbar.LiftReveal; +import com.android.systemui.statusbar.LightRevealScrim; +import com.android.systemui.statusbar.LockscreenShadeTransitionController; +import com.android.systemui.statusbar.NotificationLockscreenUserManager; +import com.android.systemui.statusbar.NotificationMediaManager; +import com.android.systemui.statusbar.NotificationPresenter; +import com.android.systemui.statusbar.NotificationRemoteInputManager; +import com.android.systemui.statusbar.NotificationShadeDepthController; +import com.android.systemui.statusbar.NotificationShadeWindowController; +import com.android.systemui.statusbar.NotificationShelfController; +import com.android.systemui.statusbar.NotificationViewHierarchyManager; +import com.android.systemui.statusbar.PowerButtonReveal; +import com.android.systemui.statusbar.PulseExpansionHandler; +import com.android.systemui.statusbar.StatusBarState; +import com.android.systemui.statusbar.SysuiStatusBarStateController; +import com.android.systemui.statusbar.charging.WiredChargingRippleController; +import com.android.systemui.statusbar.connectivity.NetworkController; +import com.android.systemui.statusbar.core.StatusBarInitializer; +import com.android.systemui.statusbar.notification.DynamicPrivacyController; +import com.android.systemui.statusbar.notification.NotifPipelineFlags; +import com.android.systemui.statusbar.notification.NotificationActivityStarter; +import com.android.systemui.statusbar.notification.NotificationEntryManager; +import com.android.systemui.statusbar.notification.NotificationLaunchAnimatorControllerProvider; +import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator; +import com.android.systemui.statusbar.notification.collection.legacy.VisualStabilityManager; +import com.android.systemui.statusbar.notification.collection.render.NotifShadeEventSource; +import com.android.systemui.statusbar.notification.init.NotificationsController; +import com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProvider; +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.notification.stack.NotificationStackScrollLayout; +import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController; +import com.android.systemui.statusbar.phone.dagger.CentralSurfacesComponent; +import com.android.systemui.statusbar.phone.dagger.StatusBarPhoneModule; +import com.android.systemui.statusbar.phone.ongoingcall.OngoingCallController; +import com.android.systemui.statusbar.phone.panelstate.PanelExpansionChangeEvent; +import com.android.systemui.statusbar.phone.panelstate.PanelExpansionStateManager; +import com.android.systemui.statusbar.policy.BatteryController; +import com.android.systemui.statusbar.policy.BrightnessMirrorController; +import com.android.systemui.statusbar.policy.ConfigurationController; +import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener; +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.KeyguardStateController; +import com.android.systemui.statusbar.policy.UserInfoControllerImpl; +import com.android.systemui.statusbar.policy.UserSwitcherController; +import com.android.systemui.statusbar.window.StatusBarWindowController; +import com.android.systemui.statusbar.window.StatusBarWindowStateController; +import com.android.systemui.util.DumpUtilsKt; +import com.android.systemui.util.WallpaperController; +import com.android.systemui.util.concurrency.DelayableExecutor; +import com.android.systemui.util.concurrency.MessageRouter; +import com.android.systemui.volume.VolumeComponent; +import com.android.systemui.wmshell.BubblesManager; +import com.android.wm.shell.bubbles.Bubbles; +import com.android.wm.shell.startingsurface.SplashscreenContentDrawer; +import com.android.wm.shell.startingsurface.StartingSurface; + +import java.io.PrintWriter; +import java.io.StringWriter; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.concurrent.Executor; + +import javax.inject.Inject; +import javax.inject.Named; + +import dagger.Lazy; + +/** + * A class handling initialization and coordination between some of the key central surfaces in + * System UI: The notification shade, the keyguard (lockscreen), and the status bar. + * + * This class is not our ideal architecture because it doesn't enforce much isolation between these + * three mostly disparate surfaces. In an ideal world, this class would not exist. Instead, we would + * break it up into three modules -- one for each of those three surfaces -- and we would define any + * APIs that are needed for these surfaces to communicate with each other when necessary. + * + * If at all possible, please avoid adding additional code to this monstrous class! Our goal is + * to break up this class into many small classes, and any code added here will slow down that goal. + * + */ +@SysUISingleton +public class CentralSurfacesImpl extends CoreStartable implements + CentralSurfaces { + + private static final String BANNER_ACTION_CANCEL = + "com.android.systemui.statusbar.banner_action_cancel"; + private static final String BANNER_ACTION_SETUP = + "com.android.systemui.statusbar.banner_action_setup"; + + private static final int MSG_OPEN_SETTINGS_PANEL = 1002; + private static final int MSG_LAUNCH_TRANSITION_TIMEOUT = 1003; + // 1020-1040 reserved for BaseStatusBar + + /** + * The delay to reset the hint text when the hint animation is finished running. + */ + private static final int HINT_RESET_DELAY_MS = 1200; + + /** If true, the lockscreen will show a distinct wallpaper */ + public static final boolean ENABLE_LOCKSCREEN_WALLPAPER = true; + + private static final UiEventLogger sUiEventLogger = new UiEventLoggerImpl(); + + private final LockscreenShadeTransitionController mLockscreenShadeTransitionController; + private final DreamOverlayStateController mDreamOverlayStateController; + private CentralSurfacesCommandQueueCallbacks mCommandQueueCallbacks; + private float mTransitionToFullShadeProgress = 0f; + private NotificationListContainer mNotifListContainer; + + private final KeyguardStateController.Callback mKeyguardStateControllerCallback = + new KeyguardStateController.Callback() { + @Override + public void onKeyguardShowingChanged() { + boolean occluded = mKeyguardStateController.isOccluded(); + mStatusBarHideIconsForBouncerManager.setIsOccludedAndTriggerUpdate(occluded); + mScrimController.setKeyguardOccluded(occluded); + } + }; + + void onStatusBarWindowStateChanged(@WindowVisibleState int state) { + updateBubblesVisibility(); + mStatusBarWindowState = state; + } + + @Override + public void acquireGestureWakeLock(long time) { + mGestureWakeLock.acquire(time); + } + + @Override + public boolean setAppearance(int appearance) { + if (mAppearance != appearance) { + mAppearance = appearance; + return updateBarMode(barMode(isTransientShown(), appearance)); + } + + return false; + } + + @Override + public int getBarMode() { + return mStatusBarMode; + } + + @Override + public void resendMessage(int msg) { + mMessageRouter.cancelMessages(msg); + mMessageRouter.sendMessage(msg); + } + + @Override + public void resendMessage(Object msg) { + mMessageRouter.cancelMessages(msg.getClass()); + mMessageRouter.sendMessage(msg); + } + + @Override + public int getDisabled1() { + return mDisabled1; + } + + @Override + public void setDisabled1(int disabled) { + mDisabled1 = disabled; + } + + @Override + public int getDisabled2() { + return mDisabled2; + } + + @Override + public void setDisabled2(int disabled) { + mDisabled2 = disabled; + } + + @Override + public void setLastCameraLaunchSource(int source) { + mLastCameraLaunchSource = source; + } + + @Override + public void setLaunchCameraOnFinishedGoingToSleep(boolean launch) { + mLaunchCameraOnFinishedGoingToSleep = launch; + } + + @Override + public void setLaunchCameraOnFinishedWaking(boolean launch) { + mLaunchCameraWhenFinishedWaking = launch; + } + + @Override + public void setLaunchEmergencyActionOnFinishedGoingToSleep(boolean launch) { + mLaunchEmergencyActionOnFinishedGoingToSleep = launch; + } + + @Override + public void setLaunchEmergencyActionOnFinishedWaking(boolean launch) { + mLaunchEmergencyActionWhenFinishedWaking = launch; + } + + @Override + public void setTopHidesStatusBar(boolean hides) { + mTopHidesStatusBar = hides; + } + + @Override + public QSPanelController getQSPanelController() { + return mQSPanelController; + } + + /** */ + @Override + public void animateExpandNotificationsPanel() { + mCommandQueueCallbacks.animateExpandNotificationsPanel(); + } + + /** */ + @Override + public void animateExpandSettingsPanel(@Nullable String subpanel) { + mCommandQueueCallbacks.animateExpandSettingsPanel(subpanel); + } + + /** */ + @Override + public void animateCollapsePanels(int flags, boolean force) { + mCommandQueueCallbacks.animateCollapsePanels(flags, force); + } + + /** */ + @Override + public void togglePanel() { + mCommandQueueCallbacks.togglePanel(); + } + /** + * The {@link StatusBarState} of the status bar. + */ + protected int mState; // TODO: remove this. Just use StatusBarStateController + protected boolean mBouncerShowing; + private boolean mBouncerShowingOverDream; + + private final PhoneStatusBarPolicy mIconPolicy; + + private final VolumeComponent mVolumeComponent; + private BrightnessMirrorController mBrightnessMirrorController; + private boolean mBrightnessMirrorVisible; + private BiometricUnlockController mBiometricUnlockController; + private final LightBarController mLightBarController; + private final Lazy mLockscreenWallpaperLazy; + private final LockscreenGestureLogger mLockscreenGestureLogger; + @Nullable + protected LockscreenWallpaper mLockscreenWallpaper; + private final AutoHideController mAutoHideController; + + private final Point mCurrentDisplaySize = new Point(); + + protected NotificationShadeWindowView mNotificationShadeWindowView; + protected PhoneStatusBarView mStatusBarView; + private PhoneStatusBarViewController mPhoneStatusBarViewController; + private PhoneStatusBarTransitions mStatusBarTransitions; + private AuthRippleController mAuthRippleController; + @WindowVisibleState private int mStatusBarWindowState = WINDOW_STATE_SHOWING; + protected final NotificationShadeWindowController mNotificationShadeWindowController; + private final StatusBarWindowController mStatusBarWindowController; + private final KeyguardUpdateMonitor mKeyguardUpdateMonitor; + @VisibleForTesting + DozeServiceHost mDozeServiceHost; + private boolean mWakeUpComingFromTouch; + private PointF mWakeUpTouchLocation; + private LightRevealScrim mLightRevealScrim; + private PowerButtonReveal mPowerButtonReveal; + + private final Object mQueueLock = new Object(); + + private final PulseExpansionHandler mPulseExpansionHandler; + private final NotificationWakeUpCoordinator mWakeUpCoordinator; + private final KeyguardBypassController mKeyguardBypassController; + private final KeyguardStateController mKeyguardStateController; + private final HeadsUpManagerPhone mHeadsUpManager; + private final StatusBarTouchableRegionManager mStatusBarTouchableRegionManager; + private final DynamicPrivacyController mDynamicPrivacyController; + private final FalsingCollector mFalsingCollector; + private final FalsingManager mFalsingManager; + private final BroadcastDispatcher mBroadcastDispatcher; + private final ConfigurationController mConfigurationController; + protected NotificationShadeWindowViewController mNotificationShadeWindowViewController; + private final DozeParameters mDozeParameters; + private final Lazy mBiometricUnlockControllerLazy; + private final CentralSurfacesComponent.Factory mCentralSurfacesComponentFactory; + private final PluginManager mPluginManager; + private final ShadeController mShadeController; + private final InitController mInitController; + + private final PluginDependencyProvider mPluginDependencyProvider; + private final KeyguardDismissUtil mKeyguardDismissUtil; + private final ExtensionController mExtensionController; + private final UserInfoControllerImpl mUserInfoControllerImpl; + private final DemoModeController mDemoModeController; + private final NotificationsController mNotificationsController; + private final OngoingCallController mOngoingCallController; + private final StatusBarSignalPolicy mStatusBarSignalPolicy; + private final StatusBarHideIconsForBouncerManager mStatusBarHideIconsForBouncerManager; + + // expanded notifications + // the sliding/resizing panel within the notification window + protected NotificationPanelViewController mNotificationPanelViewController; + + // settings + private QSPanelController mQSPanelController; + + KeyguardIndicationController mKeyguardIndicationController; + + private View mReportRejectedTouch; + + private boolean mExpandedVisible; + + private final int[] mAbsPos = new int[2]; + + private final NotifShadeEventSource mNotifShadeEventSource; + protected final NotificationEntryManager mEntryManager; + private final NotificationGutsManager mGutsManager; + private final NotificationLogger mNotificationLogger; + private final NotificationViewHierarchyManager mViewHierarchyManager; + private final PanelExpansionStateManager mPanelExpansionStateManager; + private final KeyguardViewMediator mKeyguardViewMediator; + protected final NotificationInterruptStateProvider mNotificationInterruptStateProvider; + private final BrightnessSliderController.Factory mBrightnessSliderFactory; + private final FeatureFlags mFeatureFlags; + private final FragmentService mFragmentService; + private final ScreenOffAnimationController mScreenOffAnimationController; + private final WallpaperController mWallpaperController; + private final KeyguardUnlockAnimationController mKeyguardUnlockAnimationController; + private final MessageRouter mMessageRouter; + private final WallpaperManager mWallpaperManager; + + private CentralSurfacesComponent mCentralSurfacesComponent; + + // Flags for disabling the status bar + // Two variables becaseu the first one evidently ran out of room for new flags. + private int mDisabled1 = 0; + private int mDisabled2 = 0; + + /** @see android.view.WindowInsetsController#setSystemBarsAppearance(int, int) */ + private @Appearance int mAppearance; + + private boolean mTransientShown; + + private final DisplayMetrics mDisplayMetrics; + + // XXX: gesture research + private final GestureRecorder mGestureRec = DEBUG_GESTURES + ? new GestureRecorder("/sdcard/statusbar_gestures.dat") + : null; + + private final ScreenPinningRequest mScreenPinningRequest; + + private final MetricsLogger mMetricsLogger; + + // ensure quick settings is disabled until the current user makes it through the setup wizard + @VisibleForTesting + protected boolean mUserSetup = false; + + @VisibleForTesting + public enum StatusBarUiEvent implements UiEventLogger.UiEventEnum { + @UiEvent(doc = "Secured lockscreen is opened.") + LOCKSCREEN_OPEN_SECURE(405), + + @UiEvent(doc = "Lockscreen without security is opened.") + LOCKSCREEN_OPEN_INSECURE(406), + + @UiEvent(doc = "Secured lockscreen is closed.") + LOCKSCREEN_CLOSE_SECURE(407), + + @UiEvent(doc = "Lockscreen without security is closed.") + LOCKSCREEN_CLOSE_INSECURE(408), + + @UiEvent(doc = "Secured bouncer is opened.") + BOUNCER_OPEN_SECURE(409), + + @UiEvent(doc = "Bouncer without security is opened.") + BOUNCER_OPEN_INSECURE(410), + + @UiEvent(doc = "Secured bouncer is closed.") + BOUNCER_CLOSE_SECURE(411), + + @UiEvent(doc = "Bouncer without security is closed.") + BOUNCER_CLOSE_INSECURE(412); + + private final int mId; + + StatusBarUiEvent(int id) { + mId = id; + } + + @Override + public int getId() { + return mId; + } + } + + private Handler mMainHandler; + private final DelayableExecutor mMainExecutor; + + private int mInteractingWindows; + private @TransitionMode int mStatusBarMode; + + private final ViewMediatorCallback mKeyguardViewMediatorCallback; + private final ScrimController mScrimController; + protected DozeScrimController mDozeScrimController; + private final Executor mUiBgExecutor; + + protected boolean mDozing; + private boolean mIsFullscreen; + + boolean mCloseQsBeforeScreenOff; + + private final NotificationMediaManager mMediaManager; + private final NotificationLockscreenUserManager mLockscreenUserManager; + private final NotificationRemoteInputManager mRemoteInputManager; + private boolean mWallpaperSupported; + + private Runnable mLaunchTransitionEndRunnable; + private Runnable mLaunchTransitionCancelRunnable; + private boolean mLaunchCameraWhenFinishedWaking; + private boolean mLaunchCameraOnFinishedGoingToSleep; + private boolean mLaunchEmergencyActionWhenFinishedWaking; + private boolean mLaunchEmergencyActionOnFinishedGoingToSleep; + private int mLastCameraLaunchSource; + protected PowerManager.WakeLock mGestureWakeLock; + + private final int[] mTmpInt2 = new int[2]; + + // Fingerprint (as computed by getLoggingFingerprint() of the last logged state. + private int mLastLoggedStateFingerprint; + private boolean mTopHidesStatusBar; + private boolean mStatusBarWindowHidden; + private boolean mIsLaunchingActivityOverLockscreen; + + private final UserSwitcherController mUserSwitcherController; + private final NetworkController mNetworkController; + private final LifecycleRegistry mLifecycle = new LifecycleRegistry(this); + protected final BatteryController mBatteryController; + protected boolean mPanelExpanded; + private UiModeManager mUiModeManager; + private LogMaker mStatusBarStateLog; + protected final NotificationIconAreaController mNotificationIconAreaController; + @Nullable private View mAmbientIndicationContainer; + private final SysuiColorExtractor mColorExtractor; + private final ScreenLifecycle mScreenLifecycle; + private final WakefulnessLifecycle mWakefulnessLifecycle; + + private boolean mNoAnimationOnNextBarModeChange; + private final SysuiStatusBarStateController mStatusBarStateController; + + private final ActivityLaunchAnimator mActivityLaunchAnimator; + private NotificationLaunchAnimatorControllerProvider mNotificationAnimationProvider; + protected NotificationPresenter mPresenter; + private NotificationActivityStarter mNotificationActivityStarter; + private final Lazy mNotificationShadeDepthControllerLazy; + private final Optional mBubblesManagerOptional; + private final Optional mBubblesOptional; + private final Bubbles.BubbleExpandListener mBubbleExpandListener; + private final Optional mStartingSurfaceOptional; + private final NotifPipelineFlags mNotifPipelineFlags; + + private final ActivityIntentHelper mActivityIntentHelper; + private NotificationStackScrollLayoutController mStackScrollerController; + + private final ColorExtractor.OnColorsChangedListener mOnColorsChangedListener = + (extractor, which) -> updateTheme(); + + private final InteractionJankMonitor mJankMonitor; + + + /** + * Public constructor for CentralSurfaces. + * + * CentralSurfaces is considered optional, and therefore can not be marked as @Inject directly. + * Instead, an @Provide method is included. See {@link StatusBarPhoneModule}. + */ + @SuppressWarnings("OptionalUsedAsFieldOrParameterType") + @Inject + public CentralSurfacesImpl( + Context context, + NotificationsController notificationsController, + FragmentService fragmentService, + LightBarController lightBarController, + AutoHideController autoHideController, + StatusBarWindowController statusBarWindowController, + StatusBarWindowStateController statusBarWindowStateController, + KeyguardUpdateMonitor keyguardUpdateMonitor, + StatusBarSignalPolicy statusBarSignalPolicy, + PulseExpansionHandler pulseExpansionHandler, + NotificationWakeUpCoordinator notificationWakeUpCoordinator, + KeyguardBypassController keyguardBypassController, + KeyguardStateController keyguardStateController, + HeadsUpManagerPhone headsUpManagerPhone, + DynamicPrivacyController dynamicPrivacyController, + FalsingManager falsingManager, + FalsingCollector falsingCollector, + BroadcastDispatcher broadcastDispatcher, + NotifShadeEventSource notifShadeEventSource, + NotificationEntryManager notificationEntryManager, + NotificationGutsManager notificationGutsManager, + NotificationLogger notificationLogger, + NotificationInterruptStateProvider notificationInterruptStateProvider, + NotificationViewHierarchyManager notificationViewHierarchyManager, + PanelExpansionStateManager panelExpansionStateManager, + KeyguardViewMediator keyguardViewMediator, + DisplayMetrics displayMetrics, + MetricsLogger metricsLogger, + @UiBackground Executor uiBgExecutor, + NotificationMediaManager notificationMediaManager, + NotificationLockscreenUserManager lockScreenUserManager, + NotificationRemoteInputManager remoteInputManager, + UserSwitcherController userSwitcherController, + NetworkController networkController, + BatteryController batteryController, + SysuiColorExtractor colorExtractor, + ScreenLifecycle screenLifecycle, + WakefulnessLifecycle wakefulnessLifecycle, + SysuiStatusBarStateController statusBarStateController, + Optional bubblesManagerOptional, + Optional bubblesOptional, + VisualStabilityManager visualStabilityManager, + DeviceProvisionedController deviceProvisionedController, + NavigationBarController navigationBarController, + AccessibilityFloatingMenuController accessibilityFloatingMenuController, + Lazy assistManagerLazy, + ConfigurationController configurationController, + NotificationShadeWindowController notificationShadeWindowController, + DozeParameters dozeParameters, + ScrimController scrimController, + Lazy lockscreenWallpaperLazy, + LockscreenGestureLogger lockscreenGestureLogger, + Lazy biometricUnlockControllerLazy, + DozeServiceHost dozeServiceHost, + PowerManager powerManager, + ScreenPinningRequest screenPinningRequest, + DozeScrimController dozeScrimController, + VolumeComponent volumeComponent, + CommandQueue commandQueue, + CentralSurfacesComponent.Factory centralSurfacesComponentFactory, + PluginManager pluginManager, + ShadeController shadeController, + StatusBarKeyguardViewManager statusBarKeyguardViewManager, + ViewMediatorCallback viewMediatorCallback, + InitController initController, + @Named(TIME_TICK_HANDLER_NAME) Handler timeTickHandler, + PluginDependencyProvider pluginDependencyProvider, + KeyguardDismissUtil keyguardDismissUtil, + ExtensionController extensionController, + UserInfoControllerImpl userInfoControllerImpl, + PhoneStatusBarPolicy phoneStatusBarPolicy, + KeyguardIndicationController keyguardIndicationController, + DemoModeController demoModeController, + Lazy notificationShadeDepthControllerLazy, + StatusBarTouchableRegionManager statusBarTouchableRegionManager, + NotificationIconAreaController notificationIconAreaController, + BrightnessSliderController.Factory brightnessSliderFactory, + ScreenOffAnimationController screenOffAnimationController, + WallpaperController wallpaperController, + OngoingCallController ongoingCallController, + StatusBarHideIconsForBouncerManager statusBarHideIconsForBouncerManager, + LockscreenShadeTransitionController lockscreenShadeTransitionController, + FeatureFlags featureFlags, + KeyguardUnlockAnimationController keyguardUnlockAnimationController, + @Main Handler mainHandler, + @Main DelayableExecutor delayableExecutor, + @Main MessageRouter messageRouter, + WallpaperManager wallpaperManager, + Optional startingSurfaceOptional, + ActivityLaunchAnimator activityLaunchAnimator, + NotifPipelineFlags notifPipelineFlags, + InteractionJankMonitor jankMonitor, + DeviceStateManager deviceStateManager, + DreamOverlayStateController dreamOverlayStateController, + WiredChargingRippleController wiredChargingRippleController) { + super(context); + mNotificationsController = notificationsController; + mFragmentService = fragmentService; + mLightBarController = lightBarController; + mAutoHideController = autoHideController; + mStatusBarWindowController = statusBarWindowController; + mKeyguardUpdateMonitor = keyguardUpdateMonitor; + mPulseExpansionHandler = pulseExpansionHandler; + mWakeUpCoordinator = notificationWakeUpCoordinator; + mKeyguardBypassController = keyguardBypassController; + mKeyguardStateController = keyguardStateController; + mHeadsUpManager = headsUpManagerPhone; + mKeyguardIndicationController = keyguardIndicationController; + mStatusBarTouchableRegionManager = statusBarTouchableRegionManager; + mDynamicPrivacyController = dynamicPrivacyController; + mFalsingCollector = falsingCollector; + mFalsingManager = falsingManager; + mBroadcastDispatcher = broadcastDispatcher; + mNotifShadeEventSource = notifShadeEventSource; + mEntryManager = notificationEntryManager; + mGutsManager = notificationGutsManager; + mNotificationLogger = notificationLogger; + mNotificationInterruptStateProvider = notificationInterruptStateProvider; + mViewHierarchyManager = notificationViewHierarchyManager; + mPanelExpansionStateManager = panelExpansionStateManager; + mKeyguardViewMediator = keyguardViewMediator; + mDisplayMetrics = displayMetrics; + mMetricsLogger = metricsLogger; + mUiBgExecutor = uiBgExecutor; + mMediaManager = notificationMediaManager; + mLockscreenUserManager = lockScreenUserManager; + mRemoteInputManager = remoteInputManager; + mUserSwitcherController = userSwitcherController; + mNetworkController = networkController; + mBatteryController = batteryController; + mColorExtractor = colorExtractor; + mScreenLifecycle = screenLifecycle; + mWakefulnessLifecycle = wakefulnessLifecycle; + mStatusBarStateController = statusBarStateController; + mBubblesManagerOptional = bubblesManagerOptional; + mBubblesOptional = bubblesOptional; + mVisualStabilityManager = visualStabilityManager; + mDeviceProvisionedController = deviceProvisionedController; + mNavigationBarController = navigationBarController; + mAccessibilityFloatingMenuController = accessibilityFloatingMenuController; + mAssistManagerLazy = assistManagerLazy; + mConfigurationController = configurationController; + mNotificationShadeWindowController = notificationShadeWindowController; + mDozeServiceHost = dozeServiceHost; + mPowerManager = powerManager; + mDozeParameters = dozeParameters; + mScrimController = scrimController; + mLockscreenWallpaperLazy = lockscreenWallpaperLazy; + mLockscreenGestureLogger = lockscreenGestureLogger; + mScreenPinningRequest = screenPinningRequest; + mDozeScrimController = dozeScrimController; + mBiometricUnlockControllerLazy = biometricUnlockControllerLazy; + mNotificationShadeDepthControllerLazy = notificationShadeDepthControllerLazy; + mVolumeComponent = volumeComponent; + mCommandQueue = commandQueue; + mCentralSurfacesComponentFactory = centralSurfacesComponentFactory; + mPluginManager = pluginManager; + mShadeController = shadeController; + mStatusBarKeyguardViewManager = statusBarKeyguardViewManager; + mKeyguardViewMediatorCallback = viewMediatorCallback; + mInitController = initController; + mPluginDependencyProvider = pluginDependencyProvider; + mKeyguardDismissUtil = keyguardDismissUtil; + mExtensionController = extensionController; + mUserInfoControllerImpl = userInfoControllerImpl; + mIconPolicy = phoneStatusBarPolicy; + mDemoModeController = demoModeController; + mNotificationIconAreaController = notificationIconAreaController; + mBrightnessSliderFactory = brightnessSliderFactory; + mWallpaperController = wallpaperController; + mOngoingCallController = ongoingCallController; + mStatusBarSignalPolicy = statusBarSignalPolicy; + mStatusBarHideIconsForBouncerManager = statusBarHideIconsForBouncerManager; + mFeatureFlags = featureFlags; + mKeyguardUnlockAnimationController = keyguardUnlockAnimationController; + mMainHandler = mainHandler; + mMainExecutor = delayableExecutor; + mMessageRouter = messageRouter; + mWallpaperManager = wallpaperManager; + mJankMonitor = jankMonitor; + mDreamOverlayStateController = dreamOverlayStateController; + + mLockscreenShadeTransitionController = lockscreenShadeTransitionController; + mStartingSurfaceOptional = startingSurfaceOptional; + mNotifPipelineFlags = notifPipelineFlags; + lockscreenShadeTransitionController.setCentralSurfaces(this); + statusBarWindowStateController.addListener(this::onStatusBarWindowStateChanged); + + mScreenOffAnimationController = screenOffAnimationController; + + mPanelExpansionStateManager.addExpansionListener(this::onPanelExpansionChanged); + + mBubbleExpandListener = + (isExpanding, key) -> mContext.getMainExecutor().execute(() -> { + mNotificationsController.requestNotificationUpdate("onBubbleExpandChanged"); + updateScrimController(); + }); + + mActivityIntentHelper = new ActivityIntentHelper(mContext); + mActivityLaunchAnimator = activityLaunchAnimator; + + // The status bar background may need updating when the ongoing call status changes. + mOngoingCallController.addCallback((animate) -> maybeUpdateBarMode()); + + // TODO(b/190746471): Find a better home for this. + DateTimeView.setReceiverHandler(timeTickHandler); + + mMessageRouter.subscribeTo(KeyboardShortcutsMessage.class, + data -> toggleKeyboardShortcuts(data.mDeviceId)); + mMessageRouter.subscribeTo(MSG_DISMISS_KEYBOARD_SHORTCUTS_MENU, + id -> dismissKeyboardShortcuts()); + mMessageRouter.subscribeTo(AnimateExpandSettingsPanelMessage.class, + data -> mCommandQueueCallbacks.animateExpandSettingsPanel(data.mSubpanel)); + mMessageRouter.subscribeTo(MSG_LAUNCH_TRANSITION_TIMEOUT, + id -> onLaunchTransitionTimeout()); + + deviceStateManager.registerCallback(mMainExecutor, + new FoldStateListener(mContext, this::onFoldedStateChanged)); + wiredChargingRippleController.registerCallbacks(); + } + + @Override + public void start() { + mScreenLifecycle.addObserver(mScreenObserver); + mWakefulnessLifecycle.addObserver(mWakefulnessObserver); + mUiModeManager = mContext.getSystemService(UiModeManager.class); + if (mBubblesOptional.isPresent()) { + mBubblesOptional.get().setExpandListener(mBubbleExpandListener); + } + + mStatusBarSignalPolicy.init(); + mKeyguardIndicationController.init(); + + mColorExtractor.addOnColorsChangedListener(mOnColorsChangedListener); + mStatusBarStateController.addCallback(mStateListener, + SysuiStatusBarStateController.RANK_STATUS_BAR); + + mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE); + mDreamManager = IDreamManager.Stub.asInterface( + ServiceManager.checkService(DreamService.DREAM_SERVICE)); + + mDisplay = mContext.getDisplay(); + mDisplayId = mDisplay.getDisplayId(); + updateDisplaySize(); + mStatusBarHideIconsForBouncerManager.setDisplayId(mDisplayId); + + // start old BaseStatusBar.start(). + mWindowManagerService = WindowManagerGlobal.getWindowManagerService(); + mDevicePolicyManager = (DevicePolicyManager) mContext.getSystemService( + Context.DEVICE_POLICY_SERVICE); + + mAccessibilityManager = (AccessibilityManager) + mContext.getSystemService(Context.ACCESSIBILITY_SERVICE); + + mKeyguardUpdateMonitor.setKeyguardBypassController(mKeyguardBypassController); + mBarService = IStatusBarService.Stub.asInterface( + ServiceManager.getService(Context.STATUS_BAR_SERVICE)); + + mKeyguardManager = (KeyguardManager) mContext.getSystemService(Context.KEYGUARD_SERVICE); + mWallpaperSupported = mWallpaperManager.isWallpaperSupported(); + + RegisterStatusBarResult result = null; + try { + result = mBarService.registerStatusBar(mCommandQueue); + } catch (RemoteException ex) { + ex.rethrowFromSystemServer(); + } + + createAndAddWindows(result); + + if (mWallpaperSupported) { + // Make sure we always have the most current wallpaper info. + IntentFilter wallpaperChangedFilter = new IntentFilter(Intent.ACTION_WALLPAPER_CHANGED); + mBroadcastDispatcher.registerReceiver(mWallpaperChangedReceiver, wallpaperChangedFilter, + null /* handler */, UserHandle.ALL); + mWallpaperChangedReceiver.onReceive(mContext, null); + } else if (DEBUG) { + Log.v(TAG, "start(): no wallpaper service "); + } + + // Set up the initial notification state. This needs to happen before CommandQueue.disable() + setUpPresenter(); + + if (containsType(result.mTransientBarTypes, ITYPE_STATUS_BAR)) { + showTransientUnchecked(); + } + mCommandQueueCallbacks.onSystemBarAttributesChanged(mDisplayId, result.mAppearance, + result.mAppearanceRegions, result.mNavbarColorManagedByIme, result.mBehavior, + result.mRequestedVisibilities, result.mPackageName); + + // StatusBarManagerService has a back up of IME token and it's restored here. + mCommandQueueCallbacks.setImeWindowStatus(mDisplayId, result.mImeToken, + result.mImeWindowVis, result.mImeBackDisposition, result.mShowImeSwitcher); + + // Set up the initial icon state + int numIcons = result.mIcons.size(); + for (int i = 0; i < numIcons; i++) { + mCommandQueue.setIcon(result.mIcons.keyAt(i), result.mIcons.valueAt(i)); + } + + if (DEBUG) { + Log.d(TAG, String.format( + "init: icons=%d disabled=0x%08x lights=0x%08x imeButton=0x%08x", + numIcons, + result.mDisabledFlags1, + result.mAppearance, + result.mImeWindowVis)); + } + + IntentFilter internalFilter = new IntentFilter(); + internalFilter.addAction(BANNER_ACTION_CANCEL); + internalFilter.addAction(BANNER_ACTION_SETUP); + mContext.registerReceiver(mBannerActionBroadcastReceiver, internalFilter, PERMISSION_SELF, + null, Context.RECEIVER_EXPORTED_UNAUDITED); + + if (mWallpaperSupported) { + IWallpaperManager wallpaperManager = IWallpaperManager.Stub.asInterface( + ServiceManager.getService(Context.WALLPAPER_SERVICE)); + try { + wallpaperManager.setInAmbientMode(false /* ambientMode */, 0L /* duration */); + } catch (RemoteException e) { + // Just pass, nothing critical. + } + } + + // end old BaseStatusBar.start(). + + // Lastly, call to the icon policy to install/update all the icons. + mIconPolicy.init(); + + mKeyguardStateController.addCallback(new KeyguardStateController.Callback() { + @Override + public void onUnlockedChanged() { + logStateToEventlog(); + } + }); + startKeyguard(); + + mKeyguardUpdateMonitor.registerCallback(mUpdateCallback); + mDozeServiceHost.initialize( + this, + mStatusBarKeyguardViewManager, + mNotificationShadeWindowViewController, + mNotificationPanelViewController, + mAmbientIndicationContainer); + updateLightRevealScrimVisibility(); + + mConfigurationController.addCallback(mConfigurationListener); + + mBatteryController.observe(mLifecycle, mBatteryStateChangeCallback); + mLifecycle.setCurrentState(RESUMED); + + mAccessibilityFloatingMenuController.init(); + + // set the initial view visibility + int disabledFlags1 = result.mDisabledFlags1; + int disabledFlags2 = result.mDisabledFlags2; + mInitController.addPostInitTask( + () -> setUpDisableFlags(disabledFlags1, disabledFlags2)); + + mFalsingManager.addFalsingBeliefListener(mFalsingBeliefListener); + + mPluginManager.addPluginListener( + new PluginListener() { + private final ArraySet mOverlays = new ArraySet<>(); + + @Override + public void onPluginConnected(OverlayPlugin plugin, Context pluginContext) { + mMainExecutor.execute( + () -> plugin.setup(getNotificationShadeWindowView(), + getNavigationBarView(), + new Callback(plugin), mDozeParameters)); + } + + @Override + public void onPluginDisconnected(OverlayPlugin plugin) { + mMainExecutor.execute(() -> { + mOverlays.remove(plugin); + mNotificationShadeWindowController + .setForcePluginOpen(mOverlays.size() != 0, this); + }); + } + + class Callback implements OverlayPlugin.Callback { + private final OverlayPlugin mPlugin; + + Callback(OverlayPlugin plugin) { + mPlugin = plugin; + } + + @Override + public void onHoldStatusBarOpenChange() { + if (mPlugin.holdStatusBarOpen()) { + mOverlays.add(mPlugin); + } else { + mOverlays.remove(mPlugin); + } + mMainExecutor.execute(() -> { + mNotificationShadeWindowController + .setStateListener(b -> mOverlays.forEach( + o -> o.setCollapseDesired(b))); + mNotificationShadeWindowController + .setForcePluginOpen(mOverlays.size() != 0, this); + }); + } + } + }, OverlayPlugin.class, true /* Allow multiple plugins */); + + mStartingSurfaceOptional.ifPresent(startingSurface -> startingSurface.setSysuiProxy( + (requestTopUi, componentTag) -> mMainExecutor.execute(() -> + mNotificationShadeWindowController.setRequestTopUi( + requestTopUi, componentTag)))); + } + + private void onFoldedStateChanged(boolean isFolded, boolean willGoToSleep) { + Trace.beginSection("CentralSurfaces#onFoldedStateChanged"); + onFoldedStateChangedInternal(isFolded, willGoToSleep); + Trace.endSection(); + } + + private void onFoldedStateChangedInternal(boolean isFolded, boolean willGoToSleep) { + // Folded state changes are followed by a screen off event. + // By default turning off the screen also closes the shade. + // We want to make sure that the shade status is kept after + // folding/unfolding. + boolean isShadeOpen = mShadeController.isShadeOpen(); + boolean leaveOpen = isShadeOpen && !willGoToSleep; + if (DEBUG) { + Log.d(TAG, String.format( + "#onFoldedStateChanged(): " + + "isFolded=%s, " + + "willGoToSleep=%s, " + + "isShadeOpen=%s, " + + "leaveOpen=%s", + isFolded, willGoToSleep, isShadeOpen, leaveOpen)); + } + if (leaveOpen) { + mStatusBarStateController.setLeaveOpenOnKeyguardHide(true); + if (mKeyguardStateController.isShowing()) { + // When device state changes on keyguard we don't want to keep the state of + // the shade and instead we open clean state of keyguard with shade closed. + // Normally some parts of QS state (like expanded/collapsed) are persisted and + // that causes incorrect UI rendering, especially when changing state with QS + // expanded. To prevent that we can close QS which resets QS and some parts of + // the shade to its default state. Read more in b/201537421 + mCloseQsBeforeScreenOff = true; + } + } + } + + // ================================================================================ + // Constructing the view + // ================================================================================ + protected void makeStatusBarView(@Nullable RegisterStatusBarResult result) { + updateDisplaySize(); // populates mDisplayMetrics + updateResources(); + updateTheme(); + + inflateStatusBarWindow(); + mNotificationShadeWindowView.setOnTouchListener(getStatusBarWindowTouchListener()); + mWallpaperController.setRootView(mNotificationShadeWindowView); + + // TODO: Deal with the ugliness that comes from having some of the status bar broken out + // into fragments, but the rest here, it leaves some awkward lifecycle and whatnot. + mNotificationLogger.setUpWithContainer(mNotifListContainer); + mNotificationIconAreaController.setupShelf(mNotificationShelfController); + mPanelExpansionStateManager.addExpansionListener(mWakeUpCoordinator); + mUserSwitcherController.init(mNotificationShadeWindowView); + + // Allow plugins to reference DarkIconDispatcher and StatusBarStateController + mPluginDependencyProvider.allowPluginDependency(DarkIconDispatcher.class); + mPluginDependencyProvider.allowPluginDependency(StatusBarStateController.class); + + // Set up CollapsedStatusBarFragment and PhoneStatusBarView + StatusBarInitializer initializer = mCentralSurfacesComponent.getStatusBarInitializer(); + initializer.setStatusBarViewUpdatedListener( + (statusBarView, statusBarViewController, statusBarTransitions) -> { + mStatusBarView = statusBarView; + mPhoneStatusBarViewController = statusBarViewController; + mStatusBarTransitions = statusBarTransitions; + mNotificationShadeWindowViewController + .setStatusBarViewController(mPhoneStatusBarViewController); + // Ensure we re-propagate panel expansion values to the panel controller and + // any listeners it may have, such as PanelBar. This will also ensure we + // re-display the notification panel if necessary (for example, if + // a heads-up notification was being displayed and should continue being + // displayed). + mNotificationPanelViewController.updatePanelExpansionAndVisibility(); + setBouncerShowingForStatusBarComponents(mBouncerShowing); + checkBarModes(); + }); + initializer.initializeStatusBar(mCentralSurfacesComponent); + + mStatusBarTouchableRegionManager.setup(this, mNotificationShadeWindowView); + mHeadsUpManager.addListener(mNotificationPanelViewController.getOnHeadsUpChangedListener()); + if (!mNotifPipelineFlags.isNewPipelineEnabled()) { + mHeadsUpManager.addListener(mVisualStabilityManager); + } + mNotificationPanelViewController.setHeadsUpManager(mHeadsUpManager); + + createNavigationBar(result); + + if (ENABLE_LOCKSCREEN_WALLPAPER && mWallpaperSupported) { + mLockscreenWallpaper = mLockscreenWallpaperLazy.get(); + } + + mNotificationPanelViewController.setKeyguardIndicationController( + mKeyguardIndicationController); + + mAmbientIndicationContainer = mNotificationShadeWindowView.findViewById( + R.id.ambient_indication_container); + + mAutoHideController.setStatusBar(new AutoHideUiElement() { + @Override + public void synchronizeState() { + checkBarModes(); + } + + @Override + public boolean shouldHideOnTouch() { + return !mRemoteInputManager.isRemoteInputActive(); + } + + @Override + public boolean isVisible() { + return isTransientShown(); + } + + @Override + public void hide() { + clearTransient(); + } + }); + + ScrimView scrimBehind = mNotificationShadeWindowView.findViewById(R.id.scrim_behind); + ScrimView notificationsScrim = mNotificationShadeWindowView + .findViewById(R.id.scrim_notifications); + ScrimView scrimInFront = mNotificationShadeWindowView.findViewById(R.id.scrim_in_front); + + mScrimController.setScrimVisibleListener(scrimsVisible -> { + mNotificationShadeWindowController.setScrimsVisibility(scrimsVisible); + }); + mScrimController.attachViews(scrimBehind, notificationsScrim, scrimInFront); + + mLightRevealScrim = mNotificationShadeWindowView.findViewById(R.id.light_reveal_scrim); + mLightRevealScrim.setScrimOpaqueChangedListener((opaque) -> { + Runnable updateOpaqueness = () -> { + mNotificationShadeWindowController.setLightRevealScrimOpaque( + mLightRevealScrim.isScrimOpaque()); + mScreenOffAnimationController + .onScrimOpaqueChanged(mLightRevealScrim.isScrimOpaque()); + }; + if (opaque) { + // Delay making the view opaque for a frame, because it needs some time to render + // otherwise this can lead to a flicker where the scrim doesn't cover the screen + mLightRevealScrim.post(updateOpaqueness); + } else { + updateOpaqueness.run(); + } + }); + + mScreenOffAnimationController.initialize(this, mLightRevealScrim); + updateLightRevealScrimVisibility(); + + mNotificationPanelViewController.initDependencies( + this, + this::makeExpandedInvisible, + mNotificationShelfController); + + BackDropView backdrop = mNotificationShadeWindowView.findViewById(R.id.backdrop); + mMediaManager.setup(backdrop, backdrop.findViewById(R.id.backdrop_front), + backdrop.findViewById(R.id.backdrop_back), mScrimController, mLockscreenWallpaper); + float maxWallpaperZoom = mContext.getResources().getFloat( + com.android.internal.R.dimen.config_wallpaperMaxScale); + mNotificationShadeDepthControllerLazy.get().addListener(depth -> { + float scale = MathUtils.lerp(maxWallpaperZoom, 1f, depth); + backdrop.setPivotX(backdrop.getWidth() / 2f); + backdrop.setPivotY(backdrop.getHeight() / 2f); + backdrop.setScaleX(scale); + backdrop.setScaleY(scale); + }); + + mNotificationPanelViewController.setUserSetupComplete(mUserSetup); + + // Set up the quick settings tile panel + final View container = mNotificationShadeWindowView.findViewById(R.id.qs_frame); + if (container != null) { + FragmentHostManager fragmentHostManager = FragmentHostManager.get(container); + ExtensionFragmentListener.attachExtensonToFragment(container, QS.TAG, R.id.qs_frame, + mExtensionController + .newExtension(QS.class) + .withPlugin(QS.class) + .withDefault(this::createDefaultQSFragment) + .build()); + mBrightnessMirrorController = new BrightnessMirrorController( + mNotificationShadeWindowView, + mNotificationPanelViewController, + mNotificationShadeDepthControllerLazy.get(), + mBrightnessSliderFactory, + (visible) -> { + mBrightnessMirrorVisible = visible; + updateScrimController(); + }); + fragmentHostManager.addTagListener(QS.TAG, (tag, f) -> { + QS qs = (QS) f; + if (qs instanceof QSFragment) { + mQSPanelController = ((QSFragment) qs).getQSPanelController(); + ((QSFragment) qs).setBrightnessMirrorController(mBrightnessMirrorController); + } + }); + } + + mReportRejectedTouch = mNotificationShadeWindowView + .findViewById(R.id.report_rejected_touch); + if (mReportRejectedTouch != null) { + updateReportRejectedTouchVisibility(); + mReportRejectedTouch.setOnClickListener(v -> { + Uri session = mFalsingManager.reportRejectedTouch(); + if (session == null) { return; } + + StringWriter message = new StringWriter(); + message.write("Build info: "); + message.write(SystemProperties.get("ro.build.description")); + message.write("\nSerial number: "); + message.write(SystemProperties.get("ro.serialno")); + message.write("\n"); + + startActivityDismissingKeyguard(Intent.createChooser(new Intent(Intent.ACTION_SEND) + .setType("*/*") + .putExtra(Intent.EXTRA_SUBJECT, "Rejected touch report") + .putExtra(Intent.EXTRA_STREAM, session) + .putExtra(Intent.EXTRA_TEXT, message.toString()), + "Share rejected touch report") + .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK), + true /* onlyProvisioned */, true /* dismissShade */); + }); + } + + if (!mPowerManager.isInteractive()) { + mBroadcastReceiver.onReceive(mContext, new Intent(Intent.ACTION_SCREEN_OFF)); + } + mGestureWakeLock = mPowerManager.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK, + "sysui:GestureWakeLock"); + + // receive broadcasts + registerBroadcastReceiver(); + + IntentFilter demoFilter = new IntentFilter(); + if (DEBUG_MEDIA_FAKE_ARTWORK) { + demoFilter.addAction(ACTION_FAKE_ARTWORK); + } + mContext.registerReceiverAsUser(mDemoReceiver, UserHandle.ALL, demoFilter, + android.Manifest.permission.DUMP, null, + Context.RECEIVER_EXPORTED_UNAUDITED); + + // listen for USER_SETUP_COMPLETE setting (per-user) + mDeviceProvisionedController.addCallback(mUserSetupObserver); + mUserSetupObserver.onUserSetupChanged(); + + // disable profiling bars, since they overlap and clutter the output on app windows + ThreadedRenderer.overrideProperty("disableProfileBars", "true"); + + // Private API call to make the shadows look better for Recents + ThreadedRenderer.overrideProperty("ambientRatio", String.valueOf(1.5f)); + } + + + /** + * When swiping up to dismiss the lock screen, the panel expansion fraction goes from 1f to 0f. + * This results in the clock/notifications/other content disappearing off the top of the screen. + * + * We also use the expansion fraction to animate in the app/launcher surface from the bottom of + * the screen, 'pushing' off the notifications and other content. To do this, we dispatch the + * expansion fraction to the KeyguardViewMediator if we're in the process of dismissing the + * keyguard. + */ + private void dispatchPanelExpansionForKeyguardDismiss(float fraction, boolean trackingTouch) { + // Things that mean we're not swiping to dismiss the keyguard, and should ignore this + // expansion: + // - Keyguard isn't even visible. + // - Keyguard is occluded. Expansion changes here are the shade being expanded over the + // occluding activity. + // - Keyguard is visible, but can't be dismissed (swiping up will show PIN/password prompt). + // - The SIM is locked, you can't swipe to unlock. If the SIM is locked but there is no + // device lock set, canDismissLockScreen returns true even though you should not be able + // to dismiss the lock screen until entering the SIM PIN. + // - QS is expanded and we're swiping - swiping up now will hide QS, not dismiss the + // keyguard. + if (!isKeyguardShowing() + || isOccluded() + || !mKeyguardStateController.canDismissLockScreen() + || mKeyguardViewMediator.isAnySimPinSecure() + || (mNotificationPanelViewController.isQsExpanded() && trackingTouch)) { + return; + } + + // Otherwise, we should let the keyguard know about this if we're tracking touch, or if we + // are already animating the keyguard dismiss (since we will need to either finish or cancel + // the animation). + if (trackingTouch + || mKeyguardViewMediator.isAnimatingBetweenKeyguardAndSurfaceBehindOrWillBe() + || mKeyguardUnlockAnimationController.isUnlockingWithSmartSpaceTransition()) { + mKeyguardStateController.notifyKeyguardDismissAmountChanged( + 1f - fraction, trackingTouch); + } + } + + private void onPanelExpansionChanged(PanelExpansionChangeEvent event) { + float fraction = event.getFraction(); + boolean tracking = event.getTracking(); + dispatchPanelExpansionForKeyguardDismiss(fraction, tracking); + + if (fraction == 0 || fraction == 1) { + if (getNavigationBarView() != null) { + getNavigationBarView().onStatusBarPanelStateChanged(); + } + if (getNotificationPanelViewController() != null) { + getNotificationPanelViewController().updateSystemUiStateFlags(); + } + } + } + + @NonNull + @Override + public Lifecycle getLifecycle() { + return mLifecycle; + } + + @VisibleForTesting + protected void registerBroadcastReceiver() { + IntentFilter filter = new IntentFilter(); + filter.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS); + filter.addAction(Intent.ACTION_SCREEN_OFF); + mBroadcastDispatcher.registerReceiver(mBroadcastReceiver, filter, null, UserHandle.ALL); + } + + protected QS createDefaultQSFragment() { + return FragmentHostManager.get(mNotificationShadeWindowView).create(QSFragment.class); + } + + private void setUpPresenter() { + // Set up the initial notification state. + mActivityLaunchAnimator.setCallback(mActivityLaunchAnimatorCallback); + mActivityLaunchAnimator.addListener(mActivityLaunchAnimatorListener); + mNotificationAnimationProvider = new NotificationLaunchAnimatorControllerProvider( + mNotificationShadeWindowViewController, + mNotifListContainer, + mHeadsUpManager, + mJankMonitor); + mNotificationShelfController.setOnActivatedListener(mPresenter); + mRemoteInputManager.addControllerCallback(mNotificationShadeWindowController); + mStackScrollerController.setNotificationActivityStarter(mNotificationActivityStarter); + mGutsManager.setNotificationActivityStarter(mNotificationActivityStarter); + mNotificationsController.initialize( + mPresenter, + mNotifListContainer, + mStackScrollerController.getNotifStackController(), + mNotificationActivityStarter, + mCentralSurfacesComponent.getBindRowCallback()); + } + + /** + * Post-init task of {@link #start()} + * @param state1 disable1 flags + * @param state2 disable2 flags + */ + protected void setUpDisableFlags(int state1, int state2) { + mCommandQueue.disable(mDisplayId, state1, state2, false /* animate */); + } + + /** + * Ask the display to wake up if currently dozing, else do nothing + * + * @param time when to wake up + * @param where the view requesting the wakeup + * @param why the reason for the wake up + */ + @Override + public void wakeUpIfDozing(long time, View where, String why) { + if (mDozing && mScreenOffAnimationController.allowWakeUpIfDozing()) { + mPowerManager.wakeUp( + time, PowerManager.WAKE_REASON_GESTURE, "com.android.systemui:" + why); + mWakeUpComingFromTouch = true; + where.getLocationInWindow(mTmpInt2); + + // NOTE, the incoming view can sometimes be the entire container... unsure if + // this location is valuable enough + mWakeUpTouchLocation = new PointF(mTmpInt2[0] + where.getWidth() / 2, + mTmpInt2[1] + where.getHeight() / 2); + mFalsingCollector.onScreenOnFromTouch(); + } + } + + // TODO(b/117478341): This was left such that CarStatusBar can override this method. + // Try to remove this. + protected void createNavigationBar(@Nullable RegisterStatusBarResult result) { + mNavigationBarController.createNavigationBars(true /* includeDefaultDisplay */, result); + } + + /** + * Returns the {@link android.view.View.OnTouchListener} that will be invoked when the + * background window of the status bar is clicked. + */ + protected View.OnTouchListener getStatusBarWindowTouchListener() { + return (v, event) -> { + mAutoHideController.checkUserAutoHide(event); + mRemoteInputManager.checkRemoteInputOutside(event); + if (event.getAction() == MotionEvent.ACTION_UP) { + if (mExpandedVisible) { + mShadeController.animateCollapsePanels(); + } + } + return mNotificationShadeWindowView.onTouchEvent(event); + }; + } + + private void inflateStatusBarWindow() { + if (mCentralSurfacesComponent != null) { + // Tear down + for (CentralSurfacesComponent.Startable s : mCentralSurfacesComponent.getStartables()) { + s.stop(); + } + } + mCentralSurfacesComponent = mCentralSurfacesComponentFactory.create(); + mFragmentService.addFragmentInstantiationProvider(mCentralSurfacesComponent); + + mNotificationShadeWindowView = mCentralSurfacesComponent.getNotificationShadeWindowView(); + mNotificationShadeWindowViewController = mCentralSurfacesComponent + .getNotificationShadeWindowViewController(); + mNotificationShadeWindowController.setNotificationShadeView(mNotificationShadeWindowView); + mNotificationShadeWindowViewController.setupExpandedStatusBar(); + mNotificationPanelViewController = + mCentralSurfacesComponent.getNotificationPanelViewController(); + mCentralSurfacesComponent.getLockIconViewController().init(); + mStackScrollerController = + mCentralSurfacesComponent.getNotificationStackScrollLayoutController(); + mStackScroller = mStackScrollerController.getView(); + mNotifListContainer = mCentralSurfacesComponent.getNotificationListContainer(); + mPresenter = mCentralSurfacesComponent.getNotificationPresenter(); + mNotificationActivityStarter = mCentralSurfacesComponent.getNotificationActivityStarter(); + mNotificationShelfController = mCentralSurfacesComponent.getNotificationShelfController(); + mAuthRippleController = mCentralSurfacesComponent.getAuthRippleController(); + mAuthRippleController.init(); + + mHeadsUpManager.addListener(mCentralSurfacesComponent.getStatusBarHeadsUpChangeListener()); + + // Listen for demo mode changes + mDemoModeController.addCallback(mDemoModeCallback); + + if (mCommandQueueCallbacks != null) { + mCommandQueue.removeCallback(mCommandQueueCallbacks); + } + mCommandQueueCallbacks = + mCentralSurfacesComponent.getCentralSurfacesCommandQueueCallbacks(); + // Connect in to the status bar manager service + mCommandQueue.addCallback(mCommandQueueCallbacks); + + // Perform all other initialization for CentralSurfacesScope + for (CentralSurfacesComponent.Startable s : mCentralSurfacesComponent.getStartables()) { + s.start(); + } + } + + protected void startKeyguard() { + Trace.beginSection("CentralSurfaces#startKeyguard"); + mBiometricUnlockController = mBiometricUnlockControllerLazy.get(); + mBiometricUnlockController.setBiometricModeListener( + new BiometricUnlockController.BiometricModeListener() { + @Override + public void onResetMode() { + setWakeAndUnlocking(false); + } + + @Override + public void onModeChanged(int mode) { + switch (mode) { + case BiometricUnlockController.MODE_WAKE_AND_UNLOCK_FROM_DREAM: + case BiometricUnlockController.MODE_WAKE_AND_UNLOCK_PULSING: + case BiometricUnlockController.MODE_WAKE_AND_UNLOCK: + setWakeAndUnlocking(true); + } + } + + @Override + public void notifyBiometricAuthModeChanged() { + CentralSurfacesImpl.this.notifyBiometricAuthModeChanged(); + } + + private void setWakeAndUnlocking(boolean wakeAndUnlocking) { + if (getNavigationBarView() != null) { + getNavigationBarView().setWakeAndUnlocking(wakeAndUnlocking); + } + } + }); + mStatusBarKeyguardViewManager.registerCentralSurfaces( + /* statusBar= */ this, + mNotificationPanelViewController, + mPanelExpansionStateManager, + mBiometricUnlockController, + mStackScroller, + mKeyguardBypassController); + mKeyguardStateController.addCallback(mKeyguardStateControllerCallback); + mKeyguardIndicationController + .setStatusBarKeyguardViewManager(mStatusBarKeyguardViewManager); + mBiometricUnlockController.setKeyguardViewController(mStatusBarKeyguardViewManager); + mRemoteInputManager.addControllerCallback(mStatusBarKeyguardViewManager); + mDynamicPrivacyController.setStatusBarKeyguardViewManager(mStatusBarKeyguardViewManager); + + mLightBarController.setBiometricUnlockController(mBiometricUnlockController); + mMediaManager.setBiometricUnlockController(mBiometricUnlockController); + mKeyguardDismissUtil.setDismissHandler(this::executeWhenUnlocked); + Trace.endSection(); + } + + @Override + public NotificationShadeWindowView getNotificationShadeWindowView() { + return mNotificationShadeWindowView; + } + + @Override + public NotificationShadeWindowViewController getNotificationShadeWindowViewController() { + return mNotificationShadeWindowViewController; + } + + @Override + public NotificationPanelViewController getNotificationPanelViewController() { + return mNotificationPanelViewController; + } + + @Override + public ViewGroup getBouncerContainer() { + return mNotificationShadeWindowViewController.getBouncerContainer(); + } + + @Override + public int getStatusBarHeight() { + return mStatusBarWindowController.getStatusBarHeight(); + } + + /** + * Disable QS if device not provisioned. + * If the user switcher is simple then disable QS during setup because + * the user intends to use the lock screen user switcher, QS in not needed. + */ + @Override + public void updateQsExpansionEnabled() { + final boolean expandEnabled = mDeviceProvisionedController.isDeviceProvisioned() + && (mUserSetup || mUserSwitcherController == null + || !mUserSwitcherController.isSimpleUserSwitcher()) + && !isShadeDisabled() + && ((mDisabled2 & StatusBarManager.DISABLE2_QUICK_SETTINGS) == 0) + && !mDozing; + mNotificationPanelViewController.setQsExpansionEnabledPolicy(expandEnabled); + Log.d(TAG, "updateQsExpansionEnabled - QS Expand enabled: " + expandEnabled); + } + + @Override + public boolean isShadeDisabled() { + return (mDisabled2 & StatusBarManager.DISABLE2_NOTIFICATION_SHADE) != 0; + } + + /** + * Request a notification update + * @param reason why we're requesting a notification update + */ + @Override + public void requestNotificationUpdate(String reason) { + mNotificationsController.requestNotificationUpdate(reason); + } + + /** + * Asks {@link KeyguardUpdateMonitor} to run face auth. + */ + @Override + public void requestFaceAuth(boolean userInitiatedRequest) { + if (!mKeyguardStateController.canDismissLockScreen()) { + mKeyguardUpdateMonitor.requestFaceAuth(userInitiatedRequest); + } + } + + private void updateReportRejectedTouchVisibility() { + if (mReportRejectedTouch == null) { + return; + } + mReportRejectedTouch.setVisibility(mState == StatusBarState.KEYGUARD && !mDozing + && mFalsingCollector.isReportingEnabled() ? View.VISIBLE : View.INVISIBLE); + } + + @Override + public boolean areNotificationAlertsDisabled() { + return (mDisabled1 & StatusBarManager.DISABLE_NOTIFICATION_ALERTS) != 0; + } + + @Override + public void startActivity(Intent intent, boolean onlyProvisioned, boolean dismissShade, + int flags) { + startActivityDismissingKeyguard(intent, onlyProvisioned, dismissShade, flags); + } + + @Override + public void startActivity(Intent intent, boolean dismissShade) { + startActivityDismissingKeyguard(intent, false /* onlyProvisioned */, dismissShade); + } + + @Override + public void startActivity(Intent intent, boolean dismissShade, + @Nullable ActivityLaunchAnimator.Controller animationController, + boolean showOverLockscreenWhenLocked) { + startActivity(intent, dismissShade, animationController, showOverLockscreenWhenLocked, + getActivityUserHandle(intent)); + } + + @Override + public void startActivity(Intent intent, boolean dismissShade, + @Nullable ActivityLaunchAnimator.Controller animationController, + boolean showOverLockscreenWhenLocked, UserHandle userHandle) { + // Make sure that we dismiss the keyguard if it is directly dismissable or when we don't + // want to show the activity above it. + if (mKeyguardStateController.isUnlocked() || !showOverLockscreenWhenLocked) { + startActivityDismissingKeyguard(intent, false, dismissShade, + false /* disallowEnterPictureInPictureWhileLaunching */, null /* callback */, + 0 /* flags */, animationController, userHandle); + return; + } + + boolean animate = + animationController != null && shouldAnimateLaunch(true /* isActivityIntent */, + showOverLockscreenWhenLocked); + + ActivityLaunchAnimator.Controller controller = null; + if (animate) { + // Wrap the animation controller to dismiss the shade and set + // mIsLaunchingActivityOverLockscreen during the animation. + ActivityLaunchAnimator.Controller delegate = wrapAnimationController( + animationController, dismissShade); + controller = new DelegateLaunchAnimatorController(delegate) { + @Override + public void onIntentStarted(boolean willAnimate) { + getDelegate().onIntentStarted(willAnimate); + + if (willAnimate) { + CentralSurfacesImpl.this.mIsLaunchingActivityOverLockscreen = true; + } + } + + @Override + public void onLaunchAnimationEnd(boolean isExpandingFullyAbove) { + // Set mIsLaunchingActivityOverLockscreen to false before actually finishing the + // animation so that we can assume that mIsLaunchingActivityOverLockscreen + // being true means that we will collapse the shade (or at least run the + // post collapse runnables) later on. + CentralSurfacesImpl.this.mIsLaunchingActivityOverLockscreen = false; + getDelegate().onLaunchAnimationEnd(isExpandingFullyAbove); + } + + @Override + public void onLaunchAnimationCancelled() { + // Set mIsLaunchingActivityOverLockscreen to false before actually finishing the + // animation so that we can assume that mIsLaunchingActivityOverLockscreen + // being true means that we will collapse the shade (or at least run the + // post collapse runnables) later on. + CentralSurfacesImpl.this.mIsLaunchingActivityOverLockscreen = false; + getDelegate().onLaunchAnimationCancelled(); + } + }; + } else if (dismissShade) { + // The animation will take care of dismissing the shade at the end of the animation. If + // we don't animate, collapse it directly. + collapseShade(); + } + + mActivityLaunchAnimator.startIntentWithAnimation(controller, animate, + intent.getPackage(), showOverLockscreenWhenLocked, (adapter) -> TaskStackBuilder + .create(mContext) + .addNextIntent(intent) + .startActivities( + CentralSurfaces.getActivityOptions(getDisplayId(), adapter), + userHandle)); + } + + /** + * Whether we are currently animating an activity launch above the lockscreen (occluding + * activity). + */ + @Override + public boolean isLaunchingActivityOverLockscreen() { + return mIsLaunchingActivityOverLockscreen; + } + + @Override + public void startActivity(Intent intent, boolean onlyProvisioned, boolean dismissShade) { + startActivityDismissingKeyguard(intent, onlyProvisioned, dismissShade); + } + + @Override + public void startActivity(Intent intent, boolean dismissShade, Callback callback) { + startActivityDismissingKeyguard(intent, false, dismissShade, + false /* disallowEnterPictureInPictureWhileLaunching */, callback, 0, + null /* animationController */, getActivityUserHandle(intent)); + } + + @Override + public void setQsExpanded(boolean expanded) { + mNotificationShadeWindowController.setQsExpanded(expanded); + mNotificationPanelViewController.setStatusAccessibilityImportance(expanded + ? View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS + : View.IMPORTANT_FOR_ACCESSIBILITY_AUTO); + mNotificationPanelViewController.updateSystemUiStateFlags(); + if (getNavigationBarView() != null) { + getNavigationBarView().onStatusBarPanelStateChanged(); + } + } + + @Override + public boolean isWakeUpComingFromTouch() { + return mWakeUpComingFromTouch; + } + + @Override + public boolean isFalsingThresholdNeeded() { + return true; + } + + /** + * To be called when there's a state change in StatusBarKeyguardViewManager. + */ + @Override + public void onKeyguardViewManagerStatesUpdated() { + logStateToEventlog(); + } + + @Override + public void setPanelExpanded(boolean isExpanded) { + if (mPanelExpanded != isExpanded) { + mNotificationLogger.onPanelExpandedChanged(isExpanded); + } + mPanelExpanded = isExpanded; + mStatusBarHideIconsForBouncerManager.setPanelExpandedAndTriggerUpdate(isExpanded); + mNotificationShadeWindowController.setPanelExpanded(isExpanded); + mStatusBarStateController.setPanelExpanded(isExpanded); + if (isExpanded && mStatusBarStateController.getState() != StatusBarState.KEYGUARD) { + if (DEBUG) { + Log.v(TAG, "clearing notification effects from Height"); + } + clearNotificationEffects(); + } + + if (!isExpanded) { + mRemoteInputManager.onPanelCollapsed(); + } + } + + @Override + public ViewGroup getNotificationScrollLayout() { + return mStackScroller; + } + + @Override + public boolean isPulsing() { + return mDozeServiceHost.isPulsing(); + } + + @androidx.annotation.Nullable + @Override + public View getAmbientIndicationContainer() { + return mAmbientIndicationContainer; + } + + /** + * When the keyguard is showing and covered by a "showWhenLocked" activity it + * is occluded. This is controlled by {@link com.android.server.policy.PhoneWindowManager} + * + * @return whether the keyguard is currently occluded + */ + @Override + public boolean isOccluded() { + return mKeyguardStateController.isOccluded(); + } + + /** A launch animation was cancelled. */ + //TODO: These can / should probably be moved to NotificationPresenter or ShadeController + @Override + public void onLaunchAnimationCancelled(boolean isLaunchForActivity) { + if (mPresenter.isPresenterFullyCollapsed() && !mPresenter.isCollapsing() + && isLaunchForActivity) { + onClosingFinished(); + } else { + mShadeController.collapsePanel(true /* animate */); + } + } + + /** A launch animation ended. */ + @Override + public void onLaunchAnimationEnd(boolean launchIsFullScreen) { + if (!mPresenter.isCollapsing()) { + onClosingFinished(); + } + if (launchIsFullScreen) { + instantCollapseNotificationPanel(); + } + } + + /** + * Whether we should animate an activity launch. + * + * Note: This method must be called *before* dismissing the keyguard. + */ + @Override + public boolean shouldAnimateLaunch(boolean isActivityIntent, boolean showOverLockscreen) { + // TODO(b/184121838): Support launch animations when occluded. + if (isOccluded()) { + return false; + } + + // Always animate if we are not showing the keyguard or if we animate over the lockscreen + // (without unlocking it). + if (showOverLockscreen || !mKeyguardStateController.isShowing()) { + return true; + } + + // If we are locked and have to dismiss the keyguard, only animate if remote unlock + // animations are enabled. We also don't animate non-activity launches as they can break the + // animation. + // TODO(b/184121838): Support non activity launches on the lockscreen. + return isActivityIntent && KeyguardService.sEnableRemoteKeyguardGoingAwayAnimation; + } + + /** Whether we should animate an activity launch. */ + @Override + public boolean shouldAnimateLaunch(boolean isActivityIntent) { + return shouldAnimateLaunch(isActivityIntent, false /* showOverLockscreen */); + } + + @Override + public boolean isDeviceInVrMode() { + return mPresenter.isDeviceInVrMode(); + } + + @Override + public NotificationPresenter getPresenter() { + return mPresenter; + } + + @VisibleForTesting + @Override + public void setBarStateForTest(int state) { + mState = state; + } + + static class AnimateExpandSettingsPanelMessage { + final String mSubpanel; + + AnimateExpandSettingsPanelMessage(String subpanel) { + mSubpanel = subpanel; + } + } + + private void maybeEscalateHeadsUp() { + mHeadsUpManager.getAllEntries().forEach(entry -> { + final StatusBarNotification sbn = entry.getSbn(); + final Notification notification = sbn.getNotification(); + if (notification.fullScreenIntent != null) { + if (DEBUG) { + Log.d(TAG, "converting a heads up to fullScreen"); + } + try { + EventLog.writeEvent(EventLogTags.SYSUI_HEADS_UP_ESCALATION, + sbn.getKey()); + wakeUpForFullScreenIntent(); + notification.fullScreenIntent.send(); + entry.notifyFullScreenIntentLaunched(); + } catch (PendingIntent.CanceledException e) { + } + } + }); + mHeadsUpManager.releaseAllImmediately(); + } + + @Override + public void wakeUpForFullScreenIntent() { + if (isGoingToSleep() || mDozing) { + mPowerManager.wakeUp( + SystemClock.uptimeMillis(), + PowerManager.WAKE_REASON_APPLICATION, + "com.android.systemui:full_screen_intent"); + mWakeUpComingFromTouch = false; + mWakeUpTouchLocation = null; + } + } + + @Override + public void makeExpandedVisible(boolean force) { + if (SPEW) Log.d(TAG, "Make expanded visible: expanded visible=" + mExpandedVisible); + if (!force && (mExpandedVisible || !mCommandQueue.panelsEnabled())) { + return; + } + + mExpandedVisible = true; + + // Expand the window to encompass the full screen in anticipation of the drag. + // This is only possible to do atomically because the status bar is at the top of the screen! + mNotificationShadeWindowController.setPanelVisible(true); + + visibilityChanged(true); + mCommandQueue.recomputeDisableFlags(mDisplayId, !force /* animate */); + setInteracting(StatusBarManager.WINDOW_STATUS_BAR, true); + } + + @Override + public void postAnimateCollapsePanels() { + mMainExecutor.execute(mShadeController::animateCollapsePanels); + } + + @Override + public void postAnimateForceCollapsePanels() { + mMainExecutor.execute( + () -> mShadeController.animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_NONE, + true /* force */)); + } + + @Override + public void postAnimateOpenPanels() { + mMessageRouter.sendMessage(MSG_OPEN_SETTINGS_PANEL); + } + + @Override + public boolean isExpandedVisible() { + return mExpandedVisible; + } + + @Override + public boolean isPanelExpanded() { + return mPanelExpanded; + } + + /** + * Called when another window is about to transfer it's input focus. + */ + @Override + public void onInputFocusTransfer(boolean start, boolean cancel, float velocity) { + if (!mCommandQueue.panelsEnabled()) { + return; + } + + if (start) { + mNotificationPanelViewController.startWaitingForOpenPanelGesture(); + } else { + mNotificationPanelViewController.stopWaitingForOpenPanelGesture(cancel, velocity); + } + } + + @Override + public void animateCollapseQuickSettings() { + if (mState == StatusBarState.SHADE) { + mNotificationPanelViewController.collapsePanel( + true, false /* delayed */, 1.0f /* speedUpFactor */); + } + } + + void makeExpandedInvisible() { + if (SPEW) Log.d(TAG, "makeExpandedInvisible: mExpandedVisible=" + mExpandedVisible + + " mExpandedVisible=" + mExpandedVisible); + + if (!mExpandedVisible || mNotificationShadeWindowView == null) { + return; + } + + // Ensure the panel is fully collapsed (just in case; bug 6765842, 7260868) + mNotificationPanelViewController.collapsePanel(/*animate=*/ false, false /* delayed*/, + 1.0f /* speedUpFactor */); + + mNotificationPanelViewController.closeQs(); + + mExpandedVisible = false; + visibilityChanged(false); + + // Update the visibility of notification shade and status bar window. + mNotificationShadeWindowController.setPanelVisible(false); + mStatusBarWindowController.setForceStatusBarVisible(false); + + // Close any guts that might be visible + mGutsManager.closeAndSaveGuts(true /* removeLeavebehind */, true /* force */, + true /* removeControls */, -1 /* x */, -1 /* y */, true /* resetMenu */); + + mShadeController.runPostCollapseRunnables(); + setInteracting(StatusBarManager.WINDOW_STATUS_BAR, false); + if (!mNotificationActivityStarter.isCollapsingToShowActivityOverLockscreen()) { + showBouncerOrLockScreenIfKeyguard(); + } else if (DEBUG) { + Log.d(TAG, "Not showing bouncer due to activity showing over lockscreen"); + } + mCommandQueue.recomputeDisableFlags( + mDisplayId, + mNotificationPanelViewController.hideStatusBarIconsWhenExpanded() /* animate */); + + // Trimming will happen later if Keyguard is showing - doing it here might cause a jank in + // the bouncer appear animation. + if (!mStatusBarKeyguardViewManager.isShowing()) { + WindowManagerGlobal.getInstance().trimMemory(ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN); + } + } + + /** Called when a touch event occurred on {@link PhoneStatusBarView}. */ + @Override + public void onTouchEvent(MotionEvent event) { + // TODO(b/202981994): Move this touch debugging to a central location. (Right now, it's + // split between NotificationPanelViewController and here.) + if (DEBUG_GESTURES) { + if (event.getActionMasked() != MotionEvent.ACTION_MOVE) { + EventLog.writeEvent(EventLogTags.SYSUI_STATUSBAR_TOUCH, + event.getActionMasked(), (int) event.getX(), (int) event.getY(), + mDisabled1, mDisabled2); + } + + } + + if (SPEW) { + Log.d(TAG, "Touch: rawY=" + event.getRawY() + " event=" + event + " mDisabled1=" + + mDisabled1 + " mDisabled2=" + mDisabled2); + } else if (CHATTY) { + if (event.getAction() != MotionEvent.ACTION_MOVE) { + Log.d(TAG, String.format( + "panel: %s at (%f, %f) mDisabled1=0x%08x mDisabled2=0x%08x", + MotionEvent.actionToString(event.getAction()), + event.getRawX(), event.getRawY(), mDisabled1, mDisabled2)); + } + } + + if (DEBUG_GESTURES) { + mGestureRec.add(event); + } + + if (mStatusBarWindowState == WINDOW_STATE_SHOWING) { + final boolean upOrCancel = + event.getAction() == MotionEvent.ACTION_UP || + event.getAction() == MotionEvent.ACTION_CANCEL; + setInteracting(StatusBarManager.WINDOW_STATUS_BAR, !upOrCancel || mExpandedVisible); + } + } + + @Override + public GestureRecorder getGestureRecorder() { + return mGestureRec; + } + + @Override + public BiometricUnlockController getBiometricUnlockController() { + return mBiometricUnlockController; + } + + @Override + public void showTransientUnchecked() { + if (!mTransientShown) { + mTransientShown = true; + mNoAnimationOnNextBarModeChange = true; + maybeUpdateBarMode(); + } + } + + @Override + public void clearTransient() { + if (mTransientShown) { + mTransientShown = false; + maybeUpdateBarMode(); + } + } + + private void maybeUpdateBarMode() { + final int barMode = barMode(mTransientShown, mAppearance); + if (updateBarMode(barMode)) { + mLightBarController.onStatusBarModeChanged(barMode); + updateBubblesVisibility(); + } + } + + private boolean updateBarMode(int barMode) { + if (mStatusBarMode != barMode) { + mStatusBarMode = barMode; + checkBarModes(); + mAutoHideController.touchAutoHide(); + return true; + } + return false; + } + + private @TransitionMode int barMode(boolean isTransient, int appearance) { + final int lightsOutOpaque = APPEARANCE_LOW_PROFILE_BARS | APPEARANCE_OPAQUE_STATUS_BARS; + if (mOngoingCallController.hasOngoingCall() && mIsFullscreen) { + return MODE_SEMI_TRANSPARENT; + } else 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_STATUS_BARS) != 0) { + return MODE_OPAQUE; + } else if ((appearance & APPEARANCE_SEMI_TRANSPARENT_STATUS_BARS) != 0) { + return MODE_SEMI_TRANSPARENT; + } else { + return MODE_TRANSPARENT; + } + } + + @Override + public void showWirelessChargingAnimation(int batteryLevel) { + showChargingAnimation(batteryLevel, UNKNOWN_BATTERY_LEVEL, 0); + } + + protected void showChargingAnimation(int batteryLevel, int transmittingBatteryLevel, + long animationDelay) { + WirelessChargingAnimation.makeWirelessChargingAnimation(mContext, null, + transmittingBatteryLevel, batteryLevel, + new WirelessChargingAnimation.Callback() { + @Override + public void onAnimationStarting() { + mNotificationShadeWindowController.setRequestTopUi(true, TAG); + } + + @Override + public void onAnimationEnded() { + mNotificationShadeWindowController.setRequestTopUi(false, TAG); + } + }, false, sUiEventLogger).show(animationDelay); + } + + @Override + public void checkBarModes() { + if (mDemoModeController.isInDemoMode()) return; + if (mStatusBarTransitions != null) { + checkBarMode(mStatusBarMode, mStatusBarWindowState, mStatusBarTransitions); + } + mNavigationBarController.checkNavBarModes(mDisplayId); + mNoAnimationOnNextBarModeChange = false; + } + + // Called by NavigationBarFragment + @Override + public void setQsScrimEnabled(boolean scrimEnabled) { + mNotificationPanelViewController.setQsScrimEnabled(scrimEnabled); + } + + /** Temporarily hides Bubbles if the status bar is hidden. */ + @Override + public void updateBubblesVisibility() { + mBubblesOptional.ifPresent(bubbles -> bubbles.onStatusBarVisibilityChanged( + mStatusBarMode != MODE_LIGHTS_OUT + && mStatusBarMode != MODE_LIGHTS_OUT_TRANSPARENT + && !mStatusBarWindowHidden)); + } + + void checkBarMode(@TransitionMode int mode, @WindowVisibleState int windowState, + BarTransitions transitions) { + final boolean anim = !mNoAnimationOnNextBarModeChange && mDeviceInteractive + && windowState != WINDOW_STATE_HIDDEN; + transitions.transitionTo(mode, anim); + } + + private void finishBarAnimations() { + if (mStatusBarTransitions != null) { + mStatusBarTransitions.finishAnimations(); + } + mNavigationBarController.finishBarAnimations(mDisplayId); + } + + private final Runnable mCheckBarModes = this::checkBarModes; + + @Override + public void setInteracting(int barWindow, boolean interacting) { + mInteractingWindows = interacting + ? (mInteractingWindows | barWindow) + : (mInteractingWindows & ~barWindow); + if (mInteractingWindows != 0) { + mAutoHideController.suspendAutoHide(); + } else { + mAutoHideController.resumeSuspendedAutoHide(); + } + checkBarModes(); + } + + private void dismissVolumeDialog() { + if (mVolumeComponent != null) { + mVolumeComponent.dismissNow(); + } + } + + @Override + public void dump(PrintWriter pwOriginal, String[] args) { + IndentingPrintWriter pw = DumpUtilsKt.asIndenting(pwOriginal); + synchronized (mQueueLock) { + pw.println("Current Status Bar state:"); + pw.println(" mExpandedVisible=" + mExpandedVisible); + pw.println(" mDisplayMetrics=" + mDisplayMetrics); + pw.println(" mStackScroller: " + CentralSurfaces.viewInfo(mStackScroller)); + pw.println(" mStackScroller: " + CentralSurfaces.viewInfo(mStackScroller) + + " scroll " + mStackScroller.getScrollX() + + "," + mStackScroller.getScrollY()); + } + + pw.print(" mInteractingWindows="); pw.println(mInteractingWindows); + pw.print(" mStatusBarWindowState="); + pw.println(windowStateToString(mStatusBarWindowState)); + pw.print(" mStatusBarMode="); + pw.println(BarTransitions.modeToString(mStatusBarMode)); + pw.print(" mDozing="); pw.println(mDozing); + pw.print(" mWallpaperSupported= "); pw.println(mWallpaperSupported); + + pw.println(" ShadeWindowView: "); + if (mNotificationShadeWindowViewController != null) { + mNotificationShadeWindowViewController.dump(pw, args); + CentralSurfaces.dumpBarTransitions( + pw, "PhoneStatusBarTransitions", mStatusBarTransitions); + } + + pw.println(" mMediaManager: "); + if (mMediaManager != null) { + mMediaManager.dump(pw, args); + } + + pw.println(" Panels: "); + if (mNotificationPanelViewController != null) { + pw.println(" mNotificationPanel=" + + mNotificationPanelViewController.getView() + " params=" + + mNotificationPanelViewController.getView().getLayoutParams().debug("")); + pw.print (" "); + mNotificationPanelViewController.dump(pw, args); + } + pw.println(" mStackScroller: "); + if (mStackScroller != null) { + // Double indent until we rewrite the rest of this dump() + pw.increaseIndent(); + pw.increaseIndent(); + mStackScroller.dump(pw, args); + pw.decreaseIndent(); + pw.decreaseIndent(); + } + pw.println(" Theme:"); + String nightMode = mUiModeManager == null ? "null" : mUiModeManager.getNightMode() + ""; + pw.println(" dark theme: " + nightMode + + " (auto: " + UiModeManager.MODE_NIGHT_AUTO + + ", yes: " + UiModeManager.MODE_NIGHT_YES + + ", no: " + UiModeManager.MODE_NIGHT_NO + ")"); + final boolean lightWpTheme = mContext.getThemeResId() + == R.style.Theme_SystemUI_LightWallpaper; + pw.println(" light wallpaper theme: " + lightWpTheme); + + if (mKeyguardIndicationController != null) { + mKeyguardIndicationController.dump(pw, args); + } + + if (mScrimController != null) { + mScrimController.dump(pw, args); + } + + if (mLightRevealScrim != null) { + pw.println( + "mLightRevealScrim.getRevealEffect(): " + mLightRevealScrim.getRevealEffect()); + pw.println( + "mLightRevealScrim.getRevealAmount(): " + mLightRevealScrim.getRevealAmount()); + } + + if (mStatusBarKeyguardViewManager != null) { + mStatusBarKeyguardViewManager.dump(pw); + } + + mNotificationsController.dump(pw, args, DUMPTRUCK); + + if (DEBUG_GESTURES) { + pw.print(" status bar gestures: "); + mGestureRec.dump(pw, args); + } + + if (mHeadsUpManager != null) { + mHeadsUpManager.dump(pw, args); + } else { + pw.println(" mHeadsUpManager: null"); + } + + if (mStatusBarTouchableRegionManager != null) { + mStatusBarTouchableRegionManager.dump(pw, args); + } else { + pw.println(" mStatusBarTouchableRegionManager: null"); + } + + if (mLightBarController != null) { + mLightBarController.dump(pw, args); + } + + pw.println("SharedPreferences:"); + for (Map.Entry entry : Prefs.getAll(mContext).entrySet()) { + pw.print(" "); pw.print(entry.getKey()); pw.print("="); pw.println(entry.getValue()); + } + + pw.println("Camera gesture intents:"); + pw.println(" Insecure camera: " + CameraIntents.getInsecureCameraIntent(mContext)); + pw.println(" Secure camera: " + CameraIntents.getSecureCameraIntent(mContext)); + pw.println(" Override package: " + + CameraIntents.getOverrideCameraPackage(mContext)); + } + + @Override + public void createAndAddWindows(@Nullable RegisterStatusBarResult result) { + makeStatusBarView(result); + mNotificationShadeWindowController.attach(); + mStatusBarWindowController.attach(); + } + + // called by makeStatusbar and also by PhoneStatusBarView + void updateDisplaySize() { + mDisplay.getMetrics(mDisplayMetrics); + mDisplay.getSize(mCurrentDisplaySize); + if (DEBUG_GESTURES) { + mGestureRec.tag("display", + String.format("%dx%d", mDisplayMetrics.widthPixels, mDisplayMetrics.heightPixels)); + } + } + + @Override + public float getDisplayDensity() { + return mDisplayMetrics.density; + } + + @Override + public float getDisplayWidth() { + return mDisplayMetrics.widthPixels; + } + + @Override + public float getDisplayHeight() { + return mDisplayMetrics.heightPixels; + } + + @Override + public int getRotation() { + return mDisplay.getRotation(); + } + + @Override + public int getDisplayId() { + return mDisplayId; + } + + @Override + public void startActivityDismissingKeyguard(final Intent intent, boolean onlyProvisioned, + boolean dismissShade, int flags) { + startActivityDismissingKeyguard(intent, onlyProvisioned, dismissShade, + false /* disallowEnterPictureInPictureWhileLaunching */, null /* callback */, + flags, null /* animationController */, getActivityUserHandle(intent)); + } + + @Override + public void startActivityDismissingKeyguard(final Intent intent, boolean onlyProvisioned, + boolean dismissShade) { + startActivityDismissingKeyguard(intent, onlyProvisioned, dismissShade, 0); + } + + @Override + public void startActivityDismissingKeyguard(final Intent intent, boolean onlyProvisioned, + final boolean dismissShade, final boolean disallowEnterPictureInPictureWhileLaunching, + final Callback callback, int flags, + @Nullable ActivityLaunchAnimator.Controller animationController, + final UserHandle userHandle) { + if (onlyProvisioned && !mDeviceProvisionedController.isDeviceProvisioned()) return; + + final boolean willLaunchResolverActivity = + mActivityIntentHelper.wouldLaunchResolverActivity(intent, + mLockscreenUserManager.getCurrentUserId()); + + boolean animate = + animationController != null && !willLaunchResolverActivity && shouldAnimateLaunch( + true /* isActivityIntent */); + ActivityLaunchAnimator.Controller animController = + animationController != null ? wrapAnimationController(animationController, + dismissShade) : null; + + // If we animate, we will dismiss the shade only once the animation is done. This is taken + // care of by the StatusBarLaunchAnimationController. + boolean dismissShadeDirectly = dismissShade && animController == null; + + Runnable runnable = () -> { + mAssistManagerLazy.get().hideAssist(); + intent.setFlags( + Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP); + intent.addFlags(flags); + int[] result = new int[]{ActivityManager.START_CANCELED}; + + mActivityLaunchAnimator.startIntentWithAnimation(animController, + animate, intent.getPackage(), (adapter) -> { + ActivityOptions options = new ActivityOptions( + CentralSurfaces.getActivityOptions(mDisplayId, adapter)); + options.setDisallowEnterPictureInPictureWhileLaunching( + disallowEnterPictureInPictureWhileLaunching); + if (CameraIntents.isInsecureCameraIntent(intent)) { + // Normally an activity will set it's requested rotation + // animation on its window. However when launching an activity + // causes the orientation to change this is too late. In these cases + // the default animation is used. This doesn't look good for + // the camera (as it rotates the camera contents out of sync + // with physical reality). So, we ask the WindowManager to + // force the crossfade animation if an orientation change + // happens to occur during the launch. + options.setRotationAnimationHint( + WindowManager.LayoutParams.ROTATION_ANIMATION_SEAMLESS); + } + if (Settings.Panel.ACTION_VOLUME.equals(intent.getAction())) { + // Settings Panel is implemented as activity(not a dialog), so + // underlying app is paused and may enter picture-in-picture mode + // as a result. + // So we need to disable picture-in-picture mode here + // if it is volume panel. + options.setDisallowEnterPictureInPictureWhileLaunching(true); + } + + try { + result[0] = ActivityTaskManager.getService().startActivityAsUser( + null, mContext.getBasePackageName(), + mContext.getAttributionTag(), + intent, + intent.resolveTypeIfNeeded(mContext.getContentResolver()), + null, null, 0, Intent.FLAG_ACTIVITY_NEW_TASK, null, + options.toBundle(), userHandle.getIdentifier()); + } catch (RemoteException e) { + Log.w(TAG, "Unable to start activity", e); + } + return result[0]; + }); + + if (callback != null) { + callback.onActivityStarted(result[0]); + } + }; + Runnable cancelRunnable = () -> { + if (callback != null) { + callback.onActivityStarted(ActivityManager.START_CANCELED); + } + }; + executeRunnableDismissingKeyguard(runnable, cancelRunnable, dismissShadeDirectly, + willLaunchResolverActivity, true /* deferred */, animate); + } + + @Nullable + private ActivityLaunchAnimator.Controller wrapAnimationController( + ActivityLaunchAnimator.Controller animationController, boolean dismissShade) { + View rootView = animationController.getLaunchContainer().getRootView(); + + Optional controllerFromStatusBar = + mStatusBarWindowController.wrapAnimationControllerIfInStatusBar( + rootView, animationController); + if (controllerFromStatusBar.isPresent()) { + return controllerFromStatusBar.get(); + } + + if (dismissShade) { + // If the view is not in the status bar, then we are animating a view in the shade. + // We have to make sure that we collapse it when the animation ends or is cancelled. + return new StatusBarLaunchAnimatorController(animationController, this, + true /* isLaunchForActivity */); + } + + return animationController; + } + + @Override + public void readyForKeyguardDone() { + mStatusBarKeyguardViewManager.readyForKeyguardDone(); + } + + @Override + public void executeRunnableDismissingKeyguard(final Runnable runnable, + final Runnable cancelAction, + final boolean dismissShade, + final boolean afterKeyguardGone, + final boolean deferred) { + executeRunnableDismissingKeyguard(runnable, cancelAction, dismissShade, afterKeyguardGone, + deferred, false /* willAnimateOnKeyguard */); + } + + @Override + public void executeRunnableDismissingKeyguard(final Runnable runnable, + final Runnable cancelAction, + final boolean dismissShade, + final boolean afterKeyguardGone, + final boolean deferred, + final boolean willAnimateOnKeyguard) { + OnDismissAction onDismissAction = new OnDismissAction() { + @Override + public boolean onDismiss() { + if (runnable != null) { + if (mStatusBarKeyguardViewManager.isShowing() + && mStatusBarKeyguardViewManager.isOccluded()) { + mStatusBarKeyguardViewManager.addAfterKeyguardGoneRunnable(runnable); + } else { + mMainExecutor.execute(runnable); + } + } + if (dismissShade) { + if (mExpandedVisible && !mBouncerShowing) { + mShadeController.animateCollapsePanels( + CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL, + true /* force */, true /* delayed*/); + } else { + + // Do it after DismissAction has been processed to conserve the needed + // ordering. + mMainExecutor.execute(mShadeController::runPostCollapseRunnables); + } + } else if (CentralSurfacesImpl.this.isInLaunchTransition() + && mNotificationPanelViewController.isLaunchTransitionFinished()) { + + // We are not dismissing the shade, but the launch transition is already + // finished, + // so nobody will call readyForKeyguardDone anymore. Post it such that + // keyguardDonePending gets called first. + mMainExecutor.execute(mStatusBarKeyguardViewManager::readyForKeyguardDone); + } + return deferred; + } + + @Override + public boolean willRunAnimationOnKeyguard() { + return willAnimateOnKeyguard; + } + }; + dismissKeyguardThenExecute(onDismissAction, cancelAction, afterKeyguardGone); + } + + private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + Trace.beginSection("CentralSurfaces#onReceive"); + if (DEBUG) Log.v(TAG, "onReceive: " + intent); + String action = intent.getAction(); + String reason = intent.getStringExtra(SYSTEM_DIALOG_REASON_KEY); + if (Intent.ACTION_CLOSE_SYSTEM_DIALOGS.equals(action)) { + KeyboardShortcuts.dismiss(); + mRemoteInputManager.closeRemoteInputs(); + if (mLockscreenUserManager.isCurrentProfile(getSendingUserId())) { + int flags = CommandQueue.FLAG_EXCLUDE_NONE; + if (reason != null) { + if (reason.equals(SYSTEM_DIALOG_REASON_RECENT_APPS)) { + flags |= CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL; + } + // Do not collapse notifications when starting dreaming if the notifications + // shade is used for the screen off animation. It might require expanded + // state for the scrims to be visible + if (reason.equals(SYSTEM_DIALOG_REASON_DREAM) + && mScreenOffAnimationController.shouldExpandNotifications()) { + flags |= CommandQueue.FLAG_EXCLUDE_NOTIFICATION_PANEL; + } + } + mShadeController.animateCollapsePanels(flags); + } + } else if (Intent.ACTION_SCREEN_OFF.equals(action)) { + if (mNotificationShadeWindowController != null) { + mNotificationShadeWindowController.setNotTouchable(false); + } + finishBarAnimations(); + resetUserExpandedStates(); + } + Trace.endSection(); + } + }; + + private final BroadcastReceiver mDemoReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + if (DEBUG) Log.v(TAG, "onReceive: " + intent); + String action = intent.getAction(); + if (ACTION_FAKE_ARTWORK.equals(action)) { + if (DEBUG_MEDIA_FAKE_ARTWORK) { + mPresenter.updateMediaMetaData(true, true); + } + } + } + }; + + @Override + public void resetUserExpandedStates() { + mNotificationsController.resetUserExpandedStates(); + } + + private void executeWhenUnlocked(OnDismissAction action, boolean requiresShadeOpen, + boolean afterKeyguardGone) { + if (mStatusBarKeyguardViewManager.isShowing() && requiresShadeOpen) { + mStatusBarStateController.setLeaveOpenOnKeyguardHide(true); + } + dismissKeyguardThenExecute(action, null /* cancelAction */, + afterKeyguardGone /* afterKeyguardGone */); + } + + protected void dismissKeyguardThenExecute(OnDismissAction action, boolean afterKeyguardGone) { + dismissKeyguardThenExecute(action, null /* cancelRunnable */, afterKeyguardGone); + } + + @Override + public void dismissKeyguardThenExecute(OnDismissAction action, Runnable cancelAction, + boolean afterKeyguardGone) { + if (mWakefulnessLifecycle.getWakefulness() == WAKEFULNESS_ASLEEP + && mKeyguardStateController.canDismissLockScreen() + && !mStatusBarStateController.leaveOpenOnKeyguardHide() + && 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( + BiometricUnlockController.MODE_WAKE_AND_UNLOCK_PULSING); + } + if (mStatusBarKeyguardViewManager.isShowing()) { + mStatusBarKeyguardViewManager.dismissWithAction(action, cancelAction, + afterKeyguardGone); + } else { + action.onDismiss(); + } + } + /** + * Notify the shade controller that the current user changed + * + * @param newUserId userId of the new user + */ + @Override + public void setLockscreenUser(int newUserId) { + if (mLockscreenWallpaper != null) { + mLockscreenWallpaper.setCurrentUser(newUserId); + } + mScrimController.setCurrentUser(newUserId); + if (mWallpaperSupported) { + mWallpaperChangedReceiver.onReceive(mContext, null); + } + } + + /** + * Reload some of our resources when the configuration changes. + * + * We don't reload everything when the configuration changes -- we probably + * should, but getting that smooth is tough. Someday we'll fix that. In the + * meantime, just update the things that we know change. + */ + void updateResources() { + // Update the quick setting tiles + if (mQSPanelController != null) { + mQSPanelController.updateResources(); + } + + if (mStatusBarWindowController != null) { + mStatusBarWindowController.refreshStatusBarHeight(); + } + + if (mNotificationPanelViewController != null) { + mNotificationPanelViewController.updateResources(); + } + if (mBrightnessMirrorController != null) { + mBrightnessMirrorController.updateResources(); + } + if (mStatusBarKeyguardViewManager != null) { + mStatusBarKeyguardViewManager.updateResources(); + } + + mPowerButtonReveal = new PowerButtonReveal(mContext.getResources().getDimensionPixelSize( + com.android.systemui.R.dimen.physical_power_button_center_screen_location_y)); + } + + // Visibility reporting + protected void handleVisibleToUserChanged(boolean visibleToUser) { + if (visibleToUser) { + handleVisibleToUserChangedImpl(visibleToUser); + mNotificationLogger.startNotificationLogging(); + } else { + mNotificationLogger.stopNotificationLogging(); + handleVisibleToUserChangedImpl(visibleToUser); + } + } + + // Visibility reporting + void handleVisibleToUserChangedImpl(boolean visibleToUser) { + if (visibleToUser) { + /* The LEDs are turned off when the notification panel is shown, even just a little bit. + * See also CentralSurfaces.setPanelExpanded for another place where we attempt to do + * this. + */ + boolean pinnedHeadsUp = mHeadsUpManager.hasPinnedHeadsUp(); + boolean clearNotificationEffects = + !mPresenter.isPresenterFullyCollapsed() && + (mState == StatusBarState.SHADE + || mState == StatusBarState.SHADE_LOCKED); + int notificationLoad = mNotificationsController.getActiveNotificationsCount(); + if (pinnedHeadsUp && mPresenter.isPresenterFullyCollapsed()) { + notificationLoad = 1; + } + final int finalNotificationLoad = notificationLoad; + mUiBgExecutor.execute(() -> { + try { + mBarService.onPanelRevealed(clearNotificationEffects, + finalNotificationLoad); + } catch (RemoteException ex) { + // Won't fail unless the world has ended. + } + }); + } else { + mUiBgExecutor.execute(() -> { + try { + mBarService.onPanelHidden(); + } catch (RemoteException ex) { + // Won't fail unless the world has ended. + } + }); + } + + } + + private void logStateToEventlog() { + boolean isShowing = mStatusBarKeyguardViewManager.isShowing(); + boolean isOccluded = mStatusBarKeyguardViewManager.isOccluded(); + boolean isBouncerShowing = mStatusBarKeyguardViewManager.isBouncerShowing(); + boolean isSecure = mKeyguardStateController.isMethodSecure(); + boolean unlocked = mKeyguardStateController.canDismissLockScreen(); + int stateFingerprint = getLoggingFingerprint(mState, + isShowing, + isOccluded, + isBouncerShowing, + isSecure, + unlocked); + if (stateFingerprint != mLastLoggedStateFingerprint) { + if (mStatusBarStateLog == null) { + mStatusBarStateLog = new LogMaker(MetricsEvent.VIEW_UNKNOWN); + } + mMetricsLogger.write(mStatusBarStateLog + .setCategory(isBouncerShowing ? MetricsEvent.BOUNCER : MetricsEvent.LOCKSCREEN) + .setType(isShowing ? MetricsEvent.TYPE_OPEN : MetricsEvent.TYPE_CLOSE) + .setSubtype(isSecure ? 1 : 0)); + EventLogTags.writeSysuiStatusBarState(mState, + isShowing ? 1 : 0, + isOccluded ? 1 : 0, + isBouncerShowing ? 1 : 0, + isSecure ? 1 : 0, + unlocked ? 1 : 0); + mLastLoggedStateFingerprint = stateFingerprint; + + StringBuilder uiEventValueBuilder = new StringBuilder(); + uiEventValueBuilder.append(isBouncerShowing ? "BOUNCER" : "LOCKSCREEN"); + uiEventValueBuilder.append(isShowing ? "_OPEN" : "_CLOSE"); + uiEventValueBuilder.append(isSecure ? "_SECURE" : "_INSECURE"); + sUiEventLogger.log(StatusBarUiEvent.valueOf(uiEventValueBuilder.toString())); + } + } + + /** + * Returns a fingerprint of fields logged to eventlog + */ + private static int getLoggingFingerprint(int statusBarState, boolean keyguardShowing, + boolean keyguardOccluded, boolean bouncerShowing, boolean secure, + boolean currentlyInsecure) { + // Reserve 8 bits for statusBarState. We'll never go higher than + // that, right? Riiiight. + return (statusBarState & 0xFF) + | ((keyguardShowing ? 1 : 0) << 8) + | ((keyguardOccluded ? 1 : 0) << 9) + | ((bouncerShowing ? 1 : 0) << 10) + | ((secure ? 1 : 0) << 11) + | ((currentlyInsecure ? 1 : 0) << 12); + } + + @Override + public void postQSRunnableDismissingKeyguard(final Runnable runnable) { + mMainExecutor.execute(() -> { + mStatusBarStateController.setLeaveOpenOnKeyguardHide(true); + executeRunnableDismissingKeyguard( + () -> mMainExecutor.execute(runnable), null, false, false, false); + }); + } + + @Override + public void postStartActivityDismissingKeyguard(PendingIntent intent) { + postStartActivityDismissingKeyguard(intent, null /* animationController */); + } + + @Override + public void postStartActivityDismissingKeyguard(final PendingIntent intent, + @Nullable ActivityLaunchAnimator.Controller animationController) { + mMainExecutor.execute(() -> startPendingIntentDismissingKeyguard(intent, + null /* intentSentUiThreadCallback */, animationController)); + } + + @Override + public void postStartActivityDismissingKeyguard(final Intent intent, int delay) { + postStartActivityDismissingKeyguard(intent, delay, null /* animationController */); + } + + @Override + public void postStartActivityDismissingKeyguard(Intent intent, int delay, + @Nullable ActivityLaunchAnimator.Controller animationController) { + mMainExecutor.executeDelayed( + () -> + startActivityDismissingKeyguard(intent, true /* onlyProvisioned */, + true /* dismissShade */, + false /* disallowEnterPictureInPictureWhileLaunching */, + null /* callback */, + 0 /* flags */, + animationController, + getActivityUserHandle(intent)), + delay); + } + + @Override + public void showKeyguard() { + mStatusBarStateController.setKeyguardRequested(true); + mStatusBarStateController.setLeaveOpenOnKeyguardHide(false); + updateIsKeyguard(); + mAssistManagerLazy.get().onLockscreenShown(); + } + + @Override + public boolean hideKeyguard() { + mStatusBarStateController.setKeyguardRequested(false); + return updateIsKeyguard(); + } + + @Override + public boolean updateIsKeyguard() { + return updateIsKeyguard(false /* forceStateChange */); + } + + @Override + public boolean updateIsKeyguard(boolean forceStateChange) { + boolean wakeAndUnlocking = mBiometricUnlockController.isWakeAndUnlock(); + + // For dozing, keyguard needs to be shown whenever the device is non-interactive. Otherwise + // 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 = mDozeServiceHost.getDozingRequested() + && (!mDeviceInteractive || (isGoingToSleep() + && (isScreenFullyOff() + || (mKeyguardStateController.isShowing() && !isOccluded())))); + boolean isWakingAndOccluded = isOccluded() && isWakingOrAwake(); + boolean shouldBeKeyguard = (mStatusBarStateController.isKeyguardRequested() + || keyguardForDozing) && !wakeAndUnlocking && !isWakingAndOccluded; + if (keyguardForDozing) { + updatePanelExpansionForKeyguard(); + } + if (shouldBeKeyguard) { + if (mScreenOffAnimationController.isKeyguardShowDelayed() + || (isGoingToSleep() + && mScreenLifecycle.getScreenState() == ScreenLifecycle.SCREEN_TURNING_OFF)) { + // Delay showing the keyguard until screen turned off. + } else { + showKeyguardImpl(); + } + } else { + // During folding a foldable device this might be called as a result of + // 'onScreenTurnedOff' call for the inner display. + // In this case: + // * When phone is locked on folding: it doesn't make sense to hide keyguard as it + // will be immediately locked again + // * When phone is unlocked: we still don't want to execute hiding of the keyguard + // as the animation could prepare 'fake AOD' interface (without actually + // transitioning to keyguard state) and this might reset the view states + if (!mScreenOffAnimationController.isKeyguardHideDelayed()) { + return hideKeyguardImpl(forceStateChange); + } + } + return false; + } + + @Override + public void showKeyguardImpl() { + Trace.beginSection("CentralSurfaces#showKeyguard"); + // In case we're locking while a smartspace transition is in progress, reset it. + mKeyguardUnlockAnimationController.resetSmartspaceTransition(); + if (mKeyguardStateController.isLaunchTransitionFadingAway()) { + mNotificationPanelViewController.cancelAnimation(); + onLaunchTransitionFadingEnded(); + } + mMessageRouter.cancelMessages(MSG_LAUNCH_TRANSITION_TIMEOUT); + if (!mLockscreenShadeTransitionController.isWakingToShadeLocked()) { + mStatusBarStateController.setState(StatusBarState.KEYGUARD); + } + updatePanelExpansionForKeyguard(); + Trace.endSection(); + } + + private void updatePanelExpansionForKeyguard() { + if (mState == StatusBarState.KEYGUARD && mBiometricUnlockController.getMode() + != BiometricUnlockController.MODE_WAKE_AND_UNLOCK && !mBouncerShowing) { + mShadeController.instantExpandNotificationsPanel(); + } + } + + private void onLaunchTransitionFadingEnded() { + mNotificationPanelViewController.resetAlpha(); + mNotificationPanelViewController.onAffordanceLaunchEnded(); + releaseGestureWakeLock(); + runLaunchTransitionEndRunnable(); + mKeyguardStateController.setLaunchTransitionFadingAway(false); + mPresenter.updateMediaMetaData(true /* metaDataChanged */, true); + } + + @Override + public boolean isInLaunchTransition() { + return mNotificationPanelViewController.isLaunchTransitionRunning() + || mNotificationPanelViewController.isLaunchTransitionFinished(); + } + + /** + * Fades the content of the keyguard away after the launch transition is done. + * + * @param beforeFading the runnable to be run when the circle is fully expanded and the fading + * starts + * @param endRunnable the runnable to be run when the transition is done. Will not run + * if the transition is cancelled, instead cancelRunnable will run + * @param cancelRunnable the runnable to be run if the transition is cancelled + */ + @Override + public void fadeKeyguardAfterLaunchTransition(final Runnable beforeFading, + Runnable endRunnable, Runnable cancelRunnable) { + mMessageRouter.cancelMessages(MSG_LAUNCH_TRANSITION_TIMEOUT); + mLaunchTransitionEndRunnable = endRunnable; + mLaunchTransitionCancelRunnable = cancelRunnable; + Runnable hideRunnable = () -> { + mKeyguardStateController.setLaunchTransitionFadingAway(true); + if (beforeFading != null) { + beforeFading.run(); + } + updateScrimController(); + mPresenter.updateMediaMetaData(false, true); + mNotificationPanelViewController.resetAlpha(); + mNotificationPanelViewController.fadeOut( + FADE_KEYGUARD_START_DELAY, FADE_KEYGUARD_DURATION, + this::onLaunchTransitionFadingEnded); + mCommandQueue.appTransitionStarting(mDisplayId, SystemClock.uptimeMillis(), + LightBarTransitionsController.DEFAULT_TINT_ANIMATION_DURATION, true); + }; + if (mNotificationPanelViewController.isLaunchTransitionRunning()) { + mNotificationPanelViewController.setLaunchTransitionEndRunnable(hideRunnable); + } else { + hideRunnable.run(); + } + } + + private void cancelAfterLaunchTransitionRunnables() { + if (mLaunchTransitionCancelRunnable != null) { + mLaunchTransitionCancelRunnable.run(); + } + mLaunchTransitionEndRunnable = null; + mLaunchTransitionCancelRunnable = null; + mNotificationPanelViewController.setLaunchTransitionEndRunnable(null); + } + + /** + * Fades the content of the Keyguard while we are dozing and makes it invisible when finished + * fading. + */ + @Override + public void fadeKeyguardWhilePulsing() { + mNotificationPanelViewController.fadeOut(0, FADE_KEYGUARD_DURATION_PULSING, + ()-> { + hideKeyguard(); + mStatusBarKeyguardViewManager.onKeyguardFadedAway(); + }).start(); + } + + /** + * Plays the animation when an activity that was occluding Keyguard goes away. + */ + @Override + public void animateKeyguardUnoccluding() { + mNotificationPanelViewController.setExpandedFraction(0f); + mCommandQueueCallbacks.animateExpandNotificationsPanel(); + mScrimController.setUnocclusionAnimationRunning(true); + } + + /** + * Starts the timeout when we try to start the affordances on Keyguard. We usually rely that + * Keyguard goes away via fadeKeyguardAfterLaunchTransition, however, that might not happen + * because the launched app crashed or something else went wrong. + */ + @Override + public void startLaunchTransitionTimeout() { + mMessageRouter.sendMessageDelayed( + MSG_LAUNCH_TRANSITION_TIMEOUT, LAUNCH_TRANSITION_TIMEOUT_MS); + } + + private void onLaunchTransitionTimeout() { + Log.w(TAG, "Launch transition: Timeout!"); + mNotificationPanelViewController.onAffordanceLaunchEnded(); + releaseGestureWakeLock(); + mNotificationPanelViewController.resetViews(false /* animate */); + } + + private void runLaunchTransitionEndRunnable() { + mLaunchTransitionCancelRunnable = null; + if (mLaunchTransitionEndRunnable != null) { + Runnable r = mLaunchTransitionEndRunnable; + + // mLaunchTransitionEndRunnable might call showKeyguard, which would execute it again, + // which would lead to infinite recursion. Protect against it. + mLaunchTransitionEndRunnable = null; + r.run(); + } + } + + /** + * @return true if we would like to stay in the shade, false if it should go away entirely + */ + @Override + public boolean hideKeyguardImpl(boolean forceStateChange) { + Trace.beginSection("CentralSurfaces#hideKeyguard"); + boolean staying = mStatusBarStateController.leaveOpenOnKeyguardHide(); + int previousState = mStatusBarStateController.getState(); + if (!(mStatusBarStateController.setState(StatusBarState.SHADE, forceStateChange))) { + //TODO: StatusBarStateController should probably know about hiding the keyguard and + // notify listeners. + + // If the state didn't change, we may still need to update public mode + mLockscreenUserManager.updatePublicMode(); + } + if (mStatusBarStateController.leaveOpenOnKeyguardHide()) { + if (!mStatusBarStateController.isKeyguardRequested()) { + mStatusBarStateController.setLeaveOpenOnKeyguardHide(false); + } + long delay = mKeyguardStateController.calculateGoingToFullShadeDelay(); + mLockscreenShadeTransitionController.onHideKeyguard(delay, previousState); + + // Disable layout transitions in navbar for this transition because the load is just + // too heavy for the CPU and GPU on any device. + mNavigationBarController.disableAnimationsDuringHide(mDisplayId, delay); + } else if (!mNotificationPanelViewController.isCollapsing()) { + instantCollapseNotificationPanel(); + } + + // Keyguard state has changed, but QS is not listening anymore. Make sure to update the tile + // visibilities so next time we open the panel we know the correct height already. + if (mQSPanelController != null) { + mQSPanelController.refreshAllTiles(); + } + mMessageRouter.cancelMessages(MSG_LAUNCH_TRANSITION_TIMEOUT); + releaseGestureWakeLock(); + mNotificationPanelViewController.onAffordanceLaunchEnded(); + mNotificationPanelViewController.resetAlpha(); + mNotificationPanelViewController.resetTranslation(); + mNotificationPanelViewController.resetViewGroupFade(); + updateDozingState(); + updateScrimController(); + Trace.endSection(); + return staying; + } + + private void releaseGestureWakeLock() { + if (mGestureWakeLock.isHeld()) { + mGestureWakeLock.release(); + } + } + + /** + * Notifies the status bar that Keyguard is going away very soon. + */ + @Override + public void keyguardGoingAway() { + // Treat Keyguard exit animation as an app transition to achieve nice transition for status + // bar. + mKeyguardStateController.notifyKeyguardGoingAway(true); + mCommandQueue.appTransitionPending(mDisplayId, true /* forced */); + updateScrimController(); + } + + /** + * Notifies the status bar the Keyguard is fading away with the specified timings. + * @param startTime the start time of the animations in uptime millis + * @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 + */ + @Override + public void setKeyguardFadingAway(long startTime, long delay, long fadeoutDuration, + boolean isBypassFading) { + mCommandQueue.appTransitionStarting(mDisplayId, startTime + fadeoutDuration + - LightBarTransitionsController.DEFAULT_TINT_ANIMATION_DURATION, + LightBarTransitionsController.DEFAULT_TINT_ANIMATION_DURATION, true); + mCommandQueue.recomputeDisableFlags(mDisplayId, fadeoutDuration > 0 /* animate */); + mCommandQueue.appTransitionStarting(mDisplayId, + startTime - LightBarTransitionsController.DEFAULT_TINT_ANIMATION_DURATION, + LightBarTransitionsController.DEFAULT_TINT_ANIMATION_DURATION, true); + mKeyguardStateController.notifyKeyguardFadingAway(delay, fadeoutDuration, isBypassFading); + } + + /** + * Notifies that the Keyguard fading away animation is done. + */ + @Override + public void finishKeyguardFadingAway() { + mKeyguardStateController.notifyKeyguardDoneFading(); + mScrimController.setExpansionAffectsAlpha(true); + + // If the device was re-locked while unlocking, we might have a pending lock that was + // delayed because the keyguard was in the middle of going away. + mKeyguardViewMediator.maybeHandlePendingLock(); + } + + /** + * Switches theme from light to dark and vice-versa. + */ + protected void updateTheme() { + // Set additional scrim only if the lock and system wallpaper are different to prevent + // applying the dimming effect twice. + mUiBgExecutor.execute(() -> { + float dimAmount = 0f; + if (mWallpaperManager.lockScreenWallpaperExists()) { + dimAmount = mWallpaperManager.getWallpaperDimAmount(); + } + final float scrimDimAmount = dimAmount; + mMainExecutor.execute(() -> { + mScrimController.setAdditionalScrimBehindAlphaKeyguard(scrimDimAmount); + mScrimController.applyCompositeAlphaOnScrimBehindKeyguard(); + }); + }); + + // Lock wallpaper defines the color of the majority of the views, hence we'll use it + // to set our default theme. + final boolean lockDarkText = mColorExtractor.getNeutralColors().supportsDarkText(); + final int themeResId = lockDarkText ? R.style.Theme_SystemUI_LightWallpaper + : R.style.Theme_SystemUI; + if (mContext.getThemeResId() != themeResId) { + mContext.setTheme(themeResId); + mConfigurationController.notifyThemeChanged(); + } + } + + private void updateDozingState() { + Trace.traceCounter(Trace.TRACE_TAG_APP, "dozing", mDozing ? 1 : 0); + Trace.beginSection("CentralSurfaces#updateDozingState"); + + boolean visibleNotOccluded = mStatusBarKeyguardViewManager.isShowing() + && !mStatusBarKeyguardViewManager.isOccluded(); + // If we're dozing and we'll be animating the screen off, the keyguard isn't currently + // visible but will be shortly for the animation, so we should proceed as if it's visible. + boolean visibleNotOccludedOrWillBe = + visibleNotOccluded || (mDozing && mDozeParameters.shouldDelayKeyguardShow()); + + boolean wakeAndUnlock = mBiometricUnlockController.getMode() + == BiometricUnlockController.MODE_WAKE_AND_UNLOCK; + boolean animate = (!mDozing && mDozeServiceHost.shouldAnimateWakeup() && !wakeAndUnlock) + || (mDozing && mDozeParameters.shouldControlScreenOff() + && visibleNotOccludedOrWillBe); + + mNotificationPanelViewController.setDozing(mDozing, animate, mWakeUpTouchLocation); + updateQsExpansionEnabled(); + Trace.endSection(); + } + + @Override + public void userActivity() { + if (mState == StatusBarState.KEYGUARD) { + mKeyguardViewMediatorCallback.userActivity(); + } + } + + @Override + public boolean interceptMediaKey(KeyEvent event) { + return mState == StatusBarState.KEYGUARD + && mStatusBarKeyguardViewManager.interceptMediaKey(event); + } + + /** + * While IME is active and a BACK event is detected, check with + * {@link StatusBarKeyguardViewManager#dispatchBackKeyEventPreIme()} to see if the event + * should be handled before routing to IME, in order to prevent the user having to hit back + * twice to exit bouncer. + */ + @Override + public boolean dispatchKeyEventPreIme(KeyEvent event) { + switch (event.getKeyCode()) { + case KeyEvent.KEYCODE_BACK: + if (mState == StatusBarState.KEYGUARD + && mStatusBarKeyguardViewManager.dispatchBackKeyEventPreIme()) { + return onBackPressed(); + } + } + return false; + } + + protected boolean shouldUnlockOnMenuPressed() { + return mDeviceInteractive && mState != StatusBarState.SHADE + && mStatusBarKeyguardViewManager.shouldDismissOnMenuPressed(); + } + + @Override + public boolean onMenuPressed() { + if (shouldUnlockOnMenuPressed()) { + mShadeController.animateCollapsePanels( + CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL /* flags */, true /* force */); + return true; + } + return false; + } + + @Override + public void endAffordanceLaunch() { + releaseGestureWakeLock(); + mNotificationPanelViewController.onAffordanceLaunchEnded(); + } + + @Override + public boolean onBackPressed() { + final boolean isScrimmedBouncer = + mScrimController.getState() == ScrimState.BOUNCER_SCRIMMED; + final boolean isBouncerOverDream = isBouncerShowingOverDream(); + + if (mStatusBarKeyguardViewManager.onBackPressed( + isScrimmedBouncer || isBouncerOverDream /* hideImmediately */)) { + if (isScrimmedBouncer || isBouncerOverDream) { + mStatusBarStateController.setLeaveOpenOnKeyguardHide(false); + } else { + mNotificationPanelViewController.expandWithoutQs(); + } + return true; + } + if (mNotificationPanelViewController.isQsCustomizing()) { + mNotificationPanelViewController.closeQsCustomizer(); + return true; + } + if (mNotificationPanelViewController.isQsExpanded()) { + if (mNotificationPanelViewController.isQsDetailShowing()) { + mNotificationPanelViewController.closeQsDetail(); + } else { + mNotificationPanelViewController.animateCloseQs(false /* animateAway */); + } + return true; + } + if (mNotificationPanelViewController.closeUserSwitcherIfOpen()) { + return true; + } + if (mState != StatusBarState.KEYGUARD && mState != StatusBarState.SHADE_LOCKED + && !isBouncerOverDream) { + if (mNotificationPanelViewController.canPanelBeCollapsed()) { + mShadeController.animateCollapsePanels(); + } + return true; + } + return false; + } + + @Override + public boolean onSpacePressed() { + if (mDeviceInteractive && mState != StatusBarState.SHADE) { + mShadeController.animateCollapsePanels( + CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL /* flags */, true /* force */); + return true; + } + return false; + } + + private void showBouncerOrLockScreenIfKeyguard() { + // If the keyguard is animating away, we aren't really the keyguard anymore and should not + // show the bouncer/lockscreen. + if (!mKeyguardViewMediator.isHiding() + && !mKeyguardUnlockAnimationController.isPlayingCannedUnlockAnimation()) { + if (mState == StatusBarState.SHADE_LOCKED + && mKeyguardUpdateMonitor.isUdfpsEnrolled()) { + // shade is showing while locked on the keyguard, so go back to showing the + // lock screen where users can use the UDFPS affordance to enter the device + mStatusBarKeyguardViewManager.reset(true); + } else if ((mState == StatusBarState.KEYGUARD + && !mStatusBarKeyguardViewManager.bouncerIsOrWillBeShowing()) + || mState == StatusBarState.SHADE_LOCKED) { + mStatusBarKeyguardViewManager.showGenericBouncer(true /* scrimmed */); + } + } + } + + /** + * Show the bouncer if we're currently on the keyguard or shade locked and aren't hiding. + * @param performAction the action to perform when the bouncer is dismissed. + * @param cancelAction the action to perform when unlock is aborted. + */ + @Override + public void showBouncerWithDimissAndCancelIfKeyguard(OnDismissAction performAction, + Runnable cancelAction) { + if ((mState == StatusBarState.KEYGUARD || mState == StatusBarState.SHADE_LOCKED) + && !mKeyguardViewMediator.isHiding()) { + mStatusBarKeyguardViewManager.dismissWithAction(performAction, cancelAction, + false /* afterKeyguardGone */); + } else if (cancelAction != null) { + cancelAction.run(); + } + } + + @Override + public void instantCollapseNotificationPanel() { + mNotificationPanelViewController.instantCollapse(); + mShadeController.runPostCollapseRunnables(); + } + + /** + * Collapse the panel directly if we are on the main thread, post the collapsing on the main + * thread if we are not. + */ + @Override + public void collapsePanelOnMainThread() { + if (Looper.getMainLooper().isCurrentThread()) { + mShadeController.collapsePanel(); + } else { + mContext.getMainExecutor().execute(mShadeController::collapsePanel); + } + } + + /** Collapse the panel. The collapsing will be animated for the given {@code duration}. */ + @Override + public void collapsePanelWithDuration(int duration) { + mNotificationPanelViewController.collapseWithDuration(duration); + } + + /** + * Updates the light reveal effect to reflect the reason we're waking or sleeping (for example, + * from the power button). + * @param wakingUp Whether we're updating because we're waking up (true) or going to sleep + * (false). + */ + private void updateRevealEffect(boolean wakingUp) { + if (mLightRevealScrim == null) { + return; + } + + final boolean wakingUpFromPowerButton = wakingUp + && !(mLightRevealScrim.getRevealEffect() instanceof CircleReveal) + && mWakefulnessLifecycle.getLastWakeReason() + == PowerManager.WAKE_REASON_POWER_BUTTON; + final boolean sleepingFromPowerButton = !wakingUp + && mWakefulnessLifecycle.getLastSleepReason() + == PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON; + + if (wakingUpFromPowerButton || sleepingFromPowerButton) { + mLightRevealScrim.setRevealEffect(mPowerButtonReveal); + mLightRevealScrim.setRevealAmount(1f - mStatusBarStateController.getDozeAmount()); + } else if (!wakingUp || !(mLightRevealScrim.getRevealEffect() instanceof CircleReveal)) { + // If we're going to sleep, but it's not from the power button, use the default reveal. + // If we're waking up, only use the default reveal if the biometric controller didn't + // already set it to the circular reveal because we're waking up from a fingerprint/face + // auth. + mLightRevealScrim.setRevealEffect(LiftReveal.INSTANCE); + mLightRevealScrim.setRevealAmount(1f - mStatusBarStateController.getDozeAmount()); + } + } + + @Override + public LightRevealScrim getLightRevealScrim() { + return mLightRevealScrim; + } + + @Override + public void onTrackingStarted() { + mShadeController.runPostCollapseRunnables(); + } + + @Override + public void onClosingFinished() { + mShadeController.runPostCollapseRunnables(); + if (!mPresenter.isPresenterFullyCollapsed()) { + // if we set it not to be focusable when collapsing, we have to undo it when we aborted + // the closing + mNotificationShadeWindowController.setNotificationShadeFocusable(true); + } + } + + @Override + public void onUnlockHintStarted() { + mFalsingCollector.onUnlockHintStarted(); + mKeyguardIndicationController.showActionToUnlock(); + } + + @Override + public void onHintFinished() { + // Delay the reset a bit so the user can read the text. + mKeyguardIndicationController.hideTransientIndicationDelayed(HINT_RESET_DELAY_MS); + } + + @Override + public void onCameraHintStarted() { + mFalsingCollector.onCameraHintStarted(); + mKeyguardIndicationController.showTransientIndication(R.string.camera_hint); + } + + @Override + public void onVoiceAssistHintStarted() { + mFalsingCollector.onLeftAffordanceHintStarted(); + mKeyguardIndicationController.showTransientIndication(R.string.voice_hint); + } + + @Override + public void onPhoneHintStarted() { + mFalsingCollector.onLeftAffordanceHintStarted(); + mKeyguardIndicationController.showTransientIndication(R.string.phone_hint); + } + + @Override + public void onTrackingStopped(boolean expand) { + if (mState == StatusBarState.KEYGUARD || mState == StatusBarState.SHADE_LOCKED) { + if (!expand && !mKeyguardStateController.canDismissLockScreen()) { + mStatusBarKeyguardViewManager.showBouncer(false /* scrimmed */); + } + } + } + + // TODO: Figure out way to remove these. + @Override + public NavigationBarView getNavigationBarView() { + return mNavigationBarController.getNavigationBarView(mDisplayId); + } + + @Override + public boolean isOverviewEnabled() { + return mNavigationBarController.isOverviewEnabled(mDisplayId); + } + + @Override + public void showPinningEnterExitToast(boolean entering) { + mNavigationBarController.showPinningEnterExitToast(mDisplayId, entering); + } + + @Override + public void showPinningEscapeToast() { + mNavigationBarController.showPinningEscapeToast(mDisplayId); + } + + /** + * TODO: Remove this method. Views should not be passed forward. Will cause theme issues. + * @return bottom area view + */ + @Override + public KeyguardBottomAreaView getKeyguardBottomAreaView() { + return mNotificationPanelViewController.getKeyguardBottomAreaView(); + } + + /** + * Propagation of the bouncer state, indicating that it's fully visible. + */ + @Override + public void setBouncerShowing(boolean bouncerShowing) { + mBouncerShowing = bouncerShowing; + mKeyguardBypassController.setBouncerShowing(bouncerShowing); + mPulseExpansionHandler.setBouncerShowing(bouncerShowing); + setBouncerShowingForStatusBarComponents(bouncerShowing); + mStatusBarHideIconsForBouncerManager.setBouncerShowingAndTriggerUpdate(bouncerShowing); + mCommandQueue.recomputeDisableFlags(mDisplayId, true /* animate */); + updateScrimController(); + if (!mBouncerShowing) { + updatePanelExpansionForKeyguard(); + } + } + + /** + * Sets whether the bouncer over dream is showing. Note that the bouncer over dream is handled + * independently of the rest of the notification panel. As a result, setting this state via + * {@link #setBouncerShowing(boolean)} leads to unintended side effects from states modified + * behind the dream. + */ + @Override + public void setBouncerShowingOverDream(boolean bouncerShowingOverDream) { + mBouncerShowingOverDream = bouncerShowingOverDream; + } + + /** + * Propagate the bouncer state to status bar components. + * + * Separate from {@link #setBouncerShowing} because we sometimes re-create the status bar and + * should update only the status bar components. + */ + private void setBouncerShowingForStatusBarComponents(boolean bouncerShowing) { + int importance = bouncerShowing + ? IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS + : IMPORTANT_FOR_ACCESSIBILITY_AUTO; + if (mPhoneStatusBarViewController != null) { + mPhoneStatusBarViewController.setImportantForAccessibility(importance); + } + mNotificationPanelViewController.setImportantForAccessibility(importance); + mNotificationPanelViewController.setBouncerShowing(bouncerShowing); + } + + /** + * Collapses the notification shade if it is tracking or expanded. + */ + @Override + public void collapseShade() { + if (mNotificationPanelViewController.isTracking()) { + mNotificationShadeWindowViewController.cancelCurrentTouch(); + } + if (mPanelExpanded && mState == StatusBarState.SHADE) { + mShadeController.animateCollapsePanels(); + } + } + + @VisibleForTesting + final WakefulnessLifecycle.Observer mWakefulnessObserver = new WakefulnessLifecycle.Observer() { + @Override + public void onFinishedGoingToSleep() { + mNotificationPanelViewController.onAffordanceLaunchEnded(); + releaseGestureWakeLock(); + mLaunchCameraWhenFinishedWaking = false; + mDeviceInteractive = false; + mWakeUpComingFromTouch = false; + mWakeUpTouchLocation = null; + updateVisibleToUser(); + + updateNotificationPanelTouchState(); + mNotificationShadeWindowViewController.cancelCurrentTouch(); + if (mLaunchCameraOnFinishedGoingToSleep) { + mLaunchCameraOnFinishedGoingToSleep = false; + + // This gets executed before we will show Keyguard, so post it in order that the state + // is correct. + mMainExecutor.execute(() -> mCommandQueueCallbacks.onCameraLaunchGestureDetected( + mLastCameraLaunchSource)); + } + + if (mLaunchEmergencyActionOnFinishedGoingToSleep) { + mLaunchEmergencyActionOnFinishedGoingToSleep = false; + + // This gets executed before we will show Keyguard, so post it in order that the + // state is correct. + mMainExecutor.execute( + () -> mCommandQueueCallbacks.onEmergencyActionLaunchGestureDetected()); + } + updateIsKeyguard(); + } + + @Override + public void onStartedGoingToSleep() { + String tag = "CentralSurfaces#onStartedGoingToSleep"; + DejankUtils.startDetectingBlockingIpcs(tag); + + // cancel stale runnables that could put the device in the wrong state + cancelAfterLaunchTransitionRunnables(); + + updateRevealEffect(false /* wakingUp */); + updateNotificationPanelTouchState(); + maybeEscalateHeadsUp(); + dismissVolumeDialog(); + mWakeUpCoordinator.setFullyAwake(false); + mKeyguardBypassController.onStartedGoingToSleep(); + + // The unlocked screen off and fold to aod animations might use our LightRevealScrim - + // we need to be expanded for it to be visible. + if (mDozeParameters.shouldShowLightRevealScrim()) { + makeExpandedVisible(true); + } + + DejankUtils.stopDetectingBlockingIpcs(tag); + } + + @Override + public void onStartedWakingUp() { + String tag = "CentralSurfaces#onStartedWakingUp"; + DejankUtils.startDetectingBlockingIpcs(tag); + mNotificationShadeWindowController.batchApplyWindowLayoutParams(()-> { + mDeviceInteractive = true; + mWakeUpCoordinator.setWakingUp(true); + if (!mKeyguardBypassController.getBypassEnabled()) { + mHeadsUpManager.releaseAllImmediately(); + } + updateVisibleToUser(); + updateIsKeyguard(); + mDozeServiceHost.stopDozing(); + // This is intentionally below the stopDozing call above, since it avoids that we're + // unnecessarily animating the wakeUp transition. Animations should only be enabled + // once we fully woke up. + updateRevealEffect(true /* wakingUp */); + updateNotificationPanelTouchState(); + + // If we are waking up during the screen off animation, we should undo making the + // expanded visible (we did that so the LightRevealScrim would be visible). + if (mScreenOffAnimationController.shouldHideLightRevealScrimOnWakeUp()) { + makeExpandedInvisible(); + } + + }); + DejankUtils.stopDetectingBlockingIpcs(tag); + } + + @Override + public void onFinishedWakingUp() { + mWakeUpCoordinator.setFullyAwake(true); + mWakeUpCoordinator.setWakingUp(false); + if (mLaunchCameraWhenFinishedWaking) { + mNotificationPanelViewController.launchCamera( + false /* animate */, mLastCameraLaunchSource); + mLaunchCameraWhenFinishedWaking = false; + } + if (mLaunchEmergencyActionWhenFinishedWaking) { + mLaunchEmergencyActionWhenFinishedWaking = false; + Intent emergencyIntent = getEmergencyActionIntent(); + if (emergencyIntent != null) { + mContext.startActivityAsUser(emergencyIntent, + getActivityUserHandle(emergencyIntent)); + } + } + updateScrimController(); + } + }; + + /** + * We need to disable touch events because these might + * collapse the panel after we expanded it, and thus we would end up with a blank + * Keyguard. + */ + @Override + public void updateNotificationPanelTouchState() { + boolean goingToSleepWithoutAnimation = isGoingToSleep() + && !mDozeParameters.shouldControlScreenOff(); + boolean disabled = (!mDeviceInteractive && !mDozeServiceHost.isPulsing()) + || goingToSleepWithoutAnimation; + mNotificationPanelViewController.setTouchAndAnimationDisabled(disabled); + mNotificationIconAreaController.setAnimationsEnabled(!disabled); + } + + final ScreenLifecycle.Observer mScreenObserver = new ScreenLifecycle.Observer() { + @Override + public void onScreenTurningOn(Runnable onDrawn) { + mFalsingCollector.onScreenTurningOn(); + mNotificationPanelViewController.onScreenTurningOn(); + } + + @Override + public void onScreenTurnedOn() { + mScrimController.onScreenTurnedOn(); + } + + @Override + public void onScreenTurnedOff() { + Trace.beginSection("CentralSurfaces#onScreenTurnedOff"); + mFalsingCollector.onScreenOff(); + mScrimController.onScreenTurnedOff(); + if (mCloseQsBeforeScreenOff) { + mNotificationPanelViewController.closeQs(); + mCloseQsBeforeScreenOff = false; + } + updateIsKeyguard(); + Trace.endSection(); + } + }; + + @Override + public int getWakefulnessState() { + return mWakefulnessLifecycle.getWakefulness(); + } + + /** + * @return true if the screen is currently fully off, i.e. has finished turning off and has + * since not started turning on. + */ + @Override + public boolean isScreenFullyOff() { + return mScreenLifecycle.getScreenState() == ScreenLifecycle.SCREEN_OFF; + } + + @Override + public void showScreenPinningRequest(int taskId, boolean allowCancel) { + mScreenPinningRequest.showPrompt(taskId, allowCancel); + } + + @Nullable + @Override + public Intent getEmergencyActionIntent() { + Intent emergencyIntent = new Intent(EmergencyGesture.ACTION_LAUNCH_EMERGENCY); + PackageManager pm = mContext.getPackageManager(); + List emergencyActivities = pm.queryIntentActivities(emergencyIntent, + PackageManager.MATCH_SYSTEM_ONLY); + ResolveInfo resolveInfo = getTopEmergencySosInfo(emergencyActivities); + if (resolveInfo == null) { + Log.wtf(TAG, "Couldn't find an app to process the emergency intent."); + return null; + } + emergencyIntent.setComponent(new ComponentName(resolveInfo.activityInfo.packageName, + resolveInfo.activityInfo.name)); + emergencyIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + return emergencyIntent; + } + + /** + * Select and return the "best" ResolveInfo for Emergency SOS Activity. + */ + private @Nullable ResolveInfo getTopEmergencySosInfo(List emergencyActivities) { + // No matched activity. + if (emergencyActivities == null || emergencyActivities.isEmpty()) { + return null; + } + + // Of multiple matched Activities, give preference to the pre-set package name. + String preferredAppPackageName = + mContext.getString(R.string.config_preferredEmergencySosPackage); + + // If there is no preferred app, then return first match. + if (TextUtils.isEmpty(preferredAppPackageName)) { + return emergencyActivities.get(0); + } + + for (ResolveInfo emergencyInfo: emergencyActivities) { + // If activity is from the preferred app, use it. + if (TextUtils.equals(emergencyInfo.activityInfo.packageName, preferredAppPackageName)) { + return emergencyInfo; + } + } + // No matching activity: return first match + return emergencyActivities.get(0); + } + + @Override + public boolean isCameraAllowedByAdmin() { + 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; + } + + @Override + public boolean isGoingToSleep() { + return mWakefulnessLifecycle.getWakefulness() + == WakefulnessLifecycle.WAKEFULNESS_GOING_TO_SLEEP; + } + + boolean isWakingOrAwake() { + return mWakefulnessLifecycle.getWakefulness() == WakefulnessLifecycle.WAKEFULNESS_WAKING + || mWakefulnessLifecycle.getWakefulness() == WakefulnessLifecycle.WAKEFULNESS_AWAKE; + } + + @Override + public void notifyBiometricAuthModeChanged() { + mDozeServiceHost.updateDozing(); + updateScrimController(); + } + + /** + * Set the amount of progress we are currently in if we're transitioning to the full shade. + * 0.0f means we're not transitioning yet, while 1 means we're all the way in the full + * shade. + */ + @Override + public void setTransitionToFullShadeProgress(float transitionToFullShadeProgress) { + mTransitionToFullShadeProgress = transitionToFullShadeProgress; + } + + /** + * Sets the amount of progress to the bouncer being fully hidden/visible. 1 means the bouncer + * is fully hidden, while 0 means the bouncer is visible. + */ + @Override + public void setBouncerHiddenFraction(float expansion) { + mScrimController.setBouncerHiddenFraction(expansion); + } + + @Override + @VisibleForTesting + public void updateScrimController() { + Trace.beginSection("CentralSurfaces#updateScrimController"); + + boolean unlocking = mKeyguardStateController.isShowing() && ( + mBiometricUnlockController.isWakeAndUnlock() + || mKeyguardStateController.isKeyguardFadingAway() + || mKeyguardStateController.isKeyguardGoingAway() + || mKeyguardViewMediator.requestedShowSurfaceBehindKeyguard() + || mKeyguardViewMediator.isAnimatingBetweenKeyguardAndSurfaceBehind()); + + mScrimController.setExpansionAffectsAlpha(!unlocking); + + boolean launchingAffordanceWithPreview = + mNotificationPanelViewController.isLaunchingAffordanceWithPreview(); + mScrimController.setLaunchingAffordanceWithPreview(launchingAffordanceWithPreview); + + if (mStatusBarKeyguardViewManager.isShowingAlternateAuth()) { + if (mState == StatusBarState.SHADE || mState == StatusBarState.SHADE_LOCKED + || mTransitionToFullShadeProgress > 0f) { + mScrimController.transitionTo(ScrimState.AUTH_SCRIMMED_SHADE); + } else { + mScrimController.transitionTo(ScrimState.AUTH_SCRIMMED); + } + } else if (mBouncerShowing && !unlocking) { + // Bouncer needs the front scrim when it's on top of an activity, + // tapping on a notification, editing QS or being dismissed by + // FLAG_DISMISS_KEYGUARD_ACTIVITY. + ScrimState state = mStatusBarKeyguardViewManager.bouncerNeedsScrimming() + ? ScrimState.BOUNCER_SCRIMMED : ScrimState.BOUNCER; + mScrimController.transitionTo(state); + } else if (launchingAffordanceWithPreview) { + // We want to avoid animating when launching with a preview. + mScrimController.transitionTo(ScrimState.UNLOCKED, mUnlockScrimCallback); + } else if (mBrightnessMirrorVisible) { + mScrimController.transitionTo(ScrimState.BRIGHTNESS_MIRROR); + } else if (mState == StatusBarState.SHADE_LOCKED) { + mScrimController.transitionTo(ScrimState.SHADE_LOCKED); + } 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 (mKeyguardStateController.isShowing() && !isOccluded() && !unlocking) { + mScrimController.transitionTo(ScrimState.KEYGUARD); + } else if (mKeyguardStateController.isShowing() && mKeyguardUpdateMonitor.isDreaming()) { + mScrimController.transitionTo(ScrimState.DREAMING); + } else { + mScrimController.transitionTo(ScrimState.UNLOCKED, mUnlockScrimCallback); + } + updateLightRevealScrimVisibility(); + + Trace.endSection(); + } + + @Override + public boolean isKeyguardShowing() { + if (mStatusBarKeyguardViewManager == null) { + Slog.i(TAG, "isKeyguardShowing() called before startKeyguard(), returning true"); + return true; + } + return mStatusBarKeyguardViewManager.isShowing(); + } + + @Override + public boolean shouldIgnoreTouch() { + return (mStatusBarStateController.isDozing() + && mDozeServiceHost.getIgnoreTouchWhilePulsing()) + || mScreenOffAnimationController.shouldIgnoreKeyguardTouches(); + } + + // Begin Extra BaseStatusBar methods. + + protected final CommandQueue mCommandQueue; + protected IStatusBarService mBarService; + + // all notifications + protected NotificationStackScrollLayout mStackScroller; + + // handling reordering + private final VisualStabilityManager mVisualStabilityManager; + + protected AccessibilityManager mAccessibilityManager; + + protected boolean mDeviceInteractive; + + protected boolean mVisible; + + // mScreenOnFromKeyguard && mVisible. + private boolean mVisibleToUser; + + protected DevicePolicyManager mDevicePolicyManager; + private final PowerManager mPowerManager; + protected StatusBarKeyguardViewManager mStatusBarKeyguardViewManager; + + protected KeyguardManager mKeyguardManager; + private final DeviceProvisionedController mDeviceProvisionedController; + + private final NavigationBarController mNavigationBarController; + private final AccessibilityFloatingMenuController mAccessibilityFloatingMenuController; + + // UI-specific methods + + protected WindowManager mWindowManager; + protected IWindowManager mWindowManagerService; + private IDreamManager mDreamManager; + + protected Display mDisplay; + private int mDisplayId; + + protected NotificationShelfController mNotificationShelfController; + + private final Lazy mAssistManagerLazy; + + @Override + public boolean isDeviceInteractive() { + return mDeviceInteractive; + } + + private final BroadcastReceiver mBannerActionBroadcastReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + String action = intent.getAction(); + if (BANNER_ACTION_CANCEL.equals(action) || BANNER_ACTION_SETUP.equals(action)) { + NotificationManager noMan = (NotificationManager) + mContext.getSystemService(Context.NOTIFICATION_SERVICE); + noMan.cancel(com.android.internal.messages.nano.SystemMessageProto.SystemMessage. + NOTE_HIDDEN_NOTIFICATIONS); + + Settings.Secure.putInt(mContext.getContentResolver(), + Settings.Secure.SHOW_NOTE_ABOUT_NOTIFICATION_HIDING, 0); + if (BANNER_ACTION_SETUP.equals(action)) { + mShadeController.animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL, + true /* force */); + mContext.startActivity(new Intent(Settings.ACTION_APP_NOTIFICATION_REDACTION) + .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) + + ); + } + } + } + }; + + @Override + public void setNotificationSnoozed(StatusBarNotification sbn, SnoozeOption snoozeOption) { + mNotificationsController.setNotificationSnoozed(sbn, snoozeOption); + } + + + @Override + public void awakenDreams() { + mUiBgExecutor.execute(() -> { + try { + mDreamManager.awaken(); + } catch (RemoteException e) { + e.printStackTrace(); + } + }); + } + + protected void toggleKeyboardShortcuts(int deviceId) { + KeyboardShortcuts.toggle(mContext, deviceId); + } + + protected void dismissKeyboardShortcuts() { + KeyboardShortcuts.dismiss(); + } + + /** + * Dismiss the keyguard then execute an action. + * + * @param action The action to execute after dismissing the keyguard. + * @param collapsePanel Whether we should collapse the panel after dismissing the keyguard. + * @param willAnimateOnKeyguard Whether {@param action} will run an animation on the keyguard if + * we are locked. + */ + private void executeActionDismissingKeyguard(Runnable action, boolean afterKeyguardGone, + boolean collapsePanel, boolean willAnimateOnKeyguard) { + if (!mDeviceProvisionedController.isDeviceProvisioned()) return; + + OnDismissAction onDismissAction = new OnDismissAction() { + @Override + public boolean onDismiss() { + new Thread(() -> { + try { + // The intent we are sending is for the application, which + // won't have permission to immediately start an activity after + // the user switches to home. We know it is safe to do at this + // point, so make sure new activity switches are now allowed. + ActivityManager.getService().resumeAppSwitches(); + } catch (RemoteException e) { + } + action.run(); + }).start(); + + return collapsePanel ? mShadeController.collapsePanel() : willAnimateOnKeyguard; + } + + @Override + public boolean willRunAnimationOnKeyguard() { + return willAnimateOnKeyguard; + } + }; + dismissKeyguardThenExecute(onDismissAction, afterKeyguardGone); + } + + @Override + public void startPendingIntentDismissingKeyguard(final PendingIntent intent) { + startPendingIntentDismissingKeyguard(intent, null); + } + + @Override + public void startPendingIntentDismissingKeyguard( + final PendingIntent intent, @Nullable final Runnable intentSentUiThreadCallback) { + startPendingIntentDismissingKeyguard(intent, intentSentUiThreadCallback, + (ActivityLaunchAnimator.Controller) null); + } + + @Override + public void startPendingIntentDismissingKeyguard(PendingIntent intent, + Runnable intentSentUiThreadCallback, View associatedView) { + ActivityLaunchAnimator.Controller animationController = null; + if (associatedView instanceof ExpandableNotificationRow) { + animationController = mNotificationAnimationProvider.getAnimatorController( + ((ExpandableNotificationRow) associatedView)); + } + + startPendingIntentDismissingKeyguard(intent, intentSentUiThreadCallback, + animationController); + } + + @Override + public void startPendingIntentDismissingKeyguard( + final PendingIntent intent, @Nullable final Runnable intentSentUiThreadCallback, + @Nullable ActivityLaunchAnimator.Controller animationController) { + final boolean willLaunchResolverActivity = intent.isActivity() + && mActivityIntentHelper.wouldLaunchResolverActivity(intent.getIntent(), + mLockscreenUserManager.getCurrentUserId()); + + boolean animate = !willLaunchResolverActivity + && animationController != null + && shouldAnimateLaunch(intent.isActivity()); + + // If we animate, don't collapse the shade and defer the keyguard dismiss (in case we run + // the animation on the keyguard). The animation will take care of (instantly) collapsing + // the shade and hiding the keyguard once it is done. + boolean collapse = !animate; + executeActionDismissingKeyguard(() -> { + try { + // We wrap animationCallback with a StatusBarLaunchAnimatorController so that the + // shade is collapsed after the animation (or when it is cancelled, aborted, etc). + ActivityLaunchAnimator.Controller controller = + animationController != null ? new StatusBarLaunchAnimatorController( + animationController, this, intent.isActivity()) : null; + + mActivityLaunchAnimator.startPendingIntentWithAnimation( + controller, animate, intent.getCreatorPackage(), + (animationAdapter) -> { + ActivityOptions options = new ActivityOptions( + CentralSurfaces.getActivityOptions( + mDisplayId, animationAdapter)); + // TODO b/221255671: restrict this to only be set for notifications + options.setEligibleForLegacyPermissionPrompt(true); + return intent.sendAndReturnResult(null, 0, null, null, null, + null, options.toBundle()); + }); + } catch (PendingIntent.CanceledException e) { + // the stack trace isn't very helpful here. + // Just log the exception message. + Log.w(TAG, "Sending intent failed: " + e); + if (!collapse) { + // executeActionDismissingKeyguard did not collapse for us already. + collapsePanelOnMainThread(); + } + // TODO: Dismiss Keyguard. + } + if (intent.isActivity()) { + mAssistManagerLazy.get().hideAssist(); + } + if (intentSentUiThreadCallback != null) { + postOnUiThread(intentSentUiThreadCallback); + } + }, willLaunchResolverActivity, collapse, animate); + } + + private void postOnUiThread(Runnable runnable) { + mMainExecutor.execute(runnable); + } + + @Override + public void visibilityChanged(boolean visible) { + if (mVisible != visible) { + mVisible = visible; + if (!visible) { + mGutsManager.closeAndSaveGuts(true /* removeLeavebehind */, true /* force */, + true /* removeControls */, -1 /* x */, -1 /* y */, true /* resetMenu */); + } + } + updateVisibleToUser(); + } + + protected void updateVisibleToUser() { + boolean oldVisibleToUser = mVisibleToUser; + mVisibleToUser = mVisible && mDeviceInteractive; + + if (oldVisibleToUser != mVisibleToUser) { + handleVisibleToUserChanged(mVisibleToUser); + } + } + + /** + * Clear Buzz/Beep/Blink. + */ + @Override + public void clearNotificationEffects() { + try { + mBarService.clearNotificationEffects(); + } catch (RemoteException e) { + // Won't fail unless the world has ended. + } + } + + /** + * @return Whether the security bouncer from Keyguard is showing. + */ + @Override + public boolean isBouncerShowing() { + return mBouncerShowing; + } + + /** + * @return Whether the security bouncer from Keyguard is showing. + */ + @Override + public boolean isBouncerShowingScrimmed() { + return isBouncerShowing() && mStatusBarKeyguardViewManager.bouncerNeedsScrimming(); + } + + @Override + public boolean isBouncerShowingOverDream() { + return mBouncerShowingOverDream; + } + + /** + * When {@link KeyguardBouncer} starts to be dismissed, playing its animation. + */ + @Override + public void onBouncerPreHideAnimation() { + mNotificationPanelViewController.onBouncerPreHideAnimation(); + + } + + @Override + public boolean isKeyguardSecure() { + if (mStatusBarKeyguardViewManager == null) { + // startKeyguard() hasn't been called yet, so we don't know. + // Make sure anything that needs to know isKeyguardSecure() checks and re-checks this + // value onVisibilityChanged(). + Slog.w(TAG, "isKeyguardSecure() called before startKeyguard(), returning false", + new Throwable()); + return false; + } + return mStatusBarKeyguardViewManager.isSecure(); + } + @Override + public NotificationPanelViewController getPanelController() { + return mNotificationPanelViewController; + } + // End Extra BaseStatusBarMethods. + + @Override + public NotificationGutsManager getGutsManager() { + return mGutsManager; + } + + boolean isTransientShown() { + return mTransientShown; + } + + private void updateLightRevealScrimVisibility() { + if (mLightRevealScrim == null) { + // status bar may not be inflated yet + return; + } + + mLightRevealScrim.setAlpha(mScrimController.getState().getMaxLightRevealScrimAlpha()); + } + + @Override + public void extendDozePulse(){ + mDozeScrimController.extendPulse(); + } + + private final KeyguardUpdateMonitorCallback mUpdateCallback = + new KeyguardUpdateMonitorCallback() { + @Override + public void onDreamingStateChanged(boolean dreaming) { + updateScrimController(); + if (dreaming) { + maybeEscalateHeadsUp(); + } + } + + // TODO: (b/145659174) remove when moving to NewNotifPipeline. Replaced by + // KeyguardCoordinator + @Override + public void onStrongAuthStateChanged(int userId) { + super.onStrongAuthStateChanged(userId); + mNotificationsController.requestNotificationUpdate("onStrongAuthStateChanged"); + } + }; + + + private final FalsingManager.FalsingBeliefListener mFalsingBeliefListener = + new FalsingManager.FalsingBeliefListener() { + @Override + public void onFalse() { + // Hides quick settings, bouncer, and quick-quick settings. + mStatusBarKeyguardViewManager.reset(true); + } + }; + + // Notifies StatusBarKeyguardViewManager every time the keyguard transition is over, + // this animation is tied to the scrim for historic reasons. + // TODO: notify when keyguard has faded away instead of the scrim. + private final ScrimController.Callback mUnlockScrimCallback = new ScrimController + .Callback() { + @Override + public void onFinished() { + if (mStatusBarKeyguardViewManager == null) { + Log.w(TAG, "Tried to notify keyguard visibility when " + + "mStatusBarKeyguardViewManager was null"); + return; + } + if (mKeyguardStateController.isKeyguardFadingAway()) { + mStatusBarKeyguardViewManager.onKeyguardFadedAway(); + } + } + + @Override + public void onCancelled() { + onFinished(); + } + }; + + private final DeviceProvisionedListener mUserSetupObserver = new DeviceProvisionedListener() { + @Override + public void onUserSetupChanged() { + final boolean userSetup = mDeviceProvisionedController.isCurrentUserSetup(); + Log.d(TAG, "mUserSetupObserver - DeviceProvisionedListener called for " + + "current user"); + if (MULTIUSER_DEBUG) { + Log.d(TAG, String.format("User setup changed: userSetup=%s mUserSetup=%s", + userSetup, mUserSetup)); + } + + if (userSetup != mUserSetup) { + mUserSetup = userSetup; + if (!mUserSetup) { + animateCollapseQuickSettings(); + } + if (mNotificationPanelViewController != null) { + mNotificationPanelViewController.setUserSetupComplete(mUserSetup); + } + updateQsExpansionEnabled(); + } + } + }; + + private final BroadcastReceiver mWallpaperChangedReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + if (!mWallpaperSupported) { + // Receiver should not have been registered at all... + Log.wtf(TAG, "WallpaperManager not supported"); + return; + } + WallpaperInfo info = mWallpaperManager.getWallpaperInfo(UserHandle.USER_CURRENT); + mWallpaperController.onWallpaperInfoUpdated(info); + + final boolean deviceSupportsAodWallpaper = mContext.getResources().getBoolean( + com.android.internal.R.bool.config_dozeSupportsAodWallpaper); + // If WallpaperInfo is null, it must be ImageWallpaper. + final boolean supportsAmbientMode = deviceSupportsAodWallpaper + && (info != null && info.supportsAmbientMode()); + + mNotificationShadeWindowController.setWallpaperSupportsAmbientMode(supportsAmbientMode); + mScrimController.setWallpaperSupportsAmbientMode(supportsAmbientMode); + mKeyguardViewMediator.setWallpaperSupportsAmbientMode(supportsAmbientMode); + } + }; + + private final ConfigurationListener mConfigurationListener = new ConfigurationListener() { + @Override + public void onConfigChanged(Configuration newConfig) { + updateResources(); + updateDisplaySize(); // populates mDisplayMetrics + + if (DEBUG) { + Log.v(TAG, "configuration changed: " + mContext.getResources().getConfiguration()); + } + + if (!mNotifPipelineFlags.isNewPipelineEnabled()) { + mViewHierarchyManager.updateRowStates(); + } + mScreenPinningRequest.onConfigurationChanged(); + } + + @Override + public void onDensityOrFontScaleChanged() { + // TODO: Remove this. + if (mBrightnessMirrorController != null) { + mBrightnessMirrorController.onDensityOrFontScaleChanged(); + } + // TODO: Bring these out of CentralSurfaces. + mUserInfoControllerImpl.onDensityOrFontScaleChanged(); + mUserSwitcherController.onDensityOrFontScaleChanged(); + mNotificationIconAreaController.onDensityOrFontScaleChanged(mContext); + mHeadsUpManager.onDensityOrFontScaleChanged(); + } + + @Override + public void onThemeChanged() { + if (mBrightnessMirrorController != null) { + mBrightnessMirrorController.onOverlayChanged(); + } + // We need the new R.id.keyguard_indication_area before recreating + // mKeyguardIndicationController + mNotificationPanelViewController.onThemeChanged(); + + if (mStatusBarKeyguardViewManager != null) { + mStatusBarKeyguardViewManager.onThemeChanged(); + } + if (mAmbientIndicationContainer instanceof AutoReinflateContainer) { + ((AutoReinflateContainer) mAmbientIndicationContainer).inflateLayout(); + } + mNotificationIconAreaController.onThemeChanged(); + } + + @Override + public void onUiModeChanged() { + if (mBrightnessMirrorController != null) { + mBrightnessMirrorController.onUiModeChanged(); + } + } + }; + + private StatusBarStateController.StateListener mStateListener = + new StatusBarStateController.StateListener() { + @Override + public void onStatePreChange(int oldState, int newState) { + // If we're visible and switched to SHADE_LOCKED (the user dragged + // down on the lockscreen), clear notification LED, vibration, + // ringing. + // Other transitions are covered in handleVisibleToUserChanged(). + if (mVisible && (newState == StatusBarState.SHADE_LOCKED + || mStatusBarStateController.goingToFullShade())) { + clearNotificationEffects(); + } + if (newState == StatusBarState.KEYGUARD) { + mRemoteInputManager.onPanelCollapsed(); + maybeEscalateHeadsUp(); + } + } + + @Override + public void onStateChanged(int newState) { + mState = newState; + updateReportRejectedTouchVisibility(); + mDozeServiceHost.updateDozing(); + updateTheme(); + mNavigationBarController.touchAutoDim(mDisplayId); + Trace.beginSection("CentralSurfaces#updateKeyguardState"); + if (mState == StatusBarState.KEYGUARD) { + mNotificationPanelViewController.cancelPendingPanelCollapse(); + } + updateDozingState(); + checkBarModes(); + updateScrimController(); + mPresenter.updateMediaMetaData(false, mState != StatusBarState.KEYGUARD); + Trace.endSection(); + } + + @Override + public void onDozeAmountChanged(float linear, float eased) { + if (mFeatureFlags.isEnabled(Flags.LOCKSCREEN_ANIMATIONS) + && !(mLightRevealScrim.getRevealEffect() instanceof CircleReveal)) { + mLightRevealScrim.setRevealAmount(1f - linear); + } + } + + @Override + public void onDozingChanged(boolean isDozing) { + Trace.beginSection("CentralSurfaces#updateDozing"); + mDozing = isDozing; + + // Collapse the notification panel if open + boolean dozingAnimated = mDozeServiceHost.getDozingRequested() + && mDozeParameters.shouldControlScreenOff(); + mNotificationPanelViewController.resetViews(dozingAnimated); + + updateQsExpansionEnabled(); + mKeyguardViewMediator.setDozing(mDozing); + + mNotificationsController.requestNotificationUpdate("onDozingChanged"); + updateDozingState(); + mDozeServiceHost.updateDozing(); + updateScrimController(); + updateReportRejectedTouchVisibility(); + Trace.endSection(); + } + + @Override + public void onFullscreenStateChanged(boolean isFullscreen) { + mIsFullscreen = isFullscreen; + maybeUpdateBarMode(); + } + }; + + private final BatteryController.BatteryStateChangeCallback mBatteryStateChangeCallback = + new BatteryController.BatteryStateChangeCallback() { + @Override + public void onPowerSaveChanged(boolean isPowerSave) { + mMainExecutor.execute(mCheckBarModes); + if (mDozeServiceHost != null) { + mDozeServiceHost.firePowerSaveChanged(isPowerSave); + } + } + }; + + private final ActivityLaunchAnimator.Callback mActivityLaunchAnimatorCallback = + new ActivityLaunchAnimator.Callback() { + @Override + public boolean isOnKeyguard() { + return mKeyguardStateController.isShowing(); + } + + @Override + public void hideKeyguardWithAnimation(IRemoteAnimationRunner runner) { + // We post to the main thread for 2 reasons: + // 1. KeyguardViewMediator is not thread-safe. + // 2. To ensure that ViewMediatorCallback#keyguardDonePending is called before + // ViewMediatorCallback#readyForKeyguardDone. The wrong order could occur + // when doing + // dismissKeyguardThenExecute { hideKeyguardWithAnimation(runner) }. + mMainExecutor.execute(() -> mKeyguardViewMediator.hideWithAnimation(runner)); + } + + @Override + public int getBackgroundColor(TaskInfo task) { + if (!mStartingSurfaceOptional.isPresent()) { + Log.w(TAG, "No starting surface, defaulting to SystemBGColor"); + return SplashscreenContentDrawer.getSystemBGColor(); + } + + return mStartingSurfaceOptional.get().getBackgroundColor(task); + } + }; + + private final ActivityLaunchAnimator.Listener mActivityLaunchAnimatorListener = + new ActivityLaunchAnimator.Listener() { + @Override + public void onLaunchAnimationStart() { + mKeyguardViewMediator.setBlursDisabledForAppLaunch(true); + } + + @Override + public void onLaunchAnimationEnd() { + mKeyguardViewMediator.setBlursDisabledForAppLaunch(false); + } + }; + + private final DemoMode mDemoModeCallback = new DemoMode() { + @Override + public void onDemoModeFinished() { + checkBarModes(); + } + + @Override + public void dispatchDemoCommand(String command, Bundle args) { } + }; + + /** + * Determines what UserHandle to use when launching an activity. + * + * We want to ensure that activities that are launched within the systemui process should be + * launched as user of the current process. + * @param intent + * @return UserHandle + */ + private UserHandle getActivityUserHandle(Intent intent) { + String[] packages = mContext.getResources().getStringArray(R.array.system_ui_packages); + for (String pkg : packages) { + if (intent.getComponent() == null) break; + if (pkg.equals(intent.getComponent().getPackageName())) { + return new UserHandle(UserHandle.myUserId()); + } + } + return UserHandle.CURRENT; + } +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowViewController.java index 2f11b16f93832..be5b33eb0da0c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowViewController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowViewController.java @@ -252,7 +252,7 @@ public class NotificationShadeWindowViewController { } if (mStatusBarStateController.isDozing()) { - mService.mDozeScrimController.extendPulse(); + mService.extendDozePulse(); } mLockIconViewController.onTouchEvent( ev, diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/CentralSurfacesComponent.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/CentralSurfacesComponent.java index 5d38eea157230..c5e5297ae6ba5 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/CentralSurfacesComponent.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/CentralSurfacesComponent.java @@ -31,6 +31,7 @@ import com.android.systemui.statusbar.notification.stack.NotificationListContain import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController; import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutListContainerModule; import com.android.systemui.statusbar.phone.CentralSurfacesCommandQueueCallbacks; +import com.android.systemui.statusbar.phone.CentralSurfacesImpl; import com.android.systemui.statusbar.phone.LargeScreenShadeHeaderController; import com.android.systemui.statusbar.phone.NotificationPanelViewController; import com.android.systemui.statusbar.phone.NotificationShadeWindowView; @@ -51,7 +52,7 @@ import dagger.Subcomponent; /** * Dagger subcomponent for classes (semi-)related to the status bar. The component is created once - * inside {@link com.android.systemui.statusbar.phone.CentralSurfaces} and never re-created. + * inside {@link CentralSurfacesImpl} and never re-created. * * TODO(b/197137564): This should likely be re-factored a bit. It includes classes that aren't * directly related to status bar functionality, like multiple notification classes. And, the fact diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java index c024c7245c450..942d186e7005d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java @@ -16,317 +16,22 @@ package com.android.systemui.statusbar.phone.dagger; -import static com.android.systemui.Dependency.TIME_TICK_HANDLER_NAME; - -import android.app.WallpaperManager; -import android.content.Context; -import android.hardware.devicestate.DeviceStateManager; -import android.os.Handler; -import android.os.PowerManager; -import android.util.DisplayMetrics; - -import com.android.internal.jank.InteractionJankMonitor; -import com.android.internal.logging.MetricsLogger; -import com.android.keyguard.KeyguardUpdateMonitor; -import com.android.keyguard.ViewMediatorCallback; -import com.android.systemui.InitController; -import com.android.systemui.accessibility.floatingmenu.AccessibilityFloatingMenuController; -import com.android.systemui.animation.ActivityLaunchAnimator; -import com.android.systemui.assist.AssistManager; -import com.android.systemui.broadcast.BroadcastDispatcher; -import com.android.systemui.classifier.FalsingCollector; -import com.android.systemui.colorextraction.SysuiColorExtractor; import com.android.systemui.dagger.SysUISingleton; -import com.android.systemui.dagger.qualifiers.Main; -import com.android.systemui.dagger.qualifiers.UiBackground; -import com.android.systemui.demomode.DemoModeController; -import com.android.systemui.dreams.DreamOverlayStateController; -import com.android.systemui.flags.FeatureFlags; -import com.android.systemui.fragments.FragmentService; -import com.android.systemui.keyguard.KeyguardUnlockAnimationController; -import com.android.systemui.keyguard.KeyguardViewMediator; -import com.android.systemui.keyguard.ScreenLifecycle; -import com.android.systemui.keyguard.WakefulnessLifecycle; -import com.android.systemui.navigationbar.NavigationBarController; -import com.android.systemui.plugins.FalsingManager; -import com.android.systemui.plugins.PluginDependencyProvider; -import com.android.systemui.recents.ScreenPinningRequest; -import com.android.systemui.settings.brightness.BrightnessSliderController; -import com.android.systemui.shared.plugins.PluginManager; -import com.android.systemui.statusbar.CommandQueue; -import com.android.systemui.statusbar.KeyguardIndicationController; -import com.android.systemui.statusbar.LockscreenShadeTransitionController; -import com.android.systemui.statusbar.NotificationLockscreenUserManager; -import com.android.systemui.statusbar.NotificationMediaManager; -import com.android.systemui.statusbar.NotificationRemoteInputManager; -import com.android.systemui.statusbar.NotificationShadeDepthController; -import com.android.systemui.statusbar.NotificationShadeWindowController; -import com.android.systemui.statusbar.NotificationViewHierarchyManager; -import com.android.systemui.statusbar.PulseExpansionHandler; -import com.android.systemui.statusbar.SysuiStatusBarStateController; -import com.android.systemui.statusbar.charging.WiredChargingRippleController; -import com.android.systemui.statusbar.connectivity.NetworkController; -import com.android.systemui.statusbar.notification.DynamicPrivacyController; -import com.android.systemui.statusbar.notification.NotifPipelineFlags; -import com.android.systemui.statusbar.notification.NotificationEntryManager; -import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator; -import com.android.systemui.statusbar.notification.collection.legacy.VisualStabilityManager; -import com.android.systemui.statusbar.notification.collection.render.NotifShadeEventSource; -import com.android.systemui.statusbar.notification.init.NotificationsController; -import com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProvider; -import com.android.systemui.statusbar.notification.logging.NotificationLogger; -import com.android.systemui.statusbar.notification.row.NotificationGutsManager; -import com.android.systemui.statusbar.phone.AutoHideController; -import com.android.systemui.statusbar.phone.BiometricUnlockController; -import com.android.systemui.statusbar.phone.DozeParameters; -import com.android.systemui.statusbar.phone.DozeScrimController; -import com.android.systemui.statusbar.phone.DozeServiceHost; -import com.android.systemui.statusbar.phone.HeadsUpManagerPhone; -import com.android.systemui.statusbar.phone.KeyguardBypassController; -import com.android.systemui.statusbar.phone.KeyguardDismissUtil; -import com.android.systemui.statusbar.phone.LightBarController; -import com.android.systemui.statusbar.phone.LockscreenGestureLogger; -import com.android.systemui.statusbar.phone.LockscreenWallpaper; -import com.android.systemui.statusbar.phone.NotificationIconAreaController; -import com.android.systemui.statusbar.phone.PhoneStatusBarPolicy; -import com.android.systemui.statusbar.phone.ScreenOffAnimationController; -import com.android.systemui.statusbar.phone.ScrimController; -import com.android.systemui.statusbar.phone.ShadeController; import com.android.systemui.statusbar.phone.CentralSurfaces; -import com.android.systemui.statusbar.phone.StatusBarHideIconsForBouncerManager; -import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager; -import com.android.systemui.statusbar.phone.StatusBarSignalPolicy; -import com.android.systemui.statusbar.phone.StatusBarTouchableRegionManager; -import com.android.systemui.statusbar.phone.ongoingcall.OngoingCallController; -import com.android.systemui.statusbar.phone.panelstate.PanelExpansionStateManager; -import com.android.systemui.statusbar.policy.BatteryController; -import com.android.systemui.statusbar.policy.ConfigurationController; -import com.android.systemui.statusbar.policy.DeviceProvisionedController; -import com.android.systemui.statusbar.policy.ExtensionController; -import com.android.systemui.statusbar.policy.KeyguardStateController; -import com.android.systemui.statusbar.policy.UserInfoControllerImpl; -import com.android.systemui.statusbar.policy.UserSwitcherController; -import com.android.systemui.statusbar.window.StatusBarWindowController; -import com.android.systemui.statusbar.window.StatusBarWindowStateController; -import com.android.systemui.util.WallpaperController; -import com.android.systemui.util.concurrency.DelayableExecutor; -import com.android.systemui.util.concurrency.MessageRouter; -import com.android.systemui.volume.VolumeComponent; -import com.android.systemui.wmshell.BubblesManager; -import com.android.wm.shell.bubbles.Bubbles; -import com.android.wm.shell.startingsurface.StartingSurface; +import com.android.systemui.statusbar.phone.CentralSurfacesImpl; -import java.util.Optional; -import java.util.concurrent.Executor; - -import javax.inject.Named; - -import dagger.Lazy; +import dagger.Binds; import dagger.Module; -import dagger.Provides; /** - * Dagger Module providing {@link CentralSurfaces}. + * Dagger Module providing {@link CentralSurfacesImpl}. */ @Module public interface StatusBarPhoneModule { /** * Provides our instance of CentralSurfaces which is considered optional. */ - @Provides + @Binds @SysUISingleton - static CentralSurfaces provideCentralSurfaces( - Context context, - NotificationsController notificationsController, - FragmentService fragmentService, - LightBarController lightBarController, - AutoHideController autoHideController, - StatusBarWindowController statusBarWindowController, - StatusBarWindowStateController statusBarWindowStateController, - KeyguardUpdateMonitor keyguardUpdateMonitor, - StatusBarSignalPolicy statusBarSignalPolicy, - PulseExpansionHandler pulseExpansionHandler, - NotificationWakeUpCoordinator notificationWakeUpCoordinator, - KeyguardBypassController keyguardBypassController, - KeyguardStateController keyguardStateController, - HeadsUpManagerPhone headsUpManagerPhone, - DynamicPrivacyController dynamicPrivacyController, - FalsingManager falsingManager, - FalsingCollector falsingCollector, - BroadcastDispatcher broadcastDispatcher, - NotifShadeEventSource notifShadeEventSource, - NotificationEntryManager notificationEntryManager, - NotificationGutsManager notificationGutsManager, - NotificationLogger notificationLogger, - NotificationInterruptStateProvider notificationInterruptStateProvider, - NotificationViewHierarchyManager notificationViewHierarchyManager, - PanelExpansionStateManager panelExpansionStateManager, - KeyguardViewMediator keyguardViewMediator, - DisplayMetrics displayMetrics, - MetricsLogger metricsLogger, - @UiBackground Executor uiBgExecutor, - NotificationMediaManager notificationMediaManager, - NotificationLockscreenUserManager lockScreenUserManager, - NotificationRemoteInputManager remoteInputManager, - UserSwitcherController userSwitcherController, - NetworkController networkController, - BatteryController batteryController, - SysuiColorExtractor colorExtractor, - ScreenLifecycle screenLifecycle, - WakefulnessLifecycle wakefulnessLifecycle, - SysuiStatusBarStateController statusBarStateController, - Optional bubblesManagerOptional, - Optional bubblesOptional, - VisualStabilityManager visualStabilityManager, - DeviceProvisionedController deviceProvisionedController, - NavigationBarController navigationBarController, - AccessibilityFloatingMenuController accessibilityFloatingMenuController, - Lazy assistManagerLazy, - ConfigurationController configurationController, - NotificationShadeWindowController notificationShadeWindowController, - DozeParameters dozeParameters, - ScrimController scrimController, - Lazy lockscreenWallpaperLazy, - LockscreenGestureLogger lockscreenGestureLogger, - Lazy biometricUnlockControllerLazy, - DozeServiceHost dozeServiceHost, - PowerManager powerManager, - ScreenPinningRequest screenPinningRequest, - DozeScrimController dozeScrimController, - VolumeComponent volumeComponent, - CommandQueue commandQueue, - CentralSurfacesComponent.Factory statusBarComponentFactory, - PluginManager pluginManager, - ShadeController shadeController, - StatusBarKeyguardViewManager statusBarKeyguardViewManager, - ViewMediatorCallback viewMediatorCallback, - InitController initController, - @Named(TIME_TICK_HANDLER_NAME) Handler timeTickHandler, - PluginDependencyProvider pluginDependencyProvider, - KeyguardDismissUtil keyguardDismissUtil, - ExtensionController extensionController, - UserInfoControllerImpl userInfoControllerImpl, - PhoneStatusBarPolicy phoneStatusBarPolicy, - KeyguardIndicationController keyguardIndicationController, - DemoModeController demoModeController, - Lazy notificationShadeDepthController, - StatusBarTouchableRegionManager statusBarTouchableRegionManager, - NotificationIconAreaController notificationIconAreaController, - BrightnessSliderController.Factory brightnessSliderFactory, - ScreenOffAnimationController screenOffAnimationController, - WallpaperController wallpaperController, - OngoingCallController ongoingCallController, - StatusBarHideIconsForBouncerManager statusBarHideIconsForBouncerManager, - LockscreenShadeTransitionController transitionController, - FeatureFlags featureFlags, - KeyguardUnlockAnimationController keyguardUnlockAnimationController, - @Main Handler mainHandler, - @Main DelayableExecutor delayableExecutor, - @Main MessageRouter messageRouter, - WallpaperManager wallpaperManager, - Optional startingSurfaceOptional, - ActivityLaunchAnimator activityLaunchAnimator, - NotifPipelineFlags notifPipelineFlags, - InteractionJankMonitor jankMonitor, - DeviceStateManager deviceStateManager, - DreamOverlayStateController dreamOverlayStateController, - WiredChargingRippleController wiredChargingRippleController) { - return new CentralSurfaces( - context, - notificationsController, - fragmentService, - lightBarController, - autoHideController, - statusBarWindowController, - statusBarWindowStateController, - keyguardUpdateMonitor, - statusBarSignalPolicy, - pulseExpansionHandler, - notificationWakeUpCoordinator, - keyguardBypassController, - keyguardStateController, - headsUpManagerPhone, - dynamicPrivacyController, - falsingManager, - falsingCollector, - broadcastDispatcher, - notifShadeEventSource, - notificationEntryManager, - notificationGutsManager, - notificationLogger, - notificationInterruptStateProvider, - notificationViewHierarchyManager, - panelExpansionStateManager, - keyguardViewMediator, - displayMetrics, - metricsLogger, - uiBgExecutor, - notificationMediaManager, - lockScreenUserManager, - remoteInputManager, - userSwitcherController, - networkController, - batteryController, - colorExtractor, - screenLifecycle, - wakefulnessLifecycle, - statusBarStateController, - bubblesManagerOptional, - bubblesOptional, - visualStabilityManager, - deviceProvisionedController, - navigationBarController, - accessibilityFloatingMenuController, - assistManagerLazy, - configurationController, - notificationShadeWindowController, - dozeParameters, - scrimController, - lockscreenWallpaperLazy, - lockscreenGestureLogger, - biometricUnlockControllerLazy, - dozeServiceHost, - powerManager, - screenPinningRequest, - dozeScrimController, - volumeComponent, - commandQueue, - statusBarComponentFactory, - pluginManager, - shadeController, - statusBarKeyguardViewManager, - viewMediatorCallback, - initController, - timeTickHandler, - pluginDependencyProvider, - keyguardDismissUtil, - extensionController, - userInfoControllerImpl, - phoneStatusBarPolicy, - keyguardIndicationController, - demoModeController, - notificationShadeDepthController, - statusBarTouchableRegionManager, - notificationIconAreaController, - brightnessSliderFactory, - screenOffAnimationController, - wallpaperController, - ongoingCallController, - statusBarHideIconsForBouncerManager, - transitionController, - featureFlags, - keyguardUnlockAnimationController, - mainHandler, - delayableExecutor, - messageRouter, - wallpaperManager, - startingSurfaceOptional, - activityLaunchAnimator, - notifPipelineFlags, - jankMonitor, - deviceStateManager, - dreamOverlayStateController, - wiredChargingRippleController - ); - } + CentralSurfaces bindsCentralSurfaces(CentralSurfacesImpl impl); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/dagger/StatusBarFragmentComponent.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/dagger/StatusBarFragmentComponent.java index 2eba325ff63d8..6717bc768fbba 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/dagger/StatusBarFragmentComponent.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/dagger/StatusBarFragmentComponent.java @@ -18,14 +18,12 @@ package com.android.systemui.statusbar.phone.fragment.dagger; import com.android.systemui.battery.BatteryMeterViewController; import com.android.systemui.dagger.qualifiers.RootView; -import com.android.systemui.statusbar.phone.CentralSurfaces; import com.android.systemui.statusbar.phone.HeadsUpAppearanceController; import com.android.systemui.statusbar.phone.LightsOutNotifController; import com.android.systemui.statusbar.phone.PhoneStatusBarTransitions; import com.android.systemui.statusbar.phone.PhoneStatusBarView; import com.android.systemui.statusbar.phone.PhoneStatusBarViewController; import com.android.systemui.statusbar.phone.StatusBarDemoMode; -import com.android.systemui.statusbar.phone.dagger.CentralSurfacesComponent; import com.android.systemui.statusbar.phone.fragment.CollapsedStatusBarFragment; import dagger.BindsInstance; diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java similarity index 99% rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesTest.java rename to packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java index 84edabdaa3027..d364505445f07 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java @@ -178,12 +178,12 @@ import dagger.Lazy; @SmallTest @RunWith(AndroidTestingRunner.class) @RunWithLooper(setAsMainLooper = true) -public class CentralSurfacesTest extends SysuiTestCase { +public class CentralSurfacesImplTest extends SysuiTestCase { private static final int FOLD_STATE_FOLDED = 0; private static final int FOLD_STATE_UNFOLDED = 1; - private CentralSurfaces mCentralSurfaces; + private CentralSurfacesImpl mCentralSurfaces; private FakeMetricsLogger mMetricsLogger; private PowerManager mPowerManager; private TestableNotificationInterruptStateProviderImpl mNotificationInterruptStateProvider; @@ -383,7 +383,7 @@ public class CentralSurfacesTest extends SysuiTestCase { when(mOperatorNameViewControllerFactory.create(any())) .thenReturn(mOperatorNameViewController); - mCentralSurfaces = new CentralSurfaces( + mCentralSurfaces = new CentralSurfacesImpl( mContext, mNotificationsController, mock(FragmentService.class), @@ -479,7 +479,7 @@ public class CentralSurfacesTest extends SysuiTestCase { mDreamOverlayStateController, mWiredChargingRippleController); when(mKeyguardViewMediator.registerCentralSurfaces( - any(CentralSurfaces.class), + any(CentralSurfacesImpl.class), any(NotificationPanelViewController.class), any(PanelExpansionStateManager.class), any(BiometricUnlockController.class),