From 4cc839fe01cd5bbb16650e85913070386f637e75 Mon Sep 17 00:00:00 2001 From: Garfield Tan Date: Fri, 24 Jan 2020 11:26:14 -0800 Subject: Add ID to native events. To separate this big work into pieces I introduced a placeholder in InputTransport used to initialize native input events received from InputFlinger until InputFlinger can generate random sequence numbers. The work in InputDispatcher wires up ID between events and notify args as well. Bug: 144889238 Test: Builds and some smoke tests. Test: atest libinput_tests Change-Id: I1ef7f243cc89a8b6e07ba9ba30a43c21eedb16ce --- libs/input/KeyCharacterMap.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'libs/input/KeyCharacterMap.cpp') diff --git a/libs/input/KeyCharacterMap.cpp b/libs/input/KeyCharacterMap.cpp index 6f9b162986..cb68165433 100644 --- a/libs/input/KeyCharacterMap.cpp +++ b/libs/input/KeyCharacterMap.cpp @@ -487,9 +487,9 @@ void KeyCharacterMap::addKey(Vector& outEvents, int32_t deviceId, int32_t keyCode, int32_t metaState, bool down, nsecs_t time) { outEvents.push(); KeyEvent& event = outEvents.editTop(); - event.initialize(deviceId, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE, INVALID_HMAC, - down ? AKEY_EVENT_ACTION_DOWN : AKEY_EVENT_ACTION_UP, 0, keyCode, 0, metaState, - 0, time, time); + event.initialize(InputEvent::nextId(), deviceId, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE, + INVALID_HMAC, down ? AKEY_EVENT_ACTION_DOWN : AKEY_EVENT_ACTION_UP, 0, keyCode, + 0, metaState, 0, time, time); } void KeyCharacterMap::addMetaKeys(Vector& outEvents, -- cgit v1.2.3-59-g8ed1b From 4958d061f2f4bba86ddb9d4bdde1dc0dd783c71a Mon Sep 17 00:00:00 2001 From: Chris Ye Date: Thu, 20 Aug 2020 13:21:10 -0700 Subject: Optimize memory usage of InputEvent lookup. Move the declaration of look up map to cpp file from header file to avoid duplicate copies. Bug: 165527068 Bug: 165398580 Bug: 165035349 Test: atest libinput_tests, atest inputflinger_tests adb shell showmap | grep input Check libinput.so and libinput_reader.so size to be 300 and 372KB. Change-Id: Ia80200b7889f16ce576637d746e64641f3f2a094 --- include/input/InputEventLabels.h | 443 +------------------- libs/input/Android.bp | 1 + libs/input/Input.cpp | 8 +- libs/input/InputEventLabels.cpp | 448 +++++++++++++++++++++ libs/input/KeyCharacterMap.cpp | 8 +- libs/input/KeyLayoutMap.cpp | 14 +- services/inputflinger/reader/InputDevice.cpp | 2 +- .../reader/mapper/JoystickInputMapper.cpp | 4 +- 8 files changed, 488 insertions(+), 440 deletions(-) create mode 100644 libs/input/InputEventLabels.cpp (limited to 'libs/input/KeyCharacterMap.cpp') diff --git a/include/input/InputEventLabels.h b/include/input/InputEventLabels.h index ec2de61197..2a742f9cf4 100644 --- a/include/input/InputEventLabels.h +++ b/include/input/InputEventLabels.h @@ -21,11 +21,6 @@ #include #include -#define DEFINE_KEYCODE(key) { #key, AKEYCODE_##key } -#define DEFINE_AXIS(axis) { #axis, AMOTION_EVENT_AXIS_##axis } -#define DEFINE_LED(led) { #led, ALED_##led } -#define DEFINE_FLAG(flag) { #flag, POLICY_FLAG_##flag } - namespace android { template @@ -36,437 +31,41 @@ struct InputEventLabel { int value; }; -// NOTE: If you add a new keycode here you must also add it to several other files. -// Refer to frameworks/base/core/java/android/view/KeyEvent.java for the full list. -#define KEYCODES_SEQUENCE \ - DEFINE_KEYCODE(UNKNOWN), \ - DEFINE_KEYCODE(SOFT_LEFT), \ - DEFINE_KEYCODE(SOFT_RIGHT), \ - DEFINE_KEYCODE(HOME), \ - DEFINE_KEYCODE(BACK), \ - DEFINE_KEYCODE(CALL), \ - DEFINE_KEYCODE(ENDCALL), \ - DEFINE_KEYCODE(0), \ - DEFINE_KEYCODE(1), \ - DEFINE_KEYCODE(2), \ - DEFINE_KEYCODE(3), \ - DEFINE_KEYCODE(4), \ - DEFINE_KEYCODE(5), \ - DEFINE_KEYCODE(6), \ - DEFINE_KEYCODE(7), \ - DEFINE_KEYCODE(8), \ - DEFINE_KEYCODE(9), \ - DEFINE_KEYCODE(STAR), \ - DEFINE_KEYCODE(POUND), \ - DEFINE_KEYCODE(DPAD_UP), \ - DEFINE_KEYCODE(DPAD_DOWN), \ - DEFINE_KEYCODE(DPAD_LEFT), \ - DEFINE_KEYCODE(DPAD_RIGHT), \ - DEFINE_KEYCODE(DPAD_CENTER), \ - DEFINE_KEYCODE(VOLUME_UP), \ - DEFINE_KEYCODE(VOLUME_DOWN), \ - DEFINE_KEYCODE(POWER), \ - DEFINE_KEYCODE(CAMERA), \ - DEFINE_KEYCODE(CLEAR), \ - DEFINE_KEYCODE(A), \ - DEFINE_KEYCODE(B), \ - DEFINE_KEYCODE(C), \ - DEFINE_KEYCODE(D), \ - DEFINE_KEYCODE(E), \ - DEFINE_KEYCODE(F), \ - DEFINE_KEYCODE(G), \ - DEFINE_KEYCODE(H), \ - DEFINE_KEYCODE(I), \ - DEFINE_KEYCODE(J), \ - DEFINE_KEYCODE(K), \ - DEFINE_KEYCODE(L), \ - DEFINE_KEYCODE(M), \ - DEFINE_KEYCODE(N), \ - DEFINE_KEYCODE(O), \ - DEFINE_KEYCODE(P), \ - DEFINE_KEYCODE(Q), \ - DEFINE_KEYCODE(R), \ - DEFINE_KEYCODE(S), \ - DEFINE_KEYCODE(T), \ - DEFINE_KEYCODE(U), \ - DEFINE_KEYCODE(V), \ - DEFINE_KEYCODE(W), \ - DEFINE_KEYCODE(X), \ - DEFINE_KEYCODE(Y), \ - DEFINE_KEYCODE(Z), \ - DEFINE_KEYCODE(COMMA), \ - DEFINE_KEYCODE(PERIOD), \ - DEFINE_KEYCODE(ALT_LEFT), \ - DEFINE_KEYCODE(ALT_RIGHT), \ - DEFINE_KEYCODE(SHIFT_LEFT), \ - DEFINE_KEYCODE(SHIFT_RIGHT), \ - DEFINE_KEYCODE(TAB), \ - DEFINE_KEYCODE(SPACE), \ - DEFINE_KEYCODE(SYM), \ - DEFINE_KEYCODE(EXPLORER), \ - DEFINE_KEYCODE(ENVELOPE), \ - DEFINE_KEYCODE(ENTER), \ - DEFINE_KEYCODE(DEL), \ - DEFINE_KEYCODE(GRAVE), \ - DEFINE_KEYCODE(MINUS), \ - DEFINE_KEYCODE(EQUALS), \ - DEFINE_KEYCODE(LEFT_BRACKET), \ - DEFINE_KEYCODE(RIGHT_BRACKET), \ - DEFINE_KEYCODE(BACKSLASH), \ - DEFINE_KEYCODE(SEMICOLON), \ - DEFINE_KEYCODE(APOSTROPHE), \ - DEFINE_KEYCODE(SLASH), \ - DEFINE_KEYCODE(AT), \ - DEFINE_KEYCODE(NUM), \ - DEFINE_KEYCODE(HEADSETHOOK), \ - DEFINE_KEYCODE(FOCUS), \ - DEFINE_KEYCODE(PLUS), \ - DEFINE_KEYCODE(MENU), \ - DEFINE_KEYCODE(NOTIFICATION), \ - DEFINE_KEYCODE(SEARCH), \ - DEFINE_KEYCODE(MEDIA_PLAY_PAUSE), \ - DEFINE_KEYCODE(MEDIA_STOP), \ - DEFINE_KEYCODE(MEDIA_NEXT), \ - DEFINE_KEYCODE(MEDIA_PREVIOUS), \ - DEFINE_KEYCODE(MEDIA_REWIND), \ - DEFINE_KEYCODE(MEDIA_FAST_FORWARD), \ - DEFINE_KEYCODE(MUTE), \ - DEFINE_KEYCODE(PAGE_UP), \ - DEFINE_KEYCODE(PAGE_DOWN), \ - DEFINE_KEYCODE(PICTSYMBOLS), \ - DEFINE_KEYCODE(SWITCH_CHARSET), \ - DEFINE_KEYCODE(BUTTON_A), \ - DEFINE_KEYCODE(BUTTON_B), \ - DEFINE_KEYCODE(BUTTON_C), \ - DEFINE_KEYCODE(BUTTON_X), \ - DEFINE_KEYCODE(BUTTON_Y), \ - DEFINE_KEYCODE(BUTTON_Z), \ - DEFINE_KEYCODE(BUTTON_L1), \ - DEFINE_KEYCODE(BUTTON_R1), \ - DEFINE_KEYCODE(BUTTON_L2), \ - DEFINE_KEYCODE(BUTTON_R2), \ - DEFINE_KEYCODE(BUTTON_THUMBL), \ - DEFINE_KEYCODE(BUTTON_THUMBR), \ - DEFINE_KEYCODE(BUTTON_START), \ - DEFINE_KEYCODE(BUTTON_SELECT), \ - DEFINE_KEYCODE(BUTTON_MODE), \ - DEFINE_KEYCODE(ESCAPE), \ - DEFINE_KEYCODE(FORWARD_DEL), \ - DEFINE_KEYCODE(CTRL_LEFT), \ - DEFINE_KEYCODE(CTRL_RIGHT), \ - DEFINE_KEYCODE(CAPS_LOCK), \ - DEFINE_KEYCODE(SCROLL_LOCK), \ - DEFINE_KEYCODE(META_LEFT), \ - DEFINE_KEYCODE(META_RIGHT), \ - DEFINE_KEYCODE(FUNCTION), \ - DEFINE_KEYCODE(SYSRQ), \ - DEFINE_KEYCODE(BREAK), \ - DEFINE_KEYCODE(MOVE_HOME), \ - DEFINE_KEYCODE(MOVE_END), \ - DEFINE_KEYCODE(INSERT), \ - DEFINE_KEYCODE(FORWARD), \ - DEFINE_KEYCODE(MEDIA_PLAY), \ - DEFINE_KEYCODE(MEDIA_PAUSE), \ - DEFINE_KEYCODE(MEDIA_CLOSE), \ - DEFINE_KEYCODE(MEDIA_EJECT), \ - DEFINE_KEYCODE(MEDIA_RECORD), \ - DEFINE_KEYCODE(F1), \ - DEFINE_KEYCODE(F2), \ - DEFINE_KEYCODE(F3), \ - DEFINE_KEYCODE(F4), \ - DEFINE_KEYCODE(F5), \ - DEFINE_KEYCODE(F6), \ - DEFINE_KEYCODE(F7), \ - DEFINE_KEYCODE(F8), \ - DEFINE_KEYCODE(F9), \ - DEFINE_KEYCODE(F10), \ - DEFINE_KEYCODE(F11), \ - DEFINE_KEYCODE(F12), \ - DEFINE_KEYCODE(NUM_LOCK), \ - DEFINE_KEYCODE(NUMPAD_0), \ - DEFINE_KEYCODE(NUMPAD_1), \ - DEFINE_KEYCODE(NUMPAD_2), \ - DEFINE_KEYCODE(NUMPAD_3), \ - DEFINE_KEYCODE(NUMPAD_4), \ - DEFINE_KEYCODE(NUMPAD_5), \ - DEFINE_KEYCODE(NUMPAD_6), \ - DEFINE_KEYCODE(NUMPAD_7), \ - DEFINE_KEYCODE(NUMPAD_8), \ - DEFINE_KEYCODE(NUMPAD_9), \ - DEFINE_KEYCODE(NUMPAD_DIVIDE), \ - DEFINE_KEYCODE(NUMPAD_MULTIPLY), \ - DEFINE_KEYCODE(NUMPAD_SUBTRACT), \ - DEFINE_KEYCODE(NUMPAD_ADD), \ - DEFINE_KEYCODE(NUMPAD_DOT), \ - DEFINE_KEYCODE(NUMPAD_COMMA), \ - DEFINE_KEYCODE(NUMPAD_ENTER), \ - DEFINE_KEYCODE(NUMPAD_EQUALS), \ - DEFINE_KEYCODE(NUMPAD_LEFT_PAREN), \ - DEFINE_KEYCODE(NUMPAD_RIGHT_PAREN), \ - DEFINE_KEYCODE(VOLUME_MUTE), \ - DEFINE_KEYCODE(INFO), \ - DEFINE_KEYCODE(CHANNEL_UP), \ - DEFINE_KEYCODE(CHANNEL_DOWN), \ - DEFINE_KEYCODE(ZOOM_IN), \ - DEFINE_KEYCODE(ZOOM_OUT), \ - DEFINE_KEYCODE(TV), \ - DEFINE_KEYCODE(WINDOW), \ - DEFINE_KEYCODE(GUIDE), \ - DEFINE_KEYCODE(DVR), \ - DEFINE_KEYCODE(BOOKMARK), \ - DEFINE_KEYCODE(CAPTIONS), \ - DEFINE_KEYCODE(SETTINGS), \ - DEFINE_KEYCODE(TV_POWER), \ - DEFINE_KEYCODE(TV_INPUT), \ - DEFINE_KEYCODE(STB_POWER), \ - DEFINE_KEYCODE(STB_INPUT), \ - DEFINE_KEYCODE(AVR_POWER), \ - DEFINE_KEYCODE(AVR_INPUT), \ - DEFINE_KEYCODE(PROG_RED), \ - DEFINE_KEYCODE(PROG_GREEN), \ - DEFINE_KEYCODE(PROG_YELLOW), \ - DEFINE_KEYCODE(PROG_BLUE), \ - DEFINE_KEYCODE(APP_SWITCH), \ - DEFINE_KEYCODE(BUTTON_1), \ - DEFINE_KEYCODE(BUTTON_2), \ - DEFINE_KEYCODE(BUTTON_3), \ - DEFINE_KEYCODE(BUTTON_4), \ - DEFINE_KEYCODE(BUTTON_5), \ - DEFINE_KEYCODE(BUTTON_6), \ - DEFINE_KEYCODE(BUTTON_7), \ - DEFINE_KEYCODE(BUTTON_8), \ - DEFINE_KEYCODE(BUTTON_9), \ - DEFINE_KEYCODE(BUTTON_10), \ - DEFINE_KEYCODE(BUTTON_11), \ - DEFINE_KEYCODE(BUTTON_12), \ - DEFINE_KEYCODE(BUTTON_13), \ - DEFINE_KEYCODE(BUTTON_14), \ - DEFINE_KEYCODE(BUTTON_15), \ - DEFINE_KEYCODE(BUTTON_16), \ - DEFINE_KEYCODE(LANGUAGE_SWITCH), \ - DEFINE_KEYCODE(MANNER_MODE), \ - DEFINE_KEYCODE(3D_MODE), \ - DEFINE_KEYCODE(CONTACTS), \ - DEFINE_KEYCODE(CALENDAR), \ - DEFINE_KEYCODE(MUSIC), \ - DEFINE_KEYCODE(CALCULATOR), \ - DEFINE_KEYCODE(ZENKAKU_HANKAKU), \ - DEFINE_KEYCODE(EISU), \ - DEFINE_KEYCODE(MUHENKAN), \ - DEFINE_KEYCODE(HENKAN), \ - DEFINE_KEYCODE(KATAKANA_HIRAGANA), \ - DEFINE_KEYCODE(YEN), \ - DEFINE_KEYCODE(RO), \ - DEFINE_KEYCODE(KANA), \ - DEFINE_KEYCODE(ASSIST), \ - DEFINE_KEYCODE(BRIGHTNESS_DOWN), \ - DEFINE_KEYCODE(BRIGHTNESS_UP), \ - DEFINE_KEYCODE(MEDIA_AUDIO_TRACK), \ - DEFINE_KEYCODE(SLEEP), \ - DEFINE_KEYCODE(WAKEUP), \ - DEFINE_KEYCODE(PAIRING), \ - DEFINE_KEYCODE(MEDIA_TOP_MENU), \ - DEFINE_KEYCODE(11), \ - DEFINE_KEYCODE(12), \ - DEFINE_KEYCODE(LAST_CHANNEL), \ - DEFINE_KEYCODE(TV_DATA_SERVICE), \ - DEFINE_KEYCODE(VOICE_ASSIST), \ - DEFINE_KEYCODE(TV_RADIO_SERVICE), \ - DEFINE_KEYCODE(TV_TELETEXT), \ - DEFINE_KEYCODE(TV_NUMBER_ENTRY), \ - DEFINE_KEYCODE(TV_TERRESTRIAL_ANALOG), \ - DEFINE_KEYCODE(TV_TERRESTRIAL_DIGITAL), \ - DEFINE_KEYCODE(TV_SATELLITE), \ - DEFINE_KEYCODE(TV_SATELLITE_BS), \ - DEFINE_KEYCODE(TV_SATELLITE_CS), \ - DEFINE_KEYCODE(TV_SATELLITE_SERVICE), \ - DEFINE_KEYCODE(TV_NETWORK), \ - DEFINE_KEYCODE(TV_ANTENNA_CABLE), \ - DEFINE_KEYCODE(TV_INPUT_HDMI_1), \ - DEFINE_KEYCODE(TV_INPUT_HDMI_2), \ - DEFINE_KEYCODE(TV_INPUT_HDMI_3), \ - DEFINE_KEYCODE(TV_INPUT_HDMI_4), \ - DEFINE_KEYCODE(TV_INPUT_COMPOSITE_1), \ - DEFINE_KEYCODE(TV_INPUT_COMPOSITE_2), \ - DEFINE_KEYCODE(TV_INPUT_COMPONENT_1), \ - DEFINE_KEYCODE(TV_INPUT_COMPONENT_2), \ - DEFINE_KEYCODE(TV_INPUT_VGA_1), \ - DEFINE_KEYCODE(TV_AUDIO_DESCRIPTION), \ - DEFINE_KEYCODE(TV_AUDIO_DESCRIPTION_MIX_UP), \ - DEFINE_KEYCODE(TV_AUDIO_DESCRIPTION_MIX_DOWN), \ - DEFINE_KEYCODE(TV_ZOOM_MODE), \ - DEFINE_KEYCODE(TV_CONTENTS_MENU), \ - DEFINE_KEYCODE(TV_MEDIA_CONTEXT_MENU), \ - DEFINE_KEYCODE(TV_TIMER_PROGRAMMING), \ - DEFINE_KEYCODE(HELP), \ - DEFINE_KEYCODE(NAVIGATE_PREVIOUS), \ - DEFINE_KEYCODE(NAVIGATE_NEXT), \ - DEFINE_KEYCODE(NAVIGATE_IN), \ - DEFINE_KEYCODE(NAVIGATE_OUT), \ - DEFINE_KEYCODE(STEM_PRIMARY), \ - DEFINE_KEYCODE(STEM_1), \ - DEFINE_KEYCODE(STEM_2), \ - DEFINE_KEYCODE(STEM_3), \ - DEFINE_KEYCODE(DPAD_UP_LEFT), \ - DEFINE_KEYCODE(DPAD_DOWN_LEFT), \ - DEFINE_KEYCODE(DPAD_UP_RIGHT), \ - DEFINE_KEYCODE(DPAD_DOWN_RIGHT), \ - DEFINE_KEYCODE(MEDIA_SKIP_FORWARD), \ - DEFINE_KEYCODE(MEDIA_SKIP_BACKWARD), \ - DEFINE_KEYCODE(MEDIA_STEP_FORWARD), \ - DEFINE_KEYCODE(MEDIA_STEP_BACKWARD), \ - DEFINE_KEYCODE(SOFT_SLEEP), \ - DEFINE_KEYCODE(CUT), \ - DEFINE_KEYCODE(COPY), \ - DEFINE_KEYCODE(PASTE), \ - DEFINE_KEYCODE(SYSTEM_NAVIGATION_UP), \ - DEFINE_KEYCODE(SYSTEM_NAVIGATION_DOWN), \ - DEFINE_KEYCODE(SYSTEM_NAVIGATION_LEFT), \ - DEFINE_KEYCODE(SYSTEM_NAVIGATION_RIGHT), \ - DEFINE_KEYCODE(ALL_APPS), \ - DEFINE_KEYCODE(REFRESH), \ - DEFINE_KEYCODE(THUMBS_UP), \ - DEFINE_KEYCODE(THUMBS_DOWN), \ - DEFINE_KEYCODE(PROFILE_SWITCH) - -static const std::unordered_map KEYCODES = { - KEYCODES_SEQUENCE -}; - -static const std::vector KEY_NAMES = { - KEYCODES_SEQUENCE -}; - -// NOTE: If you add a new axis here you must also add it to several other files. -// Refer to frameworks/base/core/java/android/view/MotionEvent.java for the full list. -#define AXES_SEQUENCE \ - DEFINE_AXIS(X), \ - DEFINE_AXIS(Y), \ - DEFINE_AXIS(PRESSURE), \ - DEFINE_AXIS(SIZE), \ - DEFINE_AXIS(TOUCH_MAJOR), \ - DEFINE_AXIS(TOUCH_MINOR), \ - DEFINE_AXIS(TOOL_MAJOR), \ - DEFINE_AXIS(TOOL_MINOR), \ - DEFINE_AXIS(ORIENTATION), \ - DEFINE_AXIS(VSCROLL), \ - DEFINE_AXIS(HSCROLL), \ - DEFINE_AXIS(Z), \ - DEFINE_AXIS(RX), \ - DEFINE_AXIS(RY), \ - DEFINE_AXIS(RZ), \ - DEFINE_AXIS(HAT_X), \ - DEFINE_AXIS(HAT_Y), \ - DEFINE_AXIS(LTRIGGER), \ - DEFINE_AXIS(RTRIGGER), \ - DEFINE_AXIS(THROTTLE), \ - DEFINE_AXIS(RUDDER), \ - DEFINE_AXIS(WHEEL), \ - DEFINE_AXIS(GAS), \ - DEFINE_AXIS(BRAKE), \ - DEFINE_AXIS(DISTANCE), \ - DEFINE_AXIS(TILT), \ - DEFINE_AXIS(SCROLL), \ - DEFINE_AXIS(RELATIVE_X), \ - DEFINE_AXIS(RELATIVE_Y), \ - DEFINE_AXIS(GENERIC_1), \ - DEFINE_AXIS(GENERIC_2), \ - DEFINE_AXIS(GENERIC_3), \ - DEFINE_AXIS(GENERIC_4), \ - DEFINE_AXIS(GENERIC_5), \ - DEFINE_AXIS(GENERIC_6), \ - DEFINE_AXIS(GENERIC_7), \ - DEFINE_AXIS(GENERIC_8), \ - DEFINE_AXIS(GENERIC_9), \ - DEFINE_AXIS(GENERIC_10), \ - DEFINE_AXIS(GENERIC_11), \ - DEFINE_AXIS(GENERIC_12), \ - DEFINE_AXIS(GENERIC_13), \ - DEFINE_AXIS(GENERIC_14), \ - DEFINE_AXIS(GENERIC_15), \ - DEFINE_AXIS(GENERIC_16) +// NOTE: If you want a new key code, axis code, led code or flag code in keylayout file, +// then you must add it to InputEventLabels.cpp. -static const std::unordered_map AXES = { - AXES_SEQUENCE -}; - -static const std::vector AXES_NAMES = { - AXES_SEQUENCE -}; +class InputEventLookup { +public: + static int lookupValueByLabel(const std::unordered_map& map, + const char* literal); -// NOTE: If you add new LEDs here, you must also add them to Input.h -#define LEDS_SEQUENCE \ - DEFINE_LED(NUM_LOCK), \ - DEFINE_LED(CAPS_LOCK), \ - DEFINE_LED(SCROLL_LOCK), \ - DEFINE_LED(COMPOSE), \ - DEFINE_LED(KANA), \ - DEFINE_LED(SLEEP), \ - DEFINE_LED(SUSPEND), \ - DEFINE_LED(MUTE), \ - DEFINE_LED(MISC), \ - DEFINE_LED(MAIL), \ - DEFINE_LED(CHARGING), \ - DEFINE_LED(CONTROLLER_1), \ - DEFINE_LED(CONTROLLER_2), \ - DEFINE_LED(CONTROLLER_3), \ - DEFINE_LED(CONTROLLER_4) + static const char* lookupLabelByValue(const std::vector& vec, int value); -static const std::unordered_map LEDS = { - LEDS_SEQUENCE -}; + static int32_t getKeyCodeByLabel(const char* label); -#define FLAGS_SEQUENCE \ - DEFINE_FLAG(VIRTUAL), \ - DEFINE_FLAG(FUNCTION), \ - DEFINE_FLAG(GESTURE), \ - DEFINE_FLAG(WAKE) + static const char* getLabelByKeyCode(int32_t keyCode); -static const std::unordered_map FLAGS = { - FLAGS_SEQUENCE -}; + static uint32_t getKeyFlagByLabel(const char* label); -static int lookupValueByLabel(const std::unordered_map &map, - const char* literal) { - std::string str(literal); - auto it = map.find(str); - return it != map.end() ? it->second : 0; -} + static int32_t getAxisByLabel(const char* label); -static const char* lookupLabelByValue(const std::vector &vec, int value) { - if (static_cast(value) < vec.size()) { - return vec[value].literal; - } - return nullptr; -} + static const char* getAxisLabel(int32_t axisId); -static inline int32_t getKeyCodeByLabel(const char* label) { - return int32_t(lookupValueByLabel(KEYCODES, label)); -} + static int32_t getLedByLabel(const char* label); -static inline const char* getLabelByKeyCode(int32_t keyCode) { - if (keyCode >= 0 && static_cast(keyCode) < KEYCODES.size()) { - return lookupLabelByValue(KEY_NAMES, keyCode); - } - return nullptr; -} +private: + static const std::unordered_map KEYCODES; -static inline uint32_t getKeyFlagByLabel(const char* label) { - return uint32_t(lookupValueByLabel(FLAGS, label)); -} + static const std::vector KEY_NAMES; -static inline int32_t getAxisByLabel(const char* label) { - return int32_t(lookupValueByLabel(AXES, label)); -} + static const std::unordered_map AXES; -static inline const char* getAxisLabel(int32_t axisId) { - return lookupLabelByValue(AXES_NAMES, axisId); -} + static const std::vector AXES_NAMES; -static inline int32_t getLedByLabel(const char* label) { - return int32_t(lookupValueByLabel(LEDS, label)); -} + static const std::unordered_map LEDS; + static const std::unordered_map FLAGS; +}; } // namespace android #endif // _LIBINPUT_INPUT_EVENT_LABELS_H diff --git a/libs/input/Android.bp b/libs/input/Android.bp index 0c3c1f0483..392d478b15 100644 --- a/libs/input/Android.bp +++ b/libs/input/Android.bp @@ -32,6 +32,7 @@ cc_library { srcs: [ "Input.cpp", "InputDevice.cpp", + "InputEventLabels.cpp", "Keyboard.cpp", "KeyCharacterMap.cpp", "KeyLayoutMap.cpp", diff --git a/libs/input/Input.cpp b/libs/input/Input.cpp index fc73de3ca5..51910fe6f9 100644 --- a/libs/input/Input.cpp +++ b/libs/input/Input.cpp @@ -135,11 +135,11 @@ int32_t InputEvent::nextId() { // --- KeyEvent --- const char* KeyEvent::getLabel(int32_t keyCode) { - return getLabelByKeyCode(keyCode); + return InputEventLookup::getLabelByKeyCode(keyCode); } int32_t KeyEvent::getKeyCodeFromLabel(const char* label) { - return getKeyCodeByLabel(label); + return InputEventLookup::getKeyCodeByLabel(label); } void KeyEvent::initialize(int32_t id, int32_t deviceId, uint32_t source, int32_t displayId, @@ -692,11 +692,11 @@ bool MotionEvent::isTouchEvent(uint32_t source, int32_t action) { } const char* MotionEvent::getLabel(int32_t axis) { - return getAxisLabel(axis); + return InputEventLookup::getAxisLabel(axis); } int32_t MotionEvent::getAxisFromLabel(const char* label) { - return getAxisByLabel(label); + return InputEventLookup::getAxisByLabel(label); } const char* MotionEvent::actionToString(int32_t action) { diff --git a/libs/input/InputEventLabels.cpp b/libs/input/InputEventLabels.cpp new file mode 100644 index 0000000000..dee240c0bf --- /dev/null +++ b/libs/input/InputEventLabels.cpp @@ -0,0 +1,448 @@ +/* + * Copyright (C) 2020 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 + +#define DEFINE_KEYCODE(key) { #key, AKEYCODE_##key } +#define DEFINE_AXIS(axis) { #axis, AMOTION_EVENT_AXIS_##axis } +#define DEFINE_LED(led) { #led, ALED_##led } +#define DEFINE_FLAG(flag) { #flag, POLICY_FLAG_##flag } + +namespace android { + +// NOTE: If you add a new keycode here you must also add it to several other files. +// Refer to frameworks/base/core/java/android/view/KeyEvent.java for the full list. +#define KEYCODES_SEQUENCE \ + DEFINE_KEYCODE(UNKNOWN), \ + DEFINE_KEYCODE(SOFT_LEFT), \ + DEFINE_KEYCODE(SOFT_RIGHT), \ + DEFINE_KEYCODE(HOME), \ + DEFINE_KEYCODE(BACK), \ + DEFINE_KEYCODE(CALL), \ + DEFINE_KEYCODE(ENDCALL), \ + DEFINE_KEYCODE(0), \ + DEFINE_KEYCODE(1), \ + DEFINE_KEYCODE(2), \ + DEFINE_KEYCODE(3), \ + DEFINE_KEYCODE(4), \ + DEFINE_KEYCODE(5), \ + DEFINE_KEYCODE(6), \ + DEFINE_KEYCODE(7), \ + DEFINE_KEYCODE(8), \ + DEFINE_KEYCODE(9), \ + DEFINE_KEYCODE(STAR), \ + DEFINE_KEYCODE(POUND), \ + DEFINE_KEYCODE(DPAD_UP), \ + DEFINE_KEYCODE(DPAD_DOWN), \ + DEFINE_KEYCODE(DPAD_LEFT), \ + DEFINE_KEYCODE(DPAD_RIGHT), \ + DEFINE_KEYCODE(DPAD_CENTER), \ + DEFINE_KEYCODE(VOLUME_UP), \ + DEFINE_KEYCODE(VOLUME_DOWN), \ + DEFINE_KEYCODE(POWER), \ + DEFINE_KEYCODE(CAMERA), \ + DEFINE_KEYCODE(CLEAR), \ + DEFINE_KEYCODE(A), \ + DEFINE_KEYCODE(B), \ + DEFINE_KEYCODE(C), \ + DEFINE_KEYCODE(D), \ + DEFINE_KEYCODE(E), \ + DEFINE_KEYCODE(F), \ + DEFINE_KEYCODE(G), \ + DEFINE_KEYCODE(H), \ + DEFINE_KEYCODE(I), \ + DEFINE_KEYCODE(J), \ + DEFINE_KEYCODE(K), \ + DEFINE_KEYCODE(L), \ + DEFINE_KEYCODE(M), \ + DEFINE_KEYCODE(N), \ + DEFINE_KEYCODE(O), \ + DEFINE_KEYCODE(P), \ + DEFINE_KEYCODE(Q), \ + DEFINE_KEYCODE(R), \ + DEFINE_KEYCODE(S), \ + DEFINE_KEYCODE(T), \ + DEFINE_KEYCODE(U), \ + DEFINE_KEYCODE(V), \ + DEFINE_KEYCODE(W), \ + DEFINE_KEYCODE(X), \ + DEFINE_KEYCODE(Y), \ + DEFINE_KEYCODE(Z), \ + DEFINE_KEYCODE(COMMA), \ + DEFINE_KEYCODE(PERIOD), \ + DEFINE_KEYCODE(ALT_LEFT), \ + DEFINE_KEYCODE(ALT_RIGHT), \ + DEFINE_KEYCODE(SHIFT_LEFT), \ + DEFINE_KEYCODE(SHIFT_RIGHT), \ + DEFINE_KEYCODE(TAB), \ + DEFINE_KEYCODE(SPACE), \ + DEFINE_KEYCODE(SYM), \ + DEFINE_KEYCODE(EXPLORER), \ + DEFINE_KEYCODE(ENVELOPE), \ + DEFINE_KEYCODE(ENTER), \ + DEFINE_KEYCODE(DEL), \ + DEFINE_KEYCODE(GRAVE), \ + DEFINE_KEYCODE(MINUS), \ + DEFINE_KEYCODE(EQUALS), \ + DEFINE_KEYCODE(LEFT_BRACKET), \ + DEFINE_KEYCODE(RIGHT_BRACKET), \ + DEFINE_KEYCODE(BACKSLASH), \ + DEFINE_KEYCODE(SEMICOLON), \ + DEFINE_KEYCODE(APOSTROPHE), \ + DEFINE_KEYCODE(SLASH), \ + DEFINE_KEYCODE(AT), \ + DEFINE_KEYCODE(NUM), \ + DEFINE_KEYCODE(HEADSETHOOK), \ + DEFINE_KEYCODE(FOCUS), \ + DEFINE_KEYCODE(PLUS), \ + DEFINE_KEYCODE(MENU), \ + DEFINE_KEYCODE(NOTIFICATION), \ + DEFINE_KEYCODE(SEARCH), \ + DEFINE_KEYCODE(MEDIA_PLAY_PAUSE), \ + DEFINE_KEYCODE(MEDIA_STOP), \ + DEFINE_KEYCODE(MEDIA_NEXT), \ + DEFINE_KEYCODE(MEDIA_PREVIOUS), \ + DEFINE_KEYCODE(MEDIA_REWIND), \ + DEFINE_KEYCODE(MEDIA_FAST_FORWARD), \ + DEFINE_KEYCODE(MUTE), \ + DEFINE_KEYCODE(PAGE_UP), \ + DEFINE_KEYCODE(PAGE_DOWN), \ + DEFINE_KEYCODE(PICTSYMBOLS), \ + DEFINE_KEYCODE(SWITCH_CHARSET), \ + DEFINE_KEYCODE(BUTTON_A), \ + DEFINE_KEYCODE(BUTTON_B), \ + DEFINE_KEYCODE(BUTTON_C), \ + DEFINE_KEYCODE(BUTTON_X), \ + DEFINE_KEYCODE(BUTTON_Y), \ + DEFINE_KEYCODE(BUTTON_Z), \ + DEFINE_KEYCODE(BUTTON_L1), \ + DEFINE_KEYCODE(BUTTON_R1), \ + DEFINE_KEYCODE(BUTTON_L2), \ + DEFINE_KEYCODE(BUTTON_R2), \ + DEFINE_KEYCODE(BUTTON_THUMBL), \ + DEFINE_KEYCODE(BUTTON_THUMBR), \ + DEFINE_KEYCODE(BUTTON_START), \ + DEFINE_KEYCODE(BUTTON_SELECT), \ + DEFINE_KEYCODE(BUTTON_MODE), \ + DEFINE_KEYCODE(ESCAPE), \ + DEFINE_KEYCODE(FORWARD_DEL), \ + DEFINE_KEYCODE(CTRL_LEFT), \ + DEFINE_KEYCODE(CTRL_RIGHT), \ + DEFINE_KEYCODE(CAPS_LOCK), \ + DEFINE_KEYCODE(SCROLL_LOCK), \ + DEFINE_KEYCODE(META_LEFT), \ + DEFINE_KEYCODE(META_RIGHT), \ + DEFINE_KEYCODE(FUNCTION), \ + DEFINE_KEYCODE(SYSRQ), \ + DEFINE_KEYCODE(BREAK), \ + DEFINE_KEYCODE(MOVE_HOME), \ + DEFINE_KEYCODE(MOVE_END), \ + DEFINE_KEYCODE(INSERT), \ + DEFINE_KEYCODE(FORWARD), \ + DEFINE_KEYCODE(MEDIA_PLAY), \ + DEFINE_KEYCODE(MEDIA_PAUSE), \ + DEFINE_KEYCODE(MEDIA_CLOSE), \ + DEFINE_KEYCODE(MEDIA_EJECT), \ + DEFINE_KEYCODE(MEDIA_RECORD), \ + DEFINE_KEYCODE(F1), \ + DEFINE_KEYCODE(F2), \ + DEFINE_KEYCODE(F3), \ + DEFINE_KEYCODE(F4), \ + DEFINE_KEYCODE(F5), \ + DEFINE_KEYCODE(F6), \ + DEFINE_KEYCODE(F7), \ + DEFINE_KEYCODE(F8), \ + DEFINE_KEYCODE(F9), \ + DEFINE_KEYCODE(F10), \ + DEFINE_KEYCODE(F11), \ + DEFINE_KEYCODE(F12), \ + DEFINE_KEYCODE(NUM_LOCK), \ + DEFINE_KEYCODE(NUMPAD_0), \ + DEFINE_KEYCODE(NUMPAD_1), \ + DEFINE_KEYCODE(NUMPAD_2), \ + DEFINE_KEYCODE(NUMPAD_3), \ + DEFINE_KEYCODE(NUMPAD_4), \ + DEFINE_KEYCODE(NUMPAD_5), \ + DEFINE_KEYCODE(NUMPAD_6), \ + DEFINE_KEYCODE(NUMPAD_7), \ + DEFINE_KEYCODE(NUMPAD_8), \ + DEFINE_KEYCODE(NUMPAD_9), \ + DEFINE_KEYCODE(NUMPAD_DIVIDE), \ + DEFINE_KEYCODE(NUMPAD_MULTIPLY), \ + DEFINE_KEYCODE(NUMPAD_SUBTRACT), \ + DEFINE_KEYCODE(NUMPAD_ADD), \ + DEFINE_KEYCODE(NUMPAD_DOT), \ + DEFINE_KEYCODE(NUMPAD_COMMA), \ + DEFINE_KEYCODE(NUMPAD_ENTER), \ + DEFINE_KEYCODE(NUMPAD_EQUALS), \ + DEFINE_KEYCODE(NUMPAD_LEFT_PAREN), \ + DEFINE_KEYCODE(NUMPAD_RIGHT_PAREN), \ + DEFINE_KEYCODE(VOLUME_MUTE), \ + DEFINE_KEYCODE(INFO), \ + DEFINE_KEYCODE(CHANNEL_UP), \ + DEFINE_KEYCODE(CHANNEL_DOWN), \ + DEFINE_KEYCODE(ZOOM_IN), \ + DEFINE_KEYCODE(ZOOM_OUT), \ + DEFINE_KEYCODE(TV), \ + DEFINE_KEYCODE(WINDOW), \ + DEFINE_KEYCODE(GUIDE), \ + DEFINE_KEYCODE(DVR), \ + DEFINE_KEYCODE(BOOKMARK), \ + DEFINE_KEYCODE(CAPTIONS), \ + DEFINE_KEYCODE(SETTINGS), \ + DEFINE_KEYCODE(TV_POWER), \ + DEFINE_KEYCODE(TV_INPUT), \ + DEFINE_KEYCODE(STB_POWER), \ + DEFINE_KEYCODE(STB_INPUT), \ + DEFINE_KEYCODE(AVR_POWER), \ + DEFINE_KEYCODE(AVR_INPUT), \ + DEFINE_KEYCODE(PROG_RED), \ + DEFINE_KEYCODE(PROG_GREEN), \ + DEFINE_KEYCODE(PROG_YELLOW), \ + DEFINE_KEYCODE(PROG_BLUE), \ + DEFINE_KEYCODE(APP_SWITCH), \ + DEFINE_KEYCODE(BUTTON_1), \ + DEFINE_KEYCODE(BUTTON_2), \ + DEFINE_KEYCODE(BUTTON_3), \ + DEFINE_KEYCODE(BUTTON_4), \ + DEFINE_KEYCODE(BUTTON_5), \ + DEFINE_KEYCODE(BUTTON_6), \ + DEFINE_KEYCODE(BUTTON_7), \ + DEFINE_KEYCODE(BUTTON_8), \ + DEFINE_KEYCODE(BUTTON_9), \ + DEFINE_KEYCODE(BUTTON_10), \ + DEFINE_KEYCODE(BUTTON_11), \ + DEFINE_KEYCODE(BUTTON_12), \ + DEFINE_KEYCODE(BUTTON_13), \ + DEFINE_KEYCODE(BUTTON_14), \ + DEFINE_KEYCODE(BUTTON_15), \ + DEFINE_KEYCODE(BUTTON_16), \ + DEFINE_KEYCODE(LANGUAGE_SWITCH), \ + DEFINE_KEYCODE(MANNER_MODE), \ + DEFINE_KEYCODE(3D_MODE), \ + DEFINE_KEYCODE(CONTACTS), \ + DEFINE_KEYCODE(CALENDAR), \ + DEFINE_KEYCODE(MUSIC), \ + DEFINE_KEYCODE(CALCULATOR), \ + DEFINE_KEYCODE(ZENKAKU_HANKAKU), \ + DEFINE_KEYCODE(EISU), \ + DEFINE_KEYCODE(MUHENKAN), \ + DEFINE_KEYCODE(HENKAN), \ + DEFINE_KEYCODE(KATAKANA_HIRAGANA), \ + DEFINE_KEYCODE(YEN), \ + DEFINE_KEYCODE(RO), \ + DEFINE_KEYCODE(KANA), \ + DEFINE_KEYCODE(ASSIST), \ + DEFINE_KEYCODE(BRIGHTNESS_DOWN), \ + DEFINE_KEYCODE(BRIGHTNESS_UP), \ + DEFINE_KEYCODE(MEDIA_AUDIO_TRACK), \ + DEFINE_KEYCODE(SLEEP), \ + DEFINE_KEYCODE(WAKEUP), \ + DEFINE_KEYCODE(PAIRING), \ + DEFINE_KEYCODE(MEDIA_TOP_MENU), \ + DEFINE_KEYCODE(11), \ + DEFINE_KEYCODE(12), \ + DEFINE_KEYCODE(LAST_CHANNEL), \ + DEFINE_KEYCODE(TV_DATA_SERVICE), \ + DEFINE_KEYCODE(VOICE_ASSIST), \ + DEFINE_KEYCODE(TV_RADIO_SERVICE), \ + DEFINE_KEYCODE(TV_TELETEXT), \ + DEFINE_KEYCODE(TV_NUMBER_ENTRY), \ + DEFINE_KEYCODE(TV_TERRESTRIAL_ANALOG), \ + DEFINE_KEYCODE(TV_TERRESTRIAL_DIGITAL), \ + DEFINE_KEYCODE(TV_SATELLITE), \ + DEFINE_KEYCODE(TV_SATELLITE_BS), \ + DEFINE_KEYCODE(TV_SATELLITE_CS), \ + DEFINE_KEYCODE(TV_SATELLITE_SERVICE), \ + DEFINE_KEYCODE(TV_NETWORK), \ + DEFINE_KEYCODE(TV_ANTENNA_CABLE), \ + DEFINE_KEYCODE(TV_INPUT_HDMI_1), \ + DEFINE_KEYCODE(TV_INPUT_HDMI_2), \ + DEFINE_KEYCODE(TV_INPUT_HDMI_3), \ + DEFINE_KEYCODE(TV_INPUT_HDMI_4), \ + DEFINE_KEYCODE(TV_INPUT_COMPOSITE_1), \ + DEFINE_KEYCODE(TV_INPUT_COMPOSITE_2), \ + DEFINE_KEYCODE(TV_INPUT_COMPONENT_1), \ + DEFINE_KEYCODE(TV_INPUT_COMPONENT_2), \ + DEFINE_KEYCODE(TV_INPUT_VGA_1), \ + DEFINE_KEYCODE(TV_AUDIO_DESCRIPTION), \ + DEFINE_KEYCODE(TV_AUDIO_DESCRIPTION_MIX_UP), \ + DEFINE_KEYCODE(TV_AUDIO_DESCRIPTION_MIX_DOWN), \ + DEFINE_KEYCODE(TV_ZOOM_MODE), \ + DEFINE_KEYCODE(TV_CONTENTS_MENU), \ + DEFINE_KEYCODE(TV_MEDIA_CONTEXT_MENU), \ + DEFINE_KEYCODE(TV_TIMER_PROGRAMMING), \ + DEFINE_KEYCODE(HELP), \ + DEFINE_KEYCODE(NAVIGATE_PREVIOUS), \ + DEFINE_KEYCODE(NAVIGATE_NEXT), \ + DEFINE_KEYCODE(NAVIGATE_IN), \ + DEFINE_KEYCODE(NAVIGATE_OUT), \ + DEFINE_KEYCODE(STEM_PRIMARY), \ + DEFINE_KEYCODE(STEM_1), \ + DEFINE_KEYCODE(STEM_2), \ + DEFINE_KEYCODE(STEM_3), \ + DEFINE_KEYCODE(DPAD_UP_LEFT), \ + DEFINE_KEYCODE(DPAD_DOWN_LEFT), \ + DEFINE_KEYCODE(DPAD_UP_RIGHT), \ + DEFINE_KEYCODE(DPAD_DOWN_RIGHT), \ + DEFINE_KEYCODE(MEDIA_SKIP_FORWARD), \ + DEFINE_KEYCODE(MEDIA_SKIP_BACKWARD), \ + DEFINE_KEYCODE(MEDIA_STEP_FORWARD), \ + DEFINE_KEYCODE(MEDIA_STEP_BACKWARD), \ + DEFINE_KEYCODE(SOFT_SLEEP), \ + DEFINE_KEYCODE(CUT), \ + DEFINE_KEYCODE(COPY), \ + DEFINE_KEYCODE(PASTE), \ + DEFINE_KEYCODE(SYSTEM_NAVIGATION_UP), \ + DEFINE_KEYCODE(SYSTEM_NAVIGATION_DOWN), \ + DEFINE_KEYCODE(SYSTEM_NAVIGATION_LEFT), \ + DEFINE_KEYCODE(SYSTEM_NAVIGATION_RIGHT), \ + DEFINE_KEYCODE(ALL_APPS), \ + DEFINE_KEYCODE(REFRESH), \ + DEFINE_KEYCODE(THUMBS_UP), \ + DEFINE_KEYCODE(THUMBS_DOWN), \ + DEFINE_KEYCODE(PROFILE_SWITCH) + +// NOTE: If you add a new axis here you must also add it to several other files. +// Refer to frameworks/base/core/java/android/view/MotionEvent.java for the full list. +#define AXES_SEQUENCE \ + DEFINE_AXIS(X), \ + DEFINE_AXIS(Y), \ + DEFINE_AXIS(PRESSURE), \ + DEFINE_AXIS(SIZE), \ + DEFINE_AXIS(TOUCH_MAJOR), \ + DEFINE_AXIS(TOUCH_MINOR), \ + DEFINE_AXIS(TOOL_MAJOR), \ + DEFINE_AXIS(TOOL_MINOR), \ + DEFINE_AXIS(ORIENTATION), \ + DEFINE_AXIS(VSCROLL), \ + DEFINE_AXIS(HSCROLL), \ + DEFINE_AXIS(Z), \ + DEFINE_AXIS(RX), \ + DEFINE_AXIS(RY), \ + DEFINE_AXIS(RZ), \ + DEFINE_AXIS(HAT_X), \ + DEFINE_AXIS(HAT_Y), \ + DEFINE_AXIS(LTRIGGER), \ + DEFINE_AXIS(RTRIGGER), \ + DEFINE_AXIS(THROTTLE), \ + DEFINE_AXIS(RUDDER), \ + DEFINE_AXIS(WHEEL), \ + DEFINE_AXIS(GAS), \ + DEFINE_AXIS(BRAKE), \ + DEFINE_AXIS(DISTANCE), \ + DEFINE_AXIS(TILT), \ + DEFINE_AXIS(SCROLL), \ + DEFINE_AXIS(RELATIVE_X), \ + DEFINE_AXIS(RELATIVE_Y), \ + DEFINE_AXIS(GENERIC_1), \ + DEFINE_AXIS(GENERIC_2), \ + DEFINE_AXIS(GENERIC_3), \ + DEFINE_AXIS(GENERIC_4), \ + DEFINE_AXIS(GENERIC_5), \ + DEFINE_AXIS(GENERIC_6), \ + DEFINE_AXIS(GENERIC_7), \ + DEFINE_AXIS(GENERIC_8), \ + DEFINE_AXIS(GENERIC_9), \ + DEFINE_AXIS(GENERIC_10), \ + DEFINE_AXIS(GENERIC_11), \ + DEFINE_AXIS(GENERIC_12), \ + DEFINE_AXIS(GENERIC_13), \ + DEFINE_AXIS(GENERIC_14), \ + DEFINE_AXIS(GENERIC_15), \ + DEFINE_AXIS(GENERIC_16) + + +// NOTE: If you add new LEDs here, you must also add them to Input.h +#define LEDS_SEQUENCE \ + DEFINE_LED(NUM_LOCK), \ + DEFINE_LED(CAPS_LOCK), \ + DEFINE_LED(SCROLL_LOCK), \ + DEFINE_LED(COMPOSE), \ + DEFINE_LED(KANA), \ + DEFINE_LED(SLEEP), \ + DEFINE_LED(SUSPEND), \ + DEFINE_LED(MUTE), \ + DEFINE_LED(MISC), \ + DEFINE_LED(MAIL), \ + DEFINE_LED(CHARGING), \ + DEFINE_LED(CONTROLLER_1), \ + DEFINE_LED(CONTROLLER_2), \ + DEFINE_LED(CONTROLLER_3), \ + DEFINE_LED(CONTROLLER_4) + +#define FLAGS_SEQUENCE \ + DEFINE_FLAG(VIRTUAL), \ + DEFINE_FLAG(FUNCTION), \ + DEFINE_FLAG(GESTURE), \ + DEFINE_FLAG(WAKE) + +// --- InputEventLookup --- +const std::unordered_map InputEventLookup::KEYCODES = {KEYCODES_SEQUENCE}; + +const std::vector InputEventLookup::KEY_NAMES = {KEYCODES_SEQUENCE}; + +const std::unordered_map InputEventLookup::AXES = {AXES_SEQUENCE}; + +const std::vector InputEventLookup::AXES_NAMES = {AXES_SEQUENCE}; + +const std::unordered_map InputEventLookup::LEDS = {LEDS_SEQUENCE}; + +const std::unordered_map InputEventLookup::FLAGS = {FLAGS_SEQUENCE}; + +int InputEventLookup::lookupValueByLabel(const std::unordered_map& map, + const char* literal) { + std::string str(literal); + auto it = map.find(str); + return it != map.end() ? it->second : 0; +} + +const char* InputEventLookup::lookupLabelByValue(const std::vector& vec, + int value) { + if (static_cast(value) < vec.size()) { + return vec[value].literal; + } + return nullptr; +} + +int32_t InputEventLookup::getKeyCodeByLabel(const char* label) { + return int32_t(lookupValueByLabel(KEYCODES, label)); +} + +const char* InputEventLookup::getLabelByKeyCode(int32_t keyCode) { + if (keyCode >= 0 && static_cast(keyCode) < KEYCODES.size()) { + return lookupLabelByValue(KEY_NAMES, keyCode); + } + return nullptr; +} + +uint32_t InputEventLookup::getKeyFlagByLabel(const char* label) { + return uint32_t(lookupValueByLabel(FLAGS, label)); +} + +int32_t InputEventLookup::getAxisByLabel(const char* label) { + return int32_t(lookupValueByLabel(AXES, label)); +} + +const char* InputEventLookup::getAxisLabel(int32_t axisId) { + return lookupLabelByValue(AXES_NAMES, axisId); +} + +int32_t InputEventLookup::getLedByLabel(const char* label) { + return int32_t(lookupValueByLabel(LEDS, label)); +} + +} // namespace android diff --git a/libs/input/KeyCharacterMap.cpp b/libs/input/KeyCharacterMap.cpp index cb68165433..5c03d50fbc 100644 --- a/libs/input/KeyCharacterMap.cpp +++ b/libs/input/KeyCharacterMap.cpp @@ -880,7 +880,7 @@ status_t KeyCharacterMap::Parser::parseMapKey() { mTokenizer->skipDelimiters(WHITESPACE); String8 keyCodeToken = mTokenizer->nextToken(WHITESPACE); - int32_t keyCode = getKeyCodeByLabel(keyCodeToken.string()); + int32_t keyCode = InputEventLookup::getKeyCodeByLabel(keyCodeToken.string()); if (!keyCode) { ALOGE("%s: Expected key code label, got '%s'.", mTokenizer->getLocation().string(), keyCodeToken.string()); @@ -897,7 +897,7 @@ status_t KeyCharacterMap::Parser::parseMapKey() { status_t KeyCharacterMap::Parser::parseKey() { String8 keyCodeToken = mTokenizer->nextToken(WHITESPACE); - int32_t keyCode = getKeyCodeByLabel(keyCodeToken.string()); + int32_t keyCode = InputEventLookup::getKeyCodeByLabel(keyCodeToken.string()); if (!keyCode) { ALOGE("%s: Expected key code label, got '%s'.", mTokenizer->getLocation().string(), keyCodeToken.string()); @@ -1017,7 +1017,7 @@ status_t KeyCharacterMap::Parser::parseKeyProperty() { } else if (token == "fallback") { mTokenizer->skipDelimiters(WHITESPACE); token = mTokenizer->nextToken(WHITESPACE); - int32_t keyCode = getKeyCodeByLabel(token.string()); + int32_t keyCode = InputEventLookup::getKeyCodeByLabel(token.string()); if (!keyCode) { ALOGE("%s: Invalid key code label for fallback behavior, got '%s'.", mTokenizer->getLocation().string(), @@ -1034,7 +1034,7 @@ status_t KeyCharacterMap::Parser::parseKeyProperty() { } else if (token == "replace") { mTokenizer->skipDelimiters(WHITESPACE); token = mTokenizer->nextToken(WHITESPACE); - int32_t keyCode = getKeyCodeByLabel(token.string()); + int32_t keyCode = InputEventLookup::getKeyCodeByLabel(token.string()); if (!keyCode) { ALOGE("%s: Invalid key code label for replace, got '%s'.", mTokenizer->getLocation().string(), diff --git a/libs/input/KeyLayoutMap.cpp b/libs/input/KeyLayoutMap.cpp index efca68d171..9c399b3fa1 100644 --- a/libs/input/KeyLayoutMap.cpp +++ b/libs/input/KeyLayoutMap.cpp @@ -264,7 +264,7 @@ status_t KeyLayoutMap::Parser::parseKey() { mTokenizer->skipDelimiters(WHITESPACE); String8 keyCodeToken = mTokenizer->nextToken(WHITESPACE); - int32_t keyCode = getKeyCodeByLabel(keyCodeToken.string()); + int32_t keyCode = InputEventLookup::getKeyCodeByLabel(keyCodeToken.string()); if (!keyCode) { ALOGE("%s: Expected key code label, got '%s'.", mTokenizer->getLocation().string(), keyCodeToken.string()); @@ -277,7 +277,7 @@ status_t KeyLayoutMap::Parser::parseKey() { if (mTokenizer->isEol() || mTokenizer->peekChar() == '#') break; String8 flagToken = mTokenizer->nextToken(WHITESPACE); - uint32_t flag = getKeyFlagByLabel(flagToken.string()); + uint32_t flag = InputEventLookup::getKeyFlagByLabel(flagToken.string()); if (!flag) { ALOGE("%s: Expected key flag label, got '%s'.", mTokenizer->getLocation().string(), flagToken.string()); @@ -326,7 +326,7 @@ status_t KeyLayoutMap::Parser::parseAxis() { mTokenizer->skipDelimiters(WHITESPACE); String8 axisToken = mTokenizer->nextToken(WHITESPACE); - axisInfo.axis = getAxisByLabel(axisToken.string()); + axisInfo.axis = InputEventLookup::getAxisByLabel(axisToken.string()); if (axisInfo.axis < 0) { ALOGE("%s: Expected inverted axis label, got '%s'.", mTokenizer->getLocation().string(), axisToken.string()); @@ -346,7 +346,7 @@ status_t KeyLayoutMap::Parser::parseAxis() { mTokenizer->skipDelimiters(WHITESPACE); String8 lowAxisToken = mTokenizer->nextToken(WHITESPACE); - axisInfo.axis = getAxisByLabel(lowAxisToken.string()); + axisInfo.axis = InputEventLookup::getAxisByLabel(lowAxisToken.string()); if (axisInfo.axis < 0) { ALOGE("%s: Expected low axis label, got '%s'.", mTokenizer->getLocation().string(), lowAxisToken.string()); @@ -355,14 +355,14 @@ status_t KeyLayoutMap::Parser::parseAxis() { mTokenizer->skipDelimiters(WHITESPACE); String8 highAxisToken = mTokenizer->nextToken(WHITESPACE); - axisInfo.highAxis = getAxisByLabel(highAxisToken.string()); + axisInfo.highAxis = InputEventLookup::getAxisByLabel(highAxisToken.string()); if (axisInfo.highAxis < 0) { ALOGE("%s: Expected high axis label, got '%s'.", mTokenizer->getLocation().string(), highAxisToken.string()); return BAD_VALUE; } } else { - axisInfo.axis = getAxisByLabel(token.string()); + axisInfo.axis = InputEventLookup::getAxisByLabel(token.string()); if (axisInfo.axis < 0) { ALOGE("%s: Expected axis label, 'split' or 'invert', got '%s'.", mTokenizer->getLocation().string(), token.string()); @@ -428,7 +428,7 @@ status_t KeyLayoutMap::Parser::parseLed() { mTokenizer->skipDelimiters(WHITESPACE); String8 ledCodeToken = mTokenizer->nextToken(WHITESPACE); - int32_t ledCode = getLedByLabel(ledCodeToken.string()); + int32_t ledCode = InputEventLookup::getLedByLabel(ledCodeToken.string()); if (ledCode < 0) { ALOGE("%s: Expected LED code label, got '%s'.", mTokenizer->getLocation().string(), ledCodeToken.string()); diff --git a/services/inputflinger/reader/InputDevice.cpp b/services/inputflinger/reader/InputDevice.cpp index 14f922f82d..c63c1797a9 100644 --- a/services/inputflinger/reader/InputDevice.cpp +++ b/services/inputflinger/reader/InputDevice.cpp @@ -108,7 +108,7 @@ void InputDevice::dump(std::string& dump) { dump += INDENT2 "Motion Ranges:\n"; for (size_t i = 0; i < ranges.size(); i++) { const InputDeviceInfo::MotionRange& range = ranges[i]; - const char* label = getAxisLabel(range.axis); + const char* label = InputEventLookup::getAxisLabel(range.axis); char name[32]; if (label) { strncpy(name, label, sizeof(name)); diff --git a/services/inputflinger/reader/mapper/JoystickInputMapper.cpp b/services/inputflinger/reader/mapper/JoystickInputMapper.cpp index 57acba5055..abd8aa9119 100644 --- a/services/inputflinger/reader/mapper/JoystickInputMapper.cpp +++ b/services/inputflinger/reader/mapper/JoystickInputMapper.cpp @@ -73,14 +73,14 @@ void JoystickInputMapper::dump(std::string& dump) { dump += INDENT3 "Axes:\n"; for (const auto& [rawAxis, axis] : mAxes) { - const char* label = getAxisLabel(axis.axisInfo.axis); + const char* label = InputEventLookup::getAxisLabel(axis.axisInfo.axis); if (label) { dump += StringPrintf(INDENT4 "%s", label); } else { dump += StringPrintf(INDENT4 "%d", axis.axisInfo.axis); } if (axis.axisInfo.mode == AxisInfo::MODE_SPLIT) { - label = getAxisLabel(axis.axisInfo.highAxis); + label = InputEventLookup::getAxisLabel(axis.axisInfo.highAxis); if (label) { dump += StringPrintf(" / %s (split at %d)", label, axis.axisInfo.splitValue); } else { -- cgit v1.2.3-59-g8ed1b From 09c8d2d004d715d33419f6abfc36f289051bdd3d Mon Sep 17 00:00:00 2001 From: chaviw Date: Mon, 24 Aug 2020 15:48:26 -0700 Subject: Created libattestation Move attestation logic from input into separate library. This way Input and SurfaceFlinger can leverage the same logic Test: inputflinger_test Test: attestation_tests Bug: 155825630 Change-Id: Ia4f65166da8a1c53a9570db59eab602190438696 --- include/attestation/HmacKeyManager.h | 32 ++++++ include/input/Input.h | 5 - libs/attestation/Android.bp | 31 ++++++ libs/attestation/HmacKeyManager.cpp | 52 +++++++++ libs/attestation/OWNERS | 2 + libs/attestation/TEST_MAPPING | 7 ++ libs/attestation/tests/Android.bp | 28 +++++ libs/attestation/tests/HmacKeyManager_test.cpp | 52 +++++++++ libs/input/Input.cpp | 1 + libs/input/KeyCharacterMap.cpp | 3 +- libs/input/tests/InputEvent_test.cpp | 1 + .../input/tests/InputPublisherAndConsumer_test.cpp | 3 +- libs/input/tests/VelocityTracker_test.cpp | 1 + libs/input/tests/VerifiedInputEvent_test.cpp | 1 + services/inputflinger/Android.bp | 3 + services/inputflinger/benchmarks/Android.bp | 1 + services/inputflinger/dispatcher/Android.bp | 3 + .../inputflinger/dispatcher/InputDispatcher.cpp | 73 ++++--------- services/inputflinger/dispatcher/InputDispatcher.h | 13 +-- .../inputflinger/tests/InputDispatcher_test.cpp | 121 ++++++++++----------- 20 files changed, 299 insertions(+), 134 deletions(-) create mode 100644 include/attestation/HmacKeyManager.h create mode 100644 libs/attestation/Android.bp create mode 100644 libs/attestation/HmacKeyManager.cpp create mode 100644 libs/attestation/OWNERS create mode 100644 libs/attestation/TEST_MAPPING create mode 100644 libs/attestation/tests/Android.bp create mode 100644 libs/attestation/tests/HmacKeyManager_test.cpp (limited to 'libs/input/KeyCharacterMap.cpp') diff --git a/include/attestation/HmacKeyManager.h b/include/attestation/HmacKeyManager.h new file mode 100644 index 0000000000..571a361889 --- /dev/null +++ b/include/attestation/HmacKeyManager.h @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2020 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 + +namespace android { +/** + * Invalid value of HMAC - SHA256. Any events with this HMAC value will be marked as not verified. + */ +constexpr std::array INVALID_HMAC = {0}; + +class HmacKeyManager { +public: + HmacKeyManager(); + std::array sign(const uint8_t* data, size_t size) const; +private: + const std::array mHmacKey; +}; +} // namespace android \ No newline at end of file diff --git a/include/input/Input.h b/include/input/Input.h index d40ba439db..7b66d3cac8 100644 --- a/include/input/Input.h +++ b/include/input/Input.h @@ -312,11 +312,6 @@ private: */ constexpr float AMOTION_EVENT_INVALID_CURSOR_POSITION = std::numeric_limits::quiet_NaN(); -/** - * Invalid value of HMAC - SHA256. Any events with this HMAC value will be marked as not verified. - */ -constexpr std::array INVALID_HMAC = {0}; - /* * Pointer coordinate data. */ diff --git a/libs/attestation/Android.bp b/libs/attestation/Android.bp new file mode 100644 index 0000000000..b85aecd16d --- /dev/null +++ b/libs/attestation/Android.bp @@ -0,0 +1,31 @@ +// Copyright (C) 2020 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. +cc_library_static { + name: "libattestation", + cflags: [ + "-Wall", + "-Wextra", + "-Werror", + ], + srcs: [ + "HmacKeyManager.cpp" + ], + + clang: true, + + shared_libs: [ + "liblog", + "libcrypto", + ], +} \ No newline at end of file diff --git a/libs/attestation/HmacKeyManager.cpp b/libs/attestation/HmacKeyManager.cpp new file mode 100644 index 0000000000..b15f143014 --- /dev/null +++ b/libs/attestation/HmacKeyManager.cpp @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2020 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 +#include +#include +#include + +namespace android { + +static std::array getRandomKey() { + std::array key; + if (RAND_bytes(key.data(), key.size()) != 1) { + LOG_ALWAYS_FATAL("Can't generate HMAC key"); + } + return key; +} + +HmacKeyManager::HmacKeyManager() : mHmacKey(getRandomKey()) {} + +std::array HmacKeyManager::sign(const uint8_t* data, size_t size) const { + // SHA256 always generates 32-bytes result + std::array hash; + unsigned int hashLen = 0; + uint8_t* result = + HMAC(EVP_sha256(), mHmacKey.data(), mHmacKey.size(), data, size, hash.data(), &hashLen); + if (result == nullptr) { + ALOGE("Could not sign the data using HMAC"); + return INVALID_HMAC; + } + + if (hashLen != hash.size()) { + ALOGE("HMAC-SHA256 has unexpected length"); + return INVALID_HMAC; + } + + return hash; +} +} // namespace android \ No newline at end of file diff --git a/libs/attestation/OWNERS b/libs/attestation/OWNERS new file mode 100644 index 0000000000..4dbb0eae5c --- /dev/null +++ b/libs/attestation/OWNERS @@ -0,0 +1,2 @@ +chaviw@google.com +svv@google.com \ No newline at end of file diff --git a/libs/attestation/TEST_MAPPING b/libs/attestation/TEST_MAPPING new file mode 100644 index 0000000000..43be638d91 --- /dev/null +++ b/libs/attestation/TEST_MAPPING @@ -0,0 +1,7 @@ +{ + "presubmit": [ + { + "name": "libattestation_tests" + } + ] +} \ No newline at end of file diff --git a/libs/attestation/tests/Android.bp b/libs/attestation/tests/Android.bp new file mode 100644 index 0000000000..6ce5ea1b2d --- /dev/null +++ b/libs/attestation/tests/Android.bp @@ -0,0 +1,28 @@ +// Copyright (C) 2020 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. + +cc_test { + name: "libattestation_tests", + test_suites: ["device-tests"], + srcs: [ + "HmacKeyManager_test.cpp", + ], + static_libs: [ + "libattestation", + ], + shared_libs: [ + "liblog", + "libcrypto", + ], +} diff --git a/libs/attestation/tests/HmacKeyManager_test.cpp b/libs/attestation/tests/HmacKeyManager_test.cpp new file mode 100644 index 0000000000..7f7a408886 --- /dev/null +++ b/libs/attestation/tests/HmacKeyManager_test.cpp @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2020 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 +#include + +namespace android { + +class HmacKeyManagerTest : public testing::Test { +protected: + HmacKeyManager mHmacKeyManager; +}; + +/** + * Ensure that separate calls to sign the same data are generating the same key. + * We avoid asserting against INVALID_HMAC. Since the key is random, there is a non-zero chance + * that a specific key and data combination would produce INVALID_HMAC, which would cause flaky + * tests. + */ +TEST_F(HmacKeyManagerTest, GeneratedHmac_IsConsistent) { + std::array data = {4, 3, 5, 1, 8, 5, 2, 7, 1, 8}; + + std::array hmac1 = mHmacKeyManager.sign(data.data(), sizeof(data)); + std::array hmac2 = mHmacKeyManager.sign(data.data(), sizeof(data)); + ASSERT_EQ(hmac1, hmac2); +} + +/** + * Ensure that changes in the hmac verification data produce a different hmac. + */ +TEST_F(HmacKeyManagerTest, GeneratedHmac_ChangesWhenFieldsChange) { + std::array data = {4, 3, 5, 1, 8, 5, 2, 7, 1, 8}; + std::array initialHmac = mHmacKeyManager.sign(data.data(), sizeof(data)); + + data[2] = 2; + ASSERT_NE(initialHmac, mHmacKeyManager.sign(data.data(), sizeof(data))); +} + +} // namespace android \ No newline at end of file diff --git a/libs/input/Input.cpp b/libs/input/Input.cpp index 51910fe6f9..692c65dc46 100644 --- a/libs/input/Input.cpp +++ b/libs/input/Input.cpp @@ -17,6 +17,7 @@ #define LOG_TAG "Input" //#define LOG_NDEBUG 0 +#include #include #include #include diff --git a/libs/input/KeyCharacterMap.cpp b/libs/input/KeyCharacterMap.cpp index 5c03d50fbc..0fa93d21ce 100644 --- a/libs/input/KeyCharacterMap.cpp +++ b/libs/input/KeyCharacterMap.cpp @@ -24,9 +24,10 @@ #endif #include +#include #include -#include #include +#include #include #include diff --git a/libs/input/tests/InputEvent_test.cpp b/libs/input/tests/InputEvent_test.cpp index 069bc0eb4e..601d8dabf7 100644 --- a/libs/input/tests/InputEvent_test.cpp +++ b/libs/input/tests/InputEvent_test.cpp @@ -17,6 +17,7 @@ #include #include +#include #include #include #include diff --git a/libs/input/tests/InputPublisherAndConsumer_test.cpp b/libs/input/tests/InputPublisherAndConsumer_test.cpp index e1f2562129..1452745d01 100644 --- a/libs/input/tests/InputPublisherAndConsumer_test.cpp +++ b/libs/input/tests/InputPublisherAndConsumer_test.cpp @@ -20,11 +20,12 @@ #include #include +#include #include #include #include -#include #include +#include namespace android { diff --git a/libs/input/tests/VelocityTracker_test.cpp b/libs/input/tests/VelocityTracker_test.cpp index e7db4b06a4..d049d05ac5 100644 --- a/libs/input/tests/VelocityTracker_test.cpp +++ b/libs/input/tests/VelocityTracker_test.cpp @@ -21,6 +21,7 @@ #include #include +#include #include #include diff --git a/libs/input/tests/VerifiedInputEvent_test.cpp b/libs/input/tests/VerifiedInputEvent_test.cpp index 21cfe8c36e..36f87b8a6a 100644 --- a/libs/input/tests/VerifiedInputEvent_test.cpp +++ b/libs/input/tests/VerifiedInputEvent_test.cpp @@ -14,6 +14,7 @@ * limitations under the License. */ +#include #include #include diff --git a/services/inputflinger/Android.bp b/services/inputflinger/Android.bp index a0de607864..96e62079c6 100644 --- a/services/inputflinger/Android.bp +++ b/services/inputflinger/Android.bp @@ -59,6 +59,9 @@ cc_defaults { "libutils", "libui", ], + static_libs: [ + "libattestation", + ], } cc_library_shared { diff --git a/services/inputflinger/benchmarks/Android.bp b/services/inputflinger/benchmarks/Android.bp index 066a816069..9abf8b179f 100644 --- a/services/inputflinger/benchmarks/Android.bp +++ b/services/inputflinger/benchmarks/Android.bp @@ -18,6 +18,7 @@ cc_benchmark { "libutils", ], static_libs: [ + "libattestation", "libinputdispatcher", ], } diff --git a/services/inputflinger/dispatcher/Android.bp b/services/inputflinger/dispatcher/Android.bp index d29d8dfda3..ff9aac9961 100644 --- a/services/inputflinger/dispatcher/Android.bp +++ b/services/inputflinger/dispatcher/Android.bp @@ -48,6 +48,9 @@ cc_defaults { "libui", "libutils", ], + static_libs: [ + "libattestation", + ], header_libs: [ "libinputdispatcher_headers", ], diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp index 078448f400..0980107b42 100644 --- a/services/inputflinger/dispatcher/InputDispatcher.cpp +++ b/services/inputflinger/dispatcher/InputDispatcher.cpp @@ -53,8 +53,6 @@ static constexpr bool DEBUG_FOCUS = false; #include #include #include -#include -#include #include #include #include @@ -344,53 +342,6 @@ static void addGestureMonitors(const std::vector& monitors, } } -static std::array getRandomKey() { - std::array key; - if (RAND_bytes(key.data(), key.size()) != 1) { - LOG_ALWAYS_FATAL("Can't generate HMAC key"); - } - return key; -} - -// --- HmacKeyManager --- - -HmacKeyManager::HmacKeyManager() : mHmacKey(getRandomKey()) {} - -std::array HmacKeyManager::sign(const VerifiedInputEvent& event) const { - size_t size; - switch (event.type) { - case VerifiedInputEvent::Type::KEY: { - size = sizeof(VerifiedKeyEvent); - break; - } - case VerifiedInputEvent::Type::MOTION: { - size = sizeof(VerifiedMotionEvent); - break; - } - } - const uint8_t* start = reinterpret_cast(&event); - return sign(start, size); -} - -std::array HmacKeyManager::sign(const uint8_t* data, size_t size) const { - // SHA256 always generates 32-bytes result - std::array hash; - unsigned int hashLen = 0; - uint8_t* result = - HMAC(EVP_sha256(), mHmacKey.data(), mHmacKey.size(), data, size, hash.data(), &hashLen); - if (result == nullptr) { - ALOGE("Could not sign the data using HMAC"); - return INVALID_HMAC; - } - - if (hashLen != hash.size()) { - ALOGE("HMAC-SHA256 has unexpected length"); - return INVALID_HMAC; - } - - return hash; -} - // --- InputDispatcher --- InputDispatcher::InputDispatcher(const sp& policy) @@ -2692,6 +2643,22 @@ void InputDispatcher::startDispatchCycleLocked(nsecs_t currentTime, } } +std::array InputDispatcher::sign(const VerifiedInputEvent& event) const { + size_t size; + switch (event.type) { + case VerifiedInputEvent::Type::KEY: { + size = sizeof(VerifiedKeyEvent); + break; + } + case VerifiedInputEvent::Type::MOTION: { + size = sizeof(VerifiedMotionEvent); + break; + } + } + const uint8_t* start = reinterpret_cast(&event); + return mHmacKeyManager.sign(start, size); +} + const std::array InputDispatcher::getSignature( const MotionEntry& motionEntry, const DispatchEntry& dispatchEntry) const { int32_t actionMasked = dispatchEntry.resolvedAction & AMOTION_EVENT_ACTION_MASK; @@ -2701,7 +2668,7 @@ const std::array InputDispatcher::getSignature( VerifiedMotionEvent verifiedEvent = verifiedMotionEventFromMotionEntry(motionEntry); verifiedEvent.actionMasked = actionMasked; verifiedEvent.flags = dispatchEntry.resolvedFlags & VERIFIED_MOTION_EVENT_FLAGS; - return mHmacKeyManager.sign(verifiedEvent); + return sign(verifiedEvent); } return INVALID_HMAC; } @@ -2711,7 +2678,7 @@ const std::array InputDispatcher::getSignature( VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEntry(keyEntry); verifiedEvent.flags = dispatchEntry.resolvedFlags & VERIFIED_KEY_EVENT_FLAGS; verifiedEvent.action = dispatchEntry.resolvedAction; - return mHmacKeyManager.sign(verifiedEvent); + return sign(verifiedEvent); } void InputDispatcher::finishDispatchCycleLocked(nsecs_t currentTime, @@ -3559,7 +3526,7 @@ std::unique_ptr InputDispatcher::verifyInputEvent(const Inpu const KeyEvent& keyEvent = static_cast(event); VerifiedKeyEvent verifiedKeyEvent = verifiedKeyEventFromKeyEvent(keyEvent); result = std::make_unique(verifiedKeyEvent); - calculatedHmac = mHmacKeyManager.sign(verifiedKeyEvent); + calculatedHmac = sign(verifiedKeyEvent); break; } case AINPUT_EVENT_TYPE_MOTION: { @@ -3567,7 +3534,7 @@ std::unique_ptr InputDispatcher::verifyInputEvent(const Inpu VerifiedMotionEvent verifiedMotionEvent = verifiedMotionEventFromMotionEvent(motionEvent); result = std::make_unique(verifiedMotionEvent); - calculatedHmac = mHmacKeyManager.sign(verifiedMotionEvent); + calculatedHmac = sign(verifiedMotionEvent); break; } default: { diff --git a/services/inputflinger/dispatcher/InputDispatcher.h b/services/inputflinger/dispatcher/InputDispatcher.h index 8988714030..e452ca29a0 100644 --- a/services/inputflinger/dispatcher/InputDispatcher.h +++ b/services/inputflinger/dispatcher/InputDispatcher.h @@ -31,6 +31,7 @@ #include "TouchState.h" #include "TouchedWindow.h" +#include #include #include #include @@ -58,16 +59,6 @@ namespace android::inputdispatcher { class Connection; -class HmacKeyManager { -public: - HmacKeyManager(); - std::array sign(const VerifiedInputEvent& event) const; - -private: - std::array sign(const uint8_t* data, size_t size) const; - const std::array mHmacKey; -}; - /* Dispatches events to input targets. Some functions of the input dispatcher, such as * identifying input targets, are controlled by a separate policy object. * @@ -133,6 +124,8 @@ public: virtual status_t unregisterInputChannel(const InputChannel& inputChannel) override; virtual status_t pilferPointers(const sp& token) override; + std::array sign(const VerifiedInputEvent& event) const; + private: enum class DropReason { NOT_DROPPED, diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp index da50af5c5f..3e0b5e867d 100644 --- a/services/inputflinger/tests/InputDispatcher_test.cpp +++ b/services/inputflinger/tests/InputDispatcher_test.cpp @@ -294,70 +294,6 @@ private: } }; -// --- HmacKeyManagerTest --- - -class HmacKeyManagerTest : public testing::Test { -protected: - HmacKeyManager mHmacKeyManager; -}; - -/** - * Ensure that separate calls to sign the same data are generating the same key. - * We avoid asserting against INVALID_HMAC. Since the key is random, there is a non-zero chance - * that a specific key and data combination would produce INVALID_HMAC, which would cause flaky - * tests. - */ -TEST_F(HmacKeyManagerTest, GeneratedHmac_IsConsistent) { - KeyEvent event = getTestKeyEvent(); - VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event); - - std::array hmac1 = mHmacKeyManager.sign(verifiedEvent); - std::array hmac2 = mHmacKeyManager.sign(verifiedEvent); - ASSERT_EQ(hmac1, hmac2); -} - -/** - * Ensure that changes in VerifiedKeyEvent produce a different hmac. - */ -TEST_F(HmacKeyManagerTest, GeneratedHmac_ChangesWhenFieldsChange) { - KeyEvent event = getTestKeyEvent(); - VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event); - std::array initialHmac = mHmacKeyManager.sign(verifiedEvent); - - verifiedEvent.deviceId += 1; - ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent)); - - verifiedEvent.source += 1; - ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent)); - - verifiedEvent.eventTimeNanos += 1; - ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent)); - - verifiedEvent.displayId += 1; - ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent)); - - verifiedEvent.action += 1; - ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent)); - - verifiedEvent.downTimeNanos += 1; - ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent)); - - verifiedEvent.flags += 1; - ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent)); - - verifiedEvent.keyCode += 1; - ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent)); - - verifiedEvent.scanCode += 1; - ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent)); - - verifiedEvent.metaState += 1; - ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent)); - - verifiedEvent.repeatCount += 1; - ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent)); -} - // --- InputDispatcherTest --- class InputDispatcherTest : public testing::Test { @@ -2027,6 +1963,63 @@ TEST_F(InputDispatcherTest, VerifyInputEvent_MotionEvent) { EXPECT_EQ(motionArgs.buttonState, verifiedMotion.buttonState); } +/** + * Ensure that separate calls to sign the same data are generating the same key. + * We avoid asserting against INVALID_HMAC. Since the key is random, there is a non-zero chance + * that a specific key and data combination would produce INVALID_HMAC, which would cause flaky + * tests. + */ +TEST_F(InputDispatcherTest, GeneratedHmac_IsConsistent) { + KeyEvent event = getTestKeyEvent(); + VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event); + + std::array hmac1 = mDispatcher->sign(verifiedEvent); + std::array hmac2 = mDispatcher->sign(verifiedEvent); + ASSERT_EQ(hmac1, hmac2); +} + +/** + * Ensure that changes in VerifiedKeyEvent produce a different hmac. + */ +TEST_F(InputDispatcherTest, GeneratedHmac_ChangesWhenFieldsChange) { + KeyEvent event = getTestKeyEvent(); + VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event); + std::array initialHmac = mDispatcher->sign(verifiedEvent); + + verifiedEvent.deviceId += 1; + ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent)); + + verifiedEvent.source += 1; + ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent)); + + verifiedEvent.eventTimeNanos += 1; + ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent)); + + verifiedEvent.displayId += 1; + ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent)); + + verifiedEvent.action += 1; + ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent)); + + verifiedEvent.downTimeNanos += 1; + ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent)); + + verifiedEvent.flags += 1; + ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent)); + + verifiedEvent.keyCode += 1; + ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent)); + + verifiedEvent.scanCode += 1; + ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent)); + + verifiedEvent.metaState += 1; + ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent)); + + verifiedEvent.repeatCount += 1; + ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent)); +} + class InputDispatcherKeyRepeatTest : public InputDispatcherTest { protected: static constexpr nsecs_t KEY_REPEAT_TIMEOUT = 40 * 1000000; // 40 ms -- cgit v1.2.3-59-g8ed1b From 3a1e446866d905223e731cf1319f41152cd629c3 Mon Sep 17 00:00:00 2001 From: Chris Ye Date: Wed, 12 Aug 2020 10:13:15 -0700 Subject: Move KeyCharacterMap from RefBase to shared_ptr. Move KeyCharacterMap from RefBase and make it shared_ptr in EventHub device when loaded from file. A shared_ptr of KeyCharacterMap is returned by EventHub getKeyCharacterMap to be shared in InputdeviceInfo. Remove extra KeyCharacterMap in EventHub to save memory sapce. Bug: 160010896 Test: atest inputflinger, atest libinput_tests Change-Id: Ibb317ea0684e6af6e7a6d808f816fc4a05c7b421 --- include/input/InputDevice.h | 6 +- include/input/KeyCharacterMap.h | 31 +++-- include/input/Keyboard.h | 2 +- libs/input/InputDevice.cpp | 22 ++-- libs/input/KeyCharacterMap.cpp | 134 ++++++++++----------- libs/input/Keyboard.cpp | 10 +- services/inputflinger/include/InputReaderBase.h | 2 +- services/inputflinger/reader/EventHub.cpp | 27 ++--- services/inputflinger/reader/InputDevice.cpp | 2 +- services/inputflinger/reader/include/EventHub.h | 16 +-- services/inputflinger/reader/include/InputDevice.h | 4 +- services/inputflinger/tests/InputReader_test.cpp | 7 +- 12 files changed, 130 insertions(+), 133 deletions(-) (limited to 'libs/input/KeyCharacterMap.cpp') diff --git a/include/input/InputDevice.h b/include/input/InputDevice.h index c7685b7c13..60638caaab 100644 --- a/include/input/InputDevice.h +++ b/include/input/InputDevice.h @@ -108,11 +108,11 @@ public: inline void setKeyboardType(int32_t keyboardType) { mKeyboardType = keyboardType; } inline int32_t getKeyboardType() const { return mKeyboardType; } - inline void setKeyCharacterMap(const sp& value) { + inline void setKeyCharacterMap(const std::shared_ptr value) { mKeyCharacterMap = value; } - inline sp getKeyCharacterMap() const { + inline const std::shared_ptr getKeyCharacterMap() const { return mKeyCharacterMap; } @@ -136,7 +136,7 @@ private: bool mHasMic; uint32_t mSources; int32_t mKeyboardType; - sp mKeyCharacterMap; + std::shared_ptr mKeyCharacterMap; bool mHasVibrator; bool mHasButtonUnderPad; diff --git a/include/input/KeyCharacterMap.h b/include/input/KeyCharacterMap.h index a1a32a63de..d874347929 100644 --- a/include/input/KeyCharacterMap.h +++ b/include/input/KeyCharacterMap.h @@ -23,12 +23,12 @@ #include #endif +#include #include #include #include #include #include -#include // Maximum number of keys supported by KeyCharacterMaps #define MAX_KEYS 8192 @@ -42,7 +42,7 @@ namespace android { * * This object is immutable after it has been loaded. */ -class KeyCharacterMap : public RefBase { +class KeyCharacterMap { public: enum KeyboardType { KEYBOARD_TYPE_UNKNOWN = 0, @@ -74,18 +74,18 @@ public: }; /* Loads a key character map from a file. */ - static status_t load(const std::string& filename, Format format, sp* outMap); + static base::Result> load(const std::string& filename, + Format format); /* Loads a key character map from its string contents. */ - static status_t loadContents(const std::string& filename, - const char* contents, Format format, sp* outMap); + static base::Result> loadContents(const std::string& filename, + const char* contents, + Format format); - /* Combines a base key character map and an overlay. */ - static sp combine(const sp& base, - const sp& overlay); + const std::string getLoadFileName() const; - /* Returns an empty key character map. */ - static sp empty(); + /* Combines this key character map with an overlay. */ + void combine(const KeyCharacterMap& overlay); /* Gets the keyboard type. */ int32_t getKeyboardType() const; @@ -136,13 +136,14 @@ public: #ifdef __ANDROID__ /* Reads a key map from a parcel. */ - static sp readFromParcel(Parcel* parcel); + static std::shared_ptr readFromParcel(Parcel* parcel); /* Writes a key map to a parcel. */ void writeToParcel(Parcel* parcel) const; #endif -protected: + KeyCharacterMap(const KeyCharacterMap& other); + virtual ~KeyCharacterMap(); private: @@ -224,16 +225,14 @@ private: status_t parseCharacterLiteral(char16_t* outCharacter); }; - static sp sEmpty; - KeyedVector mKeys; int mType; + std::string mLoadFileName; KeyedVector mKeysByScanCode; KeyedVector mKeysByUsageCode; KeyCharacterMap(); - KeyCharacterMap(const KeyCharacterMap& other); bool getKey(int32_t keyCode, const Key** outKey) const; bool getKeyBehavior(int32_t keyCode, int32_t metaState, @@ -242,7 +241,7 @@ private: bool findKey(char16_t ch, int32_t* outKeyCode, int32_t* outMetaState) const; - static status_t load(Tokenizer* tokenizer, Format format, sp* outMap); + static base::Result> load(Tokenizer* tokenizer, Format format); static void addKey(Vector& outEvents, int32_t deviceId, int32_t keyCode, int32_t metaState, bool down, nsecs_t time); diff --git a/include/input/Keyboard.h b/include/input/Keyboard.h index 4c56a694b4..2ae4fd564e 100644 --- a/include/input/Keyboard.h +++ b/include/input/Keyboard.h @@ -37,7 +37,7 @@ public: std::shared_ptr keyLayoutMap; std::string keyCharacterMapFile; - sp keyCharacterMap; + std::shared_ptr keyCharacterMap; KeyMap(); ~KeyMap(); diff --git a/libs/input/InputDevice.cpp b/libs/input/InputDevice.cpp index dbd6293a64..34eba5be7f 100644 --- a/libs/input/InputDevice.cpp +++ b/libs/input/InputDevice.cpp @@ -153,14 +153,20 @@ InputDeviceInfo::InputDeviceInfo() { initialize(-1, 0, -1, InputDeviceIdentifier(), "", false, false); } -InputDeviceInfo::InputDeviceInfo(const InputDeviceInfo& other) : - mId(other.mId), mGeneration(other.mGeneration), mControllerNumber(other.mControllerNumber), - mIdentifier(other.mIdentifier), mAlias(other.mAlias), mIsExternal(other.mIsExternal), - mHasMic(other.mHasMic), mSources(other.mSources), - mKeyboardType(other.mKeyboardType), mKeyCharacterMap(other.mKeyCharacterMap), - mHasVibrator(other.mHasVibrator), mHasButtonUnderPad(other.mHasButtonUnderPad), - mMotionRanges(other.mMotionRanges) { -} +InputDeviceInfo::InputDeviceInfo(const InputDeviceInfo& other) + : mId(other.mId), + mGeneration(other.mGeneration), + mControllerNumber(other.mControllerNumber), + mIdentifier(other.mIdentifier), + mAlias(other.mAlias), + mIsExternal(other.mIsExternal), + mHasMic(other.mHasMic), + mSources(other.mSources), + mKeyboardType(other.mKeyboardType), + mKeyCharacterMap(other.mKeyCharacterMap), + mHasVibrator(other.mHasVibrator), + mHasButtonUnderPad(other.mHasButtonUnderPad), + mMotionRanges(other.mMotionRanges) {} InputDeviceInfo::~InputDeviceInfo() { } diff --git a/libs/input/KeyCharacterMap.cpp b/libs/input/KeyCharacterMap.cpp index 5c03d50fbc..fd35131b6b 100644 --- a/libs/input/KeyCharacterMap.cpp +++ b/libs/input/KeyCharacterMap.cpp @@ -85,15 +85,14 @@ static String8 toString(const char16_t* chars, size_t numChars) { // --- KeyCharacterMap --- -sp KeyCharacterMap::sEmpty = new KeyCharacterMap(); - KeyCharacterMap::KeyCharacterMap() : mType(KEYBOARD_TYPE_UNKNOWN) { } -KeyCharacterMap::KeyCharacterMap(const KeyCharacterMap& other) : - RefBase(), mType(other.mType), mKeysByScanCode(other.mKeysByScanCode), - mKeysByUsageCode(other.mKeysByUsageCode) { +KeyCharacterMap::KeyCharacterMap(const KeyCharacterMap& other) + : mType(other.mType), + mKeysByScanCode(other.mKeysByScanCode), + mKeysByUsageCode(other.mKeysByUsageCode) { for (size_t i = 0; i < other.mKeys.size(); i++) { mKeys.add(other.mKeys.keyAt(i), new Key(*other.mKeys.valueAt(i))); } @@ -106,104 +105,95 @@ KeyCharacterMap::~KeyCharacterMap() { } } -status_t KeyCharacterMap::load(const std::string& filename, - Format format, sp* outMap) { - outMap->clear(); - +base::Result> KeyCharacterMap::load(const std::string& filename, + Format format) { Tokenizer* tokenizer; status_t status = Tokenizer::open(String8(filename.c_str()), &tokenizer); if (status) { - ALOGE("Error %d opening key character map file %s.", status, filename.c_str()); - } else { - status = load(tokenizer, format, outMap); - delete tokenizer; + return Errorf("Error {} opening key character map file {}.", status, filename.c_str()); } - return status; + std::unique_ptr t(tokenizer); + auto ret = load(t.get(), format); + if (ret) { + (*ret)->mLoadFileName = filename; + } + return ret; } -status_t KeyCharacterMap::loadContents(const std::string& filename, const char* contents, - Format format, sp* outMap) { - outMap->clear(); - +base::Result> KeyCharacterMap::loadContents( + const std::string& filename, const char* contents, Format format) { Tokenizer* tokenizer; status_t status = Tokenizer::fromContents(String8(filename.c_str()), contents, &tokenizer); if (status) { ALOGE("Error %d opening key character map.", status); - } else { - status = load(tokenizer, format, outMap); - delete tokenizer; + return Errorf("Error {} opening key character map.", status); } - return status; + std::unique_ptr t(tokenizer); + auto ret = load(t.get(), format); + if (ret) { + (*ret)->mLoadFileName = filename; + } + return ret; } -status_t KeyCharacterMap::load(Tokenizer* tokenizer, - Format format, sp* outMap) { +base::Result> KeyCharacterMap::load(Tokenizer* tokenizer, + Format format) { status_t status = OK; - sp map = new KeyCharacterMap(); + std::shared_ptr map = std::shared_ptr(new KeyCharacterMap()); if (!map.get()) { ALOGE("Error allocating key character map."); - status = NO_MEMORY; - } else { + return Errorf("Error allocating key character map."); + } #if DEBUG_PARSER_PERFORMANCE - nsecs_t startTime = systemTime(SYSTEM_TIME_MONOTONIC); + nsecs_t startTime = systemTime(SYSTEM_TIME_MONOTONIC); #endif - Parser parser(map.get(), tokenizer, format); - status = parser.parse(); + Parser parser(map.get(), tokenizer, format); + status = parser.parse(); #if DEBUG_PARSER_PERFORMANCE - nsecs_t elapsedTime = systemTime(SYSTEM_TIME_MONOTONIC) - startTime; - ALOGD("Parsed key character map file '%s' %d lines in %0.3fms.", - tokenizer->getFilename().string(), tokenizer->getLineNumber(), - elapsedTime / 1000000.0); + nsecs_t elapsedTime = systemTime(SYSTEM_TIME_MONOTONIC) - startTime; + ALOGD("Parsed key character map file '%s' %d lines in %0.3fms.", + tokenizer->getFilename().string(), tokenizer->getLineNumber(), elapsedTime / 1000000.0); #endif - if (!status) { - *outMap = map; - } + if (status == OK) { + return map; } - return status; -} -sp KeyCharacterMap::combine(const sp& base, - const sp& overlay) { - if (overlay == nullptr) { - return base; - } - if (base == nullptr) { - return overlay; - } + return Errorf("Load KeyCharacterMap failed {}.", status); +} - sp map = new KeyCharacterMap(*base.get()); - for (size_t i = 0; i < overlay->mKeys.size(); i++) { - int32_t keyCode = overlay->mKeys.keyAt(i); - Key* key = overlay->mKeys.valueAt(i); - ssize_t oldIndex = map->mKeys.indexOfKey(keyCode); +void KeyCharacterMap::combine(const KeyCharacterMap& overlay) { + for (size_t i = 0; i < overlay.mKeys.size(); i++) { + int32_t keyCode = overlay.mKeys.keyAt(i); + Key* key = overlay.mKeys.valueAt(i); + ssize_t oldIndex = mKeys.indexOfKey(keyCode); if (oldIndex >= 0) { - delete map->mKeys.valueAt(oldIndex); - map->mKeys.editValueAt(oldIndex) = new Key(*key); + delete mKeys.valueAt(oldIndex); + mKeys.editValueAt(oldIndex) = new Key(*key); } else { - map->mKeys.add(keyCode, new Key(*key)); + mKeys.add(keyCode, new Key(*key)); } } - for (size_t i = 0; i < overlay->mKeysByScanCode.size(); i++) { - map->mKeysByScanCode.replaceValueFor(overlay->mKeysByScanCode.keyAt(i), - overlay->mKeysByScanCode.valueAt(i)); + for (size_t i = 0; i < overlay.mKeysByScanCode.size(); i++) { + mKeysByScanCode.replaceValueFor(overlay.mKeysByScanCode.keyAt(i), + overlay.mKeysByScanCode.valueAt(i)); } - for (size_t i = 0; i < overlay->mKeysByUsageCode.size(); i++) { - map->mKeysByUsageCode.replaceValueFor(overlay->mKeysByUsageCode.keyAt(i), - overlay->mKeysByUsageCode.valueAt(i)); + for (size_t i = 0; i < overlay.mKeysByUsageCode.size(); i++) { + mKeysByUsageCode.replaceValueFor(overlay.mKeysByUsageCode.keyAt(i), + overlay.mKeysByUsageCode.valueAt(i)); } - return map; -} - -sp KeyCharacterMap::empty() { - return sEmpty; + mLoadFileName = overlay.mLoadFileName; } int32_t KeyCharacterMap::getKeyboardType() const { return mType; } +const std::string KeyCharacterMap::getLoadFileName() const { + return mLoadFileName; +} + char16_t KeyCharacterMap::getDisplayLabel(int32_t keyCode) const { char16_t result = 0; const Key* key; @@ -600,8 +590,12 @@ void KeyCharacterMap::addLockedMetaKey(Vector& outEvents, } #ifdef __ANDROID__ -sp KeyCharacterMap::readFromParcel(Parcel* parcel) { - sp map = new KeyCharacterMap(); +std::shared_ptr KeyCharacterMap::readFromParcel(Parcel* parcel) { + if (parcel == nullptr) { + ALOGE("%s: Null parcel", __func__); + return nullptr; + } + std::shared_ptr map = std::shared_ptr(new KeyCharacterMap()); map->mType = parcel->readInt32(); size_t numKeys = parcel->readInt32(); if (parcel->errorCheck()) { @@ -656,6 +650,10 @@ sp KeyCharacterMap::readFromParcel(Parcel* parcel) { } void KeyCharacterMap::writeToParcel(Parcel* parcel) const { + if (parcel == nullptr) { + ALOGE("%s: Null parcel", __func__); + return; + } parcel->writeInt32(mType); size_t numKeys = mKeys.size(); diff --git a/libs/input/Keyboard.cpp b/libs/input/Keyboard.cpp index 1a64a9ca1e..38a68b3884 100644 --- a/libs/input/Keyboard.cpp +++ b/libs/input/Keyboard.cpp @@ -127,12 +127,12 @@ status_t KeyMap::loadKeyCharacterMap(const InputDeviceIdentifier& deviceIdentifi return NAME_NOT_FOUND; } - status_t status = KeyCharacterMap::load(path, - KeyCharacterMap::FORMAT_BASE, &keyCharacterMap); - if (status) { - return status; + base::Result> ret = + KeyCharacterMap::load(path, KeyCharacterMap::FORMAT_BASE); + if (!ret) { + return ret.error().code(); } - + keyCharacterMap = *ret; keyCharacterMapFile = path; return OK; } diff --git a/services/inputflinger/include/InputReaderBase.h b/services/inputflinger/include/InputReaderBase.h index a24b293c17..573524e708 100644 --- a/services/inputflinger/include/InputReaderBase.h +++ b/services/inputflinger/include/InputReaderBase.h @@ -341,7 +341,7 @@ public: virtual void notifyInputDevicesChanged(const std::vector& inputDevices) = 0; /* Gets the keyboard layout for a particular input device. */ - virtual sp getKeyboardLayoutOverlay( + virtual std::shared_ptr getKeyboardLayoutOverlay( const InputDeviceIdentifier& identifier) = 0; /* Gets a user-supplied alias for a particular input device, or an empty string if none. */ diff --git a/services/inputflinger/reader/EventHub.cpp b/services/inputflinger/reader/EventHub.cpp index dda19c6695..67d3cc2115 100644 --- a/services/inputflinger/reader/EventHub.cpp +++ b/services/inputflinger/reader/EventHub.cpp @@ -216,10 +216,7 @@ bool EventHub::Device::hasValidFd() const { return !isVirtual && enabled; } -const sp& EventHub::Device::getKeyCharacterMap() const { - if (combinedKeyMap != nullptr) { - return combinedKeyMap; - } +const std::shared_ptr EventHub::Device::getKeyCharacterMap() const { return keyMap.keyCharacterMap; } @@ -661,8 +658,8 @@ status_t EventHub::mapKey(int32_t deviceId, int32_t scanCode, int32_t usageCode, if (device != nullptr) { // Check the key character map first. - sp kcm = device->getKeyCharacterMap(); - if (kcm != nullptr) { + const std::shared_ptr kcm = device->getKeyCharacterMap(); + if (kcm) { if (!kcm->mapKey(scanCode, usageCode, outKeycode)) { *outFlags = 0; status = NO_ERROR; @@ -677,7 +674,7 @@ status_t EventHub::mapKey(int32_t deviceId, int32_t scanCode, int32_t usageCode, } if (status == NO_ERROR) { - if (kcm != nullptr) { + if (kcm) { kcm->tryRemapKey(*outKeycode, metaState, outKeycode, outMetaState); } else { *outMetaState = metaState; @@ -754,7 +751,7 @@ void EventHub::getVirtualKeyDefinitions(int32_t deviceId, } } -sp EventHub::getKeyCharacterMap(int32_t deviceId) const { +const std::shared_ptr EventHub::getKeyCharacterMap(int32_t deviceId) const { AutoMutex _l(mLock); Device* device = getDeviceLocked(deviceId); if (device != nullptr) { @@ -763,15 +760,13 @@ sp EventHub::getKeyCharacterMap(int32_t deviceId) const { return nullptr; } -bool EventHub::setKeyboardLayoutOverlay(int32_t deviceId, const sp& map) { +bool EventHub::setKeyboardLayoutOverlay(int32_t deviceId, std::shared_ptr map) { AutoMutex _l(mLock); Device* device = getDeviceLocked(deviceId); - if (device != nullptr) { - if (map != device->overlayKeyMap) { - device->overlayKeyMap = map; - device->combinedKeyMap = KeyCharacterMap::combine(device->keyMap.keyCharacterMap, map); - return true; - } + if (device != nullptr && map != nullptr && device->keyMap.keyCharacterMap != nullptr) { + device->keyMap.keyCharacterMap->combine(*map); + device->keyMap.keyCharacterMapFile = device->keyMap.keyCharacterMap->getLoadFileName(); + return true; } return false; } @@ -1853,8 +1848,6 @@ void EventHub::dump(std::string& dump) { device->keyMap.keyCharacterMapFile.c_str()); dump += StringPrintf(INDENT3 "ConfigurationFile: %s\n", device->configurationFile.c_str()); - dump += StringPrintf(INDENT3 "HaveKeyboardLayoutOverlay: %s\n", - toString(device->overlayKeyMap != nullptr)); dump += INDENT3 "VideoDevice: "; if (device->videoDevice) { dump += device->videoDevice->dump() + "\n"; diff --git a/services/inputflinger/reader/InputDevice.cpp b/services/inputflinger/reader/InputDevice.cpp index 49607798ef..b2244762b8 100644 --- a/services/inputflinger/reader/InputDevice.cpp +++ b/services/inputflinger/reader/InputDevice.cpp @@ -240,7 +240,7 @@ void InputDevice::configure(nsecs_t when, const InputReaderConfiguration* config if (!changes || (changes & InputReaderConfiguration::CHANGE_KEYBOARD_LAYOUTS)) { if (!mClasses.test(InputDeviceClass::VIRTUAL)) { - sp keyboardLayout = + std::shared_ptr keyboardLayout = mContext->getPolicy()->getKeyboardLayoutOverlay(mIdentifier); bool shouldBumpGeneration = false; for_each_subdevice( diff --git a/services/inputflinger/reader/include/EventHub.h b/services/inputflinger/reader/include/EventHub.h index fb0f19e33f..aec4837a30 100644 --- a/services/inputflinger/reader/include/EventHub.h +++ b/services/inputflinger/reader/include/EventHub.h @@ -226,8 +226,9 @@ public: virtual void getVirtualKeyDefinitions( int32_t deviceId, std::vector& outVirtualKeys) const = 0; - virtual sp getKeyCharacterMap(int32_t deviceId) const = 0; - virtual bool setKeyboardLayoutOverlay(int32_t deviceId, const sp& map) = 0; + virtual const std::shared_ptr getKeyCharacterMap(int32_t deviceId) const = 0; + virtual bool setKeyboardLayoutOverlay(int32_t deviceId, + std::shared_ptr map) = 0; /* Control the vibrator. */ virtual void vibrate(int32_t deviceId, const VibrationElement& effect) = 0; @@ -373,8 +374,10 @@ public: int32_t deviceId, std::vector& outVirtualKeys) const override final; - sp getKeyCharacterMap(int32_t deviceId) const override final; - bool setKeyboardLayoutOverlay(int32_t deviceId, const sp& map) override final; + const std::shared_ptr getKeyCharacterMap( + int32_t deviceId) const override final; + bool setKeyboardLayoutOverlay(int32_t deviceId, + std::shared_ptr map) override final; void vibrate(int32_t deviceId, const VibrationElement& effect) override final; void cancelVibrate(int32_t deviceId) override final; @@ -421,9 +424,6 @@ private: std::unique_ptr virtualKeyMap; KeyMap keyMap; - sp overlayKeyMap; - sp combinedKeyMap; - bool ffEffectPlaying; int16_t ffEffectId; // initially -1 @@ -441,7 +441,7 @@ private: bool hasValidFd() const; const bool isVirtual; // set if fd < 0 is passed to constructor - const sp& getKeyCharacterMap() const; + const std::shared_ptr getKeyCharacterMap() const; template status_t readDeviceBitMask(unsigned long ioctlCode, BitArray& bitArray); diff --git a/services/inputflinger/reader/include/InputDevice.h b/services/inputflinger/reader/include/InputDevice.h index 307eeb4e4f..7f5e1c8443 100644 --- a/services/inputflinger/reader/include/InputDevice.h +++ b/services/inputflinger/reader/include/InputDevice.h @@ -261,10 +261,10 @@ public: inline void getVirtualKeyDefinitions(std::vector& outVirtualKeys) const { return mEventHub->getVirtualKeyDefinitions(mId, outVirtualKeys); } - inline sp getKeyCharacterMap() const { + inline const std::shared_ptr getKeyCharacterMap() const { return mEventHub->getKeyCharacterMap(mId); } - inline bool setKeyboardLayoutOverlay(const sp& map) { + inline bool setKeyboardLayoutOverlay(std::shared_ptr map) { return mEventHub->setKeyboardLayoutOverlay(mId, map); } inline void vibrate(const VibrationElement& element) { diff --git a/services/inputflinger/tests/InputReader_test.cpp b/services/inputflinger/tests/InputReader_test.cpp index 82157b69d9..b28b6ea4e2 100644 --- a/services/inputflinger/tests/InputReader_test.cpp +++ b/services/inputflinger/tests/InputReader_test.cpp @@ -340,7 +340,8 @@ private: mDevicesChangedCondition.notify_all(); } - virtual sp getKeyboardLayoutOverlay(const InputDeviceIdentifier&) { + virtual std::shared_ptr getKeyboardLayoutOverlay( + const InputDeviceIdentifier&) { return nullptr; } @@ -814,11 +815,11 @@ private: } } - virtual sp getKeyCharacterMap(int32_t) const { + virtual const std::shared_ptr getKeyCharacterMap(int32_t) const { return nullptr; } - virtual bool setKeyboardLayoutOverlay(int32_t, const sp&) { + virtual bool setKeyboardLayoutOverlay(int32_t, std::shared_ptr) { return false; } -- cgit v1.2.3-59-g8ed1b From 5820852c0f0fe634a104f81691ad3e0026caecdc Mon Sep 17 00:00:00 2001 From: Brett Chabot Date: Wed, 9 Sep 2020 13:55:24 -0700 Subject: Build all of libinput for linux host. Including enabling parcel-related code in source already building for host. Test: m libandroid_runtime Change-Id: Ia569e5158ba6ead28486069036f6a3595662bbf8 --- include/input/Input.h | 6 ------ include/input/KeyCharacterMap.h | 4 ---- libs/input/Android.bp | 29 +++++++++++++++++++++++++---- libs/input/Input.cpp | 6 +----- libs/input/KeyCharacterMap.cpp | 5 ----- libs/ui/Android.bp | 4 +++- 6 files changed, 29 insertions(+), 25 deletions(-) (limited to 'libs/input/KeyCharacterMap.cpp') diff --git a/include/input/Input.h b/include/input/Input.h index 7d81fed34b..7ec0c9a2c4 100644 --- a/include/input/Input.h +++ b/include/input/Input.h @@ -177,9 +177,7 @@ struct AInputDevice { namespace android { -#ifdef __ANDROID__ class Parcel; -#endif const char* inputEventTypeToString(int32_t type); @@ -346,10 +344,8 @@ struct PointerCoords { return getAxisValue(AMOTION_EVENT_AXIS_Y); } -#ifdef __ANDROID__ status_t readFromParcel(Parcel* parcel); status_t writeToParcel(Parcel* parcel) const; -#endif bool operator==(const PointerCoords& other) const; inline bool operator!=(const PointerCoords& other) const { @@ -708,10 +704,8 @@ public: // Matrix is in row-major form and compatible with SkMatrix. void transform(const std::array& matrix); -#ifdef __ANDROID__ status_t readFromParcel(Parcel* parcel); status_t writeToParcel(Parcel* parcel) const; -#endif static bool isTouchEvent(uint32_t source, int32_t action); inline bool isTouchEvent() const { diff --git a/include/input/KeyCharacterMap.h b/include/input/KeyCharacterMap.h index d874347929..339c7ebfeb 100644 --- a/include/input/KeyCharacterMap.h +++ b/include/input/KeyCharacterMap.h @@ -19,9 +19,7 @@ #include -#ifdef __ANDROID__ #include -#endif #include #include @@ -134,13 +132,11 @@ public: void tryRemapKey(int32_t scanCode, int32_t metaState, int32_t* outKeyCode, int32_t* outMetaState) const; -#ifdef __ANDROID__ /* Reads a key map from a parcel. */ static std::shared_ptr readFromParcel(Parcel* parcel); /* Writes a key map to a parcel. */ void writeToParcel(Parcel* parcel) const; -#endif KeyCharacterMap(const KeyCharacterMap& other); diff --git a/libs/input/Android.bp b/libs/input/Android.bp index d8c3e6fbc7..fce3000a0f 100644 --- a/libs/input/Android.bp +++ b/libs/input/Android.bp @@ -40,8 +40,11 @@ cc_library { "Keyboard.cpp", "KeyCharacterMap.cpp", "KeyLayoutMap.cpp", + "LatencyStatistics.cpp", "PropertyMap.cpp", "TouchVideoFrame.cpp", + "VelocityControl.cpp", + "VelocityTracker.cpp", "VirtualKeyMap.cpp", ], @@ -69,9 +72,6 @@ cc_library { srcs: [ "InputTransport.cpp", "InputWindow.cpp", - "LatencyStatistics.cpp", - "VelocityControl.cpp", - "VelocityTracker.cpp", "android/FocusRequest.aidl", "android/InputApplicationInfo.aidl", "android/os/IInputConstants.aidl", @@ -99,12 +99,33 @@ cc_library { shared: { enabled: false, }, + include_dirs: [ + "frameworks/native/libs/arect/include", + ], + }, + linux_glibc: { + srcs: [ + "InputTransport.cpp", + "InputWindow.cpp", + "android/FocusRequest.aidl", + "android/InputApplicationInfo.aidl", + "android/os/IInputConstants.aidl", + "android/os/IInputFlinger.aidl", + "android/os/ISetInputWindowsListener.aidl", + "android/os/TouchOcclusionMode.aidl", + ], + static_libs: [ + "libhostgraphics", + ], + shared_libs: [ + "libbinder", + ], }, }, aidl: { local_include_dirs: ["."], - export_aidl_headers: true + export_aidl_headers: true, }, } diff --git a/libs/input/Input.cpp b/libs/input/Input.cpp index fb2f186984..f3b8832a8f 100644 --- a/libs/input/Input.cpp +++ b/libs/input/Input.cpp @@ -26,8 +26,8 @@ #include #include -#ifdef __ANDROID__ #include +#ifdef __ANDROID__ #include #endif @@ -250,7 +250,6 @@ void PointerCoords::applyOffset(float xOffset, float yOffset) { setAxisValue(AMOTION_EVENT_AXIS_Y, getY() + yOffset); } -#ifdef __ANDROID__ status_t PointerCoords::readFromParcel(Parcel* parcel) { bits = parcel->readInt64(); @@ -274,7 +273,6 @@ status_t PointerCoords::writeToParcel(Parcel* parcel) const { } return OK; } -#endif void PointerCoords::tooManyAxes(int axis) { ALOGW("Could not set value for axis %d because the PointerCoords structure is full and " @@ -536,7 +534,6 @@ void MotionEvent::transform(const std::array& matrix) { } } -#ifdef __ANDROID__ static status_t readFromParcel(ui::Transform& transform, const Parcel& parcel) { float dsdx, dtdx, tx, dtdy, dsdy, ty; status_t status = parcel.readFloat(&dsdx); @@ -673,7 +670,6 @@ status_t MotionEvent::writeToParcel(Parcel* parcel) const { } return OK; } -#endif bool MotionEvent::isTouchEvent(uint32_t source, int32_t action) { if (source & AINPUT_SOURCE_CLASS_POINTER) { diff --git a/libs/input/KeyCharacterMap.cpp b/libs/input/KeyCharacterMap.cpp index 7ac8a2e02c..2623ecde45 100644 --- a/libs/input/KeyCharacterMap.cpp +++ b/libs/input/KeyCharacterMap.cpp @@ -19,10 +19,7 @@ #include #include -#ifdef __ANDROID__ #include -#endif - #include #include #include @@ -590,7 +587,6 @@ void KeyCharacterMap::addLockedMetaKey(Vector& outEvents, } } -#ifdef __ANDROID__ std::shared_ptr KeyCharacterMap::readFromParcel(Parcel* parcel) { if (parcel == nullptr) { ALOGE("%s: Null parcel", __func__); @@ -676,7 +672,6 @@ void KeyCharacterMap::writeToParcel(Parcel* parcel) const { parcel->writeInt32(0); } } -#endif // --- KeyCharacterMap::Key --- diff --git a/libs/ui/Android.bp b/libs/ui/Android.bp index e3ae27000f..7c68aaa389 100644 --- a/libs/ui/Android.bp +++ b/libs/ui/Android.bp @@ -243,6 +243,8 @@ filegroup { name: "libui_host_common", srcs: [ "Rect.cpp", - "PixelFormat.cpp" + "Region.cpp", + "PixelFormat.cpp", + "Transform.cpp" ], } -- cgit v1.2.3-59-g8ed1b From 102936ef2b2e2c0c7c782f461b48f12dfc9464eb Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Wed, 4 Nov 2020 03:44:27 +0000 Subject: Move KeyCharacterMap to enum class Bug: 160010896 Test: compiles Change-Id: Ia8c0d976665acf817f083726dcac10db0cd91048 --- include/input/KeyCharacterMap.h | 28 ++++++++++++++-------------- libs/input/KeyCharacterMap.cpp | 34 ++++++++++++++++------------------ libs/input/Keyboard.cpp | 8 ++++---- 3 files changed, 34 insertions(+), 36 deletions(-) (limited to 'libs/input/KeyCharacterMap.cpp') diff --git a/include/input/KeyCharacterMap.h b/include/input/KeyCharacterMap.h index 339c7ebfeb..8542577a8b 100644 --- a/include/input/KeyCharacterMap.h +++ b/include/input/KeyCharacterMap.h @@ -42,27 +42,27 @@ namespace android { */ class KeyCharacterMap { public: - enum KeyboardType { - KEYBOARD_TYPE_UNKNOWN = 0, - KEYBOARD_TYPE_NUMERIC = 1, - KEYBOARD_TYPE_PREDICTIVE = 2, - KEYBOARD_TYPE_ALPHA = 3, - KEYBOARD_TYPE_FULL = 4, + enum class KeyboardType : int32_t { + UNKNOWN = 0, + NUMERIC = 1, + PREDICTIVE = 2, + ALPHA = 3, + FULL = 4, /** * Deprecated. Set 'keyboard.specialFunction' to '1' in the device's IDC file instead. */ - KEYBOARD_TYPE_SPECIAL_FUNCTION = 5, - KEYBOARD_TYPE_OVERLAY = 6, + SPECIAL_FUNCTION = 5, + OVERLAY = 6, }; - enum Format { + enum class Format { // Base keyboard layout, may contain device-specific options, such as "type" declaration. - FORMAT_BASE = 0, + BASE = 0, // Overlay keyboard layout, more restrictive, may be published by applications, // cannot override device-specific options. - FORMAT_OVERLAY = 1, + OVERLAY = 1, // Either base or overlay layout ok. - FORMAT_ANY = 2, + ANY = 2, }; // Substitute key code and meta state for fallback action. @@ -86,7 +86,7 @@ public: void combine(const KeyCharacterMap& overlay); /* Gets the keyboard type. */ - int32_t getKeyboardType() const; + KeyboardType getKeyboardType() const; /* Gets the primary character for this key as in the label physically printed on it. * Returns 0 if none (eg. for non-printing keys). */ @@ -222,7 +222,7 @@ private: }; KeyedVector mKeys; - int mType; + KeyboardType mType; std::string mLoadFileName; KeyedVector mKeysByScanCode; diff --git a/libs/input/KeyCharacterMap.cpp b/libs/input/KeyCharacterMap.cpp index 2623ecde45..999d3c7508 100644 --- a/libs/input/KeyCharacterMap.cpp +++ b/libs/input/KeyCharacterMap.cpp @@ -83,9 +83,7 @@ static String8 toString(const char16_t* chars, size_t numChars) { // --- KeyCharacterMap --- -KeyCharacterMap::KeyCharacterMap() : - mType(KEYBOARD_TYPE_UNKNOWN) { -} +KeyCharacterMap::KeyCharacterMap() : mType(KeyboardType::UNKNOWN) {} KeyCharacterMap::KeyCharacterMap(const KeyCharacterMap& other) : mType(other.mType), @@ -184,7 +182,7 @@ void KeyCharacterMap::combine(const KeyCharacterMap& overlay) { mLoadFileName = overlay.mLoadFileName; } -int32_t KeyCharacterMap::getKeyboardType() const { +KeyCharacterMap::KeyboardType KeyCharacterMap::getKeyboardType() const { return mType; } @@ -593,7 +591,7 @@ std::shared_ptr KeyCharacterMap::readFromParcel(Parcel* parcel) return nullptr; } std::shared_ptr map = std::shared_ptr(new KeyCharacterMap()); - map->mType = parcel->readInt32(); + map->mType = static_cast(parcel->readInt32()); size_t numKeys = parcel->readInt32(); if (parcel->errorCheck()) { return nullptr; @@ -651,7 +649,7 @@ void KeyCharacterMap::writeToParcel(Parcel* parcel) const { ALOGE("%s: Null parcel", __func__); return; } - parcel->writeInt32(mType); + parcel->writeInt32(static_cast(mType)); size_t numKeys = mKeys.size(); parcel->writeInt32(numKeys); @@ -776,20 +774,20 @@ status_t KeyCharacterMap::Parser::parse() { return BAD_VALUE; } - if (mMap->mType == KEYBOARD_TYPE_UNKNOWN) { + if (mMap->mType == KeyboardType::UNKNOWN) { ALOGE("%s: Keyboard layout missing required keyboard 'type' declaration.", mTokenizer->getLocation().string()); return BAD_VALUE; } - if (mFormat == FORMAT_BASE) { - if (mMap->mType == KEYBOARD_TYPE_OVERLAY) { + if (mFormat == Format::BASE) { + if (mMap->mType == KeyboardType::OVERLAY) { ALOGE("%s: Base keyboard layout must specify a keyboard 'type' other than 'OVERLAY'.", mTokenizer->getLocation().string()); return BAD_VALUE; } - } else if (mFormat == FORMAT_OVERLAY) { - if (mMap->mType != KEYBOARD_TYPE_OVERLAY) { + } else if (mFormat == Format::OVERLAY) { + if (mMap->mType != KeyboardType::OVERLAY) { ALOGE("%s: Overlay keyboard layout missing required keyboard " "'type OVERLAY' declaration.", mTokenizer->getLocation().string()); @@ -801,7 +799,7 @@ status_t KeyCharacterMap::Parser::parse() { } status_t KeyCharacterMap::Parser::parseType() { - if (mMap->mType != KEYBOARD_TYPE_UNKNOWN) { + if (mMap->mType != KeyboardType::UNKNOWN) { ALOGE("%s: Duplicate keyboard 'type' declaration.", mTokenizer->getLocation().string()); return BAD_VALUE; @@ -810,20 +808,20 @@ status_t KeyCharacterMap::Parser::parseType() { KeyboardType type; String8 typeToken = mTokenizer->nextToken(WHITESPACE); if (typeToken == "NUMERIC") { - type = KEYBOARD_TYPE_NUMERIC; + type = KeyboardType::NUMERIC; } else if (typeToken == "PREDICTIVE") { - type = KEYBOARD_TYPE_PREDICTIVE; + type = KeyboardType::PREDICTIVE; } else if (typeToken == "ALPHA") { - type = KEYBOARD_TYPE_ALPHA; + type = KeyboardType::ALPHA; } else if (typeToken == "FULL") { - type = KEYBOARD_TYPE_FULL; + type = KeyboardType::FULL; } else if (typeToken == "SPECIAL_FUNCTION") { ALOGW("The SPECIAL_FUNCTION type is now declared in the device's IDC file, please set " "the property 'keyboard.specialFunction' to '1' there instead."); // TODO: return BAD_VALUE here in Q - type = KEYBOARD_TYPE_SPECIAL_FUNCTION; + type = KeyboardType::SPECIAL_FUNCTION; } else if (typeToken == "OVERLAY") { - type = KEYBOARD_TYPE_OVERLAY; + type = KeyboardType::OVERLAY; } else { ALOGE("%s: Expected keyboard type label, got '%s'.", mTokenizer->getLocation().string(), typeToken.string()); diff --git a/libs/input/Keyboard.cpp b/libs/input/Keyboard.cpp index 38a68b3884..14dc9e59fb 100644 --- a/libs/input/Keyboard.cpp +++ b/libs/input/Keyboard.cpp @@ -128,7 +128,7 @@ status_t KeyMap::loadKeyCharacterMap(const InputDeviceIdentifier& deviceIdentifi } base::Result> ret = - KeyCharacterMap::load(path, KeyCharacterMap::FORMAT_BASE); + KeyCharacterMap::load(path, KeyCharacterMap::Format::BASE); if (!ret) { return ret.error().code(); } @@ -159,9 +159,9 @@ bool isKeyboardSpecialFunction(const PropertyMap* config) { bool isEligibleBuiltInKeyboard(const InputDeviceIdentifier& deviceIdentifier, const PropertyMap* deviceConfiguration, const KeyMap* keyMap) { // TODO: remove the third OR statement (SPECIAL_FUNCTION) in Q - if (!keyMap->haveKeyCharacterMap() || isKeyboardSpecialFunction(deviceConfiguration) - || keyMap->keyCharacterMap->getKeyboardType() - == KeyCharacterMap::KEYBOARD_TYPE_SPECIAL_FUNCTION) { + if (!keyMap->haveKeyCharacterMap() || isKeyboardSpecialFunction(deviceConfiguration) || + keyMap->keyCharacterMap->getKeyboardType() == + KeyCharacterMap::KeyboardType::SPECIAL_FUNCTION) { return false; } -- cgit v1.2.3-59-g8ed1b From faa986c076dffff0be41dd866462494a76d0ad90 Mon Sep 17 00:00:00 2001 From: Brett Chabot Date: Wed, 4 Nov 2020 17:39:36 -0800 Subject: Fix libinput mac build, hopefully. Restore the ifdefs removed in go/ag/12549959, but using ifdef __linux__ instead of __ANDROID__. Test: m libinput Bug: 172023026 Change-Id: Iafbf592e7b937b780e5ffc2df490a6c17f5f6cf5 --- include/input/Input.h | 6 ++++++ include/input/KeyCharacterMap.h | 4 ++++ libs/input/Input.cpp | 6 ++++++ libs/input/KeyCharacterMap.cpp | 5 ++++- 4 files changed, 20 insertions(+), 1 deletion(-) (limited to 'libs/input/KeyCharacterMap.cpp') diff --git a/include/input/Input.h b/include/input/Input.h index d3a9694a50..3facfa5135 100644 --- a/include/input/Input.h +++ b/include/input/Input.h @@ -177,7 +177,9 @@ struct AInputDevice { namespace android { +#ifdef __linux__ class Parcel; +#endif const char* inputEventTypeToString(int32_t type); @@ -344,8 +346,10 @@ struct PointerCoords { return getAxisValue(AMOTION_EVENT_AXIS_Y); } +#ifdef __linux__ status_t readFromParcel(Parcel* parcel); status_t writeToParcel(Parcel* parcel) const; +#endif bool operator==(const PointerCoords& other) const; inline bool operator!=(const PointerCoords& other) const { @@ -704,8 +708,10 @@ public: // Matrix is in row-major form and compatible with SkMatrix. void transform(const std::array& matrix); +#ifdef __linux__ status_t readFromParcel(Parcel* parcel); status_t writeToParcel(Parcel* parcel) const; +#endif static bool isTouchEvent(uint32_t source, int32_t action); inline bool isTouchEvent() const { diff --git a/include/input/KeyCharacterMap.h b/include/input/KeyCharacterMap.h index 339c7ebfeb..3ac5cff18c 100644 --- a/include/input/KeyCharacterMap.h +++ b/include/input/KeyCharacterMap.h @@ -19,7 +19,9 @@ #include +#ifdef __linux__ #include +#endif #include #include @@ -132,11 +134,13 @@ public: void tryRemapKey(int32_t scanCode, int32_t metaState, int32_t* outKeyCode, int32_t* outMetaState) const; +#ifdef __linux__ /* Reads a key map from a parcel. */ static std::shared_ptr readFromParcel(Parcel* parcel); /* Writes a key map to a parcel. */ void writeToParcel(Parcel* parcel) const; +#endif KeyCharacterMap(const KeyCharacterMap& other); diff --git a/libs/input/Input.cpp b/libs/input/Input.cpp index ad7db75c1a..0ea3889338 100644 --- a/libs/input/Input.cpp +++ b/libs/input/Input.cpp @@ -28,7 +28,9 @@ #include #include +#ifdef __linux__ #include +#endif #ifdef __ANDROID__ #include #endif @@ -254,6 +256,7 @@ void PointerCoords::applyOffset(float xOffset, float yOffset) { setAxisValue(AMOTION_EVENT_AXIS_Y, getY() + yOffset); } +#ifdef __linux__ status_t PointerCoords::readFromParcel(Parcel* parcel) { bits = parcel->readInt64(); @@ -277,6 +280,7 @@ status_t PointerCoords::writeToParcel(Parcel* parcel) const { } return OK; } +#endif void PointerCoords::tooManyAxes(int axis) { ALOGW("Could not set value for axis %d because the PointerCoords structure is full and " @@ -538,6 +542,7 @@ void MotionEvent::transform(const std::array& matrix) { } } +#ifdef __linux__ static status_t readFromParcel(ui::Transform& transform, const Parcel& parcel) { float dsdx, dtdx, tx, dtdy, dsdy, ty; status_t status = parcel.readFloat(&dsdx); @@ -674,6 +679,7 @@ status_t MotionEvent::writeToParcel(Parcel* parcel) const { } return OK; } +#endif bool MotionEvent::isTouchEvent(uint32_t source, int32_t action) { if (source & AINPUT_SOURCE_CLASS_POINTER) { diff --git a/libs/input/KeyCharacterMap.cpp b/libs/input/KeyCharacterMap.cpp index 2623ecde45..d5457eaf08 100644 --- a/libs/input/KeyCharacterMap.cpp +++ b/libs/input/KeyCharacterMap.cpp @@ -19,7 +19,9 @@ #include #include +#ifdef __linux__ #include +#endif #include #include #include @@ -587,6 +589,7 @@ void KeyCharacterMap::addLockedMetaKey(Vector& outEvents, } } +#ifdef __linux__ std::shared_ptr KeyCharacterMap::readFromParcel(Parcel* parcel) { if (parcel == nullptr) { ALOGE("%s: Null parcel", __func__); @@ -672,7 +675,7 @@ void KeyCharacterMap::writeToParcel(Parcel* parcel) const { parcel->writeInt32(0); } } - +#endif // __linux__ // --- KeyCharacterMap::Key --- -- cgit v1.2.3-59-g8ed1b From f59a2f484d4765edd74c9bb3f911f66c4eb7a3f4 Mon Sep 17 00:00:00 2001 From: Chris Ye Date: Fri, 16 Oct 2020 12:55:26 -0700 Subject: Add SensorManager support in inputflinger. Add sensor device, sensor input mapper, sens event dispatcher support into inputflinger. Bug: 161634265 Test: atest inputflinger_tests Change-Id: I2dcb2c35d9dccefc4cd8d939b79cf340931a9410 --- include/android/input.h | 2 + include/input/InputDevice.h | 103 +++++ include/input/KeyCharacterMap.h | 2 + include/input/KeyLayoutMap.h | 10 + libs/input/InputDevice.cpp | 31 +- libs/input/KeyCharacterMap.cpp | 42 ++ libs/input/KeyLayoutMap.cpp | 129 ++++++- libs/input/tests/InputDevice_test.cpp | 53 ++- services/inputflinger/InputClassifier.cpp | 5 + services/inputflinger/InputClassifier.h | 1 + services/inputflinger/InputListener.cpp | 40 ++ .../benchmarks/InputDispatcher_benchmarks.cpp | 7 + services/inputflinger/dispatcher/Entry.cpp | 35 ++ services/inputflinger/dispatcher/Entry.h | 38 +- .../inputflinger/dispatcher/InputDispatcher.cpp | 141 ++++++- services/inputflinger/dispatcher/InputDispatcher.h | 6 +- services/inputflinger/dispatcher/InputState.cpp | 2 + .../dispatcher/include/InputDispatcherInterface.h | 6 + .../include/InputDispatcherPolicyInterface.h | 5 + services/inputflinger/include/InputListener.h | 27 ++ services/inputflinger/include/InputReaderBase.h | 11 + services/inputflinger/reader/Android.bp | 1 + services/inputflinger/reader/EventHub.cpp | 49 ++- services/inputflinger/reader/InputDevice.cpp | 25 ++ services/inputflinger/reader/InputReader.cpp | 35 ++ services/inputflinger/reader/include/EventHub.h | 13 + services/inputflinger/reader/include/InputDevice.h | 13 +- services/inputflinger/reader/include/InputReader.h | 8 + .../inputflinger/reader/mapper/InputMapper.cpp | 10 + services/inputflinger/reader/mapper/InputMapper.h | 5 + .../reader/mapper/SensorInputMapper.cpp | 421 +++++++++++++++++++++ .../inputflinger/reader/mapper/SensorInputMapper.h | 138 +++++++ .../inputflinger/tests/InputDispatcher_test.cpp | 6 + services/inputflinger/tests/InputReader_test.cpp | 197 ++++++++++ services/inputflinger/tests/TestInputListener.cpp | 10 + services/inputflinger/tests/TestInputListener.h | 4 + 36 files changed, 1587 insertions(+), 44 deletions(-) create mode 100644 services/inputflinger/reader/mapper/SensorInputMapper.cpp create mode 100644 services/inputflinger/reader/mapper/SensorInputMapper.h (limited to 'libs/input/KeyCharacterMap.cpp') diff --git a/include/android/input.h b/include/android/input.h index 38af89a31e..b5d399ee09 100644 --- a/include/android/input.h +++ b/include/android/input.h @@ -856,6 +856,8 @@ enum { AINPUT_SOURCE_TOUCH_NAVIGATION = 0x00200000 | AINPUT_SOURCE_CLASS_NONE, /** joystick */ AINPUT_SOURCE_JOYSTICK = 0x01000000 | AINPUT_SOURCE_CLASS_JOYSTICK, + /** sensor */ + AINPUT_SOURCE_SENSOR = 0x02000000 | AINPUT_SOURCE_CLASS_JOYSTICK, /** rotary encoder */ AINPUT_SOURCE_ROTARY_ENCODER = 0x00400000 | AINPUT_SOURCE_CLASS_NONE, diff --git a/include/input/InputDevice.h b/include/input/InputDevice.h index 60638caaab..23692e92d4 100644 --- a/include/input/InputDevice.h +++ b/include/input/InputDevice.h @@ -17,8 +17,10 @@ #ifndef _LIBINPUT_INPUT_DEVICE_H #define _LIBINPUT_INPUT_DEVICE_H +#include #include #include +#include #include namespace android { @@ -63,6 +65,97 @@ struct InputDeviceIdentifier { std::string getCanonicalName() const; }; +/* Types of input device sensors. Keep sync with core/java/android/hardware/Sensor.java */ +enum class InputDeviceSensorType : int32_t { + ACCELEROMETER = ASENSOR_TYPE_ACCELEROMETER, + MAGNETIC_FIELD = ASENSOR_TYPE_MAGNETIC_FIELD, + ORIENTATION = 3, + GYROSCOPE = ASENSOR_TYPE_GYROSCOPE, + LIGHT = ASENSOR_TYPE_LIGHT, + PRESSURE = ASENSOR_TYPE_PRESSURE, + TEMPERATURE = 7, + PROXIMITY = ASENSOR_TYPE_PROXIMITY, + GRAVITY = ASENSOR_TYPE_GRAVITY, + LINEAR_ACCELERATION = ASENSOR_TYPE_LINEAR_ACCELERATION, + ROTATION_VECTOR = ASENSOR_TYPE_ROTATION_VECTOR, + RELATIVE_HUMIDITY = ASENSOR_TYPE_RELATIVE_HUMIDITY, + AMBIENT_TEMPERATURE = ASENSOR_TYPE_AMBIENT_TEMPERATURE, + MAGNETIC_FIELD_UNCALIBRATED = ASENSOR_TYPE_MAGNETIC_FIELD_UNCALIBRATED, + GAME_ROTATION_VECTOR = ASENSOR_TYPE_GAME_ROTATION_VECTOR, + GYROSCOPE_UNCALIBRATED = ASENSOR_TYPE_GYROSCOPE_UNCALIBRATED, + SIGNIFICANT_MOTION = ASENSOR_TYPE_SIGNIFICANT_MOTION, +}; + +enum class InputDeviceSensorAccuracy : int32_t { + ACCURACY_NONE = 0, + ACCURACY_LOW = 1, + ACCURACY_MEDIUM = 2, + ACCURACY_HIGH = 3, +}; + +enum class InputDeviceSensorReportingMode : int32_t { + CONTINUOUS = 0, + ON_CHANGE = 1, + ONE_SHOT = 2, + SPECIAL_TRIGGER = 3, +}; + +struct InputDeviceSensorInfo { + explicit InputDeviceSensorInfo(std::string name, std::string vendor, int32_t version, + InputDeviceSensorType type, InputDeviceSensorAccuracy accuracy, + float maxRange, float resolution, float power, int32_t minDelay, + int32_t fifoReservedEventCount, int32_t fifoMaxEventCount, + std::string stringType, int32_t maxDelay, int32_t flags, + int32_t id) + : name(name), + vendor(vendor), + version(version), + type(type), + accuracy(accuracy), + maxRange(maxRange), + resolution(resolution), + power(power), + minDelay(minDelay), + fifoReservedEventCount(fifoReservedEventCount), + fifoMaxEventCount(fifoMaxEventCount), + stringType(stringType), + maxDelay(maxDelay), + flags(flags), + id(id) {} + // Name string of the sensor. + std::string name; + // Vendor string of this sensor. + std::string vendor; + // Version of the sensor's module. + int32_t version; + // Generic type of this sensor. + InputDeviceSensorType type; + // The current accuracy of sensor event. + InputDeviceSensorAccuracy accuracy; + // Maximum range of the sensor in the sensor's unit. + float maxRange; + // Resolution of the sensor in the sensor's unit. + float resolution; + // The power in mA used by this sensor while in use. + float power; + // The minimum delay allowed between two events in microsecond or zero if this sensor only + // returns a value when the data it's measuring changes. + int32_t minDelay; + // Number of events reserved for this sensor in the batch mode FIFO. + int32_t fifoReservedEventCount; + // Maximum number of events of this sensor that could be batched. + int32_t fifoMaxEventCount; + // The type of this sensor as a string. + std::string stringType; + // The delay between two sensor events corresponding to the lowest frequency that this sensor + // supports. + int32_t maxDelay; + // Sensor flags + int32_t flags; + // Sensor id, same as the input device ID it belongs to. + int32_t id; +}; + /* * Describes the characteristics and capabilities of an input device. */ @@ -104,6 +197,7 @@ public: void addMotionRange(int32_t axis, uint32_t source, float min, float max, float flat, float fuzz, float resolution); void addMotionRange(const MotionRange& range); + void addSensorInfo(const InputDeviceSensorInfo& info); inline void setKeyboardType(int32_t keyboardType) { mKeyboardType = keyboardType; } inline int32_t getKeyboardType() const { return mKeyboardType; } @@ -122,10 +216,17 @@ public: inline void setButtonUnderPad(bool hasButton) { mHasButtonUnderPad = hasButton; } inline bool hasButtonUnderPad() const { return mHasButtonUnderPad; } + inline void setHasSensor(bool hasSensor) { mHasSensor = hasSensor; } + inline bool hasSensor() const { return mHasSensor; } + inline const std::vector& getMotionRanges() const { return mMotionRanges; } + const InputDeviceSensorInfo* getSensorInfo(InputDeviceSensorType type); + + const std::vector getSensorTypes(); + private: int32_t mId; int32_t mGeneration; @@ -139,8 +240,10 @@ private: std::shared_ptr mKeyCharacterMap; bool mHasVibrator; bool mHasButtonUnderPad; + bool mHasSensor; std::vector mMotionRanges; + std::unordered_map mSensors; }; /* Types of input device configuration files. */ diff --git a/include/input/KeyCharacterMap.h b/include/input/KeyCharacterMap.h index 23f8ddf764..451ca3c6cd 100644 --- a/include/input/KeyCharacterMap.h +++ b/include/input/KeyCharacterMap.h @@ -142,6 +142,8 @@ public: void writeToParcel(Parcel* parcel) const; #endif + bool operator==(const KeyCharacterMap& other) const; + KeyCharacterMap(const KeyCharacterMap& other); virtual ~KeyCharacterMap(); diff --git a/include/input/KeyLayoutMap.h b/include/input/KeyLayoutMap.h index 872dd45c73..b2bd535cbf 100644 --- a/include/input/KeyLayoutMap.h +++ b/include/input/KeyLayoutMap.h @@ -24,6 +24,8 @@ #include #include +#include + namespace android { struct AxisInfo { @@ -76,6 +78,8 @@ public: status_t mapAxis(int32_t scanCode, AxisInfo* outAxisInfo) const; const std::string getLoadFileName() const; + // Return pair of sensor type and sensor data index, for the input device abs code + base::Result> mapSensor(int32_t absCode); virtual ~KeyLayoutMap(); @@ -89,12 +93,17 @@ private: int32_t ledCode; }; + struct Sensor { + InputDeviceSensorType sensorType; + int32_t sensorDataIndex; + }; KeyedVector mKeysByScanCode; KeyedVector mKeysByUsageCode; KeyedVector mAxes; KeyedVector mLedsByScanCode; KeyedVector mLedsByUsageCode; + std::unordered_map mSensorsByAbsCode; std::string mLoadFileName; KeyLayoutMap(); @@ -114,6 +123,7 @@ private: status_t parseKey(); status_t parseAxis(); status_t parseLed(); + status_t parseSensor(); }; }; diff --git a/libs/input/InputDevice.cpp b/libs/input/InputDevice.cpp index 34eba5be7f..2ed441d8b4 100644 --- a/libs/input/InputDevice.cpp +++ b/libs/input/InputDevice.cpp @@ -23,6 +23,7 @@ #include #include #include +#include using android::base::StringPrintf; @@ -166,7 +167,9 @@ InputDeviceInfo::InputDeviceInfo(const InputDeviceInfo& other) mKeyCharacterMap(other.mKeyCharacterMap), mHasVibrator(other.mHasVibrator), mHasButtonUnderPad(other.mHasButtonUnderPad), - mMotionRanges(other.mMotionRanges) {} + mHasSensor(other.mHasSensor), + mMotionRanges(other.mMotionRanges), + mSensors(other.mSensors) {} InputDeviceInfo::~InputDeviceInfo() { } @@ -185,7 +188,9 @@ void InputDeviceInfo::initialize(int32_t id, int32_t generation, int32_t control mKeyboardType = AINPUT_KEYBOARD_TYPE_NONE; mHasVibrator = false; mHasButtonUnderPad = false; + mHasSensor = false; mMotionRanges.clear(); + mSensors.clear(); } const InputDeviceInfo::MotionRange* InputDeviceInfo::getMotionRange( @@ -214,4 +219,28 @@ void InputDeviceInfo::addMotionRange(const MotionRange& range) { mMotionRanges.push_back(range); } +void InputDeviceInfo::addSensorInfo(const InputDeviceSensorInfo& info) { + if (mSensors.find(info.type) != mSensors.end()) { + ALOGW("Sensor type %s already exists, will be replaced by new sensor added.", + NamedEnum::string(info.type).c_str()); + } + mSensors.insert_or_assign(info.type, info); +} + +const std::vector InputDeviceInfo::getSensorTypes() { + std::vector types; + for (const auto& [type, info] : mSensors) { + types.push_back(type); + } + return types; +} + +const InputDeviceSensorInfo* InputDeviceInfo::getSensorInfo(InputDeviceSensorType type) { + auto it = mSensors.find(type); + if (it == mSensors.end()) { + return nullptr; + } + return &it->second; +} + } // namespace android diff --git a/libs/input/KeyCharacterMap.cpp b/libs/input/KeyCharacterMap.cpp index f5432ad3ee..5666de6624 100644 --- a/libs/input/KeyCharacterMap.cpp +++ b/libs/input/KeyCharacterMap.cpp @@ -103,6 +103,48 @@ KeyCharacterMap::~KeyCharacterMap() { } } +bool KeyCharacterMap::operator==(const KeyCharacterMap& other) const { + if (mType != other.mType) { + return false; + } + if (mKeys.size() != other.mKeys.size() || + mKeysByScanCode.size() != other.mKeysByScanCode.size() || + mKeysByUsageCode.size() != other.mKeysByUsageCode.size()) { + return false; + } + + for (size_t i = 0; i < mKeys.size(); i++) { + if (mKeys.keyAt(i) != other.mKeys.keyAt(i)) { + return false; + } + const Key* key = mKeys.valueAt(i); + const Key* otherKey = other.mKeys.valueAt(i); + if (key->label != otherKey->label || key->number != otherKey->number) { + return false; + } + } + + for (size_t i = 0; i < mKeysByScanCode.size(); i++) { + if (mKeysByScanCode.keyAt(i) != other.mKeysByScanCode.keyAt(i)) { + return false; + } + if (mKeysByScanCode.valueAt(i) != other.mKeysByScanCode.valueAt(i)) { + return false; + } + } + + for (size_t i = 0; i < mKeysByUsageCode.size(); i++) { + if (mKeysByUsageCode.keyAt(i) != other.mKeysByUsageCode.keyAt(i)) { + return false; + } + if (mKeysByUsageCode.valueAt(i) != other.mKeysByUsageCode.valueAt(i)) { + return false; + } + } + + return true; +} + base::Result> KeyCharacterMap::load(const std::string& filename, Format format) { Tokenizer* tokenizer; diff --git a/libs/input/KeyLayoutMap.cpp b/libs/input/KeyLayoutMap.cpp index 16ce48aca1..d36e417850 100644 --- a/libs/input/KeyLayoutMap.cpp +++ b/libs/input/KeyLayoutMap.cpp @@ -20,12 +20,13 @@ #include #include -#include #include -#include +#include +#include #include -#include +#include #include +#include // Enables debug output for the parser. #define DEBUG_PARSER 0 @@ -41,6 +42,26 @@ namespace android { static const char* WHITESPACE = " \t\r"; +#define SENSOR_ENTRY(type) NamedEnum::string(type), type +static const std::unordered_map SENSOR_LIST = + {{SENSOR_ENTRY(InputDeviceSensorType::ACCELEROMETER)}, + {SENSOR_ENTRY(InputDeviceSensorType::MAGNETIC_FIELD)}, + {SENSOR_ENTRY(InputDeviceSensorType::ORIENTATION)}, + {SENSOR_ENTRY(InputDeviceSensorType::GYROSCOPE)}, + {SENSOR_ENTRY(InputDeviceSensorType::LIGHT)}, + {SENSOR_ENTRY(InputDeviceSensorType::PRESSURE)}, + {SENSOR_ENTRY(InputDeviceSensorType::TEMPERATURE)}, + {SENSOR_ENTRY(InputDeviceSensorType::PROXIMITY)}, + {SENSOR_ENTRY(InputDeviceSensorType::GRAVITY)}, + {SENSOR_ENTRY(InputDeviceSensorType::LINEAR_ACCELERATION)}, + {SENSOR_ENTRY(InputDeviceSensorType::ROTATION_VECTOR)}, + {SENSOR_ENTRY(InputDeviceSensorType::RELATIVE_HUMIDITY)}, + {SENSOR_ENTRY(InputDeviceSensorType::AMBIENT_TEMPERATURE)}, + {SENSOR_ENTRY(InputDeviceSensorType::MAGNETIC_FIELD_UNCALIBRATED)}, + {SENSOR_ENTRY(InputDeviceSensorType::GAME_ROTATION_VECTOR)}, + {SENSOR_ENTRY(InputDeviceSensorType::GYROSCOPE_UNCALIBRATED)}, + {SENSOR_ENTRY(InputDeviceSensorType::SIGNIFICANT_MOTION)}}; + // --- KeyLayoutMap --- KeyLayoutMap::KeyLayoutMap() { @@ -127,6 +148,24 @@ status_t KeyLayoutMap::mapKey(int32_t scanCode, int32_t usageCode, return NO_ERROR; } +// Return pair of sensor type and sensor data index, for the input device abs code +base::Result> KeyLayoutMap::mapSensor(int32_t absCode) { + auto it = mSensorsByAbsCode.find(absCode); + if (it == mSensorsByAbsCode.end()) { +#if DEBUG_MAPPING + ALOGD("mapSensor: absCode=%d, ~ Failed.", absCode); +#endif + return Errorf("Can't find abs code {}.", absCode); + } + const Sensor& sensor = it->second; + +#if DEBUG_MAPPING + ALOGD("mapSensor: absCode=%d, sensorType=0x%0x, sensorDataIndex=0x%x.", absCode, + NamedEnum::string(sensor.sensorType), sensor.sensorDataIndex); +#endif + return std::make_pair(sensor.sensorType, sensor.sensorDataIndex); +} + const KeyLayoutMap::Key* KeyLayoutMap::getKey(int32_t scanCode, int32_t usageCode) const { if (usageCode) { ssize_t index = mKeysByUsageCode.indexOfKey(usageCode); @@ -242,6 +281,10 @@ status_t KeyLayoutMap::Parser::parse() { mTokenizer->skipDelimiters(WHITESPACE); status_t status = parseLed(); if (status) return status; + } else if (keywordToken == "sensor") { + mTokenizer->skipDelimiters(WHITESPACE); + status_t status = parseSensor(); + if (status) return status; } else { ALOGE("%s: Expected keyword, got '%s'.", mTokenizer->getLocation().string(), keywordToken.string()); @@ -468,4 +511,84 @@ status_t KeyLayoutMap::Parser::parseLed() { map.add(code, led); return NO_ERROR; } + +static std::optional getSensorType(const char* token) { + auto it = SENSOR_LIST.find(std::string(token)); + if (it == SENSOR_LIST.end()) { + return std::nullopt; + } + return it->second; +} + +static std::optional getSensorDataIndex(String8 token) { + std::string tokenStr(token.string()); + if (tokenStr == "X") { + return 0; + } else if (tokenStr == "Y") { + return 1; + } else if (tokenStr == "Z") { + return 2; + } + return std::nullopt; +} + +// Parse sensor type and data index mapping, as below format +// sensor +// raw abs : the linux abs code of the axis +// sensor type : string name of InputDeviceSensorType +// sensor data index : the data index of sensor, out of [X, Y, Z] +// Examples: +// sensor 0x00 ACCELEROMETER X +// sensor 0x01 ACCELEROMETER Y +// sensor 0x02 ACCELEROMETER Z +// sensor 0x03 GYROSCOPE X +// sensor 0x04 GYROSCOPE Y +// sensor 0x05 GYROSCOPE Z +status_t KeyLayoutMap::Parser::parseSensor() { + String8 codeToken = mTokenizer->nextToken(WHITESPACE); + char* end; + int32_t code = int32_t(strtol(codeToken.string(), &end, 0)); + if (*end) { + ALOGE("%s: Expected sensor %s number, got '%s'.", mTokenizer->getLocation().string(), + "abs code", codeToken.string()); + return BAD_VALUE; + } + + std::unordered_map& map = mMap->mSensorsByAbsCode; + if (map.find(code) != map.end()) { + ALOGE("%s: Duplicate entry for sensor %s '%s'.", mTokenizer->getLocation().string(), + "abs code", codeToken.string()); + return BAD_VALUE; + } + + mTokenizer->skipDelimiters(WHITESPACE); + String8 sensorTypeToken = mTokenizer->nextToken(WHITESPACE); + std::optional typeOpt = getSensorType(sensorTypeToken.string()); + if (!typeOpt) { + ALOGE("%s: Expected sensor code label, got '%s'.", mTokenizer->getLocation().string(), + sensorTypeToken.string()); + return BAD_VALUE; + } + InputDeviceSensorType sensorType = typeOpt.value(); + mTokenizer->skipDelimiters(WHITESPACE); + String8 sensorDataIndexToken = mTokenizer->nextToken(WHITESPACE); + std::optional indexOpt = getSensorDataIndex(sensorDataIndexToken); + if (!indexOpt) { + ALOGE("%s: Expected sensor data index label, got '%s'.", mTokenizer->getLocation().string(), + sensorDataIndexToken.string()); + return BAD_VALUE; + } + int32_t sensorDataIndex = indexOpt.value(); + +#if DEBUG_PARSER + ALOGD("Parsed sensor: abs code=%d, sensorType=%d, sensorDataIndex=%d.", code, + NamedEnum::string(sensorType).c_str(), sensorDataIndex); +#endif + + Sensor sensor; + sensor.sensorType = sensorType; + sensor.sensorDataIndex = sensorDataIndex; + map.emplace(code, sensor); + return NO_ERROR; +} }; diff --git a/libs/input/tests/InputDevice_test.cpp b/libs/input/tests/InputDevice_test.cpp index c174ae94a6..e2cf2456ce 100644 --- a/libs/input/tests/InputDevice_test.cpp +++ b/libs/input/tests/InputDevice_test.cpp @@ -14,9 +14,12 @@ * limitations under the License. */ - +#include +#include #include #include +#include +#include namespace android { @@ -31,4 +34,52 @@ TEST(InputDeviceIdentifierTest, getCanonicalName) { ASSERT_EQ(std::string("deviceName-123_version_C_"), identifier.getCanonicalName()); } +class InputDeviceKeyMapTest : public testing::Test { +protected: + void loadKeyLayout(const char* name) { + std::string path = + getInputDeviceConfigurationFilePathByName(name, + InputDeviceConfigurationFileType:: + KEY_LAYOUT); + ASSERT_FALSE(path.empty()); + base::Result> ret = KeyLayoutMap::load(path); + ASSERT_TRUE(ret) << "Cannot load KeyLayout at " << path; + mKeyMap.keyLayoutMap = std::move(*ret); + mKeyMap.keyLayoutFile = path; + } + + void loadKeyCharacterMap(const char* name) { + InputDeviceIdentifier identifier; + identifier.name = name; + std::string path = + getInputDeviceConfigurationFilePathByName(identifier.getCanonicalName(), + InputDeviceConfigurationFileType:: + KEY_CHARACTER_MAP); + ASSERT_FALSE(path.empty()) << "KeyCharacterMap for " << name << " not found"; + base::Result> ret = + KeyCharacterMap::load(path, KeyCharacterMap::Format::BASE); + ASSERT_TRUE(ret) << "Cannot load KeyCharacterMap at " << path; + mKeyMap.keyCharacterMap = *ret; + mKeyMap.keyCharacterMapFile = path; + } + + virtual void SetUp() override { + loadKeyLayout("Generic"); + loadKeyCharacterMap("Generic"); + } + + virtual void TearDown() override {} + + KeyMap mKeyMap; +}; + +TEST_F(InputDeviceKeyMapTest, keyCharacterMapParcelingTest) { + Parcel parcel; + mKeyMap.keyCharacterMap->writeToParcel(&parcel); + parcel.setDataPosition(0); + std::shared_ptr map = KeyCharacterMap::readFromParcel(&parcel); + // Verify the key character map is the same as original + ASSERT_EQ(*map, *mKeyMap.keyCharacterMap); +} + } // namespace android \ No newline at end of file diff --git a/services/inputflinger/InputClassifier.cpp b/services/inputflinger/InputClassifier.cpp index eafb5ab340..f5f0400995 100644 --- a/services/inputflinger/InputClassifier.cpp +++ b/services/inputflinger/InputClassifier.cpp @@ -391,6 +391,11 @@ void InputClassifier::notifyMotion(const NotifyMotionArgs* args) { mListener->notifyMotion(&newArgs); } +void InputClassifier::notifySensor(const NotifySensorArgs* args) { + // pass through + mListener->notifySensor(args); +} + void InputClassifier::notifySwitch(const NotifySwitchArgs* args) { // pass through mListener->notifySwitch(args); diff --git a/services/inputflinger/InputClassifier.h b/services/inputflinger/InputClassifier.h index 6965940e17..bf10920e61 100644 --- a/services/inputflinger/InputClassifier.h +++ b/services/inputflinger/InputClassifier.h @@ -229,6 +229,7 @@ public: virtual void notifyKey(const NotifyKeyArgs* args) override; virtual void notifyMotion(const NotifyMotionArgs* args) override; virtual void notifySwitch(const NotifySwitchArgs* args) override; + virtual void notifySensor(const NotifySensorArgs* args) override; virtual void notifyDeviceReset(const NotifyDeviceResetArgs* args) override; void notifyPointerCaptureChanged(const NotifyPointerCaptureChangedArgs* args) override; diff --git a/services/inputflinger/InputListener.cpp b/services/inputflinger/InputListener.cpp index 49a813e82d..4be49b120f 100644 --- a/services/inputflinger/InputListener.cpp +++ b/services/inputflinger/InputListener.cpp @@ -211,6 +211,41 @@ void NotifySwitchArgs::notify(const sp& listener) const listener->notifySwitch(this); } +// --- NotifySensorArgs --- + +NotifySensorArgs::NotifySensorArgs(int32_t id, nsecs_t eventTime, int32_t deviceId, uint32_t source, + InputDeviceSensorType sensorType, + InputDeviceSensorAccuracy accuracy, bool accuracyChanged, + nsecs_t hwTimestamp, std::vector values) + : NotifyArgs(id, eventTime), + deviceId(deviceId), + source(source), + sensorType(sensorType), + accuracy(accuracy), + accuracyChanged(accuracyChanged), + hwTimestamp(hwTimestamp), + values(std::move(values)) {} + +NotifySensorArgs::NotifySensorArgs(const NotifySensorArgs& other) + : NotifyArgs(other.id, other.eventTime), + deviceId(other.deviceId), + source(other.source), + sensorType(other.sensorType), + accuracy(other.accuracy), + accuracyChanged(other.accuracyChanged), + hwTimestamp(other.hwTimestamp), + values(other.values) {} + +bool NotifySensorArgs::operator==(const NotifySensorArgs rhs) const { + return id == rhs.id && eventTime == rhs.eventTime && sensorType == rhs.sensorType && + accuracy == rhs.accuracy && accuracyChanged == rhs.accuracyChanged && + hwTimestamp == rhs.hwTimestamp && values == rhs.values; +} + +void NotifySensorArgs::notify(const sp& listener) const { + listener->notifySensor(this); +} + // --- NotifyDeviceResetArgs --- NotifyDeviceResetArgs::NotifyDeviceResetArgs(int32_t id, nsecs_t eventTime, int32_t deviceId) @@ -286,6 +321,11 @@ void QueuedInputListener::notifySwitch(const NotifySwitchArgs* args) { mArgsQueue.push_back(new NotifySwitchArgs(*args)); } +void QueuedInputListener::notifySensor(const NotifySensorArgs* args) { + traceEvent(__func__, args->id); + mArgsQueue.push_back(new NotifySensorArgs(*args)); +} + void QueuedInputListener::notifyDeviceReset(const NotifyDeviceResetArgs* args) { traceEvent(__func__, args->id); mArgsQueue.push_back(new NotifyDeviceResetArgs(*args)); diff --git a/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp b/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp index 7c572b4682..4e55872bc6 100644 --- a/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp +++ b/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp @@ -66,6 +66,13 @@ private: void notifyFocusChanged(const sp&, const sp&) override {} + void notifySensorEvent(int32_t deviceId, InputDeviceSensorType sensorType, + InputDeviceSensorAccuracy accuracy, nsecs_t timestamp, + const std::vector& values) override {} + + void notifySensorAccuracy(int32_t deviceId, InputDeviceSensorType sensorType, + InputDeviceSensorAccuracy accuracy) override {} + void notifyUntrustedTouch(const std::string& obscuringPackage) override {} void getDispatcherConfiguration(InputDispatcherConfiguration* outConfig) override { diff --git a/services/inputflinger/dispatcher/Entry.cpp b/services/inputflinger/dispatcher/Entry.cpp index d8a6548856..f0976b9030 100644 --- a/services/inputflinger/dispatcher/Entry.cpp +++ b/services/inputflinger/dispatcher/Entry.cpp @@ -239,6 +239,41 @@ std::string MotionEntry::getDescription() const { return msg; } +// --- SensorEntry --- + +SensorEntry::SensorEntry(int32_t id, nsecs_t eventTime, int32_t deviceId, uint32_t source, + uint32_t policyFlags, nsecs_t hwTimestamp, + InputDeviceSensorType sensorType, InputDeviceSensorAccuracy accuracy, + bool accuracyChanged, std::vector values) + : EventEntry(id, Type::SENSOR, eventTime, policyFlags), + deviceId(deviceId), + source(source), + sensorType(sensorType), + accuracy(accuracy), + accuracyChanged(accuracyChanged), + hwTimestamp(hwTimestamp), + values(std::move(values)) {} + +SensorEntry::~SensorEntry() {} + +std::string SensorEntry::getDescription() const { + std::string msg; + msg += StringPrintf("SensorEntry(deviceId=%d, source=0x%08x, sensorType=0x%08x, " + "accuracy=0x%08x, hwTimestamp=%" PRId64, + deviceId, source, sensorType, accuracy, hwTimestamp); + + if (!GetBoolProperty("ro.debuggable", false)) { + for (size_t i = 0; i < values.size(); i++) { + if (i > 0) { + msg += ", "; + } + msg += StringPrintf("(%.3f)", values[i]); + } + } + msg += StringPrintf(", policyFlags=0x%08x", policyFlags); + return msg; +} + // --- DispatchEntry --- volatile int32_t DispatchEntry::sNextSeqAtomic; diff --git a/services/inputflinger/dispatcher/Entry.h b/services/inputflinger/dispatcher/Entry.h index fba5514625..3a860f05e0 100644 --- a/services/inputflinger/dispatcher/Entry.h +++ b/services/inputflinger/dispatcher/Entry.h @@ -36,26 +36,10 @@ struct EventEntry { FOCUS, KEY, MOTION, + SENSOR, POINTER_CAPTURE_CHANGED, }; - static const char* typeToString(Type type) { - switch (type) { - case Type::CONFIGURATION_CHANGED: - return "CONFIGURATION_CHANGED"; - case Type::DEVICE_RESET: - return "DEVICE_RESET"; - case Type::FOCUS: - return "FOCUS"; - case Type::KEY: - return "KEY"; - case Type::MOTION: - return "MOTION"; - case Type::POINTER_CAPTURE_CHANGED: - return "POINTER_CAPTURE_CHANGED"; - } - } - int32_t id; Type type; nsecs_t eventTime; @@ -191,6 +175,25 @@ struct MotionEntry : EventEntry { virtual ~MotionEntry(); }; +struct SensorEntry : EventEntry { + int32_t deviceId; + uint32_t source; + InputDeviceSensorType sensorType; + InputDeviceSensorAccuracy accuracy; + bool accuracyChanged; + nsecs_t hwTimestamp; + + std::vector values; + + SensorEntry(int32_t id, nsecs_t eventTime, int32_t deviceId, uint32_t source, + uint32_t policyFlags, nsecs_t hwTimestamp, InputDeviceSensorType sensorType, + InputDeviceSensorAccuracy accuracy, bool accuracyChanged, + std::vector values); + std::string getDescription() const override; + + virtual ~SensorEntry(); +}; + // Tracks the progress of dispatching a particular event to a particular connection. struct DispatchEntry { const uint32_t seq; // unique sequence number, never 0 @@ -257,6 +260,7 @@ struct CommandEntry { sp connection; nsecs_t eventTime; std::shared_ptr keyEntry; + std::shared_ptr sensorEntry; std::shared_ptr inputApplicationHandle; std::string reason; int32_t userActivityEventType; diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp index 6c44a54550..3af33726fd 100644 --- a/services/inputflinger/dispatcher/InputDispatcher.cpp +++ b/services/inputflinger/dispatcher/InputDispatcher.cpp @@ -47,8 +47,6 @@ static constexpr bool DEBUG_TOUCH_OCCLUSION = true; // Log debug messages about hover events. #define DEBUG_HOVER 0 -#include "InputDispatcher.h" - #include #include #include @@ -73,6 +71,7 @@ static constexpr bool DEBUG_TOUCH_OCCLUSION = true; #include #include "Connection.h" +#include "InputDispatcher.h" #define INDENT " " #define INDENT2 " " @@ -758,6 +757,23 @@ void InputDispatcher::dispatchOnceInnerLocked(nsecs_t* nextWakeupTime) { done = dispatchMotionLocked(currentTime, motionEntry, &dropReason, nextWakeupTime); break; } + + case EventEntry::Type::SENSOR: { + std::shared_ptr sensorEntry = + std::static_pointer_cast(mPendingEvent); + if (dropReason == DropReason::NOT_DROPPED && isAppSwitchDue) { + dropReason = DropReason::APP_SWITCH; + } + // Sensor timestamps use SYSTEM_TIME_BOOTTIME time base, so we can't use + // 'currentTime' here, get SYSTEM_TIME_BOOTTIME instead. + nsecs_t bootTime = systemTime(SYSTEM_TIME_BOOTTIME); + if (dropReason == DropReason::NOT_DROPPED && isStaleEvent(bootTime, *sensorEntry)) { + dropReason = DropReason::STALE; + } + dispatchSensorLocked(currentTime, sensorEntry, &dropReason, nextWakeupTime); + done = true; + break; + } } if (done) { @@ -873,6 +889,7 @@ bool InputDispatcher::enqueueInboundEventLocked(std::unique_ptr newE } case EventEntry::Type::CONFIGURATION_CHANGED: case EventEntry::Type::DEVICE_RESET: + case EventEntry::Type::SENSOR: case EventEntry::Type::POINTER_CAPTURE_CHANGED: { // nothing to do break; @@ -883,7 +900,10 @@ bool InputDispatcher::enqueueInboundEventLocked(std::unique_ptr newE } void InputDispatcher::addRecentEventLocked(std::shared_ptr entry) { - mRecentQueue.push_back(entry); + // Do not store sensor event in recent queue to avoid flooding the queue. + if (entry->type != EventEntry::Type::SENSOR) { + mRecentQueue.push_back(entry); + } if (mRecentQueue.size() > RECENT_QUEUE_MAX_SIZE) { mRecentQueue.pop_front(); } @@ -1006,13 +1026,16 @@ void InputDispatcher::dropInboundEventLocked(const EventEntry& entry, DropReason } break; } + case EventEntry::Type::SENSOR: { + break; + } case EventEntry::Type::POINTER_CAPTURE_CHANGED: { break; } case EventEntry::Type::FOCUS: case EventEntry::Type::CONFIGURATION_CHANGED: case EventEntry::Type::DEVICE_RESET: { - LOG_ALWAYS_FATAL("Should not drop %s events", EventEntry::typeToString(entry.type)); + LOG_ALWAYS_FATAL("Should not drop %s events", NamedEnum::string(entry.type).c_str()); break; } } @@ -1365,6 +1388,51 @@ void InputDispatcher::logOutboundKeyDetails(const char* prefix, const KeyEntry& #endif } +void InputDispatcher::doNotifySensorLockedInterruptible(CommandEntry* commandEntry) { + mLock.unlock(); + + const std::shared_ptr& entry = commandEntry->sensorEntry; + if (entry->accuracyChanged) { + mPolicy->notifySensorAccuracy(entry->deviceId, entry->sensorType, entry->accuracy); + } + mPolicy->notifySensorEvent(entry->deviceId, entry->sensorType, entry->accuracy, + entry->hwTimestamp, entry->values); + mLock.lock(); +} + +void InputDispatcher::dispatchSensorLocked(nsecs_t currentTime, std::shared_ptr entry, + DropReason* dropReason, nsecs_t* nextWakeupTime) { +#if DEBUG_OUTBOUND_EVENT_DETAILS + ALOGD("notifySensorEvent eventTime=%" PRId64 ", hwTimestamp=%" PRId64 ", deviceId=%d, " + "source=0x%x, sensorType=%s", + entry->eventTime, entry->hwTimestamp, entry->deviceId, entry->source, + NamedEnum::string(sensorType).c_str()); +#endif + std::unique_ptr commandEntry = + std::make_unique(&InputDispatcher::doNotifySensorLockedInterruptible); + commandEntry->sensorEntry = entry; + postCommandLocked(std::move(commandEntry)); +} + +bool InputDispatcher::flushSensor(int deviceId, InputDeviceSensorType sensorType) { +#if DEBUG_OUTBOUND_EVENT_DETAILS + ALOGD("flushSensor deviceId=%d, sensorType=%s", deviceId, + NamedEnum::string(sensorType).c_str()); +#endif + { // acquire lock + std::scoped_lock _l(mLock); + + for (auto it = mInboundQueue.begin(); it != mInboundQueue.end(); it++) { + std::shared_ptr entry = *it; + if (entry->type == EventEntry::Type::SENSOR) { + it = mInboundQueue.erase(it); + releaseInboundEventLocked(entry); + } + } + } + return true; +} + bool InputDispatcher::dispatchMotionLocked(nsecs_t currentTime, std::shared_ptr entry, DropReason* dropReason, nsecs_t* nextWakeupTime) { ATRACE_CALL(); @@ -1553,8 +1621,9 @@ int32_t InputDispatcher::getTargetDisplayId(const EventEntry& entry) { case EventEntry::Type::POINTER_CAPTURE_CHANGED: case EventEntry::Type::FOCUS: case EventEntry::Type::CONFIGURATION_CHANGED: - case EventEntry::Type::DEVICE_RESET: { - ALOGE("%s events do not have a target display", EventEntry::typeToString(entry.type)); + case EventEntry::Type::DEVICE_RESET: + case EventEntry::Type::SENSOR: { + ALOGE("%s events do not have a target display", NamedEnum::string(entry.type).c_str()); return ADISPLAY_ID_NONE; } } @@ -1608,7 +1677,7 @@ InputEventInjectionResult InputDispatcher::findFocusedWindowTargetsLocked( if (focusedWindowHandle == nullptr && focusedApplicationHandle == nullptr) { ALOGI("Dropping %s event because there is no focused window or focused application in " "display %" PRId32 ".", - EventEntry::typeToString(entry.type), displayId); + NamedEnum::string(entry.type).c_str(), displayId); return InputEventInjectionResult::FAILED; } @@ -1633,7 +1702,7 @@ InputEventInjectionResult InputDispatcher::findFocusedWindowTargetsLocked( } else if (currentTime > *mNoFocusedWindowTimeoutTime) { // Already raised ANR. Drop the event ALOGE("Dropping %s event because there is no focused window", - EventEntry::typeToString(entry.type)); + NamedEnum::string(entry.type).c_str()); return InputEventInjectionResult::FAILED; } else { // Still waiting for the focused window @@ -2476,9 +2545,10 @@ void InputDispatcher::pokeUserActivityLocked(const EventEntry& eventEntry) { case EventEntry::Type::FOCUS: case EventEntry::Type::CONFIGURATION_CHANGED: case EventEntry::Type::DEVICE_RESET: + case EventEntry::Type::SENSOR: case EventEntry::Type::POINTER_CAPTURE_CHANGED: { LOG_ALWAYS_FATAL("%s events are not user activity", - EventEntry::typeToString(eventEntry.type)); + NamedEnum::string(eventEntry.type).c_str()); break; } } @@ -2522,7 +2592,7 @@ void InputDispatcher::prepareDispatchCycleLocked(nsecs_t currentTime, if (inputTarget.flags & InputTarget::FLAG_SPLIT) { LOG_ALWAYS_FATAL_IF(eventEntry->type != EventEntry::Type::MOTION, "Entry type %s should not have FLAG_SPLIT", - EventEntry::typeToString(eventEntry->type)); + NamedEnum::string(eventEntry->type).c_str()); const MotionEntry& originalMotionEntry = static_cast(*eventEntry); if (inputTarget.pointerIds.count() != originalMotionEntry.pointerCount) { @@ -2692,10 +2762,14 @@ void InputDispatcher::enqueueDispatchEntryLocked(const sp& connectio case EventEntry::Type::POINTER_CAPTURE_CHANGED: { break; } + case EventEntry::Type::SENSOR: { + LOG_ALWAYS_FATAL("SENSOR events should not go to apps via input channel"); + break; + } case EventEntry::Type::CONFIGURATION_CHANGED: case EventEntry::Type::DEVICE_RESET: { LOG_ALWAYS_FATAL("%s events should not go to apps", - EventEntry::typeToString(newEntry.type)); + NamedEnum::string(newEntry.type).c_str()); break; } } @@ -2913,9 +2987,10 @@ void InputDispatcher::startDispatchCycleLocked(nsecs_t currentTime, } case EventEntry::Type::CONFIGURATION_CHANGED: - case EventEntry::Type::DEVICE_RESET: { + case EventEntry::Type::DEVICE_RESET: + case EventEntry::Type::SENSOR: { LOG_ALWAYS_FATAL("Should never start dispatch cycles for %s events", - EventEntry::typeToString(eventEntry.type)); + NamedEnum::string(eventEntry.type).c_str()); return; } } @@ -3209,13 +3284,14 @@ void InputDispatcher::synthesizeCancelationEventsForConnectionLocked( case EventEntry::Type::FOCUS: case EventEntry::Type::POINTER_CAPTURE_CHANGED: { LOG_ALWAYS_FATAL("Canceling %s events is not supported", - EventEntry::typeToString(cancelationEventEntry->type)); + NamedEnum::string(cancelationEventEntry->type).c_str()); break; } case EventEntry::Type::CONFIGURATION_CHANGED: - case EventEntry::Type::DEVICE_RESET: { + case EventEntry::Type::DEVICE_RESET: + case EventEntry::Type::SENSOR: { LOG_ALWAYS_FATAL("%s event should not be found inside Connections's queue", - EventEntry::typeToString(cancelationEventEntry->type)); + NamedEnum::string(cancelationEventEntry->type).c_str()); break; } } @@ -3270,9 +3346,10 @@ void InputDispatcher::synthesizePointerDownEventsForConnectionLocked( case EventEntry::Type::FOCUS: case EventEntry::Type::CONFIGURATION_CHANGED: case EventEntry::Type::DEVICE_RESET: - case EventEntry::Type::POINTER_CAPTURE_CHANGED: { + case EventEntry::Type::POINTER_CAPTURE_CHANGED: + case EventEntry::Type::SENSOR: { LOG_ALWAYS_FATAL("%s event should not be found inside Connections's queue", - EventEntry::typeToString(downEventEntry->type)); + NamedEnum::string(downEventEntry->type).c_str()); break; } } @@ -3605,6 +3682,34 @@ void InputDispatcher::notifyMotion(const NotifyMotionArgs* args) { } } +void InputDispatcher::notifySensor(const NotifySensorArgs* args) { +#if DEBUG_INBOUND_EVENT_DETAILS + ALOGD("notifySensor - id=%" PRIx32 " eventTime=%" PRId64 ", deviceId=%d, source=0x%x, " + " sensorType=%s", + args->id, args->eventTime, args->deviceId, args->source, + NamedEnum::string(args->sensorType).c_str()); +#endif + + bool needWake; + { // acquire lock + mLock.lock(); + + // Just enqueue a new sensor event. + std::unique_ptr newEntry = + std::make_unique(args->id, args->eventTime, args->deviceId, + args->source, 0 /* policyFlags*/, args->hwTimestamp, + args->sensorType, args->accuracy, + args->accuracyChanged, args->values); + + needWake = enqueueInboundEventLocked(std::move(newEntry)); + mLock.unlock(); + } // release lock + + if (needWake) { + mLooper->wake(); + } +} + bool InputDispatcher::shouldSendMotionToInputFilterLocked(const NotifyMotionArgs* args) { return mInputFilterEnabled; } diff --git a/services/inputflinger/dispatcher/InputDispatcher.h b/services/inputflinger/dispatcher/InputDispatcher.h index 5d37645e40..3004701424 100644 --- a/services/inputflinger/dispatcher/InputDispatcher.h +++ b/services/inputflinger/dispatcher/InputDispatcher.h @@ -94,6 +94,7 @@ public: virtual void notifyKey(const NotifyKeyArgs* args) override; virtual void notifyMotion(const NotifyMotionArgs* args) override; virtual void notifySwitch(const NotifySwitchArgs* args) override; + virtual void notifySensor(const NotifySensorArgs* args) override; virtual void notifyDeviceReset(const NotifyDeviceResetArgs* args) override; virtual void notifyPointerCaptureChanged(const NotifyPointerCaptureChangedArgs* args) override; @@ -128,6 +129,7 @@ public: virtual status_t removeInputChannel(const sp& connectionToken) override; virtual status_t pilferPointers(const sp& token) override; virtual void requestPointerCapture(const sp& windowToken, bool enabled) override; + virtual bool flushSensor(int deviceId, InputDeviceSensorType sensorType) override; std::array sign(const VerifiedInputEvent& event) const; @@ -392,7 +394,8 @@ private: DropReason& dropReason) REQUIRES(mLock); void dispatchEventLocked(nsecs_t currentTime, std::shared_ptr entry, const std::vector& inputTargets) REQUIRES(mLock); - + void dispatchSensorLocked(nsecs_t currentTime, std::shared_ptr entry, + DropReason* dropReason, nsecs_t* nextWakeupTime) REQUIRES(mLock); void logOutboundKeyDetails(const char* prefix, const KeyEntry& entry); void logOutboundMotionDetails(const char* prefix, const MotionEntry& entry); @@ -592,6 +595,7 @@ private: REQUIRES(mLock); void doNotifyConnectionResponsiveLockedInterruptible(CommandEntry* commandEntry) REQUIRES(mLock); + void doNotifySensorLockedInterruptible(CommandEntry* commandEntry) REQUIRES(mLock); void doNotifyUntrustedTouchLockedInterruptible(CommandEntry* commandEntry) REQUIRES(mLock); void doInterceptKeyBeforeDispatchingLockedInterruptible(CommandEntry* commandEntry) REQUIRES(mLock); diff --git a/services/inputflinger/dispatcher/InputState.cpp b/services/inputflinger/dispatcher/InputState.cpp index 1656a21b41..3bb0bc995c 100644 --- a/services/inputflinger/dispatcher/InputState.cpp +++ b/services/inputflinger/dispatcher/InputState.cpp @@ -14,6 +14,8 @@ * limitations under the License. */ +#include "input/InputDevice.h" + #include "InputState.h" #include "InputDispatcher.h" diff --git a/services/inputflinger/dispatcher/include/InputDispatcherInterface.h b/services/inputflinger/dispatcher/include/InputDispatcherInterface.h index 2909d6940d..6e76c92b72 100644 --- a/services/inputflinger/dispatcher/include/InputDispatcherInterface.h +++ b/services/inputflinger/dispatcher/include/InputDispatcherInterface.h @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -193,6 +194,11 @@ public: * InputDispatcher is the source of truth of Pointer Capture. */ virtual void requestPointerCapture(const sp& windowToken, bool enabled) = 0; + /* Flush input device motion sensor. + * + * Returns true on success. + */ + virtual bool flushSensor(int deviceId, InputDeviceSensorType sensorType) = 0; }; } // namespace android diff --git a/services/inputflinger/dispatcher/include/InputDispatcherPolicyInterface.h b/services/inputflinger/dispatcher/include/InputDispatcherPolicyInterface.h index c1821ab10f..d9ec020a2b 100644 --- a/services/inputflinger/dispatcher/include/InputDispatcherPolicyInterface.h +++ b/services/inputflinger/dispatcher/include/InputDispatcherPolicyInterface.h @@ -68,6 +68,11 @@ public: /* Notifies the system that an input channel is unrecoverably broken. */ virtual void notifyInputChannelBroken(const sp& token) = 0; virtual void notifyFocusChanged(const sp& oldToken, const sp& newToken) = 0; + virtual void notifySensorEvent(int32_t deviceId, InputDeviceSensorType sensorType, + InputDeviceSensorAccuracy accuracy, nsecs_t timestamp, + const std::vector& values) = 0; + virtual void notifySensorAccuracy(int32_t deviceId, InputDeviceSensorType sensorType, + InputDeviceSensorAccuracy accuracy) = 0; /* Notifies the system that an untrusted touch occurred. */ virtual void notifyUntrustedTouch(const std::string& obscuringPackage) = 0; diff --git a/services/inputflinger/include/InputListener.h b/services/inputflinger/include/InputListener.h index 58eb91597b..11f726d50c 100644 --- a/services/inputflinger/include/InputListener.h +++ b/services/inputflinger/include/InputListener.h @@ -20,6 +20,7 @@ #include #include +#include #include #include @@ -141,6 +142,30 @@ struct NotifyMotionArgs : public NotifyArgs { virtual void notify(const sp& listener) const; }; +/* Describes a sensor event. */ +struct NotifySensorArgs : public NotifyArgs { + int32_t deviceId; + uint32_t source; + InputDeviceSensorType sensorType; + InputDeviceSensorAccuracy accuracy; + bool accuracyChanged; + nsecs_t hwTimestamp; + std::vector values; + + inline NotifySensorArgs() {} + + NotifySensorArgs(int32_t id, nsecs_t eventTime, int32_t deviceId, uint32_t source, + InputDeviceSensorType sensorType, InputDeviceSensorAccuracy accuracy, + bool accuracyChanged, nsecs_t hwTimestamp, std::vector values); + + NotifySensorArgs(const NotifySensorArgs& other); + + bool operator==(const NotifySensorArgs rhs) const; + + ~NotifySensorArgs() override {} + + void notify(const sp& listener) const override; +}; /* Describes a switch event. */ struct NotifySwitchArgs : public NotifyArgs { @@ -211,6 +236,7 @@ public: virtual void notifyKey(const NotifyKeyArgs* args) = 0; virtual void notifyMotion(const NotifyMotionArgs* args) = 0; virtual void notifySwitch(const NotifySwitchArgs* args) = 0; + virtual void notifySensor(const NotifySensorArgs* args) = 0; virtual void notifyDeviceReset(const NotifyDeviceResetArgs* args) = 0; virtual void notifyPointerCaptureChanged(const NotifyPointerCaptureChangedArgs* args) = 0; }; @@ -231,6 +257,7 @@ public: virtual void notifyKey(const NotifyKeyArgs* args) override; virtual void notifyMotion(const NotifyMotionArgs* args) override; virtual void notifySwitch(const NotifySwitchArgs* args) override; + virtual void notifySensor(const NotifySensorArgs* args) override; virtual void notifyDeviceReset(const NotifyDeviceResetArgs* args) override; void notifyPointerCaptureChanged(const NotifyPointerCaptureChangedArgs* args) override; diff --git a/services/inputflinger/include/InputReaderBase.h b/services/inputflinger/include/InputReaderBase.h index 6cce8ecc7b..ea9b48368e 100644 --- a/services/inputflinger/include/InputReaderBase.h +++ b/services/inputflinger/include/InputReaderBase.h @@ -111,6 +111,17 @@ public: /* Return true if the device can send input events to the specified display. */ virtual bool canDispatchToDisplay(int32_t deviceId, int32_t displayId) = 0; + + /* Enable sensor in input reader mapper. */ + virtual bool enableSensor(int32_t deviceId, InputDeviceSensorType sensorType, + std::chrono::microseconds samplingPeriod, + std::chrono::microseconds maxBatchReportLatency) = 0; + + /* Disable sensor in input reader mapper. */ + virtual void disableSensor(int32_t deviceId, InputDeviceSensorType sensorType) = 0; + + /* Flush sensor data in input reader mapper. */ + virtual void flushSensor(int32_t deviceId, InputDeviceSensorType sensorType) = 0; }; // --- InputReaderConfiguration --- diff --git a/services/inputflinger/reader/Android.bp b/services/inputflinger/reader/Android.bp index 0ccada94e4..abda4ef45c 100644 --- a/services/inputflinger/reader/Android.bp +++ b/services/inputflinger/reader/Android.bp @@ -37,6 +37,7 @@ filegroup { "mapper/KeyboardInputMapper.cpp", "mapper/MultiTouchInputMapper.cpp", "mapper/RotaryEncoderInputMapper.cpp", + "mapper/SensorInputMapper.cpp", "mapper/SingleTouchInputMapper.cpp", "mapper/SwitchInputMapper.cpp", "mapper/TouchInputMapper.cpp", diff --git a/services/inputflinger/reader/EventHub.cpp b/services/inputflinger/reader/EventHub.cpp index f864c0e5b6..b97ff909d6 100644 --- a/services/inputflinger/reader/EventHub.cpp +++ b/services/inputflinger/reader/EventHub.cpp @@ -157,6 +157,18 @@ Flags getAbsAxisUsage(int32_t axis, Flags de } } + if (deviceClasses.test(InputDeviceClass::SENSOR)) { + switch (axis) { + case ABS_X: + case ABS_Y: + case ABS_Z: + case ABS_RX: + case ABS_RY: + case ABS_RZ: + return InputDeviceClass::SENSOR; + } + } + // External stylus gets the pressure axis if (deviceClasses.test(InputDeviceClass::EXTERNAL_STYLUS)) { if (axis == ABS_PRESSURE) { @@ -250,6 +262,11 @@ void EventHub::Device::configureFd() { // uses the timestamps extensively and assumes they were recorded using the monotonic // clock. int clockId = CLOCK_MONOTONIC; + if (classes.test(InputDeviceClass::SENSOR)) { + // Each new sensor event should use the same time base as + // SystemClock.elapsedRealtimeNanos(). + clockId = CLOCK_BOOTTIME; + } bool usingClockIoctl = !ioctl(fd, EVIOCSCLOCKID, &clockId); ALOGI("usingClockIoctl=%s", toString(usingClockIoctl)); } @@ -550,6 +567,15 @@ bool EventHub::hasInputProperty(int32_t deviceId, int property) const { : false; } +bool EventHub::hasMscEvent(int32_t deviceId, int mscEvent) const { + std::scoped_lock _l(mLock); + + Device* device = getDeviceLocked(deviceId); + return mscEvent >= 0 && mscEvent <= MSC_MAX && device != nullptr + ? device->mscBitmask.test(mscEvent) + : false; +} + int32_t EventHub::getScanCodeState(int32_t deviceId, int32_t scanCode) const { if (scanCode >= 0 && scanCode <= KEY_MAX) { std::scoped_lock _l(mLock); @@ -705,6 +731,17 @@ status_t EventHub::mapAxis(int32_t deviceId, int32_t scanCode, AxisInfo* outAxis return NAME_NOT_FOUND; } +base::Result> EventHub::mapSensor(int32_t deviceId, + int32_t absCode) { + std::scoped_lock _l(mLock); + Device* device = getDeviceLocked(deviceId); + + if (device != nullptr && device->keyMap.haveKeyLayout()) { + return device->keyMap.keyLayoutMap->mapSensor(absCode); + } + return Errorf("Device not found or device has no key layout."); +} + void EventHub::setExcludedDevices(const std::vector& devices) { std::scoped_lock _l(mLock); @@ -1405,6 +1442,7 @@ status_t EventHub::openDeviceLocked(const std::string& devicePath) { device->readDeviceBitMask(EVIOCGBIT(EV_SW, 0), device->swBitmask); device->readDeviceBitMask(EVIOCGBIT(EV_LED, 0), device->ledBitmask); device->readDeviceBitMask(EVIOCGBIT(EV_FF, 0), device->ffBitmask); + device->readDeviceBitMask(EVIOCGBIT(EV_MSC, 0), device->mscBitmask); device->readDeviceBitMask(EVIOCGPROP(0), device->propBitmask); // See if this is a keyboard. Ignore everything in the button range except for @@ -1469,6 +1507,11 @@ status_t EventHub::openDeviceLocked(const std::string& devicePath) { } } + // Check whether this device is an accelerometer. + if (device->propBitmask.test(INPUT_PROP_ACCELEROMETER)) { + device->classes |= InputDeviceClass::SENSOR; + } + // Check whether this device has switches. for (int i = 0; i <= SW_MAX; i++) { if (device->swBitmask.test(i)) { @@ -1493,9 +1536,11 @@ status_t EventHub::openDeviceLocked(const std::string& devicePath) { } // Load the key map. - // We need to do this for joysticks too because the key layout may specify axes. + // We need to do this for joysticks too because the key layout may specify axes, and for + // sensor as well because the key layout may specify the axes to sensor data mapping. status_t keyMapStatus = NAME_NOT_FOUND; - if (device->classes.any(InputDeviceClass::KEYBOARD | InputDeviceClass::JOYSTICK)) { + if (device->classes.any(InputDeviceClass::KEYBOARD | InputDeviceClass::JOYSTICK | + InputDeviceClass::SENSOR)) { // Load the keymap for the device. keyMapStatus = device->loadKeyMapLocked(); } diff --git a/services/inputflinger/reader/InputDevice.cpp b/services/inputflinger/reader/InputDevice.cpp index d25d64a92c..ac72ac4189 100644 --- a/services/inputflinger/reader/InputDevice.cpp +++ b/services/inputflinger/reader/InputDevice.cpp @@ -28,6 +28,7 @@ #include "KeyboardInputMapper.h" #include "MultiTouchInputMapper.h" #include "RotaryEncoderInputMapper.h" +#include "SensorInputMapper.h" #include "SingleTouchInputMapper.h" #include "SwitchInputMapper.h" #include "VibratorInputMapper.h" @@ -196,6 +197,11 @@ void InputDevice::addEventHubDevice(int32_t eventHubId, bool populateMappers) { mappers.push_back(std::make_unique(*contextPtr)); } + // Motion sensor enabled devices. + if (classes.test(InputDeviceClass::SENSOR)) { + mappers.push_back(std::make_unique(*contextPtr)); + } + // External stylus-like devices. if (classes.test(InputDeviceClass::EXTERNAL_STYLUS)) { mappers.push_back(std::make_unique(*contextPtr)); @@ -460,6 +466,25 @@ std::vector InputDevice::getVibratorIds() { return vibrators; } +bool InputDevice::enableSensor(InputDeviceSensorType sensorType, + std::chrono::microseconds samplingPeriod, + std::chrono::microseconds maxBatchReportLatency) { + bool success = true; + for_each_mapper( + [&success, sensorType, samplingPeriod, maxBatchReportLatency](InputMapper& mapper) { + success &= mapper.enableSensor(sensorType, samplingPeriod, maxBatchReportLatency); + }); + return success; +} + +void InputDevice::disableSensor(InputDeviceSensorType sensorType) { + for_each_mapper([sensorType](InputMapper& mapper) { mapper.disableSensor(sensorType); }); +} + +void InputDevice::flushSensor(InputDeviceSensorType sensorType) { + for_each_mapper([sensorType](InputMapper& mapper) { mapper.flushSensor(sensorType); }); +} + void InputDevice::cancelTouch(nsecs_t when) { for_each_mapper([when](InputMapper& mapper) { mapper.cancelTouch(when); }); } diff --git a/services/inputflinger/reader/InputReader.cpp b/services/inputflinger/reader/InputReader.cpp index a6b5e2deb8..be21ace221 100644 --- a/services/inputflinger/reader/InputReader.cpp +++ b/services/inputflinger/reader/InputReader.cpp @@ -220,6 +220,11 @@ void InputReader::addDeviceLocked(nsecs_t when, int32_t eventHubId) { if (device->getClasses().test(InputDeviceClass::EXTERNAL_STYLUS)) { notifyExternalStylusPresenceChangedLocked(); } + + // Sensor input device is noisy, to save power disable it by default. + if (device->getClasses().test(InputDeviceClass::SENSOR)) { + mEventHub->disableDevice(eventHubId); + } } void InputReader::removeDeviceLocked(nsecs_t when, int32_t eventHubId) { @@ -639,6 +644,36 @@ std::vector InputReader::getVibratorIds(int32_t deviceId) { return {}; } +void InputReader::disableSensor(int32_t deviceId, InputDeviceSensorType sensorType) { + std::scoped_lock _l(mLock); + + InputDevice* device = findInputDeviceLocked(deviceId); + if (device) { + device->disableSensor(sensorType); + } +} + +bool InputReader::enableSensor(int32_t deviceId, InputDeviceSensorType sensorType, + std::chrono::microseconds samplingPeriod, + std::chrono::microseconds maxBatchReportLatency) { + std::scoped_lock _l(mLock); + + InputDevice* device = findInputDeviceLocked(deviceId); + if (device) { + return device->enableSensor(sensorType, samplingPeriod, maxBatchReportLatency); + } + return false; +} + +void InputReader::flushSensor(int32_t deviceId, InputDeviceSensorType sensorType) { + std::scoped_lock _l(mLock); + + InputDevice* device = findInputDeviceLocked(deviceId); + if (device) { + device->flushSensor(sensorType); + } +} + bool InputReader::isInputDeviceEnabled(int32_t deviceId) { std::scoped_lock _l(mLock); diff --git a/services/inputflinger/reader/include/EventHub.h b/services/inputflinger/reader/include/EventHub.h index 9e38d0a72a..2cea01776a 100644 --- a/services/inputflinger/reader/include/EventHub.h +++ b/services/inputflinger/reader/include/EventHub.h @@ -118,6 +118,9 @@ enum class InputDeviceClass : uint32_t { /* The input device has a rotary encoder */ ROTARY_ENCODER = 0x00001000, + /* The input device has a sensor like accelerometer, gyro, etc */ + SENSOR = 0x00002000, + /* The input device is virtual (not a real device, not part of UI configuration). */ VIRTUAL = 0x40000000, @@ -177,6 +180,8 @@ public: virtual bool hasInputProperty(int32_t deviceId, int property) const = 0; + virtual bool hasMscEvent(int32_t deviceId, int mscEvent) const = 0; + virtual status_t mapKey(int32_t deviceId, int32_t scanCode, int32_t usageCode, int32_t metaState, int32_t* outKeycode, int32_t* outMetaState, uint32_t* outFlags) const = 0; @@ -201,6 +206,8 @@ public: */ virtual size_t getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSize) = 0; virtual std::vector getVideoFrames(int32_t deviceId) = 0; + virtual base::Result> mapSensor(int32_t deviceId, + int32_t absCode) = 0; /* * Query current input state. @@ -346,6 +353,8 @@ public: bool hasInputProperty(int32_t deviceId, int property) const override final; + bool hasMscEvent(int32_t deviceId, int mscEvent) const override final; + status_t mapKey(int32_t deviceId, int32_t scanCode, int32_t usageCode, int32_t metaState, int32_t* outKeycode, int32_t* outMetaState, uint32_t* outFlags) const override final; @@ -353,6 +362,9 @@ public: status_t mapAxis(int32_t deviceId, int32_t scanCode, AxisInfo* outAxisInfo) const override final; + base::Result> mapSensor( + int32_t deviceId, int32_t absCode) override final; + void setExcludedDevices(const std::vector& devices) override final; int32_t getScanCodeState(int32_t deviceId, int32_t scanCode) const override final; @@ -420,6 +432,7 @@ private: BitArray ledBitmask; BitArray ffBitmask; BitArray propBitmask; + BitArray mscBitmask; std::string configurationFile; std::unique_ptr configuration; diff --git a/services/inputflinger/reader/include/InputDevice.h b/services/inputflinger/reader/include/InputDevice.h index 8b14b062cd..5af76b7a71 100644 --- a/services/inputflinger/reader/include/InputDevice.h +++ b/services/inputflinger/reader/include/InputDevice.h @@ -87,6 +87,10 @@ public: bool isVibrating(); std::vector getVibratorIds(); void cancelTouch(nsecs_t when); + bool enableSensor(InputDeviceSensorType sensorType, std::chrono::microseconds samplingPeriod, + std::chrono::microseconds maxBatchReportLatency); + void disableSensor(InputDeviceSensorType sensorType); + void flushSensor(InputDeviceSensorType sensorType); int32_t getMetaState(); void updateMetaState(int32_t keyCode); @@ -229,9 +233,12 @@ public: inline bool hasRelativeAxis(int32_t code) const { return mEventHub->hasRelativeAxis(mId, code); } - inline bool hasInputProperty(int property) const { + inline bool hasInputProperty(int32_t property) const { return mEventHub->hasInputProperty(mId, property); } + + inline bool hasMscEvent(int mscEvent) const { return mEventHub->hasMscEvent(mId, mscEvent); } + inline status_t mapKey(int32_t scanCode, int32_t usageCode, int32_t metaState, int32_t* outKeycode, int32_t* outMetaState, uint32_t* outFlags) const { return mEventHub->mapKey(mId, scanCode, usageCode, metaState, outKeycode, outMetaState, @@ -240,6 +247,10 @@ public: inline status_t mapAxis(int32_t scanCode, AxisInfo* outAxisInfo) const { return mEventHub->mapAxis(mId, scanCode, outAxisInfo); } + inline base::Result> mapSensor(int32_t absCode) { + return mEventHub->mapSensor(mId, absCode); + } + inline std::vector getVideoFrames() { return mEventHub->getVideoFrames(mId); } inline int32_t getScanCodeState(int32_t scanCode) const { return mEventHub->getScanCodeState(mId, scanCode); diff --git a/services/inputflinger/reader/include/InputReader.h b/services/inputflinger/reader/include/InputReader.h index b16b86caaa..48d4596383 100644 --- a/services/inputflinger/reader/include/InputReader.h +++ b/services/inputflinger/reader/include/InputReader.h @@ -87,6 +87,14 @@ public: bool canDispatchToDisplay(int32_t deviceId, int32_t displayId) override; + bool enableSensor(int32_t deviceId, InputDeviceSensorType sensorType, + std::chrono::microseconds samplingPeriod, + std::chrono::microseconds maxBatchReportLatency) override; + + void disableSensor(int32_t deviceId, InputDeviceSensorType sensorType) override; + + void flushSensor(int32_t deviceId, InputDeviceSensorType sensorType) override; + protected: // These members are protected so they can be instrumented by test cases. virtual std::shared_ptr createDeviceLocked(int32_t deviceId, diff --git a/services/inputflinger/reader/mapper/InputMapper.cpp b/services/inputflinger/reader/mapper/InputMapper.cpp index 913cef72bb..1ce54ae2dd 100644 --- a/services/inputflinger/reader/mapper/InputMapper.cpp +++ b/services/inputflinger/reader/mapper/InputMapper.cpp @@ -70,6 +70,16 @@ std::vector InputMapper::getVibratorIds() { void InputMapper::cancelTouch(nsecs_t when) {} +bool InputMapper::enableSensor(InputDeviceSensorType sensorType, + std::chrono::microseconds samplingPeriod, + std::chrono::microseconds maxBatchReportLatency) { + return true; +} + +void InputMapper::disableSensor(InputDeviceSensorType sensorType) {} + +void InputMapper::flushSensor(InputDeviceSensorType sensorType) {} + int32_t InputMapper::getMetaState() { return 0; } diff --git a/services/inputflinger/reader/mapper/InputMapper.h b/services/inputflinger/reader/mapper/InputMapper.h index 088dbd8615..bd64d8d0a8 100644 --- a/services/inputflinger/reader/mapper/InputMapper.h +++ b/services/inputflinger/reader/mapper/InputMapper.h @@ -68,6 +68,11 @@ public: virtual bool isVibrating(); virtual std::vector getVibratorIds(); virtual void cancelTouch(nsecs_t when); + virtual bool enableSensor(InputDeviceSensorType sensorType, + std::chrono::microseconds samplingPeriod, + std::chrono::microseconds maxBatchReportLatency); + virtual void disableSensor(InputDeviceSensorType sensorType); + virtual void flushSensor(InputDeviceSensorType sensorType); virtual int32_t getMetaState(); virtual void updateMetaState(int32_t keyCode); diff --git a/services/inputflinger/reader/mapper/SensorInputMapper.cpp b/services/inputflinger/reader/mapper/SensorInputMapper.cpp new file mode 100644 index 0000000000..7d97014f55 --- /dev/null +++ b/services/inputflinger/reader/mapper/SensorInputMapper.cpp @@ -0,0 +1,421 @@ +/* + * Copyright (C) 2020 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 + +#include "../Macros.h" + +#include "SensorInputMapper.h" + +// Log detailed debug messages about each sensor event notification to the dispatcher. +constexpr bool DEBUG_SENSOR_EVENT_DETAILS = false; + +namespace android { + +// Mask for the LSB 2nd, 3rd and fourth bits. +constexpr int REPORTING_MODE_MASK = 0xE; +constexpr int REPORTING_MODE_SHIFT = 1; +constexpr float GRAVITY_MS2_UNIT = 9.80665f; +constexpr float DEGREE_RADIAN_UNIT = 0.0174533f; + +/* Convert the sensor data from Linux to Android + * Linux accelerometer unit is per g, Android unit is m/s^2 + * Linux gyroscope unit is degree/second, Android unit is radians/second + */ +static void convertFromLinuxToAndroid(std::vector& values, + InputDeviceSensorType sensorType) { + for (size_t i = 0; i < values.size(); i++) { + switch (sensorType) { + case InputDeviceSensorType::ACCELEROMETER: + values[i] *= GRAVITY_MS2_UNIT; + break; + case InputDeviceSensorType::GYROSCOPE: + values[i] *= DEGREE_RADIAN_UNIT; + break; + default: + break; + } + } +} + +SensorInputMapper::SensorInputMapper(InputDeviceContext& deviceContext) + : InputMapper(deviceContext) {} + +SensorInputMapper::~SensorInputMapper() {} + +uint32_t SensorInputMapper::getSources() { + return AINPUT_SOURCE_SENSOR; +} + +template +bool SensorInputMapper::tryGetProperty(std::string keyName, T& outValue) { + const auto& config = getDeviceContext().getConfiguration(); + return config.tryGetProperty(String8(keyName.c_str()), outValue); +} + +void SensorInputMapper::parseSensorConfiguration(InputDeviceSensorType sensorType, int32_t absCode, + int32_t sensorDataIndex, const Axis& axis) { + auto it = mSensors.find(sensorType); + if (it == mSensors.end()) { + Sensor sensor = createSensor(sensorType, axis); + sensor.dataVec[sensorDataIndex] = absCode; + mSensors.emplace(sensorType, sensor); + } else { + it->second.dataVec[sensorDataIndex] = absCode; + } +} + +void SensorInputMapper::populateDeviceInfo(InputDeviceInfo* info) { + InputMapper::populateDeviceInfo(info); + + for (const auto& [sensorType, sensor] : mSensors) { + info->addSensorInfo(sensor.sensorInfo); + info->setHasSensor(true); + } +} + +void SensorInputMapper::dump(std::string& dump) { + dump += INDENT2 "Sensor Input Mapper:\n"; + dump += StringPrintf(INDENT3 " isDeviceEnabled %d\n", getDeviceContext().isDeviceEnabled()); + dump += StringPrintf(INDENT3 " mHasHardwareTimestamp %d\n", mHasHardwareTimestamp); + dump += INDENT3 "Sensors:\n"; + for (const auto& [sensorType, sensor] : mSensors) { + dump += StringPrintf(INDENT4 "%s\n", NamedEnum::string(sensorType).c_str()); + dump += StringPrintf(INDENT5 "enabled: %d\n", sensor.enabled); + dump += StringPrintf(INDENT5 "samplingPeriod: %lld\n", sensor.samplingPeriod.count()); + dump += StringPrintf(INDENT5 "maxBatchReportLatency: %lld\n", + sensor.maxBatchReportLatency.count()); + dump += StringPrintf(INDENT5 "maxRange: %f\n", sensor.sensorInfo.maxRange); + dump += StringPrintf(INDENT5 "power: %f\n", sensor.sensorInfo.power); + for (ssize_t i = 0; i < SENSOR_VEC_LEN; i++) { + int32_t rawAxis = sensor.dataVec[i]; + dump += StringPrintf(INDENT5 "[%zd]: rawAxis: %d \n", i, rawAxis); + const auto it = mAxes.find(rawAxis); + if (it != mAxes.end()) { + const Axis& axis = it->second; + dump += StringPrintf(INDENT5 " min=%0.5f, max=%0.5f, flat=%0.5f, fuzz=%0.5f," + "resolution=%0.5f\n", + axis.min, axis.max, axis.flat, axis.fuzz, axis.resolution); + dump += StringPrintf(INDENT5 " scale=%0.5f, offset=%0.5f\n", axis.scale, + axis.offset); + dump += StringPrintf(INDENT5 " rawMin=%d, rawMax=%d, " + "rawFlat=%d, rawFuzz=%d, rawResolution=%d\n", + axis.rawAxisInfo.minValue, axis.rawAxisInfo.maxValue, + axis.rawAxisInfo.flat, axis.rawAxisInfo.fuzz, + axis.rawAxisInfo.resolution); + } + } + } +} + +void SensorInputMapper::configure(nsecs_t when, const InputReaderConfiguration* config, + uint32_t changes) { + InputMapper::configure(when, config, changes); + + if (!changes) { // first time only + mDeviceEnabled = true; + // Check if device has MSC_TIMESTAMP event. + mHasHardwareTimestamp = getDeviceContext().hasMscEvent(MSC_TIMESTAMP); + // Collect all axes. + for (int32_t abs = ABS_X; abs <= ABS_MAX; abs++) { + // axis must be claimed by sensor class device + if (!(getAbsAxisUsage(abs, getDeviceContext().getDeviceClasses()) + .test(InputDeviceClass::SENSOR))) { + continue; + } + RawAbsoluteAxisInfo rawAxisInfo; + getAbsoluteAxisInfo(abs, &rawAxisInfo); + if (rawAxisInfo.valid) { + AxisInfo axisInfo; + // Axis doesn't need to be mapped, as sensor mapper doesn't generate any motion + // input events + axisInfo.mode = AxisInfo::MODE_NORMAL; + axisInfo.axis = -1; + // Check key layout map for sensor data mapping to axes + auto ret = getDeviceContext().mapSensor(abs); + if (ret) { + InputDeviceSensorType sensorType = (*ret).first; + int32_t sensorDataIndex = (*ret).second; + const Axis& axis = createAxis(axisInfo, rawAxisInfo); + parseSensorConfiguration(sensorType, abs, sensorDataIndex, axis); + + mAxes.insert({abs, axis}); + } + } + } + } +} + +SensorInputMapper::Axis SensorInputMapper::createAxis(const AxisInfo& axisInfo, + const RawAbsoluteAxisInfo& rawAxisInfo) { + // Apply flat override. + int32_t rawFlat = axisInfo.flatOverride < 0 ? rawAxisInfo.flat : axisInfo.flatOverride; + + float scale = std::numeric_limits::signaling_NaN(); + float offset = 0; + + // resolution is 1 of sensor's unit. For accelerometer, it is G, for gyroscope, + // it is degree/s. + scale = 1.0f / rawAxisInfo.resolution; + offset = avg(rawAxisInfo.minValue, rawAxisInfo.maxValue) * -scale; + + const float max = rawAxisInfo.maxValue / rawAxisInfo.resolution; + const float min = rawAxisInfo.minValue / rawAxisInfo.resolution; + const float flat = rawFlat * scale; + const float fuzz = rawAxisInfo.fuzz * scale; + const float resolution = rawAxisInfo.resolution; + + // To eliminate noise while the Sensor is at rest, filter out small variations + // in axis values up front. + const float filter = fuzz ? fuzz : flat * 0.25f; + return Axis(rawAxisInfo, axisInfo, scale, offset, min, max, flat, fuzz, resolution, filter); +} + +void SensorInputMapper::reset(nsecs_t when) { + // Recenter all axes. + for (std::pair& pair : mAxes) { + Axis& axis = pair.second; + axis.resetValue(); + } + mHardwareTimestamp = 0; + mPrevMscTime = 0; + InputMapper::reset(when); +} + +SensorInputMapper::Sensor SensorInputMapper::createSensor(InputDeviceSensorType sensorType, + const Axis& axis) { + InputDeviceIdentifier identifier = getDeviceContext().getDeviceIdentifier(); + // Sensor Id will be assigned to device Id to distinguish same sensor from multiple input + // devices, in such a way that the sensor Id will be same as input device Id. + // The sensorType is to distinguish different sensors within one device. + // One input device can only have 1 sensor for each sensor Type. + InputDeviceSensorInfo sensorInfo(identifier.name, std::to_string(identifier.vendor), + identifier.version, sensorType, + InputDeviceSensorAccuracy::ACCURACY_HIGH, + axis.max /* maxRange */, axis.scale /* resolution */, + 0.0f /* power */, 0 /* minDelay */, + 0 /* fifoReservedEventCount */, 0 /* fifoMaxEventCount */, + NamedEnum::string(sensorType), 0 /* maxDelay */, 0 /* flags */, + getDeviceId()); + + std::string prefix = "sensor." + NamedEnum::string(sensorType); + transform(prefix.begin(), prefix.end(), prefix.begin(), ::tolower); + + int32_t reportingMode = 0; + if (!tryGetProperty(prefix + ".reportingMode", reportingMode)) { + sensorInfo.flags |= (reportingMode & REPORTING_MODE_MASK) << REPORTING_MODE_SHIFT; + } + + tryGetProperty(prefix + ".maxDelay", sensorInfo.maxDelay); + + tryGetProperty(prefix + ".minDelay", sensorInfo.minDelay); + + tryGetProperty(prefix + ".power", sensorInfo.power); + + tryGetProperty(prefix + ".fifoReservedEventCount", sensorInfo.fifoReservedEventCount); + + tryGetProperty(prefix + ".fifoMaxEventCount", sensorInfo.fifoMaxEventCount); + + return Sensor(sensorInfo); +} + +void SensorInputMapper::processHardWareTimestamp(nsecs_t evTime, int32_t mscTime) { + // Since MSC_TIMESTAMP initial state is different from the system time, we + // calculate the difference between two MSC_TIMESTAMP events, and use that + // to calculate the system time that should be tagged on the event. + // if the first time MSC_TIMESTAMP, store it + // else calculate difference between previous and current MSC_TIMESTAMP + if (mPrevMscTime == 0) { + mHardwareTimestamp = evTime; + if (DEBUG_SENSOR_EVENT_DETAILS) { + ALOGD("Initialize hardware timestamp = %" PRId64, mHardwareTimestamp); + } + } else { + // Calculate the difference between current msc_timestamp and + // previous msc_timestamp, including when msc_timestamp wraps around. + uint32_t timeDiff = (mPrevMscTime > static_cast(mscTime)) + ? (UINT32_MAX - mPrevMscTime + static_cast(mscTime + 1)) + : (static_cast(mscTime) - mPrevMscTime); + + mHardwareTimestamp += timeDiff * 1000LL; + } + mPrevMscTime = static_cast(mscTime); +} + +void SensorInputMapper::process(const RawEvent* rawEvent) { + switch (rawEvent->type) { + case EV_ABS: { + auto it = mAxes.find(rawEvent->code); + if (it != mAxes.end()) { + Axis& axis = it->second; + axis.newValue = rawEvent->value * axis.scale + axis.offset; + } + break; + } + + case EV_SYN: + switch (rawEvent->code) { + case SYN_REPORT: + for (std::pair& pair : mAxes) { + Axis& axis = pair.second; + axis.currentValue = axis.newValue; + } + sync(rawEvent->when, false /*force*/); + break; + } + break; + + case EV_MSC: + switch (rawEvent->code) { + case MSC_TIMESTAMP: + // hardware timestamp is nano seconds + processHardWareTimestamp(rawEvent->when, rawEvent->value); + break; + } + } +} + +bool SensorInputMapper::setSensorEnabled(InputDeviceSensorType sensorType, bool enabled) { + auto it = mSensors.find(sensorType); + if (it == mSensors.end()) { + return false; + } + + it->second.enabled = enabled; + if (!enabled) { + it->second.resetValue(); + } + + /* Currently we can't enable/disable sensors individually. Enabling any sensor will enable + * the device + */ + mDeviceEnabled = false; + for (const auto& [sensorType, sensor] : mSensors) { + // If any sensor is on we will turn on the device. + if (sensor.enabled) { + mDeviceEnabled = true; + break; + } + } + return true; +} + +void SensorInputMapper::flushSensor(InputDeviceSensorType sensorType) { + auto it = mSensors.find(sensorType); + if (it == mSensors.end()) { + return; + } + auto& sensor = it->second; + sensor.lastSampleTimeNs = 0; + for (size_t i = 0; i < SENSOR_VEC_LEN; i++) { + int32_t abs = sensor.dataVec[i]; + auto itAxis = mAxes.find(abs); + if (itAxis != mAxes.end()) { + Axis& axis = itAxis->second; + axis.resetValue(); + } + } +} + +bool SensorInputMapper::enableSensor(InputDeviceSensorType sensorType, + std::chrono::microseconds samplingPeriod, + std::chrono::microseconds maxBatchReportLatency) { + if (DEBUG_SENSOR_EVENT_DETAILS) { + ALOGD("Enable Sensor %s samplingPeriod %lld maxBatchReportLatency %lld", + NamedEnum::string(sensorType).c_str(), samplingPeriod.count(), + maxBatchReportLatency.count()); + } + + if (!setSensorEnabled(sensorType, true /* enabled */)) { + return false; + } + + // Enable device + if (mDeviceEnabled) { + getDeviceContext().enableDevice(); + } + + // We know the sensor exists now, update the sampling period and batch report latency. + auto it = mSensors.find(sensorType); + it->second.samplingPeriod = + std::chrono::duration_cast(samplingPeriod); + it->second.maxBatchReportLatency = + std::chrono::duration_cast(maxBatchReportLatency); + return true; +} + +void SensorInputMapper::disableSensor(InputDeviceSensorType sensorType) { + if (DEBUG_SENSOR_EVENT_DETAILS) { + ALOGD("Disable Sensor %s", NamedEnum::string(sensorType).c_str()); + } + + if (!setSensorEnabled(sensorType, false /* enabled */)) { + return; + } + + // Disable device + if (!mDeviceEnabled) { + mHardwareTimestamp = 0; + mPrevMscTime = 0; + getDeviceContext().disableDevice(); + } +} + +void SensorInputMapper::sync(nsecs_t when, bool force) { + for (auto& [sensorType, sensor] : mSensors) { + // Skip if sensor not enabled + if (!sensor.enabled) { + continue; + } + std::vector values; + for (ssize_t i = 0; i < SENSOR_VEC_LEN; i++) { + int32_t abs = sensor.dataVec[i]; + auto it = mAxes.find(abs); + if (it != mAxes.end()) { + const Axis& axis = it->second; + values.push_back(axis.currentValue); + } + } + + nsecs_t timestamp = mHasHardwareTimestamp ? mHardwareTimestamp : when; + if (DEBUG_SENSOR_EVENT_DETAILS) { + ALOGD("Sensor %s timestamp %" PRIu64 " values [%f %f %f]", + NamedEnum::string(sensorType).c_str(), timestamp, values[0], values[1], + values[2]); + } + if (sensor.lastSampleTimeNs.has_value() && + timestamp - sensor.lastSampleTimeNs.value() < sensor.samplingPeriod.count()) { + if (DEBUG_SENSOR_EVENT_DETAILS) { + ALOGD("Sensor %s Skip a sample.", NamedEnum::string(sensorType).c_str()); + } + } else { + // Convert to Android unit + convertFromLinuxToAndroid(values, sensorType); + // Notify dispatcher for sensor event + NotifySensorArgs args(getContext()->getNextId(), when, getDeviceId(), + AINPUT_SOURCE_SENSOR, sensorType, sensor.sensorInfo.accuracy, + sensor.accuracy != + sensor.sensorInfo.accuracy /* accuracyChanged */, + timestamp /* hwTimestamp */, values); + + getListener()->notifySensor(&args); + sensor.lastSampleTimeNs = timestamp; + sensor.accuracy = sensor.sensorInfo.accuracy; + } + } +} + +} // namespace android diff --git a/services/inputflinger/reader/mapper/SensorInputMapper.h b/services/inputflinger/reader/mapper/SensorInputMapper.h new file mode 100644 index 0000000000..337100216e --- /dev/null +++ b/services/inputflinger/reader/mapper/SensorInputMapper.h @@ -0,0 +1,138 @@ +/* + * Copyright (C) 2020 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 _UI_INPUTREADER_SENSOR_INPUT_MAPPER_H +#define _UI_INPUTREADER_SENSOR_INPUT_MAPPER_H + +#include "InputMapper.h" + +namespace android { +// sensor data vector length +static constexpr ssize_t SENSOR_VEC_LEN = 3; + +class SensorInputMapper : public InputMapper { +public: + explicit SensorInputMapper(InputDeviceContext& deviceContext); + ~SensorInputMapper() override; + + uint32_t getSources() override; + void populateDeviceInfo(InputDeviceInfo* deviceInfo) override; + void dump(std::string& dump) override; + void configure(nsecs_t when, const InputReaderConfiguration* config, uint32_t changes) override; + void reset(nsecs_t when) override; + void process(const RawEvent* rawEvent) override; + bool enableSensor(InputDeviceSensorType sensorType, std::chrono::microseconds samplingPeriod, + std::chrono::microseconds maxBatchReportLatency) override; + void disableSensor(InputDeviceSensorType sensorType) override; + void flushSensor(InputDeviceSensorType sensorType) override; + +private: + struct Axis { + explicit Axis(const RawAbsoluteAxisInfo& rawAxisInfo, const AxisInfo& axisInfo, float scale, + float offset, float min, float max, float flat, float fuzz, float resolution, + float filter) + : rawAxisInfo(rawAxisInfo), + axisInfo(axisInfo), + scale(scale), + offset(offset), + min(min), + max(max), + flat(flat), + fuzz(fuzz), + resolution(resolution), + filter(filter) { + resetValue(); + } + + RawAbsoluteAxisInfo rawAxisInfo; + AxisInfo axisInfo; + + float scale; // scale factor from raw to normalized values + float offset; // offset to add after scaling for normalization + + float min; // normalized inclusive minimum + float max; // normalized inclusive maximum + float flat; // normalized flat region size + float fuzz; // normalized error tolerance + float resolution; // normalized resolution in units + + float filter; // filter out small variations of this size + float currentValue; // current value + float newValue; // most recent value + + void resetValue() { + this->currentValue = 0; + this->newValue = 0; + } + }; + + struct Sensor { + explicit Sensor(const InputDeviceSensorInfo& sensorInfo) : sensorInfo(sensorInfo) { + resetValue(); + } + bool enabled; + InputDeviceSensorAccuracy accuracy; + std::chrono::nanoseconds samplingPeriod; + std::chrono::nanoseconds maxBatchReportLatency; + // last sample time in nano seconds + std::optional lastSampleTimeNs; + InputDeviceSensorInfo sensorInfo; + // Sensor X, Y, Z data mapping to abs + std::array dataVec; + void resetValue() { + this->enabled = false; + this->accuracy = InputDeviceSensorAccuracy::ACCURACY_NONE; + this->samplingPeriod = std::chrono::nanoseconds(0); + this->maxBatchReportLatency = std::chrono::nanoseconds(0); + this->lastSampleTimeNs = std::nullopt; + this->dataVec.fill(0); + } + }; + + static Axis createAxis(const AxisInfo& AxisInfo, const RawAbsoluteAxisInfo& rawAxisInfo); + + // Axes indexed by raw ABS_* axis index. + std::unordered_map mAxes; + + // hardware timestamp from MSC_TIMESTAMP + nsecs_t mHardwareTimestamp; + uint32_t mPrevMscTime; + + bool mDeviceEnabled; + // Does device support MSC_TIMESTAMP + bool mHasHardwareTimestamp; + + // Sensor list + std::unordered_map mSensors; + + void sync(nsecs_t when, bool force); + + template + bool tryGetProperty(std::string keyName, T& outValue); + + void parseSensorConfiguration(InputDeviceSensorType sensorType, int32_t absCode, + int32_t sensorDataIndex, const Axis& axis); + + void processHardWareTimestamp(nsecs_t evTime, int32_t evValue); + + Sensor createSensor(InputDeviceSensorType sensorType, const Axis& axis); + + bool setSensorEnabled(InputDeviceSensorType sensorType, bool enabled); +}; + +} // namespace android + +#endif // _UI_INPUTREADER_SENSOR_INPUT_MAPPER_H \ No newline at end of file diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp index 76328148c2..c819091ae0 100644 --- a/services/inputflinger/tests/InputDispatcher_test.cpp +++ b/services/inputflinger/tests/InputDispatcher_test.cpp @@ -284,6 +284,12 @@ private: void notifyFocusChanged(const sp&, const sp&) override {} void notifyUntrustedTouch(const std::string& obscuringPackage) override {} + void notifySensorEvent(int32_t deviceId, InputDeviceSensorType sensorType, + InputDeviceSensorAccuracy accuracy, nsecs_t timestamp, + const std::vector& values) override {} + + void notifySensorAccuracy(int deviceId, InputDeviceSensorType sensorType, + InputDeviceSensorAccuracy accuracy) override {} void getDispatcherConfiguration(InputDispatcherConfiguration* outConfig) override { *outConfig = mConfig; diff --git a/services/inputflinger/tests/InputReader_test.cpp b/services/inputflinger/tests/InputReader_test.cpp index c26a389342..23f30260bc 100644 --- a/services/inputflinger/tests/InputReader_test.cpp +++ b/services/inputflinger/tests/InputReader_test.cpp @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -364,6 +365,11 @@ class FakeEventHub : public EventHubInterface { uint32_t flags; }; + struct SensorInfo { + InputDeviceSensorType sensorType; + int32_t sensorDataIndex; + }; + struct Device { InputDeviceIdentifier identifier; Flags classes; @@ -377,6 +383,8 @@ class FakeEventHub : public EventHubInterface { KeyedVector keysByScanCode; KeyedVector keysByUsageCode; KeyedVector leds; + std::unordered_map sensorsByAbsCode; + BitArray mscBitmask; std::vector virtualKeys; bool enabled; @@ -535,6 +543,22 @@ public: device->leds.add(led, initialState); } + void addSensorAxis(int32_t deviceId, int32_t absCode, InputDeviceSensorType sensorType, + int32_t sensorDataIndex) { + Device* device = getDevice(deviceId); + SensorInfo info; + info.sensorType = sensorType; + info.sensorDataIndex = sensorDataIndex; + device->sensorsByAbsCode.emplace(absCode, info); + } + + void setMscEvent(int32_t deviceId, int32_t mscEvent) { + Device* device = getDevice(deviceId); + typename BitArray::Buffer buffer; + buffer[mscEvent / 32] = 1 << mscEvent % 32; + device->mscBitmask.loadFromBuffer(buffer); + } + bool getLedState(int32_t deviceId, int32_t led) { Device* device = getDevice(deviceId); return device->leds.valueFor(led); @@ -630,6 +654,14 @@ private: bool hasInputProperty(int32_t, int) const override { return false; } + bool hasMscEvent(int32_t deviceId, int mscEvent) const override final { + Device* device = getDevice(deviceId); + if (device) { + return mscEvent >= 0 && mscEvent <= MSC_MAX ? device->mscBitmask.test(mscEvent) : false; + } + return false; + } + status_t mapKey(int32_t deviceId, int32_t scanCode, int32_t usageCode, int32_t metaState, int32_t* outKeycode, int32_t* outMetaState, uint32_t* outFlags) const override { Device* device = getDevice(deviceId); @@ -669,6 +701,20 @@ private: status_t mapAxis(int32_t, int32_t, AxisInfo*) const override { return NAME_NOT_FOUND; } + base::Result> mapSensor(int32_t deviceId, + int32_t absCode) { + Device* device = getDevice(deviceId); + if (!device) { + return Errorf("Sensor device not found."); + } + auto it = device->sensorsByAbsCode.find(absCode); + if (it == device->sensorsByAbsCode.end()) { + return Errorf("Sensor map not found."); + } + const SensorInfo& info = it->second; + return std::make_pair(info.sensorType, info.sensorDataIndex); + } + void setExcludedDevices(const std::vector& devices) override { mExcludedDevices = devices; } @@ -2574,6 +2620,157 @@ TEST_F(VibratorInputMapperTest, Vibrate) { ASSERT_TRUE(mapper.isVibrating()); } +// --- SensorInputMapperTest --- + +class SensorInputMapperTest : public InputMapperTest { +protected: + static const int32_t ACCEL_RAW_MIN; + static const int32_t ACCEL_RAW_MAX; + static const int32_t ACCEL_RAW_FUZZ; + static const int32_t ACCEL_RAW_FLAT; + static const int32_t ACCEL_RAW_RESOLUTION; + + static const int32_t GYRO_RAW_MIN; + static const int32_t GYRO_RAW_MAX; + static const int32_t GYRO_RAW_FUZZ; + static const int32_t GYRO_RAW_FLAT; + static const int32_t GYRO_RAW_RESOLUTION; + + static const float GRAVITY_MS2_UNIT; + static const float DEGREE_RADIAN_UNIT; + + void prepareAccelAxes(); + void prepareGyroAxes(); + void setAccelProperties(); + void setGyroProperties(); + void SetUp() override { InputMapperTest::SetUp(DEVICE_CLASSES | InputDeviceClass::SENSOR); } +}; + +const int32_t SensorInputMapperTest::ACCEL_RAW_MIN = -32768; +const int32_t SensorInputMapperTest::ACCEL_RAW_MAX = 32768; +const int32_t SensorInputMapperTest::ACCEL_RAW_FUZZ = 16; +const int32_t SensorInputMapperTest::ACCEL_RAW_FLAT = 0; +const int32_t SensorInputMapperTest::ACCEL_RAW_RESOLUTION = 8192; + +const int32_t SensorInputMapperTest::GYRO_RAW_MIN = -2097152; +const int32_t SensorInputMapperTest::GYRO_RAW_MAX = 2097152; +const int32_t SensorInputMapperTest::GYRO_RAW_FUZZ = 16; +const int32_t SensorInputMapperTest::GYRO_RAW_FLAT = 0; +const int32_t SensorInputMapperTest::GYRO_RAW_RESOLUTION = 1024; + +const float SensorInputMapperTest::GRAVITY_MS2_UNIT = 9.80665f; +const float SensorInputMapperTest::DEGREE_RADIAN_UNIT = 0.0174533f; + +void SensorInputMapperTest::prepareAccelAxes() { + mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_X, ACCEL_RAW_MIN, ACCEL_RAW_MAX, ACCEL_RAW_FUZZ, + ACCEL_RAW_FLAT, ACCEL_RAW_RESOLUTION); + mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_Y, ACCEL_RAW_MIN, ACCEL_RAW_MAX, ACCEL_RAW_FUZZ, + ACCEL_RAW_FLAT, ACCEL_RAW_RESOLUTION); + mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_Z, ACCEL_RAW_MIN, ACCEL_RAW_MAX, ACCEL_RAW_FUZZ, + ACCEL_RAW_FLAT, ACCEL_RAW_RESOLUTION); +} + +void SensorInputMapperTest::prepareGyroAxes() { + mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_RX, GYRO_RAW_MIN, GYRO_RAW_MAX, GYRO_RAW_FUZZ, + GYRO_RAW_FLAT, GYRO_RAW_RESOLUTION); + mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_RY, GYRO_RAW_MIN, GYRO_RAW_MAX, GYRO_RAW_FUZZ, + GYRO_RAW_FLAT, GYRO_RAW_RESOLUTION); + mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_RZ, GYRO_RAW_MIN, GYRO_RAW_MAX, GYRO_RAW_FUZZ, + GYRO_RAW_FLAT, GYRO_RAW_RESOLUTION); +} + +void SensorInputMapperTest::setAccelProperties() { + mFakeEventHub->addSensorAxis(EVENTHUB_ID, /* absCode */ 0, InputDeviceSensorType::ACCELEROMETER, + /* sensorDataIndex */ 0); + mFakeEventHub->addSensorAxis(EVENTHUB_ID, /* absCode */ 1, InputDeviceSensorType::ACCELEROMETER, + /* sensorDataIndex */ 1); + mFakeEventHub->addSensorAxis(EVENTHUB_ID, /* absCode */ 2, InputDeviceSensorType::ACCELEROMETER, + /* sensorDataIndex */ 2); + mFakeEventHub->setMscEvent(EVENTHUB_ID, MSC_TIMESTAMP); + addConfigurationProperty("sensor.accelerometer.reportingMode", "0"); + addConfigurationProperty("sensor.accelerometer.maxDelay", "100000"); + addConfigurationProperty("sensor.accelerometer.minDelay", "5000"); + addConfigurationProperty("sensor.accelerometer.power", "1.5"); +} + +void SensorInputMapperTest::setGyroProperties() { + mFakeEventHub->addSensorAxis(EVENTHUB_ID, /* absCode */ 3, InputDeviceSensorType::GYROSCOPE, + /* sensorDataIndex */ 0); + mFakeEventHub->addSensorAxis(EVENTHUB_ID, /* absCode */ 4, InputDeviceSensorType::GYROSCOPE, + /* sensorDataIndex */ 1); + mFakeEventHub->addSensorAxis(EVENTHUB_ID, /* absCode */ 5, InputDeviceSensorType::GYROSCOPE, + /* sensorDataIndex */ 2); + mFakeEventHub->setMscEvent(EVENTHUB_ID, MSC_TIMESTAMP); + addConfigurationProperty("sensor.gyroscope.reportingMode", "0"); + addConfigurationProperty("sensor.gyroscope.maxDelay", "100000"); + addConfigurationProperty("sensor.gyroscope.minDelay", "5000"); + addConfigurationProperty("sensor.gyroscope.power", "0.8"); +} + +TEST_F(SensorInputMapperTest, GetSources) { + SensorInputMapper& mapper = addMapperAndConfigure(); + + ASSERT_EQ(static_cast(AINPUT_SOURCE_SENSOR), mapper.getSources()); +} + +TEST_F(SensorInputMapperTest, ProcessAccelerometerSensor) { + setAccelProperties(); + prepareAccelAxes(); + SensorInputMapper& mapper = addMapperAndConfigure(); + + ASSERT_TRUE(mapper.enableSensor(InputDeviceSensorType::ACCELEROMETER, + std::chrono::microseconds(10000), + std::chrono::microseconds(0))); + process(mapper, ARBITRARY_TIME, EV_ABS, ABS_X, 20000); + process(mapper, ARBITRARY_TIME, EV_ABS, ABS_Y, -20000); + process(mapper, ARBITRARY_TIME, EV_ABS, ABS_Z, 40000); + process(mapper, ARBITRARY_TIME, EV_MSC, MSC_TIMESTAMP, 1000); + process(mapper, ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0); + + NotifySensorArgs args; + std::vector values = {20000.0f / ACCEL_RAW_RESOLUTION * GRAVITY_MS2_UNIT, + -20000.0f / ACCEL_RAW_RESOLUTION * GRAVITY_MS2_UNIT, + 40000.0f / ACCEL_RAW_RESOLUTION * GRAVITY_MS2_UNIT}; + + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifySensorWasCalled(&args)); + ASSERT_EQ(args.source, AINPUT_SOURCE_SENSOR); + ASSERT_EQ(args.deviceId, DEVICE_ID); + ASSERT_EQ(args.sensorType, InputDeviceSensorType::ACCELEROMETER); + ASSERT_EQ(args.accuracy, InputDeviceSensorAccuracy::ACCURACY_HIGH); + ASSERT_EQ(args.hwTimestamp, ARBITRARY_TIME); + ASSERT_EQ(args.values, values); + mapper.flushSensor(InputDeviceSensorType::ACCELEROMETER); +} + +TEST_F(SensorInputMapperTest, ProcessGyroscopeSensor) { + setGyroProperties(); + prepareGyroAxes(); + SensorInputMapper& mapper = addMapperAndConfigure(); + + ASSERT_TRUE(mapper.enableSensor(InputDeviceSensorType::GYROSCOPE, + std::chrono::microseconds(10000), + std::chrono::microseconds(0))); + process(mapper, ARBITRARY_TIME, EV_ABS, ABS_RX, 20000); + process(mapper, ARBITRARY_TIME, EV_ABS, ABS_RY, -20000); + process(mapper, ARBITRARY_TIME, EV_ABS, ABS_RZ, 40000); + process(mapper, ARBITRARY_TIME, EV_MSC, MSC_TIMESTAMP, 1000); + process(mapper, ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0); + + NotifySensorArgs args; + std::vector values = {20000.0f / GYRO_RAW_RESOLUTION * DEGREE_RADIAN_UNIT, + -20000.0f / GYRO_RAW_RESOLUTION * DEGREE_RADIAN_UNIT, + 40000.0f / GYRO_RAW_RESOLUTION * DEGREE_RADIAN_UNIT}; + + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifySensorWasCalled(&args)); + ASSERT_EQ(args.source, AINPUT_SOURCE_SENSOR); + ASSERT_EQ(args.deviceId, DEVICE_ID); + ASSERT_EQ(args.sensorType, InputDeviceSensorType::GYROSCOPE); + ASSERT_EQ(args.accuracy, InputDeviceSensorAccuracy::ACCURACY_HIGH); + ASSERT_EQ(args.hwTimestamp, ARBITRARY_TIME); + ASSERT_EQ(args.values, values); + mapper.flushSensor(InputDeviceSensorType::GYROSCOPE); +} + // --- KeyboardInputMapperTest --- class KeyboardInputMapperTest : public InputMapperTest { diff --git a/services/inputflinger/tests/TestInputListener.cpp b/services/inputflinger/tests/TestInputListener.cpp index 1050ab8601..295c6e3057 100644 --- a/services/inputflinger/tests/TestInputListener.cpp +++ b/services/inputflinger/tests/TestInputListener.cpp @@ -80,6 +80,12 @@ void TestInputListener::assertNotifySwitchWasCalled(NotifySwitchArgs* outEventAr "Expected notifySwitch() to have been called.")); } +void TestInputListener::assertNotifySensorWasCalled(NotifySensorArgs* outEventArgs) { + ASSERT_NO_FATAL_FAILURE( + assertCalled(outEventArgs, + "Expected notifySensor() to have been called.")); +} + void TestInputListener::assertNotifyCaptureWasCalled( NotifyPointerCaptureChangedArgs* outEventArgs) { ASSERT_NO_FATAL_FAILURE( @@ -155,4 +161,8 @@ void TestInputListener::notifyPointerCaptureChanged(const NotifyPointerCaptureCh notify(args); } +void TestInputListener::notifySensor(const NotifySensorArgs* args) { + notify(args); +} + } // namespace android diff --git a/services/inputflinger/tests/TestInputListener.h b/services/inputflinger/tests/TestInputListener.h index 887d4eadb1..e54350a4c8 100644 --- a/services/inputflinger/tests/TestInputListener.h +++ b/services/inputflinger/tests/TestInputListener.h @@ -55,6 +55,7 @@ public: void assertNotifySwitchWasCalled(NotifySwitchArgs* outEventArgs = nullptr); void assertNotifyCaptureWasCalled(NotifyPointerCaptureChangedArgs* outEventArgs = nullptr); + void assertNotifySensorWasCalled(NotifySensorArgs* outEventArgs = nullptr); private: template @@ -76,6 +77,8 @@ private: virtual void notifySwitch(const NotifySwitchArgs* args) override; + virtual void notifySensor(const NotifySensorArgs* args) override; + virtual void notifyPointerCaptureChanged(const NotifyPointerCaptureChangedArgs* args) override; std::mutex mLock; @@ -88,6 +91,7 @@ private: std::vector, // std::vector, // std::vector, // + std::vector, // std::vector> // mQueues GUARDED_BY(mLock); }; -- cgit v1.2.3-59-g8ed1b From 9c27af55a9894911968eaf182f7888e80b9637a0 Mon Sep 17 00:00:00 2001 From: Bernie Innocenti Date: Mon, 21 Dec 2020 12:50:14 +0900 Subject: Add explicit Result::ok() checks where needed Test: m checkbuild continuous_instrumentation_tests continuous_instrumentation_tests_api_coverage continuous_native_tests device-tests platform_tests Exempt-From-Owner-Approval: mechanical mass refactoring Change-Id: I698a6843686810527d753d075f543f1d6e1eb1f4 --- libs/input/KeyCharacterMap.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'libs/input/KeyCharacterMap.cpp') diff --git a/libs/input/KeyCharacterMap.cpp b/libs/input/KeyCharacterMap.cpp index 5666de6624..44f3f34994 100644 --- a/libs/input/KeyCharacterMap.cpp +++ b/libs/input/KeyCharacterMap.cpp @@ -154,7 +154,7 @@ base::Result> KeyCharacterMap::load(const std:: } std::unique_ptr t(tokenizer); auto ret = load(t.get(), format); - if (ret) { + if (ret.ok()) { (*ret)->mLoadFileName = filename; } return ret; @@ -170,7 +170,7 @@ base::Result> KeyCharacterMap::loadContents( } std::unique_ptr t(tokenizer); auto ret = load(t.get(), format); - if (ret) { + if (ret.ok()) { (*ret)->mLoadFileName = filename; } return ret; -- cgit v1.2.3-59-g8ed1b