| /* |
| * 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 |
| */ |
| |
| package com.android.settings.fingerprint; |
| |
| import android.animation.Animator; |
| import android.animation.AnimatorListenerAdapter; |
| import android.animation.ObjectAnimator; |
| import android.app.AlertDialog; |
| import android.app.Dialog; |
| import android.app.DialogFragment; |
| import android.content.DialogInterface; |
| import android.content.Intent; |
| import android.graphics.drawable.AnimatedVectorDrawable; |
| import android.os.Bundle; |
| import android.view.MotionEvent; |
| import android.view.View; |
| import android.view.animation.AnimationUtils; |
| import android.view.animation.Interpolator; |
| import android.widget.ImageView; |
| import android.widget.ProgressBar; |
| import android.widget.TextView; |
| |
| import com.android.settings.ChooseLockSettingsHelper; |
| import com.android.settings.R; |
| |
| /** |
| * Activity which handles the actual enrolling for fingerprint. |
| */ |
| public class FingerprintEnrollEnrolling extends FingerprintEnrollBase |
| implements FingerprintEnrollSidecar.Listener { |
| |
| private static final String TAG_SIDECAR = "sidecar"; |
| |
| private static final int PROGRESS_BAR_MAX = 10000; |
| private static final int FINISH_DELAY = 250; |
| |
| /** |
| * How long the user needs to touch the icon until we show the dialog. |
| */ |
| private static final long ICON_TOUCH_DURATION_UNTIL_DIALOG_SHOWN = 500; |
| |
| /** |
| * How many times the user needs to touch the icon until we show the dialog that this is not the |
| * fingerprint sensor. |
| */ |
| private static final int ICON_TOUCH_COUNT_SHOW_UNTIL_DIALOG_SHOWN = 3; |
| |
| private ProgressBar mProgressBar; |
| private ImageView mFingerprintAnimator; |
| private ObjectAnimator mProgressAnim; |
| private TextView mStartMessage; |
| private TextView mRepeatMessage; |
| private TextView mErrorText; |
| private Interpolator mFastOutSlowInInterpolator; |
| private int mIconTouchCount; |
| private FingerprintEnrollSidecar mSidecar; |
| private boolean mAnimationCancelled; |
| private AnimatedVectorDrawable mIconAnimationDrawable; |
| |
| @Override |
| protected void onCreate(Bundle savedInstanceState) { |
| super.onCreate(savedInstanceState); |
| setContentView(R.layout.fingerprint_enroll_enrolling); |
| setHeaderText(R.string.security_settings_fingerprint_enroll_start_title); |
| mStartMessage = (TextView) findViewById(R.id.start_message); |
| mRepeatMessage = (TextView) findViewById(R.id.repeat_message); |
| mErrorText = (TextView) findViewById(R.id.error_text); |
| mProgressBar = (ProgressBar) findViewById(R.id.fingerprint_progress_bar); |
| mFingerprintAnimator = (ImageView) findViewById(R.id.fingerprint_animator); |
| mIconAnimationDrawable = (AnimatedVectorDrawable) mFingerprintAnimator.getDrawable(); |
| mIconAnimationDrawable.addListener(mIconAnimationListener); |
| mFastOutSlowInInterpolator = AnimationUtils.loadInterpolator( |
| this, android.R.interpolator.fast_out_slow_in); |
| mFingerprintAnimator.setOnTouchListener(new View.OnTouchListener() { |
| @Override |
| public boolean onTouch(View v, MotionEvent event) { |
| if (event.getActionMasked() == MotionEvent.ACTION_DOWN) { |
| mIconTouchCount++; |
| if (mIconTouchCount == ICON_TOUCH_COUNT_SHOW_UNTIL_DIALOG_SHOWN) { |
| showIconTouchDialog(); |
| } else { |
| mFingerprintAnimator.postDelayed(mShowDialogRunnable, |
| ICON_TOUCH_DURATION_UNTIL_DIALOG_SHOWN); |
| } |
| } else if (event.getActionMasked() == MotionEvent.ACTION_CANCEL |
| || event.getActionMasked() == MotionEvent.ACTION_UP) { |
| mFingerprintAnimator.removeCallbacks(mShowDialogRunnable); |
| } |
| return true; |
| } |
| }); |
| } |
| |
| @Override |
| protected void onStart() { |
| super.onStart(); |
| mSidecar = (FingerprintEnrollSidecar) getFragmentManager().findFragmentByTag(TAG_SIDECAR); |
| if (mSidecar == null) { |
| mSidecar = new FingerprintEnrollSidecar(); |
| getFragmentManager().beginTransaction().add(mSidecar, TAG_SIDECAR).commit(); |
| } |
| mSidecar.setListener(this); |
| updateProgress(false /* animate */); |
| updateDescription(); |
| } |
| |
| @Override |
| public void onEnterAnimationComplete() { |
| super.onEnterAnimationComplete(); |
| mAnimationCancelled = false; |
| startIconAnimation(); |
| } |
| |
| private void startIconAnimation() { |
| mIconAnimationDrawable.start(); |
| } |
| |
| private void stopIconAnimation() { |
| mAnimationCancelled = true; |
| mIconAnimationDrawable.stop(); |
| } |
| |
| @Override |
| protected void onStop() { |
| super.onStop(); |
| mSidecar.setListener(null); |
| stopIconAnimation(); |
| } |
| |
| private void animateProgress(int progress) { |
| if (mProgressAnim != null) { |
| mProgressAnim.cancel(); |
| } |
| ObjectAnimator anim = ObjectAnimator.ofInt(mProgressBar, "progress", |
| mProgressBar.getProgress(), progress); |
| anim.addListener(mProgressAnimationListener); |
| anim.setInterpolator(mFastOutSlowInInterpolator); |
| anim.setDuration(250); |
| anim.start(); |
| mProgressAnim = anim; |
| } |
| |
| private void launchFinish(byte[] token) { |
| Intent intent = new Intent(); |
| intent.setClassName("com.android.settings", FingerprintEnrollFinish.class.getName()); |
| intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN, token); |
| startActivity(intent); |
| setResult(RESULT_FINISHED); |
| finish(); |
| } |
| |
| private void updateDescription() { |
| if (mSidecar.getEnrollmentSteps() == -1) { |
| setHeaderText(R.string.security_settings_fingerprint_enroll_start_title); |
| mStartMessage.setVisibility(View.VISIBLE); |
| mRepeatMessage.setVisibility(View.INVISIBLE); |
| } else { |
| setHeaderText(R.string.security_settings_fingerprint_enroll_repeat_title); |
| mStartMessage.setVisibility(View.INVISIBLE); |
| mRepeatMessage.setVisibility(View.VISIBLE); |
| } |
| } |
| |
| |
| @Override |
| public void onEnrollmentHelp(CharSequence helpString) { |
| mErrorText.setText(helpString); |
| } |
| |
| @Override |
| public void onEnrollmentError(CharSequence errString) { |
| mErrorText.setText(errString); |
| } |
| |
| @Override |
| public void onEnrollmentProgressChange(int steps, int remaining) { |
| updateProgress(true /* animate */); |
| updateDescription(); |
| mErrorText.setText(""); |
| } |
| |
| private void updateProgress(boolean animate) { |
| int progress = getProgress( |
| mSidecar.getEnrollmentSteps(), mSidecar.getEnrollmentRemaining()); |
| if (animate) { |
| animateProgress(progress); |
| } else { |
| mProgressBar.setProgress(progress); |
| } |
| } |
| |
| private int getProgress(int steps, int remaining) { |
| if (steps == -1) { |
| return 0; |
| } |
| int progress = Math.max(0, steps + 1 - remaining); |
| return PROGRESS_BAR_MAX * progress / (steps + 1); |
| } |
| |
| private void showIconTouchDialog() { |
| mIconTouchCount = 0; |
| new IconTouchDialog().show(getFragmentManager(), null /* tag */); |
| } |
| |
| private final Animator.AnimatorListener mProgressAnimationListener |
| = new Animator.AnimatorListener() { |
| |
| @Override |
| public void onAnimationStart(Animator animation) { } |
| |
| @Override |
| public void onAnimationRepeat(Animator animation) { } |
| |
| @Override |
| public void onAnimationEnd(Animator animation) { |
| if (mProgressBar.getProgress() >= PROGRESS_BAR_MAX) { |
| mProgressBar.postDelayed(mDelayedFinishRunnable, FINISH_DELAY); |
| } |
| } |
| |
| @Override |
| public void onAnimationCancel(Animator animation) { } |
| }; |
| |
| // Give the user a chance to see progress completed before jumping to the next stage. |
| private final Runnable mDelayedFinishRunnable = new Runnable() { |
| @Override |
| public void run() { |
| launchFinish(mToken); |
| } |
| }; |
| |
| private final Animator.AnimatorListener mIconAnimationListener = new AnimatorListenerAdapter() { |
| @Override |
| public void onAnimationEnd(Animator animation) { |
| if (mAnimationCancelled) { |
| return; |
| } |
| |
| // Start animation after it has ended. |
| mFingerprintAnimator.post(new Runnable() { |
| @Override |
| public void run() { |
| startIconAnimation(); |
| } |
| }); |
| } |
| }; |
| |
| private final Runnable mShowDialogRunnable = new Runnable() { |
| @Override |
| public void run() { |
| showIconTouchDialog(); |
| } |
| }; |
| |
| private static class IconTouchDialog extends DialogFragment { |
| |
| @Override |
| public Dialog onCreateDialog(Bundle savedInstanceState) { |
| AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); |
| builder.setTitle(R.string.security_settings_fingerprint_enroll_touch_dialog_title) |
| .setMessage(R.string.security_settings_fingerprint_enroll_touch_dialog_message) |
| .setPositiveButton(R.string.security_settings_fingerprint_enroll_dialog_ok, |
| new DialogInterface.OnClickListener() { |
| @Override |
| public void onClick(DialogInterface dialog, int which) { |
| dialog.dismiss(); |
| } |
| }); |
| return builder.create(); |
| } |
| } |
| } |