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