KeyguardFaceUnlockView.java revision 25a272a9f6323f6a3513bb522d45e839449878ce
1/*
2 * Copyright (C) 2012 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 */
16package com.android.internal.policy.impl.keyguard;
17
18import android.content.Context;
19import android.graphics.drawable.Drawable;
20import android.os.PowerManager;
21import android.telephony.TelephonyManager;
22import android.util.AttributeSet;
23import android.util.Log;
24import android.view.View;
25import android.widget.ImageButton;
26import android.widget.LinearLayout;
27
28import com.android.internal.R;
29
30import com.android.internal.widget.LockPatternUtils;
31
32public class KeyguardFaceUnlockView extends LinearLayout implements KeyguardSecurityView {
33
34    private static final String TAG = "FULKeyguardFaceUnlockView";
35    private static final boolean DEBUG = false;
36    private KeyguardSecurityCallback mKeyguardSecurityCallback;
37    private LockPatternUtils mLockPatternUtils;
38    private BiometricSensorUnlock mBiometricUnlock;
39    private View mFaceUnlockAreaView;
40    private ImageButton mCancelButton;
41    private SecurityMessageDisplay mSecurityMessageDisplay;
42    private View mEcaView;
43    private Drawable mBouncerFrame;
44
45    private boolean mIsShowing = false;
46    private final Object mIsShowingLock = new Object();
47
48    public KeyguardFaceUnlockView(Context context) {
49        this(context, null);
50    }
51
52    public KeyguardFaceUnlockView(Context context, AttributeSet attrs) {
53        super(context, attrs);
54    }
55
56    @Override
57    protected void onFinishInflate() {
58        super.onFinishInflate();
59
60        initializeBiometricUnlockView();
61
62        mSecurityMessageDisplay = new KeyguardMessageArea.Helper(this);
63        mEcaView = findViewById(R.id.keyguard_selector_fade_container);
64        View bouncerFrameView = findViewById(R.id.keyguard_bouncer_frame);
65        if (bouncerFrameView != null) {
66            mBouncerFrame = bouncerFrameView.getBackground();
67        }
68    }
69
70    @Override
71    public void setKeyguardCallback(KeyguardSecurityCallback callback) {
72        mKeyguardSecurityCallback = callback;
73        // TODO: formalize this in the interface or factor it out
74        ((FaceUnlock)mBiometricUnlock).setKeyguardCallback(callback);
75    }
76
77    @Override
78    public void setLockPatternUtils(LockPatternUtils utils) {
79        mLockPatternUtils = utils;
80    }
81
82    @Override
83    public void reset() {
84
85    }
86
87    @Override
88    public void onDetachedFromWindow() {
89        if (DEBUG) Log.d(TAG, "onDetachedFromWindow()");
90        if (mBiometricUnlock != null) {
91            mBiometricUnlock.stop();
92        }
93        KeyguardUpdateMonitor.getInstance(mContext).removeCallback(mUpdateCallback);
94    }
95
96    @Override
97    public void onPause() {
98        if (DEBUG) Log.d(TAG, "onPause()");
99        if (mBiometricUnlock != null) {
100            mBiometricUnlock.stop();
101        }
102        KeyguardUpdateMonitor.getInstance(mContext).removeCallback(mUpdateCallback);
103    }
104
105    @Override
106    public void onResume(int reason) {
107        if (DEBUG) Log.d(TAG, "onResume()");
108        mIsShowing = KeyguardUpdateMonitor.getInstance(mContext).isKeyguardVisible();
109        maybeStartBiometricUnlock();
110        KeyguardUpdateMonitor.getInstance(mContext).registerCallback(mUpdateCallback);
111    }
112
113    @Override
114    public boolean needsInput() {
115        return false;
116    }
117
118    @Override
119    public KeyguardSecurityCallback getCallback() {
120        return mKeyguardSecurityCallback;
121    }
122
123    @Override
124    protected void onLayout(boolean changed, int l, int t, int r, int b) {
125        super.onLayout(changed, l, t, r, b);
126        mBiometricUnlock.initializeView(mFaceUnlockAreaView);
127    }
128
129    private void initializeBiometricUnlockView() {
130        if (DEBUG) Log.d(TAG, "initializeBiometricUnlockView()");
131        mFaceUnlockAreaView = findViewById(R.id.face_unlock_area_view);
132        if (mFaceUnlockAreaView != null) {
133            mBiometricUnlock = new FaceUnlock(mContext);
134
135            mCancelButton = (ImageButton) findViewById(R.id.face_unlock_cancel_button);
136            mCancelButton.setOnClickListener(new OnClickListener() {
137                @Override
138                public void onClick(View v) {
139                    mBiometricUnlock.stopAndShowBackup();
140                }
141            });
142        } else {
143            Log.w(TAG, "Couldn't find biometric unlock view");
144        }
145    }
146
147    /**
148     * Starts the biometric unlock if it should be started based on a number of factors.  If it
149     * should not be started, it either goes to the back up, or remains showing to prepare for
150     * it being started later.
151     */
152    private void maybeStartBiometricUnlock() {
153        if (DEBUG) Log.d(TAG, "maybeStartBiometricUnlock()");
154        if (mBiometricUnlock != null) {
155            KeyguardUpdateMonitor monitor = KeyguardUpdateMonitor.getInstance(mContext);
156            final boolean backupIsTimedOut = (
157                    monitor.getFailedUnlockAttempts() >=
158                    LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT);
159            PowerManager powerManager = (PowerManager) mContext.getSystemService(
160                    Context.POWER_SERVICE);
161
162            boolean isShowing;
163            synchronized(mIsShowingLock) {
164                isShowing = mIsShowing;
165            }
166
167            // Don't start it if the screen is off or if it's not showing, but keep this view up
168            // because we want it here and ready for when the screen turns on or when it does start
169            // showing.
170            if (!powerManager.isScreenOn() || !isShowing) {
171                mBiometricUnlock.stop(); // It shouldn't be running but calling this can't hurt.
172                return;
173            }
174
175            // TODO: Some of these conditions are handled in KeyguardSecurityModel and may not be
176            // necessary here.
177            if (monitor.getPhoneState() == TelephonyManager.CALL_STATE_IDLE
178                    && !monitor.getMaxBiometricUnlockAttemptsReached()
179                    && !backupIsTimedOut) {
180                mBiometricUnlock.start();
181            } else {
182                mBiometricUnlock.stopAndShowBackup();
183            }
184        }
185    }
186
187    KeyguardUpdateMonitorCallback mUpdateCallback = new KeyguardUpdateMonitorCallback() {
188        // We need to stop the biometric unlock when a phone call comes in
189        @Override
190        public void onPhoneStateChanged(int phoneState) {
191            if (DEBUG) Log.d(TAG, "onPhoneStateChanged(" + phoneState + ")");
192            if (phoneState == TelephonyManager.CALL_STATE_RINGING) {
193                if (mBiometricUnlock != null) {
194                    mBiometricUnlock.stopAndShowBackup();
195                }
196            }
197        }
198
199        @Override
200        public void onUserSwitching(int userId) {
201            if (DEBUG) Log.d(TAG, "onUserSwitched(" + userId + ")");
202            if (mBiometricUnlock != null) {
203                mBiometricUnlock.stop();
204            }
205            // No longer required; static value set by KeyguardViewMediator
206            // mLockPatternUtils.setCurrentUser(userId);
207        }
208
209        @Override
210        public void onKeyguardVisibilityChanged(boolean showing) {
211            if (DEBUG) Log.d(TAG, "onKeyguardVisibilityChanged(" + showing + ")");
212            boolean wasShowing = false;
213            synchronized(mIsShowingLock) {
214                wasShowing = mIsShowing;
215                mIsShowing = showing;
216            }
217            PowerManager powerManager = (PowerManager) mContext.getSystemService(
218                    Context.POWER_SERVICE);
219            if (mBiometricUnlock != null) {
220                if (!showing && wasShowing) {
221                    mBiometricUnlock.stop();
222                } else if (showing && powerManager.isScreenOn() && !wasShowing) {
223                    maybeStartBiometricUnlock();
224                }
225            }
226        }
227    };
228
229    @Override
230    public void showUsabilityHint() {
231    }
232
233    @Override
234    public void showBouncer(int duration) {
235        KeyguardSecurityViewHelper.
236                showBouncer(mSecurityMessageDisplay, mEcaView, mBouncerFrame, duration);
237    }
238
239    @Override
240    public void hideBouncer(int duration) {
241        KeyguardSecurityViewHelper.
242                hideBouncer(mSecurityMessageDisplay, mEcaView, mBouncerFrame, duration);
243    }
244
245}
246