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

Commit 26dbe0cf authored by Joe Bolinger's avatar Joe Bolinger
Browse files

Add tests for use of private and test API configurations in authenticate operations.

Fix: 230118936
Test: atest AuthServiceTest
Change-Id: Iaa60e70ec64a1fd2eb0429ec24efc65b656a307d
parent d12050a4
Loading
Loading
Loading
Loading
+71 −6
Original line number Diff line number Diff line
@@ -16,16 +16,23 @@

package com.android.server.biometrics;

import static android.Manifest.permission.MANAGE_BIOMETRIC;
import static android.Manifest.permission.TEST_BIOMETRIC;
import static android.Manifest.permission.USE_BIOMETRIC_INTERNAL;
import static android.hardware.biometrics.BiometricAuthenticator.TYPE_NONE;
import static android.hardware.biometrics.BiometricConstants.BIOMETRIC_ERROR_CANCELED;
import static android.hardware.biometrics.BiometricConstants.BIOMETRIC_SUCCESS;

import static junit.framework.Assert.assertEquals;

import static org.junit.Assert.assertThrows;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -53,11 +60,14 @@ import androidx.test.filters.SmallTest;
import com.android.internal.R;

import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;
import org.mockito.stubbing.Stubber;

import java.util.List;

@@ -65,11 +75,13 @@ import java.util.List;
@SmallTest
public class AuthServiceTest {

    private static final String TAG = "AuthServiceTest";
    private static final String TEST_OP_PACKAGE_NAME = "test_package";

    private AuthService mAuthService;

    @Rule
    public MockitoRule mockitorule = MockitoJUnit.rule();

    @Mock
    private Context mContext;
    @Mock
@@ -97,8 +109,6 @@ public class AuthServiceTest {

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

        // Placeholder test config
        final String[] config = {
                "0:2:15", // ID0:Fingerprint:Strong
@@ -123,10 +133,13 @@ public class AuthServiceTest {
        when(mInjector.getIrisService()).thenReturn(mIrisService);
        when(mInjector.getAppOps(any())).thenReturn(mAppOpsManager);
        when(mInjector.isHidlDisabled(any())).thenReturn(false);

        setInternalAndTestBiometricPermissions(mContext, false /* hasPermission */);
    }

    @Test
    public void testRegisterNullService_doesNotRegister() throws Exception {
        setInternalAndTestBiometricPermissions(mContext, true /* hasPermission */);

        // Config contains Fingerprint, Iris, Face, but services are all null

@@ -259,6 +272,40 @@ public class AuthServiceTest {
        verify(mReceiver).onError(eq(TYPE_NONE), eq(BIOMETRIC_ERROR_CANCELED), anyInt());
    }

    @Test
    public void testAuthenticate_throwsWhenUsingTestConfigurations() {
        final PromptInfo promptInfo = mock(PromptInfo.class);
        when(promptInfo.containsPrivateApiConfigurations()).thenReturn(false);
        when(promptInfo.containsTestConfigurations()).thenReturn(true);

        testAuthenticate_throwsWhenUsingTestConfigurations(promptInfo);
    }

    @Test
    public void testAuthenticate_throwsWhenUsingPrivateApis() {
        final PromptInfo promptInfo = mock(PromptInfo.class);
        when(promptInfo.containsPrivateApiConfigurations()).thenReturn(true);
        when(promptInfo.containsTestConfigurations()).thenReturn(false);

        testAuthenticate_throwsWhenUsingTestConfigurations(promptInfo);
    }

    private void testAuthenticate_throwsWhenUsingTestConfigurations(PromptInfo promptInfo) {
        mAuthService = new AuthService(mContext, mInjector);
        mAuthService.onStart();

        assertThrows(SecurityException.class, () -> {
            mAuthService.mImpl.authenticate(
                    null /* token */,
                    10 /* sessionId */,
                    2 /* userId */,
                    mReceiver,
                    TEST_OP_PACKAGE_NAME,
                    promptInfo);
            waitForIdle();
        });
    }

    @Test
    public void testCanAuthenticate_callsBiometricServiceCanAuthenticate() throws Exception {
        mAuthService = new AuthService(mContext, mInjector);
@@ -283,8 +330,10 @@ public class AuthServiceTest {
    }

    @Test
    public void testHasEnrolledBiometrics_callsBiometricServiceHasEnrolledBiometrics() throws
            Exception {
    public void testHasEnrolledBiometrics_callsBiometricServiceHasEnrolledBiometrics()
            throws Exception {
        setInternalAndTestBiometricPermissions(mContext, true /* hasPermission */);

        mAuthService = new AuthService(mContext, mInjector);
        mAuthService.onStart();

@@ -307,6 +356,8 @@ public class AuthServiceTest {
    @Test
    public void testRegisterKeyguardCallback_callsBiometricServiceRegisterKeyguardCallback()
            throws Exception {
        setInternalAndTestBiometricPermissions(mContext, true /* hasPermission */);

        mAuthService = new AuthService(mContext, mInjector);
        mAuthService.onStart();

@@ -320,6 +371,20 @@ public class AuthServiceTest {
                eq(callback), eq(UserHandle.getCallingUserId()));
    }

    private static void setInternalAndTestBiometricPermissions(
            Context context, boolean hasPermission) {
        for (String p : List.of(TEST_BIOMETRIC, MANAGE_BIOMETRIC, USE_BIOMETRIC_INTERNAL)) {
            when(context.checkCallingPermission(eq(p))).thenReturn(hasPermission
                    ? PackageManager.PERMISSION_GRANTED : PackageManager.PERMISSION_DENIED);
            when(context.checkCallingOrSelfPermission(eq(p))).thenReturn(hasPermission
                    ? PackageManager.PERMISSION_GRANTED : PackageManager.PERMISSION_DENIED);
            final Stubber doPermCheck =
                    hasPermission ? doNothing() : doThrow(SecurityException.class);
            doPermCheck.when(context).enforceCallingPermission(eq(p), any());
            doPermCheck.when(context).enforceCallingOrSelfPermission(eq(p), any());
        }
    }

    private static void waitForIdle() {
        InstrumentationRegistry.getInstrumentation().waitForIdleSync();
    }