@Override
 public List<TouchEvent> getTouchEvents() {
   synchronized (this) {
     int len = touchEvents.size();
     for (int i = 0; i < len; i++) touchEventPool.free(touchEvents.get(i));
     touchEvents.clear();
     touchEvents.addAll(touchEventsBuffer);
     touchEventsBuffer.clear();
     return touchEvents;
   }
 }
  @Override
  public boolean onTouch(View v, MotionEvent event) {
    synchronized (this) {
      int action = event.getAction() & MotionEvent.ACTION_MASK;
      int pointerIndex =
          (event.getAction() & MotionEvent.ACTION_POINTER_ID_MASK)
              >> MotionEvent.ACTION_POINTER_ID_SHIFT;
      int pointerCount = event.getPointerCount();
      TouchEvent touchEvent;
      for (int i = 0; i < MAX_TOUCHPOINTS; i++) {
        if (i >= pointerCount) {
          isTouched[i] = false;
          id[i] = -1;
          continue;
        }
        int pointerId = event.getPointerId(i);
        if (event.getAction() != MotionEvent.ACTION_MOVE && i != pointerIndex) {
          // if it's an up/down/cancel/out event, mask the id to see if we should process it for
          // this touch
          // point
          continue;
        }
        switch (action) {
          case MotionEvent.ACTION_DOWN:
          case MotionEvent.ACTION_POINTER_DOWN:
            touchEvent = touchEventPool.newObject();
            touchEvent.type = TouchEvent.TOUCH_DOWN;
            touchEvent.pointer = pointerId;
            touchEvent.x = touchX[i] = (int) (event.getX(i) * scaleX);
            touchEvent.y = touchY[i] = (int) (event.getY(i) * scaleY);
            isTouched[i] = true;
            id[i] = pointerId;
            touchEventsBuffer.add(touchEvent);
            break;

          case MotionEvent.ACTION_UP:
          case MotionEvent.ACTION_POINTER_UP:
          case MotionEvent.ACTION_CANCEL:
            touchEvent = touchEventPool.newObject();
            touchEvent.type = TouchEvent.TOUCH_UP;
            touchEvent.pointer = pointerId;
            touchEvent.x = touchX[i] = (int) (event.getX(i) * scaleX);
            touchEvent.y = touchY[i] = (int) (event.getY(i) * scaleY);
            isTouched[i] = false;
            id[i] = -1;
            touchEventsBuffer.add(touchEvent);
            break;

          case MotionEvent.ACTION_MOVE:
            touchEvent = touchEventPool.newObject();
            touchEvent.type = TouchEvent.TOUCH_DRAGGED;
            touchEvent.pointer = pointerId;
            touchEvent.x = touchX[i] = (int) (event.getX(i) * scaleX);
            touchEvent.y = touchY[i] = (int) (event.getY(i) * scaleY);
            isTouched[i] = true;
            id[i] = pointerId;
            touchEventsBuffer.add(touchEvent);
            break;
        }
      }
      return true;
    }
  }