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

Commit 7599d256 authored by Kevin Chyn's avatar Kevin Chyn
Browse files

2/n: Clean up ClientMonitor

This is the first step in moving ClientMonitors and their
implementations entirely to their own files.

Remove as many abstract methods in ClientMonitor and its subclass as
possible. These classes should be decoupled from their owners as much
as possible. This should make it much easier to support future extensions.

Bug: 157790417
Test: Enroll/Auth on fingerprint/face devices

TODO: Test more thoroughly

Change-Id: Idfa421ccad93e1940068f35eb74a1b4932f44de6
parent 77f92351
Loading
Loading
Loading
Loading
+43 −20
Original line number Diff line number Diff line
@@ -16,12 +16,16 @@

package com.android.server.biometrics.sensors;

import android.app.IActivityTaskManager;
import android.app.TaskStackListener;
import android.content.Context;
import android.hardware.biometrics.BiometricAuthenticator;
import android.hardware.biometrics.BiometricConstants;
import android.hardware.biometrics.BiometricsProtoEnums;
import android.os.IBinder;
import android.os.PowerManager;
import android.os.RemoteException;
import android.os.SystemClock;
import android.security.KeyStore;
import android.util.Slog;
import android.view.Surface;
@@ -32,7 +36,6 @@ import java.util.ArrayList;
 * A class to keep track of the authentication state for a given client.
 */
public abstract class AuthenticationClient extends ClientMonitor {
    private long mOpId;

    public abstract int handleFailedAttempt();
    public void resetFailedAttempts() {}
@@ -42,7 +45,12 @@ public abstract class AuthenticationClient extends ClientMonitor {
    public static final int LOCKOUT_PERMANENT = 2;

    private final boolean mIsStrongBiometric;
    private final long mOpId;
    private final boolean mShouldFrameworkHandleLockout;
    private final boolean mRequireConfirmation;
    private final IActivityTaskManager mActivityTaskManager;
    private final TaskStackListener mTaskStackListener;
    private final PowerManager mPowerManager;
    private final Surface mSurface;

    // We need to track this state since it's possible for applications to request for
@@ -54,31 +62,45 @@ public abstract class AuthenticationClient extends ClientMonitor {
    /**
     * This method is called when authentication starts.
     */
    public abstract void onStart();
    private void onStart() {
        try {
            mActivityTaskManager.registerTaskStackListener(mTaskStackListener);
        } catch (RemoteException e) {
            Slog.e(getLogTag(), "Could not register task stack listener", e);
        }
    }

    /**
     * This method is called when a biometric is authenticated or authentication is stopped
     * (cancelled by the user, or an error such as lockout has occurred).
     */
    public abstract void onStop();

    /**
     * @return true if the framework should handle lockout.
     */
    public abstract boolean shouldFrameworkHandleLockout();
    private void onStop() {
        try {
            mActivityTaskManager.unregisterTaskStackListener(mTaskStackListener);
        } catch (RemoteException e) {
            Slog.e(getLogTag(), "Could not unregister task stack listener", e);
        }
    }

    public abstract boolean wasUserDetected();

    public AuthenticationClient(Context context, Constants constants,
            BiometricServiceBase.DaemonWrapper daemon, IBinder token,
            ClientMonitorCallbackConverter listener, int targetUserId, int groupId, long opId,
            boolean restricted, String owner, int cookie, boolean requireConfirmation,
            Surface surface, int sensorId, boolean isStrongBiometric) {
            boolean shouldFrameworkHandleLockout, boolean restricted, String owner, int cookie,
            boolean requireConfirmation, int sensorId, boolean isStrongBiometric, int statsModality,
            int statsClient, IActivityTaskManager activityTaskManager,
            TaskStackListener taskStackListener, PowerManager powerManager, Surface surface) {
        super(context, constants, daemon, token, listener, targetUserId, groupId,
                restricted, owner, cookie, sensorId);
        mOpId = opId;
                restricted, owner, cookie, sensorId, statsModality,
                BiometricsProtoEnums.ACTION_AUTHENTICATE, statsClient);
        mIsStrongBiometric = isStrongBiometric;
        mOpId = opId;
        mShouldFrameworkHandleLockout = shouldFrameworkHandleLockout;
        mRequireConfirmation = requireConfirmation;
        mActivityTaskManager = activityTaskManager;
        mTaskStackListener = taskStackListener;
        mPowerManager = powerManager;
        mSurface = surface;
    }

@@ -87,14 +109,15 @@ public abstract class AuthenticationClient extends ClientMonitor {
    }

    @Override
    public void binderDied() {
        final boolean clearListener = !isBiometricPrompt();
        binderDiedInternal(clearListener);
    public void notifyUserActivity() {
        long now = SystemClock.uptimeMillis();
        mPowerManager.userActivity(now, PowerManager.USER_ACTIVITY_EVENT_TOUCH, 0);
    }

    @Override
    protected int statsAction() {
        return BiometricsProtoEnums.ACTION_AUTHENTICATE;
    public void binderDied() {
        final boolean clearListener = !isBiometricPrompt();
        binderDiedInternal(clearListener);
    }

    public boolean isBiometricPrompt() {
@@ -108,7 +131,7 @@ public abstract class AuthenticationClient extends ClientMonitor {

    @Override
    public boolean onError(int error, int vendorCode) {
        if (!shouldFrameworkHandleLockout()) {
        if (!mShouldFrameworkHandleLockout) {
            switch (error) {
                case BiometricConstants.BIOMETRIC_ERROR_TIMEOUT:
                    if (!wasUserDetected() && !isBiometricPrompt()) {
@@ -155,7 +178,7 @@ public abstract class AuthenticationClient extends ClientMonitor {
                    vibrateSuccess();
                }
                result = true;
                if (shouldFrameworkHandleLockout()) {
                if (mShouldFrameworkHandleLockout) {
                    resetFailedAttempts();
                }
                onStop();
@@ -200,7 +223,7 @@ public abstract class AuthenticationClient extends ClientMonitor {

                // Allow system-defined limit of number of attempts before giving up
                final int lockoutMode = handleFailedAttempt();
                if (lockoutMode != LOCKOUT_NONE && shouldFrameworkHandleLockout()) {
                if (lockoutMode != LOCKOUT_NONE && mShouldFrameworkHandleLockout) {
                    Slog.w(getLogTag(), "Forcing lockout (driver code should do this!), mode("
                            + lockoutMode + ")");
                    stop(false);
+14 −99
Original line number Diff line number Diff line
@@ -48,7 +48,6 @@ import android.os.PowerManager;
import android.os.Process;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemClock;
import android.os.UserHandle;
import android.os.UserManager;
import android.util.Slog;
@@ -87,7 +86,7 @@ public abstract class BiometricServiceBase extends SystemService
    private final Context mContext;
    private final String mKeyguardPackage;
    private final IActivityTaskManager mActivityTaskManager;
    private final PowerManager mPowerManager;
    public final PowerManager mPowerManager;
    private final UserManager mUserManager;
    private final MetricsLogger mMetricsLogger;
    private final BiometricTaskStackListener mTaskStackListener = new BiometricTaskStackListener();
@@ -227,56 +226,16 @@ public abstract class BiometricServiceBase extends SystemService

    protected abstract class AuthenticationClientImpl extends AuthenticationClient {

        // Used to check if the public API that was invoked was from FingerprintManager. Only
        // to be overridden by FingerprintService.
        protected boolean isFingerprint() {
            return false;
        }

        public AuthenticationClientImpl(Context context, DaemonWrapper daemon,
                IBinder token, ClientMonitorCallbackConverter listener, int targetUserId,
                int groupId, long opId, boolean restricted, String owner, int cookie,
                boolean requireConfirmation, Surface surface, int sensorId,
                boolean isStrongBiometric) {
                int groupId, long opId, boolean shouldFrameworkHandleLockout, boolean restricted,
                String owner, int cookie, boolean requireConfirmation, int sensorId,
                boolean isStrongBiometric, int statsModality, int statsClient, Surface surface) {
            super(context, getConstants(), daemon, token, listener, targetUserId,
                    groupId, opId, restricted, owner, cookie, requireConfirmation, surface,
                    sensorId, isStrongBiometric);
        }

        @Override
        protected int statsClient() {
            if (isKeyguard(getOwnerString())) {
                return BiometricsProtoEnums.CLIENT_KEYGUARD;
            } else if (isBiometricPrompt()) {
                return BiometricsProtoEnums.CLIENT_BIOMETRIC_PROMPT;
            } else if (isFingerprint()) {
                return BiometricsProtoEnums.CLIENT_FINGERPRINT_MANAGER;
            } else {
                return BiometricsProtoEnums.CLIENT_UNKNOWN;
            }
        }

        @Override
        public void onStart() {
            try {
                mActivityTaskManager.registerTaskStackListener(mTaskStackListener);
            } catch (RemoteException e) {
                Slog.e(getTag(), "Could not register task stack listener", e);
            }
        }

        @Override
        public void onStop() {
            try {
                mActivityTaskManager.unregisterTaskStackListener(mTaskStackListener);
            } catch (RemoteException e) {
                Slog.e(getTag(), "Could not unregister task stack listener", e);
            }
        }

        @Override
        public void notifyUserActivity() {
            userActivity();
                    groupId, opId, shouldFrameworkHandleLockout, restricted, owner, cookie,
                    requireConfirmation, sensorId, isStrongBiometric,
                    statsModality, statsClient, mActivityTaskManager, mTaskStackListener,
                    mPowerManager, surface);
        }

        @Override
@@ -296,41 +255,6 @@ public abstract class BiometricServiceBase extends SystemService
        }
    }

    protected abstract class EnrollClientImpl extends EnrollClient {

        public EnrollClientImpl(Context context, DaemonWrapper daemon,
                IBinder token, ClientMonitorCallbackConverter listener, int userId, int groupId,
                byte[] cryptoToken, boolean restricted, String owner,
                final int[] disabledFeatures, int timeoutSec, Surface surface, int sensorId) {
            super(context, getConstants(), daemon, token, listener,
                    userId, groupId, cryptoToken, restricted, owner, getBiometricUtils(),
                    disabledFeatures, timeoutSec, surface, sensorId);
        }

        @Override
        public void notifyUserActivity() {
            userActivity();
        }
    }

    /**
     * An internal class to help clean up unknown templates in HAL and Framework
     */
    private final class InternalRemovalClient extends RemovalClient {
        InternalRemovalClient(Context context,
                DaemonWrapper daemon, IBinder token,
                ClientMonitorCallbackConverter listener, int templateId, int groupId, int userId,
                boolean restricted, String owner, int sensorId) {
            super(context, getConstants(), daemon, token, listener, templateId, groupId,
                    userId, restricted, owner, getBiometricUtils(), sensorId);
        }

        @Override
        protected int statsModality() {
            return BiometricServiceBase.this.statsModality();
        }
    }

    /**
     * Internal class to help clean up unknown templates in the HAL and Framework
     */
@@ -350,7 +274,7 @@ public abstract class BiometricServiceBase extends SystemService
                List<? extends BiometricAuthenticator.Identifier> enrolledList,
                BiometricUtils utils, int sensorId) {
            super(context, getConstants(), daemon, token, listener, groupId, userId,
                    restricted, owner, sensorId);
                    restricted, owner, sensorId, statsModality());
            mEnrolledList = enrolledList;
            mUtils = utils;
        }
@@ -410,11 +334,6 @@ public abstract class BiometricServiceBase extends SystemService
            }
            return remaining == 0;
        }

        @Override
        protected int statsModality() {
            return BiometricServiceBase.this.statsModality();
        }
    }

    /**
@@ -774,7 +693,7 @@ public abstract class BiometricServiceBase extends SystemService
     * Calls from the Manager. These are still on the calling binder's thread.
     */

    protected void enrollInternal(EnrollClientImpl client, int userId) {
    protected void enrollInternal(EnrollClient client, int userId) {
        if (hasReachedEnrollmentLimit(userId)) {
            return;
        }
@@ -978,7 +897,7 @@ public abstract class BiometricServiceBase extends SystemService
    /**
     * @return true if this is keyguard package
     */
    private boolean isKeyguard(String clientPackage) {
    public boolean isKeyguard(String clientPackage) {
        return mKeyguardPackage.equals(clientPackage);
    }

@@ -1217,9 +1136,10 @@ public abstract class BiometricServiceBase extends SystemService
            mUnknownHALTemplates.remove(template);
            boolean restricted = !hasPermission(getManageBiometricPermission());
            InternalRemovalClient client = new InternalRemovalClient(getContext(),
                    getDaemonWrapper(), mToken, null /* listener */,
                    getConstants(), getDaemonWrapper(), mToken, null /* listener */,
                    template.mIdentifier.getBiometricId(), 0 /* groupId */, template.mUserId,
                    restricted, getContext().getPackageName(), getSensorId());
                    restricted, getContext().getPackageName(), getBiometricUtils(),
                    getSensorId(), statsModality());
            removeInternal(client);
            FrameworkStatsLog.write(FrameworkStatsLog.BIOMETRIC_SYSTEM_HEALTH_ISSUE_DETECTED,
                    statsModality(),
@@ -1267,11 +1187,6 @@ public abstract class BiometricServiceBase extends SystemService
        }
    }

    private void userActivity() {
        long now = SystemClock.uptimeMillis();
        mPowerManager.userActivity(now, PowerManager.USER_ACTIVITY_EVENT_TOUCH, 0);
    }

    /**
     * @param userId
     * @return true if this is a work profile
+3 −1
Original line number Diff line number Diff line
@@ -82,7 +82,9 @@ public abstract class ClientMonitor extends LoggableMonitor implements IBinder.D
    public ClientMonitor(Context context, Constants constants,
            BiometricServiceBase.DaemonWrapper daemon, IBinder token,
            ClientMonitorCallbackConverter listener, int userId, int groupId,
            boolean restricted, String owner, int cookie, int sensorId) {
            boolean restricted, String owner, int cookie, int sensorId, int statsModality,
            int statsAction, int statsClient) {
        super(statsModality, statsAction, statsClient);
        mContext = context;
        mConstants = constants;
        mDaemon = daemon;
+18 −11
Original line number Diff line number Diff line
@@ -21,7 +21,9 @@ import android.hardware.biometrics.BiometricAuthenticator;
import android.hardware.biometrics.BiometricConstants;
import android.hardware.biometrics.BiometricsProtoEnums;
import android.os.IBinder;
import android.os.PowerManager;
import android.os.RemoteException;
import android.os.SystemClock;
import android.util.Slog;
import android.view.Surface;

@@ -31,34 +33,33 @@ import java.util.Arrays;
/**
 * A class to keep track of the enrollment state for a given client.
 */
public abstract class EnrollClient extends ClientMonitor {
public class EnrollClient extends ClientMonitor {
    private final byte[] mCryptoToken;
    private final BiometricUtils mBiometricUtils;
    private final int[] mDisabledFeatures;
    private final int mTimeoutSec;
    private final PowerManager mPowerManager;
    private final Surface mSurface;
    private final boolean mShouldVibrate;

    private long mEnrollmentStartTimeMs;

    public abstract boolean shouldVibrate();

    public EnrollClient(Context context, Constants constants,
            BiometricServiceBase.DaemonWrapper daemon, IBinder token,
            ClientMonitorCallbackConverter listener, int userId, int groupId,
            byte[] cryptoToken, boolean restricted, String owner, BiometricUtils utils,
            final int[] disabledFeatures, int timeoutSec, Surface surface, int sensorId) {
            final int[] disabledFeatures, int timeoutSec, int statsModality,
            PowerManager powerManager, Surface surface, int sensorId, boolean shouldVibrate) {
        super(context, constants, daemon, token, listener, userId, groupId, restricted,
                owner, 0 /* cookie */, sensorId);
                owner, 0 /* cookie */, sensorId, statsModality, BiometricsProtoEnums.ACTION_ENROLL,
                BiometricsProtoEnums.CLIENT_UNKNOWN);
        mBiometricUtils = utils;
        mCryptoToken = Arrays.copyOf(cryptoToken, cryptoToken.length);
        mDisabledFeatures = Arrays.copyOf(disabledFeatures, disabledFeatures.length);
        mTimeoutSec = timeoutSec;
        mPowerManager = powerManager;
        mSurface = surface;
    }

    @Override
    protected int statsAction() {
        return BiometricsProtoEnums.ACTION_ENROLL;
        mShouldVibrate = shouldVibrate;
    }

    @Override
@@ -74,12 +75,18 @@ public abstract class EnrollClient extends ClientMonitor {
        return sendEnrollResult(identifier, remaining);
    }

    @Override
    public void notifyUserActivity() {
        long now = SystemClock.uptimeMillis();
        mPowerManager.userActivity(now, PowerManager.USER_ACTIVITY_EVENT_TOUCH, 0);
    }

    /*
     * @return true if we're done.
     */
    private boolean sendEnrollResult(BiometricAuthenticator.Identifier identifier,
            int remaining) {
        if (shouldVibrate()) {
        if (mShouldVibrate) {
            vibrateSuccess();
        }
        mMetricsLogger.action(mConstants.actionBiometricEnroll());
+4 −8
Original line number Diff line number Diff line
@@ -33,20 +33,16 @@ public abstract class EnumerateClient extends ClientMonitor {
    public EnumerateClient(Context context, Constants constants,
            BiometricServiceBase.DaemonWrapper daemon, IBinder token,
        ClientMonitorCallbackConverter listener, int groupId, int userId,
            boolean restricted, String owner, int sensorId) {
            boolean restricted, String owner, int sensorId, int statsModality) {
        super(context, constants, daemon, token, listener, userId, groupId, restricted,
                owner, 0 /* cookie */, sensorId);
                owner, 0 /* cookie */, sensorId, statsModality,
                BiometricsProtoEnums.ACTION_ENUMERATE, BiometricsProtoEnums.CLIENT_UNKNOWN);
    }

    @Override
    public void notifyUserActivity() {
    }

    @Override
    protected int statsAction() {
        return BiometricsProtoEnums.ACTION_ENUMERATE;
    }

    @Override
    public int start() {
        // The biometric template ids will be removed when we get confirmation from the HAL
Loading