Persist dialog state across configuration change
Fixes: 132208703 Test: Follow steps in comment#1 Change-Id: I82b77ec1536ce2811fa94f07296d25120e17f241
This commit is contained in:
276
packages/SystemUI/res/drawable/face_dialog_idle_static.xml
Normal file
276
packages/SystemUI/res/drawable/face_dialog_idle_static.xml
Normal file
@@ -0,0 +1,276 @@
|
||||
<!--
|
||||
~ Copyright (C) 2019 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
|
||||
-->
|
||||
|
||||
<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:aapt="http://schemas.android.com/aapt">
|
||||
<aapt:attr name="android:drawable">
|
||||
<vector
|
||||
android:width="60dp"
|
||||
android:height="60dp"
|
||||
android:viewportWidth="60"
|
||||
android:viewportHeight="60">
|
||||
<group android:name="_R_G">
|
||||
<group
|
||||
android:name="_R_G_L_0_G"
|
||||
android:pivotX="30"
|
||||
android:pivotY="30"
|
||||
android:scaleX="1.03"
|
||||
android:scaleY="1.03">
|
||||
<path
|
||||
android:name="_R_G_L_0_G_D_0_P_0"
|
||||
android:pathData=" M30 6.2 C16.9,6.2 6.3,16.8 6.3,30 C6.3,43.2 16.9,53.8 30,53.8 C43.1,53.8 53.8,43.2 53.8,30 C53.8,16.8 43.1,6.2 30,6.2c "
|
||||
android:strokeWidth="2.5"
|
||||
android:strokeAlpha="1.0"
|
||||
android:strokeColor="@color/biometric_dialog_gray"
|
||||
android:trimPathStart="0"
|
||||
android:trimPathEnd="1"
|
||||
android:trimPathOffset="0" />
|
||||
<path
|
||||
android:name="_R_G_L_0_G_D_1_P_0"
|
||||
android:pathData=" M33.75 42.75 C32.75,43.77 31.37,44.39 29.83,44.39 C26.8,44.39 24.34,41.93 24.34,38.9 "
|
||||
android:strokeWidth="2"
|
||||
android:strokeAlpha="1.0"
|
||||
android:strokeColor="@color/biometric_dialog_gray"
|
||||
android:trimPathStart="0"
|
||||
android:trimPathEnd="1"
|
||||
android:trimPathOffset="0" />
|
||||
<path
|
||||
android:name="_R_G_L_0_G_D_2_P_0"
|
||||
android:fillAlpha="1.0"
|
||||
android:fillColor="@color/biometric_dialog_gray"
|
||||
android:fillType="nonZero"
|
||||
android:pathData=" M39 23.8 C39,25 39.9,25.9 41.1,25.9 C42.2,25.9 43.2,25 43.2,23.8 C43.2,22.6 42.3,21.7 41.1,21.7 C39.9,21.7 39,22.6 39,23.8c " />
|
||||
<path
|
||||
android:name="_R_G_L_0_G_D_3_P_0"
|
||||
android:fillAlpha="1.0"
|
||||
android:fillColor="@color/biometric_dialog_gray"
|
||||
android:fillType="nonZero"
|
||||
android:pathData=" M16.5 23.8 C16.5,25 17.4,25.9 18.6,25.9 C19.8,25.9 20.7,25 20.7,23.8 C20.7,22.6 19.8,21.7 18.6,21.7 C17.4,21.7 16.5,22.6 16.5,23.8c " />
|
||||
<path
|
||||
android:name="_R_G_L_0_G_D_4_P_0"
|
||||
android:fillAlpha="1.0"
|
||||
android:fillColor="@color/biometric_dialog_gray"
|
||||
android:fillType="nonZero"
|
||||
android:pathData=" M33.33 34.95 C33.33,34.95 28.13,34.95 28.13,34.95 C28.13,34.95 28.13,32.95 28.13,32.95 C28.13,32.95 31.33,32.95 31.33,32.95 C31.33,32.95 31.33,28.45 31.33,28.45 C31.33,28.45 33.33,28.45 33.33,28.45 C33.33,28.45 33.33,34.95 33.33,34.95c " />
|
||||
</group>
|
||||
</group>
|
||||
<group android:name="time_group" />
|
||||
</vector>
|
||||
</aapt:attr>
|
||||
<target android:name="_R_G_L_0_G_D_0_P_0">
|
||||
<aapt:attr name="android:animation">
|
||||
<set android:ordering="together">
|
||||
<objectAnimator
|
||||
android:duration="500"
|
||||
android:propertyName="strokeAlpha"
|
||||
android:startOffset="0"
|
||||
android:valueFrom="1.0"
|
||||
android:valueTo="1.0"
|
||||
android:valueType="floatType">
|
||||
<aapt:attr name="android:interpolator">
|
||||
<pathInterpolator android:pathData="M 0.0,0.0 c0.118,1.266 0.419,1 1.0,1.0" />
|
||||
</aapt:attr>
|
||||
</objectAnimator>
|
||||
<objectAnimator
|
||||
android:duration="500"
|
||||
android:propertyName="strokeAlpha"
|
||||
android:startOffset="500"
|
||||
android:valueFrom="1.0"
|
||||
android:valueTo="1.0"
|
||||
android:valueType="floatType">
|
||||
<aapt:attr name="android:interpolator">
|
||||
<pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0" />
|
||||
</aapt:attr>
|
||||
</objectAnimator>
|
||||
</set>
|
||||
</aapt:attr>
|
||||
</target>
|
||||
<target android:name="_R_G_L_0_G_D_1_P_0">
|
||||
<aapt:attr name="android:animation">
|
||||
<set android:ordering="together">
|
||||
<objectAnimator
|
||||
android:duration="500"
|
||||
android:propertyName="strokeAlpha"
|
||||
android:startOffset="0"
|
||||
android:valueFrom="1.0"
|
||||
android:valueTo="1.0"
|
||||
android:valueType="floatType">
|
||||
<aapt:attr name="android:interpolator">
|
||||
<pathInterpolator android:pathData="M 0.0,0.0 c0.118,1.266 0.419,1 1.0,1.0" />
|
||||
</aapt:attr>
|
||||
</objectAnimator>
|
||||
<objectAnimator
|
||||
android:duration="500"
|
||||
android:propertyName="strokeAlpha"
|
||||
android:startOffset="500"
|
||||
android:valueFrom="1.0"
|
||||
android:valueTo="1.0"
|
||||
android:valueType="floatType">
|
||||
<aapt:attr name="android:interpolator">
|
||||
<pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0" />
|
||||
</aapt:attr>
|
||||
</objectAnimator>
|
||||
</set>
|
||||
</aapt:attr>
|
||||
</target>
|
||||
<target android:name="_R_G_L_0_G_D_2_P_0">
|
||||
<aapt:attr name="android:animation">
|
||||
<set android:ordering="together">
|
||||
<objectAnimator
|
||||
android:duration="500"
|
||||
android:propertyName="fillAlpha"
|
||||
android:startOffset="0"
|
||||
android:valueFrom="1.0"
|
||||
android:valueTo="1.0"
|
||||
android:valueType="floatType">
|
||||
<aapt:attr name="android:interpolator">
|
||||
<pathInterpolator android:pathData="M 0.0,0.0 c0.118,1.266 0.419,1 1.0,1.0" />
|
||||
</aapt:attr>
|
||||
</objectAnimator>
|
||||
<objectAnimator
|
||||
android:duration="500"
|
||||
android:propertyName="fillAlpha"
|
||||
android:startOffset="500"
|
||||
android:valueFrom="1.0"
|
||||
android:valueTo="1.0"
|
||||
android:valueType="floatType">
|
||||
<aapt:attr name="android:interpolator">
|
||||
<pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0" />
|
||||
</aapt:attr>
|
||||
</objectAnimator>
|
||||
</set>
|
||||
</aapt:attr>
|
||||
</target>
|
||||
<target android:name="_R_G_L_0_G_D_3_P_0">
|
||||
<aapt:attr name="android:animation">
|
||||
<set android:ordering="together">
|
||||
<objectAnimator
|
||||
android:duration="500"
|
||||
android:propertyName="fillAlpha"
|
||||
android:startOffset="0"
|
||||
android:valueFrom="1.0"
|
||||
android:valueTo="1.0"
|
||||
android:valueType="floatType">
|
||||
<aapt:attr name="android:interpolator">
|
||||
<pathInterpolator android:pathData="M 0.0,0.0 c0.118,1.266 0.419,1 1.0,1.0" />
|
||||
</aapt:attr>
|
||||
</objectAnimator>
|
||||
<objectAnimator
|
||||
android:duration="500"
|
||||
android:propertyName="fillAlpha"
|
||||
android:startOffset="500"
|
||||
android:valueFrom="1.0"
|
||||
android:valueTo="1.0"
|
||||
android:valueType="floatType">
|
||||
<aapt:attr name="android:interpolator">
|
||||
<pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0" />
|
||||
</aapt:attr>
|
||||
</objectAnimator>
|
||||
</set>
|
||||
</aapt:attr>
|
||||
</target>
|
||||
<target android:name="_R_G_L_0_G_D_4_P_0">
|
||||
<aapt:attr name="android:animation">
|
||||
<set android:ordering="together">
|
||||
<objectAnimator
|
||||
android:duration="500"
|
||||
android:propertyName="fillAlpha"
|
||||
android:startOffset="0"
|
||||
android:valueFrom="1.0"
|
||||
android:valueTo="1.0"
|
||||
android:valueType="floatType">
|
||||
<aapt:attr name="android:interpolator">
|
||||
<pathInterpolator android:pathData="M 0.0,0.0 c0.118,1.266 0.419,1 1.0,1.0" />
|
||||
</aapt:attr>
|
||||
</objectAnimator>
|
||||
<objectAnimator
|
||||
android:duration="500"
|
||||
android:propertyName="fillAlpha"
|
||||
android:startOffset="500"
|
||||
android:valueFrom="1.0"
|
||||
android:valueTo="1.0"
|
||||
android:valueType="floatType">
|
||||
<aapt:attr name="android:interpolator">
|
||||
<pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0" />
|
||||
</aapt:attr>
|
||||
</objectAnimator>
|
||||
</set>
|
||||
</aapt:attr>
|
||||
</target>
|
||||
<target android:name="_R_G_L_0_G">
|
||||
<aapt:attr name="android:animation">
|
||||
<set android:ordering="together">
|
||||
<objectAnimator
|
||||
android:duration="500"
|
||||
android:propertyName="scaleX"
|
||||
android:startOffset="0"
|
||||
android:valueFrom="1.03"
|
||||
android:valueTo="1"
|
||||
android:valueType="floatType">
|
||||
<aapt:attr name="android:interpolator">
|
||||
<pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0" />
|
||||
</aapt:attr>
|
||||
</objectAnimator>
|
||||
<objectAnimator
|
||||
android:duration="500"
|
||||
android:propertyName="scaleY"
|
||||
android:startOffset="0"
|
||||
android:valueFrom="1.03"
|
||||
android:valueTo="1"
|
||||
android:valueType="floatType">
|
||||
<aapt:attr name="android:interpolator">
|
||||
<pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0" />
|
||||
</aapt:attr>
|
||||
</objectAnimator>
|
||||
<objectAnimator
|
||||
android:duration="500"
|
||||
android:propertyName="scaleX"
|
||||
android:startOffset="500"
|
||||
android:valueFrom="1"
|
||||
android:valueTo="1.03"
|
||||
android:valueType="floatType">
|
||||
<aapt:attr name="android:interpolator">
|
||||
<pathInterpolator android:pathData="M 0.0,0.0 c0.204,0.46 0.568,1 1.0,1.0" />
|
||||
</aapt:attr>
|
||||
</objectAnimator>
|
||||
<objectAnimator
|
||||
android:duration="500"
|
||||
android:propertyName="scaleY"
|
||||
android:startOffset="500"
|
||||
android:valueFrom="1"
|
||||
android:valueTo="1.03"
|
||||
android:valueType="floatType">
|
||||
<aapt:attr name="android:interpolator">
|
||||
<pathInterpolator android:pathData="M 0.0,0.0 c0.204,0.46 0.568,1 1.0,1.0" />
|
||||
</aapt:attr>
|
||||
</objectAnimator>
|
||||
</set>
|
||||
</aapt:attr>
|
||||
</target>
|
||||
<target android:name="time_group">
|
||||
<aapt:attr name="android:animation">
|
||||
<set android:ordering="together">
|
||||
<objectAnimator
|
||||
android:duration="1017"
|
||||
android:propertyName="translateX"
|
||||
android:startOffset="0"
|
||||
android:valueFrom="0"
|
||||
android:valueTo="1"
|
||||
android:valueType="floatType" />
|
||||
</set>
|
||||
</aapt:attr>
|
||||
</target>
|
||||
</animated-vector>
|
||||
@@ -56,11 +56,16 @@ public abstract class BiometricDialogView extends LinearLayout {
|
||||
|
||||
private static final String KEY_TRY_AGAIN_VISIBILITY = "key_try_again_visibility";
|
||||
private static final String KEY_CONFIRM_VISIBILITY = "key_confirm_visibility";
|
||||
private static final String KEY_STATE = "key_state";
|
||||
private static final String KEY_ERROR_TEXT_VISIBILITY = "key_error_text_visibility";
|
||||
private static final String KEY_ERROR_TEXT_STRING = "key_error_text_string";
|
||||
private static final String KEY_ERROR_TEXT_IS_TEMPORARY = "key_error_text_is_temporary";
|
||||
private static final String KEY_ERROR_TEXT_COLOR = "key_error_text_color";
|
||||
|
||||
private static final int ANIMATION_DURATION_SHOW = 250; // ms
|
||||
private static final int ANIMATION_DURATION_AWAY = 350; // ms
|
||||
|
||||
protected static final int MSG_CLEAR_MESSAGE = 1;
|
||||
protected static final int MSG_RESET_MESSAGE = 1;
|
||||
|
||||
protected static final int STATE_IDLE = 0;
|
||||
protected static final int STATE_AUTHENTICATING = 1;
|
||||
@@ -94,7 +99,7 @@ public abstract class BiometricDialogView extends LinearLayout {
|
||||
private Bundle mBundle;
|
||||
private Bundle mRestoredState;
|
||||
|
||||
private int mState;
|
||||
private int mState = STATE_IDLE;
|
||||
private boolean mAnimatingAway;
|
||||
private boolean mWasForceRemoved;
|
||||
private boolean mSkipIntro;
|
||||
@@ -106,7 +111,7 @@ public abstract class BiometricDialogView extends LinearLayout {
|
||||
protected abstract int getIconDescriptionResourceId();
|
||||
protected abstract int getDelayAfterAuthenticatedDurationMs();
|
||||
protected abstract boolean shouldGrayAreaDismissDialog();
|
||||
protected abstract void handleClearMessage();
|
||||
protected abstract void handleResetMessage();
|
||||
protected abstract void updateIcon(int oldState, int newState);
|
||||
|
||||
private final Runnable mShowAnimationRunnable = new Runnable() {
|
||||
@@ -132,8 +137,8 @@ public abstract class BiometricDialogView extends LinearLayout {
|
||||
@Override
|
||||
public void handleMessage(Message msg) {
|
||||
switch(msg.what) {
|
||||
case MSG_CLEAR_MESSAGE:
|
||||
handleClearMessage();
|
||||
case MSG_RESET_MESSAGE:
|
||||
handleResetMessage();
|
||||
break;
|
||||
default:
|
||||
Log.e(TAG, "Unhandled message: " + msg.what);
|
||||
@@ -231,14 +236,17 @@ public abstract class BiometricDialogView extends LinearLayout {
|
||||
public void onSaveState(Bundle bundle) {
|
||||
bundle.putInt(KEY_TRY_AGAIN_VISIBILITY, mTryAgainButton.getVisibility());
|
||||
bundle.putInt(KEY_CONFIRM_VISIBILITY, mPositiveButton.getVisibility());
|
||||
bundle.putInt(KEY_STATE, mState);
|
||||
bundle.putInt(KEY_ERROR_TEXT_VISIBILITY, mErrorText.getVisibility());
|
||||
bundle.putCharSequence(KEY_ERROR_TEXT_STRING, mErrorText.getText());
|
||||
bundle.putBoolean(KEY_ERROR_TEXT_IS_TEMPORARY, mHandler.hasMessages(MSG_RESET_MESSAGE));
|
||||
bundle.putInt(KEY_ERROR_TEXT_COLOR, mErrorText.getCurrentTextColor());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAttachedToWindow() {
|
||||
super.onAttachedToWindow();
|
||||
|
||||
mErrorText.setText(getHintStringResourceId());
|
||||
|
||||
final ImageView backgroundView = mLayout.findViewById(R.id.background);
|
||||
|
||||
if (mUserManager.isManagedProfile(mUserId)) {
|
||||
@@ -253,14 +261,18 @@ public abstract class BiometricDialogView extends LinearLayout {
|
||||
}
|
||||
|
||||
mNegativeButton.setVisibility(View.VISIBLE);
|
||||
mErrorText.setVisibility(View.VISIBLE);
|
||||
|
||||
if (RotationUtils.getRotation(mContext) != RotationUtils.ROTATION_NONE) {
|
||||
mDialog.getLayoutParams().width = (int) mDialogWidth;
|
||||
}
|
||||
|
||||
mState = STATE_IDLE;
|
||||
updateState(STATE_AUTHENTICATING);
|
||||
if (mRestoredState == null) {
|
||||
updateState(STATE_AUTHENTICATING);
|
||||
mErrorText.setText(getHintStringResourceId());
|
||||
mErrorText.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
updateState(mState);
|
||||
}
|
||||
|
||||
CharSequence titleText = mBundle.getCharSequence(BiometricPrompt.KEY_TITLE);
|
||||
|
||||
@@ -329,7 +341,7 @@ public abstract class BiometricDialogView extends LinearLayout {
|
||||
mWindowManager.removeView(BiometricDialogView.this);
|
||||
mAnimatingAway = false;
|
||||
// Set the icons / text back to normal state
|
||||
handleClearMessage();
|
||||
handleResetMessage();
|
||||
showTryAgainButton(false /* show */);
|
||||
updateState(STATE_IDLE);
|
||||
}
|
||||
@@ -401,17 +413,17 @@ public abstract class BiometricDialogView extends LinearLayout {
|
||||
|
||||
// Shows an error/help message
|
||||
protected void showTemporaryMessage(String message) {
|
||||
mHandler.removeMessages(MSG_CLEAR_MESSAGE);
|
||||
mHandler.removeMessages(MSG_RESET_MESSAGE);
|
||||
mErrorText.setText(message);
|
||||
mErrorText.setTextColor(mErrorColor);
|
||||
mErrorText.setContentDescription(message);
|
||||
mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_CLEAR_MESSAGE),
|
||||
mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_RESET_MESSAGE),
|
||||
BiometricPrompt.HIDE_DIALOG_DELAY);
|
||||
}
|
||||
|
||||
public void clearTemporaryMessage() {
|
||||
mHandler.removeMessages(MSG_CLEAR_MESSAGE);
|
||||
mHandler.obtainMessage(MSG_CLEAR_MESSAGE).sendToTarget();
|
||||
mHandler.removeMessages(MSG_RESET_MESSAGE);
|
||||
mHandler.obtainMessage(MSG_RESET_MESSAGE).sendToTarget();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -442,7 +454,7 @@ public abstract class BiometricDialogView extends LinearLayout {
|
||||
|
||||
public void updateState(int newState) {
|
||||
if (newState == STATE_PENDING_CONFIRMATION) {
|
||||
mHandler.removeMessages(MSG_CLEAR_MESSAGE);
|
||||
mHandler.removeMessages(MSG_RESET_MESSAGE);
|
||||
mErrorText.setVisibility(View.INVISIBLE);
|
||||
mPositiveButton.setVisibility(View.VISIBLE);
|
||||
mPositiveButton.setEnabled(true);
|
||||
@@ -470,6 +482,19 @@ public abstract class BiometricDialogView extends LinearLayout {
|
||||
mRestoredState = bundle;
|
||||
mTryAgainButton.setVisibility(bundle.getInt(KEY_TRY_AGAIN_VISIBILITY));
|
||||
mPositiveButton.setVisibility(bundle.getInt(KEY_CONFIRM_VISIBILITY));
|
||||
mState = bundle.getInt(KEY_STATE);
|
||||
mErrorText.setText(bundle.getCharSequence(KEY_ERROR_TEXT_STRING));
|
||||
mErrorText.setVisibility(bundle.getInt(KEY_ERROR_TEXT_VISIBILITY));
|
||||
mErrorText.setTextColor(bundle.getInt(KEY_ERROR_TEXT_COLOR));
|
||||
|
||||
if (bundle.getBoolean(KEY_ERROR_TEXT_IS_TEMPORARY)) {
|
||||
mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_RESET_MESSAGE),
|
||||
BiometricPrompt.HIDE_DIALOG_DELAY);
|
||||
}
|
||||
}
|
||||
|
||||
protected int getState() {
|
||||
return mState;
|
||||
}
|
||||
|
||||
public WindowManager.LayoutParams getLayoutParams() {
|
||||
|
||||
@@ -44,6 +44,7 @@ public class FaceDialogView extends BiometricDialogView {
|
||||
|
||||
private static final String TAG = "FaceDialogView";
|
||||
private static final String KEY_DIALOG_SIZE = "key_dialog_size";
|
||||
private static final String KEY_DIALOG_ANIMATED_IN = "key_dialog_animated_in";
|
||||
|
||||
private static final int HIDE_DIALOG_DELAY = 500; // ms
|
||||
private static final int IMPLICIT_Y_PADDING = 16; // dp
|
||||
@@ -78,6 +79,10 @@ public class FaceDialogView extends BiometricDialogView {
|
||||
animateIcon(iconRes, false);
|
||||
}
|
||||
|
||||
public void showStatic(int iconRes) {
|
||||
mBiometricIcon.setImageDrawable(mContext.getDrawable(iconRes));
|
||||
}
|
||||
|
||||
public void startPulsing() {
|
||||
mLastPulseDirection = false;
|
||||
animateIcon(R.drawable.face_dialog_pulse_dark_to_light, true);
|
||||
@@ -276,13 +281,19 @@ public class FaceDialogView extends BiometricDialogView {
|
||||
public void onSaveState(Bundle bundle) {
|
||||
super.onSaveState(bundle);
|
||||
bundle.putInt(KEY_DIALOG_SIZE, mSize);
|
||||
bundle.putBoolean(KEY_DIALOG_ANIMATED_IN, mDialogAnimatedIn);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void handleClearMessage() {
|
||||
protected void handleResetMessage() {
|
||||
mErrorText.setText(getHintStringResourceId());
|
||||
mErrorText.setTextColor(mTextColor);
|
||||
if (getState() == STATE_AUTHENTICATING) {
|
||||
mErrorText.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
mErrorText.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -290,6 +301,7 @@ public class FaceDialogView extends BiometricDialogView {
|
||||
super.restoreState(bundle);
|
||||
// Keep in mind that this happens before onAttachedToWindow()
|
||||
mSize = bundle.getInt(KEY_DIALOG_SIZE);
|
||||
mDialogAnimatedIn = bundle.getBoolean(KEY_DIALOG_ANIMATED_IN);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -386,7 +398,8 @@ public class FaceDialogView extends BiometricDialogView {
|
||||
protected void updateIcon(int oldState, int newState) {
|
||||
mIconController.mState = newState;
|
||||
|
||||
if (oldState == STATE_IDLE && newState == STATE_AUTHENTICATING) {
|
||||
if (newState == STATE_AUTHENTICATING) {
|
||||
mHandler.removeCallbacks(mErrorToIdleAnimationRunnable);
|
||||
if (mDialogAnimatedIn) {
|
||||
mIconController.startPulsing();
|
||||
mErrorText.setVisibility(View.VISIBLE);
|
||||
@@ -397,25 +410,39 @@ public class FaceDialogView extends BiometricDialogView {
|
||||
mIconController.animateOnce(R.drawable.face_dialog_dark_to_checkmark);
|
||||
} else if (oldState == STATE_ERROR && newState == STATE_IDLE) {
|
||||
mIconController.animateOnce(R.drawable.face_dialog_error_to_idle);
|
||||
} else if (oldState == STATE_ERROR && newState == STATE_AUTHENTICATING) {
|
||||
mHandler.removeCallbacks(mErrorToIdleAnimationRunnable);
|
||||
mIconController.startPulsing();
|
||||
} else if (oldState == STATE_ERROR && newState == STATE_PENDING_CONFIRMATION) {
|
||||
mHandler.removeCallbacks(mErrorToIdleAnimationRunnable);
|
||||
mIconController.animateOnce(R.drawable.face_dialog_wink_from_dark);
|
||||
} else if (oldState == STATE_ERROR && newState == STATE_AUTHENTICATED) {
|
||||
mHandler.removeCallbacks(mErrorToIdleAnimationRunnable);
|
||||
mIconController.animateOnce(R.drawable.face_dialog_dark_to_checkmark);
|
||||
} else if (oldState == STATE_AUTHENTICATING && newState == STATE_ERROR) {
|
||||
mIconController.animateOnce(R.drawable.face_dialog_dark_to_error);
|
||||
mHandler.postDelayed(mErrorToIdleAnimationRunnable, BiometricPrompt.HIDE_DIALOG_DELAY);
|
||||
} else if (newState == STATE_ERROR) {
|
||||
// It's easier to only check newState and gate showing the animation on the
|
||||
// mErrorToIdleAnimationRunnable as a proxy, than add a ton of extra state. For example,
|
||||
// we may go from error -> error due to configuration change which is valid and we
|
||||
// should show the animation, or we can go from error -> error by receiving repeated
|
||||
// acquire messages in which case we do not want to repeatedly start the animation.
|
||||
if (!mHandler.hasCallbacks(mErrorToIdleAnimationRunnable)) {
|
||||
mIconController.animateOnce(R.drawable.face_dialog_dark_to_error);
|
||||
mHandler.postDelayed(mErrorToIdleAnimationRunnable,
|
||||
BiometricPrompt.HIDE_DIALOG_DELAY);
|
||||
}
|
||||
} else if (oldState == STATE_AUTHENTICATING && newState == STATE_AUTHENTICATED) {
|
||||
mIconController.animateOnce(R.drawable.face_dialog_dark_to_checkmark);
|
||||
} else if (oldState == STATE_AUTHENTICATING && newState == STATE_PENDING_CONFIRMATION) {
|
||||
} else if (newState == STATE_PENDING_CONFIRMATION) {
|
||||
mHandler.removeCallbacks(mErrorToIdleAnimationRunnable);
|
||||
mIconController.animateOnce(R.drawable.face_dialog_wink_from_dark);
|
||||
} else if (newState == STATE_IDLE) {
|
||||
mIconController.showStatic(R.drawable.face_dialog_idle_static);
|
||||
} else {
|
||||
Log.w(TAG, "Unknown animation from " + oldState + " -> " + newState);
|
||||
}
|
||||
|
||||
// Note that this must be after the newState == STATE_ERROR check above since this affects
|
||||
// the logic.
|
||||
if (oldState == STATE_ERROR && newState == STATE_ERROR) {
|
||||
// Keep the error icon and text around for a while longer if we keep receiving
|
||||
// STATE_ERROR
|
||||
mHandler.removeCallbacks(mErrorToIdleAnimationRunnable);
|
||||
mHandler.postDelayed(mErrorToIdleAnimationRunnable, BiometricPrompt.HIDE_DIALOG_DELAY);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -38,7 +38,7 @@ public class FingerprintDialogView extends BiometricDialogView {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void handleClearMessage() {
|
||||
protected void handleResetMessage() {
|
||||
updateState(STATE_AUTHENTICATING);
|
||||
mErrorText.setText(getHintStringResourceId());
|
||||
mErrorText.setTextColor(mTextColor);
|
||||
@@ -80,9 +80,7 @@ public class FingerprintDialogView extends BiometricDialogView {
|
||||
}
|
||||
|
||||
protected boolean shouldAnimateForTransition(int oldState, int newState) {
|
||||
if (oldState == STATE_IDLE && newState == STATE_AUTHENTICATING) {
|
||||
return false;
|
||||
} else if (oldState == STATE_AUTHENTICATING && newState == STATE_ERROR) {
|
||||
if (newState == STATE_ERROR) {
|
||||
return true;
|
||||
} else if (oldState == STATE_ERROR && newState == STATE_AUTHENTICATING) {
|
||||
return true;
|
||||
@@ -92,6 +90,8 @@ public class FingerprintDialogView extends BiometricDialogView {
|
||||
} else if (oldState == STATE_ERROR && newState == STATE_AUTHENTICATED) {
|
||||
// TODO(b/77328470): add animation when fingerprint is authenticated
|
||||
return false;
|
||||
} else if (newState == STATE_AUTHENTICATING) {
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -109,9 +109,7 @@ public class FingerprintDialogView extends BiometricDialogView {
|
||||
|
||||
protected Drawable getAnimationForTransition(int oldState, int newState) {
|
||||
int iconRes;
|
||||
if (oldState == STATE_IDLE && newState == STATE_AUTHENTICATING) {
|
||||
iconRes = R.drawable.fingerprint_dialog_fp_to_error;
|
||||
} else if (oldState == STATE_AUTHENTICATING && newState == STATE_ERROR) {
|
||||
if (newState == STATE_ERROR) {
|
||||
iconRes = R.drawable.fingerprint_dialog_fp_to_error;
|
||||
} else if (oldState == STATE_ERROR && newState == STATE_AUTHENTICATING) {
|
||||
iconRes = R.drawable.fingerprint_dialog_error_to_fp;
|
||||
@@ -121,9 +119,11 @@ public class FingerprintDialogView extends BiometricDialogView {
|
||||
} else if (oldState == STATE_ERROR && newState == STATE_AUTHENTICATED) {
|
||||
// TODO(b/77328470): add animation when fingerprint is authenticated
|
||||
iconRes = R.drawable.fingerprint_dialog_fp_to_error;
|
||||
} else if (newState == STATE_AUTHENTICATING) {
|
||||
iconRes = R.drawable.fingerprint_dialog_fp_to_error;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
return mContext.getDrawable(iconRes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user