• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_INTERNAL;
20 import static android.hardware.biometrics.BiometricManager.Authenticators;
21 
22 import static com.android.server.biometrics.BiometricServiceStateProto.STATE_AUTH_IDLE;
23 
24 import android.annotation.NonNull;
25 import android.annotation.Nullable;
26 import android.app.ActivityManager;
27 import android.app.IActivityManager;
28 import android.app.UserSwitchObserver;
29 import android.app.admin.DevicePolicyManager;
30 import android.app.trust.ITrustManager;
31 import android.content.ContentResolver;
32 import android.content.Context;
33 import android.content.pm.PackageManager;
34 import android.database.ContentObserver;
35 import android.hardware.biometrics.BiometricAuthenticator;
36 import android.hardware.biometrics.BiometricConstants;
37 import android.hardware.biometrics.BiometricPrompt;
38 import android.hardware.biometrics.IBiometricAuthenticator;
39 import android.hardware.biometrics.IBiometricEnabledOnKeyguardCallback;
40 import android.hardware.biometrics.IBiometricSensorReceiver;
41 import android.hardware.biometrics.IBiometricService;
42 import android.hardware.biometrics.IBiometricServiceReceiver;
43 import android.hardware.biometrics.IBiometricSysuiReceiver;
44 import android.hardware.biometrics.IInvalidationCallback;
45 import android.hardware.biometrics.ITestSession;
46 import android.hardware.biometrics.ITestSessionCallback;
47 import android.hardware.biometrics.PromptInfo;
48 import android.hardware.biometrics.SensorPropertiesInternal;
49 import android.hardware.fingerprint.FingerprintManager;
50 import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
51 import android.net.Uri;
52 import android.os.Binder;
53 import android.os.Build;
54 import android.os.DeadObjectException;
55 import android.os.Handler;
56 import android.os.IBinder;
57 import android.os.Looper;
58 import android.os.RemoteException;
59 import android.os.ServiceManager;
60 import android.os.UserHandle;
61 import android.provider.Settings;
62 import android.security.KeyStore;
63 import android.text.TextUtils;
64 import android.util.ArraySet;
65 import android.util.Pair;
66 import android.util.Slog;
67 import android.util.proto.ProtoOutputStream;
68 
69 import com.android.internal.R;
70 import com.android.internal.annotations.VisibleForTesting;
71 import com.android.internal.os.SomeArgs;
72 import com.android.internal.statusbar.IStatusBarService;
73 import com.android.internal.util.DumpUtils;
74 import com.android.server.SystemService;
75 import com.android.server.biometrics.sensors.CoexCoordinator;
76 
77 import java.io.FileDescriptor;
78 import java.io.PrintWriter;
79 import java.util.ArrayList;
80 import java.util.HashMap;
81 import java.util.List;
82 import java.util.Map;
83 import java.util.Random;
84 import java.util.Set;
85 import java.util.concurrent.atomic.AtomicLong;
86 import java.util.function.Supplier;
87 
88 /**
89  * System service that arbitrates the modality for BiometricPrompt to use.
90  */
91 public class BiometricService extends SystemService {
92 
93     static final String TAG = "BiometricService";
94 
95     private final Injector mInjector;
96     private final DevicePolicyManager mDevicePolicyManager;
97     @VisibleForTesting
98     final IBiometricService.Stub mImpl;
99     @VisibleForTesting
100     final SettingObserver mSettingObserver;
101     private final List<EnabledOnKeyguardCallback> mEnabledOnKeyguardCallbacks;
102     private final Random mRandom = new Random();
103     @NonNull private final Supplier<Long> mRequestCounter;
104 
105     @VisibleForTesting
106     IStatusBarService mStatusBarService;
107     @VisibleForTesting
108     KeyStore mKeyStore;
109     @VisibleForTesting
110     ITrustManager mTrustManager;
111 
112     // Get and cache the available biometric authenticators and their associated info.
113     final ArrayList<BiometricSensor> mSensors = new ArrayList<>();
114 
115     @VisibleForTesting
116     BiometricStrengthController mBiometricStrengthController;
117 
118     // The current authentication session, null if idle/done.
119     @VisibleForTesting
120     AuthSession mAuthSession;
121     private final Handler mHandler = new Handler(Looper.getMainLooper());
122 
123     /**
124      * Tracks authenticatorId invalidation. For more details, see
125      * {@link com.android.server.biometrics.sensors.InvalidationRequesterClient}.
126      */
127     @VisibleForTesting
128     static class InvalidationTracker {
129         @NonNull private final IInvalidationCallback mClientCallback;
130         @NonNull private final Set<Integer> mSensorsPendingInvalidation;
131 
start(@onNull Context context, @NonNull ArrayList<BiometricSensor> sensors, int userId, int fromSensorId, @NonNull IInvalidationCallback clientCallback)132         public static InvalidationTracker start(@NonNull Context context,
133                 @NonNull ArrayList<BiometricSensor> sensors,
134                 int userId, int fromSensorId, @NonNull IInvalidationCallback clientCallback) {
135             return new InvalidationTracker(context, sensors, userId, fromSensorId, clientCallback);
136         }
137 
InvalidationTracker(@onNull Context context, @NonNull ArrayList<BiometricSensor> sensors, int userId, int fromSensorId, @NonNull IInvalidationCallback clientCallback)138         private InvalidationTracker(@NonNull Context context,
139                 @NonNull ArrayList<BiometricSensor> sensors, int userId,
140                 int fromSensorId, @NonNull IInvalidationCallback clientCallback) {
141             mClientCallback = clientCallback;
142             mSensorsPendingInvalidation = new ArraySet<>();
143 
144             for (BiometricSensor sensor : sensors) {
145                 if (sensor.id == fromSensorId) {
146                     continue;
147                 }
148 
149                 if (!Utils.isAtLeastStrength(sensor.oemStrength, Authenticators.BIOMETRIC_STRONG)) {
150                     continue;
151                 }
152 
153                 try {
154                     if (!sensor.impl.hasEnrolledTemplates(userId, context.getOpPackageName())) {
155                         continue;
156                     }
157                 } catch (RemoteException e) {
158                     Slog.e(TAG, "Remote Exception", e);
159                 }
160 
161                 Slog.d(TAG, "Requesting authenticatorId invalidation for sensor: " + sensor.id);
162 
163                 synchronized (this) {
164                     mSensorsPendingInvalidation.add(sensor.id);
165                 }
166 
167                 try {
168                     sensor.impl.invalidateAuthenticatorId(userId, new IInvalidationCallback.Stub() {
169                         @Override
170                         public void onCompleted() {
171                             onInvalidated(sensor.id);
172                         }
173                     });
174                 } catch (RemoteException e) {
175                     Slog.d(TAG, "RemoteException", e);
176                 }
177             }
178 
179             synchronized (this) {
180                 if (mSensorsPendingInvalidation.isEmpty()) {
181                     try {
182                         Slog.d(TAG, "No sensors require invalidation");
183                         mClientCallback.onCompleted();
184                     } catch (RemoteException e) {
185                         Slog.e(TAG, "Remote Exception", e);
186                     }
187                 }
188             }
189         }
190 
191         @VisibleForTesting
onInvalidated(int sensorId)192         void onInvalidated(int sensorId) {
193             synchronized (this) {
194                 mSensorsPendingInvalidation.remove(sensorId);
195 
196                 Slog.d(TAG, "Sensor " + sensorId + " invalidated, remaining size: "
197                         + mSensorsPendingInvalidation.size());
198 
199                 if (mSensorsPendingInvalidation.isEmpty()) {
200                     try {
201                         mClientCallback.onCompleted();
202                     } catch (RemoteException e) {
203                         Slog.e(TAG, "Remote Exception", e);
204                     }
205                 }
206             }
207         }
208     }
209 
210     @VisibleForTesting
211     public static class SettingObserver extends ContentObserver {
212 
213         private static final boolean DEFAULT_KEYGUARD_ENABLED = true;
214         private static final boolean DEFAULT_APP_ENABLED = true;
215         private static final boolean DEFAULT_ALWAYS_REQUIRE_CONFIRMATION = false;
216 
217         // Some devices that shipped before S already have face-specific settings. Instead of
218         // migrating, which is complicated, let's just keep using the existing settings.
219         private final boolean mUseLegacyFaceOnlySettings;
220 
221         // Only used for legacy face-only devices
222         private final Uri FACE_UNLOCK_KEYGUARD_ENABLED =
223                 Settings.Secure.getUriFor(Settings.Secure.FACE_UNLOCK_KEYGUARD_ENABLED);
224         private final Uri FACE_UNLOCK_APP_ENABLED =
225                 Settings.Secure.getUriFor(Settings.Secure.FACE_UNLOCK_APP_ENABLED);
226 
227         // Continues to be used, even though it's face-specific.
228         private final Uri FACE_UNLOCK_ALWAYS_REQUIRE_CONFIRMATION =
229                 Settings.Secure.getUriFor(Settings.Secure.FACE_UNLOCK_ALWAYS_REQUIRE_CONFIRMATION);
230 
231         // Used for all devices other than legacy face-only devices
232         private final Uri BIOMETRIC_KEYGUARD_ENABLED =
233                 Settings.Secure.getUriFor(Settings.Secure.BIOMETRIC_KEYGUARD_ENABLED);
234         private final Uri BIOMETRIC_APP_ENABLED =
235                 Settings.Secure.getUriFor(Settings.Secure.BIOMETRIC_APP_ENABLED);
236 
237         private final ContentResolver mContentResolver;
238         private final List<BiometricService.EnabledOnKeyguardCallback> mCallbacks;
239 
240         private final Map<Integer, Boolean> mBiometricEnabledOnKeyguard = new HashMap<>();
241         private final Map<Integer, Boolean> mBiometricEnabledForApps = new HashMap<>();
242         private final Map<Integer, Boolean> mFaceAlwaysRequireConfirmation = new HashMap<>();
243 
244         /**
245          * Creates a content observer.
246          *
247          * @param handler The handler to run {@link #onChange} on, or null if none.
248          */
SettingObserver(Context context, Handler handler, List<BiometricService.EnabledOnKeyguardCallback> callbacks)249         public SettingObserver(Context context, Handler handler,
250                 List<BiometricService.EnabledOnKeyguardCallback> callbacks) {
251             super(handler);
252             mContentResolver = context.getContentResolver();
253             mCallbacks = callbacks;
254 
255             final boolean hasFingerprint = context.getPackageManager()
256                     .hasSystemFeature(PackageManager.FEATURE_FINGERPRINT);
257             final boolean hasFace = context.getPackageManager()
258                     .hasSystemFeature(PackageManager.FEATURE_FACE);
259 
260             // Use the legacy setting on face-only devices that shipped on or before Q
261             mUseLegacyFaceOnlySettings =
262                     Build.VERSION.DEVICE_INITIAL_SDK_INT <= Build.VERSION_CODES.Q
263                     && hasFace && !hasFingerprint;
264 
265             updateContentObserver();
266         }
267 
updateContentObserver()268         public void updateContentObserver() {
269             mContentResolver.unregisterContentObserver(this);
270 
271             if (mUseLegacyFaceOnlySettings) {
272                 mContentResolver.registerContentObserver(FACE_UNLOCK_KEYGUARD_ENABLED,
273                         false /* notifyForDescendants */,
274                         this /* observer */,
275                         UserHandle.USER_ALL);
276                 mContentResolver.registerContentObserver(FACE_UNLOCK_APP_ENABLED,
277                         false /* notifyForDescendants */,
278                         this /* observer */,
279                         UserHandle.USER_ALL);
280             } else {
281                 mContentResolver.registerContentObserver(BIOMETRIC_KEYGUARD_ENABLED,
282                         false /* notifyForDescendants */,
283                         this /* observer */,
284                         UserHandle.USER_ALL);
285                 mContentResolver.registerContentObserver(BIOMETRIC_APP_ENABLED,
286                         false /* notifyForDescendants */,
287                         this /* observer */,
288                         UserHandle.USER_ALL);
289             }
290             mContentResolver.registerContentObserver(FACE_UNLOCK_ALWAYS_REQUIRE_CONFIRMATION,
291                     false /* notifyForDescendants */,
292                     this /* observer */,
293                     UserHandle.USER_ALL);
294         }
295 
296         @Override
onChange(boolean selfChange, Uri uri, int userId)297         public void onChange(boolean selfChange, Uri uri, int userId) {
298             if (FACE_UNLOCK_KEYGUARD_ENABLED.equals(uri)) {
299                 mBiometricEnabledOnKeyguard.put(userId, Settings.Secure.getIntForUser(
300                                 mContentResolver,
301                                 Settings.Secure.FACE_UNLOCK_KEYGUARD_ENABLED,
302                                 DEFAULT_KEYGUARD_ENABLED ? 1 : 0 /* default */,
303                                 userId) != 0);
304 
305                 if (userId == ActivityManager.getCurrentUser() && !selfChange) {
306                     notifyEnabledOnKeyguardCallbacks(userId);
307                 }
308             } else if (FACE_UNLOCK_APP_ENABLED.equals(uri)) {
309                 mBiometricEnabledForApps.put(userId, Settings.Secure.getIntForUser(
310                                 mContentResolver,
311                                 Settings.Secure.FACE_UNLOCK_APP_ENABLED,
312                                 DEFAULT_APP_ENABLED ? 1 : 0 /* default */,
313                                 userId) != 0);
314             } else if (FACE_UNLOCK_ALWAYS_REQUIRE_CONFIRMATION.equals(uri)) {
315                 mFaceAlwaysRequireConfirmation.put(userId, Settings.Secure.getIntForUser(
316                                 mContentResolver,
317                                 Settings.Secure.FACE_UNLOCK_ALWAYS_REQUIRE_CONFIRMATION,
318                                 DEFAULT_ALWAYS_REQUIRE_CONFIRMATION ? 1 : 0 /* default */,
319                                 userId) != 0);
320             } else if (BIOMETRIC_KEYGUARD_ENABLED.equals(uri)) {
321                 mBiometricEnabledOnKeyguard.put(userId, Settings.Secure.getIntForUser(
322                         mContentResolver,
323                         Settings.Secure.BIOMETRIC_KEYGUARD_ENABLED,
324                         DEFAULT_KEYGUARD_ENABLED ? 1 : 0 /* default */,
325                         userId) != 0);
326 
327                 if (userId == ActivityManager.getCurrentUser() && !selfChange) {
328                     notifyEnabledOnKeyguardCallbacks(userId);
329                 }
330             } else if (BIOMETRIC_APP_ENABLED.equals(uri)) {
331                 mBiometricEnabledForApps.put(userId, Settings.Secure.getIntForUser(
332                         mContentResolver,
333                         Settings.Secure.BIOMETRIC_APP_ENABLED,
334                         DEFAULT_APP_ENABLED ? 1 : 0 /* default */,
335                         userId) != 0);
336             }
337         }
338 
getEnabledOnKeyguard(int userId)339         public boolean getEnabledOnKeyguard(int userId) {
340             if (!mBiometricEnabledOnKeyguard.containsKey(userId)) {
341                 if (mUseLegacyFaceOnlySettings) {
342                     onChange(true /* selfChange */, FACE_UNLOCK_KEYGUARD_ENABLED, userId);
343                 } else {
344                     onChange(true /* selfChange */, BIOMETRIC_KEYGUARD_ENABLED, userId);
345                 }
346             }
347             return mBiometricEnabledOnKeyguard.get(userId);
348         }
349 
getEnabledForApps(int userId)350         public boolean getEnabledForApps(int userId) {
351             if (!mBiometricEnabledForApps.containsKey(userId)) {
352                 if (mUseLegacyFaceOnlySettings) {
353                     onChange(true /* selfChange */, FACE_UNLOCK_APP_ENABLED, userId);
354                 } else {
355                     onChange(true /* selfChange */, BIOMETRIC_APP_ENABLED, userId);
356                 }
357             }
358             return mBiometricEnabledForApps.getOrDefault(userId, DEFAULT_APP_ENABLED);
359         }
360 
getConfirmationAlwaysRequired(@iometricAuthenticator.Modality int modality, int userId)361         public boolean getConfirmationAlwaysRequired(@BiometricAuthenticator.Modality int modality,
362                 int userId) {
363             switch (modality) {
364                 case BiometricAuthenticator.TYPE_FACE:
365                     if (!mFaceAlwaysRequireConfirmation.containsKey(userId)) {
366                         onChange(true /* selfChange */,
367                                 FACE_UNLOCK_ALWAYS_REQUIRE_CONFIRMATION,
368                                 userId);
369                     }
370                     return mFaceAlwaysRequireConfirmation.get(userId);
371 
372                 default:
373                     return false;
374             }
375         }
376 
notifyEnabledOnKeyguardCallbacks(int userId)377         void notifyEnabledOnKeyguardCallbacks(int userId) {
378             List<EnabledOnKeyguardCallback> callbacks = mCallbacks;
379             for (int i = 0; i < callbacks.size(); i++) {
380                 callbacks.get(i).notify(
381                         mBiometricEnabledOnKeyguard.getOrDefault(userId, DEFAULT_KEYGUARD_ENABLED),
382                         userId);
383             }
384         }
385     }
386 
387     final class EnabledOnKeyguardCallback implements IBinder.DeathRecipient {
388 
389         private final IBiometricEnabledOnKeyguardCallback mCallback;
390 
EnabledOnKeyguardCallback(IBiometricEnabledOnKeyguardCallback callback)391         EnabledOnKeyguardCallback(IBiometricEnabledOnKeyguardCallback callback) {
392             mCallback = callback;
393             try {
394                 mCallback.asBinder().linkToDeath(EnabledOnKeyguardCallback.this, 0);
395             } catch (RemoteException e) {
396                 Slog.w(TAG, "Unable to linkToDeath", e);
397             }
398         }
399 
notify(boolean enabled, int userId)400         void notify(boolean enabled, int userId) {
401             try {
402                 mCallback.onChanged(enabled, userId);
403             } catch (DeadObjectException e) {
404                 Slog.w(TAG, "Death while invoking notify", e);
405                 mEnabledOnKeyguardCallbacks.remove(this);
406             } catch (RemoteException e) {
407                 Slog.w(TAG, "Failed to invoke onChanged", e);
408             }
409         }
410 
411         @Override
binderDied()412         public void binderDied() {
413             Slog.e(TAG, "Enabled callback binder died");
414             mEnabledOnKeyguardCallbacks.remove(this);
415         }
416     }
417 
418     // Receives events from individual biometric sensors.
createBiometricSensorReceiver(final long requestId)419     private IBiometricSensorReceiver createBiometricSensorReceiver(final long requestId) {
420         return new IBiometricSensorReceiver.Stub() {
421             @Override
422             public void onAuthenticationSucceeded(int sensorId, byte[] token) {
423                 mHandler.post(() -> handleAuthenticationSucceeded(requestId, sensorId, token));
424             }
425 
426             @Override
427             public void onAuthenticationFailed(int sensorId) {
428                 Slog.v(TAG, "onAuthenticationFailed");
429                 mHandler.post(() -> handleAuthenticationRejected(requestId, sensorId));
430             }
431 
432             @Override
433             public void onError(int sensorId, int cookie, @BiometricConstants.Errors int error,
434                     int vendorCode) {
435                 // Determine if error is hard or soft error. Certain errors (such as TIMEOUT) are
436                 // soft errors and we should allow the user to try authenticating again instead of
437                 // dismissing BiometricPrompt.
438                 if (error == BiometricConstants.BIOMETRIC_ERROR_TIMEOUT) {
439                     mHandler.post(() -> handleAuthenticationTimedOut(
440                             requestId, sensorId, cookie, error, vendorCode));
441                 } else {
442                     mHandler.post(() -> handleOnError(
443                             requestId, sensorId, cookie, error, vendorCode));
444                 }
445             }
446 
447             @Override
448             public void onAcquired(int sensorId, int acquiredInfo, int vendorCode) {
449                 mHandler.post(() -> handleOnAcquired(
450                         requestId, sensorId, acquiredInfo, vendorCode));
451             }
452         };
453     }
454 
455     private IBiometricSysuiReceiver createSysuiReceiver(final long requestId) {
456         return new IBiometricSysuiReceiver.Stub() {
457             @Override
458             public void onDialogDismissed(@BiometricPrompt.DismissedReason int reason,
459                     @Nullable byte[] credentialAttestation) {
460                 mHandler.post(() -> handleOnDismissed(requestId, reason, credentialAttestation));
461             }
462 
463             @Override
464             public void onTryAgainPressed() {
465                 mHandler.post(() -> handleOnTryAgainPressed(requestId));
466             }
467 
468             @Override
469             public void onDeviceCredentialPressed() {
470                 mHandler.post(() -> handleOnDeviceCredentialPressed(requestId));
471             }
472 
473             @Override
474             public void onSystemEvent(int event) {
475                 mHandler.post(() -> handleOnSystemEvent(requestId, event));
476             }
477 
478             @Override
479             public void onDialogAnimatedIn() {
480                 mHandler.post(() -> handleOnDialogAnimatedIn(requestId));
481             }
482         };
483     }
484 
485     private AuthSession.ClientDeathReceiver createClientDeathReceiver(final long requestId) {
486         return () -> mHandler.post(() -> handleClientDied(requestId));
487     };
488 
489     /**
490      * Implementation of the BiometricPrompt/BiometricManager APIs. Handles client requests,
491      * sensor arbitration, threading, etc.
492      */
493     private final class BiometricServiceWrapper extends IBiometricService.Stub {
494         @Override // Binder call
495         public ITestSession createTestSession(int sensorId, @NonNull ITestSessionCallback callback,
496                 @NonNull String opPackageName) throws RemoteException {
497             checkInternalPermission();
498 
499             for (BiometricSensor sensor : mSensors) {
500                 if (sensor.id == sensorId) {
501                     return sensor.impl.createTestSession(callback, opPackageName);
502                 }
503             }
504 
505             Slog.e(TAG, "Unknown sensor for createTestSession: " + sensorId);
506             return null;
507         }
508 
509         @Override // Binder call
510         public List<SensorPropertiesInternal> getSensorProperties(String opPackageName)
511                 throws RemoteException {
512             checkInternalPermission();
513 
514             final List<SensorPropertiesInternal> sensors = new ArrayList<>();
515             for (BiometricSensor sensor : mSensors) {
516                 // Explicitly re-create as the super class, since AIDL doesn't play nicely with
517                 // "List<? extends SensorPropertiesInternal> ...
518                 final SensorPropertiesInternal prop = SensorPropertiesInternal
519                         .from(sensor.impl.getSensorProperties(opPackageName));
520                 sensors.add(prop);
521             }
522 
523             return sensors;
524         }
525 
526         @Override // Binder call
527         public void onReadyForAuthentication(long requestId, int cookie) {
528             checkInternalPermission();
529 
530             mHandler.post(() -> handleOnReadyForAuthentication(requestId, cookie));
531         }
532 
533         @Override // Binder call
534         public long authenticate(IBinder token, long operationId, int userId,
535                 IBiometricServiceReceiver receiver, String opPackageName, PromptInfo promptInfo) {
536             checkInternalPermission();
537 
538             if (token == null || receiver == null || opPackageName == null || promptInfo == null) {
539                 Slog.e(TAG, "Unable to authenticate, one or more null arguments");
540                 return -1;
541             }
542 
543             if (!Utils.isValidAuthenticatorConfig(promptInfo)) {
544                 throw new SecurityException("Invalid authenticator configuration");
545             }
546 
547             Utils.combineAuthenticatorBundles(promptInfo);
548 
549             // Set the default title if necessary.
550             if (promptInfo.isUseDefaultTitle()) {
551                 if (TextUtils.isEmpty(promptInfo.getTitle())) {
552                     promptInfo.setTitle(getContext()
553                             .getString(R.string.biometric_dialog_default_title));
554                 }
555             }
556 
557             final long requestId = mRequestCounter.get();
558             mHandler.post(() -> handleAuthenticate(
559                     token, requestId, operationId, userId, receiver, opPackageName, promptInfo));
560 
561             return requestId;
562         }
563 
564         @Override // Binder call
565         public void cancelAuthentication(IBinder token, String opPackageName, long requestId) {
566             checkInternalPermission();
567 
568             SomeArgs args = SomeArgs.obtain();
569             args.arg1 = token;
570             args.arg2 = opPackageName;
571             args.arg3 = requestId;
572 
573             mHandler.post(() -> handleCancelAuthentication(requestId));
574         }
575 
576         @Override // Binder call
577         public int canAuthenticate(String opPackageName, int userId, int callingUserId,
578                 @Authenticators.Types int authenticators) {
579             checkInternalPermission();
580 
581             Slog.d(TAG, "canAuthenticate: User=" + userId
582                     + ", Caller=" + callingUserId
583                     + ", Authenticators=" + authenticators);
584 
585             if (!Utils.isValidAuthenticatorConfig(authenticators)) {
586                 throw new SecurityException("Invalid authenticator configuration");
587             }
588 
589             try {
590                 final PreAuthInfo preAuthInfo =
591                         createPreAuthInfo(opPackageName, userId, authenticators);
592                 return preAuthInfo.getCanAuthenticateResult();
593             } catch (RemoteException e) {
594                 Slog.e(TAG, "Remote exception", e);
595                 return BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE;
596             }
597         }
598 
599         @Override
600         public boolean hasEnrolledBiometrics(int userId, String opPackageName) {
601             checkInternalPermission();
602 
603             try {
604                 for (BiometricSensor sensor : mSensors) {
605                     if (sensor.impl.hasEnrolledTemplates(userId, opPackageName)) {
606                         return true;
607                     }
608                 }
609             } catch (RemoteException e) {
610                 Slog.e(TAG, "Remote exception", e);
611             }
612 
613             return false;
614         }
615 
616         @Override
617         public synchronized void registerAuthenticator(int id, int modality,
618                 @Authenticators.Types int strength,
619                 @NonNull IBiometricAuthenticator authenticator) {
620             checkInternalPermission();
621 
622             Slog.d(TAG, "Registering ID: " + id
623                     + " Modality: " + modality
624                     + " Strength: " + strength);
625 
626             if (authenticator == null) {
627                 throw new IllegalArgumentException("Authenticator must not be null."
628                         + " Did you forget to modify the core/res/res/values/xml overlay for"
629                         + " config_biometric_sensors?");
630             }
631 
632             // Note that we allow BIOMETRIC_CONVENIENCE to register because BiometricService
633             // also does / will do other things such as keep track of lock screen timeout, etc.
634             // Just because a biometric is registered does not mean it can participate in
635             // the android.hardware.biometrics APIs.
636             if (strength != Authenticators.BIOMETRIC_STRONG
637                     && strength != Authenticators.BIOMETRIC_WEAK
638                     && strength != Authenticators.BIOMETRIC_CONVENIENCE) {
639                 throw new IllegalStateException("Unsupported strength");
640             }
641 
642             for (BiometricSensor sensor : mSensors) {
643                 if (sensor.id == id) {
644                     throw new IllegalStateException("Cannot register duplicate authenticator");
645                 }
646             }
647 
648             mSensors.add(new BiometricSensor(getContext(), id, modality, strength, authenticator) {
649                 @Override
650                 boolean confirmationAlwaysRequired(int userId) {
651                     return mSettingObserver.getConfirmationAlwaysRequired(modality, userId);
652                 }
653 
654                 @Override
655                 boolean confirmationSupported() {
656                     return Utils.isConfirmationSupported(modality);
657                 }
658             });
659 
660             mBiometricStrengthController.updateStrengths();
661         }
662 
663         @Override // Binder call
664         public void registerEnabledOnKeyguardCallback(
665                 IBiometricEnabledOnKeyguardCallback callback, int callingUserId) {
666             checkInternalPermission();
667 
668             mEnabledOnKeyguardCallbacks.add(new EnabledOnKeyguardCallback(callback));
669             try {
670                 callback.onChanged(mSettingObserver.getEnabledOnKeyguard(callingUserId),
671                         callingUserId);
672             } catch (RemoteException e) {
673                 Slog.w(TAG, "Remote exception", e);
674             }
675         }
676 
677         @Override // Binder call
678         public void invalidateAuthenticatorIds(int userId, int fromSensorId,
679                 IInvalidationCallback callback) {
680             checkInternalPermission();
681 
682             InvalidationTracker.start(getContext(), mSensors, userId, fromSensorId, callback);
683         }
684 
685         @Override // Binder call
686         public long[] getAuthenticatorIds(int callingUserId) {
687             checkInternalPermission();
688 
689             final List<Long> authenticatorIds = new ArrayList<>();
690             for (BiometricSensor sensor : mSensors) {
691                 try {
692                     final boolean hasEnrollments = sensor.impl.hasEnrolledTemplates(callingUserId,
693                             getContext().getOpPackageName());
694                     final long authenticatorId = sensor.impl.getAuthenticatorId(callingUserId);
695                     if (hasEnrollments && Utils.isAtLeastStrength(sensor.getCurrentStrength(),
696                             Authenticators.BIOMETRIC_STRONG)) {
697                         authenticatorIds.add(authenticatorId);
698                     } else {
699                         Slog.d(TAG, "Sensor " + sensor + ", sensorId " + sensor.id
700                                 + ", hasEnrollments: " + hasEnrollments
701                                 + " cannot participate in Keystore operations");
702                     }
703                 } catch (RemoteException e) {
704                     Slog.e(TAG, "RemoteException", e);
705                 }
706             }
707 
708             long[] result = new long[authenticatorIds.size()];
709             for (int i = 0; i < authenticatorIds.size(); i++) {
710                 result[i] = authenticatorIds.get(i);
711             }
712             return result;
713         }
714 
715         @Override // Binder call
716         public void resetLockoutTimeBound(IBinder token, String opPackageName, int fromSensorId,
717                 int userId, byte[] hardwareAuthToken) {
718             checkInternalPermission();
719 
720             // Check originating strength
721             if (!Utils.isAtLeastStrength(getSensorForId(fromSensorId).getCurrentStrength(),
722                     Authenticators.BIOMETRIC_STRONG)) {
723                 Slog.w(TAG, "Sensor: " + fromSensorId + " is does not meet the required strength to"
724                         + " request resetLockout");
725                 return;
726             }
727 
728             // Request resetLockout for applicable sensors
729             for (BiometricSensor sensor : mSensors) {
730                 if (sensor.id == fromSensorId) {
731                     continue;
732                 }
733                 try {
734                     final SensorPropertiesInternal props = sensor.impl
735                             .getSensorProperties(getContext().getOpPackageName());
736                     final boolean supportsChallengelessHat =
737                             props.resetLockoutRequiresHardwareAuthToken
738                             && !props.resetLockoutRequiresChallenge;
739                     final boolean doesNotRequireHat = !props.resetLockoutRequiresHardwareAuthToken;
740 
741                     if (supportsChallengelessHat || doesNotRequireHat) {
742                         Slog.d(TAG, "resetLockout from: " + fromSensorId
743                                 + ", for: " + sensor.id
744                                 + ", userId: " + userId);
745                         sensor.impl.resetLockout(token, opPackageName, userId,
746                                 hardwareAuthToken);
747                     }
748                 } catch (RemoteException e) {
749                     Slog.e(TAG, "Remote exception", e);
750                 }
751             }
752         }
753 
754         @Override // Binder call
755         public int getCurrentStrength(int sensorId) {
756             checkInternalPermission();
757 
758             for (BiometricSensor sensor : mSensors) {
759                 if (sensor.id == sensorId) {
760                     return sensor.getCurrentStrength();
761                 }
762             }
763             Slog.e(TAG, "Unknown sensorId: " + sensorId);
764             return Authenticators.EMPTY_SET;
765         }
766 
767         @Override // Binder call
768         public int getCurrentModality(
769                 String opPackageName,
770                 int userId,
771                 int callingUserId,
772                 @Authenticators.Types int authenticators) {
773 
774             checkInternalPermission();
775 
776             Slog.d(TAG, "getCurrentModality: User=" + userId
777                     + ", Caller=" + callingUserId
778                     + ", Authenticators=" + authenticators);
779 
780             if (!Utils.isValidAuthenticatorConfig(authenticators)) {
781                 throw new SecurityException("Invalid authenticator configuration");
782             }
783 
784             try {
785                 final PreAuthInfo preAuthInfo =
786                         createPreAuthInfo(opPackageName, userId, authenticators);
787                 return preAuthInfo.getPreAuthenticateStatus().first;
788             } catch (RemoteException e) {
789                 Slog.e(TAG, "Remote exception", e);
790                 return BiometricAuthenticator.TYPE_NONE;
791             }
792         }
793 
794         @Override // Binder call
795         public int getSupportedModalities(@Authenticators.Types int authenticators) {
796             checkInternalPermission();
797 
798             Slog.d(TAG, "getSupportedModalities: Authenticators=" + authenticators);
799 
800             if (!Utils.isValidAuthenticatorConfig(authenticators)) {
801                 throw new SecurityException("Invalid authenticator configuration");
802             }
803 
804             @BiometricAuthenticator.Modality int modality =
805                     Utils.isCredentialRequested(authenticators)
806                             ? BiometricAuthenticator.TYPE_CREDENTIAL
807                             : BiometricAuthenticator.TYPE_NONE;
808 
809             if (Utils.isBiometricRequested(authenticators)) {
810                 @Authenticators.Types final int requestedStrength =
811                         Utils.getPublicBiometricStrength(authenticators);
812 
813                 // Add modalities of all biometric sensors that meet the authenticator requirements.
814                 for (final BiometricSensor sensor : mSensors) {
815                     @Authenticators.Types final int sensorStrength = sensor.getCurrentStrength();
816                     if (Utils.isAtLeastStrength(sensorStrength, requestedStrength)) {
817                         modality |= sensor.modality;
818                     }
819                 }
820             }
821 
822             return modality;
823         }
824 
825         @Override
826         protected void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter pw, String[] args) {
827             if (!DumpUtils.checkDumpPermission(getContext(), TAG, pw)) {
828                 return;
829             }
830 
831             final long ident = Binder.clearCallingIdentity();
832             try {
833                 if (args.length > 0 && "--proto".equals(args[0])) {
834                     final boolean clearSchedulerBuffer = args.length > 1
835                             && "--clear-scheduler-buffer".equals(args[1]);
836                     Slog.d(TAG, "ClearSchedulerBuffer: " + clearSchedulerBuffer);
837                     final ProtoOutputStream proto = new ProtoOutputStream(fd);
838                     proto.write(BiometricServiceStateProto.AUTH_SESSION_STATE,
839                             mAuthSession != null ? mAuthSession.getState() : STATE_AUTH_IDLE);
840                     for (BiometricSensor sensor : mSensors) {
841                         byte[] serviceState = sensor.impl
842                                 .dumpSensorServiceStateProto(clearSchedulerBuffer);
843                         proto.write(BiometricServiceStateProto.SENSOR_SERVICE_STATES, serviceState);
844                     }
845                     proto.flush();
846                 } else {
847                     dumpInternal(pw);
848                 }
849             } catch (RemoteException e) {
850                 Slog.e(TAG, "Remote exception", e);
851             } finally {
852                 Binder.restoreCallingIdentity(ident);
853             }
854         }
855     }
856 
857     private void checkInternalPermission() {
858         getContext().enforceCallingOrSelfPermission(USE_BIOMETRIC_INTERNAL,
859                 "Must have USE_BIOMETRIC_INTERNAL permission");
860     }
861 
862     @NonNull
863     private PreAuthInfo createPreAuthInfo(
864             @NonNull String opPackageName,
865             int userId,
866             @Authenticators.Types int authenticators) throws RemoteException {
867 
868         final PromptInfo promptInfo = new PromptInfo();
869         promptInfo.setAuthenticators(authenticators);
870 
871         return PreAuthInfo.create(mTrustManager, mDevicePolicyManager, mSettingObserver, mSensors,
872                 userId, promptInfo, opPackageName, false /* checkDevicePolicyManager */,
873                 getContext());
874     }
875 
876     /**
877      * Class for injecting dependencies into BiometricService.
878      * TODO(b/141025588): Replace with a dependency injection framework (e.g. Guice, Dagger).
879      */
880     @VisibleForTesting
881     public static class Injector {
882 
883         public IActivityManager getActivityManagerService() {
884             return ActivityManager.getService();
885         }
886 
887         public ITrustManager getTrustManager() {
888             return ITrustManager.Stub.asInterface(ServiceManager.getService(Context.TRUST_SERVICE));
889         }
890 
891         public IStatusBarService getStatusBarService() {
892             return IStatusBarService.Stub.asInterface(
893                     ServiceManager.getService(Context.STATUS_BAR_SERVICE));
894         }
895 
896         /**
897          * Allows to mock SettingObserver for testing.
898          */
899         public SettingObserver getSettingObserver(Context context, Handler handler,
900                 List<EnabledOnKeyguardCallback> callbacks) {
901             return new SettingObserver(context, handler, callbacks);
902         }
903 
904         public KeyStore getKeyStore() {
905             return KeyStore.getInstance();
906         }
907 
908         /**
909          * Allows to enable/disable debug logs.
910          */
911         public boolean isDebugEnabled(Context context, int userId) {
912             return Utils.isDebugEnabled(context, userId);
913         }
914 
915         /**
916          * Allows to stub publishBinderService(...) for testing.
917          */
918         public void publishBinderService(BiometricService service, IBiometricService.Stub impl) {
919             service.publishBinderService(Context.BIOMETRIC_SERVICE, impl);
920         }
921 
922         /**
923          * Allows to mock BiometricStrengthController for testing.
924          */
925         public BiometricStrengthController getBiometricStrengthController(
926                 BiometricService service) {
927             return new BiometricStrengthController(service);
928         }
929 
930         /**
931          * Allows to test with various device sensor configurations.
932          * @param context System Server context
933          * @return the sensor configuration from core/res/res/values/config.xml
934          */
935         public String[] getConfiguration(Context context) {
936             return context.getResources().getStringArray(R.array.config_biometric_sensors);
937         }
938 
939         public DevicePolicyManager getDevicePolicyManager(Context context) {
940             return context.getSystemService(DevicePolicyManager.class);
941         }
942 
943         public List<FingerprintSensorPropertiesInternal> getFingerprintSensorProperties(
944                 Context context) {
945             if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_FINGERPRINT)) {
946                 final FingerprintManager fpm = context.getSystemService(FingerprintManager.class);
947                 if (fpm != null) {
948                     return fpm.getSensorPropertiesInternal();
949                 }
950             }
951             return new ArrayList<>();
952         }
953 
954         public boolean isAdvancedCoexLogicEnabled(Context context) {
955             return Settings.Secure.getInt(context.getContentResolver(),
956                     CoexCoordinator.SETTING_ENABLE_NAME, 1) != 0;
957         }
958 
959         public boolean isCoexFaceNonBypassHapticsDisabled(Context context) {
960             return Settings.Secure.getInt(context.getContentResolver(),
961                     CoexCoordinator.FACE_HAPTIC_DISABLE, 0) != 0;
962         }
963 
964         public Supplier<Long> getRequestGenerator() {
965             final AtomicLong generator = new AtomicLong(0);
966             return () -> generator.incrementAndGet();
967         }
968     }
969 
970     /**
971      * Initializes the system service.
972      * <p>
973      * Subclasses must define a single argument constructor that accepts the context
974      * and passes it to super.
975      * </p>
976      *
977      * @param context The system server context.
978      */
979     public BiometricService(Context context) {
980         this(context, new Injector());
981     }
982 
983     @VisibleForTesting
984     BiometricService(Context context, Injector injector) {
985         super(context);
986 
987         mInjector = injector;
988         mDevicePolicyManager = mInjector.getDevicePolicyManager(context);
989         mImpl = new BiometricServiceWrapper();
990         mEnabledOnKeyguardCallbacks = new ArrayList<>();
991         mSettingObserver = mInjector.getSettingObserver(context, mHandler,
992                 mEnabledOnKeyguardCallbacks);
993         mRequestCounter = mInjector.getRequestGenerator();
994 
995         // TODO(b/193089985) This logic lives here (outside of CoexCoordinator) so that it doesn't
996         //  need to depend on context. We can remove this code once the advanced logic is enabled
997         //  by default.
998         CoexCoordinator coexCoordinator = CoexCoordinator.getInstance();
999         coexCoordinator.setAdvancedLogicEnabled(injector.isAdvancedCoexLogicEnabled(context));
1000         coexCoordinator.setFaceHapticDisabledWhenNonBypass(
1001                 injector.isCoexFaceNonBypassHapticsDisabled(context));
1002 
1003         try {
1004             injector.getActivityManagerService().registerUserSwitchObserver(
1005                     new UserSwitchObserver() {
1006                         @Override
1007                         public void onUserSwitchComplete(int newUserId) {
1008                             mSettingObserver.updateContentObserver();
1009                             mSettingObserver.notifyEnabledOnKeyguardCallbacks(newUserId);
1010                         }
1011                     }, BiometricService.class.getName()
1012             );
1013         } catch (RemoteException e) {
1014             Slog.e(TAG, "Failed to register user switch observer", e);
1015         }
1016     }
1017 
1018     @Override
1019     public void onStart() {
1020         mKeyStore = mInjector.getKeyStore();
1021         mStatusBarService = mInjector.getStatusBarService();
1022         mTrustManager = mInjector.getTrustManager();
1023         mInjector.publishBinderService(this, mImpl);
1024         mBiometricStrengthController = mInjector.getBiometricStrengthController(this);
1025         mBiometricStrengthController.startListening();
1026     }
1027 
1028     private boolean isStrongBiometric(int id) {
1029         for (BiometricSensor sensor : mSensors) {
1030             if (sensor.id == id) {
1031                 return Utils.isAtLeastStrength(sensor.getCurrentStrength(),
1032                         Authenticators.BIOMETRIC_STRONG);
1033             }
1034         }
1035         Slog.e(TAG, "Unknown sensorId: " + id);
1036         return false;
1037     }
1038 
1039     @Nullable
1040     private AuthSession getAuthSessionIfCurrent(long requestId) {
1041         final AuthSession session = mAuthSession;
1042         if (session != null && session.getRequestId() == requestId) {
1043             return session;
1044         }
1045         return null;
1046     }
1047 
1048     private void handleAuthenticationSucceeded(long requestId, int sensorId, byte[] token) {
1049         Slog.v(TAG, "handleAuthenticationSucceeded(), sensorId: " + sensorId);
1050         // Should never happen, log this to catch bad HAL behavior (e.g. auth succeeded
1051         // after user dismissed/canceled dialog).
1052         final AuthSession session = getAuthSessionIfCurrent(requestId);
1053         if (session == null) {
1054             Slog.e(TAG, "handleAuthenticationSucceeded: AuthSession is null");
1055             return;
1056         }
1057 
1058         session.onAuthenticationSucceeded(sensorId, isStrongBiometric(sensorId), token);
1059     }
1060 
1061     private void handleAuthenticationRejected(long requestId, int sensorId) {
1062         Slog.v(TAG, "handleAuthenticationRejected()");
1063 
1064         // Should never happen, log this to catch bad HAL behavior (e.g. auth rejected
1065         // after user dismissed/canceled dialog).
1066         final AuthSession session = getAuthSessionIfCurrent(requestId);
1067         if (session == null) {
1068             Slog.w(TAG, "handleAuthenticationRejected: AuthSession is not current");
1069             return;
1070         }
1071 
1072         session.onAuthenticationRejected(sensorId);
1073     }
1074 
1075     private void handleAuthenticationTimedOut(long requestId, int sensorId, int cookie, int error,
1076             int vendorCode) {
1077         Slog.v(TAG, "handleAuthenticationTimedOut(), sensorId: " + sensorId
1078                 + ", cookie: " + cookie
1079                 + ", error: " + error
1080                 + ", vendorCode: " + vendorCode);
1081         // Should never happen, log this to catch bad HAL behavior (e.g. auth succeeded
1082         // after user dismissed/canceled dialog).
1083         final AuthSession session = getAuthSessionIfCurrent(requestId);
1084         if (session == null) {
1085             Slog.w(TAG, "handleAuthenticationTimedOut: AuthSession is not current");
1086             return;
1087         }
1088 
1089         session.onAuthenticationTimedOut(sensorId, cookie, error, vendorCode);
1090     }
1091 
1092     private void handleOnError(long requestId, int sensorId, int cookie,
1093             @BiometricConstants.Errors int error, int vendorCode) {
1094         Slog.d(TAG, "handleOnError() sensorId: " + sensorId
1095                 + ", cookie: " + cookie
1096                 + ", error: " + error
1097                 + ", vendorCode: " + vendorCode);
1098 
1099         final AuthSession session = getAuthSessionIfCurrent(requestId);
1100         if (session == null) {
1101             Slog.w(TAG, "handleOnError: AuthSession is not current");
1102             return;
1103         }
1104 
1105         try {
1106             final boolean finished = session.onErrorReceived(sensorId, cookie, error, vendorCode);
1107             if (finished) {
1108                 Slog.d(TAG, "handleOnError: AuthSession finished");
1109                 mAuthSession = null;
1110             }
1111         } catch (RemoteException e) {
1112             Slog.e(TAG, "RemoteException", e);
1113         }
1114     }
1115 
1116     private void handleOnAcquired(long requestId, int sensorId, int acquiredInfo, int vendorCode) {
1117         // Should never happen, log this to catch bad HAL behavior (e.g. auth succeeded
1118         // after user dismissed/canceled dialog).
1119         final AuthSession session = getAuthSessionIfCurrent(requestId);
1120         if (session == null) {
1121             Slog.w(TAG, "onAcquired: AuthSession is not current");
1122             return;
1123         }
1124 
1125         session.onAcquired(sensorId, acquiredInfo, vendorCode);
1126     }
1127 
1128     private void handleOnDismissed(long requestId, @BiometricPrompt.DismissedReason int reason,
1129             @Nullable byte[] credentialAttestation) {
1130         final AuthSession session = getAuthSessionIfCurrent(requestId);
1131         if (session == null) {
1132             Slog.e(TAG, "onDismissed: " + reason + ", AuthSession is not current");
1133             return;
1134         }
1135 
1136         session.onDialogDismissed(reason, credentialAttestation);
1137         mAuthSession = null;
1138     }
1139 
1140     private void handleOnTryAgainPressed(long requestId) {
1141         Slog.d(TAG, "onTryAgainPressed");
1142         // No need to check permission, since it can only be invoked by SystemUI
1143         // (or system server itself).
1144         final AuthSession session = getAuthSessionIfCurrent(requestId);
1145         if (session == null) {
1146             Slog.w(TAG, "handleOnTryAgainPressed: AuthSession is not current");
1147             return;
1148         }
1149 
1150         session.onTryAgainPressed();
1151     }
1152 
1153     private void handleOnDeviceCredentialPressed(long requestId) {
1154         Slog.d(TAG, "onDeviceCredentialPressed");
1155         final AuthSession session = getAuthSessionIfCurrent(requestId);
1156         if (session == null) {
1157             Slog.w(TAG, "handleOnDeviceCredentialPressed: AuthSession is not current");
1158             return;
1159         }
1160 
1161         session.onDeviceCredentialPressed();
1162     }
1163 
1164     private void handleOnSystemEvent(long requestId, int event) {
1165         Slog.d(TAG, "onSystemEvent: " + event);
1166 
1167         final AuthSession session = getAuthSessionIfCurrent(requestId);
1168         if (session == null) {
1169             Slog.w(TAG, "handleOnSystemEvent: AuthSession is not current");
1170             return;
1171         }
1172 
1173         session.onSystemEvent(event);
1174     }
1175 
1176     private void handleClientDied(long requestId) {
1177         final AuthSession session = getAuthSessionIfCurrent(requestId);
1178         if (session == null) {
1179             Slog.w(TAG, "handleClientDied: AuthSession is not current");
1180             return;
1181         }
1182 
1183         Slog.e(TAG, "Session: " + session);
1184         final boolean finished = session.onClientDied();
1185         if (finished) {
1186             mAuthSession = null;
1187         }
1188     }
1189 
1190     private void handleOnDialogAnimatedIn(long requestId) {
1191         Slog.d(TAG, "handleOnDialogAnimatedIn");
1192 
1193         final AuthSession session = getAuthSessionIfCurrent(requestId);
1194         if (session == null) {
1195             Slog.w(TAG, "handleOnDialogAnimatedIn: AuthSession is not current");
1196             return;
1197         }
1198 
1199         session.onDialogAnimatedIn();
1200     }
1201 
1202     /**
1203      * Invoked when each service has notified that its client is ready to be started. When
1204      * all biometrics are ready, this invokes the SystemUI dialog through StatusBar.
1205      */
1206     private void handleOnReadyForAuthentication(long requestId, int cookie) {
1207         final AuthSession session = getAuthSessionIfCurrent(requestId);
1208         if (session == null) {
1209             // Only should happen if a biometric was locked out when authenticate() was invoked.
1210             // In that case, if device credentials are allowed, the UI is already showing. If not
1211             // allowed, the error has already been returned to the caller.
1212             Slog.w(TAG, "handleOnReadyForAuthentication: AuthSession is not current");
1213             return;
1214         }
1215 
1216         session.onCookieReceived(cookie);
1217     }
1218 
1219     private void handleAuthenticate(IBinder token, long requestId, long operationId, int userId,
1220             IBiometricServiceReceiver receiver, String opPackageName, PromptInfo promptInfo) {
1221         mHandler.post(() -> {
1222             try {
1223                 final PreAuthInfo preAuthInfo = PreAuthInfo.create(mTrustManager,
1224                         mDevicePolicyManager, mSettingObserver, mSensors, userId, promptInfo,
1225                         opPackageName, promptInfo.isDisallowBiometricsIfPolicyExists(),
1226                         getContext());
1227 
1228                 final Pair<Integer, Integer> preAuthStatus = preAuthInfo.getPreAuthenticateStatus();
1229 
1230                 Slog.d(TAG, "handleAuthenticate: modality(" + preAuthStatus.first
1231                         + "), status(" + preAuthStatus.second + "), preAuthInfo: " + preAuthInfo
1232                         + " requestId: " + requestId + " promptInfo.isIgnoreEnrollmentState: "
1233                         + promptInfo.isIgnoreEnrollmentState());
1234                 // BIOMETRIC_ERROR_SENSOR_PRIVACY_ENABLED is added so that BiometricPrompt can
1235                 // be shown for this case.
1236                 if (preAuthStatus.second == BiometricConstants.BIOMETRIC_SUCCESS
1237                         || preAuthStatus.second
1238                         == BiometricConstants.BIOMETRIC_ERROR_SENSOR_PRIVACY_ENABLED) {
1239                     // If BIOMETRIC_WEAK or BIOMETRIC_STRONG are allowed, but not enrolled, but
1240                     // CREDENTIAL is requested and available, set the bundle to only request
1241                     // CREDENTIAL.
1242                     // TODO: We should clean this up, as well as the interface with SystemUI
1243                     if (preAuthInfo.credentialRequested && preAuthInfo.credentialAvailable
1244                             && preAuthInfo.eligibleSensors.isEmpty()) {
1245                         promptInfo.setAuthenticators(Authenticators.DEVICE_CREDENTIAL);
1246                     }
1247 
1248                     authenticateInternal(token, requestId, operationId, userId, receiver,
1249                             opPackageName, promptInfo, preAuthInfo);
1250                 } else {
1251                     receiver.onError(preAuthStatus.first /* modality */,
1252                             preAuthStatus.second /* errorCode */,
1253                             0 /* vendorCode */);
1254                 }
1255             } catch (RemoteException e) {
1256                 Slog.e(TAG, "Remote exception", e);
1257             }
1258         });
1259     }
1260 
1261     /**
1262      * handleAuthenticate() (above) which is called from BiometricPrompt determines which
1263      * modality/modalities to start authenticating with. authenticateInternal() should only be
1264      * used for preparing <Biometric>Services for authentication when BiometricPrompt#authenticate
1265      * is invoked, shortly after which BiometricPrompt is shown and authentication starts.
1266      *
1267      * Note that this path is NOT invoked when the BiometricPrompt "Try again" button is pressed.
1268      * In that case, see {@link #handleOnTryAgainPressed()}.
1269      */
1270     private void authenticateInternal(IBinder token, long requestId, long operationId, int userId,
1271             IBiometricServiceReceiver receiver, String opPackageName, PromptInfo promptInfo,
1272             PreAuthInfo preAuthInfo) {
1273         Slog.d(TAG, "Creating authSession with authRequest: " + preAuthInfo);
1274 
1275         // No need to dismiss dialog / send error yet if we're continuing authentication, e.g.
1276         // "Try again" is showing due to something like ERROR_TIMEOUT.
1277         if (mAuthSession != null) {
1278             // Forcefully cancel authentication. Dismiss the UI, and immediately send
1279             // ERROR_CANCELED to the client. Note that we should/will ignore HAL ERROR_CANCELED.
1280             // Expect to see some harmless "unknown cookie" errors.
1281             Slog.w(TAG, "Existing AuthSession: " + mAuthSession);
1282             mAuthSession.onCancelAuthSession(true /* force */);
1283             mAuthSession = null;
1284         }
1285 
1286         final boolean debugEnabled = mInjector.isDebugEnabled(getContext(), userId);
1287         mAuthSession = new AuthSession(getContext(), mStatusBarService,
1288                 createSysuiReceiver(requestId), mKeyStore, mRandom,
1289                 createClientDeathReceiver(requestId), preAuthInfo, token, requestId,
1290                 operationId, userId, createBiometricSensorReceiver(requestId), receiver,
1291                 opPackageName, promptInfo, debugEnabled,
1292                 mInjector.getFingerprintSensorProperties(getContext()));
1293         try {
1294             mAuthSession.goToInitialState();
1295         } catch (RemoteException e) {
1296             Slog.e(TAG, "RemoteException", e);
1297         }
1298     }
1299 
1300     private void handleCancelAuthentication(long requestId) {
1301         final AuthSession session = getAuthSessionIfCurrent(requestId);
1302         if (session == null) {
1303             Slog.w(TAG, "handleCancelAuthentication: AuthSession is not current");
1304             // TODO: actually cancel the operation?
1305             return;
1306         }
1307 
1308         final boolean finished = session.onCancelAuthSession(false /* force */);
1309         if (finished) {
1310             Slog.d(TAG, "handleCancelAuthentication: AuthSession finished");
1311             mAuthSession = null;
1312         }
1313     }
1314 
1315     @Nullable
1316     private BiometricSensor getSensorForId(int sensorId) {
1317         for (BiometricSensor sensor : mSensors) {
1318             if (sensor.id == sensorId) {
1319                 return sensor;
1320             }
1321         }
1322         return null;
1323     }
1324 
1325     private void dumpInternal(PrintWriter pw) {
1326         pw.println("Legacy Settings: " + mSettingObserver.mUseLegacyFaceOnlySettings);
1327         pw.println();
1328 
1329         pw.println("Sensors:");
1330         for (BiometricSensor sensor : mSensors) {
1331             pw.println(" " + sensor);
1332         }
1333         pw.println();
1334         pw.println("CurrentSession: " + mAuthSession);
1335         pw.println();
1336         pw.println("CoexCoordinator: " + CoexCoordinator.getInstance().toString());
1337         pw.println();
1338     }
1339 }
1340