Merge "Change string resource for face not detected error" into qt-r1-dev
diff --git a/core/java/android/hardware/face/FaceManager.java b/core/java/android/hardware/face/FaceManager.java
index c8f0e09..12b285a 100644
--- a/core/java/android/hardware/face/FaceManager.java
+++ b/core/java/android/hardware/face/FaceManager.java
@@ -262,7 +262,7 @@
* @hide
*/
@RequiresPermission(MANAGE_BIOMETRIC)
- public void enroll(byte[] token, CancellationSignal cancel,
+ public void enroll(int userId, byte[] token, CancellationSignal cancel,
EnrollmentCallback callback, int[] disabledFeatures) {
if (callback == null) {
throw new IllegalArgumentException("Must supply an enrollment callback");
@@ -281,7 +281,7 @@
try {
mEnrollmentCallback = callback;
Trace.beginSection("FaceManager#enroll");
- mService.enroll(mToken, token, mServiceReceiver,
+ mService.enroll(userId, mToken, token, mServiceReceiver,
mContext.getOpPackageName(), disabledFeatures);
} catch (RemoteException e) {
Log.w(TAG, "Remote exception in enroll: ", e);
@@ -339,12 +339,13 @@
* @hide
*/
@RequiresPermission(MANAGE_BIOMETRIC)
- public void setFeature(int feature, boolean enabled, byte[] token,
+ public void setFeature(int userId, int feature, boolean enabled, byte[] token,
SetFeatureCallback callback) {
if (mService != null) {
try {
mSetFeatureCallback = callback;
- mService.setFeature(feature, enabled, token, mServiceReceiver);
+ mService.setFeature(userId, feature, enabled, token, mServiceReceiver,
+ mContext.getOpPackageName());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -355,11 +356,11 @@
* @hide
*/
@RequiresPermission(MANAGE_BIOMETRIC)
- public void getFeature(int feature, GetFeatureCallback callback) {
+ public void getFeature(int userId, int feature, GetFeatureCallback callback) {
if (mService != null) {
try {
mGetFeatureCallback = callback;
- mService.getFeature(feature, mServiceReceiver);
+ mService.getFeature(userId, feature, mServiceReceiver, mContext.getOpPackageName());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -414,7 +415,8 @@
try {
mRemovalCallback = callback;
mRemovalFace = face;
- mService.remove(mToken, face.getBiometricId(), userId, mServiceReceiver);
+ mService.remove(mToken, face.getBiometricId(), userId, mServiceReceiver,
+ mContext.getOpPackageName());
} catch (RemoteException e) {
Log.w(TAG, "Remote exception in remove: ", e);
if (callback != null) {
diff --git a/core/java/android/hardware/face/IFaceService.aidl b/core/java/android/hardware/face/IFaceService.aidl
index 601be75..b6a0afb 100644
--- a/core/java/android/hardware/face/IFaceService.aidl
+++ b/core/java/android/hardware/face/IFaceService.aidl
@@ -50,14 +50,15 @@
int callingUid, int callingPid, int callingUserId, boolean fromClient);
// Start face enrollment
- void enroll(IBinder token, in byte [] cryptoToken, IFaceServiceReceiver receiver,
+ void enroll(int userId, IBinder token, in byte [] cryptoToken, IFaceServiceReceiver receiver,
String opPackageName, in int [] disabledFeatures);
// Cancel enrollment in progress
void cancelEnrollment(IBinder token);
// Any errors resulting from this call will be returned to the listener
- void remove(IBinder token, int faceId, int userId, IFaceServiceReceiver receiver);
+ void remove(IBinder token, int faceId, int userId, IFaceServiceReceiver receiver,
+ String opPackageName);
// Rename the face specified by faceId to the given name
void rename(int faceId, String name);
@@ -98,10 +99,10 @@
// Enumerate all faces
void enumerate(IBinder token, int userId, IFaceServiceReceiver receiver);
- void setFeature(int feature, boolean enabled, in byte [] token,
- IFaceServiceReceiver receiver);
+ void setFeature(int userId, int feature, boolean enabled, in byte [] token,
+ IFaceServiceReceiver receiver, String opPackageName);
- void getFeature(int feature, IFaceServiceReceiver receiver);
+ void getFeature(int userId, int feature, IFaceServiceReceiver receiver, String opPackageName);
void userActivity();
}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index 0a834c8..05e14a7 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -30,6 +30,12 @@
import static android.os.BatteryManager.EXTRA_STATUS;
import static android.telephony.PhoneStateListener.LISTEN_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGE;
+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_DPM_LOCK_NOW;
+import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_LOCKOUT;
+import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_TIMEOUT;
+import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN;
+
import android.annotation.AnyThread;
import android.annotation.MainThread;
import android.app.ActivityManager;
@@ -672,8 +678,7 @@
}
if (msgId == FingerprintManager.FINGERPRINT_ERROR_LOCKOUT_PERMANENT) {
- mLockPatternUtils.requireStrongAuth(
- LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_LOCKOUT,
+ mLockPatternUtils.requireStrongAuth(STRONG_AUTH_REQUIRED_AFTER_LOCKOUT,
getCurrentUser());
}
@@ -833,8 +838,7 @@
}
if (msgId == FaceManager.FACE_ERROR_LOCKOUT_PERMANENT) {
- mLockPatternUtils.requireStrongAuth(
- LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_LOCKOUT,
+ mLockPatternUtils.requireStrongAuth(STRONG_AUTH_REQUIRED_AFTER_LOCKOUT,
getCurrentUser());
}
@@ -953,8 +957,8 @@
}
public boolean isUserInLockdown(int userId) {
- return mStrongAuthTracker.getStrongAuthForUser(userId)
- == LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN;
+ return containsFlag(mStrongAuthTracker.getStrongAuthForUser(userId),
+ STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN);
}
public boolean userNeedsStrongAuth() {
@@ -962,6 +966,10 @@
!= LockPatternUtils.StrongAuthTracker.STRONG_AUTH_NOT_REQUIRED;
}
+ private boolean containsFlag(int haystack, int needle) {
+ return (haystack & needle) != 0;
+ }
+
public boolean needsSlowUnlockTransition() {
return mNeedsSlowUnlockTransition;
}
@@ -1680,8 +1688,12 @@
final int user = getCurrentUser();
final int strongAuth = mStrongAuthTracker.getStrongAuthForUser(user);
final boolean isLockOutOrLockDown =
- strongAuth == StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_LOCKOUT
- || strongAuth == StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN;
+ containsFlag(strongAuth, STRONG_AUTH_REQUIRED_AFTER_LOCKOUT)
+ || containsFlag(strongAuth, STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW)
+ || containsFlag(strongAuth, STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN);
+ final boolean isEncryptedOrTimedOut =
+ containsFlag(strongAuth, STRONG_AUTH_REQUIRED_AFTER_BOOT)
+ || containsFlag(strongAuth, STRONG_AUTH_REQUIRED_AFTER_TIMEOUT);
boolean canBypass = mKeyguardBypassController != null
&& mKeyguardBypassController.canBypass();
@@ -1690,13 +1702,18 @@
// TrustAgents or biometrics are keeping the device unlocked.
boolean becauseCannotSkipBouncer = !getUserCanSkipBouncer(user) || canBypass;
+ // Scan even when encrypted or timeout to show a preemptive bouncer when bypassing.
+ // Lockout/lockdown modes shouldn't scan, since they are more explicit.
+ boolean strongAuthAllowsScanning = (!isEncryptedOrTimedOut || canBypass && !mBouncer)
+ && !isLockOutOrLockDown;
+
// Only listen if this KeyguardUpdateMonitor belongs to the primary user. There is an
// instance of KeyguardUpdateMonitor for each user but KeyguardUpdateMonitor is user-aware.
return (mBouncer || mAuthInterruptActive || awakeKeyguard || shouldListenForFaceAssistant())
&& !mSwitchingUser && !isFaceDisabled(user) && becauseCannotSkipBouncer
&& !mKeyguardGoingAway && mFaceSettingEnabledForUser && !mLockIconPressed
- && mUserManager.isUserUnlocked(user) && mIsPrimaryUser
- && !mSecureCameraLaunched && !isLockOutOrLockDown;
+ && strongAuthAllowsScanning && mIsPrimaryUser
+ && !mSecureCameraLaunched;
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
index fdf18e0..e6a88b1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
@@ -410,7 +410,7 @@
} else if (unlockingAllowed) {
return faceStayingOnKeyguard ? MODE_ONLY_WAKE : MODE_UNLOCK;
} else if (face) {
- return MODE_NONE;
+ return faceStayingOnKeyguard ? MODE_NONE : MODE_SHOW_BOUNCER;
} else if (!mStatusBarKeyguardViewManager.isBouncerShowing()) {
return MODE_SHOW_BOUNCER;
}
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
index 2e02fd5..bdc6341 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
@@ -21,6 +21,7 @@
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
@@ -317,13 +318,44 @@
@Test
public void skipsAuthentication_whenEncryptedKeyguard() {
- reset(mUserManager);
- when(mUserManager.isUserUnlocked(anyInt())).thenReturn(false);
+ when(mStrongAuthTracker.getStrongAuthForUser(anyInt())).thenReturn(
+ KeyguardUpdateMonitor.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_BOOT);
+ mKeyguardUpdateMonitor.setKeyguardBypassController(mKeyguardBypassController);
mKeyguardUpdateMonitor.dispatchStartedWakingUp();
mTestableLooper.processAllMessages();
mKeyguardUpdateMonitor.onKeyguardVisibilityChanged(true);
- verify(mFaceManager, never()).authenticate(any(), any(), anyInt(), any(), any());
+ verify(mFaceManager, never()).authenticate(any(), any(), anyInt(), any(), any(), anyInt());
+ }
+
+ @Test
+ public void requiresAuthentication_whenEncryptedKeyguard_andBypass() {
+ testStrongAuthExceptOnBouncer(
+ KeyguardUpdateMonitor.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_BOOT);
+ }
+
+ @Test
+ public void requiresAuthentication_whenTimeoutKeyguard_andBypass() {
+ testStrongAuthExceptOnBouncer(
+ KeyguardUpdateMonitor.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_TIMEOUT);
+ }
+
+ private void testStrongAuthExceptOnBouncer(int strongAuth) {
+ when(mKeyguardBypassController.canBypass()).thenReturn(true);
+ mKeyguardUpdateMonitor.setKeyguardBypassController(mKeyguardBypassController);
+ when(mStrongAuthTracker.getStrongAuthForUser(anyInt())).thenReturn(strongAuth);
+
+ mKeyguardUpdateMonitor.dispatchStartedWakingUp();
+ mTestableLooper.processAllMessages();
+ mKeyguardUpdateMonitor.onKeyguardVisibilityChanged(true);
+ verify(mFaceManager).authenticate(any(), any(), anyInt(), any(), any(), anyInt());
+
+ // Stop scanning when bouncer becomes visible
+ mKeyguardUpdateMonitor.sendKeyguardBouncerChanged(true /* showingBouncer */);
+ mTestableLooper.processAllMessages();
+ clearInvocations(mFaceManager);
+ mKeyguardUpdateMonitor.requestFaceAuth();
+ verify(mFaceManager, never()).authenticate(any(), any(), anyInt(), any(), any(), anyInt());
}
@Test
@@ -357,6 +389,28 @@
}
@Test
+ public void testIgnoresAuth_whenLockdown() {
+ mKeyguardUpdateMonitor.dispatchStartedWakingUp();
+ mTestableLooper.processAllMessages();
+ when(mStrongAuthTracker.getStrongAuthForUser(anyInt())).thenReturn(
+ KeyguardUpdateMonitor.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN);
+
+ mKeyguardUpdateMonitor.onKeyguardVisibilityChanged(true);
+ verify(mFaceManager, never()).authenticate(any(), any(), anyInt(), any(), any(), anyInt());
+ }
+
+ @Test
+ public void testIgnoresAuth_whenLockout() {
+ mKeyguardUpdateMonitor.dispatchStartedWakingUp();
+ mTestableLooper.processAllMessages();
+ when(mStrongAuthTracker.getStrongAuthForUser(anyInt())).thenReturn(
+ KeyguardUpdateMonitor.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_LOCKOUT);
+
+ mKeyguardUpdateMonitor.onKeyguardVisibilityChanged(true);
+ verify(mFaceManager, never()).authenticate(any(), any(), anyInt(), any(), any(), anyInt());
+ }
+
+ @Test
public void testOnFaceAuthenticated_skipsFaceWhenAuthenticated() {
mKeyguardUpdateMonitor.onFaceAuthenticated(KeyguardUpdateMonitor.getCurrentUser());
mKeyguardUpdateMonitor.sendKeyguardBouncerChanged(true);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/BiometricsUnlockControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/BiometricsUnlockControllerTest.java
index 4e86f19..748f509 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/BiometricsUnlockControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/BiometricsUnlockControllerTest.java
@@ -155,6 +155,30 @@
}
@Test
+ public void onBiometricAuthenticated_whenFace_andBypass_encrypted_showBouncer() {
+ when(mKeyguardBypassController.getBypassEnabled()).thenReturn(true);
+ mBiometricUnlockController.setStatusBarKeyguardViewManager(mStatusBarKeyguardViewManager);
+
+ when(mUpdateMonitor.isUnlockingWithBiometricAllowed()).thenReturn(false);
+ mBiometricUnlockController.onBiometricAuthenticated(UserHandle.USER_CURRENT,
+ BiometricSourceType.FACE);
+
+ verify(mStatusBarKeyguardViewManager).showBouncer(eq(false));
+ }
+
+ @Test
+ public void onBiometricAuthenticated_whenFace_noBypass_encrypted_doNothing() {
+ mBiometricUnlockController.setStatusBarKeyguardViewManager(mStatusBarKeyguardViewManager);
+
+ when(mUpdateMonitor.isUnlockingWithBiometricAllowed()).thenReturn(false);
+ mBiometricUnlockController.onBiometricAuthenticated(UserHandle.USER_CURRENT,
+ BiometricSourceType.FACE);
+
+ verify(mStatusBarKeyguardViewManager, never()).showBouncer(anyBoolean());
+ verify(mStatusBarKeyguardViewManager, never()).animateCollapsePanels(anyFloat());
+ }
+
+ @Test
public void onBiometricAuthenticated_whenFaceOnBouncer_dismissBouncer() {
when(mUpdateMonitor.isUnlockingWithBiometricAllowed()).thenReturn(true);
when(mStatusBarKeyguardViewManager.isBouncerShowing()).thenReturn(true);
diff --git a/services/core/java/com/android/server/biometrics/face/FaceService.java b/services/core/java/com/android/server/biometrics/face/FaceService.java
index def7f75..72bac74 100644
--- a/services/core/java/com/android/server/biometrics/face/FaceService.java
+++ b/services/core/java/com/android/server/biometrics/face/FaceService.java
@@ -346,10 +346,11 @@
}
@Override // Binder call
- public void enroll(final IBinder token, final byte[] cryptoToken,
+ public void enroll(int userId, final IBinder token, final byte[] cryptoToken,
final IFaceServiceReceiver receiver, final String opPackageName,
final int[] disabledFeatures) {
checkPermission(MANAGE_BIOMETRIC);
+ updateActiveGroup(userId, opPackageName);
mNotificationManager.cancelAsUser(NOTIFICATION_TAG, NOTIFICATION_ID,
UserHandle.CURRENT);
@@ -448,8 +449,9 @@
@Override // Binder call
public void remove(final IBinder token, final int faceId, final int userId,
- final IFaceServiceReceiver receiver) {
+ final IFaceServiceReceiver receiver, final String opPackageName) {
checkPermission(MANAGE_BIOMETRIC);
+ updateActiveGroup(userId, opPackageName);
if (token == null) {
Slog.w(TAG, "remove(): token is null");
@@ -612,9 +614,10 @@
}
@Override
- public void setFeature(int feature, boolean enabled, final byte[] token,
- IFaceServiceReceiver receiver) {
+ public void setFeature(int userId, int feature, boolean enabled, final byte[] token,
+ IFaceServiceReceiver receiver, final String opPackageName) {
checkPermission(MANAGE_BIOMETRIC);
+ updateActiveGroup(userId, opPackageName);
mHandler.post(() -> {
if (!FaceService.this.hasEnrolledBiometrics(mCurrentUserId)) {
@@ -644,8 +647,10 @@
}
@Override
- public void getFeature(int feature, IFaceServiceReceiver receiver) {
+ public void getFeature(int userId, int feature, IFaceServiceReceiver receiver,
+ final String opPackageName) {
checkPermission(MANAGE_BIOMETRIC);
+ updateActiveGroup(userId, opPackageName);
mHandler.post(() -> {
// This should ideally return tri-state, but the user isn't shown settings unless