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

Commit 2f458df6 authored by Joe Bolinger's avatar Joe Bolinger
Browse files

Do not lock when biometric lock status is cleared.

This can lead to a rapid unlock -> lock -> unlock cycle while keyguard is showing.

Bug: 210897417
Test: manual (unlock with fingerprint and verify adb logcat | grep keystore2::authorization shows 1 entry)
Change-Id: I318aaf52a3540f7209f3622e877f8935cffc7f6c
parent 0917ecb0
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -36,5 +36,5 @@ interface ITrustManager {
    boolean isDeviceSecure(int userId);
    boolean isTrustUsuallyManaged(int userId);
    void unlockedByBiometricForUser(int userId, in BiometricSourceType source);
    void clearAllBiometricRecognized(in BiometricSourceType target);
    void clearAllBiometricRecognized(in BiometricSourceType target, int unlockedUser);
}
+2 −2
Original line number Diff line number Diff line
@@ -217,9 +217,9 @@ public class TrustManager {
     * Clears authentication by the specified biometric type for all users.
     */
    @RequiresPermission(Manifest.permission.ACCESS_KEYGUARD_SECURE_STORAGE)
    public void clearAllBiometricRecognized(BiometricSourceType source) {
    public void clearAllBiometricRecognized(BiometricSourceType source, int unlockedUser) {
        try {
            mService.clearAllBiometricRecognized(source);
            mService.clearAllBiometricRecognized(source, unlockedUser);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
+10 −2
Original line number Diff line number Diff line
@@ -3171,11 +3171,19 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
    }

    public void clearBiometricRecognized() {
        clearBiometricRecognized(UserHandle.USER_NULL);
    }

    public void clearBiometricRecognizedWhenKeyguardDone(int unlockedUser) {
        clearBiometricRecognized(unlockedUser);
    }

    private void clearBiometricRecognized(int unlockedUser) {
        Assert.isMainThread();
        mUserFingerprintAuthenticated.clear();
        mUserFaceAuthenticated.clear();
        mTrustManager.clearAllBiometricRecognized(BiometricSourceType.FINGERPRINT);
        mTrustManager.clearAllBiometricRecognized(BiometricSourceType.FACE);
        mTrustManager.clearAllBiometricRecognized(BiometricSourceType.FINGERPRINT, unlockedUser);
        mTrustManager.clearAllBiometricRecognized(BiometricSourceType.FACE, unlockedUser);

        for (int i = 0; i < mCallbacks.size(); i++) {
            KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
+3 −4
Original line number Diff line number Diff line
@@ -1745,7 +1745,7 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable,
        }
    };

    public void keyguardDone() {
    private void keyguardDone() {
        Trace.beginSection("KeyguardViewMediator#keyguardDone");
        if (DEBUG) Log.d(TAG, "keyguardDone()");
        userActivity();
@@ -1879,9 +1879,8 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable,
            resetKeyguardDonePendingLocked();
        }


        if (mGoingToSleep) {
            mUpdateMonitor.clearBiometricRecognized();
            mUpdateMonitor.clearBiometricRecognizedWhenKeyguardDone(currentUser);
            Log.i(TAG, "Device is going to sleep, aborting keyguardDone");
            return;
        }
@@ -1902,7 +1901,7 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable,
        }

        handleHide();
        mUpdateMonitor.clearBiometricRecognized();
        mUpdateMonitor.clearBiometricRecognizedWhenKeyguardDone(currentUser);
        Trace.endSection();
    }

+35 −8
Original line number Diff line number Diff line
@@ -46,6 +46,7 @@ import android.hardware.biometrics.BiometricSourceType;
import android.net.Uri;
import android.os.Binder;
import android.os.Build;
import android.os.Bundle;
import android.os.DeadObjectException;
import android.os.Handler;
import android.os.IBinder;
@@ -123,6 +124,8 @@ public class TrustManagerService extends SystemService {
    private static final int MSG_REFRESH_DEVICE_LOCKED_FOR_USER = 14;
    private static final int MSG_SCHEDULE_TRUST_TIMEOUT = 15;

    private static final String REFRESH_DEVICE_LOCKED_EXCEPT_USER = "except";

    private static final int TRUST_USUALLY_MANAGED_FLUSH_DELAY = 2 * 60 * 1000;
    private static final String TRUST_TIMEOUT_ALARM_TAG = "TrustManagerService.trustTimeoutForUser";
    private static final long TRUST_TIMEOUT_IN_MILLIS = 4 * 60 * 60 * 1000;
@@ -635,11 +638,18 @@ public class TrustManagerService extends SystemService {
        }
    }

    private void refreshDeviceLockedForUser(int userId) {
        refreshDeviceLockedForUser(userId, UserHandle.USER_NULL);
    }

    /**
     * Update the user's locked state. Only applicable to users with a real keyguard
     * ({@link UserInfo#supportsSwitchToByUser}) and unsecured managed profiles.
     *
     * If this is called due to an unlock operation set unlockedUser to prevent the lock from
     * being prematurely reset for that user while keyguard is still in the process of going away.
     */
    private void refreshDeviceLockedForUser(int userId) {
    private void refreshDeviceLockedForUser(int userId, int unlockedUser) {
        if (userId != UserHandle.USER_ALL && userId < UserHandle.USER_SYSTEM) {
            Log.e(TAG, "refreshDeviceLockedForUser(userId=" + userId + "): Invalid user handle,"
                    + " must be USER_ALL or a specific user.", new Throwable("here"));
@@ -675,6 +685,7 @@ public class TrustManagerService extends SystemService {
            boolean trusted = aggregateIsTrusted(id);
            boolean showingKeyguard = true;
            boolean biometricAuthenticated = false;
            boolean currentUserIsUnlocked = false;

            if (mCurrentUser == id) {
                synchronized(mUsersUnlockedByBiometric) {
@@ -683,10 +694,17 @@ public class TrustManagerService extends SystemService {
                try {
                    showingKeyguard = wm.isKeyguardLocked();
                } catch (RemoteException e) {
                    Log.w(TAG, "Unable to check keyguard lock state", e);
                }
                currentUserIsUnlocked = unlockedUser == id;
            }
            final boolean deviceLocked = secure && showingKeyguard && !trusted
                    && !biometricAuthenticated;
            if (deviceLocked && currentUserIsUnlocked) {
                // keyguard is finishing but may not have completed going away yet
                continue;
            }
            boolean deviceLocked = secure && showingKeyguard && !trusted &&
                    !biometricAuthenticated;

            setDeviceLockedForUser(id, deviceLocked);
        }
    }
@@ -1306,13 +1324,20 @@ public class TrustManagerService extends SystemService {
        }

        @Override
        public void clearAllBiometricRecognized(BiometricSourceType biometricSource) {
        public void clearAllBiometricRecognized(
                BiometricSourceType biometricSource, int unlockedUser) {
            enforceReportPermission();
            synchronized(mUsersUnlockedByBiometric) {
                mUsersUnlockedByBiometric.clear();
            }
            mHandler.obtainMessage(MSG_REFRESH_DEVICE_LOCKED_FOR_USER, UserHandle.USER_ALL,
                    0 /* arg2 */).sendToTarget();
            Message message = mHandler.obtainMessage(MSG_REFRESH_DEVICE_LOCKED_FOR_USER,
                    UserHandle.USER_ALL, 0 /* arg2 */);
            if (unlockedUser >= 0) {
                Bundle bundle = new Bundle();
                bundle.putInt(REFRESH_DEVICE_LOCKED_EXCEPT_USER, unlockedUser);
                message.setData(bundle);
            }
            message.sendToTarget();
        }
    };

@@ -1404,9 +1429,11 @@ public class TrustManagerService extends SystemService {
                    break;
                case MSG_REFRESH_DEVICE_LOCKED_FOR_USER:
                    if (msg.arg2 == 1) {
                        updateTrust(msg.arg1, 0 /* flags */, true);
                        updateTrust(msg.arg1, 0 /* flags */, true /* isFromUnlock */);
                    }
                    refreshDeviceLockedForUser(msg.arg1);
                    final int unlockedUser = msg.getData().getInt(
                            REFRESH_DEVICE_LOCKED_EXCEPT_USER, UserHandle.USER_NULL);
                    refreshDeviceLockedForUser(msg.arg1, unlockedUser);
                    break;
                case MSG_SCHEDULE_TRUST_TIMEOUT:
                    handleScheduleTrustTimeout(msg.arg1, msg.arg2);