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 | |
Kevin Chyn | e927566 | 2018-07-23 16:42:06 -0700 | [diff] [blame] | 17 | package com.android.systemui.biometrics; |
Kevin Chyn | 42653e8 | 2018-01-19 14:15:46 -0800 | [diff] [blame] | 18 | |
joshmccloskey | 6cf1277 | 2019-05-30 17:09:40 -0700 | [diff] [blame] | 19 | import static android.view.accessibility.AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE; |
| 20 | |
Kevin Chyn | 1b9f8df | 2018-11-12 19:04:55 -0800 | [diff] [blame] | 21 | import android.app.admin.DevicePolicyManager; |
Kevin Chyn | 42653e8 | 2018-01-19 14:15:46 -0800 | [diff] [blame] | 22 | import android.content.Context; |
Kevin Chyn | 42653e8 | 2018-01-19 14:15:46 -0800 | [diff] [blame] | 23 | import android.graphics.PixelFormat; |
Kevin Chyn | 1b9f8df | 2018-11-12 19:04:55 -0800 | [diff] [blame] | 24 | import android.graphics.PorterDuff; |
| 25 | import android.graphics.drawable.Drawable; |
Vishwath Mohan | ecf00ce | 2018-04-05 10:28:24 -0700 | [diff] [blame] | 26 | import android.hardware.biometrics.BiometricPrompt; |
Kevin Chyn | 42653e8 | 2018-01-19 14:15:46 -0800 | [diff] [blame] | 27 | import android.os.Binder; |
| 28 | import android.os.Bundle; |
| 29 | import android.os.Handler; |
| 30 | import android.os.IBinder; |
Kevin Chyn | 5906c17 | 2018-07-23 15:43:02 -0700 | [diff] [blame] | 31 | import android.os.Message; |
Kevin Chyn | 1b9f8df | 2018-11-12 19:04:55 -0800 | [diff] [blame] | 32 | import android.os.UserManager; |
Kevin Chyn | a4596f3 | 2018-04-05 11:33:12 -0700 | [diff] [blame] | 33 | import android.text.TextUtils; |
Kevin Chyn | 27ce194 | 2018-03-12 14:42:17 -0700 | [diff] [blame] | 34 | import android.util.DisplayMetrics; |
Kevin Chyn | d0544dc | 2018-02-06 16:30:31 -0800 | [diff] [blame] | 35 | import android.util.Log; |
Kevin Chyn | 42653e8 | 2018-01-19 14:15:46 -0800 | [diff] [blame] | 36 | import android.view.KeyEvent; |
| 37 | import android.view.LayoutInflater; |
Kevin Chyn | 42653e8 | 2018-01-19 14:15:46 -0800 | [diff] [blame] | 38 | import android.view.View; |
| 39 | import android.view.ViewGroup; |
Kevin Chyn | 42653e8 | 2018-01-19 14:15:46 -0800 | [diff] [blame] | 40 | import android.view.WindowManager; |
joshmccloskey | 6cf1277 | 2019-05-30 17:09:40 -0700 | [diff] [blame] | 41 | import android.view.accessibility.AccessibilityEvent; |
Kevin Chyn | 791f1dd | 2019-06-05 14:03:26 -0700 | [diff] [blame] | 42 | import android.view.accessibility.AccessibilityManager; |
Kevin Chyn | 42653e8 | 2018-01-19 14:15:46 -0800 | [diff] [blame] | 43 | import android.view.animation.Interpolator; |
| 44 | import android.widget.Button; |
Kevin Chyn | 6cf54e8 | 2018-09-18 19:13:27 -0700 | [diff] [blame] | 45 | import android.widget.ImageView; |
Kevin Chyn | 42653e8 | 2018-01-19 14:15:46 -0800 | [diff] [blame] | 46 | import android.widget.LinearLayout; |
| 47 | import android.widget.TextView; |
| 48 | |
Kevin Chyn | e8f3e1b | 2018-01-23 17:33:58 -0800 | [diff] [blame] | 49 | import com.android.systemui.Interpolators; |
Kevin Chyn | 42653e8 | 2018-01-19 14:15:46 -0800 | [diff] [blame] | 50 | import com.android.systemui.R; |
Kevin Chyn | bb26914 | 2018-11-07 19:31:51 -0800 | [diff] [blame] | 51 | import com.android.systemui.util.leak.RotationUtils; |
Kevin Chyn | 42653e8 | 2018-01-19 14:15:46 -0800 | [diff] [blame] | 52 | |
| 53 | /** |
Kevin Chyn | 0be1f33 | 2018-09-18 18:15:16 -0700 | [diff] [blame] | 54 | * Abstract base class. Shows a dialog for BiometricPrompt. |
Kevin Chyn | 42653e8 | 2018-01-19 14:15:46 -0800 | [diff] [blame] | 55 | */ |
Kevin Chyn | 0be1f33 | 2018-09-18 18:15:16 -0700 | [diff] [blame] | 56 | public abstract class BiometricDialogView extends LinearLayout { |
Kevin Chyn | 42653e8 | 2018-01-19 14:15:46 -0800 | [diff] [blame] | 57 | |
Kevin Chyn | a883fb5 | 2018-09-18 18:23:22 -0700 | [diff] [blame] | 58 | private static final String TAG = "BiometricDialogView"; |
Kevin Chyn | 42653e8 | 2018-01-19 14:15:46 -0800 | [diff] [blame] | 59 | |
Kevin Chyn | e191271 | 2019-01-04 14:22:34 -0800 | [diff] [blame] | 60 | private static final String KEY_TRY_AGAIN_VISIBILITY = "key_try_again_visibility"; |
| 61 | private static final String KEY_CONFIRM_VISIBILITY = "key_confirm_visibility"; |
Kevin Chyn | d4e0b3b | 2019-06-19 13:26:31 -0700 | [diff] [blame] | 62 | private static final String KEY_CONFIRM_ENABLED = "key_confirm_enabled"; |
Kevin Chyn | 8cfd7a4 | 2019-05-07 20:22:31 -0700 | [diff] [blame] | 63 | private static final String KEY_STATE = "key_state"; |
| 64 | private static final String KEY_ERROR_TEXT_VISIBILITY = "key_error_text_visibility"; |
| 65 | private static final String KEY_ERROR_TEXT_STRING = "key_error_text_string"; |
| 66 | private static final String KEY_ERROR_TEXT_IS_TEMPORARY = "key_error_text_is_temporary"; |
| 67 | private static final String KEY_ERROR_TEXT_COLOR = "key_error_text_color"; |
Kevin Chyn | e191271 | 2019-01-04 14:22:34 -0800 | [diff] [blame] | 68 | |
Kevin Chyn | dba919a | 2018-03-16 14:35:10 -0700 | [diff] [blame] | 69 | private static final int ANIMATION_DURATION_SHOW = 250; // ms |
| 70 | private static final int ANIMATION_DURATION_AWAY = 350; // ms |
Kevin Chyn | 42653e8 | 2018-01-19 14:15:46 -0800 | [diff] [blame] | 71 | |
Kevin Chyn | 8cfd7a4 | 2019-05-07 20:22:31 -0700 | [diff] [blame] | 72 | protected static final int MSG_RESET_MESSAGE = 1; |
Kevin Chyn | 5906c17 | 2018-07-23 15:43:02 -0700 | [diff] [blame] | 73 | |
Kevin Chyn | e191271 | 2019-01-04 14:22:34 -0800 | [diff] [blame] | 74 | protected static final int STATE_IDLE = 0; |
Kevin Chyn | 0be1f33 | 2018-09-18 18:15:16 -0700 | [diff] [blame] | 75 | protected static final int STATE_AUTHENTICATING = 1; |
| 76 | protected static final int STATE_ERROR = 2; |
Kevin Chyn | 6bb2077 | 2018-12-27 15:14:44 -0800 | [diff] [blame] | 77 | protected static final int STATE_PENDING_CONFIRMATION = 3; |
| 78 | protected static final int STATE_AUTHENTICATED = 4; |
Kevin Chyn | d0544dc | 2018-02-06 16:30:31 -0800 | [diff] [blame] | 79 | |
Kevin Chyn | 791f1dd | 2019-06-05 14:03:26 -0700 | [diff] [blame] | 80 | private final AccessibilityManager mAccessibilityManager; |
Kevin Chyn | 42653e8 | 2018-01-19 14:15:46 -0800 | [diff] [blame] | 81 | private final IBinder mWindowToken = new Binder(); |
Kevin Chyn | 42653e8 | 2018-01-19 14:15:46 -0800 | [diff] [blame] | 82 | private final Interpolator mLinearOutSlowIn; |
Kevin Chyn | 27e1f26 | 2018-03-08 16:38:32 -0800 | [diff] [blame] | 83 | private final WindowManager mWindowManager; |
Kevin Chyn | 1b9f8df | 2018-11-12 19:04:55 -0800 | [diff] [blame] | 84 | private final UserManager mUserManager; |
| 85 | private final DevicePolicyManager mDevicePolicyManager; |
Kevin Chyn | e8f3e1b | 2018-01-23 17:33:58 -0800 | [diff] [blame] | 86 | private final float mAnimationTranslationOffset; |
Kevin Chyn | 178ace5 | 2018-03-30 12:36:32 -0700 | [diff] [blame] | 87 | private final int mErrorColor; |
Kevin Chyn | 02129b1 | 2018-11-01 16:47:12 -0700 | [diff] [blame] | 88 | private final float mDialogWidth; |
Kevin Chyn | 3b53d6f | 2019-05-01 11:49:05 -0700 | [diff] [blame] | 89 | protected final DialogViewCallback mCallback; |
Kevin Chyn | 42653e8 | 2018-01-19 14:15:46 -0800 | [diff] [blame] | 90 | |
Kevin Chyn | e191271 | 2019-01-04 14:22:34 -0800 | [diff] [blame] | 91 | protected final ViewGroup mLayout; |
| 92 | protected final LinearLayout mDialog; |
| 93 | protected final TextView mTitleText; |
| 94 | protected final TextView mSubtitleText; |
| 95 | protected final TextView mDescriptionText; |
| 96 | protected final ImageView mBiometricIcon; |
| 97 | protected final TextView mErrorText; |
| 98 | protected final Button mPositiveButton; |
| 99 | protected final Button mNegativeButton; |
| 100 | protected final Button mTryAgainButton; |
| 101 | |
Kevin Chyn | c9744ac | 2019-01-11 18:49:50 -0800 | [diff] [blame] | 102 | protected final int mTextColor; |
| 103 | |
Kevin Chyn | 42653e8 | 2018-01-19 14:15:46 -0800 | [diff] [blame] | 104 | private Bundle mBundle; |
Kevin Chyn | 30c7608 | 2019-05-07 19:39:44 -0700 | [diff] [blame] | 105 | private Bundle mRestoredState; |
Kevin Chyn | e191271 | 2019-01-04 14:22:34 -0800 | [diff] [blame] | 106 | |
Kevin Chyn | 8cfd7a4 | 2019-05-07 20:22:31 -0700 | [diff] [blame] | 107 | private int mState = STATE_IDLE; |
Kevin Chyn | 87df068 | 2018-04-10 19:29:23 -0700 | [diff] [blame] | 108 | private boolean mAnimatingAway; |
| 109 | private boolean mWasForceRemoved; |
Kevin Chyn | 02129b1 | 2018-11-01 16:47:12 -0700 | [diff] [blame] | 110 | private boolean mSkipIntro; |
Kevin Chyn | 6cf54e8 | 2018-09-18 19:13:27 -0700 | [diff] [blame] | 111 | protected boolean mRequireConfirmation; |
Kevin Chyn | 1b9f8df | 2018-11-12 19:04:55 -0800 | [diff] [blame] | 112 | private int mUserId; // used to determine if we should show work background |
Kevin Chyn | 42653e8 | 2018-01-19 14:15:46 -0800 | [diff] [blame] | 113 | |
Kevin Chyn | 906bde5 | 2019-07-24 18:45:42 -0700 | [diff] [blame] | 114 | private boolean mCompletedAnimatingIn; |
| 115 | private boolean mPendingDismissDialog; |
| 116 | |
Kevin Chyn | 6cf54e8 | 2018-09-18 19:13:27 -0700 | [diff] [blame] | 117 | protected abstract int getHintStringResourceId(); |
| 118 | protected abstract int getAuthenticatedAccessibilityResourceId(); |
| 119 | protected abstract int getIconDescriptionResourceId(); |
Kevin Chyn | 6bb2077 | 2018-12-27 15:14:44 -0800 | [diff] [blame] | 120 | protected abstract int getDelayAfterAuthenticatedDurationMs(); |
Kevin Chyn | e191271 | 2019-01-04 14:22:34 -0800 | [diff] [blame] | 121 | protected abstract boolean shouldGrayAreaDismissDialog(); |
Kevin Chyn | 8cfd7a4 | 2019-05-07 20:22:31 -0700 | [diff] [blame] | 122 | protected abstract void handleResetMessage(); |
Kevin Chyn | 3b53d6f | 2019-05-01 11:49:05 -0700 | [diff] [blame] | 123 | protected abstract void updateIcon(int oldState, int newState); |
Kevin Chyn | 0be1f33 | 2018-09-18 18:15:16 -0700 | [diff] [blame] | 124 | |
Kevin Chyn | 87df068 | 2018-04-10 19:29:23 -0700 | [diff] [blame] | 125 | private final Runnable mShowAnimationRunnable = new Runnable() { |
| 126 | @Override |
| 127 | public void run() { |
| 128 | mLayout.animate() |
| 129 | .alpha(1f) |
| 130 | .setDuration(ANIMATION_DURATION_SHOW) |
| 131 | .setInterpolator(mLinearOutSlowIn) |
| 132 | .withLayer() |
| 133 | .start(); |
| 134 | mDialog.animate() |
| 135 | .translationY(0) |
| 136 | .setDuration(ANIMATION_DURATION_SHOW) |
| 137 | .setInterpolator(mLinearOutSlowIn) |
| 138 | .withLayer() |
Kevin Chyn | 3b53d6f | 2019-05-01 11:49:05 -0700 | [diff] [blame] | 139 | .withEndAction(() -> onDialogAnimatedIn()) |
Kevin Chyn | 87df068 | 2018-04-10 19:29:23 -0700 | [diff] [blame] | 140 | .start(); |
| 141 | } |
| 142 | }; |
| 143 | |
Kevin Chyn | 3b53d6f | 2019-05-01 11:49:05 -0700 | [diff] [blame] | 144 | protected Handler mHandler = new Handler() { |
Kevin Chyn | 5906c17 | 2018-07-23 15:43:02 -0700 | [diff] [blame] | 145 | @Override |
| 146 | public void handleMessage(Message msg) { |
| 147 | switch(msg.what) { |
Kevin Chyn | 8cfd7a4 | 2019-05-07 20:22:31 -0700 | [diff] [blame] | 148 | case MSG_RESET_MESSAGE: |
| 149 | handleResetMessage(); |
Kevin Chyn | 5906c17 | 2018-07-23 15:43:02 -0700 | [diff] [blame] | 150 | break; |
| 151 | default: |
| 152 | Log.e(TAG, "Unhandled message: " + msg.what); |
| 153 | break; |
| 154 | } |
| 155 | } |
| 156 | }; |
| 157 | |
Kevin Chyn | a883fb5 | 2018-09-18 18:23:22 -0700 | [diff] [blame] | 158 | public BiometricDialogView(Context context, DialogViewCallback callback) { |
Kevin Chyn | 42653e8 | 2018-01-19 14:15:46 -0800 | [diff] [blame] | 159 | super(context); |
Kevin Chyn | 5906c17 | 2018-07-23 15:43:02 -0700 | [diff] [blame] | 160 | mCallback = callback; |
Kevin Chyn | e8f3e1b | 2018-01-23 17:33:58 -0800 | [diff] [blame] | 161 | mLinearOutSlowIn = Interpolators.LINEAR_OUT_SLOW_IN; |
Kevin Chyn | 791f1dd | 2019-06-05 14:03:26 -0700 | [diff] [blame] | 162 | mAccessibilityManager = mContext.getSystemService(AccessibilityManager.class); |
Kevin Chyn | 1b9f8df | 2018-11-12 19:04:55 -0800 | [diff] [blame] | 163 | mWindowManager = mContext.getSystemService(WindowManager.class); |
| 164 | mUserManager = mContext.getSystemService(UserManager.class); |
| 165 | mDevicePolicyManager = mContext.getSystemService(DevicePolicyManager.class); |
Kevin Chyn | 6cf54e8 | 2018-09-18 19:13:27 -0700 | [diff] [blame] | 166 | mAnimationTranslationOffset = getResources() |
| 167 | .getDimension(R.dimen.biometric_dialog_animation_translation_offset); |
Kevin Chyn | 7f93a58 | 2019-05-07 19:15:52 -0700 | [diff] [blame] | 168 | mErrorColor = getResources().getColor(R.color.biometric_dialog_error); |
| 169 | mTextColor = getResources().getColor(R.color.biometric_dialog_gray); |
Kevin Chyn | 42653e8 | 2018-01-19 14:15:46 -0800 | [diff] [blame] | 170 | |
Kevin Chyn | 27ce194 | 2018-03-12 14:42:17 -0700 | [diff] [blame] | 171 | DisplayMetrics metrics = new DisplayMetrics(); |
| 172 | mWindowManager.getDefaultDisplay().getMetrics(metrics); |
Kevin Chyn | 02129b1 | 2018-11-01 16:47:12 -0700 | [diff] [blame] | 173 | mDialogWidth = Math.min(metrics.widthPixels, metrics.heightPixels); |
Kevin Chyn | 27ce194 | 2018-03-12 14:42:17 -0700 | [diff] [blame] | 174 | |
Kevin Chyn | 42653e8 | 2018-01-19 14:15:46 -0800 | [diff] [blame] | 175 | // Create the dialog |
| 176 | LayoutInflater factory = LayoutInflater.from(getContext()); |
Kevin Chyn | 6cf54e8 | 2018-09-18 19:13:27 -0700 | [diff] [blame] | 177 | mLayout = (ViewGroup) factory.inflate(R.layout.biometric_dialog, this, false); |
Kevin Chyn | 42653e8 | 2018-01-19 14:15:46 -0800 | [diff] [blame] | 178 | addView(mLayout); |
| 179 | |
Kevin Chyn | 42653e8 | 2018-01-19 14:15:46 -0800 | [diff] [blame] | 180 | mLayout.setOnKeyListener(new View.OnKeyListener() { |
| 181 | boolean downPressed = false; |
| 182 | @Override |
| 183 | public boolean onKey(View v, int keyCode, KeyEvent event) { |
| 184 | if (keyCode != KeyEvent.KEYCODE_BACK) { |
| 185 | return false; |
| 186 | } |
| 187 | if (event.getAction() == KeyEvent.ACTION_DOWN && downPressed == false) { |
| 188 | downPressed = true; |
| 189 | } else if (event.getAction() == KeyEvent.ACTION_DOWN) { |
| 190 | downPressed = false; |
| 191 | } else if (event.getAction() == KeyEvent.ACTION_UP && downPressed == true) { |
| 192 | downPressed = false; |
Kevin Chyn | 5906c17 | 2018-07-23 15:43:02 -0700 | [diff] [blame] | 193 | mCallback.onUserCanceled(); |
Kevin Chyn | 42653e8 | 2018-01-19 14:15:46 -0800 | [diff] [blame] | 194 | } |
| 195 | return true; |
| 196 | } |
| 197 | }); |
| 198 | |
| 199 | final View space = mLayout.findViewById(R.id.space); |
Kevin Chyn | 27ce194 | 2018-03-12 14:42:17 -0700 | [diff] [blame] | 200 | final View leftSpace = mLayout.findViewById(R.id.left_space); |
| 201 | final View rightSpace = mLayout.findViewById(R.id.right_space); |
Kevin Chyn | e191271 | 2019-01-04 14:22:34 -0800 | [diff] [blame] | 202 | |
| 203 | mDialog = mLayout.findViewById(R.id.dialog); |
| 204 | mTitleText = mLayout.findViewById(R.id.title); |
| 205 | mSubtitleText = mLayout.findViewById(R.id.subtitle); |
| 206 | mDescriptionText = mLayout.findViewById(R.id.description); |
| 207 | mBiometricIcon = mLayout.findViewById(R.id.biometric_icon); |
| 208 | mErrorText = mLayout.findViewById(R.id.error); |
Kevin Chyn | 6bb2077 | 2018-12-27 15:14:44 -0800 | [diff] [blame] | 209 | mNegativeButton = mLayout.findViewById(R.id.button2); |
| 210 | mPositiveButton = mLayout.findViewById(R.id.button1); |
Kevin Chyn | e191271 | 2019-01-04 14:22:34 -0800 | [diff] [blame] | 211 | mTryAgainButton = mLayout.findViewById(R.id.button_try_again); |
Kevin Chyn | 6cf54e8 | 2018-09-18 19:13:27 -0700 | [diff] [blame] | 212 | |
Kevin Chyn | e191271 | 2019-01-04 14:22:34 -0800 | [diff] [blame] | 213 | mBiometricIcon.setContentDescription( |
| 214 | getResources().getString(getIconDescriptionResourceId())); |
Kevin Chyn | 42653e8 | 2018-01-19 14:15:46 -0800 | [diff] [blame] | 215 | |
Kevin Chyn | 27ce194 | 2018-03-12 14:42:17 -0700 | [diff] [blame] | 216 | setDismissesDialog(space); |
| 217 | setDismissesDialog(leftSpace); |
| 218 | setDismissesDialog(rightSpace); |
Kevin Chyn | 42653e8 | 2018-01-19 14:15:46 -0800 | [diff] [blame] | 219 | |
Kevin Chyn | 6bb2077 | 2018-12-27 15:14:44 -0800 | [diff] [blame] | 220 | mNegativeButton.setOnClickListener((View v) -> { |
Kevin Chyn | 078dcf1 | 2019-04-26 11:14:20 -0700 | [diff] [blame] | 221 | if (mState == STATE_PENDING_CONFIRMATION || mState == STATE_AUTHENTICATED) { |
| 222 | mCallback.onUserCanceled(); |
| 223 | } else { |
| 224 | mCallback.onNegativePressed(); |
| 225 | } |
Kevin Chyn | 42653e8 | 2018-01-19 14:15:46 -0800 | [diff] [blame] | 226 | }); |
| 227 | |
Kevin Chyn | 6bb2077 | 2018-12-27 15:14:44 -0800 | [diff] [blame] | 228 | mPositiveButton.setOnClickListener((View v) -> { |
| 229 | updateState(STATE_AUTHENTICATED); |
| 230 | mHandler.postDelayed(() -> { |
| 231 | mCallback.onPositivePressed(); |
| 232 | }, getDelayAfterAuthenticatedDurationMs()); |
Kevin Chyn | 42653e8 | 2018-01-19 14:15:46 -0800 | [diff] [blame] | 233 | }); |
| 234 | |
Kevin Chyn | e191271 | 2019-01-04 14:22:34 -0800 | [diff] [blame] | 235 | mTryAgainButton.setOnClickListener((View v) -> { |
Kevin Chyn | bb79c00 | 2019-05-14 12:53:20 -0700 | [diff] [blame] | 236 | handleResetMessage(); |
Kevin Chyn | 3b53d6f | 2019-05-01 11:49:05 -0700 | [diff] [blame] | 237 | updateState(STATE_AUTHENTICATING); |
Kevin Chyn | 23289ef | 2018-11-28 16:32:36 -0800 | [diff] [blame] | 238 | showTryAgainButton(false /* show */); |
Kevin Chyn | d4e0b3b | 2019-06-19 13:26:31 -0700 | [diff] [blame] | 239 | |
| 240 | mPositiveButton.setVisibility(View.VISIBLE); |
| 241 | mPositiveButton.setEnabled(false); |
| 242 | |
Kevin Chyn | 23289ef | 2018-11-28 16:32:36 -0800 | [diff] [blame] | 243 | mCallback.onTryAgainPressed(); |
| 244 | }); |
Kevin Chyn | d1cdc3a | 2019-06-05 13:43:58 -0700 | [diff] [blame] | 245 | |
| 246 | // Must set these in order for the back button events to be received. |
| 247 | mLayout.setFocusableInTouchMode(true); |
| 248 | mLayout.requestFocus(); |
Kevin Chyn | 42653e8 | 2018-01-19 14:15:46 -0800 | [diff] [blame] | 249 | } |
| 250 | |
Kevin Chyn | e191271 | 2019-01-04 14:22:34 -0800 | [diff] [blame] | 251 | public void onSaveState(Bundle bundle) { |
| 252 | bundle.putInt(KEY_TRY_AGAIN_VISIBILITY, mTryAgainButton.getVisibility()); |
| 253 | bundle.putInt(KEY_CONFIRM_VISIBILITY, mPositiveButton.getVisibility()); |
Kevin Chyn | d4e0b3b | 2019-06-19 13:26:31 -0700 | [diff] [blame] | 254 | bundle.putBoolean(KEY_CONFIRM_ENABLED, mPositiveButton.isEnabled()); |
Kevin Chyn | 8cfd7a4 | 2019-05-07 20:22:31 -0700 | [diff] [blame] | 255 | bundle.putInt(KEY_STATE, mState); |
| 256 | bundle.putInt(KEY_ERROR_TEXT_VISIBILITY, mErrorText.getVisibility()); |
| 257 | bundle.putCharSequence(KEY_ERROR_TEXT_STRING, mErrorText.getText()); |
| 258 | bundle.putBoolean(KEY_ERROR_TEXT_IS_TEMPORARY, mHandler.hasMessages(MSG_RESET_MESSAGE)); |
| 259 | bundle.putInt(KEY_ERROR_TEXT_COLOR, mErrorText.getCurrentTextColor()); |
Kevin Chyn | e191271 | 2019-01-04 14:22:34 -0800 | [diff] [blame] | 260 | } |
| 261 | |
Kevin Chyn | 42653e8 | 2018-01-19 14:15:46 -0800 | [diff] [blame] | 262 | @Override |
| 263 | public void onAttachedToWindow() { |
| 264 | super.onAttachedToWindow(); |
| 265 | |
Kevin Chyn | 1b9f8df | 2018-11-12 19:04:55 -0800 | [diff] [blame] | 266 | final ImageView backgroundView = mLayout.findViewById(R.id.background); |
| 267 | |
| 268 | if (mUserManager.isManagedProfile(mUserId)) { |
| 269 | final Drawable image = getResources().getDrawable(R.drawable.work_challenge_background, |
| 270 | mContext.getTheme()); |
| 271 | image.setColorFilter(mDevicePolicyManager.getOrganizationColorForUser(mUserId), |
| 272 | PorterDuff.Mode.DARKEN); |
Kevin Chyn | b4523b3 | 2019-06-21 14:16:20 -0700 | [diff] [blame] | 273 | backgroundView.setScaleType(ImageView.ScaleType.CENTER_CROP); |
Kevin Chyn | 1b9f8df | 2018-11-12 19:04:55 -0800 | [diff] [blame] | 274 | backgroundView.setImageDrawable(image); |
| 275 | } else { |
| 276 | backgroundView.setImageDrawable(null); |
| 277 | backgroundView.setBackgroundColor(R.color.biometric_dialog_dim_color); |
| 278 | } |
Kevin Chyn | d0544dc | 2018-02-06 16:30:31 -0800 | [diff] [blame] | 279 | |
Kevin Chyn | 6bb2077 | 2018-12-27 15:14:44 -0800 | [diff] [blame] | 280 | mNegativeButton.setVisibility(View.VISIBLE); |
Kevin Chyn | 6bb2077 | 2018-12-27 15:14:44 -0800 | [diff] [blame] | 281 | |
Kevin Chyn | bb26914 | 2018-11-07 19:31:51 -0800 | [diff] [blame] | 282 | if (RotationUtils.getRotation(mContext) != RotationUtils.ROTATION_NONE) { |
| 283 | mDialog.getLayoutParams().width = (int) mDialogWidth; |
| 284 | } |
| 285 | |
Kevin Chyn | 8cfd7a4 | 2019-05-07 20:22:31 -0700 | [diff] [blame] | 286 | if (mRestoredState == null) { |
| 287 | updateState(STATE_AUTHENTICATING); |
joshmccloskey | a1c777e | 2019-07-10 17:15:15 -0700 | [diff] [blame] | 288 | mNegativeButton.setText(mBundle.getCharSequence(BiometricPrompt.KEY_NEGATIVE_TEXT)); |
Kevin Chyn | d4e0b3b | 2019-06-19 13:26:31 -0700 | [diff] [blame] | 289 | final int hint = getHintStringResourceId(); |
| 290 | if (hint != 0) { |
| 291 | mErrorText.setText(hint); |
| 292 | mErrorText.setContentDescription(mContext.getString(hint)); |
| 293 | mErrorText.setVisibility(View.VISIBLE); |
| 294 | } else { |
| 295 | mErrorText.setVisibility(View.INVISIBLE); |
| 296 | } |
| 297 | announceAccessibilityEvent(); |
Kevin Chyn | 8cfd7a4 | 2019-05-07 20:22:31 -0700 | [diff] [blame] | 298 | } else { |
| 299 | updateState(mState); |
| 300 | } |
Kevin Chyn | 42653e8 | 2018-01-19 14:15:46 -0800 | [diff] [blame] | 301 | |
Kevin Chyn | 3a018719 | 2018-10-08 15:40:05 -0700 | [diff] [blame] | 302 | CharSequence titleText = mBundle.getCharSequence(BiometricPrompt.KEY_TITLE); |
| 303 | |
Kevin Chyn | e191271 | 2019-01-04 14:22:34 -0800 | [diff] [blame] | 304 | mTitleText.setVisibility(View.VISIBLE); |
| 305 | mTitleText.setText(titleText); |
Kevin Chyn | dba919a | 2018-03-16 14:35:10 -0700 | [diff] [blame] | 306 | |
Vishwath Mohan | ecf00ce | 2018-04-05 10:28:24 -0700 | [diff] [blame] | 307 | final CharSequence subtitleText = mBundle.getCharSequence(BiometricPrompt.KEY_SUBTITLE); |
Kevin Chyn | a4596f3 | 2018-04-05 11:33:12 -0700 | [diff] [blame] | 308 | if (TextUtils.isEmpty(subtitleText)) { |
Kevin Chyn | e191271 | 2019-01-04 14:22:34 -0800 | [diff] [blame] | 309 | mSubtitleText.setVisibility(View.GONE); |
joshmccloskey | 6cf1277 | 2019-05-30 17:09:40 -0700 | [diff] [blame] | 310 | announceAccessibilityEvent(); |
Kevin Chyn | dba919a | 2018-03-16 14:35:10 -0700 | [diff] [blame] | 311 | } else { |
Kevin Chyn | e191271 | 2019-01-04 14:22:34 -0800 | [diff] [blame] | 312 | mSubtitleText.setVisibility(View.VISIBLE); |
| 313 | mSubtitleText.setText(subtitleText); |
Kevin Chyn | dba919a | 2018-03-16 14:35:10 -0700 | [diff] [blame] | 314 | } |
| 315 | |
Kevin Chyn | 23289ef | 2018-11-28 16:32:36 -0800 | [diff] [blame] | 316 | final CharSequence descriptionText = |
| 317 | mBundle.getCharSequence(BiometricPrompt.KEY_DESCRIPTION); |
Kevin Chyn | a4596f3 | 2018-04-05 11:33:12 -0700 | [diff] [blame] | 318 | if (TextUtils.isEmpty(descriptionText)) { |
Kevin Chyn | e191271 | 2019-01-04 14:22:34 -0800 | [diff] [blame] | 319 | mDescriptionText.setVisibility(View.GONE); |
joshmccloskey | 6cf1277 | 2019-05-30 17:09:40 -0700 | [diff] [blame] | 320 | announceAccessibilityEvent(); |
Kevin Chyn | dba919a | 2018-03-16 14:35:10 -0700 | [diff] [blame] | 321 | } else { |
Kevin Chyn | e191271 | 2019-01-04 14:22:34 -0800 | [diff] [blame] | 322 | mDescriptionText.setVisibility(View.VISIBLE); |
| 323 | mDescriptionText.setText(descriptionText); |
Kevin Chyn | dba919a | 2018-03-16 14:35:10 -0700 | [diff] [blame] | 324 | } |
| 325 | |
Kevin Chyn | 30c7608 | 2019-05-07 19:39:44 -0700 | [diff] [blame] | 326 | if (requiresConfirmation() && mRestoredState == null) { |
Kevin Chyn | 8d39b4e | 2019-04-26 11:02:13 -0700 | [diff] [blame] | 327 | mPositiveButton.setVisibility(View.VISIBLE); |
| 328 | mPositiveButton.setEnabled(false); |
| 329 | } |
| 330 | |
Kevin Chyn | 02129b1 | 2018-11-01 16:47:12 -0700 | [diff] [blame] | 331 | if (mWasForceRemoved || mSkipIntro) { |
Kevin Chyn | 87df068 | 2018-04-10 19:29:23 -0700 | [diff] [blame] | 332 | // Show the dialog immediately |
| 333 | mLayout.animate().cancel(); |
| 334 | mDialog.animate().cancel(); |
| 335 | mDialog.setAlpha(1.0f); |
| 336 | mDialog.setTranslationY(0); |
| 337 | mLayout.setAlpha(1.0f); |
Kevin Chyn | 906bde5 | 2019-07-24 18:45:42 -0700 | [diff] [blame] | 338 | mCompletedAnimatingIn = true; |
Kevin Chyn | 02129b1 | 2018-11-01 16:47:12 -0700 | [diff] [blame] | 339 | } else { |
| 340 | // Dim the background and slide the dialog up |
| 341 | mDialog.setTranslationY(mAnimationTranslationOffset); |
| 342 | mLayout.setAlpha(0f); |
| 343 | postOnAnimation(mShowAnimationRunnable); |
Kevin Chyn | 87df068 | 2018-04-10 19:29:23 -0700 | [diff] [blame] | 344 | } |
| 345 | mWasForceRemoved = false; |
Kevin Chyn | 02129b1 | 2018-11-01 16:47:12 -0700 | [diff] [blame] | 346 | mSkipIntro = false; |
Kevin Chyn | 42653e8 | 2018-01-19 14:15:46 -0800 | [diff] [blame] | 347 | } |
| 348 | |
Kevin Chyn | 27ce194 | 2018-03-12 14:42:17 -0700 | [diff] [blame] | 349 | private void setDismissesDialog(View v) { |
| 350 | v.setClickable(true); |
Kevin Chyn | 8ab1de6 | 2019-05-14 12:19:07 -0700 | [diff] [blame] | 351 | v.setOnClickListener(v1 -> { |
Kevin Chyn | 078dcf1 | 2019-04-26 11:14:20 -0700 | [diff] [blame] | 352 | if (mState != STATE_AUTHENTICATED && shouldGrayAreaDismissDialog()) { |
Kevin Chyn | 6bb2077 | 2018-12-27 15:14:44 -0800 | [diff] [blame] | 353 | mCallback.onUserCanceled(); |
| 354 | } |
Kevin Chyn | 27ce194 | 2018-03-12 14:42:17 -0700 | [diff] [blame] | 355 | }); |
| 356 | } |
| 357 | |
Kevin Chyn | 27e1f26 | 2018-03-08 16:38:32 -0800 | [diff] [blame] | 358 | public void startDismiss() { |
Kevin Chyn | 906bde5 | 2019-07-24 18:45:42 -0700 | [diff] [blame] | 359 | if (!mCompletedAnimatingIn) { |
| 360 | Log.w(TAG, "startDismiss(): waiting for onDialogAnimatedIn"); |
| 361 | mPendingDismissDialog = true; |
| 362 | return; |
| 363 | } |
| 364 | |
Kevin Chyn | 87df068 | 2018-04-10 19:29:23 -0700 | [diff] [blame] | 365 | mAnimatingAway = true; |
| 366 | |
Kevin Chyn | 23289ef | 2018-11-28 16:32:36 -0800 | [diff] [blame] | 367 | // This is where final cleanup should occur. |
Kevin Chyn | 27e1f26 | 2018-03-08 16:38:32 -0800 | [diff] [blame] | 368 | final Runnable endActionRunnable = new Runnable() { |
| 369 | @Override |
| 370 | public void run() { |
Kevin Chyn | a883fb5 | 2018-09-18 18:23:22 -0700 | [diff] [blame] | 371 | mWindowManager.removeView(BiometricDialogView.this); |
Kevin Chyn | 87df068 | 2018-04-10 19:29:23 -0700 | [diff] [blame] | 372 | mAnimatingAway = false; |
Kevin Chyn | 87f257a | 2018-11-27 16:26:07 -0800 | [diff] [blame] | 373 | // Set the icons / text back to normal state |
Kevin Chyn | 8cfd7a4 | 2019-05-07 20:22:31 -0700 | [diff] [blame] | 374 | handleResetMessage(); |
Kevin Chyn | 23289ef | 2018-11-28 16:32:36 -0800 | [diff] [blame] | 375 | showTryAgainButton(false /* show */); |
Kevin Chyn | e191271 | 2019-01-04 14:22:34 -0800 | [diff] [blame] | 376 | updateState(STATE_IDLE); |
Kevin Chyn | 27e1f26 | 2018-03-08 16:38:32 -0800 | [diff] [blame] | 377 | } |
| 378 | }; |
| 379 | |
| 380 | postOnAnimation(new Runnable() { |
| 381 | @Override |
| 382 | public void run() { |
| 383 | mLayout.animate() |
| 384 | .alpha(0f) |
Kevin Chyn | dba919a | 2018-03-16 14:35:10 -0700 | [diff] [blame] | 385 | .setDuration(ANIMATION_DURATION_AWAY) |
Kevin Chyn | 27e1f26 | 2018-03-08 16:38:32 -0800 | [diff] [blame] | 386 | .setInterpolator(mLinearOutSlowIn) |
| 387 | .withLayer() |
| 388 | .start(); |
| 389 | mDialog.animate() |
| 390 | .translationY(mAnimationTranslationOffset) |
Kevin Chyn | dba919a | 2018-03-16 14:35:10 -0700 | [diff] [blame] | 391 | .setDuration(ANIMATION_DURATION_AWAY) |
Kevin Chyn | 27e1f26 | 2018-03-08 16:38:32 -0800 | [diff] [blame] | 392 | .setInterpolator(mLinearOutSlowIn) |
| 393 | .withLayer() |
| 394 | .withEndAction(endActionRunnable) |
| 395 | .start(); |
| 396 | } |
| 397 | }); |
| 398 | } |
| 399 | |
Kevin Chyn | 87df068 | 2018-04-10 19:29:23 -0700 | [diff] [blame] | 400 | /** |
| 401 | * Force remove the window, cancelling any animation that's happening. This should only be |
| 402 | * called if we want to quickly show the dialog again (e.g. on rotation). Calling this method |
| 403 | * will cause the dialog to show without an animation the next time it's attached. |
| 404 | */ |
| 405 | public void forceRemove() { |
| 406 | mLayout.animate().cancel(); |
| 407 | mDialog.animate().cancel(); |
Kevin Chyn | a883fb5 | 2018-09-18 18:23:22 -0700 | [diff] [blame] | 408 | mWindowManager.removeView(BiometricDialogView.this); |
Kevin Chyn | 87df068 | 2018-04-10 19:29:23 -0700 | [diff] [blame] | 409 | mAnimatingAway = false; |
| 410 | mWasForceRemoved = true; |
| 411 | } |
| 412 | |
Kevin Chyn | 02129b1 | 2018-11-01 16:47:12 -0700 | [diff] [blame] | 413 | /** |
| 414 | * Skip the intro animation |
| 415 | */ |
| 416 | public void setSkipIntro(boolean skip) { |
| 417 | mSkipIntro = skip; |
| 418 | } |
| 419 | |
Kevin Chyn | 87df068 | 2018-04-10 19:29:23 -0700 | [diff] [blame] | 420 | public boolean isAnimatingAway() { |
| 421 | return mAnimatingAway; |
| 422 | } |
| 423 | |
Kevin Chyn | 42653e8 | 2018-01-19 14:15:46 -0800 | [diff] [blame] | 424 | public void setBundle(Bundle bundle) { |
| 425 | mBundle = bundle; |
| 426 | } |
| 427 | |
Kevin Chyn | 6cf54e8 | 2018-09-18 19:13:27 -0700 | [diff] [blame] | 428 | public void setRequireConfirmation(boolean requireConfirmation) { |
| 429 | mRequireConfirmation = requireConfirmation; |
| 430 | } |
| 431 | |
| 432 | public boolean requiresConfirmation() { |
| 433 | return mRequireConfirmation; |
| 434 | } |
| 435 | |
Kevin Chyn | 1b9f8df | 2018-11-12 19:04:55 -0800 | [diff] [blame] | 436 | public void setUserId(int userId) { |
| 437 | mUserId = userId; |
| 438 | } |
| 439 | |
Kevin Chyn | 0be1f33 | 2018-09-18 18:15:16 -0700 | [diff] [blame] | 440 | public ViewGroup getLayout() { |
| 441 | return mLayout; |
| 442 | } |
| 443 | |
Kevin Chyn | d0544dc | 2018-02-06 16:30:31 -0800 | [diff] [blame] | 444 | // Shows an error/help message |
Kevin Chyn | 3b53d6f | 2019-05-01 11:49:05 -0700 | [diff] [blame] | 445 | protected void showTemporaryMessage(String message) { |
Kevin Chyn | 8cfd7a4 | 2019-05-07 20:22:31 -0700 | [diff] [blame] | 446 | mHandler.removeMessages(MSG_RESET_MESSAGE); |
Kevin Chyn | 42653e8 | 2018-01-19 14:15:46 -0800 | [diff] [blame] | 447 | mErrorText.setText(message); |
Kevin Chyn | 178ace5 | 2018-03-30 12:36:32 -0700 | [diff] [blame] | 448 | mErrorText.setTextColor(mErrorColor); |
Kevin Chyn | 16aac7a | 2018-01-24 11:32:46 -0800 | [diff] [blame] | 449 | mErrorText.setContentDescription(message); |
Kevin Chyn | d4e0b3b | 2019-06-19 13:26:31 -0700 | [diff] [blame] | 450 | mErrorText.setVisibility(View.VISIBLE); |
Kevin Chyn | 8cfd7a4 | 2019-05-07 20:22:31 -0700 | [diff] [blame] | 451 | mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_RESET_MESSAGE), |
Vishwath Mohan | ecf00ce | 2018-04-05 10:28:24 -0700 | [diff] [blame] | 452 | BiometricPrompt.HIDE_DIALOG_DELAY); |
Kevin Chyn | 42653e8 | 2018-01-19 14:15:46 -0800 | [diff] [blame] | 453 | } |
| 454 | |
Kevin Chyn | 3b53d6f | 2019-05-01 11:49:05 -0700 | [diff] [blame] | 455 | /** |
| 456 | * Transient help message (acquire) is received, dialog stays showing. Sensor stays in |
| 457 | * "authenticating" state. |
| 458 | * @param message |
| 459 | */ |
| 460 | public void onHelpReceived(String message) { |
| 461 | updateState(STATE_ERROR); |
| 462 | showTemporaryMessage(message); |
Kevin Chyn | 42653e8 | 2018-01-19 14:15:46 -0800 | [diff] [blame] | 463 | } |
| 464 | |
Kevin Chyn | 3b53d6f | 2019-05-01 11:49:05 -0700 | [diff] [blame] | 465 | public void onAuthenticationFailed(String message) { |
| 466 | updateState(STATE_ERROR); |
| 467 | showTemporaryMessage(message); |
| 468 | } |
| 469 | |
| 470 | /** |
| 471 | * Hard error is received, dialog will be dismissed soon. |
| 472 | * @param error |
| 473 | */ |
| 474 | public void onErrorReceived(String error) { |
| 475 | updateState(STATE_ERROR); |
| 476 | showTemporaryMessage(error); |
Kevin Chyn | 23289ef | 2018-11-28 16:32:36 -0800 | [diff] [blame] | 477 | showTryAgainButton(false /* show */); |
Kevin Chyn | 3b53d6f | 2019-05-01 11:49:05 -0700 | [diff] [blame] | 478 | mCallback.onErrorShown(); // TODO: Split between fp and face |
Kevin Chyn | 42653e8 | 2018-01-19 14:15:46 -0800 | [diff] [blame] | 479 | } |
| 480 | |
Kevin Chyn | 6bb2077 | 2018-12-27 15:14:44 -0800 | [diff] [blame] | 481 | public void updateState(int newState) { |
| 482 | if (newState == STATE_PENDING_CONFIRMATION) { |
Kevin Chyn | 8cfd7a4 | 2019-05-07 20:22:31 -0700 | [diff] [blame] | 483 | mHandler.removeMessages(MSG_RESET_MESSAGE); |
Kevin Chyn | d4e0b3b | 2019-06-19 13:26:31 -0700 | [diff] [blame] | 484 | mErrorText.setTextColor(mTextColor); |
| 485 | mErrorText.setText(R.string.biometric_dialog_tap_confirm); |
joshmccloskey | a1c777e | 2019-07-10 17:15:15 -0700 | [diff] [blame] | 486 | mErrorText.setContentDescription( |
| 487 | getResources().getString(R.string.biometric_dialog_tap_confirm)); |
Kevin Chyn | d4e0b3b | 2019-06-19 13:26:31 -0700 | [diff] [blame] | 488 | mErrorText.setVisibility(View.VISIBLE); |
joshmccloskey | 6cf1277 | 2019-05-30 17:09:40 -0700 | [diff] [blame] | 489 | announceAccessibilityEvent(); |
Kevin Chyn | 30c7608 | 2019-05-07 19:39:44 -0700 | [diff] [blame] | 490 | mPositiveButton.setVisibility(View.VISIBLE); |
Kevin Chyn | 078dcf1 | 2019-04-26 11:14:20 -0700 | [diff] [blame] | 491 | mPositiveButton.setEnabled(true); |
Kevin Chyn | 6bb2077 | 2018-12-27 15:14:44 -0800 | [diff] [blame] | 492 | } else if (newState == STATE_AUTHENTICATED) { |
| 493 | mPositiveButton.setVisibility(View.GONE); |
| 494 | mNegativeButton.setVisibility(View.GONE); |
| 495 | mErrorText.setVisibility(View.INVISIBLE); |
joshmccloskey | 6cf1277 | 2019-05-30 17:09:40 -0700 | [diff] [blame] | 496 | announceAccessibilityEvent(); |
Kevin Chyn | 6bb2077 | 2018-12-27 15:14:44 -0800 | [diff] [blame] | 497 | } |
| 498 | |
Kevin Chyn | 078dcf1 | 2019-04-26 11:14:20 -0700 | [diff] [blame] | 499 | if (newState == STATE_PENDING_CONFIRMATION || newState == STATE_AUTHENTICATED) { |
| 500 | mNegativeButton.setText(R.string.cancel); |
joshmccloskey | a1c777e | 2019-07-10 17:15:15 -0700 | [diff] [blame] | 501 | mNegativeButton.setContentDescription(getResources().getString(R.string.cancel)); |
Kevin Chyn | 078dcf1 | 2019-04-26 11:14:20 -0700 | [diff] [blame] | 502 | } |
| 503 | |
| 504 | updateIcon(mState, newState); |
| 505 | mState = newState; |
Kevin Chyn | d0544dc | 2018-02-06 16:30:31 -0800 | [diff] [blame] | 506 | } |
| 507 | |
Kevin Chyn | 23289ef | 2018-11-28 16:32:36 -0800 | [diff] [blame] | 508 | public void showTryAgainButton(boolean show) { |
Kevin Chyn | 23289ef | 2018-11-28 16:32:36 -0800 | [diff] [blame] | 509 | } |
| 510 | |
Kevin Chyn | 3b53d6f | 2019-05-01 11:49:05 -0700 | [diff] [blame] | 511 | public void onDialogAnimatedIn() { |
Kevin Chyn | 906bde5 | 2019-07-24 18:45:42 -0700 | [diff] [blame] | 512 | mCompletedAnimatingIn = true; |
| 513 | |
| 514 | if (mPendingDismissDialog) { |
| 515 | Log.d(TAG, "onDialogAnimatedIn(): mPendingDismissDialog=true, dismissing now"); |
| 516 | startDismiss(); |
| 517 | mPendingDismissDialog = false; |
| 518 | } |
Kevin Chyn | 3b53d6f | 2019-05-01 11:49:05 -0700 | [diff] [blame] | 519 | } |
| 520 | |
Kevin Chyn | e191271 | 2019-01-04 14:22:34 -0800 | [diff] [blame] | 521 | public void restoreState(Bundle bundle) { |
Kevin Chyn | 30c7608 | 2019-05-07 19:39:44 -0700 | [diff] [blame] | 522 | mRestoredState = bundle; |
joshmccloskey | 6cf1277 | 2019-05-30 17:09:40 -0700 | [diff] [blame] | 523 | final int tryAgainVisibility = bundle.getInt(KEY_TRY_AGAIN_VISIBILITY); |
| 524 | mTryAgainButton.setVisibility(tryAgainVisibility); |
| 525 | final int confirmVisibility = bundle.getInt(KEY_CONFIRM_VISIBILITY); |
| 526 | mPositiveButton.setVisibility(confirmVisibility); |
Kevin Chyn | d4e0b3b | 2019-06-19 13:26:31 -0700 | [diff] [blame] | 527 | final boolean confirmEnabled = bundle.getBoolean(KEY_CONFIRM_ENABLED); |
| 528 | mPositiveButton.setEnabled(confirmEnabled); |
Kevin Chyn | 8cfd7a4 | 2019-05-07 20:22:31 -0700 | [diff] [blame] | 529 | mState = bundle.getInt(KEY_STATE); |
| 530 | mErrorText.setText(bundle.getCharSequence(KEY_ERROR_TEXT_STRING)); |
Kevin Chyn | bb79c00 | 2019-05-14 12:53:20 -0700 | [diff] [blame] | 531 | mErrorText.setContentDescription(bundle.getCharSequence(KEY_ERROR_TEXT_STRING)); |
joshmccloskey | 6cf1277 | 2019-05-30 17:09:40 -0700 | [diff] [blame] | 532 | final int errorTextVisibility = bundle.getInt(KEY_ERROR_TEXT_VISIBILITY); |
| 533 | mErrorText.setVisibility(errorTextVisibility); |
| 534 | if (errorTextVisibility == View.INVISIBLE || tryAgainVisibility == View.INVISIBLE |
| 535 | || confirmVisibility == View.INVISIBLE) { |
| 536 | announceAccessibilityEvent(); |
| 537 | } |
Kevin Chyn | 8cfd7a4 | 2019-05-07 20:22:31 -0700 | [diff] [blame] | 538 | mErrorText.setTextColor(bundle.getInt(KEY_ERROR_TEXT_COLOR)); |
Kevin Chyn | 8cfd7a4 | 2019-05-07 20:22:31 -0700 | [diff] [blame] | 539 | if (bundle.getBoolean(KEY_ERROR_TEXT_IS_TEMPORARY)) { |
| 540 | mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_RESET_MESSAGE), |
| 541 | BiometricPrompt.HIDE_DIALOG_DELAY); |
| 542 | } |
| 543 | } |
| 544 | |
| 545 | protected int getState() { |
| 546 | return mState; |
Kevin Chyn | 23289ef | 2018-11-28 16:32:36 -0800 | [diff] [blame] | 547 | } |
| 548 | |
Kevin Chyn | 42653e8 | 2018-01-19 14:15:46 -0800 | [diff] [blame] | 549 | public WindowManager.LayoutParams getLayoutParams() { |
| 550 | final WindowManager.LayoutParams lp = new WindowManager.LayoutParams( |
| 551 | ViewGroup.LayoutParams.MATCH_PARENT, |
| 552 | ViewGroup.LayoutParams.MATCH_PARENT, |
| 553 | WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL, |
| 554 | WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED, |
| 555 | PixelFormat.TRANSLUCENT); |
| 556 | lp.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS; |
Kevin Chyn | a883fb5 | 2018-09-18 18:23:22 -0700 | [diff] [blame] | 557 | lp.setTitle("BiometricDialogView"); |
Kevin Chyn | 42653e8 | 2018-01-19 14:15:46 -0800 | [diff] [blame] | 558 | lp.token = mWindowToken; |
| 559 | return lp; |
| 560 | } |
joshmccloskey | 6cf1277 | 2019-05-30 17:09:40 -0700 | [diff] [blame] | 561 | |
| 562 | // Every time a view becomes invisible we need to announce an accessibility event. |
| 563 | // This is due to an issue in the framework, b/132298701 recommended this workaround. |
| 564 | protected void announceAccessibilityEvent() { |
Kevin Chyn | 791f1dd | 2019-06-05 14:03:26 -0700 | [diff] [blame] | 565 | if (!mAccessibilityManager.isEnabled()) { |
| 566 | return; |
| 567 | } |
joshmccloskey | 6cf1277 | 2019-05-30 17:09:40 -0700 | [diff] [blame] | 568 | AccessibilityEvent event = AccessibilityEvent.obtain(); |
| 569 | event.setEventType(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED); |
| 570 | event.setContentChangeTypes(CONTENT_CHANGE_TYPE_SUBTREE); |
| 571 | mDialog.sendAccessibilityEventUnchecked(event); |
| 572 | mDialog.notifySubtreeAccessibilityStateChanged(mDialog, mDialog, |
| 573 | CONTENT_CHANGE_TYPE_SUBTREE); |
joshmccloskey | 6cf1277 | 2019-05-30 17:09:40 -0700 | [diff] [blame] | 574 | } |
Kevin Chyn | 42653e8 | 2018-01-19 14:15:46 -0800 | [diff] [blame] | 575 | } |