Loading src/com/android/settings/biometrics/combination/BiometricsSettingsBase.java +13 −0 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FINGERPRIN import static com.android.settings.password.ChooseLockPattern.RESULT_FINISHED; import android.app.Activity; import android.content.Context; import android.content.Intent; import android.hardware.biometrics.SensorProperties; Loading Loading @@ -179,6 +180,12 @@ public abstract class BiometricsSettingsBase extends DashboardFragment { } mFaceManager.generateChallenge(mUserId, (sensorId, userId, challenge) -> { final Activity activity = getActivity(); if (activity == null || activity.isFinishing()) { Log.e(getLogTag(), "Stop during generating face unlock challenge" + " because activity is null or finishing"); return; } try { final byte[] token = requestGatekeeperHat(context, mGkPwHandle, mUserId, challenge); Loading Loading @@ -215,6 +222,12 @@ public abstract class BiometricsSettingsBase extends DashboardFragment { } mFingerprintManager.generateChallenge(mUserId, (sensorId, userId, challenge) -> { final Activity activity = getActivity(); if (activity == null || activity.isFinishing()) { Log.e(getLogTag(), "Stop during generating fingerprint challenge" + " because activity is null or finishing"); return; } try { final byte[] token = requestGatekeeperHat(context, mGkPwHandle, mUserId, challenge); Loading tests/robotests/src/com/android/settings/biometrics/combination/CombinedBiometricProfileSettingsTest.java +112 −13 Original line number Diff line number Diff line Loading @@ -43,6 +43,7 @@ import android.hardware.face.FaceManager; import android.hardware.fingerprint.FingerprintManager; import android.hardware.fingerprint.FingerprintSensorPropertiesInternal; import android.os.Bundle; import android.util.AndroidRuntimeException; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; Loading @@ -58,7 +59,10 @@ import androidx.preference.PreferenceScreen; import androidx.test.core.app.ApplicationProvider; import com.android.settings.R; import com.android.settings.biometrics.BiometricStatusPreferenceController; import com.android.settings.biometrics.BiometricsSplitScreenDialog; import com.android.settings.biometrics.face.FaceStatusPreferenceController; import com.android.settings.biometrics.fingerprint.FingerprintStatusPreferenceController; import com.android.settings.password.ChooseLockSettingsHelper; import com.android.settings.testutils.FakeFeatureFactory; import com.android.settings.testutils.shadow.ShadowFragment; Loading @@ -68,7 +72,6 @@ import com.android.settingslib.core.AbstractPreferenceController; import org.junit.After; import org.junit.Before; import org.junit.Ignore; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; Loading @@ -86,7 +89,6 @@ import java.util.ArrayList; import java.util.List; import java.util.Map; @Ignore @RunWith(RobolectricTestRunner.class) @Config(shadows = {ShadowSettingsPreferenceFragment.class, ShadowUtils.class, ShadowFragment.class}) public class CombinedBiometricProfileSettingsTest { Loading @@ -104,6 +106,10 @@ public class CombinedBiometricProfileSettingsTest { @Mock private BiometricSettingsAppPreferenceController mBiometricSettingsAppPreferenceController; @Mock private FingerprintStatusPreferenceController mFingerprintStatusPreferenceController; @Mock private FaceStatusPreferenceController mFaceStatusPreferenceController; @Mock private FaceManager mFaceManager; @Mock private FragmentTransaction mFragmentTransaction; Loading @@ -128,6 +134,29 @@ public class CombinedBiometricProfileSettingsTest { List<AbstractPreferenceController> controllerList = new ArrayList<>(); controllerList.add(mBiometricSettingsAppPreferenceController); preferenceControllers.put(BiometricSettingsAppPreferenceController.class, controllerList); controllerList.add(mFingerprintStatusPreferenceController); preferenceControllers.put(FingerprintStatusPreferenceController.class, controllerList); controllerList.add(mFaceStatusPreferenceController); preferenceControllers.put(FaceStatusPreferenceController.class, controllerList); doAnswer(invocation -> { final Preference preference = invocation.getArgument(0); return preference.getKey().equals(mFragment.getFingerprintPreferenceKey()); }).when(mFingerprintStatusPreferenceController) .setPreferenceTreeClickLauncher(any(), any()); doAnswer(invocation -> { final Preference preference = invocation.getArgument(0); return preference.getKey().equals(mFragment.getFingerprintPreferenceKey()); }).when(mFingerprintStatusPreferenceController).handlePreferenceTreeClick(any()); doAnswer(invocation -> { final Preference preference = invocation.getArgument(0); return preference.getKey().equals(mFragment.getFacePreferenceKey()); }).when(mFaceStatusPreferenceController) .setPreferenceTreeClickLauncher(any(), any()); doAnswer(invocation -> { final Preference preference = invocation.getArgument(0); return preference.getKey().equals(mFragment.getFacePreferenceKey()); }).when(mFaceStatusPreferenceController).handlePreferenceTreeClick(any()); doAnswer(invocation -> { final CharSequence key = invocation.getArgument(0); Loading Loading @@ -164,7 +193,7 @@ public class CombinedBiometricProfileSettingsTest { preference.setKey(mFragment.getFingerprintPreferenceKey()); mFragment.onPreferenceTreeClick(preference); verify(mBiometricSettingsAppPreferenceController).handlePreferenceTreeClick( verify(mFingerprintStatusPreferenceController).handlePreferenceTreeClick( mPreferenceCaptor.capture()); List<Preference> capturedPreferences = mPreferenceCaptor.getAllValues(); Loading Loading @@ -224,7 +253,7 @@ public class CombinedBiometricProfileSettingsTest { mFragment.onActivityResult(CONFIRM_REQUEST, RESULT_FINISHED, new Intent().putExtra(ChooseLockSettingsHelper.EXTRA_KEY_GK_PW_HANDLE, 1L)); verify(mBiometricSettingsAppPreferenceController).handlePreferenceTreeClick( verify(mFingerprintStatusPreferenceController).handlePreferenceTreeClick( mPreferenceCaptor.capture()); List<Preference> capturedPreferences = mPreferenceCaptor.getAllValues(); assertThat(capturedPreferences.size()).isEqualTo(1); Loading Loading @@ -254,7 +283,7 @@ public class CombinedBiometricProfileSettingsTest { preference.setKey(mFragment.getFacePreferenceKey()); mFragment.onPreferenceTreeClick(preference); verify(mBiometricSettingsAppPreferenceController).handlePreferenceTreeClick( verify(mFaceStatusPreferenceController).handlePreferenceTreeClick( mPreferenceCaptor.capture()); List<Preference> capturedPreferences = mPreferenceCaptor.getAllValues(); assertThat(capturedPreferences.size()).isEqualTo(1); Loading Loading @@ -313,7 +342,7 @@ public class CombinedBiometricProfileSettingsTest { preference.setKey(mFragment.getFacePreferenceKey()); mFragment.onPreferenceTreeClick(preference); verify(mBiometricSettingsAppPreferenceController).handlePreferenceTreeClick( verify(mFaceStatusPreferenceController).handlePreferenceTreeClick( mPreferenceCaptor.capture()); List<Preference> capturedPreferences = mPreferenceCaptor.getAllValues(); assertThat(capturedPreferences.size()).isEqualTo(1); Loading @@ -323,7 +352,7 @@ public class CombinedBiometricProfileSettingsTest { @Test public void testClickFingerprintUnlock_inMultiWindow_withoutEnrolledFp_showsDialog() { testClickFingerprintUnlock(true /* isInMultiWindow */, false /* hasEnrolledFingerprint */); verifyShowsDialogAfterClickingUnlock(); verifyShowsDialogAfterClickingUnlock(mFragment.getFingerprintPreferenceKey()); } @Test Loading Loading @@ -380,7 +409,7 @@ public class CombinedBiometricProfileSettingsTest { @Test public void testClickFaceUnlock_inMultiWindow_withoutEnrolledFp_showsDialog() { testClickFaceUnlock(true /* isInMultiWindow */, false /*hasEnrolledFace*/); verifyShowsDialogAfterClickingUnlock(); verifyShowsDialogAfterClickingUnlock(mFragment.getFacePreferenceKey()); } @Test Loading Loading @@ -424,8 +453,11 @@ public class CombinedBiometricProfileSettingsTest { } private void verifyNoDialogAfterClickingUnlock(String preferenceKey) { verify(mBiometricSettingsAppPreferenceController).handlePreferenceTreeClick( mPreferenceCaptor.capture()); final BiometricStatusPreferenceController controller = preferenceKey.equals(mFragment.getFacePreferenceKey()) ? mFaceStatusPreferenceController : mFingerprintStatusPreferenceController; verify(controller).handlePreferenceTreeClick(mPreferenceCaptor.capture()); List<Preference> capturedPreferences = mPreferenceCaptor.getAllValues(); assertThat(capturedPreferences).hasSize(1); assertThat(capturedPreferences.get(0).getKey()).isEqualTo(preferenceKey); Loading @@ -433,12 +465,77 @@ public class CombinedBiometricProfileSettingsTest { eq(BiometricsSplitScreenDialog.class.getName())); } private void verifyShowsDialogAfterClickingUnlock() { verify(mBiometricSettingsAppPreferenceController, never()).handlePreferenceTreeClick(any()); private void verifyShowsDialogAfterClickingUnlock(String preferenceKey) { final BiometricStatusPreferenceController controller = preferenceKey.equals(mFragment.getFacePreferenceKey()) ? mFaceStatusPreferenceController : mFingerprintStatusPreferenceController; verify(controller, never()).handlePreferenceTreeClick(any()); verify(mFragmentTransaction).add(any(), eq(BiometricsSplitScreenDialog.class.getName())); } @Test public void testNoCrashIfDetachActivityDuringGeneratingChallengeThroughFaceManager() { doAnswer(invocation -> { final FaceManager.GenerateChallengeCallback callback = invocation.getArgument(1); mFragment.onPause(); mFragment.onStop(); mFragment.onDestroy(); mFragment.onDetach(); doReturn(null).when(mFragment).getActivity(); callback.onGenerateChallengeResult(0, 0, 1L); return null; }).when(mFaceManager).generateChallenge(anyInt(), any()); doThrow(new IllegalStateException("Test")).when(mFragment).requestGatekeeperHat( any(), anyLong(), anyInt(), anyLong()); FragmentManager fragmentManager = mock(FragmentManager.class); // Start fragment mFragment.onAttach(mContext); mFragment.onCreate(null); mFragment.onCreateView(LayoutInflater.from(mContext), mock(ViewGroup.class), Bundle.EMPTY); mFragment.onResume(); // User clicks on "Face Unlock" final Preference preference = new Preference(mContext); preference.setKey(mFragment.getFacePreferenceKey()); mFragment.onPreferenceTreeClick(preference); verify(mFragment, never()).launchChooseOrConfirmLock(); } @Test public void testNoCrashIfDetachActivityDuringGeneratingChallengeThroughFingerprintManager() { doAnswer(invocation -> { final FingerprintManager.GenerateChallengeCallback callback = invocation.getArgument(1); mFragment.onPause(); mFragment.onStop(); mFragment.onDestroy(); mFragment.onDetach(); doReturn(null).when(mFragment).getActivity(); callback.onChallengeGenerated(0, 0, 1L); return null; }).when(mFingerprintManager).generateChallenge(anyInt(), any()); doThrow(new IllegalStateException("Test")).when(mFragment).requestGatekeeperHat( any(), anyLong(), anyInt(), anyLong()); // Start fragment mFragment.onAttach(mContext); mFragment.onCreate(null); mFragment.onCreateView(LayoutInflater.from(mContext), mock(ViewGroup.class), Bundle.EMPTY); mFragment.onResume(); // User clicks on "Fingerprint Unlock" final Preference preference = new Preference(mContext); preference.setKey(mFragment.getFingerprintPreferenceKey()); mFragment.onPreferenceTreeClick(preference); verify(mFragment, never()).launchChooseOrConfirmLock(); } /** * a test fragment that initializes PreferenceScreen for testing. */ Loading Loading @@ -492,7 +589,9 @@ public class CombinedBiometricProfileSettingsTest { @Override protected void launchChooseOrConfirmLock() { // do nothing if (getActivity() == null) { throw new AndroidRuntimeException("TestFailed"); } } } } Loading
src/com/android/settings/biometrics/combination/BiometricsSettingsBase.java +13 −0 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FINGERPRIN import static com.android.settings.password.ChooseLockPattern.RESULT_FINISHED; import android.app.Activity; import android.content.Context; import android.content.Intent; import android.hardware.biometrics.SensorProperties; Loading Loading @@ -179,6 +180,12 @@ public abstract class BiometricsSettingsBase extends DashboardFragment { } mFaceManager.generateChallenge(mUserId, (sensorId, userId, challenge) -> { final Activity activity = getActivity(); if (activity == null || activity.isFinishing()) { Log.e(getLogTag(), "Stop during generating face unlock challenge" + " because activity is null or finishing"); return; } try { final byte[] token = requestGatekeeperHat(context, mGkPwHandle, mUserId, challenge); Loading Loading @@ -215,6 +222,12 @@ public abstract class BiometricsSettingsBase extends DashboardFragment { } mFingerprintManager.generateChallenge(mUserId, (sensorId, userId, challenge) -> { final Activity activity = getActivity(); if (activity == null || activity.isFinishing()) { Log.e(getLogTag(), "Stop during generating fingerprint challenge" + " because activity is null or finishing"); return; } try { final byte[] token = requestGatekeeperHat(context, mGkPwHandle, mUserId, challenge); Loading
tests/robotests/src/com/android/settings/biometrics/combination/CombinedBiometricProfileSettingsTest.java +112 −13 Original line number Diff line number Diff line Loading @@ -43,6 +43,7 @@ import android.hardware.face.FaceManager; import android.hardware.fingerprint.FingerprintManager; import android.hardware.fingerprint.FingerprintSensorPropertiesInternal; import android.os.Bundle; import android.util.AndroidRuntimeException; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; Loading @@ -58,7 +59,10 @@ import androidx.preference.PreferenceScreen; import androidx.test.core.app.ApplicationProvider; import com.android.settings.R; import com.android.settings.biometrics.BiometricStatusPreferenceController; import com.android.settings.biometrics.BiometricsSplitScreenDialog; import com.android.settings.biometrics.face.FaceStatusPreferenceController; import com.android.settings.biometrics.fingerprint.FingerprintStatusPreferenceController; import com.android.settings.password.ChooseLockSettingsHelper; import com.android.settings.testutils.FakeFeatureFactory; import com.android.settings.testutils.shadow.ShadowFragment; Loading @@ -68,7 +72,6 @@ import com.android.settingslib.core.AbstractPreferenceController; import org.junit.After; import org.junit.Before; import org.junit.Ignore; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; Loading @@ -86,7 +89,6 @@ import java.util.ArrayList; import java.util.List; import java.util.Map; @Ignore @RunWith(RobolectricTestRunner.class) @Config(shadows = {ShadowSettingsPreferenceFragment.class, ShadowUtils.class, ShadowFragment.class}) public class CombinedBiometricProfileSettingsTest { Loading @@ -104,6 +106,10 @@ public class CombinedBiometricProfileSettingsTest { @Mock private BiometricSettingsAppPreferenceController mBiometricSettingsAppPreferenceController; @Mock private FingerprintStatusPreferenceController mFingerprintStatusPreferenceController; @Mock private FaceStatusPreferenceController mFaceStatusPreferenceController; @Mock private FaceManager mFaceManager; @Mock private FragmentTransaction mFragmentTransaction; Loading @@ -128,6 +134,29 @@ public class CombinedBiometricProfileSettingsTest { List<AbstractPreferenceController> controllerList = new ArrayList<>(); controllerList.add(mBiometricSettingsAppPreferenceController); preferenceControllers.put(BiometricSettingsAppPreferenceController.class, controllerList); controllerList.add(mFingerprintStatusPreferenceController); preferenceControllers.put(FingerprintStatusPreferenceController.class, controllerList); controllerList.add(mFaceStatusPreferenceController); preferenceControllers.put(FaceStatusPreferenceController.class, controllerList); doAnswer(invocation -> { final Preference preference = invocation.getArgument(0); return preference.getKey().equals(mFragment.getFingerprintPreferenceKey()); }).when(mFingerprintStatusPreferenceController) .setPreferenceTreeClickLauncher(any(), any()); doAnswer(invocation -> { final Preference preference = invocation.getArgument(0); return preference.getKey().equals(mFragment.getFingerprintPreferenceKey()); }).when(mFingerprintStatusPreferenceController).handlePreferenceTreeClick(any()); doAnswer(invocation -> { final Preference preference = invocation.getArgument(0); return preference.getKey().equals(mFragment.getFacePreferenceKey()); }).when(mFaceStatusPreferenceController) .setPreferenceTreeClickLauncher(any(), any()); doAnswer(invocation -> { final Preference preference = invocation.getArgument(0); return preference.getKey().equals(mFragment.getFacePreferenceKey()); }).when(mFaceStatusPreferenceController).handlePreferenceTreeClick(any()); doAnswer(invocation -> { final CharSequence key = invocation.getArgument(0); Loading Loading @@ -164,7 +193,7 @@ public class CombinedBiometricProfileSettingsTest { preference.setKey(mFragment.getFingerprintPreferenceKey()); mFragment.onPreferenceTreeClick(preference); verify(mBiometricSettingsAppPreferenceController).handlePreferenceTreeClick( verify(mFingerprintStatusPreferenceController).handlePreferenceTreeClick( mPreferenceCaptor.capture()); List<Preference> capturedPreferences = mPreferenceCaptor.getAllValues(); Loading Loading @@ -224,7 +253,7 @@ public class CombinedBiometricProfileSettingsTest { mFragment.onActivityResult(CONFIRM_REQUEST, RESULT_FINISHED, new Intent().putExtra(ChooseLockSettingsHelper.EXTRA_KEY_GK_PW_HANDLE, 1L)); verify(mBiometricSettingsAppPreferenceController).handlePreferenceTreeClick( verify(mFingerprintStatusPreferenceController).handlePreferenceTreeClick( mPreferenceCaptor.capture()); List<Preference> capturedPreferences = mPreferenceCaptor.getAllValues(); assertThat(capturedPreferences.size()).isEqualTo(1); Loading Loading @@ -254,7 +283,7 @@ public class CombinedBiometricProfileSettingsTest { preference.setKey(mFragment.getFacePreferenceKey()); mFragment.onPreferenceTreeClick(preference); verify(mBiometricSettingsAppPreferenceController).handlePreferenceTreeClick( verify(mFaceStatusPreferenceController).handlePreferenceTreeClick( mPreferenceCaptor.capture()); List<Preference> capturedPreferences = mPreferenceCaptor.getAllValues(); assertThat(capturedPreferences.size()).isEqualTo(1); Loading Loading @@ -313,7 +342,7 @@ public class CombinedBiometricProfileSettingsTest { preference.setKey(mFragment.getFacePreferenceKey()); mFragment.onPreferenceTreeClick(preference); verify(mBiometricSettingsAppPreferenceController).handlePreferenceTreeClick( verify(mFaceStatusPreferenceController).handlePreferenceTreeClick( mPreferenceCaptor.capture()); List<Preference> capturedPreferences = mPreferenceCaptor.getAllValues(); assertThat(capturedPreferences.size()).isEqualTo(1); Loading @@ -323,7 +352,7 @@ public class CombinedBiometricProfileSettingsTest { @Test public void testClickFingerprintUnlock_inMultiWindow_withoutEnrolledFp_showsDialog() { testClickFingerprintUnlock(true /* isInMultiWindow */, false /* hasEnrolledFingerprint */); verifyShowsDialogAfterClickingUnlock(); verifyShowsDialogAfterClickingUnlock(mFragment.getFingerprintPreferenceKey()); } @Test Loading Loading @@ -380,7 +409,7 @@ public class CombinedBiometricProfileSettingsTest { @Test public void testClickFaceUnlock_inMultiWindow_withoutEnrolledFp_showsDialog() { testClickFaceUnlock(true /* isInMultiWindow */, false /*hasEnrolledFace*/); verifyShowsDialogAfterClickingUnlock(); verifyShowsDialogAfterClickingUnlock(mFragment.getFacePreferenceKey()); } @Test Loading Loading @@ -424,8 +453,11 @@ public class CombinedBiometricProfileSettingsTest { } private void verifyNoDialogAfterClickingUnlock(String preferenceKey) { verify(mBiometricSettingsAppPreferenceController).handlePreferenceTreeClick( mPreferenceCaptor.capture()); final BiometricStatusPreferenceController controller = preferenceKey.equals(mFragment.getFacePreferenceKey()) ? mFaceStatusPreferenceController : mFingerprintStatusPreferenceController; verify(controller).handlePreferenceTreeClick(mPreferenceCaptor.capture()); List<Preference> capturedPreferences = mPreferenceCaptor.getAllValues(); assertThat(capturedPreferences).hasSize(1); assertThat(capturedPreferences.get(0).getKey()).isEqualTo(preferenceKey); Loading @@ -433,12 +465,77 @@ public class CombinedBiometricProfileSettingsTest { eq(BiometricsSplitScreenDialog.class.getName())); } private void verifyShowsDialogAfterClickingUnlock() { verify(mBiometricSettingsAppPreferenceController, never()).handlePreferenceTreeClick(any()); private void verifyShowsDialogAfterClickingUnlock(String preferenceKey) { final BiometricStatusPreferenceController controller = preferenceKey.equals(mFragment.getFacePreferenceKey()) ? mFaceStatusPreferenceController : mFingerprintStatusPreferenceController; verify(controller, never()).handlePreferenceTreeClick(any()); verify(mFragmentTransaction).add(any(), eq(BiometricsSplitScreenDialog.class.getName())); } @Test public void testNoCrashIfDetachActivityDuringGeneratingChallengeThroughFaceManager() { doAnswer(invocation -> { final FaceManager.GenerateChallengeCallback callback = invocation.getArgument(1); mFragment.onPause(); mFragment.onStop(); mFragment.onDestroy(); mFragment.onDetach(); doReturn(null).when(mFragment).getActivity(); callback.onGenerateChallengeResult(0, 0, 1L); return null; }).when(mFaceManager).generateChallenge(anyInt(), any()); doThrow(new IllegalStateException("Test")).when(mFragment).requestGatekeeperHat( any(), anyLong(), anyInt(), anyLong()); FragmentManager fragmentManager = mock(FragmentManager.class); // Start fragment mFragment.onAttach(mContext); mFragment.onCreate(null); mFragment.onCreateView(LayoutInflater.from(mContext), mock(ViewGroup.class), Bundle.EMPTY); mFragment.onResume(); // User clicks on "Face Unlock" final Preference preference = new Preference(mContext); preference.setKey(mFragment.getFacePreferenceKey()); mFragment.onPreferenceTreeClick(preference); verify(mFragment, never()).launchChooseOrConfirmLock(); } @Test public void testNoCrashIfDetachActivityDuringGeneratingChallengeThroughFingerprintManager() { doAnswer(invocation -> { final FingerprintManager.GenerateChallengeCallback callback = invocation.getArgument(1); mFragment.onPause(); mFragment.onStop(); mFragment.onDestroy(); mFragment.onDetach(); doReturn(null).when(mFragment).getActivity(); callback.onChallengeGenerated(0, 0, 1L); return null; }).when(mFingerprintManager).generateChallenge(anyInt(), any()); doThrow(new IllegalStateException("Test")).when(mFragment).requestGatekeeperHat( any(), anyLong(), anyInt(), anyLong()); // Start fragment mFragment.onAttach(mContext); mFragment.onCreate(null); mFragment.onCreateView(LayoutInflater.from(mContext), mock(ViewGroup.class), Bundle.EMPTY); mFragment.onResume(); // User clicks on "Fingerprint Unlock" final Preference preference = new Preference(mContext); preference.setKey(mFragment.getFingerprintPreferenceKey()); mFragment.onPreferenceTreeClick(preference); verify(mFragment, never()).launchChooseOrConfirmLock(); } /** * a test fragment that initializes PreferenceScreen for testing. */ Loading Loading @@ -492,7 +589,9 @@ public class CombinedBiometricProfileSettingsTest { @Override protected void launchChooseOrConfirmLock() { // do nothing if (getActivity() == null) { throw new AndroidRuntimeException("TestFailed"); } } } }