blob: 84ef52c1483fbb526af069ea4ad08ea7ab20a451 [file] [log] [blame]
/*
* Copyright 2023 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.
*/
#include "../InputDeviceMetricsSource.h"
#include <NotifyArgsBuilders.h>
#include <android/input.h>
#include <ftl/enum.h>
#include <gtest/gtest.h>
#include <input/Input.h>
#include <input/InputEventBuilders.h>
#include <linux/input.h>
#include <set>
namespace android {
namespace {
constexpr auto ALL_USAGE_SOURCES = ftl::enum_range<InputDeviceUsageSource>();
constexpr uint32_t TOUCHSCREEN = AINPUT_SOURCE_TOUCHSCREEN;
constexpr uint32_t STYLUS = AINPUT_SOURCE_STYLUS;
constexpr uint32_t KEY_SOURCES =
AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_DPAD | AINPUT_SOURCE_GAMEPAD;
constexpr int32_t POINTER_1_DOWN =
AMOTION_EVENT_ACTION_POINTER_DOWN | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
} // namespace
// --- InputDeviceMetricsSourceDeviceClassificationTest ---
class DeviceClassificationFixture : public ::testing::Test,
public ::testing::WithParamInterface<InputDeviceUsageSource> {};
TEST_P(DeviceClassificationFixture, ValidClassifications) {
const InputDeviceUsageSource usageSource = GetParam();
// Use a switch to ensure a test is added for all source classifications.
switch (usageSource) {
case InputDeviceUsageSource::UNKNOWN: {
ASSERT_EQ(InputDeviceUsageSource::UNKNOWN,
getUsageSourceForKeyArgs(AINPUT_KEYBOARD_TYPE_NONE,
KeyArgsBuilder(AKEY_EVENT_ACTION_DOWN, TOUCHSCREEN)
.build()));
std::set<InputDeviceUsageSource> srcs{InputDeviceUsageSource::UNKNOWN};
ASSERT_EQ(srcs,
getUsageSourcesForMotionArgs(
MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_KEYBOARD)
.pointer(PointerBuilder(/*id=*/1, ToolType::PALM)
.x(100)
.y(200))
.build()));
break;
}
case InputDeviceUsageSource::BUTTONS: {
ASSERT_EQ(InputDeviceUsageSource::BUTTONS,
getUsageSourceForKeyArgs(AINPUT_KEYBOARD_TYPE_NON_ALPHABETIC,
KeyArgsBuilder(AKEY_EVENT_ACTION_DOWN, KEY_SOURCES)
.keyCode(AKEYCODE_STYLUS_BUTTON_TAIL)
.build()));
break;
}
case InputDeviceUsageSource::KEYBOARD: {
ASSERT_EQ(InputDeviceUsageSource::KEYBOARD,
getUsageSourceForKeyArgs(AINPUT_KEYBOARD_TYPE_ALPHABETIC,
KeyArgsBuilder(AKEY_EVENT_ACTION_DOWN, KEY_SOURCES)
.build()));
break;
}
case InputDeviceUsageSource::DPAD: {
ASSERT_EQ(InputDeviceUsageSource::DPAD,
getUsageSourceForKeyArgs(AINPUT_KEYBOARD_TYPE_NON_ALPHABETIC,
KeyArgsBuilder(AKEY_EVENT_ACTION_DOWN, KEY_SOURCES)
.keyCode(AKEYCODE_DPAD_CENTER)
.build()));
ASSERT_EQ(InputDeviceUsageSource::DPAD,
getUsageSourceForKeyArgs(AINPUT_KEYBOARD_TYPE_ALPHABETIC,
KeyArgsBuilder(AKEY_EVENT_ACTION_DOWN, KEY_SOURCES)
.keyCode(AKEYCODE_DPAD_CENTER)
.build()));
break;
}
case InputDeviceUsageSource::GAMEPAD: {
ASSERT_EQ(InputDeviceUsageSource::GAMEPAD,
getUsageSourceForKeyArgs(AINPUT_KEYBOARD_TYPE_NON_ALPHABETIC,
KeyArgsBuilder(AKEY_EVENT_ACTION_DOWN, KEY_SOURCES)
.keyCode(AKEYCODE_BUTTON_A)
.build()));
ASSERT_EQ(InputDeviceUsageSource::GAMEPAD,
getUsageSourceForKeyArgs(AINPUT_KEYBOARD_TYPE_ALPHABETIC,
KeyArgsBuilder(AKEY_EVENT_ACTION_DOWN, KEY_SOURCES)
.keyCode(AKEYCODE_BUTTON_A)
.build()));
break;
}
case InputDeviceUsageSource::JOYSTICK: {
std::set<InputDeviceUsageSource> srcs{InputDeviceUsageSource::JOYSTICK};
ASSERT_EQ(srcs,
getUsageSourcesForMotionArgs(
MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_JOYSTICK)
.pointer(PointerBuilder(/*id=*/1, ToolType::UNKNOWN)
.axis(AMOTION_EVENT_AXIS_GAS, 1.f))
.build()));
break;
}
case InputDeviceUsageSource::MOUSE: {
std::set<InputDeviceUsageSource> srcs{InputDeviceUsageSource::MOUSE};
ASSERT_EQ(srcs,
getUsageSourcesForMotionArgs(
MotionArgsBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
AINPUT_SOURCE_MOUSE)
.pointer(PointerBuilder(/*id=*/1, ToolType::MOUSE)
.x(100)
.y(200))
.build()));
break;
}
case InputDeviceUsageSource::MOUSE_CAPTURED: {
std::set<InputDeviceUsageSource> srcs{InputDeviceUsageSource::MOUSE_CAPTURED};
ASSERT_EQ(srcs,
getUsageSourcesForMotionArgs(
MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE,
AINPUT_SOURCE_MOUSE_RELATIVE)
.pointer(PointerBuilder(/*id=*/1, ToolType::MOUSE)
.x(100)
.y(200)
.axis(AMOTION_EVENT_AXIS_RELATIVE_X, 100)
.axis(AMOTION_EVENT_AXIS_RELATIVE_Y, 200))
.build()));
break;
}
case InputDeviceUsageSource::TOUCHPAD: {
std::set<InputDeviceUsageSource> srcs{InputDeviceUsageSource::TOUCHPAD};
ASSERT_EQ(srcs,
getUsageSourcesForMotionArgs(
MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
.pointer(PointerBuilder(/*id=*/1, ToolType::FINGER)
.x(100)
.y(200))
.build()));
break;
}
case InputDeviceUsageSource::TOUCHPAD_CAPTURED: {
std::set<InputDeviceUsageSource> srcs{InputDeviceUsageSource::TOUCHPAD_CAPTURED};
ASSERT_EQ(srcs,
getUsageSourcesForMotionArgs(
MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHPAD)
.pointer(PointerBuilder(/*id=*/1, ToolType::FINGER)
.x(100)
.y(200)
.axis(AMOTION_EVENT_AXIS_RELATIVE_X, 1)
.axis(AMOTION_EVENT_AXIS_RELATIVE_Y, 2))
.build()));
break;
}
case InputDeviceUsageSource::ROTARY_ENCODER: {
std::set<InputDeviceUsageSource> srcs{InputDeviceUsageSource::ROTARY_ENCODER};
ASSERT_EQ(srcs,
getUsageSourcesForMotionArgs(
MotionArgsBuilder(AMOTION_EVENT_ACTION_SCROLL,
AINPUT_SOURCE_ROTARY_ENCODER)
.pointer(PointerBuilder(/*id=*/1, ToolType::UNKNOWN)
.axis(AMOTION_EVENT_AXIS_SCROLL, 10)
.axis(AMOTION_EVENT_AXIS_VSCROLL, 10))
.build()));
break;
}
case InputDeviceUsageSource::STYLUS_DIRECT: {
std::set<InputDeviceUsageSource> srcs{InputDeviceUsageSource::STYLUS_DIRECT};
ASSERT_EQ(srcs,
getUsageSourcesForMotionArgs(
MotionArgsBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
STYLUS | TOUCHSCREEN)
.pointer(PointerBuilder(/*id=*/1, ToolType::STYLUS)
.x(100)
.y(200))
.build()));
break;
}
case InputDeviceUsageSource::STYLUS_INDIRECT: {
std::set<InputDeviceUsageSource> srcs{InputDeviceUsageSource::STYLUS_INDIRECT};
ASSERT_EQ(srcs,
getUsageSourcesForMotionArgs(
MotionArgsBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
STYLUS | TOUCHSCREEN | AINPUT_SOURCE_MOUSE)
.pointer(PointerBuilder(/*id=*/1, ToolType::STYLUS)
.x(100)
.y(200))
.build()));
break;
}
case InputDeviceUsageSource::STYLUS_FUSED: {
std::set<InputDeviceUsageSource> srcs{InputDeviceUsageSource::STYLUS_FUSED};
ASSERT_EQ(srcs,
getUsageSourcesForMotionArgs(
MotionArgsBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
AINPUT_SOURCE_BLUETOOTH_STYLUS | TOUCHSCREEN)
.pointer(PointerBuilder(/*id=*/1, ToolType::STYLUS)
.x(100)
.y(200))
.build()));
break;
}
case InputDeviceUsageSource::TOUCH_NAVIGATION: {
std::set<InputDeviceUsageSource> srcs{InputDeviceUsageSource::TOUCH_NAVIGATION};
ASSERT_EQ(srcs,
getUsageSourcesForMotionArgs(
MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE,
AINPUT_SOURCE_TOUCH_NAVIGATION)
.pointer(PointerBuilder(/*id=*/1, ToolType::FINGER)
.x(100)
.y(200))
.build()));
break;
}
case InputDeviceUsageSource::TOUCHSCREEN: {
std::set<InputDeviceUsageSource> srcs{InputDeviceUsageSource::TOUCHSCREEN};
ASSERT_EQ(srcs,
getUsageSourcesForMotionArgs(
MotionArgsBuilder(POINTER_1_DOWN, TOUCHSCREEN)
.pointer(PointerBuilder(/*id=*/1, ToolType::FINGER)
.x(100)
.y(200))
.pointer(PointerBuilder(/*id=*/2, ToolType::FINGER)
.x(300)
.y(400))
.build()));
break;
}
case InputDeviceUsageSource::TRACKBALL: {
std::set<InputDeviceUsageSource> srcs{InputDeviceUsageSource::TRACKBALL};
ASSERT_EQ(srcs,
getUsageSourcesForMotionArgs(
MotionArgsBuilder(AMOTION_EVENT_ACTION_SCROLL,
AINPUT_SOURCE_TRACKBALL)
.pointer(PointerBuilder(/*id=*/1, ToolType::UNKNOWN)
.axis(AMOTION_EVENT_AXIS_VSCROLL, 100)
.axis(AMOTION_EVENT_AXIS_HSCROLL, 200))
.build()));
break;
}
}
}
INSTANTIATE_TEST_SUITE_P(InputDeviceMetricsSourceDeviceClassificationTest,
DeviceClassificationFixture,
::testing::ValuesIn(ALL_USAGE_SOURCES.begin(), ALL_USAGE_SOURCES.end()),
[](const testing::TestParamInfo<InputDeviceUsageSource>& testParamInfo) {
return ftl::enum_string(testParamInfo.param);
});
TEST(InputDeviceMetricsSourceDeviceClassificationTest, MixedClassificationTouchscreenStylus) {
std::set<InputDeviceUsageSource> srcs{InputDeviceUsageSource::TOUCHSCREEN,
InputDeviceUsageSource::STYLUS_DIRECT};
ASSERT_EQ(srcs,
getUsageSourcesForMotionArgs(
MotionArgsBuilder(POINTER_1_DOWN, TOUCHSCREEN | STYLUS)
.pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(100).y(200))
.pointer(PointerBuilder(/*id=*/2, ToolType::STYLUS).x(300).y(400))
.build()));
}
} // namespace android