Loading packages/SystemUI/res/drawable/face_dialog_idle_static.xml 0 → 100644 +276 −0 Original line number Diff line number Diff line <!-- ~ 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> No newline at end of file packages/SystemUI/src/com/android/systemui/biometrics/BiometricDialogView.java +41 −16 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading @@ -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() { Loading @@ -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); Loading Loading @@ -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)) { Loading @@ -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; if (mRestoredState == null) { updateState(STATE_AUTHENTICATING); mErrorText.setText(getHintStringResourceId()); mErrorText.setVisibility(View.VISIBLE); } else { updateState(mState); } CharSequence titleText = mBundle.getCharSequence(BiometricPrompt.KEY_TITLE); Loading Loading @@ -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); } Loading Loading @@ -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(); } /** Loading Loading @@ -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); Loading Loading @@ -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() { Loading packages/SystemUI/src/com/android/systemui/biometrics/FaceDialogView.java +39 −12 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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); Loading Loading @@ -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 Loading @@ -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); } /** Loading Loading @@ -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); Loading @@ -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) { } 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); 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 Loading packages/SystemUI/src/com/android/systemui/biometrics/FingerprintDialogView.java +8 −8 File changed.Preview size limit exceeded, changes collapsed. Show changes services/core/java/com/android/server/biometrics/AuthenticationClient.java +6 −0 Original line number Diff line number Diff line Loading @@ -63,6 +63,8 @@ public abstract class AuthenticationClient extends ClientMonitor { */ public abstract boolean shouldFrameworkHandleLockout(); public abstract boolean wasUserDetected(); public AuthenticationClient(Context context, Constants constants, BiometricServiceBase.DaemonWrapper daemon, long halDeviceId, IBinder token, BiometricServiceBase.ServiceListener listener, int targetUserId, int groupId, long opId, Loading Loading @@ -105,6 +107,10 @@ public abstract class AuthenticationClient extends ClientMonitor { if (!shouldFrameworkHandleLockout()) { switch (error) { case BiometricConstants.BIOMETRIC_ERROR_TIMEOUT: if (!wasUserDetected() && !isBiometricPrompt()) { // No vibration if user was not detected on keyguard break; } case BiometricConstants.BIOMETRIC_ERROR_LOCKOUT: case BiometricConstants.BIOMETRIC_ERROR_LOCKOUT_PERMANENT: if (mStarted) { Loading Loading
packages/SystemUI/res/drawable/face_dialog_idle_static.xml 0 → 100644 +276 −0 Original line number Diff line number Diff line <!-- ~ 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> No newline at end of file
packages/SystemUI/src/com/android/systemui/biometrics/BiometricDialogView.java +41 −16 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading @@ -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() { Loading @@ -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); Loading Loading @@ -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)) { Loading @@ -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; if (mRestoredState == null) { updateState(STATE_AUTHENTICATING); mErrorText.setText(getHintStringResourceId()); mErrorText.setVisibility(View.VISIBLE); } else { updateState(mState); } CharSequence titleText = mBundle.getCharSequence(BiometricPrompt.KEY_TITLE); Loading Loading @@ -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); } Loading Loading @@ -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(); } /** Loading Loading @@ -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); Loading Loading @@ -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() { Loading
packages/SystemUI/src/com/android/systemui/biometrics/FaceDialogView.java +39 −12 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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); Loading Loading @@ -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 Loading @@ -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); } /** Loading Loading @@ -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); Loading @@ -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) { } 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); 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 Loading
packages/SystemUI/src/com/android/systemui/biometrics/FingerprintDialogView.java +8 −8 File changed.Preview size limit exceeded, changes collapsed. Show changes
services/core/java/com/android/server/biometrics/AuthenticationClient.java +6 −0 Original line number Diff line number Diff line Loading @@ -63,6 +63,8 @@ public abstract class AuthenticationClient extends ClientMonitor { */ public abstract boolean shouldFrameworkHandleLockout(); public abstract boolean wasUserDetected(); public AuthenticationClient(Context context, Constants constants, BiometricServiceBase.DaemonWrapper daemon, long halDeviceId, IBinder token, BiometricServiceBase.ServiceListener listener, int targetUserId, int groupId, long opId, Loading Loading @@ -105,6 +107,10 @@ public abstract class AuthenticationClient extends ClientMonitor { if (!shouldFrameworkHandleLockout()) { switch (error) { case BiometricConstants.BIOMETRIC_ERROR_TIMEOUT: if (!wasUserDetected() && !isBiometricPrompt()) { // No vibration if user was not detected on keyguard break; } case BiometricConstants.BIOMETRIC_ERROR_LOCKOUT: case BiometricConstants.BIOMETRIC_ERROR_LOCKOUT_PERMANENT: if (mStarted) { Loading