1 /* 2 * Copyright (C) 2020 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.sensors.fingerprint; 18 19 import static android.Manifest.permission.INTERACT_ACROSS_USERS; 20 import static android.Manifest.permission.MANAGE_BIOMETRIC; 21 import static android.Manifest.permission.MANAGE_FINGERPRINT; 22 import static android.Manifest.permission.RESET_FINGERPRINT_LOCKOUT; 23 import static android.Manifest.permission.TEST_BIOMETRIC; 24 import static android.Manifest.permission.USE_BIOMETRIC; 25 import static android.Manifest.permission.USE_BIOMETRIC_INTERNAL; 26 import static android.Manifest.permission.USE_FINGERPRINT; 27 import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FINGERPRINT; 28 import static android.hardware.biometrics.BiometricFingerprintConstants.FINGERPRINT_ACQUIRED_VENDOR; 29 import static android.hardware.biometrics.BiometricFingerprintConstants.FINGERPRINT_ERROR_USER_CANCELED; 30 import static android.hardware.biometrics.BiometricFingerprintConstants.FINGERPRINT_ERROR_VENDOR; 31 import static android.hardware.biometrics.SensorProperties.STRENGTH_STRONG; 32 33 import android.annotation.NonNull; 34 import android.annotation.Nullable; 35 import android.app.AppOpsManager; 36 import android.content.Context; 37 import android.content.pm.PackageManager; 38 import android.hardware.biometrics.BiometricManager; 39 import android.hardware.biometrics.BiometricPrompt; 40 import android.hardware.biometrics.BiometricsProtoEnums; 41 import android.hardware.biometrics.IBiometricSensorReceiver; 42 import android.hardware.biometrics.IBiometricService; 43 import android.hardware.biometrics.IBiometricServiceLockoutResetCallback; 44 import android.hardware.biometrics.IInvalidationCallback; 45 import android.hardware.biometrics.ITestSession; 46 import android.hardware.biometrics.ITestSessionCallback; 47 import android.hardware.biometrics.fingerprint.IFingerprint; 48 import android.hardware.biometrics.fingerprint.SensorProps; 49 import android.hardware.fingerprint.Fingerprint; 50 import android.hardware.fingerprint.FingerprintManager; 51 import android.hardware.fingerprint.FingerprintSensorPropertiesInternal; 52 import android.hardware.fingerprint.FingerprintServiceReceiver; 53 import android.hardware.fingerprint.IFingerprintAuthenticatorsRegisteredCallback; 54 import android.hardware.fingerprint.IFingerprintClientActiveCallback; 55 import android.hardware.fingerprint.IFingerprintService; 56 import android.hardware.fingerprint.IFingerprintServiceReceiver; 57 import android.hardware.fingerprint.IFingerprintStateListener; 58 import android.hardware.fingerprint.ISidefpsController; 59 import android.hardware.fingerprint.IUdfpsOverlayController; 60 import android.os.Binder; 61 import android.os.Build; 62 import android.os.CancellationSignal; 63 import android.os.Handler; 64 import android.os.IBinder; 65 import android.os.Process; 66 import android.os.RemoteCallbackList; 67 import android.os.RemoteException; 68 import android.os.ServiceManager; 69 import android.os.UserHandle; 70 import android.provider.Settings; 71 import android.util.EventLog; 72 import android.util.Pair; 73 import android.util.Slog; 74 import android.util.proto.ProtoOutputStream; 75 76 import com.android.internal.R; 77 import com.android.internal.annotations.GuardedBy; 78 import com.android.internal.util.DumpUtils; 79 import com.android.internal.widget.LockPatternUtils; 80 import com.android.server.ServiceThread; 81 import com.android.server.SystemService; 82 import com.android.server.biometrics.Utils; 83 import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter; 84 import com.android.server.biometrics.sensors.LockoutResetDispatcher; 85 import com.android.server.biometrics.sensors.LockoutTracker; 86 import com.android.server.biometrics.sensors.fingerprint.aidl.FingerprintProvider; 87 import com.android.server.biometrics.sensors.fingerprint.hidl.Fingerprint21; 88 import com.android.server.biometrics.sensors.fingerprint.hidl.Fingerprint21UdfpsMock; 89 90 import java.io.FileDescriptor; 91 import java.io.PrintWriter; 92 import java.util.ArrayList; 93 import java.util.Collections; 94 import java.util.List; 95 import java.util.concurrent.Executor; 96 97 /** 98 * A service to manage multiple clients that want to access the fingerprint HAL API. 99 * The service is responsible for maintaining a list of clients and dispatching all 100 * fingerprint-related events. 101 */ 102 public class FingerprintService extends SystemService { 103 104 protected static final String TAG = "FingerprintService"; 105 106 private final Object mLock = new Object(); 107 private final AppOpsManager mAppOps; 108 private final LockoutResetDispatcher mLockoutResetDispatcher; 109 private final GestureAvailabilityDispatcher mGestureAvailabilityDispatcher; 110 private final LockPatternUtils mLockPatternUtils; 111 private final FingerprintServiceWrapper mServiceWrapper; 112 @NonNull private final List<ServiceProvider> mServiceProviders; 113 @NonNull private final FingerprintStateCallback mFingerprintStateCallback; 114 115 @GuardedBy("mLock") 116 @NonNull private final RemoteCallbackList<IFingerprintAuthenticatorsRegisteredCallback> 117 mAuthenticatorsRegisteredCallbacks; 118 119 @GuardedBy("mLock") 120 @NonNull private final List<FingerprintSensorPropertiesInternal> mSensorProps; 121 122 /** 123 * Registers FingerprintStateListener in list stored by FingerprintService 124 * @param listener new FingerprintStateListener being added 125 */ registerFingerprintStateListener(@onNull IFingerprintStateListener listener)126 public void registerFingerprintStateListener(@NonNull IFingerprintStateListener listener) { 127 mFingerprintStateCallback.registerFingerprintStateListener(listener); 128 } 129 130 /** 131 * Receives the incoming binder calls from FingerprintManager. 132 */ 133 private final class FingerprintServiceWrapper extends IFingerprintService.Stub { 134 @Override createTestSession(int sensorId, @NonNull ITestSessionCallback callback, @NonNull String opPackageName)135 public ITestSession createTestSession(int sensorId, @NonNull ITestSessionCallback callback, 136 @NonNull String opPackageName) { 137 Utils.checkPermission(getContext(), TEST_BIOMETRIC); 138 139 final ServiceProvider provider = getProviderForSensor(sensorId); 140 141 if (provider == null) { 142 Slog.w(TAG, "Null provider for createTestSession, sensorId: " + sensorId); 143 return null; 144 } 145 146 return provider.createTestSession(sensorId, callback, mFingerprintStateCallback, 147 opPackageName); 148 } 149 150 @Override dumpSensorServiceStateProto(int sensorId, boolean clearSchedulerBuffer)151 public byte[] dumpSensorServiceStateProto(int sensorId, boolean clearSchedulerBuffer) { 152 Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL); 153 154 final ProtoOutputStream proto = new ProtoOutputStream(); 155 final ServiceProvider provider = getProviderForSensor(sensorId); 156 if (provider != null) { 157 provider.dumpProtoState(sensorId, proto, clearSchedulerBuffer); 158 } 159 proto.flush(); 160 return proto.getBytes(); 161 } 162 163 @Override // Binder call getSensorPropertiesInternal( @onNull String opPackageName)164 public List<FingerprintSensorPropertiesInternal> getSensorPropertiesInternal( 165 @NonNull String opPackageName) { 166 if (getContext().checkCallingOrSelfPermission(USE_BIOMETRIC_INTERNAL) 167 != PackageManager.PERMISSION_GRANTED) { 168 Utils.checkPermission(getContext(), TEST_BIOMETRIC); 169 } 170 171 return FingerprintService.this.getSensorProperties(); 172 } 173 174 @Override getSensorProperties(int sensorId, @NonNull String opPackageName)175 public FingerprintSensorPropertiesInternal getSensorProperties(int sensorId, 176 @NonNull String opPackageName) { 177 Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL); 178 179 final ServiceProvider provider = getProviderForSensor(sensorId); 180 if (provider == null) { 181 Slog.w(TAG, "No matching sensor for getSensorProperties, sensorId: " + sensorId 182 + ", caller: " + opPackageName); 183 return null; 184 } 185 return provider.getSensorProperties(sensorId); 186 } 187 188 @Override // Binder call generateChallenge(IBinder token, int sensorId, int userId, IFingerprintServiceReceiver receiver, String opPackageName)189 public void generateChallenge(IBinder token, int sensorId, int userId, 190 IFingerprintServiceReceiver receiver, String opPackageName) { 191 Utils.checkPermission(getContext(), MANAGE_FINGERPRINT); 192 193 final ServiceProvider provider = getProviderForSensor(sensorId); 194 if (provider == null) { 195 Slog.w(TAG, "No matching sensor for generateChallenge, sensorId: " + sensorId); 196 return; 197 } 198 199 provider.scheduleGenerateChallenge(sensorId, userId, token, receiver, opPackageName); 200 } 201 202 @Override // Binder call revokeChallenge(IBinder token, int sensorId, int userId, String opPackageName, long challenge)203 public void revokeChallenge(IBinder token, int sensorId, int userId, String opPackageName, 204 long challenge) { 205 Utils.checkPermission(getContext(), MANAGE_FINGERPRINT); 206 207 final ServiceProvider provider = getProviderForSensor(sensorId); 208 if (provider == null) { 209 Slog.w(TAG, "No matching sensor for revokeChallenge, sensorId: " + sensorId); 210 return; 211 } 212 213 provider.scheduleRevokeChallenge(sensorId, userId, token, opPackageName, 214 challenge); 215 } 216 217 @Override // Binder call enroll(final IBinder token, @NonNull final byte[] hardwareAuthToken, final int userId, final IFingerprintServiceReceiver receiver, final String opPackageName, @FingerprintManager.EnrollReason int enrollReason)218 public void enroll(final IBinder token, @NonNull final byte[] hardwareAuthToken, 219 final int userId, final IFingerprintServiceReceiver receiver, 220 final String opPackageName, @FingerprintManager.EnrollReason int enrollReason) { 221 Utils.checkPermission(getContext(), MANAGE_FINGERPRINT); 222 223 final Pair<Integer, ServiceProvider> provider = getSingleProvider(); 224 if (provider == null) { 225 Slog.w(TAG, "Null provider for enroll"); 226 return; 227 } 228 229 provider.second.scheduleEnroll(provider.first, token, hardwareAuthToken, userId, 230 receiver, opPackageName, enrollReason, mFingerprintStateCallback); 231 } 232 233 @Override // Binder call cancelEnrollment(final IBinder token)234 public void cancelEnrollment(final IBinder token) { 235 Utils.checkPermission(getContext(), MANAGE_FINGERPRINT); 236 237 final Pair<Integer, ServiceProvider> provider = getSingleProvider(); 238 if (provider == null) { 239 Slog.w(TAG, "Null provider for cancelEnrollment"); 240 return; 241 } 242 243 provider.second.cancelEnrollment(provider.first, token); 244 } 245 246 @SuppressWarnings("deprecation") 247 @Override // Binder call authenticate(final IBinder token, final long operationId, final int sensorId, final int userId, final IFingerprintServiceReceiver receiver, final String opPackageName)248 public void authenticate(final IBinder token, final long operationId, 249 final int sensorId, final int userId, final IFingerprintServiceReceiver receiver, 250 final String opPackageName) { 251 final int callingUid = Binder.getCallingUid(); 252 final int callingPid = Binder.getCallingPid(); 253 final int callingUserId = UserHandle.getCallingUserId(); 254 255 if (!canUseFingerprint(opPackageName, true /* requireForeground */, callingUid, 256 callingPid, callingUserId)) { 257 Slog.w(TAG, "Authenticate rejecting package: " + opPackageName); 258 return; 259 } 260 261 // Keyguard check must be done on the caller's binder identity, since it also checks 262 // permission. 263 final boolean isKeyguard = Utils.isKeyguard(getContext(), opPackageName); 264 265 // Clear calling identity when checking LockPatternUtils for StrongAuth flags. 266 long identity = Binder.clearCallingIdentity(); 267 try { 268 if (isKeyguard && Utils.isUserEncryptedOrLockdown(mLockPatternUtils, userId)) { 269 // If this happens, something in KeyguardUpdateMonitor is wrong. 270 // SafetyNet for b/79776455 271 EventLog.writeEvent(0x534e4554, "79776455"); 272 Slog.e(TAG, "Authenticate invoked when user is encrypted or lockdown"); 273 return; 274 } 275 } finally { 276 Binder.restoreCallingIdentity(identity); 277 } 278 279 final boolean restricted = getContext().checkCallingPermission(MANAGE_FINGERPRINT) 280 != PackageManager.PERMISSION_GRANTED; 281 final int statsClient = isKeyguard ? BiometricsProtoEnums.CLIENT_KEYGUARD 282 : BiometricsProtoEnums.CLIENT_FINGERPRINT_MANAGER; 283 284 final Pair<Integer, ServiceProvider> provider; 285 if (sensorId == FingerprintManager.SENSOR_ID_ANY) { 286 provider = getSingleProvider(); 287 } else { 288 Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL); 289 provider = new Pair<>(sensorId, getProviderForSensor(sensorId)); 290 } 291 if (provider == null) { 292 Slog.w(TAG, "Null provider for authenticate"); 293 return; 294 } 295 296 final FingerprintSensorPropertiesInternal sensorProps = 297 provider.second.getSensorProperties(sensorId); 298 if (!isKeyguard && !Utils.isSettings(getContext(), opPackageName) 299 && sensorProps != null && sensorProps.isAnyUdfpsType()) { 300 identity = Binder.clearCallingIdentity(); 301 try { 302 authenticateWithPrompt(operationId, sensorProps, userId, receiver); 303 } finally { 304 Binder.restoreCallingIdentity(identity); 305 } 306 } else { 307 provider.second.scheduleAuthenticate(provider.first, token, operationId, userId, 308 0 /* cookie */, new ClientMonitorCallbackConverter(receiver), opPackageName, 309 restricted, statsClient, isKeyguard, mFingerprintStateCallback); 310 } 311 } 312 authenticateWithPrompt( final long operationId, @NonNull final FingerprintSensorPropertiesInternal props, final int userId, final IFingerprintServiceReceiver receiver)313 private void authenticateWithPrompt( 314 final long operationId, 315 @NonNull final FingerprintSensorPropertiesInternal props, 316 final int userId, 317 final IFingerprintServiceReceiver receiver) { 318 319 final Context context = getUiContext(); 320 final Executor executor = context.getMainExecutor(); 321 322 final BiometricPrompt biometricPrompt = new BiometricPrompt.Builder(context) 323 .setTitle(context.getString(R.string.biometric_dialog_default_title)) 324 .setSubtitle(context.getString(R.string.fingerprint_dialog_default_subtitle)) 325 .setNegativeButton( 326 context.getString(R.string.cancel), 327 executor, 328 (dialog, which) -> { 329 try { 330 receiver.onError( 331 FINGERPRINT_ERROR_USER_CANCELED, 0 /* vendorCode */); 332 } catch (RemoteException e) { 333 Slog.e(TAG, "Remote exception in negative button onClick()", e); 334 } 335 }) 336 .setAllowedSensorIds(new ArrayList<>( 337 Collections.singletonList(props.sensorId))) 338 .build(); 339 340 final BiometricPrompt.AuthenticationCallback promptCallback = 341 new BiometricPrompt.AuthenticationCallback() { 342 @Override 343 public void onAuthenticationError(int errorCode, CharSequence errString) { 344 try { 345 if (FingerprintUtils.isKnownErrorCode(errorCode)) { 346 receiver.onError(errorCode, 0 /* vendorCode */); 347 } else { 348 receiver.onError(FINGERPRINT_ERROR_VENDOR, errorCode); 349 } 350 } catch (RemoteException e) { 351 Slog.e(TAG, "Remote exception in onAuthenticationError()", e); 352 } 353 } 354 355 @Override 356 public void onAuthenticationSucceeded( 357 BiometricPrompt.AuthenticationResult result) { 358 final Fingerprint fingerprint = new Fingerprint("", 0, 0L); 359 final boolean isStrong = props.sensorStrength == STRENGTH_STRONG; 360 try { 361 receiver.onAuthenticationSucceeded(fingerprint, userId, isStrong); 362 } catch (RemoteException e) { 363 Slog.e(TAG, "Remote exception in onAuthenticationSucceeded()", e); 364 } 365 } 366 367 @Override 368 public void onAuthenticationFailed() { 369 try { 370 receiver.onAuthenticationFailed(); 371 } catch (RemoteException e) { 372 Slog.e(TAG, "Remote exception in onAuthenticationFailed()", e); 373 } 374 } 375 376 @Override 377 public void onAuthenticationAcquired(int acquireInfo) { 378 try { 379 if (FingerprintUtils.isKnownAcquiredCode(acquireInfo)) { 380 receiver.onAcquired(acquireInfo, 0 /* vendorCode */); 381 } else { 382 receiver.onAcquired(FINGERPRINT_ACQUIRED_VENDOR, acquireInfo); 383 } 384 } catch (RemoteException e) { 385 Slog.e(TAG, "Remote exception in onAuthenticationAcquired()", e); 386 } 387 } 388 }; 389 390 biometricPrompt.authenticateUserForOperation( 391 new CancellationSignal(), executor, promptCallback, userId, operationId); 392 } 393 394 @Override detectFingerprint(final IBinder token, final int userId, final IFingerprintServiceReceiver receiver, final String opPackageName)395 public void detectFingerprint(final IBinder token, final int userId, 396 final IFingerprintServiceReceiver receiver, final String opPackageName) { 397 Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL); 398 if (!Utils.isKeyguard(getContext(), opPackageName)) { 399 Slog.w(TAG, "detectFingerprint called from non-sysui package: " + opPackageName); 400 return; 401 } 402 403 if (!Utils.isUserEncryptedOrLockdown(mLockPatternUtils, userId)) { 404 // If this happens, something in KeyguardUpdateMonitor is wrong. This should only 405 // ever be invoked when the user is encrypted or lockdown. 406 Slog.e(TAG, "detectFingerprint invoked when user is not encrypted or lockdown"); 407 return; 408 } 409 410 final Pair<Integer, ServiceProvider> provider = getSingleProvider(); 411 if (provider == null) { 412 Slog.w(TAG, "Null provider for detectFingerprint"); 413 return; 414 } 415 416 provider.second.scheduleFingerDetect(provider.first, token, userId, 417 new ClientMonitorCallbackConverter(receiver), opPackageName, 418 BiometricsProtoEnums.CLIENT_KEYGUARD, mFingerprintStateCallback); 419 } 420 421 @Override // Binder call prepareForAuthentication(int sensorId, IBinder token, long operationId, int userId, IBiometricSensorReceiver sensorReceiver, String opPackageName, int cookie, boolean allowBackgroundAuthentication)422 public void prepareForAuthentication(int sensorId, IBinder token, long operationId, 423 int userId, IBiometricSensorReceiver sensorReceiver, String opPackageName, 424 int cookie, boolean allowBackgroundAuthentication) { 425 Utils.checkPermission(getContext(), MANAGE_BIOMETRIC); 426 427 final ServiceProvider provider = getProviderForSensor(sensorId); 428 if (provider == null) { 429 Slog.w(TAG, "Null provider for prepareForAuthentication"); 430 return; 431 } 432 433 final boolean restricted = true; // BiometricPrompt is always restricted 434 provider.scheduleAuthenticate(sensorId, token, operationId, userId, cookie, 435 new ClientMonitorCallbackConverter(sensorReceiver), opPackageName, restricted, 436 BiometricsProtoEnums.CLIENT_BIOMETRIC_PROMPT, allowBackgroundAuthentication, 437 mFingerprintStateCallback); 438 } 439 440 @Override // Binder call startPreparedClient(int sensorId, int cookie)441 public void startPreparedClient(int sensorId, int cookie) { 442 Utils.checkPermission(getContext(), MANAGE_BIOMETRIC); 443 444 final ServiceProvider provider = getProviderForSensor(sensorId); 445 if (provider == null) { 446 Slog.w(TAG, "Null provider for startPreparedClient"); 447 return; 448 } 449 450 provider.startPreparedClient(sensorId, cookie); 451 } 452 453 454 @Override // Binder call cancelAuthentication(final IBinder token, final String opPackageName)455 public void cancelAuthentication(final IBinder token, final String opPackageName) { 456 final int callingUid = Binder.getCallingUid(); 457 final int callingPid = Binder.getCallingPid(); 458 final int callingUserId = UserHandle.getCallingUserId(); 459 460 if (!canUseFingerprint(opPackageName, true /* requireForeground */, callingUid, 461 callingPid, callingUserId)) { 462 Slog.w(TAG, "cancelAuthentication rejecting package: " + opPackageName); 463 return; 464 } 465 466 final Pair<Integer, ServiceProvider> provider = getSingleProvider(); 467 if (provider == null) { 468 Slog.w(TAG, "Null provider for cancelAuthentication"); 469 return; 470 } 471 472 provider.second.cancelAuthentication(provider.first, token); 473 } 474 475 @Override // Binder call cancelFingerprintDetect(final IBinder token, final String opPackageName)476 public void cancelFingerprintDetect(final IBinder token, final String opPackageName) { 477 Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL); 478 if (!Utils.isKeyguard(getContext(), opPackageName)) { 479 Slog.w(TAG, "cancelFingerprintDetect called from non-sysui package: " 480 + opPackageName); 481 return; 482 } 483 484 // For IBiometricsFingerprint2.1, cancelling fingerprint detect is the same as 485 // cancelling authentication. 486 final Pair<Integer, ServiceProvider> provider = getSingleProvider(); 487 if (provider == null) { 488 Slog.w(TAG, "Null provider for cancelFingerprintDetect"); 489 return; 490 } 491 492 provider.second.cancelAuthentication(provider.first, token); 493 } 494 495 @Override // Binder call cancelAuthenticationFromService(final int sensorId, final IBinder token, final String opPackageName)496 public void cancelAuthenticationFromService(final int sensorId, final IBinder token, 497 final String opPackageName) { 498 499 Utils.checkPermission(getContext(), MANAGE_BIOMETRIC); 500 501 Slog.d(TAG, "cancelAuthenticationFromService, sensorId: " + sensorId); 502 503 final ServiceProvider provider = getProviderForSensor(sensorId); 504 if (provider == null) { 505 Slog.w(TAG, "Null provider for cancelAuthenticationFromService"); 506 return; 507 } 508 509 provider.cancelAuthentication(sensorId, token); 510 } 511 512 @Override // Binder call remove(final IBinder token, final int fingerId, final int userId, final IFingerprintServiceReceiver receiver, final String opPackageName)513 public void remove(final IBinder token, final int fingerId, final int userId, 514 final IFingerprintServiceReceiver receiver, final String opPackageName) { 515 Utils.checkPermission(getContext(), MANAGE_FINGERPRINT); 516 517 final Pair<Integer, ServiceProvider> provider = getSingleProvider(); 518 if (provider == null) { 519 Slog.w(TAG, "Null provider for remove"); 520 return; 521 } 522 provider.second.scheduleRemove(provider.first, token, receiver, fingerId, userId, 523 opPackageName); 524 } 525 526 @Override // Binder call removeAll(final IBinder token, final int userId, final IFingerprintServiceReceiver receiver, final String opPackageName)527 public void removeAll(final IBinder token, final int userId, 528 final IFingerprintServiceReceiver receiver, final String opPackageName) { 529 Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL); 530 531 final FingerprintServiceReceiver internalReceiver = new FingerprintServiceReceiver() { 532 int sensorsFinishedRemoving = 0; 533 final int numSensors = getSensorPropertiesInternal( 534 getContext().getOpPackageName()).size(); 535 @Override 536 public void onRemoved(Fingerprint fp, int remaining) throws RemoteException { 537 if (remaining == 0) { 538 sensorsFinishedRemoving++; 539 Slog.d(TAG, "sensorsFinishedRemoving: " + sensorsFinishedRemoving 540 + ", numSensors: " + numSensors); 541 if (sensorsFinishedRemoving == numSensors) { 542 receiver.onRemoved(null, 0 /* remaining */); 543 } 544 } 545 } 546 }; 547 548 // This effectively iterates through all sensors, but has to do so by finding all 549 // sensors under each provider. 550 for (ServiceProvider provider : mServiceProviders) { 551 List<FingerprintSensorPropertiesInternal> props = provider.getSensorProperties(); 552 for (FingerprintSensorPropertiesInternal prop : props) { 553 provider.scheduleRemoveAll(prop.sensorId, token, internalReceiver, userId, 554 opPackageName); 555 } 556 } 557 } 558 559 @Override // Binder call addLockoutResetCallback(final IBiometricServiceLockoutResetCallback callback, final String opPackageName)560 public void addLockoutResetCallback(final IBiometricServiceLockoutResetCallback callback, 561 final String opPackageName) { 562 Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL); 563 mLockoutResetDispatcher.addCallback(callback, opPackageName); 564 } 565 566 @Override // Binder call dump(@onNull FileDescriptor fd, @NonNull PrintWriter pw, String[] args)567 protected void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter pw, String[] args) { 568 if (!DumpUtils.checkDumpPermission(getContext(), TAG, pw)) { 569 return; 570 } 571 572 final long ident = Binder.clearCallingIdentity(); 573 try { 574 if (args.length > 1 && "--proto".equals(args[0]) && "--state".equals(args[1])) { 575 final ProtoOutputStream proto = new ProtoOutputStream(fd); 576 for (ServiceProvider provider : mServiceProviders) { 577 for (FingerprintSensorPropertiesInternal props 578 : provider.getSensorProperties()) { 579 provider.dumpProtoState(props.sensorId, proto, false); 580 } 581 } 582 proto.flush(); 583 } else if (args.length > 0 && "--proto".equals(args[0])) { 584 for (ServiceProvider provider : mServiceProviders) { 585 for (FingerprintSensorPropertiesInternal props 586 : provider.getSensorProperties()) { 587 provider.dumpProtoMetrics(props.sensorId, fd); 588 } 589 } 590 } else { 591 for (ServiceProvider provider : mServiceProviders) { 592 for (FingerprintSensorPropertiesInternal props 593 : provider.getSensorProperties()) { 594 pw.println("Dumping for sensorId: " + props.sensorId 595 + ", provider: " + provider.getClass().getSimpleName()); 596 pw.println("Fps state: " 597 + mFingerprintStateCallback.getFingerprintState()); 598 provider.dumpInternal(props.sensorId, pw); 599 pw.println(); 600 } 601 } 602 } 603 } finally { 604 Binder.restoreCallingIdentity(ident); 605 } 606 } 607 608 @Override // Binder call isHardwareDetectedDeprecated(String opPackageName)609 public boolean isHardwareDetectedDeprecated(String opPackageName) { 610 if (!canUseFingerprint(opPackageName, false /* foregroundOnly */, 611 Binder.getCallingUid(), Binder.getCallingPid(), 612 UserHandle.getCallingUserId())) { 613 return false; 614 } 615 616 final long token = Binder.clearCallingIdentity(); 617 try { 618 final Pair<Integer, ServiceProvider> provider = getSingleProvider(); 619 if (provider == null) { 620 Slog.w(TAG, "Null provider for isHardwareDetectedDeprecated, caller: " 621 + opPackageName); 622 return false; 623 } 624 return provider.second.isHardwareDetected(provider.first); 625 } finally { 626 Binder.restoreCallingIdentity(token); 627 } 628 } 629 630 @Override // Binder call isHardwareDetected(int sensorId, String opPackageName)631 public boolean isHardwareDetected(int sensorId, String opPackageName) { 632 Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL); 633 634 final ServiceProvider provider = getProviderForSensor(sensorId); 635 if (provider == null) { 636 Slog.w(TAG, "Null provider for isHardwareDetected, caller: " + opPackageName); 637 return false; 638 } 639 640 return provider.isHardwareDetected(sensorId); 641 } 642 643 @Override // Binder call rename(final int fingerId, final int userId, final String name)644 public void rename(final int fingerId, final int userId, final String name) { 645 Utils.checkPermission(getContext(), MANAGE_FINGERPRINT); 646 if (!Utils.isCurrentUserOrProfile(getContext(), userId)) { 647 return; 648 } 649 650 final Pair<Integer, ServiceProvider> provider = getSingleProvider(); 651 if (provider == null) { 652 Slog.w(TAG, "Null provider for rename"); 653 return; 654 } 655 656 provider.second.rename(provider.first, fingerId, userId, name); 657 } 658 659 @Override // Binder call getEnrolledFingerprints(int userId, String opPackageName)660 public List<Fingerprint> getEnrolledFingerprints(int userId, String opPackageName) { 661 if (!canUseFingerprint(opPackageName, false /* foregroundOnly */, 662 Binder.getCallingUid(), Binder.getCallingPid(), 663 UserHandle.getCallingUserId())) { 664 return Collections.emptyList(); 665 } 666 667 if (userId != UserHandle.getCallingUserId()) { 668 Utils.checkPermission(getContext(), INTERACT_ACROSS_USERS); 669 } 670 671 return FingerprintService.this.getEnrolledFingerprintsDeprecated(userId, opPackageName); 672 } 673 674 @Override // Binder call hasEnrolledFingerprintsDeprecated(int userId, String opPackageName)675 public boolean hasEnrolledFingerprintsDeprecated(int userId, String opPackageName) { 676 if (!canUseFingerprint(opPackageName, false /* foregroundOnly */, 677 Binder.getCallingUid(), Binder.getCallingPid(), 678 UserHandle.getCallingUserId())) { 679 return false; 680 } 681 682 if (userId != UserHandle.getCallingUserId()) { 683 Utils.checkPermission(getContext(), INTERACT_ACROSS_USERS); 684 } 685 return !FingerprintService.this.getEnrolledFingerprintsDeprecated(userId, opPackageName) 686 .isEmpty(); 687 } 688 689 @Override // Binder call hasEnrolledTemplatesForAnySensor(int userId, @NonNull List<FingerprintSensorPropertiesInternal> sensors, @NonNull String opPackageName)690 public boolean hasEnrolledTemplatesForAnySensor(int userId, 691 @NonNull List<FingerprintSensorPropertiesInternal> sensors, 692 @NonNull String opPackageName) { 693 Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL); 694 695 for (FingerprintSensorPropertiesInternal prop : sensors) { 696 final ServiceProvider provider = getProviderForSensor(prop.sensorId); 697 if (provider == null) { 698 Slog.w(TAG, "Null provider for sensorId: " + prop.sensorId 699 + ", caller: " + opPackageName); 700 continue; 701 } 702 703 if (!provider.getEnrolledFingerprints(prop.sensorId, userId).isEmpty()) { 704 return true; 705 } 706 } 707 return false; 708 } 709 hasEnrolledFingerprints(int sensorId, int userId, String opPackageName)710 public boolean hasEnrolledFingerprints(int sensorId, int userId, String opPackageName) { 711 Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL); 712 713 final ServiceProvider provider = getProviderForSensor(sensorId); 714 if (provider == null) { 715 Slog.w(TAG, "Null provider for hasEnrolledFingerprints, caller: " + opPackageName); 716 return false; 717 } 718 719 return provider.getEnrolledFingerprints(sensorId, userId).size() > 0; 720 } 721 722 @Override // Binder call getLockoutModeForUser(int sensorId, int userId)723 public @LockoutTracker.LockoutMode int getLockoutModeForUser(int sensorId, int userId) { 724 Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL); 725 726 final ServiceProvider provider = getProviderForSensor(sensorId); 727 if (provider == null) { 728 Slog.w(TAG, "Null provider for getLockoutModeForUser"); 729 return LockoutTracker.LOCKOUT_NONE; 730 } 731 return provider.getLockoutModeForUser(sensorId, userId); 732 } 733 734 @Override invalidateAuthenticatorId(int sensorId, int userId, IInvalidationCallback callback)735 public void invalidateAuthenticatorId(int sensorId, int userId, 736 IInvalidationCallback callback) { 737 Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL); 738 739 final ServiceProvider provider = getProviderForSensor(sensorId); 740 if (provider == null) { 741 Slog.w(TAG, "Null provider for invalidateAuthenticatorId"); 742 return; 743 } 744 provider.scheduleInvalidateAuthenticatorId(sensorId, userId, callback); 745 } 746 747 @Override // Binder call getAuthenticatorId(int sensorId, int userId)748 public long getAuthenticatorId(int sensorId, int userId) { 749 Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL); 750 751 final ServiceProvider provider = getProviderForSensor(sensorId); 752 if (provider == null) { 753 Slog.w(TAG, "Null provider for getAuthenticatorId"); 754 return 0; 755 } 756 return provider.getAuthenticatorId(sensorId, userId); 757 } 758 759 @Override // Binder call resetLockout(IBinder token, int sensorId, int userId, @Nullable byte[] hardwareAuthToken, String opPackageName)760 public void resetLockout(IBinder token, int sensorId, int userId, 761 @Nullable byte[] hardwareAuthToken, String opPackageName) { 762 Utils.checkPermission(getContext(), RESET_FINGERPRINT_LOCKOUT); 763 764 final ServiceProvider provider = getProviderForSensor(sensorId); 765 if (provider == null) { 766 Slog.w(TAG, "Null provider for resetLockout, caller: " + opPackageName); 767 return; 768 } 769 770 provider.scheduleResetLockout(sensorId, userId, hardwareAuthToken); 771 } 772 773 @Override isClientActive()774 public boolean isClientActive() { 775 Utils.checkPermission(getContext(), MANAGE_FINGERPRINT); 776 return mGestureAvailabilityDispatcher.isAnySensorActive(); 777 } 778 779 @Override addClientActiveCallback(IFingerprintClientActiveCallback callback)780 public void addClientActiveCallback(IFingerprintClientActiveCallback callback) { 781 Utils.checkPermission(getContext(), MANAGE_FINGERPRINT); 782 mGestureAvailabilityDispatcher.registerCallback(callback); 783 } 784 785 @Override removeClientActiveCallback(IFingerprintClientActiveCallback callback)786 public void removeClientActiveCallback(IFingerprintClientActiveCallback callback) { 787 Utils.checkPermission(getContext(), MANAGE_FINGERPRINT); 788 mGestureAvailabilityDispatcher.removeCallback(callback); 789 } 790 addHidlProviders(List<FingerprintSensorPropertiesInternal> hidlSensors)791 private void addHidlProviders(List<FingerprintSensorPropertiesInternal> hidlSensors) { 792 for (FingerprintSensorPropertiesInternal hidlSensor : hidlSensors) { 793 final Fingerprint21 fingerprint21; 794 if ((Build.IS_USERDEBUG || Build.IS_ENG) 795 && getContext().getResources().getBoolean(R.bool.allow_test_udfps) 796 && Settings.Secure.getIntForUser(getContext().getContentResolver(), 797 Fingerprint21UdfpsMock.CONFIG_ENABLE_TEST_UDFPS, 0 /* default */, 798 UserHandle.USER_CURRENT) != 0) { 799 fingerprint21 = Fingerprint21UdfpsMock.newInstance(getContext(), hidlSensor, 800 mLockoutResetDispatcher, mGestureAvailabilityDispatcher); 801 } else { 802 fingerprint21 = Fingerprint21.newInstance(getContext(), hidlSensor, 803 mLockoutResetDispatcher, mGestureAvailabilityDispatcher); 804 } 805 mServiceProviders.add(fingerprint21); 806 } 807 } 808 addAidlProviders()809 private void addAidlProviders() { 810 final String[] instances = ServiceManager.getDeclaredInstances(IFingerprint.DESCRIPTOR); 811 if (instances == null || instances.length == 0) { 812 return; 813 } 814 for (String instance : instances) { 815 final String fqName = IFingerprint.DESCRIPTOR + "/" + instance; 816 final IFingerprint fp = IFingerprint.Stub.asInterface( 817 Binder.allowBlocking(ServiceManager.waitForDeclaredService(fqName))); 818 if (fp == null) { 819 Slog.e(TAG, "Unable to get declared service: " + fqName); 820 continue; 821 } 822 try { 823 final SensorProps[] props = fp.getSensorProps(); 824 final FingerprintProvider provider = 825 new FingerprintProvider(getContext(), props, instance, 826 mLockoutResetDispatcher, mGestureAvailabilityDispatcher); 827 mServiceProviders.add(provider); 828 } catch (RemoteException e) { 829 Slog.e(TAG, "Remote exception in getSensorProps: " + fqName); 830 } 831 } 832 } 833 834 @Override // Binder call registerAuthenticators( @onNull List<FingerprintSensorPropertiesInternal> hidlSensors)835 public void registerAuthenticators( 836 @NonNull List<FingerprintSensorPropertiesInternal> hidlSensors) { 837 Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL); 838 839 // Some HAL might not be started before the system service and will cause the code below 840 // to wait, and some of the operations below might take a significant amount of time to 841 // complete (calls to the HALs). To avoid blocking the rest of system server we put 842 // this on a background thread. 843 final ServiceThread thread = new ServiceThread(TAG, Process.THREAD_PRIORITY_BACKGROUND, 844 true /* allowIo */); 845 thread.start(); 846 final Handler handler = new Handler(thread.getLooper()); 847 848 handler.post(() -> { 849 addHidlProviders(hidlSensors); 850 addAidlProviders(); 851 852 final IBiometricService biometricService = IBiometricService.Stub.asInterface( 853 ServiceManager.getService(Context.BIOMETRIC_SERVICE)); 854 855 // Register each sensor individually with BiometricService 856 for (ServiceProvider provider : mServiceProviders) { 857 final List<FingerprintSensorPropertiesInternal> props = 858 provider.getSensorProperties(); 859 for (FingerprintSensorPropertiesInternal prop : props) { 860 final int sensorId = prop.sensorId; 861 final @BiometricManager.Authenticators.Types int strength = 862 Utils.propertyStrengthToAuthenticatorStrength(prop.sensorStrength); 863 final FingerprintAuthenticator authenticator = new FingerprintAuthenticator( 864 mServiceWrapper, sensorId); 865 try { 866 biometricService.registerAuthenticator(sensorId, TYPE_FINGERPRINT, 867 strength, authenticator); 868 } catch (RemoteException e) { 869 Slog.e(TAG, "Remote exception when registering sensorId: " + sensorId); 870 } 871 } 872 } 873 874 synchronized (mLock) { 875 for (ServiceProvider provider : mServiceProviders) { 876 mSensorProps.addAll(provider.getSensorProperties()); 877 } 878 } 879 880 broadcastAllAuthenticatorsRegistered(); 881 }); 882 } 883 884 @Override addAuthenticatorsRegisteredCallback( IFingerprintAuthenticatorsRegisteredCallback callback)885 public void addAuthenticatorsRegisteredCallback( 886 IFingerprintAuthenticatorsRegisteredCallback callback) { 887 Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL); 888 if (callback == null) { 889 Slog.e(TAG, "addAuthenticatorsRegisteredCallback, callback is null"); 890 return; 891 } 892 893 final boolean registered; 894 final boolean hasSensorProps; 895 synchronized (mLock) { 896 registered = mAuthenticatorsRegisteredCallbacks.register(callback); 897 hasSensorProps = !mSensorProps.isEmpty(); 898 } 899 if (registered && hasSensorProps) { 900 broadcastAllAuthenticatorsRegistered(); 901 } else if (!registered) { 902 Slog.e(TAG, "addAuthenticatorsRegisteredCallback failed to register callback"); 903 } 904 } 905 906 @Override onPointerDown(int sensorId, int x, int y, float minor, float major)907 public void onPointerDown(int sensorId, int x, int y, float minor, float major) { 908 Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL); 909 910 final ServiceProvider provider = getProviderForSensor(sensorId); 911 if (provider == null) { 912 Slog.w(TAG, "No matching provider for onFingerDown, sensorId: " + sensorId); 913 return; 914 } 915 provider.onPointerDown(sensorId, x, y, minor, major); 916 } 917 918 @Override onPointerUp(int sensorId)919 public void onPointerUp(int sensorId) { 920 Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL); 921 922 final ServiceProvider provider = getProviderForSensor(sensorId); 923 if (provider == null) { 924 Slog.w(TAG, "No matching provider for onFingerUp, sensorId: " + sensorId); 925 return; 926 } 927 provider.onPointerUp(sensorId); 928 } 929 930 @Override onUiReady(int sensorId)931 public void onUiReady(int sensorId) { 932 Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL); 933 934 final ServiceProvider provider = getProviderForSensor(sensorId); 935 if (provider == null) { 936 Slog.w(TAG, "No matching provider for onUiReady, sensorId: " + sensorId); 937 return; 938 } 939 provider.onUiReady(sensorId); 940 } 941 942 @Override setUdfpsOverlayController(@onNull IUdfpsOverlayController controller)943 public void setUdfpsOverlayController(@NonNull IUdfpsOverlayController controller) { 944 Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL); 945 946 for (ServiceProvider provider : mServiceProviders) { 947 provider.setUdfpsOverlayController(controller); 948 } 949 } 950 951 @Override setSidefpsController(@onNull ISidefpsController controller)952 public void setSidefpsController(@NonNull ISidefpsController controller) { 953 Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL); 954 955 for (ServiceProvider provider : mServiceProviders) { 956 provider.setSidefpsController(controller); 957 } 958 } 959 960 @Override registerFingerprintStateListener(@onNull IFingerprintStateListener listener)961 public void registerFingerprintStateListener(@NonNull IFingerprintStateListener listener) { 962 FingerprintService.this.registerFingerprintStateListener(listener); 963 } 964 } 965 FingerprintService(Context context)966 public FingerprintService(Context context) { 967 super(context); 968 mServiceWrapper = new FingerprintServiceWrapper(); 969 mAppOps = context.getSystemService(AppOpsManager.class); 970 mGestureAvailabilityDispatcher = new GestureAvailabilityDispatcher(); 971 mLockoutResetDispatcher = new LockoutResetDispatcher(context); 972 mLockPatternUtils = new LockPatternUtils(context); 973 mServiceProviders = new ArrayList<>(); 974 mFingerprintStateCallback = new FingerprintStateCallback(); 975 mAuthenticatorsRegisteredCallbacks = new RemoteCallbackList<>(); 976 mSensorProps = new ArrayList<>(); 977 } 978 979 // Notifies the callbacks that all of the authenticators have been registered and removes the 980 // invoked callbacks from the callback list. broadcastAllAuthenticatorsRegistered()981 private void broadcastAllAuthenticatorsRegistered() { 982 // Make a local copy of the data so it can be used outside of the synchronized block when 983 // making Binder calls. 984 final List<IFingerprintAuthenticatorsRegisteredCallback> callbacks = new ArrayList<>(); 985 final List<FingerprintSensorPropertiesInternal> props; 986 synchronized (mLock) { 987 if (!mSensorProps.isEmpty()) { 988 props = new ArrayList<>(mSensorProps); 989 } else { 990 Slog.e(TAG, "mSensorProps is empty"); 991 return; 992 } 993 final int n = mAuthenticatorsRegisteredCallbacks.beginBroadcast(); 994 for (int i = 0; i < n; ++i) { 995 final IFingerprintAuthenticatorsRegisteredCallback cb = 996 mAuthenticatorsRegisteredCallbacks.getBroadcastItem(i); 997 callbacks.add(cb); 998 mAuthenticatorsRegisteredCallbacks.unregister(cb); 999 } 1000 mAuthenticatorsRegisteredCallbacks.finishBroadcast(); 1001 } 1002 for (IFingerprintAuthenticatorsRegisteredCallback cb : callbacks) { 1003 try { 1004 cb.onAllAuthenticatorsRegistered(props); 1005 } catch (RemoteException e) { 1006 Slog.e(TAG, "Remote exception in onAllAuthenticatorsRegistered", e); 1007 } 1008 } 1009 } 1010 1011 @Override onStart()1012 public void onStart() { 1013 publishBinderService(Context.FINGERPRINT_SERVICE, mServiceWrapper); 1014 } 1015 1016 @Nullable getProviderForSensor(int sensorId)1017 private ServiceProvider getProviderForSensor(int sensorId) { 1018 for (ServiceProvider provider : mServiceProviders) { 1019 if (provider.containsSensor(sensorId)) { 1020 return provider; 1021 } 1022 } 1023 return null; 1024 } 1025 1026 /** 1027 * For devices with only a single provider, returns that provider. If multiple providers, 1028 * returns the first one. If no providers, returns null. 1029 */ 1030 @Nullable getSingleProvider()1031 private Pair<Integer, ServiceProvider> getSingleProvider() { 1032 final List<FingerprintSensorPropertiesInternal> properties = getSensorProperties(); 1033 if (properties.isEmpty()) { 1034 Slog.e(TAG, "No providers found"); 1035 return null; 1036 } 1037 1038 // Theoretically we can just return the first provider, but maybe this is easier to 1039 // understand. 1040 final int sensorId = properties.get(0).sensorId; 1041 for (ServiceProvider provider : mServiceProviders) { 1042 if (provider.containsSensor(sensorId)) { 1043 return new Pair<>(sensorId, provider); 1044 } 1045 } 1046 1047 Slog.e(TAG, "Provider not found"); 1048 return null; 1049 } 1050 1051 @NonNull getSensorProperties()1052 private List<FingerprintSensorPropertiesInternal> getSensorProperties() { 1053 synchronized (mLock) { 1054 return mSensorProps; 1055 } 1056 } 1057 1058 @NonNull getEnrolledFingerprintsDeprecated(int userId, String opPackageName)1059 private List<Fingerprint> getEnrolledFingerprintsDeprecated(int userId, String opPackageName) { 1060 final Pair<Integer, ServiceProvider> provider = getSingleProvider(); 1061 if (provider == null) { 1062 Slog.w(TAG, "Null provider for getEnrolledFingerprintsDeprecated, caller: " 1063 + opPackageName); 1064 return Collections.emptyList(); 1065 } 1066 1067 return provider.second.getEnrolledFingerprints(provider.first, userId); 1068 } 1069 1070 /** 1071 * Checks for public API invocations to ensure that permissions, etc are granted/correct. 1072 */ 1073 @SuppressWarnings("BooleanMethodIsAlwaysInverted") canUseFingerprint(String opPackageName, boolean requireForeground, int uid, int pid, int userId)1074 private boolean canUseFingerprint(String opPackageName, boolean requireForeground, int uid, 1075 int pid, int userId) { 1076 if (getContext().checkCallingPermission(USE_FINGERPRINT) 1077 != PackageManager.PERMISSION_GRANTED) { 1078 Utils.checkPermission(getContext(), USE_BIOMETRIC); 1079 } 1080 1081 if (Binder.getCallingUid() == Process.SYSTEM_UID) { 1082 return true; // System process (BiometricService, etc) is always allowed 1083 } 1084 if (Utils.isKeyguard(getContext(), opPackageName)) { 1085 return true; 1086 } 1087 if (!Utils.isCurrentUserOrProfile(getContext(), userId)) { 1088 Slog.w(TAG, "Rejecting " + opPackageName + "; not a current user or profile"); 1089 return false; 1090 } 1091 if (!checkAppOps(uid, opPackageName)) { 1092 Slog.w(TAG, "Rejecting " + opPackageName + "; permission denied"); 1093 return false; 1094 } 1095 if (requireForeground && !Utils.isForeground(uid, pid)) { 1096 Slog.w(TAG, "Rejecting " + opPackageName + "; not in foreground"); 1097 return false; 1098 } 1099 return true; 1100 } 1101 checkAppOps(int uid, String opPackageName)1102 private boolean checkAppOps(int uid, String opPackageName) { 1103 boolean appOpsOk = false; 1104 if (mAppOps.noteOp(AppOpsManager.OP_USE_BIOMETRIC, uid, opPackageName) 1105 == AppOpsManager.MODE_ALLOWED) { 1106 appOpsOk = true; 1107 } else if (mAppOps.noteOp(AppOpsManager.OP_USE_FINGERPRINT, uid, opPackageName) 1108 == AppOpsManager.MODE_ALLOWED) { 1109 appOpsOk = true; 1110 } 1111 return appOpsOk; 1112 } 1113 } 1114