Tests - Add mandatory biometric prompt to platform surfaces (1/N)

Tests for ag/27400418

Flag: android.hardware.biometrics.Flags.MANDATORY_BIOMETRICS
Bug: 339910718
Test: atest FingerprintSettingsFragmentTest ChooseLockGenericTest CombinedBiometricProfileSettingsTest

Change-Id: Ief7fca5d0b695d23d490b6302dea11bab6030fce
This commit is contained in:
Diya Bera
2024-07-15 22:12:03 +00:00
parent 457277d6f5
commit 2348fefd48
5 changed files with 117 additions and 6 deletions

View File

@@ -65,7 +65,8 @@ public abstract class BiometricsSettingsBase extends DashboardFragment {
static final int CONFIRM_REQUEST = 2001; static final int CONFIRM_REQUEST = 2001;
private static final int CHOOSE_LOCK_REQUEST = 2002; private static final int CHOOSE_LOCK_REQUEST = 2002;
protected static final int ACTIVE_UNLOCK_REQUEST = 2003; protected static final int ACTIVE_UNLOCK_REQUEST = 2003;
private static final int BIOMETRIC_AUTH_REQUEST = 2004; @VisibleForTesting
static final int BIOMETRIC_AUTH_REQUEST = 2004;
private static final String SAVE_STATE_CONFIRM_CREDETIAL = "confirm_credential"; private static final String SAVE_STATE_CONFIRM_CREDETIAL = "confirm_credential";
private static final String DO_NOT_FINISH_ACTIVITY = "do_not_finish_activity"; private static final String DO_NOT_FINISH_ACTIVITY = "do_not_finish_activity";

View File

@@ -160,7 +160,8 @@ public class ChooseLockGeneric extends SettingsActivity {
static final int CHOOSE_LOCK_BEFORE_BIOMETRIC_REQUEST = 103; static final int CHOOSE_LOCK_BEFORE_BIOMETRIC_REQUEST = 103;
@VisibleForTesting @VisibleForTesting
static final int SKIP_FINGERPRINT_REQUEST = 104; static final int SKIP_FINGERPRINT_REQUEST = 104;
private static final int BIOMETRIC_AUTH_REQUEST = 105; @VisibleForTesting
static final int BIOMETRIC_AUTH_REQUEST = 105;
private LockPatternUtils mLockPatternUtils; private LockPatternUtils mLockPatternUtils;
private DevicePolicyManager mDpm; private DevicePolicyManager mDpm;

View File

@@ -24,7 +24,9 @@ import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
@@ -36,9 +38,12 @@ import static org.mockito.Mockito.when;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.hardware.biometrics.BiometricManager; import android.hardware.biometrics.BiometricManager;
import android.hardware.biometrics.Flags;
import android.hardware.face.FaceManager; import android.hardware.face.FaceManager;
import android.hardware.fingerprint.FingerprintManager; import android.hardware.fingerprint.FingerprintManager;
import android.os.Bundle; import android.os.Bundle;
import android.platform.test.annotations.EnableFlags;
import android.platform.test.flag.junit.SetFlagsRule;
import android.util.AndroidRuntimeException; import android.util.AndroidRuntimeException;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
@@ -57,6 +62,7 @@ import com.android.settings.R;
import com.android.settings.biometrics.face.FaceStatusPreferenceController; import com.android.settings.biometrics.face.FaceStatusPreferenceController;
import com.android.settings.biometrics.fingerprint.FingerprintStatusPreferenceController; import com.android.settings.biometrics.fingerprint.FingerprintStatusPreferenceController;
import com.android.settings.password.ChooseLockSettingsHelper; import com.android.settings.password.ChooseLockSettingsHelper;
import com.android.settings.password.ConfirmDeviceCredentialActivity;
import com.android.settings.testutils.FakeFeatureFactory; import com.android.settings.testutils.FakeFeatureFactory;
import com.android.settings.testutils.shadow.ShadowFragment; import com.android.settings.testutils.shadow.ShadowFragment;
import com.android.settings.testutils.shadow.ShadowSettingsPreferenceFragment; import com.android.settings.testutils.shadow.ShadowSettingsPreferenceFragment;
@@ -92,6 +98,8 @@ public class CombinedBiometricProfileSettingsTest {
@Rule @Rule
public final MockitoRule mMockitoRule = MockitoJUnit.rule(); public final MockitoRule mMockitoRule = MockitoJUnit.rule();
@Rule
public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
@Captor @Captor
private ArgumentCaptor<Preference> mPreferenceCaptor; private ArgumentCaptor<Preference> mPreferenceCaptor;
@Mock @Mock
@@ -168,6 +176,26 @@ public class CombinedBiometricProfileSettingsTest {
ShadowUtils.reset(); ShadowUtils.reset();
} }
@Test
@EnableFlags(Flags.FLAG_MANDATORY_BIOMETRICS)
public void testLaunchBiometricPrompt_onCreateFragment() {
ArgumentCaptor<Intent> intentArgumentCaptor = ArgumentCaptor.forClass(Intent.class);
doNothing().when(mFragment).startActivityForResult(any(), anyInt());
when(mBiometricManager.canAuthenticate(
BiometricManager.Authenticators.MANDATORY_BIOMETRICS))
.thenReturn(BiometricManager.BIOMETRIC_SUCCESS);
mFragment.onAttach(mContext);
mFragment.onCreate(null);
verify(mFragment).startActivityForResult(intentArgumentCaptor.capture(),
eq(BiometricsSettingsBase.BIOMETRIC_AUTH_REQUEST));
Intent intent = intentArgumentCaptor.getValue();
assertThat(intent.getComponent().getClassName()).isEqualTo(
ConfirmDeviceCredentialActivity.class.getName());
}
@Test @Test
public void testClickFingerprintUnlockWithValidGkPwHandle() { public void testClickFingerprintUnlockWithValidGkPwHandle() {
doAnswer(invocation -> { doAnswer(invocation -> {

View File

@@ -19,6 +19,7 @@ package com.android.settings.biometrics.fingerprint;
import static android.hardware.fingerprint.FingerprintSensorProperties.TYPE_POWER_BUTTON; import static android.hardware.fingerprint.FingerprintSensorProperties.TYPE_POWER_BUTTON;
import static android.hardware.fingerprint.FingerprintSensorProperties.TYPE_UDFPS_OPTICAL; import static android.hardware.fingerprint.FingerprintSensorProperties.TYPE_UDFPS_OPTICAL;
import static com.android.settings.biometrics.BiometricEnrollBase.BIOMETRIC_AUTH_REQUEST;
import static com.android.settings.biometrics.fingerprint.FingerprintSettings.FingerprintSettingsFragment; import static com.android.settings.biometrics.fingerprint.FingerprintSettings.FingerprintSettingsFragment;
import static com.android.settings.biometrics.fingerprint.FingerprintSettings.FingerprintSettingsFragment.CHOOSE_LOCK_GENERIC_REQUEST; import static com.android.settings.biometrics.fingerprint.FingerprintSettings.FingerprintSettingsFragment.CHOOSE_LOCK_GENERIC_REQUEST;
import static com.android.settings.biometrics.fingerprint.FingerprintSettings.FingerprintSettingsFragment.KEY_REQUIRE_SCREEN_ON_TO_AUTH; import static com.android.settings.biometrics.fingerprint.FingerprintSettings.FingerprintSettingsFragment.KEY_REQUIRE_SCREEN_ON_TO_AUTH;
@@ -34,11 +35,14 @@ import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy; import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.pm.UserInfo; import android.content.pm.UserInfo;
import android.hardware.biometrics.BiometricManager;
import android.hardware.biometrics.ComponentInfoInternal; import android.hardware.biometrics.ComponentInfoInternal;
import android.hardware.biometrics.Flags;
import android.hardware.biometrics.SensorProperties; import android.hardware.biometrics.SensorProperties;
import android.hardware.fingerprint.FingerprintManager; import android.hardware.fingerprint.FingerprintManager;
import android.hardware.fingerprint.FingerprintSensorProperties; import android.hardware.fingerprint.FingerprintSensorProperties;
@@ -46,6 +50,8 @@ import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
import android.os.Bundle; import android.os.Bundle;
import android.os.CancellationSignal; import android.os.CancellationSignal;
import android.os.UserHandle; import android.os.UserHandle;
import android.platform.test.annotations.EnableFlags;
import android.platform.test.flag.junit.SetFlagsRule;
import android.provider.Settings; import android.provider.Settings;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.ViewGroup; import android.view.ViewGroup;
@@ -56,6 +62,7 @@ import androidx.fragment.app.FragmentTransaction;
import androidx.test.core.app.ApplicationProvider; import androidx.test.core.app.ApplicationProvider;
import com.android.settings.password.ChooseLockSettingsHelper; import com.android.settings.password.ChooseLockSettingsHelper;
import com.android.settings.password.ConfirmDeviceCredentialActivity;
import com.android.settings.testutils.FakeFeatureFactory; import com.android.settings.testutils.FakeFeatureFactory;
import com.android.settings.testutils.shadow.ShadowFragment; import com.android.settings.testutils.shadow.ShadowFragment;
import com.android.settings.testutils.shadow.ShadowLockPatternUtils; import com.android.settings.testutils.shadow.ShadowLockPatternUtils;
@@ -85,6 +92,11 @@ import java.util.ArrayList;
@Config(shadows = {ShadowSettingsPreferenceFragment.class, ShadowUtils.class, ShadowFragment.class, @Config(shadows = {ShadowSettingsPreferenceFragment.class, ShadowUtils.class, ShadowFragment.class,
ShadowUserManager.class, ShadowLockPatternUtils.class}) ShadowUserManager.class, ShadowLockPatternUtils.class})
public class FingerprintSettingsFragmentTest { public class FingerprintSettingsFragmentTest {
@Rule
public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
@Rule
public final MockitoRule mMockitoRule = MockitoJUnit.rule();
private static final int PRIMARY_USER_ID = 0; private static final int PRIMARY_USER_ID = 0;
private static final int GUEST_USER_ID = 10; private static final int GUEST_USER_ID = 10;
@@ -92,12 +104,12 @@ public class FingerprintSettingsFragmentTest {
private Context mContext; private Context mContext;
private FragmentActivity mActivity; private FragmentActivity mActivity;
@Rule
public final MockitoRule mMockitoRule = MockitoJUnit.rule();
@Mock @Mock
private FingerprintManager mFingerprintManager; private FingerprintManager mFingerprintManager;
@Mock @Mock
private FragmentTransaction mFragmentTransaction; private FragmentTransaction mFragmentTransaction;
@Mock
private BiometricManager mBiometricManager;
@Captor @Captor
private ArgumentCaptor<CancellationSignal> mCancellationSignalArgumentCaptor = private ArgumentCaptor<CancellationSignal> mCancellationSignalArgumentCaptor =
@@ -117,8 +129,11 @@ public class FingerprintSettingsFragmentTest {
mContext = spy(ApplicationProvider.getApplicationContext()); mContext = spy(ApplicationProvider.getApplicationContext());
mFragment = spy(new FingerprintSettingsFragment()); mFragment = spy(new FingerprintSettingsFragment());
doReturn(mContext).when(mFragment).getContext(); doReturn(mContext).when(mFragment).getContext();
doReturn(mBiometricManager).when(mContext).getSystemService(BiometricManager.class);
doReturn(true).when(mFingerprintManager).isHardwareDetected(); doReturn(true).when(mFingerprintManager).isHardwareDetected();
when(mBiometricManager.canAuthenticate(
BiometricManager.Authenticators.MANDATORY_BIOMETRICS))
.thenReturn(BiometricManager.BIOMETRIC_ERROR_HW_UNAVAILABLE);
} }
@After @After
@@ -139,6 +154,25 @@ public class FingerprintSettingsFragmentTest {
false)).isTrue(); false)).isTrue();
} }
@Test
@EnableFlags(Flags.FLAG_MANDATORY_BIOMETRICS)
public void testLaunchBiometricPromptForFingerprint() {
when(mBiometricManager.canAuthenticate(
BiometricManager.Authenticators.MANDATORY_BIOMETRICS))
.thenReturn(BiometricManager.BIOMETRIC_SUCCESS);
setUpFragment(false);
ArgumentCaptor<Intent> intentArgumentCaptor = ArgumentCaptor.forClass(
Intent.class);
verify(mFragment).startActivityForResult(intentArgumentCaptor.capture(),
eq(BIOMETRIC_AUTH_REQUEST));
Intent intent = intentArgumentCaptor.getValue();
assertThat(intent.getComponent().getClassName()).isEqualTo(
ConfirmDeviceCredentialActivity.class.getName());
}
// Test the case when FingerprintAuthenticateSidecar receives an error callback from the // Test the case when FingerprintAuthenticateSidecar receives an error callback from the
// framework or from another authentication client. The cancellation signal should not be set // framework or from another authentication client. The cancellation signal should not be set
// to null because there may exist a running authentication client. // to null because there may exist a running authentication client.

View File

@@ -50,9 +50,13 @@ import android.app.admin.PasswordMetrics;
import android.app.admin.PasswordPolicy; import android.app.admin.PasswordPolicy;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.hardware.biometrics.BiometricManager;
import android.hardware.biometrics.Flags;
import android.hardware.face.FaceManager; import android.hardware.face.FaceManager;
import android.hardware.fingerprint.FingerprintManager; import android.hardware.fingerprint.FingerprintManager;
import android.os.Bundle; import android.os.Bundle;
import android.platform.test.annotations.EnableFlags;
import android.platform.test.flag.junit.SetFlagsRule;
import android.provider.Settings.Global; import android.provider.Settings.Global;
import android.widget.TextView; import android.widget.TextView;
@@ -86,9 +90,13 @@ import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule; import org.mockito.junit.MockitoRule;
import org.robolectric.Robolectric; import org.robolectric.Robolectric;
import org.robolectric.RobolectricTestRunner; import org.robolectric.RobolectricTestRunner;
import org.robolectric.Shadows;
import org.robolectric.android.controller.ActivityController; import org.robolectric.android.controller.ActivityController;
import org.robolectric.annotation.Config; import org.robolectric.annotation.Config;
import org.robolectric.shadow.api.Shadow;
import org.robolectric.shadows.ShadowActivity;
import org.robolectric.shadows.ShadowApplication; import org.robolectric.shadows.ShadowApplication;
import org.robolectric.shadows.ShadowBiometricManager;
@RunWith(RobolectricTestRunner.class) @RunWith(RobolectricTestRunner.class)
@Config( @Config(
@@ -98,18 +106,23 @@ import org.robolectric.shadows.ShadowApplication;
ShadowStorageManager.class, ShadowStorageManager.class,
ShadowUserManager.class, ShadowUserManager.class,
ShadowUtils.class, ShadowUtils.class,
ShadowInteractionJankMonitor.class ShadowInteractionJankMonitor.class,
ShadowBiometricManager.class
}) })
@Ignore("b/179136903: Tests failed with collapsing toolbar, plan to figure out root cause later.") @Ignore("b/179136903: Tests failed with collapsing toolbar, plan to figure out root cause later.")
public class ChooseLockGenericTest { public class ChooseLockGenericTest {
@Rule @Rule
public final MockitoRule mMockitoRule = MockitoJUnit.rule(); public final MockitoRule mMockitoRule = MockitoJUnit.rule();
@Rule
public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
private ActivityController<ChooseLockGeneric> mActivityController; private ActivityController<ChooseLockGeneric> mActivityController;
private FakeFeatureFactory mFakeFeatureFactory; private FakeFeatureFactory mFakeFeatureFactory;
private ChooseLockGenericFragment mFragment; private ChooseLockGenericFragment mFragment;
private ChooseLockGeneric mActivity; private ChooseLockGeneric mActivity;
private ShadowBiometricManager mShadowBiometricManager;
private ShadowActivity mShadowActivity;
@Mock @Mock
private FingerprintManager mFingerprintManager; private FingerprintManager mFingerprintManager;
@Mock @Mock
@@ -125,6 +138,7 @@ public class ChooseLockGenericTest {
.postCreate(null) .postCreate(null)
.resume() .resume()
.get(); .get();
mShadowActivity = Shadows.shadowOf(mActivity);
Global.putInt(application.getContentResolver(), Global.DEVICE_PROVISIONED, 1); Global.putInt(application.getContentResolver(), Global.DEVICE_PROVISIONED, 1);
mFragment = new ChooseLockGenericFragment(); mFragment = new ChooseLockGenericFragment();
@@ -294,6 +308,21 @@ public class ChooseLockGenericTest {
assertThat(mActivity.isFinishing()).isFalse(); assertThat(mActivity.isFinishing()).isFalse();
} }
@Test
@EnableFlags(Flags.FLAG_MANDATORY_BIOMETRICS)
public void onActivityResult_requestcode100_shouldLaunchBiometricPrompt() {
initActivity(null);
mShadowBiometricManager.setCanAuthenticate(true);
mFragment.onActivityResult(
ChooseLockGenericFragment.CONFIRM_EXISTING_REQUEST,
Activity.RESULT_OK, null /* data */);
assertThat(mActivity.isFinishing()).isFalse();
assertThat(mShadowActivity.getNextStartedActivity().getComponent().getClassName())
.isEqualTo(ConfirmDeviceCredentialActivity.class.getName());
}
@Test @Test
public void onActivityResult_requestcode102_shouldFinish() { public void onActivityResult_requestcode102_shouldFinish() {
initActivity(null); initActivity(null);
@@ -336,6 +365,17 @@ public class ChooseLockGenericTest {
assertThat(mActivity.isFinishing()).isTrue(); assertThat(mActivity.isFinishing()).isTrue();
} }
@Test
public void onActivityResult_requestcode105_shouldNotFinish() {
initActivity(null);
mFragment.onActivityResult(
ChooseLockGenericFragment.BIOMETRIC_AUTH_REQUEST, Activity.RESULT_OK,
null /* data */);
assertThat(mActivity.isFinishing()).isFalse();
}
@Test @Test
public void securedScreenLock_notChangingConfig_notWaitForConfirmation_onStopFinishSelf() { public void securedScreenLock_notChangingConfig_notWaitForConfirmation_onStopFinishSelf() {
Intent intent = new Intent().putExtra( Intent intent = new Intent().putExtra(
@@ -676,6 +716,13 @@ public class ChooseLockGenericTest {
mActivity = Robolectric.buildActivity(ChooseLockGeneric.InternalActivity.class, intent) mActivity = Robolectric.buildActivity(ChooseLockGeneric.InternalActivity.class, intent)
.create().start().postCreate(null).resume().get(); .create().start().postCreate(null).resume().get();
mActivity.getSupportFragmentManager().beginTransaction().add(mFragment, null).commitNow(); mActivity.getSupportFragmentManager().beginTransaction().add(mFragment, null).commitNow();
mShadowBiometricManager = Shadow.extract(mFragment.getContext().getSystemService(
BiometricManager.class));
//TODO(b/352603684): Should be Authenticators.MANDATORY_BIOMETRICS,
// but it is not supported by ShadowBiometricManager
mShadowBiometricManager.setAuthenticatorType(
BiometricManager.Authenticators.BIOMETRIC_STRONG);
mShadowBiometricManager.setCanAuthenticate(false);
} }
private static String capitalize(final String input) { private static String capitalize(final String input) {