[DO NOT MERGE] Remove duplicate face re-enroll notification

Cancel re-enroll notification when face is removed.

Test: atest BiometricsNotificationService
Fixes: 286759227
Fixes: 289074587
Change-Id: I27d6bb843b01a844e44d9445bef4e24c38a2df56
(cherry picked from commit 03b111a261)
This commit is contained in:
Diya Bera
2023-06-15 15:42:17 -07:00
parent 0bdacdfcb6
commit b803e95bca
3 changed files with 111 additions and 14 deletions

View File

@@ -21,6 +21,8 @@ import static android.app.PendingIntent.FLAG_IMMUTABLE;
import static com.android.systemui.biometrics.BiometricNotificationBroadcastReceiver.ACTION_SHOW_FACE_REENROLL_DIALOG; 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.android.systemui.biometrics.BiometricNotificationBroadcastReceiver.ACTION_SHOW_FINGERPRINT_REENROLL_DIALOG;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.Notification; import android.app.Notification;
import android.app.NotificationChannel; import android.app.NotificationChannel;
import android.app.NotificationManager; import android.app.NotificationManager;
@@ -30,6 +32,9 @@ import android.content.Intent;
import android.content.IntentFilter; import android.content.IntentFilter;
import android.hardware.biometrics.BiometricFaceConstants; import android.hardware.biometrics.BiometricFaceConstants;
import android.hardware.biometrics.BiometricSourceType; import android.hardware.biometrics.BiometricSourceType;
import android.hardware.biometrics.BiometricStateListener;
import android.hardware.face.FaceManager;
import android.hardware.fingerprint.FingerprintManager;
import android.os.Handler; import android.os.Handler;
import android.os.UserHandle; import android.os.UserHandle;
import android.provider.Settings; import android.provider.Settings;
@@ -42,7 +47,6 @@ import com.android.systemui.R;
import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.statusbar.policy.KeyguardStateController; import com.android.systemui.statusbar.policy.KeyguardStateController;
import java.util.Optional; import java.util.Optional;
import javax.inject.Inject; import javax.inject.Inject;
@@ -69,6 +73,8 @@ public class BiometricNotificationService implements CoreStartable {
private final NotificationManager mNotificationManager; private final NotificationManager mNotificationManager;
private final BiometricNotificationBroadcastReceiver mBroadcastReceiver; private final BiometricNotificationBroadcastReceiver mBroadcastReceiver;
private final FingerprintReEnrollNotification mFingerprintReEnrollNotification; private final FingerprintReEnrollNotification mFingerprintReEnrollNotification;
private final FingerprintManager mFingerprintManager;
private final FaceManager mFaceManager;
private NotificationChannel mNotificationChannel; private NotificationChannel mNotificationChannel;
private boolean mFaceNotificationQueued; private boolean mFaceNotificationQueued;
private boolean mFingerprintNotificationQueued; private boolean mFingerprintNotificationQueued;
@@ -119,14 +125,29 @@ public class BiometricNotificationService implements CoreStartable {
} }
}; };
private final BiometricStateListener mFaceStateListener = new BiometricStateListener() {
@Override
public void onEnrollmentsChanged(int userId, int sensorId, boolean hasEnrollments) {
mNotificationManager.cancelAsUser(TAG, FACE_NOTIFICATION_ID, UserHandle.CURRENT);
}
};
private final BiometricStateListener mFingerprintStateListener = new BiometricStateListener() {
@Override
public void onEnrollmentsChanged(int userId, int sensorId, boolean hasEnrollments) {
mNotificationManager.cancelAsUser(TAG, FINGERPRINT_NOTIFICATION_ID, UserHandle.CURRENT);
}
};
@Inject @Inject
public BiometricNotificationService(Context context, public BiometricNotificationService(@NonNull Context context,
KeyguardUpdateMonitor keyguardUpdateMonitor, @NonNull KeyguardUpdateMonitor keyguardUpdateMonitor,
KeyguardStateController keyguardStateController, @NonNull KeyguardStateController keyguardStateController,
Handler handler, NotificationManager notificationManager, @NonNull Handler handler, @NonNull NotificationManager notificationManager,
BiometricNotificationBroadcastReceiver biometricNotificationBroadcastReceiver, @NonNull BiometricNotificationBroadcastReceiver biometricNotificationBroadcastReceiver,
Optional<FingerprintReEnrollNotification> fingerprintReEnrollNotification) { @NonNull Optional<FingerprintReEnrollNotification> fingerprintReEnrollNotification,
@Nullable FingerprintManager fingerprintManager,
@Nullable FaceManager faceManager) {
mContext = context; mContext = context;
mKeyguardUpdateMonitor = keyguardUpdateMonitor; mKeyguardUpdateMonitor = keyguardUpdateMonitor;
mKeyguardStateController = keyguardStateController; mKeyguardStateController = keyguardStateController;
@@ -135,6 +156,8 @@ public class BiometricNotificationService implements CoreStartable {
mBroadcastReceiver = biometricNotificationBroadcastReceiver; mBroadcastReceiver = biometricNotificationBroadcastReceiver;
mFingerprintReEnrollNotification = fingerprintReEnrollNotification.orElse( mFingerprintReEnrollNotification = fingerprintReEnrollNotification.orElse(
new FingerprintReEnrollNotificationImpl()); new FingerprintReEnrollNotificationImpl());
mFingerprintManager = fingerprintManager;
mFaceManager = faceManager;
} }
@Override @Override
@@ -148,9 +171,16 @@ public class BiometricNotificationService implements CoreStartable {
intentFilter.addAction(ACTION_SHOW_FACE_REENROLL_DIALOG); intentFilter.addAction(ACTION_SHOW_FACE_REENROLL_DIALOG);
mContext.registerReceiver(mBroadcastReceiver, intentFilter, mContext.registerReceiver(mBroadcastReceiver, intentFilter,
Context.RECEIVER_EXPORTED_UNAUDITED); Context.RECEIVER_EXPORTED_UNAUDITED);
if (mFingerprintManager != null) {
mFingerprintManager.registerBiometricStateListener(mFingerprintStateListener);
}
if (mFaceManager != null) {
mFaceManager.registerBiometricStateListener(mFaceStateListener);
}
} }
private void queueFaceReenrollNotification() { private void queueFaceReenrollNotification() {
Log.d(TAG, "Face re-enroll notification queued.");
mFaceNotificationQueued = true; mFaceNotificationQueued = true;
final String title = mContext.getString(R.string.face_re_enroll_notification_title); final String title = mContext.getString(R.string.face_re_enroll_notification_title);
final String content = mContext.getString( final String content = mContext.getString(
@@ -163,6 +193,7 @@ public class BiometricNotificationService implements CoreStartable {
} }
private void queueFingerprintReenrollNotification() { private void queueFingerprintReenrollNotification() {
Log.d(TAG, "Fingerprint re-enroll notification queued.");
mFingerprintNotificationQueued = true; mFingerprintNotificationQueued = true;
final String title = mContext.getString(R.string.fingerprint_re_enroll_notification_title); final String title = mContext.getString(R.string.fingerprint_re_enroll_notification_title);
final String content = mContext.getString( final String content = mContext.getString(

View File

@@ -30,7 +30,11 @@ import android.app.Notification;
import android.app.NotificationManager; import android.app.NotificationManager;
import android.hardware.biometrics.BiometricFaceConstants; import android.hardware.biometrics.BiometricFaceConstants;
import android.hardware.biometrics.BiometricSourceType; import android.hardware.biometrics.BiometricSourceType;
import android.hardware.biometrics.BiometricStateListener;
import android.hardware.face.FaceManager;
import android.hardware.fingerprint.FingerprintManager;
import android.os.Handler; import android.os.Handler;
import android.os.UserHandle;
import android.testing.AndroidTestingRunner; import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper; import android.testing.TestableLooper;
@@ -69,6 +73,10 @@ public class BiometricNotificationServiceTest extends SysuiTestCase {
Optional<FingerprintReEnrollNotification> mFingerprintReEnrollNotificationOptional; Optional<FingerprintReEnrollNotification> mFingerprintReEnrollNotificationOptional;
@Mock @Mock
FingerprintReEnrollNotification mFingerprintReEnrollNotification; FingerprintReEnrollNotification mFingerprintReEnrollNotification;
@Mock
FingerprintManager mFingerprintManager;
@Mock
FaceManager mFaceManager;
private static final String TAG = "BiometricNotificationService"; private static final String TAG = "BiometricNotificationService";
private static final int FACE_NOTIFICATION_ID = 1; private static final int FACE_NOTIFICATION_ID = 1;
@@ -81,6 +89,8 @@ public class BiometricNotificationServiceTest extends SysuiTestCase {
private TestableLooper mLooper; private TestableLooper mLooper;
private KeyguardUpdateMonitorCallback mKeyguardUpdateMonitorCallback; private KeyguardUpdateMonitorCallback mKeyguardUpdateMonitorCallback;
private KeyguardStateController.Callback mKeyguardStateControllerCallback; private KeyguardStateController.Callback mKeyguardStateControllerCallback;
private BiometricStateListener mFaceStateListener;
private BiometricStateListener mFingerprintStateListener;
@Before @Before
public void setUp() { public void setUp() {
@@ -99,25 +109,37 @@ public class BiometricNotificationServiceTest extends SysuiTestCase {
mKeyguardUpdateMonitor, mKeyguardStateController, handler, mKeyguardUpdateMonitor, mKeyguardStateController, handler,
mNotificationManager, mNotificationManager,
broadcastReceiver, broadcastReceiver,
mFingerprintReEnrollNotificationOptional); mFingerprintReEnrollNotificationOptional,
mFingerprintManager,
mFaceManager);
biometricNotificationService.start(); biometricNotificationService.start();
ArgumentCaptor<KeyguardUpdateMonitorCallback> updateMonitorCallbackArgumentCaptor = ArgumentCaptor<KeyguardUpdateMonitorCallback> updateMonitorCallbackArgumentCaptor =
ArgumentCaptor.forClass(KeyguardUpdateMonitorCallback.class); ArgumentCaptor.forClass(KeyguardUpdateMonitorCallback.class);
ArgumentCaptor<KeyguardStateController.Callback> stateControllerCallbackArgumentCaptor = ArgumentCaptor<KeyguardStateController.Callback> stateControllerCallbackArgumentCaptor =
ArgumentCaptor.forClass(KeyguardStateController.Callback.class); ArgumentCaptor.forClass(KeyguardStateController.Callback.class);
ArgumentCaptor<BiometricStateListener> faceStateListenerArgumentCaptor =
ArgumentCaptor.forClass(BiometricStateListener.class);
ArgumentCaptor<BiometricStateListener> fingerprintStateListenerArgumentCaptor =
ArgumentCaptor.forClass(BiometricStateListener.class);
verify(mKeyguardUpdateMonitor).registerCallback( verify(mKeyguardUpdateMonitor).registerCallback(
updateMonitorCallbackArgumentCaptor.capture()); updateMonitorCallbackArgumentCaptor.capture());
verify(mKeyguardStateController).addCallback( verify(mKeyguardStateController).addCallback(
stateControllerCallbackArgumentCaptor.capture()); stateControllerCallbackArgumentCaptor.capture());
verify(mFaceManager).registerBiometricStateListener(
faceStateListenerArgumentCaptor.capture());
verify(mFingerprintManager).registerBiometricStateListener(
fingerprintStateListenerArgumentCaptor.capture());
mFaceStateListener = faceStateListenerArgumentCaptor.getValue();
mFingerprintStateListener = fingerprintStateListenerArgumentCaptor.getValue();
mKeyguardUpdateMonitorCallback = updateMonitorCallbackArgumentCaptor.getValue(); mKeyguardUpdateMonitorCallback = updateMonitorCallbackArgumentCaptor.getValue();
mKeyguardStateControllerCallback = stateControllerCallbackArgumentCaptor.getValue(); mKeyguardStateControllerCallback = stateControllerCallbackArgumentCaptor.getValue();
} }
@Test @Test
public void testShowFingerprintReEnrollNotification() { public void testShowFingerprintReEnrollNotification_onAcquiredReEnroll() {
when(mKeyguardStateController.isShowing()).thenReturn(false); when(mKeyguardStateController.isShowing()).thenReturn(false);
mKeyguardUpdateMonitorCallback.onBiometricHelp( mKeyguardUpdateMonitorCallback.onBiometricHelp(
@@ -139,7 +161,7 @@ public class BiometricNotificationServiceTest extends SysuiTestCase {
.isEqualTo(ACTION_SHOW_FINGERPRINT_REENROLL_DIALOG); .isEqualTo(ACTION_SHOW_FINGERPRINT_REENROLL_DIALOG);
} }
@Test @Test
public void testShowFaceReEnrollNotification() { public void testShowFaceReEnrollNotification_onErrorReEnroll() {
when(mKeyguardStateController.isShowing()).thenReturn(false); when(mKeyguardStateController.isShowing()).thenReturn(false);
mKeyguardUpdateMonitorCallback.onBiometricError( mKeyguardUpdateMonitorCallback.onBiometricError(
@@ -161,4 +183,52 @@ public class BiometricNotificationServiceTest extends SysuiTestCase {
.isEqualTo(ACTION_SHOW_FACE_REENROLL_DIALOG); .isEqualTo(ACTION_SHOW_FACE_REENROLL_DIALOG);
} }
@Test
public void testCancelReEnrollmentNotification_onFaceEnrollmentStateChange() {
when(mKeyguardStateController.isShowing()).thenReturn(false);
mKeyguardUpdateMonitorCallback.onBiometricError(
BiometricFaceConstants.BIOMETRIC_ERROR_RE_ENROLL,
"Testing Face Re-enrollment" /* errString */,
BiometricSourceType.FACE
);
mKeyguardStateControllerCallback.onKeyguardShowingChanged();
mLooper.moveTimeForward(SHOW_NOTIFICATION_DELAY_MS);
mLooper.processAllMessages();
verify(mNotificationManager).notifyAsUser(eq(TAG), eq(FACE_NOTIFICATION_ID),
mNotificationArgumentCaptor.capture(), any());
mFaceStateListener.onEnrollmentsChanged(0 /* userId */, 0 /* sensorId */,
false /* hasEnrollments */);
verify(mNotificationManager).cancelAsUser(eq(TAG), eq(FACE_NOTIFICATION_ID),
eq(UserHandle.CURRENT));
}
@Test
public void testCancelReEnrollmentNotification_onFingerprintEnrollmentStateChange() {
when(mKeyguardStateController.isShowing()).thenReturn(false);
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());
mFingerprintStateListener.onEnrollmentsChanged(0 /* userId */, 0 /* sensorId */,
false /* hasEnrollments */);
verify(mNotificationManager).cancelAsUser(eq(TAG), eq(FINGERPRINT_NOTIFICATION_ID),
eq(UserHandle.CURRENT));
}
} }

View File

@@ -43,7 +43,6 @@ import com.android.server.biometrics.log.BiometricLogger;
import com.android.server.biometrics.log.OperationContextExt; import com.android.server.biometrics.log.OperationContextExt;
import com.android.server.biometrics.sensors.AuthSessionCoordinator; import com.android.server.biometrics.sensors.AuthSessionCoordinator;
import com.android.server.biometrics.sensors.AuthenticationClient; import com.android.server.biometrics.sensors.AuthenticationClient;
import com.android.server.biometrics.sensors.BiometricNotificationUtils;
import com.android.server.biometrics.sensors.ClientMonitorCallback; import com.android.server.biometrics.sensors.ClientMonitorCallback;
import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter; import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter;
import com.android.server.biometrics.sensors.ClientMonitorCompositeCallback; import com.android.server.biometrics.sensors.ClientMonitorCompositeCallback;
@@ -242,9 +241,6 @@ class FaceAuthenticationClient extends AuthenticationClient<AidlSession, FaceAut
vendorCode, vendorCode,
getTargetUserId())); getTargetUserId()));
if (error == BiometricConstants.BIOMETRIC_ERROR_RE_ENROLL) {
BiometricNotificationUtils.showReEnrollmentNotification(getContext());
}
super.onError(error, vendorCode); super.onError(error, vendorCode);
} }