StatusBarKeyguardViewManager.java revision 44cf91960d74eccec45b9adec291ddb8baf84b4d
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
17package com.android.systemui.statusbar.phone;
18
19import android.content.Context;
20import android.os.Bundle;
21import android.os.RemoteException;
22import android.os.SystemClock;
23import android.util.Slog;
24import android.view.KeyEvent;
25import android.view.View;
26import android.view.ViewGroup;
27
28import com.android.internal.policy.IKeyguardShowCallback;
29import com.android.internal.widget.LockPatternUtils;
30import com.android.keyguard.KeyguardUpdateMonitor;
31import com.android.keyguard.ViewMediatorCallback;
32
33import static com.android.keyguard.KeyguardHostView.OnDismissAction;
34
35/**
36 * Manages creating, showing, hiding and resetting the keyguard within the status bar. Calls back
37 * via {@link ViewMediatorCallback} to poke the wake lock and report that the keyguard is done,
38 * which is in turn, reported to this class by the current
39 * {@link com.android.keyguard.KeyguardViewBase}.
40 */
41public class StatusBarKeyguardViewManager {
42    private static String TAG = "StatusBarKeyguardViewManager";
43
44    private final Context mContext;
45
46    private LockPatternUtils mLockPatternUtils;
47    private ViewMediatorCallback mViewMediatorCallback;
48    private PhoneStatusBar mPhoneStatusBar;
49    private ScrimController mScrimController;
50
51    private ViewGroup mContainer;
52    private StatusBarWindowManager mStatusBarWindowManager;
53
54    private boolean mScreenOn = false;
55    private KeyguardBouncer mBouncer;
56    private boolean mShowing;
57    private boolean mOccluded;
58
59    private boolean mFirstUpdate = true;
60    private boolean mLastShowing;
61    private boolean mLastOccluded;
62    private boolean mLastBouncerShowing;
63    private boolean mLastBouncerDismissible;
64
65    public StatusBarKeyguardViewManager(Context context, ViewMediatorCallback callback,
66            LockPatternUtils lockPatternUtils) {
67        mContext = context;
68        mViewMediatorCallback = callback;
69        mLockPatternUtils = lockPatternUtils;
70    }
71
72    public void registerStatusBar(PhoneStatusBar phoneStatusBar,
73            ViewGroup container, StatusBarWindowManager statusBarWindowManager,
74            ScrimController scrimController) {
75        mPhoneStatusBar = phoneStatusBar;
76        mContainer = container;
77        mStatusBarWindowManager = statusBarWindowManager;
78        mScrimController = scrimController;
79        mBouncer = new KeyguardBouncer(mContext, mViewMediatorCallback, mLockPatternUtils,
80                mStatusBarWindowManager, container);
81    }
82
83    /**
84     * Show the keyguard.  Will handle creating and attaching to the view manager
85     * lazily.
86     */
87    public void show(Bundle options) {
88        mShowing = true;
89        mStatusBarWindowManager.setKeyguardShowing(true);
90        reset();
91    }
92
93    /**
94     * Shows the notification keyguard or the bouncer depending on
95     * {@link KeyguardBouncer#needsFullscreenBouncer()}.
96     */
97    private void showBouncerOrKeyguard() {
98        if (mBouncer.needsFullscreenBouncer()) {
99
100            // The keyguard might be showing (already). So we need to hide it.
101            mPhoneStatusBar.hideKeyguard();
102            mBouncer.show();
103        } else {
104            mPhoneStatusBar.showKeyguard();
105            mBouncer.hide(false /* destroyView */);
106            mBouncer.prepare();
107        }
108    }
109
110    private void showBouncer() {
111        if (!mOccluded) {
112            mBouncer.show();
113        }
114        updateStates();
115    }
116
117    public void dismissWithAction(OnDismissAction r) {
118        if (!mOccluded) {
119            mBouncer.showWithDismissAction(r);
120        }
121        updateStates();
122    }
123
124    /**
125     * Reset the state of the view.
126     */
127    public void reset() {
128        if (mShowing) {
129            if (mOccluded) {
130                mPhoneStatusBar.hideKeyguard();
131                mBouncer.hide(false /* destroyView */);
132            } else {
133                showBouncerOrKeyguard();
134            }
135            updateStates();
136        }
137    }
138
139    public void onScreenTurnedOff() {
140        mScreenOn = false;
141        mPhoneStatusBar.onScreenTurnedOff();
142        mBouncer.onScreenTurnedOff();
143    }
144
145    public void onScreenTurnedOn(final IKeyguardShowCallback callback) {
146        mScreenOn = true;
147        mPhoneStatusBar.onScreenTurnedOn();
148        if (callback != null) {
149            callbackAfterDraw(callback);
150        }
151    }
152
153    private void callbackAfterDraw(final IKeyguardShowCallback callback) {
154        mContainer.post(new Runnable() {
155            @Override
156            public void run() {
157                try {
158                    callback.onShown(mContainer.getWindowToken());
159                } catch (RemoteException e) {
160                    Slog.w(TAG, "Exception calling onShown():", e);
161                }
162            }
163        });
164    }
165
166    public void verifyUnlock() {
167        dismiss();
168    }
169
170    public void setNeedsInput(boolean needsInput) {
171        mStatusBarWindowManager.setKeyguardNeedsInput(needsInput);
172    }
173
174    public void updateUserActivityTimeout() {
175        mStatusBarWindowManager.setKeyguardUserActivityTimeout(mBouncer.getUserActivityTimeout());
176    }
177
178    public void setOccluded(boolean occluded) {
179        mOccluded = occluded;
180        mStatusBarWindowManager.setKeyguardOccluded(occluded);
181        reset();
182    }
183
184    public boolean isOccluded() {
185        return mOccluded;
186    }
187
188    /**
189     * Hides the keyguard view
190     */
191    public void hide(long startTime, long fadeoutDuration) {
192        mShowing = false;
193
194        long uptimeMillis = SystemClock.uptimeMillis();
195        long delay = startTime - uptimeMillis;
196        if (delay < 0) {
197            delay = 0;
198        }
199
200        mPhoneStatusBar.setKeyguardFadingAway(delay, fadeoutDuration);
201        mPhoneStatusBar.hideKeyguard();
202        mStatusBarWindowManager.setKeyguardFadingAway(true);
203        mStatusBarWindowManager.setKeyguardShowing(false);
204        mBouncer.animateHide(delay, fadeoutDuration);
205        mScrimController.animateKeyguardFadingOut(delay, fadeoutDuration, new Runnable() {
206            @Override
207            public void run() {
208                mStatusBarWindowManager.setKeyguardFadingAway(false);
209                mPhoneStatusBar.finishKeyguardFadingAway();
210            }
211        });
212        mViewMediatorCallback.keyguardGone();
213        updateStates();
214    }
215
216    /**
217     * Dismisses the keyguard by going to the next screen or making it gone.
218     */
219    public void dismiss() {
220        if (mScreenOn) {
221            showBouncer();
222        }
223    }
224
225    public boolean isSecure() {
226        return mBouncer.isSecure();
227    }
228
229    /**
230     * @return Whether the keyguard is showing
231     */
232    public boolean isShowing() {
233        return mShowing;
234    }
235
236    /**
237     * Notifies this manager that the back button has been pressed.
238     *
239     * @return whether the back press has been handled
240     */
241    public boolean onBackPressed() {
242        if (mBouncer.isShowing()) {
243            mBouncer.hide(false /* destroyView */);
244            mPhoneStatusBar.showKeyguard();
245            updateStates();
246            return true;
247        }
248        return false;
249    }
250
251    private void updateStates() {
252        int vis = mContainer.getSystemUiVisibility();
253        boolean showing = mShowing;
254        boolean occluded = mOccluded;
255        boolean bouncerShowing = mBouncer.isShowing();
256        boolean bouncerDismissible = bouncerShowing && !mBouncer.needsFullscreenBouncer();
257
258        if ((bouncerDismissible || !showing) != (mLastBouncerDismissible || !mLastShowing)
259                || mFirstUpdate) {
260            if (bouncerDismissible || !showing) {
261                mContainer.setSystemUiVisibility(vis & ~View.STATUS_BAR_DISABLE_BACK);
262            } else {
263                mContainer.setSystemUiVisibility(vis | View.STATUS_BAR_DISABLE_BACK);
264            }
265        }
266        if ((!(showing && !occluded) || bouncerShowing)
267                != (!(mLastShowing && !mLastOccluded) || mLastBouncerShowing) || mFirstUpdate) {
268            if (mPhoneStatusBar.getNavigationBarView() != null) {
269                if (!(showing && !occluded) || bouncerShowing) {
270                    mPhoneStatusBar.getNavigationBarView().setVisibility(View.VISIBLE);
271                } else {
272                    mPhoneStatusBar.getNavigationBarView().setVisibility(View.GONE);
273                }
274            }
275        }
276
277        if (bouncerShowing != mLastBouncerShowing || mFirstUpdate) {
278            mStatusBarWindowManager.setBouncerShowing(bouncerShowing);
279            mPhoneStatusBar.setBouncerShowing(bouncerShowing);
280            mScrimController.setBouncerShowing(bouncerShowing);
281        }
282
283        KeyguardUpdateMonitor updateMonitor = KeyguardUpdateMonitor.getInstance(mContext);
284        if ((showing && !occluded) != (mLastShowing && !mLastOccluded) || mFirstUpdate) {
285            updateMonitor.sendKeyguardVisibilityChanged(showing && !occluded);
286        }
287        if (bouncerShowing != mLastBouncerShowing || mFirstUpdate) {
288            updateMonitor.sendKeyguardBouncerChanged(bouncerShowing);
289        }
290
291        mFirstUpdate = false;
292        mLastShowing = showing;
293        mLastOccluded = occluded;
294        mLastBouncerShowing = bouncerShowing;
295        mLastBouncerDismissible = bouncerDismissible;
296    }
297
298    public boolean onMenuPressed() {
299        return mBouncer.onMenuPressed();
300    }
301
302    public boolean interceptMediaKey(KeyEvent event) {
303        return mBouncer.interceptMediaKey(event);
304    }
305}
306