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