Merge "Run biometric cleanup on user switch." into tm-dev
This commit is contained in:
@@ -268,4 +268,27 @@ public interface BiometricConstants {
|
|||||||
*/
|
*/
|
||||||
int BIOMETRIC_SYSTEM_EVENT_EARLY_USER_CANCEL = 1;
|
int BIOMETRIC_SYSTEM_EVENT_EARLY_USER_CANCEL = 1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* No lockout.
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
int BIOMETRIC_LOCKOUT_NONE = 0;
|
||||||
|
/**
|
||||||
|
* The biometric is in a temporary lockout state that will expire after some time.
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
int BIOMETRIC_LOCKOUT_TIMED = 1;
|
||||||
|
/**
|
||||||
|
* The biometric is locked out until a reset occurs. Resets are typically triggered by
|
||||||
|
* successfully authenticating via a stronger method than the one that is locked out.
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
int BIOMETRIC_LOCKOUT_PERMANENT = 2;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
@Retention(RetentionPolicy.SOURCE)
|
||||||
|
@IntDef({BIOMETRIC_LOCKOUT_NONE, BIOMETRIC_LOCKOUT_TIMED, BIOMETRIC_LOCKOUT_PERMANENT})
|
||||||
|
@interface LockoutMode {}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ package android.hardware.face;
|
|||||||
import static android.Manifest.permission.INTERACT_ACROSS_USERS;
|
import static android.Manifest.permission.INTERACT_ACROSS_USERS;
|
||||||
import static android.Manifest.permission.MANAGE_BIOMETRIC;
|
import static android.Manifest.permission.MANAGE_BIOMETRIC;
|
||||||
import static android.Manifest.permission.USE_BIOMETRIC_INTERNAL;
|
import static android.Manifest.permission.USE_BIOMETRIC_INTERNAL;
|
||||||
|
import static android.hardware.biometrics.BiometricConstants.BIOMETRIC_LOCKOUT_NONE;
|
||||||
|
|
||||||
import android.annotation.NonNull;
|
import android.annotation.NonNull;
|
||||||
import android.annotation.Nullable;
|
import android.annotation.Nullable;
|
||||||
@@ -672,6 +673,22 @@ public class FaceManager implements BiometricAuthenticator, BiometricFaceConstan
|
|||||||
return new ArrayList<>();
|
return new ArrayList<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
@RequiresPermission(USE_BIOMETRIC_INTERNAL)
|
||||||
|
@BiometricConstants.LockoutMode
|
||||||
|
public int getLockoutModeForUser(int sensorId, int userId) {
|
||||||
|
if (mService != null) {
|
||||||
|
try {
|
||||||
|
return mService.getLockoutModeForUser(sensorId, userId);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
e.rethrowFromSystemServer();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return BIOMETRIC_LOCKOUT_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ import static android.Manifest.permission.TEST_BIOMETRIC;
|
|||||||
import static android.Manifest.permission.USE_BIOMETRIC;
|
import static android.Manifest.permission.USE_BIOMETRIC;
|
||||||
import static android.Manifest.permission.USE_BIOMETRIC_INTERNAL;
|
import static android.Manifest.permission.USE_BIOMETRIC_INTERNAL;
|
||||||
import static android.Manifest.permission.USE_FINGERPRINT;
|
import static android.Manifest.permission.USE_FINGERPRINT;
|
||||||
|
import static android.hardware.biometrics.BiometricConstants.BIOMETRIC_LOCKOUT_NONE;
|
||||||
import static android.hardware.fingerprint.FingerprintSensorProperties.TYPE_POWER_BUTTON;
|
import static android.hardware.fingerprint.FingerprintSensorProperties.TYPE_POWER_BUTTON;
|
||||||
|
|
||||||
import static com.android.internal.util.FrameworkStatsLog.AUTH_DEPRECATED_APIUSED__DEPRECATED_API__API_FINGERPRINT_MANAGER_AUTHENTICATE;
|
import static com.android.internal.util.FrameworkStatsLog.AUTH_DEPRECATED_APIUSED__DEPRECATED_API__API_FINGERPRINT_MANAGER_AUTHENTICATE;
|
||||||
@@ -41,6 +42,7 @@ import android.compat.annotation.UnsupportedAppUsage;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.hardware.biometrics.BiometricAuthenticator;
|
import android.hardware.biometrics.BiometricAuthenticator;
|
||||||
|
import android.hardware.biometrics.BiometricConstants;
|
||||||
import android.hardware.biometrics.BiometricFingerprintConstants;
|
import android.hardware.biometrics.BiometricFingerprintConstants;
|
||||||
import android.hardware.biometrics.BiometricPrompt;
|
import android.hardware.biometrics.BiometricPrompt;
|
||||||
import android.hardware.biometrics.BiometricTestSession;
|
import android.hardware.biometrics.BiometricTestSession;
|
||||||
@@ -1094,6 +1096,22 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
@RequiresPermission(USE_BIOMETRIC_INTERNAL)
|
||||||
|
@BiometricConstants.LockoutMode
|
||||||
|
public int getLockoutModeForUser(int sensorId, int userId) {
|
||||||
|
if (mService != null) {
|
||||||
|
try {
|
||||||
|
return mService.getLockoutModeForUser(sensorId, userId);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
e.rethrowFromSystemServer();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return BIOMETRIC_LOCKOUT_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -21,6 +21,10 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
|
|||||||
import static android.content.Intent.ACTION_USER_REMOVED;
|
import static android.content.Intent.ACTION_USER_REMOVED;
|
||||||
import static android.content.Intent.ACTION_USER_STOPPED;
|
import static android.content.Intent.ACTION_USER_STOPPED;
|
||||||
import static android.content.Intent.ACTION_USER_UNLOCKED;
|
import static android.content.Intent.ACTION_USER_UNLOCKED;
|
||||||
|
import static android.hardware.biometrics.BiometricConstants.BIOMETRIC_LOCKOUT_NONE;
|
||||||
|
import static android.hardware.biometrics.BiometricConstants.BIOMETRIC_LOCKOUT_PERMANENT;
|
||||||
|
import static android.hardware.biometrics.BiometricConstants.BIOMETRIC_LOCKOUT_TIMED;
|
||||||
|
import static android.hardware.biometrics.BiometricConstants.LockoutMode;
|
||||||
import static android.os.BatteryManager.BATTERY_STATUS_UNKNOWN;
|
import static android.os.BatteryManager.BATTERY_STATUS_UNKNOWN;
|
||||||
|
|
||||||
import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_BOOT;
|
import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_BOOT;
|
||||||
@@ -61,6 +65,7 @@ import android.hardware.face.FaceSensorPropertiesInternal;
|
|||||||
import android.hardware.fingerprint.FingerprintManager;
|
import android.hardware.fingerprint.FingerprintManager;
|
||||||
import android.hardware.fingerprint.FingerprintManager.AuthenticationCallback;
|
import android.hardware.fingerprint.FingerprintManager.AuthenticationCallback;
|
||||||
import android.hardware.fingerprint.FingerprintManager.AuthenticationResult;
|
import android.hardware.fingerprint.FingerprintManager.AuthenticationResult;
|
||||||
|
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
|
||||||
import android.nfc.NfcAdapter;
|
import android.nfc.NfcAdapter;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.CancellationSignal;
|
import android.os.CancellationSignal;
|
||||||
@@ -865,10 +870,15 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleFingerprintLockoutReset() {
|
private void handleFingerprintLockoutReset(@LockoutMode int mode) {
|
||||||
boolean changed = mFingerprintLockedOut || mFingerprintLockedOutPermanent;
|
Log.d(TAG, "handleFingerprintLockoutReset: " + mode);
|
||||||
mFingerprintLockedOut = false;
|
final boolean wasLockout = mFingerprintLockedOut;
|
||||||
mFingerprintLockedOutPermanent = false;
|
final boolean wasLockoutPermanent = mFingerprintLockedOutPermanent;
|
||||||
|
mFingerprintLockedOut = (mode == BIOMETRIC_LOCKOUT_TIMED)
|
||||||
|
|| mode == BIOMETRIC_LOCKOUT_PERMANENT;
|
||||||
|
mFingerprintLockedOutPermanent = (mode == BIOMETRIC_LOCKOUT_PERMANENT);
|
||||||
|
final boolean changed = (mFingerprintLockedOut != wasLockout)
|
||||||
|
|| (mFingerprintLockedOutPermanent != wasLockoutPermanent);
|
||||||
|
|
||||||
if (isUdfpsEnrolled()) {
|
if (isUdfpsEnrolled()) {
|
||||||
// TODO(b/194825098): update the reset signal(s)
|
// TODO(b/194825098): update the reset signal(s)
|
||||||
@@ -878,7 +888,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
|
|||||||
// be noticeable.
|
// be noticeable.
|
||||||
mHandler.postDelayed(() -> {
|
mHandler.postDelayed(() -> {
|
||||||
updateFingerprintListeningState(BIOMETRIC_ACTION_UPDATE);
|
updateFingerprintListeningState(BIOMETRIC_ACTION_UPDATE);
|
||||||
}, BIOMETRIC_LOCKOUT_RESET_DELAY_MS);
|
}, getBiometricLockoutDelay());
|
||||||
} else {
|
} else {
|
||||||
updateFingerprintListeningState(BIOMETRIC_ACTION_UPDATE);
|
updateFingerprintListeningState(BIOMETRIC_ACTION_UPDATE);
|
||||||
}
|
}
|
||||||
@@ -1076,13 +1086,15 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleFaceLockoutReset() {
|
private void handleFaceLockoutReset(@LockoutMode int mode) {
|
||||||
boolean changed = mFaceLockedOutPermanent;
|
Log.d(TAG, "handleFaceLockoutReset: " + mode);
|
||||||
mFaceLockedOutPermanent = false;
|
final boolean wasLockoutPermanent = mFaceLockedOutPermanent;
|
||||||
|
mFaceLockedOutPermanent = (mode == BIOMETRIC_LOCKOUT_PERMANENT);
|
||||||
|
final boolean changed = (mFaceLockedOutPermanent != wasLockoutPermanent);
|
||||||
|
|
||||||
mHandler.postDelayed(() -> {
|
mHandler.postDelayed(() -> {
|
||||||
updateFaceListeningState(BIOMETRIC_ACTION_UPDATE);
|
updateFaceListeningState(BIOMETRIC_ACTION_UPDATE);
|
||||||
}, BIOMETRIC_LOCKOUT_RESET_DELAY_MS);
|
}, getBiometricLockoutDelay());
|
||||||
|
|
||||||
if (changed) {
|
if (changed) {
|
||||||
notifyLockedOutStateChanged(BiometricSourceType.FACE);
|
notifyLockedOutStateChanged(BiometricSourceType.FACE);
|
||||||
@@ -1462,7 +1474,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
|
|||||||
= new FingerprintManager.LockoutResetCallback() {
|
= new FingerprintManager.LockoutResetCallback() {
|
||||||
@Override
|
@Override
|
||||||
public void onLockoutReset(int sensorId) {
|
public void onLockoutReset(int sensorId) {
|
||||||
handleFingerprintLockoutReset();
|
handleFingerprintLockoutReset(BIOMETRIC_LOCKOUT_NONE);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1470,7 +1482,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
|
|||||||
= new FaceManager.LockoutResetCallback() {
|
= new FaceManager.LockoutResetCallback() {
|
||||||
@Override
|
@Override
|
||||||
public void onLockoutReset(int sensorId) {
|
public void onLockoutReset(int sensorId) {
|
||||||
handleFaceLockoutReset();
|
handleFaceLockoutReset(BIOMETRIC_LOCKOUT_NONE);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1580,10 +1592,13 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
private CancellationSignal mFingerprintCancelSignal;
|
@VisibleForTesting
|
||||||
private CancellationSignal mFaceCancelSignal;
|
CancellationSignal mFingerprintCancelSignal;
|
||||||
|
@VisibleForTesting
|
||||||
|
CancellationSignal mFaceCancelSignal;
|
||||||
private FingerprintManager mFpm;
|
private FingerprintManager mFpm;
|
||||||
private FaceManager mFaceManager;
|
private FaceManager mFaceManager;
|
||||||
|
private List<FingerprintSensorPropertiesInternal> mFingerprintSensorProperties;
|
||||||
private List<FaceSensorPropertiesInternal> mFaceSensorProperties;
|
private List<FaceSensorPropertiesInternal> mFaceSensorProperties;
|
||||||
private boolean mFingerprintLockedOut;
|
private boolean mFingerprintLockedOut;
|
||||||
private boolean mFingerprintLockedOutPermanent;
|
private boolean mFingerprintLockedOutPermanent;
|
||||||
@@ -2018,6 +2033,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
|
|||||||
|
|
||||||
if (mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_FINGERPRINT)) {
|
if (mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_FINGERPRINT)) {
|
||||||
mFpm = (FingerprintManager) context.getSystemService(Context.FINGERPRINT_SERVICE);
|
mFpm = (FingerprintManager) context.getSystemService(Context.FINGERPRINT_SERVICE);
|
||||||
|
mFingerprintSensorProperties = mFpm.getSensorPropertiesInternal();
|
||||||
}
|
}
|
||||||
if (mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_FACE)) {
|
if (mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_FACE)) {
|
||||||
mFaceManager = (FaceManager) context.getSystemService(Context.FACE_SERVICE);
|
mFaceManager = (FaceManager) context.getSystemService(Context.FACE_SERVICE);
|
||||||
@@ -2382,11 +2398,10 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
|
|||||||
final boolean shouldListenUdfpsState = !isUdfps
|
final boolean shouldListenUdfpsState = !isUdfps
|
||||||
|| (!userCanSkipBouncer
|
|| (!userCanSkipBouncer
|
||||||
&& !isEncryptedOrLockdownForUser
|
&& !isEncryptedOrLockdownForUser
|
||||||
&& userDoesNotHaveTrust
|
&& userDoesNotHaveTrust);
|
||||||
&& !mFingerprintLockedOut);
|
|
||||||
|
|
||||||
final boolean shouldListen = shouldListenKeyguardState && shouldListenUserState
|
final boolean shouldListen = shouldListenKeyguardState && shouldListenUserState
|
||||||
&& shouldListenBouncerState && shouldListenUdfpsState;
|
&& shouldListenBouncerState && shouldListenUdfpsState && !isFingerprintLockedOut();
|
||||||
|
|
||||||
if (DEBUG_FINGERPRINT || DEBUG_SPEW) {
|
if (DEBUG_FINGERPRINT || DEBUG_SPEW) {
|
||||||
maybeLogListenerModelData(
|
maybeLogListenerModelData(
|
||||||
@@ -2773,6 +2788,16 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
|
|||||||
cb.onUserSwitchComplete(userId);
|
cb.onUserSwitchComplete(userId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (mFaceManager != null && !mFaceSensorProperties.isEmpty()) {
|
||||||
|
handleFaceLockoutReset(mFaceManager.getLockoutModeForUser(
|
||||||
|
mFaceSensorProperties.get(0).sensorId, userId));
|
||||||
|
}
|
||||||
|
if (mFpm != null && !mFingerprintSensorProperties.isEmpty()) {
|
||||||
|
handleFingerprintLockoutReset(mFpm.getLockoutModeForUser(
|
||||||
|
mFingerprintSensorProperties.get(0).sensorId, userId));
|
||||||
|
}
|
||||||
|
|
||||||
mInteractionJankMonitor.end(InteractionJankMonitor.CUJ_USER_SWITCH);
|
mInteractionJankMonitor.end(InteractionJankMonitor.CUJ_USER_SWITCH);
|
||||||
mLatencyTracker.onActionEnd(LatencyTracker.ACTION_USER_SWITCH);
|
mLatencyTracker.onActionEnd(LatencyTracker.ACTION_USER_SWITCH);
|
||||||
}
|
}
|
||||||
@@ -3508,6 +3533,10 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected int getBiometricLockoutDelay() {
|
||||||
|
return BIOMETRIC_LOCKOUT_RESET_DELAY_MS;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unregister all listeners.
|
* Unregister all listeners.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -35,10 +35,12 @@ import static org.mockito.Mockito.doAnswer;
|
|||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
import static org.mockito.Mockito.never;
|
import static org.mockito.Mockito.never;
|
||||||
import static org.mockito.Mockito.spy;
|
import static org.mockito.Mockito.spy;
|
||||||
|
import static org.mockito.Mockito.times;
|
||||||
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.verify;
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
|
import android.app.ActivityManager;
|
||||||
import android.app.admin.DevicePolicyManager;
|
import android.app.admin.DevicePolicyManager;
|
||||||
import android.app.trust.IStrongAuthTracker;
|
import android.app.trust.IStrongAuthTracker;
|
||||||
import android.app.trust.TrustManager;
|
import android.app.trust.TrustManager;
|
||||||
@@ -50,15 +52,20 @@ import android.content.IntentFilter;
|
|||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.content.pm.ResolveInfo;
|
import android.content.pm.ResolveInfo;
|
||||||
import android.content.pm.ServiceInfo;
|
import android.content.pm.ServiceInfo;
|
||||||
|
import android.hardware.biometrics.BiometricConstants;
|
||||||
import android.hardware.biometrics.BiometricManager;
|
import android.hardware.biometrics.BiometricManager;
|
||||||
|
import android.hardware.biometrics.BiometricSourceType;
|
||||||
import android.hardware.biometrics.ComponentInfoInternal;
|
import android.hardware.biometrics.ComponentInfoInternal;
|
||||||
import android.hardware.biometrics.IBiometricEnabledOnKeyguardCallback;
|
import android.hardware.biometrics.IBiometricEnabledOnKeyguardCallback;
|
||||||
import android.hardware.face.FaceManager;
|
import android.hardware.face.FaceManager;
|
||||||
import android.hardware.face.FaceSensorProperties;
|
import android.hardware.face.FaceSensorProperties;
|
||||||
import android.hardware.face.FaceSensorPropertiesInternal;
|
import android.hardware.face.FaceSensorPropertiesInternal;
|
||||||
import android.hardware.fingerprint.FingerprintManager;
|
import android.hardware.fingerprint.FingerprintManager;
|
||||||
|
import android.hardware.fingerprint.FingerprintSensorProperties;
|
||||||
|
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
|
||||||
import android.nfc.NfcAdapter;
|
import android.nfc.NfcAdapter;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.os.CancellationSignal;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.os.IRemoteCallback;
|
import android.os.IRemoteCallback;
|
||||||
import android.os.UserHandle;
|
import android.os.UserHandle;
|
||||||
@@ -121,6 +128,9 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
|
|||||||
TEST_CARRIER, TEST_CARRIER_2, NAME_SOURCE_CARRIER_ID, 0xFFFFFF, "",
|
TEST_CARRIER, TEST_CARRIER_2, NAME_SOURCE_CARRIER_ID, 0xFFFFFF, "",
|
||||||
DATA_ROAMING_DISABLE, null, null, null, null, false, null, "", true, TEST_GROUP_UUID,
|
DATA_ROAMING_DISABLE, null, null, null, null, false, null, "", true, TEST_GROUP_UUID,
|
||||||
TEST_CARRIER_ID, 0);
|
TEST_CARRIER_ID, 0);
|
||||||
|
private static final int FACE_SENSOR_ID = 0;
|
||||||
|
private static final int FINGERPRINT_SENSOR_ID = 1;
|
||||||
|
|
||||||
@Mock
|
@Mock
|
||||||
private DumpManager mDumpManager;
|
private DumpManager mDumpManager;
|
||||||
@Mock
|
@Mock
|
||||||
@@ -212,6 +222,16 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
|
|||||||
|
|
||||||
when(mFingerprintManager.isHardwareDetected()).thenReturn(true);
|
when(mFingerprintManager.isHardwareDetected()).thenReturn(true);
|
||||||
when(mFingerprintManager.hasEnrolledTemplates(anyInt())).thenReturn(true);
|
when(mFingerprintManager.hasEnrolledTemplates(anyInt())).thenReturn(true);
|
||||||
|
when(mFingerprintManager.getSensorPropertiesInternal()).thenReturn(List.of(
|
||||||
|
new FingerprintSensorPropertiesInternal(1 /* sensorId */,
|
||||||
|
FingerprintSensorProperties.STRENGTH_STRONG,
|
||||||
|
1 /* maxEnrollmentsPerUser */,
|
||||||
|
List.of(new ComponentInfoInternal("fingerprintSensor" /* componentId */,
|
||||||
|
"vendor/model/revision" /* hardwareVersion */,
|
||||||
|
"1.01" /* firmwareVersion */,
|
||||||
|
"00000001" /* serialNumber */, "" /* softwareVersion */)),
|
||||||
|
FingerprintSensorProperties.TYPE_UDFPS_OPTICAL,
|
||||||
|
false /* resetLockoutRequiresHAT */)));
|
||||||
when(mUserManager.isUserUnlocked(anyInt())).thenReturn(true);
|
when(mUserManager.isUserUnlocked(anyInt())).thenReturn(true);
|
||||||
when(mUserManager.isPrimaryUser()).thenReturn(true);
|
when(mUserManager.isPrimaryUser()).thenReturn(true);
|
||||||
when(mStrongAuthTracker.getStub()).thenReturn(mock(IStrongAuthTracker.Stub.class));
|
when(mStrongAuthTracker.getStub()).thenReturn(mock(IStrongAuthTracker.Stub.class));
|
||||||
@@ -232,9 +252,13 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
|
|||||||
mSpiedContext.addMockSystemService(TelephonyManager.class, mTelephonyManager);
|
mSpiedContext.addMockSystemService(TelephonyManager.class, mTelephonyManager);
|
||||||
|
|
||||||
mMockitoSession = ExtendedMockito.mockitoSession()
|
mMockitoSession = ExtendedMockito.mockitoSession()
|
||||||
.spyStatic(SubscriptionManager.class).startMocking();
|
.spyStatic(SubscriptionManager.class)
|
||||||
|
.spyStatic(ActivityManager.class)
|
||||||
|
.startMocking();
|
||||||
ExtendedMockito.doReturn(SubscriptionManager.INVALID_SUBSCRIPTION_ID)
|
ExtendedMockito.doReturn(SubscriptionManager.INVALID_SUBSCRIPTION_ID)
|
||||||
.when(SubscriptionManager::getDefaultSubscriptionId);
|
.when(SubscriptionManager::getDefaultSubscriptionId);
|
||||||
|
ExtendedMockito.doReturn(KeyguardUpdateMonitor.getCurrentUser())
|
||||||
|
.when(ActivityManager::getCurrentUser);
|
||||||
|
|
||||||
mTestableLooper = TestableLooper.get(this);
|
mTestableLooper = TestableLooper.get(this);
|
||||||
allowTestableLooperAsMainThread();
|
allowTestableLooperAsMainThread();
|
||||||
@@ -765,6 +789,59 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
|
|||||||
verify(mLatencyTracker).onActionEnd(LatencyTracker.ACTION_USER_SWITCH);
|
verify(mLatencyTracker).onActionEnd(LatencyTracker.ACTION_USER_SWITCH);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMultiUserLockoutChanged_whenUserSwitches() {
|
||||||
|
testMultiUserLockout_whenUserSwitches(BiometricConstants.BIOMETRIC_LOCKOUT_PERMANENT,
|
||||||
|
BiometricConstants.BIOMETRIC_LOCKOUT_PERMANENT);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMultiUserLockoutNotChanged_whenUserSwitches() {
|
||||||
|
testMultiUserLockout_whenUserSwitches(BiometricConstants.BIOMETRIC_LOCKOUT_NONE,
|
||||||
|
BiometricConstants.BIOMETRIC_LOCKOUT_NONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void testMultiUserLockout_whenUserSwitches(
|
||||||
|
@BiometricConstants.LockoutMode int fingerprintLockoutMode,
|
||||||
|
@BiometricConstants.LockoutMode int faceLockoutMode) {
|
||||||
|
final int newUser = 12;
|
||||||
|
final boolean faceLocked =
|
||||||
|
faceLockoutMode != BiometricConstants.BIOMETRIC_LOCKOUT_NONE;
|
||||||
|
final boolean fpLocked =
|
||||||
|
fingerprintLockoutMode != BiometricConstants.BIOMETRIC_LOCKOUT_NONE;
|
||||||
|
when(mFingerprintManager.getLockoutModeForUser(eq(FINGERPRINT_SENSOR_ID), eq(newUser)))
|
||||||
|
.thenReturn(fingerprintLockoutMode);
|
||||||
|
when(mFaceManager.getLockoutModeForUser(eq(FACE_SENSOR_ID), eq(newUser)))
|
||||||
|
.thenReturn(faceLockoutMode);
|
||||||
|
|
||||||
|
mKeyguardUpdateMonitor.dispatchStartedWakingUp();
|
||||||
|
mTestableLooper.processAllMessages();
|
||||||
|
mKeyguardUpdateMonitor.onKeyguardVisibilityChanged(true);
|
||||||
|
|
||||||
|
verify(mFaceManager).authenticate(any(), any(), any(), any(), anyInt(), anyBoolean());
|
||||||
|
verify(mFingerprintManager).authenticate(any(), any(), any(), any(), anyInt(), anyInt(),
|
||||||
|
anyInt());
|
||||||
|
|
||||||
|
final CancellationSignal faceCancel = spy(mKeyguardUpdateMonitor.mFaceCancelSignal);
|
||||||
|
final CancellationSignal fpCancel = spy(mKeyguardUpdateMonitor.mFingerprintCancelSignal);
|
||||||
|
mKeyguardUpdateMonitor.mFaceCancelSignal = faceCancel;
|
||||||
|
mKeyguardUpdateMonitor.mFingerprintCancelSignal = fpCancel;
|
||||||
|
KeyguardUpdateMonitorCallback callback = mock(KeyguardUpdateMonitorCallback.class);
|
||||||
|
mKeyguardUpdateMonitor.registerCallback(callback);
|
||||||
|
|
||||||
|
mKeyguardUpdateMonitor.handleUserSwitchComplete(newUser);
|
||||||
|
mTestableLooper.processAllMessages();
|
||||||
|
|
||||||
|
verify(faceCancel, faceLocked ? times(1) : never()).cancel();
|
||||||
|
verify(fpCancel, fpLocked ? times(1) : never()).cancel();
|
||||||
|
verify(callback, faceLocked ? times(1) : never()).onBiometricRunningStateChanged(
|
||||||
|
eq(false), eq(BiometricSourceType.FACE));
|
||||||
|
verify(callback, fpLocked ? times(1) : never()).onBiometricRunningStateChanged(
|
||||||
|
eq(false), eq(BiometricSourceType.FINGERPRINT));
|
||||||
|
assertThat(mKeyguardUpdateMonitor.isFingerprintLockedOut()).isEqualTo(fpLocked);
|
||||||
|
assertThat(mKeyguardUpdateMonitor.isFaceLockedOut()).isEqualTo(faceLocked);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGetUserCanSkipBouncer_whenTrust() {
|
public void testGetUserCanSkipBouncer_whenTrust() {
|
||||||
int user = KeyguardUpdateMonitor.getCurrentUser();
|
int user = KeyguardUpdateMonitor.getCurrentUser();
|
||||||
@@ -1124,5 +1201,10 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
|
|||||||
mSimStateChanged.set(true);
|
mSimStateChanged.set(true);
|
||||||
super.handleSimStateChange(subId, slotId, state);
|
super.handleSimStateChange(subId, slotId, state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected int getBiometricLockoutDelay() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,12 +16,14 @@
|
|||||||
|
|
||||||
package com.android.server.biometrics.sensors;
|
package com.android.server.biometrics.sensors;
|
||||||
|
|
||||||
|
import android.util.Slog;
|
||||||
import android.util.SparseIntArray;
|
import android.util.SparseIntArray;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* For a single sensor, caches lockout states for all users.
|
* For a single sensor, caches lockout states for all users.
|
||||||
*/
|
*/
|
||||||
public class LockoutCache implements LockoutTracker {
|
public class LockoutCache implements LockoutTracker {
|
||||||
|
private static final String TAG = "LockoutCache";
|
||||||
|
|
||||||
// Map of userId to LockoutMode
|
// Map of userId to LockoutMode
|
||||||
private final SparseIntArray mUserLockoutStates;
|
private final SparseIntArray mUserLockoutStates;
|
||||||
@@ -31,6 +33,7 @@ public class LockoutCache implements LockoutTracker {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void setLockoutModeForUser(int userId, @LockoutMode int mode) {
|
public void setLockoutModeForUser(int userId, @LockoutMode int mode) {
|
||||||
|
Slog.d(TAG, "Lockout for user: " + userId + " is " + mode);
|
||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
mUserLockoutStates.put(userId, mode);
|
mUserLockoutStates.put(userId, mode);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
package com.android.server.biometrics.sensors;
|
package com.android.server.biometrics.sensors;
|
||||||
|
|
||||||
import android.annotation.IntDef;
|
import android.annotation.IntDef;
|
||||||
|
import android.hardware.biometrics.BiometricConstants;
|
||||||
|
|
||||||
import java.lang.annotation.Retention;
|
import java.lang.annotation.Retention;
|
||||||
import java.lang.annotation.RetentionPolicy;
|
import java.lang.annotation.RetentionPolicy;
|
||||||
@@ -25,9 +26,9 @@ import java.lang.annotation.RetentionPolicy;
|
|||||||
* Interface for retrieval of current user's lockout state.
|
* Interface for retrieval of current user's lockout state.
|
||||||
*/
|
*/
|
||||||
public interface LockoutTracker {
|
public interface LockoutTracker {
|
||||||
int LOCKOUT_NONE = 0;
|
int LOCKOUT_NONE = BiometricConstants.BIOMETRIC_LOCKOUT_NONE;
|
||||||
int LOCKOUT_TIMED = 1;
|
int LOCKOUT_TIMED = BiometricConstants.BIOMETRIC_LOCKOUT_TIMED;
|
||||||
int LOCKOUT_PERMANENT = 2;
|
int LOCKOUT_PERMANENT = BiometricConstants.BIOMETRIC_LOCKOUT_PERMANENT;
|
||||||
|
|
||||||
@Retention(RetentionPolicy.SOURCE)
|
@Retention(RetentionPolicy.SOURCE)
|
||||||
@IntDef({LOCKOUT_NONE, LOCKOUT_TIMED, LOCKOUT_PERMANENT})
|
@IntDef({LOCKOUT_NONE, LOCKOUT_TIMED, LOCKOUT_PERMANENT})
|
||||||
|
|||||||
@@ -18,6 +18,9 @@ package com.android.server.biometrics.sensors.face.aidl;
|
|||||||
|
|
||||||
import android.annotation.NonNull;
|
import android.annotation.NonNull;
|
||||||
import android.annotation.Nullable;
|
import android.annotation.Nullable;
|
||||||
|
import android.app.ActivityManager;
|
||||||
|
import android.app.SynchronousUserSwitchObserver;
|
||||||
|
import android.app.UserSwitchObserver;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.pm.UserInfo;
|
import android.content.pm.UserInfo;
|
||||||
import android.hardware.biometrics.BiometricsProtoEnums;
|
import android.hardware.biometrics.BiometricsProtoEnums;
|
||||||
@@ -91,6 +94,14 @@ public class Sensor {
|
|||||||
@NonNull private final Supplier<AidlSession> mLazySession;
|
@NonNull private final Supplier<AidlSession> mLazySession;
|
||||||
@Nullable private AidlSession mCurrentSession;
|
@Nullable private AidlSession mCurrentSession;
|
||||||
|
|
||||||
|
private final UserSwitchObserver mUserSwitchObserver = new SynchronousUserSwitchObserver() {
|
||||||
|
@Override
|
||||||
|
public void onUserSwitching(int newUserId) {
|
||||||
|
mProvider.scheduleInternalCleanup(
|
||||||
|
mSensorProperties.sensorId, newUserId, null /* callback */);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
public static class HalSessionCallback extends ISessionCallback.Stub {
|
public static class HalSessionCallback extends ISessionCallback.Stub {
|
||||||
/**
|
/**
|
||||||
@@ -537,6 +548,12 @@ public class Sensor {
|
|||||||
mLockoutCache = new LockoutCache();
|
mLockoutCache = new LockoutCache();
|
||||||
mAuthenticatorIds = new HashMap<>();
|
mAuthenticatorIds = new HashMap<>();
|
||||||
mLazySession = () -> mCurrentSession != null ? mCurrentSession : null;
|
mLazySession = () -> mCurrentSession != null ? mCurrentSession : null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
ActivityManager.getService().registerUserSwitchObserver(mUserSwitchObserver, mTag);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
Slog.e(mTag, "Unable to register user switch observer");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@NonNull Supplier<AidlSession> getLazySession() {
|
@NonNull Supplier<AidlSession> getLazySession() {
|
||||||
|
|||||||
@@ -18,6 +18,9 @@ package com.android.server.biometrics.sensors.fingerprint.aidl;
|
|||||||
|
|
||||||
import android.annotation.NonNull;
|
import android.annotation.NonNull;
|
||||||
import android.annotation.Nullable;
|
import android.annotation.Nullable;
|
||||||
|
import android.app.ActivityManager;
|
||||||
|
import android.app.SynchronousUserSwitchObserver;
|
||||||
|
import android.app.UserSwitchObserver;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.pm.UserInfo;
|
import android.content.pm.UserInfo;
|
||||||
import android.hardware.biometrics.BiometricsProtoEnums;
|
import android.hardware.biometrics.BiometricsProtoEnums;
|
||||||
@@ -92,6 +95,14 @@ public class Sensor {
|
|||||||
@Nullable private AidlSession mCurrentSession;
|
@Nullable private AidlSession mCurrentSession;
|
||||||
@NonNull private final Supplier<AidlSession> mLazySession;
|
@NonNull private final Supplier<AidlSession> mLazySession;
|
||||||
|
|
||||||
|
private final UserSwitchObserver mUserSwitchObserver = new SynchronousUserSwitchObserver() {
|
||||||
|
@Override
|
||||||
|
public void onUserSwitching(int newUserId) {
|
||||||
|
mProvider.scheduleInternalCleanup(
|
||||||
|
mSensorProperties.sensorId, newUserId, null /* callback */);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
public static class HalSessionCallback extends ISessionCallback.Stub {
|
public static class HalSessionCallback extends ISessionCallback.Stub {
|
||||||
|
|
||||||
@@ -491,6 +502,12 @@ public class Sensor {
|
|||||||
});
|
});
|
||||||
mAuthenticatorIds = new HashMap<>();
|
mAuthenticatorIds = new HashMap<>();
|
||||||
mLazySession = () -> mCurrentSession != null ? mCurrentSession : null;
|
mLazySession = () -> mCurrentSession != null ? mCurrentSession : null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
ActivityManager.getService().registerUserSwitchObserver(mUserSwitchObserver, mTag);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
Slog.e(mTag, "Unable to register user switch observer");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@NonNull Supplier<AidlSession> getLazySession() {
|
@NonNull Supplier<AidlSession> getLazySession() {
|
||||||
|
|||||||
Reference in New Issue
Block a user