Merge "Added FingerprintInteractiveToAuthProvider" into tm-qpr-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
103ab3935b
@@ -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<WeakReference<KeyguardUpdateMonitorCallback>>
|
||||
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
|
||||
@@ -2055,7 +2056,8 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
|
||||
@Nullable FaceManager faceManager,
|
||||
@Nullable FingerprintManager fingerprintManager,
|
||||
@Nullable BiometricManager biometricManager,
|
||||
FaceWakeUpTriggersConfig faceWakeUpTriggersConfig) {
|
||||
FaceWakeUpTriggersConfig faceWakeUpTriggersConfig,
|
||||
Optional<FingerprintInteractiveToAuthProvider> interactiveToAuthProvider) {
|
||||
mContext = context;
|
||||
mSubscriptionManager = subscriptionManager;
|
||||
mUserTracker = userTracker;
|
||||
@@ -2318,30 +2320,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() {
|
||||
@@ -2736,8 +2715,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
|
||||
@@ -3852,11 +3834,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) {
|
||||
@@ -3933,8 +3910,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",
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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<AidlSession>
|
||||
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<AidlSession>
|
||||
|
||||
@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<AidlSession>
|
||||
return false;
|
||||
}
|
||||
|
||||
public void handleAuthenticate(
|
||||
@Override
|
||||
public void onAuthenticated(
|
||||
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;
|
||||
@@ -226,73 +218,12 @@ class FingerprintAuthenticationClient extends AuthenticationClient<AidlSession>
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAuthenticated(
|
||||
BiometricAuthenticator.Identifier identifier,
|
||||
boolean authenticated,
|
||||
ArrayList<Byte> 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<AidlSession>
|
||||
}
|
||||
|
||||
@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() { }
|
||||
}
|
||||
|
||||
@@ -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 */);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user