Changes to lockscreen for laying out the 6 digit view
This CL aims at making changes for laying out the 6 and non 6 digit PIN view, and also the logic for unlocking automatically after a user sets a 6 digit PIN. Test: Tested by building and flashing on local Bug: b/262935304 Change-Id: Ic9bde6d1572a30bbc1c03164b93c4292ca4318d3
This commit is contained in:
25
packages/SystemUI/res-keyguard/drawable/ic_shape_circle.xml
Normal file
25
packages/SystemUI/res-keyguard/drawable/ic_shape_circle.xml
Normal file
@@ -0,0 +1,25 @@
|
||||
<!--
|
||||
~ 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>
|
||||
@@ -69,6 +69,10 @@
|
||||
|
||||
<!-- The size of the dots in the PIN unlock method. -->
|
||||
<dimen name="password_dot_size">9dp</dimen>
|
||||
|
||||
<!-- The size of the shape in the PIN unlock method. -->
|
||||
<dimen name="password_shape_size">34dp</dimen>
|
||||
|
||||
<!-- The size of PIN text in the PIN unlock method. -->
|
||||
<integer name="scaled_password_text_size">40</integer>
|
||||
|
||||
@@ -139,4 +143,9 @@
|
||||
|
||||
<!-- Translation y for appear animation -->
|
||||
<dimen name="keyguard_host_view_translation_y">80dp</dimen>
|
||||
|
||||
<!-- Attributes for placeholder dots in 6 digit PIN view -->
|
||||
<dimen name="default_dot_diameter">34dp</dimen>
|
||||
<dimen name="default_dot_spacing">0dp</dimen>
|
||||
|
||||
</resources>
|
||||
|
||||
56
packages/SystemUI/res/drawable/pin_dot_avd.xml
Normal file
56
packages/SystemUI/res/drawable/pin_dot_avd.xml
Normal file
@@ -0,0 +1,56 @@
|
||||
<!--
|
||||
~ 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.
|
||||
-->
|
||||
|
||||
<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:aapt="http://schemas.android.com/aapt">
|
||||
<target android:name="time_group">
|
||||
<aapt:attr name="android:animation">
|
||||
<set android:ordering="together">
|
||||
<objectAnimator
|
||||
android:duration="500"
|
||||
android:propertyName="translateX"
|
||||
android:startOffset="0"
|
||||
android:valueFrom="0"
|
||||
android:valueTo="1"
|
||||
android:valueType="floatType" />
|
||||
</set>
|
||||
</aapt:attr>
|
||||
</target>
|
||||
<aapt:attr name="android:drawable">
|
||||
<vector
|
||||
android:width="60dp"
|
||||
android:height="61dp"
|
||||
android:viewportHeight="60"
|
||||
android:viewportWidth="60">
|
||||
<group android:name="_R_G">
|
||||
<group
|
||||
android:name="_R_G_L_0_G"
|
||||
android:translateX="43.237"
|
||||
android:translateY="38.112">
|
||||
<path
|
||||
android:name="_R_G_L_0_G_D_0_P_0"
|
||||
android:pathData=" M-13.24 -12.11 C-11.03,-12.11 -9.24,-10.32 -9.24,-8.11 C-9.24,-5.9 -11.03,-4.11 -13.24,-4.11 C-15.44,-4.11 -17.24,-5.9 -17.24,-8.11 C-17.24,-10.32 -15.44,-12.11 -13.24,-12.11c "
|
||||
android:strokeAlpha="1"
|
||||
android:strokeColor="#ffffff"
|
||||
android:strokeLineCap="round"
|
||||
android:strokeLineJoin="round"
|
||||
android:strokeWidth="2" />
|
||||
</group>
|
||||
</group>
|
||||
<group android:name="time_group" />
|
||||
</vector>
|
||||
</aapt:attr>
|
||||
</animated-vector>
|
||||
@@ -0,0 +1,23 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ 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
|
||||
-->
|
||||
<com.android.keyguard.PINShapeNonSixDigitView
|
||||
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>
|
||||
@@ -0,0 +1,23 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ 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
|
||||
-->
|
||||
<com.android.keyguard.PINShapeSixDigitView
|
||||
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>
|
||||
@@ -30,6 +30,7 @@ import com.android.keyguard.KeyguardSecurityModel.SecurityMode;
|
||||
import com.android.systemui.R;
|
||||
import com.android.systemui.classifier.FalsingCollector;
|
||||
import com.android.systemui.dagger.qualifiers.Main;
|
||||
import com.android.systemui.flags.FeatureFlags;
|
||||
import com.android.systemui.statusbar.policy.DevicePostureController;
|
||||
import com.android.systemui.util.ViewController;
|
||||
import com.android.systemui.util.concurrency.DelayableExecutor;
|
||||
@@ -184,6 +185,7 @@ public abstract class KeyguardInputViewController<T extends KeyguardInputView>
|
||||
private final FalsingCollector mFalsingCollector;
|
||||
private final DevicePostureController mDevicePostureController;
|
||||
private final KeyguardViewController mKeyguardViewController;
|
||||
private final FeatureFlags mFeatureFlags;
|
||||
|
||||
@Inject
|
||||
public Factory(KeyguardUpdateMonitor keyguardUpdateMonitor,
|
||||
@@ -195,7 +197,8 @@ public abstract class KeyguardInputViewController<T extends KeyguardInputView>
|
||||
TelephonyManager telephonyManager, FalsingCollector falsingCollector,
|
||||
EmergencyButtonController.Factory emergencyButtonControllerFactory,
|
||||
DevicePostureController devicePostureController,
|
||||
KeyguardViewController keyguardViewController) {
|
||||
KeyguardViewController keyguardViewController,
|
||||
FeatureFlags featureFlags) {
|
||||
mKeyguardUpdateMonitor = keyguardUpdateMonitor;
|
||||
mLockPatternUtils = lockPatternUtils;
|
||||
mLatencyTracker = latencyTracker;
|
||||
@@ -209,6 +212,7 @@ public abstract class KeyguardInputViewController<T extends KeyguardInputView>
|
||||
mFalsingCollector = falsingCollector;
|
||||
mDevicePostureController = devicePostureController;
|
||||
mKeyguardViewController = keyguardViewController;
|
||||
mFeatureFlags = featureFlags;
|
||||
}
|
||||
|
||||
/** Create a new {@link KeyguardInputViewController}. */
|
||||
@@ -236,7 +240,7 @@ public abstract class KeyguardInputViewController<T extends KeyguardInputView>
|
||||
mKeyguardUpdateMonitor, securityMode, mLockPatternUtils,
|
||||
keyguardSecurityCallback, mMessageAreaControllerFactory, mLatencyTracker,
|
||||
mLiftToActivateListener, emergencyButtonController, mFalsingCollector,
|
||||
mDevicePostureController);
|
||||
mDevicePostureController, mFeatureFlags);
|
||||
} else if (keyguardInputView instanceof KeyguardSimPinView) {
|
||||
return new KeyguardSimPinViewController((KeyguardSimPinView) keyguardInputView,
|
||||
mKeyguardUpdateMonitor, securityMode, mLockPatternUtils,
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
package com.android.keyguard;
|
||||
|
||||
import static com.android.systemui.keyguard.shared.constants.KeyguardBouncerConstants.DEFAULT_PIN_LENGTH;
|
||||
|
||||
import android.view.View;
|
||||
|
||||
import com.android.internal.util.LatencyTracker;
|
||||
@@ -23,6 +25,8 @@ import com.android.internal.widget.LockPatternUtils;
|
||||
import com.android.keyguard.KeyguardSecurityModel.SecurityMode;
|
||||
import com.android.systemui.R;
|
||||
import com.android.systemui.classifier.FalsingCollector;
|
||||
import com.android.systemui.flags.FeatureFlags;
|
||||
import com.android.systemui.flags.Flags;
|
||||
import com.android.systemui.statusbar.policy.DevicePostureController;
|
||||
|
||||
public class KeyguardPinViewController
|
||||
@@ -31,6 +35,12 @@ public class KeyguardPinViewController
|
||||
private final DevicePostureController mPostureController;
|
||||
private final DevicePostureController.Callback mPostureCallback = posture ->
|
||||
mView.onDevicePostureChanged(posture);
|
||||
private LockPatternUtils mLockPatternUtils;
|
||||
private final FeatureFlags mFeatureFlags;
|
||||
private View mOkButton = mView.findViewById(R.id.key_enter);
|
||||
|
||||
private int mUserId;
|
||||
private long mPinLength;
|
||||
|
||||
protected KeyguardPinViewController(KeyguardPINView view,
|
||||
KeyguardUpdateMonitor keyguardUpdateMonitor,
|
||||
@@ -40,12 +50,15 @@ public class KeyguardPinViewController
|
||||
LatencyTracker latencyTracker, LiftToActivateListener liftToActivateListener,
|
||||
EmergencyButtonController emergencyButtonController,
|
||||
FalsingCollector falsingCollector,
|
||||
DevicePostureController postureController) {
|
||||
DevicePostureController postureController,
|
||||
FeatureFlags featureFlags) {
|
||||
super(view, keyguardUpdateMonitor, securityMode, lockPatternUtils, keyguardSecurityCallback,
|
||||
messageAreaControllerFactory, latencyTracker, liftToActivateListener,
|
||||
emergencyButtonController, falsingCollector);
|
||||
mKeyguardUpdateMonitor = keyguardUpdateMonitor;
|
||||
mPostureController = postureController;
|
||||
mLockPatternUtils = lockPatternUtils;
|
||||
mFeatureFlags = featureFlags;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -59,19 +72,58 @@ public class KeyguardPinViewController
|
||||
getKeyguardSecurityCallback().onCancelClicked();
|
||||
});
|
||||
}
|
||||
|
||||
mPasswordEntry.setUserActivityListener(this::onUserInput);
|
||||
mPostureController.addCallback(mPostureCallback);
|
||||
}
|
||||
|
||||
protected void onUserInput() {
|
||||
super.onUserInput();
|
||||
if (isAutoConfirmation()) {
|
||||
if (mPasswordEntry.getText().length() == mPinLength) {
|
||||
verifyPasswordAndUnlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onViewDetached() {
|
||||
super.onViewDetached();
|
||||
mPostureController.removeCallback(mPostureCallback);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startAppearAnimation() {
|
||||
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());
|
||||
}
|
||||
super.startAppearAnimation();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean startDisappearAnimation(Runnable finishRunnable) {
|
||||
return mView.startDisappearAnimation(
|
||||
mKeyguardUpdateMonitor.needsSlowUnlockTransition(), finishRunnable);
|
||||
}
|
||||
|
||||
/*
|
||||
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
|
||||
*/
|
||||
private boolean isAutoConfirmation() {
|
||||
//Checks if user has enabled the auto confirm in Settings
|
||||
return mLockPatternUtils.isAutoPinConfirmEnabled(mUserId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,13 +35,14 @@ import android.text.InputType;
|
||||
import android.text.TextUtils;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.Gravity;
|
||||
import android.view.View;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.accessibility.AccessibilityEvent;
|
||||
import android.view.accessibility.AccessibilityManager;
|
||||
import android.view.accessibility.AccessibilityNodeInfo;
|
||||
import android.view.animation.AnimationUtils;
|
||||
import android.view.animation.Interpolator;
|
||||
import android.widget.EditText;
|
||||
import android.widget.FrameLayout;
|
||||
|
||||
import com.android.settingslib.Utils;
|
||||
import com.android.systemui.R;
|
||||
@@ -52,7 +53,7 @@ import java.util.ArrayList;
|
||||
* A View similar to a textView which contains password text and can animate when the text is
|
||||
* changed
|
||||
*/
|
||||
public class PasswordTextView extends View {
|
||||
public class PasswordTextView extends FrameLayout {
|
||||
|
||||
private static final float DOT_OVERSHOOT_FACTOR = 1.5f;
|
||||
private static final long DOT_APPEAR_DURATION_OVERSHOOT = 320;
|
||||
@@ -95,11 +96,14 @@ public class PasswordTextView extends View {
|
||||
private PowerManager mPM;
|
||||
private int mCharPadding;
|
||||
private final Paint mDrawPaint = new Paint();
|
||||
private int mDrawColor;
|
||||
private Interpolator mAppearInterpolator;
|
||||
private Interpolator mDisappearInterpolator;
|
||||
private Interpolator mFastOutSlowInInterpolator;
|
||||
private boolean mShowPassword;
|
||||
private UserActivityListener mUserActivityListener;
|
||||
private PinShapeInput mPinShapeInput;
|
||||
private boolean mUsePinShapes = false;
|
||||
|
||||
public interface UserActivityListener {
|
||||
void onUserActivity();
|
||||
@@ -141,8 +145,10 @@ public class PasswordTextView extends View {
|
||||
mCharPadding = a.getDimensionPixelSize(R.styleable.PasswordTextView_charPadding,
|
||||
getContext().getResources().getDimensionPixelSize(
|
||||
R.dimen.password_char_padding));
|
||||
mDrawPaint.setColor(a.getColor(R.styleable.PasswordTextView_android_textColor,
|
||||
Color.WHITE));
|
||||
mDrawColor = a.getColor(R.styleable.PasswordTextView_android_textColor,
|
||||
Color.WHITE);
|
||||
mDrawPaint.setColor(mDrawColor);
|
||||
|
||||
} finally {
|
||||
a.recycle();
|
||||
}
|
||||
@@ -161,6 +167,7 @@ public class PasswordTextView extends View {
|
||||
mFastOutSlowInInterpolator = AnimationUtils.loadInterpolator(mContext,
|
||||
android.R.interpolator.fast_out_slow_in);
|
||||
mPM = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
|
||||
setWillNotDraw(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -171,6 +178,12 @@ public class PasswordTextView extends View {
|
||||
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
// Do not use legacy draw animations for pin shapes.
|
||||
if (mUsePinShapes) {
|
||||
super.onDraw(canvas);
|
||||
return;
|
||||
}
|
||||
|
||||
float totalDrawingWidth = getDrawingWidth();
|
||||
float currentDrawPosition;
|
||||
if ((mGravity & Gravity.HORIZONTAL_GRAVITY_MASK) == Gravity.LEFT) {
|
||||
@@ -205,9 +218,12 @@ public class PasswordTextView extends View {
|
||||
* Reload colors from resources.
|
||||
**/
|
||||
public void reloadColors() {
|
||||
int textColor = Utils.getColorAttr(getContext(), android.R.attr.textColorPrimary)
|
||||
.getDefaultColor();
|
||||
mDrawPaint.setColor(textColor);
|
||||
mDrawColor = Utils.getColorAttr(getContext(),
|
||||
android.R.attr.textColorPrimary).getDefaultColor();
|
||||
mDrawPaint.setColor(mDrawColor);
|
||||
if (mPinShapeInput != null) {
|
||||
mPinShapeInput.setDrawColor(mDrawColor);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -252,6 +268,9 @@ public class PasswordTextView extends View {
|
||||
charState = mTextChars.get(newLength - 1);
|
||||
charState.whichChar = c;
|
||||
}
|
||||
if (mPinShapeInput != null) {
|
||||
mPinShapeInput.append();
|
||||
}
|
||||
charState.startAppearAnimation();
|
||||
|
||||
// ensure that the previous element is being swapped
|
||||
@@ -284,6 +303,9 @@ public class PasswordTextView extends View {
|
||||
CharState charState = mTextChars.get(length - 1);
|
||||
charState.startRemoveAnimation(0, 0);
|
||||
sendAccessibilityEventTypeViewTextChanged(textbefore, textbefore.length() - 1, 1, 0);
|
||||
if (mPinShapeInput != null) {
|
||||
mPinShapeInput.delete();
|
||||
}
|
||||
}
|
||||
userActivity();
|
||||
}
|
||||
@@ -340,6 +362,9 @@ public class PasswordTextView extends View {
|
||||
if (!animated) {
|
||||
mTextChars.clear();
|
||||
}
|
||||
if (mPinShapeInput != null) {
|
||||
mPinShapeInput.reset();
|
||||
}
|
||||
if (announce) {
|
||||
sendAccessibilityEventTypeViewTextChanged(textbefore, 0, textbefore.length(), 0);
|
||||
}
|
||||
@@ -385,6 +410,30 @@ public class PasswordTextView extends View {
|
||||
info.setInputType(InputType.TYPE_NUMBER_VARIATION_PASSWORD);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether AutoConfirmation feature is on.
|
||||
*
|
||||
* @param usePinShapes
|
||||
* @param isPinHinting
|
||||
*/
|
||||
public void setIsPinHinting(boolean usePinShapes, boolean isPinHinting) {
|
||||
mUsePinShapes = usePinShapes;
|
||||
|
||||
if (mPinShapeInput != null) {
|
||||
removeView(mPinShapeInput.getView());
|
||||
mPinShapeInput = null;
|
||||
}
|
||||
|
||||
if (isPinHinting) {
|
||||
mPinShapeInput = (PinShapeInput) LayoutInflater.from(mContext).inflate(
|
||||
R.layout.keyguard_pin_shape_six_digit_view, null);
|
||||
} else {
|
||||
mPinShapeInput = (PinShapeInput) LayoutInflater.from(mContext).inflate(
|
||||
R.layout.keyguard_pin_shape_non_six_digit_view, null);
|
||||
}
|
||||
addView(mPinShapeInput.getView());
|
||||
}
|
||||
|
||||
private class CharState {
|
||||
char whichChar;
|
||||
ValueAnimator textAnimator;
|
||||
|
||||
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
* 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 android.graphics.drawable.Drawable;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
|
||||
import androidx.core.graphics.drawable.DrawableCompat;
|
||||
|
||||
import com.android.settingslib.Utils;
|
||||
import com.android.systemui.R;
|
||||
|
||||
/**
|
||||
* This class contains implementation for methods that will be used when user has set a
|
||||
* six digit pin on their device
|
||||
*/
|
||||
public class PinShapeHintingView extends LinearLayout implements PinShapeInput {
|
||||
|
||||
private int mPinLength;
|
||||
private int mDotDiameter;
|
||||
private int mDotSpacing;
|
||||
private int mColor = Utils.getColorAttr(getContext(), android.R.attr.textColorPrimary)
|
||||
.getDefaultColor();
|
||||
private int mPosition = 0;
|
||||
private static final int DEFAULT_PIN_LENGTH = 6;
|
||||
|
||||
public PinShapeHintingView(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
public PinShapeHintingView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
mPinLength = DEFAULT_PIN_LENGTH;
|
||||
mDotDiameter = context.getResources().getDimensionPixelSize(R.dimen.default_dot_diameter);
|
||||
mDotSpacing = context.getResources().getDimensionPixelSize(R.dimen.default_dot_spacing);
|
||||
|
||||
for (int i = 0; i < mPinLength; i++) {
|
||||
ImageView pinDot = new ImageView(context, attrs);
|
||||
LayoutParams layoutParams = new LayoutParams(mDotDiameter, mDotDiameter);
|
||||
pinDot.setLayoutParams(layoutParams);
|
||||
pinDot.setImageResource(R.drawable.pin_dot_avd);
|
||||
if (pinDot.getDrawable() != null) {
|
||||
Drawable drawable = DrawableCompat.wrap(pinDot.getDrawable());
|
||||
DrawableCompat.setTint(drawable, mColor);
|
||||
}
|
||||
addView(pinDot);
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
mPosition++;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete() {
|
||||
if (mPosition == 0) {
|
||||
return;
|
||||
}
|
||||
mPosition--;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDrawColor(int color) {
|
||||
this.mColor = color;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
int size = mPosition;
|
||||
for (int i = 0; i < size; i++) {
|
||||
delete();
|
||||
}
|
||||
mPosition = 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public View getView() {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* 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.view.View;
|
||||
|
||||
/**
|
||||
* A common interface for classes that provide functionality for the PIN type view
|
||||
*/
|
||||
public interface PinShapeInput {
|
||||
|
||||
/**
|
||||
* This is the method that is triggered when user types in a character
|
||||
*/
|
||||
void append();
|
||||
|
||||
/**
|
||||
* This is the method that is triggered when user deletes a character
|
||||
*/
|
||||
void delete();
|
||||
|
||||
/**
|
||||
* This is the method that is triggered for setting the color of the view
|
||||
*/
|
||||
void setDrawColor(int color);
|
||||
|
||||
/**
|
||||
* This is the method that is triggered for resetting the view
|
||||
*/
|
||||
void reset();
|
||||
|
||||
/**
|
||||
* This is the method that is triggered for getting the view
|
||||
*/
|
||||
View getView();
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* 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 android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
import android.widget.LinearLayout;
|
||||
|
||||
import com.android.settingslib.Utils;
|
||||
|
||||
/**
|
||||
* This class contains implementation for methods that will be used when user has set a
|
||||
* non six digit pin on their device
|
||||
*/
|
||||
public class PinShapeNonHintingView extends LinearLayout implements PinShapeInput {
|
||||
|
||||
private int mColor = Utils.getColorAttr(getContext(),
|
||||
android.R.attr.textColorPrimary).getDefaultColor();
|
||||
private int mPosition = 0;
|
||||
|
||||
public PinShapeNonHintingView(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void append() {
|
||||
mPosition++;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete() {
|
||||
if (mPosition == 0) {
|
||||
return;
|
||||
} else {
|
||||
mPosition--;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDrawColor(int color) {
|
||||
this.mColor = color;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
removeAllViews();
|
||||
mPosition = 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public View getView() {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
@@ -26,4 +26,10 @@ object KeyguardBouncerConstants {
|
||||
const val EXPANSION_HIDDEN = 1f
|
||||
const val EXPANSION_VISIBLE = 0f
|
||||
const val ALPHA_EXPANSION_THRESHOLD = 0.95f
|
||||
|
||||
/**
|
||||
* This value is used for denoting the PIN length at which we want to layout the view in which
|
||||
* PIN hinting is enabled
|
||||
*/
|
||||
const val DEFAULT_PIN_LENGTH = 6
|
||||
}
|
||||
|
||||
@@ -27,11 +27,14 @@ import com.android.systemui.R
|
||||
import com.android.systemui.SysuiTestCase
|
||||
import com.android.systemui.classifier.FalsingCollector
|
||||
import com.android.systemui.classifier.FalsingCollectorFake
|
||||
import com.android.systemui.flags.FeatureFlags
|
||||
import com.android.systemui.flags.Flags
|
||||
import com.android.systemui.statusbar.policy.DevicePostureController
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.mockito.ArgumentMatchers.anyBoolean
|
||||
import org.mockito.ArgumentMatchers.anyInt
|
||||
import org.mockito.ArgumentMatchers.anyString
|
||||
import org.mockito.Mock
|
||||
import org.mockito.Mockito
|
||||
@@ -71,6 +74,9 @@ class KeyguardPinViewControllerTest : SysuiTestCase() {
|
||||
private val falsingCollector: FalsingCollector = FalsingCollectorFake()
|
||||
@Mock lateinit var postureController: DevicePostureController
|
||||
|
||||
@Mock lateinit var featureFlags: FeatureFlags
|
||||
@Mock lateinit var passwordTextView: PasswordTextView
|
||||
|
||||
lateinit var pinViewController: KeyguardPinViewController
|
||||
|
||||
@Before
|
||||
@@ -82,6 +88,9 @@ class KeyguardPinViewControllerTest : SysuiTestCase() {
|
||||
keyguardMessageAreaControllerFactory.create(any(KeyguardMessageArea::class.java))
|
||||
)
|
||||
.thenReturn(keyguardMessageAreaController)
|
||||
`when`(keyguardPinView.passwordTextViewId).thenReturn(R.id.pinEntry)
|
||||
`when`(keyguardPinView.findViewById<PasswordTextView>(R.id.pinEntry))
|
||||
.thenReturn(passwordTextView)
|
||||
`when`(keyguardPinView.resources).thenReturn(context.resources)
|
||||
pinViewController =
|
||||
KeyguardPinViewController(
|
||||
@@ -95,7 +104,8 @@ class KeyguardPinViewControllerTest : SysuiTestCase() {
|
||||
liftToActivateListener,
|
||||
mEmergencyButtonController,
|
||||
falsingCollector,
|
||||
postureController
|
||||
postureController,
|
||||
featureFlags
|
||||
)
|
||||
}
|
||||
|
||||
@@ -112,4 +122,12 @@ class KeyguardPinViewControllerTest : SysuiTestCase() {
|
||||
pinViewController.startAppearAnimation()
|
||||
verify(keyguardMessageAreaController, Mockito.never()).setMessage(anyString(), anyBoolean())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun startAppearAnimation_withAutoPinConfirmation() {
|
||||
`when`(featureFlags.isEnabled(Flags.AUTO_PIN_CONFIRMATION)).thenReturn(true)
|
||||
`when`(lockPatternUtils.isAutoPinConfirmEnabled(anyInt())).thenReturn(true)
|
||||
pinViewController.startAppearAnimation()
|
||||
verify(passwordTextView).setIsPinHinting(true, true)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* 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.view.LayoutInflater
|
||||
import com.android.systemui.R
|
||||
import com.android.systemui.SysuiTestCase
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
|
||||
class PinShapeHintingViewTest : SysuiTestCase() {
|
||||
lateinit var mPinShapeHintingView: PinShapeHintingView
|
||||
|
||||
@Before
|
||||
fun setup() {
|
||||
mPinShapeHintingView =
|
||||
LayoutInflater.from(context).inflate(R.layout.keyguard_pin_shape_six_digit_view, null)
|
||||
as PinShapeHintingView
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testAppend() {
|
||||
// Add more when animation part is complete
|
||||
mPinShapeHintingView.append()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testDelete() {
|
||||
mPinShapeHintingView.delete()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* 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.view.LayoutInflater
|
||||
import com.android.systemui.R
|
||||
import com.android.systemui.SysuiTestCase
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
|
||||
class PinShapeNonHintingViewTest : SysuiTestCase() {
|
||||
lateinit var mPinShapeNonHintingView: PinShapeNonHintingView
|
||||
|
||||
@Before
|
||||
fun setup() {
|
||||
mPinShapeNonHintingView =
|
||||
LayoutInflater.from(context)
|
||||
.inflate(R.layout.keyguard_pin_shape_non_six_digit_view, null)
|
||||
as PinShapeNonHintingView
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testAppend() {
|
||||
// Add more when animation part is complete
|
||||
mPinShapeNonHintingView.append()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testDelete() {
|
||||
mPinShapeNonHintingView.delete()
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user