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