private void scheduleWebKitDispatchLocked() {
   if (!mWebKitDispatchScheduled) {
     mWebKitHandler.sendEmptyMessage(WebKitHandler.MSG_DISPATCH_WEBKIT_EVENTS);
     mWebKitDispatchScheduled = true;
   }
 }
  private void dispatchWebKitEvents(boolean calledFromHandler) {
    for (; ; ) {
      // Get the next event, but leave it in the queue so we can move it to the UI
      // queue if a timeout occurs.
      DispatchEvent d;
      MotionEvent event;
      final int eventType;
      int flags;
      synchronized (mLock) {
        if (!ENABLE_EVENT_BATCHING) {
          drainStaleWebKitEventsLocked();
        }
        d = mWebKitDispatchEventQueue.mHead;
        if (d == null) {
          if (mWebKitDispatchScheduled) {
            mWebKitDispatchScheduled = false;
            if (!calledFromHandler) {
              mWebKitHandler.removeMessages(WebKitHandler.MSG_DISPATCH_WEBKIT_EVENTS);
            }
          }
          return;
        }

        event = d.mEvent;
        if (event != null) {
          event.offsetLocation(d.mWebKitXOffset, d.mWebKitYOffset);
          event.scale(d.mWebKitScale);
          d.mFlags |= FLAG_WEBKIT_TRANSFORMED_EVENT;
        }

        eventType = d.mEventType;
        if (eventType == EVENT_TYPE_TOUCH) {
          event = mWebKitTouchStream.update(event);
          if (DEBUG && event == null && d.mEvent != null) {
            Log.d(TAG, "dispatchWebKitEvents: dropped event " + d.mEvent);
          }
        }

        d.mFlags |= FLAG_WEBKIT_IN_PROGRESS;
        flags = d.mFlags;
      }

      // Handle the event.
      final boolean preventDefault;
      if (event == null) {
        preventDefault = false;
      } else {
        preventDefault = dispatchWebKitEvent(event, eventType, flags);
      }

      synchronized (mLock) {
        /// M: update last event prevent status. @ {
        boolean lastPreventDefault = false;
        if (d.mEventType == EVENT_TYPE_TOUCH) {
          lastPreventDefault = mWebKitPreventTouchStream.update(event, preventDefault);
        }
        /// @ }
        flags = d.mFlags;
        d.mFlags = flags & ~FLAG_WEBKIT_IN_PROGRESS;
        boolean recycleEvent = event != d.mEvent;

        if ((flags & FLAG_WEBKIT_TIMEOUT) != 0) {
          // A timeout occurred!
          recycleDispatchEventLocked(d);
        } else {
          // Web kit finished in a timely manner.  Dequeue the event.
          assert mWebKitDispatchEventQueue.mHead == d;
          mWebKitDispatchEventQueue.dequeue();

          updateWebKitTimeoutLocked();

          if ((flags & FLAG_PRIVATE) != 0) {
            // Event was intended for web kit only.  All done.
            recycleDispatchEventLocked(d);
          } else if (preventDefault) {
            // Web kit has decided to consume the event!
            if (d.mEventType == EVENT_TYPE_TOUCH) {
              /// M: Consider two consistent events is preventDefault. @ {
              if (lastPreventDefault) {
                Log.d(TAG, "Webkit prevent current and last event, cancel ui event");
                enqueueUiCancelTouchEventIfNeededLocked();
              } else {
                Log.d(TAG, "Webkit prevent current but not last event, enqueue ui event");
                /// Only one event is preventDefault, Ui also handle this touch event.
                enqueueUiEventUnbatchedLocked(d);
              }
              unscheduleLongPressLocked();
              /// @ }
            }
          } else {
            // Web kit is being friendly.  Pass the event to the UI.
            enqueueUiEventUnbatchedLocked(d);
          }
        }

        if (event != null && recycleEvent) {
          event.recycle();
        }

        if (eventType == EVENT_TYPE_CLICK) {
          scheduleHideTapHighlightLocked();
        }
      }
    }
  }