Add support for new input sources.

Added several new coordinate values to MotionEvents to capture
touch major/minor area, tool major/minor area and orientation.

Renamed NDK input constants per convention.

Added InputDevice class in Java which will eventually provide
useful information about available input devices.

Added APIs for manufacturing new MotionEvent objects with multiple
pointers and all necessary coordinate data.

Fixed a bug in the input dispatcher where it could get stuck with
a pointer down forever.

Fixed a bug in the WindowManager where the input window list could
end up containing stale removed windows.

Fixed a bug in the WindowManager where the input channel was being
removed only after the final animation transition had taken place
which caused spurious WINDOW DIED log messages to be printed.

Change-Id: Ie55084da319b20aad29b28a0499b8dd98bb5da68
diff --git a/services/java/com/android/server/WindowManagerService.java b/services/java/com/android/server/WindowManagerService.java
index c6e5cd2..37a2a58 100644
--- a/services/java/com/android/server/WindowManagerService.java
+++ b/services/java/com/android/server/WindowManagerService.java
@@ -102,6 +102,7 @@
 import android.view.IWindowManager;
 import android.view.IWindowSession;
 import android.view.InputChannel;
+import android.view.InputDevice;
 import android.view.InputQueue;
 import android.view.KeyEvent;
 import android.view.MotionEvent;
@@ -2017,6 +2018,8 @@
             + ", surface=" + win.mSurface);
 
         final long origId = Binder.clearCallingIdentity();
+        
+        win.disposeInputChannel();
 
         if (DEBUG_APP_TRANSITIONS) Slog.v(
                 TAG, "Remove " + win + ": mSurface=" + win.mSurface
@@ -2077,8 +2080,6 @@
     }
 
     private void removeWindowInnerLocked(Session session, WindowState win) {
-        mInputMonitor.windowIsBeingRemovedLw(win);
-
         win.mRemoved = true;
 
         if (mInputMethodTarget == win) {
@@ -2157,6 +2158,8 @@
                 win.mAppToken.updateReportedVisibilityLocked();
             }
         }
+        
+        mInputMonitor.updateInputWindowsLw();
     }
 
     private static void logSurface(WindowState w, String msg, RuntimeException where) {
@@ -2907,7 +2910,6 @@
                         if (win.isVisibleNow()) {
                             applyAnimationLocked(win,
                                     WindowManagerPolicy.TRANSIT_EXIT, false);
-                            mInputMonitor.windowIsBeingRemovedLw(win);
                             changed = true;
                         }
                     }
@@ -2925,6 +2927,7 @@
                     }
                 }
 
+                mInputMonitor.updateInputWindowsLw();
             } else {
                 Slog.w(TAG, "Attempted to remove non-existing token: " + token);
             }
@@ -5111,7 +5114,7 @@
             final int N = windows.size();
             for (int i = N - 1; i >= 0; i--) {
                 final WindowState child = (WindowState) windows.get(i);
-                if (child.mInputChannel == null) {
+                if (child.mInputChannel == null || child.mRemoved) {
                     // Skip this window because it cannot possibly receive input.
                     continue;
                 }
@@ -5288,11 +5291,6 @@
             }
         }
         
-        public void windowIsBeingRemovedLw(WindowState window) {
-            // Window is being removed.
-            updateInputWindowsLw();
-        }
-        
         public void pauseDispatchingLw(WindowToken window) {
             if (! window.paused) {
                 if (DEBUG_INPUT) {
@@ -5410,19 +5408,24 @@
         int metaState = ev.getMetaState();
         int deviceId = ev.getDeviceId();
         int scancode = ev.getScanCode();
+        int source = ev.getSource();
+        
+        if (source == InputDevice.SOURCE_UNKNOWN) {
+            source = InputDevice.SOURCE_KEYBOARD;
+        }
 
         if (eventTime == 0) eventTime = SystemClock.uptimeMillis();
         if (downTime == 0) downTime = eventTime;
 
         KeyEvent newEvent = new KeyEvent(downTime, eventTime, action, code, repeatCount, metaState,
-                deviceId, scancode, KeyEvent.FLAG_FROM_SYSTEM);
+                deviceId, scancode, KeyEvent.FLAG_FROM_SYSTEM, source);
 
         final int pid = Binder.getCallingPid();
         final int uid = Binder.getCallingUid();
         final long ident = Binder.clearCallingIdentity();
         
         final int result = mInputManager.injectKeyEvent(newEvent,
-                InputQueue.INPUT_EVENT_NATURE_KEY, pid, uid, sync, INJECTION_TIMEOUT_MILLIS);
+                pid, uid, sync, INJECTION_TIMEOUT_MILLIS);
         
         Binder.restoreCallingIdentity(ident);
         return reportInjectionResult(result);
@@ -5442,8 +5445,13 @@
         final int uid = Binder.getCallingUid();
         final long ident = Binder.clearCallingIdentity();
         
-        final int result = mInputManager.injectMotionEvent(ev,
-                InputQueue.INPUT_EVENT_NATURE_TOUCH, pid, uid, sync, INJECTION_TIMEOUT_MILLIS);
+        MotionEvent newEvent = MotionEvent.obtain(ev);
+        if ((newEvent.getSource() & InputDevice.SOURCE_CLASS_POINTER) == 0) {
+            newEvent.setSource(InputDevice.SOURCE_TOUCHSCREEN);
+        }
+        
+        final int result = mInputManager.injectMotionEvent(newEvent,
+                pid, uid, sync, INJECTION_TIMEOUT_MILLIS);
         
         Binder.restoreCallingIdentity(ident);
         return reportInjectionResult(result);
@@ -5463,8 +5471,13 @@
         final int uid = Binder.getCallingUid();
         final long ident = Binder.clearCallingIdentity();
         
-        final int result = mInputManager.injectMotionEvent(ev,
-                InputQueue.INPUT_EVENT_NATURE_TRACKBALL, pid, uid, sync, INJECTION_TIMEOUT_MILLIS);
+        MotionEvent newEvent = MotionEvent.obtain(ev);
+        if ((newEvent.getSource() & InputDevice.SOURCE_CLASS_TRACKBALL) == 0) {
+            newEvent.setSource(InputDevice.SOURCE_TRACKBALL);
+        }
+        
+        final int result = mInputManager.injectMotionEvent(newEvent,
+                pid, uid, sync, INJECTION_TIMEOUT_MILLIS);
         
         Binder.restoreCallingIdentity(ident);
         return reportInjectionResult(result);
@@ -6960,6 +6973,8 @@
         }
 
         void removeLocked() {
+            disposeInputChannel();
+            
             if (mAttachedWindow != null) {
                 mAttachedWindow.mChildWindows.remove(this);
             }
@@ -6971,7 +6986,9 @@
                 // Ignore if it has already been removed (usually because
                 // we are doing this as part of processing a death note.)
             }
-            
+        }
+        
+        void disposeInputChannel() {
             if (mInputChannel != null) {
                 mInputManager.unregisterInputChannel(mInputChannel);