@Override
  public boolean onTouchEvent(@NonNull MotionEvent nativeMotionEvent) {
    if (mKeyboard == null) {
      // I mean, if there isn't any keyboard I'm handling, what's the point?
      return false;
    }

    final int action = nativeMotionEvent.getActionMasked();
    final int pointerCount = nativeMotionEvent.getPointerCount();
    if (pointerCount > 1) {
      mLastTimeHadTwoFingers =
          SystemClock.elapsedRealtime(); // marking the time. Read isAtTwoFingersState()
    }

    if (mTouchesAreDisabledTillLastFingerIsUp) {
      if (!areTouchesDisabled(nativeMotionEvent) /*this means it was just reset*/) {
        mTouchesAreDisabledTillLastFingerIsUp = false;
        // continue with onTouchEvent flow.
        if (action != MotionEvent.ACTION_DOWN) {
          // swallowing the event.
          // in case this is a DOWN event, we do want to pass it
          return true;
        }
      } else {
        // swallowing touch event until we reset mTouchesAreDisabledTillLastFingerIsUp
        return true;
      }
    }

    final long eventTime = nativeMotionEvent.getEventTime();
    final int index = nativeMotionEvent.getActionIndex();
    final int id = nativeMotionEvent.getPointerId(index);
    final int x = (int) nativeMotionEvent.getX(index);
    final int y = (int) nativeMotionEvent.getY(index);

    if (mKeyPressTimingHandler.isInKeyRepeat()) {
      // It will keep being in the key repeating mode while the key is
      // being pressed.
      if (action == MotionEvent.ACTION_MOVE) {
        return true;
      }
      final PointerTracker tracker = getPointerTracker(id);
      // Key repeating timer will be canceled if 2 or more keys are in
      // action, and current
      // event (UP or DOWN) is non-modifier key.
      if (pointerCount > 1 && !tracker.isModifier()) {
        mKeyPressTimingHandler.cancelKeyRepeatTimer();
      }
      // Up event will pass through.
    }

    if (action == MotionEvent.ACTION_MOVE) {
      for (int i = 0; i < pointerCount; i++) {
        PointerTracker tracker = getPointerTracker(nativeMotionEvent.getPointerId(i));
        tracker.onMoveEvent(
            (int) nativeMotionEvent.getX(i), (int) nativeMotionEvent.getY(i), eventTime);
      }
    } else {
      PointerTracker tracker = getPointerTracker(id);
      sendOnXEvent(action, eventTime, x, y, tracker);
    }

    return true;
  }
@Test
  public void testWithLongPressOutputLongPressKeyPressState() {
    final AnyKeyboard.AnyKey key = findKey('f');
    key.longPressCode = 'z';
    KeyDrawableStateProvider provider =
        new KeyDrawableStateProvider(
            R.attr.key_type_function,
            R.attr.key_type_action,
            R.attr.action_done,
            R.attr.action_search,
            R.attr.action_go);
    Assert.assertArrayEquals(provider.KEY_STATE_NORMAL, key.getCurrentDrawableState(provider));

    Point keyPoint = ViewTestUtils.getKeyCenterPoint(key);

    ViewTestUtils.navigateFromTo(mUnderTest, keyPoint, keyPoint, 80, true, false);
    Assert.assertArrayEquals(provider.KEY_STATE_PRESSED, key.getCurrentDrawableState(provider));
    ViewTestUtils.navigateFromTo(mUnderTest, keyPoint, keyPoint, 300, false, false);
    TestRxSchedulers.foregroundAdvanceBy(1);
    Assert.assertArrayEquals(provider.KEY_STATE_NORMAL, key.getCurrentDrawableState(provider));

    mUnderTest.onTouchEvent(
        MotionEvent.obtain(
            SystemClock.uptimeMillis(),
            SystemClock.uptimeMillis(),
            MotionEvent.ACTION_UP,
            keyPoint.x,
            keyPoint.y,
            0));

    Assert.assertArrayEquals(provider.KEY_STATE_NORMAL, key.getCurrentDrawableState(provider));
  }