[Bouncer] Add ui changes to auto confirmation.

Add pin shape avd animations to non 6 digit and 6 digit auto
confirmation screens.

Add transparent backspace key that hides and shows when text length > 0
and is auto confirmation.

Fixes: 264190150
Test: Changing pin digit size from 6 to > 6 to < 6.
Test: Inputting wrong pin code and resetting.
Test: Feature flag on/off
Change-Id: I47ce330e15e01f3a8a435eadaa1bb2d4926cbbe6
This commit is contained in:
Aaron Liu
2023-01-27 10:52:54 -08:00
parent 2dee94da2c
commit 9d54027ee3
21 changed files with 354 additions and 102 deletions

View File

@@ -1,25 +0,0 @@
<!--
~ 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.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="200dp"
android:height="200dp"
android:viewportWidth="200"
android:viewportHeight="200">
<path
android:fillColor="#FF000000"
android:pathData="M100,100m-100,0a100,100 0,1 1,200 0a100,100 0,1 1,-200 0"/>
</vector>

View File

@@ -32,4 +32,13 @@
<item>TUV</item><!-- 8 -->
<item>WXYZ</item><!-- 9 -->
</string-array>
<integer-array name="bouncer_pin_shapes">
<item>@drawable/pin_dot_shape_1_avd</item>
<item>@drawable/pin_dot_shape_2_avd</item>
<item>@drawable/pin_dot_shape_3_avd</item>
<item>@drawable/pin_dot_shape_4_avd</item>
<item>@drawable/pin_dot_shape_5_avd</item>
<item>@drawable/pin_dot_shape_6_avd</item>
</integer-array>
</resources>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -14,10 +14,10 @@
~ See the License for the specific language governing permissions and
~ limitations under the License
-->
<com.android.keyguard.PINShapeSixDigitView
<com.android.keyguard.PinShapeHintingView
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:gravity="center"
android:layout_width="match_parent"
android:layout_height="match_parent">
</com.android.keyguard.PINShapeSixDigitView>
</com.android.keyguard.PinShapeHintingView>

View File

@@ -14,10 +14,10 @@
~ See the License for the specific language governing permissions and
~ limitations under the License
-->
<com.android.keyguard.PINShapeNonSixDigitView
<com.android.keyguard.PinShapeNonHintingView
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:gravity="center"
android:layout_width="match_parent"
android:layout_height="match_parent">
</com.android.keyguard.PINShapeNonSixDigitView>
</com.android.keyguard.PinShapeNonHintingView>

View File

@@ -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

View File

@@ -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);
}

View File

@@ -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;
}
}
}

View File

@@ -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());
}

View File

@@ -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<Int> = 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)]
}
}

View File

@@ -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();
}
}
}

View File

@@ -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;
}
}
}

View File

@@ -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<PasswordTextView>(R.id.pinEntry))
.thenReturn(passwordTextView)
`when`(keyguardPinView.resources).thenReturn(context.resources)
`when`(keyguardPinView.findViewById<NumPadButton>(R.id.delete_button))
.thenReturn(deleteButton)
`when`(keyguardPinView.findViewById<View>(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)
}
}

View File

@@ -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)
}
}

View File

@@ -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
)
}
}