Skip to content

Commit

Permalink
Fix crash when move on the edge of some phones like HUAWEI P9
Browse files Browse the repository at this point in the history
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 d2939ea
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ public class JSTouchDispatcher {
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();
Expand Down Expand Up @@ -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(),
Expand All @@ -83,6 +85,7 @@ public void handleTouchEvent(MotionEvent ev, EventDispatcher eventDispatcher) {
mTargetTag,
TouchEventType.START,
ev,
mGestureStartTime,
mTargetCoordinates[0],
mTargetCoordinates[1],
mTouchEventCoalescingKeyHelper));
Expand All @@ -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));
Expand All @@ -126,6 +132,7 @@ public void handleTouchEvent(MotionEvent ev, EventDispatcher eventDispatcher) {
mTargetTag,
TouchEventType.START,
ev,
mGestureStartTime,
mTargetCoordinates[0],
mTargetCoordinates[1],
mTouchEventCoalescingKeyHelper));
Expand All @@ -136,6 +143,7 @@ public void handleTouchEvent(MotionEvent ev, EventDispatcher eventDispatcher) {
mTargetTag,
TouchEventType.END,
ev,
mGestureStartTime,
mTargetCoordinates[0],
mTargetCoordinates[1],
mTouchEventCoalescingKeyHelper));
Expand All @@ -149,6 +157,7 @@ public void handleTouchEvent(MotionEvent ev, EventDispatcher eventDispatcher) {
);
}
mTargetTag = -1;
mGestureStartTime = TouchEvent.UNSET;
} else {
FLog.w(
ReactConstants.TAG,
Expand Down Expand Up @@ -176,6 +185,7 @@ private void dispatchCancelEvent(MotionEvent androidEvent, EventDispatcher event
mTargetTag,
TouchEventType.CANCEL,
androidEvent,
mGestureStartTime,
mTargetCoordinates[0],
mTargetCoordinates[1],
mTouchEventCoalescingKeyHelper));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -31,10 +32,13 @@ public class TouchEvent extends Event<TouchEvent> {
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) {
Expand All @@ -46,6 +50,7 @@ public static TouchEvent obtain(
viewTag,
touchEventType,
motionEventToCopy,
gestureStartTime,
viewX,
viewY,
touchEventCoalescingKeyHelper);
Expand All @@ -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);
Expand Down

0 comments on commit d2939ea

Please sign in to comment.