blob: a81043e22fe53c1834572036959d84ada75f9876 [file] [log] [blame]
Kevin Chynaae4a152018-01-18 11:48:09 -08001/*
2 * Copyright (C) 2018 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License
15 */
16
17package com.android.systemui.fingerprint;
18
Kevin Chyn42653e82018-01-19 14:15:46 -080019import android.content.Context;
Kevin Chynaae4a152018-01-18 11:48:09 -080020import android.content.pm.PackageManager;
Vishwath Mohanecf00ce2018-04-05 10:28:24 -070021import android.hardware.biometrics.BiometricPrompt;
22import android.hardware.biometrics.IBiometricPromptReceiver;
Kevin Chynaae4a152018-01-18 11:48:09 -080023import android.os.Bundle;
Kevin Chyn42653e82018-01-19 14:15:46 -080024import android.os.Handler;
25import android.os.Message;
26import android.os.RemoteException;
Kevin Chynaae4a152018-01-18 11:48:09 -080027import android.util.Log;
Kevin Chyn42653e82018-01-19 14:15:46 -080028import android.view.WindowManager;
Kevin Chynaae4a152018-01-18 11:48:09 -080029
Kevin Chyn42653e82018-01-19 14:15:46 -080030import com.android.internal.os.SomeArgs;
Kevin Chynaae4a152018-01-18 11:48:09 -080031import com.android.systemui.SystemUI;
32import com.android.systemui.statusbar.CommandQueue;
33
34public class FingerprintDialogImpl extends SystemUI implements CommandQueue.Callbacks {
35 private static final String TAG = "FingerprintDialogImpl";
Kevin Chyn42653e82018-01-19 14:15:46 -080036 private static final boolean DEBUG = true;
37
38 protected static final int MSG_SHOW_DIALOG = 1;
39 protected static final int MSG_FINGERPRINT_AUTHENTICATED = 2;
40 protected static final int MSG_FINGERPRINT_HELP = 3;
41 protected static final int MSG_FINGERPRINT_ERROR = 4;
42 protected static final int MSG_HIDE_DIALOG = 5;
43 protected static final int MSG_BUTTON_NEGATIVE = 6;
44 protected static final int MSG_USER_CANCELED = 7;
45 protected static final int MSG_BUTTON_POSITIVE = 8;
46 protected static final int MSG_CLEAR_MESSAGE = 9;
47
48
49 private FingerprintDialogView mDialogView;
50 private WindowManager mWindowManager;
Vishwath Mohanecf00ce2018-04-05 10:28:24 -070051 private IBiometricPromptReceiver mReceiver;
Kevin Chyn42653e82018-01-19 14:15:46 -080052 private boolean mDialogShowing;
53
54 private Handler mHandler = new Handler() {
55 @Override
56 public void handleMessage(Message msg) {
57 switch(msg.what) {
58 case MSG_SHOW_DIALOG:
59 handleShowDialog((SomeArgs) msg.obj);
60 break;
61 case MSG_FINGERPRINT_AUTHENTICATED:
62 handleFingerprintAuthenticated();
63 break;
64 case MSG_FINGERPRINT_HELP:
65 handleFingerprintHelp((String) msg.obj);
66 break;
67 case MSG_FINGERPRINT_ERROR:
68 handleFingerprintError((String) msg.obj);
69 break;
70 case MSG_HIDE_DIALOG:
71 handleHideDialog((Boolean) msg.obj);
72 break;
73 case MSG_BUTTON_NEGATIVE:
74 handleButtonNegative();
75 break;
76 case MSG_USER_CANCELED:
77 handleUserCanceled();
78 break;
79 case MSG_BUTTON_POSITIVE:
80 handleButtonPositive();
81 break;
82 case MSG_CLEAR_MESSAGE:
83 handleClearMessage();
84 break;
85 }
86 }
87 };
Kevin Chynaae4a152018-01-18 11:48:09 -080088
89 @Override
90 public void start() {
91 if (!mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_FINGERPRINT)) {
92 return;
93 }
94 getComponent(CommandQueue.class).addCallbacks(this);
Kevin Chyne8f3e1b2018-01-23 17:33:58 -080095 mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
Kevin Chyn42653e82018-01-19 14:15:46 -080096 mDialogView = new FingerprintDialogView(mContext, mHandler);
Kevin Chynaae4a152018-01-18 11:48:09 -080097 }
98
99 @Override
Vishwath Mohanecf00ce2018-04-05 10:28:24 -0700100 public void showFingerprintDialog(Bundle bundle, IBiometricPromptReceiver receiver) {
Kevin Chyn42653e82018-01-19 14:15:46 -0800101 if (DEBUG) Log.d(TAG, "showFingerprintDialog");
102 // Remove these messages as they are part of the previous client
103 mHandler.removeMessages(MSG_FINGERPRINT_ERROR);
104 mHandler.removeMessages(MSG_FINGERPRINT_HELP);
105 mHandler.removeMessages(MSG_FINGERPRINT_AUTHENTICATED);
106 SomeArgs args = SomeArgs.obtain();
107 args.arg1 = bundle;
108 args.arg2 = receiver;
109 mHandler.obtainMessage(MSG_SHOW_DIALOG, args).sendToTarget();
Kevin Chynaae4a152018-01-18 11:48:09 -0800110 }
111
112 @Override
113 public void onFingerprintAuthenticated() {
114 if (DEBUG) Log.d(TAG, "onFingerprintAuthenticated");
Kevin Chyn42653e82018-01-19 14:15:46 -0800115 mHandler.obtainMessage(MSG_FINGERPRINT_AUTHENTICATED).sendToTarget();
Kevin Chynaae4a152018-01-18 11:48:09 -0800116 }
117
118 @Override
119 public void onFingerprintHelp(String message) {
120 if (DEBUG) Log.d(TAG, "onFingerprintHelp: " + message);
Kevin Chyn42653e82018-01-19 14:15:46 -0800121 mHandler.obtainMessage(MSG_FINGERPRINT_HELP, message).sendToTarget();
Kevin Chynaae4a152018-01-18 11:48:09 -0800122 }
123
124 @Override
125 public void onFingerprintError(String error) {
126 if (DEBUG) Log.d(TAG, "onFingerprintError: " + error);
Kevin Chyn42653e82018-01-19 14:15:46 -0800127 mHandler.obtainMessage(MSG_FINGERPRINT_ERROR, error).sendToTarget();
Kevin Chynaae4a152018-01-18 11:48:09 -0800128 }
129
130 @Override
131 public void hideFingerprintDialog() {
132 if (DEBUG) Log.d(TAG, "hideFingerprintDialog");
Kevin Chyn42653e82018-01-19 14:15:46 -0800133 mHandler.obtainMessage(MSG_HIDE_DIALOG, false /* userCanceled */).sendToTarget();
134 }
135
136 private void handleShowDialog(SomeArgs args) {
Kevin Chyn87df0682018-04-10 19:29:23 -0700137 if (DEBUG) Log.d(TAG, "handleShowDialog, isAnimatingAway: "
138 + mDialogView.isAnimatingAway());
139 if (mDialogView.isAnimatingAway()) {
140 mDialogView.forceRemove();
141 } else if (mDialogShowing) {
Kevin Chyn42653e82018-01-19 14:15:46 -0800142 Log.w(TAG, "Dialog already showing");
143 return;
144 }
Vishwath Mohanecf00ce2018-04-05 10:28:24 -0700145 mReceiver = (IBiometricPromptReceiver) args.arg2;
Kevin Chyn42653e82018-01-19 14:15:46 -0800146 mDialogView.setBundle((Bundle)args.arg1);
147 mWindowManager.addView(mDialogView, mDialogView.getLayoutParams());
148 mDialogShowing = true;
149 }
150
151 private void handleFingerprintAuthenticated() {
152 if (DEBUG) Log.d(TAG, "handleFingerprintAuthenticated");
Kevin Chyn932e1df2018-03-26 11:53:47 -0700153 mDialogView.announceForAccessibility(
154 mContext.getResources().getText(
155 com.android.internal.R.string.fingerprint_authenticated));
Kevin Chyn42653e82018-01-19 14:15:46 -0800156 handleHideDialog(false /* userCanceled */);
157 }
158
159 private void handleFingerprintHelp(String message) {
160 if (DEBUG) Log.d(TAG, "handleFingerprintHelp: " + message);
161 mDialogView.showHelpMessage(message);
162 }
163
164 private void handleFingerprintError(String error) {
165 if (DEBUG) Log.d(TAG, "handleFingerprintError: " + error);
166 if (!mDialogShowing) {
167 if (DEBUG) Log.d(TAG, "Dialog already dismissed");
168 return;
169 }
170 mDialogView.showErrorMessage(error);
171 }
172
173 private void handleHideDialog(boolean userCanceled) {
Kevin Chyn87df0682018-04-10 19:29:23 -0700174 if (DEBUG) Log.d(TAG, "handleHideDialog, userCanceled: " + userCanceled);
Kevin Chyn42653e82018-01-19 14:15:46 -0800175 if (!mDialogShowing) {
176 // This can happen if there's a race and we get called from both
177 // onAuthenticated and onError, etc.
178 Log.w(TAG, "Dialog already dismissed, userCanceled: " + userCanceled);
179 return;
180 }
181 if (userCanceled) {
182 try {
Vishwath Mohanecf00ce2018-04-05 10:28:24 -0700183 mReceiver.onDialogDismissed(BiometricPrompt.DISMISSED_REASON_USER_CANCEL);
Kevin Chyn42653e82018-01-19 14:15:46 -0800184 } catch (RemoteException e) {
185 Log.e(TAG, "RemoteException when hiding dialog", e);
186 }
187 }
188 mReceiver = null;
Kevin Chyn42653e82018-01-19 14:15:46 -0800189 mDialogShowing = false;
Kevin Chyn27e1f262018-03-08 16:38:32 -0800190 mDialogView.startDismiss();
Kevin Chyn42653e82018-01-19 14:15:46 -0800191 }
192
193 private void handleButtonNegative() {
194 if (mReceiver == null) {
195 Log.e(TAG, "Receiver is null");
196 return;
197 }
198 try {
Vishwath Mohanecf00ce2018-04-05 10:28:24 -0700199 mReceiver.onDialogDismissed(BiometricPrompt.DISMISSED_REASON_NEGATIVE);
Kevin Chyn42653e82018-01-19 14:15:46 -0800200 } catch (RemoteException e) {
201 Log.e(TAG, "Remote exception when handling negative button", e);
202 }
203 handleHideDialog(false /* userCanceled */);
204 }
205
206 private void handleButtonPositive() {
207 if (mReceiver == null) {
208 Log.e(TAG, "Receiver is null");
209 return;
210 }
211 try {
Vishwath Mohanecf00ce2018-04-05 10:28:24 -0700212 mReceiver.onDialogDismissed(BiometricPrompt.DISMISSED_REASON_POSITIVE);
Kevin Chyn42653e82018-01-19 14:15:46 -0800213 } catch (RemoteException e) {
214 Log.e(TAG, "Remote exception when handling positive button", e);
215 }
216 handleHideDialog(false /* userCanceled */);
217 }
218
219 private void handleClearMessage() {
Kevin Chynd0544dc2018-02-06 16:30:31 -0800220 mDialogView.resetMessage();
Kevin Chyn42653e82018-01-19 14:15:46 -0800221 }
222
223 private void handleUserCanceled() {
224 handleHideDialog(true /* userCanceled */);
Kevin Chynaae4a152018-01-18 11:48:09 -0800225 }
226}