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