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

Commit 66a048d6 authored by Joshua McCloskey's avatar Joshua McCloskey Committed by Joshua Mccloskey
Browse files

Added FingerprintInteractiveToAuthProvider

Also removed sidefps logic from FingerprintAuth client.
Bug: 261209932
Test: Verified device builds, and sidefps auth no longer delays auth
attempts.

Change-Id: Ibb993eccda4678013db5b0d64c6f6243c93bdf8a
Merged-In: Ibb993eccda4678013db5b0d64c6f6243c93bdf8a
parent e84b9a03
Loading
Loading
Loading
Loading
+18 −35
Original line number Diff line number Diff line
@@ -141,6 +141,7 @@ import com.android.settingslib.fuelgauge.BatteryStatus;
import com.android.systemui.Dumpable;
import com.android.systemui.R;
import com.android.systemui.biometrics.AuthController;
import com.android.systemui.biometrics.FingerprintInteractiveToAuthProvider;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Background;
@@ -170,6 +171,7 @@ import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Optional;
import java.util.Set;
import java.util.TimeZone;
import java.util.concurrent.Executor;
@@ -345,13 +347,11 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
    private final ArrayList<WeakReference<KeyguardUpdateMonitorCallback>>
            mCallbacks = Lists.newArrayList();
    private ContentObserver mDeviceProvisionedObserver;
    private ContentObserver mSfpsRequireScreenOnToAuthPrefObserver;
    private final ContentObserver mTimeFormatChangeObserver;

    private boolean mSwitchingUser;

    private boolean mDeviceInteractive;
    private boolean mSfpsRequireScreenOnToAuthPrefEnabled;
    private final SubscriptionManager mSubscriptionManager;
    private final TelephonyListenerManager mTelephonyListenerManager;
    private final TrustManager mTrustManager;
@@ -384,6 +384,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
    private boolean mLogoutEnabled;
    private boolean mIsFaceEnrolled;
    private int mActiveMobileDataSubscription = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
    private FingerprintInteractiveToAuthProvider mFingerprintInteractiveToAuthProvider;

    /**
     * Short delay before restarting fingerprint authentication after a successful try. This should
@@ -2048,7 +2049,8 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
            @Nullable FaceManager faceManager,
            @Nullable FingerprintManager fingerprintManager,
            @Nullable BiometricManager biometricManager,
            FaceWakeUpTriggersConfig faceWakeUpTriggersConfig) {
            FaceWakeUpTriggersConfig faceWakeUpTriggersConfig,
            Optional<FingerprintInteractiveToAuthProvider> interactiveToAuthProvider) {
        mContext = context;
        mSubscriptionManager = subscriptionManager;
        mUserTracker = userTracker;
@@ -2311,30 +2313,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
                Settings.System.getUriFor(Settings.System.TIME_12_24),
                false, mTimeFormatChangeObserver, UserHandle.USER_ALL);

        updateSfpsRequireScreenOnToAuthPref();
        mSfpsRequireScreenOnToAuthPrefObserver = new ContentObserver(mHandler) {
            @Override
            public void onChange(boolean selfChange) {
                updateSfpsRequireScreenOnToAuthPref();
            }
        };

        mContext.getContentResolver().registerContentObserver(
                mSecureSettings.getUriFor(
                        Settings.Secure.SFPS_REQUIRE_SCREEN_ON_TO_AUTH_ENABLED),
                false,
                mSfpsRequireScreenOnToAuthPrefObserver,
                getCurrentUser());
    }

    protected void updateSfpsRequireScreenOnToAuthPref() {
        final int defaultSfpsRequireScreenOnToAuthValue =
                mContext.getResources().getBoolean(
                        com.android.internal.R.bool.config_requireScreenOnToAuthEnabled) ? 1 : 0;
        mSfpsRequireScreenOnToAuthPrefEnabled = mSecureSettings.getIntForUser(
                Settings.Secure.SFPS_REQUIRE_SCREEN_ON_TO_AUTH_ENABLED,
                defaultSfpsRequireScreenOnToAuthValue,
                getCurrentUser()) != 0;
        mFingerprintInteractiveToAuthProvider = interactiveToAuthProvider.orElse(null);
    }

    private void initializeSimState() {
@@ -2729,8 +2708,11 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab

        boolean shouldListenSideFpsState = true;
        if (isSideFps) {
            final boolean interactiveToAuthEnabled =
                    mFingerprintInteractiveToAuthProvider != null &&
                            mFingerprintInteractiveToAuthProvider.isEnabled(getCurrentUser());
            shouldListenSideFpsState =
                    mSfpsRequireScreenOnToAuthPrefEnabled ? isDeviceInteractive() : true;
                    interactiveToAuthEnabled ? isDeviceInteractive() : true;
        }

        boolean shouldListen = shouldListenKeyguardState && shouldListenUserState
@@ -3845,11 +3827,6 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
            mContext.getContentResolver().unregisterContentObserver(mTimeFormatChangeObserver);
        }

        if (mSfpsRequireScreenOnToAuthPrefObserver != null) {
            mContext.getContentResolver().unregisterContentObserver(
                    mSfpsRequireScreenOnToAuthPrefObserver);
        }

        try {
            ActivityManager.getService().unregisterUserSwitchObserver(mUserSwitchObserver);
        } catch (RemoteException e) {
@@ -3926,8 +3903,14 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
            } else if (isSfpsSupported()) {
                pw.println("        sfpsEnrolled=" + isSfpsEnrolled());
                pw.println("        shouldListenForSfps=" + shouldListenForFingerprint(false));
                pw.println("        mSfpsRequireScreenOnToAuthPrefEnabled="
                        + mSfpsRequireScreenOnToAuthPrefEnabled);
                if (isSfpsEnrolled()) {
                    final boolean interactiveToAuthEnabled =
                                    mFingerprintInteractiveToAuthProvider != null &&
                                            mFingerprintInteractiveToAuthProvider
                                            .isEnabled(getCurrentUser());
                    pw.println("        interactiveToAuthEnabled="
                            + interactiveToAuthEnabled);
                }
            }
            new DumpsysTableLogger(
                    "KeyguardFingerprintListen",
+27 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2023 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.systemui.biometrics;

/** Provides the status of the interactive to auth feature. */
public interface FingerprintInteractiveToAuthProvider {
    /**
     *
     * @param userId the user Id.
     * @return true if the InteractiveToAuthFeature is enabled, false if disabled.
     */
    boolean isEnabled(int userId);
}
+4 −0
Original line number Diff line number Diff line
@@ -31,6 +31,7 @@ import com.android.systemui.BootCompleteCacheImpl;
import com.android.systemui.appops.dagger.AppOpsModule;
import com.android.systemui.assist.AssistModule;
import com.android.systemui.biometrics.AlternateUdfpsTouchProvider;
import com.android.systemui.biometrics.FingerprintInteractiveToAuthProvider;
import com.android.systemui.biometrics.UdfpsDisplayModeProvider;
import com.android.systemui.biometrics.dagger.BiometricsModule;
import com.android.systemui.biometrics.dagger.UdfpsModule;
@@ -221,6 +222,9 @@ public abstract class SystemUIModule {
    @BindsOptionalOf
    abstract AlternateUdfpsTouchProvider optionalUdfpsTouchProvider();

    @BindsOptionalOf
    abstract FingerprintInteractiveToAuthProvider optionalFingerprintInteractiveToAuthProvider();

    @SysUISingleton
    @Binds
    abstract SystemClock bindSystemClock(SystemClockImpl systemClock);
+7 −5
Original line number Diff line number Diff line
@@ -116,6 +116,7 @@ import com.android.keyguard.KeyguardUpdateMonitor.BiometricAuthenticated;
import com.android.keyguard.logging.KeyguardUpdateMonitorLogger;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.biometrics.AuthController;
import com.android.systemui.biometrics.FingerprintInteractiveToAuthProvider;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.log.SessionTracker;
@@ -142,6 +143,7 @@ import org.mockito.internal.util.reflection.FieldSetter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.Executor;
import java.util.concurrent.atomic.AtomicBoolean;

@@ -233,6 +235,8 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
    @Mock
    private GlobalSettings mGlobalSettings;
    private FaceWakeUpTriggersConfig mFaceWakeUpTriggersConfig;
    @Mock
    private FingerprintInteractiveToAuthProvider mInteractiveToAuthProvider;


    private final int mCurrentUserId = 100;
@@ -1259,8 +1263,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
        when(mAuthController.isSfpsEnrolled(anyInt())).thenReturn(true);

        // WHEN require screen on to auth is disabled, and keyguard is not awake
        when(mSecureSettings.getIntForUser(anyString(), anyInt(), anyInt())).thenReturn(0);
        mKeyguardUpdateMonitor.updateSfpsRequireScreenOnToAuthPref();
        when(mInteractiveToAuthProvider.isEnabled(anyInt())).thenReturn(false);

        mContext.getOrCreateTestableResources().addOverride(
                com.android.internal.R.bool.config_requireScreenOnToAuthEnabled, true);
@@ -1280,8 +1283,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
        assertThat(mKeyguardUpdateMonitor.shouldListenForFingerprint(false)).isTrue();

        // WHEN require screen on to auth is enabled, and keyguard is not awake
        when(mSecureSettings.getIntForUser(anyString(), anyInt(), anyInt())).thenReturn(1);
        mKeyguardUpdateMonitor.updateSfpsRequireScreenOnToAuthPref();
        when(mInteractiveToAuthProvider.isEnabled(anyInt())).thenReturn(true);

        // THEN we shouldn't listen for sfps when screen off, because require screen on is enabled
        assertThat(mKeyguardUpdateMonitor.shouldListenForFingerprint(false)).isFalse();
@@ -2407,7 +2409,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
                    mPowerManager, mTrustManager, mSubscriptionManager, mUserManager,
                    mDreamManager, mDevicePolicyManager, mSensorPrivacyManager, mTelephonyManager,
                    mPackageManager, mFaceManager, mFingerprintManager, mBiometricManager,
                    mFaceWakeUpTriggersConfig);
                    mFaceWakeUpTriggersConfig, Optional.of(mInteractiveToAuthProvider));
            setStrongAuthTracker(KeyguardUpdateMonitorTest.this.mStrongAuthTracker);
        }

+4 −90
Original line number Diff line number Diff line
@@ -16,15 +16,11 @@

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

import static android.hardware.biometrics.BiometricFingerprintConstants.FINGERPRINT_ACQUIRED_START;
import static android.hardware.biometrics.BiometricFingerprintConstants.FINGERPRINT_ACQUIRED_VENDOR;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.TaskStackListener;
import android.content.Context;
import android.hardware.biometrics.BiometricAuthenticator;
import android.hardware.biometrics.BiometricConstants;
import android.hardware.biometrics.BiometricFingerprintConstants;
import android.hardware.biometrics.BiometricFingerprintConstants.FingerprintAcquired;
import android.hardware.biometrics.common.ICancellationSignal;
@@ -92,7 +88,6 @@ class FingerprintAuthenticationClient extends AuthenticationClient<AidlSession>
    private long mSideFpsLastAcquireStartTime;
    private Runnable mAuthSuccessRunnable;
    private final Clock mClock;
    private boolean mDidFinishSfps;

    FingerprintAuthenticationClient(
            @NonNull Context context,
@@ -198,9 +193,8 @@ class FingerprintAuthenticationClient extends AuthenticationClient<AidlSession>

    @Override
    protected void handleLifecycleAfterAuth(boolean authenticated) {
        if (authenticated && !mDidFinishSfps) {
        if (authenticated) {
            mCallback.onClientFinished(this, true /* success */);
            mDidFinishSfps = true;
        }
    }

@@ -210,13 +204,11 @@ class FingerprintAuthenticationClient extends AuthenticationClient<AidlSession>
        return false;
    }

    public void handleAuthenticate(
    @Override
    public void onAuthenticated(
            BiometricAuthenticator.Identifier identifier,
            boolean authenticated,
            ArrayList<Byte> token) {
        if (authenticated && mSensorProps.isAnySidefpsType()) {
            Slog.i(TAG, "(sideFPS): No power press detected, sending auth");
        }
        super.onAuthenticated(identifier, authenticated, token);
        if (authenticated) {
            mState = STATE_STOPPED;
@@ -226,73 +218,12 @@ class FingerprintAuthenticationClient extends AuthenticationClient<AidlSession>
        }
    }

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

        mHandler.post(
                () -> {
                    long delay = 0;
                    if (authenticated && mSensorProps.isAnySidefpsType()) {
                        delay = isKeyguard() ? mWaitForAuthKeyguard : mWaitForAuthBp;

                        if (mSideFpsLastAcquireStartTime != -1) {
                            delay = Math.max(0,
                                    delay - (mClock.millis() - mSideFpsLastAcquireStartTime));
                        }

                        Slog.i(TAG, "(sideFPS) Auth succeeded, sideFps "
                                + "waiting for power until: " + delay + "ms");
                    }

                    if (mHandler.hasMessages(MESSAGE_FINGER_UP)) {
                        Slog.i(TAG, "Finger up detected, sending auth");
                        delay = 0;
                    }

                    mAuthSuccessRunnable =
                            () -> handleAuthenticate(identifier, authenticated, token);
                    mHandler.postDelayed(
                            mAuthSuccessRunnable,
                            MESSAGE_AUTH_SUCCESS,
                            delay);
                });
    }

    @Override
    public void onAcquired(@FingerprintAcquired int acquiredInfo, int vendorCode) {
        // For UDFPS, notify SysUI with acquiredInfo, so that the illumination can be turned off
        // for most ACQUIRED messages. See BiometricFingerprintConstants#FingerprintAcquired
        mSensorOverlays.ifUdfps(controller -> controller.onAcquired(getSensorId(), acquiredInfo));
        super.onAcquired(acquiredInfo, vendorCode);
        if (mSensorProps.isAnySidefpsType()) {
            if (acquiredInfo == FINGERPRINT_ACQUIRED_START) {
                mSideFpsLastAcquireStartTime = mClock.millis();
            }
            final boolean shouldLookForVendor =
                    mSkipWaitForPowerAcquireMessage == FINGERPRINT_ACQUIRED_VENDOR;
            final boolean acquireMessageMatch = acquiredInfo == mSkipWaitForPowerAcquireMessage;
            final boolean vendorMessageMatch = vendorCode == mSkipWaitForPowerVendorAcquireMessage;
            final boolean ignorePowerPress =
                    acquireMessageMatch && (!shouldLookForVendor || vendorMessageMatch);

            if (ignorePowerPress) {
                Slog.d(TAG, "(sideFPS) onFingerUp");
                mHandler.post(() -> {
                    if (mHandler.hasMessages(MESSAGE_AUTH_SUCCESS)) {
                        Slog.d(TAG, "(sideFPS) skipping wait for power");
                        mHandler.removeMessages(MESSAGE_AUTH_SUCCESS);
                        mHandler.post(mAuthSuccessRunnable);
                    } else {
                        mHandler.postDelayed(() -> {
                        }, MESSAGE_FINGER_UP, mFingerUpIgnoresPower);
                    }
                });
            }
        }

    }

    @Override
@@ -488,22 +419,5 @@ class FingerprintAuthenticationClient extends AuthenticationClient<AidlSession>
    }

    @Override
    public void onPowerPressed() {
        if (mSensorProps.isAnySidefpsType()) {
            Slog.i(TAG, "(sideFPS): onPowerPressed");
            mHandler.post(() -> {
                if (mDidFinishSfps) {
                    return;
                }
                Slog.i(TAG, "(sideFPS): finishing auth");
                // Ignore auths after a power has been detected
                mHandler.removeMessages(MESSAGE_AUTH_SUCCESS);
                // Do not call onError() as that will send an additional callback to coex.
                mDidFinishSfps = true;
                onErrorInternal(BiometricConstants.BIOMETRIC_ERROR_POWER_PRESSED, 0, true);
                stopHalOperation();
                mSensorOverlays.hide(getSensorId());
            });
        }
    }
    public void onPowerPressed() { }
}
Loading