• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2019 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.SET_BIOMETRIC_DIALOG_ADVANCED;
20 import static android.Manifest.permission.USE_BIOMETRIC_INTERNAL;
21 import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND_SERVICE;
22 import static android.hardware.biometrics.BiometricManager.Authenticators;
23 
24 import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_BOOT;
25 import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW;
26 import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN;
27 import static com.android.server.biometrics.PreAuthInfo.AUTHENTICATOR_OK;
28 import static com.android.server.biometrics.PreAuthInfo.BIOMETRIC_DISABLED_BY_DEVICE_POLICY;
29 import static com.android.server.biometrics.PreAuthInfo.BIOMETRIC_HARDWARE_NOT_DETECTED;
30 import static com.android.server.biometrics.PreAuthInfo.BIOMETRIC_INSUFFICIENT_STRENGTH;
31 import static com.android.server.biometrics.PreAuthInfo.BIOMETRIC_INSUFFICIENT_STRENGTH_AFTER_DOWNGRADE;
32 import static com.android.server.biometrics.PreAuthInfo.BIOMETRIC_LOCKOUT_PERMANENT;
33 import static com.android.server.biometrics.PreAuthInfo.BIOMETRIC_LOCKOUT_TIMED;
34 import static com.android.server.biometrics.PreAuthInfo.BIOMETRIC_NOT_ENABLED_FOR_APPS;
35 import static com.android.server.biometrics.PreAuthInfo.BIOMETRIC_NOT_ENROLLED;
36 import static com.android.server.biometrics.PreAuthInfo.BIOMETRIC_NO_HARDWARE;
37 import static com.android.server.biometrics.PreAuthInfo.BIOMETRIC_SENSOR_PRIVACY_ENABLED;
38 import static com.android.server.biometrics.PreAuthInfo.CREDENTIAL_NOT_ENROLLED;
39 import static com.android.server.biometrics.PreAuthInfo.MANDATORY_BIOMETRIC_UNAVAILABLE_ERROR;
40 
41 import android.annotation.NonNull;
42 import android.annotation.Nullable;
43 import android.app.ActivityManager;
44 import android.app.ActivityTaskManager;
45 import android.content.ComponentName;
46 import android.content.Context;
47 import android.content.pm.PackageManager;
48 import android.hardware.biometrics.BiometricAuthenticator;
49 import android.hardware.biometrics.BiometricConstants;
50 import android.hardware.biometrics.BiometricManager;
51 import android.hardware.biometrics.BiometricPrompt;
52 import android.hardware.biometrics.BiometricPrompt.AuthenticationResultType;
53 import android.hardware.biometrics.Flags;
54 import android.hardware.biometrics.IBiometricService;
55 import android.hardware.biometrics.PromptInfo;
56 import android.hardware.biometrics.SensorProperties;
57 import android.hardware.biometrics.SensorPropertiesInternal;
58 import android.os.Binder;
59 import android.os.Build;
60 import android.os.Process;
61 import android.os.RemoteException;
62 import android.os.ServiceManager;
63 import android.os.UserHandle;
64 import android.os.UserManager;
65 import android.provider.Settings;
66 import android.util.Slog;
67 
68 import com.android.internal.R;
69 import com.android.internal.widget.LockPatternUtils;
70 import com.android.server.biometrics.sensors.BaseClientMonitor;
71 
72 import java.util.List;
73 
74 public class Utils {
75 
76     private static final String TAG = "BiometricUtils";
77 
isDebugEnabled(Context context, int targetUserId)78     public static boolean isDebugEnabled(Context context, int targetUserId) {
79         if (targetUserId == UserHandle.USER_NULL) {
80             return false;
81         }
82 
83         if (!(Build.IS_ENG || Build.IS_USERDEBUG)) {
84             return false;
85         }
86 
87         if (Settings.Secure.getIntForUser(context.getContentResolver(),
88                 Settings.Secure.BIOMETRIC_DEBUG_ENABLED, 0,
89                 targetUserId) == 0) {
90             return false;
91         }
92         return true;
93     }
94 
95     /** If virtualized fingerprint sensor is supported. */
isFingerprintVirtualEnabled(@onNull Context context)96     public static boolean isFingerprintVirtualEnabled(@NonNull Context context) {
97         return Build.isDebuggable()
98                 && (Settings.Secure.getIntForUser(context.getContentResolver(),
99                 Settings.Secure.BIOMETRIC_FINGERPRINT_VIRTUAL_ENABLED, 0,
100                 UserHandle.USER_CURRENT) == 1
101                 || Settings.Secure.getIntForUser(context.getContentResolver(),
102                 Settings.Secure.BIOMETRIC_VIRTUAL_ENABLED, 0, UserHandle.USER_CURRENT) == 1);
103     }
104 
105     /** If virtualized face sensor is supported. */
isFaceVirtualEnabled(@onNull Context context)106     public static boolean isFaceVirtualEnabled(@NonNull Context context) {
107         return Build.isDebuggable()
108                 && (Settings.Secure.getIntForUser(context.getContentResolver(),
109                 Settings.Secure.BIOMETRIC_FACE_VIRTUAL_ENABLED, 0, UserHandle.USER_CURRENT) == 1
110                 || Settings.Secure.getIntForUser(context.getContentResolver(),
111                 Settings.Secure.BIOMETRIC_VIRTUAL_ENABLED, 0, UserHandle.USER_CURRENT) == 1);
112     }
113 
114     /**
115      * Combines {@link PromptInfo#setDeviceCredentialAllowed(boolean)} with
116      * {@link PromptInfo#setAuthenticators(int)}, as the former is not flexible enough.
117      */
combineAuthenticatorBundles(PromptInfo promptInfo)118     static void combineAuthenticatorBundles(PromptInfo promptInfo) {
119         // Cache and remove explicit ALLOW_DEVICE_CREDENTIAL boolean flag from the bundle.
120         final boolean deviceCredentialAllowed = promptInfo.isDeviceCredentialAllowed();
121         promptInfo.setDeviceCredentialAllowed(false);
122 
123         final @Authenticators.Types int authenticators;
124         if (promptInfo.getAuthenticators() != 0) {
125             // Ignore ALLOW_DEVICE_CREDENTIAL flag if AUTH_TYPES_ALLOWED is defined.
126             authenticators = promptInfo.getAuthenticators();
127         } else {
128             // Otherwise, use ALLOW_DEVICE_CREDENTIAL flag along with Weak+ biometrics by default.
129             authenticators = deviceCredentialAllowed
130                     ? Authenticators.DEVICE_CREDENTIAL | Authenticators.BIOMETRIC_WEAK
131                     : Authenticators.BIOMETRIC_WEAK;
132         }
133 
134         promptInfo.setAuthenticators(authenticators);
135     }
136 
137     /**
138      * @param authenticators composed of one or more values from {@link Authenticators}
139      * @return true if device credential is allowed.
140      */
isCredentialRequested(@uthenticators.Types int authenticators)141     static boolean isCredentialRequested(@Authenticators.Types int authenticators) {
142         return (authenticators & Authenticators.DEVICE_CREDENTIAL) != 0;
143     }
144 
145     /**
146      * @param authenticators composed of one or more values from {@link Authenticators}
147      * @return true if mandatory biometrics is requested
148      */
isMandatoryBiometricsRequested(@uthenticators.Types int authenticators)149     static boolean isMandatoryBiometricsRequested(@Authenticators.Types int authenticators) {
150         return (authenticators & Authenticators.IDENTITY_CHECK) != 0;
151     }
152 
153     /**
154      * @param promptInfo should be first processed by
155      * {@link #combineAuthenticatorBundles(PromptInfo)}
156      * @return true if device credential is allowed.
157      */
isCredentialRequested(PromptInfo promptInfo)158     static boolean isCredentialRequested(PromptInfo promptInfo) {
159         return isCredentialRequested(promptInfo.getAuthenticators());
160     }
161 
162     /**
163      * Checks if any of the publicly defined strengths are set.
164      *
165      * @param authenticators composed of one or more values from {@link Authenticators}
166      * @return minimal allowed biometric strength or 0 if biometric authentication is not allowed.
167      */
getPublicBiometricStrength(@uthenticators.Types int authenticators)168     static int getPublicBiometricStrength(@Authenticators.Types int authenticators) {
169         // Only biometrics WEAK and above are allowed to integrate with the public APIs.
170         return authenticators & Authenticators.BIOMETRIC_WEAK;
171     }
172 
173     /**
174      * Checks if any of the publicly defined strengths are set.
175      *
176      * @param promptInfo should be first processed by
177      * {@link #combineAuthenticatorBundles(PromptInfo)}
178      * @return minimal allowed biometric strength or 0 if biometric authentication is not allowed.
179      */
getPublicBiometricStrength(PromptInfo promptInfo)180     static int getPublicBiometricStrength(PromptInfo promptInfo) {
181         return getPublicBiometricStrength(promptInfo.getAuthenticators());
182     }
183 
184     /**
185      * Checks if any of the publicly defined strengths are set.
186      *
187      * @param authenticators composed of one or more values from {@link Authenticators}
188      * @return true if biometric authentication is allowed.
189      */
isBiometricRequested(@uthenticators.Types int authenticators)190     static boolean isBiometricRequested(@Authenticators.Types int authenticators) {
191         return getPublicBiometricStrength(authenticators) != 0;
192     }
193 
194     /**
195      * Checks if any of the publicly defined strengths are set.
196      *
197      * @param promptInfo should be first processed by
198      * {@link #combineAuthenticatorBundles(PromptInfo)}
199      * @return true if biometric authentication is allowed.
200      */
isBiometricRequested(PromptInfo promptInfo)201     static boolean isBiometricRequested(PromptInfo promptInfo) {
202         return getPublicBiometricStrength(promptInfo) != 0;
203     }
204 
205     /**
206      * @param sensorStrength the strength of the sensor
207      * @param requestedStrength the strength that it must meet
208      * @return true only if the sensor is at least as strong as the requested strength
209      */
isAtLeastStrength(@uthenticators.Types int sensorStrength, @Authenticators.Types int requestedStrength)210     public static boolean isAtLeastStrength(@Authenticators.Types int sensorStrength,
211             @Authenticators.Types int requestedStrength) {
212         // Clear out any bits that are not reserved for biometric
213         sensorStrength &= Authenticators.BIOMETRIC_MIN_STRENGTH;
214 
215         // If the authenticator contains bits outside of the requested strength, it is too weak.
216         if ((sensorStrength & ~requestedStrength) != 0) {
217             return false;
218         }
219 
220         for (int i = Authenticators.BIOMETRIC_MAX_STRENGTH;
221                 i <= requestedStrength; i = (i << 1) | 1) {
222             if (i == sensorStrength) {
223                 return true;
224             }
225         }
226 
227         Slog.e(BiometricService.TAG, "Unknown sensorStrength: " + sensorStrength
228                 + ", requestedStrength: " + requestedStrength);
229         return false;
230     }
231 
232     /**
233      * Checks if the authenticator configuration is a valid combination of the public APIs
234      * @param promptInfo
235      * @return
236      */
isValidAuthenticatorConfig(Context context, PromptInfo promptInfo)237     static boolean isValidAuthenticatorConfig(Context context, PromptInfo promptInfo) {
238         final int authenticators = promptInfo.getAuthenticators();
239         return isValidAuthenticatorConfig(context, authenticators);
240     }
241 
242     /**
243      * Checks if the authenticator configuration is a valid combination of the public APIs.
244      *
245      * throws {@link SecurityException} if the caller requests for mandatory biometrics without
246      * {@link SET_BIOMETRIC_DIALOG_ADVANCED} permission
247      */
isValidAuthenticatorConfig(Context context, int authenticators)248     static boolean isValidAuthenticatorConfig(Context context, int authenticators) {
249         // The caller is not required to set the authenticators. But if they do, check the below.
250         if (authenticators == 0) {
251             return true;
252         }
253 
254         // Check if any of the non-biometric and non-credential bits are set. If so, this is
255         // invalid.
256         final int testBits;
257         if (Flags.mandatoryBiometrics()) {
258             testBits = ~(Authenticators.DEVICE_CREDENTIAL
259                     | Authenticators.BIOMETRIC_MIN_STRENGTH
260                     | Authenticators.IDENTITY_CHECK);
261         } else {
262             testBits = ~(Authenticators.DEVICE_CREDENTIAL
263                     | Authenticators.BIOMETRIC_MIN_STRENGTH);
264         }
265         if ((authenticators & testBits) != 0) {
266             Slog.e(BiometricService.TAG, "Non-biometric, non-credential bits found."
267                     + " Authenticators: " + authenticators);
268             return false;
269         }
270 
271         // Check that biometrics bits are either NONE, WEAK, or STRONG. If NONE, DEVICE_CREDENTIAL
272         // should be set.
273         final int biometricBits = authenticators & Authenticators.BIOMETRIC_MIN_STRENGTH;
274         if (biometricBits == Authenticators.EMPTY_SET
275                 && isCredentialRequested(authenticators)) {
276             return true;
277         } else if (biometricBits == Authenticators.BIOMETRIC_STRONG) {
278             return true;
279         } else if (biometricBits == Authenticators.BIOMETRIC_WEAK) {
280             return true;
281         } else if (isMandatoryBiometricsRequested(authenticators)) {
282             //TODO(b/347123256): Update CTS test
283             context.enforceCallingOrSelfPermission(SET_BIOMETRIC_DIALOG_ADVANCED,
284                     "Must have SET_BIOMETRIC_DIALOG_ADVANCED permission");
285             return true;
286         }
287 
288         Slog.e(BiometricService.TAG, "Unsupported biometric flags. Authenticators: "
289                 + authenticators);
290         // Non-supported biometric flags are being used
291         return false;
292     }
293 
294     /**
295      * Converts error codes from BiometricConstants, which are used in most of the internal plumbing
296      * and eventually returned to {@link BiometricPrompt.AuthenticationCallback} to public
297      * {@link BiometricManager} constants, which are used by APIs such as
298      * {@link BiometricManager#canAuthenticate(int)}
299      *
300      * @param biometricConstantsCode see {@link BiometricConstants}
301      * @return see {@link BiometricManager}
302      */
biometricConstantsToBiometricManager(int biometricConstantsCode)303     static int biometricConstantsToBiometricManager(int biometricConstantsCode) {
304         final int biometricManagerCode;
305 
306         switch (biometricConstantsCode) {
307             case BiometricConstants.BIOMETRIC_SUCCESS:
308                 biometricManagerCode = BiometricManager.BIOMETRIC_SUCCESS;
309                 break;
310             case BiometricConstants.BIOMETRIC_ERROR_NO_BIOMETRICS:
311             case BiometricConstants.BIOMETRIC_ERROR_NO_DEVICE_CREDENTIAL:
312                 biometricManagerCode = BiometricManager.BIOMETRIC_ERROR_NONE_ENROLLED;
313                 break;
314             case BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE:
315                 biometricManagerCode = BiometricManager.BIOMETRIC_ERROR_HW_UNAVAILABLE;
316                 break;
317             case BiometricConstants.BIOMETRIC_ERROR_HW_NOT_PRESENT:
318                 biometricManagerCode = BiometricManager.BIOMETRIC_ERROR_NO_HARDWARE;
319                 break;
320             case BiometricConstants.BIOMETRIC_ERROR_SECURITY_UPDATE_REQUIRED:
321                 biometricManagerCode = BiometricManager.BIOMETRIC_ERROR_SECURITY_UPDATE_REQUIRED;
322                 break;
323             case BiometricConstants.BIOMETRIC_ERROR_LOCKOUT:
324             case BiometricConstants.BIOMETRIC_ERROR_LOCKOUT_PERMANENT:
325                 biometricManagerCode = Flags.mandatoryBiometrics()
326                         ? BiometricManager.BIOMETRIC_ERROR_LOCKOUT
327                         : BiometricManager.BIOMETRIC_SUCCESS;
328                 break;
329             case BiometricConstants.BIOMETRIC_ERROR_SENSOR_PRIVACY_ENABLED:
330                 biometricManagerCode = BiometricManager.BIOMETRIC_ERROR_HW_UNAVAILABLE;
331                 break;
332             case BiometricConstants.BIOMETRIC_ERROR_IDENTITY_CHECK_NOT_ACTIVE:
333                 biometricManagerCode = BiometricManager.BIOMETRIC_ERROR_IDENTITY_CHECK_NOT_ACTIVE;
334                 break;
335             case BiometricConstants.BIOMETRIC_ERROR_NOT_ENABLED_FOR_APPS:
336                 biometricManagerCode = BiometricManager.BIOMETRIC_ERROR_NOT_ENABLED_FOR_APPS;
337                 break;
338             default:
339                 Slog.e(BiometricService.TAG, "Unhandled result code: " + biometricConstantsCode);
340                 biometricManagerCode = BiometricManager.BIOMETRIC_ERROR_HW_UNAVAILABLE;
341                 break;
342         }
343         return biometricManagerCode;
344     }
345 
346     /**
347      * Converts a {@link BiometricPrompt} dismissal reason to an authentication type at the level of
348      * granularity supported by {@link BiometricPrompt.AuthenticationResult}.
349      *
350      * @param reason The reason that the {@link BiometricPrompt} was dismissed. Must be one of:
351      *               {@link BiometricPrompt#DISMISSED_REASON_CREDENTIAL_CONFIRMED},
352      *               {@link BiometricPrompt#DISMISSED_REASON_BIOMETRIC_CONFIRMED}, or
353      *               {@link BiometricPrompt#DISMISSED_REASON_BIOMETRIC_CONFIRM_NOT_REQUIRED}
354      * @return An integer representing the authentication type for {@link
355      *         BiometricPrompt.AuthenticationResult}.
356      * @throws IllegalArgumentException if given an invalid dismissal reason.
357      */
getAuthenticationTypeForResult(int reason)358     static @AuthenticationResultType int getAuthenticationTypeForResult(int reason) {
359         switch (reason) {
360             case BiometricPrompt.DISMISSED_REASON_CREDENTIAL_CONFIRMED:
361                 return BiometricPrompt.AUTHENTICATION_RESULT_TYPE_DEVICE_CREDENTIAL;
362 
363             case BiometricPrompt.DISMISSED_REASON_BIOMETRIC_CONFIRMED:
364             case BiometricPrompt.DISMISSED_REASON_BIOMETRIC_CONFIRM_NOT_REQUIRED:
365                 return BiometricPrompt.AUTHENTICATION_RESULT_TYPE_BIOMETRIC;
366 
367             default:
368                 throw new IllegalArgumentException("Unsupported dismissal reason: " + reason);
369         }
370     }
371 
372 
authenticatorStatusToBiometricConstant( @reAuthInfo.AuthenticatorStatus int status)373     static int authenticatorStatusToBiometricConstant(
374             @PreAuthInfo.AuthenticatorStatus int status) {
375         switch (status) {
376             case BIOMETRIC_NO_HARDWARE:
377             case BIOMETRIC_INSUFFICIENT_STRENGTH:
378                 return BiometricConstants.BIOMETRIC_ERROR_HW_NOT_PRESENT;
379 
380             case AUTHENTICATOR_OK:
381                 return BiometricConstants.BIOMETRIC_SUCCESS;
382 
383             case BIOMETRIC_INSUFFICIENT_STRENGTH_AFTER_DOWNGRADE:
384                 return BiometricConstants.BIOMETRIC_ERROR_SECURITY_UPDATE_REQUIRED;
385 
386             case BIOMETRIC_NOT_ENROLLED:
387                 return BiometricConstants.BIOMETRIC_ERROR_NO_BIOMETRICS;
388 
389             case CREDENTIAL_NOT_ENROLLED:
390                 return BiometricConstants.BIOMETRIC_ERROR_NO_DEVICE_CREDENTIAL;
391 
392             case BIOMETRIC_LOCKOUT_TIMED:
393                 return BiometricConstants.BIOMETRIC_ERROR_LOCKOUT;
394 
395             case BIOMETRIC_LOCKOUT_PERMANENT:
396                 return BiometricConstants.BIOMETRIC_ERROR_LOCKOUT_PERMANENT;
397             case BIOMETRIC_SENSOR_PRIVACY_ENABLED:
398                 return BiometricConstants.BIOMETRIC_ERROR_SENSOR_PRIVACY_ENABLED;
399             case MANDATORY_BIOMETRIC_UNAVAILABLE_ERROR:
400                 return BiometricConstants.BIOMETRIC_ERROR_IDENTITY_CHECK_NOT_ACTIVE;
401             case BIOMETRIC_NOT_ENABLED_FOR_APPS:
402                 if (Flags.mandatoryBiometrics()) {
403                     return BiometricConstants.BIOMETRIC_ERROR_NOT_ENABLED_FOR_APPS;
404                 }
405             case BIOMETRIC_DISABLED_BY_DEVICE_POLICY:
406             case BIOMETRIC_HARDWARE_NOT_DETECTED:
407             default:
408                 return BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE;
409         }
410     }
411 
isConfirmationSupported(@iometricAuthenticator.Modality int modality)412     static boolean isConfirmationSupported(@BiometricAuthenticator.Modality int modality) {
413         switch (modality) {
414             case BiometricAuthenticator.TYPE_FACE:
415             case BiometricAuthenticator.TYPE_IRIS:
416                 return true;
417             default:
418                 return false;
419         }
420     }
421 
removeBiometricBits(@uthenticators.Types int authenticators)422     static int removeBiometricBits(@Authenticators.Types int authenticators) {
423         return authenticators & ~Authenticators.BIOMETRIC_MIN_STRENGTH;
424     }
425 
listContains(int[] haystack, int needle)426     public static boolean listContains(int[] haystack, int needle) {
427         for (int i = 0; i < haystack.length; i++) {
428             if (haystack[i] == needle) {
429                 return true;
430             }
431         }
432         return false;
433     }
434 
435     /** Same as checkPermission but also allows shell. */
checkPermissionOrShell(Context context, String permission)436     public static void checkPermissionOrShell(Context context, String permission) {
437         if (Binder.getCallingUid() == Process.SHELL_UID) {
438             return;
439         }
440         checkPermission(context, permission);
441     }
442 
443 
checkPermission(Context context, String permission)444     public static void checkPermission(Context context, String permission) {
445         context.enforceCallingOrSelfPermission(permission,
446                 "Must have " + permission + " permission.");
447     }
448 
isCurrentUserOrProfile(Context context, int userId)449     public static boolean isCurrentUserOrProfile(Context context, int userId) {
450         UserManager um = UserManager.get(context);
451         if (um == null) {
452             Slog.e(TAG, "Unable to get UserManager");
453             return false;
454         }
455 
456         final long token = Binder.clearCallingIdentity();
457         try {
458             // Allow current user or profiles of the current user...
459             for (int profileId : um.getEnabledProfileIds(ActivityManager.getCurrentUser())) {
460                 if (profileId == userId) {
461                     return true;
462                 }
463             }
464         } finally {
465             Binder.restoreCallingIdentity(token);
466         }
467 
468         return false;
469     }
470 
isStrongBiometric(int sensorId)471     public static boolean isStrongBiometric(int sensorId) {
472         IBiometricService service = IBiometricService.Stub.asInterface(
473                 ServiceManager.getService(Context.BIOMETRIC_SERVICE));
474         try {
475             return Utils.isAtLeastStrength(service.getCurrentStrength(sensorId),
476                     Authenticators.BIOMETRIC_STRONG);
477         } catch (RemoteException e) {
478             Slog.e(TAG, "RemoteException", e);
479             return false;
480         }
481     }
482 
483     /**
484      * Returns the sensor's current strength, taking any updated strengths into effect.
485      *
486      * @param sensorId The sensor Id
487      * @return see {@link BiometricManager.Authenticators}
488      */
getCurrentStrength(int sensorId)489     public static @Authenticators.Types int getCurrentStrength(int sensorId) {
490         IBiometricService service = IBiometricService.Stub.asInterface(
491                 ServiceManager.getService(Context.BIOMETRIC_SERVICE));
492         try {
493             return service.getCurrentStrength(sensorId);
494         } catch (RemoteException e) {
495             Slog.e(TAG, "RemoteException", e);
496             return Authenticators.EMPTY_SET;
497         }
498     }
499 
500     /**
501      * Checks if a client package matches Keyguard and can perform internal biometric operations.
502      *
503      * @param context The system context.
504      * @param clientPackage The name of the package to be checked against Keyguard.
505      * @return Whether the given package matches Keyguard.
506      */
isKeyguard(@onNull Context context, @Nullable String clientPackage)507     public static boolean isKeyguard(@NonNull Context context, @Nullable String clientPackage) {
508         final boolean hasPermission = hasInternalPermission(context);
509         final ComponentName keyguardComponent = ComponentName.unflattenFromString(
510                 context.getResources().getString(R.string.config_keyguardComponent));
511         final String keyguardPackage = keyguardComponent != null
512                 ? keyguardComponent.getPackageName() : null;
513         return hasPermission && keyguardPackage != null && keyguardPackage.equals(clientPackage);
514     }
515 
516     /**
517      * Checks if a client package matches the Android system and can perform internal biometric
518      * operations.
519      *
520      * @param context The system context.
521      * @param clientPackage The name of the package to be checked against the Android system.
522      * @return Whether the given package matches the Android system.
523      */
isSystem(@onNull Context context, @Nullable String clientPackage)524     public static boolean isSystem(@NonNull Context context, @Nullable String clientPackage) {
525         return hasInternalPermission(context) && "android".equals(clientPackage);
526     }
527 
528     /**
529      * Checks if a client package matches Settings and can perform internal biometric operations.
530      *
531      * @param context The system context.
532      * @param clientPackage The name of the package to be checked against Settings.
533      * @return Whether the given package matches Settings.
534      */
isSettings(@onNull Context context, @Nullable String clientPackage)535     public static boolean isSettings(@NonNull Context context, @Nullable String clientPackage) {
536         return hasInternalPermission(context) && "com.android.settings".equals(clientPackage);
537     }
538 
hasInternalPermission(@onNull Context context)539     private static boolean hasInternalPermission(@NonNull Context context) {
540         return context.checkCallingOrSelfPermission(USE_BIOMETRIC_INTERNAL)
541                 == PackageManager.PERMISSION_GRANTED;
542     }
543 
getClientName(@ullable BaseClientMonitor client)544     public static String getClientName(@Nullable BaseClientMonitor client) {
545         return client != null ? client.getClass().getSimpleName() : "null";
546     }
547 
containsFlag(int haystack, int needle)548     private static boolean containsFlag(int haystack, int needle) {
549         return (haystack & needle) != 0;
550     }
551 
isUserEncryptedOrLockdown(@onNull LockPatternUtils lpu, int user)552     public static boolean isUserEncryptedOrLockdown(@NonNull LockPatternUtils lpu, int user) {
553         final int strongAuth = lpu.getStrongAuthForUser(user);
554         final boolean isEncrypted = containsFlag(strongAuth, STRONG_AUTH_REQUIRED_AFTER_BOOT);
555         final boolean isLockDown = containsFlag(strongAuth, STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW)
556                 || containsFlag(strongAuth, STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN);
557         Slog.d(TAG, "isEncrypted: " + isEncrypted + " isLockdown: " + isLockDown);
558         return isEncrypted || isLockDown;
559     }
560 
isForeground(int callingUid, int callingPid)561     public static boolean isForeground(int callingUid, int callingPid) {
562         try {
563             final List<ActivityManager.RunningAppProcessInfo> procs =
564                     ActivityManager.getService().getRunningAppProcesses();
565             if (procs == null) {
566                 Slog.e(TAG, "No running app processes found, defaulting to true");
567                 return true;
568             }
569 
570             for (int i = 0; i < procs.size(); i++) {
571                 ActivityManager.RunningAppProcessInfo proc = procs.get(i);
572                 if (proc.pid == callingPid && proc.uid == callingUid
573                         && proc.importance <= IMPORTANCE_FOREGROUND_SERVICE) {
574                     return true;
575                 }
576             }
577         } catch (RemoteException e) {
578             Slog.w(TAG, "am.getRunningAppProcesses() failed");
579         }
580         return false;
581     }
582 
583     /**
584      * Converts from {@link BiometricManager.Authenticators} biometric strength to the internal
585      * {@link SensorPropertiesInternal} strength.
586      */
authenticatorStrengthToPropertyStrength( @uthenticators.Types int strength)587     public static @SensorProperties.Strength int authenticatorStrengthToPropertyStrength(
588             @Authenticators.Types int strength) {
589         switch (strength) {
590             case BiometricManager.Authenticators.BIOMETRIC_CONVENIENCE:
591                 return SensorProperties.STRENGTH_CONVENIENCE;
592             case BiometricManager.Authenticators.BIOMETRIC_WEAK:
593                 return SensorProperties.STRENGTH_WEAK;
594             case BiometricManager.Authenticators.BIOMETRIC_STRONG:
595                 return SensorProperties.STRENGTH_STRONG;
596             default:
597                 throw new IllegalArgumentException("Unknown strength: " + strength);
598         }
599     }
600 
propertyStrengthToAuthenticatorStrength( @ensorProperties.Strength int strength)601     public static @Authenticators.Types int propertyStrengthToAuthenticatorStrength(
602             @SensorProperties.Strength int strength) {
603         switch (strength) {
604             case SensorProperties.STRENGTH_CONVENIENCE:
605                 return Authenticators.BIOMETRIC_CONVENIENCE;
606             case SensorProperties.STRENGTH_WEAK:
607                 return Authenticators.BIOMETRIC_WEAK;
608             case SensorProperties.STRENGTH_STRONG:
609                 return Authenticators.BIOMETRIC_STRONG;
610             default:
611                 throw new IllegalArgumentException("Unknown strength: " + strength);
612         }
613     }
614 
615     // LINT.IfChange
616 
617     /**
618      * Checks if a client package is running in the background.
619      *
620      * @param clientPackage The name of the package to be checked.
621      * @return Whether the client package is running in background
622      */
isBackground(String clientPackage)623     public static boolean isBackground(String clientPackage) {
624         Slog.v(TAG, "Checking if the authenticating is in background,"
625                 + " clientPackage:" + clientPackage);
626         final List<ActivityManager.RunningTaskInfo> tasks =
627                 ActivityTaskManager.getInstance().getTasks(Integer.MAX_VALUE);
628 
629         if (tasks == null || tasks.isEmpty()) {
630             Slog.d(TAG, "No running tasks reported");
631             return true;
632         }
633 
634         for (ActivityManager.RunningTaskInfo taskInfo : tasks) {
635             final ComponentName topActivity = taskInfo.topActivity;
636             if (topActivity != null) {
637                 final String topPackage = topActivity.getPackageName();
638                 if (topPackage.contentEquals(clientPackage) && taskInfo.isVisible()) {
639                     return false;
640                 } else {
641                     Slog.i(TAG, "Running task, top: " + topPackage
642                             + ", isVisible: " + taskInfo.isVisible());
643                 }
644             }
645         }
646 
647         return true;
648     }
649     // LINT.ThenChange(frameworks/base/packages/SystemUI/shared/biometrics/src/com/android
650     // /systemui/biometrics/Utils.kt)
651 }
652