Merge "Update FP failure bouncer & messaging logic" into tm-qpr-dev am: 5cdb41a8cb
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/19681152 Change-Id: I34abd3ae720b26320ab0ac5abc82f89eecb216c3 Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
@@ -206,7 +206,8 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
|
||||
*/
|
||||
private static final int BIOMETRIC_STATE_CANCELLING_RESTARTING = 3;
|
||||
|
||||
private static final int BIOMETRIC_HELP_FINGERPRINT_NOT_RECOGNIZED = -1;
|
||||
@VisibleForTesting
|
||||
public static final int BIOMETRIC_HELP_FINGERPRINT_NOT_RECOGNIZED = -1;
|
||||
public static final int BIOMETRIC_HELP_FACE_NOT_RECOGNIZED = -2;
|
||||
|
||||
/**
|
||||
|
||||
@@ -122,6 +122,7 @@ public class KeyguardIndicationController {
|
||||
private static final int MSG_HIDE_TRANSIENT = 1;
|
||||
private static final int MSG_SHOW_ACTION_TO_UNLOCK = 2;
|
||||
private static final int MSG_HIDE_BIOMETRIC_MESSAGE = 3;
|
||||
private static final int MSG_RESET_ERROR_MESSAGE_ON_SCREEN_ON = 4;
|
||||
private static final long TRANSIENT_BIOMETRIC_ERROR_TIMEOUT = 1300;
|
||||
public static final long DEFAULT_HIDE_DELAY_MS =
|
||||
3500 + KeyguardIndicationTextView.Y_IN_DURATION;
|
||||
@@ -188,9 +189,11 @@ public class KeyguardIndicationController {
|
||||
}
|
||||
};
|
||||
private ScreenLifecycle mScreenLifecycle;
|
||||
private final ScreenLifecycle.Observer mScreenObserver = new ScreenLifecycle.Observer() {
|
||||
private final ScreenLifecycle.Observer mScreenObserver =
|
||||
new ScreenLifecycle.Observer() {
|
||||
@Override
|
||||
public void onScreenTurnedOn() {
|
||||
mHandler.removeMessages(MSG_RESET_ERROR_MESSAGE_ON_SCREEN_ON);
|
||||
if (mBiometricErrorMessageToShowOnScreenOn != null) {
|
||||
showBiometricMessage(mBiometricErrorMessageToShowOnScreenOn);
|
||||
// We want to keep this message around in case the screen was off
|
||||
@@ -259,6 +262,8 @@ public class KeyguardIndicationController {
|
||||
showActionToUnlock();
|
||||
} else if (msg.what == MSG_HIDE_BIOMETRIC_MESSAGE) {
|
||||
hideBiometricMessage();
|
||||
} else if (msg.what == MSG_RESET_ERROR_MESSAGE_ON_SCREEN_ON) {
|
||||
mBiometricErrorMessageToShowOnScreenOn = null;
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -1060,6 +1065,11 @@ public class KeyguardIndicationController {
|
||||
} else if (showActionToUnlock) {
|
||||
mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_SHOW_ACTION_TO_UNLOCK),
|
||||
TRANSIENT_BIOMETRIC_ERROR_TIMEOUT);
|
||||
} else {
|
||||
mBiometricErrorMessageToShowOnScreenOn = helpString;
|
||||
mHandler.sendMessageDelayed(
|
||||
mHandler.obtainMessage(MSG_RESET_ERROR_MESSAGE_ON_SCREEN_ON),
|
||||
1000);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@ import android.content.res.Resources;
|
||||
import android.hardware.biometrics.BiometricFaceConstants;
|
||||
import android.hardware.biometrics.BiometricFingerprintConstants;
|
||||
import android.hardware.biometrics.BiometricSourceType;
|
||||
import android.hardware.face.FaceManager;
|
||||
import android.hardware.fingerprint.FingerprintManager;
|
||||
import android.metrics.LogMaker;
|
||||
import android.os.Handler;
|
||||
@@ -64,7 +65,6 @@ import com.android.systemui.shade.ShadeController;
|
||||
import com.android.systemui.statusbar.CommandQueue;
|
||||
import com.android.systemui.statusbar.NotificationMediaManager;
|
||||
import com.android.systemui.statusbar.NotificationShadeWindowController;
|
||||
import com.android.systemui.statusbar.StatusBarState;
|
||||
import com.android.systemui.statusbar.VibratorHelper;
|
||||
import com.android.systemui.statusbar.policy.KeyguardStateController;
|
||||
|
||||
@@ -87,7 +87,7 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp
|
||||
private static final long BIOMETRIC_WAKELOCK_TIMEOUT_MS = 15 * 1000;
|
||||
private static final String BIOMETRIC_WAKE_LOCK_NAME = "wake-and-unlock:wakelock";
|
||||
private static final UiEventLogger UI_EVENT_LOGGER = new UiEventLoggerImpl();
|
||||
private static final int FP_ATTEMPTS_BEFORE_SHOW_BOUNCER = 2;
|
||||
private static final int UDFPS_ATTEMPTS_BEFORE_SHOW_BOUNCER = 3;
|
||||
private static final VibrationEffect SUCCESS_VIBRATION_EFFECT =
|
||||
VibrationEffect.get(VibrationEffect.EFFECT_CLICK);
|
||||
private static final VibrationEffect ERROR_VIBRATION_EFFECT =
|
||||
@@ -450,7 +450,7 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp
|
||||
// During wake and unlock, we need to draw black before waking up to avoid abrupt
|
||||
// brightness changes due to display state transitions.
|
||||
Runnable wakeUp = ()-> {
|
||||
if (!wasDeviceInteractive) {
|
||||
if (!wasDeviceInteractive || mUpdateMonitor.isDreaming()) {
|
||||
if (DEBUG_BIO_WAKELOCK) {
|
||||
Log.i(TAG, "bio wakelock: Authenticated, waking up...");
|
||||
}
|
||||
@@ -662,7 +662,7 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp
|
||||
|
||||
if (!mVibratorHelper.hasVibrator()
|
||||
&& (!mUpdateMonitor.isDeviceInteractive() || mUpdateMonitor.isDreaming())) {
|
||||
startWakeAndUnlock(MODE_SHOW_BOUNCER);
|
||||
startWakeAndUnlock(MODE_ONLY_WAKE);
|
||||
} else if (biometricSourceType == BiometricSourceType.FINGERPRINT
|
||||
&& mUpdateMonitor.isUdfpsSupported()) {
|
||||
long currUptimeMillis = SystemClock.uptimeMillis();
|
||||
@@ -673,7 +673,7 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp
|
||||
}
|
||||
mLastFpFailureUptimeMillis = currUptimeMillis;
|
||||
|
||||
if (mNumConsecutiveFpFailures >= FP_ATTEMPTS_BEFORE_SHOW_BOUNCER) {
|
||||
if (mNumConsecutiveFpFailures >= UDFPS_ATTEMPTS_BEFORE_SHOW_BOUNCER) {
|
||||
startWakeAndUnlock(MODE_SHOW_BOUNCER);
|
||||
UI_EVENT_LOGGER.log(BiometricUiEvent.BIOMETRIC_BOUNCER_SHOWN, getSessionId());
|
||||
mNumConsecutiveFpFailures = 0;
|
||||
@@ -699,13 +699,13 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp
|
||||
Optional.ofNullable(BiometricUiEvent.ERROR_EVENT_BY_SOURCE_TYPE.get(biometricSourceType))
|
||||
.ifPresent(event -> UI_EVENT_LOGGER.log(event, getSessionId()));
|
||||
|
||||
// if we're on the shade and we're locked out, immediately show the bouncer
|
||||
if (biometricSourceType == BiometricSourceType.FINGERPRINT
|
||||
final boolean fingerprintLockout = biometricSourceType == BiometricSourceType.FINGERPRINT
|
||||
&& (msgId == FingerprintManager.FINGERPRINT_ERROR_LOCKOUT
|
||||
|| msgId == FingerprintManager.FINGERPRINT_ERROR_LOCKOUT_PERMANENT)
|
||||
&& mUpdateMonitor.isUdfpsSupported()
|
||||
&& (mStatusBarStateController.getState() == StatusBarState.SHADE
|
||||
|| mStatusBarStateController.getState() == StatusBarState.SHADE_LOCKED)) {
|
||||
|| msgId == FingerprintManager.FINGERPRINT_ERROR_LOCKOUT_PERMANENT);
|
||||
final boolean faceLockout = biometricSourceType == BiometricSourceType.FACE
|
||||
&& (msgId == FaceManager.FACE_ERROR_LOCKOUT
|
||||
|| msgId == FaceManager.FACE_ERROR_LOCKOUT_PERMANENT);
|
||||
if (fingerprintLockout || faceLockout) {
|
||||
startWakeAndUnlock(MODE_SHOW_BOUNCER);
|
||||
UI_EVENT_LOGGER.log(BiometricUiEvent.BIOMETRIC_BOUNCER_SHOWN, getSessionId());
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ import static android.app.admin.DevicePolicyManager.DEVICE_OWNER_TYPE_DEFAULT;
|
||||
import static android.app.admin.DevicePolicyManager.DEVICE_OWNER_TYPE_FINANCED;
|
||||
import static android.content.pm.UserInfo.FLAG_MANAGED_PROFILE;
|
||||
|
||||
import static com.android.keyguard.KeyguardUpdateMonitor.BIOMETRIC_HELP_FINGERPRINT_NOT_RECOGNIZED;
|
||||
import static com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController.INDICATION_TYPE_ALIGNMENT;
|
||||
import static com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController.INDICATION_TYPE_BATTERY;
|
||||
import static com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController.INDICATION_TYPE_BIOMETRIC_MESSAGE;
|
||||
@@ -31,6 +32,7 @@ import static com.android.systemui.keyguard.KeyguardIndicationRotateTextViewCont
|
||||
import static com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController.INDICATION_TYPE_TRANSIENT;
|
||||
import static com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController.INDICATION_TYPE_TRUST;
|
||||
import static com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController.INDICATION_TYPE_USER_LOCKED;
|
||||
import static com.android.systemui.keyguard.ScreenLifecycle.SCREEN_OFF;
|
||||
import static com.android.systemui.keyguard.ScreenLifecycle.SCREEN_ON;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
@@ -178,9 +180,12 @@ public class KeyguardIndicationControllerTest extends SysuiTestCase {
|
||||
private ArgumentCaptor<KeyguardUpdateMonitorCallback> mKeyguardUpdateMonitorCallbackCaptor;
|
||||
@Captor
|
||||
private ArgumentCaptor<KeyguardStateController.Callback> mKeyguardStateControllerCallbackCaptor;
|
||||
@Captor
|
||||
private ArgumentCaptor<ScreenLifecycle.Observer> mScreenObserverCaptor;
|
||||
private KeyguardStateController.Callback mKeyguardStateControllerCallback;
|
||||
private KeyguardUpdateMonitorCallback mKeyguardUpdateMonitorCallback;
|
||||
private StatusBarStateController.StateListener mStatusBarStateListener;
|
||||
private ScreenLifecycle.Observer mScreenObserver;
|
||||
private BroadcastReceiver mBroadcastReceiver;
|
||||
private FakeExecutor mExecutor = new FakeExecutor(new FakeSystemClock());
|
||||
private TestableLooper mTestableLooper;
|
||||
@@ -273,6 +278,9 @@ public class KeyguardIndicationControllerTest extends SysuiTestCase {
|
||||
mKeyguardUpdateMonitorCallbackCaptor.capture());
|
||||
mKeyguardUpdateMonitorCallback = mKeyguardUpdateMonitorCallbackCaptor.getValue();
|
||||
|
||||
verify(mScreenLifecycle).addObserver(mScreenObserverCaptor.capture());
|
||||
mScreenObserver = mScreenObserverCaptor.getValue();
|
||||
|
||||
mExecutor.runAllReady();
|
||||
reset(mRotateTextViewController);
|
||||
}
|
||||
@@ -536,6 +544,31 @@ public class KeyguardIndicationControllerTest extends SysuiTestCase {
|
||||
assertThat(mTextView.getText()).isNotEqualTo(message);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void transientIndication_visibleWhenWokenUp() {
|
||||
createController();
|
||||
when(mStatusBarKeyguardViewManager.isBouncerShowing()).thenReturn(false);
|
||||
final String message = "helpMsg";
|
||||
|
||||
// GIVEN screen is off
|
||||
when(mScreenLifecycle.getScreenState()).thenReturn(SCREEN_OFF);
|
||||
|
||||
// WHEN fingeprint help message received
|
||||
mController.setVisible(true);
|
||||
mController.getKeyguardCallback().onBiometricHelp(BIOMETRIC_HELP_FINGERPRINT_NOT_RECOGNIZED,
|
||||
message, BiometricSourceType.FINGERPRINT);
|
||||
|
||||
// THEN message isn't shown right away
|
||||
verifyNoMessage(INDICATION_TYPE_BIOMETRIC_MESSAGE);
|
||||
|
||||
// WHEN the screen turns on
|
||||
mScreenObserver.onScreenTurnedOn();
|
||||
mTestableLooper.processAllMessages();
|
||||
|
||||
// THEN the message is shown
|
||||
verifyIndicationMessage(INDICATION_TYPE_BIOMETRIC_MESSAGE, message);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void transientIndication_visibleWhenDozing_unlessSwipeUp_fromError() {
|
||||
createController();
|
||||
|
||||
@@ -22,6 +22,8 @@ import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyBoolean;
|
||||
import static org.mockito.ArgumentMatchers.anyFloat;
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.ArgumentMatchers.anyLong;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.reset;
|
||||
@@ -395,15 +397,19 @@ public class BiometricsUnlockControllerTest extends SysuiTestCase {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onUdfpsConsecutivelyFailedTwoTimes_showBouncer() {
|
||||
public void onUdfpsConsecutivelyFailedThreeTimes_showBouncer() {
|
||||
// GIVEN UDFPS is supported
|
||||
when(mUpdateMonitor.isUdfpsSupported()).thenReturn(true);
|
||||
|
||||
// WHEN udfps fails once - then don't show the bouncer
|
||||
// WHEN udfps fails once - then don't show the bouncer yet
|
||||
mBiometricUnlockController.onBiometricAuthFailed(BiometricSourceType.FINGERPRINT);
|
||||
verify(mStatusBarKeyguardViewManager, never()).showBouncer(anyBoolean());
|
||||
|
||||
// WHEN udfps fails the second time
|
||||
// WHEN udfps fails the second time - then don't show the bouncer yet
|
||||
mBiometricUnlockController.onBiometricAuthFailed(BiometricSourceType.FINGERPRINT);
|
||||
verify(mStatusBarKeyguardViewManager, never()).showBouncer(anyBoolean());
|
||||
|
||||
// WHEN udpfs fails the third time
|
||||
mBiometricUnlockController.onBiometricAuthFailed(BiometricSourceType.FINGERPRINT);
|
||||
|
||||
// THEN show the bouncer
|
||||
@@ -427,8 +433,8 @@ public class BiometricsUnlockControllerTest extends SysuiTestCase {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onFPFailureNoHaptics_notDeviceInteractive_showBouncer() {
|
||||
// GIVEN no vibrator and the screen is off
|
||||
public void onFPFailureNoHaptics_notInteractive_showLockScreen() {
|
||||
// GIVEN no vibrator and device is dreaming
|
||||
when(mVibratorHelper.hasVibrator()).thenReturn(false);
|
||||
when(mUpdateMonitor.isDeviceInteractive()).thenReturn(false);
|
||||
when(mUpdateMonitor.isDreaming()).thenReturn(false);
|
||||
@@ -436,15 +442,12 @@ public class BiometricsUnlockControllerTest extends SysuiTestCase {
|
||||
// WHEN FP fails
|
||||
mBiometricUnlockController.onBiometricAuthFailed(BiometricSourceType.FINGERPRINT);
|
||||
|
||||
// after device is finished waking up
|
||||
mBiometricUnlockController.mWakefulnessObserver.onFinishedWakingUp();
|
||||
|
||||
// THEN show the bouncer
|
||||
verify(mStatusBarKeyguardViewManager).showBouncer(true);
|
||||
// THEN wakeup the device
|
||||
verify(mPowerManager).wakeUp(anyLong(), anyInt(), anyString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onFPFailureNoHaptics_dreaming_showBouncer() {
|
||||
public void onFPFailureNoHaptics_dreaming_showLockScreen() {
|
||||
// GIVEN no vibrator and device is dreaming
|
||||
when(mVibratorHelper.hasVibrator()).thenReturn(false);
|
||||
when(mUpdateMonitor.isDeviceInteractive()).thenReturn(true);
|
||||
@@ -453,7 +456,7 @@ public class BiometricsUnlockControllerTest extends SysuiTestCase {
|
||||
// WHEN FP fails
|
||||
mBiometricUnlockController.onBiometricAuthFailed(BiometricSourceType.FINGERPRINT);
|
||||
|
||||
// THEN show the bouncer
|
||||
verify(mStatusBarKeyguardViewManager).showBouncer(true);
|
||||
// THEN wakeup the device
|
||||
verify(mPowerManager).wakeUp(anyLong(), anyInt(), anyString());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user