Recognize 3D joysticks.

Change-Id: Ie4eae09c0334f69c2ccfcf7eaede075f9ba02eab
diff --git a/data/keyboards/Generic.kl b/data/keyboards/Generic.kl
index 6d925d6..33947e7 100644
--- a/data/keyboards/Generic.kl
+++ b/data/keyboards/Generic.kl
@@ -261,6 +261,23 @@
 # key 239 "KEY_KBDILLUMUP"
 # key 240 "KEY_UNKNOWN"
 
+key 256   BUTTON_1
+key 257   BUTTON_2
+key 258   BUTTON_3
+key 259   BUTTON_4
+key 260   BUTTON_5
+key 261   BUTTON_6
+key 262   BUTTON_7
+key 263   BUTTON_8
+key 264   BUTTON_9
+key 265   BUTTON_10
+key 266   BUTTON_11
+key 267   BUTTON_12
+key 268   BUTTON_13
+key 269   BUTTON_14
+key 270   BUTTON_15
+key 271   BUTTON_16
+
 key 288   BUTTON_1
 key 289   BUTTON_2
 key 290   BUTTON_3
diff --git a/services/input/EventHub.cpp b/services/input/EventHub.cpp
index 2fe5980..d5f78a9 100644
--- a/services/input/EventHub.cpp
+++ b/services/input/EventHub.cpp
@@ -822,8 +822,10 @@
     bool haveKeyboardKeys = containsNonZeroByte(key_bitmask, 0, sizeof_bit_array(BTN_MISC))
             || containsNonZeroByte(key_bitmask, sizeof_bit_array(KEY_OK),
                     sizeof_bit_array(KEY_MAX + 1));
-    bool haveGamepadButtons =containsNonZeroByte(key_bitmask, sizeof_bit_array(BTN_JOYSTICK),
-                sizeof_bit_array(BTN_DIGI));
+    bool haveGamepadButtons = containsNonZeroByte(key_bitmask, sizeof_bit_array(BTN_MISC),
+                    sizeof_bit_array(BTN_MOUSE))
+            || containsNonZeroByte(key_bitmask, sizeof_bit_array(BTN_JOYSTICK),
+                    sizeof_bit_array(BTN_DIGI));
     if (haveKeyboardKeys || haveGamepadButtons) {
         device->classes |= INPUT_DEVICE_CLASS_KEYBOARD;
     }
@@ -852,6 +854,16 @@
         device->classes |= INPUT_DEVICE_CLASS_TOUCH;
     }
 
+    // See if this device is a joystick.
+    // Ignore touchscreens because they use the same absolute axes for other purposes.
+    // Assumes that joysticks always have gamepad buttons in order to distinguish them
+    // from other devices such as accelerometers that also have absolute axes.
+    if (haveGamepadButtons
+            && !(device->classes & INPUT_DEVICE_CLASS_TOUCH)
+            && containsNonZeroByte(abs_bitmask, 0, sizeof_bit_array(ABS_MAX + 1))) {
+        device->classes |= INPUT_DEVICE_CLASS_JOYSTICK;
+    }
+
     // figure out the switches this device reports
     bool haveSwitches = false;
     for (int i=0; i<EV_SW; i++) {
@@ -876,15 +888,21 @@
         }
     }
 
-    if ((device->classes & INPUT_DEVICE_CLASS_KEYBOARD) != 0) {
+    // Load the key map.
+    // We need to do this for joysticks too because the key layout may specify axes.
+    status_t keyMapStatus = NAME_NOT_FOUND;
+    if (device->classes & (INPUT_DEVICE_CLASS_KEYBOARD | INPUT_DEVICE_CLASS_JOYSTICK)) {
         // Load the keymap for the device.
-        status_t status = loadKeyMap(device);
+        keyMapStatus = loadKeyMap(device);
+    }
 
+    // Configure the keyboard, gamepad or virtual keyboard.
+    if (device->classes & INPUT_DEVICE_CLASS_KEYBOARD) {
         // Set system properties for the keyboard.
         setKeyboardProperties(device, false);
 
         // Register the keyboard as a built-in keyboard if it is eligible.
-        if (!status
+        if (!keyMapStatus
                 && mBuiltInKeyboardId == -1
                 && isEligibleBuiltInKeyboard(device->identifier,
                         device->configuration, &device->keyMap)) {
@@ -915,16 +933,6 @@
         }
     }
 
-    // See if this device is a joystick.
-    // Ignore touchscreens because they use the same absolute axes for other purposes.
-    // Assumes that joysticks always have buttons and the keymap has been loaded.
-    if (device->classes & INPUT_DEVICE_CLASS_GAMEPAD
-            && !(device->classes & INPUT_DEVICE_CLASS_TOUCH)) {
-        if (containsNonZeroByte(abs_bitmask, 0, sizeof_bit_array(ABS_MAX + 1))) {
-            device->classes |= INPUT_DEVICE_CLASS_JOYSTICK;
-        }
-    }
-
     // If the device isn't recognized as something we handle, don't monitor it.
     if (device->classes == 0) {
         LOGV("Dropping device: id=%d, path='%s', name='%s'",
diff --git a/services/input/InputReader.cpp b/services/input/InputReader.cpp
index 67074a3..084264b 100644
--- a/services/input/InputReader.cpp
+++ b/services/input/InputReader.cpp
@@ -945,6 +945,7 @@
 bool KeyboardInputMapper::isKeyboardOrGamepadKey(int32_t scanCode) {
     return scanCode < BTN_MOUSE
         || scanCode >= KEY_OK
+        || (scanCode >= BTN_MISC && scanCode < BTN_MOUSE)
         || (scanCode >= BTN_JOYSTICK && scanCode < BTN_DIGI);
 }