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