• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2010 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.systemui.statusbar.phone;
18 
19 import static android.app.StatusBarManager.WINDOW_STATE_HIDDEN;
20 import static android.app.StatusBarManager.WINDOW_STATE_SHOWING;
21 import static android.app.StatusBarManager.WindowType;
22 import static android.app.StatusBarManager.WindowVisibleState;
23 import static android.app.StatusBarManager.windowStateToString;
24 import static android.view.InsetsState.ITYPE_STATUS_BAR;
25 import static android.view.InsetsState.containsType;
26 import static android.view.WindowInsetsController.APPEARANCE_LOW_PROFILE_BARS;
27 import static android.view.WindowInsetsController.APPEARANCE_OPAQUE_STATUS_BARS;
28 import static android.view.WindowInsetsController.APPEARANCE_SEMI_TRANSPARENT_STATUS_BARS;
29 
30 import static androidx.lifecycle.Lifecycle.State.RESUMED;
31 
32 import static com.android.systemui.Dependency.TIME_TICK_HANDLER_NAME;
33 import static com.android.systemui.charging.WirelessChargingLayout.UNKNOWN_BATTERY_LEVEL;
34 import static com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_ASLEEP;
35 import static com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_AWAKE;
36 import static com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_WAKING;
37 import static com.android.systemui.statusbar.NotificationLockscreenUserManager.PERMISSION_SELF;
38 import static com.android.systemui.statusbar.phone.BarTransitions.MODE_LIGHTS_OUT;
39 import static com.android.systemui.statusbar.phone.BarTransitions.MODE_LIGHTS_OUT_TRANSPARENT;
40 import static com.android.systemui.statusbar.phone.BarTransitions.MODE_OPAQUE;
41 import static com.android.systemui.statusbar.phone.BarTransitions.MODE_SEMI_TRANSPARENT;
42 import static com.android.systemui.statusbar.phone.BarTransitions.MODE_TRANSLUCENT;
43 import static com.android.systemui.statusbar.phone.BarTransitions.MODE_TRANSPARENT;
44 import static com.android.systemui.statusbar.phone.BarTransitions.MODE_WARNING;
45 import static com.android.systemui.statusbar.phone.BarTransitions.TransitionMode;
46 import static com.android.wm.shell.bubbles.BubbleController.TASKBAR_CHANGED_BROADCAST;
47 
48 import android.annotation.Nullable;
49 import android.app.ActivityManager;
50 import android.app.ActivityOptions;
51 import android.app.ActivityTaskManager;
52 import android.app.IWallpaperManager;
53 import android.app.KeyguardManager;
54 import android.app.Notification;
55 import android.app.NotificationManager;
56 import android.app.PendingIntent;
57 import android.app.StatusBarManager;
58 import android.app.TaskInfo;
59 import android.app.UiModeManager;
60 import android.app.WallpaperInfo;
61 import android.app.WallpaperManager;
62 import android.app.admin.DevicePolicyManager;
63 import android.content.BroadcastReceiver;
64 import android.content.ComponentCallbacks2;
65 import android.content.ComponentName;
66 import android.content.Context;
67 import android.content.Intent;
68 import android.content.IntentFilter;
69 import android.content.pm.IPackageManager;
70 import android.content.pm.PackageManager;
71 import android.content.pm.PackageManager.NameNotFoundException;
72 import android.content.pm.ResolveInfo;
73 import android.content.res.Configuration;
74 import android.content.res.Resources;
75 import android.graphics.Point;
76 import android.graphics.PointF;
77 import android.media.AudioAttributes;
78 import android.metrics.LogMaker;
79 import android.net.Uri;
80 import android.os.AsyncTask;
81 import android.os.Bundle;
82 import android.os.Handler;
83 import android.os.Looper;
84 import android.os.Message;
85 import android.os.PowerManager;
86 import android.os.RemoteException;
87 import android.os.ServiceManager;
88 import android.os.SystemClock;
89 import android.os.SystemProperties;
90 import android.os.Trace;
91 import android.os.UserHandle;
92 import android.os.VibrationEffect;
93 import android.os.Vibrator;
94 import android.provider.Settings;
95 import android.service.dreams.DreamService;
96 import android.service.dreams.IDreamManager;
97 import android.service.notification.StatusBarNotification;
98 import android.text.TextUtils;
99 import android.util.ArraySet;
100 import android.util.DisplayMetrics;
101 import android.util.EventLog;
102 import android.util.Log;
103 import android.util.MathUtils;
104 import android.util.Slog;
105 import android.view.Display;
106 import android.view.IRemoteAnimationRunner;
107 import android.view.IWindowManager;
108 import android.view.InsetsState.InternalInsetsType;
109 import android.view.KeyEvent;
110 import android.view.MotionEvent;
111 import android.view.RemoteAnimationAdapter;
112 import android.view.ThreadedRenderer;
113 import android.view.View;
114 import android.view.ViewGroup;
115 import android.view.WindowInsetsController.Appearance;
116 import android.view.WindowInsetsController.Behavior;
117 import android.view.WindowManager;
118 import android.view.WindowManagerGlobal;
119 import android.view.accessibility.AccessibilityManager;
120 import android.widget.DateTimeView;
121 
122 import androidx.annotation.NonNull;
123 import androidx.lifecycle.Lifecycle;
124 import androidx.lifecycle.LifecycleOwner;
125 import androidx.lifecycle.LifecycleRegistry;
126 
127 import com.android.internal.annotations.VisibleForTesting;
128 import com.android.internal.colorextraction.ColorExtractor;
129 import com.android.internal.logging.MetricsLogger;
130 import com.android.internal.logging.UiEvent;
131 import com.android.internal.logging.UiEventLogger;
132 import com.android.internal.logging.UiEventLoggerImpl;
133 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
134 import com.android.internal.statusbar.IStatusBarService;
135 import com.android.internal.statusbar.RegisterStatusBarResult;
136 import com.android.internal.view.AppearanceRegion;
137 import com.android.keyguard.KeyguardUpdateMonitor;
138 import com.android.keyguard.KeyguardUpdateMonitorCallback;
139 import com.android.keyguard.ViewMediatorCallback;
140 import com.android.systemui.ActivityIntentHelper;
141 import com.android.systemui.AutoReinflateContainer;
142 import com.android.systemui.DejankUtils;
143 import com.android.systemui.Dumpable;
144 import com.android.systemui.EventLogTags;
145 import com.android.systemui.InitController;
146 import com.android.systemui.Prefs;
147 import com.android.systemui.R;
148 import com.android.systemui.SystemUI;
149 import com.android.systemui.accessibility.floatingmenu.AccessibilityFloatingMenuController;
150 import com.android.systemui.animation.ActivityLaunchAnimator;
151 import com.android.systemui.animation.DelegateLaunchAnimatorController;
152 import com.android.systemui.assist.AssistManager;
153 import com.android.systemui.biometrics.AuthRippleController;
154 import com.android.systemui.broadcast.BroadcastDispatcher;
155 import com.android.systemui.camera.CameraIntents;
156 import com.android.systemui.charging.WirelessChargingAnimation;
157 import com.android.systemui.classifier.FalsingCollector;
158 import com.android.systemui.colorextraction.SysuiColorExtractor;
159 import com.android.systemui.dagger.qualifiers.UiBackground;
160 import com.android.systemui.demomode.DemoMode;
161 import com.android.systemui.demomode.DemoModeCommandReceiver;
162 import com.android.systemui.demomode.DemoModeController;
163 import com.android.systemui.emergency.EmergencyGesture;
164 import com.android.systemui.fragments.ExtensionFragmentListener;
165 import com.android.systemui.fragments.FragmentHostManager;
166 import com.android.systemui.keyguard.DismissCallbackRegistry;
167 import com.android.systemui.keyguard.KeyguardService;
168 import com.android.systemui.keyguard.KeyguardUnlockAnimationController;
169 import com.android.systemui.keyguard.KeyguardViewMediator;
170 import com.android.systemui.keyguard.ScreenLifecycle;
171 import com.android.systemui.keyguard.WakefulnessLifecycle;
172 import com.android.systemui.navigationbar.NavigationBarController;
173 import com.android.systemui.navigationbar.NavigationBarView;
174 import com.android.systemui.plugins.ActivityStarter;
175 import com.android.systemui.plugins.DarkIconDispatcher;
176 import com.android.systemui.plugins.FalsingManager;
177 import com.android.systemui.plugins.OverlayPlugin;
178 import com.android.systemui.plugins.PluginDependencyProvider;
179 import com.android.systemui.plugins.PluginListener;
180 import com.android.systemui.plugins.qs.QS;
181 import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper.SnoozeOption;
182 import com.android.systemui.plugins.statusbar.StatusBarStateController;
183 import com.android.systemui.qs.QSFragment;
184 import com.android.systemui.qs.QSPanelController;
185 import com.android.systemui.recents.ScreenPinningRequest;
186 import com.android.systemui.scrim.ScrimView;
187 import com.android.systemui.settings.brightness.BrightnessSlider;
188 import com.android.systemui.shared.plugins.PluginManager;
189 import com.android.systemui.statusbar.AutoHideUiElement;
190 import com.android.systemui.statusbar.BackDropView;
191 import com.android.systemui.statusbar.CircleReveal;
192 import com.android.systemui.statusbar.CommandQueue;
193 import com.android.systemui.statusbar.FeatureFlags;
194 import com.android.systemui.statusbar.GestureRecorder;
195 import com.android.systemui.statusbar.KeyboardShortcuts;
196 import com.android.systemui.statusbar.KeyguardIndicationController;
197 import com.android.systemui.statusbar.LiftReveal;
198 import com.android.systemui.statusbar.LightRevealScrim;
199 import com.android.systemui.statusbar.LockscreenShadeTransitionController;
200 import com.android.systemui.statusbar.NotificationLockscreenUserManager;
201 import com.android.systemui.statusbar.NotificationMediaManager;
202 import com.android.systemui.statusbar.NotificationPresenter;
203 import com.android.systemui.statusbar.NotificationRemoteInputManager;
204 import com.android.systemui.statusbar.NotificationShadeDepthController;
205 import com.android.systemui.statusbar.NotificationShadeWindowController;
206 import com.android.systemui.statusbar.NotificationShelfController;
207 import com.android.systemui.statusbar.NotificationViewHierarchyManager;
208 import com.android.systemui.statusbar.PowerButtonReveal;
209 import com.android.systemui.statusbar.PulseExpansionHandler;
210 import com.android.systemui.statusbar.StatusBarState;
211 import com.android.systemui.statusbar.SuperStatusBarViewFactory;
212 import com.android.systemui.statusbar.SysuiStatusBarStateController;
213 import com.android.systemui.statusbar.VibratorHelper;
214 import com.android.systemui.statusbar.charging.WiredChargingRippleController;
215 import com.android.systemui.statusbar.events.SystemStatusAnimationScheduler;
216 import com.android.systemui.statusbar.notification.DynamicPrivacyController;
217 import com.android.systemui.statusbar.notification.NotificationActivityStarter;
218 import com.android.systemui.statusbar.notification.NotificationLaunchAnimatorControllerProvider;
219 import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator;
220 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
221 import com.android.systemui.statusbar.notification.collection.legacy.VisualStabilityManager;
222 import com.android.systemui.statusbar.notification.init.NotificationsController;
223 import com.android.systemui.statusbar.notification.interruption.BypassHeadsUpNotifier;
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.StatusBarComponent;
232 import com.android.systemui.statusbar.phone.dagger.StatusBarPhoneModule;
233 import com.android.systemui.statusbar.phone.ongoingcall.OngoingCallController;
234 import com.android.systemui.statusbar.policy.BatteryController;
235 import com.android.systemui.statusbar.policy.BrightnessMirrorController;
236 import com.android.systemui.statusbar.policy.ConfigurationController;
237 import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener;
238 import com.android.systemui.statusbar.policy.DeviceProvisionedController;
239 import com.android.systemui.statusbar.policy.DeviceProvisionedController.DeviceProvisionedListener;
240 import com.android.systemui.statusbar.policy.ExtensionController;
241 import com.android.systemui.statusbar.policy.KeyguardStateController;
242 import com.android.systemui.statusbar.policy.NetworkController;
243 import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener;
244 import com.android.systemui.statusbar.policy.RemoteInputQuickSettingsDisabler;
245 import com.android.systemui.statusbar.policy.UserInfoControllerImpl;
246 import com.android.systemui.statusbar.policy.UserSwitcherController;
247 import com.android.systemui.volume.VolumeComponent;
248 import com.android.systemui.wmshell.BubblesManager;
249 import com.android.wm.shell.bubbles.Bubbles;
250 import com.android.wm.shell.legacysplitscreen.LegacySplitScreen;
251 import com.android.wm.shell.startingsurface.SplashscreenContentDrawer;
252 import com.android.wm.shell.startingsurface.StartingSurface;
253 
254 import java.io.FileDescriptor;
255 import java.io.PrintWriter;
256 import java.io.StringWriter;
257 import java.util.ArrayList;
258 import java.util.List;
259 import java.util.Map;
260 import java.util.Optional;
261 import java.util.concurrent.Executor;
262 
263 import javax.inject.Named;
264 import javax.inject.Provider;
265 
266 import dagger.Lazy;
267 
268 public class StatusBar extends SystemUI implements DemoMode,
269         ActivityStarter, KeyguardStateController.Callback,
270         OnHeadsUpChangedListener, CommandQueue.Callbacks,
271         ColorExtractor.OnColorsChangedListener, ConfigurationListener,
272         StatusBarStateController.StateListener,
273         LifecycleOwner, BatteryController.BatteryStateChangeCallback,
274         ActivityLaunchAnimator.Callback {
275     public static final boolean MULTIUSER_DEBUG = false;
276 
277     protected static final int MSG_HIDE_RECENT_APPS = 1020;
278     protected static final int MSG_PRELOAD_RECENT_APPS = 1022;
279     protected static final int MSG_CANCEL_PRELOAD_RECENT_APPS = 1023;
280     protected static final int MSG_TOGGLE_KEYBOARD_SHORTCUTS_MENU = 1026;
281     protected static final int MSG_DISMISS_KEYBOARD_SHORTCUTS_MENU = 1027;
282 
283     // Should match the values in PhoneWindowManager
284     public static final String SYSTEM_DIALOG_REASON_HOME_KEY = "homekey";
285     public static final String SYSTEM_DIALOG_REASON_RECENT_APPS = "recentapps";
286     static public final String SYSTEM_DIALOG_REASON_SCREENSHOT = "screenshot";
287 
288     private static final String BANNER_ACTION_CANCEL =
289             "com.android.systemui.statusbar.banner_action_cancel";
290     private static final String BANNER_ACTION_SETUP =
291             "com.android.systemui.statusbar.banner_action_setup";
292     public static final String TAG = "StatusBar";
293     public static final boolean DEBUG = false;
294     public static final boolean SPEW = false;
295     public static final boolean DUMPTRUCK = true; // extra dumpsys info
296     public static final boolean DEBUG_GESTURES = false;
297     public static final boolean DEBUG_MEDIA_FAKE_ARTWORK = false;
298     public static final boolean DEBUG_CAMERA_LIFT = false;
299 
300     public static final boolean DEBUG_WINDOW_STATE = false;
301 
302     // additional instrumentation for testing purposes; intended to be left on during development
303     public static final boolean CHATTY = DEBUG;
304 
305     public static final boolean SHOW_LOCKSCREEN_MEDIA_ARTWORK = true;
306 
307     public static final String ACTION_FAKE_ARTWORK = "fake_artwork";
308 
309     private static final int MSG_OPEN_NOTIFICATION_PANEL = 1000;
310     private static final int MSG_CLOSE_PANELS = 1001;
311     private static final int MSG_OPEN_SETTINGS_PANEL = 1002;
312     private static final int MSG_LAUNCH_TRANSITION_TIMEOUT = 1003;
313     // 1020-1040 reserved for BaseStatusBar
314 
315     // Time after we abort the launch transition.
316     private static final long LAUNCH_TRANSITION_TIMEOUT_MS = 5000;
317 
318     protected static final boolean CLOSE_PANEL_WHEN_EMPTIED = true;
319 
320     /**
321      * The delay to reset the hint text when the hint animation is finished running.
322      */
323     private static final int HINT_RESET_DELAY_MS = 1200;
324 
325     private static final AudioAttributes VIBRATION_ATTRIBUTES = new AudioAttributes.Builder()
326             .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
327             .setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION)
328             .build();
329 
330     public static final int FADE_KEYGUARD_START_DELAY = 100;
331     public static final int FADE_KEYGUARD_DURATION = 300;
332     public static final int FADE_KEYGUARD_DURATION_PULSING = 96;
333 
334     public static final long[] CAMERA_LAUNCH_GESTURE_VIBRATION_TIMINGS =
335             new long[]{20, 20, 20, 20, 100, 20};
336     public static final int[] CAMERA_LAUNCH_GESTURE_VIBRATION_AMPLITUDES =
337             new int[]{39, 82, 139, 213, 0, 127};
338 
339     /**
340      * If true, the system is in the half-boot-to-decryption-screen state.
341      * Prudently disable QS and notifications.
342      */
343     public static final boolean ONLY_CORE_APPS;
344 
345     /** If true, the lockscreen will show a distinct wallpaper */
346     public static final boolean ENABLE_LOCKSCREEN_WALLPAPER = true;
347 
348     private static final UiEventLogger sUiEventLogger = new UiEventLoggerImpl();
349 
350     static {
351         boolean onlyCoreApps;
352         try {
353             IPackageManager packageManager =
354                     IPackageManager.Stub.asInterface(ServiceManager.getService("package"));
355             onlyCoreApps = packageManager.isOnlyCoreApps();
356         } catch (RemoteException e) {
357             onlyCoreApps = false;
358         }
359         ONLY_CORE_APPS = onlyCoreApps;
360     }
361 
362     private LockscreenShadeTransitionController mLockscreenShadeTransitionController;
363 
364     public interface ExpansionChangedListener {
onExpansionChanged(float expansion, boolean expanded)365         void onExpansionChanged(float expansion, boolean expanded);
366     }
367 
368     /**
369      * The {@link StatusBarState} of the status bar.
370      */
371     protected int mState; // TODO: remove this. Just use StatusBarStateController
372     protected boolean mBouncerShowing;
373 
374     private PhoneStatusBarPolicy mIconPolicy;
375     private StatusBarSignalPolicy mSignalPolicy;
376 
377     private final VolumeComponent mVolumeComponent;
378     private BrightnessMirrorController mBrightnessMirrorController;
379     private boolean mBrightnessMirrorVisible;
380     private BiometricUnlockController mBiometricUnlockController;
381     private final LightBarController mLightBarController;
382     private final Lazy<LockscreenWallpaper> mLockscreenWallpaperLazy;
383     @Nullable
384     protected LockscreenWallpaper mLockscreenWallpaper;
385     private final AutoHideController mAutoHideController;
386     @Nullable
387     private final KeyguardLiftController mKeyguardLiftController;
388 
389     private final Point mCurrentDisplaySize = new Point();
390 
391     protected NotificationShadeWindowView mNotificationShadeWindowView;
392     protected StatusBarWindowView mPhoneStatusBarWindow;
393     protected PhoneStatusBarView mStatusBarView;
394     private AuthRippleController mAuthRippleController;
395     private int mStatusBarWindowState = WINDOW_STATE_SHOWING;
396     protected NotificationShadeWindowController mNotificationShadeWindowController;
397     protected StatusBarWindowController mStatusBarWindowController;
398     private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
399     @VisibleForTesting
400     DozeServiceHost mDozeServiceHost;
401     private boolean mWakeUpComingFromTouch;
402     private PointF mWakeUpTouchLocation;
403     private LightRevealScrim mLightRevealScrim;
404     private WiredChargingRippleController mChargingRippleAnimationController;
405     private PowerButtonReveal mPowerButtonReveal;
406 
407     private final Object mQueueLock = new Object();
408 
409     private final PulseExpansionHandler mPulseExpansionHandler;
410     private final NotificationWakeUpCoordinator mWakeUpCoordinator;
411     private final KeyguardBypassController mKeyguardBypassController;
412     private final KeyguardStateController mKeyguardStateController;
413     private final HeadsUpManagerPhone mHeadsUpManager;
414     private final StatusBarTouchableRegionManager mStatusBarTouchableRegionManager;
415     private final DynamicPrivacyController mDynamicPrivacyController;
416     private final BypassHeadsUpNotifier mBypassHeadsUpNotifier;
417     private final FalsingCollector mFalsingCollector;
418     private final FalsingManager mFalsingManager;
419     private final BroadcastDispatcher mBroadcastDispatcher;
420     private final ConfigurationController mConfigurationController;
421     protected NotificationShadeWindowViewController mNotificationShadeWindowViewController;
422     private final DozeParameters mDozeParameters;
423     private final Lazy<BiometricUnlockController> mBiometricUnlockControllerLazy;
424     private final Provider<StatusBarComponent.Builder> mStatusBarComponentBuilder;
425     private final PluginManager mPluginManager;
426     private final Optional<LegacySplitScreen> mSplitScreenOptional;
427     private final StatusBarNotificationActivityStarter.Builder
428             mStatusBarNotificationActivityStarterBuilder;
429     private final ShadeController mShadeController;
430     private final SuperStatusBarViewFactory mSuperStatusBarViewFactory;
431     private final LightsOutNotifController mLightsOutNotifController;
432     private final InitController mInitController;
433 
434     private final PluginDependencyProvider mPluginDependencyProvider;
435     private final KeyguardDismissUtil mKeyguardDismissUtil;
436     private final ExtensionController mExtensionController;
437     private final UserInfoControllerImpl mUserInfoControllerImpl;
438     private final DismissCallbackRegistry mDismissCallbackRegistry;
439     private final DemoModeController mDemoModeController;
440     private NotificationsController mNotificationsController;
441     private final OngoingCallController mOngoingCallController;
442     private final SystemStatusAnimationScheduler mAnimationScheduler;
443     private final StatusBarLocationPublisher mStatusBarLocationPublisher;
444     private final StatusBarIconController mStatusBarIconController;
445 
446     // expanded notifications
447     // the sliding/resizing panel within the notification window
448     protected NotificationPanelViewController mNotificationPanelViewController;
449 
450     // settings
451     private QSPanelController mQSPanelController;
452 
453     KeyguardIndicationController mKeyguardIndicationController;
454 
455     private final RemoteInputQuickSettingsDisabler mRemoteInputQuickSettingsDisabler;
456 
457     private View mReportRejectedTouch;
458 
459     private boolean mExpandedVisible;
460 
461     private final int[] mAbsPos = new int[2];
462 
463     private final NotificationGutsManager mGutsManager;
464     private final NotificationLogger mNotificationLogger;
465     private final NotificationViewHierarchyManager mViewHierarchyManager;
466     private final KeyguardViewMediator mKeyguardViewMediator;
467     protected final NotificationInterruptStateProvider mNotificationInterruptStateProvider;
468     private final BrightnessSlider.Factory mBrightnessSliderFactory;
469     private final FeatureFlags mFeatureFlags;
470     private final KeyguardUnlockAnimationController mKeyguardUnlockAnimationController;
471     private final UnlockedScreenOffAnimationController mUnlockedScreenOffAnimationController;
472 
473     private final List<ExpansionChangedListener> mExpansionChangedListeners;
474 
475     // for disabling the status bar
476     private int mDisabled1 = 0;
477     private int mDisabled2 = 0;
478 
479     /** @see android.view.WindowInsetsController#setSystemBarsAppearance(int) */
480     private @Appearance int mAppearance;
481 
482     private boolean mTransientShown;
483 
484     private final DisplayMetrics mDisplayMetrics;
485 
486     // XXX: gesture research
487     private final GestureRecorder mGestureRec = DEBUG_GESTURES
488         ? new GestureRecorder("/sdcard/statusbar_gestures.dat")
489         : null;
490 
491     private final ScreenPinningRequest mScreenPinningRequest;
492 
493     private final MetricsLogger mMetricsLogger;
494 
495     // ensure quick settings is disabled until the current user makes it through the setup wizard
496     @VisibleForTesting
497     protected boolean mUserSetup = false;
498     private final DeviceProvisionedListener mUserSetupObserver = new DeviceProvisionedListener() {
499         @Override
500         public void onUserSetupChanged() {
501             final boolean userSetup = mDeviceProvisionedController.isUserSetup(
502                     mDeviceProvisionedController.getCurrentUser());
503             Log.d(TAG, "mUserSetupObserver - DeviceProvisionedListener called for user "
504                     + mDeviceProvisionedController.getCurrentUser());
505             if (MULTIUSER_DEBUG) {
506                 Log.d(TAG, String.format("User setup changed: userSetup=%s mUserSetup=%s",
507                         userSetup, mUserSetup));
508             }
509 
510             if (userSetup != mUserSetup) {
511                 mUserSetup = userSetup;
512                 if (!mUserSetup && mStatusBarView != null)
513                     animateCollapseQuickSettings();
514                 if (mNotificationPanelViewController != null) {
515                     mNotificationPanelViewController.setUserSetupComplete(mUserSetup);
516                 }
517                 updateQsExpansionEnabled();
518             }
519         }
520     };
521 
522     @VisibleForTesting
523     public enum StatusBarUiEvent implements UiEventLogger.UiEventEnum {
524         @UiEvent(doc = "Secured lockscreen is opened.")
525         LOCKSCREEN_OPEN_SECURE(405),
526 
527         @UiEvent(doc = "Lockscreen without security is opened.")
528         LOCKSCREEN_OPEN_INSECURE(406),
529 
530         @UiEvent(doc = "Secured lockscreen is closed.")
531         LOCKSCREEN_CLOSE_SECURE(407),
532 
533         @UiEvent(doc = "Lockscreen without security is closed.")
534         LOCKSCREEN_CLOSE_INSECURE(408),
535 
536         @UiEvent(doc = "Secured bouncer is opened.")
537         BOUNCER_OPEN_SECURE(409),
538 
539         @UiEvent(doc = "Bouncer without security is opened.")
540         BOUNCER_OPEN_INSECURE(410),
541 
542         @UiEvent(doc = "Secured bouncer is closed.")
543         BOUNCER_CLOSE_SECURE(411),
544 
545         @UiEvent(doc = "Bouncer without security is closed.")
546         BOUNCER_CLOSE_INSECURE(412);
547 
548         private final int mId;
549 
StatusBarUiEvent(int id)550         StatusBarUiEvent(int id) {
551             mId = id;
552         }
553 
554         @Override
getId()555         public int getId() {
556             return mId;
557         }
558     }
559 
560     protected final H mHandler = createHandler();
561 
562     private int mInteractingWindows;
563     private @TransitionMode int mStatusBarMode;
564 
565     private ViewMediatorCallback mKeyguardViewMediatorCallback;
566     private final ScrimController mScrimController;
567     protected DozeScrimController mDozeScrimController;
568     private final Executor mUiBgExecutor;
569 
570     protected boolean mDozing;
571 
572     private final NotificationMediaManager mMediaManager;
573     private final NotificationLockscreenUserManager mLockscreenUserManager;
574     private final NotificationRemoteInputManager mRemoteInputManager;
575     private boolean mWallpaperSupported;
576 
577     private final BroadcastReceiver mWallpaperChangedReceiver = new BroadcastReceiver() {
578         @Override
579         public void onReceive(Context context, Intent intent) {
580             if (!mWallpaperSupported) {
581                 // Receiver should not have been registered at all...
582                 Log.wtf(TAG, "WallpaperManager not supported");
583                 return;
584             }
585             WallpaperManager wallpaperManager = context.getSystemService(WallpaperManager.class);
586             WallpaperInfo info = wallpaperManager.getWallpaperInfo(UserHandle.USER_CURRENT);
587             final boolean deviceSupportsAodWallpaper = mContext.getResources().getBoolean(
588                     com.android.internal.R.bool.config_dozeSupportsAodWallpaper);
589             // If WallpaperInfo is null, it must be ImageWallpaper.
590             final boolean supportsAmbientMode = deviceSupportsAodWallpaper
591                     && (info != null && info.supportsAmbientMode());
592 
593             mNotificationShadeWindowController.setWallpaperSupportsAmbientMode(supportsAmbientMode);
594             mScrimController.setWallpaperSupportsAmbientMode(supportsAmbientMode);
595         }
596     };
597 
598     BroadcastReceiver mTaskbarChangeReceiver = new BroadcastReceiver() {
599         @Override
600         public void onReceive(Context context, Intent intent) {
601             if (mBubblesOptional.isPresent()) {
602                 mBubblesOptional.get().onTaskbarChanged(intent.getExtras());
603             }
604         }
605     };
606 
607     private Runnable mLaunchTransitionEndRunnable;
608     private NotificationEntry mDraggedDownEntry;
609     private boolean mLaunchCameraWhenFinishedWaking;
610     private boolean mLaunchCameraOnFinishedGoingToSleep;
611     private boolean mLaunchEmergencyActionWhenFinishedWaking;
612     private boolean mLaunchEmergencyActionOnFinishedGoingToSleep;
613     private int mLastCameraLaunchSource;
614     protected PowerManager.WakeLock mGestureWakeLock;
615     private Vibrator mVibrator;
616     private VibrationEffect mCameraLaunchGestureVibrationEffect;
617 
618     private final int[] mTmpInt2 = new int[2];
619 
620     // Fingerprint (as computed by getLoggingFingerprint() of the last logged state.
621     private int mLastLoggedStateFingerprint;
622     private boolean mTopHidesStatusBar;
623     private boolean mStatusBarWindowHidden;
624     private boolean mHideIconsForBouncer;
625     private boolean mIsOccluded;
626     private boolean mWereIconsJustHidden;
627     private boolean mBouncerWasShowingWhenHidden;
628 
629     // Notifies StatusBarKeyguardViewManager every time the keyguard transition is over,
630     // this animation is tied to the scrim for historic reasons.
631     // TODO: notify when keyguard has faded away instead of the scrim.
632     private final ScrimController.Callback mUnlockScrimCallback = new ScrimController
633             .Callback() {
634         @Override
635         public void onFinished() {
636             if (mStatusBarKeyguardViewManager == null) {
637                 Log.w(TAG, "Tried to notify keyguard visibility when "
638                         + "mStatusBarKeyguardViewManager was null");
639                 return;
640             }
641             if (mKeyguardStateController.isKeyguardFadingAway()) {
642                 mStatusBarKeyguardViewManager.onKeyguardFadedAway();
643             }
644         }
645 
646         @Override
647         public void onCancelled() {
648             onFinished();
649         }
650     };
651 
652     private final UserSwitcherController mUserSwitcherController;
653     private final NetworkController mNetworkController;
654     private final LifecycleRegistry mLifecycle = new LifecycleRegistry(this);
655     protected final BatteryController mBatteryController;
656     protected boolean mPanelExpanded;
657     private UiModeManager mUiModeManager;
658     protected boolean mIsKeyguard;
659     private LogMaker mStatusBarStateLog;
660     protected final NotificationIconAreaController mNotificationIconAreaController;
661     @Nullable private View mAmbientIndicationContainer;
662     private final SysuiColorExtractor mColorExtractor;
663     private final ScreenLifecycle mScreenLifecycle;
664     private final WakefulnessLifecycle mWakefulnessLifecycle;
665 
666     private boolean mNoAnimationOnNextBarModeChange;
667     private final SysuiStatusBarStateController mStatusBarStateController;
668 
669     private final KeyguardUpdateMonitorCallback mUpdateCallback =
670             new KeyguardUpdateMonitorCallback() {
671                 @Override
672                 public void onDreamingStateChanged(boolean dreaming) {
673                     if (dreaming) {
674                         maybeEscalateHeadsUp();
675                     }
676                 }
677 
678                 // TODO: (b/145659174) remove when moving to NewNotifPipeline. Replaced by
679                 //  KeyguardCoordinator
680                 @Override
681                 public void onStrongAuthStateChanged(int userId) {
682                     super.onStrongAuthStateChanged(userId);
683                     mNotificationsController.requestNotificationUpdate("onStrongAuthStateChanged");
684                 }
685             };
686 
687 
688     private final FalsingManager.FalsingBeliefListener mFalsingBeliefListener =
689             new FalsingManager.FalsingBeliefListener() {
690                 @Override
691                 public void onFalse() {
692                     // Hides quick settings, bouncer, and quick-quick settings.
693                     mStatusBarKeyguardViewManager.reset(true);
694                 }
695             };
696 
697     private final Handler mMainThreadHandler = new Handler(Looper.getMainLooper());
698 
699     private HeadsUpAppearanceController mHeadsUpAppearanceController;
700     private boolean mVibrateOnOpening;
701     private final VibratorHelper mVibratorHelper;
702     private ActivityLaunchAnimator mActivityLaunchAnimator;
703     private NotificationLaunchAnimatorControllerProvider mNotificationAnimationProvider;
704     protected StatusBarNotificationPresenter mPresenter;
705     private NotificationActivityStarter mNotificationActivityStarter;
706     private Lazy<NotificationShadeDepthController> mNotificationShadeDepthControllerLazy;
707     private final Optional<BubblesManager> mBubblesManagerOptional;
708     private final Optional<Bubbles> mBubblesOptional;
709     private final Bubbles.BubbleExpandListener mBubbleExpandListener;
710     private final Optional<StartingSurface> mStartingSurfaceOptional;
711 
712     private ActivityIntentHelper mActivityIntentHelper;
713     private NotificationStackScrollLayoutController mStackScrollerController;
714 
715     /**
716      * Public constructor for StatusBar.
717      *
718      * StatusBar is considered optional, and therefore can not be marked as @Inject directly.
719      * Instead, an @Provide method is included. See {@link StatusBarPhoneModule}.
720      */
721     @SuppressWarnings("OptionalUsedAsFieldOrParameterType")
StatusBar( Context context, NotificationsController notificationsController, LightBarController lightBarController, AutoHideController autoHideController, KeyguardUpdateMonitor keyguardUpdateMonitor, StatusBarSignalPolicy signalPolicy, PulseExpansionHandler pulseExpansionHandler, NotificationWakeUpCoordinator notificationWakeUpCoordinator, KeyguardBypassController keyguardBypassController, KeyguardStateController keyguardStateController, HeadsUpManagerPhone headsUpManagerPhone, DynamicPrivacyController dynamicPrivacyController, BypassHeadsUpNotifier bypassHeadsUpNotifier, FalsingManager falsingManager, FalsingCollector falsingCollector, BroadcastDispatcher broadcastDispatcher, RemoteInputQuickSettingsDisabler remoteInputQuickSettingsDisabler, NotificationGutsManager notificationGutsManager, NotificationLogger notificationLogger, NotificationInterruptStateProvider notificationInterruptStateProvider, NotificationViewHierarchyManager notificationViewHierarchyManager, KeyguardViewMediator keyguardViewMediator, DisplayMetrics displayMetrics, MetricsLogger metricsLogger, @UiBackground Executor uiBgExecutor, NotificationMediaManager notificationMediaManager, NotificationLockscreenUserManager lockScreenUserManager, NotificationRemoteInputManager remoteInputManager, UserSwitcherController userSwitcherController, NetworkController networkController, BatteryController batteryController, SysuiColorExtractor colorExtractor, ScreenLifecycle screenLifecycle, WakefulnessLifecycle wakefulnessLifecycle, SysuiStatusBarStateController statusBarStateController, VibratorHelper vibratorHelper, Optional<BubblesManager> bubblesManagerOptional, Optional<Bubbles> bubblesOptional, VisualStabilityManager visualStabilityManager, DeviceProvisionedController deviceProvisionedController, NavigationBarController navigationBarController, AccessibilityFloatingMenuController accessibilityFloatingMenuController, Lazy<AssistManager> assistManagerLazy, ConfigurationController configurationController, NotificationShadeWindowController notificationShadeWindowController, DozeParameters dozeParameters, ScrimController scrimController, @Nullable KeyguardLiftController keyguardLiftController, Lazy<LockscreenWallpaper> lockscreenWallpaperLazy, Lazy<BiometricUnlockController> biometricUnlockControllerLazy, DozeServiceHost dozeServiceHost, PowerManager powerManager, ScreenPinningRequest screenPinningRequest, DozeScrimController dozeScrimController, VolumeComponent volumeComponent, CommandQueue commandQueue, Provider<StatusBarComponent.Builder> statusBarComponentBuilder, PluginManager pluginManager, Optional<LegacySplitScreen> splitScreenOptional, LightsOutNotifController lightsOutNotifController, StatusBarNotificationActivityStarter.Builder statusBarNotificationActivityStarterBuilder, ShadeController shadeController, SuperStatusBarViewFactory superStatusBarViewFactory, StatusBarKeyguardViewManager statusBarKeyguardViewManager, ViewMediatorCallback viewMediatorCallback, InitController initController, @Named(TIME_TICK_HANDLER_NAME) Handler timeTickHandler, PluginDependencyProvider pluginDependencyProvider, KeyguardDismissUtil keyguardDismissUtil, ExtensionController extensionController, UserInfoControllerImpl userInfoControllerImpl, PhoneStatusBarPolicy phoneStatusBarPolicy, KeyguardIndicationController keyguardIndicationController, DismissCallbackRegistry dismissCallbackRegistry, DemoModeController demoModeController, Lazy<NotificationShadeDepthController> notificationShadeDepthControllerLazy, StatusBarTouchableRegionManager statusBarTouchableRegionManager, NotificationIconAreaController notificationIconAreaController, BrightnessSlider.Factory brightnessSliderFactory, WiredChargingRippleController chargingRippleAnimationController, OngoingCallController ongoingCallController, SystemStatusAnimationScheduler animationScheduler, StatusBarLocationPublisher locationPublisher, StatusBarIconController statusBarIconController, LockscreenShadeTransitionController lockscreenShadeTransitionController, FeatureFlags featureFlags, KeyguardUnlockAnimationController keyguardUnlockAnimationController, UnlockedScreenOffAnimationController unlockedScreenOffAnimationController, Optional<StartingSurface> startingSurfaceOptional)722     public StatusBar(
723             Context context,
724             NotificationsController notificationsController,
725             LightBarController lightBarController,
726             AutoHideController autoHideController,
727             KeyguardUpdateMonitor keyguardUpdateMonitor,
728             StatusBarSignalPolicy signalPolicy,
729             PulseExpansionHandler pulseExpansionHandler,
730             NotificationWakeUpCoordinator notificationWakeUpCoordinator,
731             KeyguardBypassController keyguardBypassController,
732             KeyguardStateController keyguardStateController,
733             HeadsUpManagerPhone headsUpManagerPhone,
734             DynamicPrivacyController dynamicPrivacyController,
735             BypassHeadsUpNotifier bypassHeadsUpNotifier,
736             FalsingManager falsingManager,
737             FalsingCollector falsingCollector,
738             BroadcastDispatcher broadcastDispatcher,
739             RemoteInputQuickSettingsDisabler remoteInputQuickSettingsDisabler,
740             NotificationGutsManager notificationGutsManager,
741             NotificationLogger notificationLogger,
742             NotificationInterruptStateProvider notificationInterruptStateProvider,
743             NotificationViewHierarchyManager notificationViewHierarchyManager,
744             KeyguardViewMediator keyguardViewMediator,
745             DisplayMetrics displayMetrics,
746             MetricsLogger metricsLogger,
747             @UiBackground Executor uiBgExecutor,
748             NotificationMediaManager notificationMediaManager,
749             NotificationLockscreenUserManager lockScreenUserManager,
750             NotificationRemoteInputManager remoteInputManager,
751             UserSwitcherController userSwitcherController,
752             NetworkController networkController,
753             BatteryController batteryController,
754             SysuiColorExtractor colorExtractor,
755             ScreenLifecycle screenLifecycle,
756             WakefulnessLifecycle wakefulnessLifecycle,
757             SysuiStatusBarStateController statusBarStateController,
758             VibratorHelper vibratorHelper,
759             Optional<BubblesManager> bubblesManagerOptional,
760             Optional<Bubbles> bubblesOptional,
761             VisualStabilityManager visualStabilityManager,
762             DeviceProvisionedController deviceProvisionedController,
763             NavigationBarController navigationBarController,
764             AccessibilityFloatingMenuController accessibilityFloatingMenuController,
765             Lazy<AssistManager> assistManagerLazy,
766             ConfigurationController configurationController,
767             NotificationShadeWindowController notificationShadeWindowController,
768             DozeParameters dozeParameters,
769             ScrimController scrimController,
770             @Nullable KeyguardLiftController keyguardLiftController,
771             Lazy<LockscreenWallpaper> lockscreenWallpaperLazy,
772             Lazy<BiometricUnlockController> biometricUnlockControllerLazy,
773             DozeServiceHost dozeServiceHost,
774             PowerManager powerManager,
775             ScreenPinningRequest screenPinningRequest,
776             DozeScrimController dozeScrimController,
777             VolumeComponent volumeComponent,
778             CommandQueue commandQueue,
779             Provider<StatusBarComponent.Builder> statusBarComponentBuilder,
780             PluginManager pluginManager,
781             Optional<LegacySplitScreen> splitScreenOptional,
782             LightsOutNotifController lightsOutNotifController,
783             StatusBarNotificationActivityStarter.Builder
784                     statusBarNotificationActivityStarterBuilder,
785             ShadeController shadeController,
786             SuperStatusBarViewFactory superStatusBarViewFactory,
787             StatusBarKeyguardViewManager statusBarKeyguardViewManager,
788             ViewMediatorCallback viewMediatorCallback,
789             InitController initController,
790             @Named(TIME_TICK_HANDLER_NAME) Handler timeTickHandler,
791             PluginDependencyProvider pluginDependencyProvider,
792             KeyguardDismissUtil keyguardDismissUtil,
793             ExtensionController extensionController,
794             UserInfoControllerImpl userInfoControllerImpl,
795             PhoneStatusBarPolicy phoneStatusBarPolicy,
796             KeyguardIndicationController keyguardIndicationController,
797             DismissCallbackRegistry dismissCallbackRegistry,
798             DemoModeController demoModeController,
799             Lazy<NotificationShadeDepthController> notificationShadeDepthControllerLazy,
800             StatusBarTouchableRegionManager statusBarTouchableRegionManager,
801             NotificationIconAreaController notificationIconAreaController,
802             BrightnessSlider.Factory brightnessSliderFactory,
803             WiredChargingRippleController chargingRippleAnimationController,
804             OngoingCallController ongoingCallController,
805             SystemStatusAnimationScheduler animationScheduler,
806             StatusBarLocationPublisher locationPublisher,
807             StatusBarIconController statusBarIconController,
808             LockscreenShadeTransitionController lockscreenShadeTransitionController,
809             FeatureFlags featureFlags,
810             KeyguardUnlockAnimationController keyguardUnlockAnimationController,
811             UnlockedScreenOffAnimationController unlockedScreenOffAnimationController,
812             Optional<StartingSurface> startingSurfaceOptional) {
813         super(context);
814         mNotificationsController = notificationsController;
815         mLightBarController = lightBarController;
816         mAutoHideController = autoHideController;
817         mKeyguardUpdateMonitor = keyguardUpdateMonitor;
818         mSignalPolicy = signalPolicy;
819         mPulseExpansionHandler = pulseExpansionHandler;
820         mWakeUpCoordinator = notificationWakeUpCoordinator;
821         mKeyguardBypassController = keyguardBypassController;
822         mKeyguardStateController = keyguardStateController;
823         mHeadsUpManager = headsUpManagerPhone;
824         mKeyguardIndicationController = keyguardIndicationController;
825         mStatusBarTouchableRegionManager = statusBarTouchableRegionManager;
826         mDynamicPrivacyController = dynamicPrivacyController;
827         mBypassHeadsUpNotifier = bypassHeadsUpNotifier;
828         mFalsingCollector = falsingCollector;
829         mFalsingManager = falsingManager;
830         mBroadcastDispatcher = broadcastDispatcher;
831         mRemoteInputQuickSettingsDisabler = remoteInputQuickSettingsDisabler;
832         mGutsManager = notificationGutsManager;
833         mNotificationLogger = notificationLogger;
834         mNotificationInterruptStateProvider = notificationInterruptStateProvider;
835         mViewHierarchyManager = notificationViewHierarchyManager;
836         mKeyguardViewMediator = keyguardViewMediator;
837         mDisplayMetrics = displayMetrics;
838         mMetricsLogger = metricsLogger;
839         mUiBgExecutor = uiBgExecutor;
840         mMediaManager = notificationMediaManager;
841         mLockscreenUserManager = lockScreenUserManager;
842         mRemoteInputManager = remoteInputManager;
843         mUserSwitcherController = userSwitcherController;
844         mNetworkController = networkController;
845         mBatteryController = batteryController;
846         mColorExtractor = colorExtractor;
847         mScreenLifecycle = screenLifecycle;
848         mWakefulnessLifecycle = wakefulnessLifecycle;
849         mStatusBarStateController = statusBarStateController;
850         mVibratorHelper = vibratorHelper;
851         mBubblesManagerOptional = bubblesManagerOptional;
852         mBubblesOptional = bubblesOptional;
853         mVisualStabilityManager = visualStabilityManager;
854         mDeviceProvisionedController = deviceProvisionedController;
855         mNavigationBarController = navigationBarController;
856         mAssistManagerLazy = assistManagerLazy;
857         mConfigurationController = configurationController;
858         mNotificationShadeWindowController = notificationShadeWindowController;
859         mDozeServiceHost = dozeServiceHost;
860         mPowerManager = powerManager;
861         mDozeParameters = dozeParameters;
862         mScrimController = scrimController;
863         mKeyguardLiftController = keyguardLiftController;
864         mLockscreenWallpaperLazy = lockscreenWallpaperLazy;
865         mScreenPinningRequest = screenPinningRequest;
866         mDozeScrimController = dozeScrimController;
867         mBiometricUnlockControllerLazy = biometricUnlockControllerLazy;
868         mNotificationShadeDepthControllerLazy = notificationShadeDepthControllerLazy;
869         mVolumeComponent = volumeComponent;
870         mCommandQueue = commandQueue;
871         mStatusBarComponentBuilder = statusBarComponentBuilder;
872         mPluginManager = pluginManager;
873         mSplitScreenOptional = splitScreenOptional;
874         mStatusBarNotificationActivityStarterBuilder = statusBarNotificationActivityStarterBuilder;
875         mShadeController = shadeController;
876         mSuperStatusBarViewFactory = superStatusBarViewFactory;
877         mLightsOutNotifController =  lightsOutNotifController;
878         mStatusBarKeyguardViewManager = statusBarKeyguardViewManager;
879         mKeyguardViewMediatorCallback = viewMediatorCallback;
880         mInitController = initController;
881         mPluginDependencyProvider = pluginDependencyProvider;
882         mKeyguardDismissUtil = keyguardDismissUtil;
883         mExtensionController = extensionController;
884         mUserInfoControllerImpl = userInfoControllerImpl;
885         mIconPolicy = phoneStatusBarPolicy;
886         mDismissCallbackRegistry = dismissCallbackRegistry;
887         mDemoModeController = demoModeController;
888         mNotificationIconAreaController = notificationIconAreaController;
889         mBrightnessSliderFactory = brightnessSliderFactory;
890         mChargingRippleAnimationController = chargingRippleAnimationController;
891         mOngoingCallController = ongoingCallController;
892         mAnimationScheduler = animationScheduler;
893         mStatusBarLocationPublisher = locationPublisher;
894         mStatusBarIconController = statusBarIconController;
895         mFeatureFlags = featureFlags;
896         mKeyguardUnlockAnimationController = keyguardUnlockAnimationController;
897         mUnlockedScreenOffAnimationController = unlockedScreenOffAnimationController;
898 
899         mLockscreenShadeTransitionController = lockscreenShadeTransitionController;
900         mStartingSurfaceOptional = startingSurfaceOptional;
901         lockscreenShadeTransitionController.setStatusbar(this);
902 
903         mExpansionChangedListeners = new ArrayList<>();
904 
905         mBubbleExpandListener =
906                 (isExpanding, key) -> {
907                     mContext.getMainExecutor().execute(() -> {
908                         mNotificationsController.requestNotificationUpdate("onBubbleExpandChanged");
909                         updateScrimController();
910                     });
911                 };
912 
913         mActivityIntentHelper = new ActivityIntentHelper(mContext);
914         DateTimeView.setReceiverHandler(timeTickHandler);
915     }
916 
917     @Override
start()918     public void start() {
919         mScreenLifecycle.addObserver(mScreenObserver);
920         mWakefulnessLifecycle.addObserver(mWakefulnessObserver);
921         mUiModeManager = mContext.getSystemService(UiModeManager.class);
922         mBypassHeadsUpNotifier.setUp();
923         if (mBubblesOptional.isPresent()) {
924             mBubblesOptional.get().setExpandListener(mBubbleExpandListener);
925             IntentFilter filter = new IntentFilter(TASKBAR_CHANGED_BROADCAST);
926             mBroadcastDispatcher.registerReceiver(mTaskbarChangeReceiver, filter);
927         }
928 
929         mKeyguardIndicationController.init();
930 
931         mColorExtractor.addOnColorsChangedListener(this);
932         mStatusBarStateController.addCallback(this,
933                 SysuiStatusBarStateController.RANK_STATUS_BAR);
934 
935         mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
936         mDreamManager = IDreamManager.Stub.asInterface(
937                 ServiceManager.checkService(DreamService.DREAM_SERVICE));
938 
939         mDisplay = mWindowManager.getDefaultDisplay();
940         mDisplayId = mDisplay.getDisplayId();
941         updateDisplaySize();
942 
943         mVibrateOnOpening = mContext.getResources().getBoolean(
944                 R.bool.config_vibrateOnIconAnimation);
945 
946         // start old BaseStatusBar.start().
947         mWindowManagerService = WindowManagerGlobal.getWindowManagerService();
948         mDevicePolicyManager = (DevicePolicyManager) mContext.getSystemService(
949                 Context.DEVICE_POLICY_SERVICE);
950 
951         mAccessibilityManager = (AccessibilityManager)
952                 mContext.getSystemService(Context.ACCESSIBILITY_SERVICE);
953 
954         mKeyguardUpdateMonitor.setKeyguardBypassController(mKeyguardBypassController);
955         mBarService = IStatusBarService.Stub.asInterface(
956                 ServiceManager.getService(Context.STATUS_BAR_SERVICE));
957 
958         mKeyguardManager = (KeyguardManager) mContext.getSystemService(Context.KEYGUARD_SERVICE);
959         mWallpaperSupported =
960                 mContext.getSystemService(WallpaperManager.class).isWallpaperSupported();
961 
962         // Connect in to the status bar manager service
963         mCommandQueue.addCallback(this);
964 
965         // Listen for demo mode changes
966         mDemoModeController.addCallback(this);
967 
968         RegisterStatusBarResult result = null;
969         try {
970             result = mBarService.registerStatusBar(mCommandQueue);
971         } catch (RemoteException ex) {
972             ex.rethrowFromSystemServer();
973         }
974 
975         createAndAddWindows(result);
976 
977         if (mWallpaperSupported) {
978             // Make sure we always have the most current wallpaper info.
979             IntentFilter wallpaperChangedFilter = new IntentFilter(Intent.ACTION_WALLPAPER_CHANGED);
980             mBroadcastDispatcher.registerReceiver(mWallpaperChangedReceiver, wallpaperChangedFilter,
981                     null /* handler */, UserHandle.ALL);
982             mWallpaperChangedReceiver.onReceive(mContext, null);
983         } else if (DEBUG) {
984             Log.v(TAG, "start(): no wallpaper service ");
985         }
986 
987         // Set up the initial notification state. This needs to happen before CommandQueue.disable()
988         setUpPresenter();
989 
990         if (containsType(result.mTransientBarTypes, ITYPE_STATUS_BAR)) {
991             showTransientUnchecked();
992         }
993         onSystemBarAttributesChanged(mDisplayId, result.mAppearance, result.mAppearanceRegions,
994                 result.mNavbarColorManagedByIme, result.mBehavior, result.mAppFullscreen);
995 
996         // StatusBarManagerService has a back up of IME token and it's restored here.
997         setImeWindowStatus(mDisplayId, result.mImeToken, result.mImeWindowVis,
998                 result.mImeBackDisposition, result.mShowImeSwitcher);
999 
1000         // Set up the initial icon state
1001         int numIcons = result.mIcons.size();
1002         for (int i = 0; i < numIcons; i++) {
1003             mCommandQueue.setIcon(result.mIcons.keyAt(i), result.mIcons.valueAt(i));
1004         }
1005 
1006 
1007         if (DEBUG) {
1008             Log.d(TAG, String.format(
1009                     "init: icons=%d disabled=0x%08x lights=0x%08x imeButton=0x%08x",
1010                     numIcons,
1011                     result.mDisabledFlags1,
1012                     result.mAppearance,
1013                     result.mImeWindowVis));
1014         }
1015 
1016         IntentFilter internalFilter = new IntentFilter();
1017         internalFilter.addAction(BANNER_ACTION_CANCEL);
1018         internalFilter.addAction(BANNER_ACTION_SETUP);
1019         mContext.registerReceiver(mBannerActionBroadcastReceiver, internalFilter, PERMISSION_SELF,
1020                 null);
1021 
1022         if (mWallpaperSupported) {
1023             IWallpaperManager wallpaperManager = IWallpaperManager.Stub.asInterface(
1024                     ServiceManager.getService(Context.WALLPAPER_SERVICE));
1025             try {
1026                 wallpaperManager.setInAmbientMode(false /* ambientMode */, 0L /* duration */);
1027             } catch (RemoteException e) {
1028                 // Just pass, nothing critical.
1029             }
1030         }
1031 
1032         // end old BaseStatusBar.start().
1033 
1034         // Lastly, call to the icon policy to install/update all the icons.
1035         mIconPolicy.init();
1036 
1037         mKeyguardStateController.addCallback(this);
1038         startKeyguard();
1039 
1040         mKeyguardUpdateMonitor.registerCallback(mUpdateCallback);
1041         mDozeServiceHost.initialize(
1042                 this,
1043                 mStatusBarKeyguardViewManager,
1044                 mNotificationShadeWindowViewController,
1045                 mNotificationPanelViewController,
1046                 mAmbientIndicationContainer);
1047         mDozeParameters.addCallback(this::updateLightRevealScrimVisibility);
1048 
1049         mConfigurationController.addCallback(this);
1050 
1051         mBatteryController.observe(mLifecycle, this);
1052         mLifecycle.setCurrentState(RESUMED);
1053 
1054         // set the initial view visibility
1055         int disabledFlags1 = result.mDisabledFlags1;
1056         int disabledFlags2 = result.mDisabledFlags2;
1057         mInitController.addPostInitTask(
1058                 () -> setUpDisableFlags(disabledFlags1, disabledFlags2));
1059 
1060         mFalsingManager.addFalsingBeliefListener(mFalsingBeliefListener);
1061 
1062         mPluginManager.addPluginListener(
1063                 new PluginListener<OverlayPlugin>() {
1064                     private ArraySet<OverlayPlugin> mOverlays = new ArraySet<>();
1065 
1066                     @Override
1067                     public void onPluginConnected(OverlayPlugin plugin, Context pluginContext) {
1068                         mMainThreadHandler.post(
1069                                 () -> plugin.setup(getNotificationShadeWindowView(),
1070                                         getNavigationBarView(),
1071                                         new Callback(plugin), mDozeParameters));
1072                     }
1073 
1074                     @Override
1075                     public void onPluginDisconnected(OverlayPlugin plugin) {
1076                         mMainThreadHandler.post(() -> {
1077                             mOverlays.remove(plugin);
1078                             mNotificationShadeWindowController
1079                                     .setForcePluginOpen(mOverlays.size() != 0, this);
1080                         });
1081                     }
1082 
1083                     class Callback implements OverlayPlugin.Callback {
1084                         private final OverlayPlugin mPlugin;
1085 
1086                         Callback(OverlayPlugin plugin) {
1087                             mPlugin = plugin;
1088                         }
1089 
1090                         @Override
1091                         public void onHoldStatusBarOpenChange() {
1092                             if (mPlugin.holdStatusBarOpen()) {
1093                                 mOverlays.add(mPlugin);
1094                             } else {
1095                                 mOverlays.remove(mPlugin);
1096                             }
1097                             mMainThreadHandler.post(() -> {
1098                                 mNotificationShadeWindowController
1099                                         .setStateListener(b -> mOverlays.forEach(
1100                                                 o -> o.setCollapseDesired(b)));
1101                                 mNotificationShadeWindowController
1102                                         .setForcePluginOpen(mOverlays.size() != 0, this);
1103                             });
1104                         }
1105                     }
1106                 }, OverlayPlugin.class, true /* Allow multiple plugins */);
1107     }
1108 
1109     // ================================================================================
1110     // Constructing the view
1111     // ================================================================================
makeStatusBarView(@ullable RegisterStatusBarResult result)1112     protected void makeStatusBarView(@Nullable RegisterStatusBarResult result) {
1113         final Context context = mContext;
1114         updateDisplaySize(); // populates mDisplayMetrics
1115         updateResources();
1116         updateTheme();
1117 
1118         inflateStatusBarWindow();
1119         mNotificationShadeWindowViewController.setService(this, mNotificationShadeWindowController);
1120         mNotificationShadeWindowView.setOnTouchListener(getStatusBarWindowTouchListener());
1121 
1122         // TODO: Deal with the ugliness that comes from having some of the statusbar broken out
1123         // into fragments, but the rest here, it leaves some awkward lifecycle and whatnot.
1124         mStackScrollerController =
1125                 mNotificationPanelViewController.getNotificationStackScrollLayoutController();
1126         mStackScroller = mStackScrollerController.getView();
1127         NotificationListContainer notifListContainer =
1128                 mStackScrollerController.getNotificationListContainer();
1129         mNotificationLogger.setUpWithContainer(notifListContainer);
1130 
1131         inflateShelf();
1132         mNotificationIconAreaController.setupShelf(mNotificationShelfController);
1133         mNotificationPanelViewController.addExpansionListener(mWakeUpCoordinator);
1134         mNotificationPanelViewController.addExpansionListener(
1135                 this::dispatchPanelExpansionForKeyguardDismiss);
1136 
1137         // Allow plugins to reference DarkIconDispatcher and StatusBarStateController
1138         mPluginDependencyProvider.allowPluginDependency(DarkIconDispatcher.class);
1139         mPluginDependencyProvider.allowPluginDependency(StatusBarStateController.class);
1140         FragmentHostManager.get(mPhoneStatusBarWindow)
1141                 .addTagListener(CollapsedStatusBarFragment.TAG, (tag, fragment) -> {
1142                     CollapsedStatusBarFragment statusBarFragment =
1143                             (CollapsedStatusBarFragment) fragment;
1144 
1145                     PhoneStatusBarView oldStatusBarView = mStatusBarView;
1146                     mStatusBarView = (PhoneStatusBarView) statusBarFragment.getView();
1147                     mStatusBarView.setBar(this);
1148                     mStatusBarView.setPanel(mNotificationPanelViewController);
1149                     mStatusBarView.setScrimController(mScrimController);
1150                     mStatusBarView.setExpansionChangedListeners(mExpansionChangedListeners);
1151 
1152                     // CollapsedStatusBarFragment re-inflated PhoneStatusBarView and both of
1153                     // mStatusBarView.mExpanded and mStatusBarView.mBouncerShowing are false.
1154                     // PhoneStatusBarView's new instance will set to be gone in
1155                     // PanelBar.updateVisibility after calling mStatusBarView.setBouncerShowing
1156                     // that will trigger PanelBar.updateVisibility. If there is a heads up showing,
1157                     // it needs to notify PhoneStatusBarView's new instance to update the correct
1158                     // status by calling mNotificationPanel.notifyBarPanelExpansionChanged().
1159                     if (mHeadsUpManager.hasPinnedHeadsUp()) {
1160                         mNotificationPanelViewController.notifyBarPanelExpansionChanged();
1161                     }
1162                     mStatusBarView.setBouncerShowing(mBouncerShowing);
1163                     if (oldStatusBarView != null) {
1164                         float fraction = oldStatusBarView.getExpansionFraction();
1165                         boolean expanded = oldStatusBarView.isExpanded();
1166                         mStatusBarView.panelExpansionChanged(fraction, expanded);
1167                     }
1168 
1169                     HeadsUpAppearanceController oldController = mHeadsUpAppearanceController;
1170                     if (mHeadsUpAppearanceController != null) {
1171                         // This view is being recreated, let's destroy the old one
1172                         mHeadsUpAppearanceController.destroy();
1173                     }
1174                     // TODO: this should probably be scoped to the StatusBarComponent
1175                     // TODO (b/136993073) Separate notification shade and status bar
1176                     mHeadsUpAppearanceController = new HeadsUpAppearanceController(
1177                             mNotificationIconAreaController, mHeadsUpManager,
1178                             mStackScroller.getController(),
1179                             mStatusBarStateController, mKeyguardBypassController,
1180                             mKeyguardStateController, mWakeUpCoordinator, mCommandQueue,
1181                             mNotificationPanelViewController, mStatusBarView);
1182                     mHeadsUpAppearanceController.readFrom(oldController);
1183 
1184                     mLightsOutNotifController.setLightsOutNotifView(
1185                             mStatusBarView.findViewById(R.id.notification_lights_out));
1186                     mNotificationShadeWindowViewController.setStatusBarView(mStatusBarView);
1187                     checkBarModes();
1188                 }).getFragmentManager()
1189                 .beginTransaction()
1190                 .replace(R.id.status_bar_container,
1191                         new CollapsedStatusBarFragment(
1192                                 mOngoingCallController,
1193                                 mAnimationScheduler,
1194                                 mStatusBarLocationPublisher,
1195                                 mNotificationIconAreaController,
1196                                 mFeatureFlags,
1197                                 mStatusBarIconController,
1198                                 mKeyguardStateController,
1199                                 mNetworkController,
1200                                 mStatusBarStateController,
1201                                 this,
1202                                 mCommandQueue
1203                         ),
1204                         CollapsedStatusBarFragment.TAG)
1205                 .commit();
1206 
1207         mHeadsUpManager.setup(mVisualStabilityManager);
1208         mStatusBarTouchableRegionManager.setup(this, mNotificationShadeWindowView);
1209         mHeadsUpManager.addListener(this);
1210         mHeadsUpManager.addListener(mNotificationPanelViewController.getOnHeadsUpChangedListener());
1211         mHeadsUpManager.addListener(mVisualStabilityManager);
1212         mNotificationPanelViewController.setHeadsUpManager(mHeadsUpManager);
1213 
1214         createNavigationBar(result);
1215 
1216         if (ENABLE_LOCKSCREEN_WALLPAPER && mWallpaperSupported) {
1217             mLockscreenWallpaper = mLockscreenWallpaperLazy.get();
1218         }
1219 
1220         mNotificationPanelViewController.setKeyguardIndicationController(
1221                 mKeyguardIndicationController);
1222 
1223         mAmbientIndicationContainer = mNotificationShadeWindowView.findViewById(
1224                 R.id.ambient_indication_container);
1225 
1226         mAutoHideController.setStatusBar(new AutoHideUiElement() {
1227             @Override
1228             public void synchronizeState() {
1229                 checkBarModes();
1230             }
1231 
1232             @Override
1233             public boolean shouldHideOnTouch() {
1234                 return !mRemoteInputManager.getController().isRemoteInputActive();
1235             }
1236 
1237             @Override
1238             public boolean isVisible() {
1239                 return isTransientShown();
1240             }
1241 
1242             @Override
1243             public void hide() {
1244                 clearTransient();
1245             }
1246         });
1247 
1248         ScrimView scrimBehind = mNotificationShadeWindowView.findViewById(R.id.scrim_behind);
1249         ScrimView notificationsScrim = mNotificationShadeWindowView
1250                 .findViewById(R.id.scrim_notifications);
1251         ScrimView scrimInFront = mNotificationShadeWindowView.findViewById(R.id.scrim_in_front);
1252         ScrimView scrimForBubble = mBubblesManagerOptional.isPresent()
1253                 ? mBubblesManagerOptional.get().getScrimForBubble() : null;
1254 
1255         mScrimController.setScrimVisibleListener(scrimsVisible -> {
1256             mNotificationShadeWindowController.setScrimsVisibility(scrimsVisible);
1257         });
1258         mScrimController.attachViews(scrimBehind, notificationsScrim, scrimInFront, scrimForBubble);
1259 
1260         mLightRevealScrim = mNotificationShadeWindowView.findViewById(R.id.light_reveal_scrim);
1261         mLightRevealScrim.setScrimOpaqueChangedListener((opaque) -> {
1262             Runnable updateOpaqueness = () -> {
1263                 mNotificationShadeWindowController.setLightRevealScrimOpaque(
1264                         mLightRevealScrim.isScrimOpaque());
1265             };
1266             if (opaque) {
1267                 // Delay making the view opaque for a frame, because it needs some time to render
1268                 // otherwise this can lead to a flicker where the scrim doesn't cover the screen
1269                 mLightRevealScrim.post(updateOpaqueness);
1270             } else {
1271                 updateOpaqueness.run();
1272             }
1273         });
1274         mUnlockedScreenOffAnimationController.initialize(this, mLightRevealScrim);
1275         updateLightRevealScrimVisibility();
1276 
1277         mNotificationPanelViewController.initDependencies(
1278                 this,
1279                 mNotificationShelfController);
1280 
1281         BackDropView backdrop = mNotificationShadeWindowView.findViewById(R.id.backdrop);
1282         mMediaManager.setup(backdrop, backdrop.findViewById(R.id.backdrop_front),
1283                 backdrop.findViewById(R.id.backdrop_back), mScrimController, mLockscreenWallpaper);
1284         float maxWallpaperZoom = mContext.getResources().getFloat(
1285                 com.android.internal.R.dimen.config_wallpaperMaxScale);
1286         mNotificationShadeDepthControllerLazy.get().addListener(depth -> {
1287             float scale = MathUtils.lerp(maxWallpaperZoom, 1f, depth);
1288             backdrop.setPivotX(backdrop.getWidth() / 2f);
1289             backdrop.setPivotY(backdrop.getHeight() / 2f);
1290             backdrop.setScaleX(scale);
1291             backdrop.setScaleY(scale);
1292         });
1293 
1294         mNotificationPanelViewController.setUserSetupComplete(mUserSetup);
1295 
1296         // Set up the quick settings tile panel
1297         final View container = mNotificationShadeWindowView.findViewById(R.id.qs_frame);
1298         if (container != null) {
1299             FragmentHostManager fragmentHostManager = FragmentHostManager.get(container);
1300             ExtensionFragmentListener.attachExtensonToFragment(container, QS.TAG, R.id.qs_frame,
1301                     mExtensionController
1302                             .newExtension(QS.class)
1303                             .withPlugin(QS.class)
1304                             .withDefault(this::createDefaultQSFragment)
1305                             .build());
1306             mBrightnessMirrorController = new BrightnessMirrorController(
1307                     mNotificationShadeWindowView,
1308                     mNotificationPanelViewController,
1309                     mNotificationShadeDepthControllerLazy.get(),
1310                     mBrightnessSliderFactory,
1311                     (visible) -> {
1312                         mBrightnessMirrorVisible = visible;
1313                         updateScrimController();
1314                     });
1315             fragmentHostManager.addTagListener(QS.TAG, (tag, f) -> {
1316                 QS qs = (QS) f;
1317                 if (qs instanceof QSFragment) {
1318                     mQSPanelController = ((QSFragment) qs).getQSPanelController();
1319                     mQSPanelController.setBrightnessMirror(mBrightnessMirrorController);
1320                 }
1321             });
1322         }
1323 
1324         mReportRejectedTouch = mNotificationShadeWindowView
1325                 .findViewById(R.id.report_rejected_touch);
1326         if (mReportRejectedTouch != null) {
1327             updateReportRejectedTouchVisibility();
1328             mReportRejectedTouch.setOnClickListener(v -> {
1329                 Uri session = mFalsingManager.reportRejectedTouch();
1330                 if (session == null) { return; }
1331 
1332                 StringWriter message = new StringWriter();
1333                 message.write("Build info: ");
1334                 message.write(SystemProperties.get("ro.build.description"));
1335                 message.write("\nSerial number: ");
1336                 message.write(SystemProperties.get("ro.serialno"));
1337                 message.write("\n");
1338 
1339                 startActivityDismissingKeyguard(Intent.createChooser(new Intent(Intent.ACTION_SEND)
1340                                 .setType("*/*")
1341                                 .putExtra(Intent.EXTRA_SUBJECT, "Rejected touch report")
1342                                 .putExtra(Intent.EXTRA_STREAM, session)
1343                                 .putExtra(Intent.EXTRA_TEXT, message.toString()),
1344                         "Share rejected touch report")
1345                                 .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK),
1346                         true /* onlyProvisioned */, true /* dismissShade */);
1347             });
1348         }
1349 
1350         if (!mPowerManager.isScreenOn()) {
1351             mBroadcastReceiver.onReceive(mContext, new Intent(Intent.ACTION_SCREEN_OFF));
1352         }
1353         mGestureWakeLock = mPowerManager.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK,
1354                 "GestureWakeLock");
1355         mVibrator = mContext.getSystemService(Vibrator.class);
1356         mCameraLaunchGestureVibrationEffect = getCameraGestureVibrationEffect(
1357                 mVibrator, context.getResources());
1358 
1359         // receive broadcasts
1360         registerBroadcastReceiver();
1361 
1362         IntentFilter demoFilter = new IntentFilter();
1363         if (DEBUG_MEDIA_FAKE_ARTWORK) {
1364             demoFilter.addAction(ACTION_FAKE_ARTWORK);
1365         }
1366         context.registerReceiverAsUser(mDemoReceiver, UserHandle.ALL, demoFilter,
1367                 android.Manifest.permission.DUMP, null);
1368 
1369         // listen for USER_SETUP_COMPLETE setting (per-user)
1370         mDeviceProvisionedController.addCallback(mUserSetupObserver);
1371         mUserSetupObserver.onUserSetupChanged();
1372 
1373         // disable profiling bars, since they overlap and clutter the output on app windows
1374         ThreadedRenderer.overrideProperty("disableProfileBars", "true");
1375 
1376         // Private API call to make the shadows look better for Recents
1377         ThreadedRenderer.overrideProperty("ambientRatio", String.valueOf(1.5f));
1378     }
1379 
1380 
1381     /**
1382      * When swiping up to dismiss the lock screen, the panel expansion goes from 1f to 0f. This
1383      * results in the clock/notifications/other content disappearing off the top of the screen.
1384      *
1385      * We also use the expansion amount to animate in the app/launcher surface from the bottom of
1386      * the screen, 'pushing' off the notifications and other content. To do this, we dispatch the
1387      * expansion amount to the KeyguardViewMediator if we're in the process of dismissing the
1388      * keyguard.
1389      */
dispatchPanelExpansionForKeyguardDismiss(float expansion, boolean trackingTouch)1390     private void dispatchPanelExpansionForKeyguardDismiss(float expansion, boolean trackingTouch) {
1391         // Things that mean we're not dismissing the keyguard, and should ignore this expansion:
1392         // - Keyguard isn't even visible.
1393         // - Keyguard is visible, but can't be dismissed (swiping up will show PIN/password prompt).
1394         // - QS is expanded and we're swiping - swiping up now will hide QS, not dismiss the
1395         //   keyguard.
1396         if (!isKeyguardShowing()
1397                 || !mKeyguardStateController.canDismissLockScreen()
1398                 || (mNotificationPanelViewController.isQsExpanded() && trackingTouch)) {
1399             return;
1400         }
1401 
1402         // Otherwise, we should let the keyguard know about this if we're tracking touch, or if we
1403         // are already animating the keyguard dismiss (since we will need to either finish or cancel
1404         // the animation).
1405         if (trackingTouch
1406                 || mKeyguardViewMediator.isAnimatingBetweenKeyguardAndSurfaceBehindOrWillBe()
1407                 || mKeyguardUnlockAnimationController.isUnlockingWithSmartSpaceTransition()) {
1408             mKeyguardStateController.notifyKeyguardDismissAmountChanged(
1409                     1f - expansion, trackingTouch);
1410         }
1411     }
1412 
1413     @NonNull
1414     @Override
getLifecycle()1415     public Lifecycle getLifecycle() {
1416         return mLifecycle;
1417     }
1418 
1419     @Override
onPowerSaveChanged(boolean isPowerSave)1420     public void onPowerSaveChanged(boolean isPowerSave) {
1421         mHandler.post(mCheckBarModes);
1422         if (mDozeServiceHost != null) {
1423             mDozeServiceHost.firePowerSaveChanged(isPowerSave);
1424         }
1425     }
1426 
1427     @Override
onBatteryLevelChanged(int level, boolean pluggedIn, boolean charging)1428     public void onBatteryLevelChanged(int level, boolean pluggedIn, boolean charging) {
1429         // noop
1430     }
1431 
1432     @VisibleForTesting
registerBroadcastReceiver()1433     protected void registerBroadcastReceiver() {
1434         IntentFilter filter = new IntentFilter();
1435         filter.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
1436         filter.addAction(Intent.ACTION_SCREEN_OFF);
1437         filter.addAction(DevicePolicyManager.ACTION_SHOW_DEVICE_MONITORING_DIALOG);
1438         mBroadcastDispatcher.registerReceiver(mBroadcastReceiver, filter, null, UserHandle.ALL);
1439     }
1440 
createDefaultQSFragment()1441     protected QS createDefaultQSFragment() {
1442         return FragmentHostManager.get(mNotificationShadeWindowView).create(QSFragment.class);
1443     }
1444 
setUpPresenter()1445     private void setUpPresenter() {
1446         // Set up the initial notification state.
1447         mActivityLaunchAnimator = new ActivityLaunchAnimator(this, mContext);
1448         mNotificationAnimationProvider = new NotificationLaunchAnimatorControllerProvider(
1449                 mNotificationShadeWindowViewController,
1450                 mStackScrollerController.getNotificationListContainer(),
1451                 mHeadsUpManager
1452         );
1453 
1454         // TODO: inject this.
1455         mPresenter = new StatusBarNotificationPresenter(mContext, mNotificationPanelViewController,
1456                 mHeadsUpManager, mNotificationShadeWindowView, mStackScrollerController,
1457                 mDozeScrimController, mScrimController, mNotificationShadeWindowController,
1458                 mDynamicPrivacyController, mKeyguardStateController,
1459                 mKeyguardIndicationController,
1460                 this /* statusBar */, mShadeController,
1461                 mLockscreenShadeTransitionController, mCommandQueue, mInitController,
1462                 mNotificationInterruptStateProvider);
1463 
1464         mNotificationShelfController.setOnActivatedListener(mPresenter);
1465         mRemoteInputManager.getController().addCallback(mNotificationShadeWindowController);
1466 
1467         mNotificationActivityStarter =
1468                 mStatusBarNotificationActivityStarterBuilder
1469                         .setStatusBar(this)
1470                         .setActivityLaunchAnimator(mActivityLaunchAnimator)
1471                         .setNotificationAnimatorControllerProvider(mNotificationAnimationProvider)
1472                         .setNotificationPresenter(mPresenter)
1473                         .setNotificationPanelViewController(mNotificationPanelViewController)
1474                         .build();
1475         mStackScroller.setNotificationActivityStarter(mNotificationActivityStarter);
1476         mGutsManager.setNotificationActivityStarter(mNotificationActivityStarter);
1477 
1478         mNotificationsController.initialize(
1479                 this,
1480                 mBubblesOptional,
1481                 mPresenter,
1482                 mStackScrollerController.getNotificationListContainer(),
1483                 mNotificationActivityStarter,
1484                 mPresenter);
1485     }
1486 
1487     /**
1488      * Post-init task of {@link #start()}
1489      * @param state1 disable1 flags
1490      * @param state2 disable2 flags
1491      */
setUpDisableFlags(int state1, int state2)1492     protected void setUpDisableFlags(int state1, int state2) {
1493         mCommandQueue.disable(mDisplayId, state1, state2, false /* animate */);
1494     }
1495 
1496     /**
1497      * Ask the display to wake up if currently dozing, else do nothing
1498      *
1499      * @param time when to wake up
1500      * @param where the view requesting the wakeup
1501      * @param why the reason for the wake up
1502      */
wakeUpIfDozing(long time, View where, String why)1503     public void wakeUpIfDozing(long time, View where, String why) {
1504         if (mDozing && !mUnlockedScreenOffAnimationController.isScreenOffAnimationPlaying()) {
1505             mPowerManager.wakeUp(
1506                     time, PowerManager.WAKE_REASON_GESTURE, "com.android.systemui:" + why);
1507             mWakeUpComingFromTouch = true;
1508             where.getLocationInWindow(mTmpInt2);
1509             mWakeUpTouchLocation = new PointF(mTmpInt2[0] + where.getWidth() / 2,
1510                     mTmpInt2[1] + where.getHeight() / 2);
1511             mFalsingCollector.onScreenOnFromTouch();
1512         }
1513     }
1514 
1515     // TODO(b/117478341): This was left such that CarStatusBar can override this method.
1516     // Try to remove this.
createNavigationBar(@ullable RegisterStatusBarResult result)1517     protected void createNavigationBar(@Nullable RegisterStatusBarResult result) {
1518         mNavigationBarController.createNavigationBars(true /* includeDefaultDisplay */, result);
1519     }
1520 
1521     /**
1522      * Returns the {@link android.view.View.OnTouchListener} that will be invoked when the
1523      * background window of the status bar is clicked.
1524      */
getStatusBarWindowTouchListener()1525     protected View.OnTouchListener getStatusBarWindowTouchListener() {
1526         return (v, event) -> {
1527             mAutoHideController.checkUserAutoHide(event);
1528             mRemoteInputManager.checkRemoteInputOutside(event);
1529             if (event.getAction() == MotionEvent.ACTION_DOWN) {
1530                 if (mExpandedVisible) {
1531                     mShadeController.animateCollapsePanels();
1532                 }
1533             }
1534             return mNotificationShadeWindowView.onTouchEvent(event);
1535         };
1536     }
1537 
inflateShelf()1538     private void inflateShelf() {
1539         mNotificationShelfController = mSuperStatusBarViewFactory
1540                 .getNotificationShelfController(mStackScroller);
1541     }
1542 
1543     @Override
onDensityOrFontScaleChanged()1544     public void onDensityOrFontScaleChanged() {
1545         // TODO: Remove this.
1546         if (mBrightnessMirrorController != null) {
1547             mBrightnessMirrorController.onDensityOrFontScaleChanged();
1548         }
1549         // TODO: Bring these out of StatusBar.
1550         mUserInfoControllerImpl.onDensityOrFontScaleChanged();
1551         mUserSwitcherController.onDensityOrFontScaleChanged();
1552         mNotificationIconAreaController.onDensityOrFontScaleChanged(mContext);
1553         mHeadsUpManager.onDensityOrFontScaleChanged();
1554     }
1555 
1556     @Override
onThemeChanged()1557     public void onThemeChanged() {
1558         if (mStatusBarKeyguardViewManager != null) {
1559             mStatusBarKeyguardViewManager.onThemeChanged();
1560         }
1561         if (mAmbientIndicationContainer instanceof AutoReinflateContainer) {
1562             ((AutoReinflateContainer) mAmbientIndicationContainer).inflateLayout();
1563         }
1564         mNotificationIconAreaController.onThemeChanged();
1565     }
1566 
1567     @Override
onOverlayChanged()1568     public void onOverlayChanged() {
1569         if (mBrightnessMirrorController != null) {
1570             mBrightnessMirrorController.onOverlayChanged();
1571         }
1572         // We need the new R.id.keyguard_indication_area before recreating
1573         // mKeyguardIndicationController
1574         mNotificationPanelViewController.onThemeChanged();
1575         onThemeChanged();
1576     }
1577 
1578     @Override
onUiModeChanged()1579     public void onUiModeChanged() {
1580         if (mBrightnessMirrorController != null) {
1581             mBrightnessMirrorController.onUiModeChanged();
1582         }
1583     }
1584 
inflateStatusBarWindow()1585     private void inflateStatusBarWindow() {
1586         mNotificationShadeWindowView = mSuperStatusBarViewFactory.getNotificationShadeWindowView();
1587         StatusBarComponent statusBarComponent = mStatusBarComponentBuilder.get()
1588                 .statusBarWindowView(mNotificationShadeWindowView).build();
1589         mNotificationShadeWindowViewController = statusBarComponent
1590                 .getNotificationShadeWindowViewController();
1591         mNotificationShadeWindowController.setNotificationShadeView(mNotificationShadeWindowView);
1592         mNotificationShadeWindowViewController.setupExpandedStatusBar();
1593         mStatusBarWindowController = statusBarComponent.getStatusBarWindowController();
1594         mPhoneStatusBarWindow = mSuperStatusBarViewFactory.getStatusBarWindowView();
1595         mNotificationPanelViewController = statusBarComponent.getNotificationPanelViewController();
1596         statusBarComponent.getLockIconViewController().init();
1597 
1598         mAuthRippleController = statusBarComponent.getAuthRippleController();
1599         mAuthRippleController.init();
1600     }
1601 
startKeyguard()1602     protected void startKeyguard() {
1603         Trace.beginSection("StatusBar#startKeyguard");
1604         mBiometricUnlockController = mBiometricUnlockControllerLazy.get();
1605         mBiometricUnlockController.setBiometricModeListener(
1606                 new BiometricUnlockController.BiometricModeListener() {
1607                     @Override
1608                     public void onResetMode() {
1609                         setWakeAndUnlocking(false);
1610                     }
1611 
1612                     @Override
1613                     public void onModeChanged(int mode) {
1614                         switch (mode) {
1615                             case BiometricUnlockController.MODE_WAKE_AND_UNLOCK_FROM_DREAM:
1616                             case BiometricUnlockController.MODE_WAKE_AND_UNLOCK_PULSING:
1617                             case BiometricUnlockController.MODE_WAKE_AND_UNLOCK:
1618                                 setWakeAndUnlocking(true);
1619                         }
1620                     }
1621 
1622                     @Override
1623                     public void notifyBiometricAuthModeChanged() {
1624                         StatusBar.this.notifyBiometricAuthModeChanged();
1625                     }
1626 
1627                     private void setWakeAndUnlocking(boolean wakeAndUnlocking) {
1628                         if (getNavigationBarView() != null) {
1629                             getNavigationBarView().setWakeAndUnlocking(wakeAndUnlocking);
1630                         }
1631                     }
1632                 });
1633         mStatusBarKeyguardViewManager.registerStatusBar(
1634                 /* statusBar= */ this, getBouncerContainer(),
1635                 mNotificationPanelViewController, mBiometricUnlockController,
1636                 mStackScroller, mKeyguardBypassController);
1637         mKeyguardIndicationController
1638                 .setStatusBarKeyguardViewManager(mStatusBarKeyguardViewManager);
1639         mBiometricUnlockController.setKeyguardViewController(mStatusBarKeyguardViewManager);
1640         mRemoteInputManager.getController().addCallback(mStatusBarKeyguardViewManager);
1641         mDynamicPrivacyController.setStatusBarKeyguardViewManager(mStatusBarKeyguardViewManager);
1642 
1643         mLightBarController.setBiometricUnlockController(mBiometricUnlockController);
1644         mMediaManager.setBiometricUnlockController(mBiometricUnlockController);
1645         mKeyguardDismissUtil.setDismissHandler(this::executeWhenUnlocked);
1646         Trace.endSection();
1647     }
1648 
getStatusBarView()1649     protected View getStatusBarView() {
1650         return mStatusBarView;
1651     }
1652 
getNotificationShadeWindowView()1653     public NotificationShadeWindowView getNotificationShadeWindowView() {
1654         return mNotificationShadeWindowView;
1655     }
1656 
getStatusBarWindow()1657     public StatusBarWindowView getStatusBarWindow() {
1658         return mPhoneStatusBarWindow;
1659     }
1660 
getNotificationShadeWindowViewController()1661     public NotificationShadeWindowViewController getNotificationShadeWindowViewController() {
1662         return mNotificationShadeWindowViewController;
1663     }
1664 
getNotificationPanelViewController()1665     public NotificationPanelViewController getNotificationPanelViewController() {
1666         return mNotificationPanelViewController;
1667     }
1668 
getBouncerContainer()1669     protected ViewGroup getBouncerContainer() {
1670         return mNotificationShadeWindowView;
1671     }
1672 
getStatusBarHeight()1673     public int getStatusBarHeight() {
1674         return mStatusBarWindowController.getStatusBarHeight();
1675     }
1676 
toggleSplitScreenMode(int metricsDockAction, int metricsUndockAction)1677     public boolean toggleSplitScreenMode(int metricsDockAction, int metricsUndockAction) {
1678         if (!mSplitScreenOptional.isPresent()) {
1679             return false;
1680         }
1681 
1682         final LegacySplitScreen legacySplitScreen = mSplitScreenOptional.get();
1683         if (legacySplitScreen.isDividerVisible()) {
1684             if (legacySplitScreen.isMinimized() && !legacySplitScreen.isHomeStackResizable()) {
1685                 // Undocking from the minimized state is not supported
1686                 return false;
1687             }
1688 
1689             legacySplitScreen.onUndockingTask();
1690             if (metricsUndockAction != -1) {
1691                 mMetricsLogger.action(metricsUndockAction);
1692             }
1693             return true;
1694         }
1695 
1696         if (legacySplitScreen.splitPrimaryTask()) {
1697             if (metricsDockAction != -1) {
1698                 mMetricsLogger.action(metricsDockAction);
1699             }
1700             return true;
1701         }
1702 
1703         return false;
1704     }
1705 
1706     /**
1707      * Disable QS if device not provisioned.
1708      * If the user switcher is simple then disable QS during setup because
1709      * the user intends to use the lock screen user switcher, QS in not needed.
1710      */
updateQsExpansionEnabled()1711     private void updateQsExpansionEnabled() {
1712         final boolean expandEnabled = mDeviceProvisionedController.isDeviceProvisioned()
1713                 && (mUserSetup || mUserSwitcherController == null
1714                         || !mUserSwitcherController.isSimpleUserSwitcher())
1715                 && !isShadeDisabled()
1716                 && ((mDisabled2 & StatusBarManager.DISABLE2_QUICK_SETTINGS) == 0)
1717                 && !mDozing
1718                 && !ONLY_CORE_APPS;
1719         mNotificationPanelViewController.setQsExpansionEnabledPolicy(expandEnabled);
1720         Log.d(TAG, "updateQsExpansionEnabled - QS Expand enabled: " + expandEnabled);
1721     }
1722 
isShadeDisabled()1723     public boolean isShadeDisabled() {
1724         return (mDisabled2 & StatusBarManager.DISABLE2_NOTIFICATION_SHADE) != 0;
1725     }
1726 
addQsTile(ComponentName tile)1727     public void addQsTile(ComponentName tile) {
1728         if (mQSPanelController != null && mQSPanelController.getHost() != null) {
1729             mQSPanelController.getHost().addTile(tile);
1730         }
1731     }
1732 
remQsTile(ComponentName tile)1733     public void remQsTile(ComponentName tile) {
1734         if (mQSPanelController != null && mQSPanelController.getHost() != null) {
1735             mQSPanelController.getHost().removeTile(tile);
1736         }
1737     }
1738 
clickTile(ComponentName tile)1739     public void clickTile(ComponentName tile) {
1740         mQSPanelController.clickTile(tile);
1741     }
1742 
1743     /**
1744      * Request a notification update
1745      * @param reason why we're requesting a notification update
1746      */
requestNotificationUpdate(String reason)1747     public void requestNotificationUpdate(String reason) {
1748         mNotificationsController.requestNotificationUpdate(reason);
1749     }
1750 
1751     /**
1752      * Asks {@link KeyguardUpdateMonitor} to run face auth.
1753      */
requestFaceAuth(boolean userInitiatedRequest)1754     public void requestFaceAuth(boolean userInitiatedRequest) {
1755         if (!mKeyguardStateController.canDismissLockScreen()) {
1756             mKeyguardUpdateMonitor.requestFaceAuth(userInitiatedRequest);
1757         }
1758     }
1759 
updateReportRejectedTouchVisibility()1760     private void updateReportRejectedTouchVisibility() {
1761         if (mReportRejectedTouch == null) {
1762             return;
1763         }
1764         mReportRejectedTouch.setVisibility(mState == StatusBarState.KEYGUARD && !mDozing
1765                 && mFalsingCollector.isReportingEnabled() ? View.VISIBLE : View.INVISIBLE);
1766     }
1767 
1768     /**
1769      * State is one or more of the DISABLE constants from StatusBarManager.
1770      */
1771     @Override
disable(int displayId, int state1, int state2, boolean animate)1772     public void disable(int displayId, int state1, int state2, boolean animate) {
1773         if (displayId != mDisplayId) {
1774             return;
1775         }
1776         state2 = mRemoteInputQuickSettingsDisabler.adjustDisableFlags(state2);
1777 
1778         animate &= mStatusBarWindowState != WINDOW_STATE_HIDDEN;
1779         final int old1 = mDisabled1;
1780         final int diff1 = state1 ^ old1;
1781         mDisabled1 = state1;
1782 
1783         final int old2 = mDisabled2;
1784         final int diff2 = state2 ^ old2;
1785         mDisabled2 = state2;
1786 
1787         if (DEBUG) {
1788             Log.d(TAG, String.format("disable1: 0x%08x -> 0x%08x (diff1: 0x%08x)",
1789                 old1, state1, diff1));
1790             Log.d(TAG, String.format("disable2: 0x%08x -> 0x%08x (diff2: 0x%08x)",
1791                 old2, state2, diff2));
1792         }
1793 
1794         StringBuilder flagdbg = new StringBuilder();
1795         flagdbg.append("disable<");
1796         flagdbg.append(0 != ((state1 & StatusBarManager.DISABLE_EXPAND))                ? 'E' : 'e');
1797         flagdbg.append(0 != ((diff1  & StatusBarManager.DISABLE_EXPAND))                ? '!' : ' ');
1798         flagdbg.append(0 != ((state1 & StatusBarManager.DISABLE_NOTIFICATION_ICONS))    ? 'I' : 'i');
1799         flagdbg.append(0 != ((diff1  & StatusBarManager.DISABLE_NOTIFICATION_ICONS))    ? '!' : ' ');
1800         flagdbg.append(0 != ((state1 & StatusBarManager.DISABLE_NOTIFICATION_ALERTS))   ? 'A' : 'a');
1801         flagdbg.append(0 != ((diff1  & StatusBarManager.DISABLE_NOTIFICATION_ALERTS))   ? '!' : ' ');
1802         flagdbg.append(0 != ((state1 & StatusBarManager.DISABLE_SYSTEM_INFO))           ? 'S' : 's');
1803         flagdbg.append(0 != ((diff1  & StatusBarManager.DISABLE_SYSTEM_INFO))           ? '!' : ' ');
1804         flagdbg.append(0 != ((state1 & StatusBarManager.DISABLE_BACK))                  ? 'B' : 'b');
1805         flagdbg.append(0 != ((diff1  & StatusBarManager.DISABLE_BACK))                  ? '!' : ' ');
1806         flagdbg.append(0 != ((state1 & StatusBarManager.DISABLE_HOME))                  ? 'H' : 'h');
1807         flagdbg.append(0 != ((diff1  & StatusBarManager.DISABLE_HOME))                  ? '!' : ' ');
1808         flagdbg.append(0 != ((state1 & StatusBarManager.DISABLE_RECENT))                ? 'R' : 'r');
1809         flagdbg.append(0 != ((diff1  & StatusBarManager.DISABLE_RECENT))                ? '!' : ' ');
1810         flagdbg.append(0 != ((state1 & StatusBarManager.DISABLE_CLOCK))                 ? 'C' : 'c');
1811         flagdbg.append(0 != ((diff1  & StatusBarManager.DISABLE_CLOCK))                 ? '!' : ' ');
1812         flagdbg.append(0 != ((state1 & StatusBarManager.DISABLE_SEARCH))                ? 'S' : 's');
1813         flagdbg.append(0 != ((diff1  & StatusBarManager.DISABLE_SEARCH))                ? '!' : ' ');
1814         flagdbg.append("> disable2<");
1815         flagdbg.append(0 != ((state2 & StatusBarManager.DISABLE2_QUICK_SETTINGS))       ? 'Q' : 'q');
1816         flagdbg.append(0 != ((diff2  & StatusBarManager.DISABLE2_QUICK_SETTINGS))       ? '!' : ' ');
1817         flagdbg.append(0 != ((state2 & StatusBarManager.DISABLE2_SYSTEM_ICONS))         ? 'I' : 'i');
1818         flagdbg.append(0 != ((diff2  & StatusBarManager.DISABLE2_SYSTEM_ICONS))         ? '!' : ' ');
1819         flagdbg.append(0 != ((state2 & StatusBarManager.DISABLE2_NOTIFICATION_SHADE))   ? 'N' : 'n');
1820         flagdbg.append(0 != ((diff2  & StatusBarManager.DISABLE2_NOTIFICATION_SHADE))   ? '!' : ' ');
1821         flagdbg.append('>');
1822         Log.d(TAG, flagdbg.toString());
1823 
1824         if ((diff1 & StatusBarManager.DISABLE_EXPAND) != 0) {
1825             if ((state1 & StatusBarManager.DISABLE_EXPAND) != 0) {
1826                 mShadeController.animateCollapsePanels();
1827             }
1828         }
1829 
1830         if ((diff1 & StatusBarManager.DISABLE_RECENT) != 0) {
1831             if ((state1 & StatusBarManager.DISABLE_RECENT) != 0) {
1832                 // close recents if it's visible
1833                 mHandler.removeMessages(MSG_HIDE_RECENT_APPS);
1834                 mHandler.sendEmptyMessage(MSG_HIDE_RECENT_APPS);
1835             }
1836         }
1837 
1838         if ((diff1 & StatusBarManager.DISABLE_NOTIFICATION_ALERTS) != 0) {
1839             if (areNotificationAlertsDisabled()) {
1840                 mHeadsUpManager.releaseAllImmediately();
1841             }
1842         }
1843 
1844         if ((diff2 & StatusBarManager.DISABLE2_QUICK_SETTINGS) != 0) {
1845             updateQsExpansionEnabled();
1846         }
1847 
1848         if ((diff2 & StatusBarManager.DISABLE2_NOTIFICATION_SHADE) != 0) {
1849             updateQsExpansionEnabled();
1850             if ((state2 & StatusBarManager.DISABLE2_NOTIFICATION_SHADE) != 0) {
1851                 mShadeController.animateCollapsePanels();
1852             }
1853         }
1854     }
1855 
areNotificationAlertsDisabled()1856     boolean areNotificationAlertsDisabled() {
1857         return (mDisabled1 & StatusBarManager.DISABLE_NOTIFICATION_ALERTS) != 0;
1858     }
1859 
createHandler()1860     protected H createHandler() {
1861         return new StatusBar.H();
1862     }
1863 
1864     @Override
startActivity(Intent intent, boolean onlyProvisioned, boolean dismissShade, int flags)1865     public void startActivity(Intent intent, boolean onlyProvisioned, boolean dismissShade,
1866             int flags) {
1867         startActivityDismissingKeyguard(intent, onlyProvisioned, dismissShade, flags);
1868     }
1869 
1870     @Override
startActivity(Intent intent, boolean dismissShade)1871     public void startActivity(Intent intent, boolean dismissShade) {
1872         startActivityDismissingKeyguard(intent, false /* onlyProvisioned */, dismissShade);
1873     }
1874 
1875     @Override
startActivity(Intent intent, boolean dismissShade, ActivityLaunchAnimator.Controller animationController)1876     public void startActivity(Intent intent, boolean dismissShade,
1877             ActivityLaunchAnimator.Controller animationController) {
1878         startActivityDismissingKeyguard(intent, false, dismissShade,
1879                 false /* disallowEnterPictureInPictureWhileLaunching */, null /* callback */,
1880                 0 /* flags */, animationController);
1881     }
1882 
1883     @Override
startActivity(Intent intent, boolean onlyProvisioned, boolean dismissShade)1884     public void startActivity(Intent intent, boolean onlyProvisioned, boolean dismissShade) {
1885         startActivityDismissingKeyguard(intent, onlyProvisioned, dismissShade);
1886     }
1887 
1888     @Override
startActivity(Intent intent, boolean dismissShade, Callback callback)1889     public void startActivity(Intent intent, boolean dismissShade, Callback callback) {
1890         startActivityDismissingKeyguard(intent, false, dismissShade,
1891                 false /* disallowEnterPictureInPictureWhileLaunching */, callback, 0,
1892                 null /* animationController */);
1893     }
1894 
setQsExpanded(boolean expanded)1895     public void setQsExpanded(boolean expanded) {
1896         mNotificationShadeWindowController.setQsExpanded(expanded);
1897         mNotificationPanelViewController.setStatusAccessibilityImportance(expanded
1898                 ? View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
1899                 : View.IMPORTANT_FOR_ACCESSIBILITY_AUTO);
1900         if (getNavigationBarView() != null) {
1901             getNavigationBarView().onStatusBarPanelStateChanged();
1902         }
1903     }
1904 
isWakeUpComingFromTouch()1905     public boolean isWakeUpComingFromTouch() {
1906         return mWakeUpComingFromTouch;
1907     }
1908 
isFalsingThresholdNeeded()1909     public boolean isFalsingThresholdNeeded() {
1910         return true;
1911     }
1912 
1913     /**
1914      * To be called when there's a state change in StatusBarKeyguardViewManager.
1915      */
onKeyguardViewManagerStatesUpdated()1916     public void onKeyguardViewManagerStatesUpdated() {
1917         logStateToEventlog();
1918     }
1919 
1920     @Override
onUnlockedChanged()1921     public void onUnlockedChanged() {
1922         updateKeyguardState();
1923         logStateToEventlog();
1924     }
1925 
1926     @Override
onHeadsUpPinnedModeChanged(boolean inPinnedMode)1927     public void onHeadsUpPinnedModeChanged(boolean inPinnedMode) {
1928         if (inPinnedMode) {
1929             mNotificationShadeWindowController.setHeadsUpShowing(true);
1930             mStatusBarWindowController.setForceStatusBarVisible(true);
1931             if (mNotificationPanelViewController.isFullyCollapsed()) {
1932                 // We need to ensure that the touchable region is updated before the window will be
1933                 // resized, in order to not catch any touches. A layout will ensure that
1934                 // onComputeInternalInsets will be called and after that we can resize the layout. Let's
1935                 // make sure that the window stays small for one frame until the touchableRegion is set.
1936                 mNotificationPanelViewController.getView().requestLayout();
1937                 mNotificationShadeWindowController.setForceWindowCollapsed(true);
1938                 mNotificationPanelViewController.getView().post(() -> {
1939                     mNotificationShadeWindowController.setForceWindowCollapsed(false);
1940                 });
1941             }
1942         } else {
1943             boolean bypassKeyguard = mKeyguardBypassController.getBypassEnabled()
1944                     && mState == StatusBarState.KEYGUARD;
1945             if (!mNotificationPanelViewController.isFullyCollapsed()
1946                     || mNotificationPanelViewController.isTracking() || bypassKeyguard) {
1947                 // We are currently tracking or is open and the shade doesn't need to be kept
1948                 // open artificially.
1949                 mNotificationShadeWindowController.setHeadsUpShowing(false);
1950                 if (bypassKeyguard) {
1951                     mStatusBarWindowController.setForceStatusBarVisible(false);
1952                 }
1953             } else {
1954                 // we need to keep the panel open artificially, let's wait until the animation
1955                 // is finished.
1956                 mHeadsUpManager.setHeadsUpGoingAway(true);
1957                 mNotificationPanelViewController.runAfterAnimationFinished(() -> {
1958                     if (!mHeadsUpManager.hasPinnedHeadsUp()) {
1959                         mNotificationShadeWindowController.setHeadsUpShowing(false);
1960                         mHeadsUpManager.setHeadsUpGoingAway(false);
1961                     }
1962                     mRemoteInputManager.onPanelCollapsed();
1963                 });
1964             }
1965         }
1966     }
1967 
1968     @Override
onHeadsUpStateChanged(NotificationEntry entry, boolean isHeadsUp)1969     public void onHeadsUpStateChanged(NotificationEntry entry, boolean isHeadsUp) {
1970         mNotificationsController.requestNotificationUpdate("onHeadsUpStateChanged");
1971         if (mStatusBarStateController.isDozing() && isHeadsUp) {
1972             entry.setPulseSuppressed(false);
1973             mDozeServiceHost.fireNotificationPulse(entry);
1974             if (mDozeServiceHost.isPulsing()) {
1975                 mDozeScrimController.cancelPendingPulseTimeout();
1976             }
1977         }
1978         if (!isHeadsUp && !mHeadsUpManager.hasNotifications()) {
1979             // There are no longer any notifications to show.  We should end the pulse now.
1980             mDozeScrimController.pulseOutNow();
1981         }
1982     }
1983 
setPanelExpanded(boolean isExpanded)1984     public void setPanelExpanded(boolean isExpanded) {
1985         if (mPanelExpanded != isExpanded) {
1986             mNotificationLogger.onPanelExpandedChanged(isExpanded);
1987         }
1988         mPanelExpanded = isExpanded;
1989         updateHideIconsForBouncer(false /* animate */);
1990         mNotificationShadeWindowController.setPanelExpanded(isExpanded);
1991         mStatusBarStateController.setPanelExpanded(isExpanded);
1992         if (isExpanded && mStatusBarStateController.getState() != StatusBarState.KEYGUARD) {
1993             if (DEBUG) {
1994                 Log.v(TAG, "clearing notification effects from Height");
1995             }
1996             clearNotificationEffects();
1997         }
1998 
1999         if (!isExpanded) {
2000             mRemoteInputManager.onPanelCollapsed();
2001         }
2002     }
2003 
getNotificationScrollLayout()2004     public ViewGroup getNotificationScrollLayout() {
2005         return mStackScroller;
2006     }
2007 
isPulsing()2008     public boolean isPulsing() {
2009         return mDozeServiceHost.isPulsing();
2010     }
2011 
hideStatusBarIconsWhenExpanded()2012     public boolean hideStatusBarIconsWhenExpanded() {
2013         return mNotificationPanelViewController.hideStatusBarIconsWhenExpanded();
2014     }
2015 
2016     @Override
onColorsChanged(ColorExtractor extractor, int which)2017     public void onColorsChanged(ColorExtractor extractor, int which) {
2018         updateTheme();
2019     }
2020 
2021     @Nullable
getAmbientIndicationContainer()2022     public View getAmbientIndicationContainer() {
2023         return mAmbientIndicationContainer;
2024     }
2025 
2026     /**
2027      * When the keyguard is showing and covered by a "showWhenLocked" activity it
2028      * is occluded. This is controlled by {@link com.android.server.policy.PhoneWindowManager}
2029      *
2030      * @return whether the keyguard is currently occluded
2031      */
isOccluded()2032     public boolean isOccluded() {
2033         return mIsOccluded;
2034     }
2035 
setOccluded(boolean occluded)2036     public void setOccluded(boolean occluded) {
2037         mIsOccluded = occluded;
2038         mScrimController.setKeyguardOccluded(occluded);
2039         updateHideIconsForBouncer(false /* animate */);
2040     }
2041 
hideStatusBarIconsForBouncer()2042     public boolean hideStatusBarIconsForBouncer() {
2043         return mHideIconsForBouncer || mWereIconsJustHidden;
2044     }
2045 
2046     /**
2047      * Decides if the status bar (clock + notifications + signal cluster) should be visible
2048      * or not when showing the bouncer.
2049      *
2050      * We want to hide it when:
2051      * • User swipes up on the keyguard
2052      * • Locked activity that doesn't show a status bar requests the bouncer
2053      *
2054      * @param animate should the change of the icons be animated.
2055      */
updateHideIconsForBouncer(boolean animate)2056     private void updateHideIconsForBouncer(boolean animate) {
2057         boolean hideBecauseApp = mTopHidesStatusBar && mIsOccluded
2058                 && (mStatusBarWindowHidden || mBouncerShowing);
2059         boolean hideBecauseKeyguard = !mPanelExpanded && !mIsOccluded && mBouncerShowing;
2060         boolean shouldHideIconsForBouncer = hideBecauseApp || hideBecauseKeyguard;
2061         if (mHideIconsForBouncer != shouldHideIconsForBouncer) {
2062             mHideIconsForBouncer = shouldHideIconsForBouncer;
2063             if (!shouldHideIconsForBouncer && mBouncerWasShowingWhenHidden) {
2064                 // We're delaying the showing, since most of the time the fullscreen app will
2065                 // hide the icons again and we don't want them to fade in and out immediately again.
2066                 mWereIconsJustHidden = true;
2067                 mHandler.postDelayed(() -> {
2068                     mWereIconsJustHidden = false;
2069                     mCommandQueue.recomputeDisableFlags(mDisplayId, true);
2070                 }, 500);
2071             } else {
2072                 mCommandQueue.recomputeDisableFlags(mDisplayId, animate);
2073             }
2074         }
2075         if (shouldHideIconsForBouncer) {
2076             mBouncerWasShowingWhenHidden = mBouncerShowing;
2077         }
2078     }
2079 
headsUpShouldBeVisible()2080     public boolean headsUpShouldBeVisible() {
2081         return mHeadsUpAppearanceController.shouldBeVisible();
2082     }
2083 
2084     /** A launch animation was cancelled. */
2085     //TODO: These can / should probably be moved to NotificationPresenter or ShadeController
onLaunchAnimationCancelled(boolean isLaunchForActivity)2086     public void onLaunchAnimationCancelled(boolean isLaunchForActivity) {
2087         if (mPresenter.isPresenterFullyCollapsed() && !mPresenter.isCollapsing()
2088                 && isLaunchForActivity) {
2089             onClosingFinished();
2090         } else {
2091             mShadeController.collapsePanel(true /* animate */);
2092         }
2093     }
2094 
2095     /** A launch animation ended. */
onLaunchAnimationEnd(boolean launchIsFullScreen)2096     public void onLaunchAnimationEnd(boolean launchIsFullScreen) {
2097         if (!mPresenter.isCollapsing()) {
2098             onClosingFinished();
2099         }
2100         if (launchIsFullScreen) {
2101             instantCollapseNotificationPanel();
2102         }
2103     }
2104 
2105     /**
2106      * Whether we should animate an activity launch.
2107      *
2108      * Note: This method must be called *before* dismissing the keyguard.
2109      */
shouldAnimateLaunch(boolean isActivityIntent)2110     public boolean shouldAnimateLaunch(boolean isActivityIntent) {
2111         // TODO(b/184121838): Support launch animations when occluded.
2112         if (isOccluded()) {
2113             return false;
2114         }
2115 
2116         // Always animate if we are unlocked.
2117         if (!mKeyguardStateController.isShowing()) {
2118             return true;
2119         }
2120 
2121         // If we are locked, only animate if remote unlock animations are enabled. We also don't
2122         // animate non-activity launches as they can break the animation.
2123         // TODO(b/184121838): Support non activity launches on the lockscreen.
2124         return isActivityIntent && KeyguardService.sEnableRemoteKeyguardGoingAwayAnimation;
2125     }
2126 
2127     @Override
isOnKeyguard()2128     public boolean isOnKeyguard() {
2129         return mKeyguardStateController.isShowing();
2130     }
2131 
2132     @Override
hideKeyguardWithAnimation(IRemoteAnimationRunner runner)2133     public void hideKeyguardWithAnimation(IRemoteAnimationRunner runner) {
2134         // We post to the main thread for 2 reasons:
2135         //   1. KeyguardViewMediator is not thread-safe.
2136         //   2. To ensure that ViewMediatorCallback#keyguardDonePending is called before
2137         //      ViewMediatorCallback#readyForKeyguardDone. The wrong order could occur when doing
2138         //      dismissKeyguardThenExecute { hideKeyguardWithAnimation(runner) }.
2139         mMainThreadHandler.post(() -> mKeyguardViewMediator.hideWithAnimation(runner));
2140     }
2141 
2142     @Override
setBlursDisabledForAppLaunch(boolean disabled)2143     public void setBlursDisabledForAppLaunch(boolean disabled) {
2144         mKeyguardViewMediator.setBlursDisabledForAppLaunch(disabled);
2145     }
2146 
2147     @Override
getBackgroundColor(TaskInfo task)2148     public int getBackgroundColor(TaskInfo task) {
2149         if (!mStartingSurfaceOptional.isPresent()) {
2150             Log.w(TAG, "No starting surface, defaulting to SystemBGColor");
2151             return SplashscreenContentDrawer.getSystemBGColor();
2152         }
2153 
2154         return mStartingSurfaceOptional.get().getBackgroundColor(task);
2155     }
2156 
isDeviceInVrMode()2157     public boolean isDeviceInVrMode() {
2158         return mPresenter.isDeviceInVrMode();
2159     }
2160 
getPresenter()2161     public NotificationPresenter getPresenter() {
2162         return mPresenter;
2163     }
2164 
2165     @VisibleForTesting
setBarStateForTest(int state)2166     void setBarStateForTest(int state) {
2167         mState = state;
2168     }
2169 
2170     @VisibleForTesting
setUserSetupForTest(boolean userSetup)2171     void setUserSetupForTest(boolean userSetup) {
2172         mUserSetup = userSetup;
2173     }
2174 
2175     /**
2176      * All changes to the status bar and notifications funnel through here and are batched.
2177      */
2178     protected class H extends Handler {
2179         @Override
handleMessage(Message m)2180         public void handleMessage(Message m) {
2181             switch (m.what) {
2182                 case MSG_TOGGLE_KEYBOARD_SHORTCUTS_MENU:
2183                     toggleKeyboardShortcuts(m.arg1);
2184                     break;
2185                 case MSG_DISMISS_KEYBOARD_SHORTCUTS_MENU:
2186                     dismissKeyboardShortcuts();
2187                     break;
2188                 // End old BaseStatusBar.H handling.
2189                 case MSG_OPEN_NOTIFICATION_PANEL:
2190                     animateExpandNotificationsPanel();
2191                     break;
2192                 case MSG_OPEN_SETTINGS_PANEL:
2193                     animateExpandSettingsPanel((String) m.obj);
2194                     break;
2195                 case MSG_CLOSE_PANELS:
2196                     mShadeController.animateCollapsePanels();
2197                     break;
2198                 case MSG_LAUNCH_TRANSITION_TIMEOUT:
2199                     onLaunchTransitionTimeout();
2200                     break;
2201             }
2202         }
2203     }
2204 
maybeEscalateHeadsUp()2205     public void maybeEscalateHeadsUp() {
2206         mHeadsUpManager.getAllEntries().forEach(entry -> {
2207             final StatusBarNotification sbn = entry.getSbn();
2208             final Notification notification = sbn.getNotification();
2209             if (notification.fullScreenIntent != null) {
2210                 if (DEBUG) {
2211                     Log.d(TAG, "converting a heads up to fullScreen");
2212                 }
2213                 try {
2214                     EventLog.writeEvent(EventLogTags.SYSUI_HEADS_UP_ESCALATION,
2215                             sbn.getKey());
2216                     notification.fullScreenIntent.send();
2217                     entry.notifyFullScreenIntentLaunched();
2218                 } catch (PendingIntent.CanceledException e) {
2219                 }
2220             }
2221         });
2222         mHeadsUpManager.releaseAllImmediately();
2223     }
2224 
2225     /**
2226      * Called for system navigation gestures. First action opens the panel, second opens
2227      * settings. Down action closes the entire panel.
2228      */
2229     @Override
handleSystemKey(int key)2230     public void handleSystemKey(int key) {
2231         if (SPEW) Log.d(TAG, "handleNavigationKey: " + key);
2232         if (!mCommandQueue.panelsEnabled() || !mKeyguardUpdateMonitor.isDeviceInteractive()
2233                 || mKeyguardStateController.isShowing() && !mKeyguardStateController.isOccluded()) {
2234             return;
2235         }
2236 
2237         // Panels are not available in setup
2238         if (!mUserSetup) return;
2239 
2240         if (KeyEvent.KEYCODE_SYSTEM_NAVIGATION_UP == key) {
2241             mMetricsLogger.action(MetricsEvent.ACTION_SYSTEM_NAVIGATION_KEY_UP);
2242             mNotificationPanelViewController.collapse(
2243                     false /* delayed */, 1.0f /* speedUpFactor */);
2244         } else if (KeyEvent.KEYCODE_SYSTEM_NAVIGATION_DOWN == key) {
2245             mMetricsLogger.action(MetricsEvent.ACTION_SYSTEM_NAVIGATION_KEY_DOWN);
2246             if (mNotificationPanelViewController.isFullyCollapsed()) {
2247                 if (mVibrateOnOpening) {
2248                     mVibratorHelper.vibrate(VibrationEffect.EFFECT_TICK);
2249                 }
2250                 mNotificationPanelViewController.expand(true /* animate */);
2251                 mStackScroller.setWillExpand(true);
2252                 mHeadsUpManager.unpinAll(true /* userUnpinned */);
2253                 mMetricsLogger.count(NotificationPanelView.COUNTER_PANEL_OPEN, 1);
2254             } else if (!mNotificationPanelViewController.isInSettings()
2255                     && !mNotificationPanelViewController.isExpanding()) {
2256                 mNotificationPanelViewController.flingSettings(0 /* velocity */,
2257                         NotificationPanelView.FLING_EXPAND);
2258                 mMetricsLogger.count(NotificationPanelView.COUNTER_PANEL_OPEN_QS, 1);
2259             }
2260         }
2261 
2262     }
2263 
2264     @Override
showPinningEnterExitToast(boolean entering)2265     public void showPinningEnterExitToast(boolean entering) {
2266         if (getNavigationBarView() != null) {
2267             getNavigationBarView().showPinningEnterExitToast(entering);
2268         }
2269     }
2270 
2271     @Override
showPinningEscapeToast()2272     public void showPinningEscapeToast() {
2273         if (getNavigationBarView() != null) {
2274             getNavigationBarView().showPinningEscapeToast();
2275         }
2276     }
2277 
makeExpandedVisible(boolean force)2278     void makeExpandedVisible(boolean force) {
2279         if (SPEW) Log.d(TAG, "Make expanded visible: expanded visible=" + mExpandedVisible);
2280         if (!force && (mExpandedVisible || !mCommandQueue.panelsEnabled())) {
2281             return;
2282         }
2283 
2284         mExpandedVisible = true;
2285 
2286         // Expand the window to encompass the full screen in anticipation of the drag.
2287         // This is only possible to do atomically because the status bar is at the top of the screen!
2288         mNotificationShadeWindowController.setPanelVisible(true);
2289 
2290         visibilityChanged(true);
2291         mCommandQueue.recomputeDisableFlags(mDisplayId, !force /* animate */);
2292         setInteracting(StatusBarManager.WINDOW_STATUS_BAR, true);
2293     }
2294 
postAnimateCollapsePanels()2295     public void postAnimateCollapsePanels() {
2296         mHandler.post(mShadeController::animateCollapsePanels);
2297     }
2298 
postAnimateForceCollapsePanels()2299     public void postAnimateForceCollapsePanels() {
2300         mHandler.post(() -> mShadeController.animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_NONE,
2301                 true /* force */));
2302     }
2303 
postAnimateOpenPanels()2304     public void postAnimateOpenPanels() {
2305         mHandler.sendEmptyMessage(MSG_OPEN_SETTINGS_PANEL);
2306     }
2307 
2308     @Override
togglePanel()2309     public void togglePanel() {
2310         if (mPanelExpanded) {
2311             mShadeController.animateCollapsePanels();
2312         } else {
2313             animateExpandNotificationsPanel();
2314         }
2315     }
2316 
2317     @Override
animateCollapsePanels(int flags, boolean force)2318     public void animateCollapsePanels(int flags, boolean force) {
2319         mShadeController.animateCollapsePanels(flags, force, false /* delayed */,
2320                 1.0f /* speedUpFactor */);
2321     }
2322 
2323     /**
2324      * Called by {@link ShadeController} when it calls
2325      * {@link ShadeController#animateCollapsePanels(int, boolean, boolean, float)}.
2326      */
postHideRecentApps()2327     void postHideRecentApps() {
2328         if (!mHandler.hasMessages(MSG_HIDE_RECENT_APPS)) {
2329             mHandler.removeMessages(MSG_HIDE_RECENT_APPS);
2330             mHandler.sendEmptyMessage(MSG_HIDE_RECENT_APPS);
2331         }
2332     }
2333 
isExpandedVisible()2334     public boolean isExpandedVisible() {
2335         return mExpandedVisible;
2336     }
2337 
isPanelExpanded()2338     public boolean isPanelExpanded() {
2339         return mPanelExpanded;
2340     }
2341 
2342     /**
2343      * Called when another window is about to transfer it's input focus.
2344      */
onInputFocusTransfer(boolean start, boolean cancel, float velocity)2345     public void onInputFocusTransfer(boolean start, boolean cancel, float velocity) {
2346         if (!mCommandQueue.panelsEnabled()) {
2347             return;
2348         }
2349 
2350         if (start) {
2351             mNotificationPanelViewController.startWaitingForOpenPanelGesture();
2352         } else {
2353             mNotificationPanelViewController.stopWaitingForOpenPanelGesture(cancel, velocity);
2354         }
2355     }
2356 
2357     @Override
animateExpandNotificationsPanel()2358     public void animateExpandNotificationsPanel() {
2359         if (SPEW) Log.d(TAG, "animateExpand: mExpandedVisible=" + mExpandedVisible);
2360         if (!mCommandQueue.panelsEnabled()) {
2361             return ;
2362         }
2363 
2364         mNotificationPanelViewController.expandWithoutQs();
2365 
2366         if (false) postStartTracing();
2367     }
2368 
2369     @Override
animateExpandSettingsPanel(@ullable String subPanel)2370     public void animateExpandSettingsPanel(@Nullable String subPanel) {
2371         if (SPEW) Log.d(TAG, "animateExpand: mExpandedVisible=" + mExpandedVisible);
2372         if (!mCommandQueue.panelsEnabled()) {
2373             return;
2374         }
2375 
2376         // Settings are not available in setup
2377         if (!mUserSetup) return;
2378 
2379         if (subPanel != null) {
2380             mQSPanelController.openDetails(subPanel);
2381         }
2382         mNotificationPanelViewController.expandWithQs();
2383 
2384         if (false) postStartTracing();
2385     }
2386 
animateCollapseQuickSettings()2387     public void animateCollapseQuickSettings() {
2388         if (mState == StatusBarState.SHADE) {
2389             mStatusBarView.collapsePanel(true, false /* delayed */, 1.0f /* speedUpFactor */);
2390         }
2391     }
2392 
makeExpandedInvisible()2393     void makeExpandedInvisible() {
2394         if (SPEW) Log.d(TAG, "makeExpandedInvisible: mExpandedVisible=" + mExpandedVisible
2395                 + " mExpandedVisible=" + mExpandedVisible);
2396 
2397         if (!mExpandedVisible || mNotificationShadeWindowView == null) {
2398             return;
2399         }
2400 
2401         // Ensure the panel is fully collapsed (just in case; bug 6765842, 7260868)
2402         mStatusBarView.collapsePanel(/*animate=*/ false, false /* delayed*/,
2403                 1.0f /* speedUpFactor */);
2404 
2405         mNotificationPanelViewController.closeQs();
2406 
2407         mExpandedVisible = false;
2408         visibilityChanged(false);
2409 
2410         // Update the visibility of notification shade and status bar window.
2411         mNotificationShadeWindowController.setPanelVisible(false);
2412         mStatusBarWindowController.setForceStatusBarVisible(false);
2413 
2414         // Close any guts that might be visible
2415         mGutsManager.closeAndSaveGuts(true /* removeLeavebehind */, true /* force */,
2416                 true /* removeControls */, -1 /* x */, -1 /* y */, true /* resetMenu */);
2417 
2418         mShadeController.runPostCollapseRunnables();
2419         setInteracting(StatusBarManager.WINDOW_STATUS_BAR, false);
2420         if (!mNotificationActivityStarter.isCollapsingToShowActivityOverLockscreen()) {
2421             showBouncerIfKeyguard();
2422         } else if (DEBUG) {
2423             Log.d(TAG, "Not showing bouncer due to activity showing over lockscreen");
2424         }
2425         mCommandQueue.recomputeDisableFlags(
2426                 mDisplayId,
2427                 mNotificationPanelViewController.hideStatusBarIconsWhenExpanded() /* animate */);
2428 
2429         // Trimming will happen later if Keyguard is showing - doing it here might cause a jank in
2430         // the bouncer appear animation.
2431         if (!mStatusBarKeyguardViewManager.isShowing()) {
2432             WindowManagerGlobal.getInstance().trimMemory(ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN);
2433         }
2434     }
2435 
interceptTouchEvent(MotionEvent event)2436     public boolean interceptTouchEvent(MotionEvent event) {
2437         if (DEBUG_GESTURES) {
2438             if (event.getActionMasked() != MotionEvent.ACTION_MOVE) {
2439                 EventLog.writeEvent(EventLogTags.SYSUI_STATUSBAR_TOUCH,
2440                         event.getActionMasked(), (int) event.getX(), (int) event.getY(),
2441                         mDisabled1, mDisabled2);
2442             }
2443 
2444         }
2445 
2446         if (SPEW) {
2447             Log.d(TAG, "Touch: rawY=" + event.getRawY() + " event=" + event + " mDisabled1="
2448                     + mDisabled1 + " mDisabled2=" + mDisabled2);
2449         } else if (CHATTY) {
2450             if (event.getAction() != MotionEvent.ACTION_MOVE) {
2451                 Log.d(TAG, String.format(
2452                             "panel: %s at (%f, %f) mDisabled1=0x%08x mDisabled2=0x%08x",
2453                             MotionEvent.actionToString(event.getAction()),
2454                             event.getRawX(), event.getRawY(), mDisabled1, mDisabled2));
2455             }
2456         }
2457 
2458         if (DEBUG_GESTURES) {
2459             mGestureRec.add(event);
2460         }
2461 
2462         if (mStatusBarWindowState == WINDOW_STATE_SHOWING) {
2463             final boolean upOrCancel =
2464                     event.getAction() == MotionEvent.ACTION_UP ||
2465                     event.getAction() == MotionEvent.ACTION_CANCEL;
2466             if (upOrCancel && !mExpandedVisible) {
2467                 setInteracting(StatusBarManager.WINDOW_STATUS_BAR, false);
2468             } else {
2469                 setInteracting(StatusBarManager.WINDOW_STATUS_BAR, true);
2470             }
2471         }
2472         return false;
2473     }
2474 
isSameStatusBarState(int state)2475     boolean isSameStatusBarState(int state) {
2476         return mStatusBarWindowState == state;
2477     }
2478 
getGestureRecorder()2479     public GestureRecorder getGestureRecorder() {
2480         return mGestureRec;
2481     }
2482 
getBiometricUnlockController()2483     public BiometricUnlockController getBiometricUnlockController() {
2484         return mBiometricUnlockController;
2485     }
2486 
2487     @Override // CommandQueue
setWindowState( int displayId, @WindowType int window, @WindowVisibleState int state)2488     public void setWindowState(
2489             int displayId, @WindowType int window, @WindowVisibleState int state) {
2490         if (displayId != mDisplayId) {
2491             return;
2492         }
2493         boolean showing = state == WINDOW_STATE_SHOWING;
2494         if (mNotificationShadeWindowView != null
2495                 && window == StatusBarManager.WINDOW_STATUS_BAR
2496                 && mStatusBarWindowState != state) {
2497             mStatusBarWindowState = state;
2498             if (DEBUG_WINDOW_STATE) Log.d(TAG, "Status bar " + windowStateToString(state));
2499             if (mStatusBarView != null) {
2500                 if (!showing && mState == StatusBarState.SHADE) {
2501                     mStatusBarView.collapsePanel(false /* animate */, false /* delayed */,
2502                             1.0f /* speedUpFactor */);
2503                 }
2504                 mStatusBarWindowHidden = state == WINDOW_STATE_HIDDEN;
2505                 updateHideIconsForBouncer(false /* animate */);
2506             }
2507         }
2508 
2509         updateBubblesVisibility();
2510     }
2511 
2512     @Override
onSystemBarAttributesChanged(int displayId, @Appearance int appearance, AppearanceRegion[] appearanceRegions, boolean navbarColorManagedByIme, @Behavior int behavior, boolean isFullscreen)2513     public void onSystemBarAttributesChanged(int displayId, @Appearance int appearance,
2514             AppearanceRegion[] appearanceRegions, boolean navbarColorManagedByIme,
2515             @Behavior int behavior, boolean isFullscreen) {
2516         if (displayId != mDisplayId) {
2517             return;
2518         }
2519         boolean barModeChanged = false;
2520         if (mAppearance != appearance) {
2521             mAppearance = appearance;
2522             barModeChanged = updateBarMode(barMode(mTransientShown, appearance));
2523         }
2524         mLightBarController.onStatusBarAppearanceChanged(appearanceRegions, barModeChanged,
2525                 mStatusBarMode, navbarColorManagedByIme);
2526 
2527         updateBubblesVisibility();
2528         mStatusBarStateController.setFullscreenState(isFullscreen);
2529     }
2530 
2531     @Override
showTransient(int displayId, @InternalInsetsType int[] types)2532     public void showTransient(int displayId, @InternalInsetsType int[] types) {
2533         if (displayId != mDisplayId) {
2534             return;
2535         }
2536         if (!containsType(types, ITYPE_STATUS_BAR)) {
2537             return;
2538         }
2539         showTransientUnchecked();
2540     }
2541 
showTransientUnchecked()2542     private void showTransientUnchecked() {
2543         if (!mTransientShown) {
2544             mTransientShown = true;
2545             mNoAnimationOnNextBarModeChange = true;
2546             handleTransientChanged();
2547         }
2548     }
2549 
2550     @Override
abortTransient(int displayId, @InternalInsetsType int[] types)2551     public void abortTransient(int displayId, @InternalInsetsType int[] types) {
2552         if (displayId != mDisplayId) {
2553             return;
2554         }
2555         if (!containsType(types, ITYPE_STATUS_BAR)) {
2556             return;
2557         }
2558         clearTransient();
2559     }
2560 
clearTransient()2561     private void clearTransient() {
2562         if (mTransientShown) {
2563             mTransientShown = false;
2564             handleTransientChanged();
2565         }
2566     }
2567 
handleTransientChanged()2568     private void handleTransientChanged() {
2569         final int barMode = barMode(mTransientShown, mAppearance);
2570         if (updateBarMode(barMode)) {
2571             mLightBarController.onStatusBarModeChanged(barMode);
2572             updateBubblesVisibility();
2573         }
2574     }
2575 
updateBarMode(int barMode)2576     private boolean updateBarMode(int barMode) {
2577         if (mStatusBarMode != barMode) {
2578             mStatusBarMode = barMode;
2579             checkBarModes();
2580             mAutoHideController.touchAutoHide();
2581             return true;
2582         }
2583         return false;
2584     }
2585 
barMode(boolean isTransient, int appearance)2586     private static @TransitionMode int barMode(boolean isTransient, int appearance) {
2587         final int lightsOutOpaque = APPEARANCE_LOW_PROFILE_BARS | APPEARANCE_OPAQUE_STATUS_BARS;
2588         if (isTransient) {
2589             return MODE_SEMI_TRANSPARENT;
2590         } else if ((appearance & lightsOutOpaque) == lightsOutOpaque) {
2591             return MODE_LIGHTS_OUT;
2592         } else if ((appearance & APPEARANCE_LOW_PROFILE_BARS) != 0) {
2593             return MODE_LIGHTS_OUT_TRANSPARENT;
2594         } else if ((appearance & APPEARANCE_OPAQUE_STATUS_BARS) != 0) {
2595             return MODE_OPAQUE;
2596         } else if ((appearance & APPEARANCE_SEMI_TRANSPARENT_STATUS_BARS) != 0) {
2597             return MODE_SEMI_TRANSPARENT;
2598         } else {
2599             return MODE_TRANSPARENT;
2600         }
2601     }
2602 
2603     @Override
showWirelessChargingAnimation(int batteryLevel)2604     public void showWirelessChargingAnimation(int batteryLevel) {
2605         showChargingAnimation(batteryLevel, UNKNOWN_BATTERY_LEVEL, 0);
2606     }
2607 
showChargingAnimation(int batteryLevel, int transmittingBatteryLevel, long animationDelay)2608     protected void showChargingAnimation(int batteryLevel, int transmittingBatteryLevel,
2609             long animationDelay) {
2610         WirelessChargingAnimation.makeWirelessChargingAnimation(mContext, null,
2611                 transmittingBatteryLevel, batteryLevel,
2612                 new WirelessChargingAnimation.Callback() {
2613                     @Override
2614                     public void onAnimationStarting() {
2615                         mNotificationShadeWindowController.setRequestTopUi(true, TAG);
2616                     }
2617 
2618                     @Override
2619                     public void onAnimationEnded() {
2620                         mNotificationShadeWindowController.setRequestTopUi(false, TAG);
2621                     }
2622                 }, false, sUiEventLogger).show(animationDelay);
2623     }
2624 
2625     @Override
onRecentsAnimationStateChanged(boolean running)2626     public void onRecentsAnimationStateChanged(boolean running) {
2627         setInteracting(StatusBarManager.WINDOW_NAVIGATION_BAR, running);
2628     }
2629 
getStatusBarTransitions()2630     protected BarTransitions getStatusBarTransitions() {
2631         return mNotificationShadeWindowViewController.getBarTransitions();
2632     }
2633 
checkBarModes()2634     public void checkBarModes() {
2635         if (mDemoModeController.isInDemoMode()) return;
2636         if (mNotificationShadeWindowViewController != null && getStatusBarTransitions() != null) {
2637             checkBarMode(mStatusBarMode, mStatusBarWindowState, getStatusBarTransitions());
2638         }
2639         mNavigationBarController.checkNavBarModes(mDisplayId);
2640         mNoAnimationOnNextBarModeChange = false;
2641     }
2642 
2643     // Called by NavigationBarFragment
setQsScrimEnabled(boolean scrimEnabled)2644     public void setQsScrimEnabled(boolean scrimEnabled) {
2645         mNotificationPanelViewController.setQsScrimEnabled(scrimEnabled);
2646     }
2647 
2648     /** Temporarily hides Bubbles if the status bar is hidden. */
updateBubblesVisibility()2649     private void updateBubblesVisibility() {
2650         if (mBubblesOptional.isPresent()) {
2651             mBubblesOptional.get().onStatusBarVisibilityChanged(
2652                     mStatusBarMode != MODE_LIGHTS_OUT
2653                             && mStatusBarMode != MODE_LIGHTS_OUT_TRANSPARENT
2654                             && !mStatusBarWindowHidden);
2655         }
2656     }
2657 
checkBarMode(@ransitionMode int mode, @WindowVisibleState int windowState, BarTransitions transitions)2658     void checkBarMode(@TransitionMode int mode, @WindowVisibleState int windowState,
2659             BarTransitions transitions) {
2660         final boolean anim = !mNoAnimationOnNextBarModeChange && mDeviceInteractive
2661                 && windowState != WINDOW_STATE_HIDDEN;
2662         transitions.transitionTo(mode, anim);
2663     }
2664 
finishBarAnimations()2665     private void finishBarAnimations() {
2666         if (mNotificationShadeWindowController != null
2667                 && mNotificationShadeWindowViewController.getBarTransitions() != null) {
2668             mNotificationShadeWindowViewController.getBarTransitions().finishAnimations();
2669         }
2670         mNavigationBarController.finishBarAnimations(mDisplayId);
2671     }
2672 
2673     private final Runnable mCheckBarModes = this::checkBarModes;
2674 
setInteracting(int barWindow, boolean interacting)2675     public void setInteracting(int barWindow, boolean interacting) {
2676         mInteractingWindows = interacting
2677                 ? (mInteractingWindows | barWindow)
2678                 : (mInteractingWindows & ~barWindow);
2679         if (mInteractingWindows != 0) {
2680             mAutoHideController.suspendAutoHide();
2681         } else {
2682             mAutoHideController.resumeSuspendedAutoHide();
2683         }
2684         checkBarModes();
2685     }
2686 
dismissVolumeDialog()2687     private void dismissVolumeDialog() {
2688         if (mVolumeComponent != null) {
2689             mVolumeComponent.dismissNow();
2690         }
2691     }
2692 
viewInfo(View v)2693     public static String viewInfo(View v) {
2694         return "[(" + v.getLeft() + "," + v.getTop() + ")(" + v.getRight() + "," + v.getBottom()
2695                 + ") " + v.getWidth() + "x" + v.getHeight() + "]";
2696     }
2697 
2698     @Override
dump(FileDescriptor fd, PrintWriter pw, String[] args)2699     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
2700         synchronized (mQueueLock) {
2701             pw.println("Current Status Bar state:");
2702             pw.println("  mExpandedVisible=" + mExpandedVisible);
2703             pw.println("  mDisplayMetrics=" + mDisplayMetrics);
2704             pw.println("  mStackScroller: " + viewInfo(mStackScroller));
2705             pw.println("  mStackScroller: " + viewInfo(mStackScroller)
2706                     + " scroll " + mStackScroller.getScrollX()
2707                     + "," + mStackScroller.getScrollY());
2708         }
2709 
2710         pw.print("  mInteractingWindows="); pw.println(mInteractingWindows);
2711         pw.print("  mStatusBarWindowState=");
2712         pw.println(windowStateToString(mStatusBarWindowState));
2713         pw.print("  mStatusBarMode=");
2714         pw.println(BarTransitions.modeToString(mStatusBarMode));
2715         pw.print("  mDozing="); pw.println(mDozing);
2716         pw.print("  mWallpaperSupported= "); pw.println(mWallpaperSupported);
2717 
2718         pw.println("  StatusBarWindowView: ");
2719         if (mNotificationShadeWindowViewController != null) {
2720             mNotificationShadeWindowViewController.dump(fd, pw, args);
2721             dumpBarTransitions(pw, "PhoneStatusBarTransitions",
2722                     mNotificationShadeWindowViewController.getBarTransitions());
2723         }
2724 
2725         pw.println("  mMediaManager: ");
2726         if (mMediaManager != null) {
2727             mMediaManager.dump(fd, pw, args);
2728         }
2729 
2730         pw.println("  Panels: ");
2731         if (mNotificationPanelViewController != null) {
2732             pw.println("    mNotificationPanel="
2733                     + mNotificationPanelViewController.getView() + " params="
2734                     + mNotificationPanelViewController.getView().getLayoutParams().debug(""));
2735             pw.print  ("      ");
2736             mNotificationPanelViewController.dump(fd, pw, args);
2737         }
2738         pw.println("  mStackScroller: ");
2739         if (mStackScroller instanceof Dumpable) {
2740             pw.print  ("      ");
2741             ((Dumpable) mStackScroller).dump(fd, pw, args);
2742         }
2743         pw.println("  Theme:");
2744         String nightMode = mUiModeManager == null ? "null" : mUiModeManager.getNightMode() + "";
2745         pw.println("    dark theme: " + nightMode +
2746                 " (auto: " + UiModeManager.MODE_NIGHT_AUTO +
2747                 ", yes: " + UiModeManager.MODE_NIGHT_YES +
2748                 ", no: " + UiModeManager.MODE_NIGHT_NO + ")");
2749         final boolean lightWpTheme = mContext.getThemeResId()
2750                 == R.style.Theme_SystemUI_LightWallpaper;
2751         pw.println("    light wallpaper theme: " + lightWpTheme);
2752 
2753         if (mKeyguardIndicationController != null) {
2754             mKeyguardIndicationController.dump(fd, pw, args);
2755         }
2756 
2757         if (mScrimController != null) {
2758             mScrimController.dump(fd, pw, args);
2759         }
2760 
2761         if (mLightRevealScrim != null) {
2762             pw.println(
2763                     "mLightRevealScrim.getRevealAmount(): " + mLightRevealScrim.getRevealAmount());
2764         }
2765 
2766         if (mStatusBarKeyguardViewManager != null) {
2767             mStatusBarKeyguardViewManager.dump(pw);
2768         }
2769 
2770         mNotificationsController.dump(fd, pw, args, DUMPTRUCK);
2771 
2772         if (DUMPTRUCK) {
2773             if (false) {
2774                 pw.println("see the logcat for a dump of the views we have created.");
2775                 // must happen on ui thread
2776                 mHandler.post(() -> {
2777                     mStatusBarView.getLocationOnScreen(mAbsPos);
2778                     Log.d(TAG, "mStatusBarView: ----- (" + mAbsPos[0] + "," + mAbsPos[1] +
2779                             ") " + mStatusBarView.getWidth() + "x" + getStatusBarHeight());
2780                     mStatusBarView.debug();
2781                 });
2782             }
2783         }
2784 
2785         if (DEBUG_GESTURES) {
2786             pw.print("  status bar gestures: ");
2787             mGestureRec.dump(fd, pw, args);
2788         }
2789 
2790         if (mHeadsUpManager != null) {
2791             mHeadsUpManager.dump(fd, pw, args);
2792         } else {
2793             pw.println("  mHeadsUpManager: null");
2794         }
2795 
2796         if (mStatusBarTouchableRegionManager != null) {
2797             mStatusBarTouchableRegionManager.dump(fd, pw, args);
2798         } else {
2799             pw.println("  mStatusBarTouchableRegionManager: null");
2800         }
2801 
2802         if (mLightBarController != null) {
2803             mLightBarController.dump(fd, pw, args);
2804         }
2805 
2806         pw.println("SharedPreferences:");
2807         for (Map.Entry<String, ?> entry : Prefs.getAll(mContext).entrySet()) {
2808             pw.print("  "); pw.print(entry.getKey()); pw.print("="); pw.println(entry.getValue());
2809         }
2810 
2811         pw.println("Camera gesture intents:");
2812         pw.println("   Insecure camera: " + CameraIntents.getInsecureCameraIntent(mContext));
2813         pw.println("   Secure camera: " + CameraIntents.getSecureCameraIntent(mContext));
2814         pw.println("   Override package: "
2815                 + String.valueOf(CameraIntents.getOverrideCameraPackage(mContext)));
2816     }
2817 
dumpBarTransitions( PrintWriter pw, String var, @Nullable BarTransitions transitions)2818     public static void dumpBarTransitions(
2819             PrintWriter pw, String var, @Nullable BarTransitions transitions) {
2820         pw.print("  "); pw.print(var); pw.print(".BarTransitions.mMode=");
2821         if (transitions != null) {
2822             pw.println(BarTransitions.modeToString(transitions.getMode()));
2823         } else {
2824             pw.println("Unknown");
2825         }
2826     }
2827 
createAndAddWindows(@ullable RegisterStatusBarResult result)2828     public void createAndAddWindows(@Nullable RegisterStatusBarResult result) {
2829         makeStatusBarView(result);
2830         mNotificationShadeWindowController.attach();
2831         mStatusBarWindowController.attach();
2832     }
2833 
2834     // called by makeStatusbar and also by PhoneStatusBarView
updateDisplaySize()2835     void updateDisplaySize() {
2836         mDisplay.getMetrics(mDisplayMetrics);
2837         mDisplay.getSize(mCurrentDisplaySize);
2838         if (DEBUG_GESTURES) {
2839             mGestureRec.tag("display",
2840                     String.format("%dx%d", mDisplayMetrics.widthPixels, mDisplayMetrics.heightPixels));
2841         }
2842     }
2843 
getDisplayDensity()2844     float getDisplayDensity() {
2845         return mDisplayMetrics.density;
2846     }
2847 
getDisplayWidth()2848     public float getDisplayWidth() {
2849         return mDisplayMetrics.widthPixels;
2850     }
2851 
getDisplayHeight()2852     public float getDisplayHeight() {
2853         return mDisplayMetrics.heightPixels;
2854     }
2855 
getRotation()2856     int getRotation() {
2857         return mDisplay.getRotation();
2858     }
2859 
getDisplayId()2860     int getDisplayId() {
2861         return mDisplayId;
2862     }
2863 
startActivityDismissingKeyguard(final Intent intent, boolean onlyProvisioned, boolean dismissShade, int flags)2864     public void startActivityDismissingKeyguard(final Intent intent, boolean onlyProvisioned,
2865             boolean dismissShade, int flags) {
2866         startActivityDismissingKeyguard(intent, onlyProvisioned, dismissShade,
2867                 false /* disallowEnterPictureInPictureWhileLaunching */, null /* callback */,
2868                 flags, null /* animationController */);
2869     }
2870 
startActivityDismissingKeyguard(final Intent intent, boolean onlyProvisioned, boolean dismissShade)2871     public void startActivityDismissingKeyguard(final Intent intent, boolean onlyProvisioned,
2872             boolean dismissShade) {
2873         startActivityDismissingKeyguard(intent, onlyProvisioned, dismissShade, 0);
2874     }
2875 
startActivityDismissingKeyguard(final Intent intent, boolean onlyProvisioned, final boolean dismissShade, final boolean disallowEnterPictureInPictureWhileLaunching, final Callback callback, int flags, @Nullable ActivityLaunchAnimator.Controller animationController)2876     private void startActivityDismissingKeyguard(final Intent intent, boolean onlyProvisioned,
2877             final boolean dismissShade, final boolean disallowEnterPictureInPictureWhileLaunching,
2878             final Callback callback, int flags,
2879             @Nullable ActivityLaunchAnimator.Controller animationController) {
2880         if (onlyProvisioned && !mDeviceProvisionedController.isDeviceProvisioned()) return;
2881 
2882         final boolean willLaunchResolverActivity =
2883                 mActivityIntentHelper.wouldLaunchResolverActivity(intent,
2884                         mLockscreenUserManager.getCurrentUserId());
2885 
2886         boolean animate =
2887                 animationController != null && !willLaunchResolverActivity && shouldAnimateLaunch(
2888                         true /* isActivityIntent */);
2889         ActivityLaunchAnimator.Controller animController =
2890                 animate ? wrapAnimationController(animationController, dismissShade) : null;
2891 
2892         // If we animate, we will dismiss the shade only once the animation is done. This is taken
2893         // care of by the StatusBarLaunchAnimationController.
2894         boolean dismissShadeDirectly = dismissShade && animController == null;
2895 
2896         Runnable runnable = () -> {
2897             mAssistManagerLazy.get().hideAssist();
2898             intent.setFlags(
2899                     Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
2900             intent.addFlags(flags);
2901             int[] result = new int[]{ActivityManager.START_CANCELED};
2902 
2903             mActivityLaunchAnimator.startIntentWithAnimation(animController,
2904                     animate, intent.getPackage(), (adapter) -> {
2905                         ActivityOptions options = new ActivityOptions(
2906                                 getActivityOptions(mDisplayId, adapter));
2907                         options.setDisallowEnterPictureInPictureWhileLaunching(
2908                                 disallowEnterPictureInPictureWhileLaunching);
2909                         if (CameraIntents.isInsecureCameraIntent(intent)) {
2910                             // Normally an activity will set it's requested rotation
2911                             // animation on its window. However when launching an activity
2912                             // causes the orientation to change this is too late. In these cases
2913                             // the default animation is used. This doesn't look good for
2914                             // the camera (as it rotates the camera contents out of sync
2915                             // with physical reality). So, we ask the WindowManager to
2916                             // force the crossfade animation if an orientation change
2917                             // happens to occur during the launch.
2918                             options.setRotationAnimationHint(
2919                                     WindowManager.LayoutParams.ROTATION_ANIMATION_SEAMLESS);
2920                         }
2921                         if (intent.getAction() == Settings.Panel.ACTION_VOLUME) {
2922                             // Settings Panel is implemented as activity(not a dialog), so
2923                             // underlying app is paused and may enter picture-in-picture mode
2924                             // as a result.
2925                             // So we need to disable picture-in-picture mode here
2926                             // if it is volume panel.
2927                             options.setDisallowEnterPictureInPictureWhileLaunching(true);
2928                         }
2929 
2930                         try {
2931                             result[0] = ActivityTaskManager.getService().startActivityAsUser(
2932                                     null, mContext.getBasePackageName(),
2933                                     mContext.getAttributionTag(),
2934                                     intent,
2935                                     intent.resolveTypeIfNeeded(mContext.getContentResolver()),
2936                                     null, null, 0, Intent.FLAG_ACTIVITY_NEW_TASK, null,
2937                                     options.toBundle(), UserHandle.CURRENT.getIdentifier());
2938                         } catch (RemoteException e) {
2939                             Log.w(TAG, "Unable to start activity", e);
2940                         }
2941                         return result[0];
2942                     });
2943 
2944             if (callback != null) {
2945                 callback.onActivityStarted(result[0]);
2946             }
2947         };
2948         Runnable cancelRunnable = () -> {
2949             if (callback != null) {
2950                 callback.onActivityStarted(ActivityManager.START_CANCELED);
2951             }
2952         };
2953         executeRunnableDismissingKeyguard(runnable, cancelRunnable, dismissShadeDirectly,
2954                 willLaunchResolverActivity, true /* deferred */, animate);
2955     }
2956 
2957     @Nullable
wrapAnimationController( ActivityLaunchAnimator.Controller animationController, boolean dismissShade)2958     private ActivityLaunchAnimator.Controller wrapAnimationController(
2959             ActivityLaunchAnimator.Controller animationController, boolean dismissShade) {
2960         View rootView = animationController.getLaunchContainer().getRootView();
2961         if (rootView == mSuperStatusBarViewFactory.getStatusBarWindowView()) {
2962             // We are animating a view in the status bar. We have to make sure that the status bar
2963             // window matches the full screen during the animation and that we are expanding the
2964             // view below the other status bar text.
2965             animationController.setLaunchContainer(
2966                     mStatusBarWindowController.getLaunchAnimationContainer());
2967 
2968             return new DelegateLaunchAnimatorController(animationController) {
2969                 @Override
2970                 public void onLaunchAnimationStart(boolean isExpandingFullyAbove) {
2971                     getDelegate().onLaunchAnimationStart(isExpandingFullyAbove);
2972                     mStatusBarWindowController.setLaunchAnimationRunning(true);
2973                 }
2974 
2975                 @Override
2976                 public void onLaunchAnimationEnd(boolean isExpandingFullyAbove) {
2977                     getDelegate().onLaunchAnimationEnd(isExpandingFullyAbove);
2978                     mStatusBarWindowController.setLaunchAnimationRunning(false);
2979                 }
2980             };
2981         }
2982 
2983         if (dismissShade && rootView == mNotificationShadeWindowView) {
2984             // We are animating a view in the shade. We have to make sure that we collapse it when
2985             // the animation ends or is cancelled.
2986             return new StatusBarLaunchAnimatorController(animationController, this,
2987                     true /* isLaunchForActivity */);
2988         }
2989 
2990         return animationController;
2991     }
2992 
2993     public void readyForKeyguardDone() {
2994         mStatusBarKeyguardViewManager.readyForKeyguardDone();
2995     }
2996 
2997     public void executeRunnableDismissingKeyguard(final Runnable runnable,
2998             final Runnable cancelAction,
2999             final boolean dismissShade,
3000             final boolean afterKeyguardGone,
3001             final boolean deferred) {
3002         executeRunnableDismissingKeyguard(runnable, cancelAction, dismissShade, afterKeyguardGone,
3003                 deferred, false /* willAnimateOnKeyguard */);
3004     }
3005 
3006     public void executeRunnableDismissingKeyguard(final Runnable runnable,
3007             final Runnable cancelAction,
3008             final boolean dismissShade,
3009             final boolean afterKeyguardGone,
3010             final boolean deferred,
3011             final boolean willAnimateOnKeyguard) {
3012         OnDismissAction onDismissAction = new OnDismissAction() {
3013             @Override
3014             public boolean onDismiss() {
3015                 if (runnable != null) {
3016                     if (mStatusBarKeyguardViewManager.isShowing()
3017                             && mStatusBarKeyguardViewManager.isOccluded()) {
3018                         mStatusBarKeyguardViewManager.addAfterKeyguardGoneRunnable(runnable);
3019                     } else {
3020                         AsyncTask.execute(runnable);
3021                     }
3022                 }
3023                 if (dismissShade) {
3024                     if (mExpandedVisible && !mBouncerShowing) {
3025                         mShadeController.animateCollapsePanels(
3026                                 CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL,
3027                                 true /* force */, true /* delayed*/);
3028                     } else {
3029 
3030                         // Do it after DismissAction has been processed to conserve the needed
3031                         // ordering.
3032                         mHandler.post(mShadeController::runPostCollapseRunnables);
3033                     }
3034                 } else if (StatusBar.this.isInLaunchTransition()
3035                         && mNotificationPanelViewController.isLaunchTransitionFinished()) {
3036 
3037                     // We are not dismissing the shade, but the launch transition is already
3038                     // finished,
3039                     // so nobody will call readyForKeyguardDone anymore. Post it such that
3040                     // keyguardDonePending gets called first.
3041                     mHandler.post(mStatusBarKeyguardViewManager::readyForKeyguardDone);
3042                 }
3043                 return deferred;
3044             }
3045 
3046             @Override
3047             public boolean willRunAnimationOnKeyguard() {
3048                 return willAnimateOnKeyguard;
3049             }
3050         };
3051         dismissKeyguardThenExecute(onDismissAction, cancelAction, afterKeyguardGone);
3052     }
3053 
3054     private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
3055         @Override
3056         public void onReceive(Context context, Intent intent) {
3057             Trace.beginSection("StatusBar#onReceive");
3058             if (DEBUG) Log.v(TAG, "onReceive: " + intent);
3059             String action = intent.getAction();
3060             if (Intent.ACTION_CLOSE_SYSTEM_DIALOGS.equals(action)) {
3061                 KeyboardShortcuts.dismiss();
3062                 if (mRemoteInputManager.getController() != null) {
3063                     mRemoteInputManager.getController().closeRemoteInputs();
3064                 }
3065                 if (mBubblesOptional.isPresent() && mBubblesOptional.get().isStackExpanded()) {
3066                     mBubblesOptional.get().collapseStack();
3067                 }
3068                 if (mLockscreenUserManager.isCurrentProfile(getSendingUserId())) {
3069                     int flags = CommandQueue.FLAG_EXCLUDE_NONE;
3070                     String reason = intent.getStringExtra("reason");
3071                     if (reason != null && reason.equals(SYSTEM_DIALOG_REASON_RECENT_APPS)) {
3072                         flags |= CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL;
3073                     }
3074                     mShadeController.animateCollapsePanels(flags);
3075                 }
3076             }
3077             else if (Intent.ACTION_SCREEN_OFF.equals(action)) {
3078                 if (mNotificationShadeWindowController != null) {
3079                     mNotificationShadeWindowController.setNotTouchable(false);
3080                 }
3081                 if (mBubblesOptional.isPresent() && mBubblesOptional.get().isStackExpanded()) {
3082                     // Post to main thread handler, since updating the UI.
3083                     mMainThreadHandler.post(() -> mBubblesOptional.get().collapseStack());
3084                 }
3085                 finishBarAnimations();
3086                 resetUserExpandedStates();
3087             }
3088             else if (DevicePolicyManager.ACTION_SHOW_DEVICE_MONITORING_DIALOG.equals(action)) {
3089                 mQSPanelController.showDeviceMonitoringDialog();
3090             }
3091             Trace.endSection();
3092         }
3093     };
3094 
3095     private final BroadcastReceiver mDemoReceiver = new BroadcastReceiver() {
3096         @Override
3097         public void onReceive(Context context, Intent intent) {
3098             if (DEBUG) Log.v(TAG, "onReceive: " + intent);
3099             String action = intent.getAction();
3100             if (ACTION_FAKE_ARTWORK.equals(action)) {
3101                 if (DEBUG_MEDIA_FAKE_ARTWORK) {
3102                     mPresenter.updateMediaMetaData(true, true);
3103                 }
3104             }
3105         }
3106     };
3107 
3108     public void resetUserExpandedStates() {
3109         mNotificationsController.resetUserExpandedStates();
3110     }
3111 
3112     private void executeWhenUnlocked(OnDismissAction action, boolean requiresShadeOpen,
3113             boolean afterKeyguardGone) {
3114         if (mStatusBarKeyguardViewManager.isShowing() && requiresShadeOpen) {
3115             mStatusBarStateController.setLeaveOpenOnKeyguardHide(true);
3116         }
3117         dismissKeyguardThenExecute(action, null /* cancelAction */,
3118                 afterKeyguardGone /* afterKeyguardGone */);
3119     }
3120 
3121     protected void dismissKeyguardThenExecute(OnDismissAction action, boolean afterKeyguardGone) {
3122         dismissKeyguardThenExecute(action, null /* cancelRunnable */, afterKeyguardGone);
3123     }
3124 
3125     @Override
3126     public void dismissKeyguardThenExecute(OnDismissAction action, Runnable cancelAction,
3127             boolean afterKeyguardGone) {
3128         if (mWakefulnessLifecycle.getWakefulness() == WAKEFULNESS_ASLEEP
3129                 && mKeyguardStateController.canDismissLockScreen()
3130                 && !mStatusBarStateController.leaveOpenOnKeyguardHide()
3131                 && mDozeServiceHost.isPulsing()) {
3132             // Reuse the biometric wake-and-unlock transition if we dismiss keyguard from a pulse.
3133             // TODO: Factor this transition out of BiometricUnlockController.
3134             mBiometricUnlockController.startWakeAndUnlock(
3135                     BiometricUnlockController.MODE_WAKE_AND_UNLOCK_PULSING);
3136         }
3137         if (mStatusBarKeyguardViewManager.isShowing()) {
3138             mStatusBarKeyguardViewManager.dismissWithAction(action, cancelAction,
3139                     afterKeyguardGone);
3140         } else {
3141             action.onDismiss();
3142         }
3143     }
3144 
3145     @Override
3146     public void onConfigChanged(Configuration newConfig) {
3147         updateResources();
3148         updateDisplaySize(); // populates mDisplayMetrics
3149 
3150         if (DEBUG) {
3151             Log.v(TAG, "configuration changed: " + mContext.getResources().getConfiguration());
3152         }
3153 
3154         mViewHierarchyManager.updateRowStates();
3155         mScreenPinningRequest.onConfigurationChanged();
3156     }
3157 
3158     /**
3159      * Notify the shade controller that the current user changed
3160      *
3161      * @param newUserId userId of the new user
3162      */
3163     public void setLockscreenUser(int newUserId) {
3164         if (mLockscreenWallpaper != null) {
3165             mLockscreenWallpaper.setCurrentUser(newUserId);
3166         }
3167         mScrimController.setCurrentUser(newUserId);
3168         if (mWallpaperSupported) {
3169             mWallpaperChangedReceiver.onReceive(mContext, null);
3170         }
3171     }
3172 
3173     /**
3174      * Reload some of our resources when the configuration changes.
3175      *
3176      * We don't reload everything when the configuration changes -- we probably
3177      * should, but getting that smooth is tough.  Someday we'll fix that.  In the
3178      * meantime, just update the things that we know change.
3179      */
3180     void updateResources() {
3181         // Update the quick setting tiles
3182         if (mQSPanelController != null) {
3183             mQSPanelController.updateResources();
3184         }
3185 
3186         if (mStatusBarWindowController != null) {
3187             mStatusBarWindowController.refreshStatusBarHeight();
3188         }
3189 
3190         if (mStatusBarView != null) {
3191             mStatusBarView.updateResources();
3192         }
3193         if (mNotificationPanelViewController != null) {
3194             mNotificationPanelViewController.updateResources();
3195         }
3196         if (mBrightnessMirrorController != null) {
3197             mBrightnessMirrorController.updateResources();
3198         }
3199         if (mStatusBarKeyguardViewManager != null) {
3200             mStatusBarKeyguardViewManager.updateResources();
3201         }
3202 
3203         mPowerButtonReveal = new PowerButtonReveal(mContext.getResources().getDimensionPixelSize(
3204                 com.android.systemui.R.dimen.physical_power_button_center_screen_location_y));
3205     }
3206 
3207     // Visibility reporting
3208     protected void handleVisibleToUserChanged(boolean visibleToUser) {
3209         if (visibleToUser) {
3210             handleVisibleToUserChangedImpl(visibleToUser);
3211             mNotificationLogger.startNotificationLogging();
3212         } else {
3213             mNotificationLogger.stopNotificationLogging();
3214             handleVisibleToUserChangedImpl(visibleToUser);
3215         }
3216     }
3217 
3218     // Visibility reporting
3219     void handleVisibleToUserChangedImpl(boolean visibleToUser) {
3220         if (visibleToUser) {
3221             /* The LEDs are turned off when the notification panel is shown, even just a little bit.
3222              * See also StatusBar.setPanelExpanded for another place where we attempt to do this. */
3223             boolean pinnedHeadsUp = mHeadsUpManager.hasPinnedHeadsUp();
3224             boolean clearNotificationEffects =
3225                     !mPresenter.isPresenterFullyCollapsed() &&
3226                             (mState == StatusBarState.SHADE
3227                                     || mState == StatusBarState.SHADE_LOCKED);
3228             int notificationLoad = mNotificationsController.getActiveNotificationsCount();
3229             if (pinnedHeadsUp && mPresenter.isPresenterFullyCollapsed()) {
3230                 notificationLoad = 1;
3231             }
3232             final int finalNotificationLoad = notificationLoad;
3233             mUiBgExecutor.execute(() -> {
3234                 try {
3235                     mBarService.onPanelRevealed(clearNotificationEffects,
3236                             finalNotificationLoad);
3237                 } catch (RemoteException ex) {
3238                     // Won't fail unless the world has ended.
3239                 }
3240             });
3241         } else {
3242             mUiBgExecutor.execute(() -> {
3243                 try {
3244                     mBarService.onPanelHidden();
3245                 } catch (RemoteException ex) {
3246                     // Won't fail unless the world has ended.
3247                 }
3248             });
3249         }
3250 
3251     }
3252 
3253     private void logStateToEventlog() {
3254         boolean isShowing = mStatusBarKeyguardViewManager.isShowing();
3255         boolean isOccluded = mStatusBarKeyguardViewManager.isOccluded();
3256         boolean isBouncerShowing = mStatusBarKeyguardViewManager.isBouncerShowing();
3257         boolean isSecure = mKeyguardStateController.isMethodSecure();
3258         boolean unlocked = mKeyguardStateController.canDismissLockScreen();
3259         int stateFingerprint = getLoggingFingerprint(mState,
3260                 isShowing,
3261                 isOccluded,
3262                 isBouncerShowing,
3263                 isSecure,
3264                 unlocked);
3265         if (stateFingerprint != mLastLoggedStateFingerprint) {
3266             if (mStatusBarStateLog == null) {
3267                 mStatusBarStateLog = new LogMaker(MetricsEvent.VIEW_UNKNOWN);
3268             }
3269             mMetricsLogger.write(mStatusBarStateLog
3270                     .setCategory(isBouncerShowing ? MetricsEvent.BOUNCER : MetricsEvent.LOCKSCREEN)
3271                     .setType(isShowing ? MetricsEvent.TYPE_OPEN : MetricsEvent.TYPE_CLOSE)
3272                     .setSubtype(isSecure ? 1 : 0));
3273             EventLogTags.writeSysuiStatusBarState(mState,
3274                     isShowing ? 1 : 0,
3275                     isOccluded ? 1 : 0,
3276                     isBouncerShowing ? 1 : 0,
3277                     isSecure ? 1 : 0,
3278                     unlocked ? 1 : 0);
3279             mLastLoggedStateFingerprint = stateFingerprint;
3280 
3281             StringBuilder uiEventValueBuilder = new StringBuilder();
3282             uiEventValueBuilder.append(isBouncerShowing ? "BOUNCER" : "LOCKSCREEN");
3283             uiEventValueBuilder.append(isShowing ? "_OPEN" : "_CLOSE");
3284             uiEventValueBuilder.append(isSecure ? "_SECURE" : "_INSECURE");
3285             sUiEventLogger.log(StatusBarUiEvent.valueOf(uiEventValueBuilder.toString()));
3286         }
3287     }
3288 
3289     /**
3290      * Returns a fingerprint of fields logged to eventlog
3291      */
3292     private static int getLoggingFingerprint(int statusBarState, boolean keyguardShowing,
3293             boolean keyguardOccluded, boolean bouncerShowing, boolean secure,
3294             boolean currentlyInsecure) {
3295         // Reserve 8 bits for statusBarState. We'll never go higher than
3296         // that, right? Riiiight.
3297         return (statusBarState & 0xFF)
3298                 | ((keyguardShowing   ? 1 : 0) <<  8)
3299                 | ((keyguardOccluded  ? 1 : 0) <<  9)
3300                 | ((bouncerShowing    ? 1 : 0) << 10)
3301                 | ((secure            ? 1 : 0) << 11)
3302                 | ((currentlyInsecure ? 1 : 0) << 12);
3303     }
3304 
3305     //
3306     // tracing
3307     //
3308 
3309     void postStartTracing() {
3310         mHandler.postDelayed(mStartTracing, 3000);
3311     }
3312 
3313     void vibrate() {
3314         android.os.Vibrator vib = (android.os.Vibrator)mContext.getSystemService(
3315                 Context.VIBRATOR_SERVICE);
3316         vib.vibrate(250, VIBRATION_ATTRIBUTES);
3317     }
3318 
3319     final Runnable mStartTracing = new Runnable() {
3320         @Override
3321         public void run() {
3322             vibrate();
3323             SystemClock.sleep(250);
3324             Log.d(TAG, "startTracing");
3325             android.os.Debug.startMethodTracing("/data/statusbar-traces/trace");
3326             mHandler.postDelayed(mStopTracing, 10000);
3327         }
3328     };
3329 
3330     final Runnable mStopTracing = () -> {
3331         android.os.Debug.stopMethodTracing();
3332         Log.d(TAG, "stopTracing");
3333         vibrate();
3334     };
3335 
3336     @Override
3337     public void postQSRunnableDismissingKeyguard(final Runnable runnable) {
3338         mHandler.post(() -> {
3339             mStatusBarStateController.setLeaveOpenOnKeyguardHide(true);
3340             executeRunnableDismissingKeyguard(() -> mHandler.post(runnable), null, false, false,
3341                     false);
3342         });
3343     }
3344 
3345     @Override
3346     public void postStartActivityDismissingKeyguard(PendingIntent intent) {
3347         postStartActivityDismissingKeyguard(intent, null /* animationController */);
3348     }
3349 
3350     @Override
3351     public void postStartActivityDismissingKeyguard(final PendingIntent intent,
3352             @Nullable ActivityLaunchAnimator.Controller animationController) {
3353         mHandler.post(() -> startPendingIntentDismissingKeyguard(intent,
3354                 null /* intentSentUiThreadCallback */, animationController));
3355     }
3356 
3357     @Override
3358     public void postStartActivityDismissingKeyguard(final Intent intent, int delay) {
3359         postStartActivityDismissingKeyguard(intent, delay, null /* animationController */);
3360     }
3361 
3362     @Override
3363     public void postStartActivityDismissingKeyguard(Intent intent, int delay,
3364             @Nullable ActivityLaunchAnimator.Controller animationController) {
3365         mHandler.postDelayed(
3366                 () ->
3367                         startActivityDismissingKeyguard(intent, true /* onlyProvisioned */,
3368                                 true /* dismissShade */,
3369                                 false /* disallowEnterPictureInPictureWhileLaunching */,
3370                                 null /* callback */,
3371                                 0 /* flags */,
3372                                 animationController),
3373                 delay);
3374     }
3375 
3376     @Override
3377     public List<String> demoCommands() {
3378         List<String> s = new ArrayList<>();
3379         s.add(DemoMode.COMMAND_BARS);
3380         s.add(DemoMode.COMMAND_CLOCK);
3381         s.add(DemoMode.COMMAND_OPERATOR);
3382         return s;
3383     }
3384 
3385     @Override
3386     public void onDemoModeStarted() {
3387         // Must send this message to any view that we delegate to via dispatchDemoCommandToView
3388         dispatchDemoModeStartedToView(R.id.clock);
3389         dispatchDemoModeStartedToView(R.id.operator_name);
3390     }
3391 
3392     @Override
3393     public void onDemoModeFinished() {
3394         dispatchDemoModeFinishedToView(R.id.clock);
3395         dispatchDemoModeFinishedToView(R.id.operator_name);
3396         checkBarModes();
3397     }
3398 
3399     @Override
3400     public void dispatchDemoCommand(String command, @NonNull Bundle args) {
3401         if (command.equals(COMMAND_CLOCK)) {
3402             dispatchDemoCommandToView(command, args, R.id.clock);
3403         }
3404         if (command.equals(COMMAND_BARS)) {
3405             String mode = args.getString("mode");
3406             int barMode = "opaque".equals(mode) ? MODE_OPAQUE :
3407                     "translucent".equals(mode) ? MODE_TRANSLUCENT :
3408                     "semi-transparent".equals(mode) ? MODE_SEMI_TRANSPARENT :
3409                     "transparent".equals(mode) ? MODE_TRANSPARENT :
3410                     "warning".equals(mode) ? MODE_WARNING :
3411                     -1;
3412             if (barMode != -1) {
3413                 boolean animate = true;
3414                 if (mNotificationShadeWindowController != null
3415                         && mNotificationShadeWindowViewController.getBarTransitions() != null) {
3416                     mNotificationShadeWindowViewController.getBarTransitions().transitionTo(
3417                             barMode, animate);
3418                 }
3419                 mNavigationBarController.transitionTo(mDisplayId, barMode, animate);
3420             }
3421         }
3422         if (command.equals(COMMAND_OPERATOR)) {
3423             dispatchDemoCommandToView(command, args, R.id.operator_name);
3424         }
3425     }
3426 
3427     //TODO: these should have controllers, and this method should be removed
3428     private void dispatchDemoCommandToView(String command, Bundle args, int id) {
3429         if (mStatusBarView == null) return;
3430         View v = mStatusBarView.findViewById(id);
3431         if (v instanceof DemoModeCommandReceiver) {
3432             ((DemoModeCommandReceiver) v).dispatchDemoCommand(command, args);
3433         }
3434     }
3435 
3436     private void dispatchDemoModeStartedToView(int id) {
3437         if (mStatusBarView == null) return;
3438         View v = mStatusBarView.findViewById(id);
3439         if (v instanceof DemoModeCommandReceiver) {
3440             ((DemoModeCommandReceiver) v).onDemoModeStarted();
3441         }
3442     }
3443 
3444     private void dispatchDemoModeFinishedToView(int id) {
3445         if (mStatusBarView == null) return;
3446         View v = mStatusBarView.findViewById(id);
3447         if (v instanceof DemoModeCommandReceiver) {
3448             ((DemoModeCommandReceiver) v).onDemoModeFinished();
3449         }
3450     }
3451 
3452     public void showKeyguard() {
3453         mStatusBarStateController.setKeyguardRequested(true);
3454         mStatusBarStateController.setLeaveOpenOnKeyguardHide(false);
3455         updateIsKeyguard();
3456         mAssistManagerLazy.get().onLockscreenShown();
3457     }
3458 
3459     public boolean hideKeyguard() {
3460         mStatusBarStateController.setKeyguardRequested(false);
3461         return updateIsKeyguard();
3462     }
3463 
3464     /**
3465      * stop(tag)
3466      * @return True if StatusBar state is FULLSCREEN_USER_SWITCHER.
3467      */
3468     public boolean isFullScreenUserSwitcherState() {
3469         return mState == StatusBarState.FULLSCREEN_USER_SWITCHER;
3470     }
3471 
3472     boolean updateIsKeyguard() {
3473         return updateIsKeyguard(false /* force */);
3474     }
3475 
3476     boolean updateIsKeyguard(boolean force) {
3477         boolean wakeAndUnlocking = mBiometricUnlockController.getMode()
3478                 == BiometricUnlockController.MODE_WAKE_AND_UNLOCK;
3479 
3480         // For dozing, keyguard needs to be shown whenever the device is non-interactive. Otherwise
3481         // there's no surface we can show to the user. Note that the device goes fully interactive
3482         // late in the transition, so we also allow the device to start dozing once the screen has
3483         // turned off fully.
3484         boolean keyguardForDozing = mDozeServiceHost.getDozingRequested()
3485                 && (!mDeviceInteractive || isGoingToSleep() && (isScreenFullyOff() || mIsKeyguard));
3486         boolean shouldBeKeyguard = (mStatusBarStateController.isKeyguardRequested()
3487                 || keyguardForDozing) && !wakeAndUnlocking;
3488         if (keyguardForDozing) {
3489             updatePanelExpansionForKeyguard();
3490         }
3491         if (shouldBeKeyguard) {
3492             if (mUnlockedScreenOffAnimationController.isScreenOffAnimationPlaying()
3493                     || (isGoingToSleep()
3494                     && mScreenLifecycle.getScreenState() == ScreenLifecycle.SCREEN_TURNING_OFF)) {
3495                 // Delay showing the keyguard until screen turned off.
3496             } else {
3497                 showKeyguardImpl();
3498             }
3499         } else {
3500             return hideKeyguardImpl(force);
3501         }
3502         return false;
3503     }
3504 
3505     public void showKeyguardImpl() {
3506         mIsKeyguard = true;
3507         if (mKeyguardStateController.isLaunchTransitionFadingAway()) {
3508             mNotificationPanelViewController.cancelAnimation();
3509             onLaunchTransitionFadingEnded();
3510         }
3511         mHandler.removeMessages(MSG_LAUNCH_TRANSITION_TIMEOUT);
3512         if (mUserSwitcherController != null && mUserSwitcherController.useFullscreenUserSwitcher()) {
3513             mStatusBarStateController.setState(StatusBarState.FULLSCREEN_USER_SWITCHER);
3514         } else if (!mPulseExpansionHandler.isWakingToShadeLocked()) {
3515             mStatusBarStateController.setState(StatusBarState.KEYGUARD);
3516         }
3517         updatePanelExpansionForKeyguard();
3518     }
3519 
3520     private void updatePanelExpansionForKeyguard() {
3521         if (mState == StatusBarState.KEYGUARD && mBiometricUnlockController.getMode()
3522                 != BiometricUnlockController.MODE_WAKE_AND_UNLOCK && !mBouncerShowing) {
3523             mShadeController.instantExpandNotificationsPanel();
3524         } else if (mState == StatusBarState.FULLSCREEN_USER_SWITCHER) {
3525             instantCollapseNotificationPanel();
3526         }
3527     }
3528 
3529     private void onLaunchTransitionFadingEnded() {
3530         mNotificationPanelViewController.setAlpha(1.0f);
3531         mNotificationPanelViewController.onAffordanceLaunchEnded();
3532         releaseGestureWakeLock();
3533         runLaunchTransitionEndRunnable();
3534         mKeyguardStateController.setLaunchTransitionFadingAway(false);
3535         mPresenter.updateMediaMetaData(true /* metaDataChanged */, true);
3536     }
3537 
3538     public boolean isInLaunchTransition() {
3539         return mNotificationPanelViewController.isLaunchTransitionRunning()
3540                 || mNotificationPanelViewController.isLaunchTransitionFinished();
3541     }
3542 
3543     /**
3544      * Fades the content of the keyguard away after the launch transition is done.
3545      *
3546      * @param beforeFading the runnable to be run when the circle is fully expanded and the fading
3547      *                     starts
3548      * @param endRunnable the runnable to be run when the transition is done
3549      */
3550     public void fadeKeyguardAfterLaunchTransition(final Runnable beforeFading,
3551             Runnable endRunnable) {
3552         mHandler.removeMessages(MSG_LAUNCH_TRANSITION_TIMEOUT);
3553         mLaunchTransitionEndRunnable = endRunnable;
3554         Runnable hideRunnable = () -> {
3555             mKeyguardStateController.setLaunchTransitionFadingAway(true);
3556             if (beforeFading != null) {
3557                 beforeFading.run();
3558             }
3559             updateScrimController();
3560             mPresenter.updateMediaMetaData(false, true);
3561             mNotificationPanelViewController.setAlpha(1);
3562             mNotificationPanelViewController.fadeOut(
3563                     FADE_KEYGUARD_START_DELAY, FADE_KEYGUARD_DURATION,
3564                     this::onLaunchTransitionFadingEnded);
3565             mCommandQueue.appTransitionStarting(mDisplayId, SystemClock.uptimeMillis(),
3566                     LightBarTransitionsController.DEFAULT_TINT_ANIMATION_DURATION, true);
3567         };
3568         if (mNotificationPanelViewController.isLaunchTransitionRunning()) {
3569             mNotificationPanelViewController.setLaunchTransitionEndRunnable(hideRunnable);
3570         } else {
3571             hideRunnable.run();
3572         }
3573     }
3574 
3575     /**
3576      * Fades the content of the Keyguard while we are dozing and makes it invisible when finished
3577      * fading.
3578      */
3579     public void fadeKeyguardWhilePulsing() {
3580         mNotificationPanelViewController.fadeOut(0, FADE_KEYGUARD_DURATION_PULSING,
3581                 ()-> {
3582                 hideKeyguard();
3583                 mStatusBarKeyguardViewManager.onKeyguardFadedAway();
3584             }).start();
3585     }
3586 
3587     /**
3588      * Plays the animation when an activity that was occluding Keyguard goes away.
3589      */
3590     public void animateKeyguardUnoccluding() {
3591         mNotificationPanelViewController.setExpandedFraction(0f);
3592         animateExpandNotificationsPanel();
3593     }
3594 
3595     /**
3596      * Starts the timeout when we try to start the affordances on Keyguard. We usually rely that
3597      * Keyguard goes away via fadeKeyguardAfterLaunchTransition, however, that might not happen
3598      * because the launched app crashed or something else went wrong.
3599      */
3600     public void startLaunchTransitionTimeout() {
3601         mHandler.sendEmptyMessageDelayed(MSG_LAUNCH_TRANSITION_TIMEOUT,
3602                 LAUNCH_TRANSITION_TIMEOUT_MS);
3603     }
3604 
3605     private void onLaunchTransitionTimeout() {
3606         Log.w(TAG, "Launch transition: Timeout!");
3607         mNotificationPanelViewController.onAffordanceLaunchEnded();
3608         releaseGestureWakeLock();
3609         mNotificationPanelViewController.resetViews(false /* animate */);
3610     }
3611 
3612     private void runLaunchTransitionEndRunnable() {
3613         if (mLaunchTransitionEndRunnable != null) {
3614             Runnable r = mLaunchTransitionEndRunnable;
3615 
3616             // mLaunchTransitionEndRunnable might call showKeyguard, which would execute it again,
3617             // which would lead to infinite recursion. Protect against it.
3618             mLaunchTransitionEndRunnable = null;
3619             r.run();
3620         }
3621     }
3622 
3623     /**
3624      * @return true if we would like to stay in the shade, false if it should go away entirely
3625      */
3626     public boolean hideKeyguardImpl(boolean force) {
3627         mIsKeyguard = false;
3628         Trace.beginSection("StatusBar#hideKeyguard");
3629         boolean staying = mStatusBarStateController.leaveOpenOnKeyguardHide();
3630         int previousState = mStatusBarStateController.getState();
3631         if (!(mStatusBarStateController.setState(StatusBarState.SHADE, force))) {
3632             //TODO: StatusBarStateController should probably know about hiding the keyguard and
3633             // notify listeners.
3634 
3635             // If the state didn't change, we may still need to update public mode
3636             mLockscreenUserManager.updatePublicMode();
3637         }
3638         if (mStatusBarStateController.leaveOpenOnKeyguardHide()) {
3639             if (!mStatusBarStateController.isKeyguardRequested()) {
3640                 mStatusBarStateController.setLeaveOpenOnKeyguardHide(false);
3641             }
3642             long delay = mKeyguardStateController.calculateGoingToFullShadeDelay();
3643             mLockscreenShadeTransitionController.onHideKeyguard(delay, previousState);
3644 
3645             // Disable layout transitions in navbar for this transition because the load is just
3646             // too heavy for the CPU and GPU on any device.
3647             mNavigationBarController.disableAnimationsDuringHide(mDisplayId, delay);
3648         } else if (!mNotificationPanelViewController.isCollapsing()) {
3649             instantCollapseNotificationPanel();
3650         }
3651 
3652         // Keyguard state has changed, but QS is not listening anymore. Make sure to update the tile
3653         // visibilities so next time we open the panel we know the correct height already.
3654         if (mQSPanelController != null) {
3655             mQSPanelController.refreshAllTiles();
3656         }
3657         mHandler.removeMessages(MSG_LAUNCH_TRANSITION_TIMEOUT);
3658         releaseGestureWakeLock();
3659         mNotificationPanelViewController.onAffordanceLaunchEnded();
3660         mNotificationPanelViewController.cancelAnimation();
3661         mNotificationPanelViewController.setAlpha(1f);
3662         mNotificationPanelViewController.resetViewGroupFade();
3663         updateDozingState();
3664         updateScrimController();
3665         Trace.endSection();
3666         return staying;
3667     }
3668 
3669     private void releaseGestureWakeLock() {
3670         if (mGestureWakeLock.isHeld()) {
3671             mGestureWakeLock.release();
3672         }
3673     }
3674 
3675     /**
3676      * Notifies the status bar that Keyguard is going away very soon.
3677      */
3678     public void keyguardGoingAway() {
3679         // Treat Keyguard exit animation as an app transition to achieve nice transition for status
3680         // bar.
3681         mKeyguardStateController.notifyKeyguardGoingAway(true);
3682         mCommandQueue.appTransitionPending(mDisplayId, true /* forced */);
3683     }
3684 
3685     /**
3686      * Notifies the status bar the Keyguard is fading away with the specified timings.
3687      *  @param startTime the start time of the animations in uptime millis
3688      * @param delay the precalculated animation delay in milliseconds
3689      * @param fadeoutDuration the duration of the exit animation, in milliseconds
3690      * @param isBypassFading is this a fading away animation while bypassing
3691      */
3692     public void setKeyguardFadingAway(long startTime, long delay, long fadeoutDuration,
3693             boolean isBypassFading) {
3694         mCommandQueue.appTransitionStarting(mDisplayId, startTime + fadeoutDuration
3695                         - LightBarTransitionsController.DEFAULT_TINT_ANIMATION_DURATION,
3696                 LightBarTransitionsController.DEFAULT_TINT_ANIMATION_DURATION, true);
3697         mCommandQueue.recomputeDisableFlags(mDisplayId, fadeoutDuration > 0 /* animate */);
3698         mCommandQueue.appTransitionStarting(mDisplayId,
3699                     startTime - LightBarTransitionsController.DEFAULT_TINT_ANIMATION_DURATION,
3700                     LightBarTransitionsController.DEFAULT_TINT_ANIMATION_DURATION, true);
3701         mKeyguardStateController.notifyKeyguardFadingAway(delay, fadeoutDuration, isBypassFading);
3702     }
3703 
3704     /**
3705      * Notifies that the Keyguard fading away animation is done.
3706      */
3707     public void finishKeyguardFadingAway() {
3708         mKeyguardStateController.notifyKeyguardDoneFading();
3709         mScrimController.setExpansionAffectsAlpha(true);
3710     }
3711 
3712     /**
3713      * Switches theme from light to dark and vice-versa.
3714      */
3715     protected void updateTheme() {
3716 
3717         // Lock wallpaper defines the color of the majority of the views, hence we'll use it
3718         // to set our default theme.
3719         final boolean lockDarkText = mColorExtractor.getNeutralColors().supportsDarkText();
3720         final int themeResId = lockDarkText ? R.style.Theme_SystemUI_LightWallpaper
3721                 : R.style.Theme_SystemUI;
3722         if (mContext.getThemeResId() != themeResId) {
3723             mContext.setTheme(themeResId);
3724             mConfigurationController.notifyThemeChanged();
3725         }
3726     }
3727 
3728     private void updateDozingState() {
3729         Trace.traceCounter(Trace.TRACE_TAG_APP, "dozing", mDozing ? 1 : 0);
3730         Trace.beginSection("StatusBar#updateDozingState");
3731 
3732         boolean visibleNotOccluded = mStatusBarKeyguardViewManager.isShowing()
3733                 && !mStatusBarKeyguardViewManager.isOccluded();
3734         // If we're dozing and we'll be animating the screen off, the keyguard isn't currently
3735         // visible but will be shortly for the animation, so we should proceed as if it's visible.
3736         boolean visibleNotOccludedOrWillBe =
3737                 visibleNotOccluded || (mDozing && mDozeParameters.shouldControlUnlockedScreenOff());
3738 
3739         boolean wakeAndUnlock = mBiometricUnlockController.getMode()
3740                 == BiometricUnlockController.MODE_WAKE_AND_UNLOCK;
3741         boolean animate = (!mDozing && mDozeServiceHost.shouldAnimateWakeup() && !wakeAndUnlock)
3742                 || (mDozing && mDozeServiceHost.shouldAnimateScreenOff()
3743                 && visibleNotOccludedOrWillBe);
3744 
3745         mNotificationPanelViewController.setDozing(mDozing, animate, mWakeUpTouchLocation);
3746         updateQsExpansionEnabled();
3747         Trace.endSection();
3748     }
3749 
3750     public void userActivity() {
3751         if (mState == StatusBarState.KEYGUARD) {
3752             mKeyguardViewMediatorCallback.userActivity();
3753         }
3754     }
3755 
3756     public boolean interceptMediaKey(KeyEvent event) {
3757         return mState == StatusBarState.KEYGUARD
3758                 && mStatusBarKeyguardViewManager.interceptMediaKey(event);
3759     }
3760 
3761     /**
3762      * While IME is active and a BACK event is detected, check with
3763      * {@link StatusBarKeyguardViewManager#dispatchBackKeyEventPreIme(KeyEvent)} to see if the event
3764      * should be handled before routing to IME, in order to prevent the user having to hit back
3765      * twice to exit bouncer.
3766      */
3767     public boolean dispatchKeyEventPreIme(KeyEvent event) {
3768         switch (event.getKeyCode()) {
3769             case KeyEvent.KEYCODE_BACK:
3770                 if (mState == StatusBarState.KEYGUARD
3771                         && mStatusBarKeyguardViewManager.dispatchBackKeyEventPreIme()) {
3772                     return onBackPressed();
3773                 }
3774         }
3775         return false;
3776     }
3777 
3778     protected boolean shouldUnlockOnMenuPressed() {
3779         return mDeviceInteractive && mState != StatusBarState.SHADE
3780             && mStatusBarKeyguardViewManager.shouldDismissOnMenuPressed();
3781     }
3782 
3783     public boolean onMenuPressed() {
3784         if (shouldUnlockOnMenuPressed()) {
3785             mShadeController.animateCollapsePanels(
3786                     CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL /* flags */, true /* force */);
3787             return true;
3788         }
3789         return false;
3790     }
3791 
3792     public void endAffordanceLaunch() {
3793         releaseGestureWakeLock();
3794         mNotificationPanelViewController.onAffordanceLaunchEnded();
3795     }
3796 
3797     public boolean onBackPressed() {
3798         boolean isScrimmedBouncer = mScrimController.getState() == ScrimState.BOUNCER_SCRIMMED;
3799         if (mStatusBarKeyguardViewManager.onBackPressed(isScrimmedBouncer /* hideImmediately */)) {
3800             if (isScrimmedBouncer) {
3801                 mStatusBarStateController.setLeaveOpenOnKeyguardHide(false);
3802             } else {
3803                 mNotificationPanelViewController.expandWithoutQs();
3804             }
3805             return true;
3806         }
3807         if (mNotificationPanelViewController.isQsExpanded()) {
3808             if (mNotificationPanelViewController.isQsDetailShowing()) {
3809                 mNotificationPanelViewController.closeQsDetail();
3810             } else {
3811                 mNotificationPanelViewController.animateCloseQs(false /* animateAway */);
3812             }
3813             return true;
3814         }
3815         if (mNotificationPanelViewController.closeUserSwitcherIfOpen()) {
3816             return true;
3817         }
3818         if (mState != StatusBarState.KEYGUARD && mState != StatusBarState.SHADE_LOCKED) {
3819             if (mNotificationPanelViewController.canPanelBeCollapsed()) {
3820                 mShadeController.animateCollapsePanels();
3821             }
3822             return true;
3823         }
3824         return false;
3825     }
3826 
3827     public boolean onSpacePressed() {
3828         if (mDeviceInteractive && mState != StatusBarState.SHADE) {
3829             mShadeController.animateCollapsePanels(
3830                     CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL /* flags */, true /* force */);
3831             return true;
3832         }
3833         return false;
3834     }
3835 
3836     private void showBouncerIfKeyguard() {
3837         if (!mKeyguardViewMediator.isHiding()) {
3838             if (mState == StatusBarState.KEYGUARD
3839                     && !mStatusBarKeyguardViewManager.bouncerIsOrWillBeShowing()) {
3840                 mStatusBarKeyguardViewManager.showGenericBouncer(true /* scrimmed */);
3841             } else if (mState == StatusBarState.SHADE_LOCKED) {
3842                 mStatusBarKeyguardViewManager.showBouncer(true /* scrimmed */);
3843             }
3844         }
3845     }
3846 
3847     /**
3848      * Show the bouncer if we're currently on the keyguard or shade locked and aren't hiding.
3849      * @param performAction the action to perform when the bouncer is dismissed.
3850      * @param cancelAction the action to perform when unlock is aborted.
3851      */
3852     public void showBouncerWithDimissAndCancelIfKeyguard(OnDismissAction performAction,
3853             Runnable cancelAction) {
3854         if ((mState == StatusBarState.KEYGUARD || mState == StatusBarState.SHADE_LOCKED)
3855                 && !mKeyguardViewMediator.isHiding()) {
3856             mStatusBarKeyguardViewManager.dismissWithAction(performAction, cancelAction,
3857                     false /* afterKeyguardGone */);
3858         } else if (cancelAction != null) {
3859             cancelAction.run();
3860         }
3861     }
3862 
3863     void instantCollapseNotificationPanel() {
3864         mNotificationPanelViewController.instantCollapse();
3865         mShadeController.runPostCollapseRunnables();
3866     }
3867 
3868     /**
3869      * Collapse the panel directly if we are on the main thread, post the collapsing on the main
3870      * thread if we are not.
3871      */
3872     void collapsePanelOnMainThread() {
3873         if (Looper.getMainLooper().isCurrentThread()) {
3874             mShadeController.collapsePanel();
3875         } else {
3876             mContext.getMainExecutor().execute(mShadeController::collapsePanel);
3877         }
3878     }
3879 
3880     /** Collapse the panel. The collapsing will be animated for the given {@code duration}. */
3881     void collapsePanelWithDuration(int duration) {
3882         mNotificationPanelViewController.collapseWithDuration(duration);
3883     }
3884 
3885     @Override
3886     public void onStatePreChange(int oldState, int newState) {
3887         // If we're visible and switched to SHADE_LOCKED (the user dragged
3888         // down on the lockscreen), clear notification LED, vibration,
3889         // ringing.
3890         // Other transitions are covered in handleVisibleToUserChanged().
3891         if (mVisible && (newState == StatusBarState.SHADE_LOCKED
3892                 || mStatusBarStateController.goingToFullShade())) {
3893             clearNotificationEffects();
3894         }
3895         if (newState == StatusBarState.KEYGUARD) {
3896             mRemoteInputManager.onPanelCollapsed();
3897             maybeEscalateHeadsUp();
3898         }
3899     }
3900 
3901     @Override
3902     public void onStateChanged(int newState) {
3903         mState = newState;
3904         updateReportRejectedTouchVisibility();
3905         mDozeServiceHost.updateDozing();
3906         updateTheme();
3907         mNavigationBarController.touchAutoDim(mDisplayId);
3908         Trace.beginSection("StatusBar#updateKeyguardState");
3909         if (mState == StatusBarState.KEYGUARD && mStatusBarView != null) {
3910             mStatusBarView.removePendingHideExpandedRunnables();
3911         }
3912         updateDozingState();
3913         checkBarModes();
3914         updateScrimController();
3915         mPresenter.updateMediaMetaData(false, mState != StatusBarState.KEYGUARD);
3916         updateKeyguardState();
3917         Trace.endSection();
3918     }
3919 
3920     @Override
3921     public void onDozeAmountChanged(float linear, float eased) {
3922         if (mFeatureFlags.useNewLockscreenAnimations()
3923                 && !(mLightRevealScrim.getRevealEffect() instanceof CircleReveal)) {
3924             mLightRevealScrim.setRevealAmount(1f - linear);
3925         }
3926     }
3927 
3928     @Override
3929     public void onDozingChanged(boolean isDozing) {
3930         Trace.beginSection("StatusBar#updateDozing");
3931         mDozing = isDozing;
3932 
3933         // Collapse the notification panel if open
3934         boolean dozingAnimated = mDozeServiceHost.getDozingRequested()
3935                 && mDozeParameters.shouldControlScreenOff();
3936         mNotificationPanelViewController.resetViews(dozingAnimated);
3937 
3938         updateQsExpansionEnabled();
3939         mKeyguardViewMediator.setDozing(mDozing);
3940 
3941         mNotificationsController.requestNotificationUpdate("onDozingChanged");
3942         updateDozingState();
3943         mDozeServiceHost.updateDozing();
3944         updateScrimController();
3945         updateReportRejectedTouchVisibility();
3946         Trace.endSection();
3947     }
3948 
3949     /**
3950      * Updates the light reveal effect to reflect the reason we're waking or sleeping (for example,
3951      * from the power button).
3952      * @param wakingUp Whether we're updating because we're waking up (true) or going to sleep
3953      *                 (false).
3954      */
3955     private void updateRevealEffect(boolean wakingUp) {
3956         if (mLightRevealScrim == null) {
3957             return;
3958         }
3959 
3960         if (wakingUp && mWakefulnessLifecycle.getLastWakeReason()
3961                 == PowerManager.WAKE_REASON_POWER_BUTTON
3962                 || !wakingUp && mWakefulnessLifecycle.getLastSleepReason()
3963                 == PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON) {
3964             mLightRevealScrim.setRevealEffect(mPowerButtonReveal);
3965         } else if (!wakingUp || !(mLightRevealScrim.getRevealEffect() instanceof CircleReveal)) {
3966             // If we're going to sleep, but it's not from the power button, use the default reveal.
3967             // If we're waking up, only use the default reveal if the biometric controller didn't
3968             // already set it to the circular reveal because we're waking up from a fingerprint/face
3969             // auth.
3970             mLightRevealScrim.setRevealEffect(LiftReveal.INSTANCE);
3971         }
3972     }
3973 
3974     public LightRevealScrim getLightRevealScrim() {
3975         return mLightRevealScrim;
3976     }
3977 
3978     private void updateKeyguardState() {
3979         mKeyguardStateController.notifyKeyguardState(mStatusBarKeyguardViewManager.isShowing(),
3980                 mStatusBarKeyguardViewManager.isOccluded());
3981     }
3982 
3983     public void onTrackingStarted() {
3984         mShadeController.runPostCollapseRunnables();
3985     }
3986 
3987     public void onClosingFinished() {
3988         mShadeController.runPostCollapseRunnables();
3989         if (!mPresenter.isPresenterFullyCollapsed()) {
3990             // if we set it not to be focusable when collapsing, we have to undo it when we aborted
3991             // the closing
3992             mNotificationShadeWindowController.setNotificationShadeFocusable(true);
3993         }
3994     }
3995 
3996     public void onUnlockHintStarted() {
3997         mFalsingCollector.onUnlockHintStarted();
3998         mKeyguardIndicationController.showActionToUnlock();
3999     }
4000 
4001     public void onHintFinished() {
4002         // Delay the reset a bit so the user can read the text.
4003         mKeyguardIndicationController.hideTransientIndicationDelayed(HINT_RESET_DELAY_MS);
4004     }
4005 
4006     public void onCameraHintStarted() {
4007         mFalsingCollector.onCameraHintStarted();
4008         mKeyguardIndicationController.showTransientIndication(R.string.camera_hint);
4009     }
4010 
4011     public void onVoiceAssistHintStarted() {
4012         mFalsingCollector.onLeftAffordanceHintStarted();
4013         mKeyguardIndicationController.showTransientIndication(R.string.voice_hint);
4014     }
4015 
4016     public void onPhoneHintStarted() {
4017         mFalsingCollector.onLeftAffordanceHintStarted();
4018         mKeyguardIndicationController.showTransientIndication(R.string.phone_hint);
4019     }
4020 
4021     public void onTrackingStopped(boolean expand) {
4022         if (mState == StatusBarState.KEYGUARD || mState == StatusBarState.SHADE_LOCKED) {
4023             if (!expand && !mKeyguardStateController.canDismissLockScreen()) {
4024                 mStatusBarKeyguardViewManager.showBouncer(false /* scrimmed */);
4025             }
4026         }
4027     }
4028 
4029     // TODO: Figure out way to remove these.
4030     public NavigationBarView getNavigationBarView() {
4031         return mNavigationBarController.getNavigationBarView(mDisplayId);
4032     }
4033 
4034     /**
4035      * TODO: Remove this method. Views should not be passed forward. Will cause theme issues.
4036      * @return bottom area view
4037      */
4038     public KeyguardBottomAreaView getKeyguardBottomAreaView() {
4039         return mNotificationPanelViewController.getKeyguardBottomAreaView();
4040     }
4041 
4042     /**
4043      * Propagation of the bouncer state, indicating that it's fully visible.
4044      */
4045     public void setBouncerShowing(boolean bouncerShowing) {
4046         mBouncerShowing = bouncerShowing;
4047         mKeyguardBypassController.setBouncerShowing(bouncerShowing);
4048         mPulseExpansionHandler.setBouncerShowing(bouncerShowing);
4049         if (mStatusBarView != null) mStatusBarView.setBouncerShowing(bouncerShowing);
4050         updateHideIconsForBouncer(true /* animate */);
4051         mCommandQueue.recomputeDisableFlags(mDisplayId, true /* animate */);
4052         updateScrimController();
4053         if (!mBouncerShowing) {
4054             updatePanelExpansionForKeyguard();
4055         }
4056     }
4057 
4058     /**
4059      * Collapses the notification shade if it is tracking or expanded.
4060      */
4061     public void collapseShade() {
4062         if (mNotificationPanelViewController.isTracking()) {
4063             mNotificationShadeWindowViewController.cancelCurrentTouch();
4064         }
4065         if (mPanelExpanded && mState == StatusBarState.SHADE) {
4066             mShadeController.animateCollapsePanels();
4067         }
4068     }
4069 
4070     @VisibleForTesting
4071     final WakefulnessLifecycle.Observer mWakefulnessObserver = new WakefulnessLifecycle.Observer() {
4072         @Override
4073         public void onFinishedGoingToSleep() {
4074             mNotificationPanelViewController.onAffordanceLaunchEnded();
4075             releaseGestureWakeLock();
4076             mLaunchCameraWhenFinishedWaking = false;
4077             mDeviceInteractive = false;
4078             mWakeUpComingFromTouch = false;
4079             mWakeUpTouchLocation = null;
4080             updateVisibleToUser();
4081 
4082             updateNotificationPanelTouchState();
4083             mNotificationShadeWindowViewController.cancelCurrentTouch();
4084             if (mLaunchCameraOnFinishedGoingToSleep) {
4085                 mLaunchCameraOnFinishedGoingToSleep = false;
4086 
4087                 // This gets executed before we will show Keyguard, so post it in order that the state
4088                 // is correct.
4089                 mHandler.post(() -> onCameraLaunchGestureDetected(mLastCameraLaunchSource));
4090             }
4091 
4092             if (mLaunchEmergencyActionOnFinishedGoingToSleep) {
4093                 mLaunchEmergencyActionOnFinishedGoingToSleep = false;
4094 
4095                 // This gets executed before we will show Keyguard, so post it in order that the
4096                 // state is correct.
4097                 mHandler.post(() -> onEmergencyActionLaunchGestureDetected());
4098             }
4099             updateIsKeyguard();
4100         }
4101 
4102         @Override
4103         public void onStartedGoingToSleep() {
4104             String tag = "StatusBar#onStartedGoingToSleep";
4105             DejankUtils.startDetectingBlockingIpcs(tag);
4106             updateRevealEffect(false /* wakingUp */);
4107             updateNotificationPanelTouchState();
4108             notifyHeadsUpGoingToSleep();
4109             dismissVolumeDialog();
4110             mWakeUpCoordinator.setFullyAwake(false);
4111             mBypassHeadsUpNotifier.setFullyAwake(false);
4112             mKeyguardBypassController.onStartedGoingToSleep();
4113 
4114             // The screen off animation uses our LightRevealScrim - we need to be expanded for it to
4115             // be visible.
4116             if (mDozeParameters.shouldControlUnlockedScreenOff()) {
4117                 makeExpandedVisible(true);
4118             }
4119 
4120             DejankUtils.stopDetectingBlockingIpcs(tag);
4121         }
4122 
4123         @Override
4124         public void onStartedWakingUp() {
4125             String tag = "StatusBar#onStartedWakingUp";
4126             DejankUtils.startDetectingBlockingIpcs(tag);
4127             mDeviceInteractive = true;
4128             mWakeUpCoordinator.setWakingUp(true);
4129             if (!mKeyguardBypassController.getBypassEnabled()) {
4130                 mHeadsUpManager.releaseAllImmediately();
4131             }
4132             updateVisibleToUser();
4133             updateIsKeyguard();
4134             mDozeServiceHost.stopDozing();
4135             // This is intentionally below the stopDozing call above, since it avoids that we're
4136             // unnecessarily animating the wakeUp transition. Animations should only be enabled
4137             // once we fully woke up.
4138             updateRevealEffect(true /* wakingUp */);
4139             updateNotificationPanelTouchState();
4140             mPulseExpansionHandler.onStartedWakingUp();
4141 
4142             // If we are waking up during the screen off animation, we should undo making the
4143             // expanded visible (we did that so the LightRevealScrim would be visible).
4144             if (mUnlockedScreenOffAnimationController.isScreenOffLightRevealAnimationPlaying()) {
4145                 makeExpandedInvisible();
4146             }
4147 
4148             DejankUtils.stopDetectingBlockingIpcs(tag);
4149         }
4150 
4151         @Override
4152         public void onFinishedWakingUp() {
4153             mWakeUpCoordinator.setFullyAwake(true);
4154             mBypassHeadsUpNotifier.setFullyAwake(true);
4155             mWakeUpCoordinator.setWakingUp(false);
4156             if (mLaunchCameraWhenFinishedWaking) {
4157                 mNotificationPanelViewController.launchCamera(
4158                         false /* animate */, mLastCameraLaunchSource);
4159                 mLaunchCameraWhenFinishedWaking = false;
4160             }
4161             if (mLaunchEmergencyActionWhenFinishedWaking) {
4162                 mLaunchEmergencyActionWhenFinishedWaking = false;
4163                 Intent emergencyIntent = getEmergencyActionIntent();
4164                 if (emergencyIntent != null) {
4165                     mContext.startActivityAsUser(emergencyIntent, UserHandle.CURRENT);
4166                 }
4167             }
4168             updateScrimController();
4169         }
4170     };
4171 
4172     /**
4173      * We need to disable touch events because these might
4174      * collapse the panel after we expanded it, and thus we would end up with a blank
4175      * Keyguard.
4176      */
4177     void updateNotificationPanelTouchState() {
4178         boolean goingToSleepWithoutAnimation = isGoingToSleep()
4179                 && !mDozeParameters.shouldControlScreenOff();
4180         boolean disabled = (!mDeviceInteractive && !mDozeServiceHost.isPulsing())
4181                 || goingToSleepWithoutAnimation;
4182         mNotificationPanelViewController.setTouchAndAnimationDisabled(disabled);
4183         mNotificationIconAreaController.setAnimationsEnabled(!disabled);
4184     }
4185 
4186     final ScreenLifecycle.Observer mScreenObserver = new ScreenLifecycle.Observer() {
4187         @Override
4188         public void onScreenTurningOn() {
4189             mFalsingCollector.onScreenTurningOn();
4190             mNotificationPanelViewController.onScreenTurningOn();
4191         }
4192 
4193         @Override
4194         public void onScreenTurnedOn() {
4195             mScrimController.onScreenTurnedOn();
4196         }
4197 
4198         @Override
4199         public void onScreenTurnedOff() {
4200             mFalsingCollector.onScreenOff();
4201             mScrimController.onScreenTurnedOff();
4202             updateIsKeyguard();
4203         }
4204     };
4205 
4206     public int getWakefulnessState() {
4207         return mWakefulnessLifecycle.getWakefulness();
4208     }
4209 
4210     private void vibrateForCameraGesture() {
4211         // Make sure to pass -1 for repeat so VibratorService doesn't stop us when going to sleep.
4212         mVibrator.vibrate(mCameraLaunchGestureVibrationEffect, VIBRATION_ATTRIBUTES);
4213     }
4214 
4215     private static VibrationEffect getCameraGestureVibrationEffect(Vibrator vibrator,
4216             Resources resources) {
4217         if (vibrator.areAllPrimitivesSupported(
4218                 VibrationEffect.Composition.PRIMITIVE_QUICK_RISE,
4219                 VibrationEffect.Composition.PRIMITIVE_CLICK)) {
4220             return VibrationEffect.startComposition()
4221                     .addPrimitive(VibrationEffect.Composition.PRIMITIVE_QUICK_RISE)
4222                     .addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK, 1, 50)
4223                     .compose();
4224         }
4225         if (vibrator.hasAmplitudeControl()) {
4226             return VibrationEffect.createWaveform(
4227                     CAMERA_LAUNCH_GESTURE_VIBRATION_TIMINGS,
4228                     CAMERA_LAUNCH_GESTURE_VIBRATION_AMPLITUDES,
4229                     /* repeat= */ -1);
4230         }
4231 
4232         int[] pattern = resources.getIntArray(R.array.config_cameraLaunchGestureVibePattern);
4233         long[] timings = new long[pattern.length];
4234         for (int i = 0; i < pattern.length; i++) {
4235             timings[i] = pattern[i];
4236         }
4237         return VibrationEffect.createWaveform(timings, /* repeat= */ -1);
4238     }
4239 
4240     /**
4241      * @return true if the screen is currently fully off, i.e. has finished turning off and has
4242      * since not started turning on.
4243      */
4244     public boolean isScreenFullyOff() {
4245         return mScreenLifecycle.getScreenState() == ScreenLifecycle.SCREEN_OFF;
4246     }
4247 
4248     @Override
4249     public void showScreenPinningRequest(int taskId) {
4250         if (mKeyguardStateController.isShowing()) {
4251             // Don't allow apps to trigger this from keyguard.
4252             return;
4253         }
4254         // Show screen pinning request, since this comes from an app, show 'no thanks', button.
4255         showScreenPinningRequest(taskId, true);
4256     }
4257 
4258     public void showScreenPinningRequest(int taskId, boolean allowCancel) {
4259         mScreenPinningRequest.showPrompt(taskId, allowCancel);
4260     }
4261 
4262     @Override
4263     public void appTransitionCancelled(int displayId) {
4264         if (displayId == mDisplayId) {
4265             mSplitScreenOptional.ifPresent(splitScreen -> splitScreen.onAppTransitionFinished());
4266         }
4267     }
4268 
4269     @Override
4270     public void appTransitionFinished(int displayId) {
4271         if (displayId == mDisplayId) {
4272             mSplitScreenOptional.ifPresent(splitScreen -> splitScreen.onAppTransitionFinished());
4273         }
4274     }
4275 
4276     @Override
4277     public void onCameraLaunchGestureDetected(int source) {
4278         mLastCameraLaunchSource = source;
4279         if (isGoingToSleep()) {
4280             if (DEBUG_CAMERA_LIFT) Slog.d(TAG, "Finish going to sleep before launching camera");
4281             mLaunchCameraOnFinishedGoingToSleep = true;
4282             return;
4283         }
4284         if (!mNotificationPanelViewController.canCameraGestureBeLaunched()) {
4285             if (DEBUG_CAMERA_LIFT) Slog.d(TAG, "Can't launch camera right now");
4286             return;
4287         }
4288         if (!mDeviceInteractive) {
4289             mPowerManager.wakeUp(SystemClock.uptimeMillis(), PowerManager.WAKE_REASON_CAMERA_LAUNCH,
4290                     "com.android.systemui:CAMERA_GESTURE");
4291         }
4292         vibrateForCameraGesture();
4293 
4294         if (source == StatusBarManager.CAMERA_LAUNCH_SOURCE_POWER_DOUBLE_TAP) {
4295             Log.v(TAG, "Camera launch");
4296             mKeyguardUpdateMonitor.onCameraLaunched();
4297         }
4298 
4299         if (!mStatusBarKeyguardViewManager.isShowing()) {
4300             final Intent cameraIntent = CameraIntents.getInsecureCameraIntent(mContext);
4301             startActivityDismissingKeyguard(cameraIntent,
4302                     false /* onlyProvisioned */, true /* dismissShade */,
4303                     true /* disallowEnterPictureInPictureWhileLaunching */, null /* callback */, 0,
4304                     null /* animationController */);
4305         } else {
4306             if (!mDeviceInteractive) {
4307                 // Avoid flickering of the scrim when we instant launch the camera and the bouncer
4308                 // comes on.
4309                 mGestureWakeLock.acquire(LAUNCH_TRANSITION_TIMEOUT_MS + 1000L);
4310             }
4311             if (isWakingUpOrAwake()) {
4312                 if (DEBUG_CAMERA_LIFT) Slog.d(TAG, "Launching camera");
4313                 if (mStatusBarKeyguardViewManager.isBouncerShowing()) {
4314                     mStatusBarKeyguardViewManager.reset(true /* hide */);
4315                 }
4316                 mNotificationPanelViewController.launchCamera(
4317                         mDeviceInteractive /* animate */, source);
4318                 updateScrimController();
4319             } else {
4320                 // We need to defer the camera launch until the screen comes on, since otherwise
4321                 // we will dismiss us too early since we are waiting on an activity to be drawn and
4322                 // incorrectly get notified because of the screen on event (which resumes and pauses
4323                 // some activities)
4324                 if (DEBUG_CAMERA_LIFT) Slog.d(TAG, "Deferring until screen turns on");
4325                 mLaunchCameraWhenFinishedWaking = true;
4326             }
4327         }
4328     }
4329 
4330     @Override
4331     public void onEmergencyActionLaunchGestureDetected() {
4332         Intent emergencyIntent = getEmergencyActionIntent();
4333 
4334         if (emergencyIntent == null) {
4335             Log.wtf(TAG, "Couldn't find an app to process the emergency intent.");
4336             return;
4337         }
4338 
4339         if (isGoingToSleep()) {
4340             mLaunchEmergencyActionOnFinishedGoingToSleep = true;
4341             return;
4342         }
4343 
4344         if (!mDeviceInteractive) {
4345             mPowerManager.wakeUp(SystemClock.uptimeMillis(),
4346                     PowerManager.WAKE_REASON_GESTURE,
4347                     "com.android.systemui:EMERGENCY_GESTURE");
4348         }
4349         // TODO(b/169087248) Possibly add haptics here for emergency action. Currently disabled for
4350         // app-side haptic experimentation.
4351 
4352         if (!mStatusBarKeyguardViewManager.isShowing()) {
4353             startActivityDismissingKeyguard(emergencyIntent,
4354                     false /* onlyProvisioned */, true /* dismissShade */,
4355                     true /* disallowEnterPictureInPictureWhileLaunching */, null /* callback */, 0,
4356                     null /* animationController */);
4357             return;
4358         }
4359 
4360         if (!mDeviceInteractive) {
4361             // Avoid flickering of the scrim when we instant launch the camera and the bouncer
4362             // comes on.
4363             mGestureWakeLock.acquire(LAUNCH_TRANSITION_TIMEOUT_MS + 1000L);
4364         }
4365 
4366         if (isWakingUpOrAwake()) {
4367             if (mStatusBarKeyguardViewManager.isBouncerShowing()) {
4368                 mStatusBarKeyguardViewManager.reset(true /* hide */);
4369             }
4370             mContext.startActivityAsUser(emergencyIntent, UserHandle.CURRENT);
4371             return;
4372         }
4373         // We need to defer the emergency action launch until the screen comes on, since otherwise
4374         // we will dismiss us too early since we are waiting on an activity to be drawn and
4375         // incorrectly get notified because of the screen on event (which resumes and pauses
4376         // some activities)
4377         mLaunchEmergencyActionWhenFinishedWaking = true;
4378     }
4379 
4380     private @Nullable Intent getEmergencyActionIntent() {
4381         Intent emergencyIntent = new Intent(EmergencyGesture.ACTION_LAUNCH_EMERGENCY);
4382         PackageManager pm = mContext.getPackageManager();
4383         List<ResolveInfo> emergencyActivities = pm.queryIntentActivities(emergencyIntent,
4384                 PackageManager.MATCH_SYSTEM_ONLY);
4385         ResolveInfo resolveInfo = getTopEmergencySosInfo(emergencyActivities);
4386         if (resolveInfo == null) {
4387             Log.wtf(TAG, "Couldn't find an app to process the emergency intent.");
4388             return null;
4389         }
4390         emergencyIntent.setComponent(new ComponentName(resolveInfo.activityInfo.packageName,
4391                 resolveInfo.activityInfo.name));
4392         emergencyIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
4393         return emergencyIntent;
4394     }
4395 
4396     /**
4397      * Select and return the "best" ResolveInfo for Emergency SOS Activity.
4398      */
4399     private @Nullable ResolveInfo getTopEmergencySosInfo(List<ResolveInfo> emergencyActivities) {
4400         // No matched activity.
4401         if (emergencyActivities == null || emergencyActivities.isEmpty()) {
4402             return null;
4403         }
4404 
4405         // Of multiple matched Activities, give preference to the pre-set package name.
4406         String preferredAppPackageName =
4407                 mContext.getString(R.string.config_preferredEmergencySosPackage);
4408 
4409         // If there is no preferred app, then return first match.
4410         if (TextUtils.isEmpty(preferredAppPackageName)) {
4411             return emergencyActivities.get(0);
4412         }
4413 
4414         for (ResolveInfo emergencyInfo: emergencyActivities) {
4415             // If activity is from the preferred app, use it.
4416             if (TextUtils.equals(emergencyInfo.activityInfo.packageName, preferredAppPackageName)) {
4417                 return emergencyInfo;
4418             }
4419         }
4420         // No matching activity: return first match
4421         return emergencyActivities.get(0);
4422     }
4423 
4424     boolean isCameraAllowedByAdmin() {
4425         if (mDevicePolicyManager.getCameraDisabled(null,
4426                 mLockscreenUserManager.getCurrentUserId())) {
4427             return false;
4428         } else if (mStatusBarKeyguardViewManager == null
4429                 || (isKeyguardShowing() && isKeyguardSecure())) {
4430             // Check if the admin has disabled the camera specifically for the keyguard
4431             return (mDevicePolicyManager.getKeyguardDisabledFeatures(null,
4432                     mLockscreenUserManager.getCurrentUserId())
4433                     & DevicePolicyManager.KEYGUARD_DISABLE_SECURE_CAMERA) == 0;
4434         }
4435         return true;
4436     }
4437 
4438     private boolean isGoingToSleep() {
4439         return mWakefulnessLifecycle.getWakefulness()
4440                 == WakefulnessLifecycle.WAKEFULNESS_GOING_TO_SLEEP;
4441     }
4442 
4443     private boolean isWakingUpOrAwake() {
4444         return mWakefulnessLifecycle.getWakefulness() == WAKEFULNESS_AWAKE
4445                 || mWakefulnessLifecycle.getWakefulness() == WAKEFULNESS_WAKING;
4446     }
4447 
4448     public void notifyBiometricAuthModeChanged() {
4449         mDozeServiceHost.updateDozing();
4450         updateScrimController();
4451     }
4452 
4453     @VisibleForTesting
4454     public void updateScrimController() {
4455         Trace.beginSection("StatusBar#updateScrimController");
4456 
4457         // We don't want to end up in KEYGUARD state when we're unlocking with
4458         // fingerprint from doze. We should cross fade directly from black.
4459         boolean unlocking = mBiometricUnlockController.isWakeAndUnlock()
4460                 || mKeyguardStateController.isKeyguardFadingAway();
4461 
4462         // Do not animate the scrim expansion when triggered by the fingerprint sensor.
4463         mScrimController.setExpansionAffectsAlpha(
4464                 !mBiometricUnlockController.isBiometricUnlock());
4465 
4466         boolean launchingAffordanceWithPreview =
4467                 mNotificationPanelViewController.isLaunchingAffordanceWithPreview();
4468         mScrimController.setLaunchingAffordanceWithPreview(launchingAffordanceWithPreview);
4469 
4470         if (mStatusBarKeyguardViewManager.isShowingAlternateAuth()) {
4471             mScrimController.transitionTo(ScrimState.AUTH_SCRIMMED);
4472         } else if (mBouncerShowing) {
4473             // Bouncer needs the front scrim when it's on top of an activity,
4474             // tapping on a notification, editing QS or being dismissed by
4475             // FLAG_DISMISS_KEYGUARD_ACTIVITY.
4476             ScrimState state = mStatusBarKeyguardViewManager.bouncerNeedsScrimming()
4477                     ? ScrimState.BOUNCER_SCRIMMED : ScrimState.BOUNCER;
4478             mScrimController.transitionTo(state);
4479         } else if (isInLaunchTransition()
4480                 || mLaunchCameraWhenFinishedWaking
4481                 || launchingAffordanceWithPreview) {
4482             // TODO(b/170133395) Investigate whether Emergency Gesture flag should be included here.
4483             mScrimController.transitionTo(ScrimState.UNLOCKED, mUnlockScrimCallback);
4484         } else if (mBrightnessMirrorVisible) {
4485             mScrimController.transitionTo(ScrimState.BRIGHTNESS_MIRROR);
4486         } else if (mState == StatusBarState.SHADE_LOCKED) {
4487             mScrimController.transitionTo(ScrimState.SHADE_LOCKED);
4488         } else if (mDozeServiceHost.isPulsing()) {
4489             mScrimController.transitionTo(ScrimState.PULSING,
4490                     mDozeScrimController.getScrimCallback());
4491         } else if (mDozeServiceHost.hasPendingScreenOffCallback()) {
4492             mScrimController.transitionTo(ScrimState.OFF, new ScrimController.Callback() {
4493                 @Override
4494                 public void onFinished() {
4495                     mDozeServiceHost.executePendingScreenOffCallback();
4496                 }
4497             });
4498         } else if (mDozing && !unlocking) {
4499             mScrimController.transitionTo(ScrimState.AOD);
4500         } else if (mIsKeyguard && !unlocking) {
4501             mScrimController.transitionTo(ScrimState.KEYGUARD);
4502         } else if (mBubblesOptional.isPresent() && mBubblesOptional.get().isStackExpanded()) {
4503             mScrimController.transitionTo(ScrimState.BUBBLE_EXPANDED, mUnlockScrimCallback);
4504         } else {
4505             mScrimController.transitionTo(ScrimState.UNLOCKED, mUnlockScrimCallback);
4506         }
4507         updateLightRevealScrimVisibility();
4508 
4509         Trace.endSection();
4510     }
4511 
4512     public boolean isKeyguardShowing() {
4513         if (mStatusBarKeyguardViewManager == null) {
4514             Slog.i(TAG, "isKeyguardShowing() called before startKeyguard(), returning true");
4515             return true;
4516         }
4517         return mStatusBarKeyguardViewManager.isShowing();
4518     }
4519 
4520     public boolean shouldIgnoreTouch() {
4521         return (mStatusBarStateController.isDozing()
4522                 && mDozeServiceHost.getIgnoreTouchWhilePulsing())
4523                 || mUnlockedScreenOffAnimationController.isScreenOffAnimationPlaying();
4524     }
4525 
4526     // Begin Extra BaseStatusBar methods.
4527 
4528     protected final CommandQueue mCommandQueue;
4529     protected IStatusBarService mBarService;
4530 
4531     // all notifications
4532     protected NotificationStackScrollLayout mStackScroller;
4533 
4534     // handling reordering
4535     private final VisualStabilityManager mVisualStabilityManager;
4536 
4537     protected AccessibilityManager mAccessibilityManager;
4538 
4539     protected boolean mDeviceInteractive;
4540 
4541     protected boolean mVisible;
4542 
4543     // mScreenOnFromKeyguard && mVisible.
4544     private boolean mVisibleToUser;
4545 
4546     protected DevicePolicyManager mDevicePolicyManager;
4547     private final PowerManager mPowerManager;
4548     protected StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
4549 
4550     protected KeyguardManager mKeyguardManager;
4551     private final DeviceProvisionedController mDeviceProvisionedController;
4552 
4553     private final NavigationBarController mNavigationBarController;
4554 
4555     // UI-specific methods
4556 
4557     protected WindowManager mWindowManager;
4558     protected IWindowManager mWindowManagerService;
4559     private IDreamManager mDreamManager;
4560 
4561     protected Display mDisplay;
4562     private int mDisplayId;
4563 
4564     protected NotificationShelfController mNotificationShelfController;
4565 
4566     private final Lazy<AssistManager> mAssistManagerLazy;
4567 
4568     public boolean isDeviceInteractive() {
4569         return mDeviceInteractive;
4570     }
4571 
4572     private final BroadcastReceiver mBannerActionBroadcastReceiver = new BroadcastReceiver() {
4573         @Override
4574         public void onReceive(Context context, Intent intent) {
4575             String action = intent.getAction();
4576             if (BANNER_ACTION_CANCEL.equals(action) || BANNER_ACTION_SETUP.equals(action)) {
4577                 NotificationManager noMan = (NotificationManager)
4578                         mContext.getSystemService(Context.NOTIFICATION_SERVICE);
4579                 noMan.cancel(com.android.internal.messages.nano.SystemMessageProto.SystemMessage.
4580                         NOTE_HIDDEN_NOTIFICATIONS);
4581 
4582                 Settings.Secure.putInt(mContext.getContentResolver(),
4583                         Settings.Secure.SHOW_NOTE_ABOUT_NOTIFICATION_HIDING, 0);
4584                 if (BANNER_ACTION_SETUP.equals(action)) {
4585                     mShadeController.animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL,
4586                             true /* force */);
4587                     mContext.startActivity(new Intent(Settings.ACTION_APP_NOTIFICATION_REDACTION)
4588                             .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
4589 
4590                     );
4591                 }
4592             }
4593         }
4594     };
4595 
4596     public void setNotificationSnoozed(StatusBarNotification sbn, SnoozeOption snoozeOption) {
4597         mNotificationsController.setNotificationSnoozed(sbn, snoozeOption);
4598     }
4599 
4600     @Override
4601     public void toggleSplitScreen() {
4602         toggleSplitScreenMode(-1 /* metricsDockAction */, -1 /* metricsUndockAction */);
4603     }
4604 
4605     public void awakenDreams() {
4606         mUiBgExecutor.execute(() -> {
4607             try {
4608                 mDreamManager.awaken();
4609             } catch (RemoteException e) {
4610                 e.printStackTrace();
4611             }
4612         });
4613     }
4614 
4615     @Override
4616     public void preloadRecentApps() {
4617         int msg = MSG_PRELOAD_RECENT_APPS;
4618         mHandler.removeMessages(msg);
4619         mHandler.sendEmptyMessage(msg);
4620     }
4621 
4622     @Override
4623     public void cancelPreloadRecentApps() {
4624         int msg = MSG_CANCEL_PRELOAD_RECENT_APPS;
4625         mHandler.removeMessages(msg);
4626         mHandler.sendEmptyMessage(msg);
4627     }
4628 
4629     @Override
4630     public void dismissKeyboardShortcutsMenu() {
4631         int msg = MSG_DISMISS_KEYBOARD_SHORTCUTS_MENU;
4632         mHandler.removeMessages(msg);
4633         mHandler.sendEmptyMessage(msg);
4634     }
4635 
4636     @Override
4637     public void toggleKeyboardShortcutsMenu(int deviceId) {
4638         int msg = MSG_TOGGLE_KEYBOARD_SHORTCUTS_MENU;
4639         mHandler.removeMessages(msg);
4640         mHandler.obtainMessage(msg, deviceId, 0).sendToTarget();
4641     }
4642 
4643     @Override
4644     public void setTopAppHidesStatusBar(boolean topAppHidesStatusBar) {
4645         mTopHidesStatusBar = topAppHidesStatusBar;
4646         if (!topAppHidesStatusBar && mWereIconsJustHidden) {
4647             // Immediately update the icon hidden state, since that should only apply if we're
4648             // staying fullscreen.
4649             mWereIconsJustHidden = false;
4650             mCommandQueue.recomputeDisableFlags(mDisplayId, true);
4651         }
4652         updateHideIconsForBouncer(true /* animate */);
4653     }
4654 
4655     protected void toggleKeyboardShortcuts(int deviceId) {
4656         KeyboardShortcuts.toggle(mContext, deviceId);
4657     }
4658 
4659     protected void dismissKeyboardShortcuts() {
4660         KeyboardShortcuts.dismiss();
4661     }
4662 
4663     /**
4664      * Dismiss the keyguard then execute an action.
4665      *
4666      * @param action The action to execute after dismissing the keyguard.
4667      * @param collapsePanel Whether we should collapse the panel after dismissing the keyguard.
4668      * @param willAnimateOnKeyguard Whether {@param action} will run an animation on the keyguard if
4669      *                              we are locked.
4670      */
4671     private void executeActionDismissingKeyguard(Runnable action, boolean afterKeyguardGone,
4672             boolean collapsePanel, boolean willAnimateOnKeyguard) {
4673         if (!mDeviceProvisionedController.isDeviceProvisioned()) return;
4674 
4675         OnDismissAction onDismissAction = new OnDismissAction() {
4676             @Override
4677             public boolean onDismiss() {
4678                 new Thread(() -> {
4679                     try {
4680                         // The intent we are sending is for the application, which
4681                         // won't have permission to immediately start an activity after
4682                         // the user switches to home.  We know it is safe to do at this
4683                         // point, so make sure new activity switches are now allowed.
4684                         ActivityManager.getService().resumeAppSwitches();
4685                     } catch (RemoteException e) {
4686                     }
4687                     action.run();
4688                 }).start();
4689 
4690                 return collapsePanel ? mShadeController.collapsePanel() : willAnimateOnKeyguard;
4691             }
4692 
4693             @Override
4694             public boolean willRunAnimationOnKeyguard() {
4695                 return willAnimateOnKeyguard;
4696             }
4697         };
4698         dismissKeyguardThenExecute(onDismissAction, afterKeyguardGone);
4699     }
4700 
4701     @Override
4702     public void startPendingIntentDismissingKeyguard(final PendingIntent intent) {
4703         startPendingIntentDismissingKeyguard(intent, null);
4704     }
4705 
4706     @Override
4707     public void startPendingIntentDismissingKeyguard(
4708             final PendingIntent intent, @Nullable final Runnable intentSentUiThreadCallback) {
4709         startPendingIntentDismissingKeyguard(intent, intentSentUiThreadCallback,
4710                 (ActivityLaunchAnimator.Controller) null);
4711     }
4712 
4713     @Override
4714     public void startPendingIntentDismissingKeyguard(PendingIntent intent,
4715             Runnable intentSentUiThreadCallback, View associatedView) {
4716         ActivityLaunchAnimator.Controller animationController = null;
4717         if (associatedView instanceof ExpandableNotificationRow) {
4718             animationController = mNotificationAnimationProvider.getAnimatorController(
4719                     ((ExpandableNotificationRow) associatedView));
4720         }
4721 
4722         startPendingIntentDismissingKeyguard(intent, intentSentUiThreadCallback,
4723                 animationController);
4724     }
4725 
4726     @Override
4727     public void startPendingIntentDismissingKeyguard(
4728             final PendingIntent intent, @Nullable final Runnable intentSentUiThreadCallback,
4729             @Nullable ActivityLaunchAnimator.Controller animationController) {
4730         final boolean willLaunchResolverActivity = intent.isActivity()
4731                 && mActivityIntentHelper.wouldLaunchResolverActivity(intent.getIntent(),
4732                 mLockscreenUserManager.getCurrentUserId());
4733 
4734         boolean animate = !willLaunchResolverActivity
4735                 && animationController != null
4736                 && shouldAnimateLaunch(intent.isActivity());
4737 
4738         // If we animate, don't collapse the shade and defer the keyguard dismiss (in case we run
4739         // the animation on the keyguard). The animation will take care of (instantly) collapsing
4740         // the shade and hiding the keyguard once it is done.
4741         boolean collapse = !animate;
4742         executeActionDismissingKeyguard(() -> {
4743             try {
4744                 // We wrap animationCallback with a StatusBarLaunchAnimatorController so that the
4745                 // shade is collapsed after the animation (or when it is cancelled, aborted, etc).
4746                 ActivityLaunchAnimator.Controller controller =
4747                         animationController != null ? new StatusBarLaunchAnimatorController(
4748                                 animationController, this, intent.isActivity()) : null;
4749 
4750                 mActivityLaunchAnimator.startPendingIntentWithAnimation(
4751                         controller, animate, intent.getCreatorPackage(),
4752                         (animationAdapter) -> intent.sendAndReturnResult(null, 0, null, null, null,
4753                                 null, getActivityOptions(mDisplayId, animationAdapter)));
4754             } catch (PendingIntent.CanceledException e) {
4755                 // the stack trace isn't very helpful here.
4756                 // Just log the exception message.
4757                 Log.w(TAG, "Sending intent failed: " + e);
4758                 if (!collapse) {
4759                     // executeActionDismissingKeyguard did not collapse for us already.
4760                     collapsePanelOnMainThread();
4761                 }
4762                 // TODO: Dismiss Keyguard.
4763             }
4764             if (intent.isActivity()) {
4765                 mAssistManagerLazy.get().hideAssist();
4766             }
4767             if (intentSentUiThreadCallback != null) {
4768                 postOnUiThread(intentSentUiThreadCallback);
4769             }
4770         }, willLaunchResolverActivity, collapse, animate);
4771     }
4772 
4773     private void postOnUiThread(Runnable runnable) {
4774         mMainThreadHandler.post(runnable);
4775     }
4776 
4777     /**
4778      * Returns an ActivityOptions bundle created using the given parameters.
4779      *
4780      * @param displayId The ID of the display to launch the activity in. Typically this would be the
4781      *                  display the status bar is on.
4782      * @param animationAdapter The animation adapter used to start this activity, or {@code null}
4783      *                         for the default animation.
4784      */
4785     public static Bundle getActivityOptions(int displayId,
4786             @Nullable RemoteAnimationAdapter animationAdapter) {
4787         ActivityOptions options = getDefaultActivityOptions(animationAdapter);
4788         options.setLaunchDisplayId(displayId);
4789         options.setCallerDisplayId(displayId);
4790         return options.toBundle();
4791     }
4792 
4793     /**
4794      * Returns an ActivityOptions bundle created using the given parameters.
4795      *
4796      * @param displayId The ID of the display to launch the activity in. Typically this would be the
4797      *                  display the status bar is on.
4798      * @param animationAdapter The animation adapter used to start this activity, or {@code null}
4799      *                         for the default animation.
4800      * @param isKeyguardShowing Whether keyguard is currently showing.
4801      * @param eventTime The event time in milliseconds since boot, not including sleep. See
4802      *                  {@link ActivityOptions#setSourceInfo}.
4803      */
4804     public static Bundle getActivityOptions(int displayId,
4805             @Nullable RemoteAnimationAdapter animationAdapter, boolean isKeyguardShowing,
4806             long eventTime) {
4807         ActivityOptions options = getDefaultActivityOptions(animationAdapter);
4808         options.setSourceInfo(isKeyguardShowing ? ActivityOptions.SourceInfo.TYPE_LOCKSCREEN
4809                 : ActivityOptions.SourceInfo.TYPE_NOTIFICATION, eventTime);
4810         options.setLaunchDisplayId(displayId);
4811         options.setCallerDisplayId(displayId);
4812         return options.toBundle();
4813     }
4814 
4815     public static ActivityOptions getDefaultActivityOptions(
4816             @Nullable RemoteAnimationAdapter animationAdapter) {
4817         ActivityOptions options;
4818         if (animationAdapter != null) {
4819             options = ActivityOptions.makeRemoteAnimation(animationAdapter);
4820         } else {
4821             options = ActivityOptions.makeBasic();
4822         }
4823         return options;
4824     }
4825 
4826     void visibilityChanged(boolean visible) {
4827         if (mVisible != visible) {
4828             mVisible = visible;
4829             if (!visible) {
4830                 mGutsManager.closeAndSaveGuts(true /* removeLeavebehind */, true /* force */,
4831                         true /* removeControls */, -1 /* x */, -1 /* y */, true /* resetMenu */);
4832             }
4833         }
4834         updateVisibleToUser();
4835     }
4836 
4837     protected void updateVisibleToUser() {
4838         boolean oldVisibleToUser = mVisibleToUser;
4839         mVisibleToUser = mVisible && mDeviceInteractive;
4840 
4841         if (oldVisibleToUser != mVisibleToUser) {
4842             handleVisibleToUserChanged(mVisibleToUser);
4843         }
4844     }
4845 
4846     /**
4847      * Clear Buzz/Beep/Blink.
4848      */
4849     public void clearNotificationEffects() {
4850         try {
4851             mBarService.clearNotificationEffects();
4852         } catch (RemoteException e) {
4853             // Won't fail unless the world has ended.
4854         }
4855     }
4856 
4857     protected void notifyHeadsUpGoingToSleep() {
4858         maybeEscalateHeadsUp();
4859     }
4860 
4861     /**
4862      * @return Whether the security bouncer from Keyguard is showing.
4863      */
4864     public boolean isBouncerShowing() {
4865         return mBouncerShowing;
4866     }
4867 
4868     /**
4869      * @return Whether the security bouncer from Keyguard is showing.
4870      */
4871     public boolean isBouncerShowingScrimmed() {
4872         return isBouncerShowing() && mStatusBarKeyguardViewManager.bouncerNeedsScrimming();
4873     }
4874 
4875     /**
4876      * When {@link KeyguardBouncer} starts to be dismissed, playing its animation.
4877      */
4878     public void onBouncerPreHideAnimation() {
4879         mNotificationPanelViewController.onBouncerPreHideAnimation();
4880 
4881     }
4882 
4883     /**
4884      * @return a PackageManger for userId or if userId is < 0 (USER_ALL etc) then
4885      *         return PackageManager for mContext
4886      */
4887     public static PackageManager getPackageManagerForUser(Context context, int userId) {
4888         Context contextForUser = context;
4889         // UserHandle defines special userId as negative values, e.g. USER_ALL
4890         if (userId >= 0) {
4891             try {
4892                 // Create a context for the correct user so if a package isn't installed
4893                 // for user 0 we can still load information about the package.
4894                 contextForUser =
4895                         context.createPackageContextAsUser(context.getPackageName(),
4896                         Context.CONTEXT_RESTRICTED,
4897                         new UserHandle(userId));
4898             } catch (NameNotFoundException e) {
4899                 // Shouldn't fail to find the package name for system ui.
4900             }
4901         }
4902         return contextForUser.getPackageManager();
4903     }
4904 
4905     public boolean isKeyguardSecure() {
4906         if (mStatusBarKeyguardViewManager == null) {
4907             // startKeyguard() hasn't been called yet, so we don't know.
4908             // Make sure anything that needs to know isKeyguardSecure() checks and re-checks this
4909             // value onVisibilityChanged().
4910             Slog.w(TAG, "isKeyguardSecure() called before startKeyguard(), returning false",
4911                     new Throwable());
4912             return false;
4913         }
4914         return mStatusBarKeyguardViewManager.isSecure();
4915     }
4916 
4917     @Override
4918     public void showAssistDisclosure() {
4919         mAssistManagerLazy.get().showDisclosure();
4920     }
4921 
4922     public NotificationPanelViewController getPanelController() {
4923         return mNotificationPanelViewController;
4924     }
4925 
4926     @Override
4927     public void startAssist(Bundle args) {
4928         mAssistManagerLazy.get().startAssist(args);
4929     }
4930     // End Extra BaseStatusBarMethods.
4931 
4932     public NotificationGutsManager getGutsManager() {
4933         return mGutsManager;
4934     }
4935 
4936     private boolean isTransientShown() {
4937         return mTransientShown;
4938     }
4939 
4940     @Override
4941     public void suppressAmbientDisplay(boolean suppressed) {
4942         mDozeServiceHost.setDozeSuppressed(suppressed);
4943     }
4944 
4945     public void addExpansionChangedListener(@NonNull ExpansionChangedListener listener) {
4946         mExpansionChangedListeners.add(listener);
4947     }
4948 
4949     public void removeExpansionChangedListener(@NonNull ExpansionChangedListener listener) {
4950         mExpansionChangedListeners.remove(listener);
4951     }
4952 
4953     private void updateLightRevealScrimVisibility() {
4954         if (mLightRevealScrim == null) {
4955             // status bar may not be inflated yet
4956             return;
4957         }
4958 
4959         mLightRevealScrim.setAlpha(mScrimController.getState().getMaxLightRevealScrimAlpha());
4960         if (mFeatureFlags.useNewLockscreenAnimations()
4961                 && (mDozeParameters.getAlwaysOn() || mDozeParameters.isQuickPickupEnabled())) {
4962             mLightRevealScrim.setVisibility(View.VISIBLE);
4963         } else {
4964             mLightRevealScrim.setVisibility(View.GONE);
4965         }
4966     }
4967 }
4968