Loading services/core/java/com/android/server/biometrics/BiometricService.java +7 −0 Original line number Diff line number Diff line Loading @@ -1106,6 +1106,11 @@ public class BiometricService extends SystemService { return Settings.Secure.getInt(context.getContentResolver(), CoexCoordinator.SETTING_ENABLE_NAME, 1) != 0; } public boolean isCoexFaceNonBypassHapticsDisabled(Context context) { return Settings.Secure.getInt(context.getContentResolver(), CoexCoordinator.FACE_HAPTIC_DISABLE, 1) != 0; } } /** Loading Loading @@ -1137,6 +1142,8 @@ public class BiometricService extends SystemService { // by default. CoexCoordinator coexCoordinator = CoexCoordinator.getInstance(); coexCoordinator.setAdvancedLogicEnabled(injector.isAdvancedCoexLogicEnabled(context)); coexCoordinator.setFaceHapticDisabledWhenNonBypass( injector.isCoexFaceNonBypassHapticsDisabled(context)); try { injector.getActivityManagerService().registerUserSwitchObserver( Loading services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java +9 −3 Original line number Diff line number Diff line Loading @@ -54,12 +54,18 @@ public abstract class AuthenticationClient<T> extends AcquisitionClient<T> public static final int STATE_NEW = 0; // Framework/HAL have started this operation public static final int STATE_STARTED = 1; // Operation is started, but requires some user action (such as finger lift & re-touch) // Operation is started, but requires some user action to start (such as finger lift & re-touch) public static final int STATE_STARTED_PAUSED = 2; // Same as above, except auth was attempted (rejected, timed out, etc). public static final int STATE_STARTED_PAUSED_ATTEMPTED = 3; // Done, errored, canceled, etc. HAL/framework are not running this sensor anymore. public static final int STATE_STOPPED = 3; public static final int STATE_STOPPED = 4; @IntDef({STATE_NEW, STATE_STARTED, STATE_STARTED_PAUSED, STATE_STOPPED}) @IntDef({STATE_NEW, STATE_STARTED, STATE_STARTED_PAUSED, STATE_STARTED_PAUSED_ATTEMPTED, STATE_STOPPED}) @interface State {} private final boolean mIsStrongBiometric; Loading services/core/java/com/android/server/biometrics/sensors/CoexCoordinator.java +34 −4 Original line number Diff line number Diff line Loading @@ -45,6 +45,8 @@ public class CoexCoordinator { private static final String TAG = "BiometricCoexCoordinator"; public static final String SETTING_ENABLE_NAME = "com.android.server.biometrics.sensors.CoexCoordinator.enable"; public static final String FACE_HAPTIC_DISABLE = "com.android.server.biometrics.sensors.CoexCoordinator.disable_face_haptics"; private static final boolean DEBUG = true; // Successful authentications should be used within this amount of time. Loading Loading @@ -144,6 +146,10 @@ public class CoexCoordinator { mAdvancedLogicEnabled = enabled; } public void setFaceHapticDisabledWhenNonBypass(boolean disabled) { mFaceHapticDisabledWhenNonBypass = disabled; } @VisibleForTesting void reset() { mClientMap.clear(); Loading @@ -153,6 +159,7 @@ public class CoexCoordinator { private final Map<Integer, AuthenticationClient<?>> mClientMap; @VisibleForTesting final LinkedList<SuccessfulAuth> mSuccessfulAuths; private boolean mAdvancedLogicEnabled; private boolean mFaceHapticDisabledWhenNonBypass; private final Handler mHandler; private CoexCoordinator() { Loading Loading @@ -224,8 +231,12 @@ public class CoexCoordinator { // 2) UDFPS rejected - use this face auth success to notify clients mSuccessfulAuths.add(new SuccessfulAuth(mHandler, mSuccessfulAuths, currentTimeMillis, SENSOR_TYPE_FACE, client, callback)); } else { if (mFaceHapticDisabledWhenNonBypass && !face.isKeyguardBypassEnabled()) { Slog.w(TAG, "Skipping face success haptic"); } else { callback.sendHapticFeedback(); } callback.sendAuthenticationResult(true /* addAuthTokenIfStrong */); callback.handleLifecycleAfterAuth(); } Loading Loading @@ -278,10 +289,21 @@ public class CoexCoordinator { // BiometricScheduler do not get stuck. Slog.d(TAG, "Face rejected in multi-sensor auth, udfps: " + udfps); callback.handleLifecycleAfterAuth(); } else if (isUdfpsAuthAttempted(udfps)) { // If UDFPS is STATE_STARTED_PAUSED (e.g. finger rejected but can still // auth after pointer goes down, it means UDFPS encountered a rejection. In // this case, we need to play the final reject haptic since face auth is // also done now. callback.sendHapticFeedback(); callback.handleLifecycleAfterAuth(); } else { // UDFPS auth has never been attempted. if (mFaceHapticDisabledWhenNonBypass && !face.isKeyguardBypassEnabled()) { Slog.w(TAG, "Skipping face reject haptic"); } else { // UDFPS is not actively authenticating (finger not touching, already // rejected, etc). callback.sendHapticFeedback(); } callback.handleLifecycleAfterAuth(); } } else if (isCurrentUdfps(client)) { Loading Loading @@ -374,6 +396,13 @@ public class CoexCoordinator { return false; } private static boolean isUdfpsAuthAttempted(@Nullable AuthenticationClient<?> client) { if (client instanceof Udfps) { return client.getState() == AuthenticationClient.STATE_STARTED_PAUSED_ATTEMPTED; } return false; } private boolean isUnknownClient(@NonNull AuthenticationClient<?> client) { for (AuthenticationClient<?> c : mClientMap.values()) { if (c == client) { Loading @@ -400,6 +429,7 @@ public class CoexCoordinator { public String toString() { StringBuilder sb = new StringBuilder(); sb.append("Enabled: ").append(mAdvancedLogicEnabled); sb.append(", Face Haptic Disabled: ").append(mFaceHapticDisabledWhenNonBypass); sb.append(", Queue size: " ).append(mSuccessfulAuths.size()); for (SuccessfulAuth auth : mSuccessfulAuths) { sb.append(", Auth: ").append(auth.toString()); Loading services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java +2 −2 Original line number Diff line number Diff line Loading @@ -114,7 +114,7 @@ class FingerprintAuthenticationClient extends AuthenticationClient<ISession> imp mState = STATE_STOPPED; UdfpsHelper.hideUdfpsOverlay(getSensorId(), mUdfpsOverlayController); } else { mState = STATE_STARTED_PAUSED; mState = STATE_STARTED_PAUSED_ATTEMPTED; } } Loading Loading @@ -188,7 +188,7 @@ class FingerprintAuthenticationClient extends AuthenticationClient<ISession> imp public void onPointerUp() { try { mIsPointerDown = false; mState = STATE_STARTED_PAUSED; mState = STATE_STARTED_PAUSED_ATTEMPTED; mALSProbeCallback.getProbe().disable(); getFreshDaemon().onPointerUp(0 /* pointerId */); Loading services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintAuthenticationClient.java +2 −2 Original line number Diff line number Diff line Loading @@ -112,7 +112,7 @@ class FingerprintAuthenticationClient extends AuthenticationClient<IBiometricsFi resetFailedAttempts(getTargetUserId()); UdfpsHelper.hideUdfpsOverlay(getSensorId(), mUdfpsOverlayController); } else { mState = STATE_STARTED_PAUSED; mState = STATE_STARTED_PAUSED_ATTEMPTED; final @LockoutTracker.LockoutMode int lockoutMode = mLockoutFrameworkImpl.getLockoutModeForUser(getTargetUserId()); if (lockoutMode != LockoutTracker.LOCKOUT_NONE) { Loading Loading @@ -206,7 +206,7 @@ class FingerprintAuthenticationClient extends AuthenticationClient<IBiometricsFi @Override public void onPointerUp() { mIsPointerDown = false; mState = STATE_STARTED_PAUSED; mState = STATE_STARTED_PAUSED_ATTEMPTED; mALSProbeCallback.getProbe().disable(); UdfpsHelper.onFingerUp(getFreshDaemon()); Loading Loading
services/core/java/com/android/server/biometrics/BiometricService.java +7 −0 Original line number Diff line number Diff line Loading @@ -1106,6 +1106,11 @@ public class BiometricService extends SystemService { return Settings.Secure.getInt(context.getContentResolver(), CoexCoordinator.SETTING_ENABLE_NAME, 1) != 0; } public boolean isCoexFaceNonBypassHapticsDisabled(Context context) { return Settings.Secure.getInt(context.getContentResolver(), CoexCoordinator.FACE_HAPTIC_DISABLE, 1) != 0; } } /** Loading Loading @@ -1137,6 +1142,8 @@ public class BiometricService extends SystemService { // by default. CoexCoordinator coexCoordinator = CoexCoordinator.getInstance(); coexCoordinator.setAdvancedLogicEnabled(injector.isAdvancedCoexLogicEnabled(context)); coexCoordinator.setFaceHapticDisabledWhenNonBypass( injector.isCoexFaceNonBypassHapticsDisabled(context)); try { injector.getActivityManagerService().registerUserSwitchObserver( Loading
services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java +9 −3 Original line number Diff line number Diff line Loading @@ -54,12 +54,18 @@ public abstract class AuthenticationClient<T> extends AcquisitionClient<T> public static final int STATE_NEW = 0; // Framework/HAL have started this operation public static final int STATE_STARTED = 1; // Operation is started, but requires some user action (such as finger lift & re-touch) // Operation is started, but requires some user action to start (such as finger lift & re-touch) public static final int STATE_STARTED_PAUSED = 2; // Same as above, except auth was attempted (rejected, timed out, etc). public static final int STATE_STARTED_PAUSED_ATTEMPTED = 3; // Done, errored, canceled, etc. HAL/framework are not running this sensor anymore. public static final int STATE_STOPPED = 3; public static final int STATE_STOPPED = 4; @IntDef({STATE_NEW, STATE_STARTED, STATE_STARTED_PAUSED, STATE_STOPPED}) @IntDef({STATE_NEW, STATE_STARTED, STATE_STARTED_PAUSED, STATE_STARTED_PAUSED_ATTEMPTED, STATE_STOPPED}) @interface State {} private final boolean mIsStrongBiometric; Loading
services/core/java/com/android/server/biometrics/sensors/CoexCoordinator.java +34 −4 Original line number Diff line number Diff line Loading @@ -45,6 +45,8 @@ public class CoexCoordinator { private static final String TAG = "BiometricCoexCoordinator"; public static final String SETTING_ENABLE_NAME = "com.android.server.biometrics.sensors.CoexCoordinator.enable"; public static final String FACE_HAPTIC_DISABLE = "com.android.server.biometrics.sensors.CoexCoordinator.disable_face_haptics"; private static final boolean DEBUG = true; // Successful authentications should be used within this amount of time. Loading Loading @@ -144,6 +146,10 @@ public class CoexCoordinator { mAdvancedLogicEnabled = enabled; } public void setFaceHapticDisabledWhenNonBypass(boolean disabled) { mFaceHapticDisabledWhenNonBypass = disabled; } @VisibleForTesting void reset() { mClientMap.clear(); Loading @@ -153,6 +159,7 @@ public class CoexCoordinator { private final Map<Integer, AuthenticationClient<?>> mClientMap; @VisibleForTesting final LinkedList<SuccessfulAuth> mSuccessfulAuths; private boolean mAdvancedLogicEnabled; private boolean mFaceHapticDisabledWhenNonBypass; private final Handler mHandler; private CoexCoordinator() { Loading Loading @@ -224,8 +231,12 @@ public class CoexCoordinator { // 2) UDFPS rejected - use this face auth success to notify clients mSuccessfulAuths.add(new SuccessfulAuth(mHandler, mSuccessfulAuths, currentTimeMillis, SENSOR_TYPE_FACE, client, callback)); } else { if (mFaceHapticDisabledWhenNonBypass && !face.isKeyguardBypassEnabled()) { Slog.w(TAG, "Skipping face success haptic"); } else { callback.sendHapticFeedback(); } callback.sendAuthenticationResult(true /* addAuthTokenIfStrong */); callback.handleLifecycleAfterAuth(); } Loading Loading @@ -278,10 +289,21 @@ public class CoexCoordinator { // BiometricScheduler do not get stuck. Slog.d(TAG, "Face rejected in multi-sensor auth, udfps: " + udfps); callback.handleLifecycleAfterAuth(); } else if (isUdfpsAuthAttempted(udfps)) { // If UDFPS is STATE_STARTED_PAUSED (e.g. finger rejected but can still // auth after pointer goes down, it means UDFPS encountered a rejection. In // this case, we need to play the final reject haptic since face auth is // also done now. callback.sendHapticFeedback(); callback.handleLifecycleAfterAuth(); } else { // UDFPS auth has never been attempted. if (mFaceHapticDisabledWhenNonBypass && !face.isKeyguardBypassEnabled()) { Slog.w(TAG, "Skipping face reject haptic"); } else { // UDFPS is not actively authenticating (finger not touching, already // rejected, etc). callback.sendHapticFeedback(); } callback.handleLifecycleAfterAuth(); } } else if (isCurrentUdfps(client)) { Loading Loading @@ -374,6 +396,13 @@ public class CoexCoordinator { return false; } private static boolean isUdfpsAuthAttempted(@Nullable AuthenticationClient<?> client) { if (client instanceof Udfps) { return client.getState() == AuthenticationClient.STATE_STARTED_PAUSED_ATTEMPTED; } return false; } private boolean isUnknownClient(@NonNull AuthenticationClient<?> client) { for (AuthenticationClient<?> c : mClientMap.values()) { if (c == client) { Loading @@ -400,6 +429,7 @@ public class CoexCoordinator { public String toString() { StringBuilder sb = new StringBuilder(); sb.append("Enabled: ").append(mAdvancedLogicEnabled); sb.append(", Face Haptic Disabled: ").append(mFaceHapticDisabledWhenNonBypass); sb.append(", Queue size: " ).append(mSuccessfulAuths.size()); for (SuccessfulAuth auth : mSuccessfulAuths) { sb.append(", Auth: ").append(auth.toString()); Loading
services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java +2 −2 Original line number Diff line number Diff line Loading @@ -114,7 +114,7 @@ class FingerprintAuthenticationClient extends AuthenticationClient<ISession> imp mState = STATE_STOPPED; UdfpsHelper.hideUdfpsOverlay(getSensorId(), mUdfpsOverlayController); } else { mState = STATE_STARTED_PAUSED; mState = STATE_STARTED_PAUSED_ATTEMPTED; } } Loading Loading @@ -188,7 +188,7 @@ class FingerprintAuthenticationClient extends AuthenticationClient<ISession> imp public void onPointerUp() { try { mIsPointerDown = false; mState = STATE_STARTED_PAUSED; mState = STATE_STARTED_PAUSED_ATTEMPTED; mALSProbeCallback.getProbe().disable(); getFreshDaemon().onPointerUp(0 /* pointerId */); Loading
services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintAuthenticationClient.java +2 −2 Original line number Diff line number Diff line Loading @@ -112,7 +112,7 @@ class FingerprintAuthenticationClient extends AuthenticationClient<IBiometricsFi resetFailedAttempts(getTargetUserId()); UdfpsHelper.hideUdfpsOverlay(getSensorId(), mUdfpsOverlayController); } else { mState = STATE_STARTED_PAUSED; mState = STATE_STARTED_PAUSED_ATTEMPTED; final @LockoutTracker.LockoutMode int lockoutMode = mLockoutFrameworkImpl.getLockoutModeForUser(getTargetUserId()); if (lockoutMode != LockoutTracker.LOCKOUT_NONE) { Loading Loading @@ -206,7 +206,7 @@ class FingerprintAuthenticationClient extends AuthenticationClient<IBiometricsFi @Override public void onPointerUp() { mIsPointerDown = false; mState = STATE_STARTED_PAUSED; mState = STATE_STARTED_PAUSED_ATTEMPTED; mALSProbeCallback.getProbe().disable(); UdfpsHelper.onFingerUp(getFreshDaemon()); Loading