summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--packages/Keyguard/src/com/android/keyguard/FaceUnlock.java4
-rw-r--r--packages/Keyguard/src/com/android/keyguard/KeyguardAbsKeyInputView.java8
-rw-r--r--packages/Keyguard/src/com/android/keyguard/KeyguardAccountView.java4
-rw-r--r--packages/Keyguard/src/com/android/keyguard/KeyguardActivityLauncher.java11
-rw-r--r--packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java637
-rw-r--r--packages/Keyguard/src/com/android/keyguard/KeyguardPatternView.java4
-rw-r--r--packages/Keyguard/src/com/android/keyguard/KeyguardSecurityCallback.java22
-rw-r--r--packages/Keyguard/src/com/android/keyguard/KeyguardSecurityContainer.java483
-rw-r--r--packages/Keyguard/src/com/android/keyguard/KeyguardSelectorView.java34
9 files changed, 630 insertions, 577 deletions
diff --git a/packages/Keyguard/src/com/android/keyguard/FaceUnlock.java b/packages/Keyguard/src/com/android/keyguard/FaceUnlock.java
index 689366b..de839c6 100644
--- a/packages/Keyguard/src/com/android/keyguard/FaceUnlock.java
+++ b/packages/Keyguard/src/com/android/keyguard/FaceUnlock.java
@@ -304,7 +304,7 @@ public class FaceUnlock implements BiometricSensorUnlock, Handler.Callback {
int currentUserId = mLockPatternUtils.getCurrentUser();
if (authenticatedUserId == currentUserId) {
if (DEBUG) Log.d(TAG, "Unlocking for user " + authenticatedUserId);
- mKeyguardScreenCallback.reportSuccessfulUnlockAttempt();
+ mKeyguardScreenCallback.reportUnlockAttempt(true);
mKeyguardScreenCallback.dismiss(true);
} else {
Log.d(TAG, "Ignoring unlock for authenticated user (" + authenticatedUserId +
@@ -335,7 +335,7 @@ public class FaceUnlock implements BiometricSensorUnlock, Handler.Callback {
// next time the user visits keyguard.
KeyguardUpdateMonitor.getInstance(mContext).setAlternateUnlockEnabled(false);
- mKeyguardScreenCallback.reportFailedUnlockAttempt();
+ mKeyguardScreenCallback.reportUnlockAttempt(false);
}
/**
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardAbsKeyInputView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardAbsKeyInputView.java
index 461fd77..3950159 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardAbsKeyInputView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardAbsKeyInputView.java
@@ -154,14 +154,14 @@ public abstract class KeyguardAbsKeyInputView extends LinearLayout
protected void verifyPasswordAndUnlock() {
String entry = mPasswordEntry.getText().toString();
if (mLockPatternUtils.checkPassword(entry)) {
- mCallback.reportSuccessfulUnlockAttempt();
+ mCallback.reportUnlockAttempt(true);
mCallback.dismiss(true);
} else if (entry.length() > MINIMUM_PASSWORD_LENGTH_BEFORE_REPORT ) {
// to avoid accidental lockout, only count attempts that are long enough to be a
// real password. This may require some tweaking.
- mCallback.reportFailedUnlockAttempt();
- if (0 == (mCallback.getFailedAttempts()
- % LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT)) {
+ mCallback.reportUnlockAttempt(false);
+ int attempts = KeyguardUpdateMonitor.getInstance(mContext).getFailedUnlockAttempts();
+ if (0 == (attempts % LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT)) {
long deadline = mLockPatternUtils.setLockoutAttemptDeadline();
handleAttemptLockout(deadline);
}
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardAccountView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardAccountView.java
index 6b8be69..f69fa5f 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardAccountView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardAccountView.java
@@ -177,14 +177,14 @@ public class KeyguardAccountView extends LinearLayout implements KeyguardSecurit
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
mContext.startActivityAsUser(intent,
new UserHandle(mLockPatternUtils.getCurrentUser()));
- mCallback.reportSuccessfulUnlockAttempt();
+ mCallback.reportUnlockAttempt(true);
// dismiss keyguard
mCallback.dismiss(true);
} else {
mSecurityMessageDisplay.setMessage(R.string.kg_login_invalid_input, true);
mPassword.setText("");
- mCallback.reportFailedUnlockAttempt();
+ mCallback.reportUnlockAttempt(false);
}
}
});
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardActivityLauncher.java b/packages/Keyguard/src/com/android/keyguard/KeyguardActivityLauncher.java
index 0a915ea..368a97a 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardActivityLauncher.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardActivityLauncher.java
@@ -53,10 +53,12 @@ public abstract class KeyguardActivityLauncher {
abstract Context getContext();
- abstract KeyguardSecurityCallback getCallback();
-
abstract LockPatternUtils getLockPatternUtils();
+ abstract void setOnDismissAction(OnDismissAction action);
+
+ abstract void requestDismissKeyguard();
+
public static class CameraWidgetInfo {
public String contextPackage;
public int layoutId;
@@ -190,8 +192,7 @@ public abstract class KeyguardActivityLauncher {
} else {
// Create a runnable to start the activity and ask the user to enter their
// credentials.
- KeyguardSecurityCallback callback = getCallback();
- callback.setOnDismissAction(new OnDismissAction() {
+ setOnDismissAction(new OnDismissAction() {
@Override
public boolean onDismiss() {
dismissKeyguardOnNextActivity();
@@ -199,7 +200,7 @@ public abstract class KeyguardActivityLauncher {
return true;
}
});
- callback.dismiss(false);
+ requestDismissKeyguard();
}
}
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java
index dfcd8a8..1548dee 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java
@@ -18,6 +18,7 @@ package com.android.keyguard;
import android.nfc.NfcUnlock;
import com.android.internal.widget.LockPatternUtils;
+import com.android.keyguard.KeyguardSecurityContainer.SecurityCallback;
import com.android.keyguard.KeyguardSecurityModel.SecurityMode;
import com.android.keyguard.KeyguardUpdateMonitor.DisplayClientState;
@@ -84,20 +85,12 @@ public class KeyguardHostView extends KeyguardViewBase {
private AppWidgetHost mAppWidgetHost;
private AppWidgetManager mAppWidgetManager;
private KeyguardWidgetPager mAppWidgetContainer;
- private KeyguardSecurityViewFlipper mSecurityViewContainer;
- private KeyguardSelectorView mKeyguardSelectorView;
private KeyguardTransportControlView mTransportControl;
- private boolean mIsVerifyUnlockOnly;
- private boolean mEnableFallback; // TODO: This should get the value from KeyguardPatternView
- private SecurityMode mCurrentSecuritySelection = SecurityMode.Invalid;
private int mAppWidgetToShow;
- protected OnDismissAction mDismissAction;
-
protected int mFailedAttempts;
private LockPatternUtils mLockPatternUtils;
- private KeyguardSecurityModel mSecurityModel;
private KeyguardViewStateManager mViewStateManager;
private Rect mTempRect = new Rect();
@@ -126,6 +119,8 @@ public class KeyguardHostView extends KeyguardViewBase {
private Runnable mPostBootCompletedRunnable;
+ private OnDismissAction mDismissAction;
+
/*package*/ interface UserSwitcherCallback {
void hideSecurityView(int duration);
void showSecurityView();
@@ -186,8 +181,6 @@ public class KeyguardHostView extends KeyguardViewBase {
mAppWidgetManager = AppWidgetManager.getInstance(userContext);
- mSecurityModel = new KeyguardSecurityModel(context);
-
mViewStateManager = new KeyguardViewStateManager(this);
mUserSetupCompleted = Settings.Secure.getIntForUser(mContext.getContentResolver(),
@@ -207,13 +200,6 @@ public class KeyguardHostView extends KeyguardViewBase {
}
}
- public void announceCurrentSecurityMethod() {
- View v = (View) getSecurityView(mCurrentSecuritySelection);
- if (v != null) {
- v.announceForAccessibility(v.getContentDescription());
- }
- }
-
private void getInitialTransportState() {
DisplayClientState dcs = KeyguardUpdateMonitor.getInstance(mContext)
.getCachedDisplayClientState();
@@ -300,9 +286,10 @@ public class KeyguardHostView extends KeyguardViewBase {
}
@Override
public void onNfcUnlock() {
- if (NfcUnlock.getPropertyEnabled()) mCallback.dismiss(true);
+ if (NfcUnlock.getPropertyEnabled()) {
+ dismiss(true);
+ }
}
-
};
private static final boolean isMusicPlaying(int playbackState) {
@@ -322,14 +309,15 @@ public class KeyguardHostView extends KeyguardViewBase {
private SlidingChallengeLayout mSlidingChallengeLayout;
private MultiPaneChallengeLayout mMultiPaneChallengeLayout;
+ private KeyguardSecurityContainer mSecurityContainer;
@Override
public boolean onTouchEvent(MotionEvent ev) {
boolean result = super.onTouchEvent(ev);
mTempRect.set(0, 0, 0, 0);
- offsetRectIntoDescendantCoords(mSecurityViewContainer, mTempRect);
+ offsetRectIntoDescendantCoords(mSecurityContainer, mTempRect);
ev.offsetLocation(mTempRect.left, mTempRect.top);
- result = mSecurityViewContainer.dispatchTouchEvent(ev) || result;
+ result = mSecurityContainer.dispatchTouchEvent(ev) || result;
ev.offsetLocation(-mTempRect.left, -mTempRect.top);
return result;
}
@@ -383,9 +371,48 @@ public class KeyguardHostView extends KeyguardViewBase {
mAppWidgetContainer.setBouncerAnimationDuration(challenge.getBouncerAnimationDuration());
mViewStateManager.setPagedView(mAppWidgetContainer);
mViewStateManager.setChallengeLayout(challenge);
- mSecurityViewContainer = (KeyguardSecurityViewFlipper) findViewById(R.id.view_flipper);
- mKeyguardSelectorView = (KeyguardSelectorView) findViewById(R.id.keyguard_selector_view);
- mViewStateManager.setSecurityViewContainer(mSecurityViewContainer);
+
+ mSecurityContainer =
+ (KeyguardSecurityContainer) findViewById(R.id.keyguard_security_container);
+ mSecurityContainer.setLockPatternUtils(mLockPatternUtils);
+ mSecurityContainer.setSecurityCallback(new SecurityCallback() {
+ @Override
+ public void userActivity(long timeout) {
+ if (mViewMediatorCallback != null) {
+ mViewMediatorCallback.userActivity(timeout);
+ }
+ }
+
+ @Override
+ public void dismiss(boolean authenticated) {
+ KeyguardHostView.this.dismiss(authenticated);
+ }
+
+ @Override
+ public void finish() {
+
+ // If the alternate unlock was suppressed, it can now be safely
+ // enabled because the user has left keyguard.
+ KeyguardUpdateMonitor.getInstance(mContext).setAlternateUnlockEnabled(true);
+
+ // If there's a pending runnable because the user interacted with a widget
+ // and we're leaving keyguard, then run it.
+ boolean deferKeyguardDone = false;
+ if (mDismissAction != null) {
+ deferKeyguardDone = mDismissAction.onDismiss();
+ mDismissAction = null;
+ }
+ if (mViewMediatorCallback != null) {
+ if (deferKeyguardDone) {
+ mViewMediatorCallback.keyguardDonePending();
+ } else {
+ mViewMediatorCallback.keyguardDone(true);
+ }
+ }
+ }
+ });
+
+ mViewStateManager.setSecurityViewContainer(mSecurityContainer);
setBackButtonEnabled(false);
@@ -402,8 +429,8 @@ public class KeyguardHostView extends KeyguardViewBase {
};
}
- showPrimarySecurityScreen(false);
- updateSecurityViews();
+ mSecurityContainer.showPrimarySecurityScreen(false);
+ mSecurityContainer.updateSecurityViews(mViewStateManager.isBouncing());
enableUserSelectorIfNecessary();
}
@@ -465,32 +492,10 @@ public class KeyguardHostView extends KeyguardViewBase {
|| (mDisabledFeatures & DevicePolicyManager.KEYGUARD_DISABLE_SECURE_CAMERA) != 0;
}
- private void updateSecurityViews() {
- int children = mSecurityViewContainer.getChildCount();
- for (int i = 0; i < children; i++) {
- updateSecurityView(mSecurityViewContainer.getChildAt(i));
- }
- }
-
- private void updateSecurityView(View view) {
- if (view instanceof KeyguardSecurityView) {
- KeyguardSecurityView ksv = (KeyguardSecurityView) view;
- ksv.setKeyguardCallback(mCallback);
- ksv.setLockPatternUtils(mLockPatternUtils);
- if (mViewStateManager.isBouncing()) {
- ksv.showBouncer(0);
- } else {
- ksv.hideBouncer(0);
- }
- } else {
- Log.w(TAG, "View " + view + " is not a KeyguardSecurityView");
- }
- }
-
void setLockPatternUtils(LockPatternUtils utils) {
- mSecurityModel.setLockPatternUtils(utils);
mLockPatternUtils = utils;
- updateSecurityViews();
+ mSecurityContainer.setLockPatternUtils(utils);
+ mSecurityContainer.updateSecurityViews(mViewStateManager.isBouncing());
}
@Override
@@ -577,265 +582,7 @@ public class KeyguardHostView extends KeyguardViewBase {
return -1;
}
- private KeyguardSecurityCallback mCallback = new KeyguardSecurityCallback() {
-
- public void userActivity(long timeout) {
- if (mViewMediatorCallback != null) {
- mViewMediatorCallback.userActivity(timeout);
- }
- }
-
- public void dismiss(boolean authenticated) {
- showNextSecurityScreenOrFinish(authenticated);
- }
-
- public boolean isVerifyUnlockOnly() {
- return mIsVerifyUnlockOnly;
- }
-
- public void reportSuccessfulUnlockAttempt() {
- KeyguardUpdateMonitor.getInstance(mContext).clearFailedUnlockAttempts();
- mLockPatternUtils.reportSuccessfulPasswordAttempt();
- }
-
- public void reportFailedUnlockAttempt() {
- if (mCurrentSecuritySelection == SecurityMode.Biometric) {
- KeyguardUpdateMonitor.getInstance(mContext).reportFailedBiometricUnlockAttempt();
- } else {
- KeyguardHostView.this.reportFailedUnlockAttempt();
- }
- }
-
- public int getFailedAttempts() {
- return KeyguardUpdateMonitor.getInstance(mContext).getFailedUnlockAttempts();
- }
-
- @Override
- public void showBackupSecurity() {
- KeyguardHostView.this.showBackupSecurityScreen();
- }
- @Override
- public void setOnDismissAction(OnDismissAction action) {
- KeyguardHostView.this.setOnDismissAction(action);
- }
-
- };
-
- private void showDialog(String title, String message) {
- final AlertDialog dialog = new AlertDialog.Builder(mContext)
- .setTitle(title)
- .setMessage(message)
- .setNeutralButton(R.string.ok, null)
- .create();
- if (!(mContext instanceof Activity)) {
- dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
- }
- dialog.show();
- }
-
- private void showTimeoutDialog() {
- int timeoutInSeconds = (int) LockPatternUtils.FAILED_ATTEMPT_TIMEOUT_MS / 1000;
- int messageId = 0;
-
- switch (mSecurityModel.getSecurityMode()) {
- case Pattern:
- messageId = R.string.kg_too_many_failed_pattern_attempts_dialog_message;
- break;
- case PIN:
- messageId = R.string.kg_too_many_failed_pin_attempts_dialog_message;
- break;
- case Password:
- messageId = R.string.kg_too_many_failed_password_attempts_dialog_message;
- break;
- }
-
- if (messageId != 0) {
- final String message = mContext.getString(messageId,
- KeyguardUpdateMonitor.getInstance(mContext).getFailedUnlockAttempts(),
- timeoutInSeconds);
- showDialog(null, message);
- }
- }
-
- private void showAlmostAtWipeDialog(int attempts, int remaining) {
- String message = mContext.getString(R.string.kg_failed_attempts_almost_at_wipe,
- attempts, remaining);
- showDialog(null, message);
- }
-
- private void showWipeDialog(int attempts) {
- String message = mContext.getString(R.string.kg_failed_attempts_now_wiping, attempts);
- showDialog(null, message);
- }
-
- private void showAlmostAtAccountLoginDialog() {
- final int timeoutInSeconds = (int) LockPatternUtils.FAILED_ATTEMPT_TIMEOUT_MS / 1000;
- final int count = LockPatternUtils.FAILED_ATTEMPTS_BEFORE_RESET
- - LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT;
- String message = mContext.getString(R.string.kg_failed_attempts_almost_at_login,
- count, LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT, timeoutInSeconds);
- showDialog(null, message);
- }
-
- private void reportFailedUnlockAttempt() {
- final KeyguardUpdateMonitor monitor = KeyguardUpdateMonitor.getInstance(mContext);
- final int failedAttempts = monitor.getFailedUnlockAttempts() + 1; // +1 for this time
-
- if (DEBUG) Log.d(TAG, "reportFailedPatternAttempt: #" + failedAttempts);
-
- SecurityMode mode = mSecurityModel.getSecurityMode();
- final boolean usingPattern = mode == KeyguardSecurityModel.SecurityMode.Pattern;
-
- final int failedAttemptsBeforeWipe = mLockPatternUtils.getDevicePolicyManager()
- .getMaximumFailedPasswordsForWipe(null, mLockPatternUtils.getCurrentUser());
-
- final int failedAttemptWarning = LockPatternUtils.FAILED_ATTEMPTS_BEFORE_RESET
- - LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT;
-
- final int remainingBeforeWipe = failedAttemptsBeforeWipe > 0 ?
- (failedAttemptsBeforeWipe - failedAttempts)
- : Integer.MAX_VALUE; // because DPM returns 0 if no restriction
-
- boolean showTimeout = false;
- if (remainingBeforeWipe < LockPatternUtils.FAILED_ATTEMPTS_BEFORE_WIPE_GRACE) {
- // If we reach this code, it means the user has installed a DevicePolicyManager
- // that requests device wipe after N attempts. Once we get below the grace
- // period, we'll post this dialog every time as a clear warning until the
- // bombshell hits and the device is wiped.
- if (remainingBeforeWipe > 0) {
- showAlmostAtWipeDialog(failedAttempts, remainingBeforeWipe);
- } else {
- // Too many attempts. The device will be wiped shortly.
- Slog.i(TAG, "Too many unlock attempts; device will be wiped!");
- showWipeDialog(failedAttempts);
- }
- } else {
- showTimeout =
- (failedAttempts % LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT) == 0;
- if (usingPattern && mEnableFallback) {
- if (failedAttempts == failedAttemptWarning) {
- showAlmostAtAccountLoginDialog();
- showTimeout = false; // don't show both dialogs
- } else if (failedAttempts >= LockPatternUtils.FAILED_ATTEMPTS_BEFORE_RESET) {
- mLockPatternUtils.setPermanentlyLocked(true);
- showSecurityScreen(SecurityMode.Account);
- // don't show timeout dialog because we show account unlock screen next
- showTimeout = false;
- }
- }
- }
- monitor.reportFailedUnlockAttempt();
- mLockPatternUtils.reportFailedPasswordAttempt();
- if (showTimeout) {
- showTimeoutDialog();
- }
- }
-
- /**
- * Shows the primary security screen for the user. This will be either the multi-selector
- * or the user's security method.
- * @param turningOff true if the device is being turned off
- */
- void showPrimarySecurityScreen(boolean turningOff) {
- SecurityMode securityMode = mSecurityModel.getSecurityMode();
- if (DEBUG) Log.v(TAG, "showPrimarySecurityScreen(turningOff=" + turningOff + ")");
- if (!turningOff &&
- KeyguardUpdateMonitor.getInstance(mContext).isAlternateUnlockEnabled()) {
- // If we're not turning off, then allow biometric alternate.
- // We'll reload it when the device comes back on.
- securityMode = mSecurityModel.getAlternateFor(securityMode);
- }
- showSecurityScreen(securityMode);
- }
-
- /**
- * Shows the backup security screen for the current security mode. This could be used for
- * password recovery screens but is currently only used for pattern unlock to show the
- * account unlock screen and biometric unlock to show the user's normal unlock.
- */
- private void showBackupSecurityScreen() {
- if (DEBUG) Log.d(TAG, "showBackupSecurity()");
- SecurityMode backup = mSecurityModel.getBackupSecurityMode(mCurrentSecuritySelection);
- showSecurityScreen(backup);
- }
-
- public boolean showNextSecurityScreenIfPresent() {
- SecurityMode securityMode = mSecurityModel.getSecurityMode();
- // Allow an alternate, such as biometric unlock
- securityMode = mSecurityModel.getAlternateFor(securityMode);
- if (SecurityMode.None == securityMode) {
- return false;
- } else {
- showSecurityScreen(securityMode); // switch to the alternate security view
- return true;
- }
- }
-
- private void showNextSecurityScreenOrFinish(boolean authenticated) {
- if (DEBUG) Log.d(TAG, "showNextSecurityScreenOrFinish(" + authenticated + ")");
- boolean finish = false;
- if (SecurityMode.None == mCurrentSecuritySelection) {
- SecurityMode securityMode = mSecurityModel.getSecurityMode();
- // Allow an alternate, such as biometric unlock
- securityMode = mSecurityModel.getAlternateFor(securityMode);
- if (SecurityMode.None == securityMode) {
- finish = true; // no security required
- } else {
- showSecurityScreen(securityMode); // switch to the alternate security view
- }
- } else if (authenticated) {
- switch (mCurrentSecuritySelection) {
- case Pattern:
- case Password:
- case PIN:
- case Account:
- case Biometric:
- finish = true;
- break;
-
- case SimPin:
- case SimPuk:
- // Shortcut for SIM PIN/PUK to go to directly to user's security screen or home
- SecurityMode securityMode = mSecurityModel.getSecurityMode();
- if (securityMode != SecurityMode.None) {
- showSecurityScreen(securityMode);
- } else {
- finish = true;
- }
- break;
-
- default:
- Log.v(TAG, "Bad security screen " + mCurrentSecuritySelection + ", fail safe");
- showPrimarySecurityScreen(false);
- break;
- }
- } else {
- showPrimarySecurityScreen(false);
- }
- if (finish) {
- // If the alternate unlock was suppressed, it can now be safely
- // enabled because the user has left keyguard.
- KeyguardUpdateMonitor.getInstance(mContext).setAlternateUnlockEnabled(true);
-
- // If there's a pending runnable because the user interacted with a widget
- // and we're leaving keyguard, then run it.
- boolean deferKeyguardDone = false;
- if (mDismissAction != null) {
- deferKeyguardDone = mDismissAction.onDismiss();
- mDismissAction = null;
- }
- if (mViewMediatorCallback != null) {
- if (deferKeyguardDone) {
- mViewMediatorCallback.keyguardDonePending();
- } else {
- mViewMediatorCallback.keyguardDone(true);
- }
- }
- } else {
- mViewStateManager.showBouncer(true);
- }
- }
private static class MyOnClickHandler extends OnClickHandler {
@@ -843,17 +590,17 @@ public class KeyguardHostView extends KeyguardViewBase {
// due to Binder GC linkages to AppWidgetHost. By the same token,
// this click handler should not keep references to any large
// objects.
- WeakReference<KeyguardHostView> mThis;
+ WeakReference<KeyguardHostView> mKeyguardHostView;
MyOnClickHandler(KeyguardHostView hostView) {
- mThis = new WeakReference<KeyguardHostView>(hostView);
+ mKeyguardHostView = new WeakReference<KeyguardHostView>(hostView);
}
@Override
public boolean onClickHandler(final View view,
final android.app.PendingIntent pendingIntent,
final Intent fillInIntent) {
- KeyguardHostView hostView = mThis.get();
+ KeyguardHostView hostView = mKeyguardHostView.get();
if (hostView == null) {
return false;
}
@@ -883,7 +630,7 @@ public class KeyguardHostView extends KeyguardViewBase {
if (hostView.mViewStateManager.isChallengeShowing()) {
hostView.mViewStateManager.showBouncer(true);
} else {
- hostView.mCallback.dismiss(false);
+ hostView.dismiss();
}
return true;
} else {
@@ -892,153 +639,11 @@ public class KeyguardHostView extends KeyguardViewBase {
};
};
- // Used to ignore callbacks from methods that are no longer current (e.g. face unlock).
- // This avoids unwanted asynchronous events from messing with the state.
- private KeyguardSecurityCallback mNullCallback = new KeyguardSecurityCallback() {
-
- @Override
- public void userActivity(long timeout) {
- }
-
- @Override
- public void showBackupSecurity() {
- }
-
- @Override
- public void setOnDismissAction(OnDismissAction action) {
- }
-
- @Override
- public void reportSuccessfulUnlockAttempt() {
- }
-
- @Override
- public void reportFailedUnlockAttempt() {
- }
-
- @Override
- public boolean isVerifyUnlockOnly() {
- return false;
- }
-
- @Override
- public int getFailedAttempts() {
- return 0;
- }
-
- @Override
- public void dismiss(boolean securityVerified) {
- }
- };
-
- /**
- * Sets an action to perform when keyguard is dismissed.
- * @param action
- */
- protected void setOnDismissAction(OnDismissAction action) {
- mDismissAction = action;
- }
-
- private KeyguardSecurityView getSecurityView(SecurityMode securityMode) {
- final int securityViewIdForMode = getSecurityViewIdForMode(securityMode);
- KeyguardSecurityView view = null;
- final int children = mSecurityViewContainer.getChildCount();
- for (int child = 0; child < children; child++) {
- if (mSecurityViewContainer.getChildAt(child).getId() == securityViewIdForMode) {
- view = ((KeyguardSecurityView)mSecurityViewContainer.getChildAt(child));
- break;
- }
- }
- int layoutId = getLayoutIdFor(securityMode);
- if (view == null && layoutId != 0) {
- final LayoutInflater inflater = LayoutInflater.from(mContext);
- if (DEBUG) Log.v(TAG, "inflating id = " + layoutId);
- View v = inflater.inflate(layoutId, mSecurityViewContainer, false);
- mSecurityViewContainer.addView(v);
- updateSecurityView(v);
- view = (KeyguardSecurityView)v;
- }
-
- if (view instanceof KeyguardSelectorView) {
- KeyguardSelectorView selectorView = (KeyguardSelectorView) view;
- View carrierText = selectorView.findViewById(R.id.keyguard_selector_fade_container);
- selectorView.setCarrierArea(carrierText);
- }
-
- return view;
- }
-
- /**
- * Switches to the given security view unless it's already being shown, in which case
- * this is a no-op.
- *
- * @param securityMode
- */
- private void showSecurityScreen(SecurityMode securityMode) {
- if (DEBUG) Log.d(TAG, "showSecurityScreen(" + securityMode + ")");
-
- if (securityMode == mCurrentSecuritySelection) return;
-
- KeyguardSecurityView oldView = getSecurityView(mCurrentSecuritySelection);
- KeyguardSecurityView newView = getSecurityView(securityMode);
-
- // Enter full screen mode if we're in SIM or Account screen
- boolean fullScreenEnabled = getResources().getBoolean(R.bool.kg_sim_puk_account_full_screen);
- boolean isSimOrAccount = securityMode == SecurityMode.SimPin
- || securityMode == SecurityMode.SimPuk
- || securityMode == SecurityMode.Account;
- mAppWidgetContainer.setVisibility(
- isSimOrAccount && fullScreenEnabled ? View.GONE : View.VISIBLE);
-
- // Don't show camera or search in navbar when SIM or Account screen is showing
- setSystemUiVisibility(isSimOrAccount ?
- (getSystemUiVisibility() | View.STATUS_BAR_DISABLE_SEARCH)
- : (getSystemUiVisibility() & ~View.STATUS_BAR_DISABLE_SEARCH));
-
- if (mSlidingChallengeLayout != null) {
- mSlidingChallengeLayout.setChallengeInteractive(!fullScreenEnabled);
- }
-
- // Emulate Activity life cycle
- if (oldView != null) {
- oldView.onPause();
- oldView.setKeyguardCallback(mNullCallback); // ignore requests from old view
- }
- newView.onResume(KeyguardSecurityView.VIEW_REVEALED);
- newView.setKeyguardCallback(mCallback);
-
- final boolean needsInput = newView.needsInput();
- if (mViewMediatorCallback != null) {
- mViewMediatorCallback.setNeedsInput(needsInput);
- }
-
- // Find and show this child.
- final int childCount = mSecurityViewContainer.getChildCount();
-
- final int securityViewIdForMode = getSecurityViewIdForMode(securityMode);
- for (int i = 0; i < childCount; i++) {
- if (mSecurityViewContainer.getChildAt(i).getId() == securityViewIdForMode) {
- mSecurityViewContainer.setDisplayedChild(i);
- break;
- }
- }
-
- if (securityMode == SecurityMode.None) {
- // Discard current runnable if we're switching back to the selector view
- setOnDismissAction(null);
- }
- if (securityMode == SecurityMode.Account && !mLockPatternUtils.isPermanentlyLocked()) {
- // we're showing account as a backup, provide a way to get back to primary
- setBackButtonEnabled(true);
- }
- mCurrentSecuritySelection = securityMode;
- }
-
@Override
public void onScreenTurnedOn() {
if (DEBUG) Log.d(TAG, "screen on, instance " + Integer.toHexString(hashCode()));
- showPrimarySecurityScreen(false);
- getSecurityView(mCurrentSecuritySelection).onResume(KeyguardSecurityView.SCREEN_ON);
+ mSecurityContainer.showPrimarySecurityScreen(false);
+ mSecurityContainer.onResume(KeyguardSecurityView.SCREEN_ON);
// This is a an attempt to fix bug 7137389 where the device comes back on but the entire
// layout is blank but forcing a layout causes it to reappear (e.g. with with
@@ -1065,8 +670,8 @@ public class KeyguardHostView extends KeyguardViewBase {
if (KeyguardUpdateMonitor.getInstance(mContext).hasBootCompleted()) {
checkAppWidgetConsistency();
}
- showPrimarySecurityScreen(true);
- getSecurityView(mCurrentSecuritySelection).onPause();
+ mSecurityContainer.showPrimarySecurityScreen(true);
+ mSecurityContainer.onPause();
CameraWidgetFrame cameraPage = findCameraPage();
if (cameraPage != null) {
cameraPage.onScreenTurnedOff();
@@ -1082,12 +687,12 @@ public class KeyguardHostView extends KeyguardViewBase {
@Override
public void show() {
if (DEBUG) Log.d(TAG, "show()");
- showPrimarySecurityScreen(false);
+ mSecurityContainer.showPrimarySecurityScreen(false);
}
@Override
public void verifyUnlock() {
- SecurityMode securityMode = mSecurityModel.getSecurityMode();
+ SecurityMode securityMode = mSecurityContainer.getSecurityMode();
if (securityMode == KeyguardSecurityModel.SecurityMode.None) {
if (mViewMediatorCallback != null) {
mViewMediatorCallback.keyguardDone(true);
@@ -1101,37 +706,7 @@ public class KeyguardHostView extends KeyguardViewBase {
}
} else {
// otherwise, go to the unlock screen, see if they can verify it
- mIsVerifyUnlockOnly = true;
- showSecurityScreen(securityMode);
- }
- }
-
- private int getSecurityViewIdForMode(SecurityMode securityMode) {
- switch (securityMode) {
- case None: return R.id.keyguard_selector_view;
- case Pattern: return R.id.keyguard_pattern_view;
- case PIN: return R.id.keyguard_pin_view;
- case Password: return R.id.keyguard_password_view;
- case Biometric: return R.id.keyguard_face_unlock_view;
- case Account: return R.id.keyguard_account_view;
- case SimPin: return R.id.keyguard_sim_pin_view;
- case SimPuk: return R.id.keyguard_sim_puk_view;
- }
- return 0;
- }
-
- private int getLayoutIdFor(SecurityMode securityMode) {
- switch (securityMode) {
- case None: return R.layout.keyguard_selector_view;
- case Pattern: return R.layout.keyguard_pattern_view;
- case PIN: return R.layout.keyguard_pin_view;
- case Password: return R.layout.keyguard_password_view;
- case Biometric: return R.layout.keyguard_face_unlock_view;
- case Account: return R.layout.keyguard_account_view;
- case SimPin: return R.layout.keyguard_sim_pin_view;
- case SimPuk: return R.layout.keyguard_sim_puk_view;
- default:
- return 0;
+ mSecurityContainer.verifyUnlock();
}
}
@@ -1189,14 +764,19 @@ public class KeyguardHostView extends KeyguardViewBase {
}
@Override
- KeyguardSecurityCallback getCallback() {
- return mCallback;
+ void setOnDismissAction(OnDismissAction action) {
+ mDismissAction = action;
}
@Override
LockPatternUtils getLockPatternUtils() {
return mLockPatternUtils;
}
+
+ @Override
+ void requestDismissKeyguard() {
+ KeyguardHostView.this.dismiss(false);
+ }
};
private int numWidgets() {
@@ -1618,18 +1198,18 @@ public class KeyguardHostView extends KeyguardViewBase {
UserSwitcherCallback callback = new UserSwitcherCallback() {
@Override
public void hideSecurityView(int duration) {
- mSecurityViewContainer.animate().alpha(0).setDuration(duration);
+ mSecurityContainer.animate().alpha(0).setDuration(duration);
}
@Override
public void showSecurityView() {
- mSecurityViewContainer.setAlpha(1.0f);
+ mSecurityContainer.setAlpha(1.0f);
}
@Override
public void showUnlockHint() {
- if (mKeyguardSelectorView != null) {
- mKeyguardSelectorView.showUsabilityHint();
+ if (mSecurityContainer != null) {
+ mSecurityContainer.showUsabilityHint();
}
}
@@ -1688,21 +1268,21 @@ public class KeyguardHostView extends KeyguardViewBase {
public boolean handleMenuKey() {
// The following enables the MENU key to work for testing automation
if (shouldEnableMenuKey()) {
- showNextSecurityScreenOrFinish(false);
+ dismiss();
return true;
}
return false;
}
public boolean handleBackKey() {
- if (mCurrentSecuritySelection == SecurityMode.Account) {
+ if (mSecurityContainer.getCurrentSecuritySelection() == SecurityMode.Account) {
// go back to primary screen and re-disable back
setBackButtonEnabled(false);
- showPrimarySecurityScreen(false /*turningOff*/);
+ mSecurityContainer.showPrimarySecurityScreen(false /*turningOff*/);
return true;
}
- if (mCurrentSecuritySelection != SecurityMode.None) {
- mCallback.dismiss(false);
+ if (mSecurityContainer.getCurrentSecuritySelection() != SecurityMode.None) {
+ mSecurityContainer.dismiss(false);
return true;
}
return false;
@@ -1712,7 +1292,54 @@ public class KeyguardHostView extends KeyguardViewBase {
* Dismisses the keyguard by going to the next screen or making it gone.
*/
public void dismiss() {
- showNextSecurityScreenOrFinish(false);
+ dismiss(false);
+ }
+
+ private void dismiss(boolean authenticated) {
+ boolean finished = mSecurityContainer.showNextSecurityScreenOrFinish(authenticated);
+ if (!finished) {
+ updateAfterSecuritySelection();
+ mViewStateManager.showBouncer(true);
+ }
+ }
+
+ void setOnDismissAction(OnDismissAction action) {
+ mDismissAction = action;
+ }
+
+ public void announceCurrentSecurityMethod() {
+ mSecurityContainer.announceCurrentSecurityMethod();
+ }
+
+ private void updateAfterSecuritySelection() {
+ // Enable or disable the back button based on security mode
+ if (mSecurityContainer.getSecurityMode() == SecurityMode.Account
+ && !mLockPatternUtils.isPermanentlyLocked()) {
+ // we're showing account as a backup, provide a way to get back to primary
+ setBackButtonEnabled(true);
+ }
+
+ // Enter full screen mode if we're in SIM or Account screen
+ SecurityMode securityMode = mSecurityContainer.getSecurityMode();
+ boolean isFullScreen = getResources().getBoolean(R.bool.kg_sim_puk_account_full_screen);
+ boolean isSimOrAccount = securityMode == SecurityMode.SimPin
+ || securityMode == SecurityMode.SimPuk
+ || securityMode == SecurityMode.Account;
+ mAppWidgetContainer.setVisibility(
+ isSimOrAccount && isFullScreen ? View.GONE : View.VISIBLE);
+
+ // Don't show camera or search in navbar when SIM or Account screen is showing
+ setSystemUiVisibility(isSimOrAccount ?
+ (getSystemUiVisibility() | View.STATUS_BAR_DISABLE_SEARCH)
+ : (getSystemUiVisibility() & ~View.STATUS_BAR_DISABLE_SEARCH));
+
+ if (mSlidingChallengeLayout != null) {
+ mSlidingChallengeLayout.setChallengeInteractive(!isFullScreen);
+ }
+
+ if (mViewMediatorCallback != null) {
+ mViewMediatorCallback.setNeedsInput(mSecurityContainer.needsInput());
+ }
}
public void showAssistant() {
@@ -1726,9 +1353,7 @@ public class KeyguardHostView extends KeyguardViewBase {
getHandler(), null);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-
- mActivityLauncher.launchActivityWithAnimation(
- intent, false, opts.toBundle(), null, null);
+ mActivityLauncher.launchActivityWithAnimation(intent, false, opts.toBundle(), null, null);
}
public void dispatch(MotionEvent event) {
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardPatternView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardPatternView.java
index e7f1259..0fa27c1 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardPatternView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardPatternView.java
@@ -260,7 +260,7 @@ public class KeyguardPatternView extends LinearLayout implements KeyguardSecurit
public void onPatternDetected(List<LockPatternView.Cell> pattern) {
if (mLockPatternUtils.checkPattern(pattern)) {
- mCallback.reportSuccessfulUnlockAttempt();
+ mCallback.reportUnlockAttempt(true);
mLockPatternView.setDisplayMode(LockPatternView.DisplayMode.Correct);
mTotalFailedPatternAttempts = 0;
mCallback.dismiss(true);
@@ -272,7 +272,7 @@ public class KeyguardPatternView extends LinearLayout implements KeyguardSecurit
if (pattern.size() >= LockPatternUtils.MIN_PATTERN_REGISTER_FAIL) {
mTotalFailedPatternAttempts++;
mFailedPatternAttemptsSinceLastTimeout++;
- mCallback.reportFailedUnlockAttempt();
+ mCallback.reportUnlockAttempt(false);
}
if (mFailedPatternAttemptsSinceLastTimeout
>= LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT) {
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityCallback.java b/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityCallback.java
index 4f139ad..957098c 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityCallback.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityCallback.java
@@ -15,8 +15,6 @@
*/
package com.android.keyguard;
-import com.android.keyguard.KeyguardHostView.OnDismissAction;
-
public interface KeyguardSecurityCallback {
/**
@@ -40,29 +38,13 @@ public interface KeyguardSecurityCallback {
/**
* Call when user correctly enters their credentials
+ * @param success
*/
- void reportSuccessfulUnlockAttempt();
-
- /**
- * Call when the user incorrectly enters their credentials
- */
- void reportFailedUnlockAttempt();
-
- /**
- * Gets the number of attempts thus far as reported by {@link #reportFailedUnlockAttempt()}
- * @return number of failed attempts
- */
- int getFailedAttempts();
+ void reportUnlockAttempt(boolean success);
/**
* Shows the backup security for the current method. If none available, this call is a no-op.
*/
void showBackupSecurity();
- /**
- * Sets an action to perform after the user successfully enters their credentials.
- * @param action
- */
- void setOnDismissAction(OnDismissAction action);
-
}
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityContainer.java b/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityContainer.java
index 9d03c6a..7606689 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityContainer.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityContainer.java
@@ -1,11 +1,39 @@
package com.android.keyguard;
+import android.app.Activity;
+import android.app.AlertDialog;
import android.content.Context;
import android.util.AttributeSet;
+import android.util.Log;
+import android.util.Slog;
+import android.view.LayoutInflater;
import android.view.View;
+import android.view.WindowManager;
import android.widget.FrameLayout;
-public class KeyguardSecurityContainer extends FrameLayout {
+import com.android.internal.widget.LockPatternUtils;
+import com.android.keyguard.KeyguardSecurityModel.SecurityMode;
+
+public class KeyguardSecurityContainer extends FrameLayout implements KeyguardSecurityView {
+ private static final boolean DEBUG = KeyguardViewMediator.DEBUG;
+ private static final String TAG = "KeyguardSecurityView";
+ private KeyguardSecurityModel mSecurityModel;
+ private boolean mEnableFallback; // TODO: This should get the value from KeyguardPatternView
+ private LockPatternUtils mLockPatternUtils;
+
+ private KeyguardSecurityViewFlipper mSecurityViewFlipper;
+ private boolean mIsVerifyUnlockOnly;
+ private SecurityMode mCurrentSecuritySelection = SecurityMode.Invalid;
+ private boolean mIsBouncing;
+ private SecurityCallback mSecurityCallback;
+
+ // Used to notify the container when something interesting happens.
+ public interface SecurityCallback {
+ public void dismiss(boolean authenticated);
+ public void userActivity(long timeout);
+ public void finish();
+ }
+
public KeyguardSecurityContainer(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
@@ -16,9 +44,336 @@ public class KeyguardSecurityContainer extends FrameLayout {
public KeyguardSecurityContainer(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
+ mSecurityModel = new KeyguardSecurityModel(context);
+ mLockPatternUtils = new LockPatternUtils(context);
+ }
+
+ public void setSecurityCallback(SecurityCallback callback) {
+ mSecurityCallback = callback;
+ }
+
+ @Override
+ public void onResume(int reason) {
+ getSecurityView(mCurrentSecuritySelection).onResume(reason);
+ }
+
+ @Override
+ public void onPause() {
+ getSecurityView(mCurrentSecuritySelection).onPause();
+ }
+
+ void updateSecurityViews(boolean isBouncing) {
+ int children = mSecurityViewFlipper.getChildCount();
+ for (int i = 0; i < children; i++) {
+ updateSecurityView(mSecurityViewFlipper.getChildAt(i), isBouncing);
+ }
+ }
+
+ public void announceCurrentSecurityMethod() {
+ View v = (View) getSecurityView(mCurrentSecuritySelection);
+ if (v != null) {
+ v.announceForAccessibility(v.getContentDescription());
+ }
+ }
+
+ private KeyguardSecurityView getSecurityView(SecurityMode securityMode) {
+ final int securityViewIdForMode = getSecurityViewIdForMode(securityMode);
+ KeyguardSecurityView view = null;
+ final int children = mSecurityViewFlipper.getChildCount();
+ for (int child = 0; child < children; child++) {
+ if (mSecurityViewFlipper.getChildAt(child).getId() == securityViewIdForMode) {
+ view = ((KeyguardSecurityView)mSecurityViewFlipper.getChildAt(child));
+ break;
+ }
+ }
+ int layoutId = getLayoutIdFor(securityMode);
+ if (view == null && layoutId != 0) {
+ final LayoutInflater inflater = LayoutInflater.from(mContext);
+ if (DEBUG) Log.v(TAG, "inflating id = " + layoutId);
+ View v = inflater.inflate(layoutId, mSecurityViewFlipper, false);
+ mSecurityViewFlipper.addView(v);
+ updateSecurityView(v, mIsBouncing);
+ view = (KeyguardSecurityView)v;
+ }
+
+ if (view instanceof KeyguardSelectorView) {
+ KeyguardSelectorView selectorView = (KeyguardSelectorView) view;
+ View carrierText = selectorView.findViewById(R.id.keyguard_selector_fade_container);
+ selectorView.setCarrierArea(carrierText);
+ }
+
+ return view;
+ }
+
+ private void updateSecurityView(View view, boolean isBouncing) {
+ mIsBouncing = isBouncing;
+ if (view instanceof KeyguardSecurityView) {
+ KeyguardSecurityView ksv = (KeyguardSecurityView) view;
+ ksv.setKeyguardCallback(mCallback);
+ ksv.setLockPatternUtils(mLockPatternUtils);
+ if (isBouncing) {
+ ksv.showBouncer(0);
+ } else {
+ ksv.hideBouncer(0);
+ }
+ } else {
+ Log.w(TAG, "View " + view + " is not a KeyguardSecurityView");
+ }
+ }
+
+ protected void onFinishInflate() {
+ mSecurityViewFlipper = (KeyguardSecurityViewFlipper) findViewById(R.id.view_flipper);
+ mSecurityViewFlipper.setLockPatternUtils(mLockPatternUtils);
+ }
+
+ public void setLockPatternUtils(LockPatternUtils utils) {
+ mLockPatternUtils = utils;
+ mSecurityModel.setLockPatternUtils(utils);
+ mSecurityViewFlipper.setLockPatternUtils(mLockPatternUtils);
+ }
+
+ private void showDialog(String title, String message) {
+ final AlertDialog dialog = new AlertDialog.Builder(mContext)
+ .setTitle(title)
+ .setMessage(message)
+ .setNeutralButton(R.string.ok, null)
+ .create();
+ if (!(mContext instanceof Activity)) {
+ dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
+ }
+ dialog.show();
+ }
+
+ private void showTimeoutDialog() {
+ int timeoutInSeconds = (int) LockPatternUtils.FAILED_ATTEMPT_TIMEOUT_MS / 1000;
+ int messageId = 0;
+
+ switch (mSecurityModel.getSecurityMode()) {
+ case Pattern:
+ messageId = R.string.kg_too_many_failed_pattern_attempts_dialog_message;
+ break;
+ case PIN:
+ messageId = R.string.kg_too_many_failed_pin_attempts_dialog_message;
+ break;
+ case Password:
+ messageId = R.string.kg_too_many_failed_password_attempts_dialog_message;
+ break;
+ // These don't have timeout dialogs.
+ case Account:
+ case Biometric:
+ case Invalid:
+ case None:
+ case SimPin:
+ case SimPuk:
+ break;
+ }
+
+ if (messageId != 0) {
+ final String message = mContext.getString(messageId,
+ KeyguardUpdateMonitor.getInstance(mContext).getFailedUnlockAttempts(),
+ timeoutInSeconds);
+ showDialog(null, message);
+ }
+ }
+
+ private void showAlmostAtWipeDialog(int attempts, int remaining) {
+ String message = mContext.getString(R.string.kg_failed_attempts_almost_at_wipe,
+ attempts, remaining);
+ showDialog(null, message);
+ }
+
+ private void showWipeDialog(int attempts) {
+ String message = mContext.getString(R.string.kg_failed_attempts_now_wiping, attempts);
+ showDialog(null, message);
+ }
+
+ private void showAlmostAtAccountLoginDialog() {
+ final int timeoutInSeconds = (int) LockPatternUtils.FAILED_ATTEMPT_TIMEOUT_MS / 1000;
+ final int count = LockPatternUtils.FAILED_ATTEMPTS_BEFORE_RESET
+ - LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT;
+ String message = mContext.getString(R.string.kg_failed_attempts_almost_at_login,
+ count, LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT, timeoutInSeconds);
+ showDialog(null, message);
}
- KeyguardSecurityViewFlipper getFlipper() {
+ private void reportFailedUnlockAttempt() {
+ final KeyguardUpdateMonitor monitor = KeyguardUpdateMonitor.getInstance(mContext);
+ final int failedAttempts = monitor.getFailedUnlockAttempts() + 1; // +1 for this time
+
+ if (DEBUG) Log.d(TAG, "reportFailedPatternAttempt: #" + failedAttempts);
+
+ SecurityMode mode = mSecurityModel.getSecurityMode();
+ final boolean usingPattern = mode == KeyguardSecurityModel.SecurityMode.Pattern;
+
+ final int failedAttemptsBeforeWipe = mLockPatternUtils.getDevicePolicyManager()
+ .getMaximumFailedPasswordsForWipe(null, mLockPatternUtils.getCurrentUser());
+
+ final int failedAttemptWarning = LockPatternUtils.FAILED_ATTEMPTS_BEFORE_RESET
+ - LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT;
+
+ final int remainingBeforeWipe = failedAttemptsBeforeWipe > 0 ?
+ (failedAttemptsBeforeWipe - failedAttempts)
+ : Integer.MAX_VALUE; // because DPM returns 0 if no restriction
+
+ boolean showTimeout = false;
+ if (remainingBeforeWipe < LockPatternUtils.FAILED_ATTEMPTS_BEFORE_WIPE_GRACE) {
+ // If we reach this code, it means the user has installed a DevicePolicyManager
+ // that requests device wipe after N attempts. Once we get below the grace
+ // period, we'll post this dialog every time as a clear warning until the
+ // bombshell hits and the device is wiped.
+ if (remainingBeforeWipe > 0) {
+ showAlmostAtWipeDialog(failedAttempts, remainingBeforeWipe);
+ } else {
+ // Too many attempts. The device will be wiped shortly.
+ Slog.i(TAG, "Too many unlock attempts; device will be wiped!");
+ showWipeDialog(failedAttempts);
+ }
+ } else {
+ showTimeout =
+ (failedAttempts % LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT) == 0;
+ if (usingPattern && mEnableFallback) {
+ if (failedAttempts == failedAttemptWarning) {
+ showAlmostAtAccountLoginDialog();
+ showTimeout = false; // don't show both dialogs
+ } else if (failedAttempts >= LockPatternUtils.FAILED_ATTEMPTS_BEFORE_RESET) {
+ mLockPatternUtils.setPermanentlyLocked(true);
+ showSecurityScreen(SecurityMode.Account);
+ // don't show timeout dialog because we show account unlock screen next
+ showTimeout = false;
+ }
+ }
+ }
+ monitor.reportFailedUnlockAttempt();
+ mLockPatternUtils.reportFailedPasswordAttempt();
+ if (showTimeout) {
+ showTimeoutDialog();
+ }
+ }
+
+ /**
+ * Shows the primary security screen for the user. This will be either the multi-selector
+ * or the user's security method.
+ * @param turningOff true if the device is being turned off
+ */
+ void showPrimarySecurityScreen(boolean turningOff) {
+ SecurityMode securityMode = mSecurityModel.getSecurityMode();
+ if (DEBUG) Log.v(TAG, "showPrimarySecurityScreen(turningOff=" + turningOff + ")");
+ if (!turningOff &&
+ KeyguardUpdateMonitor.getInstance(mContext).isAlternateUnlockEnabled()) {
+ // If we're not turning off, then allow biometric alternate.
+ // We'll reload it when the device comes back on.
+ securityMode = mSecurityModel.getAlternateFor(securityMode);
+ }
+ showSecurityScreen(securityMode);
+ }
+
+ /**
+ * Shows the backup security screen for the current security mode. This could be used for
+ * password recovery screens but is currently only used for pattern unlock to show the
+ * account unlock screen and biometric unlock to show the user's normal unlock.
+ */
+ private void showBackupSecurityScreen() {
+ if (DEBUG) Log.d(TAG, "showBackupSecurity()");
+ SecurityMode backup = mSecurityModel.getBackupSecurityMode(mCurrentSecuritySelection);
+ showSecurityScreen(backup);
+ }
+
+ private boolean showNextSecurityScreenIfPresent() {
+ SecurityMode securityMode = mSecurityModel.getSecurityMode();
+ // Allow an alternate, such as biometric unlock
+ securityMode = mSecurityModel.getAlternateFor(securityMode);
+ if (SecurityMode.None == securityMode) {
+ return false;
+ } else {
+ showSecurityScreen(securityMode); // switch to the alternate security view
+ return true;
+ }
+ }
+
+ boolean showNextSecurityScreenOrFinish(boolean authenticated) {
+ if (DEBUG) Log.d(TAG, "showNextSecurityScreenOrFinish(" + authenticated + ")");
+ boolean finish = false;
+ if (SecurityMode.None == mCurrentSecuritySelection) {
+ SecurityMode securityMode = mSecurityModel.getSecurityMode();
+ // Allow an alternate, such as biometric unlock
+ securityMode = mSecurityModel.getAlternateFor(securityMode);
+ if (SecurityMode.None == securityMode) {
+ finish = true; // no security required
+ } else {
+ showSecurityScreen(securityMode); // switch to the alternate security view
+ }
+ } else if (authenticated) {
+ switch (mCurrentSecuritySelection) {
+ case Pattern:
+ case Password:
+ case PIN:
+ case Account:
+ case Biometric:
+ finish = true;
+ break;
+
+ case SimPin:
+ case SimPuk:
+ // Shortcut for SIM PIN/PUK to go to directly to user's security screen or home
+ SecurityMode securityMode = mSecurityModel.getSecurityMode();
+ if (securityMode != SecurityMode.None) {
+ showSecurityScreen(securityMode);
+ } else {
+ finish = true;
+ }
+ break;
+
+ default:
+ Log.v(TAG, "Bad security screen " + mCurrentSecuritySelection + ", fail safe");
+ showPrimarySecurityScreen(false);
+ break;
+ }
+ } else {
+ showPrimarySecurityScreen(false);
+ }
+ if (finish) {
+ mSecurityCallback.finish();
+ }
+ return finish;
+ }
+
+ /**
+ * Switches to the given security view unless it's already being shown, in which case
+ * this is a no-op.
+ *
+ * @param securityMode
+ */
+ private void showSecurityScreen(SecurityMode securityMode) {
+ if (DEBUG) Log.d(TAG, "showSecurityScreen(" + securityMode + ")");
+
+ if (securityMode == mCurrentSecuritySelection) return;
+
+ KeyguardSecurityView oldView = getSecurityView(mCurrentSecuritySelection);
+ KeyguardSecurityView newView = getSecurityView(securityMode);
+
+ // Emulate Activity life cycle
+ if (oldView != null) {
+ oldView.onPause();
+ oldView.setKeyguardCallback(mNullCallback); // ignore requests from old view
+ }
+ newView.onResume(KeyguardSecurityView.VIEW_REVEALED);
+ newView.setKeyguardCallback(mCallback);
+
+ // Find and show this child.
+ final int childCount = mSecurityViewFlipper.getChildCount();
+
+ final int securityViewIdForMode = getSecurityViewIdForMode(securityMode);
+ for (int i = 0; i < childCount; i++) {
+ if (mSecurityViewFlipper.getChildAt(i).getId() == securityViewIdForMode) {
+ mSecurityViewFlipper.setDisplayedChild(i);
+ break;
+ }
+ }
+
+ mCurrentSecuritySelection = securityMode;
+ }
+
+ private KeyguardSecurityViewFlipper getFlipper() {
for (int i = 0; i < getChildCount(); i++) {
View child = getChildAt(i);
if (child instanceof KeyguardSecurityViewFlipper) {
@@ -41,5 +396,129 @@ public class KeyguardSecurityContainer extends FrameLayout {
flipper.hideBouncer(duration);
}
}
+
+ private KeyguardSecurityCallback mCallback = new KeyguardSecurityCallback() {
+
+ public void userActivity(long timeout) {
+ if (mSecurityCallback != null) {
+ mSecurityCallback.userActivity(timeout);
+ }
+ }
+
+ public void dismiss(boolean authenticated) {
+ mSecurityCallback.dismiss(authenticated);
+ }
+
+ public boolean isVerifyUnlockOnly() {
+ return mIsVerifyUnlockOnly;
+ }
+
+ public void reportUnlockAttempt(boolean success) {
+ KeyguardUpdateMonitor monitor = KeyguardUpdateMonitor.getInstance(mContext);
+ if (success) {
+ monitor.clearFailedUnlockAttempts();
+ mLockPatternUtils.reportSuccessfulPasswordAttempt();
+ } else {
+ if (mCurrentSecuritySelection == SecurityMode.Biometric) {
+ monitor.reportFailedBiometricUnlockAttempt();
+ } else {
+ KeyguardSecurityContainer.this.reportFailedUnlockAttempt();
+ }
+ }
+ }
+
+ @Override
+ public void showBackupSecurity() {
+ KeyguardSecurityContainer.this.showBackupSecurityScreen();
+ }
+
+ };
+
+ // The following is used to ignore callbacks from SecurityViews that are no longer current
+ // (e.g. face unlock). This avoids unwanted asynchronous events from messing with the
+ // state for the current security method.
+ private KeyguardSecurityCallback mNullCallback = new KeyguardSecurityCallback() {
+ @Override
+ public void userActivity(long timeout) { }
+ @Override
+ public void showBackupSecurity() { }
+ @Override
+ public void reportUnlockAttempt(boolean success) { }
+ @Override
+ public boolean isVerifyUnlockOnly() { return false; }
+ @Override
+ public void dismiss(boolean securityVerified) { }
+ };
+
+ private int getSecurityViewIdForMode(SecurityMode securityMode) {
+ switch (securityMode) {
+ case None: return R.id.keyguard_selector_view;
+ case Pattern: return R.id.keyguard_pattern_view;
+ case PIN: return R.id.keyguard_pin_view;
+ case Password: return R.id.keyguard_password_view;
+ case Biometric: return R.id.keyguard_face_unlock_view;
+ case Account: return R.id.keyguard_account_view;
+ case SimPin: return R.id.keyguard_sim_pin_view;
+ case SimPuk: return R.id.keyguard_sim_puk_view;
+ }
+ return 0;
+ }
+
+ private int getLayoutIdFor(SecurityMode securityMode) {
+ switch (securityMode) {
+ case None: return R.layout.keyguard_selector_view;
+ case Pattern: return R.layout.keyguard_pattern_view;
+ case PIN: return R.layout.keyguard_pin_view;
+ case Password: return R.layout.keyguard_password_view;
+ case Biometric: return R.layout.keyguard_face_unlock_view;
+ case Account: return R.layout.keyguard_account_view;
+ case SimPin: return R.layout.keyguard_sim_pin_view;
+ case SimPuk: return R.layout.keyguard_sim_puk_view;
+ default:
+ return 0;
+ }
+ }
+
+ public SecurityMode getSecurityMode() {
+ return mSecurityModel.getSecurityMode();
+ }
+
+ public void verifyUnlock() {
+ mIsVerifyUnlockOnly = true;
+ showSecurityScreen(getSecurityMode());
+ }
+
+ public SecurityMode getCurrentSecuritySelection() {
+ return mCurrentSecuritySelection;
+ }
+
+ public void dismiss(boolean authenticated) {
+ mCallback.dismiss(authenticated);
+ }
+
+ public boolean needsInput() {
+ return mSecurityViewFlipper.needsInput();
+ }
+
+ @Override
+ public void setKeyguardCallback(KeyguardSecurityCallback callback) {
+ mSecurityViewFlipper.setKeyguardCallback(callback);
+ }
+
+ @Override
+ public void reset() {
+ mSecurityViewFlipper.reset();
+ }
+
+ @Override
+ public KeyguardSecurityCallback getCallback() {
+ return mSecurityViewFlipper.getCallback();
+ }
+
+ @Override
+ public void showUsabilityHint() {
+ mSecurityViewFlipper.showUsabilityHint();
+ }
+
}
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardSelectorView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardSelectorView.java
index 718b06e..97aec68 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardSelectorView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardSelectorView.java
@@ -58,23 +58,6 @@ public class KeyguardSelectorView extends LinearLayout implements KeyguardSecuri
final int resId = mGlowPadView.getResourceIdForTarget(target);
switch (resId) {
- case R.drawable.ic_action_assist_generic:
- Intent assistIntent =
- ((SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE))
- .getAssistIntent(mContext, true, UserHandle.USER_CURRENT);
- if (assistIntent != null) {
- mActivityLauncher.launchActivity(assistIntent, false, true, null, null);
- } else {
- Log.w(TAG, "Failed to get intent for assist activity");
- }
- mCallback.userActivity(0);
- break;
-
- case R.drawable.ic_lockscreen_camera:
- mActivityLauncher.launchCamera(null, null);
- mCallback.userActivity(0);
- break;
-
case R.drawable.ic_lockscreen_unlock_phantom:
case R.drawable.ic_lockscreen_unlock:
mCallback.userActivity(0);
@@ -117,23 +100,6 @@ public class KeyguardSelectorView extends LinearLayout implements KeyguardSecuri
}
};
- private final KeyguardActivityLauncher mActivityLauncher = new KeyguardActivityLauncher() {
-
- @Override
- KeyguardSecurityCallback getCallback() {
- return mCallback;
- }
-
- @Override
- LockPatternUtils getLockPatternUtils() {
- return mLockPatternUtils;
- }
-
- @Override
- Context getContext() {
- return mContext;
- }};
-
public KeyguardSelectorView(Context context) {
this(context, null);
}