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