OSDN Git Service

Fix accessibility reporting for lock screen PIN
authorPhil Weaver <pweaver@google.com>
Wed, 20 Dec 2017 18:54:13 +0000 (10:54 -0800)
committerPhil Weaver <pweaver@google.com>
Thu, 21 Dec 2017 01:04:23 +0000 (17:04 -0800)
Now reporting what is shown on the screen and generating
events when that changes as dots replace the numbers.

Bug: 69454936
Test: Manually observing the event stream as I enter a PIN
on the lock screen.

Change-Id: I4c0afe1140006192b57febb500ea982976645652

packages/SystemUI/src/com/android/keyguard/PasswordTextView.java

index 12f75bb..d3dded0 100644 (file)
@@ -31,6 +31,7 @@ import android.os.PowerManager;
 import android.os.SystemClock;
 import android.provider.Settings;
 import android.text.InputType;
+import android.text.TextUtils;
 import android.util.AttributeSet;
 import android.view.Gravity;
 import android.view.View;
@@ -78,6 +79,8 @@ public class PasswordTextView extends View {
      */
     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
      */
@@ -208,7 +211,7 @@ public class PasswordTextView extends View {
 
     public void append(char c) {
         int visibleChars = mTextChars.size();
-        String textbefore = mText;
+        CharSequence textbefore = getTransformedText();
         mText = mText + c;
         int newLength = mText.length();
         CharState charState;
@@ -245,7 +248,7 @@ public class PasswordTextView extends View {
 
     public void deleteLastChar() {
         int length = mText.length();
-        String textbefore = mText;
+        CharSequence textbefore = getTransformedText();
         if (length > 0) {
             mText = mText.substring(0, length - 1);
             CharState charState = mTextChars.get(length - 1);
@@ -259,6 +262,21 @@ public class PasswordTextView extends View {
         return mText;
     }
 
+    private CharSequence getTransformedText() {
+        int textLength = mTextChars.size();
+        StringBuilder stringBuilder = new StringBuilder(textLength);
+        for (int i = 0; i < textLength; i++) {
+            CharState charState = mTextChars.get(i);
+            // If the dot is disappearing, the character is disappearing entirely. Consider
+            // it gone.
+            if (charState.dotAnimator != null && !charState.dotAnimationIsGrowing) {
+                continue;
+            }
+            stringBuilder.append(charState.isCharVisibleForA11y() ? charState.whichChar : DOT);
+        }
+        return stringBuilder;
+    }
+
     private CharState obtainCharState(char c) {
         CharState charState;
         if(mCharPool.isEmpty()) {
@@ -272,7 +290,7 @@ public class PasswordTextView extends View {
     }
 
     public void reset(boolean animated, boolean announce) {
-        String textbefore = mText;
+        CharSequence textbefore = getTransformedText();
         mText = "";
         int length = mTextChars.size();
         int middleIndex = (length - 1) / 2;
@@ -305,7 +323,7 @@ public class PasswordTextView extends View {
         }
     }
 
-    void sendAccessibilityEventTypeViewTextChanged(String beforeText, int fromIndex,
+    void sendAccessibilityEventTypeViewTextChanged(CharSequence beforeText, int fromIndex,
                                                    int removedCount, int addedCount) {
         if (AccessibilityManager.getInstance(mContext).isEnabled() &&
                 (isFocused() || isSelected() && isShown())) {
@@ -315,6 +333,10 @@ public class PasswordTextView extends View {
             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);
         }
@@ -332,8 +354,9 @@ public class PasswordTextView extends View {
     public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
         super.onInitializeAccessibilityNodeInfo(info);
 
-        info.setClassName(PasswordTextView.class.getName());
+        info.setClassName(EditText.class.getName());
         info.setPassword(true);
+        info.setText(getTransformedText());
 
         info.setEditable(true);
 
@@ -420,7 +443,19 @@ public class PasswordTextView extends View {
                 = 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();
             }
         };
@@ -673,5 +708,13 @@ public class PasswordTextView extends View {
             }
             return charWidth + mCharPadding * currentWidthFactor;
         }
+
+        public boolean isCharVisibleForA11y() {
+            // The text has size 0 when it is first added, but we want to count it as visible if
+            // it will become visible presently. Count text as visible if an animator
+            // is configured to make it grow.
+            boolean textIsGrowing = textAnimator != null && textAnimationIsGrowing;
+            return (currentTextSizeFactor > 0) || textIsGrowing;
+        }
     }
 }