Skip to content

Commit

Permalink
W3CPointerEvents: fix NPE due to missing eventCoords (#37761)
Browse files Browse the repository at this point in the history
Summary:
Pull Request resolved: #37761

Changelog: [Android] [Fixed] - W3CPointerEvents: fix a case where cancel can cause NPE

When we need to dispatch a pointercancel event, we clear the previous state (last coordinates, last hit path) for the active pointer ID (this is needed in order to fire the proper events when the action causing the cancel is over).

Previously, we stored the previous state in the form of references to the corresponding state in the current `PointerEventState`. However, this PointerEventState is also used later when actually dispatching the events. Since the dispatch can happen asynchronously, alterations to the event state might be visible during the dispatch. In particular, we saw some cases where an NPE can occur due to removing entries from our local state (which got reflected in the event state).

This change fixes the issue by making copies of the data from the PointerEventState instead of just storing references to it.

Reviewed By: rozele

Differential Revision: D46522585

fbshipit-source-id: 78d6dd60cf8f5419870fb9f6703443c957d4d048
  • Loading branch information
Alex Danoff authored and facebook-github-bot committed Jun 8, 2023
1 parent 10d5588 commit 79ae710
Showing 1 changed file with 4 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -89,8 +89,10 @@ private MotionEvent convertMotionToRootFrame(View childView, MotionEvent childMo

private void updatePreviousStateFromEvent(MotionEvent event, PointerEventState eventState) {
// Caching the event state so we have a new "last"
mLastHitPathByPointerId = eventState.getHitPathByPointerId();
mLastEventCoordinatesByPointerId = eventState.getEventCoordinatesByPointerId();
// note: we need to make copies here as the eventState may be accessed later and we don't want
// mutations of these instance vars to affect it
mLastHitPathByPointerId = new HashMap<>(eventState.getHitPathByPointerId());
mLastEventCoordinatesByPointerId = new HashMap<>(eventState.getEventCoordinatesByPointerId());
mLastButtonState = event.getButtonState();

// Clean up any stale pointerIds
Expand Down

0 comments on commit 79ae710

Please sign in to comment.