Kevin Chyn | 42653e8 | 2018-01-19 14:15:46 -0800 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (C) 2018 The Android Open Source Project |
| 3 | * |
| 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | * you may not use this file except in compliance with the License. |
| 6 | * You may obtain a copy of the License at |
| 7 | * |
| 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
| 9 | * |
| 10 | * Unless required by applicable law or agreed to in writing, software |
| 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
| 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 | * See the License for the specific language governing permissions and |
| 14 | * limitations under the License |
| 15 | */ |
| 16 | |
| 17 | package com.android.systemui.fingerprint; |
| 18 | |
Kevin Chyn | 42653e8 | 2018-01-19 14:15:46 -0800 | [diff] [blame] | 19 | import android.content.Context; |
Kevin Chyn | d0544dc | 2018-02-06 16:30:31 -0800 | [diff] [blame] | 20 | import android.graphics.Color; |
Kevin Chyn | 42653e8 | 2018-01-19 14:15:46 -0800 | [diff] [blame] | 21 | import android.graphics.PixelFormat; |
Kevin Chyn | d0544dc | 2018-02-06 16:30:31 -0800 | [diff] [blame] | 22 | import android.graphics.drawable.AnimatedVectorDrawable; |
Kevin Chyn | 42653e8 | 2018-01-19 14:15:46 -0800 | [diff] [blame] | 23 | import android.graphics.drawable.Drawable; |
Vishwath Mohan | ecf00ce | 2018-04-05 10:28:24 -0700 | [diff] [blame] | 24 | import android.hardware.biometrics.BiometricPrompt; |
Kevin Chyn | 42653e8 | 2018-01-19 14:15:46 -0800 | [diff] [blame] | 25 | import android.os.Binder; |
| 26 | import android.os.Bundle; |
| 27 | import android.os.Handler; |
| 28 | import android.os.IBinder; |
Kevin Chyn | a4596f3 | 2018-04-05 11:33:12 -0700 | [diff] [blame] | 29 | import android.text.TextUtils; |
Kevin Chyn | 27ce194 | 2018-03-12 14:42:17 -0700 | [diff] [blame] | 30 | import android.util.DisplayMetrics; |
Kevin Chyn | d0544dc | 2018-02-06 16:30:31 -0800 | [diff] [blame] | 31 | import android.util.Log; |
Kevin Chyn | 42653e8 | 2018-01-19 14:15:46 -0800 | [diff] [blame] | 32 | import android.view.KeyEvent; |
| 33 | import android.view.LayoutInflater; |
| 34 | import android.view.MotionEvent; |
| 35 | import android.view.View; |
| 36 | import android.view.ViewGroup; |
Kevin Chyn | 42653e8 | 2018-01-19 14:15:46 -0800 | [diff] [blame] | 37 | import android.view.WindowManager; |
Kevin Chyn | 42653e8 | 2018-01-19 14:15:46 -0800 | [diff] [blame] | 38 | import android.view.animation.Interpolator; |
| 39 | import android.widget.Button; |
| 40 | import android.widget.ImageView; |
| 41 | import android.widget.LinearLayout; |
| 42 | import android.widget.TextView; |
| 43 | |
Kevin Chyn | e8f3e1b | 2018-01-23 17:33:58 -0800 | [diff] [blame] | 44 | import com.android.systemui.Interpolators; |
Kevin Chyn | 42653e8 | 2018-01-19 14:15:46 -0800 | [diff] [blame] | 45 | import com.android.systemui.R; |
Kevin Chyn | 42653e8 | 2018-01-19 14:15:46 -0800 | [diff] [blame] | 46 | |
| 47 | /** |
| 48 | * This class loads the view for the system-provided dialog. The view consists of: |
| 49 | * Application Icon, Title, Subtitle, Description, Fingerprint Icon, Error/Help message area, |
| 50 | * and positive/negative buttons. |
| 51 | */ |
| 52 | public class FingerprintDialogView extends LinearLayout { |
| 53 | |
| 54 | private static final String TAG = "FingerprintDialogView"; |
| 55 | |
Kevin Chyn | dba919a | 2018-03-16 14:35:10 -0700 | [diff] [blame] | 56 | private static final int ANIMATION_DURATION_SHOW = 250; // ms |
| 57 | private static final int ANIMATION_DURATION_AWAY = 350; // ms |
Kevin Chyn | 42653e8 | 2018-01-19 14:15:46 -0800 | [diff] [blame] | 58 | |
Kevin Chyn | d0544dc | 2018-02-06 16:30:31 -0800 | [diff] [blame] | 59 | private static final int STATE_NONE = 0; |
| 60 | private static final int STATE_FINGERPRINT = 1; |
| 61 | private static final int STATE_FINGERPRINT_ERROR = 2; |
| 62 | private static final int STATE_FINGERPRINT_AUTHENTICATED = 3; |
| 63 | |
Kevin Chyn | 42653e8 | 2018-01-19 14:15:46 -0800 | [diff] [blame] | 64 | private final IBinder mWindowToken = new Binder(); |
Kevin Chyn | 42653e8 | 2018-01-19 14:15:46 -0800 | [diff] [blame] | 65 | private final Interpolator mLinearOutSlowIn; |
Kevin Chyn | 27e1f26 | 2018-03-08 16:38:32 -0800 | [diff] [blame] | 66 | private final WindowManager mWindowManager; |
Kevin Chyn | e8f3e1b | 2018-01-23 17:33:58 -0800 | [diff] [blame] | 67 | private final float mAnimationTranslationOffset; |
Kevin Chyn | 178ace5 | 2018-03-30 12:36:32 -0700 | [diff] [blame] | 68 | private final int mErrorColor; |
Kevin Chyn | d0544dc | 2018-02-06 16:30:31 -0800 | [diff] [blame] | 69 | private final int mTextColor; |
| 70 | private final int mFingerprintColor; |
Kevin Chyn | 42653e8 | 2018-01-19 14:15:46 -0800 | [diff] [blame] | 71 | |
| 72 | private ViewGroup mLayout; |
| 73 | private final TextView mErrorText; |
| 74 | private Handler mHandler; |
| 75 | private Bundle mBundle; |
Kevin Chyn | 42653e8 | 2018-01-19 14:15:46 -0800 | [diff] [blame] | 76 | private final LinearLayout mDialog; |
Kevin Chyn | d0544dc | 2018-02-06 16:30:31 -0800 | [diff] [blame] | 77 | private int mLastState; |
Kevin Chyn | 87df068 | 2018-04-10 19:29:23 -0700 | [diff] [blame] | 78 | private boolean mAnimatingAway; |
| 79 | private boolean mWasForceRemoved; |
Kevin Chyn | 42653e8 | 2018-01-19 14:15:46 -0800 | [diff] [blame] | 80 | |
Kevin Chyn | 27ce194 | 2018-03-12 14:42:17 -0700 | [diff] [blame] | 81 | private final float mDisplayWidth; |
| 82 | |
Kevin Chyn | 87df068 | 2018-04-10 19:29:23 -0700 | [diff] [blame] | 83 | private final Runnable mShowAnimationRunnable = new Runnable() { |
| 84 | @Override |
| 85 | public void run() { |
| 86 | mLayout.animate() |
| 87 | .alpha(1f) |
| 88 | .setDuration(ANIMATION_DURATION_SHOW) |
| 89 | .setInterpolator(mLinearOutSlowIn) |
| 90 | .withLayer() |
| 91 | .start(); |
| 92 | mDialog.animate() |
| 93 | .translationY(0) |
| 94 | .setDuration(ANIMATION_DURATION_SHOW) |
| 95 | .setInterpolator(mLinearOutSlowIn) |
| 96 | .withLayer() |
| 97 | .start(); |
| 98 | } |
| 99 | }; |
| 100 | |
Kevin Chyn | 42653e8 | 2018-01-19 14:15:46 -0800 | [diff] [blame] | 101 | public FingerprintDialogView(Context context, Handler handler) { |
| 102 | super(context); |
| 103 | mHandler = handler; |
Kevin Chyn | e8f3e1b | 2018-01-23 17:33:58 -0800 | [diff] [blame] | 104 | mLinearOutSlowIn = Interpolators.LINEAR_OUT_SLOW_IN; |
Kevin Chyn | 27e1f26 | 2018-03-08 16:38:32 -0800 | [diff] [blame] | 105 | mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE); |
Kevin Chyn | e8f3e1b | 2018-01-23 17:33:58 -0800 | [diff] [blame] | 106 | mAnimationTranslationOffset = getResources() |
| 107 | .getDimension(R.dimen.fingerprint_dialog_animation_translation_offset); |
Kevin Chyn | 178ace5 | 2018-03-30 12:36:32 -0700 | [diff] [blame] | 108 | mErrorColor = Color.parseColor( |
| 109 | getResources().getString(R.color.fingerprint_dialog_error_color)); |
Kevin Chyn | d0544dc | 2018-02-06 16:30:31 -0800 | [diff] [blame] | 110 | mTextColor = Color.parseColor( |
| 111 | getResources().getString(R.color.fingerprint_dialog_text_light_color)); |
| 112 | mFingerprintColor = Color.parseColor( |
| 113 | getResources().getString(R.color.fingerprint_dialog_fingerprint_color)); |
Kevin Chyn | 42653e8 | 2018-01-19 14:15:46 -0800 | [diff] [blame] | 114 | |
Kevin Chyn | 27ce194 | 2018-03-12 14:42:17 -0700 | [diff] [blame] | 115 | DisplayMetrics metrics = new DisplayMetrics(); |
| 116 | mWindowManager.getDefaultDisplay().getMetrics(metrics); |
| 117 | mDisplayWidth = metrics.widthPixels; |
| 118 | |
Kevin Chyn | 42653e8 | 2018-01-19 14:15:46 -0800 | [diff] [blame] | 119 | // Create the dialog |
| 120 | LayoutInflater factory = LayoutInflater.from(getContext()); |
| 121 | mLayout = (ViewGroup) factory.inflate(R.layout.fingerprint_dialog, this, false); |
| 122 | addView(mLayout); |
| 123 | |
| 124 | mDialog = mLayout.findViewById(R.id.dialog); |
Kevin Chyn | 42653e8 | 2018-01-19 14:15:46 -0800 | [diff] [blame] | 125 | |
| 126 | mErrorText = mLayout.findViewById(R.id.error); |
| 127 | |
| 128 | mLayout.setOnKeyListener(new View.OnKeyListener() { |
| 129 | boolean downPressed = false; |
| 130 | @Override |
| 131 | public boolean onKey(View v, int keyCode, KeyEvent event) { |
| 132 | if (keyCode != KeyEvent.KEYCODE_BACK) { |
| 133 | return false; |
| 134 | } |
| 135 | if (event.getAction() == KeyEvent.ACTION_DOWN && downPressed == false) { |
| 136 | downPressed = true; |
| 137 | } else if (event.getAction() == KeyEvent.ACTION_DOWN) { |
| 138 | downPressed = false; |
| 139 | } else if (event.getAction() == KeyEvent.ACTION_UP && downPressed == true) { |
| 140 | downPressed = false; |
| 141 | mHandler.obtainMessage(FingerprintDialogImpl.MSG_USER_CANCELED).sendToTarget(); |
| 142 | } |
| 143 | return true; |
| 144 | } |
| 145 | }); |
| 146 | |
| 147 | final View space = mLayout.findViewById(R.id.space); |
Kevin Chyn | 27ce194 | 2018-03-12 14:42:17 -0700 | [diff] [blame] | 148 | final View leftSpace = mLayout.findViewById(R.id.left_space); |
| 149 | final View rightSpace = mLayout.findViewById(R.id.right_space); |
Kevin Chyn | 42653e8 | 2018-01-19 14:15:46 -0800 | [diff] [blame] | 150 | final Button negative = mLayout.findViewById(R.id.button2); |
| 151 | final Button positive = mLayout.findViewById(R.id.button1); |
| 152 | |
Kevin Chyn | 27ce194 | 2018-03-12 14:42:17 -0700 | [diff] [blame] | 153 | setDismissesDialog(space); |
| 154 | setDismissesDialog(leftSpace); |
| 155 | setDismissesDialog(rightSpace); |
Kevin Chyn | 42653e8 | 2018-01-19 14:15:46 -0800 | [diff] [blame] | 156 | |
| 157 | negative.setOnClickListener((View v) -> { |
| 158 | mHandler.obtainMessage(FingerprintDialogImpl.MSG_BUTTON_NEGATIVE).sendToTarget(); |
| 159 | }); |
| 160 | |
| 161 | positive.setOnClickListener((View v) -> { |
| 162 | mHandler.obtainMessage(FingerprintDialogImpl.MSG_BUTTON_POSITIVE).sendToTarget(); |
| 163 | }); |
| 164 | |
| 165 | mLayout.setFocusableInTouchMode(true); |
| 166 | mLayout.requestFocus(); |
| 167 | } |
| 168 | |
| 169 | @Override |
| 170 | public void onAttachedToWindow() { |
| 171 | super.onAttachedToWindow(); |
| 172 | |
| 173 | final TextView title = mLayout.findViewById(R.id.title); |
| 174 | final TextView subtitle = mLayout.findViewById(R.id.subtitle); |
| 175 | final TextView description = mLayout.findViewById(R.id.description); |
| 176 | final Button negative = mLayout.findViewById(R.id.button2); |
Kevin Chyn | 42653e8 | 2018-01-19 14:15:46 -0800 | [diff] [blame] | 177 | final Button positive = mLayout.findViewById(R.id.button1); |
Kevin Chyn | d0544dc | 2018-02-06 16:30:31 -0800 | [diff] [blame] | 178 | |
Kevin Chyn | 27ce194 | 2018-03-12 14:42:17 -0700 | [diff] [blame] | 179 | mDialog.getLayoutParams().width = (int) mDisplayWidth; |
| 180 | |
Kevin Chyn | d0544dc | 2018-02-06 16:30:31 -0800 | [diff] [blame] | 181 | mLastState = STATE_NONE; |
| 182 | updateFingerprintIcon(STATE_FINGERPRINT); |
Kevin Chyn | 42653e8 | 2018-01-19 14:15:46 -0800 | [diff] [blame] | 183 | |
Vishwath Mohan | ecf00ce | 2018-04-05 10:28:24 -0700 | [diff] [blame] | 184 | title.setText(mBundle.getCharSequence(BiometricPrompt.KEY_TITLE)); |
Kevin Chyn | 42653e8 | 2018-01-19 14:15:46 -0800 | [diff] [blame] | 185 | title.setSelected(true); |
Kevin Chyn | dba919a | 2018-03-16 14:35:10 -0700 | [diff] [blame] | 186 | |
Vishwath Mohan | ecf00ce | 2018-04-05 10:28:24 -0700 | [diff] [blame] | 187 | final CharSequence subtitleText = mBundle.getCharSequence(BiometricPrompt.KEY_SUBTITLE); |
Kevin Chyn | a4596f3 | 2018-04-05 11:33:12 -0700 | [diff] [blame] | 188 | if (TextUtils.isEmpty(subtitleText)) { |
Kevin Chyn | dba919a | 2018-03-16 14:35:10 -0700 | [diff] [blame] | 189 | subtitle.setVisibility(View.GONE); |
| 190 | } else { |
| 191 | subtitle.setVisibility(View.VISIBLE); |
| 192 | subtitle.setText(subtitleText); |
| 193 | } |
| 194 | |
Vishwath Mohan | ecf00ce | 2018-04-05 10:28:24 -0700 | [diff] [blame] | 195 | final CharSequence descriptionText = mBundle.getCharSequence(BiometricPrompt.KEY_DESCRIPTION); |
Kevin Chyn | a4596f3 | 2018-04-05 11:33:12 -0700 | [diff] [blame] | 196 | if (TextUtils.isEmpty(descriptionText)) { |
Kevin Chyn | dba919a | 2018-03-16 14:35:10 -0700 | [diff] [blame] | 197 | description.setVisibility(View.GONE); |
| 198 | } else { |
Kevin Chyn | a4596f3 | 2018-04-05 11:33:12 -0700 | [diff] [blame] | 199 | description.setVisibility(View.VISIBLE); |
| 200 | description.setText(descriptionText); |
Kevin Chyn | dba919a | 2018-03-16 14:35:10 -0700 | [diff] [blame] | 201 | } |
| 202 | |
Vishwath Mohan | ecf00ce | 2018-04-05 10:28:24 -0700 | [diff] [blame] | 203 | negative.setText(mBundle.getCharSequence(BiometricPrompt.KEY_NEGATIVE_TEXT)); |
Kevin Chyn | 42653e8 | 2018-01-19 14:15:46 -0800 | [diff] [blame] | 204 | |
| 205 | final CharSequence positiveText = |
Vishwath Mohan | ecf00ce | 2018-04-05 10:28:24 -0700 | [diff] [blame] | 206 | mBundle.getCharSequence(BiometricPrompt.KEY_POSITIVE_TEXT); |
Kevin Chyn | 42653e8 | 2018-01-19 14:15:46 -0800 | [diff] [blame] | 207 | positive.setText(positiveText); // needs to be set for marquee to work |
| 208 | if (positiveText != null) { |
| 209 | positive.setVisibility(View.VISIBLE); |
| 210 | } else { |
| 211 | positive.setVisibility(View.GONE); |
| 212 | } |
| 213 | |
Kevin Chyn | 87df068 | 2018-04-10 19:29:23 -0700 | [diff] [blame] | 214 | if (!mWasForceRemoved) { |
| 215 | // Dim the background and slide the dialog up |
| 216 | mDialog.setTranslationY(mAnimationTranslationOffset); |
| 217 | mLayout.setAlpha(0f); |
| 218 | postOnAnimation(mShowAnimationRunnable); |
| 219 | } else { |
| 220 | // Show the dialog immediately |
| 221 | mLayout.animate().cancel(); |
| 222 | mDialog.animate().cancel(); |
| 223 | mDialog.setAlpha(1.0f); |
| 224 | mDialog.setTranslationY(0); |
| 225 | mLayout.setAlpha(1.0f); |
| 226 | } |
| 227 | mWasForceRemoved = false; |
Kevin Chyn | 42653e8 | 2018-01-19 14:15:46 -0800 | [diff] [blame] | 228 | } |
| 229 | |
Kevin Chyn | 27ce194 | 2018-03-12 14:42:17 -0700 | [diff] [blame] | 230 | private void setDismissesDialog(View v) { |
| 231 | v.setClickable(true); |
| 232 | v.setOnTouchListener((View view, MotionEvent event) -> { |
| 233 | mHandler.obtainMessage(FingerprintDialogImpl.MSG_HIDE_DIALOG, true /* userCanceled */) |
| 234 | .sendToTarget(); |
| 235 | return true; |
| 236 | }); |
| 237 | } |
| 238 | |
Kevin Chyn | 27e1f26 | 2018-03-08 16:38:32 -0800 | [diff] [blame] | 239 | public void startDismiss() { |
Kevin Chyn | 87df068 | 2018-04-10 19:29:23 -0700 | [diff] [blame] | 240 | mAnimatingAway = true; |
| 241 | |
Kevin Chyn | 27e1f26 | 2018-03-08 16:38:32 -0800 | [diff] [blame] | 242 | final Runnable endActionRunnable = new Runnable() { |
| 243 | @Override |
| 244 | public void run() { |
| 245 | mWindowManager.removeView(FingerprintDialogView.this); |
Kevin Chyn | 87df068 | 2018-04-10 19:29:23 -0700 | [diff] [blame] | 246 | mAnimatingAway = false; |
Kevin Chyn | 27e1f26 | 2018-03-08 16:38:32 -0800 | [diff] [blame] | 247 | } |
| 248 | }; |
| 249 | |
| 250 | postOnAnimation(new Runnable() { |
| 251 | @Override |
| 252 | public void run() { |
| 253 | mLayout.animate() |
| 254 | .alpha(0f) |
Kevin Chyn | dba919a | 2018-03-16 14:35:10 -0700 | [diff] [blame] | 255 | .setDuration(ANIMATION_DURATION_AWAY) |
Kevin Chyn | 27e1f26 | 2018-03-08 16:38:32 -0800 | [diff] [blame] | 256 | .setInterpolator(mLinearOutSlowIn) |
| 257 | .withLayer() |
| 258 | .start(); |
| 259 | mDialog.animate() |
| 260 | .translationY(mAnimationTranslationOffset) |
Kevin Chyn | dba919a | 2018-03-16 14:35:10 -0700 | [diff] [blame] | 261 | .setDuration(ANIMATION_DURATION_AWAY) |
Kevin Chyn | 27e1f26 | 2018-03-08 16:38:32 -0800 | [diff] [blame] | 262 | .setInterpolator(mLinearOutSlowIn) |
| 263 | .withLayer() |
| 264 | .withEndAction(endActionRunnable) |
| 265 | .start(); |
| 266 | } |
| 267 | }); |
| 268 | } |
| 269 | |
Kevin Chyn | 87df068 | 2018-04-10 19:29:23 -0700 | [diff] [blame] | 270 | /** |
| 271 | * Force remove the window, cancelling any animation that's happening. This should only be |
| 272 | * called if we want to quickly show the dialog again (e.g. on rotation). Calling this method |
| 273 | * will cause the dialog to show without an animation the next time it's attached. |
| 274 | */ |
| 275 | public void forceRemove() { |
| 276 | mLayout.animate().cancel(); |
| 277 | mDialog.animate().cancel(); |
| 278 | mWindowManager.removeView(FingerprintDialogView.this); |
| 279 | mAnimatingAway = false; |
| 280 | mWasForceRemoved = true; |
| 281 | } |
| 282 | |
| 283 | public boolean isAnimatingAway() { |
| 284 | return mAnimatingAway; |
| 285 | } |
| 286 | |
Kevin Chyn | 42653e8 | 2018-01-19 14:15:46 -0800 | [diff] [blame] | 287 | public void setBundle(Bundle bundle) { |
| 288 | mBundle = bundle; |
| 289 | } |
| 290 | |
Kevin Chyn | d0544dc | 2018-02-06 16:30:31 -0800 | [diff] [blame] | 291 | // Clears the temporary message and shows the help message. |
| 292 | protected void resetMessage() { |
| 293 | updateFingerprintIcon(STATE_FINGERPRINT); |
| 294 | mErrorText.setText(R.string.fingerprint_dialog_touch_sensor); |
| 295 | mErrorText.setTextColor(mTextColor); |
Kevin Chyn | 42653e8 | 2018-01-19 14:15:46 -0800 | [diff] [blame] | 296 | } |
| 297 | |
Kevin Chyn | d0544dc | 2018-02-06 16:30:31 -0800 | [diff] [blame] | 298 | // Shows an error/help message |
| 299 | private void showTemporaryMessage(String message) { |
Kevin Chyn | 42653e8 | 2018-01-19 14:15:46 -0800 | [diff] [blame] | 300 | mHandler.removeMessages(FingerprintDialogImpl.MSG_CLEAR_MESSAGE); |
Kevin Chyn | d0544dc | 2018-02-06 16:30:31 -0800 | [diff] [blame] | 301 | updateFingerprintIcon(STATE_FINGERPRINT_ERROR); |
Kevin Chyn | 42653e8 | 2018-01-19 14:15:46 -0800 | [diff] [blame] | 302 | mErrorText.setText(message); |
Kevin Chyn | 178ace5 | 2018-03-30 12:36:32 -0700 | [diff] [blame] | 303 | mErrorText.setTextColor(mErrorColor); |
Kevin Chyn | 16aac7a | 2018-01-24 11:32:46 -0800 | [diff] [blame] | 304 | mErrorText.setContentDescription(message); |
Kevin Chyn | 42653e8 | 2018-01-19 14:15:46 -0800 | [diff] [blame] | 305 | mHandler.sendMessageDelayed(mHandler.obtainMessage(FingerprintDialogImpl.MSG_CLEAR_MESSAGE), |
Vishwath Mohan | ecf00ce | 2018-04-05 10:28:24 -0700 | [diff] [blame] | 306 | BiometricPrompt.HIDE_DIALOG_DELAY); |
Kevin Chyn | 42653e8 | 2018-01-19 14:15:46 -0800 | [diff] [blame] | 307 | } |
| 308 | |
| 309 | public void showHelpMessage(String message) { |
Kevin Chyn | d0544dc | 2018-02-06 16:30:31 -0800 | [diff] [blame] | 310 | showTemporaryMessage(message); |
Kevin Chyn | 42653e8 | 2018-01-19 14:15:46 -0800 | [diff] [blame] | 311 | } |
| 312 | |
| 313 | public void showErrorMessage(String error) { |
Kevin Chyn | d0544dc | 2018-02-06 16:30:31 -0800 | [diff] [blame] | 314 | showTemporaryMessage(error); |
Kevin Chyn | 42653e8 | 2018-01-19 14:15:46 -0800 | [diff] [blame] | 315 | mHandler.sendMessageDelayed(mHandler.obtainMessage(FingerprintDialogImpl.MSG_HIDE_DIALOG, |
Vishwath Mohan | ecf00ce | 2018-04-05 10:28:24 -0700 | [diff] [blame] | 316 | false /* userCanceled */), BiometricPrompt.HIDE_DIALOG_DELAY); |
Kevin Chyn | 42653e8 | 2018-01-19 14:15:46 -0800 | [diff] [blame] | 317 | } |
| 318 | |
Kevin Chyn | d0544dc | 2018-02-06 16:30:31 -0800 | [diff] [blame] | 319 | private void updateFingerprintIcon(int newState) { |
Kevin Chyn | 178ace5 | 2018-03-30 12:36:32 -0700 | [diff] [blame] | 320 | Drawable icon = getAnimationForTransition(mLastState, newState); |
Kevin Chyn | d0544dc | 2018-02-06 16:30:31 -0800 | [diff] [blame] | 321 | |
| 322 | if (icon == null) { |
| 323 | Log.e(TAG, "Animation not found"); |
| 324 | return; |
| 325 | } |
| 326 | |
Kevin Chyn | d0544dc | 2018-02-06 16:30:31 -0800 | [diff] [blame] | 327 | final AnimatedVectorDrawable animation = icon instanceof AnimatedVectorDrawable |
| 328 | ? (AnimatedVectorDrawable) icon |
| 329 | : null; |
| 330 | |
| 331 | final ImageView fingerprint_icon = mLayout.findViewById(R.id.fingerprint_icon); |
| 332 | fingerprint_icon.setImageDrawable(icon); |
| 333 | |
Kevin Chyn | 178ace5 | 2018-03-30 12:36:32 -0700 | [diff] [blame] | 334 | if (animation != null && shouldAnimateForTransition(mLastState, newState)) { |
Kevin Chyn | d0544dc | 2018-02-06 16:30:31 -0800 | [diff] [blame] | 335 | animation.forceAnimationOnUI(); |
| 336 | animation.start(); |
| 337 | } |
| 338 | |
| 339 | mLastState = newState; |
| 340 | } |
| 341 | |
Kevin Chyn | 178ace5 | 2018-03-30 12:36:32 -0700 | [diff] [blame] | 342 | private boolean shouldAnimateForTransition(int oldState, int newState) { |
| 343 | if (oldState == STATE_NONE && newState == STATE_FINGERPRINT) { |
| 344 | return false; |
| 345 | } else if (oldState == STATE_FINGERPRINT && newState == STATE_FINGERPRINT_ERROR) { |
| 346 | return true; |
| 347 | } else if (oldState == STATE_FINGERPRINT_ERROR && newState == STATE_FINGERPRINT) { |
| 348 | return true; |
| 349 | } else if (oldState == STATE_FINGERPRINT && newState == STATE_FINGERPRINT_AUTHENTICATED) { |
| 350 | // TODO(b/77328470): add animation when fingerprint is authenticated |
| 351 | return false; |
| 352 | } |
| 353 | return false; |
| 354 | } |
| 355 | |
| 356 | private Drawable getAnimationForTransition(int oldState, int newState) { |
Kevin Chyn | d0544dc | 2018-02-06 16:30:31 -0800 | [diff] [blame] | 357 | int iconRes; |
| 358 | if (oldState == STATE_NONE && newState == STATE_FINGERPRINT) { |
Kevin Chyn | 178ace5 | 2018-03-30 12:36:32 -0700 | [diff] [blame] | 359 | iconRes = R.drawable.fingerprint_dialog_fp_to_error; |
Kevin Chyn | d0544dc | 2018-02-06 16:30:31 -0800 | [diff] [blame] | 360 | } else if (oldState == STATE_FINGERPRINT && newState == STATE_FINGERPRINT_ERROR) { |
Kevin Chyn | 178ace5 | 2018-03-30 12:36:32 -0700 | [diff] [blame] | 361 | iconRes = R.drawable.fingerprint_dialog_fp_to_error; |
Kevin Chyn | d0544dc | 2018-02-06 16:30:31 -0800 | [diff] [blame] | 362 | } else if (oldState == STATE_FINGERPRINT_ERROR && newState == STATE_FINGERPRINT) { |
Kevin Chyn | 178ace5 | 2018-03-30 12:36:32 -0700 | [diff] [blame] | 363 | iconRes = R.drawable.fingerprint_dialog_error_to_fp; |
Kevin Chyn | d0544dc | 2018-02-06 16:30:31 -0800 | [diff] [blame] | 364 | } else if (oldState == STATE_FINGERPRINT && newState == STATE_FINGERPRINT_AUTHENTICATED) { |
Kevin Chyn | 178ace5 | 2018-03-30 12:36:32 -0700 | [diff] [blame] | 365 | // TODO(b/77328470): add animation when fingerprint is authenticated |
| 366 | iconRes = R.drawable.fingerprint_dialog_error_to_fp; |
| 367 | } |
| 368 | else { |
Kevin Chyn | d0544dc | 2018-02-06 16:30:31 -0800 | [diff] [blame] | 369 | return null; |
| 370 | } |
| 371 | return mContext.getDrawable(iconRes); |
Kevin Chyn | 42653e8 | 2018-01-19 14:15:46 -0800 | [diff] [blame] | 372 | } |
| 373 | |
| 374 | public WindowManager.LayoutParams getLayoutParams() { |
| 375 | final WindowManager.LayoutParams lp = new WindowManager.LayoutParams( |
| 376 | ViewGroup.LayoutParams.MATCH_PARENT, |
| 377 | ViewGroup.LayoutParams.MATCH_PARENT, |
| 378 | WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL, |
| 379 | WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED, |
| 380 | PixelFormat.TRANSLUCENT); |
| 381 | lp.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS; |
| 382 | lp.setTitle("FingerprintDialogView"); |
| 383 | lp.token = mWindowToken; |
| 384 | return lp; |
| 385 | } |
| 386 | } |