summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Kevin Chyn <kchyn@google.com> 2018-09-21 04:34:59 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2018-09-21 04:34:59 +0000
commitc31c757852888d045a2d884e89fae4e069765db9 (patch)
tree30be52e7e7ecafe6980175cfdc7cd68e11d1d39c
parent6df15718f99401c31c11120ec14ca1a47236abf3 (diff)
parent6cf54e8190c35d978970d7795f2783dc46c3571b (diff)
Merge changes from topic "face-dialog"
* changes: 3/n: Add FaceDialogView and "confirmation" plumbing 2/n: Refactor common code from FingerprintDialogView 1/n: Rename FingerprintDialogView to BiometricDialogView
-rw-r--r--core/java/android/hardware/face/FaceManager.java12
-rw-r--r--core/java/android/hardware/face/IFaceService.aidl4
-rw-r--r--core/java/com/android/internal/statusbar/IStatusBar.aidl3
-rw-r--r--core/java/com/android/internal/statusbar/IStatusBarService.aidl3
-rw-r--r--core/res/res/values/strings.xml6
-rw-r--r--core/res/res/values/symbols.xml3
-rw-r--r--packages/SystemUI/res/drawable/biometric_dialog_bg.xml (renamed from packages/SystemUI/res/drawable/fingerprint_dialog_bg.xml)6
-rw-r--r--packages/SystemUI/res/drawable/face_dialog_icon.xml24
-rw-r--r--packages/SystemUI/res/drawable/fingerprint_dialog_error_to_fp.xml16
-rw-r--r--packages/SystemUI/res/drawable/fingerprint_dialog_fp_to_error.xml26
-rw-r--r--packages/SystemUI/res/layout/biometric_dialog.xml (renamed from packages/SystemUI/res/layout/fingerprint_dialog.xml)52
-rw-r--r--packages/SystemUI/res/values/colors.xml14
-rw-r--r--packages/SystemUI/res/values/dimens.xml8
-rw-r--r--packages/SystemUI/res/values/integers.xml2
-rw-r--r--packages/SystemUI/res/values/strings.xml14
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/BiometricDialogImpl.java66
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/BiometricDialogView.java363
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/FaceDialogView.java62
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/FingerprintDialogView.java351
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java9
-rw-r--r--services/core/java/com/android/server/biometrics/AuthenticationClient.java107
-rw-r--r--services/core/java/com/android/server/biometrics/BiometricPromptService.java10
-rw-r--r--services/core/java/com/android/server/biometrics/BiometricService.java19
-rw-r--r--services/core/java/com/android/server/biometrics/ClientMonitor.java3
-rw-r--r--services/core/java/com/android/server/biometrics/EnrollClient.java3
-rw-r--r--services/core/java/com/android/server/biometrics/EnumerateClient.java4
-rw-r--r--services/core/java/com/android/server/biometrics/RemovalClient.java4
-rw-r--r--services/core/java/com/android/server/biometrics/face/FaceService.java19
-rw-r--r--services/core/java/com/android/server/biometrics/fingerprint/FingerprintService.java12
-rw-r--r--services/core/java/com/android/server/statusbar/StatusBarManagerService.java5
30 files changed, 760 insertions, 470 deletions
diff --git a/core/java/android/hardware/face/FaceManager.java b/core/java/android/hardware/face/FaceManager.java
index 20e0116a0473..66613ea50357 100644
--- a/core/java/android/hardware/face/FaceManager.java
+++ b/core/java/android/hardware/face/FaceManager.java
@@ -521,16 +521,16 @@ public class FaceManager implements BiometricAuthenticator, BiometricFaceConstan
*/
public static String getErrorString(Context context, int errMsg, int vendorCode) {
switch (errMsg) {
- case FACE_ERROR_HW_UNAVAILABLE:
- return context.getString(
- com.android.internal.R.string.face_error_hw_not_available);
case FACE_ERROR_UNABLE_TO_PROCESS:
return context.getString(
com.android.internal.R.string.face_error_unable_to_process);
- case FACE_ERROR_TIMEOUT:
- return context.getString(com.android.internal.R.string.face_error_timeout);
+ case FACE_ERROR_HW_UNAVAILABLE:
+ return context.getString(
+ com.android.internal.R.string.face_error_hw_not_available);
case FACE_ERROR_NO_SPACE:
return context.getString(com.android.internal.R.string.face_error_no_space);
+ case FACE_ERROR_TIMEOUT:
+ return context.getString(com.android.internal.R.string.face_error_timeout);
case FACE_ERROR_CANCELED:
return context.getString(com.android.internal.R.string.face_error_canceled);
case FACE_ERROR_LOCKOUT:
@@ -538,6 +538,8 @@ public class FaceManager implements BiometricAuthenticator, BiometricFaceConstan
case FACE_ERROR_LOCKOUT_PERMANENT:
return context.getString(
com.android.internal.R.string.face_error_lockout_permanent);
+ case FACE_ERROR_USER_CANCELED:
+ return context.getString(com.android.internal.R.string.face_error_user_canceled);
case FACE_ERROR_NOT_ENROLLED:
return context.getString(com.android.internal.R.string.face_error_not_enrolled);
case FACE_ERROR_HW_NOT_PRESENT:
diff --git a/core/java/android/hardware/face/IFaceService.aidl b/core/java/android/hardware/face/IFaceService.aidl
index dd995c985286..a0122145c6e6 100644
--- a/core/java/android/hardware/face/IFaceService.aidl
+++ b/core/java/android/hardware/face/IFaceService.aidl
@@ -34,8 +34,8 @@ interface IFaceService {
// This method invokes the BiometricDialog. The arguments are almost the same as above,
// but should only be called from (BiometricPromptService).
- void authenticateFromService(IBinder token, long sessionId, int userId,
- IBiometricPromptServiceReceiver receiver, int flags, String opPackageName,
+ void authenticateFromService(boolean requireConfirmation, IBinder token, long sessionId,
+ int userId, IBiometricPromptServiceReceiver receiver, int flags, String opPackageName,
in Bundle bundle, IBiometricPromptReceiver dialogReceiver,
int callingUid, int callingPid, int callingUserId);
diff --git a/core/java/com/android/internal/statusbar/IStatusBar.aidl b/core/java/com/android/internal/statusbar/IStatusBar.aidl
index c4214cf19fa9..9b8f120ec08d 100644
--- a/core/java/com/android/internal/statusbar/IStatusBar.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBar.aidl
@@ -141,7 +141,8 @@ oneway interface IStatusBar
void showShutdownUi(boolean isReboot, String reason);
// Used to show the dialog when BiometricService starts authentication
- void showBiometricDialog(in Bundle bundle, IBiometricPromptReceiver receiver, int type);
+ void showBiometricDialog(in Bundle bundle, IBiometricPromptReceiver receiver, int type,
+ boolean requireConfirmation);
// Used to hide the dialog when a biometric is authenticated
void onBiometricAuthenticated();
// Used to set a temporary message, e.g. fingerprint not recognized, finger moved too fast, etc
diff --git a/core/java/com/android/internal/statusbar/IStatusBarService.aidl b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
index e48e73305191..90f2002d7363 100644
--- a/core/java/com/android/internal/statusbar/IStatusBarService.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
@@ -91,7 +91,8 @@ interface IStatusBarService
void showPinningEscapeToast();
// Used to show the dialog when BiometricService starts authentication
- void showBiometricDialog(in Bundle bundle, IBiometricPromptReceiver receiver, int type);
+ void showBiometricDialog(in Bundle bundle, IBiometricPromptReceiver receiver, int type,
+ boolean requireConfirmation);
// Used to hide the dialog when a biometric is authenticated
void onBiometricAuthenticated();
// Used to set a temporary message, e.g. fingerprint not recognized, finger moved too fast, etc
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 64620f33b2df..6d0127a4bba1 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -1439,6 +1439,10 @@
<string name="biometric_not_recognized">Not recognized</string>
<!-- Accessibility message announced when a fingerprint has been authenticated [CHAR LIMIT=NONE] -->
<string name="fingerprint_authenticated">Fingerprint authenticated</string>
+ <!-- Accessibility message announced when a face has been authenticated [CHAR LIMIT=NONE] -->
+ <string name="face_authenticated_no_confirmation_required">Face authenticated</string>
+ <!-- Accessibility message announced when a face has been authenticated, but requires the user to press the confirm button [CHAR LIMIT=NONE] -->
+ <string name="face_authenticated_confirmation_required">Face authenticated, please press confirm</string>
<!-- Error message shown when the fingerprint hardware can't be accessed -->
<string name="fingerprint_error_hw_not_available">Fingerprint hardware not available.</string>
@@ -1516,6 +1520,8 @@
<string name="face_error_no_space">Face can\u2019t be stored.</string>
<!-- Generic error message shown when the face operation (e.g. enrollment or authentication) is canceled. Generally not shown to the user. [CHAR LIMIT=50] -->
<string name="face_error_canceled">Face operation canceled.</string>
+ <!-- Generic error message shown when the face authentication operation is canceled due to user input. Generally not shown to the user [CHAR LIMIT=50] -->
+ <string name="face_error_user_canceled">Face authentication canceled by user.</string>
<!-- Generic error message shown when the face operation fails because too many attempts have been made. [CHAR LIMIT=50] -->
<string name="face_error_lockout">Too many attempts. Try again later.</string>
<!-- Generic error message shown when the face operation fails because strong authentication is required. [CHAR LIMIT=50] -->
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 7b8eceda9370..cf859867f21c 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -2429,6 +2429,7 @@
<java-symbol type="string" name="face_error_timeout" />
<java-symbol type="array" name="face_error_vendor" />
<java-symbol type="string" name="face_error_canceled" />
+ <java-symbol type="string" name="face_error_user_canceled" />
<java-symbol type="string" name="face_error_lockout" />
<java-symbol type="string" name="face_error_lockout_permanent" />
<java-symbol type="string" name="face_error_not_enrolled" />
@@ -2446,6 +2447,8 @@
<java-symbol type="string" name="face_acquired_not_detected" />
<java-symbol type="array" name="face_acquired_vendor" />
<java-symbol type="string" name="face_name_template" />
+ <java-symbol type="string" name="face_authenticated_no_confirmation_required" />
+ <java-symbol type="string" name="face_authenticated_confirmation_required" />
<!-- Face config -->
<java-symbol type="integer" name="config_faceMaxTemplatesPerUser" />
diff --git a/packages/SystemUI/res/drawable/fingerprint_dialog_bg.xml b/packages/SystemUI/res/drawable/biometric_dialog_bg.xml
index 221f1701187d..335448d82373 100644
--- a/packages/SystemUI/res/drawable/fingerprint_dialog_bg.xml
+++ b/packages/SystemUI/res/drawable/biometric_dialog_bg.xml
@@ -17,10 +17,10 @@
-->
<shape xmlns:android="http://schemas.android.com/apk/res/android">
- <solid android:color="@color/fingerprint_dialog_bg_color" />
+ <solid android:color="@color/biometric_dialog_bg_color" />
<corners android:radius="1dp"
- android:topLeftRadius="@dimen/fingerprint_dialog_corner_size"
- android:topRightRadius="@dimen/fingerprint_dialog_corner_size"
+ android:topLeftRadius="@dimen/biometric_dialog_corner_size"
+ android:topRightRadius="@dimen/biometric_dialog_corner_size"
android:bottomLeftRadius="0dp"
android:bottomRightRadius="0dp"/>
</shape> \ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/face_dialog_icon.xml b/packages/SystemUI/res/drawable/face_dialog_icon.xml
new file mode 100644
index 000000000000..6d28b5a105f2
--- /dev/null
+++ b/packages/SystemUI/res/drawable/face_dialog_icon.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2018 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
+ -->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:width="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path android:fillColor="#000" android:pathData="M9,11.75A1.25,1.25 0 0,0 7.75,13A1.25,1.25 0 0,0 9,14.25A1.25,1.25 0 0,0 10.25,13A1.25,1.25 0 0,0 9,11.75M15,11.75A1.25,1.25 0 0,0 13.75,13A1.25,1.25 0 0,0 15,14.25A1.25,1.25 0 0,0 16.25,13A1.25,1.25 0 0,0 15,11.75M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12A10,10 0 0,0 12,2M12,20C7.59,20 4,16.41 4,12C4,11.71 4,11.42 4.05,11.14C6.41,10.09 8.28,8.16 9.26,5.77C11.07,8.33 14.05,10 17.42,10C18.2,10 18.95,9.91 19.67,9.74C19.88,10.45 20,11.21 20,12C20,16.41 16.41,20 12,20Z" />
+</vector> \ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/fingerprint_dialog_error_to_fp.xml b/packages/SystemUI/res/drawable/fingerprint_dialog_error_to_fp.xml
index 83c1949b681c..05fd467b749e 100644
--- a/packages/SystemUI/res/drawable/fingerprint_dialog_error_to_fp.xml
+++ b/packages/SystemUI/res/drawable/fingerprint_dialog_error_to_fp.xml
@@ -36,7 +36,7 @@
android:name="_R_G_L_2_G_D_0_P_0"
android:pathData=" M-25.36 -24.41 C-25.93,-24.31 -26.49,-24.27 -26.81,-24.27 C-28.11,-24.27 -29.35,-24.62 -30.43,-25.4 C-32.11,-26.6 -33.2,-28.57 -33.2,-30.79 "
android:strokeAlpha="1"
- android:strokeColor="@color/fingerprint_dialog_fingerprint_color"
+ android:strokeColor="@color/biometric_dialog_biometric_color"
android:strokeLineCap="round"
android:strokeLineJoin="round"
android:strokeWidth="1.45"
@@ -47,7 +47,7 @@
android:name="_R_G_L_2_G_D_1_P_0"
android:pathData=" M-36.14 -21.78 C-37.15,-22.98 -37.72,-23.7 -38.51,-25.29 C-39.33,-26.94 -39.82,-28.78 -39.82,-30.77 C-39.82,-34.43 -36.85,-37.4 -33.19,-37.4 C-29.52,-37.4 -26.55,-34.43 -26.55,-30.77 "
android:strokeAlpha="1"
- android:strokeColor="@color/fingerprint_dialog_fingerprint_color"
+ android:strokeColor="@color/biometric_dialog_biometric_color"
android:strokeLineCap="round"
android:strokeLineJoin="round"
android:strokeWidth="1.45"
@@ -58,7 +58,7 @@
android:name="_R_G_L_2_G_D_2_P_0"
android:pathData=" M-42.19 -25.68 C-42.95,-27.82 -43.09,-29.54 -43.09,-30.8 C-43.09,-32.27 -42.84,-33.65 -42.27,-34.9 C-40.71,-38.35 -37.24,-40.75 -33.2,-40.75 C-27.71,-40.75 -23.26,-36.3 -23.26,-30.8 C-23.26,-28.97 -24.74,-27.49 -26.57,-27.49 C-28.4,-27.49 -29.89,-28.97 -29.89,-30.8 C-29.89,-32.64 -31.37,-34.12 -33.2,-34.12 C-35.04,-34.12 -36.52,-32.64 -36.52,-30.8 C-36.52,-28.23 -35.53,-25.92 -33.92,-24.22 C-32.69,-22.93 -31.48,-22.12 -29.44,-21.53 "
android:strokeAlpha="1"
- android:strokeColor="@color/fingerprint_dialog_fingerprint_color"
+ android:strokeColor="@color/biometric_dialog_biometric_color"
android:strokeLineCap="round"
android:strokeLineJoin="round"
android:strokeWidth="1.45"
@@ -69,7 +69,7 @@
android:name="_R_G_L_2_G_D_3_P_0"
android:pathData=" M-44.06 -38.17 C-42.87,-39.94 -41.39,-41.41 -39.51,-42.44 C-37.62,-43.47 -35.46,-44.05 -33.16,-44.05 C-30.88,-44.05 -28.72,-43.47 -26.85,-42.45 C-24.97,-41.43 -23.48,-39.97 -22.29,-38.21 "
android:strokeAlpha="1"
- android:strokeColor="@color/fingerprint_dialog_fingerprint_color"
+ android:strokeColor="@color/biometric_dialog_biometric_color"
android:strokeLineCap="round"
android:strokeLineJoin="round"
android:strokeWidth="1.45"
@@ -80,7 +80,7 @@
android:name="_R_G_L_2_G_D_4_P_0"
android:pathData=" M-25.72 -45.45 C-27.99,-46.76 -30.43,-47.52 -33.28,-47.52 C-36.13,-47.52 -38.51,-46.74 -40.62,-45.45 "
android:strokeAlpha="1"
- android:strokeColor="@color/fingerprint_dialog_fingerprint_color"
+ android:strokeColor="@color/biometric_dialog_biometric_color"
android:strokeLineCap="round"
android:strokeLineJoin="round"
android:strokeWidth="1.45"
@@ -97,7 +97,7 @@
android:name="_R_G_L_1_G_D_0_P_0"
android:pathData=" M0 -9 C4.97,-9 9,-4.97 9,0 C9,4.97 4.97,9 0,9 C-4.97,9 -9,4.97 -9,0 C-9,-4.97 -4.97,-9 0,-9c "
android:strokeAlpha="1"
- android:strokeColor="@color/fingerprint_dialog_error_color"
+ android:strokeColor="@color/biometric_dialog_error_color"
android:strokeLineCap="round"
android:strokeLineJoin="round"
android:strokeWidth="2"
@@ -118,7 +118,7 @@
<path
android:name="_R_G_L_0_G_D_0_P_0"
android:fillAlpha="1"
- android:fillColor="@color/fingerprint_dialog_error_color"
+ android:fillColor="@color/biometric_dialog_error_color"
android:fillType="nonZero"
android:pathData=" M1.1 3.94 C1.1,4.55 0.61,5.04 0,5.04 C-0.61,5.04 -1.1,4.55 -1.1,3.94 C-1.1,3.33 -0.61,2.84 0,2.84 C0.61,2.84 1.1,3.33 1.1,3.94c " />
</group>
@@ -131,7 +131,7 @@
<path
android:name="_R_G_L_0_G_D_0_P_1"
android:fillAlpha="1"
- android:fillColor="@color/fingerprint_dialog_error_color"
+ android:fillColor="@color/biometric_dialog_error_color"
android:fillType="nonZero"
android:pathData=" M1 -4.06 C1,-4.06 1,-0.06 1,-0.06 C1,0.49 0.55,0.94 0,0.94 C-0.55,0.94 -1,0.49 -1,-0.06 C-1,-0.06 -1,-4.06 -1,-4.06 C-1,-4.61 -0.55,-5.06 0,-5.06 C0.55,-5.06 1,-4.61 1,-4.06c " />
</group>
diff --git a/packages/SystemUI/res/drawable/fingerprint_dialog_fp_to_error.xml b/packages/SystemUI/res/drawable/fingerprint_dialog_fp_to_error.xml
index f682f87003dc..fd0ab22b2f98 100644
--- a/packages/SystemUI/res/drawable/fingerprint_dialog_fp_to_error.xml
+++ b/packages/SystemUI/res/drawable/fingerprint_dialog_fp_to_error.xml
@@ -36,7 +36,7 @@
android:name="_R_G_L_3_G_D_0_P_0"
android:pathData=" M-25.36 -24.41 C-25.93,-24.31 -26.49,-24.27 -26.81,-24.27 C-28.11,-24.27 -29.35,-24.62 -30.43,-25.4 C-32.11,-26.6 -33.2,-28.57 -33.2,-30.79 "
android:strokeAlpha="1"
- android:strokeColor="@color/fingerprint_dialog_fingerprint_color"
+ android:strokeColor="@color/biometric_dialog_biometric_color"
android:strokeLineCap="round"
android:strokeLineJoin="round"
android:strokeWidth="1.45"
@@ -47,7 +47,7 @@
android:name="_R_G_L_3_G_D_1_P_0"
android:pathData=" M-36.14 -21.78 C-37.15,-22.98 -37.72,-23.7 -38.51,-25.29 C-39.33,-26.94 -39.82,-28.78 -39.82,-30.77 C-39.82,-34.43 -36.85,-37.4 -33.19,-37.4 C-29.52,-37.4 -26.55,-34.43 -26.55,-30.77 "
android:strokeAlpha="1"
- android:strokeColor="@color/fingerprint_dialog_fingerprint_color"
+ android:strokeColor="@color/biometric_dialog_biometric_color"
android:strokeLineCap="round"
android:strokeLineJoin="round"
android:strokeWidth="1.45"
@@ -58,7 +58,7 @@
android:name="_R_G_L_3_G_D_2_P_0"
android:pathData=" M-42.19 -25.68 C-42.95,-27.82 -43.09,-29.54 -43.09,-30.8 C-43.09,-32.27 -42.84,-33.65 -42.27,-34.9 C-40.71,-38.35 -37.24,-40.75 -33.2,-40.75 C-27.71,-40.75 -23.26,-36.3 -23.26,-30.8 C-23.26,-28.97 -24.74,-27.49 -26.57,-27.49 C-28.4,-27.49 -29.89,-28.97 -29.89,-30.8 C-29.89,-32.64 -31.37,-34.12 -33.2,-34.12 C-35.04,-34.12 -36.52,-32.64 -36.52,-30.8 C-36.52,-28.23 -35.53,-25.92 -33.92,-24.22 C-32.69,-22.93 -31.48,-22.12 -29.44,-21.53 "
android:strokeAlpha="1"
- android:strokeColor="@color/fingerprint_dialog_fingerprint_color"
+ android:strokeColor="@color/biometric_dialog_biometric_color"
android:strokeLineCap="round"
android:strokeLineJoin="round"
android:strokeWidth="1.45"
@@ -69,7 +69,7 @@
android:name="_R_G_L_3_G_D_3_P_0"
android:pathData=" M-44.06 -38.17 C-42.87,-39.94 -41.39,-41.41 -39.51,-42.44 C-37.62,-43.47 -35.46,-44.05 -33.16,-44.05 C-30.88,-44.05 -28.72,-43.47 -26.85,-42.45 C-24.97,-41.43 -23.48,-39.97 -22.29,-38.21 "
android:strokeAlpha="1"
- android:strokeColor="@color/fingerprint_dialog_fingerprint_color"
+ android:strokeColor="@color/biometric_dialog_biometric_color"
android:strokeLineCap="round"
android:strokeLineJoin="round"
android:strokeWidth="1.45"
@@ -80,7 +80,7 @@
android:name="_R_G_L_3_G_D_4_P_0"
android:pathData=" M-25.72 -45.45 C-27.99,-46.76 -30.43,-47.52 -33.28,-47.52 C-36.13,-47.52 -38.51,-46.74 -40.62,-45.45 "
android:strokeAlpha="1"
- android:strokeColor="@color/fingerprint_dialog_fingerprint_color"
+ android:strokeColor="@color/biometric_dialog_biometric_color"
android:strokeLineCap="round"
android:strokeLineJoin="round"
android:strokeWidth="1.45"
@@ -101,7 +101,7 @@
android:name="_R_G_L_2_G_D_0_P_0"
android:pathData=" M-25.36 -24.41 C-25.93,-24.31 -26.49,-24.27 -26.81,-24.27 C-28.11,-24.27 -29.35,-24.62 -30.43,-25.4 C-32.11,-26.6 -33.2,-28.57 -33.2,-30.79 "
android:strokeAlpha="1"
- android:strokeColor="@color/fingerprint_dialog_error_color"
+ android:strokeColor="@color/biometric_dialog_error_color"
android:strokeLineCap="round"
android:strokeLineJoin="round"
android:strokeWidth="1.45"
@@ -112,7 +112,7 @@
android:name="_R_G_L_2_G_D_1_P_0"
android:pathData=" M-36.14 -21.78 C-37.15,-22.98 -37.72,-23.7 -38.51,-25.29 C-39.33,-26.94 -39.82,-28.78 -39.82,-30.77 C-39.82,-34.43 -36.85,-37.4 -33.19,-37.4 C-29.52,-37.4 -26.55,-34.43 -26.55,-30.77 "
android:strokeAlpha="1"
- android:strokeColor="@color/fingerprint_dialog_error_color"
+ android:strokeColor="@color/biometric_dialog_error_color"
android:strokeLineCap="round"
android:strokeLineJoin="round"
android:strokeWidth="1.45"
@@ -123,7 +123,7 @@
android:name="_R_G_L_2_G_D_2_P_0"
android:pathData=" M-42.19 -25.68 C-42.95,-27.82 -43.09,-29.54 -43.09,-30.8 C-43.09,-32.27 -42.84,-33.65 -42.27,-34.9 C-40.71,-38.35 -37.24,-40.75 -33.2,-40.75 C-27.71,-40.75 -23.26,-36.3 -23.26,-30.8 C-23.26,-28.97 -24.74,-27.49 -26.57,-27.49 C-28.4,-27.49 -29.89,-28.97 -29.89,-30.8 C-29.89,-32.64 -31.37,-34.12 -33.2,-34.12 C-35.04,-34.12 -36.52,-32.64 -36.52,-30.8 C-36.52,-28.23 -35.53,-25.92 -33.92,-24.22 C-32.69,-22.93 -31.48,-22.12 -29.44,-21.53 "
android:strokeAlpha="1"
- android:strokeColor="@color/fingerprint_dialog_error_color"
+ android:strokeColor="@color/biometric_dialog_error_color"
android:strokeLineCap="round"
android:strokeLineJoin="round"
android:strokeWidth="1.45"
@@ -134,7 +134,7 @@
android:name="_R_G_L_2_G_D_3_P_0"
android:pathData=" M-44.06 -38.17 C-42.87,-39.94 -41.39,-41.41 -39.51,-42.44 C-37.62,-43.47 -35.46,-44.05 -33.16,-44.05 C-30.88,-44.05 -28.72,-43.47 -26.85,-42.45 C-24.97,-41.43 -23.48,-39.97 -22.29,-38.21 "
android:strokeAlpha="1"
- android:strokeColor="@color/fingerprint_dialog_error_color"
+ android:strokeColor="@color/biometric_dialog_error_color"
android:strokeLineCap="round"
android:strokeLineJoin="round"
android:strokeWidth="1.45"
@@ -145,7 +145,7 @@
android:name="_R_G_L_2_G_D_4_P_0"
android:pathData=" M-25.72 -45.45 C-27.99,-46.76 -30.43,-47.52 -33.28,-47.52 C-36.13,-47.52 -38.51,-46.74 -40.62,-45.45 "
android:strokeAlpha="1"
- android:strokeColor="@color/fingerprint_dialog_error_color"
+ android:strokeColor="@color/biometric_dialog_error_color"
android:strokeLineCap="round"
android:strokeLineJoin="round"
android:strokeWidth="1.45"
@@ -162,7 +162,7 @@
android:name="_R_G_L_1_G_D_0_P_0"
android:pathData=" M0 -9 C4.97,-9 9,-4.97 9,0 C9,4.97 4.97,9 0,9 C-4.97,9 -9,4.97 -9,0 C-9,-4.97 -4.97,-9 0,-9c "
android:strokeAlpha="1"
- android:strokeColor="@color/fingerprint_dialog_error_color"
+ android:strokeColor="@color/biometric_dialog_error_color"
android:strokeLineCap="round"
android:strokeLineJoin="round"
android:strokeWidth="2"
@@ -183,7 +183,7 @@
<path
android:name="_R_G_L_0_G_D_0_P_0"
android:fillAlpha="1"
- android:fillColor="@color/fingerprint_dialog_error_color"
+ android:fillColor="@color/biometric_dialog_error_color"
android:fillType="nonZero"
android:pathData=" M1.1 3.94 C1.1,4.55 0.61,5.04 0,5.04 C-0.61,5.04 -1.1,4.55 -1.1,3.94 C-1.1,3.33 -0.61,2.84 0,2.84 C0.61,2.84 1.1,3.33 1.1,3.94c " />
</group>
@@ -196,7 +196,7 @@
<path
android:name="_R_G_L_0_G_D_0_P_1"
android:fillAlpha="1"
- android:fillColor="@color/fingerprint_dialog_error_color"
+ android:fillColor="@color/biometric_dialog_error_color"
android:fillType="nonZero"
android:pathData=" M1 -4.06 C1,-4.06 1,-0.06 1,-0.06 C1,0.49 0.55,0.94 0,0.94 C-0.55,0.94 -1,0.49 -1,-0.06 C-1,-0.06 -1,-4.06 -1,-4.06 C-1,-4.61 -0.55,-5.06 0,-5.06 C0.55,-5.06 1,-4.61 1,-4.06c " />
</group>
diff --git a/packages/SystemUI/res/layout/fingerprint_dialog.xml b/packages/SystemUI/res/layout/biometric_dialog.xml
index 1bdaf6e33544..0417e2ede2d3 100644
--- a/packages/SystemUI/res/layout/fingerprint_dialog.xml
+++ b/packages/SystemUI/res/layout/biometric_dialog.xml
@@ -19,7 +19,7 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="bottom"
- android:background="@color/fingerprint_dialog_dim_color"
+ android:background="@color/biometric_dialog_dim_color"
android:orientation="vertical">
<!-- This is not a Space since Spaces cannot be clicked -->
@@ -47,7 +47,7 @@
android:layout_height="wrap_content"
android:orientation="vertical"
android:elevation="2dp"
- android:background="@drawable/fingerprint_dialog_bg">
+ android:background="@drawable/biometric_dialog_bg">
<TextView
android:id="@+id/title"
@@ -57,13 +57,13 @@
android:layout_marginEnd="24dp"
android:layout_marginStart="24dp"
android:layout_marginTop="24dp"
- android:gravity="@integer/fingerprint_dialog_text_gravity"
+ android:gravity="@integer/biometric_dialog_text_gravity"
android:textSize="20sp"
android:maxLines="1"
android:singleLine="true"
android:ellipsize="marquee"
android:marqueeRepeatLimit="marquee_forever"
- android:textColor="@color/fingerprint_dialog_text_dark_color"/>
+ android:textColor="@color/biometric_dialog_text_dark_color"/>
<TextView
android:id="@+id/subtitle"
@@ -72,13 +72,13 @@
android:layout_marginTop="8dp"
android:layout_marginStart="24dp"
android:layout_marginEnd="24dp"
- android:gravity="@integer/fingerprint_dialog_text_gravity"
+ android:gravity="@integer/biometric_dialog_text_gravity"
android:textSize="16sp"
android:maxLines="1"
android:singleLine="true"
android:ellipsize="marquee"
android:marqueeRepeatLimit="marquee_forever"
- android:textColor="@color/fingerprint_dialog_text_dark_color"/>
+ android:textColor="@color/biometric_dialog_text_dark_color"/>
<TextView
android:id="@+id/description"
@@ -86,20 +86,19 @@
android:layout_height="wrap_content"
android:layout_marginEnd="24dp"
android:layout_marginStart="24dp"
- android:gravity="@integer/fingerprint_dialog_text_gravity"
+ android:gravity="@integer/biometric_dialog_text_gravity"
android:paddingTop="8dp"
android:textSize="16sp"
android:maxLines="4"
- android:textColor="@color/fingerprint_dialog_text_dark_color"/>
+ android:textColor="@color/biometric_dialog_text_dark_color"/>
<ImageView
- android:id="@+id/fingerprint_icon"
- android:layout_width="@dimen/fingerprint_dialog_fp_icon_size"
- android:layout_height="@dimen/fingerprint_dialog_fp_icon_size"
+ android:id="@+id/biometric_icon"
+ android:layout_width="@dimen/biometric_dialog_biometric_icon_size"
+ android:layout_height="@dimen/biometric_dialog_biometric_icon_size"
android:layout_gravity="center_horizontal"
android:layout_marginTop="48dp"
- android:scaleType="fitXY"
- android:contentDescription="@string/accessibility_fingerprint_dialog_fingerprint_icon" />
+ android:scaleType="fitXY" />
<TextView
android:id="@+id/error"
@@ -112,9 +111,8 @@
android:textSize="12sp"
android:gravity="center_horizontal"
android:accessibilityLiveRegion="polite"
- android:text="@string/fingerprint_dialog_touch_sensor"
- android:contentDescription="@string/accessibility_fingerprint_dialog_help_area"
- android:textColor="@color/fingerprint_dialog_text_light_color"/>
+ android:contentDescription="@string/accessibility_biometric_dialog_help_area"
+ android:textColor="@color/biometric_dialog_text_light_color"/>
<LinearLayout
android:layout_width="match_parent"
@@ -125,7 +123,7 @@
android:orientation="horizontal"
android:measureWithLargestChild="true">
<Space android:id="@+id/leftSpacer"
- android:layout_width="24dp"
+ android:layout_width="12dp"
android:layout_height="match_parent"
android:visibility="visible" />
<!-- Negative Button -->
@@ -133,20 +131,26 @@
android:layout_width="wrap_content"
android:layout_height="match_parent"
style="@*android:style/Widget.DeviceDefault.Button.Borderless.Colored"
- android:layout_marginStart="-12dp"
- android:gravity="start|center_vertical"
+ android:gravity="center"
android:maxLines="2" />
+ <Space android:id="@+id/middleSpacer"
+ android:layout_width="0dp"
+ android:layout_height="match_parent"
+ android:layout_weight="1"
+ android:visibility="visible" />
<!-- Positive Button -->
<Button android:id="@+id/button1"
android:layout_width="wrap_content"
android:layout_height="match_parent"
- style="@*android:style/Widget.DeviceDefault.Button.Borderless.Colored"
- android:layout_marginEnd="12dp"
- android:maxLines="2" />
+ style="@*android:style/Widget.DeviceDefault.Button.Colored"
+ android:gravity="center"
+ android:maxLines="2"
+ android:text="@string/biometric_dialog_confirm"
+ android:visibility="gone"/>
<Space android:id="@+id/rightSpacer"
- android:layout_width="24dip"
+ android:layout_width="12dip"
android:layout_height="match_parent"
- android:visibility="gone" />
+ android:visibility="visible" />
</LinearLayout>
</LinearLayout>
diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml
index 4920fb2ea407..d1320a34f365 100644
--- a/packages/SystemUI/res/values/colors.xml
+++ b/packages/SystemUI/res/values/colors.xml
@@ -160,13 +160,13 @@
<color name="smart_reply_button_background">#ffffffff</color>
<color name="smart_reply_button_stroke">#ffdadce0</color>
- <!-- Fingerprint dialog colors -->
- <color name="fingerprint_dialog_bg_color">#ffffffff</color> <!-- 100% white -->
- <color name="fingerprint_dialog_text_dark_color">#dd000000</color> <!-- 87% black -->
- <color name="fingerprint_dialog_text_light_color">#89000000</color> <!-- 54% black -->
- <color name="fingerprint_dialog_dim_color">#80000000</color> <!-- 50% black -->
- <color name="fingerprint_dialog_error_color">#fff44336</color> <!-- red -->
- <color name="fingerprint_dialog_fingerprint_color">#ff008577</color> <!-- teal -->
+ <!-- Biometric dialog colors -->
+ <color name="biometric_dialog_bg_color">#ffffffff</color> <!-- 100% white -->
+ <color name="biometric_dialog_text_dark_color">#dd000000</color> <!-- 87% black -->
+ <color name="biometric_dialog_text_light_color">#89000000</color> <!-- 54% black -->
+ <color name="biometric_dialog_dim_color">#80000000</color> <!-- 50% black -->
+ <color name="biometric_dialog_error_color">#fff44336</color> <!-- red -->
+ <color name="biometric_dialog_biometric_color">#ff008577</color> <!-- teal -->
<!-- Logout button -->
<color name="logout_button_bg_color">#ccffffff</color>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index c168d4e6d7b2..8ac3aa1748ce 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -982,10 +982,10 @@
the regular notification, when we have remote input history texts present. -->
<dimen name="remote_input_history_extra_height">60dp</dimen>
- <!-- Fingerprint Dialog values -->
- <dimen name="fingerprint_dialog_fp_icon_size">64dp</dimen>
- <dimen name="fingerprint_dialog_animation_translation_offset">350dp</dimen>
- <dimen name="fingerprint_dialog_corner_size">4dp</dimen>
+ <!-- Biometric Dialog values -->
+ <dimen name="biometric_dialog_biometric_icon_size">64dp</dimen>
+ <dimen name="biometric_dialog_corner_size">4dp</dimen>
+ <dimen name="biometric_dialog_animation_translation_offset">350dp</dimen>
<!-- Wireless Charging Animation values -->
<dimen name="wireless_charging_dots_radius_start">0dp</dimen>
diff --git a/packages/SystemUI/res/values/integers.xml b/packages/SystemUI/res/values/integers.xml
index 87c4bbba86ef..fd7a10500f36 100644
--- a/packages/SystemUI/res/values/integers.xml
+++ b/packages/SystemUI/res/values/integers.xml
@@ -15,7 +15,7 @@
~ limitations under the License
-->
<resources>
- <integer name="fingerprint_dialog_text_gravity">8388611</integer> <!-- gravity start -->
+ <integer name="biometric_dialog_text_gravity">8388611</integer> <!-- gravity start -->
<!-- Action footer width used for layout_width to indicate WRAP_CONTENT (along with a weight of
0) as we can allow the carrier text to stretch as far as needed in the QS footer. -->
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 36f97cd64642..a3306d3dc4d5 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -257,14 +257,20 @@
<!-- Button name for "Cancel". [CHAR LIMIT=NONE] -->
<string name="cancel">Cancel</string>
+ <!-- Content description for the error/help message are when the system-provided fingerprint dialog is showing, for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+ <string name="accessibility_biometric_dialog_help_area">Help message area</string>
+ <!-- Message shown when a biometric is authenticated, asking the user to confirm authentication [CHAR LIMIT=30] -->
+ <string name="biometric_dialog_confirm">Confirm</string>
+
<!-- Message shown when the system-provided fingerprint dialog is shown, asking for authentication -->
<string name="fingerprint_dialog_touch_sensor">Touch the fingerprint sensor</string>
<!-- Content description of the fingerprint icon when the system-provided fingerprint dialog is showing, for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
<string name="accessibility_fingerprint_dialog_fingerprint_icon">Fingerprint icon</string>
- <!-- Content description of the application icon when the system-provided fingerprint dialog is showing, for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
- <string name="accessibility_fingerprint_dialog_app_icon">Application icon</string>
- <!-- Content description for the error/help message are when the system-provided fingerprint dialog is showing, for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
- <string name="accessibility_fingerprint_dialog_help_area">Help message area</string>
+
+ <!-- Message shown when the system-provided face dialog is shown, asking for authentication [CHAR LIMIT=30] -->
+ <string name="face_dialog_looking_for_face">Looking for you\u2026</string>
+ <!-- Content description of the face icon when the system-provided face dialog is showing, for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+ <string name="accessibility_face_dialog_face_icon">Face icon</string>
<!-- Content description of the compatibility zoom button for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
<string name="accessibility_compatibility_zoom_button">Compatibility zoom button.</string>
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/BiometricDialogImpl.java b/packages/SystemUI/src/com/android/systemui/biometrics/BiometricDialogImpl.java
index 8fe577a4cec0..8fc46891c3a1 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/BiometricDialogImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/BiometricDialogImpl.java
@@ -18,6 +18,7 @@ package com.android.systemui.biometrics;
import android.content.Context;
import android.content.pm.PackageManager;
+import android.hardware.biometrics.BiometricAuthenticator;
import android.hardware.biometrics.BiometricPrompt;
import android.hardware.biometrics.IBiometricPromptReceiver;
import android.os.Bundle;
@@ -31,9 +32,12 @@ import com.android.internal.os.SomeArgs;
import com.android.systemui.SystemUI;
import com.android.systemui.statusbar.CommandQueue;
+import java.util.HashMap;
+import java.util.Map;
+
/**
* Receives messages sent from AuthenticationClient and shows the appropriate biometric UI (e.g.
- * FingerprintDialogView).
+ * BiometricDialogView).
*/
public class BiometricDialogImpl extends SystemUI implements CommandQueue.Callbacks {
private static final String TAG = "BiometricDialogImpl";
@@ -48,7 +52,8 @@ public class BiometricDialogImpl extends SystemUI implements CommandQueue.Callba
private static final int MSG_USER_CANCELED = 7;
private static final int MSG_BUTTON_POSITIVE = 8;
- private FingerprintDialogView mDialogView;
+ private Map<Integer, BiometricDialogView> mDialogs; // BiometricAuthenticator type, view
+ private BiometricDialogView mCurrentDialog;
private WindowManager mWindowManager;
private IBiometricPromptReceiver mReceiver;
private boolean mDialogShowing;
@@ -111,16 +116,25 @@ public class BiometricDialogImpl extends SystemUI implements CommandQueue.Callba
@Override
public void start() {
- if (!mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_FINGERPRINT)) {
- return;
+ final PackageManager pm = mContext.getPackageManager();
+ mDialogs = new HashMap<>();
+ if (pm.hasSystemFeature(PackageManager.FEATURE_FACE)) {
+ mDialogs.put(BiometricAuthenticator.TYPE_FACE, new FaceDialogView(mContext, mCallback));
+ }
+ if (pm.hasSystemFeature(PackageManager.FEATURE_FINGERPRINT)) {
+ mDialogs.put(BiometricAuthenticator.TYPE_FINGERPRINT,
+ new FingerprintDialogView(mContext, mCallback));
+ }
+
+ if (!mDialogs.isEmpty()) {
+ getComponent(CommandQueue.class).addCallbacks(this);
+ mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
}
- getComponent(CommandQueue.class).addCallbacks(this);
- mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
- mDialogView = new FingerprintDialogView(mContext, mCallback);
}
@Override
- public void showBiometricDialog(Bundle bundle, IBiometricPromptReceiver receiver, int type) {
+ public void showBiometricDialog(Bundle bundle, IBiometricPromptReceiver receiver, int type,
+ boolean requireConfirmation) {
if (DEBUG) Log.d(TAG, "showBiometricDialog, type: " + type);
// Remove these messages as they are part of the previous client
mHandler.removeMessages(MSG_BIOMETRIC_ERROR);
@@ -129,6 +143,8 @@ public class BiometricDialogImpl extends SystemUI implements CommandQueue.Callba
SomeArgs args = SomeArgs.obtain();
args.arg1 = bundle;
args.arg2 = receiver;
+ args.argi1 = type;
+ args.arg3 = requireConfirmation;
mHandler.obtainMessage(MSG_SHOW_DIALOG, args).sendToTarget();
}
@@ -157,33 +173,41 @@ public class BiometricDialogImpl extends SystemUI implements CommandQueue.Callba
}
private void handleShowDialog(SomeArgs args) {
+ final int type = args.argi1;
+ mCurrentDialog = mDialogs.get(type);
+
if (DEBUG) Log.d(TAG, "handleShowDialog, isAnimatingAway: "
- + mDialogView.isAnimatingAway());
- if (mDialogView.isAnimatingAway()) {
- mDialogView.forceRemove();
+ + mCurrentDialog.isAnimatingAway() + " type: " + type);
+
+ if (mCurrentDialog.isAnimatingAway()) {
+ mCurrentDialog.forceRemove();
} else if (mDialogShowing) {
Log.w(TAG, "Dialog already showing");
return;
}
mReceiver = (IBiometricPromptReceiver) args.arg2;
- mDialogView.setBundle((Bundle)args.arg1);
- mWindowManager.addView(mDialogView, mDialogView.getLayoutParams());
+ mCurrentDialog.setBundle((Bundle)args.arg1);
+ mCurrentDialog.setRequireConfirmation((boolean)args.arg3);
+ mWindowManager.addView(mCurrentDialog, mCurrentDialog.getLayoutParams());
mDialogShowing = true;
}
private void handleBiometricAuthenticated() {
if (DEBUG) Log.d(TAG, "handleBiometricAuthenticated");
- // TODO: announce correct string depending on modality
- mDialogView.announceForAccessibility(
- mContext.getResources().getText(
- com.android.internal.R.string.fingerprint_authenticated));
- handleHideDialog(false /* userCanceled */);
+ mCurrentDialog.announceForAccessibility(
+ mContext.getResources()
+ .getText(mCurrentDialog.getAuthenticatedAccessibilityResourceId()));
+ if (mCurrentDialog.requiresConfirmation()) {
+ mCurrentDialog.showConfirmationButton();
+ } else {
+ handleHideDialog(false /* userCanceled */);
+ }
}
private void handleBiometricHelp(String message) {
if (DEBUG) Log.d(TAG, "handleBiometricHelp: " + message);
- mDialogView.showHelpMessage(message);
+ mCurrentDialog.showHelpMessage(message);
}
private void handleBiometricError(String error) {
@@ -192,7 +216,7 @@ public class BiometricDialogImpl extends SystemUI implements CommandQueue.Callba
if (DEBUG) Log.d(TAG, "Dialog already dismissed");
return;
}
- mDialogView.showErrorMessage(error);
+ mCurrentDialog.showErrorMessage(error);
}
private void handleHideDialog(boolean userCanceled) {
@@ -212,7 +236,7 @@ public class BiometricDialogImpl extends SystemUI implements CommandQueue.Callba
}
mReceiver = null;
mDialogShowing = false;
- mDialogView.startDismiss();
+ mCurrentDialog.startDismiss();
}
private void handleButtonNegative() {
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/BiometricDialogView.java b/packages/SystemUI/src/com/android/systemui/biometrics/BiometricDialogView.java
new file mode 100644
index 000000000000..c90861e4af52
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/BiometricDialogView.java
@@ -0,0 +1,363 @@
+/*
+ * Copyright (C) 2018 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.systemui.biometrics;
+
+import android.content.Context;
+import android.graphics.Color;
+import android.graphics.PixelFormat;
+import android.hardware.biometrics.BiometricPrompt;
+import android.os.Binder;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Message;
+import android.text.TextUtils;
+import android.util.DisplayMetrics;
+import android.util.Log;
+import android.view.KeyEvent;
+import android.view.LayoutInflater;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.WindowManager;
+import android.view.animation.Interpolator;
+import android.widget.Button;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import com.android.systemui.Interpolators;
+import com.android.systemui.R;
+
+/**
+ * Abstract base class. Shows a dialog for BiometricPrompt.
+ */
+public abstract class BiometricDialogView extends LinearLayout {
+
+ private static final String TAG = "BiometricDialogView";
+
+ private static final int ANIMATION_DURATION_SHOW = 250; // ms
+ private static final int ANIMATION_DURATION_AWAY = 350; // ms
+
+ private static final int MSG_CLEAR_MESSAGE = 1;
+
+ protected static final int STATE_NONE = 0;
+ protected static final int STATE_AUTHENTICATING = 1;
+ protected static final int STATE_ERROR = 2;
+ protected static final int STATE_AUTHENTICATED = 3;
+
+ private final IBinder mWindowToken = new Binder();
+ private final Interpolator mLinearOutSlowIn;
+ private final WindowManager mWindowManager;
+ private final float mAnimationTranslationOffset;
+ private final int mErrorColor;
+ private final int mTextColor;
+ private final float mDisplayWidth;
+ private final DialogViewCallback mCallback;
+
+ private ViewGroup mLayout;
+ private final TextView mErrorText;
+ private Bundle mBundle;
+ private final LinearLayout mDialog;
+ private int mLastState;
+ private boolean mAnimatingAway;
+ private boolean mWasForceRemoved;
+ protected boolean mRequireConfirmation;
+
+ protected abstract void updateIcon(int lastState, int newState);
+ protected abstract int getHintStringResourceId();
+ protected abstract int getAuthenticatedAccessibilityResourceId();
+ protected abstract int getIconDescriptionResourceId();
+
+ private final Runnable mShowAnimationRunnable = new Runnable() {
+ @Override
+ public void run() {
+ mLayout.animate()
+ .alpha(1f)
+ .setDuration(ANIMATION_DURATION_SHOW)
+ .setInterpolator(mLinearOutSlowIn)
+ .withLayer()
+ .start();
+ mDialog.animate()
+ .translationY(0)
+ .setDuration(ANIMATION_DURATION_SHOW)
+ .setInterpolator(mLinearOutSlowIn)
+ .withLayer()
+ .start();
+ }
+ };
+
+ private Handler mHandler = new Handler() {
+ @Override
+ public void handleMessage(Message msg) {
+ switch(msg.what) {
+ case MSG_CLEAR_MESSAGE:
+ handleClearMessage();
+ break;
+ default:
+ Log.e(TAG, "Unhandled message: " + msg.what);
+ break;
+ }
+ }
+ };
+
+ public BiometricDialogView(Context context, DialogViewCallback callback) {
+ super(context);
+ mCallback = callback;
+ mLinearOutSlowIn = Interpolators.LINEAR_OUT_SLOW_IN;
+ mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
+ mAnimationTranslationOffset = getResources()
+ .getDimension(R.dimen.biometric_dialog_animation_translation_offset);
+ mErrorColor = Color.parseColor(
+ getResources().getString(R.color.biometric_dialog_error_color));
+ mTextColor = Color.parseColor(
+ getResources().getString(R.color.biometric_dialog_text_light_color));
+
+ DisplayMetrics metrics = new DisplayMetrics();
+ mWindowManager.getDefaultDisplay().getMetrics(metrics);
+ mDisplayWidth = metrics.widthPixels;
+
+ // Create the dialog
+ LayoutInflater factory = LayoutInflater.from(getContext());
+ mLayout = (ViewGroup) factory.inflate(R.layout.biometric_dialog, this, false);
+ addView(mLayout);
+
+ mDialog = mLayout.findViewById(R.id.dialog);
+
+ mErrorText = mLayout.findViewById(R.id.error);
+
+ mLayout.setOnKeyListener(new View.OnKeyListener() {
+ boolean downPressed = false;
+ @Override
+ public boolean onKey(View v, int keyCode, KeyEvent event) {
+ if (keyCode != KeyEvent.KEYCODE_BACK) {
+ return false;
+ }
+ if (event.getAction() == KeyEvent.ACTION_DOWN && downPressed == false) {
+ downPressed = true;
+ } else if (event.getAction() == KeyEvent.ACTION_DOWN) {
+ downPressed = false;
+ } else if (event.getAction() == KeyEvent.ACTION_UP && downPressed == true) {
+ downPressed = false;
+ mCallback.onUserCanceled();
+ }
+ return true;
+ }
+ });
+
+ final View space = mLayout.findViewById(R.id.space);
+ final View leftSpace = mLayout.findViewById(R.id.left_space);
+ final View rightSpace = mLayout.findViewById(R.id.right_space);
+ final Button negative = mLayout.findViewById(R.id.button2);
+ final Button positive = mLayout.findViewById(R.id.button1);
+ final ImageView icon = mLayout.findViewById(R.id.biometric_icon);
+
+ icon.setContentDescription(getResources().getString(getIconDescriptionResourceId()));
+ mErrorText.setText(getResources().getString(getHintStringResourceId()));
+
+ setDismissesDialog(space);
+ setDismissesDialog(leftSpace);
+ setDismissesDialog(rightSpace);
+
+ negative.setOnClickListener((View v) -> {
+ mCallback.onNegativePressed();
+ });
+
+ positive.setOnClickListener((View v) -> {
+ mCallback.onPositivePressed();
+ });
+
+ mLayout.setFocusableInTouchMode(true);
+ mLayout.requestFocus();
+ }
+
+ @Override
+ public void onAttachedToWindow() {
+ super.onAttachedToWindow();
+
+ final TextView title = mLayout.findViewById(R.id.title);
+ final TextView subtitle = mLayout.findViewById(R.id.subtitle);
+ final TextView description = mLayout.findViewById(R.id.description);
+ final Button negative = mLayout.findViewById(R.id.button2);
+ final Button positive = mLayout.findViewById(R.id.button1);
+
+ mDialog.getLayoutParams().width = (int) mDisplayWidth;
+
+ mLastState = STATE_NONE;
+ updateState(STATE_AUTHENTICATING);
+
+ title.setText(mBundle.getCharSequence(BiometricPrompt.KEY_TITLE));
+ title.setSelected(true);
+
+ positive.setVisibility(View.INVISIBLE);
+
+ final CharSequence subtitleText = mBundle.getCharSequence(BiometricPrompt.KEY_SUBTITLE);
+ if (TextUtils.isEmpty(subtitleText)) {
+ subtitle.setVisibility(View.GONE);
+ } else {
+ subtitle.setVisibility(View.VISIBLE);
+ subtitle.setText(subtitleText);
+ }
+
+ final CharSequence descriptionText = mBundle.getCharSequence(BiometricPrompt.KEY_DESCRIPTION);
+ if (TextUtils.isEmpty(descriptionText)) {
+ description.setVisibility(View.GONE);
+ } else {
+ description.setVisibility(View.VISIBLE);
+ description.setText(descriptionText);
+ }
+
+ negative.setText(mBundle.getCharSequence(BiometricPrompt.KEY_NEGATIVE_TEXT));
+
+ if (!mWasForceRemoved) {
+ // Dim the background and slide the dialog up
+ mDialog.setTranslationY(mAnimationTranslationOffset);
+ mLayout.setAlpha(0f);
+ postOnAnimation(mShowAnimationRunnable);
+ } else {
+ // Show the dialog immediately
+ mLayout.animate().cancel();
+ mDialog.animate().cancel();
+ mDialog.setAlpha(1.0f);
+ mDialog.setTranslationY(0);
+ mLayout.setAlpha(1.0f);
+ }
+ mWasForceRemoved = false;
+ }
+
+ private void setDismissesDialog(View v) {
+ v.setClickable(true);
+ v.setOnTouchListener((View view, MotionEvent event) -> {
+ mCallback.onUserCanceled();
+ return true;
+ });
+ }
+
+ public void startDismiss() {
+ mAnimatingAway = true;
+
+ final Runnable endActionRunnable = new Runnable() {
+ @Override
+ public void run() {
+ mWindowManager.removeView(BiometricDialogView.this);
+ mAnimatingAway = false;
+ }
+ };
+
+ postOnAnimation(new Runnable() {
+ @Override
+ public void run() {
+ mLayout.animate()
+ .alpha(0f)
+ .setDuration(ANIMATION_DURATION_AWAY)
+ .setInterpolator(mLinearOutSlowIn)
+ .withLayer()
+ .start();
+ mDialog.animate()
+ .translationY(mAnimationTranslationOffset)
+ .setDuration(ANIMATION_DURATION_AWAY)
+ .setInterpolator(mLinearOutSlowIn)
+ .withLayer()
+ .withEndAction(endActionRunnable)
+ .start();
+ }
+ });
+ }
+
+ /**
+ * Force remove the window, cancelling any animation that's happening. This should only be
+ * called if we want to quickly show the dialog again (e.g. on rotation). Calling this method
+ * will cause the dialog to show without an animation the next time it's attached.
+ */
+ public void forceRemove() {
+ mLayout.animate().cancel();
+ mDialog.animate().cancel();
+ mWindowManager.removeView(BiometricDialogView.this);
+ mAnimatingAway = false;
+ mWasForceRemoved = true;
+ }
+
+ public boolean isAnimatingAway() {
+ return mAnimatingAway;
+ }
+
+ public void setBundle(Bundle bundle) {
+ mBundle = bundle;
+ }
+
+ public void setRequireConfirmation(boolean requireConfirmation) {
+ mRequireConfirmation = requireConfirmation;
+ }
+
+ public boolean requiresConfirmation() {
+ return mRequireConfirmation;
+ }
+
+ public void showConfirmationButton() {
+ final Button positive = mLayout.findViewById(R.id.button1);
+ positive.setVisibility(View.VISIBLE);
+ }
+
+ public ViewGroup getLayout() {
+ return mLayout;
+ }
+
+ // Clears the temporary message and shows the help message.
+ private void handleClearMessage() {
+ updateState(STATE_AUTHENTICATING);
+ mErrorText.setText(getHintStringResourceId());
+ mErrorText.setTextColor(mTextColor);
+ }
+
+ // Shows an error/help message
+ private void showTemporaryMessage(String message) {
+ mHandler.removeMessages(MSG_CLEAR_MESSAGE);
+ updateState(STATE_ERROR);
+ mErrorText.setText(message);
+ mErrorText.setTextColor(mErrorColor);
+ mErrorText.setContentDescription(message);
+ mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_CLEAR_MESSAGE),
+ BiometricPrompt.HIDE_DIALOG_DELAY);
+ }
+
+ public void showHelpMessage(String message) {
+ showTemporaryMessage(message);
+ }
+
+ public void showErrorMessage(String error) {
+ showTemporaryMessage(error);
+ mCallback.onErrorShown();
+ }
+
+ private void updateState(int newState) {
+ updateIcon(mLastState, newState);
+ mLastState = newState;
+ }
+
+ public WindowManager.LayoutParams getLayoutParams() {
+ final WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
+ ViewGroup.LayoutParams.MATCH_PARENT,
+ ViewGroup.LayoutParams.MATCH_PARENT,
+ WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL,
+ WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED,
+ PixelFormat.TRANSLUCENT);
+ lp.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
+ lp.setTitle("BiometricDialogView");
+ lp.token = mWindowToken;
+ return lp;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/FaceDialogView.java b/packages/SystemUI/src/com/android/systemui/biometrics/FaceDialogView.java
new file mode 100644
index 000000000000..feef3a6dc133
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/FaceDialogView.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2018 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.systemui.biometrics;
+
+import android.content.Context;
+import android.graphics.drawable.Drawable;
+import android.widget.ImageView;
+
+import com.android.systemui.R;
+
+/**
+ * This class loads the view for the system-provided dialog. The view consists of:
+ * Application Icon, Title, Subtitle, Description, Fingerprint Icon, Error/Help message area,
+ * and positive/negative buttons.
+ */
+public class FaceDialogView extends BiometricDialogView {
+ public FaceDialogView(Context context,
+ DialogViewCallback callback) {
+ super(context, callback);
+ }
+
+ @Override
+ protected int getHintStringResourceId() {
+ return R.string.face_dialog_looking_for_face;
+ }
+
+ @Override
+ protected int getAuthenticatedAccessibilityResourceId() {
+ if (mRequireConfirmation) {
+ return com.android.internal.R.string.face_authenticated_confirmation_required;
+ } else {
+ return com.android.internal.R.string.face_authenticated_no_confirmation_required;
+ }
+ }
+
+ @Override
+ protected int getIconDescriptionResourceId() {
+ return R.string.accessibility_face_dialog_face_icon;
+ }
+
+ @Override
+ protected void updateIcon(int lastState, int newState) {
+ Drawable icon = mContext.getDrawable(R.drawable.face_dialog_icon);
+
+ final ImageView faceIcon = getLayout().findViewById(R.id.biometric_icon);
+ faceIcon.setImageDrawable(icon);
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/FingerprintDialogView.java b/packages/SystemUI/src/com/android/systemui/biometrics/FingerprintDialogView.java
index 68c2c42dd961..38a69a90f0bb 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/FingerprintDialogView.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/FingerprintDialogView.java
@@ -17,32 +17,11 @@
package com.android.systemui.biometrics;
import android.content.Context;
-import android.graphics.Color;
-import android.graphics.PixelFormat;
import android.graphics.drawable.AnimatedVectorDrawable;
import android.graphics.drawable.Drawable;
-import android.hardware.biometrics.BiometricPrompt;
-import android.os.Binder;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.IBinder;
-import android.os.Message;
-import android.text.TextUtils;
-import android.util.DisplayMetrics;
import android.util.Log;
-import android.view.KeyEvent;
-import android.view.LayoutInflater;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.WindowManager;
-import android.view.animation.Interpolator;
-import android.widget.Button;
import android.widget.ImageView;
-import android.widget.LinearLayout;
-import android.widget.TextView;
-import com.android.systemui.Interpolators;
import com.android.systemui.R;
/**
@@ -50,288 +29,27 @@ import com.android.systemui.R;
* Application Icon, Title, Subtitle, Description, Fingerprint Icon, Error/Help message area,
* and positive/negative buttons.
*/
-public class FingerprintDialogView extends LinearLayout {
-
+public class FingerprintDialogView extends BiometricDialogView {
private static final String TAG = "FingerprintDialogView";
- private static final int ANIMATION_DURATION_SHOW = 250; // ms
- private static final int ANIMATION_DURATION_AWAY = 350; // ms
-
- private static final int MSG_CLEAR_MESSAGE = 1;
-
- private static final int STATE_NONE = 0;
- private static final int STATE_FINGERPRINT = 1;
- private static final int STATE_FINGERPRINT_ERROR = 2;
- private static final int STATE_FINGERPRINT_AUTHENTICATED = 3;
-
- private final IBinder mWindowToken = new Binder();
- private final Interpolator mLinearOutSlowIn;
- private final WindowManager mWindowManager;
- private final float mAnimationTranslationOffset;
- private final int mErrorColor;
- private final int mTextColor;
- private final int mFingerprintColor;
- private final float mDisplayWidth;
- private final DialogViewCallback mCallback;
-
- private ViewGroup mLayout;
- private final TextView mErrorText;
- private Bundle mBundle;
- private final LinearLayout mDialog;
- private int mLastState;
- private boolean mAnimatingAway;
- private boolean mWasForceRemoved;
-
- private final Runnable mShowAnimationRunnable = new Runnable() {
- @Override
- public void run() {
- mLayout.animate()
- .alpha(1f)
- .setDuration(ANIMATION_DURATION_SHOW)
- .setInterpolator(mLinearOutSlowIn)
- .withLayer()
- .start();
- mDialog.animate()
- .translationY(0)
- .setDuration(ANIMATION_DURATION_SHOW)
- .setInterpolator(mLinearOutSlowIn)
- .withLayer()
- .start();
- }
- };
-
- private Handler mHandler = new Handler() {
- @Override
- public void handleMessage(Message msg) {
- switch(msg.what) {
- case MSG_CLEAR_MESSAGE:
- handleClearMessage();
- break;
- default:
- Log.e(TAG, "Unhandled message: " + msg.what);
- break;
- }
- }
- };
-
- public FingerprintDialogView(Context context, DialogViewCallback callback) {
- super(context);
- mCallback = callback;
- mLinearOutSlowIn = Interpolators.LINEAR_OUT_SLOW_IN;
- mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
- mAnimationTranslationOffset = getResources()
- .getDimension(R.dimen.fingerprint_dialog_animation_translation_offset);
- mErrorColor = Color.parseColor(
- getResources().getString(R.color.fingerprint_dialog_error_color));
- mTextColor = Color.parseColor(
- getResources().getString(R.color.fingerprint_dialog_text_light_color));
- mFingerprintColor = Color.parseColor(
- getResources().getString(R.color.fingerprint_dialog_fingerprint_color));
-
- DisplayMetrics metrics = new DisplayMetrics();
- mWindowManager.getDefaultDisplay().getMetrics(metrics);
- mDisplayWidth = metrics.widthPixels;
-
- // Create the dialog
- LayoutInflater factory = LayoutInflater.from(getContext());
- mLayout = (ViewGroup) factory.inflate(R.layout.fingerprint_dialog, this, false);
- addView(mLayout);
-
- mDialog = mLayout.findViewById(R.id.dialog);
-
- mErrorText = mLayout.findViewById(R.id.error);
-
- mLayout.setOnKeyListener(new View.OnKeyListener() {
- boolean downPressed = false;
- @Override
- public boolean onKey(View v, int keyCode, KeyEvent event) {
- if (keyCode != KeyEvent.KEYCODE_BACK) {
- return false;
- }
- if (event.getAction() == KeyEvent.ACTION_DOWN && downPressed == false) {
- downPressed = true;
- } else if (event.getAction() == KeyEvent.ACTION_DOWN) {
- downPressed = false;
- } else if (event.getAction() == KeyEvent.ACTION_UP && downPressed == true) {
- downPressed = false;
- mCallback.onUserCanceled();
- }
- return true;
- }
- });
-
- final View space = mLayout.findViewById(R.id.space);
- final View leftSpace = mLayout.findViewById(R.id.left_space);
- final View rightSpace = mLayout.findViewById(R.id.right_space);
- final Button negative = mLayout.findViewById(R.id.button2);
- final Button positive = mLayout.findViewById(R.id.button1);
-
- setDismissesDialog(space);
- setDismissesDialog(leftSpace);
- setDismissesDialog(rightSpace);
-
- negative.setOnClickListener((View v) -> {
- mCallback.onNegativePressed();
- });
-
- positive.setOnClickListener((View v) -> {
- mCallback.onPositivePressed();
- });
-
- mLayout.setFocusableInTouchMode(true);
- mLayout.requestFocus();
- }
-
@Override
- public void onAttachedToWindow() {
- super.onAttachedToWindow();
-
- final TextView title = mLayout.findViewById(R.id.title);
- final TextView subtitle = mLayout.findViewById(R.id.subtitle);
- final TextView description = mLayout.findViewById(R.id.description);
- final Button negative = mLayout.findViewById(R.id.button2);
- final Button positive = mLayout.findViewById(R.id.button1);
-
- mDialog.getLayoutParams().width = (int) mDisplayWidth;
-
- mLastState = STATE_NONE;
- updateFingerprintIcon(STATE_FINGERPRINT);
-
- title.setText(mBundle.getCharSequence(BiometricPrompt.KEY_TITLE));
- title.setSelected(true);
-
- final CharSequence subtitleText = mBundle.getCharSequence(BiometricPrompt.KEY_SUBTITLE);
- if (TextUtils.isEmpty(subtitleText)) {
- subtitle.setVisibility(View.GONE);
- } else {
- subtitle.setVisibility(View.VISIBLE);
- subtitle.setText(subtitleText);
- }
-
- final CharSequence descriptionText = mBundle.getCharSequence(BiometricPrompt.KEY_DESCRIPTION);
- if (TextUtils.isEmpty(descriptionText)) {
- description.setVisibility(View.GONE);
- } else {
- description.setVisibility(View.VISIBLE);
- description.setText(descriptionText);
- }
-
- negative.setText(mBundle.getCharSequence(BiometricPrompt.KEY_NEGATIVE_TEXT));
-
- final CharSequence positiveText =
- mBundle.getCharSequence(BiometricPrompt.KEY_POSITIVE_TEXT);
- positive.setText(positiveText); // needs to be set for marquee to work
- if (positiveText != null) {
- positive.setVisibility(View.VISIBLE);
- } else {
- positive.setVisibility(View.GONE);
- }
-
- if (!mWasForceRemoved) {
- // Dim the background and slide the dialog up
- mDialog.setTranslationY(mAnimationTranslationOffset);
- mLayout.setAlpha(0f);
- postOnAnimation(mShowAnimationRunnable);
- } else {
- // Show the dialog immediately
- mLayout.animate().cancel();
- mDialog.animate().cancel();
- mDialog.setAlpha(1.0f);
- mDialog.setTranslationY(0);
- mLayout.setAlpha(1.0f);
- }
- mWasForceRemoved = false;
- }
-
- private void setDismissesDialog(View v) {
- v.setClickable(true);
- v.setOnTouchListener((View view, MotionEvent event) -> {
- mCallback.onUserCanceled();
- return true;
- });
- }
-
- public void startDismiss() {
- mAnimatingAway = true;
-
- final Runnable endActionRunnable = new Runnable() {
- @Override
- public void run() {
- mWindowManager.removeView(FingerprintDialogView.this);
- mAnimatingAway = false;
- }
- };
-
- postOnAnimation(new Runnable() {
- @Override
- public void run() {
- mLayout.animate()
- .alpha(0f)
- .setDuration(ANIMATION_DURATION_AWAY)
- .setInterpolator(mLinearOutSlowIn)
- .withLayer()
- .start();
- mDialog.animate()
- .translationY(mAnimationTranslationOffset)
- .setDuration(ANIMATION_DURATION_AWAY)
- .setInterpolator(mLinearOutSlowIn)
- .withLayer()
- .withEndAction(endActionRunnable)
- .start();
- }
- });
- }
-
- /**
- * Force remove the window, cancelling any animation that's happening. This should only be
- * called if we want to quickly show the dialog again (e.g. on rotation). Calling this method
- * will cause the dialog to show without an animation the next time it's attached.
- */
- public void forceRemove() {
- mLayout.animate().cancel();
- mDialog.animate().cancel();
- mWindowManager.removeView(FingerprintDialogView.this);
- mAnimatingAway = false;
- mWasForceRemoved = true;
+ protected int getHintStringResourceId() {
+ return R.string.fingerprint_dialog_touch_sensor;
}
- public boolean isAnimatingAway() {
- return mAnimatingAway;
- }
-
- public void setBundle(Bundle bundle) {
- mBundle = bundle;
- }
-
- // Clears the temporary message and shows the help message.
- private void handleClearMessage() {
- updateFingerprintIcon(STATE_FINGERPRINT);
- mErrorText.setText(R.string.fingerprint_dialog_touch_sensor);
- mErrorText.setTextColor(mTextColor);
- }
-
- // Shows an error/help message
- private void showTemporaryMessage(String message) {
- mHandler.removeMessages(MSG_CLEAR_MESSAGE);
- updateFingerprintIcon(STATE_FINGERPRINT_ERROR);
- mErrorText.setText(message);
- mErrorText.setTextColor(mErrorColor);
- mErrorText.setContentDescription(message);
- mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_CLEAR_MESSAGE),
- BiometricPrompt.HIDE_DIALOG_DELAY);
- }
-
- public void showHelpMessage(String message) {
- showTemporaryMessage(message);
+ @Override
+ protected int getAuthenticatedAccessibilityResourceId() {
+ return com.android.internal.R.string.fingerprint_authenticated;
}
- public void showErrorMessage(String error) {
- showTemporaryMessage(error);
- mCallback.onErrorShown();
+ @Override
+ protected int getIconDescriptionResourceId() {
+ return R.string.accessibility_fingerprint_dialog_fingerprint_icon;
}
- private void updateFingerprintIcon(int newState) {
- Drawable icon = getAnimationForTransition(mLastState, newState);
+ @Override
+ protected void updateIcon(int lastState, int newState) {
+ Drawable icon = getAnimationForTransition(lastState, newState);
if (icon == null) {
Log.e(TAG, "Animation not found");
@@ -342,25 +60,28 @@ public class FingerprintDialogView extends LinearLayout {
? (AnimatedVectorDrawable) icon
: null;
- final ImageView fingerprint_icon = mLayout.findViewById(R.id.fingerprint_icon);
- fingerprint_icon.setImageDrawable(icon);
+ final ImageView fingerprintIcon = getLayout().findViewById(R.id.biometric_icon);
+ fingerprintIcon.setImageDrawable(icon);
- if (animation != null && shouldAnimateForTransition(mLastState, newState)) {
+ if (animation != null && shouldAnimateForTransition(lastState, newState)) {
animation.forceAnimationOnUI();
animation.start();
}
+ }
- mLastState = newState;
+ public FingerprintDialogView(Context context,
+ DialogViewCallback callback) {
+ super(context, callback);
}
private boolean shouldAnimateForTransition(int oldState, int newState) {
- if (oldState == STATE_NONE && newState == STATE_FINGERPRINT) {
+ if (oldState == STATE_NONE && newState == STATE_AUTHENTICATING) {
return false;
- } else if (oldState == STATE_FINGERPRINT && newState == STATE_FINGERPRINT_ERROR) {
+ } else if (oldState == STATE_AUTHENTICATING && newState == STATE_ERROR) {
return true;
- } else if (oldState == STATE_FINGERPRINT_ERROR && newState == STATE_FINGERPRINT) {
+ } else if (oldState == STATE_ERROR && newState == STATE_AUTHENTICATING) {
return true;
- } else if (oldState == STATE_FINGERPRINT && newState == STATE_FINGERPRINT_AUTHENTICATED) {
+ } else if (oldState == STATE_AUTHENTICATING && newState == STATE_AUTHENTICATED) {
// TODO(b/77328470): add animation when fingerprint is authenticated
return false;
}
@@ -369,32 +90,18 @@ public class FingerprintDialogView extends LinearLayout {
private Drawable getAnimationForTransition(int oldState, int newState) {
int iconRes;
- if (oldState == STATE_NONE && newState == STATE_FINGERPRINT) {
+ if (oldState == STATE_NONE && newState == STATE_AUTHENTICATING) {
iconRes = R.drawable.fingerprint_dialog_fp_to_error;
- } else if (oldState == STATE_FINGERPRINT && newState == STATE_FINGERPRINT_ERROR) {
+ } else if (oldState == STATE_AUTHENTICATING && newState == STATE_ERROR) {
iconRes = R.drawable.fingerprint_dialog_fp_to_error;
- } else if (oldState == STATE_FINGERPRINT_ERROR && newState == STATE_FINGERPRINT) {
+ } else if (oldState == STATE_ERROR && newState == STATE_AUTHENTICATING) {
iconRes = R.drawable.fingerprint_dialog_error_to_fp;
- } else if (oldState == STATE_FINGERPRINT && newState == STATE_FINGERPRINT_AUTHENTICATED) {
+ } else if (oldState == STATE_AUTHENTICATING && newState == STATE_AUTHENTICATED) {
// TODO(b/77328470): add animation when fingerprint is authenticated
iconRes = R.drawable.fingerprint_dialog_error_to_fp;
- }
- else {
+ } else {
return null;
}
return mContext.getDrawable(iconRes);
}
-
- public WindowManager.LayoutParams getLayoutParams() {
- final WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
- ViewGroup.LayoutParams.MATCH_PARENT,
- ViewGroup.LayoutParams.MATCH_PARENT,
- WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL,
- WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED,
- PixelFormat.TRANSLUCENT);
- lp.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
- lp.setTitle("FingerprintDialogView");
- lp.token = mWindowToken;
- return lp;
- }
-}
+} \ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
index e19c8441c44d..5c0b3289c61a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
@@ -161,7 +161,7 @@ public class CommandQueue extends IStatusBar.Stub {
default void onRotationProposal(int rotation, boolean isValid) { }
default void showBiometricDialog(Bundle bundle, IBiometricPromptReceiver receiver,
- int type) { }
+ int type, boolean requireConfirmation) { }
default void onBiometricAuthenticated() { }
default void onBiometricHelp(String message) { }
default void onBiometricError(String error) { }
@@ -514,12 +514,14 @@ public class CommandQueue extends IStatusBar.Stub {
}
@Override
- public void showBiometricDialog(Bundle bundle, IBiometricPromptReceiver receiver, int type) {
+ public void showBiometricDialog(Bundle bundle, IBiometricPromptReceiver receiver, int type,
+ boolean requireConfirmation) {
synchronized (mLock) {
SomeArgs args = SomeArgs.obtain();
args.arg1 = bundle;
args.arg2 = receiver;
args.argi1 = type;
+ args.arg3 = requireConfirmation;
mHandler.obtainMessage(MSG_BIOMETRIC_SHOW, args)
.sendToTarget();
}
@@ -763,7 +765,8 @@ public class CommandQueue extends IStatusBar.Stub {
mCallbacks.get(i).showBiometricDialog(
(Bundle) someArgs.arg1,
(IBiometricPromptReceiver) someArgs.arg2,
- someArgs.argi1);
+ someArgs.argi1,
+ (boolean) someArgs.arg3);
}
someArgs.recycle();
break;
diff --git a/services/core/java/com/android/server/biometrics/AuthenticationClient.java b/services/core/java/com/android/server/biometrics/AuthenticationClient.java
index 6b09f1bab364..65e55d66a4bb 100644
--- a/services/core/java/com/android/server/biometrics/AuthenticationClient.java
+++ b/services/core/java/com/android/server/biometrics/AuthenticationClient.java
@@ -26,10 +26,13 @@ import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.RemoteException;
+import android.security.KeyStore;
import android.util.Slog;
import com.android.internal.statusbar.IStatusBarService;
+import java.util.ArrayList;
+
/**
* A class to keep track of the authentication state for a given client.
*/
@@ -50,28 +53,68 @@ public abstract class AuthenticationClient extends ClientMonitor {
public static final int LOCKOUT_TIMED = 1;
public static final int LOCKOUT_PERMANENT = 2;
+ private final boolean mRequireConfirmation;
// Callback mechanism received from the client
// (BiometricPrompt -> BiometricPromptService -> <Biometric>Service -> AuthenticationClient)
private IBiometricPromptReceiver mDialogReceiverFromClient;
private Bundle mBundle;
private IStatusBarService mStatusBarService;
private boolean mInLockout;
+ private TokenEscrow mEscrow;
protected boolean mDialogDismissed;
+ /**
+ * Container that holds the identifier and authToken. For biometrics that require user
+ * confirmation, these should not be sent to their final destinations until the user confirms.
+ */
+ class TokenEscrow {
+ final BiometricAuthenticator.Identifier mIdentifier;
+ final ArrayList<Byte> mToken;
+
+ TokenEscrow(BiometricAuthenticator.Identifier identifier, ArrayList<Byte> token) {
+ mIdentifier = identifier;
+ mToken = token;
+ }
+
+ BiometricAuthenticator.Identifier getIdentifier() {
+ return mIdentifier;
+ }
+
+ ArrayList<Byte> getToken() {
+ return mToken;
+ }
+ }
+
// Receives events from SystemUI and handles them before forwarding them to BiometricDialog
protected IBiometricPromptReceiver mDialogReceiver = new IBiometricPromptReceiver.Stub() {
@Override // binder call
public void onDialogDismissed(int reason) {
if (mBundle != null && mDialogReceiverFromClient != null) {
try {
- mDialogReceiverFromClient.onDialogDismissed(reason);
+ if (reason != BiometricPrompt.DISMISSED_REASON_POSITIVE) {
+ // Positive button is used by passive modalities as a "confirm" button,
+ // do not send to client
+ mDialogReceiverFromClient.onDialogDismissed(reason);
+ }
if (reason == BiometricPrompt.DISMISSED_REASON_USER_CANCEL) {
onError(getHalDeviceId(), BiometricConstants.BIOMETRIC_ERROR_USER_CANCELED,
0 /* vendorCode */);
+ } else if (reason == BiometricPrompt.DISMISSED_REASON_POSITIVE) {
+ // Have the service send the token to KeyStore, and send onAuthenticated
+ // to the application.
+ if (mEscrow != null) {
+ if (DEBUG) Slog.d(getLogTag(), "Confirmed");
+ addTokenToKeyStore(mEscrow.getToken());
+ notifyClientAuthenticationSucceeded(mEscrow.getIdentifier());
+ mEscrow = null;
+ onAuthenticationConfirmed();
+ } else {
+ Slog.e(getLogTag(), "Escrow is null!!!");
+ }
}
mDialogDismissed = true;
} catch (RemoteException e) {
- Slog.e(getLogTag(), "Unable to notify dialog dismissed", e);
+ Slog.e(getLogTag(), "Remote exception", e);
}
stop(true /* initiatedByClient */);
}
@@ -89,11 +132,18 @@ public abstract class AuthenticationClient extends ClientMonitor {
*/
public abstract void onStop();
+ /**
+ * This method is called when biometric authentication was confirmed by the user. The client
+ * should be removed.
+ */
+ public abstract void onAuthenticationConfirmed();
+
public AuthenticationClient(Context context, Metrics metrics,
BiometricService.DaemonWrapper daemon, long halDeviceId, IBinder token,
BiometricService.ServiceListener listener, int targetUserId, int groupId, long opId,
boolean restricted, String owner, Bundle bundle,
- IBiometricPromptReceiver dialogReceiver, IStatusBarService statusBarService) {
+ IBiometricPromptReceiver dialogReceiver, IStatusBarService statusBarService,
+ boolean requireConfirmation) {
super(context, metrics, daemon, halDeviceId, token, listener, targetUserId, groupId,
restricted, owner);
mOpId = opId;
@@ -101,6 +151,7 @@ public abstract class AuthenticationClient extends ClientMonitor {
mDialogReceiverFromClient = dialogReceiver;
mStatusBarService = statusBarService;
mHandler = new Handler(Looper.getMainLooper());
+ mRequireConfirmation = requireConfirmation;
}
@Override
@@ -154,9 +205,41 @@ public abstract class AuthenticationClient extends ClientMonitor {
return super.onError(deviceId, error, vendorCode);
}
+ private void notifyClientAuthenticationSucceeded(BiometricAuthenticator.Identifier identifier)
+ throws RemoteException {
+ final BiometricService.ServiceListener listener = getListener();
+ // Explicitly have if/else here to make it super obvious in case the code is
+ // touched in the future.
+ if (!getIsRestricted()) {
+ listener.onAuthenticationSucceeded(
+ getHalDeviceId(), identifier, getTargetUserId());
+ } else {
+ listener.onAuthenticationSucceeded(
+ getHalDeviceId(), null, getTargetUserId());
+ }
+ }
+
+ private void addTokenToKeyStore(ArrayList<Byte> token) {
+ // Send the token to KeyStore
+ final byte[] byteToken = new byte[token.size()];
+ for (int i = 0; i < token.size(); i++) {
+ byteToken[i] = token.get(i);
+ }
+ KeyStore.getInstance().addAuthToken(byteToken);
+ }
+
@Override
public boolean onAuthenticated(BiometricAuthenticator.Identifier identifier,
- boolean authenticated) {
+ boolean authenticated, ArrayList<Byte> token) {
+ if (authenticated) {
+ if (mRequireConfirmation) {
+ // Store the token so it can be sent to keystore after the user presses confirm
+ mEscrow = new TokenEscrow(identifier, token);
+ } else {
+ addTokenToKeyStore(token);
+ }
+ }
+
boolean result = false;
// If the biometric dialog is showing, notify authentication succeeded
@@ -184,15 +267,8 @@ public abstract class AuthenticationClient extends ClientMonitor {
Slog.v(getLogTag(), "onAuthenticated(owner=" + getOwnerString()
+ ", id=" + identifier.getBiometricId());
}
-
- // Explicitly have if/else here to make it super obvious in case the code is
- // touched in the future.
- if (!getIsRestricted()) {
- listener.onAuthenticationSucceeded(
- getHalDeviceId(), identifier, getTargetUserId());
- } else {
- listener.onAuthenticationSucceeded(
- getHalDeviceId(), null, getTargetUserId());
+ if (!mRequireConfirmation) {
+ notifyClientAuthenticationSucceeded(identifier);
}
}
} catch (RemoteException e) {
@@ -241,7 +317,8 @@ public abstract class AuthenticationClient extends ClientMonitor {
if (listener != null) {
vibrateSuccess();
}
- result |= true; // we have a valid biometric, done
+ // we have a valid biometric that doesn't require confirmation, done
+ result |= !mRequireConfirmation;
resetFailedAttempts();
onStop();
}
@@ -269,7 +346,7 @@ public abstract class AuthenticationClient extends ClientMonitor {
if (mBundle != null) {
try {
mStatusBarService.showBiometricDialog(mBundle, mDialogReceiver,
- getBiometricType());
+ getBiometricType(), mRequireConfirmation);
} catch (RemoteException e) {
Slog.e(getLogTag(), "Unable to show biometric dialog", e);
}
diff --git a/services/core/java/com/android/server/biometrics/BiometricPromptService.java b/services/core/java/com/android/server/biometrics/BiometricPromptService.java
index d1371d1e0bf5..35c9d3ed9a51 100644
--- a/services/core/java/com/android/server/biometrics/BiometricPromptService.java
+++ b/services/core/java/com/android/server/biometrics/BiometricPromptService.java
@@ -154,9 +154,9 @@ public class BiometricPromptService extends SystemService {
} else if (mCurrentModality == BIOMETRIC_IRIS) {
Slog.w(TAG, "Unsupported modality");
} else if (mCurrentModality == BIOMETRIC_FACE) {
- mFaceService.authenticateFromService(token, sessionId, userId,
- receiver, flags, opPackageName, bundle, dialogReceiver,
- callingUid, callingPid, callingUserId);
+ mFaceService.authenticateFromService(true /* requireConfirmation */, token,
+ sessionId, userId, receiver, flags, opPackageName, bundle,
+ dialogReceiver, callingUid, callingPid, callingUserId);
} else {
Slog.w(TAG, "Unsupported modality");
}
@@ -305,7 +305,9 @@ public class BiometricPromptService extends SystemService {
try {
receiver.onError(0 /* deviceId */,
BiometricConstants.BIOMETRIC_ERROR_NO_BIOMETRICS,
- hardwareUnavailable);
+ FaceManager.getErrorString(getContext(),
+ BiometricConstants.BIOMETRIC_ERROR_NO_BIOMETRICS,
+ 0 /* vendorCode */));
} catch (RemoteException e) {
Slog.e(TAG, "Unable to send error", e);
}
diff --git a/services/core/java/com/android/server/biometrics/BiometricService.java b/services/core/java/com/android/server/biometrics/BiometricService.java
index 73c4223b48f8..c9b740d203cf 100644
--- a/services/core/java/com/android/server/biometrics/BiometricService.java
+++ b/services/core/java/com/android/server/biometrics/BiometricService.java
@@ -51,7 +51,6 @@ import android.os.ServiceManager;
import android.os.SystemClock;
import android.os.UserHandle;
import android.os.UserManager;
-import android.security.KeyStore;
import android.util.Slog;
import android.util.SparseBooleanArray;
import android.util.SparseIntArray;
@@ -225,10 +224,10 @@ public abstract class BiometricService extends SystemService implements IHwBinde
IBinder token, ServiceListener listener, int targetUserId, int groupId, long opId,
boolean restricted, String owner, Bundle bundle,
IBiometricPromptReceiver dialogReceiver,
- IStatusBarService statusBarService) {
+ IStatusBarService statusBarService, boolean requireConfirmation) {
super(context, getMetrics(), daemon, halDeviceId, token, listener,
targetUserId, groupId, opId, restricted, owner, bundle, dialogReceiver,
- statusBarService);
+ statusBarService, requireConfirmation);
}
@Override
@@ -279,6 +278,11 @@ public abstract class BiometricService extends SystemService implements IHwBinde
}
return AuthenticationClient.LOCKOUT_NONE;
}
+
+ @Override
+ public void onAuthenticationConfirmed() {
+ removeClient(mCurrentClient);
+ }
}
protected class EnrollClientImpl extends EnrollClient {
@@ -587,14 +591,7 @@ public abstract class BiometricService extends SystemService implements IHwBinde
ClientMonitor client = mCurrentClient;
final boolean authenticated = identifier.getBiometricId() != 0;
- if (authenticated) {
- final byte[] byteToken = new byte[token.size()];
- for (int i = 0; i < token.size(); i++) {
- byteToken[i] = token.get(i);
- }
- KeyStore.getInstance().addAuthToken(byteToken);
- }
- if (client != null && client.onAuthenticated(identifier, authenticated)) {
+ if (client != null && client.onAuthenticated(identifier, authenticated, token)) {
removeClient(client);
}
if (authenticated) {
diff --git a/services/core/java/com/android/server/biometrics/ClientMonitor.java b/services/core/java/com/android/server/biometrics/ClientMonitor.java
index d30bed23ea97..408e26ab0efb 100644
--- a/services/core/java/com/android/server/biometrics/ClientMonitor.java
+++ b/services/core/java/com/android/server/biometrics/ClientMonitor.java
@@ -28,6 +28,7 @@ import android.util.Slog;
import com.android.internal.logging.MetricsLogger;
+import java.util.ArrayList;
import java.util.NoSuchElementException;
/**
@@ -128,7 +129,7 @@ public abstract class ClientMonitor implements IBinder.DeathRecipient {
public abstract boolean onEnrollResult(BiometricAuthenticator.Identifier identifier,
int remaining);
public abstract boolean onAuthenticated(BiometricAuthenticator.Identifier identifier,
- boolean authenticated);
+ boolean authenticated, ArrayList<Byte> token);
public abstract boolean onRemoved(BiometricAuthenticator.Identifier identifier,
int remaining);
public abstract boolean onEnumerationResult(
diff --git a/services/core/java/com/android/server/biometrics/EnrollClient.java b/services/core/java/com/android/server/biometrics/EnrollClient.java
index c305eca682be..7d186a925984 100644
--- a/services/core/java/com/android/server/biometrics/EnrollClient.java
+++ b/services/core/java/com/android/server/biometrics/EnrollClient.java
@@ -23,6 +23,7 @@ import android.os.IBinder;
import android.os.RemoteException;
import android.util.Slog;
+import java.util.ArrayList;
import java.util.Arrays;
/**
@@ -126,7 +127,7 @@ public abstract class EnrollClient extends ClientMonitor {
@Override
public boolean onAuthenticated(BiometricAuthenticator.Identifier identifier,
- boolean authenticated) {
+ boolean authenticated, ArrayList<Byte> token) {
if (DEBUG) Slog.w(getLogTag(), "onAuthenticated() called for enroll!");
return true; // Invalid for EnrollClient
}
diff --git a/services/core/java/com/android/server/biometrics/EnumerateClient.java b/services/core/java/com/android/server/biometrics/EnumerateClient.java
index b76376962c0e..159d95edf869 100644
--- a/services/core/java/com/android/server/biometrics/EnumerateClient.java
+++ b/services/core/java/com/android/server/biometrics/EnumerateClient.java
@@ -23,6 +23,8 @@ import android.os.IBinder;
import android.os.RemoteException;
import android.util.Slog;
+import java.util.ArrayList;
+
/**
* A class to keep track of the enumeration state for a given client.
*/
@@ -94,7 +96,7 @@ public abstract class EnumerateClient extends ClientMonitor {
@Override
public boolean onAuthenticated(BiometricAuthenticator.Identifier identifier,
- boolean authenticated) {
+ boolean authenticated, ArrayList<Byte> token) {
if (DEBUG) Slog.w(getLogTag(), "onAuthenticated() called for enumerate!");
return true; // Invalid for Enumerate.
}
diff --git a/services/core/java/com/android/server/biometrics/RemovalClient.java b/services/core/java/com/android/server/biometrics/RemovalClient.java
index 3bf7f0404b1e..1995b9c313d4 100644
--- a/services/core/java/com/android/server/biometrics/RemovalClient.java
+++ b/services/core/java/com/android/server/biometrics/RemovalClient.java
@@ -23,6 +23,8 @@ import android.os.IBinder;
import android.os.RemoteException;
import android.util.Slog;
+import java.util.ArrayList;
+
/**
* A class to keep track of the remove state for a given client.
*/
@@ -111,7 +113,7 @@ public abstract class RemovalClient extends ClientMonitor {
@Override
public boolean onAuthenticated(BiometricAuthenticator.Identifier identifier,
- boolean authenticated) {
+ boolean authenticated, ArrayList<Byte> token) {
if (DEBUG) Slog.w(getLogTag(), "onAuthenticated() called for remove!");
return true; // Invalid for Remove.
}
diff --git a/services/core/java/com/android/server/biometrics/face/FaceService.java b/services/core/java/com/android/server/biometrics/face/FaceService.java
index 660710e34947..376eabc92875 100644
--- a/services/core/java/com/android/server/biometrics/face/FaceService.java
+++ b/services/core/java/com/android/server/biometrics/face/FaceService.java
@@ -88,10 +88,11 @@ public class FaceService extends BiometricService {
DaemonWrapper daemon, long halDeviceId, IBinder token,
ServiceListener listener, int targetUserId, int groupId, long opId,
boolean restricted, String owner, Bundle bundle,
- IBiometricPromptReceiver dialogReceiver, IStatusBarService statusBarService) {
+ IBiometricPromptReceiver dialogReceiver, IStatusBarService statusBarService,
+ boolean requireConfirmation) {
super(context, daemon, halDeviceId, token, listener, targetUserId, groupId, opId,
- restricted,
- owner, bundle, dialogReceiver, statusBarService);
+ restricted, owner, bundle, dialogReceiver, statusBarService,
+ requireConfirmation);
}
@Override
@@ -159,15 +160,15 @@ public class FaceService extends BiometricService {
final AuthenticationClientImpl client = new FaceAuthClient(getContext(),
mDaemonWrapper, mHalDeviceId, token, new ServiceListenerImpl(receiver),
mCurrentUserId, 0 /* groupId */, opId, restricted, opPackageName,
- null /* bundle */, null /* dialogReceiver */, mStatusBarService);
-
+ null /* bundle */, null /* dialogReceiver */, mStatusBarService,
+ false /* requireConfirmation */);
authenticateInternal(client, opId, opPackageName);
}
@Override // Binder call
- public void authenticateFromService(IBinder token, long opId, int groupId,
- IBiometricPromptServiceReceiver receiver, int flags, String opPackageName,
- Bundle bundle, IBiometricPromptReceiver dialogReceiver,
+ public void authenticateFromService(boolean requireConfirmation, IBinder token, long opId,
+ int groupId, IBiometricPromptServiceReceiver receiver, int flags,
+ String opPackageName, Bundle bundle, IBiometricPromptReceiver dialogReceiver,
int callingUid, int callingPid, int callingUserId) {
checkPermission(USE_BIOMETRIC_INTERNAL);
final boolean restricted = true; // BiometricPrompt is always restricted
@@ -175,7 +176,7 @@ public class FaceService extends BiometricService {
mDaemonWrapper, mHalDeviceId, token,
new BiometricPromptServiceListenerImpl(receiver),
mCurrentUserId, 0 /* groupId */, opId, restricted, opPackageName,
- bundle, dialogReceiver, mStatusBarService);
+ bundle, dialogReceiver, mStatusBarService, true /* requireConfirmation */);
authenticateInternal(client, opId, opPackageName, callingUid, callingPid,
callingUserId);
}
diff --git a/services/core/java/com/android/server/biometrics/fingerprint/FingerprintService.java b/services/core/java/com/android/server/biometrics/fingerprint/FingerprintService.java
index 9f4fff8157a2..1852aa84d817 100644
--- a/services/core/java/com/android/server/biometrics/fingerprint/FingerprintService.java
+++ b/services/core/java/com/android/server/biometrics/fingerprint/FingerprintService.java
@@ -110,10 +110,11 @@ public class FingerprintService extends BiometricService {
DaemonWrapper daemon, long halDeviceId, IBinder token,
ServiceListener listener, int targetUserId, int groupId, long opId,
boolean restricted, String owner, Bundle bundle,
- IBiometricPromptReceiver dialogReceiver, IStatusBarService statusBarService) {
+ IBiometricPromptReceiver dialogReceiver, IStatusBarService statusBarService,
+ boolean requireConfirmation) {
super(context, daemon, halDeviceId, token, listener, targetUserId, groupId, opId,
- restricted,
- owner, bundle, dialogReceiver, statusBarService);
+ restricted, owner, bundle, dialogReceiver, statusBarService,
+ requireConfirmation);
}
@Override
@@ -182,8 +183,7 @@ public class FingerprintService extends BiometricService {
final AuthenticationClientImpl client = new FingerprintAuthClient(getContext(),
mDaemonWrapper, mHalDeviceId, token, new ServiceListenerImpl(receiver),
mCurrentUserId, groupId, opId, restricted, opPackageName, null /* bundle */,
- null /* dialogReceiver */, mStatusBarService);
-
+ null /* dialogReceiver */, mStatusBarService, false /* requireConfirmation */);
authenticateInternal(client, opId, opPackageName);
}
@@ -198,7 +198,7 @@ public class FingerprintService extends BiometricService {
mDaemonWrapper, mHalDeviceId, token,
new BiometricPromptServiceListenerImpl(receiver),
mCurrentUserId, groupId, opId, restricted, opPackageName, bundle,
- dialogReceiver, mStatusBarService);
+ dialogReceiver, mStatusBarService, false /* requireConfirmation */);
authenticateInternal(client, opId, opPackageName, callingUid, callingPid,
callingUserId);
}
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
index c2d8188649da..79eab6b12c10 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
@@ -565,11 +565,12 @@ public class StatusBarManagerService extends IStatusBarService.Stub {
}
@Override
- public void showBiometricDialog(Bundle bundle, IBiometricPromptReceiver receiver, int type) {
+ public void showBiometricDialog(Bundle bundle, IBiometricPromptReceiver receiver, int type,
+ boolean requireConfirmation) {
enforceBiometricDialog();
if (mBar != null) {
try {
- mBar.showBiometricDialog(bundle, receiver, type);
+ mBar.showBiometricDialog(bundle, receiver, type, requireConfirmation);
} catch (RemoteException ex) {
}
}