diff options
author | Danielle Millett <dmillett@google.com> | 2012-10-09 18:07:02 -0400 |
---|---|---|
committer | Danielle Millett <dmillett@google.com> | 2012-10-09 18:15:49 -0400 |
commit | 61413b5ed215accd7b4f3eaf80edeab2f330aa49 (patch) | |
tree | bd6388b4b03c217ce720d9050d2e1267a7ec44d6 | |
parent | 6be35dd636bd530a781e997ea9f9a43fc82a1fef (diff) | |
download | frameworks_base-61413b5ed215accd7b4f3eaf80edeab2f330aa49.zip frameworks_base-61413b5ed215accd7b4f3eaf80edeab2f330aa49.tar.gz frameworks_base-61413b5ed215accd7b4f3eaf80edeab2f330aa49.tar.bz2 |
Face Unlock is shown correctly during a phone call - fix b/7271718
If the user was in the middle of a phone call and went to the lock screen
it would show a black box with an X, but Face Unlock wouldn't pop up and
the X was unresponsive.
There were a few issues causing this. The X on the default view wasn't a
button, so it has been changed to a button which will go to the backup
lock. The concept of show() and hide() in FaceUnlock.java are obsolete
because Face Unlock is no longer being overlayed on top of the backup so
there's isn't a black box to show or hide. In addition, since it's not being
overlayed, Face Unlock doesn't cover the backup lock so fading to the backup
looks janky. The flip animation is more appropriate.
Change-Id: I730aa4bbce42b4656ee1bce61352b8aefbd6892d
6 files changed, 53 insertions, 114 deletions
diff --git a/core/res/res/layout/keyguard_face_unlock_view.xml b/core/res/res/layout/keyguard_face_unlock_view.xml index 60f0492..e25d035 100644 --- a/core/res/res/layout/keyguard_face_unlock_view.xml +++ b/core/res/res/layout/keyguard_face_unlock_view.xml @@ -46,13 +46,14 @@ android:background="@color/facelock_spotlight_mask" /> - <ImageView - android:id="@+id/cancel_button" + <ImageButton + android:id="@+id/face_unlock_cancel_button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:padding="5dip" android:layout_alignParentTop="true" android:layout_alignParentEnd="true" + android:background="#00000000" android:src="@drawable/ic_facial_backup" /> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 281d92a..1b175ad 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -1230,6 +1230,7 @@ <java-symbol type="id" name="eight" /> <java-symbol type="id" name="emergencyCallButton" /> <java-symbol type="id" name="face_unlock_area_view" /> + <java-symbol type="id" name="face_unlock_cancel_button" /> <java-symbol type="id" name="five" /> <java-symbol type="id" name="forgotPatternButton" /> <java-symbol type="id" name="four" /> diff --git a/policy/src/com/android/internal/policy/impl/keyguard/BiometricSensorUnlock.java b/policy/src/com/android/internal/policy/impl/keyguard/BiometricSensorUnlock.java index 39afaa2..e65a716 100644 --- a/policy/src/com/android/internal/policy/impl/keyguard/BiometricSensorUnlock.java +++ b/policy/src/com/android/internal/policy/impl/keyguard/BiometricSensorUnlock.java @@ -37,21 +37,9 @@ interface BiometricSensorUnlock { public boolean isRunning(); /** - * 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); - - /** - * Uncovers the backup unlock mechanism by hiding the contents of the view initialized in - * {@link BiometricSensorUnlock#initializeView(View)}. + * Stops and removes the biometric unlock and shows the backup unlock */ - public void hide(); + public void stopAndShowBackup(); /** * Binds to the biometric unlock service and starts the unlock procedure. Called on the UI diff --git a/policy/src/com/android/internal/policy/impl/keyguard/FaceUnlock.java b/policy/src/com/android/internal/policy/impl/keyguard/FaceUnlock.java index 4f2f6bf..3fe16cf 100644 --- a/policy/src/com/android/internal/policy/impl/keyguard/FaceUnlock.java +++ b/policy/src/com/android/internal/policy/impl/keyguard/FaceUnlock.java @@ -52,26 +52,19 @@ public class FaceUnlock implements BiometricSensorUnlock, Handler.Callback { private View mFaceUnlockView; private Handler mHandler; - private final int MSG_SHOW_FACE_UNLOCK_VIEW = 0; - private final int MSG_HIDE_FACE_UNLOCK_VIEW = 1; - private final int MSG_SERVICE_CONNECTED = 2; - private final int MSG_SERVICE_DISCONNECTED = 3; - private final int MSG_UNLOCK = 4; - private final int MSG_CANCEL = 5; - private final int MSG_REPORT_FAILED_ATTEMPT = 6; - private final int MSG_EXPOSE_FALLBACK = 7; - private final int MSG_POKE_WAKELOCK = 8; + private final int MSG_SERVICE_CONNECTED = 0; + private final int MSG_SERVICE_DISCONNECTED = 1; + private final int MSG_UNLOCK = 2; + private final int MSG_CANCEL = 3; + private final int MSG_REPORT_FAILED_ATTEMPT = 4; + private final int MSG_EXPOSE_FALLBACK = 5; + private final int MSG_POKE_WAKELOCK = 6; // 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 volatile 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 SERVICE_STARTUP_VIEW_TIMEOUT = 3000; - // 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; @@ -110,30 +103,11 @@ public class FaceUnlock implements BiometricSensorUnlock, Handler.Callback { } /** - * Sets the Face Unlock view to visible, hiding it after the specified amount of time. If - * timeoutMillis is 0, no hide is performed. Called on the UI thread. + * Dismisses face unlock and goes to the backup lock */ - public void show(long timeoutMillis) { - if (DEBUG) Log.d(TAG, "show()"); - if (mHandler.getLooper() != Looper.myLooper()) { - Log.e(TAG, "show() called off of the UI thread"); - } - removeDisplayMessages(); - if (timeoutMillis > 0) { - mHandler.sendEmptyMessageDelayed(MSG_HIDE_FACE_UNLOCK_VIEW, timeoutMillis); - } - } - - /** - * Hides the Face Unlock view. - */ - public void hide() { - if (DEBUG) Log.d(TAG, "hide()"); - // Removes any wakelock messages to make sure they don't cause the screen to turn back on. - mHandler.removeMessages(MSG_POKE_WAKELOCK); - // Remove messages to prevent a delayed show message from undo-ing the hide - removeDisplayMessages(); - mHandler.sendEmptyMessage(MSG_HIDE_FACE_UNLOCK_VIEW); + public void stopAndShowBackup() { + if (DEBUG) Log.d(TAG, "stopAndShowBackup()"); + mHandler.sendEmptyMessage(MSG_CANCEL); } /** @@ -151,10 +125,6 @@ public class FaceUnlock implements BiometricSensorUnlock, Handler.Callback { 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(SERVICE_STARTUP_VIEW_TIMEOUT); if (!mBoundToService) { Log.d(TAG, "Binding to Face Unlock service for user=" + mLockPatternUtils.getCurrentUser()); @@ -234,12 +204,6 @@ public class FaceUnlock implements BiometricSensorUnlock, Handler.Callback { */ public boolean handleMessage(Message msg) { switch (msg.what) { - case MSG_SHOW_FACE_UNLOCK_VIEW: - handleShowFaceUnlockView(); - break; - case MSG_HIDE_FACE_UNLOCK_VIEW: - handleHideFaceUnlockView(); - break; case MSG_SERVICE_CONNECTED: handleServiceConnected(); break; @@ -269,22 +233,6 @@ public class FaceUnlock implements BiometricSensorUnlock, Handler.Callback { } /** - * Sets the Face Unlock view to visible, thus covering the backup lock. - */ - void handleShowFaceUnlockView() { - if (DEBUG) Log.d(TAG, "handleShowFaceUnlockView()"); - // Not required - } - - /** - * Hide face unlock and show backup - */ - void handleHideFaceUnlockView() { - if (DEBUG) Log.d(TAG, "handleHideFaceUnlockView()"); - mKeyguardScreenCallback.showBackupSecurity(); - } - - /** * Tells the service to start its UI via an AIDL interface. Called when the * onServiceConnected() callback is received. */ @@ -347,23 +295,21 @@ public class FaceUnlock implements BiometricSensorUnlock, Handler.Callback { } /** - * Stops the Face Unlock service and tells the device to grant access to the user. Shows the - * Face Unlock view to keep the backup lock covered while the device unlocks. + * Stops the Face Unlock service and tells the device to grant access to the user. */ void handleUnlock() { if (DEBUG) Log.d(TAG, "handleUnlock()"); - removeDisplayMessages(); stop(); mKeyguardScreenCallback.reportSuccessfulUnlockAttempt(); mKeyguardScreenCallback.dismiss(true); } /** - * Stops the Face Unlock service and exposes the backup lock. + * Stops the Face Unlock service and goes to the backup lock. */ void handleCancel() { if (DEBUG) Log.d(TAG, "handleCancel()"); - mKeyguardScreenCallback.dismiss(false); + mKeyguardScreenCallback.showBackupSecurity(); stop(); mKeyguardScreenCallback.userActivity(BACKUP_LOCK_TIMEOUT); } @@ -398,15 +344,6 @@ public class FaceUnlock implements BiometricSensorUnlock, Handler.Callback { } /** - * Removes show and hide messages from the message queue. Called to prevent delayed show/hide - * messages from undoing a new message. - */ - private void removeDisplayMessages() { - mHandler.removeMessages(MSG_SHOW_FACE_UNLOCK_VIEW); - mHandler.removeMessages(MSG_HIDE_FACE_UNLOCK_VIEW); - } - - /** * Implements service connection methods. */ private ServiceConnection mConnection = new ServiceConnection() { @@ -508,7 +445,7 @@ public class FaceUnlock implements BiometricSensorUnlock, Handler.Callback { * Called when the Face Unlock service starts displaying the UI, indicating that the backup * unlock can be exposed because the Face Unlock service is now covering the backup with its * UI. - **/ + */ public void exposeFallback() { if (DEBUG) Log.d(TAG, "exposeFallback()"); mHandler.sendEmptyMessage(MSG_EXPOSE_FALLBACK); diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardFaceUnlockView.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardFaceUnlockView.java index 8776a80..d059e36 100644 --- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardFaceUnlockView.java +++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardFaceUnlockView.java @@ -20,6 +20,7 @@ import android.telephony.TelephonyManager; import android.util.AttributeSet; import android.util.Log; import android.view.View; +import android.widget.ImageButton; import android.widget.LinearLayout; import com.android.internal.R; @@ -29,11 +30,13 @@ import com.android.internal.widget.LockPatternUtils; public class KeyguardFaceUnlockView extends LinearLayout implements KeyguardSecurityView { private static final String TAG = "KeyguardFaceUnlockView"; + private static final boolean DEBUG = false; private KeyguardSecurityCallback mKeyguardSecurityCallback; private LockPatternUtils mLockPatternUtils; private BiometricSensorUnlock mBiometricUnlock; private KeyguardNavigationManager mNavigationManager; private View mFaceUnlockAreaView; + private ImageButton mCancelButton; public KeyguardFaceUnlockView(Context context) { this(context, null); @@ -70,25 +73,25 @@ public class KeyguardFaceUnlockView extends LinearLayout implements KeyguardSecu @Override public void onDetachedFromWindow() { + if (DEBUG) Log.d(TAG, "onDetachedFromWindow()"); if (mBiometricUnlock != null) { - mBiometricUnlock.hide(); - mBiometricUnlock.stop(); + mBiometricUnlock.stopAndShowBackup(); } } @Override public void onPause() { + if (DEBUG) Log.d(TAG, "onPause()"); if (mBiometricUnlock != null) { - mBiometricUnlock.hide(); - mBiometricUnlock.stop(); + mBiometricUnlock.stopAndShowBackup(); } KeyguardUpdateMonitor.getInstance(mContext).removeCallback(mUpdateCallback); } @Override public void onResume() { + if (DEBUG) Log.d(TAG, "onResume()"); maybeStartBiometricUnlock(); - mBiometricUnlock.show(0); KeyguardUpdateMonitor.getInstance(mContext).registerCallback(mUpdateCallback); } @@ -112,6 +115,14 @@ public class KeyguardFaceUnlockView extends LinearLayout implements KeyguardSecu mFaceUnlockAreaView = findViewById(R.id.face_unlock_area_view); if (mFaceUnlockAreaView != null) { mBiometricUnlock = new FaceUnlock(mContext); + + mCancelButton = (ImageButton) findViewById(R.id.face_unlock_cancel_button); + mCancelButton.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + mBiometricUnlock.stopAndShowBackup(); + } + }); } else { Log.w(TAG, "Couldn't find biometric unlock view"); } @@ -123,17 +134,20 @@ public class KeyguardFaceUnlockView extends LinearLayout implements KeyguardSecu * unlock area. */ private void maybeStartBiometricUnlock() { + if (DEBUG) Log.d(TAG, "maybeStartBiometricUnlock()"); if (mBiometricUnlock != null) { KeyguardUpdateMonitor monitor = KeyguardUpdateMonitor.getInstance(mContext); final boolean backupIsTimedOut = ( monitor.getFailedUnlockAttempts() >= LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT); - if (monitor.getPhoneState() == TelephonyManager.CALL_STATE_IDLE + // TODO: These max attempts checks are also checked in KeyguardSecurityModel so they + // might not be necessary here anymore. + if (monitor.getPhoneState() != TelephonyManager.CALL_STATE_RINGING && !monitor.getMaxBiometricUnlockAttemptsReached() && !backupIsTimedOut) { mBiometricUnlock.start(); } else { - mBiometricUnlock.hide(); + mBiometricUnlock.stopAndShowBackup(); } } } @@ -142,14 +156,15 @@ public class KeyguardFaceUnlockView extends LinearLayout implements KeyguardSecu // We need to stop the biometric unlock when a phone call comes in @Override public void onPhoneStateChanged(int phoneState) { + if (DEBUG) Log.d(TAG, "onPhoneStateChanged(" + phoneState + ")"); if (phoneState == TelephonyManager.CALL_STATE_RINGING) { - mBiometricUnlock.stop(); - mBiometricUnlock.hide(); + mBiometricUnlock.stopAndShowBackup(); } } @Override public void onUserSwitched(int userId) { + if (DEBUG) Log.d(TAG, "onUserSwitched(" + userId + ")"); if (mBiometricUnlock != null) { mBiometricUnlock.stop(); } diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardHostView.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardHostView.java index 6ea3513..bf0d03d 100644 --- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardHostView.java +++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardHostView.java @@ -403,6 +403,7 @@ public class KeyguardHostView extends KeyguardViewBase { * account unlock screen and biometric unlock to show the user's normal unlock. */ private void showBackupSecurity() { + if (DEBUG) Log.d(TAG, "showBackupSecurity()"); showSecurityScreen(mSecurityModel.getBackupSecurityMode()); } @@ -419,6 +420,7 @@ public class KeyguardHostView extends KeyguardViewBase { } private void showNextSecurityScreenOrFinish(boolean authenticated) { + if (DEBUG) Log.d(TAG, "showNextSecurityScreenOrFinish(" + authenticated + ")"); boolean finish = false; if (SecurityMode.None == mCurrentSecuritySelection) { SecurityMode securityMode = mSecurityModel.getSecurityMode(); @@ -547,7 +549,7 @@ public class KeyguardHostView extends KeyguardViewBase { * @param securityMode */ private void showSecurityScreen(SecurityMode securityMode) { - + if (DEBUG) Log.d(TAG, "showSecurityScreen"); if (securityMode == mCurrentSecuritySelection) return; KeyguardSecurityView oldView = getSecurityView(mCurrentSecuritySelection); @@ -565,16 +567,11 @@ public class KeyguardHostView extends KeyguardViewBase { // Find and show this child. final int childCount = mSecurityViewContainer.getChildCount(); - // If we're go to/from the selector view, do flip animation, otherwise use fade animation. - final boolean doFlip = mCurrentSecuritySelection == SecurityMode.None - || securityMode == SecurityMode.None; - final int inAnimation = doFlip ? R.anim.keyguard_security_animate_in - : R.anim.keyguard_security_fade_in; - final int outAnimation = doFlip ? R.anim.keyguard_security_animate_out - : R.anim.keyguard_security_fade_out; - - mSecurityViewContainer.setInAnimation(AnimationUtils.loadAnimation(mContext, inAnimation)); - mSecurityViewContainer.setOutAnimation(AnimationUtils.loadAnimation(mContext, outAnimation)); + // Do flip animation to the next screen + mSecurityViewContainer.setInAnimation( + AnimationUtils.loadAnimation(mContext, R.anim.keyguard_security_animate_in)); + mSecurityViewContainer.setOutAnimation( + AnimationUtils.loadAnimation(mContext, R.anim.keyguard_security_animate_out)); final int securityViewIdForMode = getSecurityViewIdForMode(securityMode); for (int i = 0; i < childCount; i++) { if (mSecurityViewContainer.getChildAt(i).getId() == securityViewIdForMode) { |