Allow biometric messages to show in sequence

Test: atest KeyguardIndicationControllerTest
Bug: 231757718
Bug: 237104481
Change-Id: Ia8bf1037092247099c4a992d51563dd060d8fa5a
This commit is contained in:
Beverly
2022-07-25 19:34:00 +00:00
committed by Beverly Tai
parent cfaad7ffb3
commit a9ff3a649e
6 changed files with 100 additions and 61 deletions

View File

@@ -799,7 +799,7 @@
<!-- Message shown when lock screen is tapped or face authentication fails. [CHAR LIMIT=60] -->
<string name="keyguard_unlock">Swipe up to open</string>
<!-- Message shown when lock screen is unlocked (ie: by trust agent) and the user taps the empty space on the lock screen and UDFPS is supported. Provides extra instructions for how the user can enter their device [CHAR LIMIT=60] -->
<!-- Message shown when lock screen is unlocked (ie: by trust agent or face auth). Provides extra instructions for how the user can enter their device [CHAR LIMIT=60] -->
<string name="keyguard_unlock_press">Press the unlock icon to open</string>
<!-- Message shown when non-bypass face authentication succeeds. Provides extra instructions for how the user can enter their device [CHAR LIMIT=60] -->
@@ -813,6 +813,10 @@
<!-- Message shown when non-bypass face authentication succeeds and UDFPS is supported. Provides extra instructions for how the user can enter their device [CHAR LIMIT=60] -->
<string name="keyguard_face_successful_unlock_press_alt_3">Face recognized. Press the unlock icon to open.</string>
<!-- Message shown when non-bypass face authentication succeeds. [CHAR LIMIT=60] -->
<string name="keyguard_face_successful_unlock">Unlocked by face</string>
<!-- Message shown when non-bypass face authentication succeeds. [CHAR LIMIT=60] -->
<string name="keyguard_face_successful_unlock_alt1">Face recognized</string>
<!-- Messages shown when users press outside of udfps region during -->
<string-array name="udfps_accessibility_touch_hints">

View File

@@ -271,7 +271,7 @@ public class KeyguardUpdateMonitorCallback {
* like fingerprint authentication errors.
*
* @param message Message that indicates an error.
* @see KeyguardIndicationController.BaseKeyguardCallback#HIDE_DELAY_MS
* @see KeyguardIndicationController#DEFAULT_HIDE_DELAY_MS
* @see KeyguardIndicationController#showTransientIndication(CharSequence)
*/
public void onTrustAgentErrorMessage(CharSequence message) { }

View File

@@ -27,6 +27,7 @@ import androidx.annotation.IntDef;
import com.android.systemui.Dumpable;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.KeyguardIndicationController;
import com.android.systemui.statusbar.phone.KeyguardIndicationTextView;
import com.android.systemui.util.ViewController;
import com.android.systemui.util.concurrency.DelayableExecutor;
@@ -56,8 +57,11 @@ import java.util.Map;
public class KeyguardIndicationRotateTextViewController extends
ViewController<KeyguardIndicationTextView> implements Dumpable {
public static String TAG = "KgIndicationRotatingCtrl";
private static final long DEFAULT_INDICATION_SHOW_LENGTH = 3500; // milliseconds
public static final long IMPORTANT_MSG_MIN_DURATION = 2000L + 600L; // 2000ms + [Y in duration]
private static final long DEFAULT_INDICATION_SHOW_LENGTH =
KeyguardIndicationController.DEFAULT_HIDE_DELAY_MS
- KeyguardIndicationTextView.Y_IN_DURATION;
public static final long IMPORTANT_MSG_MIN_DURATION =
2000L + KeyguardIndicationTextView.Y_IN_DURATION;
private final StatusBarStateController mStatusBarStateController;
private final float mMaxAlpha;
@@ -375,6 +379,7 @@ public class KeyguardIndicationRotateTextViewController extends
public static final int INDICATION_TYPE_USER_LOCKED = 8;
public static final int INDICATION_TYPE_REVERSE_CHARGING = 10;
public static final int INDICATION_TYPE_BIOMETRIC_MESSAGE = 11;
public static final int INDICATION_TYPE_BIOMETRIC_MESSAGE_FOLLOW_UP = 12;
@IntDef({
INDICATION_TYPE_NONE,
@@ -388,7 +393,8 @@ public class KeyguardIndicationRotateTextViewController extends
INDICATION_TYPE_RESTING,
INDICATION_TYPE_USER_LOCKED,
INDICATION_TYPE_REVERSE_CHARGING,
INDICATION_TYPE_BIOMETRIC_MESSAGE
INDICATION_TYPE_BIOMETRIC_MESSAGE,
INDICATION_TYPE_BIOMETRIC_MESSAGE_FOLLOW_UP
})
@Retention(RetentionPolicy.SOURCE)
public @interface IndicationType{}

View File

@@ -27,6 +27,7 @@ import static com.android.systemui.keyguard.KeyguardIndicationRotateTextViewCont
import static com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController.INDICATION_TYPE_ALIGNMENT;
import static com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController.INDICATION_TYPE_BATTERY;
import static com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController.INDICATION_TYPE_BIOMETRIC_MESSAGE;
import static com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController.INDICATION_TYPE_BIOMETRIC_MESSAGE_FOLLOW_UP;
import static com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController.INDICATION_TYPE_DISCLOSURE;
import static com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController.INDICATION_TYPE_LOGOUT;
import static com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController.INDICATION_TYPE_OWNER_INFO;
@@ -36,7 +37,6 @@ import static com.android.systemui.keyguard.KeyguardIndicationRotateTextViewCont
import static com.android.systemui.keyguard.ScreenLifecycle.SCREEN_ON;
import static com.android.systemui.plugins.FalsingManager.LOW_PENALTY;
import android.app.IActivityManager;
import android.app.admin.DevicePolicyManager;
import android.content.BroadcastReceiver;
import android.content.Context;
@@ -123,6 +123,8 @@ public class KeyguardIndicationController {
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;
public static final long DEFAULT_HIDE_DELAY_MS =
3500 + KeyguardIndicationTextView.Y_IN_DURATION;
private final Context mContext;
private final BroadcastDispatcher mBroadcastDispatcher;
@@ -140,7 +142,6 @@ public class KeyguardIndicationController {
protected final @Main DelayableExecutor mExecutor;
protected final @Background DelayableExecutor mBackgroundExecutor;
private final LockPatternUtils mLockPatternUtils;
private final IActivityManager mIActivityManager;
private final FalsingManager mFalsingManager;
private final KeyguardBypassController mKeyguardBypassController;
private final AccessibilityManager mAccessibilityManager;
@@ -155,6 +156,7 @@ public class KeyguardIndicationController {
private CharSequence mTrustGrantedIndication;
private CharSequence mTransientIndication;
private CharSequence mBiometricMessage;
private CharSequence mBiometricMessageFollowUp;
protected ColorStateList mInitialTextColorState;
private boolean mVisible;
private boolean mOrganizationOwnedDevice;
@@ -171,7 +173,7 @@ public class KeyguardIndicationController {
private int mBatteryLevel;
private boolean mBatteryPresent = true;
private long mChargingTimeRemaining;
private String mMessageToShowOnScreenOn;
private String mBiometricErrorMessageToShowOnScreenOn;
private final Set<Integer> mCoExFaceHelpMsgIdsToShow;
private boolean mInited;
@@ -189,11 +191,11 @@ public class KeyguardIndicationController {
private final ScreenLifecycle.Observer mScreenObserver = new ScreenLifecycle.Observer() {
@Override
public void onScreenTurnedOn() {
if (mMessageToShowOnScreenOn != null) {
showBiometricMessage(mMessageToShowOnScreenOn);
if (mBiometricErrorMessageToShowOnScreenOn != null) {
showBiometricMessage(mBiometricErrorMessageToShowOnScreenOn);
// We want to keep this message around in case the screen was off
hideBiometricMessageDelayed(BaseKeyguardCallback.HIDE_DELAY_MS);
mMessageToShowOnScreenOn = null;
hideBiometricMessageDelayed(DEFAULT_HIDE_DELAY_MS);
mBiometricErrorMessageToShowOnScreenOn = null;
}
}
};
@@ -219,7 +221,6 @@ public class KeyguardIndicationController {
FalsingManager falsingManager,
LockPatternUtils lockPatternUtils,
ScreenLifecycle screenLifecycle,
IActivityManager iActivityManager,
KeyguardBypassController keyguardBypassController,
AccessibilityManager accessibilityManager) {
mContext = context;
@@ -236,7 +237,6 @@ public class KeyguardIndicationController {
mExecutor = executor;
mBackgroundExecutor = bgExecutor;
mLockPatternUtils = lockPatternUtils;
mIActivityManager = iActivityManager;
mFalsingManager = falsingManager;
mKeyguardBypassController = keyguardBypassController;
mAccessibilityManager = accessibilityManager;
@@ -498,8 +498,23 @@ public class KeyguardIndicationController {
.build(),
true
);
if (!TextUtils.isEmpty(mBiometricMessageFollowUp)) {
mRotateTextViewController.updateIndication(
INDICATION_TYPE_BIOMETRIC_MESSAGE_FOLLOW_UP,
new KeyguardIndication.Builder()
.setMessage(mBiometricMessageFollowUp)
.setMinVisibilityMillis(IMPORTANT_MSG_MIN_DURATION)
.setTextColor(mInitialTextColorState)
.build(),
true
);
} else {
mRotateTextViewController.hideIndication(
INDICATION_TYPE_BIOMETRIC_MESSAGE_FOLLOW_UP);
}
} else {
mRotateTextViewController.hideIndication(INDICATION_TYPE_BIOMETRIC_MESSAGE);
mRotateTextViewController.hideIndication(INDICATION_TYPE_BIOMETRIC_MESSAGE_FOLLOW_UP);
}
}
@@ -719,38 +734,45 @@ public class KeyguardIndicationController {
private void showTransientIndication(CharSequence transientIndication) {
mTransientIndication = transientIndication;
mHandler.removeMessages(MSG_HIDE_TRANSIENT);
hideTransientIndicationDelayed(BaseKeyguardCallback.HIDE_DELAY_MS);
hideTransientIndicationDelayed(DEFAULT_HIDE_DELAY_MS);
updateTransient();
}
/**
* Shows {@param biometricMessage} until it is hidden by {@link #hideBiometricMessage}.
*/
public void showBiometricMessage(int biometricMessage) {
showBiometricMessage(mContext.getResources().getString(biometricMessage));
private void showBiometricMessage(CharSequence biometricMessage) {
showBiometricMessage(biometricMessage, null);
}
/**
* Shows {@param biometricMessage} until it is hidden by {@link #hideBiometricMessage}.
* Shows {@param biometricMessage} and {@param biometricMessageFollowUp}
* until they are hidden by {@link #hideBiometricMessage}. Messages are rotated through
* by {@link KeyguardIndicationRotateTextViewController}, see class for rotating message
* logic.
*/
private void showBiometricMessage(CharSequence biometricMessage) {
private void showBiometricMessage(CharSequence biometricMessage,
CharSequence biometricMessageFollowUp) {
if (TextUtils.equals(biometricMessage, mBiometricMessage)) {
return;
}
mBiometricMessage = biometricMessage;
mBiometricMessageFollowUp = biometricMessageFollowUp;
mHandler.removeMessages(MSG_SHOW_ACTION_TO_UNLOCK);
mHandler.removeMessages(MSG_HIDE_BIOMETRIC_MESSAGE);
hideBiometricMessageDelayed(BaseKeyguardCallback.HIDE_DELAY_MS);
hideBiometricMessageDelayed(
mBiometricMessageFollowUp != null
? DEFAULT_HIDE_DELAY_MS * 2
: DEFAULT_HIDE_DELAY_MS
);
updateBiometricMessage();
}
private void hideBiometricMessage() {
if (mBiometricMessage != null) {
if (mBiometricMessage != null || mBiometricMessageFollowUp != null) {
mBiometricMessage = null;
mBiometricMessageFollowUp = null;
mHandler.removeMessages(MSG_HIDE_BIOMETRIC_MESSAGE);
updateBiometricMessage();
}
@@ -789,9 +811,9 @@ public class KeyguardIndicationController {
// colors can be hard to read in low brightness.
mTopIndicationView.setTextColor(Color.WHITE);
CharSequence newIndication = null;
CharSequence newIndication;
if (!TextUtils.isEmpty(mBiometricMessage)) {
newIndication = mBiometricMessage;
newIndication = mBiometricMessage; // note: doesn't show mBiometricMessageFollowUp
} else if (!TextUtils.isEmpty(mTransientIndication)) {
newIndication = mTransientIndication;
} else if (!mBatteryPresent) {
@@ -909,15 +931,21 @@ public class KeyguardIndicationController {
|| mAccessibilityManager.isTouchExplorationEnabled();
if (udfpsSupported && faceAuthenticated) { // co-ex
if (a11yEnabled) {
showBiometricMessage(mContext.getString(
R.string.keyguard_face_successful_unlock_swipe));
showBiometricMessage(
mContext.getString(R.string.keyguard_face_successful_unlock),
mContext.getString(R.string.keyguard_unlock)
);
} else {
showBiometricMessage(mContext.getString(
R.string.keyguard_face_successful_unlock_press));
showBiometricMessage(
mContext.getString(R.string.keyguard_face_successful_unlock),
mContext.getString(R.string.keyguard_unlock_press)
);
}
} else if (faceAuthenticated) { // face-only
showBiometricMessage(mContext.getString(
R.string.keyguard_face_successful_unlock_swipe));
showBiometricMessage(
mContext.getString(R.string.keyguard_face_successful_unlock),
mContext.getString(R.string.keyguard_unlock)
);
} else if (udfpsSupported) { // udfps-only
if (a11yEnabled) {
showBiometricMessage(mContext.getString(R.string.keyguard_unlock));
@@ -943,10 +971,11 @@ public class KeyguardIndicationController {
pw.println(" mPowerCharged: " + mPowerCharged);
pw.println(" mChargingSpeed: " + mChargingSpeed);
pw.println(" mChargingWattage: " + mChargingWattage);
pw.println(" mMessageToShowOnScreenOn: " + mMessageToShowOnScreenOn);
pw.println(" mMessageToShowOnScreenOn: " + mBiometricErrorMessageToShowOnScreenOn);
pw.println(" mDozing: " + mDozing);
pw.println(" mTransientIndication: " + mTransientIndication);
pw.println(" mBiometricMessage: " + mBiometricMessage);
pw.println(" mBiometricMessageFollowUp: " + mBiometricMessageFollowUp);
pw.println(" mBatteryLevel: " + mBatteryLevel);
pw.println(" mBatteryPresent: " + mBatteryPresent);
pw.println(" AOD text: " + (
@@ -958,8 +987,6 @@ public class KeyguardIndicationController {
}
protected class BaseKeyguardCallback extends KeyguardUpdateMonitorCallback {
public static final int HIDE_DELAY_MS = 5000;
@Override
public void onTimeChanged() {
if (mVisible) {
@@ -1077,7 +1104,7 @@ public class KeyguardIndicationController {
} else if (mScreenLifecycle.getScreenState() == SCREEN_ON) {
showBiometricMessage(errString);
} else {
mMessageToShowOnScreenOn = errString;
mBiometricErrorMessageToShowOnScreenOn = errString;
}
}
@@ -1139,7 +1166,7 @@ public class KeyguardIndicationController {
// Let's hide any previous messages when authentication starts, otherwise
// multiple auth attempts would overlap.
hideBiometricMessage();
mMessageToShowOnScreenOn = null;
mBiometricErrorMessageToShowOnScreenOn = null;
}
}
@@ -1179,7 +1206,7 @@ public class KeyguardIndicationController {
@Override
public void onRequireUnlockForNfc() {
showTransientIndication(mContext.getString(R.string.require_unlock_for_nfc));
hideTransientIndicationDelayed(HIDE_DELAY_MS);
hideTransientIndicationDelayed(DEFAULT_HIDE_DELAY_MS);
}
}

View File

@@ -39,6 +39,8 @@ import com.android.systemui.keyguard.KeyguardIndication;
* A view to show hints on Keyguard ("Swipe up to unlock", "Tap again to open").
*/
public class KeyguardIndicationTextView extends TextView {
public static final long Y_IN_DURATION = 600L;
@StyleRes
private static int sStyleId = R.style.TextAppearance_Keyguard_BottomArea;
@StyleRes
@@ -259,7 +261,7 @@ public class KeyguardIndicationTextView extends TextView {
private long getYInDuration() {
if (!mAnimationsEnabled) return 0L;
return 600L;
return Y_IN_DURATION;
}
private long getFadeOutDuration() {

View File

@@ -23,6 +23,7 @@ import static android.content.pm.UserInfo.FLAG_MANAGED_PROFILE;
import static com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController.INDICATION_TYPE_ALIGNMENT;
import static com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController.INDICATION_TYPE_BATTERY;
import static com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController.INDICATION_TYPE_BIOMETRIC_MESSAGE;
import static com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController.INDICATION_TYPE_BIOMETRIC_MESSAGE_FOLLOW_UP;
import static com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController.INDICATION_TYPE_DISCLOSURE;
import static com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController.INDICATION_TYPE_LOGOUT;
import static com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController.INDICATION_TYPE_OWNER_INFO;
@@ -50,7 +51,6 @@ import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.app.IActivityManager;
import android.app.Instrumentation;
import android.app.admin.DevicePolicyManager;
import android.app.admin.DevicePolicyResourcesManager;
@@ -161,8 +161,6 @@ public class KeyguardIndicationControllerTest extends SysuiTestCase {
@Mock
private LockPatternUtils mLockPatternUtils;
@Mock
private IActivityManager mIActivityManager;
@Mock
private KeyguardBypassController mKeyguardBypassController;
@Mock
private AccessibilityManager mAccessibilityManager;
@@ -256,8 +254,7 @@ public class KeyguardIndicationControllerTest extends SysuiTestCase {
mKeyguardStateController, mStatusBarStateController, mKeyguardUpdateMonitor,
mDockManager, mBroadcastDispatcher, mDevicePolicyManager, mIBatteryStats,
mUserManager, mExecutor, mExecutor, mFalsingManager, mLockPatternUtils,
mScreenLifecycle, mIActivityManager, mKeyguardBypassController,
mAccessibilityManager);
mScreenLifecycle, mKeyguardBypassController, mAccessibilityManager);
mController.init();
mController.setIndicationArea(mIndicationArea);
verify(mStatusBarStateController).addCallback(mStatusBarStateListenerCaptor.capture());
@@ -971,11 +968,11 @@ public class KeyguardIndicationControllerTest extends SysuiTestCase {
mController.getKeyguardCallback().onBiometricAuthenticated(0,
BiometricSourceType.FACE, false);
// THEN 'face unlocked. press unlock icon to open' message shows
String pressToOpen = mContext.getString(R.string.keyguard_face_successful_unlock_press);
verifyIndicationMessage(INDICATION_TYPE_BIOMETRIC_MESSAGE, pressToOpen);
assertThat(mTextView.getText()).isNotEqualTo(pressToOpen);
// THEN 'face unlocked' then 'press unlock icon to open' message show
String unlockedByFace = mContext.getString(R.string.keyguard_face_successful_unlock);
verifyIndicationMessage(INDICATION_TYPE_BIOMETRIC_MESSAGE, unlockedByFace);
String pressToOpen = mContext.getString(R.string.keyguard_unlock_press);
verifyIndicationMessage(INDICATION_TYPE_BIOMETRIC_MESSAGE_FOLLOW_UP, pressToOpen);
}
@@ -996,10 +993,11 @@ public class KeyguardIndicationControllerTest extends SysuiTestCase {
mController.getKeyguardCallback().onBiometricAuthenticated(0,
BiometricSourceType.FACE, false);
// THEN show 'face unlocked. swipe up to open' message
String faceUnlockedSwipeToOpen =
mContext.getString(R.string.keyguard_face_successful_unlock_swipe);
verifyIndicationMessage(INDICATION_TYPE_BIOMETRIC_MESSAGE, faceUnlockedSwipeToOpen);
// THEN show 'face unlocked' and 'swipe up to open' messages
String unlockedByFace = mContext.getString(R.string.keyguard_face_successful_unlock);
verifyIndicationMessage(INDICATION_TYPE_BIOMETRIC_MESSAGE, unlockedByFace);
String swipeUpToOpen = mContext.getString(R.string.keyguard_unlock);
verifyIndicationMessage(INDICATION_TYPE_BIOMETRIC_MESSAGE_FOLLOW_UP, swipeUpToOpen);
}
@Test
@@ -1018,10 +1016,11 @@ public class KeyguardIndicationControllerTest extends SysuiTestCase {
mController.getKeyguardCallback().onBiometricAuthenticated(0,
BiometricSourceType.FACE, false);
// THEN show 'swipe up to open' message
String faceUnlockedSwipeToOpen =
mContext.getString(R.string.keyguard_face_successful_unlock_swipe);
verifyIndicationMessage(INDICATION_TYPE_BIOMETRIC_MESSAGE, faceUnlockedSwipeToOpen);
// THEN show 'face unlocked' and 'swipe up to open' messages
String unlockedByFace = mContext.getString(R.string.keyguard_face_successful_unlock);
verifyIndicationMessage(INDICATION_TYPE_BIOMETRIC_MESSAGE, unlockedByFace);
String swipeUpToOpen = mContext.getString(R.string.keyguard_unlock);
verifyIndicationMessage(INDICATION_TYPE_BIOMETRIC_MESSAGE_FOLLOW_UP, swipeUpToOpen);
}
@Test
@@ -1039,10 +1038,11 @@ public class KeyguardIndicationControllerTest extends SysuiTestCase {
mController.getKeyguardCallback().onBiometricAuthenticated(0,
BiometricSourceType.FACE, false);
// THEN show 'swipe up to open' message
String faceUnlockedSwipeToOpen =
mContext.getString(R.string.keyguard_face_successful_unlock_swipe);
verifyIndicationMessage(INDICATION_TYPE_BIOMETRIC_MESSAGE, faceUnlockedSwipeToOpen);
// THEN show 'face unlocked' and 'swipe up to open' messages
String unlockedByFace = mContext.getString(R.string.keyguard_face_successful_unlock);
verifyIndicationMessage(INDICATION_TYPE_BIOMETRIC_MESSAGE, unlockedByFace);
String swipeUpToOpen = mContext.getString(R.string.keyguard_unlock);
verifyIndicationMessage(INDICATION_TYPE_BIOMETRIC_MESSAGE_FOLLOW_UP, swipeUpToOpen);
}
@Test