KeyguardBouncer.java revision 2231c6e1adefdb7636d9fe38a388f1b0660d30ea
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.view.Choreographer;
21import android.view.KeyEvent;
22import android.view.LayoutInflater;
23import android.view.View;
24import android.view.ViewGroup;
25
26import com.android.internal.widget.LockPatternUtils;
27import com.android.keyguard.KeyguardViewBase;
28import com.android.keyguard.R;
29import com.android.keyguard.ViewMediatorCallback;
30import com.android.systemui.keyguard.KeyguardViewMediator;
31
32import static com.android.keyguard.KeyguardHostView.OnDismissAction;
33import static com.android.keyguard.KeyguardSecurityModel.SecurityMode;
34
35/**
36 * A class which manages the bouncer on the lockscreen.
37 */
38public class KeyguardBouncer {
39
40    private Context mContext;
41    private ViewMediatorCallback mCallback;
42    private LockPatternUtils mLockPatternUtils;
43    private ViewGroup mContainer;
44    private StatusBarWindowManager mWindowManager;
45    private KeyguardViewBase mKeyguardView;
46    private ViewGroup mRoot;
47    private boolean mShowingSoon;
48    private Choreographer mChoreographer = Choreographer.getInstance();
49
50    public KeyguardBouncer(Context context, ViewMediatorCallback callback,
51            LockPatternUtils lockPatternUtils, StatusBarWindowManager windowManager,
52            ViewGroup container) {
53        mContext = context;
54        mCallback = callback;
55        mLockPatternUtils = lockPatternUtils;
56        mContainer = container;
57        mWindowManager = windowManager;
58    }
59
60    public void show(boolean resetSecuritySelection) {
61        ensureView();
62        if (resetSecuritySelection) {
63            // showPrimarySecurityScreen() updates the current security method. This is needed in
64            // case we are already showing and the current security method changed.
65            mKeyguardView.showPrimarySecurityScreen();
66        }
67        if (mRoot.getVisibility() == View.VISIBLE || mShowingSoon) {
68            return;
69        }
70
71        // Try to dismiss the Keyguard. If no security pattern is set, this will dismiss the whole
72        // Keyguard. If we need to authenticate, show the bouncer.
73        if (!mKeyguardView.dismiss()) {
74            mShowingSoon = true;
75
76            // Split up the work over multiple frames.
77            mChoreographer.postCallbackDelayed(Choreographer.CALLBACK_ANIMATION, mShowRunnable,
78                    null, 16);
79        }
80    }
81
82    private final Runnable mShowRunnable = new Runnable() {
83        @Override
84        public void run() {
85            mRoot.setVisibility(View.VISIBLE);
86            mKeyguardView.onResume();
87            mKeyguardView.startAppearAnimation();
88            mShowingSoon = false;
89        }
90    };
91
92    private void cancelShowRunnable() {
93        mChoreographer.removeCallbacks(Choreographer.CALLBACK_ANIMATION, mShowRunnable, null);
94        mShowingSoon = false;
95    }
96
97    public void showWithDismissAction(OnDismissAction r) {
98        ensureView();
99        mKeyguardView.setOnDismissAction(r);
100        show(false /* resetSecuritySelection */);
101    }
102
103    public void hide(boolean destroyView) {
104        cancelShowRunnable();
105         if (mKeyguardView != null) {
106            mKeyguardView.setOnDismissAction(null);
107            mKeyguardView.cleanUp();
108        }
109        if (destroyView) {
110            removeView();
111        } else if (mRoot != null) {
112            mRoot.setVisibility(View.INVISIBLE);
113        }
114    }
115
116    /**
117     * See {@link StatusBarKeyguardViewManager#startPreHideAnimation}.
118     */
119    public void startPreHideAnimation(Runnable runnable) {
120        if (mKeyguardView != null) {
121            mKeyguardView.startDisappearAnimation(runnable);
122        } else if (runnable != null) {
123            runnable.run();
124        }
125    }
126
127    /**
128     * Reset the state of the view.
129     */
130    public void reset() {
131        cancelShowRunnable();
132        inflateView();
133    }
134
135    public void onScreenTurnedOff() {
136        if (mKeyguardView != null && mRoot != null && mRoot.getVisibility() == View.VISIBLE) {
137            mKeyguardView.onPause();
138        }
139    }
140
141    public long getUserActivityTimeout() {
142        if (mKeyguardView != null) {
143            long timeout = mKeyguardView.getUserActivityTimeout();
144            if (timeout >= 0) {
145                return timeout;
146            }
147        }
148        return KeyguardViewMediator.AWAKE_INTERVAL_DEFAULT_MS;
149    }
150
151    public boolean isShowing() {
152        return mShowingSoon || (mRoot != null && mRoot.getVisibility() == View.VISIBLE);
153    }
154
155    public void prepare() {
156        boolean wasInitialized = mRoot != null;
157        ensureView();
158        if (wasInitialized) {
159            mKeyguardView.showPrimarySecurityScreen();
160        }
161    }
162
163    private void ensureView() {
164        if (mRoot == null) {
165            inflateView();
166        }
167    }
168
169    private void inflateView() {
170        removeView();
171        mRoot = (ViewGroup) LayoutInflater.from(mContext).inflate(R.layout.keyguard_bouncer, null);
172        mKeyguardView = (KeyguardViewBase) mRoot.findViewById(R.id.keyguard_host_view);
173        mKeyguardView.setLockPatternUtils(mLockPatternUtils);
174        mKeyguardView.setViewMediatorCallback(mCallback);
175        mContainer.addView(mRoot, mContainer.getChildCount());
176        mRoot.setVisibility(View.INVISIBLE);
177        mRoot.setSystemUiVisibility(View.STATUS_BAR_DISABLE_HOME);
178    }
179
180    private void removeView() {
181        if (mRoot != null && mRoot.getParent() == mContainer) {
182            mContainer.removeView(mRoot);
183            mRoot = null;
184        }
185    }
186
187    public boolean onBackPressed() {
188        return mKeyguardView != null && mKeyguardView.handleBackKey();
189    }
190
191    /**
192     * @return True if and only if the security method should be shown before showing the
193     * notifications on Keyguard, like SIM PIN/PUK.
194     */
195    public boolean needsFullscreenBouncer() {
196        if (mKeyguardView != null) {
197            SecurityMode mode = mKeyguardView.getSecurityMode();
198            return mode == SecurityMode.SimPin || mode == SecurityMode.SimPuk;
199        }
200        return false;
201    }
202
203    /**
204     * Like {@link #needsFullscreenBouncer}, but uses the currently visible security method, which
205     * makes this method much faster.
206     */
207    public boolean isFullscreenBouncer() {
208        if (mKeyguardView != null) {
209            SecurityMode mode = mKeyguardView.getCurrentSecurityMode();
210            return mode == SecurityMode.SimPin || mode == SecurityMode.SimPuk;
211        }
212        return false;
213    }
214
215    /**
216     * WARNING: This method might cause Binder calls.
217     */
218    public boolean isSecure() {
219        return mKeyguardView == null || mKeyguardView.getSecurityMode() != SecurityMode.None;
220    }
221
222    public boolean onMenuPressed() {
223        ensureView();
224        if (mKeyguardView.handleMenuKey()) {
225
226            // We need to show it in case it is secure. If not, it will get dismissed in any case.
227            mRoot.setVisibility(View.VISIBLE);
228            mKeyguardView.requestFocus();
229            mKeyguardView.onResume();
230            return true;
231        } else {
232            return false;
233        }
234    }
235
236    public boolean interceptMediaKey(KeyEvent event) {
237        ensureView();
238        return mKeyguardView.interceptMediaKey(event);
239    }
240}
241