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
This commit is contained in:
Joe Bolinger
2022-01-05 20:54:50 +00:00
parent 0917ecb080
commit 2f458df6f7
5 changed files with 51 additions and 17 deletions

View File

@@ -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);
}

View File

@@ -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();
}

View File

@@ -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();

View File

@@ -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();
}

View File

@@ -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;
}
boolean deviceLocked = secure && showingKeyguard && !trusted &&
!biometricAuthenticated;
final boolean deviceLocked = secure && showingKeyguard && !trusted
&& !biometricAuthenticated;
if (deviceLocked && currentUserIsUnlocked) {
// keyguard is finishing but may not have completed going away yet
continue;
}
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);