Merge \"Improve initial unlock delay (1/2)\" into nyc-mr1-dev
am: 165b011a74
Change-Id: Ib7bfefcd59288d144a22434e5a99124c66fa4826
This commit is contained in:
@@ -343,6 +343,7 @@ LOCAL_SRC_FILES += \
|
||||
core/java/com/android/internal/view/IInputMethodManager.aidl \
|
||||
core/java/com/android/internal/view/IInputMethodSession.aidl \
|
||||
core/java/com/android/internal/view/IInputSessionCallback.aidl \
|
||||
core/java/com/android/internal/widget/ICheckCredentialProgressCallback.aidl \
|
||||
core/java/com/android/internal/widget/ILockSettings.aidl \
|
||||
core/java/com/android/internal/widget/IRemoteViewsFactory.aidl \
|
||||
core/java/com/android/internal/widget/IRemoteViewsAdapterConnection.aidl \
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright (C) 2016 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.internal.widget;
|
||||
|
||||
/** {@hide} */
|
||||
oneway interface ICheckCredentialProgressCallback {
|
||||
void onCredentialVerified();
|
||||
}
|
||||
@@ -17,6 +17,7 @@
|
||||
package com.android.internal.widget;
|
||||
|
||||
import android.app.trust.IStrongAuthTracker;
|
||||
import com.android.internal.widget.ICheckCredentialProgressCallback;
|
||||
import com.android.internal.widget.VerifyCredentialResponse;
|
||||
|
||||
/** {@hide} */
|
||||
@@ -29,10 +30,12 @@ interface ILockSettings {
|
||||
String getString(in String key, in String defaultValue, in int userId);
|
||||
void setLockPattern(in String pattern, in String savedPattern, int userId);
|
||||
void resetKeyStore(int userId);
|
||||
VerifyCredentialResponse checkPattern(in String pattern, int userId);
|
||||
VerifyCredentialResponse checkPattern(in String pattern, int userId,
|
||||
in ICheckCredentialProgressCallback progressCallback);
|
||||
VerifyCredentialResponse verifyPattern(in String pattern, long challenge, int userId);
|
||||
void setLockPassword(in String password, in String savedPassword, int userId);
|
||||
VerifyCredentialResponse checkPassword(in String password, int userId);
|
||||
VerifyCredentialResponse checkPassword(in String password, int userId,
|
||||
in ICheckCredentialProgressCallback progressCallback);
|
||||
VerifyCredentialResponse verifyPassword(in String password, long challenge, int userId);
|
||||
VerifyCredentialResponse verifyTiedProfileChallenge(String password, boolean isPattern, long challenge, int userId);
|
||||
boolean checkVoldPassword(int userId);
|
||||
|
||||
@@ -14,6 +14,13 @@ public final class LockPatternChecker {
|
||||
* Interface for a callback to be invoked after security check.
|
||||
*/
|
||||
public interface OnCheckCallback {
|
||||
|
||||
/**
|
||||
* Invoked as soon as possible we know that the credentials match. This will be called
|
||||
* earlier than {@link #onChecked} but only if the credentials match.
|
||||
*/
|
||||
default void onEarlyMatched() {}
|
||||
|
||||
/**
|
||||
* Invoked when a security check is finished.
|
||||
*
|
||||
@@ -92,7 +99,7 @@ public final class LockPatternChecker {
|
||||
@Override
|
||||
protected Boolean doInBackground(Void... args) {
|
||||
try {
|
||||
return utils.checkPattern(pattern, userId);
|
||||
return utils.checkPattern(pattern, userId, callback::onEarlyMatched);
|
||||
} catch (RequestThrottledException ex) {
|
||||
mThrottleTimeout = ex.getTimeoutMs();
|
||||
return false;
|
||||
@@ -199,7 +206,7 @@ public final class LockPatternChecker {
|
||||
@Override
|
||||
protected Boolean doInBackground(Void... args) {
|
||||
try {
|
||||
return utils.checkPassword(password, userId);
|
||||
return utils.checkPassword(password, userId, callback::onEarlyMatched);
|
||||
} catch (RequestThrottledException ex) {
|
||||
mThrottleTimeout = ex.getTimeoutMs();
|
||||
return false;
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package com.android.internal.widget;
|
||||
|
||||
import android.annotation.IntDef;
|
||||
import android.annotation.Nullable;
|
||||
import android.app.admin.DevicePolicyManager;
|
||||
import android.app.trust.IStrongAuthTracker;
|
||||
import android.app.trust.TrustManager;
|
||||
@@ -32,7 +33,6 @@ import android.os.Message;
|
||||
import android.os.RemoteException;
|
||||
import android.os.ServiceManager;
|
||||
import android.os.SystemClock;
|
||||
import android.os.SystemProperties;
|
||||
import android.os.UserHandle;
|
||||
import android.os.UserManager;
|
||||
import android.os.storage.IMountService;
|
||||
@@ -149,6 +149,7 @@ public class LockPatternUtils {
|
||||
private DevicePolicyManager mDevicePolicyManager;
|
||||
private ILockSettings mLockSettingsService;
|
||||
private UserManager mUserManager;
|
||||
private final Handler mHandler = new Handler();
|
||||
|
||||
/**
|
||||
* Use {@link TrustManager#isTrustUsuallyManaged(int)}.
|
||||
@@ -341,10 +342,23 @@ public class LockPatternUtils {
|
||||
*/
|
||||
public boolean checkPattern(List<LockPatternView.Cell> pattern, int userId)
|
||||
throws RequestThrottledException {
|
||||
return checkPattern(pattern, userId, null /* progressCallback */);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check to see if a pattern matches the saved pattern. If no pattern exists,
|
||||
* always returns true.
|
||||
* @param pattern The pattern to check.
|
||||
* @return Whether the pattern matches the stored one.
|
||||
*/
|
||||
public boolean checkPattern(List<LockPatternView.Cell> pattern, int userId,
|
||||
@Nullable CheckCredentialProgressCallback progressCallback)
|
||||
throws RequestThrottledException {
|
||||
throwIfCalledOnMainThread();
|
||||
try {
|
||||
VerifyCredentialResponse response =
|
||||
getLockSettings().checkPattern(patternToString(pattern), userId);
|
||||
getLockSettings().checkPattern(patternToString(pattern), userId,
|
||||
wrapCallback(progressCallback));
|
||||
|
||||
if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK) {
|
||||
return true;
|
||||
@@ -423,10 +437,22 @@ public class LockPatternUtils {
|
||||
* @return Whether the password matches the stored one.
|
||||
*/
|
||||
public boolean checkPassword(String password, int userId) throws RequestThrottledException {
|
||||
return checkPassword(password, userId, null /* progressCallback */);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check to see if a password matches the saved password. If no password exists,
|
||||
* always returns true.
|
||||
* @param password The password to check.
|
||||
* @return Whether the password matches the stored one.
|
||||
*/
|
||||
public boolean checkPassword(String password, int userId,
|
||||
@Nullable CheckCredentialProgressCallback progressCallback)
|
||||
throws RequestThrottledException {
|
||||
throwIfCalledOnMainThread();
|
||||
try {
|
||||
VerifyCredentialResponse response =
|
||||
getLockSettings().checkPassword(password, userId);
|
||||
getLockSettings().checkPassword(password, userId, wrapCallback(progressCallback));
|
||||
if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK) {
|
||||
return true;
|
||||
} else if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_RETRY) {
|
||||
@@ -1475,6 +1501,33 @@ public class LockPatternUtils {
|
||||
return (getStrongAuthForUser(userId) & ~StrongAuthTracker.ALLOWING_FINGERPRINT) == 0;
|
||||
}
|
||||
|
||||
private ICheckCredentialProgressCallback wrapCallback(
|
||||
final CheckCredentialProgressCallback callback) {
|
||||
if (callback == null) {
|
||||
return null;
|
||||
} else {
|
||||
return new ICheckCredentialProgressCallback.Stub() {
|
||||
|
||||
@Override
|
||||
public void onCredentialVerified() throws RemoteException {
|
||||
mHandler.post(callback::onEarlyMatched);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback to be notified about progress when checking credentials.
|
||||
*/
|
||||
public interface CheckCredentialProgressCallback {
|
||||
|
||||
/**
|
||||
* Called as soon as possible when we know that the credentials match but the user hasn't
|
||||
* been fully unlocked.
|
||||
*/
|
||||
void onEarlyMatched();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tracks the global strong authentication state.
|
||||
*/
|
||||
|
||||
@@ -137,12 +137,21 @@ public abstract class KeyguardAbsKeyInputView extends LinearLayout
|
||||
entry,
|
||||
userId,
|
||||
new LockPatternChecker.OnCheckCallback() {
|
||||
|
||||
@Override
|
||||
public void onEarlyMatched() {
|
||||
onPasswordChecked(userId, true /* matched */, 0 /* timeoutMs */,
|
||||
true /* isValidPassword */);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChecked(boolean matched, int timeoutMs) {
|
||||
setPasswordEntryInputEnabled(true);
|
||||
mPendingLockCheck = null;
|
||||
onPasswordChecked(userId, matched, timeoutMs,
|
||||
true /* isValidPassword */);
|
||||
if (!matched) {
|
||||
onPasswordChecked(userId, false /* matched */, timeoutMs,
|
||||
true /* isValidPassword */);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -36,6 +36,7 @@ public class KeyguardPINView extends KeyguardPinBasedInputView {
|
||||
|
||||
private final AppearAnimationUtils mAppearAnimationUtils;
|
||||
private final DisappearAnimationUtils mDisappearAnimationUtils;
|
||||
private final DisappearAnimationUtils mDisappearAnimationUtilsLocked;
|
||||
private ViewGroup mContainer;
|
||||
private ViewGroup mRow0;
|
||||
private ViewGroup mRow1;
|
||||
@@ -44,6 +45,7 @@ public class KeyguardPINView extends KeyguardPinBasedInputView {
|
||||
private View mDivider;
|
||||
private int mDisappearYTranslation;
|
||||
private View[][] mViews;
|
||||
private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
|
||||
|
||||
public KeyguardPINView(Context context) {
|
||||
this(context, null);
|
||||
@@ -56,8 +58,14 @@ public class KeyguardPINView extends KeyguardPinBasedInputView {
|
||||
125, 0.6f /* translationScale */,
|
||||
0.45f /* delayScale */, AnimationUtils.loadInterpolator(
|
||||
mContext, android.R.interpolator.fast_out_linear_in));
|
||||
mDisappearAnimationUtilsLocked = new DisappearAnimationUtils(context,
|
||||
(long) (125 * KeyguardPatternView.DISAPPEAR_MULTIPLIER_LOCKED),
|
||||
0.6f /* translationScale */,
|
||||
0.45f /* delayScale */, AnimationUtils.loadInterpolator(
|
||||
mContext, android.R.interpolator.fast_out_linear_in));
|
||||
mDisappearYTranslation = getResources().getDimensionPixelSize(
|
||||
R.dimen.disappear_y_translation);
|
||||
mKeyguardUpdateMonitor = KeyguardUpdateMonitor.getInstance(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -136,7 +144,10 @@ public class KeyguardPINView extends KeyguardPinBasedInputView {
|
||||
setTranslationY(0);
|
||||
AppearAnimationUtils.startTranslationYAnimation(this, 0 /* delay */, 280 /* duration */,
|
||||
mDisappearYTranslation, mDisappearAnimationUtils.getInterpolator());
|
||||
mDisappearAnimationUtils.startAnimation2d(mViews,
|
||||
DisappearAnimationUtils disappearAnimationUtils = mKeyguardUpdateMonitor.isUserUnlocked()
|
||||
? mDisappearAnimationUtils
|
||||
: mDisappearAnimationUtilsLocked;
|
||||
disappearAnimationUtils.startAnimation2d(mViews,
|
||||
new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
@@ -55,9 +55,13 @@ public class KeyguardPatternView extends LinearLayout implements KeyguardSecurit
|
||||
// how many cells the user has to cross before we poke the wakelock
|
||||
private static final int MIN_PATTERN_BEFORE_POKE_WAKELOCK = 2;
|
||||
|
||||
// How much we scale up the duration of the disappear animation when the current user is locked
|
||||
public static final float DISAPPEAR_MULTIPLIER_LOCKED = 1.5f;
|
||||
|
||||
private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
|
||||
private final AppearAnimationUtils mAppearAnimationUtils;
|
||||
private final DisappearAnimationUtils mDisappearAnimationUtils;
|
||||
private final DisappearAnimationUtils mDisappearAnimationUtilsLocked;
|
||||
|
||||
private CountDownTimer mCountdownTimer = null;
|
||||
private LockPatternUtils mLockPatternUtils;
|
||||
@@ -109,6 +113,10 @@ public class KeyguardPatternView extends LinearLayout implements KeyguardSecurit
|
||||
125, 1.2f /* translationScale */,
|
||||
0.6f /* delayScale */, AnimationUtils.loadInterpolator(
|
||||
mContext, android.R.interpolator.fast_out_linear_in));
|
||||
mDisappearAnimationUtilsLocked = new DisappearAnimationUtils(context,
|
||||
(long) (125 * DISAPPEAR_MULTIPLIER_LOCKED), 1.2f /* translationScale */,
|
||||
0.6f /* delayScale */, AnimationUtils.loadInterpolator(
|
||||
mContext, android.R.interpolator.fast_out_linear_in));
|
||||
mDisappearYTranslation = getResources().getDimensionPixelSize(
|
||||
R.dimen.disappear_y_translation);
|
||||
}
|
||||
@@ -239,11 +247,21 @@ public class KeyguardPatternView extends LinearLayout implements KeyguardSecurit
|
||||
pattern,
|
||||
userId,
|
||||
new LockPatternChecker.OnCheckCallback() {
|
||||
|
||||
@Override
|
||||
public void onEarlyMatched() {
|
||||
onPatternChecked(userId, true /* matched */, 0 /* timeoutMs */,
|
||||
true /* isValidPattern */);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChecked(boolean matched, int timeoutMs) {
|
||||
mLockPatternView.enableInput();
|
||||
mPendingLockCheck = null;
|
||||
onPatternChecked(userId, matched, timeoutMs, true);
|
||||
if (!matched) {
|
||||
onPatternChecked(userId, false /* matched */, timeoutMs,
|
||||
true /* isValidPattern */);
|
||||
}
|
||||
}
|
||||
});
|
||||
if (pattern.size() > MIN_PATTERN_BEFORE_POKE_WAKELOCK) {
|
||||
@@ -390,25 +408,30 @@ public class KeyguardPatternView extends LinearLayout implements KeyguardSecurit
|
||||
|
||||
@Override
|
||||
public boolean startDisappearAnimation(final Runnable finishRunnable) {
|
||||
float durationMultiplier = mKeyguardUpdateMonitor.isUserUnlocked()
|
||||
? 1f
|
||||
: DISAPPEAR_MULTIPLIER_LOCKED;
|
||||
mLockPatternView.clearPattern();
|
||||
enableClipping(false);
|
||||
setTranslationY(0);
|
||||
AppearAnimationUtils.startTranslationYAnimation(this, 0 /* delay */, 300 /* duration */,
|
||||
AppearAnimationUtils.startTranslationYAnimation(this, 0 /* delay */,
|
||||
(long) (300 * durationMultiplier),
|
||||
-mDisappearAnimationUtils.getStartTranslation(),
|
||||
mDisappearAnimationUtils.getInterpolator());
|
||||
mDisappearAnimationUtils.startAnimation2d(mLockPatternView.getCellStates(),
|
||||
new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
enableClipping(true);
|
||||
if (finishRunnable != null) {
|
||||
finishRunnable.run();
|
||||
}
|
||||
|
||||
DisappearAnimationUtils disappearAnimationUtils = mKeyguardUpdateMonitor.isUserUnlocked()
|
||||
? mDisappearAnimationUtils
|
||||
: mDisappearAnimationUtilsLocked;
|
||||
disappearAnimationUtils.startAnimation2d(mLockPatternView.getCellStates(),
|
||||
() -> {
|
||||
enableClipping(true);
|
||||
if (finishRunnable != null) {
|
||||
finishRunnable.run();
|
||||
}
|
||||
}, KeyguardPatternView.this);
|
||||
if (!TextUtils.isEmpty(mSecurityMessageDisplay.getText())) {
|
||||
mDisappearAnimationUtils.createAnimation(mSecurityMessageDisplay, 0,
|
||||
200,
|
||||
(long) (200 * durationMultiplier),
|
||||
- mDisappearAnimationUtils.getStartTranslation() * 3,
|
||||
false /* appearing */,
|
||||
mDisappearAnimationUtils.getInterpolator(),
|
||||
|
||||
@@ -16,6 +16,16 @@
|
||||
|
||||
package com.android.keyguard;
|
||||
|
||||
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_MAX_CHARGING_VOLTAGE;
|
||||
import static android.os.BatteryManager.EXTRA_PLUGGED;
|
||||
import static android.os.BatteryManager.EXTRA_STATUS;
|
||||
|
||||
import android.app.ActivityManager;
|
||||
import android.app.ActivityManagerNative;
|
||||
import android.app.AlarmManager;
|
||||
@@ -29,7 +39,6 @@ import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.database.ContentObserver;
|
||||
import android.graphics.Bitmap;
|
||||
import android.hardware.fingerprint.Fingerprint;
|
||||
import android.hardware.fingerprint.FingerprintManager;
|
||||
import android.hardware.fingerprint.FingerprintManager.AuthenticationCallback;
|
||||
import android.hardware.fingerprint.FingerprintManager.AuthenticationResult;
|
||||
@@ -42,6 +51,7 @@ import android.os.Message;
|
||||
import android.os.RemoteException;
|
||||
import android.os.SystemClock;
|
||||
import android.os.UserHandle;
|
||||
import android.os.UserManager;
|
||||
import android.provider.Settings;
|
||||
import android.telephony.ServiceState;
|
||||
import android.telephony.SubscriptionInfo;
|
||||
@@ -69,16 +79,6 @@ 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_MAX_CHARGING_VOLTAGE;
|
||||
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
|
||||
@@ -176,6 +176,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
|
||||
private boolean mGoingToSleep;
|
||||
private boolean mBouncer;
|
||||
private boolean mBootCompleted;
|
||||
private boolean mUserUnlocked;
|
||||
|
||||
// Device provisioning state
|
||||
private boolean mDeviceProvisioned;
|
||||
@@ -202,6 +203,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
|
||||
private AlarmManager mAlarmManager;
|
||||
private List<SubscriptionInfo> mSubscriptionInfo;
|
||||
private TrustManager mTrustManager;
|
||||
private UserManager mUserManager;
|
||||
private int mFingerprintRunningState = FINGERPRINT_STATE_STOPPED;
|
||||
|
||||
private final Handler mHandler = new Handler() {
|
||||
@@ -554,6 +556,10 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
|
||||
&& !hasFingerprintUnlockTimedOut(sCurrentUser);
|
||||
}
|
||||
|
||||
public boolean isUserUnlocked() {
|
||||
return mUserUnlocked;
|
||||
}
|
||||
|
||||
public StrongAuthTracker getStrongAuthTracker() {
|
||||
return mStrongAuthTracker;
|
||||
}
|
||||
@@ -1058,6 +1064,8 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
|
||||
if (mFpm != null) {
|
||||
mFpm.addLockoutResetCallback(mLockoutResetCallback);
|
||||
}
|
||||
|
||||
mUserManager = context.getSystemService(UserManager.class);
|
||||
}
|
||||
|
||||
private void updateFingerprintListeningState() {
|
||||
@@ -1390,6 +1398,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
|
||||
private void handleKeyguardReset() {
|
||||
if (DEBUG) Log.d(TAG, "handleKeyguardReset");
|
||||
updateFingerprintListeningState();
|
||||
mUserUnlocked = mUserManager.isUserUnlocked(getCurrentUser());
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -234,7 +234,6 @@ public class KeyguardBouncer {
|
||||
mKeyguardView.setViewMediatorCallback(mCallback);
|
||||
mContainer.addView(mRoot, mContainer.getChildCount());
|
||||
mRoot.setVisibility(View.INVISIBLE);
|
||||
mRoot.setSystemUiVisibility(View.STATUS_BAR_DISABLE_HOME);
|
||||
}
|
||||
|
||||
protected void removeView() {
|
||||
|
||||
@@ -30,6 +30,7 @@ import android.view.animation.DecelerateInterpolator;
|
||||
import android.view.animation.Interpolator;
|
||||
import android.view.animation.PathInterpolator;
|
||||
|
||||
import com.android.keyguard.KeyguardUpdateMonitor;
|
||||
import com.android.systemui.R;
|
||||
import com.android.systemui.statusbar.ExpandableNotificationRow;
|
||||
import com.android.systemui.statusbar.NotificationData;
|
||||
@@ -46,10 +47,13 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener,
|
||||
public static final long ANIMATION_DURATION = 220;
|
||||
public static final Interpolator KEYGUARD_FADE_OUT_INTERPOLATOR
|
||||
= new PathInterpolator(0f, 0, 0.7f, 1f);
|
||||
public static final Interpolator KEYGUARD_FADE_OUT_INTERPOLATOR_LOCKED
|
||||
= new PathInterpolator(0.3f, 0f, 0.8f, 1f);
|
||||
private static final float SCRIM_BEHIND_ALPHA = 0.62f;
|
||||
private static final float SCRIM_BEHIND_ALPHA_KEYGUARD = 0.45f;
|
||||
private static final float SCRIM_BEHIND_ALPHA_UNLOCKING = 0.2f;
|
||||
private static final float SCRIM_IN_FRONT_ALPHA = 0.75f;
|
||||
private static final float SCRIM_IN_FRONT_ALPHA_LOCKED = 0.85f;
|
||||
private static final int TAG_KEY_ANIM = R.id.scrim;
|
||||
private static final int TAG_KEY_ANIM_TARGET = R.id.scrim_target;
|
||||
private static final int TAG_START_ALPHA = R.id.scrim_alpha_start;
|
||||
@@ -59,6 +63,7 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener,
|
||||
private final ScrimView mScrimInFront;
|
||||
private final UnlockMethodCache mUnlockMethodCache;
|
||||
private final View mHeadsUpScrim;
|
||||
private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
|
||||
|
||||
private float mScrimBehindAlpha = SCRIM_BEHIND_ALPHA;
|
||||
private float mScrimBehindAlphaKeyguard = SCRIM_BEHIND_ALPHA_KEYGUARD;
|
||||
@@ -99,6 +104,7 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener,
|
||||
mHeadsUpScrim = headsUpScrim;
|
||||
final Context context = scrimBehind.getContext();
|
||||
mUnlockMethodCache = UnlockMethodCache.getInstance(context);
|
||||
mKeyguardUpdateMonitor = KeyguardUpdateMonitor.getInstance(context);
|
||||
updateHeadsUpScrim(false);
|
||||
}
|
||||
|
||||
@@ -162,11 +168,19 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener,
|
||||
mAnimateChange = true;
|
||||
mSkipFirstFrame = skipFirstFrame;
|
||||
mOnAnimationFinished = onAnimationFinished;
|
||||
scheduleUpdate();
|
||||
|
||||
// No need to wait for the next frame to be drawn for this case - onPreDraw will execute
|
||||
// the changes we just scheduled.
|
||||
onPreDraw();
|
||||
if (mKeyguardUpdateMonitor.isUserUnlocked()) {
|
||||
scheduleUpdate();
|
||||
|
||||
// No need to wait for the next frame to be drawn for this case - onPreDraw will execute
|
||||
// the changes we just scheduled.
|
||||
onPreDraw();
|
||||
} else {
|
||||
|
||||
// In case the user isn't unlocked, make sure to delay a bit because the system is hosed
|
||||
// with too many things in this case, in order to not skip the initial frames.
|
||||
mScrimInFront.postOnAnimationDelayed(this::scheduleUpdate, 16);
|
||||
}
|
||||
}
|
||||
|
||||
public void abortKeyguardFadingOut() {
|
||||
@@ -211,6 +225,11 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener,
|
||||
return mDozeInFrontAlpha;
|
||||
}
|
||||
|
||||
private float getScrimInFrontAlpha() {
|
||||
return mKeyguardUpdateMonitor.isUserUnlocked()
|
||||
? SCRIM_IN_FRONT_ALPHA
|
||||
: SCRIM_IN_FRONT_ALPHA_LOCKED;
|
||||
}
|
||||
private void scheduleUpdate() {
|
||||
if (mUpdatePending) return;
|
||||
|
||||
@@ -250,10 +269,10 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener,
|
||||
float fraction = 1 - behindFraction;
|
||||
fraction = (float) Math.pow(fraction, 0.8f);
|
||||
behindFraction = (float) Math.pow(behindFraction, 0.8f);
|
||||
setScrimInFrontColor(fraction * SCRIM_IN_FRONT_ALPHA);
|
||||
setScrimInFrontColor(fraction * getScrimInFrontAlpha());
|
||||
setScrimBehindColor(behindFraction * mScrimBehindAlphaKeyguard);
|
||||
} else if (mBouncerShowing) {
|
||||
setScrimInFrontColor(SCRIM_IN_FRONT_ALPHA);
|
||||
setScrimInFrontColor(getScrimInFrontAlpha());
|
||||
setScrimBehindColor(0f);
|
||||
} else {
|
||||
float fraction = Math.max(0, Math.min(mFraction, 1));
|
||||
@@ -371,7 +390,13 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener,
|
||||
}
|
||||
|
||||
private Interpolator getInterpolator() {
|
||||
return mAnimateKeyguardFadingOut ? KEYGUARD_FADE_OUT_INTERPOLATOR : mInterpolator;
|
||||
if (mAnimateKeyguardFadingOut && !mKeyguardUpdateMonitor.isUserUnlocked()) {
|
||||
return KEYGUARD_FADE_OUT_INTERPOLATOR_LOCKED;
|
||||
} else if (mAnimateKeyguardFadingOut) {
|
||||
return KEYGUARD_FADE_OUT_INTERPOLATOR;
|
||||
} else {
|
||||
return mInterpolator;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -53,6 +53,11 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
|
||||
|
||||
private static final long WAKE_AND_UNLOCK_SCRIM_FADEOUT_DURATION_MS = 200;
|
||||
|
||||
// Duration of the Keyguard dismissal animation in case the user is currently locked. This is to
|
||||
// make everything a bit slower to bridge a gap until the user is unlocked and home screen has
|
||||
// dranw its first frame.
|
||||
private static final long KEYGUARD_DISMISS_DURATION_LOCKED = 2000;
|
||||
|
||||
private static String TAG = "StatusBarKeyguardViewManager";
|
||||
|
||||
protected final Context mContext;
|
||||
@@ -274,9 +279,12 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
|
||||
/**
|
||||
* Hides the keyguard view
|
||||
*/
|
||||
public void hide(long startTime, final long fadeoutDuration) {
|
||||
public void hide(long startTime, long fadeoutDuration) {
|
||||
mShowing = false;
|
||||
|
||||
if (!KeyguardUpdateMonitor.getInstance(mContext).isUserUnlocked()) {
|
||||
fadeoutDuration = KEYGUARD_DISMISS_DURATION_LOCKED;
|
||||
}
|
||||
long uptimeMillis = SystemClock.uptimeMillis();
|
||||
long delay = Math.max(0, startTime + HIDE_TIMING_CORRECTION_MS - uptimeMillis);
|
||||
|
||||
|
||||
@@ -69,6 +69,7 @@ import android.util.Log;
|
||||
import android.util.Slog;
|
||||
|
||||
import com.android.internal.util.ArrayUtils;
|
||||
import com.android.internal.widget.ICheckCredentialProgressCallback;
|
||||
import com.android.internal.widget.ILockSettings;
|
||||
import com.android.internal.widget.LockPatternUtils;
|
||||
import com.android.internal.widget.VerifyCredentialResponse;
|
||||
@@ -760,7 +761,7 @@ public class LockSettingsService extends ILockSettings.Stub {
|
||||
private void unlockChildProfile(int profileHandle) throws RemoteException {
|
||||
try {
|
||||
doVerifyPassword(getDecryptedPasswordForTiedProfile(profileHandle), false,
|
||||
0 /* no challenge */, profileHandle);
|
||||
0 /* no challenge */, profileHandle, null /* progressCallback */);
|
||||
} catch (UnrecoverableKeyException | InvalidKeyException | KeyStoreException
|
||||
| NoSuchAlgorithmException | NoSuchPaddingException
|
||||
| InvalidAlgorithmParameterException | IllegalBlockSizeException
|
||||
@@ -947,7 +948,7 @@ public class LockSettingsService extends ILockSettings.Stub {
|
||||
CredentialHash willStore
|
||||
= new CredentialHash(enrolledHandle, CredentialHash.VERSION_GATEKEEPER);
|
||||
setUserKeyProtection(userId, pattern,
|
||||
doVerifyPattern(pattern, willStore, true, 0, userId));
|
||||
doVerifyPattern(pattern, willStore, true, 0, userId, null /* progressCallback */));
|
||||
mStorage.writePatternHash(enrolledHandle, userId);
|
||||
fixateNewestUserKeyAuth(userId);
|
||||
onUserLockChanged(userId);
|
||||
@@ -1007,7 +1008,8 @@ public class LockSettingsService extends ILockSettings.Stub {
|
||||
CredentialHash willStore
|
||||
= new CredentialHash(enrolledHandle, CredentialHash.VERSION_GATEKEEPER);
|
||||
setUserKeyProtection(userId, password,
|
||||
doVerifyPassword(password, willStore, true, 0, userId));
|
||||
doVerifyPassword(password, willStore, true, 0, userId,
|
||||
null /* progressCallback */));
|
||||
mStorage.writePasswordHash(enrolledHandle, userId);
|
||||
fixateNewestUserKeyAuth(userId);
|
||||
onUserLockChanged(userId);
|
||||
@@ -1205,25 +1207,29 @@ public class LockSettingsService extends ILockSettings.Stub {
|
||||
}
|
||||
|
||||
@Override
|
||||
public VerifyCredentialResponse checkPattern(String pattern, int userId) throws RemoteException {
|
||||
return doVerifyPattern(pattern, false, 0, userId);
|
||||
public VerifyCredentialResponse checkPattern(String pattern, int userId,
|
||||
ICheckCredentialProgressCallback progressCallback) throws RemoteException {
|
||||
return doVerifyPattern(pattern, false, 0, userId, progressCallback);
|
||||
}
|
||||
|
||||
@Override
|
||||
public VerifyCredentialResponse verifyPattern(String pattern, long challenge, int userId)
|
||||
throws RemoteException {
|
||||
return doVerifyPattern(pattern, true, challenge, userId);
|
||||
return doVerifyPattern(pattern, true, challenge, userId, null /* progressCallback */);
|
||||
}
|
||||
|
||||
private VerifyCredentialResponse doVerifyPattern(String pattern, boolean hasChallenge,
|
||||
long challenge, int userId) throws RemoteException {
|
||||
long challenge, int userId, ICheckCredentialProgressCallback progressCallback)
|
||||
throws RemoteException {
|
||||
checkPasswordReadPermission(userId);
|
||||
CredentialHash storedHash = mStorage.readPatternHash(userId);
|
||||
return doVerifyPattern(pattern, storedHash, hasChallenge, challenge, userId);
|
||||
return doVerifyPattern(pattern, storedHash, hasChallenge, challenge, userId,
|
||||
progressCallback);
|
||||
}
|
||||
|
||||
private VerifyCredentialResponse doVerifyPattern(String pattern, CredentialHash storedHash,
|
||||
boolean hasChallenge, long challenge, int userId) throws RemoteException {
|
||||
boolean hasChallenge, long challenge, int userId,
|
||||
ICheckCredentialProgressCallback progressCallback) throws RemoteException {
|
||||
boolean shouldReEnrollBaseZero = storedHash != null && storedHash.isBaseZeroPattern;
|
||||
|
||||
String patternToVerify;
|
||||
@@ -1252,7 +1258,8 @@ public class LockSettingsService extends ILockSettings.Stub {
|
||||
public String adjustForKeystore(String pattern) {
|
||||
return LockPatternUtils.patternStringToBaseZero(pattern);
|
||||
}
|
||||
}
|
||||
},
|
||||
progressCallback
|
||||
);
|
||||
|
||||
if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK
|
||||
@@ -1264,15 +1271,15 @@ public class LockSettingsService extends ILockSettings.Stub {
|
||||
}
|
||||
|
||||
@Override
|
||||
public VerifyCredentialResponse checkPassword(String password, int userId)
|
||||
throws RemoteException {
|
||||
return doVerifyPassword(password, false, 0, userId);
|
||||
public VerifyCredentialResponse checkPassword(String password, int userId,
|
||||
ICheckCredentialProgressCallback progressCallback) throws RemoteException {
|
||||
return doVerifyPassword(password, false, 0, userId, progressCallback);
|
||||
}
|
||||
|
||||
@Override
|
||||
public VerifyCredentialResponse verifyPassword(String password, long challenge, int userId)
|
||||
throws RemoteException {
|
||||
return doVerifyPassword(password, true, challenge, userId);
|
||||
return doVerifyPassword(password, true, challenge, userId, null /* progressCallback */);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1285,8 +1292,10 @@ public class LockSettingsService extends ILockSettings.Stub {
|
||||
final int parentProfileId = mUserManager.getProfileParent(userId).id;
|
||||
// Unlock parent by using parent's challenge
|
||||
final VerifyCredentialResponse parentResponse = isPattern
|
||||
? doVerifyPattern(password, true, challenge, parentProfileId)
|
||||
: doVerifyPassword(password, true, challenge, parentProfileId);
|
||||
? doVerifyPattern(password, true, challenge, parentProfileId,
|
||||
null /* progressCallback */)
|
||||
: doVerifyPassword(password, true, challenge, parentProfileId,
|
||||
null /* progressCallback */);
|
||||
if (parentResponse.getResponseCode() != VerifyCredentialResponse.RESPONSE_OK) {
|
||||
// Failed, just return parent's response
|
||||
return parentResponse;
|
||||
@@ -1296,7 +1305,7 @@ public class LockSettingsService extends ILockSettings.Stub {
|
||||
// Unlock work profile, and work profile with unified lock must use password only
|
||||
return doVerifyPassword(getDecryptedPasswordForTiedProfile(userId), true,
|
||||
challenge,
|
||||
userId);
|
||||
userId, null /* progressCallback */);
|
||||
} catch (UnrecoverableKeyException | InvalidKeyException | KeyStoreException
|
||||
| NoSuchAlgorithmException | NoSuchPaddingException
|
||||
| InvalidAlgorithmParameterException | IllegalBlockSizeException
|
||||
@@ -1307,14 +1316,17 @@ public class LockSettingsService extends ILockSettings.Stub {
|
||||
}
|
||||
|
||||
private VerifyCredentialResponse doVerifyPassword(String password, boolean hasChallenge,
|
||||
long challenge, int userId) throws RemoteException {
|
||||
long challenge, int userId, ICheckCredentialProgressCallback progressCallback)
|
||||
throws RemoteException {
|
||||
checkPasswordReadPermission(userId);
|
||||
CredentialHash storedHash = mStorage.readPasswordHash(userId);
|
||||
return doVerifyPassword(password, storedHash, hasChallenge, challenge, userId);
|
||||
return doVerifyPassword(password, storedHash, hasChallenge, challenge, userId,
|
||||
progressCallback);
|
||||
}
|
||||
|
||||
private VerifyCredentialResponse doVerifyPassword(String password, CredentialHash storedHash,
|
||||
boolean hasChallenge, long challenge, int userId) throws RemoteException {
|
||||
boolean hasChallenge, long challenge, int userId,
|
||||
ICheckCredentialProgressCallback progressCallback) throws RemoteException {
|
||||
return verifyCredential(userId, storedHash, password, hasChallenge, challenge,
|
||||
new CredentialUtil() {
|
||||
@Override
|
||||
@@ -1332,12 +1344,12 @@ public class LockSettingsService extends ILockSettings.Stub {
|
||||
public String adjustForKeystore(String password) {
|
||||
return password;
|
||||
}
|
||||
}
|
||||
);
|
||||
}, progressCallback);
|
||||
}
|
||||
|
||||
private VerifyCredentialResponse verifyCredential(int userId, CredentialHash storedHash,
|
||||
String credential, boolean hasChallenge, long challenge, CredentialUtil credentialUtil)
|
||||
String credential, boolean hasChallenge, long challenge, CredentialUtil credentialUtil,
|
||||
ICheckCredentialProgressCallback progressCallback)
|
||||
throws RemoteException {
|
||||
if ((storedHash == null || storedHash.hash.length == 0) && TextUtils.isEmpty(credential)) {
|
||||
// don't need to pass empty credentials to GateKeeper
|
||||
@@ -1395,6 +1407,10 @@ public class LockSettingsService extends ILockSettings.Stub {
|
||||
|
||||
if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK) {
|
||||
// credential has matched
|
||||
|
||||
if (progressCallback != null) {
|
||||
progressCallback.onCredentialVerified();
|
||||
}
|
||||
unlockKeystore(credential, userId);
|
||||
|
||||
Slog.i(TAG, "Unlocking user " + userId +
|
||||
@@ -1450,7 +1466,7 @@ public class LockSettingsService extends ILockSettings.Stub {
|
||||
|
||||
try {
|
||||
if (mLockPatternUtils.isLockPatternEnabled(userId)) {
|
||||
if (checkPattern(password, userId).getResponseCode()
|
||||
if (checkPattern(password, userId, null /* progressCallback */).getResponseCode()
|
||||
== GateKeeperResponse.RESPONSE_OK) {
|
||||
return true;
|
||||
}
|
||||
@@ -1460,7 +1476,7 @@ public class LockSettingsService extends ILockSettings.Stub {
|
||||
|
||||
try {
|
||||
if (mLockPatternUtils.isLockPasswordEnabled(userId)) {
|
||||
if (checkPassword(password, userId).getResponseCode()
|
||||
if (checkPassword(password, userId, null /* progressCallback */).getResponseCode()
|
||||
== GateKeeperResponse.RESPONSE_OK) {
|
||||
return true;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user