docs: @SuppressWarnings("unused")
  	public boolean onTouchEvent(MotionEvent event) {
  		try {
  			int pointerCount = multiTouchSupported ? (Integer) m_getPointerCount.invoke(event) : 1;
  			if (DEBUG)
  				Log.i("MultiTouch", "Got here 1 - " + multiTouchSupported + " " + mMode + " " + handleSingleTouchEvents + " " + pointerCount);
  			if (mMode == MODE_NOTHING && !handleSingleTouchEvents && pointerCount == 1)
  				// Not handling initial single touch events, just pass them on
  				return false;
  			if (DEBUG)
  				Log.i("MultiTouch", "Got here 2");
  
  			// Handle history first (we sometimes get history with ACTION_MOVE events)
  			int action = event.getAction();
  			int histLen = event.getHistorySize() / pointerCount;
  			for (int histIdx = 0; histIdx <= histLen; histIdx++) {
  				// Read from history entries until histIdx == histLen, then read from current event
  				boolean processingHist = histIdx < histLen;
  				if (!multiTouchSupported || pointerCount == 1) {
  					// Use single-pointer methods -- these are needed as a special case (for some weird reason) even if
  					// multitouch is supported but there's only one touch point down currently -- event.getX(0) etc. throw
  					// an exception if there's only one point down.
  					if (DEBUG)
  						Log.i("MultiTouch", "Got here 3");
  					xVals[0] = processingHist ? event.getHistoricalX(histIdx) : event.getX();
  					yVals[0] = processingHist ? event.getHistoricalY(histIdx) : event.getY();
  					pressureVals[0] = processingHist ? event.getHistoricalPressure(histIdx) : event.getPressure();
  				} else {
  					// Read x, y and pressure of each pointer
  					if (DEBUG)
  						Log.i("MultiTouch", "Got here 4");
  					int numPointers = Math.min(pointerCount, MAX_TOUCH_POINTS);
  					if (DEBUG && pointerCount > MAX_TOUCH_POINTS)
  						Log.i("MultiTouch", "Got more pointers than MAX_TOUCH_POINTS");
  					for (int ptrIdx = 0; ptrIdx < numPointers; ptrIdx++) {
  						int ptrId = (Integer) m_getPointerId.invoke(event, ptrIdx);
  						pointerIds[ptrIdx] = ptrId;
  						// N.B. if pointerCount == 1, then the following methods throw an array index out of range exception,
  						// and the code above is therefore required not just for Android 1.5/1.6 but also for when there is
  						// only one touch point on the screen -- pointlessly inconsistent :(
  						xVals[ptrIdx] = (Float) (processingHist ? m_getHistoricalX.invoke(event, ptrIdx, histIdx) : m_getX.invoke(event, ptrIdx));
  						yVals[ptrIdx] = (Float) (processingHist ? m_getHistoricalY.invoke(event, ptrIdx, histIdx) : m_getY.invoke(event, ptrIdx));
  						pressureVals[ptrIdx] = (Float) (processingHist ? m_getHistoricalPressure.invoke(event, ptrIdx, histIdx) : m_getPressure
  								.invoke(event, ptrIdx));
  					}
  				}
  				// Decode event
  				decodeTouchEvent(pointerCount, xVals, yVals, pressureVals, pointerIds, //
  						/* action = */processingHist ? MotionEvent.ACTION_MOVE : action, //
  						/* down = */processingHist ? true : action != MotionEvent.ACTION_UP //
  								&& (action & ((1 << ACTION_POINTER_INDEX_SHIFT) - 1)) != ACTION_POINTER_UP //
  								&& action != MotionEvent.ACTION_CANCEL, //
  						processingHist ? event.getHistoricalEventTime(histIdx) : event.getEventTime());
  			}
  
  			return true;
  		} catch (Exception e) {
  			// In case any of the introspection stuff fails (it shouldn't)
  			Log.e("MultiTouchController", "onTouchEvent() failed", e);
  			return false;
  		}
  	}