Skip to content

Commit 8f89e6f

Browse files
Danielle MillettAndroid (Google) Code Review
authored andcommitted
Merge "Face Unlock is shown correctly during a phone call - fix b/7271718" into jb-mr1-dev
2 parents ff97e6e + 61413b5 commit 8f89e6f

File tree

6 files changed

+53
-114
lines changed

6 files changed

+53
-114
lines changed

core/res/res/layout/keyguard_face_unlock_view.xml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,13 +46,14 @@
4646
android:background="@color/facelock_spotlight_mask"
4747
/>
4848

49-
<ImageView
50-
android:id="@+id/cancel_button"
49+
<ImageButton
50+
android:id="@+id/face_unlock_cancel_button"
5151
android:layout_width="wrap_content"
5252
android:layout_height="wrap_content"
5353
android:padding="5dip"
5454
android:layout_alignParentTop="true"
5555
android:layout_alignParentEnd="true"
56+
android:background="#00000000"
5657
android:src="@drawable/ic_facial_backup"
5758
/>
5859

core/res/res/values/symbols.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1233,6 +1233,7 @@
12331233
<java-symbol type="id" name="eight" />
12341234
<java-symbol type="id" name="emergencyCallButton" />
12351235
<java-symbol type="id" name="face_unlock_area_view" />
1236+
<java-symbol type="id" name="face_unlock_cancel_button" />
12361237
<java-symbol type="id" name="five" />
12371238
<java-symbol type="id" name="forgotPatternButton" />
12381239
<java-symbol type="id" name="four" />

policy/src/com/android/internal/policy/impl/keyguard/BiometricSensorUnlock.java

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -37,21 +37,9 @@ interface BiometricSensorUnlock {
3737
public boolean isRunning();
3838

3939
/**
40-
* Covers the backup unlock mechanism by showing the contents of the view initialized in
41-
* {@link BiometricSensorUnlock#initializeView(View)}. The view should disappear after the
42-
* specified timeout. If the timeout is 0, the interface shows until another event, such as
43-
* calling {@link BiometricSensorUnlock#hide()}, causes it to disappear. Called on the UI
44-
* thread.
45-
* @param timeoutMilliseconds Amount of time in milliseconds to display the view before
46-
* disappearing. A value of 0 means the view should remain visible.
47-
*/
48-
public void show(long timeoutMilliseconds);
49-
50-
/**
51-
* Uncovers the backup unlock mechanism by hiding the contents of the view initialized in
52-
* {@link BiometricSensorUnlock#initializeView(View)}.
40+
* Stops and removes the biometric unlock and shows the backup unlock
5341
*/
54-
public void hide();
42+
public void stopAndShowBackup();
5543

5644
/**
5745
* Binds to the biometric unlock service and starts the unlock procedure. Called on the UI

policy/src/com/android/internal/policy/impl/keyguard/FaceUnlock.java

Lines changed: 15 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -52,26 +52,19 @@ public class FaceUnlock implements BiometricSensorUnlock, Handler.Callback {
5252
private View mFaceUnlockView;
5353

5454
private Handler mHandler;
55-
private final int MSG_SHOW_FACE_UNLOCK_VIEW = 0;
56-
private final int MSG_HIDE_FACE_UNLOCK_VIEW = 1;
57-
private final int MSG_SERVICE_CONNECTED = 2;
58-
private final int MSG_SERVICE_DISCONNECTED = 3;
59-
private final int MSG_UNLOCK = 4;
60-
private final int MSG_CANCEL = 5;
61-
private final int MSG_REPORT_FAILED_ATTEMPT = 6;
62-
private final int MSG_EXPOSE_FALLBACK = 7;
63-
private final int MSG_POKE_WAKELOCK = 8;
55+
private final int MSG_SERVICE_CONNECTED = 0;
56+
private final int MSG_SERVICE_DISCONNECTED = 1;
57+
private final int MSG_UNLOCK = 2;
58+
private final int MSG_CANCEL = 3;
59+
private final int MSG_REPORT_FAILED_ATTEMPT = 4;
60+
private final int MSG_EXPOSE_FALLBACK = 5;
61+
private final int MSG_POKE_WAKELOCK = 6;
6462

6563
// TODO: This was added for the purpose of adhering to what the biometric interface expects
6664
// the isRunning() function to return. However, it is probably not necessary to have both
6765
// mRunning and mServiceRunning. I'd just rather wait to change that logic.
6866
private volatile boolean mIsRunning = false;
6967

70-
// Long enough to stay visible while the service starts
71-
// Short enough to not have to wait long for backup if service fails to start or crashes
72-
// The service can take a couple of seconds to start on the first try after boot
73-
private final int SERVICE_STARTUP_VIEW_TIMEOUT = 3000;
74-
7568
// So the user has a consistent amount of time when brought to the backup method from Face
7669
// Unlock
7770
private final int BACKUP_LOCK_TIMEOUT = 5000;
@@ -110,30 +103,11 @@ public boolean isRunning() {
110103
}
111104

112105
/**
113-
* Sets the Face Unlock view to visible, hiding it after the specified amount of time. If
114-
* timeoutMillis is 0, no hide is performed. Called on the UI thread.
106+
* Dismisses face unlock and goes to the backup lock
115107
*/
116-
public void show(long timeoutMillis) {
117-
if (DEBUG) Log.d(TAG, "show()");
118-
if (mHandler.getLooper() != Looper.myLooper()) {
119-
Log.e(TAG, "show() called off of the UI thread");
120-
}
121-
removeDisplayMessages();
122-
if (timeoutMillis > 0) {
123-
mHandler.sendEmptyMessageDelayed(MSG_HIDE_FACE_UNLOCK_VIEW, timeoutMillis);
124-
}
125-
}
126-
127-
/**
128-
* Hides the Face Unlock view.
129-
*/
130-
public void hide() {
131-
if (DEBUG) Log.d(TAG, "hide()");
132-
// Removes any wakelock messages to make sure they don't cause the screen to turn back on.
133-
mHandler.removeMessages(MSG_POKE_WAKELOCK);
134-
// Remove messages to prevent a delayed show message from undo-ing the hide
135-
removeDisplayMessages();
136-
mHandler.sendEmptyMessage(MSG_HIDE_FACE_UNLOCK_VIEW);
108+
public void stopAndShowBackup() {
109+
if (DEBUG) Log.d(TAG, "stopAndShowBackup()");
110+
mHandler.sendEmptyMessage(MSG_CANCEL);
137111
}
138112

139113
/**
@@ -151,10 +125,6 @@ public boolean start() {
151125
Log.w(TAG, "start() called when already running");
152126
}
153127

154-
// Show Face Unlock view, but only for a little bit so lockpattern will become visible if
155-
// Face Unlock fails to start or crashes
156-
// This must show before bind to guarantee that Face Unlock has a place to display
157-
show(SERVICE_STARTUP_VIEW_TIMEOUT);
158128
if (!mBoundToService) {
159129
Log.d(TAG, "Binding to Face Unlock service for user="
160130
+ mLockPatternUtils.getCurrentUser());
@@ -234,12 +204,6 @@ public int getQuality() {
234204
*/
235205
public boolean handleMessage(Message msg) {
236206
switch (msg.what) {
237-
case MSG_SHOW_FACE_UNLOCK_VIEW:
238-
handleShowFaceUnlockView();
239-
break;
240-
case MSG_HIDE_FACE_UNLOCK_VIEW:
241-
handleHideFaceUnlockView();
242-
break;
243207
case MSG_SERVICE_CONNECTED:
244208
handleServiceConnected();
245209
break;
@@ -268,22 +232,6 @@ public boolean handleMessage(Message msg) {
268232
return true;
269233
}
270234

271-
/**
272-
* Sets the Face Unlock view to visible, thus covering the backup lock.
273-
*/
274-
void handleShowFaceUnlockView() {
275-
if (DEBUG) Log.d(TAG, "handleShowFaceUnlockView()");
276-
// Not required
277-
}
278-
279-
/**
280-
* Hide face unlock and show backup
281-
*/
282-
void handleHideFaceUnlockView() {
283-
if (DEBUG) Log.d(TAG, "handleHideFaceUnlockView()");
284-
mKeyguardScreenCallback.showBackupSecurity();
285-
}
286-
287235
/**
288236
* Tells the service to start its UI via an AIDL interface. Called when the
289237
* onServiceConnected() callback is received.
@@ -347,23 +295,21 @@ void handleServiceDisconnected() {
347295
}
348296

349297
/**
350-
* Stops the Face Unlock service and tells the device to grant access to the user. Shows the
351-
* Face Unlock view to keep the backup lock covered while the device unlocks.
298+
* Stops the Face Unlock service and tells the device to grant access to the user.
352299
*/
353300
void handleUnlock() {
354301
if (DEBUG) Log.d(TAG, "handleUnlock()");
355-
removeDisplayMessages();
356302
stop();
357303
mKeyguardScreenCallback.reportSuccessfulUnlockAttempt();
358304
mKeyguardScreenCallback.dismiss(true);
359305
}
360306

361307
/**
362-
* Stops the Face Unlock service and exposes the backup lock.
308+
* Stops the Face Unlock service and goes to the backup lock.
363309
*/
364310
void handleCancel() {
365311
if (DEBUG) Log.d(TAG, "handleCancel()");
366-
mKeyguardScreenCallback.dismiss(false);
312+
mKeyguardScreenCallback.showBackupSecurity();
367313
stop();
368314
mKeyguardScreenCallback.userActivity(BACKUP_LOCK_TIMEOUT);
369315
}
@@ -397,15 +343,6 @@ void handlePokeWakelock(int millis) {
397343
}
398344
}
399345

400-
/**
401-
* Removes show and hide messages from the message queue. Called to prevent delayed show/hide
402-
* messages from undoing a new message.
403-
*/
404-
private void removeDisplayMessages() {
405-
mHandler.removeMessages(MSG_SHOW_FACE_UNLOCK_VIEW);
406-
mHandler.removeMessages(MSG_HIDE_FACE_UNLOCK_VIEW);
407-
}
408-
409346
/**
410347
* Implements service connection methods.
411348
*/
@@ -508,7 +445,7 @@ public void reportFailedAttempt() {
508445
* Called when the Face Unlock service starts displaying the UI, indicating that the backup
509446
* unlock can be exposed because the Face Unlock service is now covering the backup with its
510447
* UI.
511-
**/
448+
*/
512449
public void exposeFallback() {
513450
if (DEBUG) Log.d(TAG, "exposeFallback()");
514451
mHandler.sendEmptyMessage(MSG_EXPOSE_FALLBACK);

policy/src/com/android/internal/policy/impl/keyguard/KeyguardFaceUnlockView.java

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import android.util.AttributeSet;
2121
import android.util.Log;
2222
import android.view.View;
23+
import android.widget.ImageButton;
2324
import android.widget.LinearLayout;
2425

2526
import com.android.internal.R;
@@ -29,11 +30,13 @@
2930
public class KeyguardFaceUnlockView extends LinearLayout implements KeyguardSecurityView {
3031

3132
private static final String TAG = "KeyguardFaceUnlockView";
33+
private static final boolean DEBUG = false;
3234
private KeyguardSecurityCallback mKeyguardSecurityCallback;
3335
private LockPatternUtils mLockPatternUtils;
3436
private BiometricSensorUnlock mBiometricUnlock;
3537
private KeyguardNavigationManager mNavigationManager;
3638
private View mFaceUnlockAreaView;
39+
private ImageButton mCancelButton;
3740

3841
public KeyguardFaceUnlockView(Context context) {
3942
this(context, null);
@@ -70,25 +73,25 @@ public void reset() {
7073

7174
@Override
7275
public void onDetachedFromWindow() {
76+
if (DEBUG) Log.d(TAG, "onDetachedFromWindow()");
7377
if (mBiometricUnlock != null) {
74-
mBiometricUnlock.hide();
75-
mBiometricUnlock.stop();
78+
mBiometricUnlock.stopAndShowBackup();
7679
}
7780
}
7881

7982
@Override
8083
public void onPause() {
84+
if (DEBUG) Log.d(TAG, "onPause()");
8185
if (mBiometricUnlock != null) {
82-
mBiometricUnlock.hide();
83-
mBiometricUnlock.stop();
86+
mBiometricUnlock.stopAndShowBackup();
8487
}
8588
KeyguardUpdateMonitor.getInstance(mContext).removeCallback(mUpdateCallback);
8689
}
8790

8891
@Override
8992
public void onResume() {
93+
if (DEBUG) Log.d(TAG, "onResume()");
9094
maybeStartBiometricUnlock();
91-
mBiometricUnlock.show(0);
9295
KeyguardUpdateMonitor.getInstance(mContext).registerCallback(mUpdateCallback);
9396
}
9497

@@ -112,6 +115,14 @@ private void initializeBiometricUnlockView() {
112115
mFaceUnlockAreaView = findViewById(R.id.face_unlock_area_view);
113116
if (mFaceUnlockAreaView != null) {
114117
mBiometricUnlock = new FaceUnlock(mContext);
118+
119+
mCancelButton = (ImageButton) findViewById(R.id.face_unlock_cancel_button);
120+
mCancelButton.setOnClickListener(new OnClickListener() {
121+
@Override
122+
public void onClick(View v) {
123+
mBiometricUnlock.stopAndShowBackup();
124+
}
125+
});
115126
} else {
116127
Log.w(TAG, "Couldn't find biometric unlock view");
117128
}
@@ -123,17 +134,20 @@ private void initializeBiometricUnlockView() {
123134
* unlock area.
124135
*/
125136
private void maybeStartBiometricUnlock() {
137+
if (DEBUG) Log.d(TAG, "maybeStartBiometricUnlock()");
126138
if (mBiometricUnlock != null) {
127139
KeyguardUpdateMonitor monitor = KeyguardUpdateMonitor.getInstance(mContext);
128140
final boolean backupIsTimedOut = (
129141
monitor.getFailedUnlockAttempts() >=
130142
LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT);
131-
if (monitor.getPhoneState() == TelephonyManager.CALL_STATE_IDLE
143+
// TODO: These max attempts checks are also checked in KeyguardSecurityModel so they
144+
// might not be necessary here anymore.
145+
if (monitor.getPhoneState() != TelephonyManager.CALL_STATE_RINGING
132146
&& !monitor.getMaxBiometricUnlockAttemptsReached()
133147
&& !backupIsTimedOut) {
134148
mBiometricUnlock.start();
135149
} else {
136-
mBiometricUnlock.hide();
150+
mBiometricUnlock.stopAndShowBackup();
137151
}
138152
}
139153
}
@@ -142,14 +156,15 @@ private void maybeStartBiometricUnlock() {
142156
// We need to stop the biometric unlock when a phone call comes in
143157
@Override
144158
public void onPhoneStateChanged(int phoneState) {
159+
if (DEBUG) Log.d(TAG, "onPhoneStateChanged(" + phoneState + ")");
145160
if (phoneState == TelephonyManager.CALL_STATE_RINGING) {
146-
mBiometricUnlock.stop();
147-
mBiometricUnlock.hide();
161+
mBiometricUnlock.stopAndShowBackup();
148162
}
149163
}
150164

151165
@Override
152166
public void onUserSwitched(int userId) {
167+
if (DEBUG) Log.d(TAG, "onUserSwitched(" + userId + ")");
153168
if (mBiometricUnlock != null) {
154169
mBiometricUnlock.stop();
155170
}

policy/src/com/android/internal/policy/impl/keyguard/KeyguardHostView.java

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -415,6 +415,7 @@ private void reportFailedUnlockAttempt() {
415415
* account unlock screen and biometric unlock to show the user's normal unlock.
416416
*/
417417
private void showBackupSecurity() {
418+
if (DEBUG) Log.d(TAG, "showBackupSecurity()");
418419
showSecurityScreen(mSecurityModel.getBackupSecurityMode());
419420
}
420421

@@ -431,6 +432,7 @@ public boolean showNextSecurityScreenIfPresent() {
431432
}
432433

433434
private void showNextSecurityScreenOrFinish(boolean authenticated) {
435+
if (DEBUG) Log.d(TAG, "showNextSecurityScreenOrFinish(" + authenticated + ")");
434436
boolean finish = false;
435437
if (SecurityMode.None == mCurrentSecuritySelection) {
436438
SecurityMode securityMode = mSecurityModel.getSecurityMode();
@@ -559,7 +561,7 @@ private KeyguardSecurityView getSecurityView(SecurityMode securityMode) {
559561
* @param securityMode
560562
*/
561563
private void showSecurityScreen(SecurityMode securityMode) {
562-
564+
if (DEBUG) Log.d(TAG, "showSecurityScreen");
563565
if (securityMode == mCurrentSecuritySelection) return;
564566

565567
KeyguardSecurityView oldView = getSecurityView(mCurrentSecuritySelection);
@@ -577,16 +579,11 @@ private void showSecurityScreen(SecurityMode securityMode) {
577579
// Find and show this child.
578580
final int childCount = mSecurityViewContainer.getChildCount();
579581

580-
// If we're go to/from the selector view, do flip animation, otherwise use fade animation.
581-
final boolean doFlip = mCurrentSecuritySelection == SecurityMode.None
582-
|| securityMode == SecurityMode.None;
583-
final int inAnimation = doFlip ? R.anim.keyguard_security_animate_in
584-
: R.anim.keyguard_security_fade_in;
585-
final int outAnimation = doFlip ? R.anim.keyguard_security_animate_out
586-
: R.anim.keyguard_security_fade_out;
587-
588-
mSecurityViewContainer.setInAnimation(AnimationUtils.loadAnimation(mContext, inAnimation));
589-
mSecurityViewContainer.setOutAnimation(AnimationUtils.loadAnimation(mContext, outAnimation));
582+
// Do flip animation to the next screen
583+
mSecurityViewContainer.setInAnimation(
584+
AnimationUtils.loadAnimation(mContext, R.anim.keyguard_security_animate_in));
585+
mSecurityViewContainer.setOutAnimation(
586+
AnimationUtils.loadAnimation(mContext, R.anim.keyguard_security_animate_out));
590587
final int securityViewIdForMode = getSecurityViewIdForMode(securityMode);
591588
for (int i = 0; i < childCount; i++) {
592589
if (mSecurityViewContainer.getChildAt(i).getId() == securityViewIdForMode) {

0 commit comments

Comments
 (0)