diff --git a/packages/SystemUI/res-keyguard/drawable/ic_shape_circle.xml b/packages/SystemUI/res-keyguard/drawable/ic_shape_circle.xml
deleted file mode 100644
index 1d9247c10a3ff..0000000000000
--- a/packages/SystemUI/res-keyguard/drawable/ic_shape_circle.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-
-
-
-
-
\ No newline at end of file
diff --git a/packages/SystemUI/res-keyguard/values/arrays.xml b/packages/SystemUI/res-keyguard/values/arrays.xml
index a8b3c1bf97971..26bc865bcaf70 100644
--- a/packages/SystemUI/res-keyguard/values/arrays.xml
+++ b/packages/SystemUI/res-keyguard/values/arrays.xml
@@ -32,4 +32,13 @@
- TUV
- WXYZ
+
+
+ - @drawable/pin_dot_shape_1_avd
+ - @drawable/pin_dot_shape_2_avd
+ - @drawable/pin_dot_shape_3_avd
+ - @drawable/pin_dot_shape_4_avd
+ - @drawable/pin_dot_shape_5_avd
+ - @drawable/pin_dot_shape_6_avd
+
diff --git a/packages/SystemUI/res/drawable/pin_dot_delete_avd.xml b/packages/SystemUI/res/drawable/pin_dot_delete_avd.xml
new file mode 100644
index 0000000000000..33f995cfb7b69
--- /dev/null
+++ b/packages/SystemUI/res/drawable/pin_dot_delete_avd.xml
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/pin_dot_shape_1_avd.xml b/packages/SystemUI/res/drawable/pin_dot_shape_1_avd.xml
new file mode 100644
index 0000000000000..da936a28e34fb
--- /dev/null
+++ b/packages/SystemUI/res/drawable/pin_dot_shape_1_avd.xml
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/pin_dot_shape_2_avd.xml b/packages/SystemUI/res/drawable/pin_dot_shape_2_avd.xml
new file mode 100644
index 0000000000000..d910990ae248d
--- /dev/null
+++ b/packages/SystemUI/res/drawable/pin_dot_shape_2_avd.xml
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/pin_dot_shape_3_avd.xml b/packages/SystemUI/res/drawable/pin_dot_shape_3_avd.xml
new file mode 100644
index 0000000000000..cf08899979701
--- /dev/null
+++ b/packages/SystemUI/res/drawable/pin_dot_shape_3_avd.xml
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/pin_dot_shape_4_avd.xml b/packages/SystemUI/res/drawable/pin_dot_shape_4_avd.xml
new file mode 100644
index 0000000000000..76ee65b0060c4
--- /dev/null
+++ b/packages/SystemUI/res/drawable/pin_dot_shape_4_avd.xml
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/pin_dot_shape_5_avd.xml b/packages/SystemUI/res/drawable/pin_dot_shape_5_avd.xml
new file mode 100644
index 0000000000000..de2a7db4ab0a9
--- /dev/null
+++ b/packages/SystemUI/res/drawable/pin_dot_shape_5_avd.xml
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/pin_dot_shape_6_avd.xml b/packages/SystemUI/res/drawable/pin_dot_shape_6_avd.xml
new file mode 100644
index 0000000000000..e7ce4267fc323
--- /dev/null
+++ b/packages/SystemUI/res/drawable/pin_dot_shape_6_avd.xml
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/keyguard_pin_shape_six_digit_view.xml b/packages/SystemUI/res/layout/keyguard_pin_shape_hinting_view.xml
similarity index 90%
rename from packages/SystemUI/res/layout/keyguard_pin_shape_six_digit_view.xml
rename to packages/SystemUI/res/layout/keyguard_pin_shape_hinting_view.xml
index 722f52eff59a5..aab987075bbd5 100644
--- a/packages/SystemUI/res/layout/keyguard_pin_shape_six_digit_view.xml
+++ b/packages/SystemUI/res/layout/keyguard_pin_shape_hinting_view.xml
@@ -14,10 +14,10 @@
~ See the License for the specific language governing permissions and
~ limitations under the License
-->
-
-
+
diff --git a/packages/SystemUI/res/layout/keyguard_pin_shape_non_six_digit_view.xml b/packages/SystemUI/res/layout/keyguard_pin_shape_non_hinting_view.xml
similarity index 90%
rename from packages/SystemUI/res/layout/keyguard_pin_shape_non_six_digit_view.xml
rename to packages/SystemUI/res/layout/keyguard_pin_shape_non_hinting_view.xml
index cbf9f7abe85a3..cba1db0487d63 100644
--- a/packages/SystemUI/res/layout/keyguard_pin_shape_non_six_digit_view.xml
+++ b/packages/SystemUI/res/layout/keyguard_pin_shape_non_hinting_view.xml
@@ -14,10 +14,10 @@
~ See the License for the specific language governing permissions and
~ limitations under the License
-->
-
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPinViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPinViewController.java
index db22c5e702920..fd47e39534a7a 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardPinViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPinViewController.java
@@ -37,6 +37,8 @@ public class KeyguardPinViewController
mView.onDevicePostureChanged(posture);
private LockPatternUtils mLockPatternUtils;
private final FeatureFlags mFeatureFlags;
+ private static final int DEFAULT_PIN_LENGTH = 6;
+ private NumPadButton mBackspaceKey;
private View mOkButton = mView.findViewById(R.id.key_enter);
private int mUserId;
@@ -59,6 +61,7 @@ public class KeyguardPinViewController
mPostureController = postureController;
mLockPatternUtils = lockPatternUtils;
mFeatureFlags = featureFlags;
+ mBackspaceKey = view.findViewById(R.id.delete_button);
}
@Override
@@ -79,6 +82,7 @@ public class KeyguardPinViewController
protected void onUserInput() {
super.onUserInput();
if (isAutoConfirmation()) {
+ updateBackSpaceVisibility();
if (mPasswordEntry.getText().length() == mPinLength) {
verifyPasswordAndUnlock();
}
@@ -96,12 +100,11 @@ public class KeyguardPinViewController
if (mFeatureFlags.isEnabled(Flags.AUTO_PIN_CONFIRMATION)) {
mUserId = KeyguardUpdateMonitor.getCurrentUser();
mPinLength = mLockPatternUtils.getPinLength(mUserId);
- if (isAutoConfirmation()) {
- mOkButton.setVisibility(View.INVISIBLE);
- } else {
- mOkButton.setVisibility(View.VISIBLE);
- }
- mPasswordEntry.setIsPinHinting(true, isPinHinting());
+ mBackspaceKey.setTransparentMode(/* isTransparentMode= */ isAutoConfirmation());
+ mOkButton.setVisibility(isAutoConfirmation() ? View.INVISIBLE : View.VISIBLE);
+ updateBackSpaceVisibility();
+ mPasswordEntry.setUsePinShapes(true);
+ mPasswordEntry.setIsPinHinting(isAutoConfirmation() && isPinHinting());
}
super.startAppearAnimation();
}
@@ -112,15 +115,33 @@ public class KeyguardPinViewController
mKeyguardUpdateMonitor.needsSlowUnlockTransition(), finishRunnable);
}
- /*
- Responsible for identifying if PIN hinting is to be enabled or not
+ //
+
+ /**
+ * Updates the visibility and the enabled state of the backspace.
+ * Visibility changes are only for auto confirmation configuration.
+ */
+ private void updateBackSpaceVisibility() {
+ if (!isAutoConfirmation()) {
+ return;
+ }
+
+ if (mPasswordEntry.getText().length() > 0) {
+ mBackspaceKey.setVisibility(View.VISIBLE);
+ } else {
+ mBackspaceKey.setVisibility(View.INVISIBLE);
+ }
+ }
+
+ /**
+ * Responsible for identifying if PIN hinting is to be enabled or not
*/
private boolean isPinHinting() {
return mLockPatternUtils.getPinLength(mUserId) == DEFAULT_PIN_LENGTH;
}
- /*
- Responsible for identifying if auto confirm is enabled or not in Settings
+ /**
+ * Responsible for identifying if auto confirm is enabled or not in Settings
*/
private boolean isAutoConfirmation() {
//Checks if user has enabled the auto confirm in Settings
diff --git a/packages/SystemUI/src/com/android/keyguard/NumPadAnimator.java b/packages/SystemUI/src/com/android/keyguard/NumPadAnimator.java
index 41111e3d3c6cf..5135eed519a9e 100644
--- a/packages/SystemUI/src/com/android/keyguard/NumPadAnimator.java
+++ b/packages/SystemUI/src/com/android/keyguard/NumPadAnimator.java
@@ -95,7 +95,6 @@ class NumPadAnimator {
mHeight = height;
mStartRadius = height / 2f;
mEndRadius = height / 4f;
- mBackground.setCornerRadius(mStartRadius);
mExpandAnimator.setFloatValues(mStartRadius, mEndRadius);
mContractAnimator.setFloatValues(mEndRadius, mStartRadius);
}
diff --git a/packages/SystemUI/src/com/android/keyguard/NumPadButton.java b/packages/SystemUI/src/com/android/keyguard/NumPadButton.java
index 37060987cb21b..11c329e9811d3 100644
--- a/packages/SystemUI/src/com/android/keyguard/NumPadButton.java
+++ b/packages/SystemUI/src/com/android/keyguard/NumPadButton.java
@@ -27,6 +27,8 @@ import android.view.MotionEvent;
import androidx.annotation.Nullable;
+import com.android.systemui.R;
+
/**
* Similar to the {@link NumPadKey}, but displays an image.
*/
@@ -35,18 +37,13 @@ public class NumPadButton extends AlphaOptimizedImageButton implements NumPadAni
@Nullable
private NumPadAnimator mAnimator;
private int mOrientation;
+ private int mStyleAttr;
+ private boolean mIsTransparentMode;
public NumPadButton(Context context, AttributeSet attrs) {
super(context, attrs);
-
- Drawable background = getBackground();
- if (background instanceof GradientDrawable) {
- mAnimator = new NumPadAnimator(context, background.mutate(),
- attrs.getStyleAttribute(), getDrawable());
- } else {
- mAnimator = null;
- }
-
+ mStyleAttr = attrs.getStyleAttribute();
+ setupAnimator();
}
@Override
@@ -98,7 +95,9 @@ public class NumPadButton extends AlphaOptimizedImageButton implements NumPadAni
public void reloadColors() {
if (mAnimator != null) mAnimator.reloadColors(getContext());
- int[] customAttrs = {android.R.attr.textColorPrimaryInverse};
+ int textColorResId = mIsTransparentMode ? android.R.attr.textColorPrimary
+ : android.R.attr.textColorPrimaryInverse;
+ int[] customAttrs = {textColorResId};
TypedArray a = getContext().obtainStyledAttributes(customAttrs);
int imageColor = a.getColor(0, 0);
a.recycle();
@@ -111,4 +110,34 @@ public class NumPadButton extends AlphaOptimizedImageButton implements NumPadAni
mAnimator.setProgress(progress);
}
}
+
+ /**
+ * Set whether button is transparent mode.
+ *
+ * @param isTransparentMode
+ */
+ public void setTransparentMode(boolean isTransparentMode) {
+ mIsTransparentMode = isTransparentMode;
+ if (isTransparentMode) {
+ setBackgroundColor(android.R.color.transparent);
+ } else {
+ setBackground(getContext().getDrawable(R.drawable.num_pad_key_background));
+ }
+ setupAnimator();
+ reloadColors();
+ requestLayout();
+ }
+
+ /**
+ * Set up the animator for the NumPadButton.
+ */
+ private void setupAnimator() {
+ Drawable background = getBackground();
+ if (background instanceof GradientDrawable) {
+ mAnimator = new NumPadAnimator(getContext(), background.mutate(),
+ mStyleAttr, getDrawable());
+ } else {
+ mAnimator = null;
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/keyguard/PasswordTextView.java b/packages/SystemUI/src/com/android/keyguard/PasswordTextView.java
index 65edce0d98a09..8554e11a2f3cf 100644
--- a/packages/SystemUI/src/com/android/keyguard/PasswordTextView.java
+++ b/packages/SystemUI/src/com/android/keyguard/PasswordTextView.java
@@ -57,8 +57,8 @@ public class PasswordTextView extends FrameLayout {
private static final float DOT_OVERSHOOT_FACTOR = 1.5f;
private static final long DOT_APPEAR_DURATION_OVERSHOOT = 320;
- private static final long APPEAR_DURATION = 160;
- private static final long DISAPPEAR_DURATION = 160;
+ public static final long APPEAR_DURATION = 160;
+ public static final long DISAPPEAR_DURATION = 160;
private static final long RESET_DELAY_PER_ELEMENT = 40;
private static final long RESET_MAX_DELAY = 200;
@@ -284,8 +284,8 @@ public class PasswordTextView extends FrameLayout {
sendAccessibilityEventTypeViewTextChanged(textbefore, textbefore.length(), 0, 1);
}
- public void setUserActivityListener(UserActivityListener userActivitiListener) {
- mUserActivityListener = userActivitiListener;
+ public void setUserActivityListener(UserActivityListener userActivityListener) {
+ mUserActivityListener = userActivityListener;
}
private void userActivity() {
@@ -361,6 +361,8 @@ public class PasswordTextView extends FrameLayout {
}
if (!animated) {
mTextChars.clear();
+ } else {
+ userActivity();
}
if (mPinShapeInput != null) {
mPinShapeInput.reset();
@@ -410,15 +412,20 @@ public class PasswordTextView extends FrameLayout {
info.setInputType(InputType.TYPE_NUMBER_VARIATION_PASSWORD);
}
+ /**
+ * Sets whether to use pin shapes.
+ */
+ public void setUsePinShapes(boolean usePinShapes) {
+ mUsePinShapes = usePinShapes;
+ }
+
/**
* Determines whether AutoConfirmation feature is on.
*
* @param usePinShapes
* @param isPinHinting
*/
- public void setIsPinHinting(boolean usePinShapes, boolean isPinHinting) {
- mUsePinShapes = usePinShapes;
-
+ public void setIsPinHinting(boolean isPinHinting) {
if (mPinShapeInput != null) {
removeView(mPinShapeInput.getView());
mPinShapeInput = null;
@@ -426,10 +433,10 @@ public class PasswordTextView extends FrameLayout {
if (isPinHinting) {
mPinShapeInput = (PinShapeInput) LayoutInflater.from(mContext).inflate(
- R.layout.keyguard_pin_shape_six_digit_view, null);
+ R.layout.keyguard_pin_shape_hinting_view, null);
} else {
mPinShapeInput = (PinShapeInput) LayoutInflater.from(mContext).inflate(
- R.layout.keyguard_pin_shape_non_six_digit_view, null);
+ R.layout.keyguard_pin_shape_non_hinting_view, null);
}
addView(mPinShapeInput.getView());
}
diff --git a/packages/SystemUI/src/com/android/keyguard/PinShapeAdapter.kt b/packages/SystemUI/src/com/android/keyguard/PinShapeAdapter.kt
new file mode 100644
index 0000000000000..4496dc311e92b
--- /dev/null
+++ b/packages/SystemUI/src/com/android/keyguard/PinShapeAdapter.kt
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.keyguard
+
+import android.content.Context
+import com.android.systemui.R
+import kotlin.random.Random
+
+class PinShapeAdapter {
+ var shapes: MutableList = ArrayList()
+ val random = Random(System.currentTimeMillis())
+
+ constructor(context: Context) {
+ val availableShapes = context.resources.obtainTypedArray(R.array.bouncer_pin_shapes)
+
+ for (i in 0 until availableShapes.length()) {
+ val shape = availableShapes.getResourceId(i, 0)
+ shapes.add(shape)
+ }
+
+ shapes.shuffle()
+ availableShapes.recycle()
+ }
+
+ fun getShape(pos: Int): Int {
+ return shapes[pos.mod(shapes.size)]
+ }
+}
diff --git a/packages/SystemUI/src/com/android/keyguard/PinShapeHintingView.java b/packages/SystemUI/src/com/android/keyguard/PinShapeHintingView.java
index d37d7dee944bd..cf9d0537defeb 100644
--- a/packages/SystemUI/src/com/android/keyguard/PinShapeHintingView.java
+++ b/packages/SystemUI/src/com/android/keyguard/PinShapeHintingView.java
@@ -17,6 +17,7 @@
package com.android.keyguard;
import android.content.Context;
+import android.graphics.drawable.AnimatedVectorDrawable;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.View;
@@ -41,13 +42,11 @@ public class PinShapeHintingView extends LinearLayout implements PinShapeInput {
.getDefaultColor();
private int mPosition = 0;
private static final int DEFAULT_PIN_LENGTH = 6;
-
- public PinShapeHintingView(Context context) {
- super(context);
- }
+ private PinShapeAdapter mPinShapeAdapter;
public PinShapeHintingView(Context context, AttributeSet attrs) {
super(context, attrs);
+ mPinShapeAdapter = new PinShapeAdapter(context);
mPinLength = DEFAULT_PIN_LENGTH;
mDotDiameter = context.getResources().getDimensionPixelSize(R.dimen.default_dot_diameter);
mDotSpacing = context.getResources().getDimensionPixelSize(R.dimen.default_dot_spacing);
@@ -65,20 +64,12 @@ public class PinShapeHintingView extends LinearLayout implements PinShapeInput {
}
}
- public PinShapeHintingView(Context context, AttributeSet attrs, int defStyleAttr) {
- super(context, attrs, defStyleAttr);
- }
-
- public PinShapeHintingView(Context context, AttributeSet attrs, int defStyleAttr,
- int defStyleRes) {
- super(context, attrs, defStyleAttr, defStyleRes);
- }
-
@Override
public void append() {
if (mPosition == DEFAULT_PIN_LENGTH) {
return;
}
+ setAnimatedDrawable(mPosition, mPinShapeAdapter.getShape(mPosition));
mPosition++;
}
@@ -88,6 +79,7 @@ public class PinShapeHintingView extends LinearLayout implements PinShapeInput {
return;
}
mPosition--;
+ setAnimatedDrawable(mPosition, R.drawable.pin_dot_delete_avd);
}
@Override
@@ -108,4 +100,16 @@ public class PinShapeHintingView extends LinearLayout implements PinShapeInput {
public View getView() {
return this;
}
+
+ private void setAnimatedDrawable(int position, int drawableResId) {
+ ImageView pinDot = (ImageView) getChildAt(position);
+ pinDot.setImageResource(drawableResId);
+ if (pinDot.getDrawable() != null) {
+ Drawable drawable = DrawableCompat.wrap(pinDot.getDrawable());
+ DrawableCompat.setTint(drawable, mColor);
+ }
+ if (pinDot.getDrawable() instanceof AnimatedVectorDrawable) {
+ ((AnimatedVectorDrawable) pinDot.getDrawable()).start();
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/keyguard/PinShapeNonHintingView.java b/packages/SystemUI/src/com/android/keyguard/PinShapeNonHintingView.java
index e6f8ac3feacc6..6a6e81e9cb463 100644
--- a/packages/SystemUI/src/com/android/keyguard/PinShapeNonHintingView.java
+++ b/packages/SystemUI/src/com/android/keyguard/PinShapeNonHintingView.java
@@ -16,12 +16,29 @@
package com.android.keyguard;
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.ValueAnimator;
import android.content.Context;
+import android.graphics.Rect;
+import android.graphics.drawable.AnimatedVectorDrawable;
+import android.graphics.drawable.Drawable;
+import android.transition.Transition;
+import android.transition.TransitionManager;
+import android.transition.TransitionValues;
import android.util.AttributeSet;
+import android.util.Log;
import android.view.View;
+import android.view.ViewGroup;
+import android.view.animation.Animation;
+import android.widget.ImageView;
import android.widget.LinearLayout;
+import androidx.core.graphics.drawable.DrawableCompat;
+
import com.android.settingslib.Utils;
+import com.android.systemui.R;
+import com.android.systemui.animation.Interpolators;
/**
* This class contains implementation for methods that will be used when user has set a
@@ -32,36 +49,58 @@ public class PinShapeNonHintingView extends LinearLayout implements PinShapeInpu
private int mColor = Utils.getColorAttr(getContext(),
android.R.attr.textColorPrimary).getDefaultColor();
private int mPosition = 0;
-
- public PinShapeNonHintingView(Context context) {
- super(context);
- }
-
+ private final PinShapeAdapter mPinShapeAdapter;
+ private Animation mCurrentPlayingAnimation;
public PinShapeNonHintingView(Context context, AttributeSet attrs) {
super(context, attrs);
- }
-
- public PinShapeNonHintingView(Context context, AttributeSet attrs, int defStyleAttr) {
- super(context, attrs, defStyleAttr);
- }
-
- public PinShapeNonHintingView(Context context, AttributeSet attrs, int defStyleAttr,
- int defStyleRes) {
- super(context, attrs, defStyleAttr, defStyleRes);
+ mPinShapeAdapter = new PinShapeAdapter(context);
}
@Override
public void append() {
+ int size = getResources().getDimensionPixelSize(R.dimen.password_shape_size);
+ ImageView pinDot = new ImageView(getContext());
+ pinDot.setLayoutParams(new LayoutParams(size, size));
+ pinDot.setImageResource(mPinShapeAdapter.getShape(mPosition));
+ if (pinDot.getDrawable() != null) {
+ Drawable wrappedDrawable = DrawableCompat.wrap(pinDot.getDrawable());
+ DrawableCompat.setTint(wrappedDrawable, mColor);
+ }
+ if (pinDot.getDrawable() instanceof AnimatedVectorDrawable) {
+ ((AnimatedVectorDrawable) pinDot.getDrawable()).start();
+ }
+ TransitionManager.beginDelayedTransition(this, new PinShapeViewTransition());
+ addView(pinDot);
mPosition++;
}
@Override
public void delete() {
if (mPosition == 0) {
+ Log.e(getClass().getName(), "Trying to delete a non-existent char");
return;
- } else {
- mPosition--;
}
+ mPosition--;
+ ImageView pinDot = (ImageView) getChildAt(mPosition);
+ ValueAnimator animator = ValueAnimator.ofFloat(1f, 0f);
+ animator.addUpdateListener(valueAnimator -> {
+ float value = (float) valueAnimator.getAnimatedValue();
+ pinDot.setScaleX(value);
+ pinDot.setScaleY(value);
+ });
+ animator.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ super.onAnimationEnd(animation);
+ TransitionManager.beginDelayedTransition(
+ PinShapeNonHintingView.this,
+ new PinShapeViewTransition());
+ removeView(pinDot);
+ mCurrentPlayingAnimation = null;
+ }
+ });
+ animator.setDuration(PasswordTextView.DISAPPEAR_DURATION);
+ animator.start();
}
@Override
@@ -71,12 +110,74 @@ public class PinShapeNonHintingView extends LinearLayout implements PinShapeInpu
@Override
public void reset() {
- removeAllViews();
- mPosition = 0;
+ final int position = mPosition;
+ for (int i = 0; i < position; i++) {
+ delete();
+ }
}
@Override
public View getView() {
return this;
}
+
+ class PinShapeViewTransition extends Transition {
+ private static final String PROP_BOUNDS = "PinShapeViewTransition:bounds";
+
+ @Override
+ public void captureEndValues(TransitionValues transitionValues) {
+ if (transitionValues != null) {
+ captureValues(transitionValues);
+ }
+ }
+
+ @Override
+ public void captureStartValues(TransitionValues transitionValues) {
+ if (transitionValues != null) {
+ captureValues(transitionValues);
+ }
+ }
+
+ private void captureValues(TransitionValues values) {
+ Rect boundsRect = new Rect();
+ boundsRect.left = values.view.getLeft();
+ boundsRect.top = values.view.getTop();
+ boundsRect.right = values.view.getRight();
+ boundsRect.bottom = values.view.getBottom();
+ values.values.put(PROP_BOUNDS, boundsRect);
+ }
+
+ @Override
+ public String[] getTransitionProperties() {
+ return new String[] { PROP_BOUNDS };
+ }
+
+ @Override
+ public Animator createAnimator(ViewGroup sceneRoot, TransitionValues startValues,
+ TransitionValues endValues) {
+ if (sceneRoot == null || startValues == null || endValues == null) {
+ return null;
+ }
+
+ Rect startRect = (Rect) startValues.values.get(PROP_BOUNDS);
+ Rect endRect = (Rect) endValues.values.get(PROP_BOUNDS);
+ View v = startValues.view;
+ ValueAnimator animator = ValueAnimator.ofFloat(0f, 1f);
+ animator.setDuration(PasswordTextView.APPEAR_DURATION);
+ animator.setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN);
+ animator.addUpdateListener(valueAnimator -> {
+ float value = (float) valueAnimator.getAnimatedValue();
+ int diff = startRect.left - endRect.left;
+ int currentTranslation = (int) ((diff) * value);
+ v.setLeftTopRightBottom(
+ startRect.left - currentTranslation,
+ startRect.top,
+ startRect.right - currentTranslation,
+ startRect.bottom
+ );
+ });
+ animator.start();
+ return animator;
+ }
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPinViewControllerTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPinViewControllerTest.kt
index 5ba4aabc1a339..a1af8e8fac9c0 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPinViewControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPinViewControllerTest.kt
@@ -76,6 +76,8 @@ class KeyguardPinViewControllerTest : SysuiTestCase() {
@Mock lateinit var featureFlags: FeatureFlags
@Mock lateinit var passwordTextView: PasswordTextView
+ @Mock lateinit var deleteButton: NumPadButton
+ @Mock lateinit var enterButton: View
lateinit var pinViewController: KeyguardPinViewController
@@ -92,6 +94,9 @@ class KeyguardPinViewControllerTest : SysuiTestCase() {
`when`(keyguardPinView.findViewById(R.id.pinEntry))
.thenReturn(passwordTextView)
`when`(keyguardPinView.resources).thenReturn(context.resources)
+ `when`(keyguardPinView.findViewById(R.id.delete_button))
+ .thenReturn(deleteButton)
+ `when`(keyguardPinView.findViewById(R.id.key_enter)).thenReturn(enterButton)
pinViewController =
KeyguardPinViewController(
keyguardPinView,
@@ -126,8 +131,14 @@ class KeyguardPinViewControllerTest : SysuiTestCase() {
@Test
fun startAppearAnimation_withAutoPinConfirmation() {
`when`(featureFlags.isEnabled(Flags.AUTO_PIN_CONFIRMATION)).thenReturn(true)
+ `when`(lockPatternUtils.getPinLength(anyInt())).thenReturn(6)
`when`(lockPatternUtils.isAutoPinConfirmEnabled(anyInt())).thenReturn(true)
+ `when`(passwordTextView.text).thenReturn("")
+
pinViewController.startAppearAnimation()
- verify(passwordTextView).setIsPinHinting(true, true)
+ verify(deleteButton).visibility = View.INVISIBLE
+ verify(enterButton).visibility = View.INVISIBLE
+ verify(passwordTextView).setUsePinShapes(true)
+ verify(passwordTextView).setIsPinHinting(true)
}
}
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/PinShapeHintingViewTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/PinShapeHintingViewTest.kt
index c13b43158ec60..42e12df431c55 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/PinShapeHintingViewTest.kt
+++ b/packages/SystemUI/tests/src/com/android/keyguard/PinShapeHintingViewTest.kt
@@ -16,30 +16,49 @@
package com.android.keyguard
+import android.testing.AndroidTestingRunner
+import android.testing.TestableLooper
import android.view.LayoutInflater
+import androidx.test.filters.SmallTest
import com.android.systemui.R
import com.android.systemui.SysuiTestCase
+import com.google.common.truth.Truth
import org.junit.Before
import org.junit.Test
+import org.junit.runner.RunWith
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+@TestableLooper.RunWithLooper
class PinShapeHintingViewTest : SysuiTestCase() {
- lateinit var mPinShapeHintingView: PinShapeHintingView
+ lateinit var underTest: PinShapeHintingView
@Before
fun setup() {
- mPinShapeHintingView =
- LayoutInflater.from(context).inflate(R.layout.keyguard_pin_shape_six_digit_view, null)
+ underTest =
+ LayoutInflater.from(context).inflate(R.layout.keyguard_pin_shape_hinting_view, null)
as PinShapeHintingView
}
@Test
fun testAppend() {
// Add more when animation part is complete
- mPinShapeHintingView.append()
+ underTest.append()
+ Truth.assertThat(underTest.childCount).isEqualTo(6)
}
@Test
fun testDelete() {
- mPinShapeHintingView.delete()
+ underTest.delete()
+ Truth.assertThat(underTest.childCount).isEqualTo(6)
+ }
+
+ @Test
+ fun testReset() {
+ for (i in 0 until 3) {
+ underTest.append()
+ }
+ underTest.reset()
+ Truth.assertThat(underTest.childCount).isEqualTo(6)
}
}
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/PinShapeNonHintingViewTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/PinShapeNonHintingViewTest.kt
index 1bf27d2c4621f..c04fd39168de9 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/PinShapeNonHintingViewTest.kt
+++ b/packages/SystemUI/tests/src/com/android/keyguard/PinShapeNonHintingViewTest.kt
@@ -16,31 +16,59 @@
package com.android.keyguard
+import android.testing.AndroidTestingRunner
+import android.testing.TestableLooper
import android.view.LayoutInflater
+import androidx.test.filters.SmallTest
import com.android.systemui.R
import com.android.systemui.SysuiTestCase
+import com.google.common.truth.Truth
import org.junit.Before
import org.junit.Test
+import org.junit.runner.RunWith
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+@TestableLooper.RunWithLooper
class PinShapeNonHintingViewTest : SysuiTestCase() {
- lateinit var mPinShapeNonHintingView: PinShapeNonHintingView
+ lateinit var underTest: PinShapeNonHintingView
@Before
fun setup() {
- mPinShapeNonHintingView =
- LayoutInflater.from(context)
- .inflate(R.layout.keyguard_pin_shape_non_six_digit_view, null)
+ underTest =
+ LayoutInflater.from(context).inflate(R.layout.keyguard_pin_shape_non_hinting_view, null)
as PinShapeNonHintingView
}
@Test
fun testAppend() {
// Add more when animation part is complete
- mPinShapeNonHintingView.append()
+ underTest.append()
+ Truth.assertThat(underTest.childCount).isEqualTo(1)
}
@Test
fun testDelete() {
- mPinShapeNonHintingView.delete()
+ for (i in 0 until 3) {
+ underTest.append()
+ }
+ underTest.delete()
+
+ underTest.postDelayed(
+ { Truth.assertThat(underTest.childCount).isEqualTo(2) },
+ PasswordTextView.DISAPPEAR_DURATION + 100L
+ )
+ }
+
+ @Test
+ fun testReset() {
+ for (i in 0 until 3) {
+ underTest.append()
+ }
+ underTest.reset()
+ underTest.postDelayed(
+ { Truth.assertThat(underTest.childCount).isEqualTo(0) },
+ PasswordTextView.DISAPPEAR_DURATION + 100L
+ )
}
}