Merge "Update vis of face acquisition + err messages" into tm-d1-dev am: b87eac3000

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/18437709

Change-Id: I3a2b866b5e8c0c97ff14da1de2bbf85de732accd
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
TreeHugger Robot
2022-05-19 15:31:56 +00:00
committed by Automerger Merge Worker
4 changed files with 144 additions and 8 deletions

View File

@@ -614,6 +614,12 @@
2 - Override the setting to never bypass keyguard -->
<integer name="config_face_unlock_bypass_override">0</integer>
<!-- Which face help messages to surface when fingerprint is also enrolled.
Message ids correspond with the acquired ids in BiometricFaceConstants -->
<integer-array name="config_face_help_msgs_when_fingerprint_enrolled">
<!-- for example: <item>26</item> for FACE_ACQUIRED_MOUTH_COVERING_DETECTED -->
</integer-array>
<!-- Whether the communal service should be enabled -->
<bool name="config_communalServiceEnabled">false</bool>

View File

@@ -275,7 +275,6 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
HashMap<Integer, SimData> mSimDatas = new HashMap<>();
HashMap<Integer, ServiceState> mServiceStates = new HashMap<Integer, ServiceState>();
private int mRingMode;
private int mPhoneState;
private boolean mKeyguardIsVisible;
private boolean mCredentialAttempted;

View File

@@ -49,12 +49,14 @@ import android.hardware.biometrics.BiometricSourceType;
import android.hardware.face.FaceManager;
import android.hardware.fingerprint.FingerprintManager;
import android.os.BatteryManager;
import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.RemoteException;
import android.os.UserHandle;
import android.os.UserManager;
import android.provider.Settings;
import android.text.TextUtils;
import android.text.format.Formatter;
import android.util.Log;
@@ -92,6 +94,8 @@ import com.android.systemui.util.wakelock.WakeLock;
import java.io.PrintWriter;
import java.text.NumberFormat;
import java.util.HashSet;
import java.util.Set;
import javax.inject.Inject;
@@ -112,12 +116,12 @@ public class KeyguardIndicationController {
private static final String TAG = "KeyguardIndication";
private static final boolean DEBUG_CHARGING_SPEED = false;
private static final boolean DEBUG = Build.IS_DEBUGGABLE;
private static final int MSG_HIDE_TRANSIENT = 1;
private static final int MSG_SHOW_ACTION_TO_UNLOCK = 2;
private static final int MSG_HIDE_BIOMETRIC_MESSAGE = 3;
private static final long TRANSIENT_BIOMETRIC_ERROR_TIMEOUT = 1300;
private static final float BOUNCE_ANIMATION_FINAL_Y = 0f;
private final Context mContext;
private final BroadcastDispatcher mBroadcastDispatcher;
@@ -166,6 +170,7 @@ public class KeyguardIndicationController {
private boolean mBatteryPresent = true;
private long mChargingTimeRemaining;
private String mMessageToShowOnScreenOn;
private final Set<Integer> mCoExFaceHelpMsgIdsToShow;
private boolean mInited;
private KeyguardUpdateMonitorCallback mUpdateMonitorCallback;
@@ -234,6 +239,22 @@ public class KeyguardIndicationController {
mScreenLifecycle = screenLifecycle;
mScreenLifecycle.addObserver(mScreenObserver);
mCoExFaceHelpMsgIdsToShow = new HashSet<>();
final String msgsToShowOverride = Settings.Global.getString(mContext.getContentResolver(),
"coex_face_help_msgs"); // TODO: remove after UX testing b/231733975
if (msgsToShowOverride != null) {
final String[] msgIds = msgsToShowOverride.split("\\|");
for (String msgId : msgIds) {
mCoExFaceHelpMsgIdsToShow.add(Integer.parseInt(msgId));
}
} else {
int[] msgIds = context.getResources().getIntArray(
com.android.systemui.R.array.config_face_help_msgs_when_fingerprint_enrolled);
for (int msgId : msgIds) {
mCoExFaceHelpMsgIdsToShow.add(msgId);
}
}
mHandler = new Handler(mainLooper) {
@Override
public void handleMessage(Message msg) {
@@ -924,6 +945,7 @@ public class KeyguardIndicationController {
mTopIndicationView == null ? null : mTopIndicationView.getText()));
pw.println(" computePowerIndication(): " + computePowerIndication());
pw.println(" trustGrantedIndication: " + getTrustGrantedIndication());
pw.println(" mCoExFaceHelpMsgIdsToShow=" + mCoExFaceHelpMsgIdsToShow);
mRotateTextViewController.dump(pw, args);
}
@@ -982,9 +1004,20 @@ public class KeyguardIndicationController {
.isUnlockingWithBiometricAllowed(true /* isStrongBiometric */)) {
return;
}
boolean showActionToUnlock =
msgId == KeyguardUpdateMonitor.BIOMETRIC_HELP_FACE_NOT_RECOGNIZED;
if (mStatusBarKeyguardViewManager.isBouncerShowing()) {
if (biometricSourceType == BiometricSourceType.FACE
&& !showActionToUnlock
&& mKeyguardUpdateMonitor.getCachedIsUnlockWithFingerprintPossible(
KeyguardUpdateMonitor.getCurrentUser())
&& !mCoExFaceHelpMsgIdsToShow.contains(msgId)) {
if (DEBUG) {
Log.d(TAG, "skip showing msgId=" + msgId + " helpString=" + helpString
+ ", due to co-ex logic");
}
return;
} else if (mStatusBarKeyguardViewManager.isBouncerShowing()) {
mStatusBarKeyguardViewManager.showBouncerMessage(helpString,
mInitialTextColorState);
} else if (mScreenLifecycle.getScreenState() == SCREEN_ON) {
@@ -1001,14 +1034,20 @@ public class KeyguardIndicationController {
if (shouldSuppressBiometricError(msgId, biometricSourceType, mKeyguardUpdateMonitor)) {
return;
}
if (msgId == FaceManager.FACE_ERROR_TIMEOUT) {
if (mKeyguardUpdateMonitor.getCachedIsUnlockWithFingerprintPossible(
KeyguardUpdateMonitor.getCurrentUser())) {
// no message if fingerprint is also enrolled
if (DEBUG) {
Log.d(TAG, "skip showing FACE_ERROR_TIMEOUT due to co-ex logic");
}
return;
}
// The face timeout message is not very actionable, let's ask the user to
// manually retry.
if (!mStatusBarKeyguardViewManager.isBouncerShowing()
&& mKeyguardUpdateMonitor.isUdfpsEnrolled()
&& mKeyguardUpdateMonitor.isFingerprintDetectionRunning()) {
showFaceFailedTryFingerprintMsg(msgId, errString);
} else if (mStatusBarKeyguardViewManager.isShowingAlternateAuth()) {
if (mStatusBarKeyguardViewManager.isShowingAlternateAuth()) {
mStatusBarKeyguardViewManager.showBouncerMessage(
mContext.getResources().getString(R.string.keyguard_try_fingerprint),
mInitialTextColorState

View File

@@ -45,6 +45,7 @@ import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -59,6 +60,7 @@ import android.content.Context;
import android.content.Intent;
import android.content.pm.UserInfo;
import android.graphics.Color;
import android.hardware.biometrics.BiometricFaceConstants;
import android.hardware.biometrics.BiometricSourceType;
import android.hardware.face.FaceManager;
import android.hardware.fingerprint.FingerprintManager;
@@ -106,6 +108,9 @@ import org.mockito.MockitoAnnotations;
import java.text.NumberFormat;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@SmallTest
@RunWith(AndroidTestingRunner.class)
@@ -577,6 +582,80 @@ public class KeyguardIndicationControllerTest extends SysuiTestCase {
verify(mStatusBarKeyguardViewManager).showBouncerMessage(eq(message), any());
}
@Test
public void faceErrorTimeout_whenFingerprintEnrolled_doesNotShowMessage() {
createController();
when(mKeyguardUpdateMonitor.getCachedIsUnlockWithFingerprintPossible(
0)).thenReturn(true);
String message = "A message";
mController.setVisible(true);
mController.getKeyguardCallback().onBiometricError(
FaceManager.FACE_ERROR_TIMEOUT, message, BiometricSourceType.FACE);
verifyNoMessage(INDICATION_TYPE_BIOMETRIC_MESSAGE);
}
@Test
public void doNotSendFaceHelpMessages_fingerprintEnrolled() {
createController();
// GIVEN fingerprint enrolled
when(mKeyguardUpdateMonitor.getCachedIsUnlockWithFingerprintPossible(
0)).thenReturn(true);
// WHEN help messages received
final String helpString = "helpString";
final int[] msgIds = new int[]{
BiometricFaceConstants.FACE_ACQUIRED_FACE_OBSCURED,
BiometricFaceConstants.FACE_ACQUIRED_DARK_GLASSES_DETECTED,
BiometricFaceConstants.FACE_ACQUIRED_TOO_RIGHT,
BiometricFaceConstants.FACE_ACQUIRED_TOO_LEFT,
BiometricFaceConstants.FACE_ACQUIRED_TOO_HIGH,
BiometricFaceConstants.FACE_ACQUIRED_TOO_LOW,
BiometricFaceConstants.FACE_ACQUIRED_TOO_BRIGHT,
BiometricFaceConstants.FACE_ACQUIRED_TOO_DARK
};
for (int msgId : msgIds) {
mKeyguardUpdateMonitorCallback.onBiometricHelp(
msgId, helpString + msgId, BiometricSourceType.FACE);
}
// THEN no messages shown
verifyNoMessage(INDICATION_TYPE_BIOMETRIC_MESSAGE);
}
@Test
public void sendAllFaceHelpMessages_fingerprintNotEnrolled() {
createController();
// GIVEN fingerprint NOT enrolled
when(mKeyguardUpdateMonitor.getCachedIsUnlockWithFingerprintPossible(
0)).thenReturn(false);
// WHEN help messages received
final Set<CharSequence> helpStrings = new HashSet<>();
final String helpString = "helpString";
final int[] msgIds = new int[]{
BiometricFaceConstants.FACE_ACQUIRED_FACE_OBSCURED,
BiometricFaceConstants.FACE_ACQUIRED_DARK_GLASSES_DETECTED,
BiometricFaceConstants.FACE_ACQUIRED_TOO_RIGHT,
BiometricFaceConstants.FACE_ACQUIRED_TOO_LEFT,
BiometricFaceConstants.FACE_ACQUIRED_TOO_HIGH,
BiometricFaceConstants.FACE_ACQUIRED_TOO_LOW,
BiometricFaceConstants.FACE_ACQUIRED_TOO_BRIGHT,
BiometricFaceConstants.FACE_ACQUIRED_TOO_DARK
};
for (int msgId : msgIds) {
final String numberedHelpString = helpString + msgId;
mKeyguardUpdateMonitorCallback.onBiometricHelp(
msgId, numberedHelpString, BiometricSourceType.FACE);
helpStrings.add(numberedHelpString);
}
// THEN message shown for each call
verifyIndicationMessages(INDICATION_TYPE_BIOMETRIC_MESSAGE, helpStrings);
}
@Test
public void updateMonitor_listenerUpdatesIndication() {
createController();
@@ -850,6 +929,19 @@ public class KeyguardIndicationControllerTest extends SysuiTestCase {
mBroadcastReceiver.onReceive(mContext, new Intent());
}
private void verifyIndicationMessages(int type, Set<CharSequence> messages) {
verify(mRotateTextViewController, times(messages.size())).updateIndication(eq(type),
mKeyguardIndicationCaptor.capture(), anyBoolean());
List<KeyguardIndication> kis = mKeyguardIndicationCaptor.getAllValues();
for (KeyguardIndication ki : kis) {
final CharSequence msg = ki.getMessage();
assertTrue(messages.contains(msg)); // check message is shown
messages.remove(msg);
}
assertThat(messages.size()).isEqualTo(0); // check that all messages accounted for (removed)
}
private void verifyIndicationMessage(int type, String message) {
verify(mRotateTextViewController).updateIndication(eq(type),
mKeyguardIndicationCaptor.capture(), anyBoolean());