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

Commit 4d81f75c authored by Austin Delgado's avatar Austin Delgado
Browse files

Added subscription to binder death which removes dead callbacks

Test: atest BiometricStateCallbackTest
Bug: 237439972
Change-Id: I4fad4c5f1042edb27e20c9f916f999092afed0e0
Merged-In: I4fad4c5f1042edb27e20c9f916f999092afed0e0
parent fea416b8
Loading
Loading
Loading
Loading
+22 −1
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@ import static android.hardware.biometrics.BiometricStateListener.STATE_KEYGUARD_
import android.annotation.NonNull;
import android.hardware.biometrics.BiometricStateListener;
import android.hardware.biometrics.IBiometricStateListener;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Slog;

@@ -35,7 +36,7 @@ import java.util.concurrent.CopyOnWriteArrayList;
/**
 * A callback for receiving notifications about biometric sensor state changes.
 */
public class BiometricStateCallback implements ClientMonitorCallback {
public class BiometricStateCallback implements ClientMonitorCallback, IBinder.DeathRecipient {

    private static final String TAG = "BiometricStateCallback";

@@ -153,5 +154,25 @@ public class BiometricStateCallback implements ClientMonitorCallback {
     */
    public void registerBiometricStateListener(@NonNull IBiometricStateListener listener) {
        mBiometricStateListeners.add(listener);
        try {
            listener.asBinder().linkToDeath(this, 0 /* flags */);
        } catch (RemoteException e) {
            Slog.e(TAG, "Failed to link to death", e);
        }
    }

    @Override
    public void binderDied() {
        // Do nothing, handled below
    }

    @Override
    public void binderDied(IBinder who) {
        Slog.w(TAG, "Callback binder died: " + who);
        if (mBiometricStateListeners.removeIf(listener -> listener.asBinder().equals(who))) {
            Slog.w(TAG, "Removed dead listener for " + who);
        } else {
            Slog.w(TAG, "No dead listeners found");
        }
    }
}
+18 −7
Original line number Diff line number Diff line
@@ -24,7 +24,8 @@ import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import android.hardware.biometrics.BiometricStateListener;
import android.hardware.biometrics.IBiometricStateListener;
import android.os.RemoteException;
import android.platform.test.annotations.Presubmit;

import androidx.test.filters.SmallTest;
@@ -45,36 +46,46 @@ public class BiometricStateCallbackTest {
    private BiometricStateCallback mCallback;

    @Mock
    BiometricStateListener mBiometricStateListener;
    private IBiometricStateListener.Stub mBiometricStateListener;

    @Before
    public void setup() {
        MockitoAnnotations.initMocks(this);

        when(mBiometricStateListener.asBinder()).thenReturn(mBiometricStateListener);

        mCallback = new BiometricStateCallback();
        mCallback.registerBiometricStateListener(mBiometricStateListener);
    }

    @Test
    public void testNoEnrollmentsToEnrollments_callbackNotified() {
    public void testNoEnrollmentsToEnrollments_callbackNotified() throws RemoteException {
        testEnrollmentCallback(true /* changed */, true /* isNowEnrolled */,
                true /* expectCallback */, true /* expectedCallbackValue */);
    }

    @Test
    public void testEnrollmentsToNoEnrollments_callbackNotified() {
    public void testEnrollmentsToNoEnrollments_callbackNotified() throws RemoteException {
        testEnrollmentCallback(true /* changed */, false /* isNowEnrolled */,
                true /* expectCallback */, false /* expectedCallbackValue */);
    }

    @Test
    public void testEnrollmentsToEnrollments_callbackNotNotified() {
    public void testEnrollmentsToEnrollments_callbackNotNotified() throws RemoteException {
        testEnrollmentCallback(false /* changed */, true /* isNowEnrolled */,
                false /* expectCallback */, false /* expectedCallbackValue */);
    }

    @Test
    public void testBinderDeath() throws RemoteException {
        mCallback.binderDied(mBiometricStateListener.asBinder());

        testEnrollmentCallback(true /* changed */, false /* isNowEnrolled */,
                false /* expectCallback */, false /* expectedCallbackValue */);
    }

    private void testEnrollmentCallback(boolean changed, boolean isNowEnrolled,
            boolean expectCallback, boolean expectedCallbackValue) {
            boolean expectCallback, boolean expectedCallbackValue) throws RemoteException {
        EnrollClient<?> client = mock(EnrollClient.class);

        final int userId = 10;
@@ -96,7 +107,7 @@ public class BiometricStateCallbackTest {
    }

    @Test
    public void testAuthentication_enrollmentCallbackNeverNotified() {
    public void testAuthentication_enrollmentCallbackNeverNotified() throws RemoteException {
        AuthenticationClient<?> client = mock(AuthenticationClient.class);
        mCallback.onClientFinished(client, true /* success */);
        verify(mBiometricStateListener, never()).onEnrollmentsChanged(anyInt(), anyInt(),