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();
115 mPhoneStatusBar.showKeyguard();
116 mBouncer.hide(false /* destroyView */);
121 private void showBouncer() {
128 public void dismissWithAction(OnDismissAction r, boolean afterKeyguardGone) {
130 if (!afterKeyguardGone) {
131 mBouncer.showWithDismissAction(r);
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 updateUserActivityTimeout() {
191 mStatusBarWindowManager.setKeyguardUserActivityTimeout(mBouncer.getUserActivityTimeout());
194 public void setOccluded(boolean occluded) {
195 if (occluded && !mOccluded && mShowing) {
196 if (mPhoneStatusBar.isInLaunchTransition()) {
198 mPhoneStatusBar.fadeKeyguardAfterLaunchTransition(null /* beforeFading */,
202 mStatusBarWindowManager.setKeyguardOccluded(true);
209 mOccluded = occluded;
210 mStatusBarWindowManager.setKeyguardOccluded(occluded);
214 public boolean isOccluded() {
219 * Starts the animation before we dismiss Keyguard, i.e. an disappearing animation on the
220 * security view of the bouncer.
222 * @param finishRunnable the runnable to be run after the animation finished, or {@code null} if
223 * no action should be run
225 public void startPreHideAnimation(Runnable finishRunnable) {
226 if (mBouncer.isShowing()) {
227 mBouncer.startPreHideAnimation(finishRunnable);
228 } else if (finishRunnable != null) {
229 finishRunnable.run();
234 * Hides the keyguard view
236 public void hide(long startTime, final long fadeoutDuration) {
239 long uptimeMillis = SystemClock.uptimeMillis();
240 long delay = Math.max(0, startTime + HIDE_TIMING_CORRECTION_MS - uptimeMillis);
242 if (mPhoneStatusBar.isInLaunchTransition() ) {
243 mPhoneStatusBar.fadeKeyguardAfterLaunchTransition(new Runnable() {
246 mStatusBarWindowManager.setKeyguardShowing(false);
247 mStatusBarWindowManager.setKeyguardFadingAway(true);
248 mBouncer.hide(true /* destroyView */);
250 mScrimController.animateKeyguardFadingOut(
251 PhoneStatusBar.FADE_KEYGUARD_START_DELAY,
252 PhoneStatusBar.FADE_KEYGUARD_DURATION, null);
257 mPhoneStatusBar.hideKeyguard();
258 mStatusBarWindowManager.setKeyguardFadingAway(false);
259 mViewMediatorCallback.keyguardGone();
260 executeAfterKeyguardGoneAction();
264 mPhoneStatusBar.setKeyguardFadingAway(delay, fadeoutDuration);
265 boolean staying = mPhoneStatusBar.hideKeyguard();
267 mStatusBarWindowManager.setKeyguardFadingAway(true);
268 mScrimController.animateKeyguardFadingOut(delay, fadeoutDuration, new Runnable() {
271 mStatusBarWindowManager.setKeyguardFadingAway(false);
272 mPhoneStatusBar.finishKeyguardFadingAway();
273 WindowManagerGlobal.getInstance().trimMemory(
274 ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN);
278 mScrimController.animateGoingToFullShade(delay, fadeoutDuration);
279 mPhoneStatusBar.finishKeyguardFadingAway();
281 mStatusBarWindowManager.setKeyguardShowing(false);
282 mBouncer.hide(true /* destroyView */);
283 mViewMediatorCallback.keyguardGone();
284 executeAfterKeyguardGoneAction();
290 private void executeAfterKeyguardGoneAction() {
291 if (mAfterKeyguardGoneAction != null) {
292 mAfterKeyguardGoneAction.onDismiss();
293 mAfterKeyguardGoneAction = null;
298 * Dismisses the keyguard by going to the next screen or making it gone.
300 public void dismiss() {
306 public boolean isSecure() {
307 return mBouncer.isSecure();
311 * @return Whether the keyguard is showing
313 public boolean isShowing() {
318 * Notifies this manager that the back button has been pressed.
320 * @return whether the back press has been handled
322 public boolean onBackPressed() {
323 if (mBouncer.isShowing()) {
330 public boolean isBouncerShowing() {
331 return mBouncer.isShowing();
334 private long getNavBarShowDelay() {
335 if (mPhoneStatusBar.isKeyguardFadingAway()) {
336 return mPhoneStatusBar.getKeyguardFadingAwayDelay();
339 // Keyguard is not going away, thus we are showing the navigation bar because the
340 // bouncer is appearing.
341 return NAV_BAR_SHOW_DELAY_BOUNCER;
345 private Runnable mMakeNavigationBarVisibleRunnable = new Runnable() {
348 mPhoneStatusBar.getNavigationBarView().setVisibility(View.VISIBLE);
352 private void updateStates() {
353 int vis = mContainer.getSystemUiVisibility();
354 boolean showing = mShowing;
355 boolean occluded = mOccluded;
356 boolean bouncerShowing = mBouncer.isShowing();
357 boolean bouncerDismissible = !mBouncer.needsFullscreenBouncer();
359 if ((bouncerDismissible || !showing) != (mLastBouncerDismissible || !mLastShowing)
361 if (bouncerDismissible || !showing) {
362 mContainer.setSystemUiVisibility(vis & ~View.STATUS_BAR_DISABLE_BACK);
364 mContainer.setSystemUiVisibility(vis | View.STATUS_BAR_DISABLE_BACK);
367 if ((!(showing && !occluded) || bouncerShowing)
368 != (!(mLastShowing && !mLastOccluded) || mLastBouncerShowing) || mFirstUpdate) {
369 if (mPhoneStatusBar.getNavigationBarView() != null) {
370 if (!(showing && !occluded) || bouncerShowing) {
371 mContainer.postOnAnimationDelayed(mMakeNavigationBarVisibleRunnable,
372 getNavBarShowDelay());
374 mContainer.removeCallbacks(mMakeNavigationBarVisibleRunnable);
375 mPhoneStatusBar.getNavigationBarView().setVisibility(View.GONE);
380 if (bouncerShowing != mLastBouncerShowing || mFirstUpdate) {
381 mStatusBarWindowManager.setBouncerShowing(bouncerShowing);
382 mPhoneStatusBar.setBouncerShowing(bouncerShowing);
383 mScrimController.setBouncerShowing(bouncerShowing);
386 KeyguardUpdateMonitor updateMonitor = KeyguardUpdateMonitor.getInstance(mContext);
387 if ((showing && !occluded) != (mLastShowing && !mLastOccluded) || mFirstUpdate) {
388 updateMonitor.sendKeyguardVisibilityChanged(showing && !occluded);
390 if (bouncerShowing != mLastBouncerShowing || mFirstUpdate) {
391 updateMonitor.sendKeyguardBouncerChanged(bouncerShowing);
394 mFirstUpdate = false;
395 mLastShowing = showing;
396 mLastOccluded = occluded;
397 mLastBouncerShowing = bouncerShowing;
398 mLastBouncerDismissible = bouncerDismissible;
401 public boolean onMenuPressed() {
402 return mBouncer.onMenuPressed();
405 public boolean interceptMediaKey(KeyEvent event) {
406 return mBouncer.interceptMediaKey(event);
409 public void onActivityDrawn() {
410 if (mPhoneStatusBar.isCollapsing()) {
411 mPhoneStatusBar.addPostCollapseAction(new Runnable() {
414 mViewMediatorCallback.readyForKeyguardDone();
418 mViewMediatorCallback.readyForKeyguardDone();
422 public boolean shouldDisableWindowAnimationsForUnlock() {
423 return mPhoneStatusBar.isInLaunchTransition();
426 public boolean isGoingToNotificationShade() {
427 return mPhoneStatusBar.isGoingToNotificationShade();
430 public boolean isSecure(int userId) {
431 return mBouncer.isSecure() || mLockPatternUtils.isSecure(userId);