From f624d6adf774b5460db63817b7f9f488dc1002b2 Mon Sep 17 00:00:00 2001 From: Joshua McCloskey Date: Tue, 16 Jul 2024 20:36:29 +0000 Subject: [PATCH] Refresh templates when fp removal fails Test: atest Fixes: 339556796 Flag: EXEMPT bugfix Change-Id: I369e37f170a57bc9ced98f9728d06f2072c01263 --- .../fingerprint/FingerprintRemoveSidecar.java | 4 +- .../fingerprint/FingerprintSettings.java | 20 +++++-- .../FingerprintSettingsFragmentTest.java | 52 ++++++++++++++++--- 3 files changed, 64 insertions(+), 12 deletions(-) diff --git a/src/com/android/settings/biometrics/fingerprint/FingerprintRemoveSidecar.java b/src/com/android/settings/biometrics/fingerprint/FingerprintRemoveSidecar.java index 73eccdc4564..2737d3802b5 100644 --- a/src/com/android/settings/biometrics/fingerprint/FingerprintRemoveSidecar.java +++ b/src/com/android/settings/biometrics/fingerprint/FingerprintRemoveSidecar.java @@ -23,6 +23,7 @@ import android.os.Bundle; import android.util.Log; import androidx.annotation.Nullable; +import androidx.annotation.VisibleForTesting; import com.android.settings.core.InstrumentedFragment; @@ -51,7 +52,8 @@ public class FingerprintRemoveSidecar extends InstrumentedFragment { } } - private FingerprintManager.RemovalCallback + @VisibleForTesting + FingerprintManager.RemovalCallback mRemoveCallback = new FingerprintManager.RemovalCallback() { @Override public void onRemovalSucceeded(Fingerprint fingerprint, int remaining) { diff --git a/src/com/android/settings/biometrics/fingerprint/FingerprintSettings.java b/src/com/android/settings/biometrics/fingerprint/FingerprintSettings.java index cb7d617f6ee..9a4e657a219 100644 --- a/src/com/android/settings/biometrics/fingerprint/FingerprintSettings.java +++ b/src/com/android/settings/biometrics/fingerprint/FingerprintSettings.java @@ -226,6 +226,7 @@ public class FingerprintSettings extends SubSettings { private static final int MSG_FINGER_AUTH_FAIL = 1002; private static final int MSG_FINGER_AUTH_ERROR = 1003; private static final int MSG_FINGER_AUTH_HELP = 1004; + private static final int MSG_RELOAD_FINGERPRINT_TEMPLATES = 1005; private static final int CONFIRM_REQUEST = 101; @VisibleForTesting @@ -313,6 +314,8 @@ public class FingerprintSettings extends SubSettings { if (activity != null) { Toast.makeText(activity, errString, Toast.LENGTH_SHORT); } + mHandler.obtainMessage(MSG_RELOAD_FINGERPRINT_TEMPLATES) + .sendToTarget(); updateDialog(); } @@ -331,11 +334,7 @@ public class FingerprintSettings extends SubSettings { switch (msg.what) { case MSG_REFRESH_FINGERPRINT_TEMPLATES: removeFingerprintPreference(msg.arg1); - updateAddPreference(); - if (isSfps()) { - updateFingerprintUnlockCategoryVisibility(); - } - updatePreferences(); + updatePreferencesAfterFingerprintRemoved(); break; case MSG_FINGER_AUTH_SUCCESS: highlightFingerprintItem(msg.arg1); @@ -347,6 +346,9 @@ public class FingerprintSettings extends SubSettings { case MSG_FINGER_AUTH_ERROR: handleError(msg.arg1 /* errMsgId */, (CharSequence) msg.obj /* errStr */); break; + case MSG_RELOAD_FINGERPRINT_TEMPLATES: + updatePreferencesAfterFingerprintRemoved(); + break; case MSG_FINGER_AUTH_HELP: { // Not used } @@ -568,6 +570,7 @@ public class FingerprintSettings extends SubSettings { protected void removeFingerprintPreference(int fingerprintId) { String name = genKey(fingerprintId); + Log.e(TAG, "removeFingerprintPreference : " + fingerprintId); Preference prefToRemove = findPreference(name); if (prefToRemove != null) { if (!getPreferenceScreen().removePreference(prefToRemove)) { @@ -692,6 +695,13 @@ public class FingerprintSettings extends SubSettings { }); } + private void updatePreferencesAfterFingerprintRemoved() { + updateAddPreference(); + if (isSfps()) { + updateFingerprintUnlockCategoryVisibility(); + } + } + private void updateAddPreference() { if (getActivity() == null) { return; // Activity went away diff --git a/tests/robotests/src/com/android/settings/biometrics/fingerprint/FingerprintSettingsFragmentTest.java b/tests/robotests/src/com/android/settings/biometrics/fingerprint/FingerprintSettingsFragmentTest.java index 4ef32237086..a34b6de5335 100644 --- a/tests/robotests/src/com/android/settings/biometrics/fingerprint/FingerprintSettingsFragmentTest.java +++ b/tests/robotests/src/com/android/settings/biometrics/fingerprint/FingerprintSettingsFragmentTest.java @@ -36,6 +36,7 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import static org.robolectric.Shadows.shadowOf; import android.content.Context; import android.content.Intent; @@ -44,11 +45,13 @@ import android.hardware.biometrics.BiometricManager; import android.hardware.biometrics.ComponentInfoInternal; import android.hardware.biometrics.Flags; import android.hardware.biometrics.SensorProperties; +import android.hardware.fingerprint.Fingerprint; import android.hardware.fingerprint.FingerprintManager; import android.hardware.fingerprint.FingerprintSensorProperties; import android.hardware.fingerprint.FingerprintSensorPropertiesInternal; import android.os.Bundle; import android.os.CancellationSignal; +import android.os.Looper; import android.os.UserHandle; import android.platform.test.annotations.EnableFlags; import android.platform.test.flag.junit.SetFlagsRule; @@ -59,6 +62,7 @@ import android.view.ViewGroup; import androidx.fragment.app.FragmentActivity; import androidx.fragment.app.FragmentManager; import androidx.fragment.app.FragmentTransaction; +import androidx.preference.Preference; import androidx.test.core.app.ApplicationProvider; import com.android.settings.password.ChooseLockSettingsHelper; @@ -87,6 +91,7 @@ import org.robolectric.RobolectricTestRunner; import org.robolectric.annotation.Config; import java.util.ArrayList; +import java.util.List; @RunWith(RobolectricTestRunner.class) @Config(shadows = {ShadowSettingsPreferenceFragment.class, ShadowUtils.class, ShadowFragment.class, @@ -120,6 +125,7 @@ public class FingerprintSettingsFragmentTest { FingerprintManager.AuthenticationCallback.class); private FingerprintAuthenticateSidecar mFingerprintAuthenticateSidecar; + private FingerprintRemoveSidecar mFingerprintRemoveSidecar; @Before public void setUp() { @@ -216,7 +222,7 @@ public class FingerprintSettingsFragmentTest { 1, UserHandle.of(GUEST_USER_ID).getIdentifier()); - setUpFragment(false, GUEST_USER_ID, TYPE_POWER_BUTTON); + setUpFragment(false, GUEST_USER_ID, TYPE_POWER_BUTTON, 1); final RestrictedSwitchPreference requireScreenOnToAuthPreference = mFragment.findPreference( KEY_REQUIRE_SCREEN_ON_TO_AUTH); @@ -224,11 +230,15 @@ public class FingerprintSettingsFragmentTest { } private void setUpFragment(boolean showChooseLock) { - setUpFragment(showChooseLock, PRIMARY_USER_ID, TYPE_UDFPS_OPTICAL); + setUpFragment(showChooseLock, PRIMARY_USER_ID, TYPE_UDFPS_OPTICAL, 1); + } + + private void setUpFragment(boolean showChooseLock, int maxFingerprints) { + setUpFragment(showChooseLock, PRIMARY_USER_ID, TYPE_UDFPS_OPTICAL, maxFingerprints); } private void setUpFragment(boolean showChooseLock, int userId, - @FingerprintSensorProperties.SensorType int sensorType) { + @FingerprintSensorProperties.SensorType int sensorType, int maxFingerprints) { ShadowUserManager.getShadow().addProfile(new UserInfo(userId, "", 0)); Intent intent = new Intent(); @@ -250,9 +260,13 @@ public class FingerprintSettingsFragmentTest { doReturn(mFingerprintAuthenticateSidecar).when(fragmentManager).findFragmentByTag( "authenticate_sidecar"); + mFingerprintRemoveSidecar = new FingerprintRemoveSidecar(); + doReturn(mFingerprintRemoveSidecar).when(fragmentManager).findFragmentByTag( + "removal_sidecar"); + doNothing().when(mFragment).startActivityForResult(any(Intent.class), anyInt()); - setSensor(sensorType); + setSensor(sensorType, maxFingerprints); // Start fragment mFragment.onAttach(mContext); @@ -269,12 +283,38 @@ public class FingerprintSettingsFragmentTest { assertThat(mFragment.isVisible()).isTrue(); } - private void setSensor(@FingerprintSensorProperties.SensorType int sensorType) { + @Ignore("b/353726774") + @Test + public void testAddButtonWorksAfterRemovalError() { + final Fingerprint fingerprint = new Fingerprint("Test", 0, 0); + doReturn(List.of(fingerprint)).when(mFingerprintManager).getEnrolledFingerprints(anyInt()); + setUpFragment(false, 5); + shadowOf(Looper.getMainLooper()).idle(); + final Preference addPref = mFragment.findPreference("key_fingerprint_add"); + final FingerprintSettings.FingerprintPreference fpPref = + mFragment.findPreference("key_fingerprint_item_0"); + assertThat(fpPref).isNotNull(); + assertThat(addPref).isNotNull(); + assertThat(addPref.isEnabled()).isTrue(); + + mFingerprintRemoveSidecar.setListener(mFragment.mRemovalListener); + mFragment.deleteFingerPrint(fingerprint); + verify(mFingerprintManager).remove(any(), anyInt(), any()); + assertThat(addPref.isEnabled()).isFalse(); + + mFingerprintRemoveSidecar.mRemoveCallback.onRemovalError(fingerprint, 0, "failure"); + + shadowOf(Looper.getMainLooper()).idle(); + assertThat(addPref.isEnabled()).isTrue(); + } + + private void setSensor(@FingerprintSensorProperties.SensorType int sensorType, + int maxFingerprints) { final ArrayList props = new ArrayList<>(); props.add(new FingerprintSensorPropertiesInternal( 0 /* sensorId */, SensorProperties.STRENGTH_STRONG, - 1 /* maxEnrollmentsPerUser */, + maxFingerprints /* maxEnrollmentsPerUser */, new ArrayList(), sensorType, true /* resetLockoutRequiresHardwareAuthToken */));