2 * Copyright (C) 2014 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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
17 package com.android.systemui.statusbar.phone;
19 import android.content.ComponentCallbacks2;
20 import android.content.Context;
21 import android.os.Bundle;
22 import android.os.RemoteException;
23 import android.os.SystemClock;
24 import android.util.Slog;
25 import android.view.KeyEvent;
26 import android.view.View;
27 import android.view.ViewGroup;
28 import android.view.WindowManagerGlobal;
30 import com.android.internal.policy.IKeyguardShowCallback;
31 import com.android.internal.widget.LockPatternUtils;
32 import com.android.keyguard.KeyguardUpdateMonitor;
33 import com.android.keyguard.ViewMediatorCallback;
35 import static com.android.keyguard.KeyguardHostView.OnDismissAction;
38 * Manages creating, showing, hiding and resetting the keyguard within the status bar. Calls back
39 * via {@link ViewMediatorCallback} to poke the wake lock and report that the keyguard is done,
40 * which is in turn, reported to this class by the current
41 * {@link com.android.keyguard.KeyguardViewBase}.
43 public class StatusBarKeyguardViewManager {
45 // When hiding the Keyguard with timing supplied from WindowManager, better be early than late.
46 private static final long HIDE_TIMING_CORRECTION_MS = -3 * 16;
48 // Delay for showing the navigation bar when the bouncer appears. This should be kept in sync
49 // with the appear animations of the PIN/pattern/password views.
50 private static final long NAV_BAR_SHOW_DELAY_BOUNCER = 320;
52 private static String TAG = "StatusBarKeyguardViewManager";
54 private final Context mContext;
56 private LockPatternUtils mLockPatternUtils;
57 private ViewMediatorCallback mViewMediatorCallback;
58 private PhoneStatusBar mPhoneStatusBar;
59 private ScrimController mScrimController;
61 private ViewGroup mContainer;
62 private StatusBarWindowManager mStatusBarWindowManager;
64 private boolean mScreenOn = false;
65 private KeyguardBouncer mBouncer;
66 private boolean mShowing;
67 private boolean mOccluded;
69 private boolean mFirstUpdate = true;
70 private boolean mLastShowing;
71 private boolean mLastOccluded;
72 private boolean mLastBouncerShowing;
73 private boolean mLastBouncerDismissible;
74 private OnDismissAction mAfterKeyguardGoneAction;
76 public StatusBarKeyguardViewManager(Context context, ViewMediatorCallback callback,
77 LockPatternUtils lockPatternUtils) {
79 mViewMediatorCallback = callback;
80 mLockPatternUtils = lockPatternUtils;
83 public void registerStatusBar(PhoneStatusBar phoneStatusBar,
84 ViewGroup container, StatusBarWindowManager statusBarWindowManager,
85 ScrimController scrimController) {
86 mPhoneStatusBar = phoneStatusBar;
87 mContainer = container;
88 mStatusBarWindowManager = statusBarWindowManager;
89 mScrimController = scrimController;
90 mBouncer = new KeyguardBouncer(mContext, mViewMediatorCallback, mLockPatternUtils,
91 mStatusBarWindowManager, container);
95 * Show the keyguard. Will handle creating and attaching to the view manager
98 public void show(Bundle options) {
100 mStatusBarWindowManager.setKeyguardShowing(true);
105 * Shows the notification keyguard or the bouncer depending on
106 * {@link KeyguardBouncer#needsFullscreenBouncer()}.
108 private void showBouncerOrKeyguard() {
109 if (mBouncer.needsFullscreenBouncer()) {
111 // The keyguard might be showing (already). So we need to hide it.
112 mPhoneStatusBar.hideKeyguard();
113 mBouncer.show(true /* resetSecuritySelection */);
115 mPhoneStatusBar.showKeyguard();
116 mBouncer.hide(false /* destroyView */);
121 private void showBouncer() {
123 mBouncer.show(false /* resetSecuritySelection */);
128 public void dismissWithAction(OnDismissAction r, boolean afterKeyguardGone) {
130 if (!afterKeyguardGone) {
131 mBouncer.showWithDismissAction(r);
133 mBouncer.show(false /* resetSecuritySelection */);
134 mAfterKeyguardGoneAction = r;
141 * Reset the state of the view.
143 public void reset() {
146 mPhoneStatusBar.hideKeyguard();
147 mBouncer.hide(false /* destroyView */);
149 showBouncerOrKeyguard();
155 public void onScreenTurnedOff() {
157 mPhoneStatusBar.onScreenTurnedOff();
158 mBouncer.onScreenTurnedOff();
161 public void onScreenTurnedOn(final IKeyguardShowCallback callback) {
163 mPhoneStatusBar.onScreenTurnedOn();
164 if (callback != null) {
165 callbackAfterDraw(callback);
169 private void callbackAfterDraw(final IKeyguardShowCallback callback) {
170 mContainer.post(new Runnable() {
174 callback.onShown(mContainer.getWindowToken());
175 } catch (RemoteException e) {
176 Slog.w(TAG, "Exception calling onShown():", e);
182 public void verifyUnlock() {
186 public void setNeedsInput(boolean needsInput) {
187 mStatusBarWindowManager.setKeyguardNeedsInput(needsInput);
190 public void setOccluded(boolean occluded) {
191 if (occluded && !mOccluded && mShowing) {
192 if (mPhoneStatusBar.isInLaunchTransition()) {
194 mPhoneStatusBar.fadeKeyguardAfterLaunchTransition(null /* beforeFading */,
198 mStatusBarWindowManager.setKeyguardOccluded(mOccluded);
205 mOccluded = occluded;
206 mStatusBarWindowManager.setKeyguardOccluded(occluded);
210 public boolean isOccluded() {
215 * Starts the animation before we dismiss Keyguard, i.e. an disappearing animation on the
216 * security view of the bouncer.
218 * @param finishRunnable the runnable to be run after the animation finished, or {@code null} if
219 * no action should be run
221 public void startPreHideAnimation(Runnable finishRunnable) {
222 if (mBouncer.isShowing()) {
223 mBouncer.startPreHideAnimation(finishRunnable);
224 } else if (finishRunnable != null) {
225 finishRunnable.run();
230 * Hides the keyguard view
232 public void hide(long startTime, final long fadeoutDuration) {
235 long uptimeMillis = SystemClock.uptimeMillis();
236 long delay = Math.max(0, startTime + HIDE_TIMING_CORRECTION_MS - uptimeMillis);
238 if (mPhoneStatusBar.isInLaunchTransition() ) {
239 mPhoneStatusBar.fadeKeyguardAfterLaunchTransition(new Runnable() {
242 mStatusBarWindowManager.setKeyguardShowing(false);
243 mStatusBarWindowManager.setKeyguardFadingAway(true);
244 mBouncer.hide(true /* destroyView */);
246 mScrimController.animateKeyguardFadingOut(
247 PhoneStatusBar.FADE_KEYGUARD_START_DELAY,
248 PhoneStatusBar.FADE_KEYGUARD_DURATION, null);
253 mPhoneStatusBar.hideKeyguard();
254 mStatusBarWindowManager.setKeyguardFadingAway(false);
255 mViewMediatorCallback.keyguardGone();
256 executeAfterKeyguardGoneAction();
260 mPhoneStatusBar.setKeyguardFadingAway(delay, fadeoutDuration);
261 boolean staying = mPhoneStatusBar.hideKeyguard();
263 mStatusBarWindowManager.setKeyguardFadingAway(true);
264 mScrimController.animateKeyguardFadingOut(delay, fadeoutDuration, new Runnable() {
267 mStatusBarWindowManager.setKeyguardFadingAway(false);
268 mPhoneStatusBar.finishKeyguardFadingAway();
269 WindowManagerGlobal.getInstance().trimMemory(
270 ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN);
274 mScrimController.animateGoingToFullShade(delay, fadeoutDuration);
275 mPhoneStatusBar.finishKeyguardFadingAway();
277 mStatusBarWindowManager.setKeyguardShowing(false);
278 mBouncer.hide(true /* destroyView */);
279 mViewMediatorCallback.keyguardGone();
280 executeAfterKeyguardGoneAction();
286 private void executeAfterKeyguardGoneAction() {
287 if (mAfterKeyguardGoneAction != null) {
288 mAfterKeyguardGoneAction.onDismiss();
289 mAfterKeyguardGoneAction = null;
294 * Dismisses the keyguard by going to the next screen or making it gone.
296 public void dismiss() {
302 public boolean isSecure() {
303 return mBouncer.isSecure();
307 * @return Whether the keyguard is showing
309 public boolean isShowing() {
314 * Notifies this manager that the back button has been pressed.
316 * @return whether the back press has been handled
318 public boolean onBackPressed() {
319 if (mBouncer.isShowing()) {
326 public boolean isBouncerShowing() {
327 return mBouncer.isShowing();
330 private long getNavBarShowDelay() {
331 if (mPhoneStatusBar.isKeyguardFadingAway()) {
332 return mPhoneStatusBar.getKeyguardFadingAwayDelay();
335 // Keyguard is not going away, thus we are showing the navigation bar because the
336 // bouncer is appearing.
337 return NAV_BAR_SHOW_DELAY_BOUNCER;
341 private Runnable mMakeNavigationBarVisibleRunnable = new Runnable() {
344 mPhoneStatusBar.getNavigationBarView().setVisibility(View.VISIBLE);
348 private void updateStates() {
349 int vis = mContainer.getSystemUiVisibility();
350 boolean showing = mShowing;
351 boolean occluded = mOccluded;
352 boolean bouncerShowing = mBouncer.isShowing();
353 boolean bouncerDismissible = !mBouncer.isFullscreenBouncer();
355 if ((bouncerDismissible || !showing) != (mLastBouncerDismissible || !mLastShowing)
357 if (bouncerDismissible || !showing) {
358 mContainer.setSystemUiVisibility(vis & ~View.STATUS_BAR_DISABLE_BACK);
360 mContainer.setSystemUiVisibility(vis | View.STATUS_BAR_DISABLE_BACK);
363 if ((!(showing && !occluded) || bouncerShowing)
364 != (!(mLastShowing && !mLastOccluded) || mLastBouncerShowing) || mFirstUpdate) {
365 if (mPhoneStatusBar.getNavigationBarView() != null) {
366 if (!(showing && !occluded) || bouncerShowing) {
367 mContainer.postOnAnimationDelayed(mMakeNavigationBarVisibleRunnable,
368 getNavBarShowDelay());
370 mContainer.removeCallbacks(mMakeNavigationBarVisibleRunnable);
371 mPhoneStatusBar.getNavigationBarView().setVisibility(View.GONE);
376 if (bouncerShowing != mLastBouncerShowing || mFirstUpdate) {
377 mStatusBarWindowManager.setBouncerShowing(bouncerShowing);
378 mPhoneStatusBar.setBouncerShowing(bouncerShowing);
379 mScrimController.setBouncerShowing(bouncerShowing);
382 KeyguardUpdateMonitor updateMonitor = KeyguardUpdateMonitor.getInstance(mContext);
383 if ((showing && !occluded) != (mLastShowing && !mLastOccluded) || mFirstUpdate) {
384 updateMonitor.sendKeyguardVisibilityChanged(showing && !occluded);
386 if (bouncerShowing != mLastBouncerShowing || mFirstUpdate) {
387 updateMonitor.sendKeyguardBouncerChanged(bouncerShowing);
390 mFirstUpdate = false;
391 mLastShowing = showing;
392 mLastOccluded = occluded;
393 mLastBouncerShowing = bouncerShowing;
394 mLastBouncerDismissible = bouncerDismissible;
397 public boolean onMenuPressed() {
398 return mBouncer.onMenuPressed();
401 public boolean interceptMediaKey(KeyEvent event) {
402 return mBouncer.interceptMediaKey(event);
405 public void onActivityDrawn() {
406 if (mPhoneStatusBar.isCollapsing()) {
407 mPhoneStatusBar.addPostCollapseAction(new Runnable() {
410 mViewMediatorCallback.readyForKeyguardDone();
414 mViewMediatorCallback.readyForKeyguardDone();
418 public boolean shouldDisableWindowAnimationsForUnlock() {
419 return mPhoneStatusBar.isInLaunchTransition();
422 public boolean isGoingToNotificationShade() {
423 return mPhoneStatusBar.isGoingToNotificationShade();
426 public boolean isSecure(int userId) {
427 return mBouncer.isSecure() || mLockPatternUtils.isSecure(userId);
430 public boolean isInputRestricted() {
431 return mViewMediatorCallback.isInputRestricted();