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