Updated keyguard to be robust against fpm

Test: atest KeyguardUpdateMonitorTest
Bug: 238070374
Change-Id: If51313b03dc40442ad6c42603f77579e77b0c873
This commit is contained in:
Joshua McCloskey
2022-08-06 17:04:51 +00:00
parent 382cf79482
commit d2a790740b
2 changed files with 65 additions and 9 deletions

View File

@@ -214,7 +214,8 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
* If no cancel signal has been received after this amount of time, set the biometric running * If no cancel signal has been received after this amount of time, set the biometric running
* state to stopped to allow Keyguard to retry authentication. * state to stopped to allow Keyguard to retry authentication.
*/ */
private static final int DEFAULT_CANCEL_SIGNAL_TIMEOUT = 3000; @VisibleForTesting
protected static final int DEFAULT_CANCEL_SIGNAL_TIMEOUT = 3000;
private static final ComponentName FALLBACK_HOME_COMPONENT = new ComponentName( private static final ComponentName FALLBACK_HOME_COMPONENT = new ComponentName(
"com.android.settings", "com.android.settings.FallbackHome"); "com.android.settings", "com.android.settings.FallbackHome");
@@ -332,10 +333,15 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
private static final int HAL_ERROR_RETRY_TIMEOUT = 500; // ms private static final int HAL_ERROR_RETRY_TIMEOUT = 500; // ms
private static final int HAL_ERROR_RETRY_MAX = 20; private static final int HAL_ERROR_RETRY_MAX = 20;
private final Runnable mFpCancelNotReceived = this::onFingerprintCancelNotReceived; @VisibleForTesting
protected final Runnable mFpCancelNotReceived = this::onFingerprintCancelNotReceived;
private final Runnable mFaceCancelNotReceived = this::onFaceCancelNotReceived; private final Runnable mFaceCancelNotReceived = this::onFaceCancelNotReceived;
@VisibleForTesting
protected Handler getHandler() {
return mHandler;
}
private final Handler mHandler; private final Handler mHandler;
private SparseBooleanArray mBiometricEnabledForUser = new SparseBooleanArray(); private SparseBooleanArray mBiometricEnabledForUser = new SparseBooleanArray();
@@ -723,6 +729,11 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
private void handleFingerprintAuthFailed() { private void handleFingerprintAuthFailed() {
Assert.isMainThread(); Assert.isMainThread();
if (mHandler.hasCallbacks(mFpCancelNotReceived)) {
Log.d(TAG, "handleFingerprintAuthFailed()"
+ " triggered while waiting for cancellation, removing watchdog");
mHandler.removeCallbacks(mFpCancelNotReceived);
}
for (int i = 0; i < mCallbacks.size(); i++) { for (int i = 0; i < mCallbacks.size(); i++) {
KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get(); KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
if (cb != null) { if (cb != null) {
@@ -753,6 +764,11 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
private void handleFingerprintAuthenticated(int authUserId, boolean isStrongBiometric) { private void handleFingerprintAuthenticated(int authUserId, boolean isStrongBiometric) {
Trace.beginSection("KeyGuardUpdateMonitor#handlerFingerPrintAuthenticated"); Trace.beginSection("KeyGuardUpdateMonitor#handlerFingerPrintAuthenticated");
if (mHandler.hasCallbacks(mFpCancelNotReceived)) {
Log.d(TAG, "handleFingerprintAuthenticated()"
+ " triggered while waiting for cancellation, removing watchdog");
mHandler.removeCallbacks(mFpCancelNotReceived);
}
try { try {
final int userId; final int userId;
try { try {

View File

@@ -22,6 +22,7 @@ import static android.telephony.SubscriptionManager.NAME_SOURCE_CARRIER_ID;
import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.SOME_AUTH_REQUIRED_AFTER_USER_REQUEST; import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.SOME_AUTH_REQUIRED_AFTER_USER_REQUEST;
import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_BOOT; import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_BOOT;
import static com.android.keyguard.KeyguardUpdateMonitor.DEFAULT_CANCEL_SIGNAL_TIMEOUT;
import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertThat;
@@ -109,6 +110,7 @@ import org.mockito.Captor;
import org.mockito.Mock; import org.mockito.Mock;
import org.mockito.MockitoAnnotations; import org.mockito.MockitoAnnotations;
import org.mockito.MockitoSession; import org.mockito.MockitoSession;
import org.mockito.internal.util.reflection.FieldSetter;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
@@ -200,9 +202,10 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
private ArgumentCaptor<CancellationSignal> mCancellationSignalCaptor; private ArgumentCaptor<CancellationSignal> mCancellationSignalCaptor;
// Direct executor // Direct executor
private Executor mBackgroundExecutor = Runnable::run; private final Executor mBackgroundExecutor = Runnable::run;
private Executor mMainExecutor = Runnable::run; private final Executor mMainExecutor = Runnable::run;
private TestableLooper mTestableLooper; private TestableLooper mTestableLooper;
private Handler mHandler;
private TestableKeyguardUpdateMonitor mKeyguardUpdateMonitor; private TestableKeyguardUpdateMonitor mKeyguardUpdateMonitor;
private TestableContext mSpiedContext; private TestableContext mSpiedContext;
private MockitoSession mMockitoSession; private MockitoSession mMockitoSession;
@@ -291,6 +294,13 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
mBiometricEnabledOnKeyguardCallback = mBiometricEnabledCallbackArgCaptor.getValue(); mBiometricEnabledOnKeyguardCallback = mBiometricEnabledCallbackArgCaptor.getValue();
biometricsEnabledForCurrentUser(); biometricsEnabledForCurrentUser();
mHandler = spy(mKeyguardUpdateMonitor.getHandler());
try {
FieldSetter.setField(mKeyguardUpdateMonitor,
KeyguardUpdateMonitor.class.getDeclaredField("mHandler"), mHandler);
} catch (NoSuchFieldException e) {
}
verify(mStatusBarStateController).addCallback(mStatusBarStateListenerCaptor.capture()); verify(mStatusBarStateController).addCallback(mStatusBarStateListenerCaptor.capture());
mStatusBarStateListener = mStatusBarStateListenerCaptor.getValue(); mStatusBarStateListener = mStatusBarStateListenerCaptor.getValue();
mKeyguardUpdateMonitor.registerCallback(mTestCallback); mKeyguardUpdateMonitor.registerCallback(mTestCallback);
@@ -791,7 +801,8 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
public void testBiometricsCleared_whenUserSwitches() throws Exception { public void testBiometricsCleared_whenUserSwitches() throws Exception {
final IRemoteCallback reply = new IRemoteCallback.Stub() { final IRemoteCallback reply = new IRemoteCallback.Stub() {
@Override @Override
public void sendResult(Bundle data) {} // do nothing public void sendResult(Bundle data) {
} // do nothing
}; };
final BiometricAuthenticated dummyAuthentication = final BiometricAuthenticated dummyAuthentication =
new BiometricAuthenticated(true /* authenticated */, true /* strong */); new BiometricAuthenticated(true /* authenticated */, true /* strong */);
@@ -809,7 +820,8 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
public void testMultiUserJankMonitor_whenUserSwitches() throws Exception { public void testMultiUserJankMonitor_whenUserSwitches() throws Exception {
final IRemoteCallback reply = new IRemoteCallback.Stub() { final IRemoteCallback reply = new IRemoteCallback.Stub() {
@Override @Override
public void sendResult(Bundle data) {} // do nothing public void sendResult(Bundle data) {
} // do nothing
}; };
mKeyguardUpdateMonitor.handleUserSwitchComplete(10 /* user */); mKeyguardUpdateMonitor.handleUserSwitchComplete(10 /* user */);
verify(mInteractionJankMonitor).end(InteractionJankMonitor.CUJ_USER_SWITCH); verify(mInteractionJankMonitor).end(InteractionJankMonitor.CUJ_USER_SWITCH);
@@ -1499,6 +1511,34 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
assertThat(cancelSignal.isCanceled()).isTrue(); assertThat(cancelSignal.isCanceled()).isTrue();
} }
@Test
public void testFingerprintCanAuth_whenCancellationNotReceivedAndAuthFailed() {
mKeyguardUpdateMonitor.dispatchStartedWakingUp();
mTestableLooper.processAllMessages();
mKeyguardUpdateMonitor.onKeyguardVisibilityChanged(true);
verify(mFaceManager).authenticate(any(), any(), any(), any(), anyInt(), anyBoolean());
verify(mFingerprintManager).authenticate(any(), any(), any(), any(), anyInt(), anyInt(),
anyInt());
mKeyguardUpdateMonitor.onFaceAuthenticated(0, false);
// Make sure keyguard is going away after face auth attempt, and that it calls
// updateBiometricStateListeningState.
mKeyguardUpdateMonitor.onKeyguardVisibilityChanged(false);
mTestableLooper.processAllMessages();
verify(mHandler).postDelayed(mKeyguardUpdateMonitor.mFpCancelNotReceived,
DEFAULT_CANCEL_SIGNAL_TIMEOUT);
mKeyguardUpdateMonitor.onFingerprintAuthenticated(0, true);
mTestableLooper.processAllMessages();
verify(mHandler, times(1)).removeCallbacks(mKeyguardUpdateMonitor.mFpCancelNotReceived);
mKeyguardUpdateMonitor.dispatchStartedGoingToSleep(0 /* why */);
mTestableLooper.processAllMessages();
assertThat(mKeyguardUpdateMonitor.shouldListenForFingerprint(anyBoolean())).isEqualTo(true);
}
private void fingerprintIsNotEnrolled() { private void fingerprintIsNotEnrolled() {
when(mFingerprintManager.hasEnrolledTemplates(mCurrentUserId)).thenReturn(false); when(mFingerprintManager.hasEnrolledTemplates(mCurrentUserId)).thenReturn(false);
} }