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

Commit cb08949a authored by Diya Bera's avatar Diya Bera
Browse files

Cancel acquisition client in scheduler

If acquisition client has been cancelled and the cancellation not been propagated to the scheduler, force cancel the client in scheduler to avoid it from being hung.

Test: atest BiometricSchedulerTest
Fixes: 263527633
Change-Id: I2c4167950aada9ae564fc44246b4ed83e8444a20
parent b2757069
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -210,4 +210,8 @@ public abstract class AcquisitionClient<T> extends HalClientMonitor<T> implement
    public boolean isInterruptable() {
        return true;
    }

    public boolean isAlreadyCancelled() {
        return mAlreadyCancelled;
    }
}
+8 −0
Original line number Diff line number Diff line
@@ -268,6 +268,14 @@ public class BiometricScheduler {
            return;
        }

        if (mCurrentOperation.isAcquisitionOperation()) {
            AcquisitionClient client = (AcquisitionClient) mCurrentOperation.getClientMonitor();
            if (client.isAlreadyCancelled()) {
                mCurrentOperation.cancel(mHandler, mInternalCallback);
                return;
            }
        }

        if (mGestureAvailabilityDispatcher != null && mCurrentOperation.isAcquisitionOperation()) {
            mGestureAvailabilityDispatcher.markSensorActive(
                    mCurrentOperation.getSensorId(), true /* active */);
+55 −0
Original line number Diff line number Diff line
@@ -19,6 +19,8 @@ package com.android.server.biometrics.sensors;
import static android.hardware.biometrics.BiometricConstants.BIOMETRIC_ERROR_CANCELED;
import static android.hardware.biometrics.BiometricConstants.BIOMETRIC_SUCCESS;

import static com.google.common.truth.Truth.assertThat;

import static junit.framework.Assert.assertTrue;
import static junit.framework.Assert.fail;

@@ -405,6 +407,59 @@ public class BiometricSchedulerTest {
        testCancelsEnrollWhenRequestId(10L, 20, false /* started */);
    }

    @Test
    public void testCancelAuthenticationClientWithoutStarting() {
        final Supplier<Object> lazyDaemon = () -> mock(Object.class);
        final TestHalClientMonitor client1 = new TestHalClientMonitor(mContext, mToken, lazyDaemon);
        final ClientMonitorCallbackConverter callback = mock(ClientMonitorCallbackConverter.class);
        final TestAuthenticationClient client2 = new TestAuthenticationClient(mContext, lazyDaemon,
                mToken, callback, mBiometricContext);

        //Schedule authentication client to the pending queue
        mScheduler.scheduleClientMonitor(client1);
        mScheduler.scheduleClientMonitor(client2);
        waitForIdle();

        assertThat(mScheduler.getCurrentClient()).isEqualTo(client1);

        client2.cancel();
        waitForIdle();

        assertThat(client2.isAlreadyCancelled()).isTrue();

        client1.getCallback().onClientFinished(client1, false);
        waitForIdle();

        assertThat(mScheduler.getCurrentClient()).isNull();
    }

    @Test
    public void testCancelAuthenticationClientWithoutStarting_whenAppCrashes() {
        final Supplier<Object> lazyDaemon = () -> mock(Object.class);
        final TestHalClientMonitor client1 = new TestHalClientMonitor(mContext, mToken, lazyDaemon);
        final ClientMonitorCallbackConverter callback = mock(ClientMonitorCallbackConverter.class);
        final TestAuthenticationClient client2 = new TestAuthenticationClient(mContext, lazyDaemon,
                mToken, callback, mBiometricContext);

        //Schedule authentication client to the pending queue
        mScheduler.scheduleClientMonitor(client1);
        mScheduler.scheduleClientMonitor(client2);
        waitForIdle();

        assertThat(mScheduler.getCurrentClient()).isEqualTo(client1);

        //App crashes
        client2.binderDied();
        waitForIdle();

        assertThat(client2.isAlreadyCancelled()).isTrue();

        client1.getCallback().onClientFinished(client1, false);
        waitForIdle();

        assertThat(mScheduler.getCurrentClient()).isNull();
    }

    private void testCancelsEnrollWhenRequestId(@Nullable Long requestId, long cancelRequestId,
            boolean started) {
        final Supplier<Object> lazyDaemon = () -> mock(Object.class);