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