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

Commit 68ab86bf authored by Kevin Chyn's avatar Kevin Chyn Committed by Automerger Merge Worker
Browse files

Merge "7/n: Add mechanism to hold onto already-completed operations" into sc-dev am: 63614e99

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/15337428

Change-Id: I8d71c02bc00db411a416452e14372cc722f55dfb
parents acb5d60b 63614e99
Loading
Loading
Loading
Loading
+4 −0
Original line number Original line Diff line number Diff line
@@ -3365,6 +3365,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
            pw.println("    trustManaged=" + getUserTrustIsManaged(userId));
            pw.println("    trustManaged=" + getUserTrustIsManaged(userId));
            pw.println("    udfpsEnrolled=" + isUdfpsEnrolled());
            pw.println("    udfpsEnrolled=" + isUdfpsEnrolled());
            pw.println("    mFingerprintLockedOut=" + mFingerprintLockedOut);
            pw.println("    mFingerprintLockedOut=" + mFingerprintLockedOut);
            pw.println("    mFingerprintLockedOutPermanent=" + mFingerprintLockedOutPermanent);
            pw.println("    enabledByUser=" + mBiometricEnabledForUser.get(userId));
            pw.println("    enabledByUser=" + mBiometricEnabledForUser.get(userId));
            if (isUdfpsEnrolled()) {
            if (isUdfpsEnrolled()) {
                pw.println("        shouldListenForUdfps=" + shouldListenForFingerprint(true));
                pw.println("        shouldListenForUdfps=" + shouldListenForFingerprint(true));
@@ -3386,8 +3387,11 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
                    + getStrongAuthTracker().hasUserAuthenticatedSinceBoot());
                    + getStrongAuthTracker().hasUserAuthenticatedSinceBoot());
            pw.println("    disabled(DPM)=" + isFaceDisabled(userId));
            pw.println("    disabled(DPM)=" + isFaceDisabled(userId));
            pw.println("    possible=" + isUnlockWithFacePossible(userId));
            pw.println("    possible=" + isUnlockWithFacePossible(userId));
            pw.println("    listening: actual=" + mFaceRunningState
                    + " expected=(" + (shouldListenForFace() ? 1 : 0));
            pw.println("    strongAuthFlags=" + Integer.toHexString(strongAuthFlags));
            pw.println("    strongAuthFlags=" + Integer.toHexString(strongAuthFlags));
            pw.println("    trustManaged=" + getUserTrustIsManaged(userId));
            pw.println("    trustManaged=" + getUserTrustIsManaged(userId));
            pw.println("    mFaceLockedOutPermanent=" + mFaceLockedOutPermanent);
            pw.println("    enabledByUser=" + mBiometricEnabledForUser.get(userId));
            pw.println("    enabledByUser=" + mBiometricEnabledForUser.get(userId));
            pw.println("    mSecureCameraLaunched=" + mSecureCameraLaunched);
            pw.println("    mSecureCameraLaunched=" + mSecureCameraLaunched);
        }
        }
+51 −2
Original line number Original line Diff line number Diff line
@@ -16,6 +16,7 @@


package com.android.server.biometrics.sensors;
package com.android.server.biometrics.sensors;


import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.Nullable;
import android.app.ActivityManager;
import android.app.ActivityManager;
@@ -30,6 +31,7 @@ import android.hardware.biometrics.BiometricManager;
import android.hardware.biometrics.BiometricsProtoEnums;
import android.hardware.biometrics.BiometricsProtoEnums;
import android.os.IBinder;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.RemoteException;
import android.os.SystemClock;
import android.security.KeyStore;
import android.security.KeyStore;
import android.util.EventLog;
import android.util.EventLog;
import android.util.Slog;
import android.util.Slog;
@@ -48,6 +50,18 @@ public abstract class AuthenticationClient<T> extends AcquisitionClient<T>


    private static final String TAG = "Biometrics/AuthenticationClient";
    private static final String TAG = "Biometrics/AuthenticationClient";


    // New, has not started yet
    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)
    public static final int STATE_STARTED_PAUSED = 2;
    // Done, errored, canceled, etc. HAL/framework are not running this sensor anymore.
    public static final int STATE_STOPPED = 3;

    @IntDef({STATE_NEW, STATE_STARTED, STATE_STARTED_PAUSED, STATE_STOPPED})
    @interface State {}

    private final boolean mIsStrongBiometric;
    private final boolean mIsStrongBiometric;
    private final boolean mRequireConfirmation;
    private final boolean mRequireConfirmation;
    private final ActivityTaskManager mActivityTaskManager;
    private final ActivityTaskManager mActivityTaskManager;
@@ -63,6 +77,20 @@ public abstract class AuthenticationClient<T> extends AcquisitionClient<T>


    protected boolean mAuthAttempted;
    protected boolean mAuthAttempted;


    // TODO: This is currently hard to maintain, as each AuthenticationClient subclass must update
    //  the state. We should think of a way to improve this in the future.
    protected @State int mState = STATE_NEW;

    /**
     * Handles lifecycle, e.g. {@link BiometricScheduler},
     * {@link com.android.server.biometrics.sensors.BaseClientMonitor.Callback} after authentication
     * results are known. Note that this happens asynchronously from (but shortly after)
     * {@link #onAuthenticated(BiometricAuthenticator.Identifier, boolean, ArrayList)} and allows
     * {@link CoexCoordinator} a chance to invoke/delay this event.
     * @param authenticated
     */
    protected abstract void handleLifecycleAfterAuth(boolean authenticated);

    public AuthenticationClient(@NonNull Context context, @NonNull LazyDaemon<T> lazyDaemon,
    public AuthenticationClient(@NonNull Context context, @NonNull LazyDaemon<T> lazyDaemon,
            @NonNull IBinder token, @NonNull ClientMonitorCallbackConverter listener,
            @NonNull IBinder token, @NonNull ClientMonitorCallbackConverter listener,
            int targetUserId, long operationId, boolean restricted, @NonNull String owner,
            int targetUserId, long operationId, boolean restricted, @NonNull String owner,
@@ -221,7 +249,8 @@ public abstract class AuthenticationClient<T> extends AcquisitionClient<T>
            }
            }


            final CoexCoordinator coordinator = CoexCoordinator.getInstance();
            final CoexCoordinator coordinator = CoexCoordinator.getInstance();
            coordinator.onAuthenticationSucceeded(this, new CoexCoordinator.Callback() {
            coordinator.onAuthenticationSucceeded(SystemClock.uptimeMillis(), this,
                    new CoexCoordinator.Callback() {
                @Override
                @Override
                public void sendAuthenticationResult(boolean addAuthTokenIfStrong) {
                public void sendAuthenticationResult(boolean addAuthTokenIfStrong) {
                    if (addAuthTokenIfStrong && mIsStrongBiometric) {
                    if (addAuthTokenIfStrong && mIsStrongBiometric) {
@@ -262,6 +291,11 @@ public abstract class AuthenticationClient<T> extends AcquisitionClient<T>
                        vibrateSuccess();
                        vibrateSuccess();
                    }
                    }
                }
                }

                @Override
                public void handleLifecycleAfterAuth() {
                    AuthenticationClient.this.handleLifecycleAfterAuth(true /* authenticated */);
                }
            });
            });
        } else {
        } else {
            // Allow system-defined limit of number of attempts before giving up
            // Allow system-defined limit of number of attempts before giving up
@@ -272,7 +306,7 @@ public abstract class AuthenticationClient<T> extends AcquisitionClient<T>
            }
            }


            final CoexCoordinator coordinator = CoexCoordinator.getInstance();
            final CoexCoordinator coordinator = CoexCoordinator.getInstance();
            coordinator.onAuthenticationRejected(this, lockoutMode,
            coordinator.onAuthenticationRejected(SystemClock.uptimeMillis(), this, lockoutMode,
                    new CoexCoordinator.Callback() {
                    new CoexCoordinator.Callback() {
                @Override
                @Override
                public void sendAuthenticationResult(boolean addAuthTokenIfStrong) {
                public void sendAuthenticationResult(boolean addAuthTokenIfStrong) {
@@ -291,6 +325,11 @@ public abstract class AuthenticationClient<T> extends AcquisitionClient<T>
                        vibrateError();
                        vibrateError();
                    }
                    }
                }
                }

                @Override
                public void handleLifecycleAfterAuth() {
                    AuthenticationClient.this.handleLifecycleAfterAuth(false /* authenticated */);
                }
            });
            });
        }
        }
    }
    }
@@ -307,6 +346,12 @@ public abstract class AuthenticationClient<T> extends AcquisitionClient<T>
        }
        }
    }
    }


    @Override
    public void onError(int errorCode, int vendorCode) {
        super.onError(errorCode, vendorCode);
        mState = STATE_STOPPED;
    }

    /**
    /**
     * Start authentication
     * Start authentication
     */
     */
@@ -345,6 +390,10 @@ public abstract class AuthenticationClient<T> extends AcquisitionClient<T>
        }
        }
    }
    }


    public @State int getState() {
        return mState;
    }

    @Override
    @Override
    public int getProtoEnum() {
    public int getProtoEnum() {
        return BiometricsProto.CM_AUTHENTICATE;
        return BiometricsProto.CM_AUTHENTICATE;
+0 −1
Original line number Original line Diff line number Diff line
@@ -355,7 +355,6 @@ public class BiometricScheduler {


    /**
    /**
     * Creates a new scheduler.
     * Creates a new scheduler.
     * @param context system_server context.
     * @param tag for the specific instance of the scheduler. Should be unique.
     * @param tag for the specific instance of the scheduler. Should be unique.
     * @param sensorType the sensorType that this scheduler is handling.
     * @param sensorType the sensorType that this scheduler is handling.
     * @param gestureAvailabilityDispatcher may be null if the sensor does not support gestures
     * @param gestureAvailabilityDispatcher may be null if the sensor does not support gestures
+182 −10
Original line number Original line Diff line number Diff line
@@ -22,12 +22,17 @@ import static com.android.server.biometrics.sensors.BiometricScheduler.sensorTyp


import android.annotation.NonNull;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.Nullable;
import android.os.Handler;
import android.os.Looper;
import android.util.Slog;
import android.util.Slog;


import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.annotations.VisibleForTesting;
import com.android.server.biometrics.sensors.BiometricScheduler.SensorType;
import com.android.server.biometrics.sensors.fingerprint.Udfps;
import com.android.server.biometrics.sensors.fingerprint.Udfps;


import java.util.HashMap;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;
import java.util.Map;


/**
/**
@@ -43,6 +48,9 @@ public class CoexCoordinator {
            "com.android.server.biometrics.sensors.CoexCoordinator.enable";
            "com.android.server.biometrics.sensors.CoexCoordinator.enable";
    private static final boolean DEBUG = true;
    private static final boolean DEBUG = true;


    // Successful authentications should be used within this amount of time.
    static final long SUCCESSFUL_AUTH_VALID_DURATION_MS = 5000;

    /**
    /**
     * Callback interface notifying the owner of "results" from the CoexCoordinator's business
     * Callback interface notifying the owner of "results" from the CoexCoordinator's business
     * logic.
     * logic.
@@ -58,10 +66,69 @@ public class CoexCoordinator {
         * Requests the owner to initiate a vibration for this event.
         * Requests the owner to initiate a vibration for this event.
         */
         */
        void sendHapticFeedback();
        void sendHapticFeedback();

        /**
         * Requests the owner to handle the AuthenticationClient's lifecycle (e.g. finish and remove
         * from scheduler if auth was successful).
         */
        void handleLifecycleAfterAuth();
    }
    }


    private static CoexCoordinator sInstance;
    private static CoexCoordinator sInstance;


    @VisibleForTesting
    public static class SuccessfulAuth {
        final long mAuthTimestamp;
        final @SensorType int mSensorType;
        final AuthenticationClient<?> mAuthenticationClient;
        final Callback mCallback;
        final CleanupRunnable mCleanupRunnable;

        public static class CleanupRunnable implements Runnable {
            @NonNull final LinkedList<SuccessfulAuth> mSuccessfulAuths;
            @NonNull final SuccessfulAuth mAuth;
            @NonNull final Callback mCallback;

            public CleanupRunnable(@NonNull LinkedList<SuccessfulAuth> successfulAuths,
                    @NonNull SuccessfulAuth auth, @NonNull Callback callback) {
                mSuccessfulAuths = successfulAuths;
                mAuth = auth;
                mCallback = callback;
            }

            @Override
            public void run() {
                final boolean removed = mSuccessfulAuths.remove(mAuth);
                Slog.w(TAG, "Removing stale successfulAuth: " + mAuth.toString()
                        + ", success: " + removed);
                mCallback.handleLifecycleAfterAuth();
            }
        }

        public SuccessfulAuth(@NonNull Handler handler,
                @NonNull LinkedList<SuccessfulAuth> successfulAuths,
                long currentTimeMillis,
                @SensorType int sensorType,
                @NonNull AuthenticationClient<?> authenticationClient,
                @NonNull Callback callback) {
            mAuthTimestamp = currentTimeMillis;
            mSensorType = sensorType;
            mAuthenticationClient = authenticationClient;
            mCallback = callback;

            mCleanupRunnable = new CleanupRunnable(successfulAuths, this, callback);

            handler.postDelayed(mCleanupRunnable, SUCCESSFUL_AUTH_VALID_DURATION_MS);
        }

        @Override
        public String toString() {
            return "SensorType: " + sensorTypeToString(mSensorType)
                    + ", mAuthTimestamp: " + mAuthTimestamp
                    + ", authenticationClient: " + mAuthenticationClient;
        }
    }

    /**
    /**
     * @return a singleton instance.
     * @return a singleton instance.
     */
     */
@@ -85,11 +152,15 @@ public class CoexCoordinator {


    // SensorType to AuthenticationClient map
    // SensorType to AuthenticationClient map
    private final Map<Integer, AuthenticationClient<?>> mClientMap;
    private final Map<Integer, AuthenticationClient<?>> mClientMap;
    @VisibleForTesting final LinkedList<SuccessfulAuth> mSuccessfulAuths;
    private boolean mAdvancedLogicEnabled;
    private boolean mAdvancedLogicEnabled;
    private final Handler mHandler;


    private CoexCoordinator() {
    private CoexCoordinator() {
        // Singleton
        // Singleton
        mClientMap = new HashMap<>();
        mClientMap = new HashMap<>();
        mSuccessfulAuths = new LinkedList<>();
        mHandler = new Handler(Looper.getMainLooper());
    }
    }


    public void addAuthenticationClient(@BiometricScheduler.SensorType int sensorType,
    public void addAuthenticationClient(@BiometricScheduler.SensorType int sensorType,
@@ -121,34 +192,43 @@ public class CoexCoordinator {
        mClientMap.remove(sensorType);
        mClientMap.remove(sensorType);
    }
    }


    public void onAuthenticationSucceeded(@NonNull AuthenticationClient<?> client,
    public void onAuthenticationSucceeded(long currentTimeMillis,
            @NonNull AuthenticationClient<?> client,
            @NonNull Callback callback) {
            @NonNull Callback callback) {
        if (client.isBiometricPrompt()) {
        if (client.isBiometricPrompt()) {
            callback.sendHapticFeedback();
            callback.sendHapticFeedback();
            // For BP, BiometricService will add the authToken to Keystore.
            // For BP, BiometricService will add the authToken to Keystore.
            callback.sendAuthenticationResult(false /* addAuthTokenIfStrong */);
            callback.sendAuthenticationResult(false /* addAuthTokenIfStrong */);
            callback.handleLifecycleAfterAuth();
        } else if (isUnknownClient(client)) {
        } else if (isUnknownClient(client)) {
            // Client doesn't exist in our map for some reason. Give the user feedback so the
            // Client doesn't exist in our map for some reason. Give the user feedback so the
            // device doesn't feel like it's stuck. All other cases below can assume that the
            // device doesn't feel like it's stuck. All other cases below can assume that the
            // client exists in our map.
            // client exists in our map.
            callback.sendHapticFeedback();
            callback.sendHapticFeedback();
            callback.sendAuthenticationResult(true /* addAuthTokenIfStrong */);
            callback.sendAuthenticationResult(true /* addAuthTokenIfStrong */);
            callback.handleLifecycleAfterAuth();
        } else if (mAdvancedLogicEnabled && client.isKeyguard()) {
        } else if (mAdvancedLogicEnabled && client.isKeyguard()) {
            if (isSingleAuthOnly(client)) {
            if (isSingleAuthOnly(client)) {
                // Single sensor authentication
                // Single sensor authentication
                callback.sendHapticFeedback();
                callback.sendHapticFeedback();
                callback.sendAuthenticationResult(true /* addAuthTokenIfStrong */);
                callback.sendAuthenticationResult(true /* addAuthTokenIfStrong */);
                callback.handleLifecycleAfterAuth();
            } else {
            } else {
                // Multi sensor authentication
                // Multi sensor authentication
                AuthenticationClient<?> udfps = mClientMap.getOrDefault(SENSOR_TYPE_UDFPS, null);
                AuthenticationClient<?> udfps = mClientMap.getOrDefault(SENSOR_TYPE_UDFPS, null);
                AuthenticationClient<?> face = mClientMap.getOrDefault(SENSOR_TYPE_FACE, null);
                AuthenticationClient<?> face = mClientMap.getOrDefault(SENSOR_TYPE_FACE, null);
                if (isCurrentFaceAuth(client)) {
                if (isCurrentFaceAuth(client)) {
                    if (isPointerDown(udfps)) {
                    if (isUdfpsActivelyAuthing(udfps)) {
                        // Face auth success while UDFPS pointer down. No callback, no haptic.
                        // Face auth success while UDFPS is actively authing. No callback, no haptic
                        // Feedback will be provided after UDFPS result.
                        // Feedback will be provided after UDFPS result:
                        // 1) UDFPS succeeds - simply remove this from the queue
                        // 2) UDFPS rejected - use this face auth success to notify clients
                        mSuccessfulAuths.add(new SuccessfulAuth(mHandler, mSuccessfulAuths,
                                currentTimeMillis, SENSOR_TYPE_FACE, client, callback));
                    } else {
                    } else {
                        callback.sendHapticFeedback();
                        callback.sendHapticFeedback();
                        callback.sendAuthenticationResult(true /* addAuthTokenIfStrong */);
                        callback.sendAuthenticationResult(true /* addAuthTokenIfStrong */);
                        callback.handleLifecycleAfterAuth();
                    }
                    }
                } else if (isCurrentUdfps(client)) {
                } else if (isCurrentUdfps(client)) {
                    if (isFaceScanning()) {
                    if (isFaceScanning()) {
@@ -156,8 +236,12 @@ public class CoexCoordinator {
                        // Cancel face auth and/or prevent it from invoking haptics/callbacks after
                        // Cancel face auth and/or prevent it from invoking haptics/callbacks after
                        face.cancel();
                        face.cancel();
                    }
                    }

                    removeAndFinishAllFaceFromQueue();

                    callback.sendHapticFeedback();
                    callback.sendHapticFeedback();
                    callback.sendAuthenticationResult(true /* addAuthTokenIfStrong */);
                    callback.sendAuthenticationResult(true /* addAuthTokenIfStrong */);
                    callback.handleLifecycleAfterAuth();
                }
                }
            }
            }
        } else {
        } else {
@@ -165,13 +249,68 @@ public class CoexCoordinator {
            // FingerprintManager for highlighting fingers
            // FingerprintManager for highlighting fingers
            callback.sendHapticFeedback();
            callback.sendHapticFeedback();
            callback.sendAuthenticationResult(true /* addAuthTokenIfStrong */);
            callback.sendAuthenticationResult(true /* addAuthTokenIfStrong */);
            callback.handleLifecycleAfterAuth();
        }
        }
    }
    }


    public void onAuthenticationRejected(@NonNull AuthenticationClient<?> client,
    public void onAuthenticationRejected(long currentTimeMillis,
            @NonNull AuthenticationClient<?> client,
            @LockoutTracker.LockoutMode int lockoutMode,
            @LockoutTracker.LockoutMode int lockoutMode,
            @NonNull Callback callback) {
            @NonNull Callback callback) {
        final boolean keyguardAdvancedLogic = mAdvancedLogicEnabled && client.isKeyguard();

        if (keyguardAdvancedLogic) {
            if (isSingleAuthOnly(client)) {
                callback.sendHapticFeedback();
                callback.handleLifecycleAfterAuth();
            } else {
                // Multi sensor authentication
                AuthenticationClient<?> udfps = mClientMap.getOrDefault(SENSOR_TYPE_UDFPS, null);
                AuthenticationClient<?> face = mClientMap.getOrDefault(SENSOR_TYPE_FACE, null);
                if (isCurrentFaceAuth(client)) {
                    // UDFPS should still be running in this case, do not vibrate. However, we
                    // should notify the callback and finish the client, so that Keyguard and
                    // BiometricScheduler do not get stuck.
                    Slog.d(TAG, "Face rejected in multi-sensor auth, udfps: " + udfps);
                    callback.handleLifecycleAfterAuth();
                } else if (isCurrentUdfps(client)) {
                    // Face should either be running, or have already finished
                    SuccessfulAuth auth = popSuccessfulFaceAuthIfExists(currentTimeMillis);
                    if (auth != null) {
                        Slog.d(TAG, "Using recent auth: " + auth);
                        callback.handleLifecycleAfterAuth();

                        auth.mCallback.sendHapticFeedback();
                        auth.mCallback.sendAuthenticationResult(true /* addAuthTokenIfStrong */);
                        auth.mCallback.handleLifecycleAfterAuth();
                    } else if (isFaceScanning()) {
                        // UDFPS rejected but face is still scanning
                        Slog.d(TAG, "UDFPS rejected in multi-sensor auth, face: " + face);
                        callback.handleLifecycleAfterAuth();

                        // TODO(b/193089985): Enforce/ensure that face auth finishes (whether
                        //  accept/reject) within X amount of time. Otherwise users will be stuck
                        //  waiting with their finger down for a long time.
                    } else {
                        // Face not scanning, and was not found in the queue. Most likely, face
                        // auth was too long ago.
                        Slog.d(TAG, "UDFPS rejected in multi-sensor auth, face not scanning");
                        callback.sendHapticFeedback();
                        callback.handleLifecycleAfterAuth();
                    }
                } else {
                    Slog.d(TAG, "Unknown client rejected: " + client);
                    callback.sendHapticFeedback();
                    callback.sendHapticFeedback();
                    callback.handleLifecycleAfterAuth();
                }
            }
        } else {
            callback.sendHapticFeedback();
            callback.handleLifecycleAfterAuth();
        }

        // Always notify keyguard, otherwise the cached "running" state in KeyguardUpdateMonitor
        // will get stuck.
        if (lockoutMode == LockoutTracker.LOCKOUT_NONE) {
        if (lockoutMode == LockoutTracker.LOCKOUT_NONE) {
            // Don't send onAuthenticationFailed if we're in lockout, it causes a
            // Don't send onAuthenticationFailed if we're in lockout, it causes a
            // janky UI on Keyguard/BiometricPrompt since "authentication failed"
            // janky UI on Keyguard/BiometricPrompt since "authentication failed"
@@ -180,6 +319,30 @@ public class CoexCoordinator {
        }
        }
    }
    }


    @Nullable
    private SuccessfulAuth popSuccessfulFaceAuthIfExists(long currentTimeMillis) {
        for (SuccessfulAuth auth : mSuccessfulAuths) {
            if (currentTimeMillis - auth.mAuthTimestamp >= SUCCESSFUL_AUTH_VALID_DURATION_MS) {
                Slog.d(TAG, "Removing stale auth: " + auth);
                mSuccessfulAuths.remove(auth);
            } else if (auth.mSensorType == SENSOR_TYPE_FACE) {
                mSuccessfulAuths.remove(auth);
                return auth;
            }
        }
        return null;
    }

    private void removeAndFinishAllFaceFromQueue() {
        for (SuccessfulAuth auth : mSuccessfulAuths) {
            if (auth.mSensorType == SENSOR_TYPE_FACE) {
                Slog.d(TAG, "Removing from queue and finishing: " + auth);
                auth.mCallback.handleLifecycleAfterAuth();
                mSuccessfulAuths.remove(auth);
            }
        }
    }

    private boolean isCurrentFaceAuth(@NonNull AuthenticationClient<?> client) {
    private boolean isCurrentFaceAuth(@NonNull AuthenticationClient<?> client) {
        return client == mClientMap.getOrDefault(SENSOR_TYPE_FACE, null);
        return client == mClientMap.getOrDefault(SENSOR_TYPE_FACE, null);
    }
    }
@@ -189,12 +352,13 @@ public class CoexCoordinator {
    }
    }


    private boolean isFaceScanning() {
    private boolean isFaceScanning() {
        return mClientMap.containsKey(SENSOR_TYPE_FACE);
        AuthenticationClient<?> client = mClientMap.getOrDefault(SENSOR_TYPE_FACE, null);
        return client != null && client.getState() == AuthenticationClient.STATE_STARTED;
    }
    }


    private static boolean isPointerDown(@Nullable AuthenticationClient<?> client) {
    private static boolean isUdfpsActivelyAuthing(@Nullable AuthenticationClient<?> client) {
        if (client instanceof Udfps) {
        if (client instanceof Udfps) {
            return ((Udfps) client).isPointerDown();
            return client.getState() == AuthenticationClient.STATE_STARTED;
        }
        }
        return false;
        return false;
    }
    }
@@ -221,7 +385,15 @@ public class CoexCoordinator {
        return true;
        return true;
    }
    }


    @Override
    public String toString() {
    public String toString() {
        return "Enabled: " + mAdvancedLogicEnabled;
        StringBuilder sb = new StringBuilder();
        sb.append("Enabled: ").append(mAdvancedLogicEnabled);
        sb.append(", Queue size: " ).append(mSuccessfulAuths.size());
        for (SuccessfulAuth auth : mSuccessfulAuths) {
            sb.append(", Auth: ").append(auth.toString());
        }

        return sb.toString();
    }
    }
}
}
+16 −6
Original line number Original line Diff line number Diff line
@@ -89,6 +89,12 @@ class FaceAuthenticationClient extends AuthenticationClient<ISession> implements
                R.array.config_face_acquire_vendor_keyguard_ignorelist);
                R.array.config_face_acquire_vendor_keyguard_ignorelist);
    }
    }


    @Override
    public void start(@NonNull Callback callback) {
        super.start(callback);
        mState = STATE_STARTED;
    }

    @NonNull
    @NonNull
    @Override
    @Override
    protected Callback wrapCallbackForStart(@NonNull Callback callback) {
    protected Callback wrapCallbackForStart(@NonNull Callback callback) {
@@ -127,11 +133,21 @@ class FaceAuthenticationClient extends AuthenticationClient<ISession> implements
                && mLastAcquire != FaceManager.FACE_ACQUIRED_UNKNOWN;
                && mLastAcquire != FaceManager.FACE_ACQUIRED_UNKNOWN;
    }
    }


    @Override
    protected void handleLifecycleAfterAuth(boolean authenticated) {
        // For face, the authentication lifecycle ends either when
        // 1) Authenticated == true
        // 2) Error occurred
        // 3) Authenticated == false
        mCallback.onClientFinished(this, true /* success */);
    }

    @Override
    @Override
    public void onAuthenticated(BiometricAuthenticator.Identifier identifier,
    public void onAuthenticated(BiometricAuthenticator.Identifier identifier,
            boolean authenticated, ArrayList<Byte> token) {
            boolean authenticated, ArrayList<Byte> token) {
        super.onAuthenticated(identifier, authenticated, token);
        super.onAuthenticated(identifier, authenticated, token);


        mState = STATE_STOPPED;
        mUsageStats.addEvent(new UsageStats.AuthenticationEvent(
        mUsageStats.addEvent(new UsageStats.AuthenticationEvent(
                getStartTimeMs(),
                getStartTimeMs(),
                System.currentTimeMillis() - getStartTimeMs() /* latency */,
                System.currentTimeMillis() - getStartTimeMs() /* latency */,
@@ -139,12 +155,6 @@ class FaceAuthenticationClient extends AuthenticationClient<ISession> implements
                0 /* error */,
                0 /* error */,
                0 /* vendorError */,
                0 /* vendorError */,
                getTargetUserId()));
                getTargetUserId()));

        // For face, the authentication lifecycle ends either when
        // 1) Authenticated == true
        // 2) Error occurred
        // 3) Authenticated == false
        mCallback.onClientFinished(this, true /* success */);
    }
    }


    @Override
    @Override
Loading