diff options
4 files changed, 162 insertions, 1 deletions
diff --git a/packages/SystemUI/res-keyguard/values/strings.xml b/packages/SystemUI/res-keyguard/values/strings.xml index 2f5222744a86..1efa3a81e5ab 100644 --- a/packages/SystemUI/res-keyguard/values/strings.xml +++ b/packages/SystemUI/res-keyguard/values/strings.xml @@ -102,6 +102,9 @@ <string name="keyguard_widget_12_hours_format" translatable="false">h\uee01mm</string> <!-- Time format strings for fall-back clock widget --> <string name="keyguard_widget_24_hours_format" translatable="false">kk\uee01mm</string> + <!-- The character used in keyguard_widget_12_hours_format and keyguard_widget_24_hours_format + to represent a ":". --> + <string name="keyguard_fancy_colon" translatable="false">\uee01</string> <!-- Accessibility description of the PIN password view. [CHAR_LIMIT=none] --> <string name="keyguard_accessibility_pin_area">PIN area</string> diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardClockAccessibilityDelegate.java b/packages/SystemUI/src/com/android/keyguard/KeyguardClockAccessibilityDelegate.java new file mode 100644 index 000000000000..80509a689a64 --- /dev/null +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardClockAccessibilityDelegate.java @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2017 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.text.TextUtils; +import android.view.View; +import android.view.accessibility.AccessibilityEvent; +import android.view.accessibility.AccessibilityNodeInfo; +import android.widget.TextView; + +/** + * Replaces fancy colons with regular colons. Only works on TextViews. + */ +class KeyguardClockAccessibilityDelegate extends View.AccessibilityDelegate { + private final String mFancyColon; + + public KeyguardClockAccessibilityDelegate(Context context) { + mFancyColon = context.getString(R.string.keyguard_fancy_colon); + } + + @Override + public void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) { + super.onInitializeAccessibilityEvent(host, event); + CharSequence text = event.getContentDescription(); + if (!TextUtils.isEmpty(text)) { + event.setContentDescription(replaceFancyColon(text)); + } + } + + @Override + public void onPopulateAccessibilityEvent(View host, AccessibilityEvent event) { + CharSequence text = ((TextView) host).getText(); + if (!TextUtils.isEmpty(text)) { + event.getText().add(replaceFancyColon(text)); + } + } + + @Override + public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) { + super.onInitializeAccessibilityNodeInfo(host, info); + if (!TextUtils.isEmpty(info.getText())) { + info.setText(replaceFancyColon(info.getText())); + } + if (!TextUtils.isEmpty(info.getContentDescription())) { + info.setContentDescription(replaceFancyColon(info.getContentDescription())); + } + } + + private CharSequence replaceFancyColon(CharSequence text) { + return text.toString().replace(mFancyColon, ":"); + } +} diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java index 162faa595ed3..d4d69ffd3b7c 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java @@ -38,7 +38,6 @@ import com.android.internal.util.ArrayUtils; import com.android.internal.widget.LockPatternUtils; import com.android.systemui.ChargingView; -import java.util.Arrays; import java.util.Locale; public class KeyguardStatusView extends GridLayout { @@ -121,6 +120,7 @@ public class KeyguardStatusView extends GridLayout { mClockView = findViewById(R.id.clock_view); mDateView.setShowCurrentUserTime(true); mClockView.setShowCurrentUserTime(true); + mClockView.setAccessibilityDelegate(new KeyguardClockAccessibilityDelegate(mContext)); mOwnerInfo = findViewById(R.id.owner_info); mBatteryDoze = findViewById(R.id.battery_doze); mVisibleInDoze = new View[]{mBatteryDoze, mClockView}; diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockAccessibilityDelegateTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockAccessibilityDelegateTest.java new file mode 100644 index 000000000000..1c9f8133a15f --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockAccessibilityDelegateTest.java @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2017 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 static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import android.content.Context; +import android.support.test.InstrumentationRegistry; +import android.text.TextUtils; +import android.view.accessibility.AccessibilityEvent; +import android.view.accessibility.AccessibilityNodeInfo; +import android.widget.TextView; + +import org.junit.Before; +import org.junit.Test; + +import java.util.List; + +public class KeyguardClockAccessibilityDelegateTest { + + private Context mContext; + private TextView mView; + + @Before + public void setUp() throws Exception { + mContext = InstrumentationRegistry.getContext(); + mView = new TextView(mContext); + mView.setText(R.string.keyguard_widget_12_hours_format); + mView.setContentDescription(mContext.getString(R.string.keyguard_widget_12_hours_format)); + mView.setAccessibilityDelegate(new KeyguardClockAccessibilityDelegate(mContext)); + } + + @Test + public void onInitializeAccessibilityEvent_producesNonEmptyAsciiContentDesc() throws Exception { + AccessibilityEvent ev = AccessibilityEvent.obtain(); + mView.onInitializeAccessibilityEvent(ev); + + assertFalse(TextUtils.isEmpty(ev.getContentDescription())); + assertTrue(isAscii(ev.getContentDescription())); + } + + @Test + public void onPopulateAccessibilityEvent_producesNonEmptyAsciiText() throws Exception { + AccessibilityEvent ev = AccessibilityEvent.obtain(); + mView.onPopulateAccessibilityEvent(ev); + + assertFalse(isEmpty(ev.getText())); + assertTrue(isAscii(ev.getText())); + } + + @Test + public void onInitializeAccessibilityNodeInfo_producesNonEmptyAsciiText() throws Exception { + AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain(); + // Usually done in View.onInitializeAccessibilityNodeInfoInternal, but only when attached. + info.setContentDescription(mView.getContentDescription()); + mView.onInitializeAccessibilityNodeInfo(info); + + assertFalse(TextUtils.isEmpty(info.getText())); + assertTrue(isAscii(info.getText())); + + assertFalse(TextUtils.isEmpty(info.getContentDescription())); + assertTrue(isAscii(info.getContentDescription())); + } + + private boolean isAscii(CharSequence text) { + return text.chars().allMatch((i) -> i < 128); + } + + private boolean isAscii(List<CharSequence> texts) { + return texts.stream().allMatch(this::isAscii); + } + + private boolean isEmpty(List<CharSequence> texts) { + return texts.stream().allMatch(TextUtils::isEmpty); + } +}
\ No newline at end of file |