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

Commit 3fdbbf87 authored by Kevin Chyn's avatar Kevin Chyn
Browse files

update trust state immediately when user auths via FP on keyguard

KeyguardUpdateMonitor onFingerprintAuthenticated currently doesn't
immediately update the trust state. TrustManager.isDeviceLocked()
should return "unlocked" after FP is authenticated.

Fixes: 37963501

Test: Two tests as follows

1) use custom app that polls isDeviceLocked(), make sure
it returns "unlocked" after FP is authenticated but keyguard is showing.
To get that state, slide keyguard up slightly and touch FP sensor
without letting go of the other finger.

2) with at least 2 accounts, run the app on both accounts.
when switching users, the app should show that the "inactive/underneath"
user is locked. the app should report that the current user is locked
before touching fp, and unlocked after touching fp

Change-Id: I2a11411deebf369d85dee62cffdcd631bd99649f
parent a6cf18f4
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -34,4 +34,6 @@ interface ITrustManager {
    boolean isDeviceLocked(int userId);
    boolean isDeviceSecure(int userId);
    boolean isTrustUsuallyManaged(int userId);
    void unlockedByFingerprintForUser(int userId);
    void clearAllFingerprints();
}
+26 −2
Original line number Diff line number Diff line
@@ -25,8 +25,6 @@ import android.os.Message;
import android.os.RemoteException;
import android.util.ArrayMap;

import com.android.internal.widget.LockPatternUtils;

/**
 * See {@link com.android.server.trust.TrustManagerService}
 * @hide
@@ -184,6 +182,32 @@ public class TrustManager {
        }
    }

    /**
     * Updates the trust state for the user due to the user unlocking via fingerprint.
     * Should only be called if user authenticated via fingerprint and bouncer can be skipped.
     * @param userId
     */
    @RequiresPermission(Manifest.permission.ACCESS_KEYGUARD_SECURE_STORAGE)
    public void unlockedByFingerprintForUser(int userId) {
        try {
            mService.unlockedByFingerprintForUser(userId);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Clears authenticated fingerprints for all users.
     */
    @RequiresPermission(Manifest.permission.ACCESS_KEYGUARD_SECURE_STORAGE)
    public void clearAllFingerprints() {
        try {
            mService.clearAllFingerprints();
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    private final Handler mHandler = new Handler(Looper.getMainLooper()) {
        @Override
        public void handleMessage(Message msg) {
+5 −0
Original line number Diff line number Diff line
@@ -415,6 +415,10 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
    private void onFingerprintAuthenticated(int userId) {
        Trace.beginSection("KeyGuardUpdateMonitor#onFingerPrintAuthenticated");
        mUserFingerprintAuthenticated.put(userId, true);
        // Update/refresh trust state only if user can skip bouncer
        if (getUserCanSkipBouncer(userId)) {
            mTrustManager.unlockedByFingerprintForUser(userId);
        }
        // Don't send cancel if authentication succeeds
        mFingerprintCancelSignal = null;
        for (int i = 0; i < mCallbacks.size(); i++) {
@@ -1649,6 +1653,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener {

    public void clearFingerprintRecognized() {
        mUserFingerprintAuthenticated.clear();
        mTrustManager.clearAllFingerprints();
    }

    public boolean isSimPinVoiceSecure() {
+39 −3
Original line number Diff line number Diff line
@@ -106,6 +106,7 @@ public class TrustManagerService extends SystemService {
    private static final int MSG_UNLOCK_USER = 11;
    private static final int MSG_STOP_USER = 12;
    private static final int MSG_DISPATCH_UNLOCK_LOCKOUT = 13;
    private static final int MSG_REFRESH_DEVICE_LOCKED_FOR_USER = 14;

    private static final int TRUST_USUALLY_MANAGED_FLUSH_DELAY = 2 * 60 * 1000;

@@ -125,9 +126,13 @@ public class TrustManagerService extends SystemService {
    @GuardedBy("mDeviceLockedForUser")
    private final SparseBooleanArray mDeviceLockedForUser = new SparseBooleanArray();

    @GuardedBy("mDeviceLockedForUser")
    @GuardedBy("mTrustUsuallyManagedForUser")
    private final SparseBooleanArray mTrustUsuallyManagedForUser = new SparseBooleanArray();

    // set to true only if user can skip bouncer
    @GuardedBy("mUsersUnlockedByFingerprint")
    private SparseBooleanArray mUsersUnlockedByFingerprint = new SparseBooleanArray();

    private final StrongAuthTracker mStrongAuthTracker;

    private boolean mTrustAgentsCanRun = false;
@@ -406,7 +411,6 @@ public class TrustManagerService extends SystemService {
                    + " must be USER_ALL or a specific user.", new Throwable("here"));
            userId = UserHandle.USER_ALL;
        }

        List<UserInfo> userInfos;
        if (userId == UserHandle.USER_ALL) {
            userInfos = mUserManager.getUsers(true /* excludeDying */);
@@ -429,13 +433,19 @@ public class TrustManagerService extends SystemService {
            boolean secure = mLockPatternUtils.isSecure(id);
            boolean trusted = aggregateIsTrusted(id);
            boolean showingKeyguard = true;
            boolean fingerprintAuthenticated = false;

            if (mCurrentUser == id) {
                synchronized(mUsersUnlockedByFingerprint) {
                    fingerprintAuthenticated = mUsersUnlockedByFingerprint.get(id, false);
                }
                try {
                    showingKeyguard = wm.isKeyguardLocked();
                } catch (RemoteException e) {
                }
            }
            boolean deviceLocked = secure && showingKeyguard && !trusted;
            boolean deviceLocked = secure && showingKeyguard && !trusted &&
                    !fingerprintAuthenticated;
            setDeviceLockedForUser(id, deviceLocked);
        }
    }
@@ -983,6 +993,26 @@ public class TrustManagerService extends SystemService {
                    "query trust state");
            return isTrustUsuallyManagedInternal(userId);
        }

        @Override
        public void unlockedByFingerprintForUser(int userId) {
            enforceReportPermission();
            synchronized(mUsersUnlockedByFingerprint) {
                mUsersUnlockedByFingerprint.put(userId, true);
            }
            mHandler.obtainMessage(MSG_REFRESH_DEVICE_LOCKED_FOR_USER, userId,
                    0 /* arg2 */).sendToTarget();
        }

        @Override
        public void clearAllFingerprints() {
            enforceReportPermission();
            synchronized(mUsersUnlockedByFingerprint) {
                mUsersUnlockedByFingerprint.clear();
            }
            mHandler.obtainMessage(MSG_REFRESH_DEVICE_LOCKED_FOR_USER, UserHandle.USER_ALL,
                    0 /* arg2 */).sendToTarget();
        }
    };

    private boolean isTrustUsuallyManagedInternal(int userId) {
@@ -1070,6 +1100,9 @@ public class TrustManagerService extends SystemService {
                        }
                    }
                    break;
                case MSG_REFRESH_DEVICE_LOCKED_FOR_USER:
                    refreshDeviceLockedForUser(msg.arg1);
                    break;
            }
        }
    };
@@ -1129,6 +1162,9 @@ public class TrustManagerService extends SystemService {
                    synchronized (mTrustUsuallyManagedForUser) {
                        mTrustUsuallyManagedForUser.delete(userId);
                    }
                    synchronized (mUsersUnlockedByFingerprint) {
                        mUsersUnlockedByFingerprint.delete(userId);
                    }
                    refreshAgentList(userId);
                    refreshDeviceLockedForUser(userId);
                }