Loading core/res/res/values/config.xml +10 −0 Original line number Diff line number Diff line Loading @@ -3534,6 +3534,16 @@ automatically dismissing. This is currently used in SideFpsEventHandler --> <integer name="config_sideFpsToastTimeout">3000</integer> <!-- This acquired message will cause the sidefpsKgPowerPress window to be skipped. If this is set to BIOMETRIC_ACQUIRED_VENDOR, then the framework will skip on config_sidefpsSkipWaitForPowerVendorAcquireMessage --> <integer name="config_sidefpsSkipWaitForPowerAcquireMessage">6</integer> <!-- This vendor acquired message that will cause the sidefpsKgPowerPress window to be skipped. config_sidefpsSkipWaitForPowerOnFingerUp must be true and config_sidefpsSkipWaitForPowerAcquireMessage must be BIOMETRIC_ACQUIRED_VENDOR == 6. --> <integer name="config_sidefpsSkipWaitForPowerVendorAcquireMessage">2</integer> <!-- This config is used to force VoiceInteractionService to start on certain low ram devices. It declares the package name of VoiceInteractionService that should be started. --> <string translatable="false" name="config_forceVoiceInteractionServicePackage"></string> Loading core/res/res/values/symbols.xml +2 −0 Original line number Diff line number Diff line Loading @@ -2634,6 +2634,8 @@ <java-symbol type="integer" name="config_sidefpsKeyguardPowerPressWindow"/> <java-symbol type="integer" name="config_sidefpsPostAuthDowntime"/> <java-symbol type="integer" name="config_sideFpsToastTimeout"/> <java-symbol type="integer" name="config_sidefpsSkipWaitForPowerAcquireMessage"/> <java-symbol type="integer" name="config_sidefpsSkipWaitForPowerVendorAcquireMessage"/> <!-- Clickable toast used during sidefps enrollment --> <java-symbol type="layout" name="side_fps_toast" /> Loading services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java +100 −40 Original line number Diff line number Diff line Loading @@ -16,6 +16,8 @@ package com.android.server.biometrics.sensors.fingerprint.aidl; import static android.hardware.biometrics.BiometricFingerprintConstants.FINGERPRINT_ACQUIRED_VENDOR; import android.annotation.NonNull; import android.annotation.Nullable; import android.app.TaskStackListener; Loading Loading @@ -65,22 +67,28 @@ import java.util.function.Supplier; class FingerprintAuthenticationClient extends AuthenticationClient<AidlSession> implements Udfps, LockoutConsumer, PowerPressHandler { private static final String TAG = "FingerprintAuthenticationClient"; @NonNull private final LockoutCache mLockoutCache; @NonNull private final SensorOverlays mSensorOverlays; @NonNull private final FingerprintSensorPropertiesInternal mSensorProps; @NonNull private final CallbackWithProbe<Probe> mALSProbeCallback; private static final int MESSAGE_IGNORE_AUTH = 1; private static final int MESSAGE_AUTH_SUCCESS = 2; private static final int MESSAGE_FINGER_UP = 3; @NonNull private final LockoutCache mLockoutCache; @NonNull private final SensorOverlays mSensorOverlays; @NonNull private final FingerprintSensorPropertiesInternal mSensorProps; @NonNull private final CallbackWithProbe<Probe> mALSProbeCallback; private final Handler mHandler; private final int mSkipWaitForPowerAcquireMessage; private final int mSkipWaitForPowerVendorAcquireMessage; private final long mFingerUpIgnoresPower = 500; @Nullable private ICancellationSignal mCancellationSignal; private boolean mIsPointerDown; private final Handler mHandler; private static final int MESSAGE_IGNORE_AUTH = 1; private static final int MESSAGE_AUTH_SUCCESS = 2; private long mWaitForAuthKeyguard; private long mWaitForAuthBp; private long mIgnoreAuthFor; private Runnable mAuthSuccessRunnable; FingerprintAuthenticationClient( @NonNull Context context, Loading Loading @@ -140,6 +148,13 @@ class FingerprintAuthenticationClient extends AuthenticationClient<AidlSession> mIgnoreAuthFor = context.getResources().getInteger(R.integer.config_sidefpsPostAuthDowntime); mSkipWaitForPowerAcquireMessage = context.getResources().getInteger( R.integer.config_sidefpsSkipWaitForPowerAcquireMessage); mSkipWaitForPowerVendorAcquireMessage = context.getResources().getInteger( R.integer.config_sidefpsSkipWaitForPowerVendorAcquireMessage); if (mSensorProps.isAnySidefpsType()) { if (Build.isDebuggable()) { mWaitForAuthKeyguard = Settings.Secure.getIntForUser(context.getContentResolver(), Loading Loading @@ -187,38 +202,55 @@ class FingerprintAuthenticationClient extends AuthenticationClient<AidlSession> return false; } public void handleAuthenticate( BiometricAuthenticator.Identifier identifier, boolean authenticated, ArrayList<Byte> token) { if (authenticated && mSensorProps.isAnySidefpsType()) { Slog.i(TAG, "(sideFPS): No power press detected, sending auth"); } super.onAuthenticated(identifier, authenticated, token); if (authenticated) { mState = STATE_STOPPED; mSensorOverlays.hide(getSensorId()); } else { mState = STATE_STARTED_PAUSED_ATTEMPTED; } } @Override public void onAuthenticated( BiometricAuthenticator.Identifier identifier, boolean authenticated, ArrayList<Byte> token) { mHandler.post( () -> { long delay = 0; if (authenticated && mSensorProps.isAnySidefpsType()) { if (mHandler.hasMessages(MESSAGE_IGNORE_AUTH)) { Slog.i(TAG, "(sideFPS) Ignoring auth due to recent power press"); onErrorInternal(BiometricConstants.BIOMETRIC_ERROR_POWER_PRESSED, 0, true); onErrorInternal(BiometricConstants.BIOMETRIC_ERROR_POWER_PRESSED, 0, true); return; } delay = isKeyguard() ? mWaitForAuthKeyguard : mWaitForAuthBp; Slog.i(TAG, "(sideFPS) Auth succeeded, sideFps waiting for power until: " + delay); Slog.i(TAG, "(sideFPS) Auth succeeded, sideFps waiting for power for: " + delay + "ms"); } mHandler.postDelayed( () -> { if (authenticated && mSensorProps.isAnySidefpsType()) { Slog.i(TAG, "(sideFPS): No power press detected, sending auth"); } super.onAuthenticated(identifier, authenticated, token); if (authenticated) { mState = STATE_STOPPED; mSensorOverlays.hide(getSensorId()); } else { mState = STATE_STARTED_PAUSED_ATTEMPTED; if (mHandler.hasMessages(MESSAGE_FINGER_UP)) { Slog.i(TAG, "Finger up detected, sending auth"); delay = 0; } }, mAuthSuccessRunnable = () -> handleAuthenticate(identifier, authenticated, token); mHandler.postDelayed( mAuthSuccessRunnable, MESSAGE_AUTH_SUCCESS, delay); }); } @Override Loading @@ -227,6 +259,30 @@ class FingerprintAuthenticationClient extends AuthenticationClient<AidlSession> // for most ACQUIRED messages. See BiometricFingerprintConstants#FingerprintAcquired mSensorOverlays.ifUdfps(controller -> controller.onAcquired(getSensorId(), acquiredInfo)); super.onAcquired(acquiredInfo, vendorCode); if (mSensorProps.isAnySidefpsType()) { final boolean shouldLookForVendor = mSkipWaitForPowerAcquireMessage == FINGERPRINT_ACQUIRED_VENDOR; final boolean acquireMessageMatch = acquiredInfo == mSkipWaitForPowerAcquireMessage; final boolean vendorMessageMatch = vendorCode == mSkipWaitForPowerVendorAcquireMessage; final boolean ignorePowerPress = (acquireMessageMatch && !shouldLookForVendor) || (shouldLookForVendor && acquireMessageMatch && vendorMessageMatch); if (ignorePowerPress) { Slog.d(TAG, "(sideFPS) onFingerUp"); mHandler.post(() -> { if (mHandler.hasMessages(MESSAGE_AUTH_SUCCESS)) { Slog.d(TAG, "(sideFPS) skipping wait for power"); mHandler.removeMessages(MESSAGE_AUTH_SUCCESS); mHandler.post(mAuthSuccessRunnable); } else { mHandler.postDelayed(() -> { }, MESSAGE_FINGER_UP, mFingerUpIgnoresPower); } }); } } } @Override Loading Loading @@ -418,6 +474,7 @@ class FingerprintAuthenticationClient extends AuthenticationClient<AidlSession> public void onPowerPressed() { if (mSensorProps.isAnySidefpsType()) { Slog.i(TAG, "(sideFPS): onPowerPressed"); mHandler.post(() -> { if (mHandler.hasMessages(MESSAGE_AUTH_SUCCESS)) { Slog.i(TAG, "(sideFPS): Ignoring auth in queue"); mHandler.removeMessages(MESSAGE_AUTH_SUCCESS); Loading @@ -425,7 +482,10 @@ class FingerprintAuthenticationClient extends AuthenticationClient<AidlSession> onErrorInternal(BiometricConstants.BIOMETRIC_ERROR_POWER_PRESSED, 0, true); } mHandler.removeMessages(MESSAGE_IGNORE_AUTH); mHandler.postDelayed(() -> {}, MESSAGE_IGNORE_AUTH, mIgnoreAuthFor); mHandler.postDelayed(() -> { }, MESSAGE_IGNORE_AUTH, mIgnoreAuthFor); }); } } } services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClientTest.java +93 −11 Original line number Diff line number Diff line Loading @@ -53,6 +53,7 @@ import android.testing.TestableContext; import androidx.test.filters.SmallTest; import androidx.test.platform.app.InstrumentationRegistry; import com.android.internal.R; import com.android.server.biometrics.log.BiometricContext; import com.android.server.biometrics.log.BiometricLogger; import com.android.server.biometrics.log.CallbackWithProbe; Loading Loading @@ -88,11 +89,13 @@ public class FingerprintAuthenticationClientTest { private static final int TOUCH_Y = 20; private static final float TOUCH_MAJOR = 4.4f; private static final float TOUCH_MINOR = 5.5f; private static final int FINGER_UP = 111; @Rule public final TestableContext mContext = new TestableContext( InstrumentationRegistry.getInstrumentation().getTargetContext(), null); @Rule public final MockitoRule mockito = MockitoJUnit.rule(); @Mock private ISession mHal; @Mock Loading Loading @@ -129,11 +132,7 @@ public class FingerprintAuthenticationClientTest { private ArgumentCaptor<PointerContext> mPointerContextCaptor; @Captor private ArgumentCaptor<Consumer<OperationContext>> mContextInjector; private TestLooper mLooper = new TestLooper(); @Rule public final MockitoRule mockito = MockitoJUnit.rule(); private final TestLooper mLooper = new TestLooper(); @Before public void setup() { Loading Loading @@ -358,16 +357,97 @@ public class FingerprintAuthenticationClientTest { final FingerprintAuthenticationClient client = createClient(1); client.start(mCallback); client.onPowerPressed(); mLooper.dispatchAll(); mLooper.moveTimeForward(1000); mLooper.dispatchAll(); client.onAuthenticated(new Fingerprint("friendly", 4 /* fingerId */, 5 /* deviceId */), true /* authenticated */, new ArrayList<>()); mLooper.dispatchAll(); mLooper.moveTimeForward(1000); mLooper.dispatchAll(); verify(mCallback).onClientFinished(any(), eq(true)); } @Test public void sideFingerprintDoesntSendAuthImmediately() throws Exception { when(mSensorProps.isAnySidefpsType()).thenReturn(true); final FingerprintAuthenticationClient client = createClient(1); client.start(mCallback); mLooper.dispatchAll(); client.onAuthenticated(new Fingerprint("friendly", 4 /* fingerId */, 5 /* deviceId */), true /* authenticated */, new ArrayList<>()); mLooper.dispatchAll(); verify(mCallback, never()).onClientFinished(any(), anyBoolean()); } @Test public void sideFingerprintSkipsWindowIfFingerUp() throws Exception { when(mSensorProps.isAnySidefpsType()).thenReturn(true); mContext.getOrCreateTestableResources().addOverride( R.integer.config_sidefpsSkipWaitForPowerAcquireMessage, FINGER_UP); final FingerprintAuthenticationClient client = createClient(1); client.start(mCallback); mLooper.dispatchAll(); client.onAuthenticated(new Fingerprint("friendly", 4 /* fingerId */, 5 /* deviceId */), true /* authenticated */, new ArrayList<>()); client.onAcquired(FINGER_UP, 0); mLooper.dispatchAll(); verify(mCallback).onClientFinished(any(), eq(true)); } @Test public void sideFingerprintSendsAuthIfFingerUp() throws Exception { when(mSensorProps.isAnySidefpsType()).thenReturn(true); mContext.getOrCreateTestableResources().addOverride( R.integer.config_sidefpsSkipWaitForPowerAcquireMessage, FINGER_UP); final FingerprintAuthenticationClient client = createClient(1); client.start(mCallback); mLooper.dispatchAll(); client.onAcquired(FINGER_UP, 0); client.onAuthenticated(new Fingerprint("friendly", 4 /* fingerId */, 5 /* deviceId */), true /* authenticated */, new ArrayList<>()); mLooper.dispatchAll(); verify(mCallback).onClientFinished(any(), eq(true)); } @Test public void sideFingerprintShortCircuitExpires() throws Exception { when(mSensorProps.isAnySidefpsType()).thenReturn(true); final int timeBeforeAuthSent = 500; mContext.getOrCreateTestableResources().addOverride( R.integer.config_sidefpsKeyguardPowerPressWindow, timeBeforeAuthSent); mContext.getOrCreateTestableResources().addOverride( R.integer.config_sidefpsSkipWaitForPowerAcquireMessage, FINGER_UP); final FingerprintAuthenticationClient client = createClient(1); client.start(mCallback); mLooper.dispatchAll(); client.onAcquired(FINGER_UP, 0); mLooper.dispatchAll(); mLooper.moveTimeForward(500); mLooper.dispatchAll(); client.onAuthenticated(new Fingerprint("friendly", 4 /* fingerId */, 5 /* deviceId */), true /* authenticated */, new ArrayList<>()); mLooper.dispatchAll(); verify(mCallback, never()).onClientFinished(any(), anyBoolean()); mLooper.moveTimeForward(500); mLooper.dispatchAll(); verify(mCallback).onClientFinished(any(), eq(true)); } private FingerprintAuthenticationClient createClient() throws RemoteException { return createClient(100 /* version */, true /* allowBackgroundAuthentication */); } Loading @@ -388,11 +468,13 @@ public class FingerprintAuthenticationClientTest { final AidlSession aidl = new AidlSession(version, mHal, USER_ID, mHalSessionCallback); return new FingerprintAuthenticationClient(mContext, () -> aidl, mToken, REQUEST_ID, mClientMonitorCallbackConverter, 5 /* targetUserId */, OP_ID, false /* restricted */, "test-owner", 4 /* cookie */, false /* requireConfirmation */, false /* restricted */, "test-owner", 4 /* cookie */, false /* requireConfirmation */, 9 /* sensorId */, mBiometricLogger, mBiometricContext, true /* isStrongBiometric */, null /* taskStackListener */, mLockoutCache, mUdfpsOverlayController, mSideFpsController, allowBackgroundAuthentication, mSensorProps, mUdfpsOverlayController, mSideFpsController, allowBackgroundAuthentication, mSensorProps, new Handler(mLooper.getLooper())) { @Override protected ActivityTaskManager getActivityTaskManager() { Loading Loading
core/res/res/values/config.xml +10 −0 Original line number Diff line number Diff line Loading @@ -3534,6 +3534,16 @@ automatically dismissing. This is currently used in SideFpsEventHandler --> <integer name="config_sideFpsToastTimeout">3000</integer> <!-- This acquired message will cause the sidefpsKgPowerPress window to be skipped. If this is set to BIOMETRIC_ACQUIRED_VENDOR, then the framework will skip on config_sidefpsSkipWaitForPowerVendorAcquireMessage --> <integer name="config_sidefpsSkipWaitForPowerAcquireMessage">6</integer> <!-- This vendor acquired message that will cause the sidefpsKgPowerPress window to be skipped. config_sidefpsSkipWaitForPowerOnFingerUp must be true and config_sidefpsSkipWaitForPowerAcquireMessage must be BIOMETRIC_ACQUIRED_VENDOR == 6. --> <integer name="config_sidefpsSkipWaitForPowerVendorAcquireMessage">2</integer> <!-- This config is used to force VoiceInteractionService to start on certain low ram devices. It declares the package name of VoiceInteractionService that should be started. --> <string translatable="false" name="config_forceVoiceInteractionServicePackage"></string> Loading
core/res/res/values/symbols.xml +2 −0 Original line number Diff line number Diff line Loading @@ -2634,6 +2634,8 @@ <java-symbol type="integer" name="config_sidefpsKeyguardPowerPressWindow"/> <java-symbol type="integer" name="config_sidefpsPostAuthDowntime"/> <java-symbol type="integer" name="config_sideFpsToastTimeout"/> <java-symbol type="integer" name="config_sidefpsSkipWaitForPowerAcquireMessage"/> <java-symbol type="integer" name="config_sidefpsSkipWaitForPowerVendorAcquireMessage"/> <!-- Clickable toast used during sidefps enrollment --> <java-symbol type="layout" name="side_fps_toast" /> Loading
services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java +100 −40 Original line number Diff line number Diff line Loading @@ -16,6 +16,8 @@ package com.android.server.biometrics.sensors.fingerprint.aidl; import static android.hardware.biometrics.BiometricFingerprintConstants.FINGERPRINT_ACQUIRED_VENDOR; import android.annotation.NonNull; import android.annotation.Nullable; import android.app.TaskStackListener; Loading Loading @@ -65,22 +67,28 @@ import java.util.function.Supplier; class FingerprintAuthenticationClient extends AuthenticationClient<AidlSession> implements Udfps, LockoutConsumer, PowerPressHandler { private static final String TAG = "FingerprintAuthenticationClient"; @NonNull private final LockoutCache mLockoutCache; @NonNull private final SensorOverlays mSensorOverlays; @NonNull private final FingerprintSensorPropertiesInternal mSensorProps; @NonNull private final CallbackWithProbe<Probe> mALSProbeCallback; private static final int MESSAGE_IGNORE_AUTH = 1; private static final int MESSAGE_AUTH_SUCCESS = 2; private static final int MESSAGE_FINGER_UP = 3; @NonNull private final LockoutCache mLockoutCache; @NonNull private final SensorOverlays mSensorOverlays; @NonNull private final FingerprintSensorPropertiesInternal mSensorProps; @NonNull private final CallbackWithProbe<Probe> mALSProbeCallback; private final Handler mHandler; private final int mSkipWaitForPowerAcquireMessage; private final int mSkipWaitForPowerVendorAcquireMessage; private final long mFingerUpIgnoresPower = 500; @Nullable private ICancellationSignal mCancellationSignal; private boolean mIsPointerDown; private final Handler mHandler; private static final int MESSAGE_IGNORE_AUTH = 1; private static final int MESSAGE_AUTH_SUCCESS = 2; private long mWaitForAuthKeyguard; private long mWaitForAuthBp; private long mIgnoreAuthFor; private Runnable mAuthSuccessRunnable; FingerprintAuthenticationClient( @NonNull Context context, Loading Loading @@ -140,6 +148,13 @@ class FingerprintAuthenticationClient extends AuthenticationClient<AidlSession> mIgnoreAuthFor = context.getResources().getInteger(R.integer.config_sidefpsPostAuthDowntime); mSkipWaitForPowerAcquireMessage = context.getResources().getInteger( R.integer.config_sidefpsSkipWaitForPowerAcquireMessage); mSkipWaitForPowerVendorAcquireMessage = context.getResources().getInteger( R.integer.config_sidefpsSkipWaitForPowerVendorAcquireMessage); if (mSensorProps.isAnySidefpsType()) { if (Build.isDebuggable()) { mWaitForAuthKeyguard = Settings.Secure.getIntForUser(context.getContentResolver(), Loading Loading @@ -187,38 +202,55 @@ class FingerprintAuthenticationClient extends AuthenticationClient<AidlSession> return false; } public void handleAuthenticate( BiometricAuthenticator.Identifier identifier, boolean authenticated, ArrayList<Byte> token) { if (authenticated && mSensorProps.isAnySidefpsType()) { Slog.i(TAG, "(sideFPS): No power press detected, sending auth"); } super.onAuthenticated(identifier, authenticated, token); if (authenticated) { mState = STATE_STOPPED; mSensorOverlays.hide(getSensorId()); } else { mState = STATE_STARTED_PAUSED_ATTEMPTED; } } @Override public void onAuthenticated( BiometricAuthenticator.Identifier identifier, boolean authenticated, ArrayList<Byte> token) { mHandler.post( () -> { long delay = 0; if (authenticated && mSensorProps.isAnySidefpsType()) { if (mHandler.hasMessages(MESSAGE_IGNORE_AUTH)) { Slog.i(TAG, "(sideFPS) Ignoring auth due to recent power press"); onErrorInternal(BiometricConstants.BIOMETRIC_ERROR_POWER_PRESSED, 0, true); onErrorInternal(BiometricConstants.BIOMETRIC_ERROR_POWER_PRESSED, 0, true); return; } delay = isKeyguard() ? mWaitForAuthKeyguard : mWaitForAuthBp; Slog.i(TAG, "(sideFPS) Auth succeeded, sideFps waiting for power until: " + delay); Slog.i(TAG, "(sideFPS) Auth succeeded, sideFps waiting for power for: " + delay + "ms"); } mHandler.postDelayed( () -> { if (authenticated && mSensorProps.isAnySidefpsType()) { Slog.i(TAG, "(sideFPS): No power press detected, sending auth"); } super.onAuthenticated(identifier, authenticated, token); if (authenticated) { mState = STATE_STOPPED; mSensorOverlays.hide(getSensorId()); } else { mState = STATE_STARTED_PAUSED_ATTEMPTED; if (mHandler.hasMessages(MESSAGE_FINGER_UP)) { Slog.i(TAG, "Finger up detected, sending auth"); delay = 0; } }, mAuthSuccessRunnable = () -> handleAuthenticate(identifier, authenticated, token); mHandler.postDelayed( mAuthSuccessRunnable, MESSAGE_AUTH_SUCCESS, delay); }); } @Override Loading @@ -227,6 +259,30 @@ class FingerprintAuthenticationClient extends AuthenticationClient<AidlSession> // for most ACQUIRED messages. See BiometricFingerprintConstants#FingerprintAcquired mSensorOverlays.ifUdfps(controller -> controller.onAcquired(getSensorId(), acquiredInfo)); super.onAcquired(acquiredInfo, vendorCode); if (mSensorProps.isAnySidefpsType()) { final boolean shouldLookForVendor = mSkipWaitForPowerAcquireMessage == FINGERPRINT_ACQUIRED_VENDOR; final boolean acquireMessageMatch = acquiredInfo == mSkipWaitForPowerAcquireMessage; final boolean vendorMessageMatch = vendorCode == mSkipWaitForPowerVendorAcquireMessage; final boolean ignorePowerPress = (acquireMessageMatch && !shouldLookForVendor) || (shouldLookForVendor && acquireMessageMatch && vendorMessageMatch); if (ignorePowerPress) { Slog.d(TAG, "(sideFPS) onFingerUp"); mHandler.post(() -> { if (mHandler.hasMessages(MESSAGE_AUTH_SUCCESS)) { Slog.d(TAG, "(sideFPS) skipping wait for power"); mHandler.removeMessages(MESSAGE_AUTH_SUCCESS); mHandler.post(mAuthSuccessRunnable); } else { mHandler.postDelayed(() -> { }, MESSAGE_FINGER_UP, mFingerUpIgnoresPower); } }); } } } @Override Loading Loading @@ -418,6 +474,7 @@ class FingerprintAuthenticationClient extends AuthenticationClient<AidlSession> public void onPowerPressed() { if (mSensorProps.isAnySidefpsType()) { Slog.i(TAG, "(sideFPS): onPowerPressed"); mHandler.post(() -> { if (mHandler.hasMessages(MESSAGE_AUTH_SUCCESS)) { Slog.i(TAG, "(sideFPS): Ignoring auth in queue"); mHandler.removeMessages(MESSAGE_AUTH_SUCCESS); Loading @@ -425,7 +482,10 @@ class FingerprintAuthenticationClient extends AuthenticationClient<AidlSession> onErrorInternal(BiometricConstants.BIOMETRIC_ERROR_POWER_PRESSED, 0, true); } mHandler.removeMessages(MESSAGE_IGNORE_AUTH); mHandler.postDelayed(() -> {}, MESSAGE_IGNORE_AUTH, mIgnoreAuthFor); mHandler.postDelayed(() -> { }, MESSAGE_IGNORE_AUTH, mIgnoreAuthFor); }); } } }
services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClientTest.java +93 −11 Original line number Diff line number Diff line Loading @@ -53,6 +53,7 @@ import android.testing.TestableContext; import androidx.test.filters.SmallTest; import androidx.test.platform.app.InstrumentationRegistry; import com.android.internal.R; import com.android.server.biometrics.log.BiometricContext; import com.android.server.biometrics.log.BiometricLogger; import com.android.server.biometrics.log.CallbackWithProbe; Loading Loading @@ -88,11 +89,13 @@ public class FingerprintAuthenticationClientTest { private static final int TOUCH_Y = 20; private static final float TOUCH_MAJOR = 4.4f; private static final float TOUCH_MINOR = 5.5f; private static final int FINGER_UP = 111; @Rule public final TestableContext mContext = new TestableContext( InstrumentationRegistry.getInstrumentation().getTargetContext(), null); @Rule public final MockitoRule mockito = MockitoJUnit.rule(); @Mock private ISession mHal; @Mock Loading Loading @@ -129,11 +132,7 @@ public class FingerprintAuthenticationClientTest { private ArgumentCaptor<PointerContext> mPointerContextCaptor; @Captor private ArgumentCaptor<Consumer<OperationContext>> mContextInjector; private TestLooper mLooper = new TestLooper(); @Rule public final MockitoRule mockito = MockitoJUnit.rule(); private final TestLooper mLooper = new TestLooper(); @Before public void setup() { Loading Loading @@ -358,16 +357,97 @@ public class FingerprintAuthenticationClientTest { final FingerprintAuthenticationClient client = createClient(1); client.start(mCallback); client.onPowerPressed(); mLooper.dispatchAll(); mLooper.moveTimeForward(1000); mLooper.dispatchAll(); client.onAuthenticated(new Fingerprint("friendly", 4 /* fingerId */, 5 /* deviceId */), true /* authenticated */, new ArrayList<>()); mLooper.dispatchAll(); mLooper.moveTimeForward(1000); mLooper.dispatchAll(); verify(mCallback).onClientFinished(any(), eq(true)); } @Test public void sideFingerprintDoesntSendAuthImmediately() throws Exception { when(mSensorProps.isAnySidefpsType()).thenReturn(true); final FingerprintAuthenticationClient client = createClient(1); client.start(mCallback); mLooper.dispatchAll(); client.onAuthenticated(new Fingerprint("friendly", 4 /* fingerId */, 5 /* deviceId */), true /* authenticated */, new ArrayList<>()); mLooper.dispatchAll(); verify(mCallback, never()).onClientFinished(any(), anyBoolean()); } @Test public void sideFingerprintSkipsWindowIfFingerUp() throws Exception { when(mSensorProps.isAnySidefpsType()).thenReturn(true); mContext.getOrCreateTestableResources().addOverride( R.integer.config_sidefpsSkipWaitForPowerAcquireMessage, FINGER_UP); final FingerprintAuthenticationClient client = createClient(1); client.start(mCallback); mLooper.dispatchAll(); client.onAuthenticated(new Fingerprint("friendly", 4 /* fingerId */, 5 /* deviceId */), true /* authenticated */, new ArrayList<>()); client.onAcquired(FINGER_UP, 0); mLooper.dispatchAll(); verify(mCallback).onClientFinished(any(), eq(true)); } @Test public void sideFingerprintSendsAuthIfFingerUp() throws Exception { when(mSensorProps.isAnySidefpsType()).thenReturn(true); mContext.getOrCreateTestableResources().addOverride( R.integer.config_sidefpsSkipWaitForPowerAcquireMessage, FINGER_UP); final FingerprintAuthenticationClient client = createClient(1); client.start(mCallback); mLooper.dispatchAll(); client.onAcquired(FINGER_UP, 0); client.onAuthenticated(new Fingerprint("friendly", 4 /* fingerId */, 5 /* deviceId */), true /* authenticated */, new ArrayList<>()); mLooper.dispatchAll(); verify(mCallback).onClientFinished(any(), eq(true)); } @Test public void sideFingerprintShortCircuitExpires() throws Exception { when(mSensorProps.isAnySidefpsType()).thenReturn(true); final int timeBeforeAuthSent = 500; mContext.getOrCreateTestableResources().addOverride( R.integer.config_sidefpsKeyguardPowerPressWindow, timeBeforeAuthSent); mContext.getOrCreateTestableResources().addOverride( R.integer.config_sidefpsSkipWaitForPowerAcquireMessage, FINGER_UP); final FingerprintAuthenticationClient client = createClient(1); client.start(mCallback); mLooper.dispatchAll(); client.onAcquired(FINGER_UP, 0); mLooper.dispatchAll(); mLooper.moveTimeForward(500); mLooper.dispatchAll(); client.onAuthenticated(new Fingerprint("friendly", 4 /* fingerId */, 5 /* deviceId */), true /* authenticated */, new ArrayList<>()); mLooper.dispatchAll(); verify(mCallback, never()).onClientFinished(any(), anyBoolean()); mLooper.moveTimeForward(500); mLooper.dispatchAll(); verify(mCallback).onClientFinished(any(), eq(true)); } private FingerprintAuthenticationClient createClient() throws RemoteException { return createClient(100 /* version */, true /* allowBackgroundAuthentication */); } Loading @@ -388,11 +468,13 @@ public class FingerprintAuthenticationClientTest { final AidlSession aidl = new AidlSession(version, mHal, USER_ID, mHalSessionCallback); return new FingerprintAuthenticationClient(mContext, () -> aidl, mToken, REQUEST_ID, mClientMonitorCallbackConverter, 5 /* targetUserId */, OP_ID, false /* restricted */, "test-owner", 4 /* cookie */, false /* requireConfirmation */, false /* restricted */, "test-owner", 4 /* cookie */, false /* requireConfirmation */, 9 /* sensorId */, mBiometricLogger, mBiometricContext, true /* isStrongBiometric */, null /* taskStackListener */, mLockoutCache, mUdfpsOverlayController, mSideFpsController, allowBackgroundAuthentication, mSensorProps, mUdfpsOverlayController, mSideFpsController, allowBackgroundAuthentication, mSensorProps, new Handler(mLooper.getLooper())) { @Override protected ActivityTaskManager getActivityTaskManager() { Loading