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