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

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

Cancel non interruptable clients when binder dies

Test: atest com.android.server.biometrics.sensors.face.aidl.SensorTest
Test: atest com.android.server.biometrics.sensors.fingerprint.aidl.SensorTest
Bug: 282695338
Change-Id: Ia8d8beb93c57716bfcc863f2198cdddaf849f349
parent 7a973036
Loading
Loading
Loading
Loading
+5 −3
Original line number Diff line number Diff line
@@ -70,9 +70,11 @@ public class UserAwareBiometricScheduler extends BiometricScheduler {

                // Set mStopUserClient to null when StopUserClient fails. Otherwise it's possible
                // for that the queue will wait indefinitely until the field is cleared.
                if (clientMonitor instanceof StopUserClient<?> && !success) {
                    Slog.w(getTag(),
                            "StopUserClient failed(), is the HAL stuck? Clearing mStopUserClient");
                if (clientMonitor instanceof StopUserClient<?>) {
                    if (!success) {
                        Slog.w(getTag(), "StopUserClient failed(), is the HAL stuck? "
                                + "Clearing mStopUserClient");
                    }
                    mStopUserClient = null;
                }
                if (mCurrentOperation != null && mCurrentOperation.isFor(mOwner)) {
+13 −3
Original line number Diff line number Diff line
@@ -89,7 +89,7 @@ public class Sensor {
    @NonNull private final Map<Integer, Long> mAuthenticatorIds;

    @NonNull private final Supplier<AidlSession> mLazySession;
    @Nullable private AidlSession mCurrentSession;
    @Nullable AidlSession mCurrentSession;

    @VisibleForTesting
    public static class HalSessionCallback extends ISessionCallback.Stub {
@@ -486,7 +486,7 @@ public class Sensor {
    Sensor(@NonNull String tag, @NonNull FaceProvider provider, @NonNull Context context,
            @NonNull Handler handler, @NonNull FaceSensorPropertiesInternal sensorProperties,
            @NonNull LockoutResetDispatcher lockoutResetDispatcher,
            @NonNull BiometricContext biometricContext) {
            @NonNull BiometricContext biometricContext, AidlSession session) {
        mTag = tag;
        mProvider = provider;
        mContext = context;
@@ -549,6 +549,14 @@ public class Sensor {
        mLazySession = () -> mCurrentSession != null ? mCurrentSession : null;
    }

    Sensor(@NonNull String tag, @NonNull FaceProvider provider, @NonNull Context context,
            @NonNull Handler handler, @NonNull FaceSensorPropertiesInternal sensorProperties,
            @NonNull LockoutResetDispatcher lockoutResetDispatcher,
            @NonNull BiometricContext biometricContext) {
        this(tag, provider, context, handler, sensorProperties, lockoutResetDispatcher,
                biometricContext, null);
    }

    @NonNull Supplier<AidlSession> getLazySession() {
        return mLazySession;
    }
@@ -557,7 +565,7 @@ public class Sensor {
        return mSensorProperties;
    }

    @Nullable AidlSession getSessionForUser(int userId) {
    @VisibleForTesting @Nullable AidlSession getSessionForUser(int userId) {
        if (mCurrentSession != null && mCurrentSession.getUserId() == userId) {
            return mCurrentSession;
        } else {
@@ -641,6 +649,8 @@ public class Sensor {
                    BiometricsProtoEnums.MODALITY_FACE,
                    BiometricsProtoEnums.ISSUE_HAL_DEATH,
                    -1 /* sensorId */);
        } else if (client != null) {
            client.cancel();
        }

        mScheduler.recordCrashState();
+14 −2
Original line number Diff line number Diff line
@@ -90,7 +90,7 @@ public class Sensor {
    @NonNull private final LockoutCache mLockoutCache;
    @NonNull private final Map<Integer, Long> mAuthenticatorIds;

    @Nullable private AidlSession mCurrentSession;
    @Nullable AidlSession mCurrentSession;
    @NonNull private final Supplier<AidlSession> mLazySession;

    @VisibleForTesting
@@ -439,7 +439,7 @@ public class Sensor {
            @NonNull Handler handler, @NonNull FingerprintSensorPropertiesInternal sensorProperties,
            @NonNull LockoutResetDispatcher lockoutResetDispatcher,
            @NonNull GestureAvailabilityDispatcher gestureAvailabilityDispatcher,
            @NonNull BiometricContext biometricContext) {
            @NonNull BiometricContext biometricContext, AidlSession session) {
        mTag = tag;
        mProvider = provider;
        mContext = context;
@@ -501,6 +501,16 @@ public class Sensor {
                });
        mAuthenticatorIds = new HashMap<>();
        mLazySession = () -> mCurrentSession != null ? mCurrentSession : null;
        mCurrentSession = session;
    }

    Sensor(@NonNull String tag, @NonNull FingerprintProvider provider, @NonNull Context context,
            @NonNull Handler handler, @NonNull FingerprintSensorPropertiesInternal sensorProperties,
            @NonNull LockoutResetDispatcher lockoutResetDispatcher,
            @NonNull GestureAvailabilityDispatcher gestureAvailabilityDispatcher,
            @NonNull BiometricContext biometricContext) {
        this(tag, provider, context, handler, sensorProperties, lockoutResetDispatcher,
                gestureAvailabilityDispatcher, biometricContext, null);
    }

    @NonNull Supplier<AidlSession> getLazySession() {
@@ -599,6 +609,8 @@ public class Sensor {
                    BiometricsProtoEnums.MODALITY_FINGERPRINT,
                    BiometricsProtoEnums.ISSUE_HAL_DEATH,
                    -1 /* sensorId */);
        } else if (client != null) {
            client.cancel();
        }

        mScheduler.recordCrashState();
+40 −0
Original line number Diff line number Diff line
@@ -17,12 +17,14 @@
package com.android.server.biometrics.sensors.face.aidl;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

@@ -41,6 +43,7 @@ import androidx.test.filters.SmallTest;
import com.android.server.biometrics.log.BiometricContext;
import com.android.server.biometrics.log.BiometricLogger;
import com.android.server.biometrics.sensors.AuthSessionCoordinator;
import com.android.server.biometrics.sensors.BaseClientMonitor;
import com.android.server.biometrics.sensors.BiometricScheduler;
import com.android.server.biometrics.sensors.LockoutCache;
import com.android.server.biometrics.sensors.LockoutResetDispatcher;
@@ -82,6 +85,10 @@ public class SensorTest {
    private AuthSessionCoordinator mAuthSessionCoordinator;
    @Mock
    FaceProvider mFaceProvider;
    @Mock
    BaseClientMonitor mClientMonitor;
    @Mock
    AidlSession mCurrentSession;

    private final TestLooper mLooper = new TestLooper();
    private final LockoutCache mLockoutCache = new LockoutCache();
@@ -161,6 +168,39 @@ public class SensorTest {
        assertNull(sensor.getSessionForUser(USER_ID));
    }

    @Test
    public void onBinderDied_cancelNonInterruptableClient() {
        mLooper.dispatchAll();

        when(mCurrentSession.getUserId()).thenReturn(USER_ID);
        when(mClientMonitor.getTargetUserId()).thenReturn(USER_ID);
        when(mClientMonitor.isInterruptable()).thenReturn(false);

        final SensorProps sensorProps = new SensorProps();
        sensorProps.commonProps = new CommonProps();
        sensorProps.commonProps.sensorId = 1;
        final FaceSensorPropertiesInternal internalProp = new FaceSensorPropertiesInternal(
                sensorProps.commonProps.sensorId, sensorProps.commonProps.sensorStrength,
                sensorProps.commonProps.maxEnrollmentsPerUser, null,
                sensorProps.sensorType, sensorProps.supportsDetectInteraction,
                sensorProps.halControlsPreview, false /* resetLockoutRequiresChallenge */);
        final Sensor sensor = new Sensor("SensorTest", mFaceProvider, mContext, null,
                internalProp, mLockoutResetDispatcher, mBiometricContext, mCurrentSession);
        mScheduler = (UserAwareBiometricScheduler) sensor.getScheduler();
        sensor.mCurrentSession = new AidlSession(0, mock(ISession.class),
                USER_ID, mHalCallback);

        mScheduler.scheduleClientMonitor(mClientMonitor);

        assertNotNull(mScheduler.getCurrentClient());

        sensor.onBinderDied();

        verify(mClientMonitor).cancel();
        assertNull(sensor.getSessionForUser(USER_ID));
        assertNull(mScheduler.getCurrentClient());
    }

    private void verifyNotLocked() {
        assertEquals(LockoutTracker.LOCKOUT_NONE, mLockoutCache.getLockoutModeForUser(USER_ID));
        verify(mLockoutResetDispatcher).notifyLockoutResetCallbacks(eq(SENSOR_ID));
+50 −0
Original line number Diff line number Diff line
@@ -17,17 +17,23 @@
package com.android.server.biometrics.sensors.fingerprint.aidl;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import android.content.Context;
import android.hardware.biometrics.IBiometricService;
import android.hardware.biometrics.common.CommonProps;
import android.hardware.biometrics.face.SensorProps;
import android.hardware.biometrics.fingerprint.ISession;
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
import android.os.Handler;
import android.os.test.TestLooper;
import android.platform.test.annotations.Presubmit;
@@ -37,11 +43,13 @@ import androidx.test.filters.SmallTest;
import com.android.server.biometrics.log.BiometricContext;
import com.android.server.biometrics.log.BiometricLogger;
import com.android.server.biometrics.sensors.AuthSessionCoordinator;
import com.android.server.biometrics.sensors.BaseClientMonitor;
import com.android.server.biometrics.sensors.BiometricScheduler;
import com.android.server.biometrics.sensors.LockoutCache;
import com.android.server.biometrics.sensors.LockoutResetDispatcher;
import com.android.server.biometrics.sensors.LockoutTracker;
import com.android.server.biometrics.sensors.UserAwareBiometricScheduler;
import com.android.server.biometrics.sensors.fingerprint.GestureAvailabilityDispatcher;

import org.junit.Before;
import org.junit.Test;
@@ -76,6 +84,14 @@ public class SensorTest {
    private BiometricContext mBiometricContext;
    @Mock
    private AuthSessionCoordinator mAuthSessionCoordinator;
    @Mock
    FingerprintProvider mFingerprintProvider;
    @Mock
    GestureAvailabilityDispatcher mGestureAvailabilityDispatcher;
    @Mock
    private AidlSession mCurrentSession;
    @Mock
    private BaseClientMonitor mClientMonitor;

    private final TestLooper mLooper = new TestLooper();
    private final LockoutCache mLockoutCache = new LockoutCache();
@@ -130,6 +146,40 @@ public class SensorTest {
        verifyNotLocked();
    }

    @Test
    public void onBinderDied_cancelNonInterruptableClient() {
        mLooper.dispatchAll();

        when(mCurrentSession.getUserId()).thenReturn(USER_ID);
        when(mClientMonitor.getTargetUserId()).thenReturn(USER_ID);
        when(mClientMonitor.isInterruptable()).thenReturn(false);

        final SensorProps sensorProps = new SensorProps();
        sensorProps.commonProps = new CommonProps();
        sensorProps.commonProps.sensorId = 1;
        final FingerprintSensorPropertiesInternal internalProp = new
                FingerprintSensorPropertiesInternal(
                        sensorProps.commonProps.sensorId, sensorProps.commonProps.sensorStrength,
                        sensorProps.commonProps.maxEnrollmentsPerUser, null,
                        sensorProps.sensorType, false /* resetLockoutRequiresHardwareAuthToken */);
        final Sensor sensor = new Sensor("SensorTest", mFingerprintProvider, mContext,
                null /* handler */, internalProp, mLockoutResetDispatcher,
                mGestureAvailabilityDispatcher, mBiometricContext, mCurrentSession);
        mScheduler = (UserAwareBiometricScheduler) sensor.getScheduler();
        sensor.mCurrentSession = new AidlSession(0, mock(ISession.class),
                USER_ID, mHalCallback);

        mScheduler.scheduleClientMonitor(mClientMonitor);

        assertNotNull(mScheduler.getCurrentClient());

        sensor.onBinderDied();

        verify(mClientMonitor).cancel();
        assertNull(sensor.getSessionForUser(USER_ID));
        assertNull(mScheduler.getCurrentClient());
    }

    private void verifyNotLocked() {
        assertEquals(LockoutTracker.LOCKOUT_NONE, mLockoutCache.getLockoutModeForUser(USER_ID));
        verify(mLockoutResetDispatcher).notifyLockoutResetCallbacks(eq(SENSOR_ID));