Support force fingerprint reenrollment
Add a new fingerprint constant FINGERPRINT_ACQUIRED_RE_ENROLL_FORCED and
rename existing FINGERPRINT_ACQUIRED_RE_ENROLL to
FINGERPRINT_ACQUIRED_RE_ENROLL_OPTIONAL.
When force reenroll is received, only show the positive button in the
dialog.
Bug: 325516143
Test: atest BiometricNotificationDialogFactoryTest
BiometricNotificationServiceTest
Flag: NONE
Change-Id: Ie7c1bb0df144172c5a202fcd74f4b3715b57869b
diff --git a/core/java/android/hardware/biometrics/BiometricFingerprintConstants.java b/core/java/android/hardware/biometrics/BiometricFingerprintConstants.java
index 770448b..fc72db3 100644
--- a/core/java/android/hardware/biometrics/BiometricFingerprintConstants.java
+++ b/core/java/android/hardware/biometrics/BiometricFingerprintConstants.java
@@ -221,7 +221,8 @@
FINGERPRINT_ACQUIRED_IMMOBILE,
FINGERPRINT_ACQUIRED_TOO_BRIGHT,
FINGERPRINT_ACQUIRED_POWER_PRESSED,
- FINGERPRINT_ACQUIRED_RE_ENROLL})
+ FINGERPRINT_ACQUIRED_RE_ENROLL_OPTIONAL,
+ FINGERPRINT_ACQUIRED_RE_ENROLL_FORCED})
@Retention(RetentionPolicy.SOURCE)
@interface FingerprintAcquired {}
@@ -316,7 +317,13 @@
* This message is sent to encourage the user to re-enroll their fingerprints.
* @hide
*/
- int FINGERPRINT_ACQUIRED_RE_ENROLL = 12;
+ int FINGERPRINT_ACQUIRED_RE_ENROLL_OPTIONAL = 12;
+
+ /**
+ * This message is sent to force the user to re-enroll their fingerprints.
+ * @hide
+ */
+ int FINGERPRINT_ACQUIRED_RE_ENROLL_FORCED = 13;
/**
* @hide
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/BiometricNotificationBroadcastReceiver.java b/packages/SystemUI/src/com/android/systemui/biometrics/BiometricNotificationBroadcastReceiver.java
index df27cbb..027f674 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/BiometricNotificationBroadcastReceiver.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/BiometricNotificationBroadcastReceiver.java
@@ -35,6 +35,8 @@
static final String ACTION_SHOW_FINGERPRINT_REENROLL_DIALOG =
"fingerprint_action_show_reenroll_dialog";
+ static final String EXTRA_IS_REENROLL_FORCED = "is_reenroll_forced";
+
private static final String TAG = "BiometricNotificationBroadcastReceiver";
private final Context mContext;
@@ -56,14 +58,16 @@
mNotificationDialogFactory.createReenrollDialog(
mContext.getUserId(),
mContext::startActivity,
- BiometricSourceType.FACE)
+ BiometricSourceType.FACE,
+ false)
.show();
break;
case ACTION_SHOW_FINGERPRINT_REENROLL_DIALOG:
mNotificationDialogFactory.createReenrollDialog(
mContext.getUserId(),
mContext::startActivity,
- BiometricSourceType.FINGERPRINT)
+ BiometricSourceType.FINGERPRINT,
+ intent.getBooleanExtra(EXTRA_IS_REENROLL_FORCED, false))
.show();
break;
default:
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/BiometricNotificationDialogFactory.java b/packages/SystemUI/src/com/android/systemui/biometrics/BiometricNotificationDialogFactory.java
index fd0feef..4ac5a12 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/BiometricNotificationDialogFactory.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/BiometricNotificationDialogFactory.java
@@ -29,13 +29,12 @@
import android.provider.Settings;
import android.util.Log;
-import com.android.systemui.res.R;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Main;
+import com.android.systemui.res.R;
import com.android.systemui.statusbar.phone.SystemUIDialog;
import javax.inject.Inject;
-import javax.inject.Provider;
/**
* Manages the creation of dialogs to be shown for biometric re enroll notifications.
@@ -61,7 +60,8 @@
}
Dialog createReenrollDialog(
- int userId, ActivityStarter activityStarter, BiometricSourceType biometricSourceType) {
+ int userId, ActivityStarter activityStarter, BiometricSourceType biometricSourceType,
+ boolean isReenrollForced) {
SystemUIDialog sysuiDialog = mSystemUIDialogFactory.create();
if (biometricSourceType == BiometricSourceType.FACE) {
sysuiDialog.setTitle(mResources.getString(R.string.face_re_enroll_dialog_title));
@@ -80,8 +80,12 @@
sysuiDialog.setPositiveButton(R.string.biometric_re_enroll_dialog_confirm,
(dialog, which) -> onReenrollDialogConfirm(
userId, biometricSourceType, activityStarter));
- sysuiDialog.setNegativeButton(R.string.biometric_re_enroll_dialog_cancel,
- (dialog, which) -> {});
+ if (!isReenrollForced) {
+ sysuiDialog.setNegativeButton(R.string.biometric_re_enroll_dialog_cancel,
+ (dialog, which) -> {
+ });
+ }
+ sysuiDialog.setCanceledOnTouchOutside(!isReenrollForced);
return sysuiDialog;
}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/BiometricNotificationService.java b/packages/SystemUI/src/com/android/systemui/biometrics/BiometricNotificationService.java
index d6a4cbb..3b49ce2 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/BiometricNotificationService.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/BiometricNotificationService.java
@@ -17,6 +17,7 @@
package com.android.systemui.biometrics;
import static android.app.PendingIntent.FLAG_IMMUTABLE;
+import static android.app.PendingIntent.FLAG_UPDATE_CURRENT;
import static com.android.systemui.biometrics.BiometricNotificationBroadcastReceiver.ACTION_SHOW_FACE_REENROLL_DIALOG;
import static com.android.systemui.biometrics.BiometricNotificationBroadcastReceiver.ACTION_SHOW_FINGERPRINT_REENROLL_DIALOG;
@@ -43,8 +44,8 @@
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.keyguard.KeyguardUpdateMonitorCallback;
import com.android.systemui.CoreStartable;
-import com.android.systemui.res.R;
import com.android.systemui.dagger.SysUISingleton;
+import com.android.systemui.res.R;
import com.android.systemui.statusbar.policy.KeyguardStateController;
import java.util.Optional;
@@ -80,6 +81,8 @@
private boolean mFingerprintNotificationQueued;
private boolean mFingerprintReenrollRequired;
+ private boolean mIsFingerprintReenrollForced;
+
private final KeyguardStateController.Callback mKeyguardStateControllerCallback =
new KeyguardStateController.Callback() {
private boolean mIsShowing = true;
@@ -118,9 +121,11 @@
public void onBiometricHelp(int msgId, String helpString,
BiometricSourceType biometricSourceType) {
if (biometricSourceType == BiometricSourceType.FINGERPRINT
- && mFingerprintReEnrollNotification.isFingerprintReEnrollRequired(
+ && mFingerprintReEnrollNotification.isFingerprintReEnrollRequested(
msgId)) {
mFingerprintReenrollRequired = true;
+ mIsFingerprintReenrollForced =
+ mFingerprintReEnrollNotification.isFingerprintReEnrollForced(msgId);
}
}
};
@@ -191,7 +196,7 @@
final String name = mContext.getString(R.string.face_re_enroll_notification_name);
mHandler.postDelayed(
() -> showNotification(ACTION_SHOW_FACE_REENROLL_DIALOG, title, content, name,
- FACE_NOTIFICATION_ID),
+ FACE_NOTIFICATION_ID, false),
SHOW_NOTIFICATION_DELAY_MS);
}
@@ -204,12 +209,12 @@
final String name = mContext.getString(R.string.fingerprint_re_enroll_notification_name);
mHandler.postDelayed(
() -> showNotification(ACTION_SHOW_FINGERPRINT_REENROLL_DIALOG, title, content,
- name, FINGERPRINT_NOTIFICATION_ID),
+ name, FINGERPRINT_NOTIFICATION_ID, mIsFingerprintReenrollForced),
SHOW_NOTIFICATION_DELAY_MS);
}
private void showNotification(String action, CharSequence title, CharSequence content,
- CharSequence name, int notificationId) {
+ CharSequence name, int notificationId, boolean isReenrollForced) {
if (notificationId == FACE_NOTIFICATION_ID) {
mFaceNotificationQueued = false;
} else if (notificationId == FINGERPRINT_NOTIFICATION_ID) {
@@ -223,8 +228,12 @@
}
final Intent onClickIntent = new Intent(action);
+ onClickIntent.putExtra(BiometricNotificationBroadcastReceiver.EXTRA_IS_REENROLL_FORCED,
+ isReenrollForced);
+
final PendingIntent onClickPendingIntent = PendingIntent.getBroadcastAsUser(mContext,
- 0 /* requestCode */, onClickIntent, FLAG_IMMUTABLE, UserHandle.CURRENT);
+ 0 /* requestCode */, onClickIntent, FLAG_IMMUTABLE | FLAG_UPDATE_CURRENT,
+ UserHandle.CURRENT);
final Notification notification = new Notification.Builder(mContext, CHANNEL_ID)
.setCategory(Notification.CATEGORY_SYSTEM)
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/FingerprintReEnrollNotification.java b/packages/SystemUI/src/com/android/systemui/biometrics/FingerprintReEnrollNotification.java
index 9050f26..5b9ed483 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/FingerprintReEnrollNotification.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/FingerprintReEnrollNotification.java
@@ -23,7 +23,16 @@
*/
public interface FingerprintReEnrollNotification {
//TODO: Remove this class and add a constant in the HAL API instead (b/281841852)
- /** Returns true if msgId corresponds to FINGERPRINT_ACQUIRED_RE_ENROLL. */
- boolean isFingerprintReEnrollRequired(
+ /**
+ * Returns true if msgId corresponds to FINGERPRINT_ACQUIRED_RE_ENROLL_OPTIONAL or
+ * FINGERPRINT_ACQUIRED_RE_ENROLL_FORCED.
+ */
+ boolean isFingerprintReEnrollRequested(
+ @BiometricFingerprintConstants.FingerprintAcquired int msgId);
+
+ /**
+ * Returns true if msgId corresponds to FINGERPRINT_ACQUIRED_RE_ENROLL_FORCED.
+ */
+ boolean isFingerprintReEnrollForced(
@BiometricFingerprintConstants.FingerprintAcquired int msgId);
}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/FingerprintReEnrollNotificationImpl.java b/packages/SystemUI/src/com/android/systemui/biometrics/FingerprintReEnrollNotificationImpl.java
index 1f86bc6..d47e1e6 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/FingerprintReEnrollNotificationImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/FingerprintReEnrollNotificationImpl.java
@@ -23,7 +23,13 @@
*/
public class FingerprintReEnrollNotificationImpl implements FingerprintReEnrollNotification{
@Override
- public boolean isFingerprintReEnrollRequired(int msgId) {
- return msgId == BiometricFingerprintConstants.FINGERPRINT_ACQUIRED_RE_ENROLL;
+ public boolean isFingerprintReEnrollRequested(int msgId) {
+ return msgId == BiometricFingerprintConstants.FINGERPRINT_ACQUIRED_RE_ENROLL_OPTIONAL
+ || msgId == BiometricFingerprintConstants.FINGERPRINT_ACQUIRED_RE_ENROLL_FORCED;
+ }
+
+ @Override
+ public boolean isFingerprintReEnrollForced(int msgId) {
+ return msgId == BiometricFingerprintConstants.FINGERPRINT_ACQUIRED_RE_ENROLL_FORCED;
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/BiometricNotificationDialogFactoryTest.java b/packages/SystemUI/tests/src/com/android/systemui/biometrics/BiometricNotificationDialogFactoryTest.java
index 8c8544c..d2c6957 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/BiometricNotificationDialogFactoryTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/BiometricNotificationDialogFactoryTest.java
@@ -17,6 +17,7 @@
package com.android.systemui.biometrics;
import static com.google.common.truth.Truth.assertThat;
+
import static org.junit.Assume.assumeTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
@@ -90,7 +91,8 @@
assumeTrue(getContext().getPackageManager()
.hasSystemFeature(PackageManager.FEATURE_FINGERPRINT));
- mDialogFactory.createReenrollDialog(0, mActivityStarter, BiometricSourceType.FINGERPRINT);
+ mDialogFactory.createReenrollDialog(0, mActivityStarter, BiometricSourceType.FINGERPRINT,
+ false);
verify(mDialog).setPositiveButton(anyInt(), mOnClickListenerArgumentCaptor.capture());
@@ -115,7 +117,8 @@
assumeTrue(getContext().getPackageManager()
.hasSystemFeature(PackageManager.FEATURE_FINGERPRINT));
- mDialogFactory.createReenrollDialog(0, mActivityStarter, BiometricSourceType.FINGERPRINT);
+ mDialogFactory.createReenrollDialog(0, mActivityStarter, BiometricSourceType.FINGERPRINT,
+ false);
verify(mDialog).setPositiveButton(anyInt(), mOnClickListenerArgumentCaptor.capture());
@@ -134,11 +137,25 @@
}
@Test
+ public void testFingerprintReEnrollDialog_forced() {
+ assumeTrue(getContext().getPackageManager()
+ .hasSystemFeature(PackageManager.FEATURE_FINGERPRINT));
+
+ mDialogFactory.createReenrollDialog(0, mActivityStarter, BiometricSourceType.FINGERPRINT,
+ true);
+
+ verify(mDialog).setPositiveButton(anyInt(), mOnClickListenerArgumentCaptor.capture());
+
+ verify(mDialog, never()).setNegativeButton(anyInt(), any());
+ }
+
+ @Test
public void testFaceReEnrollDialog_onRemovalSucceeded() {
assumeTrue(getContext().getPackageManager()
.hasSystemFeature(PackageManager.FEATURE_FACE));
- mDialogFactory.createReenrollDialog(0, mActivityStarter, BiometricSourceType.FACE);
+ mDialogFactory.createReenrollDialog(0, mActivityStarter, BiometricSourceType.FACE,
+ false);
verify(mDialog).setPositiveButton(anyInt(), mOnClickListenerArgumentCaptor.capture());
@@ -163,7 +180,8 @@
assumeTrue(getContext().getPackageManager()
.hasSystemFeature(PackageManager.FEATURE_FACE));
- mDialogFactory.createReenrollDialog(0, mActivityStarter, BiometricSourceType.FACE);
+ mDialogFactory.createReenrollDialog(0, mActivityStarter, BiometricSourceType.FACE,
+ false);
verify(mDialog).setPositiveButton(anyInt(), mOnClickListenerArgumentCaptor.capture());
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/BiometricNotificationServiceTest.java b/packages/SystemUI/tests/src/com/android/systemui/biometrics/BiometricNotificationServiceTest.java
index c6771b2..a279d3e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/BiometricNotificationServiceTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/BiometricNotificationServiceTest.java
@@ -18,7 +18,9 @@
import static com.android.systemui.biometrics.BiometricNotificationBroadcastReceiver.ACTION_SHOW_FACE_REENROLL_DIALOG;
import static com.android.systemui.biometrics.BiometricNotificationBroadcastReceiver.ACTION_SHOW_FINGERPRINT_REENROLL_DIALOG;
+
import static com.google.common.truth.Truth.assertThat;
+
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.never;
@@ -98,7 +100,7 @@
public void setUp() {
when(mFingerprintReEnrollNotificationOptional.orElse(any()))
.thenReturn(mFingerprintReEnrollNotification);
- when(mFingerprintReEnrollNotification.isFingerprintReEnrollRequired(
+ when(mFingerprintReEnrollNotification.isFingerprintReEnrollRequested(
FINGERPRINT_ACQUIRED_RE_ENROLL)).thenReturn(true);
mLooper = TestableLooper.get(this);
@@ -140,8 +142,10 @@
}
@Test
- public void testShowFingerprintReEnrollNotification_onAcquiredReEnroll() {
+ public void testShowFingerprintReEnrollNotification_onAcquiredReEnroll_Optional() {
when(mKeyguardStateController.isShowing()).thenReturn(false);
+ when(mFingerprintReEnrollNotification.isFingerprintReEnrollForced(
+ FINGERPRINT_ACQUIRED_RE_ENROLL)).thenReturn(false);
mKeyguardUpdateMonitorCallback.onBiometricHelp(
FINGERPRINT_ACQUIRED_RE_ENROLL,
@@ -160,6 +164,35 @@
assertThat(fingerprintNotification.contentIntent.getIntent().getAction())
.isEqualTo(ACTION_SHOW_FINGERPRINT_REENROLL_DIALOG);
+ assertThat(fingerprintNotification.contentIntent.getIntent().getBooleanExtra(
+ BiometricNotificationBroadcastReceiver.EXTRA_IS_REENROLL_FORCED, false)).isFalse();
+ }
+
+ @Test
+ public void testShowFingerprintReEnrollNotification_onAcquiredReEnroll_force() {
+ when(mKeyguardStateController.isShowing()).thenReturn(false);
+ when(mFingerprintReEnrollNotification.isFingerprintReEnrollForced(
+ FINGERPRINT_ACQUIRED_RE_ENROLL)).thenReturn(true);
+
+ mKeyguardUpdateMonitorCallback.onBiometricHelp(
+ FINGERPRINT_ACQUIRED_RE_ENROLL,
+ "Testing Fingerprint Re-enrollment" /* errString */,
+ BiometricSourceType.FINGERPRINT
+ );
+ mKeyguardStateControllerCallback.onKeyguardShowingChanged();
+
+ mLooper.moveTimeForward(SHOW_NOTIFICATION_DELAY_MS);
+ mLooper.processAllMessages();
+
+ verify(mNotificationManager).notifyAsUser(eq(TAG), eq(FINGERPRINT_NOTIFICATION_ID),
+ mNotificationArgumentCaptor.capture(), any());
+
+ Notification fingerprintNotification = mNotificationArgumentCaptor.getValue();
+
+ assertThat(fingerprintNotification.contentIntent.getIntent().getAction())
+ .isEqualTo(ACTION_SHOW_FINGERPRINT_REENROLL_DIALOG);
+ assertThat(fingerprintNotification.contentIntent.getIntent().getBooleanExtra(
+ BiometricNotificationBroadcastReceiver.EXTRA_IS_REENROLL_FORCED, false)).isTrue();
}
@Test
public void testShowFaceReEnrollNotification_onErrorReEnroll() {