summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Alan Viverette <alanv@google.com> 2016-01-22 10:14:02 -0500
committer Alan Viverette <alanv@google.com> 2016-01-22 10:14:02 -0500
commita7b85e6855fa8474a002b0bcce62ab988c3636a9 (patch)
tree7bf97891be6b8a14e49787dc8d695c22b5de07ba
parentb7cc096fd49e99c01a9e963a895f6d26d685e474 (diff)
Verify results of methods called during child ordering
Also updates nullability annotations for methods called during touch dispatch. Verifies that TouchTarget and HoverTarget are not recycled multiple times. Bug: 26611563 Change-Id: Ica5ff18e18b325b12fe72b8ca145443b25625fe4
-rw-r--r--core/java/android/view/ViewGroup.java123
1 files changed, 85 insertions, 38 deletions
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 868dddaa0270..fbe4c5d41941 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -1653,10 +1653,9 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
&& isChildrenDrawingOrderEnabled();
final View[] children = mChildren;
for (int i = childrenCount - 1; i >= 0; i--) {
- final int childIndex = customOrder ? getChildDrawingOrder(childrenCount, i) : i;
- final View child = (preorderedList == null)
- ? children[childIndex] : preorderedList.get(childIndex);
- PointF point = getLocalPoint();
+ final int childIndex = getAndVerifyPreorderedIndex(childrenCount, i, customOrder);
+ final View child = getAndVerifyPreorderedView(preorderedList, children, childIndex);
+ final PointF point = getLocalPoint();
if (isTransformedTouchPointInView(x, y, child, point)) {
final PointerIcon pointerIcon = child.getPointerIcon(event, point.x, point.y);
if (pointerIcon != null) {
@@ -1672,6 +1671,22 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
return super.getPointerIcon(event, x, y);
}
+ private int getAndVerifyPreorderedIndex(int childrenCount, int i, boolean customOrder) {
+ final int childIndex;
+ if (customOrder) {
+ final int childIndex1 = getChildDrawingOrder(childrenCount, i);
+ if (childIndex1 >= childrenCount) {
+ throw new IndexOutOfBoundsException("getChildDrawingOrder() "
+ + "returned invalid index " + childIndex1
+ + " (child count is " + childrenCount + ")");
+ }
+ childIndex = childIndex1;
+ } else {
+ childIndex = i;
+ }
+ return childIndex;
+ }
+
@SuppressWarnings({"ConstantConditions"})
@Override
protected boolean dispatchHoverEvent(MotionEvent event) {
@@ -1699,9 +1714,10 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
final View[] children = mChildren;
HoverTarget lastHoverTarget = null;
for (int i = childrenCount - 1; i >= 0; i--) {
- int childIndex = customOrder ? getChildDrawingOrder(childrenCount, i) : i;
- final View child = (preorderedList == null)
- ? children[childIndex] : preorderedList.get(childIndex);
+ final int childIndex = getAndVerifyPreorderedIndex(
+ childrenCount, i, customOrder);
+ final View child = getAndVerifyPreorderedView(
+ preorderedList, children, childIndex);
if (!canViewReceivePointerEvents(child)
|| !isTransformedTouchPointInView(x, y, child, null)) {
continue;
@@ -1983,9 +1999,8 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
&& isChildrenDrawingOrderEnabled();
final View[] children = mChildren;
for (int i = childrenCount - 1; i >= 0; i--) {
- int childIndex = customOrder ? getChildDrawingOrder(childrenCount, i) : i;
- final View child = (preorderedList == null)
- ? children[childIndex] : preorderedList.get(childIndex);
+ final int childIndex = getAndVerifyPreorderedIndex(childrenCount, i, customOrder);
+ final View child = getAndVerifyPreorderedView(preorderedList, children, childIndex);
if (!canViewReceivePointerEvents(child)
|| !isTransformedTouchPointInView(x, y, child, null)) {
continue;
@@ -2132,10 +2147,10 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
&& isChildrenDrawingOrderEnabled();
final View[] children = mChildren;
for (int i = childrenCount - 1; i >= 0; i--) {
- final int childIndex = customOrder
- ? getChildDrawingOrder(childrenCount, i) : i;
- final View child = (preorderedList == null)
- ? children[childIndex] : preorderedList.get(childIndex);
+ final int childIndex = getAndVerifyPreorderedIndex(
+ childrenCount, i, customOrder);
+ final View child = getAndVerifyPreorderedView(
+ preorderedList, children, childIndex);
// If there is a view that has accessibility focus we want it
// to get the event first and if not handled we will perform a
@@ -2313,7 +2328,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
* Resets the cancel next up flag.
* Returns true if the flag was previously set.
*/
- private static boolean resetCancelNextUpFlag(View view) {
+ private static boolean resetCancelNextUpFlag(@NonNull View view) {
if ((view.mPrivateFlags & PFLAG_CANCEL_NEXT_UP_EVENT) != 0) {
view.mPrivateFlags &= ~PFLAG_CANCEL_NEXT_UP_EVENT;
return true;
@@ -2366,7 +2381,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
* Gets the touch target for specified child view.
* Returns null if not found.
*/
- private TouchTarget getTouchTarget(View child) {
+ private TouchTarget getTouchTarget(@NonNull View child) {
for (TouchTarget target = mFirstTouchTarget; target != null; target = target.next) {
if (target.child == child) {
return target;
@@ -2379,8 +2394,8 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
* Adds a touch target for specified child to the beginning of the list.
* Assumes the target child is not already present.
*/
- private TouchTarget addTouchTarget(View child, int pointerIdBits) {
- TouchTarget target = TouchTarget.obtain(child, pointerIdBits);
+ private TouchTarget addTouchTarget(@NonNull View child, int pointerIdBits) {
+ final TouchTarget target = TouchTarget.obtain(child, pointerIdBits);
target.next = mFirstTouchTarget;
mFirstTouchTarget = target;
return target;
@@ -2442,7 +2457,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
* Returns true if a child view can receive pointer events.
* @hide
*/
- private static boolean canViewReceivePointerEvents(View child) {
+ private static boolean canViewReceivePointerEvents(@NonNull View child) {
return (child.mViewFlags & VISIBILITY_MASK) == VISIBLE
|| child.getAnimation() != null;
}
@@ -2888,7 +2903,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
for (int i=0; i<childrenCount; i++) {
int childIndex;
try {
- childIndex = customOrder ? getChildDrawingOrder(childrenCount, i) : i;
+ childIndex = getAndVerifyPreorderedIndex(childrenCount, i, customOrder);
} catch (IndexOutOfBoundsException e) {
childIndex = i;
if (mContext.getApplicationInfo().targetSdkVersion
@@ -2933,9 +2948,10 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
throw e;
}
}
- final View child = (preorderedList == null)
- ? children[childIndex] : preorderedList.get(childIndex);
- ViewStructure cstructure = structure.newChild(i);
+
+ final View child = getAndVerifyPreorderedView(
+ preorderedList, children, childIndex);
+ final ViewStructure cstructure = structure.newChild(i);
child.dispatchProvideStructure(cstructure);
}
}
@@ -2943,6 +2959,21 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
}
}
+ private static View getAndVerifyPreorderedView(ArrayList<View> preorderedList, View[] children,
+ int childIndex) {
+ final View child;
+ if (preorderedList != null) {
+ child = preorderedList.get(childIndex);
+ if (child == null) {
+ throw new RuntimeException("Invalid preorderedList contained null child at index "
+ + childIndex);
+ }
+ } else {
+ child = children[childIndex];
+ }
+ return child;
+ }
+
/** @hide */
@Override
public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
@@ -3380,9 +3411,9 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
transientIndex = -1;
}
}
- int childIndex = customOrder ? getChildDrawingOrder(childrenCount, i) : i;
- final View child = (preorderedList == null)
- ? children[childIndex] : preorderedList.get(childIndex);
+
+ final int childIndex = getAndVerifyPreorderedIndex(childrenCount, i, customOrder);
+ final View child = getAndVerifyPreorderedView(preorderedList, children, childIndex);
if ((child.mViewFlags & VISIBILITY_MASK) == VISIBLE || child.getAnimation() != null) {
more |= drawChild(canvas, child, drawingTime);
}
@@ -3502,21 +3533,21 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
* children.
*/
ArrayList<View> buildOrderedChildList() {
- final int count = mChildrenCount;
- if (count <= 1 || !hasChildWithZ()) return null;
+ final int childrenCount = mChildrenCount;
+ if (childrenCount <= 1 || !hasChildWithZ()) return null;
if (mPreSortedChildren == null) {
- mPreSortedChildren = new ArrayList<View>(count);
+ mPreSortedChildren = new ArrayList<>(childrenCount);
} else {
- mPreSortedChildren.ensureCapacity(count);
+ mPreSortedChildren.ensureCapacity(childrenCount);
}
- final boolean useCustomOrder = isChildrenDrawingOrderEnabled();
- for (int i = 0; i < mChildrenCount; i++) {
+ final boolean customOrder = isChildrenDrawingOrderEnabled();
+ for (int i = 0; i < childrenCount; i++) {
// add next child (in child order) to end of list
- int childIndex = useCustomOrder ? getChildDrawingOrder(mChildrenCount, i) : i;
- View nextChild = mChildren[childIndex];
- float currentZ = nextChild.getZ();
+ final int childIndex = getAndVerifyPreorderedIndex(childrenCount, i, customOrder);
+ final View nextChild = mChildren[childIndex];
+ final float currentZ = nextChild.getZ();
// insert ahead of any Views with greater Z
int insertIndex = i;
@@ -7475,7 +7506,11 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
private TouchTarget() {
}
- public static TouchTarget obtain(View child, int pointerIdBits) {
+ public static TouchTarget obtain(@NonNull View child, int pointerIdBits) {
+ if (child == null) {
+ throw new IllegalArgumentException("child must be non-null");
+ }
+
final TouchTarget target;
synchronized (sRecycleLock) {
if (sRecycleBin == null) {
@@ -7493,6 +7528,10 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
}
public void recycle() {
+ if (child == null) {
+ throw new IllegalStateException("already recycled once");
+ }
+
synchronized (sRecycleLock) {
if (sRecycledCount < MAX_RECYCLED) {
next = sRecycleBin;
@@ -7522,7 +7561,11 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
private HoverTarget() {
}
- public static HoverTarget obtain(View child) {
+ public static HoverTarget obtain(@NonNull View child) {
+ if (child == null) {
+ throw new IllegalArgumentException("child must be non-null");
+ }
+
final HoverTarget target;
synchronized (sRecycleLock) {
if (sRecycleBin == null) {
@@ -7530,7 +7573,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
} else {
target = sRecycleBin;
sRecycleBin = target.next;
- sRecycledCount--;
+ sRecycledCount--;
target.next = null;
}
}
@@ -7539,6 +7582,10 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
}
public void recycle() {
+ if (child == null) {
+ throw new IllegalStateException("already recycled once");
+ }
+
synchronized (sRecycleLock) {
if (sRecycledCount < MAX_RECYCLED) {
next = sRecycleBin;