Merge "Skip wait for power window" into tm-qpr-dev

This commit is contained in:
Joshua Mccloskey
2022-08-26 17:15:04 +00:00
committed by Android (Google) Code Review
4 changed files with 205 additions and 51 deletions

View File

@@ -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>

View File

@@ -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" />

View File

@@ -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);
});
}
}
}

View File

@@ -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() {