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

Commit 0d09e5b0 authored by Joshua McCloskey's avatar Joshua McCloskey Committed by Joshua Mccloskey
Browse files

Removed Coexcoordinator.

Test: atest com.android.server.biometrics
Test: Manually verified on dual biometric device, auth and BP work
as expected.
Fixes: 244083311

Change-Id: Ie87156f0a498103bd7f0e74d016de29d8c9e305b
parent 48383690
Loading
Loading
Loading
Loading
+0 −21
Original line number Diff line number Diff line
@@ -72,7 +72,6 @@ import com.android.internal.os.SomeArgs;
import com.android.internal.statusbar.IStatusBarService;
import com.android.internal.util.DumpUtils;
import com.android.server.SystemService;
import com.android.server.biometrics.sensors.CoexCoordinator;

import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -951,16 +950,6 @@ public class BiometricService extends SystemService {
            return new ArrayList<>();
        }

        public boolean isAdvancedCoexLogicEnabled(Context context) {
            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, 0) != 0;
        }

        public Supplier<Long> getRequestGenerator() {
            final AtomicLong generator = new AtomicLong(0);
            return () -> generator.incrementAndGet();
@@ -992,14 +981,6 @@ public class BiometricService extends SystemService {
                mEnabledOnKeyguardCallbacks);
        mRequestCounter = mInjector.getRequestGenerator();

        // TODO(b/193089985) This logic lives here (outside of CoexCoordinator) so that it doesn't
        //  need to depend on context. We can remove this code once the advanced logic is enabled
        //  by default.
        CoexCoordinator coexCoordinator = CoexCoordinator.getInstance();
        coexCoordinator.setAdvancedLogicEnabled(injector.isAdvancedCoexLogicEnabled(context));
        coexCoordinator.setFaceHapticDisabledWhenNonBypass(
                injector.isCoexFaceNonBypassHapticsDisabled(context));

        try {
            injector.getActivityManagerService().registerUserSwitchObserver(
                    new UserSwitchObserver() {
@@ -1333,7 +1314,5 @@ public class BiometricService extends SystemService {
        pw.println();
        pw.println("CurrentSession: " + mAuthSession);
        pw.println();
        pw.println("CoexCoordinator: " + CoexCoordinator.getInstance().toString());
        pw.println();
    }
}
+66 −156
Original line number Diff line number Diff line
@@ -29,7 +29,6 @@ import android.hardware.biometrics.BiometricManager;
import android.hardware.biometrics.BiometricOverlayConstants;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.SystemClock;
import android.security.KeyStore;
import android.util.EventLog;
import android.util.Slog;
@@ -48,8 +47,6 @@ import java.util.function.Supplier;
public abstract class AuthenticationClient<T> extends AcquisitionClient<T>
        implements AuthenticationConsumer {

    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
@@ -67,28 +64,27 @@ public abstract class AuthenticationClient<T> extends AcquisitionClient<T>
            STATE_STARTED_PAUSED_ATTEMPTED,
            STATE_STOPPED})
    @interface State {}

    private static final String TAG = "Biometrics/AuthenticationClient";
    protected final long mOperationId;
    private final boolean mIsStrongBiometric;
    private final boolean mRequireConfirmation;
    private final ActivityTaskManager mActivityTaskManager;
    private final BiometricManager mBiometricManager;
    @Nullable private final TaskStackListener mTaskStackListener;
    @Nullable
    private final TaskStackListener mTaskStackListener;
    private final LockoutTracker mLockoutTracker;
    private final boolean mIsRestricted;
    private final boolean mAllowBackgroundAuthentication;
    private final boolean mIsKeyguardBypassEnabled;

    protected final long mOperationId;

    // 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.
    @State
    protected int mState = STATE_NEW;
    private long mStartTimeMs;

    private boolean mAuthAttempted;
    private boolean mAuthSuccess = false;

    // 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;

    public AuthenticationClient(@NonNull Context context, @NonNull Supplier<T> lazyDaemon,
            @NonNull IBinder token, @NonNull ClientMonitorCallbackConverter listener,
            int targetUserId, long operationId, boolean restricted, @NonNull String owner,
@@ -111,8 +107,9 @@ public abstract class AuthenticationClient<T> extends AcquisitionClient<T>
        mIsKeyguardBypassEnabled = isKeyguardBypassEnabled;
    }

    public @LockoutTracker.LockoutMode int handleFailedAttempt(int userId) {
        final @LockoutTracker.LockoutMode int lockoutMode =
    @LockoutTracker.LockoutMode
    public int handleFailedAttempt(int userId) {
        @LockoutTracker.LockoutMode final int lockoutMode =
                mLockoutTracker.getLockoutModeForUser(userId);
        final PerformanceTracker performanceTracker =
                PerformanceTracker.getInstanceForSensorId(getSensorId());
@@ -173,14 +170,16 @@ public abstract class AuthenticationClient<T> extends AcquisitionClient<T>

        final ClientMonitorCallbackConverter listener = getListener();

        if (DEBUG) Slog.v(TAG, "onAuthenticated(" + authenticated + ")"
        if (DEBUG) {
            Slog.v(TAG, "onAuthenticated(" + authenticated + ")"
                    + ", ID:" + identifier.getBiometricId()
                    + ", Owner: " + getOwnerString()
                    + ", isBP: " + isBiometricPrompt()
                    + ", listener: " + listener
                    + ", requireConfirmation: " + mRequireConfirmation
                    + ", user: " + getTargetUserId()
                + ", clientMonitor: " + toString());
                    + ", clientMonitor: " + this);
        }

        final PerformanceTracker pm = PerformanceTracker.getInstanceForSensorId(getSensorId());
        if (isCryptoOperation()) {
@@ -239,142 +238,57 @@ public abstract class AuthenticationClient<T> extends AcquisitionClient<T>
                        getSensorId(), getTargetUserId(), byteToken);
            }

            final CoexCoordinator coordinator = CoexCoordinator.getInstance();
            coordinator.onAuthenticationSucceeded(SystemClock.uptimeMillis(), this,
                    new CoexCoordinator.Callback() {
                @Override
                public void sendAuthenticationResult(boolean addAuthTokenIfStrong) {
                    if (addAuthTokenIfStrong && mIsStrongBiometric) {
            // For BP, BiometricService will add the authToken to Keystore.
            if (!isBiometricPrompt() && mIsStrongBiometric) {
                final int result = KeyStore.getInstance().addAuthToken(byteToken);
                if (result != KeyStore.NO_ERROR) {
                    Slog.d(TAG, "Error adding auth token : " + result);
                } else {
                    Slog.d(TAG, "addAuthToken: " + result);
                }
            } else {
                Slog.d(TAG, "Skipping addAuthToken");
            }

                    if (listener != null) {
            try {
                            // Explicitly have if/else here to make it super obvious in case the
                            // code is touched in the future.
                if (listener != null) {
                    if (!mIsRestricted) {
                                listener.onAuthenticationSucceeded(getSensorId(),
                                        identifier,
                                        byteToken,
                                        getTargetUserId(),
                                        mIsStrongBiometric);
                        listener.onAuthenticationSucceeded(getSensorId(), identifier, byteToken,
                                getTargetUserId(), mIsStrongBiometric);
                    } else {
                                listener.onAuthenticationSucceeded(getSensorId(),
                                        null /* identifier */,
                        listener.onAuthenticationSucceeded(getSensorId(), null /* identifier */,
                                byteToken,
                                        getTargetUserId(),
                                        mIsStrongBiometric);
                                getTargetUserId(), mIsStrongBiometric);
                    }
                } else {
                    Slog.e(TAG, "Received successful auth, but client was not listening");
                }
            } catch (RemoteException e) {
                Slog.e(TAG, "Unable to notify listener", e);
                mCallback.onClientFinished(this, false);
                return;
            }
        } else {
                        Slog.w(TAG, "Client not listening");
                    }
                }

                @Override
                public void sendHapticFeedback() {
                    if (listener != null && mShouldVibrate) {
                        vibrateSuccess();
                    }
                }

                @Override
                public void handleLifecycleAfterAuth() {
                    AuthenticationClient.this.handleLifecycleAfterAuth(true /* authenticated */);
                }

                @Override
                public void sendAuthenticationCanceled() {
                    sendCancelOnly(listener);
                }
            });
        } else { // not authenticated
            if (isBackgroundAuth) {
                Slog.e(TAG, "cancelling due to background auth");
                cancel();
            } else {
                // Allow system-defined limit of number of attempts before giving up
                final @LockoutTracker.LockoutMode int lockoutMode =
                @LockoutTracker.LockoutMode final int lockoutMode =
                        handleFailedAttempt(getTargetUserId());
                if (lockoutMode != LockoutTracker.LOCKOUT_NONE) {
                    markAlreadyDone();
                }

                final CoexCoordinator coordinator = CoexCoordinator.getInstance();
                coordinator.onAuthenticationRejected(SystemClock.uptimeMillis(), this, lockoutMode,
                        new CoexCoordinator.Callback() {
                            @Override
                            public void sendAuthenticationResult(boolean addAuthTokenIfStrong) {
                                if (listener != null) {
                try {
                    listener.onAuthenticationFailed(getSensorId());
                } catch (RemoteException e) {
                    Slog.e(TAG, "Unable to notify listener", e);
                    mCallback.onClientFinished(this, false);
                    return;
                }
            }
        }

                            @Override
                            public void sendHapticFeedback() {
                                if (listener != null && mShouldVibrate) {
                                    vibrateError();
                                }
                            }

                            @Override
                            public void handleLifecycleAfterAuth() {
                                AuthenticationClient.this.handleLifecycleAfterAuth(false /* authenticated */);
                            }

                            @Override
                            public void sendAuthenticationCanceled() {
                                sendCancelOnly(listener);
                            }
                        });
            }
        }
    }

    /**
     * Only call this method on interfaces where lockout does not come from onError, I.E. the
     * old HIDL implementation.
     */
    protected void onLockoutTimed(long durationMillis) {
        final ClientMonitorCallbackConverter listener = getListener();
        final CoexCoordinator coordinator = CoexCoordinator.getInstance();
        coordinator.onAuthenticationError(this, BiometricConstants.BIOMETRIC_ERROR_LOCKOUT,
                new CoexCoordinator.ErrorCallback() {
            @Override
            public void sendHapticFeedback() {
                if (listener != null && mShouldVibrate) {
                    vibrateError();
                }
            }
        });
    }

    /**
     * Only call this method on interfaces where lockout does not come from onError, I.E. the
     * old HIDL implementation.
     */
    protected void onLockoutPermanent() {
        final ClientMonitorCallbackConverter listener = getListener();
        final CoexCoordinator coordinator = CoexCoordinator.getInstance();
        coordinator.onAuthenticationError(this,
                BiometricConstants.BIOMETRIC_ERROR_LOCKOUT_PERMANENT,
                new CoexCoordinator.ErrorCallback() {
            @Override
            public void sendHapticFeedback() {
                if (listener != null && mShouldVibrate) {
                    vibrateError();
                }
            }
        });
        AuthenticationClient.this.handleLifecycleAfterAuth(authenticated);
    }

    private void sendCancelOnly(@Nullable ClientMonitorCallbackConverter listener) {
@@ -396,7 +310,7 @@ public abstract class AuthenticationClient<T> extends AcquisitionClient<T>
    public void onAcquired(int acquiredInfo, int vendorCode) {
        super.onAcquired(acquiredInfo, vendorCode);

        final @LockoutTracker.LockoutMode int lockoutMode =
        @LockoutTracker.LockoutMode final int lockoutMode =
                mLockoutTracker.getLockoutModeForUser(getTargetUserId());
        if (lockoutMode == LockoutTracker.LOCKOUT_NONE) {
            PerformanceTracker pt = PerformanceTracker.getInstanceForSensorId(getSensorId());
@@ -408,8 +322,6 @@ public abstract class AuthenticationClient<T> extends AcquisitionClient<T>
    public void onError(@BiometricConstants.Errors int errorCode, int vendorCode) {
        super.onError(errorCode, vendorCode);
        mState = STATE_STOPPED;

        CoexCoordinator.getInstance().onAuthenticationError(this, errorCode, this::vibrateError);
    }

    /**
@@ -419,7 +331,7 @@ public abstract class AuthenticationClient<T> extends AcquisitionClient<T>
    public void start(@NonNull ClientMonitorCallback callback) {
        super.start(callback);

        final @LockoutTracker.LockoutMode int lockoutMode =
        @LockoutTracker.LockoutMode final int lockoutMode =
                mLockoutTracker.getLockoutModeForUser(getTargetUserId());
        if (lockoutMode != LockoutTracker.LOCKOUT_NONE) {
            Slog.v(TAG, "In lockout mode(" + lockoutMode + ") ; disallowing authentication");
@@ -450,12 +362,9 @@ public abstract class AuthenticationClient<T> extends AcquisitionClient<T>
    }

    /**
     * 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
     * Handles lifecycle, e.g. {@link BiometricScheduler} after authentication. This is necessary
     * as different clients handle the lifecycle of authentication success/reject differently. I.E.
     * Fingerprint does not finish authentication when it is rejected.
     */
    protected abstract void handleLifecycleAfterAuth(boolean authenticated);

@@ -465,7 +374,8 @@ public abstract class AuthenticationClient<T> extends AcquisitionClient<T>
     */
    public abstract boolean wasUserDetected();

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

+3 −15
Original line number Diff line number Diff line
@@ -54,7 +54,7 @@ import java.util.function.Consumer;
 * 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}.
 * {@link BiometricScheduler}.
 */
@MainThread
public class BiometricScheduler {
@@ -156,7 +156,6 @@ 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
@@ -165,11 +164,6 @@ public class BiometricScheduler {
        @Override
        public void onClientStarted(@NonNull BaseClientMonitor clientMonitor) {
            Slog.d(getTag(), "[Started] " + clientMonitor);

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

        @Override
@@ -189,10 +183,6 @@ public class BiometricScheduler {
                }

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

                if (mGestureAvailabilityDispatcher != null) {
                    mGestureAvailabilityDispatcher.markSensorActive(
@@ -216,8 +206,7 @@ public class BiometricScheduler {
            @SensorType int sensorType,
            @Nullable GestureAvailabilityDispatcher gestureAvailabilityDispatcher,
            @NonNull IBiometricService biometricService,
            int recentOperationsLimit,
            @NonNull CoexCoordinator coexCoordinator) {
            int recentOperationsLimit) {
        mBiometricTag = tag;
        mHandler = handler;
        mSensorType = sensorType;
@@ -227,7 +216,6 @@ public class BiometricScheduler {
        mCrashStates = new ArrayDeque<>();
        mRecentOperationsLimit = recentOperationsLimit;
        mRecentOperations = new ArrayList<>();
        mCoexCoordinator = coexCoordinator;
    }

    /**
@@ -244,7 +232,7 @@ public class BiometricScheduler {
        this(tag, new Handler(Looper.getMainLooper()), sensorType, gestureAvailabilityDispatcher,
                IBiometricService.Stub.asInterface(
                        ServiceManager.getService(Context.BIOMETRIC_SERVICE)),
                LOG_NUM_RECENT_OPERATIONS, CoexCoordinator.getInstance());
                LOG_NUM_RECENT_OPERATIONS);
    }

    @VisibleForTesting
+0 −525

File deleted.

Preview size limit exceeded, changes collapsed.

+3 −4
Original line number Diff line number Diff line
@@ -95,10 +95,9 @@ public class UserAwareBiometricScheduler extends BiometricScheduler {
            @Nullable GestureAvailabilityDispatcher gestureAvailabilityDispatcher,
            @NonNull IBiometricService biometricService,
            @NonNull CurrentUserRetriever currentUserRetriever,
            @NonNull UserSwitchCallback userSwitchCallback,
            @NonNull CoexCoordinator coexCoordinator) {
            @NonNull UserSwitchCallback userSwitchCallback) {
        super(tag, handler, sensorType, gestureAvailabilityDispatcher, biometricService,
                LOG_NUM_RECENT_OPERATIONS, coexCoordinator);
                LOG_NUM_RECENT_OPERATIONS);

        mCurrentUserRetriever = currentUserRetriever;
        mUserSwitchCallback = userSwitchCallback;
@@ -112,7 +111,7 @@ public class UserAwareBiometricScheduler extends BiometricScheduler {
        this(tag, new Handler(Looper.getMainLooper()), sensorType, gestureAvailabilityDispatcher,
                IBiometricService.Stub.asInterface(
                        ServiceManager.getService(Context.BIOMETRIC_SERVICE)),
                currentUserRetriever, userSwitchCallback, CoexCoordinator.getInstance());
                currentUserRetriever, userSwitchCallback);
    }

    @Override
Loading