Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 25403b7d authored by Joshua McCloskey's avatar Joshua McCloskey
Browse files

Skip wait for power window

Test: atest FingerprintAuthenticationClient
Fixes: 242265123
Change-Id: I99509bca62168bf0d2909b964ef5ef9a4dc5429a
parent dc0b0fd9
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -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>
+2 −0
Original line number Diff line number Diff line
@@ -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" />
+100 −40
Original line number Diff line number Diff line
@@ -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) {

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

            });
        }
    }
}
+93 −11
Original line number Diff line number Diff line
@@ -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 */,
                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() {