Home | History | Annotate | Download | only in fingerprint
      1 /*
      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 
     17 package com.android.systemui.fingerprint;
     18 
     19 import android.content.Context;
     20 import android.content.pm.PackageManager;
     21 import android.hardware.biometrics.BiometricPrompt;
     22 import android.hardware.biometrics.IBiometricPromptReceiver;
     23 import android.os.Bundle;
     24 import android.os.Handler;
     25 import android.os.Message;
     26 import android.os.RemoteException;
     27 import android.util.Log;
     28 import android.view.WindowManager;
     29 
     30 import com.android.internal.os.SomeArgs;
     31 import com.android.systemui.SystemUI;
     32 import com.android.systemui.statusbar.CommandQueue;
     33 
     34 public class FingerprintDialogImpl extends SystemUI implements CommandQueue.Callbacks {
     35     private static final String TAG = "FingerprintDialogImpl";
     36     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;
     51     private IBiometricPromptReceiver mReceiver;
     52     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     };
     88 
     89     @Override
     90     public void start() {
     91         if (!mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_FINGERPRINT)) {
     92             return;
     93         }
     94         getComponent(CommandQueue.class).addCallbacks(this);
     95         mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
     96         mDialogView = new FingerprintDialogView(mContext, mHandler);
     97     }
     98 
     99     @Override
    100     public void showFingerprintDialog(Bundle bundle, IBiometricPromptReceiver receiver) {
    101         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();
    110     }
    111 
    112     @Override
    113     public void onFingerprintAuthenticated() {
    114         if (DEBUG) Log.d(TAG, "onFingerprintAuthenticated");
    115         mHandler.obtainMessage(MSG_FINGERPRINT_AUTHENTICATED).sendToTarget();
    116     }
    117 
    118     @Override
    119     public void onFingerprintHelp(String message) {
    120         if (DEBUG) Log.d(TAG, "onFingerprintHelp: " + message);
    121         mHandler.obtainMessage(MSG_FINGERPRINT_HELP, message).sendToTarget();
    122     }
    123 
    124     @Override
    125     public void onFingerprintError(String error) {
    126         if (DEBUG) Log.d(TAG, "onFingerprintError: " + error);
    127         mHandler.obtainMessage(MSG_FINGERPRINT_ERROR, error).sendToTarget();
    128     }
    129 
    130     @Override
    131     public void hideFingerprintDialog() {
    132         if (DEBUG) Log.d(TAG, "hideFingerprintDialog");
    133         mHandler.obtainMessage(MSG_HIDE_DIALOG, false /* userCanceled */).sendToTarget();
    134     }
    135 
    136     private void handleShowDialog(SomeArgs args) {
    137         if (DEBUG) Log.d(TAG, "handleShowDialog, isAnimatingAway: "
    138                 + mDialogView.isAnimatingAway());
    139         if (mDialogView.isAnimatingAway()) {
    140             mDialogView.forceRemove();
    141         } else if (mDialogShowing) {
    142             Log.w(TAG, "Dialog already showing");
    143             return;
    144         }
    145         mReceiver = (IBiometricPromptReceiver) args.arg2;
    146         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");
    153         mDialogView.announceForAccessibility(
    154                 mContext.getResources().getText(
    155                         com.android.internal.R.string.fingerprint_authenticated));
    156         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) {
    174         if (DEBUG) Log.d(TAG, "handleHideDialog, userCanceled: " + userCanceled);
    175         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 {
    183                 mReceiver.onDialogDismissed(BiometricPrompt.DISMISSED_REASON_USER_CANCEL);
    184             } catch (RemoteException e) {
    185                 Log.e(TAG, "RemoteException when hiding dialog", e);
    186             }
    187         }
    188         mReceiver = null;
    189         mDialogShowing = false;
    190         mDialogView.startDismiss();
    191     }
    192 
    193     private void handleButtonNegative() {
    194         if (mReceiver == null) {
    195             Log.e(TAG, "Receiver is null");
    196             return;
    197         }
    198         try {
    199             mReceiver.onDialogDismissed(BiometricPrompt.DISMISSED_REASON_NEGATIVE);
    200         } 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 {
    212             mReceiver.onDialogDismissed(BiometricPrompt.DISMISSED_REASON_POSITIVE);
    213         } 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() {
    220         mDialogView.resetMessage();
    221     }
    222 
    223     private void handleUserCanceled() {
    224         handleHideDialog(true /* userCanceled */);
    225     }
    226 }
    227