Add support for mouse hover and scroll wheel.

Dispatch ACTION_HOVER_MOVE and ACTION_SCROLL through the View
hierarchy as onGenericTouchEvent.  Pointer events dispatched
this way are delivered to the view under the pointer.  Non-pointer
events continue to be delivered to the focused view.

Added scroll wheel support to AbsListView, ScrollView,
HorizontalScrollView and WebView.  Shift+VSCROLL is translated
to HSCROLL as appropriate.

Added logging of new pointer events in PointerLocationView.

Fixed a problem in EventHub when a USB device is removed that
resulted in a long stream of ENODEV errors being logged until INotify
noticed the device was gone.

Note that the new events are not supported by wallpapers at this time
because the wallpaper engine only delivers touch events.

Make all mouse buttons behave identically.  (Effectively we only
support one button.)

Change-Id: I9ab445ffb63c813fcb07db6693987b02475f3756
diff --git a/services/input/InputReader.cpp b/services/input/InputReader.cpp
index a963c72..a865d9f 100644
--- a/services/input/InputReader.cpp
+++ b/services/input/InputReader.cpp
@@ -1197,7 +1197,14 @@
     switch (rawEvent->type) {
     case EV_KEY:
         switch (rawEvent->scanCode) {
-        case BTN_MOUSE:
+        case BTN_LEFT:
+        case BTN_RIGHT:
+        case BTN_MIDDLE:
+        case BTN_SIDE:
+        case BTN_EXTRA:
+        case BTN_FORWARD:
+        case BTN_BACK:
+        case BTN_TASK:
             mAccumulator.fields |= Accumulator::FIELD_BTN_MOUSE;
             mAccumulator.btnMouse = rawEvent->value != 0;
             // Sync now since BTN_MOUSE is not necessarily followed by SYN_REPORT and
@@ -1247,6 +1254,7 @@
     int motionEventAction;
     PointerCoords pointerCoords;
     nsecs_t downTime;
+    float vscroll, hscroll;
     { // acquire lock
         AutoMutex _l(mLock);
 
@@ -1331,10 +1339,14 @@
         pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, mLocked.down ? 1.0f : 0.0f);
 
         if (mHaveVWheel && (fields & Accumulator::FIELD_REL_WHEEL)) {
-            pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_VSCROLL, mAccumulator.relWheel);
+            vscroll = mAccumulator.relWheel;
+        } else {
+            vscroll = 0;
         }
         if (mHaveHWheel && (fields & Accumulator::FIELD_REL_HWHEEL)) {
-            pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_HSCROLL, mAccumulator.relHWheel);
+            hscroll = mAccumulator.relHWheel;
+        } else {
+            hscroll = 0;
         }
     } // release lock
 
@@ -1345,6 +1357,15 @@
             1, &pointerId, &pointerCoords, mXPrecision, mYPrecision, downTime);
 
     mAccumulator.clear();
+
+    if (vscroll != 0 || hscroll != 0) {
+        pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_VSCROLL, vscroll);
+        pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_HSCROLL, hscroll);
+
+        getDispatcher()->notifyMotion(when, getDeviceId(), mSources, 0,
+                AMOTION_EVENT_ACTION_SCROLL, 0, metaState, AMOTION_EVENT_EDGE_FLAG_NONE,
+                1, &pointerId, &pointerCoords, mXPrecision, mYPrecision, downTime);
+    }
 }
 
 int32_t CursorInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {