diff options
15 files changed, 269 insertions, 60 deletions
diff --git a/packages/Keyguard/res/values/strings.xml b/packages/Keyguard/res/values/strings.xml index e835536..df221fa 100644 --- a/packages/Keyguard/res/values/strings.xml +++ b/packages/Keyguard/res/values/strings.xml @@ -303,4 +303,7 @@ <!-- Description of airplane mode --> <string name="airplane_mode">Airplane mode</string> + <!-- Fingerprint hint message when finger was not recognized.--> + <string name="fingerprint_not_recognized">Not recognized</string> + </resources> diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java index 82dec30..5a4d5cd 100644 --- a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java +++ b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java @@ -149,6 +149,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { private boolean mScreenOn; private SubscriptionManager mSubscriptionManager; private List<SubscriptionInfo> mSubscriptionInfo; + private boolean mFingerprintDetectionRunning; private final Handler mHandler = new Handler() { @Override @@ -332,27 +333,35 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { } private void handleFingerprintAuthenticated(int fingerId, int groupId) { - if (fingerId == 0) return; // not a valid fingerprint - - final int userId; - try { - userId = ActivityManagerNative.getDefault().getCurrentUser().id; - } catch (RemoteException e) { - Log.e(TAG, "Failed to get current user id: ", e); + if (fingerId == 0) { + // not a valid fingerprint + handleFingerprintHelp(-1, mContext.getString(R.string.fingerprint_not_recognized)); return; } - if (isFingerprintDisabled(userId)) { - Log.d(TAG, "Fingerprint disabled by DPM for userId: " + userId); - return; - } - final ContentResolver res = mContext.getContentResolver(); - final int ids[] = FingerprintUtils.getFingerprintIdsForUser(res, userId); - for (int i = 0; i < ids.length; i++) { - // TODO: fix once HAL supports storing group id - final boolean isCorrectUser = true || (groupId == userId); - if (ids[i] == fingerId && isCorrectUser) { - onFingerprintAuthenticated(userId); + + try { + final int userId; + try { + userId = ActivityManagerNative.getDefault().getCurrentUser().id; + } catch (RemoteException e) { + Log.e(TAG, "Failed to get current user id: ", e); + return; + } + if (isFingerprintDisabled(userId)) { + Log.d(TAG, "Fingerprint disabled by DPM for userId: " + userId); + return; + } + final ContentResolver res = mContext.getContentResolver(); + final int ids[] = FingerprintUtils.getFingerprintIdsForUser(res, userId); + for (int i = 0; i < ids.length; i++) { + // TODO: fix once HAL supports storing group id + final boolean isCorrectUser = true || (groupId == userId); + if (ids[i] == fingerId && isCorrectUser) { + onFingerprintAuthenticated(userId); + } } + } finally { + setFingerprintRunningDetectionRunning(false); } } @@ -366,6 +375,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { } private void handleFingerprintError(int msgId, String errString) { + setFingerprintRunningDetectionRunning(false); for (int i = 0; i < mCallbacks.size(); i++) { KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get(); if (cb != null) { @@ -374,6 +384,21 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { } } + private void setFingerprintRunningDetectionRunning(boolean running) { + if (running != mFingerprintDetectionRunning) { + mFingerprintDetectionRunning = running; + notifyFingerprintRunningStateChanged(); + } + } + + private void notifyFingerprintRunningStateChanged() { + for (int i = 0; i < mCallbacks.size(); i++) { + KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get(); + if (cb != null) { + cb.onFingerprintRunningStateChanged(mFingerprintDetectionRunning); + } + } + } private void handleFaceUnlockStateChanged(boolean running, int userId) { mUserFaceUnlockRunning.put(userId, running); for (int i = 0; i < mCallbacks.size(); i++) { @@ -388,6 +413,10 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { return mUserFaceUnlockRunning.get(userId); } + public boolean isFingerprintDetectionRunning() { + return mFingerprintDetectionRunning; + } + private boolean isTrustDisabled(int userId) { // Don't allow trust agent if device is secured with a SIM PIN. This is here // mainly because there's no other way to prompt the user to enter their SIM PIN @@ -736,13 +765,15 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { } private void startListeningForFingerprint(Context context) { - if (mFpm != null && mFpm.isHardwareDetected()) { + if (mFpm != null && mFpm.isHardwareDetected() + && mFpm.getEnrolledFingerprints().size() > 0) { if (mFingerprintCancelSignal == null) { mFingerprintCancelSignal = new CancellationSignal(); } else { mFingerprintCancelSignal.cancel(); } mFpm.authenticate(null, mAuthenticationCallback, mFingerprintCancelSignal, 0); + setFingerprintRunningDetectionRunning(true); } } @@ -750,6 +781,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { if (mFingerprintCancelSignal != null) { mFingerprintCancelSignal.cancel(); } + setFingerprintRunningDetectionRunning(false); } private boolean isDeviceProvisionedInSettingsDb() { diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java index 8d2562d..756a7a4 100644 --- a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java +++ b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java @@ -200,4 +200,9 @@ public class KeyguardUpdateMonitorCallback { * Called when the state of face unlock changed. */ public void onFaceUnlockStateChanged(boolean running, int userId) { } + + /** + * Called when the fingerprint running state changed. + */ + public void onFingerprintRunningStateChanged(boolean running) { } } diff --git a/packages/SystemUI/res/drawable/ic_fingerprint.xml b/packages/SystemUI/res/drawable/ic_fingerprint.xml new file mode 100644 index 0000000..ee2cf03 --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_fingerprint.xml @@ -0,0 +1,36 @@ +<!-- + ~ Copyright (C) 2015 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 + --> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="32.0dp" + android:height="32.0dp" + android:viewportWidth="32.0" + android:viewportHeight="32.0"> + <path + android:fillColor="#80ffffff" + android:pathData="M23.7,5.9c-0.1,0.0 -0.2,0.0 -0.3,-0.1C21.0,4.5 18.6,3.9 16.0,3.9c-2.5,0.0 -4.6,0.6 -6.9,1.9C8.8,6.0 8.3,5.9 8.1,5.5C7.9,5.2 8.0,4.7 8.4,4.5c2.5,-1.4 4.9,-2.1 7.7,-2.1c2.8,0.0 5.4,0.7 8.0,2.1c0.4,0.2 0.5,0.6 0.3,1.0C24.2,5.7 24.0,5.9 23.7,5.9z"/> + <path + android:fillColor="#80ffffff" + android:pathData="M5.3,13.2c-0.1,0.0 -0.3,0.0 -0.4,-0.1c-0.3,-0.2 -0.4,-0.7 -0.2,-1.0c1.3,-1.9 2.9,-3.4 4.9,-4.5c4.1,-2.2 9.3,-2.2 13.4,0.0c1.9,1.1 3.6,2.5 4.9,4.4c0.2,0.3 0.1,0.8 -0.2,1.0c-0.3,0.2 -0.8,0.1 -1.0,-0.2c-1.2,-1.7 -2.6,-3.0 -4.3,-4.0c-3.7,-2.0 -8.3,-2.0 -12.0,0.0c-1.7,0.9 -3.2,2.3 -4.3,4.0C5.7,13.1 5.5,13.2 5.3,13.2z"/> + <path + android:fillColor="#80ffffff" + android:pathData="M13.3,29.6c-0.2,0.0 -0.4,-0.1 -0.5,-0.2c-1.1,-1.2 -1.7,-2.0 -2.6,-3.6c-0.9,-1.7 -1.4,-3.7 -1.4,-5.9c0.0,-4.1 3.3,-7.4 7.4,-7.4c4.1,0.0 7.4,3.3 7.4,7.4c0.0,0.4 -0.3,0.7 -0.7,0.7s-0.7,-0.3 -0.7,-0.7c0.0,-3.3 -2.7,-5.9 -5.9,-5.9c-3.3,0.0 -5.9,2.7 -5.9,5.9c0.0,2.0 0.4,3.8 1.2,5.2c0.8,1.6 1.4,2.2 2.4,3.3c0.3,0.3 0.3,0.8 0.0,1.0C13.7,29.5 13.5,29.6 13.3,29.6z"/> + <path + android:fillColor="#80ffffff" + android:pathData="M22.6,27.1c-1.6,0.0 -2.9,-0.4 -4.1,-1.2c-1.9,-1.4 -3.1,-3.6 -3.1,-6.0c0.0,-0.4 0.3,-0.7 0.7,-0.7s0.7,0.3 0.7,0.7c0.0,1.9 0.9,3.7 2.5,4.8c0.9,0.6 1.9,1.0 3.2,1.0c0.3,0.0 0.8,0.0 1.3,-0.1c0.4,-0.1 0.8,0.2 0.8,0.6c0.1,0.4 -0.2,0.8 -0.6,0.8C23.4,27.1 22.8,27.1 22.6,27.1z"/> + <path + android:fillColor="#80ffffff" + android:pathData="M20.0,29.9c-0.1,0.0 -0.1,0.0 -0.2,0.0c-2.1,-0.6 -3.4,-1.4 -4.8,-2.9c-1.8,-1.9 -2.8,-4.4 -2.8,-7.1c0.0,-2.2 1.8,-4.1 4.1,-4.1c2.2,0.0 4.1,1.8 4.1,4.1c0.0,1.4 1.2,2.6 2.6,2.6c1.4,0.0 2.6,-1.2 2.6,-2.6c0.0,-5.1 -4.2,-9.3 -9.3,-9.3c-3.6,0.0 -6.9,2.1 -8.4,5.4C7.3,17.1 7.0,18.4 7.0,19.8c0.0,1.1 0.1,2.7 0.9,4.9c0.1,0.4 -0.1,0.8 -0.4,0.9c-0.4,0.1 -0.8,-0.1 -0.9,-0.4c-0.6,-1.8 -0.9,-3.6 -0.9,-5.4c0.0,-1.6 0.3,-3.1 0.9,-4.4c1.7,-3.8 5.6,-6.3 9.8,-6.3c5.9,0.0 10.7,4.8 10.7,10.7c0.0,2.2 -1.8,4.1 -4.1,4.1s-4.0,-1.8 -4.0,-4.1c0.0,-1.4 -1.2,-2.6 -2.6,-2.6c-1.4,0.0 -2.6,1.2 -2.6,2.6c0.0,2.3 0.9,4.5 2.4,6.1c1.2,1.3 2.4,2.0 4.2,2.5c0.4,0.1 0.6,0.5 0.5,0.9C20.6,29.7 20.3,29.9 20.0,29.9z"/> +</vector> diff --git a/packages/SystemUI/res/drawable/ic_fingerprint_error.xml b/packages/SystemUI/res/drawable/ic_fingerprint_error.xml new file mode 100644 index 0000000..11e83a1 --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_fingerprint_error.xml @@ -0,0 +1,30 @@ +<!-- +Copyright (C) 2015 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. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="32.0dp" + android:height="32.0dp" + android:viewportWidth="32.0" + android:viewportHeight="32.0"> + <path + android:fillColor="@color/system_warning_color" + android:pathData="M15.99,2.5C8.53,2.5 2.5,8.54 2.5,16.0s6.03,13.5 13.49,13.5S29.5,23.46 29.5,16.0S23.45,2.5 15.99,2.5zM16.0,26.8c-5.97,0.0 -10.8,-4.83 -10.8,-10.8S10.03,5.2 16.0,5.2S26.8,10.03 26.8,16.0S21.97,26.8 16.0,26.8z"/> + <path + android:fillColor="@color/system_warning_color" + android:pathData="M14.65,20.05l2.7,0.0l0.0,2.7l-2.7,0.0z"/> + <path + android:fillColor="@color/system_warning_color" + android:pathData="M14.65,9.25l2.7,0.0l0.0,8.1l-2.7,0.0z"/> +</vector> diff --git a/packages/SystemUI/res/layout/keyguard_bottom_area.xml b/packages/SystemUI/res/layout/keyguard_bottom_area.xml index 01b2713..fca8231 100644 --- a/packages/SystemUI/res/layout/keyguard_bottom_area.xml +++ b/packages/SystemUI/res/layout/keyguard_bottom_area.xml @@ -68,7 +68,6 @@ android:layout_gravity="bottom|center_horizontal" android:src="@drawable/ic_lock_24dp" android:scaleType="center" - android:tint="#ffffffff" android:contentDescription="@string/accessibility_unlock_button" /> </com.android.systemui.statusbar.phone.KeyguardBottomAreaView> diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml index c9e1fee..b6ff1ce 100644 --- a/packages/SystemUI/res/values/dimens.xml +++ b/packages/SystemUI/res/values/dimens.xml @@ -573,4 +573,7 @@ <!-- Screen pinning inner nav bar outer circle size --> <dimen name="screen_pinning_nav_highlight_outer_size">84dp</dimen> + <!-- Padding to be used on the bottom of the fingerprint icon on Keyguard so it better aligns + with the other icons. --> + <dimen name="fingerprint_icon_additional_padding">12dp</dimen> </resources> diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java index f75dd73..d2837b7 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java @@ -1628,7 +1628,7 @@ public abstract class BaseStatusBar extends SystemUI implements // close the shade if it was open animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL, - true /* force */); + true /* force */, true /* delayed */); visibilityChanged(false); return mIntent != null && mIntent.isActivity(); @@ -1640,6 +1640,9 @@ public abstract class BaseStatusBar extends SystemUI implements public void animateCollapsePanels(int flags, boolean force) { } + public void animateCollapsePanels(int flags, boolean force, boolean delayed) { + } + public void overrideActivityPendingAppTransition(boolean keyguardShowing) { if (keyguardShowing) { try { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardAffordanceView.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardAffordanceView.java index e2464c2..583184f 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardAffordanceView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardAffordanceView.java @@ -34,6 +34,7 @@ import android.view.animation.AnimationUtils; import android.view.animation.Interpolator; import android.widget.ImageView; import com.android.systemui.R; +import com.android.systemui.statusbar.phone.KeyguardAffordanceHelper; /** * An ImageView which does not have overlapping renderings commands and therefore does not need a @@ -75,6 +76,7 @@ public class KeyguardAffordanceView extends ImageView { private float mCircleStartRadius; private float mMaxCircleSize; private Animator mPreviewClipper; + private float mRestingAlpha = KeyguardAffordanceHelper.SWIPE_RESTING_ALPHA_AMOUNT; private AnimatorListenerAdapter mClipEndListener = new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { @@ -394,6 +396,17 @@ public class KeyguardAffordanceView extends ImageView { } } + public void setRestingAlpha(float alpha) { + mRestingAlpha = alpha; + + // TODO: Handle the case an animation is playing. + setImageAlpha(alpha, false); + } + + public float getRestingAlpha() { + return mRestingAlpha; + } + public void setImageAlpha(float alpha, boolean animate) { setImageAlpha(alpha, animate, -1, null, null); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java index 58067c3..07a055c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java @@ -26,6 +26,7 @@ import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; +import android.graphics.Color; import android.os.BatteryManager; import android.os.BatteryStats; import android.os.Handler; @@ -53,6 +54,7 @@ public class KeyguardIndicationController { private String mRestingIndication; private String mTransientIndication; + private int mTransientTextColor; private boolean mVisible; private boolean mPowerPluggedIn; @@ -105,7 +107,15 @@ public class KeyguardIndicationController { * Shows {@param transientIndication} until it is hidden by {@link #hideTransientIndication}. */ public void showTransientIndication(String transientIndication) { + showTransientIndication(transientIndication, Color.WHITE); + } + + /** + * Shows {@param transientIndication} until it is hidden by {@link #hideTransientIndication}. + */ + public void showTransientIndication(String transientIndication, int textColor) { mTransientIndication = transientIndication; + mTransientTextColor = textColor; mHandler.removeMessages(MSG_HIDE_TRANSIENT); updateIndication(); } @@ -124,7 +134,15 @@ public class KeyguardIndicationController { private void updateIndication() { if (mVisible) { mTextView.switchIndication(computeIndication()); + mTextView.setTextColor(computeColor()); + } + } + + private int computeColor() { + if (!TextUtils.isEmpty(mTransientIndication)) { + return mTransientTextColor; } + return Color.WHITE; } private String computeIndication() { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardAffordanceHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardAffordanceHelper.java index cab152f..9d892f6 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardAffordanceHelper.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardAffordanceHelper.java @@ -83,9 +83,9 @@ public class KeyguardAffordanceHelper { mContext = context; mCallback = callback; initIcons(); - updateIcon(mLeftIcon, 0.0f, SWIPE_RESTING_ALPHA_AMOUNT, false, false); - updateIcon(mCenterIcon, 0.0f, SWIPE_RESTING_ALPHA_AMOUNT, false, false); - updateIcon(mRightIcon, 0.0f, SWIPE_RESTING_ALPHA_AMOUNT, false, false); + updateIcon(mLeftIcon, 0.0f, mLeftIcon.getRestingAlpha(), false, false); + updateIcon(mCenterIcon, 0.0f, mCenterIcon.getRestingAlpha(), false, false); + updateIcon(mRightIcon, 0.0f, mRightIcon.getRestingAlpha(), false, false); initDimens(); } @@ -344,22 +344,23 @@ public class KeyguardAffordanceHelper { float alpha = absTranslation / getMinTranslationAmount(); // We interpolate the alpha of the other icons to 0 - float fadeOutAlpha = SWIPE_RESTING_ALPHA_AMOUNT * (1.0f - alpha); - fadeOutAlpha = Math.max(0.0f, fadeOutAlpha); - - // We interpolate the alpha of the targetView to 1 - alpha = fadeOutAlpha + alpha; + float fadeOutAlpha = 1.0f - alpha; + fadeOutAlpha = Math.min(1.0f, Math.max(0.0f, fadeOutAlpha)); boolean animateIcons = isReset && animateReset; float radius = getRadiusFromTranslation(absTranslation); boolean slowAnimation = isReset && isBelowFalsingThreshold(); if (!isReset) { - updateIcon(targetView, radius, alpha, false, false); + updateIcon(targetView, radius, alpha + fadeOutAlpha * targetView.getRestingAlpha(), + false, false); } else { - updateIcon(targetView, 0.0f, fadeOutAlpha, animateIcons, slowAnimation); + updateIcon(targetView, 0.0f, fadeOutAlpha * targetView.getRestingAlpha(), + animateIcons, slowAnimation); } - updateIcon(otherView, 0.0f, fadeOutAlpha, animateIcons, slowAnimation); - updateIcon(mCenterIcon, 0.0f, fadeOutAlpha, animateIcons, slowAnimation); + updateIcon(otherView, 0.0f, fadeOutAlpha * otherView.getRestingAlpha(), + animateIcons, slowAnimation); + updateIcon(mCenterIcon, 0.0f, fadeOutAlpha * mCenterIcon.getRestingAlpha(), + animateIcons, slowAnimation); mTranslation = translation; } @@ -369,15 +370,14 @@ public class KeyguardAffordanceHelper { float alpha = newRadius / mMinBackgroundRadius; // We interpolate the alpha of the other icons to 0 - float fadeOutAlpha = SWIPE_RESTING_ALPHA_AMOUNT * (1.0f - alpha); + float fadeOutAlpha = 1.0f - alpha; fadeOutAlpha = Math.max(0.0f, fadeOutAlpha); // We interpolate the alpha of the targetView to 1 - alpha = fadeOutAlpha + alpha; KeyguardAffordanceView otherView = targetView == mRightIcon ? mLeftIcon : mRightIcon; - updateIconAlpha(targetView, alpha, false); - updateIconAlpha(otherView, fadeOutAlpha, false); - updateIconAlpha(mCenterIcon, fadeOutAlpha, false); + updateIconAlpha(targetView, alpha + fadeOutAlpha * targetView.getRestingAlpha(), false); + updateIconAlpha(otherView, fadeOutAlpha * otherView.getRestingAlpha(), false); + updateIconAlpha(mCenterIcon, fadeOutAlpha * mCenterIcon.getRestingAlpha(), false); } private float getTranslationFromRadius(float circleSize) { @@ -404,14 +404,14 @@ public class KeyguardAffordanceHelper { } private void updateIconAlpha(KeyguardAffordanceView view, float alpha, boolean animate) { - float scale = getScale(alpha); + float scale = getScale(alpha, view); alpha = Math.min(1.0f, alpha); view.setImageAlpha(alpha, animate); view.setImageScale(scale, animate); } - private float getScale(float alpha) { - float scale = alpha / SWIPE_RESTING_ALPHA_AMOUNT * 0.2f + + private float getScale(float alpha, KeyguardAffordanceView icon) { + float scale = alpha / icon.getRestingAlpha() * 0.2f + KeyguardAffordanceView.MIN_ICON_SCALE_AMOUNT; return Math.min(scale, KeyguardAffordanceView.MAX_ICON_SCALE_AMOUNT); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java index 628ae84..410a7e4 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java @@ -25,13 +25,16 @@ import android.content.IntentFilter; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.content.res.Configuration; +import android.content.res.Resources; import android.graphics.drawable.Drawable; import android.graphics.drawable.InsetDrawable; import android.os.AsyncTask; import android.os.Bundle; import android.os.RemoteException; import android.os.UserHandle; +import android.os.Vibrator; import android.provider.MediaStore; +import android.provider.Settings; import android.telecom.TelecomManager; import android.util.AttributeSet; import android.util.Log; @@ -78,6 +81,9 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL private static final Intent PHONE_INTENT = new Intent(Intent.ACTION_DIAL); private static final int DOZE_ANIMATION_STAGGER_DELAY = 48; private static final int DOZE_ANIMATION_ELEMENT_DURATION = 250; + private static final long TRANSIENT_FP_ERROR_TIMEOUT = 1300; + private static final long[] FP_ERROR_VIBRATE_PATTERN = new long[] {0, 30, 100, 30}; + private static final long[] FP_SUCCESS_VIBRATE_PATTERN = new long[] {0, 30}; private KeyguardAffordanceView mCameraImageView; private KeyguardAffordanceView mPhoneImageView; @@ -101,6 +107,7 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL private final Interpolator mLinearOutSlowInInterpolator; private int mLastUnlockIconRes = 0; private boolean mPrewarmSent; + private boolean mTransientFpError; public KeyguardBottomAreaView(Context context) { this(context, null); @@ -431,28 +438,41 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL return; } // TODO: Real icon for facelock. - int iconRes = mUnlockMethodCache.isFaceUnlockRunning() - ? com.android.internal.R.drawable.ic_account_circle + boolean isFingerprintIcon = + KeyguardUpdateMonitor.getInstance(mContext).isFingerprintDetectionRunning(); + boolean anyFingerprintIcon = isFingerprintIcon || mTransientFpError; + int iconRes = mTransientFpError ? R.drawable.ic_fingerprint_error + : isFingerprintIcon ? R.drawable.ic_fingerprint + : mUnlockMethodCache.isFaceUnlockRunning() + ? com.android.internal.R.drawable.ic_account_circle : mUnlockMethodCache.isCurrentlyInsecure() ? R.drawable.ic_lock_open_24dp : R.drawable.ic_lock_24dp; + if (mLastUnlockIconRes != iconRes) { Drawable icon = mContext.getDrawable(iconRes); int iconHeight = getResources().getDimensionPixelSize( R.dimen.keyguard_affordance_icon_height); int iconWidth = getResources().getDimensionPixelSize( R.dimen.keyguard_affordance_icon_width); - if (icon.getIntrinsicHeight() != iconHeight || icon.getIntrinsicWidth() != iconWidth) { + if (!anyFingerprintIcon && (icon.getIntrinsicHeight() != iconHeight + || icon.getIntrinsicWidth() != iconWidth)) { icon = new IntrinsicSizeDrawable(icon, iconWidth, iconHeight); } mLockIcon.setImageDrawable(icon); + mLockIcon.setPaddingRelative(0, 0, 0, anyFingerprintIcon + ? getResources().getDimensionPixelSize( + R.dimen.fingerprint_icon_additional_padding) + : 0); + mLockIcon.setRestingAlpha( + anyFingerprintIcon ? 1f : KeyguardAffordanceHelper.SWIPE_RESTING_ALPHA_AMOUNT); } - boolean trustManaged = mUnlockMethodCache.isTrustManaged(); + + // Hide trust circle when fingerprint is running. + boolean trustManaged = mUnlockMethodCache.isTrustManaged() && !anyFingerprintIcon; mTrustDrawable.setTrustManaged(trustManaged); updateLockIconClickability(); } - - public KeyguardAffordanceView getPhoneView() { return mPhoneImageView; } @@ -530,6 +550,14 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL .setDuration(DOZE_ANIMATION_ELEMENT_DURATION); } + private void vibrateFingerprintError() { + mContext.getSystemService(Vibrator.class).vibrate(FP_ERROR_VIBRATE_PATTERN, -1); + } + + private void vibrateFingerprintSuccess() { + mContext.getSystemService(Vibrator.class).vibrate(FP_SUCCESS_VIBRATE_PATTERN, -1); + } + private final BroadcastReceiver mDevicePolicyReceiver = new BroadcastReceiver() { public void onReceive(Context context, Intent intent) { post(new Runnable() { @@ -541,6 +569,15 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL } }; + private final Runnable mTransientFpErrorClearRunnable = new Runnable() { + @Override + public void run() { + mTransientFpError = false; + mIndicationController.hideTransientIndication(); + updateLockIcon(); + } + }; + private final KeyguardUpdateMonitorCallback mUpdateMonitorCallback = new KeyguardUpdateMonitorCallback() { @Override @@ -562,6 +599,33 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL public void onKeyguardVisibilityChanged(boolean showing) { updateLockIcon(); } + + @Override + public void onFingerprintAuthenticated(int userId) { + vibrateFingerprintSuccess(); + } + + @Override + public void onFingerprintRunningStateChanged(boolean running) { + updateLockIcon(); + } + + @Override + public void onFingerprintHelp(int msgId, String helpString) { + vibrateFingerprintError(); + mTransientFpError = true; + mIndicationController.showTransientIndication(helpString, + getResources().getColor(R.color.system_warning_color, null)); + removeCallbacks(mTransientFpErrorClearRunnable); + postDelayed(mTransientFpErrorClearRunnable, TRANSIENT_FP_ERROR_TIMEOUT); + updateLockIcon(); + } + + @Override + public void onFingerprintError(int msgId, String errString) { + // TODO: Go to bouncer if this is "too many attempts" (lockout) error. + Log.i(TAG, "FP Error: " + errString); + } }; public void setKeyguardIndicationController( @@ -569,7 +633,6 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL mIndicationController = keyguardIndicationController; } - /** * A wrapper around another Drawable that overrides the intrinsic size. */ diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java index 216730b..02b6c19 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java @@ -1505,7 +1505,7 @@ public class NotificationPanelView extends PanelView implements lockIcon.setImageScale(LOCK_ICON_ACTIVE_SCALE, true, 150, mFastOutLinearInterpolator); } else if (!active && mUnlockIconActive && mTracking) { - lockIcon.setImageAlpha(KeyguardAffordanceHelper.SWIPE_RESTING_ALPHA_AMOUNT, true, + lockIcon.setImageAlpha(lockIcon.getRestingAlpha(), true /* animate */, 150, mFastOutLinearInterpolator, null); lockIcon.setImageScale(1.0f, true, 150, mFastOutLinearInterpolator); @@ -1796,8 +1796,8 @@ public class NotificationPanelView extends PanelView implements mFastOutSlowInInterpolator, new Runnable() { @Override public void run() { - icon.setImageAlpha(KeyguardAffordanceHelper.SWIPE_RESTING_ALPHA_AMOUNT, - true, KeyguardAffordanceHelper.HINT_PHASE1_DURATION, + icon.setImageAlpha(icon.getRestingAlpha(), + true /* animate */, KeyguardAffordanceHelper.HINT_PHASE1_DURATION, mFastOutSlowInInterpolator, null); } }); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java index 3efaaff..c6e1be9 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java @@ -187,11 +187,11 @@ public class PanelBar extends FrameLayout { (fullyOpenedPanel!=null)?" fullyOpened":"", fullyClosed?" fullyClosed":""); } - public void collapseAllPanels(boolean animate) { + public void collapseAllPanels(boolean animate, boolean delayed) { boolean waiting = false; for (PanelView pv : mPanels) { if (animate && !pv.isFullyCollapsed()) { - pv.collapse(true /* delayed */); + pv.collapse(delayed); waiting = true; } else { pv.resetViews(); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java index ad78f6a..a43110d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java @@ -1991,10 +1991,14 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, } public void animateCollapsePanels(int flags) { - animateCollapsePanels(flags, false /* force */); + animateCollapsePanels(flags, false /* force */, false /* delayed */); } public void animateCollapsePanels(int flags, boolean force) { + animateCollapsePanels(flags, force, false /* delayed*/); + } + + public void animateCollapsePanels(int flags, boolean force, boolean delayed) { if (!force && (mState == StatusBarState.KEYGUARD || mState == StatusBarState.SHADE_LOCKED)) { runPostCollapseRunnables(); @@ -2018,7 +2022,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, mStatusBarWindowManager.setStatusBarFocusable(false); mStatusBarWindow.cancelExpandHelper(); - mStatusBarView.collapseAllPanels(true); + mStatusBarView.collapseAllPanels(true /* animate */, delayed); } } @@ -2061,7 +2065,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, public void animateCollapseQuickSettings() { if (mState == StatusBarState.SHADE) { - mStatusBarView.collapseAllPanels(true); + mStatusBarView.collapseAllPanels(true, false /* delayed */); } } @@ -2074,7 +2078,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, } // Ensure the panel is fully collapsed (just in case; bug 6765842, 7260868) - mStatusBarView.collapseAllPanels(/*animate=*/ false); + mStatusBarView.collapseAllPanels(/*animate=*/ false, false /* delayed*/); // reset things to their proper state mStackScroller.setVisibility(View.VISIBLE); @@ -2168,7 +2172,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, mStatusBarWindowState = state; if (DEBUG_WINDOW_STATE) Log.d(TAG, "Status bar " + windowStateToString(state)); if (!showing && mState == StatusBarState.SHADE) { - mStatusBarView.collapseAllPanels(false); + mStatusBarView.collapseAllPanels(false /* animate */, false /* delayed */); } } if (mNavigationBarView != null @@ -2643,8 +2647,8 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, } }); if (dismissShade) { - animateCollapsePanels( - CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL, true /* force */); + animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL, true /* force */, + true /* delayed*/); } return true; } |
