resolved conflicts for merge of aca672ba to master

Change-Id: I7ae11fca0acdbf513a4870226d0d3e3cafbe9a08
diff --git a/api/9.xml b/api/9.xml
index 6ab09e2..9e3b397 100644
--- a/api/9.xml
+++ b/api/9.xml
@@ -167608,6 +167608,38 @@
 </parameter>
 </constructor>
 </class>
+<class name="InputEvent"
+ extends="java.lang.Object"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="android.os.Parcelable">
+</implements>
+<method name="getDeviceId"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<field name="mDeviceId"
+ type="int"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+</field>
+</class>
 <class name="KeyCharacterMap"
  extends="java.lang.Object"
  abstract="false"
@@ -167944,7 +167976,7 @@
 </field>
 </class>
 <class name="KeyEvent"
- extends="java.lang.Object"
+ extends="android.view.InputEvent"
  abstract="false"
  static="false"
  final="false"
@@ -168237,17 +168269,6 @@
 <parameter name="c" type="int">
 </parameter>
 </method>
-<method name="getDeviceId"
- return="int"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
 <method name="getDisplayLabel"
  return="char"
  abstract="false"
@@ -171122,7 +171143,7 @@
 </method>
 </interface>
 <class name="MotionEvent"
- extends="java.lang.Object"
+ extends="android.view.InputEvent"
  abstract="false"
  static="false"
  final="true"
@@ -171211,17 +171232,6 @@
  visibility="public"
 >
 </method>
-<method name="getDeviceId"
- return="int"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
 <method name="getDownTime"
  return="long"
  abstract="false"
diff --git a/api/current.xml b/api/current.xml
index 355b3cd..090d6ba 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -177157,6 +177157,285 @@
 </parameter>
 </constructor>
 </class>
+<class name="InputDevice"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="InputDevice"
+ type="android.view.InputDevice"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<method name="getKeyCharacterMap"
+ return="android.view.KeyCharacterMap"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getName"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getSources"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<field name="SOURCE_CLASS_BUTTON"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="SOURCE_CLASS_JOYSTICK"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="SOURCE_CLASS_MASK"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="255"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="SOURCE_CLASS_POINTER"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="SOURCE_CLASS_POSITION"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="8"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="SOURCE_CLASS_TRACKBALL"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="4"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="SOURCE_DPAD"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="513"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="SOURCE_GAMEPAD"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1025"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="SOURCE_JOYSTICK_LEFT"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16777232"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="SOURCE_JOYSTICK_RIGHT"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="33554448"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="SOURCE_KEYBOARD"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="257"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="SOURCE_MOUSE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="8194"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="SOURCE_TOUCHPAD"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1048584"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="SOURCE_TOUCHSCREEN"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="4098"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="SOURCE_TRACKBALL"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="65540"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="SOURCE_UNKNOWN"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="0"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+<class name="InputEvent"
+ extends="java.lang.Object"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="android.os.Parcelable">
+</implements>
+<method name="getDeviceId"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getSource"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<field name="mDeviceId"
+ type="int"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+</field>
+<field name="mSource"
+ type="int"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+</field>
+</class>
 <class name="InputQueue"
  extends="java.lang.Object"
  abstract="false"
@@ -177536,7 +177815,7 @@
 </field>
 </class>
 <class name="KeyEvent"
- extends="java.lang.Object"
+ extends="android.view.InputEvent"
  abstract="false"
  static="false"
  final="false"
@@ -177614,7 +177893,7 @@
 </parameter>
 <parameter name="metaState" type="int">
 </parameter>
-<parameter name="device" type="int">
+<parameter name="deviceId" type="int">
 </parameter>
 <parameter name="scancode" type="int">
 </parameter>
@@ -177638,7 +177917,7 @@
 </parameter>
 <parameter name="metaState" type="int">
 </parameter>
-<parameter name="device" type="int">
+<parameter name="deviceId" type="int">
 </parameter>
 <parameter name="scancode" type="int">
 </parameter>
@@ -177652,11 +177931,39 @@
  deprecated="not deprecated"
  visibility="public"
 >
+<parameter name="downTime" type="long">
+</parameter>
+<parameter name="eventTime" type="long">
+</parameter>
+<parameter name="action" type="int">
+</parameter>
+<parameter name="code" type="int">
+</parameter>
+<parameter name="repeat" type="int">
+</parameter>
+<parameter name="metaState" type="int">
+</parameter>
+<parameter name="deviceId" type="int">
+</parameter>
+<parameter name="scancode" type="int">
+</parameter>
+<parameter name="flags" type="int">
+</parameter>
+<parameter name="source" type="int">
+</parameter>
+</constructor>
+<constructor name="KeyEvent"
+ type="android.view.KeyEvent"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
 <parameter name="time" type="long">
 </parameter>
 <parameter name="characters" type="java.lang.String">
 </parameter>
-<parameter name="device" type="int">
+<parameter name="deviceId" type="int">
 </parameter>
 <parameter name="flags" type="int">
 </parameter>
@@ -177829,17 +178136,6 @@
 <parameter name="c" type="int">
 </parameter>
 </method>
-<method name="getDeviceId"
- return="int"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
 <method name="getDisplayLabel"
  return="char"
  abstract="false"
@@ -180969,7 +181265,7 @@
 </method>
 </interface>
 <class name="MotionEvent"
- extends="java.lang.Object"
+ extends="android.view.InputEvent"
  abstract="false"
  static="false"
  final="true"
@@ -181001,6 +181297,23 @@
 <parameter name="metaState" type="int">
 </parameter>
 </method>
+<method name="addBatch"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="eventTime" type="long">
+</parameter>
+<parameter name="pointerCoords" type="android.view.MotionEvent.PointerCoords[]">
+</parameter>
+<parameter name="metaState" type="int">
+</parameter>
+</method>
 <method name="describeContents"
  return="int"
  abstract="false"
@@ -181058,17 +181371,6 @@
  visibility="public"
 >
 </method>
-<method name="getDeviceId"
- return="int"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
 <method name="getDownTime"
  return="long"
  abstract="false"
@@ -181115,6 +181417,51 @@
 <parameter name="pos" type="int">
 </parameter>
 </method>
+<method name="getHistoricalOrientation"
+ return="float"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="pos" type="int">
+</parameter>
+</method>
+<method name="getHistoricalOrientation"
+ return="float"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="pointerIndex" type="int">
+</parameter>
+<parameter name="pos" type="int">
+</parameter>
+</method>
+<method name="getHistoricalPointerCoords"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="pointerIndex" type="int">
+</parameter>
+<parameter name="pos" type="int">
+</parameter>
+<parameter name="outPointerCoords" type="android.view.MotionEvent.PointerCoords">
+</parameter>
+</method>
 <method name="getHistoricalPressure"
  return="float"
  abstract="false"
@@ -181171,6 +181518,118 @@
 <parameter name="pos" type="int">
 </parameter>
 </method>
+<method name="getHistoricalToolMajor"
+ return="float"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="pos" type="int">
+</parameter>
+</method>
+<method name="getHistoricalToolMajor"
+ return="float"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="pointerIndex" type="int">
+</parameter>
+<parameter name="pos" type="int">
+</parameter>
+</method>
+<method name="getHistoricalToolMinor"
+ return="float"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="pos" type="int">
+</parameter>
+</method>
+<method name="getHistoricalToolMinor"
+ return="float"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="pointerIndex" type="int">
+</parameter>
+<parameter name="pos" type="int">
+</parameter>
+</method>
+<method name="getHistoricalTouchMajor"
+ return="float"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="pos" type="int">
+</parameter>
+</method>
+<method name="getHistoricalTouchMajor"
+ return="float"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="pointerIndex" type="int">
+</parameter>
+<parameter name="pos" type="int">
+</parameter>
+</method>
+<method name="getHistoricalTouchMinor"
+ return="float"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="pos" type="int">
+</parameter>
+</method>
+<method name="getHistoricalTouchMinor"
+ return="float"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="pointerIndex" type="int">
+</parameter>
+<parameter name="pos" type="int">
+</parameter>
+</method>
 <method name="getHistoricalX"
  return="float"
  abstract="false"
@@ -181249,6 +181708,45 @@
  visibility="public"
 >
 </method>
+<method name="getOrientation"
+ return="float"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getOrientation"
+ return="float"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="pointerIndex" type="int">
+</parameter>
+</method>
+<method name="getPointerCoords"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="pointerIndex" type="int">
+</parameter>
+<parameter name="outPointerCoords" type="android.view.MotionEvent.PointerCoords">
+</parameter>
+</method>
 <method name="getPointerCount"
  return="int"
  abstract="false"
@@ -181343,6 +181841,102 @@
 <parameter name="pointerIndex" type="int">
 </parameter>
 </method>
+<method name="getToolMajor"
+ return="float"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getToolMajor"
+ return="float"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="pointerIndex" type="int">
+</parameter>
+</method>
+<method name="getToolMinor"
+ return="float"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getToolMinor"
+ return="float"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="pointerIndex" type="int">
+</parameter>
+</method>
+<method name="getTouchMajor"
+ return="float"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getTouchMajor"
+ return="float"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="pointerIndex" type="int">
+</parameter>
+</method>
+<method name="getTouchMinor"
+ return="float"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getTouchMinor"
+ return="float"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="pointerIndex" type="int">
+</parameter>
+</method>
 <method name="getX"
  return="float"
  abstract="false"
@@ -181429,6 +182023,41 @@
 </parameter>
 <parameter name="action" type="int">
 </parameter>
+<parameter name="pointers" type="int">
+</parameter>
+<parameter name="pointerIds" type="int[]">
+</parameter>
+<parameter name="pointerCoords" type="android.view.MotionEvent.PointerCoords[]">
+</parameter>
+<parameter name="metaState" type="int">
+</parameter>
+<parameter name="xPrecision" type="float">
+</parameter>
+<parameter name="yPrecision" type="float">
+</parameter>
+<parameter name="deviceId" type="int">
+</parameter>
+<parameter name="edgeFlags" type="int">
+</parameter>
+<parameter name="source" type="int">
+</parameter>
+</method>
+<method name="obtain"
+ return="android.view.MotionEvent"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="downTime" type="long">
+</parameter>
+<parameter name="eventTime" type="long">
+</parameter>
+<parameter name="action" type="int">
+</parameter>
 <parameter name="x" type="float">
 </parameter>
 <parameter name="y" type="float">
@@ -181869,6 +182498,113 @@
 >
 </field>
 </class>
+<class name="MotionEvent.PointerCoords"
+ extends="java.lang.Object"
+ abstract="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="MotionEvent.PointerCoords"
+ type="android.view.MotionEvent.PointerCoords"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<field name="orientation"
+ type="float"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="pressure"
+ type="float"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="size"
+ type="float"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="toolMajor"
+ type="float"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="toolMinor"
+ type="float"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="touchMajor"
+ type="float"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="touchMinor"
+ type="float"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="x"
+ type="float"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="y"
+ type="float"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
 <class name="OrientationEventListener"
  extends="java.lang.Object"
  abstract="true"
diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java
index e26a090..57a72bf 100644
--- a/core/java/android/service/wallpaper/WallpaperService.java
+++ b/core/java/android/service/wallpaper/WallpaperService.java
@@ -41,6 +41,7 @@
 import android.view.Gravity;
 import android.view.IWindowSession;
 import android.view.InputChannel;
+import android.view.InputDevice;
 import android.view.InputHandler;
 import android.view.InputQueue;
 import android.view.KeyEvent;
@@ -214,9 +215,12 @@
         
         final InputHandler mInputHandler = new BaseInputHandler() {
             @Override
-            public void handleTouch(MotionEvent event, Runnable finishedCallback) {
+            public void handleMotion(MotionEvent event, Runnable finishedCallback) {
                 try {
-                    dispatchPointer(event);
+                    int source = event.getSource();
+                    if ((source & InputDevice.SOURCE_CLASS_POINTER) != 0) {
+                        dispatchPointer(event);
+                    }
                 } finally {
                     finishedCallback.run();
                 }
diff --git a/core/java/android/view/InputChannel.java b/core/java/android/view/InputChannel.java
index e24c3c9..f2cad2f 100644
--- a/core/java/android/view/InputChannel.java
+++ b/core/java/android/view/InputChannel.java
@@ -30,6 +30,8 @@
 public final class InputChannel implements Parcelable {
     private static final String TAG = "InputChannel";
     
+    private static final boolean DEBUG = false;
+    
     public static final Parcelable.Creator<InputChannel> CREATOR
             = new Parcelable.Creator<InputChannel>() {
         public InputChannel createFromParcel(Parcel source) {
@@ -84,8 +86,10 @@
         if (name == null) {
             throw new IllegalArgumentException("name must not be null");
         }
-        
-        Slog.d(TAG, "Opening input channel pair '" + name + "'");
+
+        if (DEBUG) {
+            Slog.d(TAG, "Opening input channel pair '" + name + "'");
+        }
         return nativeOpenInputChannelPair(name);
     }
     
diff --git a/core/java/android/view/InputDevice.java b/core/java/android/view/InputDevice.java
new file mode 100755
index 0000000..568caa2
--- /dev/null
+++ b/core/java/android/view/InputDevice.java
@@ -0,0 +1,231 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view;
+
+/**
+ * Describes the capabilities of a particular input device.
+ * <p>
+ * Each input device may support multiple classes of input.  For example, a multifunction
+ * keyboard may compose the capabilities of a standard keyboard together with a track pad mouse
+ * or other pointing device.
+ * </p><p>
+ * Some input devices present multiple distinguishable sources of input.  For example, a
+ * game pad may have two analog joysticks, a directional pad and a full complement of buttons.
+ * Applications can query the framework about the characteristics of each distinct source.
+ * </p><p>
+ * As a further wrinkle, different kinds of input sources uses different coordinate systems
+ * to describe motion events.  Refer to the comments on the input source constants for
+ * the appropriate interpretation.
+ */
+public final class InputDevice {
+    private int mId;
+    private String mName;
+    private int mSources;
+    
+    /**
+     * A mask for input source classes.
+     * 
+     * Each distinct input source constant has one or more input source class bits set to
+     * specify the desired interpretation for its input events.
+     */
+    public static final int SOURCE_CLASS_MASK = 0x000000ff;
+    
+    /**
+     * The input source has buttons or keys.
+     * Examples: {@link #SOURCE_KEYBOARD}, {@link #SOURCE_GAMEPAD}, {@link #SOURCE_DPAD}.
+     * 
+     * A {@link KeyEvent} should be interpreted as a button or key press.
+     * 
+     * Use {@link #hasKeyCode} to query whether the device supports a particular button or key.
+     */
+    public static final int SOURCE_CLASS_BUTTON = 0x00000001;
+    
+    /**
+     * The input source is a pointing device associated with a display.
+     * Examples: {@link #SOURCE_TOUCHSCREEN}, {@link #SOURCE_MOUSE}.
+     * 
+     * A {@link MotionEvent} should be interpreted as absolute coordinates in
+     * display units according to the {@link View} hierarchy.  Pointer down/up indicated when
+     * the finger touches the display or when the selection button is pressed/released.
+     * 
+     * Use {@link #getMotionRange} to query the range of the pointing device.  Some devices permit
+     * touches outside the display area so the effective range may be somewhat smaller or larger
+     * than the actual display size.
+     */
+    public static final int SOURCE_CLASS_POINTER = 0x00000002;
+    
+    /**
+     * The input source is a trackball navigation device.
+     * Examples: {@link #SOURCE_TRACKBALL}.
+     * 
+     * A {@link MotionEvent} should be interpreted as relative movements in device-specific
+     * units used for navigation purposes.  Pointer down/up indicates when the selection button
+     * is pressed/released.
+     * 
+     * Use {@link #getMotionRange} to query the range of motion.
+     */
+    public static final int SOURCE_CLASS_TRACKBALL = 0x00000004;
+    
+    /**
+     * The input source is an absolute positioning device not associated with a display
+     * (unlike {@link #SOURCE_CLASS_POINTER}).
+     * 
+     * A {@link MotionEvent} should be interpreted as absolute coordinates in
+     * device-specific surface units.
+     * 
+     * Use {@link #getMotionRange} to query the range of positions.
+     */
+    public static final int SOURCE_CLASS_POSITION = 0x00000008;
+    
+    /**
+     * The input source is a joystick.
+     * 
+     * A {@link KeyEvent} should be interpreted as a joystick button press.
+     * 
+     * A {@link MotionEvent} should be interpreted in absolute coordinates as a joystick
+     * position in normalized device-specific units nominally between -1.0 and 1.0.
+     * 
+     * Use {@link #getMotionRange} to query the range and precision of motion.
+     */
+    public static final int SOURCE_CLASS_JOYSTICK = 0x00000010;
+    
+    /**
+     * The input source is unknown.
+     */
+    public static final int SOURCE_UNKNOWN = 0x00000000;
+    
+    /**
+     * The input source is a keyboard.
+     * 
+     * @see #SOURCE_CLASS_BUTTON
+     */
+    public static final int SOURCE_KEYBOARD = 0x00000100 | SOURCE_CLASS_BUTTON;
+    
+    /**
+     * The input source is a DPad.
+     * 
+     * @see #SOURCE_CLASS_BUTTON
+     */
+    public static final int SOURCE_DPAD = 0x00000200 | SOURCE_CLASS_BUTTON;
+    
+    /**
+     * The input source is a gamepad.
+     * 
+     * @see #SOURCE_CLASS_BUTTON
+     */
+    public static final int SOURCE_GAMEPAD = 0x00000400 | SOURCE_CLASS_BUTTON;
+    
+    /**
+     * The input source is a touch screen pointing device.
+     * 
+     * @see #SOURCE_CLASS_POINTER
+     */
+    public static final int SOURCE_TOUCHSCREEN = 0x00001000 | SOURCE_CLASS_POINTER;
+    
+    /**
+     * The input source is a mouse pointing device.
+     * This code is also used for other mouse-like pointing devices such as trackpads
+     * and trackpoints.
+     * 
+     * @see #SOURCE_CLASS_POINTER
+     */
+    public static final int SOURCE_MOUSE = 0x00002000 | SOURCE_CLASS_POINTER;
+    
+    /**
+     * The input source is a trackball.
+     * 
+     * @see #SOURCE_CLASS_TRACKBALL
+     */
+    public static final int SOURCE_TRACKBALL = 0x00010000 | SOURCE_CLASS_TRACKBALL;
+    
+    /**
+     * The input source is a touch pad or digitizer tablet that is not
+     * associated with a display (unlike {@link SOURCE_TOUCHSCREEN}).
+     * 
+     * @see #SOURCE_CLASS_POSITION
+     */
+    public static final int SOURCE_TOUCHPAD = 0x00100000 | SOURCE_CLASS_POSITION;
+
+    /**
+     * The input source is a joystick mounted on the left or is a standalone joystick.
+     * 
+     * @see #SOURCE_CLASS_JOYSTICK
+     */
+    public static final int SOURCE_JOYSTICK_LEFT = 0x01000000 | SOURCE_CLASS_JOYSTICK;
+    
+    /**
+     * The input source is a joystick mounted on the right.
+     * 
+     * @see #SOURCE_CLASS_JOYSTICK
+     */
+    public static final int SOURCE_JOYSTICK_RIGHT = 0x02000000 | SOURCE_CLASS_JOYSTICK;
+
+    /*
+    public static final int MOTION_RANGE_X = 0;
+    public static final int MOTION_RANGE_Y = 1;
+    public static final int MOTION_RANGE_PRESSURE = 2;
+    public static final int MOTION_RANGE_SIZE = 3;
+    public static final int MOTION_RANGE_TOUCH_MAJOR = 4;
+    public static final int MOTION_RANGE_TOUCH_MINOR = 5;
+    public static final int MOTION_RANGE_TOOL_MAJOR = 6;
+    public static final int MOTION_RANGE_TOOL_MINOR = 7;
+    public static final int MOTION_RANGE_ORIENTATION = 8;
+    
+    public static InputDevice getDevice(int id) {
+    }
+    */
+    
+    /**
+     * Gets the name of this input device.
+     * @return The input device name.
+     */
+    public String getName() {
+        return mName;
+    }
+    
+    /**
+     * Gets the input sources supported by this input device as a combined bitfield.
+     * @return The supported input sources.
+     */
+    public int getSources() {
+        return mSources;
+    }
+    
+    /**
+     * Gets the key character map associated with this input device.
+     * @return The key character map.
+     */
+    public KeyCharacterMap getKeyCharacterMap() {
+        return KeyCharacterMap.load(mId);
+    }
+    
+    /*
+    
+    public MotionRange getMotionRange(int range) {
+    }
+    
+    public boolean hasKeyCode(int keyCode) {
+    }
+    
+    public static final class MotionRange {
+        public float min;
+        public float max;
+        public float range;
+        public float flat;
+        public float fuzz;
+    }*/
+}
diff --git a/core/java/android/view/InputEvent.java b/core/java/android/view/InputEvent.java
new file mode 100755
index 0000000..445a980
--- /dev/null
+++ b/core/java/android/view/InputEvent.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view;
+
+import android.os.Parcelable;
+
+/**
+ * Common base class for input events.
+ */
+public abstract class InputEvent implements Parcelable {
+    protected int mDeviceId;
+    protected int mSource;
+    
+    /*package*/ InputEvent() {
+    }
+
+    /**
+     * Gets the id for the device that this event came from.  An id of
+     * zero indicates that the event didn't come from a physical device
+     * and maps to the default keymap.  The other numbers are arbitrary and
+     * you shouldn't depend on the values.
+     * 
+     * @return The device id.
+     * @see InputDevice#getDevice
+     */
+    public final int getDeviceId() {
+        return mDeviceId;
+    }
+    
+    /**
+     * Gets the source of the event.
+     * 
+     * @return The event source or {@link InputDevice.SOURCE_UNKNOWN} if unknown.
+     * @see InputDevice#getSourceInfo
+     */
+    public final int getSource() {
+        return mSource;
+    }
+    
+    /**
+     * Modifies the source of the event.
+     * @param source The source.
+     * 
+     * @hide
+     */
+    public final void setSource(int source) {
+        mSource = source;
+    }
+}
diff --git a/core/java/android/view/InputHandler.java b/core/java/android/view/InputHandler.java
index 816f622..41a152d 100644
--- a/core/java/android/view/InputHandler.java
+++ b/core/java/android/view/InputHandler.java
@@ -32,22 +32,12 @@
     public void handleKey(KeyEvent event, Runnable finishedCallback);
     
     /**
-     * Handle a touch event.
+     * Handle a motion event.
      * It is the responsibility of the callee to ensure that the finished callback is
      * eventually invoked when the event processing is finished and the input system
      * can send the next event.
      * @param event The motion event data.
      * @param finishedCallback The callback to invoke when event processing is finished.
      */
-    public void handleTouch(MotionEvent event, Runnable finishedCallback);
-    
-    /**
-     * Handle a trackball event.
-     * It is the responsibility of the callee to ensure that the finished callback is
-     * eventually invoked when the event processing is finished and the input system
-     * can send the next event.
-     * @param event The motion event data.
-     * @param finishedCallback The callback to invoke when event processing is finished.
-     */
-    public void handleTrackball(MotionEvent event, Runnable finishedCallback);
+    public void handleMotion(MotionEvent event, Runnable finishedCallback);
 }
diff --git a/core/java/android/view/InputQueue.java b/core/java/android/view/InputQueue.java
index 7feee38..997246f 100644
--- a/core/java/android/view/InputQueue.java
+++ b/core/java/android/view/InputQueue.java
@@ -26,6 +26,8 @@
 public final class InputQueue {
     private static final String TAG = "InputQueue";
     
+    private static final boolean DEBUG = false;
+    
     public static interface Callback {
         void onInputQueueCreated(InputQueue queue);
         void onInputQueueDestroyed(InputQueue queue);
@@ -33,15 +35,6 @@
 
     final InputChannel mChannel;
     
-    // Describes the interpretation of an event.
-    // XXX This concept is tentative.  See comments in android/input.h.
-    /** @hide */
-    public static final int INPUT_EVENT_NATURE_KEY = 1;
-    /** @hide */
-    public static final int INPUT_EVENT_NATURE_TOUCH = 2;
-    /** @hide */
-    public static final int INPUT_EVENT_NATURE_TRACKBALL = 3;
-    
     private static Object sLock = new Object();
     
     private static native void nativeRegisterInputChannel(InputChannel inputChannel,
@@ -79,7 +72,10 @@
         }
         
         synchronized (sLock) {
-            Slog.d(TAG, "Registering input channel '" + inputChannel + "'");
+            if (DEBUG) {
+                Slog.d(TAG, "Registering input channel '" + inputChannel + "'");
+            }
+            
             nativeRegisterInputChannel(inputChannel, inputHandler, messageQueue);
         }
     }
@@ -96,35 +92,26 @@
         }
 
         synchronized (sLock) {
-            Slog.d(TAG, "Unregistering input channel '" + inputChannel + "'");
+            if (DEBUG) {
+                Slog.d(TAG, "Unregistering input channel '" + inputChannel + "'");
+            }
+            
             nativeUnregisterInputChannel(inputChannel);
         }
     }
     
     @SuppressWarnings("unused")
     private static void dispatchKeyEvent(InputHandler inputHandler,
-            KeyEvent event, int nature, long finishedToken) {
+            KeyEvent event, long finishedToken) {
         Runnable finishedCallback = new FinishedCallback(finishedToken);
-        
-        if (nature == INPUT_EVENT_NATURE_KEY) {
-            inputHandler.handleKey(event, finishedCallback);
-        } else {
-            Slog.d(TAG, "Unsupported nature for key event: " + nature);
-        }
+        inputHandler.handleKey(event, finishedCallback);
     }
 
     @SuppressWarnings("unused")
     private static void dispatchMotionEvent(InputHandler inputHandler,
-            MotionEvent event, int nature, long finishedToken) {
+            MotionEvent event, long finishedToken) {
         Runnable finishedCallback = new FinishedCallback(finishedToken);
-        
-        if (nature == INPUT_EVENT_NATURE_TOUCH) {
-            inputHandler.handleTouch(event, finishedCallback);
-        } else if (nature == INPUT_EVENT_NATURE_TRACKBALL) {
-            inputHandler.handleTrackball(event, finishedCallback);
-        } else {
-            Slog.d(TAG, "Unsupported nature for motion event: " + nature);
-        }
+        inputHandler.handleMotion(event, finishedCallback);
     }
     
     // TODO consider recycling finished callbacks when done
diff --git a/core/java/android/view/KeyCharacterMap.java b/core/java/android/view/KeyCharacterMap.java
index 25958aa..9981d87 100644
--- a/core/java/android/view/KeyCharacterMap.java
+++ b/core/java/android/view/KeyCharacterMap.java
@@ -26,6 +26,9 @@
 import java.lang.Character;
 import java.lang.ref.WeakReference;
 
+/**
+ * Describes the keys provided by a device and their associated labels.
+ */
 public class KeyCharacterMap
 {
     /**
@@ -59,6 +62,11 @@
     private static SparseArray<WeakReference<KeyCharacterMap>> sInstances 
         = new SparseArray<WeakReference<KeyCharacterMap>>();
 
+    /**
+     * Loads the key character maps for the keyboard with the specified device id.
+     * @param keyboard The device id of the keyboard.
+     * @return The associated key character map.
+     */
     public static KeyCharacterMap load(int keyboard)
     {
         synchronized (sLock) {
diff --git a/core/java/android/view/KeyEvent.java b/core/java/android/view/KeyEvent.java
index 9c05008..dd0d21a3 100755
--- a/core/java/android/view/KeyEvent.java
+++ b/core/java/android/view/KeyEvent.java
@@ -26,7 +26,7 @@
 /**
  * Contains constants for key events.
  */
-public class KeyEvent implements Parcelable {
+public class KeyEvent extends InputEvent implements Parcelable {
     // key codes
     public static final int KEYCODE_UNKNOWN         = 0;
     public static final int KEYCODE_SOFT_LEFT       = 1;
@@ -349,7 +349,6 @@
     private int mKeyCode;
     private int mScanCode;
     private int mRepeatCount;
-    private int mDeviceId;
     private int mFlags;
     private long mDownTime;
     private long mEventTime;
@@ -484,19 +483,19 @@
      * @param repeat A repeat count for down events (> 0 if this is after the
      * initial down) or event count for multiple events.
      * @param metaState Flags indicating which meta keys are currently pressed.
-     * @param device The device ID that generated the key event.
+     * @param deviceId The device ID that generated the key event.
      * @param scancode Raw device scan code of the event.
      */
     public KeyEvent(long downTime, long eventTime, int action,
                     int code, int repeat, int metaState,
-                    int device, int scancode) {
+                    int deviceId, int scancode) {
         mDownTime = downTime;
         mEventTime = eventTime;
         mAction = action;
         mKeyCode = code;
         mRepeatCount = repeat;
         mMetaState = metaState;
-        mDeviceId = device;
+        mDeviceId = deviceId;
         mScanCode = scancode;
     }
 
@@ -513,44 +512,79 @@
      * @param repeat A repeat count for down events (> 0 if this is after the
      * initial down) or event count for multiple events.
      * @param metaState Flags indicating which meta keys are currently pressed.
-     * @param device The device ID that generated the key event.
+     * @param deviceId The device ID that generated the key event.
      * @param scancode Raw device scan code of the event.
      * @param flags The flags for this key event
      */
     public KeyEvent(long downTime, long eventTime, int action,
                     int code, int repeat, int metaState,
-                    int device, int scancode, int flags) {
+                    int deviceId, int scancode, int flags) {
         mDownTime = downTime;
         mEventTime = eventTime;
         mAction = action;
         mKeyCode = code;
         mRepeatCount = repeat;
         mMetaState = metaState;
-        mDeviceId = device;
+        mDeviceId = deviceId;
         mScanCode = scancode;
         mFlags = flags;
     }
 
     /**
+     * Create a new key event.
+     * 
+     * @param downTime The time (in {@link android.os.SystemClock#uptimeMillis})
+     * at which this key code originally went down.
+     * @param eventTime The time (in {@link android.os.SystemClock#uptimeMillis})
+     * at which this event happened.
+     * @param action Action code: either {@link #ACTION_DOWN},
+     * {@link #ACTION_UP}, or {@link #ACTION_MULTIPLE}.
+     * @param code The key code.
+     * @param repeat A repeat count for down events (> 0 if this is after the
+     * initial down) or event count for multiple events.
+     * @param metaState Flags indicating which meta keys are currently pressed.
+     * @param deviceId The device ID that generated the key event.
+     * @param scancode Raw device scan code of the event.
+     * @param flags The flags for this key event
+     * @param source The input source such as {@link InputDevice#SOURCE_KEYBOARD}.
+     */
+    public KeyEvent(long downTime, long eventTime, int action,
+                    int code, int repeat, int metaState,
+                    int deviceId, int scancode, int flags, int source) {
+        mDownTime = downTime;
+        mEventTime = eventTime;
+        mAction = action;
+        mKeyCode = code;
+        mRepeatCount = repeat;
+        mMetaState = metaState;
+        mDeviceId = deviceId;
+        mScanCode = scancode;
+        mFlags = flags;
+        mSource = source;
+    }
+
+    /**
      * Create a new key event for a string of characters.  The key code,
-     * action, and repeat could will automatically be set to
-     * {@link #KEYCODE_UNKNOWN}, {@link #ACTION_MULTIPLE}, and 0 for you.
+     * action, repeat count and source will automatically be set to
+     * {@link #KEYCODE_UNKNOWN}, {@link #ACTION_MULTIPLE}, 0, and
+     * {@link InputDevice#SOURCE_KEYBOARD} for you.
      * 
      * @param time The time (in {@link android.os.SystemClock#uptimeMillis})
      * at which this event occured.
      * @param characters The string of characters.
-     * @param device The device ID that generated the key event.
+     * @param deviceId The device ID that generated the key event.
      * @param flags The flags for this key event
      */
-    public KeyEvent(long time, String characters, int device, int flags) {
+    public KeyEvent(long time, String characters, int deviceId, int flags) {
         mDownTime = time;
         mEventTime = time;
         mCharacters = characters;
         mAction = ACTION_MULTIPLE;
         mKeyCode = KEYCODE_UNKNOWN;
         mRepeatCount = 0;
-        mDeviceId = device;
+        mDeviceId = deviceId;
         mFlags = flags;
+        mSource = InputDevice.SOURCE_KEYBOARD;
     }
 
     /**
@@ -564,6 +598,7 @@
         mRepeatCount = origEvent.mRepeatCount;
         mMetaState = origEvent.mMetaState;
         mDeviceId = origEvent.mDeviceId;
+        mSource = origEvent.mSource;
         mScanCode = origEvent.mScanCode;
         mFlags = origEvent.mFlags;
         mCharacters = origEvent.mCharacters;
@@ -589,6 +624,7 @@
         mRepeatCount = newRepeat;
         mMetaState = origEvent.mMetaState;
         mDeviceId = origEvent.mDeviceId;
+        mSource = origEvent.mSource;
         mScanCode = origEvent.mScanCode;
         mFlags = origEvent.mFlags;
         mCharacters = origEvent.mCharacters;
@@ -642,6 +678,7 @@
         mRepeatCount = origEvent.mRepeatCount;
         mMetaState = origEvent.mMetaState;
         mDeviceId = origEvent.mDeviceId;
+        mSource = origEvent.mSource;
         mScanCode = origEvent.mScanCode;
         mFlags = origEvent.mFlags;
         // Don't copy mCharacters, since one way or the other we'll lose it
@@ -897,18 +934,6 @@
     }
 
     /**
-     * Return the id for the keyboard that this event came from.  A device
-     * id of 0 indicates the event didn't come from a physical device and
-     * maps to the default keymap.  The other numbers are arbitrary and
-     * you shouldn't depend on the values.
-     * 
-     * @see KeyCharacterMap#load
-     */
-    public final int getDeviceId() {
-        return mDeviceId;
-    }
-
-    /**
      * Renamed to {@link #getDeviceId}.
      * 
      * @hide
@@ -1204,6 +1229,7 @@
         out.writeInt(mRepeatCount);
         out.writeInt(mMetaState);
         out.writeInt(mDeviceId);
+        out.writeInt(mSource);
         out.writeInt(mScanCode);
         out.writeInt(mFlags);
         out.writeLong(mDownTime);
@@ -1216,6 +1242,7 @@
         mRepeatCount = in.readInt();
         mMetaState = in.readInt();
         mDeviceId = in.readInt();
+        mSource = in.readInt();
         mScanCode = in.readInt();
         mFlags = in.readInt();
         mDownTime = in.readLong();
diff --git a/core/java/android/view/MotionEvent.java b/core/java/android/view/MotionEvent.java
index 35e229a..49ef5a1 100644
--- a/core/java/android/view/MotionEvent.java
+++ b/core/java/android/view/MotionEvent.java
@@ -19,16 +19,17 @@
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.os.SystemClock;
-import android.util.Log;
 
 /**
  * Object used to report movement (mouse, pen, finger, trackball) events.  This
  * class may hold either absolute or relative movements, depending on what
  * it is being used for.
+ * 
+ * Refer to {@link InputDevice} for information about how different kinds of
+ * input devices and sources represent pointer coordinates.
  */
-public final class MotionEvent implements Parcelable {
+public final class MotionEvent extends InputEvent implements Parcelable {
     private static final long MS_PER_NS = 1000000;
-    static final boolean DEBUG_POINTERS = false;
     
     /**
      * Bit mask of the parts of the action code that are the action itself.
@@ -189,22 +190,52 @@
     static public final int SAMPLE_Y = 1;
     
     /**
-     * Offset for the sample's X coordinate.
+     * Offset for the sample's pressure.
      * @hide
      */
     static public final int SAMPLE_PRESSURE = 2;
     
     /**
-     * Offset for the sample's X coordinate.
+     * Offset for the sample's size
      * @hide
      */
     static public final int SAMPLE_SIZE = 3;
     
     /**
+     * Offset for the sample's touch major axis length.
+     * @hide
+     */
+    static public final int SAMPLE_TOUCH_MAJOR = 4;
+
+    /**
+     * Offset for the sample's touch minor axis length.
+     * @hide
+     */
+    static public final int SAMPLE_TOUCH_MINOR = 5;
+    
+    /**
+     * Offset for the sample's tool major axis length.
+     * @hide
+     */
+    static public final int SAMPLE_TOOL_MAJOR = 6;
+
+    /**
+     * Offset for the sample's tool minor axis length.
+     * @hide
+     */
+    static public final int SAMPLE_TOOL_MINOR = 7;
+    
+    /**
+     * Offset for the sample's orientation.
+     * @hide
+     */
+    static public final int SAMPLE_ORIENTATION = 8;
+
+    /**
      * Number of data items for each sample.
      * @hide
      */
-    static public final int NUM_SAMPLE_DATA = 4;
+    static public final int NUM_SAMPLE_DATA = 9;
     
     /**
      * Number of possible pointers.
@@ -225,7 +256,6 @@
     private float mYOffset;
     private float mXPrecision;
     private float mYPrecision;
-    private int mDeviceId;
     private int mEdgeFlags;
     private int mMetaState;
     
@@ -298,18 +328,16 @@
      * 
      * @param downTime The time (in ms) when the user originally pressed down to start 
      * a stream of position events.  This must be obtained from {@link SystemClock#uptimeMillis()}.
-     * @param eventTime  The the time (in ms) when this specific event was generated.  This 
+     * @param eventTime The the time (in ms) when this specific event was generated.  This 
      * must be obtained from {@link SystemClock#uptimeMillis()}.
-     * @param eventTimeNano  The the time (in ns) when this specific event was generated.  This 
-     * must be obtained from {@link System#nanoTime()}.
      * @param action The kind of action being performed -- one of either
      * {@link #ACTION_DOWN}, {@link #ACTION_MOVE}, {@link #ACTION_UP}, or
      * {@link #ACTION_CANCEL}.
      * @param pointers The number of points that will be in this event.
-     * @param inPointerIds An array of <em>pointers</em> values providing
+     * @param pointerIds An array of <em>pointers</em> values providing
      * an identifier for each pointer.
-     * @param inData An array of <em>pointers*NUM_SAMPLE_DATA</em> of initial
-     * data samples for the event.
+     * @param pointerCoords An array of <em>pointers</em> values providing
+     * a {@link PointerCoords} coordinate object for each pointer.
      * @param metaState The state of any meta / modifier keys that were in effect when
      * the event was generated.
      * @param xPrecision The precision of the X coordinate being reported.
@@ -319,14 +347,15 @@
      * numbers are arbitrary and you shouldn't depend on the values.
      * @param edgeFlags A bitfield indicating which edges, if any, where touched by this
      * MotionEvent.
-     *
-     * @hide
+     * @param source The source of this event.
      */
-    static public MotionEvent obtainNano(long downTime, long eventTime, long eventTimeNano,
-            int action, int pointers, int[] inPointerIds, float[] inData, int metaState,
-            float xPrecision, float yPrecision, int deviceId, int edgeFlags) {
+    static public MotionEvent obtain(long downTime, long eventTime,
+            int action, int pointers, int[] pointerIds, PointerCoords[] pointerCoords,
+            int metaState, float xPrecision, float yPrecision, int deviceId,
+            int edgeFlags, int source) {
         MotionEvent ev = obtain(pointers, 1);
         ev.mDeviceId = deviceId;
+        ev.mSource = source;
         ev.mEdgeFlags = edgeFlags;
         ev.mDownTimeNano = downTime * MS_PER_NS;
         ev.mAction = action;
@@ -342,26 +371,11 @@
         ev.mLastDataSampleIndex = 0;
         ev.mLastEventTimeNanoSampleIndex = 0;
         
-        System.arraycopy(inPointerIds, 0, ev.mPointerIdentifiers, 0, pointers);
+        System.arraycopy(pointerIds, 0, ev.mPointerIdentifiers, 0, pointers);
         
-        ev.mEventTimeNanoSamples[0] = eventTimeNano;
+        ev.mEventTimeNanoSamples[0] = eventTime * MS_PER_NS;
         
-        System.arraycopy(inData, 0, ev.mDataSamples, 0, pointers * NUM_SAMPLE_DATA);
-
-        if (DEBUG_POINTERS) {
-            StringBuilder sb = new StringBuilder(128);
-            sb.append("New:");
-            for (int i = 0; i < pointers; i++) {
-                sb.append(" #");
-                sb.append(ev.getPointerId(i));
-                sb.append("(");
-                sb.append(ev.getX(i));
-                sb.append(",");
-                sb.append(ev.getY(i));
-                sb.append(")");
-            }
-            Log.v("MotionEvent", sb.toString());
-        }
+        ev.setPointerCoordsAtSampleIndex(0, pointerCoords);
         
         return ev;
     }
@@ -402,6 +416,7 @@
             float xPrecision, float yPrecision, int deviceId, int edgeFlags) {
         MotionEvent ev = obtain(1, 1);
         ev.mDeviceId = deviceId;
+        ev.mSource = InputDevice.SOURCE_UNKNOWN;
         ev.mEdgeFlags = edgeFlags;
         ev.mDownTimeNano = downTime * MS_PER_NS;
         ev.mAction = action;
@@ -421,11 +436,7 @@
         
         ev.mEventTimeNanoSamples[0] = eventTime * MS_PER_NS;
         
-        float[] dataSamples = ev.mDataSamples;
-        dataSamples[SAMPLE_X] = x;
-        dataSamples[SAMPLE_Y] = y;
-        dataSamples[SAMPLE_PRESSURE] = pressure;
-        dataSamples[SAMPLE_SIZE] = size;
+        ev.setPointerCoordsAtSampleIndex(0, x, y, pressure, size);
         return ev;
     }
 
@@ -501,6 +512,7 @@
     static public MotionEvent obtain(MotionEvent o) {
         MotionEvent ev = obtain(o.mNumPointers, o.mNumSamples);
         ev.mDeviceId = o.mDeviceId;
+        ev.mSource = o.mSource;
         ev.mEdgeFlags = o.mEdgeFlags;
         ev.mDownTimeNano = o.mDownTimeNano;
         ev.mAction = o.mAction;
@@ -531,6 +543,7 @@
     static public MotionEvent obtainNoHistory(MotionEvent o) {
         MotionEvent ev = obtain(o.mNumPointers, 1);
         ev.mDeviceId = o.mDeviceId;
+        ev.mSource = o.mSource;
         ev.mEdgeFlags = o.mEdgeFlags;
         ev.mDownTimeNano = o.mDownTimeNano;
         ev.mAction = o.mAction;
@@ -602,6 +615,10 @@
             history[i + SAMPLE_Y] *= scale;
             // no need to scale pressure
             history[i + SAMPLE_SIZE] *= scale;    // TODO: square this?
+            history[i + SAMPLE_TOUCH_MAJOR] *= scale;
+            history[i + SAMPLE_TOUCH_MINOR] *= scale;
+            history[i + SAMPLE_TOOL_MAJOR] *= scale;
+            history[i + SAMPLE_TOOL_MINOR] *= scale;
         }
     }
 
@@ -696,6 +713,46 @@
     public final float getSize() {
         return mDataSamples[mLastDataSampleIndex + SAMPLE_SIZE];
     }
+    
+    /**
+     * {@link #getTouchMajor(int)} for the first pointer index (may be an
+     * arbitrary pointer identifier).
+     */
+    public final float getTouchMajor() {
+        return mDataSamples[mLastDataSampleIndex + SAMPLE_TOUCH_MAJOR];
+    }
+
+    /**
+     * {@link #getTouchMinor(int)} for the first pointer index (may be an
+     * arbitrary pointer identifier).
+     */
+    public final float getTouchMinor() {
+        return mDataSamples[mLastDataSampleIndex + SAMPLE_TOUCH_MINOR];
+    }
+    
+    /**
+     * {@link #getToolMajor(int)} for the first pointer index (may be an
+     * arbitrary pointer identifier).
+     */
+    public final float getToolMajor() {
+        return mDataSamples[mLastDataSampleIndex + SAMPLE_TOOL_MAJOR];
+    }
+
+    /**
+     * {@link #getToolMinor(int)} for the first pointer index (may be an
+     * arbitrary pointer identifier).
+     */
+    public final float getToolMinor() {
+        return mDataSamples[mLastDataSampleIndex + SAMPLE_TOOL_MINOR];
+    }
+    
+    /**
+     * {@link #getOrientation(int)} for the first pointer index (may be an
+     * arbitrary pointer identifier).
+     */
+    public final float getOrientation() {
+        return mDataSamples[mLastDataSampleIndex + SAMPLE_ORIENTATION];
+    }
 
     /**
      * The number of pointers of data contained in this event.  Always
@@ -796,6 +853,93 @@
         return mDataSamples[mLastDataSampleIndex
                             + pointerIndex * NUM_SAMPLE_DATA + SAMPLE_SIZE];
     }
+    
+    /**
+     * Returns the length of the major axis of an ellipse that describes the touch
+     * area at the point of contact for the given pointer
+     * <em>index</em> (use {@link #getPointerId(int)} to find the pointer
+     * identifier for this index).
+     * @param pointerIndex Raw index of pointer to retrieve.  Value may be from 0
+     * (the first pointer that is down) to {@link #getPointerCount()}-1.
+     */
+    public final float getTouchMajor(int pointerIndex) {
+        return mDataSamples[mLastDataSampleIndex
+                            + pointerIndex * NUM_SAMPLE_DATA + SAMPLE_TOUCH_MAJOR];
+    }
+    
+    /**
+     * Returns the length of the minor axis of an ellipse that describes the touch
+     * area at the point of contact for the given pointer
+     * <em>index</em> (use {@link #getPointerId(int)} to find the pointer
+     * identifier for this index).
+     * @param pointerIndex Raw index of pointer to retrieve.  Value may be from 0
+     * (the first pointer that is down) to {@link #getPointerCount()}-1.
+     */
+    public final float getTouchMinor(int pointerIndex) {
+        return mDataSamples[mLastDataSampleIndex
+                            + pointerIndex * NUM_SAMPLE_DATA + SAMPLE_TOUCH_MINOR];
+    }
+    
+    /**
+     * Returns the length of the major axis of an ellipse that describes the size of
+     * the approaching tool for the given pointer
+     * <em>index</em> (use {@link #getPointerId(int)} to find the pointer
+     * identifier for this index).
+     * The tool area represents the estimated size of the finger or pen that is
+     * touching the device independent of its actual touch area at the point of contact.
+     * @param pointerIndex Raw index of pointer to retrieve.  Value may be from 0
+     * (the first pointer that is down) to {@link #getPointerCount()}-1.
+     */
+    public final float getToolMajor(int pointerIndex) {
+        return mDataSamples[mLastDataSampleIndex
+                            + pointerIndex * NUM_SAMPLE_DATA + SAMPLE_TOOL_MAJOR];
+    }
+    
+    /**
+     * Returns the length of the minor axis of an ellipse that describes the size of
+     * the approaching tool for the given pointer
+     * <em>index</em> (use {@link #getPointerId(int)} to find the pointer
+     * identifier for this index).
+     * The tool area represents the estimated size of the finger or pen that is
+     * touching the device independent of its actual touch area at the point of contact.
+     * @param pointerIndex Raw index of pointer to retrieve.  Value may be from 0
+     * (the first pointer that is down) to {@link #getPointerCount()}-1.
+     */
+    public final float getToolMinor(int pointerIndex) {
+        return mDataSamples[mLastDataSampleIndex
+                            + pointerIndex * NUM_SAMPLE_DATA + SAMPLE_TOOL_MINOR];
+    }
+    
+    /**
+     * Returns the orientation of the touch area and tool area in radians clockwise from vertical
+     * for the given pointer <em>index</em> (use {@link #getPointerId(int)} to find the pointer
+     * identifier for this index).
+     * An angle of 0 degrees indicates that the major axis of contact is oriented
+     * upwards, is perfectly circular or is of unknown orientation.  A positive angle
+     * indicates that the major axis of contact is oriented to the right.  A negative angle
+     * indicates that the major axis of contact is oriented to the left.
+     * The full range is from -PI/4 radians (finger pointing fully left) to PI/4 radians
+     * (finger pointing fully right).
+     * @param pointerIndex Raw index of pointer to retrieve.  Value may be from 0
+     * (the first pointer that is down) to {@link #getPointerCount()}-1.
+     */
+    public final float getOrientation(int pointerIndex) {
+        return mDataSamples[mLastDataSampleIndex
+                            + pointerIndex * NUM_SAMPLE_DATA + SAMPLE_ORIENTATION];
+    }
+    
+    /**
+     * Populates a {@link PointerCoords} object with pointer coordinate data for
+     * the specified pointer index.
+     * 
+     * @param pointerIndex Raw index of pointer to retrieve.  Value may be from 0
+     * (the first pointer that is down) to {@link #getPointerCount()}-1.
+     * @param outPointerCoords The pointer coordinate object to populate.
+     */
+    public final void getPointerCoords(int pointerIndex, PointerCoords outPointerCoords) {
+        final int sampleIndex = mLastDataSampleIndex + pointerIndex * NUM_SAMPLE_DATA;
+        getPointerCoordsAtSampleIndex(sampleIndex, outPointerCoords);
+    }
 
     /**
      * Returns the state of any meta / modifier keys that were in effect when
@@ -820,7 +964,7 @@
     public final float getRawX() {
         return mDataSamples[mLastDataSampleIndex + SAMPLE_X];
     }
-
+    
     /**
      * Returns the original raw Y coordinate of this event.  For touch
      * events on the screen, this is the original location of the event
@@ -910,6 +1054,46 @@
     }
 
     /**
+     * {@link #getHistoricalTouchMajor(int)} for the first pointer index (may be an
+     * arbitrary pointer identifier).
+     */
+    public final float getHistoricalTouchMajor(int pos) {
+        return mDataSamples[pos * mNumPointers * NUM_SAMPLE_DATA + SAMPLE_TOUCH_MAJOR];
+    }
+
+    /**
+     * {@link #getHistoricalTouchMinor(int)} for the first pointer index (may be an
+     * arbitrary pointer identifier).
+     */
+    public final float getHistoricalTouchMinor(int pos) {
+        return mDataSamples[pos * mNumPointers * NUM_SAMPLE_DATA + SAMPLE_TOUCH_MINOR];
+    }
+    
+    /**
+     * {@link #getHistoricalToolMajor(int)} for the first pointer index (may be an
+     * arbitrary pointer identifier).
+     */
+    public final float getHistoricalToolMajor(int pos) {
+        return mDataSamples[pos * mNumPointers * NUM_SAMPLE_DATA + SAMPLE_TOOL_MAJOR];
+    }
+
+    /**
+     * {@link #getHistoricalToolMinor(int)} for the first pointer index (may be an
+     * arbitrary pointer identifier).
+     */
+    public final float getHistoricalToolMinor(int pos) {
+        return mDataSamples[pos * mNumPointers * NUM_SAMPLE_DATA + SAMPLE_TOOL_MINOR];
+    }
+    
+    /**
+     * {@link #getHistoricalOrientation(int)} for the first pointer index (may be an
+     * arbitrary pointer identifier).
+     */
+    public final float getHistoricalOrientation(int pos) {
+        return mDataSamples[pos * mNumPointers * NUM_SAMPLE_DATA + SAMPLE_ORIENTATION];
+    }
+    
+    /**
      * Returns a historical X coordinate, as per {@link #getX(int)}, that
      * occurred between this event and the previous event for the given pointer.
      * Only applies to ACTION_MOVE events.
@@ -980,17 +1164,119 @@
         return mDataSamples[(pos * mNumPointers + pointerIndex)
                             * NUM_SAMPLE_DATA + SAMPLE_SIZE];
     }
-
+    
     /**
-     * Return the id for the device that this event came from.  An id of
-     * zero indicates that the event didn't come from a physical device; other
-     * numbers are arbitrary and you shouldn't depend on the values.
+     * Returns a historical touch major axis coordinate, as per {@link #getTouchMajor(int)}, that
+     * occurred between this event and the previous event for the given pointer.
+     * Only applies to ACTION_MOVE events.
+     *
+     * @param pointerIndex Raw index of pointer to retrieve.  Value may be from 0
+     * (the first pointer that is down) to {@link #getPointerCount()}-1.
+     * @param pos Which historical value to return; must be less than
+     * {@link #getHistorySize}
+     * 
+     * @see #getHistorySize
+     * @see #getTouchMajor
      */
-    public final int getDeviceId() {
-        return mDeviceId;
+    public final float getHistoricalTouchMajor(int pointerIndex, int pos) {
+        return mDataSamples[(pos * mNumPointers + pointerIndex)
+                            * NUM_SAMPLE_DATA + SAMPLE_TOUCH_MAJOR];
     }
 
     /**
+     * Returns a historical touch minor axis coordinate, as per {@link #getTouchMinor(int)}, that
+     * occurred between this event and the previous event for the given pointer.
+     * Only applies to ACTION_MOVE events.
+     *
+     * @param pointerIndex Raw index of pointer to retrieve.  Value may be from 0
+     * (the first pointer that is down) to {@link #getPointerCount()}-1.
+     * @param pos Which historical value to return; must be less than
+     * {@link #getHistorySize}
+     * 
+     * @see #getHistorySize
+     * @see #getTouchMinor
+     */
+    public final float getHistoricalTouchMinor(int pointerIndex, int pos) {
+        return mDataSamples[(pos * mNumPointers + pointerIndex)
+                            * NUM_SAMPLE_DATA + SAMPLE_TOUCH_MINOR];
+    }
+
+    /**
+     * Returns a historical tool major axis coordinate, as per {@link #getToolMajor(int)}, that
+     * occurred between this event and the previous event for the given pointer.
+     * Only applies to ACTION_MOVE events.
+     *
+     * @param pointerIndex Raw index of pointer to retrieve.  Value may be from 0
+     * (the first pointer that is down) to {@link #getPointerCount()}-1.
+     * @param pos Which historical value to return; must be less than
+     * {@link #getHistorySize}
+     * 
+     * @see #getHistorySize
+     * @see #getToolMajor
+     */
+    public final float getHistoricalToolMajor(int pointerIndex, int pos) {
+        return mDataSamples[(pos * mNumPointers + pointerIndex)
+                            * NUM_SAMPLE_DATA + SAMPLE_TOOL_MAJOR];
+    }
+
+    /**
+     * Returns a historical tool minor axis coordinate, as per {@link #getToolMinor(int)}, that
+     * occurred between this event and the previous event for the given pointer.
+     * Only applies to ACTION_MOVE events.
+     *
+     * @param pointerIndex Raw index of pointer to retrieve.  Value may be from 0
+     * (the first pointer that is down) to {@link #getPointerCount()}-1.
+     * @param pos Which historical value to return; must be less than
+     * {@link #getHistorySize}
+     * 
+     * @see #getHistorySize
+     * @see #getToolMinor
+     */
+    public final float getHistoricalToolMinor(int pointerIndex, int pos) {
+        return mDataSamples[(pos * mNumPointers + pointerIndex)
+                            * NUM_SAMPLE_DATA + SAMPLE_TOOL_MINOR];
+    }
+
+    /**
+     * Returns a historical orientation coordinate, as per {@link #getOrientation(int)}, that
+     * occurred between this event and the previous event for the given pointer.
+     * Only applies to ACTION_MOVE events.
+     *
+     * @param pointerIndex Raw index of pointer to retrieve.  Value may be from 0
+     * (the first pointer that is down) to {@link #getPointerCount()}-1.
+     * @param pos Which historical value to return; must be less than
+     * {@link #getHistorySize}
+     * 
+     * @see #getHistorySize
+     * @see #getOrientation
+     */
+    public final float getHistoricalOrientation(int pointerIndex, int pos) {
+        return mDataSamples[(pos * mNumPointers + pointerIndex)
+                            * NUM_SAMPLE_DATA + SAMPLE_ORIENTATION];
+    }
+
+    /**
+     * Populates a {@link PointerCoords} object with historical pointer coordinate data,
+     * as per {@link #getPointerCoords}, that occurred between this event and the previous
+     * event for the given pointer.
+     * Only applies to ACTION_MOVE events.
+     * 
+     * @param pointerIndex Raw index of pointer to retrieve.  Value may be from 0
+     * (the first pointer that is down) to {@link #getPointerCount()}-1.
+     * @param pos Which historical value to return; must be less than
+     * {@link #getHistorySize}
+     * @param outPointerCoords The pointer coordinate object to populate.
+     * 
+     * @see #getHistorySize
+     * @see #getPointerCoords
+     */
+    public final void getHistoricalPointerCoords(int pointerIndex, int pos,
+            PointerCoords outPointerCoords) {
+        final int sampleIndex = (pos * mNumPointers + pointerIndex) * NUM_SAMPLE_DATA;
+        getPointerCoordsAtSampleIndex(sampleIndex, outPointerCoords);
+    }
+    
+    /**
      * Returns a bitfield indicating which edges, if any, were touched by this
      * MotionEvent. For touch events, clients can use this to determine if the
      * user's finger was touching the edge of the display.
@@ -1044,6 +1330,54 @@
         mYOffset = y - mDataSamples[mLastDataSampleIndex + SAMPLE_Y];
     }
     
+    private final void getPointerCoordsAtSampleIndex(int sampleIndex,
+            PointerCoords outPointerCoords) {
+        outPointerCoords.x = mDataSamples[sampleIndex + SAMPLE_X] + mXOffset;
+        outPointerCoords.y = mDataSamples[sampleIndex + SAMPLE_Y] + mYOffset;
+        outPointerCoords.pressure = mDataSamples[sampleIndex + SAMPLE_PRESSURE];
+        outPointerCoords.size = mDataSamples[sampleIndex + SAMPLE_SIZE];
+        outPointerCoords.touchMajor = mDataSamples[sampleIndex + SAMPLE_TOUCH_MAJOR];
+        outPointerCoords.touchMinor = mDataSamples[sampleIndex + SAMPLE_TOUCH_MINOR];
+        outPointerCoords.toolMajor = mDataSamples[sampleIndex + SAMPLE_TOOL_MAJOR];
+        outPointerCoords.toolMinor = mDataSamples[sampleIndex + SAMPLE_TOOL_MINOR];
+        outPointerCoords.orientation = mDataSamples[sampleIndex + SAMPLE_ORIENTATION];
+    }
+    
+    private final void setPointerCoordsAtSampleIndex(int sampleIndex,
+            PointerCoords[] pointerCoords) {
+        final int numPointers = mNumPointers;
+        for (int i = 0; i < numPointers; i++) {
+            setPointerCoordsAtSampleIndex(sampleIndex, pointerCoords[i]);
+            sampleIndex += NUM_SAMPLE_DATA;
+        }
+    }
+    
+    private final void setPointerCoordsAtSampleIndex(int sampleIndex,
+            PointerCoords pointerCoords) {
+        mDataSamples[sampleIndex + SAMPLE_X] = pointerCoords.x - mXOffset;
+        mDataSamples[sampleIndex + SAMPLE_Y] = pointerCoords.y - mYOffset;
+        mDataSamples[sampleIndex + SAMPLE_PRESSURE] = pointerCoords.pressure;
+        mDataSamples[sampleIndex + SAMPLE_SIZE] = pointerCoords.size;
+        mDataSamples[sampleIndex + SAMPLE_TOUCH_MAJOR] = pointerCoords.touchMajor;
+        mDataSamples[sampleIndex + SAMPLE_TOUCH_MINOR] = pointerCoords.touchMinor;
+        mDataSamples[sampleIndex + SAMPLE_TOOL_MAJOR] = pointerCoords.toolMajor;
+        mDataSamples[sampleIndex + SAMPLE_TOOL_MINOR] = pointerCoords.toolMinor;
+        mDataSamples[sampleIndex + SAMPLE_ORIENTATION] = pointerCoords.orientation;
+    }
+    
+    private final void setPointerCoordsAtSampleIndex(int sampleIndex,
+            float x, float y, float pressure, float size) {
+        mDataSamples[sampleIndex + SAMPLE_X] = x - mXOffset;
+        mDataSamples[sampleIndex + SAMPLE_Y] = y - mYOffset;
+        mDataSamples[sampleIndex + SAMPLE_PRESSURE] = pressure;
+        mDataSamples[sampleIndex + SAMPLE_SIZE] = size;
+        mDataSamples[sampleIndex + SAMPLE_TOUCH_MAJOR] = pressure;
+        mDataSamples[sampleIndex + SAMPLE_TOUCH_MINOR] = pressure;
+        mDataSamples[sampleIndex + SAMPLE_TOOL_MAJOR] = size;
+        mDataSamples[sampleIndex + SAMPLE_TOOL_MINOR] = size;
+        mDataSamples[sampleIndex + SAMPLE_ORIENTATION] = 0;
+    }
+    
     private final void incrementNumSamplesAndReserveStorage(int dataSampleStride) {
         if (mNumSamples == mEventTimeNanoSamples.length) {
             long[] newEventTimeNanoSamples = new long[mNumSamples + BASE_AVAIL_SAMPLES];
@@ -1066,11 +1400,12 @@
 
     /**
      * Add a new movement to the batch of movements in this event.  The event's
-     * current location, position and size is updated to the new values.  In
-     * the future, the current values in the event will be added to a list of
-     * historic values.
+     * current location, position and size is updated to the new values.
+     * The current values in the event are added to a list of historical values.
+     * 
+     * Only applies to {@link ACTION_MOVE} events.
      *
-     * @param eventTime The time stamp for this data.
+     * @param eventTime The time stamp (in ms) for this data.
      * @param x The new X position.
      * @param y The new Y position.
      * @param pressure The new pressure.
@@ -1082,62 +1417,30 @@
         incrementNumSamplesAndReserveStorage(NUM_SAMPLE_DATA);
         
         mEventTimeNanoSamples[mLastEventTimeNanoSampleIndex] = eventTime * MS_PER_NS;
-        
-        float[] dataSamples = mDataSamples;
-        dataSamples[mLastDataSampleIndex + SAMPLE_X] = x - mXOffset;
-        dataSamples[mLastDataSampleIndex + SAMPLE_Y] = y - mYOffset;
-        dataSamples[mLastDataSampleIndex + SAMPLE_PRESSURE] = pressure;
-        dataSamples[mLastDataSampleIndex + SAMPLE_SIZE] = size;
+        setPointerCoordsAtSampleIndex(mLastDataSampleIndex, x, y, pressure, size);
         
         mMetaState |= metaState;
     }
 
     /**
-     * Add a new movement to the batch of movements in this event.  The
-     * input data must contain (NUM_SAMPLE_DATA * {@link #getPointerCount()})
-     * samples of data.
-     *
-     * @param eventTime The time stamp for this data.
-     * @param inData The actual data.
-     * @param metaState Meta key state.
+     * Add a new movement to the batch of movements in this event.  The event's
+     * current location, position and size is updated to the new values.
+     * The current values in the event are added to a list of historical values.
      * 
-     * @hide
+     * Only applies to {@link ACTION_MOVE} events.
+     *
+     * @param eventTime The time stamp (in ms) for this data.
+     * @param pointerCoords The new pointer coordinates.
+     * @param metaState Meta key state.
      */
-    public final void addBatch(long eventTime, float[] inData, int metaState) {
-        final int numPointers = mNumPointers;
-        final int dataSampleStride = numPointers * NUM_SAMPLE_DATA;
+    public final void addBatch(long eventTime, PointerCoords[] pointerCoords, int metaState) {
+        final int dataSampleStride = mNumPointers * NUM_SAMPLE_DATA;
         incrementNumSamplesAndReserveStorage(dataSampleStride);
         
         mEventTimeNanoSamples[mLastEventTimeNanoSampleIndex] = eventTime * MS_PER_NS;
-        
-        float[] dataSamples = mDataSamples;
-        System.arraycopy(inData, 0, dataSamples, mLastDataSampleIndex, dataSampleStride);
-
-        if (mXOffset != 0 || mYOffset != 0) {
-            int index = mLastEventTimeNanoSampleIndex;
-            for (int i = 0; i < numPointers; i++) {
-                dataSamples[index + SAMPLE_X] -= mXOffset;
-                dataSamples[index + SAMPLE_Y] -= mYOffset;
-                index += NUM_SAMPLE_DATA;
-            }
-        }
+        setPointerCoordsAtSampleIndex(mLastDataSampleIndex, pointerCoords);
         
         mMetaState |= metaState;
-        
-        if (DEBUG_POINTERS) {
-            StringBuilder sb = new StringBuilder(128);
-            sb.append("Add:");
-            for (int i = 0; i < mNumPointers; i++) {
-                sb.append(" #");
-                sb.append(getPointerId(i));
-                sb.append("(");
-                sb.append(getX(i));
-                sb.append(",");
-                sb.append(getY(i));
-                sb.append(")");
-            }
-            Log.v("MotionEvent", sb.toString());
-        }
     }
 
     @Override
@@ -1165,6 +1468,7 @@
             ev.mXPrecision = in.readFloat();
             ev.mYPrecision = in.readFloat();
             ev.mDeviceId = in.readInt();
+            ev.mSource = in.readInt();
             ev.mEdgeFlags = in.readInt();
             ev.mMetaState = in.readInt();
             
@@ -1212,6 +1516,7 @@
         out.writeFloat(mXPrecision);
         out.writeFloat(mYPrecision);
         out.writeInt(mDeviceId);
+        out.writeInt(mSource);
         out.writeInt(mEdgeFlags);
         out.writeInt(mMetaState);
         
@@ -1230,4 +1535,108 @@
             out.writeFloat(dataSamples[i]);
         }
     }
+    
+    /**
+     * Transfer object for pointer coordinates.
+     * 
+     * Objects of this type can be used to manufacture new {@link MotionEvent} objects
+     * and to query pointer coordinate information in bulk.
+     * 
+     * Refer to {@link InputDevice} for information about how different kinds of
+     * input devices and sources represent pointer coordinates.
+     */
+    public static final class PointerCoords {
+        /**
+         * The X coordinate of the pointer movement.
+         * The interpretation varies by input source and may represent the position of
+         * the center of the contact area, a relative displacement in device-specific units
+         * or something else.
+         */
+        public float x;
+        
+        /**
+         * The Y coordinate of the pointer movement.
+         * The interpretation varies by input source and may represent the position of
+         * the center of the contact area, a relative displacement in device-specific units
+         * or something else.
+         */
+        public float y;
+        
+        /**
+         * A scaled value that describes the pressure applied to the pointer.
+         * The pressure generally ranges from 0 (no pressure at all) to 1 (normal pressure),
+         * however values higher than 1 may be generated depending on the calibration of
+         * the input device.
+         */
+        public float pressure;
+        
+        /**
+         * A scaled value of the approximate size of the pointer touch area.
+         * This represents some approximation of the area of the screen being
+         * pressed; the actual value in pixels corresponding to the
+         * touch is normalized with the device specific range of values
+         * and scaled to a value between 0 and 1. The value of size can be used to
+         * determine fat touch events.
+         */
+        public float size;
+        
+        /**
+         * The length of the major axis of an ellipse that describes the touch area at
+         * the point of contact.
+         */
+        public float touchMajor;
+        
+        /**
+         * The length of the minor axis of an ellipse that describes the touch area at
+         * the point of contact.
+         */
+        public float touchMinor;
+        
+        /**
+         * The length of the major axis of an ellipse that describes the size of
+         * the approaching tool.
+         * The tool area represents the estimated size of the finger or pen that is
+         * touching the device independent of its actual touch area at the point of contact.
+         */
+        public float toolMajor;
+        
+        /**
+         * The length of the minor axis of an ellipse that describes the size of
+         * the approaching tool.
+         * The tool area represents the estimated size of the finger or pen that is
+         * touching the device independent of its actual touch area at the point of contact.
+         */
+        public float toolMinor;
+        
+        /**
+         * The orientation of the touch area and tool area in radians clockwise from vertical.
+         * An angle of 0 degrees indicates that the major axis of contact is oriented
+         * upwards, is perfectly circular or is of unknown orientation.  A positive angle
+         * indicates that the major axis of contact is oriented to the right.  A negative angle
+         * indicates that the major axis of contact is oriented to the left.
+         * The full range is from -PI/4 radians (finger pointing fully left) to PI/4 radians
+         * (finger pointing fully right).
+         */
+        public float orientation;
+        
+        /*
+        private static final float PI_8 = (float) (Math.PI / 8);
+        
+        public float getTouchWidth() {
+            return Math.abs(orientation) > PI_8 ? touchMajor : touchMinor;
+        }
+        
+        public float getTouchHeight() {
+            return Math.abs(orientation) > PI_8 ? touchMinor : touchMajor;
+        }
+        
+        public float getToolWidth() {
+            return Math.abs(orientation) > PI_8 ? toolMajor : toolMinor;
+        }
+        
+        public float getToolHeight() {
+            return Math.abs(orientation) > PI_8 ? toolMinor : toolMajor;
+        }
+        */
+    }
 }
diff --git a/core/java/android/view/ViewRoot.java b/core/java/android/view/ViewRoot.java
index a89e7f6..03cbb8a 100644
--- a/core/java/android/view/ViewRoot.java
+++ b/core/java/android/view/ViewRoot.java
@@ -400,7 +400,7 @@
                 }
                 mPendingContentInsets.set(mAttachInfo.mContentInsets);
                 mPendingVisibleInsets.set(0, 0, 0, 0);
-                if (Config.LOGV) Log.v("ViewRoot", "Added window " + mWindow);
+                if (Config.LOGV) Log.v(TAG, "Added window " + mWindow);
                 if (res < WindowManagerImpl.ADD_OKAY) {
                     mView = null;
                     mAttachInfo.mRootView = null;
@@ -665,7 +665,7 @@
             desiredWindowWidth = frame.width();
             desiredWindowHeight = frame.height();
             if (desiredWindowWidth != mWidth || desiredWindowHeight != mHeight) {
-                if (DEBUG_ORIENTATION) Log.v("ViewRoot",
+                if (DEBUG_ORIENTATION) Log.v(TAG,
                         "View " + host + " resized to: " + frame);
                 fullRedrawNeeded = true;
                 mLayoutRequested = true;
@@ -729,7 +729,7 @@
             childHeightMeasureSpec = getRootMeasureSpec(desiredWindowHeight, lp.height);
 
             // Ask host how big it wants to be
-            if (DEBUG_ORIENTATION || DEBUG_LAYOUT) Log.v("ViewRoot",
+            if (DEBUG_ORIENTATION || DEBUG_LAYOUT) Log.v(TAG,
                     "Measuring " + host + " in display " + desiredWindowWidth
                     + "x" + desiredWindowHeight + "...");
             host.measure(childWidthMeasureSpec, childHeightMeasureSpec);
@@ -900,7 +900,7 @@
             }
             
             if (DEBUG_ORIENTATION) Log.v(
-                    "ViewRoot", "Relayout returned: frame=" + frame + ", surface=" + mSurface);
+                    TAG, "Relayout returned: frame=" + frame + ", surface=" + mSurface);
 
             attachInfo.mWindowLeft = frame.left;
             attachInfo.mWindowTop = frame.top;
@@ -1020,7 +1020,7 @@
             mLayoutRequested = false;
             mScrollMayChange = true;
             if (DEBUG_ORIENTATION || DEBUG_LAYOUT) Log.v(
-                "ViewRoot", "Laying out " + host + " to (" +
+                TAG, "Laying out " + host + " to (" +
                 host.mMeasuredWidth + ", " + host.mMeasuredHeight + ")");
             long startTime = 0L;
             if (Config.DEBUG && ViewDebug.profileLayout) {
@@ -1149,7 +1149,7 @@
             if ((relayoutResult&WindowManagerImpl.RELAYOUT_FIRST_TIME) != 0
                     || mReportNextDraw) {
                 if (LOCAL_LOGV) {
-                    Log.v("ViewRoot", "FINISHED DRAWING: " + mWindowAttributes.getTitle());
+                    Log.v(TAG, "FINISHED DRAWING: " + mWindowAttributes.getTitle());
                 }
                 mReportNextDraw = false;
                 if (mSurfaceHolder != null && mSurface.isValid()) {
@@ -1290,7 +1290,7 @@
         }
 
         if (DEBUG_ORIENTATION || DEBUG_DRAW) {
-            Log.v("ViewRoot", "Draw " + mView + "/"
+            Log.v(TAG, "Draw " + mView + "/"
                     + mWindowAttributes.getTitle()
                     + ": dirty={" + dirty.left + "," + dirty.top
                     + "," + dirty.right + "," + dirty.bottom + "} surface="
@@ -1315,12 +1315,12 @@
                 // TODO: Do this in native
                 canvas.setDensity(mDensity);
             } catch (Surface.OutOfResourcesException e) {
-                Log.e("ViewRoot", "OutOfResourcesException locking surface", e);
+                Log.e(TAG, "OutOfResourcesException locking surface", e);
                 // TODO: we should ask the window manager to do something!
                 // for now we just do nothing
                 return;
             } catch (IllegalArgumentException e) {
-                Log.e("ViewRoot", "IllegalArgumentException locking surface", e);
+                Log.e(TAG, "IllegalArgumentException locking surface", e);
                 // TODO: we should ask the window manager to do something!
                 // for now we just do nothing
                 return;
@@ -1331,7 +1331,7 @@
                     long startTime = 0L;
 
                     if (DEBUG_ORIENTATION || DEBUG_DRAW) {
-                        Log.v("ViewRoot", "Surface " + surface + " drawing to bitmap w="
+                        Log.v(TAG, "Surface " + surface + " drawing to bitmap w="
                                 + canvas.getWidth() + ", h=" + canvas.getHeight());
                         //canvas.drawARGB(255, 255, 0, 0);
                     }
@@ -1400,7 +1400,7 @@
         }
 
         if (LOCAL_LOGV) {
-            Log.v("ViewRoot", "Surface " + surface + " unlockCanvasAndPost");
+            Log.v(TAG, "Surface " + surface + " unlockCanvasAndPost");
         }
 
         if (scrolling) {
@@ -1718,7 +1718,7 @@
             break;
         case DISPATCH_KEY:
             if (LOCAL_LOGV) Log.v(
-                "ViewRoot", "Dispatching key "
+                TAG, "Dispatching key "
                 + msg.obj + " to " + mView);
             deliverKeyEvent((KeyEvent)msg.obj, true);
             break;
@@ -1830,7 +1830,7 @@
             break;
         case DISPATCH_KEY_FROM_IME: {
             if (LOCAL_LOGV) Log.v(
-                "ViewRoot", "Dispatching key "
+                TAG, "Dispatching key "
                 + msg.obj + " from IME to " + mView);
             KeyEvent event = (KeyEvent)msg.obj;
             if ((event.getFlags()&KeyEvent.FLAG_FROM_SYSTEM) != 0) {
@@ -2323,7 +2323,7 @@
         if (handled) {
             if (sendDone) {
                 if (LOCAL_LOGV) Log.v(
-                    "ViewRoot", "Telling window manager key is finished");
+                    TAG, "Telling window manager key is finished");
                 finishKeyEvent(event);
             }
             return;
@@ -2355,10 +2355,10 @@
                 deliverKeyEventToViewHierarchy(event, sendDone);
             } else if (sendDone) {
                 if (LOCAL_LOGV) Log.v(
-                        "ViewRoot", "Telling window manager key is finished");
+                        TAG, "Telling window manager key is finished");
                 finishKeyEvent(event);
             } else {
-                Log.w("ViewRoot", "handleFinishedEvent(seq=" + seq
+                Log.w(TAG, "handleFinishedEvent(seq=" + seq
                         + " handled=" + handled + " ev=" + event
                         + ") neither delivering nor finishing key");
             }
@@ -2430,7 +2430,7 @@
         } finally {
             if (sendDone) {
                 if (LOCAL_LOGV) Log.v(
-                    "ViewRoot", "Telling window manager key is finished");
+                    TAG, "Telling window manager key is finished");
                 finishKeyEvent(event);
             }
             // Let the exception fall through -- the looper will catch
@@ -2553,7 +2553,7 @@
 
     void doDie() {
         checkThread();
-        if (LOCAL_LOGV) Log.v("ViewRoot", "DIE in " + this + " of " + mSurface);
+        if (LOCAL_LOGV) Log.v(TAG, "DIE in " + this + " of " + mSurface);
         synchronized (this) {
             if (mAdded && !mFirst) {
                 int viewVisibility = mView.getVisibility();
@@ -2619,16 +2619,10 @@
             dispatchKey(event);
         }
 
-        public void handleTouch(MotionEvent event, Runnable finishedCallback) {
+        public void handleMotion(MotionEvent event, Runnable finishedCallback) {
             finishedCallback.run();
             
-            dispatchPointer(event);
-        }
-
-        public void handleTrackball(MotionEvent event, Runnable finishedCallback) {
-            finishedCallback.run();
-            
-            dispatchTrackball(event);
+            dispatchMotion(event);
         }
     };
 
@@ -2649,10 +2643,22 @@
         msg.obj = event;
 
         if (LOCAL_LOGV) Log.v(
-            "ViewRoot", "sending key " + event + " to " + mView);
+            TAG, "sending key " + event + " to " + mView);
 
         sendMessageAtTime(msg, event.getEventTime());
     }
+    
+    public void dispatchMotion(MotionEvent event) {
+        int source = event.getSource();
+        if ((source & InputDevice.SOURCE_CLASS_POINTER) != 0) {
+            dispatchPointer(event);
+        } else if ((source & InputDevice.SOURCE_CLASS_TRACKBALL) != 0) {
+            dispatchTrackball(event);
+        } else {
+            // TODO
+            Log.v(TAG, "Dropping unsupported motion event (unimplemented): " + event);
+        }
+    }
 
     public void dispatchPointer(MotionEvent event) {
         Message msg = obtainMessage(DISPATCH_POINTER);
diff --git a/core/java/com/android/internal/view/BaseInputHandler.java b/core/java/com/android/internal/view/BaseInputHandler.java
index 6fe5063..e943a7d 100644
--- a/core/java/com/android/internal/view/BaseInputHandler.java
+++ b/core/java/com/android/internal/view/BaseInputHandler.java
@@ -29,11 +29,7 @@
         finishedCallback.run();
     }
     
-    public void handleTouch(MotionEvent event, Runnable finishedCallback) {
-        finishedCallback.run();
-    }
-    
-    public void handleTrackball(MotionEvent event, Runnable finishedCallback) {
+    public void handleMotion(MotionEvent event, Runnable finishedCallback) {
         finishedCallback.run();
     }
 }
diff --git a/core/jni/android_app_NativeActivity.cpp b/core/jni/android_app_NativeActivity.cpp
index 9f042c2..c17b504 100644
--- a/core/jni/android_app_NativeActivity.cpp
+++ b/core/jni/android_app_NativeActivity.cpp
@@ -196,7 +196,7 @@
 void AInputQueue::finishEvent(AInputEvent* event, bool handled) {
     bool needFinished = true;
 
-    if (!handled && ((InputEvent*)event)->getType() == INPUT_EVENT_TYPE_KEY
+    if (!handled && ((InputEvent*)event)->getType() == AINPUT_EVENT_TYPE_KEY
             && ((KeyEvent*)event)->hasDefaultAction()) {
         // The app didn't handle this, but it may have a default action
         // associated with it.  We need to hand this back to Java to be
@@ -767,7 +767,7 @@
         NativeCode* code = (NativeCode*)handle;
         if (code->nativeInputQueue != NULL) {
             KeyEvent* event = new KeyEvent();
-            android_view_KeyEvent_toNative(env, eventObj, INPUT_EVENT_NATURE_KEY, event);
+            android_view_KeyEvent_toNative(env, eventObj, event);
             code->nativeInputQueue->dispatchEvent(event);
         }
     }
diff --git a/core/jni/android_view_InputQueue.cpp b/core/jni/android_view_InputQueue.cpp
index 6fb3cf7..226c797 100644
--- a/core/jni/android_view_InputQueue.cpp
+++ b/core/jni/android_view_InputQueue.cpp
@@ -326,12 +326,11 @@
     //       the input handler object itself for the same reason.
 
     int32_t inputEventType = inputEvent->getType();
-    int32_t inputEventNature = inputEvent->getNature();
 
     jobject inputEventObj;
     jmethodID dispatchMethodId;
     switch (inputEventType) {
-    case INPUT_EVENT_TYPE_KEY:
+    case AINPUT_EVENT_TYPE_KEY:
 #if DEBUG_DISPATCH_CYCLE
         LOGD("channel '%s' ~ Received key event.", connection->getInputChannelName());
 #endif
@@ -340,7 +339,7 @@
         dispatchMethodId = gInputQueueClassInfo.dispatchKeyEvent;
         break;
 
-    case INPUT_EVENT_TYPE_MOTION:
+    case AINPUT_EVENT_TYPE_MOTION:
 #if DEBUG_DISPATCH_CYCLE
         LOGD("channel '%s' ~ Received motion event.", connection->getInputChannelName());
 #endif
@@ -367,7 +366,7 @@
 #endif
     env->CallStaticVoidMethod(gInputQueueClassInfo.clazz,
             dispatchMethodId, inputHandlerObjLocal, inputEventObj,
-            jint(inputEventNature), jlong(finishedToken));
+            jlong(finishedToken));
 #if DEBUG_DISPATCH_CYCLE
     LOGD("Returned from input handler.");
 #endif
@@ -471,11 +470,11 @@
 
     GET_STATIC_METHOD_ID(gInputQueueClassInfo.dispatchKeyEvent, gInputQueueClassInfo.clazz,
             "dispatchKeyEvent",
-            "(Landroid/view/InputHandler;Landroid/view/KeyEvent;IJ)V");
+            "(Landroid/view/InputHandler;Landroid/view/KeyEvent;J)V");
 
     GET_STATIC_METHOD_ID(gInputQueueClassInfo.dispatchMotionEvent, gInputQueueClassInfo.clazz,
             "dispatchMotionEvent",
-            "(Landroid/view/InputHandler;Landroid/view/MotionEvent;IJ)V");
+            "(Landroid/view/InputHandler;Landroid/view/MotionEvent;J)V");
     return 0;
 }
 
diff --git a/core/jni/android_view_KeyEvent.cpp b/core/jni/android_view_KeyEvent.cpp
index 8f648f4..7e7583c 100644
--- a/core/jni/android_view_KeyEvent.cpp
+++ b/core/jni/android_view_KeyEvent.cpp
@@ -32,12 +32,13 @@
 
     jmethodID ctor;
 
+    jfieldID mDeviceId;
+    jfieldID mSource;
     jfieldID mMetaState;
     jfieldID mAction;
     jfieldID mKeyCode;
     jfieldID mScanCode;
     jfieldID mRepeatCount;
-    jfieldID mDeviceId;
     jfieldID mFlags;
     jfieldID mDownTime;
     jfieldID mEventTime;
@@ -56,22 +57,24 @@
             event->getMetaState(),
             event->getDeviceId(),
             event->getScanCode(),
-            event->getFlags());
+            event->getFlags(),
+            event->getSource());
 }
 
-void android_view_KeyEvent_toNative(JNIEnv* env, jobject eventObj, int32_t nature,
+void android_view_KeyEvent_toNative(JNIEnv* env, jobject eventObj,
         KeyEvent* event) {
+    jint deviceId = env->GetIntField(eventObj, gKeyEventClassInfo.mDeviceId);
+    jint source = env->GetIntField(eventObj, gKeyEventClassInfo.mSource);
     jint metaState = env->GetIntField(eventObj, gKeyEventClassInfo.mMetaState);
     jint action = env->GetIntField(eventObj, gKeyEventClassInfo.mAction);
     jint keyCode = env->GetIntField(eventObj, gKeyEventClassInfo.mKeyCode);
     jint scanCode = env->GetIntField(eventObj, gKeyEventClassInfo.mScanCode);
     jint repeatCount = env->GetIntField(eventObj, gKeyEventClassInfo.mRepeatCount);
-    jint deviceId = env->GetIntField(eventObj, gKeyEventClassInfo.mDeviceId);
     jint flags = env->GetIntField(eventObj, gKeyEventClassInfo.mFlags);
     jlong downTime = env->GetLongField(eventObj, gKeyEventClassInfo.mDownTime);
     jlong eventTime = env->GetLongField(eventObj, gKeyEventClassInfo.mEventTime);
 
-    event->initialize(deviceId, nature, action, flags, keyCode, scanCode, metaState, repeatCount,
+    event->initialize(deviceId, source, action, flags, keyCode, scanCode, metaState, repeatCount,
             milliseconds_to_nanoseconds(downTime),
             milliseconds_to_nanoseconds(eventTime));
 }
@@ -91,8 +94,6 @@
     { "native_hasDefaultAction", "(I)Z", (void*)native_hasDefaultAction },
 };
 
-static const char* const kKeyEventPathName = "android/view/KeyEvent";
-
 #define FIND_CLASS(var, className) \
         var = env->FindClass(className); \
         LOG_FATAL_IF(! var, "Unable to find class " className); \
@@ -107,11 +108,15 @@
         LOG_FATAL_IF(! var, "Unable to find field " fieldName);
 
 int register_android_view_KeyEvent(JNIEnv* env) {
-    FIND_CLASS(gKeyEventClassInfo.clazz, kKeyEventPathName);
+    FIND_CLASS(gKeyEventClassInfo.clazz, "android/view/KeyEvent");
         
     GET_METHOD_ID(gKeyEventClassInfo.ctor, gKeyEventClassInfo.clazz,
-            "<init>", "(JJIIIIIII)V");
+            "<init>", "(JJIIIIIIII)V");
 
+    GET_FIELD_ID(gKeyEventClassInfo.mDeviceId, gKeyEventClassInfo.clazz,
+            "mDeviceId", "I");
+    GET_FIELD_ID(gKeyEventClassInfo.mSource, gKeyEventClassInfo.clazz,
+            "mSource", "I");
     GET_FIELD_ID(gKeyEventClassInfo.mMetaState, gKeyEventClassInfo.clazz,
             "mMetaState", "I");
     GET_FIELD_ID(gKeyEventClassInfo.mAction, gKeyEventClassInfo.clazz,
@@ -122,8 +127,6 @@
             "mScanCode", "I");
     GET_FIELD_ID(gKeyEventClassInfo.mRepeatCount, gKeyEventClassInfo.clazz,
             "mRepeatCount", "I");
-    GET_FIELD_ID(gKeyEventClassInfo.mDeviceId, gKeyEventClassInfo.clazz,
-            "mDeviceId", "I");
     GET_FIELD_ID(gKeyEventClassInfo.mFlags, gKeyEventClassInfo.clazz,
             "mFlags", "I");
     GET_FIELD_ID(gKeyEventClassInfo.mDownTime, gKeyEventClassInfo.clazz,
@@ -134,8 +137,7 @@
             "mCharacters", "Ljava/lang/String;");
 
     return AndroidRuntime::registerNativeMethods(
-        env, kKeyEventPathName,
-        g_methods, NELEM(g_methods));
+        env, "android/view/KeyEvent", g_methods, NELEM(g_methods));
 }
 
 } // namespace android
diff --git a/core/jni/android_view_KeyEvent.h b/core/jni/android_view_KeyEvent.h
index 3c71b1a..0bd410c 100644
--- a/core/jni/android_view_KeyEvent.h
+++ b/core/jni/android_view_KeyEvent.h
@@ -27,7 +27,7 @@
 extern jobject android_view_KeyEvent_fromNative(JNIEnv* env, const KeyEvent* event);
 
 /* Copies the contents of a DVM KeyEvent object to a native KeyEvent instance. */
-extern void android_view_KeyEvent_toNative(JNIEnv* env, jobject eventObj, int32_t nature,
+extern void android_view_KeyEvent_toNative(JNIEnv* env, jobject eventObj,
         KeyEvent* event);
 
 } // namespace android
diff --git a/core/jni/android_view_MotionEvent.cpp b/core/jni/android_view_MotionEvent.cpp
index 78137e2..fe247e8 100644
--- a/core/jni/android_view_MotionEvent.cpp
+++ b/core/jni/android_view_MotionEvent.cpp
@@ -24,7 +24,7 @@
 #include "android_view_MotionEvent.h"
 
 // Number of float items per entry in a DVM sample data array
-#define NUM_SAMPLE_DATA 4
+#define NUM_SAMPLE_DATA 9
 
 namespace android {
 
@@ -36,13 +36,14 @@
     jmethodID obtain;
     jmethodID recycle;
 
+    jfieldID mDeviceId;
+    jfieldID mSource;
     jfieldID mDownTimeNano;
     jfieldID mAction;
     jfieldID mXOffset;
     jfieldID mYOffset;
     jfieldID mXPrecision;
     jfieldID mYPrecision;
-    jfieldID mDeviceId;
     jfieldID mEdgeFlags;
     jfieldID mMetaState;
     jfieldID mNumPointers;
@@ -70,6 +71,10 @@
         return NULL;
     }
 
+    env->SetIntField(eventObj, gMotionEventClassInfo.mDeviceId,
+            event->getDeviceId());
+    env->SetIntField(eventObj, gMotionEventClassInfo.mSource,
+            event->getSource());
     env->SetLongField(eventObj, gMotionEventClassInfo.mDownTimeNano,
             event->getDownTime());
     env->SetIntField(eventObj, gMotionEventClassInfo.mAction,
@@ -82,8 +87,6 @@
             event->getXPrecision());
     env->SetFloatField(eventObj, gMotionEventClassInfo.mYPrecision,
             event->getYPrecision());
-    env->SetIntField(eventObj, gMotionEventClassInfo.mDeviceId,
-            event->getDeviceId());
     env->SetIntField(eventObj, gMotionEventClassInfo.mEdgeFlags,
             event->getEdgeFlags());
     env->SetIntField(eventObj, gMotionEventClassInfo.mMetaState,
@@ -129,6 +132,11 @@
         *(destDataSamples++) = srcSamplePointerCoords->y;
         *(destDataSamples++) = srcSamplePointerCoords->pressure;
         *(destDataSamples++) = srcSamplePointerCoords->size;
+        *(destDataSamples++) = srcSamplePointerCoords->touchMajor;
+        *(destDataSamples++) = srcSamplePointerCoords->touchMinor;
+        *(destDataSamples++) = srcSamplePointerCoords->toolMajor;
+        *(destDataSamples++) = srcSamplePointerCoords->toolMinor;
+        *(destDataSamples++) = srcSamplePointerCoords->orientation;
         srcSamplePointerCoords += 1;
     }
 
@@ -142,15 +150,16 @@
     return eventObj;
 }
 
-void android_view_MotionEvent_toNative(JNIEnv* env, jobject eventObj, int32_t nature,
+void android_view_MotionEvent_toNative(JNIEnv* env, jobject eventObj,
         MotionEvent* event) {
+    jint deviceId = env->GetIntField(eventObj, gMotionEventClassInfo.mDeviceId);
+    jint source = env->GetIntField(eventObj, gMotionEventClassInfo.mSource);
     jlong downTimeNano = env->GetLongField(eventObj, gMotionEventClassInfo.mDownTimeNano);
     jint action = env->GetIntField(eventObj, gMotionEventClassInfo.mAction);
     jfloat xOffset = env->GetFloatField(eventObj, gMotionEventClassInfo.mXOffset);
     jfloat yOffset = env->GetFloatField(eventObj, gMotionEventClassInfo.mYOffset);
     jfloat xPrecision = env->GetFloatField(eventObj, gMotionEventClassInfo.mXPrecision);
     jfloat yPrecision = env->GetFloatField(eventObj, gMotionEventClassInfo.mYPrecision);
-    jint deviceId = env->GetIntField(eventObj, gMotionEventClassInfo.mDeviceId);
     jint edgeFlags = env->GetIntField(eventObj, gMotionEventClassInfo.mEdgeFlags);
     jint metaState = env->GetIntField(eventObj, gMotionEventClassInfo.mMetaState);
     jint numPointers = env->GetIntField(eventObj, gMotionEventClassInfo.mNumPointers);
@@ -180,9 +189,14 @@
         samplePointerCoords[j].y = *(srcDataSamples++);
         samplePointerCoords[j].pressure = *(srcDataSamples++);
         samplePointerCoords[j].size = *(srcDataSamples++);
+        samplePointerCoords[j].touchMajor = *(srcDataSamples++);
+        samplePointerCoords[j].touchMinor = *(srcDataSamples++);
+        samplePointerCoords[j].toolMajor = *(srcDataSamples++);
+        samplePointerCoords[j].toolMinor = *(srcDataSamples++);
+        samplePointerCoords[j].orientation = *(srcDataSamples++);
     }
 
-    event->initialize(deviceId, nature, action, edgeFlags, metaState,
+    event->initialize(deviceId, source, action, edgeFlags, metaState,
             xOffset, yOffset, xPrecision, yPrecision, downTimeNano, sampleEventTime,
             numPointers, pointerIdentifiers, samplePointerCoords);
 
@@ -193,6 +207,11 @@
             samplePointerCoords[j].y = *(srcDataSamples++);
             samplePointerCoords[j].pressure = *(srcDataSamples++);
             samplePointerCoords[j].size = *(srcDataSamples++);
+            samplePointerCoords[j].touchMajor = *(srcDataSamples++);
+            samplePointerCoords[j].touchMinor = *(srcDataSamples++);
+            samplePointerCoords[j].toolMajor = *(srcDataSamples++);
+            samplePointerCoords[j].toolMinor = *(srcDataSamples++);
+            samplePointerCoords[j].orientation = *(srcDataSamples++);
         }
         event->addSample(sampleEventTime, samplePointerCoords);
     }
@@ -242,6 +261,10 @@
     GET_METHOD_ID(gMotionEventClassInfo.recycle, gMotionEventClassInfo.clazz,
             "recycle", "()V");
 
+    GET_FIELD_ID(gMotionEventClassInfo.mDeviceId, gMotionEventClassInfo.clazz,
+            "mDeviceId", "I");
+    GET_FIELD_ID(gMotionEventClassInfo.mSource, gMotionEventClassInfo.clazz,
+            "mSource", "I");
     GET_FIELD_ID(gMotionEventClassInfo.mDownTimeNano, gMotionEventClassInfo.clazz,
             "mDownTimeNano", "J");
     GET_FIELD_ID(gMotionEventClassInfo.mAction, gMotionEventClassInfo.clazz,
@@ -254,8 +277,6 @@
             "mXPrecision", "F");
     GET_FIELD_ID(gMotionEventClassInfo.mYPrecision, gMotionEventClassInfo.clazz,
             "mYPrecision", "F");
-    GET_FIELD_ID(gMotionEventClassInfo.mDeviceId, gMotionEventClassInfo.clazz,
-            "mDeviceId", "I");
     GET_FIELD_ID(gMotionEventClassInfo.mEdgeFlags, gMotionEventClassInfo.clazz,
             "mEdgeFlags", "I");
     GET_FIELD_ID(gMotionEventClassInfo.mMetaState, gMotionEventClassInfo.clazz,
diff --git a/core/jni/android_view_MotionEvent.h b/core/jni/android_view_MotionEvent.h
index 03ee32f..86e4bde 100644
--- a/core/jni/android_view_MotionEvent.h
+++ b/core/jni/android_view_MotionEvent.h
@@ -27,7 +27,7 @@
 extern jobject android_view_MotionEvent_fromNative(JNIEnv* env, const MotionEvent* event);
 
 /* Copies the contents of a DVM MotionEvent object to a native MotionEvent instance. */
-extern void android_view_MotionEvent_toNative(JNIEnv* env, jobject eventObj, int32_t nature,
+extern void android_view_MotionEvent_toNative(JNIEnv* env, jobject eventObj,
         MotionEvent* event);
 
 /* Recycles a DVM MotionEvent object. */
diff --git a/include/ui/EventHub.h b/include/ui/EventHub.h
index d322a34..5be17d3 100644
--- a/include/ui/EventHub.h
+++ b/include/ui/EventHub.h
@@ -60,6 +60,32 @@
 class KeyLayoutMap;
 
 /*
+ * Input device classes.
+ */
+enum {
+    /* The input device is a keyboard. */
+    INPUT_DEVICE_CLASS_KEYBOARD      = 0x00000001,
+
+    /* The input device is an alpha-numeric keyboard (not just a dial pad). */
+    INPUT_DEVICE_CLASS_ALPHAKEY      = 0x00000002,
+
+    /* The input device is a touchscreen (either single-touch or multi-touch). */
+    INPUT_DEVICE_CLASS_TOUCHSCREEN   = 0x00000004,
+
+    /* The input device is a trackball. */
+    INPUT_DEVICE_CLASS_TRACKBALL     = 0x00000008,
+
+    /* The input device is a multi-touch touchscreen. */
+    INPUT_DEVICE_CLASS_TOUCHSCREEN_MT= 0x00000010,
+
+    /* The input device is a directional pad. */
+    INPUT_DEVICE_CLASS_DPAD          = 0x00000020,
+
+    /* The input device is a gamepad (implies keyboard). */
+    INPUT_DEVICE_CLASS_GAMEPAD       = 0x00000040
+};
+
+/*
  * Grand Central Station for events.
  *
  * The event hub aggregates input events received across all known input
diff --git a/include/ui/Input.h b/include/ui/Input.h
index a7d23d4..f069888 100644
--- a/include/ui/Input.h
+++ b/include/ui/Input.h
@@ -32,7 +32,7 @@
     /*
      * Private control to determine when an app is tracking a key sequence.
      */
-    KEY_EVENT_FLAG_START_TRACKING = 0x40000000
+    AKEY_EVENT_FLAG_START_TRACKING = 0x40000000
 };
 
 /*
@@ -130,6 +130,11 @@
     float y;
     float pressure;
     float size;
+    float touchMajor;
+    float touchMinor;
+    float toolMajor;
+    float toolMinor;
+    float orientation;
 };
 
 /*
@@ -143,14 +148,14 @@
 
     inline int32_t getDeviceId() const { return mDeviceId; }
 
-    inline int32_t getNature() const { return mNature; }
+    inline int32_t getSource() const { return mSource; }
     
 protected:
-    void initialize(int32_t deviceId, int32_t nature);
+    void initialize(int32_t deviceId, int32_t source);
 
 private:
     int32_t mDeviceId;
-    int32_t mNature;
+    int32_t mSource;
 };
 
 /*
@@ -160,7 +165,7 @@
 public:
     virtual ~KeyEvent() { }
 
-    virtual int32_t getType() const { return INPUT_EVENT_TYPE_KEY; }
+    virtual int32_t getType() const { return AINPUT_EVENT_TYPE_KEY; }
 
     inline int32_t getAction() const { return mAction; }
 
@@ -188,7 +193,7 @@
     
     void initialize(
             int32_t deviceId,
-            int32_t nature,
+            int32_t source,
             int32_t action,
             int32_t flags,
             int32_t keyCode,
@@ -216,7 +221,7 @@
 public:
     virtual ~MotionEvent() { }
 
-    virtual int32_t getType() const { return INPUT_EVENT_TYPE_MOTION; }
+    virtual int32_t getType() const { return AINPUT_EVENT_TYPE_MOTION; }
 
     inline int32_t getAction() const { return mAction; }
 
@@ -264,6 +269,26 @@
         return getCurrentPointerCoords(pointerIndex).size;
     }
 
+    inline float getTouchMajor(size_t pointerIndex) const {
+        return getCurrentPointerCoords(pointerIndex).touchMajor;
+    }
+
+    inline float getTouchMinor(size_t pointerIndex) const {
+        return getCurrentPointerCoords(pointerIndex).touchMinor;
+    }
+
+    inline float getToolMajor(size_t pointerIndex) const {
+        return getCurrentPointerCoords(pointerIndex).toolMajor;
+    }
+
+    inline float getToolMinor(size_t pointerIndex) const {
+        return getCurrentPointerCoords(pointerIndex).toolMinor;
+    }
+
+    inline float getOrientation(size_t pointerIndex) const {
+        return getCurrentPointerCoords(pointerIndex).orientation;
+    }
+
     inline size_t getHistorySize() const { return mSampleEventTimes.size() - 1; }
 
     inline nsecs_t getHistoricalEventTime(size_t historicalIndex) const {
@@ -294,9 +319,29 @@
         return getHistoricalPointerCoords(pointerIndex, historicalIndex).size;
     }
 
+    inline float getHistoricalTouchMajor(size_t pointerIndex, size_t historicalIndex) const {
+        return getHistoricalPointerCoords(pointerIndex, historicalIndex).touchMajor;
+    }
+
+    inline float getHistoricalTouchMinor(size_t pointerIndex, size_t historicalIndex) const {
+        return getHistoricalPointerCoords(pointerIndex, historicalIndex).touchMinor;
+    }
+
+    inline float getHistoricalToolMajor(size_t pointerIndex, size_t historicalIndex) const {
+        return getHistoricalPointerCoords(pointerIndex, historicalIndex).toolMajor;
+    }
+
+    inline float getHistoricalToolMinor(size_t pointerIndex, size_t historicalIndex) const {
+        return getHistoricalPointerCoords(pointerIndex, historicalIndex).toolMinor;
+    }
+
+    inline float getHistoricalOrientation(size_t pointerIndex, size_t historicalIndex) const {
+        return getHistoricalPointerCoords(pointerIndex, historicalIndex).orientation;
+    }
+
     void initialize(
             int32_t deviceId,
-            int32_t nature,
+            int32_t source,
             int32_t action,
             int32_t edgeFlags,
             int32_t metaState,
diff --git a/include/ui/InputDevice.h b/include/ui/InputDevice.h
index 4420600..3b9c70e 100644
--- a/include/ui/InputDevice.h
+++ b/include/ui/InputDevice.h
@@ -42,6 +42,7 @@
 extern int32_t updateMetaState(int32_t keyCode, bool down, int32_t oldMetaState);
 extern int32_t rotateKeyCode(int32_t keyCode, int32_t orientation);
 
+
 /*
  * An input device structure tracks the state of a single input device.
  *
@@ -168,8 +169,11 @@
                 FIELD_ABS_MT_POSITION_X = 1,
                 FIELD_ABS_MT_POSITION_Y = 2,
                 FIELD_ABS_MT_TOUCH_MAJOR = 4,
-                FIELD_ABS_MT_WIDTH_MAJOR = 8,
-                FIELD_ABS_MT_TRACKING_ID = 16
+                FIELD_ABS_MT_TOUCH_MINOR = 8,
+                FIELD_ABS_MT_WIDTH_MAJOR = 16,
+                FIELD_ABS_MT_WIDTH_MINOR = 32,
+                FIELD_ABS_MT_ORIENTATION = 64,
+                FIELD_ABS_MT_TRACKING_ID = 128
             };
 
             uint32_t pointerCount;
@@ -179,7 +183,10 @@
                 int32_t absMTPositionX;
                 int32_t absMTPositionY;
                 int32_t absMTTouchMajor;
+                int32_t absMTTouchMinor;
                 int32_t absMTWidthMajor;
+                int32_t absMTWidthMinor;
+                int32_t absMTOrientation;
                 int32_t absMTTrackingId;
 
                 inline void clear() {
@@ -206,6 +213,11 @@
         int32_t y;
         int32_t pressure;
         int32_t size;
+        int32_t touchMajor;
+        int32_t touchMinor;
+        int32_t toolMajor;
+        int32_t toolMinor;
+        int32_t orientation;
     };
 
     struct TouchData {
@@ -236,6 +248,7 @@
             AbsoluteAxisInfo yAxis;
             AbsoluteAxisInfo pressureAxis;
             AbsoluteAxisInfo sizeAxis;
+            AbsoluteAxisInfo orientationAxis;
         } parameters;
 
         // The touch data of the current sample being processed.
@@ -290,6 +303,8 @@
 
             int32_t sizeOrigin;
             float sizeScale;
+
+            float orientationScale;
         } precalculated;
 
         void reset();
diff --git a/include/ui/InputDispatcher.h b/include/ui/InputDispatcher.h
index eb8f820..674852a 100644
--- a/include/ui/InputDispatcher.h
+++ b/include/ui/InputDispatcher.h
@@ -167,10 +167,10 @@
      */
     virtual void notifyConfigurationChanged(nsecs_t eventTime) = 0;
     virtual void notifyAppSwitchComing(nsecs_t eventTime) = 0;
-    virtual void notifyKey(nsecs_t eventTime, int32_t deviceId, int32_t nature,
+    virtual void notifyKey(nsecs_t eventTime, int32_t deviceId, int32_t source,
             uint32_t policyFlags, int32_t action, int32_t flags, int32_t keyCode,
             int32_t scanCode, int32_t metaState, nsecs_t downTime) = 0;
-    virtual void notifyMotion(nsecs_t eventTime, int32_t deviceId, int32_t nature,
+    virtual void notifyMotion(nsecs_t eventTime, int32_t deviceId, int32_t source,
             uint32_t policyFlags, int32_t action, int32_t metaState, int32_t edgeFlags,
             uint32_t pointerCount, const int32_t* pointerIds, const PointerCoords* pointerCoords,
             float xPrecision, float yPrecision, nsecs_t downTime) = 0;
@@ -232,10 +232,10 @@
 
     virtual void notifyConfigurationChanged(nsecs_t eventTime);
     virtual void notifyAppSwitchComing(nsecs_t eventTime);
-    virtual void notifyKey(nsecs_t eventTime, int32_t deviceId, int32_t nature,
+    virtual void notifyKey(nsecs_t eventTime, int32_t deviceId, int32_t source,
             uint32_t policyFlags, int32_t action, int32_t flags, int32_t keyCode,
             int32_t scanCode, int32_t metaState, nsecs_t downTime);
-    virtual void notifyMotion(nsecs_t eventTime, int32_t deviceId, int32_t nature,
+    virtual void notifyMotion(nsecs_t eventTime, int32_t deviceId, int32_t source,
             uint32_t policyFlags, int32_t action, int32_t metaState, int32_t edgeFlags,
             uint32_t pointerCount, const int32_t* pointerIds, const PointerCoords* pointerCoords,
             float xPrecision, float yPrecision, nsecs_t downTime);
@@ -281,7 +281,7 @@
 
     struct KeyEntry : EventEntry {
         int32_t deviceId;
-        int32_t nature;
+        int32_t source;
         uint32_t policyFlags;
         int32_t action;
         int32_t flags;
@@ -301,7 +301,7 @@
 
     struct MotionEntry : EventEntry {
         int32_t deviceId;
-        int32_t nature;
+        int32_t source;
         uint32_t policyFlags;
         int32_t action;
         int32_t metaState;
@@ -424,11 +424,11 @@
 
         ConfigurationChangedEntry* obtainConfigurationChangedEntry(nsecs_t eventTime);
         KeyEntry* obtainKeyEntry(nsecs_t eventTime,
-                int32_t deviceId, int32_t nature, uint32_t policyFlags, int32_t action,
+                int32_t deviceId, int32_t source, uint32_t policyFlags, int32_t action,
                 int32_t flags, int32_t keyCode, int32_t scanCode, int32_t metaState,
                 int32_t repeatCount, nsecs_t downTime);
         MotionEntry* obtainMotionEntry(nsecs_t eventTime,
-                int32_t deviceId, int32_t nature, uint32_t policyFlags, int32_t action,
+                int32_t deviceId, int32_t source, uint32_t policyFlags, int32_t action,
                 int32_t metaState, int32_t edgeFlags, float xPrecision, float yPrecision,
                 nsecs_t downTime, uint32_t pointerCount,
                 const int32_t* pointerIds, const PointerCoords* pointerCoords);
diff --git a/include/ui/InputTransport.h b/include/ui/InputTransport.h
index 226d1d5..31ec701 100644
--- a/include/ui/InputTransport.h
+++ b/include/ui/InputTransport.h
@@ -119,7 +119,7 @@
     };
 
     int32_t deviceId;
-    int32_t nature;
+    int32_t source;
 
     union {
         struct {
@@ -198,7 +198,7 @@
      */
     status_t publishKeyEvent(
             int32_t deviceId,
-            int32_t nature,
+            int32_t source,
             int32_t action,
             int32_t flags,
             int32_t keyCode,
@@ -216,7 +216,7 @@
      */
     status_t publishMotionEvent(
             int32_t deviceId,
-            int32_t nature,
+            int32_t source,
             int32_t action,
             int32_t edgeFlags,
             int32_t metaState,
@@ -233,7 +233,7 @@
     /* Appends a motion sample to a motion event unless already consumed.
      *
      * Returns OK on success.
-     * Returns INVALID_OPERATION if the current event is not a MOTION_EVENT_ACTION_MOVE event.
+     * Returns INVALID_OPERATION if the current event is not a AMOTION_EVENT_ACTION_MOVE event.
      * Returns FAILED_TRANSACTION if the current event has already been consumed.
      * Returns NO_MEMORY if the buffer is full and no additional samples can be added.
      */
@@ -272,7 +272,7 @@
     status_t publishInputEvent(
             int32_t type,
             int32_t deviceId,
-            int32_t nature);
+            int32_t source);
 };
 
 /*
diff --git a/libs/ui/EventHub.cpp b/libs/ui/EventHub.cpp
index 768b04e..33dd3732 100644
--- a/libs/ui/EventHub.cpp
+++ b/libs/ui/EventHub.cpp
@@ -168,12 +168,12 @@
                 device_t* device = mDevicesById[i].device;
                 if (device != NULL && (device->classes & deviceClasses) != 0) {
                     int32_t result = getScanCodeStateLocked(device, scanCode);
-                    if (result >= KEY_STATE_DOWN) {
+                    if (result >= AKEY_STATE_DOWN) {
                         return result;
                     }
                 }
             }
-            return KEY_STATE_UP;
+            return AKEY_STATE_UP;
         } else {
             device_t* device = getDevice(deviceId);
             if (device != NULL) {
@@ -181,7 +181,7 @@
             }
         }
     }
-    return KEY_STATE_UNKNOWN;
+    return AKEY_STATE_UNKNOWN;
 }
 
 int32_t EventHub::getScanCodeStateLocked(device_t* device, int32_t scanCode) const {
@@ -189,9 +189,9 @@
     memset(key_bitmask, 0, sizeof(key_bitmask));
     if (ioctl(mFDs[id_to_index(device->id)].fd,
                EVIOCGKEY(sizeof(key_bitmask)), key_bitmask) >= 0) {
-        return test_bit(scanCode, key_bitmask) ? KEY_STATE_DOWN : KEY_STATE_UP;
+        return test_bit(scanCode, key_bitmask) ? AKEY_STATE_DOWN : AKEY_STATE_UP;
     }
-    return KEY_STATE_UNKNOWN;
+    return AKEY_STATE_UNKNOWN;
 }
 
 int32_t EventHub::getKeyCodeState(int32_t deviceId, int32_t deviceClasses,
@@ -202,19 +202,19 @@
             device_t* device = mDevicesById[i].device;
             if (device != NULL && (device->classes & deviceClasses) != 0) {
                 int32_t result = getKeyCodeStateLocked(device, keyCode);
-                if (result >= KEY_STATE_DOWN) {
+                if (result >= AKEY_STATE_DOWN) {
                     return result;
                 }
             }
         }
-        return KEY_STATE_UP;
+        return AKEY_STATE_UP;
     } else {
         device_t* device = getDevice(deviceId);
         if (device != NULL) {
             return getKeyCodeStateLocked(device, keyCode);
         }
     }
-    return KEY_STATE_UNKNOWN;
+    return AKEY_STATE_UNKNOWN;
 }
 
 int32_t EventHub::getKeyCodeStateLocked(device_t* device, int32_t keyCode) const {
@@ -235,12 +235,12 @@
             int32_t sc = scanCodes.itemAt(i);
             //LOGI("Code %d: down=%d", sc, test_bit(sc, key_bitmask));
             if (sc >= 0 && sc <= KEY_MAX && test_bit(sc, key_bitmask)) {
-                return KEY_STATE_DOWN;
+                return AKEY_STATE_DOWN;
             }
         }
-        return KEY_STATE_UP;
+        return AKEY_STATE_UP;
     }
-    return KEY_STATE_UNKNOWN;
+    return AKEY_STATE_UNKNOWN;
 }
 
 int32_t EventHub::getSwitchState(int32_t deviceId, int32_t deviceClasses, int32_t sw) const {
@@ -251,19 +251,19 @@
         if (deviceId == -1) {
             deviceId = mSwitches[sw];
             if (deviceId == 0) {
-                return KEY_STATE_UNKNOWN;
+                return AKEY_STATE_UNKNOWN;
             }
         }
 
         device_t* device = getDevice(deviceId);
         if (device == NULL) {
-            return KEY_STATE_UNKNOWN;
+            return AKEY_STATE_UNKNOWN;
         }
 
         return getSwitchStateLocked(device, sw);
     }
 #endif
-    return KEY_STATE_UNKNOWN;
+    return AKEY_STATE_UNKNOWN;
 }
 
 int32_t EventHub::getSwitchStateLocked(device_t* device, int32_t sw) const {
@@ -271,9 +271,9 @@
     memset(sw_bitmask, 0, sizeof(sw_bitmask));
     if (ioctl(mFDs[id_to_index(device->id)].fd,
                EVIOCGSW(sizeof(sw_bitmask)), sw_bitmask) >= 0) {
-        return test_bit(sw, sw_bitmask) ? KEY_STATE_DOWN : KEY_STATE_UP;
+        return test_bit(sw, sw_bitmask) ? AKEY_STATE_DOWN : AKEY_STATE_UP;
     }
-    return KEY_STATE_UNKNOWN;
+    return AKEY_STATE_UNKNOWN;
 }
 
 status_t EventHub::scancodeToKeycode(int32_t deviceId, int scancode,
diff --git a/libs/ui/Input.cpp b/libs/ui/Input.cpp
index 1f19c2c..e5f014f 100644
--- a/libs/ui/Input.cpp
+++ b/libs/ui/Input.cpp
@@ -13,9 +13,9 @@
 
 // class InputEvent
 
-void InputEvent::initialize(int32_t deviceId, int32_t nature) {
+void InputEvent::initialize(int32_t deviceId, int32_t source) {
     mDeviceId = deviceId;
-    mNature = nature;
+    mSource = source;
 }
 
 // class KeyEvent
@@ -86,7 +86,7 @@
 
 void KeyEvent::initialize(
         int32_t deviceId,
-        int32_t nature,
+        int32_t source,
         int32_t action,
         int32_t flags,
         int32_t keyCode,
@@ -95,7 +95,7 @@
         int32_t repeatCount,
         nsecs_t downTime,
         nsecs_t eventTime) {
-    InputEvent::initialize(deviceId, nature);
+    InputEvent::initialize(deviceId, source);
     mAction = action;
     mFlags = flags;
     mKeyCode = keyCode;
@@ -110,7 +110,7 @@
 
 void MotionEvent::initialize(
         int32_t deviceId,
-        int32_t nature,
+        int32_t source,
         int32_t action,
         int32_t edgeFlags,
         int32_t metaState,
@@ -123,7 +123,7 @@
         size_t pointerCount,
         const int32_t* pointerIds,
         const PointerCoords* pointerCoords) {
-    InputEvent::initialize(deviceId, nature);
+    InputEvent::initialize(deviceId, source);
     mAction = action;
     mEdgeFlags = edgeFlags;
     mMetaState = metaState;
diff --git a/libs/ui/InputDevice.cpp b/libs/ui/InputDevice.cpp
index 6014017..b2a4d6c 100644
--- a/libs/ui/InputDevice.cpp
+++ b/libs/ui/InputDevice.cpp
@@ -108,7 +108,7 @@
 // --- InputDevice::KeyboardState ---
 
 void InputDevice::KeyboardState::reset() {
-    current.metaState = META_NONE;
+    current.metaState = AMETA_NONE;
     current.downTime = 0;
 }
 
diff --git a/libs/ui/InputDispatcher.cpp b/libs/ui/InputDispatcher.cpp
index c4ffce1..a438c69 100644
--- a/libs/ui/InputDispatcher.cpp
+++ b/libs/ui/InputDispatcher.cpp
@@ -245,14 +245,14 @@
 void InputDispatcher::processKeyLockedInterruptible(
         nsecs_t currentTime, KeyEntry* entry, nsecs_t keyRepeatTimeout) {
 #if DEBUG_OUTBOUND_EVENT_DETAILS
-    LOGD("processKey - eventTime=%lld, deviceId=0x%x, nature=0x%x, policyFlags=0x%x, action=0x%x, "
+    LOGD("processKey - eventTime=%lld, deviceId=0x%x, source=0x%x, policyFlags=0x%x, action=0x%x, "
             "flags=0x%x, keyCode=0x%x, scanCode=0x%x, metaState=0x%x, downTime=%lld",
-            entry->eventTime, entry->deviceId, entry->nature, entry->policyFlags, entry->action,
+            entry->eventTime, entry->deviceId, entry->source, entry->policyFlags, entry->action,
             entry->flags, entry->keyCode, entry->scanCode, entry->metaState,
             entry->downTime);
 #endif
 
-    if (entry->action == KEY_EVENT_ACTION_DOWN && ! entry->isInjected()) {
+    if (entry->action == AKEY_EVENT_ACTION_DOWN && ! entry->isInjected()) {
         if (mKeyRepeatState.lastKeyEntry
                 && mKeyRepeatState.lastKeyEntry->keyCode == entry->keyCode) {
             // We have seen two identical key downs in a row which indicates that the device
@@ -287,7 +287,7 @@
         if (queuedEntry->type == EventEntry::TYPE_KEY) {
             KeyEntry* queuedKeyEntry = static_cast<KeyEntry*>(queuedEntry);
             if (queuedKeyEntry->deviceId == entry->deviceId
-                    && entry->action == KEY_EVENT_ACTION_UP) {
+                    && entry->action == AKEY_EVENT_ACTION_UP) {
                 resetKeyRepeatLocked();
                 return;
             }
@@ -303,7 +303,7 @@
         entry->repeatCount += 1;
     } else {
         KeyEntry* newEntry = mAllocator.obtainKeyEntry(currentTime,
-                entry->deviceId, entry->nature, policyFlags,
+                entry->deviceId, entry->source, policyFlags,
                 entry->action, entry->flags, entry->keyCode, entry->scanCode,
                 entry->metaState, entry->repeatCount + 1, entry->downTime);
 
@@ -314,16 +314,16 @@
     }
 
     if (entry->repeatCount == 1) {
-        entry->flags |= KEY_EVENT_FLAG_LONG_PRESS;
+        entry->flags |= AKEY_EVENT_FLAG_LONG_PRESS;
     }
 
     mKeyRepeatState.nextRepeatTime = currentTime + keyRepeatTimeout;
 
 #if DEBUG_OUTBOUND_EVENT_DETAILS
-    LOGD("processKeyRepeat - eventTime=%lld, deviceId=0x%x, nature=0x%x, policyFlags=0x%x, "
+    LOGD("processKeyRepeat - eventTime=%lld, deviceId=0x%x, source=0x%x, policyFlags=0x%x, "
             "action=0x%x, flags=0x%x, keyCode=0x%x, scanCode=0x%x, metaState=0x%x, "
             "repeatCount=%d, downTime=%lld",
-            entry->eventTime, entry->deviceId, entry->nature, entry->policyFlags,
+            entry->eventTime, entry->deviceId, entry->source, entry->policyFlags,
             entry->action, entry->flags, entry->keyCode, entry->scanCode, entry->metaState,
             entry->repeatCount, entry->downTime);
 #endif
@@ -334,9 +334,9 @@
 void InputDispatcher::processMotionLockedInterruptible(
         nsecs_t currentTime, MotionEntry* entry) {
 #if DEBUG_OUTBOUND_EVENT_DETAILS
-    LOGD("processMotion - eventTime=%lld, deviceId=0x%x, nature=0x%x, policyFlags=0x%x, action=0x%x, "
+    LOGD("processMotion - eventTime=%lld, deviceId=0x%x, source=0x%x, policyFlags=0x%x, action=0x%x, "
             "metaState=0x%x, edgeFlags=0x%x, xPrecision=%f, yPrecision=%f, downTime=%lld",
-            entry->eventTime, entry->deviceId, entry->nature, entry->policyFlags, entry->action,
+            entry->eventTime, entry->deviceId, entry->source, entry->policyFlags, entry->action,
             entry->metaState, entry->edgeFlags, entry->xPrecision, entry->yPrecision,
             entry->downTime);
 
@@ -357,7 +357,7 @@
 
     // Keep in mind that due to batching, it is possible for the number of samples actually
     // dispatched to change before the application finally consumed them.
-    if (entry->action == MOTION_EVENT_ACTION_MOVE) {
+    if (entry->action == AMOTION_EVENT_ACTION_MOVE) {
         LOGD("  ... Total movement samples currently batched %d ...", sampleCount);
     }
 #endif
@@ -375,7 +375,7 @@
     mCurrentInputTargetsValid = false;
     mLock.unlock();
 
-    mReusableKeyEvent.initialize(entry->deviceId, entry->nature, entry->action, entry->flags,
+    mReusableKeyEvent.initialize(entry->deviceId, entry->source, entry->action, entry->flags,
             entry->keyCode, entry->scanCode, entry->metaState, entry->repeatCount,
             entry->downTime, entry->eventTime);
 
@@ -404,7 +404,7 @@
     mCurrentInputTargetsValid = false;
     mLock.unlock();
 
-    mReusableMotionEvent.initialize(entry->deviceId, entry->nature, entry->action,
+    mReusableMotionEvent.initialize(entry->deviceId, entry->source, entry->action,
             entry->edgeFlags, entry->metaState,
             0, 0, entry->xPrecision, entry->yPrecision,
             entry->downTime, entry->eventTime, entry->pointerCount, entry->pointerIds,
@@ -611,11 +611,11 @@
         int32_t action = keyEntry->action;
         int32_t flags = keyEntry->flags;
         if (dispatchEntry->targetFlags & InputTarget::FLAG_CANCEL) {
-            flags |= KEY_EVENT_FLAG_CANCELED;
+            flags |= AKEY_EVENT_FLAG_CANCELED;
         }
 
         // Publish the key event.
-        status = connection->inputPublisher.publishKeyEvent(keyEntry->deviceId, keyEntry->nature,
+        status = connection->inputPublisher.publishKeyEvent(keyEntry->deviceId, keyEntry->source,
                 action, flags, keyEntry->keyCode, keyEntry->scanCode,
                 keyEntry->metaState, keyEntry->repeatCount, keyEntry->downTime,
                 keyEntry->eventTime);
@@ -635,10 +635,10 @@
         // Apply target flags.
         int32_t action = motionEntry->action;
         if (dispatchEntry->targetFlags & InputTarget::FLAG_OUTSIDE) {
-            action = MOTION_EVENT_ACTION_OUTSIDE;
+            action = AMOTION_EVENT_ACTION_OUTSIDE;
         }
         if (dispatchEntry->targetFlags & InputTarget::FLAG_CANCEL) {
-            action = MOTION_EVENT_ACTION_CANCEL;
+            action = AMOTION_EVENT_ACTION_CANCEL;
         }
 
         // If headMotionSample is non-NULL, then it points to the first new sample that we
@@ -652,7 +652,7 @@
 
         // Publish the motion event and the first motion sample.
         status = connection->inputPublisher.publishMotionEvent(motionEntry->deviceId,
-                motionEntry->nature, action, motionEntry->edgeFlags, motionEntry->metaState,
+                motionEntry->source, action, motionEntry->edgeFlags, motionEntry->metaState,
                 dispatchEntry->xOffset, dispatchEntry->yOffset,
                 motionEntry->xPrecision, motionEntry->yPrecision,
                 motionEntry->downTime, firstMotionSample->eventTime,
@@ -964,13 +964,13 @@
     } // release lock
 }
 
-void InputDispatcher::notifyKey(nsecs_t eventTime, int32_t deviceId, int32_t nature,
+void InputDispatcher::notifyKey(nsecs_t eventTime, int32_t deviceId, int32_t source,
         uint32_t policyFlags, int32_t action, int32_t flags,
         int32_t keyCode, int32_t scanCode, int32_t metaState, nsecs_t downTime) {
 #if DEBUG_INBOUND_EVENT_DETAILS
-    LOGD("notifyKey - eventTime=%lld, deviceId=0x%x, nature=0x%x, policyFlags=0x%x, action=0x%x, "
+    LOGD("notifyKey - eventTime=%lld, deviceId=0x%x, source=0x%x, policyFlags=0x%x, action=0x%x, "
             "flags=0x%x, keyCode=0x%x, scanCode=0x%x, metaState=0x%x, downTime=%lld",
-            eventTime, deviceId, nature, policyFlags, action, flags,
+            eventTime, deviceId, source, policyFlags, action, flags,
             keyCode, scanCode, metaState, downTime);
 #endif
 
@@ -980,7 +980,7 @@
 
         int32_t repeatCount = 0;
         KeyEntry* newEntry = mAllocator.obtainKeyEntry(eventTime,
-                deviceId, nature, policyFlags, action, flags, keyCode, scanCode,
+                deviceId, source, policyFlags, action, flags, keyCode, scanCode,
                 metaState, repeatCount, downTime);
 
         wasEmpty = mInboundQueue.isEmpty();
@@ -992,15 +992,15 @@
     }
 }
 
-void InputDispatcher::notifyMotion(nsecs_t eventTime, int32_t deviceId, int32_t nature,
+void InputDispatcher::notifyMotion(nsecs_t eventTime, int32_t deviceId, int32_t source,
         uint32_t policyFlags, int32_t action, int32_t metaState, int32_t edgeFlags,
         uint32_t pointerCount, const int32_t* pointerIds, const PointerCoords* pointerCoords,
         float xPrecision, float yPrecision, nsecs_t downTime) {
 #if DEBUG_INBOUND_EVENT_DETAILS
-    LOGD("notifyMotion - eventTime=%lld, deviceId=0x%x, nature=0x%x, policyFlags=0x%x, "
+    LOGD("notifyMotion - eventTime=%lld, deviceId=0x%x, source=0x%x, policyFlags=0x%x, "
             "action=0x%x, metaState=0x%x, edgeFlags=0x%x, xPrecision=%f, yPrecision=%f, "
             "downTime=%lld",
-            eventTime, deviceId, nature, policyFlags, action, metaState, edgeFlags,
+            eventTime, deviceId, source, policyFlags, action, metaState, edgeFlags,
             xPrecision, yPrecision, downTime);
     for (uint32_t i = 0; i < pointerCount; i++) {
         LOGD("  Pointer %d: id=%d, x=%f, y=%f, pressure=%f, size=%f",
@@ -1014,7 +1014,7 @@
         AutoMutex _l(mLock);
 
         // Attempt batching and streaming of move events.
-        if (action == MOTION_EVENT_ACTION_MOVE) {
+        if (action == AMOTION_EVENT_ACTION_MOVE) {
             // BATCHING CASE
             //
             // Try to append a move sample to the tail of the inbound queue for this device.
@@ -1033,7 +1033,7 @@
                     continue;
                 }
 
-                if (motionEntry->action != MOTION_EVENT_ACTION_MOVE
+                if (motionEntry->action != AMOTION_EVENT_ACTION_MOVE
                         || motionEntry->pointerCount != pointerCount
                         || motionEntry->isInjected()) {
                     // Last motion event in the queue for this device is not compatible for
@@ -1094,7 +1094,7 @@
 
                             MotionEntry* syncedMotionEntry = static_cast<MotionEntry*>(
                                     dispatchEntry->eventEntry);
-                            if (syncedMotionEntry->action != MOTION_EVENT_ACTION_MOVE
+                            if (syncedMotionEntry->action != AMOTION_EVENT_ACTION_MOVE
                                     || syncedMotionEntry->deviceId != deviceId
                                     || syncedMotionEntry->pointerCount != pointerCount
                                     || syncedMotionEntry->isInjected()) {
@@ -1124,7 +1124,7 @@
 
         // Just enqueue a new motion event.
         MotionEntry* newEntry = mAllocator.obtainMotionEntry(eventTime,
-                deviceId, nature, policyFlags, action, metaState, edgeFlags,
+                deviceId, source, policyFlags, action, metaState, edgeFlags,
                 xPrecision, yPrecision, downTime,
                 pointerCount, pointerIds, pointerCoords);
 
@@ -1224,19 +1224,19 @@
 InputDispatcher::EventEntry* InputDispatcher::createEntryFromInputEventLocked(
         const InputEvent* event) {
     switch (event->getType()) {
-    case INPUT_EVENT_TYPE_KEY: {
+    case AINPUT_EVENT_TYPE_KEY: {
         const KeyEvent* keyEvent = static_cast<const KeyEvent*>(event);
         uint32_t policyFlags = 0; // XXX consider adding a policy flag to track injected events
 
         KeyEntry* keyEntry = mAllocator.obtainKeyEntry(keyEvent->getEventTime(),
-                keyEvent->getDeviceId(), keyEvent->getNature(), policyFlags,
+                keyEvent->getDeviceId(), keyEvent->getSource(), policyFlags,
                 keyEvent->getAction(), keyEvent->getFlags(),
                 keyEvent->getKeyCode(), keyEvent->getScanCode(), keyEvent->getMetaState(),
                 keyEvent->getRepeatCount(), keyEvent->getDownTime());
         return keyEntry;
     }
 
-    case INPUT_EVENT_TYPE_MOTION: {
+    case AINPUT_EVENT_TYPE_MOTION: {
         const MotionEvent* motionEvent = static_cast<const MotionEvent*>(event);
         uint32_t policyFlags = 0; // XXX consider adding a policy flag to track injected events
 
@@ -1245,7 +1245,7 @@
         size_t pointerCount = motionEvent->getPointerCount();
 
         MotionEntry* motionEntry = mAllocator.obtainMotionEntry(*sampleEventTimes,
-                motionEvent->getDeviceId(), motionEvent->getNature(), policyFlags,
+                motionEvent->getDeviceId(), motionEvent->getSource(), policyFlags,
                 motionEvent->getAction(), motionEvent->getMetaState(), motionEvent->getEdgeFlags(),
                 motionEvent->getXPrecision(), motionEvent->getYPrecision(),
                 motionEvent->getDownTime(), uint32_t(pointerCount),
@@ -1500,14 +1500,14 @@
 }
 
 InputDispatcher::KeyEntry* InputDispatcher::Allocator::obtainKeyEntry(nsecs_t eventTime,
-        int32_t deviceId, int32_t nature, uint32_t policyFlags, int32_t action,
+        int32_t deviceId, int32_t source, uint32_t policyFlags, int32_t action,
         int32_t flags, int32_t keyCode, int32_t scanCode, int32_t metaState,
         int32_t repeatCount, nsecs_t downTime) {
     KeyEntry* entry = mKeyEntryPool.alloc();
     initializeEventEntry(entry, EventEntry::TYPE_KEY, eventTime);
 
     entry->deviceId = deviceId;
-    entry->nature = nature;
+    entry->source = source;
     entry->policyFlags = policyFlags;
     entry->action = action;
     entry->flags = flags;
@@ -1520,7 +1520,7 @@
 }
 
 InputDispatcher::MotionEntry* InputDispatcher::Allocator::obtainMotionEntry(nsecs_t eventTime,
-        int32_t deviceId, int32_t nature, uint32_t policyFlags, int32_t action,
+        int32_t deviceId, int32_t source, uint32_t policyFlags, int32_t action,
         int32_t metaState, int32_t edgeFlags, float xPrecision, float yPrecision,
         nsecs_t downTime, uint32_t pointerCount,
         const int32_t* pointerIds, const PointerCoords* pointerCoords) {
@@ -1529,7 +1529,7 @@
 
     entry->eventTime = eventTime;
     entry->deviceId = deviceId;
-    entry->nature = nature;
+    entry->source = source;
     entry->policyFlags = policyFlags;
     entry->action = action;
     entry->metaState = metaState;
diff --git a/libs/ui/InputReader.cpp b/libs/ui/InputReader.cpp
index 0a21db7..cd4654a 100644
--- a/libs/ui/InputReader.cpp
+++ b/libs/ui/InputReader.cpp
@@ -29,6 +29,7 @@
 #include <unistd.h>
 #include <errno.h>
 #include <limits.h>
+#include <math.h>
 
 /** Amount that trackball needs to move in order to generate a key event. */
 #define TRACKBALL_MOVEMENT_THRESHOLD 6
@@ -60,33 +61,33 @@
     int32_t mask;
     switch (keyCode) {
     case AKEYCODE_ALT_LEFT:
-        mask = META_ALT_LEFT_ON;
+        mask = AMETA_ALT_LEFT_ON;
         break;
     case AKEYCODE_ALT_RIGHT:
-        mask = META_ALT_RIGHT_ON;
+        mask = AMETA_ALT_RIGHT_ON;
         break;
     case AKEYCODE_SHIFT_LEFT:
-        mask = META_SHIFT_LEFT_ON;
+        mask = AMETA_SHIFT_LEFT_ON;
         break;
     case AKEYCODE_SHIFT_RIGHT:
-        mask = META_SHIFT_RIGHT_ON;
+        mask = AMETA_SHIFT_RIGHT_ON;
         break;
     case AKEYCODE_SYM:
-        mask = META_SYM_ON;
+        mask = AMETA_SYM_ON;
         break;
     default:
         return oldMetaState;
     }
 
     int32_t newMetaState = down ? oldMetaState | mask : oldMetaState & ~ mask
-            & ~ (META_ALT_ON | META_SHIFT_ON);
+            & ~ (AMETA_ALT_ON | AMETA_SHIFT_ON);
 
-    if (newMetaState & (META_ALT_LEFT_ON | META_ALT_RIGHT_ON)) {
-        newMetaState |= META_ALT_ON;
+    if (newMetaState & (AMETA_ALT_LEFT_ON | AMETA_ALT_RIGHT_ON)) {
+        newMetaState |= AMETA_ALT_ON;
     }
 
-    if (newMetaState & (META_SHIFT_LEFT_ON | META_SHIFT_RIGHT_ON)) {
-        newMetaState |= META_SHIFT_ON;
+    if (newMetaState & (AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_RIGHT_ON)) {
+        newMetaState |= AMETA_SHIFT_ON;
     }
 
     return newMetaState;
@@ -324,11 +325,26 @@
                     InputDevice::MultiTouchScreenState::Accumulator::FIELD_ABS_MT_TOUCH_MAJOR;
             pointer->absMTTouchMajor = rawEvent->value;
             break;
+        case ABS_MT_TOUCH_MINOR:
+            pointer->fields |=
+                    InputDevice::MultiTouchScreenState::Accumulator::FIELD_ABS_MT_TOUCH_MINOR;
+            pointer->absMTTouchMinor = rawEvent->value;
+            break;
         case ABS_MT_WIDTH_MAJOR:
             pointer->fields |=
                     InputDevice::MultiTouchScreenState::Accumulator::FIELD_ABS_MT_WIDTH_MAJOR;
             pointer->absMTWidthMajor = rawEvent->value;
             break;
+        case ABS_MT_WIDTH_MINOR:
+            pointer->fields |=
+                    InputDevice::MultiTouchScreenState::Accumulator::FIELD_ABS_MT_WIDTH_MINOR;
+            pointer->absMTWidthMinor = rawEvent->value;
+            break;
+        case ABS_MT_ORIENTATION:
+            pointer->fields |=
+                    InputDevice::MultiTouchScreenState::Accumulator::FIELD_ABS_MT_ORIENTATION;
+            pointer->absMTOrientation = rawEvent->value;
+            break;
         case ABS_MT_TRACKING_ID:
             pointer->fields |=
                     InputDevice::MultiTouchScreenState::Accumulator::FIELD_ABS_MT_TRACKING_ID;
@@ -408,17 +424,17 @@
     int32_t keyEventAction;
     if (down) {
         device->keyboard.current.downTime = when;
-        keyEventAction = KEY_EVENT_ACTION_DOWN;
+        keyEventAction = AKEY_EVENT_ACTION_DOWN;
     } else {
-        keyEventAction = KEY_EVENT_ACTION_UP;
+        keyEventAction = AKEY_EVENT_ACTION_UP;
     }
 
-    int32_t keyEventFlags = KEY_EVENT_FLAG_FROM_SYSTEM;
+    int32_t keyEventFlags = AKEY_EVENT_FLAG_FROM_SYSTEM;
     if (policyActions & InputReaderPolicyInterface::ACTION_WOKE_HERE) {
-        keyEventFlags = keyEventFlags | KEY_EVENT_FLAG_WOKE_HERE;
+        keyEventFlags = keyEventFlags | AKEY_EVENT_FLAG_WOKE_HERE;
     }
 
-    mDispatcher->notifyKey(when, device->id, INPUT_EVENT_NATURE_KEY, policyFlags,
+    mDispatcher->notifyKey(when, device->id, AINPUT_SOURCE_KEYBOARD, policyFlags,
             keyEventAction, keyEventFlags, keyCode, scanCode,
             device->keyboard.current.metaState,
             device->keyboard.current.downTime);
@@ -473,11 +489,29 @@
             continue;
         }
 
+        out->pointers[outCount].x = in->accumulator.pointers[inIndex].absMTPositionX;
+        out->pointers[outCount].y = in->accumulator.pointers[inIndex].absMTPositionY;
+
+        out->pointers[outCount].touchMajor = in->accumulator.pointers[inIndex].absMTTouchMajor;
+        out->pointers[outCount].touchMinor = (fields
+                & InputDevice::MultiTouchScreenState::Accumulator::FIELD_ABS_MT_TOUCH_MINOR) != 0
+                ? in->accumulator.pointers[inIndex].absMTTouchMinor
+                        : in->accumulator.pointers[inIndex].absMTTouchMajor;
+
+        out->pointers[outCount].toolMajor = in->accumulator.pointers[inIndex].absMTWidthMajor;
+        out->pointers[outCount].toolMinor = (fields
+                & InputDevice::MultiTouchScreenState::Accumulator::FIELD_ABS_MT_WIDTH_MINOR) != 0
+                ? in->accumulator.pointers[inIndex].absMTWidthMinor
+                        : in->accumulator.pointers[inIndex].absMTWidthMajor;
+
+        out->pointers[outCount].orientation = (fields
+                & InputDevice::MultiTouchScreenState::Accumulator::FIELD_ABS_MT_ORIENTATION) != 0
+                ? in->accumulator.pointers[inIndex].absMTOrientation : 0;
+
+        // Derive an approximation of pressure and size.
         // FIXME assignment of pressure may be incorrect, probably better to let
         // pressure = touch / width.  Later on we pass width to MotionEvent as a size, which
         // isn't quite right either.  Should be using touch for that.
-        out->pointers[outCount].x = in->accumulator.pointers[inIndex].absMTPositionX;
-        out->pointers[outCount].y = in->accumulator.pointers[inIndex].absMTPositionY;
         out->pointers[outCount].pressure = in->accumulator.pointers[inIndex].absMTTouchMajor;
         out->pointers[outCount].size = in->accumulator.pointers[inIndex].absMTWidthMajor;
 
@@ -556,6 +590,11 @@
         out->pointers[0].y = in->current.y;
         out->pointers[0].pressure = in->current.pressure;
         out->pointers[0].size = in->current.size;
+        out->pointers[0].touchMajor = in->current.pressure;
+        out->pointers[0].touchMinor = in->current.pressure;
+        out->pointers[0].toolMajor = in->current.size;
+        out->pointers[0].toolMinor = in->current.size;
+        out->pointers[0].orientation = 0;
         out->idToIndex[0] = 0;
         out->idBits.markBit(0);
     }
@@ -635,8 +674,8 @@
                     device->touchScreen.currentVirtualKey.keyCode,
                     device->touchScreen.currentVirtualKey.scanCode);
 #endif
-            dispatchVirtualKey(when, device, policyFlags, KEY_EVENT_ACTION_UP,
-                    KEY_EVENT_FLAG_FROM_SYSTEM | KEY_EVENT_FLAG_VIRTUAL_HARD_KEY);
+            dispatchVirtualKey(when, device, policyFlags, AKEY_EVENT_ACTION_UP,
+                    AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY);
             return true; // consumed
         }
 
@@ -658,9 +697,9 @@
                 device->touchScreen.currentVirtualKey.keyCode,
                 device->touchScreen.currentVirtualKey.scanCode);
 #endif
-        dispatchVirtualKey(when, device, policyFlags, KEY_EVENT_ACTION_UP,
-                KEY_EVENT_FLAG_FROM_SYSTEM | KEY_EVENT_FLAG_VIRTUAL_HARD_KEY
-                        | KEY_EVENT_FLAG_CANCELED);
+        dispatchVirtualKey(when, device, policyFlags, AKEY_EVENT_ACTION_UP,
+                AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY
+                        | AKEY_EVENT_FLAG_CANCELED);
         return true; // consumed
 
     default:
@@ -679,8 +718,8 @@
                         device->touchScreen.currentVirtualKey.keyCode,
                         device->touchScreen.currentVirtualKey.scanCode);
 #endif
-                dispatchVirtualKey(when, device, policyFlags, KEY_EVENT_ACTION_DOWN,
-                        KEY_EVENT_FLAG_FROM_SYSTEM | KEY_EVENT_FLAG_VIRTUAL_HARD_KEY);
+                dispatchVirtualKey(when, device, policyFlags, AKEY_EVENT_ACTION_DOWN,
+                        AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY);
                 return true; // consumed
             }
         }
@@ -698,15 +737,15 @@
     nsecs_t downTime = device->touchScreen.currentVirtualKey.downTime;
     int32_t metaState = globalMetaState();
 
-    if (keyEventAction == KEY_EVENT_ACTION_DOWN) {
+    if (keyEventAction == AKEY_EVENT_ACTION_DOWN) {
         mPolicy->virtualKeyDownFeedback();
     }
 
     int32_t policyActions = mPolicy->interceptKey(when, device->id,
-            keyEventAction == KEY_EVENT_ACTION_DOWN, keyCode, scanCode, policyFlags);
+            keyEventAction == AKEY_EVENT_ACTION_DOWN, keyCode, scanCode, policyFlags);
 
     if (applyStandardInputDispatchPolicyActions(when, policyActions, & policyFlags)) {
-        mDispatcher->notifyKey(when, device->id, INPUT_EVENT_NATURE_KEY, policyFlags,
+        mDispatcher->notifyKey(when, device->id, AINPUT_SOURCE_KEYBOARD, policyFlags,
                 keyEventAction, keyEventFlags, keyCode, scanCode, metaState, downTime);
     }
 }
@@ -725,7 +764,7 @@
     if (currentIdBits == lastIdBits) {
         // No pointer id changes so this is a move event.
         // The dispatcher takes care of batching moves so we don't have to deal with that here.
-        int32_t motionEventAction = MOTION_EVENT_ACTION_MOVE;
+        int32_t motionEventAction = AMOTION_EVENT_ACTION_MOVE;
         dispatchTouch(when, device, policyFlags, & device->touchScreen.currentTouch,
                 currentIdBits, motionEventAction);
     } else {
@@ -743,10 +782,10 @@
 
             int32_t motionEventAction;
             if (activeIdBits.isEmpty()) {
-                motionEventAction = MOTION_EVENT_ACTION_UP;
+                motionEventAction = AMOTION_EVENT_ACTION_UP;
             } else {
-                motionEventAction = MOTION_EVENT_ACTION_POINTER_UP
-                        | (upId << MOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
+                motionEventAction = AMOTION_EVENT_ACTION_POINTER_UP
+                        | (upId << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
             }
 
             dispatchTouch(when, device, policyFlags, & device->touchScreen.lastTouch,
@@ -761,11 +800,11 @@
 
             int32_t motionEventAction;
             if (oldActiveIdBits.isEmpty()) {
-                motionEventAction = MOTION_EVENT_ACTION_DOWN;
+                motionEventAction = AMOTION_EVENT_ACTION_DOWN;
                 device->touchScreen.downTime = when;
             } else {
-                motionEventAction = MOTION_EVENT_ACTION_POINTER_DOWN
-                        | (downId << MOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
+                motionEventAction = AMOTION_EVENT_ACTION_POINTER_DOWN
+                        | (downId << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
             }
 
             dispatchTouch(when, device, policyFlags, & device->touchScreen.currentTouch,
@@ -813,11 +852,17 @@
         float size = float(touch->pointers[index].size
                 - precalculated.sizeOrigin) * precalculated.sizeScale;
 
+        float orientation = float(touch->pointers[index].orientation)
+                * precalculated.orientationScale;
+
+        bool vertical = abs(orientation) <= M_PI / 8;
+
         switch (mDisplayOrientation) {
         case InputReaderPolicyInterface::ROTATION_90: {
             float xTemp = x;
             x = y;
             y = mDisplayWidth - xTemp;
+            vertical = ! vertical;
             break;
         }
         case InputReaderPolicyInterface::ROTATION_180: {
@@ -829,16 +874,35 @@
             float xTemp = x;
             x = mDisplayHeight - y;
             y = xTemp;
+            vertical = ! vertical;
             break;
         }
         }
 
+        float touchMajor, touchMinor, toolMajor, toolMinor;
+        if (vertical) {
+            touchMajor = float(touch->pointers[index].touchMajor) * precalculated.yScale;
+            touchMinor = float(touch->pointers[index].touchMinor) * precalculated.xScale;
+            toolMajor = float(touch->pointers[index].toolMajor) * precalculated.yScale;
+            toolMinor = float(touch->pointers[index].toolMinor) * precalculated.xScale;
+        } else {
+            touchMajor = float(touch->pointers[index].touchMajor) * precalculated.xScale;
+            touchMinor = float(touch->pointers[index].touchMinor) * precalculated.yScale;
+            toolMajor = float(touch->pointers[index].toolMajor) * precalculated.xScale;
+            toolMinor = float(touch->pointers[index].toolMinor) * precalculated.yScale;
+        }
+
         pointerIds[pointerCount] = int32_t(id);
 
         pointerCoords[pointerCount].x = x;
         pointerCoords[pointerCount].y = y;
         pointerCoords[pointerCount].pressure = pressure;
         pointerCoords[pointerCount].size = size;
+        pointerCoords[pointerCount].touchMajor = touchMajor;
+        pointerCoords[pointerCount].touchMinor = touchMinor;
+        pointerCoords[pointerCount].toolMajor = toolMajor;
+        pointerCoords[pointerCount].toolMinor = toolMinor;
+        pointerCoords[pointerCount].orientation = orientation;
 
         pointerCount += 1;
     }
@@ -847,21 +911,21 @@
     // global to the event.
     // XXX Maybe we should revise the edge flags API to work on a per-pointer basis.
     int32_t motionEventEdgeFlags = 0;
-    if (motionEventAction == MOTION_EVENT_ACTION_DOWN) {
+    if (motionEventAction == AMOTION_EVENT_ACTION_DOWN) {
         if (pointerCoords[0].x <= 0) {
-            motionEventEdgeFlags |= MOTION_EVENT_EDGE_FLAG_LEFT;
+            motionEventEdgeFlags |= AMOTION_EVENT_EDGE_FLAG_LEFT;
         } else if (pointerCoords[0].x >= orientedWidth) {
-            motionEventEdgeFlags |= MOTION_EVENT_EDGE_FLAG_RIGHT;
+            motionEventEdgeFlags |= AMOTION_EVENT_EDGE_FLAG_RIGHT;
         }
         if (pointerCoords[0].y <= 0) {
-            motionEventEdgeFlags |= MOTION_EVENT_EDGE_FLAG_TOP;
+            motionEventEdgeFlags |= AMOTION_EVENT_EDGE_FLAG_TOP;
         } else if (pointerCoords[0].y >= orientedHeight) {
-            motionEventEdgeFlags |= MOTION_EVENT_EDGE_FLAG_BOTTOM;
+            motionEventEdgeFlags |= AMOTION_EVENT_EDGE_FLAG_BOTTOM;
         }
     }
 
     nsecs_t downTime = device->touchScreen.downTime;
-    mDispatcher->notifyMotion(when, device->id, INPUT_EVENT_NATURE_TOUCH, policyFlags,
+    mDispatcher->notifyMotion(when, device->id, AINPUT_SOURCE_TOUCHSCREEN, policyFlags,
             motionEventAction, globalMetaState(), motionEventEdgeFlags,
             pointerCount, pointerIds, pointerCoords,
             0, 0, downTime);
@@ -912,9 +976,9 @@
 
     int32_t motionEventAction;
     if (downChanged) {
-        motionEventAction = down ? MOTION_EVENT_ACTION_DOWN : MOTION_EVENT_ACTION_UP;
+        motionEventAction = down ? AMOTION_EVENT_ACTION_DOWN : AMOTION_EVENT_ACTION_UP;
     } else {
-        motionEventAction = MOTION_EVENT_ACTION_MOVE;
+        motionEventAction = AMOTION_EVENT_ACTION_MOVE;
     }
 
     int32_t pointerId = 0;
@@ -925,6 +989,11 @@
             ? device->trackball.accumulator.relY * device->trackball.precalculated.yScale : 0;
     pointerCoords.pressure = 1.0f; // XXX Consider making this 1.0f if down, 0 otherwise.
     pointerCoords.size = 0;
+    pointerCoords.touchMajor = 0;
+    pointerCoords.touchMinor = 0;
+    pointerCoords.toolMajor = 0;
+    pointerCoords.toolMinor = 0;
+    pointerCoords.orientation = 0;
 
     float temp;
     switch (mDisplayOrientation) {
@@ -946,8 +1015,8 @@
         break;
     }
 
-    mDispatcher->notifyMotion(when, device->id, INPUT_EVENT_NATURE_TRACKBALL, policyFlags,
-            motionEventAction, globalMetaState(), MOTION_EVENT_EDGE_FLAG_NONE,
+    mDispatcher->notifyMotion(when, device->id, AINPUT_SOURCE_TRACKBALL, policyFlags,
+            motionEventAction, globalMetaState(), AMOTION_EVENT_EDGE_FLAG_NONE,
             1, & pointerId, & pointerCoords,
             device->trackball.precalculated.xPrecision,
             device->trackball.precalculated.yPrecision,
@@ -1079,6 +1148,8 @@
                 & device->touchScreen.parameters.pressureAxis);
         configureAbsoluteAxisInfo(device, ABS_MT_WIDTH_MAJOR, "Size",
                 & device->touchScreen.parameters.sizeAxis);
+        configureAbsoluteAxisInfo(device, ABS_MT_ORIENTATION, "Orientation",
+                & device->touchScreen.parameters.orientationAxis);
     } else if (device->isSingleTouchScreen()) {
         configureAbsoluteAxisInfo(device, ABS_X, "X",
                 & device->touchScreen.parameters.xAxis);
@@ -1088,6 +1159,7 @@
                 & device->touchScreen.parameters.pressureAxis);
         configureAbsoluteAxisInfo(device, ABS_TOOL_WIDTH, "Size",
                 & device->touchScreen.parameters.sizeAxis);
+        device->touchScreen.parameters.orientationAxis.valid = false;
     }
 
     if (device->isTouchScreen()) {
@@ -1117,6 +1189,14 @@
             device->touchScreen.precalculated.sizeOrigin = 0;
             device->touchScreen.precalculated.sizeScale = 1.0f;
         }
+
+        if (device->touchScreen.parameters.orientationAxis.valid
+                && device->touchScreen.parameters.orientationAxis.maxValue > 0) {
+            device->touchScreen.precalculated.orientationScale =
+                    M_PI_4 / device->touchScreen.parameters.orientationAxis.maxValue;
+        } else {
+            device->touchScreen.precalculated.orientationScale = 0.0f;
+        }
     }
 
     if (device->isTrackball()) {
@@ -1347,7 +1427,7 @@
         AutoMutex _l(mExportedStateLock);
 
         if (mExportedVirtualScanCode == scanCode) {
-            return KEY_STATE_VIRTUAL;
+            return AKEY_STATE_VIRTUAL;
         }
     } // release exported state lock
 
@@ -1360,7 +1440,7 @@
         AutoMutex _l(mExportedStateLock);
 
         if (mExportedVirtualKeyCode == keyCode) {
-            return KEY_STATE_VIRTUAL;
+            return AKEY_STATE_VIRTUAL;
         }
     } // release exported state lock
 
diff --git a/libs/ui/InputTransport.cpp b/libs/ui/InputTransport.cpp
index fc83e31..cf0f63e 100644
--- a/libs/ui/InputTransport.cpp
+++ b/libs/ui/InputTransport.cpp
@@ -270,7 +270,7 @@
 status_t InputPublisher::publishInputEvent(
         int32_t type,
         int32_t deviceId,
-        int32_t nature) {
+        int32_t source) {
     if (mPinned) {
         LOGE("channel '%s' publisher ~ Attempted to publish a new event but publisher has "
                 "not yet been reset.", mChannel->getName().string());
@@ -302,13 +302,13 @@
     mSharedMessage->consumed = false;
     mSharedMessage->type = type;
     mSharedMessage->deviceId = deviceId;
-    mSharedMessage->nature = nature;
+    mSharedMessage->source = source;
     return OK;
 }
 
 status_t InputPublisher::publishKeyEvent(
         int32_t deviceId,
-        int32_t nature,
+        int32_t source,
         int32_t action,
         int32_t flags,
         int32_t keyCode,
@@ -318,15 +318,15 @@
         nsecs_t downTime,
         nsecs_t eventTime) {
 #if DEBUG_TRANSPORT_ACTIONS
-    LOGD("channel '%s' publisher ~ publishKeyEvent: deviceId=%d, nature=%d, "
+    LOGD("channel '%s' publisher ~ publishKeyEvent: deviceId=%d, source=%d, "
             "action=%d, flags=%d, keyCode=%d, scanCode=%d, metaState=%d, repeatCount=%d,"
             "downTime=%lld, eventTime=%lld",
             mChannel->getName().string(),
-            deviceId, nature, action, flags, keyCode, scanCode, metaState, repeatCount,
+            deviceId, source, action, flags, keyCode, scanCode, metaState, repeatCount,
             downTime, eventTime);
 #endif
 
-    status_t result = publishInputEvent(INPUT_EVENT_TYPE_KEY, deviceId, nature);
+    status_t result = publishInputEvent(AINPUT_EVENT_TYPE_KEY, deviceId, source);
     if (result < 0) {
         return result;
     }
@@ -344,7 +344,7 @@
 
 status_t InputPublisher::publishMotionEvent(
         int32_t deviceId,
-        int32_t nature,
+        int32_t source,
         int32_t action,
         int32_t edgeFlags,
         int32_t metaState,
@@ -358,12 +358,12 @@
         const int32_t* pointerIds,
         const PointerCoords* pointerCoords) {
 #if DEBUG_TRANSPORT_ACTIONS
-    LOGD("channel '%s' publisher ~ publishMotionEvent: deviceId=%d, nature=%d, "
+    LOGD("channel '%s' publisher ~ publishMotionEvent: deviceId=%d, source=%d, "
             "action=%d, edgeFlags=%d, metaState=%d, xOffset=%f, yOffset=%f, "
             "xPrecision=%f, yPrecision=%f, downTime=%lld, eventTime=%lld, "
             "pointerCount=%d",
             mChannel->getName().string(),
-            deviceId, nature, action, edgeFlags, metaState, xOffset, yOffset,
+            deviceId, source, action, edgeFlags, metaState, xOffset, yOffset,
             xPrecision, yPrecision, downTime, eventTime, pointerCount);
 #endif
 
@@ -373,7 +373,7 @@
         return BAD_VALUE;
     }
 
-    status_t result = publishInputEvent(INPUT_EVENT_TYPE_MOTION, deviceId, nature);
+    status_t result = publishInputEvent(AINPUT_EVENT_TYPE_MOTION, deviceId, source);
     if (result < 0) {
         return result;
     }
@@ -399,7 +399,7 @@
     // Cache essential information about the motion event to ensure that a malicious consumer
     // cannot confuse the publisher by modifying the contents of the shared memory buffer while
     // it is being updated.
-    if (action == MOTION_EVENT_ACTION_MOVE) {
+    if (action == AMOTION_EVENT_ACTION_MOVE) {
         mMotionEventPointerCount = pointerCount;
         mMotionEventSampleDataStride = InputMessage::sampleDataStride(pointerCount);
         mMotionEventSampleDataTail = InputMessage::sampleDataPtrIncrement(
@@ -420,7 +420,7 @@
 
     if (! mPinned || ! mMotionEventSampleDataTail) {
         LOGE("channel '%s' publisher ~ Cannot append motion sample because there is no current "
-                "MOTION_EVENT_ACTION_MOVE event.", mChannel->getName().string());
+                "AMOTION_EVENT_ACTION_MOVE event.", mChannel->getName().string());
         return INVALID_OPERATION;
     }
 
@@ -588,7 +588,7 @@
     mSharedMessage->consumed = true;
 
     switch (mSharedMessage->type) {
-    case INPUT_EVENT_TYPE_KEY: {
+    case AINPUT_EVENT_TYPE_KEY: {
         KeyEvent* keyEvent = factory->createKeyEvent();
         if (! keyEvent) return NO_MEMORY;
 
@@ -598,7 +598,7 @@
         break;
     }
 
-    case INPUT_EVENT_TYPE_MOTION: {
+    case AINPUT_EVENT_TYPE_MOTION: {
         MotionEvent* motionEvent = factory->createMotionEvent();
         if (! motionEvent) return NO_MEMORY;
 
@@ -648,7 +648,7 @@
 void InputConsumer::populateKeyEvent(KeyEvent* keyEvent) const {
     keyEvent->initialize(
             mSharedMessage->deviceId,
-            mSharedMessage->nature,
+            mSharedMessage->source,
             mSharedMessage->key.action,
             mSharedMessage->key.flags,
             mSharedMessage->key.keyCode,
@@ -662,7 +662,7 @@
 void InputConsumer::populateMotionEvent(MotionEvent* motionEvent) const {
     motionEvent->initialize(
             mSharedMessage->deviceId,
-            mSharedMessage->nature,
+            mSharedMessage->source,
             mSharedMessage->motion.action,
             mSharedMessage->motion.edgeFlags,
             mSharedMessage->motion.metaState,
diff --git a/libs/ui/tests/InputPublisherAndConsumer_test.cpp b/libs/ui/tests/InputPublisherAndConsumer_test.cpp
index 55504f2..3bc21fa 100644
--- a/libs/ui/tests/InputPublisherAndConsumer_test.cpp
+++ b/libs/ui/tests/InputPublisherAndConsumer_test.cpp
@@ -73,17 +73,17 @@
     status_t status;
 
     const int32_t deviceId = 1;
-    const int32_t nature = INPUT_EVENT_NATURE_KEY;
-    const int32_t action = KEY_EVENT_ACTION_DOWN;
-    const int32_t flags = KEY_EVENT_FLAG_FROM_SYSTEM;
+    const int32_t source = AINPUT_SOURCE_KEYBOARD;
+    const int32_t action = AKEY_EVENT_ACTION_DOWN;
+    const int32_t flags = AKEY_EVENT_FLAG_FROM_SYSTEM;
     const int32_t keyCode = AKEYCODE_ENTER;
     const int32_t scanCode = 13;
-    const int32_t metaState = META_ALT_LEFT_ON | META_ALT_ON;
+    const int32_t metaState = AMETA_ALT_LEFT_ON | AMETA_ALT_ON;
     const int32_t repeatCount = 1;
     const nsecs_t downTime = 3;
     const nsecs_t eventTime = 4;
 
-    status = mPublisher->publishKeyEvent(deviceId, nature, action, flags,
+    status = mPublisher->publishKeyEvent(deviceId, source, action, flags,
             keyCode, scanCode, metaState, repeatCount, downTime, eventTime);
     ASSERT_EQ(OK, status)
             << "publisher publishKeyEvent should return OK";
@@ -103,12 +103,12 @@
 
     ASSERT_TRUE(event != NULL)
             << "consumer should have returned non-NULL event";
-    ASSERT_EQ(INPUT_EVENT_TYPE_KEY, event->getType())
+    ASSERT_EQ(AINPUT_EVENT_TYPE_KEY, event->getType())
             << "consumer should have returned a key event";
 
     KeyEvent* keyEvent = static_cast<KeyEvent*>(event);
     EXPECT_EQ(deviceId, keyEvent->getDeviceId());
-    EXPECT_EQ(nature, keyEvent->getNature());
+    EXPECT_EQ(source, keyEvent->getSource());
     EXPECT_EQ(action, keyEvent->getAction());
     EXPECT_EQ(flags, keyEvent->getFlags());
     EXPECT_EQ(keyCode, keyEvent->getKeyCode());
@@ -136,10 +136,10 @@
     status_t status;
 
     const int32_t deviceId = 1;
-    const int32_t nature = INPUT_EVENT_NATURE_TOUCH;
-    const int32_t action = MOTION_EVENT_ACTION_MOVE;
-    const int32_t edgeFlags = MOTION_EVENT_EDGE_FLAG_TOP;
-    const int32_t metaState = META_ALT_LEFT_ON | META_ALT_ON;
+    const int32_t source = AINPUT_SOURCE_TOUCHSCREEN;
+    const int32_t action = AMOTION_EVENT_ACTION_MOVE;
+    const int32_t edgeFlags = AMOTION_EVENT_EDGE_FLAG_TOP;
+    const int32_t metaState = AMETA_ALT_LEFT_ON | AMETA_ALT_ON;
     const float xOffset = -10;
     const float yOffset = -20;
     const float xPrecision = 0.25;
@@ -159,10 +159,15 @@
             samplePointerCoords.editTop().y = 200 * i + j;
             samplePointerCoords.editTop().pressure = 0.5 * i + j;
             samplePointerCoords.editTop().size = 0.7 * i + j;
+            samplePointerCoords.editTop().touchMajor = 1.5 * i + j;
+            samplePointerCoords.editTop().touchMinor = 1.7 * i + j;
+            samplePointerCoords.editTop().toolMajor = 2.5 * i + j;
+            samplePointerCoords.editTop().toolMinor = 2.7 * i + j;
+            samplePointerCoords.editTop().orientation = 3.5 * i + j;
         }
     }
 
-    status = mPublisher->publishMotionEvent(deviceId, nature, action, edgeFlags,
+    status = mPublisher->publishMotionEvent(deviceId, source, action, edgeFlags,
             metaState, xOffset, yOffset, xPrecision, yPrecision,
             downTime, sampleEventTimes[0], pointerCount, pointerIds, samplePointerCoords.array());
     ASSERT_EQ(OK, status)
@@ -199,14 +204,14 @@
 
     ASSERT_TRUE(event != NULL)
             << "consumer should have returned non-NULL event";
-    ASSERT_EQ(INPUT_EVENT_TYPE_MOTION, event->getType())
+    ASSERT_EQ(AINPUT_EVENT_TYPE_MOTION, event->getType())
             << "consumer should have returned a motion event";
 
     size_t lastSampleIndex = samplesToAppendBeforeDispatch + samplesToAppendAfterDispatch;
 
     MotionEvent* motionEvent = static_cast<MotionEvent*>(event);
     EXPECT_EQ(deviceId, motionEvent->getDeviceId());
-    EXPECT_EQ(nature, motionEvent->getNature());
+    EXPECT_EQ(source, motionEvent->getSource());
     EXPECT_EQ(action, motionEvent->getAction());
     EXPECT_EQ(edgeFlags, motionEvent->getEdgeFlags());
     EXPECT_EQ(metaState, motionEvent->getMetaState());
@@ -241,6 +246,16 @@
                     motionEvent->getHistoricalPressure(i, sampleIndex));
             EXPECT_EQ(samplePointerCoords[offset].size,
                     motionEvent->getHistoricalSize(i, sampleIndex));
+            EXPECT_EQ(samplePointerCoords[offset].touchMajor,
+                    motionEvent->getHistoricalTouchMajor(i, sampleIndex));
+            EXPECT_EQ(samplePointerCoords[offset].touchMinor,
+                    motionEvent->getHistoricalTouchMinor(i, sampleIndex));
+            EXPECT_EQ(samplePointerCoords[offset].toolMajor,
+                    motionEvent->getHistoricalToolMajor(i, sampleIndex));
+            EXPECT_EQ(samplePointerCoords[offset].toolMinor,
+                    motionEvent->getHistoricalToolMinor(i, sampleIndex));
+            EXPECT_EQ(samplePointerCoords[offset].orientation,
+                    motionEvent->getHistoricalOrientation(i, sampleIndex));
         }
     }
 
@@ -255,6 +270,11 @@
         EXPECT_EQ(samplePointerCoords[offset].y + yOffset, motionEvent->getY(i));
         EXPECT_EQ(samplePointerCoords[offset].pressure, motionEvent->getPressure(i));
         EXPECT_EQ(samplePointerCoords[offset].size, motionEvent->getSize(i));
+        EXPECT_EQ(samplePointerCoords[offset].touchMajor, motionEvent->getTouchMajor(i));
+        EXPECT_EQ(samplePointerCoords[offset].touchMinor, motionEvent->getTouchMinor(i));
+        EXPECT_EQ(samplePointerCoords[offset].toolMajor, motionEvent->getToolMajor(i));
+        EXPECT_EQ(samplePointerCoords[offset].toolMinor, motionEvent->getToolMinor(i));
+        EXPECT_EQ(samplePointerCoords[offset].orientation, motionEvent->getOrientation(i));
     }
 
     status = mConsumer->sendFinishedSignal();
@@ -300,7 +320,7 @@
 
     const size_t pointerCount = 1;
     int32_t pointerIds[pointerCount] = { 0 };
-    PointerCoords pointerCoords[pointerCount] = { { 0, 0, 0, 0 } };
+    PointerCoords pointerCoords[pointerCount] = { { 0, 0, 0, 0, 0, 0, 0, 0, 0 } };
 
     status = mPublisher->publishMotionEvent(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
             pointerCount, pointerIds, pointerCoords);
@@ -381,7 +401,7 @@
     int32_t pointerIds[pointerCount];
     PointerCoords pointerCoords[pointerCount];
 
-    status = mPublisher->publishMotionEvent(0, 0, MOTION_EVENT_ACTION_DOWN,
+    status = mPublisher->publishMotionEvent(0, 0, AMOTION_EVENT_ACTION_DOWN,
             0, 0, 0, 0, 0, 0, 0, 0, pointerCount, pointerIds, pointerCoords);
     ASSERT_EQ(OK, status);
 
@@ -398,7 +418,7 @@
     int32_t pointerIds[pointerCount];
     PointerCoords pointerCoords[pointerCount];
 
-    status = mPublisher->publishMotionEvent(0, 0, MOTION_EVENT_ACTION_MOVE,
+    status = mPublisher->publishMotionEvent(0, 0, AMOTION_EVENT_ACTION_MOVE,
             0, 0, 0, 0, 0, 0, 0, 0, pointerCount, pointerIds, pointerCoords);
     ASSERT_EQ(OK, status);
 
@@ -425,7 +445,7 @@
     int32_t pointerIds[pointerCount];
     PointerCoords pointerCoords[pointerCount];
 
-    status = mPublisher->publishMotionEvent(0, 0, MOTION_EVENT_ACTION_MOVE,
+    status = mPublisher->publishMotionEvent(0, 0, AMOTION_EVENT_ACTION_MOVE,
             0, 0, 0, 0, 0, 0, 0, 0, pointerCount, pointerIds, pointerCoords);
     ASSERT_EQ(OK, status);
 
diff --git a/native/android/input.cpp b/native/android/input.cpp
index a4dde51..4e1b6dc 100644
--- a/native/android/input.cpp
+++ b/native/android/input.cpp
@@ -38,8 +38,8 @@
     return static_cast<const InputEvent*>(event)->getDeviceId();
 }
 
-int32_t AInputEvent_getNature(const AInputEvent* event) {
-    return static_cast<const InputEvent*>(event)->getNature();
+int32_t AInputEvent_getSource(const AInputEvent* event) {
+    return static_cast<const InputEvent*>(event)->getSource();
 }
 
 int32_t AKeyEvent_getAction(const AInputEvent* key_event) {
@@ -69,6 +69,7 @@
     return static_cast<const KeyEvent*>(key_event)->getDownTime();
 }
 
+
 int64_t AKeyEvent_getEventTime(const AInputEvent* key_event) {
     return static_cast<const KeyEvent*>(key_event)->getEventTime();
 }
@@ -141,6 +142,26 @@
     return static_cast<const MotionEvent*>(motion_event)->getSize(pointer_index);
 }
 
+float AMotionEvent_getTouchMajor(const AInputEvent* motion_event, size_t pointer_index) {
+    return static_cast<const MotionEvent*>(motion_event)->getTouchMajor(pointer_index);
+}
+
+float AMotionEvent_getTouchMinor(const AInputEvent* motion_event, size_t pointer_index) {
+    return static_cast<const MotionEvent*>(motion_event)->getTouchMinor(pointer_index);
+}
+
+float AMotionEvent_getToolMajor(const AInputEvent* motion_event, size_t pointer_index) {
+    return static_cast<const MotionEvent*>(motion_event)->getToolMajor(pointer_index);
+}
+
+float AMotionEvent_getToolMinor(const AInputEvent* motion_event, size_t pointer_index) {
+    return static_cast<const MotionEvent*>(motion_event)->getToolMinor(pointer_index);
+}
+
+float AMotionEvent_getOrientation(const AInputEvent* motion_event, size_t pointer_index) {
+    return static_cast<const MotionEvent*>(motion_event)->getOrientation(pointer_index);
+}
+
 size_t AMotionEvent_getHistorySize(const AInputEvent* motion_event) {
     return static_cast<const MotionEvent*>(motion_event)->getHistorySize();
 }
@@ -187,6 +208,37 @@
             pointer_index, history_index);
 }
 
+float AMotionEvent_getHistoricalTouchMajor(AInputEvent* motion_event, size_t pointer_index,
+        size_t history_index) {
+    return static_cast<const MotionEvent*>(motion_event)->getHistoricalTouchMajor(
+            pointer_index, history_index);
+}
+
+float AMotionEvent_getHistoricalTouchMinor(AInputEvent* motion_event, size_t pointer_index,
+        size_t history_index) {
+    return static_cast<const MotionEvent*>(motion_event)->getHistoricalTouchMinor(
+            pointer_index, history_index);
+}
+
+float AMotionEvent_getHistoricalToolMajor(AInputEvent* motion_event, size_t pointer_index,
+        size_t history_index) {
+    return static_cast<const MotionEvent*>(motion_event)->getHistoricalToolMajor(
+            pointer_index, history_index);
+}
+
+float AMotionEvent_getHistoricalToolMinor(AInputEvent* motion_event, size_t pointer_index,
+        size_t history_index) {
+    return static_cast<const MotionEvent*>(motion_event)->getHistoricalToolMinor(
+            pointer_index, history_index);
+}
+
+float AMotionEvent_getHistoricalOrientation(AInputEvent* motion_event, size_t pointer_index,
+        size_t history_index) {
+    return static_cast<const MotionEvent*>(motion_event)->getHistoricalOrientation(
+            pointer_index, history_index);
+}
+
+
 void AInputQueue_attachLooper(AInputQueue* queue, ALooper* looper,
         ALooper_callbackFunc* callback, void* data) {
     queue->attachLooper(looper, callback, data);
diff --git a/native/include/android/input.h b/native/include/android/input.h
index 25dd68e..ce79cd4 100644
--- a/native/include/android/input.h
+++ b/native/include/android/input.h
@@ -49,49 +49,21 @@
 #endif
 
 /*
- * Input device classes.
- */
-enum {
-    /* The input device is a keyboard. */
-    INPUT_DEVICE_CLASS_KEYBOARD      = 0x00000001,
-
-    /* The input device is an alpha-numeric keyboard (not just a dial pad). */
-    INPUT_DEVICE_CLASS_ALPHAKEY      = 0x00000002,
-
-    /* The input device is a touchscreen (either single-touch or multi-touch). */
-    INPUT_DEVICE_CLASS_TOUCHSCREEN   = 0x00000004,
-
-    /* The input device is a trackball. */
-    INPUT_DEVICE_CLASS_TRACKBALL     = 0x00000008,
-
-    /* The input device is a multi-touch touchscreen. */
-    INPUT_DEVICE_CLASS_TOUCHSCREEN_MT= 0x00000010,
-
-    /* The input device is a directional pad. */
-    INPUT_DEVICE_CLASS_DPAD          = 0x00000020,
-
-    /* The input device is a gamepad (implies keyboard). */
-    INPUT_DEVICE_CLASS_GAMEPAD       = 0x00000040
-};
-
-/*
  * Key states (may be returned by queries about the current state of a
  * particular key code, scan code or switch).
- *
- * XXX should we call this BUTTON_STATE_XXX?
  */
 enum {
     /* The key state is unknown or the requested key itself is not supported. */
-    KEY_STATE_UNKNOWN = -1,
+    AKEY_STATE_UNKNOWN = -1,
 
     /* The key is up. */
-    KEY_STATE_UP = 0,
+    AKEY_STATE_UP = 0,
 
     /* The key is down. */
-    KEY_STATE_DOWN = 1,
+    AKEY_STATE_DOWN = 1,
 
     /* The key is down but is a virtual key press that is being emulated by the system. */
-    KEY_STATE_VIRTUAL = 2
+    AKEY_STATE_VIRTUAL = 2
 };
 
 /*
@@ -99,28 +71,28 @@
  */
 enum {
     /* No meta keys are pressed. */
-    META_NONE = 0,
+    AMETA_NONE = 0,
 
     /* This mask is used to check whether one of the ALT meta keys is pressed. */
-    META_ALT_ON = 0x02,
+    AMETA_ALT_ON = 0x02,
 
     /* This mask is used to check whether the left ALT meta key is pressed. */
-    META_ALT_LEFT_ON = 0x10,
+    AMETA_ALT_LEFT_ON = 0x10,
 
     /* This mask is used to check whether the right ALT meta key is pressed. */
-    META_ALT_RIGHT_ON = 0x20,
+    AMETA_ALT_RIGHT_ON = 0x20,
 
     /* This mask is used to check whether one of the SHIFT meta keys is pressed. */
-    META_SHIFT_ON = 0x01,
+    AMETA_SHIFT_ON = 0x01,
 
     /* This mask is used to check whether the left SHIFT meta key is pressed. */
-    META_SHIFT_LEFT_ON = 0x40,
+    AMETA_SHIFT_LEFT_ON = 0x40,
 
     /* This mask is used to check whether the right SHIFT meta key is pressed. */
-    META_SHIFT_RIGHT_ON = 0x80,
+    AMETA_SHIFT_RIGHT_ON = 0x80,
 
     /* This mask is used to check whether the SYM meta key is pressed. */
-    META_SYM_ON = 0x04
+    AMETA_SYM_ON = 0x04
 };
 
 /*
@@ -137,10 +109,10 @@
  */
 enum {
     /* Indicates that the input event is a key event. */
-    INPUT_EVENT_TYPE_KEY = 1,
+    AINPUT_EVENT_TYPE_KEY = 1,
 
     /* Indicates that the input event is a motion event. */
-    INPUT_EVENT_TYPE_MOTION = 2
+    AINPUT_EVENT_TYPE_MOTION = 2
 };
 
 /*
@@ -148,16 +120,16 @@
  */
 enum {
     /* The key has been pressed down. */
-    KEY_EVENT_ACTION_DOWN = 0,
+    AKEY_EVENT_ACTION_DOWN = 0,
 
     /* The key has been released. */
-    KEY_EVENT_ACTION_UP = 1,
+    AKEY_EVENT_ACTION_UP = 1,
 
     /* Multiple duplicate key events have occurred in a row, or a complex string is
      * being delivered.  The repeat_count property of the key event contains the number
      * of times the given key code should be executed.
      */
-    KEY_EVENT_ACTION_MULTIPLE = 2
+    AKEY_EVENT_ACTION_MULTIPLE = 2
 };
 
 /*
@@ -165,25 +137,25 @@
  */
 enum {
     /* This mask is set if the device woke because of this key event. */
-    KEY_EVENT_FLAG_WOKE_HERE = 0x1,
+    AKEY_EVENT_FLAG_WOKE_HERE = 0x1,
 
     /* This mask is set if the key event was generated by a software keyboard. */
-    KEY_EVENT_FLAG_SOFT_KEYBOARD = 0x2,
+    AKEY_EVENT_FLAG_SOFT_KEYBOARD = 0x2,
 
     /* This mask is set if we don't want the key event to cause us to leave touch mode. */
-    KEY_EVENT_FLAG_KEEP_TOUCH_MODE = 0x4,
+    AKEY_EVENT_FLAG_KEEP_TOUCH_MODE = 0x4,
 
     /* This mask is set if an event was known to come from a trusted part
      * of the system.  That is, the event is known to come from the user,
      * and could not have been spoofed by a third party component. */
-    KEY_EVENT_FLAG_FROM_SYSTEM = 0x8,
+    AKEY_EVENT_FLAG_FROM_SYSTEM = 0x8,
 
     /* This mask is used for compatibility, to identify enter keys that are
      * coming from an IME whose enter key has been auto-labelled "next" or
      * "done".  This allows TextView to dispatch these as normal enter keys
      * for old applications, but still do the appropriate action when
      * receiving them. */
-    KEY_EVENT_FLAG_EDITOR_ACTION = 0x10,
+    AKEY_EVENT_FLAG_EDITOR_ACTION = 0x10,
 
     /* When associated with up key events, this indicates that the key press
      * has been canceled.  Typically this is used with virtual touch screen
@@ -193,26 +165,26 @@
      * key.  Note that for this to work, the application can not perform an
      * action for a key until it receives an up or the long press timeout has
      * expired. */
-    KEY_EVENT_FLAG_CANCELED = 0x20,
+    AKEY_EVENT_FLAG_CANCELED = 0x20,
 
     /* This key event was generated by a virtual (on-screen) hard key area.
      * Typically this is an area of the touchscreen, outside of the regular
      * display, dedicated to "hardware" buttons. */
-    KEY_EVENT_FLAG_VIRTUAL_HARD_KEY = 0x40,
+    AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY = 0x40,
 
     /* This flag is set for the first key repeat that occurs after the
      * long press timeout. */
-    KEY_EVENT_FLAG_LONG_PRESS = 0x80,
+    AKEY_EVENT_FLAG_LONG_PRESS = 0x80,
 
-    /* Set when a key event has KEY_EVENT_FLAG_CANCELED set because a long
+    /* Set when a key event has AKEY_EVENT_FLAG_CANCELED set because a long
      * press action was executed while it was down. */
-    KEY_EVENT_FLAG_CANCELED_LONG_PRESS = 0x100,
+    AKEY_EVENT_FLAG_CANCELED_LONG_PRESS = 0x100,
 
-    /* Set for KEY_EVENT_ACTION_UP when this event's key code is still being
+    /* Set for AKEY_EVENT_ACTION_UP when this event's key code is still being
      * tracked from its initial down.  That is, somebody requested that tracking
      * started on the key down and a long press has not caused
      * the tracking to be canceled. */
-    KEY_EVENT_FLAG_TRACKING = 0x200
+    AKEY_EVENT_FLAG_TRACKING = 0x200
 };
 
 /*
@@ -220,57 +192,57 @@
  */
 
 /* Bit shift for the action bits holding the pointer index as
- * defined by MOTION_EVENT_ACTION_POINTER_INDEX_MASK.
+ * defined by AMOTION_EVENT_ACTION_POINTER_INDEX_MASK.
  */
-#define MOTION_EVENT_ACTION_POINTER_INDEX_SHIFT 8
+#define AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT 8
 
 enum {
     /* Bit mask of the parts of the action code that are the action itself.
      */
-    MOTION_EVENT_ACTION_MASK = 0xff,
+    AMOTION_EVENT_ACTION_MASK = 0xff,
 
     /* Bits in the action code that represent a pointer index, used with
-     * MOTION_EVENT_ACTION_POINTER_DOWN and MOTION_EVENT_ACTION_POINTER_UP.  Shifting
-     * down by MOTION_EVENT_ACTION_POINTER_INDEX_SHIFT provides the actual pointer
+     * AMOTION_EVENT_ACTION_POINTER_DOWN and AMOTION_EVENT_ACTION_POINTER_UP.  Shifting
+     * down by AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT provides the actual pointer
      * index where the data for the pointer going up or down can be found.
      */
-    MOTION_EVENT_ACTION_POINTER_INDEX_MASK  = 0xff00,
+    AMOTION_EVENT_ACTION_POINTER_INDEX_MASK  = 0xff00,
 
     /* A pressed gesture has started, the motion contains the initial starting location.
      */
-    MOTION_EVENT_ACTION_DOWN = 0,
+    AMOTION_EVENT_ACTION_DOWN = 0,
 
     /* A pressed gesture has finished, the motion contains the final release location
      * as well as any intermediate points since the last down or move event.
      */
-    MOTION_EVENT_ACTION_UP = 1,
+    AMOTION_EVENT_ACTION_UP = 1,
 
-    /* A change has happened during a press gesture (between MOTION_EVENT_ACTION_DOWN and
-     * MOTION_EVENT_ACTION_UP).  The motion contains the most recent point, as well as
+    /* A change has happened during a press gesture (between AMOTION_EVENT_ACTION_DOWN and
+     * AMOTION_EVENT_ACTION_UP).  The motion contains the most recent point, as well as
      * any intermediate points since the last down or move event.
      */
-    MOTION_EVENT_ACTION_MOVE = 2,
+    AMOTION_EVENT_ACTION_MOVE = 2,
 
     /* The current gesture has been aborted.
      * You will not receive any more points in it.  You should treat this as
      * an up event, but not perform any action that you normally would.
      */
-    MOTION_EVENT_ACTION_CANCEL = 3,
+    AMOTION_EVENT_ACTION_CANCEL = 3,
 
     /* A movement has happened outside of the normal bounds of the UI element.
      * This does not provide a full gesture, but only the initial location of the movement/touch.
      */
-    MOTION_EVENT_ACTION_OUTSIDE = 4,
+    AMOTION_EVENT_ACTION_OUTSIDE = 4,
 
     /* A non-primary pointer has gone down.
-     * The bits in MOTION_EVENT_ACTION_POINTER_INDEX_MASK indicate which pointer changed.
+     * The bits in AMOTION_EVENT_ACTION_POINTER_INDEX_MASK indicate which pointer changed.
      */
-    MOTION_EVENT_ACTION_POINTER_DOWN = 5,
+    AMOTION_EVENT_ACTION_POINTER_DOWN = 5,
 
     /* A non-primary pointer has gone up.
-     * The bits in MOTION_EVENT_ACTION_POINTER_INDEX_MASK indicate which pointer changed.
+     * The bits in AMOTION_EVENT_ACTION_POINTER_INDEX_MASK indicate which pointer changed.
      */
-    MOTION_EVENT_ACTION_POINTER_UP = 6
+    AMOTION_EVENT_ACTION_POINTER_UP = 6
 };
 
 /*
@@ -278,39 +250,50 @@
  */
 enum {
     /* No edges intersected */
-    MOTION_EVENT_EDGE_FLAG_NONE = 0,
+    AMOTION_EVENT_EDGE_FLAG_NONE = 0,
 
     /* Flag indicating the motion event intersected the top edge of the screen. */
-    MOTION_EVENT_EDGE_FLAG_TOP = 0x01,
+    AMOTION_EVENT_EDGE_FLAG_TOP = 0x01,
 
     /* Flag indicating the motion event intersected the bottom edge of the screen. */
-    MOTION_EVENT_EDGE_FLAG_BOTTOM = 0x02,
+    AMOTION_EVENT_EDGE_FLAG_BOTTOM = 0x02,
 
     /* Flag indicating the motion event intersected the left edge of the screen. */
-    MOTION_EVENT_EDGE_FLAG_LEFT = 0x04,
+    AMOTION_EVENT_EDGE_FLAG_LEFT = 0x04,
 
     /* Flag indicating the motion event intersected the right edge of the screen. */
-    MOTION_EVENT_EDGE_FLAG_RIGHT = 0x08
+    AMOTION_EVENT_EDGE_FLAG_RIGHT = 0x08
 };
 
 /*
- * Specifies the logical nature of an input event.
- * For example, the nature distinguishes between motion events that represent touches and
- * those that represent trackball moves.
+ * Input sources.
  *
- * XXX This concept is tentative.  Another idea would be to associate events with logical
- *     controllers rather than physical devices.   The interpretation of an event would
- *     be made with respect to the nature of the controller that is considered the logical
- *     source of an event.  The decoupling is beneficial since multiple physical (and virtual)
- *     devices could be responsible for producing events that would be associated with
- *     various logical controllers.  For example, the hard keyboard, on screen keyboard,
- *     and peripheral keyboard could be mapped onto a single logical "keyboard" controller
- *     (or treated independently, if desired).
+ * The appropriate interpretation for an input event depends on its source.
+ * Refer to the documentation on android.view.InputDevice for more details about input sources
+ * and their correct interpretation.
  */
 enum {
-    INPUT_EVENT_NATURE_KEY = 1,
-    INPUT_EVENT_NATURE_TOUCH = 2,
-    INPUT_EVENT_NATURE_TRACKBALL = 3
+    AINPUT_SOURCE_CLASS_MASK = 0x000000ff,
+
+    AINPUT_SOURCE_CLASS_BUTTON = 0x00000001,
+    AINPUT_SOURCE_CLASS_POINTER = 0x00000002,
+    AINPUT_SOURCE_CLASS_NAVIGATION = 0x00000004,
+    AINPUT_SOURCE_CLASS_POSITION = 0x00000008,
+    AINPUT_SOURCE_CLASS_JOYSTICK = 0x00000010,
+};
+
+enum {
+    AINPUT_SOURCE_UNKNOWN = 0x00000000,
+
+    AINPUT_SOURCE_KEYBOARD = 0x00000100 | AINPUT_SOURCE_CLASS_BUTTON,
+    AINPUT_SOURCE_DPAD = 0x00000200 | AINPUT_SOURCE_CLASS_BUTTON,
+    AINPUT_SOURCE_GAMEPAD = 0x00000400 | AINPUT_SOURCE_CLASS_BUTTON,
+    AINPUT_SOURCE_TOUCHSCREEN = 0x00001000 | AINPUT_SOURCE_CLASS_POINTER,
+    AINPUT_SOURCE_MOUSE = 0x00002000 | AINPUT_SOURCE_CLASS_POINTER,
+    AINPUT_SOURCE_TRACKBALL = 0x00010000 | AINPUT_SOURCE_CLASS_NAVIGATION,
+    AINPUT_SOURCE_TOUCHPAD = 0x00100000 | AINPUT_SOURCE_CLASS_POSITION,
+    AINPUT_SOURCE_JOYSTICK_LEFT = 0x01000000 | AINPUT_SOURCE_CLASS_JOYSTICK,
+    AINPUT_SOURCE_JOYSTICK_RIGHT = 0x02000000 | AINPUT_SOURCE_CLASS_JOYSTICK,
 };
 
 /*
@@ -337,8 +320,8 @@
  */
 int32_t AInputEvent_getDeviceId(const AInputEvent* event);
 
-/* Get the input event nature. */
-int32_t AInputEvent_getNature(const AInputEvent* event);
+/* Get the input event source. */
+int32_t AInputEvent_getSource(const AInputEvent* event);
 
 /*** Accessors for key events only. ***/
 
@@ -466,11 +449,41 @@
  * determine fat touch events. */
 float AMotionEvent_getSize(const AInputEvent* motion_event, size_t pointer_index);
 
+/* Get the current length of the major axis of an ellipse that describes the touch area
+ * at the point of contact for the given pointer index. */
+float AMotionEvent_getTouchMajor(const AInputEvent* motion_event, size_t pointer_index);
+
+/* Get the current length of the minor axis of an ellipse that describes the touch area
+ * at the point of contact for the given pointer index. */
+float AMotionEvent_getTouchMinor(const AInputEvent* motion_event, size_t pointer_index);
+
+/* Get the current length of the major axis of an ellipse that describes the size
+ * of the approaching tool for the given pointer index.
+ * The tool area represents the estimated size of the finger or pen that is
+ * touching the device independent of its actual touch area at the point of contact. */
+float AMotionEvent_getToolMajor(const AInputEvent* motion_event, size_t pointer_index);
+
+/* Get the current length of the minor axis of an ellipse that describes the size
+ * of the approaching tool for the given pointer index.
+ * The tool area represents the estimated size of the finger or pen that is
+ * touching the device independent of its actual touch area at the point of contact. */
+float AMotionEvent_getToolMinor(const AInputEvent* motion_event, size_t pointer_index);
+
+/* Get the current orientation of the touch area and tool area in radians clockwise from
+ * vertical for the given pointer index.
+ * An angle of 0 degrees indicates that the major axis of contact is oriented
+ * upwards, is perfectly circular or is of unknown orientation.  A positive angle
+ * indicates that the major axis of contact is oriented to the right.  A negative angle
+ * indicates that the major axis of contact is oriented to the left.
+ * The full range is from -PI/4 radians (finger pointing fully left) to PI/4 radians
+ * (finger pointing fully right). */
+float AMotionEvent_getOrientation(const AInputEvent* motion_event, size_t pointer_index);
+
 /* Get the number of historical points in this event.  These are movements that
  * have occurred between this event and the previous event.  This only applies
- * to MOTION_EVENT_ACTION_MOVE events -- all other actions will have a size of 0.
+ * to AMOTION_EVENT_ACTION_MOVE events -- all other actions will have a size of 0.
  * Historical samples are indexed from oldest to newest. */
-size_t AMotionEvent_get_history_size(const AInputEvent* motion_event);
+size_t AMotionEvent_getHistorySize(const AInputEvent* motion_event);
 
 /* Get the time that a historical movement occurred between this event and
  * the previous event, in the java.lang.System.nanoTime() time base. */
@@ -527,6 +540,47 @@
 float AMotionEvent_getHistoricalSize(AInputEvent* motion_event, size_t pointer_index,
         size_t history_index);
 
+/* Get the historical length of the major axis of an ellipse that describes the touch area
+ * at the point of contact for the given pointer index that
+ * occurred between this event and the previous motion event. */
+float AMotionEvent_getHistoricalTouchMajor(const AInputEvent* motion_event, size_t pointer_index,
+        size_t history_index);
+
+/* Get the historical length of the minor axis of an ellipse that describes the touch area
+ * at the point of contact for the given pointer index that
+ * occurred between this event and the previous motion event. */
+float AMotionEvent_getHistoricalTouchMinor(const AInputEvent* motion_event, size_t pointer_index,
+        size_t history_index);
+
+/* Get the historical length of the major axis of an ellipse that describes the size
+ * of the approaching tool for the given pointer index that
+ * occurred between this event and the previous motion event.
+ * The tool area represents the estimated size of the finger or pen that is
+ * touching the device independent of its actual touch area at the point of contact. */
+float AMotionEvent_getHistoricalToolMajor(const AInputEvent* motion_event, size_t pointer_index,
+        size_t history_index);
+
+/* Get the historical length of the minor axis of an ellipse that describes the size
+ * of the approaching tool for the given pointer index that
+ * occurred between this event and the previous motion event.
+ * The tool area represents the estimated size of the finger or pen that is
+ * touching the device independent of its actual touch area at the point of contact. */
+float AMotionEvent_getHistoricalToolMinor(const AInputEvent* motion_event, size_t pointer_index,
+        size_t history_index);
+
+/* Get the historical orientation of the touch area and tool area in radians clockwise from
+ * vertical for the given pointer index that
+ * occurred between this event and the previous motion event.
+ * An angle of 0 degrees indicates that the major axis of contact is oriented
+ * upwards, is perfectly circular or is of unknown orientation.  A positive angle
+ * indicates that the major axis of contact is oriented to the right.  A negative angle
+ * indicates that the major axis of contact is oriented to the left.
+ * The full range is from -PI/4 radians (finger pointing fully left) to PI/4 radians
+ * (finger pointing fully right). */
+float AMotionEvent_getHistoricalOrientation(const AInputEvent* motion_event, size_t pointer_index,
+        size_t history_index);
+
+
 /*
  * Input queue
  *
diff --git a/services/java/com/android/server/InputManager.java b/services/java/com/android/server/InputManager.java
index cdae27c..3c60a98 100644
--- a/services/java/com/android/server/InputManager.java
+++ b/services/java/com/android/server/InputManager.java
@@ -77,9 +77,9 @@
     private static native boolean nativeHasKeys(int[] keyCodes, boolean[] keyExists);
     private static native void nativeRegisterInputChannel(InputChannel inputChannel);
     private static native void nativeUnregisterInputChannel(InputChannel inputChannel);
-    private static native int nativeInjectKeyEvent(KeyEvent event, int nature,
+    private static native int nativeInjectKeyEvent(KeyEvent event,
             int injectorPid, int injectorUid, boolean sync, int timeoutMillis);
-    private static native int nativeInjectMotionEvent(MotionEvent event, int nature,
+    private static native int nativeInjectMotionEvent(MotionEvent event,
             int injectorPid, int injectorUid, boolean sync, int timeoutMillis);
     private static native void nativeSetInputWindows(InputWindow[] windows);
     private static native void nativeSetInputDispatchMode(boolean enabled, boolean frozen);
@@ -229,14 +229,13 @@
      * to be dispatched before it can determine whether input event injection will be
      * permitted based on the current input focus.
      * @param event The event to inject.
-     * @param nature The nature of the event.
      * @param injectorPid The pid of the injecting application.
      * @param injectorUid The uid of the injecting application.
      * @param sync If true, waits for the event to be completed before returning.
      * @param timeoutMillis The injection timeout in milliseconds.
      * @return One of the INPUT_EVENT_INJECTION_XXX constants.
      */
-    public int injectKeyEvent(KeyEvent event, int nature, int injectorPid, int injectorUid,
+    public int injectKeyEvent(KeyEvent event, int injectorPid, int injectorUid,
             boolean sync, int timeoutMillis) {
         if (event == null) {
             throw new IllegalArgumentException("event must not be null");
@@ -248,7 +247,7 @@
             throw new IllegalArgumentException("timeoutMillis must be positive");
         }
         
-        return nativeInjectKeyEvent(event, nature, injectorPid, injectorUid,
+        return nativeInjectKeyEvent(event, injectorPid, injectorUid,
                 sync, timeoutMillis);
     }
     
@@ -258,7 +257,6 @@
      * to be dispatched before it can determine whether input event injection will be
      * permitted based on the current input focus.
      * @param event The event to inject.
-     * @param nature The nature of the event.
      * @param sync If true, waits for the event to be completed before returning.
      * @param injectorPid The pid of the injecting application.
      * @param injectorUid The uid of the injecting application.
@@ -266,7 +264,7 @@
      * @param timeoutMillis The injection timeout in milliseconds.
      * @return One of the INPUT_EVENT_INJECTION_XXX constants.
      */
-    public int injectMotionEvent(MotionEvent event, int nature, int injectorPid, int injectorUid,
+    public int injectMotionEvent(MotionEvent event, int injectorPid, int injectorUid,
             boolean sync, int timeoutMillis) {
         if (event == null) {
             throw new IllegalArgumentException("event must not be null");
@@ -278,7 +276,7 @@
             throw new IllegalArgumentException("timeoutMillis must be positive");
         }
         
-        return nativeInjectMotionEvent(event, nature, injectorPid, injectorUid,
+        return nativeInjectMotionEvent(event, injectorPid, injectorUid,
                 sync, timeoutMillis);
     }
     
diff --git a/services/java/com/android/server/WindowManagerService.java b/services/java/com/android/server/WindowManagerService.java
index 3475b2f..0e5ff42 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;
@@ -2016,6 +2017,8 @@
             + ", surface=" + win.mSurface);
 
         final long origId = Binder.clearCallingIdentity();
+        
+        win.disposeInputChannel();
 
         if (DEBUG_APP_TRANSITIONS) Slog.v(
                 TAG, "Remove " + win + ": mSurface=" + win.mSurface
@@ -2076,8 +2079,6 @@
     }
 
     private void removeWindowInnerLocked(Session session, WindowState win) {
-        mInputMonitor.windowIsBeingRemovedLw(win);
-
         win.mRemoved = true;
 
         if (mInputMethodTarget == win) {
@@ -2156,6 +2157,8 @@
                 win.mAppToken.updateReportedVisibilityLocked();
             }
         }
+        
+        mInputMonitor.updateInputWindowsLw();
     }
 
     private static void logSurface(WindowState w, String msg, RuntimeException where) {
@@ -2906,7 +2909,6 @@
                         if (win.isVisibleNow()) {
                             applyAnimationLocked(win,
                                     WindowManagerPolicy.TRANSIT_EXIT, false);
-                            mInputMonitor.windowIsBeingRemovedLw(win);
                             changed = true;
                         }
                     }
@@ -2924,6 +2926,7 @@
                     }
                 }
 
+                mInputMonitor.updateInputWindowsLw();
             } else {
                 Slog.w(TAG, "Attempted to remove non-existing token: " + token);
             }
@@ -5109,7 +5112,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;
                 }
@@ -5286,11 +5289,6 @@
             }
         }
         
-        public void windowIsBeingRemovedLw(WindowState window) {
-            // Window is being removed.
-            updateInputWindowsLw();
-        }
-        
         public void pauseDispatchingLw(WindowToken window) {
             if (! window.paused) {
                 if (DEBUG_INPUT) {
@@ -5408,19 +5406,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);
@@ -5440,8 +5443,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);
@@ -5461,8 +5469,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);
@@ -6956,6 +6969,8 @@
         }
 
         void removeLocked() {
+            disposeInputChannel();
+            
             if (mAttachedWindow != null) {
                 mAttachedWindow.mChildWindows.remove(this);
             }
@@ -6967,7 +6982,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);
                 
diff --git a/services/jni/com_android_server_InputManager.cpp b/services/jni/com_android_server_InputManager.cpp
index 26e105a..bc052a0 100644
--- a/services/jni/com_android_server_InputManager.cpp
+++ b/services/jni/com_android_server_InputManager.cpp
@@ -354,7 +354,7 @@
 
     void releaseTouchedWindowLd();
 
-    int32_t waitForTrackballEventTargets(MotionEvent* motionEvent, uint32_t policyFlags,
+    int32_t waitForNonTouchEventTargets(MotionEvent* motionEvent, uint32_t policyFlags,
             int32_t injectorPid, int32_t injectorUid, Vector<InputTarget>& outTargets);
     int32_t waitForTouchEventTargets(MotionEvent* motionEvent, uint32_t policyFlags,
             int32_t injectorPid, int32_t injectorUid, Vector<InputTarget>& outTargets);
@@ -1222,14 +1222,17 @@
     return injectionResult;
 }
 
+enum InjectionPermission {
+    INJECTION_PERMISSION_UNKNOWN,
+    INJECTION_PERMISSION_GRANTED,
+    INJECTION_PERMISSION_DENIED
+};
+
 int32_t NativeInputManager::waitForTouchedWindowLd(MotionEvent* motionEvent, uint32_t policyFlags,
         int32_t injectorPid, int32_t injectorUid, Vector<InputTarget>& outTargets,
         InputWindow*& outTouchedWindow) {
     nsecs_t startTime = now();
 
-    int32_t injectionResult = INPUT_EVENT_INJECTION_SUCCEEDED;
-    int32_t action = motionEvent->getAction();
-
     // For security reasons, we defer updating the touch state until we are sure that
     // event injection will be allowed.
     //
@@ -1255,8 +1258,13 @@
     //       instead of POLICY_FLAG_WOKE_HERE...
     //
     bool screenWasOff = false; // original policy: policyFlags & POLICY_FLAG_BRIGHT_HERE;
+
+    int32_t action = motionEvent->getAction();
+
     bool firstIteration = true;
     ANRTimer anrTimer;
+    int32_t injectionResult;
+    InjectionPermission injectionPermission;
     for (;;) {
         if (firstIteration) {
             firstIteration = false;
@@ -1265,7 +1273,8 @@
                 LOGW("Dropping event because the dispatcher timed out waiting to identify "
                         "the window that should receive it.");
                 injectionResult = INPUT_EVENT_INJECTION_TIMED_OUT;
-                break;
+                injectionPermission = INJECTION_PERMISSION_UNKNOWN;
+                break; // timed out, exit wait loop
             }
         }
 
@@ -1273,6 +1282,7 @@
         if (! mDispatchEnabled) {
             LOGI("Dropping event because input dispatch is disabled.");
             injectionResult = INPUT_EVENT_INJECTION_FAILED;
+            injectionPermission = INJECTION_PERMISSION_UNKNOWN;
             break; // failed, exit wait loop
         }
 
@@ -1286,7 +1296,9 @@
         }
 
         // Update the touch state as needed based on the properties of the touch event.
-        if (action == MOTION_EVENT_ACTION_DOWN) {
+        if (action == AMOTION_EVENT_ACTION_DOWN) {
+            /* Case 1: ACTION_DOWN */
+
             InputWindow* newTouchedWindow = NULL;
             mTempTouchedOutsideWindows.clear();
 
@@ -1348,12 +1360,14 @@
 
                 LOGI("Dropping event because there is no touched window or focused application.");
                 injectionResult = INPUT_EVENT_INJECTION_FAILED;
+                injectionPermission = INJECTION_PERMISSION_UNKNOWN;
                 break; // failed, exit wait loop
             }
 
             // Check permissions.
             if (! checkInjectionPermission(newTouchedWindow, injectorPid, injectorUid)) {
                 injectionResult = INPUT_EVENT_INJECTION_PERMISSION_DENIED;
+                injectionPermission = INJECTION_PERMISSION_DENIED;
                 break; // failed, exit wait loop
             }
 
@@ -1374,18 +1388,33 @@
             if (newTouchedWindow->hasWallpaper) {
                 mTouchedWallpaperWindows.appendVector(mWallpaperWindows);
             }
+
+            injectionResult = INPUT_EVENT_INJECTION_SUCCEEDED;
+            injectionPermission = INJECTION_PERMISSION_GRANTED;
             break; // done
         } else {
+            /* Case 2: Everything but ACTION_DOWN */
+
             // Check permissions.
             if (! checkInjectionPermission(mTouchedWindow, injectorPid, injectorUid)) {
                 injectionResult = INPUT_EVENT_INJECTION_PERMISSION_DENIED;
+                injectionPermission = INJECTION_PERMISSION_DENIED;
+                break; // failed, exit wait loop
+            }
+
+            // If the pointer is not currently down, then ignore the event.
+            if (! mTouchDown) {
+                LOGI("Dropping event because the pointer is not down.");
+                injectionResult = INPUT_EVENT_INJECTION_FAILED;
+                injectionPermission = INJECTION_PERMISSION_GRANTED;
                 break; // failed, exit wait loop
             }
 
             // If there is no currently touched window then fail.
-            if (! mTouchedWindow || ! mTouchDown) {
-                LOGI("Dropping event because touched window is no longer valid.");
+            if (! mTouchedWindow) {
+                LOGW("Dropping event because there is no touched window to receive it.");
                 injectionResult = INPUT_EVENT_INJECTION_FAILED;
+                injectionPermission = INJECTION_PERMISSION_GRANTED;
                 break; // failed, exit wait loop
             }
 
@@ -1399,16 +1428,14 @@
             }
 
             // Success!
+            injectionResult = INPUT_EVENT_INJECTION_SUCCEEDED;
+            injectionPermission = INJECTION_PERMISSION_GRANTED;
             break; // done
         }
     }
 
     // Output targets.
-    bool havePermission;
     if (injectionResult == INPUT_EVENT_INJECTION_SUCCEEDED) {
-        // Injection succeeded so the injector must have permission.
-        havePermission = true;
-
         size_t numWallpaperWindows = mTouchedWallpaperWindows.size();
         for (size_t i = 0; i < numWallpaperWindows; i++) {
             addTarget(mTouchedWallpaperWindows[i], 0, 0, outTargets);
@@ -1423,25 +1450,23 @@
                 anrTimer.getTimeSpentWaitingForApplication(), outTargets);
         outTouchedWindow = mTouchedWindow;
     } else {
-        if (injectionResult != INPUT_EVENT_INJECTION_PERMISSION_DENIED
-                && checkInjectionPermission(NULL, injectorPid, injectorUid)) {
-            // Injection failed but the injector does have permission to inject events.
-            // While we might not have found a valid target for the injected event, we
-            // still want to update the dispatch state to take it into account.
-            havePermission = true;
-        } else {
-            // Injector does not have permission to inject events.
-            // We make sure to leave the dispatch state unchanged.
-            havePermission = false;
-        }
         outTouchedWindow = NULL;
     }
     mTempTouchedOutsideWindows.clear();
 
-    // Update final pieces of touch state now that we know for sure whether the injector
-    // had permission to perform the injection.
-    if (havePermission) {
-        if (action == MOTION_EVENT_ACTION_DOWN) {
+    // Check injection permission once and for all.
+    if (injectionPermission == INJECTION_PERMISSION_UNKNOWN) {
+        if (checkInjectionPermission(action == AMOTION_EVENT_ACTION_DOWN ? NULL : mTouchedWindow,
+                injectorPid, injectorUid)) {
+            injectionPermission = INJECTION_PERMISSION_GRANTED;
+        } else {
+            injectionPermission = INJECTION_PERMISSION_DENIED;
+        }
+    }
+
+    // Update final pieces of touch state if the injector had permission.
+    if (injectionPermission == INJECTION_PERMISSION_GRANTED) {
+        if (action == AMOTION_EVENT_ACTION_DOWN) {
             if (mTouchDown) {
                 // This is weird.  We got a down but we thought it was already down!
                 LOGW("Pointer down received while already down.");
@@ -1454,10 +1479,12 @@
                 // be holding on to an earlier target from a previous touch down.  Release it.
                 releaseTouchedWindowLd();
             }
-        } else if (action == MOTION_EVENT_ACTION_UP) {
+        } else if (action == AMOTION_EVENT_ACTION_UP) {
             mTouchDown = false;
             releaseTouchedWindowLd();
         }
+    } else {
+        LOGW("Not updating touch focus because injection was denied.");
     }
 
 #if DEBUG_FOCUS
@@ -1557,26 +1584,21 @@
             policyFlags, injectorPid, injectorUid);
 #endif
 
-    switch (motionEvent->getNature()) {
-    case INPUT_EVENT_NATURE_TRACKBALL:
-        return waitForTrackballEventTargets(motionEvent, policyFlags, injectorPid, injectorUid,
-                outTargets);
-
-    case INPUT_EVENT_NATURE_TOUCH:
+    int32_t source = motionEvent->getSource();
+    if (source & AINPUT_SOURCE_CLASS_POINTER) {
         return waitForTouchEventTargets(motionEvent, policyFlags, injectorPid, injectorUid,
                 outTargets);
-
-    default:
-        assert(false);
-        return INPUT_EVENT_INJECTION_FAILED;
+    } else {
+        return waitForNonTouchEventTargets(motionEvent, policyFlags, injectorPid, injectorUid,
+                outTargets);
     }
 }
 
-int32_t NativeInputManager::waitForTrackballEventTargets(MotionEvent* motionEvent,
+int32_t NativeInputManager::waitForNonTouchEventTargets(MotionEvent* motionEvent,
         uint32_t policyFlags, int32_t injectorPid, int32_t injectorUid,
         Vector<InputTarget>& outTargets) {
 #if DEBUG_INPUT_DISPATCHER_POLICY
-    LOGD("waitForTrackballEventTargets - policyFlags=%d, injectorPid=%d, injectorUid=%d",
+    LOGD("waitForNonTouchEventTargets - policyFlags=%d, injectorPid=%d, injectorUid=%d",
             policyFlags, injectorPid, injectorUid);
 #endif
 
@@ -1622,10 +1644,10 @@
 
     int32_t eventType;
     switch (motionEvent->getAction()) {
-    case MOTION_EVENT_ACTION_DOWN:
+    case AMOTION_EVENT_ACTION_DOWN:
         eventType = POWER_MANAGER_TOUCH_EVENT;
         break;
-    case MOTION_EVENT_ACTION_UP:
+    case AMOTION_EVENT_ACTION_UP:
         eventType = POWER_MANAGER_TOUCH_UP_EVENT;
         break;
     default:
@@ -1852,7 +1874,7 @@
 static jint android_server_InputManager_nativeGetScanCodeState(JNIEnv* env, jclass clazz,
         jint deviceId, jint deviceClasses, jint scanCode) {
     if (checkInputManagerUnitialized(env)) {
-        return KEY_STATE_UNKNOWN;
+        return AKEY_STATE_UNKNOWN;
     }
 
     return gNativeInputManager->getInputManager()->getScanCodeState(
@@ -1862,7 +1884,7 @@
 static jint android_server_InputManager_nativeGetKeyCodeState(JNIEnv* env, jclass clazz,
         jint deviceId, jint deviceClasses, jint keyCode) {
     if (checkInputManagerUnitialized(env)) {
-        return KEY_STATE_UNKNOWN;
+        return AKEY_STATE_UNKNOWN;
     }
 
     return gNativeInputManager->getInputManager()->getKeyCodeState(
@@ -1872,7 +1894,7 @@
 static jint android_server_InputManager_nativeGetSwitchState(JNIEnv* env, jclass clazz,
         jint deviceId, jint deviceClasses, jint sw) {
     if (checkInputManagerUnitialized(env)) {
-        return KEY_STATE_UNKNOWN;
+        return AKEY_STATE_UNKNOWN;
     }
 
     return gNativeInputManager->getInputManager()->getSwitchState(deviceId, deviceClasses, sw);
@@ -1963,28 +1985,28 @@
 }
 
 static jint android_server_InputManager_nativeInjectKeyEvent(JNIEnv* env, jclass clazz,
-        jobject keyEventObj, jint nature, jint injectorPid, jint injectorUid,
+        jobject keyEventObj, jint injectorPid, jint injectorUid,
         jboolean sync, jint timeoutMillis) {
     if (checkInputManagerUnitialized(env)) {
         return INPUT_EVENT_INJECTION_FAILED;
     }
 
     KeyEvent keyEvent;
-    android_view_KeyEvent_toNative(env, keyEventObj, nature, & keyEvent);
+    android_view_KeyEvent_toNative(env, keyEventObj, & keyEvent);
 
     return gNativeInputManager->getInputManager()->injectInputEvent(& keyEvent,
             injectorPid, injectorUid, sync, timeoutMillis);
 }
 
 static jint android_server_InputManager_nativeInjectMotionEvent(JNIEnv* env, jclass clazz,
-        jobject motionEventObj, jint nature, jint injectorPid, jint injectorUid,
+        jobject motionEventObj, jint injectorPid, jint injectorUid,
         jboolean sync, jint timeoutMillis) {
     if (checkInputManagerUnitialized(env)) {
         return INPUT_EVENT_INJECTION_FAILED;
     }
 
     MotionEvent motionEvent;
-    android_view_MotionEvent_toNative(env, motionEventObj, nature, & motionEvent);
+    android_view_MotionEvent_toNative(env, motionEventObj, & motionEvent);
 
     return gNativeInputManager->getInputManager()->injectInputEvent(& motionEvent,
             injectorPid, injectorUid, sync, timeoutMillis);
@@ -2050,9 +2072,9 @@
             (void*) android_server_InputManager_nativeRegisterInputChannel },
     { "nativeUnregisterInputChannel", "(Landroid/view/InputChannel;)V",
             (void*) android_server_InputManager_nativeUnregisterInputChannel },
-    { "nativeInjectKeyEvent", "(Landroid/view/KeyEvent;IIIZI)I",
+    { "nativeInjectKeyEvent", "(Landroid/view/KeyEvent;IIZI)I",
             (void*) android_server_InputManager_nativeInjectKeyEvent },
-    { "nativeInjectMotionEvent", "(Landroid/view/MotionEvent;IIIZI)I",
+    { "nativeInjectMotionEvent", "(Landroid/view/MotionEvent;IIZI)I",
             (void*) android_server_InputManager_nativeInjectMotionEvent },
     { "nativeSetInputWindows", "([Lcom/android/server/InputWindow;)V",
             (void*) android_server_InputManager_nativeSetInputWindows },