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.server.biometrics;
18 
19 import static android.Manifest.permission.USE_BIOMETRIC;
20 import static android.Manifest.permission.USE_BIOMETRIC_INTERNAL;
21 import static android.Manifest.permission.USE_FINGERPRINT;
22 import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FACE;
23 import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FINGERPRINT;
24 import static android.hardware.biometrics.BiometricAuthenticator.TYPE_IRIS;
25 import static android.hardware.biometrics.BiometricAuthenticator.TYPE_NONE;
26 
27 import android.app.ActivityManager;
28 import android.app.ActivityTaskManager;
29 import android.app.AppOpsManager;
30 import android.app.IActivityTaskManager;
31 import android.app.KeyguardManager;
32 import android.app.TaskStackListener;
33 import android.app.UserSwitchObserver;
34 import android.content.ContentResolver;
35 import android.content.Context;
36 import android.content.Intent;
37 import android.content.pm.PackageManager;
38 import android.database.ContentObserver;
39 import android.hardware.biometrics.BiometricAuthenticator;
40 import android.hardware.biometrics.BiometricConstants;
41 import android.hardware.biometrics.BiometricPrompt;
42 import android.hardware.biometrics.BiometricSourceType;
43 import android.hardware.biometrics.BiometricsProtoEnums;
44 import android.hardware.biometrics.IBiometricConfirmDeviceCredentialCallback;
45 import android.hardware.biometrics.IBiometricEnabledOnKeyguardCallback;
46 import android.hardware.biometrics.IBiometricService;
47 import android.hardware.biometrics.IBiometricServiceReceiver;
48 import android.hardware.biometrics.IBiometricServiceReceiverInternal;
49 import android.hardware.face.FaceManager;
50 import android.hardware.face.IFaceService;
51 import android.hardware.fingerprint.FingerprintManager;
52 import android.hardware.fingerprint.IFingerprintService;
53 import android.net.Uri;
54 import android.os.Binder;
55 import android.os.Bundle;
56 import android.os.DeadObjectException;
57 import android.os.Handler;
58 import android.os.IBinder;
59 import android.os.Looper;
60 import android.os.Message;
61 import android.os.RemoteException;
62 import android.os.ServiceManager;
63 import android.os.UserHandle;
64 import android.provider.Settings;
65 import android.security.KeyStore;
66 import android.text.TextUtils;
67 import android.util.Pair;
68 import android.util.Slog;
69 import android.util.StatsLog;
70 
71 import com.android.internal.R;
72 import com.android.internal.os.SomeArgs;
73 import com.android.internal.statusbar.IStatusBarService;
74 import com.android.server.SystemService;
75 
76 import java.util.ArrayList;
77 import java.util.HashMap;
78 import java.util.Iterator;
79 import java.util.List;
80 import java.util.Map;
81 import java.util.Random;
82 
83 /**
84  * System service that arbitrates the modality for BiometricPrompt to use.
85  */
86 public class BiometricService extends SystemService {
87 
88     private static final String TAG = "BiometricService";
89     private static final boolean DEBUG = true;
90 
91     private static final int MSG_ON_TASK_STACK_CHANGED = 1;
92     private static final int MSG_ON_AUTHENTICATION_SUCCEEDED = 2;
93     private static final int MSG_ON_AUTHENTICATION_FAILED = 3;
94     private static final int MSG_ON_ERROR = 4;
95     private static final int MSG_ON_ACQUIRED = 5;
96     private static final int MSG_ON_DISMISSED = 6;
97     private static final int MSG_ON_TRY_AGAIN_PRESSED = 7;
98     private static final int MSG_ON_READY_FOR_AUTHENTICATION = 8;
99     private static final int MSG_AUTHENTICATE = 9;
100     private static final int MSG_CANCEL_AUTHENTICATION = 10;
101     private static final int MSG_ON_CONFIRM_DEVICE_CREDENTIAL_SUCCESS = 11;
102     private static final int MSG_ON_CONFIRM_DEVICE_CREDENTIAL_ERROR = 12;
103     private static final int MSG_REGISTER_CANCELLATION_CALLBACK = 13;
104 
105     private static final int[] FEATURE_ID = {
106         TYPE_FINGERPRINT,
107         TYPE_IRIS,
108         TYPE_FACE
109     };
110 
111     /**
112      * Authentication either just called and we have not transitioned to the CALLED state, or
113      * authentication terminated (success or error).
114      */
115     private static final int STATE_AUTH_IDLE = 0;
116     /**
117      * Authentication was called and we are waiting for the <Biometric>Services to return their
118      * cookies before starting the hardware and showing the BiometricPrompt.
119      */
120     private static final int STATE_AUTH_CALLED = 1;
121     /**
122      * Authentication started, BiometricPrompt is showing and the hardware is authenticating.
123      */
124     private static final int STATE_AUTH_STARTED = 2;
125     /**
126      * Authentication is paused, waiting for the user to press "try again" button. Only
127      * passive modalities such as Face or Iris should have this state. Note that for passive
128      * modalities, the HAL enters the idle state after onAuthenticated(false) which differs from
129      * fingerprint.
130      */
131     private static final int STATE_AUTH_PAUSED = 3;
132     /**
133      * Authentication is successful, but we're waiting for the user to press "confirm" button.
134      */
135     private static final int STATE_AUTH_PENDING_CONFIRM = 5;
136     /**
137      * Biometric authentication was canceled, but the device is now showing ConfirmDeviceCredential
138      */
139     private static final int STATE_BIOMETRIC_AUTH_CANCELED_SHOWING_CDC = 6;
140 
141     private final class AuthSession implements IBinder.DeathRecipient {
142         // Map of Authenticator/Cookie pairs. We expect to receive the cookies back from
143         // <Biometric>Services before we can start authenticating. Pairs that have been returned
144         // are moved to mModalitiesMatched.
145         final HashMap<Integer, Integer> mModalitiesWaiting;
146         // Pairs that have been matched.
147         final HashMap<Integer, Integer> mModalitiesMatched = new HashMap<>();
148 
149         // The following variables are passed to authenticateInternal, which initiates the
150         // appropriate <Biometric>Services.
151         final IBinder mToken;
152         final long mSessionId;
153         final int mUserId;
154         // Original receiver from BiometricPrompt.
155         final IBiometricServiceReceiver mClientReceiver;
156         final String mOpPackageName;
157         // Info to be shown on BiometricDialog when all cookies are returned.
158         final Bundle mBundle;
159         final int mCallingUid;
160         final int mCallingPid;
161         final int mCallingUserId;
162         // Continue authentication with the same modality/modalities after "try again" is
163         // pressed
164         final int mModality;
165         final boolean mRequireConfirmation;
166 
167         // The current state, which can be either idle, called, or started
168         private int mState = STATE_AUTH_IDLE;
169         // For explicit confirmation, do not send to keystore until the user has confirmed
170         // the authentication.
171         byte[] mTokenEscrow;
172 
173         // Timestamp when authentication started
174         private long mStartTimeMs;
175         // Timestamp when hardware authentication occurred
176         private long mAuthenticatedTimeMs;
177 
178         // TODO(b/123378871): Remove when moved.
179         private IBiometricConfirmDeviceCredentialCallback mConfirmDeviceCredentialCallback;
180 
AuthSession(HashMap<Integer, Integer> modalities, IBinder token, long sessionId, int userId, IBiometricServiceReceiver receiver, String opPackageName, Bundle bundle, int callingUid, int callingPid, int callingUserId, int modality, boolean requireConfirmation, IBiometricConfirmDeviceCredentialCallback callback)181         AuthSession(HashMap<Integer, Integer> modalities, IBinder token, long sessionId,
182                 int userId, IBiometricServiceReceiver receiver, String opPackageName,
183                 Bundle bundle, int callingUid, int callingPid, int callingUserId,
184                 int modality, boolean requireConfirmation,
185                 IBiometricConfirmDeviceCredentialCallback callback) {
186             mModalitiesWaiting = modalities;
187             mToken = token;
188             mSessionId = sessionId;
189             mUserId = userId;
190             mClientReceiver = receiver;
191             mOpPackageName = opPackageName;
192             mBundle = bundle;
193             mCallingUid = callingUid;
194             mCallingPid = callingPid;
195             mCallingUserId = callingUserId;
196             mModality = modality;
197             mRequireConfirmation = requireConfirmation;
198             mConfirmDeviceCredentialCallback = callback;
199 
200             if (isFromConfirmDeviceCredential()) {
201                 try {
202                     token.linkToDeath(this, 0 /* flags */);
203                 } catch (RemoteException e) {
204                     Slog.e(TAG, "Unable to link to death", e);
205                 }
206             }
207         }
208 
isCrypto()209         boolean isCrypto() {
210             return mSessionId != 0;
211         }
212 
isFromConfirmDeviceCredential()213         boolean isFromConfirmDeviceCredential() {
214             return mBundle.getBoolean(BiometricPrompt.KEY_FROM_CONFIRM_DEVICE_CREDENTIAL, false);
215         }
216 
containsCookie(int cookie)217         boolean containsCookie(int cookie) {
218             if (mModalitiesWaiting != null && mModalitiesWaiting.containsValue(cookie)) {
219                 return true;
220             }
221             if (mModalitiesMatched != null && mModalitiesMatched.containsValue(cookie)) {
222                 return true;
223             }
224             return false;
225         }
226 
227         // TODO(b/123378871): Remove when moved.
228         @Override
binderDied()229         public void binderDied() {
230             mHandler.post(() -> {
231                 Slog.e(TAG, "Binder died, killing ConfirmDeviceCredential");
232                 if (mConfirmDeviceCredentialCallback == null) {
233                     Slog.e(TAG, "Callback is null");
234                     return;
235                 }
236 
237                 try {
238                     mConfirmDeviceCredentialCallback.cancel();
239                     mConfirmDeviceCredentialCallback = null;
240                 } catch (RemoteException e) {
241                     Slog.e(TAG, "Unable to send cancel", e);
242                 }
243             });
244         }
245     }
246 
247     private final class BiometricTaskStackListener extends TaskStackListener {
248         @Override
onTaskStackChanged()249         public void onTaskStackChanged() {
250             mHandler.sendEmptyMessage(MSG_ON_TASK_STACK_CHANGED);
251         }
252     }
253 
254     private final AppOpsManager mAppOps;
255     private final boolean mHasFeatureFingerprint;
256     private final boolean mHasFeatureIris;
257     private final boolean mHasFeatureFace;
258     private final SettingObserver mSettingObserver;
259     private final List<EnabledOnKeyguardCallback> mEnabledOnKeyguardCallbacks;
260     private final BiometricTaskStackListener mTaskStackListener = new BiometricTaskStackListener();
261     private final Random mRandom = new Random();
262 
263     private IFingerprintService mFingerprintService;
264     private IFaceService mFaceService;
265     private IActivityTaskManager mActivityTaskManager;
266     private IStatusBarService mStatusBarService;
267 
268     // Get and cache the available authenticator (manager) classes. Used since aidl doesn't support
269     // polymorphism :/
270     final ArrayList<Authenticator> mAuthenticators = new ArrayList<>();
271 
272     // Cache the current service that's being used. This is the service which
273     // cancelAuthentication() must be forwarded to. This is just a cache, and the actual
274     // check (is caller the current client) is done in the <Biometric>Service.
275     // Since Settings/System (not application) is responsible for changing preference, this
276     // should be safe.
277     private int mCurrentModality;
278 
279     // The current authentication session, null if idle/done. We need to track both the current
280     // and pending sessions since errors may be sent to either.
281     private AuthSession mCurrentAuthSession;
282     private AuthSession mPendingAuthSession;
283 
284     // TODO(b/123378871): Remove when moved.
285     // When BiometricPrompt#setAllowDeviceCredentials is set to true, we need to store the
286     // client (app) receiver. BiometricService internally launches CDCA which invokes
287     // BiometricService to start authentication (normal path). When auth is success/rejected,
288     // CDCA will use an aidl method to poke BiometricService - the result will then be forwarded
289     // to this receiver.
290     private IBiometricServiceReceiver mConfirmDeviceCredentialReceiver;
291 
292     private final Handler mHandler = new Handler(Looper.getMainLooper()) {
293         @Override
294         public void handleMessage(Message msg) {
295             switch (msg.what) {
296                 case MSG_ON_TASK_STACK_CHANGED: {
297                     handleTaskStackChanged();
298                     break;
299                 }
300 
301                 case MSG_ON_AUTHENTICATION_SUCCEEDED: {
302                     SomeArgs args = (SomeArgs) msg.obj;
303                     handleAuthenticationSucceeded(
304                             (boolean) args.arg1 /* requireConfirmation */,
305                             (byte[]) args.arg2 /* token */);
306                     args.recycle();
307                     break;
308                 }
309 
310                 case MSG_ON_AUTHENTICATION_FAILED: {
311                     handleAuthenticationFailed((String) msg.obj /* failureReason */);
312                     break;
313                 }
314 
315                 case MSG_ON_ERROR: {
316                     SomeArgs args = (SomeArgs) msg.obj;
317                     handleOnError(
318                             args.argi1 /* cookie */,
319                             args.argi2 /* error */,
320                             (String) args.arg1 /* message */);
321                     args.recycle();
322                     break;
323                 }
324 
325                 case MSG_ON_ACQUIRED: {
326                     SomeArgs args = (SomeArgs) msg.obj;
327                     handleOnAcquired(
328                             args.argi1 /* acquiredInfo */,
329                             (String) args.arg1 /* message */);
330                     args.recycle();
331                     break;
332                 }
333 
334                 case MSG_ON_DISMISSED: {
335                     handleOnDismissed(msg.arg1);
336                     break;
337                 }
338 
339                 case MSG_ON_TRY_AGAIN_PRESSED: {
340                     handleOnTryAgainPressed();
341                     break;
342                 }
343 
344                 case MSG_ON_READY_FOR_AUTHENTICATION: {
345                     SomeArgs args = (SomeArgs) msg.obj;
346                     handleOnReadyForAuthentication(
347                             args.argi1 /* cookie */,
348                             (boolean) args.arg1 /* requireConfirmation */,
349                             args.argi2 /* userId */);
350                     args.recycle();
351                     break;
352                 }
353 
354                 case MSG_AUTHENTICATE: {
355                     SomeArgs args = (SomeArgs) msg.obj;
356                     handleAuthenticate(
357                             (IBinder) args.arg1 /* token */,
358                             (long) args.arg2 /* sessionId */,
359                             args.argi1 /* userid */,
360                             (IBiometricServiceReceiver) args.arg3 /* receiver */,
361                             (String) args.arg4 /* opPackageName */,
362                             (Bundle) args.arg5 /* bundle */,
363                             args.argi2 /* callingUid */,
364                             args.argi3 /* callingPid */,
365                             args.argi4 /* callingUserId */,
366                             (IBiometricConfirmDeviceCredentialCallback) args.arg6 /* callback */);
367                     args.recycle();
368                     break;
369                 }
370 
371                 case MSG_CANCEL_AUTHENTICATION: {
372                     SomeArgs args = (SomeArgs) msg.obj;
373                     handleCancelAuthentication(
374                             (IBinder) args.arg1 /* token */,
375                             (String) args.arg2 /* opPackageName */);
376                     args.recycle();
377                     break;
378                 }
379 
380                 case MSG_ON_CONFIRM_DEVICE_CREDENTIAL_SUCCESS: {
381                     handleOnConfirmDeviceCredentialSuccess();
382                     break;
383                 }
384 
385                 case MSG_ON_CONFIRM_DEVICE_CREDENTIAL_ERROR: {
386                     SomeArgs args = (SomeArgs) msg.obj;
387                     handleOnConfirmDeviceCredentialError(
388                             args.argi1 /* error */,
389                             (String) args.arg1 /* errorMsg */);
390                     args.recycle();
391                     break;
392                 }
393 
394                 case MSG_REGISTER_CANCELLATION_CALLBACK: {
395                     handleRegisterCancellationCallback(
396                             (IBiometricConfirmDeviceCredentialCallback) msg.obj /* callback */);
397                     break;
398                 }
399 
400                 default:
401                     Slog.e(TAG, "Unknown message: " + msg);
402                     break;
403             }
404         }
405     };
406 
407     private final class Authenticator {
408         int mType;
409         BiometricAuthenticator mAuthenticator;
410 
Authenticator(int type, BiometricAuthenticator authenticator)411         Authenticator(int type, BiometricAuthenticator authenticator) {
412             mType = type;
413             mAuthenticator = authenticator;
414         }
415 
getType()416         int getType() {
417             return mType;
418         }
419 
getAuthenticator()420         BiometricAuthenticator getAuthenticator() {
421             return mAuthenticator;
422         }
423     }
424 
425     private final class SettingObserver extends ContentObserver {
426 
427         private static final boolean DEFAULT_KEYGUARD_ENABLED = true;
428         private static final boolean DEFAULT_APP_ENABLED = true;
429         private static final boolean DEFAULT_ALWAYS_REQUIRE_CONFIRMATION = false;
430 
431         private final Uri FACE_UNLOCK_KEYGUARD_ENABLED =
432                 Settings.Secure.getUriFor(Settings.Secure.FACE_UNLOCK_KEYGUARD_ENABLED);
433         private final Uri FACE_UNLOCK_APP_ENABLED =
434                 Settings.Secure.getUriFor(Settings.Secure.FACE_UNLOCK_APP_ENABLED);
435         private final Uri FACE_UNLOCK_ALWAYS_REQUIRE_CONFIRMATION =
436                 Settings.Secure.getUriFor(Settings.Secure.FACE_UNLOCK_ALWAYS_REQUIRE_CONFIRMATION);
437 
438         private final ContentResolver mContentResolver;
439 
440         private Map<Integer, Boolean> mFaceEnabledOnKeyguard = new HashMap<>();
441         private Map<Integer, Boolean> mFaceEnabledForApps = new HashMap<>();
442         private Map<Integer, Boolean> mFaceAlwaysRequireConfirmation = new HashMap<>();
443 
444         /**
445          * Creates a content observer.
446          *
447          * @param handler The handler to run {@link #onChange} on, or null if none.
448          */
SettingObserver(Handler handler)449         SettingObserver(Handler handler) {
450             super(handler);
451             mContentResolver = getContext().getContentResolver();
452             updateContentObserver();
453         }
454 
updateContentObserver()455         void updateContentObserver() {
456             mContentResolver.unregisterContentObserver(this);
457             mContentResolver.registerContentObserver(FACE_UNLOCK_KEYGUARD_ENABLED,
458                     false /* notifyForDescendents */,
459                     this /* observer */,
460                     UserHandle.USER_ALL);
461             mContentResolver.registerContentObserver(FACE_UNLOCK_APP_ENABLED,
462                     false /* notifyForDescendents */,
463                     this /* observer */,
464                     UserHandle.USER_ALL);
465             mContentResolver.registerContentObserver(FACE_UNLOCK_ALWAYS_REQUIRE_CONFIRMATION,
466                     false /* notifyForDescendents */,
467                     this /* observer */,
468                     UserHandle.USER_ALL);
469         }
470 
471         @Override
onChange(boolean selfChange, Uri uri, int userId)472         public void onChange(boolean selfChange, Uri uri, int userId) {
473             if (FACE_UNLOCK_KEYGUARD_ENABLED.equals(uri)) {
474                 mFaceEnabledOnKeyguard.put(userId, Settings.Secure.getIntForUser(
475                                 mContentResolver,
476                                 Settings.Secure.FACE_UNLOCK_KEYGUARD_ENABLED,
477                                 DEFAULT_KEYGUARD_ENABLED ? 1 : 0 /* default */,
478                                 userId) != 0);
479 
480                 if (userId == ActivityManager.getCurrentUser() && !selfChange) {
481                     notifyEnabledOnKeyguardCallbacks(userId);
482                 }
483             } else if (FACE_UNLOCK_APP_ENABLED.equals(uri)) {
484                 mFaceEnabledForApps.put(userId, Settings.Secure.getIntForUser(
485                                 mContentResolver,
486                                 Settings.Secure.FACE_UNLOCK_APP_ENABLED,
487                                 DEFAULT_APP_ENABLED ? 1 : 0 /* default */,
488                                 userId) != 0);
489             } else if (FACE_UNLOCK_ALWAYS_REQUIRE_CONFIRMATION.equals(uri)) {
490                 mFaceAlwaysRequireConfirmation.put(userId, Settings.Secure.getIntForUser(
491                                 mContentResolver,
492                                 Settings.Secure.FACE_UNLOCK_ALWAYS_REQUIRE_CONFIRMATION,
493                                 DEFAULT_ALWAYS_REQUIRE_CONFIRMATION ? 1 : 0 /* default */,
494                                 userId) != 0);
495             }
496         }
497 
getFaceEnabledOnKeyguard()498         boolean getFaceEnabledOnKeyguard() {
499             final int user = ActivityManager.getCurrentUser();
500             if (!mFaceEnabledOnKeyguard.containsKey(user)) {
501                 onChange(true /* selfChange */, FACE_UNLOCK_KEYGUARD_ENABLED, user);
502             }
503             return mFaceEnabledOnKeyguard.get(user);
504         }
505 
getFaceEnabledForApps(int userId)506         boolean getFaceEnabledForApps(int userId) {
507             if (!mFaceEnabledForApps.containsKey(userId)) {
508                 onChange(true /* selfChange */, FACE_UNLOCK_APP_ENABLED, userId);
509             }
510             return mFaceEnabledForApps.getOrDefault(userId, DEFAULT_APP_ENABLED);
511         }
512 
getFaceAlwaysRequireConfirmation(int userId)513         boolean getFaceAlwaysRequireConfirmation(int userId) {
514             if (!mFaceAlwaysRequireConfirmation.containsKey(userId)) {
515                 onChange(true /* selfChange */, FACE_UNLOCK_ALWAYS_REQUIRE_CONFIRMATION, userId);
516             }
517             return mFaceAlwaysRequireConfirmation.get(userId);
518         }
519 
notifyEnabledOnKeyguardCallbacks(int userId)520         void notifyEnabledOnKeyguardCallbacks(int userId) {
521             List<EnabledOnKeyguardCallback> callbacks = mEnabledOnKeyguardCallbacks;
522             for (int i = 0; i < callbacks.size(); i++) {
523                 callbacks.get(i).notify(BiometricSourceType.FACE,
524                         mFaceEnabledOnKeyguard.getOrDefault(userId, DEFAULT_KEYGUARD_ENABLED),
525                         userId);
526             }
527         }
528     }
529 
530     private final class EnabledOnKeyguardCallback implements IBinder.DeathRecipient {
531 
532         private final IBiometricEnabledOnKeyguardCallback mCallback;
533 
EnabledOnKeyguardCallback(IBiometricEnabledOnKeyguardCallback callback)534         EnabledOnKeyguardCallback(IBiometricEnabledOnKeyguardCallback callback) {
535             mCallback = callback;
536             try {
537                 mCallback.asBinder().linkToDeath(EnabledOnKeyguardCallback.this, 0);
538             } catch (RemoteException e) {
539                 Slog.w(TAG, "Unable to linkToDeath", e);
540             }
541         }
542 
notify(BiometricSourceType sourceType, boolean enabled, int userId)543         void notify(BiometricSourceType sourceType, boolean enabled, int userId) {
544             try {
545                 mCallback.onChanged(sourceType, enabled, userId);
546             } catch (DeadObjectException e) {
547                 Slog.w(TAG, "Death while invoking notify", e);
548                 mEnabledOnKeyguardCallbacks.remove(this);
549             } catch (RemoteException e) {
550                 Slog.w(TAG, "Failed to invoke onChanged", e);
551             }
552         }
553 
554         @Override
binderDied()555         public void binderDied() {
556             Slog.e(TAG, "Enabled callback binder died");
557             mEnabledOnKeyguardCallbacks.remove(this);
558         }
559     }
560 
561     // Wrap the client's receiver so we can do things with the BiometricDialog first
562     private final IBiometricServiceReceiverInternal mInternalReceiver =
563             new IBiometricServiceReceiverInternal.Stub() {
564         @Override
565         public void onAuthenticationSucceeded(boolean requireConfirmation, byte[] token)
566                 throws RemoteException {
567             SomeArgs args = SomeArgs.obtain();
568             args.arg1 = requireConfirmation;
569             args.arg2 = token;
570             mHandler.obtainMessage(MSG_ON_AUTHENTICATION_SUCCEEDED, args).sendToTarget();
571         }
572 
573         @Override
574         public void onAuthenticationFailed(int cookie, boolean requireConfirmation)
575                 throws RemoteException {
576             String failureReason = getContext().getString(R.string.biometric_not_recognized);
577             mHandler.obtainMessage(MSG_ON_AUTHENTICATION_FAILED, failureReason).sendToTarget();
578         }
579 
580         @Override
581         public void onError(int cookie, int error, String message) throws RemoteException {
582             // Determine if error is hard or soft error. Certain errors (such as TIMEOUT) are
583             // soft errors and we should allow the user to try authenticating again instead of
584             // dismissing BiometricPrompt.
585             if (error == BiometricConstants.BIOMETRIC_ERROR_TIMEOUT) {
586                 mHandler.obtainMessage(MSG_ON_AUTHENTICATION_FAILED, message).sendToTarget();
587             } else {
588                 SomeArgs args = SomeArgs.obtain();
589                 args.argi1 = cookie;
590                 args.argi2 = error;
591                 args.arg1 = message;
592                 mHandler.obtainMessage(MSG_ON_ERROR, args).sendToTarget();
593             }
594         }
595 
596         @Override
597         public void onAcquired(int acquiredInfo, String message) throws RemoteException {
598             SomeArgs args = SomeArgs.obtain();
599             args.argi1 = acquiredInfo;
600             args.arg1 = message;
601             mHandler.obtainMessage(MSG_ON_ACQUIRED, args).sendToTarget();
602         }
603 
604         @Override
605         public void onDialogDismissed(int reason) throws RemoteException {
606             mHandler.obtainMessage(MSG_ON_DISMISSED, reason, 0 /* arg2 */).sendToTarget();
607         }
608 
609         @Override
610         public void onTryAgainPressed() {
611             mHandler.sendEmptyMessage(MSG_ON_TRY_AGAIN_PRESSED);
612         }
613     };
614 
615 
616     /**
617      * This is just a pass-through service that wraps Fingerprint, Iris, Face services. This service
618      * should not carry any state. The reality is we need to keep a tiny amount of state so that
619      * cancelAuthentication() can go to the right place.
620      */
621     private final class BiometricServiceWrapper extends IBiometricService.Stub {
622         @Override // Binder call
onReadyForAuthentication(int cookie, boolean requireConfirmation, int userId)623         public void onReadyForAuthentication(int cookie, boolean requireConfirmation, int userId) {
624             checkInternalPermission();
625 
626             SomeArgs args = SomeArgs.obtain();
627             args.argi1 = cookie;
628             args.arg1 = requireConfirmation;
629             args.argi2 = userId;
630             mHandler.obtainMessage(MSG_ON_READY_FOR_AUTHENTICATION, args).sendToTarget();
631         }
632 
633         @Override // Binder call
authenticate(IBinder token, long sessionId, int userId, IBiometricServiceReceiver receiver, String opPackageName, Bundle bundle, IBiometricConfirmDeviceCredentialCallback callback)634         public void authenticate(IBinder token, long sessionId, int userId,
635                 IBiometricServiceReceiver receiver, String opPackageName, Bundle bundle,
636                 IBiometricConfirmDeviceCredentialCallback callback)
637                 throws RemoteException {
638             final int callingUid = Binder.getCallingUid();
639             final int callingPid = Binder.getCallingPid();
640             final int callingUserId = UserHandle.getCallingUserId();
641 
642             // TODO(b/123378871): Remove when moved.
643             if (callback != null) {
644                 checkInternalPermission();
645             }
646 
647             // In the BiometricServiceBase, check do the AppOps and foreground check.
648             if (userId == callingUserId) {
649                 // Check the USE_BIOMETRIC permission here.
650                 checkPermission();
651             } else {
652                 // Only allow internal clients to authenticate with a different userId
653                 Slog.w(TAG, "User " + callingUserId + " is requesting authentication of userid: "
654                         + userId);
655                 checkInternalPermission();
656             }
657 
658             if (token == null || receiver == null || opPackageName == null || bundle == null) {
659                 Slog.e(TAG, "Unable to authenticate, one or more null arguments");
660                 return;
661             }
662 
663             final boolean isFromConfirmDeviceCredential =
664                     bundle.getBoolean(BiometricPrompt.KEY_FROM_CONFIRM_DEVICE_CREDENTIAL, false);
665             if (isFromConfirmDeviceCredential) {
666                 checkInternalPermission();
667             }
668 
669             // Check the usage of this in system server. Need to remove this check if it becomes
670             // a public API.
671             final boolean useDefaultTitle =
672                     bundle.getBoolean(BiometricPrompt.KEY_USE_DEFAULT_TITLE, false);
673             if (useDefaultTitle) {
674                 checkInternalPermission();
675                 // Set the default title if necessary
676                 if (TextUtils.isEmpty(bundle.getCharSequence(BiometricPrompt.KEY_TITLE))) {
677                     bundle.putCharSequence(BiometricPrompt.KEY_TITLE,
678                             getContext().getString(R.string.biometric_dialog_default_title));
679                 }
680             }
681 
682             // Launch CDC instead if necessary. CDC will return results through an AIDL call, since
683             // we can't get activity results. Store the receiver somewhere so we can forward the
684             // result back to the client.
685             // TODO(b/123378871): Remove when moved.
686             if (bundle.getBoolean(BiometricPrompt.KEY_ALLOW_DEVICE_CREDENTIAL)) {
687                 mHandler.post(() -> {
688                     final KeyguardManager kgm = getContext().getSystemService(
689                             KeyguardManager.class);
690                     if (!kgm.isDeviceSecure()) {
691                         try {
692                             receiver.onError(
693                                     BiometricConstants.BIOMETRIC_ERROR_NO_DEVICE_CREDENTIAL,
694                                     getContext().getString(
695                                             R.string.biometric_error_device_not_secured));
696                         } catch (RemoteException e) {
697                             Slog.e(TAG, "Remote exception", e);
698                         }
699                         return;
700                     }
701                     mConfirmDeviceCredentialReceiver = receiver;
702                     // Use this so we don't need to duplicate logic..
703                     final Intent intent = kgm.createConfirmDeviceCredentialIntent(null /* title */,
704                             null /* description */, userId);
705                     // Then give it the bundle to do magic behavior..
706                     intent.putExtra(KeyguardManager.EXTRA_BIOMETRIC_PROMPT_BUNDLE, bundle);
707                     // Create a new task with this activity located at the root.
708                     intent.setFlags(
709                             Intent.FLAG_ACTIVITY_MULTIPLE_TASK | Intent.FLAG_ACTIVITY_NEW_DOCUMENT);
710                     getContext().startActivityAsUser(intent, UserHandle.CURRENT);
711                 });
712                 return;
713             }
714 
715             SomeArgs args = SomeArgs.obtain();
716             args.arg1 = token;
717             args.arg2 = sessionId;
718             args.argi1 = userId;
719             args.arg3 = receiver;
720             args.arg4 = opPackageName;
721             args.arg5 = bundle;
722             args.argi2 = callingUid;
723             args.argi3 = callingPid;
724             args.argi4 = callingUserId;
725             args.arg6 = callback;
726 
727             mHandler.obtainMessage(MSG_AUTHENTICATE, args).sendToTarget();
728         }
729 
730         @Override // Binder call
onConfirmDeviceCredentialSuccess()731         public void onConfirmDeviceCredentialSuccess() {
732             checkInternalPermission();
733 
734             mHandler.sendEmptyMessage(MSG_ON_CONFIRM_DEVICE_CREDENTIAL_SUCCESS);
735         }
736 
737         @Override // Binder call
onConfirmDeviceCredentialError(int error, String message)738         public void onConfirmDeviceCredentialError(int error, String message) {
739             checkInternalPermission();
740 
741             SomeArgs args = SomeArgs.obtain();
742             args.argi1 = error;
743             args.arg1 = message;
744             mHandler.obtainMessage(MSG_ON_CONFIRM_DEVICE_CREDENTIAL_ERROR, args).sendToTarget();
745         }
746 
747         @Override // Binder call
registerCancellationCallback( IBiometricConfirmDeviceCredentialCallback callback)748         public void registerCancellationCallback(
749                 IBiometricConfirmDeviceCredentialCallback callback) {
750             // TODO(b/123378871): Remove when moved.
751             // This callback replaces the one stored in the current session. If the session is null
752             // we can ignore this, since it means ConfirmDeviceCredential was launched by something
753             // else (not BiometricPrompt)
754             checkInternalPermission();
755 
756             mHandler.obtainMessage(MSG_REGISTER_CANCELLATION_CALLBACK, callback).sendToTarget();
757         }
758 
759         @Override // Binder call
cancelAuthentication(IBinder token, String opPackageName)760         public void cancelAuthentication(IBinder token, String opPackageName)
761                 throws RemoteException {
762             checkPermission();
763 
764             SomeArgs args = SomeArgs.obtain();
765             args.arg1 = token;
766             args.arg2 = opPackageName;
767             mHandler.obtainMessage(MSG_CANCEL_AUTHENTICATION, args).sendToTarget();
768         }
769 
770         @Override // Binder call
canAuthenticate(String opPackageName, int userId)771         public int canAuthenticate(String opPackageName, int userId) {
772             Slog.d(TAG, "canAuthenticate: User=" + userId
773                     + ", Caller=" + UserHandle.getCallingUserId());
774 
775             if (userId != UserHandle.getCallingUserId()) {
776                 checkInternalPermission();
777             } else {
778                 checkPermission();
779             }
780 
781             final long ident = Binder.clearCallingIdentity();
782             int error;
783             try {
784                 final Pair<Integer, Integer> result = checkAndGetBiometricModality(userId);
785                 error = result.second;
786             } finally {
787                 Binder.restoreCallingIdentity(ident);
788             }
789             return error;
790         }
791 
792         @Override
hasEnrolledBiometrics(int userId)793         public boolean hasEnrolledBiometrics(int userId) {
794             checkInternalPermission();
795 
796             final long ident = Binder.clearCallingIdentity();
797             try {
798                 for (int i = 0; i < mAuthenticators.size(); i++) {
799                     if (mAuthenticators.get(i).mAuthenticator.hasEnrolledTemplates(userId)) {
800                         return true;
801                     }
802                 }
803             } finally {
804                 Binder.restoreCallingIdentity(ident);
805             }
806             return false;
807         }
808 
809         @Override // Binder call
registerEnabledOnKeyguardCallback(IBiometricEnabledOnKeyguardCallback callback)810         public void registerEnabledOnKeyguardCallback(IBiometricEnabledOnKeyguardCallback callback)
811                 throws RemoteException {
812             checkInternalPermission();
813             mEnabledOnKeyguardCallbacks.add(new EnabledOnKeyguardCallback(callback));
814             try {
815                 callback.onChanged(BiometricSourceType.FACE,
816                         mSettingObserver.getFaceEnabledOnKeyguard(),
817                         UserHandle.getCallingUserId());
818             } catch (RemoteException e) {
819                 Slog.w(TAG, "Remote exception", e);
820             }
821         }
822 
823         @Override // Binder call
setActiveUser(int userId)824         public void setActiveUser(int userId) {
825             checkInternalPermission();
826             final long ident = Binder.clearCallingIdentity();
827             try {
828                 for (int i = 0; i < mAuthenticators.size(); i++) {
829                     mAuthenticators.get(i).getAuthenticator().setActiveUser(userId);
830                 }
831             } finally {
832                 Binder.restoreCallingIdentity(ident);
833             }
834         }
835 
836         @Override // Binder call
resetLockout(byte[] token)837         public void resetLockout(byte[] token) {
838             checkInternalPermission();
839             final long ident = Binder.clearCallingIdentity();
840             try {
841                 if (mFingerprintService != null) {
842                     mFingerprintService.resetTimeout(token);
843                 }
844                 if (mFaceService != null) {
845                     mFaceService.resetLockout(token);
846                 }
847             } catch (RemoteException e) {
848                 Slog.e(TAG, "Remote exception", e);
849             } finally {
850                 Binder.restoreCallingIdentity(ident);
851             }
852         }
853     }
854 
checkAppOp(String opPackageName, int callingUid)855     private void checkAppOp(String opPackageName, int callingUid) {
856         if (mAppOps.noteOp(AppOpsManager.OP_USE_BIOMETRIC, callingUid,
857                 opPackageName) != AppOpsManager.MODE_ALLOWED) {
858             Slog.w(TAG, "Rejecting " + opPackageName + "; permission denied");
859             throw new SecurityException("Permission denied");
860         }
861     }
862 
checkInternalPermission()863     private void checkInternalPermission() {
864         getContext().enforceCallingOrSelfPermission(USE_BIOMETRIC_INTERNAL,
865                 "Must have USE_BIOMETRIC_INTERNAL permission");
866     }
867 
checkPermission()868     private void checkPermission() {
869         if (getContext().checkCallingOrSelfPermission(USE_FINGERPRINT)
870                 != PackageManager.PERMISSION_GRANTED) {
871             getContext().enforceCallingOrSelfPermission(USE_BIOMETRIC,
872                     "Must have USE_BIOMETRIC permission");
873         }
874     }
875 
876     /**
877      * Initializes the system service.
878      * <p>
879      * Subclasses must define a single argument constructor that accepts the context
880      * and passes it to super.
881      * </p>
882      *
883      * @param context The system server context.
884      */
BiometricService(Context context)885     public BiometricService(Context context) {
886         super(context);
887 
888         mAppOps = context.getSystemService(AppOpsManager.class);
889         mEnabledOnKeyguardCallbacks = new ArrayList<>();
890         mSettingObserver = new SettingObserver(mHandler);
891 
892         final PackageManager pm = context.getPackageManager();
893         mHasFeatureFingerprint = pm.hasSystemFeature(PackageManager.FEATURE_FINGERPRINT);
894         mHasFeatureIris = pm.hasSystemFeature(PackageManager.FEATURE_IRIS);
895         mHasFeatureFace = pm.hasSystemFeature(PackageManager.FEATURE_FACE);
896 
897         try {
898             ActivityManager.getService().registerUserSwitchObserver(
899                     new UserSwitchObserver() {
900                         @Override
901                         public void onUserSwitchComplete(int newUserId) {
902                             mSettingObserver.updateContentObserver();
903                             mSettingObserver.notifyEnabledOnKeyguardCallbacks(newUserId);
904                         }
905                     }, BiometricService.class.getName()
906             );
907         } catch (RemoteException e) {
908             Slog.e(TAG, "Failed to register user switch observer", e);
909         }
910     }
911 
912     @Override
onStart()913     public void onStart() {
914         // TODO: maybe get these on-demand
915         if (mHasFeatureFingerprint) {
916             mFingerprintService = IFingerprintService.Stub.asInterface(
917                     ServiceManager.getService(Context.FINGERPRINT_SERVICE));
918         }
919         if (mHasFeatureFace) {
920             mFaceService = IFaceService.Stub.asInterface(
921                     ServiceManager.getService(Context.FACE_SERVICE));
922         }
923 
924         mActivityTaskManager = ActivityTaskManager.getService();
925         mStatusBarService = IStatusBarService.Stub.asInterface(
926                 ServiceManager.getService(Context.STATUS_BAR_SERVICE));
927 
928         // Cache the authenticators
929         for (int i = 0; i < FEATURE_ID.length; i++) {
930             if (hasFeature(FEATURE_ID[i])) {
931                 Authenticator authenticator =
932                         new Authenticator(FEATURE_ID[i], getAuthenticator(FEATURE_ID[i]));
933                 mAuthenticators.add(authenticator);
934             }
935         }
936 
937         publishBinderService(Context.BIOMETRIC_SERVICE, new BiometricServiceWrapper());
938     }
939 
940     /**
941      * Checks if there are any available biometrics, and returns the modality. This method also
942      * returns errors through the callback (no biometric feature, hardware not detected, no
943      * templates enrolled, etc). This service must not start authentication if errors are sent.
944      *
945      * @Returns A pair [Modality, Error] with Modality being one of
946      * {@link BiometricAuthenticator#TYPE_NONE},
947      * {@link BiometricAuthenticator#TYPE_FINGERPRINT},
948      * {@link BiometricAuthenticator#TYPE_IRIS},
949      * {@link BiometricAuthenticator#TYPE_FACE}
950      * and the error containing one of the {@link BiometricConstants} errors.
951      */
checkAndGetBiometricModality(int userId)952     private Pair<Integer, Integer> checkAndGetBiometricModality(int userId) {
953         int modality = TYPE_NONE;
954 
955         // No biometric features, send error
956         if (mAuthenticators.isEmpty()) {
957             return new Pair<>(TYPE_NONE, BiometricConstants.BIOMETRIC_ERROR_HW_NOT_PRESENT);
958         }
959 
960         // Assuming that authenticators are listed in priority-order, the rest of this function
961         // will go through and find the first authenticator that's available, enrolled, and enabled.
962         // The tricky part is returning the correct error. Error strings that are modality-specific
963         // should also respect the priority-order.
964 
965         // Find first authenticator that's detected, enrolled, and enabled.
966         boolean isHardwareDetected = false;
967         boolean hasTemplatesEnrolled = false;
968         boolean enabledForApps = false;
969 
970         int firstHwAvailable = TYPE_NONE;
971         for (int i = 0; i < mAuthenticators.size(); i++) {
972             modality = mAuthenticators.get(i).getType();
973             BiometricAuthenticator authenticator = mAuthenticators.get(i).getAuthenticator();
974             if (authenticator.isHardwareDetected()) {
975                 isHardwareDetected = true;
976                 if (firstHwAvailable == TYPE_NONE) {
977                     // Store the first one since we want to return the error in correct priority
978                     // order.
979                     firstHwAvailable = modality;
980                 }
981                 if (authenticator.hasEnrolledTemplates(userId)) {
982                     hasTemplatesEnrolled = true;
983                     if (isEnabledForApp(modality, userId)) {
984                         // TODO(b/110907543): When face settings (and other settings) have both a
985                         // user toggle as well as a work profile settings page, this needs to be
986                         // updated to reflect the correct setting.
987                         enabledForApps = true;
988                         break;
989                     }
990                 }
991             }
992         }
993 
994         Slog.d(TAG, "checkAndGetBiometricModality: user=" + userId
995                 + " isHardwareDetected=" + isHardwareDetected
996                 + " hasTemplatesEnrolled=" + hasTemplatesEnrolled
997                 + " enabledForApps=" + enabledForApps);
998 
999         // Check error conditions
1000         if (!isHardwareDetected) {
1001             return new Pair<>(TYPE_NONE, BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE);
1002         } else if (!hasTemplatesEnrolled) {
1003             // Return the modality here so the correct error string can be sent. This error is
1004             // preferred over !enabledForApps
1005             return new Pair<>(firstHwAvailable, BiometricConstants.BIOMETRIC_ERROR_NO_BIOMETRICS);
1006         } else if (!enabledForApps) {
1007             return new Pair<>(TYPE_NONE, BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE);
1008         }
1009 
1010         return new Pair<>(modality, BiometricConstants.BIOMETRIC_SUCCESS);
1011     }
1012 
isEnabledForApp(int modality, int userId)1013     private boolean isEnabledForApp(int modality, int userId) {
1014         switch(modality) {
1015             case TYPE_FINGERPRINT:
1016                 return true;
1017             case TYPE_IRIS:
1018                 return true;
1019             case TYPE_FACE:
1020                 return mSettingObserver.getFaceEnabledForApps(userId);
1021             default:
1022                 Slog.w(TAG, "Unsupported modality: " + modality);
1023                 return false;
1024         }
1025     }
1026 
getErrorString(int type, int error, int vendorCode)1027     private String getErrorString(int type, int error, int vendorCode) {
1028         switch (type) {
1029             case TYPE_FINGERPRINT:
1030                 return FingerprintManager.getErrorString(getContext(), error, vendorCode);
1031             case TYPE_IRIS:
1032                 Slog.w(TAG, "Modality not supported");
1033                 return null; // not supported
1034             case TYPE_FACE:
1035                 return FaceManager.getErrorString(getContext(), error, vendorCode);
1036             default:
1037                 Slog.w(TAG, "Unable to get error string for modality: " + type);
1038                 return null;
1039         }
1040     }
1041 
getAuthenticator(int type)1042     private BiometricAuthenticator getAuthenticator(int type) {
1043         switch (type) {
1044             case TYPE_FINGERPRINT:
1045                 return (FingerprintManager)
1046                         getContext().getSystemService(Context.FINGERPRINT_SERVICE);
1047             case TYPE_IRIS:
1048                 return null;
1049             case TYPE_FACE:
1050                 return (FaceManager)
1051                         getContext().getSystemService(Context.FACE_SERVICE);
1052             default:
1053                 return null;
1054         }
1055     }
1056 
hasFeature(int type)1057     private boolean hasFeature(int type) {
1058         switch (type) {
1059             case TYPE_FINGERPRINT:
1060                 return mHasFeatureFingerprint;
1061             case TYPE_IRIS:
1062                 return mHasFeatureIris;
1063             case TYPE_FACE:
1064                 return mHasFeatureFace;
1065             default:
1066                 return false;
1067         }
1068     }
1069 
logDialogDismissed(int reason)1070     private void logDialogDismissed(int reason) {
1071         if (reason == BiometricPrompt.DISMISSED_REASON_POSITIVE) {
1072             // Explicit auth, authentication confirmed.
1073             // Latency in this case is authenticated -> confirmed. <Biometric>Service
1074             // should have the first half (first acquired -> authenticated).
1075             final long latency = System.currentTimeMillis()
1076                     - mCurrentAuthSession.mAuthenticatedTimeMs;
1077 
1078             if (LoggableMonitor.DEBUG) {
1079                 Slog.v(LoggableMonitor.TAG, "Confirmed! Modality: " + statsModality()
1080                         + ", User: " + mCurrentAuthSession.mUserId
1081                         + ", IsCrypto: " + mCurrentAuthSession.isCrypto()
1082                         + ", Client: " + BiometricsProtoEnums.CLIENT_BIOMETRIC_PROMPT
1083                         + ", RequireConfirmation: "
1084                         + mCurrentAuthSession.mRequireConfirmation
1085                         + ", State: " + StatsLog.BIOMETRIC_AUTHENTICATED__STATE__CONFIRMED
1086                         + ", Latency: " + latency);
1087             }
1088 
1089             StatsLog.write(StatsLog.BIOMETRIC_AUTHENTICATED,
1090                     statsModality(),
1091                     mCurrentAuthSession.mUserId,
1092                     mCurrentAuthSession.isCrypto(),
1093                     BiometricsProtoEnums.CLIENT_BIOMETRIC_PROMPT,
1094                     mCurrentAuthSession.mRequireConfirmation,
1095                     StatsLog.BIOMETRIC_AUTHENTICATED__STATE__CONFIRMED,
1096                     latency,
1097                     Utils.isDebugEnabled(getContext(), mCurrentAuthSession.mUserId));
1098         } else {
1099 
1100             final long latency = System.currentTimeMillis() - mCurrentAuthSession.mStartTimeMs;
1101 
1102             int error = reason == BiometricPrompt.DISMISSED_REASON_NEGATIVE
1103                     ? BiometricConstants.BIOMETRIC_ERROR_NEGATIVE_BUTTON
1104                     : reason == BiometricPrompt.DISMISSED_REASON_USER_CANCEL
1105                             ? BiometricConstants.BIOMETRIC_ERROR_USER_CANCELED
1106                             : 0;
1107             if (LoggableMonitor.DEBUG) {
1108                 Slog.v(LoggableMonitor.TAG, "Dismissed! Modality: " + statsModality()
1109                         + ", User: " + mCurrentAuthSession.mUserId
1110                         + ", IsCrypto: " + mCurrentAuthSession.isCrypto()
1111                         + ", Action: " + BiometricsProtoEnums.ACTION_AUTHENTICATE
1112                         + ", Client: " + BiometricsProtoEnums.CLIENT_BIOMETRIC_PROMPT
1113                         + ", Error: " + error
1114                         + ", Latency: " + latency);
1115             }
1116             // Auth canceled
1117             StatsLog.write(StatsLog.BIOMETRIC_ERROR_OCCURRED,
1118                     statsModality(),
1119                     mCurrentAuthSession.mUserId,
1120                     mCurrentAuthSession.isCrypto(),
1121                     BiometricsProtoEnums.ACTION_AUTHENTICATE,
1122                     BiometricsProtoEnums.CLIENT_BIOMETRIC_PROMPT,
1123                     error,
1124                     0 /* vendorCode */,
1125                     Utils.isDebugEnabled(getContext(), mCurrentAuthSession.mUserId),
1126                     latency);
1127         }
1128     }
1129 
statsModality()1130     private int statsModality() {
1131         int modality = 0;
1132         if (mCurrentAuthSession == null) {
1133             return BiometricsProtoEnums.MODALITY_UNKNOWN;
1134         }
1135         if ((mCurrentAuthSession.mModality & BiometricAuthenticator.TYPE_FINGERPRINT)
1136                 != 0) {
1137             modality |= BiometricsProtoEnums.MODALITY_FINGERPRINT;
1138         }
1139         if ((mCurrentAuthSession.mModality & BiometricAuthenticator.TYPE_IRIS) != 0) {
1140             modality |= BiometricsProtoEnums.MODALITY_IRIS;
1141         }
1142         if ((mCurrentAuthSession.mModality & BiometricAuthenticator.TYPE_FACE) != 0) {
1143             modality |= BiometricsProtoEnums.MODALITY_FACE;
1144         }
1145         return modality;
1146     }
1147 
handleTaskStackChanged()1148     private void handleTaskStackChanged() {
1149         try {
1150             final List<ActivityManager.RunningTaskInfo> runningTasks =
1151                     mActivityTaskManager.getTasks(1);
1152             if (!runningTasks.isEmpty()) {
1153                 final String topPackage = runningTasks.get(0).topActivity.getPackageName();
1154                 if (mCurrentAuthSession != null
1155                         && !topPackage.contentEquals(mCurrentAuthSession.mOpPackageName)) {
1156                     mStatusBarService.hideBiometricDialog();
1157                     mActivityTaskManager.unregisterTaskStackListener(mTaskStackListener);
1158                     mCurrentAuthSession.mClientReceiver.onError(
1159                             BiometricConstants.BIOMETRIC_ERROR_CANCELED,
1160                             getContext().getString(
1161                                     com.android.internal.R.string.biometric_error_canceled)
1162                     );
1163                     mCurrentAuthSession.mState = STATE_AUTH_IDLE;
1164                     mCurrentAuthSession = null;
1165                 }
1166             }
1167         } catch (RemoteException e) {
1168             Slog.e(TAG, "Unable to get running tasks", e);
1169         }
1170     }
1171 
handleAuthenticationSucceeded(boolean requireConfirmation, byte[] token)1172     private void handleAuthenticationSucceeded(boolean requireConfirmation, byte[] token) {
1173 
1174         try {
1175             // Should never happen, log this to catch bad HAL behavior (e.g. auth succeeded
1176             // after user dismissed/canceled dialog).
1177             if (mCurrentAuthSession == null) {
1178                 Slog.e(TAG, "onAuthenticationSucceeded(): Auth session is null");
1179                 return;
1180             }
1181 
1182             if (!requireConfirmation) {
1183                 mActivityTaskManager.unregisterTaskStackListener(mTaskStackListener);
1184                 KeyStore.getInstance().addAuthToken(token);
1185                 mCurrentAuthSession.mClientReceiver.onAuthenticationSucceeded();
1186                 mCurrentAuthSession.mState = STATE_AUTH_IDLE;
1187                 mCurrentAuthSession = null;
1188             } else {
1189                 mCurrentAuthSession.mAuthenticatedTimeMs = System.currentTimeMillis();
1190                 // Store the auth token and submit it to keystore after the confirmation
1191                 // button has been pressed.
1192                 mCurrentAuthSession.mTokenEscrow = token;
1193                 mCurrentAuthSession.mState = STATE_AUTH_PENDING_CONFIRM;
1194             }
1195 
1196             // Notify SysUI that the biometric has been authenticated. SysUI already knows
1197             // the implicit/explicit state and will react accordingly.
1198             mStatusBarService.onBiometricAuthenticated(true, null /* failureReason */);
1199         } catch (RemoteException e) {
1200             Slog.e(TAG, "Remote exception", e);
1201         }
1202     }
1203 
handleAuthenticationFailed(String failureReason)1204     private void handleAuthenticationFailed(String failureReason) {
1205         try {
1206             // Should never happen, log this to catch bad HAL behavior (e.g. auth succeeded
1207             // after user dismissed/canceled dialog).
1208             if (mCurrentAuthSession == null) {
1209                 Slog.e(TAG, "onAuthenticationFailed(): Auth session is null");
1210                 return;
1211             }
1212 
1213             mStatusBarService.onBiometricAuthenticated(false, failureReason);
1214 
1215             // TODO: This logic will need to be updated if BP is multi-modal
1216             if ((mCurrentAuthSession.mModality & TYPE_FACE) != 0) {
1217                 // Pause authentication. onBiometricAuthenticated(false) causes the
1218                 // dialog to show a "try again" button for passive modalities.
1219                 mCurrentAuthSession.mState = STATE_AUTH_PAUSED;
1220             }
1221 
1222             mCurrentAuthSession.mClientReceiver.onAuthenticationFailed();
1223         } catch (RemoteException e) {
1224             Slog.e(TAG, "Remote exception", e);
1225         }
1226     }
1227 
handleOnConfirmDeviceCredentialSuccess()1228     private void handleOnConfirmDeviceCredentialSuccess() {
1229         if (mConfirmDeviceCredentialReceiver == null) {
1230             Slog.w(TAG, "onCDCASuccess null!");
1231             return;
1232         }
1233         try {
1234             mActivityTaskManager.unregisterTaskStackListener(mTaskStackListener);
1235             mConfirmDeviceCredentialReceiver.onAuthenticationSucceeded();
1236             if (mCurrentAuthSession != null) {
1237                 mCurrentAuthSession.mState = STATE_AUTH_IDLE;
1238                 mCurrentAuthSession = null;
1239             }
1240         } catch (RemoteException e) {
1241             Slog.e(TAG, "RemoteException", e);
1242         }
1243         mConfirmDeviceCredentialReceiver = null;
1244     }
1245 
handleOnConfirmDeviceCredentialError(int error, String message)1246     private void handleOnConfirmDeviceCredentialError(int error, String message) {
1247         if (mConfirmDeviceCredentialReceiver == null) {
1248             Slog.w(TAG, "onCDCAError null! Error: " + error + " " + message);
1249             return;
1250         }
1251         try {
1252             mActivityTaskManager.unregisterTaskStackListener(mTaskStackListener);
1253             mConfirmDeviceCredentialReceiver.onError(error, message);
1254             if (mCurrentAuthSession != null) {
1255                 mCurrentAuthSession.mState = STATE_AUTH_IDLE;
1256                 mCurrentAuthSession = null;
1257             }
1258         } catch (RemoteException e) {
1259             Slog.e(TAG, "RemoteException", e);
1260         }
1261         mConfirmDeviceCredentialReceiver = null;
1262     }
1263 
handleRegisterCancellationCallback( IBiometricConfirmDeviceCredentialCallback callback)1264     private void handleRegisterCancellationCallback(
1265             IBiometricConfirmDeviceCredentialCallback callback) {
1266         if (mCurrentAuthSession == null) {
1267             Slog.d(TAG, "Current auth session null");
1268             return;
1269         }
1270         Slog.d(TAG, "Updating cancel callback");
1271         mCurrentAuthSession.mConfirmDeviceCredentialCallback = callback;
1272     }
1273 
handleOnError(int cookie, int error, String message)1274     private void handleOnError(int cookie, int error, String message) {
1275         Slog.d(TAG, "Error: " + error + " cookie: " + cookie);
1276         // Errors can either be from the current auth session or the pending auth session.
1277         // The pending auth session may receive errors such as ERROR_LOCKOUT before
1278         // it becomes the current auth session. Similarly, the current auth session may
1279         // receive errors such as ERROR_CANCELED while the pending auth session is preparing
1280         // to be started. Thus we must match error messages with their cookies to be sure
1281         // of their intended receivers.
1282         try {
1283             if (mCurrentAuthSession != null && mCurrentAuthSession.containsCookie(cookie)) {
1284 
1285                 if (mCurrentAuthSession.isFromConfirmDeviceCredential()) {
1286                     // If we were invoked by ConfirmDeviceCredential, do not delete the current
1287                     // auth session since we still need to respond to cancel signal while
1288                     if (DEBUG) Slog.d(TAG, "From CDC, transition to CANCELED_SHOWING_CDC state");
1289 
1290                     // Send the error to ConfirmDeviceCredential so that it goes to Pin/Pattern/Pass
1291                     // screen
1292                     mCurrentAuthSession.mClientReceiver.onError(error, message);
1293                     mCurrentAuthSession.mState = STATE_BIOMETRIC_AUTH_CANCELED_SHOWING_CDC;
1294                     mStatusBarService.hideBiometricDialog();
1295                 } else if (mCurrentAuthSession.mState == STATE_AUTH_STARTED) {
1296                     mStatusBarService.onBiometricError(message);
1297                     if (error == BiometricConstants.BIOMETRIC_ERROR_CANCELED) {
1298                         mActivityTaskManager.unregisterTaskStackListener(
1299                                 mTaskStackListener);
1300                         mCurrentAuthSession.mClientReceiver.onError(error, message);
1301                         mCurrentAuthSession.mState = STATE_AUTH_IDLE;
1302                         mCurrentAuthSession = null;
1303                         mStatusBarService.hideBiometricDialog();
1304                     } else {
1305                         // Send errors after the dialog is dismissed.
1306                         mHandler.postDelayed(() -> {
1307                             try {
1308                                 if (mCurrentAuthSession != null) {
1309                                     mActivityTaskManager.unregisterTaskStackListener(
1310                                             mTaskStackListener);
1311                                     mCurrentAuthSession.mClientReceiver.onError(error,
1312                                             message);
1313                                     mCurrentAuthSession.mState = STATE_AUTH_IDLE;
1314                                     mCurrentAuthSession = null;
1315                                 }
1316                             } catch (RemoteException e) {
1317                                 Slog.e(TAG, "Remote exception", e);
1318                             }
1319                         }, BiometricPrompt.HIDE_DIALOG_DELAY);
1320                     }
1321                 } else if (mCurrentAuthSession.mState == STATE_AUTH_PAUSED) {
1322                     // In the "try again" state, we should forward canceled errors to
1323                     // the client and and clean up.
1324                     mCurrentAuthSession.mClientReceiver.onError(error, message);
1325                     mStatusBarService.onBiometricError(message);
1326                     mActivityTaskManager.unregisterTaskStackListener(
1327                             mTaskStackListener);
1328                     mCurrentAuthSession.mState = STATE_AUTH_IDLE;
1329                     mCurrentAuthSession = null;
1330                 } else {
1331                     Slog.e(TAG, "Impossible session error state: "
1332                             + mCurrentAuthSession.mState);
1333                 }
1334             } else if (mPendingAuthSession != null
1335                     && mPendingAuthSession.containsCookie(cookie)) {
1336                 if (mPendingAuthSession.mState == STATE_AUTH_CALLED) {
1337                     mPendingAuthSession.mClientReceiver.onError(error, message);
1338                     mPendingAuthSession.mState = STATE_AUTH_IDLE;
1339                     mPendingAuthSession = null;
1340                 } else {
1341                     Slog.e(TAG, "Impossible pending session error state: "
1342                             + mPendingAuthSession.mState);
1343                 }
1344             }
1345         } catch (RemoteException e) {
1346             Slog.e(TAG, "Remote exception", e);
1347         }
1348     }
1349 
handleOnAcquired(int acquiredInfo, String message)1350     private void handleOnAcquired(int acquiredInfo, String message) {
1351         // Should never happen, log this to catch bad HAL behavior (e.g. auth succeeded
1352         // after user dismissed/canceled dialog).
1353         if (mCurrentAuthSession == null) {
1354             Slog.e(TAG, "onAcquired(): Auth session is null");
1355             return;
1356         }
1357 
1358         if (acquiredInfo != BiometricConstants.BIOMETRIC_ACQUIRED_GOOD) {
1359             if (message == null) {
1360                 Slog.w(TAG, "Ignoring null message: " + acquiredInfo);
1361                 return;
1362             }
1363             try {
1364                 mStatusBarService.onBiometricHelp(message);
1365             } catch (RemoteException e) {
1366                 Slog.e(TAG, "Remote exception", e);
1367             }
1368         }
1369     }
1370 
handleOnDismissed(int reason)1371     private void handleOnDismissed(int reason) {
1372         if (mCurrentAuthSession == null) {
1373             Slog.e(TAG, "onDialogDismissed: " + reason + ", auth session null");
1374             return;
1375         }
1376 
1377         logDialogDismissed(reason);
1378 
1379         try {
1380             if (reason != BiometricPrompt.DISMISSED_REASON_POSITIVE) {
1381                 // Positive button is used by passive modalities as a "confirm" button,
1382                 // do not send to client
1383                 mCurrentAuthSession.mClientReceiver.onDialogDismissed(reason);
1384                 // Cancel authentication. Skip the token/package check since we are cancelling
1385                 // from system server. The interface is permission protected so this is fine.
1386                 cancelInternal(null /* token */, null /* package */, false /* fromClient */);
1387             }
1388             if (reason == BiometricPrompt.DISMISSED_REASON_USER_CANCEL) {
1389                 mCurrentAuthSession.mClientReceiver.onError(
1390                         BiometricConstants.BIOMETRIC_ERROR_USER_CANCELED,
1391                         getContext().getString(
1392                                 com.android.internal.R.string.biometric_error_user_canceled));
1393             } else if (reason == BiometricPrompt.DISMISSED_REASON_POSITIVE) {
1394                 // Have the service send the token to KeyStore, and send onAuthenticated
1395                 // to the application
1396                 KeyStore.getInstance().addAuthToken(mCurrentAuthSession.mTokenEscrow);
1397                 mCurrentAuthSession.mClientReceiver.onAuthenticationSucceeded();
1398             }
1399 
1400             // Do not clean up yet if we are from ConfirmDeviceCredential. We should be in the
1401             // STATE_BIOMETRIC_AUTH_CANCELED_SHOWING_CDC. The session should only be removed when
1402             // ConfirmDeviceCredential is confirmed or canceled.
1403             // TODO(b/123378871): Remove when moved
1404             if (!mCurrentAuthSession.isFromConfirmDeviceCredential()) {
1405                 mActivityTaskManager.unregisterTaskStackListener(mTaskStackListener);
1406                 mCurrentAuthSession.mState = STATE_AUTH_IDLE;
1407                 mCurrentAuthSession = null;
1408             }
1409         } catch (RemoteException e) {
1410             Slog.e(TAG, "Remote exception", e);
1411         }
1412     }
1413 
handleOnTryAgainPressed()1414     private void handleOnTryAgainPressed() {
1415         Slog.d(TAG, "onTryAgainPressed");
1416         // No need to check permission, since it can only be invoked by SystemUI
1417         // (or system server itself).
1418         authenticateInternal(mCurrentAuthSession.mToken,
1419                 mCurrentAuthSession.mSessionId,
1420                 mCurrentAuthSession.mUserId,
1421                 mCurrentAuthSession.mClientReceiver,
1422                 mCurrentAuthSession.mOpPackageName,
1423                 mCurrentAuthSession.mBundle,
1424                 mCurrentAuthSession.mCallingUid,
1425                 mCurrentAuthSession.mCallingPid,
1426                 mCurrentAuthSession.mCallingUserId,
1427                 mCurrentAuthSession.mModality,
1428                 mCurrentAuthSession.mConfirmDeviceCredentialCallback);
1429     }
1430 
handleOnReadyForAuthentication(int cookie, boolean requireConfirmation, int userId)1431     private void handleOnReadyForAuthentication(int cookie, boolean requireConfirmation,
1432             int userId) {
1433         Iterator it = mPendingAuthSession.mModalitiesWaiting.entrySet().iterator();
1434         while (it.hasNext()) {
1435             Map.Entry<Integer, Integer> pair = (Map.Entry) it.next();
1436             if (pair.getValue() == cookie) {
1437                 mPendingAuthSession.mModalitiesMatched.put(pair.getKey(), pair.getValue());
1438                 mPendingAuthSession.mModalitiesWaiting.remove(pair.getKey());
1439                 Slog.d(TAG, "Matched cookie: " + cookie + ", "
1440                         + mPendingAuthSession.mModalitiesWaiting.size() + " remaining");
1441                 break;
1442             }
1443         }
1444 
1445         if (mPendingAuthSession.mModalitiesWaiting.isEmpty()) {
1446             final boolean continuing = mCurrentAuthSession != null
1447                     && mCurrentAuthSession.mState == STATE_AUTH_PAUSED;
1448 
1449             mCurrentAuthSession = mPendingAuthSession;
1450 
1451             // Time starts when lower layers are ready to start the client.
1452             mCurrentAuthSession.mStartTimeMs = System.currentTimeMillis();
1453             mPendingAuthSession = null;
1454 
1455             mCurrentAuthSession.mState = STATE_AUTH_STARTED;
1456             try {
1457                 int modality = TYPE_NONE;
1458                 it = mCurrentAuthSession.mModalitiesMatched.entrySet().iterator();
1459                 while (it.hasNext()) {
1460                     Map.Entry<Integer, Integer> pair = (Map.Entry) it.next();
1461                     if (pair.getKey() == TYPE_FINGERPRINT) {
1462                         mFingerprintService.startPreparedClient(pair.getValue());
1463                     } else if (pair.getKey() == TYPE_IRIS) {
1464                         Slog.e(TAG, "Iris unsupported");
1465                     } else if (pair.getKey() == TYPE_FACE) {
1466                         mFaceService.startPreparedClient(pair.getValue());
1467                     } else {
1468                         Slog.e(TAG, "Unknown modality: " + pair.getKey());
1469                     }
1470                     modality |= pair.getKey();
1471                 }
1472 
1473                 if (!continuing) {
1474                     mStatusBarService.showBiometricDialog(mCurrentAuthSession.mBundle,
1475                             mInternalReceiver, modality, requireConfirmation, userId);
1476                     mActivityTaskManager.registerTaskStackListener(mTaskStackListener);
1477                 }
1478             } catch (RemoteException e) {
1479                 Slog.e(TAG, "Remote exception", e);
1480             }
1481         }
1482     }
1483 
handleAuthenticate(IBinder token, long sessionId, int userId, IBiometricServiceReceiver receiver, String opPackageName, Bundle bundle, int callingUid, int callingPid, int callingUserId, IBiometricConfirmDeviceCredentialCallback callback)1484     private void handleAuthenticate(IBinder token, long sessionId, int userId,
1485             IBiometricServiceReceiver receiver, String opPackageName, Bundle bundle,
1486             int callingUid, int callingPid, int callingUserId,
1487             IBiometricConfirmDeviceCredentialCallback callback) {
1488 
1489         mHandler.post(() -> {
1490             final Pair<Integer, Integer> result = checkAndGetBiometricModality(userId);
1491             final int modality = result.first;
1492             final int error = result.second;
1493 
1494             // Check for errors, notify callback, and return
1495             if (error != BiometricConstants.BIOMETRIC_SUCCESS) {
1496                 try {
1497                     final String hardwareUnavailable =
1498                             getContext().getString(R.string.biometric_error_hw_unavailable);
1499                     switch (error) {
1500                         case BiometricConstants.BIOMETRIC_ERROR_HW_NOT_PRESENT:
1501                             receiver.onError(error, hardwareUnavailable);
1502                             break;
1503                         case BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE:
1504                             receiver.onError(error, hardwareUnavailable);
1505                             break;
1506                         case BiometricConstants.BIOMETRIC_ERROR_NO_BIOMETRICS:
1507                             receiver.onError(error,
1508                                     getErrorString(modality, error, 0 /* vendorCode */));
1509                             break;
1510                         default:
1511                             Slog.e(TAG, "Unhandled error");
1512                             break;
1513                     }
1514                 } catch (RemoteException e) {
1515                     Slog.e(TAG, "Unable to send error", e);
1516                 }
1517                 return;
1518             }
1519 
1520             mCurrentModality = modality;
1521 
1522             // Start preparing for authentication. Authentication starts when
1523             // all modalities requested have invoked onReadyForAuthentication.
1524             authenticateInternal(token, sessionId, userId, receiver, opPackageName, bundle,
1525                     callingUid, callingPid, callingUserId, modality, callback);
1526         });
1527     }
1528 
1529     /**
1530      * authenticate() (above) which is called from BiometricPrompt determines which
1531      * modality/modalities to start authenticating with. authenticateInternal() should only be
1532      * used for:
1533      * 1) Preparing <Biometric>Services for authentication when BiometricPrompt#authenticate is,
1534      *    invoked, shortly after which BiometricPrompt is shown and authentication starts
1535      * 2) Preparing <Biometric>Services for authentication when BiometricPrompt is already shown
1536      *    and the user has pressed "try again"
1537      */
authenticateInternal(IBinder token, long sessionId, int userId, IBiometricServiceReceiver receiver, String opPackageName, Bundle bundle, int callingUid, int callingPid, int callingUserId, int modality, IBiometricConfirmDeviceCredentialCallback callback)1538     private void authenticateInternal(IBinder token, long sessionId, int userId,
1539             IBiometricServiceReceiver receiver, String opPackageName, Bundle bundle,
1540             int callingUid, int callingPid, int callingUserId, int modality,
1541             IBiometricConfirmDeviceCredentialCallback callback) {
1542         try {
1543             boolean requireConfirmation = bundle.getBoolean(
1544                     BiometricPrompt.KEY_REQUIRE_CONFIRMATION, true /* default */);
1545             if ((modality & TYPE_FACE) != 0) {
1546                 // Check if the user has forced confirmation to be required in Settings.
1547                 requireConfirmation = requireConfirmation
1548                         || mSettingObserver.getFaceAlwaysRequireConfirmation(userId);
1549             }
1550             // Generate random cookies to pass to the services that should prepare to start
1551             // authenticating. Store the cookie here and wait for all services to "ack"
1552             // with the cookie. Once all cookies are received, we can show the prompt
1553             // and let the services start authenticating. The cookie should be non-zero.
1554             final int cookie = mRandom.nextInt(Integer.MAX_VALUE - 1) + 1;
1555             Slog.d(TAG, "Creating auth session. Modality: " + modality
1556                     + ", cookie: " + cookie);
1557             final HashMap<Integer, Integer> authenticators = new HashMap<>();
1558             authenticators.put(modality, cookie);
1559             mPendingAuthSession = new AuthSession(authenticators, token, sessionId, userId,
1560                     receiver, opPackageName, bundle, callingUid, callingPid, callingUserId,
1561                     modality, requireConfirmation, callback);
1562             mPendingAuthSession.mState = STATE_AUTH_CALLED;
1563             // No polymorphism :(
1564             if ((modality & TYPE_FINGERPRINT) != 0) {
1565                 mFingerprintService.prepareForAuthentication(token, sessionId, userId,
1566                         mInternalReceiver, opPackageName, cookie,
1567                         callingUid, callingPid, callingUserId);
1568             }
1569             if ((modality & TYPE_IRIS) != 0) {
1570                 Slog.w(TAG, "Iris unsupported");
1571             }
1572             if ((modality & TYPE_FACE) != 0) {
1573                 mFaceService.prepareForAuthentication(requireConfirmation,
1574                         token, sessionId, userId, mInternalReceiver, opPackageName,
1575                         cookie, callingUid, callingPid, callingUserId);
1576             }
1577         } catch (RemoteException e) {
1578             Slog.e(TAG, "Unable to start authentication", e);
1579         }
1580     }
1581 
handleCancelAuthentication(IBinder token, String opPackageName)1582     private void handleCancelAuthentication(IBinder token, String opPackageName) {
1583         if (token == null || opPackageName == null) {
1584             Slog.e(TAG, "Unable to cancel, one or more null arguments");
1585             return;
1586         }
1587 
1588         if (mCurrentAuthSession != null
1589                 && mCurrentAuthSession.mState == STATE_BIOMETRIC_AUTH_CANCELED_SHOWING_CDC) {
1590             if (DEBUG) Slog.d(TAG, "Cancel received while ConfirmDeviceCredential showing");
1591             try {
1592                 mCurrentAuthSession.mConfirmDeviceCredentialCallback.cancel();
1593             } catch (RemoteException e) {
1594                 Slog.e(TAG, "Unable to cancel ConfirmDeviceCredential", e);
1595             }
1596 
1597             // TODO(b/123378871): Remove when moved. Piggy back on this for now to clean up.
1598             handleOnConfirmDeviceCredentialError(BiometricConstants.BIOMETRIC_ERROR_CANCELED,
1599                     getContext().getString(R.string.biometric_error_canceled));
1600         } else if (mCurrentAuthSession != null
1601                 && mCurrentAuthSession.mState != STATE_AUTH_STARTED) {
1602             // We need to check the current authenticators state. If we're pending confirm
1603             // or idle, we need to dismiss the dialog and send an ERROR_CANCELED to the client,
1604             // since we won't be getting an onError from the driver.
1605             try {
1606                 // Send error to client
1607                 mCurrentAuthSession.mClientReceiver.onError(
1608                         BiometricConstants.BIOMETRIC_ERROR_CANCELED,
1609                         getContext().getString(
1610                                 com.android.internal.R.string.biometric_error_user_canceled)
1611                 );
1612 
1613                 mCurrentAuthSession.mState = STATE_AUTH_IDLE;
1614                 mCurrentAuthSession = null;
1615                 mStatusBarService.hideBiometricDialog();
1616             } catch (RemoteException e) {
1617                 Slog.e(TAG, "Remote exception", e);
1618             }
1619         } else {
1620             boolean fromCDC = false;
1621             if (mCurrentAuthSession != null) {
1622                 fromCDC = mCurrentAuthSession.mBundle.getBoolean(
1623                         BiometricPrompt.KEY_FROM_CONFIRM_DEVICE_CREDENTIAL, false);
1624             }
1625 
1626             if (fromCDC) {
1627                 if (DEBUG) Slog.d(TAG, "Cancelling from CDC");
1628                 cancelInternal(token, opPackageName, false /* fromClient */);
1629             } else {
1630                 cancelInternal(token, opPackageName, true /* fromClient */);
1631             }
1632 
1633         }
1634     }
1635 
cancelInternal(IBinder token, String opPackageName, boolean fromClient)1636     void cancelInternal(IBinder token, String opPackageName, boolean fromClient) {
1637         final int callingUid = Binder.getCallingUid();
1638         final int callingPid = Binder.getCallingPid();
1639         final int callingUserId = UserHandle.getCallingUserId();
1640         mHandler.post(() -> {
1641             try {
1642                 // TODO: For multiple modalities, send a single ERROR_CANCELED only when all
1643                 // drivers have canceled authentication.
1644                 if ((mCurrentModality & TYPE_FINGERPRINT) != 0) {
1645                     mFingerprintService.cancelAuthenticationFromService(token, opPackageName,
1646                             callingUid, callingPid, callingUserId, fromClient);
1647                 }
1648                 if ((mCurrentModality & TYPE_IRIS) != 0) {
1649                     Slog.w(TAG, "Iris unsupported");
1650                 }
1651                 if ((mCurrentModality & TYPE_FACE) != 0) {
1652                     mFaceService.cancelAuthenticationFromService(token, opPackageName,
1653                             callingUid, callingPid, callingUserId, fromClient);
1654                 }
1655             } catch (RemoteException e) {
1656                 Slog.e(TAG, "Unable to cancel authentication");
1657             }
1658         });
1659     }
1660 
1661 }
1662