Loading services/inputflinger/InputDeviceMetricsCollector.cpp +92 −1 Original line number Diff line number Diff line Loading @@ -17,10 +17,11 @@ #define LOG_TAG "InputDeviceMetricsCollector" #include "InputDeviceMetricsCollector.h" #include "KeyCodeClassifications.h" #include <android-base/stringprintf.h> #include <input/PrintTools.h> #include <linux/input.h> #include <statslog.h> namespace android { Loading Loading @@ -80,6 +81,96 @@ bool isIgnoredInputDeviceId(int32_t deviceId) { } // namespace InputDeviceUsageSource getUsageSourceForKeyArgs(const InputDeviceInfo& info, const NotifyKeyArgs& keyArgs) { if (!isFromSource(keyArgs.source, AINPUT_SOURCE_KEYBOARD)) { return InputDeviceUsageSource::UNKNOWN; } if (isFromSource(keyArgs.source, AINPUT_SOURCE_DPAD) && DPAD_ALL_KEYCODES.count(keyArgs.keyCode) != 0) { return InputDeviceUsageSource::DPAD; } if (isFromSource(keyArgs.source, AINPUT_SOURCE_GAMEPAD) && GAMEPAD_KEYCODES.count(keyArgs.keyCode) != 0) { return InputDeviceUsageSource::GAMEPAD; } if (info.getKeyboardType() == AINPUT_KEYBOARD_TYPE_ALPHABETIC) { return InputDeviceUsageSource::KEYBOARD; } return InputDeviceUsageSource::BUTTONS; } std::set<InputDeviceUsageSource> getUsageSourcesForMotionArgs(const NotifyMotionArgs& motionArgs) { LOG_ALWAYS_FATAL_IF(motionArgs.pointerCount < 1, "Received motion args without pointers"); std::set<InputDeviceUsageSource> sources; for (uint32_t i = 0; i < motionArgs.pointerCount; i++) { const auto toolType = motionArgs.pointerProperties[i].toolType; if (isFromSource(motionArgs.source, AINPUT_SOURCE_MOUSE)) { if (toolType == ToolType::MOUSE) { sources.emplace(InputDeviceUsageSource::MOUSE); continue; } if (toolType == ToolType::FINGER) { sources.emplace(InputDeviceUsageSource::TOUCHPAD); continue; } if (isStylusToolType(toolType)) { sources.emplace(InputDeviceUsageSource::STYLUS_INDIRECT); continue; } } if (isFromSource(motionArgs.source, AINPUT_SOURCE_MOUSE_RELATIVE) && toolType == ToolType::MOUSE) { sources.emplace(InputDeviceUsageSource::MOUSE_CAPTURED); continue; } if (isFromSource(motionArgs.source, AINPUT_SOURCE_TOUCHPAD) && toolType == ToolType::FINGER) { sources.emplace(InputDeviceUsageSource::TOUCHPAD_CAPTURED); continue; } if (isFromSource(motionArgs.source, AINPUT_SOURCE_BLUETOOTH_STYLUS) && isStylusToolType(toolType)) { sources.emplace(InputDeviceUsageSource::STYLUS_FUSED); continue; } if (isFromSource(motionArgs.source, AINPUT_SOURCE_STYLUS) && isStylusToolType(toolType)) { sources.emplace(InputDeviceUsageSource::STYLUS_DIRECT); continue; } if (isFromSource(motionArgs.source, AINPUT_SOURCE_TOUCH_NAVIGATION)) { sources.emplace(InputDeviceUsageSource::TOUCH_NAVIGATION); continue; } if (isFromSource(motionArgs.source, AINPUT_SOURCE_JOYSTICK)) { sources.emplace(InputDeviceUsageSource::JOYSTICK); continue; } if (isFromSource(motionArgs.source, AINPUT_SOURCE_ROTARY_ENCODER)) { sources.emplace(InputDeviceUsageSource::ROTARY_ENCODER); continue; } if (isFromSource(motionArgs.source, AINPUT_SOURCE_TRACKBALL)) { sources.emplace(InputDeviceUsageSource::TRACKBALL); continue; } if (isFromSource(motionArgs.source, AINPUT_SOURCE_TOUCHSCREEN)) { sources.emplace(InputDeviceUsageSource::TOUCHSCREEN); continue; } sources.emplace(InputDeviceUsageSource::UNKNOWN); } return sources; } // --- InputDeviceMetricsCollector --- InputDeviceMetricsCollector::InputDeviceMetricsCollector(InputListenerInterface& listener) : InputDeviceMetricsCollector(listener, sStatsdLogger, DEFAULT_USAGE_SESSION_TIMEOUT) {} Loading services/inputflinger/InputDeviceMetricsCollector.h +35 −0 Original line number Diff line number Diff line Loading @@ -17,11 +17,14 @@ #pragma once #include "InputListener.h" #include "NotifyArgs.h" #include <ftl/mixins.h> #include <input/InputDevice.h> #include <statslog.h> #include <chrono> #include <map> #include <set> #include <vector> namespace android { Loading @@ -40,6 +43,38 @@ public: virtual void dump(std::string& dump) = 0; }; /** * Enum representation of the InputDeviceUsageSource. */ enum class InputDeviceUsageSource : int32_t { UNKNOWN = util::INPUT_DEVICE_USAGE_REPORTED__USAGE_SOURCES__UNKNOWN, BUTTONS = util::INPUT_DEVICE_USAGE_REPORTED__USAGE_SOURCES__BUTTONS, KEYBOARD = util::INPUT_DEVICE_USAGE_REPORTED__USAGE_SOURCES__KEYBOARD, DPAD = util::INPUT_DEVICE_USAGE_REPORTED__USAGE_SOURCES__DPAD, GAMEPAD = util::INPUT_DEVICE_USAGE_REPORTED__USAGE_SOURCES__GAMEPAD, JOYSTICK = util::INPUT_DEVICE_USAGE_REPORTED__USAGE_SOURCES__JOYSTICK, MOUSE = util::INPUT_DEVICE_USAGE_REPORTED__USAGE_SOURCES__MOUSE, MOUSE_CAPTURED = util::INPUT_DEVICE_USAGE_REPORTED__USAGE_SOURCES__MOUSE_CAPTURED, TOUCHPAD = util::INPUT_DEVICE_USAGE_REPORTED__USAGE_SOURCES__TOUCHPAD, TOUCHPAD_CAPTURED = util::INPUT_DEVICE_USAGE_REPORTED__USAGE_SOURCES__TOUCHPAD_CAPTURED, ROTARY_ENCODER = util::INPUT_DEVICE_USAGE_REPORTED__USAGE_SOURCES__ROTARY_ENCODER, STYLUS_DIRECT = util::INPUT_DEVICE_USAGE_REPORTED__USAGE_SOURCES__STYLUS_DIRECT, STYLUS_INDIRECT = util::INPUT_DEVICE_USAGE_REPORTED__USAGE_SOURCES__STYLUS_INDIRECT, STYLUS_FUSED = util::INPUT_DEVICE_USAGE_REPORTED__USAGE_SOURCES__STYLUS_FUSED, TOUCH_NAVIGATION = util::INPUT_DEVICE_USAGE_REPORTED__USAGE_SOURCES__TOUCH_NAVIGATION, TOUCHSCREEN = util::INPUT_DEVICE_USAGE_REPORTED__USAGE_SOURCES__TOUCHSCREEN, TRACKBALL = util::INPUT_DEVICE_USAGE_REPORTED__USAGE_SOURCES__TRACKBALL, ftl_first = UNKNOWN, ftl_last = TRACKBALL, }; /** Returns the InputDeviceUsageSource that corresponds to the key event. */ InputDeviceUsageSource getUsageSourceForKeyArgs(const InputDeviceInfo&, const NotifyKeyArgs&); /** Returns the InputDeviceUsageSources that correspond to the motion event. */ std::set<InputDeviceUsageSource> getUsageSourcesForMotionArgs(const NotifyMotionArgs&); /** The logging interface for the metrics collector, injected for testing. */ class InputDeviceMetricsLogger { public: Loading services/inputflinger/include/KeyCodeClassifications.h 0 → 100644 +55 −0 Original line number Diff line number Diff line /* * 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. */ #pragma once #include <android/input.h> #include <set> namespace android { /** The set of all Android key codes that are required for a device to be classified as a D-pad. */ static const std::set<int32_t> DPAD_REQUIRED_KEYCODES = { AKEYCODE_DPAD_UP, AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_CENTER, }; /** The set of all Android key codes that correspond to D-pad keys. */ static const std::set<int32_t> DPAD_ALL_KEYCODES = { AKEYCODE_DPAD_UP, AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_CENTER, AKEYCODE_DPAD_UP_LEFT, AKEYCODE_DPAD_UP_RIGHT, AKEYCODE_DPAD_DOWN_LEFT, AKEYCODE_DPAD_DOWN_RIGHT, }; /** The set of all Android key codes that correspond to gamepad buttons. */ static const std::set<int32_t> GAMEPAD_KEYCODES = { AKEYCODE_BUTTON_A, AKEYCODE_BUTTON_B, AKEYCODE_BUTTON_C, // AKEYCODE_BUTTON_X, AKEYCODE_BUTTON_Y, AKEYCODE_BUTTON_Z, // AKEYCODE_BUTTON_L1, AKEYCODE_BUTTON_R1, // AKEYCODE_BUTTON_L2, AKEYCODE_BUTTON_R2, // AKEYCODE_BUTTON_THUMBL, AKEYCODE_BUTTON_THUMBR, // AKEYCODE_BUTTON_START, AKEYCODE_BUTTON_SELECT, AKEYCODE_BUTTON_MODE, // }; /** The set of all Android key codes that correspond to buttons (bit-switches) on a stylus. */ static const std::set<int32_t> STYLUS_BUTTON_KEYCODES = { AKEYCODE_STYLUS_BUTTON_PRIMARY, AKEYCODE_STYLUS_BUTTON_SECONDARY, AKEYCODE_STYLUS_BUTTON_TERTIARY, AKEYCODE_STYLUS_BUTTON_TAIL, }; } // namespace android services/inputflinger/reader/EventHub.cpp +12 −35 Original line number Diff line number Diff line Loading @@ -58,6 +58,8 @@ #include "EventHub.h" #include "KeyCodeClassifications.h" #define INDENT " " #define INDENT2 " " #define INDENT3 " " Loading Loading @@ -189,14 +191,6 @@ static std::string sha1(const std::string& in) { return out; } /* The set of all Android key codes that correspond to buttons (bit-switches) on a stylus. */ static constexpr std::array<int32_t, 4> STYLUS_BUTTON_KEYCODES = { AKEYCODE_STYLUS_BUTTON_PRIMARY, AKEYCODE_STYLUS_BUTTON_SECONDARY, AKEYCODE_STYLUS_BUTTON_TERTIARY, AKEYCODE_STYLUS_BUTTON_TAIL, }; /** * Return true if name matches "v4l-touch*" */ Loading Loading @@ -2060,15 +2054,6 @@ void EventHub::scanDevicesLocked() { // ---------------------------------------------------------------------------- static const int32_t GAMEPAD_KEYCODES[] = { AKEYCODE_BUTTON_A, AKEYCODE_BUTTON_B, AKEYCODE_BUTTON_C, // AKEYCODE_BUTTON_X, AKEYCODE_BUTTON_Y, AKEYCODE_BUTTON_Z, // AKEYCODE_BUTTON_L1, AKEYCODE_BUTTON_R1, // AKEYCODE_BUTTON_L2, AKEYCODE_BUTTON_R2, // AKEYCODE_BUTTON_THUMBL, AKEYCODE_BUTTON_THUMBR, // AKEYCODE_BUTTON_START, AKEYCODE_BUTTON_SELECT, AKEYCODE_BUTTON_MODE, // }; status_t EventHub::registerFdForEpoll(int fd) { // TODO(b/121395353) - consider adding EPOLLRDHUP struct epoll_event eventItem = {}; Loading Loading @@ -2391,31 +2376,23 @@ void EventHub::openDeviceLocked(const std::string& devicePath) { device->classes |= InputDeviceClass::ALPHAKEY; } // See if this device has a DPAD. if (device->hasKeycodeLocked(AKEYCODE_DPAD_UP) && device->hasKeycodeLocked(AKEYCODE_DPAD_DOWN) && device->hasKeycodeLocked(AKEYCODE_DPAD_LEFT) && device->hasKeycodeLocked(AKEYCODE_DPAD_RIGHT) && device->hasKeycodeLocked(AKEYCODE_DPAD_CENTER)) { // See if this device has a D-pad. if (std::all_of(DPAD_REQUIRED_KEYCODES.begin(), DPAD_REQUIRED_KEYCODES.end(), [&](int32_t keycode) { return device->hasKeycodeLocked(keycode); })) { device->classes |= InputDeviceClass::DPAD; } // See if this device has a gamepad. for (size_t i = 0; i < sizeof(GAMEPAD_KEYCODES) / sizeof(GAMEPAD_KEYCODES[0]); i++) { if (device->hasKeycodeLocked(GAMEPAD_KEYCODES[i])) { if (std::any_of(GAMEPAD_KEYCODES.begin(), GAMEPAD_KEYCODES.end(), [&](int32_t keycode) { return device->hasKeycodeLocked(keycode); })) { device->classes |= InputDeviceClass::GAMEPAD; break; } } // See if this device has any stylus buttons that we would want to fuse with touch data. if (!device->classes.any(InputDeviceClass::TOUCH | InputDeviceClass::TOUCH_MT)) { for (int32_t keycode : STYLUS_BUTTON_KEYCODES) { if (device->hasKeycodeLocked(keycode)) { if (!device->classes.any(InputDeviceClass::TOUCH | InputDeviceClass::TOUCH_MT) && std::any_of(STYLUS_BUTTON_KEYCODES.begin(), STYLUS_BUTTON_KEYCODES.end(), [&](int32_t keycode) { return device->hasKeycodeLocked(keycode); })) { device->classes |= InputDeviceClass::EXTERNAL_STYLUS; break; } } } } Loading services/inputflinger/tests/EventBuilders.h +74 −0 Original line number Diff line number Diff line Loading @@ -285,4 +285,78 @@ private: std::vector<PointerBuilder> mPointers; }; class KeyArgsBuilder { public: KeyArgsBuilder(int32_t action, int32_t source) { mAction = action; mSource = source; mEventTime = systemTime(SYSTEM_TIME_MONOTONIC); mDownTime = mEventTime; } KeyArgsBuilder& deviceId(int32_t deviceId) { mDeviceId = deviceId; return *this; } KeyArgsBuilder& downTime(nsecs_t downTime) { mDownTime = downTime; return *this; } KeyArgsBuilder& eventTime(nsecs_t eventTime) { mEventTime = eventTime; return *this; } KeyArgsBuilder& displayId(int32_t displayId) { mDisplayId = displayId; return *this; } KeyArgsBuilder& policyFlags(int32_t policyFlags) { mPolicyFlags = policyFlags; return *this; } KeyArgsBuilder& addFlag(uint32_t flags) { mFlags |= flags; return *this; } KeyArgsBuilder& keyCode(int32_t keyCode) { mKeyCode = keyCode; return *this; } NotifyKeyArgs build() const { return {InputEvent::nextId(), mEventTime, /*readTime=*/mEventTime, mDeviceId, mSource, mDisplayId, mPolicyFlags, mAction, mFlags, mKeyCode, mScanCode, mMetaState, mDownTime}; } private: int32_t mAction; int32_t mDeviceId = DEFAULT_DEVICE_ID; uint32_t mSource; nsecs_t mDownTime; nsecs_t mEventTime; int32_t mDisplayId{ADISPLAY_ID_DEFAULT}; uint32_t mPolicyFlags = DEFAULT_POLICY_FLAGS; int32_t mFlags{0}; int32_t mKeyCode{AKEYCODE_UNKNOWN}; int32_t mScanCode{0}; int32_t mMetaState{AMETA_NONE}; }; } // namespace android Loading
services/inputflinger/InputDeviceMetricsCollector.cpp +92 −1 Original line number Diff line number Diff line Loading @@ -17,10 +17,11 @@ #define LOG_TAG "InputDeviceMetricsCollector" #include "InputDeviceMetricsCollector.h" #include "KeyCodeClassifications.h" #include <android-base/stringprintf.h> #include <input/PrintTools.h> #include <linux/input.h> #include <statslog.h> namespace android { Loading Loading @@ -80,6 +81,96 @@ bool isIgnoredInputDeviceId(int32_t deviceId) { } // namespace InputDeviceUsageSource getUsageSourceForKeyArgs(const InputDeviceInfo& info, const NotifyKeyArgs& keyArgs) { if (!isFromSource(keyArgs.source, AINPUT_SOURCE_KEYBOARD)) { return InputDeviceUsageSource::UNKNOWN; } if (isFromSource(keyArgs.source, AINPUT_SOURCE_DPAD) && DPAD_ALL_KEYCODES.count(keyArgs.keyCode) != 0) { return InputDeviceUsageSource::DPAD; } if (isFromSource(keyArgs.source, AINPUT_SOURCE_GAMEPAD) && GAMEPAD_KEYCODES.count(keyArgs.keyCode) != 0) { return InputDeviceUsageSource::GAMEPAD; } if (info.getKeyboardType() == AINPUT_KEYBOARD_TYPE_ALPHABETIC) { return InputDeviceUsageSource::KEYBOARD; } return InputDeviceUsageSource::BUTTONS; } std::set<InputDeviceUsageSource> getUsageSourcesForMotionArgs(const NotifyMotionArgs& motionArgs) { LOG_ALWAYS_FATAL_IF(motionArgs.pointerCount < 1, "Received motion args without pointers"); std::set<InputDeviceUsageSource> sources; for (uint32_t i = 0; i < motionArgs.pointerCount; i++) { const auto toolType = motionArgs.pointerProperties[i].toolType; if (isFromSource(motionArgs.source, AINPUT_SOURCE_MOUSE)) { if (toolType == ToolType::MOUSE) { sources.emplace(InputDeviceUsageSource::MOUSE); continue; } if (toolType == ToolType::FINGER) { sources.emplace(InputDeviceUsageSource::TOUCHPAD); continue; } if (isStylusToolType(toolType)) { sources.emplace(InputDeviceUsageSource::STYLUS_INDIRECT); continue; } } if (isFromSource(motionArgs.source, AINPUT_SOURCE_MOUSE_RELATIVE) && toolType == ToolType::MOUSE) { sources.emplace(InputDeviceUsageSource::MOUSE_CAPTURED); continue; } if (isFromSource(motionArgs.source, AINPUT_SOURCE_TOUCHPAD) && toolType == ToolType::FINGER) { sources.emplace(InputDeviceUsageSource::TOUCHPAD_CAPTURED); continue; } if (isFromSource(motionArgs.source, AINPUT_SOURCE_BLUETOOTH_STYLUS) && isStylusToolType(toolType)) { sources.emplace(InputDeviceUsageSource::STYLUS_FUSED); continue; } if (isFromSource(motionArgs.source, AINPUT_SOURCE_STYLUS) && isStylusToolType(toolType)) { sources.emplace(InputDeviceUsageSource::STYLUS_DIRECT); continue; } if (isFromSource(motionArgs.source, AINPUT_SOURCE_TOUCH_NAVIGATION)) { sources.emplace(InputDeviceUsageSource::TOUCH_NAVIGATION); continue; } if (isFromSource(motionArgs.source, AINPUT_SOURCE_JOYSTICK)) { sources.emplace(InputDeviceUsageSource::JOYSTICK); continue; } if (isFromSource(motionArgs.source, AINPUT_SOURCE_ROTARY_ENCODER)) { sources.emplace(InputDeviceUsageSource::ROTARY_ENCODER); continue; } if (isFromSource(motionArgs.source, AINPUT_SOURCE_TRACKBALL)) { sources.emplace(InputDeviceUsageSource::TRACKBALL); continue; } if (isFromSource(motionArgs.source, AINPUT_SOURCE_TOUCHSCREEN)) { sources.emplace(InputDeviceUsageSource::TOUCHSCREEN); continue; } sources.emplace(InputDeviceUsageSource::UNKNOWN); } return sources; } // --- InputDeviceMetricsCollector --- InputDeviceMetricsCollector::InputDeviceMetricsCollector(InputListenerInterface& listener) : InputDeviceMetricsCollector(listener, sStatsdLogger, DEFAULT_USAGE_SESSION_TIMEOUT) {} Loading
services/inputflinger/InputDeviceMetricsCollector.h +35 −0 Original line number Diff line number Diff line Loading @@ -17,11 +17,14 @@ #pragma once #include "InputListener.h" #include "NotifyArgs.h" #include <ftl/mixins.h> #include <input/InputDevice.h> #include <statslog.h> #include <chrono> #include <map> #include <set> #include <vector> namespace android { Loading @@ -40,6 +43,38 @@ public: virtual void dump(std::string& dump) = 0; }; /** * Enum representation of the InputDeviceUsageSource. */ enum class InputDeviceUsageSource : int32_t { UNKNOWN = util::INPUT_DEVICE_USAGE_REPORTED__USAGE_SOURCES__UNKNOWN, BUTTONS = util::INPUT_DEVICE_USAGE_REPORTED__USAGE_SOURCES__BUTTONS, KEYBOARD = util::INPUT_DEVICE_USAGE_REPORTED__USAGE_SOURCES__KEYBOARD, DPAD = util::INPUT_DEVICE_USAGE_REPORTED__USAGE_SOURCES__DPAD, GAMEPAD = util::INPUT_DEVICE_USAGE_REPORTED__USAGE_SOURCES__GAMEPAD, JOYSTICK = util::INPUT_DEVICE_USAGE_REPORTED__USAGE_SOURCES__JOYSTICK, MOUSE = util::INPUT_DEVICE_USAGE_REPORTED__USAGE_SOURCES__MOUSE, MOUSE_CAPTURED = util::INPUT_DEVICE_USAGE_REPORTED__USAGE_SOURCES__MOUSE_CAPTURED, TOUCHPAD = util::INPUT_DEVICE_USAGE_REPORTED__USAGE_SOURCES__TOUCHPAD, TOUCHPAD_CAPTURED = util::INPUT_DEVICE_USAGE_REPORTED__USAGE_SOURCES__TOUCHPAD_CAPTURED, ROTARY_ENCODER = util::INPUT_DEVICE_USAGE_REPORTED__USAGE_SOURCES__ROTARY_ENCODER, STYLUS_DIRECT = util::INPUT_DEVICE_USAGE_REPORTED__USAGE_SOURCES__STYLUS_DIRECT, STYLUS_INDIRECT = util::INPUT_DEVICE_USAGE_REPORTED__USAGE_SOURCES__STYLUS_INDIRECT, STYLUS_FUSED = util::INPUT_DEVICE_USAGE_REPORTED__USAGE_SOURCES__STYLUS_FUSED, TOUCH_NAVIGATION = util::INPUT_DEVICE_USAGE_REPORTED__USAGE_SOURCES__TOUCH_NAVIGATION, TOUCHSCREEN = util::INPUT_DEVICE_USAGE_REPORTED__USAGE_SOURCES__TOUCHSCREEN, TRACKBALL = util::INPUT_DEVICE_USAGE_REPORTED__USAGE_SOURCES__TRACKBALL, ftl_first = UNKNOWN, ftl_last = TRACKBALL, }; /** Returns the InputDeviceUsageSource that corresponds to the key event. */ InputDeviceUsageSource getUsageSourceForKeyArgs(const InputDeviceInfo&, const NotifyKeyArgs&); /** Returns the InputDeviceUsageSources that correspond to the motion event. */ std::set<InputDeviceUsageSource> getUsageSourcesForMotionArgs(const NotifyMotionArgs&); /** The logging interface for the metrics collector, injected for testing. */ class InputDeviceMetricsLogger { public: Loading
services/inputflinger/include/KeyCodeClassifications.h 0 → 100644 +55 −0 Original line number Diff line number Diff line /* * 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. */ #pragma once #include <android/input.h> #include <set> namespace android { /** The set of all Android key codes that are required for a device to be classified as a D-pad. */ static const std::set<int32_t> DPAD_REQUIRED_KEYCODES = { AKEYCODE_DPAD_UP, AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_CENTER, }; /** The set of all Android key codes that correspond to D-pad keys. */ static const std::set<int32_t> DPAD_ALL_KEYCODES = { AKEYCODE_DPAD_UP, AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_CENTER, AKEYCODE_DPAD_UP_LEFT, AKEYCODE_DPAD_UP_RIGHT, AKEYCODE_DPAD_DOWN_LEFT, AKEYCODE_DPAD_DOWN_RIGHT, }; /** The set of all Android key codes that correspond to gamepad buttons. */ static const std::set<int32_t> GAMEPAD_KEYCODES = { AKEYCODE_BUTTON_A, AKEYCODE_BUTTON_B, AKEYCODE_BUTTON_C, // AKEYCODE_BUTTON_X, AKEYCODE_BUTTON_Y, AKEYCODE_BUTTON_Z, // AKEYCODE_BUTTON_L1, AKEYCODE_BUTTON_R1, // AKEYCODE_BUTTON_L2, AKEYCODE_BUTTON_R2, // AKEYCODE_BUTTON_THUMBL, AKEYCODE_BUTTON_THUMBR, // AKEYCODE_BUTTON_START, AKEYCODE_BUTTON_SELECT, AKEYCODE_BUTTON_MODE, // }; /** The set of all Android key codes that correspond to buttons (bit-switches) on a stylus. */ static const std::set<int32_t> STYLUS_BUTTON_KEYCODES = { AKEYCODE_STYLUS_BUTTON_PRIMARY, AKEYCODE_STYLUS_BUTTON_SECONDARY, AKEYCODE_STYLUS_BUTTON_TERTIARY, AKEYCODE_STYLUS_BUTTON_TAIL, }; } // namespace android
services/inputflinger/reader/EventHub.cpp +12 −35 Original line number Diff line number Diff line Loading @@ -58,6 +58,8 @@ #include "EventHub.h" #include "KeyCodeClassifications.h" #define INDENT " " #define INDENT2 " " #define INDENT3 " " Loading Loading @@ -189,14 +191,6 @@ static std::string sha1(const std::string& in) { return out; } /* The set of all Android key codes that correspond to buttons (bit-switches) on a stylus. */ static constexpr std::array<int32_t, 4> STYLUS_BUTTON_KEYCODES = { AKEYCODE_STYLUS_BUTTON_PRIMARY, AKEYCODE_STYLUS_BUTTON_SECONDARY, AKEYCODE_STYLUS_BUTTON_TERTIARY, AKEYCODE_STYLUS_BUTTON_TAIL, }; /** * Return true if name matches "v4l-touch*" */ Loading Loading @@ -2060,15 +2054,6 @@ void EventHub::scanDevicesLocked() { // ---------------------------------------------------------------------------- static const int32_t GAMEPAD_KEYCODES[] = { AKEYCODE_BUTTON_A, AKEYCODE_BUTTON_B, AKEYCODE_BUTTON_C, // AKEYCODE_BUTTON_X, AKEYCODE_BUTTON_Y, AKEYCODE_BUTTON_Z, // AKEYCODE_BUTTON_L1, AKEYCODE_BUTTON_R1, // AKEYCODE_BUTTON_L2, AKEYCODE_BUTTON_R2, // AKEYCODE_BUTTON_THUMBL, AKEYCODE_BUTTON_THUMBR, // AKEYCODE_BUTTON_START, AKEYCODE_BUTTON_SELECT, AKEYCODE_BUTTON_MODE, // }; status_t EventHub::registerFdForEpoll(int fd) { // TODO(b/121395353) - consider adding EPOLLRDHUP struct epoll_event eventItem = {}; Loading Loading @@ -2391,31 +2376,23 @@ void EventHub::openDeviceLocked(const std::string& devicePath) { device->classes |= InputDeviceClass::ALPHAKEY; } // See if this device has a DPAD. if (device->hasKeycodeLocked(AKEYCODE_DPAD_UP) && device->hasKeycodeLocked(AKEYCODE_DPAD_DOWN) && device->hasKeycodeLocked(AKEYCODE_DPAD_LEFT) && device->hasKeycodeLocked(AKEYCODE_DPAD_RIGHT) && device->hasKeycodeLocked(AKEYCODE_DPAD_CENTER)) { // See if this device has a D-pad. if (std::all_of(DPAD_REQUIRED_KEYCODES.begin(), DPAD_REQUIRED_KEYCODES.end(), [&](int32_t keycode) { return device->hasKeycodeLocked(keycode); })) { device->classes |= InputDeviceClass::DPAD; } // See if this device has a gamepad. for (size_t i = 0; i < sizeof(GAMEPAD_KEYCODES) / sizeof(GAMEPAD_KEYCODES[0]); i++) { if (device->hasKeycodeLocked(GAMEPAD_KEYCODES[i])) { if (std::any_of(GAMEPAD_KEYCODES.begin(), GAMEPAD_KEYCODES.end(), [&](int32_t keycode) { return device->hasKeycodeLocked(keycode); })) { device->classes |= InputDeviceClass::GAMEPAD; break; } } // See if this device has any stylus buttons that we would want to fuse with touch data. if (!device->classes.any(InputDeviceClass::TOUCH | InputDeviceClass::TOUCH_MT)) { for (int32_t keycode : STYLUS_BUTTON_KEYCODES) { if (device->hasKeycodeLocked(keycode)) { if (!device->classes.any(InputDeviceClass::TOUCH | InputDeviceClass::TOUCH_MT) && std::any_of(STYLUS_BUTTON_KEYCODES.begin(), STYLUS_BUTTON_KEYCODES.end(), [&](int32_t keycode) { return device->hasKeycodeLocked(keycode); })) { device->classes |= InputDeviceClass::EXTERNAL_STYLUS; break; } } } } Loading
services/inputflinger/tests/EventBuilders.h +74 −0 Original line number Diff line number Diff line Loading @@ -285,4 +285,78 @@ private: std::vector<PointerBuilder> mPointers; }; class KeyArgsBuilder { public: KeyArgsBuilder(int32_t action, int32_t source) { mAction = action; mSource = source; mEventTime = systemTime(SYSTEM_TIME_MONOTONIC); mDownTime = mEventTime; } KeyArgsBuilder& deviceId(int32_t deviceId) { mDeviceId = deviceId; return *this; } KeyArgsBuilder& downTime(nsecs_t downTime) { mDownTime = downTime; return *this; } KeyArgsBuilder& eventTime(nsecs_t eventTime) { mEventTime = eventTime; return *this; } KeyArgsBuilder& displayId(int32_t displayId) { mDisplayId = displayId; return *this; } KeyArgsBuilder& policyFlags(int32_t policyFlags) { mPolicyFlags = policyFlags; return *this; } KeyArgsBuilder& addFlag(uint32_t flags) { mFlags |= flags; return *this; } KeyArgsBuilder& keyCode(int32_t keyCode) { mKeyCode = keyCode; return *this; } NotifyKeyArgs build() const { return {InputEvent::nextId(), mEventTime, /*readTime=*/mEventTime, mDeviceId, mSource, mDisplayId, mPolicyFlags, mAction, mFlags, mKeyCode, mScanCode, mMetaState, mDownTime}; } private: int32_t mAction; int32_t mDeviceId = DEFAULT_DEVICE_ID; uint32_t mSource; nsecs_t mDownTime; nsecs_t mEventTime; int32_t mDisplayId{ADISPLAY_ID_DEFAULT}; uint32_t mPolicyFlags = DEFAULT_POLICY_FLAGS; int32_t mFlags{0}; int32_t mKeyCode{AKEYCODE_UNKNOWN}; int32_t mScanCode{0}; int32_t mMetaState{AMETA_NONE}; }; } // namespace android