Use a shared password text view for PIN lock

This new library will be shared with external.

Bug: 270108982
Test: Manual test by building and flashing on local
Test: Tested  both hinting and non-hinting pin view. Tested append, delete, full delete, reset, lockout and talkback
Change-Id: I0ddc7c46848c5430d08d2b39ffa0a524e695ebc0
diff --git a/packages/SystemUI/shared/Android.bp b/packages/SystemUI/shared/Android.bp
index ca30e15..a6517c1 100644
--- a/packages/SystemUI/shared/Android.bp
+++ b/packages/SystemUI/shared/Android.bp
@@ -50,6 +50,7 @@
         "SystemUIAnimationLib",
         "SystemUIPluginLib",
         "SystemUIUnfoldLib",
+        "SystemUISharedLib-Keyguard",
         "androidx.dynamicanimation_dynamicanimation",
         "androidx.concurrent_concurrent-futures",
         "androidx.lifecycle_lifecycle-runtime-ktx",
diff --git a/packages/SystemUI/shared/keyguard/Android.bp b/packages/SystemUI/shared/keyguard/Android.bp
new file mode 100644
index 0000000..2181439
--- /dev/null
+++ b/packages/SystemUI/shared/keyguard/Android.bp
@@ -0,0 +1,16 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_packages_SystemUI_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_packages_SystemUI_license"],
+}
+
+android_library {
+    name: "SystemUISharedLib-Keyguard",
+    srcs: [
+        "src/**/*.java",
+    ],
+    min_sdk_version: "current",
+}
diff --git a/packages/SystemUI/shared/keyguard/AndroidManifest.xml b/packages/SystemUI/shared/keyguard/AndroidManifest.xml
new file mode 100644
index 0000000..49bee08
--- /dev/null
+++ b/packages/SystemUI/shared/keyguard/AndroidManifest.xml
@@ -0,0 +1,20 @@
+<?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.
+  -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          package="com.android.systemui.shared.keyguard">
+</manifest>
\ No newline at end of file
diff --git a/packages/SystemUI/shared/keyguard/src/com/android/keyguard/BasePasswordTextView.java b/packages/SystemUI/shared/keyguard/src/com/android/keyguard/BasePasswordTextView.java
new file mode 100644
index 0000000..fe12134
--- /dev/null
+++ b/packages/SystemUI/shared/keyguard/src/com/android/keyguard/BasePasswordTextView.java
@@ -0,0 +1,239 @@
+/*
+ * 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.annotation.CallSuper;
+import android.content.Context;
+import android.text.InputType;
+import android.text.TextUtils;
+import android.util.AttributeSet;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityManager;
+import android.view.accessibility.AccessibilityNodeInfo;
+import android.widget.EditText;
+import android.widget.FrameLayout;
+
+/**
+ * A View similar to a textView which contains password text and can animate when the text is
+ * changed
+ */
+public abstract class BasePasswordTextView extends FrameLayout {
+    private String mText = "";
+    private UserActivityListener mUserActivityListener;
+    protected boolean mIsPinHinting;
+    protected PinShapeInput mPinShapeInput;
+    protected boolean mShowPassword = true;
+    protected boolean mUsePinShapes = false;
+    protected static final char DOT = '\u2022';
+
+    /** Listens to user activities like appending, deleting and resetting PIN text */
+    public interface UserActivityListener {
+
+        /** Listens to user activities. */
+        void onUserActivity();
+    }
+
+    public BasePasswordTextView(Context context) {
+        this(context, null);
+    }
+
+    public BasePasswordTextView(Context context, AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    public BasePasswordTextView(Context context, AttributeSet attrs, int defStyleAttr) {
+        this(context, attrs, defStyleAttr, 0);
+    }
+
+    public BasePasswordTextView(
+            Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
+        super(context, attrs, defStyleAttr, defStyleRes);
+    }
+
+    protected abstract PinShapeInput inflatePinShapeInput(boolean isPinHinting);
+
+    protected abstract boolean shouldSendAccessibilityEvent();
+
+    protected void onAppend(char c, int newLength) {}
+
+    protected void onDelete(int index) {}
+
+    protected void onReset(boolean animated) {}
+
+    @CallSuper
+    protected void onUserActivity() {
+        if (mUserActivityListener != null) {
+            mUserActivityListener.onUserActivity();
+        }
+    }
+
+    @Override
+    public boolean hasOverlappingRendering() {
+        return false;
+    }
+
+    /** Appends a PIN text */
+    public void append(char c) {
+        CharSequence textbefore = getTransformedText();
+
+        mText = mText + c;
+        int newLength = mText.length();
+        onAppend(c, newLength);
+
+        if (mPinShapeInput != null) {
+            mPinShapeInput.append();
+        }
+
+        onUserActivity();
+
+        sendAccessibilityEventTypeViewTextChanged(textbefore, textbefore.length(), 0, 1);
+    }
+
+    /** Sets a listener who is notified on user activity */
+    public void setUserActivityListener(UserActivityListener userActivityListener) {
+        mUserActivityListener = userActivityListener;
+    }
+
+    /** Deletes the last PIN text */
+    public void deleteLastChar() {
+        int length = mText.length();
+        if (length > 0) {
+            CharSequence textbefore = getTransformedText();
+
+            mText = mText.substring(0, length - 1);
+            onDelete(length - 1);
+
+            if (mPinShapeInput != null) {
+                mPinShapeInput.delete();
+            }
+
+            sendAccessibilityEventTypeViewTextChanged(textbefore, textbefore.length() - 1, 1, 0);
+        }
+        onUserActivity();
+    }
+
+    /** Gets entered PIN text */
+    public String getText() {
+        return mText;
+    }
+
+    /** Gets a transformed text for accessibility event. Called before text changed. */
+    protected CharSequence getTransformedText() {
+        return String.valueOf(DOT).repeat(mText.length());
+    }
+
+    /** Gets a transformed text for accessibility event. Called after text changed. */
+    protected CharSequence getTransformedText(int fromIndex, int removedCount, int addedCount) {
+        return getTransformedText();
+    }
+
+    /** Reset PIN text without error */
+    public void reset(boolean animated, boolean announce) {
+        reset(false /* error */, animated, announce);
+    }
+
+    /** Reset PIN text */
+    public void reset(boolean error, boolean animated, boolean announce) {
+        CharSequence textbefore = getTransformedText();
+
+        mText = "";
+
+        onReset(animated);
+        if (animated) {
+            onUserActivity();
+        }
+
+        if (mPinShapeInput != null) {
+            if (error) {
+                mPinShapeInput.resetWithError();
+            } else {
+                mPinShapeInput.reset();
+            }
+        }
+
+        if (announce) {
+            sendAccessibilityEventTypeViewTextChanged(textbefore, 0, textbefore.length(), 0);
+        }
+    }
+
+    void sendAccessibilityEventTypeViewTextChanged(
+            CharSequence beforeText, int fromIndex, int removedCount, int addedCount) {
+        if (AccessibilityManager.getInstance(mContext).isEnabled()
+                && shouldSendAccessibilityEvent()) {
+            AccessibilityEvent event =
+                    AccessibilityEvent.obtain(AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED);
+            event.setFromIndex(fromIndex);
+            event.setRemovedCount(removedCount);
+            event.setAddedCount(addedCount);
+            event.setBeforeText(beforeText);
+            CharSequence transformedText = getTransformedText(fromIndex, removedCount, addedCount);
+            if (!TextUtils.isEmpty(transformedText)) {
+                event.getText().add(transformedText);
+            }
+            event.setPassword(true);
+            sendAccessibilityEventUnchecked(event);
+        }
+    }
+
+    /** Sets whether to use pin shapes. */
+    public void setUsePinShapes(boolean usePinShapes) {
+        mUsePinShapes = usePinShapes;
+    }
+
+    /** Determines whether AutoConfirmation feature is on. */
+    public void setIsPinHinting(boolean isPinHinting) {
+        // Do not reinflate the view if we are using the same one.
+        if (mPinShapeInput != null && mIsPinHinting == isPinHinting) {
+            return;
+        }
+        mIsPinHinting = isPinHinting;
+
+        if (mPinShapeInput != null) {
+            removeView(mPinShapeInput.getView());
+            mPinShapeInput = null;
+        }
+
+        mPinShapeInput = inflatePinShapeInput(isPinHinting);
+        addView(mPinShapeInput.getView());
+    }
+
+    /** Controls whether the last entered digit is briefly shown after being entered */
+    public void setShowPassword(boolean enabled) {
+        mShowPassword = enabled;
+    }
+
+    @Override
+    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
+        super.onInitializeAccessibilityEvent(event);
+
+        event.setClassName(EditText.class.getName());
+        event.setPassword(true);
+    }
+
+    @Override
+    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
+        super.onInitializeAccessibilityNodeInfo(info);
+
+        info.setClassName(EditText.class.getName());
+        info.setPassword(true);
+        info.setText(getTransformedText());
+
+        info.setEditable(true);
+
+        info.setInputType(InputType.TYPE_NUMBER_VARIATION_PASSWORD);
+    }
+}
diff --git a/packages/SystemUI/src/com/android/keyguard/PinShapeInput.java b/packages/SystemUI/shared/keyguard/src/com/android/keyguard/PinShapeInput.java
similarity index 85%
rename from packages/SystemUI/src/com/android/keyguard/PinShapeInput.java
rename to packages/SystemUI/shared/keyguard/src/com/android/keyguard/PinShapeInput.java
index 52ae6ba..d2b4066 100644
--- a/packages/SystemUI/src/com/android/keyguard/PinShapeInput.java
+++ b/packages/SystemUI/shared/keyguard/src/com/android/keyguard/PinShapeInput.java
@@ -44,6 +44,14 @@
     void reset();
 
     /**
+     * This is the method that is triggered for resetting the view with error If it doesn't have to
+     * show something regarding error, just reset
+     */
+    default void resetWithError() {
+        reset();
+    }
+
+    /**
      * This is the method that is triggered for getting the view
      */
     View getView();
diff --git a/packages/SystemUI/src/com/android/keyguard/PasswordTextView.java b/packages/SystemUI/src/com/android/keyguard/PasswordTextView.java
index 8e8ee48..9a2ffe0 100644
--- a/packages/SystemUI/src/com/android/keyguard/PasswordTextView.java
+++ b/packages/SystemUI/src/com/android/keyguard/PasswordTextView.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2014 The Android Open Source Project
+ * 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.
@@ -11,7 +11,7 @@
  * 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
+ * limitations under the License.
  */
 
 package com.android.keyguard;
@@ -30,18 +30,11 @@
 import android.graphics.Typeface;
 import android.os.PowerManager;
 import android.os.SystemClock;
-import android.text.InputType;
-import android.text.TextUtils;
 import android.util.AttributeSet;
 import android.view.Gravity;
 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,12 +45,11 @@
  * A View similar to a textView which contains password text and can animate when the text is
  * changed
  */
-public class PasswordTextView extends FrameLayout {
-
-    private static final float DOT_OVERSHOOT_FACTOR = 1.5f;
-    private static final long DOT_APPEAR_DURATION_OVERSHOOT = 320;
+public class PasswordTextView extends BasePasswordTextView {
     public static final long APPEAR_DURATION = 160;
     public static final long DISAPPEAR_DURATION = 160;
+    private static final float DOT_OVERSHOOT_FACTOR = 1.5f;
+    private static final long DOT_APPEAR_DURATION_OVERSHOOT = 320;
     private static final long RESET_DELAY_PER_ELEMENT = 40;
     private static final long RESET_MAX_DELAY = 200;
 
@@ -82,15 +74,12 @@
      */
     private static final float OVERSHOOT_TIME_POSITION = 0.5f;
 
-    private static char DOT = '\u2022';
-
     /**
      * The raw text size, will be multiplied by the scaled density when drawn
      */
     private int mTextHeightRaw;
     private final int mGravity;
     private ArrayList<CharState> mTextChars = new ArrayList<>();
-    private String mText = "";
     private int mDotSize;
     private PowerManager mPM;
     private int mCharPadding;
@@ -99,15 +88,6 @@
     private Interpolator mAppearInterpolator;
     private Interpolator mDisappearInterpolator;
     private Interpolator mFastOutSlowInInterpolator;
-    private boolean mShowPassword = true;
-    private UserActivityListener mUserActivityListener;
-    private boolean mIsPinHinting;
-    private PinShapeInput mPinShapeInput;
-    private boolean mUsePinShapes = false;
-
-    public interface UserActivityListener {
-        void onUserActivity();
-    }
 
     public PasswordTextView(Context context) {
         this(context, null);
@@ -145,8 +125,7 @@
             mCharPadding = a.getDimensionPixelSize(R.styleable.PasswordTextView_charPadding,
                     getContext().getResources().getDimensionPixelSize(
                             R.dimen.password_char_padding));
-            mDrawColor = a.getColor(R.styleable.PasswordTextView_android_textColor,
-                    Color.WHITE);
+            mDrawColor = a.getColor(R.styleable.PasswordTextView_android_textColor, Color.WHITE);
             mDrawPaint.setColor(mDrawColor);
 
         } finally {
@@ -156,8 +135,7 @@
         mDrawPaint.setFlags(Paint.SUBPIXEL_TEXT_FLAG | Paint.ANTI_ALIAS_FLAG);
         mDrawPaint.setTextAlign(Paint.Align.CENTER);
         mDrawPaint.setTypeface(Typeface.create(
-                context.getString(com.android.internal.R.string.config_headlineFontFamily),
-                0));
+                context.getString(com.android.internal.R.string.config_headlineFontFamily), 0));
         mAppearInterpolator = AnimationUtils.loadInterpolator(mContext,
                 android.R.interpolator.linear_out_slow_in);
         mDisappearInterpolator = AnimationUtils.loadInterpolator(mContext,
@@ -169,9 +147,19 @@
     }
 
     @Override
-    protected void onConfigurationChanged(Configuration newConfig) {
-        mTextHeightRaw = getContext().getResources().getInteger(
-                R.integer.scaled_password_text_size);
+    protected PinShapeInput inflatePinShapeInput(boolean isPinHinting) {
+        if (isPinHinting) {
+            return (PinShapeInput) LayoutInflater.from(mContext).inflate(
+                    R.layout.keyguard_pin_shape_hinting_view, null);
+        } else {
+            return (PinShapeInput) LayoutInflater.from(mContext).inflate(
+                    R.layout.keyguard_pin_shape_non_hinting_view, null);
+        }
+    }
+
+    @Override
+    protected boolean shouldSendAccessibilityEvent() {
+        return isFocused() || isSelected() && isShown();
     }
 
     @Override
@@ -201,8 +189,8 @@
         int charHeight = (bounds.bottom - bounds.top);
         float yPosition =
                 (getHeight() - getPaddingBottom() - getPaddingTop()) / 2 + getPaddingTop();
-        canvas.clipRect(getPaddingLeft(), getPaddingTop(),
-                getWidth() - getPaddingRight(), getHeight() - getPaddingBottom());
+        canvas.clipRect(getPaddingLeft(), getPaddingTop(), getWidth() - getPaddingRight(),
+                getHeight() - getPaddingBottom());
         float charLength = bounds.right - bounds.left;
         for (int i = 0; i < length; i++) {
             CharState charState = mTextChars.get(i);
@@ -212,6 +200,67 @@
         }
     }
 
+    @Override
+    protected void onAppend(char c, int newLength) {
+        int visibleChars = mTextChars.size();
+        CharState charState;
+        if (newLength > visibleChars) {
+            charState = obtainCharState(c);
+            mTextChars.add(charState);
+        } else {
+            charState = mTextChars.get(newLength - 1);
+            charState.whichChar = c;
+        }
+        charState.startAppearAnimation();
+
+        // ensure that the previous element is being swapped
+        if (newLength > 1) {
+            CharState previousState = mTextChars.get(newLength - 2);
+            if (previousState.isDotSwapPending) {
+                previousState.swapToDotWhenAppearFinished();
+            }
+        }
+    }
+
+    @Override
+    protected void onDelete(int index) {
+        CharState charState = mTextChars.get(index);
+        charState.startRemoveAnimation(0, 0);
+    }
+
+    @Override
+    protected void onReset(boolean animated) {
+        if (animated) {
+            int length = mTextChars.size();
+            int middleIndex = (length - 1) / 2;
+            long delayPerElement = RESET_DELAY_PER_ELEMENT;
+            for (int i = 0; i < length; i++) {
+                CharState charState = mTextChars.get(i);
+                int delayIndex;
+                if (i <= middleIndex) {
+                    delayIndex = i * 2;
+                } else {
+                    int distToMiddle = i - middleIndex;
+                    delayIndex = (length - 1) - (distToMiddle - 1) * 2;
+                }
+                long startDelay = delayIndex * delayPerElement;
+                startDelay = Math.min(startDelay, RESET_MAX_DELAY);
+                long maxDelay = delayPerElement * (length - 1);
+                maxDelay = Math.min(maxDelay, RESET_MAX_DELAY) + DISAPPEAR_DURATION;
+                charState.startRemoveAnimation(startDelay, maxDelay);
+                charState.removeDotSwapCallbacks();
+            }
+        } else {
+            mTextChars.clear();
+        }
+    }
+
+    @Override
+    protected void onUserActivity() {
+        mPM.userActivity(SystemClock.uptimeMillis(), false);
+        super.onUserActivity();
+    }
+
     /**
      * Reload colors from resources.
      **/
@@ -225,8 +274,9 @@
     }
 
     @Override
-    public boolean hasOverlappingRendering() {
-        return false;
+    protected void onConfigurationChanged(Configuration newConfig) {
+        mTextHeightRaw = getContext().getResources().getInteger(
+                R.integer.scaled_password_text_size);
     }
 
     private Rect getCharBounds() {
@@ -252,67 +302,14 @@
         return width;
     }
 
-
-    public void append(char c) {
-        int visibleChars = mTextChars.size();
-        CharSequence textbefore = getTransformedText();
-        mText = mText + c;
-        int newLength = mText.length();
-        CharState charState;
-        if (newLength > visibleChars) {
-            charState = obtainCharState(c);
-            mTextChars.add(charState);
-        } else {
-            charState = mTextChars.get(newLength - 1);
-            charState.whichChar = c;
-        }
-        if (mPinShapeInput != null) {
-            mPinShapeInput.append();
-        }
-        charState.startAppearAnimation();
-
-        // ensure that the previous element is being swapped
-        if (newLength > 1) {
-            CharState previousState = mTextChars.get(newLength - 2);
-            if (previousState.isDotSwapPending) {
-                previousState.swapToDotWhenAppearFinished();
-            }
-        }
-        userActivity();
-        sendAccessibilityEventTypeViewTextChanged(textbefore, textbefore.length(), 0, 1);
+    private CharState obtainCharState(char c) {
+        CharState charState = new CharState();
+        charState.whichChar = c;
+        return charState;
     }
 
-    public void setUserActivityListener(UserActivityListener userActivityListener) {
-        mUserActivityListener = userActivityListener;
-    }
-
-    private void userActivity() {
-        mPM.userActivity(SystemClock.uptimeMillis(), false);
-        if (mUserActivityListener != null) {
-            mUserActivityListener.onUserActivity();
-        }
-    }
-
-    public void deleteLastChar() {
-        int length = mText.length();
-        CharSequence textbefore = getTransformedText();
-        if (length > 0) {
-            mText = mText.substring(0, length - 1);
-            CharState charState = mTextChars.get(length - 1);
-            charState.startRemoveAnimation(0, 0);
-            sendAccessibilityEventTypeViewTextChanged(textbefore, textbefore.length() - 1, 1, 0);
-            if (mPinShapeInput != null) {
-                mPinShapeInput.delete();
-            }
-        }
-        userActivity();
-    }
-
-    public String getText() {
-        return mText;
-    }
-
-    private CharSequence getTransformedText() {
+    @Override
+    protected CharSequence getTransformedText() {
         int textLength = mTextChars.size();
         StringBuilder stringBuilder = new StringBuilder(textLength);
         for (int i = 0; i < textLength; i++) {
@@ -327,130 +324,6 @@
         return stringBuilder;
     }
 
-    private CharState obtainCharState(char c) {
-        CharState charState = new CharState();
-        charState.whichChar = c;
-        return charState;
-    }
-
-    public void reset(boolean animated, boolean announce) {
-        CharSequence textbefore = getTransformedText();
-        mText = "";
-        int length = mTextChars.size();
-        int middleIndex = (length - 1) / 2;
-        long delayPerElement = RESET_DELAY_PER_ELEMENT;
-        for (int i = 0; i < length; i++) {
-            CharState charState = mTextChars.get(i);
-            if (animated) {
-                int delayIndex;
-                if (i <= middleIndex) {
-                    delayIndex = i * 2;
-                } else {
-                    int distToMiddle = i - middleIndex;
-                    delayIndex = (length - 1) - (distToMiddle - 1) * 2;
-                }
-                long startDelay = delayIndex * delayPerElement;
-                startDelay = Math.min(startDelay, RESET_MAX_DELAY);
-                long maxDelay = delayPerElement * (length - 1);
-                maxDelay = Math.min(maxDelay, RESET_MAX_DELAY) + DISAPPEAR_DURATION;
-                charState.startRemoveAnimation(startDelay, maxDelay);
-                charState.removeDotSwapCallbacks();
-            }
-        }
-        if (!animated) {
-            mTextChars.clear();
-        } else {
-            userActivity();
-        }
-        if (mPinShapeInput != null) {
-            mPinShapeInput.reset();
-        }
-        if (announce) {
-            sendAccessibilityEventTypeViewTextChanged(textbefore, 0, textbefore.length(), 0);
-        }
-    }
-
-    void sendAccessibilityEventTypeViewTextChanged(CharSequence beforeText, int fromIndex,
-                                                   int removedCount, int addedCount) {
-        if (AccessibilityManager.getInstance(mContext).isEnabled() &&
-                (isFocused() || isSelected() && isShown())) {
-            AccessibilityEvent event =
-                    AccessibilityEvent.obtain(AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED);
-            event.setFromIndex(fromIndex);
-            event.setRemovedCount(removedCount);
-            event.setAddedCount(addedCount);
-            event.setBeforeText(beforeText);
-            CharSequence transformedText = getTransformedText();
-            if (!TextUtils.isEmpty(transformedText)) {
-                event.getText().add(transformedText);
-            }
-            event.setPassword(true);
-            sendAccessibilityEventUnchecked(event);
-        }
-    }
-
-    @Override
-    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
-        super.onInitializeAccessibilityEvent(event);
-
-        event.setClassName(EditText.class.getName());
-        event.setPassword(true);
-    }
-
-    @Override
-    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
-        super.onInitializeAccessibilityNodeInfo(info);
-
-        info.setClassName(EditText.class.getName());
-        info.setPassword(true);
-        info.setText(getTransformedText());
-
-        info.setEditable(true);
-
-        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 isPinHinting
-     */
-    public void setIsPinHinting(boolean isPinHinting) {
-        // Do not reinflate the view if we are using the same one.
-        if (mPinShapeInput != null && mIsPinHinting == isPinHinting) {
-            return;
-        }
-        mIsPinHinting = isPinHinting;
-
-        if (mPinShapeInput != null) {
-            removeView(mPinShapeInput.getView());
-            mPinShapeInput = null;
-        }
-
-        if (isPinHinting) {
-            mPinShapeInput = (PinShapeInput) LayoutInflater.from(mContext).inflate(
-                    R.layout.keyguard_pin_shape_hinting_view, null);
-        } else {
-            mPinShapeInput = (PinShapeInput) LayoutInflater.from(mContext).inflate(
-                    R.layout.keyguard_pin_shape_non_hinting_view, null);
-        }
-        addView(mPinShapeInput.getView());
-    }
-
-    /**
-     * Controls whether the last entered digit is briefly shown after being entered
-     */
-    public void setShowPassword(boolean enabled) {
-        mShowPassword = enabled;
-    }
-
     private class CharState {
         char whichChar;
         ValueAnimator textAnimator;
@@ -468,6 +341,7 @@
 
         Animator.AnimatorListener removeEndListener = new AnimatorListenerAdapter() {
             private boolean mCancelled;
+
             @Override
             public void onAnimationCancel(Animator animation) {
                 mCancelled = true;
@@ -516,53 +390,53 @@
             }
         };
 
-        private ValueAnimator.AnimatorUpdateListener dotSizeUpdater
-                = new ValueAnimator.AnimatorUpdateListener() {
-            @Override
-            public void onAnimationUpdate(ValueAnimator animation) {
-                currentDotSizeFactor = (float) animation.getAnimatedValue();
-                invalidate();
-            }
-        };
-
-        private ValueAnimator.AnimatorUpdateListener textSizeUpdater
-                = new ValueAnimator.AnimatorUpdateListener() {
-            @Override
-            public void onAnimationUpdate(ValueAnimator animation) {
-                boolean textVisibleBefore = isCharVisibleForA11y();
-                float beforeTextSizeFactor = currentTextSizeFactor;
-                currentTextSizeFactor = (float) animation.getAnimatedValue();
-                if (textVisibleBefore != isCharVisibleForA11y()) {
-                    currentTextSizeFactor = beforeTextSizeFactor;
-                    CharSequence beforeText = getTransformedText();
-                    currentTextSizeFactor = (float) animation.getAnimatedValue();
-                    int indexOfThisChar = mTextChars.indexOf(CharState.this);
-                    if (indexOfThisChar >= 0) {
-                        sendAccessibilityEventTypeViewTextChanged(
-                                beforeText, indexOfThisChar, 1, 1);
+        private ValueAnimator.AnimatorUpdateListener mDotSizeUpdater =
+                new ValueAnimator.AnimatorUpdateListener() {
+                    @Override
+                    public void onAnimationUpdate(ValueAnimator animation) {
+                        currentDotSizeFactor = (float) animation.getAnimatedValue();
+                        invalidate();
                     }
-                }
-                invalidate();
-            }
-        };
+                };
 
-        private ValueAnimator.AnimatorUpdateListener textTranslationUpdater
-                = new ValueAnimator.AnimatorUpdateListener() {
-            @Override
-            public void onAnimationUpdate(ValueAnimator animation) {
-                currentTextTranslationY = (float) animation.getAnimatedValue();
-                invalidate();
-            }
-        };
+        private ValueAnimator.AnimatorUpdateListener mTextSizeUpdater =
+                new ValueAnimator.AnimatorUpdateListener() {
+                    @Override
+                    public void onAnimationUpdate(ValueAnimator animation) {
+                        boolean textVisibleBefore = isCharVisibleForA11y();
+                        float beforeTextSizeFactor = currentTextSizeFactor;
+                        currentTextSizeFactor = (float) animation.getAnimatedValue();
+                        if (textVisibleBefore != isCharVisibleForA11y()) {
+                            currentTextSizeFactor = beforeTextSizeFactor;
+                            CharSequence beforeText = getTransformedText();
+                            currentTextSizeFactor = (float) animation.getAnimatedValue();
+                            int indexOfThisChar = mTextChars.indexOf(CharState.this);
+                            if (indexOfThisChar >= 0) {
+                                sendAccessibilityEventTypeViewTextChanged(beforeText,
+                                        indexOfThisChar, 1, 1);
+                            }
+                        }
+                        invalidate();
+                    }
+                };
 
-        private ValueAnimator.AnimatorUpdateListener widthUpdater
-                = new ValueAnimator.AnimatorUpdateListener() {
-            @Override
-            public void onAnimationUpdate(ValueAnimator animation) {
-                currentWidthFactor = (float) animation.getAnimatedValue();
-                invalidate();
-            }
-        };
+        private ValueAnimator.AnimatorUpdateListener mTextTranslationUpdater =
+                new ValueAnimator.AnimatorUpdateListener() {
+                    @Override
+                    public void onAnimationUpdate(ValueAnimator animation) {
+                        currentTextTranslationY = (float) animation.getAnimatedValue();
+                        invalidate();
+                    }
+                };
+
+        private ValueAnimator.AnimatorUpdateListener mWidthUpdater =
+                new ValueAnimator.AnimatorUpdateListener() {
+                    @Override
+                    public void onAnimationUpdate(ValueAnimator animation) {
+                        currentWidthFactor = (float) animation.getAnimatedValue();
+                        invalidate();
+                    }
+                };
 
         private Runnable dotSwapperRunnable = new Runnable() {
             @Override
@@ -573,12 +447,15 @@
         };
 
         void startRemoveAnimation(long startDelay, long widthDelay) {
-            boolean dotNeedsAnimation = (currentDotSizeFactor > 0.0f && dotAnimator == null)
-                    || (dotAnimator != null && dotAnimationIsGrowing);
-            boolean textNeedsAnimation = (currentTextSizeFactor > 0.0f && textAnimator == null)
-                    || (textAnimator != null && textAnimationIsGrowing);
-            boolean widthNeedsAnimation = (currentWidthFactor > 0.0f && widthAnimator == null)
-                    || (widthAnimator != null && widthAnimationIsGrowing);
+            boolean dotNeedsAnimation =
+                    (currentDotSizeFactor > 0.0f && dotAnimator == null) || (dotAnimator != null
+                            && dotAnimationIsGrowing);
+            boolean textNeedsAnimation =
+                    (currentTextSizeFactor > 0.0f && textAnimator == null) || (textAnimator != null
+                            && textAnimationIsGrowing);
+            boolean widthNeedsAnimation =
+                    (currentWidthFactor > 0.0f && widthAnimator == null) || (widthAnimator != null
+                            && widthAnimationIsGrowing);
             if (dotNeedsAnimation) {
                 startDotDisappearAnimation(startDelay);
             }
@@ -591,10 +468,10 @@
         }
 
         void startAppearAnimation() {
-            boolean dotNeedsAnimation = !mShowPassword
-                    && (dotAnimator == null || !dotAnimationIsGrowing);
-            boolean textNeedsAnimation = mShowPassword
-                    && (textAnimator == null || !textAnimationIsGrowing);
+            boolean dotNeedsAnimation =
+                    !mShowPassword && (dotAnimator == null || !dotAnimationIsGrowing);
+            boolean textNeedsAnimation =
+                    mShowPassword && (textAnimator == null || !textAnimationIsGrowing);
             boolean widthNeedsAnimation = (widthAnimator == null || !widthAnimationIsGrowing);
             if (dotNeedsAnimation) {
                 startDotAppearAnimation(0);
@@ -628,8 +505,8 @@
         void swapToDotWhenAppearFinished() {
             removeDotSwapCallbacks();
             if (textAnimator != null) {
-                long remainingDuration = textAnimator.getDuration()
-                        - textAnimator.getCurrentPlayTime();
+                long remainingDuration =
+                        textAnimator.getDuration() - textAnimator.getCurrentPlayTime();
                 postDotSwap(remainingDuration + TEXT_REST_DURATION_AFTER_APPEAR);
             } else {
                 performSwap();
@@ -638,14 +515,14 @@
 
         private void performSwap() {
             startTextDisappearAnimation(0);
-            startDotAppearAnimation(DISAPPEAR_DURATION
-                    - DOT_APPEAR_TEXT_DISAPPEAR_OVERLAP_DURATION);
+            startDotAppearAnimation(
+                    DISAPPEAR_DURATION - DOT_APPEAR_TEXT_DISAPPEAR_OVERLAP_DURATION);
         }
 
         private void startWidthDisappearAnimation(long widthDelay) {
             cancelAnimator(widthAnimator);
             widthAnimator = ValueAnimator.ofFloat(currentWidthFactor, 0.0f);
-            widthAnimator.addUpdateListener(widthUpdater);
+            widthAnimator.addUpdateListener(mWidthUpdater);
             widthAnimator.addListener(widthFinishListener);
             widthAnimator.addListener(removeEndListener);
             widthAnimator.setDuration((long) (DISAPPEAR_DURATION * currentWidthFactor));
@@ -657,7 +534,7 @@
         private void startTextDisappearAnimation(long startDelay) {
             cancelAnimator(textAnimator);
             textAnimator = ValueAnimator.ofFloat(currentTextSizeFactor, 0.0f);
-            textAnimator.addUpdateListener(textSizeUpdater);
+            textAnimator.addUpdateListener(mTextSizeUpdater);
             textAnimator.addListener(textFinishListener);
             textAnimator.setInterpolator(mDisappearInterpolator);
             textAnimator.setDuration((long) (DISAPPEAR_DURATION * currentTextSizeFactor));
@@ -669,7 +546,7 @@
         private void startDotDisappearAnimation(long startDelay) {
             cancelAnimator(dotAnimator);
             ValueAnimator animator = ValueAnimator.ofFloat(currentDotSizeFactor, 0.0f);
-            animator.addUpdateListener(dotSizeUpdater);
+            animator.addUpdateListener(mDotSizeUpdater);
             animator.addListener(dotFinishListener);
             animator.setInterpolator(mDisappearInterpolator);
             long duration = (long) (DISAPPEAR_DURATION * Math.min(currentDotSizeFactor, 1.0f));
@@ -683,7 +560,7 @@
         private void startWidthAppearAnimation() {
             cancelAnimator(widthAnimator);
             widthAnimator = ValueAnimator.ofFloat(currentWidthFactor, 1.0f);
-            widthAnimator.addUpdateListener(widthUpdater);
+            widthAnimator.addUpdateListener(mWidthUpdater);
             widthAnimator.addListener(widthFinishListener);
             widthAnimator.setDuration((long) (APPEAR_DURATION * (1f - currentWidthFactor)));
             widthAnimator.start();
@@ -693,7 +570,7 @@
         private void startTextAppearAnimation() {
             cancelAnimator(textAnimator);
             textAnimator = ValueAnimator.ofFloat(currentTextSizeFactor, 1.0f);
-            textAnimator.addUpdateListener(textSizeUpdater);
+            textAnimator.addUpdateListener(mTextSizeUpdater);
             textAnimator.addListener(textFinishListener);
             textAnimator.setInterpolator(mAppearInterpolator);
             textAnimator.setDuration((long) (APPEAR_DURATION * (1f - currentTextSizeFactor)));
@@ -703,7 +580,7 @@
             // handle translation
             if (textTranslateAnimator == null) {
                 textTranslateAnimator = ValueAnimator.ofFloat(1.0f, 0.0f);
-                textTranslateAnimator.addUpdateListener(textTranslationUpdater);
+                textTranslateAnimator.addUpdateListener(mTextTranslationUpdater);
                 textTranslateAnimator.addListener(textTranslateFinishListener);
                 textTranslateAnimator.setInterpolator(mAppearInterpolator);
                 textTranslateAnimator.setDuration(APPEAR_DURATION);
@@ -717,14 +594,14 @@
                 // We perform an overshoot animation
                 ValueAnimator overShootAnimator = ValueAnimator.ofFloat(currentDotSizeFactor,
                         DOT_OVERSHOOT_FACTOR);
-                overShootAnimator.addUpdateListener(dotSizeUpdater);
+                overShootAnimator.addUpdateListener(mDotSizeUpdater);
                 overShootAnimator.setInterpolator(mAppearInterpolator);
-                long overShootDuration = (long) (DOT_APPEAR_DURATION_OVERSHOOT
-                        * OVERSHOOT_TIME_POSITION);
+                long overShootDuration =
+                        (long) (DOT_APPEAR_DURATION_OVERSHOOT * OVERSHOOT_TIME_POSITION);
                 overShootAnimator.setDuration(overShootDuration);
                 ValueAnimator settleBackAnimator = ValueAnimator.ofFloat(DOT_OVERSHOOT_FACTOR,
                         1.0f);
-                settleBackAnimator.addUpdateListener(dotSizeUpdater);
+                settleBackAnimator.addUpdateListener(mDotSizeUpdater);
                 settleBackAnimator.setDuration(DOT_APPEAR_DURATION_OVERSHOOT - overShootDuration);
                 settleBackAnimator.addListener(dotFinishListener);
                 AnimatorSet animatorSet = new AnimatorSet();
@@ -734,7 +611,7 @@
                 dotAnimator = animatorSet;
             } else {
                 ValueAnimator growAnimator = ValueAnimator.ofFloat(currentDotSizeFactor, 1.0f);
-                growAnimator.addUpdateListener(dotSizeUpdater);
+                growAnimator.addUpdateListener(mDotSizeUpdater);
                 growAnimator.setDuration((long) (APPEAR_DURATION * (1.0f - currentDotSizeFactor)));
                 growAnimator.addListener(dotFinishListener);
                 growAnimator.setStartDelay(delay);