Indicating fingerprint error messages on the bouncer now

Also ensure that error messages are surfaced when the screen
comes on such that the user knows why his fingerprint is not
working.

Bug: 22035466
Bug: 22524101
Change-Id: I00b0e833cdb8a3475545ba75b8cb7bf7a419dfd4
This commit is contained in:
Selim Cinek
2015-08-11 14:58:44 -07:00
parent ec85b52232
commit cfafe4ea6f
13 changed files with 158 additions and 66 deletions

View File

@@ -234,6 +234,12 @@ public abstract class KeyguardAbsKeyInputView extends LinearLayout
}
}
@Override
public void showMessage(String message, int color) {
mSecurityMessageDisplay.setNextMessageColor(color);
mSecurityMessageDisplay.setMessage(message, true /* important */);
}
protected abstract int getPromtReasonStringRes(int reason);
// Cause a VIRTUAL_KEY vibration

View File

@@ -170,6 +170,10 @@ public class KeyguardHostView extends FrameLayout implements SecurityCallback {
mSecurityContainer.showPromptReason(reason);
}
public void showMessage(String message, int color) {
mSecurityContainer.showMessage(message, color);
}
/**
* Dismisses the keyguard by going to the next screen or making it gone.
*

View File

@@ -39,15 +39,18 @@ class KeyguardMessageArea extends TextView implements SecurityMessageDisplay {
* lift-to-type from interrupting itself.
*/
private static final long ANNOUNCEMENT_DELAY = 250;
private static final int DEFAULT_COLOR = -1;
private static final int SECURITY_MESSAGE_DURATION = 5000;
private final KeyguardUpdateMonitor mUpdateMonitor;
private final Handler mHandler;
private final int mDefaultColor;
// Timeout before we reset the message to show charging/owner info
long mTimeout = SECURITY_MESSAGE_DURATION;
CharSequence mMessage;
private int mNextMessageColor = DEFAULT_COLOR;
private final Runnable mClearMessageRunnable = new Runnable() {
@Override
@@ -78,9 +81,15 @@ class KeyguardMessageArea extends TextView implements SecurityMessageDisplay {
mUpdateMonitor.registerCallback(mInfoCallback);
mHandler = new Handler(Looper.myLooper());
mDefaultColor = getCurrentTextColor();
update();
}
@Override
public void setNextMessageColor(int color) {
mNextMessageColor = color;
}
@Override
public void setMessage(CharSequence msg, boolean important) {
if (!TextUtils.isEmpty(msg) && important) {
@@ -151,6 +160,12 @@ class KeyguardMessageArea extends TextView implements SecurityMessageDisplay {
CharSequence status = mMessage;
setVisibility(TextUtils.isEmpty(status) ? INVISIBLE : VISIBLE);
setText(status);
int color = mDefaultColor;
if (mNextMessageColor != DEFAULT_COLOR) {
color = mNextMessageColor;
mNextMessageColor = DEFAULT_COLOR;
}
setTextColor(color);
}

View File

@@ -15,10 +15,6 @@
*/
package com.android.keyguard;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Rect;
import android.os.AsyncTask;
@@ -28,7 +24,6 @@ import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.RenderNodeAnimator;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.AnimationUtils;
@@ -341,6 +336,12 @@ public class KeyguardPatternView extends LinearLayout implements KeyguardSecurit
}
}
@Override
public void showMessage(String message, int color) {
mSecurityMessageDisplay.setNextMessageColor(color);
mSecurityMessageDisplay.setMessage(message, true /* important */);
}
@Override
public void startAppearAnimation() {
enableClipping(false);

View File

@@ -518,6 +518,13 @@ public class KeyguardSecurityContainer extends FrameLayout implements KeyguardSe
}
}
public void showMessage(String message, int color) {
if (mCurrentSecuritySelection != SecurityMode.None) {
getSecurityView(mCurrentSecuritySelection).showMessage(message, color);
}
}
@Override
public void showUsabilityHint() {
mSecurityViewFlipper.showUsabilityHint();

View File

@@ -76,6 +76,14 @@ public interface KeyguardSecurityView {
*/
void showPromptReason(int reason);
/**
* Show a message on the security view with a specified color
*
* @param message the message to show
* @param color the color to use
*/
void showMessage(String message, int color);
/**
* Instruct the view to show usability hints, if any.
*

View File

@@ -138,6 +138,14 @@ public class KeyguardSecurityViewFlipper extends ViewFlipper implements Keyguard
}
}
@Override
public void showMessage(String message, int color) {
KeyguardSecurityView ksv = getSecurityView();
if (ksv != null) {
ksv.showMessage(message, color);
}
}
@Override
public void showUsabilityHint() {
KeyguardSecurityView ksv = getSecurityView();

View File

@@ -17,11 +17,14 @@
package com.android.keyguard;
public interface SecurityMessageDisplay {
public void setMessage(CharSequence msg, boolean important);
public void setMessage(int resId, boolean important);
void setNextMessageColor(int color);
public void setMessage(int resId, boolean important, Object... formatArgs);
void setMessage(CharSequence msg, boolean important);
public void setTimeout(int timeout_ms);
void setMessage(int resId, boolean important);
void setMessage(int resId, boolean important, Object... formatArgs);
void setTimeout(int timeout_ms);
}

View File

@@ -16,18 +16,13 @@
package com.android.systemui.statusbar;
import com.android.internal.app.IBatteryStats;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.keyguard.KeyguardUpdateMonitorCallback;
import com.android.systemui.R;
import com.android.systemui.statusbar.phone.KeyguardIndicationTextView;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.res.Resources;
import android.graphics.Color;
import android.hardware.fingerprint.FingerprintManager;
import android.os.BatteryManager;
import android.os.BatteryStats;
import android.os.Handler;
@@ -40,8 +35,16 @@ import android.text.format.Formatter;
import android.util.Log;
import android.view.View;
import com.android.internal.app.IBatteryStats;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.keyguard.KeyguardUpdateMonitorCallback;
import com.android.systemui.R;
import com.android.systemui.statusbar.phone.KeyguardIndicationTextView;
import com.android.systemui.statusbar.phone.LockIcon;
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
/**
* Controls the little text indicator on the keyguard.
* Controls the indications and error messages shown on the Keyguard
*/
public class KeyguardIndicationController {
@@ -49,6 +52,8 @@ public class KeyguardIndicationController {
private static final boolean DEBUG_CHARGING_CURRENT = false;
private static final int MSG_HIDE_TRANSIENT = 1;
private static final int MSG_CLEAR_FP_MSG = 2;
private static final long TRANSIENT_FP_ERROR_TIMEOUT = 1300;
private final Context mContext;
private final KeyguardIndicationTextView mTextView;
@@ -56,6 +61,8 @@ public class KeyguardIndicationController {
private final int mSlowThreshold;
private final int mFastThreshold;
private final LockIcon mLockIcon;
private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
private String mRestingIndication;
private String mTransientIndication;
@@ -66,10 +73,13 @@ public class KeyguardIndicationController {
private boolean mPowerCharged;
private int mChargingSpeed;
private int mChargingCurrent;
private String mMessageToShowOnScreenOn;
public KeyguardIndicationController(Context context, KeyguardIndicationTextView textView) {
public KeyguardIndicationController(Context context, KeyguardIndicationTextView textView,
LockIcon lockIcon) {
mContext = context;
mTextView = textView;
mLockIcon = lockIcon;
Resources res = context.getResources();
mSlowThreshold = res.getInteger(R.integer.config_chargingSlowlyThreshold);
@@ -216,6 +226,64 @@ public class KeyguardIndicationController {
mChargingSpeed = status.getChargingSpeed(mSlowThreshold, mFastThreshold);
updateIndication();
}
@Override
public void onFingerprintHelp(int msgId, String helpString) {
KeyguardUpdateMonitor updateMonitor = KeyguardUpdateMonitor.getInstance(mContext);
if (!updateMonitor.isUnlockingWithFingerprintAllowed()) {
return;
}
int errorColor = mContext.getResources().getColor(R.color.system_warning_color, null);
if (mStatusBarKeyguardViewManager.isBouncerShowing()) {
mStatusBarKeyguardViewManager.showBouncerMessage(helpString, errorColor);
} else if (updateMonitor.isDeviceInteractive()) {
mLockIcon.setTransientFpError(true);
showTransientIndication(helpString, errorColor);
mHandler.removeMessages(MSG_CLEAR_FP_MSG);
mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_CLEAR_FP_MSG),
TRANSIENT_FP_ERROR_TIMEOUT);
}
}
@Override
public void onFingerprintError(int msgId, String errString) {
KeyguardUpdateMonitor updateMonitor = KeyguardUpdateMonitor.getInstance(mContext);
if (!updateMonitor.isUnlockingWithFingerprintAllowed()
|| msgId == FingerprintManager.FINGERPRINT_ERROR_CANCELED) {
return;
}
int errorColor = mContext.getResources().getColor(R.color.system_warning_color, null);
if (mStatusBarKeyguardViewManager.isBouncerShowing()) {
mStatusBarKeyguardViewManager.showBouncerMessage(errString, errorColor);
} else if (updateMonitor.isDeviceInteractive()) {
showTransientIndication(errString, errorColor);
// We want to keep this message around in case the screen was off
mHandler.removeMessages(MSG_HIDE_TRANSIENT);
hideTransientIndicationDelayed(5000);
} else {
mMessageToShowOnScreenOn = errString;
}
}
@Override
public void onScreenTurnedOn() {
if (mMessageToShowOnScreenOn != null) {
int errorColor = mContext.getResources().getColor(R.color.system_warning_color,
null);
showTransientIndication(mMessageToShowOnScreenOn, errorColor);
// We want to keep this message around in case the screen was off
mHandler.removeMessages(MSG_HIDE_TRANSIENT);
hideTransientIndicationDelayed(5000);
mMessageToShowOnScreenOn = null;
}
}
@Override
public void onFingerprintRunningStateChanged(boolean running) {
if (running) {
mMessageToShowOnScreenOn = null;
}
}
};
BroadcastReceiver mReceiver = new BroadcastReceiver() {
@@ -233,7 +301,15 @@ public class KeyguardIndicationController {
if (msg.what == MSG_HIDE_TRANSIENT && mTransientIndication != null) {
mTransientIndication = null;
updateIndication();
} else if (msg.what == MSG_CLEAR_FP_MSG) {
mLockIcon.setTransientFpError(false);
hideTransientIndication();
}
}
};
public void setStatusBarKeyguardViewManager(
StatusBarKeyguardViewManager statusBarKeyguardViewManager) {
mStatusBarKeyguardViewManager = statusBarKeyguardViewManager;
}
}

View File

@@ -29,7 +29,6 @@ import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.res.Configuration;
import android.hardware.fingerprint.FingerprintManager;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.IBinder;
@@ -86,7 +85,6 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
private static final Intent PHONE_INTENT = new Intent(Intent.ACTION_DIAL);
private static final int DOZE_ANIMATION_STAGGER_DELAY = 48;
private static final int DOZE_ANIMATION_ELEMENT_DURATION = 250;
private static final long TRANSIENT_FP_ERROR_TIMEOUT = 1300;
private KeyguardAffordanceView mCameraImageView;
private KeyguardAffordanceView mLeftAffordanceView;
@@ -528,7 +526,7 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
return mCameraPreview;
}
public KeyguardAffordanceView getLockIcon() {
public LockIcon getLockIcon() {
return mLockIcon;
}
@@ -613,21 +611,6 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
}
};
private final Runnable mTransientFpErrorClearRunnable = new Runnable() {
@Override
public void run() {
mLockIcon.setTransientFpError(false);
mIndicationController.hideTransientIndication();
}
};
private final Runnable mHideTransientIndicationRunnable = new Runnable() {
@Override
public void run() {
mIndicationController.hideTransientIndication();
}
};
private final KeyguardUpdateMonitorCallback mUpdateMonitorCallback =
new KeyguardUpdateMonitorCallback() {
@Override
@@ -660,39 +643,10 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
mLockIcon.update();
}
@Override
public void onFingerprintAuthenticated(int userId, boolean wakeAndUnlocking) {
}
@Override
public void onFingerprintRunningStateChanged(boolean running) {
mLockIcon.update();
}
@Override
public void onFingerprintHelp(int msgId, String helpString) {
if (!KeyguardUpdateMonitor.getInstance(mContext).isUnlockingWithFingerprintAllowed()) {
return;
}
mLockIcon.setTransientFpError(true);
mIndicationController.showTransientIndication(helpString,
getResources().getColor(R.color.system_warning_color, null));
removeCallbacks(mTransientFpErrorClearRunnable);
postDelayed(mTransientFpErrorClearRunnable, TRANSIENT_FP_ERROR_TIMEOUT);
}
@Override
public void onFingerprintError(int msgId, String errString) {
if (!KeyguardUpdateMonitor.getInstance(mContext).isUnlockingWithFingerprintAllowed()
|| msgId == FingerprintManager.FINGERPRINT_ERROR_CANCELED) {
return;
}
// TODO: Go to bouncer if this is "too many attempts" (lockout) error.
mIndicationController.showTransientIndication(errString,
getResources().getColor(R.color.system_warning_color, null));
removeCallbacks(mHideTransientIndicationRunnable);
postDelayed(mHideTransientIndicationRunnable, 5000);
}
};
public void setKeyguardIndicationController(

View File

@@ -17,7 +17,6 @@
package com.android.systemui.statusbar.phone;
import android.content.Context;
import android.view.Choreographer;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
@@ -103,6 +102,10 @@ public class KeyguardBouncer {
mKeyguardView.showPromptReason(reason);
}
public void showMessage(String message, int color) {
mKeyguardView.showMessage(message, color);
}
private void cancelShowRunnable() {
DejankUtils.removeCallbacks(mShowRunnable);
mShowingSoon = false;

View File

@@ -780,7 +780,8 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
mKeyguardBottomArea.setAssistManager(mAssistManager);
mKeyguardIndicationController = new KeyguardIndicationController(mContext,
(KeyguardIndicationTextView) mStatusBarWindow.findViewById(
R.id.keyguard_indication_text));
R.id.keyguard_indication_text),
mKeyguardBottomArea.getLockIcon());
mKeyguardBottomArea.setKeyguardIndicationController(mKeyguardIndicationController);
// set the inital view visibility
@@ -1011,6 +1012,8 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
KeyguardViewMediator keyguardViewMediator = getComponent(KeyguardViewMediator.class);
mStatusBarKeyguardViewManager = keyguardViewMediator.registerStatusBar(this,
mStatusBarWindow, mStatusBarWindowManager, mScrimController);
mKeyguardIndicationController.setStatusBarKeyguardViewManager(
mStatusBarKeyguardViewManager);
mKeyguardViewMediatorCallback = keyguardViewMediator.getViewMediatorCallback();
}

View File

@@ -491,4 +491,8 @@ public class StatusBarKeyguardViewManager {
mPhoneStatusBar.getNavigationBarView().setWakeAndUnlocking(true);
}
}
public void showBouncerMessage(String message, int color) {
mBouncer.showMessage(message, color);
}
}