Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit ed88d0a

Browse files
author
Michael Klimushyn
authored
Change SemanticsNode#children lists to be non-null (#10952)
Prevents NPEs and simplifies the code needed to handle these collections. There doesn't seem to have been a meaningful difference between null and empty collection here. The specific crash was happening when `object.scrollChildren > 0` while `object.childrenInHitTestOrder == null`, which looks like it may be a bug on its own and probably needs further investigation.
1 parent 853464e commit ed88d0a

File tree

1 file changed

+40
-61
lines changed

1 file changed

+40
-61
lines changed

shell/platform/android/io/flutter/view/AccessibilityBridge.java

Lines changed: 40 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -756,11 +756,9 @@ public AccessibilityNodeInfo createAccessibilityNodeInfo(int virtualViewId) {
756756
}
757757
}
758758

759-
if (semanticsNode.childrenInTraversalOrder != null) {
760-
for (SemanticsNode child : semanticsNode.childrenInTraversalOrder) {
761-
if (!child.hasFlag(Flag.IS_HIDDEN)) {
762-
result.addChild(rootAccessibilityView, child.id);
763-
}
759+
for (SemanticsNode child : semanticsNode.childrenInTraversalOrder) {
760+
if (!child.hasFlag(Flag.IS_HIDDEN)) {
761+
result.addChild(rootAccessibilityView, child.id);
764762
}
765763
}
766764

@@ -1335,6 +1333,10 @@ void updateSemantics(@NonNull ByteBuffer buffer, @NonNull String[] strings) {
13351333
if (object.scrollIndex + visibleChildren > object.scrollChildren) {
13361334
Log.e(TAG, "Scroll index is out of bounds.");
13371335
}
1336+
1337+
if (object.childrenInHitTestOrder.isEmpty()) {
1338+
Log.e(TAG, "Had scrollChildren but no childrenInHitTestOrder");
1339+
}
13381340
}
13391341
// The setToIndex should be the index of the last visible child. Because we counted all
13401342
// children, including the first index we need to subtract one.
@@ -1752,8 +1754,8 @@ private static boolean nullableHasAncestor(SemanticsNode target, Predicate<Seman
17521754
private float[] transform;
17531755

17541756
private SemanticsNode parent;
1755-
private List<SemanticsNode> childrenInTraversalOrder;
1756-
private List<SemanticsNode> childrenInHitTestOrder;
1757+
private List<SemanticsNode> childrenInTraversalOrder = new ArrayList<>();
1758+
private List<SemanticsNode> childrenInHitTestOrder = new ArrayList<>();
17571759
private List<CustomAccessibilityAction> customAccessibilityActions;
17581760
private CustomAccessibilityAction onTapOverride;
17591761
private CustomAccessibilityAction onLongPressOverride;
@@ -1833,7 +1835,7 @@ private void log(@NonNull String indent, boolean recursive) {
18331835
+ textDirection + "\n" + indent + " +-- rect.ltrb=(" + left + ", "
18341836
+ top + ", " + right + ", " + bottom + ")\n" + indent
18351837
+ " +-- transform=" + Arrays.toString(transform) + "\n");
1836-
if (childrenInTraversalOrder != null && recursive) {
1838+
if (recursive) {
18371839
String childIndent = indent + " ";
18381840
for (SemanticsNode child : childrenInTraversalOrder) {
18391841
child.log(childIndent, recursive);
@@ -1897,32 +1899,19 @@ private void updateWith(@NonNull ByteBuffer buffer, @NonNull String[] strings) {
18971899
globalGeometryDirty = true;
18981900

18991901
final int childCount = buffer.getInt();
1900-
if (childCount == 0) {
1901-
childrenInTraversalOrder = null;
1902-
childrenInHitTestOrder = null;
1903-
} else {
1904-
if (childrenInTraversalOrder == null)
1905-
childrenInTraversalOrder = new ArrayList<>(childCount);
1906-
else
1907-
childrenInTraversalOrder.clear();
1908-
1909-
for (int i = 0; i < childCount; ++i) {
1910-
SemanticsNode child = accessibilityBridge.getOrCreateSemanticsNode(buffer.getInt());
1911-
child.parent = this;
1912-
childrenInTraversalOrder.add(child);
1913-
}
1914-
1915-
if (childrenInHitTestOrder == null)
1916-
childrenInHitTestOrder = new ArrayList<>(childCount);
1917-
else
1918-
childrenInHitTestOrder.clear();
1919-
1920-
for (int i = 0; i < childCount; ++i) {
1921-
SemanticsNode child = accessibilityBridge.getOrCreateSemanticsNode(buffer.getInt());
1922-
child.parent = this;
1923-
childrenInHitTestOrder.add(child);
1924-
}
1902+
childrenInTraversalOrder.clear();
1903+
childrenInHitTestOrder.clear();
1904+
for (int i = 0; i < childCount; ++i) {
1905+
SemanticsNode child = accessibilityBridge.getOrCreateSemanticsNode(buffer.getInt());
1906+
child.parent = this;
1907+
childrenInTraversalOrder.add(child);
1908+
}
1909+
for (int i = 0; i < childCount; ++i) {
1910+
SemanticsNode child = accessibilityBridge.getOrCreateSemanticsNode(buffer.getInt());
1911+
child.parent = this;
1912+
childrenInHitTestOrder.add(child);
19251913
}
1914+
19261915
final int actionCount = buffer.getInt();
19271916
if (actionCount == 0) {
19281917
customAccessibilityActions = null;
@@ -1976,19 +1965,16 @@ private SemanticsNode hitTest(float[] point) {
19761965
final float x = point[0] / w;
19771966
final float y = point[1] / w;
19781967
if (x < left || x >= right || y < top || y >= bottom) return null;
1979-
if (childrenInHitTestOrder != null) {
1980-
final float[] transformedPoint = new float[4];
1981-
for (int i = 0; i < childrenInHitTestOrder.size(); i += 1) {
1982-
final SemanticsNode child = childrenInHitTestOrder.get(i);
1983-
if (child.hasFlag(Flag.IS_HIDDEN)) {
1984-
continue;
1985-
}
1986-
child.ensureInverseTransform();
1987-
Matrix.multiplyMV(transformedPoint, 0, child.inverseTransform, 0, point, 0);
1988-
final SemanticsNode result = child.hitTest(transformedPoint);
1989-
if (result != null) {
1990-
return result;
1991-
}
1968+
final float[] transformedPoint = new float[4];
1969+
for (SemanticsNode child : childrenInHitTestOrder) {
1970+
if (child.hasFlag(Flag.IS_HIDDEN)) {
1971+
continue;
1972+
}
1973+
child.ensureInverseTransform();
1974+
Matrix.multiplyMV(transformedPoint, 0, child.inverseTransform, 0, point, 0);
1975+
final SemanticsNode result = child.hitTest(transformedPoint);
1976+
if (result != null) {
1977+
return result;
19921978
}
19931979
}
19941980
return this;
@@ -2013,10 +1999,8 @@ private void collectRoutes(List<SemanticsNode> edges) {
20131999
if (hasFlag(Flag.SCOPES_ROUTE)) {
20142000
edges.add(this);
20152001
}
2016-
if (childrenInTraversalOrder != null) {
2017-
for (int i = 0; i < childrenInTraversalOrder.size(); ++i) {
2018-
childrenInTraversalOrder.get(i).collectRoutes(edges);
2019-
}
2002+
for (SemanticsNode child : childrenInTraversalOrder) {
2003+
child.collectRoutes(edges);
20202004
}
20212005
}
20222006

@@ -2028,12 +2012,10 @@ private String getRouteName() {
20282012
return label;
20292013
}
20302014
}
2031-
if (childrenInTraversalOrder != null) {
2032-
for (int i = 0; i < childrenInTraversalOrder.size(); ++i) {
2033-
String newName = childrenInTraversalOrder.get(i).getRouteName();
2034-
if (newName != null && !newName.isEmpty()) {
2035-
return newName;
2036-
}
2015+
for (SemanticsNode child : childrenInTraversalOrder) {
2016+
String newName = child.getRouteName();
2017+
if (newName != null && !newName.isEmpty()) {
2018+
return newName;
20372019
}
20382020
}
20392021
return null;
@@ -2097,11 +2079,8 @@ private void updateRecursively(float[] ancestorTransform, Set<SemanticsNode> vis
20972079
}
20982080
}
20992081

2100-
if (childrenInTraversalOrder != null) {
2101-
for (int i = 0; i < childrenInTraversalOrder.size(); ++i) {
2102-
childrenInTraversalOrder.get(i).updateRecursively(
2103-
globalTransform, visitedObjects, forceUpdate);
2104-
}
2082+
for (SemanticsNode child : childrenInTraversalOrder) {
2083+
child.updateRecursively(globalTransform, visitedObjects, forceUpdate);
21052084
}
21062085
}
21072086

0 commit comments

Comments
 (0)