1 /*
2  * Copyright (C) 2017 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.settings.biometrics.fingerprint;
18 
19 import android.app.settings.SettingsEnums;
20 import android.hardware.fingerprint.FingerprintManager;
21 import android.hardware.fingerprint.FingerprintManager.AuthenticationResult;
22 import android.os.CancellationSignal;
23 
24 import com.android.internal.annotations.VisibleForTesting;
25 import com.android.settings.core.InstrumentedFragment;
26 
27 /**
28  * Sidecar fragment to handle the state around fingerprint authentication
29  */
30 public class FingerprintAuthenticateSidecar extends InstrumentedFragment {
31 
32     private static final String TAG = "FingerprintAuthenticateSidecar";
33 
34     private FingerprintManager mFingerprintManager;
35     private Listener mListener;
36     private AuthenticationResult mAuthenticationResult;
37     private CancellationSignal mCancellationSignal;
38     private AuthenticationError mAuthenticationError;
39 
40     public interface Listener {
onAuthenticationSucceeded(AuthenticationResult result)41         void onAuthenticationSucceeded(AuthenticationResult result);
onAuthenticationFailed()42         void onAuthenticationFailed();
onAuthenticationError(int errMsgId, CharSequence errString)43         void onAuthenticationError(int errMsgId, CharSequence errString);
onAuthenticationHelp(int helpMsgId, CharSequence helpString)44         void onAuthenticationHelp(int helpMsgId, CharSequence helpString);
45     }
46 
47     private class AuthenticationError {
48         int error;
49         CharSequence errorString;
50 
AuthenticationError(int errMsgId, CharSequence errString)51         public AuthenticationError(int errMsgId, CharSequence errString) {
52             error = errMsgId;
53             errorString = errString;
54         }
55     }
56 
57     @Override
getMetricsCategory()58     public int getMetricsCategory() {
59         return SettingsEnums.FINGERPRINT_AUTHENTICATE_SIDECAR;
60     }
61 
62     private FingerprintManager.AuthenticationCallback mAuthenticationCallback =
63             new FingerprintManager.AuthenticationCallback() {
64                 @Override
65                 public void onAuthenticationSucceeded(AuthenticationResult result) {
66                     mCancellationSignal = null;
67                     if (mListener != null) {
68                         mListener.onAuthenticationSucceeded(result);
69                     } else {
70                         mAuthenticationResult = result;
71                         mAuthenticationError = null;
72                     }
73                 }
74 
75                 @Override
76                 public void onAuthenticationFailed() {
77                     if (mListener != null) {
78                         mListener.onAuthenticationFailed();
79                     }
80                 }
81 
82                 @Override
83                 public void onAuthenticationError(int errMsgId, CharSequence errString) {
84                     if (mListener != null) {
85                         mListener.onAuthenticationError(errMsgId, errString);
86                     } else {
87                         mAuthenticationError = new AuthenticationError(errMsgId, errString);
88                         mAuthenticationResult = null;
89                     }
90                 }
91 
92                 @Override
93                 public void onAuthenticationHelp(int helpMsgId, CharSequence helpString) {
94                     if (mListener != null) {
95                         mListener.onAuthenticationHelp(helpMsgId, helpString);
96                     }
97                 }
98     };
99 
setFingerprintManager(FingerprintManager fingerprintManager)100     public void setFingerprintManager(FingerprintManager fingerprintManager) {
101         mFingerprintManager = fingerprintManager;
102     }
103 
startAuthentication(int userId)104     public void startAuthentication(int userId) {
105         mCancellationSignal = new CancellationSignal();
106         mFingerprintManager.authenticate(null /* crypto */, mCancellationSignal,
107                 mAuthenticationCallback, null /* handler */, userId);
108     }
109 
stopAuthentication()110     public void stopAuthentication() {
111         if (mCancellationSignal != null) {
112             // This will automatically check if the cancel has been sent and if so
113             // it won't send it again.
114             mCancellationSignal.cancel();
115             mCancellationSignal = null;
116         }
117     }
118 
setListener(Listener listener)119     public void setListener(Listener listener) {
120         if (mListener == null && listener != null) {
121             if (mAuthenticationResult != null) {
122                 listener.onAuthenticationSucceeded(mAuthenticationResult);
123                 mAuthenticationResult = null;
124             }
125             if (mAuthenticationError != null &&
126                     mAuthenticationError.error != FingerprintManager.FINGERPRINT_ERROR_CANCELED) {
127                 listener.onAuthenticationError(mAuthenticationError.error,
128                         mAuthenticationError.errorString);
129                 mAuthenticationError = null;
130             }
131         }
132         mListener = listener;
133     }
134 
135     @VisibleForTesting
isCancelled()136     boolean isCancelled() {
137         return mCancellationSignal == null || mCancellationSignal.isCanceled();
138     }
139 }