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

Commit c4815d0f authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "4/n: Make CoexCoordinator multi-sensor-aware" into sc-dev

parents c4adbc27 164f70d4
Loading
Loading
Loading
Loading
+77 −6
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@ import android.annotation.Nullable;
import android.content.Context;
import android.hardware.biometrics.BiometricConstants;
import android.hardware.biometrics.IBiometricService;
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
@@ -48,8 +49,11 @@ import java.util.Locale;

/**
 * A scheduler for biometric HAL operations. Maintains a queue of {@link BaseClientMonitor}
 * operations, without caring about its implementation details. Operations may perform one or more
 * operations, without caring about its implementation details. Operations may perform zero or more
 * interactions with the HAL before finishing.
 *
 * We currently assume (and require) that each biometric sensor have its own instance of a
 * {@link BiometricScheduler}. See {@link CoexCoordinator}.
 */
public class BiometricScheduler {

@@ -57,6 +61,55 @@ public class BiometricScheduler {
    // Number of recent operations to keep in our logs for dumpsys
    protected static final int LOG_NUM_RECENT_OPERATIONS = 50;

    /**
     * Unknown sensor type. This should never be used, and is a sign that something is wrong during
     * initialization.
     */
    public static final int SENSOR_TYPE_UNKNOWN = 0;

    /**
     * Face authentication.
     */
    public static final int SENSOR_TYPE_FACE = 1;

    /**
     * Any UDFPS type. See {@link FingerprintSensorPropertiesInternal#isAnyUdfpsType()}.
     */
    public static final int SENSOR_TYPE_UDFPS = 2;

    /**
     * Any other fingerprint sensor. We can add additional definitions in the future when necessary.
     */
    public static final int SENSOR_TYPE_FP_OTHER = 3;

    @IntDef({SENSOR_TYPE_UNKNOWN, SENSOR_TYPE_FACE, SENSOR_TYPE_UDFPS, SENSOR_TYPE_FP_OTHER})
    @Retention(RetentionPolicy.SOURCE)
    public @interface SensorType {}

    public static @SensorType int sensorTypeFromFingerprintProperties(
            @NonNull FingerprintSensorPropertiesInternal props) {
        if (props.isAnyUdfpsType()) {
            return SENSOR_TYPE_UDFPS;
        }

        return SENSOR_TYPE_FP_OTHER;
    }

    public static String sensorTypeToString(@SensorType int sensorType) {
        switch (sensorType) {
            case SENSOR_TYPE_UNKNOWN:
                return "Unknown";
            case SENSOR_TYPE_FACE:
                return "Face";
            case SENSOR_TYPE_UDFPS:
                return "Udfps";
            case SENSOR_TYPE_FP_OTHER:
                return "OtherFp";
            default:
                return "UnknownUnknown";
        }
    }

    /**
     * Contains all the necessary information for a HAL operation.
     */
@@ -207,6 +260,7 @@ public class BiometricScheduler {
    }

    @NonNull protected final String mBiometricTag;
    private final @SensorType int mSensorType;
    @Nullable private final GestureAvailabilityDispatcher mGestureAvailabilityDispatcher;
    @NonNull private final IBiometricService mBiometricService;
    @NonNull protected final Handler mHandler = new Handler(Looper.getMainLooper());
@@ -218,6 +272,7 @@ public class BiometricScheduler {
    private int mTotalOperationsHandled;
    private final int mRecentOperationsLimit;
    @NonNull private final List<Integer> mRecentOperations;
    @NonNull private final CoexCoordinator mCoexCoordinator;

    // Internal callback, notified when an operation is complete. Notifies the requester
    // that the operation is complete, before performing internal scheduler work (such as
@@ -226,6 +281,12 @@ public class BiometricScheduler {
        @Override
        public void onClientStarted(@NonNull BaseClientMonitor clientMonitor) {
            Slog.d(getTag(), "[Started] " + clientMonitor);

            if (clientMonitor instanceof AuthenticationClient) {
                mCoexCoordinator.addAuthenticationClient(mSensorType,
                        (AuthenticationClient<?>) clientMonitor);
            }

            if (mCurrentOperation.mClientCallback != null) {
                mCurrentOperation.mClientCallback.onClientStarted(clientMonitor);
            }
@@ -248,6 +309,11 @@ public class BiometricScheduler {
                }

                Slog.d(getTag(), "[Finishing] " + clientMonitor + ", success: " + success);
                if (clientMonitor instanceof AuthenticationClient) {
                    mCoexCoordinator.removeAuthenticationClient(mSensorType,
                            (AuthenticationClient<?>) clientMonitor);
                }

                mCurrentOperation.mState = Operation.STATE_FINISHED;

                if (mCurrentOperation.mClientCallback != null) {
@@ -271,10 +337,12 @@ public class BiometricScheduler {
    }

    @VisibleForTesting
    BiometricScheduler(@NonNull String tag,
    BiometricScheduler(@NonNull String tag, @SensorType int sensorType,
            @Nullable GestureAvailabilityDispatcher gestureAvailabilityDispatcher,
            @NonNull IBiometricService biometricService, int recentOperationsLimit) {
            @NonNull IBiometricService biometricService, int recentOperationsLimit,
            @NonNull CoexCoordinator coexCoordinator) {
        mBiometricTag = tag;
        mSensorType = sensorType;
        mInternalCallback = new InternalCallback();
        mGestureAvailabilityDispatcher = gestureAvailabilityDispatcher;
        mPendingOperations = new ArrayDeque<>();
@@ -282,6 +350,7 @@ public class BiometricScheduler {
        mCrashStates = new ArrayDeque<>();
        mRecentOperationsLimit = recentOperationsLimit;
        mRecentOperations = new ArrayList<>();
        mCoexCoordinator = coexCoordinator;
    }

    /**
@@ -290,10 +359,11 @@ public class BiometricScheduler {
     * @param gestureAvailabilityDispatcher may be null if the sensor does not support gestures
     *                                      (such as fingerprint swipe).
     */
    public BiometricScheduler(@NonNull String tag,
    public BiometricScheduler(@NonNull String tag, @SensorType int sensorType,
            @Nullable GestureAvailabilityDispatcher gestureAvailabilityDispatcher) {
        this(tag, gestureAvailabilityDispatcher, IBiometricService.Stub.asInterface(
                ServiceManager.getService(Context.BIOMETRIC_SERVICE)), LOG_NUM_RECENT_OPERATIONS);
        this(tag, sensorType, gestureAvailabilityDispatcher, IBiometricService.Stub.asInterface(
                ServiceManager.getService(Context.BIOMETRIC_SERVICE)), LOG_NUM_RECENT_OPERATIONS,
                CoexCoordinator.getInstance());
    }

    /**
@@ -645,6 +715,7 @@ public class BiometricScheduler {

    public void dump(PrintWriter pw) {
        pw.println("Dump of BiometricScheduler " + getTag());
        pw.println("Type: " + mSensorType);
        pw.println("Current operation: " + mCurrentOperation);
        pw.println("Pending operations: " + mPendingOperations.size());
        for (Operation operation : mPendingOperations) {
+44 −4
Original line number Diff line number Diff line
@@ -16,7 +16,13 @@

package com.android.server.biometrics.sensors;

import static com.android.server.biometrics.sensors.BiometricScheduler.sensorTypeToString;

import android.annotation.NonNull;
import android.util.Slog;

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

/**
 * Singleton that contains the core logic for determining if haptics and authentication callbacks
@@ -27,6 +33,7 @@ import android.annotation.NonNull;
public class CoexCoordinator {

    private static final String TAG = "BiometricCoexCoordinator";
    private static final boolean DEBUG = true;

    /**
     * Callback interface notifying the owner of "results" from the CoexCoordinator's business
@@ -47,10 +54,6 @@ public class CoexCoordinator {

    private static CoexCoordinator sInstance;

    private CoexCoordinator() {
        // Singleton
    }

    @NonNull
    static CoexCoordinator getInstance() {
        if (sInstance == null) {
@@ -59,6 +62,43 @@ public class CoexCoordinator {
        return sInstance;
    }

    // SensorType to AuthenticationClient map
    private final Map<Integer, AuthenticationClient<?>> mClientMap;

    private CoexCoordinator() {
        // Singleton
        mClientMap = new HashMap<>();
    }

    public void addAuthenticationClient(@BiometricScheduler.SensorType int sensorType,
            @NonNull AuthenticationClient<?> client) {
        if (DEBUG) {
            Slog.d(TAG, "addAuthenticationClient(" + sensorTypeToString(sensorType) + ")"
                    + ", client: " + client);
        }

        if (mClientMap.containsKey(sensorType)) {
            Slog.w(TAG, "Overwriting existing client: " + mClientMap.get(sensorType)
                    + " with new client: " + client);
        }

        mClientMap.put(sensorType, client);
    }

    public void removeAuthenticationClient(@BiometricScheduler.SensorType int sensorType,
            @NonNull AuthenticationClient<?> client) {
        if (DEBUG) {
            Slog.d(TAG, "removeAuthenticationClient(" + sensorTypeToString(sensorType) + ")"
                    + ", client: " + client);
        }

        if (!mClientMap.containsKey(sensorType)) {
            Slog.e(TAG, "sensorType: " + sensorType + " does not exist in map. Client: " + client);
            return;
        }
        mClientMap.remove(sensorType);
    }

    public void onAuthenticationSucceeded(@NonNull AuthenticationClient<?> client,
            @NonNull Callback callback) {
        if (client.isBiometricPrompt()) {
+8 −6
Original line number Diff line number Diff line
@@ -83,24 +83,26 @@ public class UserAwareBiometricScheduler extends BiometricScheduler {
    }

    @VisibleForTesting
    UserAwareBiometricScheduler(@NonNull String tag,
    UserAwareBiometricScheduler(@NonNull String tag, @SensorType int sensorType,
            @Nullable GestureAvailabilityDispatcher gestureAvailabilityDispatcher,
            @NonNull IBiometricService biometricService,
            @NonNull CurrentUserRetriever currentUserRetriever,
            @NonNull UserSwitchCallback userSwitchCallback) {
        super(tag, gestureAvailabilityDispatcher, biometricService, LOG_NUM_RECENT_OPERATIONS);
            @NonNull UserSwitchCallback userSwitchCallback,
            @NonNull CoexCoordinator coexCoordinator) {
        super(tag, sensorType, gestureAvailabilityDispatcher, biometricService,
                LOG_NUM_RECENT_OPERATIONS, coexCoordinator);

        mCurrentUserRetriever = currentUserRetriever;
        mUserSwitchCallback = userSwitchCallback;
    }

    public UserAwareBiometricScheduler(@NonNull String tag,
    public UserAwareBiometricScheduler(@NonNull String tag, @SensorType int sensorType,
            @Nullable GestureAvailabilityDispatcher gestureAvailabilityDispatcher,
            @NonNull CurrentUserRetriever currentUserRetriever,
            @NonNull UserSwitchCallback userSwitchCallback) {
        this(tag, gestureAvailabilityDispatcher, IBiometricService.Stub.asInterface(
        this(tag, sensorType, gestureAvailabilityDispatcher, IBiometricService.Stub.asInterface(
                ServiceManager.getService(Context.BIOMETRIC_SERVICE)), currentUserRetriever,
                userSwitchCallback);
                userSwitchCallback, CoexCoordinator.getInstance());
    }

    @Override
+2 −1
Original line number Diff line number Diff line
@@ -494,7 +494,8 @@ public class Sensor {
        mToken = new Binder();
        mHandler = handler;
        mSensorProperties = sensorProperties;
        mScheduler = new UserAwareBiometricScheduler(tag, null /* gestureAvailabilityDispatcher */,
        mScheduler = new UserAwareBiometricScheduler(tag, BiometricScheduler.SENSOR_TYPE_FACE,
                null /* gestureAvailabilityDispatcher */,
                () -> mCurrentSession != null ? mCurrentSession.mUserId : UserHandle.USER_NULL,
                new UserAwareBiometricScheduler.UserSwitchCallback() {
                    @NonNull
+2 −1
Original line number Diff line number Diff line
@@ -355,7 +355,8 @@ public class Face10 implements IHwBinder.DeathRecipient, ServiceProvider {
    public Face10(@NonNull Context context, @NonNull FaceSensorPropertiesInternal sensorProps,
            @NonNull LockoutResetDispatcher lockoutResetDispatcher) {
        this(context, sensorProps, lockoutResetDispatcher,
                new BiometricScheduler(TAG, null /* gestureAvailabilityTracker */));
                new BiometricScheduler(TAG, BiometricScheduler.SENSOR_TYPE_FACE,
                        null /* gestureAvailabilityTracker */));
    }

    @Override
Loading