From 66a048d646fd816e7757e300c62fa5cebf04761d Mon Sep 17 00:00:00 2001 From: Joshua McCloskey Date: Thu, 5 Jan 2023 04:15:32 +0000 Subject: [PATCH] Added FingerprintInteractiveToAuthProvider Also removed sidefps logic from FingerprintAuth client. Bug: 261209932 Test: Verified device builds, and sidefps auth no longer delays auth attempts. Change-Id: Ibb993eccda4678013db5b0d64c6f6243c93bdf8a Merged-In: Ibb993eccda4678013db5b0d64c6f6243c93bdf8a --- .../keyguard/KeyguardUpdateMonitor.java | 53 ++-- .../FingerprintInteractiveToAuthProvider.java | 27 ++ .../systemui/dagger/SystemUIModule.java | 4 + .../keyguard/KeyguardUpdateMonitorTest.java | 12 +- .../aidl/FingerprintAuthenticationClient.java | 94 +----- .../FingerprintAuthenticationClientTest.java | 270 ------------------ 6 files changed, 60 insertions(+), 400 deletions(-) create mode 100644 packages/SystemUI/src/com/android/systemui/biometrics/FingerprintInteractiveToAuthProvider.java diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java index 93027c1914ee5..1546d5c58d5ab 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java @@ -141,6 +141,7 @@ import com.android.settingslib.fuelgauge.BatteryStatus; import com.android.systemui.Dumpable; import com.android.systemui.R; import com.android.systemui.biometrics.AuthController; +import com.android.systemui.biometrics.FingerprintInteractiveToAuthProvider; import com.android.systemui.broadcast.BroadcastDispatcher; import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.Background; @@ -170,6 +171,7 @@ import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Map.Entry; +import java.util.Optional; import java.util.Set; import java.util.TimeZone; import java.util.concurrent.Executor; @@ -345,13 +347,11 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab private final ArrayList> mCallbacks = Lists.newArrayList(); private ContentObserver mDeviceProvisionedObserver; - private ContentObserver mSfpsRequireScreenOnToAuthPrefObserver; private final ContentObserver mTimeFormatChangeObserver; private boolean mSwitchingUser; private boolean mDeviceInteractive; - private boolean mSfpsRequireScreenOnToAuthPrefEnabled; private final SubscriptionManager mSubscriptionManager; private final TelephonyListenerManager mTelephonyListenerManager; private final TrustManager mTrustManager; @@ -384,6 +384,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab private boolean mLogoutEnabled; private boolean mIsFaceEnrolled; private int mActiveMobileDataSubscription = SubscriptionManager.INVALID_SUBSCRIPTION_ID; + private FingerprintInteractiveToAuthProvider mFingerprintInteractiveToAuthProvider; /** * Short delay before restarting fingerprint authentication after a successful try. This should @@ -2048,7 +2049,8 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab @Nullable FaceManager faceManager, @Nullable FingerprintManager fingerprintManager, @Nullable BiometricManager biometricManager, - FaceWakeUpTriggersConfig faceWakeUpTriggersConfig) { + FaceWakeUpTriggersConfig faceWakeUpTriggersConfig, + Optional interactiveToAuthProvider) { mContext = context; mSubscriptionManager = subscriptionManager; mUserTracker = userTracker; @@ -2311,30 +2313,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab Settings.System.getUriFor(Settings.System.TIME_12_24), false, mTimeFormatChangeObserver, UserHandle.USER_ALL); - updateSfpsRequireScreenOnToAuthPref(); - mSfpsRequireScreenOnToAuthPrefObserver = new ContentObserver(mHandler) { - @Override - public void onChange(boolean selfChange) { - updateSfpsRequireScreenOnToAuthPref(); - } - }; - - mContext.getContentResolver().registerContentObserver( - mSecureSettings.getUriFor( - Settings.Secure.SFPS_REQUIRE_SCREEN_ON_TO_AUTH_ENABLED), - false, - mSfpsRequireScreenOnToAuthPrefObserver, - getCurrentUser()); - } - - protected void updateSfpsRequireScreenOnToAuthPref() { - final int defaultSfpsRequireScreenOnToAuthValue = - mContext.getResources().getBoolean( - com.android.internal.R.bool.config_requireScreenOnToAuthEnabled) ? 1 : 0; - mSfpsRequireScreenOnToAuthPrefEnabled = mSecureSettings.getIntForUser( - Settings.Secure.SFPS_REQUIRE_SCREEN_ON_TO_AUTH_ENABLED, - defaultSfpsRequireScreenOnToAuthValue, - getCurrentUser()) != 0; + mFingerprintInteractiveToAuthProvider = interactiveToAuthProvider.orElse(null); } private void initializeSimState() { @@ -2729,8 +2708,11 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab boolean shouldListenSideFpsState = true; if (isSideFps) { + final boolean interactiveToAuthEnabled = + mFingerprintInteractiveToAuthProvider != null && + mFingerprintInteractiveToAuthProvider.isEnabled(getCurrentUser()); shouldListenSideFpsState = - mSfpsRequireScreenOnToAuthPrefEnabled ? isDeviceInteractive() : true; + interactiveToAuthEnabled ? isDeviceInteractive() : true; } boolean shouldListen = shouldListenKeyguardState && shouldListenUserState @@ -3845,11 +3827,6 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab mContext.getContentResolver().unregisterContentObserver(mTimeFormatChangeObserver); } - if (mSfpsRequireScreenOnToAuthPrefObserver != null) { - mContext.getContentResolver().unregisterContentObserver( - mSfpsRequireScreenOnToAuthPrefObserver); - } - try { ActivityManager.getService().unregisterUserSwitchObserver(mUserSwitchObserver); } catch (RemoteException e) { @@ -3926,8 +3903,14 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab } else if (isSfpsSupported()) { pw.println(" sfpsEnrolled=" + isSfpsEnrolled()); pw.println(" shouldListenForSfps=" + shouldListenForFingerprint(false)); - pw.println(" mSfpsRequireScreenOnToAuthPrefEnabled=" - + mSfpsRequireScreenOnToAuthPrefEnabled); + if (isSfpsEnrolled()) { + final boolean interactiveToAuthEnabled = + mFingerprintInteractiveToAuthProvider != null && + mFingerprintInteractiveToAuthProvider + .isEnabled(getCurrentUser()); + pw.println(" interactiveToAuthEnabled=" + + interactiveToAuthEnabled); + } } new DumpsysTableLogger( "KeyguardFingerprintListen", diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/FingerprintInteractiveToAuthProvider.java b/packages/SystemUI/src/com/android/systemui/biometrics/FingerprintInteractiveToAuthProvider.java new file mode 100644 index 0000000000000..902bb18d17b29 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/biometrics/FingerprintInteractiveToAuthProvider.java @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.biometrics; + +/** Provides the status of the interactive to auth feature. */ +public interface FingerprintInteractiveToAuthProvider { + /** + * + * @param userId the user Id. + * @return true if the InteractiveToAuthFeature is enabled, false if disabled. + */ + boolean isEnabled(int userId); +} diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java index b8e66735c7408..6d13740afe8ba 100644 --- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java +++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java @@ -31,6 +31,7 @@ import com.android.systemui.BootCompleteCacheImpl; import com.android.systemui.appops.dagger.AppOpsModule; import com.android.systemui.assist.AssistModule; import com.android.systemui.biometrics.AlternateUdfpsTouchProvider; +import com.android.systemui.biometrics.FingerprintInteractiveToAuthProvider; import com.android.systemui.biometrics.UdfpsDisplayModeProvider; import com.android.systemui.biometrics.dagger.BiometricsModule; import com.android.systemui.biometrics.dagger.UdfpsModule; @@ -221,6 +222,9 @@ public abstract class SystemUIModule { @BindsOptionalOf abstract AlternateUdfpsTouchProvider optionalUdfpsTouchProvider(); + @BindsOptionalOf + abstract FingerprintInteractiveToAuthProvider optionalFingerprintInteractiveToAuthProvider(); + @SysUISingleton @Binds abstract SystemClock bindSystemClock(SystemClockImpl systemClock); diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java index 13cd328d00e0d..9a9387b968174 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java +++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java @@ -116,6 +116,7 @@ import com.android.keyguard.KeyguardUpdateMonitor.BiometricAuthenticated; import com.android.keyguard.logging.KeyguardUpdateMonitorLogger; import com.android.systemui.SysuiTestCase; import com.android.systemui.biometrics.AuthController; +import com.android.systemui.biometrics.FingerprintInteractiveToAuthProvider; import com.android.systemui.broadcast.BroadcastDispatcher; import com.android.systemui.dump.DumpManager; import com.android.systemui.log.SessionTracker; @@ -142,6 +143,7 @@ import org.mockito.internal.util.reflection.FieldSetter; import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.Optional; import java.util.concurrent.Executor; import java.util.concurrent.atomic.AtomicBoolean; @@ -233,6 +235,8 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase { @Mock private GlobalSettings mGlobalSettings; private FaceWakeUpTriggersConfig mFaceWakeUpTriggersConfig; + @Mock + private FingerprintInteractiveToAuthProvider mInteractiveToAuthProvider; private final int mCurrentUserId = 100; @@ -1259,8 +1263,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase { when(mAuthController.isSfpsEnrolled(anyInt())).thenReturn(true); // WHEN require screen on to auth is disabled, and keyguard is not awake - when(mSecureSettings.getIntForUser(anyString(), anyInt(), anyInt())).thenReturn(0); - mKeyguardUpdateMonitor.updateSfpsRequireScreenOnToAuthPref(); + when(mInteractiveToAuthProvider.isEnabled(anyInt())).thenReturn(false); mContext.getOrCreateTestableResources().addOverride( com.android.internal.R.bool.config_requireScreenOnToAuthEnabled, true); @@ -1280,8 +1283,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase { assertThat(mKeyguardUpdateMonitor.shouldListenForFingerprint(false)).isTrue(); // WHEN require screen on to auth is enabled, and keyguard is not awake - when(mSecureSettings.getIntForUser(anyString(), anyInt(), anyInt())).thenReturn(1); - mKeyguardUpdateMonitor.updateSfpsRequireScreenOnToAuthPref(); + when(mInteractiveToAuthProvider.isEnabled(anyInt())).thenReturn(true); // THEN we shouldn't listen for sfps when screen off, because require screen on is enabled assertThat(mKeyguardUpdateMonitor.shouldListenForFingerprint(false)).isFalse(); @@ -2407,7 +2409,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase { mPowerManager, mTrustManager, mSubscriptionManager, mUserManager, mDreamManager, mDevicePolicyManager, mSensorPrivacyManager, mTelephonyManager, mPackageManager, mFaceManager, mFingerprintManager, mBiometricManager, - mFaceWakeUpTriggersConfig); + mFaceWakeUpTriggersConfig, Optional.of(mInteractiveToAuthProvider)); setStrongAuthTracker(KeyguardUpdateMonitorTest.this.mStrongAuthTracker); } diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java index 05e83da6a107e..787bfb00a5549 100644 --- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java @@ -16,15 +16,11 @@ package com.android.server.biometrics.sensors.fingerprint.aidl; -import static android.hardware.biometrics.BiometricFingerprintConstants.FINGERPRINT_ACQUIRED_START; -import static android.hardware.biometrics.BiometricFingerprintConstants.FINGERPRINT_ACQUIRED_VENDOR; - import android.annotation.NonNull; import android.annotation.Nullable; import android.app.TaskStackListener; import android.content.Context; import android.hardware.biometrics.BiometricAuthenticator; -import android.hardware.biometrics.BiometricConstants; import android.hardware.biometrics.BiometricFingerprintConstants; import android.hardware.biometrics.BiometricFingerprintConstants.FingerprintAcquired; import android.hardware.biometrics.common.ICancellationSignal; @@ -92,7 +88,6 @@ class FingerprintAuthenticationClient extends AuthenticationClient private long mSideFpsLastAcquireStartTime; private Runnable mAuthSuccessRunnable; private final Clock mClock; - private boolean mDidFinishSfps; FingerprintAuthenticationClient( @NonNull Context context, @@ -198,9 +193,8 @@ class FingerprintAuthenticationClient extends AuthenticationClient @Override protected void handleLifecycleAfterAuth(boolean authenticated) { - if (authenticated && !mDidFinishSfps) { + if (authenticated) { mCallback.onClientFinished(this, true /* success */); - mDidFinishSfps = true; } } @@ -210,13 +204,11 @@ class FingerprintAuthenticationClient extends AuthenticationClient return false; } - public void handleAuthenticate( + @Override + public void onAuthenticated( BiometricAuthenticator.Identifier identifier, boolean authenticated, ArrayList 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; @@ -226,73 +218,12 @@ class FingerprintAuthenticationClient extends AuthenticationClient } } - @Override - public void onAuthenticated( - BiometricAuthenticator.Identifier identifier, - boolean authenticated, - ArrayList token) { - - mHandler.post( - () -> { - long delay = 0; - if (authenticated && mSensorProps.isAnySidefpsType()) { - delay = isKeyguard() ? mWaitForAuthKeyguard : mWaitForAuthBp; - - if (mSideFpsLastAcquireStartTime != -1) { - delay = Math.max(0, - delay - (mClock.millis() - mSideFpsLastAcquireStartTime)); - } - - Slog.i(TAG, "(sideFPS) Auth succeeded, sideFps " - + "waiting for power until: " + delay + "ms"); - } - - 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 public void onAcquired(@FingerprintAcquired int acquiredInfo, int vendorCode) { // For UDFPS, notify SysUI with acquiredInfo, so that the illumination can be turned off // for most ACQUIRED messages. See BiometricFingerprintConstants#FingerprintAcquired mSensorOverlays.ifUdfps(controller -> controller.onAcquired(getSensorId(), acquiredInfo)); super.onAcquired(acquiredInfo, vendorCode); - if (mSensorProps.isAnySidefpsType()) { - if (acquiredInfo == FINGERPRINT_ACQUIRED_START) { - mSideFpsLastAcquireStartTime = mClock.millis(); - } - final boolean shouldLookForVendor = - mSkipWaitForPowerAcquireMessage == FINGERPRINT_ACQUIRED_VENDOR; - final boolean acquireMessageMatch = acquiredInfo == mSkipWaitForPowerAcquireMessage; - final boolean vendorMessageMatch = vendorCode == mSkipWaitForPowerVendorAcquireMessage; - final boolean ignorePowerPress = - acquireMessageMatch && (!shouldLookForVendor || 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 @@ -488,22 +419,5 @@ class FingerprintAuthenticationClient extends AuthenticationClient } @Override - public void onPowerPressed() { - if (mSensorProps.isAnySidefpsType()) { - Slog.i(TAG, "(sideFPS): onPowerPressed"); - mHandler.post(() -> { - if (mDidFinishSfps) { - return; - } - Slog.i(TAG, "(sideFPS): finishing auth"); - // Ignore auths after a power has been detected - mHandler.removeMessages(MESSAGE_AUTH_SUCCESS); - // Do not call onError() as that will send an additional callback to coex. - mDidFinishSfps = true; - onErrorInternal(BiometricConstants.BIOMETRIC_ERROR_POWER_PRESSED, 0, true); - stopHalOperation(); - mSensorOverlays.hide(getSensorId()); - }); - } - } + public void onPowerPressed() { } } diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClientTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClientTest.java index 666d4010e9214..3c735e335e754 100644 --- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClientTest.java +++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClientTest.java @@ -41,7 +41,6 @@ import android.hardware.biometrics.common.OperationContext; import android.hardware.biometrics.fingerprint.ISession; import android.hardware.biometrics.fingerprint.PointerContext; import android.hardware.fingerprint.Fingerprint; -import android.hardware.fingerprint.FingerprintManager; import android.hardware.fingerprint.FingerprintSensorPropertiesInternal; import android.hardware.fingerprint.ISidefpsController; import android.hardware.fingerprint.IUdfpsOverlayController; @@ -55,7 +54,6 @@ 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; @@ -369,274 +367,6 @@ public class FingerprintAuthenticationClientTest { verify(mCancellationSignal).cancel(); } - @Test - public void fingerprintPowerIgnoresAuthInWindow() throws Exception { - when(mSensorProps.isAnySidefpsType()).thenReturn(true); - when(mHal.authenticate(anyLong())).thenReturn(mCancellationSignal); - - final FingerprintAuthenticationClient client = createClient(1); - client.start(mCallback); - client.onPowerPressed(); - client.onAuthenticated(new Fingerprint("friendly", 1 /* fingerId */, 2 /* deviceId */), - true /* authenticated */, new ArrayList<>()); - mLooper.moveTimeForward(1000); - mLooper.dispatchAll(); - - verify(mCallback).onClientFinished(any(), eq(false)); - verify(mCancellationSignal).cancel(); - } - - @Test - public void fingerprintAuthIgnoredWaitingForPower() throws Exception { - when(mSensorProps.isAnySidefpsType()).thenReturn(true); - when(mHal.authenticate(anyLong())).thenReturn(mCancellationSignal); - - final FingerprintAuthenticationClient client = createClient(1); - client.start(mCallback); - client.onAuthenticated(new Fingerprint("friendly", 3 /* fingerId */, 4 /* deviceId */), - true /* authenticated */, new ArrayList<>()); - client.onPowerPressed(); - mLooper.moveTimeForward(1000); - mLooper.dispatchAll(); - - verify(mCallback).onClientFinished(any(), eq(false)); - verify(mCancellationSignal).cancel(); - } - - @Test - public void fingerprintAuthFailsWhenAuthAfterPower() throws Exception { - when(mSensorProps.isAnySidefpsType()).thenReturn(true); - when(mHal.authenticate(anyLong())).thenReturn(mCancellationSignal); - - 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, never()).onClientFinished(any(), eq(true)); - verify(mCallback).onClientFinished(any(), eq(false)); - when(mHal.authenticateWithContext(anyLong(), any())).thenReturn(mCancellationSignal); - } - - @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 sideFingerprintSkipsWindowIfVendorMessageMatch() throws Exception { - when(mSensorProps.isAnySidefpsType()).thenReturn(true); - final int vendorAcquireMessage = 1234; - - mContext.getOrCreateTestableResources().addOverride( - R.integer.config_sidefpsSkipWaitForPowerAcquireMessage, - FingerprintManager.FINGERPRINT_ACQUIRED_VENDOR); - mContext.getOrCreateTestableResources().addOverride( - R.integer.config_sidefpsSkipWaitForPowerVendorAcquireMessage, - vendorAcquireMessage); - - 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(FingerprintManager.FINGERPRINT_ACQUIRED_VENDOR, vendorAcquireMessage); - mLooper.dispatchAll(); - - verify(mCallback).onClientFinished(any(), eq(true)); - } - - @Test - public void sideFingerprintDoesNotSkipWindowOnVendorErrorMismatch() throws Exception { - when(mSensorProps.isAnySidefpsType()).thenReturn(true); - final int vendorAcquireMessage = 1234; - - mContext.getOrCreateTestableResources().addOverride( - R.integer.config_sidefpsSkipWaitForPowerAcquireMessage, - FingerprintManager.FINGERPRINT_ACQUIRED_VENDOR); - mContext.getOrCreateTestableResources().addOverride( - R.integer.config_sidefpsSkipWaitForPowerVendorAcquireMessage, - vendorAcquireMessage); - - 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(FingerprintManager.FINGERPRINT_ACQUIRED_VENDOR, 1); - mLooper.dispatchAll(); - - verify(mCallback, never()).onClientFinished(any(), anyBoolean()); - } - - @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)); - } - - @Test - public void sideFingerprintPowerWindowStartsOnAcquireStart() throws Exception { - final int powerWindow = 500; - final long authStart = 300; - - when(mSensorProps.isAnySidefpsType()).thenReturn(true); - mContext.getOrCreateTestableResources().addOverride( - R.integer.config_sidefpsBpPowerPressWindow, powerWindow); - - final FingerprintAuthenticationClient client = createClient(1); - client.start(mCallback); - - // Acquire start occurs at time = 0ms - when(mClock.millis()).thenReturn(0L); - client.onAcquired(FingerprintManager.FINGERPRINT_ACQUIRED_START, 0 /* vendorCode */); - - // Auth occurs at time = 300 - when(mClock.millis()).thenReturn(authStart); - // At this point the delay should be 500 - (300 - 0) == 200 milliseconds. - client.onAuthenticated(new Fingerprint("friendly", 4 /* fingerId */, 5 /* deviceId */), - true /* authenticated */, new ArrayList<>()); - mLooper.dispatchAll(); - verify(mCallback, never()).onClientFinished(any(), anyBoolean()); - - // After waiting 200 milliseconds, auth should succeed. - mLooper.moveTimeForward(powerWindow - authStart); - mLooper.dispatchAll(); - verify(mCallback).onClientFinished(any(), eq(true)); - } - - @Test - public void sideFingerprintPowerWindowStartsOnLastAcquireStart() throws Exception { - final int powerWindow = 500; - - when(mSensorProps.isAnySidefpsType()).thenReturn(true); - mContext.getOrCreateTestableResources().addOverride( - R.integer.config_sidefpsBpPowerPressWindow, powerWindow); - - final FingerprintAuthenticationClient client = createClient(1); - client.start(mCallback); - // Acquire start occurs at time = 0ms - when(mClock.millis()).thenReturn(0L); - client.onAcquired(FingerprintManager.FINGERPRINT_ACQUIRED_START, 0 /* vendorCode */); - - // Auth reject occurs at time = 300ms - when(mClock.millis()).thenReturn(300L); - client.onAuthenticated(new Fingerprint("friendly", 4 /* fingerId */, 5 /* deviceId */), - false /* authenticated */, new ArrayList<>()); - mLooper.dispatchAll(); - - mLooper.moveTimeForward(300); - mLooper.dispatchAll(); - verify(mCallback, never()).onClientFinished(any(), anyBoolean()); - - when(mClock.millis()).thenReturn(1300L); - client.onAcquired(FingerprintManager.FINGERPRINT_ACQUIRED_START, 0 /* vendorCode */); - - // If code is correct, the new acquired start timestamp should be used - // and the code should only have to wait 500 - (1500-1300)ms. - when(mClock.millis()).thenReturn(1500L); - client.onAuthenticated(new Fingerprint("friendly", 4 /* fingerId */, 5 /* deviceId */), - true /* authenticated */, new ArrayList<>()); - mLooper.dispatchAll(); - - mLooper.moveTimeForward(299); - mLooper.dispatchAll(); - verify(mCallback, never()).onClientFinished(any(), anyBoolean()); - - mLooper.moveTimeForward(1); - mLooper.dispatchAll(); - verify(mCallback).onClientFinished(any(), eq(true)); - } - - @Test - public void sideFpsPowerPressCancelsIsntantly() throws Exception { - when(mSensorProps.isAnySidefpsType()).thenReturn(true); - - final FingerprintAuthenticationClient client = createClient(1); - client.start(mCallback); - - client.onPowerPressed(); - mLooper.dispatchAll(); - - verify(mCallback, never()).onClientFinished(any(), eq(true)); - verify(mCallback).onClientFinished(any(), eq(false)); - } - private FingerprintAuthenticationClient createClient() throws RemoteException { return createClient(100 /* version */, true /* allowBackgroundAuthentication */); }