1 /* 2 * Copyright (C) 2014 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 com.android.keyguard.KeyguardHostView.OnDismissAction; 20 import static com.android.systemui.statusbar.phone.FingerprintUnlockController.MODE_WAKE_AND_UNLOCK; 21 import static com.android.systemui.statusbar.phone.FingerprintUnlockController.MODE_WAKE_AND_UNLOCK_PULSING; 22 23 import android.content.ComponentCallbacks2; 24 import android.content.Context; 25 import android.os.Bundle; 26 import android.os.SystemClock; 27 import android.util.StatsLog; 28 import android.view.KeyEvent; 29 import android.view.View; 30 import android.view.ViewGroup; 31 import android.view.ViewRootImpl; 32 import android.view.WindowManagerGlobal; 33 34 import com.android.internal.annotations.VisibleForTesting; 35 import com.android.internal.util.LatencyTracker; 36 import com.android.internal.widget.LockPatternUtils; 37 import com.android.keyguard.KeyguardUpdateMonitor; 38 import com.android.keyguard.KeyguardUpdateMonitorCallback; 39 import com.android.keyguard.ViewMediatorCallback; 40 import com.android.systemui.DejankUtils; 41 import com.android.systemui.Dependency; 42 import com.android.systemui.SystemUIFactory; 43 import com.android.systemui.keyguard.DismissCallbackRegistry; 44 import com.android.systemui.statusbar.CommandQueue; 45 import com.android.systemui.statusbar.RemoteInputController; 46 import com.android.systemui.statusbar.phone.KeyguardBouncer.BouncerExpansionCallback; 47 48 import java.io.PrintWriter; 49 import java.util.ArrayList; 50 51 /** 52 * Manages creating, showing, hiding and resetting the keyguard within the status bar. Calls back 53 * via {@link ViewMediatorCallback} to poke the wake lock and report that the keyguard is done, 54 * which is in turn, reported to this class by the current 55 * {@link com.android.keyguard.KeyguardViewBase}. 56 */ 57 public class StatusBarKeyguardViewManager implements RemoteInputController.Callback { 58 59 // When hiding the Keyguard with timing supplied from WindowManager, better be early than late. 60 private static final long HIDE_TIMING_CORRECTION_MS = - 16 * 3; 61 62 // Delay for showing the navigation bar when the bouncer appears. This should be kept in sync 63 // with the appear animations of the PIN/pattern/password views. 64 private static final long NAV_BAR_SHOW_DELAY_BOUNCER = 320; 65 66 private static final long WAKE_AND_UNLOCK_SCRIM_FADEOUT_DURATION_MS = 200; 67 68 // Duration of the Keyguard dismissal animation in case the user is currently locked. This is to 69 // make everything a bit slower to bridge a gap until the user is unlocked and home screen has 70 // dranw its first frame. 71 private static final long KEYGUARD_DISMISS_DURATION_LOCKED = 2000; 72 73 private static String TAG = "StatusBarKeyguardViewManager"; 74 75 protected final Context mContext; 76 private final StatusBarWindowManager mStatusBarWindowManager; 77 private final BouncerExpansionCallback mExpansionCallback = new BouncerExpansionCallback() { 78 @Override 79 public void onFullyShown() { 80 updateStates(); 81 } 82 83 @Override 84 public void onFullyHidden() { 85 updateStates(); 86 } 87 }; 88 89 protected LockPatternUtils mLockPatternUtils; 90 protected ViewMediatorCallback mViewMediatorCallback; 91 protected StatusBar mStatusBar; 92 private NotificationPanelView mNotificationPanelView; 93 private FingerprintUnlockController mFingerprintUnlockController; 94 95 private ViewGroup mContainer; 96 97 protected KeyguardBouncer mBouncer; 98 protected boolean mShowing; 99 protected boolean mOccluded; 100 protected boolean mRemoteInputActive; 101 private boolean mDozing; 102 103 protected boolean mFirstUpdate = true; 104 protected boolean mLastShowing; 105 protected boolean mLastOccluded; 106 private boolean mLastBouncerShowing; 107 private boolean mLastBouncerDismissible; 108 protected boolean mLastRemoteInputActive; 109 private boolean mLastDozing; 110 private int mLastFpMode; 111 private boolean mGoingToSleepVisibleNotOccluded; 112 113 private OnDismissAction mAfterKeyguardGoneAction; 114 private final ArrayList<Runnable> mAfterKeyguardGoneRunnables = new ArrayList<>(); 115 116 // Dismiss action to be launched when we stop dozing or the keyguard is gone. 117 private DismissWithActionRequest mPendingWakeupAction; 118 119 private final KeyguardUpdateMonitorCallback mUpdateMonitorCallback = 120 new KeyguardUpdateMonitorCallback() { 121 @Override 122 public void onEmergencyCallAction() { 123 124 // Since we won't get a setOccluded call we have to reset the view manually such that 125 // the bouncer goes away. 126 if (mOccluded) { 127 reset(true /* hideBouncerWhenShowing */); 128 } 129 } 130 }; 131 StatusBarKeyguardViewManager(Context context, ViewMediatorCallback callback, LockPatternUtils lockPatternUtils)132 public StatusBarKeyguardViewManager(Context context, ViewMediatorCallback callback, 133 LockPatternUtils lockPatternUtils) { 134 mContext = context; 135 mViewMediatorCallback = callback; 136 mLockPatternUtils = lockPatternUtils; 137 mStatusBarWindowManager = Dependency.get(StatusBarWindowManager.class); 138 KeyguardUpdateMonitor.getInstance(context).registerCallback(mUpdateMonitorCallback); 139 } 140 registerStatusBar(StatusBar statusBar, ViewGroup container, NotificationPanelView notificationPanelView, FingerprintUnlockController fingerprintUnlockController, DismissCallbackRegistry dismissCallbackRegistry)141 public void registerStatusBar(StatusBar statusBar, 142 ViewGroup container, 143 NotificationPanelView notificationPanelView, 144 FingerprintUnlockController fingerprintUnlockController, 145 DismissCallbackRegistry dismissCallbackRegistry) { 146 mStatusBar = statusBar; 147 mContainer = container; 148 mFingerprintUnlockController = fingerprintUnlockController; 149 mBouncer = SystemUIFactory.getInstance().createKeyguardBouncer(mContext, 150 mViewMediatorCallback, mLockPatternUtils, container, dismissCallbackRegistry, 151 mExpansionCallback); 152 mContainer.addOnLayoutChangeListener(this::onContainerLayout); 153 mNotificationPanelView = notificationPanelView; 154 notificationPanelView.setExpansionListener(this::onPanelExpansionChanged); 155 } 156 onContainerLayout(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom)157 private void onContainerLayout(View v, int left, int top, int right, int bottom, 158 int oldLeft, int oldTop, int oldRight, int oldBottom) { 159 mNotificationPanelView.setBouncerTop(mBouncer.getTop()); 160 } 161 162 @VisibleForTesting onPanelExpansionChanged(float expansion, boolean tracking)163 void onPanelExpansionChanged(float expansion, boolean tracking) { 164 // We don't want to translate the bounce when: 165 // • Keyguard is occluded, because we're in a FLAG_SHOW_WHEN_LOCKED activity and need to 166 // conserve the original animation. 167 // • The user quickly taps on the display and we show "swipe up to unlock." 168 // • Keyguard will be dismissed by an action. a.k.a: FLAG_DISMISS_KEYGUARD_ACTIVITY 169 // • Full-screen user switcher is displayed. 170 if (mNotificationPanelView.isUnlockHintRunning()) { 171 mBouncer.setExpansion(KeyguardBouncer.EXPANSION_HIDDEN); 172 } else if (mOccluded || mBouncer.willDismissWithAction() || mBouncer.isShowingScrimmed() 173 || mStatusBar.isFullScreenUserSwitcherState()) { 174 mBouncer.setExpansion(KeyguardBouncer.EXPANSION_VISIBLE); 175 } else if (mShowing && !mDozing) { 176 if (!isWakeAndUnlocking()) { 177 mBouncer.setExpansion(expansion); 178 } 179 if (expansion != KeyguardBouncer.EXPANSION_HIDDEN && tracking 180 && mStatusBar.isKeyguardCurrentlySecure() 181 && !mBouncer.isShowing() && !mBouncer.isAnimatingAway()) { 182 mBouncer.show(false /* resetSecuritySelection */, false /* scrimmed */); 183 } 184 } 185 } 186 187 /** 188 * Show the keyguard. Will handle creating and attaching to the view manager 189 * lazily. 190 */ show(Bundle options)191 public void show(Bundle options) { 192 mShowing = true; 193 mStatusBarWindowManager.setKeyguardShowing(true); 194 reset(true /* hideBouncerWhenShowing */); 195 StatsLog.write(StatsLog.KEYGUARD_STATE_CHANGED, 196 StatsLog.KEYGUARD_STATE_CHANGED__STATE__SHOWN); 197 } 198 199 /** 200 * Shows the notification keyguard or the bouncer depending on 201 * {@link KeyguardBouncer#needsFullscreenBouncer()}. 202 */ showBouncerOrKeyguard(boolean hideBouncerWhenShowing)203 protected void showBouncerOrKeyguard(boolean hideBouncerWhenShowing) { 204 if (mBouncer.needsFullscreenBouncer() && !mDozing) { 205 // The keyguard might be showing (already). So we need to hide it. 206 mStatusBar.hideKeyguard(); 207 mBouncer.show(true /* resetSecuritySelection */); 208 } else { 209 mStatusBar.showKeyguard(); 210 if (hideBouncerWhenShowing) { 211 hideBouncer(shouldDestroyViewOnReset() /* destroyView */); 212 mBouncer.prepare(); 213 } 214 } 215 updateStates(); 216 } 217 shouldDestroyViewOnReset()218 protected boolean shouldDestroyViewOnReset() { 219 return false; 220 } 221 hideBouncer(boolean destroyView)222 private void hideBouncer(boolean destroyView) { 223 mBouncer.hide(destroyView); 224 cancelPendingWakeupAction(); 225 } 226 showBouncer(boolean scrimmed)227 public void showBouncer(boolean scrimmed) { 228 if (mShowing && !mBouncer.isShowing()) { 229 mBouncer.show(false /* resetSecuritySelection */, scrimmed); 230 } 231 updateStates(); 232 } 233 dismissWithAction(OnDismissAction r, Runnable cancelAction, boolean afterKeyguardGone)234 public void dismissWithAction(OnDismissAction r, Runnable cancelAction, 235 boolean afterKeyguardGone) { 236 dismissWithAction(r, cancelAction, afterKeyguardGone, null /* message */); 237 } 238 dismissWithAction(OnDismissAction r, Runnable cancelAction, boolean afterKeyguardGone, String message)239 public void dismissWithAction(OnDismissAction r, Runnable cancelAction, 240 boolean afterKeyguardGone, String message) { 241 if (mShowing) { 242 cancelPendingWakeupAction(); 243 // If we're dozing, this needs to be delayed until after we wake up - unless we're 244 // wake-and-unlocking, because there dozing will last until the end of the transition. 245 if (mDozing && !isWakeAndUnlocking()) { 246 mPendingWakeupAction = new DismissWithActionRequest( 247 r, cancelAction, afterKeyguardGone, message); 248 return; 249 } 250 251 if (!afterKeyguardGone) { 252 mBouncer.showWithDismissAction(r, cancelAction); 253 } else { 254 mAfterKeyguardGoneAction = r; 255 mBouncer.show(false /* resetSecuritySelection */); 256 } 257 } 258 updateStates(); 259 } 260 isWakeAndUnlocking()261 private boolean isWakeAndUnlocking() { 262 int mode = mFingerprintUnlockController.getMode(); 263 return mode == MODE_WAKE_AND_UNLOCK || mode == MODE_WAKE_AND_UNLOCK_PULSING; 264 } 265 266 /** 267 * Adds a {@param runnable} to be executed after Keyguard is gone. 268 */ addAfterKeyguardGoneRunnable(Runnable runnable)269 public void addAfterKeyguardGoneRunnable(Runnable runnable) { 270 mAfterKeyguardGoneRunnables.add(runnable); 271 } 272 273 /** 274 * Reset the state of the view. 275 */ reset(boolean hideBouncerWhenShowing)276 public void reset(boolean hideBouncerWhenShowing) { 277 if (mShowing) { 278 if (mOccluded && !mDozing) { 279 mStatusBar.hideKeyguard(); 280 if (hideBouncerWhenShowing || mBouncer.needsFullscreenBouncer()) { 281 hideBouncer(false /* destroyView */); 282 } 283 } else { 284 showBouncerOrKeyguard(hideBouncerWhenShowing); 285 } 286 KeyguardUpdateMonitor.getInstance(mContext).sendKeyguardReset(); 287 updateStates(); 288 } 289 } 290 isGoingToSleepVisibleNotOccluded()291 public boolean isGoingToSleepVisibleNotOccluded() { 292 return mGoingToSleepVisibleNotOccluded; 293 } 294 onStartedGoingToSleep()295 public void onStartedGoingToSleep() { 296 mGoingToSleepVisibleNotOccluded = isShowing() && !isOccluded(); 297 } 298 onFinishedGoingToSleep()299 public void onFinishedGoingToSleep() { 300 mGoingToSleepVisibleNotOccluded = false; 301 mBouncer.onScreenTurnedOff(); 302 } 303 onStartedWakingUp()304 public void onStartedWakingUp() { 305 // TODO: remove 306 } 307 onScreenTurningOn()308 public void onScreenTurningOn() { 309 // TODO: remove 310 } 311 onScreenTurnedOn()312 public void onScreenTurnedOn() { 313 // TODO: remove 314 } 315 316 @Override onRemoteInputActive(boolean active)317 public void onRemoteInputActive(boolean active) { 318 mRemoteInputActive = active; 319 updateStates(); 320 } 321 setDozing(boolean dozing)322 public void setDozing(boolean dozing) { 323 if (mDozing != dozing) { 324 mDozing = dozing; 325 if (dozing || mBouncer.needsFullscreenBouncer() || mOccluded) { 326 reset(dozing /* hideBouncerWhenShowing */); 327 } 328 updateStates(); 329 330 if (!dozing) { 331 launchPendingWakeupAction(); 332 } 333 } 334 } 335 onScreenTurnedOff()336 public void onScreenTurnedOff() { 337 // TODO: remove 338 } 339 notifyDeviceWakeUpRequested()340 public void notifyDeviceWakeUpRequested() { 341 // TODO: remove 342 } 343 setNeedsInput(boolean needsInput)344 public void setNeedsInput(boolean needsInput) { 345 mStatusBarWindowManager.setKeyguardNeedsInput(needsInput); 346 } 347 isUnlockWithWallpaper()348 public boolean isUnlockWithWallpaper() { 349 return mStatusBarWindowManager.isShowingWallpaper(); 350 } 351 setOccluded(boolean occluded, boolean animate)352 public void setOccluded(boolean occluded, boolean animate) { 353 mStatusBar.setOccluded(occluded); 354 if (occluded && !mOccluded && mShowing) { 355 StatsLog.write(StatsLog.KEYGUARD_STATE_CHANGED, 356 StatsLog.KEYGUARD_STATE_CHANGED__STATE__OCCLUDED); 357 if (mStatusBar.isInLaunchTransition()) { 358 mOccluded = true; 359 mStatusBar.fadeKeyguardAfterLaunchTransition(null /* beforeFading */, 360 new Runnable() { 361 @Override 362 public void run() { 363 mStatusBarWindowManager.setKeyguardOccluded(mOccluded); 364 reset(true /* hideBouncerWhenShowing */); 365 } 366 }); 367 return; 368 } 369 } else if (!occluded && mOccluded && mShowing) { 370 StatsLog.write(StatsLog.KEYGUARD_STATE_CHANGED, 371 StatsLog.KEYGUARD_STATE_CHANGED__STATE__SHOWN); 372 } 373 boolean isOccluding = !mOccluded && occluded; 374 mOccluded = occluded; 375 if (mShowing) { 376 mStatusBar.updateMediaMetaData(false, animate && !occluded); 377 } 378 mStatusBarWindowManager.setKeyguardOccluded(occluded); 379 380 // setDozing(false) will call reset once we stop dozing. 381 if (!mDozing) { 382 // If Keyguard is reshown, don't hide the bouncer as it might just have been requested 383 // by a FLAG_DISMISS_KEYGUARD_ACTIVITY. 384 reset(isOccluding /* hideBouncerWhenShowing*/); 385 } 386 if (animate && !occluded && mShowing) { 387 mStatusBar.animateKeyguardUnoccluding(); 388 } 389 } 390 isOccluded()391 public boolean isOccluded() { 392 return mOccluded; 393 } 394 395 /** 396 * Starts the animation before we dismiss Keyguard, i.e. an disappearing animation on the 397 * security view of the bouncer. 398 * 399 * @param finishRunnable the runnable to be run after the animation finished, or {@code null} if 400 * no action should be run 401 */ startPreHideAnimation(Runnable finishRunnable)402 public void startPreHideAnimation(Runnable finishRunnable) { 403 if (mBouncer.isShowing()) { 404 mBouncer.startPreHideAnimation(finishRunnable); 405 mNotificationPanelView.onBouncerPreHideAnimation(); 406 } else if (finishRunnable != null) { 407 finishRunnable.run(); 408 } 409 } 410 411 /** 412 * Hides the keyguard view 413 */ hide(long startTime, long fadeoutDuration)414 public void hide(long startTime, long fadeoutDuration) { 415 mShowing = false; 416 launchPendingWakeupAction(); 417 418 if (KeyguardUpdateMonitor.getInstance(mContext).needsSlowUnlockTransition()) { 419 fadeoutDuration = KEYGUARD_DISMISS_DURATION_LOCKED; 420 } 421 long uptimeMillis = SystemClock.uptimeMillis(); 422 long delay = Math.max(0, startTime + HIDE_TIMING_CORRECTION_MS - uptimeMillis); 423 424 if (mStatusBar.isInLaunchTransition() ) { 425 mStatusBar.fadeKeyguardAfterLaunchTransition(new Runnable() { 426 @Override 427 public void run() { 428 mStatusBarWindowManager.setKeyguardShowing(false); 429 mStatusBarWindowManager.setKeyguardFadingAway(true); 430 hideBouncer(true /* destroyView */); 431 updateStates(); 432 } 433 }, new Runnable() { 434 @Override 435 public void run() { 436 mStatusBar.hideKeyguard(); 437 mStatusBarWindowManager.setKeyguardFadingAway(false); 438 mViewMediatorCallback.keyguardGone(); 439 executeAfterKeyguardGoneAction(); 440 } 441 }); 442 } else { 443 executeAfterKeyguardGoneAction(); 444 boolean wakeUnlockPulsing = 445 mFingerprintUnlockController.getMode() == MODE_WAKE_AND_UNLOCK_PULSING; 446 if (wakeUnlockPulsing) { 447 delay = 0; 448 fadeoutDuration = 240; 449 } 450 mStatusBar.setKeyguardFadingAway(startTime, delay, fadeoutDuration); 451 mFingerprintUnlockController.startKeyguardFadingAway(); 452 hideBouncer(true /* destroyView */); 453 if (wakeUnlockPulsing) { 454 mStatusBar.fadeKeyguardWhilePulsing(); 455 wakeAndUnlockDejank(); 456 } else { 457 boolean staying = mStatusBar.hideKeyguard(); 458 if (!staying) { 459 mStatusBarWindowManager.setKeyguardFadingAway(true); 460 wakeAndUnlockDejank(); 461 } else { 462 mStatusBar.finishKeyguardFadingAway(); 463 mFingerprintUnlockController.finishKeyguardFadingAway(); 464 } 465 } 466 updateStates(); 467 mStatusBarWindowManager.setKeyguardShowing(false); 468 mViewMediatorCallback.keyguardGone(); 469 } 470 StatsLog.write(StatsLog.KEYGUARD_STATE_CHANGED, 471 StatsLog.KEYGUARD_STATE_CHANGED__STATE__HIDDEN); 472 } 473 onDensityOrFontScaleChanged()474 public void onDensityOrFontScaleChanged() { 475 hideBouncer(true /* destroyView */); 476 } 477 onThemeChanged()478 public void onThemeChanged() { 479 hideBouncer(true /* destroyView */); 480 mBouncer.prepare(); 481 } 482 onKeyguardFadedAway()483 public void onKeyguardFadedAway() { 484 mContainer.postDelayed(() -> mStatusBarWindowManager.setKeyguardFadingAway(false), 485 100); 486 mStatusBar.finishKeyguardFadingAway(); 487 mFingerprintUnlockController.finishKeyguardFadingAway(); 488 WindowManagerGlobal.getInstance().trimMemory( 489 ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN); 490 491 } 492 wakeAndUnlockDejank()493 private void wakeAndUnlockDejank() { 494 if (mFingerprintUnlockController.getMode() == MODE_WAKE_AND_UNLOCK 495 && LatencyTracker.isEnabled(mContext)) { 496 DejankUtils.postAfterTraversal(() -> 497 LatencyTracker.getInstance(mContext).onActionEnd( 498 LatencyTracker.ACTION_FINGERPRINT_WAKE_AND_UNLOCK)); 499 } 500 } 501 executeAfterKeyguardGoneAction()502 private void executeAfterKeyguardGoneAction() { 503 if (mAfterKeyguardGoneAction != null) { 504 mAfterKeyguardGoneAction.onDismiss(); 505 mAfterKeyguardGoneAction = null; 506 } 507 for (int i = 0; i < mAfterKeyguardGoneRunnables.size(); i++) { 508 mAfterKeyguardGoneRunnables.get(i).run(); 509 } 510 mAfterKeyguardGoneRunnables.clear(); 511 } 512 513 /** 514 * Dismisses the keyguard by going to the next screen or making it gone. 515 */ dismissAndCollapse()516 public void dismissAndCollapse() { 517 mStatusBar.executeRunnableDismissingKeyguard(null, null, true, false, true); 518 } 519 520 /** 521 * WARNING: This method might cause Binder calls. 522 */ isSecure()523 public boolean isSecure() { 524 return mBouncer.isSecure(); 525 } 526 527 /** 528 * @return Whether the keyguard is showing 529 */ isShowing()530 public boolean isShowing() { 531 return mShowing; 532 } 533 534 /** 535 * Notifies this manager that the back button has been pressed. 536 * 537 * @param hideImmediately Hide bouncer when {@code true}, keep it around otherwise. 538 * Non-scrimmed bouncers have a special animation tied to the expansion 539 * of the notification panel. 540 * @return whether the back press has been handled 541 */ onBackPressed(boolean hideImmediately)542 public boolean onBackPressed(boolean hideImmediately) { 543 if (mBouncer.isShowing()) { 544 mStatusBar.endAffordanceLaunch(); 545 reset(hideImmediately); 546 return true; 547 } 548 return false; 549 } 550 isBouncerShowing()551 public boolean isBouncerShowing() { 552 return mBouncer.isShowing(); 553 } 554 isFullscreenBouncer()555 public boolean isFullscreenBouncer() { 556 return mBouncer.isFullscreenBouncer(); 557 } 558 getNavBarShowDelay()559 private long getNavBarShowDelay() { 560 if (mStatusBar.isKeyguardFadingAway()) { 561 return mStatusBar.getKeyguardFadingAwayDelay(); 562 } else if (mBouncer.isShowing()) { 563 return NAV_BAR_SHOW_DELAY_BOUNCER; 564 } else { 565 // No longer dozing, or remote input is active. No delay. 566 return 0; 567 } 568 } 569 570 private Runnable mMakeNavigationBarVisibleRunnable = new Runnable() { 571 @Override 572 public void run() { 573 mStatusBar.getNavigationBarView().getRootView().setVisibility(View.VISIBLE); 574 } 575 }; 576 updateStates()577 protected void updateStates() { 578 int vis = mContainer.getSystemUiVisibility(); 579 boolean showing = mShowing; 580 boolean occluded = mOccluded; 581 boolean bouncerShowing = mBouncer.isShowing(); 582 boolean bouncerDismissible = !mBouncer.isFullscreenBouncer(); 583 boolean remoteInputActive = mRemoteInputActive; 584 585 if ((bouncerDismissible || !showing || remoteInputActive) != 586 (mLastBouncerDismissible || !mLastShowing || mLastRemoteInputActive) 587 || mFirstUpdate) { 588 if (bouncerDismissible || !showing || remoteInputActive) { 589 mContainer.setSystemUiVisibility(vis & ~View.STATUS_BAR_DISABLE_BACK); 590 } else { 591 mContainer.setSystemUiVisibility(vis | View.STATUS_BAR_DISABLE_BACK); 592 } 593 } 594 595 boolean navBarVisible = isNavBarVisible(); 596 boolean lastNavBarVisible = getLastNavBarVisible(); 597 if (navBarVisible != lastNavBarVisible || mFirstUpdate) { 598 updateNavigationBarVisibility(navBarVisible); 599 } 600 601 if (bouncerShowing != mLastBouncerShowing || mFirstUpdate) { 602 mStatusBarWindowManager.setBouncerShowing(bouncerShowing); 603 mStatusBar.setBouncerShowing(bouncerShowing); 604 } 605 606 KeyguardUpdateMonitor updateMonitor = KeyguardUpdateMonitor.getInstance(mContext); 607 if ((showing && !occluded) != (mLastShowing && !mLastOccluded) || mFirstUpdate) { 608 updateMonitor.onKeyguardVisibilityChanged(showing && !occluded); 609 } 610 if (bouncerShowing != mLastBouncerShowing || mFirstUpdate) { 611 updateMonitor.sendKeyguardBouncerChanged(bouncerShowing); 612 } 613 614 mFirstUpdate = false; 615 mLastShowing = showing; 616 mLastOccluded = occluded; 617 mLastBouncerShowing = bouncerShowing; 618 mLastBouncerDismissible = bouncerDismissible; 619 mLastRemoteInputActive = remoteInputActive; 620 mLastDozing = mDozing; 621 mLastFpMode = mFingerprintUnlockController.getMode(); 622 mStatusBar.onKeyguardViewManagerStatesUpdated(); 623 } 624 updateNavigationBarVisibility(boolean navBarVisible)625 protected void updateNavigationBarVisibility(boolean navBarVisible) { 626 if (mStatusBar.getNavigationBarView() != null) { 627 if (navBarVisible) { 628 long delay = getNavBarShowDelay(); 629 if (delay == 0) { 630 mMakeNavigationBarVisibleRunnable.run(); 631 } else { 632 mContainer.postOnAnimationDelayed(mMakeNavigationBarVisibleRunnable, 633 delay); 634 } 635 } else { 636 mContainer.removeCallbacks(mMakeNavigationBarVisibleRunnable); 637 mStatusBar.getNavigationBarView().getRootView().setVisibility(View.GONE); 638 } 639 } 640 } 641 642 /** 643 * @return Whether the navigation bar should be made visible based on the current state. 644 */ isNavBarVisible()645 protected boolean isNavBarVisible() { 646 int fpMode = mFingerprintUnlockController.getMode(); 647 boolean keyguardShowing = mShowing && !mOccluded; 648 boolean hideWhileDozing = mDozing && fpMode != MODE_WAKE_AND_UNLOCK_PULSING; 649 return (!keyguardShowing && !hideWhileDozing || mBouncer.isShowing() 650 || mRemoteInputActive); 651 } 652 653 /** 654 * @return Whether the navigation bar was made visible based on the last known state. 655 */ getLastNavBarVisible()656 protected boolean getLastNavBarVisible() { 657 boolean keyguardShowing = mLastShowing && !mLastOccluded; 658 boolean hideWhileDozing = mLastDozing && mLastFpMode != MODE_WAKE_AND_UNLOCK_PULSING; 659 return (!keyguardShowing && !hideWhileDozing || mLastBouncerShowing 660 || mLastRemoteInputActive); 661 } 662 shouldDismissOnMenuPressed()663 public boolean shouldDismissOnMenuPressed() { 664 return mBouncer.shouldDismissOnMenuPressed(); 665 } 666 interceptMediaKey(KeyEvent event)667 public boolean interceptMediaKey(KeyEvent event) { 668 return mBouncer.interceptMediaKey(event); 669 } 670 readyForKeyguardDone()671 public void readyForKeyguardDone() { 672 mViewMediatorCallback.readyForKeyguardDone(); 673 } 674 shouldDisableWindowAnimationsForUnlock()675 public boolean shouldDisableWindowAnimationsForUnlock() { 676 return mStatusBar.isInLaunchTransition(); 677 } 678 isGoingToNotificationShade()679 public boolean isGoingToNotificationShade() { 680 return mStatusBar.isGoingToNotificationShade(); 681 } 682 isSecure(int userId)683 public boolean isSecure(int userId) { 684 return mBouncer.isSecure() || mLockPatternUtils.isSecure(userId); 685 } 686 keyguardGoingAway()687 public void keyguardGoingAway() { 688 mStatusBar.keyguardGoingAway(); 689 } 690 animateCollapsePanels(float speedUpFactor)691 public void animateCollapsePanels(float speedUpFactor) { 692 mStatusBar.animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_NONE, true /* force */, 693 false /* delayed */, speedUpFactor); 694 } 695 696 /** 697 * Notifies that the user has authenticated by other means than using the bouncer, for example, 698 * fingerprint. 699 */ notifyKeyguardAuthenticated(boolean strongAuth)700 public void notifyKeyguardAuthenticated(boolean strongAuth) { 701 mBouncer.notifyKeyguardAuthenticated(strongAuth); 702 } 703 showBouncerMessage(String message, int color)704 public void showBouncerMessage(String message, int color) { 705 mBouncer.showMessage(message, color); 706 } 707 getViewRootImpl()708 public ViewRootImpl getViewRootImpl() { 709 return mStatusBar.getStatusBarView().getViewRootImpl(); 710 } 711 launchPendingWakeupAction()712 public void launchPendingWakeupAction() { 713 DismissWithActionRequest request = mPendingWakeupAction; 714 mPendingWakeupAction = null; 715 if (request != null) { 716 if (mShowing) { 717 dismissWithAction(request.dismissAction, request.cancelAction, 718 request.afterKeyguardGone, request.message); 719 } else if (request.dismissAction != null) { 720 request.dismissAction.onDismiss(); 721 } 722 } 723 } 724 cancelPendingWakeupAction()725 public void cancelPendingWakeupAction() { 726 DismissWithActionRequest request = mPendingWakeupAction; 727 mPendingWakeupAction = null; 728 if (request != null && request.cancelAction != null) { 729 request.cancelAction.run(); 730 } 731 } 732 willDismissWithAction()733 public boolean willDismissWithAction() { 734 return mBouncer.willDismissWithAction(); 735 } 736 bouncerNeedsScrimming()737 public boolean bouncerNeedsScrimming() { 738 return mBouncer.isShowingScrimmed(); 739 } 740 dump(PrintWriter pw)741 public void dump(PrintWriter pw) { 742 pw.println("StatusBarKeyguardViewManager:"); 743 pw.println(" mShowing: " + mShowing); 744 pw.println(" mOccluded: " + mOccluded); 745 pw.println(" mRemoteInputActive: " + mRemoteInputActive); 746 pw.println(" mDozing: " + mDozing); 747 pw.println(" mGoingToSleepVisibleNotOccluded: " + mGoingToSleepVisibleNotOccluded); 748 pw.println(" mAfterKeyguardGoneAction: " + mAfterKeyguardGoneAction); 749 pw.println(" mAfterKeyguardGoneRunnables: " + mAfterKeyguardGoneRunnables); 750 pw.println(" mPendingWakeupAction: " + mPendingWakeupAction); 751 752 if (mBouncer != null) { 753 mBouncer.dump(pw); 754 } 755 } 756 757 private static class DismissWithActionRequest { 758 final OnDismissAction dismissAction; 759 final Runnable cancelAction; 760 final boolean afterKeyguardGone; 761 final String message; 762 DismissWithActionRequest(OnDismissAction dismissAction, Runnable cancelAction, boolean afterKeyguardGone, String message)763 DismissWithActionRequest(OnDismissAction dismissAction, Runnable cancelAction, 764 boolean afterKeyguardGone, String message) { 765 this.dismissAction = dismissAction; 766 this.cancelAction = cancelAction; 767 this.afterKeyguardGone = afterKeyguardGone; 768 this.message = message; 769 } 770 } 771 } 772