blob: 3e499b2b0be731f5f901a9534532b4223d27836c [file] [log] [blame]
Jim Millerdcb3d842012-08-23 19:18:12 -07001/*
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 */
Jim Miller5ecd8112013-01-09 18:50:26 -080016package com.android.keyguard;
Jim Millerdcb3d842012-08-23 19:18:12 -070017
18import android.content.Context;
Chris Wrenc0ae9e62012-11-05 13:16:31 -050019import android.graphics.drawable.Drawable;
Uriel Rodriguez94c7b142012-10-12 15:00:48 -040020import android.os.PowerManager;
Brian Colonnab1b9a8a2013-03-29 11:52:42 -040021import android.os.RemoteException;
22import android.os.ServiceManager;
Jim Miller000464a2012-09-04 16:45:06 -070023import android.telephony.TelephonyManager;
Jim Millerdcb3d842012-08-23 19:18:12 -070024import android.util.AttributeSet;
Jim Miller000464a2012-09-04 16:45:06 -070025import android.util.Log;
Brian Colonnab1b9a8a2013-03-29 11:52:42 -040026import android.view.IRotationWatcher;
27import android.view.IWindowManager;
Jim Miller000464a2012-09-04 16:45:06 -070028import android.view.View;
Danielle Millett61413b52012-10-09 18:07:02 -040029import android.widget.ImageButton;
Jim Millerdcb3d842012-08-23 19:18:12 -070030import android.widget.LinearLayout;
31
32import com.android.internal.widget.LockPatternUtils;
33
Brian Colonnab1b9a8a2013-03-29 11:52:42 -040034import java.lang.Math;
35
Jim Millerdcb3d842012-08-23 19:18:12 -070036public class KeyguardFaceUnlockView extends LinearLayout implements KeyguardSecurityView {
37
Uriel Rodriguez94c7b142012-10-12 15:00:48 -040038 private static final String TAG = "FULKeyguardFaceUnlockView";
Danielle Millett61413b52012-10-09 18:07:02 -040039 private static final boolean DEBUG = false;
Jim Millerdcb3d842012-08-23 19:18:12 -070040 private KeyguardSecurityCallback mKeyguardSecurityCallback;
41 private LockPatternUtils mLockPatternUtils;
Jim Miller000464a2012-09-04 16:45:06 -070042 private BiometricSensorUnlock mBiometricUnlock;
Jim Miller000464a2012-09-04 16:45:06 -070043 private View mFaceUnlockAreaView;
Danielle Millett61413b52012-10-09 18:07:02 -040044 private ImageButton mCancelButton;
Chris Wrenc0ae9e62012-11-05 13:16:31 -050045 private SecurityMessageDisplay mSecurityMessageDisplay;
46 private View mEcaView;
47 private Drawable mBouncerFrame;
Jim Millerdcb3d842012-08-23 19:18:12 -070048
Danielle Millettf6d0fc12012-10-23 16:16:52 -040049 private boolean mIsShowing = false;
50 private final Object mIsShowingLock = new Object();
51
Brian Colonnab1b9a8a2013-03-29 11:52:42 -040052 private int mLastRotation;
53 private boolean mWatchingRotation;
54 private final IWindowManager mWindowManager =
55 IWindowManager.Stub.asInterface(ServiceManager.getService("window"));
56
57 private final IRotationWatcher mRotationWatcher = new IRotationWatcher.Stub() {
58 public void onRotationChanged(int rotation) {
59 if (DEBUG) Log.d(TAG, "onRotationChanged(): " + mLastRotation + "->" + rotation);
60
61 // If the difference between the new rotation value and the previous rotation value is
62 // equal to 2, the rotation change was 180 degrees. This stops the biometric unlock
63 // and starts it in the new position. This is not performed for 90 degree rotations
64 // since a 90 degree rotation is a configuration change, which takes care of this for
65 // us.
66 if (Math.abs(rotation - mLastRotation) == 2) {
67 if (mBiometricUnlock != null) {
68 mBiometricUnlock.stop();
69 maybeStartBiometricUnlock();
70 }
71 }
72 mLastRotation = rotation;
73 }
74 };
75
Jim Millerdcb3d842012-08-23 19:18:12 -070076 public KeyguardFaceUnlockView(Context context) {
77 this(context, null);
78 }
79
80 public KeyguardFaceUnlockView(Context context, AttributeSet attrs) {
81 super(context, attrs);
82 }
83
84 @Override
Jim Miller000464a2012-09-04 16:45:06 -070085 protected void onFinishInflate() {
86 super.onFinishInflate();
Jim Miller000464a2012-09-04 16:45:06 -070087
88 initializeBiometricUnlockView();
Chris Wrenc0ae9e62012-11-05 13:16:31 -050089
90 mSecurityMessageDisplay = new KeyguardMessageArea.Helper(this);
91 mEcaView = findViewById(R.id.keyguard_selector_fade_container);
92 View bouncerFrameView = findViewById(R.id.keyguard_bouncer_frame);
93 if (bouncerFrameView != null) {
94 mBouncerFrame = bouncerFrameView.getBackground();
95 }
Jim Miller000464a2012-09-04 16:45:06 -070096 }
97
98 @Override
Jim Millerdcb3d842012-08-23 19:18:12 -070099 public void setKeyguardCallback(KeyguardSecurityCallback callback) {
100 mKeyguardSecurityCallback = callback;
Jim Miller000464a2012-09-04 16:45:06 -0700101 // TODO: formalize this in the interface or factor it out
102 ((FaceUnlock)mBiometricUnlock).setKeyguardCallback(callback);
Jim Millerdcb3d842012-08-23 19:18:12 -0700103 }
104
105 @Override
106 public void setLockPatternUtils(LockPatternUtils utils) {
107 mLockPatternUtils = utils;
108 }
109
110 @Override
111 public void reset() {
112
113 }
114
115 @Override
Steven Rossfbb9c612012-09-27 07:47:55 -0400116 public void onDetachedFromWindow() {
Danielle Millett61413b52012-10-09 18:07:02 -0400117 if (DEBUG) Log.d(TAG, "onDetachedFromWindow()");
Steven Rossfbb9c612012-09-27 07:47:55 -0400118 if (mBiometricUnlock != null) {
Steven Ross9a9f4ce2012-10-16 13:56:37 -0400119 mBiometricUnlock.stop();
Steven Rossfbb9c612012-09-27 07:47:55 -0400120 }
Danielle Millettcade0042012-11-06 14:18:59 -0500121 KeyguardUpdateMonitor.getInstance(mContext).removeCallback(mUpdateCallback);
Brian Colonnab1b9a8a2013-03-29 11:52:42 -0400122 if (mWatchingRotation) {
123 try {
124 mWindowManager.removeRotationWatcher(mRotationWatcher);
125 mWatchingRotation = false;
126 } catch (RemoteException e) {
127 Log.e(TAG, "Remote exception when removing rotation watcher");
128 }
129 }
Steven Rossfbb9c612012-09-27 07:47:55 -0400130 }
131
132 @Override
Jim Millerdcb3d842012-08-23 19:18:12 -0700133 public void onPause() {
Danielle Millett61413b52012-10-09 18:07:02 -0400134 if (DEBUG) Log.d(TAG, "onPause()");
Jim Miller000464a2012-09-04 16:45:06 -0700135 if (mBiometricUnlock != null) {
Danielle Millett1108a2c2012-10-29 22:16:32 -0400136 mBiometricUnlock.stop();
Jim Miller000464a2012-09-04 16:45:06 -0700137 }
138 KeyguardUpdateMonitor.getInstance(mContext).removeCallback(mUpdateCallback);
Brian Colonnab1b9a8a2013-03-29 11:52:42 -0400139 if (mWatchingRotation) {
140 try {
141 mWindowManager.removeRotationWatcher(mRotationWatcher);
142 mWatchingRotation = false;
143 } catch (RemoteException e) {
144 Log.e(TAG, "Remote exception when removing rotation watcher");
145 }
146 }
Jim Millerdcb3d842012-08-23 19:18:12 -0700147 }
148
149 @Override
Chris Wrena042ac92012-11-07 11:37:06 -0500150 public void onResume(int reason) {
Danielle Millett61413b52012-10-09 18:07:02 -0400151 if (DEBUG) Log.d(TAG, "onResume()");
Danielle Millett5d2404d2012-11-01 00:05:27 -0400152 mIsShowing = KeyguardUpdateMonitor.getInstance(mContext).isKeyguardVisible();
Brian Colonnaa5239892013-04-15 11:45:40 -0400153 if (!KeyguardUpdateMonitor.getInstance(mContext).isSwitchingUser()) {
154 maybeStartBiometricUnlock();
155 }
Jim Miller000464a2012-09-04 16:45:06 -0700156 KeyguardUpdateMonitor.getInstance(mContext).registerCallback(mUpdateCallback);
Brian Colonnab1b9a8a2013-03-29 11:52:42 -0400157
158 // Registers a callback which handles stopping the biometric unlock and restarting it in
159 // the new position for a 180 degree rotation change.
160 if (!mWatchingRotation) {
161 try {
162 mLastRotation = mWindowManager.watchRotation(mRotationWatcher);
163 mWatchingRotation = true;
164 } catch (RemoteException e) {
165 Log.e(TAG, "Remote exception when adding rotation watcher");
166 }
167 }
Jim Millerdcb3d842012-08-23 19:18:12 -0700168 }
169
170 @Override
171 public boolean needsInput() {
172 return false;
173 }
174
175 @Override
176 public KeyguardSecurityCallback getCallback() {
177 return mKeyguardSecurityCallback;
178 }
179
Jim Miller000464a2012-09-04 16:45:06 -0700180 @Override
181 protected void onLayout(boolean changed, int l, int t, int r, int b) {
182 super.onLayout(changed, l, t, r, b);
183 mBiometricUnlock.initializeView(mFaceUnlockAreaView);
184 }
Jim Millerdcb3d842012-08-23 19:18:12 -0700185
Jim Miller000464a2012-09-04 16:45:06 -0700186 private void initializeBiometricUnlockView() {
Danielle Millettf6d0fc12012-10-23 16:16:52 -0400187 if (DEBUG) Log.d(TAG, "initializeBiometricUnlockView()");
Jim Miller000464a2012-09-04 16:45:06 -0700188 mFaceUnlockAreaView = findViewById(R.id.face_unlock_area_view);
189 if (mFaceUnlockAreaView != null) {
190 mBiometricUnlock = new FaceUnlock(mContext);
Danielle Millett61413b52012-10-09 18:07:02 -0400191
192 mCancelButton = (ImageButton) findViewById(R.id.face_unlock_cancel_button);
193 mCancelButton.setOnClickListener(new OnClickListener() {
194 @Override
195 public void onClick(View v) {
196 mBiometricUnlock.stopAndShowBackup();
197 }
198 });
Jim Miller000464a2012-09-04 16:45:06 -0700199 } else {
200 Log.w(TAG, "Couldn't find biometric unlock view");
201 }
202 }
Jim Millerdcb3d842012-08-23 19:18:12 -0700203
Jim Miller000464a2012-09-04 16:45:06 -0700204 /**
Danielle Millettf6d0fc12012-10-23 16:16:52 -0400205 * Starts the biometric unlock if it should be started based on a number of factors. If it
206 * should not be started, it either goes to the back up, or remains showing to prepare for
207 * it being started later.
Jim Miller000464a2012-09-04 16:45:06 -0700208 */
209 private void maybeStartBiometricUnlock() {
Danielle Millett61413b52012-10-09 18:07:02 -0400210 if (DEBUG) Log.d(TAG, "maybeStartBiometricUnlock()");
Jim Miller000464a2012-09-04 16:45:06 -0700211 if (mBiometricUnlock != null) {
212 KeyguardUpdateMonitor monitor = KeyguardUpdateMonitor.getInstance(mContext);
213 final boolean backupIsTimedOut = (
214 monitor.getFailedUnlockAttempts() >=
215 LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT);
Uriel Rodriguez94c7b142012-10-12 15:00:48 -0400216 PowerManager powerManager = (PowerManager) mContext.getSystemService(
217 Context.POWER_SERVICE);
Danielle Millettf6d0fc12012-10-23 16:16:52 -0400218
219 boolean isShowing;
220 synchronized(mIsShowingLock) {
221 isShowing = mIsShowing;
222 }
223
224 // Don't start it if the screen is off or if it's not showing, but keep this view up
225 // because we want it here and ready for when the screen turns on or when it does start
226 // showing.
227 if (!powerManager.isScreenOn() || !isShowing) {
228 mBiometricUnlock.stop(); // It shouldn't be running but calling this can't hurt.
229 return;
230 }
231
Brian Colonnab1b9a8a2013-03-29 11:52:42 -0400232 // Although these same conditions are handled in KeyguardSecurityModel, they are still
233 // necessary here. When a tablet is rotated 90 degrees, a configuration change is
234 // triggered and everything is torn down and reconstructed. That means
235 // KeyguardSecurityModel gets a chance to take care of the logic and doesn't even
236 // reconstruct KeyguardFaceUnlockView if the biometric unlock should be suppressed.
237 // However, for a 180 degree rotation, no configuration change is triggered, so only
238 // the logic here is capable of suppressing Face Unlock.
Danielle Millettd95c6592012-10-12 14:55:44 -0400239 if (monitor.getPhoneState() == TelephonyManager.CALL_STATE_IDLE
Brian Colonnab1b9a8a2013-03-29 11:52:42 -0400240 && monitor.isAlternateUnlockEnabled()
Jim Miller000464a2012-09-04 16:45:06 -0700241 && !monitor.getMaxBiometricUnlockAttemptsReached()
Danielle Millettf6d0fc12012-10-23 16:16:52 -0400242 && !backupIsTimedOut) {
Jim Miller000464a2012-09-04 16:45:06 -0700243 mBiometricUnlock.start();
244 } else {
Danielle Millett61413b52012-10-09 18:07:02 -0400245 mBiometricUnlock.stopAndShowBackup();
Jim Miller000464a2012-09-04 16:45:06 -0700246 }
247 }
248 }
Jim Millerdcb3d842012-08-23 19:18:12 -0700249
Jim Miller000464a2012-09-04 16:45:06 -0700250 KeyguardUpdateMonitorCallback mUpdateCallback = new KeyguardUpdateMonitorCallback() {
251 // We need to stop the biometric unlock when a phone call comes in
252 @Override
253 public void onPhoneStateChanged(int phoneState) {
Danielle Millett61413b52012-10-09 18:07:02 -0400254 if (DEBUG) Log.d(TAG, "onPhoneStateChanged(" + phoneState + ")");
Jim Miller000464a2012-09-04 16:45:06 -0700255 if (phoneState == TelephonyManager.CALL_STATE_RINGING) {
Danielle Millettf6d0fc12012-10-23 16:16:52 -0400256 if (mBiometricUnlock != null) {
257 mBiometricUnlock.stopAndShowBackup();
258 }
Jim Miller000464a2012-09-04 16:45:06 -0700259 }
260 }
Jim Millerdcb3d842012-08-23 19:18:12 -0700261
Jim Miller000464a2012-09-04 16:45:06 -0700262 @Override
Chris Wrenf41c61b2012-11-29 15:19:54 -0500263 public void onUserSwitching(int userId) {
Danielle Millett61413b52012-10-09 18:07:02 -0400264 if (DEBUG) Log.d(TAG, "onUserSwitched(" + userId + ")");
Jim Miller000464a2012-09-04 16:45:06 -0700265 if (mBiometricUnlock != null) {
266 mBiometricUnlock.stop();
267 }
Jim Milleree82f8f2012-10-01 16:26:18 -0700268 // No longer required; static value set by KeyguardViewMediator
269 // mLockPatternUtils.setCurrentUser(userId);
Jim Miller000464a2012-09-04 16:45:06 -0700270 }
Danielle Millettf6d0fc12012-10-23 16:16:52 -0400271
272 @Override
Brian Colonnaa5239892013-04-15 11:45:40 -0400273 public void onUserSwitchComplete(int userId) {
274 if (DEBUG) Log.d(TAG, "onUserSwitchComplete(" + userId + ")");
275 if (mBiometricUnlock != null) {
276 maybeStartBiometricUnlock();
277 }
278 }
279
280 @Override
Danielle Millettf6d0fc12012-10-23 16:16:52 -0400281 public void onKeyguardVisibilityChanged(boolean showing) {
282 if (DEBUG) Log.d(TAG, "onKeyguardVisibilityChanged(" + showing + ")");
283 boolean wasShowing = false;
284 synchronized(mIsShowingLock) {
285 wasShowing = mIsShowing;
286 mIsShowing = showing;
287 }
288 PowerManager powerManager = (PowerManager) mContext.getSystemService(
289 Context.POWER_SERVICE);
290 if (mBiometricUnlock != null) {
291 if (!showing && wasShowing) {
292 mBiometricUnlock.stop();
293 } else if (showing && powerManager.isScreenOn() && !wasShowing) {
294 maybeStartBiometricUnlock();
295 }
296 }
297 }
Jim Miller000464a2012-09-04 16:45:06 -0700298 };
Jim Millerdcb3d842012-08-23 19:18:12 -0700299
Jim Miller0ff7f012012-10-11 20:40:01 -0700300 @Override
Adam Cohen6fb841f2012-10-24 13:15:38 -0700301 public void showUsabilityHint() {
302 }
Chris Wrenc0ae9e62012-11-05 13:16:31 -0500303
304 @Override
305 public void showBouncer(int duration) {
306 KeyguardSecurityViewHelper.
307 showBouncer(mSecurityMessageDisplay, mEcaView, mBouncerFrame, duration);
308 }
309
310 @Override
311 public void hideBouncer(int duration) {
312 KeyguardSecurityViewHelper.
313 hideBouncer(mSecurityMessageDisplay, mEcaView, mBouncerFrame, duration);
314 }
315
Jim Millerdcb3d842012-08-23 19:18:12 -0700316}