Permalink
Browse files

Fix crash when move on the edge of some phones like HUAWEI P9

Summary:
The app crashes because of `TouchEventCoalescingKeyHelper.getCoalescingKey` throwing an exception when move on the edge of some phones like HUAWEI P9. It's caused by that the down time differs from `ACTION_DOWN` to `ACTION_MOVE` which belongs to the same gesture when I touched on the edge of my HUAWEI P9. It seems a native bug of manufacturer. Related issue #11302.
```
java.lang.RuntimeException: Tried to get non-existent cookie
    at com.facebook.react.uimanager.events.TouchEventCoalescingKeyHelper.getCoalescingKey(TouchEventCoalescingKeyHelper.java:75)
    at com.facebook.react.uimanager.events.TouchEvent.init(TouchEvent.java:93)
    at com.facebook.react.uimanager.events.TouchEvent.obtain(TouchEvent.java:46)
    at com.facebook.react.uimanager.JSTouchDispatcher.handleTouchEvent(JSTouchDispatcher.java:118)
    at com.facebook.react.ReactRootView.dispatchJSTouchEvent(ReactRootView.java:158)
    at com.facebook.react.ReactRootView.onInterceptTouchEvent(ReactRootView.java:130)
    at android.view.Vie
Closes #12063

Differential Revision: D4779060

Pulled By: astreet

fbshipit-source-id: 5cf20084ff9081f2535ff9cb3b99d1d52c443f03
  • Loading branch information...
wenzhe.lv authored and facebook-github-bot committed Mar 27, 2017
1 parent 3b28644 commit d2939eafbf56f99ea4da7374b9812ae6f54c1d3d
@@ -30,6 +30,7 @@
private int mTargetTag = -1;
private final float[] mTargetCoordinates = new float[2];
private boolean mChildIsHandlingNativeGesture = false;
private long mGestureStartTime = TouchEvent.UNSET;
private final ViewGroup mRootViewGroup;
private final TouchEventCoalescingKeyHelper mTouchEventCoalescingKeyHelper =
new TouchEventCoalescingKeyHelper();
@@ -72,6 +73,7 @@ public void handleTouchEvent(MotionEvent ev, EventDispatcher eventDispatcher) {
// {@link #findTargetTagForTouch} to find react view ID that will be responsible for handling
// this gesture
mChildIsHandlingNativeGesture = false;
mGestureStartTime = ev.getEventTime();
mTargetTag = TouchTargetHelper.findTargetTagAndCoordinatesForTouch(
ev.getX(),
ev.getY(),
@@ -83,6 +85,7 @@ public void handleTouchEvent(MotionEvent ev, EventDispatcher eventDispatcher) {
mTargetTag,
TouchEventType.START,
ev,
mGestureStartTime,
mTargetCoordinates[0],
mTargetCoordinates[1],
mTouchEventCoalescingKeyHelper));
@@ -105,17 +108,20 @@ public void handleTouchEvent(MotionEvent ev, EventDispatcher eventDispatcher) {
mTargetTag,
TouchEventType.END,
ev,
mGestureStartTime,
mTargetCoordinates[0],
mTargetCoordinates[1],
mTouchEventCoalescingKeyHelper));
mTargetTag = -1;
mGestureStartTime = TouchEvent.UNSET;
} else if (action == MotionEvent.ACTION_MOVE) {
// Update pointer position for current gesture
eventDispatcher.dispatchEvent(
TouchEvent.obtain(
mTargetTag,
TouchEventType.MOVE,
ev,
mGestureStartTime,
mTargetCoordinates[0],
mTargetCoordinates[1],
mTouchEventCoalescingKeyHelper));
@@ -126,6 +132,7 @@ public void handleTouchEvent(MotionEvent ev, EventDispatcher eventDispatcher) {
mTargetTag,
TouchEventType.START,
ev,
mGestureStartTime,
mTargetCoordinates[0],
mTargetCoordinates[1],
mTouchEventCoalescingKeyHelper));
@@ -136,6 +143,7 @@ public void handleTouchEvent(MotionEvent ev, EventDispatcher eventDispatcher) {
mTargetTag,
TouchEventType.END,
ev,
mGestureStartTime,
mTargetCoordinates[0],
mTargetCoordinates[1],
mTouchEventCoalescingKeyHelper));
@@ -149,6 +157,7 @@ public void handleTouchEvent(MotionEvent ev, EventDispatcher eventDispatcher) {
);
}
mTargetTag = -1;
mGestureStartTime = TouchEvent.UNSET;
} else {
FLog.w(
ReactConstants.TAG,
@@ -176,6 +185,7 @@ private void dispatchCancelEvent(MotionEvent androidEvent, EventDispatcher event
mTargetTag,
TouchEventType.CANCEL,
androidEvent,
mGestureStartTime,
mTargetCoordinates[0],
mTargetCoordinates[1],
mTouchEventCoalescingKeyHelper));
@@ -15,6 +15,7 @@
import android.view.MotionEvent;
import com.facebook.infer.annotation.Assertions;
import com.facebook.react.bridge.SoftAssertions;
/**
* An event representing the start, end or movement of a touch. Corresponds to a single
@@ -31,10 +32,13 @@
private static final Pools.SynchronizedPool<TouchEvent> EVENTS_POOL =
new Pools.SynchronizedPool<>(TOUCH_EVENTS_POOL_SIZE);
public static final long UNSET = Long.MIN_VALUE;
public static TouchEvent obtain(
int viewTag,
TouchEventType touchEventType,
MotionEvent motionEventToCopy,
long gestureStartTime,
float viewX,
float viewY,
TouchEventCoalescingKeyHelper touchEventCoalescingKeyHelper) {
@@ -46,6 +50,7 @@ public static TouchEvent obtain(
viewTag,
touchEventType,
motionEventToCopy,
gestureStartTime,
viewX,
viewY,
touchEventCoalescingKeyHelper);
@@ -67,30 +72,33 @@ private void init(
int viewTag,
TouchEventType touchEventType,
MotionEvent motionEventToCopy,
long gestureStartTime,
float viewX,
float viewY,
TouchEventCoalescingKeyHelper touchEventCoalescingKeyHelper) {
super.init(viewTag);
SoftAssertions.assertCondition(gestureStartTime != UNSET,
"Gesture start time must be initialized");
short coalescingKey = 0;
int action = (motionEventToCopy.getAction() & MotionEvent.ACTION_MASK);
switch (action) {
case MotionEvent.ACTION_DOWN:
touchEventCoalescingKeyHelper.addCoalescingKey(motionEventToCopy.getDownTime());
touchEventCoalescingKeyHelper.addCoalescingKey(gestureStartTime);
break;
case MotionEvent.ACTION_UP:
touchEventCoalescingKeyHelper.removeCoalescingKey(motionEventToCopy.getDownTime());
touchEventCoalescingKeyHelper.removeCoalescingKey(gestureStartTime);
break;
case MotionEvent.ACTION_POINTER_DOWN:
case MotionEvent.ACTION_POINTER_UP:
touchEventCoalescingKeyHelper.incrementCoalescingKey(motionEventToCopy.getDownTime());
touchEventCoalescingKeyHelper.incrementCoalescingKey(gestureStartTime);
break;
case MotionEvent.ACTION_MOVE:
coalescingKey =
touchEventCoalescingKeyHelper.getCoalescingKey(motionEventToCopy.getDownTime());
touchEventCoalescingKeyHelper.getCoalescingKey(gestureStartTime);
break;
case MotionEvent.ACTION_CANCEL:
touchEventCoalescingKeyHelper.removeCoalescingKey(motionEventToCopy.getDownTime());
touchEventCoalescingKeyHelper.removeCoalescingKey(gestureStartTime);
break;
default:
throw new RuntimeException("Unhandled MotionEvent action: " + action);

0 comments on commit d2939ea

Please sign in to comment.