aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKevin Jin <kjin@google.com>2014-07-02 15:11:29 -0700
committerKevin Jin <kjin@google.com>2014-07-02 15:11:29 -0700
commitd22fedf52b8cbf700142a4448b3f59254b37851e (patch)
treee435dfecbf3f57327cafd6402519c563044ee0a7
parentcf1203b8078bed407ed0035c201746fae136439a (diff)
downloaddroiddriver-android-cts-5.1_r28.tar.gz
match DefaultAccessibilityValidator to TalkBack behaviorandroid-cts-5.1_r9android-cts-5.1_r8android-cts-5.1_r7android-cts-5.1_r6android-cts-5.1_r5android-cts-5.1_r4android-cts-5.1_r3android-cts-5.1_r28android-cts-5.1_r27android-cts-5.1_r26android-cts-5.1_r25android-cts-5.1_r24android-cts-5.1_r23android-cts-5.1_r22android-cts-5.1_r21android-cts-5.1_r20android-cts-5.1_r2android-cts-5.1_r19android-cts-5.1_r18android-cts-5.1_r17android-cts-5.1_r16android-cts-5.1_r15android-cts-5.1_r14android-cts-5.1_r13android-cts-5.1_r10android-cts-5.1_r1android-cts-5.0_r9android-cts-5.0_r8android-cts-5.0_r7android-cts-5.0_r6android-cts-5.0_r5android-cts-5.0_r4android-cts-5.0_r3android-5.1.1_r9android-5.1.1_r8android-5.1.1_r7android-5.1.1_r6android-5.1.1_r5android-5.1.1_r4android-5.1.1_r38android-5.1.1_r37android-5.1.1_r36android-5.1.1_r35android-5.1.1_r34android-5.1.1_r33android-5.1.1_r30android-5.1.1_r3android-5.1.1_r29android-5.1.1_r28android-5.1.1_r26android-5.1.1_r25android-5.1.1_r24android-5.1.1_r23android-5.1.1_r22android-5.1.1_r20android-5.1.1_r2android-5.1.1_r19android-5.1.1_r18android-5.1.1_r17android-5.1.1_r16android-5.1.1_r15android-5.1.1_r14android-5.1.1_r13android-5.1.1_r12android-5.1.1_r10android-5.1.1_r1android-5.1.0_r5android-5.1.0_r4android-5.1.0_r3android-5.1.0_r1android-5.0.2_r3android-5.0.2_r1android-5.0.1_r1android-5.0.0_r7android-5.0.0_r6android-5.0.0_r5.1android-5.0.0_r5android-5.0.0_r4android-5.0.0_r3android-5.0.0_r2android-5.0.0_r1lollipop-releaselollipop-mr1-wfc-releaselollipop-mr1-releaselollipop-mr1-fi-releaselollipop-mr1-devlollipop-mr1-cts-releaselollipop-devlollipop-cts-release
Change-Id: I6c9659336b07e4a74e3435f55c9b40ce4b4fd043
-rw-r--r--src/com/google/android/droiddriver/validators/DefaultAccessibilityValidator.java50
1 files changed, 48 insertions, 2 deletions
diff --git a/src/com/google/android/droiddriver/validators/DefaultAccessibilityValidator.java b/src/com/google/android/droiddriver/validators/DefaultAccessibilityValidator.java
index b220a1b..5f49bcd 100644
--- a/src/com/google/android/droiddriver/validators/DefaultAccessibilityValidator.java
+++ b/src/com/google/android/droiddriver/validators/DefaultAccessibilityValidator.java
@@ -17,9 +17,11 @@
package com.google.android.droiddriver.validators;
import android.text.TextUtils;
+import android.view.accessibility.AccessibilityNodeInfo;
import com.google.android.droiddriver.UiElement;
import com.google.android.droiddriver.actions.Action;
+import com.google.android.droiddriver.uiautomation.UiAutomationElement;
/**
* Fall-back Validator for accessibility.
@@ -32,10 +34,54 @@ public class DefaultAccessibilityValidator implements Validator {
@Override
public String validate(UiElement element, Action action) {
- return hasContentDescriptionOrText(element) ? null : "no content description or text";
+ return isSpeakingNode(element) ? null : "TalkBack cannot speak about it";
}
- private boolean hasContentDescriptionOrText(UiElement element) {
+ // Logic from TalkBack
+ private static boolean isAccessibilityFocusable(UiElement element) {
+ if (isActionableForAccessibility(element)) {
+ return true;
+ }
+
+ if (isTopLevelScrollItem(element) && (isSpeakingNode(element))) {
+ return true;
+ }
+ return false;
+ }
+
+ private static boolean isTopLevelScrollItem(UiElement element) {
+ UiElement parent = element.getParent();
+ return parent != null && parent.isScrollable();
+ }
+
+ private static boolean isActionableForAccessibility(UiElement element) {
+ if (element.isFocusable() || element.isClickable() || element.isLongClickable()) {
+ return true;
+ }
+
+ if (element instanceof UiAutomationElement) {
+ AccessibilityNodeInfo node = ((UiAutomationElement) element).getRawElement();
+ return (node.getActions() & AccessibilityNodeInfo.ACTION_FOCUS) == AccessibilityNodeInfo.ACTION_FOCUS;
+ }
+ return false;
+ }
+
+ private static boolean isSpeakingNode(UiElement element) {
+ return hasContentDescriptionOrText(element) || element.isCheckable()
+ || hasNonActionableSpeakingChildren(element);
+ }
+
+ private static boolean hasNonActionableSpeakingChildren(UiElement element) {
+ // Recursively check visible and non-focusable descendant nodes.
+ for (UiElement child : element.getChildren(UiElement.VISIBLE)) {
+ if (!isAccessibilityFocusable(child) && isSpeakingNode(child)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private static boolean hasContentDescriptionOrText(UiElement element) {
return !TextUtils.isEmpty(element.getContentDescription())
|| !TextUtils.isEmpty(element.getText());
}