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