From 7b6dd6a64c80cd7cc6932f41c42ee5133b96d037 Mon Sep 17 00:00:00 2001 From: Kevin Chyn Date: Tue, 23 Feb 2021 13:58:59 -0800 Subject: [PATCH] Add re-enrollment notification for face AIDL 1) Move re-enrollment logic to its own class 2) Show / clear the notification when appropriate for face AIDL Fixes: 180652977 Test: manual Change-Id: I85b386be132974cda6e6e973b244f3cb8300c291 --- .../biometrics/BiometricConstants.java | 6 ++ .../biometrics/BiometricFaceConstants.java | 6 ++ .../BiometricFingerprintConstants.java | 6 ++ .../android/hardware/face/FaceManager.java | 3 + .../face/ReEnrollNotificationUtils.java | 82 +++++++++++++++++++ .../face/aidl/FaceAuthenticationClient.java | 4 + .../sensors/face/aidl/FaceEnrollClient.java | 8 ++ .../biometrics/sensors/face/hidl/Face10.java | 9 +- .../face/hidl/FaceAuthenticationClient.java | 46 +---------- 9 files changed, 120 insertions(+), 50 deletions(-) create mode 100644 services/core/java/com/android/server/biometrics/sensors/face/ReEnrollNotificationUtils.java diff --git a/core/java/android/hardware/biometrics/BiometricConstants.java b/core/java/android/hardware/biometrics/BiometricConstants.java index 76d50bdf414cc..43ef33e1f420c 100644 --- a/core/java/android/hardware/biometrics/BiometricConstants.java +++ b/core/java/android/hardware/biometrics/BiometricConstants.java @@ -144,6 +144,12 @@ public interface BiometricConstants { */ int BIOMETRIC_ERROR_SECURITY_UPDATE_REQUIRED = 15; + /** + * Authentication cannot proceed because re-enrollment is required. + * @hide + */ + int BIOMETRIC_ERROR_RE_ENROLL = 16; + /** * This constant is only used by SystemUI. It notifies SystemUI that authentication was paused * because the authentication attempt was unsuccessful. diff --git a/core/java/android/hardware/biometrics/BiometricFaceConstants.java b/core/java/android/hardware/biometrics/BiometricFaceConstants.java index eafcf529de62a..4385b1dac7a0a 100644 --- a/core/java/android/hardware/biometrics/BiometricFaceConstants.java +++ b/core/java/android/hardware/biometrics/BiometricFaceConstants.java @@ -152,6 +152,12 @@ public interface BiometricFaceConstants { */ int BIOMETRIC_ERROR_SECURITY_UPDATE_REQUIRED = 15; + /** + * Authentication cannot proceed because re-enrollment is required. + * @hide + */ + int BIOMETRIC_ERROR_RE_ENROLL = 16; + /** * @hide */ diff --git a/core/java/android/hardware/biometrics/BiometricFingerprintConstants.java b/core/java/android/hardware/biometrics/BiometricFingerprintConstants.java index 01f0e71a7c33a..30e24d2ec8db2 100644 --- a/core/java/android/hardware/biometrics/BiometricFingerprintConstants.java +++ b/core/java/android/hardware/biometrics/BiometricFingerprintConstants.java @@ -165,6 +165,12 @@ public interface BiometricFingerprintConstants { */ public static final int BIOMETRIC_ERROR_SECURITY_UPDATE_REQUIRED = 15; + /** + * Authentication cannot proceed because re-enrollment is required. + * @hide + */ + int BIOMETRIC_ERROR_RE_ENROLL = 16; + /** * @hide */ diff --git a/core/java/android/hardware/face/FaceManager.java b/core/java/android/hardware/face/FaceManager.java index 886a8c1fdae57..22e310199b970 100644 --- a/core/java/android/hardware/face/FaceManager.java +++ b/core/java/android/hardware/face/FaceManager.java @@ -820,6 +820,9 @@ public class FaceManager implements BiometricAuthenticator, BiometricFaceConstan case BIOMETRIC_ERROR_SECURITY_UPDATE_REQUIRED: return context.getString( com.android.internal.R.string.face_error_security_update_required); + case BIOMETRIC_ERROR_RE_ENROLL: + return context.getString( + com.android.internal.R.string.face_recalibrate_notification_content); case FACE_ERROR_VENDOR: { String[] msgArray = context.getResources().getStringArray( com.android.internal.R.array.face_error_vendor); diff --git a/services/core/java/com/android/server/biometrics/sensors/face/ReEnrollNotificationUtils.java b/services/core/java/com/android/server/biometrics/sensors/face/ReEnrollNotificationUtils.java new file mode 100644 index 0000000000000..f35a5208f6ed5 --- /dev/null +++ b/services/core/java/com/android/server/biometrics/sensors/face/ReEnrollNotificationUtils.java @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.biometrics.sensors.face; + +import android.annotation.NonNull; +import android.app.Notification; +import android.app.NotificationChannel; +import android.app.NotificationManager; +import android.app.PendingIntent; +import android.content.Context; +import android.content.Intent; +import android.os.UserHandle; + +import com.android.internal.R; + +public class ReEnrollNotificationUtils { + + private static final String NOTIFICATION_TAG = "FaceService"; + private static final int NOTIFICATION_ID = 1; + + public static void showReEnrollmentNotification(@NonNull Context context) { + final NotificationManager notificationManager = + context.getSystemService(NotificationManager.class); + + final String name = + context.getString(R.string.face_recalibrate_notification_name); + final String title = + context.getString(R.string.face_recalibrate_notification_title); + final String content = + context.getString(R.string.face_recalibrate_notification_content); + + final Intent intent = new Intent("android.settings.FACE_SETTINGS"); + intent.setPackage("com.android.settings"); + + final PendingIntent pendingIntent = PendingIntent.getActivityAsUser(context, + 0 /* requestCode */, intent, PendingIntent.FLAG_IMMUTABLE /* flags */, + null /* options */, UserHandle.CURRENT); + + final String channelName = "FaceEnrollNotificationChannel"; + + final NotificationChannel channel = new NotificationChannel(channelName, name, + NotificationManager.IMPORTANCE_HIGH); + final Notification notification = new Notification.Builder(context, channelName) + .setSmallIcon(R.drawable.ic_lock) + .setContentTitle(title) + .setContentText(content) + .setSubText(name) + .setOnlyAlertOnce(true) + .setLocalOnly(true) + .setAutoCancel(true) + .setCategory(Notification.CATEGORY_SYSTEM) + .setContentIntent(pendingIntent) + .setVisibility(Notification.VISIBILITY_SECRET) + .build(); + + notificationManager.createNotificationChannel(channel); + notificationManager.notifyAsUser(NOTIFICATION_TAG, + NOTIFICATION_ID, notification, + UserHandle.CURRENT); + } + + public static void cancelNotification(@NonNull Context context) { + final NotificationManager notificationManager = + context.getSystemService(NotificationManager.class); + notificationManager.cancelAsUser(NOTIFICATION_TAG, NOTIFICATION_ID, UserHandle.CURRENT); + } + +} diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClient.java index 8f554028ebfd6..089cf1e4cee87 100644 --- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClient.java +++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClient.java @@ -41,6 +41,7 @@ import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter; import com.android.server.biometrics.sensors.LockoutCache; import com.android.server.biometrics.sensors.LockoutConsumer; import com.android.server.biometrics.sensors.LockoutTracker; +import com.android.server.biometrics.sensors.face.ReEnrollNotificationUtils; import com.android.server.biometrics.sensors.face.UsageStats; import java.util.ArrayList; @@ -163,6 +164,9 @@ class FaceAuthenticationClient extends AuthenticationClient implements vibrateError(); } break; + case BiometricConstants.BIOMETRIC_ERROR_RE_ENROLL: + ReEnrollNotificationUtils.showReEnrollmentNotification(getContext()); + break; default: break; } diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceEnrollClient.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceEnrollClient.java index 898d81b0c8c46..0eb51fdba1591 100644 --- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceEnrollClient.java +++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceEnrollClient.java @@ -41,6 +41,7 @@ import com.android.server.biometrics.sensors.BiometricUtils; import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter; import com.android.server.biometrics.sensors.EnrollClient; import com.android.server.biometrics.sensors.face.FaceUtils; +import com.android.server.biometrics.sensors.face.ReEnrollNotificationUtils; import java.io.IOException; import java.util.ArrayList; @@ -84,6 +85,13 @@ public class FaceEnrollClient extends EnrollClient { } } + @Override + public void start(@NonNull Callback callback) { + super.start(callback); + + ReEnrollNotificationUtils.cancelNotification(getContext()); + } + @Override public void destroy() { try { diff --git a/services/core/java/com/android/server/biometrics/sensors/face/hidl/Face10.java b/services/core/java/com/android/server/biometrics/sensors/face/hidl/Face10.java index e46661a5e985f..66eeb061db540 100644 --- a/services/core/java/com/android/server/biometrics/sensors/face/hidl/Face10.java +++ b/services/core/java/com/android/server/biometrics/sensors/face/hidl/Face10.java @@ -19,7 +19,6 @@ package com.android.server.biometrics.sensors.face.hidl; import android.annotation.NonNull; import android.annotation.Nullable; import android.app.ActivityManager; -import android.app.NotificationManager; import android.app.SynchronousUserSwitchObserver; import android.app.UserSwitchObserver; import android.content.Context; @@ -70,6 +69,7 @@ import com.android.server.biometrics.sensors.PerformanceTracker; import com.android.server.biometrics.sensors.RemovalConsumer; import com.android.server.biometrics.sensors.face.FaceUtils; import com.android.server.biometrics.sensors.face.LockoutHalImpl; +import com.android.server.biometrics.sensors.face.ReEnrollNotificationUtils; import com.android.server.biometrics.sensors.face.ServiceProvider; import com.android.server.biometrics.sensors.face.UsageStats; @@ -95,8 +95,6 @@ public class Face10 implements IHwBinder.DeathRecipient, ServiceProvider { private static final String TAG = "Face10"; private static final int ENROLL_TIMEOUT_SEC = 75; - static final String NOTIFICATION_TAG = "FaceService"; - static final int NOTIFICATION_ID = 1; private boolean mTestHalEnabled; @@ -108,7 +106,6 @@ public class Face10 implements IHwBinder.DeathRecipient, ServiceProvider { @NonNull private final LockoutResetDispatcher mLockoutResetDispatcher; @NonNull private final LockoutHalImpl mLockoutTracker; @NonNull private final UsageStats mUsageStats; - @NonNull private final NotificationManager mNotificationManager; @NonNull private final Map mAuthenticatorIds; @Nullable private IBiometricsFace mDaemon; @NonNull private final HalResultController mHalResultController; @@ -342,7 +339,6 @@ public class Face10 implements IHwBinder.DeathRecipient, ServiceProvider { mUsageStats = new UsageStats(context); mAuthenticatorIds = new HashMap<>(); mLazyDaemon = Face10.this::getDaemon; - mNotificationManager = mContext.getSystemService(NotificationManager.class); mLockoutTracker = new LockoutHalImpl(); mLockoutResetDispatcher = lockoutResetDispatcher; mHalResultController = new HalResultController(sensorId, context, mHandler, mScheduler, @@ -606,8 +602,7 @@ public class Face10 implements IHwBinder.DeathRecipient, ServiceProvider { mHandler.post(() -> { scheduleUpdateActiveUserWithoutHandler(userId); - mNotificationManager.cancelAsUser(NOTIFICATION_TAG, NOTIFICATION_ID, - UserHandle.CURRENT); + ReEnrollNotificationUtils.cancelNotification(mContext); final FaceEnrollClient client = new FaceEnrollClient(mContext, mLazyDaemon, token, new ClientMonitorCallbackConverter(receiver), userId, hardwareAuthToken, diff --git a/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceAuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceAuthenticationClient.java index a4b3ac57a4dfc..3ca51d32797ef 100644 --- a/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceAuthenticationClient.java +++ b/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceAuthenticationClient.java @@ -17,12 +17,7 @@ package com.android.server.biometrics.sensors.face.hidl; import android.annotation.NonNull; -import android.app.Notification; -import android.app.NotificationChannel; -import android.app.NotificationManager; -import android.app.PendingIntent; import android.content.Context; -import android.content.Intent; import android.content.res.Resources; import android.hardware.biometrics.BiometricAuthenticator; import android.hardware.biometrics.BiometricConstants; @@ -32,7 +27,6 @@ import android.hardware.biometrics.face.V1_0.IBiometricsFace; import android.hardware.face.FaceManager; import android.os.IBinder; import android.os.RemoteException; -import android.os.UserHandle; import android.util.Slog; import com.android.internal.R; @@ -40,6 +34,7 @@ import com.android.server.biometrics.Utils; import com.android.server.biometrics.sensors.AuthenticationClient; import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter; import com.android.server.biometrics.sensors.LockoutTracker; +import com.android.server.biometrics.sensors.face.ReEnrollNotificationUtils; import com.android.server.biometrics.sensors.face.UsageStats; import java.util.ArrayList; @@ -52,7 +47,7 @@ class FaceAuthenticationClient extends AuthenticationClient { private static final String TAG = "FaceAuthenticationClient"; - private final NotificationManager mNotificationManager; + private final UsageStats mUsageStats; private final int[] mBiometricPromptIgnoreList; @@ -72,7 +67,6 @@ class FaceAuthenticationClient extends AuthenticationClient { owner, cookie, requireConfirmation, sensorId, isStrongBiometric, BiometricsProtoEnums.MODALITY_FACE, statsClient, null /* taskStackListener */, lockoutTracker, isKeyguard); - mNotificationManager = context.getSystemService(NotificationManager.class); mUsageStats = usageStats; final Resources resources = getContext().getResources(); @@ -188,41 +182,7 @@ class FaceAuthenticationClient extends AuthenticationClient { mLastAcquire = acquireInfo; if (acquireInfo == FaceManager.FACE_ACQUIRED_RECALIBRATE) { - final String name = - getContext().getString(R.string.face_recalibrate_notification_name); - final String title = - getContext().getString(R.string.face_recalibrate_notification_title); - final String content = - getContext().getString(R.string.face_recalibrate_notification_content); - - final Intent intent = new Intent("android.settings.FACE_SETTINGS"); - intent.setPackage("com.android.settings"); - - final PendingIntent pendingIntent = PendingIntent.getActivityAsUser(getContext(), - 0 /* requestCode */, intent, PendingIntent.FLAG_IMMUTABLE /* flags */, - null /* options */, UserHandle.CURRENT); - - final String channelName = "FaceEnrollNotificationChannel"; - - NotificationChannel channel = new NotificationChannel(channelName, name, - NotificationManager.IMPORTANCE_HIGH); - Notification notification = new Notification.Builder(getContext(), channelName) - .setSmallIcon(R.drawable.ic_lock) - .setContentTitle(title) - .setContentText(content) - .setSubText(name) - .setOnlyAlertOnce(true) - .setLocalOnly(true) - .setAutoCancel(true) - .setCategory(Notification.CATEGORY_SYSTEM) - .setContentIntent(pendingIntent) - .setVisibility(Notification.VISIBILITY_SECRET) - .build(); - - mNotificationManager.createNotificationChannel(channel); - mNotificationManager.notifyAsUser(Face10.NOTIFICATION_TAG, - Face10.NOTIFICATION_ID, notification, - UserHandle.CURRENT); + ReEnrollNotificationUtils.showReEnrollmentNotification(getContext()); } final boolean shouldSend = shouldSend(acquireInfo, vendorCode);