Added LatencyTimer to ease latency measurements

	new file:   core/java/android/os/LatencyTimer.java
	modified:   core/java/android/view/MotionEvent.java
	modified:   core/java/android/view/ViewRoot.java
	modified:   services/java/com/android/server/InputDevice.java
	modified:   services/java/com/android/server/KeyInputQueue.java
	modified:   services/java/com/android/server/WindowManagerService.java
diff --git a/core/java/android/view/ViewRoot.java b/core/java/android/view/ViewRoot.java
index 7cd65e2..d999119 100644
--- a/core/java/android/view/ViewRoot.java
+++ b/core/java/android/view/ViewRoot.java
@@ -77,6 +77,9 @@
     private static final boolean DEBUG_IMF = false || LOCAL_LOGV;
     private static final boolean WATCH_POINTER = false;
 
+    private static final boolean MEASURE_LATENCY = false;
+    private static LatencyTimer lt;
+
     /**
      * Maximum time we allow the user to roll the trackball enough to generate
      * a key event, before resetting the counters.
@@ -192,6 +195,10 @@
     public ViewRoot(Context context) {
         super();
 
+        if (MEASURE_LATENCY && lt == null) {
+            lt = new LatencyTimer(100, 1000);
+        }
+
         ++sInstanceCount;
 
         // Initialize the statics when this class is first instantiated. This is
@@ -1579,7 +1586,17 @@
             boolean didFinish;
             if (event == null) {
                 try {
+                    long timeBeforeGettingEvents;
+                    if (MEASURE_LATENCY) {
+                        timeBeforeGettingEvents = System.nanoTime();
+                    }
+
                     event = sWindowSession.getPendingPointerMove(mWindow);
+
+                    if (MEASURE_LATENCY && event != null) {
+                        lt.sample("9 Client got events      ", System.nanoTime() - event.getEventTimeNano());
+                        lt.sample("8 Client getting events  ", timeBeforeGettingEvents - event.getEventTimeNano());
+                    }
                 } catch (RemoteException e) {
                 }
                 didFinish = true;
@@ -1603,7 +1620,13 @@
                         captureMotionLog("captureDispatchPointer", event);
                     }
                     event.offsetLocation(0, mCurScrollY);
+                    if (MEASURE_LATENCY) {
+                        lt.sample("A Dispatching TouchEvents", System.nanoTime() - event.getEventTimeNano());
+                    }
                     handled = mView.dispatchTouchEvent(event);
+                    if (MEASURE_LATENCY) {
+                        lt.sample("B Dispatched TouchEvents ", System.nanoTime() - event.getEventTimeNano());
+                    }
                     if (!handled && isDown) {
                         int edgeSlop = mViewConfiguration.getScaledEdgeSlop();
 
@@ -2685,7 +2708,11 @@
 
         public void dispatchPointer(MotionEvent event, long eventTime) {
             final ViewRoot viewRoot = mViewRoot.get();
-            if (viewRoot != null) {
+            if (viewRoot != null) {                
+                if (MEASURE_LATENCY) {
+                    // Note: eventTime is in milliseconds
+                    ViewRoot.lt.sample("* ViewRoot b4 dispatchPtr", System.nanoTime() - eventTime * 1000000);
+                }
                 viewRoot.dispatchPointer(event, eventTime);
             } else {
                 new EventCompletion(mMainLooper, this, null, true, event);