Fix touch handling crash that can when Modal is displayed as a result of touch handling code

Reviewed By: dmmiller

Differential Revision: D3399325

fbshipit-source-id: 0a0bb179ef524bf35cc137d94ea3d5680a68aab2
This commit is contained in:
Olivier Notteghem 2016-06-07 11:53:28 -07:00 committed by Facebook Github Bot 9
parent f3fab5184e
commit 837aafde72
3 changed files with 44 additions and 27 deletions

View File

@ -32,6 +32,8 @@ public class JSTouchDispatcher {
private final float[] mTargetCoordinates = new float[2]; private final float[] mTargetCoordinates = new float[2];
private boolean mChildIsHandlingNativeGesture = false; private boolean mChildIsHandlingNativeGesture = false;
private final ViewGroup mRootViewGroup; private final ViewGroup mRootViewGroup;
private final TouchEventCoalescingKeyHelper mTouchEventCoalescingKeyHelper =
new TouchEventCoalescingKeyHelper();
public JSTouchDispatcher(ViewGroup viewGroup) { public JSTouchDispatcher(ViewGroup viewGroup) {
mRootViewGroup = viewGroup; mRootViewGroup = viewGroup;
@ -83,7 +85,8 @@ public class JSTouchDispatcher {
TouchEventType.START, TouchEventType.START,
ev, ev,
mTargetCoordinates[0], mTargetCoordinates[0],
mTargetCoordinates[1])); mTargetCoordinates[1],
mTouchEventCoalescingKeyHelper));
} else if (mChildIsHandlingNativeGesture) { } else if (mChildIsHandlingNativeGesture) {
// If the touch was intercepted by a child, we've already sent a cancel event to JS for this // If the touch was intercepted by a child, we've already sent a cancel event to JS for this
// gesture, so we shouldn't send any more touches related to it. // gesture, so we shouldn't send any more touches related to it.
@ -105,7 +108,8 @@ public class JSTouchDispatcher {
TouchEventType.END, TouchEventType.END,
ev, ev,
mTargetCoordinates[0], mTargetCoordinates[0],
mTargetCoordinates[1])); mTargetCoordinates[1],
mTouchEventCoalescingKeyHelper));
mTargetTag = -1; mTargetTag = -1;
} else if (action == MotionEvent.ACTION_MOVE) { } else if (action == MotionEvent.ACTION_MOVE) {
// Update pointer position for current gesture // Update pointer position for current gesture
@ -116,7 +120,8 @@ public class JSTouchDispatcher {
TouchEventType.MOVE, TouchEventType.MOVE,
ev, ev,
mTargetCoordinates[0], mTargetCoordinates[0],
mTargetCoordinates[1])); mTargetCoordinates[1],
mTouchEventCoalescingKeyHelper));
} else if (action == MotionEvent.ACTION_POINTER_DOWN) { } else if (action == MotionEvent.ACTION_POINTER_DOWN) {
// New pointer goes down, this can only happen after ACTION_DOWN is sent for the first pointer // New pointer goes down, this can only happen after ACTION_DOWN is sent for the first pointer
eventDispatcher.dispatchEvent( eventDispatcher.dispatchEvent(
@ -126,7 +131,8 @@ public class JSTouchDispatcher {
TouchEventType.START, TouchEventType.START,
ev, ev,
mTargetCoordinates[0], mTargetCoordinates[0],
mTargetCoordinates[1])); mTargetCoordinates[1],
mTouchEventCoalescingKeyHelper));
} else if (action == MotionEvent.ACTION_POINTER_UP) { } else if (action == MotionEvent.ACTION_POINTER_UP) {
// Exactly onw of the pointers goes up // Exactly onw of the pointers goes up
eventDispatcher.dispatchEvent( eventDispatcher.dispatchEvent(
@ -136,9 +142,10 @@ public class JSTouchDispatcher {
TouchEventType.END, TouchEventType.END,
ev, ev,
mTargetCoordinates[0], mTargetCoordinates[0],
mTargetCoordinates[1])); mTargetCoordinates[1],
mTouchEventCoalescingKeyHelper));
} else if (action == MotionEvent.ACTION_CANCEL) { } else if (action == MotionEvent.ACTION_CANCEL) {
if (TouchEventCoalescingKeyHelper.hasCoalescingKey(ev.getDownTime())) { if (mTouchEventCoalescingKeyHelper.hasCoalescingKey(ev.getDownTime())) {
dispatchCancelEvent(ev, eventDispatcher); dispatchCancelEvent(ev, eventDispatcher);
} else { } else {
FLog.e( FLog.e(
@ -176,6 +183,7 @@ public class JSTouchDispatcher {
TouchEventType.CANCEL, TouchEventType.CANCEL,
androidEvent, androidEvent,
mTargetCoordinates[0], mTargetCoordinates[0],
mTargetCoordinates[1])); mTargetCoordinates[1],
mTouchEventCoalescingKeyHelper));
} }
} }

View File

@ -37,12 +37,20 @@ public class TouchEvent extends Event<TouchEvent> {
TouchEventType touchEventType, TouchEventType touchEventType,
MotionEvent motionEventToCopy, MotionEvent motionEventToCopy,
float viewX, float viewX,
float viewY) { float viewY,
TouchEventCoalescingKeyHelper touchEventCoalescingKeyHelper) {
TouchEvent event = EVENTS_POOL.acquire(); TouchEvent event = EVENTS_POOL.acquire();
if (event == null) { if (event == null) {
event = new TouchEvent(); event = new TouchEvent();
} }
event.init(viewTag, timestampMs, touchEventType, motionEventToCopy, viewX, viewY); event.init(
viewTag,
timestampMs,
touchEventType,
motionEventToCopy,
viewX,
viewY,
touchEventCoalescingKeyHelper);
return event; return event;
} }
@ -63,28 +71,29 @@ public class TouchEvent extends Event<TouchEvent> {
TouchEventType touchEventType, TouchEventType touchEventType,
MotionEvent motionEventToCopy, MotionEvent motionEventToCopy,
float viewX, float viewX,
float viewY) { float viewY,
TouchEventCoalescingKeyHelper touchEventCoalescingKeyHelper) {
super.init(viewTag, timestampMs); super.init(viewTag, timestampMs);
short coalescingKey = 0; short coalescingKey = 0;
int action = (motionEventToCopy.getAction() & MotionEvent.ACTION_MASK); int action = (motionEventToCopy.getAction() & MotionEvent.ACTION_MASK);
switch (action) { switch (action) {
case MotionEvent.ACTION_DOWN: case MotionEvent.ACTION_DOWN:
TouchEventCoalescingKeyHelper.addCoalescingKey(motionEventToCopy.getDownTime()); touchEventCoalescingKeyHelper.addCoalescingKey(motionEventToCopy.getDownTime());
break; break;
case MotionEvent.ACTION_UP: case MotionEvent.ACTION_UP:
TouchEventCoalescingKeyHelper.removeCoalescingKey(motionEventToCopy.getDownTime()); touchEventCoalescingKeyHelper.removeCoalescingKey(motionEventToCopy.getDownTime());
break; break;
case MotionEvent.ACTION_POINTER_DOWN: case MotionEvent.ACTION_POINTER_DOWN:
case MotionEvent.ACTION_POINTER_UP: case MotionEvent.ACTION_POINTER_UP:
TouchEventCoalescingKeyHelper.incrementCoalescingKey(motionEventToCopy.getDownTime()); touchEventCoalescingKeyHelper.incrementCoalescingKey(motionEventToCopy.getDownTime());
break; break;
case MotionEvent.ACTION_MOVE: case MotionEvent.ACTION_MOVE:
coalescingKey = coalescingKey =
TouchEventCoalescingKeyHelper.getCoalescingKey(motionEventToCopy.getDownTime()); touchEventCoalescingKeyHelper.getCoalescingKey(motionEventToCopy.getDownTime());
break; break;
case MotionEvent.ACTION_CANCEL: case MotionEvent.ACTION_CANCEL:
TouchEventCoalescingKeyHelper.removeCoalescingKey(motionEventToCopy.getDownTime()); touchEventCoalescingKeyHelper.removeCoalescingKey(motionEventToCopy.getDownTime());
break; break;
default: default:
throw new RuntimeException("Unhandled MotionEvent action: " + action); throw new RuntimeException("Unhandled MotionEvent action: " + action);

View File

@ -46,31 +46,31 @@ import android.util.SparseIntArray;
*/ */
public class TouchEventCoalescingKeyHelper { public class TouchEventCoalescingKeyHelper {
private static final SparseIntArray sDownTimeToCoalescingKey = new SparseIntArray(); private final SparseIntArray mDownTimeToCoalescingKey = new SparseIntArray();
/** /**
* Starts tracking a new coalescing key corresponding to the gesture with this down time. * Starts tracking a new coalescing key corresponding to the gesture with this down time.
*/ */
public static void addCoalescingKey(long downTime) { public void addCoalescingKey(long downTime) {
sDownTimeToCoalescingKey.put((int) downTime, 0); mDownTimeToCoalescingKey.put((int) downTime, 0);
} }
/** /**
* Increments the coalescing key corresponding to the gesture with this down time. * Increments the coalescing key corresponding to the gesture with this down time.
*/ */
public static void incrementCoalescingKey(long downTime) { public void incrementCoalescingKey(long downTime) {
int currentValue = sDownTimeToCoalescingKey.get((int) downTime, -1); int currentValue = mDownTimeToCoalescingKey.get((int) downTime, -1);
if (currentValue == -1) { if (currentValue == -1) {
throw new RuntimeException("Tried to increment non-existent cookie"); throw new RuntimeException("Tried to increment non-existent cookie");
} }
sDownTimeToCoalescingKey.put((int) downTime, currentValue + 1); mDownTimeToCoalescingKey.put((int) downTime, currentValue + 1);
} }
/** /**
* Gets the coalescing key corresponding to the gesture with this down time. * Gets the coalescing key corresponding to the gesture with this down time.
*/ */
public static short getCoalescingKey(long downTime) { public short getCoalescingKey(long downTime) {
int currentValue = sDownTimeToCoalescingKey.get((int) downTime, -1); int currentValue = mDownTimeToCoalescingKey.get((int) downTime, -1);
if (currentValue == -1) { if (currentValue == -1) {
throw new RuntimeException("Tried to get non-existent cookie"); throw new RuntimeException("Tried to get non-existent cookie");
} }
@ -80,12 +80,12 @@ public class TouchEventCoalescingKeyHelper {
/** /**
* Stops tracking a new coalescing key corresponding to the gesture with this down time. * Stops tracking a new coalescing key corresponding to the gesture with this down time.
*/ */
public static void removeCoalescingKey(long downTime) { public void removeCoalescingKey(long downTime) {
sDownTimeToCoalescingKey.delete((int) downTime); mDownTimeToCoalescingKey.delete((int) downTime);
} }
public static boolean hasCoalescingKey(long downTime) { public boolean hasCoalescingKey(long downTime) {
int currentValue = sDownTimeToCoalescingKey.get((int) downTime, -1); int currentValue = mDownTimeToCoalescingKey.get((int) downTime, -1);
if (currentValue == -1) { if (currentValue == -1) {
return false; return false;
} }