diff options
author | Ricardo Cerqueira <ricardo@cyngn.com> | 2015-11-05 02:27:28 +0000 |
---|---|---|
committer | Ricardo Cerqueira <ricardo@cyngn.com> | 2015-11-05 15:13:26 +0000 |
commit | a89168479cb14f482268af6f1a650b28eba0b393 (patch) | |
tree | 8552b9d49ecfad6a453ee5f743571b700b4d3d3c /packages/Keyguard/src | |
parent | 8331d3e508498a19c296fed41b9d4b23ea960031 (diff) | |
parent | 25b5096f154721c8142d54f1b3af9e2998deffe9 (diff) | |
download | frameworks_base-a89168479cb14f482268af6f1a650b28eba0b393.zip frameworks_base-a89168479cb14f482268af6f1a650b28eba0b393.tar.gz frameworks_base-a89168479cb14f482268af6f1a650b28eba0b393.tar.bz2 |
Merge tag 'android-6.0.0_r26' into HEAD
Android 6.0.0 release 26
Conflicts:
cmds/bootanimation/BootAnimation.cpp
core/java/android/accounts/AccountManager.java
core/java/android/app/AppOpsManager.java
core/java/android/os/PowerManagerInternal.java
core/java/android/os/storage/IMountService.java
core/java/android/provider/Settings.java
core/java/com/android/internal/widget/ILockSettings.aidl
core/res/res/values-mcc204-mnc12/config.xml
core/res/res/values-mcc219-mnc02/config.xml
core/res/res/values-mcc730-mnc07/config.xml
core/res/res/values/config.xml
core/res/res/values/symbols.xml
packages/SystemUI/res/values/config.xml
packages/SystemUI/src/com/android/systemui/doze/DozeService.java
packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
packages/SystemUI/src/com/android/systemui/statusbar/ExpandableOutlineView.java
packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java
packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java
packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
services/core/java/com/android/server/LocationManagerService.java
services/core/java/com/android/server/am/ActivityManagerService.java
services/core/java/com/android/server/pm/PackageManagerService.java
services/core/java/com/android/server/power/PowerManagerService.java
telecomm/java/android/telecom/Phone.java
telephony/java/android/telephony/CarrierConfigManager.java
telephony/java/android/telephony/RadioAccessFamily.java
telephony/java/android/telephony/ServiceState.java
telephony/java/android/telephony/SignalStrength.java
telephony/java/android/telephony/TelephonyManager.java
telephony/java/com/android/ims/ImsCallProfile.java
telephony/java/com/android/ims/ImsReasonInfo.java
telephony/java/com/android/ims/ImsSuppServiceNotification.aidl
telephony/java/com/android/ims/ImsSuppServiceNotification.java
telephony/java/com/android/ims/internal/IImsRegistrationListener.aidl
telephony/java/com/android/internal/telephony/RILConstants.java
Change-Id: I99c6edb8e25a77145b5adef97d0d55bfbe676959
Diffstat (limited to 'packages/Keyguard/src')
14 files changed, 467 insertions, 188 deletions
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardAbsKeyInputView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardAbsKeyInputView.java index 8f792de..b03871a 100644 --- a/packages/Keyguard/src/com/android/keyguard/KeyguardAbsKeyInputView.java +++ b/packages/Keyguard/src/com/android/keyguard/KeyguardAbsKeyInputView.java @@ -40,6 +40,7 @@ public abstract class KeyguardAbsKeyInputView extends LinearLayout protected SecurityMessageDisplay mSecurityMessageDisplay; protected View mEcaView; protected boolean mEnableHaptics; + private boolean mDismissing; // To avoid accidental lockout due to events while the device in in the pocket, ignore // any passwords with length less than or equal to this length. @@ -67,6 +68,7 @@ public abstract class KeyguardAbsKeyInputView extends LinearLayout @Override public void reset() { // start fresh + mDismissing = false; resetPasswordText(false /* animate */); // if the user is currently locked out, enforce it. long deadline = mLockPatternUtils.getLockoutAttemptDeadline( @@ -113,6 +115,8 @@ public abstract class KeyguardAbsKeyInputView extends LinearLayout } protected void verifyPasswordAndUnlock() { + if (mDismissing) return; // already verified but haven't been dismissed; don't do it again. + final String entry = getPasswordText(); setPasswordEntryInputEnabled(false); if (mPendingLockCheck != null) { @@ -143,6 +147,7 @@ public abstract class KeyguardAbsKeyInputView extends LinearLayout private void onPasswordChecked(boolean matched, int timeoutMs, boolean isValidPassword) { if (matched) { + mDismissing = true; mCallback.reportUnlockAttempt(true, 0); mCallback.dismiss(true); } else { @@ -234,6 +239,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 diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java index ff4e815..ec2a173 100644 --- a/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java +++ b/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java @@ -163,13 +163,18 @@ public class KeyguardHostView extends FrameLayout implements SecurityCallback { * Show a string explaining why the security view needs to be solved. * * @param reason a flag indicating which string should be shown, see - * {@link KeyguardSecurityView#PROMPT_REASON_NONE} - * and {@link KeyguardSecurityView#PROMPT_REASON_RESTART} + * {@link KeyguardSecurityView#PROMPT_REASON_NONE}, + * {@link KeyguardSecurityView#PROMPT_REASON_RESTART} and + * {@link KeyguardSecurityView#PROMPT_REASON_TIMEOUT}. */ public void showPromptReason(int reason) { 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. * @@ -209,9 +214,12 @@ public class KeyguardHostView extends FrameLayout implements SecurityCallback { /** * Authentication has happened and it's time to dismiss keyguard. This function * should clean up and inform KeyguardViewMediator. + * + * @param strongAuth whether the user has authenticated with strong authentication like + * pattern, password or PIN but not by trust agents or fingerprint */ @Override - public void finish() { + public void finish(boolean strongAuth) { // If there's a pending runnable because the user interacted with a widget // and we're leaving keyguard, then run it. boolean deferKeyguardDone = false; @@ -222,9 +230,9 @@ public class KeyguardHostView extends FrameLayout implements SecurityCallback { } if (mViewMediatorCallback != null) { if (deferKeyguardDone) { - mViewMediatorCallback.keyguardDonePending(); + mViewMediatorCallback.keyguardDonePending(strongAuth); } else { - mViewMediatorCallback.keyguardDone(true); + mViewMediatorCallback.keyguardDone(strongAuth); } } } @@ -281,32 +289,6 @@ public class KeyguardHostView extends FrameLayout implements SecurityCallback { } /** - * Verify that the user can get past the keyguard securely. This is called, - * for example, when the phone disables the keyguard but then wants to launch - * something else that requires secure access. - * - * The result will be propogated back via {@link KeyguardViewCallback#keyguardDone(boolean)} - */ - public void verifyUnlock() { - SecurityMode securityMode = mSecurityContainer.getSecurityMode(); - if (securityMode == KeyguardSecurityModel.SecurityMode.None) { - if (mViewMediatorCallback != null) { - mViewMediatorCallback.keyguardDone(true); - } - } else if (securityMode != KeyguardSecurityModel.SecurityMode.Pattern - && securityMode != KeyguardSecurityModel.SecurityMode.PIN - && securityMode != KeyguardSecurityModel.SecurityMode.Password) { - // can only verify unlock when in pattern/password mode - if (mViewMediatorCallback != null) { - mViewMediatorCallback.keyguardDone(false); - } - } else { - // otherwise, go to the unlock screen, see if they can verify it - mSecurityContainer.verifyUnlock(); - } - } - - /** * Called before this view is being removed. */ public void cleanUp() { diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardMessageArea.java b/packages/Keyguard/src/com/android/keyguard/KeyguardMessageArea.java index 2951af9..c8adf64 100644 --- a/packages/Keyguard/src/com/android/keyguard/KeyguardMessageArea.java +++ b/packages/Keyguard/src/com/android/keyguard/KeyguardMessageArea.java @@ -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,10 +81,16 @@ 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) { securityMessageChanged(msg); @@ -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); } diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardPasswordView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardPasswordView.java index 2db87b3..3a7e6d0 100644 --- a/packages/Keyguard/src/com/android/keyguard/KeyguardPasswordView.java +++ b/packages/Keyguard/src/com/android/keyguard/KeyguardPasswordView.java @@ -115,6 +115,8 @@ public class KeyguardPasswordView extends KeyguardAbsKeyInputView switch (reason) { case PROMPT_REASON_RESTART: return R.string.kg_prompt_reason_restart_password; + case PROMPT_REASON_TIMEOUT: + return R.string.kg_prompt_reason_timeout_password; default: return 0; } diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardPatternView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardPatternView.java index 4bd1a2e..9a91ca4 100644 --- a/packages/Keyguard/src/com/android/keyguard/KeyguardPatternView.java +++ b/packages/Keyguard/src/com/android/keyguard/KeyguardPatternView.java @@ -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; @@ -337,11 +332,22 @@ public class KeyguardPatternView extends LinearLayout implements KeyguardSecurit mSecurityMessageDisplay.setMessage(R.string.kg_prompt_reason_restart_pattern, true /* important */); break; + case PROMPT_REASON_TIMEOUT: + mSecurityMessageDisplay.setMessage(R.string.kg_prompt_reason_timeout_pattern, + true /* important */); + break; default: + break; } } @Override + public void showMessage(String message, int color) { + mSecurityMessageDisplay.setNextMessageColor(color); + mSecurityMessageDisplay.setMessage(message, true /* important */); + } + + @Override public void startAppearAnimation() { enableClipping(false); setAlpha(1f); diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardPinBasedInputView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardPinBasedInputView.java index 07947b1..f51e10f 100644 --- a/packages/Keyguard/src/com/android/keyguard/KeyguardPinBasedInputView.java +++ b/packages/Keyguard/src/com/android/keyguard/KeyguardPinBasedInputView.java @@ -62,18 +62,21 @@ public abstract class KeyguardPinBasedInputView extends KeyguardAbsKeyInputView return mPasswordEntry.requestFocus(direction, previouslyFocusedRect); } + @Override protected void resetState() { - mPasswordEntry.setEnabled(true); + setPasswordEntryEnabled(true); } @Override protected void setPasswordEntryEnabled(boolean enabled) { mPasswordEntry.setEnabled(enabled); + mOkButton.setEnabled(enabled); } @Override protected void setPasswordEntryInputEnabled(boolean enabled) { mPasswordEntry.setEnabled(enabled); + mOkButton.setEnabled(enabled); } @Override @@ -98,6 +101,8 @@ public abstract class KeyguardPinBasedInputView extends KeyguardAbsKeyInputView switch (reason) { case PROMPT_REASON_RESTART: return R.string.kg_prompt_reason_restart_pin; + case PROMPT_REASON_TIMEOUT: + return R.string.kg_prompt_reason_timeout_pin; default: return 0; } @@ -184,6 +189,7 @@ public abstract class KeyguardPinBasedInputView extends KeyguardAbsKeyInputView mDeleteButton = findViewById(R.id.delete_button); mDeleteButton.setVisibility(View.VISIBLE); mDeleteButton.setOnClickListener(new OnClickListener() { + @Override public void onClick(View v) { // check for time-based lockouts if (mPasswordEntry.isEnabled()) { @@ -193,6 +199,7 @@ public abstract class KeyguardPinBasedInputView extends KeyguardAbsKeyInputView } }); mDeleteButton.setOnLongClickListener(new View.OnLongClickListener() { + @Override public boolean onLongClick(View v) { // check for time-based lockouts if (mPasswordEntry.isEnabled()) { diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityContainer.java b/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityContainer.java index 85da298..77215a7 100644 --- a/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityContainer.java +++ b/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityContainer.java @@ -54,7 +54,12 @@ public class KeyguardSecurityContainer extends FrameLayout implements KeyguardSe public boolean dismiss(boolean authenticated); public void userActivity(); public void onSecurityModeChanged(SecurityMode securityMode, boolean needsInput); - public void finish(); + + /** + * @param strongAuth wheher the user has authenticated with strong authentication like + * pattern, password or PIN but not by trust agents or fingerprint + */ + public void finish(boolean strongAuth); public void reset(); } @@ -282,7 +287,7 @@ public class KeyguardSecurityContainer extends FrameLayout implements KeyguardSe showWipeDialog(failedAttempts, userType); } } - monitor.reportFailedUnlockAttempt(); + monitor.reportFailedStrongAuthUnlockAttempt(); mLockPatternUtils.reportFailedPasswordAttempt(KeyguardUpdateMonitor.getCurrentUser()); if (timeoutMs > 0) { showTimeoutDialog(timeoutMs); @@ -308,6 +313,7 @@ public class KeyguardSecurityContainer extends FrameLayout implements KeyguardSe boolean showNextSecurityScreenOrFinish(boolean authenticated) { if (DEBUG) Log.d(TAG, "showNextSecurityScreenOrFinish(" + authenticated + ")"); boolean finish = false; + boolean strongAuth = false; if (mUpdateMonitor.getUserCanSkipBouncer( KeyguardUpdateMonitor.getCurrentUser())) { finish = true; @@ -323,6 +329,7 @@ public class KeyguardSecurityContainer extends FrameLayout implements KeyguardSe case Pattern: case Password: case PIN: + strongAuth = true; finish = true; break; @@ -346,7 +353,7 @@ public class KeyguardSecurityContainer extends FrameLayout implements KeyguardSe } } if (finish) { - mSecurityCallback.finish(); + mSecurityCallback.finish(strongAuth); } return finish; } @@ -518,6 +525,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(); diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityView.java index 5658a74..38302fb 100644 --- a/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityView.java +++ b/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityView.java @@ -22,9 +22,18 @@ public interface KeyguardSecurityView { static public final int VIEW_REVEALED = 2; int PROMPT_REASON_NONE = 0; + + /** + * Strong auth is required because the device has just booted. + */ int PROMPT_REASON_RESTART = 1; /** + * Strong auth is required because the user hasn't used strong auth since a while. + */ + int PROMPT_REASON_TIMEOUT = 2; + + /** * Interface back to keyguard to tell it when security * @param callback */ @@ -77,6 +86,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. * */ diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityViewFlipper.java b/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityViewFlipper.java index a0ff21b..6012c45 100644 --- a/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityViewFlipper.java +++ b/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityViewFlipper.java @@ -139,6 +139,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(); if (ksv != null) { diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardSimPinView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardSimPinView.java index 9dcef3a..7214d40 100644 --- a/packages/Keyguard/src/com/android/keyguard/KeyguardSimPinView.java +++ b/packages/Keyguard/src/com/android/keyguard/KeyguardSimPinView.java @@ -23,6 +23,7 @@ import com.android.internal.telephony.PhoneConstants; import android.content.Context; import android.content.res.ColorStateList; +import android.content.res.Configuration; import android.content.res.Resources; import android.app.AlertDialog; import android.app.AlertDialog.Builder; @@ -85,6 +86,12 @@ public class KeyguardSimPinView extends KeyguardPinBasedInputView { } @Override + protected void onConfigurationChanged(Configuration newConfig) { + super.onConfigurationChanged(newConfig); + resetState(); + } + + @Override protected int getPromtReasonStringRes(int reason) { // No message on SIM Pin return 0; diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java index 2f00bb1..5e09729 100644 --- a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java +++ b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java @@ -29,46 +29,38 @@ import android.content.Intent; import android.content.IntentFilter; import android.database.ContentObserver; import android.graphics.Bitmap; - -import static android.os.BatteryManager.BATTERY_STATUS_FULL; -import static android.os.BatteryManager.BATTERY_STATUS_UNKNOWN; -import static android.os.BatteryManager.BATTERY_HEALTH_UNKNOWN; -import static android.os.BatteryManager.EXTRA_STATUS; -import static android.os.BatteryManager.EXTRA_PLUGGED; -import static android.os.BatteryManager.EXTRA_LEVEL; -import static android.os.BatteryManager.EXTRA_HEALTH; - +import android.hardware.fingerprint.Fingerprint; +import android.hardware.fingerprint.FingerprintManager; +import android.hardware.fingerprint.FingerprintManager.AuthenticationCallback; +import android.hardware.fingerprint.FingerprintManager.AuthenticationResult; import android.media.AudioManager; import android.os.BatteryManager; import android.os.CancellationSignal; import android.os.Handler; import android.os.IRemoteCallback; import android.os.Message; -import android.os.PowerManager; import android.os.RemoteException; import android.os.SystemClock; import android.os.UserHandle; import android.provider.Settings; - -import com.android.internal.telephony.IccCardConstants; -import com.android.internal.telephony.IccCardConstants.State; -import com.android.internal.telephony.PhoneConstants; -import com.android.internal.telephony.TelephonyIntents; - -import android.hardware.fingerprint.FingerprintManager; -import android.hardware.fingerprint.FingerprintManager.AuthenticationCallback; -import android.hardware.fingerprint.FingerprintManager.AuthenticationResult; import android.telephony.ServiceState; import android.telephony.SubscriptionInfo; import android.telephony.SubscriptionManager; import android.telephony.SubscriptionManager.OnSubscriptionsChangedListener; import android.telephony.TelephonyManager; +import android.util.ArraySet; import android.util.Log; import android.util.SparseBooleanArray; import android.util.SparseIntArray; import com.google.android.collect.Lists; +import com.android.internal.telephony.IccCardConstants; +import com.android.internal.telephony.IccCardConstants.State; +import com.android.internal.telephony.PhoneConstants; +import com.android.internal.telephony.TelephonyIntents; +import com.android.internal.widget.LockPatternUtils; + import java.io.FileDescriptor; import java.io.PrintWriter; import java.lang.ref.WeakReference; @@ -77,6 +69,15 @@ import java.util.HashMap; import java.util.List; import java.util.Map.Entry; +import static android.os.BatteryManager.BATTERY_HEALTH_UNKNOWN; +import static android.os.BatteryManager.BATTERY_STATUS_FULL; +import static android.os.BatteryManager.BATTERY_STATUS_UNKNOWN; +import static android.os.BatteryManager.EXTRA_HEALTH; +import static android.os.BatteryManager.EXTRA_LEVEL; +import static android.os.BatteryManager.EXTRA_MAX_CHARGING_CURRENT; +import static android.os.BatteryManager.EXTRA_PLUGGED; +import static android.os.BatteryManager.EXTRA_STATUS; + /** * Watches for updates that may be interesting to the keyguard, and provides * the up to date information as well as a registration for callbacks that care @@ -92,32 +93,24 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { private static final String TAG = "KeyguardUpdateMonitor"; private static final boolean DEBUG = KeyguardConstants.DEBUG; private static final boolean DEBUG_SIM_STATES = KeyguardConstants.DEBUG_SIM_STATES; - private static final boolean DEBUG_FP_WAKELOCK = KeyguardConstants.DEBUG_FP_WAKELOCK; private static final int LOW_BATTERY_THRESHOLD = 20; - private static final long FINGERPRINT_WAKELOCK_TIMEOUT_MS = 15 * 1000; private static final String ACTION_FACE_UNLOCK_STARTED = "com.android.facelock.FACE_UNLOCK_STARTED"; private static final String ACTION_FACE_UNLOCK_STOPPED = "com.android.facelock.FACE_UNLOCK_STOPPED"; - private static final String FINGERPRINT_WAKE_LOCK_NAME = "wake-and-unlock wakelock"; - /** - * Mode in which we don't need to wake up the device when we get a fingerprint. - */ - private static final int FP_WAKE_NONE = 0; + private static final String ACTION_STRONG_AUTH_TIMEOUT = + "com.android.systemui.ACTION_STRONG_AUTH_TIMEOUT"; + private static final String USER_ID = "com.android.systemui.USER_ID"; - /** - * Mode in which we wake up the device, and directly dismiss Keyguard. Active when we acquire - * a fingerprint while the screen is off and the device was sleeping. - */ - private static final int FP_WAKE_DIRECT_UNLOCK = 1; + private static final String PERMISSION_SELF = "com.android.systemui.permission.SELF"; /** - * Mode in which we wake up the device, but play the normal dismiss animation. Active when we - * acquire a fingerprint pulsing in doze mode. - * */ - private static final int FP_WAKE_WAKE_TO_BOUNCER = 2; + * Milliseconds after unlocking with fingerprint times out, i.e. the user has to use a + * strong auth method like password, PIN or pattern. + */ + private static final long FINGERPRINT_UNLOCK_TIMEOUT_MS = 72 * 60 * 60 * 1000; // Callback messages private static final int MSG_TIME_UPDATE = 301; @@ -128,7 +121,6 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { private static final int MSG_DEVICE_PROVISIONED = 308; private static final int MSG_DPM_STATE_CHANGED = 309; private static final int MSG_USER_SWITCHING = 310; - private static final int MSG_KEYGUARD_VISIBILITY_CHANGED = 311; private static final int MSG_KEYGUARD_RESET = 312; private static final int MSG_BOOT_COMPLETED = 313; private static final int MSG_USER_SWITCH_COMPLETE = 314; @@ -136,11 +128,32 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { private static final int MSG_REPORT_EMERGENCY_CALL_ACTION = 318; private static final int MSG_STARTED_WAKING_UP = 319; private static final int MSG_FINISHED_GOING_TO_SLEEP = 320; + private static final int MSG_STARTED_GOING_TO_SLEEP = 321; private static final int MSG_KEYGUARD_BOUNCER_CHANGED = 322; private static final int MSG_FACE_UNLOCK_STATE_CHANGED = 327; private static final int MSG_SIM_SUBSCRIPTION_INFO_CHANGED = 328; private static final int MSG_AIRPLANE_MODE_CHANGED = 329; private static final int MSG_SERVICE_STATE_CHANGE = 330; + private static final int MSG_SCREEN_TURNED_ON = 331; + private static final int MSG_SCREEN_TURNED_OFF = 332; + + /** Fingerprint state: Not listening to fingerprint. */ + private static final int FINGERPRINT_STATE_STOPPED = 0; + + /** Fingerprint state: Listening. */ + private static final int FINGERPRINT_STATE_RUNNING = 1; + + /** + * Fingerprint state: Cancelling and waiting for the confirmation from FingerprintService to + * send us the confirmation that cancellation has happened. + */ + private static final int FINGERPRINT_STATE_CANCELLING = 2; + + /** + * Fingerprint state: During cancelling we got another request to start listening, so when we + * receive the cancellation done signal, we should start listening again. + */ + private static final int FINGERPRINT_STATE_CANCELLING_RESTARTING = 3; private static KeyguardUpdateMonitor sInstance; @@ -151,9 +164,15 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { private int mRingMode; private int mPhoneState; private boolean mKeyguardIsVisible; + + /** + * If true, fingerprint was already authenticated and we don't need to start listening again + * until the Keyguard has been dismissed. + */ + private boolean mFingerprintAlreadyAuthenticated; + private boolean mGoingToSleep; private boolean mBouncer; private boolean mBootCompleted; - private boolean mUserHasAuthenticatedSinceBoot; // Device provisioning state private boolean mDeviceProvisioned; @@ -164,7 +183,9 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { // Password attempts private SparseIntArray mFailedAttempts = new SparseIntArray(); - private boolean mClockVisible; + /** Tracks whether strong authentication hasn't been used since quite some time per user. */ + private ArraySet<Integer> mStrongAuthNotTimedOut = new ArraySet<>(); + private final StrongAuthTracker mStrongAuthTracker = new StrongAuthTracker(); private final ArrayList<WeakReference<KeyguardUpdateMonitorCallback>> mCallbacks = Lists.newArrayList(); @@ -175,10 +196,10 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { private boolean mDeviceInteractive; private boolean mScreenOn; private SubscriptionManager mSubscriptionManager; + private AlarmManager mAlarmManager; private List<SubscriptionInfo> mSubscriptionInfo; - private boolean mFingerprintDetectionRunning; private TrustManager mTrustManager; - private PowerManager mPowerManager; + private int mFingerprintRunningState = FINGERPRINT_STATE_STOPPED; private final Handler mHandler = new Handler() { @Override @@ -211,9 +232,6 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { case MSG_USER_SWITCH_COMPLETE: handleUserSwitchComplete(msg.arg1); break; - case MSG_KEYGUARD_VISIBILITY_CHANGED: - handleKeyguardVisibilityChanged(msg.arg1); - break; case MSG_KEYGUARD_RESET: handleKeyguardReset(); break; @@ -229,6 +247,9 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { case MSG_REPORT_EMERGENCY_CALL_ACTION: handleReportEmergencyCallAction(); break; + case MSG_STARTED_GOING_TO_SLEEP: + handleStartedGoingToSleep(msg.arg1); + break; case MSG_FINISHED_GOING_TO_SLEEP: handleFinishedGoingToSleep(msg.arg1); break; @@ -247,6 +268,12 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { case MSG_SERVICE_STATE_CHANGE: handleServiceStateChange(msg.arg1, (ServiceState) msg.obj); break; + case MSG_SCREEN_TURNED_ON: + handleScreenTurnedOn(); + break; + case MSG_SCREEN_TURNED_OFF: + handleScreenTurnedOff(); + break; } } }; @@ -266,8 +293,6 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { private static int sCurrentUser; - private int mFpWakeMode; - public synchronized static void setCurrentUser(int currentUser) { sCurrentUser = currentUser; } @@ -368,18 +393,28 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { } } - private void onFingerprintAuthenticated(int userId, boolean wakeAndUnlocking) { + private void onFingerprintAuthenticated(int userId) { mUserFingerprintAuthenticated.put(userId, true); + + // If fingerprint unlocking is allowed, this event will lead to a Keyguard dismiss or to a + // wake-up (if Keyguard is not showing), so we don't need to listen until Keyguard is + // fully gone. + mFingerprintAlreadyAuthenticated = isUnlockingWithFingerprintAllowed(); for (int i = 0; i < mCallbacks.size(); i++) { KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get(); if (cb != null) { - cb.onFingerprintAuthenticated(userId, wakeAndUnlocking); + cb.onFingerprintAuthenticated(userId); } } } private void handleFingerprintAuthFailed() { - releaseFingerprintWakeLock(); + for (int i = 0; i < mCallbacks.size(); i++) { + KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get(); + if (cb != null) { + cb.onFingerprintAuthFailed(); + } + } handleFingerprintHelp(-1, mContext.getString(R.string.fingerprint_not_recognized)); } @@ -387,53 +422,15 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { if (acquireInfo != FingerprintManager.FINGERPRINT_ACQUIRED_GOOD) { return; } - if (!mDeviceInteractive && !mScreenOn) { - releaseFingerprintWakeLock(); - mWakeLock = mPowerManager.newWakeLock( - PowerManager.PARTIAL_WAKE_LOCK, FINGERPRINT_WAKE_LOCK_NAME); - mWakeLock.acquire(); - mFpWakeMode = FP_WAKE_DIRECT_UNLOCK; - if (DEBUG_FP_WAKELOCK) { - Log.i(TAG, "fingerprint acquired, grabbing fp wakelock"); - } - mHandler.postDelayed(mReleaseFingerprintWakeLockRunnable, - FINGERPRINT_WAKELOCK_TIMEOUT_MS); - } else if (!mDeviceInteractive) { - mFpWakeMode = FP_WAKE_WAKE_TO_BOUNCER; - } else { - mFpWakeMode = FP_WAKE_NONE; - } - } - - private final Runnable mReleaseFingerprintWakeLockRunnable = new Runnable() { - @Override - public void run() { - if (DEBUG_FP_WAKELOCK) { - Log.i(TAG, "fp wakelock: TIMEOUT!!"); - } - releaseFingerprintWakeLock(); - } - }; - - private void releaseFingerprintWakeLock() { - if (mWakeLock != null) { - mHandler.removeCallbacks(mReleaseFingerprintWakeLockRunnable); - if (DEBUG_FP_WAKELOCK) { - Log.i(TAG, "releasing fp wakelock"); + for (int i = 0; i < mCallbacks.size(); i++) { + KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get(); + if (cb != null) { + cb.onFingerprintAcquired(); } - mWakeLock.release(); - mWakeLock = null; } } private void handleFingerprintAuthenticated() { - if (mFpWakeMode == FP_WAKE_WAKE_TO_BOUNCER || mFpWakeMode == FP_WAKE_DIRECT_UNLOCK) { - if (DEBUG_FP_WAKELOCK) { - Log.i(TAG, "fp wakelock: Authenticated, waking up..."); - } - mPowerManager.wakeUp(SystemClock.uptimeMillis()); - } - releaseFingerprintWakeLock(); try { final int userId; try { @@ -446,9 +443,9 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { Log.d(TAG, "Fingerprint disabled by DPM for userId: " + userId); return; } - onFingerprintAuthenticated(userId, mFpWakeMode == FP_WAKE_DIRECT_UNLOCK); + onFingerprintAuthenticated(userId); } finally { - setFingerprintRunningDetectionRunning(false); + setFingerprintRunningState(FINGERPRINT_STATE_STOPPED); } } @@ -462,7 +459,13 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { } private void handleFingerprintError(int msgId, String errString) { - setFingerprintRunningDetectionRunning(false); + if (msgId == FingerprintManager.FINGERPRINT_ERROR_CANCELED + && mFingerprintRunningState == FINGERPRINT_STATE_CANCELLING_RESTARTING) { + setFingerprintRunningState(FINGERPRINT_STATE_STOPPED); + startListeningForFingerprint(); + } else { + setFingerprintRunningState(FINGERPRINT_STATE_STOPPED); + } for (int i = 0; i < mCallbacks.size(); i++) { KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get(); if (cb != null) { @@ -471,9 +474,19 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { } } - private void setFingerprintRunningDetectionRunning(boolean running) { - if (running != mFingerprintDetectionRunning) { - mFingerprintDetectionRunning = running; + private void handleFingerprintLockoutReset() { + updateFingerprintListeningState(); + } + + private void setFingerprintRunningState(int fingerprintRunningState) { + boolean wasRunning = mFingerprintRunningState == FINGERPRINT_STATE_RUNNING; + boolean isRunning = fingerprintRunningState == FINGERPRINT_STATE_RUNNING; + mFingerprintRunningState = fingerprintRunningState; + + // Clients of KeyguardUpdateMonitor don't care about the internal state about the + // asynchronousness of the cancel cycle. So only notify them if the actualy running state + // has changed. + if (wasRunning != isRunning) { notifyFingerprintRunningStateChanged(); } } @@ -482,7 +495,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { for (int i = 0; i < mCallbacks.size(); i++) { KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get(); if (cb != null) { - cb.onFingerprintRunningStateChanged(mFingerprintDetectionRunning); + cb.onFingerprintRunningStateChanged(isFingerprintDetectionRunning()); } } } @@ -501,7 +514,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { } public boolean isFingerprintDetectionRunning() { - return mFingerprintDetectionRunning; + return mFingerprintRunningState == FINGERPRINT_STATE_RUNNING; } private boolean isTrustDisabled(int userId) { @@ -516,7 +529,8 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { final DevicePolicyManager dpm = (DevicePolicyManager) mContext.getSystemService(Context.DEVICE_POLICY_SERVICE); return dpm != null && (dpm.getKeyguardDisabledFeatures(null, userId) - & DevicePolicyManager.KEYGUARD_DISABLE_FINGERPRINT) != 0; + & DevicePolicyManager.KEYGUARD_DISABLE_FINGERPRINT) != 0 + || isSimPinSecure(); } public boolean getUserCanSkipBouncer(int userId) { @@ -533,7 +547,48 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { } public boolean isUnlockingWithFingerprintAllowed() { - return mUserHasAuthenticatedSinceBoot; + return mStrongAuthTracker.isUnlockingWithFingerprintAllowed() + && !hasFingerprintUnlockTimedOut(sCurrentUser); + } + + public StrongAuthTracker getStrongAuthTracker() { + return mStrongAuthTracker; + } + + /** + * @return true if the user hasn't use strong authentication (pattern, PIN, password) since a + * while and thus can't unlock with fingerprint, false otherwise + */ + public boolean hasFingerprintUnlockTimedOut(int userId) { + return !mStrongAuthNotTimedOut.contains(userId); + } + + public void reportSuccessfulStrongAuthUnlockAttempt() { + mStrongAuthNotTimedOut.add(sCurrentUser); + scheduleStrongAuthTimeout(); + if (mFpm != null) { + byte[] token = null; /* TODO: pass real auth token once fp HAL supports it */ + mFpm.resetTimeout(token); + } + } + + private void scheduleStrongAuthTimeout() { + long when = SystemClock.elapsedRealtime() + FINGERPRINT_UNLOCK_TIMEOUT_MS; + Intent intent = new Intent(ACTION_STRONG_AUTH_TIMEOUT); + intent.putExtra(USER_ID, sCurrentUser); + PendingIntent sender = PendingIntent.getBroadcast(mContext, + sCurrentUser, intent, PendingIntent.FLAG_CANCEL_CURRENT); + mAlarmManager.set(AlarmManager.ELAPSED_REALTIME, when, sender); + notifyStrongAuthStateChanged(sCurrentUser); + } + + private void notifyStrongAuthStateChanged(int userId) { + for (int i = 0; i < mCallbacks.size(); i++) { + KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get(); + if (cb != null) { + cb.onStrongAuthStateChanged(userId); + } + } } static class DisplayClientState { @@ -561,8 +616,10 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { final int plugged = intent.getIntExtra(EXTRA_PLUGGED, 0); final int level = intent.getIntExtra(EXTRA_LEVEL, 0); final int health = intent.getIntExtra(EXTRA_HEALTH, BATTERY_HEALTH_UNKNOWN); + final int maxChargingCurrent = intent.getIntExtra(EXTRA_MAX_CHARGING_CURRENT, -1); final Message msg = mHandler.obtainMessage( - MSG_BATTERY_UPDATE, new BatteryStatus(status, level, plugged, health)); + MSG_BATTERY_UPDATE, new BatteryStatus(status, level, plugged, health, + maxChargingCurrent)); mHandler.sendMessage(msg); } else if (TelephonyIntents.ACTION_SIM_STATE_CHANGED.equals(action)) { SimData args = SimData.fromIntent(intent); @@ -619,6 +676,25 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { } }; + private final BroadcastReceiver mStrongAuthTimeoutReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + if (ACTION_STRONG_AUTH_TIMEOUT.equals(intent.getAction())) { + int userId = intent.getIntExtra(USER_ID, -1); + mStrongAuthNotTimedOut.remove(userId); + notifyStrongAuthStateChanged(userId); + } + } + }; + + private final FingerprintManager.LockoutResetCallback mLockoutResetCallback + = new FingerprintManager.LockoutResetCallback() { + @Override + public void onLockoutReset() { + handleFingerprintLockoutReset(); + } + }; + private FingerprintManager.AuthenticationCallback mAuthenticationCallback = new AuthenticationCallback() { @@ -649,7 +725,6 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { }; private CancellationSignal mFingerprintCancelSignal; private FingerprintManager mFpm; - private PowerManager.WakeLock mWakeLock; /** * When we receive a @@ -721,15 +796,22 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { } public static class BatteryStatus { + public static final int CHARGING_UNKNOWN = -1; + public static final int CHARGING_SLOWLY = 0; + public static final int CHARGING_REGULAR = 1; + public static final int CHARGING_FAST = 2; + public final int status; public final int level; public final int plugged; public final int health; - public BatteryStatus(int status, int level, int plugged, int health) { + public final int maxChargingCurrent; + public BatteryStatus(int status, int level, int plugged, int health, int maxChargingCurrent) { this.status = status; this.level = level; this.plugged = plugged; this.health = health; + this.maxChargingCurrent = maxChargingCurrent; } /** @@ -760,6 +842,31 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { return level < LOW_BATTERY_THRESHOLD; } + public final int getChargingSpeed(int slowThreshold, int fastThreshold) { + return maxChargingCurrent <= 0 ? CHARGING_UNKNOWN : + maxChargingCurrent < slowThreshold ? CHARGING_SLOWLY : + maxChargingCurrent > fastThreshold ? CHARGING_FAST : + CHARGING_REGULAR; + } + } + + public class StrongAuthTracker extends LockPatternUtils.StrongAuthTracker { + + public boolean isUnlockingWithFingerprintAllowed() { + int userId = getCurrentUser(); + return isFingerprintAllowedForUser(userId); + } + + public boolean hasUserAuthenticatedSinceBoot() { + int userId = getCurrentUser(); + return (getStrongAuthForUser(userId) + & STRONG_AUTH_REQUIRED_AFTER_BOOT) == 0; + } + + @Override + public void onStrongAuthRequiredChanged(int userId) { + notifyStrongAuthStateChanged(userId); + } } public static KeyguardUpdateMonitor getInstance(Context context) { @@ -780,18 +887,52 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { } } - protected void handleFinishedGoingToSleep(int arg1) { + protected void handleStartedGoingToSleep(int arg1) { clearFingerprintRecognized(); final int count = mCallbacks.size(); for (int i = 0; i < count; i++) { KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get(); if (cb != null) { + cb.onStartedGoingToSleep(arg1); + } + } + mGoingToSleep = true; + mFingerprintAlreadyAuthenticated = false; + updateFingerprintListeningState(); + } + + protected void handleFinishedGoingToSleep(int arg1) { + mGoingToSleep = false; + final int count = mCallbacks.size(); + for (int i = 0; i < count; i++) { + KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get(); + if (cb != null) { cb.onFinishedGoingToSleep(arg1); } } updateFingerprintListeningState(); } + private void handleScreenTurnedOn() { + final int count = mCallbacks.size(); + for (int i = 0; i < count; i++) { + KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get(); + if (cb != null) { + cb.onScreenTurnedOn(); + } + } + } + + private void handleScreenTurnedOff() { + final int count = mCallbacks.size(); + for (int i = 0; i < count; i++) { + KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get(); + if (cb != null) { + cb.onScreenTurnedOff(); + } + } + } + /** * IMPORTANT: Must be called from UI thread. */ @@ -818,8 +959,9 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { private KeyguardUpdateMonitor(Context context) { mContext = context; mSubscriptionManager = SubscriptionManager.from(context); - mPowerManager = context.getSystemService(PowerManager.class); + mAlarmManager = context.getSystemService(AlarmManager.class); mDeviceProvisioned = isDeviceProvisionedInSettingsDb(); + // Since device can't be un-provisioned, we only need to register a content observer // to update mDeviceProvisioned when we are... if (!mDeviceProvisioned) { @@ -827,7 +969,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { } // Take a guess at initial SIM state, battery status and PLMN until we get an update - mBatteryStatus = new BatteryStatus(BATTERY_STATUS_UNKNOWN, 100, 0, 0); + mBatteryStatus = new BatteryStatus(BATTERY_STATUS_UNKNOWN, 100, 0, 0, 0); // Watch for interesting updates final IntentFilter filter = new IntentFilter(); @@ -880,53 +1022,69 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { e.printStackTrace(); } + IntentFilter strongAuthTimeoutFilter = new IntentFilter(); + strongAuthTimeoutFilter.addAction(ACTION_STRONG_AUTH_TIMEOUT); + context.registerReceiver(mStrongAuthTimeoutReceiver, strongAuthTimeoutFilter, + PERMISSION_SELF, null /* handler */); mTrustManager = (TrustManager) context.getSystemService(Context.TRUST_SERVICE); mTrustManager.registerTrustListener(this); + new LockPatternUtils(context).registerStrongAuthTracker(mStrongAuthTracker); mFpm = (FingerprintManager) context.getSystemService(Context.FINGERPRINT_SERVICE); updateFingerprintListeningState(); + if (mFpm != null) { + mFpm.addLockoutResetCallback(mLockoutResetCallback); + } } private void updateFingerprintListeningState() { boolean shouldListenForFingerprint = shouldListenForFingerprint(); - if (mFingerprintDetectionRunning && !shouldListenForFingerprint) { + if (mFingerprintRunningState == FINGERPRINT_STATE_RUNNING && !shouldListenForFingerprint) { stopListeningForFingerprint(); - } else if (!mFingerprintDetectionRunning && shouldListenForFingerprint) { + } else if (mFingerprintRunningState != FINGERPRINT_STATE_RUNNING + && shouldListenForFingerprint) { startListeningForFingerprint(); } } private boolean shouldListenForFingerprint() { - return mKeyguardIsVisible && !mSwitchingUser; + return (mKeyguardIsVisible || !mDeviceInteractive || mBouncer || mGoingToSleep) + && !mSwitchingUser && !mFingerprintAlreadyAuthenticated + && !isFingerprintDisabled(getCurrentUser()); } private void startListeningForFingerprint() { + if (mFingerprintRunningState == FINGERPRINT_STATE_CANCELLING) { + setFingerprintRunningState(FINGERPRINT_STATE_CANCELLING_RESTARTING); + return; + } if (DEBUG) Log.v(TAG, "startListeningForFingerprint()"); int userId = ActivityManager.getCurrentUser(); - if (isUnlockWithFingerPrintPossible(userId)) { - mUserHasAuthenticatedSinceBoot = mTrustManager.hasUserAuthenticatedSinceBoot( - ActivityManager.getCurrentUser()); + if (isUnlockWithFingerprintPossible(userId)) { if (mFingerprintCancelSignal != null) { mFingerprintCancelSignal.cancel(); } mFingerprintCancelSignal = new CancellationSignal(); mFpm.authenticate(null, mFingerprintCancelSignal, 0, mAuthenticationCallback, null, userId); - setFingerprintRunningDetectionRunning(true); + setFingerprintRunningState(FINGERPRINT_STATE_RUNNING); } } - public boolean isUnlockWithFingerPrintPossible(int userId) { + public boolean isUnlockWithFingerprintPossible(int userId) { return mFpm != null && mFpm.isHardwareDetected() && !isFingerprintDisabled(userId) && mFpm.getEnrolledFingerprints(userId).size() > 0; } private void stopListeningForFingerprint() { if (DEBUG) Log.v(TAG, "stopListeningForFingerprint()"); - if (isFingerprintDetectionRunning()) { + if (mFingerprintRunningState == FINGERPRINT_STATE_RUNNING) { mFingerprintCancelSignal.cancel(); mFingerprintCancelSignal = null; + setFingerprintRunningState(FINGERPRINT_STATE_CANCELLING); + } + if (mFingerprintRunningState == FINGERPRINT_STATE_CANCELLING_RESTARTING) { + setFingerprintRunningState(FINGERPRINT_STATE_CANCELLING); } - setFingerprintRunningDetectionRunning(false); } private boolean isDeviceProvisionedInSettingsDb() { @@ -966,6 +1124,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { * Handle {@link #MSG_DPM_STATE_CHANGED} */ protected void handleDevicePolicyManagerStateChanged() { + updateFingerprintListeningState(); for (int i = mCallbacks.size() - 1; i >= 0; i--) { KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get(); if (cb != null) { @@ -1183,18 +1342,22 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { } /** - * Handle {@link #MSG_KEYGUARD_VISIBILITY_CHANGED} + * Notifies that the visibility state of Keyguard has changed. + * + * <p>Needs to be called from the main thread. */ - private void handleKeyguardVisibilityChanged(int showing) { - if (DEBUG) Log.d(TAG, "handleKeyguardVisibilityChanged(" + showing + ")"); - boolean isShowing = (showing == 1); - mKeyguardIsVisible = isShowing; + public void onKeyguardVisibilityChanged(boolean showing) { + if (DEBUG) Log.d(TAG, "onKeyguardVisibilityChanged(" + showing + ")"); + mKeyguardIsVisible = showing; for (int i = 0; i < mCallbacks.size(); i++) { KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get(); if (cb != null) { - cb.onKeyguardVisibilityChangedRaw(isShowing); + cb.onKeyguardVisibilityChangedRaw(showing); } } + if (!showing) { + mFingerprintAlreadyAuthenticated = false; + } updateFingerprintListeningState(); } @@ -1203,9 +1366,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { */ private void handleKeyguardReset() { if (DEBUG) Log.d(TAG, "handleKeyguardReset"); - if (!isUnlockingWithFingerprintAllowed()) { - updateFingerprintListeningState(); - } + updateFingerprintListeningState(); } /** @@ -1222,6 +1383,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { cb.onKeyguardBouncerChanged(isBouncer); } } + updateFingerprintListeningState(); } /** @@ -1257,6 +1419,12 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { if (!nowPluggedIn && current.isBatteryLow() && current.level != old.level) { return true; } + + // change in charging current while plugged in + if (nowPluggedIn && current.maxChargingCurrent != old.maxChargingCurrent) { + return true; + } + return false; } @@ -1308,13 +1476,6 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { } } - public void sendKeyguardVisibilityChanged(boolean showing) { - if (DEBUG) Log.d(TAG, "sendKeyguardVisibilityChanged(" + showing + ")"); - Message message = mHandler.obtainMessage(MSG_KEYGUARD_VISIBILITY_CHANGED); - message.arg1 = showing ? 1 : 0; - message.sendToTarget(); - } - public void sendKeyguardReset() { mHandler.obtainMessage(MSG_KEYGUARD_RESET).sendToTarget(); } @@ -1375,7 +1536,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { return mFailedAttempts.get(sCurrentUser, 0); } - public void reportFailedUnlockAttempt() { + public void reportFailedStrongAuthUnlockAttempt() { mFailedAttempts.put(sCurrentUser, getFailedUnlockAttempts() + 1); } @@ -1455,6 +1616,10 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { mHandler.sendEmptyMessage(MSG_STARTED_WAKING_UP); } + public void dispatchStartedGoingToSleep(int why) { + mHandler.sendMessage(mHandler.obtainMessage(MSG_STARTED_GOING_TO_SLEEP, why, 0)); + } + public void dispatchFinishedGoingToSleep(int why) { synchronized(this) { mDeviceInteractive = false; @@ -1466,18 +1631,24 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { synchronized (this) { mScreenOn = true; } + mHandler.sendEmptyMessage(MSG_SCREEN_TURNED_ON); } public void dispatchScreenTurnedOff() { synchronized(this) { mScreenOn = false; } + mHandler.sendEmptyMessage(MSG_SCREEN_TURNED_OFF); } public boolean isDeviceInteractive() { return mDeviceInteractive; } + public boolean isGoingToSleep() { + return mGoingToSleep; + } + /** * Find the next SubscriptionId for a SIM in the given state, favoring lower slot numbers first. * @param state diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java index 0cdf999..bd6c51c 100644 --- a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java +++ b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java @@ -153,6 +153,12 @@ public class KeyguardUpdateMonitorCallback { public void onStartedWakingUp() { } /** + * Called when the device has started going to sleep. + * @param why see {@link #onFinishedGoingToSleep(int)} + */ + public void onStartedGoingToSleep(int why) { } + + /** * Called when the device has finished going to sleep. * @param why either {@link WindowManagerPolicy#OFF_BECAUSE_OF_ADMIN}, * {@link WindowManagerPolicy#OFF_BECAUSE_OF_USER}, or @@ -161,6 +167,16 @@ public class KeyguardUpdateMonitorCallback { public void onFinishedGoingToSleep(int why) { } /** + * Called when the screen has been turned on. + */ + public void onScreenTurnedOn() { } + + /** + * Called when the screen has been turned off. + */ + public void onScreenTurnedOff() { } + + /** * Called when trust changes for a user. */ public void onTrustChanged(int userId) { } @@ -176,12 +192,23 @@ public class KeyguardUpdateMonitorCallback { public void onTrustGrantedWithFlags(int flags, int userId) { } /** + * Called when a finger has been acquired. + * <p> + * It is guaranteed that either {@link #onFingerprintAuthenticated} or + * {@link #onFingerprintAuthFailed()} is called after this method eventually. + */ + public void onFingerprintAcquired() { } + + /** + * Called when a fingerprint couldn't be authenticated. + */ + public void onFingerprintAuthFailed() { } + + /** * Called when a fingerprint is recognized. * @param userId the user id for which the fingerprint was authenticated - * @param wakeAndUnlocking whether the authentication woke the device up and thus we'd like to - * dismiss the lockscreen before turning on the screen */ - public void onFingerprintAuthenticated(int userId, boolean wakeAndUnlocking) { } + public void onFingerprintAuthenticated(int userId) { } /** * Called when fingerprint provides help string (e.g. "Try again") @@ -207,4 +234,10 @@ public class KeyguardUpdateMonitorCallback { * Called when the fingerprint running state changed. */ public void onFingerprintRunningStateChanged(boolean running) { } + + /** + * Called when the state that the user hasn't used strong authentication since quite some time + * has changed. + */ + public void onStrongAuthStateChanged(int userId) { } } diff --git a/packages/Keyguard/src/com/android/keyguard/SecurityMessageDisplay.java b/packages/Keyguard/src/com/android/keyguard/SecurityMessageDisplay.java index b38cfd5..ddb1f6e 100644 --- a/packages/Keyguard/src/com/android/keyguard/SecurityMessageDisplay.java +++ b/packages/Keyguard/src/com/android/keyguard/SecurityMessageDisplay.java @@ -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); } diff --git a/packages/Keyguard/src/com/android/keyguard/ViewMediatorCallback.java b/packages/Keyguard/src/com/android/keyguard/ViewMediatorCallback.java index ff463c6..8ab3011 100644 --- a/packages/Keyguard/src/com/android/keyguard/ViewMediatorCallback.java +++ b/packages/Keyguard/src/com/android/keyguard/ViewMediatorCallback.java @@ -28,12 +28,11 @@ public interface ViewMediatorCallback { /** * Report that the keyguard is done. - * @param authenticated Whether the user securely got past the keyguard. - * the only reason for this to be false is if the keyguard was instructed - * to appear temporarily to verify the user is supposed to get past the - * keyguard, and the user fails to do so. + * + * @param strongAuth whether the user has authenticated with strong authentication like + * pattern, password or PIN but not by trust agents or fingerprint */ - void keyguardDone(boolean authenticated); + void keyguardDone(boolean strongAuth); /** * Report that the keyguard is done drawing. @@ -48,8 +47,11 @@ public interface ViewMediatorCallback { /** * Report that the keyguard is dismissable, pending the next keyguardDone call. + * + * @param strongAuth whether the user has authenticated with strong authentication like + * pattern, password or PIN but not by trust agents or fingerprint */ - void keyguardDonePending(); + void keyguardDonePending(boolean strongAuth); /** * Report when keyguard is actually gone @@ -85,8 +87,9 @@ public interface ViewMediatorCallback { /** * @return one of the reasons why the bouncer needs to be shown right now and the user can't use * his normal unlock method like fingerprint or trust agents. See - * {@link KeyguardSecurityView#PROMPT_REASON_NONE} - * and {@link KeyguardSecurityView#PROMPT_REASON_RESTART}. + * {@link KeyguardSecurityView#PROMPT_REASON_NONE}, + * {@link KeyguardSecurityView#PROMPT_REASON_RESTART} and + * {@link KeyguardSecurityView#PROMPT_REASON_TIMEOUT}. */ int getBouncerPromptReason(); } |