1 /* 2 * Copyright (C) 2010 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.systemui.statusbar.phone; 18 19 import static android.app.StatusBarManager.WINDOW_STATE_HIDDEN; 20 import static android.app.StatusBarManager.WINDOW_STATE_SHOWING; 21 import static android.app.StatusBarManager.windowStateToString; 22 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY; 23 24 import static com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_ASLEEP; 25 import static com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_AWAKE; 26 import static com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_WAKING; 27 import static com.android.systemui.shared.system.WindowManagerWrapper.NAV_BAR_POS_LEFT; 28 import static com.android.systemui.shared.system.WindowManagerWrapper.NAV_BAR_POS_INVALID; 29 import static com.android.systemui.statusbar.NotificationLockscreenUserManager 30 .NOTIFICATION_UNLOCKED_BY_WORK_CHALLENGE_ACTION; 31 import static com.android.systemui.statusbar.NotificationLockscreenUserManager.PERMISSION_SELF; 32 import static com.android.systemui.statusbar.NotificationMediaManager.DEBUG_MEDIA; 33 import static com.android.systemui.statusbar.phone.BarTransitions.MODE_LIGHTS_OUT; 34 import static com.android.systemui.statusbar.phone.BarTransitions.MODE_LIGHTS_OUT_TRANSPARENT; 35 import static com.android.systemui.statusbar.phone.BarTransitions.MODE_OPAQUE; 36 import static com.android.systemui.statusbar.phone.BarTransitions.MODE_SEMI_TRANSPARENT; 37 import static com.android.systemui.statusbar.phone.BarTransitions.MODE_TRANSLUCENT; 38 import static com.android.systemui.statusbar.phone.BarTransitions.MODE_TRANSPARENT; 39 import static com.android.systemui.statusbar.phone.BarTransitions.MODE_WARNING; 40 41 import android.animation.Animator; 42 import android.animation.AnimatorListenerAdapter; 43 import android.annotation.NonNull; 44 import android.annotation.Nullable; 45 import android.app.ActivityManager; 46 import android.app.ActivityOptions; 47 import android.app.AlarmManager; 48 import android.app.IWallpaperManager; 49 import android.app.KeyguardManager; 50 import android.app.Notification; 51 import android.app.NotificationManager; 52 import android.app.PendingIntent; 53 import android.app.StatusBarManager; 54 import android.app.TaskStackBuilder; 55 import android.app.WallpaperColors; 56 import android.app.WallpaperInfo; 57 import android.app.WallpaperManager; 58 import android.app.admin.DevicePolicyManager; 59 import android.content.BroadcastReceiver; 60 import android.content.ComponentCallbacks2; 61 import android.content.ComponentName; 62 import android.content.Context; 63 import android.content.Intent; 64 import android.content.IntentFilter; 65 import android.content.IntentSender; 66 import android.content.om.IOverlayManager; 67 import android.content.om.OverlayInfo; 68 import android.content.pm.IPackageManager; 69 import android.content.pm.PackageManager; 70 import android.content.pm.PackageManager.NameNotFoundException; 71 import android.content.pm.UserInfo; 72 import android.content.res.Configuration; 73 import android.content.res.Resources; 74 import android.graphics.Bitmap; 75 import android.graphics.Point; 76 import android.graphics.PointF; 77 import android.graphics.PorterDuff; 78 import android.graphics.PorterDuffXfermode; 79 import android.graphics.Rect; 80 import android.graphics.drawable.BitmapDrawable; 81 import android.graphics.drawable.ColorDrawable; 82 import android.graphics.drawable.Drawable; 83 import android.media.AudioAttributes; 84 import android.media.MediaMetadata; 85 import android.metrics.LogMaker; 86 import android.net.Uri; 87 import android.os.AsyncTask; 88 import android.os.Bundle; 89 import android.os.Handler; 90 import android.os.IBinder; 91 import android.os.Looper; 92 import android.os.Message; 93 import android.os.PowerManager; 94 import android.os.RemoteException; 95 import android.os.ServiceManager; 96 import android.os.SystemClock; 97 import android.os.SystemProperties; 98 import android.os.Trace; 99 import android.os.UserHandle; 100 import android.os.UserManager; 101 import android.os.VibrationEffect; 102 import android.os.Vibrator; 103 import android.provider.Settings; 104 import android.service.notification.StatusBarNotification; 105 import android.service.vr.IVrManager; 106 import android.service.vr.IVrStateCallbacks; 107 import android.text.TextUtils; 108 import android.util.DisplayMetrics; 109 import android.util.EventLog; 110 import android.util.Log; 111 import android.util.Slog; 112 import android.util.SparseArray; 113 import android.view.Display; 114 import android.view.IWindowManager; 115 import android.view.KeyEvent; 116 import android.view.LayoutInflater; 117 import android.view.MotionEvent; 118 import android.view.RemoteAnimationAdapter; 119 import android.view.ThreadedRenderer; 120 import android.view.View; 121 import android.view.ViewGroup; 122 import android.view.ViewParent; 123 import android.view.ViewTreeObserver; 124 import android.view.WindowManager; 125 import android.view.WindowManagerGlobal; 126 import android.view.accessibility.AccessibilityManager; 127 import android.view.animation.AccelerateInterpolator; 128 import android.widget.DateTimeView; 129 import android.widget.ImageView; 130 import android.widget.TextView; 131 132 import com.android.internal.annotations.VisibleForTesting; 133 import com.android.internal.colorextraction.ColorExtractor; 134 import com.android.internal.logging.MetricsLogger; 135 import com.android.internal.logging.nano.MetricsProto.MetricsEvent; 136 import com.android.internal.statusbar.IStatusBarService; 137 import com.android.internal.statusbar.NotificationVisibility; 138 import com.android.internal.statusbar.StatusBarIcon; 139 import com.android.internal.widget.LockPatternUtils; 140 import com.android.internal.widget.MessagingGroup; 141 import com.android.internal.widget.MessagingMessage; 142 import com.android.keyguard.KeyguardHostView.OnDismissAction; 143 import com.android.keyguard.KeyguardUpdateMonitor; 144 import com.android.keyguard.KeyguardUpdateMonitorCallback; 145 import com.android.keyguard.ViewMediatorCallback; 146 import com.android.systemui.ActivityStarterDelegate; 147 import com.android.systemui.AutoReinflateContainer; 148 import com.android.systemui.DemoMode; 149 import com.android.systemui.Dependency; 150 import com.android.systemui.EventLogTags; 151 import com.android.systemui.Interpolators; 152 import com.android.systemui.Prefs; 153 import com.android.systemui.R; 154 import com.android.systemui.RecentsComponent; 155 import com.android.systemui.SystemUI; 156 import com.android.systemui.SystemUIFactory; 157 import com.android.systemui.UiOffloadThread; 158 import com.android.systemui.assist.AssistManager; 159 import com.android.systemui.charging.WirelessChargingAnimation; 160 import com.android.systemui.classifier.FalsingLog; 161 import com.android.systemui.classifier.FalsingManager; 162 import com.android.systemui.colorextraction.SysuiColorExtractor; 163 import com.android.systemui.doze.DozeHost; 164 import com.android.systemui.doze.DozeLog; 165 import com.android.systemui.doze.DozeReceiver; 166 import com.android.systemui.fragments.ExtensionFragmentListener; 167 import com.android.systemui.fragments.FragmentHostManager; 168 import com.android.systemui.keyguard.KeyguardViewMediator; 169 import com.android.systemui.keyguard.ScreenLifecycle; 170 import com.android.systemui.keyguard.WakefulnessLifecycle; 171 import com.android.systemui.plugins.ActivityStarter; 172 import com.android.systemui.plugins.qs.QS; 173 import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper.SnoozeOption; 174 import com.android.systemui.qs.QSFragment; 175 import com.android.systemui.qs.QSPanel; 176 import com.android.systemui.qs.QSTileHost; 177 import com.android.systemui.qs.car.CarQSFragment; 178 import com.android.systemui.recents.Recents; 179 import com.android.systemui.recents.ScreenPinningRequest; 180 import com.android.systemui.recents.events.EventBus; 181 import com.android.systemui.recents.events.activity.AppTransitionFinishedEvent; 182 import com.android.systemui.recents.events.activity.UndockingTaskEvent; 183 import com.android.systemui.recents.misc.SystemServicesProxy; 184 import com.android.systemui.shared.system.WindowManagerWrapper; 185 import com.android.systemui.stackdivider.Divider; 186 import com.android.systemui.stackdivider.WindowManagerProxy; 187 import com.android.systemui.statusbar.ActivatableNotificationView; 188 import com.android.systemui.statusbar.AppOpsListener; 189 import com.android.systemui.statusbar.BackDropView; 190 import com.android.systemui.statusbar.CommandQueue; 191 import com.android.systemui.statusbar.CrossFadeHelper; 192 import com.android.systemui.statusbar.DragDownHelper; 193 import com.android.systemui.statusbar.EmptyShadeView; 194 import com.android.systemui.statusbar.ExpandableNotificationRow; 195 import com.android.systemui.statusbar.FooterView; 196 import com.android.systemui.statusbar.GestureRecorder; 197 import com.android.systemui.statusbar.KeyboardShortcuts; 198 import com.android.systemui.statusbar.KeyguardIndicationController; 199 import com.android.systemui.statusbar.NotificationData; 200 import com.android.systemui.statusbar.NotificationData.Entry; 201 import com.android.systemui.statusbar.NotificationEntryManager; 202 import com.android.systemui.statusbar.NotificationGutsManager; 203 import com.android.systemui.statusbar.NotificationInfo; 204 import com.android.systemui.statusbar.NotificationListener; 205 import com.android.systemui.statusbar.NotificationLockscreenUserManager; 206 import com.android.systemui.statusbar.NotificationLogger; 207 import com.android.systemui.statusbar.NotificationMediaManager; 208 import com.android.systemui.statusbar.NotificationPresenter; 209 import com.android.systemui.statusbar.NotificationRemoteInputManager; 210 import com.android.systemui.statusbar.NotificationShelf; 211 import com.android.systemui.statusbar.NotificationViewHierarchyManager; 212 import com.android.systemui.statusbar.RemoteInputController; 213 import com.android.systemui.statusbar.ScrimView; 214 import com.android.systemui.statusbar.StatusBarState; 215 import com.android.systemui.statusbar.VibratorHelper; 216 import com.android.systemui.statusbar.notification.AboveShelfObserver; 217 import com.android.systemui.statusbar.notification.ActivityLaunchAnimator; 218 import com.android.systemui.statusbar.notification.VisualStabilityManager; 219 import com.android.systemui.statusbar.phone.UnlockMethodCache.OnUnlockMethodChangedListener; 220 import com.android.systemui.statusbar.policy.BatteryController; 221 import com.android.systemui.statusbar.policy.BatteryController.BatteryStateChangeCallback; 222 import com.android.systemui.statusbar.policy.BrightnessMirrorController; 223 import com.android.systemui.statusbar.policy.ConfigurationController; 224 import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener; 225 import com.android.systemui.statusbar.policy.DarkIconDispatcher; 226 import com.android.systemui.statusbar.policy.DeviceProvisionedController; 227 import com.android.systemui.statusbar.policy.DeviceProvisionedController.DeviceProvisionedListener; 228 import com.android.systemui.statusbar.policy.ExtensionController; 229 import com.android.systemui.statusbar.policy.HeadsUpManager; 230 import com.android.systemui.statusbar.policy.HeadsUpUtil; 231 import com.android.systemui.statusbar.policy.KeyguardMonitor; 232 import com.android.systemui.statusbar.policy.KeyguardMonitorImpl; 233 import com.android.systemui.statusbar.policy.KeyguardUserSwitcher; 234 import com.android.systemui.statusbar.policy.NetworkController; 235 import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener; 236 import com.android.systemui.statusbar.policy.PreviewInflater; 237 import com.android.systemui.statusbar.policy.RemoteInputQuickSettingsDisabler; 238 import com.android.systemui.statusbar.policy.UserInfoController; 239 import com.android.systemui.statusbar.policy.UserInfoControllerImpl; 240 import com.android.systemui.statusbar.policy.UserSwitcherController; 241 import com.android.systemui.statusbar.policy.ZenModeController; 242 import com.android.systemui.statusbar.stack.NotificationStackScrollLayout; 243 import com.android.systemui.volume.VolumeComponent; 244 245 import java.io.FileDescriptor; 246 import java.io.PrintWriter; 247 import java.io.StringWriter; 248 import java.util.ArrayList; 249 import java.util.List; 250 import java.util.Map; 251 252 public class StatusBar extends SystemUI implements DemoMode, 253 DragDownHelper.DragDownCallback, ActivityStarter, OnUnlockMethodChangedListener, 254 OnHeadsUpChangedListener, CommandQueue.Callbacks, ZenModeController.Callback, 255 ColorExtractor.OnColorsChangedListener, ConfigurationListener, NotificationPresenter { 256 public static final boolean MULTIUSER_DEBUG = false; 257 258 public static final boolean ENABLE_CHILD_NOTIFICATIONS 259 = SystemProperties.getBoolean("debug.child_notifs", true); 260 261 protected static final int MSG_HIDE_RECENT_APPS = 1020; 262 protected static final int MSG_PRELOAD_RECENT_APPS = 1022; 263 protected static final int MSG_CANCEL_PRELOAD_RECENT_APPS = 1023; 264 protected static final int MSG_TOGGLE_KEYBOARD_SHORTCUTS_MENU = 1026; 265 protected static final int MSG_DISMISS_KEYBOARD_SHORTCUTS_MENU = 1027; 266 267 // Should match the values in PhoneWindowManager 268 public static final String SYSTEM_DIALOG_REASON_HOME_KEY = "homekey"; 269 public static final String SYSTEM_DIALOG_REASON_RECENT_APPS = "recentapps"; 270 static public final String SYSTEM_DIALOG_REASON_SCREENSHOT = "screenshot"; 271 272 private static final String BANNER_ACTION_CANCEL = 273 "com.android.systemui.statusbar.banner_action_cancel"; 274 private static final String BANNER_ACTION_SETUP = 275 "com.android.systemui.statusbar.banner_action_setup"; 276 public static final String TAG = "StatusBar"; 277 public static final boolean DEBUG = false; 278 public static final boolean SPEW = false; 279 public static final boolean DUMPTRUCK = true; // extra dumpsys info 280 public static final boolean DEBUG_GESTURES = false; 281 public static final boolean DEBUG_MEDIA_FAKE_ARTWORK = false; 282 public static final boolean DEBUG_CAMERA_LIFT = false; 283 284 public static final boolean DEBUG_WINDOW_STATE = false; 285 286 // additional instrumentation for testing purposes; intended to be left on during development 287 public static final boolean CHATTY = DEBUG; 288 289 public static final boolean SHOW_LOCKSCREEN_MEDIA_ARTWORK = true; 290 291 public static final String ACTION_FAKE_ARTWORK = "fake_artwork"; 292 293 private static final int MSG_OPEN_NOTIFICATION_PANEL = 1000; 294 private static final int MSG_CLOSE_PANELS = 1001; 295 private static final int MSG_OPEN_SETTINGS_PANEL = 1002; 296 private static final int MSG_LAUNCH_TRANSITION_TIMEOUT = 1003; 297 // 1020-1040 reserved for BaseStatusBar 298 299 // Time after we abort the launch transition. 300 private static final long LAUNCH_TRANSITION_TIMEOUT_MS = 5000; 301 302 protected static final boolean CLOSE_PANEL_WHEN_EMPTIED = true; 303 304 private static final int STATUS_OR_NAV_TRANSIENT = 305 View.STATUS_BAR_TRANSIENT | View.NAVIGATION_BAR_TRANSIENT; 306 private static final long AUTOHIDE_TIMEOUT_MS = 2250; 307 308 /** 309 * The delay to reset the hint text when the hint animation is finished running. 310 */ 311 private static final int HINT_RESET_DELAY_MS = 1200; 312 313 private static final AudioAttributes VIBRATION_ATTRIBUTES = new AudioAttributes.Builder() 314 .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION) 315 .setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION) 316 .build(); 317 318 public static final int FADE_KEYGUARD_START_DELAY = 100; 319 public static final int FADE_KEYGUARD_DURATION = 300; 320 public static final int FADE_KEYGUARD_DURATION_PULSING = 96; 321 322 /** If true, the system is in the half-boot-to-decryption-screen state. 323 * Prudently disable QS and notifications. */ 324 private static final boolean ONLY_CORE_APPS; 325 326 /** If true, the lockscreen will show a distinct wallpaper */ 327 private static final boolean ENABLE_LOCKSCREEN_WALLPAPER = true; 328 329 /** 330 * Never let the alpha become zero for surfaces that draw with SRC - otherwise the RenderNode 331 * won't draw anything and uninitialized memory will show through 332 * if mScrimSrcModeEnabled. Note that 0.001 is rounded down to 0 in 333 * libhwui. 334 */ 335 private static final float SRC_MIN_ALPHA = 0.002f; 336 337 static { 338 boolean onlyCoreApps; 339 try { 340 IPackageManager packageManager = 341 IPackageManager.Stub.asInterface(ServiceManager.getService("package")); 342 onlyCoreApps = packageManager.isOnlyCoreApps(); 343 } catch (RemoteException e) { 344 onlyCoreApps = false; 345 } 346 ONLY_CORE_APPS = onlyCoreApps; 347 } 348 349 /** 350 * The {@link StatusBarState} of the status bar. 351 */ 352 protected int mState; 353 protected boolean mBouncerShowing; 354 355 private PhoneStatusBarPolicy mIconPolicy; 356 private StatusBarSignalPolicy mSignalPolicy; 357 358 private VolumeComponent mVolumeComponent; 359 private BrightnessMirrorController mBrightnessMirrorController; 360 private boolean mBrightnessMirrorVisible; 361 protected FingerprintUnlockController mFingerprintUnlockController; 362 private LightBarController mLightBarController; 363 protected LockscreenWallpaper mLockscreenWallpaper; 364 365 private int mNaturalBarHeight = -1; 366 367 private final Point mCurrentDisplaySize = new Point(); 368 369 protected StatusBarWindowView mStatusBarWindow; 370 protected PhoneStatusBarView mStatusBarView; 371 private int mStatusBarWindowState = WINDOW_STATE_SHOWING; 372 protected StatusBarWindowManager mStatusBarWindowManager; 373 protected UnlockMethodCache mUnlockMethodCache; 374 private DozeServiceHost mDozeServiceHost = new DozeServiceHost(); 375 private boolean mWakeUpComingFromTouch; 376 private PointF mWakeUpTouchLocation; 377 378 private final Object mQueueLock = new Object(); 379 380 protected StatusBarIconController mIconController; 381 382 // expanded notifications 383 protected NotificationPanelView mNotificationPanel; // the sliding/resizing panel within the notification window 384 private TextView mNotificationPanelDebugText; 385 386 // settings 387 private QSPanel mQSPanel; 388 389 // top bar 390 private KeyguardStatusBarView mKeyguardStatusBar; 391 private boolean mLeaveOpenOnKeyguardHide; 392 KeyguardIndicationController mKeyguardIndicationController; 393 394 // Keyguard is actually fading away now. 395 protected boolean mKeyguardFadingAway; 396 protected long mKeyguardFadingAwayDelay; 397 protected long mKeyguardFadingAwayDuration; 398 399 // RemoteInputView to be activated after unlock 400 private View mPendingRemoteInputView; 401 private View mPendingWorkRemoteInputView; 402 403 private RemoteInputQuickSettingsDisabler mRemoteInputQuickSettingsDisabler = 404 Dependency.get(RemoteInputQuickSettingsDisabler.class); 405 406 private View mReportRejectedTouch; 407 408 private int mMaxAllowedKeyguardNotifications; 409 410 private boolean mExpandedVisible; 411 412 private final int[] mAbsPos = new int[2]; 413 private final ArrayList<Runnable> mPostCollapseRunnables = new ArrayList<>(); 414 415 private NotificationGutsManager mGutsManager; 416 protected NotificationLogger mNotificationLogger; 417 protected NotificationEntryManager mEntryManager; 418 protected NotificationViewHierarchyManager mViewHierarchyManager; 419 protected AppOpsListener mAppOpsListener; 420 protected KeyguardViewMediator mKeyguardViewMediator; 421 private ZenModeController mZenController; 422 423 /** 424 * Helper that is responsible for showing the right toast when a disallowed activity operation 425 * occurred. In pinned mode, we show instructions on how to break out of this mode, whilst in 426 * fully locked mode we only show that unlocking is blocked. 427 */ 428 private ScreenPinningNotify mScreenPinningNotify; 429 430 // for disabling the status bar 431 private int mDisabled1 = 0; 432 private int mDisabled2 = 0; 433 434 // tracking calls to View.setSystemUiVisibility() 435 private int mSystemUiVisibility = View.SYSTEM_UI_FLAG_VISIBLE; 436 private final Rect mLastFullscreenStackBounds = new Rect(); 437 private final Rect mLastDockedStackBounds = new Rect(); 438 private final Rect mTmpRect = new Rect(); 439 440 // last value sent to window manager 441 private int mLastDispatchedSystemUiVisibility = ~View.SYSTEM_UI_FLAG_VISIBLE; 442 443 private final DisplayMetrics mDisplayMetrics = new DisplayMetrics(); 444 445 // XXX: gesture research 446 private final GestureRecorder mGestureRec = DEBUG_GESTURES 447 ? new GestureRecorder("/sdcard/statusbar_gestures.dat") 448 : null; 449 450 private ScreenPinningRequest mScreenPinningRequest; 451 452 private final MetricsLogger mMetricsLogger = Dependency.get(MetricsLogger.class); 453 454 // ensure quick settings is disabled until the current user makes it through the setup wizard 455 @VisibleForTesting 456 protected boolean mUserSetup = false; 457 private final DeviceProvisionedListener mUserSetupObserver = new DeviceProvisionedListener() { 458 @Override 459 public void onUserSetupChanged() { 460 final boolean userSetup = mDeviceProvisionedController.isUserSetup( 461 mDeviceProvisionedController.getCurrentUser()); 462 if (MULTIUSER_DEBUG) { 463 Log.d(TAG, String.format("User setup changed: userSetup=%s mUserSetup=%s", 464 userSetup, mUserSetup)); 465 } 466 467 if (userSetup != mUserSetup) { 468 mUserSetup = userSetup; 469 if (!mUserSetup && mStatusBarView != null) 470 animateCollapseQuickSettings(); 471 if (mNotificationPanel != null) { 472 mNotificationPanel.setUserSetupComplete(mUserSetup); 473 } 474 updateQsExpansionEnabled(); 475 } 476 } 477 }; 478 479 protected final H mHandler = createHandler(); 480 481 private int mInteractingWindows; 482 private boolean mAutohideSuspended; 483 private int mStatusBarMode; 484 private int mMaxKeyguardNotifications; 485 486 private ViewMediatorCallback mKeyguardViewMediatorCallback; 487 protected ScrimController mScrimController; 488 protected DozeScrimController mDozeScrimController; 489 private final UiOffloadThread mUiOffloadThread = Dependency.get(UiOffloadThread.class); 490 491 private final Runnable mAutohide = () -> { 492 int requested = mSystemUiVisibility & ~STATUS_OR_NAV_TRANSIENT; 493 if (mSystemUiVisibility != requested) { 494 notifyUiVisibilityChanged(requested); 495 } 496 }; 497 498 protected boolean mDozing; 499 private boolean mDozingRequested; 500 protected boolean mScrimSrcModeEnabled; 501 502 protected BackDropView mBackdrop; 503 protected ImageView mBackdropFront, mBackdropBack; 504 protected final PorterDuffXfermode mSrcXferMode = new PorterDuffXfermode(PorterDuff.Mode.SRC); 505 protected final PorterDuffXfermode mSrcOverXferMode = 506 new PorterDuffXfermode(PorterDuff.Mode.SRC_OVER); 507 508 private NotificationMediaManager mMediaManager; 509 protected NotificationLockscreenUserManager mLockscreenUserManager; 510 protected NotificationRemoteInputManager mRemoteInputManager; 511 512 private BroadcastReceiver mWallpaperChangedReceiver = new BroadcastReceiver() { 513 @Override 514 public void onReceive(Context context, Intent intent) { 515 WallpaperManager wallpaperManager = context.getSystemService(WallpaperManager.class); 516 if (wallpaperManager == null) { 517 Log.w(TAG, "WallpaperManager not available"); 518 return; 519 } 520 WallpaperInfo info = wallpaperManager.getWallpaperInfo(); 521 final boolean supportsAmbientMode = info != null && 522 info.getSupportsAmbientMode(); 523 524 mStatusBarWindowManager.setWallpaperSupportsAmbientMode(supportsAmbientMode); 525 mScrimController.setWallpaperSupportsAmbientMode(supportsAmbientMode); 526 } 527 }; 528 529 private Runnable mLaunchTransitionEndRunnable; 530 protected boolean mLaunchTransitionFadingAway; 531 private ExpandableNotificationRow mDraggedDownRow; 532 private boolean mLaunchCameraOnScreenTurningOn; 533 private boolean mLaunchCameraOnFinishedGoingToSleep; 534 private int mLastCameraLaunchSource; 535 private PowerManager.WakeLock mGestureWakeLock; 536 private Vibrator mVibrator; 537 private long[] mCameraLaunchGestureVibePattern; 538 539 private final int[] mTmpInt2 = new int[2]; 540 541 // Fingerprint (as computed by getLoggingFingerprint() of the last logged state. 542 private int mLastLoggedStateFingerprint; 543 private boolean mTopHidesStatusBar; 544 private boolean mStatusBarWindowHidden; 545 private boolean mHideIconsForBouncer; 546 private boolean mIsOccluded; 547 private boolean mWereIconsJustHidden; 548 private boolean mBouncerWasShowingWhenHidden; 549 550 // Notifies StatusBarKeyguardViewManager every time the keyguard transition is over, 551 // this animation is tied to the scrim for historic reasons. 552 // TODO: notify when keyguard has faded away instead of the scrim. 553 private final ScrimController.Callback mUnlockScrimCallback = new ScrimController 554 .Callback() { 555 @Override 556 public void onFinished() { 557 if (mStatusBarKeyguardViewManager == null) { 558 Log.w(TAG, "Tried to notify keyguard visibility when " 559 + "mStatusBarKeyguardViewManager was null"); 560 return; 561 } 562 if (mKeyguardFadingAway) { 563 mStatusBarKeyguardViewManager.onKeyguardFadedAway(); 564 } 565 } 566 567 @Override 568 public void onCancelled() { 569 onFinished(); 570 } 571 }; 572 573 private KeyguardUserSwitcher mKeyguardUserSwitcher; 574 protected UserSwitcherController mUserSwitcherController; 575 private NetworkController mNetworkController; 576 private KeyguardMonitorImpl mKeyguardMonitor 577 = (KeyguardMonitorImpl) Dependency.get(KeyguardMonitor.class); 578 private BatteryController mBatteryController; 579 protected boolean mPanelExpanded; 580 private IOverlayManager mOverlayManager; 581 private boolean mKeyguardRequested; 582 private boolean mIsKeyguard; 583 private LogMaker mStatusBarStateLog; 584 private final LockscreenGestureLogger mLockscreenGestureLogger = new LockscreenGestureLogger(); 585 protected NotificationIconAreaController mNotificationIconAreaController; 586 private boolean mReinflateNotificationsOnUserSwitched; 587 protected boolean mClearAllEnabled; 588 @Nullable private View mAmbientIndicationContainer; 589 private SysuiColorExtractor mColorExtractor; 590 private ScreenLifecycle mScreenLifecycle; 591 @VisibleForTesting WakefulnessLifecycle mWakefulnessLifecycle; 592 593 private final View.OnClickListener mGoToLockedShadeListener = v -> { 594 if (mState == StatusBarState.KEYGUARD) { 595 wakeUpIfDozing(SystemClock.uptimeMillis(), v); 596 goToLockedShade(null); 597 } 598 }; 599 private boolean mNoAnimationOnNextBarModeChange; 600 protected FalsingManager mFalsingManager; 601 602 private final KeyguardUpdateMonitorCallback mUpdateCallback = 603 new KeyguardUpdateMonitorCallback() { 604 @Override 605 public void onDreamingStateChanged(boolean dreaming) { 606 if (dreaming) { 607 maybeEscalateHeadsUp(); 608 } 609 } 610 611 @Override 612 public void onStrongAuthStateChanged(int userId) { 613 super.onStrongAuthStateChanged(userId); 614 mEntryManager.updateNotifications(); 615 } 616 }; 617 618 private NavigationBarFragment mNavigationBar; 619 private View mNavigationBarView; 620 protected ActivityLaunchAnimator mActivityLaunchAnimator; 621 private HeadsUpAppearanceController mHeadsUpAppearanceController; 622 private boolean mVibrateOnOpening; 623 private VibratorHelper mVibratorHelper; 624 625 @Override start()626 public void start() { 627 mGroupManager = Dependency.get(NotificationGroupManager.class); 628 mVisualStabilityManager = Dependency.get(VisualStabilityManager.class); 629 mNotificationLogger = Dependency.get(NotificationLogger.class); 630 mRemoteInputManager = Dependency.get(NotificationRemoteInputManager.class); 631 mNotificationListener = Dependency.get(NotificationListener.class); 632 mGroupManager = Dependency.get(NotificationGroupManager.class); 633 mNetworkController = Dependency.get(NetworkController.class); 634 mUserSwitcherController = Dependency.get(UserSwitcherController.class); 635 mScreenLifecycle = Dependency.get(ScreenLifecycle.class); 636 mScreenLifecycle.addObserver(mScreenObserver); 637 mWakefulnessLifecycle = Dependency.get(WakefulnessLifecycle.class); 638 mWakefulnessLifecycle.addObserver(mWakefulnessObserver); 639 mBatteryController = Dependency.get(BatteryController.class); 640 mAssistManager = Dependency.get(AssistManager.class); 641 mOverlayManager = IOverlayManager.Stub.asInterface( 642 ServiceManager.getService(Context.OVERLAY_SERVICE)); 643 mLockscreenUserManager = Dependency.get(NotificationLockscreenUserManager.class); 644 mGutsManager = Dependency.get(NotificationGutsManager.class); 645 mMediaManager = Dependency.get(NotificationMediaManager.class); 646 mEntryManager = Dependency.get(NotificationEntryManager.class); 647 mViewHierarchyManager = Dependency.get(NotificationViewHierarchyManager.class); 648 mAppOpsListener = Dependency.get(AppOpsListener.class); 649 mAppOpsListener.setUpWithPresenter(this, mEntryManager); 650 mZenController = Dependency.get(ZenModeController.class); 651 mKeyguardViewMediator = getComponent(KeyguardViewMediator.class); 652 653 mColorExtractor = Dependency.get(SysuiColorExtractor.class); 654 mColorExtractor.addOnColorsChangedListener(this); 655 656 mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE); 657 658 mDisplay = mWindowManager.getDefaultDisplay(); 659 updateDisplaySize(); 660 661 Resources res = mContext.getResources(); 662 mVibrateOnOpening = mContext.getResources().getBoolean( 663 R.bool.config_vibrateOnIconAnimation); 664 mVibratorHelper = Dependency.get(VibratorHelper.class); 665 mScrimSrcModeEnabled = res.getBoolean(R.bool.config_status_bar_scrim_behind_use_src); 666 mClearAllEnabled = res.getBoolean(R.bool.config_enableNotificationsClearAll); 667 668 DateTimeView.setReceiverHandler(Dependency.get(Dependency.TIME_TICK_HANDLER)); 669 putComponent(StatusBar.class, this); 670 671 // start old BaseStatusBar.start(). 672 mWindowManagerService = WindowManagerGlobal.getWindowManagerService(); 673 mDevicePolicyManager = (DevicePolicyManager) mContext.getSystemService( 674 Context.DEVICE_POLICY_SERVICE); 675 676 mAccessibilityManager = (AccessibilityManager) 677 mContext.getSystemService(Context.ACCESSIBILITY_SERVICE); 678 679 mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE); 680 681 mDeviceProvisionedController = Dependency.get(DeviceProvisionedController.class); 682 683 mBarService = IStatusBarService.Stub.asInterface( 684 ServiceManager.getService(Context.STATUS_BAR_SERVICE)); 685 686 mRecents = getComponent(Recents.class); 687 688 mKeyguardManager = (KeyguardManager) mContext.getSystemService(Context.KEYGUARD_SERVICE); 689 mLockPatternUtils = new LockPatternUtils(mContext); 690 691 mMediaManager.setUpWithPresenter(this, mEntryManager); 692 693 // Connect in to the status bar manager service 694 mCommandQueue = getComponent(CommandQueue.class); 695 mCommandQueue.addCallbacks(this); 696 697 int[] switches = new int[9]; 698 ArrayList<IBinder> binders = new ArrayList<>(); 699 ArrayList<String> iconSlots = new ArrayList<>(); 700 ArrayList<StatusBarIcon> icons = new ArrayList<>(); 701 Rect fullscreenStackBounds = new Rect(); 702 Rect dockedStackBounds = new Rect(); 703 try { 704 mBarService.registerStatusBar(mCommandQueue, iconSlots, icons, switches, binders, 705 fullscreenStackBounds, dockedStackBounds); 706 } catch (RemoteException ex) { 707 // If the system process isn't there we're doomed anyway. 708 } 709 710 createAndAddWindows(); 711 712 // Make sure we always have the most current wallpaper info. 713 IntentFilter wallpaperChangedFilter = new IntentFilter(Intent.ACTION_WALLPAPER_CHANGED); 714 mContext.registerReceiver(mWallpaperChangedReceiver, wallpaperChangedFilter); 715 mWallpaperChangedReceiver.onReceive(mContext, null); 716 717 mLockscreenUserManager.setUpWithPresenter(this, mEntryManager); 718 mCommandQueue.disable(switches[0], switches[6], false /* animate */); 719 setSystemUiVisibility(switches[1], switches[7], switches[8], 0xffffffff, 720 fullscreenStackBounds, dockedStackBounds); 721 topAppWindowChanged(switches[2] != 0); 722 // StatusBarManagerService has a back up of IME token and it's restored here. 723 setImeWindowStatus(binders.get(0), switches[3], switches[4], switches[5] != 0); 724 725 // Set up the initial icon state 726 int N = iconSlots.size(); 727 for (int i=0; i < N; i++) { 728 mCommandQueue.setIcon(iconSlots.get(i), icons.get(i)); 729 } 730 731 // Set up the initial notification state. 732 mNotificationListener.setUpWithPresenter(this, mEntryManager); 733 734 if (DEBUG) { 735 Log.d(TAG, String.format( 736 "init: icons=%d disabled=0x%08x lights=0x%08x menu=0x%08x imeButton=0x%08x", 737 icons.size(), 738 switches[0], 739 switches[1], 740 switches[2], 741 switches[3] 742 )); 743 } 744 745 setHeadsUpUser(mLockscreenUserManager.getCurrentUserId()); 746 747 IntentFilter internalFilter = new IntentFilter(); 748 internalFilter.addAction(BANNER_ACTION_CANCEL); 749 internalFilter.addAction(BANNER_ACTION_SETUP); 750 mContext.registerReceiver(mBannerActionBroadcastReceiver, internalFilter, PERMISSION_SELF, 751 null); 752 753 IVrManager vrManager = IVrManager.Stub.asInterface(ServiceManager.getService( 754 Context.VR_SERVICE)); 755 try { 756 vrManager.registerListener(mVrStateCallbacks); 757 } catch (RemoteException e) { 758 Slog.e(TAG, "Failed to register VR mode state listener: " + e); 759 } 760 761 IWallpaperManager wallpaperManager = IWallpaperManager.Stub.asInterface( 762 ServiceManager.getService(Context.WALLPAPER_SERVICE)); 763 try { 764 wallpaperManager.setInAmbientMode(false /* ambientMode */, false /* animated */); 765 } catch (RemoteException e) { 766 // Just pass, nothing critical. 767 } 768 769 // end old BaseStatusBar.start(). 770 771 // Lastly, call to the icon policy to install/update all the icons. 772 mIconPolicy = new PhoneStatusBarPolicy(mContext, mIconController); 773 mSignalPolicy = new StatusBarSignalPolicy(mContext, mIconController); 774 775 mUnlockMethodCache = UnlockMethodCache.getInstance(mContext); 776 mUnlockMethodCache.addListener(this); 777 startKeyguard(); 778 779 KeyguardUpdateMonitor.getInstance(mContext).registerCallback(mUpdateCallback); 780 putComponent(DozeHost.class, mDozeServiceHost); 781 782 mScreenPinningRequest = new ScreenPinningRequest(mContext); 783 mFalsingManager = FalsingManager.getInstance(mContext); 784 785 Dependency.get(ActivityStarterDelegate.class).setActivityStarterImpl(this); 786 787 Dependency.get(ConfigurationController.class).addCallback(this); 788 } 789 790 // ================================================================================ 791 // Constructing the view 792 // ================================================================================ makeStatusBarView()793 protected void makeStatusBarView() { 794 final Context context = mContext; 795 updateDisplaySize(); // populates mDisplayMetrics 796 updateResources(); 797 updateTheme(); 798 799 inflateStatusBarWindow(context); 800 mStatusBarWindow.setService(this); 801 mStatusBarWindow.setOnTouchListener(getStatusBarWindowTouchListener()); 802 803 // TODO: Deal with the ugliness that comes from having some of the statusbar broken out 804 // into fragments, but the rest here, it leaves some awkward lifecycle and whatnot. 805 mNotificationPanel = mStatusBarWindow.findViewById(R.id.notification_panel); 806 mStackScroller = mStatusBarWindow.findViewById(R.id.notification_stack_scroller); 807 mZenController.addCallback(this); 808 mActivityLaunchAnimator = new ActivityLaunchAnimator(mStatusBarWindow, 809 this, 810 mNotificationPanel, 811 mStackScroller); 812 mGutsManager.setUpWithPresenter(this, mEntryManager, mStackScroller, mCheckSaveListener, 813 key -> { 814 try { 815 mBarService.onNotificationSettingsViewed(key); 816 } catch (RemoteException e) { 817 // if we're here we're dead 818 } 819 }); 820 mNotificationLogger.setUpWithEntryManager(mEntryManager, mStackScroller); 821 mNotificationPanel.setStatusBar(this); 822 mNotificationPanel.setGroupManager(mGroupManager); 823 mAboveShelfObserver = new AboveShelfObserver(mStackScroller); 824 mAboveShelfObserver.setListener(mStatusBarWindow.findViewById( 825 R.id.notification_container_parent)); 826 mKeyguardStatusBar = mStatusBarWindow.findViewById(R.id.keyguard_header); 827 828 mNotificationIconAreaController = SystemUIFactory.getInstance() 829 .createNotificationIconAreaController(context, this); 830 inflateShelf(); 831 mNotificationIconAreaController.setupShelf(mNotificationShelf); 832 Dependency.get(DarkIconDispatcher.class).addDarkReceiver(mNotificationIconAreaController); 833 FragmentHostManager.get(mStatusBarWindow) 834 .addTagListener(CollapsedStatusBarFragment.TAG, (tag, fragment) -> { 835 CollapsedStatusBarFragment statusBarFragment = 836 (CollapsedStatusBarFragment) fragment; 837 statusBarFragment.initNotificationIconArea(mNotificationIconAreaController); 838 mStatusBarView = (PhoneStatusBarView) fragment.getView(); 839 mStatusBarView.setBar(this); 840 mStatusBarView.setPanel(mNotificationPanel); 841 mStatusBarView.setScrimController(mScrimController); 842 mStatusBarView.setBouncerShowing(mBouncerShowing); 843 if (mHeadsUpAppearanceController != null) { 844 // This view is being recreated, let's destroy the old one 845 mHeadsUpAppearanceController.destroy(); 846 } 847 mHeadsUpAppearanceController = new HeadsUpAppearanceController( 848 mNotificationIconAreaController, mHeadsUpManager, mStatusBarWindow); 849 setAreThereNotifications(); 850 checkBarModes(); 851 }).getFragmentManager() 852 .beginTransaction() 853 .replace(R.id.status_bar_container, new CollapsedStatusBarFragment(), 854 CollapsedStatusBarFragment.TAG) 855 .commit(); 856 mIconController = Dependency.get(StatusBarIconController.class); 857 858 mHeadsUpManager = new HeadsUpManagerPhone(context, mStatusBarWindow, mGroupManager, this, 859 mVisualStabilityManager); 860 Dependency.get(ConfigurationController.class).addCallback(mHeadsUpManager); 861 mHeadsUpManager.addListener(this); 862 mHeadsUpManager.addListener(mNotificationPanel); 863 mHeadsUpManager.addListener(mGroupManager); 864 mHeadsUpManager.addListener(mVisualStabilityManager); 865 mNotificationPanel.setHeadsUpManager(mHeadsUpManager); 866 mGroupManager.setHeadsUpManager(mHeadsUpManager); 867 putComponent(HeadsUpManager.class, mHeadsUpManager); 868 869 mEntryManager.setUpWithPresenter(this, mStackScroller, this, mHeadsUpManager); 870 mViewHierarchyManager.setUpWithPresenter(this, mEntryManager, mStackScroller); 871 872 if (MULTIUSER_DEBUG) { 873 mNotificationPanelDebugText = mNotificationPanel.findViewById(R.id.header_debug_info); 874 mNotificationPanelDebugText.setVisibility(View.VISIBLE); 875 } 876 877 try { 878 boolean showNav = mWindowManagerService.hasNavigationBar(); 879 if (DEBUG) Log.v(TAG, "hasNavigationBar=" + showNav); 880 if (showNav) { 881 createNavigationBar(); 882 } 883 } catch (RemoteException ex) { 884 // no window manager? good luck with that 885 } 886 mScreenPinningNotify = new ScreenPinningNotify(mContext); 887 mStackScroller.setLongPressListener(mEntryManager.getNotificationLongClicker()); 888 mStackScroller.setStatusBar(this); 889 mStackScroller.setGroupManager(mGroupManager); 890 mStackScroller.setHeadsUpManager(mHeadsUpManager); 891 mGroupManager.setOnGroupChangeListener(mStackScroller); 892 mVisualStabilityManager.setVisibilityLocationProvider(mStackScroller); 893 894 inflateEmptyShadeView(); 895 inflateFooterView(); 896 897 mBackdrop = mStatusBarWindow.findViewById(R.id.backdrop); 898 mBackdropFront = mBackdrop.findViewById(R.id.backdrop_front); 899 mBackdropBack = mBackdrop.findViewById(R.id.backdrop_back); 900 901 if (ENABLE_LOCKSCREEN_WALLPAPER) { 902 mLockscreenWallpaper = new LockscreenWallpaper(mContext, this, mHandler); 903 } 904 905 mKeyguardIndicationController = 906 SystemUIFactory.getInstance().createKeyguardIndicationController(mContext, 907 mStatusBarWindow.findViewById(R.id.keyguard_indication_area), 908 mNotificationPanel.getLockIcon()); 909 mNotificationPanel.setKeyguardIndicationController(mKeyguardIndicationController); 910 911 912 mAmbientIndicationContainer = mStatusBarWindow.findViewById( 913 R.id.ambient_indication_container); 914 915 // set the initial view visibility 916 setAreThereNotifications(); 917 918 // TODO: Find better place for this callback. 919 mBatteryController.addCallback(new BatteryStateChangeCallback() { 920 @Override 921 public void onPowerSaveChanged(boolean isPowerSave) { 922 mHandler.post(mCheckBarModes); 923 if (mDozeServiceHost != null) { 924 mDozeServiceHost.firePowerSaveChanged(isPowerSave); 925 } 926 } 927 928 @Override 929 public void onBatteryLevelChanged(int level, boolean pluggedIn, boolean charging) { 930 // noop 931 } 932 }); 933 934 mLightBarController = Dependency.get(LightBarController.class); 935 if (mNavigationBar != null) { 936 mNavigationBar.setLightBarController(mLightBarController); 937 } 938 939 ScrimView scrimBehind = mStatusBarWindow.findViewById(R.id.scrim_behind); 940 ScrimView scrimInFront = mStatusBarWindow.findViewById(R.id.scrim_in_front); 941 mScrimController = SystemUIFactory.getInstance().createScrimController( 942 scrimBehind, scrimInFront, mLockscreenWallpaper, 943 (state, alpha, color) -> mLightBarController.setScrimState(state, alpha, color), 944 scrimsVisible -> { 945 if (mStatusBarWindowManager != null) { 946 mStatusBarWindowManager.setScrimsVisibility(scrimsVisible); 947 } 948 }, DozeParameters.getInstance(mContext), 949 mContext.getSystemService(AlarmManager.class)); 950 if (mScrimSrcModeEnabled) { 951 Runnable runnable = () -> { 952 boolean asSrc = mBackdrop.getVisibility() != View.VISIBLE; 953 mScrimController.setDrawBehindAsSrc(asSrc); 954 mStackScroller.setDrawBackgroundAsSrc(asSrc); 955 }; 956 mBackdrop.setOnVisibilityChangedRunnable(runnable); 957 runnable.run(); 958 } 959 mStackScroller.setScrimController(mScrimController); 960 mDozeScrimController = new DozeScrimController(mScrimController, context, 961 DozeParameters.getInstance(context)); 962 963 // Other icons 964 mVolumeComponent = getComponent(VolumeComponent.class); 965 966 mNotificationPanel.setUserSetupComplete(mUserSetup); 967 if (UserManager.get(mContext).isUserSwitcherEnabled()) { 968 createUserSwitcher(); 969 } 970 971 // Set up the quick settings tile panel 972 View container = mStatusBarWindow.findViewById(R.id.qs_frame); 973 if (container != null) { 974 FragmentHostManager fragmentHostManager = FragmentHostManager.get(container); 975 ExtensionFragmentListener.attachExtensonToFragment(container, QS.TAG, R.id.qs_frame, 976 Dependency.get(ExtensionController.class) 977 .newExtension(QS.class) 978 .withPlugin(QS.class) 979 .withFeature(PackageManager.FEATURE_AUTOMOTIVE, CarQSFragment::new) 980 .withDefault(QSFragment::new) 981 .build()); 982 final QSTileHost qsh = SystemUIFactory.getInstance().createQSTileHost(mContext, this, 983 mIconController); 984 mBrightnessMirrorController = new BrightnessMirrorController(mStatusBarWindow, 985 (visible) -> { 986 mBrightnessMirrorVisible = visible; 987 updateScrimController(); 988 }); 989 fragmentHostManager.addTagListener(QS.TAG, (tag, f) -> { 990 QS qs = (QS) f; 991 if (qs instanceof QSFragment) { 992 ((QSFragment) qs).setHost(qsh); 993 mQSPanel = ((QSFragment) qs).getQsPanel(); 994 mQSPanel.setBrightnessMirror(mBrightnessMirrorController); 995 mKeyguardStatusBar.setQSPanel(mQSPanel); 996 } 997 }); 998 } 999 1000 mReportRejectedTouch = mStatusBarWindow.findViewById(R.id.report_rejected_touch); 1001 if (mReportRejectedTouch != null) { 1002 updateReportRejectedTouchVisibility(); 1003 mReportRejectedTouch.setOnClickListener(v -> { 1004 Uri session = mFalsingManager.reportRejectedTouch(); 1005 if (session == null) { return; } 1006 1007 StringWriter message = new StringWriter(); 1008 message.write("Build info: "); 1009 message.write(SystemProperties.get("ro.build.description")); 1010 message.write("\nSerial number: "); 1011 message.write(SystemProperties.get("ro.serialno")); 1012 message.write("\n"); 1013 1014 PrintWriter falsingPw = new PrintWriter(message); 1015 FalsingLog.dump(falsingPw); 1016 falsingPw.flush(); 1017 1018 startActivityDismissingKeyguard(Intent.createChooser(new Intent(Intent.ACTION_SEND) 1019 .setType("*/*") 1020 .putExtra(Intent.EXTRA_SUBJECT, "Rejected touch report") 1021 .putExtra(Intent.EXTRA_STREAM, session) 1022 .putExtra(Intent.EXTRA_TEXT, message.toString()), 1023 "Share rejected touch report") 1024 .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK), 1025 true /* onlyProvisioned */, true /* dismissShade */); 1026 }); 1027 } 1028 1029 PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE); 1030 if (!pm.isScreenOn()) { 1031 mBroadcastReceiver.onReceive(mContext, new Intent(Intent.ACTION_SCREEN_OFF)); 1032 } 1033 mGestureWakeLock = pm.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK, 1034 "GestureWakeLock"); 1035 mVibrator = mContext.getSystemService(Vibrator.class); 1036 int[] pattern = mContext.getResources().getIntArray( 1037 R.array.config_cameraLaunchGestureVibePattern); 1038 mCameraLaunchGestureVibePattern = new long[pattern.length]; 1039 for (int i = 0; i < pattern.length; i++) { 1040 mCameraLaunchGestureVibePattern[i] = pattern[i]; 1041 } 1042 1043 // receive broadcasts 1044 IntentFilter filter = new IntentFilter(); 1045 filter.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS); 1046 filter.addAction(Intent.ACTION_SCREEN_OFF); 1047 filter.addAction(DevicePolicyManager.ACTION_SHOW_DEVICE_MONITORING_DIALOG); 1048 context.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL, filter, null, null); 1049 1050 IntentFilter demoFilter = new IntentFilter(); 1051 if (DEBUG_MEDIA_FAKE_ARTWORK) { 1052 demoFilter.addAction(ACTION_FAKE_ARTWORK); 1053 } 1054 demoFilter.addAction(ACTION_DEMO); 1055 context.registerReceiverAsUser(mDemoReceiver, UserHandle.ALL, demoFilter, 1056 android.Manifest.permission.DUMP, null); 1057 1058 // listen for USER_SETUP_COMPLETE setting (per-user) 1059 mDeviceProvisionedController.addCallback(mUserSetupObserver); 1060 mUserSetupObserver.onUserSetupChanged(); 1061 1062 // disable profiling bars, since they overlap and clutter the output on app windows 1063 ThreadedRenderer.overrideProperty("disableProfileBars", "true"); 1064 1065 // Private API call to make the shadows look better for Recents 1066 ThreadedRenderer.overrideProperty("ambientRatio", String.valueOf(1.5f)); 1067 } 1068 createNavigationBar()1069 protected void createNavigationBar() { 1070 mNavigationBarView = NavigationBarFragment.create(mContext, (tag, fragment) -> { 1071 mNavigationBar = (NavigationBarFragment) fragment; 1072 if (mLightBarController != null) { 1073 mNavigationBar.setLightBarController(mLightBarController); 1074 } 1075 mNavigationBar.setCurrentSysuiVisibility(mSystemUiVisibility); 1076 }); 1077 } 1078 1079 /** 1080 * Returns the {@link android.view.View.OnTouchListener} that will be invoked when the 1081 * background window of the status bar is clicked. 1082 */ getStatusBarWindowTouchListener()1083 protected View.OnTouchListener getStatusBarWindowTouchListener() { 1084 return (v, event) -> { 1085 checkUserAutohide(event); 1086 mRemoteInputManager.checkRemoteInputOutside(event); 1087 if (event.getAction() == MotionEvent.ACTION_DOWN) { 1088 if (mExpandedVisible) { 1089 animateCollapsePanels(); 1090 } 1091 } 1092 return mStatusBarWindow.onTouchEvent(event); 1093 }; 1094 } 1095 inflateShelf()1096 private void inflateShelf() { 1097 mNotificationShelf = 1098 (NotificationShelf) LayoutInflater.from(mContext).inflate( 1099 R.layout.status_bar_notification_shelf, mStackScroller, false); 1100 mNotificationShelf.setOnActivatedListener(this); 1101 mStackScroller.setShelf(mNotificationShelf); 1102 mNotificationShelf.setOnClickListener(mGoToLockedShadeListener); 1103 mNotificationShelf.setStatusBarState(mState); 1104 } 1105 onDensityOrFontScaleChanged()1106 public void onDensityOrFontScaleChanged() { 1107 MessagingMessage.dropCache(); 1108 MessagingGroup.dropCache(); 1109 // start old BaseStatusBar.onDensityOrFontScaleChanged(). 1110 if (!KeyguardUpdateMonitor.getInstance(mContext).isSwitchingUser()) { 1111 mEntryManager.updateNotificationsOnDensityOrFontScaleChanged(); 1112 } else { 1113 mReinflateNotificationsOnUserSwitched = true; 1114 } 1115 // end old BaseStatusBar.onDensityOrFontScaleChanged(). 1116 // TODO: Remove this. 1117 if (mBrightnessMirrorController != null) { 1118 mBrightnessMirrorController.onDensityOrFontScaleChanged(); 1119 } 1120 mStatusBarKeyguardViewManager.onDensityOrFontScaleChanged(); 1121 // TODO: Bring these out of StatusBar. 1122 ((UserInfoControllerImpl) Dependency.get(UserInfoController.class)) 1123 .onDensityOrFontScaleChanged(); 1124 Dependency.get(UserSwitcherController.class).onDensityOrFontScaleChanged(); 1125 if (mKeyguardUserSwitcher != null) { 1126 mKeyguardUserSwitcher.onDensityOrFontScaleChanged(); 1127 } 1128 mNotificationIconAreaController.onDensityOrFontScaleChanged(mContext); 1129 mHeadsUpManager.onDensityOrFontScaleChanged(); 1130 1131 reevaluateStyles(); 1132 } 1133 onThemeChanged()1134 private void onThemeChanged() { 1135 reevaluateStyles(); 1136 1137 // Clock and bottom icons 1138 mNotificationPanel.onThemeChanged(); 1139 // The status bar on the keyguard is a special layout. 1140 if (mKeyguardStatusBar != null) mKeyguardStatusBar.onThemeChanged(); 1141 // Recreate Indication controller because internal references changed 1142 mKeyguardIndicationController = 1143 SystemUIFactory.getInstance().createKeyguardIndicationController(mContext, 1144 mStatusBarWindow.findViewById(R.id.keyguard_indication_area), 1145 mNotificationPanel.getLockIcon()); 1146 mNotificationPanel.setKeyguardIndicationController(mKeyguardIndicationController); 1147 mKeyguardIndicationController 1148 .setStatusBarKeyguardViewManager(mStatusBarKeyguardViewManager); 1149 mKeyguardIndicationController.setVisible(mState == StatusBarState.KEYGUARD); 1150 mKeyguardIndicationController.setDozing(mDozing); 1151 if (mStatusBarKeyguardViewManager != null) { 1152 mStatusBarKeyguardViewManager.onThemeChanged(); 1153 } 1154 if (mAmbientIndicationContainer instanceof AutoReinflateContainer) { 1155 ((AutoReinflateContainer) mAmbientIndicationContainer).inflateLayout(); 1156 } 1157 } 1158 reevaluateStyles()1159 protected void reevaluateStyles() { 1160 inflateFooterView(); 1161 updateFooter(); 1162 inflateEmptyShadeView(); 1163 updateEmptyShadeView(); 1164 } 1165 1166 @Override onOverlayChanged()1167 public void onOverlayChanged() { 1168 if (mBrightnessMirrorController != null) { 1169 mBrightnessMirrorController.onOverlayChanged(); 1170 } 1171 } 1172 inflateEmptyShadeView()1173 private void inflateEmptyShadeView() { 1174 if (mStackScroller == null) { 1175 return; 1176 } 1177 mEmptyShadeView = (EmptyShadeView) LayoutInflater.from(mContext).inflate( 1178 R.layout.status_bar_no_notifications, mStackScroller, false); 1179 mEmptyShadeView.setText(R.string.empty_shade_text); 1180 mStackScroller.setEmptyShadeView(mEmptyShadeView); 1181 } 1182 inflateFooterView()1183 private void inflateFooterView() { 1184 if (mStackScroller == null) { 1185 return; 1186 } 1187 1188 mFooterView = (FooterView) LayoutInflater.from(mContext).inflate( 1189 R.layout.status_bar_notification_footer, mStackScroller, false); 1190 mFooterView.setDismissButtonClickListener(v -> { 1191 mMetricsLogger.action(MetricsEvent.ACTION_DISMISS_ALL_NOTES); 1192 clearAllNotifications(); 1193 }); 1194 mFooterView.setManageButtonClickListener(v -> { 1195 manageNotifications(); 1196 }); 1197 mStackScroller.setFooterView(mFooterView); 1198 } 1199 createUserSwitcher()1200 protected void createUserSwitcher() { 1201 mKeyguardUserSwitcher = new KeyguardUserSwitcher(mContext, 1202 mStatusBarWindow.findViewById(R.id.keyguard_user_switcher), mKeyguardStatusBar, 1203 mNotificationPanel); 1204 } 1205 inflateStatusBarWindow(Context context)1206 protected void inflateStatusBarWindow(Context context) { 1207 mStatusBarWindow = (StatusBarWindowView) View.inflate(context, 1208 R.layout.super_status_bar, null); 1209 } 1210 manageNotifications()1211 public void manageNotifications() { 1212 Intent intent = new Intent(Settings.ACTION_ALL_APPS_NOTIFICATION_SETTINGS); 1213 startActivity(intent, true, true, Intent.FLAG_ACTIVITY_SINGLE_TOP); 1214 } 1215 clearAllNotifications()1216 public void clearAllNotifications() { 1217 // animate-swipe all dismissable notifications, then animate the shade closed 1218 int numChildren = mStackScroller.getChildCount(); 1219 1220 final ArrayList<View> viewsToHide = new ArrayList<>(numChildren); 1221 final ArrayList<ExpandableNotificationRow> viewsToRemove = new ArrayList<>(numChildren); 1222 for (int i = 0; i < numChildren; i++) { 1223 final View child = mStackScroller.getChildAt(i); 1224 if (child instanceof ExpandableNotificationRow) { 1225 ExpandableNotificationRow row = (ExpandableNotificationRow) child; 1226 boolean parentVisible = false; 1227 boolean hasClipBounds = child.getClipBounds(mTmpRect); 1228 if (mStackScroller.canChildBeDismissed(child)) { 1229 viewsToRemove.add(row); 1230 if (child.getVisibility() == View.VISIBLE 1231 && (!hasClipBounds || mTmpRect.height() > 0)) { 1232 viewsToHide.add(child); 1233 parentVisible = true; 1234 } 1235 } else if (child.getVisibility() == View.VISIBLE 1236 && (!hasClipBounds || mTmpRect.height() > 0)) { 1237 parentVisible = true; 1238 } 1239 List<ExpandableNotificationRow> children = row.getNotificationChildren(); 1240 if (children != null) { 1241 for (ExpandableNotificationRow childRow : children) { 1242 viewsToRemove.add(childRow); 1243 if (parentVisible && row.areChildrenExpanded() 1244 && mStackScroller.canChildBeDismissed(childRow)) { 1245 hasClipBounds = childRow.getClipBounds(mTmpRect); 1246 if (childRow.getVisibility() == View.VISIBLE 1247 && (!hasClipBounds || mTmpRect.height() > 0)) { 1248 viewsToHide.add(childRow); 1249 } 1250 } 1251 } 1252 } 1253 } 1254 } 1255 if (viewsToRemove.isEmpty()) { 1256 animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_NONE); 1257 return; 1258 } 1259 1260 addPostCollapseAction(() -> { 1261 mStackScroller.setDismissAllInProgress(false); 1262 for (ExpandableNotificationRow rowToRemove : viewsToRemove) { 1263 if (mStackScroller.canChildBeDismissed(rowToRemove)) { 1264 mEntryManager.removeNotification(rowToRemove.getEntry().key, null); 1265 } else { 1266 rowToRemove.resetTranslation(); 1267 } 1268 } 1269 try { 1270 mBarService.onClearAllNotifications(mLockscreenUserManager.getCurrentUserId()); 1271 } catch (Exception ex) { 1272 } 1273 }); 1274 1275 performDismissAllAnimations(viewsToHide); 1276 1277 } 1278 performDismissAllAnimations(ArrayList<View> hideAnimatedList)1279 private void performDismissAllAnimations(ArrayList<View> hideAnimatedList) { 1280 Runnable animationFinishAction = () -> { 1281 animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_NONE); 1282 }; 1283 1284 if (hideAnimatedList.isEmpty()) { 1285 animationFinishAction.run(); 1286 return; 1287 } 1288 1289 // let's disable our normal animations 1290 mStackScroller.setDismissAllInProgress(true); 1291 1292 // Decrease the delay for every row we animate to give the sense of 1293 // accelerating the swipes 1294 int rowDelayDecrement = 10; 1295 int currentDelay = 140; 1296 int totalDelay = 180; 1297 int numItems = hideAnimatedList.size(); 1298 for (int i = numItems - 1; i >= 0; i--) { 1299 View view = hideAnimatedList.get(i); 1300 Runnable endRunnable = null; 1301 if (i == 0) { 1302 endRunnable = animationFinishAction; 1303 } 1304 mStackScroller.dismissViewAnimated(view, endRunnable, totalDelay, 260); 1305 currentDelay = Math.max(50, currentDelay - rowDelayDecrement); 1306 totalDelay += currentDelay; 1307 } 1308 } 1309 startKeyguard()1310 protected void startKeyguard() { 1311 Trace.beginSection("StatusBar#startKeyguard"); 1312 KeyguardViewMediator keyguardViewMediator = getComponent(KeyguardViewMediator.class); 1313 mFingerprintUnlockController = new FingerprintUnlockController(mContext, 1314 mDozeScrimController, keyguardViewMediator, 1315 mScrimController, this, UnlockMethodCache.getInstance(mContext)); 1316 mStatusBarKeyguardViewManager = keyguardViewMediator.registerStatusBar(this, 1317 getBouncerContainer(), mNotificationPanel, mFingerprintUnlockController); 1318 mKeyguardIndicationController 1319 .setStatusBarKeyguardViewManager(mStatusBarKeyguardViewManager); 1320 mFingerprintUnlockController.setStatusBarKeyguardViewManager(mStatusBarKeyguardViewManager); 1321 mRemoteInputManager.getController().addCallback(mStatusBarKeyguardViewManager); 1322 1323 mKeyguardViewMediatorCallback = keyguardViewMediator.getViewMediatorCallback(); 1324 mLightBarController.setFingerprintUnlockController(mFingerprintUnlockController); 1325 Dependency.get(KeyguardDismissUtil.class).setDismissHandler(this::executeWhenUnlocked); 1326 Trace.endSection(); 1327 } 1328 getStatusBarView()1329 protected View getStatusBarView() { 1330 return mStatusBarView; 1331 } 1332 getStatusBarWindow()1333 public StatusBarWindowView getStatusBarWindow() { 1334 return mStatusBarWindow; 1335 } 1336 getBouncerContainer()1337 protected ViewGroup getBouncerContainer() { 1338 return mStatusBarWindow; 1339 } 1340 getStatusBarHeight()1341 public int getStatusBarHeight() { 1342 if (mNaturalBarHeight < 0) { 1343 final Resources res = mContext.getResources(); 1344 mNaturalBarHeight = 1345 res.getDimensionPixelSize(com.android.internal.R.dimen.status_bar_height); 1346 } 1347 return mNaturalBarHeight; 1348 } 1349 toggleSplitScreenMode(int metricsDockAction, int metricsUndockAction)1350 protected boolean toggleSplitScreenMode(int metricsDockAction, int metricsUndockAction) { 1351 if (mRecents == null) { 1352 return false; 1353 } 1354 int dockSide = WindowManagerProxy.getInstance().getDockSide(); 1355 if (dockSide == WindowManager.DOCKED_INVALID) { 1356 final int navbarPos = WindowManagerWrapper.getInstance().getNavBarPosition(); 1357 if (navbarPos == NAV_BAR_POS_INVALID) { 1358 return false; 1359 } 1360 int createMode = navbarPos == NAV_BAR_POS_LEFT 1361 ? ActivityManager.SPLIT_SCREEN_CREATE_MODE_BOTTOM_OR_RIGHT 1362 : ActivityManager.SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT; 1363 return mRecents.splitPrimaryTask(NavigationBarGestureHelper.DRAG_MODE_NONE, createMode, 1364 null, metricsDockAction); 1365 } else { 1366 Divider divider = getComponent(Divider.class); 1367 if (divider != null && divider.isMinimized() && !divider.isHomeStackResizable()) { 1368 // Undocking from the minimized state is not supported 1369 return false; 1370 } else { 1371 EventBus.getDefault().send(new UndockingTaskEvent()); 1372 if (metricsUndockAction != -1) { 1373 mMetricsLogger.action(metricsUndockAction); 1374 } 1375 } 1376 } 1377 return true; 1378 } 1379 1380 @Override onPerformRemoveNotification(StatusBarNotification n)1381 public void onPerformRemoveNotification(StatusBarNotification n) { 1382 if (mStackScroller.hasPulsingNotifications() && 1383 !mHeadsUpManager.hasHeadsUpNotifications()) { 1384 // We were showing a pulse for a notification, but no notifications are pulsing anymore. 1385 // Finish the pulse. 1386 mDozeScrimController.pulseOutNow(); 1387 } 1388 } 1389 1390 @Override updateNotificationViews()1391 public void updateNotificationViews() { 1392 // The function updateRowStates depends on both of these being non-null, so check them here. 1393 // We may be called before they are set from DeviceProvisionedController's callback. 1394 if (mStackScroller == null || mScrimController == null) return; 1395 1396 // Do not modify the notifications during collapse. 1397 if (isCollapsing()) { 1398 addPostCollapseAction(this::updateNotificationViews); 1399 return; 1400 } 1401 1402 mViewHierarchyManager.updateNotificationViews(); 1403 1404 updateSpeedBumpIndex(); 1405 updateFooter(); 1406 updateEmptyShadeView(); 1407 1408 updateQsExpansionEnabled(); 1409 1410 // Let's also update the icons 1411 mNotificationIconAreaController.updateNotificationIcons(); 1412 } 1413 1414 @Override onNotificationAdded(Entry shadeEntry)1415 public void onNotificationAdded(Entry shadeEntry) { 1416 // Recalculate the position of the sliding windows and the titles. 1417 setAreThereNotifications(); 1418 } 1419 1420 @Override onNotificationUpdated(StatusBarNotification notification)1421 public void onNotificationUpdated(StatusBarNotification notification) { 1422 setAreThereNotifications(); 1423 } 1424 1425 @Override onNotificationRemoved(String key, StatusBarNotification old)1426 public void onNotificationRemoved(String key, StatusBarNotification old) { 1427 if (SPEW) Log.d(TAG, "removeNotification key=" + key + " old=" + old); 1428 1429 if (old != null) { 1430 if (CLOSE_PANEL_WHEN_EMPTIED && !hasActiveNotifications() 1431 && !mNotificationPanel.isTracking() && !mNotificationPanel.isQsExpanded()) { 1432 if (mState == StatusBarState.SHADE) { 1433 animateCollapsePanels(); 1434 } else if (mState == StatusBarState.SHADE_LOCKED && !isCollapsing()) { 1435 goToKeyguard(); 1436 } 1437 } 1438 } 1439 setAreThereNotifications(); 1440 } 1441 1442 /** 1443 * Disable QS if device not provisioned. 1444 * If the user switcher is simple then disable QS during setup because 1445 * the user intends to use the lock screen user switcher, QS in not needed. 1446 */ updateQsExpansionEnabled()1447 private void updateQsExpansionEnabled() { 1448 mNotificationPanel.setQsExpansionEnabled(isDeviceProvisioned() 1449 && (mUserSetup || mUserSwitcherController == null 1450 || !mUserSwitcherController.isSimpleUserSwitcher()) 1451 && ((mDisabled2 & StatusBarManager.DISABLE2_NOTIFICATION_SHADE) == 0) 1452 && ((mDisabled2 & StatusBarManager.DISABLE2_QUICK_SETTINGS) == 0) 1453 && !mDozing 1454 && !ONLY_CORE_APPS); 1455 } 1456 addQsTile(ComponentName tile)1457 public void addQsTile(ComponentName tile) { 1458 if (mQSPanel != null && mQSPanel.getHost() != null) { 1459 mQSPanel.getHost().addTile(tile); 1460 } 1461 } 1462 remQsTile(ComponentName tile)1463 public void remQsTile(ComponentName tile) { 1464 if (mQSPanel != null && mQSPanel.getHost() != null) { 1465 mQSPanel.getHost().removeTile(tile); 1466 } 1467 } 1468 clickTile(ComponentName tile)1469 public void clickTile(ComponentName tile) { 1470 mQSPanel.clickTile(tile); 1471 } 1472 1473 @VisibleForTesting updateFooter()1474 protected void updateFooter() { 1475 boolean showDismissView = mClearAllEnabled && hasActiveClearableNotifications(); 1476 boolean showFooterView = (showDismissView || 1477 mEntryManager.getNotificationData().getActiveNotifications().size() != 0) 1478 && mState != StatusBarState.KEYGUARD 1479 && !mRemoteInputManager.getController().isRemoteInputActive(); 1480 1481 mStackScroller.updateFooterView(showFooterView, showDismissView); 1482 } 1483 1484 /** 1485 * Return whether there are any clearable notifications 1486 */ hasActiveClearableNotifications()1487 private boolean hasActiveClearableNotifications() { 1488 int childCount = mStackScroller.getChildCount(); 1489 for (int i = 0; i < childCount; i++) { 1490 View child = mStackScroller.getChildAt(i); 1491 if (!(child instanceof ExpandableNotificationRow)) { 1492 continue; 1493 } 1494 if (((ExpandableNotificationRow) child).canViewBeDismissed()) { 1495 return true; 1496 } 1497 } 1498 return false; 1499 } 1500 updateEmptyShadeView()1501 private void updateEmptyShadeView() { 1502 boolean showEmptyShadeView = 1503 mState != StatusBarState.KEYGUARD && 1504 mEntryManager.getNotificationData().getActiveNotifications().size() == 0; 1505 mNotificationPanel.showEmptyShadeView(showEmptyShadeView); 1506 } 1507 updateSpeedBumpIndex()1508 private void updateSpeedBumpIndex() { 1509 int speedBumpIndex = 0; 1510 int currentIndex = 0; 1511 final int N = mStackScroller.getChildCount(); 1512 for (int i = 0; i < N; i++) { 1513 View view = mStackScroller.getChildAt(i); 1514 if (view.getVisibility() == View.GONE || !(view instanceof ExpandableNotificationRow)) { 1515 continue; 1516 } 1517 ExpandableNotificationRow row = (ExpandableNotificationRow) view; 1518 currentIndex++; 1519 if (!mEntryManager.getNotificationData().isAmbient( 1520 row.getStatusBarNotification().getKey())) { 1521 speedBumpIndex = currentIndex; 1522 } 1523 } 1524 boolean noAmbient = speedBumpIndex == N; 1525 mStackScroller.updateSpeedBumpIndex(speedBumpIndex, noAmbient); 1526 } 1527 isTopLevelChild(Entry entry)1528 public static boolean isTopLevelChild(Entry entry) { 1529 return entry.row.getParent() instanceof NotificationStackScrollLayout; 1530 } 1531 areNotificationsHidden()1532 public boolean areNotificationsHidden() { 1533 return mZenController.areNotificationsHiddenInShade(); 1534 } 1535 requestNotificationUpdate()1536 public void requestNotificationUpdate() { 1537 mEntryManager.updateNotifications(); 1538 } 1539 setAreThereNotifications()1540 protected void setAreThereNotifications() { 1541 1542 if (SPEW) { 1543 final boolean clearable = hasActiveNotifications() && 1544 hasActiveClearableNotifications(); 1545 Log.d(TAG, "setAreThereNotifications: N=" + 1546 mEntryManager.getNotificationData().getActiveNotifications().size() + " any=" + 1547 hasActiveNotifications() + " clearable=" + clearable); 1548 } 1549 1550 if (mStatusBarView != null) { 1551 final View nlo = mStatusBarView.findViewById(R.id.notification_lights_out); 1552 final boolean showDot = hasActiveNotifications() && !areLightsOn(); 1553 if (showDot != (nlo.getAlpha() == 1.0f)) { 1554 if (showDot) { 1555 nlo.setAlpha(0f); 1556 nlo.setVisibility(View.VISIBLE); 1557 } 1558 nlo.animate() 1559 .alpha(showDot ? 1 : 0) 1560 .setDuration(showDot ? 750 : 250) 1561 .setInterpolator(new AccelerateInterpolator(2.0f)) 1562 .setListener(showDot ? null : new AnimatorListenerAdapter() { 1563 @Override 1564 public void onAnimationEnd(Animator _a) { 1565 nlo.setVisibility(View.GONE); 1566 } 1567 }) 1568 .start(); 1569 } 1570 } 1571 1572 mMediaManager.findAndUpdateMediaNotifications(); 1573 } 1574 1575 1576 /** 1577 * Hide the album artwork that is fading out and release its bitmap. 1578 */ 1579 protected final Runnable mHideBackdropFront = new Runnable() { 1580 @Override 1581 public void run() { 1582 if (DEBUG_MEDIA) { 1583 Log.v(TAG, "DEBUG_MEDIA: removing fade layer"); 1584 } 1585 mBackdropFront.setVisibility(View.INVISIBLE); 1586 mBackdropFront.animate().cancel(); 1587 mBackdropFront.setImageDrawable(null); 1588 } 1589 }; 1590 1591 // TODO: Move this to NotificationMediaManager. 1592 /** 1593 * Refresh or remove lockscreen artwork from media metadata or the lockscreen wallpaper. 1594 */ 1595 @Override updateMediaMetaData(boolean metaDataChanged, boolean allowEnterAnimation)1596 public void updateMediaMetaData(boolean metaDataChanged, boolean allowEnterAnimation) { 1597 Trace.beginSection("StatusBar#updateMediaMetaData"); 1598 if (!SHOW_LOCKSCREEN_MEDIA_ARTWORK) { 1599 Trace.endSection(); 1600 return; 1601 } 1602 1603 if (mBackdrop == null) { 1604 Trace.endSection(); 1605 return; // called too early 1606 } 1607 1608 boolean wakeAndUnlock = mFingerprintUnlockController != null 1609 && mFingerprintUnlockController.isWakeAndUnlock(); 1610 if (mLaunchTransitionFadingAway || wakeAndUnlock) { 1611 mBackdrop.setVisibility(View.INVISIBLE); 1612 Trace.endSection(); 1613 return; 1614 } 1615 1616 MediaMetadata mediaMetadata = mMediaManager.getMediaMetadata(); 1617 1618 if (DEBUG_MEDIA) { 1619 Log.v(TAG, "DEBUG_MEDIA: updating album art for notification " 1620 + mMediaManager.getMediaNotificationKey() 1621 + " metadata=" + mediaMetadata 1622 + " metaDataChanged=" + metaDataChanged 1623 + " state=" + mState); 1624 } 1625 1626 Drawable artworkDrawable = null; 1627 if (mediaMetadata != null) { 1628 Bitmap artworkBitmap = mediaMetadata.getBitmap(MediaMetadata.METADATA_KEY_ART); 1629 if (artworkBitmap == null) { 1630 artworkBitmap = mediaMetadata.getBitmap(MediaMetadata.METADATA_KEY_ALBUM_ART); 1631 // might still be null 1632 } 1633 if (artworkBitmap != null) { 1634 artworkDrawable = new BitmapDrawable(mBackdropBack.getResources(), artworkBitmap); 1635 } 1636 } 1637 boolean allowWhenShade = false; 1638 if (ENABLE_LOCKSCREEN_WALLPAPER && artworkDrawable == null) { 1639 Bitmap lockWallpaper = mLockscreenWallpaper.getBitmap(); 1640 if (lockWallpaper != null) { 1641 artworkDrawable = new LockscreenWallpaper.WallpaperDrawable( 1642 mBackdropBack.getResources(), lockWallpaper); 1643 // We're in the SHADE mode on the SIM screen - yet we still need to show 1644 // the lockscreen wallpaper in that mode. 1645 allowWhenShade = mStatusBarKeyguardViewManager != null 1646 && mStatusBarKeyguardViewManager.isShowing(); 1647 } 1648 } 1649 1650 boolean hideBecauseOccluded = mStatusBarKeyguardViewManager != null 1651 && mStatusBarKeyguardViewManager.isOccluded(); 1652 1653 final boolean hasArtwork = artworkDrawable != null; 1654 1655 if ((hasArtwork || DEBUG_MEDIA_FAKE_ARTWORK) && !mDozing 1656 && (mState != StatusBarState.SHADE || allowWhenShade) 1657 && mFingerprintUnlockController.getMode() 1658 != FingerprintUnlockController.MODE_WAKE_AND_UNLOCK_PULSING 1659 && !hideBecauseOccluded) { 1660 // time to show some art! 1661 if (mBackdrop.getVisibility() != View.VISIBLE) { 1662 mBackdrop.setVisibility(View.VISIBLE); 1663 if (allowEnterAnimation) { 1664 mBackdrop.setAlpha(SRC_MIN_ALPHA); 1665 mBackdrop.animate().alpha(1f); 1666 } else { 1667 mBackdrop.animate().cancel(); 1668 mBackdrop.setAlpha(1f); 1669 } 1670 mStatusBarWindowManager.setBackdropShowing(true); 1671 mColorExtractor.setMediaBackdropVisible(true); 1672 metaDataChanged = true; 1673 if (DEBUG_MEDIA) { 1674 Log.v(TAG, "DEBUG_MEDIA: Fading in album artwork"); 1675 } 1676 } 1677 if (metaDataChanged) { 1678 if (mBackdropBack.getDrawable() != null) { 1679 Drawable drawable = 1680 mBackdropBack.getDrawable().getConstantState() 1681 .newDrawable(mBackdropFront.getResources()).mutate(); 1682 mBackdropFront.setImageDrawable(drawable); 1683 if (mScrimSrcModeEnabled) { 1684 mBackdropFront.getDrawable().mutate().setXfermode(mSrcOverXferMode); 1685 } 1686 mBackdropFront.setAlpha(1f); 1687 mBackdropFront.setVisibility(View.VISIBLE); 1688 } else { 1689 mBackdropFront.setVisibility(View.INVISIBLE); 1690 } 1691 1692 if (DEBUG_MEDIA_FAKE_ARTWORK) { 1693 final int c = 0xFF000000 | (int)(Math.random() * 0xFFFFFF); 1694 Log.v(TAG, String.format("DEBUG_MEDIA: setting new color: 0x%08x", c)); 1695 mBackdropBack.setBackgroundColor(0xFFFFFFFF); 1696 mBackdropBack.setImageDrawable(new ColorDrawable(c)); 1697 } else { 1698 mBackdropBack.setImageDrawable(artworkDrawable); 1699 } 1700 if (mScrimSrcModeEnabled) { 1701 mBackdropBack.getDrawable().mutate().setXfermode(mSrcXferMode); 1702 } 1703 1704 if (mBackdropFront.getVisibility() == View.VISIBLE) { 1705 if (DEBUG_MEDIA) { 1706 Log.v(TAG, "DEBUG_MEDIA: Crossfading album artwork from " 1707 + mBackdropFront.getDrawable() 1708 + " to " 1709 + mBackdropBack.getDrawable()); 1710 } 1711 mBackdropFront.animate() 1712 .setDuration(250) 1713 .alpha(0f).withEndAction(mHideBackdropFront); 1714 } 1715 } 1716 } else { 1717 // need to hide the album art, either because we are unlocked, on AOD 1718 // or because the metadata isn't there to support it 1719 if (mBackdrop.getVisibility() != View.GONE) { 1720 if (DEBUG_MEDIA) { 1721 Log.v(TAG, "DEBUG_MEDIA: Fading out album artwork"); 1722 } 1723 mColorExtractor.setMediaBackdropVisible(false); 1724 boolean cannotAnimateDoze = mDozing && !ScrimState.AOD.getAnimateChange(); 1725 if (mFingerprintUnlockController.getMode() 1726 == FingerprintUnlockController.MODE_WAKE_AND_UNLOCK_PULSING 1727 || hideBecauseOccluded || cannotAnimateDoze) { 1728 1729 // We are unlocking directly - no animation! 1730 mBackdrop.setVisibility(View.GONE); 1731 mBackdropBack.setImageDrawable(null); 1732 mStatusBarWindowManager.setBackdropShowing(false); 1733 } else { 1734 mStatusBarWindowManager.setBackdropShowing(false); 1735 mBackdrop.animate() 1736 .alpha(SRC_MIN_ALPHA) 1737 .setInterpolator(Interpolators.ACCELERATE_DECELERATE) 1738 .setDuration(300) 1739 .setStartDelay(0) 1740 .withEndAction(() -> { 1741 mBackdrop.setVisibility(View.GONE); 1742 mBackdropFront.animate().cancel(); 1743 mBackdropBack.setImageDrawable(null); 1744 mHandler.post(mHideBackdropFront); 1745 }); 1746 if (mKeyguardFadingAway) { 1747 mBackdrop.animate() 1748 // Make it disappear faster, as the focus should be on the activity 1749 // behind. 1750 .setDuration(mKeyguardFadingAwayDuration / 2) 1751 .setStartDelay(mKeyguardFadingAwayDelay) 1752 .setInterpolator(Interpolators.LINEAR) 1753 .start(); 1754 } 1755 } 1756 } 1757 } 1758 Trace.endSection(); 1759 } 1760 updateReportRejectedTouchVisibility()1761 private void updateReportRejectedTouchVisibility() { 1762 if (mReportRejectedTouch == null) { 1763 return; 1764 } 1765 mReportRejectedTouch.setVisibility(mState == StatusBarState.KEYGUARD && !mDozing 1766 && mFalsingManager.isReportingEnabled() ? View.VISIBLE : View.INVISIBLE); 1767 } 1768 1769 /** 1770 * State is one or more of the DISABLE constants from StatusBarManager. 1771 */ 1772 @Override disable(int state1, int state2, boolean animate)1773 public void disable(int state1, int state2, boolean animate) { 1774 state2 = mRemoteInputQuickSettingsDisabler.adjustDisableFlags(state2); 1775 1776 animate &= mStatusBarWindowState != WINDOW_STATE_HIDDEN; 1777 final int old1 = mDisabled1; 1778 final int diff1 = state1 ^ old1; 1779 mDisabled1 = state1; 1780 1781 final int old2 = mDisabled2; 1782 final int diff2 = state2 ^ old2; 1783 mDisabled2 = state2; 1784 1785 if (DEBUG) { 1786 Log.d(TAG, String.format("disable1: 0x%08x -> 0x%08x (diff1: 0x%08x)", 1787 old1, state1, diff1)); 1788 Log.d(TAG, String.format("disable2: 0x%08x -> 0x%08x (diff2: 0x%08x)", 1789 old2, state2, diff2)); 1790 } 1791 1792 StringBuilder flagdbg = new StringBuilder(); 1793 flagdbg.append("disable<"); 1794 flagdbg.append(0 != ((state1 & StatusBarManager.DISABLE_EXPAND)) ? 'E' : 'e'); 1795 flagdbg.append(0 != ((diff1 & StatusBarManager.DISABLE_EXPAND)) ? '!' : ' '); 1796 flagdbg.append(0 != ((state1 & StatusBarManager.DISABLE_NOTIFICATION_ICONS)) ? 'I' : 'i'); 1797 flagdbg.append(0 != ((diff1 & StatusBarManager.DISABLE_NOTIFICATION_ICONS)) ? '!' : ' '); 1798 flagdbg.append(0 != ((state1 & StatusBarManager.DISABLE_NOTIFICATION_ALERTS)) ? 'A' : 'a'); 1799 flagdbg.append(0 != ((diff1 & StatusBarManager.DISABLE_NOTIFICATION_ALERTS)) ? '!' : ' '); 1800 flagdbg.append(0 != ((state1 & StatusBarManager.DISABLE_SYSTEM_INFO)) ? 'S' : 's'); 1801 flagdbg.append(0 != ((diff1 & StatusBarManager.DISABLE_SYSTEM_INFO)) ? '!' : ' '); 1802 flagdbg.append(0 != ((state1 & StatusBarManager.DISABLE_BACK)) ? 'B' : 'b'); 1803 flagdbg.append(0 != ((diff1 & StatusBarManager.DISABLE_BACK)) ? '!' : ' '); 1804 flagdbg.append(0 != ((state1 & StatusBarManager.DISABLE_HOME)) ? 'H' : 'h'); 1805 flagdbg.append(0 != ((diff1 & StatusBarManager.DISABLE_HOME)) ? '!' : ' '); 1806 flagdbg.append(0 != ((state1 & StatusBarManager.DISABLE_RECENT)) ? 'R' : 'r'); 1807 flagdbg.append(0 != ((diff1 & StatusBarManager.DISABLE_RECENT)) ? '!' : ' '); 1808 flagdbg.append(0 != ((state1 & StatusBarManager.DISABLE_CLOCK)) ? 'C' : 'c'); 1809 flagdbg.append(0 != ((diff1 & StatusBarManager.DISABLE_CLOCK)) ? '!' : ' '); 1810 flagdbg.append(0 != ((state1 & StatusBarManager.DISABLE_SEARCH)) ? 'S' : 's'); 1811 flagdbg.append(0 != ((diff1 & StatusBarManager.DISABLE_SEARCH)) ? '!' : ' '); 1812 flagdbg.append("> disable2<"); 1813 flagdbg.append(0 != ((state2 & StatusBarManager.DISABLE2_QUICK_SETTINGS)) ? 'Q' : 'q'); 1814 flagdbg.append(0 != ((diff2 & StatusBarManager.DISABLE2_QUICK_SETTINGS)) ? '!' : ' '); 1815 flagdbg.append(0 != ((state2 & StatusBarManager.DISABLE2_SYSTEM_ICONS)) ? 'I' : 'i'); 1816 flagdbg.append(0 != ((diff2 & StatusBarManager.DISABLE2_SYSTEM_ICONS)) ? '!' : ' '); 1817 flagdbg.append(0 != ((state2 & StatusBarManager.DISABLE2_NOTIFICATION_SHADE)) ? 'N' : 'n'); 1818 flagdbg.append(0 != ((diff2 & StatusBarManager.DISABLE2_NOTIFICATION_SHADE)) ? '!' : ' '); 1819 flagdbg.append('>'); 1820 Log.d(TAG, flagdbg.toString()); 1821 1822 if ((diff1 & StatusBarManager.DISABLE_EXPAND) != 0) { 1823 if ((state1 & StatusBarManager.DISABLE_EXPAND) != 0) { 1824 animateCollapsePanels(); 1825 } 1826 } 1827 1828 if ((diff1 & StatusBarManager.DISABLE_RECENT) != 0) { 1829 if ((state1 & StatusBarManager.DISABLE_RECENT) != 0) { 1830 // close recents if it's visible 1831 mHandler.removeMessages(MSG_HIDE_RECENT_APPS); 1832 mHandler.sendEmptyMessage(MSG_HIDE_RECENT_APPS); 1833 } 1834 } 1835 1836 if ((diff1 & StatusBarManager.DISABLE_NOTIFICATION_ALERTS) != 0) { 1837 mEntryManager.setDisableNotificationAlerts( 1838 (state1 & StatusBarManager.DISABLE_NOTIFICATION_ALERTS) != 0); 1839 } 1840 1841 if ((diff2 & StatusBarManager.DISABLE2_QUICK_SETTINGS) != 0) { 1842 updateQsExpansionEnabled(); 1843 } 1844 1845 if ((diff2 & StatusBarManager.DISABLE2_NOTIFICATION_SHADE) != 0) { 1846 updateQsExpansionEnabled(); 1847 if ((state1 & StatusBarManager.DISABLE2_NOTIFICATION_SHADE) != 0) { 1848 animateCollapsePanels(); 1849 } 1850 } 1851 } 1852 1853 /** 1854 * Reapplies the disable flags as last requested by StatusBarManager. 1855 * 1856 * This needs to be called if state used by {@link #adjustDisableFlags} changes. 1857 */ recomputeDisableFlags(boolean animate)1858 public void recomputeDisableFlags(boolean animate) { 1859 mCommandQueue.recomputeDisableFlags(animate); 1860 } 1861 createHandler()1862 protected H createHandler() { 1863 return new StatusBar.H(); 1864 } 1865 startActivity(Intent intent, boolean onlyProvisioned, boolean dismissShade, int flags)1866 private void startActivity(Intent intent, boolean onlyProvisioned, boolean dismissShade, 1867 int flags) { 1868 startActivityDismissingKeyguard(intent, onlyProvisioned, dismissShade, flags); 1869 } 1870 1871 @Override startActivity(Intent intent, boolean dismissShade)1872 public void startActivity(Intent intent, boolean dismissShade) { 1873 startActivityDismissingKeyguard(intent, false, dismissShade); 1874 } 1875 1876 @Override startActivity(Intent intent, boolean onlyProvisioned, boolean dismissShade)1877 public void startActivity(Intent intent, boolean onlyProvisioned, boolean dismissShade) { 1878 startActivityDismissingKeyguard(intent, onlyProvisioned, dismissShade); 1879 } 1880 1881 @Override startActivity(Intent intent, boolean dismissShade, Callback callback)1882 public void startActivity(Intent intent, boolean dismissShade, Callback callback) { 1883 startActivityDismissingKeyguard(intent, false, dismissShade, 1884 false /* disallowEnterPictureInPictureWhileLaunching */, callback, 0); 1885 } 1886 setQsExpanded(boolean expanded)1887 public void setQsExpanded(boolean expanded) { 1888 mStatusBarWindowManager.setQsExpanded(expanded); 1889 mNotificationPanel.setStatusAccessibilityImportance(expanded 1890 ? View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS 1891 : View.IMPORTANT_FOR_ACCESSIBILITY_AUTO); 1892 } 1893 isGoingToNotificationShade()1894 public boolean isGoingToNotificationShade() { 1895 return mLeaveOpenOnKeyguardHide; 1896 } 1897 isWakeUpComingFromTouch()1898 public boolean isWakeUpComingFromTouch() { 1899 return mWakeUpComingFromTouch; 1900 } 1901 isFalsingThresholdNeeded()1902 public boolean isFalsingThresholdNeeded() { 1903 return getBarState() == StatusBarState.KEYGUARD; 1904 } 1905 1906 @Override isDozing()1907 public boolean isDozing() { 1908 return mDozing && mStackScroller.isFullyDark(); 1909 } 1910 1911 @Override shouldPeek(Entry entry, StatusBarNotification sbn)1912 public boolean shouldPeek(Entry entry, StatusBarNotification sbn) { 1913 if (mIsOccluded && !isDozing()) { 1914 boolean devicePublic = mLockscreenUserManager. 1915 isLockscreenPublicMode(mLockscreenUserManager.getCurrentUserId()); 1916 boolean userPublic = devicePublic 1917 || mLockscreenUserManager.isLockscreenPublicMode(sbn.getUserId()); 1918 boolean needsRedaction = mLockscreenUserManager.needsRedaction(entry); 1919 if (userPublic && needsRedaction) { 1920 return false; 1921 } 1922 } 1923 1924 if (!panelsEnabled()) { 1925 if (DEBUG) { 1926 Log.d(TAG, "No peeking: disabled panel : " + sbn.getKey()); 1927 } 1928 return false; 1929 } 1930 1931 if (sbn.getNotification().fullScreenIntent != null) { 1932 if (mAccessibilityManager.isTouchExplorationEnabled()) { 1933 if (DEBUG) Log.d(TAG, "No peeking: accessible fullscreen: " + sbn.getKey()); 1934 return false; 1935 } else if (isDozing()) { 1936 // We never want heads up when we are dozing. 1937 return false; 1938 } else { 1939 // we only allow head-up on the lockscreen if it doesn't have a fullscreen intent 1940 return !mStatusBarKeyguardViewManager.isShowing() 1941 || mStatusBarKeyguardViewManager.isOccluded(); 1942 } 1943 } 1944 return true; 1945 } 1946 1947 @Override // NotificationData.Environment getCurrentMediaNotificationKey()1948 public String getCurrentMediaNotificationKey() { 1949 return mMediaManager.getMediaNotificationKey(); 1950 } 1951 isScrimSrcModeEnabled()1952 public boolean isScrimSrcModeEnabled() { 1953 return mScrimSrcModeEnabled; 1954 } 1955 1956 /** 1957 * To be called when there's a state change in StatusBarKeyguardViewManager. 1958 */ onKeyguardViewManagerStatesUpdated()1959 public void onKeyguardViewManagerStatesUpdated() { 1960 logStateToEventlog(); 1961 } 1962 1963 @Override // UnlockMethodCache.OnUnlockMethodChangedListener onUnlockMethodStateChanged()1964 public void onUnlockMethodStateChanged() { 1965 logStateToEventlog(); 1966 } 1967 1968 @Override onHeadsUpPinnedModeChanged(boolean inPinnedMode)1969 public void onHeadsUpPinnedModeChanged(boolean inPinnedMode) { 1970 if (inPinnedMode) { 1971 mStatusBarWindowManager.setHeadsUpShowing(true); 1972 mStatusBarWindowManager.setForceStatusBarVisible(true); 1973 if (mNotificationPanel.isFullyCollapsed()) { 1974 // We need to ensure that the touchable region is updated before the window will be 1975 // resized, in order to not catch any touches. A layout will ensure that 1976 // onComputeInternalInsets will be called and after that we can resize the layout. Let's 1977 // make sure that the window stays small for one frame until the touchableRegion is set. 1978 mNotificationPanel.requestLayout(); 1979 mStatusBarWindowManager.setForceWindowCollapsed(true); 1980 mNotificationPanel.post(() -> { 1981 mStatusBarWindowManager.setForceWindowCollapsed(false); 1982 }); 1983 } 1984 } else { 1985 if (!mNotificationPanel.isFullyCollapsed() || mNotificationPanel.isTracking()) { 1986 // We are currently tracking or is open and the shade doesn't need to be kept 1987 // open artificially. 1988 mStatusBarWindowManager.setHeadsUpShowing(false); 1989 } else { 1990 // we need to keep the panel open artificially, let's wait until the animation 1991 // is finished. 1992 mHeadsUpManager.setHeadsUpGoingAway(true); 1993 mStackScroller.runAfterAnimationFinished(() -> { 1994 if (!mHeadsUpManager.hasPinnedHeadsUp()) { 1995 mStatusBarWindowManager.setHeadsUpShowing(false); 1996 mHeadsUpManager.setHeadsUpGoingAway(false); 1997 } 1998 mRemoteInputManager.removeRemoteInputEntriesKeptUntilCollapsed(); 1999 }); 2000 } 2001 } 2002 } 2003 2004 @Override onHeadsUpPinned(ExpandableNotificationRow headsUp)2005 public void onHeadsUpPinned(ExpandableNotificationRow headsUp) { 2006 dismissVolumeDialog(); 2007 } 2008 2009 @Override onHeadsUpUnPinned(ExpandableNotificationRow headsUp)2010 public void onHeadsUpUnPinned(ExpandableNotificationRow headsUp) { 2011 } 2012 2013 @Override onHeadsUpStateChanged(Entry entry, boolean isHeadsUp)2014 public void onHeadsUpStateChanged(Entry entry, boolean isHeadsUp) { 2015 mEntryManager.onHeadsUpStateChanged(entry, isHeadsUp); 2016 2017 if (isHeadsUp) { 2018 mDozeServiceHost.fireNotificationHeadsUp(); 2019 } 2020 } 2021 setHeadsUpUser(int newUserId)2022 protected void setHeadsUpUser(int newUserId) { 2023 if (mHeadsUpManager != null) { 2024 mHeadsUpManager.setUser(newUserId); 2025 } 2026 } 2027 isKeyguardCurrentlySecure()2028 public boolean isKeyguardCurrentlySecure() { 2029 return !mUnlockMethodCache.canSkipBouncer(); 2030 } 2031 setPanelExpanded(boolean isExpanded)2032 public void setPanelExpanded(boolean isExpanded) { 2033 mPanelExpanded = isExpanded; 2034 updateHideIconsForBouncer(false /* animate */); 2035 mStatusBarWindowManager.setPanelExpanded(isExpanded); 2036 mVisualStabilityManager.setPanelExpanded(isExpanded); 2037 if (isExpanded && getBarState() != StatusBarState.KEYGUARD) { 2038 if (DEBUG) { 2039 Log.v(TAG, "clearing notification effects from setExpandedHeight"); 2040 } 2041 clearNotificationEffects(); 2042 } 2043 2044 if (!isExpanded) { 2045 mRemoteInputManager.removeRemoteInputEntriesKeptUntilCollapsed(); 2046 } 2047 } 2048 getNotificationScrollLayout()2049 public NotificationStackScrollLayout getNotificationScrollLayout() { 2050 return mStackScroller; 2051 } 2052 isPulsing()2053 public boolean isPulsing() { 2054 return mDozeScrimController != null && mDozeScrimController.isPulsing(); 2055 } 2056 isLaunchTransitionFadingAway()2057 public boolean isLaunchTransitionFadingAway() { 2058 return mLaunchTransitionFadingAway; 2059 } 2060 hideStatusBarIconsWhenExpanded()2061 public boolean hideStatusBarIconsWhenExpanded() { 2062 return mNotificationPanel.hideStatusBarIconsWhenExpanded(); 2063 } 2064 2065 @Override onColorsChanged(ColorExtractor extractor, int which)2066 public void onColorsChanged(ColorExtractor extractor, int which) { 2067 updateTheme(); 2068 } 2069 isUsingDarkTheme()2070 public boolean isUsingDarkTheme() { 2071 OverlayInfo themeInfo = null; 2072 try { 2073 themeInfo = mOverlayManager.getOverlayInfo("com.android.systemui.theme.dark", 2074 mLockscreenUserManager.getCurrentUserId()); 2075 } catch (RemoteException e) { 2076 e.printStackTrace(); 2077 } 2078 return themeInfo != null && themeInfo.isEnabled(); 2079 } 2080 2081 @Nullable getAmbientIndicationContainer()2082 public View getAmbientIndicationContainer() { 2083 return mAmbientIndicationContainer; 2084 } 2085 setOccluded(boolean occluded)2086 public void setOccluded(boolean occluded) { 2087 mIsOccluded = occluded; 2088 mScrimController.setKeyguardOccluded(occluded); 2089 updateHideIconsForBouncer(false /* animate */); 2090 } 2091 hideStatusBarIconsForBouncer()2092 public boolean hideStatusBarIconsForBouncer() { 2093 return mHideIconsForBouncer || mWereIconsJustHidden; 2094 } 2095 2096 /** 2097 * Decides if the status bar (clock + notifications + signal cluster) should be visible 2098 * or not when showing the bouncer. 2099 * 2100 * We want to hide it when: 2101 * • User swipes up on the keyguard 2102 * • Locked activity that doesn't show a status bar requests the bouncer 2103 * 2104 * @param animate should the change of the icons be animated. 2105 */ updateHideIconsForBouncer(boolean animate)2106 private void updateHideIconsForBouncer(boolean animate) { 2107 boolean hideBecauseApp = mTopHidesStatusBar && mIsOccluded 2108 && (mStatusBarWindowHidden || mBouncerShowing); 2109 boolean hideBecauseKeyguard = !mPanelExpanded && !mIsOccluded && mBouncerShowing; 2110 boolean shouldHideIconsForBouncer = hideBecauseApp || hideBecauseKeyguard; 2111 if (mHideIconsForBouncer != shouldHideIconsForBouncer) { 2112 mHideIconsForBouncer = shouldHideIconsForBouncer; 2113 if (!shouldHideIconsForBouncer && mBouncerWasShowingWhenHidden) { 2114 // We're delaying the showing, since most of the time the fullscreen app will 2115 // hide the icons again and we don't want them to fade in and out immediately again. 2116 mWereIconsJustHidden = true; 2117 mHandler.postDelayed(() -> { 2118 mWereIconsJustHidden = false; 2119 recomputeDisableFlags(true); 2120 }, 500); 2121 } else { 2122 recomputeDisableFlags(animate); 2123 } 2124 } 2125 if (shouldHideIconsForBouncer) { 2126 mBouncerWasShowingWhenHidden = mBouncerShowing; 2127 } 2128 } 2129 onLaunchAnimationCancelled()2130 public void onLaunchAnimationCancelled() { 2131 if (!isCollapsing()) { 2132 onClosingFinished(); 2133 } 2134 } 2135 2136 /** 2137 * All changes to the status bar and notifications funnel through here and are batched. 2138 */ 2139 protected class H extends Handler { 2140 @Override handleMessage(Message m)2141 public void handleMessage(Message m) { 2142 switch (m.what) { 2143 case MSG_TOGGLE_KEYBOARD_SHORTCUTS_MENU: 2144 toggleKeyboardShortcuts(m.arg1); 2145 break; 2146 case MSG_DISMISS_KEYBOARD_SHORTCUTS_MENU: 2147 dismissKeyboardShortcuts(); 2148 break; 2149 // End old BaseStatusBar.H handling. 2150 case MSG_OPEN_NOTIFICATION_PANEL: 2151 animateExpandNotificationsPanel(); 2152 break; 2153 case MSG_OPEN_SETTINGS_PANEL: 2154 animateExpandSettingsPanel((String) m.obj); 2155 break; 2156 case MSG_CLOSE_PANELS: 2157 animateCollapsePanels(); 2158 break; 2159 case MSG_LAUNCH_TRANSITION_TIMEOUT: 2160 onLaunchTransitionTimeout(); 2161 break; 2162 } 2163 } 2164 } 2165 maybeEscalateHeadsUp()2166 public void maybeEscalateHeadsUp() { 2167 mHeadsUpManager.getAllEntries().forEach(entry -> { 2168 final StatusBarNotification sbn = entry.notification; 2169 final Notification notification = sbn.getNotification(); 2170 if (notification.fullScreenIntent != null) { 2171 if (DEBUG) { 2172 Log.d(TAG, "converting a heads up to fullScreen"); 2173 } 2174 try { 2175 EventLog.writeEvent(EventLogTags.SYSUI_HEADS_UP_ESCALATION, 2176 sbn.getKey()); 2177 notification.fullScreenIntent.send(); 2178 entry.notifyFullScreenIntentLaunched(); 2179 } catch (PendingIntent.CanceledException e) { 2180 } 2181 } 2182 }); 2183 mHeadsUpManager.releaseAllImmediately(); 2184 } 2185 2186 /** 2187 * Called for system navigation gestures. First action opens the panel, second opens 2188 * settings. Down action closes the entire panel. 2189 */ 2190 @Override handleSystemKey(int key)2191 public void handleSystemKey(int key) { 2192 if (SPEW) Log.d(TAG, "handleNavigationKey: " + key); 2193 if (!panelsEnabled() || !mKeyguardMonitor.isDeviceInteractive() 2194 || mKeyguardMonitor.isShowing() && !mKeyguardMonitor.isOccluded()) { 2195 return; 2196 } 2197 2198 // Panels are not available in setup 2199 if (!mUserSetup) return; 2200 2201 if (KeyEvent.KEYCODE_SYSTEM_NAVIGATION_UP == key) { 2202 mMetricsLogger.action(MetricsEvent.ACTION_SYSTEM_NAVIGATION_KEY_UP); 2203 mNotificationPanel.collapse(false /* delayed */, 1.0f /* speedUpFactor */); 2204 } else if (KeyEvent.KEYCODE_SYSTEM_NAVIGATION_DOWN == key) { 2205 mMetricsLogger.action(MetricsEvent.ACTION_SYSTEM_NAVIGATION_KEY_DOWN); 2206 if (mNotificationPanel.isFullyCollapsed()) { 2207 if (mVibrateOnOpening) { 2208 mVibratorHelper.vibrate(VibrationEffect.EFFECT_TICK); 2209 } 2210 mNotificationPanel.expand(true /* animate */); 2211 mMetricsLogger.count(NotificationPanelView.COUNTER_PANEL_OPEN, 1); 2212 } else if (!mNotificationPanel.isInSettings() && !mNotificationPanel.isExpanding()){ 2213 mNotificationPanel.flingSettings(0 /* velocity */, true /* expand */); 2214 mMetricsLogger.count(NotificationPanelView.COUNTER_PANEL_OPEN_QS, 1); 2215 } 2216 } 2217 2218 } 2219 2220 @Override showPinningEnterExitToast(boolean entering)2221 public void showPinningEnterExitToast(boolean entering) { 2222 if (entering) { 2223 mScreenPinningNotify.showPinningStartToast(); 2224 } else { 2225 mScreenPinningNotify.showPinningExitToast(); 2226 } 2227 } 2228 2229 @Override showPinningEscapeToast()2230 public void showPinningEscapeToast() { 2231 mScreenPinningNotify.showEscapeToast(getNavigationBarView() == null 2232 || getNavigationBarView().isRecentsButtonVisible()); 2233 } 2234 panelsEnabled()2235 boolean panelsEnabled() { 2236 return (mDisabled1 & StatusBarManager.DISABLE_EXPAND) == 0 2237 && (mDisabled2 & StatusBarManager.DISABLE2_NOTIFICATION_SHADE) == 0 2238 && !ONLY_CORE_APPS; 2239 } 2240 makeExpandedVisible(boolean force)2241 void makeExpandedVisible(boolean force) { 2242 if (SPEW) Log.d(TAG, "Make expanded visible: expanded visible=" + mExpandedVisible); 2243 if (!force && (mExpandedVisible || !panelsEnabled())) { 2244 return; 2245 } 2246 2247 mExpandedVisible = true; 2248 2249 // Expand the window to encompass the full screen in anticipation of the drag. 2250 // This is only possible to do atomically because the status bar is at the top of the screen! 2251 mStatusBarWindowManager.setPanelVisible(true); 2252 2253 visibilityChanged(true); 2254 recomputeDisableFlags(!force /* animate */); 2255 setInteracting(StatusBarManager.WINDOW_STATUS_BAR, true); 2256 } 2257 animateCollapsePanels()2258 public void animateCollapsePanels() { 2259 animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_NONE); 2260 } 2261 2262 private final Runnable mAnimateCollapsePanels = this::animateCollapsePanels; 2263 postAnimateCollapsePanels()2264 public void postAnimateCollapsePanels() { 2265 mHandler.post(mAnimateCollapsePanels); 2266 } 2267 postAnimateForceCollapsePanels()2268 public void postAnimateForceCollapsePanels() { 2269 mHandler.post(() -> { 2270 animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_NONE, true /* force */); 2271 }); 2272 } 2273 postAnimateOpenPanels()2274 public void postAnimateOpenPanels() { 2275 mHandler.sendEmptyMessage(MSG_OPEN_SETTINGS_PANEL); 2276 } 2277 2278 @Override togglePanel()2279 public void togglePanel() { 2280 if (mPanelExpanded) { 2281 animateCollapsePanels(); 2282 } else { 2283 animateExpandNotificationsPanel(); 2284 } 2285 } 2286 2287 @Override animateCollapsePanels(int flags)2288 public void animateCollapsePanels(int flags) { 2289 animateCollapsePanels(flags, false /* force */, false /* delayed */, 2290 1.0f /* speedUpFactor */); 2291 } 2292 animateCollapsePanels(int flags, boolean force)2293 public void animateCollapsePanels(int flags, boolean force) { 2294 animateCollapsePanels(flags, force, false /* delayed */, 1.0f /* speedUpFactor */); 2295 } 2296 animateCollapsePanels(int flags, boolean force, boolean delayed)2297 public void animateCollapsePanels(int flags, boolean force, boolean delayed) { 2298 animateCollapsePanels(flags, force, delayed, 1.0f /* speedUpFactor */); 2299 } 2300 animateCollapsePanels(int flags, boolean force, boolean delayed, float speedUpFactor)2301 public void animateCollapsePanels(int flags, boolean force, boolean delayed, 2302 float speedUpFactor) { 2303 if (!force && mState != StatusBarState.SHADE) { 2304 runPostCollapseRunnables(); 2305 return; 2306 } 2307 if (SPEW) { 2308 Log.d(TAG, "animateCollapse():" 2309 + " mExpandedVisible=" + mExpandedVisible 2310 + " flags=" + flags); 2311 } 2312 2313 if ((flags & CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL) == 0) { 2314 if (!mHandler.hasMessages(MSG_HIDE_RECENT_APPS)) { 2315 mHandler.removeMessages(MSG_HIDE_RECENT_APPS); 2316 mHandler.sendEmptyMessage(MSG_HIDE_RECENT_APPS); 2317 } 2318 } 2319 2320 // TODO(b/62444020): remove when this bug is fixed 2321 Log.v(TAG, "mStatusBarWindow: " + mStatusBarWindow + " canPanelBeCollapsed(): " 2322 + mNotificationPanel.canPanelBeCollapsed()); 2323 if (mStatusBarWindow != null && mNotificationPanel.canPanelBeCollapsed()) { 2324 // release focus immediately to kick off focus change transition 2325 mStatusBarWindowManager.setStatusBarFocusable(false); 2326 2327 mStatusBarWindow.cancelExpandHelper(); 2328 mStatusBarView.collapsePanel(true /* animate */, delayed, speedUpFactor); 2329 } 2330 } 2331 runPostCollapseRunnables()2332 private void runPostCollapseRunnables() { 2333 ArrayList<Runnable> clonedList = new ArrayList<>(mPostCollapseRunnables); 2334 mPostCollapseRunnables.clear(); 2335 int size = clonedList.size(); 2336 for (int i = 0; i < size; i++) { 2337 clonedList.get(i).run(); 2338 } 2339 mStatusBarKeyguardViewManager.readyForKeyguardDone(); 2340 } 2341 2342 @Override animateExpandNotificationsPanel()2343 public void animateExpandNotificationsPanel() { 2344 if (SPEW) Log.d(TAG, "animateExpand: mExpandedVisible=" + mExpandedVisible); 2345 if (!panelsEnabled()) { 2346 return ; 2347 } 2348 2349 mNotificationPanel.expandWithoutQs(); 2350 2351 if (false) postStartTracing(); 2352 } 2353 2354 @Override animateExpandSettingsPanel(String subPanel)2355 public void animateExpandSettingsPanel(String subPanel) { 2356 if (SPEW) Log.d(TAG, "animateExpand: mExpandedVisible=" + mExpandedVisible); 2357 if (!panelsEnabled()) { 2358 return; 2359 } 2360 2361 // Settings are not available in setup 2362 if (!mUserSetup) return; 2363 2364 2365 if (subPanel != null) { 2366 mQSPanel.openDetails(subPanel); 2367 } 2368 mNotificationPanel.expandWithQs(); 2369 2370 if (false) postStartTracing(); 2371 } 2372 animateCollapseQuickSettings()2373 public void animateCollapseQuickSettings() { 2374 if (mState == StatusBarState.SHADE) { 2375 mStatusBarView.collapsePanel(true, false /* delayed */, 1.0f /* speedUpFactor */); 2376 } 2377 } 2378 makeExpandedInvisible()2379 void makeExpandedInvisible() { 2380 if (SPEW) Log.d(TAG, "makeExpandedInvisible: mExpandedVisible=" + mExpandedVisible 2381 + " mExpandedVisible=" + mExpandedVisible); 2382 2383 if (!mExpandedVisible || mStatusBarWindow == null) { 2384 return; 2385 } 2386 2387 // Ensure the panel is fully collapsed (just in case; bug 6765842, 7260868) 2388 mStatusBarView.collapsePanel(/*animate=*/ false, false /* delayed*/, 2389 1.0f /* speedUpFactor */); 2390 2391 mNotificationPanel.closeQs(); 2392 2393 mExpandedVisible = false; 2394 visibilityChanged(false); 2395 2396 // Shrink the window to the size of the status bar only 2397 mStatusBarWindowManager.setPanelVisible(false); 2398 mStatusBarWindowManager.setForceStatusBarVisible(false); 2399 2400 // Close any guts that might be visible 2401 mGutsManager.closeAndSaveGuts(true /* removeLeavebehind */, true /* force */, 2402 true /* removeControls */, -1 /* x */, -1 /* y */, true /* resetMenu */); 2403 2404 runPostCollapseRunnables(); 2405 setInteracting(StatusBarManager.WINDOW_STATUS_BAR, false); 2406 showBouncerIfKeyguard(); 2407 recomputeDisableFlags(mNotificationPanel.hideStatusBarIconsWhenExpanded() /* animate */); 2408 2409 // Trimming will happen later if Keyguard is showing - doing it here might cause a jank in 2410 // the bouncer appear animation. 2411 if (!mStatusBarKeyguardViewManager.isShowing()) { 2412 WindowManagerGlobal.getInstance().trimMemory(ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN); 2413 } 2414 } 2415 interceptTouchEvent(MotionEvent event)2416 public boolean interceptTouchEvent(MotionEvent event) { 2417 if (DEBUG_GESTURES) { 2418 if (event.getActionMasked() != MotionEvent.ACTION_MOVE) { 2419 EventLog.writeEvent(EventLogTags.SYSUI_STATUSBAR_TOUCH, 2420 event.getActionMasked(), (int) event.getX(), (int) event.getY(), 2421 mDisabled1, mDisabled2); 2422 } 2423 2424 } 2425 2426 if (SPEW) { 2427 Log.d(TAG, "Touch: rawY=" + event.getRawY() + " event=" + event + " mDisabled1=" 2428 + mDisabled1 + " mDisabled2=" + mDisabled2); 2429 } else if (CHATTY) { 2430 if (event.getAction() != MotionEvent.ACTION_MOVE) { 2431 Log.d(TAG, String.format( 2432 "panel: %s at (%f, %f) mDisabled1=0x%08x mDisabled2=0x%08x", 2433 MotionEvent.actionToString(event.getAction()), 2434 event.getRawX(), event.getRawY(), mDisabled1, mDisabled2)); 2435 } 2436 } 2437 2438 if (DEBUG_GESTURES) { 2439 mGestureRec.add(event); 2440 } 2441 2442 if (mStatusBarWindowState == WINDOW_STATE_SHOWING) { 2443 final boolean upOrCancel = 2444 event.getAction() == MotionEvent.ACTION_UP || 2445 event.getAction() == MotionEvent.ACTION_CANCEL; 2446 if (upOrCancel && !mExpandedVisible) { 2447 setInteracting(StatusBarManager.WINDOW_STATUS_BAR, false); 2448 } else { 2449 setInteracting(StatusBarManager.WINDOW_STATUS_BAR, true); 2450 } 2451 } 2452 return false; 2453 } 2454 getGestureRecorder()2455 public GestureRecorder getGestureRecorder() { 2456 return mGestureRec; 2457 } 2458 getFingerprintUnlockController()2459 public FingerprintUnlockController getFingerprintUnlockController() { 2460 return mFingerprintUnlockController; 2461 } 2462 2463 @Override // CommandQueue setWindowState(int window, int state)2464 public void setWindowState(int window, int state) { 2465 boolean showing = state == WINDOW_STATE_SHOWING; 2466 if (mStatusBarWindow != null 2467 && window == StatusBarManager.WINDOW_STATUS_BAR 2468 && mStatusBarWindowState != state) { 2469 mStatusBarWindowState = state; 2470 if (DEBUG_WINDOW_STATE) Log.d(TAG, "Status bar " + windowStateToString(state)); 2471 if (!showing && mState == StatusBarState.SHADE) { 2472 mStatusBarView.collapsePanel(false /* animate */, false /* delayed */, 2473 1.0f /* speedUpFactor */); 2474 } 2475 if (mStatusBarView != null) { 2476 mStatusBarWindowHidden = state == WINDOW_STATE_HIDDEN; 2477 updateHideIconsForBouncer(false /* animate */); 2478 } 2479 } 2480 } 2481 2482 @Override // CommandQueue setSystemUiVisibility(int vis, int fullscreenStackVis, int dockedStackVis, int mask, Rect fullscreenStackBounds, Rect dockedStackBounds)2483 public void setSystemUiVisibility(int vis, int fullscreenStackVis, int dockedStackVis, 2484 int mask, Rect fullscreenStackBounds, Rect dockedStackBounds) { 2485 final int oldVal = mSystemUiVisibility; 2486 final int newVal = (oldVal&~mask) | (vis&mask); 2487 final int diff = newVal ^ oldVal; 2488 if (DEBUG) Log.d(TAG, String.format( 2489 "setSystemUiVisibility vis=%s mask=%s oldVal=%s newVal=%s diff=%s", 2490 Integer.toHexString(vis), Integer.toHexString(mask), 2491 Integer.toHexString(oldVal), Integer.toHexString(newVal), 2492 Integer.toHexString(diff))); 2493 boolean sbModeChanged = false; 2494 if (diff != 0) { 2495 mSystemUiVisibility = newVal; 2496 2497 // update low profile 2498 if ((diff & View.SYSTEM_UI_FLAG_LOW_PROFILE) != 0) { 2499 setAreThereNotifications(); 2500 } 2501 2502 // ready to unhide 2503 if ((vis & View.STATUS_BAR_UNHIDE) != 0) { 2504 mSystemUiVisibility &= ~View.STATUS_BAR_UNHIDE; 2505 mNoAnimationOnNextBarModeChange = true; 2506 } 2507 2508 // update status bar mode 2509 final int sbMode = computeStatusBarMode(oldVal, newVal); 2510 2511 sbModeChanged = sbMode != -1; 2512 if (sbModeChanged && sbMode != mStatusBarMode) { 2513 mStatusBarMode = sbMode; 2514 checkBarModes(); 2515 touchAutoHide(); 2516 } 2517 2518 if ((vis & View.NAVIGATION_BAR_UNHIDE) != 0) { 2519 mSystemUiVisibility &= ~View.NAVIGATION_BAR_UNHIDE; 2520 } 2521 2522 // send updated sysui visibility to window manager 2523 notifyUiVisibilityChanged(mSystemUiVisibility); 2524 } 2525 2526 mLightBarController.onSystemUiVisibilityChanged(fullscreenStackVis, dockedStackVis, 2527 mask, fullscreenStackBounds, dockedStackBounds, sbModeChanged, mStatusBarMode); 2528 } 2529 2530 @Override showWirelessChargingAnimation(int batteryLevel)2531 public void showWirelessChargingAnimation(int batteryLevel) { 2532 if (mDozing || mKeyguardManager.isKeyguardLocked()) { 2533 // on ambient or lockscreen, hide notification panel 2534 WirelessChargingAnimation.makeWirelessChargingAnimation(mContext, null, 2535 batteryLevel, new WirelessChargingAnimation.Callback() { 2536 @Override 2537 public void onAnimationStarting() { 2538 CrossFadeHelper.fadeOut(mNotificationPanel, 1); 2539 } 2540 2541 @Override 2542 public void onAnimationEnded() { 2543 CrossFadeHelper.fadeIn(mNotificationPanel); 2544 } 2545 }, mDozing).show(); 2546 } else { 2547 // workspace 2548 WirelessChargingAnimation.makeWirelessChargingAnimation(mContext, null, 2549 batteryLevel, null, false).show(); 2550 } 2551 } 2552 touchAutoHide()2553 void touchAutoHide() { 2554 // update transient bar autohide 2555 if (mStatusBarMode == MODE_SEMI_TRANSPARENT || (mNavigationBar != null 2556 && mNavigationBar.isSemiTransparent())) { 2557 scheduleAutohide(); 2558 } else { 2559 cancelAutohide(); 2560 } 2561 } 2562 computeStatusBarMode(int oldVal, int newVal)2563 protected int computeStatusBarMode(int oldVal, int newVal) { 2564 return computeBarMode(oldVal, newVal, View.STATUS_BAR_TRANSIENT, 2565 View.STATUS_BAR_TRANSLUCENT, View.STATUS_BAR_TRANSPARENT); 2566 } 2567 getStatusBarTransitions()2568 protected BarTransitions getStatusBarTransitions() { 2569 return mStatusBarView.getBarTransitions(); 2570 } 2571 computeBarMode(int oldVis, int newVis, int transientFlag, int translucentFlag, int transparentFlag)2572 protected int computeBarMode(int oldVis, int newVis, 2573 int transientFlag, int translucentFlag, int transparentFlag) { 2574 final int oldMode = barMode(oldVis, transientFlag, translucentFlag, transparentFlag); 2575 final int newMode = barMode(newVis, transientFlag, translucentFlag, transparentFlag); 2576 if (oldMode == newMode) { 2577 return -1; // no mode change 2578 } 2579 return newMode; 2580 } 2581 barMode(int vis, int transientFlag, int translucentFlag, int transparentFlag)2582 private int barMode(int vis, int transientFlag, int translucentFlag, int transparentFlag) { 2583 int lightsOutTransparent = View.SYSTEM_UI_FLAG_LOW_PROFILE | transparentFlag; 2584 return (vis & transientFlag) != 0 ? MODE_SEMI_TRANSPARENT 2585 : (vis & translucentFlag) != 0 ? MODE_TRANSLUCENT 2586 : (vis & lightsOutTransparent) == lightsOutTransparent ? MODE_LIGHTS_OUT_TRANSPARENT 2587 : (vis & transparentFlag) != 0 ? MODE_TRANSPARENT 2588 : (vis & View.SYSTEM_UI_FLAG_LOW_PROFILE) != 0 ? MODE_LIGHTS_OUT 2589 : MODE_OPAQUE; 2590 } 2591 checkBarModes()2592 void checkBarModes() { 2593 if (mDemoMode) return; 2594 if (mStatusBarView != null) checkBarMode(mStatusBarMode, mStatusBarWindowState, 2595 getStatusBarTransitions()); 2596 if (mNavigationBar != null) mNavigationBar.checkNavBarModes(); 2597 mNoAnimationOnNextBarModeChange = false; 2598 } 2599 2600 // Called by NavigationBarFragment setQsScrimEnabled(boolean scrimEnabled)2601 void setQsScrimEnabled(boolean scrimEnabled) { 2602 mNotificationPanel.setQsScrimEnabled(scrimEnabled); 2603 } 2604 checkBarMode(int mode, int windowState, BarTransitions transitions)2605 void checkBarMode(int mode, int windowState, BarTransitions transitions) { 2606 final boolean anim = !mNoAnimationOnNextBarModeChange && mDeviceInteractive 2607 && windowState != WINDOW_STATE_HIDDEN; 2608 transitions.transitionTo(mode, anim); 2609 } 2610 finishBarAnimations()2611 private void finishBarAnimations() { 2612 if (mStatusBarView != null) { 2613 mStatusBarView.getBarTransitions().finishAnimations(); 2614 } 2615 if (mNavigationBar != null) { 2616 mNavigationBar.finishBarAnimations(); 2617 } 2618 } 2619 2620 private final Runnable mCheckBarModes = this::checkBarModes; 2621 setInteracting(int barWindow, boolean interacting)2622 public void setInteracting(int barWindow, boolean interacting) { 2623 final boolean changing = ((mInteractingWindows & barWindow) != 0) != interacting; 2624 mInteractingWindows = interacting 2625 ? (mInteractingWindows | barWindow) 2626 : (mInteractingWindows & ~barWindow); 2627 if (mInteractingWindows != 0) { 2628 suspendAutohide(); 2629 } else { 2630 resumeSuspendedAutohide(); 2631 } 2632 // manually dismiss the volume panel when interacting with the nav bar 2633 if (changing && interacting && barWindow == StatusBarManager.WINDOW_NAVIGATION_BAR) { 2634 touchAutoDim(); 2635 dismissVolumeDialog(); 2636 } 2637 checkBarModes(); 2638 } 2639 dismissVolumeDialog()2640 private void dismissVolumeDialog() { 2641 if (mVolumeComponent != null) { 2642 mVolumeComponent.dismissNow(); 2643 } 2644 } 2645 resumeSuspendedAutohide()2646 private void resumeSuspendedAutohide() { 2647 if (mAutohideSuspended) { 2648 scheduleAutohide(); 2649 mHandler.postDelayed(mCheckBarModes, 500); // longer than home -> launcher 2650 } 2651 } 2652 suspendAutohide()2653 private void suspendAutohide() { 2654 mHandler.removeCallbacks(mAutohide); 2655 mHandler.removeCallbacks(mCheckBarModes); 2656 mAutohideSuspended = (mSystemUiVisibility & STATUS_OR_NAV_TRANSIENT) != 0; 2657 } 2658 cancelAutohide()2659 private void cancelAutohide() { 2660 mAutohideSuspended = false; 2661 mHandler.removeCallbacks(mAutohide); 2662 } 2663 scheduleAutohide()2664 private void scheduleAutohide() { 2665 cancelAutohide(); 2666 mHandler.postDelayed(mAutohide, AUTOHIDE_TIMEOUT_MS); 2667 } 2668 touchAutoDim()2669 public void touchAutoDim() { 2670 if (mNavigationBar != null) { 2671 mNavigationBar.getBarTransitions().setAutoDim(false); 2672 } 2673 mHandler.removeCallbacks(mAutoDim); 2674 if (mState != StatusBarState.KEYGUARD && mState != StatusBarState.SHADE_LOCKED) { 2675 mHandler.postDelayed(mAutoDim, AUTOHIDE_TIMEOUT_MS); 2676 } 2677 } 2678 checkUserAutohide(MotionEvent event)2679 void checkUserAutohide(MotionEvent event) { 2680 if ((mSystemUiVisibility & STATUS_OR_NAV_TRANSIENT) != 0 // a transient bar is revealed 2681 && event.getAction() == MotionEvent.ACTION_OUTSIDE // touch outside the source bar 2682 && event.getX() == 0 && event.getY() == 0 // a touch outside both bars 2683 && !mRemoteInputManager.getController() 2684 .isRemoteInputActive()) { // not due to typing in IME 2685 userAutohide(); 2686 } 2687 } 2688 userAutohide()2689 private void userAutohide() { 2690 cancelAutohide(); 2691 mHandler.postDelayed(mAutohide, 350); // longer than app gesture -> flag clear 2692 } 2693 areLightsOn()2694 private boolean areLightsOn() { 2695 return 0 == (mSystemUiVisibility & View.SYSTEM_UI_FLAG_LOW_PROFILE); 2696 } 2697 setLightsOn(boolean on)2698 public void setLightsOn(boolean on) { 2699 Log.v(TAG, "setLightsOn(" + on + ")"); 2700 if (on) { 2701 setSystemUiVisibility(0, 0, 0, View.SYSTEM_UI_FLAG_LOW_PROFILE, 2702 mLastFullscreenStackBounds, mLastDockedStackBounds); 2703 } else { 2704 setSystemUiVisibility(View.SYSTEM_UI_FLAG_LOW_PROFILE, 0, 0, 2705 View.SYSTEM_UI_FLAG_LOW_PROFILE, mLastFullscreenStackBounds, 2706 mLastDockedStackBounds); 2707 } 2708 } 2709 notifyUiVisibilityChanged(int vis)2710 private void notifyUiVisibilityChanged(int vis) { 2711 try { 2712 if (mLastDispatchedSystemUiVisibility != vis) { 2713 mWindowManagerService.statusBarVisibilityChanged(vis); 2714 mLastDispatchedSystemUiVisibility = vis; 2715 } 2716 } catch (RemoteException ex) { 2717 } 2718 } 2719 2720 @Override topAppWindowChanged(boolean showMenu)2721 public void topAppWindowChanged(boolean showMenu) { 2722 if (SPEW) { 2723 Log.d(TAG, (showMenu?"showing":"hiding") + " the MENU button"); 2724 } 2725 2726 // See above re: lights-out policy for legacy apps. 2727 if (showMenu) setLightsOn(true); 2728 } 2729 viewInfo(View v)2730 public static String viewInfo(View v) { 2731 return "[(" + v.getLeft() + "," + v.getTop() + ")(" + v.getRight() + "," + v.getBottom() 2732 + ") " + v.getWidth() + "x" + v.getHeight() + "]"; 2733 } 2734 2735 @Override dump(FileDescriptor fd, PrintWriter pw, String[] args)2736 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 2737 synchronized (mQueueLock) { 2738 pw.println("Current Status Bar state:"); 2739 pw.println(" mExpandedVisible=" + mExpandedVisible); 2740 pw.println(" mDisplayMetrics=" + mDisplayMetrics); 2741 pw.println(" mStackScroller: " + viewInfo(mStackScroller)); 2742 pw.println(" mStackScroller: " + viewInfo(mStackScroller) 2743 + " scroll " + mStackScroller.getScrollX() 2744 + "," + mStackScroller.getScrollY()); 2745 } 2746 2747 pw.print(" mInteractingWindows="); pw.println(mInteractingWindows); 2748 pw.print(" mStatusBarWindowState="); 2749 pw.println(windowStateToString(mStatusBarWindowState)); 2750 pw.print(" mStatusBarMode="); 2751 pw.println(BarTransitions.modeToString(mStatusBarMode)); 2752 pw.print(" mDozing="); pw.println(mDozing); 2753 pw.print(" mZenMode="); 2754 pw.println(Settings.Global.zenModeToString(Settings.Global.getInt( 2755 mContext.getContentResolver(), Settings.Global.ZEN_MODE, 2756 Settings.Global.ZEN_MODE_OFF))); 2757 2758 if (mStatusBarView != null) { 2759 dumpBarTransitions(pw, "mStatusBarView", mStatusBarView.getBarTransitions()); 2760 } 2761 pw.println(" StatusBarWindowView: "); 2762 if (mStatusBarWindow != null) { 2763 mStatusBarWindow.dump(fd, pw, args); 2764 } 2765 2766 pw.println(" mMediaManager: "); 2767 if (mMediaManager != null) { 2768 mMediaManager.dump(fd, pw, args); 2769 } 2770 2771 pw.println(" Panels: "); 2772 if (mNotificationPanel != null) { 2773 pw.println(" mNotificationPanel=" + 2774 mNotificationPanel + " params=" + mNotificationPanel.getLayoutParams().debug("")); 2775 pw.print (" "); 2776 mNotificationPanel.dump(fd, pw, args); 2777 } 2778 pw.println(" mStackScroller: "); 2779 if (mStackScroller != null) { 2780 pw.print (" "); 2781 mStackScroller.dump(fd, pw, args); 2782 } 2783 pw.println(" Theme:"); 2784 if (mOverlayManager == null) { 2785 pw.println(" overlay manager not initialized!"); 2786 } else { 2787 pw.println(" dark overlay on: " + isUsingDarkTheme()); 2788 } 2789 final boolean lightWpTheme = mContext.getThemeResId() == R.style.Theme_SystemUI_Light; 2790 pw.println(" light wallpaper theme: " + lightWpTheme); 2791 2792 DozeLog.dump(pw); 2793 2794 if (mFingerprintUnlockController != null) { 2795 mFingerprintUnlockController.dump(pw); 2796 } 2797 2798 if (mKeyguardIndicationController != null) { 2799 mKeyguardIndicationController.dump(fd, pw, args); 2800 } 2801 2802 if (mScrimController != null) { 2803 mScrimController.dump(fd, pw, args); 2804 } 2805 2806 if (mStatusBarKeyguardViewManager != null) { 2807 mStatusBarKeyguardViewManager.dump(pw); 2808 } 2809 2810 if (DUMPTRUCK) { 2811 synchronized (mEntryManager.getNotificationData()) { 2812 mEntryManager.getNotificationData().dump(pw, " "); 2813 } 2814 2815 if (false) { 2816 pw.println("see the logcat for a dump of the views we have created."); 2817 // must happen on ui thread 2818 mHandler.post(() -> { 2819 mStatusBarView.getLocationOnScreen(mAbsPos); 2820 Log.d(TAG, "mStatusBarView: ----- (" + mAbsPos[0] + "," + mAbsPos[1] + 2821 ") " + mStatusBarView.getWidth() + "x" + getStatusBarHeight()); 2822 mStatusBarView.debug(); 2823 }); 2824 } 2825 } 2826 2827 if (DEBUG_GESTURES) { 2828 pw.print(" status bar gestures: "); 2829 mGestureRec.dump(fd, pw, args); 2830 } 2831 2832 if (mHeadsUpManager != null) { 2833 mHeadsUpManager.dump(fd, pw, args); 2834 } else { 2835 pw.println(" mHeadsUpManager: null"); 2836 } 2837 if (mGroupManager != null) { 2838 mGroupManager.dump(fd, pw, args); 2839 } else { 2840 pw.println(" mGroupManager: null"); 2841 } 2842 2843 if (mLightBarController != null) { 2844 mLightBarController.dump(fd, pw, args); 2845 } 2846 2847 if (KeyguardUpdateMonitor.getInstance(mContext) != null) { 2848 KeyguardUpdateMonitor.getInstance(mContext).dump(fd, pw, args); 2849 } 2850 2851 FalsingManager.getInstance(mContext).dump(pw); 2852 FalsingLog.dump(pw); 2853 2854 pw.println("SharedPreferences:"); 2855 for (Map.Entry<String, ?> entry : Prefs.getAll(mContext).entrySet()) { 2856 pw.print(" "); pw.print(entry.getKey()); pw.print("="); pw.println(entry.getValue()); 2857 } 2858 } 2859 dumpBarTransitions(PrintWriter pw, String var, BarTransitions transitions)2860 static void dumpBarTransitions(PrintWriter pw, String var, BarTransitions transitions) { 2861 pw.print(" "); pw.print(var); pw.print(".BarTransitions.mMode="); 2862 pw.println(BarTransitions.modeToString(transitions.getMode())); 2863 } 2864 createAndAddWindows()2865 public void createAndAddWindows() { 2866 addStatusBarWindow(); 2867 } 2868 addStatusBarWindow()2869 private void addStatusBarWindow() { 2870 makeStatusBarView(); 2871 mStatusBarWindowManager = Dependency.get(StatusBarWindowManager.class); 2872 mRemoteInputManager.setUpWithPresenter(this, mEntryManager, this, 2873 new RemoteInputController.Delegate() { 2874 public void setRemoteInputActive(NotificationData.Entry entry, 2875 boolean remoteInputActive) { 2876 mHeadsUpManager.setRemoteInputActive(entry, remoteInputActive); 2877 entry.row.notifyHeightChanged(true /* needsAnimation */); 2878 updateFooter(); 2879 } 2880 public void lockScrollTo(NotificationData.Entry entry) { 2881 mStackScroller.lockScrollTo(entry.row); 2882 } 2883 public void requestDisallowLongPressAndDismiss() { 2884 mStackScroller.requestDisallowLongPress(); 2885 mStackScroller.requestDisallowDismiss(); 2886 } 2887 }); 2888 mRemoteInputManager.getController().addCallback(mStatusBarWindowManager); 2889 mStatusBarWindowManager.add(mStatusBarWindow, getStatusBarHeight()); 2890 } 2891 2892 // called by makeStatusbar and also by PhoneStatusBarView updateDisplaySize()2893 void updateDisplaySize() { 2894 mDisplay.getMetrics(mDisplayMetrics); 2895 mDisplay.getSize(mCurrentDisplaySize); 2896 if (DEBUG_GESTURES) { 2897 mGestureRec.tag("display", 2898 String.format("%dx%d", mDisplayMetrics.widthPixels, mDisplayMetrics.heightPixels)); 2899 } 2900 } 2901 getDisplayDensity()2902 float getDisplayDensity() { 2903 return mDisplayMetrics.density; 2904 } 2905 getDisplayWidth()2906 float getDisplayWidth() { 2907 return mDisplayMetrics.widthPixels; 2908 } 2909 getDisplayHeight()2910 float getDisplayHeight() { 2911 return mDisplayMetrics.heightPixels; 2912 } 2913 getRotation()2914 int getRotation() { 2915 return mDisplay.getRotation(); 2916 } 2917 startActivityDismissingKeyguard(final Intent intent, boolean onlyProvisioned, boolean dismissShade, int flags)2918 public void startActivityDismissingKeyguard(final Intent intent, boolean onlyProvisioned, 2919 boolean dismissShade, int flags) { 2920 startActivityDismissingKeyguard(intent, onlyProvisioned, dismissShade, 2921 false /* disallowEnterPictureInPictureWhileLaunching */, null /* callback */, 2922 flags); 2923 } 2924 startActivityDismissingKeyguard(final Intent intent, boolean onlyProvisioned, boolean dismissShade)2925 public void startActivityDismissingKeyguard(final Intent intent, boolean onlyProvisioned, 2926 boolean dismissShade) { 2927 startActivityDismissingKeyguard(intent, onlyProvisioned, dismissShade, 0); 2928 } 2929 startActivityDismissingKeyguard(final Intent intent, boolean onlyProvisioned, final boolean dismissShade, final boolean disallowEnterPictureInPictureWhileLaunching, final Callback callback, int flags)2930 public void startActivityDismissingKeyguard(final Intent intent, boolean onlyProvisioned, 2931 final boolean dismissShade, final boolean disallowEnterPictureInPictureWhileLaunching, 2932 final Callback callback, int flags) { 2933 if (onlyProvisioned && !isDeviceProvisioned()) return; 2934 2935 final boolean afterKeyguardGone = PreviewInflater.wouldLaunchResolverActivity( 2936 mContext, intent, mLockscreenUserManager.getCurrentUserId()); 2937 Runnable runnable = () -> { 2938 mAssistManager.hideAssist(); 2939 intent.setFlags( 2940 Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP); 2941 intent.addFlags(flags); 2942 int result = ActivityManager.START_CANCELED; 2943 ActivityOptions options = new ActivityOptions(getActivityOptions( 2944 null /* remoteAnimation */)); 2945 options.setDisallowEnterPictureInPictureWhileLaunching( 2946 disallowEnterPictureInPictureWhileLaunching); 2947 if (intent == KeyguardBottomAreaView.INSECURE_CAMERA_INTENT) { 2948 // Normally an activity will set it's requested rotation 2949 // animation on its window. However when launching an activity 2950 // causes the orientation to change this is too late. In these cases 2951 // the default animation is used. This doesn't look good for 2952 // the camera (as it rotates the camera contents out of sync 2953 // with physical reality). So, we ask the WindowManager to 2954 // force the crossfade animation if an orientation change 2955 // happens to occur during the launch. 2956 options.setRotationAnimationHint( 2957 WindowManager.LayoutParams.ROTATION_ANIMATION_SEAMLESS); 2958 } 2959 try { 2960 result = ActivityManager.getService().startActivityAsUser( 2961 null, mContext.getBasePackageName(), 2962 intent, 2963 intent.resolveTypeIfNeeded(mContext.getContentResolver()), 2964 null, null, 0, Intent.FLAG_ACTIVITY_NEW_TASK, null, 2965 options.toBundle(), UserHandle.CURRENT.getIdentifier()); 2966 } catch (RemoteException e) { 2967 Log.w(TAG, "Unable to start activity", e); 2968 } 2969 if (callback != null) { 2970 callback.onActivityStarted(result); 2971 } 2972 }; 2973 Runnable cancelRunnable = () -> { 2974 if (callback != null) { 2975 callback.onActivityStarted(ActivityManager.START_CANCELED); 2976 } 2977 }; 2978 executeRunnableDismissingKeyguard(runnable, cancelRunnable, dismissShade, 2979 afterKeyguardGone, true /* deferred */); 2980 } 2981 readyForKeyguardDone()2982 public void readyForKeyguardDone() { 2983 mStatusBarKeyguardViewManager.readyForKeyguardDone(); 2984 } 2985 executeRunnableDismissingKeyguard(final Runnable runnable, final Runnable cancelAction, final boolean dismissShade, final boolean afterKeyguardGone, final boolean deferred)2986 public void executeRunnableDismissingKeyguard(final Runnable runnable, 2987 final Runnable cancelAction, 2988 final boolean dismissShade, 2989 final boolean afterKeyguardGone, 2990 final boolean deferred) { 2991 dismissKeyguardThenExecute(() -> { 2992 if (runnable != null) { 2993 if (mStatusBarKeyguardViewManager.isShowing() 2994 && mStatusBarKeyguardViewManager.isOccluded()) { 2995 mStatusBarKeyguardViewManager.addAfterKeyguardGoneRunnable(runnable); 2996 } else { 2997 AsyncTask.execute(runnable); 2998 } 2999 } 3000 if (dismissShade) { 3001 if (mExpandedVisible) { 3002 animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL, true /* force */, 3003 true /* delayed*/); 3004 } else { 3005 3006 // Do it after DismissAction has been processed to conserve the needed ordering. 3007 mHandler.post(this::runPostCollapseRunnables); 3008 } 3009 } else if (isInLaunchTransition() && mNotificationPanel.isLaunchTransitionFinished()) { 3010 3011 // We are not dismissing the shade, but the launch transition is already finished, 3012 // so nobody will call readyForKeyguardDone anymore. Post it such that 3013 // keyguardDonePending gets called first. 3014 mHandler.post(mStatusBarKeyguardViewManager::readyForKeyguardDone); 3015 } 3016 return deferred; 3017 }, cancelAction, afterKeyguardGone); 3018 } 3019 3020 private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { 3021 @Override 3022 public void onReceive(Context context, Intent intent) { 3023 if (DEBUG) Log.v(TAG, "onReceive: " + intent); 3024 String action = intent.getAction(); 3025 if (Intent.ACTION_CLOSE_SYSTEM_DIALOGS.equals(action)) { 3026 KeyboardShortcuts.dismiss(); 3027 if (mRemoteInputManager.getController() != null) { 3028 mRemoteInputManager.getController().closeRemoteInputs(); 3029 } 3030 if (mLockscreenUserManager.isCurrentProfile(getSendingUserId())) { 3031 int flags = CommandQueue.FLAG_EXCLUDE_NONE; 3032 String reason = intent.getStringExtra("reason"); 3033 if (reason != null && reason.equals(SYSTEM_DIALOG_REASON_RECENT_APPS)) { 3034 flags |= CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL; 3035 } 3036 animateCollapsePanels(flags); 3037 } 3038 } 3039 else if (Intent.ACTION_SCREEN_OFF.equals(action)) { 3040 finishBarAnimations(); 3041 resetUserExpandedStates(); 3042 } 3043 else if (DevicePolicyManager.ACTION_SHOW_DEVICE_MONITORING_DIALOG.equals(action)) { 3044 mQSPanel.showDeviceMonitoringDialog(); 3045 } 3046 } 3047 }; 3048 3049 private final BroadcastReceiver mDemoReceiver = new BroadcastReceiver() { 3050 @Override 3051 public void onReceive(Context context, Intent intent) { 3052 if (DEBUG) Log.v(TAG, "onReceive: " + intent); 3053 String action = intent.getAction(); 3054 if (ACTION_DEMO.equals(action)) { 3055 Bundle bundle = intent.getExtras(); 3056 if (bundle != null) { 3057 String command = bundle.getString("command", "").trim().toLowerCase(); 3058 if (command.length() > 0) { 3059 try { 3060 dispatchDemoCommand(command, bundle); 3061 } catch (Throwable t) { 3062 Log.w(TAG, "Error running demo command, intent=" + intent, t); 3063 } 3064 } 3065 } 3066 } else if (ACTION_FAKE_ARTWORK.equals(action)) { 3067 if (DEBUG_MEDIA_FAKE_ARTWORK) { 3068 updateMediaMetaData(true, true); 3069 } 3070 } 3071 } 3072 }; 3073 resetUserExpandedStates()3074 public void resetUserExpandedStates() { 3075 ArrayList<Entry> activeNotifications = mEntryManager.getNotificationData() 3076 .getActiveNotifications(); 3077 final int notificationCount = activeNotifications.size(); 3078 for (int i = 0; i < notificationCount; i++) { 3079 NotificationData.Entry entry = activeNotifications.get(i); 3080 if (entry.row != null) { 3081 entry.row.resetUserExpansion(); 3082 } 3083 } 3084 } 3085 executeWhenUnlocked(OnDismissAction action)3086 private void executeWhenUnlocked(OnDismissAction action) { 3087 if (mStatusBarKeyguardViewManager.isShowing()) { 3088 mLeaveOpenOnKeyguardHide = true; 3089 } 3090 dismissKeyguardThenExecute(action, null /* cancelAction */, false /* afterKeyguardGone */); 3091 } 3092 dismissKeyguardThenExecute(OnDismissAction action, boolean afterKeyguardGone)3093 protected void dismissKeyguardThenExecute(OnDismissAction action, boolean afterKeyguardGone) { 3094 dismissKeyguardThenExecute(action, null /* cancelRunnable */, afterKeyguardGone); 3095 } 3096 dismissKeyguardThenExecute(OnDismissAction action, Runnable cancelAction, boolean afterKeyguardGone)3097 private void dismissKeyguardThenExecute(OnDismissAction action, Runnable cancelAction, 3098 boolean afterKeyguardGone) { 3099 if (mWakefulnessLifecycle.getWakefulness() == WAKEFULNESS_ASLEEP 3100 && mUnlockMethodCache.canSkipBouncer() 3101 && !mLeaveOpenOnKeyguardHide 3102 && isPulsing()) { 3103 // Reuse the fingerprint wake-and-unlock transition if we dismiss keyguard from a pulse. 3104 // TODO: Factor this transition out of FingerprintUnlockController. 3105 mFingerprintUnlockController.startWakeAndUnlock( 3106 FingerprintUnlockController.MODE_WAKE_AND_UNLOCK_PULSING); 3107 } 3108 if (mStatusBarKeyguardViewManager.isShowing()) { 3109 mStatusBarKeyguardViewManager.dismissWithAction(action, cancelAction, 3110 afterKeyguardGone); 3111 } else { 3112 action.onDismiss(); 3113 } 3114 } 3115 3116 // SystemUIService notifies SystemBars of configuration changes, which then calls down here 3117 @Override onConfigChanged(Configuration newConfig)3118 public void onConfigChanged(Configuration newConfig) { 3119 updateResources(); 3120 updateDisplaySize(); // populates mDisplayMetrics 3121 3122 if (DEBUG) { 3123 Log.v(TAG, "configuration changed: " + mContext.getResources().getConfiguration()); 3124 } 3125 3126 mViewHierarchyManager.updateRowStates(); 3127 mScreenPinningRequest.onConfigurationChanged(); 3128 } 3129 3130 @Override onUserSwitched(int newUserId)3131 public void onUserSwitched(int newUserId) { 3132 // Begin old BaseStatusBar.userSwitched 3133 setHeadsUpUser(newUserId); 3134 // End old BaseStatusBar.userSwitched 3135 if (MULTIUSER_DEBUG) mNotificationPanelDebugText.setText("USER " + newUserId); 3136 animateCollapsePanels(); 3137 updatePublicMode(); 3138 mEntryManager.getNotificationData().filterAndSort(); 3139 if (mReinflateNotificationsOnUserSwitched) { 3140 mEntryManager.updateNotificationsOnDensityOrFontScaleChanged(); 3141 mReinflateNotificationsOnUserSwitched = false; 3142 } 3143 updateNotificationViews(); 3144 mMediaManager.clearCurrentMediaNotification(); 3145 setLockscreenUser(newUserId); 3146 } 3147 3148 @Override getNotificationLockscreenUserManager()3149 public NotificationLockscreenUserManager getNotificationLockscreenUserManager() { 3150 return mLockscreenUserManager; 3151 } 3152 3153 @Override onBindRow(Entry entry, PackageManager pmUser, StatusBarNotification sbn, ExpandableNotificationRow row)3154 public void onBindRow(Entry entry, PackageManager pmUser, 3155 StatusBarNotification sbn, ExpandableNotificationRow row) { 3156 row.setAboveShelfChangedListener(mAboveShelfObserver); 3157 row.setSecureStateProvider(this::isKeyguardCurrentlySecure); 3158 } 3159 setLockscreenUser(int newUserId)3160 protected void setLockscreenUser(int newUserId) { 3161 mLockscreenWallpaper.setCurrentUser(newUserId); 3162 mScrimController.setCurrentUser(newUserId); 3163 updateMediaMetaData(true, false); 3164 } 3165 3166 /** 3167 * Reload some of our resources when the configuration changes. 3168 * 3169 * We don't reload everything when the configuration changes -- we probably 3170 * should, but getting that smooth is tough. Someday we'll fix that. In the 3171 * meantime, just update the things that we know change. 3172 */ updateResources()3173 void updateResources() { 3174 // Update the quick setting tiles 3175 if (mQSPanel != null) { 3176 mQSPanel.updateResources(); 3177 } 3178 3179 loadDimens(); 3180 3181 if (mStatusBarView != null) { 3182 mStatusBarView.updateResources(); 3183 } 3184 if (mNotificationPanel != null) { 3185 mNotificationPanel.updateResources(); 3186 } 3187 if (mBrightnessMirrorController != null) { 3188 mBrightnessMirrorController.updateResources(); 3189 } 3190 } 3191 loadDimens()3192 protected void loadDimens() { 3193 final Resources res = mContext.getResources(); 3194 3195 int oldBarHeight = mNaturalBarHeight; 3196 mNaturalBarHeight = res.getDimensionPixelSize( 3197 com.android.internal.R.dimen.status_bar_height); 3198 if (mStatusBarWindowManager != null && mNaturalBarHeight != oldBarHeight) { 3199 mStatusBarWindowManager.setBarHeight(mNaturalBarHeight); 3200 } 3201 mMaxAllowedKeyguardNotifications = res.getInteger( 3202 R.integer.keyguard_max_notification_count); 3203 3204 if (DEBUG) Log.v(TAG, "defineSlots"); 3205 } 3206 3207 // Visibility reporting 3208 handleVisibleToUserChanged(boolean visibleToUser)3209 protected void handleVisibleToUserChanged(boolean visibleToUser) { 3210 if (visibleToUser) { 3211 handleVisibleToUserChangedImpl(visibleToUser); 3212 mNotificationLogger.startNotificationLogging(); 3213 } else { 3214 mNotificationLogger.stopNotificationLogging(); 3215 handleVisibleToUserChangedImpl(visibleToUser); 3216 } 3217 } 3218 handlePeekToExpandTransistion()3219 void handlePeekToExpandTransistion() { 3220 try { 3221 // consider the transition from peek to expanded to be a panel open, 3222 // but not one that clears notification effects. 3223 int notificationLoad = mEntryManager.getNotificationData() 3224 .getActiveNotifications().size(); 3225 mBarService.onPanelRevealed(false, notificationLoad); 3226 } catch (RemoteException ex) { 3227 // Won't fail unless the world has ended. 3228 } 3229 } 3230 3231 /** 3232 * The LEDs are turned off when the notification panel is shown, even just a little bit. 3233 * See also StatusBar.setPanelExpanded for another place where we attempt to do this. 3234 */ handleVisibleToUserChangedImpl(boolean visibleToUser)3235 private void handleVisibleToUserChangedImpl(boolean visibleToUser) { 3236 if (visibleToUser) { 3237 boolean pinnedHeadsUp = mHeadsUpManager.hasPinnedHeadsUp(); 3238 boolean clearNotificationEffects = 3239 !isPresenterFullyCollapsed() && 3240 (mState == StatusBarState.SHADE 3241 || mState == StatusBarState.SHADE_LOCKED); 3242 int notificationLoad = mEntryManager.getNotificationData().getActiveNotifications() 3243 .size(); 3244 if (pinnedHeadsUp && isPresenterFullyCollapsed()) { 3245 notificationLoad = 1; 3246 } 3247 final int finalNotificationLoad = notificationLoad; 3248 mUiOffloadThread.submit(() -> { 3249 try { 3250 mBarService.onPanelRevealed(clearNotificationEffects, 3251 finalNotificationLoad); 3252 } catch (RemoteException ex) { 3253 // Won't fail unless the world has ended. 3254 } 3255 }); 3256 } else { 3257 mUiOffloadThread.submit(() -> { 3258 try { 3259 mBarService.onPanelHidden(); 3260 } catch (RemoteException ex) { 3261 // Won't fail unless the world has ended. 3262 } 3263 }); 3264 } 3265 3266 } 3267 logStateToEventlog()3268 private void logStateToEventlog() { 3269 boolean isShowing = mStatusBarKeyguardViewManager.isShowing(); 3270 boolean isOccluded = mStatusBarKeyguardViewManager.isOccluded(); 3271 boolean isBouncerShowing = mStatusBarKeyguardViewManager.isBouncerShowing(); 3272 boolean isSecure = mUnlockMethodCache.isMethodSecure(); 3273 boolean canSkipBouncer = mUnlockMethodCache.canSkipBouncer(); 3274 int stateFingerprint = getLoggingFingerprint(mState, 3275 isShowing, 3276 isOccluded, 3277 isBouncerShowing, 3278 isSecure, 3279 canSkipBouncer); 3280 if (stateFingerprint != mLastLoggedStateFingerprint) { 3281 if (mStatusBarStateLog == null) { 3282 mStatusBarStateLog = new LogMaker(MetricsEvent.VIEW_UNKNOWN); 3283 } 3284 mMetricsLogger.write(mStatusBarStateLog 3285 .setCategory(isBouncerShowing ? MetricsEvent.BOUNCER : MetricsEvent.LOCKSCREEN) 3286 .setType(isShowing ? MetricsEvent.TYPE_OPEN : MetricsEvent.TYPE_CLOSE) 3287 .setSubtype(isSecure ? 1 : 0)); 3288 EventLogTags.writeSysuiStatusBarState(mState, 3289 isShowing ? 1 : 0, 3290 isOccluded ? 1 : 0, 3291 isBouncerShowing ? 1 : 0, 3292 isSecure ? 1 : 0, 3293 canSkipBouncer ? 1 : 0); 3294 mLastLoggedStateFingerprint = stateFingerprint; 3295 } 3296 } 3297 3298 /** 3299 * Returns a fingerprint of fields logged to eventlog 3300 */ getLoggingFingerprint(int statusBarState, boolean keyguardShowing, boolean keyguardOccluded, boolean bouncerShowing, boolean secure, boolean currentlyInsecure)3301 private static int getLoggingFingerprint(int statusBarState, boolean keyguardShowing, 3302 boolean keyguardOccluded, boolean bouncerShowing, boolean secure, 3303 boolean currentlyInsecure) { 3304 // Reserve 8 bits for statusBarState. We'll never go higher than 3305 // that, right? Riiiight. 3306 return (statusBarState & 0xFF) 3307 | ((keyguardShowing ? 1 : 0) << 8) 3308 | ((keyguardOccluded ? 1 : 0) << 9) 3309 | ((bouncerShowing ? 1 : 0) << 10) 3310 | ((secure ? 1 : 0) << 11) 3311 | ((currentlyInsecure ? 1 : 0) << 12); 3312 } 3313 3314 // 3315 // tracing 3316 // 3317 postStartTracing()3318 void postStartTracing() { 3319 mHandler.postDelayed(mStartTracing, 3000); 3320 } 3321 vibrate()3322 void vibrate() { 3323 android.os.Vibrator vib = (android.os.Vibrator)mContext.getSystemService( 3324 Context.VIBRATOR_SERVICE); 3325 vib.vibrate(250, VIBRATION_ATTRIBUTES); 3326 } 3327 3328 final Runnable mStartTracing = new Runnable() { 3329 @Override 3330 public void run() { 3331 vibrate(); 3332 SystemClock.sleep(250); 3333 Log.d(TAG, "startTracing"); 3334 android.os.Debug.startMethodTracing("/data/statusbar-traces/trace"); 3335 mHandler.postDelayed(mStopTracing, 10000); 3336 } 3337 }; 3338 3339 final Runnable mStopTracing = () -> { 3340 android.os.Debug.stopMethodTracing(); 3341 Log.d(TAG, "stopTracing"); 3342 vibrate(); 3343 }; 3344 3345 @Override postQSRunnableDismissingKeyguard(final Runnable runnable)3346 public void postQSRunnableDismissingKeyguard(final Runnable runnable) { 3347 mHandler.post(() -> { 3348 mLeaveOpenOnKeyguardHide = true; 3349 executeRunnableDismissingKeyguard(() -> mHandler.post(runnable), null, false, false, 3350 false); 3351 }); 3352 } 3353 3354 @Override postStartActivityDismissingKeyguard(final PendingIntent intent)3355 public void postStartActivityDismissingKeyguard(final PendingIntent intent) { 3356 mHandler.post(() -> startPendingIntentDismissingKeyguard(intent)); 3357 } 3358 3359 @Override postStartActivityDismissingKeyguard(final Intent intent, int delay)3360 public void postStartActivityDismissingKeyguard(final Intent intent, int delay) { 3361 mHandler.postDelayed(() -> 3362 handleStartActivityDismissingKeyguard(intent, true /*onlyProvisioned*/), delay); 3363 } 3364 handleStartActivityDismissingKeyguard(Intent intent, boolean onlyProvisioned)3365 private void handleStartActivityDismissingKeyguard(Intent intent, boolean onlyProvisioned) { 3366 startActivityDismissingKeyguard(intent, onlyProvisioned, true /* dismissShade */); 3367 } 3368 destroy()3369 public void destroy() { 3370 // Begin old BaseStatusBar.destroy(). 3371 mContext.unregisterReceiver(mBannerActionBroadcastReceiver); 3372 mLockscreenUserManager.destroy(); 3373 try { 3374 mNotificationListener.unregisterAsSystemService(); 3375 } catch (RemoteException e) { 3376 // Ignore. 3377 } 3378 mEntryManager.destroy(); 3379 // End old BaseStatusBar.destroy(). 3380 if (mStatusBarWindow != null) { 3381 mWindowManager.removeViewImmediate(mStatusBarWindow); 3382 mStatusBarWindow = null; 3383 } 3384 if (mNavigationBarView != null) { 3385 mWindowManager.removeViewImmediate(mNavigationBarView); 3386 mNavigationBarView = null; 3387 } 3388 mContext.unregisterReceiver(mBroadcastReceiver); 3389 mContext.unregisterReceiver(mDemoReceiver); 3390 mAssistManager.destroy(); 3391 3392 if (mQSPanel != null && mQSPanel.getHost() != null) { 3393 mQSPanel.getHost().destroy(); 3394 } 3395 Dependency.get(ActivityStarterDelegate.class).setActivityStarterImpl(null); 3396 mDeviceProvisionedController.removeCallback(mUserSetupObserver); 3397 Dependency.get(ConfigurationController.class).removeCallback(this); 3398 mZenController.removeCallback(this); 3399 mAppOpsListener.destroy(); 3400 } 3401 3402 private boolean mDemoModeAllowed; 3403 private boolean mDemoMode; 3404 3405 @Override dispatchDemoCommand(String command, Bundle args)3406 public void dispatchDemoCommand(String command, Bundle args) { 3407 if (!mDemoModeAllowed) { 3408 mDemoModeAllowed = Settings.Global.getInt(mContext.getContentResolver(), 3409 DEMO_MODE_ALLOWED, 0) != 0; 3410 } 3411 if (!mDemoModeAllowed) return; 3412 if (command.equals(COMMAND_ENTER)) { 3413 mDemoMode = true; 3414 } else if (command.equals(COMMAND_EXIT)) { 3415 mDemoMode = false; 3416 checkBarModes(); 3417 } else if (!mDemoMode) { 3418 // automatically enter demo mode on first demo command 3419 dispatchDemoCommand(COMMAND_ENTER, new Bundle()); 3420 } 3421 boolean modeChange = command.equals(COMMAND_ENTER) || command.equals(COMMAND_EXIT); 3422 if ((modeChange || command.equals(COMMAND_VOLUME)) && mVolumeComponent != null) { 3423 mVolumeComponent.dispatchDemoCommand(command, args); 3424 } 3425 if (modeChange || command.equals(COMMAND_CLOCK)) { 3426 dispatchDemoCommandToView(command, args, R.id.clock); 3427 } 3428 if (modeChange || command.equals(COMMAND_BATTERY)) { 3429 mBatteryController.dispatchDemoCommand(command, args); 3430 } 3431 if (modeChange || command.equals(COMMAND_STATUS)) { 3432 ((StatusBarIconControllerImpl) mIconController).dispatchDemoCommand(command, args); 3433 } 3434 if (mNetworkController != null && (modeChange || command.equals(COMMAND_NETWORK))) { 3435 mNetworkController.dispatchDemoCommand(command, args); 3436 } 3437 if (modeChange || command.equals(COMMAND_NOTIFICATIONS)) { 3438 View notifications = mStatusBarView == null ? null 3439 : mStatusBarView.findViewById(R.id.notification_icon_area); 3440 if (notifications != null) { 3441 String visible = args.getString("visible"); 3442 int vis = mDemoMode && "false".equals(visible) ? View.INVISIBLE : View.VISIBLE; 3443 notifications.setVisibility(vis); 3444 } 3445 } 3446 if (command.equals(COMMAND_BARS)) { 3447 String mode = args.getString("mode"); 3448 int barMode = "opaque".equals(mode) ? MODE_OPAQUE : 3449 "translucent".equals(mode) ? MODE_TRANSLUCENT : 3450 "semi-transparent".equals(mode) ? MODE_SEMI_TRANSPARENT : 3451 "transparent".equals(mode) ? MODE_TRANSPARENT : 3452 "warning".equals(mode) ? MODE_WARNING : 3453 -1; 3454 if (barMode != -1) { 3455 boolean animate = true; 3456 if (mStatusBarView != null) { 3457 mStatusBarView.getBarTransitions().transitionTo(barMode, animate); 3458 } 3459 if (mNavigationBar != null) { 3460 mNavigationBar.getBarTransitions().transitionTo(barMode, animate); 3461 } 3462 } 3463 } 3464 if (modeChange || command.equals(COMMAND_OPERATOR)) { 3465 dispatchDemoCommandToView(command, args, R.id.operator_name); 3466 } 3467 } 3468 dispatchDemoCommandToView(String command, Bundle args, int id)3469 private void dispatchDemoCommandToView(String command, Bundle args, int id) { 3470 if (mStatusBarView == null) return; 3471 View v = mStatusBarView.findViewById(id); 3472 if (v instanceof DemoMode) { 3473 ((DemoMode)v).dispatchDemoCommand(command, args); 3474 } 3475 } 3476 3477 /** 3478 * @return The {@link StatusBarState} the status bar is in. 3479 */ getBarState()3480 public int getBarState() { 3481 return mState; 3482 } 3483 3484 @Override isPresenterFullyCollapsed()3485 public boolean isPresenterFullyCollapsed() { 3486 return mNotificationPanel.isFullyCollapsed(); 3487 } 3488 showKeyguard()3489 public void showKeyguard() { 3490 mKeyguardRequested = true; 3491 mLeaveOpenOnKeyguardHide = false; 3492 mPendingRemoteInputView = null; 3493 updateIsKeyguard(); 3494 mAssistManager.onLockscreenShown(); 3495 } 3496 hideKeyguard()3497 public boolean hideKeyguard() { 3498 mKeyguardRequested = false; 3499 return updateIsKeyguard(); 3500 } 3501 3502 /** 3503 * @return True if StatusBar state is FULLSCREEN_USER_SWITCHER. 3504 */ isFullScreenUserSwitcherState()3505 public boolean isFullScreenUserSwitcherState() { 3506 return mState == StatusBarState.FULLSCREEN_USER_SWITCHER; 3507 } 3508 updateIsKeyguard()3509 private boolean updateIsKeyguard() { 3510 boolean wakeAndUnlocking = mFingerprintUnlockController.getMode() 3511 == FingerprintUnlockController.MODE_WAKE_AND_UNLOCK; 3512 3513 // For dozing, keyguard needs to be shown whenever the device is non-interactive. Otherwise 3514 // there's no surface we can show to the user. Note that the device goes fully interactive 3515 // late in the transition, so we also allow the device to start dozing once the screen has 3516 // turned off fully. 3517 boolean keyguardForDozing = mDozingRequested && 3518 (!mDeviceInteractive || isGoingToSleep() && (isScreenFullyOff() || mIsKeyguard)); 3519 boolean shouldBeKeyguard = (mKeyguardRequested || keyguardForDozing) && !wakeAndUnlocking; 3520 if (keyguardForDozing) { 3521 updatePanelExpansionForKeyguard(); 3522 } 3523 if (shouldBeKeyguard) { 3524 if (isGoingToSleep() 3525 && mScreenLifecycle.getScreenState() == ScreenLifecycle.SCREEN_TURNING_OFF) { 3526 // Delay showing the keyguard until screen turned off. 3527 } else { 3528 showKeyguardImpl(); 3529 } 3530 } else { 3531 return hideKeyguardImpl(); 3532 } 3533 return false; 3534 } 3535 showKeyguardImpl()3536 public void showKeyguardImpl() { 3537 mIsKeyguard = true; 3538 if (mLaunchTransitionFadingAway) { 3539 mNotificationPanel.animate().cancel(); 3540 onLaunchTransitionFadingEnded(); 3541 } 3542 mHandler.removeMessages(MSG_LAUNCH_TRANSITION_TIMEOUT); 3543 if (mUserSwitcherController != null && mUserSwitcherController.useFullscreenUserSwitcher()) { 3544 setBarState(StatusBarState.FULLSCREEN_USER_SWITCHER); 3545 } else { 3546 setBarState(StatusBarState.KEYGUARD); 3547 } 3548 updateKeyguardState(false /* goingToFullShade */, false /* fromShadeLocked */); 3549 updatePanelExpansionForKeyguard(); 3550 if (mDraggedDownRow != null) { 3551 mDraggedDownRow.setUserLocked(false); 3552 mDraggedDownRow.notifyHeightChanged(false /* needsAnimation */); 3553 mDraggedDownRow = null; 3554 } 3555 } 3556 updatePanelExpansionForKeyguard()3557 private void updatePanelExpansionForKeyguard() { 3558 if (mState == StatusBarState.KEYGUARD && mFingerprintUnlockController.getMode() 3559 != FingerprintUnlockController.MODE_WAKE_AND_UNLOCK) { 3560 instantExpandNotificationsPanel(); 3561 } else if (mState == StatusBarState.FULLSCREEN_USER_SWITCHER) { 3562 instantCollapseNotificationPanel(); 3563 } 3564 } 3565 onLaunchTransitionFadingEnded()3566 private void onLaunchTransitionFadingEnded() { 3567 mNotificationPanel.setAlpha(1.0f); 3568 mNotificationPanel.onAffordanceLaunchEnded(); 3569 releaseGestureWakeLock(); 3570 runLaunchTransitionEndRunnable(); 3571 mLaunchTransitionFadingAway = false; 3572 updateMediaMetaData(true /* metaDataChanged */, true); 3573 } 3574 isCollapsing()3575 public boolean isCollapsing() { 3576 return mNotificationPanel.isCollapsing() || mActivityLaunchAnimator.isAnimationPending(); 3577 } 3578 addPostCollapseAction(Runnable r)3579 public void addPostCollapseAction(Runnable r) { 3580 mPostCollapseRunnables.add(r); 3581 } 3582 isInLaunchTransition()3583 public boolean isInLaunchTransition() { 3584 return mNotificationPanel.isLaunchTransitionRunning() 3585 || mNotificationPanel.isLaunchTransitionFinished(); 3586 } 3587 3588 /** 3589 * Fades the content of the keyguard away after the launch transition is done. 3590 * 3591 * @param beforeFading the runnable to be run when the circle is fully expanded and the fading 3592 * starts 3593 * @param endRunnable the runnable to be run when the transition is done 3594 */ fadeKeyguardAfterLaunchTransition(final Runnable beforeFading, Runnable endRunnable)3595 public void fadeKeyguardAfterLaunchTransition(final Runnable beforeFading, 3596 Runnable endRunnable) { 3597 mHandler.removeMessages(MSG_LAUNCH_TRANSITION_TIMEOUT); 3598 mLaunchTransitionEndRunnable = endRunnable; 3599 Runnable hideRunnable = () -> { 3600 mLaunchTransitionFadingAway = true; 3601 if (beforeFading != null) { 3602 beforeFading.run(); 3603 } 3604 updateScrimController(); 3605 updateMediaMetaData(false, true); 3606 mNotificationPanel.setAlpha(1); 3607 mStackScroller.setParentNotFullyVisible(true); 3608 mNotificationPanel.animate() 3609 .alpha(0) 3610 .setStartDelay(FADE_KEYGUARD_START_DELAY) 3611 .setDuration(FADE_KEYGUARD_DURATION) 3612 .withLayer() 3613 .withEndAction(this::onLaunchTransitionFadingEnded); 3614 mCommandQueue.appTransitionStarting(SystemClock.uptimeMillis(), 3615 LightBarTransitionsController.DEFAULT_TINT_ANIMATION_DURATION, true); 3616 }; 3617 if (mNotificationPanel.isLaunchTransitionRunning()) { 3618 mNotificationPanel.setLaunchTransitionEndRunnable(hideRunnable); 3619 } else { 3620 hideRunnable.run(); 3621 } 3622 } 3623 3624 /** 3625 * Fades the content of the Keyguard while we are dozing and makes it invisible when finished 3626 * fading. 3627 */ fadeKeyguardWhilePulsing()3628 public void fadeKeyguardWhilePulsing() { 3629 mNotificationPanel.notifyStartFading(); 3630 mNotificationPanel.animate() 3631 .alpha(0f) 3632 .setStartDelay(0) 3633 .setDuration(FADE_KEYGUARD_DURATION_PULSING) 3634 .setInterpolator(Interpolators.ALPHA_OUT) 3635 .withEndAction(()-> { 3636 hideKeyguard(); 3637 mStatusBarKeyguardViewManager.onKeyguardFadedAway(); 3638 }).start(); 3639 } 3640 3641 /** 3642 * Plays the animation when an activity that was occluding Keyguard goes away. 3643 */ animateKeyguardUnoccluding()3644 public void animateKeyguardUnoccluding() { 3645 mNotificationPanel.setExpandedFraction(0f); 3646 animateExpandNotificationsPanel(); 3647 } 3648 3649 /** 3650 * Starts the timeout when we try to start the affordances on Keyguard. We usually rely that 3651 * Keyguard goes away via fadeKeyguardAfterLaunchTransition, however, that might not happen 3652 * because the launched app crashed or something else went wrong. 3653 */ startLaunchTransitionTimeout()3654 public void startLaunchTransitionTimeout() { 3655 mHandler.sendEmptyMessageDelayed(MSG_LAUNCH_TRANSITION_TIMEOUT, 3656 LAUNCH_TRANSITION_TIMEOUT_MS); 3657 } 3658 onLaunchTransitionTimeout()3659 private void onLaunchTransitionTimeout() { 3660 Log.w(TAG, "Launch transition: Timeout!"); 3661 mNotificationPanel.onAffordanceLaunchEnded(); 3662 releaseGestureWakeLock(); 3663 mNotificationPanel.resetViews(); 3664 } 3665 runLaunchTransitionEndRunnable()3666 private void runLaunchTransitionEndRunnable() { 3667 if (mLaunchTransitionEndRunnable != null) { 3668 Runnable r = mLaunchTransitionEndRunnable; 3669 3670 // mLaunchTransitionEndRunnable might call showKeyguard, which would execute it again, 3671 // which would lead to infinite recursion. Protect against it. 3672 mLaunchTransitionEndRunnable = null; 3673 r.run(); 3674 } 3675 } 3676 3677 /** 3678 * @return true if we would like to stay in the shade, false if it should go away entirely 3679 */ hideKeyguardImpl()3680 public boolean hideKeyguardImpl() { 3681 mIsKeyguard = false; 3682 Trace.beginSection("StatusBar#hideKeyguard"); 3683 boolean staying = mLeaveOpenOnKeyguardHide; 3684 setBarState(StatusBarState.SHADE); 3685 View viewToClick = null; 3686 if (mLeaveOpenOnKeyguardHide) { 3687 if (!mKeyguardRequested) { 3688 mLeaveOpenOnKeyguardHide = false; 3689 } 3690 long delay = calculateGoingToFullShadeDelay(); 3691 mNotificationPanel.animateToFullShade(delay); 3692 if (mDraggedDownRow != null) { 3693 mDraggedDownRow.setUserLocked(false); 3694 mDraggedDownRow = null; 3695 } 3696 if (!mKeyguardRequested) { 3697 viewToClick = mPendingRemoteInputView; 3698 mPendingRemoteInputView = null; 3699 } 3700 3701 // Disable layout transitions in navbar for this transition because the load is just 3702 // too heavy for the CPU and GPU on any device. 3703 if (mNavigationBar != null) { 3704 mNavigationBar.disableAnimationsDuringHide(delay); 3705 } 3706 } else if (!mNotificationPanel.isCollapsing()) { 3707 instantCollapseNotificationPanel(); 3708 } 3709 updateKeyguardState(staying, false /* fromShadeLocked */); 3710 3711 if (viewToClick != null && viewToClick.isAttachedToWindow()) { 3712 viewToClick.callOnClick(); 3713 } 3714 3715 // Keyguard state has changed, but QS is not listening anymore. Make sure to update the tile 3716 // visibilities so next time we open the panel we know the correct height already. 3717 if (mQSPanel != null) { 3718 mQSPanel.refreshAllTiles(); 3719 } 3720 mHandler.removeMessages(MSG_LAUNCH_TRANSITION_TIMEOUT); 3721 releaseGestureWakeLock(); 3722 mNotificationPanel.onAffordanceLaunchEnded(); 3723 mNotificationPanel.animate().cancel(); 3724 mNotificationPanel.setAlpha(1f); 3725 Trace.endSection(); 3726 return staying; 3727 } 3728 releaseGestureWakeLock()3729 private void releaseGestureWakeLock() { 3730 if (mGestureWakeLock.isHeld()) { 3731 mGestureWakeLock.release(); 3732 } 3733 } 3734 calculateGoingToFullShadeDelay()3735 public long calculateGoingToFullShadeDelay() { 3736 return mKeyguardFadingAwayDelay + mKeyguardFadingAwayDuration; 3737 } 3738 3739 /** 3740 * Notifies the status bar that Keyguard is going away very soon. 3741 */ keyguardGoingAway()3742 public void keyguardGoingAway() { 3743 3744 // Treat Keyguard exit animation as an app transition to achieve nice transition for status 3745 // bar. 3746 mKeyguardMonitor.notifyKeyguardGoingAway(true); 3747 mCommandQueue.appTransitionPending(true); 3748 } 3749 3750 /** 3751 * Notifies the status bar the Keyguard is fading away with the specified timings. 3752 * 3753 * @param startTime the start time of the animations in uptime millis 3754 * @param delay the precalculated animation delay in milliseconds 3755 * @param fadeoutDuration the duration of the exit animation, in milliseconds 3756 */ setKeyguardFadingAway(long startTime, long delay, long fadeoutDuration)3757 public void setKeyguardFadingAway(long startTime, long delay, long fadeoutDuration) { 3758 mKeyguardFadingAway = true; 3759 mKeyguardFadingAwayDelay = delay; 3760 mKeyguardFadingAwayDuration = fadeoutDuration; 3761 mCommandQueue.appTransitionStarting(startTime + fadeoutDuration 3762 - LightBarTransitionsController.DEFAULT_TINT_ANIMATION_DURATION, 3763 LightBarTransitionsController.DEFAULT_TINT_ANIMATION_DURATION, true); 3764 recomputeDisableFlags(fadeoutDuration > 0 /* animate */); 3765 mCommandQueue.appTransitionStarting( 3766 startTime - LightBarTransitionsController.DEFAULT_TINT_ANIMATION_DURATION, 3767 LightBarTransitionsController.DEFAULT_TINT_ANIMATION_DURATION, true); 3768 mKeyguardMonitor.notifyKeyguardFadingAway(delay, fadeoutDuration); 3769 } 3770 isKeyguardFadingAway()3771 public boolean isKeyguardFadingAway() { 3772 return mKeyguardFadingAway; 3773 } 3774 3775 /** 3776 * Notifies that the Keyguard fading away animation is done. 3777 */ finishKeyguardFadingAway()3778 public void finishKeyguardFadingAway() { 3779 mKeyguardFadingAway = false; 3780 mKeyguardMonitor.notifyKeyguardDoneFading(); 3781 mScrimController.setExpansionAffectsAlpha(true); 3782 } 3783 3784 // TODO: Move this to NotificationLockscreenUserManager. updatePublicMode()3785 private void updatePublicMode() { 3786 final boolean showingKeyguard = mStatusBarKeyguardViewManager.isShowing(); 3787 final boolean devicePublic = showingKeyguard 3788 && mStatusBarKeyguardViewManager.isSecure( 3789 mLockscreenUserManager.getCurrentUserId()); 3790 3791 // Look for public mode users. Users are considered public in either case of: 3792 // - device keyguard is shown in secure mode; 3793 // - profile is locked with a work challenge. 3794 SparseArray<UserInfo> currentProfiles = mLockscreenUserManager.getCurrentProfiles(); 3795 for (int i = currentProfiles.size() - 1; i >= 0; i--) { 3796 final int userId = currentProfiles.valueAt(i).id; 3797 boolean isProfilePublic = devicePublic; 3798 if (!devicePublic && userId != mLockscreenUserManager.getCurrentUserId()) { 3799 // We can't rely on KeyguardManager#isDeviceLocked() for unified profile challenge 3800 // due to a race condition where this code could be called before 3801 // TrustManagerService updates its internal records, resulting in an incorrect 3802 // state being cached in mLockscreenPublicMode. (b/35951989) 3803 if (mLockPatternUtils.isSeparateProfileChallengeEnabled(userId) 3804 && mStatusBarKeyguardViewManager.isSecure(userId)) { 3805 isProfilePublic = mKeyguardManager.isDeviceLocked(userId); 3806 } 3807 } 3808 mLockscreenUserManager.setLockscreenPublicMode(isProfilePublic, userId); 3809 } 3810 } 3811 updateKeyguardState(boolean goingToFullShade, boolean fromShadeLocked)3812 protected void updateKeyguardState(boolean goingToFullShade, boolean fromShadeLocked) { 3813 Trace.beginSection("StatusBar#updateKeyguardState"); 3814 if (mState == StatusBarState.KEYGUARD) { 3815 mKeyguardIndicationController.setVisible(true); 3816 mNotificationPanel.resetViews(); 3817 if (mKeyguardUserSwitcher != null) { 3818 mKeyguardUserSwitcher.setKeyguard(true, fromShadeLocked); 3819 } 3820 if (mStatusBarView != null) mStatusBarView.removePendingHideExpandedRunnables(); 3821 if (mAmbientIndicationContainer != null) { 3822 mAmbientIndicationContainer.setVisibility(View.VISIBLE); 3823 } 3824 } else { 3825 mKeyguardIndicationController.setVisible(false); 3826 if (mKeyguardUserSwitcher != null) { 3827 mKeyguardUserSwitcher.setKeyguard(false, 3828 goingToFullShade || 3829 mState == StatusBarState.SHADE_LOCKED || 3830 fromShadeLocked); 3831 } 3832 if (mAmbientIndicationContainer != null) { 3833 mAmbientIndicationContainer.setVisibility(View.INVISIBLE); 3834 } 3835 } 3836 mNotificationPanel.setBarState(mState, mKeyguardFadingAway, goingToFullShade); 3837 updateTheme(); 3838 updateDozingState(); 3839 updatePublicMode(); 3840 updateStackScrollerState(goingToFullShade, fromShadeLocked); 3841 mEntryManager.updateNotifications(); 3842 checkBarModes(); 3843 updateScrimController(); 3844 updateMediaMetaData(false, mState != StatusBarState.KEYGUARD); 3845 mKeyguardMonitor.notifyKeyguardState(mStatusBarKeyguardViewManager.isShowing(), 3846 mUnlockMethodCache.isMethodSecure(), 3847 mStatusBarKeyguardViewManager.isOccluded()); 3848 Trace.endSection(); 3849 } 3850 3851 /** 3852 * Switches theme from light to dark and vice-versa. 3853 */ updateTheme()3854 protected void updateTheme() { 3855 final boolean inflated = mStackScroller != null; 3856 3857 // The system wallpaper defines if QS should be light or dark. 3858 WallpaperColors systemColors = mColorExtractor 3859 .getWallpaperColors(WallpaperManager.FLAG_SYSTEM); 3860 final boolean useDarkTheme = systemColors != null 3861 && (systemColors.getColorHints() & WallpaperColors.HINT_SUPPORTS_DARK_THEME) != 0; 3862 if (isUsingDarkTheme() != useDarkTheme) { 3863 mUiOffloadThread.submit(() -> { 3864 try { 3865 mOverlayManager.setEnabled("com.android.systemui.theme.dark", 3866 useDarkTheme, mLockscreenUserManager.getCurrentUserId()); 3867 } catch (RemoteException e) { 3868 Log.w(TAG, "Can't change theme", e); 3869 } 3870 }); 3871 } 3872 3873 // Lock wallpaper defines the color of the majority of the views, hence we'll use it 3874 // to set our default theme. 3875 final boolean lockDarkText = mColorExtractor.getColors(WallpaperManager.FLAG_LOCK, true 3876 /* ignoreVisibility */).supportsDarkText(); 3877 final int themeResId = lockDarkText ? R.style.Theme_SystemUI_Light : R.style.Theme_SystemUI; 3878 if (mContext.getThemeResId() != themeResId) { 3879 mContext.setTheme(themeResId); 3880 if (inflated) { 3881 onThemeChanged(); 3882 } 3883 } 3884 3885 if (inflated) { 3886 int which; 3887 if (mState == StatusBarState.KEYGUARD || mState == StatusBarState.SHADE_LOCKED) { 3888 which = WallpaperManager.FLAG_LOCK; 3889 } else { 3890 which = WallpaperManager.FLAG_SYSTEM; 3891 } 3892 final boolean useDarkText = mColorExtractor.getColors(which, 3893 true /* ignoreVisibility */).supportsDarkText(); 3894 mStackScroller.updateDecorViews(useDarkText); 3895 3896 // Make sure we have the correct navbar/statusbar colors. 3897 mStatusBarWindowManager.setKeyguardDark(useDarkText); 3898 } 3899 } 3900 updateDozingState()3901 private void updateDozingState() { 3902 Trace.traceCounter(Trace.TRACE_TAG_APP, "dozing", mDozing ? 1 : 0); 3903 Trace.beginSection("StatusBar#updateDozingState"); 3904 3905 boolean sleepingFromKeyguard = 3906 mStatusBarKeyguardViewManager.isGoingToSleepVisibleNotOccluded(); 3907 boolean animate = (!mDozing && mDozeServiceHost.shouldAnimateWakeup()) 3908 || (mDozing && mDozeServiceHost.shouldAnimateScreenOff() && sleepingFromKeyguard); 3909 3910 mStackScroller.setDark(mDozing, animate, mWakeUpTouchLocation); 3911 mDozeScrimController.setDozing(mDozing); 3912 mKeyguardIndicationController.setDozing(mDozing); 3913 mNotificationPanel.setDozing(mDozing, animate); 3914 updateQsExpansionEnabled(); 3915 Trace.endSection(); 3916 } 3917 updateStackScrollerState(boolean goingToFullShade, boolean fromShadeLocked)3918 public void updateStackScrollerState(boolean goingToFullShade, boolean fromShadeLocked) { 3919 if (mStackScroller == null) return; 3920 boolean onKeyguard = mState == StatusBarState.KEYGUARD; 3921 boolean publicMode = mLockscreenUserManager.isAnyProfilePublicMode(); 3922 if (mHeadsUpAppearanceController != null) { 3923 mHeadsUpAppearanceController.setPublicMode(publicMode); 3924 } 3925 mStackScroller.setHideSensitive(publicMode, goingToFullShade); 3926 mStackScroller.setDimmed(onKeyguard, fromShadeLocked /* animate */); 3927 mStackScroller.setExpandingEnabled(!onKeyguard); 3928 ActivatableNotificationView activatedChild = mStackScroller.getActivatedChild(); 3929 mStackScroller.setActivatedChild(null); 3930 if (activatedChild != null) { 3931 activatedChild.makeInactive(false /* animate */); 3932 } 3933 } 3934 userActivity()3935 public void userActivity() { 3936 if (mState == StatusBarState.KEYGUARD) { 3937 mKeyguardViewMediatorCallback.userActivity(); 3938 } 3939 } 3940 interceptMediaKey(KeyEvent event)3941 public boolean interceptMediaKey(KeyEvent event) { 3942 return mState == StatusBarState.KEYGUARD 3943 && mStatusBarKeyguardViewManager.interceptMediaKey(event); 3944 } 3945 shouldUnlockOnMenuPressed()3946 protected boolean shouldUnlockOnMenuPressed() { 3947 return mDeviceInteractive && mState != StatusBarState.SHADE 3948 && mStatusBarKeyguardViewManager.shouldDismissOnMenuPressed(); 3949 } 3950 onMenuPressed()3951 public boolean onMenuPressed() { 3952 if (shouldUnlockOnMenuPressed()) { 3953 animateCollapsePanels( 3954 CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL /* flags */, true /* force */); 3955 return true; 3956 } 3957 return false; 3958 } 3959 endAffordanceLaunch()3960 public void endAffordanceLaunch() { 3961 releaseGestureWakeLock(); 3962 mNotificationPanel.onAffordanceLaunchEnded(); 3963 } 3964 onBackPressed()3965 public boolean onBackPressed() { 3966 boolean isScrimmedBouncer = mScrimController.getState() == ScrimState.BOUNCER_SCRIMMED; 3967 if (mStatusBarKeyguardViewManager.onBackPressed(isScrimmedBouncer /* hideImmediately */)) { 3968 if (!isScrimmedBouncer) { 3969 mNotificationPanel.expandWithoutQs(); 3970 } 3971 return true; 3972 } 3973 if (mNotificationPanel.isQsExpanded()) { 3974 if (mNotificationPanel.isQsDetailShowing()) { 3975 mNotificationPanel.closeQsDetail(); 3976 } else { 3977 mNotificationPanel.animateCloseQs(); 3978 } 3979 return true; 3980 } 3981 if (mState != StatusBarState.KEYGUARD && mState != StatusBarState.SHADE_LOCKED) { 3982 animateCollapsePanels(); 3983 return true; 3984 } 3985 if (mKeyguardUserSwitcher != null && mKeyguardUserSwitcher.hideIfNotSimple(true)) { 3986 return true; 3987 } 3988 return false; 3989 } 3990 onSpacePressed()3991 public boolean onSpacePressed() { 3992 if (mDeviceInteractive && mState != StatusBarState.SHADE) { 3993 animateCollapsePanels( 3994 CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL /* flags */, true /* force */); 3995 return true; 3996 } 3997 return false; 3998 } 3999 showBouncerIfKeyguard()4000 private void showBouncerIfKeyguard() { 4001 if ((mState == StatusBarState.KEYGUARD || mState == StatusBarState.SHADE_LOCKED) 4002 && !mKeyguardViewMediator.isHiding()) { 4003 showBouncer(true /* scrimmed */); 4004 } 4005 } 4006 showBouncer(boolean scrimmed)4007 protected void showBouncer(boolean scrimmed) { 4008 mStatusBarKeyguardViewManager.showBouncer(scrimmed); 4009 } 4010 instantExpandNotificationsPanel()4011 private void instantExpandNotificationsPanel() { 4012 // Make our window larger and the panel expanded. 4013 makeExpandedVisible(true); 4014 mNotificationPanel.expand(false /* animate */); 4015 recomputeDisableFlags(false /* animate */); 4016 } 4017 instantCollapseNotificationPanel()4018 private void instantCollapseNotificationPanel() { 4019 mNotificationPanel.instantCollapse(); 4020 runPostCollapseRunnables(); 4021 } 4022 4023 @Override onActivated(ActivatableNotificationView view)4024 public void onActivated(ActivatableNotificationView view) { 4025 onActivated((View) view); 4026 mStackScroller.setActivatedChild(view); 4027 } 4028 onActivated(View view)4029 public void onActivated(View view) { 4030 mLockscreenGestureLogger.write( 4031 MetricsEvent.ACTION_LS_NOTE, 4032 0 /* lengthDp - N/A */, 0 /* velocityDp - N/A */); 4033 mKeyguardIndicationController.showTransientIndication(R.string.notification_tap_again); 4034 ActivatableNotificationView previousView = mStackScroller.getActivatedChild(); 4035 if (previousView != null) { 4036 previousView.makeInactive(true /* animate */); 4037 } 4038 } 4039 4040 /** 4041 * @param state The {@link StatusBarState} to set. 4042 */ setBarState(int state)4043 public void setBarState(int state) { 4044 // If we're visible and switched to SHADE_LOCKED (the user dragged 4045 // down on the lockscreen), clear notification LED, vibration, 4046 // ringing. 4047 // Other transitions are covered in handleVisibleToUserChanged(). 4048 if (state != mState && mVisible && (state == StatusBarState.SHADE_LOCKED 4049 || (state == StatusBarState.SHADE && isGoingToNotificationShade()))) { 4050 clearNotificationEffects(); 4051 } 4052 if (state == StatusBarState.KEYGUARD) { 4053 mRemoteInputManager.removeRemoteInputEntriesKeptUntilCollapsed(); 4054 maybeEscalateHeadsUp(); 4055 } 4056 mState = state; 4057 mGroupManager.setStatusBarState(state); 4058 mHeadsUpManager.setStatusBarState(state); 4059 mFalsingManager.setStatusBarState(state); 4060 mStatusBarWindowManager.setStatusBarState(state); 4061 mStackScroller.setStatusBarState(state); 4062 updateReportRejectedTouchVisibility(); 4063 updateDozing(); 4064 updateTheme(); 4065 touchAutoDim(); 4066 mNotificationShelf.setStatusBarState(state); 4067 } 4068 4069 @Override onActivationReset(ActivatableNotificationView view)4070 public void onActivationReset(ActivatableNotificationView view) { 4071 if (view == mStackScroller.getActivatedChild()) { 4072 mStackScroller.setActivatedChild(null); 4073 onActivationReset((View)view); 4074 } 4075 } 4076 onActivationReset(View view)4077 public void onActivationReset(View view) { 4078 mKeyguardIndicationController.hideTransientIndication(); 4079 } 4080 onTrackingStarted()4081 public void onTrackingStarted() { 4082 runPostCollapseRunnables(); 4083 } 4084 onClosingFinished()4085 public void onClosingFinished() { 4086 runPostCollapseRunnables(); 4087 if (!isPresenterFullyCollapsed()) { 4088 // if we set it not to be focusable when collapsing, we have to undo it when we aborted 4089 // the closing 4090 mStatusBarWindowManager.setStatusBarFocusable(true); 4091 } 4092 } 4093 onUnlockHintStarted()4094 public void onUnlockHintStarted() { 4095 mFalsingManager.onUnlockHintStarted(); 4096 mKeyguardIndicationController.showTransientIndication(R.string.keyguard_unlock); 4097 } 4098 onHintFinished()4099 public void onHintFinished() { 4100 // Delay the reset a bit so the user can read the text. 4101 mKeyguardIndicationController.hideTransientIndicationDelayed(HINT_RESET_DELAY_MS); 4102 } 4103 onCameraHintStarted()4104 public void onCameraHintStarted() { 4105 mFalsingManager.onCameraHintStarted(); 4106 mKeyguardIndicationController.showTransientIndication(R.string.camera_hint); 4107 } 4108 onVoiceAssistHintStarted()4109 public void onVoiceAssistHintStarted() { 4110 mFalsingManager.onLeftAffordanceHintStarted(); 4111 mKeyguardIndicationController.showTransientIndication(R.string.voice_hint); 4112 } 4113 onPhoneHintStarted()4114 public void onPhoneHintStarted() { 4115 mFalsingManager.onLeftAffordanceHintStarted(); 4116 mKeyguardIndicationController.showTransientIndication(R.string.phone_hint); 4117 } 4118 onTrackingStopped(boolean expand)4119 public void onTrackingStopped(boolean expand) { 4120 if (mState == StatusBarState.KEYGUARD || mState == StatusBarState.SHADE_LOCKED) { 4121 if (!expand && !mUnlockMethodCache.canSkipBouncer()) { 4122 showBouncer(false /* scrimmed */); 4123 } 4124 } 4125 } 4126 4127 @Override getMaxNotificationsWhileLocked(boolean recompute)4128 public int getMaxNotificationsWhileLocked(boolean recompute) { 4129 if (recompute) { 4130 mMaxKeyguardNotifications = Math.max(1, 4131 mNotificationPanel.computeMaxKeyguardNotifications( 4132 mMaxAllowedKeyguardNotifications)); 4133 return mMaxKeyguardNotifications; 4134 } 4135 return mMaxKeyguardNotifications; 4136 } 4137 getMaxNotificationsWhileLocked()4138 public int getMaxNotificationsWhileLocked() { 4139 return getMaxNotificationsWhileLocked(false /* recompute */); 4140 } 4141 4142 // TODO: Figure out way to remove these. getNavigationBarView()4143 public NavigationBarView getNavigationBarView() { 4144 return (mNavigationBar != null ? (NavigationBarView) mNavigationBar.getView() : null); 4145 } 4146 getNavigationBarWindow()4147 public View getNavigationBarWindow() { 4148 return mNavigationBarView; 4149 } 4150 4151 /** 4152 * TODO: Remove this method. Views should not be passed forward. Will cause theme issues. 4153 * @return bottom area view 4154 */ getKeyguardBottomAreaView()4155 public KeyguardBottomAreaView getKeyguardBottomAreaView() { 4156 return mNotificationPanel.getKeyguardBottomAreaView(); 4157 } 4158 4159 // ---------------------- DragDownHelper.OnDragDownListener ------------------------------------ 4160 4161 4162 /* Only ever called as a consequence of a lockscreen expansion gesture. */ 4163 @Override onDraggedDown(View startingChild, int dragLengthY)4164 public boolean onDraggedDown(View startingChild, int dragLengthY) { 4165 if (mState == StatusBarState.KEYGUARD 4166 && hasActiveNotifications() && (!isDozing() || isPulsing())) { 4167 mLockscreenGestureLogger.write( 4168 MetricsEvent.ACTION_LS_SHADE, 4169 (int) (dragLengthY / mDisplayMetrics.density), 4170 0 /* velocityDp - N/A */); 4171 4172 // We have notifications, go to locked shade. 4173 goToLockedShade(startingChild); 4174 if (startingChild instanceof ExpandableNotificationRow) { 4175 ExpandableNotificationRow row = (ExpandableNotificationRow) startingChild; 4176 row.onExpandedByGesture(true /* drag down is always an open */); 4177 } 4178 return true; 4179 } else { 4180 // abort gesture. 4181 return false; 4182 } 4183 } 4184 4185 @Override onDragDownReset()4186 public void onDragDownReset() { 4187 mStackScroller.setDimmed(true /* dimmed */, true /* animated */); 4188 mStackScroller.resetScrollPosition(); 4189 mStackScroller.resetCheckSnoozeLeavebehind(); 4190 } 4191 4192 @Override onCrossedThreshold(boolean above)4193 public void onCrossedThreshold(boolean above) { 4194 mStackScroller.setDimmed(!above /* dimmed */, true /* animate */); 4195 } 4196 4197 @Override onTouchSlopExceeded()4198 public void onTouchSlopExceeded() { 4199 mStackScroller.cancelLongPress(); 4200 mStackScroller.checkSnoozeLeavebehind(); 4201 } 4202 4203 @Override setEmptyDragAmount(float amount)4204 public void setEmptyDragAmount(float amount) { 4205 mNotificationPanel.setEmptyDragAmount(amount); 4206 } 4207 4208 @Override isFalsingCheckNeeded()4209 public boolean isFalsingCheckNeeded() { 4210 return mState == StatusBarState.KEYGUARD; 4211 } 4212 4213 /** 4214 * If secure with redaction: Show bouncer, go to unlocked shade. 4215 * 4216 * <p>If secure without redaction or no security: Go to {@link StatusBarState#SHADE_LOCKED}.</p> 4217 * 4218 * @param expandView The view to expand after going to the shade. 4219 */ goToLockedShade(View expandView)4220 public void goToLockedShade(View expandView) { 4221 if ((mDisabled2 & StatusBarManager.DISABLE2_NOTIFICATION_SHADE) != 0) { 4222 return; 4223 } 4224 4225 int userId = mLockscreenUserManager.getCurrentUserId(); 4226 ExpandableNotificationRow row = null; 4227 if (expandView instanceof ExpandableNotificationRow) { 4228 row = (ExpandableNotificationRow) expandView; 4229 row.setUserExpanded(true /* userExpanded */, true /* allowChildExpansion */); 4230 // Indicate that the group expansion is changing at this time -- this way the group 4231 // and children backgrounds / divider animations will look correct. 4232 row.setGroupExpansionChanging(true); 4233 if (row.getStatusBarNotification() != null) { 4234 userId = row.getStatusBarNotification().getUserId(); 4235 } 4236 } 4237 boolean fullShadeNeedsBouncer = !mLockscreenUserManager. 4238 userAllowsPrivateNotificationsInPublic(mLockscreenUserManager.getCurrentUserId()) 4239 || !mLockscreenUserManager.shouldShowLockscreenNotifications() 4240 || mFalsingManager.shouldEnforceBouncer(); 4241 if (mLockscreenUserManager.isLockscreenPublicMode(userId) && fullShadeNeedsBouncer) { 4242 mLeaveOpenOnKeyguardHide = true; 4243 showBouncerIfKeyguard(); 4244 mDraggedDownRow = row; 4245 mPendingRemoteInputView = null; 4246 } else { 4247 mNotificationPanel.animateToFullShade(0 /* delay */); 4248 setBarState(StatusBarState.SHADE_LOCKED); 4249 updateKeyguardState(false /* goingToFullShade */, false /* fromShadeLocked */); 4250 } 4251 } 4252 onLockedNotificationImportanceChange(OnDismissAction dismissAction)4253 public void onLockedNotificationImportanceChange(OnDismissAction dismissAction) { 4254 mLeaveOpenOnKeyguardHide = true; 4255 dismissKeyguardThenExecute(dismissAction, true /* afterKeyguardGone */); 4256 } 4257 4258 @Override onLockedRemoteInput(ExpandableNotificationRow row, View clicked)4259 public void onLockedRemoteInput(ExpandableNotificationRow row, View clicked) { 4260 mLeaveOpenOnKeyguardHide = true; 4261 showBouncer(true /* scrimmed */); 4262 mPendingRemoteInputView = clicked; 4263 } 4264 4265 @Override onMakeExpandedVisibleForRemoteInput(ExpandableNotificationRow row, View clickedView)4266 public void onMakeExpandedVisibleForRemoteInput(ExpandableNotificationRow row, 4267 View clickedView) { 4268 if (isKeyguardShowing()) { 4269 onLockedRemoteInput(row, clickedView); 4270 } else { 4271 row.setUserExpanded(true); 4272 row.getPrivateLayout().setOnExpandedVisibleListener(clickedView::performClick); 4273 } 4274 } 4275 4276 @Override shouldHandleRemoteInput(View view, PendingIntent pendingIntent)4277 public boolean shouldHandleRemoteInput(View view, PendingIntent pendingIntent) { 4278 // Skip remote input as doing so will expand the notification shade. 4279 return (mDisabled2 & StatusBarManager.DISABLE2_NOTIFICATION_SHADE) != 0; 4280 } 4281 4282 @Override handleRemoteViewClick(View view, PendingIntent pendingIntent, Intent fillInIntent, NotificationRemoteInputManager.ClickHandler defaultHandler)4283 public boolean handleRemoteViewClick(View view, PendingIntent pendingIntent, 4284 Intent fillInIntent, NotificationRemoteInputManager.ClickHandler defaultHandler) { 4285 final boolean isActivity = pendingIntent.isActivity(); 4286 if (isActivity) { 4287 final boolean afterKeyguardGone = PreviewInflater.wouldLaunchResolverActivity( 4288 mContext, pendingIntent.getIntent(), mLockscreenUserManager.getCurrentUserId()); 4289 dismissKeyguardThenExecute(() -> { 4290 try { 4291 ActivityManager.getService().resumeAppSwitches(); 4292 } catch (RemoteException e) { 4293 } 4294 4295 boolean handled = defaultHandler.handleClick(); 4296 4297 // close the shade if it was open 4298 if (handled && !mNotificationPanel.isFullyCollapsed()) { 4299 animateCollapsePanels( 4300 CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL, true /* force */); 4301 visibilityChanged(false); 4302 mAssistManager.hideAssist(); 4303 4304 // Wait for activity start. 4305 return true; 4306 } else { 4307 return false; 4308 } 4309 4310 }, afterKeyguardGone); 4311 return true; 4312 } else { 4313 return defaultHandler.handleClick(); 4314 } 4315 } 4316 startWorkChallengeIfNecessary(int userId, IntentSender intendSender, String notificationKey)4317 protected boolean startWorkChallengeIfNecessary(int userId, IntentSender intendSender, 4318 String notificationKey) { 4319 // Clear pending remote view, as we do not want to trigger pending remote input view when 4320 // it's called by other code 4321 mPendingWorkRemoteInputView = null; 4322 // Begin old BaseStatusBar.startWorkChallengeIfNecessary. 4323 final Intent newIntent = mKeyguardManager.createConfirmDeviceCredentialIntent(null, 4324 null, userId); 4325 if (newIntent == null) { 4326 return false; 4327 } 4328 final Intent callBackIntent = new Intent(NOTIFICATION_UNLOCKED_BY_WORK_CHALLENGE_ACTION); 4329 callBackIntent.putExtra(Intent.EXTRA_INTENT, intendSender); 4330 callBackIntent.putExtra(Intent.EXTRA_INDEX, notificationKey); 4331 callBackIntent.setPackage(mContext.getPackageName()); 4332 4333 PendingIntent callBackPendingIntent = PendingIntent.getBroadcast( 4334 mContext, 4335 0, 4336 callBackIntent, 4337 PendingIntent.FLAG_CANCEL_CURRENT | 4338 PendingIntent.FLAG_ONE_SHOT | 4339 PendingIntent.FLAG_IMMUTABLE); 4340 newIntent.putExtra( 4341 Intent.EXTRA_INTENT, 4342 callBackPendingIntent.getIntentSender()); 4343 try { 4344 ActivityManager.getService().startConfirmDeviceCredentialIntent(newIntent, 4345 null /*options*/); 4346 } catch (RemoteException ex) { 4347 // ignore 4348 } 4349 return true; 4350 // End old BaseStatusBar.startWorkChallengeIfNecessary. 4351 } 4352 4353 @Override onLockedWorkRemoteInput(int userId, ExpandableNotificationRow row, View clicked)4354 public void onLockedWorkRemoteInput(int userId, ExpandableNotificationRow row, 4355 View clicked) { 4356 // Collapse notification and show work challenge 4357 animateCollapsePanels(); 4358 startWorkChallengeIfNecessary(userId, null, null); 4359 // Add pending remote input view after starting work challenge, as starting work challenge 4360 // will clear all previous pending review view 4361 mPendingWorkRemoteInputView = clicked; 4362 } 4363 4364 @Override onWorkChallengeChanged()4365 public void onWorkChallengeChanged() { 4366 updatePublicMode(); 4367 mEntryManager.updateNotifications(); 4368 if (mPendingWorkRemoteInputView != null 4369 && !mLockscreenUserManager.isAnyProfilePublicMode()) { 4370 // Expand notification panel and the notification row, then click on remote input view 4371 final Runnable clickPendingViewRunnable = () -> { 4372 final View pendingWorkRemoteInputView = mPendingWorkRemoteInputView; 4373 if (pendingWorkRemoteInputView == null) { 4374 return; 4375 } 4376 4377 // Climb up the hierarchy until we get to the container for this row. 4378 ViewParent p = pendingWorkRemoteInputView.getParent(); 4379 while (!(p instanceof ExpandableNotificationRow)) { 4380 if (p == null) { 4381 return; 4382 } 4383 p = p.getParent(); 4384 } 4385 4386 final ExpandableNotificationRow row = (ExpandableNotificationRow) p; 4387 ViewParent viewParent = row.getParent(); 4388 if (viewParent instanceof NotificationStackScrollLayout) { 4389 final NotificationStackScrollLayout scrollLayout = 4390 (NotificationStackScrollLayout) viewParent; 4391 row.makeActionsVisibile(); 4392 row.post(() -> { 4393 final Runnable finishScrollingCallback = () -> { 4394 mPendingWorkRemoteInputView.callOnClick(); 4395 mPendingWorkRemoteInputView = null; 4396 scrollLayout.setFinishScrollingCallback(null); 4397 }; 4398 if (scrollLayout.scrollTo(row)) { 4399 // It scrolls! So call it when it's finished. 4400 scrollLayout.setFinishScrollingCallback(finishScrollingCallback); 4401 } else { 4402 // It does not scroll, so call it now! 4403 finishScrollingCallback.run(); 4404 } 4405 }); 4406 } 4407 }; 4408 mNotificationPanel.getViewTreeObserver().addOnGlobalLayoutListener( 4409 new ViewTreeObserver.OnGlobalLayoutListener() { 4410 @Override 4411 public void onGlobalLayout() { 4412 if (mNotificationPanel.mStatusBar.getStatusBarWindow() 4413 .getHeight() != mNotificationPanel.mStatusBar 4414 .getStatusBarHeight()) { 4415 mNotificationPanel.getViewTreeObserver() 4416 .removeOnGlobalLayoutListener(this); 4417 mNotificationPanel.post(clickPendingViewRunnable); 4418 } 4419 } 4420 }); 4421 instantExpandNotificationsPanel(); 4422 } 4423 } 4424 4425 @Override onExpandClicked(Entry clickedEntry, boolean nowExpanded)4426 public void onExpandClicked(Entry clickedEntry, boolean nowExpanded) { 4427 mHeadsUpManager.setExpanded(clickedEntry, nowExpanded); 4428 if (mState == StatusBarState.KEYGUARD && nowExpanded) { 4429 goToLockedShade(clickedEntry.row); 4430 } 4431 } 4432 4433 /** 4434 * Goes back to the keyguard after hanging around in {@link StatusBarState#SHADE_LOCKED}. 4435 */ goToKeyguard()4436 public void goToKeyguard() { 4437 if (mState == StatusBarState.SHADE_LOCKED) { 4438 mStackScroller.onGoToKeyguard(); 4439 setBarState(StatusBarState.KEYGUARD); 4440 updateKeyguardState(false /* goingToFullShade */, true /* fromShadeLocked*/); 4441 } 4442 } 4443 getKeyguardFadingAwayDelay()4444 public long getKeyguardFadingAwayDelay() { 4445 return mKeyguardFadingAwayDelay; 4446 } 4447 getKeyguardFadingAwayDuration()4448 public long getKeyguardFadingAwayDuration() { 4449 return mKeyguardFadingAwayDuration; 4450 } 4451 setBouncerShowing(boolean bouncerShowing)4452 public void setBouncerShowing(boolean bouncerShowing) { 4453 mBouncerShowing = bouncerShowing; 4454 if (mStatusBarView != null) mStatusBarView.setBouncerShowing(bouncerShowing); 4455 updateHideIconsForBouncer(true /* animate */); 4456 recomputeDisableFlags(true /* animate */); 4457 updateScrimController(); 4458 } 4459 cancelCurrentTouch()4460 public void cancelCurrentTouch() { 4461 if (mNotificationPanel.isTracking()) { 4462 mStatusBarWindow.cancelCurrentTouch(); 4463 if (mState == StatusBarState.SHADE) { 4464 animateCollapsePanels(); 4465 } 4466 } 4467 } 4468 4469 final WakefulnessLifecycle.Observer mWakefulnessObserver = new WakefulnessLifecycle.Observer() { 4470 @Override 4471 public void onFinishedGoingToSleep() { 4472 mNotificationPanel.onAffordanceLaunchEnded(); 4473 releaseGestureWakeLock(); 4474 mLaunchCameraOnScreenTurningOn = false; 4475 mDeviceInteractive = false; 4476 mWakeUpComingFromTouch = false; 4477 mWakeUpTouchLocation = null; 4478 mStackScroller.setAnimationsEnabled(false); 4479 mVisualStabilityManager.setScreenOn(false); 4480 updateVisibleToUser(); 4481 4482 // We need to disable touch events because these might 4483 // collapse the panel after we expanded it, and thus we would end up with a blank 4484 // Keyguard. 4485 mNotificationPanel.setTouchDisabled(true); 4486 mStatusBarWindow.cancelCurrentTouch(); 4487 if (mLaunchCameraOnFinishedGoingToSleep) { 4488 mLaunchCameraOnFinishedGoingToSleep = false; 4489 4490 // This gets executed before we will show Keyguard, so post it in order that the state 4491 // is correct. 4492 mHandler.post(() -> onCameraLaunchGestureDetected(mLastCameraLaunchSource)); 4493 } 4494 updateIsKeyguard(); 4495 } 4496 4497 @Override 4498 public void onStartedGoingToSleep() { 4499 notifyHeadsUpGoingToSleep(); 4500 dismissVolumeDialog(); 4501 } 4502 4503 @Override 4504 public void onStartedWakingUp() { 4505 mDeviceInteractive = true; 4506 mStackScroller.setAnimationsEnabled(true); 4507 mVisualStabilityManager.setScreenOn(true); 4508 mNotificationPanel.setTouchDisabled(false); 4509 mDozeServiceHost.stopDozing(); 4510 updateVisibleToUser(); 4511 updateIsKeyguard(); 4512 updateScrimController(); 4513 } 4514 }; 4515 4516 final ScreenLifecycle.Observer mScreenObserver = new ScreenLifecycle.Observer() { 4517 @Override 4518 public void onScreenTurningOn() { 4519 mFalsingManager.onScreenTurningOn(); 4520 mNotificationPanel.onScreenTurningOn(); 4521 4522 if (mLaunchCameraOnScreenTurningOn) { 4523 mNotificationPanel.launchCamera(false, mLastCameraLaunchSource); 4524 mLaunchCameraOnScreenTurningOn = false; 4525 } 4526 4527 updateScrimController(); 4528 } 4529 4530 @Override 4531 public void onScreenTurnedOn() { 4532 mScrimController.onScreenTurnedOn(); 4533 } 4534 4535 @Override 4536 public void onScreenTurnedOff() { 4537 mFalsingManager.onScreenOff(); 4538 mScrimController.onScreenTurnedOff(); 4539 // If we pulse in from AOD, we turn the screen off first. However, updatingIsKeyguard 4540 // in that case destroys the HeadsUpManager state, so don't do it in that case. 4541 if (!isPulsing()) { 4542 updateIsKeyguard(); 4543 } 4544 } 4545 }; 4546 getWakefulnessState()4547 public int getWakefulnessState() { 4548 return mWakefulnessLifecycle.getWakefulness(); 4549 } 4550 vibrateForCameraGesture()4551 private void vibrateForCameraGesture() { 4552 // Make sure to pass -1 for repeat so VibratorService doesn't stop us when going to sleep. 4553 mVibrator.vibrate(mCameraLaunchGestureVibePattern, -1 /* repeat */); 4554 } 4555 4556 /** 4557 * @return true if the screen is currently fully off, i.e. has finished turning off and has 4558 * since not started turning on. 4559 */ isScreenFullyOff()4560 public boolean isScreenFullyOff() { 4561 return mScreenLifecycle.getScreenState() == ScreenLifecycle.SCREEN_OFF; 4562 } 4563 4564 @Override showScreenPinningRequest(int taskId)4565 public void showScreenPinningRequest(int taskId) { 4566 if (mKeyguardMonitor.isShowing()) { 4567 // Don't allow apps to trigger this from keyguard. 4568 return; 4569 } 4570 // Show screen pinning request, since this comes from an app, show 'no thanks', button. 4571 showScreenPinningRequest(taskId, true); 4572 } 4573 showScreenPinningRequest(int taskId, boolean allowCancel)4574 public void showScreenPinningRequest(int taskId, boolean allowCancel) { 4575 mScreenPinningRequest.showPrompt(taskId, allowCancel); 4576 } 4577 hasActiveNotifications()4578 public boolean hasActiveNotifications() { 4579 return !mEntryManager.getNotificationData().getActiveNotifications().isEmpty(); 4580 } 4581 4582 @Override wakeUpIfDozing(long time, View where)4583 public void wakeUpIfDozing(long time, View where) { 4584 if (mDozing) { 4585 PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE); 4586 pm.wakeUp(time, "com.android.systemui:NODOZE"); 4587 mWakeUpComingFromTouch = true; 4588 where.getLocationInWindow(mTmpInt2); 4589 mWakeUpTouchLocation = new PointF(mTmpInt2[0] + where.getWidth() / 2, 4590 mTmpInt2[1] + where.getHeight() / 2); 4591 mStatusBarKeyguardViewManager.notifyDeviceWakeUpRequested(); 4592 mFalsingManager.onScreenOnFromTouch(); 4593 } 4594 } 4595 4596 @Override isDeviceLocked(int userId)4597 public boolean isDeviceLocked(int userId) { 4598 return mKeyguardManager.isDeviceLocked(userId); 4599 } 4600 4601 @Override appTransitionCancelled()4602 public void appTransitionCancelled() { 4603 EventBus.getDefault().send(new AppTransitionFinishedEvent()); 4604 } 4605 4606 @Override appTransitionFinished()4607 public void appTransitionFinished() { 4608 EventBus.getDefault().send(new AppTransitionFinishedEvent()); 4609 } 4610 4611 @Override onCameraLaunchGestureDetected(int source)4612 public void onCameraLaunchGestureDetected(int source) { 4613 mLastCameraLaunchSource = source; 4614 if (isGoingToSleep()) { 4615 if (DEBUG_CAMERA_LIFT) Slog.d(TAG, "Finish going to sleep before launching camera"); 4616 mLaunchCameraOnFinishedGoingToSleep = true; 4617 return; 4618 } 4619 if (!mNotificationPanel.canCameraGestureBeLaunched( 4620 mStatusBarKeyguardViewManager.isShowing() && mExpandedVisible)) { 4621 if (DEBUG_CAMERA_LIFT) Slog.d(TAG, "Can't launch camera right now, mExpandedVisible: " + 4622 mExpandedVisible); 4623 return; 4624 } 4625 if (!mDeviceInteractive) { 4626 PowerManager pm = mContext.getSystemService(PowerManager.class); 4627 pm.wakeUp(SystemClock.uptimeMillis(), "com.android.systemui:CAMERA_GESTURE"); 4628 mStatusBarKeyguardViewManager.notifyDeviceWakeUpRequested(); 4629 } 4630 vibrateForCameraGesture(); 4631 if (!mStatusBarKeyguardViewManager.isShowing()) { 4632 startActivityDismissingKeyguard(KeyguardBottomAreaView.INSECURE_CAMERA_INTENT, 4633 false /* onlyProvisioned */, true /* dismissShade */, 4634 true /* disallowEnterPictureInPictureWhileLaunching */, null /* callback */, 0); 4635 } else { 4636 if (!mDeviceInteractive) { 4637 // Avoid flickering of the scrim when we instant launch the camera and the bouncer 4638 // comes on. 4639 mGestureWakeLock.acquire(LAUNCH_TRANSITION_TIMEOUT_MS + 1000L); 4640 } 4641 if (isScreenTurningOnOrOn()) { 4642 if (DEBUG_CAMERA_LIFT) Slog.d(TAG, "Launching camera"); 4643 if (mStatusBarKeyguardViewManager.isBouncerShowing()) { 4644 mStatusBarKeyguardViewManager.reset(true /* hide */); 4645 } 4646 mNotificationPanel.launchCamera(mDeviceInteractive /* animate */, source); 4647 updateScrimController(); 4648 } else { 4649 // We need to defer the camera launch until the screen comes on, since otherwise 4650 // we will dismiss us too early since we are waiting on an activity to be drawn and 4651 // incorrectly get notified because of the screen on event (which resumes and pauses 4652 // some activities) 4653 if (DEBUG_CAMERA_LIFT) Slog.d(TAG, "Deferring until screen turns on"); 4654 mLaunchCameraOnScreenTurningOn = true; 4655 } 4656 } 4657 } 4658 isCameraAllowedByAdmin()4659 boolean isCameraAllowedByAdmin() { 4660 if (mDevicePolicyManager.getCameraDisabled(null, 4661 mLockscreenUserManager.getCurrentUserId())) { 4662 return false; 4663 } else if (mStatusBarKeyguardViewManager == null || 4664 (isKeyguardShowing() && isKeyguardSecure())) { 4665 // Check if the admin has disabled the camera specifically for the keyguard 4666 return (mDevicePolicyManager. 4667 getKeyguardDisabledFeatures(null, mLockscreenUserManager.getCurrentUserId()) 4668 & DevicePolicyManager.KEYGUARD_DISABLE_SECURE_CAMERA) == 0; 4669 } 4670 4671 return true; 4672 } 4673 isGoingToSleep()4674 private boolean isGoingToSleep() { 4675 return mWakefulnessLifecycle.getWakefulness() 4676 == WakefulnessLifecycle.WAKEFULNESS_GOING_TO_SLEEP; 4677 } 4678 isScreenTurningOnOrOn()4679 private boolean isScreenTurningOnOrOn() { 4680 return mScreenLifecycle.getScreenState() == ScreenLifecycle.SCREEN_TURNING_ON 4681 || mScreenLifecycle.getScreenState() == ScreenLifecycle.SCREEN_ON; 4682 } 4683 notifyFpAuthModeChanged()4684 public void notifyFpAuthModeChanged() { 4685 updateDozing(); 4686 updateScrimController(); 4687 } 4688 updateDozing()4689 private void updateDozing() { 4690 Trace.beginSection("StatusBar#updateDozing"); 4691 // When in wake-and-unlock while pulsing, keep dozing state until fully unlocked. 4692 boolean dozing = mDozingRequested && mState == StatusBarState.KEYGUARD 4693 || mFingerprintUnlockController.getMode() 4694 == FingerprintUnlockController.MODE_WAKE_AND_UNLOCK_PULSING; 4695 final boolean alwaysOn = DozeParameters.getInstance(mContext).getAlwaysOn(); 4696 // When in wake-and-unlock we may not have received a change to mState 4697 // but we still should not be dozing, manually set to false. 4698 if (mFingerprintUnlockController.getMode() == 4699 FingerprintUnlockController.MODE_WAKE_AND_UNLOCK) { 4700 dozing = false; 4701 } 4702 if (mDozing != dozing) { 4703 mDozing = dozing; 4704 mKeyguardViewMediator.setAodShowing(mDozing && alwaysOn); 4705 mStatusBarWindowManager.setDozing(mDozing); 4706 mStatusBarKeyguardViewManager.setDozing(mDozing); 4707 if (mAmbientIndicationContainer instanceof DozeReceiver) { 4708 ((DozeReceiver) mAmbientIndicationContainer).setDozing(mDozing); 4709 } 4710 mEntryManager.updateNotifications(); 4711 updateDozingState(); 4712 updateReportRejectedTouchVisibility(); 4713 } 4714 Trace.endSection(); 4715 } 4716 4717 @VisibleForTesting updateScrimController()4718 void updateScrimController() { 4719 Trace.beginSection("StatusBar#updateScrimController"); 4720 4721 // We don't want to end up in KEYGUARD state when we're unlocking with 4722 // fingerprint from doze. We should cross fade directly from black. 4723 boolean wakeAndUnlocking = mFingerprintUnlockController.isWakeAndUnlock(); 4724 4725 // Do not animate the scrim expansion when triggered by the fingerprint sensor. 4726 mScrimController.setExpansionAffectsAlpha( 4727 !mFingerprintUnlockController.isFingerprintUnlock()); 4728 4729 if (mBouncerShowing) { 4730 // Bouncer needs the front scrim when it's on top of an activity, 4731 // tapping on a notification, editing QS or being dismissed by 4732 // FLAG_DISMISS_KEYGUARD_ACTIVITY. 4733 ScrimState state = mIsOccluded || mStatusBarKeyguardViewManager.bouncerNeedsScrimming() 4734 || mStatusBarKeyguardViewManager.willDismissWithAction() 4735 || mStatusBarKeyguardViewManager.isFullscreenBouncer() ? 4736 ScrimState.BOUNCER_SCRIMMED : ScrimState.BOUNCER; 4737 mScrimController.transitionTo(state); 4738 } else if (mLaunchCameraOnScreenTurningOn || isInLaunchTransition()) { 4739 mScrimController.transitionTo(ScrimState.UNLOCKED, mUnlockScrimCallback); 4740 } else if (mBrightnessMirrorVisible) { 4741 mScrimController.transitionTo(ScrimState.BRIGHTNESS_MIRROR); 4742 } else if (isPulsing()) { 4743 // Handled in DozeScrimController#setPulsing 4744 } else if (mDozing) { 4745 mScrimController.transitionTo(ScrimState.AOD); 4746 } else if (mIsKeyguard && !wakeAndUnlocking) { 4747 mScrimController.transitionTo(ScrimState.KEYGUARD); 4748 } else { 4749 mScrimController.transitionTo(ScrimState.UNLOCKED, mUnlockScrimCallback); 4750 } 4751 Trace.endSection(); 4752 } 4753 isKeyguardShowing()4754 public boolean isKeyguardShowing() { 4755 if (mStatusBarKeyguardViewManager == null) { 4756 Slog.i(TAG, "isKeyguardShowing() called before startKeyguard(), returning true"); 4757 return true; 4758 } 4759 return mStatusBarKeyguardViewManager.isShowing(); 4760 } 4761 4762 private final class DozeServiceHost implements DozeHost { 4763 private final ArrayList<Callback> mCallbacks = new ArrayList<>(); 4764 private boolean mAnimateWakeup; 4765 private boolean mAnimateScreenOff; 4766 private boolean mIgnoreTouchWhilePulsing; 4767 4768 @Override toString()4769 public String toString() { 4770 return "PSB.DozeServiceHost[mCallbacks=" + mCallbacks.size() + "]"; 4771 } 4772 firePowerSaveChanged(boolean active)4773 public void firePowerSaveChanged(boolean active) { 4774 for (Callback callback : mCallbacks) { 4775 callback.onPowerSaveChanged(active); 4776 } 4777 } 4778 fireNotificationHeadsUp()4779 public void fireNotificationHeadsUp() { 4780 for (Callback callback : mCallbacks) { 4781 callback.onNotificationHeadsUp(); 4782 } 4783 } 4784 4785 @Override addCallback(@onNull Callback callback)4786 public void addCallback(@NonNull Callback callback) { 4787 mCallbacks.add(callback); 4788 } 4789 4790 @Override removeCallback(@onNull Callback callback)4791 public void removeCallback(@NonNull Callback callback) { 4792 mCallbacks.remove(callback); 4793 } 4794 4795 @Override startDozing()4796 public void startDozing() { 4797 if (!mDozingRequested) { 4798 mDozingRequested = true; 4799 DozeLog.traceDozing(mContext, mDozing); 4800 updateDozing(); 4801 updateIsKeyguard(); 4802 } 4803 } 4804 4805 @Override pulseWhileDozing(@onNull PulseCallback callback, int reason)4806 public void pulseWhileDozing(@NonNull PulseCallback callback, int reason) { 4807 if (reason == DozeLog.PULSE_REASON_SENSOR_LONG_PRESS) { 4808 mPowerManager.wakeUp(SystemClock.uptimeMillis(), "com.android.systemui:NODOZE"); 4809 startAssist(new Bundle()); 4810 return; 4811 } 4812 4813 mDozeScrimController.pulse(new PulseCallback() { 4814 @Override 4815 public void onPulseStarted() { 4816 callback.onPulseStarted(); 4817 if (mHeadsUpManager.hasHeadsUpNotifications()) { 4818 // Only pulse the stack scroller if there's actually something to show. 4819 // Otherwise just show the always-on screen. 4820 setPulsing(true); 4821 } 4822 } 4823 4824 @Override 4825 public void onPulseFinished() { 4826 callback.onPulseFinished(); 4827 setPulsing(false); 4828 } 4829 4830 private void setPulsing(boolean pulsing) { 4831 mNotificationPanel.setPulsing(pulsing); 4832 mVisualStabilityManager.setPulsing(pulsing); 4833 mIgnoreTouchWhilePulsing = false; 4834 } 4835 }, reason); 4836 } 4837 4838 @Override stopDozing()4839 public void stopDozing() { 4840 if (mDozingRequested) { 4841 mDozingRequested = false; 4842 DozeLog.traceDozing(mContext, mDozing); 4843 mWakefulnessLifecycle.dispatchStartedWakingUp(); 4844 updateDozing(); 4845 } 4846 } 4847 4848 @Override onIgnoreTouchWhilePulsing(boolean ignore)4849 public void onIgnoreTouchWhilePulsing(boolean ignore) { 4850 if (ignore != mIgnoreTouchWhilePulsing) { 4851 DozeLog.tracePulseTouchDisabledByProx(mContext, ignore); 4852 } 4853 mIgnoreTouchWhilePulsing = ignore; 4854 if (isDozing() && ignore) { 4855 mStatusBarWindow.cancelCurrentTouch(); 4856 } 4857 } 4858 4859 @Override dozeTimeTick()4860 public void dozeTimeTick() { 4861 mNotificationPanel.dozeTimeTick(); 4862 } 4863 4864 @Override isPowerSaveActive()4865 public boolean isPowerSaveActive() { 4866 return mBatteryController.isAodPowerSave(); 4867 } 4868 4869 @Override isPulsingBlocked()4870 public boolean isPulsingBlocked() { 4871 return mFingerprintUnlockController.getMode() 4872 == FingerprintUnlockController.MODE_WAKE_AND_UNLOCK; 4873 } 4874 4875 @Override isProvisioned()4876 public boolean isProvisioned() { 4877 return mDeviceProvisionedController.isDeviceProvisioned() 4878 && mDeviceProvisionedController.isCurrentUserSetup(); 4879 } 4880 4881 @Override isBlockingDoze()4882 public boolean isBlockingDoze() { 4883 if (mFingerprintUnlockController.hasPendingAuthentication()) { 4884 Log.i(TAG, "Blocking AOD because fingerprint has authenticated"); 4885 return true; 4886 } 4887 return false; 4888 } 4889 4890 @Override startPendingIntentDismissingKeyguard(PendingIntent intent)4891 public void startPendingIntentDismissingKeyguard(PendingIntent intent) { 4892 StatusBar.this.startPendingIntentDismissingKeyguard(intent); 4893 } 4894 4895 @Override extendPulse()4896 public void extendPulse() { 4897 mDozeScrimController.extendPulse(); 4898 } 4899 4900 @Override setAnimateWakeup(boolean animateWakeup)4901 public void setAnimateWakeup(boolean animateWakeup) { 4902 if (mWakefulnessLifecycle.getWakefulness() == WAKEFULNESS_AWAKE 4903 || mWakefulnessLifecycle.getWakefulness() == WAKEFULNESS_WAKING) { 4904 // Too late to change the wakeup animation. 4905 return; 4906 } 4907 mAnimateWakeup = animateWakeup; 4908 } 4909 4910 @Override setAnimateScreenOff(boolean animateScreenOff)4911 public void setAnimateScreenOff(boolean animateScreenOff) { 4912 mAnimateScreenOff = animateScreenOff; 4913 } 4914 4915 @Override onDoubleTap(float screenX, float screenY)4916 public void onDoubleTap(float screenX, float screenY) { 4917 if (screenX > 0 && screenY > 0 && mAmbientIndicationContainer != null 4918 && mAmbientIndicationContainer.getVisibility() == View.VISIBLE) { 4919 mAmbientIndicationContainer.getLocationOnScreen(mTmpInt2); 4920 float viewX = screenX - mTmpInt2[0]; 4921 float viewY = screenY - mTmpInt2[1]; 4922 if (0 <= viewX && viewX <= mAmbientIndicationContainer.getWidth() 4923 && 0 <= viewY && viewY <= mAmbientIndicationContainer.getHeight()) { 4924 dispatchDoubleTap(viewX, viewY); 4925 } 4926 } 4927 } 4928 4929 @Override setDozeScreenBrightness(int value)4930 public void setDozeScreenBrightness(int value) { 4931 mStatusBarWindowManager.setDozeScreenBrightness(value); 4932 } 4933 4934 @Override setAodDimmingScrim(float scrimOpacity)4935 public void setAodDimmingScrim(float scrimOpacity) { 4936 mScrimController.setAodFrontScrimAlpha(scrimOpacity); 4937 } 4938 dispatchDoubleTap(float viewX, float viewY)4939 public void dispatchDoubleTap(float viewX, float viewY) { 4940 dispatchTap(mAmbientIndicationContainer, viewX, viewY); 4941 dispatchTap(mAmbientIndicationContainer, viewX, viewY); 4942 } 4943 dispatchTap(View view, float x, float y)4944 private void dispatchTap(View view, float x, float y) { 4945 long now = SystemClock.elapsedRealtime(); 4946 dispatchTouchEvent(view, x, y, now, MotionEvent.ACTION_DOWN); 4947 dispatchTouchEvent(view, x, y, now, MotionEvent.ACTION_UP); 4948 } 4949 dispatchTouchEvent(View view, float x, float y, long now, int action)4950 private void dispatchTouchEvent(View view, float x, float y, long now, int action) { 4951 MotionEvent ev = MotionEvent.obtain(now, now, action, x, y, 0 /* meta */); 4952 view.dispatchTouchEvent(ev); 4953 ev.recycle(); 4954 } 4955 shouldAnimateWakeup()4956 private boolean shouldAnimateWakeup() { 4957 return mAnimateWakeup; 4958 } 4959 shouldAnimateScreenOff()4960 public boolean shouldAnimateScreenOff() { 4961 return mAnimateScreenOff; 4962 } 4963 } 4964 shouldIgnoreTouch()4965 public boolean shouldIgnoreTouch() { 4966 return isDozing() && mDozeServiceHost.mIgnoreTouchWhilePulsing; 4967 } 4968 4969 // Begin Extra BaseStatusBar methods. 4970 4971 protected CommandQueue mCommandQueue; 4972 protected IStatusBarService mBarService; 4973 4974 // all notifications 4975 protected NotificationStackScrollLayout mStackScroller; 4976 4977 protected NotificationGroupManager mGroupManager; 4978 4979 4980 // for heads up notifications 4981 protected HeadsUpManagerPhone mHeadsUpManager; 4982 4983 private AboveShelfObserver mAboveShelfObserver; 4984 4985 // handling reordering 4986 protected VisualStabilityManager mVisualStabilityManager; 4987 4988 protected AccessibilityManager mAccessibilityManager; 4989 4990 protected boolean mDeviceInteractive; 4991 4992 protected boolean mVisible; 4993 4994 // mScreenOnFromKeyguard && mVisible. 4995 private boolean mVisibleToUser; 4996 4997 protected DevicePolicyManager mDevicePolicyManager; 4998 protected PowerManager mPowerManager; 4999 protected StatusBarKeyguardViewManager mStatusBarKeyguardViewManager; 5000 5001 protected KeyguardManager mKeyguardManager; 5002 private LockPatternUtils mLockPatternUtils; 5003 private DeviceProvisionedController mDeviceProvisionedController 5004 = Dependency.get(DeviceProvisionedController.class); 5005 5006 // UI-specific methods 5007 5008 protected WindowManager mWindowManager; 5009 protected IWindowManager mWindowManagerService; 5010 5011 protected Display mDisplay; 5012 5013 protected RecentsComponent mRecents; 5014 5015 protected NotificationShelf mNotificationShelf; 5016 protected FooterView mFooterView; 5017 protected EmptyShadeView mEmptyShadeView; 5018 5019 protected AssistManager mAssistManager; 5020 5021 protected boolean mVrMode; 5022 isDeviceInteractive()5023 public boolean isDeviceInteractive() { 5024 return mDeviceInteractive; 5025 } 5026 5027 @Override // NotificationData.Environment isDeviceProvisioned()5028 public boolean isDeviceProvisioned() { 5029 return mDeviceProvisionedController.isDeviceProvisioned(); 5030 } 5031 5032 private final IVrStateCallbacks mVrStateCallbacks = new IVrStateCallbacks.Stub() { 5033 @Override 5034 public void onVrStateChanged(boolean enabled) { 5035 mVrMode = enabled; 5036 } 5037 }; 5038 isDeviceInVrMode()5039 public boolean isDeviceInVrMode() { 5040 return mVrMode; 5041 } 5042 5043 private final BroadcastReceiver mBannerActionBroadcastReceiver = new BroadcastReceiver() { 5044 @Override 5045 public void onReceive(Context context, Intent intent) { 5046 String action = intent.getAction(); 5047 if (BANNER_ACTION_CANCEL.equals(action) || BANNER_ACTION_SETUP.equals(action)) { 5048 NotificationManager noMan = (NotificationManager) 5049 mContext.getSystemService(Context.NOTIFICATION_SERVICE); 5050 noMan.cancel(com.android.internal.messages.nano.SystemMessageProto.SystemMessage. 5051 NOTE_HIDDEN_NOTIFICATIONS); 5052 5053 Settings.Secure.putInt(mContext.getContentResolver(), 5054 Settings.Secure.SHOW_NOTE_ABOUT_NOTIFICATION_HIDING, 0); 5055 if (BANNER_ACTION_SETUP.equals(action)) { 5056 animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL, 5057 true /* force */); 5058 mContext.startActivity(new Intent(Settings.ACTION_APP_NOTIFICATION_REDACTION) 5059 .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) 5060 5061 ); 5062 } 5063 } 5064 } 5065 }; 5066 5067 @Override onNotificationClicked(StatusBarNotification sbn, ExpandableNotificationRow row)5068 public void onNotificationClicked(StatusBarNotification sbn, ExpandableNotificationRow row) { 5069 RemoteInputController controller = mRemoteInputManager.getController(); 5070 if (controller.isRemoteInputActive(row.getEntry()) 5071 && !TextUtils.isEmpty(row.getActiveRemoteInputText())) { 5072 // We have an active remote input typed and the user clicked on the notification. 5073 // this was probably unintentional, so we're closing the edit text instead. 5074 controller.closeRemoteInputs(); 5075 return; 5076 } 5077 Notification notification = sbn.getNotification(); 5078 final PendingIntent intent = notification.contentIntent != null 5079 ? notification.contentIntent 5080 : notification.fullScreenIntent; 5081 final String notificationKey = sbn.getKey(); 5082 5083 final boolean afterKeyguardGone = intent.isActivity() 5084 && PreviewInflater.wouldLaunchResolverActivity(mContext, intent.getIntent(), 5085 mLockscreenUserManager.getCurrentUserId()); 5086 final boolean wasOccluded = mIsOccluded; 5087 dismissKeyguardThenExecute(() -> { 5088 // TODO: Some of this code may be able to move to NotificationEntryManager. 5089 if (mHeadsUpManager != null && mHeadsUpManager.isHeadsUp(notificationKey)) { 5090 // Release the HUN notification to the shade. 5091 5092 if (isPresenterFullyCollapsed()) { 5093 HeadsUpUtil.setIsClickedHeadsUpNotification(row, true); 5094 } 5095 // 5096 // In most cases, when FLAG_AUTO_CANCEL is set, the notification will 5097 // become canceled shortly by NoMan, but we can't assume that. 5098 mHeadsUpManager.releaseImmediately(notificationKey); 5099 } 5100 StatusBarNotification parentToCancel = null; 5101 if (shouldAutoCancel(sbn) && mGroupManager.isOnlyChildInGroup(sbn)) { 5102 StatusBarNotification summarySbn = 5103 mGroupManager.getLogicalGroupSummary(sbn).getStatusBarNotification(); 5104 if (shouldAutoCancel(summarySbn)) { 5105 parentToCancel = summarySbn; 5106 } 5107 } 5108 final StatusBarNotification parentToCancelFinal = parentToCancel; 5109 final Runnable runnable = () -> { 5110 try { 5111 // The intent we are sending is for the application, which 5112 // won't have permission to immediately start an activity after 5113 // the user switches to home. We know it is safe to do at this 5114 // point, so make sure new activity switches are now allowed. 5115 ActivityManager.getService().resumeAppSwitches(); 5116 } catch (RemoteException e) { 5117 } 5118 int launchResult = ActivityManager.START_CANCELED; 5119 if (intent != null) { 5120 // If we are launching a work activity and require to launch 5121 // separate work challenge, we defer the activity action and cancel 5122 // notification until work challenge is unlocked. 5123 if (intent.isActivity()) { 5124 final int userId = intent.getCreatorUserHandle().getIdentifier(); 5125 if (mLockPatternUtils.isSeparateProfileChallengeEnabled(userId) 5126 && mKeyguardManager.isDeviceLocked(userId)) { 5127 // TODO(b/28935539): should allow certain activities to 5128 // bypass work challenge 5129 if (startWorkChallengeIfNecessary(userId, intent.getIntentSender(), 5130 notificationKey)) { 5131 // Show work challenge, do not run PendingIntent and 5132 // remove notification 5133 collapseOnMainThread(); 5134 return; 5135 } 5136 } 5137 } 5138 Intent fillInIntent = null; 5139 Entry entry = row.getEntry(); 5140 CharSequence remoteInputText = null; 5141 if (!TextUtils.isEmpty(entry.remoteInputText)) { 5142 remoteInputText = entry.remoteInputText; 5143 } 5144 if (!TextUtils.isEmpty(remoteInputText) 5145 && !controller.isSpinning(entry.key)) { 5146 fillInIntent = new Intent().putExtra(Notification.EXTRA_REMOTE_INPUT_DRAFT, 5147 remoteInputText.toString()); 5148 } 5149 RemoteAnimationAdapter adapter = mActivityLaunchAnimator.getLaunchAnimation( 5150 row, wasOccluded); 5151 try { 5152 if (adapter != null) { 5153 ActivityManager.getService() 5154 .registerRemoteAnimationForNextActivityStart( 5155 intent.getCreatorPackage(), adapter); 5156 } 5157 launchResult = intent.sendAndReturnResult(mContext, 0, fillInIntent, null, 5158 null, null, getActivityOptions(adapter)); 5159 mActivityLaunchAnimator.setLaunchResult(launchResult); 5160 } catch (RemoteException | PendingIntent.CanceledException e) { 5161 // the stack trace isn't very helpful here. 5162 // Just log the exception message. 5163 Log.w(TAG, "Sending contentIntent failed: " + e); 5164 5165 // TODO: Dismiss Keyguard. 5166 } 5167 if (intent.isActivity()) { 5168 mAssistManager.hideAssist(); 5169 } 5170 } 5171 if (shouldCollapse()) { 5172 collapseOnMainThread(); 5173 } 5174 5175 final int count = 5176 mEntryManager.getNotificationData().getActiveNotifications().size(); 5177 final int rank = mEntryManager.getNotificationData().getRank(notificationKey); 5178 final NotificationVisibility nv = NotificationVisibility.obtain(notificationKey, 5179 rank, count, true); 5180 try { 5181 mBarService.onNotificationClick(notificationKey, nv); 5182 } catch (RemoteException ex) { 5183 // system process is dead if we're here. 5184 } 5185 if (parentToCancelFinal != null) { 5186 removeNotification(parentToCancelFinal); 5187 } 5188 if (shouldAutoCancel(sbn) 5189 || mEntryManager.isNotificationKeptForRemoteInput(notificationKey)) { 5190 // Automatically remove all notifications that we may have kept around longer 5191 removeNotification(sbn); 5192 } 5193 }; 5194 5195 if (mStatusBarKeyguardViewManager.isShowing() 5196 && mStatusBarKeyguardViewManager.isOccluded()) { 5197 mStatusBarKeyguardViewManager.addAfterKeyguardGoneRunnable(runnable); 5198 collapsePanel(true /* animate */); 5199 } else { 5200 new Thread(runnable).start(); 5201 } 5202 5203 return !mNotificationPanel.isFullyCollapsed(); 5204 }, afterKeyguardGone); 5205 } 5206 collapseOnMainThread()5207 private void collapseOnMainThread() { 5208 if (Looper.getMainLooper().isCurrentThread()) { 5209 collapsePanel(); 5210 } else { 5211 mStackScroller.post(this::collapsePanel); 5212 } 5213 } 5214 shouldCollapse()5215 private boolean shouldCollapse() { 5216 return mState != StatusBarState.SHADE || !mActivityLaunchAnimator.isAnimationPending(); 5217 } 5218 collapsePanel(boolean animate)5219 public void collapsePanel(boolean animate) { 5220 if (animate) { 5221 collapsePanel(); 5222 } else if (!isPresenterFullyCollapsed()) { 5223 instantCollapseNotificationPanel(); 5224 visibilityChanged(false); 5225 } else { 5226 runPostCollapseRunnables(); 5227 } 5228 } 5229 collapsePanel()5230 private boolean collapsePanel() { 5231 if (!mNotificationPanel.isFullyCollapsed()) { 5232 // close the shade if it was open 5233 animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL, true /* force */, 5234 true /* delayed */); 5235 visibilityChanged(false); 5236 5237 return true; 5238 } else { 5239 return false; 5240 } 5241 } 5242 removeNotification(StatusBarNotification notification)5243 private void removeNotification(StatusBarNotification notification) { 5244 // We have to post it to the UI thread for synchronization 5245 mHandler.post(() -> { 5246 Runnable removeRunnable = 5247 () -> mEntryManager.performRemoveNotification(notification); 5248 if (isCollapsing()) { 5249 // To avoid lags we're only performing the remove 5250 // after the shade was collapsed 5251 addPostCollapseAction(removeRunnable); 5252 } else { 5253 removeRunnable.run(); 5254 } 5255 }); 5256 } 5257 5258 protected NotificationListener mNotificationListener; 5259 5260 @Override // NotificationData.Environment isNotificationForCurrentProfiles(StatusBarNotification n)5261 public boolean isNotificationForCurrentProfiles(StatusBarNotification n) { 5262 final int notificationUserId = n.getUserId(); 5263 if (DEBUG && MULTIUSER_DEBUG) { 5264 Log.v(TAG, String.format("%s: current userid: %d, notification userid: %d", n, 5265 mLockscreenUserManager.getCurrentUserId(), notificationUserId)); 5266 } 5267 return mLockscreenUserManager.isCurrentProfile(notificationUserId); 5268 } 5269 5270 @Override getGroupManager()5271 public NotificationGroupManager getGroupManager() { 5272 return mGroupManager; 5273 } 5274 5275 @Override startNotificationGutsIntent(final Intent intent, final int appUid, ExpandableNotificationRow row)5276 public void startNotificationGutsIntent(final Intent intent, final int appUid, 5277 ExpandableNotificationRow row) { 5278 dismissKeyguardThenExecute(() -> { 5279 AsyncTask.execute(() -> { 5280 int launchResult = TaskStackBuilder.create(mContext) 5281 .addNextIntentWithParentStack(intent) 5282 .startActivities(getActivityOptions( 5283 mActivityLaunchAnimator.getLaunchAnimation(row, mIsOccluded)), 5284 new UserHandle(UserHandle.getUserId(appUid))); 5285 mActivityLaunchAnimator.setLaunchResult(launchResult); 5286 if (shouldCollapse()) { 5287 // Putting it back on the main thread, since we're touching views 5288 mStatusBarWindow.post(() -> animateCollapsePanels( 5289 CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL, true /* force */)); 5290 } 5291 }); 5292 return true; 5293 }, false /* afterKeyguardGone */); 5294 } 5295 setNotificationSnoozed(StatusBarNotification sbn, SnoozeOption snoozeOption)5296 public void setNotificationSnoozed(StatusBarNotification sbn, SnoozeOption snoozeOption) { 5297 if (snoozeOption.getSnoozeCriterion() != null) { 5298 mNotificationListener.snoozeNotification(sbn.getKey(), 5299 snoozeOption.getSnoozeCriterion().getId()); 5300 } else { 5301 mNotificationListener.snoozeNotification(sbn.getKey(), 5302 snoozeOption.getMinutesToSnoozeFor() * 60 * 1000); 5303 } 5304 } 5305 5306 @Override toggleSplitScreen()5307 public void toggleSplitScreen() { 5308 toggleSplitScreenMode(-1 /* metricsDockAction */, -1 /* metricsUndockAction */); 5309 } 5310 awakenDreams()5311 void awakenDreams() { 5312 SystemServicesProxy.getInstance(mContext).awakenDreamsAsync(); 5313 } 5314 5315 @Override preloadRecentApps()5316 public void preloadRecentApps() { 5317 int msg = MSG_PRELOAD_RECENT_APPS; 5318 mHandler.removeMessages(msg); 5319 mHandler.sendEmptyMessage(msg); 5320 } 5321 5322 @Override cancelPreloadRecentApps()5323 public void cancelPreloadRecentApps() { 5324 int msg = MSG_CANCEL_PRELOAD_RECENT_APPS; 5325 mHandler.removeMessages(msg); 5326 mHandler.sendEmptyMessage(msg); 5327 } 5328 5329 @Override dismissKeyboardShortcutsMenu()5330 public void dismissKeyboardShortcutsMenu() { 5331 int msg = MSG_DISMISS_KEYBOARD_SHORTCUTS_MENU; 5332 mHandler.removeMessages(msg); 5333 mHandler.sendEmptyMessage(msg); 5334 } 5335 5336 @Override toggleKeyboardShortcutsMenu(int deviceId)5337 public void toggleKeyboardShortcutsMenu(int deviceId) { 5338 int msg = MSG_TOGGLE_KEYBOARD_SHORTCUTS_MENU; 5339 mHandler.removeMessages(msg); 5340 mHandler.obtainMessage(msg, deviceId, 0).sendToTarget(); 5341 } 5342 5343 @Override setTopAppHidesStatusBar(boolean topAppHidesStatusBar)5344 public void setTopAppHidesStatusBar(boolean topAppHidesStatusBar) { 5345 mTopHidesStatusBar = topAppHidesStatusBar; 5346 if (!topAppHidesStatusBar && mWereIconsJustHidden) { 5347 // Immediately update the icon hidden state, since that should only apply if we're 5348 // staying fullscreen. 5349 mWereIconsJustHidden = false; 5350 recomputeDisableFlags(true); 5351 } 5352 updateHideIconsForBouncer(true /* animate */); 5353 } 5354 toggleKeyboardShortcuts(int deviceId)5355 protected void toggleKeyboardShortcuts(int deviceId) { 5356 KeyboardShortcuts.toggle(mContext, deviceId); 5357 } 5358 dismissKeyboardShortcuts()5359 protected void dismissKeyboardShortcuts() { 5360 KeyboardShortcuts.dismiss(); 5361 } 5362 5363 @Override // NotificationData.Environment shouldHideNotifications(int userId)5364 public boolean shouldHideNotifications(int userId) { 5365 return mLockscreenUserManager.shouldHideNotifications(userId); 5366 } 5367 5368 @Override // NotificationDate.Environment shouldHideNotifications(String key)5369 public boolean shouldHideNotifications(String key) { 5370 return mLockscreenUserManager.shouldHideNotifications(key); 5371 } 5372 5373 /** 5374 * Returns true if we're on a secure lockscreen. 5375 */ 5376 @Override // NotificationData.Environment isSecurelyLocked(int userId)5377 public boolean isSecurelyLocked(int userId) { 5378 return mLockscreenUserManager.isLockscreenPublicMode(userId); 5379 } 5380 5381 /** 5382 * Called when the notification panel layouts 5383 */ onPanelLaidOut()5384 public void onPanelLaidOut() { 5385 updateKeyguardMaxNotifications(); 5386 } 5387 updateKeyguardMaxNotifications()5388 public void updateKeyguardMaxNotifications() { 5389 if (mState == StatusBarState.KEYGUARD) { 5390 // Since the number of notifications is determined based on the height of the view, we 5391 // need to update them. 5392 int maxBefore = getMaxNotificationsWhileLocked(false /* recompute */); 5393 int maxNotifications = getMaxNotificationsWhileLocked(true /* recompute */); 5394 if (maxBefore != maxNotifications) { 5395 mViewHierarchyManager.updateRowStates(); 5396 } 5397 } 5398 } 5399 startPendingIntentDismissingKeyguard(final PendingIntent intent)5400 public void startPendingIntentDismissingKeyguard(final PendingIntent intent) { 5401 if (!isDeviceProvisioned()) return; 5402 5403 final boolean afterKeyguardGone = intent.isActivity() 5404 && PreviewInflater.wouldLaunchResolverActivity(mContext, intent.getIntent(), 5405 mLockscreenUserManager.getCurrentUserId()); 5406 dismissKeyguardThenExecute(() -> { 5407 new Thread(() -> { 5408 try { 5409 // The intent we are sending is for the application, which 5410 // won't have permission to immediately start an activity after 5411 // the user switches to home. We know it is safe to do at this 5412 // point, so make sure new activity switches are now allowed. 5413 ActivityManager.getService().resumeAppSwitches(); 5414 } catch (RemoteException e) { 5415 } 5416 try { 5417 intent.send(null, 0, null, null, null, null, getActivityOptions( 5418 null /* animationAdapter */)); 5419 } catch (PendingIntent.CanceledException e) { 5420 // the stack trace isn't very helpful here. 5421 // Just log the exception message. 5422 Log.w(TAG, "Sending intent failed: " + e); 5423 5424 // TODO: Dismiss Keyguard. 5425 } 5426 if (intent.isActivity()) { 5427 mAssistManager.hideAssist(); 5428 } 5429 }).start(); 5430 5431 return collapsePanel(); 5432 }, afterKeyguardGone); 5433 } 5434 shouldAutoCancel(StatusBarNotification sbn)5435 private boolean shouldAutoCancel(StatusBarNotification sbn) { 5436 int flags = sbn.getNotification().flags; 5437 if ((flags & Notification.FLAG_AUTO_CANCEL) != Notification.FLAG_AUTO_CANCEL) { 5438 return false; 5439 } 5440 if ((flags & Notification.FLAG_FOREGROUND_SERVICE) != 0) { 5441 return false; 5442 } 5443 return true; 5444 } 5445 getActivityOptions(@ullable RemoteAnimationAdapter animationAdapter)5446 protected Bundle getActivityOptions(@Nullable RemoteAnimationAdapter animationAdapter) { 5447 ActivityOptions options; 5448 if (animationAdapter != null) { 5449 options = ActivityOptions.makeRemoteAnimation(animationAdapter); 5450 } else { 5451 options = ActivityOptions.makeBasic(); 5452 } 5453 // Anything launched from the notification shade should always go into the secondary 5454 // split-screen windowing mode. 5455 options.setLaunchWindowingMode(WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY); 5456 return options.toBundle(); 5457 } 5458 visibilityChanged(boolean visible)5459 protected void visibilityChanged(boolean visible) { 5460 if (mVisible != visible) { 5461 mVisible = visible; 5462 if (!visible) { 5463 mGutsManager.closeAndSaveGuts(true /* removeLeavebehind */, true /* force */, 5464 true /* removeControls */, -1 /* x */, -1 /* y */, true /* resetMenu */); 5465 } 5466 } 5467 updateVisibleToUser(); 5468 } 5469 updateVisibleToUser()5470 protected void updateVisibleToUser() { 5471 boolean oldVisibleToUser = mVisibleToUser; 5472 mVisibleToUser = mVisible && mDeviceInteractive; 5473 5474 if (oldVisibleToUser != mVisibleToUser) { 5475 handleVisibleToUserChanged(mVisibleToUser); 5476 } 5477 } 5478 5479 /** 5480 * Clear Buzz/Beep/Blink. 5481 */ clearNotificationEffects()5482 public void clearNotificationEffects() { 5483 try { 5484 mBarService.clearNotificationEffects(); 5485 } catch (RemoteException e) { 5486 // Won't fail unless the world has ended. 5487 } 5488 } 5489 5490 /** 5491 * Updates expanded, dimmed and locked states of notification rows. 5492 */ 5493 @Override onUpdateRowStates()5494 public void onUpdateRowStates() { 5495 // The following views will be moved to the end of mStackScroller. This counter represents 5496 // the offset from the last child. Initialized to 1 for the very last position. It is post- 5497 // incremented in the following "changeViewPosition" calls so that its value is correct for 5498 // subsequent calls. 5499 int offsetFromEnd = 1; 5500 if (mFooterView != null) { 5501 mStackScroller.changeViewPosition(mFooterView, 5502 mStackScroller.getChildCount() - offsetFromEnd++); 5503 } 5504 5505 mStackScroller.changeViewPosition(mEmptyShadeView, 5506 mStackScroller.getChildCount() - offsetFromEnd++); 5507 5508 // No post-increment for this call because it is the last one. Make sure to add one if 5509 // another "changeViewPosition" call is ever added. 5510 mStackScroller.changeViewPosition(mNotificationShelf, 5511 mStackScroller.getChildCount() - offsetFromEnd); 5512 5513 // Scrim opacity varies based on notification count 5514 mScrimController.setNotificationCount(mStackScroller.getNotGoneChildCount()); 5515 } 5516 notifyHeadsUpGoingToSleep()5517 protected void notifyHeadsUpGoingToSleep() { 5518 maybeEscalateHeadsUp(); 5519 } 5520 5521 /** 5522 * @return Whether the security bouncer from Keyguard is showing. 5523 */ isBouncerShowing()5524 public boolean isBouncerShowing() { 5525 return mBouncerShowing; 5526 } 5527 5528 /** 5529 * @return a PackageManger for userId or if userId is < 0 (USER_ALL etc) then 5530 * return PackageManager for mContext 5531 */ getPackageManagerForUser(Context context, int userId)5532 public static PackageManager getPackageManagerForUser(Context context, int userId) { 5533 Context contextForUser = context; 5534 // UserHandle defines special userId as negative values, e.g. USER_ALL 5535 if (userId >= 0) { 5536 try { 5537 // Create a context for the correct user so if a package isn't installed 5538 // for user 0 we can still load information about the package. 5539 contextForUser = 5540 context.createPackageContextAsUser(context.getPackageName(), 5541 Context.CONTEXT_RESTRICTED, 5542 new UserHandle(userId)); 5543 } catch (NameNotFoundException e) { 5544 // Shouldn't fail to find the package name for system ui. 5545 } 5546 } 5547 return contextForUser.getPackageManager(); 5548 } 5549 isKeyguardSecure()5550 public boolean isKeyguardSecure() { 5551 if (mStatusBarKeyguardViewManager == null) { 5552 // startKeyguard() hasn't been called yet, so we don't know. 5553 // Make sure anything that needs to know isKeyguardSecure() checks and re-checks this 5554 // value onVisibilityChanged(). 5555 Slog.w(TAG, "isKeyguardSecure() called before startKeyguard(), returning false", 5556 new Throwable()); 5557 return false; 5558 } 5559 return mStatusBarKeyguardViewManager.isSecure(); 5560 } 5561 5562 @Override onZenChanged(int zen)5563 public void onZenChanged(int zen) { 5564 updateEmptyShadeView(); 5565 } 5566 5567 @Override showAssistDisclosure()5568 public void showAssistDisclosure() { 5569 if (mAssistManager != null) { 5570 mAssistManager.showDisclosure(); 5571 } 5572 } 5573 getPanel()5574 public NotificationPanelView getPanel() { 5575 return mNotificationPanel; 5576 } 5577 5578 @Override startAssist(Bundle args)5579 public void startAssist(Bundle args) { 5580 if (mAssistManager != null) { 5581 mAssistManager.startAssist(args); 5582 } 5583 } 5584 // End Extra BaseStatusBarMethods. 5585 5586 private final Runnable mAutoDim = () -> { 5587 if (mNavigationBar != null) { 5588 mNavigationBar.getBarTransitions().setAutoDim(true); 5589 } 5590 }; 5591 getGutsManager()5592 public NotificationGutsManager getGutsManager() { 5593 return mGutsManager; 5594 } 5595 5596 @Override isPresenterLocked()5597 public boolean isPresenterLocked() { 5598 return mState == StatusBarState.KEYGUARD; 5599 } 5600 5601 @Override getHandler()5602 public Handler getHandler() { 5603 return mHandler; 5604 } 5605 5606 private final NotificationInfo.CheckSaveListener mCheckSaveListener = 5607 (Runnable saveImportance, StatusBarNotification sbn) -> { 5608 // If the user has security enabled, show challenge if the setting is changed. 5609 if (mLockscreenUserManager.isLockscreenPublicMode(sbn.getUser().getIdentifier()) 5610 && (mState == StatusBarState.KEYGUARD || 5611 mState == StatusBarState.SHADE_LOCKED)) { 5612 onLockedNotificationImportanceChange(() -> { 5613 saveImportance.run(); 5614 return true; 5615 }); 5616 } else { 5617 saveImportance.run(); 5618 } 5619 }; 5620 } 5621