Update AX sidebar properties - clarify focus vs accessibility-focus

Summary: Updated properties to be more specific about what type of focus they are describing (keyboard vs accessibility vs talkback). Also separates sidebar into 3 sections (View, Talkback, and AccessibilityNodeInfo) since this organization is clearer now that Talkback is more robust.

Reviewed By: blavalla

Differential Revision: D9338822

fbshipit-source-id: d110faa43822faa36a081832207c259cddec44f0
This commit is contained in:
Sara Valderrama
2018-08-15 20:35:18 -07:00
committed by Facebook Github Bot
parent e82808da6f
commit 6a746d744e
4 changed files with 32 additions and 35 deletions

View File

@@ -15,7 +15,6 @@ import android.view.accessibility.AccessibilityEvent;
import android.view.MotionEvent; import android.view.MotionEvent;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.view.accessibility.AccessibilityManager;
import com.facebook.sonar.core.ErrorReportingRunnable; import com.facebook.sonar.core.ErrorReportingRunnable;
import com.facebook.sonar.core.SonarArray; import com.facebook.sonar.core.SonarArray;
import com.facebook.sonar.core.SonarConnection; import com.facebook.sonar.core.SonarConnection;

View File

@@ -50,8 +50,9 @@ import javax.annotation.Nullable;
public class ViewDescriptor extends NodeDescriptor<View> { public class ViewDescriptor extends NodeDescriptor<View> {
private static final String axViewPropsTitle = "Accessibility View"; private static final String axViewPropsTitle = "View";
private static final String axNodeInfoPropsTitle = "NodeInfo & TalkBack"; private static final String axNodeInfoPropsTitle = "AccessibilityNodeInfo";
private static final String axTalkbackPropsTitle = "Talkback";
private static Field sKeyedTagsField; private static Field sKeyedTagsField;
private static Field sListenerInfoField; private static Field sListenerInfoField;
@@ -202,7 +203,8 @@ public class ViewDescriptor extends NodeDescriptor<View> {
@Override @Override
public List<Named<SonarObject>> getAXData(View node) { public List<Named<SonarObject>> getAXData(View node) {
return Arrays.asList( return Arrays.asList(
new Named<>(axNodeInfoPropsTitle, AccessibilityUtil.getDerivedAXData(node)), new Named<>(axNodeInfoPropsTitle, AccessibilityUtil.getAccessibilityNodeInfoData(node)),
new Named<>(axTalkbackPropsTitle, AccessibilityUtil.getTalkbackData(node)),
new Named<>(axViewPropsTitle, AccessibilityUtil.getViewAXData(node))); new Named<>(axViewPropsTitle, AccessibilityUtil.getViewAXData(node)));
} }
@@ -233,7 +235,8 @@ public class ViewDescriptor extends NodeDescriptor<View> {
public void setValue(View node, String[] path, SonarDynamic value) { public void setValue(View node, String[] path, SonarDynamic value) {
if (path[0].equals("Accessibility") if (path[0].equals("Accessibility")
|| path[0].equals(axViewPropsTitle) || path[0].equals(axViewPropsTitle)
|| path[0].equals(axNodeInfoPropsTitle)) { || path[0].equals(axNodeInfoPropsTitle)
|| path[0].equals(axTalkbackPropsTitle)) {
setAccessibilityValue(node, path, value); setAccessibilityValue(node, path, value);
return; return;
} }

View File

@@ -548,7 +548,7 @@ public final class AccessibilityUtil {
.put("clickable", nodeInfo.isClickable()) .put("clickable", nodeInfo.isClickable())
.put("content-description", nodeInfo.getContentDescription()) .put("content-description", nodeInfo.getContentDescription())
.put("text", nodeInfo.getText()) .put("text", nodeInfo.getText())
.put("focused", nodeInfo.isAccessibilityFocused()) .put("accessibility-focused", nodeInfo.isAccessibilityFocused())
.put("long-clickable", nodeInfo.isLongClickable()) .put("long-clickable", nodeInfo.isLongClickable())
.put("focusable", nodeInfo.isFocusable()); .put("focusable", nodeInfo.isFocusable());
@@ -581,7 +581,7 @@ public final class AccessibilityUtil {
/** /**
* Creates a {@link SonarObject} of useful properties of AccessibilityNodeInfo, to be shown in the * Creates a {@link SonarObject} of useful properties of AccessibilityNodeInfo, to be shown in the
* Sonar Layout Inspector extension. All properties are immutable since they are all derived from * Sonar Layout Inspector accessibility extension. All properties are immutable since they are all derived from
* various {@link View} properties. This is a more complete list than * various {@link View} properties. This is a more complete list than
* getAccessibilityNodeInfoProperties returns. * getAccessibilityNodeInfoProperties returns.
* *
@@ -589,7 +589,7 @@ public final class AccessibilityUtil {
* @return {@link SonarObject} containing the properties. * @return {@link SonarObject} containing the properties.
*/ */
@Nullable @Nullable
public static SonarObject getAXNodeInfoProperties(View view) { public static SonarObject getAccessibilityNodeInfoData(View view) {
final AccessibilityNodeInfoCompat nodeInfo = final AccessibilityNodeInfoCompat nodeInfo =
ViewAccessibilityHelper.createNodeInfoFromView(view); ViewAccessibilityHelper.createNodeInfoFromView(view);
if (nodeInfo == null) { if (nodeInfo == null) {
@@ -615,6 +615,7 @@ public final class AccessibilityUtil {
} }
nodeInfoProps nodeInfoProps
.put("accessibility-focused", nodeInfo.isAccessibilityFocused())
.put("checkable", nodeInfo.isCheckable()) .put("checkable", nodeInfo.isCheckable())
.put("checked", nodeInfo.isChecked()) .put("checked", nodeInfo.isChecked())
.put("clickable", nodeInfo.isClickable()) .put("clickable", nodeInfo.isClickable())
@@ -625,9 +626,9 @@ public final class AccessibilityUtil {
.put("drawing-order", nodeInfo.getDrawingOrder()) .put("drawing-order", nodeInfo.getDrawingOrder())
.put("editable", nodeInfo.isEditable()) .put("editable", nodeInfo.isEditable())
.put("enabled", nodeInfo.isEnabled()) .put("enabled", nodeInfo.isEnabled())
.put("focusable", nodeInfo.isFocusable())
.put("focused", nodeInfo.isAccessibilityFocused())
.put("important-for-accessibility", nodeInfo.isImportantForAccessibility()) .put("important-for-accessibility", nodeInfo.isImportantForAccessibility())
.put("focusable", nodeInfo.isFocusable())
.put("focused", nodeInfo.isFocused())
.put("long-clickable", nodeInfo.isLongClickable()) .put("long-clickable", nodeInfo.isLongClickable())
.put("multiline", nodeInfo.isMultiLine()) .put("multiline", nodeInfo.isMultiLine())
.put("password", nodeInfo.isPassword()) .put("password", nodeInfo.isPassword())
@@ -702,12 +703,13 @@ public final class AccessibilityUtil {
// This needs to be an empty string to be mutable. See t20470623. // This needs to be an empty string to be mutable. See t20470623.
CharSequence contentDescription = CharSequence contentDescription =
view.getContentDescription() != null ? view.getContentDescription() : ""; view.getContentDescription() != null ? view.getContentDescription() : "";
props.put("content-description", InspectorValue.mutable(contentDescription)); props.put("content-description", InspectorValue.mutable(contentDescription))
props.put("focusable", InspectorValue.mutable(view.isFocusable())); .put("focusable", InspectorValue.mutable(view.isFocusable()))
props.put("selected", InspectorValue.mutable(view.isSelected())); .put("selected", InspectorValue.mutable(view.isSelected()))
props.put("long-clickable", InspectorValue.mutable(view.isLongClickable())); .put("enabled", InspectorValue.mutable(view.isEnabled()))
props.put("clickable", InspectorValue.mutable(view.isClickable())); .put("long-clickable", InspectorValue.mutable(view.isLongClickable()))
props.put("focused", view.isFocused()); .put("clickable", InspectorValue.mutable(view.isClickable()))
.put("focused", view.isFocused());
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
props.put("accessibility-focused", view.isAccessibilityFocused()); props.put("accessibility-focused", view.isAccessibilityFocused());
@@ -723,30 +725,23 @@ public final class AccessibilityUtil {
return props.build(); return props.build();
} }
public static SonarObject getDerivedAXData(View view) { public static SonarObject getTalkbackData(View view) {
final SonarObject.Builder props = new SonarObject.Builder();
if (!AccessibilityEvaluationUtil.isTalkbackFocusable(view)) { if (!AccessibilityEvaluationUtil.isTalkbackFocusable(view)) {
String reason = getTalkbackIgnoredReasons(view); String reason = getTalkbackIgnoredReasons(view);
props return new SonarObject.Builder()
.put("talkback-ignored", true) .put("talkback-ignored", true)
.put("talkback-ignored-reasons", reason == null ? "" : reason); .put("talkback-ignored-reasons", reason == null ? "" : reason)
.build();
} else { } else {
String reason = getTalkbackFocusableReasons(view); String reason = getTalkbackFocusableReasons(view);
CharSequence description = getTalkbackDescription(view); CharSequence description = getTalkbackDescription(view);
CharSequence hint = getTalkbackHint(view); CharSequence hint = getTalkbackHint(view);
props return new SonarObject.Builder()
.put("talkback-focusable", true) .put("talkback-focusable", true)
.put("talkback-focusable-reasons", reason) .put("talkback-focusable-reasons", reason)
.put("talkback-output", description) .put("talkback-output", description)
.put("talkback-hint", hint); .put("talkback-hint", hint)
.build();
} }
SonarObject axNodeInfo = getAXNodeInfoProperties(view);
if (axNodeInfo != null) {
props.put("node-info", axNodeInfo);
}
return props.build();
} }
} }

View File

@@ -261,7 +261,7 @@ public class DebugComponentDescriptor extends NodeDescriptor<DebugComponent> {
} }
// host view exists so add node info and TalkBack properties // host view exists so add node info and TalkBack properties
props.put("node-info", AccessibilityUtil.getAXNodeInfoProperties(hostView)); props.put("node-info", AccessibilityUtil.getAccessibilityNodeInfoData(hostView));
AccessibilityUtil.addTalkbackProperties(props, hostView); AccessibilityUtil.addTalkbackProperties(props, hostView);
return props.build(); return props.build();