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