Android's ViewPager caches the active pointer id from ACTION_DOWN and
later calls findPointerIndex(mActivePointerId) on MOVE events. When
the OS delivers a MOVE whose pointer set no longer contains that id
(a known multi-touch race), findPointerIndex returns -1 and getX(-1)
throws IllegalArgumentException from native code, crashing the app:
java.lang.IllegalArgumentException: invalid pointerIndex -1 for
MotionEvent { action=MOVE, ... }
at android.view.MotionEvent.nativeGetAxisValue(Native Method)
at android.view.MotionEvent.getX(MotionEvent.java:2655)
at androidx.viewpager.widget.ViewPager.onInterceptTouchEvent(ViewPager.java:2087)
SafeViewPager wraps onInterceptTouchEvent and onTouchEvent in a
try/catch and returns false on the exception, letting children handle
the event and letting the pager recover on the next clean DOWN.
Subsequent commits route the three ViewPager instances in the app
through this class.
A couple of places have implemented basically this exact workaround,
e.g., https://github.com/signalapp/Signal-Android/blob/main/app/src/main/java/org/thoughtcrime/securesms/components/viewpager/HackyViewPager.java