OSDN Git Service

Support composite touch / joystick devices better.
authorJeff Brown <jeffbrown@google.com>
Wed, 31 Aug 2011 19:56:34 +0000 (12:56 -0700)
committerJeff Brown <jeffbrown@google.com>
Wed, 31 Aug 2011 19:56:34 +0000 (12:56 -0700)
This change enables the joystick input mapper to handle any axes
that are not claimed by the touch input mapper, which makes
auxiliary controls such as wheels / knobs accessible.

Change-Id: I01ee7f342ac91acfcb4ccb6676fd52b3d5bf31a0

services/input/EventHub.cpp
services/input/EventHub.h
services/input/InputReader.cpp
services/input/InputReader.h
services/input/tests/InputReader_test.cpp

index 1d7cc19..157a997 100644 (file)
@@ -78,6 +78,40 @@ static inline const char* toString(bool value) {
     return value ? "true" : "false";
 }
 
+// --- Global Functions ---
+
+uint32_t getAbsAxisUsage(int32_t axis, uint32_t deviceClasses) {
+    // Touch devices get dibs on touch-related axes.
+    if (deviceClasses & INPUT_DEVICE_CLASS_TOUCH) {
+        switch (axis) {
+        case ABS_X:
+        case ABS_Y:
+        case ABS_PRESSURE:
+        case ABS_TOOL_WIDTH:
+        case ABS_DISTANCE:
+        case ABS_TILT_X:
+        case ABS_TILT_Y:
+        case ABS_MT_SLOT:
+        case ABS_MT_TOUCH_MAJOR:
+        case ABS_MT_TOUCH_MINOR:
+        case ABS_MT_WIDTH_MAJOR:
+        case ABS_MT_WIDTH_MINOR:
+        case ABS_MT_ORIENTATION:
+        case ABS_MT_POSITION_X:
+        case ABS_MT_POSITION_Y:
+        case ABS_MT_TOOL_TYPE:
+        case ABS_MT_BLOB_ID:
+        case ABS_MT_TRACKING_ID:
+        case ABS_MT_PRESSURE:
+        case ABS_MT_DISTANCE:
+            return INPUT_DEVICE_CLASS_TOUCH;
+        }
+    }
+
+    // Joystick devices get the rest.
+    return deviceClasses & INPUT_DEVICE_CLASS_JOYSTICK;
+}
+
 // --- EventHub::Device ---
 
 EventHub::Device::Device(int fd, int32_t id, const String8& path,
@@ -936,13 +970,17 @@ status_t EventHub::openDeviceLocked(const char *devicePath) {
     }
 
     // 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(device->absBitmask, 0, sizeof_bit_array(ABS_MAX + 1))) {
-        device->classes |= INPUT_DEVICE_CLASS_JOYSTICK;
+    if (haveGamepadButtons) {
+        uint32_t assumedClasses = device->classes | INPUT_DEVICE_CLASS_JOYSTICK;
+        for (int i = 0; i <= ABS_MAX; i++) {
+            if (test_bit(i, device->absBitmask)
+                    && (getAbsAxisUsage(i, assumedClasses) & INPUT_DEVICE_CLASS_JOYSTICK)) {
+                device->classes = assumedClasses;
+                break;
+            }
+        }
     }
 
     // Check whether this device has switches.
index fae5d4f..d37549a 100644 (file)
@@ -112,6 +112,12 @@ enum {
 };
 
 /*
+ * Gets the class that owns an axis, in cases where multiple classes might claim
+ * the same axis for different purposes.
+ */
+extern uint32_t getAbsAxisUsage(int32_t axis, uint32_t deviceClasses);
+
+/*
  * Grand Central Station for events.
  *
  * The event hub aggregates input events received across all known input
index e39712e..88c19a4 100644 (file)
@@ -390,7 +390,7 @@ void InputReader::removeDeviceLocked(nsecs_t when, int32_t deviceId) {
 
 InputDevice* InputReader::createDeviceLocked(int32_t deviceId,
         const String8& name, uint32_t classes) {
-    InputDevice* device = new InputDevice(&mContext, deviceId, name);
+    InputDevice* device = new InputDevice(&mContext, deviceId, name, classes);
 
     // External devices.
     if (classes & INPUT_DEVICE_CLASS_EXTERNAL) {
@@ -842,9 +842,10 @@ bool InputReaderThread::threadLoop() {
 
 // --- InputDevice ---
 
-InputDevice::InputDevice(InputReaderContext* context, int32_t id, const String8& name) :
-        mContext(context), mId(id), mName(name), mSources(0),
-        mIsExternal(false), mDropUntilNextSync(false) {
+InputDevice::InputDevice(InputReaderContext* context, int32_t id, const String8& name,
+        uint32_t classes) :
+        mContext(context), mId(id), mName(name), mClasses(classes),
+        mSources(0), mIsExternal(false), mDropUntilNextSync(false) {
 }
 
 InputDevice::~InputDevice() {
@@ -5759,6 +5760,11 @@ void JoystickInputMapper::configure(nsecs_t when,
     if (!changes) { // first time only
         // Collect all axes.
         for (int32_t abs = 0; abs <= ABS_MAX; abs++) {
+            if (!(getAbsAxisUsage(abs, getDevice()->getClasses())
+                    & INPUT_DEVICE_CLASS_JOYSTICK)) {
+                continue; // axis must be claimed by a different device
+            }
+
             RawAbsoluteAxisInfo rawAxisInfo;
             getAbsoluteAxisInfo(abs, &rawAxisInfo);
             if (rawAxisInfo.valid) {
index cd3ea37..a122c97 100644 (file)
@@ -430,12 +430,13 @@ private:
 /* Represents the state of a single input device. */
 class InputDevice {
 public:
-    InputDevice(InputReaderContext* context, int32_t id, const String8& name);
+    InputDevice(InputReaderContext* context, int32_t id, const String8& name, uint32_t classes);
     ~InputDevice();
 
     inline InputReaderContext* getContext() { return mContext; }
     inline int32_t getId() { return mId; }
     inline const String8& getName() { return mName; }
+    inline uint32_t getClasses() { return mClasses; }
     inline uint32_t getSources() { return mSources; }
 
     inline bool isExternal() { return mIsExternal; }
@@ -483,10 +484,11 @@ public:
 private:
     InputReaderContext* mContext;
     int32_t mId;
+    String8 mName;
+    uint32_t mClasses;
 
     Vector<InputMapper*> mMappers;
 
-    String8 mName;
     uint32_t mSources;
     bool mIsExternal;
     bool mDropUntilNextSync;
index 32f948b..a086208 100644 (file)
@@ -852,8 +852,8 @@ public:
         mNextDevice = device;
     }
 
-    InputDevice* newDevice(int32_t deviceId, const String8& name) {
-        return new InputDevice(&mContext, deviceId, name);
+    InputDevice* newDevice(int32_t deviceId, const String8& name, uint32_t classes) {
+        return new InputDevice(&mContext, deviceId, name, classes);
     }
 
 protected:
@@ -912,7 +912,7 @@ protected:
     FakeInputMapper* addDeviceWithFakeInputMapper(int32_t deviceId,
             const String8& name, uint32_t classes, uint32_t sources,
             const PropertyMap* configuration) {
-        InputDevice* device = mReader->newDevice(deviceId, name);
+        InputDevice* device = mReader->newDevice(deviceId, name, classes);
         FakeInputMapper* mapper = new FakeInputMapper(device, sources);
         device->addMapper(mapper);
         mReader->setNextDevice(device);
@@ -1211,6 +1211,7 @@ class InputDeviceTest : public testing::Test {
 protected:
     static const char* DEVICE_NAME;
     static const int32_t DEVICE_ID;
+    static const uint32_t DEVICE_CLASSES;
 
     sp<FakeEventHub> mFakeEventHub;
     sp<FakeInputReaderPolicy> mFakePolicy;
@@ -1226,7 +1227,7 @@ protected:
         mFakeContext = new FakeInputReaderContext(mFakeEventHub, mFakePolicy, mFakeListener);
 
         mFakeEventHub->addDevice(DEVICE_ID, String8(DEVICE_NAME), 0);
-        mDevice = new InputDevice(mFakeContext, DEVICE_ID, String8(DEVICE_NAME));
+        mDevice = new InputDevice(mFakeContext, DEVICE_ID, String8(DEVICE_NAME), DEVICE_CLASSES);
     }
 
     virtual void TearDown() {
@@ -1241,10 +1242,13 @@ protected:
 
 const char* InputDeviceTest::DEVICE_NAME = "device";
 const int32_t InputDeviceTest::DEVICE_ID = 1;
+const uint32_t InputDeviceTest::DEVICE_CLASSES = INPUT_DEVICE_CLASS_KEYBOARD
+        | INPUT_DEVICE_CLASS_TOUCH | INPUT_DEVICE_CLASS_JOYSTICK;
 
 TEST_F(InputDeviceTest, ImmutableProperties) {
     ASSERT_EQ(DEVICE_ID, mDevice->getId());
     ASSERT_STREQ(DEVICE_NAME, mDevice->getName());
+    ASSERT_EQ(DEVICE_CLASSES, mDevice->getClasses());
 }
 
 TEST_F(InputDeviceTest, WhenNoMappersAreRegistered_DeviceIsIgnored) {
@@ -1390,6 +1394,7 @@ class InputMapperTest : public testing::Test {
 protected:
     static const char* DEVICE_NAME;
     static const int32_t DEVICE_ID;
+    static const uint32_t DEVICE_CLASSES;
 
     sp<FakeEventHub> mFakeEventHub;
     sp<FakeInputReaderPolicy> mFakePolicy;
@@ -1402,7 +1407,7 @@ protected:
         mFakePolicy = new FakeInputReaderPolicy();
         mFakeListener = new FakeInputListener();
         mFakeContext = new FakeInputReaderContext(mFakeEventHub, mFakePolicy, mFakeListener);
-        mDevice = new InputDevice(mFakeContext, DEVICE_ID, String8(DEVICE_NAME));
+        mDevice = new InputDevice(mFakeContext, DEVICE_ID, String8(DEVICE_NAME), DEVICE_CLASSES);
 
         mFakeEventHub->addDevice(DEVICE_ID, String8(DEVICE_NAME), 0);
     }
@@ -1483,6 +1488,7 @@ protected:
 
 const char* InputMapperTest::DEVICE_NAME = "device";
 const int32_t InputMapperTest::DEVICE_ID = 1;
+const uint32_t InputMapperTest::DEVICE_CLASSES = 0; // not needed for current tests
 
 
 // --- SwitchInputMapperTest ---