Configure device classes for evdev devices.
Change-Id: Ia75b71253771d9d558c59411e27f8a51e352fb8b
diff --git a/tests/input/evdev/Android.mk b/tests/input/evdev/Android.mk
index 167cbc2..544e5a8 100644
--- a/tests/input/evdev/Android.mk
+++ b/tests/input/evdev/Android.mk
@@ -6,6 +6,7 @@
LOCAL_SRC_FILES:= \
InputDevice_test.cpp \
InputHub_test.cpp \
+ InputMocks.cpp \
TestHelpers.cpp
LOCAL_SHARED_LIBRARIES := \
diff --git a/tests/input/evdev/InputDevice_test.cpp b/tests/input/evdev/InputDevice_test.cpp
index a96d664..123f2b8 100644
--- a/tests/input/evdev/InputDevice_test.cpp
+++ b/tests/input/evdev/InputDevice_test.cpp
@@ -17,6 +17,8 @@
#define LOG_TAG "InputHub_test"
//#define LOG_NDEBUG 0
+#include <memory>
+
#include <linux/input.h>
#include <gtest/gtest.h>
@@ -24,7 +26,9 @@
#include <utils/Timers.h>
#include "InputDevice.h"
+#include "InputHost.h"
#include "InputHub.h"
+#include "InputMocks.h"
// # of milliseconds to allow for timing measurements
#define TIMING_TOLERANCE_MS 25
@@ -35,42 +39,23 @@
namespace android {
namespace tests {
-class MockInputDeviceNode : public InputDeviceNode {
- virtual const std::string& getPath() const override { return mPath; }
+class EvdevDeviceTest : public ::testing::Test {
+protected:
+ virtual void SetUp() override {
+ mMockHost.reset(new MockInputHost());
+ }
- virtual const std::string& getName() const override { return mName; }
- virtual const std::string& getLocation() const override { return mLocation; }
- virtual const std::string& getUniqueId() const override { return mUniqueId; }
+ virtual void TearDown() override {
+ ASSERT_TRUE(mMockHost->checkAllocations());
+ }
- virtual uint16_t getBusType() const override { return 0; }
- virtual uint16_t getVendorId() const override { return 0; }
- virtual uint16_t getProductId() const override { return 0; }
- virtual uint16_t getVersion() const override { return 0; }
-
- virtual bool hasKey(int32_t key) const { return false; }
- virtual bool hasRelativeAxis(int axis) const { return false; }
- virtual bool hasInputProperty(int property) const { return false; }
-
- virtual int32_t getKeyState(int32_t key) const { return 0; }
- virtual int32_t getSwitchState(int32_t sw) const { return 0; }
- virtual const AbsoluteAxisInfo* getAbsoluteAxisInfo(int32_t axis) const { return nullptr; }
- virtual status_t getAbsoluteAxisValue(int32_t axis, int32_t* outValue) const { return 0; }
-
- virtual void vibrate(nsecs_t duration) {}
- virtual void cancelVibrate(int32_t deviceId) {}
-
- virtual void disableDriverKeyRepeat() {}
-
-private:
- std::string mPath = "/test";
- std::string mName = "Test Device";
- std::string mLocation = "test/0";
- std::string mUniqueId = "test-id";
+ std::unique_ptr<MockInputHost> mMockHost;
};
-TEST(EvdevDeviceTest, testOverrideTime) {
+TEST_F(EvdevDeviceTest, testOverrideTime) {
+ InputHost host = {mMockHost.get(), kTestCallbacks};
auto node = std::make_shared<MockInputDeviceNode>();
- auto device = std::make_unique<EvdevDevice>(node);
+ auto device = std::make_unique<EvdevDevice>(host, node);
ASSERT_TRUE(device != nullptr);
// Send two timestamp override events before an input event.
@@ -97,9 +82,10 @@
EXPECT_EQ(when, keyUp.when);
}
-TEST(EvdevDeviceTest, testWrongClockCorrection) {
+TEST_F(EvdevDeviceTest, testWrongClockCorrection) {
+ InputHost host = {mMockHost.get(), kTestCallbacks};
auto node = std::make_shared<MockInputDeviceNode>();
- auto device = std::make_unique<EvdevDevice>(node);
+ auto device = std::make_unique<EvdevDevice>(host, node);
ASSERT_TRUE(device != nullptr);
auto now = systemTime(SYSTEM_TIME_MONOTONIC);
@@ -113,9 +99,10 @@
EXPECT_NEAR(now, event.when, ms2ns(TIMING_TOLERANCE_MS));
}
-TEST(EvdevDeviceTest, testClockCorrectionOk) {
+TEST_F(EvdevDeviceTest, testClockCorrectionOk) {
+ InputHost host = {mMockHost.get(), kTestCallbacks};
auto node = std::make_shared<MockInputDeviceNode>();
- auto device = std::make_unique<EvdevDevice>(node);
+ auto device = std::make_unique<EvdevDevice>(host, node);
ASSERT_TRUE(device != nullptr);
auto now = systemTime(SYSTEM_TIME_MONOTONIC);
@@ -130,5 +117,69 @@
EXPECT_NEAR(now, event.when, ms2ns(TIMING_TOLERANCE_MS));
}
+TEST_F(EvdevDeviceTest, testN7v2Touchscreen) {
+ InputHost host = {mMockHost.get(), kTestCallbacks};
+ auto node = std::shared_ptr<MockInputDeviceNode>(MockNexus7v2::getElanTouchscreen());
+ auto device = std::make_unique<EvdevDevice>(host, node);
+ EXPECT_EQ(INPUT_DEVICE_CLASS_TOUCH|INPUT_DEVICE_CLASS_TOUCH_MT,
+ device->getInputClasses());
+}
+
+TEST_F(EvdevDeviceTest, testN7v2ButtonJack) {
+ InputHost host = {mMockHost.get(), kTestCallbacks};
+ auto node = std::shared_ptr<MockInputDeviceNode>(MockNexus7v2::getButtonJack());
+ auto device = std::make_unique<EvdevDevice>(host, node);
+ EXPECT_EQ(INPUT_DEVICE_CLASS_KEYBOARD, device->getInputClasses());
+}
+
+TEST_F(EvdevDeviceTest, testN7v2HeadsetJack) {
+ InputHost host = {mMockHost.get(), kTestCallbacks};
+ auto node = std::shared_ptr<MockInputDeviceNode>(MockNexus7v2::getHeadsetJack());
+ auto device = std::make_unique<EvdevDevice>(host, node);
+ EXPECT_EQ(INPUT_DEVICE_CLASS_SWITCH, device->getInputClasses());
+}
+
+TEST_F(EvdevDeviceTest, testN7v2H2wButton) {
+ InputHost host = {mMockHost.get(), kTestCallbacks};
+ auto node = std::shared_ptr<MockInputDeviceNode>(MockNexus7v2::getH2wButton());
+ auto device = std::make_unique<EvdevDevice>(host, node);
+ EXPECT_EQ(INPUT_DEVICE_CLASS_KEYBOARD, device->getInputClasses());
+}
+
+TEST_F(EvdevDeviceTest, testN7v2GpioKeys) {
+ InputHost host = {mMockHost.get(), kTestCallbacks};
+ auto node = std::shared_ptr<MockInputDeviceNode>(MockNexus7v2::getGpioKeys());
+ auto device = std::make_unique<EvdevDevice>(host, node);
+ EXPECT_EQ(INPUT_DEVICE_CLASS_KEYBOARD, device->getInputClasses());
+}
+
+TEST_F(EvdevDeviceTest, testNexusPlayerGpioKeys) {
+ InputHost host = {mMockHost.get(), kTestCallbacks};
+ auto node = std::shared_ptr<MockInputDeviceNode>(MockNexusPlayer::getGpioKeys());
+ auto device = std::make_unique<EvdevDevice>(host, node);
+ EXPECT_EQ(INPUT_DEVICE_CLASS_KEYBOARD, device->getInputClasses());
+}
+
+TEST_F(EvdevDeviceTest, testNexusPlayerMidPowerBtn) {
+ InputHost host = {mMockHost.get(), kTestCallbacks};
+ auto node = std::shared_ptr<MockInputDeviceNode>(MockNexusPlayer::getMidPowerBtn());
+ auto device = std::make_unique<EvdevDevice>(host, node);
+ EXPECT_EQ(INPUT_DEVICE_CLASS_KEYBOARD, device->getInputClasses());
+}
+
+TEST_F(EvdevDeviceTest, testNexusRemote) {
+ InputHost host = {mMockHost.get(), kTestCallbacks};
+ auto node = std::shared_ptr<MockInputDeviceNode>(MockNexusPlayer::getNexusRemote());
+ auto device = std::make_unique<EvdevDevice>(host, node);
+ EXPECT_EQ(INPUT_DEVICE_CLASS_KEYBOARD, device->getInputClasses());
+}
+
+TEST_F(EvdevDeviceTest, testAsusGamepad) {
+ InputHost host = {mMockHost.get(), kTestCallbacks};
+ auto node = std::shared_ptr<MockInputDeviceNode>(MockNexusPlayer::getAsusGamepad());
+ auto device = std::make_unique<EvdevDevice>(host, node);
+ EXPECT_EQ(INPUT_DEVICE_CLASS_JOYSTICK|INPUT_DEVICE_CLASS_KEYBOARD, device->getInputClasses());
+}
+
} // namespace tests
} // namespace android
diff --git a/tests/input/evdev/InputHub_test.cpp b/tests/input/evdev/InputHub_test.cpp
index f2967b9..5864a95 100644
--- a/tests/input/evdev/InputHub_test.cpp
+++ b/tests/input/evdev/InputHub_test.cpp
@@ -30,6 +30,7 @@
#include <utils/Timers.h>
#include "InputHub.h"
+#include "InputHub-internal.h"
#include "TestHelpers.h"
// # of milliseconds to fudge stopwatch measurements
@@ -256,5 +257,63 @@
EXPECT_TRUE(deviceCallbackFinished);
}
+using internal::testBitInRange;
+
+TEST(BitInRange, testInvalidRange) {
+ uint8_t arr[2] = { 0xff, 0xff };
+ EXPECT_FALSE(testBitInRange(arr, 0, 0));
+ EXPECT_FALSE(testBitInRange(arr, 1, 0));
+}
+
+TEST(BitInRange, testNoBits) {
+ uint8_t arr[1];
+ arr[0] = 0;
+ EXPECT_FALSE(testBitInRange(arr, 0, 8));
+}
+
+TEST(BitInRange, testOneBit) {
+ uint8_t arr[1];
+ for (int i = 0; i < 8; ++i) {
+ arr[0] = 1 << i;
+ EXPECT_TRUE(testBitInRange(arr, 0, 8));
+ }
+}
+
+TEST(BitInRange, testZeroStart) {
+ uint8_t arr[1] = { 0x10 };
+ for (int i = 0; i < 5; ++i) {
+ EXPECT_FALSE(testBitInRange(arr, 0, i));
+ }
+ for (int i = 5; i <= 8; ++i) {
+ EXPECT_TRUE(testBitInRange(arr, 0, i));
+ }
+}
+
+TEST(BitInRange, testByteBoundaryEnd) {
+ uint8_t arr[1] = { 0x10 };
+ for (int i = 0; i < 5; ++i) {
+ EXPECT_TRUE(testBitInRange(arr, i, 8));
+ }
+ for (int i = 5; i <= 8; ++i) {
+ EXPECT_FALSE(testBitInRange(arr, i, 8));
+ }
+}
+
+TEST(BitInRange, testMultiByteArray) {
+ // bits set: 11 and 16
+ uint8_t arr[3] = { 0x00, 0x08, 0x01 };
+ for (int start = 0; start < 24; ++start) {
+ for (int end = start + 1; end <= 24; ++end) {
+ if (start > 16 || end <= 11 || (start > 11 && end <= 16)) {
+ EXPECT_FALSE(testBitInRange(arr, start, end))
+ << "range = (" << start << ", " << end << ")";
+ } else {
+ EXPECT_TRUE(testBitInRange(arr, start, end))
+ << "range = (" << start << ", " << end << ")";
+ }
+ }
+ }
+}
+
} // namespace tests
} // namespace android
diff --git a/tests/input/evdev/InputMocks.cpp b/tests/input/evdev/InputMocks.cpp
new file mode 100644
index 0000000..c316075
--- /dev/null
+++ b/tests/input/evdev/InputMocks.cpp
@@ -0,0 +1,406 @@
+#include "InputMocks.h"
+
+// Private test definitions of opaque HAL structs
+
+// Not used
+struct input_property_map {};
+
+// Holds the key and value from the mock host's PropertyMap
+struct input_property {
+ android::String8 key;
+ android::String8 value;
+};
+
+namespace android {
+
+bool MockInputHost::checkAllocations() const {
+ bool ret = true;
+ if (mMapAllocations != 0) {
+ ALOGE("Leaked %d device property map allocations", mMapAllocations);
+ ret = false;
+ }
+ for (auto entry : mPropertyAllocations) {
+ if (entry.second != 0) {
+ ALOGE("Leaked %d property allocation for %s", entry.second, entry.first.c_str());
+ ret = false;
+ }
+ }
+ return ret;
+}
+
+input_device_identifier_t* MockInputHost::createDeviceIdentifier(
+ const char* name, int32_t product_id, int32_t vendor_id,
+ input_bus_t bus, const char* unique_id) {
+ mDeviceId.reset(new input_device_identifier_t{
+ .name = name,
+ .productId = product_id,
+ .vendorId = vendor_id,
+ .bus = bus,
+ .uniqueId = unique_id
+ });
+ // Just return the raw pointer. We don't have a method for deallocating
+ // device identifiers yet, and they should exist throughout the lifetime of
+ // the input process for now.
+ return mDeviceId.get();
+}
+
+input_property_map_t* MockInputHost::getDevicePropertyMap(input_device_identifier_t* id) {
+ mMapAllocations++;
+ // Handled in the MockInputHost.
+ return nullptr;
+}
+
+input_property_t* MockInputHost::getDeviceProperty(input_property_map_t* map, const char* key) {
+ mPropertyAllocations[key]++;
+ return new input_property_t{.key = String8(key)};
+}
+
+const char* MockInputHost::getPropertyKey(input_property_t* property) {
+ return property->key.string();
+}
+
+const char* MockInputHost::getPropertyValue(input_property_t* property) {
+ if (!mDevicePropertyMap.tryGetProperty(property->key, property->value)) {
+ return nullptr;
+ }
+ return property->value.string();
+}
+
+void MockInputHost::freeDeviceProperty(input_property_t* property) {
+ if (property != nullptr) {
+ mPropertyAllocations[property->key.string()]--;
+ delete property;
+ }
+}
+
+void MockInputHost::freeDevicePropertyMap(input_property_map_t* map) {
+ mMapAllocations--;
+}
+
+input_host_callbacks_t kTestCallbacks = {
+ .create_device_identifier = create_device_identifier,
+ .create_device_definition = create_device_definition,
+ .create_input_report_definition = create_input_report_definition,
+ .create_output_report_definition = create_output_report_definition,
+ .input_device_definition_add_report = input_device_definition_add_report,
+ .input_report_definition_add_collection = input_report_definition_add_collection,
+ .input_report_definition_declare_usage_int = input_report_definition_declare_usage_int,
+ .input_report_definition_declare_usages_bool = input_report_definition_declare_usages_bool,
+ .register_device = register_device,
+ .input_allocate_report = input_allocate_report,
+ .input_report_set_usage_int = input_report_set_usage_int,
+ .input_report_set_usage_bool = input_report_set_usage_bool,
+ .report_event = report_event,
+ .input_get_device_property_map = input_get_device_property_map,
+ .input_get_device_property = input_get_device_property,
+ .input_get_property_key = input_get_property_key,
+ .input_get_property_value = input_get_property_value,
+ .input_free_device_property = input_free_device_property,
+ .input_free_device_property_map = input_free_device_property_map,
+};
+
+bool MockInputDeviceNode::hasKeyInRange(int32_t startKey, int32_t endKey) const {
+ auto iter = mKeys.lower_bound(startKey);
+ if (iter == mKeys.end()) return false;
+ return *iter < endKey;
+}
+
+namespace MockNexus7v2 {
+
+MockInputDeviceNode* getElanTouchscreen() {
+ auto node = new MockInputDeviceNode();
+ node->setPath("/dev/input/event0");
+ node->setName("elan-touchscreen");
+ // Location not set
+ // UniqueId not set
+ node->setBusType(0);
+ node->setVendorId(0);
+ node->setProductId(0);
+ node->setVersion(0);
+ // No keys
+ // No relative axes
+ // TODO: set the AbsoluteAxisInfo pointers
+ node->addAbsAxis(ABS_MT_SLOT, nullptr);
+ node->addAbsAxis(ABS_MT_TOUCH_MAJOR, nullptr);
+ node->addAbsAxis(ABS_MT_POSITION_X, nullptr);
+ node->addAbsAxis(ABS_MT_POSITION_Y, nullptr);
+ node->addAbsAxis(ABS_MT_TRACKING_ID, nullptr);
+ node->addAbsAxis(ABS_MT_PRESSURE, nullptr);
+ // No switches
+ // No forcefeedback
+ node->addInputProperty(INPUT_PROP_DIRECT);
+ return node;
+}
+
+MockInputDeviceNode* getLidInput() {
+ auto node = new MockInputDeviceNode();
+ node->setPath("/dev/input/event1");
+ node->setName("lid_input");
+ node->setLocation("/dev/input/lid_indev");
+ // UniqueId not set
+ node->setBusType(0);
+ node->setVendorId(0);
+ node->setProductId(0);
+ node->setVersion(0);
+ // No keys
+ // No relative axes
+ // No absolute axes
+ node->addSwitch(SW_LID);
+ // No forcefeedback
+ node->addInputProperty(INPUT_PROP_DIRECT);
+ return node;
+}
+
+MockInputDeviceNode* getButtonJack() {
+ auto node = new MockInputDeviceNode();
+ node->setPath("/dev/input/event2");
+ node->setName("apq8064-tabla-snd-card Button Jack");
+ node->setLocation("ALSA");
+ // UniqueId not set
+ node->setBusType(0);
+ node->setVendorId(0);
+ node->setProductId(0);
+ node->setVersion(0);
+ node->addKeys(BTN_0, BTN_1, BTN_2, BTN_3, BTN_4, BTN_5, BTN_6, BTN_7);
+ // No relative axes
+ // No absolute axes
+ // No switches
+ // No forcefeedback
+ node->addInputProperty(INPUT_PROP_DIRECT);
+ return node;
+}
+
+MockInputDeviceNode* getHeadsetJack() {
+ auto node = new MockInputDeviceNode();
+ node->setPath("/dev/input/event3");
+ node->setName("apq8064-tabla-snd-card Headset Jack");
+ node->setLocation("ALSA");
+ // UniqueId not set
+ node->setBusType(0);
+ node->setVendorId(0);
+ node->setProductId(0);
+ node->setVersion(0);
+ // No keys
+ // No relative axes
+ // No absolute axes
+ node->addSwitch(SW_HEADPHONE_INSERT);
+ node->addSwitch(SW_MICROPHONE_INSERT);
+ node->addSwitch(SW_LINEOUT_INSERT);
+ // ASUS adds some proprietary switches, but we'll only see two of them.
+ node->addSwitch(0x0e); // SW_HPHL_OVERCURRENT
+ node->addSwitch(0x0f); // SW_HPHR_OVERCURRENT
+ // No forcefeedback
+ node->addInputProperty(INPUT_PROP_DIRECT);
+ return node;
+}
+
+MockInputDeviceNode* getH2wButton() {
+ auto node = new MockInputDeviceNode();
+ node->setPath("/dev/input/event4");
+ node->setName("h2w button");
+ // Location not set
+ // UniqueId not set
+ node->setBusType(0);
+ node->setVendorId(0);
+ node->setProductId(0);
+ node->setVersion(0);
+ node->addKeys(KEY_MEDIA);
+ // No relative axes
+ // No absolute axes
+ // No switches
+ node->addInputProperty(INPUT_PROP_DIRECT);
+ return node;
+}
+
+MockInputDeviceNode* getGpioKeys() {
+ auto node = new MockInputDeviceNode();
+ node->setPath("/dev/input/event5");
+ node->setName("gpio-keys");
+ node->setLocation("gpio-keys/input0");
+ // UniqueId not set
+ node->setBusType(0x0019);
+ node->setVendorId(0x0001);
+ node->setProductId(0x0001);
+ node->setVersion(0x0100);
+ node->addKeys(KEY_VOLUMEDOWN, KEY_VOLUMEUP, KEY_POWER);
+ // No relative axes
+ // No absolute axes
+ // No switches
+ node->addInputProperty(INPUT_PROP_DIRECT);
+ return node;
+}
+
+} // namespace MockNexus7v2
+
+namespace MockNexusPlayer {
+
+MockInputDeviceNode* getGpioKeys() {
+ auto node = new MockInputDeviceNode();
+ node->setPath("/dev/input/event0");
+ node->setName("gpio-keys");
+ node->setLocation("gpio-keys/input0");
+ // UniqueId not set
+ node->setBusType(0x0019);
+ node->setVendorId(0x0001);
+ node->setProductId(0x0001);
+ node->setVersion(0x0100);
+ node->addKeys(KEY_CONNECT);
+ // No relative axes
+ // No absolute axes
+ // No switches
+ node->addInputProperty(INPUT_PROP_DIRECT);
+ return node;
+}
+
+MockInputDeviceNode* getMidPowerBtn() {
+ auto node = new MockInputDeviceNode();
+ node->setPath("/dev/input/event1");
+ node->setName("mid_powerbtn");
+ node->setLocation("power-button/input0");
+ // UniqueId not set
+ node->setBusType(0x0019);
+ node->setVendorId(0);
+ node->setProductId(0);
+ node->setVersion(0);
+ node->addKeys(KEY_POWER);
+ // No relative axes
+ // No absolute axes
+ // No switches
+ node->addInputProperty(INPUT_PROP_DIRECT);
+ return node;
+}
+
+MockInputDeviceNode* getNexusRemote() {
+ auto node = new MockInputDeviceNode();
+ node->setPath("/dev/input/event2");
+ node->setName("Nexus Remote");
+ // Location not set
+ node->setUniqueId("78:86:D9:50:A0:54");
+ node->setBusType(0x0005);
+ node->setVendorId(0x18d1);
+ node->setProductId(0x2c42);
+ node->setVersion(0);
+ node->addKeys(KEY_UP, KEY_LEFT, KEY_RIGHT, KEY_DOWN, KEY_BACK, KEY_PLAYPAUSE,
+ KEY_HOMEPAGE, KEY_SEARCH, KEY_SELECT);
+ // No relative axes
+ node->addAbsAxis(ABS_MISC, nullptr);
+ // No switches
+ node->addInputProperty(INPUT_PROP_DIRECT);
+ return node;
+}
+
+MockInputDeviceNode* getAsusGamepad() {
+ auto node = new MockInputDeviceNode();
+ node->setPath("/dev/input/event3");
+ node->setName("ASUS Gamepad");
+ // Location not set
+ node->setUniqueId("C5:30:CD:50:A0:54");
+ node->setBusType(0x0005);
+ node->setVendorId(0x0b05);
+ node->setProductId(0x4500);
+ node->setVersion(0x0040);
+ node->addKeys(KEY_BACK, KEY_HOMEPAGE, BTN_A, BTN_B, BTN_X, BTN_Y, BTN_TL, BTN_TR,
+ BTN_MODE, BTN_THUMBL, BTN_THUMBR);
+ // No relative axes
+ node->addAbsAxis(ABS_X, nullptr);
+ node->addAbsAxis(ABS_Y, nullptr);
+ node->addAbsAxis(ABS_Z, nullptr);
+ node->addAbsAxis(ABS_RZ, nullptr);
+ node->addAbsAxis(ABS_GAS, nullptr);
+ node->addAbsAxis(ABS_BRAKE, nullptr);
+ node->addAbsAxis(ABS_HAT0X, nullptr);
+ node->addAbsAxis(ABS_HAT0Y, nullptr);
+ node->addAbsAxis(ABS_MISC, nullptr);
+ node->addAbsAxis(0x29, nullptr);
+ node->addAbsAxis(0x2a, nullptr);
+ // No switches
+ node->addInputProperty(INPUT_PROP_DIRECT);
+ // Note: this device has MSC and LED bitmaps as well.
+ return node;
+}
+
+} // namespace MockNexusPlayer
+
+::input_device_identifier_t* create_device_identifier(input_host_t* host,
+ const char* name, int32_t product_id, int32_t vendor_id,
+ input_bus_t bus, const char* unique_id) {
+ auto mockHost = static_cast<MockInputHost*>(host);
+ return mockHost->createDeviceIdentifier(name, product_id, vendor_id, bus, unique_id);
+}
+
+input_device_definition_t* create_device_definition(input_host_t* host) {
+ return nullptr;
+}
+
+input_report_definition_t* create_input_report_definition(input_host_t* host) {
+ return nullptr;
+}
+
+input_report_definition_t* create_output_report_definition(input_host_t* host) {
+ return nullptr;
+}
+
+void input_device_definition_add_report(input_host_t* host,
+ input_device_definition_t* d, input_report_definition_t* r) { }
+
+void input_report_definition_add_collection(input_host_t* host,
+ input_report_definition_t* report, input_collection_id_t id, int32_t arity) { }
+
+void input_report_definition_declare_usage_int(input_host_t* host,
+ input_report_definition_t* report, input_collection_id_t id,
+ input_usage_t usage, int32_t min, int32_t max, float resolution) { }
+
+void input_report_definition_declare_usages_bool(input_host_t* host,
+ input_report_definition_t* report, input_collection_id_t id,
+ input_usage_t* usage, size_t usage_count) { }
+
+
+input_device_handle_t* register_device(input_host_t* host,
+ input_device_identifier_t* id, input_device_definition_t* d) {
+ return nullptr;
+}
+
+input_report_t* input_allocate_report(input_host_t* host, input_report_definition_t* r) {
+ return nullptr;
+}
+void input_report_set_usage_int(input_host_t* host, input_report_t* r,
+ input_collection_id_t id, input_usage_t usage, int32_t value, int32_t arity_index) { }
+
+void input_report_set_usage_bool(input_host_t* host, input_report_t* r,
+ input_collection_id_t id, input_usage_t usage, bool value, int32_t arity_index) { }
+
+void report_event(input_host_t* host, input_device_handle_t* d, input_report_t* report) { }
+
+input_property_map_t* input_get_device_property_map(input_host_t* host,
+ input_device_identifier_t* id) {
+ auto mockHost = static_cast<MockInputHost*>(host);
+ return mockHost->getDevicePropertyMap(id);
+}
+
+input_property_t* input_get_device_property(input_host_t* host, input_property_map_t* map,
+ const char* key) {
+ auto mockHost = static_cast<MockInputHost*>(host);
+ return mockHost->getDeviceProperty(map, key);
+}
+
+const char* input_get_property_key(input_host_t* host, input_property_t* property) {
+ auto mockHost = static_cast<MockInputHost*>(host);
+ return mockHost->getPropertyKey(property);
+}
+
+const char* input_get_property_value(input_host_t* host, input_property_t* property) {
+ auto mockHost = static_cast<MockInputHost*>(host);
+ return mockHost->getPropertyValue(property);
+}
+
+void input_free_device_property(input_host_t* host, input_property_t* property) {
+ auto mockHost = static_cast<MockInputHost*>(host);
+ return mockHost->freeDeviceProperty(property);
+}
+
+void input_free_device_property_map(input_host_t* host, input_property_map_t* map) {
+ auto mockHost = static_cast<MockInputHost*>(host);
+ return mockHost->freeDevicePropertyMap(map);
+}
+
+} // namespace android
diff --git a/tests/input/evdev/InputMocks.h b/tests/input/evdev/InputMocks.h
new file mode 100644
index 0000000..5c6eb80
--- /dev/null
+++ b/tests/input/evdev/InputMocks.h
@@ -0,0 +1,256 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+#ifndef ANDROID_INPUT_MOCKS_H_
+#define ANDROID_INPUT_MOCKS_H_
+
+#include <map>
+#include <memory>
+#include <set>
+#include <string>
+#include <unordered_map>
+
+#include <linux/input.h>
+
+#include <hardware/input.h>
+#include <utils/PropertyMap.h>
+
+#include "InputHub.h"
+
+// Test definitions of opaque HAL structs
+struct input_host {};
+struct input_device_identifier {
+ const char* name;
+ const char* uniqueId;
+ input_bus_t bus;
+ int32_t vendorId;
+ int32_t productId;
+ int32_t version;
+};
+
+
+namespace android {
+
+extern input_host_callbacks_t kTestCallbacks;
+
+class MockInputHost : public ::input_host_t {
+public:
+ virtual ~MockInputHost() = default;
+
+ void addDeviceProperty(const std::string& key, const std::string& value) {
+ mDevicePropertyMap.addProperty(String8(key.c_str()), String8(value.c_str()));
+ }
+
+ /**
+ * Call this at the end of a test to verify that any allocations made
+ * during the test were freed.
+ */
+ bool checkAllocations() const;
+
+ // Callbacks
+ input_device_identifier_t* createDeviceIdentifier(
+ const char* name, int32_t product_id, int32_t vendor_id,
+ input_bus_t bus, const char* unique_id);
+
+ input_property_map_t* getDevicePropertyMap(input_device_identifier_t* id);
+
+ input_property_t* getDeviceProperty(input_property_map_t* map, const char* key);
+
+ const char* getPropertyKey(input_property_t* property);
+
+ const char* getPropertyValue(input_property_t* property);
+
+ void freeDeviceProperty(input_property_t* property);
+
+ void freeDevicePropertyMap(input_property_map_t* map);
+
+private:
+ PropertyMap mDevicePropertyMap;
+ std::unique_ptr<input_device_identifier_t> mDeviceId;
+ int32_t mMapAllocations = 0;
+ std::unordered_map<std::string, int32_t> mPropertyAllocations;
+};
+
+class MockInputDeviceNode : public InputDeviceNode {
+public:
+ MockInputDeviceNode() = default;
+ virtual ~MockInputDeviceNode() = default;
+
+ virtual const std::string& getPath() const override { return mPath; }
+ virtual const std::string& getName() const override { return mName; }
+ virtual const std::string& getLocation() const override { return mLocation; }
+ virtual const std::string& getUniqueId() const override { return mUniqueId; }
+
+ void setPath(const std::string& path) { mPath = path; }
+ void setName(const std::string& name) { mName = name; }
+ void setLocation(const std::string& location) { mLocation = location; }
+ void setUniqueId(const std::string& uniqueId) { mUniqueId = uniqueId; }
+
+ virtual uint16_t getBusType() const override { return mBusType; }
+ virtual uint16_t getVendorId() const override { return mVendorId; }
+ virtual uint16_t getProductId() const override { return mProductId; }
+ virtual uint16_t getVersion() const override { return mVersion; }
+
+ void setBusType(uint16_t busType) { mBusType = busType; }
+ void setVendorId(uint16_t vendorId) { mVendorId = vendorId; }
+ void setProductId(uint16_t productId) { mProductId = productId; }
+ void setVersion(uint16_t version) { mVersion = version; }
+
+ virtual bool hasKey(int32_t key) const override { return mKeys.count(key); }
+ virtual bool hasKeyInRange(int32_t startKey, int32_t endKey) const override;
+ virtual bool hasRelativeAxis(int axis) const override { return mRelAxes.count(axis); }
+ virtual bool hasAbsoluteAxis(int32_t axis) const override { return mAbsAxes.count(axis); }
+ virtual bool hasSwitch(int32_t sw) const override { return mSwitches.count(sw); }
+ virtual bool hasForceFeedback(int32_t ff) const override { return mForceFeedbacks.count(ff); }
+ virtual bool hasInputProperty(int32_t property) const override {
+ return mInputProperties.count(property);
+ }
+
+ // base case
+ void addKeys() {}
+ // inductive case
+ template<typename I, typename... Is>
+ void addKeys(I key, Is... keys) {
+ // Add the first key
+ mKeys.insert(key);
+ // Recursively add the remaining keys
+ addKeys(keys...);
+ }
+
+ void addRelAxis(int32_t axis) { mRelAxes.insert(axis); }
+ void addAbsAxis(int32_t axis, AbsoluteAxisInfo* info) { mAbsAxes[axis] = info; }
+ void addSwitch(int32_t sw) { mSwitches.insert(sw); }
+ void addForceFeedback(int32_t ff) { mForceFeedbacks.insert(ff); }
+ void addInputProperty(int32_t property) { mInputProperties.insert(property); }
+
+ virtual int32_t getKeyState(int32_t key) const override { return 0; }
+ virtual int32_t getSwitchState(int32_t sw) const override { return 0; }
+ virtual const AbsoluteAxisInfo* getAbsoluteAxisInfo(int32_t axis) const override {
+ auto iter = mAbsAxes.find(axis);
+ if (iter != mAbsAxes.end()) {
+ return iter->second;
+ }
+ return nullptr;
+ }
+ virtual status_t getAbsoluteAxisValue(int32_t axis, int32_t* outValue) const override {
+ // TODO
+ return 0;
+ }
+
+ virtual void vibrate(nsecs_t duration) override {}
+ virtual void cancelVibrate() override {}
+
+ virtual void disableDriverKeyRepeat() override { mKeyRepeatDisabled = true; }
+
+ bool isDriverKeyRepeatEnabled() { return mKeyRepeatDisabled; }
+
+private:
+ std::string mPath = "/test";
+ std::string mName = "Test Device";
+ std::string mLocation = "test/0";
+ std::string mUniqueId = "test-id";
+
+ uint16_t mBusType = 0;
+ uint16_t mVendorId = 0;
+ uint16_t mProductId = 0;
+ uint16_t mVersion = 0;
+
+ std::set<int32_t> mKeys;
+ std::set<int32_t> mRelAxes;
+ std::map<int32_t, AbsoluteAxisInfo*> mAbsAxes;
+ std::set<int32_t> mSwitches;
+ std::set<int32_t> mForceFeedbacks;
+ std::set<int32_t> mInputProperties;
+
+ bool mKeyRepeatDisabled = false;
+};
+
+namespace MockNexus7v2 {
+MockInputDeviceNode* getElanTouchscreen();
+MockInputDeviceNode* getLidInput();
+MockInputDeviceNode* getButtonJack();
+MockInputDeviceNode* getHeadsetJack();
+MockInputDeviceNode* getH2wButton();
+MockInputDeviceNode* getGpioKeys();
+} // namespace MockNexus7v2
+
+namespace MockNexusPlayer {
+MockInputDeviceNode* getGpioKeys();
+MockInputDeviceNode* getMidPowerBtn();
+MockInputDeviceNode* getNexusRemote();
+MockInputDeviceNode* getAsusGamepad();
+} // namespace MockNexusPlayer
+
+// HAL method prototypes used in mock callbacks
+extern "C" {
+input_device_identifier_t* create_device_identifier(input_host_t* host,
+ const char* name, int32_t product_id, int32_t vendor_id,
+ input_bus_t bus, const char* unique_id);
+
+input_device_definition_t* create_device_definition(input_host_t* host);
+
+input_report_definition_t* create_input_report_definition(input_host_t* host);
+
+input_report_definition_t* create_output_report_definition(input_host_t* host);
+
+void input_device_definition_add_report(input_host_t* host,
+ input_device_definition_t* d, input_report_definition_t* r);
+
+void input_report_definition_add_collection(input_host_t* host,
+ input_report_definition_t* report, input_collection_id_t id, int32_t arity);
+
+void input_report_definition_declare_usage_int(input_host_t* host,
+ input_report_definition_t* report, input_collection_id_t id,
+ input_usage_t usage, int32_t min, int32_t max, float resolution);
+
+void input_report_definition_declare_usages_bool(input_host_t* host,
+ input_report_definition_t* report, input_collection_id_t id,
+ input_usage_t* usage, size_t usage_count);
+
+
+input_device_handle_t* register_device(input_host_t* host,
+ input_device_identifier_t* id, input_device_definition_t* d);
+
+void unregister_device(input_host_t* host, input_device_handle_t* handle);
+
+input_report_t* input_allocate_report(input_host_t* host, input_report_definition_t* r);
+
+void input_report_set_usage_int(input_host_t* host, input_report_t* r,
+ input_collection_id_t id, input_usage_t usage, int32_t value, int32_t arity_index);
+
+void input_report_set_usage_bool(input_host_t* host, input_report_t* r,
+ input_collection_id_t id, input_usage_t usage, bool value, int32_t arity_index);
+
+void report_event(input_host_t* host, input_device_handle_t* d, input_report_t* report);
+
+input_property_map_t* input_get_device_property_map(input_host_t* host,
+ input_device_identifier_t* id);
+
+input_property_t* input_get_device_property(input_host_t* host, input_property_map_t* map,
+ const char* key);
+
+const char* input_get_property_key(input_host_t* host, input_property_t* property);
+
+const char* input_get_property_value(input_host_t* host, input_property_t* property);
+
+void input_free_device_property(input_host_t* host, input_property_t* property);
+
+void input_free_device_property_map(input_host_t* host, input_property_map_t* map);
+} // extern "C"
+
+} // namespace android
+
+#endif // ANDROID_INPUT_MOCKS_H_