Merge "Refine fingerprint enrollment experience" into mnc-dev

This commit is contained in:
Jorim Jaggi
2015-06-11 22:34:52 +00:00
committed by Android (Google) Code Review
10 changed files with 153 additions and 12 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

View File

@@ -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="88.0dp"
android:height="88.0dp"
android:viewportWidth="88.0"
android:viewportHeight="88.0">
<path
android:fillColor="#FF000000"
android:pathData="M67.74,11.59c-0.41,0.0 -0.82,-0.1 -1.2,-0.31c-7.44,-4.06 -15.0,-6.04 -23.11,-6.04c-7.92,0.0 -14.67,1.85 -21.88,6.01c-1.2,0.69 -2.73,0.28 -3.42,-0.92s-0.28,-2.72 0.92,-3.41c7.9,-4.55 15.65,-6.68 24.37,-6.68c8.97,0.0 17.32,2.17 25.51,6.65c1.21,0.66 1.66,2.18 1.0,3.39C69.48,11.12 68.62,11.59 67.74,11.59z"/>
<path
android:fillColor="#FF000000"
android:pathData="M9.25,34.74c-0.48,0.0 -0.96,-0.14 -1.39,-0.42c-1.15,-0.77 -1.45,-2.32 -0.68,-3.47c4.09,-6.09 9.3,-10.89 15.49,-14.27c6.52,-3.55 13.91,-5.43 21.38,-5.43c7.44,0.0 14.8,1.86 21.3,5.39c6.17,3.35 11.38,8.12 15.47,14.16c0.77,1.14 0.47,2.7 -0.67,3.47c-1.14,0.77 -2.7,0.47 -3.47,-0.67c-3.64,-5.38 -8.25,-9.61 -13.71,-12.57c-5.77,-3.13 -12.31,-4.78 -18.92,-4.78c-6.63,0.0 -13.2,1.67 -18.98,4.82c-5.48,2.99 -10.1,7.25 -13.73,12.66C10.85,34.35 10.06,34.74 9.25,34.74z"/>
<path
android:fillColor="#FF000000"
android:pathData="M34.76,86.82c-0.67,0.0 -1.33,-0.27 -1.82,-0.79c-3.49,-3.72 -5.51,-6.25 -8.26,-11.45c-2.84,-5.35 -4.34,-11.88 -4.34,-18.86c0.0,-13.02 10.59,-23.61 23.61,-23.61c13.02,0.0 23.61,10.59 23.61,23.61c0.0,1.38 -1.12,2.5 -2.5,2.5s-2.5,-1.12 -2.5,-2.5c0.0,-10.26 -8.35,-18.61 -18.61,-18.61c-10.26,0.0 -18.61,8.35 -18.61,18.61c0.0,6.17 1.3,11.89 3.76,16.52c2.62,4.94 4.37,7.04 7.49,10.37c0.94,1.01 0.89,2.59 -0.11,3.53C35.99,86.6 35.38,86.82 34.76,86.82z"/>
<path
android:fillColor="#FF000000"
android:pathData="M64.28,78.84c-4.99,0.0 -9.35,-1.32 -12.98,-3.92c-6.17,-4.43 -9.86,-11.6 -9.86,-19.19c0.0,-1.38 1.12,-2.5 2.5,-2.5s2.5,1.12 2.5,2.5c0.0,5.98 2.91,11.64 7.77,15.13c2.8,2.01 6.09,2.98 10.06,2.98c0.97,0.0 2.57,-0.11 4.17,-0.4c1.36,-0.25 2.66,0.64 2.92,2.0c0.25,1.36 -0.64,2.66 -2.0,2.92C66.93,78.8 64.86,78.84 64.28,78.84z"/>
<path
android:fillColor="#FF000000"
android:pathData="M55.92,87.75c-0.23,0.0 -0.46,-0.03 -0.7,-0.1c-6.6,-1.91 -10.92,-4.49 -15.4,-9.2c-5.76,-6.06 -8.94,-14.13 -8.94,-22.72c0.0,-7.2 5.86,-13.05 13.05,-13.05c7.2,0.0 13.05,5.86 13.05,13.05c0.0,4.44 3.61,8.05 8.05,8.05s8.05,-3.61 8.05,-8.05c0.0,-16.08 -13.08,-29.16 -29.16,-29.16c-11.43,0.0 -21.86,6.73 -26.58,17.15c-1.57,3.48 -2.37,7.52 -2.37,12.01c0.0,3.36 0.28,8.62 2.71,15.49c0.46,1.3 -0.22,2.73 -1.52,3.19c-1.3,0.46 -2.73,-0.22 -3.19,-1.52c-2.02,-5.7 -3.0,-11.31 -3.0,-17.16c0.0,-5.21 0.95,-9.94 2.82,-14.07c5.52,-12.2 17.74,-20.09 31.13,-20.09c18.83,0.0 34.16,15.32 34.16,34.16c0.0,7.2 -5.86,13.05 -13.05,13.05S52.0,62.92 52.0,55.73c0.0,-4.44 -3.61,-8.05 -8.05,-8.05s-8.05,3.61 -8.05,8.05c0.0,7.3 2.69,14.15 7.56,19.28c3.86,4.06 7.43,6.18 13.17,7.84c1.33,0.38 2.09,1.77 1.71,3.1C58.01,87.04 57.01,87.75 55.92,87.75z"/>
</vector>

View File

@@ -69,7 +69,8 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginBottom="16dp" android:layout_marginBottom="16dp"
android:layout_gravity="center_horizontal|bottom"/> android:layout_gravity="center_horizontal|bottom"
android:visibility="invisible"/>
</FrameLayout> </FrameLayout>

View File

@@ -66,7 +66,8 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="24dp" android:layout_marginTop="24dp"
android:layout_gravity="center_horizontal"/> android:layout_gravity="center_horizontal"
android:visibility="invisible"/>
</LinearLayout> </LinearLayout>

View File

@@ -22,18 +22,14 @@
android:layout_marginTop="36dp" android:layout_marginTop="36dp"
android:layout_gravity="center_horizontal"> android:layout_gravity="center_horizontal">
<ImageView
android:layout_width="88dp"
android:layout_height="88dp"
android:layout_centerInParent="true"
android:src="@drawable/fingerprint_indicator" />
<ImageView <ImageView
android:id="@+id/fingerprint_animator" android:id="@+id/fingerprint_animator"
android:layout_width="88dp" android:layout_width="88dp"
android:layout_height="88dp" android:layout_height="88dp"
android:layout_centerInParent="true" android:layout_centerInParent="true"
android:src="@drawable/enrollment_fingerprint_isolated_animation" /> android:background="@drawable/fp_illustration_enrollment"
android:backgroundTint="@color/fingerprint_indicator_background_resting"
android:src="@drawable/enrollment_fingerprint_isolated_animation"/>
<ProgressBar <ProgressBar
android:id="@+id/fingerprint_progress_bar" android:id="@+id/fingerprint_progress_bar"

View File

@@ -63,7 +63,6 @@
android:id="@+id/add_another_button" android:id="@+id/add_another_button"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:text="@string/fingerprint_enroll_button_add" /> android:text="@string/fingerprint_enroll_button_add" />
<Button <Button

View File

@@ -66,6 +66,8 @@
<color name="fingerprint_message_color">#de000000</color> <color name="fingerprint_message_color">#de000000</color>
<color name="fingerprint_progress_ring">?android:attr/colorAccent</color> <color name="fingerprint_progress_ring">?android:attr/colorAccent</color>
<color name="fingerprint_progress_ring_bg">#20000000</color> <color name="fingerprint_progress_ring_bg">#20000000</color>
<color name="fingerprint_indicator_background_resting">#12000000</color>
<color name="fingerprint_indicator_background_activated">#80009688</color>
<color name="running_processes_system_ram">#ff384248</color> <color name="running_processes_system_ram">#ff384248</color>
<color name="running_processes_apps_ram">#ff009587</color> <color name="running_processes_apps_ram">#ff009587</color>

View File

@@ -231,6 +231,8 @@
<dimen name="fingerprint_find_sensor_graphic_size">200dp</dimen> <dimen name="fingerprint_find_sensor_graphic_size">200dp</dimen>
<item name="fingerprint_illustration_aspect_ratio" format="float" type="dimen">2.6</item> <item name="fingerprint_illustration_aspect_ratio" format="float" type="dimen">2.6</item>
<dimen name="fingerprint_decor_padding_top">0dp</dimen> <dimen name="fingerprint_decor_padding_top">0dp</dimen>
<dimen name="fingerprint_error_text_appear_distance">16dp</dimen>
<dimen name="fingerprint_error_text_disappear_distance">-8dp</dimen>
<dimen name="confirm_credentials_security_method_margin">48dp</dimen> <dimen name="confirm_credentials_security_method_margin">48dp</dimen>
<dimen name="fab_size">56dp</dimen> <dimen name="fab_size">56dp</dimen>

View File

@@ -823,6 +823,8 @@
<string name="security_settings_fingerprint_enroll_disclaimer">In addition to unlocking your phone, you can also use your fingerprint to authorize purchases and app access. <annotation id="url">Learn more</annotation></string> <string name="security_settings_fingerprint_enroll_disclaimer">In addition to unlocking your phone, you can also use your fingerprint to authorize purchases and app access. <annotation id="url">Learn more</annotation></string>
<!-- Text shown in fingerprint settings explaining what the fingerprint can be used for in the case unlocking is disabled [CHAR LIMIT=NONE] --> <!-- Text shown in fingerprint settings explaining what the fingerprint can be used for in the case unlocking is disabled [CHAR LIMIT=NONE] -->
<string name="security_settings_fingerprint_enroll_disclaimer_lockscreen_disabled">Screen lock option disabled. You can still use your fingerprint to authorize purchases and app access. <annotation id="url">Learn more</annotation></string> <string name="security_settings_fingerprint_enroll_disclaimer_lockscreen_disabled">Screen lock option disabled. You can still use your fingerprint to authorize purchases and app access. <annotation id="url">Learn more</annotation></string>
<!-- Text shown in fingerprint enroll when we didn't observe progress for a few seconds. [CHAR LIMIT=100] -->
<string name="security_settings_fingerprint_enroll_lift_touch_again">Lift finger, then touch sensor again</string>
<!-- Title of the preferences category for preference items to control encryption --> <!-- Title of the preferences category for preference items to control encryption -->
<string name="crypt_keeper_settings_title">Encryption</string> <string name="crypt_keeper_settings_title">Encryption</string>

View File

@@ -17,12 +17,15 @@
package com.android.settings.fingerprint; package com.android.settings.fingerprint;
import android.animation.Animator; import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator; import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.app.AlertDialog; import android.app.AlertDialog;
import android.app.Dialog; import android.app.Dialog;
import android.app.DialogFragment; import android.app.DialogFragment;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.content.Intent; import android.content.Intent;
import android.content.res.ColorStateList;
import android.graphics.drawable.Animatable2; import android.graphics.drawable.Animatable2;
import android.graphics.drawable.AnimatedVectorDrawable; import android.graphics.drawable.AnimatedVectorDrawable;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
@@ -49,6 +52,12 @@ public class FingerprintEnrollEnrolling extends FingerprintEnrollBase
private static final int PROGRESS_BAR_MAX = 10000; private static final int PROGRESS_BAR_MAX = 10000;
private static final int FINISH_DELAY = 250; private static final int FINISH_DELAY = 250;
/**
* If we don't see progress during this time, we show an error message to remind the user that
* he needs to lift the finger and touch again.
*/
private static final int HINT_TIMEOUT_DURATION = 2500;
/** /**
* How long the user needs to touch the icon until we show the dialog. * How long the user needs to touch the icon until we show the dialog.
*/ */
@@ -67,10 +76,15 @@ public class FingerprintEnrollEnrolling extends FingerprintEnrollBase
private TextView mRepeatMessage; private TextView mRepeatMessage;
private TextView mErrorText; private TextView mErrorText;
private Interpolator mFastOutSlowInInterpolator; private Interpolator mFastOutSlowInInterpolator;
private Interpolator mLinearOutSlowInInterpolator;
private Interpolator mFastOutLinearInInterpolator;
private int mIconTouchCount; private int mIconTouchCount;
private FingerprintEnrollSidecar mSidecar; private FingerprintEnrollSidecar mSidecar;
private boolean mAnimationCancelled; private boolean mAnimationCancelled;
private AnimatedVectorDrawable mIconAnimationDrawable; private AnimatedVectorDrawable mIconAnimationDrawable;
private int mIndicatorBackgroundRestingColor;
private int mIndicatorBackgroundActivatedColor;
private boolean mRestoring;
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
@@ -86,6 +100,10 @@ public class FingerprintEnrollEnrolling extends FingerprintEnrollBase
mIconAnimationDrawable.registerAnimationCallback(mIconAnimationCallback); mIconAnimationDrawable.registerAnimationCallback(mIconAnimationCallback);
mFastOutSlowInInterpolator = AnimationUtils.loadInterpolator( mFastOutSlowInInterpolator = AnimationUtils.loadInterpolator(
this, android.R.interpolator.fast_out_slow_in); this, android.R.interpolator.fast_out_slow_in);
mLinearOutSlowInInterpolator = AnimationUtils.loadInterpolator(
this, android.R.interpolator.linear_out_slow_in);
mFastOutLinearInInterpolator = AnimationUtils.loadInterpolator(
this, android.R.interpolator.fast_out_linear_in);
mFingerprintAnimator.setOnTouchListener(new View.OnTouchListener() { mFingerprintAnimator.setOnTouchListener(new View.OnTouchListener() {
@Override @Override
public boolean onTouch(View v, MotionEvent event) { public boolean onTouch(View v, MotionEvent event) {
@@ -104,6 +122,11 @@ public class FingerprintEnrollEnrolling extends FingerprintEnrollBase
return true; return true;
} }
}); });
mIndicatorBackgroundRestingColor
= getColor(R.color.fingerprint_indicator_background_resting);
mIndicatorBackgroundActivatedColor
= getColor(R.color.fingerprint_indicator_background_activated);
mRestoring = savedInstanceState != null;
} }
@Override @Override
@@ -117,6 +140,9 @@ public class FingerprintEnrollEnrolling extends FingerprintEnrollBase
mSidecar.setListener(this); mSidecar.setListener(this);
updateProgress(false /* animate */); updateProgress(false /* animate */);
updateDescription(); updateDescription();
if (mRestoring) {
startIconAnimation();
}
} }
@Override @Override
@@ -158,6 +184,34 @@ public class FingerprintEnrollEnrolling extends FingerprintEnrollBase
mProgressAnim = anim; mProgressAnim = anim;
} }
private void animateFlash() {
ValueAnimator anim = ValueAnimator.ofArgb(mIndicatorBackgroundRestingColor,
mIndicatorBackgroundActivatedColor);
final ValueAnimator.AnimatorUpdateListener listener =
new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
mFingerprintAnimator.setBackgroundTintList(ColorStateList.valueOf(
(Integer) animation.getAnimatedValue()));
}
};
anim.addUpdateListener(listener);
anim.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
ValueAnimator anim = ValueAnimator.ofArgb(mIndicatorBackgroundActivatedColor,
mIndicatorBackgroundRestingColor);
anim.addUpdateListener(listener);
anim.setDuration(300);
anim.setInterpolator(mLinearOutSlowInInterpolator);
anim.start();
}
});
anim.setInterpolator(mFastOutSlowInInterpolator);
anim.setDuration(300);
anim.start();
}
private void launchFinish(byte[] token) { private void launchFinish(byte[] token) {
Intent intent = new Intent(); Intent intent = new Intent();
intent.setClassName("com.android.settings", FingerprintEnrollFinish.class.getName()); intent.setClassName("com.android.settings", FingerprintEnrollFinish.class.getName());
@@ -187,7 +241,7 @@ public class FingerprintEnrollEnrolling extends FingerprintEnrollBase
@Override @Override
public void onEnrollmentError(CharSequence errString) { public void onEnrollmentError(CharSequence errString) {
mErrorText.setText(errString); showError(errString);
stopIconAnimation(); stopIconAnimation();
} }
@@ -195,7 +249,10 @@ public class FingerprintEnrollEnrolling extends FingerprintEnrollBase
public void onEnrollmentProgressChange(int steps, int remaining) { public void onEnrollmentProgressChange(int steps, int remaining) {
updateProgress(true /* animate */); updateProgress(true /* animate */);
updateDescription(); updateDescription();
mErrorText.setText(""); clearError();
animateFlash();
mErrorText.removeCallbacks(mTouchAgainRunnable);
mErrorText.postDelayed(mTouchAgainRunnable, HINT_TIMEOUT_DURATION);
} }
private void updateProgress(boolean animate) { private void updateProgress(boolean animate) {
@@ -221,6 +278,44 @@ public class FingerprintEnrollEnrolling extends FingerprintEnrollBase
new IconTouchDialog().show(getFragmentManager(), null /* tag */); new IconTouchDialog().show(getFragmentManager(), null /* tag */);
} }
private void showError(CharSequence error) {
mErrorText.setText(error);
if (mErrorText.getVisibility() == View.INVISIBLE) {
mErrorText.setVisibility(View.VISIBLE);
mErrorText.setTranslationY(getResources().getDimensionPixelSize(
R.dimen.fingerprint_error_text_appear_distance));
mErrorText.setAlpha(0f);
mErrorText.animate()
.alpha(1f)
.translationY(0f)
.setDuration(200)
.setInterpolator(mLinearOutSlowInInterpolator)
.start();
} else {
mErrorText.animate().cancel();
mErrorText.setAlpha(1f);
mErrorText.setTranslationY(0f);
}
}
private void clearError() {
if (mErrorText.getVisibility() == View.VISIBLE) {
mErrorText.animate()
.alpha(0f)
.translationY(getResources().getDimensionPixelSize(
R.dimen.fingerprint_error_text_disappear_distance))
.setDuration(100)
.setInterpolator(mFastOutLinearInInterpolator)
.withEndAction(new Runnable() {
@Override
public void run() {
mErrorText.setVisibility(View.INVISIBLE);
}
})
.start();
}
}
private final Animator.AnimatorListener mProgressAnimationListener private final Animator.AnimatorListener mProgressAnimationListener
= new Animator.AnimatorListener() { = new Animator.AnimatorListener() {
@@ -274,6 +369,13 @@ public class FingerprintEnrollEnrolling extends FingerprintEnrollBase
} }
}; };
private final Runnable mTouchAgainRunnable = new Runnable() {
@Override
public void run() {
showError(getString(R.string.security_settings_fingerprint_enroll_lift_touch_again));
}
};
private static class IconTouchDialog extends DialogFragment { private static class IconTouchDialog extends DialogFragment {
@Override @Override