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