diff options
| author | 2012-04-26 14:41:18 -0700 | |
|---|---|---|
| committer | 2012-04-26 14:41:18 -0700 | |
| commit | 6bc75916401ba85efd19a09a834f4c91cdd8c7f5 (patch) | |
| tree | 76caadec612fa6c00c13b378de4d78420064b76f | |
| parent | 9ad1b113260dfb1ac04a7c30e804e24e74dada4f (diff) | |
| parent | ea8441e22a4316cb6e78dd8bf461d3e658545b64 (diff) | |
Merge "Changes to biometric sensor interface in lockscreen" into jb-dev
5 files changed, 242 insertions, 161 deletions
diff --git a/policy/src/com/android/internal/policy/impl/BiometricSensorUnlock.java b/policy/src/com/android/internal/policy/impl/BiometricSensorUnlock.java index c36e1481adb0..ad26845366f4 100644 --- a/policy/src/com/android/internal/policy/impl/BiometricSensorUnlock.java +++ b/policy/src/com/android/internal/policy/impl/BiometricSensorUnlock.java @@ -19,33 +19,63 @@ package com.android.internal.policy.impl; import android.view.View; interface BiometricSensorUnlock { - // Returns 'true' if the biometric sensor has started its unlock procedure but has not yet - // accepted or rejected the user. + /** + * Initializes the view provided for the biometric unlock UI to work within. The provided area + * completely covers the backup unlock mechanism. The view is then displayed in the same manner + * as if {@link BiometricSensorUnlock#show(long)} was called with a timeout of 0. + * @param biometricUnlockView View provided for the biometric unlock UI. + */ + public void initializeView(View biometricUnlockView); + + /** + * Indicates whether the biometric unlock is running. Before + * {@link BiometricSensorUnlock#start} is called, isRunning() returns false. After a successful + * call to {@link BiometricSensorUnlock#start}, isRunning() returns true until the biometric + * unlock completes, {@link BiometricSensorUnlock#stop} has been called, or an error has + * forced the biometric unlock to stop. + * @return whether the biometric unlock is currently running. + */ public boolean isRunning(); - // Show the interface, but don't start the unlock procedure. The interface should disappear - // after the specified timeout. If the timeout is 0, the interface shows until another event, - // such as calling hide(), causes it to disappear. - // Called on the UI Thread + /** + * Covers the backup unlock mechanism by showing the contents of the view initialized in + * {@link BiometricSensorUnlock#initializeView(View)}. The view should disappear after the + * specified timeout. If the timeout is 0, the interface shows until another event, such as + * calling {@link BiometricSensorUnlock#hide()}, causes it to disappear. Called on the UI + * thread. + * @param timeoutMilliseconds Amount of time in milliseconds to display the view before + * disappearing. A value of 0 means the view should remain visible. + */ public void show(long timeoutMilliseconds); - // Hide the interface, if any, exposing the lockscreen. + /** + * Uncovers the backup unlock mechanism by hiding the contents of the view initialized in + * {@link BiometricSensorUnlock#initializeView(View)}. + */ public void hide(); - // Stop the unlock procedure if running. Returns 'true' if it was in fact running. - public boolean stop(); - - // Start the unlock procedure. Returns ‘false’ if it can’t be started or if the backup should - // be used. - // Called on the UI thread. - public boolean start(boolean suppressBiometricUnlock); + /** + * Binds to the biometric unlock service and starts the unlock procedure. Called on the UI + * thread. + * @return false if it can't be started or the backup should be used. + */ + public boolean start(); - // Provide a view to work within. - public void initializeAreaView(View topView); + /** + * Stops the biometric unlock procedure and unbinds from the service. + * @return whether the biometric unlock was running when called. + */ + public boolean stop(); - // Clean up any resources used by the biometric unlock. + /** + * Cleans up any resources used by the biometric unlock. + */ public void cleanUp(); - // Returns the Device Policy Manager quality (e.g. PASSWORD_QUALITY_BIOMETRIC_WEAK). + /** + * Gets the Device Policy Manager quality of the biometric unlock sensor + * (e.g., PASSWORD_QUALITY_BIOMETRIC_WEAK). + * @return biometric unlock sensor quality, as defined by Device Policy Manager. + */ public int getQuality(); } diff --git a/policy/src/com/android/internal/policy/impl/FaceUnlock.java b/policy/src/com/android/internal/policy/impl/FaceUnlock.java index ac86141fb413..16d4003354d2 100644 --- a/policy/src/com/android/internal/policy/impl/FaceUnlock.java +++ b/policy/src/com/android/internal/policy/impl/FaceUnlock.java @@ -40,31 +40,34 @@ public class FaceUnlock implements BiometricSensorUnlock, Handler.Callback { private static final String TAG = "FULLockscreen"; private final Context mContext; + private final LockPatternUtils mLockPatternUtils; private final KeyguardUpdateMonitor mUpdateMonitor; + // TODO: is mServiceRunning needed or can we just use mIsRunning or check if mService is null? + private boolean mServiceRunning = false; + private final Object mServiceRunningLock = new Object(); private IFaceLockInterface mService; private boolean mBoundToService = false; - private View mAreaView; + private View mFaceUnlockView; private Handler mHandler; private final int MSG_SHOW_AREA_VIEW = 0; private final int MSG_HIDE_AREA_VIEW = 1; - private boolean mServiceRunning = false; - private final Object mServiceRunningLock = new Object(); + // TODO: This was added for the purpose of adhering to what the biometric interface expects + // the isRunning() function to return. However, it is probably not necessary to have both + // mRunning and mServiceRunning. I'd just rather wait to change that logic. + private boolean mIsRunning = false; // Long enough to stay visible while the service starts // Short enough to not have to wait long for backup if service fails to start or crashes // The service can take a couple of seconds to start on the first try after boot private final int VIEW_AREA_SERVICE_TIMEOUT = 3000; - // So the user has a consistent amount of time when brought to the backup method from FaceLock + // So the user has a consistent amount of time when brought to the backup method from Face + // Unlock private final int BACKUP_LOCK_TIMEOUT = 5000; - /** - * Used to lookup the state of the lock pattern - */ - private final LockPatternUtils mLockPatternUtils; KeyguardScreenCallback mKeyguardScreenCallback; @@ -77,102 +80,116 @@ public class FaceUnlock implements BiometricSensorUnlock, Handler.Callback { mHandler = new Handler(this); } + /** + * Stores and displays the view that Face Unlock is allowed to draw within. + * TODO: since the layout object will eventually be shared by multiple biometric unlock + * methods, we will have to add our other views (background, cancel button) here. + */ + public void initializeView(View biometricUnlockView) { + mFaceUnlockView = biometricUnlockView; + show(0); + } + + /** + * Indicates whether Face Unlock is currently running. + */ public boolean isRunning() { - return mServiceRunning; + return mIsRunning; } - // Shows the FaceLock area for a period of time - // Called on the UI thread + /** + * Sets the Face Unlock view to visible, hiding it after the specified amount of time. If + * timeoutMillis is 0, no hide is performed. + */ public void show(long timeoutMillis) { removeAreaDisplayMessages(); - showArea(); - if (timeoutMillis > 0) + if (mFaceUnlockView != null) { + mFaceUnlockView.setVisibility(View.VISIBLE); + } + if (timeoutMillis > 0) { mHandler.sendEmptyMessageDelayed(MSG_HIDE_AREA_VIEW, timeoutMillis); + } } - // Hides the FaceLock area immediately + /** + * Hides the Face Unlock view. + */ public void hide() { // Remove messages to prevent a delayed show message from undo-ing the hide removeAreaDisplayMessages(); mHandler.sendEmptyMessage(MSG_HIDE_AREA_VIEW); } - // Tells FaceLock to stop and then unbinds from the FaceLock service + /** + * Binds to the Face Unlock service. Face Unlock will be started when the bind completes. The + * Face Unlock area is displayed to hide the backup while the service is starting up. + */ + public boolean start() { + if (mIsRunning) { + Log.w(TAG, "start() called when already running"); + } + + // Show Face Unlock view, but only for a little bit so lockpattern will become visible if + // Face Unlock fails to start or crashes + // This must show before bind to guarantee that Face Unlock has a place to display + show(VIEW_AREA_SERVICE_TIMEOUT); + if (!mBoundToService) { + if (DEBUG) Log.d(TAG, "before bind to Face Unlock service"); + mContext.bindService(new Intent(IFaceLockInterface.class.getName()), + mConnection, + Context.BIND_AUTO_CREATE, + mLockPatternUtils.getCurrentUser()); + if (DEBUG) Log.d(TAG, "after bind to Face Unlock service"); + mBoundToService = true; + } else { + Log.w(TAG, "Attempt to bind to Face Unlock when already bound"); + } + + // When switching between portrait and landscape view while Face Unlock is running, the + // screen will eventually go dark unless we poke the wakelock when Face Unlock is + // restarted + mKeyguardScreenCallback.pokeWakelock(); + + mIsRunning = true; + return true; + } + + /** + * Stops Face Unlock and unbinds from the service. + */ public boolean stop() { - boolean wasRunning = false; + boolean mWasRunning = mIsRunning; stopUi(); if (mBoundToService) { - wasRunning = true; - if (DEBUG) Log.d(TAG, "before unbind from FaceLock service"); + if (DEBUG) Log.d(TAG, "before unbind from Face Unlock service"); if (mService != null) { try { - mService.unregisterCallback(mFaceLockCallback); + mService.unregisterCallback(mFaceUnlockCallback); } catch (RemoteException e) { // Not much we can do } } mContext.unbindService(mConnection); - if (DEBUG) Log.d(TAG, "after unbind from FaceLock service"); + if (DEBUG) Log.d(TAG, "after unbind from Face Unlock service"); mBoundToService = false; } else { // This is usually not an error when this happens. Sometimes we will tell it to // unbind multiple times because it's called from both onWindowFocusChanged and // onDetachedFromWindow. - if (DEBUG) Log.d(TAG, "Attempt to unbind from FaceLock when not bound"); + if (DEBUG) Log.d(TAG, "Attempt to unbind from Face Unlock when not bound"); } - - return wasRunning; + mIsRunning = false; + return mWasRunning; } /** - * When screen is turned on and focused, need to bind to FaceLock service if we are using - * FaceLock, but only if we're not dealing with a call - * Called on the UI thread + * Frees up resources used by Face Unlock and stops it if it is still running. */ - public boolean start(boolean suppressBiometricUnlock) { - final boolean tooManyFaceUnlockTries = mUpdateMonitor.getMaxFaceUnlockAttemptsReached(); - final int failedBackupAttempts = mUpdateMonitor.getFailedAttempts(); - final boolean backupIsTimedOut = - (failedBackupAttempts >= LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT); - if (tooManyFaceUnlockTries) Log.i(TAG, "tooManyFaceUnlockTries: " + tooManyFaceUnlockTries); - if (mUpdateMonitor.getPhoneState() == TelephonyManager.CALL_STATE_IDLE - && !suppressBiometricUnlock - && !tooManyFaceUnlockTries - && !backupIsTimedOut) { - // Show FaceLock area, but only for a little bit so lockpattern will become visible if - // FaceLock fails to start or crashes - // This must show before bind to guarantee that Face Unlock has a place to display - show(VIEW_AREA_SERVICE_TIMEOUT); - - bind(); - - // When switching between portrait and landscape view while FaceLock is running, the - // screen will eventually go dark unless we poke the wakelock when FaceLock is - // restarted - mKeyguardScreenCallback.pokeWakelock(); - } else { - hide(); - return false; - } - - return true; - } - - // Takes care of FaceLock area when layout is created - public void initializeAreaView(View topView) { - mAreaView = topView.findViewById(R.id.faceLockAreaView); - if (mAreaView == null) { - Log.e(TAG, "Layout does not have areaView and FaceLock is enabled"); - } else { - show(0); - } - } - public void cleanUp() { if (mService != null) { try { - mService.unregisterCallback(mFaceLockCallback); + mService.unregisterCallback(mFaceUnlockCallback); } catch (RemoteException e) { // Not much we can do } @@ -181,30 +198,31 @@ public class FaceUnlock implements BiometricSensorUnlock, Handler.Callback { } } + /** + * Returns the Device Policy Manager quality for Face Unlock, which is BIOMETRIC_WEAK. + */ public int getQuality() { return DevicePolicyManager.PASSWORD_QUALITY_BIOMETRIC_WEAK; } - // Shows the FaceLock area - // Called on the UI thread - private void showArea() { - if (mAreaView != null) { - mAreaView.setVisibility(View.VISIBLE); - } - } - - // Handles covering or exposing FaceLock area on the client side when FaceLock starts or stops - // This needs to be done in a handler because the call could be coming from a callback from the - // FaceLock service that is in a thread that can't modify the UI + /** + * Handles showing the Face Unlock view (hiding the backup lock) and hiding the Face Unlock view + * (exposing the backup lock). In cases where 'show' needs to happen immediately, + * setVisibility() is called directly (without using this handler). This handler is used when + * 'show' needs to happen from a non-UI thread. It also handles hide() messages since they + * often require a delay. + */ @Override public boolean handleMessage(Message msg) { switch (msg.what) { case MSG_SHOW_AREA_VIEW: - showArea(); + if (mFaceUnlockView != null) { + mFaceUnlockView.setVisibility(View.VISIBLE); + } break; case MSG_HIDE_AREA_VIEW: - if (mAreaView != null) { - mAreaView.setVisibility(View.INVISIBLE); + if (mFaceUnlockView != null) { + mFaceUnlockView.setVisibility(View.INVISIBLE); } break; default: @@ -214,53 +232,44 @@ public class FaceUnlock implements BiometricSensorUnlock, Handler.Callback { return true; } - // Removes show and hide messages from the message queue + /** + * Removes show and hide messages from the message queue + */ private void removeAreaDisplayMessages() { mHandler.removeMessages(MSG_SHOW_AREA_VIEW); mHandler.removeMessages(MSG_HIDE_AREA_VIEW); } - // Binds to FaceLock service. This call does not tell it to start, but it causes the service - // to call the onServiceConnected callback, which then starts FaceLock. - private void bind() { - if (!mBoundToService) { - if (DEBUG) Log.d(TAG, "before bind to FaceLock service"); - mContext.bindService(new Intent(IFaceLockInterface.class.getName()), - mConnection, - Context.BIND_AUTO_CREATE, - mLockPatternUtils.getCurrentUser()); - if (DEBUG) Log.d(TAG, "after bind to FaceLock service"); - mBoundToService = true; - } else { - Log.w(TAG, "Attempt to bind to FaceLock when already bound"); - } - } - private ServiceConnection mConnection = new ServiceConnection() { - // Completes connection, registers callback and starts FaceLock when service is bound + /** + * Completes connection, registers callback, and starts Face Unlock when service is bound + */ @Override public void onServiceConnected(ComponentName className, IBinder iservice) { mService = IFaceLockInterface.Stub.asInterface(iservice); - if (DEBUG) Log.d(TAG, "Connected to FaceLock service"); + if (DEBUG) Log.d(TAG, "Connected to Face Unlock service"); try { - mService.registerCallback(mFaceLockCallback); + mService.registerCallback(mFaceUnlockCallback); } catch (RemoteException e) { - Log.e(TAG, "Caught exception connecting to FaceLock: " + e.toString()); + Log.e(TAG, "Caught exception connecting to Face Unlock: " + e.toString()); mService = null; mBoundToService = false; + mIsRunning = false; return; } - if (mAreaView != null) { + if (mFaceUnlockView != null) { int[] position; position = new int[2]; - mAreaView.getLocationInWindow(position); - startUi(mAreaView.getWindowToken(), position[0], position[1], - mAreaView.getWidth(), mAreaView.getHeight()); + mFaceUnlockView.getLocationInWindow(position); + startUi(mFaceUnlockView.getWindowToken(), position[0], position[1], + mFaceUnlockView.getWidth(), mFaceUnlockView.getHeight()); } } - // Cleans up if FaceLock service unexpectedly disconnects + /** + * Cleans up if Face Unlock service unexpectedly disconnects + */ @Override public void onServiceDisconnected(ComponentName className) { synchronized(mServiceRunningLock) { @@ -268,20 +277,23 @@ public class FaceUnlock implements BiometricSensorUnlock, Handler.Callback { mServiceRunning = false; } mBoundToService = false; - Log.w(TAG, "Unexpected disconnect from FaceLock service"); + mIsRunning = false; + Log.w(TAG, "Unexpected disconnect from Face Unlock service"); } }; - // Tells the FaceLock service to start displaying its UI and perform recognition + /** + * Tells the Face Unlock service to start displaying its UI and perform recognition + */ private void startUi(IBinder windowToken, int x, int y, int w, int h) { synchronized (mServiceRunningLock) { if (!mServiceRunning) { - if (DEBUG) Log.d(TAG, "Starting FaceLock"); + if (DEBUG) Log.d(TAG, "Starting Face Unlock"); try { mService.startUi(windowToken, x, y, w, h, mLockPatternUtils.isBiometricWeakLivelinessEnabled()); } catch (RemoteException e) { - Log.e(TAG, "Caught exception starting FaceLock: " + e.toString()); + Log.e(TAG, "Caught exception starting Face Unlock: " + e.toString()); return; } mServiceRunning = true; @@ -291,30 +303,36 @@ public class FaceUnlock implements BiometricSensorUnlock, Handler.Callback { } } - // Tells the FaceLock service to stop displaying its UI and stop recognition + /** + * Tells the Face Unlock service to stop displaying its UI and stop recognition + */ private void stopUi() { - // Note that attempting to stop FaceLock when it's not running is not an issue. - // FaceLock can return, which stops it and then we try to stop it when the + // Note that attempting to stop Face Unlock when it's not running is not an issue. + // Face Unlock can return, which stops it and then we try to stop it when the // screen is turned off. That's why we check. synchronized (mServiceRunningLock) { if (mServiceRunning) { try { - if (DEBUG) Log.d(TAG, "Stopping FaceLock"); + if (DEBUG) Log.d(TAG, "Stopping Face Unlock"); mService.stopUi(); } catch (RemoteException e) { - Log.e(TAG, "Caught exception stopping FaceLock: " + e.toString()); + Log.e(TAG, "Caught exception stopping Face Unlock: " + e.toString()); } mServiceRunning = false; } } } - // Implements the FaceLock service callback interface defined in AIDL - private final IFaceLockCallback mFaceLockCallback = new IFaceLockCallback.Stub() { - // Stops the FaceLock UI and indicates that the phone should be unlocked + /** + * Implements the biometric unlock service callback interface defined in AIDL + */ + private final IFaceLockCallback mFaceUnlockCallback = new IFaceLockCallback.Stub() { + /** + * Stops the Face Unlock UI and indicates that the phone should be unlocked + */ @Override public void unlock() { - if (DEBUG) Log.d(TAG, "FaceLock unlock()"); + if (DEBUG) Log.d(TAG, "unlock()"); // Keep fallback covered removeAreaDisplayMessages(); @@ -326,38 +344,46 @@ public class FaceUnlock implements BiometricSensorUnlock, Handler.Callback { mKeyguardScreenCallback.reportSuccessfulUnlockAttempt(); } - // Stops the FaceLock UI and exposes the backup method without unlocking - // This means the user has cancelled out + /** + * Stops the Face Unlock UI and exposes the backup method without unlocking + * This means the user has cancelled out + */ @Override public void cancel() { - if (DEBUG) Log.d(TAG, "FaceLock cancel()"); + if (DEBUG) Log.d(TAG, "cancel()"); hide(); // Expose fallback stop(); mKeyguardScreenCallback.pokeWakelock(BACKUP_LOCK_TIMEOUT); } - // Stops the FaceLock UI and exposes the backup method without unlocking - // This means FaceLock failed to recognize them + /** + * Stops the Face Unlock UI and exposes the backup method without unlocking + * This means Face Unlock failed to recognize them + */ @Override public void reportFailedAttempt() { - if (DEBUG) Log.d(TAG, "FaceLock reportFailedAttempt()"); - mUpdateMonitor.reportFailedFaceUnlockAttempt(); + if (DEBUG) Log.d(TAG, "reportFailedAttempt()"); + mUpdateMonitor.reportFailedBiometricUnlockAttempt(); hide(); // Expose fallback stop(); mKeyguardScreenCallback.pokeWakelock(BACKUP_LOCK_TIMEOUT); } - // Removes the black area that covers the backup unlock method + /** + * Removes the black area that covers the backup unlock method + **/ @Override public void exposeFallback() { - if (DEBUG) Log.d(TAG, "FaceLock exposeFallback()"); + if (DEBUG) Log.d(TAG, "exposeFallback()"); hide(); // Expose fallback } - // Allows the Face Unlock service to poke the wake lock to keep the lockscreen alive + /** + * Allows the Face Unlock service to poke the wake lock to keep the lockscreen alive + */ @Override public void pokeWakelock() { - if (DEBUG) Log.d(TAG, "FaceLock pokeWakelock()"); + if (DEBUG) Log.d(TAG, "pokeWakelock()"); mKeyguardScreenCallback.pokeWakelock(); } }; diff --git a/policy/src/com/android/internal/policy/impl/KeyguardStatusViewManager.java b/policy/src/com/android/internal/policy/impl/KeyguardStatusViewManager.java index 25af2e6f944b..a6986de378d3 100644 --- a/policy/src/com/android/internal/policy/impl/KeyguardStatusViewManager.java +++ b/policy/src/com/android/internal/policy/impl/KeyguardStatusViewManager.java @@ -303,8 +303,10 @@ class KeyguardStatusViewManager implements OnClickListener { mUpdateMonitor.registerInfoCallback(mInfoCallback); mUpdateMonitor.registerSimStateCallback(mSimStateCallback); resetStatusInfo(); - //Issue the faceunlock failure message in a centralized place - if (mUpdateMonitor.getMaxFaceUnlockAttemptsReached()) { + // Issue the biometric unlock failure message in a centralized place + // TODO: we either need to make the Face Unlock multiple failures string a more general + // 'biometric unlock' or have each biometric unlock handle this on their own. + if (mUpdateMonitor.getMaxBiometricUnlockAttemptsReached()) { setInstructionText(getContext().getString(R.string.faceunlock_multiple_failures)); } } diff --git a/policy/src/com/android/internal/policy/impl/KeyguardUpdateMonitor.java b/policy/src/com/android/internal/policy/impl/KeyguardUpdateMonitor.java index a4723751d74c..d340516d296b 100644 --- a/policy/src/com/android/internal/policy/impl/KeyguardUpdateMonitor.java +++ b/policy/src/com/android/internal/policy/impl/KeyguardUpdateMonitor.java @@ -82,8 +82,8 @@ public class KeyguardUpdateMonitor { private CharSequence mTelephonySpn; private int mFailedAttempts = 0; - private int mFailedFaceUnlockAttempts = 0; - private static final int FAILED_FACE_UNLOCK_ATTEMPTS_BEFORE_BACKUP = 15; + private int mFailedBiometricUnlockAttempts = 0; + private static final int FAILED_BIOMETRIC_UNLOCK_ATTEMPTS_BEFORE_BACKUP = 15; private boolean mClockVisible; @@ -703,7 +703,7 @@ public class KeyguardUpdateMonitor { public void clearFailedAttempts() { mFailedAttempts = 0; - mFailedFaceUnlockAttempts = 0; + mFailedBiometricUnlockAttempts = 0; } public void reportFailedAttempt() { @@ -718,12 +718,12 @@ public class KeyguardUpdateMonitor { return mPhoneState; } - public void reportFailedFaceUnlockAttempt() { - mFailedFaceUnlockAttempts++; + public void reportFailedBiometricUnlockAttempt() { + mFailedBiometricUnlockAttempts++; } - public boolean getMaxFaceUnlockAttemptsReached() { - return mFailedFaceUnlockAttempts >= FAILED_FACE_UNLOCK_ATTEMPTS_BEFORE_BACKUP; + public boolean getMaxBiometricUnlockAttemptsReached() { + return mFailedBiometricUnlockAttempts >= FAILED_BIOMETRIC_UNLOCK_ATTEMPTS_BEFORE_BACKUP; } public boolean isSimLocked() { diff --git a/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java b/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java index 7e2985deb5dc..010c8d676f55 100644 --- a/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java +++ b/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java @@ -580,7 +580,7 @@ public class LockPatternKeyguardView extends KeyguardViewBase { restoreWidgetState(); if (mBiometricUnlock != null && startBiometricUnlock) { - mBiometricUnlock.start(mSuppressBiometricUnlock); + maybeStartBiometricUnlock(); } } @@ -623,7 +623,7 @@ public class LockPatternKeyguardView extends KeyguardViewBase { } else { mHasDialog = false; if (mBiometricUnlock != null && startBiometricUnlock) { - mBiometricUnlock.start(mSuppressBiometricUnlock); + maybeStartBiometricUnlock(); } } } @@ -855,7 +855,7 @@ public class LockPatternKeyguardView extends KeyguardViewBase { } recreateUnlockScreen(unlockMode); if (mBiometricUnlock != null && restartBiometricUnlock) { - mBiometricUnlock.start(mSuppressBiometricUnlock); + maybeStartBiometricUnlock(); } } } @@ -971,7 +971,10 @@ public class LockPatternKeyguardView extends KeyguardViewBase { initializeTransportControlView(unlockView); if (mBiometricUnlock != null) { - mBiometricUnlock.initializeAreaView(unlockView); + // TODO: make faceLockAreaView a more general biometricUnlockView + // We will need to add our Face Unlock specific child views programmatically in + // initializeView rather than having them in the XML files. + mBiometricUnlock.initializeView(unlockView.findViewById(R.id.faceLockAreaView)); } mUnlockScreenMode = unlockMode; @@ -1154,4 +1157,24 @@ public class LockPatternKeyguardView extends KeyguardViewBase { return mBitmap.getHeight(); } } + + /** + * Starts the biometric unlock if it should be started based on a number of factors including + * the mSuppressBiometricUnlock flag. If it should not be started, it hides the biometric + * unlock area. + */ + private void maybeStartBiometricUnlock() { + if (mBiometricUnlock != null) { + final boolean backupIsTimedOut = (mUpdateMonitor.getFailedAttempts() >= + LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT); + if (!mSuppressBiometricUnlock + && mUpdateMonitor.getPhoneState() == TelephonyManager.CALL_STATE_IDLE + && !mUpdateMonitor.getMaxBiometricUnlockAttemptsReached() + && !backupIsTimedOut) { + mBiometricUnlock.start(); + } else { + mBiometricUnlock.hide(); + } + } + } } |