code: public boolean onTouchEvent(MotionEvent event) {
  
          switch (event.getActionMasked()) {
              case MotionEvent.ACTION_DOWN:
              case MotionEvent.ACTION_CANCEL:
              case MotionEvent.ACTION_UP:
  
                  cancelRotation();
                  break;
  
              case MotionEvent.ACTION_POINTER_DOWN:
  
                  if (event.getPointerCount() == 2) {
                      // Second finger is placed
                      initialAngle = prevAngle = currAngle = computeRotation(event);
                  }
                  break;
  
              case MotionEvent.ACTION_MOVE:
  
                  if (event.getPointerCount() >= 2 && (!isInProgress || isGestureAccepted)) {
                      // Moving 2 or more fingers on the screen
                      currAngle = computeRotation(event);
                      focusX = 0.5f * (event.getX(1) + event.getX(0));
                      focusY = 0.5f * (event.getY(1) + event.getY(0));
                      boolean isAlreadyStarted = isInProgress;
                      tryStartRotation();
                      boolean isAccepted = !isAlreadyStarted || processRotation();
                      if (isAccepted) {
                          prevAngle = currAngle;
                      }
                  }
                  break;
  
              case MotionEvent.ACTION_POINTER_UP:
  
                  if (event.getPointerCount() == 2) {
                      // Only one finger is left
                      cancelRotation();
                  }
                  break;
  
              default:
          }
  
          return true;
      }
docs: Accepts MotionEvents and dispatches events to a {@link OnRotationGestureListener}
  when appropriate.
  <p>
  Applications should pass a complete and consistent event stream to this method.
  A complete and consistent event stream involves all MotionEvents from the initial
  ACTION_DOWN to the final ACTION_UP or ACTION_CANCEL.
  
  @param event The event to process
  @return true if the event was processed and the detector wants to receive the
  rest of the MotionEvents in this event stream.