@Override public boolean onTouchEvent(MotionEvent event) { // TODO(abarth): This version check might not be effective in some // versions of Android that statically compile code and will be upset // at the lack of |requestUnbufferedDispatch|. Instead, we should factor // version-dependent code into separate classes for each supported // version and dispatch dynamically. if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { requestUnbufferedDispatch(event); } ArrayList<Pointer> pointers = new ArrayList<Pointer>(); // TODO(abarth): Rather than unpacking these events here, we should // probably send them in one packet to the engine. int maskedAction = event.getActionMasked(); // ACTION_UP, ACTION_POINTER_UP, ACTION_DOWN, and ACTION_POINTER_DOWN // only apply to a single pointer, other events apply to all pointers. if (maskedAction == MotionEvent.ACTION_UP || maskedAction == MotionEvent.ACTION_POINTER_UP || maskedAction == MotionEvent.ACTION_DOWN || maskedAction == MotionEvent.ACTION_POINTER_DOWN) { addPointerForIndex(event, event.getActionIndex(), pointers); } else { // ACTION_MOVE may not actually mean all pointers have moved // but it's the responsibility of a later part of the system to // ignore 0-deltas if desired. for (int p = 0; p < event.getPointerCount(); p++) { addPointerForIndex(event, p, pointers); } } PointerPacket packet = new PointerPacket(); packet.pointers = pointers.toArray(new Pointer[0]); mSkyEngine.onPointerPacket(packet); return true; }