• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2010 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.systemui.statusbar.phone;
18 
19 import static android.app.StatusBarManager.DISABLE_HOME;
20 import static android.app.StatusBarManager.WINDOW_STATE_HIDDEN;
21 import static android.app.StatusBarManager.WINDOW_STATE_SHOWING;
22 import static android.app.StatusBarManager.WindowVisibleState;
23 import static android.app.StatusBarManager.windowStateToString;
24 import static android.view.InsetsState.ITYPE_STATUS_BAR;
25 import static android.view.InsetsState.containsType;
26 import static android.view.WindowInsetsController.APPEARANCE_LOW_PROFILE_BARS;
27 import static android.view.WindowInsetsController.APPEARANCE_OPAQUE_STATUS_BARS;
28 import static android.view.WindowInsetsController.APPEARANCE_SEMI_TRANSPARENT_STATUS_BARS;
29 
30 import static androidx.core.view.ViewCompat.IMPORTANT_FOR_ACCESSIBILITY_AUTO;
31 import static androidx.core.view.ViewCompat.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS;
32 import static androidx.lifecycle.Lifecycle.State.RESUMED;
33 
34 import static com.android.systemui.Dependency.TIME_TICK_HANDLER_NAME;
35 import static com.android.systemui.charging.WirelessChargingAnimation.UNKNOWN_BATTERY_LEVEL;
36 import static com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_ASLEEP;
37 import static com.android.systemui.statusbar.NotificationLockscreenUserManager.PERMISSION_SELF;
38 import static com.android.systemui.statusbar.StatusBarState.SHADE;
39 import static com.android.systemui.statusbar.phone.BarTransitions.MODE_LIGHTS_OUT;
40 import static com.android.systemui.statusbar.phone.BarTransitions.MODE_LIGHTS_OUT_TRANSPARENT;
41 import static com.android.systemui.statusbar.phone.BarTransitions.MODE_OPAQUE;
42 import static com.android.systemui.statusbar.phone.BarTransitions.MODE_SEMI_TRANSPARENT;
43 import static com.android.systemui.statusbar.phone.BarTransitions.MODE_TRANSPARENT;
44 import static com.android.systemui.statusbar.phone.BarTransitions.TransitionMode;
45 
46 import android.annotation.Nullable;
47 import android.app.ActivityManager;
48 import android.app.ActivityOptions;
49 import android.app.ActivityTaskManager;
50 import android.app.IWallpaperManager;
51 import android.app.KeyguardManager;
52 import android.app.Notification;
53 import android.app.NotificationManager;
54 import android.app.PendingIntent;
55 import android.app.StatusBarManager;
56 import android.app.TaskInfo;
57 import android.app.TaskStackBuilder;
58 import android.app.UiModeManager;
59 import android.app.WallpaperInfo;
60 import android.app.WallpaperManager;
61 import android.app.admin.DevicePolicyManager;
62 import android.content.BroadcastReceiver;
63 import android.content.ComponentName;
64 import android.content.Context;
65 import android.content.Intent;
66 import android.content.IntentFilter;
67 import android.content.pm.PackageManager;
68 import android.content.pm.ResolveInfo;
69 import android.content.res.Configuration;
70 import android.graphics.Point;
71 import android.hardware.devicestate.DeviceStateManager;
72 import android.hardware.fingerprint.FingerprintManager;
73 import android.metrics.LogMaker;
74 import android.net.Uri;
75 import android.os.Binder;
76 import android.os.Bundle;
77 import android.os.Handler;
78 import android.os.Looper;
79 import android.os.PowerManager;
80 import android.os.RemoteException;
81 import android.os.ServiceManager;
82 import android.os.SystemClock;
83 import android.os.SystemProperties;
84 import android.os.Trace;
85 import android.os.UserHandle;
86 import android.provider.Settings;
87 import android.service.dreams.IDreamManager;
88 import android.service.notification.StatusBarNotification;
89 import android.text.TextUtils;
90 import android.util.ArraySet;
91 import android.util.DisplayMetrics;
92 import android.util.EventLog;
93 import android.util.IndentingPrintWriter;
94 import android.util.Log;
95 import android.util.MathUtils;
96 import android.view.Display;
97 import android.view.IRemoteAnimationRunner;
98 import android.view.IWindowManager;
99 import android.view.KeyEvent;
100 import android.view.ThreadedRenderer;
101 import android.view.View;
102 import android.view.ViewGroup;
103 import android.view.ViewRootImpl;
104 import android.view.WindowInsetsController.Appearance;
105 import android.view.WindowManager;
106 import android.view.WindowManagerGlobal;
107 import android.view.accessibility.AccessibilityManager;
108 import android.widget.DateTimeView;
109 import android.window.OnBackInvokedCallback;
110 import android.window.OnBackInvokedDispatcher;
111 
112 import androidx.annotation.NonNull;
113 import androidx.lifecycle.Lifecycle;
114 import androidx.lifecycle.LifecycleRegistry;
115 
116 import com.android.internal.annotations.VisibleForTesting;
117 import com.android.internal.colorextraction.ColorExtractor;
118 import com.android.internal.jank.InteractionJankMonitor;
119 import com.android.internal.logging.MetricsLogger;
120 import com.android.internal.logging.UiEvent;
121 import com.android.internal.logging.UiEventLogger;
122 import com.android.internal.logging.UiEventLoggerImpl;
123 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
124 import com.android.internal.statusbar.IStatusBarService;
125 import com.android.internal.statusbar.RegisterStatusBarResult;
126 import com.android.keyguard.AuthKeyguardMessageArea;
127 import com.android.keyguard.KeyguardUpdateMonitor;
128 import com.android.keyguard.KeyguardUpdateMonitorCallback;
129 import com.android.keyguard.ViewMediatorCallback;
130 import com.android.systemui.ActivityIntentHelper;
131 import com.android.systemui.AutoReinflateContainer;
132 import com.android.systemui.CoreStartable;
133 import com.android.systemui.DejankUtils;
134 import com.android.systemui.EventLogTags;
135 import com.android.systemui.InitController;
136 import com.android.systemui.Prefs;
137 import com.android.systemui.R;
138 import com.android.systemui.accessibility.floatingmenu.AccessibilityFloatingMenuController;
139 import com.android.systemui.animation.ActivityLaunchAnimator;
140 import com.android.systemui.animation.DelegateLaunchAnimatorController;
141 import com.android.systemui.assist.AssistManager;
142 import com.android.systemui.biometrics.AuthRippleController;
143 import com.android.systemui.broadcast.BroadcastDispatcher;
144 import com.android.systemui.camera.CameraIntents;
145 import com.android.systemui.charging.WiredChargingRippleController;
146 import com.android.systemui.charging.WirelessChargingAnimation;
147 import com.android.systemui.classifier.FalsingCollector;
148 import com.android.systemui.colorextraction.SysuiColorExtractor;
149 import com.android.systemui.dagger.SysUISingleton;
150 import com.android.systemui.dagger.qualifiers.Main;
151 import com.android.systemui.dagger.qualifiers.UiBackground;
152 import com.android.systemui.demomode.DemoMode;
153 import com.android.systemui.demomode.DemoModeController;
154 import com.android.systemui.emergency.EmergencyGesture;
155 import com.android.systemui.flags.FeatureFlags;
156 import com.android.systemui.flags.Flags;
157 import com.android.systemui.fragments.ExtensionFragmentListener;
158 import com.android.systemui.fragments.FragmentHostManager;
159 import com.android.systemui.fragments.FragmentService;
160 import com.android.systemui.keyguard.KeyguardService;
161 import com.android.systemui.keyguard.KeyguardUnlockAnimationController;
162 import com.android.systemui.keyguard.KeyguardViewMediator;
163 import com.android.systemui.keyguard.ScreenLifecycle;
164 import com.android.systemui.keyguard.WakefulnessLifecycle;
165 import com.android.systemui.keyguard.domain.interactor.AlternateBouncerInteractor;
166 import com.android.systemui.keyguard.ui.binder.LightRevealScrimViewBinder;
167 import com.android.systemui.keyguard.ui.viewmodel.LightRevealScrimViewModel;
168 import com.android.systemui.navigationbar.NavigationBarController;
169 import com.android.systemui.navigationbar.NavigationBarView;
170 import com.android.systemui.plugins.DarkIconDispatcher;
171 import com.android.systemui.plugins.FalsingManager;
172 import com.android.systemui.plugins.OverlayPlugin;
173 import com.android.systemui.plugins.PluginDependencyProvider;
174 import com.android.systemui.plugins.PluginListener;
175 import com.android.systemui.plugins.PluginManager;
176 import com.android.systemui.plugins.qs.QS;
177 import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper.SnoozeOption;
178 import com.android.systemui.plugins.statusbar.StatusBarStateController;
179 import com.android.systemui.qs.QSFragment;
180 import com.android.systemui.qs.QSPanelController;
181 import com.android.systemui.recents.ScreenPinningRequest;
182 import com.android.systemui.scrim.ScrimView;
183 import com.android.systemui.settings.UserTracker;
184 import com.android.systemui.settings.brightness.BrightnessSliderController;
185 import com.android.systemui.shade.CameraLauncher;
186 import com.android.systemui.shade.NotificationPanelViewController;
187 import com.android.systemui.shade.NotificationShadeWindowView;
188 import com.android.systemui.shade.NotificationShadeWindowViewController;
189 import com.android.systemui.shade.QuickSettingsController;
190 import com.android.systemui.shade.ShadeController;
191 import com.android.systemui.shade.ShadeExpansionChangeEvent;
192 import com.android.systemui.shade.ShadeExpansionStateManager;
193 import com.android.systemui.statusbar.AutoHideUiElement;
194 import com.android.systemui.statusbar.BackDropView;
195 import com.android.systemui.statusbar.CircleReveal;
196 import com.android.systemui.statusbar.CommandQueue;
197 import com.android.systemui.statusbar.GestureRecorder;
198 import com.android.systemui.statusbar.KeyboardShortcuts;
199 import com.android.systemui.statusbar.KeyguardIndicationController;
200 import com.android.systemui.statusbar.LiftReveal;
201 import com.android.systemui.statusbar.LightRevealScrim;
202 import com.android.systemui.statusbar.LockscreenShadeTransitionController;
203 import com.android.systemui.statusbar.NotificationLockscreenUserManager;
204 import com.android.systemui.statusbar.NotificationMediaManager;
205 import com.android.systemui.statusbar.NotificationPresenter;
206 import com.android.systemui.statusbar.NotificationRemoteInputManager;
207 import com.android.systemui.statusbar.NotificationShadeDepthController;
208 import com.android.systemui.statusbar.NotificationShadeWindowController;
209 import com.android.systemui.statusbar.NotificationShelfController;
210 import com.android.systemui.statusbar.PowerButtonReveal;
211 import com.android.systemui.statusbar.PulseExpansionHandler;
212 import com.android.systemui.statusbar.StatusBarState;
213 import com.android.systemui.statusbar.SysuiStatusBarStateController;
214 import com.android.systemui.statusbar.core.StatusBarInitializer;
215 import com.android.systemui.statusbar.notification.DynamicPrivacyController;
216 import com.android.systemui.statusbar.notification.NotificationActivityStarter;
217 import com.android.systemui.statusbar.notification.NotificationLaunchAnimatorControllerProvider;
218 import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator;
219 import com.android.systemui.statusbar.notification.init.NotificationsController;
220 import com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProvider;
221 import com.android.systemui.statusbar.notification.logging.NotificationLogger;
222 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
223 import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
224 import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
225 import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
226 import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController;
227 import com.android.systemui.statusbar.phone.dagger.CentralSurfacesComponent;
228 import com.android.systemui.statusbar.phone.dagger.StatusBarPhoneModule;
229 import com.android.systemui.statusbar.phone.ongoingcall.OngoingCallController;
230 import com.android.systemui.statusbar.policy.BatteryController;
231 import com.android.systemui.statusbar.policy.BrightnessMirrorController;
232 import com.android.systemui.statusbar.policy.ConfigurationController;
233 import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener;
234 import com.android.systemui.statusbar.policy.DeviceProvisionedController;
235 import com.android.systemui.statusbar.policy.DeviceProvisionedController.DeviceProvisionedListener;
236 import com.android.systemui.statusbar.policy.ExtensionController;
237 import com.android.systemui.statusbar.policy.KeyguardStateController;
238 import com.android.systemui.statusbar.policy.UserInfoControllerImpl;
239 import com.android.systemui.statusbar.policy.UserSwitcherController;
240 import com.android.systemui.statusbar.window.StatusBarWindowController;
241 import com.android.systemui.statusbar.window.StatusBarWindowStateController;
242 import com.android.systemui.surfaceeffects.ripple.RippleShader.RippleShape;
243 import com.android.systemui.util.DumpUtilsKt;
244 import com.android.systemui.util.WallpaperController;
245 import com.android.systemui.util.concurrency.DelayableExecutor;
246 import com.android.systemui.util.concurrency.MessageRouter;
247 import com.android.systemui.volume.VolumeComponent;
248 import com.android.wm.shell.bubbles.Bubbles;
249 import com.android.wm.shell.startingsurface.SplashscreenContentDrawer;
250 import com.android.wm.shell.startingsurface.StartingSurface;
251 
252 import java.io.PrintWriter;
253 import java.io.StringWriter;
254 import java.util.List;
255 import java.util.Map;
256 import java.util.Optional;
257 import java.util.concurrent.Executor;
258 
259 import javax.inject.Inject;
260 import javax.inject.Named;
261 import javax.inject.Provider;
262 
263 import dagger.Lazy;
264 
265 /**
266  * A class handling initialization and coordination between some of the key central surfaces in
267  * System UI: The notification shade, the keyguard (lockscreen), and the status bar.
268  *
269  * This class is not our ideal architecture because it doesn't enforce much isolation between these
270  * three mostly disparate surfaces. In an ideal world, this class would not exist. Instead, we would
271  * break it up into three modules -- one for each of those three surfaces -- and we would define any
272  * APIs that are needed for these surfaces to communicate with each other when necessary.
273  *
274  * <b>If at all possible, please avoid adding additional code to this monstrous class! Our goal is
275  * to break up this class into many small classes, and any code added here will slow down that goal.
276  * </b>
277  */
278 @SysUISingleton
279 public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces {
280 
281     private static final String BANNER_ACTION_CANCEL =
282             "com.android.systemui.statusbar.banner_action_cancel";
283     private static final String BANNER_ACTION_SETUP =
284             "com.android.systemui.statusbar.banner_action_setup";
285 
286     private static final int MSG_OPEN_SETTINGS_PANEL = 1002;
287     private static final int MSG_LAUNCH_TRANSITION_TIMEOUT = 1003;
288     // 1020-1040 reserved for BaseStatusBar
289 
290     /**
291      * TODO(b/249277686) delete this
292      * The delay to reset the hint text when the hint animation is finished running.
293      */
294     private static final int HINT_RESET_DELAY_MS = 1200;
295 
296     private static final UiEventLogger sUiEventLogger = new UiEventLoggerImpl();
297 
298     private final Context mContext;
299     private final LockscreenShadeTransitionController mLockscreenShadeTransitionController;
300     private final DeviceStateManager mDeviceStateManager;
301     private CentralSurfacesCommandQueueCallbacks mCommandQueueCallbacks;
302     private float mTransitionToFullShadeProgress = 0f;
303     private NotificationListContainer mNotifListContainer;
304 
305     private final KeyguardStateController.Callback mKeyguardStateControllerCallback =
306             new KeyguardStateController.Callback() {
307                 @Override
308                 public void onKeyguardShowingChanged() {
309                     boolean occluded = mKeyguardStateController.isOccluded();
310                     mStatusBarHideIconsForBouncerManager.setIsOccludedAndTriggerUpdate(occluded);
311                     mScrimController.setKeyguardOccluded(occluded);
312                 }
313             };
314 
onStatusBarWindowStateChanged(@indowVisibleState int state)315     void onStatusBarWindowStateChanged(@WindowVisibleState int state) {
316         updateBubblesVisibility();
317         mStatusBarWindowState = state;
318     }
319 
320     @Override
acquireGestureWakeLock(long time)321     public void acquireGestureWakeLock(long time) {
322         mGestureWakeLock.acquire(time);
323     }
324 
325     @Override
setAppearance(int appearance)326     public boolean setAppearance(int appearance) {
327         if (mAppearance != appearance) {
328             mAppearance = appearance;
329             return updateBarMode(barMode(isTransientShown(), appearance));
330         }
331 
332         return false;
333     }
334 
335     @Override
getBarMode()336     public int getBarMode() {
337         return mStatusBarMode;
338     }
339 
340     @Override
resendMessage(int msg)341     public void resendMessage(int msg) {
342         mMessageRouter.cancelMessages(msg);
343         mMessageRouter.sendMessage(msg);
344     }
345 
346     @Override
resendMessage(Object msg)347     public void resendMessage(Object msg) {
348         mMessageRouter.cancelMessages(msg.getClass());
349         mMessageRouter.sendMessage(msg);
350     }
351 
352     @Override
getDisabled1()353     public int getDisabled1() {
354         return mDisabled1;
355     }
356 
357     @Override
setDisabled1(int disabled)358     public void setDisabled1(int disabled) {
359         mDisabled1 = disabled;
360     }
361 
362     @Override
getDisabled2()363     public int getDisabled2() {
364         return mDisabled2;
365     }
366 
367     @Override
setDisabled2(int disabled)368     public void setDisabled2(int disabled) {
369         mDisabled2 = disabled;
370     }
371 
372     @Override
setLastCameraLaunchSource(int source)373     public void setLastCameraLaunchSource(int source) {
374         mLastCameraLaunchSource = source;
375     }
376 
377     @Override
setLaunchCameraOnFinishedGoingToSleep(boolean launch)378     public void setLaunchCameraOnFinishedGoingToSleep(boolean launch) {
379         mLaunchCameraOnFinishedGoingToSleep = launch;
380     }
381 
382     @Override
setLaunchCameraOnFinishedWaking(boolean launch)383     public void setLaunchCameraOnFinishedWaking(boolean launch) {
384         mLaunchCameraWhenFinishedWaking = launch;
385     }
386 
387     @Override
setLaunchEmergencyActionOnFinishedGoingToSleep(boolean launch)388     public void setLaunchEmergencyActionOnFinishedGoingToSleep(boolean launch) {
389         mLaunchEmergencyActionOnFinishedGoingToSleep = launch;
390     }
391 
392     @Override
setLaunchEmergencyActionOnFinishedWaking(boolean launch)393     public void setLaunchEmergencyActionOnFinishedWaking(boolean launch) {
394         mLaunchEmergencyActionWhenFinishedWaking = launch;
395     }
396 
397     @Override
getQSPanelController()398     public QSPanelController getQSPanelController() {
399         return mQSPanelController;
400     }
401 
402     /** */
403     @Override
animateExpandNotificationsPanel()404     public void animateExpandNotificationsPanel() {
405         mCommandQueueCallbacks.animateExpandNotificationsPanel();
406     }
407 
408     /** */
409     @Override
animateExpandSettingsPanel(@ullable String subpanel)410     public void animateExpandSettingsPanel(@Nullable String subpanel) {
411         mCommandQueueCallbacks.animateExpandSettingsPanel(subpanel);
412     }
413 
414     /** */
415     @Override
togglePanel()416     public void togglePanel() {
417         mCommandQueueCallbacks.togglePanel();
418     }
419     /**
420      * The {@link StatusBarState} of the status bar.
421      */
422     protected int mState; // TODO: remove this. Just use StatusBarStateController
423     protected boolean mBouncerShowing;
424     private boolean mBouncerShowingOverDream;
425 
426     private final PhoneStatusBarPolicy mIconPolicy;
427 
428     private final VolumeComponent mVolumeComponent;
429     private BrightnessMirrorController mBrightnessMirrorController;
430     private boolean mBrightnessMirrorVisible;
431     private BiometricUnlockController mBiometricUnlockController;
432     private final LightBarController mLightBarController;
433     private final Lazy<LockscreenWallpaper> mLockscreenWallpaperLazy;
434     @Nullable
435     protected LockscreenWallpaper mLockscreenWallpaper;
436     private final AutoHideController mAutoHideController;
437 
438     private final Point mCurrentDisplaySize = new Point();
439 
440     protected NotificationShadeWindowView mNotificationShadeWindowView;
441     protected PhoneStatusBarView mStatusBarView;
442     private PhoneStatusBarViewController mPhoneStatusBarViewController;
443     private PhoneStatusBarTransitions mStatusBarTransitions;
444     private AuthRippleController mAuthRippleController;
445     @WindowVisibleState private int mStatusBarWindowState = WINDOW_STATE_SHOWING;
446     protected final NotificationShadeWindowController mNotificationShadeWindowController;
447     private final StatusBarWindowController mStatusBarWindowController;
448     private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
449     @VisibleForTesting
450     DozeServiceHost mDozeServiceHost;
451     private LightRevealScrim mLightRevealScrim;
452     private PowerButtonReveal mPowerButtonReveal;
453 
454     private boolean mWakeUpComingFromTouch;
455 
456     /**
457      * Whether we should delay the wakeup animation (which shows the notifications and moves the
458      * clock view). This is typically done when waking up from a 'press to unlock' gesture on a
459      * device with a side fingerprint sensor, so that if the fingerprint scan is successful, we
460      * can play the unlock animation directly rather than interrupting the wakeup animation part
461      * way through.
462      */
463     private boolean mShouldDelayWakeUpAnimation = false;
464 
465     private final Object mQueueLock = new Object();
466 
467     private final PulseExpansionHandler mPulseExpansionHandler;
468     private final NotificationWakeUpCoordinator mWakeUpCoordinator;
469     private final KeyguardBypassController mKeyguardBypassController;
470     private final KeyguardStateController mKeyguardStateController;
471     private final HeadsUpManagerPhone mHeadsUpManager;
472     private final StatusBarTouchableRegionManager mStatusBarTouchableRegionManager;
473     private final FalsingCollector mFalsingCollector;
474     private final FalsingManager mFalsingManager;
475     private final BroadcastDispatcher mBroadcastDispatcher;
476     private final ConfigurationController mConfigurationController;
477     protected NotificationShadeWindowViewController mNotificationShadeWindowViewController;
478     private final DozeParameters mDozeParameters;
479     private final Lazy<BiometricUnlockController> mBiometricUnlockControllerLazy;
480     private final CentralSurfacesComponent.Factory mCentralSurfacesComponentFactory;
481     private final PluginManager mPluginManager;
482     private final ShadeController mShadeController;
483     private final InitController mInitController;
484     private final Lazy<CameraLauncher> mCameraLauncherLazy;
485     private final AlternateBouncerInteractor mAlternateBouncerInteractor;
486 
487     private final PluginDependencyProvider mPluginDependencyProvider;
488     private final KeyguardDismissUtil mKeyguardDismissUtil;
489     private final ExtensionController mExtensionController;
490     private final UserInfoControllerImpl mUserInfoControllerImpl;
491     private final DemoModeController mDemoModeController;
492     private final NotificationsController mNotificationsController;
493     private final OngoingCallController mOngoingCallController;
494     private final StatusBarSignalPolicy mStatusBarSignalPolicy;
495     private final StatusBarHideIconsForBouncerManager mStatusBarHideIconsForBouncerManager;
496     private final Lazy<LightRevealScrimViewModel> mLightRevealScrimViewModelLazy;
497 
498     /** Controller for the Shade. */
499     @VisibleForTesting
500     NotificationPanelViewController mNotificationPanelViewController;
501 
502     // settings
503     private QSPanelController mQSPanelController;
504     @VisibleForTesting
505     QuickSettingsController mQsController;
506 
507     KeyguardIndicationController mKeyguardIndicationController;
508 
509     private View mReportRejectedTouch;
510 
511     private final NotificationGutsManager mGutsManager;
512     private final NotificationLogger mNotificationLogger;
513     private final ShadeExpansionStateManager mShadeExpansionStateManager;
514     private final KeyguardViewMediator mKeyguardViewMediator;
515     protected final NotificationInterruptStateProvider mNotificationInterruptStateProvider;
516     private final BrightnessSliderController.Factory mBrightnessSliderFactory;
517     private final FeatureFlags mFeatureFlags;
518     private final FragmentService mFragmentService;
519     private final ScreenOffAnimationController mScreenOffAnimationController;
520     private final WallpaperController mWallpaperController;
521     private final KeyguardUnlockAnimationController mKeyguardUnlockAnimationController;
522     private final MessageRouter mMessageRouter;
523     private final WallpaperManager mWallpaperManager;
524     private final UserTracker mUserTracker;
525     private final Provider<FingerprintManager> mFingerprintManager;
526 
527     private CentralSurfacesComponent mCentralSurfacesComponent;
528 
529     // Flags for disabling the status bar
530     // Two variables because the first one evidently ran out of room for new flags.
531     private int mDisabled1 = 0;
532     private int mDisabled2 = 0;
533 
534     /**
535      * This keeps track of whether we have (or haven't) registered the predictive back callback.
536      * Since we can have visible -> visible transitions, we need to avoid
537      * double-registering (or double-unregistering) our callback.
538      */
539     private boolean mIsBackCallbackRegistered = false;
540 
541     /** @see android.view.WindowInsetsController#setSystemBarsAppearance(int, int) */
542     private @Appearance int mAppearance;
543 
544     private boolean mTransientShown;
545 
546     private final DisplayMetrics mDisplayMetrics;
547 
548     // XXX: gesture research
549     private final GestureRecorder mGestureRec = DEBUG_GESTURES
550         ? new GestureRecorder("/sdcard/statusbar_gestures.dat")
551         : null;
552 
553     private final ScreenPinningRequest mScreenPinningRequest;
554 
555     private final MetricsLogger mMetricsLogger;
556 
557     // ensure quick settings is disabled until the current user makes it through the setup wizard
558     @VisibleForTesting
559     protected boolean mUserSetup = false;
560 
561     @VisibleForTesting
562     public enum StatusBarUiEvent implements UiEventLogger.UiEventEnum {
563         @UiEvent(doc = "Secured lockscreen is opened.")
564         LOCKSCREEN_OPEN_SECURE(405),
565 
566         @UiEvent(doc = "Lockscreen without security is opened.")
567         LOCKSCREEN_OPEN_INSECURE(406),
568 
569         @UiEvent(doc = "Secured lockscreen is closed.")
570         LOCKSCREEN_CLOSE_SECURE(407),
571 
572         @UiEvent(doc = "Lockscreen without security is closed.")
573         LOCKSCREEN_CLOSE_INSECURE(408),
574 
575         @UiEvent(doc = "Secured bouncer is opened.")
576         BOUNCER_OPEN_SECURE(409),
577 
578         @UiEvent(doc = "Bouncer without security is opened.")
579         BOUNCER_OPEN_INSECURE(410),
580 
581         @UiEvent(doc = "Secured bouncer is closed.")
582         BOUNCER_CLOSE_SECURE(411),
583 
584         @UiEvent(doc = "Bouncer without security is closed.")
585         BOUNCER_CLOSE_INSECURE(412);
586 
587         private final int mId;
588 
StatusBarUiEvent(int id)589         StatusBarUiEvent(int id) {
590             mId = id;
591         }
592 
593         @Override
getId()594         public int getId() {
595             return mId;
596         }
597     }
598 
599     private final DelayableExecutor mMainExecutor;
600 
601     private int mInteractingWindows;
602     private @TransitionMode int mStatusBarMode;
603 
604     private final ViewMediatorCallback mKeyguardViewMediatorCallback;
605     private final ScrimController mScrimController;
606     protected DozeScrimController mDozeScrimController;
607     private final Executor mUiBgExecutor;
608 
609     protected boolean mDozing;
610     private boolean mIsFullscreen;
611 
612     boolean mCloseQsBeforeScreenOff;
613 
614     private final NotificationMediaManager mMediaManager;
615     private final NotificationLockscreenUserManager mLockscreenUserManager;
616     private final NotificationRemoteInputManager mRemoteInputManager;
617     private boolean mWallpaperSupported;
618 
619     private Runnable mLaunchTransitionEndRunnable;
620     private Runnable mLaunchTransitionCancelRunnable;
621     private boolean mLaunchCameraWhenFinishedWaking;
622     private boolean mLaunchCameraOnFinishedGoingToSleep;
623     private boolean mLaunchEmergencyActionWhenFinishedWaking;
624     private boolean mLaunchEmergencyActionOnFinishedGoingToSleep;
625     private int mLastCameraLaunchSource;
626     protected PowerManager.WakeLock mGestureWakeLock;
627 
628     // Fingerprint (as computed by getLoggingFingerprint() of the last logged state.
629     private int mLastLoggedStateFingerprint;
630     private boolean mIsLaunchingActivityOverLockscreen;
631 
632     private final UserSwitcherController mUserSwitcherController;
633     private final LifecycleRegistry mLifecycle = new LifecycleRegistry(this);
634     protected final BatteryController mBatteryController;
635     protected boolean mPanelExpanded;
636     private UiModeManager mUiModeManager;
637     private LogMaker mStatusBarStateLog;
638     protected final NotificationIconAreaController mNotificationIconAreaController;
639     @Nullable private View mAmbientIndicationContainer;
640     private final SysuiColorExtractor mColorExtractor;
641     private final ScreenLifecycle mScreenLifecycle;
642     private final WakefulnessLifecycle mWakefulnessLifecycle;
643 
644     private boolean mNoAnimationOnNextBarModeChange;
645     private final SysuiStatusBarStateController mStatusBarStateController;
646 
647     private final ActivityLaunchAnimator mActivityLaunchAnimator;
648     private NotificationLaunchAnimatorControllerProvider mNotificationAnimationProvider;
649     protected NotificationPresenter mPresenter;
650     private NotificationActivityStarter mNotificationActivityStarter;
651     private final Lazy<NotificationShadeDepthController> mNotificationShadeDepthControllerLazy;
652     private final Optional<Bubbles> mBubblesOptional;
653     private final Bubbles.BubbleExpandListener mBubbleExpandListener;
654     private final Optional<StartingSurface> mStartingSurfaceOptional;
655 
656     private final ActivityIntentHelper mActivityIntentHelper;
657     private NotificationStackScrollLayoutController mStackScrollerController;
658 
659     private final ColorExtractor.OnColorsChangedListener mOnColorsChangedListener =
660             (extractor, which) -> updateTheme();
661 
662     private final InteractionJankMonitor mJankMonitor;
663 
664     private final OnBackInvokedCallback mOnBackInvokedCallback = () -> {
665         if (DEBUG) {
666             Log.d(TAG, "mOnBackInvokedCallback() called");
667         }
668         onBackPressed();
669     };
670 
671     /**
672      * Public constructor for CentralSurfaces.
673      *
674      * CentralSurfaces is considered optional, and therefore can not be marked as @Inject directly.
675      * Instead, an @Provide method is included. See {@link StatusBarPhoneModule}.
676      */
677     @SuppressWarnings("OptionalUsedAsFieldOrParameterType")
678     @Inject
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, NotificationGutsManager notificationGutsManager, NotificationLogger notificationLogger, NotificationInterruptStateProvider notificationInterruptStateProvider, ShadeExpansionStateManager shadeExpansionStateManager, KeyguardViewMediator keyguardViewMediator, DisplayMetrics displayMetrics, MetricsLogger metricsLogger, @UiBackground Executor uiBgExecutor, NotificationMediaManager notificationMediaManager, NotificationLockscreenUserManager lockScreenUserManager, NotificationRemoteInputManager remoteInputManager, UserSwitcherController userSwitcherController, BatteryController batteryController, SysuiColorExtractor colorExtractor, ScreenLifecycle screenLifecycle, WakefulnessLifecycle wakefulnessLifecycle, SysuiStatusBarStateController statusBarStateController, Optional<Bubbles> bubblesOptional, DeviceProvisionedController deviceProvisionedController, NavigationBarController navigationBarController, AccessibilityFloatingMenuController accessibilityFloatingMenuController, Lazy<AssistManager> assistManagerLazy, ConfigurationController configurationController, NotificationShadeWindowController notificationShadeWindowController, DozeParameters dozeParameters, ScrimController scrimController, Lazy<LockscreenWallpaper> lockscreenWallpaperLazy, Lazy<BiometricUnlockController> 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<NotificationShadeDepthController> notificationShadeDepthControllerLazy, StatusBarTouchableRegionManager statusBarTouchableRegionManager, NotificationIconAreaController notificationIconAreaController, BrightnessSliderController.Factory brightnessSliderFactory, ScreenOffAnimationController screenOffAnimationController, WallpaperController wallpaperController, OngoingCallController ongoingCallController, StatusBarHideIconsForBouncerManager statusBarHideIconsForBouncerManager, LockscreenShadeTransitionController lockscreenShadeTransitionController, FeatureFlags featureFlags, KeyguardUnlockAnimationController keyguardUnlockAnimationController, @Main DelayableExecutor delayableExecutor, @Main MessageRouter messageRouter, WallpaperManager wallpaperManager, Optional<StartingSurface> startingSurfaceOptional, ActivityLaunchAnimator activityLaunchAnimator, InteractionJankMonitor jankMonitor, DeviceStateManager deviceStateManager, WiredChargingRippleController wiredChargingRippleController, IDreamManager dreamManager, Lazy<CameraLauncher> cameraLauncherLazy, Lazy<LightRevealScrimViewModel> lightRevealScrimViewModelLazy, AlternateBouncerInteractor alternateBouncerInteractor, UserTracker userTracker, Provider<FingerprintManager> fingerprintManager )679     public CentralSurfacesImpl(
680             Context context,
681             NotificationsController notificationsController,
682             FragmentService fragmentService,
683             LightBarController lightBarController,
684             AutoHideController autoHideController,
685             StatusBarWindowController statusBarWindowController,
686             StatusBarWindowStateController statusBarWindowStateController,
687             KeyguardUpdateMonitor keyguardUpdateMonitor,
688             StatusBarSignalPolicy statusBarSignalPolicy,
689             PulseExpansionHandler pulseExpansionHandler,
690             NotificationWakeUpCoordinator notificationWakeUpCoordinator,
691             KeyguardBypassController keyguardBypassController,
692             KeyguardStateController keyguardStateController,
693             HeadsUpManagerPhone headsUpManagerPhone,
694             DynamicPrivacyController dynamicPrivacyController,
695             FalsingManager falsingManager,
696             FalsingCollector falsingCollector,
697             BroadcastDispatcher broadcastDispatcher,
698             NotificationGutsManager notificationGutsManager,
699             NotificationLogger notificationLogger,
700             NotificationInterruptStateProvider notificationInterruptStateProvider,
701             ShadeExpansionStateManager shadeExpansionStateManager,
702             KeyguardViewMediator keyguardViewMediator,
703             DisplayMetrics displayMetrics,
704             MetricsLogger metricsLogger,
705             @UiBackground Executor uiBgExecutor,
706             NotificationMediaManager notificationMediaManager,
707             NotificationLockscreenUserManager lockScreenUserManager,
708             NotificationRemoteInputManager remoteInputManager,
709             UserSwitcherController userSwitcherController,
710             BatteryController batteryController,
711             SysuiColorExtractor colorExtractor,
712             ScreenLifecycle screenLifecycle,
713             WakefulnessLifecycle wakefulnessLifecycle,
714             SysuiStatusBarStateController statusBarStateController,
715             Optional<Bubbles> bubblesOptional,
716             DeviceProvisionedController deviceProvisionedController,
717             NavigationBarController navigationBarController,
718             AccessibilityFloatingMenuController accessibilityFloatingMenuController,
719             Lazy<AssistManager> assistManagerLazy,
720             ConfigurationController configurationController,
721             NotificationShadeWindowController notificationShadeWindowController,
722             DozeParameters dozeParameters,
723             ScrimController scrimController,
724             Lazy<LockscreenWallpaper> lockscreenWallpaperLazy,
725             Lazy<BiometricUnlockController> biometricUnlockControllerLazy,
726             DozeServiceHost dozeServiceHost,
727             PowerManager powerManager,
728             ScreenPinningRequest screenPinningRequest,
729             DozeScrimController dozeScrimController,
730             VolumeComponent volumeComponent,
731             CommandQueue commandQueue,
732             CentralSurfacesComponent.Factory centralSurfacesComponentFactory,
733             PluginManager pluginManager,
734             ShadeController shadeController,
735             StatusBarKeyguardViewManager statusBarKeyguardViewManager,
736             ViewMediatorCallback viewMediatorCallback,
737             InitController initController,
738             @Named(TIME_TICK_HANDLER_NAME) Handler timeTickHandler,
739             PluginDependencyProvider pluginDependencyProvider,
740             KeyguardDismissUtil keyguardDismissUtil,
741             ExtensionController extensionController,
742             UserInfoControllerImpl userInfoControllerImpl,
743             PhoneStatusBarPolicy phoneStatusBarPolicy,
744             KeyguardIndicationController keyguardIndicationController,
745             DemoModeController demoModeController,
746             Lazy<NotificationShadeDepthController> notificationShadeDepthControllerLazy,
747             StatusBarTouchableRegionManager statusBarTouchableRegionManager,
748             NotificationIconAreaController notificationIconAreaController,
749             BrightnessSliderController.Factory brightnessSliderFactory,
750             ScreenOffAnimationController screenOffAnimationController,
751             WallpaperController wallpaperController,
752             OngoingCallController ongoingCallController,
753             StatusBarHideIconsForBouncerManager statusBarHideIconsForBouncerManager,
754             LockscreenShadeTransitionController lockscreenShadeTransitionController,
755             FeatureFlags featureFlags,
756             KeyguardUnlockAnimationController keyguardUnlockAnimationController,
757             @Main DelayableExecutor delayableExecutor,
758             @Main MessageRouter messageRouter,
759             WallpaperManager wallpaperManager,
760             Optional<StartingSurface> startingSurfaceOptional,
761             ActivityLaunchAnimator activityLaunchAnimator,
762             InteractionJankMonitor jankMonitor,
763             DeviceStateManager deviceStateManager,
764             WiredChargingRippleController wiredChargingRippleController,
765             IDreamManager dreamManager,
766             Lazy<CameraLauncher> cameraLauncherLazy,
767             Lazy<LightRevealScrimViewModel> lightRevealScrimViewModelLazy,
768             AlternateBouncerInteractor alternateBouncerInteractor,
769             UserTracker userTracker,
770             Provider<FingerprintManager> fingerprintManager
771     ) {
772         mContext = context;
773         mNotificationsController = notificationsController;
774         mFragmentService = fragmentService;
775         mLightBarController = lightBarController;
776         mAutoHideController = autoHideController;
777         mStatusBarWindowController = statusBarWindowController;
778         mKeyguardUpdateMonitor = keyguardUpdateMonitor;
779         mPulseExpansionHandler = pulseExpansionHandler;
780         mWakeUpCoordinator = notificationWakeUpCoordinator;
781         mKeyguardBypassController = keyguardBypassController;
782         mKeyguardStateController = keyguardStateController;
783         mHeadsUpManager = headsUpManagerPhone;
784         mKeyguardIndicationController = keyguardIndicationController;
785         mStatusBarTouchableRegionManager = statusBarTouchableRegionManager;
786         mFalsingCollector = falsingCollector;
787         mFalsingManager = falsingManager;
788         mBroadcastDispatcher = broadcastDispatcher;
789         mGutsManager = notificationGutsManager;
790         mNotificationLogger = notificationLogger;
791         mNotificationInterruptStateProvider = notificationInterruptStateProvider;
792         mShadeExpansionStateManager = shadeExpansionStateManager;
793         mKeyguardViewMediator = keyguardViewMediator;
794         mDisplayMetrics = displayMetrics;
795         mMetricsLogger = metricsLogger;
796         mUiBgExecutor = uiBgExecutor;
797         mMediaManager = notificationMediaManager;
798         mLockscreenUserManager = lockScreenUserManager;
799         mRemoteInputManager = remoteInputManager;
800         mUserSwitcherController = userSwitcherController;
801         mBatteryController = batteryController;
802         mColorExtractor = colorExtractor;
803         mScreenLifecycle = screenLifecycle;
804         mWakefulnessLifecycle = wakefulnessLifecycle;
805         mStatusBarStateController = statusBarStateController;
806         mBubblesOptional = bubblesOptional;
807         mDeviceProvisionedController = deviceProvisionedController;
808         mNavigationBarController = navigationBarController;
809         mAccessibilityFloatingMenuController = accessibilityFloatingMenuController;
810         mAssistManagerLazy = assistManagerLazy;
811         mConfigurationController = configurationController;
812         mNotificationShadeWindowController = notificationShadeWindowController;
813         mDozeServiceHost = dozeServiceHost;
814         mPowerManager = powerManager;
815         mDozeParameters = dozeParameters;
816         mScrimController = scrimController;
817         mLockscreenWallpaperLazy = lockscreenWallpaperLazy;
818         mScreenPinningRequest = screenPinningRequest;
819         mDozeScrimController = dozeScrimController;
820         mBiometricUnlockControllerLazy = biometricUnlockControllerLazy;
821         mNotificationShadeDepthControllerLazy = notificationShadeDepthControllerLazy;
822         mVolumeComponent = volumeComponent;
823         mCommandQueue = commandQueue;
824         mCentralSurfacesComponentFactory = centralSurfacesComponentFactory;
825         mPluginManager = pluginManager;
826         mShadeController = shadeController;
827         mStatusBarKeyguardViewManager = statusBarKeyguardViewManager;
828         mKeyguardViewMediatorCallback = viewMediatorCallback;
829         mInitController = initController;
830         mPluginDependencyProvider = pluginDependencyProvider;
831         mKeyguardDismissUtil = keyguardDismissUtil;
832         mExtensionController = extensionController;
833         mUserInfoControllerImpl = userInfoControllerImpl;
834         mIconPolicy = phoneStatusBarPolicy;
835         mDemoModeController = demoModeController;
836         mNotificationIconAreaController = notificationIconAreaController;
837         mBrightnessSliderFactory = brightnessSliderFactory;
838         mWallpaperController = wallpaperController;
839         mOngoingCallController = ongoingCallController;
840         mStatusBarSignalPolicy = statusBarSignalPolicy;
841         mStatusBarHideIconsForBouncerManager = statusBarHideIconsForBouncerManager;
842         mFeatureFlags = featureFlags;
843         mKeyguardUnlockAnimationController = keyguardUnlockAnimationController;
844         mMainExecutor = delayableExecutor;
845         mMessageRouter = messageRouter;
846         mWallpaperManager = wallpaperManager;
847         mJankMonitor = jankMonitor;
848         mCameraLauncherLazy = cameraLauncherLazy;
849         mAlternateBouncerInteractor = alternateBouncerInteractor;
850         mUserTracker = userTracker;
851         mFingerprintManager = fingerprintManager;
852 
853         mLockscreenShadeTransitionController = lockscreenShadeTransitionController;
854         mStartingSurfaceOptional = startingSurfaceOptional;
855         mDreamManager = dreamManager;
856         lockscreenShadeTransitionController.setCentralSurfaces(this);
857         statusBarWindowStateController.addListener(this::onStatusBarWindowStateChanged);
858 
859         mScreenOffAnimationController = screenOffAnimationController;
860 
861         mShadeExpansionStateManager.addExpansionListener(this::onPanelExpansionChanged);
862         mShadeExpansionStateManager.addFullExpansionListener(this::onShadeExpansionFullyChanged);
863 
864         mBubbleExpandListener = (isExpanding, key) ->
865                 mContext.getMainExecutor().execute(this::updateScrimController);
866 
867         mActivityIntentHelper = new ActivityIntentHelper(mContext);
868         mActivityLaunchAnimator = activityLaunchAnimator;
869 
870         // The status bar background may need updating when the ongoing call status changes.
871         mOngoingCallController.addCallback((animate) -> maybeUpdateBarMode());
872 
873         // TODO(b/190746471): Find a better home for this.
874         DateTimeView.setReceiverHandler(timeTickHandler);
875 
876         mMessageRouter.subscribeTo(KeyboardShortcutsMessage.class,
877                 data -> toggleKeyboardShortcuts(data.mDeviceId));
878         mMessageRouter.subscribeTo(MSG_DISMISS_KEYBOARD_SHORTCUTS_MENU,
879                 id -> dismissKeyboardShortcuts());
880         mMessageRouter.subscribeTo(AnimateExpandSettingsPanelMessage.class,
881                 data -> mCommandQueueCallbacks.animateExpandSettingsPanel(data.mSubpanel));
882         mMessageRouter.subscribeTo(MSG_LAUNCH_TRANSITION_TIMEOUT,
883                 id -> onLaunchTransitionTimeout());
884 
885         mDeviceStateManager = deviceStateManager;
886         wiredChargingRippleController.registerCallbacks();
887 
888         mLightRevealScrimViewModelLazy = lightRevealScrimViewModelLazy;
889 
890         // Based on teamfood flag, turn predictive back dispatch on at runtime.
891         if (mFeatureFlags.isEnabled(Flags.WM_ENABLE_PREDICTIVE_BACK_SYSUI)) {
892             mContext.getApplicationInfo().setEnableOnBackInvokedCallback(true);
893         }
894     }
895 
896     @Override
start()897     public void start() {
898         mScreenLifecycle.addObserver(mScreenObserver);
899         mWakefulnessLifecycle.addObserver(mWakefulnessObserver);
900         mUiModeManager = mContext.getSystemService(UiModeManager.class);
901         if (mBubblesOptional.isPresent()) {
902             mBubblesOptional.get().setExpandListener(mBubbleExpandListener);
903         }
904 
905         // Do not restart System UI when the bugreport flag changes.
906         mFeatureFlags.addListener(Flags.LEAVE_SHADE_OPEN_FOR_BUGREPORT, event -> {
907             event.requestNoRestart();
908         });
909 
910         mStatusBarSignalPolicy.init();
911         mKeyguardIndicationController.init();
912 
913         mColorExtractor.addOnColorsChangedListener(mOnColorsChangedListener);
914 
915         mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
916 
917         mDisplay = mContext.getDisplay();
918         mDisplayId = mDisplay.getDisplayId();
919         updateDisplaySize();
920         mStatusBarHideIconsForBouncerManager.setDisplayId(mDisplayId);
921 
922         initShadeVisibilityListener();
923 
924         // start old BaseStatusBar.start().
925         mWindowManagerService = WindowManagerGlobal.getWindowManagerService();
926         mDevicePolicyManager = (DevicePolicyManager) mContext.getSystemService(
927                 Context.DEVICE_POLICY_SERVICE);
928 
929         mAccessibilityManager = (AccessibilityManager)
930                 mContext.getSystemService(Context.ACCESSIBILITY_SERVICE);
931 
932         mKeyguardUpdateMonitor.setKeyguardBypassController(mKeyguardBypassController);
933         mBarService = IStatusBarService.Stub.asInterface(
934                 ServiceManager.getService(Context.STATUS_BAR_SERVICE));
935 
936         mKeyguardManager = (KeyguardManager) mContext.getSystemService(Context.KEYGUARD_SERVICE);
937         mWallpaperSupported = mWallpaperManager.isWallpaperSupported();
938 
939         RegisterStatusBarResult result = null;
940         try {
941             result = mBarService.registerStatusBar(mCommandQueue);
942         } catch (RemoteException ex) {
943             ex.rethrowFromSystemServer();
944         }
945 
946         createAndAddWindows(result);
947 
948         if (mWallpaperSupported) {
949             // Make sure we always have the most current wallpaper info.
950             IntentFilter wallpaperChangedFilter = new IntentFilter(Intent.ACTION_WALLPAPER_CHANGED);
951             mBroadcastDispatcher.registerReceiver(mWallpaperChangedReceiver, wallpaperChangedFilter,
952                     null /* handler */, UserHandle.ALL);
953             mWallpaperChangedReceiver.onReceive(mContext, null);
954         } else if (DEBUG) {
955             Log.v(TAG, "start(): no wallpaper service ");
956         }
957 
958         // Set up the initial notification state. This needs to happen before CommandQueue.disable()
959         setUpPresenter();
960 
961         if (containsType(result.mTransientBarTypes, ITYPE_STATUS_BAR)) {
962             showTransientUnchecked();
963         }
964         mCommandQueueCallbacks.onSystemBarAttributesChanged(mDisplayId, result.mAppearance,
965                 result.mAppearanceRegions, result.mNavbarColorManagedByIme, result.mBehavior,
966                 result.mRequestedVisibilities, result.mPackageName, result.mLetterboxDetails);
967 
968         // StatusBarManagerService has a back up of IME token and it's restored here.
969         mCommandQueueCallbacks.setImeWindowStatus(mDisplayId, result.mImeToken,
970                 result.mImeWindowVis, result.mImeBackDisposition, result.mShowImeSwitcher);
971 
972         // Set up the initial icon state
973         int numIcons = result.mIcons.size();
974         for (int i = 0; i < numIcons; i++) {
975             mCommandQueue.setIcon(result.mIcons.keyAt(i), result.mIcons.valueAt(i));
976         }
977 
978         if (DEBUG) {
979             Log.d(TAG, String.format(
980                     "init: icons=%d disabled=0x%08x lights=0x%08x imeButton=0x%08x",
981                     numIcons,
982                     result.mDisabledFlags1,
983                     result.mAppearance,
984                     result.mImeWindowVis));
985         }
986 
987         IntentFilter internalFilter = new IntentFilter();
988         internalFilter.addAction(BANNER_ACTION_CANCEL);
989         internalFilter.addAction(BANNER_ACTION_SETUP);
990         mContext.registerReceiver(mBannerActionBroadcastReceiver, internalFilter, PERMISSION_SELF,
991                 null, Context.RECEIVER_EXPORTED_UNAUDITED);
992 
993         if (mWallpaperSupported) {
994             IWallpaperManager wallpaperManager = IWallpaperManager.Stub.asInterface(
995                     ServiceManager.getService(Context.WALLPAPER_SERVICE));
996             try {
997                 wallpaperManager.setInAmbientMode(false /* ambientMode */, 0L /* duration */);
998             } catch (RemoteException e) {
999                 // Just pass, nothing critical.
1000             }
1001         }
1002 
1003         // end old BaseStatusBar.start().
1004 
1005         // Lastly, call to the icon policy to install/update all the icons.
1006         mIconPolicy.init();
1007 
1008         mKeyguardStateController.addCallback(new KeyguardStateController.Callback() {
1009             @Override
1010             public void onUnlockedChanged() {
1011                 logStateToEventlog();
1012             }
1013 
1014             @Override
1015             public void onKeyguardGoingAwayChanged() {
1016                 if (mFeatureFlags.isEnabled(Flags.LIGHT_REVEAL_MIGRATION)) {
1017                     // This code path is not used if the KeyguardTransitionRepository is managing
1018                     // the lightreveal scrim.
1019                     return;
1020                 }
1021 
1022                 // The light reveal scrim should always be fully revealed by the time the keyguard
1023                 // is done going away. Double check that this is true.
1024                 if (!mKeyguardStateController.isKeyguardGoingAway()) {
1025                     if (mLightRevealScrim.getRevealAmount() != 1f) {
1026                         Log.e(TAG, "Keyguard is done going away, but someone left the light reveal "
1027                                 + "scrim at reveal amount: " + mLightRevealScrim.getRevealAmount());
1028                     }
1029 
1030                     // If the auth ripple is still playing, let it finish.
1031                     if (!mAuthRippleController.isAnimatingLightRevealScrim()) {
1032                         mLightRevealScrim.setRevealAmount(1f);
1033                     }
1034                 }
1035             }
1036         });
1037         startKeyguard();
1038 
1039         mKeyguardUpdateMonitor.registerCallback(mUpdateCallback);
1040         mDozeServiceHost.initialize(
1041                 this,
1042                 mStatusBarKeyguardViewManager,
1043                 mNotificationShadeWindowViewController,
1044                 mNotificationPanelViewController,
1045                 mAmbientIndicationContainer);
1046         updateLightRevealScrimVisibility();
1047 
1048         mConfigurationController.addCallback(mConfigurationListener);
1049 
1050         mBatteryController.observe(mLifecycle, mBatteryStateChangeCallback);
1051         mLifecycle.setCurrentState(RESUMED);
1052 
1053         mAccessibilityFloatingMenuController.init();
1054 
1055         // set the initial view visibility
1056         int disabledFlags1 = result.mDisabledFlags1;
1057         int disabledFlags2 = result.mDisabledFlags2;
1058         mInitController.addPostInitTask(() -> {
1059             setUpDisableFlags(disabledFlags1, disabledFlags2);
1060             try {
1061                 // NOTE(b/262059863): Force-update the disable flags after applying the flags
1062                 // returned from registerStatusBar(). The result's disabled flags may be stale
1063                 // if StatusBarManager's disabled flags are updated between registering the bar and
1064                 // this handling this post-init task. We force an update in this case, and use a new
1065                 // token to not conflict with any other disabled flags already requested by SysUI
1066                 Binder token = new Binder();
1067                 mBarService.disable(DISABLE_HOME, token, mContext.getPackageName());
1068                 mBarService.disable(0, token, mContext.getPackageName());
1069             } catch (RemoteException ex) {
1070                 ex.rethrowFromSystemServer();
1071             }
1072         });
1073 
1074         registerCallbacks();
1075 
1076         mFalsingManager.addFalsingBeliefListener(mFalsingBeliefListener);
1077 
1078         mPluginManager.addPluginListener(
1079                 new PluginListener<OverlayPlugin>() {
1080                     private final ArraySet<OverlayPlugin> mOverlays = new ArraySet<>();
1081 
1082                     @Override
1083                     public void onPluginConnected(OverlayPlugin plugin, Context pluginContext) {
1084                         mMainExecutor.execute(
1085                                 () -> plugin.setup(getNotificationShadeWindowView(),
1086                                         getNavigationBarView(),
1087                                         new Callback(plugin), mDozeParameters));
1088                     }
1089 
1090                     @Override
1091                     public void onPluginDisconnected(OverlayPlugin plugin) {
1092                         mMainExecutor.execute(() -> {
1093                             mOverlays.remove(plugin);
1094                             mNotificationShadeWindowController
1095                                     .setForcePluginOpen(mOverlays.size() != 0, this);
1096                         });
1097                     }
1098 
1099                     class Callback implements OverlayPlugin.Callback {
1100                         private final OverlayPlugin mPlugin;
1101 
1102                         Callback(OverlayPlugin plugin) {
1103                             mPlugin = plugin;
1104                         }
1105 
1106                         @Override
1107                         public void onHoldStatusBarOpenChange() {
1108                             if (mPlugin.holdStatusBarOpen()) {
1109                                 mOverlays.add(mPlugin);
1110                             } else {
1111                                 mOverlays.remove(mPlugin);
1112                             }
1113                             mMainExecutor.execute(() -> {
1114                                 mNotificationShadeWindowController
1115                                         .setStateListener(b -> mOverlays.forEach(
1116                                                 o -> o.setCollapseDesired(b)));
1117                                 mNotificationShadeWindowController
1118                                         .setForcePluginOpen(mOverlays.size() != 0, this);
1119                             });
1120                         }
1121                     }
1122                 }, OverlayPlugin.class, true /* Allow multiple plugins */);
1123 
1124         mStartingSurfaceOptional.ifPresent(startingSurface -> startingSurface.setSysuiProxy(
1125                 (requestTopUi, componentTag) -> mMainExecutor.execute(() ->
1126                         mNotificationShadeWindowController.setRequestTopUi(
1127                                 requestTopUi, componentTag))));
1128     }
1129 
1130     @VisibleForTesting
1131     /** Registers listeners/callbacks with external dependencies. */
registerCallbacks()1132     void registerCallbacks() {
1133         //TODO(b/264502026) move the rest of the listeners here.
1134         mDeviceStateManager.registerCallback(mMainExecutor,
1135                 new FoldStateListener(mContext, this::onFoldedStateChanged));
1136     }
1137 
1138     @VisibleForTesting
initShadeVisibilityListener()1139     void initShadeVisibilityListener() {
1140         mShadeController.setVisibilityListener(new ShadeController.ShadeVisibilityListener() {
1141             @Override
1142             public void visibilityChanged(boolean visible) {
1143                 onShadeVisibilityChanged(visible);
1144             }
1145 
1146             @Override
1147             public void expandedVisibleChanged(boolean expandedVisible) {
1148                 if (expandedVisible) {
1149                     setInteracting(StatusBarManager.WINDOW_STATUS_BAR, true);
1150                 } else {
1151                     onExpandedInvisible();
1152                 }
1153             }
1154         });
1155     }
1156 
onFoldedStateChanged(boolean isFolded, boolean willGoToSleep)1157     private void onFoldedStateChanged(boolean isFolded, boolean willGoToSleep) {
1158         Trace.beginSection("CentralSurfaces#onFoldedStateChanged");
1159         onFoldedStateChangedInternal(isFolded, willGoToSleep);
1160         Trace.endSection();
1161     }
1162 
onFoldedStateChangedInternal(boolean isFolded, boolean willGoToSleep)1163     private void onFoldedStateChangedInternal(boolean isFolded, boolean willGoToSleep) {
1164         // Folded state changes are followed by a screen off event.
1165         // By default turning off the screen also closes the shade.
1166         // We want to make sure that the shade status is kept after folding/unfolding.
1167         boolean isShadeOpen = mShadeController.isShadeFullyOpen();
1168         boolean leaveOpen = isShadeOpen && !willGoToSleep && mState == SHADE;
1169         if (DEBUG) {
1170             Log.d(TAG, String.format(
1171                     "#onFoldedStateChanged(): "
1172                             + "isFolded=%s, "
1173                             + "willGoToSleep=%s, "
1174                             + "isShadeOpen=%s, "
1175                             + "leaveOpen=%s",
1176                     isFolded, willGoToSleep, isShadeOpen, leaveOpen));
1177         }
1178         if (leaveOpen) {
1179             // below makes shade stay open when going from folded to unfolded
1180             mStatusBarStateController.setLeaveOpenOnKeyguardHide(true);
1181         }
1182         if (mState != SHADE && isShadeOpen) {
1183             // When device state changes on KEYGUARD/SHADE_LOCKED we don't want to keep the state of
1184             // the shade and instead we open clean state of keyguard with shade closed.
1185             // Normally some parts of QS state (like expanded/collapsed) are persisted and
1186             // that causes incorrect UI rendering, especially when changing state with QS
1187             // expanded. To prevent that we can close QS which resets QS and some parts of
1188             // the shade to its default state. Read more in b/201537421
1189             mCloseQsBeforeScreenOff = true;
1190         }
1191     }
1192 
1193     // ================================================================================
1194     // Constructing the view
1195     // ================================================================================
makeStatusBarView(@ullable RegisterStatusBarResult result)1196     protected void makeStatusBarView(@Nullable RegisterStatusBarResult result) {
1197         updateDisplaySize(); // populates mDisplayMetrics
1198         updateResources();
1199         updateTheme();
1200 
1201         inflateStatusBarWindow();
1202         mNotificationShadeWindowView.setOnTouchListener(getStatusBarWindowTouchListener());
1203         mWallpaperController.setRootView(mNotificationShadeWindowView);
1204 
1205         // TODO: Deal with the ugliness that comes from having some of the status bar broken out
1206         // into fragments, but the rest here, it leaves some awkward lifecycle and whatnot.
1207         mNotificationIconAreaController.setupShelf(mNotificationShelfController);
1208         mShadeExpansionStateManager.addExpansionListener(mWakeUpCoordinator);
1209 
1210         // Allow plugins to reference DarkIconDispatcher and StatusBarStateController
1211         mPluginDependencyProvider.allowPluginDependency(DarkIconDispatcher.class);
1212         mPluginDependencyProvider.allowPluginDependency(StatusBarStateController.class);
1213 
1214         // Set up CollapsedStatusBarFragment and PhoneStatusBarView
1215         StatusBarInitializer initializer = mCentralSurfacesComponent.getStatusBarInitializer();
1216         initializer.setStatusBarViewUpdatedListener(
1217                 (statusBarView, statusBarViewController, statusBarTransitions) -> {
1218                     mStatusBarView = statusBarView;
1219                     mPhoneStatusBarViewController = statusBarViewController;
1220                     mStatusBarTransitions = statusBarTransitions;
1221                     mNotificationShadeWindowViewController
1222                             .setStatusBarViewController(mPhoneStatusBarViewController);
1223                     // Ensure we re-propagate panel expansion values to the panel controller and
1224                     // any listeners it may have, such as PanelBar. This will also ensure we
1225                     // re-display the notification panel if necessary (for example, if
1226                     // a heads-up notification was being displayed and should continue being
1227                     // displayed).
1228                     mNotificationPanelViewController.updatePanelExpansionAndVisibility();
1229                     setBouncerShowingForStatusBarComponents(mBouncerShowing);
1230                     checkBarModes();
1231                 });
1232         initializer.initializeStatusBar(mCentralSurfacesComponent);
1233 
1234         mStatusBarTouchableRegionManager.setup(this, mNotificationShadeWindowView);
1235         mNotificationPanelViewController.setHeadsUpManager(mHeadsUpManager);
1236 
1237         createNavigationBar(result);
1238 
1239         if (ENABLE_LOCKSCREEN_WALLPAPER && mWallpaperSupported) {
1240             mLockscreenWallpaper = mLockscreenWallpaperLazy.get();
1241         }
1242 
1243         mAmbientIndicationContainer = mNotificationShadeWindowView.findViewById(
1244                 R.id.ambient_indication_container);
1245 
1246         mAutoHideController.setStatusBar(new AutoHideUiElement() {
1247             @Override
1248             public void synchronizeState() {
1249                 checkBarModes();
1250             }
1251 
1252             @Override
1253             public boolean shouldHideOnTouch() {
1254                 return !mRemoteInputManager.isRemoteInputActive();
1255             }
1256 
1257             @Override
1258             public boolean isVisible() {
1259                 return isTransientShown();
1260             }
1261 
1262             @Override
1263             public void hide() {
1264                 clearTransient();
1265             }
1266         });
1267 
1268         ScrimView scrimBehind = mNotificationShadeWindowView.findViewById(R.id.scrim_behind);
1269         ScrimView notificationsScrim = mNotificationShadeWindowView
1270                 .findViewById(R.id.scrim_notifications);
1271         ScrimView scrimInFront = mNotificationShadeWindowView.findViewById(R.id.scrim_in_front);
1272 
1273         mScrimController.setScrimVisibleListener(scrimsVisible -> {
1274             mNotificationShadeWindowController.setScrimsVisibility(scrimsVisible);
1275         });
1276         mScrimController.attachViews(scrimBehind, notificationsScrim, scrimInFront);
1277 
1278         mLightRevealScrim = mNotificationShadeWindowView.findViewById(R.id.light_reveal_scrim);
1279 
1280         if (mFeatureFlags.isEnabled(Flags.LIGHT_REVEAL_MIGRATION)) {
1281             LightRevealScrimViewBinder.bind(
1282                     mLightRevealScrim, mLightRevealScrimViewModelLazy.get());
1283         }
1284 
1285         mLightRevealScrim.setScrimOpaqueChangedListener((opaque) -> {
1286             Runnable updateOpaqueness = () -> {
1287                 mNotificationShadeWindowController.setLightRevealScrimOpaque(
1288                         mLightRevealScrim.isScrimOpaque());
1289                 mScreenOffAnimationController
1290                         .onScrimOpaqueChanged(mLightRevealScrim.isScrimOpaque());
1291             };
1292             if (opaque) {
1293                 // Delay making the view opaque for a frame, because it needs some time to render
1294                 // otherwise this can lead to a flicker where the scrim doesn't cover the screen
1295                 mLightRevealScrim.post(updateOpaqueness);
1296             } else {
1297                 updateOpaqueness.run();
1298             }
1299         });
1300 
1301         mScreenOffAnimationController.initialize(this, mLightRevealScrim);
1302         updateLightRevealScrimVisibility();
1303 
1304         mNotificationPanelViewController.initDependencies(
1305                 this,
1306                 mGestureRec,
1307                 mShadeController::makeExpandedInvisible,
1308                 mNotificationShelfController);
1309 
1310         BackDropView backdrop = mNotificationShadeWindowView.findViewById(R.id.backdrop);
1311         mMediaManager.setup(backdrop, backdrop.findViewById(R.id.backdrop_front),
1312                 backdrop.findViewById(R.id.backdrop_back), mScrimController, mLockscreenWallpaper);
1313         float maxWallpaperZoom = mContext.getResources().getFloat(
1314                 com.android.internal.R.dimen.config_wallpaperMaxScale);
1315         mNotificationShadeDepthControllerLazy.get().addListener(depth -> {
1316             float scale = MathUtils.lerp(maxWallpaperZoom, 1f, depth);
1317             backdrop.setPivotX(backdrop.getWidth() / 2f);
1318             backdrop.setPivotY(backdrop.getHeight() / 2f);
1319             backdrop.setScaleX(scale);
1320             backdrop.setScaleY(scale);
1321         });
1322 
1323         // Set up the quick settings tile panel
1324         final View container = mNotificationShadeWindowView.findViewById(R.id.qs_frame);
1325         if (container != null) {
1326             FragmentHostManager fragmentHostManager =
1327                     mFragmentService.getFragmentHostManager(container);
1328             ExtensionFragmentListener.attachExtensonToFragment(
1329                     mFragmentService,
1330                     container,
1331                     QS.TAG,
1332                     R.id.qs_frame,
1333                     mExtensionController
1334                             .newExtension(QS.class)
1335                             .withPlugin(QS.class)
1336                             .withDefault(this::createDefaultQSFragment)
1337                             .build());
1338             mBrightnessMirrorController = new BrightnessMirrorController(
1339                     mNotificationShadeWindowView,
1340                     mNotificationPanelViewController,
1341                     mNotificationShadeDepthControllerLazy.get(),
1342                     mBrightnessSliderFactory,
1343                     (visible) -> {
1344                         mBrightnessMirrorVisible = visible;
1345                         updateScrimController();
1346                     });
1347             fragmentHostManager.addTagListener(QS.TAG, (tag, f) -> {
1348                 QS qs = (QS) f;
1349                 if (qs instanceof QSFragment) {
1350                     mQSPanelController = ((QSFragment) qs).getQSPanelController();
1351                     ((QSFragment) qs).setBrightnessMirrorController(mBrightnessMirrorController);
1352                 }
1353             });
1354         }
1355 
1356         mReportRejectedTouch = mNotificationShadeWindowView
1357                 .findViewById(R.id.report_rejected_touch);
1358         if (mReportRejectedTouch != null) {
1359             updateReportRejectedTouchVisibility();
1360             mReportRejectedTouch.setOnClickListener(v -> {
1361                 Uri session = mFalsingManager.reportRejectedTouch();
1362                 if (session == null) { return; }
1363 
1364                 StringWriter message = new StringWriter();
1365                 message.write("Build info: ");
1366                 message.write(SystemProperties.get("ro.build.description"));
1367                 message.write("\nSerial number: ");
1368                 message.write(SystemProperties.get("ro.serialno"));
1369                 message.write("\n");
1370 
1371                 startActivityDismissingKeyguard(Intent.createChooser(new Intent(Intent.ACTION_SEND)
1372                                 .setType("*/*")
1373                                 .putExtra(Intent.EXTRA_SUBJECT, "Rejected touch report")
1374                                 .putExtra(Intent.EXTRA_STREAM, session)
1375                                 .putExtra(Intent.EXTRA_TEXT, message.toString()),
1376                         "Share rejected touch report")
1377                                 .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK),
1378                         true /* onlyProvisioned */, true /* dismissShade */);
1379             });
1380         }
1381 
1382         if (!mPowerManager.isInteractive()) {
1383             mBroadcastReceiver.onReceive(mContext, new Intent(Intent.ACTION_SCREEN_OFF));
1384         }
1385         mGestureWakeLock = mPowerManager.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK,
1386                 "sysui:GestureWakeLock");
1387 
1388         // receive broadcasts
1389         registerBroadcastReceiver();
1390 
1391         IntentFilter demoFilter = new IntentFilter();
1392         if (DEBUG_MEDIA_FAKE_ARTWORK) {
1393             demoFilter.addAction(ACTION_FAKE_ARTWORK);
1394         }
1395         mContext.registerReceiverAsUser(mDemoReceiver, UserHandle.ALL, demoFilter,
1396                 android.Manifest.permission.DUMP, null,
1397                 Context.RECEIVER_EXPORTED_UNAUDITED);
1398 
1399         // listen for USER_SETUP_COMPLETE setting (per-user)
1400         mDeviceProvisionedController.addCallback(mUserSetupObserver);
1401         mUserSetupObserver.onUserSetupChanged();
1402 
1403         // disable profiling bars, since they overlap and clutter the output on app windows
1404         ThreadedRenderer.overrideProperty("disableProfileBars", "true");
1405 
1406         // Private API call to make the shadows look better for Recents
1407         ThreadedRenderer.overrideProperty("ambientRatio", String.valueOf(1.5f));
1408     }
1409 
1410 
1411     /**
1412      * When swiping up to dismiss the lock screen, the panel expansion fraction goes from 1f to 0f.
1413      * This results in the clock/notifications/other content disappearing off the top of the screen.
1414      *
1415      * We also use the expansion fraction to animate in the app/launcher surface from the bottom of
1416      * the screen, 'pushing' off the notifications and other content. To do this, we dispatch the
1417      * expansion fraction to the KeyguardViewMediator if we're in the process of dismissing the
1418      * keyguard.
1419      */
dispatchPanelExpansionForKeyguardDismiss(float fraction, boolean trackingTouch)1420     private void dispatchPanelExpansionForKeyguardDismiss(float fraction, boolean trackingTouch) {
1421         // Things that mean we're not swiping to dismiss the keyguard, and should ignore this
1422         // expansion:
1423         // - Keyguard isn't even visible.
1424         // - We're swiping on the bouncer, not the lockscreen.
1425         // - Keyguard is occluded. Expansion changes here are the shade being expanded over the
1426         //   occluding activity.
1427         // - Keyguard is visible, but can't be dismissed (swiping up will show PIN/password prompt).
1428         // - The SIM is locked, you can't swipe to unlock. If the SIM is locked but there is no
1429         //   device lock set, canDismissLockScreen returns true even though you should not be able
1430         //   to dismiss the lock screen until entering the SIM PIN.
1431         // - QS is expanded and we're swiping - swiping up now will hide QS, not dismiss the
1432         //   keyguard.
1433         // - Shade is in QQS over keyguard - swiping up should take us back to keyguard
1434         if (!isKeyguardShowing()
1435                 || mStatusBarKeyguardViewManager.primaryBouncerIsOrWillBeShowing()
1436                 || isOccluded()
1437                 || !mKeyguardStateController.canDismissLockScreen()
1438                 || mKeyguardViewMediator.isAnySimPinSecure()
1439                 || (mQsController.getExpanded() && trackingTouch)
1440                 || mNotificationPanelViewController.getBarState() == StatusBarState.SHADE_LOCKED) {
1441             return;
1442         }
1443 
1444         // Otherwise, we should let the keyguard know about this if we're tracking touch, or if we
1445         // are already animating the keyguard dismiss (since we will need to either finish or cancel
1446         // the animation).
1447         if (trackingTouch
1448                 || mKeyguardViewMediator.isAnimatingBetweenKeyguardAndSurfaceBehindOrWillBe()
1449                 || mKeyguardUnlockAnimationController.isUnlockingWithSmartSpaceTransition()) {
1450             mKeyguardStateController.notifyKeyguardDismissAmountChanged(
1451                     1f - fraction, trackingTouch);
1452         }
1453     }
1454 
onPanelExpansionChanged(ShadeExpansionChangeEvent event)1455     private void onPanelExpansionChanged(ShadeExpansionChangeEvent event) {
1456         float fraction = event.getFraction();
1457         boolean tracking = event.getTracking();
1458         dispatchPanelExpansionForKeyguardDismiss(fraction, tracking);
1459 
1460         if (getNotificationPanelViewController() != null) {
1461             getNotificationPanelViewController().updateSystemUiStateFlags();
1462         }
1463 
1464         if (fraction == 0 || fraction == 1) {
1465             if (getNavigationBarView() != null) {
1466                 getNavigationBarView().onStatusBarPanelStateChanged();
1467             }
1468         }
1469     }
1470 
1471     @VisibleForTesting
onShadeExpansionFullyChanged(Boolean isExpanded)1472     void onShadeExpansionFullyChanged(Boolean isExpanded) {
1473         if (mPanelExpanded != isExpanded) {
1474             mPanelExpanded = isExpanded;
1475             if (isExpanded && mStatusBarStateController.getState() != StatusBarState.KEYGUARD) {
1476                 if (DEBUG) {
1477                     Log.v(TAG, "clearing notification effects from Height");
1478                 }
1479                 clearNotificationEffects();
1480             }
1481 
1482             if (!isExpanded) {
1483                 mRemoteInputManager.onPanelCollapsed();
1484             }
1485         }
1486     }
1487 
1488     @NonNull
1489     @Override
getLifecycle()1490     public Lifecycle getLifecycle() {
1491         return mLifecycle;
1492     }
1493 
1494     @VisibleForTesting
registerBroadcastReceiver()1495     protected void registerBroadcastReceiver() {
1496         IntentFilter filter = new IntentFilter();
1497         filter.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
1498         filter.addAction(Intent.ACTION_SCREEN_OFF);
1499         mBroadcastDispatcher.registerReceiver(mBroadcastReceiver, filter, null, UserHandle.ALL);
1500     }
1501 
createDefaultQSFragment()1502     protected QS createDefaultQSFragment() {
1503         return mFragmentService
1504                 .getFragmentHostManager(mNotificationShadeWindowView)
1505                 .create(QSFragment.class);
1506     }
1507 
setUpPresenter()1508     private void setUpPresenter() {
1509         // Set up the initial notification state.
1510         mActivityLaunchAnimator.setCallback(mActivityLaunchAnimatorCallback);
1511         mActivityLaunchAnimator.addListener(mActivityLaunchAnimatorListener);
1512         mNotificationAnimationProvider = new NotificationLaunchAnimatorControllerProvider(
1513                 mNotificationShadeWindowViewController,
1514                 mNotifListContainer,
1515                 mHeadsUpManager,
1516                 mJankMonitor);
1517         mNotificationShelfController.setOnActivatedListener(mPresenter);
1518         mRemoteInputManager.addControllerCallback(mNotificationShadeWindowController);
1519         mStackScrollerController.setNotificationActivityStarter(mNotificationActivityStarter);
1520         mGutsManager.setNotificationActivityStarter(mNotificationActivityStarter);
1521         mShadeController.setNotificationPresenter(mPresenter);
1522         mNotificationsController.initialize(
1523                 this,
1524                 mPresenter,
1525                 mNotifListContainer,
1526                 mStackScrollerController.getNotifStackController(),
1527                 mNotificationActivityStarter,
1528                 mCentralSurfacesComponent.getBindRowCallback());
1529     }
1530 
1531     /**
1532      * Post-init task of {@link #start()}
1533      * @param state1 disable1 flags
1534      * @param state2 disable2 flags
1535      */
setUpDisableFlags(int state1, int state2)1536     protected void setUpDisableFlags(int state1, int state2) {
1537         mCommandQueue.disable(mDisplayId, state1, state2, false /* animate */);
1538     }
1539 
1540     /**
1541      * Ask the display to wake up if currently dozing, else do nothing
1542      *
1543      * @param time when to wake up
1544      * @param where the view requesting the wakeup
1545      * @param why the reason for the wake up
1546      */
1547     @Override
wakeUpIfDozing(long time, View where, String why, @PowerManager.WakeReason int wakeReason)1548     public void wakeUpIfDozing(long time, View where, String why,
1549             @PowerManager.WakeReason int wakeReason) {
1550         if (mDozing && mScreenOffAnimationController.allowWakeUpIfDozing()) {
1551             mPowerManager.wakeUp(
1552                     time, wakeReason, "com.android.systemui:" + why);
1553             mWakeUpComingFromTouch = true;
1554             mFalsingCollector.onScreenOnFromTouch();
1555         }
1556     }
1557 
1558     // TODO(b/117478341): This was left such that CarStatusBar can override this method.
1559     // Try to remove this.
createNavigationBar(@ullable RegisterStatusBarResult result)1560     protected void createNavigationBar(@Nullable RegisterStatusBarResult result) {
1561         mNavigationBarController.createNavigationBars(true /* includeDefaultDisplay */, result);
1562     }
1563 
1564     /**
1565      * Returns the {@link android.view.View.OnTouchListener} that will be invoked when the
1566      * background window of the status bar is clicked.
1567      */
getStatusBarWindowTouchListener()1568     protected View.OnTouchListener getStatusBarWindowTouchListener() {
1569         return (v, event) -> {
1570             mAutoHideController.checkUserAutoHide(event);
1571             mRemoteInputManager.checkRemoteInputOutside(event);
1572             mShadeController.onStatusBarTouch(event);
1573             return mNotificationShadeWindowView.onTouchEvent(event);
1574         };
1575     }
1576 
inflateStatusBarWindow()1577     private void inflateStatusBarWindow() {
1578         if (mCentralSurfacesComponent != null) {
1579             // Tear down
1580             for (CentralSurfacesComponent.Startable s : mCentralSurfacesComponent.getStartables()) {
1581                 s.stop();
1582             }
1583         }
1584         mCentralSurfacesComponent = mCentralSurfacesComponentFactory.create();
1585         mFragmentService.addFragmentInstantiationProvider(mCentralSurfacesComponent);
1586 
1587         mNotificationShadeWindowView = mCentralSurfacesComponent.getNotificationShadeWindowView();
1588         mNotificationShadeWindowViewController = mCentralSurfacesComponent
1589                 .getNotificationShadeWindowViewController();
1590         mNotificationShadeWindowController.setNotificationShadeView(mNotificationShadeWindowView);
1591         mNotificationShadeWindowViewController.setupExpandedStatusBar();
1592         mNotificationPanelViewController =
1593                 mCentralSurfacesComponent.getNotificationPanelViewController();
1594         mShadeController.setNotificationPanelViewController(mNotificationPanelViewController);
1595         mShadeController.setNotificationShadeWindowViewController(
1596                 mNotificationShadeWindowViewController);
1597         mCentralSurfacesComponent.getLockIconViewController().init();
1598         mStackScrollerController =
1599                 mCentralSurfacesComponent.getNotificationStackScrollLayoutController();
1600         mQsController = mCentralSurfacesComponent.getQuickSettingsController();
1601         mStackScroller = mStackScrollerController.getView();
1602         mNotifListContainer = mCentralSurfacesComponent.getNotificationListContainer();
1603         mPresenter = mCentralSurfacesComponent.getNotificationPresenter();
1604         mNotificationActivityStarter = mCentralSurfacesComponent.getNotificationActivityStarter();
1605         mNotificationShelfController = mCentralSurfacesComponent.getNotificationShelfController();
1606         mAuthRippleController = mCentralSurfacesComponent.getAuthRippleController();
1607         mAuthRippleController.init();
1608 
1609         mHeadsUpManager.addListener(mCentralSurfacesComponent.getStatusBarHeadsUpChangeListener());
1610 
1611         // Listen for demo mode changes
1612         mDemoModeController.addCallback(mDemoModeCallback);
1613 
1614         if (mCommandQueueCallbacks != null) {
1615             mCommandQueue.removeCallback(mCommandQueueCallbacks);
1616         }
1617         mCommandQueueCallbacks =
1618                 mCentralSurfacesComponent.getCentralSurfacesCommandQueueCallbacks();
1619         // Connect in to the status bar manager service
1620         mCommandQueue.addCallback(mCommandQueueCallbacks);
1621 
1622         // Perform all other initialization for CentralSurfacesScope
1623         for (CentralSurfacesComponent.Startable s : mCentralSurfacesComponent.getStartables()) {
1624             s.start();
1625         }
1626     }
1627 
startKeyguard()1628     protected void startKeyguard() {
1629         Trace.beginSection("CentralSurfaces#startKeyguard");
1630         mStatusBarStateController.addCallback(mStateListener,
1631                 SysuiStatusBarStateController.RANK_STATUS_BAR);
1632         mBiometricUnlockController = mBiometricUnlockControllerLazy.get();
1633         mBiometricUnlockController.addBiometricModeListener(
1634                 new BiometricUnlockController.BiometricModeListener() {
1635                     @Override
1636                     public void onResetMode() {
1637                         setWakeAndUnlocking(false);
1638                         notifyBiometricAuthModeChanged();
1639                     }
1640 
1641                     @Override
1642                     public void onModeChanged(int mode) {
1643                         switch (mode) {
1644                             case BiometricUnlockController.MODE_WAKE_AND_UNLOCK_FROM_DREAM:
1645                             case BiometricUnlockController.MODE_WAKE_AND_UNLOCK_PULSING:
1646                             case BiometricUnlockController.MODE_WAKE_AND_UNLOCK:
1647                                 setWakeAndUnlocking(true);
1648                         }
1649                         notifyBiometricAuthModeChanged();
1650                     }
1651 
1652                     private void setWakeAndUnlocking(boolean wakeAndUnlocking) {
1653                         if (getNavigationBarView() != null) {
1654                             getNavigationBarView().setWakeAndUnlocking(wakeAndUnlocking);
1655                         }
1656                     }
1657                 });
1658         mKeyguardViewMediator.registerCentralSurfaces(
1659                 /* statusBar= */ this,
1660                 mNotificationPanelViewController,
1661                 mShadeExpansionStateManager,
1662                 mBiometricUnlockController,
1663                 mStackScroller,
1664                 mKeyguardBypassController);
1665         mKeyguardStateController.addCallback(mKeyguardStateControllerCallback);
1666         mKeyguardIndicationController
1667                 .setStatusBarKeyguardViewManager(mStatusBarKeyguardViewManager);
1668         mBiometricUnlockController.setKeyguardViewController(mStatusBarKeyguardViewManager);
1669         mRemoteInputManager.addControllerCallback(mStatusBarKeyguardViewManager);
1670 
1671         mLightBarController.setBiometricUnlockController(mBiometricUnlockController);
1672         mMediaManager.setBiometricUnlockController(mBiometricUnlockController);
1673         mKeyguardDismissUtil.setDismissHandler(this::executeWhenUnlocked);
1674         Trace.endSection();
1675     }
1676 
1677     @Override
getNotificationShadeWindowView()1678     public NotificationShadeWindowView getNotificationShadeWindowView() {
1679         return mNotificationShadeWindowView;
1680     }
1681 
1682     @Override
getNotificationShadeWindowViewController()1683     public NotificationShadeWindowViewController getNotificationShadeWindowViewController() {
1684         return mNotificationShadeWindowViewController;
1685     }
1686 
1687     @Override
getNotificationPanelViewController()1688     public NotificationPanelViewController getNotificationPanelViewController() {
1689         return mNotificationPanelViewController;
1690     }
1691 
1692     @Override
getBouncerContainer()1693     public ViewGroup getBouncerContainer() {
1694         return mNotificationShadeWindowViewController.getBouncerContainer();
1695     }
1696 
1697     @Override
getKeyguardMessageArea()1698     public AuthKeyguardMessageArea getKeyguardMessageArea() {
1699         return mNotificationShadeWindowViewController.getKeyguardMessageArea();
1700     }
1701 
1702     @Override
getStatusBarHeight()1703     public int getStatusBarHeight() {
1704         return mStatusBarWindowController.getStatusBarHeight();
1705     }
1706 
1707     /**
1708      * Disable QS if device not provisioned.
1709      * If the user switcher is simple then disable QS during setup because
1710      * the user intends to use the lock screen user switcher, QS in not needed.
1711      */
1712     @Override
updateQsExpansionEnabled()1713     public void updateQsExpansionEnabled() {
1714         final boolean expandEnabled = mDeviceProvisionedController.isDeviceProvisioned()
1715                 && (mUserSetup || mUserSwitcherController == null
1716                         || !mUserSwitcherController.isSimpleUserSwitcher())
1717                 && !isShadeDisabled()
1718                 && ((mDisabled2 & StatusBarManager.DISABLE2_QUICK_SETTINGS) == 0)
1719                 && !mDozing;
1720         mQsController.setExpansionEnabledPolicy(expandEnabled);
1721         Log.d(TAG, "updateQsExpansionEnabled - QS Expand enabled: " + expandEnabled);
1722     }
1723 
1724     @Override
isShadeDisabled()1725     public boolean isShadeDisabled() {
1726         return (mDisabled2 & StatusBarManager.DISABLE2_NOTIFICATION_SHADE) != 0;
1727     }
1728 
updateReportRejectedTouchVisibility()1729     private void updateReportRejectedTouchVisibility() {
1730         if (mReportRejectedTouch == null) {
1731             return;
1732         }
1733         mReportRejectedTouch.setVisibility(mState == StatusBarState.KEYGUARD && !mDozing
1734                 && mFalsingCollector.isReportingEnabled() ? View.VISIBLE : View.INVISIBLE);
1735     }
1736 
1737     @Override
areNotificationAlertsDisabled()1738     public boolean areNotificationAlertsDisabled() {
1739         return (mDisabled1 & StatusBarManager.DISABLE_NOTIFICATION_ALERTS) != 0;
1740     }
1741 
1742     @Override
startActivity(Intent intent, boolean onlyProvisioned, boolean dismissShade, int flags)1743     public void startActivity(Intent intent, boolean onlyProvisioned, boolean dismissShade,
1744             int flags) {
1745         startActivityDismissingKeyguard(intent, onlyProvisioned, dismissShade, flags);
1746     }
1747 
1748     @Override
startActivity(Intent intent, boolean dismissShade)1749     public void startActivity(Intent intent, boolean dismissShade) {
1750         startActivityDismissingKeyguard(intent, false /* onlyProvisioned */, dismissShade);
1751     }
1752 
1753     @Override
startActivity(Intent intent, boolean dismissShade, @Nullable ActivityLaunchAnimator.Controller animationController, boolean showOverLockscreenWhenLocked)1754     public void startActivity(Intent intent, boolean dismissShade,
1755             @Nullable ActivityLaunchAnimator.Controller animationController,
1756             boolean showOverLockscreenWhenLocked) {
1757         startActivity(intent, dismissShade, animationController, showOverLockscreenWhenLocked,
1758                 getActivityUserHandle(intent));
1759     }
1760 
1761     @Override
startActivity(Intent intent, boolean dismissShade, @Nullable ActivityLaunchAnimator.Controller animationController, boolean showOverLockscreenWhenLocked, UserHandle userHandle)1762     public void startActivity(Intent intent, boolean dismissShade,
1763             @Nullable ActivityLaunchAnimator.Controller animationController,
1764             boolean showOverLockscreenWhenLocked, UserHandle userHandle) {
1765         // Make sure that we dismiss the keyguard if it is directly dismissable or when we don't
1766         // want to show the activity above it.
1767         if (mKeyguardStateController.isUnlocked() || !showOverLockscreenWhenLocked) {
1768             startActivityDismissingKeyguard(intent, false, dismissShade,
1769                     false /* disallowEnterPictureInPictureWhileLaunching */, null /* callback */,
1770                     0 /* flags */, animationController, userHandle);
1771             return;
1772         }
1773 
1774         boolean animate =
1775                 animationController != null && shouldAnimateLaunch(true /* isActivityIntent */,
1776                         showOverLockscreenWhenLocked);
1777 
1778         ActivityLaunchAnimator.Controller controller = null;
1779         if (animate) {
1780             // Wrap the animation controller to dismiss the shade and set
1781             // mIsLaunchingActivityOverLockscreen during the animation.
1782             ActivityLaunchAnimator.Controller delegate = wrapAnimationController(
1783                     animationController, dismissShade, /* isLaunchForActivity= */ true);
1784             controller = new DelegateLaunchAnimatorController(delegate) {
1785                 @Override
1786                 public void onIntentStarted(boolean willAnimate) {
1787                     getDelegate().onIntentStarted(willAnimate);
1788 
1789                     if (willAnimate) {
1790                         CentralSurfacesImpl.this.mIsLaunchingActivityOverLockscreen = true;
1791                     }
1792                 }
1793 
1794                 @Override
1795                 public void onLaunchAnimationStart(boolean isExpandingFullyAbove) {
1796                     super.onLaunchAnimationStart(isExpandingFullyAbove);
1797 
1798                     // Double check that the keyguard is still showing and not going away, but if so
1799                     // set the keyguard occluded. Typically, WM will let KeyguardViewMediator know
1800                     // directly, but we're overriding that to play the custom launch animation, so
1801                     // we need to take care of that here. The unocclude animation is not overridden,
1802                     // so WM will call KeyguardViewMediator's unocclude animation runner when the
1803                     // activity is exited.
1804                     if (mKeyguardStateController.isShowing()
1805                             && !mKeyguardStateController.isKeyguardGoingAway()) {
1806                         Log.d(TAG, "Setting occluded = true in #startActivity.");
1807                         mKeyguardViewMediator.setOccluded(true /* isOccluded */,
1808                                 true /* animate */);
1809                     }
1810                 }
1811 
1812                 @Override
1813                 public void onLaunchAnimationEnd(boolean isExpandingFullyAbove) {
1814                     // Set mIsLaunchingActivityOverLockscreen to false before actually finishing the
1815                     // animation so that we can assume that mIsLaunchingActivityOverLockscreen
1816                     // being true means that we will collapse the shade (or at least run the
1817                     // post collapse runnables) later on.
1818                     CentralSurfacesImpl.this.mIsLaunchingActivityOverLockscreen = false;
1819                     getDelegate().onLaunchAnimationEnd(isExpandingFullyAbove);
1820                 }
1821 
1822                 @Override
1823                 public void onLaunchAnimationCancelled(@Nullable Boolean newKeyguardOccludedState) {
1824                     if (newKeyguardOccludedState != null) {
1825                         mKeyguardViewMediator.setOccluded(
1826                                 newKeyguardOccludedState, false /* animate */);
1827                     }
1828 
1829                     // Set mIsLaunchingActivityOverLockscreen to false before actually finishing the
1830                     // animation so that we can assume that mIsLaunchingActivityOverLockscreen
1831                     // being true means that we will collapse the shade (or at least run the
1832                     // post collapse runnables) later on.
1833                     CentralSurfacesImpl.this.mIsLaunchingActivityOverLockscreen = false;
1834                     getDelegate().onLaunchAnimationCancelled(newKeyguardOccludedState);
1835                 }
1836             };
1837         } else if (dismissShade) {
1838             // The animation will take care of dismissing the shade at the end of the animation. If
1839             // we don't animate, collapse it directly.
1840             collapseShade();
1841         }
1842 
1843         // We should exit the dream to prevent the activity from starting below the
1844         // dream.
1845         if (mKeyguardUpdateMonitor.isDreaming()) {
1846             awakenDreams();
1847         }
1848 
1849         mActivityLaunchAnimator.startIntentWithAnimation(controller, animate,
1850                 intent.getPackage(), showOverLockscreenWhenLocked, (adapter) -> TaskStackBuilder
1851                         .create(mContext)
1852                         .addNextIntent(intent)
1853                         .startActivities(
1854                                 CentralSurfaces.getActivityOptions(getDisplayId(), adapter),
1855                                 userHandle));
1856     }
1857 
1858     /**
1859      * Whether we are currently animating an activity launch above the lockscreen (occluding
1860      * activity).
1861      */
1862     @Override
isLaunchingActivityOverLockscreen()1863     public boolean isLaunchingActivityOverLockscreen() {
1864         return mIsLaunchingActivityOverLockscreen;
1865     }
1866 
1867     @Override
startActivity(Intent intent, boolean onlyProvisioned, boolean dismissShade)1868     public void startActivity(Intent intent, boolean onlyProvisioned, boolean dismissShade) {
1869         startActivityDismissingKeyguard(intent, onlyProvisioned, dismissShade);
1870     }
1871 
1872     @Override
startActivity(Intent intent, boolean dismissShade, Callback callback)1873     public void startActivity(Intent intent, boolean dismissShade, Callback callback) {
1874         startActivityDismissingKeyguard(intent, false, dismissShade,
1875                 false /* disallowEnterPictureInPictureWhileLaunching */, callback, 0,
1876                 null /* animationController */, getActivityUserHandle(intent));
1877     }
1878 
1879     @Override
isWakeUpComingFromTouch()1880     public boolean isWakeUpComingFromTouch() {
1881         return mWakeUpComingFromTouch;
1882     }
1883 
1884     /**
1885      * To be called when there's a state change in StatusBarKeyguardViewManager.
1886      */
1887     @Override
onKeyguardViewManagerStatesUpdated()1888     public void onKeyguardViewManagerStatesUpdated() {
1889         logStateToEventlog();
1890     }
1891 
1892     @Override
getNotificationScrollLayout()1893     public ViewGroup getNotificationScrollLayout() {
1894         return mStackScroller;
1895     }
1896 
1897     @Override
isPulsing()1898     public boolean isPulsing() {
1899         return mDozeServiceHost.isPulsing();
1900     }
1901 
1902     /**
1903      * When the keyguard is showing and covered by a "showWhenLocked" activity it
1904      * is occluded. This is controlled by {@link com.android.server.policy.PhoneWindowManager}
1905      *
1906      * @return whether the keyguard is currently occluded
1907      */
1908     @Override
isOccluded()1909     public boolean isOccluded() {
1910         return mKeyguardStateController.isOccluded();
1911     }
1912 
1913     /** A launch animation was cancelled. */
1914     //TODO: These can / should probably be moved to NotificationPresenter or ShadeController
1915     @Override
onLaunchAnimationCancelled(boolean isLaunchForActivity)1916     public void onLaunchAnimationCancelled(boolean isLaunchForActivity) {
1917         if (mPresenter.isPresenterFullyCollapsed() && !mPresenter.isCollapsing()
1918                 && isLaunchForActivity) {
1919             mShadeController.onClosingFinished();
1920         } else {
1921             mShadeController.collapseShade(true /* animate */);
1922         }
1923     }
1924 
1925     /** A launch animation ended. */
1926     @Override
onLaunchAnimationEnd(boolean launchIsFullScreen)1927     public void onLaunchAnimationEnd(boolean launchIsFullScreen) {
1928         if (!mPresenter.isCollapsing()) {
1929             mShadeController.onClosingFinished();
1930         }
1931         if (launchIsFullScreen) {
1932             mShadeController.instantCollapseShade();
1933         }
1934     }
1935 
1936     /**
1937      * Whether we should animate an activity launch.
1938      *
1939      * Note: This method must be called *before* dismissing the keyguard.
1940      */
1941     @Override
shouldAnimateLaunch(boolean isActivityIntent, boolean showOverLockscreen)1942     public boolean shouldAnimateLaunch(boolean isActivityIntent, boolean showOverLockscreen) {
1943         // TODO(b/184121838): Support launch animations when occluded.
1944         if (isOccluded()) {
1945             return false;
1946         }
1947 
1948         // Always animate if we are not showing the keyguard or if we animate over the lockscreen
1949         // (without unlocking it).
1950         if (showOverLockscreen || !mKeyguardStateController.isShowing()) {
1951             return true;
1952         }
1953 
1954         // If we are locked and have to dismiss the keyguard, only animate if remote unlock
1955         // animations are enabled. We also don't animate non-activity launches as they can break the
1956         // animation.
1957         // TODO(b/184121838): Support non activity launches on the lockscreen.
1958         return isActivityIntent && KeyguardService.sEnableRemoteKeyguardGoingAwayAnimation;
1959     }
1960 
1961     /** Whether we should animate an activity launch. */
1962     @Override
shouldAnimateLaunch(boolean isActivityIntent)1963     public boolean shouldAnimateLaunch(boolean isActivityIntent) {
1964         return shouldAnimateLaunch(isActivityIntent, false /* showOverLockscreen */);
1965     }
1966 
1967     @Override
isDeviceInVrMode()1968     public boolean isDeviceInVrMode() {
1969         return mPresenter.isDeviceInVrMode();
1970     }
1971 
1972     @Override
getPresenter()1973     public NotificationPresenter getPresenter() {
1974         return mPresenter;
1975     }
1976 
1977     @VisibleForTesting
1978     @Override
setBarStateForTest(int state)1979     public void setBarStateForTest(int state) {
1980         mState = state;
1981     }
1982 
1983     static class AnimateExpandSettingsPanelMessage {
1984         final String mSubpanel;
1985 
AnimateExpandSettingsPanelMessage(String subpanel)1986         AnimateExpandSettingsPanelMessage(String subpanel) {
1987             mSubpanel = subpanel;
1988         }
1989     }
1990 
maybeEscalateHeadsUp()1991     private void maybeEscalateHeadsUp() {
1992         mHeadsUpManager.getAllEntries().forEach(entry -> {
1993             final StatusBarNotification sbn = entry.getSbn();
1994             final Notification notification = sbn.getNotification();
1995             if (notification.fullScreenIntent != null) {
1996                 if (DEBUG) {
1997                     Log.d(TAG, "converting a heads up to fullScreen");
1998                 }
1999                 try {
2000                     EventLog.writeEvent(EventLogTags.SYSUI_HEADS_UP_ESCALATION,
2001                             sbn.getKey());
2002                     wakeUpForFullScreenIntent();
2003                     notification.fullScreenIntent.send();
2004                     entry.notifyFullScreenIntentLaunched();
2005                 } catch (PendingIntent.CanceledException e) {
2006                 }
2007             }
2008         });
2009         mHeadsUpManager.releaseAllImmediately();
2010     }
2011 
2012     @Override
wakeUpForFullScreenIntent()2013     public void wakeUpForFullScreenIntent() {
2014         if (isGoingToSleep() || mDozing) {
2015             mPowerManager.wakeUp(
2016                     SystemClock.uptimeMillis(),
2017                     PowerManager.WAKE_REASON_APPLICATION,
2018                     "com.android.systemui:full_screen_intent");
2019             mWakeUpComingFromTouch = false;
2020         }
2021     }
2022 
2023     @Override
postAnimateCollapsePanels()2024     public void postAnimateCollapsePanels() {
2025         mMainExecutor.execute(mShadeController::animateCollapseShade);
2026     }
2027 
2028     @Override
postAnimateForceCollapsePanels()2029     public void postAnimateForceCollapsePanels() {
2030         mMainExecutor.execute(mShadeController::animateCollapseShadeForced);
2031     }
2032 
2033     @Override
postAnimateOpenPanels()2034     public void postAnimateOpenPanels() {
2035         mMessageRouter.sendMessage(MSG_OPEN_SETTINGS_PANEL);
2036     }
2037 
2038     @Override
isPanelExpanded()2039     public boolean isPanelExpanded() {
2040         return mPanelExpanded;
2041     }
2042 
2043     /**
2044      * Called when another window is about to transfer it's input focus.
2045      */
2046     @Override
onInputFocusTransfer(boolean start, boolean cancel, float velocity)2047     public void onInputFocusTransfer(boolean start, boolean cancel, float velocity) {
2048         if (!mCommandQueue.panelsEnabled()) {
2049             return;
2050         }
2051 
2052         if (start) {
2053             mNotificationPanelViewController.startWaitingForOpenPanelGesture();
2054         } else {
2055             mNotificationPanelViewController.stopWaitingForOpenPanelGesture(cancel, velocity);
2056         }
2057     }
2058 
2059     @Override
animateCollapseQuickSettings()2060     public void animateCollapseQuickSettings() {
2061         if (mState == StatusBarState.SHADE) {
2062             mNotificationPanelViewController.collapsePanel(
2063                     true, false /* delayed */, 1.0f /* speedUpFactor */);
2064         }
2065     }
2066 
onExpandedInvisible()2067     private void onExpandedInvisible() {
2068         setInteracting(StatusBarManager.WINDOW_STATUS_BAR, false);
2069         if (!mNotificationActivityStarter.isCollapsingToShowActivityOverLockscreen()) {
2070             showBouncerOrLockScreenIfKeyguard();
2071         } else if (DEBUG) {
2072             Log.d(TAG, "Not showing bouncer due to activity showing over lockscreen");
2073         }
2074     }
2075 
2076     @Override
getCommandQueuePanelsEnabled()2077     public boolean getCommandQueuePanelsEnabled() {
2078         return mCommandQueue.panelsEnabled();
2079     }
2080 
2081     @Override
getStatusBarWindowState()2082     public int getStatusBarWindowState() {
2083         return mStatusBarWindowState;
2084     }
2085 
2086     @Override
getBiometricUnlockController()2087     public BiometricUnlockController getBiometricUnlockController() {
2088         return mBiometricUnlockController;
2089     }
2090 
2091     @Override
showTransientUnchecked()2092     public void showTransientUnchecked() {
2093         if (!mTransientShown) {
2094             mTransientShown = true;
2095             mNoAnimationOnNextBarModeChange = true;
2096             maybeUpdateBarMode();
2097         }
2098     }
2099 
2100     @Override
clearTransient()2101     public void clearTransient() {
2102         if (mTransientShown) {
2103             mTransientShown = false;
2104             maybeUpdateBarMode();
2105         }
2106     }
2107 
maybeUpdateBarMode()2108     private void maybeUpdateBarMode() {
2109         final int barMode = barMode(mTransientShown, mAppearance);
2110         if (updateBarMode(barMode)) {
2111             mLightBarController.onStatusBarModeChanged(barMode);
2112             updateBubblesVisibility();
2113         }
2114     }
2115 
updateBarMode(int barMode)2116     private boolean updateBarMode(int barMode) {
2117         if (mStatusBarMode != barMode) {
2118             mStatusBarMode = barMode;
2119             checkBarModes();
2120             mAutoHideController.touchAutoHide();
2121             return true;
2122         }
2123         return false;
2124     }
2125 
barMode(boolean isTransient, int appearance)2126     private @TransitionMode int barMode(boolean isTransient, int appearance) {
2127         final int lightsOutOpaque = APPEARANCE_LOW_PROFILE_BARS | APPEARANCE_OPAQUE_STATUS_BARS;
2128         if (mOngoingCallController.hasOngoingCall() && mIsFullscreen) {
2129             return MODE_SEMI_TRANSPARENT;
2130         } else if (isTransient) {
2131             return MODE_SEMI_TRANSPARENT;
2132         } else if ((appearance & lightsOutOpaque) == lightsOutOpaque) {
2133             return MODE_LIGHTS_OUT;
2134         } else if ((appearance & APPEARANCE_LOW_PROFILE_BARS) != 0) {
2135             return MODE_LIGHTS_OUT_TRANSPARENT;
2136         } else if ((appearance & APPEARANCE_OPAQUE_STATUS_BARS) != 0) {
2137             return MODE_OPAQUE;
2138         } else if ((appearance & APPEARANCE_SEMI_TRANSPARENT_STATUS_BARS) != 0) {
2139             return MODE_SEMI_TRANSPARENT;
2140         } else {
2141             return MODE_TRANSPARENT;
2142         }
2143     }
2144 
2145     @Override
showWirelessChargingAnimation(int batteryLevel)2146     public void showWirelessChargingAnimation(int batteryLevel) {
2147         showChargingAnimation(batteryLevel, UNKNOWN_BATTERY_LEVEL, 0);
2148     }
2149 
showChargingAnimation(int batteryLevel, int transmittingBatteryLevel, long animationDelay)2150     protected void showChargingAnimation(int batteryLevel, int transmittingBatteryLevel,
2151             long animationDelay) {
2152         WirelessChargingAnimation.makeWirelessChargingAnimation(mContext, null,
2153                 transmittingBatteryLevel, batteryLevel,
2154                 new WirelessChargingAnimation.Callback() {
2155                     @Override
2156                     public void onAnimationStarting() {
2157                         mNotificationShadeWindowController.setRequestTopUi(true, TAG);
2158                     }
2159 
2160                     @Override
2161                     public void onAnimationEnded() {
2162                         mNotificationShadeWindowController.setRequestTopUi(false, TAG);
2163                     }
2164                 }, /* isDozing= */ false, RippleShape.CIRCLE,
2165                 sUiEventLogger).show(animationDelay);
2166     }
2167 
2168     @Override
checkBarModes()2169     public void checkBarModes() {
2170         if (mDemoModeController.isInDemoMode()) return;
2171         if (mStatusBarTransitions != null) {
2172             checkBarMode(mStatusBarMode, mStatusBarWindowState, mStatusBarTransitions);
2173         }
2174         mNavigationBarController.checkNavBarModes(mDisplayId);
2175         mNoAnimationOnNextBarModeChange = false;
2176     }
2177 
2178     /** Temporarily hides Bubbles if the status bar is hidden. */
2179     @Override
updateBubblesVisibility()2180     public void updateBubblesVisibility() {
2181         mBubblesOptional.ifPresent(bubbles -> bubbles.onStatusBarVisibilityChanged(
2182                 mStatusBarMode != MODE_LIGHTS_OUT
2183                         && mStatusBarMode != MODE_LIGHTS_OUT_TRANSPARENT));
2184     }
2185 
checkBarMode(@ransitionMode int mode, @WindowVisibleState int windowState, BarTransitions transitions)2186     void checkBarMode(@TransitionMode int mode, @WindowVisibleState int windowState,
2187             BarTransitions transitions) {
2188         final boolean anim = !mNoAnimationOnNextBarModeChange && mDeviceInteractive
2189                 && windowState != WINDOW_STATE_HIDDEN;
2190         transitions.transitionTo(mode, anim);
2191     }
2192 
finishBarAnimations()2193     private void finishBarAnimations() {
2194         if (mStatusBarTransitions != null) {
2195             mStatusBarTransitions.finishAnimations();
2196         }
2197         mNavigationBarController.finishBarAnimations(mDisplayId);
2198     }
2199 
2200     private final Runnable mCheckBarModes = this::checkBarModes;
2201 
2202     @Override
setInteracting(int barWindow, boolean interacting)2203     public void setInteracting(int barWindow, boolean interacting) {
2204         mInteractingWindows = interacting
2205                 ? (mInteractingWindows | barWindow)
2206                 : (mInteractingWindows & ~barWindow);
2207         if (mInteractingWindows != 0) {
2208             mAutoHideController.suspendAutoHide();
2209         } else {
2210             mAutoHideController.resumeSuspendedAutoHide();
2211         }
2212         checkBarModes();
2213     }
2214 
dismissVolumeDialog()2215     private void dismissVolumeDialog() {
2216         if (mVolumeComponent != null) {
2217             mVolumeComponent.dismissNow();
2218         }
2219     }
2220 
2221     @Override
dump(PrintWriter pwOriginal, String[] args)2222     public void dump(PrintWriter pwOriginal, String[] args) {
2223         IndentingPrintWriter pw = DumpUtilsKt.asIndenting(pwOriginal);
2224         synchronized (mQueueLock) {
2225             pw.println("Current Status Bar state:");
2226             pw.println("  mExpandedVisible=" + mShadeController.isExpandedVisible());
2227             pw.println("  mDisplayMetrics=" + mDisplayMetrics);
2228             pw.print("  mStackScroller: " + CentralSurfaces.viewInfo(mStackScroller));
2229             pw.print(" scroll " + mStackScroller.getScrollX()
2230                     + "," + mStackScroller.getScrollY());
2231             pw.println(" translationX " + mStackScroller.getTranslationX());
2232         }
2233 
2234         pw.print("  mInteractingWindows="); pw.println(mInteractingWindows);
2235         pw.print("  mStatusBarWindowState=");
2236         pw.println(windowStateToString(mStatusBarWindowState));
2237         pw.print("  mStatusBarMode=");
2238         pw.println(BarTransitions.modeToString(mStatusBarMode));
2239         pw.print("  mDozing="); pw.println(mDozing);
2240         pw.print("  mWallpaperSupported= "); pw.println(mWallpaperSupported);
2241 
2242         pw.println("  ShadeWindowView: ");
2243         if (mNotificationShadeWindowViewController != null) {
2244             mNotificationShadeWindowViewController.dump(pw, args);
2245             CentralSurfaces.dumpBarTransitions(
2246                     pw, "PhoneStatusBarTransitions", mStatusBarTransitions);
2247         }
2248 
2249         pw.println("  mMediaManager: ");
2250         if (mMediaManager != null) {
2251             mMediaManager.dump(pw, args);
2252         }
2253 
2254         pw.println("  Panels: ");
2255         pw.println("  mStackScroller: " + mStackScroller + " (dump moved)");
2256         pw.println("  Theme:");
2257         String nightMode = mUiModeManager == null ? "null" : mUiModeManager.getNightMode() + "";
2258         pw.println("    dark theme: " + nightMode +
2259                 " (auto: " + UiModeManager.MODE_NIGHT_AUTO +
2260                 ", yes: " + UiModeManager.MODE_NIGHT_YES +
2261                 ", no: " + UiModeManager.MODE_NIGHT_NO + ")");
2262         final boolean lightWpTheme = mContext.getThemeResId()
2263                 == R.style.Theme_SystemUI_LightWallpaper;
2264         pw.println("    light wallpaper theme: " + lightWpTheme);
2265 
2266         if (mKeyguardIndicationController != null) {
2267             mKeyguardIndicationController.dump(pw, args);
2268         }
2269 
2270         if (mScrimController != null) {
2271             mScrimController.dump(pw, args);
2272         }
2273 
2274         if (mLightRevealScrim != null) {
2275             pw.println(
2276                     "mLightRevealScrim.getRevealEffect(): " + mLightRevealScrim.getRevealEffect());
2277             pw.println(
2278                     "mLightRevealScrim.getRevealAmount(): " + mLightRevealScrim.getRevealAmount());
2279         }
2280 
2281         if (mStatusBarKeyguardViewManager != null) {
2282             mStatusBarKeyguardViewManager.dump(pw);
2283         }
2284 
2285         if (DEBUG_GESTURES) {
2286             pw.print("  status bar gestures: ");
2287             mGestureRec.dump(pw, args);
2288         }
2289 
2290         if (mHeadsUpManager != null) {
2291             mHeadsUpManager.dump(pw, args);
2292         } else {
2293             pw.println("  mHeadsUpManager: null");
2294         }
2295 
2296         if (mStatusBarTouchableRegionManager != null) {
2297             mStatusBarTouchableRegionManager.dump(pw, args);
2298         } else {
2299             pw.println("  mStatusBarTouchableRegionManager: null");
2300         }
2301 
2302         if (mLightBarController != null) {
2303             mLightBarController.dump(pw, args);
2304         }
2305 
2306         pw.println("SharedPreferences:");
2307         for (Map.Entry<String, ?> entry : Prefs.getAll(mContext).entrySet()) {
2308             pw.print("  "); pw.print(entry.getKey()); pw.print("="); pw.println(entry.getValue());
2309         }
2310 
2311         pw.println("Camera gesture intents:");
2312         pw.println("   Insecure camera: " + CameraIntents.getInsecureCameraIntent(mContext));
2313         pw.println("   Secure camera: " + CameraIntents.getSecureCameraIntent(mContext));
2314         pw.println("   Override package: "
2315                 + CameraIntents.getOverrideCameraPackage(mContext));
2316     }
2317 
2318     @Override
createAndAddWindows(@ullable RegisterStatusBarResult result)2319     public void createAndAddWindows(@Nullable RegisterStatusBarResult result) {
2320         makeStatusBarView(result);
2321         mNotificationShadeWindowController.attach();
2322         mStatusBarWindowController.attach();
2323     }
2324 
2325     // called by makeStatusbar and also by PhoneStatusBarView
updateDisplaySize()2326     void updateDisplaySize() {
2327         mDisplay.getMetrics(mDisplayMetrics);
2328         mDisplay.getSize(mCurrentDisplaySize);
2329         mMediaManager.onDisplayUpdated(mDisplay);
2330         if (DEBUG_GESTURES) {
2331             mGestureRec.tag("display",
2332                     String.format("%dx%d", mDisplayMetrics.widthPixels, mDisplayMetrics.heightPixels));
2333         }
2334     }
2335 
2336     @Override
getDisplayDensity()2337     public float getDisplayDensity() {
2338         return mDisplayMetrics.density;
2339     }
2340 
2341     @Override
getDisplayWidth()2342     public float getDisplayWidth() {
2343         return mDisplayMetrics.widthPixels;
2344     }
2345 
2346     @Override
getDisplayHeight()2347     public float getDisplayHeight() {
2348         return mDisplayMetrics.heightPixels;
2349     }
2350 
2351     @Override
getRotation()2352     public int getRotation() {
2353         return mDisplay.getRotation();
2354     }
2355 
2356     @Override
getDisplayId()2357     public int getDisplayId() {
2358         return mDisplayId;
2359     }
2360 
2361     @Override
startActivityDismissingKeyguard(final Intent intent, boolean onlyProvisioned, boolean dismissShade, int flags)2362     public void startActivityDismissingKeyguard(final Intent intent, boolean onlyProvisioned,
2363             boolean dismissShade, int flags) {
2364         startActivityDismissingKeyguard(intent, onlyProvisioned, dismissShade,
2365                 false /* disallowEnterPictureInPictureWhileLaunching */, null /* callback */,
2366                 flags, null /* animationController */, getActivityUserHandle(intent));
2367     }
2368 
2369     @Override
startActivityDismissingKeyguard(final Intent intent, boolean onlyProvisioned, boolean dismissShade)2370     public void startActivityDismissingKeyguard(final Intent intent, boolean onlyProvisioned,
2371             boolean dismissShade) {
2372         startActivityDismissingKeyguard(intent, onlyProvisioned, dismissShade, 0);
2373     }
2374 
2375     @Override
startActivityDismissingKeyguard(final Intent intent, boolean onlyProvisioned, final boolean dismissShade, final boolean disallowEnterPictureInPictureWhileLaunching, final Callback callback, int flags, @Nullable ActivityLaunchAnimator.Controller animationController, final UserHandle userHandle)2376     public void startActivityDismissingKeyguard(final Intent intent, boolean onlyProvisioned,
2377             final boolean dismissShade, final boolean disallowEnterPictureInPictureWhileLaunching,
2378             final Callback callback, int flags,
2379             @Nullable ActivityLaunchAnimator.Controller animationController,
2380             final UserHandle userHandle) {
2381         if (onlyProvisioned && !mDeviceProvisionedController.isDeviceProvisioned()) return;
2382 
2383         final boolean willLaunchResolverActivity =
2384                 mActivityIntentHelper.wouldLaunchResolverActivity(intent,
2385                         mLockscreenUserManager.getCurrentUserId());
2386 
2387         boolean animate =
2388                 animationController != null && !willLaunchResolverActivity && shouldAnimateLaunch(
2389                         true /* isActivityIntent */);
2390         ActivityLaunchAnimator.Controller animController =
2391                 animationController != null ? wrapAnimationController(animationController,
2392                         dismissShade, /* isLaunchForActivity= */ true) : null;
2393 
2394         // If we animate, we will dismiss the shade only once the animation is done. This is taken
2395         // care of by the StatusBarLaunchAnimationController.
2396         boolean dismissShadeDirectly = dismissShade && animController == null;
2397 
2398         Runnable runnable = () -> {
2399             mAssistManagerLazy.get().hideAssist();
2400             intent.setFlags(
2401                     Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
2402             intent.addFlags(flags);
2403             int[] result = new int[]{ActivityManager.START_CANCELED};
2404 
2405             mActivityLaunchAnimator.startIntentWithAnimation(animController,
2406                     animate, intent.getPackage(), (adapter) -> {
2407                         ActivityOptions options = new ActivityOptions(
2408                                 CentralSurfaces.getActivityOptions(mDisplayId, adapter));
2409 
2410                         // We know that the intent of the caller is to dismiss the keyguard and
2411                         // this runnable is called right after the keyguard is solved, so we tell
2412                         // WM that we should dismiss it to avoid flickers when opening an activity
2413                         // that can also be shown over the keyguard.
2414                         options.setDismissKeyguard();
2415                         options.setDisallowEnterPictureInPictureWhileLaunching(
2416                                 disallowEnterPictureInPictureWhileLaunching);
2417                         if (CameraIntents.isInsecureCameraIntent(intent)) {
2418                             // Normally an activity will set it's requested rotation
2419                             // animation on its window. However when launching an activity
2420                             // causes the orientation to change this is too late. In these cases
2421                             // the default animation is used. This doesn't look good for
2422                             // the camera (as it rotates the camera contents out of sync
2423                             // with physical reality). So, we ask the WindowManager to
2424                             // force the crossfade animation if an orientation change
2425                             // happens to occur during the launch.
2426                             options.setRotationAnimationHint(
2427                                     WindowManager.LayoutParams.ROTATION_ANIMATION_SEAMLESS);
2428                         }
2429                         if (Settings.Panel.ACTION_VOLUME.equals(intent.getAction())) {
2430                             // Settings Panel is implemented as activity(not a dialog), so
2431                             // underlying app is paused and may enter picture-in-picture mode
2432                             // as a result.
2433                             // So we need to disable picture-in-picture mode here
2434                             // if it is volume panel.
2435                             options.setDisallowEnterPictureInPictureWhileLaunching(true);
2436                         }
2437 
2438                         try {
2439                             result[0] = ActivityTaskManager.getService().startActivityAsUser(
2440                                     null, mContext.getBasePackageName(),
2441                                     mContext.getAttributionTag(),
2442                                     intent,
2443                                     intent.resolveTypeIfNeeded(mContext.getContentResolver()),
2444                                     null, null, 0, Intent.FLAG_ACTIVITY_NEW_TASK, null,
2445                                     options.toBundle(), userHandle.getIdentifier());
2446                         } catch (RemoteException e) {
2447                             Log.w(TAG, "Unable to start activity", e);
2448                         }
2449                         return result[0];
2450                     });
2451 
2452             if (callback != null) {
2453                 callback.onActivityStarted(result[0]);
2454             }
2455         };
2456         Runnable cancelRunnable = () -> {
2457             if (callback != null) {
2458                 callback.onActivityStarted(ActivityManager.START_CANCELED);
2459             }
2460         };
2461         // Do not deferKeyguard when occluded because, when keyguard is occluded,
2462         // we do not launch the activity until keyguard is done.
2463         boolean occluded = mKeyguardStateController.isShowing()
2464                 && mKeyguardStateController.isOccluded();
2465         boolean deferred = !occluded;
2466         executeRunnableDismissingKeyguard(runnable, cancelRunnable, dismissShadeDirectly,
2467                 willLaunchResolverActivity, deferred /* deferred */, animate);
2468     }
2469 
2470     /**
2471      * Return a {@link ActivityLaunchAnimator.Controller} wrapping {@code animationController} so
2472      * that:
2473      *  - if it launches in the notification shade window and {@code dismissShade} is true, then
2474      *    the shade will be instantly dismissed at the end of the animation.
2475      *  - if it launches in status bar window, it will make the status bar window match the device
2476      *    size during the animation (that way, the animation won't be clipped by the status bar
2477      *    size).
2478      *
2479      * @param animationController the controller that is wrapped and will drive the main animation.
2480      * @param dismissShade whether the notification shade will be dismissed at the end of the
2481      *                     animation. This is ignored if {@code animationController} is not
2482      *                     animating in the shade window.
2483      * @param isLaunchForActivity whether the launch is for an activity.
2484      */
2485     @Nullable
wrapAnimationController( ActivityLaunchAnimator.Controller animationController, boolean dismissShade, boolean isLaunchForActivity)2486     private ActivityLaunchAnimator.Controller wrapAnimationController(
2487             ActivityLaunchAnimator.Controller animationController, boolean dismissShade,
2488             boolean isLaunchForActivity) {
2489         View rootView = animationController.getLaunchContainer().getRootView();
2490 
2491         Optional<ActivityLaunchAnimator.Controller> controllerFromStatusBar =
2492                 mStatusBarWindowController.wrapAnimationControllerIfInStatusBar(
2493                         rootView, animationController);
2494         if (controllerFromStatusBar.isPresent()) {
2495             return controllerFromStatusBar.get();
2496         }
2497 
2498         if (dismissShade) {
2499             // If the view is not in the status bar, then we are animating a view in the shade.
2500             // We have to make sure that we collapse it when the animation ends or is cancelled.
2501             return new StatusBarLaunchAnimatorController(animationController, this,
2502                     isLaunchForActivity);
2503         }
2504 
2505         return animationController;
2506     }
2507 
2508     @Override
readyForKeyguardDone()2509     public void readyForKeyguardDone() {
2510         mStatusBarKeyguardViewManager.readyForKeyguardDone();
2511     }
2512 
2513     @Override
executeRunnableDismissingKeyguard(final Runnable runnable, final Runnable cancelAction, final boolean dismissShade, final boolean afterKeyguardGone, final boolean deferred)2514     public void executeRunnableDismissingKeyguard(final Runnable runnable,
2515             final Runnable cancelAction,
2516             final boolean dismissShade,
2517             final boolean afterKeyguardGone,
2518             final boolean deferred) {
2519         executeRunnableDismissingKeyguard(runnable, cancelAction, dismissShade, afterKeyguardGone,
2520                 deferred, false /* willAnimateOnKeyguard */);
2521     }
2522 
2523     @Override
executeRunnableDismissingKeyguard(final Runnable runnable, final Runnable cancelAction, final boolean dismissShade, final boolean afterKeyguardGone, final boolean deferred, final boolean willAnimateOnKeyguard)2524     public void executeRunnableDismissingKeyguard(final Runnable runnable,
2525             final Runnable cancelAction,
2526             final boolean dismissShade,
2527             final boolean afterKeyguardGone,
2528             final boolean deferred,
2529             final boolean willAnimateOnKeyguard) {
2530         OnDismissAction onDismissAction = new OnDismissAction() {
2531             @Override
2532             public boolean onDismiss() {
2533                 if (runnable != null) {
2534                     if (mKeyguardStateController.isShowing()
2535                             && mKeyguardStateController.isOccluded()) {
2536                         mStatusBarKeyguardViewManager.addAfterKeyguardGoneRunnable(runnable);
2537                     } else {
2538                         mMainExecutor.execute(runnable);
2539                     }
2540                 }
2541                 if (dismissShade) {
2542                     if (mShadeController.isExpandedVisible() && !mBouncerShowing) {
2543                         mShadeController.animateCollapseShadeDelayed();
2544                     } else {
2545                         // Do it after DismissAction has been processed to conserve the needed
2546                         // ordering.
2547                         mMainExecutor.execute(mShadeController::runPostCollapseRunnables);
2548                     }
2549                 }
2550                 return deferred;
2551             }
2552 
2553             @Override
2554             public boolean willRunAnimationOnKeyguard() {
2555                 return willAnimateOnKeyguard;
2556             }
2557         };
2558         dismissKeyguardThenExecute(onDismissAction, cancelAction, afterKeyguardGone);
2559     }
2560 
2561     private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
2562         @Override
2563         public void onReceive(Context context, Intent intent) {
2564             Trace.beginSection("CentralSurfaces#onReceive");
2565             if (DEBUG) Log.v(TAG, "onReceive: " + intent);
2566             String action = intent.getAction();
2567             String reason = intent.getStringExtra(SYSTEM_DIALOG_REASON_KEY);
2568             if (Intent.ACTION_CLOSE_SYSTEM_DIALOGS.equals(action)) {
2569                 KeyboardShortcuts.dismiss();
2570                 mRemoteInputManager.closeRemoteInputs();
2571                 if (mLockscreenUserManager.isCurrentProfile(getSendingUserId())) {
2572                     int flags = CommandQueue.FLAG_EXCLUDE_NONE;
2573                     if (reason != null) {
2574                         if (reason.equals(SYSTEM_DIALOG_REASON_RECENT_APPS)) {
2575                             flags |= CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL;
2576                         }
2577                         // Do not collapse notifications when starting dreaming if the notifications
2578                         // shade is used for the screen off animation. It might require expanded
2579                         // state for the scrims to be visible
2580                         if (reason.equals(SYSTEM_DIALOG_REASON_DREAM)
2581                                 && mScreenOffAnimationController.shouldExpandNotifications()) {
2582                             flags |= CommandQueue.FLAG_EXCLUDE_NOTIFICATION_PANEL;
2583                         }
2584                     }
2585                     mShadeController.animateCollapseShade(flags);
2586                 }
2587             } else if (Intent.ACTION_SCREEN_OFF.equals(action)) {
2588                 if (mNotificationShadeWindowController != null) {
2589                     mNotificationShadeWindowController.setNotTouchable(false);
2590                 }
2591                 finishBarAnimations();
2592                 resetUserExpandedStates();
2593             }
2594             Trace.endSection();
2595         }
2596     };
2597 
2598     private final BroadcastReceiver mDemoReceiver = new BroadcastReceiver() {
2599         @Override
2600         public void onReceive(Context context, Intent intent) {
2601             if (DEBUG) Log.v(TAG, "onReceive: " + intent);
2602             String action = intent.getAction();
2603             if (ACTION_FAKE_ARTWORK.equals(action)) {
2604                 if (DEBUG_MEDIA_FAKE_ARTWORK) {
2605                     mPresenter.updateMediaMetaData(true, true);
2606                 }
2607             }
2608         }
2609     };
2610 
2611     @Override
resetUserExpandedStates()2612     public void resetUserExpandedStates() {
2613         mNotificationsController.resetUserExpandedStates();
2614     }
2615 
executeWhenUnlocked(OnDismissAction action, boolean requiresShadeOpen, boolean afterKeyguardGone)2616     private void executeWhenUnlocked(OnDismissAction action, boolean requiresShadeOpen,
2617             boolean afterKeyguardGone) {
2618         if (mKeyguardStateController.isShowing() && requiresShadeOpen) {
2619             mStatusBarStateController.setLeaveOpenOnKeyguardHide(true);
2620         }
2621         dismissKeyguardThenExecute(action, null /* cancelAction */,
2622                 afterKeyguardGone /* afterKeyguardGone */);
2623     }
2624 
dismissKeyguardThenExecute(OnDismissAction action, boolean afterKeyguardGone)2625     protected void dismissKeyguardThenExecute(OnDismissAction action, boolean afterKeyguardGone) {
2626         dismissKeyguardThenExecute(action, null /* cancelRunnable */, afterKeyguardGone);
2627     }
2628 
2629     @Override
dismissKeyguardThenExecute(OnDismissAction action, Runnable cancelAction, boolean afterKeyguardGone)2630     public void dismissKeyguardThenExecute(OnDismissAction action, Runnable cancelAction,
2631             boolean afterKeyguardGone) {
2632         if (!action.willRunAnimationOnKeyguard()
2633                 && mWakefulnessLifecycle.getWakefulness() == WAKEFULNESS_ASLEEP
2634                 && mKeyguardStateController.canDismissLockScreen()
2635                 && !mStatusBarStateController.leaveOpenOnKeyguardHide()
2636                 && mDozeServiceHost.isPulsing()) {
2637             // Reuse the biometric wake-and-unlock transition if we dismiss keyguard from a pulse.
2638             // TODO: Factor this transition out of BiometricUnlockController.
2639             mBiometricUnlockController.startWakeAndUnlock(
2640                     BiometricUnlockController.MODE_WAKE_AND_UNLOCK_PULSING);
2641         }
2642         if (mKeyguardStateController.isShowing()) {
2643             mStatusBarKeyguardViewManager.dismissWithAction(action, cancelAction,
2644                     afterKeyguardGone);
2645         } else {
2646             // If the keyguard isn't showing but the device is dreaming, we should exit the dream.
2647             if (mKeyguardUpdateMonitor.isDreaming()) {
2648                 awakenDreams();
2649             }
2650             action.onDismiss();
2651         }
2652     }
2653     /**
2654      * Notify the shade controller that the current user changed
2655      *
2656      * @param newUserId userId of the new user
2657      */
2658     @Override
setLockscreenUser(int newUserId)2659     public void setLockscreenUser(int newUserId) {
2660         if (mLockscreenWallpaper != null) {
2661             mLockscreenWallpaper.setCurrentUser(newUserId);
2662         }
2663         mScrimController.setCurrentUser(newUserId);
2664         if (mWallpaperSupported) {
2665             mWallpaperChangedReceiver.onReceive(mContext, null);
2666         }
2667     }
2668 
2669     /**
2670      * Reload some of our resources when the configuration changes.
2671      *
2672      * We don't reload everything when the configuration changes -- we probably
2673      * should, but getting that smooth is tough.  Someday we'll fix that.  In the
2674      * meantime, just update the things that we know change.
2675      */
updateResources()2676     void updateResources() {
2677         // Update the quick setting tiles
2678         if (mQSPanelController != null) {
2679             mQSPanelController.updateResources();
2680         }
2681 
2682         if (mStatusBarWindowController != null) {
2683             mStatusBarWindowController.refreshStatusBarHeight();
2684         }
2685 
2686         if (mNotificationPanelViewController != null) {
2687             mNotificationPanelViewController.updateResources();
2688         }
2689         if (mBrightnessMirrorController != null) {
2690             mBrightnessMirrorController.updateResources();
2691         }
2692         if (mStatusBarKeyguardViewManager != null) {
2693             mStatusBarKeyguardViewManager.updateResources();
2694         }
2695 
2696         mPowerButtonReveal = new PowerButtonReveal(mContext.getResources().getDimensionPixelSize(
2697                 com.android.systemui.R.dimen.physical_power_button_center_screen_location_y));
2698     }
2699 
handleVisibleToUserChanged(boolean visibleToUser)2700     protected void handleVisibleToUserChanged(boolean visibleToUser) {
2701         if (visibleToUser) {
2702             onVisibleToUser();
2703             mNotificationLogger.startNotificationLogging();
2704 
2705             if (!mIsBackCallbackRegistered) {
2706                 ViewRootImpl viewRootImpl = getViewRootImpl();
2707                 if (viewRootImpl != null) {
2708                     viewRootImpl.getOnBackInvokedDispatcher()
2709                             .registerOnBackInvokedCallback(OnBackInvokedDispatcher.PRIORITY_DEFAULT,
2710                                     mOnBackInvokedCallback);
2711                     mIsBackCallbackRegistered = true;
2712                     if (DEBUG) Log.d(TAG, "is now VISIBLE to user AND callback registered");
2713                 }
2714             } else {
2715                 if (DEBUG) Log.d(TAG, "is now VISIBLE to user, BUT callback ALREADY unregistered");
2716             }
2717         } else {
2718             mNotificationLogger.stopNotificationLogging();
2719             onInvisibleToUser();
2720 
2721             if (mIsBackCallbackRegistered) {
2722                 ViewRootImpl viewRootImpl = getViewRootImpl();
2723                 if (viewRootImpl != null) {
2724                     viewRootImpl.getOnBackInvokedDispatcher()
2725                             .unregisterOnBackInvokedCallback(mOnBackInvokedCallback);
2726                     mIsBackCallbackRegistered = false;
2727                     if (DEBUG) Log.d(TAG, "is NOT VISIBLE to user, AND callback unregistered");
2728                 }
2729             } else {
2730                 if (DEBUG) {
2731                     Log.d(TAG,
2732                             "is NOT VISIBLE to user, BUT NO callback (or callback ALREADY "
2733                                     + "unregistered)");
2734                 }
2735             }
2736         }
2737     }
2738 
onVisibleToUser()2739     void onVisibleToUser() {
2740         /* The LEDs are turned off when the notification panel is shown, even just a little bit.
2741          * See also CentralSurfaces.setPanelExpanded for another place where we attempt to do
2742          * this.
2743          */
2744         boolean pinnedHeadsUp = mHeadsUpManager.hasPinnedHeadsUp();
2745         boolean clearNotificationEffects =
2746                 !mPresenter.isPresenterFullyCollapsed() && (mState == StatusBarState.SHADE
2747                         || mState == StatusBarState.SHADE_LOCKED);
2748         int notificationLoad = mNotificationsController.getActiveNotificationsCount();
2749         if (pinnedHeadsUp && mPresenter.isPresenterFullyCollapsed()) {
2750             notificationLoad = 1;
2751         }
2752         final int finalNotificationLoad = notificationLoad;
2753         mUiBgExecutor.execute(() -> {
2754             try {
2755                 mBarService.onPanelRevealed(clearNotificationEffects,
2756                         finalNotificationLoad);
2757             } catch (RemoteException ex) {
2758                 // Won't fail unless the world has ended.
2759             }
2760         });
2761     }
2762 
onInvisibleToUser()2763     void onInvisibleToUser() {
2764         mUiBgExecutor.execute(() -> {
2765             try {
2766                 mBarService.onPanelHidden();
2767             } catch (RemoteException ex) {
2768                 // Won't fail unless the world has ended.
2769             }
2770         });
2771     }
2772 
logStateToEventlog()2773     private void logStateToEventlog() {
2774         boolean isShowing = mKeyguardStateController.isShowing();
2775         boolean isOccluded = mKeyguardStateController.isOccluded();
2776         boolean isBouncerShowing = mStatusBarKeyguardViewManager.isBouncerShowing();
2777         boolean isSecure = mKeyguardStateController.isMethodSecure();
2778         boolean unlocked = mKeyguardStateController.canDismissLockScreen();
2779         int stateFingerprint = getLoggingFingerprint(mState,
2780                 isShowing,
2781                 isOccluded,
2782                 isBouncerShowing,
2783                 isSecure,
2784                 unlocked);
2785         if (stateFingerprint != mLastLoggedStateFingerprint) {
2786             if (mStatusBarStateLog == null) {
2787                 mStatusBarStateLog = new LogMaker(MetricsEvent.VIEW_UNKNOWN);
2788             }
2789             mMetricsLogger.write(mStatusBarStateLog
2790                     .setCategory(isBouncerShowing ? MetricsEvent.BOUNCER : MetricsEvent.LOCKSCREEN)
2791                     .setType(isShowing ? MetricsEvent.TYPE_OPEN : MetricsEvent.TYPE_CLOSE)
2792                     .setSubtype(isSecure ? 1 : 0));
2793             EventLogTags.writeSysuiStatusBarState(mState,
2794                     isShowing ? 1 : 0,
2795                     isOccluded ? 1 : 0,
2796                     isBouncerShowing ? 1 : 0,
2797                     isSecure ? 1 : 0,
2798                     unlocked ? 1 : 0);
2799             mLastLoggedStateFingerprint = stateFingerprint;
2800 
2801             StringBuilder uiEventValueBuilder = new StringBuilder();
2802             uiEventValueBuilder.append(isBouncerShowing ? "BOUNCER" : "LOCKSCREEN");
2803             uiEventValueBuilder.append(isShowing ? "_OPEN" : "_CLOSE");
2804             uiEventValueBuilder.append(isSecure ? "_SECURE" : "_INSECURE");
2805             sUiEventLogger.log(StatusBarUiEvent.valueOf(uiEventValueBuilder.toString()));
2806         }
2807     }
2808 
2809     /**
2810      * Returns a fingerprint of fields logged to eventlog
2811      */
getLoggingFingerprint(int statusBarState, boolean keyguardShowing, boolean keyguardOccluded, boolean bouncerShowing, boolean secure, boolean currentlyInsecure)2812     private static int getLoggingFingerprint(int statusBarState, boolean keyguardShowing,
2813             boolean keyguardOccluded, boolean bouncerShowing, boolean secure,
2814             boolean currentlyInsecure) {
2815         // Reserve 8 bits for statusBarState. We'll never go higher than
2816         // that, right? Riiiight.
2817         return (statusBarState & 0xFF)
2818                 | ((keyguardShowing   ? 1 : 0) <<  8)
2819                 | ((keyguardOccluded  ? 1 : 0) <<  9)
2820                 | ((bouncerShowing    ? 1 : 0) << 10)
2821                 | ((secure            ? 1 : 0) << 11)
2822                 | ((currentlyInsecure ? 1 : 0) << 12);
2823     }
2824 
2825     @Override
postQSRunnableDismissingKeyguard(final Runnable runnable)2826     public void postQSRunnableDismissingKeyguard(final Runnable runnable) {
2827         mMainExecutor.execute(() -> {
2828             mStatusBarStateController.setLeaveOpenOnKeyguardHide(true);
2829             executeRunnableDismissingKeyguard(
2830                     () -> mMainExecutor.execute(runnable), null, false, false, false);
2831         });
2832     }
2833 
2834     @Override
postStartActivityDismissingKeyguard(PendingIntent intent)2835     public void postStartActivityDismissingKeyguard(PendingIntent intent) {
2836         postStartActivityDismissingKeyguard(intent, null /* animationController */);
2837     }
2838 
2839     @Override
postStartActivityDismissingKeyguard(final PendingIntent intent, @Nullable ActivityLaunchAnimator.Controller animationController)2840     public void postStartActivityDismissingKeyguard(final PendingIntent intent,
2841             @Nullable ActivityLaunchAnimator.Controller animationController) {
2842         mMainExecutor.execute(() -> startPendingIntentDismissingKeyguard(intent,
2843                 null /* intentSentUiThreadCallback */, animationController));
2844     }
2845 
2846     @Override
postStartActivityDismissingKeyguard(final Intent intent, int delay)2847     public void postStartActivityDismissingKeyguard(final Intent intent, int delay) {
2848         postStartActivityDismissingKeyguard(intent, delay, null /* animationController */);
2849     }
2850 
2851     @Override
postStartActivityDismissingKeyguard(Intent intent, int delay, @Nullable ActivityLaunchAnimator.Controller animationController)2852     public void postStartActivityDismissingKeyguard(Intent intent, int delay,
2853             @Nullable ActivityLaunchAnimator.Controller animationController) {
2854         mMainExecutor.executeDelayed(
2855                 () ->
2856                         startActivityDismissingKeyguard(intent, true /* onlyProvisioned */,
2857                                 true /* dismissShade */,
2858                                 false /* disallowEnterPictureInPictureWhileLaunching */,
2859                                 null /* callback */,
2860                                 0 /* flags */,
2861                                 animationController,
2862                                 getActivityUserHandle(intent)),
2863                 delay);
2864     }
2865 
2866     @Override
showKeyguard()2867     public void showKeyguard() {
2868         mStatusBarStateController.setKeyguardRequested(true);
2869         mStatusBarStateController.setLeaveOpenOnKeyguardHide(false);
2870         updateIsKeyguard();
2871         mAssistManagerLazy.get().onLockscreenShown();
2872     }
2873 
2874     @Override
hideKeyguard()2875     public boolean hideKeyguard() {
2876         mStatusBarStateController.setKeyguardRequested(false);
2877         return updateIsKeyguard();
2878     }
2879 
2880     @Override
updateIsKeyguard()2881     public boolean updateIsKeyguard() {
2882         return updateIsKeyguard(false /* forceStateChange */);
2883     }
2884 
2885     @Override
updateIsKeyguard(boolean forceStateChange)2886     public boolean updateIsKeyguard(boolean forceStateChange) {
2887         boolean wakeAndUnlocking = mBiometricUnlockController.isWakeAndUnlock();
2888 
2889         // For dozing, keyguard needs to be shown whenever the device is non-interactive. Otherwise
2890         // there's no surface we can show to the user. Note that the device goes fully interactive
2891         // late in the transition, so we also allow the device to start dozing once the screen has
2892         // turned off fully.
2893         boolean keyguardForDozing = mDozeServiceHost.getDozingRequested()
2894                 && (!mDeviceInteractive || (isGoingToSleep()
2895                     && (isScreenFullyOff()
2896                         || (mKeyguardStateController.isShowing() && !isOccluded()))));
2897         boolean isWakingAndOccluded = isOccluded() && isWakingOrAwake();
2898         boolean shouldBeKeyguard = (mStatusBarStateController.isKeyguardRequested()
2899                 || keyguardForDozing) && !wakeAndUnlocking && !isWakingAndOccluded;
2900         if (keyguardForDozing) {
2901             updatePanelExpansionForKeyguard();
2902         }
2903         if (shouldBeKeyguard) {
2904             if (mScreenOffAnimationController.isKeyguardShowDelayed()
2905                     || (isGoingToSleep()
2906                     && mScreenLifecycle.getScreenState() == ScreenLifecycle.SCREEN_TURNING_OFF)) {
2907                 // Delay showing the keyguard until screen turned off.
2908             } else {
2909                 showKeyguardImpl();
2910             }
2911         } else {
2912             // During folding a foldable device this might be called as a result of
2913             // 'onScreenTurnedOff' call for the inner display.
2914             // In this case:
2915             //  * When phone is locked on folding: it doesn't make sense to hide keyguard as it
2916             //    will be immediately locked again
2917             //  * When phone is unlocked: we still don't want to execute hiding of the keyguard
2918             //    as the animation could prepare 'fake AOD' interface (without actually
2919             //    transitioning to keyguard state) and this might reset the view states
2920             if (!mScreenOffAnimationController.isKeyguardHideDelayed()
2921                     // If we're animating occluded, there's an activity launching over the keyguard
2922                     // UI. Wait to hide it until after the animation concludes.
2923                     && !mKeyguardViewMediator.isOccludeAnimationPlaying()) {
2924                 return hideKeyguardImpl(forceStateChange);
2925             }
2926         }
2927         return false;
2928     }
2929 
2930     @Override
showKeyguardImpl()2931     public void showKeyguardImpl() {
2932         Trace.beginSection("CentralSurfaces#showKeyguard");
2933         if (mKeyguardStateController.isLaunchTransitionFadingAway()) {
2934             mNotificationPanelViewController.cancelAnimation();
2935             onLaunchTransitionFadingEnded();
2936         }
2937         mMessageRouter.cancelMessages(MSG_LAUNCH_TRANSITION_TIMEOUT);
2938         if (!mLockscreenShadeTransitionController.isWakingToShadeLocked()) {
2939             mStatusBarStateController.setState(StatusBarState.KEYGUARD);
2940         }
2941         updatePanelExpansionForKeyguard();
2942         Trace.endSection();
2943     }
2944 
updatePanelExpansionForKeyguard()2945     private void updatePanelExpansionForKeyguard() {
2946         if (mState == StatusBarState.KEYGUARD && mBiometricUnlockController.getMode()
2947                 != BiometricUnlockController.MODE_WAKE_AND_UNLOCK && !mBouncerShowing) {
2948             mShadeController.instantExpandShade();
2949         }
2950     }
2951 
onLaunchTransitionFadingEnded()2952     private void onLaunchTransitionFadingEnded() {
2953         mNotificationPanelViewController.resetAlpha();
2954         mCameraLauncherLazy.get().setLaunchingAffordance(false);
2955         releaseGestureWakeLock();
2956         runLaunchTransitionEndRunnable();
2957         mKeyguardStateController.setLaunchTransitionFadingAway(false);
2958         mPresenter.updateMediaMetaData(true /* metaDataChanged */, true);
2959     }
2960 
2961     /**
2962      * Fades the content of the keyguard away after the launch transition is done.
2963      *
2964      * @param beforeFading the runnable to be run when the circle is fully expanded and the fading
2965      *                     starts
2966      * @param endRunnable the runnable to be run when the transition is done. Will not run
2967      *                    if the transition is cancelled, instead cancelRunnable will run
2968      * @param cancelRunnable the runnable to be run if the transition is cancelled
2969      */
2970     @Override
fadeKeyguardAfterLaunchTransition(final Runnable beforeFading, Runnable endRunnable, Runnable cancelRunnable)2971     public void fadeKeyguardAfterLaunchTransition(final Runnable beforeFading,
2972             Runnable endRunnable, Runnable cancelRunnable) {
2973         mMessageRouter.cancelMessages(MSG_LAUNCH_TRANSITION_TIMEOUT);
2974         mLaunchTransitionEndRunnable = endRunnable;
2975         mLaunchTransitionCancelRunnable = cancelRunnable;
2976         Runnable hideRunnable = () -> {
2977             mKeyguardStateController.setLaunchTransitionFadingAway(true);
2978             if (beforeFading != null) {
2979                 beforeFading.run();
2980             }
2981             updateScrimController();
2982             mPresenter.updateMediaMetaData(false, true);
2983             mNotificationPanelViewController.resetAlpha();
2984             mNotificationPanelViewController.fadeOut(
2985                     FADE_KEYGUARD_START_DELAY, FADE_KEYGUARD_DURATION,
2986                     this::onLaunchTransitionFadingEnded);
2987             mCommandQueue.appTransitionStarting(mDisplayId, SystemClock.uptimeMillis(),
2988                     LightBarTransitionsController.DEFAULT_TINT_ANIMATION_DURATION, true);
2989         };
2990         hideRunnable.run();
2991     }
2992 
cancelAfterLaunchTransitionRunnables()2993     private void cancelAfterLaunchTransitionRunnables() {
2994         if (mLaunchTransitionCancelRunnable != null) {
2995             mLaunchTransitionCancelRunnable.run();
2996         }
2997         mLaunchTransitionEndRunnable = null;
2998         mLaunchTransitionCancelRunnable = null;
2999     }
3000 
3001     /**
3002      * Starts the timeout when we try to start the affordances on Keyguard. We usually rely that
3003      * Keyguard goes away via fadeKeyguardAfterLaunchTransition, however, that might not happen
3004      * because the launched app crashed or something else went wrong.
3005      */
3006     @Override
startLaunchTransitionTimeout()3007     public void startLaunchTransitionTimeout() {
3008         mMessageRouter.sendMessageDelayed(
3009                 MSG_LAUNCH_TRANSITION_TIMEOUT, LAUNCH_TRANSITION_TIMEOUT_MS);
3010     }
3011 
onLaunchTransitionTimeout()3012     private void onLaunchTransitionTimeout() {
3013         Log.w(TAG, "Launch transition: Timeout!");
3014         mCameraLauncherLazy.get().setLaunchingAffordance(false);
3015         releaseGestureWakeLock();
3016         mNotificationPanelViewController.resetViews(false /* animate */);
3017     }
3018 
runLaunchTransitionEndRunnable()3019     private void runLaunchTransitionEndRunnable() {
3020         mLaunchTransitionCancelRunnable = null;
3021         if (mLaunchTransitionEndRunnable != null) {
3022             Runnable r = mLaunchTransitionEndRunnable;
3023 
3024             // mLaunchTransitionEndRunnable might call showKeyguard, which would execute it again,
3025             // which would lead to infinite recursion. Protect against it.
3026             mLaunchTransitionEndRunnable = null;
3027             r.run();
3028         }
3029     }
3030 
3031     /**
3032      * @return true if we would like to stay in the shade, false if it should go away entirely
3033      */
3034     @Override
hideKeyguardImpl(boolean forceStateChange)3035     public boolean hideKeyguardImpl(boolean forceStateChange) {
3036         Trace.beginSection("CentralSurfaces#hideKeyguard");
3037         boolean staying = mStatusBarStateController.leaveOpenOnKeyguardHide();
3038         int previousState = mStatusBarStateController.getState();
3039         if (!(mStatusBarStateController.setState(StatusBarState.SHADE, forceStateChange))) {
3040             //TODO: StatusBarStateController should probably know about hiding the keyguard and
3041             // notify listeners.
3042 
3043             // If the state didn't change, we may still need to update public mode
3044             mLockscreenUserManager.updatePublicMode();
3045         }
3046         if (mStatusBarStateController.leaveOpenOnKeyguardHide()) {
3047             if (!mStatusBarStateController.isKeyguardRequested()) {
3048                 mStatusBarStateController.setLeaveOpenOnKeyguardHide(false);
3049             }
3050             long delay = mKeyguardStateController.calculateGoingToFullShadeDelay();
3051             mLockscreenShadeTransitionController.onHideKeyguard(delay, previousState);
3052 
3053             // Disable layout transitions in navbar for this transition because the load is just
3054             // too heavy for the CPU and GPU on any device.
3055             mNavigationBarController.disableAnimationsDuringHide(mDisplayId, delay);
3056         } else if (!mNotificationPanelViewController.isCollapsing()) {
3057             mShadeController.instantCollapseShade();
3058         }
3059 
3060         // Keyguard state has changed, but QS is not listening anymore. Make sure to update the tile
3061         // visibilities so next time we open the panel we know the correct height already.
3062         if (mQSPanelController != null) {
3063             mQSPanelController.refreshAllTiles();
3064         }
3065         mMessageRouter.cancelMessages(MSG_LAUNCH_TRANSITION_TIMEOUT);
3066         releaseGestureWakeLock();
3067         mCameraLauncherLazy.get().setLaunchingAffordance(false);
3068         mNotificationPanelViewController.resetAlpha();
3069         mNotificationPanelViewController.resetTranslation();
3070         mNotificationPanelViewController.resetViewGroupFade();
3071         updateDozingState();
3072         updateScrimController();
3073         Trace.endSection();
3074         return staying;
3075     }
3076 
releaseGestureWakeLock()3077     private void releaseGestureWakeLock() {
3078         if (mGestureWakeLock.isHeld()) {
3079             mGestureWakeLock.release();
3080         }
3081     }
3082 
3083     /**
3084      * Notifies the status bar that Keyguard is going away very soon.
3085      */
3086     @Override
keyguardGoingAway()3087     public void keyguardGoingAway() {
3088         // Treat Keyguard exit animation as an app transition to achieve nice transition for status
3089         // bar.
3090         mKeyguardStateController.notifyKeyguardGoingAway(true);
3091         mCommandQueue.appTransitionPending(mDisplayId, true /* forced */);
3092         updateScrimController();
3093     }
3094 
3095     /**
3096      * Notifies the status bar the Keyguard is fading away with the specified timings.
3097      * @param startTime the start time of the animations in uptime millis
3098      * @param delay the precalculated animation delay in milliseconds
3099      * @param fadeoutDuration the duration of the exit animation, in milliseconds
3100      */
3101     @Override
setKeyguardFadingAway(long startTime, long delay, long fadeoutDuration)3102     public void setKeyguardFadingAway(long startTime, long delay, long fadeoutDuration) {
3103         mCommandQueue.appTransitionStarting(mDisplayId, startTime + fadeoutDuration
3104                         - LightBarTransitionsController.DEFAULT_TINT_ANIMATION_DURATION,
3105                 LightBarTransitionsController.DEFAULT_TINT_ANIMATION_DURATION, true);
3106         mCommandQueue.recomputeDisableFlags(mDisplayId, fadeoutDuration > 0 /* animate */);
3107         mCommandQueue.appTransitionStarting(mDisplayId,
3108                     startTime - LightBarTransitionsController.DEFAULT_TINT_ANIMATION_DURATION,
3109                     LightBarTransitionsController.DEFAULT_TINT_ANIMATION_DURATION, true);
3110         mKeyguardStateController.notifyKeyguardFadingAway(delay, fadeoutDuration);
3111     }
3112 
3113     /**
3114      * Notifies that the Keyguard fading away animation is done.
3115      */
3116     @Override
finishKeyguardFadingAway()3117     public void finishKeyguardFadingAway() {
3118         mKeyguardStateController.notifyKeyguardDoneFading();
3119         mScrimController.setExpansionAffectsAlpha(true);
3120 
3121         // If the device was re-locked while unlocking, we might have a pending lock that was
3122         // delayed because the keyguard was in the middle of going away.
3123         mKeyguardViewMediator.maybeHandlePendingLock();
3124     }
3125 
3126     /**
3127      * Switches theme from light to dark and vice-versa.
3128      */
updateTheme()3129     protected void updateTheme() {
3130         // Set additional scrim only if the lock and system wallpaper are different to prevent
3131         // applying the dimming effect twice.
3132         mUiBgExecutor.execute(() -> {
3133             float dimAmount = 0f;
3134             if (mWallpaperManager.lockScreenWallpaperExists()) {
3135                 dimAmount = mWallpaperManager.getWallpaperDimAmount();
3136             }
3137             final float scrimDimAmount = dimAmount;
3138             mMainExecutor.execute(() -> {
3139                 mScrimController.setAdditionalScrimBehindAlphaKeyguard(scrimDimAmount);
3140                 mScrimController.applyCompositeAlphaOnScrimBehindKeyguard();
3141             });
3142         });
3143 
3144         // Lock wallpaper defines the color of the majority of the views, hence we'll use it
3145         // to set our default theme.
3146         final boolean lockDarkText = mColorExtractor.getNeutralColors().supportsDarkText();
3147         final int themeResId = lockDarkText ? R.style.Theme_SystemUI_LightWallpaper
3148                 : R.style.Theme_SystemUI;
3149         if (mContext.getThemeResId() != themeResId) {
3150             mContext.setTheme(themeResId);
3151             mConfigurationController.notifyThemeChanged();
3152         }
3153     }
3154 
shouldDelayWakeUpAnimation()3155     public boolean shouldDelayWakeUpAnimation() {
3156         return mShouldDelayWakeUpAnimation;
3157     }
3158 
updateDozingState()3159     private void updateDozingState() {
3160         Trace.traceCounter(Trace.TRACE_TAG_APP, "dozing", mDozing ? 1 : 0);
3161         Trace.beginSection("CentralSurfaces#updateDozingState");
3162 
3163         boolean keyguardVisible = mKeyguardStateController.isVisible();
3164         // If we're dozing and we'll be animating the screen off, the keyguard isn't currently
3165         // visible but will be shortly for the animation, so we should proceed as if it's visible.
3166         boolean keyguardVisibleOrWillBe =
3167                 keyguardVisible || (mDozing && mDozeParameters.shouldDelayKeyguardShow());
3168 
3169         boolean animate = (!mDozing && shouldAnimateDozeWakeup())
3170                 || (mDozing && mDozeParameters.shouldControlScreenOff() && keyguardVisibleOrWillBe);
3171 
3172         mNotificationPanelViewController.setDozing(mDozing, animate);
3173         updateQsExpansionEnabled();
3174         Trace.endSection();
3175     }
3176 
3177     @Override
userActivity()3178     public void userActivity() {
3179         if (mState == StatusBarState.KEYGUARD) {
3180             mKeyguardViewMediatorCallback.userActivity();
3181         }
3182     }
3183 
3184     @Override
interceptMediaKey(KeyEvent event)3185     public boolean interceptMediaKey(KeyEvent event) {
3186         return mState == StatusBarState.KEYGUARD
3187                 && mStatusBarKeyguardViewManager.interceptMediaKey(event);
3188     }
3189 
3190     /**
3191      * While IME is active and a BACK event is detected, check with
3192      * {@link StatusBarKeyguardViewManager#dispatchBackKeyEventPreIme()} to see if the event
3193      * should be handled before routing to IME, in order to prevent the user having to hit back
3194      * twice to exit bouncer.
3195      */
3196     @Override
dispatchKeyEventPreIme(KeyEvent event)3197     public boolean dispatchKeyEventPreIme(KeyEvent event) {
3198         switch (event.getKeyCode()) {
3199             case KeyEvent.KEYCODE_BACK:
3200                 if (mState == StatusBarState.KEYGUARD
3201                         && mStatusBarKeyguardViewManager.dispatchBackKeyEventPreIme()) {
3202                     return onBackPressed();
3203                 }
3204         }
3205         return false;
3206     }
3207 
shouldUnlockOnMenuPressed()3208     protected boolean shouldUnlockOnMenuPressed() {
3209         return mDeviceInteractive && mState != StatusBarState.SHADE
3210             && mStatusBarKeyguardViewManager.shouldDismissOnMenuPressed();
3211     }
3212 
3213     @Override
onMenuPressed()3214     public boolean onMenuPressed() {
3215         if (shouldUnlockOnMenuPressed()) {
3216             mShadeController.animateCollapseShadeForced();
3217             return true;
3218         }
3219         return false;
3220     }
3221 
3222     @Override
endAffordanceLaunch()3223     public void endAffordanceLaunch() {
3224         releaseGestureWakeLock();
3225         mCameraLauncherLazy.get().setLaunchingAffordance(false);
3226     }
3227 
3228     /**
3229      * Returns whether the keyguard should hide immediately (as opposed to via an animation).
3230      * Non-scrimmed bouncers have a special animation tied to the notification panel expansion.
3231      * @return whether the keyguard should be immediately hidden.
3232      */
3233     @Override
shouldKeyguardHideImmediately()3234     public boolean shouldKeyguardHideImmediately() {
3235         final boolean isScrimmedBouncer =
3236                 mScrimController.getState() == ScrimState.BOUNCER_SCRIMMED;
3237         final boolean isBouncerOverDream = isBouncerShowingOverDream();
3238         return (isScrimmedBouncer || isBouncerOverDream);
3239     }
3240 
3241     @Override
onBackPressed()3242     public boolean onBackPressed() {
3243         if (mStatusBarKeyguardViewManager.canHandleBackPressed()) {
3244             mStatusBarKeyguardViewManager.onBackPressed();
3245             return true;
3246         }
3247         if (mQsController.isCustomizing()) {
3248             mQsController.closeQsCustomizer();
3249             return true;
3250         }
3251         if (mQsController.getExpanded()) {
3252             mNotificationPanelViewController.animateCloseQs(false);
3253             return true;
3254         }
3255         if (mNotificationPanelViewController.closeUserSwitcherIfOpen()) {
3256             return true;
3257         }
3258         if (mState != StatusBarState.KEYGUARD && mState != StatusBarState.SHADE_LOCKED
3259                 && !isBouncerShowingOverDream()) {
3260             if (mNotificationPanelViewController.canPanelBeCollapsed()) {
3261                 mShadeController.animateCollapseShade();
3262             }
3263             return true;
3264         }
3265         return false;
3266     }
3267 
3268     @Override
onSpacePressed()3269     public boolean onSpacePressed() {
3270         if (mDeviceInteractive && mState != StatusBarState.SHADE) {
3271             mShadeController.animateCollapseShadeForced();
3272             return true;
3273         }
3274         return false;
3275     }
3276 
showBouncerOrLockScreenIfKeyguard()3277     private void showBouncerOrLockScreenIfKeyguard() {
3278         // If the keyguard is animating away, we aren't really the keyguard anymore and should not
3279         // show the bouncer/lockscreen.
3280         if (!mKeyguardViewMediator.isHiding() && !mKeyguardUpdateMonitor.isKeyguardGoingAway()) {
3281             if (mState == StatusBarState.SHADE_LOCKED) {
3282                 // shade is showing while locked on the keyguard, so go back to showing the
3283                 // lock screen where users can use the UDFPS affordance to enter the device
3284                 mStatusBarKeyguardViewManager.reset(true);
3285             } else if (mState == StatusBarState.KEYGUARD
3286                     && !mStatusBarKeyguardViewManager.primaryBouncerIsOrWillBeShowing()) {
3287                 mStatusBarKeyguardViewManager.showBouncer(true /* scrimmed */);
3288             }
3289         }
3290     }
3291 
3292     /**
3293      * Show the bouncer if we're currently on the keyguard or shade locked and aren't hiding.
3294      * @param performAction the action to perform when the bouncer is dismissed.
3295      * @param cancelAction the action to perform when unlock is aborted.
3296      */
3297     @Override
showBouncerWithDimissAndCancelIfKeyguard(OnDismissAction performAction, Runnable cancelAction)3298     public void showBouncerWithDimissAndCancelIfKeyguard(OnDismissAction performAction,
3299             Runnable cancelAction) {
3300         if ((mState == StatusBarState.KEYGUARD || mState == StatusBarState.SHADE_LOCKED)
3301                 && !mKeyguardViewMediator.isHiding()) {
3302             mStatusBarKeyguardViewManager.dismissWithAction(performAction, cancelAction,
3303                     false /* afterKeyguardGone */);
3304         } else if (cancelAction != null) {
3305             cancelAction.run();
3306         }
3307     }
3308 
3309     /**
3310      * Collapse the panel directly if we are on the main thread, post the collapsing on the main
3311      * thread if we are not.
3312      */
3313     @Override
collapsePanelOnMainThread()3314     public void collapsePanelOnMainThread() {
3315         if (Looper.getMainLooper().isCurrentThread()) {
3316             mShadeController.collapseShade();
3317         } else {
3318             mContext.getMainExecutor().execute(mShadeController::collapseShade);
3319         }
3320     }
3321 
3322     /**
3323      * Updates the light reveal effect to reflect the reason we're waking or sleeping (for example,
3324      * from the power button).
3325      * @param wakingUp Whether we're updating because we're waking up (true) or going to sleep
3326      *                 (false).
3327      */
updateRevealEffect(boolean wakingUp)3328     private void updateRevealEffect(boolean wakingUp) {
3329         if (mLightRevealScrim == null) {
3330             return;
3331         }
3332 
3333         if (mFeatureFlags.isEnabled(Flags.LIGHT_REVEAL_MIGRATION)) {
3334             return;
3335         }
3336 
3337         final boolean wakingUpFromPowerButton = wakingUp
3338                 && !(mLightRevealScrim.getRevealEffect() instanceof CircleReveal)
3339                 && mWakefulnessLifecycle.getLastWakeReason()
3340                 == PowerManager.WAKE_REASON_POWER_BUTTON;
3341         final boolean sleepingFromPowerButton = !wakingUp
3342                 && mWakefulnessLifecycle.getLastSleepReason()
3343                 == PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON;
3344 
3345         if (wakingUpFromPowerButton || sleepingFromPowerButton) {
3346             mLightRevealScrim.setRevealEffect(mPowerButtonReveal);
3347             mLightRevealScrim.setRevealAmount(1f - mStatusBarStateController.getDozeAmount());
3348         } else if (!wakingUp || !(mLightRevealScrim.getRevealEffect() instanceof CircleReveal)) {
3349             // If we're going to sleep, but it's not from the power button, use the default reveal.
3350             // If we're waking up, only use the default reveal if the biometric controller didn't
3351             // already set it to the circular reveal because we're waking up from a fingerprint/face
3352             // auth.
3353             mLightRevealScrim.setRevealEffect(LiftReveal.INSTANCE);
3354             mLightRevealScrim.setRevealAmount(1f - mStatusBarStateController.getDozeAmount());
3355         }
3356     }
3357 
3358     @Override
getLightRevealScrim()3359     public LightRevealScrim getLightRevealScrim() {
3360         return mLightRevealScrim;
3361     }
3362 
3363     // TODO: Figure out way to remove these.
3364     @Override
getNavigationBarView()3365     public NavigationBarView getNavigationBarView() {
3366         return mNavigationBarController.getNavigationBarView(mDisplayId);
3367     }
3368 
3369     @Override
isOverviewEnabled()3370     public boolean isOverviewEnabled() {
3371         return mNavigationBarController.isOverviewEnabled(mDisplayId);
3372     }
3373 
3374     @Override
showPinningEnterExitToast(boolean entering)3375     public void showPinningEnterExitToast(boolean entering) {
3376         mNavigationBarController.showPinningEnterExitToast(mDisplayId, entering);
3377     }
3378 
3379     @Override
showPinningEscapeToast()3380     public void showPinningEscapeToast() {
3381         mNavigationBarController.showPinningEscapeToast(mDisplayId);
3382     }
3383 
getViewRootImpl()3384     protected ViewRootImpl getViewRootImpl()  {
3385         NotificationShadeWindowView nswv = getNotificationShadeWindowView();
3386         if (nswv != null) return nswv.getViewRootImpl();
3387 
3388         return null;
3389     }
3390     /**
3391      * Propagation of the bouncer state, indicating that it's fully visible.
3392      */
3393     @Override
setBouncerShowing(boolean bouncerShowing)3394     public void setBouncerShowing(boolean bouncerShowing) {
3395         mBouncerShowing = bouncerShowing;
3396         mKeyguardBypassController.setBouncerShowing(bouncerShowing);
3397         mPulseExpansionHandler.setBouncerShowing(bouncerShowing);
3398         setBouncerShowingForStatusBarComponents(bouncerShowing);
3399         mStatusBarHideIconsForBouncerManager.setBouncerShowingAndTriggerUpdate(bouncerShowing);
3400         mCommandQueue.recomputeDisableFlags(mDisplayId, true /* animate */);
3401         if (mBouncerShowing) {
3402             wakeUpIfDozing(SystemClock.uptimeMillis(), null, "BOUNCER_VISIBLE",
3403                     PowerManager.WAKE_REASON_GESTURE);
3404         }
3405         updateScrimController();
3406         if (!mBouncerShowing) {
3407             updatePanelExpansionForKeyguard();
3408         }
3409     }
3410 
3411     /**
3412      * Sets whether the bouncer over dream is showing. Note that the bouncer over dream is handled
3413      * independently of the rest of the notification panel. As a result, setting this state via
3414      * {@link #setBouncerShowing(boolean)} leads to unintended side effects from states modified
3415      * behind the dream.
3416      */
3417     @Override
setBouncerShowingOverDream(boolean bouncerShowingOverDream)3418     public void setBouncerShowingOverDream(boolean bouncerShowingOverDream) {
3419         mBouncerShowingOverDream = bouncerShowingOverDream;
3420     }
3421 
3422     /**
3423      * Propagate the bouncer state to status bar components.
3424      *
3425      * Separate from {@link #setBouncerShowing} because we sometimes re-create the status bar and
3426      * should update only the status bar components.
3427      */
setBouncerShowingForStatusBarComponents(boolean bouncerShowing)3428     private void setBouncerShowingForStatusBarComponents(boolean bouncerShowing) {
3429         int importance = bouncerShowing
3430                 ? IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
3431                 : IMPORTANT_FOR_ACCESSIBILITY_AUTO;
3432         if (mPhoneStatusBarViewController != null) {
3433             mPhoneStatusBarViewController.setImportantForAccessibility(importance);
3434         }
3435         mNotificationPanelViewController.setImportantForAccessibility(importance);
3436         mNotificationPanelViewController.setBouncerShowing(bouncerShowing);
3437     }
3438 
3439     /**
3440      * Collapses the notification shade if it is tracking or expanded.
3441      */
3442     @Override
collapseShade()3443     public void collapseShade() {
3444         if (mNotificationPanelViewController.isTracking()) {
3445             mNotificationShadeWindowViewController.cancelCurrentTouch();
3446         }
3447         if (mPanelExpanded && mState == StatusBarState.SHADE) {
3448             mShadeController.animateCollapseShade();
3449         }
3450     }
3451 
3452     @Override
collapseShadeForBugreport()3453     public void collapseShadeForBugreport() {
3454         if (!mFeatureFlags.isEnabled(Flags.LEAVE_SHADE_OPEN_FOR_BUGREPORT)) {
3455             collapseShade();
3456         }
3457     }
3458 
3459     @VisibleForTesting
3460     final WakefulnessLifecycle.Observer mWakefulnessObserver = new WakefulnessLifecycle.Observer() {
3461         @Override
3462         public void onFinishedGoingToSleep() {
3463             mCameraLauncherLazy.get().setLaunchingAffordance(false);
3464             releaseGestureWakeLock();
3465             mLaunchCameraWhenFinishedWaking = false;
3466             mDeviceInteractive = false;
3467             mWakeUpComingFromTouch = false;
3468             updateVisibleToUser();
3469 
3470             updateNotificationPanelTouchState();
3471             mNotificationShadeWindowViewController.cancelCurrentTouch();
3472             if (mLaunchCameraOnFinishedGoingToSleep) {
3473                 mLaunchCameraOnFinishedGoingToSleep = false;
3474 
3475                 // This gets executed before we will show Keyguard, so post it in order that the state
3476                 // is correct.
3477                 mMainExecutor.execute(() -> mCommandQueueCallbacks.onCameraLaunchGestureDetected(
3478                         mLastCameraLaunchSource));
3479             }
3480 
3481             if (mLaunchEmergencyActionOnFinishedGoingToSleep) {
3482                 mLaunchEmergencyActionOnFinishedGoingToSleep = false;
3483 
3484                 // This gets executed before we will show Keyguard, so post it in order that the
3485                 // state is correct.
3486                 mMainExecutor.execute(
3487                         () -> mCommandQueueCallbacks.onEmergencyActionLaunchGestureDetected());
3488             }
3489             updateIsKeyguard();
3490         }
3491 
3492         @Override
3493         public void onStartedGoingToSleep() {
3494             String tag = "CentralSurfaces#onStartedGoingToSleep";
3495             DejankUtils.startDetectingBlockingIpcs(tag);
3496 
3497             //  cancel stale runnables that could put the device in the wrong state
3498             cancelAfterLaunchTransitionRunnables();
3499 
3500             updateRevealEffect(false /* wakingUp */);
3501             updateNotificationPanelTouchState();
3502             maybeEscalateHeadsUp();
3503             dismissVolumeDialog();
3504             mWakeUpCoordinator.setFullyAwake(false);
3505             mKeyguardBypassController.onStartedGoingToSleep();
3506             mStatusBarTouchableRegionManager.updateTouchableRegion();
3507 
3508             // The unlocked screen off and fold to aod animations might use our LightRevealScrim -
3509             // we need to be expanded for it to be visible.
3510             if (mDozeParameters.shouldShowLightRevealScrim()) {
3511                 mShadeController.makeExpandedVisible(true);
3512             }
3513 
3514             DejankUtils.stopDetectingBlockingIpcs(tag);
3515         }
3516 
3517         @Override
3518         public void onStartedWakingUp() {
3519             String tag = "CentralSurfaces#onStartedWakingUp";
3520             DejankUtils.startDetectingBlockingIpcs(tag);
3521             mNotificationShadeWindowController.batchApplyWindowLayoutParams(()-> {
3522                 mDeviceInteractive = true;
3523 
3524                 if (shouldAnimateDozeWakeup()) {
3525                     // If this is false, the power button must be physically pressed in order to
3526                     // trigger fingerprint authentication.
3527                     final boolean touchToUnlockAnytime = Settings.Secure.getIntForUser(
3528                             mContext.getContentResolver(),
3529                             Settings.Secure.SFPS_PERFORMANT_AUTH_ENABLED,
3530                             -1,
3531                             mUserTracker.getUserId()) > 0;
3532 
3533                     // Delay if we're waking up, not mid-doze animation (which means we are
3534                     // cancelling a sleep), from the power button, on a device with a power button
3535                     // FPS, and 'press to unlock' is required.
3536                     mShouldDelayWakeUpAnimation =
3537                             !isPulsing()
3538                                     && mStatusBarStateController.getDozeAmount() == 1f
3539                                     && mWakefulnessLifecycle.getLastWakeReason()
3540                                     == PowerManager.WAKE_REASON_POWER_BUTTON
3541                                     && mFingerprintManager.get().isPowerbuttonFps()
3542                                     && mFingerprintManager.get().hasEnrolledFingerprints()
3543                                     && !touchToUnlockAnytime;
3544                     if (DEBUG_WAKEUP_DELAY) {
3545                         Log.d(TAG, "mShouldDelayWakeUpAnimation=" + mShouldDelayWakeUpAnimation);
3546                     }
3547                 } else {
3548                     // If we're not animating anyway, we do not need to delay it.
3549                     mShouldDelayWakeUpAnimation = false;
3550                     if (DEBUG_WAKEUP_DELAY) {
3551                         Log.d(TAG, "mShouldDelayWakeUpAnimation CLEARED");
3552                     }
3553                 }
3554 
3555                 mNotificationPanelViewController.setWillPlayDelayedDozeAmountAnimation(
3556                         mShouldDelayWakeUpAnimation);
3557                 mWakeUpCoordinator.setWakingUp(
3558                         /* wakingUp= */ true,
3559                         mShouldDelayWakeUpAnimation);
3560 
3561                 if (!mKeyguardBypassController.getBypassEnabled()) {
3562                     mHeadsUpManager.releaseAllImmediately();
3563                 }
3564                 updateVisibleToUser();
3565                 updateIsKeyguard();
3566                 mDozeServiceHost.stopDozing();
3567                 // This is intentionally below the stopDozing call above, since it avoids that we're
3568                 // unnecessarily animating the wakeUp transition. Animations should only be enabled
3569                 // once we fully woke up.
3570                 updateRevealEffect(true /* wakingUp */);
3571                 updateNotificationPanelTouchState();
3572                 mStatusBarTouchableRegionManager.updateTouchableRegion();
3573 
3574                 // If we are waking up during the screen off animation, we should undo making the
3575                 // expanded visible (we did that so the LightRevealScrim would be visible).
3576                 if (mScreenOffAnimationController.shouldHideLightRevealScrimOnWakeUp()) {
3577                     mShadeController.makeExpandedInvisible();
3578                 }
3579 
3580             });
3581             DejankUtils.stopDetectingBlockingIpcs(tag);
3582         }
3583 
3584         @Override
3585         public void onFinishedWakingUp() {
3586             mWakeUpCoordinator.setFullyAwake(true);
3587             mWakeUpCoordinator.setWakingUp(false, false);
3588             if (mKeyguardStateController.isOccluded()
3589                     && !mDozeParameters.canControlUnlockedScreenOff()) {
3590                 // When the keyguard is occluded we don't use the KEYGUARD state which would
3591                 // normally cause these redaction updates.  If AOD is on, the KEYGUARD state is used
3592                 // to show the doze, AND UnlockedScreenOffAnimationController.onFinishedWakingUp()
3593                 // would force a KEYGUARD state that would take care of recalculating redaction.
3594                 // So if AOD is off or unsupported we need to trigger these updates at screen on
3595                 // when the keyguard is occluded.
3596                 mLockscreenUserManager.updatePublicMode();
3597                 mNotificationPanelViewController.getNotificationStackScrollLayoutController()
3598                         .updateSensitivenessForOccludedWakeup();
3599             }
3600             if (mLaunchCameraWhenFinishedWaking) {
3601                 mCameraLauncherLazy.get().launchCamera(mLastCameraLaunchSource,
3602                         mNotificationPanelViewController.isFullyCollapsed());
3603                 mLaunchCameraWhenFinishedWaking = false;
3604             }
3605             if (mLaunchEmergencyActionWhenFinishedWaking) {
3606                 mLaunchEmergencyActionWhenFinishedWaking = false;
3607                 Intent emergencyIntent = getEmergencyActionIntent();
3608                 if (emergencyIntent != null) {
3609                     mContext.startActivityAsUser(emergencyIntent,
3610                             getActivityUserHandle(emergencyIntent));
3611                 }
3612             }
3613             updateScrimController();
3614         }
3615     };
3616 
3617     /**
3618      * We need to disable touch events because these might
3619      * collapse the panel after we expanded it, and thus we would end up with a blank
3620      * Keyguard.
3621      */
3622     @Override
updateNotificationPanelTouchState()3623     public void updateNotificationPanelTouchState() {
3624         boolean goingToSleepWithoutAnimation = isGoingToSleep()
3625                 && !mDozeParameters.shouldControlScreenOff();
3626         boolean disabled = (!mDeviceInteractive && !mDozeServiceHost.isPulsing())
3627                 || goingToSleepWithoutAnimation
3628                 || mDeviceProvisionedController.isFrpActive();
3629         mNotificationPanelViewController.setTouchAndAnimationDisabled(disabled);
3630         mNotificationIconAreaController.setAnimationsEnabled(!disabled);
3631     }
3632 
3633     final ScreenLifecycle.Observer mScreenObserver = new ScreenLifecycle.Observer() {
3634         @Override
3635         public void onScreenTurningOn() {
3636             mFalsingCollector.onScreenTurningOn();
3637             mNotificationPanelViewController.onScreenTurningOn();
3638         }
3639 
3640         @Override
3641         public void onScreenTurnedOn() {
3642             mScrimController.onScreenTurnedOn();
3643         }
3644 
3645         @Override
3646         public void onScreenTurnedOff() {
3647             Trace.beginSection("CentralSurfaces#onScreenTurnedOff");
3648             mFalsingCollector.onScreenOff();
3649             mScrimController.onScreenTurnedOff();
3650             if (mCloseQsBeforeScreenOff) {
3651                 mQsController.closeQs();
3652                 mCloseQsBeforeScreenOff = false;
3653             }
3654             updateIsKeyguard();
3655             Trace.endSection();
3656         }
3657     };
3658 
3659     @Override
getWakefulnessState()3660     public int getWakefulnessState() {
3661         return mWakefulnessLifecycle.getWakefulness();
3662     }
3663 
3664     /**
3665      * @return true if the screen is currently fully off, i.e. has finished turning off and has
3666      * since not started turning on.
3667      */
3668     @Override
isScreenFullyOff()3669     public boolean isScreenFullyOff() {
3670         return mScreenLifecycle.getScreenState() == ScreenLifecycle.SCREEN_OFF;
3671     }
3672 
3673     @Override
showScreenPinningRequest(int taskId, boolean allowCancel)3674     public void showScreenPinningRequest(int taskId, boolean allowCancel) {
3675         mScreenPinningRequest.showPrompt(taskId, allowCancel);
3676     }
3677 
3678     @Nullable
3679     @Override
getEmergencyActionIntent()3680     public Intent getEmergencyActionIntent() {
3681         Intent emergencyIntent = new Intent(EmergencyGesture.ACTION_LAUNCH_EMERGENCY);
3682         PackageManager pm = mContext.getPackageManager();
3683         List<ResolveInfo> emergencyActivities = pm.queryIntentActivities(emergencyIntent,
3684                 PackageManager.MATCH_SYSTEM_ONLY);
3685         ResolveInfo resolveInfo = getTopEmergencySosInfo(emergencyActivities);
3686         if (resolveInfo == null) {
3687             Log.wtf(TAG, "Couldn't find an app to process the emergency intent.");
3688             return null;
3689         }
3690         emergencyIntent.setComponent(new ComponentName(resolveInfo.activityInfo.packageName,
3691                 resolveInfo.activityInfo.name));
3692         emergencyIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
3693         return emergencyIntent;
3694     }
3695 
3696     /**
3697      * Select and return the "best" ResolveInfo for Emergency SOS Activity.
3698      */
getTopEmergencySosInfo(List<ResolveInfo> emergencyActivities)3699     private @Nullable ResolveInfo getTopEmergencySosInfo(List<ResolveInfo> emergencyActivities) {
3700         // No matched activity.
3701         if (emergencyActivities == null || emergencyActivities.isEmpty()) {
3702             return null;
3703         }
3704 
3705         // Of multiple matched Activities, give preference to the pre-set package name.
3706         String preferredAppPackageName =
3707                 mContext.getString(R.string.config_preferredEmergencySosPackage);
3708 
3709         // If there is no preferred app, then return first match.
3710         if (TextUtils.isEmpty(preferredAppPackageName)) {
3711             return emergencyActivities.get(0);
3712         }
3713 
3714         for (ResolveInfo emergencyInfo: emergencyActivities) {
3715             // If activity is from the preferred app, use it.
3716             if (TextUtils.equals(emergencyInfo.activityInfo.packageName, preferredAppPackageName)) {
3717                 return emergencyInfo;
3718             }
3719         }
3720         // No matching activity: return first match
3721         return emergencyActivities.get(0);
3722     }
3723 
3724     @Override
isCameraAllowedByAdmin()3725     public boolean isCameraAllowedByAdmin() {
3726         if (mDevicePolicyManager.getCameraDisabled(null,
3727                 mLockscreenUserManager.getCurrentUserId())) {
3728             return false;
3729         } else if (isKeyguardShowing() && isKeyguardSecure()) {
3730             // Check if the admin has disabled the camera specifically for the keyguard
3731             return (mDevicePolicyManager.getKeyguardDisabledFeatures(null,
3732                     mLockscreenUserManager.getCurrentUserId())
3733                     & DevicePolicyManager.KEYGUARD_DISABLE_SECURE_CAMERA) == 0;
3734         }
3735         return true;
3736     }
3737 
3738     @Override
isGoingToSleep()3739     public boolean isGoingToSleep() {
3740         return mWakefulnessLifecycle.getWakefulness()
3741                 == WakefulnessLifecycle.WAKEFULNESS_GOING_TO_SLEEP;
3742     }
3743 
isWakingOrAwake()3744     boolean isWakingOrAwake() {
3745         return mWakefulnessLifecycle.getWakefulness() == WakefulnessLifecycle.WAKEFULNESS_WAKING
3746                 || mWakefulnessLifecycle.getWakefulness() == WakefulnessLifecycle.WAKEFULNESS_AWAKE;
3747     }
3748 
3749     @Override
notifyBiometricAuthModeChanged()3750     public void notifyBiometricAuthModeChanged() {
3751         mDozeServiceHost.updateDozing();
3752         if (mBiometricUnlockController.getMode()
3753                 == BiometricUnlockController.MODE_DISMISS_BOUNCER) {
3754             // Don't update the scrim controller at this time, in favor of the transition repository
3755             // updating the scrim
3756             return;
3757         }
3758         updateScrimController();
3759     }
3760 
3761     @VisibleForTesting
setNotificationShadeWindowViewController( NotificationShadeWindowViewController nswvc)3762     public void setNotificationShadeWindowViewController(
3763             NotificationShadeWindowViewController nswvc) {
3764         mNotificationShadeWindowViewController = nswvc;
3765     }
3766 
3767     /**
3768      * Set the amount of progress we are currently in if we're transitioning to the full shade.
3769      * 0.0f means we're not transitioning yet, while 1 means we're all the way in the full
3770      * shade.
3771      */
3772     @Override
setTransitionToFullShadeProgress(float transitionToFullShadeProgress)3773     public void setTransitionToFullShadeProgress(float transitionToFullShadeProgress) {
3774         mTransitionToFullShadeProgress = transitionToFullShadeProgress;
3775     }
3776 
3777     /**
3778      * Sets the amount of progress to the bouncer being fully hidden/visible. 1 means the bouncer
3779      * is fully hidden, while 0 means the bouncer is visible.
3780      */
3781     @Override
setPrimaryBouncerHiddenFraction(float expansion)3782     public void setPrimaryBouncerHiddenFraction(float expansion) {
3783         mScrimController.setBouncerHiddenFraction(expansion);
3784     }
3785 
3786     @Override
3787     @VisibleForTesting
updateScrimController()3788     public void updateScrimController() {
3789         Trace.beginSection("CentralSurfaces#updateScrimController");
3790 
3791         boolean unlocking = mKeyguardStateController.isShowing() && (
3792                 mBiometricUnlockController.isWakeAndUnlock()
3793                         || mKeyguardStateController.isKeyguardFadingAway()
3794                         || mKeyguardStateController.isKeyguardGoingAway()
3795                         || mKeyguardViewMediator.requestedShowSurfaceBehindKeyguard()
3796                         || mKeyguardViewMediator.isAnimatingBetweenKeyguardAndSurfaceBehind());
3797 
3798         mScrimController.setExpansionAffectsAlpha(!unlocking);
3799 
3800         if (mAlternateBouncerInteractor.isVisibleState()) {
3801             if ((!isOccluded() || isPanelExpanded())
3802                     && (mState == StatusBarState.SHADE || mState == StatusBarState.SHADE_LOCKED
3803                     || mTransitionToFullShadeProgress > 0f)) {
3804                 mScrimController.transitionTo(ScrimState.AUTH_SCRIMMED_SHADE);
3805             } else {
3806                 mScrimController.transitionTo(ScrimState.AUTH_SCRIMMED);
3807             }
3808             // This will cancel the keyguardFadingAway animation if it is running. We need to do
3809             // this as otherwise it can remain pending and leave keyguard in a weird state.
3810             mUnlockScrimCallback.onCancelled();
3811         } else if (mBouncerShowing && !unlocking) {
3812             // Bouncer needs the front scrim when it's on top of an activity,
3813             // tapping on a notification, editing QS or being dismissed by
3814             // FLAG_DISMISS_KEYGUARD_ACTIVITY.
3815             ScrimState state = mStatusBarKeyguardViewManager.primaryBouncerNeedsScrimming()
3816                     ? ScrimState.BOUNCER_SCRIMMED : ScrimState.BOUNCER;
3817             mScrimController.transitionTo(state);
3818         } else if (mBrightnessMirrorVisible) {
3819             mScrimController.transitionTo(ScrimState.BRIGHTNESS_MIRROR);
3820         } else if (mState == StatusBarState.SHADE_LOCKED) {
3821             mScrimController.transitionTo(ScrimState.SHADE_LOCKED);
3822         } else if (mDozeServiceHost.isPulsing()) {
3823             mScrimController.transitionTo(ScrimState.PULSING,
3824                     mDozeScrimController.getScrimCallback());
3825         } else if (mDozeServiceHost.hasPendingScreenOffCallback()) {
3826             mScrimController.transitionTo(ScrimState.OFF, new ScrimController.Callback() {
3827                 @Override
3828                 public void onFinished() {
3829                     mDozeServiceHost.executePendingScreenOffCallback();
3830                 }
3831             });
3832         } else if (mDozing && !unlocking) {
3833             mScrimController.transitionTo(ScrimState.AOD);
3834             // This will cancel the keyguardFadingAway animation if it is running. We need to do
3835             // this as otherwise it can remain pending and leave keyguard in a weird state.
3836             mUnlockScrimCallback.onCancelled();
3837         } else if (mKeyguardStateController.isShowing() && !isOccluded() && !unlocking) {
3838             mScrimController.transitionTo(ScrimState.KEYGUARD);
3839         } else if (mKeyguardStateController.isShowing() && mKeyguardUpdateMonitor.isDreaming()
3840                 && !unlocking) {
3841             mScrimController.transitionTo(ScrimState.DREAMING);
3842         } else {
3843             mScrimController.transitionTo(ScrimState.UNLOCKED, mUnlockScrimCallback);
3844         }
3845         updateLightRevealScrimVisibility();
3846 
3847         Trace.endSection();
3848     }
3849 
3850     @Override
isKeyguardShowing()3851     public boolean isKeyguardShowing() {
3852         return mKeyguardStateController.isShowing();
3853     }
3854 
3855     @Override
shouldIgnoreTouch()3856     public boolean shouldIgnoreTouch() {
3857         return (mStatusBarStateController.isDozing()
3858                 && mDozeServiceHost.getIgnoreTouchWhilePulsing())
3859                 || mScreenOffAnimationController.shouldIgnoreKeyguardTouches();
3860     }
3861 
3862     // Begin Extra BaseStatusBar methods.
3863 
3864     protected final CommandQueue mCommandQueue;
3865     protected IStatusBarService mBarService;
3866 
3867     // all notifications
3868     protected NotificationStackScrollLayout mStackScroller;
3869 
3870     protected AccessibilityManager mAccessibilityManager;
3871 
3872     protected boolean mDeviceInteractive;
3873 
3874     protected boolean mVisible;
3875 
3876     // mScreenOnFromKeyguard && mVisible.
3877     private boolean mVisibleToUser;
3878 
3879     protected DevicePolicyManager mDevicePolicyManager;
3880     private final PowerManager mPowerManager;
3881     protected StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
3882 
3883     protected KeyguardManager mKeyguardManager;
3884     private final DeviceProvisionedController mDeviceProvisionedController;
3885 
3886     private final NavigationBarController mNavigationBarController;
3887     private final AccessibilityFloatingMenuController mAccessibilityFloatingMenuController;
3888 
3889     // UI-specific methods
3890 
3891     protected WindowManager mWindowManager;
3892     protected IWindowManager mWindowManagerService;
3893     private final IDreamManager mDreamManager;
3894 
3895     protected Display mDisplay;
3896     private int mDisplayId;
3897 
3898     protected NotificationShelfController mNotificationShelfController;
3899 
3900     private final Lazy<AssistManager> mAssistManagerLazy;
3901 
3902     @Override
isDeviceInteractive()3903     public boolean isDeviceInteractive() {
3904         return mDeviceInteractive;
3905     }
3906 
3907     private final BroadcastReceiver mBannerActionBroadcastReceiver = new BroadcastReceiver() {
3908         @Override
3909         public void onReceive(Context context, Intent intent) {
3910             String action = intent.getAction();
3911             if (BANNER_ACTION_CANCEL.equals(action) || BANNER_ACTION_SETUP.equals(action)) {
3912                 NotificationManager noMan = (NotificationManager)
3913                         mContext.getSystemService(Context.NOTIFICATION_SERVICE);
3914                 noMan.cancel(com.android.internal.messages.nano.SystemMessageProto.SystemMessage.
3915                         NOTE_HIDDEN_NOTIFICATIONS);
3916 
3917                 Settings.Secure.putInt(mContext.getContentResolver(),
3918                         Settings.Secure.SHOW_NOTE_ABOUT_NOTIFICATION_HIDING, 0);
3919                 if (BANNER_ACTION_SETUP.equals(action)) {
3920                     mShadeController.animateCollapseShadeForced();
3921                     mContext.startActivity(new Intent(Settings.ACTION_APP_NOTIFICATION_REDACTION)
3922                             .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
3923 
3924                     );
3925                 }
3926             }
3927         }
3928     };
3929 
3930     @Override
setNotificationSnoozed(StatusBarNotification sbn, SnoozeOption snoozeOption)3931     public void setNotificationSnoozed(StatusBarNotification sbn, SnoozeOption snoozeOption) {
3932         mNotificationsController.setNotificationSnoozed(sbn, snoozeOption);
3933     }
3934 
3935 
3936     @Override
awakenDreams()3937     public void awakenDreams() {
3938         mUiBgExecutor.execute(() -> {
3939             try {
3940                 mDreamManager.awaken();
3941             } catch (RemoteException e) {
3942                 e.printStackTrace();
3943             }
3944         });
3945     }
3946 
toggleKeyboardShortcuts(int deviceId)3947     protected void toggleKeyboardShortcuts(int deviceId) {
3948         KeyboardShortcuts.toggle(mContext, deviceId);
3949     }
3950 
dismissKeyboardShortcuts()3951     protected void dismissKeyboardShortcuts() {
3952         KeyboardShortcuts.dismiss();
3953     }
3954 
3955     /**
3956      * Dismiss the keyguard then execute an action.
3957      *
3958      * @param action The action to execute after dismissing the keyguard.
3959      * @param collapsePanel Whether we should collapse the panel after dismissing the keyguard.
3960      * @param willAnimateOnKeyguard Whether {@param action} will run an animation on the keyguard if
3961      *                              we are locked.
3962      */
executeActionDismissingKeyguard(Runnable action, boolean afterKeyguardGone, boolean collapsePanel, boolean willAnimateOnKeyguard)3963     private void executeActionDismissingKeyguard(Runnable action, boolean afterKeyguardGone,
3964             boolean collapsePanel, boolean willAnimateOnKeyguard) {
3965         if (!mDeviceProvisionedController.isDeviceProvisioned()) return;
3966 
3967         OnDismissAction onDismissAction = new OnDismissAction() {
3968             @Override
3969             public boolean onDismiss() {
3970                 new Thread(() -> {
3971                     try {
3972                         // The intent we are sending is for the application, which
3973                         // won't have permission to immediately start an activity after
3974                         // the user switches to home.  We know it is safe to do at this
3975                         // point, so make sure new activity switches are now allowed.
3976                         ActivityManager.getService().resumeAppSwitches();
3977                     } catch (RemoteException e) {
3978                     }
3979                     action.run();
3980                 }).start();
3981 
3982                 return collapsePanel ? mShadeController.collapseShade() : willAnimateOnKeyguard;
3983             }
3984 
3985             @Override
3986             public boolean willRunAnimationOnKeyguard() {
3987                 return willAnimateOnKeyguard;
3988             }
3989         };
3990         dismissKeyguardThenExecute(onDismissAction, afterKeyguardGone);
3991     }
3992 
3993     @Override
startPendingIntentDismissingKeyguard(final PendingIntent intent)3994     public void startPendingIntentDismissingKeyguard(final PendingIntent intent) {
3995         startPendingIntentDismissingKeyguard(intent, null);
3996     }
3997 
3998     @Override
startPendingIntentDismissingKeyguard( final PendingIntent intent, @Nullable final Runnable intentSentUiThreadCallback)3999     public void startPendingIntentDismissingKeyguard(
4000             final PendingIntent intent, @Nullable final Runnable intentSentUiThreadCallback) {
4001         startPendingIntentDismissingKeyguard(intent, intentSentUiThreadCallback,
4002                 (ActivityLaunchAnimator.Controller) null);
4003     }
4004 
4005     @Override
startPendingIntentDismissingKeyguard(PendingIntent intent, Runnable intentSentUiThreadCallback, View associatedView)4006     public void startPendingIntentDismissingKeyguard(PendingIntent intent,
4007             Runnable intentSentUiThreadCallback, View associatedView) {
4008         ActivityLaunchAnimator.Controller animationController = null;
4009         if (associatedView instanceof ExpandableNotificationRow) {
4010             animationController = mNotificationAnimationProvider.getAnimatorController(
4011                     ((ExpandableNotificationRow) associatedView));
4012         }
4013 
4014         startPendingIntentDismissingKeyguard(intent, intentSentUiThreadCallback,
4015                 animationController);
4016     }
4017 
4018     @Override
startPendingIntentDismissingKeyguard( final PendingIntent intent, @Nullable final Runnable intentSentUiThreadCallback, @Nullable ActivityLaunchAnimator.Controller animationController)4019     public void startPendingIntentDismissingKeyguard(
4020             final PendingIntent intent, @Nullable final Runnable intentSentUiThreadCallback,
4021             @Nullable ActivityLaunchAnimator.Controller animationController) {
4022         final boolean willLaunchResolverActivity = intent.isActivity()
4023                 && mActivityIntentHelper.wouldPendingLaunchResolverActivity(intent,
4024                 mLockscreenUserManager.getCurrentUserId());
4025 
4026         boolean animate = !willLaunchResolverActivity
4027                 && animationController != null
4028                 && shouldAnimateLaunch(intent.isActivity());
4029 
4030         // If we animate, don't collapse the shade and defer the keyguard dismiss (in case we run
4031         // the animation on the keyguard). The animation will take care of (instantly) collapsing
4032         // the shade and hiding the keyguard once it is done.
4033         boolean collapse = !animate;
4034         executeActionDismissingKeyguard(() -> {
4035             try {
4036                 // We wrap animationCallback with a StatusBarLaunchAnimatorController so that the
4037                 // shade is collapsed after the animation (or when it is cancelled, aborted, etc).
4038                 ActivityLaunchAnimator.Controller controller =
4039                         animationController != null ? wrapAnimationController(
4040                                 animationController, /* dismissShade= */ true, intent.isActivity())
4041                                 : null;
4042 
4043                 mActivityLaunchAnimator.startPendingIntentWithAnimation(
4044                         controller, animate, intent.getCreatorPackage(),
4045                         (animationAdapter) -> {
4046                             ActivityOptions options = new ActivityOptions(
4047                                     CentralSurfaces.getActivityOptions(
4048                                             mDisplayId, animationAdapter));
4049                             // TODO b/221255671: restrict this to only be set for notifications
4050                             options.setEligibleForLegacyPermissionPrompt(true);
4051                             return intent.sendAndReturnResult(null, 0, null, null, null,
4052                                     null, options.toBundle());
4053                         });
4054             } catch (PendingIntent.CanceledException e) {
4055                 // the stack trace isn't very helpful here.
4056                 // Just log the exception message.
4057                 Log.w(TAG, "Sending intent failed: " + e);
4058                 if (!collapse) {
4059                     // executeActionDismissingKeyguard did not collapse for us already.
4060                     collapsePanelOnMainThread();
4061                 }
4062                 // TODO: Dismiss Keyguard.
4063             }
4064             if (intent.isActivity()) {
4065                 mAssistManagerLazy.get().hideAssist();
4066             }
4067             if (intentSentUiThreadCallback != null) {
4068                 postOnUiThread(intentSentUiThreadCallback);
4069             }
4070         }, willLaunchResolverActivity, collapse, animate);
4071     }
4072 
postOnUiThread(Runnable runnable)4073     private void postOnUiThread(Runnable runnable) {
4074         mMainExecutor.execute(runnable);
4075     }
4076 
onShadeVisibilityChanged(boolean visible)4077     private void onShadeVisibilityChanged(boolean visible) {
4078         if (mVisible != visible) {
4079             mVisible = visible;
4080             if (!visible) {
4081                 mGutsManager.closeAndSaveGuts(true /* removeLeavebehind */, true /* force */,
4082                         true /* removeControls */, -1 /* x */, -1 /* y */, true /* resetMenu */);
4083             }
4084         }
4085         updateVisibleToUser();
4086     }
4087 
updateVisibleToUser()4088     protected void updateVisibleToUser() {
4089         boolean oldVisibleToUser = mVisibleToUser;
4090         mVisibleToUser = mVisible && mDeviceInteractive;
4091 
4092         if (oldVisibleToUser != mVisibleToUser) {
4093             handleVisibleToUserChanged(mVisibleToUser);
4094         }
4095     }
4096 
4097     /**
4098      * Clear Buzz/Beep/Blink.
4099      */
4100     @Override
clearNotificationEffects()4101     public void clearNotificationEffects() {
4102         try {
4103             mBarService.clearNotificationEffects();
4104         } catch (RemoteException e) {
4105             // Won't fail unless the world has ended.
4106         }
4107     }
4108 
4109     /**
4110      * @return Whether the security bouncer from Keyguard is showing.
4111      */
4112     @Override
isBouncerShowing()4113     public boolean isBouncerShowing() {
4114         return mBouncerShowing;
4115     }
4116 
4117     /**
4118      * @return Whether the security bouncer from Keyguard is showing.
4119      */
4120     @Override
isBouncerShowingScrimmed()4121     public boolean isBouncerShowingScrimmed() {
4122         return isBouncerShowing() && mStatusBarKeyguardViewManager.primaryBouncerNeedsScrimming();
4123     }
4124 
4125     @Override
isBouncerShowingOverDream()4126     public boolean isBouncerShowingOverDream() {
4127         return mBouncerShowingOverDream;
4128     }
4129 
4130     @Override
isKeyguardSecure()4131     public boolean isKeyguardSecure() {
4132         return mStatusBarKeyguardViewManager.isSecure();
4133     }
4134 
4135     // End Extra BaseStatusBarMethods.
4136 
isTransientShown()4137     boolean isTransientShown() {
4138         return mTransientShown;
4139     }
4140 
updateLightRevealScrimVisibility()4141     private void updateLightRevealScrimVisibility() {
4142         if (mLightRevealScrim == null) {
4143             // status bar may not be inflated yet
4144             return;
4145         }
4146 
4147         if (!mFeatureFlags.isEnabled(Flags.LIGHT_REVEAL_MIGRATION)) {
4148             mLightRevealScrim.setAlpha(mScrimController.getState().getMaxLightRevealScrimAlpha());
4149         }
4150     }
4151 
4152     @Override
extendDozePulse()4153     public void extendDozePulse(){
4154         mDozeScrimController.extendPulse();
4155     }
4156 
4157     private final KeyguardUpdateMonitorCallback mUpdateCallback =
4158             new KeyguardUpdateMonitorCallback() {
4159                 @Override
4160                 public void onDreamingStateChanged(boolean dreaming) {
4161                     updateScrimController();
4162                     if (dreaming) {
4163                         maybeEscalateHeadsUp();
4164                     }
4165                 }
4166             };
4167 
4168 
4169     private final FalsingManager.FalsingBeliefListener mFalsingBeliefListener =
4170             new FalsingManager.FalsingBeliefListener() {
4171                 @Override
4172                 public void onFalse() {
4173                     // Hides quick settings, bouncer, and quick-quick settings.
4174                     mStatusBarKeyguardViewManager.reset(true);
4175                 }
4176             };
4177 
4178     // Notifies StatusBarKeyguardViewManager every time the keyguard transition is over,
4179     // this animation is tied to the scrim for historic reasons.
4180     // TODO: notify when keyguard has faded away instead of the scrim.
4181     private final ScrimController.Callback mUnlockScrimCallback = new ScrimController
4182             .Callback() {
4183         @Override
4184         public void onFinished() {
4185             if (mKeyguardStateController.isKeyguardFadingAway()) {
4186                 mStatusBarKeyguardViewManager.onKeyguardFadedAway();
4187             }
4188         }
4189 
4190         @Override
4191         public void onCancelled() {
4192             onFinished();
4193         }
4194     };
4195 
4196     private final DeviceProvisionedListener mUserSetupObserver = new DeviceProvisionedListener() {
4197         @Override
4198         public void onUserSetupChanged() {
4199             final boolean userSetup = mDeviceProvisionedController.isCurrentUserSetup();
4200             Log.d(TAG, "mUserSetupObserver - DeviceProvisionedListener called for "
4201                     + "current user");
4202             if (MULTIUSER_DEBUG) {
4203                 Log.d(TAG, String.format("User setup changed: userSetup=%s mUserSetup=%s",
4204                         userSetup, mUserSetup));
4205             }
4206 
4207             if (userSetup != mUserSetup) {
4208                 mUserSetup = userSetup;
4209                 if (!mUserSetup) {
4210                     animateCollapseQuickSettings();
4211                 }
4212                 updateQsExpansionEnabled();
4213             }
4214         }
4215     };
4216 
4217     private final BroadcastReceiver mWallpaperChangedReceiver = new BroadcastReceiver() {
4218         @Override
4219         public void onReceive(Context context, Intent intent) {
4220             if (!mWallpaperSupported) {
4221                 // Receiver should not have been registered at all...
4222                 Log.wtf(TAG, "WallpaperManager not supported");
4223                 return;
4224             }
4225             WallpaperInfo info = mWallpaperManager.getWallpaperInfo(mUserTracker.getUserId());
4226             mWallpaperController.onWallpaperInfoUpdated(info);
4227 
4228             final boolean deviceSupportsAodWallpaper = mContext.getResources().getBoolean(
4229                     com.android.internal.R.bool.config_dozeSupportsAodWallpaper);
4230             // If WallpaperInfo is null, it must be ImageWallpaper.
4231             final boolean supportsAmbientMode = deviceSupportsAodWallpaper
4232                     && (info != null && info.supportsAmbientMode());
4233 
4234             mNotificationShadeWindowController.setWallpaperSupportsAmbientMode(supportsAmbientMode);
4235             mScrimController.setWallpaperSupportsAmbientMode(supportsAmbientMode);
4236             mKeyguardViewMediator.setWallpaperSupportsAmbientMode(supportsAmbientMode);
4237         }
4238     };
4239 
4240     private final ConfigurationListener mConfigurationListener = new ConfigurationListener() {
4241         @Override
4242         public void onConfigChanged(Configuration newConfig) {
4243             updateResources();
4244             updateDisplaySize(); // populates mDisplayMetrics
4245 
4246             if (DEBUG) {
4247                 Log.v(TAG, "configuration changed: " + mContext.getResources().getConfiguration());
4248             }
4249 
4250             mScreenPinningRequest.onConfigurationChanged();
4251         }
4252 
4253         @Override
4254         public void onDensityOrFontScaleChanged() {
4255             // TODO: Remove this.
4256             if (mBrightnessMirrorController != null) {
4257                 mBrightnessMirrorController.onDensityOrFontScaleChanged();
4258             }
4259             // TODO: Bring these out of CentralSurfaces.
4260             mUserInfoControllerImpl.onDensityOrFontScaleChanged();
4261             mNotificationIconAreaController.onDensityOrFontScaleChanged(mContext);
4262             mHeadsUpManager.onDensityOrFontScaleChanged();
4263         }
4264 
4265         @Override
4266         public void onThemeChanged() {
4267             if (mBrightnessMirrorController != null) {
4268                 mBrightnessMirrorController.onOverlayChanged();
4269             }
4270             // We need the new R.id.keyguard_indication_area before recreating
4271             // mKeyguardIndicationController
4272             mNotificationPanelViewController.onThemeChanged();
4273 
4274             if (mStatusBarKeyguardViewManager != null) {
4275                 mStatusBarKeyguardViewManager.onThemeChanged();
4276             }
4277             if (mAmbientIndicationContainer instanceof AutoReinflateContainer) {
4278                 ((AutoReinflateContainer) mAmbientIndicationContainer).inflateLayout();
4279             }
4280             mNotificationIconAreaController.onThemeChanged();
4281         }
4282 
4283         @Override
4284         public void onUiModeChanged() {
4285             if (mBrightnessMirrorController != null) {
4286                 mBrightnessMirrorController.onUiModeChanged();
4287             }
4288         }
4289     };
4290 
4291     private StatusBarStateController.StateListener mStateListener =
4292             new StatusBarStateController.StateListener() {
4293                 @Override
4294                 public void onStatePreChange(int oldState, int newState) {
4295                     // If we're visible and switched to SHADE_LOCKED (the user dragged
4296                     // down on the lockscreen), clear notification LED, vibration,
4297                     // ringing.
4298                     // Other transitions are covered in handleVisibleToUserChanged().
4299                     if (mVisible && (newState == StatusBarState.SHADE_LOCKED
4300                             || mStatusBarStateController.goingToFullShade())) {
4301                         clearNotificationEffects();
4302                     }
4303                     if (newState == StatusBarState.KEYGUARD) {
4304                         mRemoteInputManager.onPanelCollapsed();
4305                         maybeEscalateHeadsUp();
4306                     }
4307                 }
4308 
4309                 @Override
4310                 public void onStateChanged(int newState) {
4311                     mState = newState;
4312                     updateReportRejectedTouchVisibility();
4313                     mDozeServiceHost.updateDozing();
4314                     updateTheme();
4315                     mNavigationBarController.touchAutoDim(mDisplayId);
4316                     Trace.beginSection("CentralSurfaces#updateKeyguardState");
4317                     if (mState == StatusBarState.KEYGUARD) {
4318                         mNotificationPanelViewController.cancelPendingPanelCollapse();
4319                     }
4320                     updateDozingState();
4321                     checkBarModes();
4322                     updateScrimController();
4323                     mPresenter.updateMediaMetaData(false, mState != StatusBarState.KEYGUARD);
4324                     Trace.endSection();
4325                 }
4326 
4327                 @Override
4328                 public void onDozeAmountChanged(float linear, float eased) {
4329                     if (!mFeatureFlags.isEnabled(Flags.LIGHT_REVEAL_MIGRATION)
4330                             && !(mLightRevealScrim.getRevealEffect() instanceof CircleReveal)) {
4331                         mLightRevealScrim.setRevealAmount(1f - linear);
4332                     }
4333                 }
4334 
4335                 @Override
4336                 public void onDozingChanged(boolean isDozing) {
4337                     Trace.beginSection("CentralSurfaces#updateDozing");
4338                     mDozing = isDozing;
4339 
4340                     boolean dozingAnimated = mDozeServiceHost.getDozingRequested()
4341                             && mDozeParameters.shouldControlScreenOff();
4342                     // resetting views is already done when going into doze, there's no need to
4343                     // reset them again when we're waking up
4344                     mNotificationPanelViewController.resetViews(dozingAnimated && isDozing);
4345 
4346                     updateQsExpansionEnabled();
4347                     mKeyguardViewMediator.setDozing(mDozing);
4348 
4349                     updateDozingState();
4350                     mDozeServiceHost.updateDozing();
4351                     updateScrimController();
4352 
4353                     if (mBiometricUnlockController.isWakeAndUnlock()) {
4354                         // Usually doze changes are to/from lockscreen/AOD, but if we're wake and
4355                         // unlocking we should hide the keyguard ASAP if necessary.
4356                         updateIsKeyguard();
4357                     }
4358 
4359                     updateReportRejectedTouchVisibility();
4360                     Trace.endSection();
4361                 }
4362 
4363                 @Override
4364                 public void onFullscreenStateChanged(boolean isFullscreen) {
4365                     mIsFullscreen = isFullscreen;
4366                     maybeUpdateBarMode();
4367                 }
4368             };
4369 
4370     private final BatteryController.BatteryStateChangeCallback mBatteryStateChangeCallback =
4371             new BatteryController.BatteryStateChangeCallback() {
4372                 @Override
4373                 public void onPowerSaveChanged(boolean isPowerSave) {
4374                     mMainExecutor.execute(mCheckBarModes);
4375                     if (mDozeServiceHost != null) {
4376                         mDozeServiceHost.firePowerSaveChanged(isPowerSave);
4377                     }
4378                 }
4379             };
4380 
4381     private final ActivityLaunchAnimator.Callback mActivityLaunchAnimatorCallback =
4382             new ActivityLaunchAnimator.Callback() {
4383                 @Override
4384                 public boolean isOnKeyguard() {
4385                     return mKeyguardStateController.isShowing();
4386                 }
4387 
4388                 @Override
4389                 public void hideKeyguardWithAnimation(IRemoteAnimationRunner runner) {
4390                     // We post to the main thread for 2 reasons:
4391                     //   1. KeyguardViewMediator is not thread-safe.
4392                     //   2. To ensure that ViewMediatorCallback#keyguardDonePending is called before
4393                     //      ViewMediatorCallback#readyForKeyguardDone. The wrong order could occur
4394                     //      when doing
4395                     //      dismissKeyguardThenExecute { hideKeyguardWithAnimation(runner) }.
4396                     mMainExecutor.execute(() -> mKeyguardViewMediator.hideWithAnimation(runner));
4397                 }
4398 
4399                 @Override
4400                 public int getBackgroundColor(TaskInfo task) {
4401                     if (!mStartingSurfaceOptional.isPresent()) {
4402                         Log.w(TAG, "No starting surface, defaulting to SystemBGColor");
4403                         return SplashscreenContentDrawer.getSystemBGColor();
4404                     }
4405 
4406                     return mStartingSurfaceOptional.get().getBackgroundColor(task);
4407                 }
4408             };
4409 
4410     private final ActivityLaunchAnimator.Listener mActivityLaunchAnimatorListener =
4411             new ActivityLaunchAnimator.Listener() {
4412                 @Override
4413                 public void onLaunchAnimationStart() {
4414                     mKeyguardViewMediator.setBlursDisabledForAppLaunch(true);
4415                 }
4416 
4417                 @Override
4418                 public void onLaunchAnimationEnd() {
4419                     mKeyguardViewMediator.setBlursDisabledForAppLaunch(false);
4420                 }
4421             };
4422 
4423     private final DemoMode mDemoModeCallback = new DemoMode() {
4424         @Override
4425         public void onDemoModeFinished() {
4426             checkBarModes();
4427         }
4428 
4429         @Override
4430         public void dispatchDemoCommand(String command, Bundle args) { }
4431     };
4432 
4433     /**
4434      *  Determines what UserHandle to use when launching an activity.
4435      *
4436      *  We want to ensure that activities that are launched within the systemui process should be
4437      *  launched as user of the current process.
4438      * @param intent
4439      * @return UserHandle
4440      */
getActivityUserHandle(Intent intent)4441     private UserHandle getActivityUserHandle(Intent intent) {
4442         String[] packages = mContext.getResources().getStringArray(R.array.system_ui_packages);
4443         for (String pkg : packages) {
4444             if (intent.getComponent() == null) break;
4445             if (pkg.equals(intent.getComponent().getPackageName())) {
4446                 return new UserHandle(UserHandle.myUserId());
4447             }
4448         }
4449         return mUserTracker.getUserHandle();
4450     }
4451 
4452     /**
4453      * Whether we want to animate the wake animation AOD to lockscreen. This is done only if the
4454      * doze service host says we can, and also we're not wake and unlocking (in which case the
4455      * AOD instantly hides).
4456      */
shouldAnimateDozeWakeup()4457     private boolean shouldAnimateDozeWakeup() {
4458         return mDozeServiceHost.shouldAnimateWakeup()
4459                 && mBiometricUnlockController.getMode()
4460                 != BiometricUnlockController.MODE_WAKE_AND_UNLOCK;
4461     }
4462 }
4463