Skip wait for power window
Test: atest FingerprintAuthenticationClient Fixes: 242265123 Change-Id: I99509bca62168bf0d2909b964ef5ef9a4dc5429a
This commit is contained in:
@@ -3526,6 +3526,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>
|
||||
|
||||
@@ -2631,6 +2631,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" />
|
||||
|
||||
@@ -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;
|
||||
@@ -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,
|
||||
@@ -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(),
|
||||
@@ -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) {
|
||||
|
||||
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);
|
||||
return;
|
||||
}
|
||||
delay = isKeyguard() ? mWaitForAuthKeyguard : mWaitForAuthBp;
|
||||
Slog.i(TAG, "(sideFPS) Auth succeeded, sideFps waiting for power until: " + delay);
|
||||
}
|
||||
|
||||
mHandler.postDelayed(
|
||||
mHandler.post(
|
||||
() -> {
|
||||
long delay = 0;
|
||||
if (authenticated && mSensorProps.isAnySidefpsType()) {
|
||||
Slog.i(TAG, "(sideFPS): No power press detected, sending auth");
|
||||
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);
|
||||
return;
|
||||
}
|
||||
delay = isKeyguard() ? mWaitForAuthKeyguard : mWaitForAuthBp;
|
||||
Slog.i(TAG, "(sideFPS) Auth succeeded, sideFps waiting for power for: "
|
||||
+ delay + "ms");
|
||||
}
|
||||
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;
|
||||
}
|
||||
},
|
||||
MESSAGE_AUTH_SUCCESS,
|
||||
delay);
|
||||
|
||||
mAuthSuccessRunnable =
|
||||
() -> handleAuthenticate(identifier, authenticated, token);
|
||||
mHandler.postDelayed(
|
||||
mAuthSuccessRunnable,
|
||||
MESSAGE_AUTH_SUCCESS,
|
||||
delay);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -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
|
||||
@@ -418,14 +474,18 @@ class FingerprintAuthenticationClient extends AuthenticationClient<AidlSession>
|
||||
public void onPowerPressed() {
|
||||
if (mSensorProps.isAnySidefpsType()) {
|
||||
Slog.i(TAG, "(sideFPS): onPowerPressed");
|
||||
if (mHandler.hasMessages(MESSAGE_AUTH_SUCCESS)) {
|
||||
Slog.i(TAG, "(sideFPS): Ignoring auth in queue");
|
||||
mHandler.removeMessages(MESSAGE_AUTH_SUCCESS);
|
||||
// Do not call onError() as that will send an additional callback to coex.
|
||||
onErrorInternal(BiometricConstants.BIOMETRIC_ERROR_POWER_PRESSED, 0, true);
|
||||
}
|
||||
mHandler.removeMessages(MESSAGE_IGNORE_AUTH);
|
||||
mHandler.postDelayed(() -> {}, MESSAGE_IGNORE_AUTH, mIgnoreAuthFor);
|
||||
mHandler.post(() -> {
|
||||
if (mHandler.hasMessages(MESSAGE_AUTH_SUCCESS)) {
|
||||
Slog.i(TAG, "(sideFPS): Ignoring auth in queue");
|
||||
mHandler.removeMessages(MESSAGE_AUTH_SUCCESS);
|
||||
// Do not call onError() as that will send an additional callback to coex.
|
||||
onErrorInternal(BiometricConstants.BIOMETRIC_ERROR_POWER_PRESSED, 0, true);
|
||||
}
|
||||
mHandler.removeMessages(MESSAGE_IGNORE_AUTH);
|
||||
mHandler.postDelayed(() -> {
|
||||
}, MESSAGE_IGNORE_AUTH, mIgnoreAuthFor);
|
||||
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
@@ -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
|
||||
@@ -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() {
|
||||
@@ -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 */);
|
||||
}
|
||||
@@ -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 */,
|
||||
9 /* sensorId */, mBiometricLogger, mBiometricContext,
|
||||
true /* isStrongBiometric */,
|
||||
null /* taskStackListener */, mLockoutCache,
|
||||
mUdfpsOverlayController, mSideFpsController, allowBackgroundAuthentication, mSensorProps,
|
||||
false /* restricted */, "test-owner", 4 /* cookie */,
|
||||
false /* requireConfirmation */,
|
||||
9 /* sensorId */, mBiometricLogger, mBiometricContext,
|
||||
true /* isStrongBiometric */,
|
||||
null /* taskStackListener */, mLockoutCache,
|
||||
mUdfpsOverlayController, mSideFpsController, allowBackgroundAuthentication,
|
||||
mSensorProps,
|
||||
new Handler(mLooper.getLooper())) {
|
||||
@Override
|
||||
protected ActivityTaskManager getActivityTaskManager() {
|
||||
|
||||
Reference in New Issue
Block a user