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