Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ab1dcf5e authored by Kevin Chyn's avatar Kevin Chyn
Browse files

31/n: Move Fingerprint2.1 into a wrapper with its own scheduler

This is a pretty big change since it basically allows/requires us to
have FingerprintService not extend from BiometricServiceBase anymore

Bug: 157790417
Bug: 158481661

1) Move Fingerprint2.1-specific code into wrapper class. This will
   A) Make it obvious where global dependencies still exist, and
   B) Make room for new HIDLs
2) Sensor-ID is creeping in. Eventually there will be Manager-level
   APIs for platform code to query functionality. Most likely all
   IFingerprintService/IFaceService interfaces will have sensorId
   as a parameter soon
3) Added Udfps interface and UdfpsHelper
4) FingerprintService no longer extends from BiometricServiceBase.
   BiometricServiceBase will be removed soon. A lot of permission
   checking is fingerprint-specific, since face operations all
   require internal permission. Thus, moved canUseBiometric into
   FingerprintService
5) Updated fingerprint retry logic in KeyguardUpdateMonitor. The
   retry should keep going if isHardwareDetected()==false. Also
   increased the retry counter, seems like HAL reload time has
   increased.

Test: enroll, auth (settings), auth (keyguard), auth (BiometricPrompt),
      rename, remove
Test: atest com.android.server.biometrics
Test: atest KeyguardUpdateMonitorTest
Test: Reset lockout
Test: atest AccessibilityFingerprintGestureTest
Test: Fingerprint stack recovers after HAL death, e.g.
      1) Go to keyguard
      2) adb shell ps | grep -i fingerprint
      3) adb shell killall -9 android.hardware.biometrics...
      4) fingerprint auth resumes after HAL reloads
Test: CtsVerifier
Test: adb shell dumpsys fingerprint
Test: Modify settings to not cancel auth when onPause, notice
      task stack listener stopping settings auth
Test: Invoke assistant on keyguard, auth continues
Test: No effect on face auth devices (enroll, auth on keyguard,
      BiometricPrompt)

Change-Id: Iffbdd841c093fe612e664195dcf79319d1d444ab
parent 27fa2683
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -26,5 +26,5 @@ oneway interface IBiometricServiceLockoutResetCallback {
    /**
     * A wakelock will be held until the reciever calls back into {@param callback}
     */
    void onLockoutReset(IRemoteCallback callback);
    void onLockoutReset(int sensorId, IRemoteCallback callback);
}
+3 −3
Original line number Diff line number Diff line
@@ -592,7 +592,7 @@ public class FaceManager implements BiometricAuthenticator, BiometricFaceConstan
                        new IBiometricServiceLockoutResetCallback.Stub() {

                            @Override
                            public void onLockoutReset(IRemoteCallback serverCallback)
                            public void onLockoutReset(int sensorId, IRemoteCallback serverCallback)
                                    throws RemoteException {
                                try {
                                    final PowerManager.WakeLock wakeLock = powerManager.newWakeLock(
@@ -601,7 +601,7 @@ public class FaceManager implements BiometricAuthenticator, BiometricFaceConstan
                                    wakeLock.acquire();
                                    mHandler.post(() -> {
                                        try {
                                            callback.onLockoutReset();
                                            callback.onLockoutReset(sensorId);
                                        } finally {
                                            wakeLock.release();
                                        }
@@ -978,7 +978,7 @@ public class FaceManager implements BiometricAuthenticator, BiometricFaceConstan
         * authentication
         * again.
         */
        public void onLockoutReset() {
        public void onLockoutReset(int sensorId) {
        }
    }

+3 −3
Original line number Diff line number Diff line
@@ -347,7 +347,7 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing
         * Called when lockout period expired and clients are allowed to listen for fingerprint
         * again.
         */
        public void onLockoutReset() { }
        public void onLockoutReset(int sensorId) { }
    };

    /**
@@ -751,7 +751,7 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing
                        new IBiometricServiceLockoutResetCallback.Stub() {

                    @Override
                    public void onLockoutReset(IRemoteCallback serverCallback)
                    public void onLockoutReset(int sensorId, IRemoteCallback serverCallback)
                            throws RemoteException {
                        try {
                            final PowerManager.WakeLock wakeLock = powerManager.newWakeLock(
@@ -759,7 +759,7 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing
                            wakeLock.acquire();
                            mHandler.post(() -> {
                                try {
                                    callback.onLockoutReset();
                                    callback.onLockoutReset(sensorId);
                                } finally {
                                    wakeLock.release();
                                }
+11 −10
Original line number Diff line number Diff line
@@ -295,7 +295,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
    private int mHardwareFingerprintUnavailableRetryCount = 0;
    private int mHardwareFaceUnavailableRetryCount = 0;
    private static final int HAL_ERROR_RETRY_TIMEOUT = 500; // ms
    private static final int HAL_ERROR_RETRY_MAX = 10;
    private static final int HAL_ERROR_RETRY_MAX = 20;

    private final Runnable mCancelNotReceived = new Runnable() {
        @Override
@@ -682,7 +682,12 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
        public void run() {
            Log.w(TAG, "Retrying fingerprint after HW unavailable, attempt " +
                    mHardwareFingerprintUnavailableRetryCount);
            if (mFpm.isHardwareDetected()) {
                updateFingerprintListeningState();
            } else if (mHardwareFingerprintUnavailableRetryCount < HAL_ERROR_RETRY_MAX) {
                mHardwareFingerprintUnavailableRetryCount++;
                mHandler.postDelayed(mRetryFingerprintAuthentication, HAL_ERROR_RETRY_TIMEOUT);
            }
        }
    };

@@ -704,12 +709,8 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
        }

        if (msgId == FingerprintManager.FINGERPRINT_ERROR_HW_UNAVAILABLE) {
            if (mHardwareFingerprintUnavailableRetryCount < HAL_ERROR_RETRY_MAX) {
                mHardwareFingerprintUnavailableRetryCount++;
                mHandler.removeCallbacks(mRetryFingerprintAuthentication);
            mHandler.postDelayed(mRetryFingerprintAuthentication, HAL_ERROR_RETRY_TIMEOUT);
        }
        }

        if (msgId == FingerprintManager.FINGERPRINT_ERROR_LOCKOUT_PERMANENT) {
            mLockPatternUtils.requireStrongAuth(STRONG_AUTH_REQUIRED_AFTER_LOCKOUT,
@@ -1234,7 +1235,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
    private final FingerprintManager.LockoutResetCallback mFingerprintLockoutResetCallback
            = new FingerprintManager.LockoutResetCallback() {
        @Override
        public void onLockoutReset() {
        public void onLockoutReset(int sensorId) {
            handleFingerprintLockoutReset();
        }
    };
@@ -1242,7 +1243,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
    private final FaceManager.LockoutResetCallback mFaceLockoutResetCallback
            = new FaceManager.LockoutResetCallback() {
        @Override
        public void onLockoutReset() {
        public void onLockoutReset(int sensorId) {
            handleFaceLockoutReset();
        }
    };
@@ -1838,7 +1839,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
        if (mHandler.hasMessages(MSG_BIOMETRIC_AUTHENTICATION_CONTINUE)) {
            return;
        }
        mHandler.removeCallbacks(mRetryFingerprintAuthentication);

        boolean shouldListenForFingerprint = shouldListenForFingerprint();
        boolean runningOrRestarting = mFingerprintRunningState == BIOMETRIC_STATE_RUNNING
                || mFingerprintRunningState == BIOMETRIC_STATE_CANCELLING_RESTARTING;
+64 −0
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package com.android.server.biometrics;

import static android.Manifest.permission.USE_BIOMETRIC_INTERNAL;
import static android.hardware.biometrics.BiometricManager.Authenticators;

import static com.android.server.biometrics.PreAuthInfo.AUTHENTICATOR_OK;
@@ -30,19 +31,32 @@ import static com.android.server.biometrics.PreAuthInfo.BIOMETRIC_NOT_ENROLLED;
import static com.android.server.biometrics.PreAuthInfo.BIOMETRIC_NO_HARDWARE;
import static com.android.server.biometrics.PreAuthInfo.CREDENTIAL_NOT_ENROLLED;

import android.app.ActivityManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.PackageManager;
import android.hardware.biometrics.BiometricAuthenticator;
import android.hardware.biometrics.BiometricConstants;
import android.hardware.biometrics.BiometricManager;
import android.hardware.biometrics.BiometricPrompt;
import android.hardware.biometrics.BiometricPrompt.AuthenticationResultType;
import android.hardware.biometrics.IBiometricService;
import android.hardware.biometrics.PromptInfo;
import android.os.Binder;
import android.os.Build;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.UserHandle;
import android.os.UserManager;
import android.provider.Settings;
import android.util.Slog;

import com.android.internal.R;

public class Utils {

    private static final String TAG = "BiometricUtils";

    public static boolean isDebugEnabled(Context context, int targetUserId) {
        if (targetUserId == UserHandle.USER_NULL) {
            return false;
@@ -331,4 +345,54 @@ public class Utils {
        }
        return false;
    }

    public static void checkPermission(Context context, String permission) {
        context.enforceCallingOrSelfPermission(permission,
                "Must have " + permission + " permission.");
    }

    public static boolean isCurrentUserOrProfile(Context context, int userId) {
        UserManager um = UserManager.get(context);
        if (um == null) {
            Slog.e(TAG, "Unable to get UserManager");
            return false;
        }

        final long token = Binder.clearCallingIdentity();
        try {
            // Allow current user or profiles of the current user...
            for (int profileId : um.getEnabledProfileIds(ActivityManager.getCurrentUser())) {
                if (profileId == userId) {
                    return true;
                }
            }
        } finally {
            Binder.restoreCallingIdentity(token);
        }

        return false;
    }

    public static boolean isStrongBiometric(int sensorId) {
        IBiometricService service = IBiometricService.Stub.asInterface(
                ServiceManager.getService(Context.BIOMETRIC_SERVICE));
        try {
            return Utils.isAtLeastStrength(service.getCurrentStrength(sensorId),
                    Authenticators.BIOMETRIC_STRONG);
        } catch (RemoteException e) {
            Slog.e(TAG, "RemoteException", e);
            return false;
        }
    }

    public static boolean isKeyguard(Context context, String clientPackage) {
        final boolean hasPermission = context.checkCallingOrSelfPermission(USE_BIOMETRIC_INTERNAL)
                == PackageManager.PERMISSION_GRANTED;

        final ComponentName keyguardComponent = ComponentName.unflattenFromString(
                context.getResources().getString(R.string.config_keyguardComponent));
        final String keyguardPackage = keyguardComponent != null
                ? keyguardComponent.getPackageName() : null;
        return hasPermission && keyguardPackage != null && keyguardPackage.equals(clientPackage);
    }
}
Loading